@tanstack/cli 0.68.0 → 0.69.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.
- package/dist/cli.js +8 -9
- package/dist/command-line.js +8 -12
- package/dist/options.js +15 -18
- package/dist/telemetry.js +1 -1
- package/dist/types/utils.d.ts +11 -0
- package/dist/ui-prompts.js +17 -23
- package/dist/utils.js +43 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -353,8 +353,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
353
353
|
throw new Error('Failed to normalize options');
|
|
354
354
|
}
|
|
355
355
|
currentTelemetry?.mergeProperties(getResolvedCreateTelemetryProperties(normalizedOpts, options));
|
|
356
|
-
normalizedOpts.targetDir =
|
|
357
|
-
options.targetDir || resolve(process.cwd(), projectName);
|
|
356
|
+
normalizedOpts.targetDir = resolve(normalizedOpts.targetDir);
|
|
358
357
|
// Create the initial app with minimal output for dev watch mode
|
|
359
358
|
console.log(chalk.bold('\ndev-watch'));
|
|
360
359
|
console.log(chalk.gray('├─') + ' ' + `creating initial ${appName} app...`);
|
|
@@ -629,7 +628,10 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
629
628
|
}
|
|
630
629
|
let cameFromPrompts = false;
|
|
631
630
|
if (finalOptions) {
|
|
632
|
-
|
|
631
|
+
const createLocation = resolve(finalOptions.targetDir) === resolve(process.cwd())
|
|
632
|
+
? 'the current directory'
|
|
633
|
+
: finalOptions.projectName;
|
|
634
|
+
intro(`Creating a new ${appName} app in ${createLocation}...`);
|
|
633
635
|
}
|
|
634
636
|
else {
|
|
635
637
|
if (!wantsInteractiveMode) {
|
|
@@ -652,14 +654,11 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
652
654
|
telemetry.mergeProperties(getResolvedCreateTelemetryProperties(finalOptions, cliOptions));
|
|
653
655
|
finalOptions.routerOnly =
|
|
654
656
|
!!cliOptions.routerOnly;
|
|
655
|
-
if (
|
|
656
|
-
finalOptions.targetDir = options.targetDir;
|
|
657
|
-
}
|
|
658
|
-
else if (finalOptions.targetDir) {
|
|
657
|
+
if (finalOptions.targetDir) {
|
|
659
658
|
// Keep the normalized target dir.
|
|
660
659
|
}
|
|
661
|
-
else if (
|
|
662
|
-
finalOptions.targetDir = resolve(
|
|
660
|
+
else if (options.targetDir) {
|
|
661
|
+
finalOptions.targetDir = resolve(options.targetDir);
|
|
663
662
|
}
|
|
664
663
|
else {
|
|
665
664
|
finalOptions.targetDir = resolve(process.cwd(), finalOptions.projectName);
|
package/dist/command-line.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import { DEFAULT_PACKAGE_MANAGER, finalizeAddOns, getFrameworkById, getPackageManager, getRawRegistry, loadStarter, populateAddOnOptionsDefaults, } from '@tanstack/create';
|
|
4
|
-
import {
|
|
4
|
+
import { resolveProjectLocation, validateProjectName, } from './utils.js';
|
|
5
5
|
const SUPPORTED_LEGACY_TEMPLATES = new Set([
|
|
6
6
|
'file-router',
|
|
7
7
|
'typescript',
|
|
@@ -264,19 +264,15 @@ export function validateLegacyCreateFlags(cliOptions) {
|
|
|
264
264
|
return { warnings };
|
|
265
265
|
}
|
|
266
266
|
export async function normalizeOptions(cliOptions, forcedAddOns, opts) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
targetDir = resolve(process.cwd());
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
targetDir = resolve(process.cwd(), projectName);
|
|
276
|
-
}
|
|
277
|
-
if (!projectName && !opts?.disableNameCheck) {
|
|
267
|
+
const projectLocation = resolveProjectLocation({
|
|
268
|
+
projectName: cliOptions.projectName,
|
|
269
|
+
targetDir: cliOptions.targetDir,
|
|
270
|
+
});
|
|
271
|
+
if (!projectLocation && !opts?.disableNameCheck) {
|
|
278
272
|
return undefined;
|
|
279
273
|
}
|
|
274
|
+
const projectName = projectLocation?.projectName ?? '';
|
|
275
|
+
const targetDir = projectLocation?.targetDir ?? resolve(process.cwd());
|
|
280
276
|
if (projectName) {
|
|
281
277
|
const { valid, error } = validateProjectName(projectName);
|
|
282
278
|
if (!valid) {
|
package/dist/options.js
CHANGED
|
@@ -2,7 +2,7 @@ import { intro } from '@clack/prompts';
|
|
|
2
2
|
import { finalizeAddOns, getFrameworkById, getFrameworks, getPackageManager, loadStarter, populateAddOnOptionsDefaults, readConfigFile, } from '@tanstack/create';
|
|
3
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
|
-
import {
|
|
5
|
+
import { resolveProjectLocation, validateProjectName, } from './utils.js';
|
|
6
6
|
export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], forcedDeployment, showDeploymentOptions = true, defaultFrameworkId, }) {
|
|
7
7
|
const options = {};
|
|
8
8
|
if (cliOptions.framework) {
|
|
@@ -17,23 +17,20 @@ export async function promptForCreateOptions(cliOptions, { forcedAddOns = [], fo
|
|
|
17
17
|
options.framework = await selectFramework(availableFrameworks, defaultFrameworkId);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
options.projectName = await getProjectName();
|
|
20
|
+
const projectLocation = resolveProjectLocation({
|
|
21
|
+
projectName: cliOptions.projectName ?? (await getProjectName()),
|
|
22
|
+
targetDir: cliOptions.targetDir,
|
|
23
|
+
emptyProjectNameIsCurrentDirectory: true,
|
|
24
|
+
});
|
|
25
|
+
if (!projectLocation) {
|
|
26
|
+
throw new Error('Project name or target directory is required');
|
|
27
|
+
}
|
|
28
|
+
options.projectName = projectLocation.projectName;
|
|
29
|
+
options.targetDir = projectLocation.targetDir;
|
|
30
|
+
const { valid, error } = validateProjectName(options.projectName);
|
|
31
|
+
if (!valid) {
|
|
32
|
+
console.error(error);
|
|
33
|
+
process.exit(1);
|
|
37
34
|
}
|
|
38
35
|
// Mode is always file-router (TanStack Start)
|
|
39
36
|
options.mode = 'file-router';
|
package/dist/telemetry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { version as nodeVersion } from 'node:process';
|
|
2
|
-
import { getTelemetryStatus, markTelemetryNoticeSeen,
|
|
2
|
+
import { TELEMETRY_NOTICE_VERSION, getTelemetryStatus, markTelemetryNoticeSeen, } from './telemetry-config.js';
|
|
3
3
|
const TELEMETRY_TRANSPORT_ENDPOINT = 'https://www.google-analytics.com/g/collect';
|
|
4
4
|
const TELEMETRY_PROPERTY_ID = 'G-JMT1Z50SPS';
|
|
5
5
|
const TELEMETRY_NOTICE = 'TanStack CLI sends anonymous usage telemetry by default. It never sends project names, paths, raw search text, template URLs, add-on config values, or raw error messages. Disable it with `tanstack telemetry disable` or `TANSTACK_CLI_TELEMETRY_DISABLED=1`.';
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
export declare function sanitizePackageName(name: string): string;
|
|
2
2
|
export declare function getCurrentDirectoryName(): string;
|
|
3
|
+
export declare function getDirectoryPackageName(directory: string): string;
|
|
4
|
+
export declare function getCurrentDirectoryPackageName(): string;
|
|
5
|
+
export declare function isCurrentDirectoryProjectNameInput(name: string): boolean;
|
|
6
|
+
export declare function resolveProjectLocation({ projectName, targetDir, emptyProjectNameIsCurrentDirectory, }: {
|
|
7
|
+
projectName?: string;
|
|
8
|
+
targetDir?: string;
|
|
9
|
+
emptyProjectNameIsCurrentDirectory?: boolean;
|
|
10
|
+
}): {
|
|
11
|
+
projectName: string;
|
|
12
|
+
targetDir: string;
|
|
13
|
+
} | undefined;
|
|
3
14
|
export declare function validateProjectName(name: string): {
|
|
4
15
|
valid: boolean;
|
|
5
16
|
error: string;
|
package/dist/ui-prompts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
|
-
import { validateProjectName } from './utils.js';
|
|
3
|
+
import { isCurrentDirectoryProjectNameInput, validateProjectName, } from './utils.js';
|
|
4
4
|
export async function selectFramework(frameworks, defaultFrameworkId) {
|
|
5
5
|
const initialValue = (defaultFrameworkId &&
|
|
6
6
|
frameworks.find((f) => f.id.toLowerCase() === defaultFrameworkId.toLowerCase())?.id) ||
|
|
@@ -34,10 +34,10 @@ export async function selectInstall() {
|
|
|
34
34
|
export async function getProjectName() {
|
|
35
35
|
const value = await text({
|
|
36
36
|
message: 'What would you like to name your project?',
|
|
37
|
-
|
|
37
|
+
placeholder: 'Leave empty to initialize in the current directory',
|
|
38
38
|
validate(value) {
|
|
39
|
-
if (
|
|
40
|
-
return
|
|
39
|
+
if (isCurrentDirectoryProjectNameInput(value)) {
|
|
40
|
+
return;
|
|
41
41
|
}
|
|
42
42
|
const { valid, error } = validateProjectName(value);
|
|
43
43
|
if (!valid) {
|
|
@@ -49,7 +49,7 @@ export async function getProjectName() {
|
|
|
49
49
|
cancel('Operation cancelled.');
|
|
50
50
|
process.exit(0);
|
|
51
51
|
}
|
|
52
|
-
return value;
|
|
52
|
+
return value.trim();
|
|
53
53
|
}
|
|
54
54
|
export async function selectPackageManager() {
|
|
55
55
|
const packageManager = await select({
|
|
@@ -208,25 +208,19 @@ export async function promptForAddOnOptions(addOnIds, framework) {
|
|
|
208
208
|
continue;
|
|
209
209
|
addOnOptions[addOnId] = {};
|
|
210
210
|
for (const [optionName, option] of Object.entries(addOn.options)) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (isCancel(value)) {
|
|
223
|
-
cancel('Operation cancelled.');
|
|
224
|
-
process.exit(0);
|
|
225
|
-
}
|
|
226
|
-
addOnOptions[addOnId][optionName] = value;
|
|
227
|
-
}
|
|
228
|
-
// Future option types can be added here
|
|
211
|
+
const value = await select({
|
|
212
|
+
message: `${addOn.name}: ${option.label}`,
|
|
213
|
+
options: option.options.map((opt) => ({
|
|
214
|
+
value: opt.value,
|
|
215
|
+
label: opt.label,
|
|
216
|
+
})),
|
|
217
|
+
initialValue: option.default,
|
|
218
|
+
});
|
|
219
|
+
if (isCancel(value)) {
|
|
220
|
+
cancel('Operation cancelled.');
|
|
221
|
+
process.exit(0);
|
|
229
222
|
}
|
|
223
|
+
addOnOptions[addOnId][optionName] = value;
|
|
230
224
|
}
|
|
231
225
|
}
|
|
232
226
|
return addOnOptions;
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { basename } from 'node:path';
|
|
1
|
+
import { basename, resolve } from 'node:path';
|
|
2
2
|
import validatePackageName from 'validate-npm-package-name';
|
|
3
|
+
const FALLBACK_PACKAGE_NAME = 'tanstack-app';
|
|
3
4
|
export function sanitizePackageName(name) {
|
|
4
5
|
return name
|
|
5
6
|
.toLowerCase()
|
|
@@ -13,6 +14,47 @@ export function sanitizePackageName(name) {
|
|
|
13
14
|
export function getCurrentDirectoryName() {
|
|
14
15
|
return basename(process.cwd());
|
|
15
16
|
}
|
|
17
|
+
export function getDirectoryPackageName(directory) {
|
|
18
|
+
return sanitizePackageName(basename(resolve(directory))) || FALLBACK_PACKAGE_NAME;
|
|
19
|
+
}
|
|
20
|
+
export function getCurrentDirectoryPackageName() {
|
|
21
|
+
return getDirectoryPackageName(process.cwd());
|
|
22
|
+
}
|
|
23
|
+
export function isCurrentDirectoryProjectNameInput(name) {
|
|
24
|
+
const normalized = name.trim();
|
|
25
|
+
return normalized === '' || normalized === '.';
|
|
26
|
+
}
|
|
27
|
+
export function resolveProjectLocation({ projectName, targetDir, emptyProjectNameIsCurrentDirectory = false, }) {
|
|
28
|
+
const normalizedProjectName = projectName?.trim() ?? '';
|
|
29
|
+
if (normalizedProjectName === '.') {
|
|
30
|
+
return {
|
|
31
|
+
projectName: getCurrentDirectoryPackageName(),
|
|
32
|
+
targetDir: resolve(process.cwd()),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (normalizedProjectName) {
|
|
36
|
+
return {
|
|
37
|
+
projectName: normalizedProjectName,
|
|
38
|
+
targetDir: targetDir
|
|
39
|
+
? resolve(targetDir)
|
|
40
|
+
: resolve(process.cwd(), normalizedProjectName),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (targetDir) {
|
|
44
|
+
const resolvedTargetDir = resolve(targetDir);
|
|
45
|
+
return {
|
|
46
|
+
projectName: getDirectoryPackageName(resolvedTargetDir),
|
|
47
|
+
targetDir: resolvedTargetDir,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (emptyProjectNameIsCurrentDirectory) {
|
|
51
|
+
return {
|
|
52
|
+
projectName: getCurrentDirectoryPackageName(),
|
|
53
|
+
targetDir: resolve(process.cwd()),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
16
58
|
export function validateProjectName(name) {
|
|
17
59
|
const { validForNewPackages, validForOldPackages, errors, warnings } = validatePackageName(name);
|
|
18
60
|
const error = errors?.[0] || warnings?.[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.69.0",
|
|
4
4
|
"description": "TanStack CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"tempy": "^3.1.0",
|
|
45
45
|
"validate-npm-package-name": "^7.0.0",
|
|
46
46
|
"zod": "^3.24.2",
|
|
47
|
-
"@tanstack/create": "0.68.
|
|
47
|
+
"@tanstack/create": "0.68.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@playwright/test": "^1.58.2",
|