@tanstack/cli 0.60.1 → 0.62.0

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 (66) hide show
  1. package/dist/cli.js +266 -11
  2. package/dist/command-line.js +103 -8
  3. package/dist/discovery.js +144 -0
  4. package/dist/options.js +35 -2
  5. package/dist/types/command-line.d.ts +7 -0
  6. package/dist/types/{mcp/types.d.ts → discovery.d.ts} +23 -75
  7. package/dist/types/types.d.ts +1 -2
  8. package/dist/types/ui-prompts.d.ts +5 -0
  9. package/dist/ui-prompts.js +26 -0
  10. package/package.json +6 -5
  11. package/skills/CHANGELOG.md +18 -0
  12. package/skills/add-addons-existing-app/SKILL.md +113 -0
  13. package/skills/choose-ecosystem-integrations/SKILL.md +140 -0
  14. package/skills/choose-ecosystem-integrations/references/authentication-providers.md +19 -0
  15. package/skills/choose-ecosystem-integrations/references/data-layer-providers.md +20 -0
  16. package/skills/choose-ecosystem-integrations/references/deployment-targets.md +19 -0
  17. package/skills/create-app-scaffold/SKILL.md +132 -0
  18. package/skills/create-app-scaffold/references/create-flag-compatibility-matrix.md +34 -0
  19. package/skills/create-app-scaffold/references/deployment-providers.md +19 -0
  20. package/skills/create-app-scaffold/references/framework-adapters.md +17 -0
  21. package/skills/create-app-scaffold/references/toolchains.md +17 -0
  22. package/skills/maintain-custom-addons-dev-watch/SKILL.md +118 -0
  23. package/skills/query-docs-library-metadata/SKILL.md +85 -0
  24. package/skills/query-docs-library-metadata/references/discovery-command-output-schemas.md +70 -0
  25. package/CHANGELOG.md +0 -787
  26. package/dist/mcp/api.js +0 -31
  27. package/dist/mcp/tools.js +0 -250
  28. package/dist/mcp/types.js +0 -37
  29. package/dist/mcp.js +0 -181
  30. package/dist/types/mcp/api.d.ts +0 -4
  31. package/dist/types/mcp/tools.d.ts +0 -2
  32. package/dist/types/mcp.d.ts +0 -5
  33. package/playwright-report/index.html +0 -85
  34. package/playwright.config.ts +0 -21
  35. package/src/bin.ts +0 -15
  36. package/src/cli.ts +0 -767
  37. package/src/command-line.ts +0 -473
  38. package/src/dev-watch.ts +0 -564
  39. package/src/file-syncer.ts +0 -263
  40. package/src/index.ts +0 -21
  41. package/src/mcp/api.ts +0 -42
  42. package/src/mcp/tools.ts +0 -323
  43. package/src/mcp/types.ts +0 -46
  44. package/src/mcp.ts +0 -263
  45. package/src/options.ts +0 -234
  46. package/src/types.ts +0 -28
  47. package/src/ui-environment.ts +0 -74
  48. package/src/ui-prompts.ts +0 -355
  49. package/src/utils.ts +0 -30
  50. package/test-results/.last-run.json +0 -4
  51. package/tests/command-line.test.ts +0 -622
  52. package/tests/index.test.ts +0 -9
  53. package/tests/mcp.test.ts +0 -225
  54. package/tests/options.test.ts +0 -216
  55. package/tests/setupVitest.ts +0 -6
  56. package/tests/ui-environment.test.ts +0 -97
  57. package/tests/ui-prompts.test.ts +0 -205
  58. package/tests-e2e/addons-smoke.spec.ts +0 -31
  59. package/tests-e2e/create-smoke.spec.ts +0 -39
  60. package/tests-e2e/helpers.ts +0 -526
  61. package/tests-e2e/matrix-opportunistic.spec.ts +0 -142
  62. package/tests-e2e/router-only-smoke.spec.ts +0 -68
  63. package/tests-e2e/solid-smoke.spec.ts +0 -25
  64. package/tests-e2e/templates-smoke.spec.ts +0 -52
  65. package/tsconfig.json +0 -17
  66. package/vitest.config.js +0 -8
