create-krispya 0.12.0 → 0.14.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.cjs +484 -190
- package/dist/cli.d.cts +2 -2
- package/dist/cli.d.mts +2 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.mjs +491 -196
- package/dist/index.cjs +39 -1
- package/dist/index.d.cts +127 -7
- package/dist/index.d.mts +127 -7
- package/dist/index.d.ts +127 -7
- package/dist/index.mjs +2 -1
- package/dist/shared/{create-krispya.CcQTepKu.d.cts → create-krispya.8Jt7v_KA.d.cts} +1 -1
- package/dist/shared/{create-krispya.CcQTepKu.d.mts → create-krispya.8Jt7v_KA.d.mts} +1 -1
- package/dist/shared/{create-krispya.CcQTepKu.d.ts → create-krispya.8Jt7v_KA.d.ts} +1 -1
- package/dist/shared/{create-krispya.DZWMfM2v.mjs → create-krispya.BYCdQkPo.mjs} +667 -382
- package/dist/shared/{create-krispya.FNrYi_5V.cjs → create-krispya.Wf4wp5cQ.cjs} +697 -381
- package/package.json +16 -16
package/dist/cli.cjs
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
const p = require('@clack/prompts');
|
|
5
5
|
const color = require('chalk');
|
|
6
6
|
const commander = require('commander');
|
|
7
|
-
const promises
|
|
7
|
+
const promises = require('node:fs/promises');
|
|
8
8
|
const node_module = require('node:module');
|
|
9
9
|
const node_path = require('node:path');
|
|
10
10
|
const node_process = require('node:process');
|
|
11
11
|
const undici = require('undici');
|
|
12
|
-
const workspace = require('./shared/create-krispya.
|
|
13
|
-
const
|
|
14
|
-
const promises = require('fs/promises');
|
|
12
|
+
const workspace = require('./shared/create-krispya.Wf4wp5cQ.cjs');
|
|
13
|
+
const promises$1 = require('fs/promises');
|
|
15
14
|
const fs = require('fs');
|
|
16
15
|
const path = require('path');
|
|
17
16
|
const node_fs = require('node:fs');
|
|
17
|
+
const node_child_process = require('node:child_process');
|
|
18
|
+
require('conf');
|
|
18
19
|
|
|
19
20
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
20
21
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
@@ -33,7 +34,6 @@ function _interopNamespaceCompat(e) {
|
|
|
33
34
|
|
|
34
35
|
const p__namespace = /*#__PURE__*/_interopNamespaceCompat(p);
|
|
35
36
|
const color__default = /*#__PURE__*/_interopDefaultCompat(color);
|
|
36
|
-
const Conf__default = /*#__PURE__*/_interopDefaultCompat(Conf);
|
|
37
37
|
|
|
38
38
|
function formatConfigSummary(options, inherited) {
|
|
39
39
|
const lines = [];
|
|
@@ -51,8 +51,9 @@ function formatConfigSummary(options, inherited) {
|
|
|
51
51
|
const projectType = options.projectType ?? "app";
|
|
52
52
|
const baseTemplate = options.template ? workspace.getBaseTemplate(options.template) : "vanilla";
|
|
53
53
|
if (baseTemplate === "react") {
|
|
54
|
-
lines.push(
|
|
55
|
-
|
|
54
|
+
lines.push(
|
|
55
|
+
formatRow("Framework", workspace.shouldEnableReactCompiler(options) ? "React + compiler" : "React")
|
|
56
|
+
);
|
|
56
57
|
} else if (baseTemplate === "r3f") {
|
|
57
58
|
lines.push(formatRow("Framework", "React Three Fiber"));
|
|
58
59
|
}
|
|
@@ -133,8 +134,9 @@ function formatMonorepoConfigSummary(options) {
|
|
|
133
134
|
lines.push(
|
|
134
135
|
formatRow("Engine", `${workspace.getEngineName(options.engine)}@${options.engine.version ?? "latest"}`)
|
|
135
136
|
);
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
const packageManagerName = workspace.getPackageManagerName(options.packageManager);
|
|
138
|
+
lines.push(formatRow("Package manager", packageManagerName));
|
|
139
|
+
if (packageManagerName === "pnpm") {
|
|
138
140
|
const versionManaged = options.pnpmManageVersions ? "yes" : "no";
|
|
139
141
|
lines.push(formatRow("\u21B3 Version managed", versionManaged, ""));
|
|
140
142
|
}
|
|
@@ -144,22 +146,6 @@ function formatMonorepoConfigSummary(options) {
|
|
|
144
146
|
return lines.join("\n");
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
const config = new Conf__default({
|
|
148
|
-
projectName: "create-krispya"
|
|
149
|
-
});
|
|
150
|
-
function getAiPlatforms() {
|
|
151
|
-
return config.get("aiPlatforms");
|
|
152
|
-
}
|
|
153
|
-
function getConfigStrategy() {
|
|
154
|
-
return config.get("configStrategy") ?? "stealth";
|
|
155
|
-
}
|
|
156
|
-
function clearConfig() {
|
|
157
|
-
config.clear();
|
|
158
|
-
}
|
|
159
|
-
function getConfigPath() {
|
|
160
|
-
return config.path;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
149
|
const R3F_INTEGRATION_OPTIONS = [
|
|
164
150
|
{ value: "drei", label: "Drei" },
|
|
165
151
|
{ value: "handle", label: "Handle" },
|
|
@@ -223,7 +209,7 @@ function getDefaultOptions(template, name, projectType = "app", libraryBundler,
|
|
|
223
209
|
formatter: inheritedSettings?.formatter ?? "prettier",
|
|
224
210
|
// Libraries get vitest by default, apps don't
|
|
225
211
|
testing: projectType === "library" ? "vitest" : "none",
|
|
226
|
-
configStrategy: getConfigStrategy(),
|
|
212
|
+
configStrategy: workspace.getConfigStrategy(),
|
|
227
213
|
ide: "vscode"
|
|
228
214
|
};
|
|
229
215
|
return {
|
|
@@ -273,7 +259,7 @@ async function promptForCustomization(template, name, projectType, features, inh
|
|
|
273
259
|
libraryBundler = bundler;
|
|
274
260
|
}
|
|
275
261
|
let engine = inheritedSettings?.engine ?? presets?.engine ?? { name: "node", version: "latest" };
|
|
276
|
-
let finalPackageManager = inheritedSettings?.packageManager?.name ?? presets?.packageManager ?? "pnpm";
|
|
262
|
+
let finalPackageManager = inheritedSettings?.packageManager?.name ?? presets?.packageManager?.name ?? "pnpm";
|
|
277
263
|
let pnpmManageVersions = inheritedSettings?.pnpmManageVersions ?? presets?.pnpmManageVersions ?? true;
|
|
278
264
|
if (!inheritedSettings?.engine?.version) {
|
|
279
265
|
const nodeVersionInput = await p__namespace.text({
|
|
@@ -281,7 +267,7 @@ async function promptForCustomization(template, name, projectType, features, inh
|
|
|
281
267
|
placeholder: presets?.engine?.version ?? "latest",
|
|
282
268
|
defaultValue: presets?.engine?.version ?? "latest",
|
|
283
269
|
validate: (value) => {
|
|
284
|
-
if (!value
|
|
270
|
+
if (!value?.length) return "Required";
|
|
285
271
|
if (value !== "latest" && !/^\d+(\.\d+(\.\d+)?)?$/.test(value)) {
|
|
286
272
|
return 'Must be "latest" or a valid semver (e.g., "22" or "22.13.0")';
|
|
287
273
|
}
|
|
@@ -301,7 +287,7 @@ async function promptForCustomization(template, name, projectType, features, inh
|
|
|
301
287
|
{ value: "npm", label: "npm" },
|
|
302
288
|
{ value: "yarn", label: "yarn" }
|
|
303
289
|
],
|
|
304
|
-
initialValue: presets?.packageManager ?? "pnpm"
|
|
290
|
+
initialValue: presets?.packageManager?.name ?? "pnpm"
|
|
305
291
|
});
|
|
306
292
|
if (p__namespace.isCancel(packageManager)) {
|
|
307
293
|
p__namespace.cancel("Operation cancelled.");
|
|
@@ -384,7 +370,7 @@ async function promptForCustomization(template, name, projectType, features, inh
|
|
|
384
370
|
{ value: "stealth", label: "stealth", hint: "configs in .config/" },
|
|
385
371
|
{ value: "root", label: "root", hint: "configs at project root" }
|
|
386
372
|
],
|
|
387
|
-
initialValue: getConfigStrategy()
|
|
373
|
+
initialValue: workspace.getConfigStrategy()
|
|
388
374
|
});
|
|
389
375
|
if (p__namespace.isCancel(configStrategyChoice)) {
|
|
390
376
|
p__namespace.cancel("Operation cancelled.");
|
|
@@ -410,7 +396,7 @@ async function promptForCustomization(template, name, projectType, features, inh
|
|
|
410
396
|
projectType,
|
|
411
397
|
libraryBundler: projectType === "library" ? libraryBundler : void 0,
|
|
412
398
|
engine,
|
|
413
|
-
packageManager: { name: finalPackageManager },
|
|
399
|
+
packageManager: presets?.packageManager?.name === finalPackageManager ? presets.packageManager : { name: finalPackageManager },
|
|
414
400
|
pnpmManageVersions,
|
|
415
401
|
linter,
|
|
416
402
|
formatter,
|
|
@@ -457,7 +443,7 @@ async function promptForMonorepoCustomization(name, presets) {
|
|
|
457
443
|
placeholder: presets?.engine?.version ?? "latest",
|
|
458
444
|
defaultValue: presets?.engine?.version ?? "latest",
|
|
459
445
|
validate: (value) => {
|
|
460
|
-
if (!value
|
|
446
|
+
if (!value?.length) return "Required";
|
|
461
447
|
if (value !== "latest" && !/^\d+(\.\d+(\.\d+)?)?$/.test(value)) {
|
|
462
448
|
return 'Must be "latest" or a valid semver (e.g., "22" or "22.13.0")';
|
|
463
449
|
}
|
|
@@ -538,7 +524,7 @@ async function promptForMonorepo(workspaceName, presets) {
|
|
|
538
524
|
formatMonorepoConfigSummary({
|
|
539
525
|
name: defaultOptions.name,
|
|
540
526
|
engine: defaultOptions.engine ?? { name: "node", version: "latest" },
|
|
541
|
-
packageManager:
|
|
527
|
+
packageManager: defaultOptions.packageManager ?? { name: "pnpm" },
|
|
542
528
|
pnpmManageVersions: defaultOptions.pnpmManageVersions,
|
|
543
529
|
linter: defaultOptions.linter ?? "oxlint",
|
|
544
530
|
formatter: defaultOptions.formatter ?? "prettier",
|
|
@@ -559,7 +545,7 @@ async function promptForOptions(name, presets) {
|
|
|
559
545
|
placeholder: workspace.generateRandomName(),
|
|
560
546
|
defaultValue: workspace.generateRandomName(),
|
|
561
547
|
validate: (value) => {
|
|
562
|
-
if (!value
|
|
548
|
+
if (!value?.length) return "Project name is required";
|
|
563
549
|
}
|
|
564
550
|
});
|
|
565
551
|
if (p__namespace.isCancel(nameResult)) {
|
|
@@ -591,7 +577,7 @@ function presetsToInheritedSettings(presets) {
|
|
|
591
577
|
return {
|
|
592
578
|
linter: presets.linter,
|
|
593
579
|
formatter: presets.formatter,
|
|
594
|
-
packageManager: presets.packageManager
|
|
580
|
+
packageManager: presets.packageManager,
|
|
595
581
|
engine: presets.engine,
|
|
596
582
|
pnpmManageVersions: presets.pnpmManageVersions
|
|
597
583
|
};
|
|
@@ -643,7 +629,7 @@ async function promptForPackageOptions(projectName, projectType, inheritedSettin
|
|
|
643
629
|
}
|
|
644
630
|
|
|
645
631
|
async function promptForAiAgentPlatforms(isNonInteractive) {
|
|
646
|
-
const savedPlatforms = getAiPlatforms();
|
|
632
|
+
const savedPlatforms = workspace.getAiPlatforms();
|
|
647
633
|
if (isNonInteractive) {
|
|
648
634
|
return savedPlatforms ?? workspace.ALL_AI_PLATFORMS;
|
|
649
635
|
}
|
|
@@ -676,54 +662,9 @@ async function promptForAiAgentPlatforms(isNonInteractive) {
|
|
|
676
662
|
return selected;
|
|
677
663
|
}
|
|
678
664
|
|
|
679
|
-
async function checkAnyExists(paths) {
|
|
680
|
-
for (const path of paths) {
|
|
681
|
-
try {
|
|
682
|
-
await promises.access(path, promises.constants.F_OK);
|
|
683
|
-
return true;
|
|
684
|
-
} catch {
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
return false;
|
|
688
|
-
}
|
|
689
|
-
async function validateWorkspace(monorepoRoot) {
|
|
690
|
-
const errors = [];
|
|
691
|
-
const tsConfigPath = path.join(monorepoRoot, ".config/typescript/package.json");
|
|
692
|
-
try {
|
|
693
|
-
await promises.access(tsConfigPath, promises.constants.F_OK);
|
|
694
|
-
} catch {
|
|
695
|
-
errors.push("Missing .config/typescript package");
|
|
696
|
-
}
|
|
697
|
-
const linterPaths = [
|
|
698
|
-
path.join(monorepoRoot, ".config/oxlint/package.json"),
|
|
699
|
-
path.join(monorepoRoot, ".config/eslint/package.json"),
|
|
700
|
-
path.join(monorepoRoot, "eslint.config.js"),
|
|
701
|
-
path.join(monorepoRoot, "biome.json")
|
|
702
|
-
];
|
|
703
|
-
const hasLinter = await checkAnyExists(linterPaths);
|
|
704
|
-
if (!hasLinter) {
|
|
705
|
-
errors.push(
|
|
706
|
-
"Missing linter config (.config/oxlint, .config/eslint, eslint.config.js, or biome.json)"
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
|
-
const formatterPaths = [
|
|
710
|
-
path.join(monorepoRoot, ".config/oxfmt/package.json"),
|
|
711
|
-
path.join(monorepoRoot, ".config/prettier/package.json"),
|
|
712
|
-
path.join(monorepoRoot, ".prettierrc.json"),
|
|
713
|
-
path.join(monorepoRoot, "biome.json")
|
|
714
|
-
];
|
|
715
|
-
const hasFormatter = await checkAnyExists(formatterPaths);
|
|
716
|
-
if (!hasFormatter) {
|
|
717
|
-
errors.push(
|
|
718
|
-
"Missing formatter config (.config/oxfmt, .config/prettier, .prettierrc.json, or biome.json)"
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
return { valid: errors.length === 0, errors };
|
|
722
|
-
}
|
|
723
|
-
|
|
724
665
|
async function fileExists$1(path) {
|
|
725
666
|
try {
|
|
726
|
-
await promises
|
|
667
|
+
await promises.access(path, node_fs.constants.F_OK);
|
|
727
668
|
return true;
|
|
728
669
|
} catch {
|
|
729
670
|
return false;
|
|
@@ -739,8 +680,8 @@ async function detectMonorepoRoot() {
|
|
|
739
680
|
while (currentDir !== root) {
|
|
740
681
|
const workspaceFile = node_path.join(currentDir, "pnpm-workspace.yaml");
|
|
741
682
|
try {
|
|
742
|
-
await promises
|
|
743
|
-
const content = await promises
|
|
683
|
+
await promises.access(workspaceFile, node_fs.constants.F_OK);
|
|
684
|
+
const content = await promises.readFile(workspaceFile, "utf-8");
|
|
744
685
|
if (content.includes("packages:")) {
|
|
745
686
|
return currentDir;
|
|
746
687
|
}
|
|
@@ -764,7 +705,7 @@ async function detectPackageRoot() {
|
|
|
764
705
|
async function parseWorkspaceDirectories(monorepoRoot) {
|
|
765
706
|
try {
|
|
766
707
|
const workspaceFile = node_path.join(monorepoRoot, "pnpm-workspace.yaml");
|
|
767
|
-
const content = await promises
|
|
708
|
+
const content = await promises.readFile(workspaceFile, "utf-8");
|
|
768
709
|
return workspace.parseWorkspaceYamlContent(content);
|
|
769
710
|
} catch {
|
|
770
711
|
return [];
|
|
@@ -774,14 +715,14 @@ async function detectWorkspaceSettings(monorepoRoot) {
|
|
|
774
715
|
try {
|
|
775
716
|
const tooling = await workspace.detectTooling(monorepoRoot);
|
|
776
717
|
const pkgPath = node_path.join(monorepoRoot, "package.json");
|
|
777
|
-
const content = await promises
|
|
718
|
+
const content = await promises.readFile(pkgPath, "utf-8");
|
|
778
719
|
const pkgJson = JSON.parse(content);
|
|
779
|
-
const packageManager = workspace.
|
|
720
|
+
const packageManager = workspace.parsePackageManagerSpec(pkgJson.packageManager);
|
|
780
721
|
const engine = workspace.parseEngine(pkgJson.engines);
|
|
781
722
|
let pnpmManageVersions;
|
|
782
723
|
try {
|
|
783
724
|
const workspaceFile = node_path.join(monorepoRoot, "pnpm-workspace.yaml");
|
|
784
|
-
const workspaceContent = await promises
|
|
725
|
+
const workspaceContent = await promises.readFile(workspaceFile, "utf-8");
|
|
785
726
|
pnpmManageVersions = workspaceContent.includes("manage-package-manager-versions: true");
|
|
786
727
|
} catch {
|
|
787
728
|
}
|
|
@@ -819,7 +760,7 @@ async function detectExistingConfigs(monorepoRoot) {
|
|
|
819
760
|
async function getMonorepoScope(monorepoRoot) {
|
|
820
761
|
try {
|
|
821
762
|
const pkgPath = node_path.join(monorepoRoot, "package.json");
|
|
822
|
-
const content = await promises
|
|
763
|
+
const content = await promises.readFile(pkgPath, "utf-8");
|
|
823
764
|
const pkgJson = JSON.parse(content);
|
|
824
765
|
if (pkgJson.name) {
|
|
825
766
|
return pkgJson.name.replace(/^@/, "").replace(/\/.*$/, "");
|
|
@@ -831,12 +772,12 @@ async function getMonorepoScope(monorepoRoot) {
|
|
|
831
772
|
async function getWorkspacePackages(monorepoRoot) {
|
|
832
773
|
const packagesDir = node_path.join(monorepoRoot, "packages");
|
|
833
774
|
try {
|
|
834
|
-
const entries = await promises
|
|
775
|
+
const entries = await promises.readdir(packagesDir, { withFileTypes: true });
|
|
835
776
|
const names = [];
|
|
836
777
|
for (const entry of entries) {
|
|
837
778
|
if (!entry.isDirectory()) continue;
|
|
838
779
|
try {
|
|
839
|
-
const content = await promises
|
|
780
|
+
const content = await promises.readFile(node_path.join(packagesDir, entry.name, "package.json"), "utf-8");
|
|
840
781
|
const pkg = JSON.parse(content);
|
|
841
782
|
if (pkg.name) names.push(pkg.name);
|
|
842
783
|
} catch {
|
|
@@ -851,13 +792,13 @@ async function ensureConfigInWorkspace(monorepoRoot) {
|
|
|
851
792
|
const workspacePath = node_path.join(monorepoRoot, "pnpm-workspace.yaml");
|
|
852
793
|
let content;
|
|
853
794
|
try {
|
|
854
|
-
content = await promises
|
|
795
|
+
content = await promises.readFile(workspacePath, "utf-8");
|
|
855
796
|
} catch {
|
|
856
797
|
content = `packages:
|
|
857
798
|
- '.config/*'
|
|
858
799
|
- 'packages/*'
|
|
859
800
|
`;
|
|
860
|
-
await promises
|
|
801
|
+
await promises.writeFile(workspacePath, content);
|
|
861
802
|
return;
|
|
862
803
|
}
|
|
863
804
|
if (content.includes(".config/*")) {
|
|
@@ -873,7 +814,7 @@ ${content}`;
|
|
|
873
814
|
lines.splice(packagesIndex + 1, 0, " - '.config/*'");
|
|
874
815
|
content = lines.join("\n");
|
|
875
816
|
}
|
|
876
|
-
await promises
|
|
817
|
+
await promises.writeFile(workspacePath, content);
|
|
877
818
|
}
|
|
878
819
|
|
|
879
820
|
async function handleCheckCommand() {
|
|
@@ -882,7 +823,7 @@ async function handleCheckCommand() {
|
|
|
882
823
|
console.log(color__default.red("\u2717") + " Not a monorepo workspace");
|
|
883
824
|
process.exit(1);
|
|
884
825
|
}
|
|
885
|
-
const { valid, errors } = await validateWorkspace(monorepoRoot);
|
|
826
|
+
const { valid, errors } = await workspace.validateWorkspace(monorepoRoot);
|
|
886
827
|
if (valid) {
|
|
887
828
|
console.log(color__default.green("\u2713") + " Valid monorepo workspace");
|
|
888
829
|
console.log(color__default.dim(` ${monorepoRoot}`));
|
|
@@ -901,7 +842,7 @@ async function migrateEslintConfig(monorepoRoot, files) {
|
|
|
901
842
|
const existingConfigPath = node_path.join(monorepoRoot, "eslint.config.js");
|
|
902
843
|
let existingContent;
|
|
903
844
|
try {
|
|
904
|
-
existingContent = await promises
|
|
845
|
+
existingContent = await promises.readFile(existingConfigPath, "utf-8");
|
|
905
846
|
} catch {
|
|
906
847
|
workspace.renderEslintConfigPackage(files);
|
|
907
848
|
return;
|
|
@@ -980,7 +921,7 @@ async function migratePrettierConfig(monorepoRoot, files) {
|
|
|
980
921
|
const existingConfigPath = node_path.join(monorepoRoot, ".prettierrc.json");
|
|
981
922
|
let existingContent;
|
|
982
923
|
try {
|
|
983
|
-
existingContent = await promises
|
|
924
|
+
existingContent = await promises.readFile(existingConfigPath, "utf-8");
|
|
984
925
|
} catch {
|
|
985
926
|
workspace.renderPrettierConfigPackage(files);
|
|
986
927
|
return;
|
|
@@ -1039,7 +980,7 @@ async function handleFixCommand(options) {
|
|
|
1039
980
|
console.log(color__default.dim(" Run this command from within a monorepo"));
|
|
1040
981
|
process.exit(1);
|
|
1041
982
|
}
|
|
1042
|
-
const { valid, errors } = await validateWorkspace(monorepoRoot);
|
|
983
|
+
const { valid, errors } = await workspace.validateWorkspace(monorepoRoot);
|
|
1043
984
|
if (valid) {
|
|
1044
985
|
console.log(color__default.green("\u2713") + " Workspace is already valid");
|
|
1045
986
|
console.log(color__default.dim(` ${monorepoRoot}`));
|
|
@@ -1173,19 +1114,19 @@ async function handleFixCommand(options) {
|
|
|
1173
1114
|
}
|
|
1174
1115
|
for (const [filePath, file] of Object.entries(files)) {
|
|
1175
1116
|
const fullPath = node_path.join(monorepoRoot, filePath);
|
|
1176
|
-
await promises
|
|
1177
|
-
await promises
|
|
1117
|
+
await promises.mkdir(node_path.dirname(fullPath), { recursive: true });
|
|
1118
|
+
await promises.writeFile(fullPath, file.content);
|
|
1178
1119
|
}
|
|
1179
1120
|
await ensureConfigInWorkspace(monorepoRoot);
|
|
1180
1121
|
if (existingConfigs.eslintConfigPath && linter === "eslint") {
|
|
1181
1122
|
try {
|
|
1182
|
-
await promises
|
|
1123
|
+
await promises.unlink(existingConfigs.eslintConfigPath);
|
|
1183
1124
|
} catch {
|
|
1184
1125
|
}
|
|
1185
1126
|
}
|
|
1186
1127
|
if (existingConfigs.prettierConfigPath && formatter === "prettier") {
|
|
1187
1128
|
try {
|
|
1188
|
-
await promises
|
|
1129
|
+
await promises.unlink(existingConfigs.prettierConfigPath);
|
|
1189
1130
|
} catch {
|
|
1190
1131
|
}
|
|
1191
1132
|
}
|
|
@@ -1214,8 +1155,8 @@ async function handleFixCommand(options) {
|
|
|
1214
1155
|
workspace.renderVscodeFiles(vscodeFiles, linter, formatter);
|
|
1215
1156
|
for (const [filePath, file] of Object.entries(vscodeFiles)) {
|
|
1216
1157
|
const fullPath = node_path.join(monorepoRoot, filePath);
|
|
1217
|
-
await promises
|
|
1218
|
-
await promises
|
|
1158
|
+
await promises.mkdir(node_path.dirname(fullPath), { recursive: true });
|
|
1159
|
+
await promises.writeFile(fullPath, file.content);
|
|
1219
1160
|
}
|
|
1220
1161
|
console.log(color__default.dim(" Generated .vscode/settings.json"));
|
|
1221
1162
|
console.log(color__default.dim(" Generated .vscode/extensions.json"));
|
|
@@ -1238,8 +1179,8 @@ async function handleFixCommand(options) {
|
|
|
1238
1179
|
});
|
|
1239
1180
|
for (const [filePath, file] of Object.entries(aiFilesOutput)) {
|
|
1240
1181
|
const fullPath = node_path.join(monorepoRoot, filePath);
|
|
1241
|
-
await promises
|
|
1242
|
-
await promises
|
|
1182
|
+
await promises.mkdir(node_path.dirname(fullPath), { recursive: true });
|
|
1183
|
+
await promises.writeFile(fullPath, file.content);
|
|
1243
1184
|
console.log(color__default.dim(` Generated ${filePath}`));
|
|
1244
1185
|
}
|
|
1245
1186
|
}
|
|
@@ -1281,18 +1222,22 @@ function renderExpectedViteConfig(template) {
|
|
|
1281
1222
|
async function detectCurrentConfig(root, isMonorepo = true) {
|
|
1282
1223
|
let name = root.split(/[/\\]/).pop() ?? "workspace";
|
|
1283
1224
|
let packageManager = "pnpm";
|
|
1225
|
+
let packageManagerSpec = { name: "pnpm" };
|
|
1226
|
+
let engine;
|
|
1284
1227
|
let hasTypecheck = false;
|
|
1285
1228
|
let viteTemplate;
|
|
1286
1229
|
try {
|
|
1287
1230
|
const pkgPath = path.join(root, "package.json");
|
|
1288
|
-
const content = await promises.readFile(pkgPath, "utf-8");
|
|
1231
|
+
const content = await promises$1.readFile(pkgPath, "utf-8");
|
|
1289
1232
|
const pkgJson = JSON.parse(content);
|
|
1290
1233
|
if (pkgJson.name) {
|
|
1291
1234
|
name = pkgJson.name.replace(/^@/, "").replace(/\/.*$/, "");
|
|
1292
1235
|
}
|
|
1293
1236
|
if (pkgJson.packageManager) {
|
|
1294
|
-
|
|
1237
|
+
packageManagerSpec = workspace.parsePackageManagerSpec(pkgJson.packageManager) ?? packageManagerSpec;
|
|
1238
|
+
packageManager = packageManagerSpec.name;
|
|
1295
1239
|
}
|
|
1240
|
+
engine = workspace.parseEngine(pkgJson.engines);
|
|
1296
1241
|
hasTypecheck = pkgJson.scripts?.typecheck != null;
|
|
1297
1242
|
viteTemplate = detectViteTemplate(pkgJson);
|
|
1298
1243
|
} catch {
|
|
@@ -1304,6 +1249,8 @@ async function detectCurrentConfig(root, isMonorepo = true) {
|
|
|
1304
1249
|
linter: tooling.linter ?? "oxlint",
|
|
1305
1250
|
formatter: tooling.formatter ?? "prettier",
|
|
1306
1251
|
packageManager,
|
|
1252
|
+
packageManagerSpec,
|
|
1253
|
+
engine,
|
|
1307
1254
|
isMonorepo,
|
|
1308
1255
|
configStrategy,
|
|
1309
1256
|
hasTypecheck,
|
|
@@ -1410,7 +1357,7 @@ async function planExpectedFiles(config) {
|
|
|
1410
1357
|
}
|
|
1411
1358
|
async function fileExists(path) {
|
|
1412
1359
|
try {
|
|
1413
|
-
await promises.access(path, fs.constants.F_OK);
|
|
1360
|
+
await promises$1.access(path, fs.constants.F_OK);
|
|
1414
1361
|
return true;
|
|
1415
1362
|
} catch {
|
|
1416
1363
|
return false;
|
|
@@ -1552,7 +1499,7 @@ async function compareWithDisk(expected, root) {
|
|
|
1552
1499
|
const fullPath = path.join(root, filePath);
|
|
1553
1500
|
const newContent = file.content;
|
|
1554
1501
|
if (await fileExists(fullPath)) {
|
|
1555
|
-
const currentContent = await promises.readFile(fullPath, "utf-8");
|
|
1502
|
+
const currentContent = await promises$1.readFile(fullPath, "utf-8");
|
|
1556
1503
|
if (fileContentsEqual(filePath, currentContent, newContent)) {
|
|
1557
1504
|
changes.push({
|
|
1558
1505
|
path: filePath,
|
|
@@ -1630,7 +1577,7 @@ function detectLibraryPackage(pkg) {
|
|
|
1630
1577
|
return pkg.exports != null || pkg.main?.includes("dist") === true || pkg.module?.includes("dist") === true || Array.isArray(pkg.files) && pkg.files.includes("dist");
|
|
1631
1578
|
}
|
|
1632
1579
|
function getPackageManagerForScripts(config, pkg) {
|
|
1633
|
-
const packageManager = pkg.packageManager?.
|
|
1580
|
+
const packageManager = workspace.parsePackageManagerSpec(pkg.packageManager)?.name ?? config.packageManager;
|
|
1634
1581
|
return isPackageManagerName(packageManager) ? packageManager : "pnpm";
|
|
1635
1582
|
}
|
|
1636
1583
|
function getSinglePackageToolScripts(config) {
|
|
@@ -1660,6 +1607,35 @@ function scriptsEqual(left, right) {
|
|
|
1660
1607
|
if (leftEntries.length !== Object.keys(right).length) return false;
|
|
1661
1608
|
return leftEntries.every(([key, value]) => right[key] === value);
|
|
1662
1609
|
}
|
|
1610
|
+
function packageManagerFieldsEqual(pkg, packageManagerSpec, targetNodeVersion) {
|
|
1611
|
+
if (packageManagerSpec == null || packageManagerSpec.version == null) {
|
|
1612
|
+
return targetNodeVersion == null || pkg.engines?.node === `>=${targetNodeVersion}`;
|
|
1613
|
+
}
|
|
1614
|
+
const majorVersion = workspace.getSemverMajorString(packageManagerSpec.version);
|
|
1615
|
+
return pkg.packageManager === workspace.formatPackageManager(packageManagerSpec) && pkg.engines?.[packageManagerSpec.name] === `>=${majorVersion}.0.0` && (targetNodeVersion == null || pkg.engines?.node === `>=${targetNodeVersion}`);
|
|
1616
|
+
}
|
|
1617
|
+
function applyPackageManagerFields(pkg, packageManagerSpec, targetNodeVersion) {
|
|
1618
|
+
if (packageManagerSpec == null || packageManagerSpec.version == null) {
|
|
1619
|
+
if (targetNodeVersion == null) return pkg;
|
|
1620
|
+
return {
|
|
1621
|
+
...pkg,
|
|
1622
|
+
engines: {
|
|
1623
|
+
...pkg.engines,
|
|
1624
|
+
node: `>=${targetNodeVersion}`
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
const majorVersion = workspace.getSemverMajorString(packageManagerSpec.version);
|
|
1629
|
+
return {
|
|
1630
|
+
...pkg,
|
|
1631
|
+
packageManager: workspace.formatPackageManager(packageManagerSpec),
|
|
1632
|
+
engines: {
|
|
1633
|
+
...pkg.engines,
|
|
1634
|
+
[packageManagerSpec.name]: `>=${majorVersion}.0.0`,
|
|
1635
|
+
...targetNodeVersion == null ? {} : { node: `>=${targetNodeVersion}` }
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1663
1639
|
async function getExpectedPackageScripts(root, config, pkg) {
|
|
1664
1640
|
if (config.isMonorepo) {
|
|
1665
1641
|
return workspace.packageJsonScripts.monorepoRoot(config.linter, config.formatter);
|
|
@@ -1688,6 +1664,9 @@ async function getExpectedPackageDevDependencies(root, config, pkg) {
|
|
|
1688
1664
|
addMissingDevDependency(pkg, nextDevDependencies, "@babel/core");
|
|
1689
1665
|
addMissingDevDependency(pkg, nextDevDependencies, "@rolldown/plugin-babel");
|
|
1690
1666
|
addMissingDevDependency(pkg, nextDevDependencies, "babel-plugin-react-compiler");
|
|
1667
|
+
if (config.linter === "oxlint") {
|
|
1668
|
+
addMissingDevDependency(pkg, nextDevDependencies, "eslint-plugin-react-hooks");
|
|
1669
|
+
}
|
|
1691
1670
|
if (await detectTypeScriptPackage(root, pkg)) {
|
|
1692
1671
|
addMissingDevDependency(pkg, nextDevDependencies, "@types/babel__core");
|
|
1693
1672
|
}
|
|
@@ -1698,7 +1677,7 @@ async function getPackageJsonScriptUpdates(root, config) {
|
|
|
1698
1677
|
const packageJsonPath = path.join(root, "package.json");
|
|
1699
1678
|
let currentContent;
|
|
1700
1679
|
try {
|
|
1701
|
-
currentContent = await promises.readFile(packageJsonPath, "utf-8");
|
|
1680
|
+
currentContent = await promises$1.readFile(packageJsonPath, "utf-8");
|
|
1702
1681
|
} catch {
|
|
1703
1682
|
return [];
|
|
1704
1683
|
}
|
|
@@ -1708,7 +1687,9 @@ async function getPackageJsonScriptUpdates(root, config) {
|
|
|
1708
1687
|
const nextScripts = workspace.mergePackageJsonScripts(currentScripts, expectedScripts);
|
|
1709
1688
|
const currentDevDependencies = pkg.devDependencies ?? {};
|
|
1710
1689
|
const nextDevDependencies = await getExpectedPackageDevDependencies(root, config, pkg);
|
|
1711
|
-
|
|
1690
|
+
const targetPackageManagerSpec = config.targetPackageManagerSpec;
|
|
1691
|
+
const targetNodeVersion = config.targetNodeVersion;
|
|
1692
|
+
if (scriptsEqual(currentScripts, nextScripts) && scriptsEqual(currentDevDependencies, nextDevDependencies) && packageManagerFieldsEqual(pkg, targetPackageManagerSpec, targetNodeVersion)) {
|
|
1712
1693
|
return [
|
|
1713
1694
|
{
|
|
1714
1695
|
path: "package.json",
|
|
@@ -1718,10 +1699,14 @@ async function getPackageJsonScriptUpdates(root, config) {
|
|
|
1718
1699
|
}
|
|
1719
1700
|
];
|
|
1720
1701
|
}
|
|
1721
|
-
const nextPackageJson =
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1702
|
+
const nextPackageJson = applyPackageManagerFields(
|
|
1703
|
+
{
|
|
1704
|
+
...pkg,
|
|
1705
|
+
scripts: nextScripts
|
|
1706
|
+
},
|
|
1707
|
+
targetPackageManagerSpec,
|
|
1708
|
+
targetNodeVersion
|
|
1709
|
+
);
|
|
1725
1710
|
if (Object.keys(nextDevDependencies).length > 0 || pkg.devDependencies != null) {
|
|
1726
1711
|
nextPackageJson.devDependencies = nextDevDependencies;
|
|
1727
1712
|
}
|
|
@@ -1736,12 +1721,49 @@ async function getPackageJsonScriptUpdates(root, config) {
|
|
|
1736
1721
|
}
|
|
1737
1722
|
];
|
|
1738
1723
|
}
|
|
1724
|
+
async function getPackageManagerConfigUpdates(root, config) {
|
|
1725
|
+
if (config.targetPackageManagerSpec == null && config.targetNodeVersion == null) return [];
|
|
1726
|
+
const packageJsonPath = path.join(root, "package.json");
|
|
1727
|
+
let currentContent;
|
|
1728
|
+
try {
|
|
1729
|
+
currentContent = await promises$1.readFile(packageJsonPath, "utf-8");
|
|
1730
|
+
} catch {
|
|
1731
|
+
return [];
|
|
1732
|
+
}
|
|
1733
|
+
const pkg = JSON.parse(currentContent);
|
|
1734
|
+
if (packageManagerFieldsEqual(pkg, config.targetPackageManagerSpec, config.targetNodeVersion)) {
|
|
1735
|
+
return [
|
|
1736
|
+
{
|
|
1737
|
+
path: "package.json",
|
|
1738
|
+
status: "unchanged",
|
|
1739
|
+
currentContent,
|
|
1740
|
+
newContent: currentContent
|
|
1741
|
+
}
|
|
1742
|
+
];
|
|
1743
|
+
}
|
|
1744
|
+
const nextPackageJson = applyPackageManagerFields(
|
|
1745
|
+
pkg,
|
|
1746
|
+
config.targetPackageManagerSpec,
|
|
1747
|
+
config.targetNodeVersion
|
|
1748
|
+
);
|
|
1749
|
+
return [
|
|
1750
|
+
{
|
|
1751
|
+
path: "package.json",
|
|
1752
|
+
status: "modified",
|
|
1753
|
+
currentContent,
|
|
1754
|
+
newContent: `${JSON.stringify(nextPackageJson, null, 2)}
|
|
1755
|
+
`
|
|
1756
|
+
}
|
|
1757
|
+
];
|
|
1758
|
+
}
|
|
1739
1759
|
function planSinglePackageOxlintConfig(config) {
|
|
1740
1760
|
if (config.linter !== "oxlint" || config.isMonorepo) return void 0;
|
|
1741
1761
|
const isStealth = (config.configStrategy ?? "stealth") === "stealth";
|
|
1742
1762
|
const path = isStealth ? ".config/oxlint.json" : "oxlint.json";
|
|
1743
1763
|
const oxlintConfig = workspace.renderOxlintConfig({
|
|
1744
1764
|
schemaPath: isStealth ? "../node_modules/oxlint/configuration_schema.json" : "./node_modules/oxlint/configuration_schema.json",
|
|
1765
|
+
react: config.viteTemplate === "react" || config.viteTemplate === "r3f",
|
|
1766
|
+
reactCompiler: config.viteTemplate === "react",
|
|
1745
1767
|
typescript: true
|
|
1746
1768
|
});
|
|
1747
1769
|
return {
|
|
@@ -1757,7 +1779,7 @@ async function getOxlintConfigReplacementUpdates(root, config) {
|
|
|
1757
1779
|
const fullPath = path.join(root, expected.path);
|
|
1758
1780
|
let currentContent;
|
|
1759
1781
|
try {
|
|
1760
|
-
currentContent = await promises.readFile(fullPath, "utf-8");
|
|
1782
|
+
currentContent = await promises$1.readFile(fullPath, "utf-8");
|
|
1761
1783
|
} catch {
|
|
1762
1784
|
return [expected];
|
|
1763
1785
|
}
|
|
@@ -1779,26 +1801,118 @@ async function getOxlintConfigReplacementUpdates(root, config) {
|
|
|
1779
1801
|
}
|
|
1780
1802
|
];
|
|
1781
1803
|
}
|
|
1782
|
-
|
|
1804
|
+
function extractBuildDependencies(content) {
|
|
1805
|
+
const buildDependencies = {};
|
|
1806
|
+
let section;
|
|
1807
|
+
for (const line of content.split("\n")) {
|
|
1808
|
+
const trimmed = line.trim();
|
|
1809
|
+
if (trimmed === "onlyBuiltDependencies:") {
|
|
1810
|
+
section = "onlyBuiltDependencies";
|
|
1811
|
+
continue;
|
|
1812
|
+
}
|
|
1813
|
+
if (trimmed === "allowBuilds:") {
|
|
1814
|
+
section = "allowBuilds";
|
|
1815
|
+
continue;
|
|
1816
|
+
}
|
|
1817
|
+
if (section != null && trimmed && !line.startsWith(" ") && !line.startsWith(" ")) {
|
|
1818
|
+
section = void 0;
|
|
1819
|
+
}
|
|
1820
|
+
if (section === "onlyBuiltDependencies" && trimmed.startsWith("-")) {
|
|
1821
|
+
const dependency = trimmed.slice(1).trim().replace(/^["']|["']$/g, "");
|
|
1822
|
+
if (dependency.length > 0) {
|
|
1823
|
+
buildDependencies[dependency] = true;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
if (section === "allowBuilds") {
|
|
1827
|
+
const match = trimmed.match(/^([^:]+):\s*(true|false)$/);
|
|
1828
|
+
if (match == null) continue;
|
|
1829
|
+
const dependency = match[1].trim().replace(/^["']|["']$/g, "");
|
|
1830
|
+
if (dependency.length > 0) {
|
|
1831
|
+
buildDependencies[dependency] = match[2] === "true";
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
return buildDependencies;
|
|
1836
|
+
}
|
|
1837
|
+
function withDefaultBuildDependencies(buildDependencies) {
|
|
1838
|
+
return Object.keys(buildDependencies).length > 0 ? buildDependencies : { esbuild: true };
|
|
1839
|
+
}
|
|
1840
|
+
function isPnpmWorkspaceManagedScalarKey(trimmed) {
|
|
1841
|
+
return trimmed.startsWith("manage-package-manager-versions:") || trimmed.startsWith("pmOnFail:");
|
|
1842
|
+
}
|
|
1843
|
+
function isPnpmWorkspaceManagedBlockKey(trimmed) {
|
|
1844
|
+
return trimmed === "onlyBuiltDependencies:" || trimmed === "allowBuilds:";
|
|
1845
|
+
}
|
|
1846
|
+
function isIndentedWorkspaceLine(line) {
|
|
1847
|
+
return line.startsWith(" ") || line.startsWith(" ");
|
|
1848
|
+
}
|
|
1849
|
+
function removePnpmWorkspaceManagedKeys(content) {
|
|
1850
|
+
const sourceLines = content.split("\n");
|
|
1851
|
+
const lines = [];
|
|
1852
|
+
let insertionIndex = 0;
|
|
1853
|
+
let foundManagedKey = false;
|
|
1854
|
+
for (let index = 0; index < sourceLines.length; index++) {
|
|
1855
|
+
const line = sourceLines[index];
|
|
1856
|
+
const trimmed = line.trim();
|
|
1857
|
+
if (isPnpmWorkspaceManagedScalarKey(trimmed)) {
|
|
1858
|
+
if (!foundManagedKey) {
|
|
1859
|
+
insertionIndex = lines.length;
|
|
1860
|
+
foundManagedKey = true;
|
|
1861
|
+
}
|
|
1862
|
+
continue;
|
|
1863
|
+
}
|
|
1864
|
+
if (isPnpmWorkspaceManagedBlockKey(trimmed)) {
|
|
1865
|
+
if (!foundManagedKey) {
|
|
1866
|
+
insertionIndex = lines.length;
|
|
1867
|
+
foundManagedKey = true;
|
|
1868
|
+
}
|
|
1869
|
+
while (index + 1 < sourceLines.length) {
|
|
1870
|
+
const nextLine = sourceLines[index + 1];
|
|
1871
|
+
const nextTrimmed = nextLine.trim();
|
|
1872
|
+
if (nextTrimmed !== "" && !isIndentedWorkspaceLine(nextLine)) break;
|
|
1873
|
+
index++;
|
|
1874
|
+
}
|
|
1875
|
+
continue;
|
|
1876
|
+
}
|
|
1877
|
+
lines.push(line);
|
|
1878
|
+
}
|
|
1879
|
+
return {
|
|
1880
|
+
content: lines.join("\n").trim(),
|
|
1881
|
+
insertionIndex
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
function patchPnpmWorkspaceManagedKeys(content, profile, buildDependencies) {
|
|
1885
|
+
const managedContent = workspace.renderPnpmWorkspaceConfig({
|
|
1886
|
+
profile,
|
|
1887
|
+
manageVersions: true,
|
|
1888
|
+
buildDependencies
|
|
1889
|
+
});
|
|
1890
|
+
const existing = removePnpmWorkspaceManagedKeys(content);
|
|
1891
|
+
const preservedLines = existing.content.length > 0 ? existing.content.split("\n") : [];
|
|
1892
|
+
const insertionIndex = Math.min(existing.insertionIndex, preservedLines.length);
|
|
1893
|
+
const managedLines = managedContent.split("\n");
|
|
1894
|
+
preservedLines.splice(insertionIndex, 0, ...managedLines);
|
|
1895
|
+
return preservedLines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1896
|
+
}
|
|
1897
|
+
async function getWorkspaceConfigUpdates(root, config) {
|
|
1783
1898
|
const workspacePath = path.join(root, "pnpm-workspace.yaml");
|
|
1784
1899
|
const changes = [];
|
|
1900
|
+
const packageManagerSpec = config?.targetPackageManagerSpec ?? config?.packageManagerSpec ?? { name: "pnpm" };
|
|
1901
|
+
const profile = workspace.getPackageManagerProfile(packageManagerSpec);
|
|
1902
|
+
const defaultPackages = [".config/*", "apps/*", "packages/*"];
|
|
1785
1903
|
let currentContent = "";
|
|
1786
1904
|
let exists = false;
|
|
1787
1905
|
try {
|
|
1788
|
-
currentContent = await promises.readFile(workspacePath, "utf-8");
|
|
1906
|
+
currentContent = await promises$1.readFile(workspacePath, "utf-8");
|
|
1789
1907
|
exists = true;
|
|
1790
1908
|
} catch {
|
|
1791
1909
|
}
|
|
1792
1910
|
if (!exists) {
|
|
1793
|
-
const newContent =
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
- 'packages/*'
|
|
1799
|
-
|
|
1800
|
-
onlyBuiltDependencies:
|
|
1801
|
-
- esbuild
|
|
1911
|
+
const newContent = `${workspace.renderPnpmWorkspaceConfig({
|
|
1912
|
+
profile,
|
|
1913
|
+
manageVersions: true,
|
|
1914
|
+
packages: defaultPackages
|
|
1915
|
+
})}
|
|
1802
1916
|
`;
|
|
1803
1917
|
changes.push({
|
|
1804
1918
|
path: "pnpm-workspace.yaml",
|
|
@@ -1807,32 +1921,14 @@ onlyBuiltDependencies:
|
|
|
1807
1921
|
});
|
|
1808
1922
|
return changes;
|
|
1809
1923
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
needsUpdate = true;
|
|
1817
|
-
}
|
|
1818
|
-
if (!currentContent.includes("onlyBuiltDependencies")) {
|
|
1819
|
-
updatedContent = `${updatedContent.trimEnd()}
|
|
1820
|
-
|
|
1821
|
-
onlyBuiltDependencies:
|
|
1822
|
-
- esbuild
|
|
1924
|
+
const buildDependencies = withDefaultBuildDependencies(extractBuildDependencies(currentContent));
|
|
1925
|
+
const updatedContent = `${patchPnpmWorkspaceManagedKeys(
|
|
1926
|
+
currentContent,
|
|
1927
|
+
profile,
|
|
1928
|
+
buildDependencies
|
|
1929
|
+
)}
|
|
1823
1930
|
`;
|
|
1824
|
-
|
|
1825
|
-
}
|
|
1826
|
-
if (!currentContent.includes(".config/*")) {
|
|
1827
|
-
const lines = updatedContent.split("\n");
|
|
1828
|
-
const packagesIndex = lines.findIndex((line) => line.trim().startsWith("packages:"));
|
|
1829
|
-
if (packagesIndex !== -1) {
|
|
1830
|
-
lines.splice(packagesIndex + 1, 0, " - '.config/*'");
|
|
1831
|
-
updatedContent = lines.join("\n");
|
|
1832
|
-
needsUpdate = true;
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
if (needsUpdate) {
|
|
1931
|
+
if (updatedContent !== currentContent) {
|
|
1836
1932
|
changes.push({
|
|
1837
1933
|
path: "pnpm-workspace.yaml",
|
|
1838
1934
|
status: "modified",
|
|
@@ -1853,8 +1949,8 @@ async function applyUpdates(changes, root) {
|
|
|
1853
1949
|
for (const change of changes) {
|
|
1854
1950
|
if (change.status === "unchanged") continue;
|
|
1855
1951
|
const fullPath = path.join(root, change.path);
|
|
1856
|
-
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
1857
|
-
await promises.writeFile(fullPath, change.newContent);
|
|
1952
|
+
await promises$1.mkdir(path.dirname(fullPath), { recursive: true });
|
|
1953
|
+
await promises$1.writeFile(fullPath, change.newContent);
|
|
1858
1954
|
}
|
|
1859
1955
|
}
|
|
1860
1956
|
function formatFileChange(change) {
|
|
@@ -1930,6 +2026,96 @@ function orderUpdateCategories(categories) {
|
|
|
1930
2026
|
(left, right) => getCategoryOrder(left.category) - getCategoryOrder(right.category)
|
|
1931
2027
|
);
|
|
1932
2028
|
}
|
|
2029
|
+
function isPnpmMajorMigration(config) {
|
|
2030
|
+
const currentPackageManager = config.packageManagerSpec;
|
|
2031
|
+
const targetPackageManager = config.targetPackageManagerSpec;
|
|
2032
|
+
if (currentPackageManager?.name !== "pnpm" || targetPackageManager?.name !== "pnpm") {
|
|
2033
|
+
return false;
|
|
2034
|
+
}
|
|
2035
|
+
const currentMajor = workspace.getSemverMajor(currentPackageManager.version);
|
|
2036
|
+
const targetMajor = workspace.getSemverMajor(targetPackageManager.version);
|
|
2037
|
+
return currentMajor != null && targetMajor != null && currentMajor !== targetMajor;
|
|
2038
|
+
}
|
|
2039
|
+
function getPackageUpdateCommand(config) {
|
|
2040
|
+
const packageManagerName = config.packageManager.split("@")[0] ?? config.packageManager;
|
|
2041
|
+
if (packageManagerName === "pnpm") {
|
|
2042
|
+
if (isPnpmMajorMigration(config)) {
|
|
2043
|
+
return {
|
|
2044
|
+
command: "pnpm",
|
|
2045
|
+
args: ["install"],
|
|
2046
|
+
displayCommand: "pnpm install",
|
|
2047
|
+
promptMessage: "Install dependencies?",
|
|
2048
|
+
successMessage: "Dependencies installed",
|
|
2049
|
+
failureLabel: "Dependency install"
|
|
2050
|
+
};
|
|
2051
|
+
}
|
|
2052
|
+
return {
|
|
2053
|
+
command: "pnpm",
|
|
2054
|
+
args: ["update"],
|
|
2055
|
+
displayCommand: "pnpm update",
|
|
2056
|
+
promptMessage: "Update packages?",
|
|
2057
|
+
successMessage: "Packages updated",
|
|
2058
|
+
failureLabel: "Package update"
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
if (packageManagerName === "npm") {
|
|
2062
|
+
return {
|
|
2063
|
+
command: "npm",
|
|
2064
|
+
args: ["update"],
|
|
2065
|
+
displayCommand: "npm update",
|
|
2066
|
+
promptMessage: "Update packages?",
|
|
2067
|
+
successMessage: "Packages updated",
|
|
2068
|
+
failureLabel: "Package update"
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
return void 0;
|
|
2072
|
+
}
|
|
2073
|
+
async function runPackageUpdate(projectRoot, updateCommand) {
|
|
2074
|
+
await new Promise((resolve, reject) => {
|
|
2075
|
+
const child = node_child_process.spawn(updateCommand.command, updateCommand.args, {
|
|
2076
|
+
cwd: projectRoot,
|
|
2077
|
+
shell: process.platform === "win32",
|
|
2078
|
+
stdio: "inherit"
|
|
2079
|
+
});
|
|
2080
|
+
child.on("error", reject);
|
|
2081
|
+
child.on("exit", (code) => {
|
|
2082
|
+
if (code === 0) {
|
|
2083
|
+
resolve();
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
reject(new Error(`${updateCommand.displayCommand} exited with code ${code ?? "unknown"}`));
|
|
2087
|
+
});
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
async function promptForPackageUpdate(projectRoot, config, options) {
|
|
2091
|
+
const updateCommand = getPackageUpdateCommand(config);
|
|
2092
|
+
if (!updateCommand) {
|
|
2093
|
+
console.log(color__default.dim(` Package updates are not supported for ${config.packageManager}`));
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
const shouldUpdatePackages = options.yes || await p__namespace.confirm({
|
|
2097
|
+
message: updateCommand.promptMessage,
|
|
2098
|
+
initialValue: true
|
|
2099
|
+
});
|
|
2100
|
+
if (p__namespace.isCancel(shouldUpdatePackages)) {
|
|
2101
|
+
p__namespace.cancel("Operation cancelled.");
|
|
2102
|
+
process.exit(0);
|
|
2103
|
+
}
|
|
2104
|
+
if (!shouldUpdatePackages) {
|
|
2105
|
+
console.log(color__default.dim(" Skipped package updates"));
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2108
|
+
console.log();
|
|
2109
|
+
console.log(color__default.cyan(`Running ${updateCommand.displayCommand}...`));
|
|
2110
|
+
try {
|
|
2111
|
+
await runPackageUpdate(projectRoot, updateCommand);
|
|
2112
|
+
console.log(color__default.green("\u2713") + ` ${updateCommand.successMessage}`);
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2115
|
+
console.log(color__default.red("\u2717") + ` ${updateCommand.failureLabel} failed: ${message}`);
|
|
2116
|
+
process.exit(1);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
1933
2119
|
async function collectUpdateCategories(projectRoot, config, isMonorepo) {
|
|
1934
2120
|
const expected = await planExpectedFiles(config);
|
|
1935
2121
|
const categories = await compareWithDisk(expected, projectRoot);
|
|
@@ -1953,7 +2139,7 @@ async function collectUpdateCategories(projectRoot, config, isMonorepo) {
|
|
|
1953
2139
|
});
|
|
1954
2140
|
}
|
|
1955
2141
|
if (isMonorepo) {
|
|
1956
|
-
const workspaceConfigChanges = await getWorkspaceConfigUpdates(projectRoot);
|
|
2142
|
+
const workspaceConfigChanges = await getWorkspaceConfigUpdates(projectRoot, config);
|
|
1957
2143
|
if (workspaceConfigChanges.length > 0) {
|
|
1958
2144
|
allCategories.push({
|
|
1959
2145
|
category: "workspace-config",
|
|
@@ -1965,6 +2151,110 @@ async function collectUpdateCategories(projectRoot, config, isMonorepo) {
|
|
|
1965
2151
|
}
|
|
1966
2152
|
return orderUpdateCategories(allCategories);
|
|
1967
2153
|
}
|
|
2154
|
+
async function resolveTargetPackageManagerSpec(options, config) {
|
|
2155
|
+
if (options.packageManager == null) return void 0;
|
|
2156
|
+
const packageManager = workspace.parsePackageManagerSpec(options.packageManager);
|
|
2157
|
+
if (packageManager == null) {
|
|
2158
|
+
console.log(color__default.red("\u2717") + ` Unsupported package manager: ${options.packageManager}`);
|
|
2159
|
+
process.exit(1);
|
|
2160
|
+
}
|
|
2161
|
+
return workspace.resolvePackageManager({
|
|
2162
|
+
name: config.name,
|
|
2163
|
+
packageManager
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
2166
|
+
function getPackageManagerMajorUpdateTarget(currentPackageManager, latestPackageManager) {
|
|
2167
|
+
if (currentPackageManager?.version == null) return void 0;
|
|
2168
|
+
const currentMajor = workspace.getSemverMajor(currentPackageManager.version);
|
|
2169
|
+
const latestMajor = workspace.getSemverMajor(latestPackageManager.version);
|
|
2170
|
+
if (currentMajor == null || latestMajor == null || latestMajor <= currentMajor) {
|
|
2171
|
+
return void 0;
|
|
2172
|
+
}
|
|
2173
|
+
return latestPackageManager;
|
|
2174
|
+
}
|
|
2175
|
+
function getRequiredNodeUpdateTarget(currentNodeVersion, requiredNodeVersion) {
|
|
2176
|
+
if (requiredNodeVersion == null) return void 0;
|
|
2177
|
+
if (currentNodeVersion == null) return requiredNodeVersion;
|
|
2178
|
+
return workspace.compareNumericSemver(currentNodeVersion, requiredNodeVersion) < 0 ? requiredNodeVersion : void 0;
|
|
2179
|
+
}
|
|
2180
|
+
function formatPackageManagerMajor(packageManager) {
|
|
2181
|
+
const major = workspace.getSemverMajor(packageManager.version);
|
|
2182
|
+
return major == null ? packageManager.name : `${packageManager.name}@${major}`;
|
|
2183
|
+
}
|
|
2184
|
+
async function promptForNodeRequirementUpdate(options, config, targetPackageManagerSpec) {
|
|
2185
|
+
if (targetPackageManagerSpec == null) return void 0;
|
|
2186
|
+
const profile = workspace.getPackageManagerProfile(targetPackageManagerSpec);
|
|
2187
|
+
const requiredNodeVersion = profile.requirements.node;
|
|
2188
|
+
const currentNodeVersion = config.engine?.version;
|
|
2189
|
+
const targetNodeVersion = getRequiredNodeUpdateTarget(currentNodeVersion, requiredNodeVersion);
|
|
2190
|
+
if (targetNodeVersion == null) return void 0;
|
|
2191
|
+
const currentNodeLabel = currentNodeVersion == null ? "not set" : `>=${currentNodeVersion}`;
|
|
2192
|
+
p__namespace.log.warn(
|
|
2193
|
+
`${workspace.formatPackageManager(targetPackageManagerSpec)} requires Node >=${targetNodeVersion}; current engines.node is ${currentNodeLabel}.`
|
|
2194
|
+
);
|
|
2195
|
+
const shouldUpdate = options.yes || await p__namespace.confirm({
|
|
2196
|
+
message: `Update engines.node to >=${targetNodeVersion} too?`,
|
|
2197
|
+
initialValue: true
|
|
2198
|
+
});
|
|
2199
|
+
if (p__namespace.isCancel(shouldUpdate)) {
|
|
2200
|
+
p__namespace.cancel("Operation cancelled.");
|
|
2201
|
+
process.exit(0);
|
|
2202
|
+
}
|
|
2203
|
+
return shouldUpdate ? targetNodeVersion : void 0;
|
|
2204
|
+
}
|
|
2205
|
+
async function promptForPackageManagerMajorUpdate(options, config) {
|
|
2206
|
+
if (options.packageManager != null || config.packageManagerSpec == null) return void 0;
|
|
2207
|
+
const currentPackageManager = config.packageManagerSpec;
|
|
2208
|
+
if (currentPackageManager.version == null) return void 0;
|
|
2209
|
+
const latestPackageManager = await workspace.resolvePackageManager({
|
|
2210
|
+
name: config.name,
|
|
2211
|
+
packageManager: { name: currentPackageManager.name }
|
|
2212
|
+
});
|
|
2213
|
+
const updateTarget = getPackageManagerMajorUpdateTarget(
|
|
2214
|
+
currentPackageManager,
|
|
2215
|
+
latestPackageManager
|
|
2216
|
+
);
|
|
2217
|
+
if (updateTarget == null) return void 0;
|
|
2218
|
+
const shouldUpdate = options.yes || await p__namespace.confirm({
|
|
2219
|
+
message: `Update ${currentPackageManager.name} from ${formatPackageManagerMajor(
|
|
2220
|
+
currentPackageManager
|
|
2221
|
+
)} to ${formatPackageManagerMajor(latestPackageManager)}?`,
|
|
2222
|
+
initialValue: true
|
|
2223
|
+
});
|
|
2224
|
+
if (p__namespace.isCancel(shouldUpdate)) {
|
|
2225
|
+
p__namespace.cancel("Operation cancelled.");
|
|
2226
|
+
process.exit(0);
|
|
2227
|
+
}
|
|
2228
|
+
return shouldUpdate ? updateTarget : void 0;
|
|
2229
|
+
}
|
|
2230
|
+
async function applyPackageManagerMigration(projectRoot, isMonorepo, options, detectedConfig) {
|
|
2231
|
+
const targetPackageManagerSpec = await resolveTargetPackageManagerSpec(options, detectedConfig) ?? await promptForPackageManagerMajorUpdate(options, detectedConfig);
|
|
2232
|
+
if (targetPackageManagerSpec == null) return detectedConfig;
|
|
2233
|
+
const targetNodeVersion = await promptForNodeRequirementUpdate(
|
|
2234
|
+
options,
|
|
2235
|
+
detectedConfig,
|
|
2236
|
+
targetPackageManagerSpec
|
|
2237
|
+
);
|
|
2238
|
+
const migrationConfig = {
|
|
2239
|
+
...detectedConfig,
|
|
2240
|
+
packageManager: targetPackageManagerSpec.name,
|
|
2241
|
+
targetPackageManagerSpec,
|
|
2242
|
+
targetNodeVersion
|
|
2243
|
+
};
|
|
2244
|
+
const changes = [
|
|
2245
|
+
...await getPackageManagerConfigUpdates(projectRoot, migrationConfig),
|
|
2246
|
+
...isMonorepo || targetPackageManagerSpec.name === "pnpm" ? await getWorkspaceConfigUpdates(projectRoot, migrationConfig) : []
|
|
2247
|
+
].filter((change) => change.status === "added" || change.status === "modified");
|
|
2248
|
+
if (changes.length === 0) return migrationConfig;
|
|
2249
|
+
console.log();
|
|
2250
|
+
console.log(color__default.cyan("Package Manager:"));
|
|
2251
|
+
for (const change of changes) {
|
|
2252
|
+
console.log(formatFileChange(change));
|
|
2253
|
+
}
|
|
2254
|
+
await applyUpdates(changes, projectRoot);
|
|
2255
|
+
console.log(color__default.green("\u2713") + ` Package Manager: updated ${changes.length}`);
|
|
2256
|
+
return migrationConfig;
|
|
2257
|
+
}
|
|
1968
2258
|
async function processUpdateCategory(category, projectRoot, options) {
|
|
1969
2259
|
const newChanges = category.changes.filter((change) => change.status === "added");
|
|
1970
2260
|
const modifiedChanges = category.changes.filter((change) => change.status === "modified");
|
|
@@ -2004,11 +2294,8 @@ async function processUpdateCategory(category, projectRoot, options) {
|
|
|
2004
2294
|
if (addedCount > 0) parts.push(`added ${addedCount}`);
|
|
2005
2295
|
if (updatedFilesCount > 0) parts.push(`updated ${updatedFilesCount}`);
|
|
2006
2296
|
console.log(color__default.green("\u2713") + ` ${category.label}: ${parts.join(", ")}`);
|
|
2007
|
-
console.log();
|
|
2008
2297
|
return "updated";
|
|
2009
2298
|
}
|
|
2010
|
-
console.log(color__default.dim(` Skipped ${category.label}`));
|
|
2011
|
-
console.log();
|
|
2012
2299
|
return "skipped";
|
|
2013
2300
|
}
|
|
2014
2301
|
async function handleUpdateCommand(options, handleFixCommand) {
|
|
@@ -2021,7 +2308,7 @@ async function handleUpdateCommand(options, handleFixCommand) {
|
|
|
2021
2308
|
}
|
|
2022
2309
|
const isMonorepo = monorepoRoot != null;
|
|
2023
2310
|
if (isMonorepo) {
|
|
2024
|
-
const { valid, errors } = await validateWorkspace(projectRoot);
|
|
2311
|
+
const { valid, errors } = await workspace.validateWorkspace(projectRoot);
|
|
2025
2312
|
if (!valid) {
|
|
2026
2313
|
console.log(color__default.yellow("!") + " Workspace has issues:");
|
|
2027
2314
|
for (const error of errors) {
|
|
@@ -2074,6 +2361,8 @@ async function handleUpdateCommand(options, handleFixCommand) {
|
|
|
2074
2361
|
console.log(color__default.dim(` Skipped ${skippedCount}`));
|
|
2075
2362
|
}
|
|
2076
2363
|
}
|
|
2364
|
+
const finalConfig = await applyPackageManagerMigration(projectRoot, isMonorepo, options, config);
|
|
2365
|
+
await promptForPackageUpdate(projectRoot, finalConfig, options);
|
|
2077
2366
|
process.exit(0);
|
|
2078
2367
|
}
|
|
2079
2368
|
|
|
@@ -2091,9 +2380,10 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
2091
2380
|
message: "Package name?",
|
|
2092
2381
|
initialValue: `@${scope}/`,
|
|
2093
2382
|
validate: (value) => {
|
|
2094
|
-
const
|
|
2383
|
+
const packageName = value ?? "";
|
|
2384
|
+
const validationError = workspace.validatePackageName(packageName);
|
|
2095
2385
|
if (validationError) return validationError;
|
|
2096
|
-
const dirName =
|
|
2386
|
+
const dirName = workspace.getPackageDirectoryName(packageName);
|
|
2097
2387
|
if (!dirName) return "Package name is required";
|
|
2098
2388
|
if (!hasCustomDirectories) {
|
|
2099
2389
|
const targetPath = node_path.join(monorepoRoot, defaultDir, dirName);
|
|
@@ -2110,7 +2400,7 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
2110
2400
|
return false;
|
|
2111
2401
|
}
|
|
2112
2402
|
const scopedName = packageNameInput;
|
|
2113
|
-
const shortName =
|
|
2403
|
+
const shortName = workspace.getPackageDirectoryName(scopedName);
|
|
2114
2404
|
const packageOptions = await promptForPackageOptions(scopedName, packageType, inheritedSettings);
|
|
2115
2405
|
let targetDir = defaultDir;
|
|
2116
2406
|
if (hasCustomDirectories && workspaceDirectories.length > 0) {
|
|
@@ -2191,10 +2481,11 @@ async function handleWorkspaceCommand(name, options, writeGeneratedFiles) {
|
|
|
2191
2481
|
const template = options.template ?? "vanilla";
|
|
2192
2482
|
const baseTemplate = workspace.getBaseTemplate(template);
|
|
2193
2483
|
const scopedName = name.startsWith("@") ? name : `@${scope}/${name}`;
|
|
2194
|
-
const
|
|
2484
|
+
const packageDirName = workspace.getPackageDirectoryName(name);
|
|
2485
|
+
const fullPackagePath = node_path.join(monorepoRoot, targetDir, packageDirName);
|
|
2195
2486
|
try {
|
|
2196
|
-
await promises
|
|
2197
|
-
console.error(color__default.red("Error:") + ` Directory ${targetDir}/${
|
|
2487
|
+
await promises.access(fullPackagePath, node_fs.constants.F_OK);
|
|
2488
|
+
console.error(color__default.red("Error:") + ` Directory ${targetDir}/${packageDirName} already exists`);
|
|
2198
2489
|
process.exit(1);
|
|
2199
2490
|
} catch {
|
|
2200
2491
|
}
|
|
@@ -2207,7 +2498,7 @@ async function handleWorkspaceCommand(name, options, writeGeneratedFiles) {
|
|
|
2207
2498
|
};
|
|
2208
2499
|
const pnpmManageVersions = inheritedSettings.pnpmManageVersions ?? true;
|
|
2209
2500
|
const isLibrary = projectType === "library";
|
|
2210
|
-
const relativePkgPath = node_path.join(targetDir,
|
|
2501
|
+
const relativePkgPath = node_path.join(targetDir, packageDirName);
|
|
2211
2502
|
const workspaceRoot = calculateWorkspaceRoot(relativePkgPath);
|
|
2212
2503
|
const projectOptions = {
|
|
2213
2504
|
name: scopedName,
|
|
@@ -2235,11 +2526,11 @@ async function handleWorkspaceCommand(name, options, writeGeneratedFiles) {
|
|
|
2235
2526
|
triplex: options.triplex ? {} : void 0
|
|
2236
2527
|
}
|
|
2237
2528
|
};
|
|
2238
|
-
console.log(color__default.cyan("Creating") + ` ${scopedName} in ${targetDir}/${
|
|
2529
|
+
console.log(color__default.cyan("Creating") + ` ${scopedName} in ${targetDir}/${packageDirName}...`);
|
|
2239
2530
|
try {
|
|
2240
2531
|
const { files } = await workspace.planProject(workspace.resolveProjectPlanInput(projectOptions));
|
|
2241
2532
|
await writeGeneratedFiles(fullPackagePath, files);
|
|
2242
|
-
console.log(color__default.green("\u2713") + ` Created ${scopedName} at ${targetDir}/${
|
|
2533
|
+
console.log(color__default.green("\u2713") + ` Created ${scopedName} at ${targetDir}/${packageDirName}`);
|
|
2243
2534
|
process.exit(0);
|
|
2244
2535
|
} catch (error) {
|
|
2245
2536
|
console.error(color__default.red("Error:") + " Failed to create package");
|
|
@@ -2310,13 +2601,13 @@ async function writeGeneratedFiles(basePath, files) {
|
|
|
2310
2601
|
const filePaths = Object.keys(files).sort();
|
|
2311
2602
|
for (const filePath of filePaths) {
|
|
2312
2603
|
const fullFilePath = node_path.join(basePath, filePath);
|
|
2313
|
-
await promises
|
|
2604
|
+
await promises.mkdir(node_path.dirname(fullFilePath), { recursive: true });
|
|
2314
2605
|
const file = files[filePath];
|
|
2315
2606
|
if (file.type === "text") {
|
|
2316
|
-
await promises
|
|
2607
|
+
await promises.writeFile(fullFilePath, file.content);
|
|
2317
2608
|
} else {
|
|
2318
2609
|
const response = await undici.fetch(file.url);
|
|
2319
|
-
await promises
|
|
2610
|
+
await promises.writeFile(fullFilePath, response.body);
|
|
2320
2611
|
}
|
|
2321
2612
|
}
|
|
2322
2613
|
}
|
|
@@ -2384,7 +2675,8 @@ async function handleSingleWorkspaceCreation(projectOptions, isNonInteractive) {
|
|
|
2384
2675
|
const defaultFallbackName = base === "vanilla" ? "vanilla-app" : base === "react" ? "react-app" : "react-three-app";
|
|
2385
2676
|
projectOptions.name ??= defaultFallbackName;
|
|
2386
2677
|
const packageManager = workspace.getPackageManagerName(projectOptions.packageManager);
|
|
2387
|
-
const
|
|
2678
|
+
const projectDirName = workspace.getPackageDirectoryName(projectOptions.name);
|
|
2679
|
+
const projectPath = node_path.join(node_process.cwd(), projectDirName);
|
|
2388
2680
|
const spinner = p__namespace.spinner();
|
|
2389
2681
|
spinner.start("Creating project...");
|
|
2390
2682
|
try {
|
|
@@ -2393,15 +2685,11 @@ async function handleSingleWorkspaceCreation(projectOptions, isNonInteractive) {
|
|
|
2393
2685
|
await writeGeneratedFiles(projectPath, files);
|
|
2394
2686
|
spinner.stop(color__default.green.inverse(" \u2713 Project created! "));
|
|
2395
2687
|
if (isNonInteractive) process.exit(0);
|
|
2396
|
-
const nextSteps = projectOptions.projectType === "library" ? [
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
`cd ${projectOptions.name}`,
|
|
2402
|
-
`${packageManager} install`,
|
|
2403
|
-
`${packageManager} run dev`
|
|
2404
|
-
].join("\n");
|
|
2688
|
+
const nextSteps = projectOptions.projectType === "library" ? [`cd ${projectDirName}`, `${packageManager} install`, `${packageManager} run build`].join(
|
|
2689
|
+
"\n"
|
|
2690
|
+
) : [`cd ${projectDirName}`, `${packageManager} install`, `${packageManager} run dev`].join(
|
|
2691
|
+
"\n"
|
|
2692
|
+
);
|
|
2405
2693
|
p__namespace.note(nextSteps, "Next steps");
|
|
2406
2694
|
p__namespace.outro(color__default.green("Happy coding! \u2728"));
|
|
2407
2695
|
} catch (error) {
|
|
@@ -2417,7 +2705,7 @@ async function main() {
|
|
|
2417
2705
|
).option(
|
|
2418
2706
|
"--template <type>",
|
|
2419
2707
|
"project template: vanilla, vanilla-js, react, react-js, r3f, r3f-js (default: vanilla)"
|
|
2420
|
-
).option("--linter <type>", "linter: eslint, oxlint, or biome (default: oxlint)").option("--formatter <type>", "formatter: prettier, oxfmt, or biome (default: prettier)").option("--drei", "add @react-three/drei (r3f only)").option("--handle", "add @react-three/handle (r3f only)").option("--leva", "add leva (r3f only)").option("--postprocessing", "add @react-three/postprocessing (r3f only)").option("--rapier", "add @react-three/rapier (r3f only)").option("--xr", "add @react-three/xr (r3f only)").option("--uikit", "add @react-three/uikit (r3f only)").option("--offscreen", "add @react-three/offscreen (r3f only)").option("--zustand", "add zustand (r3f only)").option("--koota", "add koota (r3f only)").option("--triplex", "set up triplex development environment (r3f only)").option("--viverse", "set up viverse deployment (r3f only)").option("--package-manager <manager>", "specify package manager (e.g. npm, yarn, pnpm)").option("--ide <ide>", "IDE files: vscode or none (default: vscode)").option(
|
|
2708
|
+
).option("--linter <type>", "linter: eslint, oxlint, or biome (default: oxlint)").option("--formatter <type>", "formatter: prettier, oxfmt, or biome (default: prettier)").option("--drei", "add @react-three/drei (r3f only)").option("--handle", "add @react-three/handle (r3f only)").option("--leva", "add leva (r3f only)").option("--postprocessing", "add @react-three/postprocessing (r3f only)").option("--rapier", "add @react-three/rapier (r3f only)").option("--xr", "add @react-three/xr (r3f only)").option("--uikit", "add @react-three/uikit (r3f only)").option("--offscreen", "add @react-three/offscreen (r3f only)").option("--zustand", "add zustand (r3f only)").option("--koota", "add koota (r3f only)").option("--triplex", "set up triplex development environment (r3f only)").option("--viverse", "set up viverse deployment (r3f only)").option("--package-manager <manager>", "specify package manager (e.g. npm, yarn, pnpm@11)").option("--ide <ide>", "IDE files: vscode or none (default: vscode)").option(
|
|
2421
2709
|
"--pnpm-manage-versions",
|
|
2422
2710
|
"enable manage-package-manager-versions in pnpm-workspace.yaml (default: true)"
|
|
2423
2711
|
).option(
|
|
@@ -2431,18 +2719,24 @@ async function main() {
|
|
|
2431
2719
|
process.chdir(options.path);
|
|
2432
2720
|
}
|
|
2433
2721
|
if (options.clearConfig) {
|
|
2434
|
-
clearConfig();
|
|
2722
|
+
workspace.clearConfig();
|
|
2435
2723
|
console.log("Configuration cleared.");
|
|
2436
2724
|
process.exit(0);
|
|
2437
2725
|
}
|
|
2438
2726
|
if (options.configPath) {
|
|
2439
|
-
console.log(getConfigPath());
|
|
2727
|
+
console.log(workspace.getConfigPath());
|
|
2440
2728
|
process.exit(0);
|
|
2441
2729
|
}
|
|
2442
2730
|
if (options.ide && !["vscode", "none"].includes(options.ide)) {
|
|
2443
2731
|
console.error(color__default.red("Error:") + ' --ide must be "vscode" or "none"');
|
|
2444
2732
|
process.exit(1);
|
|
2445
2733
|
}
|
|
2734
|
+
const packageManagerSpec = workspace.parsePackageManagerSpec(options.packageManager);
|
|
2735
|
+
if (options.packageManager && packageManagerSpec == null) {
|
|
2736
|
+
console.error(color__default.red("Error:") + " --package-manager must be npm, yarn, or pnpm");
|
|
2737
|
+
console.log(color__default.dim(" Version specs are allowed, e.g. pnpm@10 or pnpm@11"));
|
|
2738
|
+
process.exit(1);
|
|
2739
|
+
}
|
|
2446
2740
|
if (name?.startsWith("-")) {
|
|
2447
2741
|
switch (name) {
|
|
2448
2742
|
case "--version":
|
|
@@ -2454,11 +2748,11 @@ async function main() {
|
|
|
2454
2748
|
program.help();
|
|
2455
2749
|
break;
|
|
2456
2750
|
case "--clear-config":
|
|
2457
|
-
clearConfig();
|
|
2751
|
+
workspace.clearConfig();
|
|
2458
2752
|
console.log("Configuration cleared.");
|
|
2459
2753
|
process.exit(0);
|
|
2460
2754
|
case "--config-path":
|
|
2461
|
-
console.log(getConfigPath());
|
|
2755
|
+
console.log(workspace.getConfigPath());
|
|
2462
2756
|
process.exit(0);
|
|
2463
2757
|
case "--check":
|
|
2464
2758
|
await handleCheckCommand();
|
|
@@ -2528,7 +2822,7 @@ async function main() {
|
|
|
2528
2822
|
viverse: options.viverse ? {} : void 0,
|
|
2529
2823
|
triplex: options.triplex ? {} : void 0
|
|
2530
2824
|
},
|
|
2531
|
-
packageManager:
|
|
2825
|
+
packageManager: packageManagerSpec,
|
|
2532
2826
|
pnpmManageVersions: options.pnpmManageVersions,
|
|
2533
2827
|
engine: { name: "node", version: options.nodeVersion ?? "latest" }
|
|
2534
2828
|
};
|
|
@@ -2539,7 +2833,7 @@ async function main() {
|
|
|
2539
2833
|
bundler: options.bundler,
|
|
2540
2834
|
linter: options.linter,
|
|
2541
2835
|
formatter: options.formatter,
|
|
2542
|
-
packageManager:
|
|
2836
|
+
packageManager: packageManagerSpec,
|
|
2543
2837
|
ide: options.ide,
|
|
2544
2838
|
engine: options.nodeVersion ? { name: "node", version: options.nodeVersion } : void 0,
|
|
2545
2839
|
pnpmManageVersions: options.pnpmManageVersions,
|