@tanstack/cli 0.64.0 → 0.64.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 CHANGED
@@ -147,7 +147,7 @@ function getResolvedCreateTelemetryProperties(finalOptions, cliOptions) {
147
147
  function formatErrorMessage(error) {
148
148
  return error instanceof Error ? error.message : 'An unknown error occurred';
149
149
  }
150
- export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaultFramework, frameworkDefinitionInitializers, showDeploymentOptions = false, legacyAutoCreate = false, defaultRouterOnly = false, }) {
150
+ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaultFramework, frameworkDefinitionInitializers, showDeploymentOptions = true, legacyAutoCreate = false, defaultRouterOnly = false, }) {
151
151
  let currentTelemetry;
152
152
  const environment = createUIEnvironment(appName, false, () => currentTelemetry);
153
153
  const program = new Command();
@@ -459,38 +459,49 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
459
459
  cliOptions.template.toLowerCase() !== 'file-router') {
460
460
  cliOptions.routerOnly = true;
461
461
  }
462
- cliOptions.framework = getFrameworkByName(options.framework || defaultFramework || 'React').id;
462
+ if (options.framework) {
463
+ cliOptions.framework = getFrameworkByName(options.framework).id;
464
+ }
465
+ else if (defaultFramework) {
466
+ cliOptions.framework = getFrameworkByName(defaultFramework).id;
467
+ }
463
468
  const nonInteractive = !!cliOptions.nonInteractive || !!cliOptions.yes;
464
469
  if (cliOptions.interactive && nonInteractive) {
465
470
  throw new Error('Cannot combine --interactive with --non-interactive/--yes.');
466
471
  }
467
- const addOnsFlagPassed = process.argv.includes('--add-ons');
472
+ const hasInteractiveTerminal = !!process.stdin.isTTY && !!process.stdout.isTTY && !process.env.CI;
468
473
  const wantsInteractiveMode = !nonInteractive &&
469
- (cliOptions.interactive ||
470
- (cliOptions.addOns === true && addOnsFlagPassed));
474
+ (cliOptions.interactive || hasInteractiveTerminal);
471
475
  let finalOptions;
472
476
  if (wantsInteractiveMode) {
473
- cliOptions.addOns = true;
477
+ if (cliOptions.addOns === undefined) {
478
+ cliOptions.addOns = true;
479
+ }
474
480
  }
475
481
  else {
482
+ if (!cliOptions.framework) {
483
+ cliOptions.framework = getFrameworkByName(defaultFramework || 'React').id;
484
+ }
476
485
  finalOptions = await normalizeOptions(cliOptions, forcedAddOns, { forcedDeployment });
477
486
  }
478
- if (nonInteractive) {
479
- if (cliOptions.addOns === true) {
480
- throw new Error('When using --non-interactive/--yes, pass explicit add-ons via --add-ons <ids>.');
481
- }
487
+ if (!wantsInteractiveMode && cliOptions.addOns === true) {
488
+ throw new Error('When running non-interactively, pass explicit add-ons via --add-ons <ids>.');
482
489
  }
483
490
  if (finalOptions) {
484
491
  intro(`Creating a new ${appName} app in ${projectName}...`);
485
492
  }
486
493
  else {
487
- if (nonInteractive) {
494
+ if (!wantsInteractiveMode) {
488
495
  throw new Error('Project name is required in non-interactive mode. Pass [project-name] or --target-dir.');
489
496
  }
490
497
  intro(`Let's configure your ${appName} application`);
491
498
  finalOptions = await promptForCreateOptions(cliOptions, {
492
499
  forcedAddOns,
500
+ forcedDeployment,
493
501
  showDeploymentOptions,
502
+ defaultFrameworkId: defaultFramework
503
+ ? getFrameworkByName(defaultFramework)?.id
504
+ : undefined,
494
505
  });
495
506
  }
496
507
  if (!finalOptions) {
@@ -533,7 +544,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
533
544
  throw new InvalidArgumentError(`Invalid framework: ${value}. Only the following are allowed: ${availableFrameworks.join(', ')}`);
534
545
  }
535
546
  return value;
536
- }, defaultFramework || 'React');
547
+ });
537
548
  }
538
549
  cmd
539
550
  .option('--starter [url-or-id]', 'DEPRECATED: use --template. Initializes from a template URL or built-in id', false)
package/dist/options.js CHANGED
@@ -1,11 +1,22 @@
1
1
  import { intro } from '@clack/prompts';
