Files
klz-cables.com/.pnpm-store/v10/files/73/d34017cfc41ae10355e5243a111d409e2fca014cca3787eab8ab7a02cc1170538a86efba08ff96de3f6c01192e2974b3c9668c2742ed9d471030097c7d85b8
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

1 line
11 KiB
Plaintext

{"version":3,"file":"parameterization.js","sources":["../../../../src/client/routing/parameterization.ts"],"sourcesContent":["import { debug, GLOBAL_OBJ } from '@sentry/core';\nimport { DEBUG_BUILD } from '../../common/debug-build';\nimport type { RouteManifest } from '../../config/manifest/types';\n\nconst globalWithInjectedManifest = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n _sentryRouteManifest: RouteManifest | undefined;\n};\n\n// Some performance caches\nlet cachedManifest: RouteManifest | null = null;\nlet cachedManifestString: string | undefined = undefined;\nconst compiledRegexCache: Map<string, RegExp> = new Map();\nconst routeResultCache: Map<string, string | undefined> = new Map();\n\n/**\n * Calculate the specificity score for a route path.\n * Lower scores indicate more specific routes.\n */\nfunction getRouteSpecificity(routePath: string): number {\n const segments = routePath.split('/').filter(Boolean);\n let score = 0;\n\n for (const segment of segments) {\n if (segment.startsWith(':')) {\n const paramName = segment.substring(1);\n if (paramName.endsWith('*?')) {\n // Optional catch-all: [[...param]]\n score += 1000;\n } else if (paramName.endsWith('*')) {\n // Required catch-all: [...param]\n score += 100;\n } else {\n // Regular dynamic segment: [param]\n score += 10;\n }\n }\n // Static segments add 0 to score as they are most specific\n }\n\n if (segments.length > 0) {\n // Add a small penalty based on inverse of segment count\n // This ensures that routes with more segments are preferred\n // e.g., '/:locale/foo' is more specific than '/:locale'\n // We use a small value (1 / segments.length) so it doesn't override the main scoring\n // but breaks ties between routes with the same number of dynamic segments\n const segmentCountPenalty = 1 / segments.length;\n score += segmentCountPenalty;\n }\n\n return score;\n}\n\n/**\n * Get compiled regex from cache or create and cache it.\n */\nfunction getCompiledRegex(regexString: string): RegExp | null {\n if (compiledRegexCache.has(regexString)) {\n return compiledRegexCache.get(regexString) ?? null;\n }\n\n try {\n // eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor -- regex patterns are from build-time route manifest, not user input\n const regex = new RegExp(regexString);\n compiledRegexCache.set(regexString, regex);\n return regex;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Could not compile regex', { regexString, error });\n // Cache the failure to avoid repeated attempts by storing undefined\n return null;\n }\n}\n\n/**\n * Get and cache the route manifest from the global object.\n * @returns The parsed route manifest or null if not available/invalid.\n */\nexport function getManifest(): RouteManifest | null {\n if (\n !globalWithInjectedManifest?._sentryRouteManifest ||\n typeof globalWithInjectedManifest._sentryRouteManifest !== 'string'\n ) {\n return null;\n }\n\n const currentManifestString = globalWithInjectedManifest._sentryRouteManifest;\n\n // Return cached manifest if the string hasn't changed\n if (cachedManifest && cachedManifestString === currentManifestString) {\n return cachedManifest;\n }\n\n // Clear caches when manifest changes\n compiledRegexCache.clear();\n routeResultCache.clear();\n\n let manifest: RouteManifest = {\n staticRoutes: [],\n dynamicRoutes: [],\n isrRoutes: [],\n };\n\n // Shallow check if the manifest is actually what we expect it to be\n try {\n manifest = JSON.parse(currentManifestString);\n if (!Array.isArray(manifest.staticRoutes) || !Array.isArray(manifest.dynamicRoutes)) {\n return null;\n }\n // Cache the successfully parsed manifest\n cachedManifest = manifest;\n cachedManifestString = currentManifestString;\n return manifest;\n } catch {\n // Something went wrong while parsing the manifest, so we'll fallback to no parameterization\n DEBUG_BUILD && debug.warn('Could not extract route manifest');\n return null;\n }\n}\n\n/**\n * Find matching routes from static and dynamic route collections.\n * @param route - The route to match against.\n * @param staticRoutes - Array of static route objects.\n * @param dynamicRoutes - Array of dynamic route objects.\n * @returns Array of matching route paths.\n */\nfunction findMatchingRoutes(\n route: string,\n staticRoutes: RouteManifest['staticRoutes'],\n dynamicRoutes: RouteManifest['dynamicRoutes'],\n): string[] {\n const matches: string[] = [];\n\n // Static path: no parameterization needed, return empty array\n if (staticRoutes.some(r => r.path === route)) {\n return matches;\n }\n\n // Dynamic path: find the route pattern that matches the concrete route\n for (const dynamicRoute of dynamicRoutes) {\n if (dynamicRoute.regex) {\n const regex = getCompiledRegex(dynamicRoute.regex);\n if (regex?.test(route)) {\n matches.push(dynamicRoute.path);\n }\n }\n }\n\n // Try matching with optional prefix segments (for i18n routing patterns)\n // This handles cases like '/foo' matching '/:locale/foo' when using next-intl with localePrefix: \"as-needed\"\n // We do this regardless of whether we found direct matches, as we want the most specific match\n if (!route.startsWith('/:')) {\n for (const dynamicRoute of dynamicRoutes) {\n if (dynamicRoute.hasOptionalPrefix && dynamicRoute.regex) {\n // Prepend a placeholder segment to simulate the optional prefix\n // e.g., '/foo' becomes '/PLACEHOLDER/foo' to match '/:locale/foo'\n // Special case: '/' becomes '/PLACEHOLDER' (not '/PLACEHOLDER/') to match '/:locale' pattern\n const routeWithPrefix = route === '/' ? '/SENTRY_OPTIONAL_PREFIX' : `/SENTRY_OPTIONAL_PREFIX${route}`;\n const regex = getCompiledRegex(dynamicRoute.regex);\n if (regex?.test(routeWithPrefix)) {\n matches.push(dynamicRoute.path);\n }\n }\n }\n }\n\n return matches;\n}\n\n/**\n * Parameterize a route using the route manifest.\n *\n * @param route - The route to parameterize.\n * @returns The parameterized route or undefined if no parameterization is needed.\n */\nexport const maybeParameterizeRoute = (route: string): string | undefined => {\n const manifest = getManifest();\n if (!manifest) {\n return undefined;\n }\n\n // Check route result cache after manifest validation\n if (routeResultCache.has(route)) {\n return routeResultCache.get(route);\n }\n\n const { staticRoutes, dynamicRoutes } = manifest;\n if (!Array.isArray(staticRoutes) || !Array.isArray(dynamicRoutes)) {\n return undefined;\n }\n\n const matches = findMatchingRoutes(route, staticRoutes, dynamicRoutes);\n\n // We can always do the `sort()` call, it will short-circuit when it has one array item\n const result = matches.sort((a, b) => getRouteSpecificity(a) - getRouteSpecificity(b))[0];\n\n routeResultCache.set(route, result);\n\n return result;\n};\n"],"names":["GLOBAL_OBJ","DEBUG_BUILD","debug"],"mappings":"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"}