vite-plus 0.1.3 → 0.1.4
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/global/{agent-BE4Xze8Q.js → agent-CpNB3GIY.js} +111 -86
- package/dist/global/config.js +1 -1
- package/dist/global/create.js +324 -170
- package/dist/global/migrate.js +159 -55
- package/dist/global/staged.js +768 -660
- package/dist/global/{workspace-lRm8huz4.js → workspace-CiqQdO1L.js} +153 -85
- package/dist/utils/prompts.d.ts +1 -1
- package/dist/utils/prompts.js +2 -2
- package/package.json +12 -12
package/dist/global/create.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { i as __toESM, t as __commonJSMin } from "./chunk-CgnkrU7a.js";
|
|
2
|
-
import { A as select, C as cancel, D as multiselect, E as log, M as Ct, S as PackageManager, T as intro, a as selectAgentTargetPaths, c as defaultInteractive, d as promptGitHooks, f as runViteFmt, g as displayRelative, j as
|
|
2
|
+
import { A as select, C as cancel, D as multiselect, E as log, M as text, N as Ct, S as PackageManager, T as intro, a as selectAgentTargetPaths, c as defaultInteractive, d as promptGitHooks, f as runViteFmt, g as displayRelative, j as spinner, l as downloadPackageManager$1, m as selectPackageManager, o as writeAgentInstructions, p as runViteInstall, r as detectExistingAgentTargetPaths, w as confirm, x as DependencyType, y as templatesDir } from "./agent-CpNB3GIY.js";
|
|
3
3
|
import { t as lib_default } from "./lib-DxappLRQ.js";
|
|
4
|
-
import {
|
|
4
|
+
import { _ as rewriteMonorepo, a as detectExistingEditor, f as installGitHooks, n as updatePackageJsonWithDeps, o as selectEditor, r as updateWorkspaceConfig, s as writeEditorConfigs, t as detectWorkspace$1, v as rewriteMonorepoProject, y as rewriteStandaloneProject } from "./workspace-CiqQdO1L.js";
|
|
5
5
|
import "./browser-CBapUTD0.js";
|
|
6
6
|
import { r as readJsonFile, t as editJsonFile } from "./json-BRdVJ52a.js";
|
|
7
7
|
import "./package-YAMvX5PJ.js";
|
|
8
8
|
import { a as success, i as muted, n as accent, r as log$1, t as renderCliDoc } from "./help-BAGHa8fD.js";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { styleText } from "node:util";
|
|
11
|
-
import
|
|
11
|
+
import color from "picocolors";
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import { runCommand, vitePlusHeader } from "../../binding/index.js";
|
|
14
14
|
import spawn from "cross-spawn";
|
|
@@ -148,6 +148,11 @@ function parseGitHubUrl(url) {
|
|
|
148
148
|
if (match) return match[1].replace(/\.git$/, "");
|
|
149
149
|
return null;
|
|
150
150
|
}
|
|
151
|
+
function inferGitHubRepoName(templateName) {
|
|
152
|
+
const degitPath = parseGitHubUrl(templateName);
|
|
153
|
+
if (!degitPath) return null;
|
|
154
|
+
return degitPath.split("/").pop() || null;
|
|
155
|
+
}
|
|
151
156
|
function discoverTemplate(templateName, templateArgs, workspaceInfo, interactive) {
|
|
152
157
|
const envs = prependToPathToEnvs(workspaceInfo.downloadPackageManager.binPrefix, { ...process.env });
|
|
153
158
|
const parentDir = inferParentDir(templateName, workspaceInfo);
|
|
@@ -163,11 +168,7 @@ function discoverTemplate(templateName, templateArgs, workspaceInfo, interactive
|
|
|
163
168
|
const degitPath = parseGitHubUrl(templateName);
|
|
164
169
|
if (degitPath) return {
|
|
165
170
|
command: "degit",
|
|
166
|
-
args: [
|
|
167
|
-
degitPath,
|
|
168
|
-
templateName,
|
|
169
|
-
...templateArgs
|
|
170
|
-
],
|
|
171
|
+
args: [degitPath, ...templateArgs],
|
|
171
172
|
envs,
|
|
172
173
|
type: TemplateType.remote,
|
|
173
174
|
parentDir,
|
|
@@ -330,7 +331,7 @@ var require_builtin_modules = /* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
330
331
|
];
|
|
331
332
|
}));
|
|
332
333
|
//#endregion
|
|
333
|
-
//#region
|
|
334
|
+
//#region ../../node_modules/.pnpm/@nkzw+safe-word-list@3.1.0/node_modules/@nkzw/safe-word-list/index.js
|
|
334
335
|
var import_lib = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
335
336
|
const builtins = require_builtin_modules();
|
|
336
337
|
var scopedPackagePattern = /* @__PURE__ */ new RegExp("^(?:@([^/]+?)[/])?([^/]+?)$");
|
|
@@ -387,159 +388,6 @@ var import_lib = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((export
|
|
|
387
388
|
};
|
|
388
389
|
module.exports = validate;
|
|
389
390
|
})))(), 1);
|
|
390
|
-
function copy(src, dest) {
|
|
391
|
-
if (fs.statSync(src).isDirectory()) copyDir(src, dest);
|
|
392
|
-
else fs.copyFileSync(src, dest);
|
|
393
|
-
}
|
|
394
|
-
function copyDir(srcDir, destDir) {
|
|
395
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
396
|
-
for (const file of fs.readdirSync(srcDir)) copy(path.resolve(srcDir, file), path.resolve(destDir, file));
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Format the target directory into a valid directory name and package name
|
|
400
|
-
*
|
|
401
|
-
* Examples:
|
|
402
|
-
* ```
|
|
403
|
-
* # invalid target directories
|
|
404
|
-
* ./ -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
405
|
-
* /foo/bar -> { directory: '', packageName: '', error: 'Absolute path is not allowed' }
|
|
406
|
-
* @scope/ -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
407
|
-
* ../../foo/bar -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
408
|
-
*
|
|
409
|
-
* # valid target directories
|
|
410
|
-
* ./my-package -> { directory: './my-package', packageName: 'my-package' }
|
|
411
|
-
* ./foo/bar-package -> { directory: './foo/bar-package', packageName: 'bar-package' }
|
|
412
|
-
* ./foo/bar-package/ -> { directory: './foo/bar-package', packageName: 'bar-package' }
|
|
413
|
-
* my-package -> { directory: 'my-package', packageName: 'my-package' }
|
|
414
|
-
* @my-scope/my-package -> { directory: 'my-package', packageName: '@my-scope/my-package' }
|
|
415
|
-
* foo/@my-scope/my-package -> { directory: 'foo/my-package', packageName: '@scope/my-package' }
|
|
416
|
-
* ./foo/@my-scope/my-package -> { directory: './foo/my-package', packageName: '@scope/my-package' }
|
|
417
|
-
* ./foo/bar/@scope/my-package -> { directory: './foo/bar/my-package', packageName: '@scope/my-package' }
|
|
418
|
-
* ```
|
|
419
|
-
*/
|
|
420
|
-
function formatTargetDir(input) {
|
|
421
|
-
let targetDir = path.normalize(input.trim());
|
|
422
|
-
const parsed = path.parse(targetDir);
|
|
423
|
-
if (parsed.root || path.isAbsolute(targetDir)) return {
|
|
424
|
-
directory: "",
|
|
425
|
-
packageName: "",
|
|
426
|
-
error: "Absolute path is not allowed"
|
|
427
|
-
};
|
|
428
|
-
if (targetDir.includes("..")) return {
|
|
429
|
-
directory: "",
|
|
430
|
-
packageName: "",
|
|
431
|
-
error: "Relative path contains \"..\" which is not allowed"
|
|
432
|
-
};
|
|
433
|
-
let packageName = parsed.base;
|
|
434
|
-
const parentName = path.basename(parsed.dir);
|
|
435
|
-
if (parentName.startsWith("@")) {
|
|
436
|
-
targetDir = path.join(path.dirname(parsed.dir), packageName);
|
|
437
|
-
packageName = `${parentName}/${packageName}`;
|
|
438
|
-
}
|
|
439
|
-
const result = (0, import_lib.default)(packageName);
|
|
440
|
-
if (!result.validForNewPackages) {
|
|
441
|
-
const message = result.errors?.[0] ?? result.warnings?.[0] ?? "Invalid package name";
|
|
442
|
-
return {
|
|
443
|
-
directory: "",
|
|
444
|
-
packageName: "",
|
|
445
|
-
error: `Parsed package name "${packageName}" is invalid: ${message}`
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
return {
|
|
449
|
-
directory: targetDir,
|
|
450
|
-
packageName
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
function getProjectDirFromPackageName(packageName) {
|
|
454
|
-
if (packageName.startsWith("@")) return packageName.split("/")[1];
|
|
455
|
-
return packageName;
|
|
456
|
-
}
|
|
457
|
-
function setPackageName(projectDir, packageName) {
|
|
458
|
-
editJsonFile(path.join(projectDir, "package.json"), (pkg) => {
|
|
459
|
-
pkg.name = packageName;
|
|
460
|
-
return pkg;
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
function formatDisplayTargetDir(targetDir) {
|
|
464
|
-
const normalized = targetDir.split(path.sep).join("/");
|
|
465
|
-
if (normalized === "" || normalized === ".") return "./";
|
|
466
|
-
if (normalized.startsWith("./") || normalized.startsWith("../") || normalized.startsWith("/") || normalized.startsWith("~")) return normalized;
|
|
467
|
-
return `./${normalized}`;
|
|
468
|
-
}
|
|
469
|
-
//#endregion
|
|
470
|
-
//#region src/create/prompts.ts
|
|
471
|
-
async function promptPackageNameAndTargetDir(defaultPackageName, interactive) {
|
|
472
|
-
let packageName;
|
|
473
|
-
let targetDir;
|
|
474
|
-
if (interactive) {
|
|
475
|
-
const selected = await text({
|
|
476
|
-
message: "Package name:",
|
|
477
|
-
placeholder: defaultPackageName,
|
|
478
|
-
defaultValue: defaultPackageName,
|
|
479
|
-
validate: (value) => {
|
|
480
|
-
if (value == null || value.length === 0) return;
|
|
481
|
-
const result = value ? (0, import_lib.default)(value) : null;
|
|
482
|
-
if (result?.validForNewPackages) return;
|
|
483
|
-
return result?.errors?.[0] ?? result?.warnings?.[0] ?? "Invalid package name";
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
if (Ct(selected)) cancelAndExit();
|
|
487
|
-
packageName = selected;
|
|
488
|
-
targetDir = getProjectDirFromPackageName(packageName);
|
|
489
|
-
} else {
|
|
490
|
-
packageName = defaultPackageName;
|
|
491
|
-
targetDir = getProjectDirFromPackageName(packageName);
|
|
492
|
-
log.info(`Using default package name: ${accent(packageName)}`);
|
|
493
|
-
}
|
|
494
|
-
return {
|
|
495
|
-
packageName,
|
|
496
|
-
targetDir
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
async function checkProjectDirExists(projectDirFullPath, interactive) {
|
|
500
|
-
if (!fs.existsSync(projectDirFullPath) || isEmpty(projectDirFullPath)) return;
|
|
501
|
-
if (!interactive) {
|
|
502
|
-
log.info("Use --directory to specify a different location or remove the directory first");
|
|
503
|
-
cancelAndExit(`Target directory "${projectDirFullPath}" is not empty`, 1);
|
|
504
|
-
}
|
|
505
|
-
const overwrite = await select({
|
|
506
|
-
message: `Target directory "${projectDirFullPath}" is not empty. Please choose how to proceed:`,
|
|
507
|
-
options: [{
|
|
508
|
-
label: "Cancel operation",
|
|
509
|
-
value: "no"
|
|
510
|
-
}, {
|
|
511
|
-
label: "Remove existing files and continue",
|
|
512
|
-
value: "yes"
|
|
513
|
-
}]
|
|
514
|
-
});
|
|
515
|
-
if (Ct(overwrite)) cancelAndExit();
|
|
516
|
-
switch (overwrite) {
|
|
517
|
-
case "yes":
|
|
518
|
-
emptyDir(projectDirFullPath);
|
|
519
|
-
break;
|
|
520
|
-
case "no": cancelAndExit();
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
function cancelAndExit(message = "Operation cancelled", exitCode = 0) {
|
|
524
|
-
cancel(message);
|
|
525
|
-
process.exit(exitCode);
|
|
526
|
-
}
|
|
527
|
-
function isEmpty(path) {
|
|
528
|
-
const files = fs.readdirSync(path);
|
|
529
|
-
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
530
|
-
}
|
|
531
|
-
function emptyDir(dir) {
|
|
532
|
-
if (!fs.existsSync(dir)) return;
|
|
533
|
-
for (const file of fs.readdirSync(dir)) {
|
|
534
|
-
if (file === ".git") continue;
|
|
535
|
-
fs.rmSync(path.resolve(dir, file), {
|
|
536
|
-
recursive: true,
|
|
537
|
-
force: true
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
//#endregion
|
|
542
|
-
//#region ../../node_modules/.pnpm/@nkzw+safe-word-list@3.1.0/node_modules/@nkzw/safe-word-list/index.js
|
|
543
391
|
const words = [
|
|
544
392
|
"ability",
|
|
545
393
|
"able",
|
|
@@ -3291,6 +3139,213 @@ function getRandomProjectName(options = {}) {
|
|
|
3291
3139
|
return scope ? `${scope}/${projectName}` : projectName;
|
|
3292
3140
|
}
|
|
3293
3141
|
//#endregion
|
|
3142
|
+
//#region src/create/utils.ts
|
|
3143
|
+
function copy(src, dest) {
|
|
3144
|
+
if (fs.statSync(src).isDirectory()) copyDir(src, dest);
|
|
3145
|
+
else fs.copyFileSync(src, dest);
|
|
3146
|
+
}
|
|
3147
|
+
function copyDir(srcDir, destDir) {
|
|
3148
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
3149
|
+
for (const file of fs.readdirSync(srcDir)) copy(path.resolve(srcDir, file), path.resolve(destDir, file));
|
|
3150
|
+
}
|
|
3151
|
+
/**
|
|
3152
|
+
* Format the target directory into a valid directory name and package name
|
|
3153
|
+
*
|
|
3154
|
+
* Examples:
|
|
3155
|
+
* ```
|
|
3156
|
+
* # invalid target directories
|
|
3157
|
+
* ./ -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
3158
|
+
* /foo/bar -> { directory: '', packageName: '', error: 'Absolute path is not allowed' }
|
|
3159
|
+
* @scope/ -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
3160
|
+
* ../../foo/bar -> { directory: '', packageName: '', error: 'Invalid target directory' }
|
|
3161
|
+
*
|
|
3162
|
+
* # valid target directories
|
|
3163
|
+
* ./my-package -> { directory: './my-package', packageName: 'my-package' }
|
|
3164
|
+
* ./foo/bar-package -> { directory: './foo/bar-package', packageName: 'bar-package' }
|
|
3165
|
+
* ./foo/bar-package/ -> { directory: './foo/bar-package', packageName: 'bar-package' }
|
|
3166
|
+
* my-package -> { directory: 'my-package', packageName: 'my-package' }
|
|
3167
|
+
* @my-scope/my-package -> { directory: 'my-package', packageName: '@my-scope/my-package' }
|
|
3168
|
+
* foo/@my-scope/my-package -> { directory: 'foo/my-package', packageName: '@scope/my-package' }
|
|
3169
|
+
* ./foo/@my-scope/my-package -> { directory: './foo/my-package', packageName: '@scope/my-package' }
|
|
3170
|
+
* ./foo/bar/@scope/my-package -> { directory: './foo/bar/my-package', packageName: '@scope/my-package' }
|
|
3171
|
+
* ```
|
|
3172
|
+
*/
|
|
3173
|
+
function formatTargetDir(input) {
|
|
3174
|
+
let targetDir = path.normalize(input.trim());
|
|
3175
|
+
const parsed = path.parse(targetDir);
|
|
3176
|
+
if (parsed.root || path.isAbsolute(targetDir)) return {
|
|
3177
|
+
directory: "",
|
|
3178
|
+
packageName: "",
|
|
3179
|
+
error: "Absolute path is not allowed"
|
|
3180
|
+
};
|
|
3181
|
+
if (targetDir.includes("..")) return {
|
|
3182
|
+
directory: "",
|
|
3183
|
+
packageName: "",
|
|
3184
|
+
error: "Relative path contains \"..\" which is not allowed"
|
|
3185
|
+
};
|
|
3186
|
+
let packageName = parsed.base;
|
|
3187
|
+
const parentName = path.basename(parsed.dir);
|
|
3188
|
+
if (parentName.startsWith("@")) {
|
|
3189
|
+
targetDir = path.join(path.dirname(parsed.dir), packageName);
|
|
3190
|
+
packageName = `${parentName}/${packageName}`;
|
|
3191
|
+
}
|
|
3192
|
+
const result = (0, import_lib.default)(packageName);
|
|
3193
|
+
if (!result.validForNewPackages) {
|
|
3194
|
+
const message = result.errors?.[0] ?? result.warnings?.[0] ?? "Invalid package name";
|
|
3195
|
+
return {
|
|
3196
|
+
directory: "",
|
|
3197
|
+
packageName: "",
|
|
3198
|
+
error: `Parsed package name "${packageName}" is invalid: ${message}`
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
return {
|
|
3202
|
+
directory: targetDir,
|
|
3203
|
+
packageName
|
|
3204
|
+
};
|
|
3205
|
+
}
|
|
3206
|
+
function getProjectDirFromPackageName(packageName) {
|
|
3207
|
+
if (packageName.startsWith("@")) return packageName.split("/")[1];
|
|
3208
|
+
return packageName;
|
|
3209
|
+
}
|
|
3210
|
+
function setPackageName(projectDir, packageName) {
|
|
3211
|
+
editJsonFile(path.join(projectDir, "package.json"), (pkg) => {
|
|
3212
|
+
pkg.name = packageName;
|
|
3213
|
+
return pkg;
|
|
3214
|
+
});
|
|
3215
|
+
}
|
|
3216
|
+
function formatDisplayTargetDir(targetDir) {
|
|
3217
|
+
const normalized = targetDir.split(path.sep).join("/");
|
|
3218
|
+
if (normalized === "" || normalized === ".") return "./";
|
|
3219
|
+
if (normalized.startsWith("./") || normalized.startsWith("../") || normalized.startsWith("/") || normalized.startsWith("~")) return normalized;
|
|
3220
|
+
return `./${normalized}`;
|
|
3221
|
+
}
|
|
3222
|
+
//#endregion
|
|
3223
|
+
//#region src/create/prompts.ts
|
|
3224
|
+
async function promptPackageNameAndTargetDir(defaultPackageName, interactive) {
|
|
3225
|
+
let packageName;
|
|
3226
|
+
let targetDir;
|
|
3227
|
+
if (interactive) {
|
|
3228
|
+
const selected = await text({
|
|
3229
|
+
message: "Package name:",
|
|
3230
|
+
placeholder: defaultPackageName,
|
|
3231
|
+
defaultValue: defaultPackageName,
|
|
3232
|
+
validate: (value) => {
|
|
3233
|
+
if (value == null || value.length === 0) return;
|
|
3234
|
+
const result = value ? (0, import_lib.default)(value) : null;
|
|
3235
|
+
if (result?.validForNewPackages) return;
|
|
3236
|
+
return result?.errors?.[0] ?? result?.warnings?.[0] ?? "Invalid package name";
|
|
3237
|
+
}
|
|
3238
|
+
});
|
|
3239
|
+
if (Ct(selected)) cancelAndExit();
|
|
3240
|
+
packageName = selected;
|
|
3241
|
+
targetDir = getProjectDirFromPackageName(packageName);
|
|
3242
|
+
} else {
|
|
3243
|
+
packageName = defaultPackageName;
|
|
3244
|
+
targetDir = getProjectDirFromPackageName(packageName);
|
|
3245
|
+
log.info(`Using default package name: ${accent(packageName)}`);
|
|
3246
|
+
}
|
|
3247
|
+
return {
|
|
3248
|
+
packageName,
|
|
3249
|
+
targetDir
|
|
3250
|
+
};
|
|
3251
|
+
}
|
|
3252
|
+
async function promptTargetDir(defaultTargetDir, interactive, options) {
|
|
3253
|
+
let targetDir;
|
|
3254
|
+
if (interactive) {
|
|
3255
|
+
const selected = await text({
|
|
3256
|
+
message: "Target directory:",
|
|
3257
|
+
placeholder: defaultTargetDir,
|
|
3258
|
+
defaultValue: defaultTargetDir,
|
|
3259
|
+
validate: (value) => validateTargetDir(value ?? defaultTargetDir, options?.cwd).error
|
|
3260
|
+
});
|
|
3261
|
+
if (Ct(selected)) cancelAndExit();
|
|
3262
|
+
targetDir = validateTargetDir(selected ?? defaultTargetDir, options?.cwd).directory;
|
|
3263
|
+
} else {
|
|
3264
|
+
targetDir = validateTargetDir(defaultTargetDir, options?.cwd).directory;
|
|
3265
|
+
log.info(`Using default target directory: ${accent(targetDir)}`);
|
|
3266
|
+
}
|
|
3267
|
+
return targetDir;
|
|
3268
|
+
}
|
|
3269
|
+
function suggestAvailableTargetDir(defaultTargetDir, cwd) {
|
|
3270
|
+
let suggestedTargetDir = defaultTargetDir;
|
|
3271
|
+
let attempt = 1;
|
|
3272
|
+
while (!isTargetDirAvailable(path.join(cwd, suggestedTargetDir))) {
|
|
3273
|
+
suggestedTargetDir = getRandomProjectName({ fallbackName: `${defaultTargetDir}-${attempt}` });
|
|
3274
|
+
attempt++;
|
|
3275
|
+
}
|
|
3276
|
+
return suggestedTargetDir;
|
|
3277
|
+
}
|
|
3278
|
+
async function checkProjectDirExists(projectDirFullPath, interactive) {
|
|
3279
|
+
if (isTargetDirAvailable(projectDirFullPath)) return;
|
|
3280
|
+
if (!interactive) {
|
|
3281
|
+
log.info("Use --directory to specify a different location or remove the directory first");
|
|
3282
|
+
cancelAndExit(`Target directory "${projectDirFullPath}" is not empty`, 1);
|
|
3283
|
+
}
|
|
3284
|
+
const overwrite = await select({
|
|
3285
|
+
message: `Target directory "${projectDirFullPath}" is not empty. Please choose how to proceed:`,
|
|
3286
|
+
options: [{
|
|
3287
|
+
label: "Cancel operation",
|
|
3288
|
+
value: "no"
|
|
3289
|
+
}, {
|
|
3290
|
+
label: "Remove existing files and continue",
|
|
3291
|
+
value: "yes"
|
|
3292
|
+
}]
|
|
3293
|
+
});
|
|
3294
|
+
if (Ct(overwrite)) cancelAndExit();
|
|
3295
|
+
switch (overwrite) {
|
|
3296
|
+
case "yes":
|
|
3297
|
+
emptyDir(projectDirFullPath);
|
|
3298
|
+
break;
|
|
3299
|
+
case "no": cancelAndExit();
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
function cancelAndExit(message = "Operation cancelled", exitCode = 0) {
|
|
3303
|
+
cancel(message);
|
|
3304
|
+
process.exit(exitCode);
|
|
3305
|
+
}
|
|
3306
|
+
function isEmpty(path) {
|
|
3307
|
+
const files = fs.readdirSync(path);
|
|
3308
|
+
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
3309
|
+
}
|
|
3310
|
+
function emptyDir(dir) {
|
|
3311
|
+
if (!fs.existsSync(dir)) return;
|
|
3312
|
+
for (const file of fs.readdirSync(dir)) {
|
|
3313
|
+
if (file === ".git") continue;
|
|
3314
|
+
fs.rmSync(path.resolve(dir, file), {
|
|
3315
|
+
recursive: true,
|
|
3316
|
+
force: true
|
|
3317
|
+
});
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
function isTargetDirAvailable(projectDirFullPath) {
|
|
3321
|
+
return !fs.existsSync(projectDirFullPath) || isEmpty(projectDirFullPath);
|
|
3322
|
+
}
|
|
3323
|
+
function validateTargetDir(input, cwd) {
|
|
3324
|
+
const value = input?.trim() ?? "";
|
|
3325
|
+
if (!value) return {
|
|
3326
|
+
directory: "",
|
|
3327
|
+
error: "Target directory is required"
|
|
3328
|
+
};
|
|
3329
|
+
const targetDir = path.normalize(value);
|
|
3330
|
+
if (!targetDir || targetDir === ".") return {
|
|
3331
|
+
directory: "",
|
|
3332
|
+
error: "Target directory is required"
|
|
3333
|
+
};
|
|
3334
|
+
if (path.isAbsolute(targetDir)) return {
|
|
3335
|
+
directory: "",
|
|
3336
|
+
error: "Absolute path is not allowed"
|
|
3337
|
+
};
|
|
3338
|
+
if (targetDir.includes("..")) return {
|
|
3339
|
+
directory: "",
|
|
3340
|
+
error: "Relative path contains \"..\" which is not allowed"
|
|
3341
|
+
};
|
|
3342
|
+
if (cwd && !isTargetDirAvailable(path.join(cwd, targetDir))) return {
|
|
3343
|
+
directory: "",
|
|
3344
|
+
error: `Target directory "${targetDir}" already exists`
|
|
3345
|
+
};
|
|
3346
|
+
return { directory: targetDir };
|
|
3347
|
+
}
|
|
3348
|
+
//#endregion
|
|
3294
3349
|
//#region src/create/templates/generator.ts
|
|
3295
3350
|
async function executeGeneratorScaffold(workspaceInfo, templateInfo, options) {
|
|
3296
3351
|
if (!options?.silent) log.step("Creating generator scaffold...");
|
|
@@ -3320,7 +3375,7 @@ async function executeGeneratorScaffold(workspaceInfo, templateInfo, options) {
|
|
|
3320
3375
|
}
|
|
3321
3376
|
//#endregion
|
|
3322
3377
|
//#region src/create/templates/remote.ts
|
|
3323
|
-
const { gray, yellow } =
|
|
3378
|
+
const { gray, yellow } = color;
|
|
3324
3379
|
async function executeRemoteTemplate(workspaceInfo, templateInfo, options) {
|
|
3325
3380
|
const silent = options?.silent ?? false;
|
|
3326
3381
|
if (!silent) log.step("Generating project…");
|
|
@@ -3403,8 +3458,8 @@ async function executeBuiltinTemplate(workspaceInfo, templateInfo, options) {
|
|
|
3403
3458
|
if (!templateInfo.interactive) templateInfo.args.push("--no-interactive");
|
|
3404
3459
|
} else if (templateInfo.command === BuiltinTemplate.library) {
|
|
3405
3460
|
templateInfo.command = "create-tsdown@latest";
|
|
3406
|
-
if (!templateInfo.interactive) {
|
|
3407
|
-
if (!templateInfo.args.
|
|
3461
|
+
if (!templateInfo.interactive || options?.silent) {
|
|
3462
|
+
if (!templateInfo.args.some((arg) => arg.startsWith("--template") || arg.startsWith("-t"))) templateInfo.args.push("--template", "default");
|
|
3408
3463
|
}
|
|
3409
3464
|
}
|
|
3410
3465
|
templateInfo.args.unshift(templateInfo.targetDir);
|
|
@@ -3745,6 +3800,9 @@ function getTemplateOption(args) {
|
|
|
3745
3800
|
if (arg.startsWith("--template=")) return arg.slice(11);
|
|
3746
3801
|
}
|
|
3747
3802
|
}
|
|
3803
|
+
function hasExplicitTargetDir(args) {
|
|
3804
|
+
return args[0] !== void 0 && !args[0].startsWith("-");
|
|
3805
|
+
}
|
|
3748
3806
|
function formatTemplateName(templateName) {
|
|
3749
3807
|
const templateAliases = {
|
|
3750
3808
|
lit: "Lit",
|
|
@@ -3828,6 +3886,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
3828
3886
|
let selectedAgentTargetPaths;
|
|
3829
3887
|
let selectedEditor;
|
|
3830
3888
|
let selectedParentDir;
|
|
3889
|
+
let remoteTargetDir;
|
|
3831
3890
|
let shouldSetupHooks = false;
|
|
3832
3891
|
if (!selectedTemplateName) {
|
|
3833
3892
|
const templates = [];
|
|
@@ -3936,6 +3995,15 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
3936
3995
|
if (isInSubdirectory && !compactOutput) log.info(`Use ${accent("--directory")} to specify a different target location.`);
|
|
3937
3996
|
selectedParentDir = inferParentDir(selectedTemplateName, workspaceInfoOptional) ?? workspaceInfoOptional.parentDirs[0];
|
|
3938
3997
|
}
|
|
3998
|
+
if (isGitHubUrl(selectedTemplateName)) if (hasExplicitTargetDir(selectedTemplateArgs)) remoteTargetDir = selectedTemplateArgs[0];
|
|
3999
|
+
else {
|
|
4000
|
+
const inferredTargetDir = inferGitHubRepoName(selectedTemplateName) ?? "template";
|
|
4001
|
+
const remoteTargetBaseDir = selectedParentDir ? path.join(workspaceInfoOptional.rootDir, selectedParentDir) : workspaceInfoOptional.rootDir;
|
|
4002
|
+
const defaultTargetDir = suggestAvailableTargetDir(inferredTargetDir, remoteTargetBaseDir);
|
|
4003
|
+
if (defaultTargetDir !== inferredTargetDir && options.interactive) log.info(` Target directory "${inferredTargetDir}" already exists. Suggested: ${accent(defaultTargetDir)}`);
|
|
4004
|
+
remoteTargetDir = await promptTargetDir(defaultTargetDir, options.interactive, { cwd: remoteTargetBaseDir });
|
|
4005
|
+
selectedTemplateArgs = [remoteTargetDir, ...selectedTemplateArgs];
|
|
4006
|
+
}
|
|
3939
4007
|
if (isBuiltinTemplate && !targetDir) if (selectedTemplateName === BuiltinTemplate.monorepo) {
|
|
3940
4008
|
const selected = await promptPackageNameAndTargetDir(getRandomProjectName({ fallbackName: "vite-plus-monorepo" }), options.interactive);
|
|
3941
4009
|
packageName = selected.packageName;
|
|
@@ -3968,10 +4036,55 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
3968
4036
|
onCancel: () => cancelAndExit()
|
|
3969
4037
|
});
|
|
3970
4038
|
shouldSetupHooks = await promptGitHooks(options);
|
|
4039
|
+
const createProgress = options.interactive && compactOutput ? spinner({ indicator: "timer" }) : void 0;
|
|
4040
|
+
let createProgressStarted = false;
|
|
4041
|
+
let createProgressMessage = "Scaffolding project";
|
|
4042
|
+
const updateCreateProgress = (message) => {
|
|
4043
|
+
createProgressMessage = message;
|
|
4044
|
+
if (!createProgress) return;
|
|
4045
|
+
if (createProgressStarted) {
|
|
4046
|
+
createProgress.message(message);
|
|
4047
|
+
return;
|
|
4048
|
+
}
|
|
4049
|
+
createProgress.start(message);
|
|
4050
|
+
createProgressStarted = true;
|
|
4051
|
+
};
|
|
4052
|
+
const clearCreateProgress = () => {
|
|
4053
|
+
if (createProgress && createProgressStarted) {
|
|
4054
|
+
createProgress.clear();
|
|
4055
|
+
createProgressStarted = false;
|
|
4056
|
+
}
|
|
4057
|
+
};
|
|
4058
|
+
const failCreateProgress = (message) => {
|
|
4059
|
+
if (createProgress && createProgressStarted) {
|
|
4060
|
+
createProgress.error(message);
|
|
4061
|
+
createProgressStarted = false;
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
4064
|
+
const pauseCreateProgress = () => {
|
|
4065
|
+
if (createProgress && createProgressStarted) {
|
|
4066
|
+
createProgress.pause();
|
|
4067
|
+
createProgressStarted = false;
|
|
4068
|
+
}
|
|
4069
|
+
};
|
|
4070
|
+
const resumeCreateProgress = () => {
|
|
4071
|
+
if (createProgress && !createProgressStarted) {
|
|
4072
|
+
createProgress.resume(createProgressMessage);
|
|
4073
|
+
createProgressStarted = true;
|
|
4074
|
+
}
|
|
4075
|
+
};
|
|
4076
|
+
updateCreateProgress("Scaffolding project");
|
|
3971
4077
|
const templateInfo = discoverTemplate(selectedTemplateName, selectedTemplateArgs, workspaceInfo, options.interactive);
|
|
3972
4078
|
if (selectedParentDir) templateInfo.parentDir = selectedParentDir;
|
|
3973
4079
|
if (targetDir) templateInfo.parentDir = void 0;
|
|
4080
|
+
if (remoteTargetDir) {
|
|
4081
|
+
const projectDir = templateInfo.parentDir ? path.join(templateInfo.parentDir, remoteTargetDir) : remoteTargetDir;
|
|
4082
|
+
pauseCreateProgress();
|
|
4083
|
+
await checkProjectDirExists(path.join(workspaceInfo.rootDir, projectDir), options.interactive);
|
|
4084
|
+
resumeCreateProgress();
|
|
4085
|
+
}
|
|
3974
4086
|
if (templateInfo.command === BuiltinTemplate.monorepo) {
|
|
4087
|
+
updateCreateProgress("Creating monorepo");
|
|
3975
4088
|
await checkProjectDirExists(path.join(workspaceInfo.rootDir, targetDir), options.interactive);
|
|
3976
4089
|
const result = await executeMonorepoTemplate(workspaceInfo, {
|
|
3977
4090
|
...templateInfo,
|
|
@@ -3979,25 +4092,38 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
3979
4092
|
targetDir
|
|
3980
4093
|
}, options.interactive, { silent: compactOutput });
|
|
3981
4094
|
const { projectDir } = result;
|
|
3982
|
-
if (result.exitCode !== 0 || !projectDir)
|
|
4095
|
+
if (result.exitCode !== 0 || !projectDir) {
|
|
4096
|
+
failCreateProgress("Scaffolding failed");
|
|
4097
|
+
cancelAndExit(`Failed to create monorepo, exit code: ${result.exitCode}`, result.exitCode);
|
|
4098
|
+
}
|
|
3983
4099
|
const fullPath = path.join(workspaceInfo.rootDir, projectDir);
|
|
4100
|
+
updateCreateProgress("Writing agent instructions");
|
|
4101
|
+
pauseCreateProgress();
|
|
3984
4102
|
await writeAgentInstructions({
|
|
3985
4103
|
projectRoot: fullPath,
|
|
3986
4104
|
targetPaths: selectedAgentTargetPaths,
|
|
3987
4105
|
interactive: options.interactive,
|
|
3988
4106
|
silent: compactOutput
|
|
3989
4107
|
});
|
|
4108
|
+
resumeCreateProgress();
|
|
4109
|
+
updateCreateProgress("Writing editor configs");
|
|
4110
|
+
pauseCreateProgress();
|
|
3990
4111
|
await writeEditorConfigs({
|
|
3991
4112
|
projectRoot: fullPath,
|
|
3992
4113
|
editorId: selectedEditor,
|
|
3993
4114
|
interactive: options.interactive,
|
|
3994
4115
|
silent: compactOutput
|
|
3995
4116
|
});
|
|
4117
|
+
resumeCreateProgress();
|
|
3996
4118
|
workspaceInfo.rootDir = fullPath;
|
|
4119
|
+
updateCreateProgress("Integrating monorepo");
|
|
3997
4120
|
rewriteMonorepo(workspaceInfo, void 0, compactOutput);
|
|
3998
4121
|
if (shouldSetupHooks) installGitHooks(fullPath, compactOutput);
|
|
4122
|
+
updateCreateProgress("Installing dependencies");
|
|
3999
4123
|
const installSummary = await runViteInstall(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
4124
|
+
updateCreateProgress("Formatting code");
|
|
4000
4125
|
await runViteFmt(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
4126
|
+
clearCreateProgress();
|
|
4001
4127
|
showCreateSummary({
|
|
4002
4128
|
description: describeScaffold(selectedTemplateName, selectedTemplateArgs),
|
|
4003
4129
|
installSummary,
|
|
@@ -4018,35 +4144,56 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4018
4144
|
packageName = selected.packageName;
|
|
4019
4145
|
targetDir = templateInfo.parentDir ? path.join(templateInfo.parentDir, selected.targetDir) : selected.targetDir;
|
|
4020
4146
|
}
|
|
4147
|
+
pauseCreateProgress();
|
|
4021
4148
|
await checkProjectDirExists(targetDir, options.interactive);
|
|
4149
|
+
resumeCreateProgress();
|
|
4150
|
+
updateCreateProgress("Generating project");
|
|
4022
4151
|
result = await executeBuiltinTemplate(workspaceInfo, {
|
|
4023
4152
|
...templateInfo,
|
|
4024
4153
|
packageName,
|
|
4025
4154
|
targetDir
|
|
4026
4155
|
}, { silent: compactOutput });
|
|
4027
|
-
} else
|
|
4028
|
-
|
|
4156
|
+
} else {
|
|
4157
|
+
updateCreateProgress("Generating project");
|
|
4158
|
+
result = await executeRemoteTemplate(workspaceInfo, templateInfo, { silent: compactOutput });
|
|
4159
|
+
}
|
|
4160
|
+
if (result.exitCode !== 0) {
|
|
4161
|
+
failCreateProgress("Scaffolding failed");
|
|
4162
|
+
process.exit(result.exitCode);
|
|
4163
|
+
}
|
|
4029
4164
|
const projectDir = result.projectDir;
|
|
4030
|
-
if (!projectDir)
|
|
4165
|
+
if (!projectDir) {
|
|
4166
|
+
clearCreateProgress();
|
|
4167
|
+
process.exit(0);
|
|
4168
|
+
}
|
|
4031
4169
|
const fullPath = path.join(workspaceInfo.rootDir, projectDir);
|
|
4170
|
+
const agentInstructionsRoot = isMonorepo ? workspaceInfo.rootDir : fullPath;
|
|
4171
|
+
updateCreateProgress("Writing agent instructions");
|
|
4172
|
+
pauseCreateProgress();
|
|
4032
4173
|
await writeAgentInstructions({
|
|
4033
|
-
projectRoot:
|
|
4174
|
+
projectRoot: agentInstructionsRoot,
|
|
4034
4175
|
targetPaths: selectedAgentTargetPaths,
|
|
4035
4176
|
interactive: options.interactive,
|
|
4036
4177
|
silent: compactOutput
|
|
4037
4178
|
});
|
|
4179
|
+
resumeCreateProgress();
|
|
4180
|
+
updateCreateProgress("Writing editor configs");
|
|
4181
|
+
pauseCreateProgress();
|
|
4038
4182
|
await writeEditorConfigs({
|
|
4039
4183
|
projectRoot: fullPath,
|
|
4040
4184
|
editorId: selectedEditor,
|
|
4041
4185
|
interactive: options.interactive,
|
|
4042
4186
|
silent: compactOutput
|
|
4043
4187
|
});
|
|
4188
|
+
resumeCreateProgress();
|
|
4044
4189
|
let installSummary;
|
|
4045
4190
|
if (isMonorepo) {
|
|
4046
4191
|
if (!compactOutput) log.step("Monorepo integration...");
|
|
4192
|
+
updateCreateProgress("Integrating into monorepo");
|
|
4047
4193
|
rewriteMonorepoProject(fullPath, workspaceInfo.packageManager, void 0, compactOutput);
|
|
4048
4194
|
if (workspaceInfo.packages.length > 0) {
|
|
4049
4195
|
if (options.interactive) {
|
|
4196
|
+
pauseCreateProgress();
|
|
4050
4197
|
const selectedDepTypeOptions = await multiselect({
|
|
4051
4198
|
message: `Add workspace dependencies to ${accent(projectDir)}?`,
|
|
4052
4199
|
options: [
|
|
@@ -4072,17 +4219,24 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4072
4219
|
if (!Ct(selected)) selectedDeps = selected;
|
|
4073
4220
|
if (selectedDeps.length > 0) updatePackageJsonWithDeps(workspaceInfo.rootDir, projectDir, selectedDeps, selectedDepType);
|
|
4074
4221
|
}
|
|
4222
|
+
resumeCreateProgress();
|
|
4075
4223
|
}
|
|
4076
4224
|
}
|
|
4077
4225
|
updateWorkspaceConfig(projectDir, workspaceInfo);
|
|
4226
|
+
updateCreateProgress("Installing dependencies");
|
|
4078
4227
|
installSummary = await runViteInstall(workspaceInfo.rootDir, options.interactive, void 0, { silent: compactOutput });
|
|
4228
|
+
updateCreateProgress("Formatting code");
|
|
4079
4229
|
await runViteFmt(workspaceInfo.rootDir, options.interactive, [projectDir], { silent: compactOutput });
|
|
4080
4230
|
} else {
|
|
4231
|
+
updateCreateProgress("Applying Vite+ project setup");
|
|
4081
4232
|
rewriteStandaloneProject(fullPath, workspaceInfo, void 0, compactOutput);
|
|
4082
4233
|
if (shouldSetupHooks) installGitHooks(fullPath, compactOutput);
|
|
4234
|
+
updateCreateProgress("Installing dependencies");
|
|
4083
4235
|
installSummary = await runViteInstall(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
4236
|
+
updateCreateProgress("Formatting code");
|
|
4084
4237
|
await runViteFmt(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
4085
4238
|
}
|
|
4239
|
+
clearCreateProgress();
|
|
4086
4240
|
showCreateSummary({
|
|
4087
4241
|
description: describeScaffold(selectedTemplateName, selectedTemplateArgs),
|
|
4088
4242
|
installSummary,
|