@tanstack/cli 0.0.8 → 0.48.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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.js +7 -0
  3. package/dist/cli.js +481 -0
  4. package/dist/command-line.js +174 -0
  5. package/dist/dev-watch.js +290 -0
  6. package/dist/file-syncer.js +148 -0
  7. package/dist/index.js +1 -0
  8. package/dist/mcp/api.js +31 -0
  9. package/dist/mcp/tools.js +250 -0
  10. package/dist/mcp/types.js +37 -0
  11. package/dist/mcp.js +121 -0
  12. package/dist/options.js +162 -0
  13. package/dist/types/bin.d.ts +2 -0
  14. package/dist/types/cli.d.ts +16 -0
  15. package/dist/types/command-line.d.ts +10 -0
  16. package/dist/types/dev-watch.d.ts +27 -0
  17. package/dist/types/file-syncer.d.ts +18 -0
  18. package/dist/types/index.d.ts +1 -0
  19. package/dist/types/mcp/api.d.ts +4 -0
  20. package/dist/types/mcp/tools.d.ts +2 -0
  21. package/dist/types/mcp/types.d.ts +217 -0
  22. package/dist/types/mcp.d.ts +6 -0
  23. package/dist/types/options.d.ts +8 -0
  24. package/dist/types/types.d.ts +25 -0
  25. package/dist/types/ui-environment.d.ts +2 -0
  26. package/dist/types/ui-prompts.d.ts +12 -0
  27. package/dist/types/utils.d.ts +8 -0
  28. package/dist/types.js +1 -0
  29. package/dist/ui-environment.js +52 -0
  30. package/dist/ui-prompts.js +244 -0
  31. package/dist/utils.js +30 -0
  32. package/package.json +46 -47
  33. package/src/bin.ts +6 -93
  34. package/src/cli.ts +692 -0
  35. package/src/command-line.ts +236 -0
  36. package/src/dev-watch.ts +430 -0
  37. package/src/file-syncer.ts +205 -0
  38. package/src/index.ts +1 -85
  39. package/src/mcp.ts +190 -0
  40. package/src/options.ts +260 -0
  41. package/src/types.ts +27 -0
  42. package/src/ui-environment.ts +74 -0
  43. package/src/ui-prompts.ts +322 -0
  44. package/src/utils.ts +38 -0
  45. package/tests/command-line.test.ts +304 -0
  46. package/tests/index.test.ts +9 -0
  47. package/tests/mcp.test.ts +225 -0
  48. package/tests/options.test.ts +304 -0
  49. package/tests/setupVitest.ts +6 -0
  50. package/tests/ui-environment.test.ts +97 -0
  51. package/tests/ui-prompts.test.ts +238 -0
  52. package/tsconfig.json +17 -0
  53. package/vitest.config.js +7 -0
  54. package/dist/bin.cjs +0 -769
  55. package/dist/bin.d.cts +0 -1
  56. package/dist/bin.d.mts +0 -1
  57. package/dist/bin.mjs +0 -768
  58. package/dist/fetch-CbFFGJEw.cjs +0 -3
  59. package/dist/fetch-DG5dLrsb.cjs +0 -522
  60. package/dist/fetch-DhlVXS6S.mjs +0 -390
  61. package/dist/fetch-I_OVg8JX.mjs +0 -3
  62. package/dist/index.cjs +0 -37
  63. package/dist/index.d.cts +0 -1172
  64. package/dist/index.d.mts +0 -1172
  65. package/dist/index.mjs +0 -4
  66. package/dist/template-Szi7-AZJ.mjs +0 -2202
  67. package/dist/template-lWrIZhCQ.cjs +0 -2314
  68. package/src/api/fetch.test.ts +0 -114
  69. package/src/api/fetch.ts +0 -278
  70. package/src/cache/index.ts +0 -89
  71. package/src/commands/create.ts +0 -470
  72. package/src/commands/mcp.test.ts +0 -152
  73. package/src/commands/mcp.ts +0 -211
  74. package/src/engine/compile-with-addons.test.ts +0 -302
  75. package/src/engine/compile.test.ts +0 -404
  76. package/src/engine/compile.ts +0 -569
  77. package/src/engine/config-file.test.ts +0 -118
  78. package/src/engine/config-file.ts +0 -61
  79. package/src/engine/custom-addons/integration.ts +0 -323
  80. package/src/engine/custom-addons/shared.test.ts +0 -98
  81. package/src/engine/custom-addons/shared.ts +0 -281
  82. package/src/engine/custom-addons/template.test.ts +0 -288
  83. package/src/engine/custom-addons/template.ts +0 -124
  84. package/src/engine/template.test.ts +0 -256
  85. package/src/engine/template.ts +0 -269
  86. package/src/engine/types.ts +0 -336
  87. package/src/parse-gitignore.d.ts +0 -5
  88. package/src/templates/base.ts +0 -883
