@tanstack/cli 0.0.8 → 0.48.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +7 -0
- package/dist/cli.js +481 -0
- package/dist/command-line.js +174 -0
- package/dist/dev-watch.js +290 -0
- package/dist/file-syncer.js +148 -0
- package/dist/index.js +1 -0
- package/dist/mcp/api.js +31 -0
- package/dist/mcp/tools.js +250 -0
- package/dist/mcp/types.js +37 -0
- package/dist/mcp.js +121 -0
- package/dist/options.js +162 -0
- package/dist/types/bin.d.ts +2 -0
- package/dist/types/cli.d.ts +16 -0
- package/dist/types/command-line.d.ts +10 -0
- package/dist/types/dev-watch.d.ts +27 -0
- package/dist/types/file-syncer.d.ts +18 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/mcp/api.d.ts +4 -0
- package/dist/types/mcp/tools.d.ts +2 -0
- package/dist/types/mcp/types.d.ts +217 -0
- package/dist/types/mcp.d.ts +6 -0
- package/dist/types/options.d.ts +8 -0
- package/dist/types/types.d.ts +25 -0
- package/dist/types/ui-environment.d.ts +2 -0
- package/dist/types/ui-prompts.d.ts +12 -0
- package/dist/types/utils.d.ts +8 -0
- package/dist/types.js +1 -0
- package/dist/ui-environment.js +52 -0
- package/dist/ui-prompts.js +244 -0
- package/dist/utils.js +30 -0
- package/package.json +46 -46
- package/src/bin.ts +6 -93
- package/src/cli.ts +692 -0
- package/src/command-line.ts +236 -0
- package/src/dev-watch.ts +430 -0
- package/src/file-syncer.ts +205 -0
- package/src/index.ts +1 -85
- package/src/mcp.ts +190 -0
- package/src/options.ts +260 -0
- package/src/types.ts +27 -0
- package/src/ui-environment.ts +74 -0
- package/src/ui-prompts.ts +322 -0
- package/src/utils.ts +38 -0
- package/tests/command-line.test.ts +304 -0
- package/tests/index.test.ts +9 -0
- package/tests/mcp.test.ts +225 -0
- package/tests/options.test.ts +304 -0
- package/tests/setupVitest.ts +6 -0
- package/tests/ui-environment.test.ts +97 -0
- package/tests/ui-prompts.test.ts +238 -0
- package/tsconfig.json +17 -0
- package/vitest.config.js +7 -0
- package/dist/bin.cjs +0 -769
- package/dist/bin.d.cts +0 -1
- package/dist/bin.d.mts +0 -1
- package/dist/bin.mjs +0 -768
- package/dist/fetch-CbFFGJEw.cjs +0 -3
- package/dist/fetch-DG5dLrsb.cjs +0 -522
- package/dist/fetch-DhlVXS6S.mjs +0 -390
- package/dist/fetch-I_OVg8JX.mjs +0 -3
- package/dist/index.cjs +0 -37
- package/dist/index.d.cts +0 -1172
- package/dist/index.d.mts +0 -1172
- package/dist/index.mjs +0 -4
- package/dist/template-Szi7-AZJ.mjs +0 -2202
- package/dist/template-lWrIZhCQ.cjs +0 -2314
- package/src/api/fetch.test.ts +0 -114
- package/src/api/fetch.ts +0 -278
- package/src/cache/index.ts +0 -89
- package/src/commands/create.ts +0 -470
- package/src/commands/mcp.test.ts +0 -152
- package/src/commands/mcp.ts +0 -211
- package/src/engine/compile-with-addons.test.ts +0 -302
- package/src/engine/compile.test.ts +0 -404
- package/src/engine/compile.ts +0 -569
- package/src/engine/config-file.test.ts +0 -118
- package/src/engine/config-file.ts +0 -61
- package/src/engine/custom-addons/integration.ts +0 -323
- package/src/engine/custom-addons/shared.test.ts +0 -98
- package/src/engine/custom-addons/shared.ts +0 -281
- package/src/engine/custom-addons/template.test.ts +0 -288
- package/src/engine/custom-addons/template.ts +0 -124
- package/src/engine/template.test.ts +0 -256
- package/src/engine/template.ts +0 -269
- package/src/engine/types.ts +0 -336
- package/src/parse-gitignore.d.ts +0 -5
- package/src/templates/base.ts +0 -883
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
createTemplateContext,
|
|
4
|
-
processTemplateFile,
|
|
5
|
-
relativePath,
|
|
6
|
-
} from './template.js'
|
|
7
|
-
import type { CompileOptions } from './types.js'
|
|
8
|
-
|
|
9
|
-
const baseOptions: CompileOptions = {
|
|
10
|
-
projectName: 'test-project',
|
|
11
|
-
framework: 'react',
|
|
12
|
-
mode: 'file-router',
|
|
13
|
-
typescript: true,
|
|
14
|
-
tailwind: true,
|
|
15
|
-
packageManager: 'pnpm',
|
|
16
|
-
chosenIntegrations: [],
|
|
17
|
-
integrationOptions: {},
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
describe('relativePath', () => {
|
|
21
|
-
it('should calculate relative path between files in same directory', () => {
|
|
22
|
-
expect(relativePath('src/routes/index.tsx', 'src/routes/about.tsx')).toBe(
|
|
23
|
-
'./about.tsx',
|
|
24
|
-
)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('should calculate relative path going up directories', () => {
|
|
28
|
-
expect(
|
|
29
|
-
relativePath('src/routes/demo/test.tsx', 'src/integrations/query/client.ts'),
|
|
30
|
-
).toBe('../../integrations/query/client.ts')
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should calculate relative path going down directories', () => {
|
|
34
|
-
expect(relativePath('src/index.tsx', 'src/routes/demo/test.tsx')).toBe(
|
|
35
|
-
'./routes/demo/test.tsx',
|
|
36
|
-
)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should strip extension when requested', () => {
|
|
40
|
-
expect(
|
|
41
|
-
relativePath('src/routes/index.tsx', 'src/integrations/query/client.ts', true),
|
|
42
|
-
).toBe('../integrations/query/client')
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
describe('createTemplateContext', () => {
|
|
47
|
-
it('should create context with correct project config', () => {
|
|
48
|
-
const ctx = createTemplateContext(baseOptions, 'src/index.tsx')
|
|
49
|
-
|
|
50
|
-
expect(ctx.projectName).toBe('test-project')
|
|
51
|
-
expect(ctx.packageManager).toBe('pnpm')
|
|
52
|
-
expect(ctx.typescript).toBe(true)
|
|
53
|
-
expect(ctx.tailwind).toBe(true)
|
|
54
|
-
expect(ctx.js).toBe('ts')
|
|
55
|
-
expect(ctx.jsx).toBe('tsx')
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('should set router mode flags correctly for file-router', () => {
|
|
59
|
-
const ctx = createTemplateContext(baseOptions, 'src/index.tsx')
|
|
60
|
-
|
|
61
|
-
expect(ctx.fileRouter).toBe(true)
|
|
62
|
-
expect(ctx.codeRouter).toBe(false)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('should set router mode flags correctly for code-router', () => {
|
|
66
|
-
const ctx = createTemplateContext(
|
|
67
|
-
{ ...baseOptions, mode: 'code-router' },
|
|
68
|
-
'src/index.tsx',
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
expect(ctx.fileRouter).toBe(false)
|
|
72
|
-
expect(ctx.codeRouter).toBe(true)
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('should generate correct package manager scripts for pnpm', () => {
|
|
76
|
-
const ctx = createTemplateContext(baseOptions, 'src/index.tsx')
|
|
77
|
-
|
|
78
|
-
expect(ctx.getPackageManagerAddScript('react')).toBe('pnpm add react')
|
|
79
|
-
expect(ctx.getPackageManagerAddScript('vitest', true)).toBe('pnpm add -D vitest')
|
|
80
|
-
expect(ctx.getPackageManagerRunScript('dev')).toBe('pnpm dev')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('should generate correct package manager scripts for npm', () => {
|
|
84
|
-
const ctx = createTemplateContext(
|
|
85
|
-
{ ...baseOptions, packageManager: 'npm' },
|
|
86
|
-
'src/index.tsx',
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
expect(ctx.getPackageManagerAddScript('react')).toBe('npm install react')
|
|
90
|
-
expect(ctx.getPackageManagerAddScript('vitest', true)).toBe('npm install -D vitest')
|
|
91
|
-
expect(ctx.getPackageManagerRunScript('dev')).toBe('npm run dev')
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('should collect hooks from integrations', () => {
|
|
95
|
-
const ctx = createTemplateContext(
|
|
96
|
-
{
|
|
97
|
-
...baseOptions,
|
|
98
|
-
chosenIntegrations: [
|
|
99
|
-
{
|
|
100
|
-
id: 'test',
|
|
101
|
-
name: 'Test',
|
|
102
|
-
description: 'Test integration',
|
|
103
|
-
type: 'integration',
|
|
104
|
-
phase: 'integration',
|
|
105
|
-
modes: ['file-router'],
|
|
106
|
-
files: {},
|
|
107
|
-
deletedFiles: [],
|
|
108
|
-
hooks: [
|
|
109
|
-
{ type: 'root-provider', jsName: 'TestProvider', path: 'src/test.tsx' },
|
|
110
|
-
],
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
},
|
|
114
|
-
'src/index.tsx',
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
expect(ctx.hooks).toHaveLength(1)
|
|
118
|
-
expect(ctx.hooks[0]?.jsName).toBe('TestProvider')
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('should build integrationEnabled map', () => {
|
|
122
|
-
const ctx = createTemplateContext(
|
|
123
|
-
{
|
|
124
|
-
...baseOptions,
|
|
125
|
-
chosenIntegrations: [
|
|
126
|
-
{
|
|
127
|
-
id: 'tanstack-query',
|
|
128
|
-
name: 'TanStack Query',
|
|
129
|
-
description: 'Data fetching',
|
|
130
|
-
type: 'integration',
|
|
131
|
-
phase: 'integration',
|
|
132
|
-
modes: ['file-router'],
|
|
133
|
-
files: {},
|
|
134
|
-
deletedFiles: [],
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
},
|
|
138
|
-
'src/index.tsx',
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
expect(ctx.integrationEnabled['tanstack-query']).toBe(true)
|
|
142
|
-
expect(ctx.integrationEnabled['clerk']).toBeUndefined()
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
describe('processTemplateFile', () => {
|
|
147
|
-
it('should pass through non-EJS files unchanged', () => {
|
|
148
|
-
const result = processTemplateFile(
|
|
149
|
-
'src/utils.ts',
|
|
150
|
-
'export const foo = 1',
|
|
151
|
-
baseOptions,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
expect(result).not.toBeNull()
|
|
155
|
-
expect(result!.path).toBe('src/utils.ts')
|
|
156
|
-
expect(result!.content).toBe('export const foo = 1')
|
|
157
|
-
expect(result!.append).toBe(false)
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it('should process EJS templates', () => {
|
|
161
|
-
const result = processTemplateFile(
|
|
162
|
-
'src/config.ts.ejs',
|
|
163
|
-
'export const name = "<%= projectName %>"',
|
|
164
|
-
baseOptions,
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
expect(result).not.toBeNull()
|
|
168
|
-
expect(result!.path).toBe('src/config.ts')
|
|
169
|
-
expect(result!.content).toBe('export const name = "test-project"')
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
it('should convert _dot_ prefix to dot', () => {
|
|
173
|
-
const result = processTemplateFile(
|
|
174
|
-
'_dot_gitignore',
|
|
175
|
-
'node_modules',
|
|
176
|
-
baseOptions,
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
expect(result).not.toBeNull()
|
|
180
|
-
expect(result!.path).toBe('.gitignore')
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('should handle .append suffix', () => {
|
|
184
|
-
const result = processTemplateFile(
|
|
185
|
-
'src/styles.css.append',
|
|
186
|
-
'.new-class { }',
|
|
187
|
-
baseOptions,
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
expect(result).not.toBeNull()
|
|
191
|
-
expect(result!.path).toBe('src/styles.css')
|
|
192
|
-
expect(result!.append).toBe(true)
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('should convert .ts to .js when typescript is disabled', () => {
|
|
196
|
-
const result = processTemplateFile('src/utils.ts', 'const x = 1', {
|
|
197
|
-
...baseOptions,
|
|
198
|
-
typescript: false,
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
expect(result).not.toBeNull()
|
|
202
|
-
expect(result!.path).toBe('src/utils.js')
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
it('should convert .tsx to .jsx when typescript is disabled', () => {
|
|
206
|
-
const result = processTemplateFile(
|
|
207
|
-
'src/App.tsx',
|
|
208
|
-
'export default () => <div />',
|
|
209
|
-
{ ...baseOptions, typescript: false },
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
expect(result).not.toBeNull()
|
|
213
|
-
expect(result!.path).toBe('src/App.jsx')
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
it('should return null when ignoreFile() is called', () => {
|
|
217
|
-
const result = processTemplateFile(
|
|
218
|
-
'src/conditional.ts.ejs',
|
|
219
|
-
'<% ignoreFile() %>',
|
|
220
|
-
baseOptions,
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
expect(result).toBeNull()
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('should process conditional EJS based on integrations', () => {
|
|
227
|
-
const withQuery = processTemplateFile(
|
|
228
|
-
'src/test.ts.ejs',
|
|
229
|
-
'<% if (integrationEnabled["tanstack-query"]) { %>query enabled<% } else { %>no query<% } %>',
|
|
230
|
-
{
|
|
231
|
-
...baseOptions,
|
|
232
|
-
chosenIntegrations: [
|
|
233
|
-
{
|
|
234
|
-
id: 'tanstack-query',
|
|
235
|
-
name: 'TanStack Query',
|
|
236
|
-
description: 'Data fetching',
|
|
237
|
-
type: 'integration',
|
|
238
|
-
phase: 'integration',
|
|
239
|
-
modes: ['file-router'],
|
|
240
|
-
files: {},
|
|
241
|
-
deletedFiles: [],
|
|
242
|
-
},
|
|
243
|
-
],
|
|
244
|
-
},
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
const withoutQuery = processTemplateFile(
|
|
248
|
-
'src/test.ts.ejs',
|
|
249
|
-
'<% if (integrationEnabled["tanstack-query"]) { %>query enabled<% } else { %>no query<% } %>',
|
|
250
|
-
baseOptions,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
expect(withQuery!.content).toBe('query enabled')
|
|
254
|
-
expect(withoutQuery!.content).toBe('no query')
|
|
255
|
-
})
|
|
256
|
-
})
|
package/src/engine/template.ts
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { render } from 'ejs'
|
|
2
|
-
import type {
|
|
3
|
-
CompileOptions,
|
|
4
|
-
Hook,
|
|
5
|
-
IntegrationCompiled,
|
|
6
|
-
Route,
|
|
7
|
-
} from './types.js'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Convert _dot_ prefixes to actual dots (for dotfiles)
|
|
11
|
-
*/
|
|
12
|
-
function convertDotFiles(path: string): string {
|
|
13
|
-
return path
|
|
14
|
-
.split('/')
|
|
15
|
-
.map((segment) => segment.replace(/^_dot_/, '.'))
|
|
16
|
-
.join('/')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Strip option prefixes from filename
|
|
21
|
-
* e.g., __postgres__schema.prisma -> schema.prisma
|
|
22
|
-
*/
|
|
23
|
-
function stripOptionPrefix(path: string): string {
|
|
24
|
-
const match = path.match(/^(.+\/)?__([^_]+)__(.+)$/)
|
|
25
|
-
if (match) {
|
|
26
|
-
const [, directory, , filename] = match
|
|
27
|
-
return (directory || '') + filename
|
|
28
|
-
}
|
|
29
|
-
return path
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Calculate relative path between two file paths
|
|
34
|
-
*/
|
|
35
|
-
export function relativePath(
|
|
36
|
-
from: string,
|
|
37
|
-
to: string,
|
|
38
|
-
stripExtension: boolean = false,
|
|
39
|
-
): string {
|
|
40
|
-
const fromParts = from.split('/').slice(0, -1) // Remove filename
|
|
41
|
-
const toParts = to.split('/')
|
|
42
|
-
|
|
43
|
-
// Find common prefix length
|
|
44
|
-
let commonLength = 0
|
|
45
|
-
while (
|
|
46
|
-
commonLength < fromParts.length &&
|
|
47
|
-
commonLength < toParts.length &&
|
|
48
|
-
fromParts[commonLength] === toParts[commonLength]
|
|
49
|
-
) {
|
|
50
|
-
commonLength++
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Build relative path
|
|
54
|
-
const upCount = fromParts.length - commonLength
|
|
55
|
-
const ups = Array(upCount).fill('..')
|
|
56
|
-
const remainder = toParts.slice(commonLength)
|
|
57
|
-
|
|
58
|
-
let result = [...ups, ...remainder].join('/')
|
|
59
|
-
if (!result.startsWith('.')) {
|
|
60
|
-
result = './' + result
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (stripExtension) {
|
|
64
|
-
result = result.replace(/\.[^/.]+$/, '')
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return result
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Error thrown when ignoreFile() is called in a template
|
|
72
|
-
*/
|
|
73
|
-
class IgnoreFileError extends Error {
|
|
74
|
-
constructor() {
|
|
75
|
-
super('ignoreFile')
|
|
76
|
-
this.name = 'IgnoreFileError'
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface TemplateContext {
|
|
81
|
-
// Project config
|
|
82
|
-
packageManager: string
|
|
83
|
-
projectName: string
|
|
84
|
-
typescript: boolean
|
|
85
|
-
tailwind: boolean
|
|
86
|
-
js: 'ts' | 'js'
|
|
87
|
-
jsx: 'tsx' | 'jsx'
|
|
88
|
-
|
|
89
|
-
// Router mode
|
|
90
|
-
fileRouter: boolean
|
|
91
|
-
codeRouter: boolean
|
|
92
|
-
|
|
93
|
-
// Integration state
|
|
94
|
-
integrationEnabled: Record<string, boolean>
|
|
95
|
-
integrationOption: Record<string, Record<string, unknown>>
|
|
96
|
-
integrations: Array<IntegrationCompiled>
|
|
97
|
-
hooks: Array<Hook>
|
|
98
|
-
routes: Array<Route>
|
|
99
|
-
|
|
100
|
-
// Helper functions
|
|
101
|
-
getPackageManagerAddScript: (pkg: string, isDev?: boolean) => string
|
|
102
|
-
getPackageManagerRunScript: (script: string, args?: Array<string>) => string
|
|
103
|
-
relativePath: (to: string, stripExt?: boolean) => string
|
|
104
|
-
hookImportContent: (hook: Hook) => string
|
|
105
|
-
hookImportCode: (hook: Hook) => string
|
|
106
|
-
ignoreFile: () => never
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Create template context from compile options
|
|
111
|
-
*/
|
|
112
|
-
export function createTemplateContext(
|
|
113
|
-
options: CompileOptions,
|
|
114
|
-
currentFile: string,
|
|
115
|
-
): TemplateContext {
|
|
116
|
-
// Collect all hooks from chosen integrations
|
|
117
|
-
const hooks: Array<Hook> = []
|
|
118
|
-
for (const integration of options.chosenIntegrations) {
|
|
119
|
-
if (integration.hooks) {
|
|
120
|
-
hooks.push(...integration.hooks)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Collect all routes from chosen integrations
|
|
125
|
-
const routes: Array<Route> = []
|
|
126
|
-
for (const integration of options.chosenIntegrations) {
|
|
127
|
-
if (integration.routes) {
|
|
128
|
-
routes.push(...integration.routes)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Build integration enabled map
|
|
133
|
-
const integrationEnabled: Record<string, boolean> = {}
|
|
134
|
-
for (const integration of options.chosenIntegrations) {
|
|
135
|
-
integrationEnabled[integration.id] = true
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Helper to calculate relative path from current file
|
|
139
|
-
const localRelativePath = (to: string, stripExt: boolean = false) =>
|
|
140
|
-
relativePath(currentFile, to, stripExt)
|
|
141
|
-
|
|
142
|
-
// Helper to generate import statement for hook
|
|
143
|
-
const hookImportContent = (hook: Hook) =>
|
|
144
|
-
hook.import ||
|
|
145
|
-
`import ${hook.jsName} from '${localRelativePath(hook.path || '')}'`
|
|
146
|
-
|
|
147
|
-
// Helper to get the code/value for a hook
|
|
148
|
-
const hookImportCode = (hook: Hook) =>
|
|
149
|
-
hook.code || hook.jsName || ''
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
packageManager: options.packageManager,
|
|
153
|
-
projectName: options.projectName,
|
|
154
|
-
typescript: options.typescript,
|
|
155
|
-
tailwind: options.tailwind,
|
|
156
|
-
js: options.typescript ? 'ts' : 'js',
|
|
157
|
-
jsx: options.typescript ? 'tsx' : 'jsx',
|
|
158
|
-
|
|
159
|
-
fileRouter: options.mode === 'file-router',
|
|
160
|
-
codeRouter: options.mode === 'code-router',
|
|
161
|
-
|
|
162
|
-
integrationEnabled,
|
|
163
|
-
integrationOption: options.integrationOptions,
|
|
164
|
-
integrations: options.chosenIntegrations,
|
|
165
|
-
hooks,
|
|
166
|
-
routes,
|
|
167
|
-
|
|
168
|
-
getPackageManagerAddScript: (pkg: string, isDev: boolean = false) => {
|
|
169
|
-
const pm = options.packageManager
|
|
170
|
-
if (pm === 'npm') return `npm install ${isDev ? '-D ' : ''}${pkg}`
|
|
171
|
-
if (pm === 'yarn') return `yarn add ${isDev ? '-D ' : ''}${pkg}`
|
|
172
|
-
if (pm === 'pnpm') return `pnpm add ${isDev ? '-D ' : ''}${pkg}`
|
|
173
|
-
if (pm === 'bun') return `bun add ${isDev ? '-d ' : ''}${pkg}`
|
|
174
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
175
|
-
if (pm === 'deno') return `deno add ${pkg}`
|
|
176
|
-
return `npm install ${isDev ? '-D ' : ''}${pkg}`
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
getPackageManagerRunScript: (
|
|
180
|
-
script: string,
|
|
181
|
-
args: Array<string> = [],
|
|
182
|
-
) => {
|
|
183
|
-
const pm = options.packageManager
|
|
184
|
-
const argsStr = args.length ? ' ' + args.join(' ') : ''
|
|
185
|
-
if (pm === 'npm') return `npm run ${script}${argsStr}`
|
|
186
|
-
if (pm === 'yarn') return `yarn ${script}${argsStr}`
|
|
187
|
-
if (pm === 'pnpm') return `pnpm ${script}${argsStr}`
|
|
188
|
-
if (pm === 'bun') return `bun run ${script}${argsStr}`
|
|
189
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
190
|
-
if (pm === 'deno') return `deno task ${script}${argsStr}`
|
|
191
|
-
return `npm run ${script}${argsStr}`
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
relativePath: localRelativePath,
|
|
195
|
-
hookImportContent,
|
|
196
|
-
hookImportCode,
|
|
197
|
-
|
|
198
|
-
ignoreFile: () => {
|
|
199
|
-
throw new IgnoreFileError()
|
|
200
|
-
},
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export interface ProcessedFile {
|
|
205
|
-
path: string
|
|
206
|
-
content: string
|
|
207
|
-
append: boolean
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Process a template file with EJS
|
|
212
|
-
*/
|
|
213
|
-
export function processTemplateFile(
|
|
214
|
-
filePath: string,
|
|
215
|
-
content: string,
|
|
216
|
-
options: CompileOptions,
|
|
217
|
-
): ProcessedFile | null {
|
|
218
|
-
const context = createTemplateContext(options, filePath)
|
|
219
|
-
|
|
220
|
-
let processedContent = content
|
|
221
|
-
let shouldIgnore = false
|
|
222
|
-
|
|
223
|
-
// Process EJS if file ends with .ejs
|
|
224
|
-
if (filePath.endsWith('.ejs')) {
|
|
225
|
-
try {
|
|
226
|
-
processedContent = render(content, context)
|
|
227
|
-
} catch (error) {
|
|
228
|
-
if (error instanceof IgnoreFileError) {
|
|
229
|
-
shouldIgnore = true
|
|
230
|
-
} else {
|
|
231
|
-
throw new Error(`EJS error in file ${filePath}: ${error}`)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (shouldIgnore) {
|
|
237
|
-
return null
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Process path transformations
|
|
241
|
-
let outputPath = filePath
|
|
242
|
-
|
|
243
|
-
// Remove .ejs extension
|
|
244
|
-
outputPath = outputPath.replace(/\.ejs$/, '')
|
|
245
|
-
|
|
246
|
-
// Convert _dot_ to .
|
|
247
|
-
outputPath = convertDotFiles(outputPath)
|
|
248
|
-
|
|
249
|
-
// Strip option prefixes
|
|
250
|
-
outputPath = stripOptionPrefix(outputPath)
|
|
251
|
-
|
|
252
|
-
// Check for .append suffix
|
|
253
|
-
let append = false
|
|
254
|
-
if (outputPath.endsWith('.append')) {
|
|
255
|
-
append = true
|
|
256
|
-
outputPath = outputPath.replace(/\.append$/, '')
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Convert .ts/.tsx to .js/.jsx if not TypeScript
|
|
260
|
-
if (!options.typescript) {
|
|
261
|
-
outputPath = outputPath.replace(/\.tsx$/, '.jsx').replace(/\.ts$/, '.js')
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
path: outputPath,
|
|
266
|
-
content: processedContent,
|
|
267
|
-
append,
|
|
268
|
-
}
|
|
269
|
-
}
|