2
- import { finalizeAddOns, getFrameworkById, getPackageManager, loadStarter, populateAddOnOptionsDefaults, readConfigFile, } from '@tanstack/create';
3
- import { getProjectName, promptForAddOnOptions, promptForEnvVars, selectAddOns, selectDeployment, selectExamples, selectGit, selectPackageManager, selectTemplate, selectToolchain, } from './ui-prompts.js';
2
+ import { finalizeAddOns, getFrameworkById, getFrameworks, getPackageManager, loadStarter, populateAddOnOptionsDefaults, readConfigFile, } from '@tanstack/create';
3
+ import { getProjectName, promptForAddOnOptions, promptForEnvVars, selectAddOns, selectDeployment, selectExamples, selectFramework, selectGit, selectInstall, selectPackageManager, selectTemplate, selectToolchain, } from './ui-prompts.js';
4
4
  import { listTemplateChoices, resolveStarterSpecifier, } from './command-line.js';
5
5
  import { getCurrentDirectoryName, sanitizePackageName, validateProjectName, } from './utils.js';
6
- export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], showDeploymentOptions = false, }) {
6
+ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], forcedDeployment, showDeploymentOptions = true, defaultFrameworkId, }) {
7
7
  const options = {};
8
- options.framework = getFrameworkById(cliOptions.framework || 'react');
8
+ if (cliOptions.framework) {
9
+ options.framework = getFrameworkById(cliOptions.framework);
10
+ }
11
+ else {
12
+ const availableFrameworks = getFrameworks();
13
+ if (defaultFrameworkId || availableFrameworks.length <= 1) {
14
+ options.framework = getFrameworkById(defaultFrameworkId || 'react');
15
+ }
16
+ else {
17
+ options.framework = await selectFramework(availableFrameworks, defaultFrameworkId);
18
+ }
19
+ }
9
20
  // Validate project name
10
21
  if (cliOptions.projectName) {
11
22
  // Handle "." as project name - use sanitized current directory name
@@ -71,11 +82,19 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], sh
71
82
  // Toolchain selection
72
83
  const toolchain = await selectToolchain(options.framework, cliOptions.toolchain);
73
84
  // Deployment selection
74
- const deployment = showDeploymentOptions
75
- ? routerOnly
76
- ? undefined
77
- : await selectDeployment(options.framework, cliOptions.deployment)
78
- : undefined;
85
+ let deployment;
86
+ if (routerOnly) {
87
+ deployment = undefined;
88
+ }
89
+ else if (cliOptions.deployment) {
90
+ deployment = cliOptions.deployment;
91
+ }
92
+ else if (showDeploymentOptions) {
93
+ deployment = await selectDeployment(options.framework, cliOptions.deployment, forcedDeployment);
94
+ }
95
+ else {
96
+ deployment = forcedDeployment;
97
+ }
79
98
  // Add-ons selection
80
99
  const addOns = new Set();
81
100
  // Examples/demo pages are enabled by default
@@ -139,9 +158,7 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], sh
139
158
  options.envVarValues =
140
159
  envVarValues;
141
160
  options.git = cliOptions.git ?? (await selectGit());
142
- if (cliOptions.install === false) {
143
- options.install = false;
144
- }
161
+ options.install = cliOptions.install ?? (await selectInstall());
145
162
  if (starter) {
146
163
  options.starter = starter;
147
164
  }
@@ -1,7 +1,9 @@
1
1
  import type { Options } from '@tanstack/create';
2
2
  import type { CliOptions } from './types.js';