@@ -1,404 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { compile, compileWithAttribution } from './compile.js'
3
- import type { CompileOptions, CustomTemplateCompiled, IntegrationCompiled } from './types.js'
4
-
5
- const baseOptions: CompileOptions = {
6
- projectName: 'test-project',
7
- framework: 'react',
8
- mode: 'file-router',
9
- typescript: true,
10
- tailwind: true,
11
- packageManager: 'pnpm',
12
- chosenIntegrations: [],
13
- integrationOptions: {},
14
- }
15
-
16
- describe('compile', () => {
17
- describe('base template', () => {
18
- it('should generate base project files', () => {
19
- const output = compile(baseOptions)
20
-
21
- // Should have essential files
22
- expect(output.files).toHaveProperty('package.json')
23
- expect(output.files).toHaveProperty('vite.config.ts')
24
- expect(output.files).toHaveProperty('tsconfig.json')
25
- expect(output.files).toHaveProperty('src/routes/__root.tsx')
26
- expect(output.files).toHaveProperty('src/routes/index.tsx')
27
- expect(output.files).toHaveProperty('src/styles.css')
28
- expect(output.files).toHaveProperty('.gitignore')
29
- expect(output.files).toHaveProperty('.env.example')
30
- })
31
-
32
- it('should generate valid package.json', () => {
33
- const output = compile(baseOptions)
34
- const pkg = JSON.parse(output.files['package.json']!)
35
-
36
- expect(pkg.name).toBe('test-project')
37
- expect(pkg.scripts).toHaveProperty('dev')
38
- expect(pkg.scripts).toHaveProperty('build')
39
- expect(pkg.scripts).toHaveProperty('start')
40
- expect(pkg.dependencies).toHaveProperty('@tanstack/react-start')
41
- expect(pkg.dependencies).toHaveProperty('@tanstack/react-router')
42
- })
43
-
44
- it('should include tailwind when enabled', () => {
45
- const output = compile({ ...baseOptions, tailwind: true })
46
- const pkg = JSON.parse(output.files['package.json']!)
47
-
48
- expect(pkg.devDependencies).toHaveProperty('@tailwindcss/vite')
49
- expect(output.files['vite.config.ts']).toContain('tailwindcss')
50
- })
51
-
52
- it('should exclude tailwind when disabled', () => {
53
- const output = compile({ ...baseOptions, tailwind: false })
54
- const pkg = JSON.parse(output.files['package.json']!)
55
-
56
- expect(pkg.dependencies).not.toHaveProperty('@tailwindcss/vite')
57
- expect(output.files['vite.config.ts']).not.toContain('tailwindcss')
58
- })
59
-
60
- it('should generate vite.config.ts with correct plugins', () => {
61
- const output = compile(baseOptions)
62
- const viteConfig = output.files['vite.config.ts']!
63
-
64
- expect(viteConfig).toContain("import { defineConfig } from 'vite'")
65
- expect(viteConfig).toContain('tanstackStart')
66
- expect(viteConfig).toContain('viteReact')
67
- expect(viteConfig).toContain('viteTsConfigPaths')
68
- })
69
-
70
- it('should generate __root.tsx with router devtools', () => {
71
- const output = compile(baseOptions)
72
- const rootRoute = output.files['src/routes/__root.tsx']!
73
-
74
- expect(rootRoute).toContain('createRootRoute')
75
- expect(rootRoute).toContain('TanStackRouterDevtools')
76
- expect(rootRoute).toContain('shellComponent')
77
- expect(rootRoute).toContain('{children}')
78
- })
79
- })
80
-
81
- describe('integration', () => {
82
- const mockIntegration: IntegrationCompiled = {
83
- id: 'test-integration',
84
- name: 'Test Integration',
85
- description: 'A test integration',
86
- type: 'integration',
87
- phase: 'integration',
88
- modes: ['file-router'],
89
- files: {
90
- 'src/integrations/test-integration/index.ts': 'export const testIntegration = true',
91
- },
92
- packageAdditions: {
93
- dependencies: {
94
- 'test-package': '^1.0.0',
95
- },
96
- devDependencies: {
97
- 'test-dev-package': '^2.0.0',
98
- },
99
- },
100
- }
101
-
102
- it('should include integration files in output', () => {
103
- const output = compile({
104
- ...baseOptions,
105
- chosenIntegrations: [mockIntegration],
106
- })
107
-
108
- expect(output.files).toHaveProperty('src/integrations/test-integration/index.ts')
109
- expect(output.files['src/integrations/test-integration/index.ts']).toBe(
110
- 'export const testIntegration = true',
111
- )
112
- })
113
-
114
- it('should merge integration package dependencies', () => {
115
- const output = compile({
116
- ...baseOptions,
117
- chosenIntegrations: [mockIntegration],
118
- })
119
-
120
- expect(output.packages.dependencies).toHaveProperty('test-package', '^1.0.0')
121
- expect(output.packages.devDependencies).toHaveProperty('test-dev-package', '^2.0.0')
122
- })
123
-
124
- it('should collect integration warnings', () => {
125
- const integrationWithWarning: IntegrationCompiled = {
126
- ...mockIntegration,
127
- id: 'warning-integration',
128
- name: 'Warning Integration',
129
- warning: 'This integration requires configuration!',
130
- }
131
-
132
- const output = compile({
133
- ...baseOptions,
134
- chosenIntegrations: [integrationWithWarning],
135
- })
136
-
137
- // Warnings are prefixed with integration name
138
- expect(output.warnings).toContain('Warning Integration: This integration requires configuration!')
139
- })
140
-
141
- it('should collect integration env vars', () => {
142
- const integrationWithEnv: IntegrationCompiled = {
143
- ...mockIntegration,
144
- id: 'env-integration',
145
- envVars: [
146
- { name: 'API_KEY', description: 'Your API key', required: true },
147
- { name: 'API_URL', description: 'API endpoint', example: 'https://api.example.com' },
148
- ],
149
- }
150
-
151
- const output = compile({
152
- ...baseOptions,
153
- chosenIntegrations: [integrationWithEnv],
154
- })
155
-
156
- expect(output.envVars).toHaveLength(2)
157
- expect(output.envVars[0]).toEqual({
158
- name: 'API_KEY',
159
- description: 'Your API key',
160
- required: true,
161
- })
162
- })
163
- })
164
-
165
- describe('vite-plugin hook', () => {
166
- it('should inject vite plugins into vite.config.ts', () => {
167
- const integrationWithVitePlugin: IntegrationCompiled = {
168
- id: 'vite-plugin-integration',
169
- name: 'Vite Plugin Integration',
170
- description: 'Integration with vite plugin',
171
- type: 'integration',
172
- phase: 'integration',
173
- modes: ['file-router'],
174
- files: {
175
- 'src/integrations/vite-plugin-integration/vite-plugin.ts':
176
- 'export default function myPlugin() { return { name: "my-plugin" } }',
177
- },
178
- hooks: [
179
- {
180
- type: 'vite-plugin',
181
- jsName: 'myPlugin',
182
- path: 'src/integrations/vite-plugin-integration/vite-plugin.ts',
183
- code: 'myPlugin()',
184
- },
185
- ],
186
- }
187
-
188
- const output = compile({
189
- ...baseOptions,
190
- chosenIntegrations: [integrationWithVitePlugin],
191
- })
192
-
193
- const viteConfig = output.files['vite.config.ts']!
194
- expect(viteConfig).toContain('myPlugin')
195
- })
196
- })
197
-
198
- describe('root-provider hook', () => {
199
- it('should wrap app with provider in __root.tsx', () => {
200
- const integrationWithProvider: IntegrationCompiled = {
201
- id: 'provider-integration',
202
- name: 'Provider Integration',
203
- description: 'Integration with root provider',
204
- type: 'integration',
205
- phase: 'integration',
206
- modes: ['file-router'],
207
- files: {
208
- 'src/integrations/provider-integration/provider.tsx':
209
- 'export function Provider({ children }) { return <div>{children}</div> }',
210
- },
211
- hooks: [
212
- {
213
- type: 'root-provider',
214
- jsName: 'Provider',
215
- path: 'src/integrations/provider-integration/provider.tsx',
216
- code: '<Provider>',
217
- },
218
- ],
219
- }
220
-
221
- const output = compile({
222
- ...baseOptions,
223
- chosenIntegrations: [integrationWithProvider],
224
- })
225
-
226
- const rootRoute = output.files['src/routes/__root.tsx']!
227
- expect(rootRoute).toContain('Provider')
228
- })
229
- })
230
-
231
- describe('devtools hook', () => {
232
- it('should add devtools to __root.tsx', () => {
233
- const integrationWithDevtools: IntegrationCompiled = {
234
- id: 'devtools-integration',
235
- name: 'Devtools Integration',
236
- description: 'Integration with devtools',
237
- type: 'integration',
238
- phase: 'integration',
239
- modes: ['file-router'],
240
- files: {
241
- 'src/integrations/devtools-integration/devtools.tsx':
242
- 'export function Devtools() { return <div>Devtools</div> }',
243
- },
244
- hooks: [
245
- {
246
- type: 'devtools',
247
- jsName: 'Devtools',
248
- path: 'src/integrations/devtools-integration/devtools.tsx',
249
- code: '<Devtools />',
250
- },
251
- ],
252
- }
253
-
254
- const output = compile({
255
- ...baseOptions,
256
- chosenIntegrations: [integrationWithDevtools],
257
- })
258
-
259
- const rootRoute = output.files['src/routes/__root.tsx']!
260
- expect(rootRoute).toContain('Devtools')
261
- })
262
- })
263
-
264
- describe('custom template support', () => {
265
- // Custom templates are just integration presets - they don't add files directly
266
- const mockTemplate: CustomTemplateCompiled = {
267
- id: 'test-template',
268
- name: 'Test Template',
269
- description: 'A test template',
270
- framework: 'react',
271
- mode: 'file-router',
272
- typescript: true,
273
- tailwind: true,
274
- integrations: [], // List of integration IDs to include
275
- }
276
-
277
- it('should compile with custom template (templates are just integration presets)', () => {
278
- const output = compile({
279
- ...baseOptions,
280
- customTemplate: mockTemplate,
281
- })
282
-
283
- // Template doesn't add files directly - it just specifies integrations
284
- // The template's integrations should be resolved into chosenIntegrations by caller
285
- expect(output.files).toHaveProperty('package.json')
286
- expect(output.files).toHaveProperty('vite.config.ts')
287
- })
288
-
289
- it('should use custom template settings', () => {
290
- const output = compile({
291
- ...baseOptions,
292
- // Template settings would be applied by the create command
293
- // Here we just verify compile works with a template present
294
- customTemplate: mockTemplate,
295
- })
296
-
297
- expect(output.files).toBeDefined()
298
- })
299
- })
300
-
301
- describe('integration sorting by phase', () => {
302
- it('should process setup integrations before integration phase', () => {
303
- const setupIntegration: IntegrationCompiled = {
304
- id: 'setup-integration',
305
- name: 'Setup Integration',
306
- description: 'Setup phase integration',
307
- type: 'toolchain',
308
- phase: 'setup',
309
- modes: ['file-router'],
310
- files: { 'setup.txt': 'setup' },
311
- }
312
-
313
- const integrationPhase: IntegrationCompiled = {
314
- id: 'integration-phase',
315
- name: 'Integration Phase',
316
- description: 'Integration phase integration',
317
- type: 'integration',
318
- phase: 'integration',
319
- modes: ['file-router'],
320
- files: { 'integration.txt': 'integration' },
321
- }
322
-
323
- // Order shouldn't matter in input - they should be sorted internally
324
- const output = compile({
325
- ...baseOptions,
326
- chosenIntegrations: [integrationPhase, setupIntegration],
327
- })
328
-
329
- // Both files should exist
330
- expect(output.files).toHaveProperty('setup.txt')
331
- expect(output.files).toHaveProperty('integration.txt')
332
- })
333
- })
334
- })
335
-
336
- describe('compileWithAttribution', () => {
337
- it('should include line attributions for files', () => {
338
- const output = compileWithAttribution(baseOptions)
339
-
340
- expect(output.attributedFiles).toBeDefined()
341
- expect(output.attributedFiles['vite.config.ts']).toBeDefined()
342
- expect(output.attributedFiles['vite.config.ts']!.attributions.length).toBeGreaterThan(0)
343
- })
344
-
345
- it('should attribute integration lines to the integration', () => {
346
- const integration: IntegrationCompiled = {
347
- id: 'attr-integration',
348
- name: 'Attribution Integration',
349
- description: 'Test attribution',
350
- type: 'integration',
351
- phase: 'integration',
352
- modes: ['file-router'],
353
- files: {},
354
- hooks: [
355
- {
356
- type: 'vite-plugin',
357
- jsName: 'myPlugin',
358
- path: 'src/integrations/attr-integration/plugin.ts',
359
- code: 'myPlugin()',
360
- },
361
- ],
362
- }
363
-
364
- const output = compileWithAttribution({
365
- ...baseOptions,
366
- chosenIntegrations: [integration],
367
- })
368
-
369
- const viteAttrs = output.attributedFiles['vite.config.ts']!.attributions
370
- const integrationLine = viteAttrs.find((a) => a.featureId === 'attr-integration')
371
- expect(integrationLine).toBeDefined()
372
- })
373
-
374
- it('should attribute gitignore patterns to integrations', () => {
375
- const integration: IntegrationCompiled = {
376
- id: 'drizzle',
377
- name: 'Drizzle',
378
- description: 'Database ORM',
379
- type: 'integration',
380
- phase: 'integration',
381
- modes: ['file-router'],
382
- files: {},
383
- gitignorePatterns: ['drizzle/', '*.db'],
384
- }
385
-
386
- const output = compileWithAttribution({
387
- ...baseOptions,
388
- chosenIntegrations: [integration],
389
- })
390
-
391
- // Check gitignore has attributions
392
- const gitignoreAttrs = output.attributedFiles['.gitignore']!.attributions
393
- expect(gitignoreAttrs).toBeDefined()
394
-
395
- // Should have integration-attributed lines
396
- const integrationLines = gitignoreAttrs.filter((a) => a.featureId === 'drizzle')
397
- expect(integrationLines.length).toBe(2) // drizzle/ and *.db
398
-
399
- // Check the actual content includes the patterns
400
- const gitignoreContent = output.files['.gitignore']!
401
- expect(gitignoreContent).toContain('drizzle/')
402
- expect(gitignoreContent).toContain('*.db')
403
- })
404
- })