@tanstack/router-generator 1.20.0 → 1.20.3-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 (74) hide show
  1. package/dist/cjs/config.cjs +93 -13
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +126 -9
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +191 -0
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -0
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +14 -0
  7. package/dist/cjs/filesystem/physical/rootPathId.cjs +5 -0
  8. package/dist/cjs/filesystem/physical/rootPathId.cjs.map +1 -0
  9. package/dist/cjs/filesystem/physical/rootPathId.d.cts +1 -0
  10. package/dist/cjs/filesystem/virtual/config.cjs +37 -0
  11. package/dist/cjs/filesystem/virtual/config.cjs.map +1 -0
  12. package/dist/cjs/filesystem/virtual/config.d.cts +3 -0
  13. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +186 -0
  14. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -0
  15. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +5 -0
  16. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs +11 -0
  17. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -0
  18. package/dist/cjs/filesystem/virtual/loadConfigFile.d.cts +1 -0
  19. package/dist/cjs/generator.cjs +516 -328
  20. package/dist/cjs/generator.cjs.map +1 -1
  21. package/dist/cjs/generator.d.cts +1 -37
  22. package/dist/cjs/index.cjs +24 -0
  23. package/dist/cjs/index.cjs.map +1 -1
  24. package/dist/cjs/index.d.cts +7 -1
  25. package/dist/cjs/template.cjs +110 -0
  26. package/dist/cjs/template.cjs.map +1 -0
  27. package/dist/cjs/template.d.cts +33 -0
  28. package/dist/cjs/types.d.cts +20 -0
  29. package/dist/cjs/utils.cjs +177 -10
  30. package/dist/cjs/utils.cjs.map +1 -1
  31. package/dist/cjs/utils.d.cts +47 -5
  32. package/dist/esm/config.d.ts +126 -9
  33. package/dist/esm/config.js +88 -8
  34. package/dist/esm/config.js.map +1 -1
  35. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +14 -0
  36. package/dist/esm/filesystem/physical/getRouteNodes.js +174 -0
  37. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -0
  38. package/dist/esm/filesystem/physical/rootPathId.d.ts +1 -0
  39. package/dist/esm/filesystem/physical/rootPathId.js +5 -0
  40. package/dist/esm/filesystem/physical/rootPathId.js.map +1 -0
  41. package/dist/esm/filesystem/virtual/config.d.ts +3 -0
  42. package/dist/esm/filesystem/virtual/config.js +37 -0
  43. package/dist/esm/filesystem/virtual/config.js.map +1 -0
  44. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +5 -0
  45. package/dist/esm/filesystem/virtual/getRouteNodes.js +186 -0
  46. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -0
  47. package/dist/esm/filesystem/virtual/loadConfigFile.d.ts +1 -0
  48. package/dist/esm/filesystem/virtual/loadConfigFile.js +11 -0
  49. package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -0
  50. package/dist/esm/generator.d.ts +1 -37
  51. package/dist/esm/generator.js +509 -320
  52. package/dist/esm/generator.js.map +1 -1
  53. package/dist/esm/index.d.ts +7 -1
  54. package/dist/esm/index.js +26 -2
  55. package/dist/esm/index.js.map +1 -1
  56. package/dist/esm/template.d.ts +33 -0
  57. package/dist/esm/template.js +110 -0
  58. package/dist/esm/template.js.map +1 -0
  59. package/dist/esm/types.d.ts +20 -0
  60. package/dist/esm/utils.d.ts +47 -5
  61. package/dist/esm/utils.js +160 -11
  62. package/dist/esm/utils.js.map +1 -1
  63. package/package.json +27 -22
  64. package/src/config.ts +112 -8
  65. package/src/filesystem/physical/getRouteNodes.ts +295 -0
  66. package/src/filesystem/physical/rootPathId.ts +1 -0
  67. package/src/filesystem/virtual/config.ts +45 -0
  68. package/src/filesystem/virtual/getRouteNodes.ts +260 -0
  69. package/src/filesystem/virtual/loadConfigFile.ts +8 -0
  70. package/src/generator.ts +712 -395
  71. package/src/index.ts +33 -1
  72. package/src/template.ts +156 -0
  73. package/src/types.ts +31 -0
  74. package/src/utils.ts +237 -10