3
- export declare function promptForCreateOptions(cliOptions: CliOptions, { forcedAddOns, showDeploymentOptions, }: {
3
+ export declare function promptForCreateOptions(cliOptions: CliOptions, { forcedAddOns, forcedDeployment, showDeploymentOptions, defaultFrameworkId, }: {
4
4
  forcedAddOns?: Array<string>;
5
+ forcedDeployment?: string;
5
6
  showDeploymentOptions?: boolean;
7
+ defaultFrameworkId?: string;
6
8
  }): Promise<Required<Options> | undefined>;
7
9
  export declare function promptForAddOns(): Promise<Array<string>>;
@@ -1,5 +1,7 @@
1
1
  import type { AddOn, PackageManager } from '@tanstack/create';
2
2
  import type { Framework } from '@tanstack/create/dist/types/types.js';
3
+ export declare function selectFramework(frameworks: Array<Framework>, defaultFrameworkId?: string): Promise<Framework>;
4
+ export declare function selectInstall(): Promise<boolean>;
3
5
  export declare function getProjectName(): Promise<string>;
4
6
  export declare function selectPackageManager(): Promise<PackageManager>;
5
7
  export declare function selectTemplate(templates: Array<{
@@ -13,4 +15,4 @@ export declare function selectExamples(): Promise<boolean>;
13
15
  export declare function selectToolchain(framework: Framework, toolchain?: string | false): Promise<string | undefined>;
14
16
  export declare function promptForAddOnOptions(addOnIds: Array<string>, framework: Framework): Promise<Record<string, Record<string, any>>>;
15
17
  export declare function promptForEnvVars(addOns: Array<AddOn>): Promise<Record<string, string>>;
16
- export declare function selectDeployment(framework: Framework, deployment?: string): Promise<string | undefined>;
18
+ export declare function selectDeployment(framework: Framework, deployment?: string, forcedDeployment?: string): Promise<string | undefined>;
@@ -1,6 +1,36 @@
1
1
  import { cancel, confirm, isCancel, multiselect, note, password, select, text, } from '@clack/prompts';
2
2
  import { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getAllAddOns, } from '@tanstack/create';
3
3
  import { validateProjectName } from './utils.js';
4
+ export async function selectFramework(frameworks, defaultFrameworkId) {
5
+ const initialValue = (defaultFrameworkId &&
6
+ frameworks.find((f) => f.id.toLowerCase() === defaultFrameworkId.toLowerCase())?.id) ||
7
+ frameworks[0].id;
8
+ const selected = await select({
9
+ message: 'Select framework:',
10
+ options: frameworks.map((f) => ({ value: f.id, label: f.name })),
11
+ initialValue,
12
+ });
13
+ if (isCancel(selected)) {
14
+ cancel('Operation cancelled.');
15
+ process.exit(0);
16
+ }
17
+ const framework = frameworks.find((f) => f.id === selected);
18
+ if (!framework) {
19
+ throw new Error(`Unknown framework: ${selected}`);
20
+ }
21
+ return framework;
22
+ }
23
+ export async function selectInstall() {
24
+ const install = await confirm({
25
+ message: 'Would you like to install dependencies now?',
26
+ initialValue: true,
27
+ });
28
+ if (isCancel(install)) {
29
+ cancel('Operation cancelled.');
30
+ process.exit(0);
31
+ }
32
+ return install;
33
+ }
4
34
  export async function getProjectName() {
5
35
  const value = await text({
6
36
  message: 'What would you like to name your project?',
@@ -249,7 +279,7 @@ export async function promptForEnvVars(addOns) {
249
279
  }
250
280
  return result;
251
281
  }
252
- export async function selectDeployment(framework, deployment) {
282
+ export async function selectDeployment(framework, deployment, forcedDeployment) {
253
283
  const deployments = new Set();
254
284
  let initialValue = undefined;
255
285
  for (const addOn of framework
@@ -260,20 +290,27 @@ export async function selectDeployment(framework, deployment) {
260
290
  if (deployment && addOn.id === deployment) {
261
291
  return deployment;
262
292
  }
263
- if (addOn.default) {
293
+ if (forcedDeployment && addOn.id === forcedDeployment) {
294
+ initialValue = addOn.id;
295
+ }
296
+ else if (!initialValue && addOn.default) {
264
297
  initialValue = addOn.id;
265
298
  }
266
299
  }
267
300
  }
301
+ if (deployments.size === 0) {
302
+ return undefined;
303
+ }
268
304
  const dp = await select({
269
- message: 'Select deployment adapter',
305
+ message: 'Select deployment adapter:',
270
306
  options: [
307
+ { value: undefined, label: 'None' },
271
308
  ...Array.from(deployments).map((d) => ({
272
309
  value: d.id,
273
310
  label: d.name,
274
311
  })),
275
312
  ],
276
- initialValue: initialValue,
313
+ initialValue,
277
314
  });
278
315
  if (isCancel(dp)) {
279
316
  cancel('Operation cancelled.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cli",
3
- "version": "0.64.0",
3
+ "version": "0.64.1",
4
4
  "description": "TanStack CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -41,7 +41,7 @@
41
41
  "tempy": "^3.1.0",
42
42
  "validate-npm-package-name": "^7.0.0",
43
43
  "zod": "^3.24.2",
44
- "@tanstack/create": "0.63.4"
44
+ "@tanstack/create": "0.63.5"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@playwright/test": "^1.58.2",