@tanstack/router-plugin 1.121.4 → 1.121.7

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 (34) hide show
  1. package/dist/cjs/core/route-autoimport-plugin.cjs +51 -45
  2. package/dist/cjs/core/route-autoimport-plugin.cjs.map +1 -1
  3. package/dist/cjs/core/router-code-splitter-plugin.cjs +60 -54
  4. package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
  5. package/dist/cjs/core/router-composed-plugin.cjs +7 -1
  6. package/dist/cjs/core/router-composed-plugin.cjs.map +1 -1
  7. package/dist/cjs/core/router-generator-plugin.cjs +18 -19
  8. package/dist/cjs/core/router-generator-plugin.cjs.map +1 -1
  9. package/dist/cjs/core/router-hmr-plugin.cjs +26 -24
  10. package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
  11. package/dist/cjs/core/utils.cjs +0 -7
  12. package/dist/cjs/core/utils.cjs.map +1 -1
  13. package/dist/cjs/core/utils.d.cts +0 -1
  14. package/dist/esm/core/route-autoimport-plugin.js +52 -46
  15. package/dist/esm/core/route-autoimport-plugin.js.map +1 -1
  16. package/dist/esm/core/router-code-splitter-plugin.js +62 -56
  17. package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
  18. package/dist/esm/core/router-composed-plugin.js +7 -1
  19. package/dist/esm/core/router-composed-plugin.js.map +1 -1
  20. package/dist/esm/core/router-generator-plugin.js +19 -20
  21. package/dist/esm/core/router-generator-plugin.js.map +1 -1
  22. package/dist/esm/core/router-hmr-plugin.js +27 -25
  23. package/dist/esm/core/router-hmr-plugin.js.map +1 -1
  24. package/dist/esm/core/utils.d.ts +0 -1
  25. package/dist/esm/core/utils.js +1 -8
  26. package/dist/esm/core/utils.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/core/route-autoimport-plugin.ts +57 -53
  29. package/src/core/router-code-splitter-plugin.ts +69 -75
  30. package/src/core/router-composed-plugin.ts +7 -1
  31. package/src/core/router-generator-plugin.ts +23 -24
  32. package/src/core/router-hmr-plugin.ts +24 -23
  33. package/src/core/utils.ts +0 -15
  34. package/src/global.d.ts +5 -0
@@ -2,7 +2,7 @@ import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'
2
2
  import babel from '@babel/core'
3
3
  import * as template from '@babel/template'
4
4
  import { getConfig } from './config'
5
- import { debug, fileIsInRoutesDirectory } from './utils'
5
+ import { debug } from './utils'
6
6
  import type { Config } from './config'
7
7
  import type { UnpluginFactory } from 'unplugin'
8
8
 
@@ -16,70 +16,74 @@ export const unpluginRouteAutoImportFactory: UnpluginFactory<
16
16
  let userConfig = options as Config
17
17
 
