@tanstack/cta-cli 0.10.0-alpha.19 → 0.10.0-alpha.21

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/options.js CHANGED
@@ -1,361 +1,70 @@
1
- import { cancel, confirm, isCancel, multiselect, select, text, } from '@clack/prompts';
2
- import { CODE_ROUTER, DEFAULT_PACKAGE_MANAGER, FILE_ROUTER, SUPPORTED_PACKAGE_MANAGERS, finalizeAddOns, getAllAddOns, getFrameworkById, getPackageManager, loadRemoteAddOn, } from '@tanstack/cta-engine';
3
- // If all CLI options are provided, use them directly
4
- export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns) {
5
- // in some cases, if you use windows/powershell, the argument for addons
6
- // if sepparated by comma is not really passed as an array, but as a string
7
- // with spaces, We need to normalize this edge case.
8
- if (Array.isArray(cliOptions.addOns) && cliOptions.addOns.length === 1) {
9
- const parseSeparatedArgs = cliOptions.addOns[0].split(' ');
10
- if (parseSeparatedArgs.length > 1) {
11
- cliOptions.addOns = parseSeparatedArgs;
12
- }
13
- }
14
- if (cliOptions.projectName) {
15
- let typescript = cliOptions.template === 'typescript' ||
16
- cliOptions.template === 'file-router' ||
17
- cliOptions.framework === 'solid';
18
- let tailwind = !!cliOptions.tailwind;
19
- if (cliOptions.framework === 'solid') {
20
- tailwind = true;
21
- }
22
- let mode = cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
23
- const starter = cliOptions.starter
24
- ? (await loadRemoteAddOn(cliOptions.starter))
25
- : undefined;
26
- if (starter) {
27
- tailwind = starter.tailwind;
28
- typescript = starter.typescript;
29
- cliOptions.framework = starter.framework;
30
- mode = starter.mode;
31
- }
32
- let addOns = false;
33
- let chosenAddOns = [];
34
- if (Array.isArray(cliOptions.addOns) ||
35
- starter?.dependsOn ||
36
- forcedAddOns ||
37
- cliOptions.toolchain) {
38
- addOns = true;
39
- let finalAddOns = Array.from(new Set([...(starter?.dependsOn || []), ...(forcedAddOns || [])]));
40
- if (cliOptions.addOns && Array.isArray(cliOptions.addOns)) {
41
- finalAddOns = Array.from(new Set([
42
- ...(forcedAddOns || []),
43
- ...finalAddOns,
44
- ...cliOptions.addOns,
45
- ]));
46
- }
47
- const framework = getFrameworkById(cliOptions.framework || 'react-cra');
48
- if (cliOptions.toolchain) {
49
- finalAddOns.push(cliOptions.toolchain);
50
- }
51
- chosenAddOns = await finalizeAddOns(framework, forcedMode || cliOptions.template === 'file-router'
52
- ? FILE_ROUTER
53
- : CODE_ROUTER, finalAddOns);
54
- tailwind = true;
55
- typescript = true;
56
- }
57
- return {
58
- // TODO: This is a bit to fix the default framework
59
- framework: getFrameworkById(cliOptions.framework || 'react-cra'),
60
- projectName: cliOptions.projectName,
61
- typescript,
62
- tailwind,
63
- packageManager: cliOptions.packageManager ||
64
- getPackageManager() ||
65
- DEFAULT_PACKAGE_MANAGER,
66
- mode,
67
- git: !!cliOptions.git,
68
- addOns,
69
- chosenAddOns,
70
- variableValues: {},
71
- starter,
72
- };
73
- }
74
- }
75
- async function collectVariables(variables) {
76
- const responses = {};
77
- for (const variable of variables) {
78
- if (variable.type === 'string') {
79
- const response = await text({
80
- message: variable.description,
81
- initialValue: variable.default,
82
- });
83
- if (isCancel(response)) {
84
- cancel('Operation cancelled.');
85
- process.exit(0);
86
- }
87
- responses[variable.name] = response;
88
- }
89
- else if (variable.type === 'number') {
90
- const response = await text({
91
- message: variable.description,
92
- initialValue: variable.default.toString(),
93
- });
94
- if (isCancel(response)) {
95
- cancel('Operation cancelled.');
96
- process.exit(0);
97
- }
98
- responses[variable.name] = Number(response);
99
- }
100
- else {
101
- const response = await confirm({
102
- message: variable.description,
103
- initialValue: variable.default === true,
104
- });
105
- if (isCancel(response)) {
106
- cancel('Operation cancelled.');
107
- process.exit(0);
108
- }
109
- responses[variable.name] = response;
110
- }
111
- }
112
- return responses;
113
- }
1
+ import { CODE_ROUTER, FILE_ROUTER, finalizeAddOns, getFrameworkById, getPackageManager, } from '@tanstack/cta-engine';
2
+ import { getProjectName, selectAddOns, selectGit, selectPackageManager, selectRouterType, selectTailwind, selectToolchain, selectTypescript, } from './ui-prompts.js';
114
3
  export async function promptForOptions(cliOptions, { forcedAddOns = [], forcedMode, }) {
115
4
  const options = {};
116
- const framework = getFrameworkById(cliOptions.framework || 'react-cra');
117
- options.framework = framework;
118
- // TODO: This is a bit of a hack to ensure that the framework is solid
119
- if (options.framework.id === 'solid') {
120
- options.typescript = true;
121
- options.tailwind = true;
122
- }
123
- if (cliOptions.addOns) {
124
- options.typescript = true;
125
- }
126
- if (!cliOptions.projectName) {
127
- const value = await text({
128
- message: 'What would you like to name your project?',
129
- defaultValue: 'my-app',
130
- validate(value) {
131
- if (!value) {
132
- return 'Please enter a name';
133
- }
134
- },
135
- });
136
- if (isCancel(value)) {
137
- cancel('Operation cancelled.');
138
- process.exit(0);
139
- }
140
- options.projectName = value;
141
- }
142
- else {
143
- options.projectName = cliOptions.projectName;
144
- }
5
+ options.framework = getFrameworkById(cliOptions.framework || 'react-cra');
6
+ options.projectName = cliOptions.projectName || (await getProjectName());
145
7
  // Router type selection
146
- if (!cliOptions.template && !forcedMode) {
147
- const routerType = await select({
148
- message: 'Select the router type:',
149
- options: [
150
- {
151
- value: FILE_ROUTER,
152
- label: 'File Router - File-based routing structure',
153
- },
154
- {
155
- value: CODE_ROUTER,
156
- label: 'Code Router - Traditional code-based routing',
157
- },
158
- ],
159
- initialValue: FILE_ROUTER,
160
- });
161
- if (isCancel(routerType)) {
162
- cancel('Operation cancelled.');
163
- process.exit(0);
164
- }
165
- options.mode = routerType;
8
+ if (forcedMode) {
9
+ options.mode = forcedMode;
166
10
  }
167
- else if (forcedMode) {
168
- options.mode = forcedMode === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
169
- options.typescript = options.mode === FILE_ROUTER;
170
- }
171
- else {
11
+ else if (cliOptions.template) {
172
12
  options.mode =
173
13
  cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
174
- if (options.mode === FILE_ROUTER) {
175
- options.typescript = true;
176
- }
14
+ }
15
+ else {
16
+ options.mode = await selectRouterType();
177
17
  }
178
18
  // TypeScript selection (if using Code Router)
179
- if (!options.typescript) {
180
- if (options.mode === CODE_ROUTER) {
181
- const typescriptEnable = await confirm({
182
- message: 'Would you like to use TypeScript?',
183
- initialValue: true,
184
- });
185
- if (isCancel(typescriptEnable)) {
186
- cancel('Operation cancelled.');
187
- process.exit(0);
188
- }
189
- options.typescript = typescriptEnable;
190
- }
191
- else {
192
- options.typescript = true;
193
- }
19
+ options.typescript =
20
+ options.mode === FILE_ROUTER || options.framework.id === 'solid';
21
+ if (!options.typescript && options.mode === CODE_ROUTER) {
22
+ options.typescript = await selectTypescript();
194
23
  }
195
24
  // Tailwind selection
196
25
  if (!cliOptions.tailwind && options.framework.id === 'react-cra') {
197
- const tailwind = await confirm({
198
- message: 'Would you like to use Tailwind CSS?',
199
- initialValue: true,
200
- });
201
- if (isCancel(tailwind)) {
202
- cancel('Operation cancelled.');
203
- process.exit(0);
204
- }
205
- options.tailwind = tailwind;
26
+ options.tailwind = await selectTailwind();
206
27
  }
207
28
  else {
208
- // TODO: This is a bit of a hack to ensure that the framework is solid
209
- options.tailwind = options.framework.id === 'solid' || !!cliOptions.tailwind;
29
+ options.tailwind = true;
210
30
  }
211
31
  // Package manager selection
212
- if (cliOptions.packageManager === undefined) {
213
- const detectedPackageManager = getPackageManager();
214
- if (!detectedPackageManager) {
215
- const pm = await select({
216
- message: 'Select package manager:',
217
- options: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({
218
- value: pm,
219
- label: pm,
220
- })),
221
- initialValue: DEFAULT_PACKAGE_MANAGER,
222
- });
223
- if (isCancel(pm)) {
224
- cancel('Operation cancelled.');
225
- process.exit(0);
226
- }
227
- options.packageManager = pm;
228
- }
229
- else {
230
- options.packageManager = detectedPackageManager;
231
- }
32
+ if (cliOptions.packageManager) {
33
+ options.packageManager = cliOptions.packageManager;
232
34
  }
233
35
  else {
234
- options.packageManager = cliOptions.packageManager;
36
+ const detectedPackageManager = await getPackageManager();
37
+ options.packageManager =
38
+ detectedPackageManager || (await selectPackageManager());
235
39
  }
236
40
  // Toolchain selection
237
- let toolchain = undefined;
238
- if (cliOptions.toolchain === undefined) {
239
- const toolchains = new Set();
240
- for (const addOn of framework.getAddOns()) {
241
- if (addOn.type === 'toolchain') {
242
- toolchains.add(addOn);
243
- }
244
- }
245
- const tc = await select({
246
- message: 'Select toolchain',
247
- options: [
248
- {
249
- value: undefined,
250
- label: 'None',
251
- },
252
- ...Array.from(toolchains).map((tc) => ({
253
- value: tc,
254
- label: tc.name,
255
- })),
256
- ],
257
- initialValue: undefined,
258
- });
259
- if (isCancel(tc)) {
260
- cancel('Operation cancelled.');
261
- process.exit(0);
262
- }
263
- toolchain = tc;
41
+ const toolchain = await selectToolchain(options.framework, cliOptions.toolchain);
42
+ // Add-ons selection
43
+ const addOns = new Set();
44
+ if (toolchain) {
45
+ addOns.add(toolchain);
264
46
  }
265
- else {
266
- for (const addOn of framework.getAddOns()) {
267
- if (addOn.type === 'toolchain' && addOn.id === cliOptions.toolchain) {
268
- toolchain = addOn;
269
- }
270
- }
47
+ for (const addOn of forcedAddOns) {
48
+ addOns.add(addOn);
271
49
  }
272
- options.chosenAddOns = toolchain ? [toolchain] : [];
273
50
  if (Array.isArray(cliOptions.addOns)) {
274
- options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, Array.from(new Set([...cliOptions.addOns, ...forcedAddOns, toolchain?.id])).filter(Boolean));
275
- options.tailwind = true;
276
- }
277
- else if (cliOptions.addOns) {
278
- // Select any add-ons
279
- const allAddOns = await getAllAddOns(options.framework, options.mode);
280
- const addOns = allAddOns.filter((addOn) => addOn.type === 'add-on');
281
- let selectedAddOns = [];
282
- if (options.typescript && addOns.length > 0) {
283
- const value = await multiselect({
284
- message: 'What add-ons would you like for your project:',
285
- options: addOns
286
- .filter((addOn) => !forcedAddOns.includes(addOn.id))
287
- .map((addOn) => ({
288
- value: addOn.id,
289
- label: addOn.name,
290
- hint: addOn.description,
291
- })),
292
- required: false,
293
- });
294
- if (isCancel(value)) {
295
- cancel('Operation cancelled.');
296
- process.exit(0);
297
- }
298
- selectedAddOns = value;
299
- }
300
- // Select any examples
301
- let selectedExamples = [];
302
- const examples = allAddOns.filter((addOn) => addOn.type === 'example');
303
- if (options.typescript && examples.length > 0) {
304
- const value = await multiselect({
305
- message: 'Would you like any examples?',
306
- options: examples
307
- .filter((addOn) => !forcedAddOns.includes(addOn.id))
308
- .map((addOn) => ({
309
- value: addOn.id,
310
- label: addOn.name,
311
- hint: addOn.description,
312
- })),
313
- required: false,
314
- });
315
- if (isCancel(value)) {
316
- cancel('Operation cancelled.');
317
- process.exit(0);
318
- }
319
- selectedExamples = value;
320
- }
321
- if (selectedAddOns.length > 0 ||
322
- selectedExamples.length > 0 ||
323
- forcedAddOns.length > 0 ||
324
- toolchain) {
325
- options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, Array.from(new Set([
326
- ...selectedAddOns,
327
- ...selectedExamples,
328
- ...forcedAddOns,
329
- toolchain?.id,
330
- ])).filter(Boolean));
331
- options.tailwind = true;
51
+ for (const addOn of cliOptions.addOns) {
52
+ addOns.add(addOn);
332
53
  }
333
54
  }
334
- else if (forcedAddOns.length > 0) {
335
- options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, Array.from(new Set([...forcedAddOns, toolchain?.id])).filter(Boolean));
336
- }
337
- // Collect variables
338
- const variables = [];
339
- for (const addOn of options.chosenAddOns) {
340
- for (const variable of addOn.variables ?? []) {
341
- variables.push(variable);
55
+ else {
56
+ for (const addOn of await selectAddOns(options.framework, options.mode, 'add-on', 'What add-ons would you like for your project?', forcedAddOns)) {
57
+ addOns.add(addOn);
342
58
  }
343
- }
344
- options.variableValues = await collectVariables(variables);
345
- // Git selection
346
- if (cliOptions.git === undefined) {
347
- const git = await confirm({
348
- message: 'Would you like to initialize a new git repository?',
349
- initialValue: true,
350
- });
351
- if (isCancel(git)) {
352
- cancel('Operation cancelled.');
353
- process.exit(0);
59
+ for (const addOn of await selectAddOns(options.framework, options.mode, 'example', 'Would you like any examples?', forcedAddOns)) {
60
+ addOns.add(addOn);
354
61
  }
355
- options.git = git;
356
62
  }
357
- else {
358
- options.git = !!cliOptions.git;
63
+ options.chosenAddOns = Array.from(await finalizeAddOns(options.framework, options.mode, Array.from(addOns)));
64
+ if (options.chosenAddOns.length) {
65
+ options.tailwind = true;
66
+ options.typescript = true;
359
67
  }
68
+ options.git = cliOptions.git || (await selectGit());
360
69
  return options;
361
70
  }
@@ -1,7 +1,9 @@
1
1
  import type { Mode } from '@tanstack/cta-engine';
2
- export declare function cli({ name, appName, forcedMode, forcedAddOns, }: {
2
+ import type { TemplateOptions } from './types.js';
3
+ export declare function cli({ name, appName, forcedMode, forcedAddOns, defaultTemplate, }: {
3
4
  name: string;
4
5
  appName: string;
5
6
  forcedMode?: Mode;
6
7
  forcedAddOns?: Array<string>;
8
+ defaultTemplate?: TemplateOptions;
7
9
  }): void;
@@ -0,0 +1,3 @@
1
+ import type { Mode, Options } from '@tanstack/cta-engine';
2
+ import type { CliOptions } from './types.js';
3
+ export declare function normalizeOptions(cliOptions: CliOptions, forcedMode?: Mode, forcedAddOns?: Array<string>): Promise<Options | undefined>;
@@ -0,0 +1,7 @@
1
+ import type { Mode } from '@tanstack/cta-engine';
2
+ export declare function runMCPServer(sse: boolean, { forcedAddOns, appName, name, }: {
3
+ forcedMode?: Mode;
4
+ forcedAddOns?: Array<string>;
5
+ appName?: string;
6
+ name?: string;
7
+ }): Promise<void>;
@@ -1,7 +1,6 @@
1
- import type { Mode, Options, TemplateOptions } from '@tanstack/cta-engine';
1
+ import type { Mode, Options } from '@tanstack/cta-engine';
2
2
  import type { CliOptions } from './types.js';
3
- export declare function normalizeOptions(cliOptions: CliOptions, forcedMode?: Mode, forcedAddOns?: Array<string>): Promise<Options | undefined>;
4
3
  export declare function promptForOptions(cliOptions: CliOptions, { forcedAddOns, forcedMode, }: {
5
4
  forcedAddOns?: Array<string>;
6
- forcedMode?: TemplateOptions;
5
+ forcedMode?: Mode;
7
6
  }): Promise<Required<Options> | undefined>;
@@ -1,4 +1,5 @@
1
- import type { PackageManager, TemplateOptions } from '@tanstack/cta-engine';
1
+ import type { PackageManager } from '@tanstack/cta-engine';
2
+ export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
2
3
  export interface CliOptions {
3
4
  template?: TemplateOptions;
4
5
  framework?: string;
@@ -14,4 +15,5 @@ export interface CliOptions {
14
15
  starter?: string;
15
16
  targetDir?: string;
16
17
  interactive?: boolean;
18
+ ui?: boolean;
17
19
  }
@@ -1,2 +1,2 @@
1
1
  import type { Environment } from '@tanstack/cta-engine';
2
- export declare function createUIEnvironment(): Environment;
2
+ export declare function createUIEnvironment(appName: string, silent: boolean): Environment;
@@ -0,0 +1,10 @@
1
+ import type { Mode, PackageManager } from '@tanstack/cta-engine';
2
+ import type { Framework } from '@tanstack/cta-engine/dist/types/types.js';
3
+ export declare function getProjectName(): Promise<string>;
4
+ export declare function selectRouterType(): Promise<Mode>;
5
+ export declare function selectTypescript(): Promise<boolean>;
6
+ export declare function selectTailwind(): Promise<boolean>;
7
+ export declare function selectPackageManager(): Promise<PackageManager>;
8
+ export declare function selectAddOns(framework: Framework, mode: Mode, type: string, message: string, forcedAddOns?: Array<string>): Promise<Array<string>>;
9
+ export declare function selectGit(): Promise<boolean>;
10
+ export declare function selectToolchain(framework: Framework, toolchain?: string): Promise<string | undefined>;
@@ -0,0 +1,3 @@
1
+ import type { Mode } from '@tanstack/cta-engine';
2
+ import type { TemplateOptions } from './types.js';
3
+ export declare function convertTemplateToMode(template: TemplateOptions): Mode;
@@ -1,49 +1,52 @@
1
1
  import { cancel, confirm, intro, isCancel, log, outro, spinner, } from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
3
  import { createDefaultEnvironment } from '@tanstack/cta-engine';
4
- export function createUIEnvironment() {
4
+ export function createUIEnvironment(appName, silent) {
5
5
  const defaultEnvironment = createDefaultEnvironment();
6
- return {
6
+ let newEnvironment = {
7
7
  ...defaultEnvironment,
8
- intro: (message) => {
9
- intro(message);
10
- },
11
- outro: (message) => {
12
- outro(message);
13
- },
14
- info: (title, message) => {
15
- console.log('info', title, message);
16
- log.info(`${title ? chalk.red(title) : ''}${message ? chalk.green(message) : ''}`);
17
- },
18
- error: (title, message) => {
19
- console.log('error', title, message);
20
- log.error(`${title ? `${title}: ` : ''}${message}`);
21
- },
22
- warn: (title, message) => {
23
- console.log('warn', title, message);
24
- log.warn(`${title ? `${title}: ` : ''}${message}`);
25
- },
26
- confirm: async (message) => {
27
- console.log('confirm', message);
28
- const shouldContinue = await confirm({
29
- message,
30
- });
31
- if (isCancel(shouldContinue)) {
32
- cancel('Operation cancelled.');
33
- process.exit(0);
34
- }
35
- return shouldContinue;
36
- },
37
- spinner: () => {
38
- const s = spinner();
39
- return {
40
- start: (message) => {
41
- s.start(message);
42
- },
43
- stop: (message) => {
44
- s.stop(message);
45
- },
46
- };
47
- },
8
+ appName,
48
9
  };
10
+ if (!silent) {
11
+ newEnvironment = {
12
+ ...newEnvironment,
13
+ intro: (message) => {
14
+ intro(message);
15
+ },
16
+ outro: (message) => {
17
+ outro(message);
18
+ },
19
+ info: (title, message) => {
20
+ log.info(`${title ? chalk.red(title) : ''}${message ? '\n' + chalk.green(message) : ''}`);
21
+ },
22
+ error: (title, message) => {
23
+ log.error(`${title ? `${title}: ` : ''}${message ? '\n' + message : ''}`);
24
+ },
25
+ warn: (title, message) => {
26
+ log.warn(`${title ? `${title}: ` : ''}${message ? '\n' + message : ''}`);
27
+ },
28
+ confirm: async (message) => {
29
+ const shouldContinue = await confirm({
30
+ message,
31
+ });
32
+ if (isCancel(shouldContinue)) {
33
+ cancel('Operation cancelled.');
34
+ process.exit(0);
35
+ }
36
+ return shouldContinue;
37
+ },
38
+ spinner: () => {
39
+ const s = spinner();
40
+ return {
41
+ start: (message) => {
42
+ s.start(message);
43
+ },
44
+ stop: (message) => {
45
+ s.stop(message);
46
+ },
47
+ };
48
+ },
49
+ };
50
+ }
51
+ return newEnvironment;
49
52
  }