@tanstack/router-vite-plugin 1.24.1 → 1.26.6

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 (43) hide show
  1. package/dist/cjs/compilers.cjs +335 -0
  2. package/dist/cjs/compilers.cjs.map +1 -0
  3. package/dist/cjs/compilers.d.cts +38 -0
  4. package/dist/cjs/constants.cjs +5 -0
  5. package/dist/cjs/constants.cjs.map +1 -0
  6. package/dist/cjs/constants.d.cts +1 -0
  7. package/dist/cjs/eliminateUnreferencedIdentifiers.cjs +144 -0
  8. package/dist/cjs/eliminateUnreferencedIdentifiers.cjs.map +1 -0
  9. package/dist/cjs/eliminateUnreferencedIdentifiers.d.cts +8 -0
  10. package/dist/cjs/index.cjs +103 -8
  11. package/dist/cjs/index.cjs.map +1 -1
  12. package/dist/cjs/index.d.cts +55 -2
  13. package/dist/esm/compilers.d.ts +38 -0
  14. package/dist/esm/compilers.js +316 -0
  15. package/dist/esm/compilers.js.map +1 -0
  16. package/dist/esm/constants.d.ts +1 -0
  17. package/dist/esm/constants.js +5 -0
  18. package/dist/esm/constants.js.map +1 -0
  19. package/dist/esm/eliminateUnreferencedIdentifiers.d.ts +8 -0
  20. package/dist/esm/eliminateUnreferencedIdentifiers.js +127 -0
  21. package/dist/esm/eliminateUnreferencedIdentifiers.js.map +1 -0
  22. package/dist/esm/index.d.ts +55 -2
  23. package/dist/esm/index.js +103 -8
  24. package/dist/esm/index.js.map +1 -1
  25. package/package.json +18 -1
  26. package/src/compilers.ts +420 -0
  27. package/src/constants.ts +1 -0
  28. package/src/eliminateUnreferencedIdentifiers.ts +287 -0
  29. package/src/index.ts +167 -8
  30. package/src/tests/index.test.ts +60 -0
  31. package/src/tests/shared/imported.tsx +11 -0
  32. package/src/tests/snapshots/function-declaration.tsx +10 -0
  33. package/src/tests/snapshots/function-declaration?split.tsx +29 -0
  34. package/src/tests/snapshots/imported.tsx +10 -0
  35. package/src/tests/snapshots/imported?split.tsx +5 -0
  36. package/src/tests/snapshots/inline.tsx +8 -0
  37. package/src/tests/snapshots/inline?split.tsx +18 -0
  38. package/src/tests/snapshots/random-number.tsx +11 -0
  39. package/src/tests/snapshots/random-number?split.tsx +27 -0
  40. package/src/tests/test-files/function-declaration.tsx +39 -0
  41. package/src/tests/test-files/imported.tsx +8 -0
  42. package/src/tests/test-files/inline.tsx +25 -0
  43. package/src/tests/test-files/random-number.tsx +83 -0
