Duffer Derek
{"version":3,"sources":["../../src/build/validate-app-paths.ts"],"sourcesContent":["import {\n getParamProperties,\n type SegmentParam,\n} from '../shared/lib/router/utils/get-segment-param'\nimport {\n isInterceptionAppRoute,\n parseAppRoute,\n type NormalizedAppRoute,\n type NormalizedAppRouteSegment,\n} from '../shared/lib/router/routes/app'\n\n/**\n * Validates segment parameters for common syntax errors.\n * Based on validation logic from sorted-routes.ts\n */\nfunction validateSegmentParam(param: SegmentParam, pathname: string): void {\n // Check for empty parameter names\n if (param.paramName.length === 0) {\n throw new Error(`Parameter names cannot be empty in route \"${pathname}\".`)\n }\n\n // Check for three-dot character (…) instead of ...\n if (param.paramName.includes('…')) {\n throw new Error(\n `Detected a three-dot character ('…') in parameter \"${param.paramName}\" in route \"${pathname}\". Did you mean ('...')?`\n )\n }\n\n // Check for optional non-catch-all segments (not yet supported)\n if (\n param.paramType !== 'optional-catchall' &&\n param.paramName.startsWith('[') &&\n param.paramName.endsWith(']')\n ) {\n throw new Error(\n `Optional route parameters are not yet supported (\"[${param.paramName}]\") in route \"${pathname}\".`\n )\n }\n\n // Check for extra brackets\n if (param.paramName.startsWith('[') || param.paramName.endsWith(']')) {\n throw new Error(\n `Segment names may not start or end with extra brackets ('${param.paramName}') in route \"${pathname}\".`\n )\n }\n\n // Check for erroneous periods\n if (param.paramName.startsWith('.')) {\n throw new Error(\n `Segment names may not start with erroneous periods ('${param.paramName}') in route \"${pathname}\".`\n )\n }\n}\n\n/**\n * Validates a Route object for internal consistency.\n * Checks for duplicate slugs, invalid catch-all placement, and other route errors.\n * For interception routes, validates both the intercepting and intercepted routes separately.\n * Returns the validated segment parameters.\n */\nfunction validateAppRoute(route: NormalizedAppRoute): void {\n // For interception routes, validate the intercepting and intercepted routes separately\n // This allows the same parameter name to appear in both parts\n if (isInterceptionAppRoute(route)) {\n validateAppRoute(route.interceptingRoute)\n validateAppRoute(route.interceptedRoute)\n return\n }\n\n // Then validate semantic constraints (duplicates, normalization, positioning)\n const slugNames = new Set<string>()\n const normalizedSegments = new Set<string>()\n let hasCatchAll = false\n let hasOptionalCatchAllInPath = false\n let catchAllPosition = -1\n\n for (let i = 0; i < route.segments.length; i++) {\n const segment = route.segments[i]\n\n // Type narrowing - only process dynamic segments\n if (segment.type === 'dynamic') {\n // First, validate syntax\n validateSegmentParam(segment.param, route.pathname)\n\n const properties = getParamProperties(segment.param.paramType)\n\n if (properties.repeat) {\n if (properties.optional) {\n hasOptionalCatchAllInPath = true\n } else {\n hasCatchAll = true\n }\n\n catchAllPosition = i\n }\n\n // Check to see if the parameter name is already in use.\n if (slugNames.has(segment.param.paramName)) {\n throw new Error(\n `You cannot have the same slug name \"${segment.param.paramName}\" repeat within a single dynamic path in route \"${route.pathname}\".`\n )\n }\n\n // Normalize parameter name for comparison by removing all non-word\n // characters.\n const normalizedSegment = segment.param.paramName.replace(/\\W/g, '')\n if (normalizedSegments.has(normalizedSegment)) {\n const existing = Array.from(slugNames).find((s) => {\n return s.replace(/\\W/g, '') === normalizedSegment\n })\n throw new Error(\n `You cannot have the slug names \"${existing}\" and \"${segment.param.paramName}\" differ only by non-word symbols within a single dynamic path in route \"${route.pathname}\".`\n )\n }\n\n slugNames.add(segment.param.paramName)\n normalizedSegments.add(normalizedSegment)\n }\n\n // Check if catch-all is not at the end\n if (hasCatchAll && i > catchAllPosition) {\n throw new Error(\n `Catch-all must be the last part of the URL in route \"${route.pathname}\".`\n )\n }\n if (hasOptionalCatchAllInPath && i > catchAllPosition) {\n throw new Error(\n `Optional catch-all must be the last part of the URL in route \"${route.pathname}\".`\n )\n }\n }\n\n // Check for both required and optional catch-all\n if (hasCatchAll && hasOptionalCatchAllInPath) {\n throw new Error(\n `You cannot use both a required and optional catch-all route at the same level in route \"${route.pathname}\".`\n )\n }\n}\n\n/**\n * Validates a single path for internal consistency and returns its segment parameters.\n */\nfunction parseAndValidateAppPath(path: string): NormalizedAppRoute {\n // Fast parse the route information. We're expecting this to be a normalized\n // route, so we pass `true` to the `parseAppRoute` function.\n const route = parseAppRoute(path, true)\n\n // Slow walk the data from the route in order to validate it.\n validateAppRoute(route)\n\n return route\n}\n\n/**\n * Normalizes segments by replacing dynamic segment names with placeholders.\n * This allows us to compare routes for structural equivalence.\n * Preserves interception markers so that routes with different markers are not considered ambiguous.\n *\n * Examples:\n * - [slug] -> [*]\n * - [modalSlug] -> [*]\n * - [...slug] -> [...*]\n * - [[...slug]] -> [[...*]]\n * - (..)test -> (..)test\n * - (..)[slug] -> (..)[*]\n */\nfunction normalizeSegments(\n segments: readonly NormalizedAppRouteSegment[]\n): string {\n return (\n '/' +\n segments\n .map((segment) => {\n if (segment.type === 'static') {\n return segment.name\n }\n\n // Dynamic segment - normalize the parameter name by replacing the\n // parameter name with a wildcard. The interception marker is already\n // included in the segment name, so no special handling is needed.\n return segment.name.replace(segment.param.paramName, '*')\n })\n .join('/')\n )\n}\n\n/**\n * Validates that app paths don't create ambiguous routes.\n *\n * NOTE: The paths passed to this function should already have been normalized by normalizeAppPath,\n * which means parallel route segments (@modal, @sidebar, etc.) have been removed.\n *\n * This function performs two types of validation:\n * 1. Individual path validation (syntax, slug names, catch-all placement, etc.)\n * 2. Cross-path validation (ambiguous routes, conflicting patterns)\n *\n * @param appPaths - Array of normalized app router paths to validate\n * @returns Array of validated routes\n * @throws Error if validation fails\n */\nexport function validateAppPaths(\n appPaths: readonly string[]\n): NormalizedAppRoute[] {\n // First, validate each path individually\n const paramsByPath = new Map<string, NormalizedAppRoute>()\n for (const path of appPaths) {\n paramsByPath.set(path, parseAndValidateAppPath(path))\n }\n\n // Group paths by their normalized structure for ambiguity detection\n const structureMap = new Map<string, string[]>()\n\n for (const [path, route] of paramsByPath) {\n // Check if the last segment is an optional catch-all and check to see if\n // there is a route with the same specificity that conflicts with it.\n const lastSegment = route.segments[route.segments.length - 1]\n if (\n lastSegment?.type === 'dynamic' &&\n lastSegment.param.paramType === 'optional-catchall'\n ) {\n const prefixSegments = route.segments.slice(0, -1)\n const normalizedPrefix = normalizeSegments(prefixSegments)\n\n for (const [appPath, appRoute] of paramsByPath) {\n const normalizedAppPath = normalizeSegments(appRoute.segments)\n\n // Special case: root-level optional catch-all\n // /[[...slug]] has prefix '' which should match '/'\n if (prefixSegments.length === 0 && appPath === '/') {\n throw new Error(\n `You cannot define a route with the same specificity as an optional catch-all route (\"${appPath}\" and \"/[[...${lastSegment.param.paramName}]]\").`\n )\n }\n\n // General case: compare normalized structures\n if (normalizedAppPath === normalizedPrefix) {\n throw new Error(\n `You cannot define a route with the same specificity as an optional catch-all route (\"${appPath}\" and \"${normalizedPrefix}/[[...${lastSegment.param.paramName}]]\").`\n )\n }\n }\n }\n\n // Normalize the route to get its structure\n const structure = normalizeSegments(route.segments)\n\n // Track which paths map to this structure\n const existingPaths = structureMap.get(structure) ?? []\n existingPaths.push(path)\n structureMap.set(structure, existingPaths)\n }\n\n // Check for ambiguous routes (different slug names, same structure)\n const conflicts: Array<{ paths: string[]; normalizedPath: string }> = []\n\n for (const [structure, paths] of structureMap) {\n if (paths.length > 1) {\n // Multiple paths map to the same structure - this is ambiguous\n conflicts.push({\n paths,\n normalizedPath: structure,\n })\n }\n }\n\n if (conflicts.length > 0) {\n const errorMessages = conflicts.map(({ paths, normalizedPath }) => {\n const pathsList = paths.map((p) => ` - ${p}`).join('\\n')\n return `Ambiguous route pattern \"${normalizedPath}\" matches multiple routes:\\n${pathsList}`\n })\n\n throw new Error(\n `Ambiguous app routes detected:\\n\\n${errorMessages.join('\\n\\n')}\\n\\n` +\n `These routes cannot be distinguished from each other when matching URLs. ` +\n `Please ensure that dynamic segments have unique patterns or use different static segments.`\n )\n }\n\n return Array.from(paramsByPath.values())\n}\n"],"names":["validateAppPaths","validateSegmentParam","param","pathname","paramName","length","Error","includes","paramType","startsWith","endsWith","validateAppRoute","route","isInterceptionAppRoute","interceptingRoute","interceptedRoute","slugNames","Set","normalizedSegments","hasCatchAll","hasOptionalCatchAllInPath","catchAllPosition","i","segments","segment","type","properties","getParamProperties","repeat","optional","has","normalizedSegment","replace","existing","Array","from","find","s","add","parseAndValidateAppPath","path","parseAppRoute","normalizeSegments","map","name","join","appPaths","paramsByPath","Map","set","structureMap","lastSegment","prefixSegments","slice","normalizedPrefix","appPath","appRoute","normalizedAppPath","structure","existingPaths","get","push","conflicts","paths","normalizedPath","errorMessages","pathsList","p","values"],"mappings":";;;;+BAyMgBA;;;eAAAA;;;iCAtMT;qBAMA;AAEP;;;CAGC,GACD,SAASC,qBAAqBC,KAAmB,EAAEC,QAAgB;IACjE,kCAAkC;IAClC,IAAID,MAAME,SAAS,CAACC,MAAM,KAAK,GAAG;QAChC,MAAM,qBAAoE,CAApE,IAAIC,MAAM,CAAC,0CAA0C,EAAEH,SAAS,EAAE,CAAC,GAAnE,qBAAA;mBAAA;wBAAA;0BAAA;QAAmE;IAC3E;IAEA,mDAAmD;IACnD,IAAID,MAAME,SAAS,CAACG,QAAQ,CAAC,MAAM;QACjC,MAAM,qBAEL,CAFK,IAAID,MACR,CAAC,mDAAmD,EAAEJ,MAAME,SAAS,CAAC,YAAY,EAAED,SAAS,wBAAwB,CAAC,GADlH,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;IAEA,gEAAgE;IAChE,IACED,MAAMM,SAAS,KAAK,uBACpBN,MAAME,SAAS,CAACK,UAAU,CAAC,QAC3BP,MAAME,SAAS,CAACM,QAAQ,CAAC,MACzB;QACA,MAAM,qBAEL,CAFK,IAAIJ,MACR,CAAC,mDAAmD,EAAEJ,MAAME,SAAS,CAAC,cAAc,EAAED,SAAS,EAAE,CAAC,GAD9F,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;IAEA,2BAA2B;IAC3B,IAAID,MAAME,SAAS,CAACK,UAAU,CAAC,QAAQP,MAAME,SAAS,CAACM,QAAQ,CAAC,MAAM;QACpE,MAAM,qBAEL,CAFK,IAAIJ,MACR,CAAC,yDAAyD,EAAEJ,MAAME,SAAS,CAAC,aAAa,EAAED,SAAS,EAAE,CAAC,GADnG,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;IAEA,8BAA8B;IAC9B,IAAID,MAAME,SAAS,CAACK,UAAU,CAAC,MAAM;QACnC,MAAM,qBAEL,CAFK,IAAIH,MACR,CAAC,qDAAqD,EAAEJ,MAAME,SAAS,CAAC,aAAa,EAAED,SAAS,EAAE,CAAC,GAD/F,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;AACF;AAEA;;;;;CAKC,GACD,SAASQ,iBAAiBC,KAAyB;IACjD,uFAAuF;IACvF,8DAA8D;IAC9D,IAAIC,IAAAA,2BAAsB,EAACD,QAAQ;QACjCD,iBAAiBC,MAAME,iBAAiB;QACxCH,iBAAiBC,MAAMG,gBAAgB;QACvC;IACF;IAEA,8EAA8E;IAC9E,MAAMC,YAAY,IAAIC;IACtB,MAAMC,qBAAqB,IAAID;IAC/B,IAAIE,cAAc;IAClB,IAAIC,4BAA4B;IAChC,IAAIC,mBAAmB,CAAC;IAExB,IAAK,IAAIC,IAAI,GAAGA,IAAIV,MAAMW,QAAQ,CAAClB,MAAM,EAAEiB,IAAK;QAC9C,MAAME,UAAUZ,MAAMW,QAAQ,CAACD,EAAE;QAEjC,iDAAiD;QACjD,IAAIE,QAAQC,IAAI,KAAK,WAAW;YAC9B,yBAAyB;YACzBxB,qBAAqBuB,QAAQtB,KAAK,EAAEU,MAAMT,QAAQ;YAElD,MAAMuB,aAAaC,IAAAA,mCAAkB,EAACH,QAAQtB,KAAK,CAACM,SAAS;YAE7D,IAAIkB,WAAWE,MAAM,EAAE;gBACrB,IAAIF,WAAWG,QAAQ,EAAE;oBACvBT,4BAA4B;gBAC9B,OAAO;oBACLD,cAAc;gBAChB;gBAEAE,mBAAmBC;YACrB;YAEA,wDAAwD;YACxD,IAAIN,UAAUc,GAAG,CAACN,QAAQtB,KAAK,CAACE,SAAS,GAAG;gBAC1C,MAAM,qBAEL,CAFK,IAAIE,MACR,CAAC,oCAAoC,EAAEkB,QAAQtB,KAAK,CAACE,SAAS,CAAC,gDAAgD,EAAEQ,MAAMT,QAAQ,CAAC,EAAE,CAAC,GAD/H,qBAAA;2BAAA;gCAAA;kCAAA;gBAEN;YACF;YAEA,mEAAmE;YACnE,cAAc;YACd,MAAM4B,oBAAoBP,QAAQtB,KAAK,CAACE,SAAS,CAAC4B,OAAO,CAAC,OAAO;YACjE,IAAId,mBAAmBY,GAAG,CAACC,oBAAoB;gBAC7C,MAAME,WAAWC,MAAMC,IAAI,CAACnB,WAAWoB,IAAI,CAAC,CAACC;oBAC3C,OAAOA,EAAEL,OAAO,CAAC,OAAO,QAAQD;gBAClC;gBACA,MAAM,qBAEL,CAFK,IAAIzB,MACR,CAAC,gCAAgC,EAAE2B,SAAS,OAAO,EAAET,QAAQtB,KAAK,CAACE,SAAS,CAAC,yEAAyE,EAAEQ,MAAMT,QAAQ,CAAC,EAAE,CAAC,GADtK,qBAAA;2BAAA;gCAAA;kCAAA;gBAEN;YACF;YAEAa,UAAUsB,GAAG,CAACd,QAAQtB,KAAK,CAACE,SAAS;YACrCc,mBAAmBoB,GAAG,CAACP;QACzB;QAEA,uCAAuC;QACvC,IAAIZ,eAAeG,IAAID,kBAAkB;YACvC,MAAM,qBAEL,CAFK,IAAIf,MACR,CAAC,qDAAqD,EAAEM,MAAMT,QAAQ,CAAC,EAAE,CAAC,GADtE,qBAAA;uBAAA;4BAAA;8BAAA;YAEN;QACF;QACA,IAAIiB,6BAA6BE,IAAID,kBAAkB;YACrD,MAAM,qBAEL,CAFK,IAAIf,MACR,CAAC,8DAA8D,EAAEM,MAAMT,QAAQ,CAAC,EAAE,CAAC,GAD/E,qBAAA;uBAAA;4BAAA;8BAAA;YAEN;QACF;IACF;IAEA,iDAAiD;IACjD,IAAIgB,eAAeC,2BAA2B;QAC5C,MAAM,qBAEL,CAFK,IAAId,MACR,CAAC,wFAAwF,EAAEM,MAAMT,QAAQ,CAAC,EAAE,CAAC,GADzG,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;AACF;AAEA;;CAEC,GACD,SAASoC,wBAAwBC,IAAY;IAC3C,4EAA4E;IAC5E,4DAA4D;IAC5D,MAAM5B,QAAQ6B,IAAAA,kBAAa,EAACD,MAAM;IAElC,6DAA6D;IAC7D7B,iBAAiBC;IAEjB,OAAOA;AACT;AAEA;;;;;;;;;;;;CAYC,GACD,SAAS8B,kBACPnB,QAA8C;IAE9C,OACE,MACAA,SACGoB,GAAG,CAAC,CAACnB;QACJ,IAAIA,QAAQC,IAAI,KAAK,UAAU;YAC7B,OAAOD,QAAQoB,IAAI;QACrB;QAEA,kEAAkE;QAClE,qEAAqE;QACrE,kEAAkE;QAClE,OAAOpB,QAAQoB,IAAI,CAACZ,OAAO,CAACR,QAAQtB,KAAK,CAACE,SAAS,EAAE;IACvD,GACCyC,IAAI,CAAC;AAEZ;AAgBO,SAAS7C,iBACd8C,QAA2B;IAE3B,yCAAyC;IACzC,MAAMC,eAAe,IAAIC;IACzB,KAAK,MAAMR,QAAQM,SAAU;QAC3BC,aAAaE,GAAG,CAACT,MAAMD,wBAAwBC;IACjD;IAEA,oEAAoE;IACpE,MAAMU,eAAe,IAAIF;IAEzB,KAAK,MAAM,CAACR,MAAM5B,MAAM,IAAImC,aAAc;QACxC,yEAAyE;QACzE,qEAAqE;QACrE,MAAMI,cAAcvC,MAAMW,QAAQ,CAACX,MAAMW,QAAQ,CAAClB,MAAM,GAAG,EAAE;QAC7D,IACE8C,CAAAA,+BAAAA,YAAa1B,IAAI,MAAK,aACtB0B,YAAYjD,KAAK,CAACM,SAAS,KAAK,qBAChC;YACA,MAAM4C,iBAAiBxC,MAAMW,QAAQ,CAAC8B,KAAK,CAAC,GAAG,CAAC;YAChD,MAAMC,mBAAmBZ,kBAAkBU;YAE3C,KAAK,MAAM,CAACG,SAASC,SAAS,IAAIT,aAAc;gBAC9C,MAAMU,oBAAoBf,kBAAkBc,SAASjC,QAAQ;gBAE7D,8CAA8C;gBAC9C,oDAAoD;gBACpD,IAAI6B,eAAe/C,MAAM,KAAK,KAAKkD,YAAY,KAAK;oBAClD,MAAM,qBAEL,CAFK,IAAIjD,MACR,CAAC,qFAAqF,EAAEiD,QAAQ,aAAa,EAAEJ,YAAYjD,KAAK,CAACE,SAAS,CAAC,KAAK,CAAC,GAD7I,qBAAA;+BAAA;oCAAA;sCAAA;oBAEN;gBACF;gBAEA,8CAA8C;gBAC9C,IAAIqD,sBAAsBH,kBAAkB;oBAC1C,MAAM,qBAEL,CAFK,IAAIhD,MACR,CAAC,qFAAqF,EAAEiD,QAAQ,OAAO,EAAED,iBAAiB,MAAM,EAAEH,YAAYjD,KAAK,CAACE,SAAS,CAAC,KAAK,CAAC,GADhK,qBAAA;+BAAA;oCAAA;sCAAA;oBAEN;gBACF;YACF;QACF;QAEA,2CAA2C;QAC3C,MAAMsD,YAAYhB,kBAAkB9B,MAAMW,QAAQ;QAElD,0CAA0C;QAC1C,MAAMoC,gBAAgBT,aAAaU,GAAG,CAACF,cAAc,EAAE;QACvDC,cAAcE,IAAI,CAACrB;QACnBU,aAAaD,GAAG,CAACS,WAAWC;IAC9B;IAEA,oEAAoE;IACpE,MAAMG,YAAgE,EAAE;IAExE,KAAK,MAAM,CAACJ,WAAWK,MAAM,IAAIb,aAAc;QAC7C,IAAIa,MAAM1D,MAAM,GAAG,GAAG;YACpB,+DAA+D;YAC/DyD,UAAUD,IAAI,CAAC;gBACbE;gBACAC,gBAAgBN;YAClB;QACF;IACF;IAEA,IAAII,UAAUzD,MAAM,GAAG,GAAG;QACxB,MAAM4D,gBAAgBH,UAAUnB,GAAG,CAAC,CAAC,EAAEoB,KAAK,EAAEC,cAAc,EAAE;YAC5D,MAAME,YAAYH,MAAMpB,GAAG,CAAC,CAACwB,IAAM,CAAC,IAAI,EAAEA,GAAG,EAAEtB,IAAI,CAAC;YACpD,OAAO,CAAC,yBAAyB,EAAEmB,eAAe,4BAA4B,EAAEE,WAAW;QAC7F;QAEA,MAAM,qBAIL,CAJK,IAAI5D,MACR,CAAC,kCAAkC,EAAE2D,cAAcpB,IAAI,CAAC,QAAQ,IAAI,CAAC,GACnE,CAAC,yEAAyE,CAAC,GAC3E,CAAC,0FAA0F,CAAC,GAH1F,qBAAA;mBAAA;wBAAA;0BAAA;QAIN;IACF;IAEA,OAAOX,MAAMC,IAAI,CAACY,aAAaqB,MAAM;AACvC","ignoreList":[0]}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists