@tanstack/router-generator 1.146.2 → 1.149.0
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.
- package/dist/cjs/config.cjs +29 -6
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.cts +94 -12
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +50 -27
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +12 -3
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +12 -5
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +3 -2
- package/dist/cjs/generator.cjs +32 -7
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/generator.d.cts +20 -2
- package/dist/cjs/utils.cjs +47 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +6 -1
- package/dist/esm/config.d.ts +94 -12
- package/dist/esm/config.js +29 -6
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.d.ts +12 -3
- package/dist/esm/filesystem/physical/getRouteNodes.js +51 -28
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
- package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +3 -2
- package/dist/esm/filesystem/virtual/getRouteNodes.js +12 -5
- package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
- package/dist/esm/generator.d.ts +20 -2
- package/dist/esm/generator.js +33 -8
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/utils.d.ts +6 -1
- package/dist/esm/utils.js +47 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/config.ts +58 -6
- package/src/filesystem/physical/getRouteNodes.ts +105 -43
- package/src/filesystem/virtual/getRouteNodes.ts +12 -2
- package/src/generator.ts +59 -9
- package/src/utils.ts +73 -1
package/dist/cjs/config.cjs
CHANGED
|
@@ -4,6 +4,15 @@ const path = require("node:path");
|
|
|
4
4
|
const node_fs = require("node:fs");
|
|
5
5
|
const zod = require("zod");
|
|
6
6
|
const config = require("./filesystem/virtual/config.cjs");
|
|
7
|
+
const tokenJsonRegexSchema = zod.z.object({
|
|
8
|
+
regex: zod.z.string(),
|
|
9
|
+
flags: zod.z.string().optional()
|
|
10
|
+
});
|
|
11
|
+
const tokenMatcherSchema = zod.z.union([
|
|
12
|
+
zod.z.string(),
|
|
13
|
+
zod.z.instanceof(RegExp),
|
|
14
|
+
tokenJsonRegexSchema
|
|
15
|
+
]);
|
|
7
16
|
const baseConfigSchema = zod.z.object({
|
|
8
17
|
target: zod.z.enum(["react", "solid", "vue"]).optional().default("react"),
|
|
9
18
|
virtualRouteConfig: config.virtualRootRouteSchema.or(zod.z.string()).optional(),
|
|
@@ -19,8 +28,8 @@ const baseConfigSchema = zod.z.object({
|
|
|
19
28
|
"// @ts-nocheck",
|
|
20
29
|
"// noinspection JSUnusedGlobalSymbols"
|
|
21
30
|
]),
|
|
22
|
-
indexToken:
|
|
23
|
-
routeToken:
|
|
31
|
+
indexToken: tokenMatcherSchema.optional().default("index"),
|
|
32
|
+
routeToken: tokenMatcherSchema.optional().default("route"),
|
|
24
33
|
pathParamsAllowedCharacters: zod.z.array(zod.z.enum([";", ":", "@", "&", "=", "+", "$", ","])).optional()
|
|
25
34
|
});
|
|
26
35
|
const configSchema = baseConfigSchema.extend({
|
|
@@ -57,10 +66,12 @@ function getConfig(inlineConfig = {}, configDirectory) {
|
|
|
57
66
|
const exists = node_fs.existsSync(configFilePathJson);
|
|
58
67
|
let config2;
|
|
59
68
|
if (exists) {
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
const fileConfigRaw = JSON.parse(node_fs.readFileSync(configFilePathJson, "utf-8"));
|
|
70
|
+
const merged = {
|
|
71
|
+
...fileConfigRaw,
|
|
62
72
|
...inlineConfig
|
|
63
|
-
}
|
|
73
|
+
};
|
|
74
|
+
config2 = configSchema.parse(merged);
|
|
64
75
|
} else {
|
|
65
76
|
config2 = configSchema.parse(inlineConfig);
|
|
66
77
|
}
|
|
@@ -123,7 +134,7 @@ ERROR: The "experimental.enableCodeSplitting" flag has been made stable and is n
|
|
|
123
134
|
console.error(message);
|
|
124
135
|
throw new Error(message);
|
|
125
136
|
}
|
|
126
|
-
if (config2.indexToken
|
|
137
|
+
if (areTokensEqual(config2.indexToken, config2.routeToken)) {
|
|
127
138
|
throw new Error(
|
|
128
139
|
`The "indexToken" and "routeToken" options must be different.`
|
|
129
140
|
);
|
|
@@ -135,6 +146,18 @@ ERROR: The "experimental.enableCodeSplitting" flag has been made stable and is n
|
|
|
135
146
|
}
|
|
136
147
|
return config2;
|
|
137
148
|
}
|
|
149
|
+
function areTokensEqual(a, b) {
|
|
150
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
151
|
+
return a === b;
|
|
152
|
+
}
|
|
153
|
+
if (a instanceof RegExp && b instanceof RegExp) {
|
|
154
|
+
return a.source === b.source && a.flags === b.flags;
|
|
155
|
+
}
|
|
156
|
+
if (typeof a === "object" && "regex" in a && typeof b === "object" && "regex" in b) {
|
|
157
|
+
return a.regex === b.regex && (a.flags ?? "") === (b.flags ?? "");
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
138
161
|
exports.baseConfigSchema = baseConfigSchema;
|
|
139
162
|
exports.configSchema = configSchema;
|
|
140
163
|
exports.getConfig = getConfig;
|
package/dist/cjs/config.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","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'\nimport type { GeneratorPlugin } from './plugin/types'\n\nexport const baseConfigSchema = z.object({\n target: z.enum(['react', 'solid', 'vue']).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 enableRouteTreeFormatting: z.boolean().optional().default(true),\n routeTreeFileFooter: z\n .union([\n z.array(z.string()).optional().default([]),\n z.function().returns(z.array(z.string())),\n ])\n .optional(),\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 plugins: z.array(z.custom<GeneratorPlugin>()).optional(),\n tmpDir: z.string().optional().default(''),\n importRoutesUsingAbsolutePaths: z.boolean().optional().default(false),\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 const resolveTmpDir = (dir: string | Array<string>) => {\n if (Array.isArray(dir)) {\n dir = path.join(...dir)\n }\n if (!path.isAbsolute(dir)) {\n dir = path.resolve(process.cwd(), dir)\n }\n return dir\n }\n\n if (config.tmpDir) {\n config.tmpDir = resolveTmpDir(config.tmpDir)\n } else if (process.env.TSR_TMP_DIR) {\n config.tmpDir = resolveTmpDir(process.env.TSR_TMP_DIR)\n } else {\n config.tmpDir = resolveTmpDir(['.tanstack', 'tmp'])\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":["z","virtualRootRouteSchema","existsSync","config","readFileSync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.cjs","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'\nimport type { GeneratorPlugin } from './plugin/types'\n\nconst tokenJsonRegexSchema = z.object({\n regex: z.string(),\n flags: z.string().optional(),\n})\n\nconst tokenMatcherSchema = z.union([\n z.string(),\n z.instanceof(RegExp),\n tokenJsonRegexSchema,\n])\n\nexport type TokenMatcherJson = string | z.infer<typeof tokenJsonRegexSchema>\n\nexport type TokenMatcher = z.infer<typeof tokenMatcherSchema>\n\nexport const baseConfigSchema = z.object({\n target: z.enum(['react', 'solid', 'vue']).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: tokenMatcherSchema.optional().default('index'),\n routeToken: tokenMatcherSchema.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 enableRouteTreeFormatting: z.boolean().optional().default(true),\n routeTreeFileFooter: z\n .union([\n z.array(z.string()).optional().default([]),\n z.function().returns(z.array(z.string())),\n ])\n .optional(),\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 plugins: z.array(z.custom<GeneratorPlugin>()).optional(),\n tmpDir: z.string().optional().default(''),\n importRoutesUsingAbsolutePaths: z.boolean().optional().default(false),\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 // Parse file config (allows JSON regex-object form)\n const fileConfigRaw = JSON.parse(readFileSync(configFilePathJson, 'utf-8'))\n\n // Merge raw configs (inline overrides file), then parse once to apply defaults\n // This ensures file config values aren't overwritten by inline defaults\n const merged = {\n ...fileConfigRaw,\n ...inlineConfig,\n }\n config = configSchema.parse(merged)\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 const resolveTmpDir = (dir: string | Array<string>) => {\n if (Array.isArray(dir)) {\n dir = path.join(...dir)\n }\n if (!path.isAbsolute(dir)) {\n dir = path.resolve(process.cwd(), dir)\n }\n return dir\n }\n\n if (config.tmpDir) {\n config.tmpDir = resolveTmpDir(config.tmpDir)\n } else if (process.env.TSR_TMP_DIR) {\n config.tmpDir = resolveTmpDir(process.env.TSR_TMP_DIR)\n } else {\n config.tmpDir = resolveTmpDir(['.tanstack', 'tmp'])\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 // Check that indexToken and routeToken are not identical\n // Works for strings, RegExp, and JSON regex objects\n if (areTokensEqual(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\n/**\n * Compares two token matchers for equality.\n * Handles strings, RegExp instances, and JSON regex objects.\n */\nfunction areTokensEqual(a: TokenMatcher, b: TokenMatcher): boolean {\n // Both strings\n if (typeof a === 'string' && typeof b === 'string') {\n return a === b\n }\n\n // Both RegExp instances\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source === b.source && a.flags === b.flags\n }\n\n // Both JSON regex objects\n if (\n typeof a === 'object' &&\n 'regex' in a &&\n typeof b === 'object' &&\n 'regex' in b\n ) {\n return a.regex === b.regex && (a.flags ?? '') === (b.flags ?? '')\n }\n\n // Mixed types - not equal\n return false\n}\n"],"names":["z","virtualRootRouteSchema","existsSync","config","readFileSync"],"mappings":"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"}
|
package/dist/cjs/config.d.cts
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { GeneratorPlugin } from './plugin/types.cjs';
|
|
3
|
+
declare const tokenJsonRegexSchema: z.ZodObject<{
|
|
4
|
+
regex: z.ZodString;
|
|
5
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
regex: string;
|
|
8
|
+
flags?: string | undefined;
|
|
9
|
+
}, {
|
|
10
|
+
regex: string;
|
|
11
|
+
flags?: string | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
declare const tokenMatcherSchema: z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>, z.ZodObject<{
|
|
14
|
+
regex: z.ZodString;
|
|
15
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
regex: string;
|
|
18
|
+
flags?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
regex: string;
|
|
21
|
+
flags?: string | undefined;
|
|
22
|
+
}>]>;
|
|
23
|
+
export type TokenMatcherJson = string | z.infer<typeof tokenJsonRegexSchema>;
|
|
24
|
+
export type TokenMatcher = z.infer<typeof tokenMatcherSchema>;
|
|
3
25
|
export declare const baseConfigSchema: z.ZodObject<{
|
|
4
26
|
target: z.ZodDefault<z.ZodOptional<z.ZodEnum<["react", "solid", "vue"]>>>;
|
|
5
27
|
virtualRouteConfig: z.ZodOptional<z.ZodUnion<[z.ZodType<import('@tanstack/virtual-file-routes').VirtualRootRoute, z.ZodTypeDef, import('@tanstack/virtual-file-routes').VirtualRootRoute>, z.ZodString]>>;
|
|
@@ -11,8 +33,26 @@ export declare const baseConfigSchema: z.ZodObject<{
|
|
|
11
33
|
semicolons: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
34
|
disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
13
35
|
routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
14
|
-
indexToken: z.ZodDefault<z.ZodOptional<z.ZodString
|
|
15
|
-
|
|
36
|
+
indexToken: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>, z.ZodObject<{
|
|
37
|
+
regex: z.ZodString;
|
|
38
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
39
|
+
}, "strip", z.ZodTypeAny, {
|
|
40
|
+
regex: string;
|
|
41
|
+
flags?: string | undefined;
|
|
42
|
+
}, {
|
|
43
|
+
regex: string;
|
|
44
|
+
flags?: string | undefined;
|
|
45
|
+
}>]>>>;
|
|
46
|
+
routeToken: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>, z.ZodObject<{
|
|
47
|
+
regex: z.ZodString;
|
|
48
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
regex: string;
|
|
51
|
+
flags?: string | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
regex: string;
|
|
54
|
+
flags?: string | undefined;
|
|
55
|
+
}>]>>>;
|
|
16
56
|
pathParamsAllowedCharacters: z.ZodOptional<z.ZodArray<z.ZodEnum<[";", ":", "@", "&", "=", "+", "$", ","]>, "many">>;
|
|
17
57
|
}, "strip", z.ZodTypeAny, {
|
|
18
58
|
target: "vue" | "react" | "solid";
|
|
@@ -22,8 +62,14 @@ export declare const baseConfigSchema: z.ZodObject<{
|
|
|
22
62
|
semicolons: boolean;
|
|
23
63
|
disableLogging: boolean;
|
|
24
64
|
routeTreeFileHeader: string[];
|
|
25
|
-
indexToken: string
|
|
26
|
-
|
|
65
|
+
indexToken: string | RegExp | {
|
|
66
|
+
regex: string;
|
|
67
|
+
flags?: string | undefined;
|
|
68
|
+
};
|
|
69
|
+
routeToken: string | RegExp | {
|
|
70
|
+
regex: string;
|
|
71
|
+
flags?: string | undefined;
|
|
72
|
+
};
|
|
27
73
|
virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
|
|
28
74
|
routeFilePrefix?: string | undefined;
|
|
29
75
|
routeFileIgnorePattern?: string | undefined;
|
|
@@ -39,8 +85,14 @@ export declare const baseConfigSchema: z.ZodObject<{
|
|
|
39
85
|
semicolons?: boolean | undefined;
|
|
40
86
|
disableLogging?: boolean | undefined;
|
|
41
87
|
routeTreeFileHeader?: string[] | undefined;
|
|
42
|
-
indexToken?: string |
|
|
43
|
-
|
|
88
|
+
indexToken?: string | RegExp | {
|
|
89
|
+
regex: string;
|
|
90
|
+
flags?: string | undefined;
|
|
91
|
+
} | undefined;
|
|
92
|
+
routeToken?: string | RegExp | {
|
|
93
|
+
regex: string;
|
|
94
|
+
flags?: string | undefined;
|
|
95
|
+
} | undefined;
|
|
44
96
|
pathParamsAllowedCharacters?: (":" | "$" | ";" | "@" | "&" | "=" | "+" | ",")[] | undefined;
|
|
45
97
|
}>;
|
|
46
98
|
export type BaseConfig = z.infer<typeof baseConfigSchema>;
|
|
@@ -55,8 +107,26 @@ export declare const configSchema: z.ZodObject<{
|
|
|
55
107
|
semicolons: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
56
108
|
disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
57
109
|
routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
58
|
-
indexToken: z.ZodDefault<z.ZodOptional<z.ZodString
|
|
59
|
-
|
|
110
|
+
indexToken: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>, z.ZodObject<{
|
|
111
|
+
regex: z.ZodString;
|
|
112
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
113
|
+
}, "strip", z.ZodTypeAny, {
|
|
114
|
+
regex: string;
|
|
115
|
+
flags?: string | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
regex: string;
|
|
118
|
+
flags?: string | undefined;
|
|
119
|
+
}>]>>>;
|
|
120
|
+
routeToken: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>, z.ZodObject<{
|
|
121
|
+
regex: z.ZodString;
|
|
122
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
123
|
+
}, "strip", z.ZodTypeAny, {
|
|
124
|
+
regex: string;
|
|
125
|
+
flags?: string | undefined;
|
|
126
|
+
}, {
|
|
127
|
+
regex: string;
|
|
128
|
+
flags?: string | undefined;
|
|
129
|
+
}>]>>>;
|
|
60
130
|
pathParamsAllowedCharacters: z.ZodOptional<z.ZodArray<z.ZodEnum<[";", ":", "@", "&", "=", "+", "$", ","]>, "many">>;
|
|
61
131
|
} & {
|
|
62
132
|
generatedRouteTree: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
@@ -94,8 +164,14 @@ export declare const configSchema: z.ZodObject<{
|
|
|
94
164
|
semicolons: boolean;
|
|
95
165
|
disableLogging: boolean;
|
|
96
166
|
routeTreeFileHeader: string[];
|
|
97
|
-
indexToken: string
|
|
98
|
-
|
|
167
|
+
indexToken: string | RegExp | {
|
|
168
|
+
regex: string;
|
|
169
|
+
flags?: string | undefined;
|
|
170
|
+
};
|
|
171
|
+
routeToken: string | RegExp | {
|
|
172
|
+
regex: string;
|
|
173
|
+
flags?: string | undefined;
|
|
174
|
+
};
|
|
99
175
|
generatedRouteTree: string;
|
|
100
176
|
disableTypes: boolean;
|
|
101
177
|
addExtensions: boolean;
|
|
@@ -129,8 +205,14 @@ export declare const configSchema: z.ZodObject<{
|
|
|
129
205
|
semicolons?: boolean | undefined;
|
|
130
206
|
disableLogging?: boolean | undefined;
|
|
131
207
|
routeTreeFileHeader?: string[] | undefined;
|
|
132
|
-
indexToken?: string |
|
|
133
|
-
|
|
208
|
+
indexToken?: string | RegExp | {
|
|
209
|
+
regex: string;
|
|
210
|
+
flags?: string | undefined;
|
|
211
|
+
} | undefined;
|
|
212
|
+
routeToken?: string | RegExp | {
|
|
213
|
+
regex: string;
|
|
214
|
+
flags?: string | undefined;
|
|
215
|
+
} | undefined;
|
|
134
216
|
pathParamsAllowedCharacters?: (":" | "$" | ";" | "@" | "&" | "=" | "+" | ",")[] | undefined;
|
|
135
217
|
generatedRouteTree?: string | undefined;
|
|
136
218
|
disableTypes?: boolean | undefined;
|
|
@@ -29,7 +29,7 @@ const virtualConfigFileRegExp = /__virtual\.[mc]?[jt]s$/;
|
|
|
29
29
|
function isVirtualConfigFile(fileName) {
|
|
30
30
|
return virtualConfigFileRegExp.test(fileName);
|
|
31
31
|
}
|
|
32
|
-
async function getRouteNodes(config, root) {
|
|
32
|
+
async function getRouteNodes(config, root, tokenRegexes) {
|
|
33
33
|
const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } = config;
|
|
34
34
|
const logger$1 = logger.logging({ disabled: config.disableLogging });
|
|
35
35
|
const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? "", "g");
|
|
@@ -77,7 +77,8 @@ async function getRouteNodes(config, root) {
|
|
|
77
77
|
routesDirectory: fullDir,
|
|
78
78
|
virtualRouteConfig: dummyRoot
|
|
79
79
|
},
|
|
80
|
-
root
|
|
80
|
+
root,
|
|
81
|
+
tokenRegexes
|
|
81
82
|
);
|
|
82
83
|
allPhysicalDirectories.push(...physicalDirectories);
|
|
83
84
|
virtualRouteNodes.forEach((node) => {
|
|
@@ -122,7 +123,7 @@ async function getRouteNodes(config, root) {
|
|
|
122
123
|
logger$1.error(`ERROR: ${errorMessage}`);
|
|
123
124
|
throw new Error(errorMessage);
|
|
124
125
|
}
|
|
125
|
-
const meta = getRouteMeta(routePath, originalRoutePath,
|
|
126
|
+
const meta = getRouteMeta(routePath, originalRoutePath, tokenRegexes);
|
|
126
127
|
const variableName = meta.variableName;
|
|
127
128
|
let routeType = meta.fsRouteType;
|
|
128
129
|
if (routeType === "lazy") {
|
|
@@ -133,7 +134,7 @@ async function getRouteNodes(config, root) {
|
|
|
133
134
|
routePath,
|
|
134
135
|
originalRoutePath,
|
|
135
136
|
routeType,
|
|
136
|
-
|
|
137
|
+
tokenRegexes
|
|
137
138
|
)) {
|
|
138
139
|
routeType = "pathless_layout";
|
|
139
140
|
}
|
|
@@ -155,42 +156,58 @@ async function getRouteNodes(config, root) {
|
|
|
155
156
|
}
|
|
156
157
|
const originalSegments = originalRoutePath.split("/").filter(Boolean);
|
|
157
158
|
const lastOriginalSegmentForSuffix = originalSegments[originalSegments.length - 1] || "";
|
|
159
|
+
const { routeTokenSegmentRegex, indexTokenSegmentRegex } = tokenRegexes;
|
|
158
160
|
const specialSuffixes = [
|
|
159
161
|
"component",
|
|
160
162
|
"errorComponent",
|
|
161
163
|
"notFoundComponent",
|
|
162
164
|
"pendingComponent",
|
|
163
165
|
"loader",
|
|
164
|
-
config.routeToken,
|
|
165
166
|
"lazy"
|
|
166
167
|
];
|
|
168
|
+
const routePathSegments = routePath.split("/").filter(Boolean);
|
|
169
|
+
const lastRouteSegment = routePathSegments[routePathSegments.length - 1] || "";
|
|
167
170
|
const suffixToStrip = specialSuffixes.find((suffix) => {
|
|
168
171
|
const endsWithSuffix = routePath.endsWith(`/${suffix}`);
|
|
169
|
-
const isEscaped = lastOriginalSegmentForSuffix ===
|
|
172
|
+
const isEscaped = lastOriginalSegmentForSuffix.startsWith("[") && lastOriginalSegmentForSuffix.endsWith("]") && utils.unwrapBracketWrappedSegment(lastOriginalSegmentForSuffix) === suffix;
|
|
170
173
|
return endsWithSuffix && !isEscaped;
|
|
171
174
|
});
|
|
172
|
-
|
|
173
|
-
|
|
175
|
+
const routeTokenCandidate = utils.unwrapBracketWrappedSegment(
|
|
176
|
+
lastOriginalSegmentForSuffix
|
|
177
|
+
);
|
|
178
|
+
const isRouteTokenEscaped = lastOriginalSegmentForSuffix !== routeTokenCandidate && routeTokenSegmentRegex.test(routeTokenCandidate);
|
|
179
|
+
const shouldStripRouteToken = routeTokenSegmentRegex.test(lastRouteSegment) && !isRouteTokenEscaped;
|
|
180
|
+
if (suffixToStrip || shouldStripRouteToken) {
|
|
181
|
+
const stripSegment = suffixToStrip ?? lastRouteSegment;
|
|
182
|
+
routePath = routePath.replace(new RegExp(`/${stripSegment}$`), "");
|
|
174
183
|
originalRoutePath = originalRoutePath.replace(
|
|
175
|
-
new RegExp(`/${
|
|
184
|
+
new RegExp(`/${stripSegment}$`),
|
|
176
185
|
""
|
|
177
186
|
);
|
|
178
187
|
}
|
|
179
188
|
const lastOriginalSegment = originalRoutePath.split("/").filter(Boolean).pop() || "";
|
|
180
|
-
const
|
|
189
|
+
const indexTokenCandidate = utils.unwrapBracketWrappedSegment(lastOriginalSegment);
|
|
190
|
+
const isIndexEscaped = lastOriginalSegment !== indexTokenCandidate && indexTokenSegmentRegex.test(indexTokenCandidate);
|
|
181
191
|
if (!isIndexEscaped) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
const updatedRouteSegments = routePath.split("/").filter(Boolean);
|
|
193
|
+
const updatedLastRouteSegment = updatedRouteSegments[updatedRouteSegments.length - 1] || "";
|
|
194
|
+
if (indexTokenSegmentRegex.test(updatedLastRouteSegment)) {
|
|
195
|
+
if (routePathSegments.length === 1) {
|
|
196
|
+
routePath = "/";
|
|
197
|
+
}
|
|
198
|
+
if (lastOriginalSegment === updatedLastRouteSegment) {
|
|
199
|
+
originalRoutePath = "/";
|
|
200
|
+
}
|
|
201
|
+
const isLayoutRoute = routeType === "layout";
|
|
202
|
+
routePath = routePath.replace(
|
|
203
|
+
new RegExp(`/${updatedLastRouteSegment}$`),
|
|
204
|
+
"/"
|
|
205
|
+
) || (isLayoutRoute ? "" : "/");
|
|
206
|
+
originalRoutePath = originalRoutePath.replace(
|
|
207
|
+
new RegExp(`/${indexTokenCandidate}$`),
|
|
208
|
+
"/"
|
|
209
|
+
) || (isLayoutRoute ? "" : "/");
|
|
187
210
|
}
|
|
188
|
-
const isLayoutRoute = routeType === "layout";
|
|
189
|
-
routePath = routePath.replace(new RegExp(`/${config.indexToken}$`), "/") || (isLayoutRoute ? "" : "/");
|
|
190
|
-
originalRoutePath = originalRoutePath.replace(
|
|
191
|
-
new RegExp(`/${config.indexToken}$`),
|
|
192
|
-
"/"
|
|
193
|
-
) || (isLayoutRoute ? "" : "/");
|
|
194
211
|
}
|
|
195
212
|
routeNodes.push({
|
|
196
213
|
filePath,
|
|
@@ -226,14 +243,19 @@ async function getRouteNodes(config, root) {
|
|
|
226
243
|
physicalDirectories: allPhysicalDirectories
|
|
227
244
|
};
|
|
228
245
|
}
|
|
229
|
-
function getRouteMeta(routePath, originalRoutePath,
|
|
246
|
+
function getRouteMeta(routePath, originalRoutePath, tokenRegexes) {
|
|
230
247
|
let fsRouteType = "static";
|
|
231
248
|
const originalSegments = originalRoutePath.split("/").filter(Boolean);
|
|
232
249
|
const lastOriginalSegment = originalSegments[originalSegments.length - 1] || "";
|
|
250
|
+
const { routeTokenSegmentRegex } = tokenRegexes;
|
|
233
251
|
const isSuffixEscaped = (suffix) => {
|
|
234
|
-
return lastOriginalSegment ===
|
|
252
|
+
return lastOriginalSegment.startsWith("[") && lastOriginalSegment.endsWith("]") && utils.unwrapBracketWrappedSegment(lastOriginalSegment) === suffix;
|
|
235
253
|
};
|
|
236
|
-
|
|
254
|
+
const routeSegments = routePath.split("/").filter(Boolean);
|
|
255
|
+
const lastRouteSegment = routeSegments[routeSegments.length - 1] || "";
|
|
256
|
+
const routeTokenCandidate = utils.unwrapBracketWrappedSegment(lastOriginalSegment);
|
|
257
|
+
const isRouteTokenEscaped = lastOriginalSegment !== routeTokenCandidate && routeTokenSegmentRegex.test(routeTokenCandidate);
|
|
258
|
+
if (routeTokenSegmentRegex.test(lastRouteSegment) && !isRouteTokenEscaped) {
|
|
237
259
|
fsRouteType = "layout";
|
|
238
260
|
} else if (routePath.endsWith("/lazy") && !isSuffixEscaped("lazy")) {
|
|
239
261
|
fsRouteType = "lazy";
|
|
@@ -251,7 +273,7 @@ function getRouteMeta(routePath, originalRoutePath, config) {
|
|
|
251
273
|
const variableName = utils.routePathToVariable(routePath);
|
|
252
274
|
return { fsRouteType, variableName };
|
|
253
275
|
}
|
|
254
|
-
function isValidPathlessLayoutRoute(normalizedRoutePath, originalRoutePath, routeType,
|
|
276
|
+
function isValidPathlessLayoutRoute(normalizedRoutePath, originalRoutePath, routeType, tokenRegexes) {
|
|
255
277
|
if (routeType === "lazy") {
|
|
256
278
|
return false;
|
|
257
279
|
}
|
|
@@ -267,7 +289,8 @@ function isValidPathlessLayoutRoute(normalizedRoutePath, originalRoutePath, rout
|
|
|
267
289
|
if (lastRouteSegment === rootPathId.rootPathId) {
|
|
268
290
|
return false;
|
|
269
291
|
}
|
|
270
|
-
|
|
292
|
+
const { routeTokenSegmentRegex, indexTokenSegmentRegex } = tokenRegexes;
|
|
293
|
+
if (routeTokenSegmentRegex.test(lastRouteSegment) && typeof secondToLastRouteSegment === "string" && typeof secondToLastOriginalSegment === "string") {
|
|
271
294
|
if (utils.hasEscapedLeadingUnderscore(secondToLastOriginalSegment)) {
|
|
272
295
|
return false;
|
|
273
296
|
}
|
|
@@ -276,7 +299,7 @@ function isValidPathlessLayoutRoute(normalizedRoutePath, originalRoutePath, rout
|
|
|
276
299
|
if (utils.hasEscapedLeadingUnderscore(lastOriginalSegment)) {
|
|
277
300
|
return false;
|
|
278
301
|
}
|
|
279
|
-
return lastRouteSegment
|
|
302
|
+
return !indexTokenSegmentRegex.test(lastRouteSegment) && !routeTokenSegmentRegex.test(lastRouteSegment) && lastRouteSegment.startsWith("_");
|
|
280
303
|
}
|
|
281
304
|
exports.getRouteMeta = getRouteMeta;
|
|
282
305
|
exports.getRouteNodes = getRouteNodes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRouteNodes.cjs","sources":["../../../../src/filesystem/physical/getRouteNodes.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport {\n determineInitialRoutePath,\n hasEscapedLeadingUnderscore,\n removeExt,\n replaceBackslash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesVirtual } from '../virtual/getRouteNodes'\nimport { loadConfigFile } from '../virtual/loadConfigFile'\nimport { logging } from '../../logger'\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|vue)/\n\nconst virtualConfigFileRegExp = /__virtual\\.[mc]?[jt]s$/\nexport function isVirtualConfigFile(fileName: string): boolean {\n return virtualConfigFileRegExp.test(fileName)\n}\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\n const logger = logging({ disabled: config.disableLogging })\n const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')\n\n const routeNodes: Array<RouteNode> = []\n const allPhysicalDirectories: Array<string> = []\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 if (routeFileIgnorePattern) {\n return (\n d.name.startsWith(routeFilePrefix) &&\n !d.name.match(routeFileIgnoreRegExp)\n )\n }\n\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() && isVirtualConfigFile(dirent.name)\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, physicalDirectories } =\n await getRouteNodesVirtual(\n {\n ...config,\n routesDirectory: fullDir,\n virtualRouteConfig: dummyRoot,\n },\n root,\n )\n allPhysicalDirectories.push(...physicalDirectories)\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 // Keep originalRoutePath aligned with routePath for escape detection\n if (node.originalRoutePath) {\n node.originalRoutePath = `/${dir}${node.originalRoutePath}`\n }\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 = replaceBackslash(path.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|vue)$/)) {\n const filePath = replaceBackslash(path.join(dir, dirent.name))\n const filePathNoExt = removeExt(filePath)\n const {\n routePath: initialRoutePath,\n originalRoutePath: initialOriginalRoutePath,\n } = determineInitialRoutePath(filePathNoExt)\n\n let routePath = initialRoutePath\n let originalRoutePath = initialOriginalRoutePath\n\n if (routeFilePrefix) {\n routePath = routePath.replaceAll(routeFilePrefix, '')\n originalRoutePath = originalRoutePath.replaceAll(\n routeFilePrefix,\n '',\n )\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, originalRoutePath, config)\n const variableName = meta.variableName\n let routeType: FsRouteType = meta.fsRouteType\n\n if (routeType === 'lazy') {\n routePath = routePath.replace(/\\/lazy$/, '')\n originalRoutePath = originalRoutePath.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 (\n isValidPathlessLayoutRoute(\n routePath,\n originalRoutePath,\n routeType,\n config,\n )\n ) {\n routeType = 'pathless_layout'\n }\n\n // Only show deprecation warning for .tsx/.ts files, not .vue files\n // Vue files using .component.vue is the Vue-native way\n const isVueFile = filePath.endsWith('.vue')\n if (!isVueFile) {\n ;(\n [\n ['component', 'component'],\n ['errorComponent', 'errorComponent'],\n ['notFoundComponent', 'notFoundComponent'],\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\n // Get the last segment of originalRoutePath to check for escaping\n const originalSegments = originalRoutePath.split('/').filter(Boolean)\n const lastOriginalSegmentForSuffix =\n originalSegments[originalSegments.length - 1] || ''\n\n // List of special suffixes that can be escaped\n const specialSuffixes = [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n config.routeToken,\n 'lazy',\n ]\n\n // Only strip the suffix if it wasn't escaped (not wrapped in brackets)\n const suffixToStrip = specialSuffixes.find((suffix) => {\n const endsWithSuffix = routePath.endsWith(`/${suffix}`)\n const isEscaped = lastOriginalSegmentForSuffix === `[${suffix}]`\n return endsWithSuffix && !isEscaped\n })\n\n if (suffixToStrip) {\n routePath = routePath.replace(new RegExp(`/${suffixToStrip}$`), '')\n originalRoutePath = originalRoutePath.replace(\n new RegExp(`/${suffixToStrip}$`),\n '',\n )\n }\n\n // Check if the index token should be treated specially or as a literal path\n // If it's escaped (wrapped in brackets in originalRoutePath), it should be literal\n const lastOriginalSegment =\n originalRoutePath.split('/').filter(Boolean).pop() || ''\n const isIndexEscaped =\n lastOriginalSegment === `[${config.indexToken}]`\n\n if (!isIndexEscaped) {\n if (routePath === config.indexToken) {\n routePath = '/'\n }\n\n if (originalRoutePath === config.indexToken) {\n originalRoutePath = '/'\n }\n\n // For layout routes, don't use '/' fallback - an empty path means\n // \"layout for the parent path\" which is important for physical() mounts\n // where route.tsx at root should have empty path, not '/'\n const isLayoutRoute = routeType === 'layout'\n\n routePath =\n routePath.replace(new RegExp(`/${config.indexToken}$`), '/') ||\n (isLayoutRoute ? '' : '/')\n\n originalRoutePath =\n originalRoutePath.replace(\n new RegExp(`/${config.indexToken}$`),\n '/',\n ) || (isLayoutRoute ? '' : '/')\n }\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n _fsRouteType: routeType,\n originalRoutePath,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n // Find the root route node - prefer the actual route file over component/loader files\n const rootRouteNode =\n routeNodes.find(\n (d) =>\n d.routePath === `/${rootPathId}` &&\n ![\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType),\n ) ?? routeNodes.find((d) => d.routePath === `/${rootPathId}`)\n if (rootRouteNode) {\n rootRouteNode._fsRouteType = '__root'\n rootRouteNode.variableName = 'root'\n }\n\n return {\n rootRouteNode,\n routeNodes,\n physicalDirectories: allPhysicalDirectories,\n }\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 (with brackets removed).\n * @param originalRoutePath - The original route path (may contain brackets for escaped content).\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 originalRoutePath: 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 | 'notFoundComponent'\n >\n variableName: string\n} {\n let fsRouteType: FsRouteType = 'static'\n\n // Get the last segment from the original path to check for escaping\n const originalSegments = originalRoutePath.split('/').filter(Boolean)\n const lastOriginalSegment =\n originalSegments[originalSegments.length - 1] || ''\n\n // Helper to check if a specific suffix is escaped\n const isSuffixEscaped = (suffix: string): boolean => {\n return lastOriginalSegment === `[${suffix}]`\n }\n\n if (\n routePath.endsWith(`/${config.routeToken}`) &&\n !isSuffixEscaped(config.routeToken)\n ) {\n // layout routes, i.e `/foo/route.tsx` or `/foo/_layout/route.tsx`\n fsRouteType = 'layout'\n } else if (routePath.endsWith('/lazy') && !isSuffixEscaped('lazy')) {\n // lazy routes, i.e. `/foo.lazy.tsx`\n fsRouteType = 'lazy'\n } else if (routePath.endsWith('/loader') && !isSuffixEscaped('loader')) {\n // loader routes, i.e. `/foo.loader.tsx`\n fsRouteType = 'loader'\n } else if (\n routePath.endsWith('/component') &&\n !isSuffixEscaped('component')\n ) {\n // component routes, i.e. `/foo.component.tsx`\n fsRouteType = 'component'\n } else if (\n routePath.endsWith('/pendingComponent') &&\n !isSuffixEscaped('pendingComponent')\n ) {\n // pending component routes, i.e. `/foo.pendingComponent.tsx`\n fsRouteType = 'pendingComponent'\n } else if (\n routePath.endsWith('/errorComponent') &&\n !isSuffixEscaped('errorComponent')\n ) {\n // error component routes, i.e. `/foo.errorComponent.tsx`\n fsRouteType = 'errorComponent'\n } else if (\n routePath.endsWith('/notFoundComponent') &&\n !isSuffixEscaped('notFoundComponent')\n ) {\n // not found component routes, i.e. `/foo.notFoundComponent.tsx`\n fsRouteType = 'notFoundComponent'\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 originalRoutePath Original route path with brackets for escaped content\n * @param routeType The route type determined from file extension\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 originalRoutePath: 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 const originalSegments = originalRoutePath.split('/').filter(Boolean)\n\n if (segments.length === 0) {\n return false\n }\n\n const lastRouteSegment = segments[segments.length - 1]!\n const lastOriginalSegment =\n originalSegments[originalSegments.length - 1] || ''\n const secondToLastRouteSegment = segments[segments.length - 2]\n const secondToLastOriginalSegment =\n originalSegments[originalSegments.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 // But if the underscore is escaped, it's not a pathless layout\n if (\n lastRouteSegment === config.routeToken &&\n typeof secondToLastRouteSegment === 'string' &&\n typeof secondToLastOriginalSegment === 'string'\n ) {\n // Check if the underscore is escaped\n if (hasEscapedLeadingUnderscore(secondToLastOriginalSegment)) {\n return false\n }\n return secondToLastRouteSegment.startsWith('_')\n }\n\n // Segment starts with _ but check if it's escaped\n // If the original segment has [_] at the start, the underscore is escaped and it's not a pathless layout\n if (hasEscapedLeadingUnderscore(lastOriginalSegment)) {\n return false\n }\n\n return (\n lastRouteSegment !== config.indexToken &&\n lastRouteSegment !== config.routeToken &&\n lastRouteSegment.startsWith('_')\n )\n}\n"],"names":["logger","logging","fsp","loadConfigFile","getRouteNodesVirtual","replaceBackslash","routePathToVariable","removeExt","determineInitialRoutePath","rootPathId","hasEscapedLeadingUnderscore"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getRouteNodes.cjs","sources":["../../../../src/filesystem/physical/getRouteNodes.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport {\n determineInitialRoutePath,\n hasEscapedLeadingUnderscore,\n removeExt,\n replaceBackslash,\n routePathToVariable,\n unwrapBracketWrappedSegment,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesVirtual } from '../virtual/getRouteNodes'\nimport { loadConfigFile } from '../virtual/loadConfigFile'\nimport { logging } from '../../logger'\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\n/**\n * Pre-compiled segment regexes for matching token patterns against route segments.\n * These are created once (in Generator constructor) and passed through to avoid\n * repeated regex compilation during route crawling.\n */\nexport interface TokenRegexBundle {\n indexTokenSegmentRegex: RegExp\n routeTokenSegmentRegex: RegExp\n}\n\nconst disallowedRouteGroupConfiguration = /\\(([^)]+)\\).(ts|js|tsx|jsx|vue)/\n\nconst virtualConfigFileRegExp = /__virtual\\.[mc]?[jt]s$/\nexport function isVirtualConfigFile(fileName: string): boolean {\n return virtualConfigFileRegExp.test(fileName)\n}\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 tokenRegexes: TokenRegexBundle,\n): Promise<GetRouteNodesResult> {\n const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } =\n config\n\n const logger = logging({ disabled: config.disableLogging })\n const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')\n\n const routeNodes: Array<RouteNode> = []\n const allPhysicalDirectories: Array<string> = []\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 if (routeFileIgnorePattern) {\n return (\n d.name.startsWith(routeFilePrefix) &&\n !d.name.match(routeFileIgnoreRegExp)\n )\n }\n\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() && isVirtualConfigFile(dirent.name)\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, physicalDirectories } =\n await getRouteNodesVirtual(\n {\n ...config,\n routesDirectory: fullDir,\n virtualRouteConfig: dummyRoot,\n },\n root,\n tokenRegexes,\n )\n allPhysicalDirectories.push(...physicalDirectories)\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 // Keep originalRoutePath aligned with routePath for escape detection\n if (node.originalRoutePath) {\n node.originalRoutePath = `/${dir}${node.originalRoutePath}`\n }\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 = replaceBackslash(path.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|vue)$/)) {\n const filePath = replaceBackslash(path.join(dir, dirent.name))\n const filePathNoExt = removeExt(filePath)\n const {\n routePath: initialRoutePath,\n originalRoutePath: initialOriginalRoutePath,\n } = determineInitialRoutePath(filePathNoExt)\n\n let routePath = initialRoutePath\n let originalRoutePath = initialOriginalRoutePath\n\n if (routeFilePrefix) {\n routePath = routePath.replaceAll(routeFilePrefix, '')\n originalRoutePath = originalRoutePath.replaceAll(\n routeFilePrefix,\n '',\n )\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, originalRoutePath, tokenRegexes)\n const variableName = meta.variableName\n let routeType: FsRouteType = meta.fsRouteType\n\n if (routeType === 'lazy') {\n routePath = routePath.replace(/\\/lazy$/, '')\n originalRoutePath = originalRoutePath.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 (\n isValidPathlessLayoutRoute(\n routePath,\n originalRoutePath,\n routeType,\n tokenRegexes,\n )\n ) {\n routeType = 'pathless_layout'\n }\n\n // Only show deprecation warning for .tsx/.ts files, not .vue files\n // Vue files using .component.vue is the Vue-native way\n const isVueFile = filePath.endsWith('.vue')\n if (!isVueFile) {\n ;(\n [\n ['component', 'component'],\n ['errorComponent', 'errorComponent'],\n ['notFoundComponent', 'notFoundComponent'],\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\n // Get the last segment of originalRoutePath to check for escaping\n const originalSegments = originalRoutePath.split('/').filter(Boolean)\n const lastOriginalSegmentForSuffix =\n originalSegments[originalSegments.length - 1] || ''\n\n const { routeTokenSegmentRegex, indexTokenSegmentRegex } =\n tokenRegexes\n\n // List of special suffixes that can be escaped\n const specialSuffixes = [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ]\n\n const routePathSegments = routePath.split('/').filter(Boolean)\n const lastRouteSegment =\n routePathSegments[routePathSegments.length - 1] || ''\n\n const suffixToStrip = specialSuffixes.find((suffix) => {\n const endsWithSuffix = routePath.endsWith(`/${suffix}`)\n // A suffix is escaped if wrapped in brackets in the original: [lazy] means literal \"lazy\"\n const isEscaped =\n lastOriginalSegmentForSuffix.startsWith('[') &&\n lastOriginalSegmentForSuffix.endsWith(']') &&\n unwrapBracketWrappedSegment(lastOriginalSegmentForSuffix) ===\n suffix\n return endsWithSuffix && !isEscaped\n })\n\n const routeTokenCandidate = unwrapBracketWrappedSegment(\n lastOriginalSegmentForSuffix,\n )\n const isRouteTokenEscaped =\n lastOriginalSegmentForSuffix !== routeTokenCandidate &&\n routeTokenSegmentRegex.test(routeTokenCandidate)\n\n const shouldStripRouteToken =\n routeTokenSegmentRegex.test(lastRouteSegment) &&\n !isRouteTokenEscaped\n\n if (suffixToStrip || shouldStripRouteToken) {\n const stripSegment = suffixToStrip ?? lastRouteSegment\n routePath = routePath.replace(new RegExp(`/${stripSegment}$`), '')\n originalRoutePath = originalRoutePath.replace(\n new RegExp(`/${stripSegment}$`),\n '',\n )\n }\n\n // Check if the index token should be treated specially or as a literal path\n // Escaping stays literal-only: if the last original segment is bracket-wrapped,\n // treat it as literal even if it matches the token regex.\n const lastOriginalSegment =\n originalRoutePath.split('/').filter(Boolean).pop() || ''\n\n const indexTokenCandidate =\n unwrapBracketWrappedSegment(lastOriginalSegment)\n const isIndexEscaped =\n lastOriginalSegment !== indexTokenCandidate &&\n indexTokenSegmentRegex.test(indexTokenCandidate)\n\n if (!isIndexEscaped) {\n const updatedRouteSegments = routePath.split('/').filter(Boolean)\n const updatedLastRouteSegment =\n updatedRouteSegments[updatedRouteSegments.length - 1] || ''\n\n if (indexTokenSegmentRegex.test(updatedLastRouteSegment)) {\n if (routePathSegments.length === 1) {\n routePath = '/'\n }\n\n if (lastOriginalSegment === updatedLastRouteSegment) {\n originalRoutePath = '/'\n }\n\n // For layout routes, don't use '/' fallback - an empty path means\n // \"layout for the parent path\" which is important for physical() mounts\n // where route.tsx at root should have empty path, not '/'\n const isLayoutRoute = routeType === 'layout'\n\n routePath =\n routePath.replace(\n new RegExp(`/${updatedLastRouteSegment}$`),\n '/',\n ) || (isLayoutRoute ? '' : '/')\n\n originalRoutePath =\n originalRoutePath.replace(\n new RegExp(`/${indexTokenCandidate}$`),\n '/',\n ) || (isLayoutRoute ? '' : '/')\n }\n }\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n _fsRouteType: routeType,\n originalRoutePath,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n // Find the root route node - prefer the actual route file over component/loader files\n const rootRouteNode =\n routeNodes.find(\n (d) =>\n d.routePath === `/${rootPathId}` &&\n ![\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType),\n ) ?? routeNodes.find((d) => d.routePath === `/${rootPathId}`)\n if (rootRouteNode) {\n rootRouteNode._fsRouteType = '__root'\n rootRouteNode.variableName = 'root'\n }\n\n return {\n rootRouteNode,\n routeNodes,\n physicalDirectories: allPhysicalDirectories,\n }\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 (with brackets removed).\n * @param originalRoutePath - The original route path (may contain brackets for escaped content).\n * @param tokenRegexes - Pre-compiled token regexes for matching.\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 originalRoutePath: string,\n tokenRegexes: TokenRegexBundle,\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 | 'notFoundComponent'\n >\n variableName: string\n} {\n let fsRouteType: FsRouteType = 'static'\n\n // Get the last segment from the original path to check for escaping\n const originalSegments = originalRoutePath.split('/').filter(Boolean)\n const lastOriginalSegment =\n originalSegments[originalSegments.length - 1] || ''\n\n const { routeTokenSegmentRegex } = tokenRegexes\n\n // Helper to check if a specific suffix is escaped (literal-only)\n // A suffix is escaped if the original segment is wrapped in brackets: [lazy] means literal \"lazy\"\n const isSuffixEscaped = (suffix: string): boolean => {\n return (\n lastOriginalSegment.startsWith('[') &&\n lastOriginalSegment.endsWith(']') &&\n unwrapBracketWrappedSegment(lastOriginalSegment) === suffix\n )\n }\n\n const routeSegments = routePath.split('/').filter(Boolean)\n const lastRouteSegment = routeSegments[routeSegments.length - 1] || ''\n\n const routeTokenCandidate = unwrapBracketWrappedSegment(lastOriginalSegment)\n const isRouteTokenEscaped =\n lastOriginalSegment !== routeTokenCandidate &&\n routeTokenSegmentRegex.test(routeTokenCandidate)\n\n if (routeTokenSegmentRegex.test(lastRouteSegment) && !isRouteTokenEscaped) {\n // layout routes, i.e `/foo/route.tsx` or `/foo/_layout/route.tsx`\n fsRouteType = 'layout'\n } else if (routePath.endsWith('/lazy') && !isSuffixEscaped('lazy')) {\n // lazy routes, i.e. `/foo.lazy.tsx`\n fsRouteType = 'lazy'\n } else if (routePath.endsWith('/loader') && !isSuffixEscaped('loader')) {\n // loader routes, i.e. `/foo.loader.tsx`\n fsRouteType = 'loader'\n } else if (\n routePath.endsWith('/component') &&\n !isSuffixEscaped('component')\n ) {\n // component routes, i.e. `/foo.component.tsx`\n fsRouteType = 'component'\n } else if (\n routePath.endsWith('/pendingComponent') &&\n !isSuffixEscaped('pendingComponent')\n ) {\n // pending component routes, i.e. `/foo.pendingComponent.tsx`\n fsRouteType = 'pendingComponent'\n } else if (\n routePath.endsWith('/errorComponent') &&\n !isSuffixEscaped('errorComponent')\n ) {\n // error component routes, i.e. `/foo.errorComponent.tsx`\n fsRouteType = 'errorComponent'\n } else if (\n routePath.endsWith('/notFoundComponent') &&\n !isSuffixEscaped('notFoundComponent')\n ) {\n // not found component routes, i.e. `/foo.notFoundComponent.tsx`\n fsRouteType = 'notFoundComponent'\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 originalRoutePath Original route path with brackets for escaped content\n * @param routeType The route type determined from file extension\n * @param tokenRegexes Pre-compiled token regexes for matching\n * @returns Boolean indicating if the route is a pathless layout route\n */\nfunction isValidPathlessLayoutRoute(\n normalizedRoutePath: string,\n originalRoutePath: string,\n routeType: FsRouteType,\n tokenRegexes: TokenRegexBundle,\n): boolean {\n if (routeType === 'lazy') {\n return false\n }\n\n const segments = normalizedRoutePath.split('/').filter(Boolean)\n const originalSegments = originalRoutePath.split('/').filter(Boolean)\n\n if (segments.length === 0) {\n return false\n }\n\n const lastRouteSegment = segments[segments.length - 1]!\n const lastOriginalSegment =\n originalSegments[originalSegments.length - 1] || ''\n const secondToLastRouteSegment = segments[segments.length - 2]\n const secondToLastOriginalSegment =\n originalSegments[originalSegments.length - 2]\n\n // If segment === __root, then exit as false\n if (lastRouteSegment === rootPathId) {\n return false\n }\n\n const { routeTokenSegmentRegex, indexTokenSegmentRegex } = tokenRegexes\n\n // If segment matches 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 // But if the underscore is escaped, it's not a pathless layout\n if (\n routeTokenSegmentRegex.test(lastRouteSegment) &&\n typeof secondToLastRouteSegment === 'string' &&\n typeof secondToLastOriginalSegment === 'string'\n ) {\n // Check if the underscore is escaped\n if (hasEscapedLeadingUnderscore(secondToLastOriginalSegment)) {\n return false\n }\n return secondToLastRouteSegment.startsWith('_')\n }\n\n // Segment starts with _ but check if it's escaped\n // If the original segment has [_] at the start, the underscore is escaped and it's not a pathless layout\n if (hasEscapedLeadingUnderscore(lastOriginalSegment)) {\n return false\n }\n\n return (\n !indexTokenSegmentRegex.test(lastRouteSegment) &&\n !routeTokenSegmentRegex.test(lastRouteSegment) &&\n lastRouteSegment.startsWith('_')\n )\n}\n"],"names":["logger","logging","fsp","loadConfigFile","getRouteNodesVirtual","replaceBackslash","routePathToVariable","removeExt","determineInitialRoutePath","unwrapBracketWrappedSegment","rootPathId","hasEscapedLeadingUnderscore"],"mappings":"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"}
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { FsRouteType, GetRouteNodesResult } from '../../types.cjs';
|
|
2
2
|
import { Config } from '../../config.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* Pre-compiled segment regexes for matching token patterns against route segments.
|
|
5
|
+
* These are created once (in Generator constructor) and passed through to avoid
|
|
6
|
+
* repeated regex compilation during route crawling.
|
|
7
|
+
*/
|
|
8
|
+
export interface TokenRegexBundle {
|
|
9
|
+
indexTokenSegmentRegex: RegExp;
|
|
10
|
+
routeTokenSegmentRegex: RegExp;
|
|
11
|
+
}
|
|
3
12
|
export declare function isVirtualConfigFile(fileName: string): boolean;
|
|
4
|
-
export declare function getRouteNodes(config: Pick<Config, 'routesDirectory' | 'routeFilePrefix' | 'routeFileIgnorePrefix' | 'routeFileIgnorePattern' | 'disableLogging' | 'routeToken' | 'indexToken'>, root: string): Promise<GetRouteNodesResult>;
|
|
13
|
+
export declare function getRouteNodes(config: Pick<Config, 'routesDirectory' | 'routeFilePrefix' | 'routeFileIgnorePrefix' | 'routeFileIgnorePattern' | 'disableLogging' | 'routeToken' | 'indexToken'>, root: string, tokenRegexes: TokenRegexBundle): Promise<GetRouteNodesResult>;
|
|
5
14
|
/**
|
|
6
15
|
* Determines the metadata for a given route path based on the provided configuration.
|
|
7
16
|
*
|
|
8
17
|
* @param routePath - The determined initial routePath (with brackets removed).
|
|
9
18
|
* @param originalRoutePath - The original route path (may contain brackets for escaped content).
|
|
10
|
-
* @param
|
|
19
|
+
* @param tokenRegexes - Pre-compiled token regexes for matching.
|
|
11
20
|
* @returns An object containing the type of the route and the variable name derived from the route path.
|
|
12
21
|
*/
|
|
13
|
-
export declare function getRouteMeta(routePath: string, originalRoutePath: string,
|
|
22
|
+
export declare function getRouteMeta(routePath: string, originalRoutePath: string, tokenRegexes: TokenRegexBundle): {
|
|
14
23
|
fsRouteType: Extract<FsRouteType, 'static' | 'layout' | 'api' | 'lazy' | 'loader' | 'component' | 'pendingComponent' | 'errorComponent' | 'notFoundComponent'>;
|
|
15
24
|
variableName: string;
|
|
16
25
|
};
|