@tanstack/cta-cli 0.24.1 → 0.25.1
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/cli.js +23 -6
- package/dist/command-line.js +5 -1
- package/dist/options.js +6 -1
- package/dist/types/types.d.ts +1 -0
- package/dist/types/ui-prompts.d.ts +1 -0
- package/dist/ui-prompts.js +32 -0
- package/package.json +3 -3
- package/src/cli.ts +33 -6
- package/src/command-line.ts +5 -1
- package/src/options.ts +7 -0
- package/src/types.ts +1 -0
- package/src/ui-prompts.ts +39 -0
- package/tests/command-line.test.ts +34 -2
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { promptForAddOns, promptForCreateOptions } from './options.js';
|
|
|
11
11
|
import { normalizeOptions } from './command-line.js';
|
|
12
12
|
import { createUIEnvironment } from './ui-environment.js';
|
|
13
13
|
import { convertTemplateToMode } from './utils.js';
|
|
14
|
-
// This CLI assumes that all of the registered frameworks have the same set of toolchains, modes, etc.
|
|
14
|
+
// This CLI assumes that all of the registered frameworks have the same set of toolchains, hosts, modes, etc.
|
|
15
15
|
export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTemplate = 'javascript', defaultFramework, craCompatible = false, webBase, }) {
|
|
16
16
|
const environment = createUIEnvironment(appName, false);
|
|
17
17
|
const program = new Command();
|
|
@@ -24,6 +24,14 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
const hosts = new Set();
|
|
28
|
+
for (const framework of getFrameworks()) {
|
|
29
|
+
for (const addOn of framework.getAddOns()) {
|
|
30
|
+
if (addOn.type === 'host') {
|
|
31
|
+
hosts.add(addOn.id);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
27
35
|
let defaultMode = forcedMode;
|
|
28
36
|
const supportedModes = new Set();
|
|
29
37
|
for (const framework of getFrameworks()) {
|
|
@@ -191,6 +199,14 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
191
199
|
}
|
|
192
200
|
return value;
|
|
193
201
|
});
|
|
202
|
+
if (hosts.size > 0) {
|
|
203
|
+
program.option(`--host <${Array.from(hosts).join('|')}>`, `Explicitly tell the CLI to use this hosting provider`, (value) => {
|
|
204
|
+
if (!hosts.has(value)) {
|
|
205
|
+
throw new InvalidArgumentError(`Invalid host: ${value}. The following are allowed: ${Array.from(hosts).join(', ')}`);
|
|
206
|
+
}
|
|
207
|
+
return value;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
194
210
|
if (toolchains.size > 0) {
|
|
195
211
|
program.option(`--toolchain <${Array.from(toolchains).join('|')}>`, `Explicitly tell the CLI to use this toolchain`, (value) => {
|
|
196
212
|
if (!toolchains.has(value)) {
|
|
@@ -249,13 +265,14 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
249
265
|
}
|
|
250
266
|
if (options.ui) {
|
|
251
267
|
const optionsFromCLI = await normalizeOptions(cliOptions, defaultMode, forcedAddOns, { disableNameCheck: true });
|
|
268
|
+
const options = {
|
|
269
|
+
...createSerializedOptions(optionsFromCLI),
|
|
270
|
+
projectName: 'my-app',
|
|
271
|
+
targetDir: resolve(process.cwd(), 'my-app'),
|
|
272
|
+
};
|
|
252
273
|
launchUI({
|
|
253
274
|
mode: 'setup',
|
|
254
|
-
options
|
|
255
|
-
...createSerializedOptions(optionsFromCLI),
|
|
256
|
-
projectName: 'my-app',
|
|
257
|
-
targetDir: resolve(process.cwd(), 'my-app'),
|
|
258
|
-
},
|
|
275
|
+
options,
|
|
259
276
|
forcedRouterMode: defaultMode,
|
|
260
277
|
forcedAddOns,
|
|
261
278
|
environmentFactory: () => createUIEnvironment(appName, false),
|
package/dist/command-line.js
CHANGED
|
@@ -40,7 +40,8 @@ export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns, opt
|
|
|
40
40
|
if (Array.isArray(cliOptions.addOns) ||
|
|
41
41
|
starter?.dependsOn ||
|
|
42
42
|
forcedAddOns ||
|
|
43
|
-
cliOptions.toolchain
|
|
43
|
+
cliOptions.toolchain ||
|
|
44
|
+
cliOptions.host) {
|
|
44
45
|
const selectedAddOns = new Set([
|
|
45
46
|
...(starter?.dependsOn || []),
|
|
46
47
|
...(forcedAddOns || []),
|
|
@@ -53,6 +54,9 @@ export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns, opt
|
|
|
53
54
|
if (cliOptions.toolchain) {
|
|
54
55
|
selectedAddOns.add(cliOptions.toolchain);
|
|
55
56
|
}
|
|
57
|
+
if (cliOptions.host) {
|
|
58
|
+
selectedAddOns.add(cliOptions.host);
|
|
59
|
+
}
|
|
56
60
|
return await finalizeAddOns(framework, mode, Array.from(selectedAddOns));
|
|
57
61
|
}
|
|
58
62
|
return [];
|
package/dist/options.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { intro } from '@clack/prompts';
|
|
2
2
|
import { finalizeAddOns, getFrameworkById, getPackageManager, readConfigFile, } from '@tanstack/cta-engine';
|
|
3
|
-
import { getProjectName, selectAddOns, selectGit, selectPackageManager, selectRouterType, selectTailwind, selectToolchain, selectTypescript, } from './ui-prompts.js';
|
|
3
|
+
import { getProjectName, selectAddOns, selectGit, selectPackageManager, selectRouterType, selectTailwind, selectToolchain, selectHost, selectTypescript, } from './ui-prompts.js';
|
|
4
4
|
export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], forcedMode, }) {
|
|
5
5
|
const options = {};
|
|
6
6
|
options.framework = getFrameworkById(cliOptions.framework || 'react-cra');
|
|
@@ -45,11 +45,16 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], fo
|
|
|
45
45
|
}
|
|
46
46
|
// Toolchain selection
|
|
47
47
|
const toolchain = await selectToolchain(options.framework, cliOptions.toolchain);
|
|
48
|
+
// Host selection
|
|
49
|
+
const host = await selectHost(options.framework, cliOptions.host);
|
|
48
50
|
// Add-ons selection
|
|
49
51
|
const addOns = new Set();
|
|
50
52
|
if (toolchain) {
|
|
51
53
|
addOns.add(toolchain);
|
|
52
54
|
}
|
|
55
|
+
if (host) {
|
|
56
|
+
addOns.add(host);
|
|
57
|
+
}
|
|
53
58
|
for (const addOn of forcedAddOns) {
|
|
54
59
|
addOns.add(addOn);
|
|
55
60
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export declare function selectPackageManager(): Promise<PackageManager>;
|
|
|
8
8
|
export declare function selectAddOns(framework: Framework, mode: string, type: string, message: string, forcedAddOns?: Array<string>): Promise<Array<string>>;
|
|
9
9
|
export declare function selectGit(): Promise<boolean>;
|
|
10
10
|
export declare function selectToolchain(framework: Framework, toolchain?: string): Promise<string | undefined>;
|
|
11
|
+
export declare function selectHost(framework: Framework, host?: string): Promise<string | undefined>;
|
package/dist/ui-prompts.js
CHANGED
|
@@ -138,3 +138,35 @@ export async function selectToolchain(framework, toolchain) {
|
|
|
138
138
|
}
|
|
139
139
|
return tc;
|
|
140
140
|
}
|
|
141
|
+
export async function selectHost(framework, host) {
|
|
142
|
+
const hosts = new Set();
|
|
143
|
+
for (const addOn of framework
|
|
144
|
+
.getAddOns()
|
|
145
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
146
|
+
if (addOn.type === 'host') {
|
|
147
|
+
hosts.add(addOn);
|
|
148
|
+
if (host && addOn.id === host) {
|
|
149
|
+
return host;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const hp = await select({
|
|
154
|
+
message: 'Select hosting provider',
|
|
155
|
+
options: [
|
|
156
|
+
{
|
|
157
|
+
value: undefined,
|
|
158
|
+
label: 'None',
|
|
159
|
+
},
|
|
160
|
+
...Array.from(hosts).map((h) => ({
|
|
161
|
+
value: h.id,
|
|
162
|
+
label: h.name,
|
|
163
|
+
})),
|
|
164
|
+
],
|
|
165
|
+
initialValue: undefined,
|
|
166
|
+
});
|
|
167
|
+
if (isCancel(hp)) {
|
|
168
|
+
cancel('Operation cancelled.');
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
return hp;
|
|
172
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cta-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Tanstack Application Builder CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"express": "^4.21.2",
|
|
31
31
|
"semver": "^7.7.2",
|
|
32
32
|
"zod": "^3.24.2",
|
|
33
|
-
"@tanstack/cta-
|
|
34
|
-
"@tanstack/cta-
|
|
33
|
+
"@tanstack/cta-ui": "0.25.1",
|
|
34
|
+
"@tanstack/cta-engine": "0.25.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@tanstack/config": "^0.16.2",
|
package/src/cli.ts
CHANGED
|
@@ -33,7 +33,7 @@ import { convertTemplateToMode } from './utils.js'
|
|
|
33
33
|
import type { CliOptions, TemplateOptions } from './types.js'
|
|
34
34
|
import type { Options, PackageManager } from '@tanstack/cta-engine'
|
|
35
35
|
|
|
36
|
-
// This CLI assumes that all of the registered frameworks have the same set of toolchains, modes, etc.
|
|
36
|
+
// This CLI assumes that all of the registered frameworks have the same set of toolchains, hosts, modes, etc.
|
|
37
37
|
|
|
38
38
|
export function cli({
|
|
39
39
|
name,
|
|
@@ -69,6 +69,15 @@ export function cli({
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
const hosts = new Set<string>()
|
|
73
|
+
for (const framework of getFrameworks()) {
|
|
74
|
+
for (const addOn of framework.getAddOns()) {
|
|
75
|
+
if (addOn.type === 'host') {
|
|
76
|
+
hosts.add(addOn.id)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
72
81
|
let defaultMode: string | undefined = forcedMode
|
|
73
82
|
const supportedModes = new Set<string>()
|
|
74
83
|
for (const framework of getFrameworks()) {
|
|
@@ -295,6 +304,23 @@ Remove your node_modules directory and package lock file and re-install.`,
|
|
|
295
304
|
},
|
|
296
305
|
)
|
|
297
306
|
|
|
307
|
+
if (hosts.size > 0) {
|
|
308
|
+
program.option<string>(
|
|
309
|
+
`--host <${Array.from(hosts).join('|')}>`,
|
|
310
|
+
`Explicitly tell the CLI to use this hosting provider`,
|
|
311
|
+
(value) => {
|
|
312
|
+
if (!hosts.has(value)) {
|
|
313
|
+
throw new InvalidArgumentError(
|
|
314
|
+
`Invalid host: ${value}. The following are allowed: ${Array.from(
|
|
315
|
+
hosts,
|
|
316
|
+
).join(', ')}`,
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
return value
|
|
320
|
+
},
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
|
|
298
324
|
if (toolchains.size > 0) {
|
|
299
325
|
program.option<string>(
|
|
300
326
|
`--toolchain <${Array.from(toolchains).join('|')}>`,
|
|
@@ -385,13 +411,14 @@ Remove your node_modules directory and package lock file and re-install.`,
|
|
|
385
411
|
forcedAddOns,
|
|
386
412
|
{ disableNameCheck: true },
|
|
387
413
|
)
|
|
414
|
+
const options = {
|
|
415
|
+
...createSerializedOptions(optionsFromCLI!),
|
|
416
|
+
projectName: 'my-app',
|
|
417
|
+
targetDir: resolve(process.cwd(), 'my-app'),
|
|
418
|
+
}
|
|
388
419
|
launchUI({
|
|
389
420
|
mode: 'setup',
|
|
390
|
-
options
|
|
391
|
-
...createSerializedOptions(optionsFromCLI!),
|
|
392
|
-
projectName: 'my-app',
|
|
393
|
-
targetDir: resolve(process.cwd(), 'my-app'),
|
|
394
|
-
},
|
|
421
|
+
options,
|
|
395
422
|
forcedRouterMode: defaultMode,
|
|
396
423
|
forcedAddOns,
|
|
397
424
|
environmentFactory: () => createUIEnvironment(appName, false),
|
package/src/command-line.ts
CHANGED
|
@@ -74,7 +74,8 @@ export async function normalizeOptions(
|
|
|
74
74
|
Array.isArray(cliOptions.addOns) ||
|
|
75
75
|
starter?.dependsOn ||
|
|
76
76
|
forcedAddOns ||
|
|
77
|
-
cliOptions.toolchain
|
|
77
|
+
cliOptions.toolchain ||
|
|
78
|
+
cliOptions.host
|
|
78
79
|
) {
|
|
79
80
|
const selectedAddOns = new Set<string>([
|
|
80
81
|
...(starter?.dependsOn || []),
|
|
@@ -88,6 +89,9 @@ export async function normalizeOptions(
|
|
|
88
89
|
if (cliOptions.toolchain) {
|
|
89
90
|
selectedAddOns.add(cliOptions.toolchain)
|
|
90
91
|
}
|
|
92
|
+
if (cliOptions.host) {
|
|
93
|
+
selectedAddOns.add(cliOptions.host)
|
|
94
|
+
}
|
|
91
95
|
|
|
92
96
|
return await finalizeAddOns(framework, mode, Array.from(selectedAddOns))
|
|
93
97
|
}
|
package/src/options.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
selectRouterType,
|
|
16
16
|
selectTailwind,
|
|
17
17
|
selectToolchain,
|
|
18
|
+
selectHost,
|
|
18
19
|
selectTypescript,
|
|
19
20
|
} from './ui-prompts.js'
|
|
20
21
|
|
|
@@ -84,12 +85,18 @@ export async function promptForCreateOptions(
|
|
|
84
85
|
cliOptions.toolchain,
|
|
85
86
|
)
|
|
86
87
|
|
|
88
|
+
// Host selection
|
|
89
|
+
const host = await selectHost(options.framework, cliOptions.host)
|
|
90
|
+
|
|
87
91
|
// Add-ons selection
|
|
88
92
|
const addOns: Set<string> = new Set()
|
|
89
93
|
|
|
90
94
|
if (toolchain) {
|
|
91
95
|
addOns.add(toolchain)
|
|
92
96
|
}
|
|
97
|
+
if (host) {
|
|
98
|
+
addOns.add(host)
|
|
99
|
+
}
|
|
93
100
|
|
|
94
101
|
for (const addOn of forcedAddOns) {
|
|
95
102
|
addOns.add(addOn)
|
package/src/types.ts
CHANGED
package/src/ui-prompts.ts
CHANGED
|
@@ -183,3 +183,42 @@ export async function selectToolchain(
|
|
|
183
183
|
|
|
184
184
|
return tc
|
|
185
185
|
}
|
|
186
|
+
|
|
187
|
+
export async function selectHost(
|
|
188
|
+
framework: Framework,
|
|
189
|
+
host?: string,
|
|
190
|
+
): Promise<string | undefined> {
|
|
191
|
+
const hosts = new Set<AddOn>()
|
|
192
|
+
for (const addOn of framework
|
|
193
|
+
.getAddOns()
|
|
194
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
195
|
+
if (addOn.type === 'host') {
|
|
196
|
+
hosts.add(addOn)
|
|
197
|
+
if (host && addOn.id === host) {
|
|
198
|
+
return host
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const hp = await select({
|
|
204
|
+
message: 'Select hosting provider',
|
|
205
|
+
options: [
|
|
206
|
+
{
|
|
207
|
+
value: undefined,
|
|
208
|
+
label: 'None',
|
|
209
|
+
},
|
|
210
|
+
...Array.from(hosts).map((h) => ({
|
|
211
|
+
value: h.id,
|
|
212
|
+
label: h.name,
|
|
213
|
+
})),
|
|
214
|
+
],
|
|
215
|
+
initialValue: undefined,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
if (isCancel(hp)) {
|
|
219
|
+
cancel('Operation cancelled.')
|
|
220
|
+
process.exit(0)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return hp as string
|
|
224
|
+
}
|
|
@@ -62,7 +62,14 @@ describe('normalizeOptions', () => {
|
|
|
62
62
|
__testRegisterFramework({
|
|
63
63
|
id: 'solid',
|
|
64
64
|
name: 'Solid',
|
|
65
|
-
getAddOns: () => [
|
|
65
|
+
getAddOns: () => [
|
|
66
|
+
{
|
|
67
|
+
id: 'nitro',
|
|
68
|
+
name: 'nitro',
|
|
69
|
+
modes: ['file-router'],
|
|
70
|
+
default: true,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
66
73
|
supportedModes: {
|
|
67
74
|
'code-router': {
|
|
68
75
|
displayName: 'Code Router',
|
|
@@ -95,10 +102,11 @@ describe('normalizeOptions', () => {
|
|
|
95
102
|
const options = await normalizeOptions({
|
|
96
103
|
projectName: 'test',
|
|
97
104
|
starter: 'https://github.com/cta-dev/cta-starter-solid',
|
|
105
|
+
host: 'nitro',
|
|
98
106
|
})
|
|
99
107
|
expect(options?.mode).toBe('file-router')
|
|
100
108
|
expect(options?.tailwind).toBe(true)
|
|
101
|
-
expect(options?.typescript).toBe(
|
|
109
|
+
expect(options?.typescript).toBe(true)
|
|
102
110
|
expect(options?.framework?.id).toBe('solid')
|
|
103
111
|
})
|
|
104
112
|
|
|
@@ -123,6 +131,12 @@ describe('normalizeOptions', () => {
|
|
|
123
131
|
name: 'foobar',
|
|
124
132
|
modes: ['file-router'],
|
|
125
133
|
},
|
|
134
|
+
{
|
|
135
|
+
id: 'nitro',
|
|
136
|
+
name: 'nitro',
|
|
137
|
+
modes: ['file-router'],
|
|
138
|
+
default: true,
|
|
139
|
+
},
|
|
126
140
|
],
|
|
127
141
|
})
|
|
128
142
|
const options = await normalizeOptions(
|
|
@@ -151,6 +165,12 @@ describe('normalizeOptions', () => {
|
|
|
151
165
|
name: 'baz',
|
|
152
166
|
modes: ['file-router'],
|
|
153
167
|
},
|
|
168
|
+
{
|
|
169
|
+
id: 'nitro',
|
|
170
|
+
name: 'nitro',
|
|
171
|
+
modes: ['file-router'],
|
|
172
|
+
default: true,
|
|
173
|
+
},
|
|
154
174
|
],
|
|
155
175
|
})
|
|
156
176
|
const options = await normalizeOptions(
|
|
@@ -179,6 +199,12 @@ describe('normalizeOptions', () => {
|
|
|
179
199
|
name: 'Biome',
|
|
180
200
|
modes: ['file-router', 'code-router'],
|
|
181
201
|
},
|
|
202
|
+
{
|
|
203
|
+
id: 'nitro',
|
|
204
|
+
name: 'nitro',
|
|
205
|
+
modes: ['file-router', 'code-router'],
|
|
206
|
+
default: true,
|
|
207
|
+
},
|
|
182
208
|
],
|
|
183
209
|
})
|
|
184
210
|
const options = await normalizeOptions({
|
|
@@ -205,6 +231,12 @@ describe('normalizeOptions', () => {
|
|
|
205
231
|
name: 'baz',
|
|
206
232
|
modes: ['file-router', 'code-router'],
|
|
207
233
|
},
|
|
234
|
+
{
|
|
235
|
+
id: 'nitro',
|
|
236
|
+
name: 'nitro',
|
|
237
|
+
modes: ['file-router', 'code-router'],
|
|
238
|
+
default: true,
|
|
239
|
+
},
|
|
208
240
|
],
|
|
209
241
|
})
|
|
210
242
|
const options = await normalizeOptions({
|