@tanstack/router-vite-plugin 1.25.0 → 1.26.8

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.
@@ -82,25 +82,26 @@ const eliminateUnreferencedIdentifiers = (programPath, refs) => {
82
82
  }
83
83
  } else if (path.node.id.type === "ArrayPattern") {
84
84
  const pattern = path.get("id");
85
- const beforeCount = referencesRemovedInThisPass;
86
- const elements = pattern.get("elements");
87
- elements.forEach((e) => {
88
- var _a, _b;
89
- let local;
90
- if (((_a = e.node) == null ? void 0 : _a.type) === "Identifier") {
91
- local = e;
92
- } else if (((_b = e.node) == null ? void 0 : _b.type) === "RestElement") {
93
- local = e.get("argument");
85
+ let hasRemoved = false;
86
+ pattern.get("elements").forEach((element, index) => {
87
+ let identifierPath;
88
+ if (t__namespace.isIdentifier(element.node)) {
89
+ identifierPath = element;
90
+ } else if (t__namespace.isRestElement(element.node)) {
91
+ identifierPath = element.get(
92
+ "argument"
93
+ );
94
94
  } else {
95
95
  return;
96
96
  }
97
- if (shouldBeRemoved(local)) {
98
- ++referencesRemovedInThisPass;
99
- e.remove();
97
+ if (shouldBeRemoved(identifierPath)) {
98
+ hasRemoved = true;
99
+ pattern.node.elements[index] = null;
100
100
  }
101
101
  });
102
- if (beforeCount !== referencesRemovedInThisPass && pattern.get("elements").length < 1) {
102
+ if (hasRemoved && pattern.node.elements.every((element) => element === null)) {
103
103
  path.remove();
104
+ ++referencesRemovedInThisPass;
104
105
  }
105
106
  }
106
107
  },
@@ -1 +1 @@
1
- {"version":3,"file":"eliminateUnreferencedIdentifiers.cjs","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":["t"],"mappings":"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"}
1
+ {"version":3,"file":"eliminateUnreferencedIdentifiers.cjs","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 let hasRemoved = false as boolean\n\n pattern.get('elements').forEach((element, index) => {\n // if (!element) return // Skip holes in the pattern\n\n let identifierPath: NodePath<BabelTypes.Identifier>\n\n if (t.isIdentifier(element.node)) {\n identifierPath = element as NodePath<BabelTypes.Identifier>\n } else if (t.isRestElement(element.node)) {\n identifierPath = element.get(\n 'argument',\n ) as NodePath<BabelTypes.Identifier>\n } else {\n // For now, ignore other types like AssignmentPattern\n return\n }\n\n if (shouldBeRemoved(identifierPath)) {\n hasRemoved = true\n pattern.node.elements[index] = null // Remove the element by setting it to null\n }\n })\n\n // If any elements were removed and no elements are left, remove the entire declaration\n if (\n hasRemoved &&\n pattern.node.elements.every((element) => element === null)\n ) {\n path.remove()\n ++referencesRemovedInThisPass\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":["t"],"mappings":"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"}
@@ -99,25 +99,12 @@ function TanStackRouterViteCodeSplitter(inlineConfig = {}) {
99
99
  root: ROOT
100
100
  });
101
101
  if (id.includes(constants.splitPrefix)) {
102
- console.info("Splitting route: ", id);
103
102
  const compiled = await compilers.splitFile({
104
103
  code,
105
104
  compile,
106
105
  filename: id
107
106
  // ref,
108
107
  });
109
- console.info("");
110
- console.info("Split Output");
111
- console.info("");
112
- console.info(compiled.code);
113
- console.info("");
114
- console.info("");
115
- console.info("");
116
- console.info("");
117
- console.info("");
118
- console.info("");
119
- console.info("");
120
- console.info("");
121
108
  return compiled;
122
109
  } else if (fileIsInRoutesDirectory(id, userConfig.routesDirectory) && (code.includes("createRoute(") || code.includes("createFileRoute("))) {
123
110
  if (code.includes("@react-refresh")) {
@@ -132,26 +119,11 @@ plugins: [
132
119
  `
133
120
  );
134
121
  }
135
- console.info("Handling createRoute: ", id);
136
122
  const compiled = await compilers.compileFile({
137
123
  code,
138
124
  compile,
139
125
  filename: id
140
126
  });
141
- console.info("");
142
- console.info("Compiled Output");
143
- console.info("");
144
- console.info(compiled.code);
145
- console.info("");
146
- console.info("");
147
- console.info("");
148
- console.info("");
149
- console.info("");
150
- console.info("");
151
- console.info("");
152
- console.info("");
153
- console.info("");
154
- console.info("");
155
127
  return compiled;
156
128
  }
157
129
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","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 = true 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","z","getGeneratorConfig","generator","normalize","join","isAbsolute","splitPrefix","url","pathToFileURL","fileURLToPath","makeCompile","splitFile","compileFile"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","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","z","getGeneratorConfig","generator","normalize","join","isAbsolute","splitPrefix","url","pathToFileURL","fileURLToPath","makeCompile","splitFile","compileFile"],"mappings":"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"}
@@ -63,25 +63,26 @@ const eliminateUnreferencedIdentifiers = (programPath, refs) => {
63
63
  }
64
64
  } else if (path.node.id.type === "ArrayPattern") {
65
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");
66
+ let hasRemoved = false;
67
+ pattern.get("elements").forEach((element, index) => {
68
+ let identifierPath;
69
+ if (t.isIdentifier(element.node)) {
70
+ identifierPath = element;
71
+ } else if (t.isRestElement(element.node)) {
72
+ identifierPath = element.get(
73
+ "argument"
74
+ );
75
75
  } else {
76
76
  return;
77
77
  }
78
- if (shouldBeRemoved(local)) {
79
- ++referencesRemovedInThisPass;
80
- e.remove();
78
+ if (shouldBeRemoved(identifierPath)) {
79
+ hasRemoved = true;
80
+ pattern.node.elements[index] = null;
81
81
  }
82
82
  });
83
- if (beforeCount !== referencesRemovedInThisPass && pattern.get("elements").length < 1) {
83
+ if (hasRemoved && pattern.node.elements.every((element) => element === null)) {
84
84
  path.remove();
85
+ ++referencesRemovedInThisPass;
85
86
  }
86
87
  }
87
88
  },
@@ -1 +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
+ {"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 let hasRemoved = false as boolean\n\n pattern.get('elements').forEach((element, index) => {\n // if (!element) return // Skip holes in the pattern\n\n let identifierPath: NodePath<BabelTypes.Identifier>\n\n if (t.isIdentifier(element.node)) {\n identifierPath = element as NodePath<BabelTypes.Identifier>\n } else if (t.isRestElement(element.node)) {\n identifierPath = element.get(\n 'argument',\n ) as NodePath<BabelTypes.Identifier>\n } else {\n // For now, ignore other types like AssignmentPattern\n return\n }\n\n if (shouldBeRemoved(identifierPath)) {\n hasRemoved = true\n pattern.node.elements[index] = null // Remove the element by setting it to null\n }\n })\n\n // If any elements were removed and no elements are left, remove the entire declaration\n if (\n hasRemoved &&\n pattern.node.elements.every((element) => element === null)\n ) {\n path.remove()\n ++referencesRemovedInThisPass\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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"}
package/dist/esm/index.js CHANGED
@@ -97,25 +97,12 @@ function TanStackRouterViteCodeSplitter(inlineConfig = {}) {
97
97
  root: ROOT
98
98
  });
99
99
  if (id.includes(splitPrefix)) {
100
- console.info("Splitting route: ", id);
101
100
  const compiled = await splitFile({
102
101
  code,
103
102
  compile,
104
103
  filename: id
105
104
  // ref,
106
105
  });
107
- console.info("");
108
- console.info("Split Output");
109
- console.info("");
110
- console.info(compiled.code);
111
- console.info("");
112
- console.info("");
113
- console.info("");
114
- console.info("");
115
- console.info("");
116
- console.info("");
117
- console.info("");
118
- console.info("");
119
106
  return compiled;
120
107
  } else if (fileIsInRoutesDirectory(id, userConfig.routesDirectory) && (code.includes("createRoute(") || code.includes("createFileRoute("))) {
121
108
  if (code.includes("@react-refresh")) {
@@ -130,26 +117,11 @@ plugins: [
130
117
  `
131
118
  );
132
119
  }
133
- console.info("Handling createRoute: ", id);
134
120
  const compiled = await compileFile({
135
121
  code,
136
122
  compile,
137
123
  filename: id
138
124
  });
139
- console.info("");
140
- console.info("Compiled Output");
141
- console.info("");
142
- console.info(compiled.code);
143
- console.info("");
144
- console.info("");
145
- console.info("");
146
- console.info("");
147
- console.info("");
148
- console.info("");
149
- console.info("");
150
- console.info("");
151
- console.info("");
152
- console.info("");
153
125
  return compiled;
154
126
  }
155
127
  return null;
@@ -1 +1 @@
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 = true 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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"}
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.25.0",
3
+ "version": "1.26.8",
4
4
  "description": "",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -197,29 +197,37 @@ export const eliminateUnreferencedIdentifiers = (
197
197
  } else if (path.node.id.type === 'ArrayPattern') {
198
198
  const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>
199
199
 
200
- const beforeCount = referencesRemovedInThisPass
201
- const elements = pattern.get('elements')
202
- elements.forEach((e) => {
203
- let local: NodePath<BabelTypes.Identifier>
204
- if (e.node?.type === 'Identifier') {
205
- local = e as NodePath<BabelTypes.Identifier>
206
- } else if (e.node?.type === 'RestElement') {
207
- local = e.get('argument') as NodePath<BabelTypes.Identifier>
200
+ let hasRemoved = false as boolean
201
+
202
+ pattern.get('elements').forEach((element, index) => {
203
+ // if (!element) return // Skip holes in the pattern
204
+
205
+ let identifierPath: NodePath<BabelTypes.Identifier>
206
+
207
+ if (t.isIdentifier(element.node)) {
208
+ identifierPath = element as NodePath<BabelTypes.Identifier>
209
+ } else if (t.isRestElement(element.node)) {
210
+ identifierPath = element.get(
211
+ 'argument',
212
+ ) as NodePath<BabelTypes.Identifier>
208
213
  } else {
214
+ // For now, ignore other types like AssignmentPattern
209
215
  return
210
216
  }
211
217
 
212
- if (shouldBeRemoved(local)) {
213
- ++referencesRemovedInThisPass
214
- e.remove()
218
+ if (shouldBeRemoved(identifierPath)) {
219
+ hasRemoved = true
220
+ pattern.node.elements[index] = null // Remove the element by setting it to null
215
221
  }
216
222
  })
217
223
 
224
+ // If any elements were removed and no elements are left, remove the entire declaration
218
225
  if (
219
- beforeCount !== referencesRemovedInThisPass &&
220
- pattern.get('elements').length < 1
226
+ hasRemoved &&
227
+ pattern.node.elements.every((element) => element === null)
221
228
  ) {
222
229
  path.remove()
230
+ ++referencesRemovedInThisPass
223
231
  }
224
232
  }
225
233
  },
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ export const configSchema = generatorConfigSchema.extend({
22
22
  export type Config = z.infer<typeof configSchema>
23
23
 
24
24
  const CONFIG_FILE_NAME = 'tsr.config.json'
25
- const debug = true as any
25
+ const debug = false as any
26
26
 
27
27
  const getConfig = async (inlineConfig: Partial<Config>, root: string) => {
28
28
  const config = await getGeneratorConfig(inlineConfig, root)
@@ -0,0 +1,12 @@
1
+ import { lazyRouteComponent } from '@tanstack/react-router';
2
+ const $$splitComponentImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/useStateDestructure.tsx?tsr-split');
3
+ import { startProject } from '~/projects/start';
4
+ import { createFileRoute } from '@tanstack/react-router';
5
+ import { seo } from '~/utils/seo';
6
+ export const Route = createFileRoute('/_libraries/start/$version/')({
7
+ component: lazyRouteComponent($$splitComponentImporter, 'component'),
8
+ meta: () => seo({
9
+ title: startProject.name,
10
+ description: startProject.description
11
+ })
12
+ });