@tanstack/router-generator 1.120.5 → 1.121.0-alpha.3

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 (51) hide show
  1. package/dist/cjs/config.cjs +14 -14
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +68 -31
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +1 -5
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +2 -2
  7. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
  8. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +2 -2
  9. package/dist/cjs/generator.cjs +160 -172
  10. package/dist/cjs/generator.cjs.map +1 -1
  11. package/dist/cjs/generator.d.cts +0 -59
  12. package/dist/cjs/index.cjs +23 -2
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/cjs/index.d.cts +8 -4
  15. package/dist/cjs/template.cjs +4 -12
  16. package/dist/cjs/template.cjs.map +1 -1
  17. package/dist/cjs/template.d.cts +0 -1
  18. package/dist/cjs/types.d.cts +1 -1
  19. package/dist/cjs/utils.cjs +64 -5
  20. package/dist/cjs/utils.cjs.map +1 -1
  21. package/dist/cjs/utils.d.cts +11 -2
  22. package/dist/esm/config.d.ts +68 -31
  23. package/dist/esm/config.js +14 -14
  24. package/dist/esm/config.js.map +1 -1
  25. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +2 -2
  26. package/dist/esm/filesystem/physical/getRouteNodes.js +2 -6
  27. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
  28. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +2 -2
  29. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
  30. package/dist/esm/generator.d.ts +0 -59
  31. package/dist/esm/generator.js +163 -175
  32. package/dist/esm/generator.js.map +1 -1
  33. package/dist/esm/index.d.ts +8 -4
  34. package/dist/esm/index.js +25 -4
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/esm/template.d.ts +0 -1
  37. package/dist/esm/template.js +4 -12
  38. package/dist/esm/template.js.map +1 -1
  39. package/dist/esm/types.d.ts +1 -1
  40. package/dist/esm/utils.d.ts +11 -2
  41. package/dist/esm/utils.js +63 -4
  42. package/dist/esm/utils.js.map +1 -1
  43. package/package.json +3 -3
  44. package/src/config.ts +14 -11
  45. package/src/filesystem/physical/getRouteNodes.ts +13 -14
  46. package/src/filesystem/virtual/getRouteNodes.ts +18 -3
  47. package/src/generator.ts +242 -221
  48. package/src/index.ts +32 -7
  49. package/src/template.ts +4 -15
  50. package/src/types.ts +0 -1
  51. package/src/utils.ts +102 -6
package/src/index.ts CHANGED
@@ -1,9 +1,34 @@
1
- export { configSchema, getConfig, resolveConfigPath } from './config'
2
- export type { Config } from './config'
1
+ export {
2
+ configSchema,
3
+ getConfig,
4
+ resolveConfigPath,
5
+ baseConfigSchema,
6
+ } from './config'
7
+ export type { Config, BaseConfig } from './config'
8
+
9
+ export { generator } from './generator'
3
10
 