@@ -0,0 +1,174 @@
1
+ import path from "node:path";
2
+ import * as fsp from "node:fs/promises";
3
+ import { logging, replaceBackslash, routePathToVariable, removeExt, determineInitialRoutePath } from "../../utils.js";
4
+ import { getRouteNodes as getRouteNodes$1 } from "../virtual/getRouteNodes.js";
5
+ import { loadConfigFile } from "../virtual/loadConfigFile.js";
6
+ import { rootPathId } from "./rootPathId.js";
7
+ const disallowedRouteGroupConfiguration = /\(([^)]+)\).(ts|js|tsx|jsx)/;
8
+ async function getRouteNodes(config, root) {
9
+ const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } = config;
10
+ const logger = logging({ disabled: config.disableLogging });
11
+ const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? "", "g");
12
+ const routeNodes = [];
13
+ async function recurse(dir) {
14
+ const fullDir = path.resolve(config.routesDirectory, dir);
15
+ let dirList = await fsp.readdir(fullDir, { withFileTypes: true });
16
+ dirList = dirList.filter((d) => {
17
+ if (d.name.startsWith(".") || routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix)) {
18
+ return false;
19
+ }
20
+ if (routeFilePrefix) {
21
+ return d.name.startsWith(routeFilePrefix);
22
+ }
23
+ if (routeFileIgnorePattern) {
24
+ return !d.name.match(routeFileIgnoreRegExp);
25
+ }
26
+ return true;
27
+ });
28
+ const virtualConfigFile = dirList.find((dirent) => {
29
+ return dirent.isFile() && dirent.name.match(/__virtual\.[mc]?[jt]s$/);
30
+ });
31
+ if (virtualConfigFile !== void 0) {
32
+ const virtualRouteConfigExport = await loadConfigFile(
33
+ path.resolve(fullDir, virtualConfigFile.name)
34
+ );
35
+ let virtualRouteSubtreeConfig;
36
+ if (typeof virtualRouteConfigExport.default === "function") {
37
+ virtualRouteSubtreeConfig = await virtualRouteConfigExport.default();
38
+ } else {
39
+ virtualRouteSubtreeConfig = virtualRouteConfigExport.default;
40
+ }
41
+ const dummyRoot = {
42
+ type: "root",
43
+ file: "",
44
+ children: virtualRouteSubtreeConfig
45
+ };
46
+ const { routeNodes: virtualRouteNodes } = await getRouteNodes$1(
47
+ {
48
+ ...config,
49
+ routesDirectory: fullDir,
50
+ virtualRouteConfig: dummyRoot
51
+ },
52
+ root
53
+ );
54
+ virtualRouteNodes.forEach((node) => {
55
+ const filePath = replaceBackslash(path.join(dir, node.filePath));
56
+ const routePath = `/${dir}${node.routePath}`;
57
+ node.variableName = routePathToVariable(
58
+ `${dir}/${removeExt(node.filePath)}`
59
+ );
60
+ node.routePath = routePath;
61
+ node.filePath = filePath;
62
+ });
63
+ routeNodes.push(...virtualRouteNodes);
64
+ return;
65
+ }
66
+ await Promise.all(
67
+ dirList.map(async (dirent) => {
68
+ const fullPath = path.posix.join(fullDir, dirent.name);
69
+ const relativePath = path.posix.join(dir, dirent.name);
70
+ if (dirent.isDirectory()) {
71
+ await recurse(relativePath);
72
+ } else if (fullPath.match(/\.(tsx|ts|jsx|js)$/)) {
73
+ const filePath = replaceBackslash(path.join(dir, dirent.name));
74
+ const filePathNoExt = removeExt(filePath);
75
+ let routePath = determineInitialRoutePath(filePathNoExt);
76
+ if (routeFilePrefix) {
77
+ routePath = routePath.replaceAll(routeFilePrefix, "");
78
+ }
79
+ if (disallowedRouteGroupConfiguration.test(dirent.name)) {
80
+ 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?`;
81
+ logger.error(`ERROR: ${errorMessage}`);
82
+ throw new Error(errorMessage);
83
+ }
84
+ const meta = getRouteMeta(routePath, config);
85
+ const variableName = meta.variableName;
86
+ let routeType = meta.fsRouteType;
87
+ if (routeType === "lazy") {
88
+ routePath = routePath.replace(/\/lazy$/, "");
89
+ }
90
+ if (isValidPathlessLayoutRoute(routePath, routeType, config)) {
91
+ routeType = "pathless_layout";
92
+ }
93
+ [
94
+ ["component", "component"],
95
+ ["errorComponent", "errorComponent"],
96
+ ["pendingComponent", "pendingComponent"],
97
+ ["loader", "loader"]
98
+ ].forEach(([matcher, type]) => {
99
+ if (routeType === matcher) {
100
+ logger.warn(
101
+ `WARNING: The \`.${type}.tsx\` suffix used for the ${filePath} file is deprecated. Use the new \`.lazy.tsx\` suffix instead.`
102
+ );
103
+ }
104
+ });
105
+ routePath = routePath.replace(
106
+ new RegExp(
107
+ `/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`
108
+ ),
109
+ ""
110
+ );
111
+ if (routePath === config.indexToken) {
112
+ routePath = "/";
113
+ }
114
+ routePath = routePath.replace(new RegExp(`/${config.indexToken}$`), "/") || "/";
115
+ routeNodes.push({
116
+ filePath,
117
+ fullPath,
118
+ routePath,
119
+ variableName,
120
+ _fsRouteType: routeType
121
+ });
122
+ }
123
+ })
124
+ );
125
+ return routeNodes;
126
+ }
127
+ await recurse("./");
128
+ const rootRouteNode = routeNodes.find((d) => d.routePath === `/${rootPathId}`);
129
+ if (rootRouteNode) {
130
+ rootRouteNode._fsRouteType = "__root";
131
+ }
132
+ return { rootRouteNode, routeNodes };
133
+ }
134
+ function getRouteMeta(routePath, config) {
135
+ let fsRouteType = "static";
136
+ if (routePath.endsWith(`/${config.routeToken}`)) {
137
+ fsRouteType = "layout";
138
+ } else if (routePath.endsWith("/lazy")) {
139
+ fsRouteType = "lazy";
140
+ } else if (routePath.endsWith("/loader")) {
141
+ fsRouteType = "loader";
142
+ } else if (routePath.endsWith("/component")) {
143
+ fsRouteType = "component";
144
+ } else if (routePath.endsWith("/pendingComponent")) {
145
+ fsRouteType = "pendingComponent";
146
+ } else if (routePath.endsWith("/errorComponent")) {
147
+ fsRouteType = "errorComponent";
148
+ }
149
+ const variableName = routePathToVariable(routePath);
150
+ return { fsRouteType, variableName };
151
+ }
152
+ function isValidPathlessLayoutRoute(normalizedRoutePath, routeType, config) {
153
+ if (routeType === "lazy") {
154
+ return false;
155
+ }
156
+ const segments = normalizedRoutePath.split("/").filter(Boolean);
157
+ if (segments.length === 0) {
158
+ return false;
159
+ }
160
+ const lastRouteSegment = segments[segments.length - 1];
161
+ const secondToLastRouteSegment = segments[segments.length - 2];
162
+ if (lastRouteSegment === rootPathId) {
163
+ return false;
164
+ }
165
+ if (lastRouteSegment === config.routeToken && typeof secondToLastRouteSegment === "string") {
166
+ return secondToLastRouteSegment.startsWith("_");
167
+ }
168
+ return lastRouteSegment !== config.indexToken && lastRouteSegment !== config.routeToken && lastRouteSegment.startsWith("_");
169
+ }
170
+ export {
171
+ getRouteMeta,
172
+ getRouteNodes
173
+ };
174
+ //# sourceMappingURL=getRouteNodes.js.map
@@ -0,0 +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 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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"}
@@ -0,0 +1 @@
1
+ export declare const rootPathId = "__root";
@@ -0,0 +1,5 @@
1
+ const rootPathId = "__root";
2
+ export {
3
+ rootPathId
4
+ };
5
+ //# sourceMappingURL=rootPathId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rootPathId.js","sources":["../../../../src/filesystem/physical/rootPathId.ts"],"sourcesContent":["export const rootPathId = '__root'\n"],"names":[],"mappings":"AAAO,MAAM,aAAa;"}
@@ -0,0 +1,3 @@
1
+ import { z } from 'zod';
2
+ import { VirtualRootRoute } from '@tanstack/virtual-file-routes';
3
+ export declare const virtualRootRouteSchema: z.ZodType<VirtualRootRoute>;
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ const indexRouteSchema = z.object({
3
+ type: z.literal("index"),
4
+ file: z.string()
5
+ });
6
+ const layoutRouteSchema = z.object({
7
+ type: z.literal("layout"),
8
+ id: z.string().optional(),
9
+ file: z.string(),
10
+ children: z.array(z.lazy(() => virtualRouteNodeSchema)).optional()
11
+ });
12
+ const routeSchema = z.object({
13
+ type: z.literal("route"),
14
+ file: z.string().optional(),
15
+ path: z.string(),
16
+ children: z.array(z.lazy(() => virtualRouteNodeSchema)).optional()
17
+ });
18
+ const physicalSubTreeSchema = z.object({
19
+ type: z.literal("physical"),
20
+ directory: z.string(),
21
+ pathPrefix: z.string()
22
+ });
23
+ const virtualRouteNodeSchema = z.union([
24
+ indexRouteSchema,
25
+ layoutRouteSchema,
26
+ routeSchema,
27
+ physicalSubTreeSchema
28
+ ]);
29
+ const virtualRootRouteSchema = z.object({
30
+ type: z.literal("root"),
31
+ file: z.string(),
32
+ children: z.array(virtualRouteNodeSchema).optional()
33
+ });
34
+ export {
35
+ virtualRootRouteSchema
36
+ };
37
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sources":["../../../../src/filesystem/virtual/config.ts"],"sourcesContent":["import { z } from 'zod'\nimport type {\n LayoutRoute,\n PhysicalSubtree,\n Route,\n VirtualRootRoute,\n} from '@tanstack/virtual-file-routes'\n\nconst indexRouteSchema = z.object({\n type: z.literal('index'),\n file: z.string(),\n})\n\nconst layoutRouteSchema: z.ZodType<LayoutRoute> = z.object({\n type: z.literal('layout'),\n id: z.string().optional(),\n file: z.string(),\n children: z.array(z.lazy(() => virtualRouteNodeSchema)).optional(),\n})\n\nconst routeSchema: z.ZodType<Route> = z.object({\n type: z.literal('route'),\n file: z.string().optional(),\n path: z.string(),\n children: z.array(z.lazy(() => virtualRouteNodeSchema)).optional(),\n})\n\nconst physicalSubTreeSchema: z.ZodType<PhysicalSubtree> = z.object({\n type: z.literal('physical'),\n directory: z.string(),\n pathPrefix: z.string(),\n})\n\nconst virtualRouteNodeSchema = z.union([\n indexRouteSchema,\n layoutRouteSchema,\n routeSchema,\n physicalSubTreeSchema,\n])\n\nexport const virtualRootRouteSchema: z.ZodType<VirtualRootRoute> = z.object({\n type: z.literal('root'),\n file: z.string(),\n children: z.array(virtualRouteNodeSchema).optional(),\n})\n"],"names":[],"mappings":";AAQA,MAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,MAAM,EAAE,OAAO;AACjB,CAAC;AAED,MAAM,oBAA4C,EAAE,OAAO;AAAA,EACzD,MAAM,EAAE,QAAQ,QAAQ;AAAA,EACxB,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,EACxB,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,MAAM,EAAE,KAAK,MAAM,sBAAsB,CAAC,EAAE,SAAS;AACnE,CAAC;AAED,MAAM,cAAgC,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,MAAM,EAAE,KAAK,MAAM,sBAAsB,CAAC,EAAE,SAAS;AACnE,CAAC;AAED,MAAM,wBAAoD,EAAE,OAAO;AAAA,EACjE,MAAM,EAAE,QAAQ,UAAU;AAAA,EAC1B,WAAW,EAAE,OAAO;AAAA,EACpB,YAAY,EAAE,OAAO;AACvB,CAAC;AAED,MAAM,yBAAyB,EAAE,MAAM;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEY,MAAA,yBAAsD,EAAE,OAAO;AAAA,EAC1E,MAAM,EAAE,QAAQ,MAAM;AAAA,EACtB,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,MAAM,sBAAsB,EAAE,SAAS;AACrD,CAAC;"}
@@ -0,0 +1,5 @@
1
+ import { VirtualRouteNode } from '@tanstack/virtual-file-routes';
2
+ import { GetRouteNodesResult, RouteNode } from '../../types.js';
3
+ import { Config } from '../../config.js';
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>>;
@@ -0,0 +1,186 @@
1
+ import path, { resolve, join } from "node:path";
2
+ import { routePathToVariable, removeExt, removeTrailingSlash, removeLeadingSlash } from "../../utils.js";
3
+ import { getRouteNodes as getRouteNodes$1 } from "../physical/getRouteNodes.js";
4
+ import { rootPathId } from "../physical/rootPathId.js";
5
+ import { virtualRootRouteSchema } from "./config.js";
6
+ import { loadConfigFile } from "./loadConfigFile.js";
7
+ function ensureLeadingUnderScore(id) {
8
+ if (id.startsWith("_")) {
9
+ return id;
10
+ }
11
+ return `_${id}`;
12
+ }
13
+ function flattenTree(node) {
14
+ const result = [node];
15
+ if (node.children) {
16
+ for (const child of node.children) {
17
+ result.push(...flattenTree(child));
18
+ }
19
+ }
20
+ delete node.children;
21
+ return result;
22
+ }
23
+ async function getRouteNodes(tsrConfig, root) {
24
+ const fullDir = resolve(tsrConfig.routesDirectory);
25
+ if (tsrConfig.virtualRouteConfig === void 0) {
26
+ throw new Error(`virtualRouteConfig is undefined`);
27
+ }
28
+ let virtualRouteConfig;
29
+ let children = [];
30
+ if (typeof tsrConfig.virtualRouteConfig === "string") {
31
+ virtualRouteConfig = await getVirtualRouteConfigFromFileExport(
32
+ tsrConfig,
33
+ root
34
+ );
35
+ } else {
36
+ virtualRouteConfig = tsrConfig.virtualRouteConfig;
37
+ }
38
+ children = await getRouteNodesRecursive(
39
+ tsrConfig,
40
+ root,
41
+ fullDir,
42
+ virtualRouteConfig.children
43
+ );
44
+ const allNodes = flattenTree({
45
+ children,
46
+ filePath: virtualRouteConfig.file,
47
+ fullPath: join(fullDir, virtualRouteConfig.file),
48
+ variableName: "rootRoute",
49
+ routePath: `/${rootPathId}`,
50
+ _fsRouteType: "__root"
51
+ });
52
+ const rootRouteNode = allNodes[0];
53
+ const routeNodes = allNodes.slice(1);
54
+ return { rootRouteNode, routeNodes };
55
+ }
56
+ async function getVirtualRouteConfigFromFileExport(tsrConfig, root) {
57
+ if (tsrConfig.virtualRouteConfig === void 0 || typeof tsrConfig.virtualRouteConfig !== "string" || tsrConfig.virtualRouteConfig === "") {
58
+ throw new Error(`virtualRouteConfig is undefined or empty`);
59
+ }
60
+ const exports = await loadConfigFile(join(root, tsrConfig.virtualRouteConfig));
61
+ if (!("routes" in exports) && !("default" in exports)) {
62
+ throw new Error(
63
+ `routes not found in ${tsrConfig.virtualRouteConfig}. The routes export must be named like 'export const routes = ...' or done using 'export default ...'`
64
+ );
65
+ }
66
+ const virtualRouteConfig = "routes" in exports ? exports.routes : exports.default;
67
+ return virtualRootRouteSchema.parse(virtualRouteConfig);
68
+ }
69
+ async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, parent) {
70
+ if (nodes === void 0) {
71
+ return [];
72
+ }
73
+ const children = await Promise.all(
74
+ nodes.map(async (node) => {
75
+ if (node.type === "physical") {
76
+ const { routeNodes } = await getRouteNodes$1(
77
+ {
78
+ ...tsrConfig,
79
+ routesDirectory: resolve(fullDir, node.directory)
80
+ },
81
+ root
82
+ );
83
+ routeNodes.forEach((subtreeNode) => {
84
+ subtreeNode.variableName = routePathToVariable(
85
+ `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`
86
+ );
87
+ subtreeNode.routePath = `${(parent == null ? void 0 : parent.routePath) ?? ""}${node.pathPrefix}${subtreeNode.routePath}`;
88
+ subtreeNode.filePath = `${node.directory}/${subtreeNode.filePath}`;
89
+ });
90
+ return routeNodes;
91
+ }
92
+ function getFile(file) {
93
+ const filePath = file;
94
+ const variableName = routePathToVariable(removeExt(filePath));
95
+ const fullPath = join(fullDir, filePath);
96
+ return { filePath, variableName, fullPath };
97
+ }
98
+ const parentRoutePath = removeTrailingSlash((parent == null ? void 0 : parent.routePath) ?? "/");
99
+ switch (node.type) {
100
+ case "index": {
101
+ const { filePath, variableName, fullPath } = getFile(node.file);
102
+ const routePath = `${parentRoutePath}/`;
103
+ return {
104
+ filePath,
105
+ fullPath,
106
+ variableName,
107
+ routePath,
108
+ _fsRouteType: "static"
109
+ };
110
+ }
111
+ case "route": {
112
+ const lastSegment = node.path;
113
+ let routeNode;
114
+ const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`;
115
+ if (node.file) {
116
+ const { filePath, variableName, fullPath } = getFile(node.file);
117
+ routeNode = {
118
+ filePath,
119
+ fullPath,
120
+ variableName,
121
+ routePath,
122
+ _fsRouteType: "static"
123
+ };
124
+ } else {
125
+ routeNode = {
126
+ filePath: "",
127
+ fullPath: "",
128
+ variableName: routePathToVariable(routePath),
129
+ routePath,
130
+ isVirtual: true,
131
+ _fsRouteType: "static"
132
+ };
133
+ }
134
+ if (node.children !== void 0) {
135
+ const children2 = await getRouteNodesRecursive(
136
+ tsrConfig,
137
+ root,
138
+ fullDir,
139
+ node.children,
140
+ routeNode
141
+ );
142
+ routeNode.children = children2;
143
+ routeNode._fsRouteType = "layout";
144
+ }
145
+ return routeNode;
146
+ }
147
+ case "layout": {
148
+ const { filePath, variableName, fullPath } = getFile(node.file);
149
+ if (node.id !== void 0) {
150
+ node.id = ensureLeadingUnderScore(node.id);
151
+ } else {
152
+ const baseName = path.basename(filePath);
153
+ const fileNameWithoutExt = path.parse(baseName).name;
154
+ node.id = ensureLeadingUnderScore(fileNameWithoutExt);
155
+ }
156
+ const lastSegment = node.id;
157
+ const routePath = `${parentRoutePath}/${removeLeadingSlash(lastSegment)}`;
158
+ const routeNode = {
159
+ fullPath,
160
+ filePath,
161
+ variableName,
162
+ routePath,
163
+ _fsRouteType: "pathless_layout"
164
+ };
165
+ if (node.children !== void 0) {
166
+ const children2 = await getRouteNodesRecursive(
167
+ tsrConfig,
168
+ root,
169
+ fullDir,
170
+ node.children,
171
+ routeNode
172
+ );
173
+ routeNode.children = children2;
174
+ }
175
+ return routeNode;
176
+ }
177
+ }
178
+ })
179
+ );
180
+ return children.flat();
181
+ }
182
+ export {
183
+ getRouteNodes,
184
+ getRouteNodesRecursive
185
+ };
186
+ //# sourceMappingURL=getRouteNodes.js.map
@@ -0,0 +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: 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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"}
@@ -0,0 +1 @@
1
+ export declare function loadConfigFile(filePath: string): Promise<any>;
@@ -0,0 +1,11 @@
1
+ import { pathToFileURL } from "node:url";
2
+ import { tsImport } from "tsx/esm/api";
3
+ async function loadConfigFile(filePath) {
4
+ const fileURL = pathToFileURL(filePath).href;
5
+ const loaded = await tsImport(fileURL, "./");
6
+ return loaded;
7
+ }
8
+ export {
9
+ loadConfigFile
10
+ };
11
+ //# sourceMappingURL=loadConfigFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadConfigFile.js","sources":["../../../../src/filesystem/virtual/loadConfigFile.ts"],"sourcesContent":["import { pathToFileURL } from 'node:url'\nimport { tsImport } from 'tsx/esm/api'\n\nexport async function loadConfigFile(filePath: string) {\n const fileURL = pathToFileURL(filePath).href\n const loaded = await tsImport(fileURL, './')\n return loaded\n}\n"],"names":[],"mappings":";;AAGA,eAAsB,eAAe,UAAkB;AAC/C,QAAA,UAAU,cAAc,QAAQ,EAAE;AACxC,QAAM,SAAS,MAAM,SAAS,SAAS,IAAI;AACpC,SAAA;AACT;"}
@@ -1,38 +1,2 @@
1
1
  import { Config } from './config.js';
2
- export declare const rootPathId = "__root";
3
- export type RouteNode = {
4
- filePath: string;
5
- fullPath: string;
6
- variableName: string;
7
- routePath?: string;
8
- cleanedPath?: string;
9
- path?: string;
10
- isNonPath?: boolean;
11
- isNonLayout?: boolean;
12
- isLayout?: boolean;
13
- isVirtualParentRequired?: boolean;
14
- isVirtualParentRoute?: boolean;
15
- isRoute?: boolean;
16
- isLoader?: boolean;
17
- isComponent?: boolean;
18
- isErrorComponent?: boolean;
19
- isPendingComponent?: boolean;
20
- isVirtual?: boolean;
21
- isLazy?: boolean;
22
- isRoot?: boolean;
23
- children?: RouteNode[];
24
- parent?: RouteNode;
25
- };
26
- export declare function generator(config: Config): Promise<void>;
27
- export declare function removeExt(d: string, keepExtension?: boolean): string;
28
- export declare function multiSortBy<T>(arr: T[], accessors?: ((item: T) => any)[]): T[];
29
- /**
30
- * Removes the last segment from a given path. Segments are considered to be separated by a '/'.
31
- *
32
- * @param {string} path - The path from which to remove the last segment. Defaults to '/'.
33
- * @returns {string} The path with the last segment removed.
34
- * @example
35
- * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'
36
- */
37
- export declare function removeLastSegmentFromPath(path?: string): string;
38
- export declare function hasParentRoute(routes: RouteNode[], node: RouteNode, routePathToCheck: string | undefined): RouteNode | null;
2
+ export declare function generator(config: Config, root: string): Promise<void>;