@@ -1,205 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
-
3
- import * as clack from '@clack/prompts'
4
-
5
- import {
6
- getProjectName,
7
- selectAddOns,
8
- selectGit,
9
- selectPackageManager,
10
- selectToolchain,
11
- } from '../src/ui-prompts'
12
-
13
- import type { AddOn, Framework } from '@tanstack/create'
14
-
15
- vi.mock('@clack/prompts')
16
-
17
- vi.spyOn(process, 'exit').mockImplementation((number) => {
18
- throw new Error(`process.exit: ${number}`)
19
- })
20
-
21
- describe('getProjectName', () => {
22
- it('should return the project name', async () => {
23
- vi.spyOn(clack, 'text').mockImplementation(async () => 'my-app')
24
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
25
-
26
- const projectName = await getProjectName()
27
- expect(projectName).toBe('my-app')
28
- })
29
-
30
- it('should exit on cancel', async () => {
31
- vi.spyOn(clack, 'text').mockImplementation(async () => 'Cancelled')
32
- vi.spyOn(clack, 'isCancel').mockImplementation(() => true)
33
-
34
- await expect(getProjectName()).rejects.toThrowError(/exit/)
35
- })
36
- })
37
-
38
- describe('selectPackageManager', () => {
39
- it('should select pnpm', async () => {
40
- vi.spyOn(clack, 'select').mockImplementation(async () => 'pnpm')
41
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
42
-
43
- const packageManager = await selectPackageManager()
44
- expect(packageManager).toBe('pnpm')
45
- })
46
-
47
- it('should exit on cancel', async () => {
48
- vi.spyOn(clack, 'select').mockImplementation(async () =>
49
- Symbol.for('cancel'),
50
- )
51
- vi.spyOn(clack, 'isCancel').mockImplementation(() => true)
52
-
53
- await expect(selectPackageManager()).rejects.toThrowError(/exit/)
54
- })
55
- })
56
-
57
- describe('selectAddOns', () => {
58
- it('should show keyboard shortcuts help and select add-ons', async () => {
59
- const noteSpy = vi.spyOn(clack, 'note').mockImplementation(() => {})
60
- const multiselectSpy = vi
61
- .spyOn(clack, 'multiselect')
62
- .mockImplementation(async () => ['add-on-1'])
63
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
64
-
65
- const packageManager = await selectAddOns(
66
- {
67
- getAddOns: () =>
68
- [
69
- {
70
- id: 'add-on-1',
71
- name: 'Add-on 1',
72
- description: 'Add-on 1 description',
73
- type: 'add-on',
74
- modes: ['file-router'],
75
- },
76
- ] as Array<AddOn>,
77
- } as Framework,
78
- 'file-router',
79
- 'add-on',
80
- 'Select add-ons',
81
- )
82
-
83
- expect(packageManager).toEqual(['add-on-1'])
84
- expect(noteSpy).toHaveBeenCalledWith(
85
- 'Use ↑/↓ to navigate • Space to select/deselect • Enter to confirm',
86
- 'Keyboard Shortcuts',
87
- )
88
- expect(multiselectSpy).toHaveBeenCalledWith(
89
- expect.objectContaining({ maxItems: 1 }),
90
- )
91
- })
92
-
93
- it('should exit on cancel', async () => {
94
- vi.spyOn(clack, 'select').mockImplementation(async () =>
95
- Symbol.for('cancel'),
96
- )
97
- vi.spyOn(clack, 'isCancel').mockImplementation(() => true)
98
-
99
- await expect(
100
- selectAddOns(
101
- {
102
- getAddOns: () =>
103
- [
104
- {
105
- id: 'add-on-1',
106
- name: 'Add-on 1',
107
- description: 'Add-on 1 description',
108
- type: 'add-on',
109
- modes: ['file-router'],
110
- },
111
- ] as Array<AddOn>,
112
- } as Framework,
113
- 'file-router',
114
- 'add-on',
115
- 'Select add-ons',
116
- ),
117
- ).rejects.toThrowError(/exit/)
118
- })
119
- })
120
-
121
- describe('selectGit', () => {
122
- it('should select git', async () => {
123
- vi.spyOn(clack, 'confirm').mockImplementation(async () => true)
124
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
125
-
126
- const git = await selectGit()
127
- expect(git).toBe(true)
128
- })
129
-
130
- it('should exit on cancel', async () => {
131
- vi.spyOn(clack, 'confirm').mockImplementation(async () =>
132
- Symbol.for('cancel'),
133
- )
134
- vi.spyOn(clack, 'isCancel').mockImplementation(() => true)
135
-
136
- await expect(selectGit()).rejects.toThrowError(/exit/)
137
- })
138
- })
139
-
140
- describe('selectToolchain', () => {
141
- it('should select a toolchain', async () => {
142
- vi.spyOn(clack, 'select').mockImplementation(async () => 'biome')
143
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
144
-
145
- const packageManager = await selectToolchain({
146
- getAddOns: () =>
147
- [
148
- {
149
- id: 'biome',
150
- name: 'Biome',
151
- description: 'Biome description',
152
- type: 'toolchain',
153
- modes: ['file-router'],
154
- },
155
- ] as Array<AddOn>,
156
- } as Framework)
157
- expect(packageManager).toEqual('biome')
158
- })
159
- it('should select a toolchain', async () => {
160
- const selectSpy = vi
161
- .spyOn(clack, 'select')
162
- .mockImplementation(async () => 'biome')
163
- vi.spyOn(clack, 'isCancel').mockImplementation(() => false)
164
-
165
- const packageManager = await selectToolchain(
166
- {
167
- getAddOns: () =>
168
- [
169
- {
170
- id: 'biome',
171
- name: 'Biome',
172
- description: 'Biome description',
173
- type: 'toolchain',
174
- modes: ['file-router'],
175
- },
176
- ] as Array<AddOn>,
177
- } as Framework,
178
- 'biome',
179
- )
180
- expect(packageManager).toEqual('biome')
181
- expect(selectSpy).not.toHaveBeenCalled()
182
- })
183
-
184
- it('should exit on cancel', async () => {
185
- vi.spyOn(clack, 'select').mockImplementation(async () =>
186
- Symbol.for('cancel'),
187
- )
188
- vi.spyOn(clack, 'isCancel').mockImplementation(() => true)
189
-
190
- await expect(
191
- selectToolchain({
192
- getAddOns: () =>
193
- [
194
- {
195
- id: 'biome',
196
- name: 'Biome',
197
- description: 'Biome description',
198
- type: 'toolchain',
199
- modes: ['file-router'],
200
- },
201
- ] as Array<AddOn>,
202
- } as Framework),
203
- ).rejects.toThrowError(/exit/)
204
- })
205
- })
@@ -1,31 +0,0 @@
1
- import { expect, test } from '@playwright/test'
2
-
3
- import { attachRuntimeGuards, createReactAppFixture } from './helpers'
4
-
5
- test('@blocking creates app with multiple add-ons and renders demo routes', async ({ page }) => {
6
- const fixture = await createReactAppFixture({
7
- appName: 'addons-create-smoke-app',
8
- addOns: ['shadcn', 'form', 'tanstack-query', 'store'],
9
- })
10
- const guards = attachRuntimeGuards(page, fixture.url)
11
-
12
- try {
13
- await page.goto(`${fixture.url}/demo/form/simple`)
14
- await expect(page.getByText('Title', { exact: true })).toBeVisible()
15
- await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible()
16
-
17
- await page.goto(`${fixture.url}/demo/tanstack-query`)
18
- await expect(page.getByRole('heading', { name: /TanStack Query/ })).toBeVisible()
19
-
20
- await page.goto(`${fixture.url}/demo/store`)
21
- await expect(page.getByRole('heading', { name: 'Store Example' })).toBeVisible()
22
- } finally {
23
- try {
24
- guards.assertClean()
25
- } finally {
26
- guards.dispose()
27
- await fixture.stop()
28
- await fixture.cleanup()
29
- }
30
- }
31
- })
@@ -1,39 +0,0 @@
1
- import { expect, test } from '@playwright/test'
2
-
3
- import { attachRuntimeGuards, createReactAppFixture } from './helpers'
4
-
5
- test('@blocking creates a React app and navigates core demo routes', async ({ page }) => {
6
- const fixture = await createReactAppFixture({
7
- appName: 'react-smoke-app',
8
- })
9
- const guards = attachRuntimeGuards(page, fixture.url)
10
-
11
- try {
12
- await page.goto(fixture.url)
13
- await expect(
14
- page.getByRole('heading', {
15
- name: 'Island hours, but for product teams.',
16
- }),
17
- ).toBeVisible()
18
-
19
- await page.getByRole('link', { name: 'Blog' }).click()
20
- await expect(page).toHaveURL(/\/blog\/?$/)
21
- await expect(page.getByRole('heading', { name: 'Blog' })).toBeVisible()
22
-
23
- await page.locator('main article a').first().click()
24
- await expect(page).toHaveURL(/\/blog\/.+/)
25
- await expect(page.getByText('Post', { exact: true })).toBeVisible()
26
-
27
- await page.getByRole('link', { name: 'About' }).click()
28
- await expect(page).toHaveURL(/\/about\/?$/)
29
- await expect(page.getByRole('heading', { name: 'Built for shipping fast.' })).toBeVisible()
30
- } finally {
31
- try {
32
- guards.assertClean()
33
- } finally {
34
- guards.dispose()
35
- await fixture.stop()
36
- await fixture.cleanup()
37
- }
38
- }
39
- })