4
11
  export {
5
- generator,
6
- startAPIRouteSegmentsFromTSRFilePath,
7
- CONSTANTS,
8
- } from './generator'
9
- export type { StartAPIRoutePathSegment } from './generator'
12
+ logging,
13
+ capitalize,
14
+ cleanPath,
15
+ trimPathLeft,
16
+ removeLeadingSlash,
17
+ removeTrailingSlash,
18
+ determineInitialRoutePath,
19
+ replaceBackslash,
20
+ routePathToVariable,
21
+ removeUnderscores,
22
+ resetRegex,
23
+ multiSortBy,
24
+ writeIfDifferent,
25
+ format,
26
+ removeExt,
27
+ } from './utils'
28
+
29
+ export type { RouteNode, GetRouteNodesResult } from './types'
30
+
31
+ export { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'
32
+ export { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'
33
+
34
+ export { rootPathId } from './filesystem/physical/rootPathId'
package/src/template.ts CHANGED
@@ -77,10 +77,8 @@ export function getTargetTemplate(target: Config['target']): TargetTemplate {
77
77
  'function RouteComponent() { return <div>Hello "%%tsrPath%%"!</div> };\n',
78
78
  ].join(''),
79
79
  imports: {
80
- tsrImports: () =>
81
- "import { createFileRoute } from '@tanstack/react-router';",
82
- tsrExportStart: (routePath) =>
83
- `export const Route = createFileRoute('${routePath}')(`,
80
+ tsrImports: () => '',
81
+ tsrExportStart: () => `export const Route = createFileRoute(`,
84
82
  tsrExportEnd: () => ');',
85
83
  },
86
84
  },
@@ -130,10 +128,8 @@ export function getTargetTemplate(target: Config['target']): TargetTemplate {
130
128
  'function RouteComponent() { return <div>Hello "%%tsrPath%%"!</div> };\n',
131
129
  ].join(''),
132
130
  imports: {
133
- tsrImports: () =>
134
- "import { createFileRoute } from '@tanstack/solid-router';",
135
- tsrExportStart: (routePath) =>
136
- `export const Route = createFileRoute('${routePath}')(`,
131
+ tsrImports: () => '',
132
+ tsrExportStart: () => `export const Route = createFileRoute(`,
137
133
  tsrExportEnd: () => ');',
138
134
  },
139
135
  },
@@ -158,10 +154,3 @@ export function getTargetTemplate(target: Config['target']): TargetTemplate {
158
154
  throw new Error(`router-generator: Unknown target type: ${target}`)
159
155
  }
160
156
  }
161
-
162
- export const defaultAPIRouteTemplate = [
163
- 'import { json } from "@tanstack/react-start";\n',
164
- '%%tsrImports%%',
165
- '\n\n',
166
- '%%tsrExportStart%%{ GET: ({ request, params }) => { return json({ message:\'Hello "%%tsrPath%%"!\' }) }}%%tsrExportEnd%%\n',
167
- ].join('')
package/src/types.ts CHANGED
@@ -25,7 +25,6 @@ export type FsRouteType =
25
25
  | 'layout'
26
26
  | 'pathless_layout'
27
27
  | 'lazy'
28
- | 'api'
29
28
  | 'loader' // @deprecated
30
29
  | 'component' // @deprecated
31
30
  | 'pendingComponent' // @deprecated
package/src/utils.ts CHANGED
@@ -1,6 +1,5 @@
1
- import * as fs from 'node:fs'
1
+ import * as fsp from 'node:fs/promises'
2
2
  import * as prettier from 'prettier'
3
- import type { Config } from './config'
4
3
 
