@tanstack/router-generator 1.120.4 → 1.121.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cjs/config.cjs +14 -14
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +68 -31
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +1 -5
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +2 -2
  7. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
  8. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +2 -2
  9. package/dist/cjs/generator.cjs +160 -172
  10. package/dist/cjs/generator.cjs.map +1 -1
  11. package/dist/cjs/generator.d.cts +0 -59
  12. package/dist/cjs/index.cjs +23 -2
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/cjs/index.d.cts +8 -4
  15. package/dist/cjs/template.cjs +4 -12
  16. package/dist/cjs/template.cjs.map +1 -1
  17. package/dist/cjs/template.d.cts +0 -1
  18. package/dist/cjs/types.d.cts +1 -1
  19. package/dist/cjs/utils.cjs +64 -5
  20. package/dist/cjs/utils.cjs.map +1 -1
  21. package/dist/cjs/utils.d.cts +11 -2
  22. package/dist/esm/config.d.ts +68 -31
  23. package/dist/esm/config.js +14 -14
  24. package/dist/esm/config.js.map +1 -1
  25. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +2 -2
  26. package/dist/esm/filesystem/physical/getRouteNodes.js +2 -6
  27. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
  28. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +2 -2
  29. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
  30. package/dist/esm/generator.d.ts +0 -59
  31. package/dist/esm/generator.js +163 -175
  32. package/dist/esm/generator.js.map +1 -1
  33. package/dist/esm/index.d.ts +8 -4
  34. package/dist/esm/index.js +25 -4
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/esm/template.d.ts +0 -1
  37. package/dist/esm/template.js +4 -12
  38. package/dist/esm/template.js.map +1 -1
  39. package/dist/esm/types.d.ts +1 -1
  40. package/dist/esm/utils.d.ts +11 -2
  41. package/dist/esm/utils.js +63 -4
  42. package/dist/esm/utils.js.map +1 -1
  43. package/package.json +3 -3
  44. package/src/config.ts +14 -11
  45. package/src/filesystem/physical/getRouteNodes.ts +13 -14
  46. package/src/filesystem/virtual/getRouteNodes.ts +18 -3
  47. package/src/generator.ts +242 -221
  48. package/src/index.ts +32 -7
  49. package/src/template.ts +4 -15
  50. package/src/types.ts +0 -1
  51. package/src/utils.ts +102 -6
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as fs from 'node:fs'\nimport * as prettier from 'prettier'\nimport type { Config } from './config'\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function logging(config: { disabled: boolean }) {\n function stripEmojis(str: string) {\n return str.replace(\n /[\\p{Emoji_Presentation}\\p{Extended_Pictographic}]/gu,\n '',\n )\n }\n\n function formatLogArgs(args: Array<any>): Array<any> {\n if (process.env.CI) {\n return args.map((arg) =>\n typeof arg === 'string' ? stripEmojis(arg) : arg,\n )\n }\n return args\n }\n\n return {\n log: (...args: Array<any>) => {\n if (!config.disabled) console.log(...formatLogArgs(args))\n },\n debug: (...args: Array<any>) => {\n if (!config.disabled) console.debug(...formatLogArgs(args))\n },\n info: (...args: Array<any>) => {\n if (!config.disabled) console.info(...formatLogArgs(args))\n },\n warn: (...args: Array<any>) => {\n if (!config.disabled) console.warn(...formatLogArgs(args))\n },\n error: (...args: Array<any>) => {\n if (!config.disabled) console.error(...formatLogArgs(args))\n },\n }\n}\n\nexport function removeLeadingSlash(path: string): string {\n return path.replace(/^\\//, '')\n}\n\nexport function removeTrailingSlash(s: string) {\n return s.replace(/\\/$/, '')\n}\n\nexport function determineInitialRoutePath(routePath: string) {\n return cleanPath(`/${routePath.split('.').join('/')}`) || ''\n}\n\nexport function replaceBackslash(s: string) {\n return s.replaceAll(/\\\\/gi, '/')\n}\n\nexport function routePathToVariable(routePath: string): string {\n return (\n removeUnderscores(routePath)\n ?.replace(/\\/\\$\\//g, '/splat/')\n .replace(/\\$$/g, 'splat')\n .replace(/\\$/g, '')\n .split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .replace(/([^a-zA-Z0-9]|[.])/gm, '')\n .replace(/^(\\d)/g, 'R$1') ?? ''\n )\n}\n\nexport function removeUnderscores(s?: string) {\n return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\\/_|_\\/)/gi, '/')\n}\n\nexport function capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nexport function removeExt(d: string, keepExtension: boolean = false) {\n return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d\n}\n\n/**\n * This function writes to a file if the content is different.\n *\n * @param filepath The path to the file\n * @param content Original content\n * @param incomingContent New content\n * @param callbacks Callbacks to run before and after writing\n * @returns Whether the file was written\n */\nexport async function writeIfDifferent(\n filepath: string,\n content: string,\n incomingContent: string,\n callbacks?: { beforeWrite?: () => void; afterWrite?: () => void },\n): Promise<boolean> {\n if (content !== incomingContent) {\n callbacks?.beforeWrite?.()\n fs.writeFileSync(filepath, incomingContent)\n callbacks?.afterWrite?.()\n return true\n }\n return false\n}\n\n/**\n * This function formats the source code using the default formatter (Prettier).\n *\n * @param source The content to format\n * @param config The configuration object\n * @returns The formatted content\n */\nexport async function format(source: string, config: Config): Promise<string> {\n const prettierOptions: prettier.Config = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n return prettier.format(source, prettierOptions)\n}\n\n/**\n * This function resets the regex index to 0 so that it can be reused\n * without having to create a new regex object or worry about the last\n * state when using the global flag.\n *\n * @param regex The regex object to reset\n * @returns\n */\nexport function resetRegex(regex: RegExp) {\n regex.lastIndex = 0\n return\n}\n"],"names":["fs","prettier"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAIO,SAAS,YACd,KACA,YAAqC,CAAC,CAAC,MAAM,CAAC,GACpC;AACV,SAAO,IACJ,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAU,EAC7B,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM;AAC1B,eAAW,YAAY,WAAW;AAC1B,YAAA,KAAK,SAAS,CAAC;AACf,YAAA,KAAK,SAAS,CAAC;AAEjB,UAAA,OAAO,OAAO,aAAa;AACzB,YAAA,OAAO,OAAO,aAAa;AAC7B;AAAA,QAAA;AAEK,eAAA;AAAA,MAAA;AAGT,UAAI,OAAO,IAAI;AACb;AAAA,MAAA;AAGK,aAAA,KAAK,KAAK,IAAI;AAAA,IAAA;AAGvB,WAAO,KAAK;AAAA,EACb,CAAA,EACA,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACnB;AAEO,SAAS,UAAU,MAAc;AAE/B,SAAA,KAAK,QAAQ,WAAW,GAAG;AACpC;AAEO,SAAS,aAAa,MAAc;AACzC,SAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AAEO,SAAS,QAAQ,QAA+B;AACrD,WAAS,YAAY,KAAa;AAChC,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAGF,WAAS,cAAc,MAA8B;AAC/C,QAAA,QAAQ,IAAI,IAAI;AAClB,aAAO,KAAK;AAAA,QAAI,CAAC,QACf,OAAO,QAAQ,WAAW,YAAY,GAAG,IAAI;AAAA,MAC/C;AAAA,IAAA;AAEK,WAAA;AAAA,EAAA;AAGF,SAAA;AAAA,IACL,KAAK,IAAI,SAAqB;AACxB,UAAA,CAAC,OAAO,SAAU,SAAQ,IAAI,GAAG,cAAc,IAAI,CAAC;AAAA,IAC1D;AAAA,IACA,OAAO,IAAI,SAAqB;AAC1B,UAAA,CAAC,OAAO,SAAU,SAAQ,MAAM,GAAG,cAAc,IAAI,CAAC;AAAA,IAC5D;AAAA,IACA,MAAM,IAAI,SAAqB;AACzB,UAAA,CAAC,OAAO,SAAU,SAAQ,KAAK,GAAG,cAAc,IAAI,CAAC;AAAA,IAC3D;AAAA,IACA,MAAM,IAAI,SAAqB;AACzB,UAAA,CAAC,OAAO,SAAU,SAAQ,KAAK,GAAG,cAAc,IAAI,CAAC;AAAA,IAC3D;AAAA,IACA,OAAO,IAAI,SAAqB;AAC1B,UAAA,CAAC,OAAO,SAAU,SAAQ,MAAM,GAAG,cAAc,IAAI,CAAC;AAAA,IAAA;AAAA,EAE9D;AACF;AAEO,SAAS,mBAAmB,MAAsB;AAChD,SAAA,KAAK,QAAQ,OAAO,EAAE;AAC/B;AAEO,SAAS,oBAAoB,GAAW;AACtC,SAAA,EAAE,QAAQ,OAAO,EAAE;AAC5B;AAEO,SAAS,0BAA0B,WAAmB;AACpD,SAAA,UAAU,IAAI,UAAU,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK;AAC5D;AAEO,SAAS,iBAAiB,GAAW;AACnC,SAAA,EAAE,WAAW,QAAQ,GAAG;AACjC;AAEO,SAAS,oBAAoB,WAA2B;;AAC7D,WACE,uBAAkB,SAAS,MAA3B,mBACI,QAAQ,WAAW,WACpB,QAAQ,QAAQ,SAChB,QAAQ,OAAO,IACf,MAAM,SACN,IAAI,CAAC,GAAG,MAAO,IAAI,IAAI,WAAW,CAAC,IAAI,GACvC,KAAK,IACL,QAAQ,wBAAwB,IAChC,QAAQ,UAAU,WAAU;AAEnC;AAEO,SAAS,kBAAkB,GAAY;AAC5C,SAAO,uBAAG,WAAW,aAAa,IAAI,WAAW,eAAe;AAClE;AAEO,SAAS,WAAW,GAAW;AAChC,MAAA,OAAO,MAAM,SAAiB,QAAA;AAC3B,SAAA,EAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC;AAC9C;AAEgB,SAAA,UAAU,GAAW,gBAAyB,OAAO;AAC5D,SAAA,gBAAgB,IAAI,EAAE,UAAU,GAAG,EAAE,YAAY,GAAG,CAAC,KAAK;AACnE;AAWA,eAAsB,iBACpB,UACA,SACA,iBACA,WACkB;;AAClB,MAAI,YAAY,iBAAiB;AAC/B,iDAAW,gBAAX;AACGA,kBAAA,cAAc,UAAU,eAAe;AAC1C,iDAAW,eAAX;AACO,WAAA;AAAA,EAAA;AAEF,SAAA;AACT;AASsB,eAAA,OAAO,QAAgB,QAAiC;AAC5E,QAAM,kBAAmC;AAAA,IACvC,MAAM,OAAO;AAAA,IACb,aAAa,OAAO,eAAe;AAAA,IACnC,QAAQ;AAAA,EACV;AACO,SAAAC,oBAAS,OAAO,QAAQ,eAAe;AAChD;AAUO,SAAS,WAAW,OAAe;AACxC,QAAM,YAAY;AAClB;AACF;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as fsp from 'node:fs/promises'\nimport * as prettier from 'prettier'\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function logging(config: { disabled: boolean }) {\n function stripEmojis(str: string) {\n return str.replace(\n /[\\p{Emoji_Presentation}\\p{Extended_Pictographic}]/gu,\n '',\n )\n }\n\n function formatLogArgs(args: Array<any>): Array<any> {\n if (process.env.CI) {\n return args.map((arg) =>\n typeof arg === 'string' ? stripEmojis(arg) : arg,\n )\n }\n return args\n }\n\n return {\n log: (...args: Array<any>) => {\n if (!config.disabled) console.log(...formatLogArgs(args))\n },\n debug: (...args: Array<any>) => {\n if (!config.disabled) console.debug(...formatLogArgs(args))\n },\n info: (...args: Array<any>) => {\n if (!config.disabled) console.info(...formatLogArgs(args))\n },\n warn: (...args: Array<any>) => {\n if (!config.disabled) console.warn(...formatLogArgs(args))\n },\n error: (...args: Array<any>) => {\n if (!config.disabled) console.error(...formatLogArgs(args))\n },\n }\n}\n\nexport function removeLeadingSlash(path: string): string {\n return path.replace(/^\\//, '')\n}\n\nexport function removeTrailingSlash(s: string) {\n return s.replace(/\\/$/, '')\n}\n\nexport function determineInitialRoutePath(routePath: string) {\n const DISALLOWED_ESCAPE_CHARS = new Set([\n '/',\n '\\\\',\n '?',\n '#',\n ':',\n '*',\n '<',\n '>',\n '|',\n '!',\n '$',\n '%',\n ])\n\n const parts = routePath.split(/(?<!\\[)\\.(?!\\])/g)\n\n // Escape any characters that in square brackets\n const escapedParts = parts.map((part) => {\n // Check if any disallowed characters are used in brackets\n const BRACKET_CONTENT_RE = /\\[(.*?)\\]/g\n\n let match\n while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {\n const character = match[1]\n if (character === undefined) continue\n if (DISALLOWED_ESCAPE_CHARS.has(character)) {\n console.error(\n `Error: Disallowed character \"${character}\" found in square brackets in route path \"${routePath}\".\\nYou cannot use any of the following characters in square brackets: ${Array.from(\n DISALLOWED_ESCAPE_CHARS,\n ).join(', ')}\\nPlease remove and/or replace them.`,\n )\n process.exit(1)\n }\n }\n\n // Since this split segment is safe at this point, we can\n // remove the brackets and replace them with the content inside\n return part.replace(/\\[(.)\\]/g, '$1')\n })\n\n // If the syntax for prefix/suffix is different, from the path\n // matching internals of router-core, we'd perform those changes here\n // on the `escapedParts` array before it is joined back together in\n // `final`\n\n const final = cleanPath(`/${escapedParts.join('/')}`) || ''\n\n return final\n}\n\nexport function replaceBackslash(s: string) {\n return s.replaceAll(/\\\\/gi, '/')\n}\n\nexport function routePathToVariable(routePath: string): string {\n const toVariableSafeChar = (char: string): string => {\n if (/[a-zA-Z0-9_]/.test(char)) {\n return char // Keep alphanumeric characters and underscores as is\n }\n\n // Replace special characters with meaningful text equivalents\n switch (char) {\n case '.':\n return 'Dot'\n case '-':\n return 'Dash'\n case '@':\n return 'At'\n case '(':\n return '' // Removed since route groups use parentheses\n case ')':\n return '' // Removed since route groups use parentheses\n case ' ':\n return '' // Remove spaces\n default:\n return `Char${char.charCodeAt(0)}` // For any other characters\n }\n }\n\n return (\n removeUnderscores(routePath)\n ?.replace(/\\/\\$\\//g, '/splat/')\n .replace(/\\$$/g, 'splat')\n .replace(/\\$\\{\\$\\}/g, 'splat')\n .replace(/\\$/g, '')\n .split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .split('')\n .map(toVariableSafeChar)\n .join('')\n // .replace(/([^a-zA-Z0-9]|[.])/gm, '')\n .replace(/^(\\d)/g, 'R$1') ?? ''\n )\n}\n\nexport function removeUnderscores(s?: string) {\n return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\\/_|_\\/)/gi, '/')\n}\n\nexport function capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nexport function removeExt(d: string, keepExtension: boolean = false) {\n return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d\n}\n\n/**\n * This function writes to a file if the content is different.\n *\n * @param filepath The path to the file\n * @param content Original content\n * @param incomingContent New content\n * @param callbacks Callbacks to run before and after writing\n * @returns Whether the file was written\n */\nexport async function writeIfDifferent(\n filepath: string,\n content: string,\n incomingContent: string,\n callbacks?: { beforeWrite?: () => void; afterWrite?: () => void },\n): Promise<boolean> {\n if (content !== incomingContent) {\n callbacks?.beforeWrite?.()\n await fsp.writeFile(filepath, incomingContent)\n callbacks?.afterWrite?.()\n return true\n }\n return false\n}\n\n/**\n * This function formats the source code using the default formatter (Prettier).\n *\n * @param source The content to format\n * @param config The configuration object\n * @returns The formatted content\n */\nexport async function format(\n source: string,\n config: {\n quoteStyle: 'single' | 'double'\n semicolons: boolean\n },\n): Promise<string> {\n const prettierOptions: prettier.Config = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n return prettier.format(source, prettierOptions)\n}\n\n/**\n * This function resets the regex index to 0 so that it can be reused\n * without having to create a new regex object or worry about the last\n * state when using the global flag.\n *\n * @param regex The regex object to reset\n * @returns\n */\nexport function resetRegex(regex: RegExp) {\n regex.lastIndex = 0\n return\n}\n\n/**\n * This function checks if a file exists.\n *\n * @param file The path to the file\n * @returns Whether the file exists\n */\nexport async function checkFileExists(file: string) {\n try {\n await fsp.access(file, fsp.constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n"],"names":["fsp","prettier"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { Config } from './config.cjs';
2
1
  export declare function multiSortBy<T>(arr: Array<T>, accessors?: Array<(item: T) => any>): Array<T>;
3
2
  export declare function cleanPath(path: string): string;
4
3
  export declare function trimPathLeft(path: string): string;
@@ -39,7 +38,10 @@ export declare function writeIfDifferent(filepath: string, content: string, inco
39
38
  * @param config The configuration object
40
39
  * @returns The formatted content
41
40
  */
42
- export declare function format(source: string, config: Config): Promise<string>;
41
+ export declare function format(source: string, config: {
42
+ quoteStyle: 'single' | 'double';
43
+ semicolons: boolean;
44
+ }): Promise<string>;
43
45
  /**
44
46
  * This function resets the regex index to 0 so that it can be reused
45
47
  * without having to create a new regex object or worry about the last
@@ -49,3 +51,10 @@ export declare function format(source: string, config: Config): Promise<string>;
49
51
  * @returns
50
52
  */
51
53
  export declare function resetRegex(regex: RegExp): void;
54
+ /**
55
+ * This function checks if a file exists.
56
+ *
57
+ * @param file The path to the file
58
+ * @returns Whether the file exists
59
+ */
60
+ export declare function checkFileExists(file: string): Promise<boolean>;
@@ -1,39 +1,80 @@
1
1
  import { z } from 'zod';
2
- export declare const configSchema: z.ZodObject<{
2
+ export declare const baseConfigSchema: z.ZodObject<{
3
+ target: z.ZodDefault<z.ZodOptional<z.ZodEnum<["react", "solid"]>>>;
4
+ virtualRouteConfig: z.ZodOptional<z.ZodUnion<[z.ZodType<import('@tanstack/virtual-file-routes').VirtualRootRoute, z.ZodTypeDef, import('@tanstack/virtual-file-routes').VirtualRootRoute>, z.ZodString]>>;
5
+ routeFilePrefix: z.ZodOptional<z.ZodString>;
6
+ routeFileIgnorePrefix: z.ZodDefault<z.ZodOptional<z.ZodString>>;
7
+ routeFileIgnorePattern: z.ZodOptional<z.ZodString>;
8
+ routesDirectory: z.ZodDefault<z.ZodOptional<z.ZodString>>;
9
+ quoteStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double"]>>>;
10
+ semicolons: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
11
+ disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
12
+ routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
13
+ indexToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14
+ routeToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
15
+ pathParamsAllowedCharacters: z.ZodOptional<z.ZodArray<z.ZodEnum<[";", ":", "@", "&", "=", "+", "$", ","]>, "many">>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ target: "react" | "solid";
18
+ routeFileIgnorePrefix: string;
19
+ routesDirectory: string;
20
+ quoteStyle: "single" | "double";
21
+ semicolons: boolean;
22
+ disableLogging: boolean;
23
+ routeTreeFileHeader: string[];
24
+ indexToken: string;
25
+ routeToken: string;
26
+ virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
27
+ routeFilePrefix?: string | undefined;
28
+ routeFileIgnorePattern?: string | undefined;
29
+ pathParamsAllowedCharacters?: (";" | ":" | "@" | "&" | "=" | "+" | "$" | ",")[] | undefined;
30
+ }, {
31
+ target?: "react" | "solid" | undefined;
32
+ virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
33
+ routeFilePrefix?: string | undefined;
34
+ routeFileIgnorePrefix?: string | undefined;
35
+ routeFileIgnorePattern?: string | undefined;
36
+ routesDirectory?: string | undefined;
37
+ quoteStyle?: "single" | "double" | undefined;
38
+ semicolons?: boolean | undefined;
39
+ disableLogging?: boolean | undefined;
40
+ routeTreeFileHeader?: string[] | undefined;
41
+ indexToken?: string | undefined;
42
+ routeToken?: string | undefined;
43
+ pathParamsAllowedCharacters?: (";" | ":" | "@" | "&" | "=" | "+" | "$" | ",")[] | undefined;
44
+ }>;
45
+ export type BaseConfig = z.infer<typeof baseConfigSchema>;
46
+ export declare const configSchema: z.ZodObject<z.objectUtil.extendShape<{
3
47
  target: z.ZodDefault<z.ZodOptional<z.ZodEnum<["react", "solid"]>>>;
4
48
  virtualRouteConfig: z.ZodOptional<z.ZodUnion<[z.ZodType<import('@tanstack/virtual-file-routes').VirtualRootRoute, z.ZodTypeDef, import('@tanstack/virtual-file-routes').VirtualRootRoute>, z.ZodString]>>;
5
49
  routeFilePrefix: z.ZodOptional<z.ZodString>;
6
50
  routeFileIgnorePrefix: z.ZodDefault<z.ZodOptional<z.ZodString>>;
7
51
  routeFileIgnorePattern: z.ZodOptional<z.ZodString>;
8
52
  routesDirectory: z.ZodDefault<z.ZodOptional<z.ZodString>>;
9
- generatedRouteTree: z.ZodDefault<z.ZodOptional<z.ZodString>>;
10
53
  quoteStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double"]>>>;
11
54
  semicolons: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
55
+ disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
56
+ routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
57
+ indexToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
58
+ routeToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
59
+ pathParamsAllowedCharacters: z.ZodOptional<z.ZodArray<z.ZodEnum<[";", ":", "@", "&", "=", "+", "$", ","]>, "many">>;
60
+ }, {
61
+ generatedRouteTree: z.ZodDefault<z.ZodOptional<z.ZodString>>;
12
62
  disableTypes: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
63
+ verboseFileRoutes: z.ZodOptional<z.ZodBoolean>;
13
64
  addExtensions: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
- disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15
65
  disableManifestGeneration: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
16
66
  enableRouteTreeFormatting: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
17
- __enableAPIRoutesGeneration: z.ZodOptional<z.ZodBoolean>;
18
- apiBase: z.ZodDefault<z.ZodOptional<z.ZodString>>;
19
- routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
20
67
  routeTreeFileFooter: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
21
68
  autoCodeSplitting: z.ZodOptional<z.ZodBoolean>;
22
- indexToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
23
- routeToken: z.ZodDefault<z.ZodOptional<z.ZodString>>;
24
- pathParamsAllowedCharacters: z.ZodOptional<z.ZodArray<z.ZodEnum<[";", ":", "@", "&", "=", "+", "$", ","]>, "many">>;
25
69
  customScaffolding: z.ZodOptional<z.ZodObject<{
26
70
  routeTemplate: z.ZodOptional<z.ZodString>;
27
71
  lazyRouteTemplate: z.ZodOptional<z.ZodString>;
28
- apiTemplate: z.ZodOptional<z.ZodString>;
29
72
  }, "strip", z.ZodTypeAny, {
30
73
  routeTemplate?: string | undefined;
31
74
  lazyRouteTemplate?: string | undefined;
32
- apiTemplate?: string | undefined;
33
75
  }, {
34
76
  routeTemplate?: string | undefined;
35
77
  lazyRouteTemplate?: string | undefined;
36
- apiTemplate?: string | undefined;
37
78
  }>>;
38
79
  experimental: z.ZodOptional<z.ZodObject<{
39
80
  enableCodeSplitting: z.ZodOptional<z.ZodBoolean>;
@@ -42,33 +83,31 @@ export declare const configSchema: z.ZodObject<{
42
83
  }, {
43
84
  enableCodeSplitting?: boolean | undefined;
44
85
  }>>;
45
- }, "strip", z.ZodTypeAny, {
86
+ }>, "strip", z.ZodTypeAny, {
46
87
  target: "react" | "solid";
47
88
  routeFileIgnorePrefix: string;
48
89
  routesDirectory: string;
49
- generatedRouteTree: string;
50
90
  quoteStyle: "single" | "double";
51
91
  semicolons: boolean;
92
+ disableLogging: boolean;
93
+ routeTreeFileHeader: string[];
94
+ indexToken: string;
95
+ routeToken: string;
96
+ generatedRouteTree: string;
52
97
  disableTypes: boolean;
53
98
  addExtensions: boolean;
54
- disableLogging: boolean;
55
99
  disableManifestGeneration: boolean;
56
100
  enableRouteTreeFormatting: boolean;
57
- apiBase: string;
58
- routeTreeFileHeader: string[];
59
101
  routeTreeFileFooter: string[];
60
- indexToken: string;
61
- routeToken: string;
62
102
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
63
103
  routeFilePrefix?: string | undefined;
64
104
  routeFileIgnorePattern?: string | undefined;
65
- __enableAPIRoutesGeneration?: boolean | undefined;
66
- autoCodeSplitting?: boolean | undefined;
67
105
  pathParamsAllowedCharacters?: (";" | ":" | "@" | "&" | "=" | "+" | "$" | ",")[] | undefined;
106
+ verboseFileRoutes?: boolean | undefined;
107
+ autoCodeSplitting?: boolean | undefined;
68
108
  customScaffolding?: {
69
109
  routeTemplate?: string | undefined;
70
110
  lazyRouteTemplate?: string | undefined;
71
- apiTemplate?: string | undefined;
72
111
  } | undefined;
73
112
  experimental?: {
74
113
  enableCodeSplitting?: boolean | undefined;
@@ -80,26 +119,24 @@ export declare const configSchema: z.ZodObject<{
80
119
  routeFileIgnorePrefix?: string | undefined;
81
120
  routeFileIgnorePattern?: string | undefined;
82
121
  routesDirectory?: string | undefined;
83
- generatedRouteTree?: string | undefined;
84
122
  quoteStyle?: "single" | "double" | undefined;
85
123
  semicolons?: boolean | undefined;
124
+ disableLogging?: boolean | undefined;
125
+ routeTreeFileHeader?: string[] | undefined;
126
+ indexToken?: string | undefined;
127
+ routeToken?: string | undefined;
128
+ pathParamsAllowedCharacters?: (";" | ":" | "@" | "&" | "=" | "+" | "$" | ",")[] | undefined;
129
+ generatedRouteTree?: string | undefined;
86
130
  disableTypes?: boolean | undefined;
131
+ verboseFileRoutes?: boolean | undefined;
87
132
  addExtensions?: boolean | undefined;
88
- disableLogging?: boolean | undefined;
89
133
  disableManifestGeneration?: boolean | undefined;
90
134
  enableRouteTreeFormatting?: boolean | undefined;
91
- __enableAPIRoutesGeneration?: boolean | undefined;
92
- apiBase?: string | undefined;
93
- routeTreeFileHeader?: string[] | undefined;
94
135
  routeTreeFileFooter?: string[] | undefined;
95
136
  autoCodeSplitting?: boolean | undefined;
96
- indexToken?: string | undefined;
97
- routeToken?: string | undefined;
98
- pathParamsAllowedCharacters?: (";" | ":" | "@" | "&" | "=" | "+" | "$" | ",")[] | undefined;
99
137
  customScaffolding?: {
100
138
  routeTemplate?: string | undefined;
101
139
  lazyRouteTemplate?: string | undefined;
102
- apiTemplate?: string | undefined;
103
140
  } | undefined;
104
141
  experimental?: {
105
142
  enableCodeSplitting?: boolean | undefined;
@@ -2,38 +2,37 @@ import path from "node:path";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { z } from "zod";
4
4
  import { virtualRootRouteSchema } from "./filesystem/virtual/config.js";
5
- const configSchema = z.object({
5
+ const baseConfigSchema = z.object({
6
6
  target: z.enum(["react", "solid"]).optional().default("react"),
7
7
  virtualRouteConfig: virtualRootRouteSchema.or(z.string()).optional(),
8
8
  routeFilePrefix: z.string().optional(),
9
9
  routeFileIgnorePrefix: z.string().optional().default("-"),
10
10
  routeFileIgnorePattern: z.string().optional(),
11
11
  routesDirectory: z.string().optional().default("./src/routes"),
12
- generatedRouteTree: z.string().optional().default("./src/routeTree.gen.ts"),
13
12
  quoteStyle: z.enum(["single", "double"]).optional().default("single"),
14
13
  semicolons: z.boolean().optional().default(false),
15
- disableTypes: z.boolean().optional().default(false),
16
- addExtensions: z.boolean().optional().default(false),
17
14
  disableLogging: z.boolean().optional().default(false),
18
- disableManifestGeneration: z.boolean().optional().default(false),
19
- enableRouteTreeFormatting: z.boolean().optional().default(true),
20
- __enableAPIRoutesGeneration: z.boolean().optional(),
21
- // Internal flag to be turned on for TanStack Start
22
- apiBase: z.string().optional().default("/api"),
23
15
  routeTreeFileHeader: z.array(z.string()).optional().default([
24
16
  "/* eslint-disable */",
25
17
  "// @ts-nocheck",
26
18
  "// noinspection JSUnusedGlobalSymbols"
27
19
  ]),
28
- routeTreeFileFooter: z.array(z.string()).optional().default([]),
29
- autoCodeSplitting: z.boolean().optional(),
30
20
  indexToken: z.string().optional().default("index"),
31
21
  routeToken: z.string().optional().default("route"),
32
- pathParamsAllowedCharacters: z.array(z.enum([";", ":", "@", "&", "=", "+", "$", ","])).optional(),
22
+ pathParamsAllowedCharacters: z.array(z.enum([";", ":", "@", "&", "=", "+", "$", ","])).optional()
23
+ });
24
+ const configSchema = baseConfigSchema.extend({
25
+ generatedRouteTree: z.string().optional().default("./src/routeTree.gen.ts"),
26
+ disableTypes: z.boolean().optional().default(false),
27
+ verboseFileRoutes: z.boolean().optional(),
28
+ addExtensions: z.boolean().optional().default(false),
29
+ disableManifestGeneration: z.boolean().optional().default(false),
30
+ enableRouteTreeFormatting: z.boolean().optional().default(true),
31
+ routeTreeFileFooter: z.array(z.string()).optional().default([]),
32
+ autoCodeSplitting: z.boolean().optional(),
33
33
  customScaffolding: z.object({
34
34
  routeTemplate: z.string().optional(),
35
- lazyRouteTemplate: z.string().optional(),
36
- apiTemplate: z.string().optional()
35
+ lazyRouteTemplate: z.string().optional()
37
36
  }).optional(),
38
37
  experimental: z.object({
39
38
  // TODO: This has been made stable and is now "autoCodeSplitting". Remove in next major version.
@@ -115,6 +114,7 @@ ERROR: The "experimental.enableCodeSplitting" flag has been made stable and is n
115
114
  return config;
116
115
  }
117
116
  export {
117
+ baseConfigSchema,
118
118
  configSchema,
119
119
  getConfig,
120
120
  resolveConfigPath
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../src/config.ts"],"sourcesContent":["import path from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { z } from 'zod'\nimport { virtualRootRouteSchema } from './filesystem/virtual/config'\n\nexport const configSchema = z.object({\n target: z.enum(['react', 'solid']).optional().default('react'),\n virtualRouteConfig: virtualRootRouteSchema.or(z.string()).optional(),\n routeFilePrefix: z.string().optional(),\n routeFileIgnorePrefix: z.string().optional().default('-'),\n routeFileIgnorePattern: z.string().optional(),\n routesDirectory: z.string().optional().default('./src/routes'),\n generatedRouteTree: z.string().optional().default('./src/routeTree.gen.ts'),\n quoteStyle: z.enum(['single', 'double']).optional().default('single'),\n semicolons: z.boolean().optional().default(false),\n disableTypes: z.boolean().optional().default(false),\n addExtensions: z.boolean().optional().default(false),\n disableLogging: z.boolean().optional().default(false),\n disableManifestGeneration: z.boolean().optional().default(false),\n enableRouteTreeFormatting: z.boolean().optional().default(true),\n __enableAPIRoutesGeneration: z.boolean().optional(), // Internal flag to be turned on for TanStack Start\n apiBase: z.string().optional().default('/api'),\n routeTreeFileHeader: z\n .array(z.string())\n .optional()\n .default([\n '/* eslint-disable */',\n '// @ts-nocheck',\n '// noinspection JSUnusedGlobalSymbols',\n ]),\n routeTreeFileFooter: z.array(z.string()).optional().default([]),\n autoCodeSplitting: z.boolean().optional(),\n indexToken: z.string().optional().default('index'),\n routeToken: z.string().optional().default('route'),\n pathParamsAllowedCharacters: z\n .array(z.enum([';', ':', '@', '&', '=', '+', '$', ',']))\n .optional(),\n customScaffolding: z\n .object({\n routeTemplate: z.string().optional(),\n lazyRouteTemplate: z.string().optional(),\n apiTemplate: z.string().optional(),\n })\n .optional(),\n experimental: z\n .object({\n // TODO: This has been made stable and is now \"autoCodeSplitting\". Remove in next major version.\n enableCodeSplitting: z.boolean().optional(),\n })\n .optional(),\n})\n\nexport type Config = z.infer<typeof configSchema>\n\ntype ResolveParams = {\n configDirectory: string\n}\n\nexport function resolveConfigPath({ configDirectory }: ResolveParams) {\n return path.resolve(configDirectory, 'tsr.config.json')\n}\n\nexport function getConfig(\n inlineConfig: Partial<Config> = {},\n configDirectory?: string,\n): Config {\n if (configDirectory === undefined) {\n configDirectory = process.cwd()\n }\n const configFilePathJson = resolveConfigPath({ configDirectory })\n const exists = existsSync(configFilePathJson)\n\n let config: Config\n\n if (exists) {\n config = configSchema.parse({\n ...JSON.parse(readFileSync(configFilePathJson, 'utf-8')),\n ...inlineConfig,\n })\n } else {\n config = configSchema.parse(inlineConfig)\n }\n\n // If typescript is disabled, make sure the generated route tree is a .js file\n if (config.disableTypes) {\n config.generatedRouteTree = config.generatedRouteTree.replace(\n /\\.(ts|tsx)$/,\n '.js',\n )\n }\n\n // if a configDirectory is used, paths should be relative to that directory\n if (configDirectory) {\n // if absolute configDirectory is provided, use it as the root\n if (path.isAbsolute(configDirectory)) {\n config.routesDirectory = path.resolve(\n configDirectory,\n config.routesDirectory,\n )\n config.generatedRouteTree = path.resolve(\n configDirectory,\n config.generatedRouteTree,\n )\n } else {\n config.routesDirectory = path.resolve(\n process.cwd(),\n configDirectory,\n config.routesDirectory,\n )\n config.generatedRouteTree = path.resolve(\n process.cwd(),\n configDirectory,\n config.generatedRouteTree,\n )\n }\n }\n\n validateConfig(config)\n return config\n}\n\nfunction validateConfig(config: Config) {\n if (typeof config.experimental?.enableCodeSplitting !== 'undefined') {\n const message = `\n------\n⚠️ ⚠️ ⚠️\nERROR: The \"experimental.enableCodeSplitting\" flag has been made stable and is now \"autoCodeSplitting\". Please update your configuration file to use \"autoCodeSplitting\" instead of \"experimental.enableCodeSplitting\".\n------\n`\n console.error(message)\n throw new Error(message)\n }\n\n if (config.indexToken === config.routeToken) {\n throw new Error(\n `The \"indexToken\" and \"routeToken\" options must be different.`,\n )\n }\n\n if (\n config.routeFileIgnorePrefix &&\n config.routeFileIgnorePrefix.trim() === '_'\n ) {\n throw new Error(\n `The \"routeFileIgnorePrefix\" cannot be an underscore (\"_\"). This is a reserved character used to denote a pathless route. Please use a different prefix.`,\n )\n }\n\n return config\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sources":["../../src/config.ts"],"sourcesContent":["import path from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { z } from 'zod'\nimport { virtualRootRouteSchema } from './filesystem/virtual/config'\n\nexport const baseConfigSchema = z.object({\n target: z.enum(['react', 'solid']).optional().default('react'),\n virtualRouteConfig: virtualRootRouteSchema.or(z.string()).optional(),\n routeFilePrefix: z.string().optional(),\n routeFileIgnorePrefix: z.string().optional().default('-'),\n routeFileIgnorePattern: z.string().optional(),\n routesDirectory: z.string().optional().default('./src/routes'),\n quoteStyle: z.enum(['single', 'double']).optional().default('single'),\n semicolons: z.boolean().optional().default(false),\n disableLogging: z.boolean().optional().default(false),\n routeTreeFileHeader: z\n .array(z.string())\n .optional()\n .default([\n '/* eslint-disable */',\n '// @ts-nocheck',\n '// noinspection JSUnusedGlobalSymbols',\n ]),\n indexToken: z.string().optional().default('index'),\n routeToken: z.string().optional().default('route'),\n pathParamsAllowedCharacters: z\n .array(z.enum([';', ':', '@', '&', '=', '+', '$', ',']))\n .optional(),\n})\n\nexport type BaseConfig = z.infer<typeof baseConfigSchema>\n\nexport const configSchema = baseConfigSchema.extend({\n generatedRouteTree: z.string().optional().default('./src/routeTree.gen.ts'),\n disableTypes: z.boolean().optional().default(false),\n verboseFileRoutes: z.boolean().optional(),\n addExtensions: z.boolean().optional().default(false),\n disableManifestGeneration: z.boolean().optional().default(false),\n enableRouteTreeFormatting: z.boolean().optional().default(true),\n routeTreeFileFooter: z.array(z.string()).optional().default([]),\n autoCodeSplitting: z.boolean().optional(),\n customScaffolding: z\n .object({\n routeTemplate: z.string().optional(),\n lazyRouteTemplate: z.string().optional(),\n })\n .optional(),\n experimental: z\n .object({\n // TODO: This has been made stable and is now \"autoCodeSplitting\". Remove in next major version.\n enableCodeSplitting: z.boolean().optional(),\n })\n .optional(),\n})\n\nexport type Config = z.infer<typeof configSchema>\n\ntype ResolveParams = {\n configDirectory: string\n}\n\nexport function resolveConfigPath({ configDirectory }: ResolveParams) {\n return path.resolve(configDirectory, 'tsr.config.json')\n}\n\nexport function getConfig(\n inlineConfig: Partial<Config> = {},\n configDirectory?: string,\n): Config {\n if (configDirectory === undefined) {\n configDirectory = process.cwd()\n }\n const configFilePathJson = resolveConfigPath({ configDirectory })\n const exists = existsSync(configFilePathJson)\n\n let config: Config\n\n if (exists) {\n config = configSchema.parse({\n ...JSON.parse(readFileSync(configFilePathJson, 'utf-8')),\n ...inlineConfig,\n })\n } else {\n config = configSchema.parse(inlineConfig)\n }\n\n // If typescript is disabled, make sure the generated route tree is a .js file\n if (config.disableTypes) {\n config.generatedRouteTree = config.generatedRouteTree.replace(\n /\\.(ts|tsx)$/,\n '.js',\n )\n }\n\n // if a configDirectory is used, paths should be relative to that directory\n if (configDirectory) {\n // if absolute configDirectory is provided, use it as the root\n if (path.isAbsolute(configDirectory)) {\n config.routesDirectory = path.resolve(\n configDirectory,\n config.routesDirectory,\n )\n config.generatedRouteTree = path.resolve(\n configDirectory,\n config.generatedRouteTree,\n )\n } else {\n config.routesDirectory = path.resolve(\n process.cwd(),\n configDirectory,\n config.routesDirectory,\n )\n config.generatedRouteTree = path.resolve(\n process.cwd(),\n configDirectory,\n config.generatedRouteTree,\n )\n }\n }\n\n validateConfig(config)\n return config\n}\n\nfunction validateConfig(config: Config) {\n if (typeof config.experimental?.enableCodeSplitting !== 'undefined') {\n const message = `\n------\n⚠️ ⚠️ ⚠️\nERROR: The \"experimental.enableCodeSplitting\" flag has been made stable and is now \"autoCodeSplitting\". Please update your configuration file to use \"autoCodeSplitting\" instead of \"experimental.enableCodeSplitting\".\n------\n`\n console.error(message)\n throw new Error(message)\n }\n\n if (config.indexToken === config.routeToken) {\n throw new Error(\n `The \"indexToken\" and \"routeToken\" options must be different.`,\n )\n }\n\n if (\n config.routeFileIgnorePrefix &&\n config.routeFileIgnorePrefix.trim() === '_'\n ) {\n throw new Error(\n `The \"routeFileIgnorePrefix\" cannot be an underscore (\"_\"). This is a reserved character used to denote a pathless route. Please use a different prefix.`,\n )\n }\n\n return config\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { FsRouteType, GetRouteNodesResult } from '../../types.js';
2
2
  import { Config } from '../../config.js';
3
- export declare function getRouteNodes(config: Config, root: string): Promise<GetRouteNodesResult>;
3
+ export declare function getRouteNodes(config: Pick<Config, 'routesDirectory' | 'routeFilePrefix' | 'routeFileIgnorePrefix' | 'routeFileIgnorePattern' | 'disableLogging' | 'routeToken' | 'indexToken'>, root: string): Promise<GetRouteNodesResult>;
4
4
  /**
5
5
  * Determines the metadata for a given route path based on the provided configuration.
6
6
  *
@@ -8,7 +8,7 @@ export declare function getRouteNodes(config: Config, root: string): Promise<Get
8
8
  * @param config - The user configuration object.
9
9
  * @returns An object containing the type of the route and the variable name derived from the route path.
10
10
  */
11
- export declare function getRouteMeta(routePath: string, config: Config): {
11
+ export declare function getRouteMeta(routePath: string, config: Pick<Config, 'routeToken' | 'indexToken'>): {
12
12
  fsRouteType: Extract<FsRouteType, 'static' | 'layout' | 'api' | 'lazy' | 'loader' | 'component' | 'pendingComponent' | 'errorComponent'>;
13
13
  variableName: string;
14
14
  };
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import * as fsp from "node:fs/promises";
3
- import { logging, replaceBackslash, routePathToVariable, removeExt, determineInitialRoutePath, removeLeadingSlash, removeTrailingSlash } from "../../utils.js";
3
+ import { logging, replaceBackslash, routePathToVariable, removeExt, determineInitialRoutePath } from "../../utils.js";
4
4
  import { getRouteNodes as getRouteNodes$1 } from "../virtual/getRouteNodes.js";
5
5
  import { loadConfigFile } from "../virtual/loadConfigFile.js";
6
6
  import { rootPathId } from "./rootPathId.js";
@@ -133,11 +133,7 @@ async function getRouteNodes(config, root) {
133
133
  }
134
134
  function getRouteMeta(routePath, config) {
135
135
  let fsRouteType = "static";
136
- if (removeLeadingSlash(routePath).startsWith(
137
- `${removeTrailingSlash(removeLeadingSlash(config.apiBase))}/`
138
- ) && config.__enableAPIRoutesGeneration) {
139
- fsRouteType = "api";
140
- } else if (routePath.endsWith(`/${config.routeToken}`)) {
136
+ if (routePath.endsWith(`/${config.routeToken}`)) {
141
137
  fsRouteType = "layout";
142
138
  } else if (routePath.endsWith("/lazy")) {
143
139
  fsRouteType = "lazy";
@@ -1 +1 @@
1
- {"version":3,"file":"getRouteNodes.js","sources":["../../../../src/filesystem/physical/getRouteNodes.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport {\n determineInitialRoutePath,\n logging,\n removeExt,\n removeLeadingSlash,\n removeTrailingSlash,\n replaceBackslash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesVirtual } from '../virtual/getRouteNodes'\nimport { loadConfigFile } from '../virtual/loadConfigFile'\nimport { rootPathId } from './rootPathId'\nimport type {\n VirtualRootRoute,\n VirtualRouteSubtreeConfig,\n} from '@tanstack/virtual-file-routes'\nimport type { FsRouteType, GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\nconst disallowedRouteGroupConfiguration = /\\(([^)]+)\\).(ts|js|tsx|jsx)/\n\nexport async function getRouteNodes(\n config: Config,\n root: string,\n): Promise<GetRouteNodesResult> {\n const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } =\n config\n const logger = logging({ disabled: config.disableLogging })\n const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')\n\n const routeNodes: Array<RouteNode> = []\n\n async function recurse(dir: string) {\n const fullDir = path.resolve(config.routesDirectory, dir)\n let dirList = await fsp.readdir(fullDir, { withFileTypes: true })\n\n dirList = dirList.filter((d) => {\n if (\n d.name.startsWith('.') ||\n (routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix))\n ) {\n return false\n }\n\n if (routeFilePrefix) {\n return d.name.startsWith(routeFilePrefix)\n }\n\n if (routeFileIgnorePattern) {\n return !d.name.match(routeFileIgnoreRegExp)\n }\n\n return true\n })\n\n const virtualConfigFile = dirList.find((dirent) => {\n return dirent.isFile() && dirent.name.match(/__virtual\\.[mc]?[jt]s$/)\n })\n\n if (virtualConfigFile !== undefined) {\n const virtualRouteConfigExport = await loadConfigFile(\n path.resolve(fullDir, virtualConfigFile.name),\n )\n let virtualRouteSubtreeConfig: VirtualRouteSubtreeConfig\n if (typeof virtualRouteConfigExport.default === 'function') {\n virtualRouteSubtreeConfig = await virtualRouteConfigExport.default()\n } else {\n virtualRouteSubtreeConfig = virtualRouteConfigExport.default\n }\n const dummyRoot: VirtualRootRoute = {\n type: 'root',\n file: '',\n children: virtualRouteSubtreeConfig,\n }\n const { routeNodes: virtualRouteNodes } = await getRouteNodesVirtual(\n {\n ...config,\n routesDirectory: fullDir,\n virtualRouteConfig: dummyRoot,\n },\n root,\n )\n virtualRouteNodes.forEach((node) => {\n const filePath = replaceBackslash(path.join(dir, node.filePath))\n const routePath = `/${dir}${node.routePath}`\n\n node.variableName = routePathToVariable(\n `${dir}/${removeExt(node.filePath)}`,\n )\n node.routePath = routePath\n node.filePath = filePath\n })\n\n routeNodes.push(...virtualRouteNodes)\n\n return\n }\n\n await Promise.all(\n dirList.map(async (dirent) => {\n const fullPath = path.posix.join(fullDir, dirent.name)\n const relativePath = path.posix.join(dir, dirent.name)\n\n if (dirent.isDirectory()) {\n await recurse(relativePath)\n } else if (fullPath.match(/\\.(tsx|ts|jsx|js)$/)) {\n const filePath = replaceBackslash(path.join(dir, dirent.name))\n const filePathNoExt = removeExt(filePath)\n let routePath = determineInitialRoutePath(filePathNoExt)\n\n if (routeFilePrefix) {\n routePath = routePath.replaceAll(routeFilePrefix, '')\n }\n\n if (disallowedRouteGroupConfiguration.test(dirent.name)) {\n const errorMessage = `A route configuration for a route group was found at \\`${filePath}\\`. This is not supported. Did you mean to use a layout/pathless route instead?`\n logger.error(`ERROR: ${errorMessage}`)\n throw new Error(errorMessage)\n }\n\n const meta = getRouteMeta(routePath, config)\n const variableName = meta.variableName\n let routeType: FsRouteType = meta.fsRouteType\n\n if (routeType === 'lazy') {\n routePath = routePath.replace(/\\/lazy$/, '')\n }\n\n // this check needs to happen after the lazy route has been cleaned up\n // since the routePath is used to determine if a route is pathless\n if (isValidPathlessLayoutRoute(routePath, routeType, config)) {\n routeType = 'pathless_layout'\n }\n\n ;(\n [\n ['component', 'component'],\n ['errorComponent', 'errorComponent'],\n ['pendingComponent', 'pendingComponent'],\n ['loader', 'loader'],\n ] satisfies Array<[FsRouteType, string]>\n ).forEach(([matcher, type]) => {\n if (routeType === matcher) {\n logger.warn(\n `WARNING: The \\`.${type}.tsx\\` suffix used for the ${filePath} file is deprecated. Use the new \\`.lazy.tsx\\` suffix instead.`,\n )\n }\n })\n\n routePath = routePath.replace(\n new RegExp(\n `/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,\n ),\n '',\n )\n\n if (routePath === config.indexToken) {\n routePath = '/'\n }\n\n routePath =\n routePath.replace(new RegExp(`/${config.indexToken}$`), '/') || '/'\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n _fsRouteType: routeType,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n const rootRouteNode = routeNodes.find((d) => d.routePath === `/${rootPathId}`)\n if (rootRouteNode) {\n rootRouteNode._fsRouteType = '__root'\n }\n\n return { rootRouteNode, routeNodes }\n}\n\n/**\n * Determines the metadata for a given route path based on the provided configuration.\n *\n * @param routePath - The determined initial routePath.\n * @param config - The user configuration object.\n * @returns An object containing the type of the route and the variable name derived from the route path.\n */\nexport function getRouteMeta(\n routePath: string,\n config: Config,\n): {\n // `__root` is can be more easily determined by filtering down to routePath === /${rootPathId}\n // `pathless` is needs to determined after `lazy` has been cleaned up from the routePath\n fsRouteType: Extract<\n FsRouteType,\n | 'static'\n | 'layout'\n | 'api'\n | 'lazy'\n | 'loader'\n | 'component'\n | 'pendingComponent'\n | 'errorComponent'\n >\n variableName: string\n} {\n let fsRouteType: FsRouteType = 'static'\n\n if (\n removeLeadingSlash(routePath).startsWith(\n `${removeTrailingSlash(removeLeadingSlash(config.apiBase))}/`,\n ) &&\n config.__enableAPIRoutesGeneration\n ) {\n // api routes, i.e. `/api/foo.ts`\n fsRouteType = 'api'\n } else if (routePath.endsWith(`/${config.routeToken}`)) {\n // layout routes, i.e `/foo/route.tsx` or `/foo/_layout/route.tsx`\n fsRouteType = 'layout'\n } else if (routePath.endsWith('/lazy')) {\n // lazy routes, i.e. `/foo.lazy.tsx`\n fsRouteType = 'lazy'\n } else if (routePath.endsWith('/loader')) {\n // loader routes, i.e. `/foo.loader.tsx`\n fsRouteType = 'loader'\n } else if (routePath.endsWith('/component')) {\n // component routes, i.e. `/foo.component.tsx`\n fsRouteType = 'component'\n } else if (routePath.endsWith('/pendingComponent')) {\n // pending component routes, i.e. `/foo.pendingComponent.tsx`\n fsRouteType = 'pendingComponent'\n } else if (routePath.endsWith('/errorComponent')) {\n // error component routes, i.e. `/foo.errorComponent.tsx`\n fsRouteType = 'errorComponent'\n }\n\n const variableName = routePathToVariable(routePath)\n\n return { fsRouteType, variableName }\n}\n\n/**\n * Used to validate if a route is a pathless layout route\n * @param normalizedRoutePath Normalized route path, i.e `/foo/_layout/route.tsx` and `/foo._layout.route.tsx` to `/foo/_layout/route`\n * @param config The `router-generator` configuration object\n * @returns Boolean indicating if the route is a pathless layout route\n */\nfunction isValidPathlessLayoutRoute(\n normalizedRoutePath: string,\n routeType: FsRouteType,\n config: Config,\n): boolean {\n if (routeType === 'lazy') {\n return false\n }\n\n const segments = normalizedRoutePath.split('/').filter(Boolean)\n\n if (segments.length === 0) {\n return false\n }\n\n const lastRouteSegment = segments[segments.length - 1]!\n const secondToLastRouteSegment = segments[segments.length - 2]\n\n // If segment === __root, then exit as false\n if (lastRouteSegment === rootPathId) {\n return false\n }\n\n // If segment === config.routeToken and secondToLastSegment is a string that starts with _, then exit as true\n // Since the route is actually a configuration route for a layout/pathless route\n // i.e. /foo/_layout/route.tsx === /foo/_layout.tsx\n if (\n lastRouteSegment === config.routeToken &&\n typeof secondToLastRouteSegment === 'string'\n ) {\n return secondToLastRouteSegment.startsWith('_')\n }\n\n // Segment starts with _\n return (\n lastRouteSegment !== config.indexToken &&\n lastRouteSegment !== config.routeToken &&\n lastRouteSegment.startsWith('_')\n )\n}\n"],"names":["getRouteNodesVirtual"],"mappings":"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"}
1
+ {"version":3,"file":"getRouteNodes.js","sources":["../../../../src/filesystem/physical/getRouteNodes.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport {\n determineInitialRoutePath,\n logging,\n removeExt,\n replaceBackslash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesVirtual } from '../virtual/getRouteNodes'\nimport { loadConfigFile } from '../virtual/loadConfigFile'\nimport { rootPathId } from './rootPathId'\nimport type {\n VirtualRootRoute,\n VirtualRouteSubtreeConfig,\n} from '@tanstack/virtual-file-routes'\nimport type { FsRouteType, GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\nconst disallowedRouteGroupConfiguration = /\\(([^)]+)\\).(ts|js|tsx|jsx)/\n\nexport async function getRouteNodes(\n config: Pick<\n Config,\n | 'routesDirectory'\n | 'routeFilePrefix'\n | 'routeFileIgnorePrefix'\n | 'routeFileIgnorePattern'\n | 'disableLogging'\n | 'routeToken'\n | 'indexToken'\n >,\n root: string,\n): Promise<GetRouteNodesResult> {\n const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } =\n config\n const logger = logging({ disabled: config.disableLogging })\n const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')\n\n const routeNodes: Array<RouteNode> = []\n\n async function recurse(dir: string) {\n const fullDir = path.resolve(config.routesDirectory, dir)\n let dirList = await fsp.readdir(fullDir, { withFileTypes: true })\n\n dirList = dirList.filter((d) => {\n if (\n d.name.startsWith('.') ||\n (routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix))\n ) {\n return false\n }\n\n if (routeFilePrefix) {\n return d.name.startsWith(routeFilePrefix)\n }\n\n if (routeFileIgnorePattern) {\n return !d.name.match(routeFileIgnoreRegExp)\n }\n\n return true\n })\n\n const virtualConfigFile = dirList.find((dirent) => {\n return dirent.isFile() && dirent.name.match(/__virtual\\.[mc]?[jt]s$/)\n })\n\n if (virtualConfigFile !== undefined) {\n const virtualRouteConfigExport = await loadConfigFile(\n path.resolve(fullDir, virtualConfigFile.name),\n )\n let virtualRouteSubtreeConfig: VirtualRouteSubtreeConfig\n if (typeof virtualRouteConfigExport.default === 'function') {\n virtualRouteSubtreeConfig = await virtualRouteConfigExport.default()\n } else {\n virtualRouteSubtreeConfig = virtualRouteConfigExport.default\n }\n const dummyRoot: VirtualRootRoute = {\n type: 'root',\n file: '',\n children: virtualRouteSubtreeConfig,\n }\n const { routeNodes: virtualRouteNodes } = await getRouteNodesVirtual(\n {\n ...config,\n routesDirectory: fullDir,\n virtualRouteConfig: dummyRoot,\n },\n root,\n )\n virtualRouteNodes.forEach((node) => {\n const filePath = replaceBackslash(path.join(dir, node.filePath))\n const routePath = `/${dir}${node.routePath}`\n\n node.variableName = routePathToVariable(\n `${dir}/${removeExt(node.filePath)}`,\n )\n node.routePath = routePath\n node.filePath = filePath\n })\n\n routeNodes.push(...virtualRouteNodes)\n\n return\n }\n\n await Promise.all(\n dirList.map(async (dirent) => {\n const fullPath = path.posix.join(fullDir, dirent.name)\n const relativePath = path.posix.join(dir, dirent.name)\n\n if (dirent.isDirectory()) {\n await recurse(relativePath)\n } else if (fullPath.match(/\\.(tsx|ts|jsx|js)$/)) {\n const filePath = replaceBackslash(path.join(dir, dirent.name))\n const filePathNoExt = removeExt(filePath)\n let routePath = determineInitialRoutePath(filePathNoExt)\n\n if (routeFilePrefix) {\n routePath = routePath.replaceAll(routeFilePrefix, '')\n }\n\n if (disallowedRouteGroupConfiguration.test(dirent.name)) {\n const errorMessage = `A route configuration for a route group was found at \\`${filePath}\\`. This is not supported. Did you mean to use a layout/pathless route instead?`\n logger.error(`ERROR: ${errorMessage}`)\n throw new Error(errorMessage)\n }\n\n const meta = getRouteMeta(routePath, config)\n const variableName = meta.variableName\n let routeType: FsRouteType = meta.fsRouteType\n\n if (routeType === 'lazy') {\n routePath = routePath.replace(/\\/lazy$/, '')\n }\n\n // this check needs to happen after the lazy route has been cleaned up\n // since the routePath is used to determine if a route is pathless\n if (isValidPathlessLayoutRoute(routePath, routeType, config)) {\n routeType = 'pathless_layout'\n }\n\n ;(\n [\n ['component', 'component'],\n ['errorComponent', 'errorComponent'],\n ['pendingComponent', 'pendingComponent'],\n ['loader', 'loader'],\n ] satisfies Array<[FsRouteType, string]>\n ).forEach(([matcher, type]) => {\n if (routeType === matcher) {\n logger.warn(\n `WARNING: The \\`.${type}.tsx\\` suffix used for the ${filePath} file is deprecated. Use the new \\`.lazy.tsx\\` suffix instead.`,\n )\n }\n })\n\n routePath = routePath.replace(\n new RegExp(\n `/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,\n ),\n '',\n )\n\n if (routePath === config.indexToken) {\n routePath = '/'\n }\n\n routePath =\n routePath.replace(new RegExp(`/${config.indexToken}$`), '/') || '/'\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n _fsRouteType: routeType,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n const rootRouteNode = routeNodes.find((d) => d.routePath === `/${rootPathId}`)\n if (rootRouteNode) {\n rootRouteNode._fsRouteType = '__root'\n }\n\n return { rootRouteNode, routeNodes }\n}\n\n/**\n * Determines the metadata for a given route path based on the provided configuration.\n *\n * @param routePath - The determined initial routePath.\n * @param config - The user configuration object.\n * @returns An object containing the type of the route and the variable name derived from the route path.\n */\nexport function getRouteMeta(\n routePath: string,\n config: Pick<Config, 'routeToken' | 'indexToken'>,\n): {\n // `__root` is can be more easily determined by filtering down to routePath === /${rootPathId}\n // `pathless` is needs to determined after `lazy` has been cleaned up from the routePath\n fsRouteType: Extract<\n FsRouteType,\n | 'static'\n | 'layout'\n | 'api'\n | 'lazy'\n | 'loader'\n | 'component'\n | 'pendingComponent'\n | 'errorComponent'\n >\n variableName: string\n} {\n let fsRouteType: FsRouteType = 'static'\n\n if (routePath.endsWith(`/${config.routeToken}`)) {\n // layout routes, i.e `/foo/route.tsx` or `/foo/_layout/route.tsx`\n fsRouteType = 'layout'\n } else if (routePath.endsWith('/lazy')) {\n // lazy routes, i.e. `/foo.lazy.tsx`\n fsRouteType = 'lazy'\n } else if (routePath.endsWith('/loader')) {\n // loader routes, i.e. `/foo.loader.tsx`\n fsRouteType = 'loader'\n } else if (routePath.endsWith('/component')) {\n // component routes, i.e. `/foo.component.tsx`\n fsRouteType = 'component'\n } else if (routePath.endsWith('/pendingComponent')) {\n // pending component routes, i.e. `/foo.pendingComponent.tsx`\n fsRouteType = 'pendingComponent'\n } else if (routePath.endsWith('/errorComponent')) {\n // error component routes, i.e. `/foo.errorComponent.tsx`\n fsRouteType = 'errorComponent'\n }\n\n const variableName = routePathToVariable(routePath)\n\n return { fsRouteType, variableName }\n}\n\n/**\n * Used to validate if a route is a pathless layout route\n * @param normalizedRoutePath Normalized route path, i.e `/foo/_layout/route.tsx` and `/foo._layout.route.tsx` to `/foo/_layout/route`\n * @param config The `router-generator` configuration object\n * @returns Boolean indicating if the route is a pathless layout route\n */\nfunction isValidPathlessLayoutRoute(\n normalizedRoutePath: string,\n routeType: FsRouteType,\n config: Pick<Config, 'routeToken' | 'indexToken'>,\n): boolean {\n if (routeType === 'lazy') {\n return false\n }\n\n const segments = normalizedRoutePath.split('/').filter(Boolean)\n\n if (segments.length === 0) {\n return false\n }\n\n const lastRouteSegment = segments[segments.length - 1]!\n const secondToLastRouteSegment = segments[segments.length - 2]\n\n // If segment === __root, then exit as false\n if (lastRouteSegment === rootPathId) {\n return false\n }\n\n // If segment === config.routeToken and secondToLastSegment is a string that starts with _, then exit as true\n // Since the route is actually a configuration route for a layout/pathless route\n // i.e. /foo/_layout/route.tsx === /foo/_layout.tsx\n if (\n lastRouteSegment === config.routeToken &&\n typeof secondToLastRouteSegment === 'string'\n ) {\n return secondToLastRouteSegment.startsWith('_')\n }\n\n // Segment starts with _\n return (\n lastRouteSegment !== config.indexToken &&\n lastRouteSegment !== config.routeToken &&\n lastRouteSegment.startsWith('_')\n )\n}\n"],"names":["getRouteNodesVirtual"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { VirtualRouteNode } from '@tanstack/virtual-file-routes';
2
2
  import { GetRouteNodesResult, RouteNode } from '../../types.js';
3
3
  import { Config } from '../../config.js';
4
- export declare function getRouteNodes(tsrConfig: Config, root: string): Promise<GetRouteNodesResult>;
5
- export declare function getRouteNodesRecursive(tsrConfig: Config, root: string, fullDir: string, nodes?: Array<VirtualRouteNode>, parent?: RouteNode): Promise<Array<RouteNode>>;
4
+ export declare function getRouteNodes(tsrConfig: Pick<Config, 'routesDirectory' | 'virtualRouteConfig' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string): Promise<GetRouteNodesResult>;
5
+ export declare function getRouteNodesRecursive(tsrConfig: Pick<Config, 'routesDirectory' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string, fullDir: string, nodes?: Array<VirtualRouteNode>, parent?: RouteNode): Promise<Array<RouteNode>>;
@@ -1 +1 @@
1
- {"version":3,"file":"getRouteNodes.js","sources":["../../../../src/filesystem/virtual/getRouteNodes.ts"],"sourcesContent":["import path, { join, resolve } from 'node:path'\nimport {\n removeExt,\n removeLeadingSlash,\n removeTrailingSlash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesPhysical } from '../physical/getRouteNodes'\nimport { rootPathId } from '../physical/rootPathId'\nimport { virtualRootRouteSchema } from './config'\nimport { loadConfigFile } from './loadConfigFile'\nimport type {\n VirtualRootRoute,\n VirtualRouteNode,\n} from '@tanstack/virtual-file-routes'\nimport type { GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\nfunction ensureLeadingUnderScore(id: string) {\n if (id.startsWith('_')) {\n return id\n }\n return `_${id}`\n}\n\nfunction flattenTree(node: RouteNode): Array<RouteNode> {\n const result = [node]\n\n if (node.children) {\n for (const child of node.children) {\n result.push(...flattenTree(child))\n }\n }\n delete node.children\n\n return result\n}\n\nexport async function getRouteNodes(\n tsrConfig: Config,\n root: string,\n): Promise<GetRouteNodesResult> {\n const fullDir = resolve(tsrConfig.routesDirectory)\n if (tsrConfig.virtualRouteConfig === undefined) {\n throw new Error(`virtualRouteConfig is undefined`)\n }\n let virtualRouteConfig: VirtualRootRoute\n let children: Array<RouteNode> = []\n if (typeof tsrConfig.virtualRouteConfig === 'string') {\n virtualRouteConfig = await getVirtualRouteConfigFromFileExport(\n tsrConfig,\n root,\n )\n } else {\n virtualRouteConfig = tsrConfig.virtualRouteConfig\n }\n children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n virtualRouteConfig.children,\n )\n const allNodes = flattenTree({\n children,\n filePath: virtualRouteConfig.file,\n fullPath: join(fullDir, virtualRouteConfig.file),\n variableName: 'rootRoute',\n routePath: `/${rootPathId}`,\n _fsRouteType: '__root',\n })\n\n const rootRouteNode = allNodes[0]\n const routeNodes = allNodes.slice(1)\n\n return { rootRouteNode, routeNodes }\n}\n\n/**\n * Get the virtual route config from a file export\n *\n * @example\n * ```ts\n * // routes.ts\n * import { rootRoute } from '@tanstack/virtual-file-routes'\n *\n * export const routes = rootRoute({ ... })\n * // or\n * export default rootRoute({ ... })\n * ```\n *\n */\nasync function getVirtualRouteConfigFromFileExport(\n tsrConfig: Config,\n root: string,\n): Promise<VirtualRootRoute> {\n if (\n tsrConfig.virtualRouteConfig === undefined ||\n typeof tsrConfig.virtualRouteConfig !== 'string' ||\n tsrConfig.virtualRouteConfig === ''\n ) {\n throw new Error(`virtualRouteConfig is undefined or empty`)\n }\n const exports = await loadConfigFile(join(root, tsrConfig.virtualRouteConfig))\n\n if (!('routes' in exports) && !('default' in exports)) {\n throw new Error(\n `routes not found in ${tsrConfig.virtualRouteConfig}. The routes export must be named like 'export const routes = ...' or done using 'export default ...'`,\n )\n }\n\n const virtualRouteConfig =\n 'routes' in exports ? exports.routes : exports.default\n\n return virtualRootRouteSchema.parse(virtualRouteConfig)\n}\n\nexport async function getRouteNodesRecursive(\n tsrConfig: Config,\n root: string,\n fullDir: string,\n nodes?: Array<VirtualRouteNode>,\n parent?: RouteNode,\n): Promise<Array<RouteNode>> {\n if (nodes === undefined) {\n return []\n }\n const children = await Promise.all(\n nodes.map(async (node) => {\n if (node.type === 'physical') {\n const { routeNodes } = await getRouteNodesPhysical(\n {\n ...tsrConfig,\n routesDirectory: resolve(fullDir, node.directory),\n },\n root,\n )\n routeNodes.forEach((subtreeNode) => {\n subtreeNode.variableName = routePathToVariable(\n `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`,\n )\n subtreeNode.routePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.routePath}`\n subtreeNode.filePath = `${node.directory}/${subtreeNode.filePath}`\n })\n return routeNodes\n }\n\n function getFile(file: string) {\n const filePath = file\n const variableName = routePathToVariable(removeExt(filePath))\n const fullPath = join(fullDir, filePath)\n return { filePath, variableName, fullPath }\n }\n const parentRoutePath = removeTrailingSlash(parent?.routePath ?? '/')\n\n switch (node.type) {\n case 'index': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n const routePath = `${parentRoutePath}/`\n return {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n } satisfies RouteNode\n }\n\n case 'route': {\n const lastSegment = node.path\n let routeNode: RouteNode\n\n const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`\n if (node.file) {\n const { filePath, variableName, fullPath } = getFile(node.file)\n routeNode = {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n }\n } else {\n routeNode = {\n filePath: '',\n fullPath: '',\n variableName: routePathToVariable(routePath),\n routePath,\n isVirtual: true,\n _fsRouteType: 'static',\n }\n }\n\n if (node.children !== undefined) {\n const children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n\n // If the route has children, it should be a layout\n routeNode._fsRouteType = 'layout'\n }\n return routeNode\n }\n case 'layout': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n\n if (node.id !== undefined) {\n node.id = ensureLeadingUnderScore(node.id)\n } else {\n const baseName = path.basename(filePath)\n const fileNameWithoutExt = path.parse(baseName).name\n node.id = ensureLeadingUnderScore(fileNameWithoutExt)\n }\n const lastSegment = node.id\n const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`\n\n const routeNode: RouteNode = {\n fullPath,\n filePath,\n variableName,\n routePath,\n _fsRouteType: 'pathless_layout',\n }\n\n if (node.children !== undefined) {\n const children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n }\n return routeNode\n }\n }\n }),\n )\n return children.flat()\n}\n"],"names":["getRouteNodesPhysical","children"],"mappings":";;;;;;AAkBA,SAAS,wBAAwB,IAAY;AACvC,MAAA,GAAG,WAAW,GAAG,GAAG;AACf,WAAA;AAAA,EAAA;AAET,SAAO,IAAI,EAAE;AACf;AAEA,SAAS,YAAY,MAAmC;AAChD,QAAA,SAAS,CAAC,IAAI;AAEpB,MAAI,KAAK,UAAU;AACN,eAAA,SAAS,KAAK,UAAU;AACjC,aAAO,KAAK,GAAG,YAAY,KAAK,CAAC;AAAA,IAAA;AAAA,EACnC;AAEF,SAAO,KAAK;AAEL,SAAA;AACT;AAEsB,eAAA,cACpB,WACA,MAC8B;AACxB,QAAA,UAAU,QAAQ,UAAU,eAAe;AAC7C,MAAA,UAAU,uBAAuB,QAAW;AACxC,UAAA,IAAI,MAAM,iCAAiC;AAAA,EAAA;AAE/C,MAAA;AACJ,MAAI,WAA6B,CAAC;AAC9B,MAAA,OAAO,UAAU,uBAAuB,UAAU;AACpD,yBAAqB,MAAM;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EAAA,OACK;AACL,yBAAqB,UAAU;AAAA,EAAA;AAEjC,aAAW,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,EACrB;AACA,QAAM,WAAW,YAAY;AAAA,IAC3B;AAAA,IACA,UAAU,mBAAmB;AAAA,IAC7B,UAAU,KAAK,SAAS,mBAAmB,IAAI;AAAA,IAC/C,cAAc;AAAA,IACd,WAAW,IAAI,UAAU;AAAA,IACzB,cAAc;AAAA,EAAA,CACf;AAEK,QAAA,gBAAgB,SAAS,CAAC;AAC1B,QAAA,aAAa,SAAS,MAAM,CAAC;AAE5B,SAAA,EAAE,eAAe,WAAW;AACrC;AAgBA,eAAe,oCACb,WACA,MAC2B;AAEzB,MAAA,UAAU,uBAAuB,UACjC,OAAO,UAAU,uBAAuB,YACxC,UAAU,uBAAuB,IACjC;AACM,UAAA,IAAI,MAAM,0CAA0C;AAAA,EAAA;AAE5D,QAAM,UAAU,MAAM,eAAe,KAAK,MAAM,UAAU,kBAAkB,CAAC;AAE7E,MAAI,EAAE,YAAY,YAAY,EAAE,aAAa,UAAU;AACrD,UAAM,IAAI;AAAA,MACR,uBAAuB,UAAU,kBAAkB;AAAA,IACrD;AAAA,EAAA;AAGF,QAAM,qBACJ,YAAY,UAAU,QAAQ,SAAS,QAAQ;AAE1C,SAAA,uBAAuB,MAAM,kBAAkB;AACxD;AAEA,eAAsB,uBACpB,WACA,MACA,SACA,OACA,QAC2B;AAC3B,MAAI,UAAU,QAAW;AACvB,WAAO,CAAC;AAAA,EAAA;AAEJ,QAAA,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,IAAI,OAAO,SAAS;AACpB,UAAA,KAAK,SAAS,YAAY;AACtB,cAAA,EAAE,WAAW,IAAI,MAAMA;AAAAA,UAC3B;AAAA,YACE,GAAG;AAAA,YACH,iBAAiB,QAAQ,SAAS,KAAK,SAAS;AAAA,UAClD;AAAA,UACA;AAAA,QACF;AACW,mBAAA,QAAQ,CAAC,gBAAgB;AAClC,sBAAY,eAAe;AAAA,YACzB,GAAG,KAAK,UAAU,IAAI,UAAU,YAAY,QAAQ,CAAC;AAAA,UACvD;AACY,sBAAA,YAAY,IAAG,iCAAQ,cAAa,EAAE,GAAG,KAAK,UAAU,GAAG,YAAY,SAAS;AAC5F,sBAAY,WAAW,GAAG,KAAK,SAAS,IAAI,YAAY,QAAQ;AAAA,QAAA,CACjE;AACM,eAAA;AAAA,MAAA;AAGT,eAAS,QAAQ,MAAc;AAC7B,cAAM,WAAW;AACjB,cAAM,eAAe,oBAAoB,UAAU,QAAQ,CAAC;AACtD,cAAA,WAAW,KAAK,SAAS,QAAQ;AAChC,eAAA,EAAE,UAAU,cAAc,SAAS;AAAA,MAAA;AAE5C,YAAM,kBAAkB,qBAAoB,iCAAQ,cAAa,GAAG;AAEpE,cAAQ,KAAK,MAAM;AAAA,QACjB,KAAK,SAAS;AACZ,gBAAM,EAAE,UAAU,cAAc,SAAa,IAAA,QAAQ,KAAK,IAAI;AACxD,gBAAA,YAAY,GAAG,eAAe;AAC7B,iBAAA;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,cAAc;AAAA,UAChB;AAAA,QAAA;AAAA,QAGF,KAAK,SAAS;AACZ,gBAAM,cAAc,KAAK;AACrB,cAAA;AAEJ,gBAAM,YAAY,GAAG,eAAe,IAAI,mBAAmB,WAAW,CAAC;AACvE,cAAI,KAAK,MAAM;AACb,kBAAM,EAAE,UAAU,cAAc,SAAa,IAAA,QAAQ,KAAK,IAAI;AAClD,wBAAA;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,cAAc;AAAA,YAChB;AAAA,UAAA,OACK;AACO,wBAAA;AAAA,cACV,UAAU;AAAA,cACV,UAAU;AAAA,cACV,cAAc,oBAAoB,SAAS;AAAA,cAC3C;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,UAAA;AAGE,cAAA,KAAK,aAAa,QAAW;AAC/B,kBAAMC,YAAW,MAAM;AAAA,cACrB;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL;AAAA,YACF;AACA,sBAAU,WAAWA;AAGrB,sBAAU,eAAe;AAAA,UAAA;AAEpB,iBAAA;AAAA,QAAA;AAAA,QAET,KAAK,UAAU;AACb,gBAAM,EAAE,UAAU,cAAc,SAAa,IAAA,QAAQ,KAAK,IAAI;AAE1D,cAAA,KAAK,OAAO,QAAW;AACpB,iBAAA,KAAK,wBAAwB,KAAK,EAAE;AAAA,UAAA,OACpC;AACC,kBAAA,WAAW,KAAK,SAAS,QAAQ;AACvC,kBAAM,qBAAqB,KAAK,MAAM,QAAQ,EAAE;AAC3C,iBAAA,KAAK,wBAAwB,kBAAkB;AAAA,UAAA;AAEtD,gBAAM,cAAc,KAAK;AACzB,gBAAM,YAAY,GAAG,eAAe,IAAI,mBAAmB,WAAW,CAAC;AAEvE,gBAAM,YAAuB;AAAA,YAC3B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,cAAc;AAAA,UAChB;AAEI,cAAA,KAAK,aAAa,QAAW;AAC/B,kBAAMA,YAAW,MAAM;AAAA,cACrB;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL;AAAA,YACF;AACA,sBAAU,WAAWA;AAAAA,UAAA;AAEhB,iBAAA;AAAA,QAAA;AAAA,MACT;AAAA,IAEH,CAAA;AAAA,EACH;AACA,SAAO,SAAS,KAAK;AACvB;"}
1
+ {"version":3,"file":"getRouteNodes.js","sources":["../../../../src/filesystem/virtual/getRouteNodes.ts"],"sourcesContent":["import path, { join, resolve } from 'node:path'\nimport {\n removeExt,\n removeLeadingSlash,\n removeTrailingSlash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesPhysical } from '../physical/getRouteNodes'\nimport { rootPathId } from '../physical/rootPathId'\nimport { virtualRootRouteSchema } from './config'\nimport { loadConfigFile } from './loadConfigFile'\nimport type {\n VirtualRootRoute,\n VirtualRouteNode,\n} from '@tanstack/virtual-file-routes'\nimport type { GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\nfunction ensureLeadingUnderScore(id: string) {\n if (id.startsWith('_')) {\n return id\n }\n return `_${id}`\n}\n\nfunction flattenTree(node: RouteNode): Array<RouteNode> {\n const result = [node]\n\n if (node.children) {\n for (const child of node.children) {\n result.push(...flattenTree(child))\n }\n }\n delete node.children\n\n return result\n}\n\nexport async function getRouteNodes(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'virtualRouteConfig'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n): Promise<GetRouteNodesResult> {\n const fullDir = resolve(tsrConfig.routesDirectory)\n if (tsrConfig.virtualRouteConfig === undefined) {\n throw new Error(`virtualRouteConfig is undefined`)\n }\n let virtualRouteConfig: VirtualRootRoute\n let children: Array<RouteNode> = []\n if (typeof tsrConfig.virtualRouteConfig === 'string') {\n virtualRouteConfig = await getVirtualRouteConfigFromFileExport(\n tsrConfig,\n root,\n )\n } else {\n virtualRouteConfig = tsrConfig.virtualRouteConfig\n }\n children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n virtualRouteConfig.children,\n )\n const allNodes = flattenTree({\n children,\n filePath: virtualRouteConfig.file,\n fullPath: join(fullDir, virtualRouteConfig.file),\n variableName: 'rootRoute',\n routePath: `/${rootPathId}`,\n _fsRouteType: '__root',\n })\n\n const rootRouteNode = allNodes[0]\n const routeNodes = allNodes.slice(1)\n\n return { rootRouteNode, routeNodes }\n}\n\n/**\n * Get the virtual route config from a file export\n *\n * @example\n * ```ts\n * // routes.ts\n * import { rootRoute } from '@tanstack/virtual-file-routes'\n *\n * export const routes = rootRoute({ ... })\n * // or\n * export default rootRoute({ ... })\n * ```\n *\n */\nasync function getVirtualRouteConfigFromFileExport(\n tsrConfig: Pick<Config, 'virtualRouteConfig'>,\n root: string,\n): Promise<VirtualRootRoute> {\n if (\n tsrConfig.virtualRouteConfig === undefined ||\n typeof tsrConfig.virtualRouteConfig !== 'string' ||\n tsrConfig.virtualRouteConfig === ''\n ) {\n throw new Error(`virtualRouteConfig is undefined or empty`)\n }\n const exports = await loadConfigFile(join(root, tsrConfig.virtualRouteConfig))\n\n if (!('routes' in exports) && !('default' in exports)) {\n throw new Error(\n `routes not found in ${tsrConfig.virtualRouteConfig}. The routes export must be named like 'export const routes = ...' or done using 'export default ...'`,\n )\n }\n\n const virtualRouteConfig =\n 'routes' in exports ? exports.routes : exports.default\n\n return virtualRootRouteSchema.parse(virtualRouteConfig)\n}\n\nexport async function getRouteNodesRecursive(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n fullDir: string,\n nodes?: Array<VirtualRouteNode>,\n parent?: RouteNode,\n): Promise<Array<RouteNode>> {\n if (nodes === undefined) {\n return []\n }\n const children = await Promise.all(\n nodes.map(async (node) => {\n if (node.type === 'physical') {\n const { routeNodes } = await getRouteNodesPhysical(\n {\n ...tsrConfig,\n routesDirectory: resolve(fullDir, node.directory),\n },\n root,\n )\n routeNodes.forEach((subtreeNode) => {\n subtreeNode.variableName = routePathToVariable(\n `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`,\n )\n subtreeNode.routePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.routePath}`\n subtreeNode.filePath = `${node.directory}/${subtreeNode.filePath}`\n })\n return routeNodes\n }\n\n function getFile(file: string) {\n const filePath = file\n const variableName = routePathToVariable(removeExt(filePath))\n const fullPath = join(fullDir, filePath)\n return { filePath, variableName, fullPath }\n }\n const parentRoutePath = removeTrailingSlash(parent?.routePath ?? '/')\n\n switch (node.type) {\n case 'index': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n const routePath = `${parentRoutePath}/`\n return {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n } satisfies RouteNode\n }\n\n case 'route': {\n const lastSegment = node.path\n let routeNode: RouteNode\n\n const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`\n if (node.file) {\n const { filePath, variableName, fullPath } = getFile(node.file)\n routeNode = {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n }\n } else {\n routeNode = {\n filePath: '',\n fullPath: '',\n variableName: routePathToVariable(routePath),\n routePath,\n isVirtual: true,\n _fsRouteType: 'static',\n }\n }\n\n if (node.children !== undefined) {\n const children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n\n // If the route has children, it should be a layout\n routeNode._fsRouteType = 'layout'\n }\n return routeNode\n }\n case 'layout': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n\n if (node.id !== undefined) {\n node.id = ensureLeadingUnderScore(node.id)\n } else {\n const baseName = path.basename(filePath)\n const fileNameWithoutExt = path.parse(baseName).name\n node.id = ensureLeadingUnderScore(fileNameWithoutExt)\n }\n const lastSegment = node.id\n const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`\n\n const routeNode: RouteNode = {\n fullPath,\n filePath,\n variableName,\n routePath,\n _fsRouteType: 'pathless_layout',\n }\n\n if (node.children !== undefined) {\n const children = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n }\n return routeNode\n }\n }\n }),\n )\n return children.flat()\n}\n"],"names":["getRouteNodesPhysical","children"],"mappings":"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"}
@@ -1,61 +1,2 @@
1
- import { RouteNode } from './types.js';
2
1
  import { Config } from './config.js';
3
- export declare const CONSTANTS: {
4
- APIRouteExportVariable: string;
5
- };
6
2
  export declare function generator(config: Config, root: string): Promise<void>;
7
- /**
8
- * Removes the last segment from a given path. Segments are considered to be separated by a '/'.
9
- *
10
- * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.
11
- * @returns {string} The path with the last segment removed.
12
- * @example
13
- * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'
14
- */
15
- export declare function removeLastSegmentFromPath(routePath?: string): string;
16
- export declare function hasParentRoute(routes: Array<RouteNode>, node: RouteNode, routePathToCheck: string | undefined): RouteNode | null;
17
- /**
18
- * Gets the final variable name for a route
19
- */
20
- export declare const getResolvedRouteNodeVariableName: (routeNode: RouteNode) => string;
21
- /**
22
- * Creates a map from fullPath to routeNode
23
- */
24
- export declare const createRouteNodesByFullPath: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
25
- /**
26
- * Create a map from 'to' to a routeNode
27
- */
28
- export declare const createRouteNodesByTo: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
29
- /**
30
- * Create a map from 'id' to a routeNode
31
- */
32
- export declare const createRouteNodesById: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
33
- /**
34
- * Infers the full path for use by TS
35
- */
36
- export declare const inferFullPath: (routeNode: RouteNode) => string;
37
- /**
38
- * Infers the path for use by TS
39
- */
40
- export declare const inferPath: (routeNode: RouteNode) => string;
41
- /**
42
- * Infers to path
43
- */
44
- export declare const inferTo: (routeNode: RouteNode) => string;
45
- /**
46
- * Dedupes branches and index routes
47
- */
48
- export declare const dedupeBranchesAndIndexRoutes: (routes: Array<RouteNode>) => Array<RouteNode>;
49
- export type StartAPIRoutePathSegment = {
50
- value: string;
51
- type: 'path' | 'param' | 'splat';
52
- };
53
- /**
54
- * This function takes in a path in the format accepted by TanStack Router
55
- * and returns an array of path segments that can be used to generate
56
- * the pathname of the TanStack Start API route.
57
- *
58
- * @param src
59
- * @returns
60
- */
61
- export declare function startAPIRouteSegmentsFromTSRFilePath(src: string, config: Config): Array<StartAPIRoutePathSegment>;