@tanstack/cli 0.48.7 → 0.58.5
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/CHANGELOG.md +539 -0
- package/dist/bin.js +0 -1
- package/dist/cli.js +23 -60
- package/dist/command-line.js +35 -36
- package/dist/mcp.js +60 -0
- package/dist/options.js +8 -46
- package/dist/types/cli.d.ts +1 -5
- package/dist/types/command-line.d.ts +5 -1
- package/dist/types/mcp.d.ts +0 -1
- package/dist/types/options.d.ts +1 -2
- package/dist/types/types.d.ts +1 -3
- package/dist/types/ui-prompts.d.ts +0 -3
- package/dist/types/utils.d.ts +0 -2
- package/dist/ui-prompts.js +0 -43
- package/dist/utils.js +0 -6
- package/package.json +3 -3
- package/src/bin.ts +0 -1
- package/src/cli.ts +35 -79
- package/src/command-line.ts +51 -46
- package/src/mcp.ts +74 -1
- package/src/options.ts +6 -50
- package/src/types.ts +1 -4
- package/src/ui-prompts.ts +0 -50
- package/src/utils.ts +0 -8
- package/tests/command-line.test.ts +44 -40
- package/tests/options.test.ts +11 -99
- package/tests/ui-prompts.test.ts +0 -38
package/dist/cli.js
CHANGED
|
@@ -8,15 +8,14 @@ import { SUPPORTED_PACKAGE_MANAGERS, addToApp, compileAddOn, compileStarter, cre
|
|
|
8
8
|
import { launchUI } from '@tanstack/create-ui';
|
|
9
9
|
import { runMCPServer } from './mcp.js';
|
|
10
10
|
import { promptForAddOns, promptForCreateOptions } from './options.js';
|
|
11
|
-
import { normalizeOptions, validateDevWatchOptions } from './command-line.js';
|
|
11
|
+
import { normalizeOptions, validateDevWatchOptions, validateLegacyCreateFlags, } from './command-line.js';
|
|
12
12
|
import { createUIEnvironment } from './ui-environment.js';
|
|
13
|
-
import { convertTemplateToMode } from './utils.js';
|
|
14
13
|
import { DevWatchManager } from './dev-watch.js';
|
|
15
14
|
// Read version from package.json
|
|
16
15
|
const packageJsonPath = new URL('../package.json', import.meta.url);
|
|
17
16
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
18
17
|
const VERSION = packageJson.version;
|
|
19
|
-
export function cli({ name, appName,
|
|
18
|
+
export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaultFramework, webBase, frameworkDefinitionInitializers, showDeploymentOptions = false, legacyAutoCreate = false, }) {
|
|
20
19
|
const environment = createUIEnvironment(appName, false);
|
|
21
20
|
const program = new Command();
|
|
22
21
|
const availableFrameworks = getFrameworks().map((f) => f.name);
|
|
@@ -36,28 +35,24 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
for (const framework of getFrameworks()) {
|
|
42
|
-
for (const mode of Object.keys(framework.supportedModes)) {
|
|
43
|
-
supportedModes.add(mode);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (defaultMode && !supportedModes.has(defaultMode)) {
|
|
47
|
-
throw new InvalidArgumentError(`Invalid mode: ${defaultMode}. The following are allowed: ${Array.from(supportedModes).join(', ')}`);
|
|
48
|
-
}
|
|
49
|
-
if (supportedModes.size < 2) {
|
|
50
|
-
defaultMode = Array.from(supportedModes)[0];
|
|
51
|
-
}
|
|
38
|
+
// Mode is always file-router (TanStack Start)
|
|
39
|
+
const defaultMode = 'file-router';
|
|
52
40
|
program
|
|
53
41
|
.name(name)
|
|
54
42
|
.description(`${appName} CLI`)
|
|
55
43
|
.version(VERSION, '-v, --version', 'output the current version');
|
|
56
44
|
// Helper to create the create command action handler
|
|
57
45
|
async function handleCreate(projectName, options) {
|
|
46
|
+
const legacyCreateFlags = validateLegacyCreateFlags(options);
|
|
47
|
+
if (legacyCreateFlags.error) {
|
|
48
|
+
log.error(legacyCreateFlags.error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
for (const warning of legacyCreateFlags.warnings) {
|
|
52
|
+
log.warn(warning);
|
|
53
|
+
}
|
|
58
54
|
if (options.listAddOns) {
|
|
59
|
-
const addOns = await getAllAddOns(getFrameworkByName(options.framework || defaultFramework || 'React'), defaultMode
|
|
60
|
-
convertTemplateToMode(options.template || defaultTemplate));
|
|
55
|
+
const addOns = await getAllAddOns(getFrameworkByName(options.framework || defaultFramework || 'React'), defaultMode);
|
|
61
56
|
let hasConfigurableAddOns = false;
|
|
62
57
|
for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
|
|
63
58
|
const hasOptions = addOn.options && Object.keys(addOn.options).length > 0;
|
|
@@ -72,9 +67,9 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
72
67
|
return;
|
|
73
68
|
}
|
|
74
69
|
if (options.addonDetails) {
|
|
75
|
-
const addOns = await getAllAddOns(getFrameworkByName(options.framework || defaultFramework || 'React'), defaultMode
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
const addOns = await getAllAddOns(getFrameworkByName(options.framework || defaultFramework || 'React'), defaultMode);
|
|
71
|
+
const addOn = addOns.find((a) => a.id === options.addonDetails) ??
|
|
72
|
+
addOns.find((a) => a.id.toLowerCase() === options.addonDetails.toLowerCase());
|
|
78
73
|
if (!addOn) {
|
|
79
74
|
console.error(`Add-on '${options.addonDetails}' not found`);
|
|
80
75
|
process.exit(1);
|
|
@@ -150,7 +145,7 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
150
145
|
...options,
|
|
151
146
|
projectName,
|
|
152
147
|
framework: framework.id,
|
|
153
|
-
},
|
|
148
|
+
}, forcedAddOns);
|
|
154
149
|
if (!normalizedOpts) {
|
|
155
150
|
throw new Error('Failed to normalize options');
|
|
156
151
|
}
|
|
@@ -184,34 +179,15 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
184
179
|
...options,
|
|
185
180
|
};
|
|
186
181
|
cliOptions.framework = getFrameworkByName(options.framework || defaultFramework || 'React').id;
|
|
187
|
-
if (defaultMode) {
|
|
188
|
-
cliOptions.template = defaultMode;
|
|
189
|
-
}
|
|
190
|
-
// Default to Start unless --router-only is specified
|
|
191
|
-
// Skip this if forcedAddOns already includes 'start' (e.g., from cli-aliases)
|
|
192
|
-
if (!options.routerOnly && !forcedAddOns.includes('start')) {
|
|
193
|
-
if (Array.isArray(cliOptions.addOns)) {
|
|
194
|
-
if (!cliOptions.addOns.includes('start')) {
|
|
195
|
-
cliOptions.addOns = [...cliOptions.addOns, 'start'];
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
else if (cliOptions.addOns !== true) {
|
|
199
|
-
cliOptions.addOns = ['start'];
|
|
200
|
-
}
|
|
201
|
-
// Also set template to file-router for Start
|
|
202
|
-
if (!cliOptions.template) {
|
|
203
|
-
cliOptions.template = 'file-router';
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
182
|
let finalOptions;
|
|
207
183
|
if (cliOptions.interactive) {
|
|
208
184
|
cliOptions.addOns = true;
|
|
209
185
|
}
|
|
210
186
|
else {
|
|
211
|
-
finalOptions = await normalizeOptions(cliOptions,
|
|
187
|
+
finalOptions = await normalizeOptions(cliOptions, forcedAddOns, { forcedDeployment });
|
|
212
188
|
}
|
|
213
189
|
if (options.ui) {
|
|
214
|
-
const optionsFromCLI = await normalizeOptions(cliOptions,
|
|
190
|
+
const optionsFromCLI = await normalizeOptions(cliOptions, forcedAddOns, { disableNameCheck: true, forcedDeployment });
|
|
215
191
|
const uiOptions = {
|
|
216
192
|
...createSerializedOptions(optionsFromCLI),
|
|
217
193
|
projectName: 'my-app',
|
|
@@ -234,7 +210,6 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
234
210
|
else {
|
|
235
211
|
intro(`Let's configure your ${appName} application`);
|
|
236
212
|
finalOptions = await promptForCreateOptions(cliOptions, {
|
|
237
|
-
forcedMode: defaultMode,
|
|
238
213
|
forcedAddOns,
|
|
239
214
|
showDeploymentOptions,
|
|
240
215
|
});
|
|
@@ -269,16 +244,6 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
269
244
|
// Helper to configure create command options
|
|
270
245
|
function configureCreateCommand(cmd) {
|
|
271
246
|
cmd.argument('[project-name]', 'name of the project');
|
|
272
|
-
if (!defaultMode && craCompatible) {
|
|
273
|
-
cmd.option('--template <type>', 'project template (typescript, javascript, file-router)', (value) => {
|
|
274
|
-
if (value !== 'typescript' &&
|
|
275
|
-
value !== 'javascript' &&
|
|
276
|
-
value !== 'file-router') {
|
|
277
|
-
throw new InvalidArgumentError(`Invalid template: ${value}. Only the following are allowed: typescript, javascript, file-router`);
|
|
278
|
-
}
|
|
279
|
-
return value;
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
247
|
if (!defaultFramework) {
|
|
283
248
|
cmd.option('--framework <type>', `project framework (${availableFrameworks.join(', ')})`, (value) => {
|
|
284
249
|
if (!availableFrameworks.some((f) => f.toLowerCase() === value.toLowerCase())) {
|
|
@@ -296,7 +261,9 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
296
261
|
}
|
|
297
262
|
return value;
|
|
298
263
|
})
|
|
299
|
-
.option('--dev-watch <path>', 'Watch a framework directory for changes and auto-rebuild')
|
|
264
|
+
.option('--dev-watch <path>', 'Watch a framework directory for changes and auto-rebuild')
|
|
265
|
+
.option('--router-only', 'Deprecated: compatibility flag from create-tsrouter-app')
|
|
266
|
+
.option('--template <type>', 'Deprecated: compatibility flag from create-tsrouter-app');
|
|
300
267
|
if (deployments.size > 0) {
|
|
301
268
|
cmd.option(`--deployment <${Array.from(deployments).join('|')}>`, `Explicitly tell the CLI to use this deployment adapter`, (value) => {
|
|
302
269
|
if (!deployments.has(value)) {
|
|
@@ -316,10 +283,7 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
316
283
|
.option('--no-toolchain', 'skip toolchain selection');
|
|
317
284
|
}
|
|
318
285
|
cmd
|
|
319
|
-
.option('--router-only', 'create a Router-only SPA without TanStack Start (SSR)', false)
|
|
320
286
|
.option('--interactive', 'interactive mode', false)
|
|
321
|
-
.option('--tailwind', 'add Tailwind CSS')
|
|
322
|
-
.option('--no-tailwind', 'skip Tailwind CSS')
|
|
323
287
|
.option('--add-ons [...add-ons]', 'pick from a list of available add-ons (comma separated list)', (value) => {
|
|
324
288
|
let addOns = !!value;
|
|
325
289
|
if (typeof value === 'string') {
|
|
@@ -337,7 +301,7 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
337
301
|
return cmd;
|
|
338
302
|
}
|
|
339
303
|
// === CREATE SUBCOMMAND ===
|
|
340
|
-
//
|
|
304
|
+
// Creates a TanStack Start app (file-router mode).
|
|
341
305
|
const createCommand = program
|
|
342
306
|
.command('create')
|
|
343
307
|
.description(`Create a new TanStack Start application`);
|
|
@@ -350,7 +314,6 @@ export function cli({ name, appName, forcedMode, forcedAddOns = [], defaultTempl
|
|
|
350
314
|
.option('--sse', 'Run in SSE mode instead of stdio', false)
|
|
351
315
|
.action(async (options) => {
|
|
352
316
|
await runMCPServer(options.sse, {
|
|
353
|
-
forcedMode: defaultMode,
|
|
354
317
|
forcedAddOns,
|
|
355
318
|
appName,
|
|
356
319
|
});
|
package/dist/command-line.js
CHANGED
|
@@ -2,7 +2,36 @@ import { resolve } from 'node:path';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import { DEFAULT_PACKAGE_MANAGER, finalizeAddOns, getFrameworkById, getPackageManager, loadStarter, populateAddOnOptionsDefaults, } from '@tanstack/create';
|
|
4
4
|
import { getCurrentDirectoryName, sanitizePackageName, validateProjectName, } from './utils.js';
|
|
5
|
-
|
|
5
|
+
const SUPPORTED_LEGACY_TEMPLATES = new Set([
|
|
6
|
+
'file-router',
|
|
7
|
+
'typescript',
|
|
8
|
+
'tsx',
|
|
9
|
+
]);
|
|
10
|
+
export function validateLegacyCreateFlags(cliOptions) {
|
|
11
|
+
const warnings = [];
|
|
12
|
+
if (cliOptions.routerOnly) {
|
|
13
|
+
warnings.push('The --router-only flag is deprecated and ignored. `tanstack create` already creates router-based apps.');
|
|
14
|
+
}
|
|
15
|
+
if (!cliOptions.template) {
|
|
16
|
+
return { warnings };
|
|
17
|
+
}
|
|
18
|
+
const template = cliOptions.template.toLowerCase().trim();
|
|
19
|
+
if (template === 'javascript' || template === 'js' || template === 'jsx') {
|
|
20
|
+
return {
|
|
21
|
+
warnings,
|
|
22
|
+
error: 'JavaScript/JSX templates are not supported. TanStack Start file-router templates are TypeScript-only.',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (!SUPPORTED_LEGACY_TEMPLATES.has(template)) {
|
|
26
|
+
return {
|
|
27
|
+
warnings,
|
|
28
|
+
error: `Invalid --template value: ${cliOptions.template}. Supported values are: file-router, typescript, tsx.`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
warnings.push('The --template flag is deprecated. TypeScript/TSX is the default and only supported template.');
|
|
32
|
+
return { warnings };
|
|
33
|
+
}
|
|
34
|
+
export async function normalizeOptions(cliOptions, forcedAddOns, opts) {
|
|
6
35
|
let projectName = (cliOptions.projectName ?? '').trim();
|
|
7
36
|
let targetDir;
|
|
8
37
|
// Handle "." as project name - use current directory
|
|
@@ -23,30 +52,19 @@ export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns, opt
|
|
|
23
52
|
process.exit(1);
|
|
24
53
|
}
|
|
25
54
|
}
|
|
26
|
-
|
|
27
|
-
let mode =
|
|
28
|
-
(cliOptions.template === 'file-router' ? 'file-router' : 'code-router');
|
|
55
|
+
// Mode is always file-router (TanStack Start)
|
|
56
|
+
let mode = 'file-router';
|
|
29
57
|
const starter = cliOptions.starter
|
|
30
58
|
? await loadStarter(cliOptions.starter)
|
|
31
59
|
: undefined;
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
cliOptions.framework === 'solid';
|
|
60
|
+
// TypeScript and Tailwind are always enabled with TanStack Start
|
|
61
|
+
const typescript = true;
|
|
62
|
+
const tailwind = true;
|
|
36
63
|
if (starter) {
|
|
37
|
-
tailwind = starter.tailwind;
|
|
38
|
-
typescript = starter.typescript;
|
|
39
64
|
cliOptions.framework = starter.framework;
|
|
40
65
|
mode = starter.mode;
|
|
41
66
|
}
|
|
42
67
|
const framework = getFrameworkById(cliOptions.framework || 'react-cra');
|
|
43
|
-
if (forcedMode &&
|
|
44
|
-
framework.supportedModes?.[forcedMode]?.forceTypescript !== undefined) {
|
|
45
|
-
typescript = true;
|
|
46
|
-
}
|
|
47
|
-
if (cliOptions.framework === 'solid') {
|
|
48
|
-
tailwind = true;
|
|
49
|
-
}
|
|
50
68
|
async function selectAddOns() {
|
|
51
69
|
// Edge case for Windows Powershell
|
|
52
70
|
if (Array.isArray(cliOptions.addOns) && cliOptions.addOns.length === 1) {
|
|
@@ -83,25 +101,6 @@ export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns, opt
|
|
|
83
101
|
return [];
|
|
84
102
|
}
|
|
85
103
|
const chosenAddOns = await selectAddOns();
|
|
86
|
-
if (chosenAddOns.length) {
|
|
87
|
-
typescript = true;
|
|
88
|
-
// Check if any add-on explicitly requires tailwind
|
|
89
|
-
const addOnsRequireTailwind = chosenAddOns.some((addOn) => addOn.tailwind === true);
|
|
90
|
-
// Only set tailwind to true if:
|
|
91
|
-
// 1. An add-on explicitly requires it, OR
|
|
92
|
-
// 2. User explicitly set it via CLI
|
|
93
|
-
if (addOnsRequireTailwind) {
|
|
94
|
-
tailwind = true;
|
|
95
|
-
}
|
|
96
|
-
else if (cliOptions.tailwind === true) {
|
|
97
|
-
tailwind = true;
|
|
98
|
-
}
|
|
99
|
-
else if (cliOptions.tailwind === false) {
|
|
100
|
-
tailwind = false;
|
|
101
|
-
}
|
|
102
|
-
// If cliOptions.tailwind is undefined and no add-ons require it,
|
|
103
|
-
// leave tailwind as is (will be prompted in interactive mode)
|
|
104
|
-
}
|
|
105
104
|
// Handle add-on configuration option
|
|
106
105
|
let addOnOptionsFromCLI = {};
|
|
107
106
|
if (cliOptions.addOnConfig) {
|
package/dist/mcp.js
CHANGED
|
@@ -29,6 +29,11 @@ function createServer({ appName, forcedAddOns = [], }) {
|
|
|
29
29
|
id: addOn.id,
|
|
30
30
|
name: addOn.name,
|
|
31
31
|
description: addOn.description,
|
|
32
|
+
type: addOn.type,
|
|
33
|
+
category: addOn.category,
|
|
34
|
+
link: addOn.link,
|
|
35
|
+
warning: addOn.warning,
|
|
36
|
+
exclusive: addOn.exclusive,
|
|
32
37
|
options: addOn.options,
|
|
33
38
|
dependsOn: addOn.dependsOn,
|
|
34
39
|
}))),
|
|
@@ -36,6 +41,61 @@ function createServer({ appName, forcedAddOns = [], }) {
|
|
|
36
41
|
],
|
|
37
42
|
};
|
|
38
43
|
});
|
|
44
|
+
server.tool('getAddOnDetails', 'Get detailed information about a specific add-on including implementation patterns, routes, dependencies, and documentation', {
|
|
45
|
+
framework: z
|
|
46
|
+
.string()
|
|
47
|
+
.describe(`The framework to use. Available frameworks: ${frameworkNames.join(', ')}`),
|
|
48
|
+
addOnId: z
|
|
49
|
+
.string()
|
|
50
|
+
.describe('The ID of the add-on to get details for'),
|
|
51
|
+
}, async ({ framework: frameworkName, addOnId }) => {
|
|
52
|
+
const framework = getFrameworkByName(frameworkName);
|
|
53
|
+
const allAddOns = framework.getAddOns();
|
|
54
|
+
const addOn = allAddOns.find((a) => a.id === addOnId) ??
|
|
55
|
+
allAddOns.find((a) => a.id.toLowerCase() === addOnId.toLowerCase());
|
|
56
|
+
if (!addOn) {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: JSON.stringify({ error: `Add-on '${addOnId}' not found` }),
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Get file list for context
|
|
67
|
+
const files = await addOn.getFiles();
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: 'text',
|
|
72
|
+
text: JSON.stringify({
|
|
73
|
+
id: addOn.id,
|
|
74
|
+
name: addOn.name,
|
|
75
|
+
description: addOn.description,
|
|
76
|
+
type: addOn.type,
|
|
77
|
+
category: addOn.category,
|
|
78
|
+
phase: addOn.phase,
|
|
79
|
+
modes: addOn.modes,
|
|
80
|
+
link: addOn.link,
|
|
81
|
+
warning: addOn.warning,
|
|
82
|
+
exclusive: addOn.exclusive,
|
|
83
|
+
dependsOn: addOn.dependsOn,
|
|
84
|
+
options: addOn.options,
|
|
85
|
+
routes: addOn.routes,
|
|
86
|
+
packageAdditions: addOn.packageAdditions,
|
|
87
|
+
shadcnComponents: addOn.shadcnComponents,
|
|
88
|
+
integrations: addOn.integrations,
|
|
89
|
+
readme: addOn.readme,
|
|
90
|
+
files,
|
|
91
|
+
author: addOn.author,
|
|
92
|
+
version: addOn.version,
|
|
93
|
+
license: addOn.license,
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
});
|
|
39
99
|
server.tool('createTanStackApplication', 'Create a new TanStack application', {
|
|
40
100
|
framework: z
|
|
41
101
|
.string()
|
package/dist/options.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { cancel, confirm, intro, isCancel } from '@clack/prompts';
|
|
3
3
|
import { finalizeAddOns, getFrameworkById, getPackageManager, populateAddOnOptionsDefaults, readConfigFile, } from '@tanstack/create';
|
|
4
|
-
import { getProjectName, promptForAddOnOptions, selectAddOns, selectDeployment, selectGit, selectPackageManager,
|
|
4
|
+
import { getProjectName, promptForAddOnOptions, selectAddOns, selectDeployment, selectGit, selectPackageManager, selectToolchain, } from './ui-prompts.js';
|
|
5
5
|
import { getCurrentDirectoryName, sanitizePackageName, validateProjectName, } from './utils.js';
|
|
6
|
-
export async function promptForCreateOptions(cliOptions, { forcedAddOns = [],
|
|
6
|
+
export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], showDeploymentOptions = false, }) {
|
|
7
7
|
const options = {};
|
|
8
8
|
options.framework = getFrameworkById(cliOptions.framework || 'react-cra');
|
|
9
9
|
// Validate project name
|
|
@@ -37,28 +37,10 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], fo
|
|
|
37
37
|
process.exit(0);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
else if (cliOptions.template) {
|
|
45
|
-
options.mode =
|
|
46
|
-
cliOptions.template === 'file-router' ? 'file-router' : 'code-router';
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
options.mode = await selectRouterType();
|
|
50
|
-
}
|
|
51
|
-
// TypeScript selection (if using Code Router)
|
|
52
|
-
// TODO: Make this declarative
|
|
53
|
-
options.typescript =
|
|
54
|
-
options.mode === 'file-router' || options.framework.id === 'solid';
|
|
55
|
-
if (forcedMode &&
|
|
56
|
-
options.framework.supportedModes[forcedMode].forceTypescript) {
|
|
57
|
-
options.typescript = true;
|
|
58
|
-
}
|
|
59
|
-
if (!options.typescript && options.mode === 'code-router') {
|
|
60
|
-
options.typescript = await selectTypescript();
|
|
61
|
-
}
|
|
40
|
+
// Mode is always file-router (TanStack Start)
|
|
41
|
+
options.mode = 'file-router';
|
|
42
|
+
// TypeScript is always enabled with file-router
|
|
43
|
+
options.typescript = true;
|
|
62
44
|
// Package manager selection
|
|
63
45
|
if (cliOptions.packageManager) {
|
|
64
46
|
options.packageManager = cliOptions.packageManager;
|
|
@@ -99,28 +81,8 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], fo
|
|
|
99
81
|
}
|
|
100
82
|
}
|
|
101
83
|
options.chosenAddOns = Array.from(await finalizeAddOns(options.framework, options.mode, Array.from(addOns)));
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
// Tailwind selection
|
|
106
|
-
// Only treat add-ons as requiring tailwind if they explicitly have "tailwind": true
|
|
107
|
-
const addOnsRequireTailwind = options.chosenAddOns.some((addOn) => addOn.tailwind === true);
|
|
108
|
-
if (addOnsRequireTailwind) {
|
|
109
|
-
// If any add-on explicitly requires tailwind, enable it automatically
|
|
110
|
-
options.tailwind = true;
|
|
111
|
-
}
|
|
112
|
-
else if (cliOptions.tailwind !== undefined) {
|
|
113
|
-
// User explicitly provided a CLI flag, respect it
|
|
114
|
-
options.tailwind = !!cliOptions.tailwind;
|
|
115
|
-
}
|
|
116
|
-
else if (options.framework.id === 'react-cra') {
|
|
117
|
-
// Only show prompt for react-cra when no CLI flag and no add-ons require it
|
|
118
|
-
options.tailwind = await selectTailwind();
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// For other frameworks (like solid), default to true
|
|
122
|
-
options.tailwind = true;
|
|
123
|
-
}
|
|
84
|
+
// Tailwind is always enabled
|
|
85
|
+
options.tailwind = true;
|
|
124
86
|
// Prompt for add-on options in interactive mode
|
|
125
87
|
if (Array.isArray(cliOptions.addOns)) {
|
|
126
88
|
// Non-interactive mode: use defaults
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import type { TemplateOptions } from './types.js';
|
|
2
1
|
import type { FrameworkDefinition } from '@tanstack/create';
|
|
3
|
-
export declare function cli({ name, appName,
|
|
2
|
+
export declare function cli({ name, appName, forcedAddOns, forcedDeployment, defaultFramework, webBase, frameworkDefinitionInitializers, showDeploymentOptions, legacyAutoCreate, }: {
|
|
4
3
|
name: string;
|
|
5
4
|
appName: string;
|
|
6
|
-
forcedMode?: string;
|
|
7
5
|
forcedAddOns?: Array<string>;
|
|
8
6
|
forcedDeployment?: string;
|
|
9
|
-
defaultTemplate?: TemplateOptions;
|
|
10
7
|
defaultFramework?: string;
|
|
11
|
-
craCompatible?: boolean;
|
|
12
8
|
webBase?: string;
|
|
13
9
|
frameworkDefinitionInitializers?: Array<() => FrameworkDefinition>;
|
|
14
10
|
showDeploymentOptions?: boolean;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Options } from '@tanstack/create';
|
|
2
2
|
import type { CliOptions } from './types.js';
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function validateLegacyCreateFlags(cliOptions: CliOptions): {
|
|
4
|
+
warnings: Array<string>;
|
|
5
|
+
error?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function normalizeOptions(cliOptions: CliOptions, forcedAddOns?: Array<string>, opts?: {
|
|
4
8
|
disableNameCheck?: boolean;
|
|
5
9
|
forcedDeployment?: string;
|
|
6
10
|
}): Promise<Options | undefined>;
|
package/dist/types/mcp.d.ts
CHANGED
package/dist/types/options.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Options } from '@tanstack/create';
|
|
2
2
|
import type { CliOptions } from './types.js';
|
|
3
|
-
export declare function promptForCreateOptions(cliOptions: CliOptions, { forcedAddOns,
|
|
3
|
+
export declare function promptForCreateOptions(cliOptions: CliOptions, { forcedAddOns, showDeploymentOptions, }: {
|
|
4
4
|
forcedAddOns?: Array<string>;
|
|
5
|
-
forcedMode?: string;
|
|
6
5
|
showDeploymentOptions?: boolean;
|
|
7
6
|
}): Promise<Required<Options> | undefined>;
|
|
8
7
|
export declare function promptForAddOns(): Promise<Array<string>>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { PackageManager } from '@tanstack/create';
|
|
2
|
-
export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
|
|
3
2
|
export interface CliOptions {
|
|
4
|
-
template?: TemplateOptions;
|
|
5
3
|
framework?: string;
|
|
6
|
-
tailwind?: boolean;
|
|
7
4
|
packageManager?: PackageManager;
|
|
8
5
|
toolchain?: string | false;
|
|
9
6
|
deployment?: string;
|
|
@@ -23,4 +20,5 @@ export interface CliOptions {
|
|
|
23
20
|
addOnConfig?: string;
|
|
24
21
|
force?: boolean;
|
|
25
22
|
routerOnly?: boolean;
|
|
23
|
+
template?: string;
|
|
26
24
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { PackageManager } from '@tanstack/create';
|
|
2
2
|
import type { Framework } from '@tanstack/create/dist/types/types.js';
|
|
3
3
|
export declare function getProjectName(): Promise<string>;
|
|
4
|
-
export declare function selectRouterType(): Promise<string>;
|
|
5
|
-
export declare function selectTypescript(): Promise<boolean>;
|
|
6
|
-
export declare function selectTailwind(): Promise<boolean>;
|
|
7
4
|
export declare function selectPackageManager(): Promise<PackageManager>;
|
|
8
5
|
export declare function selectAddOns(framework: Framework, mode: string, type: string, message: string, forcedAddOns?: Array<string>, allowMultiple?: boolean): Promise<Array<string>>;
|
|
9
6
|
export declare function selectGit(): Promise<boolean>;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { TemplateOptions } from './types.js';
|
|
2
|
-
export declare function convertTemplateToMode(template: TemplateOptions): string;
|
|
3
1
|
export declare function sanitizePackageName(name: string): string;
|
|
4
2
|
export declare function getCurrentDirectoryName(): string;
|
|
5
3
|
export declare function validateProjectName(name: string): {
|
package/dist/ui-prompts.js
CHANGED
|
@@ -21,49 +21,6 @@ export async function getProjectName() {
|
|
|
21
21
|
}
|
|
22
22
|
return value;
|
|
23
23
|
}
|
|
24
|
-
export async function selectRouterType() {
|
|
25
|
-
const routerType = await select({
|
|
26
|
-
message: 'Select the router type:',
|
|
27
|
-
options: [
|
|
28
|
-
{
|
|
29
|
-
value: 'file-router',
|
|
30
|
-
label: 'File Router - File-based routing structure',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
value: 'code-router',
|
|
34
|
-
label: 'Code Router - Traditional code-based routing',
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
initialValue: 'file-router',
|
|
38
|
-
});
|
|
39
|
-
if (isCancel(routerType)) {
|
|
40
|
-
cancel('Operation cancelled.');
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
43
|
-
return routerType;
|
|
44
|
-
}
|
|
45
|
-
export async function selectTypescript() {
|
|
46
|
-
const typescriptEnable = await confirm({
|
|
47
|
-
message: 'Would you like to use TypeScript?',
|
|
48
|
-
initialValue: true,
|
|
49
|
-
});
|
|
50
|
-
if (isCancel(typescriptEnable)) {
|
|
51
|
-
cancel('Operation cancelled.');
|
|
52
|
-
process.exit(0);
|
|
53
|
-
}
|
|
54
|
-
return typescriptEnable;
|
|
55
|
-
}
|
|
56
|
-
export async function selectTailwind() {
|
|
57
|
-
const tailwind = await confirm({
|
|
58
|
-
message: 'Would you like to use Tailwind CSS?',
|
|
59
|
-
initialValue: true,
|
|
60
|
-
});
|
|
61
|
-
if (isCancel(tailwind)) {
|
|
62
|
-
cancel('Operation cancelled.');
|
|
63
|
-
process.exit(0);
|
|
64
|
-
}
|
|
65
|
-
return tailwind;
|
|
66
|
-
}
|
|
67
24
|
export async function selectPackageManager() {
|
|
68
25
|
const packageManager = await select({
|
|
69
26
|
message: 'Select package manager:',
|
package/dist/utils.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { basename } from 'node:path';
|
|
2
2
|
import validatePackageName from 'validate-npm-package-name';
|
|
3
|
-
export function convertTemplateToMode(template) {
|
|
4
|
-
if (template === 'typescript' || template === 'javascript') {
|
|
5
|
-
return 'code-router';
|
|
6
|
-
}
|
|
7
|
-
return 'file-router';
|
|
8
|
-
}
|
|
9
3
|
export function sanitizePackageName(name) {
|
|
10
4
|
return name
|
|
11
5
|
.toLowerCase()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.5",
|
|
4
4
|
"description": "TanStack CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"tempy": "^3.1.0",
|
|
39
39
|
"validate-npm-package-name": "^7.0.0",
|
|
40
40
|
"zod": "^3.24.2",
|
|
41
|
-
"@tanstack/create": "0.
|
|
42
|
-
"@tanstack/create-ui": "0.
|
|
41
|
+
"@tanstack/create": "0.59.4",
|
|
42
|
+
"@tanstack/create-ui": "0.58.4"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@tanstack/config": "^0.16.2",
|