5
4
  export function multiSortBy<T>(
6
5
  arr: Array<T>,
@@ -86,7 +85,55 @@ export function removeTrailingSlash(s: string) {
86
85
  }
87
86
 
88
87
  export function determineInitialRoutePath(routePath: string) {
89
- return cleanPath(`/${routePath.split('.').join('/')}`) || ''
88
+ const DISALLOWED_ESCAPE_CHARS = new Set([
89
+ '/',
90
+ '\\',
91
+ '?',
92
+ '#',
93
+ ':',
94
+ '*',
95
+ '<',
96
+ '>',
97
+ '|',
98
+ '!',
99
+ '$',
100
+ '%',
101
+ ])
102
+
103
+ const parts = routePath.split(/(?<!\[)\.(?!\])/g)
104
+
105
+ // Escape any characters that in square brackets
106
+ const escapedParts = parts.map((part) => {
107
+ // Check if any disallowed characters are used in brackets
108
+ const BRACKET_CONTENT_RE = /\[(.*?)\]/g
109
+
110
+ let match
111
+ while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {
112
+ const character = match[1]
113
+ if (character === undefined) continue
114
+ if (DISALLOWED_ESCAPE_CHARS.has(character)) {
115
+ console.error(
116
+ `Error: Disallowed character "${character}" found in square brackets in route path "${routePath}".\nYou cannot use any of the following characters in square brackets: ${Array.from(
117
+ DISALLOWED_ESCAPE_CHARS,
118
+ ).join(', ')}\nPlease remove and/or replace them.`,
119
+ )
120
+ process.exit(1)
121
+ }
122
+ }
123
+
124
+ // Since this split segment is safe at this point, we can
125
+ // remove the brackets and replace them with the content inside
126
+ return part.replace(/\[(.)\]/g, '$1')
127
+ })
128
+
129
+ // If the syntax for prefix/suffix is different, from the path
130
+ // matching internals of router-core, we'd perform those changes here
131
+ // on the `escapedParts` array before it is joined back together in
132
+ // `final`
133
+
134
+ const final = cleanPath(`/${escapedParts.join('/')}`) || ''
135
+
136
+ return final
90
137
  }
91
138
 
92
139
  export function replaceBackslash(s: string) {
@@ -94,15 +141,43 @@ export function replaceBackslash(s: string) {
94
141
  }
95
142
 
96
143
  export function routePathToVariable(routePath: string): string {
144
+ const toVariableSafeChar = (char: string): string => {
145
+ if (/[a-zA-Z0-9_]/.test(char)) {
146
+ return char // Keep alphanumeric characters and underscores as is
147
+ }
148
+
149
+ // Replace special characters with meaningful text equivalents
150
+ switch (char) {
151
+ case '.':
152
+ return 'Dot'
153
+ case '-':
154
+ return 'Dash'
155
+ case '@':
156
+ return 'At'
157
+ case '(':
158
+ return '' // Removed since route groups use parentheses
159
+ case ')':
160
+ return '' // Removed since route groups use parentheses
161
+ case ' ':
162
+ return '' // Remove spaces
163
+ default:
164
+ return `Char${char.charCodeAt(0)}` // For any other characters
165
+ }
166
+ }
167
+
97
168
  return (
98
169
  removeUnderscores(routePath)
99
170
  ?.replace(/\/\$\//g, '/splat/')
100
171
  .replace(/\$$/g, 'splat')
172
+ .replace(/\$\{\$\}/g, 'splat')
101
173
  .replace(/\$/g, '')
102
174
  .split(/[/-]/g)
103
175
  .map((d, i) => (i > 0 ? capitalize(d) : d))
104
176
  .join('')
105
- .replace(/([^a-zA-Z0-9]|[.])/gm, '')
177
+ .split('')
178
+ .map(toVariableSafeChar)
179
+ .join('')
180
+ // .replace(/([^a-zA-Z0-9]|[.])/gm, '')
106
181
  .replace(/^(\d)/g, 'R$1') ?? ''
107
182
  )
108
183
  }
@@ -137,7 +212,7 @@ export async function writeIfDifferent(
137
212
  ): Promise<boolean> {
138
213
  if (content !== incomingContent) {
139
214
  callbacks?.beforeWrite?.()
140
- fs.writeFileSync(filepath, incomingContent)
215
+ await fsp.writeFile(filepath, incomingContent)
141
216
  callbacks?.afterWrite?.()
142
217
  return true
143
218
  }
@@ -151,7 +226,13 @@ export async function writeIfDifferent(
151
226
  * @param config The configuration object
152
227
  * @returns The formatted content
153
228
  */
154
- export async function format(source: string, config: Config): Promise<string> {
229
+ export async function format(
230
+ source: string,
231
+ config: {
232
+ quoteStyle: 'single' | 'double'
233
+ semicolons: boolean
234
+ },
235
+ ): Promise<string> {
155
236
  const prettierOptions: prettier.Config = {
156
237
  semi: config.semicolons,
157
238
  singleQuote: config.quoteStyle === 'single',
@@ -172,3 +253,18 @@ export function resetRegex(regex: RegExp) {
172
253
  regex.lastIndex = 0
173
254
  return
174
255
  }
256
+
257
+ /**
258
+ * This function checks if a file exists.
259
+ *
260
+ * @param file The path to the file
261
+ * @returns Whether the file exists
262
+ */
263
+ export async function checkFileExists(file: string) {
264
+ try {
265
+ await fsp.access(file, fsp.constants.F_OK)
266
+ return true
267
+ } catch {
268
+ return false
269
+ }
270
+ }