18
18
  return {
19
- name: 'router-autoimport-plugin',
19
+ name: 'tanstack-router:autoimport',
20
20
  enforce: 'pre',
21
21
 
22
- transform(code, id) {
23
- let routeType: 'createFileRoute' | 'createLazyFileRoute'
24
- if (code.includes('export const Route = createFileRoute(')) {
25
- routeType = 'createFileRoute'
26
- } else if (code.includes('export const Route = createLazyFileRoute(')) {
27
- routeType = 'createLazyFileRoute'
28
- } else {
29
- return null
30
- }
22
+ transform: {
23
+ filter: {
24
+ code: /createFileRoute\(|createLazyFileRoute\(/,
25
+ },
26
+ handler(code, id) {
27
+ if (!globalThis.TSR_ROUTE_FILES?.has(id)) {
28
+ return null
29
+ }
30
+ let routeType: 'createFileRoute' | 'createLazyFileRoute'
31
+ if (code.includes('createFileRoute(')) {
32
+ routeType = 'createFileRoute'
33
+ } else if (code.includes('createLazyFileRoute(')) {
34
+ routeType = 'createLazyFileRoute'
35
+ } else {
36
+ return null
37
+ }
31
38
 
32
- const routerImportPath = `@tanstack/${userConfig.target}-router`
39
+ const routerImportPath = `@tanstack/${userConfig.target}-router`
33
40
 
34
- const ast = parseAst({ code })
41
+ const ast = parseAst({ code })
35
42
 
36
- let isCreateRouteFunctionImported = false as boolean
43
+ let isCreateRouteFunctionImported = false as boolean
37
44
 
38
- babel.traverse(ast, {
39
- Program: {
40
- enter(programPath) {
41
- programPath.traverse({
42
- ImportDeclaration(path) {
43
- const importedSpecifiers = path.node.specifiers.map(
44
- (specifier) => specifier.local.name,
45
- )
46
- if (
47
- importedSpecifiers.includes(routeType) &&
48
- path.node.source.value === routerImportPath
49
- ) {
50
- isCreateRouteFunctionImported = true
51
- }
52
- },
53
- })
45
+ babel.traverse(ast, {
46
+ Program: {
47
+ enter(programPath) {
48
+ programPath.traverse({
49
+ ImportDeclaration(path) {
50
+ const importedSpecifiers = path.node.specifiers.map(
51
+ (specifier) => specifier.local.name,
52
+ )
53
+ if (
54
+ importedSpecifiers.includes(routeType) &&
55
+ path.node.source.value === routerImportPath
56
+ ) {
57
+ isCreateRouteFunctionImported = true
58
+ }
59
+ },
60
+ })
61
+ },
54
62
  },
55
- },
56
- })
63
+ })
57
64
 
58
- if (!isCreateRouteFunctionImported) {
59
- if (debug) console.info('Adding autoimports to route ', id)
65
+ if (!isCreateRouteFunctionImported) {
66
+ if (debug) console.info('Adding autoimports to route ', id)
60
67
 
61
- const autoImportStatement = template.statement(
62
- `import { ${routeType} } from '${routerImportPath}'`,
63
- )()
64
- ast.program.body.unshift(autoImportStatement)
68
+ const autoImportStatement = template.statement(
69
+ `import { ${routeType} } from '${routerImportPath}'`,
70
+ )()
71
+ ast.program.body.unshift(autoImportStatement)
65
72
 
66
- const result = generateFromAst(ast, {
67
- sourceMaps: true,
68
- filename: id,
69
- sourceFileName: id,
70
- })
71
- if (debug) {
72
- logDiff(code, result.code)
73
- console.log('Output:\n', result.code + '\n\n')
73
+ const result = generateFromAst(ast, {
74
+ sourceMaps: true,
75
+ filename: id,
76
+ sourceFileName: id,
77
+ })
78
+ if (debug) {
79
+ logDiff(code, result.code)
80
+ console.log('Output:\n', result.code + '\n\n')
81
+ }
82
+ return result
74
83
  }
75
- return result
76
- }
77
-
78
- return null
79
- },
80
84
 
81
- transformInclude(id) {
82
- return fileIsInRoutesDirectory(id, userConfig.routesDirectory)
85
+ return null
86
+ },
83
87
  },
84
88
 
85
89
  vite: {
@@ -17,7 +17,7 @@ import {
17
17
  tsrSplit,
18
18
  } from './constants'
19
19
  import { decodeIdentifier } from './code-splitter/path-ids'
20
- import { debug, fileIsInRoutesDirectory } from './utils'
20
+ import { debug } from './utils'
21
21
  import type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'
22
22
 
23
23
  import type { Config } from './config'
@@ -27,10 +27,6 @@ import type {
27
27
  TransformResult as UnpluginTransformResult,
28
28
  } from 'unplugin'
29
29
 
30
- function capitalizeFirst(str: string): string {
31
- return str.charAt(0).toUpperCase() + str.slice(1)
32
- }
33
-
34
30
  type BannedBeforeExternalPlugin = {
35
31
  identifier: string
36
32
  pkg: string
@@ -52,7 +48,7 @@ class FoundPluginInBeforeCode extends Error {
52
48
  super(`We detected that the '${externalPlugin.pkg}' was passed before '@tanstack/router-plugin'. Please make sure that '@tanstack/router-plugin' is passed before '${externalPlugin.pkg}' and try again:
53
49
  e.g.
54
50
  plugins: [
55
- TanStackRouter${capitalizeFirst(framework)}(), // Place this before ${externalPlugin.usage}
51
+ tanstackRouter(), // Place this before ${externalPlugin.usage}
56
52
  ${externalPlugin.usage},
57
53
  ]
58
54
  `)
@@ -171,83 +167,81 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
171
167
  return result
172
168
  }
173
169
 
174
- return {
175
- name: 'router-code-splitter-plugin',
176
- enforce: 'pre',
177
-
178
- transform(code, id) {
179
- if (!userConfig.autoCodeSplitting) {
180
- return null
181
- }
182
-
183
- const url = pathToFileURL(id)
184
- url.searchParams.delete('v')
185
- id = fileURLToPath(url).replace(/\\/g, '/')
186
-
187
- if (id.includes(tsrSplit)) {
188
- return handleCompilingVirtualFile(code, id)
189
- } else if (
190
- fileIsInRoutesDirectory(id, userConfig.routesDirectory) &&
191
- (code.includes('createRoute(') || code.includes('createFileRoute('))
192
- ) {
193
- for (const externalPlugin of bannedBeforeExternalPlugins) {
194
- if (!externalPlugin.frameworks.includes(framework)) {
195
- continue
196
- }
197
-
198
- if (code.includes(externalPlugin.identifier)) {
199
- throw new FoundPluginInBeforeCode(externalPlugin, framework)
170
+ return [
171
+ {
172
+ name: 'tanstack-router:code-splitter:compile-reference-file',
173
+ enforce: 'pre',
174
+
175
+ transform: {
176
+ filter: {
177
+ id: {
178
+ exclude: tsrSplit,
179
+ },
180
+ code: 'createFileRoute(',
181
+ },
182
+ handler(code, id) {
183
+ if (
184
+ globalThis.TSR_ROUTE_FILES?.has(id) &&
185
+ code.includes('createFileRoute(')
186
+ ) {
187
+ for (const externalPlugin of bannedBeforeExternalPlugins) {
188
+ if (!externalPlugin.frameworks.includes(framework)) {
189
+ continue
190
+ }
191
+
192
+ if (code.includes(externalPlugin.identifier)) {
193
+ throw new FoundPluginInBeforeCode(externalPlugin, framework)
194
+ }
195
+ }
196
+
197
+ return handleCompilingReferenceFile(code, id)
200
198
  }
201
- }
202
-
203
- return handleCompilingReferenceFile(code, id)
204
- }
205
-
206
- return null
207
- },
208
-
209
- transformInclude(id) {
210
- if (!userConfig.autoCodeSplitting) {
211
- return undefined
212
- }
213
199
 
214
- if (
215
- fileIsInRoutesDirectory(id, userConfig.routesDirectory) ||
216
- id.includes(tsrSplit)
217
- ) {
218
- return true
219
- }
220
- return false
221
- },
200
+ return null
201
+ },
202
+ },
222
203
 
223
- vite: {
224
- configResolved(config) {
225
- ROOT = config.root
204
+ vite: {
205
+ configResolved(config) {
206
+ ROOT = config.root
207
+ userConfig = getConfig(options, ROOT)
208
+ },
209
+ },
226
210
 
211
+ rspack() {
212
+ ROOT = process.cwd()
227
213
  userConfig = getConfig(options, ROOT)
228
214
  },
229
- },
230
215
 
231
- rspack(_compiler) {
232
- ROOT = process.cwd()
233
- userConfig = getConfig(options, ROOT)
234
- },
216
+ webpack(compiler) {
217
+ ROOT = process.cwd()
218
+ userConfig = getConfig(options, ROOT)
235
219
 
236
- webpack(compiler) {
237
- ROOT = process.cwd()
238
- userConfig = getConfig(options, ROOT)
239
-
240
- if (
241
- userConfig.autoCodeSplitting &&
242
- compiler.options.mode === 'production'
243
- ) {
244
- compiler.hooks.done.tap(PLUGIN_NAME, () => {
245
- console.info('✅ ' + PLUGIN_NAME + ': code-splitting done!')
246
- setTimeout(() => {
247
- process.exit(0)
220
+ if (compiler.options.mode === 'production') {
221
+ compiler.hooks.done.tap(PLUGIN_NAME, () => {
222
+ console.info('✅ ' + PLUGIN_NAME + ': code-splitting done!')
223
+ setTimeout(() => {
224
+ process.exit(0)
225
+ })
248
226
  })
249
- })
250
- }
227
+ }
228
+ },
251
229
  },
252
- }
230
+ {
231
+ name: 'tanstack-router:code-splitter:compile-virtual-file',
232
+ enforce: 'pre',
233
+
234
+ transform: {
235
+ filter: {
236
+ id: /tsr-split/,
237
+ },
238
+ handler(code, id) {
239
+ const url = pathToFileURL(id)
240
+ url.searchParams.delete('v')
241
+ id = fileURLToPath(url).replace(/\\/g, '/')
242
+ return handleCompilingVirtualFile(code, id)
243
+ },
244
+ },
245
+ },
246
+ ]
253
247
  }
@@ -20,7 +20,13 @@ export const unpluginRouterComposedFactory: UnpluginFactory<
20
20
  const routerCodeSplitter = getPlugin(unpluginRouterCodeSplitterFactory)
21
21
  const routeAutoImport = getPlugin(unpluginRouteAutoImportFactory)
22
22
 
23
- const result = [...routerGenerator, ...routerCodeSplitter, ...routeAutoImport]
23
+ const result = [...routerGenerator]
24
+ if (options.autoCodeSplitting) {
25
+ result.push(...routerCodeSplitter)
26
+ }
27
+ if (options.verboseFileRoutes === false) {
28
+ result.push(...routeAutoImport)
29
+ }
24
30
 
25
31
  const isProduction = process.env.NODE_ENV === 'production'
26
32
 
@@ -1,7 +1,8 @@
1
1
  import { isAbsolute, join, normalize } from 'node:path'
2
2
  import { Generator, resolveConfigPath } from '@tanstack/router-generator'
3
-
4
3
  import { getConfig } from './config'
4
+
5
+ import type { GeneratorEvent } from '@tanstack/router-generator'
5
6
  import type { FSWatcher } from 'chokidar'
6
7
  import type { UnpluginFactory } from 'unplugin'
7
8
  import type { Config } from './config'
@@ -31,41 +32,39 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory<
31
32
  })
32
33
  }
33
34
 
34
- const generate = async () => {
35
+ const generate = async (opts?: {
36
+ file: string
37
+ event: 'create' | 'update' | 'delete'
38
+ }) => {
35
39
  if (routeGenerationDisabled()) {
36
40
  return
37
41
  }
38
- try {
39
- await generator.run()
40
- } catch (e) {
41
- console.error(e)
42
+ let generatorEvent: GeneratorEvent | undefined = undefined
43
+ if (opts) {
44
+ const filePath = normalize(opts.file)
45
+ if (filePath === resolveConfigPath({ configDirectory: ROOT })) {
46
+ initConfigAndGenerator()
47
+ return
48
+ }
49
+ generatorEvent = { path: filePath, type: opts.event }
42
50
  }
43
- }
44
-
45
- const handleFile = async (
46
- file: string,
47
- event: 'create' | 'update' | 'delete',
48
- ) => {
49
- const filePath = normalize(file)
50
51
 
51
- if (filePath === resolveConfigPath({ configDirectory: ROOT })) {
52
- initConfigAndGenerator()
53
- return
54
- }
55
52
  try {
56
- await generator.run({ path: filePath, type: event })
53
+ await generator.run(generatorEvent)
54
+ globalThis.TSR_ROUTE_FILES = generator.getRouteFileList()
57
55
  } catch (e) {
58
56
  console.error(e)
59
57
  }
60
58
  }
61
59
 
62
60
  return {
63
- name: 'router-generator-plugin',
61
+ name: 'tanstack:router-generator',
64
62
  enforce: 'pre',
65
63
  async watchChange(id, { event }) {
66
- if (!routeGenerationDisabled()) {
67
- await handleFile(id, event)
68
- }
64
+ await generate({
65
+ file: id,
66
+ event,
67
+ })
69
68
  },
70
69
  async buildStart() {
71
70
  await generate()
@@ -89,7 +88,7 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory<
89
88
 
90
89
  let handle: FSWatcher | null = null
91
90
 
92
- compiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, generate)
91
+ compiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, () => generate())
93
92
 
94
93
  compiler.hooks.watchRun.tapPromise(PLUGIN_NAME, async () => {
95
94
  if (handle) {
@@ -117,7 +116,7 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory<
117
116
 
118
117
  let handle: FSWatcher | null = null
119
118
 
120
- compiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, generate)
119
+ compiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, () => generate())
121
120
 
122
121
  compiler.hooks.watchRun.tapPromise(PLUGIN_NAME, async () => {
123
122
  if (handle) {
@@ -1,7 +1,7 @@
1
1
  import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'
2
2
  import { getConfig } from './config'
3
3
  import { routeHmrStatement } from './route-hmr-statement'
4
- import { debug, fileIsInRoutesDirectory } from './utils'
4
+ import { debug } from './utils'
5
5
  import type { Config } from './config'
6
6
  import type { UnpluginFactory } from 'unplugin'
7
7
 
@@ -17,32 +17,33 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
17
17
  let userConfig = options as Config
18
18
 
19
19
  return {
20
- name: 'router-hmr-plugin',
20
+ name: 'tanstack-router:hmr',
21
21
  enforce: 'pre',
22
22
 
23
- transform(code, id) {
24
- if (!code.includes('export const Route = createFileRoute(')) {
25
- return null
26
- }
27
-
28
- if (debug) console.info('Adding HMR handling to route ', id)
23
+ transform: {
24
+ filter: {
25
+ code: 'createFileRoute(',
26
+ },
27
+ handler(code, id) {
28
+ if (!globalThis.TSR_ROUTE_FILES?.has(id)) {
29
+ return null
30
+ }
29
31
 
30
- const ast = parseAst({ code })
31
- ast.program.body.push(routeHmrStatement)
32
- const result = generateFromAst(ast, {
33
- sourceMaps: true,
34
- filename: id,
35
- sourceFileName: id,
36
- })
37
- if (debug) {
38
- logDiff(code, result.code)
39
- console.log('Output:\n', result.code + '\n\n')
40
- }
41
- return result
42
- },
32
+ if (debug) console.info('Adding HMR handling to route ', id)
43
33
 
44
- transformInclude(id) {
45
- return fileIsInRoutesDirectory(id, userConfig.routesDirectory)
34
+ const ast = parseAst({ code })
35
+ ast.program.body.push(routeHmrStatement)
36
+ const result = generateFromAst(ast, {
37
+ sourceMaps: true,
38
+ filename: id,
39
+ sourceFileName: id,
40
+ })
41
+ if (debug) {
42
+ logDiff(code, result.code)
43
+ console.log('Output:\n', result.code + '\n\n')
44
+ }
45
+ return result
46
+ },
46
47
  },
47
48
 
48
49
  vite: {
package/src/core/utils.ts CHANGED
@@ -1,18 +1,3 @@
1
- import { isAbsolute, join, normalize } from 'node:path'
2
-
3
1
  export const debug =
4
2
  process.env.TSR_VITE_DEBUG &&
5
3
  ['true', 'router-plugin'].includes(process.env.TSR_VITE_DEBUG)
6
-
7
- export function fileIsInRoutesDirectory(
8
- filePath: string,
9
- routesDirectory: string,
10
- ): boolean {
11
- const routesDirectoryPath = isAbsolute(routesDirectory)
12
- ? routesDirectory
13
- : join(process.cwd(), routesDirectory)
14
-
15
- const path = normalize(filePath)
16
-
17
- return path.startsWith(routesDirectoryPath)
18
- }
@@ -0,0 +1,5 @@
1
+ /* eslint-disable no-var */
2
+ declare global {
3
+ var TSR_ROUTE_FILES: Set<string> | undefined
4
+ }
5
+ export {}