@@ -0,0 +1,127 @@
1
+ import * as t from "@babel/types";
2
+ const eliminateUnreferencedIdentifiers = (programPath, refs) => {
3
+ let referencesRemovedInThisPass;
4
+ const shouldBeRemoved = (ident) => {
5
+ if (isIdentifierReferenced(ident))
6
+ return false;
7
+ if (!refs)
8
+ return true;
9
+ return refs.has(ident);
10
+ };
11
+ const sweepFunction = (path) => {
12
+ const identifier = getIdentifier(path);
13
+ if ((identifier == null ? void 0 : identifier.node) && shouldBeRemoved(identifier)) {
14
+ ++referencesRemovedInThisPass;
15
+ if (t.isAssignmentExpression(path.parentPath.node) || t.isVariableDeclarator(path.parentPath.node)) {
16
+ path.parentPath.remove();
17
+ } else {
18
+ path.remove();
19
+ }
20
+ }
21
+ };
22
+ const sweepImport = (path) => {
23
+ const local = path.get("local");
24
+ if (shouldBeRemoved(local)) {
25
+ ++referencesRemovedInThisPass;
26
+ path.remove();
27
+ if (path.parent.specifiers.length === 0) {
28
+ path.parentPath.remove();
29
+ }
30
+ }
31
+ };
32
+ do {
33
+ referencesRemovedInThisPass = 0;
34
+ programPath.scope.crawl();
35
+ programPath.traverse({
36
+ VariableDeclarator(path) {
37
+ if (path.node.id.type === "Identifier") {
38
+ const local = path.get("id");
39
+ if (shouldBeRemoved(local)) {
40
+ ++referencesRemovedInThisPass;
41
+ path.remove();
42
+ }
43
+ } else if (path.node.id.type === "ObjectPattern") {
44
+ const pattern = path.get("id");
45
+ const beforeCount = referencesRemovedInThisPass;
46
+ const properties = pattern.get("properties");
47
+ properties.forEach((property) => {
48
+ const local = property.get(
49
+ property.node.type === "ObjectProperty" ? "value" : (
50
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
51
+ property.node.type === "RestElement" ? "argument" : function() {
52
+ throw new Error("invariant");
53
+ }()
54
+ )
55
+ );
56
+ if (shouldBeRemoved(local)) {
57
+ ++referencesRemovedInThisPass;
58
+ property.remove();
59
+ }
60
+ });
61
+ if (beforeCount !== referencesRemovedInThisPass && pattern.get("properties").length < 1) {
62
+ path.remove();
63
+ }
64
+ } else if (path.node.id.type === "ArrayPattern") {
65
+ const pattern = path.get("id");
66
+ const beforeCount = referencesRemovedInThisPass;
67
+ const elements = pattern.get("elements");
68
+ elements.forEach((e) => {
69
+ var _a, _b;
70
+ let local;
71
+ if (((_a = e.node) == null ? void 0 : _a.type) === "Identifier") {
72
+ local = e;
73
+ } else if (((_b = e.node) == null ? void 0 : _b.type) === "RestElement") {
74
+ local = e.get("argument");
75
+ } else {
76
+ return;
77
+ }
78
+ if (shouldBeRemoved(local)) {
79
+ ++referencesRemovedInThisPass;
80
+ e.remove();
81
+ }
82
+ });
83
+ if (beforeCount !== referencesRemovedInThisPass && pattern.get("elements").length < 1) {
84
+ path.remove();
85
+ }
86
+ }
87
+ },
88
+ FunctionDeclaration: sweepFunction,
89
+ FunctionExpression: sweepFunction,
90
+ ArrowFunctionExpression: sweepFunction,
91
+ ImportSpecifier: sweepImport,
92
+ ImportDefaultSpecifier: sweepImport,
93
+ ImportNamespaceSpecifier: sweepImport
94
+ });
95
+ } while (referencesRemovedInThisPass);
96
+ };
97
+ function getIdentifier(path) {
98
+ const parentPath = path.parentPath;
99
+ if (parentPath.type === "VariableDeclarator") {
100
+ const variablePath = parentPath;
101
+ const name = variablePath.get("id");
102
+ return name.node.type === "Identifier" ? name : null;
103
+ }
104
+ if (parentPath.type === "AssignmentExpression") {
105
+ const variablePath = parentPath;
106
+ const name = variablePath.get("left");
107
+ return name.node.type === "Identifier" ? name : null;
108
+ }
109
+ if (path.node.type === "ArrowFunctionExpression") {
110
+ return null;
111
+ }
112
+ return path.node.id && path.node.id.type === "Identifier" ? path.get("id") : null;
113
+ }
114
+ function isIdentifierReferenced(ident) {
115
+ const binding = ident.scope.getBinding(ident.node.name);
116
+ if (binding == null ? void 0 : binding.referenced) {
117
+ if (binding.path.type === "FunctionDeclaration") {
118
+ return !binding.constantViolations.concat(binding.referencePaths).every((ref) => ref.findParent((parent) => parent === binding.path));
119
+ }
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+ export {
125
+ eliminateUnreferencedIdentifiers
126
+ };
127
+ //# sourceMappingURL=eliminateUnreferencedIdentifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eliminateUnreferencedIdentifiers.js","sources":["../../src/eliminateUnreferencedIdentifiers.ts"],"sourcesContent":["// Copied from https://github.com/pcattori/vite-env-only/blob/main/src/dce.ts\n// Adapted with some minor changes for the purpose of this project\n\nimport * as t from '@babel/types'\nimport type { types as BabelTypes } from '@babel/core'\nimport type { NodePath } from '@babel/traverse'\n\ntype IdentifierPath = NodePath<BabelTypes.Identifier>\n\n// export function findReferencedIdentifiers(\n// programPath: NodePath<BabelTypes.Program>,\n// ): Set<IdentifierPath> {\n// const refs = new Set<IdentifierPath>()\n\n// function markFunction(\n// path: NodePath<\n// | BabelTypes.FunctionDeclaration\n// | BabelTypes.FunctionExpression\n// | BabelTypes.ArrowFunctionExpression\n// >,\n// ) {\n// const ident = getIdentifier(path)\n// if (ident?.node && isIdentifierReferenced(ident)) {\n// refs.add(ident)\n// }\n// }\n\n// function markImport(\n// path: NodePath<\n// | BabelTypes.ImportSpecifier\n// | BabelTypes.ImportDefaultSpecifier\n// | BabelTypes.ImportNamespaceSpecifier\n// >,\n// ) {\n// const local = path.get('local')\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// }\n\n// programPath.traverse({\n// VariableDeclarator(path) {\n// if (path.node.id.type === 'Identifier') {\n// const local = path.get('id') as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// } else if (path.node.id.type === 'ObjectPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n// const properties = pattern.get('properties')\n// properties.forEach((p) => {\n// const local = p.get(\n// p.node.type === 'ObjectProperty'\n// ? 'value'\n// : p.node.type === 'RestElement'\n// ? 'argument'\n// : (function () {\n// throw new Error('invariant')\n// })(),\n// ) as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// } else if (path.node.id.type === 'ArrayPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n// const elements = pattern.get('elements')\n// elements.forEach((e) => {\n// let local: NodePath<BabelTypes.Identifier>\n// if (e.node?.type === 'Identifier') {\n// local = e as NodePath<BabelTypes.Identifier>\n// } else if (e.node?.type === 'RestElement') {\n// local = e.get('argument') as NodePath<BabelTypes.Identifier>\n// } else {\n// return\n// }\n\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// }\n// },\n\n// FunctionDeclaration: markFunction,\n// FunctionExpression: markFunction,\n// ArrowFunctionExpression: markFunction,\n// ImportSpecifier: markImport,\n// ImportDefaultSpecifier: markImport,\n// ImportNamespaceSpecifier: markImport,\n// })\n// return refs\n// }\n\n/**\n * @param refs - If provided, only these identifiers will be considered for removal.\n */\nexport const eliminateUnreferencedIdentifiers = (\n programPath: NodePath<BabelTypes.Program>,\n refs?: Set<IdentifierPath>,\n) => {\n let referencesRemovedInThisPass: number\n\n const shouldBeRemoved = (ident: IdentifierPath) => {\n if (isIdentifierReferenced(ident)) return false\n if (!refs) return true\n return refs.has(ident)\n }\n\n const sweepFunction = (\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n ) => {\n const identifier = getIdentifier(path)\n if (identifier?.node && shouldBeRemoved(identifier)) {\n ++referencesRemovedInThisPass\n\n if (\n t.isAssignmentExpression(path.parentPath.node) ||\n t.isVariableDeclarator(path.parentPath.node)\n ) {\n path.parentPath.remove()\n } else {\n path.remove()\n }\n }\n }\n\n const sweepImport = (\n path: NodePath<\n | BabelTypes.ImportSpecifier\n | BabelTypes.ImportDefaultSpecifier\n | BabelTypes.ImportNamespaceSpecifier\n >,\n ) => {\n const local = path.get('local')\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n if (\n (path.parent as BabelTypes.ImportDeclaration).specifiers.length === 0\n ) {\n path.parentPath.remove()\n }\n }\n }\n\n // Traverse again to remove unused references. This happens at least once,\n // then repeats until no more references are removed.\n do {\n referencesRemovedInThisPass = 0\n\n programPath.scope.crawl()\n\n programPath.traverse({\n VariableDeclarator(path) {\n if (path.node.id.type === 'Identifier') {\n const local = path.get('id') as NodePath<BabelTypes.Identifier>\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n }\n } else if (path.node.id.type === 'ObjectPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const properties = pattern.get('properties')\n properties.forEach((property) => {\n const local = property.get(\n property.node.type === 'ObjectProperty'\n ? 'value'\n : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n property.node.type === 'RestElement'\n ? 'argument'\n : (function () {\n throw new Error('invariant')\n })(),\n ) as NodePath<BabelTypes.Identifier>\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n property.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('properties').length < 1\n ) {\n path.remove()\n }\n } else if (path.node.id.type === 'ArrayPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const elements = pattern.get('elements')\n elements.forEach((e) => {\n let local: NodePath<BabelTypes.Identifier>\n if (e.node?.type === 'Identifier') {\n local = e as NodePath<BabelTypes.Identifier>\n } else if (e.node?.type === 'RestElement') {\n local = e.get('argument') as NodePath<BabelTypes.Identifier>\n } else {\n return\n }\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n e.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('elements').length < 1\n ) {\n path.remove()\n }\n }\n },\n FunctionDeclaration: sweepFunction,\n FunctionExpression: sweepFunction,\n ArrowFunctionExpression: sweepFunction,\n ImportSpecifier: sweepImport,\n ImportDefaultSpecifier: sweepImport,\n ImportNamespaceSpecifier: sweepImport,\n })\n } while (referencesRemovedInThisPass)\n}\n\nfunction getIdentifier(\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n): NodePath<BabelTypes.Identifier> | null {\n const parentPath = path.parentPath\n if (parentPath.type === 'VariableDeclarator') {\n const variablePath = parentPath as NodePath<BabelTypes.VariableDeclarator>\n const name = variablePath.get('id')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (parentPath.type === 'AssignmentExpression') {\n const variablePath = parentPath as NodePath<BabelTypes.AssignmentExpression>\n const name = variablePath.get('left')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (path.node.type === 'ArrowFunctionExpression') {\n return null\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return path.node.id && path.node.id.type === 'Identifier'\n ? (path.get('id') as NodePath<BabelTypes.Identifier>)\n : null\n}\n\nfunction isIdentifierReferenced(\n ident: NodePath<BabelTypes.Identifier>,\n): boolean {\n const binding = ident.scope.getBinding(ident.node.name)\n if (binding?.referenced) {\n // Functions can reference themselves, so we need to check if there's a\n // binding outside the function scope or not.\n if (binding.path.type === 'FunctionDeclaration') {\n return !binding.constantViolations\n .concat(binding.referencePaths)\n // Check that every reference is contained within the function:\n .every((ref) => ref.findParent((parent) => parent === binding.path))\n }\n\n return true\n }\n return false\n}\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,56 @@
1
- import { type Config } from '@tanstack/router-generator';
1
+ import { z } from 'zod';
2
2
  import type { Plugin } from 'vite';
3
- export declare function TanStackRouterVite(inlineConfig?: Partial<Config>): Plugin;
3
+ export declare const configSchema: z.ZodObject<{
4
+ routeFilePrefix: z.ZodOptional<z.ZodString>;
5
+ routeFileIgnorePrefix: z.ZodDefault<z.ZodOptional<z.ZodString>>;
6
+ routeFileIgnorePattern: z.ZodOptional<z.ZodString>;
7
+ routesDirectory: z.ZodDefault<z.ZodOptional<z.ZodString>>;
8
+ generatedRouteTree: z.ZodDefault<z.ZodOptional<z.ZodString>>;
9
+ quoteStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double"]>>>;
10
+ semicolons: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
11
+ disableTypes: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
12
+ addExtensions: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
13
+ disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
+ enableRouteGeneration: z.ZodOptional<z.ZodBoolean>;
15
+ experimental: z.ZodOptional<z.ZodObject<{
16
+ enableCodeSplitting: z.ZodOptional<z.ZodBoolean>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ enableCodeSplitting?: boolean | undefined;
19
+ }, {
20
+ enableCodeSplitting?: boolean | undefined;
21
+ }>>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ routeFileIgnorePrefix: string;
24
+ routesDirectory: string;
25
+ generatedRouteTree: string;
26
+ quoteStyle: "single" | "double";
27
+ semicolons: boolean;
28
+ disableTypes: boolean;
29
+ addExtensions: boolean;
30
+ disableLogging: boolean;
31
+ routeFilePrefix?: string | undefined;
32
+ routeFileIgnorePattern?: string | undefined;
33
+ enableRouteGeneration?: boolean | undefined;
34
+ experimental?: {
35
+ enableCodeSplitting?: boolean | undefined;
36
+ } | undefined;
37
+ }, {
38
+ routeFilePrefix?: string | undefined;
39
+ routeFileIgnorePrefix?: string | undefined;
40
+ routeFileIgnorePattern?: string | undefined;
41
+ routesDirectory?: string | undefined;
42
+ generatedRouteTree?: string | undefined;
43
+ quoteStyle?: "single" | "double" | undefined;
44
+ semicolons?: boolean | undefined;
45
+ disableTypes?: boolean | undefined;
46
+ addExtensions?: boolean | undefined;
47
+ disableLogging?: boolean | undefined;
48
+ enableRouteGeneration?: boolean | undefined;
49
+ experimental?: {
50
+ enableCodeSplitting?: boolean | undefined;
51
+ } | undefined;
52
+ }>;
53
+ export type Config = z.infer<typeof configSchema>;
54
+ export declare function TanStackRouterVite(inlineConfig?: Partial<Config>): Array<Plugin>;
55
+ export declare function TanStackRouterViteGenerator(inlineConfig?: Partial<Config>): Plugin;
56
+ export declare function TanStackRouterViteCodeSplitter(inlineConfig?: Partial<Config>): Plugin;
package/dist/esm/index.js CHANGED
@@ -1,8 +1,28 @@
1
1
  import { normalize, join, isAbsolute } from "path";
2
- import { getConfig, generator } from "@tanstack/router-generator";
2
+ import { pathToFileURL, fileURLToPath } from "url";
3
+ import { z } from "zod";
4
+ import { configSchema as configSchema$1, getConfig as getConfig$1, generator } from "@tanstack/router-generator";
5
+ import { splitFile, compileFile, makeCompile } from "./compilers.js";
6
+ import { splitPrefix } from "./constants.js";
7
+ const configSchema = configSchema$1.extend({
8
+ enableRouteGeneration: z.boolean().optional(),
9
+ experimental: z.object({
10
+ enableCodeSplitting: z.boolean().optional()
11
+ }).optional()
12
+ });
3
13
  const CONFIG_FILE_NAME = "tsr.config.json";
14
+ const getConfig = async (inlineConfig, root) => {
15
+ const config = await getConfig$1(inlineConfig, root);
16
+ return configSchema.parse({ ...inlineConfig, ...config });
17
+ };
4
18
  function TanStackRouterVite(inlineConfig = {}) {
5
- const ROOT = process.cwd();
19
+ return [
20
+ TanStackRouterViteGenerator(inlineConfig),
21
+ TanStackRouterViteCodeSplitter(inlineConfig)
22
+ ];
23
+ }
24
+ function TanStackRouterViteGenerator(inlineConfig = {}) {
25
+ let ROOT = process.cwd();
6
26
  let userConfig;
7
27
  const generate = async () => {
8
28
  try {
@@ -24,19 +44,94 @@ function TanStackRouterVite(inlineConfig = {}) {
24
44
  }
25
45
  };
26
46
  return {
27
- name: "vite-plugin-tanstack-router",
28
- configResolved: async () => {
47
+ name: "vite-plugin-tanstack-router-generator",
48
+ configResolved: async (config) => {
49
+ ROOT = config.root;
29
50
  userConfig = await getConfig(inlineConfig, ROOT);
30
- await generate();
51
+ if (userConfig.enableRouteGeneration ?? true) {
52
+ await generate();
53
+ }
31
54
  },
32
55
  watchChange: async (file, context) => {
33
- if (["create", "update", "delete"].includes(context.event)) {
34
- await handleFile(file);
56
+ if (userConfig.enableRouteGeneration ?? true) {
57
+ if (["create", "update", "delete"].includes(context.event)) {
58
+ await handleFile(file);
59
+ }
60
+ }
61
+ }
62
+ };
63
+ }
64
+ function fileIsInRoutesDirectory(filePath, routesDirectory) {
65
+ const routesDirectoryPath = isAbsolute(routesDirectory) ? routesDirectory : join(process.cwd(), routesDirectory);
66
+ return filePath.startsWith(routesDirectoryPath);
67
+ }
68
+ function TanStackRouterViteCodeSplitter(inlineConfig = {}) {
69
+ let ROOT = process.cwd();
70
+ let userConfig;
71
+ return {
72
+ name: "vite-plugin-tanstack-router-code-splitter",
73
+ enforce: "pre",
74
+ configResolved: async (config) => {
75
+ ROOT = config.root;
76
+ userConfig = await getConfig(inlineConfig, ROOT);
77
+ },
78
+ resolveId(source) {
79
+ var _a;
80
+ if (!((_a = userConfig.experimental) == null ? void 0 : _a.enableCodeSplitting)) {
81
+ return null;
82
+ }
83
+ if (source.startsWith(splitPrefix + ":")) {
84
+ return source.replace(splitPrefix + ":", "");
85
+ }
86
+ return null;
87
+ },
88
+ async transform(code, id, transformOptions) {
89
+ var _a;
90
+ if (!((_a = userConfig.experimental) == null ? void 0 : _a.enableCodeSplitting)) {
91
+ return null;
92
+ }
93
+ const url = pathToFileURL(id);
94
+ url.searchParams.delete("v");
95
+ id = fileURLToPath(url).replace(/\\/g, "/");
96
+ const compile = makeCompile({
97
+ root: ROOT
98
+ });
99
+ if (id.includes(splitPrefix)) {
100
+ const compiled = await splitFile({
101
+ code,
102
+ compile,
103
+ filename: id
104
+ // ref,
105
+ });
106
+ return compiled;
107
+ } else if (fileIsInRoutesDirectory(id, userConfig.routesDirectory) && (code.includes("createRoute(") || code.includes("createFileRoute("))) {
108
+ if (code.includes("@react-refresh")) {
109
+ throw new Error(
110
+ `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/router-vite-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again:
111
+ e.g.
112
+
113
+ plugins: [
114
+ TanStackRouterVite(), // Place this before viteReact()
115
+ viteReact(),
116
+ ]
117
+ `
118
+ );
119
+ }
120
+ const compiled = await compileFile({
121
+ code,
122
+ compile,
123
+ filename: id
124
+ });
125
+ return compiled;
35
126
  }
127
+ return null;
36
128
  }
37
129
  };
38
130
  }
39
131
  export {
40
- TanStackRouterVite
132
+ TanStackRouterVite,
133
+ TanStackRouterViteCodeSplitter,
134
+ TanStackRouterViteGenerator,
135
+ configSchema
41
136
  };
42
137
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { isAbsolute, join, normalize } from 'path'\nimport { type Config, generator, getConfig } from '@tanstack/router-generator'\nimport type { Plugin } from 'vite'\n\nconst CONFIG_FILE_NAME = 'tsr.config.json'\n\nexport function TanStackRouterVite(inlineConfig: Partial<Config> = {}): Plugin {\n const ROOT: string = process.cwd()\n let userConfig: Config\n\n const generate = async () => {\n try {\n await generator(userConfig)\n } catch (err) {\n console.error(err)\n console.info()\n }\n }\n\n const handleFile = async (file: string) => {\n const filePath = normalize(file)\n if (filePath === join(ROOT, CONFIG_FILE_NAME)) {\n userConfig = await getConfig(inlineConfig, ROOT)\n return\n }\n const routesDirectoryPath = isAbsolute(userConfig.routesDirectory)\n ? userConfig.routesDirectory\n : join(ROOT, userConfig.routesDirectory)\n if (filePath.startsWith(routesDirectoryPath)) {\n await generate()\n }\n }\n\n return {\n name: 'vite-plugin-tanstack-router',\n configResolved: async () => {\n userConfig = await getConfig(inlineConfig, ROOT)\n await generate()\n },\n watchChange: async (file, context) => {\n if (['create', 'update', 'delete'].includes(context.event)) {\n await handleFile(file)\n }\n },\n }\n}\n"],"names":[],"mappings":";;AAIA,MAAM,mBAAmB;AAET,SAAA,mBAAmB,eAAgC,IAAY;AACvE,QAAA,OAAe,QAAQ;AACzB,MAAA;AAEJ,QAAM,WAAW,YAAY;AACvB,QAAA;AACF,YAAM,UAAU,UAAU;AAAA,aACnB,KAAK;AACZ,cAAQ,MAAM,GAAG;AACjB,cAAQ,KAAK;AAAA,IACf;AAAA,EAAA;AAGI,QAAA,aAAa,OAAO,SAAiB;AACnC,UAAA,WAAW,UAAU,IAAI;AAC/B,QAAI,aAAa,KAAK,MAAM,gBAAgB,GAAG;AAChC,mBAAA,MAAM,UAAU,cAAc,IAAI;AAC/C;AAAA,IACF;AACM,UAAA,sBAAsB,WAAW,WAAW,eAAe,IAC7D,WAAW,kBACX,KAAK,MAAM,WAAW,eAAe;AACrC,QAAA,SAAS,WAAW,mBAAmB,GAAG;AAC5C,YAAM,SAAS;AAAA,IACjB;AAAA,EAAA;AAGK,SAAA;AAAA,IACL,MAAM;AAAA,IACN,gBAAgB,YAAY;AACb,mBAAA,MAAM,UAAU,cAAc,IAAI;AAC/C,YAAM,SAAS;AAAA,IACjB;AAAA,IACA,aAAa,OAAO,MAAM,YAAY;AAChC,UAAA,CAAC,UAAU,UAAU,QAAQ,EAAE,SAAS,QAAQ,KAAK,GAAG;AAC1D,cAAM,WAAW,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { isAbsolute, join, normalize } from 'path'\nimport { fileURLToPath, pathToFileURL } from 'url'\nimport { z } from 'zod'\nimport {\n generator,\n configSchema as generatorConfigSchema,\n getConfig as getGeneratorConfig,\n} from '@tanstack/router-generator'\nimport { compileFile, makeCompile, splitFile } from './compilers'\nimport { splitPrefix } from './constants'\nimport type { Plugin } from 'vite'\n\nexport const configSchema = generatorConfigSchema.extend({\n enableRouteGeneration: z.boolean().optional(),\n experimental: z\n .object({\n enableCodeSplitting: z.boolean().optional(),\n })\n .optional(),\n})\n\nexport type Config = z.infer<typeof configSchema>\n\nconst CONFIG_FILE_NAME = 'tsr.config.json'\nconst debug = false as any\n\nconst getConfig = async (inlineConfig: Partial<Config>, root: string) => {\n const config = await getGeneratorConfig(inlineConfig, root)\n\n return configSchema.parse({ ...inlineConfig, ...config })\n}\n\nexport function TanStackRouterVite(\n inlineConfig: Partial<Config> = {},\n): Array<Plugin> {\n return [\n TanStackRouterViteGenerator(inlineConfig),\n TanStackRouterViteCodeSplitter(inlineConfig),\n ]\n}\n\nexport function TanStackRouterViteGenerator(\n inlineConfig: Partial<Config> = {},\n): Plugin {\n let ROOT: string = process.cwd()\n let userConfig: Config\n\n const generate = async () => {\n try {\n await generator(userConfig)\n } catch (err) {\n console.error(err)\n console.info()\n }\n }\n\n const handleFile = async (file: string) => {\n const filePath = normalize(file)\n if (filePath === join(ROOT, CONFIG_FILE_NAME)) {\n userConfig = await getConfig(inlineConfig, ROOT)\n return\n }\n const routesDirectoryPath = isAbsolute(userConfig.routesDirectory)\n ? userConfig.routesDirectory\n : join(ROOT, userConfig.routesDirectory)\n if (filePath.startsWith(routesDirectoryPath)) {\n await generate()\n }\n }\n\n return {\n name: 'vite-plugin-tanstack-router-generator',\n configResolved: async (config) => {\n ROOT = config.root\n userConfig = await getConfig(inlineConfig, ROOT)\n\n if (userConfig.enableRouteGeneration ?? true) {\n await generate()\n }\n },\n watchChange: async (file, context) => {\n if (userConfig.enableRouteGeneration ?? true) {\n if (['create', 'update', 'delete'].includes(context.event)) {\n await handleFile(file)\n }\n }\n },\n }\n}\n\nfunction fileIsInRoutesDirectory(filePath: string, routesDirectory: string) {\n const routesDirectoryPath = isAbsolute(routesDirectory)\n ? routesDirectory\n : join(process.cwd(), routesDirectory)\n\n return filePath.startsWith(routesDirectoryPath)\n}\n\nexport function TanStackRouterViteCodeSplitter(\n inlineConfig: Partial<Config> = {},\n): Plugin {\n let ROOT: string = process.cwd()\n let userConfig: Config\n\n return {\n name: 'vite-plugin-tanstack-router-code-splitter',\n enforce: 'pre',\n configResolved: async (config) => {\n ROOT = config.root\n userConfig = await getConfig(inlineConfig, ROOT)\n },\n resolveId(source) {\n if (!userConfig.experimental?.enableCodeSplitting) {\n return null\n }\n\n if (source.startsWith(splitPrefix + ':')) {\n return source.replace(splitPrefix + ':', '')\n }\n return null\n },\n async transform(code, id, transformOptions) {\n if (!userConfig.experimental?.enableCodeSplitting) {\n return null\n }\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n const compile = makeCompile({\n root: ROOT,\n })\n\n if (id.includes(splitPrefix)) {\n if (debug) console.info('Splitting route: ', id)\n // const ref = new URLSearchParams(id.split('?')[1]).get('ref') || ''\n\n const compiled = await splitFile({\n code,\n compile,\n filename: id,\n // ref,\n })\n\n if (debug) console.info('')\n if (debug) console.info('Split Output')\n if (debug) console.info('')\n if (debug) console.info(compiled.code)\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n\n return compiled\n } else if (\n fileIsInRoutesDirectory(id, userConfig.routesDirectory) &&\n (code.includes('createRoute(') || code.includes('createFileRoute('))\n ) {\n if (code.includes('@react-refresh')) {\n throw new Error(\n `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/router-vite-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: \ne.g.\n\nplugins: [\n TanStackRouterVite(), // Place this before viteReact()\n viteReact(),\n]\n`,\n )\n }\n\n if (debug) console.info('Handling createRoute: ', id)\n const compiled = await compileFile({\n code,\n compile,\n filename: id,\n })\n\n if (debug) console.info('')\n if (debug) console.info('Compiled Output')\n if (debug) console.info('')\n if (debug) console.info(compiled.code)\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n if (debug) console.info('')\n\n return compiled\n }\n\n return null\n },\n }\n}\n"],"names":["generatorConfigSchema","getGeneratorConfig"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-vite-plugin",
3
- "version": "1.24.1",
3
+ "version": "1.26.6",
4
4
  "description": "",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -49,10 +49,27 @@
49
49
  "src/**"
50
50
  ],
51
51
  "dependencies": {
52
+ "@babel/core": "^7.23.7",
53
+ "@babel/generator": "^7.23.6",
54
+ "@babel/plugin-syntax-jsx": "^7.24.1",
55
+ "@babel/plugin-syntax-typescript": "^7.24.1",
56
+ "@babel/plugin-transform-react-jsx": "^7.23.4",
57
+ "@babel/plugin-transform-typescript": "^7.24.1",
58
+ "@babel/template": "^7.24.0",
59
+ "@babel/traverse": "^7.24.1",
60
+ "@babel/types": "^7.24.0",
61
+ "@types/babel__core": "^7.20.5",
62
+ "@types/babel__generator": "^7.6.8",
63
+ "@types/babel__template": "^7.4.4",
64
+ "@types/babel__traverse": "^7.20.5",
65
+ "@vitejs/plugin-react": "^4.2.1",
66
+ "zod": "^3.22.4",
52
67
  "@tanstack/router-generator": "1.23.0"
53
68
  },
54
69
  "scripts": {
55
70
  "clean": "rimraf ./dist && rimraf ./coverage",
71
+ "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit",
72
+ "test:unit": "vitest",
56
73
  "test:eslint": "eslint --ext .ts,.tsx ./src",
57
74
  "test:types": "tsc --noEmit",
58
75
  "test:build": "publint --strict",