create-krispya 0.6.0 → 0.8.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/README.md +13 -341
- package/dist/chunks/index.cjs +741 -451
- package/dist/chunks/index.mjs +731 -452
- package/dist/cli.cjs +374 -573
- package/dist/cli.mjs +364 -563
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +40 -34
- package/dist/index.d.mts +40 -34
- package/dist/index.d.ts +40 -34
- package/dist/index.mjs +2 -2
- package/package.json +32 -15
- package/LICENSE +0 -15
package/dist/cli.mjs
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from 'module';
|
|
3
|
-
import { cwd } from 'process';
|
|
4
|
-
import { join, dirname, resolve } from 'path';
|
|
5
|
-
import { access, constants, readFile, mkdir, writeFile, rm, readdir, unlink } from 'fs/promises';
|
|
6
|
-
import { constants as constants$1 } from 'fs';
|
|
7
|
-
import { Command } from 'commander';
|
|
8
2
|
import * as p from '@clack/prompts';
|
|
9
3
|
import color from 'chalk';
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { constants as constants$2 } from 'node:fs';
|
|
6
|
+
import { mkdir as mkdir$1, writeFile as writeFile$1, unlink, access as access$1, readFile as readFile$1 } from 'node:fs/promises';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { join as join$1, dirname as dirname$1, resolve } from 'node:path';
|
|
9
|
+
import { cwd } from 'node:process';
|
|
10
10
|
import { fetch } from 'undici';
|
|
11
11
|
import { spawn } from 'child_process';
|
|
12
|
-
import { g as
|
|
12
|
+
import { g as getEngineName, a as getBaseTemplate, b as getLanguageFromTemplate, c as getPackageManagerName, d as generateRandomName, e as detectTooling, r as resolveMonorepoRootPackageVersions, f as generateAiFiles, A as ALL_AI_PLATFORMS, h as generateVscodeFiles, i as generateTypescriptConfigPackage, j as generateOxlintConfigPackage, k as generateEslintConfigPackage, l as generateOxfmtConfigPackage, m as generatePrettierConfigPackage, n as generateGitignore, o as getResolvedPackageVersion, p as parseWorkspaceYamlContent, q as formatResolvedPackageVersion, s as resolvePackageManager, t as resolveEngine, u as resolveProjectPackageVersions, v as generate, w as parsePackageManager, x as parseEngine, y as AI_PLATFORM_LABELS, z as AI_PLATFORM_HINTS, B as validatePackageName } from './chunks/index.mjs';
|
|
13
13
|
import Conf from 'conf';
|
|
14
|
+
import { readFile, mkdir, writeFile, rm, access, readdir, constants as constants$1 } from 'fs/promises';
|
|
15
|
+
import { constants } from 'fs';
|
|
16
|
+
import { join, dirname } from 'path';
|
|
14
17
|
|
|
15
18
|
const editorNames = {
|
|
16
19
|
cursor: "Cursor",
|
|
@@ -64,11 +67,19 @@ function formatConfigSummary(options, inherited) {
|
|
|
64
67
|
} else {
|
|
65
68
|
lines.push(formatRow("Bundler", "vite"));
|
|
66
69
|
}
|
|
67
|
-
const
|
|
68
|
-
lines.push(
|
|
70
|
+
const engineInherited = inherited?.engine !== void 0;
|
|
71
|
+
lines.push(
|
|
72
|
+
formatRow(
|
|
73
|
+
"Engine",
|
|
74
|
+
`${getEngineName(options.engine)}@${options.engine?.version ?? "latest"}`,
|
|
75
|
+
engineInherited
|
|
76
|
+
)
|
|
77
|
+
);
|
|
69
78
|
const pmInherited = inherited?.packageManager !== void 0;
|
|
70
|
-
lines.push(
|
|
71
|
-
|
|
79
|
+
lines.push(
|
|
80
|
+
formatRow("Package manager", getPackageManagerName(options.packageManager), pmInherited)
|
|
81
|
+
);
|
|
82
|
+
if (getPackageManagerName(options.packageManager) === "pnpm") {
|
|
72
83
|
const versionManaged = options.pnpmManageVersions ? "yes" : "no";
|
|
73
84
|
const pnpmVersionInherited = inherited?.pnpmManageVersions !== void 0;
|
|
74
85
|
lines.push(formatRow("\u21B3 Version managed", versionManaged, pnpmVersionInherited, ""));
|
|
@@ -122,8 +133,10 @@ function formatMonorepoConfigSummary(options) {
|
|
|
122
133
|
const dots = color.gray(".".repeat(dotCount));
|
|
123
134
|
return `${indent}${label} ${dots} ${value}`;
|
|
124
135
|
};
|
|
125
|
-
lines.push(
|
|
126
|
-
|
|
136
|
+
lines.push(
|
|
137
|
+
formatRow("Engine", `${getEngineName(options.engine)}@${options.engine.version ?? "latest"}`)
|
|
138
|
+
);
|
|
139
|
+
lines.push(formatRow("Package manager", options.packageManager));
|
|
127
140
|
if (options.packageManager === "pnpm") {
|
|
128
141
|
const versionManaged = options.pnpmManageVersions ? "yes" : "no";
|
|
129
142
|
lines.push(formatRow("\u21B3 Version managed", versionManaged, ""));
|
|
@@ -151,9 +164,6 @@ function setReuseWindow(reuse) {
|
|
|
151
164
|
function getAiPlatforms() {
|
|
152
165
|
return config.get("aiPlatforms");
|
|
153
166
|
}
|
|
154
|
-
function setAiPlatforms(platforms) {
|
|
155
|
-
config.set("aiPlatforms", platforms);
|
|
156
|
-
}
|
|
157
167
|
function getConfigStrategy() {
|
|
158
168
|
return config.get("configStrategy") ?? "stealth";
|
|
159
169
|
}
|
|
@@ -174,9 +184,9 @@ function getDefaultOptions(template, name, projectType = "app", libraryBundler,
|
|
|
174
184
|
template,
|
|
175
185
|
projectType,
|
|
176
186
|
libraryBundler: projectType === "library" ? libraryBundler ?? "unbuild" : void 0,
|
|
177
|
-
packageManager: inheritedSettings?.packageManager ?? "pnpm",
|
|
187
|
+
packageManager: inheritedSettings?.packageManager ?? { name: "pnpm" },
|
|
178
188
|
pnpmManageVersions: inheritedSettings?.pnpmManageVersions ?? true,
|
|
179
|
-
|
|
189
|
+
engine: inheritedSettings?.engine ?? { name: "node", version: "latest" },
|
|
180
190
|
linter: inheritedSettings?.linter ?? "oxlint",
|
|
181
191
|
formatter: inheritedSettings?.formatter ?? "prettier",
|
|
182
192
|
// Libraries get vitest by default, apps don't
|
|
@@ -271,14 +281,14 @@ async function promptForCustomization(template, name, projectType, integrations,
|
|
|
271
281
|
}
|
|
272
282
|
libraryBundler = bundler;
|
|
273
283
|
}
|
|
274
|
-
let
|
|
275
|
-
let finalPackageManager = inheritedSettings?.packageManager ?? presets?.packageManager ?? "pnpm";
|
|
284
|
+
let engine = inheritedSettings?.engine ?? presets?.engine ?? { name: "node", version: "latest" };
|
|
285
|
+
let finalPackageManager = inheritedSettings?.packageManager?.name ?? presets?.packageManager ?? "pnpm";
|
|
276
286
|
let pnpmManageVersions = inheritedSettings?.pnpmManageVersions ?? presets?.pnpmManageVersions ?? true;
|
|
277
|
-
if (!inheritedSettings?.
|
|
287
|
+
if (!inheritedSettings?.engine?.version) {
|
|
278
288
|
const nodeVersionInput = await p.text({
|
|
279
289
|
message: "Node.js version",
|
|
280
|
-
placeholder: presets?.
|
|
281
|
-
defaultValue: presets?.
|
|
290
|
+
placeholder: presets?.engine?.version ?? "latest",
|
|
291
|
+
defaultValue: presets?.engine?.version ?? "latest",
|
|
282
292
|
validate: (value) => {
|
|
283
293
|
if (!value.length) return "Required";
|
|
284
294
|
if (value !== "latest" && !/^\d+(\.\d+(\.\d+)?)?$/.test(value)) {
|
|
@@ -290,7 +300,7 @@ async function promptForCustomization(template, name, projectType, integrations,
|
|
|
290
300
|
p.cancel("Operation cancelled.");
|
|
291
301
|
process.exit(0);
|
|
292
302
|
}
|
|
293
|
-
|
|
303
|
+
engine = { name: "node", version: nodeVersionInput };
|
|
294
304
|
}
|
|
295
305
|
if (!inheritedSettings?.packageManager) {
|
|
296
306
|
const packageManager = await p.select({
|
|
@@ -396,8 +406,8 @@ async function promptForCustomization(template, name, projectType, integrations,
|
|
|
396
406
|
template: finalTemplate,
|
|
397
407
|
projectType,
|
|
398
408
|
libraryBundler: projectType === "library" ? libraryBundler : void 0,
|
|
399
|
-
|
|
400
|
-
packageManager: finalPackageManager,
|
|
409
|
+
engine,
|
|
410
|
+
packageManager: { name: finalPackageManager },
|
|
401
411
|
pnpmManageVersions,
|
|
402
412
|
linter,
|
|
403
413
|
formatter,
|
|
@@ -443,9 +453,9 @@ function getDefaultMonorepoOptions(name) {
|
|
|
443
453
|
return {
|
|
444
454
|
name,
|
|
445
455
|
projectType: "monorepo",
|
|
446
|
-
packageManager: "pnpm",
|
|
456
|
+
packageManager: { name: "pnpm" },
|
|
447
457
|
pnpmManageVersions: true,
|
|
448
|
-
|
|
458
|
+
engine: { name: "node", version: "latest" },
|
|
449
459
|
linter: "oxlint",
|
|
450
460
|
formatter: "prettier"
|
|
451
461
|
};
|
|
@@ -453,8 +463,8 @@ function getDefaultMonorepoOptions(name) {
|
|
|
453
463
|
async function promptForMonorepoCustomization(name, presets) {
|
|
454
464
|
const nodeVersion = await p.text({
|
|
455
465
|
message: "Node.js version",
|
|
456
|
-
placeholder: presets?.
|
|
457
|
-
defaultValue: presets?.
|
|
466
|
+
placeholder: presets?.engine?.version ?? "latest",
|
|
467
|
+
defaultValue: presets?.engine?.version ?? "latest",
|
|
458
468
|
validate: (value) => {
|
|
459
469
|
if (!value.length) return "Required";
|
|
460
470
|
if (value !== "latest" && !/^\d+(\.\d+(\.\d+)?)?$/.test(value)) {
|
|
@@ -503,8 +513,8 @@ async function promptForMonorepoCustomization(name, presets) {
|
|
|
503
513
|
return {
|
|
504
514
|
name,
|
|
505
515
|
projectType: "monorepo",
|
|
506
|
-
nodeVersion,
|
|
507
|
-
packageManager: "pnpm",
|
|
516
|
+
engine: { name: "node", version: nodeVersion },
|
|
517
|
+
packageManager: { name: "pnpm" },
|
|
508
518
|
pnpmManageVersions: managePnpm,
|
|
509
519
|
linter,
|
|
510
520
|
formatter
|
|
@@ -515,15 +525,15 @@ async function promptForMonorepo(workspaceName, presets) {
|
|
|
515
525
|
if (presets) {
|
|
516
526
|
if (presets.linter) defaultOptions.linter = presets.linter;
|
|
517
527
|
if (presets.formatter) defaultOptions.formatter = presets.formatter;
|
|
518
|
-
if (presets.
|
|
528
|
+
if (presets.engine) defaultOptions.engine = presets.engine;
|
|
519
529
|
if (presets.pnpmManageVersions !== void 0)
|
|
520
530
|
defaultOptions.pnpmManageVersions = presets.pnpmManageVersions;
|
|
521
531
|
}
|
|
522
532
|
p.note(
|
|
523
533
|
formatMonorepoConfigSummary({
|
|
524
534
|
name: defaultOptions.name,
|
|
525
|
-
|
|
526
|
-
packageManager: defaultOptions.packageManager
|
|
535
|
+
engine: defaultOptions.engine ?? { name: "node", version: "latest" },
|
|
536
|
+
packageManager: getPackageManagerName(defaultOptions.packageManager),
|
|
527
537
|
pnpmManageVersions: defaultOptions.pnpmManageVersions,
|
|
528
538
|
linter: defaultOptions.linter ?? "oxlint",
|
|
529
539
|
formatter: defaultOptions.formatter ?? "prettier"
|
|
@@ -580,12 +590,7 @@ async function promptForOptions(name, presets) {
|
|
|
580
590
|
if (projectType === "monorepo") {
|
|
581
591
|
return promptForMonorepo(projectName, presets);
|
|
582
592
|
}
|
|
583
|
-
return promptForPackageOptions(
|
|
584
|
-
projectName,
|
|
585
|
-
projectType,
|
|
586
|
-
void 0,
|
|
587
|
-
presets
|
|
588
|
-
);
|
|
593
|
+
return promptForPackageOptions(projectName, projectType, void 0, presets);
|
|
589
594
|
}
|
|
590
595
|
function customTemplateToOptions(customTemplate, name, projectType, inheritedSettings) {
|
|
591
596
|
const baseTemplate = customTemplate.baseTemplate;
|
|
@@ -594,9 +599,9 @@ function customTemplateToOptions(customTemplate, name, projectType, inheritedSet
|
|
|
594
599
|
name,
|
|
595
600
|
template,
|
|
596
601
|
projectType,
|
|
597
|
-
packageManager: inheritedSettings?.packageManager ?? "pnpm",
|
|
602
|
+
packageManager: inheritedSettings?.packageManager ?? { name: "pnpm" },
|
|
598
603
|
pnpmManageVersions: inheritedSettings?.pnpmManageVersions ?? true,
|
|
599
|
-
|
|
604
|
+
engine: inheritedSettings?.engine ?? { name: "node", version: "latest" },
|
|
600
605
|
linter: inheritedSettings?.linter ?? customTemplate.linter,
|
|
601
606
|
formatter: inheritedSettings?.formatter ?? customTemplate.formatter,
|
|
602
607
|
testing: customTemplate.testing,
|
|
@@ -627,8 +632,8 @@ function presetsToInheritedSettings(presets) {
|
|
|
627
632
|
return {
|
|
628
633
|
linter: presets.linter,
|
|
629
634
|
formatter: presets.formatter,
|
|
630
|
-
packageManager: presets.packageManager,
|
|
631
|
-
|
|
635
|
+
packageManager: presets.packageManager ? { name: presets.packageManager } : void 0,
|
|
636
|
+
engine: presets.engine,
|
|
632
637
|
pnpmManageVersions: presets.pnpmManageVersions
|
|
633
638
|
};
|
|
634
639
|
}
|
|
@@ -730,53 +735,9 @@ async function promptForPackageOptions(projectName, projectType, inheritedSettin
|
|
|
730
735
|
);
|
|
731
736
|
}
|
|
732
737
|
|
|
733
|
-
async function
|
|
734
|
-
for (const path of paths) {
|
|
735
|
-
try {
|
|
736
|
-
await access(path, constants.F_OK);
|
|
737
|
-
return true;
|
|
738
|
-
} catch {
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
return false;
|
|
742
|
-
}
|
|
743
|
-
async function validateWorkspace(monorepoRoot) {
|
|
744
|
-
const errors = [];
|
|
745
|
-
const tsConfigPath = join(monorepoRoot, ".config/typescript/package.json");
|
|
746
|
-
try {
|
|
747
|
-
await access(tsConfigPath, constants.F_OK);
|
|
748
|
-
} catch {
|
|
749
|
-
errors.push("Missing .config/typescript package");
|
|
750
|
-
}
|
|
751
|
-
const linterPaths = [
|
|
752
|
-
join(monorepoRoot, ".config/oxlint/package.json"),
|
|
753
|
-
join(monorepoRoot, ".config/eslint/package.json"),
|
|
754
|
-
join(monorepoRoot, "eslint.config.js"),
|
|
755
|
-
join(monorepoRoot, "biome.json")
|
|
756
|
-
];
|
|
757
|
-
const hasLinter = await checkAnyExists(linterPaths);
|
|
758
|
-
if (!hasLinter) {
|
|
759
|
-
errors.push(
|
|
760
|
-
"Missing linter config (.config/oxlint, .config/eslint, eslint.config.js, or biome.json)"
|
|
761
|
-
);
|
|
762
|
-
}
|
|
763
|
-
const formatterPaths = [
|
|
764
|
-
join(monorepoRoot, ".config/oxfmt/package.json"),
|
|
765
|
-
join(monorepoRoot, ".config/prettier/package.json"),
|
|
766
|
-
join(monorepoRoot, ".prettierrc.json"),
|
|
767
|
-
join(monorepoRoot, "biome.json")
|
|
768
|
-
];
|
|
769
|
-
const hasFormatter = await checkAnyExists(formatterPaths);
|
|
770
|
-
if (!hasFormatter) {
|
|
771
|
-
errors.push(
|
|
772
|
-
"Missing formatter config (.config/oxfmt, .config/prettier, .prettierrc.json, or biome.json)"
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
return { valid: errors.length === 0, errors };
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
async function detectCurrentConfig(root) {
|
|
738
|
+
async function detectCurrentConfig(root, isMonorepo = true) {
|
|
779
739
|
let name = root.split(/[/\\]/).pop() ?? "workspace";
|
|
740
|
+
let packageManager = "pnpm";
|
|
780
741
|
try {
|
|
781
742
|
const pkgPath = join(root, "package.json");
|
|
782
743
|
const content = await readFile(pkgPath, "utf-8");
|
|
@@ -784,47 +745,63 @@ async function detectCurrentConfig(root) {
|
|
|
784
745
|
if (pkgJson.name) {
|
|
785
746
|
name = pkgJson.name.replace(/^@/, "").replace(/\/.*$/, "");
|
|
786
747
|
}
|
|
748
|
+
if (pkgJson.packageManager) {
|
|
749
|
+
packageManager = pkgJson.packageManager.split("@")[0] ?? packageManager;
|
|
750
|
+
}
|
|
787
751
|
} catch {
|
|
788
752
|
}
|
|
789
753
|
const tooling = await detectTooling(root);
|
|
754
|
+
const configStrategy = isMonorepo ? void 0 : await detectStandaloneConfigStrategy(root);
|
|
790
755
|
return {
|
|
791
756
|
name,
|
|
792
757
|
linter: tooling.linter ?? "oxlint",
|
|
793
758
|
formatter: tooling.formatter ?? "prettier",
|
|
794
|
-
packageManager
|
|
759
|
+
packageManager,
|
|
760
|
+
isMonorepo,
|
|
761
|
+
configStrategy
|
|
795
762
|
};
|
|
796
763
|
}
|
|
797
|
-
function
|
|
798
|
-
const
|
|
764
|
+
async function detectStandaloneConfigStrategy(root) {
|
|
765
|
+
const hasStealthConfig = await Promise.all([
|
|
766
|
+
fileExists$1(join(root, ".config/tsconfig.app.json")),
|
|
767
|
+
fileExists$1(join(root, ".config/tsconfig.node.json")),
|
|
768
|
+
fileExists$1(join(root, ".config/prettier.json")),
|
|
769
|
+
fileExists$1(join(root, ".config/oxlint.json"))
|
|
770
|
+
]).then((matches) => matches.some(Boolean));
|
|
771
|
+
return hasStealthConfig ? "stealth" : "root";
|
|
772
|
+
}
|
|
773
|
+
async function generateExpectedFiles(config) {
|
|
774
|
+
const { name, linter, formatter, packageManager, isMonorepo, configStrategy } = config;
|
|
775
|
+
const versions = linter === "biome" || formatter === "biome" ? await resolveMonorepoRootPackageVersions({ linter, formatter }) : {};
|
|
799
776
|
const aiFilesMap = {};
|
|
800
777
|
generateAiFiles(aiFilesMap, {
|
|
801
778
|
name,
|
|
802
779
|
packageManager,
|
|
803
780
|
linter,
|
|
804
781
|
formatter,
|
|
805
|
-
isMonorepo
|
|
782
|
+
isMonorepo,
|
|
783
|
+
configStrategy,
|
|
806
784
|
platforms: ALL_AI_PLATFORMS
|
|
807
785
|
});
|
|
808
786
|
const vscodeFiles = {};
|
|
809
787
|
generateVscodeFiles(vscodeFiles, linter, formatter);
|
|
810
788
|
const configPackages = {};
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
789
|
+
if (isMonorepo) {
|
|
790
|
+
generateTypescriptConfigPackage(configPackages);
|
|
791
|
+
if (linter === "oxlint") {
|
|
792
|
+
generateOxlintConfigPackage(configPackages);
|
|
793
|
+
} else if (linter === "eslint") {
|
|
794
|
+
generateEslintConfigPackage(configPackages);
|
|
795
|
+
}
|
|
796
|
+
if (formatter === "oxfmt") {
|
|
797
|
+
generateOxfmtConfigPackage(configPackages);
|
|
798
|
+
} else if (formatter === "prettier") {
|
|
799
|
+
generatePrettierConfigPackage(configPackages);
|
|
800
|
+
}
|
|
821
801
|
}
|
|
822
802
|
const workspaceConfig = {};
|
|
823
803
|
const rootConfig = {};
|
|
824
|
-
rootConfig[".gitignore"] =
|
|
825
|
-
type: "text",
|
|
826
|
-
content: ["node_modules", "dist", "*.tsbuildinfo", ".DS_Store"].join("\n")
|
|
827
|
-
};
|
|
804
|
+
rootConfig[".gitignore"] = generateGitignore(isMonorepo ? "workspace-root" : "standalone");
|
|
828
805
|
rootConfig[".gitattributes"] = {
|
|
829
806
|
type: "text",
|
|
830
807
|
content: `* text=auto eol=lf
|
|
@@ -833,8 +810,9 @@ function generateExpectedFiles(config) {
|
|
|
833
810
|
`
|
|
834
811
|
};
|
|
835
812
|
if (linter === "biome" || formatter === "biome") {
|
|
813
|
+
const biomeVersion = getResolvedPackageVersion(versions, "@biomejs/biome");
|
|
836
814
|
const biomeConfig = {
|
|
837
|
-
$schema:
|
|
815
|
+
$schema: `https://biomejs.dev/schemas/${biomeVersion}/schema.json`,
|
|
838
816
|
vcs: {
|
|
839
817
|
enabled: true,
|
|
840
818
|
clientKind: "git",
|
|
@@ -865,7 +843,7 @@ function generateExpectedFiles(config) {
|
|
|
865
843
|
}
|
|
866
844
|
async function fileExists$1(path) {
|
|
867
845
|
try {
|
|
868
|
-
await access(path, constants
|
|
846
|
+
await access(path, constants.F_OK);
|
|
869
847
|
return true;
|
|
870
848
|
} catch {
|
|
871
849
|
return false;
|
|
@@ -968,9 +946,7 @@ onlyBuiltDependencies:
|
|
|
968
946
|
}
|
|
969
947
|
if (!currentContent.includes(".config/*") && !currentContent.includes('".config/*"')) {
|
|
970
948
|
const lines = updatedContent.split("\n");
|
|
971
|
-
const packagesIndex = lines.findIndex(
|
|
972
|
-
(line) => line.trim().startsWith("packages:")
|
|
973
|
-
);
|
|
949
|
+
const packagesIndex = lines.findIndex((line) => line.trim().startsWith("packages:"));
|
|
974
950
|
if (packagesIndex !== -1) {
|
|
975
951
|
lines.splice(packagesIndex + 1, 0, ' - ".config/*"');
|
|
976
952
|
updatedContent = lines.join("\n");
|
|
@@ -1036,6 +1012,14 @@ function needsMigration(current, target) {
|
|
|
1036
1012
|
async function getMigrationPlan(current, target, root) {
|
|
1037
1013
|
const toLinter = target.linter ?? current.linter;
|
|
1038
1014
|
const toFormatter = target.formatter ?? current.formatter;
|
|
1015
|
+
const targetVersions = toLinter === "biome" || toFormatter === "biome" ? await resolveMonorepoRootPackageVersions({
|
|
1016
|
+
linter: toLinter,
|
|
1017
|
+
formatter: toFormatter
|
|
1018
|
+
}) : {};
|
|
1019
|
+
const biomeSchemaUrl = toLinter === "biome" || toFormatter === "biome" ? `https://biomejs.dev/schemas/${getResolvedPackageVersion(
|
|
1020
|
+
targetVersions,
|
|
1021
|
+
"@biomejs/biome"
|
|
1022
|
+
)}/schema.json` : "";
|
|
1039
1023
|
const changes = [];
|
|
1040
1024
|
if (toLinter !== current.linter) {
|
|
1041
1025
|
if (current.linter !== "biome") {
|
|
@@ -1070,7 +1054,7 @@ async function getMigrationPlan(current, target, root) {
|
|
|
1070
1054
|
description: "Add biome.json config",
|
|
1071
1055
|
content: JSON.stringify(
|
|
1072
1056
|
{
|
|
1073
|
-
$schema:
|
|
1057
|
+
$schema: biomeSchemaUrl,
|
|
1074
1058
|
vcs: { enabled: true, clientKind: "git", useIgnoreFile: true },
|
|
1075
1059
|
linter: { enabled: true, rules: { recommended: true } },
|
|
1076
1060
|
formatter: { enabled: true }
|
|
@@ -1086,7 +1070,7 @@ async function getMigrationPlan(current, target, root) {
|
|
|
1086
1070
|
description: "Add biome.json config (linter only)",
|
|
1087
1071
|
content: JSON.stringify(
|
|
1088
1072
|
{
|
|
1089
|
-
$schema:
|
|
1073
|
+
$schema: biomeSchemaUrl,
|
|
1090
1074
|
vcs: { enabled: true, clientKind: "git", useIgnoreFile: true },
|
|
1091
1075
|
linter: { enabled: true, rules: { recommended: true } },
|
|
1092
1076
|
formatter: { enabled: false }
|
|
@@ -1139,7 +1123,7 @@ async function getMigrationPlan(current, target, root) {
|
|
|
1139
1123
|
description: "Add biome.json config (formatter only)",
|
|
1140
1124
|
content: JSON.stringify(
|
|
1141
1125
|
{
|
|
1142
|
-
$schema:
|
|
1126
|
+
$schema: biomeSchemaUrl,
|
|
1143
1127
|
vcs: { enabled: true, clientKind: "git", useIgnoreFile: true },
|
|
1144
1128
|
linter: { enabled: false },
|
|
1145
1129
|
formatter: { enabled: true }
|
|
@@ -1162,12 +1146,7 @@ async function getMigrationPlan(current, target, root) {
|
|
|
1162
1146
|
path: "package.json",
|
|
1163
1147
|
description: "Update root package.json (devDependencies, scripts)"
|
|
1164
1148
|
});
|
|
1165
|
-
const subPackageUpdates = await getSubPackageUpdates(
|
|
1166
|
-
root,
|
|
1167
|
-
current,
|
|
1168
|
-
toLinter,
|
|
1169
|
-
toFormatter
|
|
1170
|
-
);
|
|
1149
|
+
const subPackageUpdates = await getSubPackageUpdates(root, current, toLinter, toFormatter);
|
|
1171
1150
|
return {
|
|
1172
1151
|
fromLinter: current.linter,
|
|
1173
1152
|
toLinter,
|
|
@@ -1277,23 +1256,15 @@ async function updateRootPackageJson(root, plan) {
|
|
|
1277
1256
|
const oldFormatterDep = FORMATTER_DEPS[plan.fromFormatter];
|
|
1278
1257
|
delete devDeps[oldFormatterDep];
|
|
1279
1258
|
}
|
|
1259
|
+
const resolvedVersions = await resolveMonorepoRootPackageVersions({
|
|
1260
|
+
linter: plan.toLinter,
|
|
1261
|
+
formatter: plan.toFormatter
|
|
1262
|
+
});
|
|
1280
1263
|
const newLinterDep = LINTER_DEPS[plan.toLinter];
|
|
1281
|
-
|
|
1282
|
-
devDeps[newLinterDep] = "^1.36.0";
|
|
1283
|
-
} else if (plan.toLinter === "eslint") {
|
|
1284
|
-
devDeps[newLinterDep] = "^9.17.0";
|
|
1285
|
-
} else if (plan.toLinter === "biome") {
|
|
1286
|
-
devDeps[newLinterDep] = "^1.9.4";
|
|
1287
|
-
}
|
|
1264
|
+
devDeps[newLinterDep] = formatResolvedPackageVersion(resolvedVersions, newLinterDep);
|
|
1288
1265
|
if (plan.toFormatter !== plan.toLinter) {
|
|
1289
1266
|
const newFormatterDep = FORMATTER_DEPS[plan.toFormatter];
|
|
1290
|
-
|
|
1291
|
-
devDeps[newFormatterDep] = "^0.21.0";
|
|
1292
|
-
} else if (plan.toFormatter === "prettier") {
|
|
1293
|
-
devDeps[newFormatterDep] = "^3.4.2";
|
|
1294
|
-
} else if (plan.toFormatter === "biome") {
|
|
1295
|
-
devDeps[newFormatterDep] = "^1.9.4";
|
|
1296
|
-
}
|
|
1267
|
+
devDeps[newFormatterDep] = formatResolvedPackageVersion(resolvedVersions, newFormatterDep);
|
|
1297
1268
|
}
|
|
1298
1269
|
pkg.devDependencies = Object.fromEntries(
|
|
1299
1270
|
Object.entries(devDeps).sort(([a], [b]) => a.localeCompare(b))
|
|
@@ -1337,6 +1308,51 @@ function formatMigrationChange(change) {
|
|
|
1337
1308
|
return ` ${icon} ${change.description}`;
|
|
1338
1309
|
}
|
|
1339
1310
|
|
|
1311
|
+
async function checkAnyExists(paths) {
|
|
1312
|
+
for (const path of paths) {
|
|
1313
|
+
try {
|
|
1314
|
+
await access(path, constants$1.F_OK);
|
|
1315
|
+
return true;
|
|
1316
|
+
} catch {
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return false;
|
|
1320
|
+
}
|
|
1321
|
+
async function validateWorkspace(monorepoRoot) {
|
|
1322
|
+
const errors = [];
|
|
1323
|
+
const tsConfigPath = join(monorepoRoot, ".config/typescript/package.json");
|
|
1324
|
+
try {
|
|
1325
|
+
await access(tsConfigPath, constants$1.F_OK);
|
|
1326
|
+
} catch {
|
|
1327
|
+
errors.push("Missing .config/typescript package");
|
|
1328
|
+
}
|
|
1329
|
+
const linterPaths = [
|
|
1330
|
+
join(monorepoRoot, ".config/oxlint/package.json"),
|
|
1331
|
+
join(monorepoRoot, ".config/eslint/package.json"),
|
|
1332
|
+
join(monorepoRoot, "eslint.config.js"),
|
|
1333
|
+
join(monorepoRoot, "biome.json")
|
|
1334
|
+
];
|
|
1335
|
+
const hasLinter = await checkAnyExists(linterPaths);
|
|
1336
|
+
if (!hasLinter) {
|
|
1337
|
+
errors.push(
|
|
1338
|
+
"Missing linter config (.config/oxlint, .config/eslint, eslint.config.js, or biome.json)"
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
const formatterPaths = [
|
|
1342
|
+
join(monorepoRoot, ".config/oxfmt/package.json"),
|
|
1343
|
+
join(monorepoRoot, ".config/prettier/package.json"),
|
|
1344
|
+
join(monorepoRoot, ".prettierrc.json"),
|
|
1345
|
+
join(monorepoRoot, "biome.json")
|
|
1346
|
+
];
|
|
1347
|
+
const hasFormatter = await checkAnyExists(formatterPaths);
|
|
1348
|
+
if (!hasFormatter) {
|
|
1349
|
+
errors.push(
|
|
1350
|
+
"Missing formatter config (.config/oxfmt, .config/prettier, .prettierrc.json, or biome.json)"
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
return { valid: errors.length === 0, errors };
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1340
1356
|
const require$1 = createRequire(import.meta.url);
|
|
1341
1357
|
const pkg = require$1("../package.json");
|
|
1342
1358
|
const META_OPTIONS = [
|
|
@@ -1357,7 +1373,7 @@ function hasConfigOptions(options) {
|
|
|
1357
1373
|
}
|
|
1358
1374
|
async function fileExists(path) {
|
|
1359
1375
|
try {
|
|
1360
|
-
await access(path, constants$
|
|
1376
|
+
await access$1(path, constants$2.F_OK);
|
|
1361
1377
|
return true;
|
|
1362
1378
|
} catch {
|
|
1363
1379
|
return false;
|
|
@@ -1388,7 +1404,7 @@ async function promptForAiPlatforms(isNonInteractive) {
|
|
|
1388
1404
|
label: AI_PLATFORM_LABELS[platform],
|
|
1389
1405
|
hint: AI_PLATFORM_HINTS[platform]
|
|
1390
1406
|
})),
|
|
1391
|
-
initialValues: [],
|
|
1407
|
+
initialValues: ["agents"],
|
|
1392
1408
|
required: false
|
|
1393
1409
|
});
|
|
1394
1410
|
if (p.isCancel(selected)) {
|
|
@@ -1398,26 +1414,19 @@ async function promptForAiPlatforms(isNonInteractive) {
|
|
|
1398
1414
|
if (platforms.length === 0) {
|
|
1399
1415
|
return [];
|
|
1400
1416
|
}
|
|
1401
|
-
const saveChoice = await p.confirm({
|
|
1402
|
-
message: "Save selection for future projects?",
|
|
1403
|
-
initialValue: true
|
|
1404
|
-
});
|
|
1405
|
-
if (!p.isCancel(saveChoice) && saveChoice) {
|
|
1406
|
-
setAiPlatforms(platforms);
|
|
1407
|
-
}
|
|
1408
1417
|
return platforms;
|
|
1409
1418
|
}
|
|
1410
1419
|
async function writeGeneratedFiles(basePath, files) {
|
|
1411
1420
|
const filePaths = Object.keys(files).sort();
|
|
1412
1421
|
for (const filePath of filePaths) {
|
|
1413
|
-
const fullFilePath = join(basePath, filePath);
|
|
1414
|
-
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
1422
|
+
const fullFilePath = join$1(basePath, filePath);
|
|
1423
|
+
await mkdir$1(dirname$1(fullFilePath), { recursive: true });
|
|
1415
1424
|
const file = files[filePath];
|
|
1416
1425
|
if (file.type === "text") {
|
|
1417
|
-
await writeFile(fullFilePath, file.content);
|
|
1426
|
+
await writeFile$1(fullFilePath, file.content);
|
|
1418
1427
|
} else {
|
|
1419
1428
|
const response = await fetch(file.url);
|
|
1420
|
-
await writeFile(fullFilePath, response.body);
|
|
1429
|
+
await writeFile$1(fullFilePath, response.body);
|
|
1421
1430
|
}
|
|
1422
1431
|
}
|
|
1423
1432
|
}
|
|
@@ -1429,23 +1438,34 @@ async function detectMonorepoRoot() {
|
|
|
1429
1438
|
let currentDir = cwd();
|
|
1430
1439
|
const root = resolve("/");
|
|
1431
1440
|
while (currentDir !== root) {
|
|
1432
|
-
const workspaceFile = join(currentDir, "pnpm-workspace.yaml");
|
|
1441
|
+
const workspaceFile = join$1(currentDir, "pnpm-workspace.yaml");
|
|
1433
1442
|
try {
|
|
1434
|
-
await access(workspaceFile, constants$
|
|
1435
|
-
const content = await readFile(workspaceFile, "utf-8");
|
|
1443
|
+
await access$1(workspaceFile, constants$2.F_OK);
|
|
1444
|
+
const content = await readFile$1(workspaceFile, "utf-8");
|
|
1436
1445
|
if (content.includes("packages:")) {
|
|
1437
1446
|
return currentDir;
|
|
1438
1447
|
}
|
|
1439
1448
|
} catch {
|
|
1440
1449
|
}
|
|
1441
|
-
currentDir = dirname(currentDir);
|
|
1450
|
+
currentDir = dirname$1(currentDir);
|
|
1442
1451
|
}
|
|
1443
1452
|
return null;
|
|
1444
1453
|
}
|
|
1454
|
+
async function detectPackageRoot() {
|
|
1455
|
+
let currentDir = cwd();
|
|
1456
|
+
const root = resolve("/");
|
|
1457
|
+
while (currentDir !== root) {
|
|
1458
|
+
if (await fileExists(join$1(currentDir, "package.json"))) {
|
|
1459
|
+
return currentDir;
|
|
1460
|
+
}
|
|
1461
|
+
currentDir = dirname$1(currentDir);
|
|
1462
|
+
}
|
|
1463
|
+
return await fileExists(join$1(root, "package.json")) ? root : null;
|
|
1464
|
+
}
|
|
1445
1465
|
async function parseWorkspaceDirectories(monorepoRoot) {
|
|
1446
1466
|
try {
|
|
1447
|
-
const workspaceFile = join(monorepoRoot, "pnpm-workspace.yaml");
|
|
1448
|
-
const content = await readFile(workspaceFile, "utf-8");
|
|
1467
|
+
const workspaceFile = join$1(monorepoRoot, "pnpm-workspace.yaml");
|
|
1468
|
+
const content = await readFile$1(workspaceFile, "utf-8");
|
|
1449
1469
|
return parseWorkspaceYamlContent(content);
|
|
1450
1470
|
} catch {
|
|
1451
1471
|
return [];
|
|
@@ -1454,34 +1474,23 @@ async function parseWorkspaceDirectories(monorepoRoot) {
|
|
|
1454
1474
|
async function detectWorkspaceSettings(monorepoRoot) {
|
|
1455
1475
|
try {
|
|
1456
1476
|
const tooling = await detectTooling(monorepoRoot);
|
|
1457
|
-
const pkgPath = join(monorepoRoot, "package.json");
|
|
1458
|
-
const content = await readFile(pkgPath, "utf-8");
|
|
1477
|
+
const pkgPath = join$1(monorepoRoot, "package.json");
|
|
1478
|
+
const content = await readFile$1(pkgPath, "utf-8");
|
|
1459
1479
|
const pkgJson = JSON.parse(content);
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
packageManager = pkgJson.packageManager.split("@")[0];
|
|
1463
|
-
}
|
|
1464
|
-
let nodeVersion;
|
|
1465
|
-
if (pkgJson.engines?.node) {
|
|
1466
|
-
const match = pkgJson.engines.node.match(/(\d+)/);
|
|
1467
|
-
if (match) {
|
|
1468
|
-
nodeVersion = match[1];
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1480
|
+
const packageManager = parsePackageManager(pkgJson.packageManager);
|
|
1481
|
+
const engine = parseEngine(pkgJson.engines);
|
|
1471
1482
|
let pnpmManageVersions;
|
|
1472
1483
|
try {
|
|
1473
|
-
const workspaceFile = join(monorepoRoot, "pnpm-workspace.yaml");
|
|
1474
|
-
const workspaceContent = await readFile(workspaceFile, "utf-8");
|
|
1475
|
-
pnpmManageVersions = workspaceContent.includes(
|
|
1476
|
-
"manage-package-manager-versions: true"
|
|
1477
|
-
);
|
|
1484
|
+
const workspaceFile = join$1(monorepoRoot, "pnpm-workspace.yaml");
|
|
1485
|
+
const workspaceContent = await readFile$1(workspaceFile, "utf-8");
|
|
1486
|
+
pnpmManageVersions = workspaceContent.includes("manage-package-manager-versions: true");
|
|
1478
1487
|
} catch {
|
|
1479
1488
|
}
|
|
1480
1489
|
return {
|
|
1481
1490
|
linter: tooling.linter,
|
|
1482
1491
|
formatter: tooling.formatter,
|
|
1483
1492
|
packageManager,
|
|
1484
|
-
|
|
1493
|
+
engine,
|
|
1485
1494
|
pnpmManageVersions
|
|
1486
1495
|
};
|
|
1487
1496
|
} catch {
|
|
@@ -1490,17 +1499,17 @@ async function detectWorkspaceSettings(monorepoRoot) {
|
|
|
1490
1499
|
}
|
|
1491
1500
|
async function detectExistingConfigs(monorepoRoot) {
|
|
1492
1501
|
const configs = {};
|
|
1493
|
-
const eslintPath = join(monorepoRoot, "eslint.config.js");
|
|
1502
|
+
const eslintPath = join$1(monorepoRoot, "eslint.config.js");
|
|
1494
1503
|
if (await fileExists(eslintPath)) {
|
|
1495
1504
|
configs.linter = "eslint";
|
|
1496
1505
|
configs.eslintConfigPath = eslintPath;
|
|
1497
1506
|
}
|
|
1498
|
-
const prettierPath = join(monorepoRoot, ".prettierrc.json");
|
|
1507
|
+
const prettierPath = join$1(monorepoRoot, ".prettierrc.json");
|
|
1499
1508
|
if (await fileExists(prettierPath)) {
|
|
1500
1509
|
configs.formatter = "prettier";
|
|
1501
1510
|
configs.prettierConfigPath = prettierPath;
|
|
1502
1511
|
}
|
|
1503
|
-
const biomePath = join(monorepoRoot, "biome.json");
|
|
1512
|
+
const biomePath = join$1(monorepoRoot, "biome.json");
|
|
1504
1513
|
if (await fileExists(biomePath)) {
|
|
1505
1514
|
configs.biomeConfigPath = biomePath;
|
|
1506
1515
|
if (!configs.linter) configs.linter = "biome";
|
|
@@ -1510,8 +1519,8 @@ async function detectExistingConfigs(monorepoRoot) {
|
|
|
1510
1519
|
}
|
|
1511
1520
|
async function getMonorepoScope(monorepoRoot) {
|
|
1512
1521
|
try {
|
|
1513
|
-
const pkgPath = join(monorepoRoot, "package.json");
|
|
1514
|
-
const content = await readFile(pkgPath, "utf-8");
|
|
1522
|
+
const pkgPath = join$1(monorepoRoot, "package.json");
|
|
1523
|
+
const content = await readFile$1(pkgPath, "utf-8");
|
|
1515
1524
|
const pkgJson = JSON.parse(content);
|
|
1516
1525
|
if (pkgJson.name) {
|
|
1517
1526
|
return pkgJson.name.replace(/^@/, "").replace(/\/.*$/, "");
|
|
@@ -1521,7 +1530,7 @@ async function getMonorepoScope(monorepoRoot) {
|
|
|
1521
1530
|
return monorepoRoot.split(/[/\\]/).pop() ?? "workspace";
|
|
1522
1531
|
}
|
|
1523
1532
|
async function getWorkspacePackages(monorepoRoot) {
|
|
1524
|
-
const packagesDir = join(monorepoRoot, "packages");
|
|
1533
|
+
const packagesDir = join$1(monorepoRoot, "packages");
|
|
1525
1534
|
try {
|
|
1526
1535
|
const { readdir } = await import('fs/promises');
|
|
1527
1536
|
const entries = await readdir(packagesDir, { withFileTypes: true });
|
|
@@ -1529,8 +1538,8 @@ async function getWorkspacePackages(monorepoRoot) {
|
|
|
1529
1538
|
for (const entry of entries) {
|
|
1530
1539
|
if (!entry.isDirectory()) continue;
|
|
1531
1540
|
try {
|
|
1532
|
-
const content = await readFile(
|
|
1533
|
-
join(packagesDir, entry.name, "package.json"),
|
|
1541
|
+
const content = await readFile$1(
|
|
1542
|
+
join$1(packagesDir, entry.name, "package.json"),
|
|
1534
1543
|
"utf-8"
|
|
1535
1544
|
);
|
|
1536
1545
|
const pkg2 = JSON.parse(content);
|
|
@@ -1544,25 +1553,23 @@ async function getWorkspacePackages(monorepoRoot) {
|
|
|
1544
1553
|
}
|
|
1545
1554
|
}
|
|
1546
1555
|
async function ensureConfigInWorkspace(monorepoRoot) {
|
|
1547
|
-
const workspacePath = join(monorepoRoot, "pnpm-workspace.yaml");
|
|
1556
|
+
const workspacePath = join$1(monorepoRoot, "pnpm-workspace.yaml");
|
|
1548
1557
|
let content;
|
|
1549
1558
|
try {
|
|
1550
|
-
content = await readFile(workspacePath, "utf-8");
|
|
1559
|
+
content = await readFile$1(workspacePath, "utf-8");
|
|
1551
1560
|
} catch {
|
|
1552
1561
|
content = `packages:
|
|
1553
1562
|
- ".config/*"
|
|
1554
1563
|
- "packages/*"
|
|
1555
1564
|
`;
|
|
1556
|
-
await writeFile(workspacePath, content);
|
|
1565
|
+
await writeFile$1(workspacePath, content);
|
|
1557
1566
|
return;
|
|
1558
1567
|
}
|
|
1559
1568
|
if (content.includes(".config/*") || content.includes('".config/*"')) {
|
|
1560
1569
|
return;
|
|
1561
1570
|
}
|
|
1562
1571
|
const lines = content.split("\n");
|
|
1563
|
-
const packagesIndex = lines.findIndex(
|
|
1564
|
-
(line) => line.trim().startsWith("packages:")
|
|
1565
|
-
);
|
|
1572
|
+
const packagesIndex = lines.findIndex((line) => line.trim().startsWith("packages:"));
|
|
1566
1573
|
if (packagesIndex === -1) {
|
|
1567
1574
|
content = `packages:
|
|
1568
1575
|
- ".config/*"
|
|
@@ -1571,14 +1578,14 @@ ${content}`;
|
|
|
1571
1578
|
lines.splice(packagesIndex + 1, 0, ' - ".config/*"');
|
|
1572
1579
|
content = lines.join("\n");
|
|
1573
1580
|
}
|
|
1574
|
-
await writeFile(workspacePath, content);
|
|
1581
|
+
await writeFile$1(workspacePath, content);
|
|
1575
1582
|
}
|
|
1576
1583
|
async function migrateEslintConfig(monorepoRoot, files) {
|
|
1577
1584
|
const configBasePath = ".config/eslint";
|
|
1578
|
-
const existingConfigPath = join(monorepoRoot, "eslint.config.js");
|
|
1585
|
+
const existingConfigPath = join$1(monorepoRoot, "eslint.config.js");
|
|
1579
1586
|
let existingContent;
|
|
1580
1587
|
try {
|
|
1581
|
-
existingContent = await readFile(existingConfigPath, "utf-8");
|
|
1588
|
+
existingContent = await readFile$1(existingConfigPath, "utf-8");
|
|
1582
1589
|
} catch {
|
|
1583
1590
|
generateEslintConfigPackage(files);
|
|
1584
1591
|
return;
|
|
@@ -1654,10 +1661,10 @@ export default [
|
|
|
1654
1661
|
}
|
|
1655
1662
|
async function migratePrettierConfig(monorepoRoot, files) {
|
|
1656
1663
|
const configBasePath = ".config/prettier";
|
|
1657
|
-
const existingConfigPath = join(monorepoRoot, ".prettierrc.json");
|
|
1664
|
+
const existingConfigPath = join$1(monorepoRoot, ".prettierrc.json");
|
|
1658
1665
|
let existingContent;
|
|
1659
1666
|
try {
|
|
1660
|
-
existingContent = await readFile(existingConfigPath, "utf-8");
|
|
1667
|
+
existingContent = await readFile$1(existingConfigPath, "utf-8");
|
|
1661
1668
|
} catch {
|
|
1662
1669
|
generatePrettierConfigPackage(files);
|
|
1663
1670
|
return;
|
|
@@ -1727,7 +1734,7 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
1727
1734
|
const dirName = value.includes("/") ? value.split("/").pop() : value;
|
|
1728
1735
|
if (!dirName) return "Package name is required";
|
|
1729
1736
|
if (!hasCustomDirectories) {
|
|
1730
|
-
const targetPath = join(monorepoRoot, defaultDir, dirName);
|
|
1737
|
+
const targetPath = join$1(monorepoRoot, defaultDir, dirName);
|
|
1731
1738
|
try {
|
|
1732
1739
|
const { statSync } = require$1("fs");
|
|
1733
1740
|
statSync(targetPath);
|
|
@@ -1742,11 +1749,7 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
1742
1749
|
}
|
|
1743
1750
|
const scopedName = packageNameInput;
|
|
1744
1751
|
const shortName = scopedName.includes("/") ? scopedName.split("/").pop() : scopedName;
|
|
1745
|
-
const packageOptions = await promptForPackageOptions(
|
|
1746
|
-
scopedName,
|
|
1747
|
-
packageType,
|
|
1748
|
-
inheritedSettings
|
|
1749
|
-
);
|
|
1752
|
+
const packageOptions = await promptForPackageOptions(scopedName, packageType, inheritedSettings);
|
|
1750
1753
|
let targetDir = defaultDir;
|
|
1751
1754
|
if (hasCustomDirectories && workspaceDirectories.length > 0) {
|
|
1752
1755
|
const dirChoice = await p.select({
|
|
@@ -1761,7 +1764,7 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
1761
1764
|
return false;
|
|
1762
1765
|
}
|
|
1763
1766
|
targetDir = dirChoice;
|
|
1764
|
-
const targetPath = join(monorepoRoot, targetDir, shortName);
|
|
1767
|
+
const targetPath = join$1(monorepoRoot, targetDir, shortName);
|
|
1765
1768
|
try {
|
|
1766
1769
|
const { statSync } = require$1("fs");
|
|
1767
1770
|
statSync(targetPath);
|
|
@@ -1770,81 +1773,13 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
1770
1773
|
} catch {
|
|
1771
1774
|
}
|
|
1772
1775
|
}
|
|
1773
|
-
const relativePkgPath = join(targetDir, shortName);
|
|
1776
|
+
const relativePkgPath = join$1(targetDir, shortName);
|
|
1774
1777
|
const workspaceRoot = calculateWorkspaceRoot(relativePkgPath);
|
|
1775
1778
|
packageOptions.workspaceRoot = workspaceRoot;
|
|
1776
1779
|
packageOptions.name = scopedName;
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
packageOptions.yarnVersion = await getLatestYarnVersion();
|
|
1781
|
-
} else if (packageManager === "npm") {
|
|
1782
|
-
packageOptions.npmVersion = await getLatestNpmCliVersion();
|
|
1783
|
-
}
|
|
1784
|
-
const nodeVersion = packageOptions.nodeVersion ?? "latest";
|
|
1785
|
-
if (nodeVersion === "latest") {
|
|
1786
|
-
packageOptions.nodeVersion = await getLatestNodeVersion();
|
|
1787
|
-
}
|
|
1788
|
-
const versions = {};
|
|
1789
|
-
const versionPromises = [];
|
|
1790
|
-
const pkgIsLibrary = packageOptions.projectType === "library";
|
|
1791
|
-
const pkgTesting = packageOptions.testing ?? (pkgIsLibrary ? "vitest" : "none");
|
|
1792
|
-
if (pkgTesting === "vitest") {
|
|
1793
|
-
versionPromises.push(
|
|
1794
|
-
getLatestNpmVersion("vitest", "4.0.0").then((v) => {
|
|
1795
|
-
versions.vitest = v;
|
|
1796
|
-
})
|
|
1797
|
-
);
|
|
1798
|
-
}
|
|
1799
|
-
if (!pkgIsLibrary) {
|
|
1800
|
-
versionPromises.push(
|
|
1801
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
1802
|
-
versions.vite = v;
|
|
1803
|
-
})
|
|
1804
|
-
);
|
|
1805
|
-
}
|
|
1806
|
-
const linter = packageOptions.linter ?? "oxlint";
|
|
1807
|
-
if (linter === "eslint") {
|
|
1808
|
-
versionPromises.push(
|
|
1809
|
-
getLatestNpmVersion("eslint", "9.17.0").then((v) => {
|
|
1810
|
-
versions.eslint = v;
|
|
1811
|
-
})
|
|
1812
|
-
);
|
|
1813
|
-
} else if (linter === "oxlint") {
|
|
1814
|
-
versionPromises.push(
|
|
1815
|
-
getLatestNpmVersion("oxlint", "0.16.0").then((v) => {
|
|
1816
|
-
versions.oxlint = v;
|
|
1817
|
-
})
|
|
1818
|
-
);
|
|
1819
|
-
} else if (linter === "biome") {
|
|
1820
|
-
versionPromises.push(
|
|
1821
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
1822
|
-
versions.biome = v;
|
|
1823
|
-
})
|
|
1824
|
-
);
|
|
1825
|
-
}
|
|
1826
|
-
const formatter = packageOptions.formatter ?? "prettier";
|
|
1827
|
-
if (formatter === "prettier") {
|
|
1828
|
-
versionPromises.push(
|
|
1829
|
-
getLatestNpmVersion("prettier", "3.4.2").then((v) => {
|
|
1830
|
-
versions.prettier = v;
|
|
1831
|
-
})
|
|
1832
|
-
);
|
|
1833
|
-
} else if (formatter === "oxfmt") {
|
|
1834
|
-
versionPromises.push(
|
|
1835
|
-
getLatestNpmVersion("oxfmt", "0.1.0").then((v) => {
|
|
1836
|
-
versions.oxfmt = v;
|
|
1837
|
-
})
|
|
1838
|
-
);
|
|
1839
|
-
} else if (formatter === "biome" && linter !== "biome") {
|
|
1840
|
-
versionPromises.push(
|
|
1841
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
1842
|
-
versions.biome = v;
|
|
1843
|
-
})
|
|
1844
|
-
);
|
|
1845
|
-
}
|
|
1846
|
-
await Promise.all(versionPromises);
|
|
1847
|
-
packageOptions.versions = versions;
|
|
1780
|
+
packageOptions.packageManager = await resolvePackageManager(packageOptions);
|
|
1781
|
+
packageOptions.engine = await resolveEngine(packageOptions);
|
|
1782
|
+
packageOptions.versions = await resolveProjectPackageVersions(packageOptions);
|
|
1848
1783
|
const workspacePackages = packageType === "app" ? await getWorkspacePackages(monorepoRoot) : [];
|
|
1849
1784
|
if (workspacePackages.length > 0) {
|
|
1850
1785
|
const selectedDeps = await p.multiselect({
|
|
@@ -1856,15 +1791,13 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
|
|
|
1856
1791
|
packageOptions.workspaceDependencies = selectedDeps;
|
|
1857
1792
|
}
|
|
1858
1793
|
}
|
|
1859
|
-
const outputPath = join(monorepoRoot, relativePkgPath);
|
|
1794
|
+
const outputPath = join$1(monorepoRoot, relativePkgPath);
|
|
1860
1795
|
const spinner = p.spinner();
|
|
1861
1796
|
spinner.start("Creating package...");
|
|
1862
1797
|
try {
|
|
1863
1798
|
const files = generate(packageOptions);
|
|
1864
1799
|
await writeGeneratedFiles(outputPath, files);
|
|
1865
|
-
spinner.stop(
|
|
1866
|
-
color.green.inverse(` \u2713 Package created at ${relativePkgPath}! `)
|
|
1867
|
-
);
|
|
1800
|
+
spinner.stop(color.green.inverse(` \u2713 Package created at ${relativePkgPath}! `));
|
|
1868
1801
|
const addAnother = await p.select({
|
|
1869
1802
|
message: "Add another package?",
|
|
1870
1803
|
options: [
|
|
@@ -2042,19 +1975,17 @@ async function handleFixCommand(options) {
|
|
|
2042
1975
|
try {
|
|
2043
1976
|
const files = {};
|
|
2044
1977
|
const tsConfigExists = await fileExists(
|
|
2045
|
-
join(monorepoRoot, ".config/typescript/package.json")
|
|
1978
|
+
join$1(monorepoRoot, ".config/typescript/package.json")
|
|
2046
1979
|
);
|
|
2047
1980
|
if (!tsConfigExists) {
|
|
2048
1981
|
generateTypescriptConfigPackage(files);
|
|
2049
1982
|
}
|
|
2050
1983
|
if (linter === "oxlint") {
|
|
2051
|
-
const oxlintExists = await fileExists(
|
|
2052
|
-
join(monorepoRoot, ".config/oxlint/package.json")
|
|
2053
|
-
);
|
|
1984
|
+
const oxlintExists = await fileExists(join$1(monorepoRoot, ".config/oxlint/package.json"));
|
|
2054
1985
|
if (!oxlintExists) generateOxlintConfigPackage(files);
|
|
2055
1986
|
} else if (linter === "eslint") {
|
|
2056
1987
|
const eslintPkgExists = await fileExists(
|
|
2057
|
-
join(monorepoRoot, ".config/eslint/package.json")
|
|
1988
|
+
join$1(monorepoRoot, ".config/eslint/package.json")
|
|
2058
1989
|
);
|
|
2059
1990
|
if (!eslintPkgExists) {
|
|
2060
1991
|
if (existingConfigs.eslintConfigPath) {
|
|
@@ -2065,13 +1996,11 @@ async function handleFixCommand(options) {
|
|
|
2065
1996
|
}
|
|
2066
1997
|
}
|
|
2067
1998
|
if (formatter === "oxfmt") {
|
|
2068
|
-
const oxfmtExists = await fileExists(
|
|
2069
|
-
join(monorepoRoot, ".config/oxfmt/package.json")
|
|
2070
|
-
);
|
|
1999
|
+
const oxfmtExists = await fileExists(join$1(monorepoRoot, ".config/oxfmt/package.json"));
|
|
2071
2000
|
if (!oxfmtExists) generateOxfmtConfigPackage(files);
|
|
2072
2001
|
} else if (formatter === "prettier") {
|
|
2073
2002
|
const prettierPkgExists = await fileExists(
|
|
2074
|
-
join(monorepoRoot, ".config/prettier/package.json")
|
|
2003
|
+
join$1(monorepoRoot, ".config/prettier/package.json")
|
|
2075
2004
|
);
|
|
2076
2005
|
if (!prettierPkgExists) {
|
|
2077
2006
|
if (existingConfigs.prettierConfigPath) {
|
|
@@ -2082,8 +2011,13 @@ async function handleFixCommand(options) {
|
|
|
2082
2011
|
}
|
|
2083
2012
|
}
|
|
2084
2013
|
if ((linter === "biome" || formatter === "biome") && !existingConfigs.biomeConfigPath) {
|
|
2014
|
+
const versions = await resolveMonorepoRootPackageVersions({
|
|
2015
|
+
linter,
|
|
2016
|
+
formatter
|
|
2017
|
+
});
|
|
2018
|
+
const biomeVersion = getResolvedPackageVersion(versions, "@biomejs/biome");
|
|
2085
2019
|
const biomeConfig = {
|
|
2086
|
-
$schema:
|
|
2020
|
+
$schema: `https://biomejs.dev/schemas/${biomeVersion}/schema.json`,
|
|
2087
2021
|
vcs: {
|
|
2088
2022
|
enabled: true,
|
|
2089
2023
|
clientKind: "git",
|
|
@@ -2105,9 +2039,9 @@ async function handleFixCommand(options) {
|
|
|
2105
2039
|
};
|
|
2106
2040
|
}
|
|
2107
2041
|
for (const [filePath, file] of Object.entries(files)) {
|
|
2108
|
-
const fullPath = join(monorepoRoot, filePath);
|
|
2109
|
-
await mkdir(dirname(fullPath), { recursive: true });
|
|
2110
|
-
await writeFile(fullPath, file.content);
|
|
2042
|
+
const fullPath = join$1(monorepoRoot, filePath);
|
|
2043
|
+
await mkdir$1(dirname$1(fullPath), { recursive: true });
|
|
2044
|
+
await writeFile$1(fullPath, file.content);
|
|
2111
2045
|
}
|
|
2112
2046
|
await ensureConfigInWorkspace(monorepoRoot);
|
|
2113
2047
|
if (existingConfigs.eslintConfigPath && linter === "eslint") {
|
|
@@ -2123,18 +2057,14 @@ async function handleFixCommand(options) {
|
|
|
2123
2057
|
}
|
|
2124
2058
|
}
|
|
2125
2059
|
spinner.stop(color.green("\u2713") + " Workspace fixed!");
|
|
2126
|
-
const generated = Object.keys(files).filter(
|
|
2127
|
-
(f) => f.endsWith("package.json")
|
|
2128
|
-
);
|
|
2060
|
+
const generated = Object.keys(files).filter((f) => f.endsWith("package.json"));
|
|
2129
2061
|
for (const pkgFile of generated) {
|
|
2130
2062
|
const pkgName = pkgFile.replace("/package.json", "");
|
|
2131
2063
|
console.log(color.dim(` Generated ${pkgName}`));
|
|
2132
2064
|
}
|
|
2133
|
-
const vscodeSettingsExists = await fileExists(
|
|
2134
|
-
join(monorepoRoot, ".vscode/settings.json")
|
|
2135
|
-
);
|
|
2065
|
+
const vscodeSettingsExists = await fileExists(join$1(monorepoRoot, ".vscode/settings.json"));
|
|
2136
2066
|
const vscodeExtensionsExists = await fileExists(
|
|
2137
|
-
join(monorepoRoot, ".vscode/extensions.json")
|
|
2067
|
+
join$1(monorepoRoot, ".vscode/extensions.json")
|
|
2138
2068
|
);
|
|
2139
2069
|
const vscodeExists = vscodeSettingsExists && vscodeExtensionsExists;
|
|
2140
2070
|
if (!vscodeExists) {
|
|
@@ -2152,17 +2082,15 @@ async function handleFixCommand(options) {
|
|
|
2152
2082
|
const vscodeFiles = {};
|
|
2153
2083
|
generateVscodeFiles(vscodeFiles, linter, formatter);
|
|
2154
2084
|
for (const [filePath, file] of Object.entries(vscodeFiles)) {
|
|
2155
|
-
const fullPath = join(monorepoRoot, filePath);
|
|
2156
|
-
await mkdir(dirname(fullPath), { recursive: true });
|
|
2157
|
-
await writeFile(fullPath, file.content);
|
|
2085
|
+
const fullPath = join$1(monorepoRoot, filePath);
|
|
2086
|
+
await mkdir$1(dirname$1(fullPath), { recursive: true });
|
|
2087
|
+
await writeFile$1(fullPath, file.content);
|
|
2158
2088
|
}
|
|
2159
2089
|
console.log(color.dim(" Generated .vscode/settings.json"));
|
|
2160
2090
|
console.log(color.dim(" Generated .vscode/extensions.json"));
|
|
2161
2091
|
}
|
|
2162
2092
|
}
|
|
2163
|
-
const aiRulesExist = await fileExists(
|
|
2164
|
-
join(monorepoRoot, ".ai/workspace.md")
|
|
2165
|
-
);
|
|
2093
|
+
const aiRulesExist = await fileExists(join$1(monorepoRoot, ".ai/workspace.md"));
|
|
2166
2094
|
if (!aiRulesExist) {
|
|
2167
2095
|
const platforms = await promptForAiPlatforms(isNonInteractive);
|
|
2168
2096
|
if (platforms.length > 0) {
|
|
@@ -2177,9 +2105,9 @@ async function handleFixCommand(options) {
|
|
|
2177
2105
|
platforms
|
|
2178
2106
|
});
|
|
2179
2107
|
for (const [filePath, file] of Object.entries(aiFilesOutput)) {
|
|
2180
|
-
const fullPath = join(monorepoRoot, filePath);
|
|
2181
|
-
await mkdir(dirname(fullPath), { recursive: true });
|
|
2182
|
-
await writeFile(fullPath, file.content);
|
|
2108
|
+
const fullPath = join$1(monorepoRoot, filePath);
|
|
2109
|
+
await mkdir$1(dirname$1(fullPath), { recursive: true });
|
|
2110
|
+
await writeFile$1(fullPath, file.content);
|
|
2183
2111
|
console.log(color.dim(` Generated ${filePath}`));
|
|
2184
2112
|
}
|
|
2185
2113
|
}
|
|
@@ -2195,15 +2123,11 @@ async function handleMigration(config, target, root, options) {
|
|
|
2195
2123
|
const plan = await getMigrationPlan(config, target, root);
|
|
2196
2124
|
console.log(color.cyan("Migration:"));
|
|
2197
2125
|
if (plan.fromLinter !== plan.toLinter) {
|
|
2198
|
-
console.log(
|
|
2199
|
-
` Linter: ${color.dim(plan.fromLinter)} \u2192 ${color.green(plan.toLinter)}`
|
|
2200
|
-
);
|
|
2126
|
+
console.log(` Linter: ${color.dim(plan.fromLinter)} \u2192 ${color.green(plan.toLinter)}`);
|
|
2201
2127
|
}
|
|
2202
2128
|
if (plan.fromFormatter !== plan.toFormatter) {
|
|
2203
2129
|
console.log(
|
|
2204
|
-
` Formatter: ${color.dim(plan.fromFormatter)} \u2192 ${color.green(
|
|
2205
|
-
plan.toFormatter
|
|
2206
|
-
)}`
|
|
2130
|
+
` Formatter: ${color.dim(plan.fromFormatter)} \u2192 ${color.green(plan.toFormatter)}`
|
|
2207
2131
|
);
|
|
2208
2132
|
}
|
|
2209
2133
|
console.log();
|
|
@@ -2234,17 +2158,17 @@ async function handleMigration(config, target, root, options) {
|
|
|
2234
2158
|
}
|
|
2235
2159
|
}
|
|
2236
2160
|
await applyMigration(plan, root);
|
|
2237
|
-
const aiWorkspacePath = join(root, ".ai/workspace.md");
|
|
2161
|
+
const aiWorkspacePath = join$1(root, ".ai/workspace.md");
|
|
2238
2162
|
const aiRulesExist = await fileExists(aiWorkspacePath);
|
|
2239
2163
|
if (aiRulesExist) {
|
|
2240
2164
|
console.log();
|
|
2241
2165
|
console.log(color.cyan("Updating AI rules..."));
|
|
2242
2166
|
const scope = await getMonorepoScope(root);
|
|
2243
2167
|
const existingPlatforms = [];
|
|
2244
|
-
if (await fileExists(join(root, "AGENTS.md"))) {
|
|
2168
|
+
if (await fileExists(join$1(root, "AGENTS.md"))) {
|
|
2245
2169
|
existingPlatforms.push("agents");
|
|
2246
2170
|
}
|
|
2247
|
-
if (await fileExists(join(root, "CLAUDE.md"))) {
|
|
2171
|
+
if (await fileExists(join$1(root, "CLAUDE.md"))) {
|
|
2248
2172
|
existingPlatforms.push("claude");
|
|
2249
2173
|
}
|
|
2250
2174
|
const aiFilesOutput = {};
|
|
@@ -2257,94 +2181,94 @@ async function handleMigration(config, target, root, options) {
|
|
|
2257
2181
|
platforms: existingPlatforms.length > 0 ? existingPlatforms : ["agents"]
|
|
2258
2182
|
});
|
|
2259
2183
|
for (const [filePath, file] of Object.entries(aiFilesOutput)) {
|
|
2260
|
-
const fullPath = join(root, filePath);
|
|
2261
|
-
await mkdir(dirname(fullPath), { recursive: true });
|
|
2262
|
-
await writeFile(fullPath, file.content);
|
|
2184
|
+
const fullPath = join$1(root, filePath);
|
|
2185
|
+
await mkdir$1(dirname$1(fullPath), { recursive: true });
|
|
2186
|
+
await writeFile$1(fullPath, file.content);
|
|
2263
2187
|
console.log(color.dim(` ${filePath}`));
|
|
2264
2188
|
}
|
|
2265
2189
|
}
|
|
2266
2190
|
console.log();
|
|
2267
|
-
console.log(
|
|
2268
|
-
color.green("\u2713") + ` Migrated to ${plan.toLinter}/${plan.toFormatter}`
|
|
2269
|
-
);
|
|
2191
|
+
console.log(color.green("\u2713") + ` Migrated to ${plan.toLinter}/${plan.toFormatter}`);
|
|
2270
2192
|
console.log(color.dim(" Run `pnpm install` to update dependencies"));
|
|
2271
2193
|
process.exit(0);
|
|
2272
2194
|
}
|
|
2273
2195
|
async function handleUpdateCommand(options) {
|
|
2274
2196
|
const monorepoRoot = await detectMonorepoRoot();
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
console.log(color.
|
|
2197
|
+
const projectRoot = monorepoRoot ?? await detectPackageRoot();
|
|
2198
|
+
if (!projectRoot) {
|
|
2199
|
+
console.log(color.red("\u2717") + " Could not find a project root");
|
|
2200
|
+
console.log(color.dim(" Run this command from inside a generated project"));
|
|
2278
2201
|
process.exit(1);
|
|
2279
2202
|
}
|
|
2280
|
-
const
|
|
2281
|
-
if (
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
console.log(color.
|
|
2203
|
+
const isMonorepo = monorepoRoot != null;
|
|
2204
|
+
if (isMonorepo) {
|
|
2205
|
+
const { valid, errors } = await validateWorkspace(projectRoot);
|
|
2206
|
+
if (!valid) {
|
|
2207
|
+
console.log(color.yellow("!") + " Workspace has issues:");
|
|
2208
|
+
for (const error of errors) {
|
|
2209
|
+
console.log(color.dim(` \u2022 ${error}`));
|
|
2210
|
+
}
|
|
2211
|
+
console.log();
|
|
2212
|
+
const shouldFix = options.yes || await p.confirm({
|
|
2213
|
+
message: "Run fix first to resolve these issues?",
|
|
2214
|
+
initialValue: true
|
|
2215
|
+
});
|
|
2216
|
+
if (p.isCancel(shouldFix) || !shouldFix) {
|
|
2217
|
+
console.log(color.dim(" Run `pnpm create krispya --fix` to fix manually"));
|
|
2218
|
+
process.exit(1);
|
|
2219
|
+
}
|
|
2220
|
+
const preFixConfig = await detectCurrentConfig(projectRoot);
|
|
2221
|
+
const fixOptions = {
|
|
2222
|
+
...options,
|
|
2223
|
+
linter: options.linter ?? preFixConfig.linter,
|
|
2224
|
+
formatter: options.formatter ?? preFixConfig.formatter
|
|
2225
|
+
};
|
|
2226
|
+
await handleFixCommand(fixOptions);
|
|
2285
2227
|
}
|
|
2228
|
+
} else if (options.linter || options.formatter) {
|
|
2229
|
+
console.log(
|
|
2230
|
+
color.yellow("!") + " Linter/formatter migrations in --update are currently monorepo-only"
|
|
2231
|
+
);
|
|
2232
|
+
console.log(color.dim(" Continuing with standalone shared config updates"));
|
|
2286
2233
|
console.log();
|
|
2287
|
-
const shouldFix = options.yes || await p.confirm({
|
|
2288
|
-
message: "Run fix first to resolve these issues?",
|
|
2289
|
-
initialValue: true
|
|
2290
|
-
});
|
|
2291
|
-
if (p.isCancel(shouldFix) || !shouldFix) {
|
|
2292
|
-
console.log(
|
|
2293
|
-
color.dim(" Run `pnpm create krispya --fix` to fix manually")
|
|
2294
|
-
);
|
|
2295
|
-
process.exit(1);
|
|
2296
|
-
}
|
|
2297
|
-
const preFixConfig = await detectCurrentConfig(monorepoRoot);
|
|
2298
|
-
const fixOptions = {
|
|
2299
|
-
...options,
|
|
2300
|
-
linter: options.linter ?? preFixConfig.linter,
|
|
2301
|
-
formatter: options.formatter ?? preFixConfig.formatter
|
|
2302
|
-
};
|
|
2303
|
-
await handleFixCommand(fixOptions);
|
|
2304
2234
|
}
|
|
2305
|
-
const config = await detectCurrentConfig(
|
|
2235
|
+
const config = await detectCurrentConfig(projectRoot, isMonorepo);
|
|
2306
2236
|
const targetLinter = options.linter;
|
|
2307
2237
|
const targetFormatter = options.formatter;
|
|
2308
2238
|
const migrationTarget = { linter: targetLinter, formatter: targetFormatter };
|
|
2309
|
-
if (needsMigration(config, migrationTarget)) {
|
|
2310
|
-
await handleMigration(config, migrationTarget,
|
|
2239
|
+
if (isMonorepo && needsMigration(config, migrationTarget)) {
|
|
2240
|
+
await handleMigration(config, migrationTarget, projectRoot, options);
|
|
2311
2241
|
return;
|
|
2312
2242
|
}
|
|
2313
2243
|
console.log(
|
|
2314
2244
|
color.cyan("Checking for updates...") + color.dim(` (${config.linter}/${config.formatter})`)
|
|
2315
2245
|
);
|
|
2316
2246
|
console.log();
|
|
2317
|
-
const expected = generateExpectedFiles(config);
|
|
2318
|
-
const categories = await compareWithDisk(expected,
|
|
2319
|
-
const
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
if (configPkgIndex !== -1) {
|
|
2336
|
-
allCategories.splice(configPkgIndex + 1, 0, workspaceCategory);
|
|
2337
|
-
} else {
|
|
2338
|
-
allCategories.push(workspaceCategory);
|
|
2247
|
+
const expected = await generateExpectedFiles(config);
|
|
2248
|
+
const categories = await compareWithDisk(expected, projectRoot);
|
|
2249
|
+
const allCategories = categories.filter((c) => c.category !== "workspace-config");
|
|
2250
|
+
if (isMonorepo) {
|
|
2251
|
+
const workspaceConfigChanges = await getWorkspaceConfigUpdates(projectRoot);
|
|
2252
|
+
const workspaceCategory = {
|
|
2253
|
+
category: "workspace-config",
|
|
2254
|
+
label: "Workspace Config",
|
|
2255
|
+
changes: workspaceConfigChanges,
|
|
2256
|
+
hasUserModifications: workspaceConfigChanges.some((c) => c.status === "modified")
|
|
2257
|
+
};
|
|
2258
|
+
if (workspaceConfigChanges.length > 0) {
|
|
2259
|
+
const configPkgIndex = allCategories.findIndex((c) => c.category === "config-packages");
|
|
2260
|
+
if (configPkgIndex !== -1) {
|
|
2261
|
+
allCategories.splice(configPkgIndex + 1, 0, workspaceCategory);
|
|
2262
|
+
} else {
|
|
2263
|
+
allCategories.push(workspaceCategory);
|
|
2264
|
+
}
|
|
2339
2265
|
}
|
|
2340
2266
|
}
|
|
2341
2267
|
let updatedCount = 0;
|
|
2342
2268
|
let skippedCount = 0;
|
|
2343
2269
|
for (const category of allCategories) {
|
|
2344
2270
|
const newChanges = category.changes.filter((c) => c.status === "added");
|
|
2345
|
-
const modifiedChanges = category.changes.filter(
|
|
2346
|
-
(c) => c.status === "modified"
|
|
2347
|
-
);
|
|
2271
|
+
const modifiedChanges = category.changes.filter((c) => c.status === "modified");
|
|
2348
2272
|
const hasNew = newChanges.length > 0;
|
|
2349
2273
|
const hasModified = modifiedChanges.length > 0;
|
|
2350
2274
|
const hasChanges = hasNew || hasModified;
|
|
@@ -2355,19 +2279,15 @@ async function handleUpdateCommand(options) {
|
|
|
2355
2279
|
if (category.category === "ai-files") {
|
|
2356
2280
|
if (hasNew) {
|
|
2357
2281
|
console.log(color.cyan(category.label + ":"));
|
|
2358
|
-
console.log(
|
|
2359
|
-
color.dim(` ${newChanges.length} AI file(s) can be added`)
|
|
2360
|
-
);
|
|
2282
|
+
console.log(color.dim(` ${newChanges.length} AI file(s) can be added`));
|
|
2361
2283
|
console.log();
|
|
2362
2284
|
const applyAi = options.yes ? true : await p.confirm({
|
|
2363
2285
|
message: "Add AI rules?",
|
|
2364
2286
|
initialValue: true
|
|
2365
2287
|
});
|
|
2366
2288
|
if (!p.isCancel(applyAi) && applyAi) {
|
|
2367
|
-
await applyUpdates(newChanges,
|
|
2368
|
-
console.log(
|
|
2369
|
-
color.green("\u2713") + ` Added ${newChanges.length} AI file(s)`
|
|
2370
|
-
);
|
|
2289
|
+
await applyUpdates(newChanges, projectRoot);
|
|
2290
|
+
console.log(color.green("\u2713") + ` Added ${newChanges.length} AI file(s)`);
|
|
2371
2291
|
updatedCount++;
|
|
2372
2292
|
} else {
|
|
2373
2293
|
console.log(color.dim(` Skipped ${category.label}`));
|
|
@@ -2388,7 +2308,7 @@ async function handleUpdateCommand(options) {
|
|
|
2388
2308
|
initialValue: false
|
|
2389
2309
|
});
|
|
2390
2310
|
if (!p.isCancel(updateExisting) && updateExisting) {
|
|
2391
|
-
await applyUpdates(modifiedChanges,
|
|
2311
|
+
await applyUpdates(modifiedChanges, projectRoot);
|
|
2392
2312
|
console.log(color.green("\u2713") + " Updated existing AI files");
|
|
2393
2313
|
}
|
|
2394
2314
|
}
|
|
@@ -2431,9 +2351,7 @@ async function handleUpdateCommand(options) {
|
|
|
2431
2351
|
process.exit(0);
|
|
2432
2352
|
}
|
|
2433
2353
|
if (selectedFiles.length > 0) {
|
|
2434
|
-
changesToApply = allChanges.filter(
|
|
2435
|
-
(c) => selectedFiles.includes(c.path)
|
|
2436
|
-
);
|
|
2354
|
+
changesToApply = allChanges.filter((c) => selectedFiles.includes(c.path));
|
|
2437
2355
|
}
|
|
2438
2356
|
} else if (hasNew) {
|
|
2439
2357
|
console.log(color.cyan(category.label + ":"));
|
|
@@ -2471,13 +2389,9 @@ async function handleUpdateCommand(options) {
|
|
|
2471
2389
|
}
|
|
2472
2390
|
}
|
|
2473
2391
|
if (changesToApply.length > 0) {
|
|
2474
|
-
await applyUpdates(changesToApply,
|
|
2475
|
-
const addedCount = changesToApply.filter(
|
|
2476
|
-
|
|
2477
|
-
).length;
|
|
2478
|
-
const updatedFilesCount = changesToApply.filter(
|
|
2479
|
-
(c) => c.status === "modified"
|
|
2480
|
-
).length;
|
|
2392
|
+
await applyUpdates(changesToApply, projectRoot);
|
|
2393
|
+
const addedCount = changesToApply.filter((c) => c.status === "added").length;
|
|
2394
|
+
const updatedFilesCount = changesToApply.filter((c) => c.status === "modified").length;
|
|
2481
2395
|
const parts = [];
|
|
2482
2396
|
if (addedCount > 0) parts.push(`added ${addedCount}`);
|
|
2483
2397
|
if (updatedFilesCount > 0) parts.push(`updated ${updatedFilesCount}`);
|
|
@@ -2504,20 +2418,12 @@ async function handleUpdateCommand(options) {
|
|
|
2504
2418
|
async function handleWorkspaceCommand(name, options) {
|
|
2505
2419
|
const monorepoRoot = await detectMonorepoRoot();
|
|
2506
2420
|
if (!monorepoRoot) {
|
|
2507
|
-
console.error(
|
|
2508
|
-
color.red("Error:") + " --workspace flag requires being inside a monorepo"
|
|
2509
|
-
);
|
|
2421
|
+
console.error(color.red("Error:") + " --workspace flag requires being inside a monorepo");
|
|
2510
2422
|
process.exit(1);
|
|
2511
2423
|
}
|
|
2512
2424
|
if (!name) {
|
|
2513
|
-
console.error(
|
|
2514
|
-
|
|
2515
|
-
);
|
|
2516
|
-
console.log(
|
|
2517
|
-
color.dim(
|
|
2518
|
-
" Example: pnpm create krispya my-lib --workspace --type library"
|
|
2519
|
-
)
|
|
2520
|
-
);
|
|
2425
|
+
console.error(color.red("Error:") + " Package name is required with --workspace flag");
|
|
2426
|
+
console.log(color.dim(" Example: pnpm create krispya my-lib --workspace --type library"));
|
|
2521
2427
|
process.exit(1);
|
|
2522
2428
|
}
|
|
2523
2429
|
const scope = await getMonorepoScope(monorepoRoot);
|
|
@@ -2528,32 +2434,23 @@ async function handleWorkspaceCommand(name, options) {
|
|
|
2528
2434
|
const template = options.template ?? "vanilla";
|
|
2529
2435
|
const baseTemplate = getBaseTemplate(template);
|
|
2530
2436
|
const scopedName = name.startsWith("@") ? name : `@${scope}/${name}`;
|
|
2531
|
-
const fullPackagePath = join(monorepoRoot, targetDir, name);
|
|
2437
|
+
const fullPackagePath = join$1(monorepoRoot, targetDir, name);
|
|
2532
2438
|
try {
|
|
2533
|
-
await access(fullPackagePath, constants$
|
|
2534
|
-
console.error(
|
|
2535
|
-
color.red("Error:") + ` Directory ${targetDir}/${name} already exists`
|
|
2536
|
-
);
|
|
2439
|
+
await access$1(fullPackagePath, constants$2.F_OK);
|
|
2440
|
+
console.error(color.red("Error:") + ` Directory ${targetDir}/${name} already exists`);
|
|
2537
2441
|
process.exit(1);
|
|
2538
2442
|
} catch {
|
|
2539
2443
|
}
|
|
2540
|
-
const versions = {};
|
|
2541
|
-
const versionPromises = [];
|
|
2542
|
-
const isLibrary = projectType === "library";
|
|
2543
|
-
if (!isLibrary) {
|
|
2544
|
-
versionPromises.push(
|
|
2545
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
2546
|
-
versions.vite = v;
|
|
2547
|
-
})
|
|
2548
|
-
);
|
|
2549
|
-
}
|
|
2550
2444
|
const linter = inheritedSettings.linter ?? options.linter ?? "oxlint";
|
|
2551
2445
|
const formatter = inheritedSettings.formatter ?? options.formatter ?? "prettier";
|
|
2552
|
-
const packageManager = inheritedSettings.packageManager ?? "pnpm";
|
|
2553
|
-
const
|
|
2446
|
+
const packageManager = inheritedSettings.packageManager?.name ?? "pnpm";
|
|
2447
|
+
const engine = inheritedSettings.engine ?? {
|
|
2448
|
+
name: "node",
|
|
2449
|
+
version: "latest"
|
|
2450
|
+
};
|
|
2554
2451
|
const pnpmManageVersions = inheritedSettings.pnpmManageVersions ?? true;
|
|
2555
|
-
|
|
2556
|
-
const relativePkgPath = join(targetDir, name);
|
|
2452
|
+
const isLibrary = projectType === "library";
|
|
2453
|
+
const relativePkgPath = join$1(targetDir, name);
|
|
2557
2454
|
const workspaceRoot = calculateWorkspaceRoot(relativePkgPath);
|
|
2558
2455
|
const generateOptions = {
|
|
2559
2456
|
name: scopedName,
|
|
@@ -2562,11 +2459,10 @@ async function handleWorkspaceCommand(name, options) {
|
|
|
2562
2459
|
template,
|
|
2563
2460
|
linter,
|
|
2564
2461
|
formatter,
|
|
2565
|
-
packageManager,
|
|
2566
|
-
|
|
2462
|
+
packageManager: { name: packageManager },
|
|
2463
|
+
engine,
|
|
2567
2464
|
pnpmManageVersions,
|
|
2568
2465
|
workspaceRoot,
|
|
2569
|
-
versions,
|
|
2570
2466
|
...baseTemplate === "r3f" && {
|
|
2571
2467
|
drei: options.drei ? {} : void 0,
|
|
2572
2468
|
handle: options.handle ? {} : void 0,
|
|
@@ -2582,15 +2478,14 @@ async function handleWorkspaceCommand(name, options) {
|
|
|
2582
2478
|
triplex: options.triplex ? {} : void 0
|
|
2583
2479
|
}
|
|
2584
2480
|
};
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
);
|
|
2481
|
+
generateOptions.packageManager = await resolvePackageManager(generateOptions);
|
|
2482
|
+
generateOptions.engine = await resolveEngine(generateOptions);
|
|
2483
|
+
generateOptions.versions = await resolveProjectPackageVersions(generateOptions);
|
|
2484
|
+
console.log(color.cyan("Creating") + ` ${scopedName} in ${targetDir}/${name}...`);
|
|
2588
2485
|
try {
|
|
2589
2486
|
const files = generate(generateOptions);
|
|
2590
2487
|
await writeGeneratedFiles(fullPackagePath, files);
|
|
2591
|
-
console.log(
|
|
2592
|
-
color.green("\u2713") + ` Created ${scopedName} at ${targetDir}/${name}`
|
|
2593
|
-
);
|
|
2488
|
+
console.log(color.green("\u2713") + ` Created ${scopedName} at ${targetDir}/${name}`);
|
|
2594
2489
|
process.exit(0);
|
|
2595
2490
|
} catch (error) {
|
|
2596
2491
|
console.error(color.red("Error:") + " Failed to create package");
|
|
@@ -2599,21 +2494,17 @@ async function handleWorkspaceCommand(name, options) {
|
|
|
2599
2494
|
}
|
|
2600
2495
|
}
|
|
2601
2496
|
async function handleMonorepoCreation(generateOptions, isNonInteractive) {
|
|
2602
|
-
const { generateMonorepo } = await import('./chunks/index.mjs').then(function (n) { return n.
|
|
2603
|
-
const packageManager = generateOptions.packageManager
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
generateOptions.
|
|
2608
|
-
|
|
2609
|
-
generateOptions.
|
|
2610
|
-
}
|
|
2611
|
-
const nodeVersion = generateOptions.nodeVersion ?? "latest";
|
|
2612
|
-
if (nodeVersion === "latest") {
|
|
2613
|
-
generateOptions.nodeVersion = await getLatestNodeVersion();
|
|
2614
|
-
}
|
|
2497
|
+
const { generateMonorepo } = await import('./chunks/index.mjs').then(function (n) { return n.I; });
|
|
2498
|
+
const packageManager = getPackageManagerName(generateOptions.packageManager);
|
|
2499
|
+
generateOptions.packageManager = await resolvePackageManager(generateOptions);
|
|
2500
|
+
generateOptions.engine = await resolveEngine(generateOptions);
|
|
2501
|
+
generateOptions.versions = await resolveMonorepoRootPackageVersions({
|
|
2502
|
+
linter: generateOptions.linter ?? "oxlint",
|
|
2503
|
+
formatter: generateOptions.formatter ?? "prettier",
|
|
2504
|
+
versions: generateOptions.versions
|
|
2505
|
+
});
|
|
2615
2506
|
const aiPlatforms = await promptForAiPlatforms(isNonInteractive);
|
|
2616
|
-
const projectPath = join(cwd(), generateOptions.name);
|
|
2507
|
+
const projectPath = join$1(cwd(), generateOptions.name);
|
|
2617
2508
|
const spinner = p.spinner();
|
|
2618
2509
|
spinner.start("Creating monorepo workspace...");
|
|
2619
2510
|
try {
|
|
@@ -2621,19 +2512,21 @@ async function handleMonorepoCreation(generateOptions, isNonInteractive) {
|
|
|
2621
2512
|
name: generateOptions.name,
|
|
2622
2513
|
linter: generateOptions.linter ?? "oxlint",
|
|
2623
2514
|
formatter: generateOptions.formatter ?? "prettier",
|
|
2624
|
-
packageManager
|
|
2625
|
-
|
|
2515
|
+
packageManager: generateOptions.packageManager ?? {
|
|
2516
|
+
name: packageManager
|
|
2517
|
+
},
|
|
2626
2518
|
pnpmManageVersions: generateOptions.pnpmManageVersions,
|
|
2627
|
-
|
|
2519
|
+
engine: generateOptions.engine,
|
|
2520
|
+
versions: generateOptions.versions,
|
|
2628
2521
|
aiPlatforms: aiPlatforms.length > 0 ? aiPlatforms : void 0
|
|
2629
2522
|
});
|
|
2630
2523
|
const filePaths = Object.keys(files).sort();
|
|
2631
2524
|
for (const filePath of filePaths) {
|
|
2632
|
-
const fullFilePath = join(projectPath, filePath);
|
|
2633
|
-
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
2525
|
+
const fullFilePath = join$1(projectPath, filePath);
|
|
2526
|
+
await mkdir$1(dirname$1(fullFilePath), { recursive: true });
|
|
2634
2527
|
const file = files[filePath];
|
|
2635
2528
|
if (file.type === "text") {
|
|
2636
|
-
await writeFile(fullFilePath, file.content);
|
|
2529
|
+
await writeFile$1(fullFilePath, file.content);
|
|
2637
2530
|
}
|
|
2638
2531
|
}
|
|
2639
2532
|
spinner.stop(color.green.inverse(" \u2713 Monorepo workspace created! "));
|
|
@@ -2643,8 +2536,10 @@ async function handleMonorepoCreation(generateOptions, isNonInteractive) {
|
|
|
2643
2536
|
const newWorkspaceSettings = {
|
|
2644
2537
|
linter: generateOptions.linter,
|
|
2645
2538
|
formatter: generateOptions.formatter,
|
|
2646
|
-
packageManager
|
|
2647
|
-
|
|
2539
|
+
packageManager: generateOptions.packageManager ?? {
|
|
2540
|
+
name: packageManager
|
|
2541
|
+
},
|
|
2542
|
+
engine: generateOptions.engine,
|
|
2648
2543
|
pnpmManageVersions: generateOptions.pnpmManageVersions
|
|
2649
2544
|
};
|
|
2650
2545
|
const scope = generateOptions.name;
|
|
@@ -2680,88 +2575,19 @@ async function handleStandaloneProjectCreation(generateOptions, isNonInteractive
|
|
|
2680
2575
|
if (aiPlatforms.length > 0) {
|
|
2681
2576
|
generateOptions.aiPlatforms = aiPlatforms;
|
|
2682
2577
|
}
|
|
2683
|
-
const packageManager = generateOptions.packageManager
|
|
2684
|
-
if (packageManager === "pnpm") {
|
|
2685
|
-
generateOptions.pnpmVersion = await getLatestPnpmVersion();
|
|
2686
|
-
} else if (packageManager === "yarn") {
|
|
2687
|
-
generateOptions.yarnVersion = await getLatestYarnVersion();
|
|
2688
|
-
} else if (packageManager === "npm") {
|
|
2689
|
-
generateOptions.npmVersion = await getLatestNpmCliVersion();
|
|
2690
|
-
}
|
|
2691
|
-
const nodeVersion = generateOptions.nodeVersion ?? "latest";
|
|
2692
|
-
if (nodeVersion === "latest") {
|
|
2693
|
-
generateOptions.nodeVersion = await getLatestNodeVersion();
|
|
2694
|
-
}
|
|
2695
|
-
const versions = {};
|
|
2696
|
-
const versionPromises = [];
|
|
2578
|
+
const packageManager = getPackageManagerName(generateOptions.packageManager);
|
|
2697
2579
|
const isLibrary = generateOptions.projectType === "library";
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
versions.vitest = v;
|
|
2703
|
-
})
|
|
2704
|
-
);
|
|
2705
|
-
}
|
|
2706
|
-
if (!isLibrary) {
|
|
2707
|
-
versionPromises.push(
|
|
2708
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
2709
|
-
versions.vite = v;
|
|
2710
|
-
})
|
|
2711
|
-
);
|
|
2712
|
-
}
|
|
2713
|
-
const linter = generateOptions.linter ?? "oxlint";
|
|
2714
|
-
if (linter === "eslint") {
|
|
2715
|
-
versionPromises.push(
|
|
2716
|
-
getLatestNpmVersion("eslint", "9.17.0").then((v) => {
|
|
2717
|
-
versions.eslint = v;
|
|
2718
|
-
})
|
|
2719
|
-
);
|
|
2720
|
-
} else if (linter === "oxlint") {
|
|
2721
|
-
versionPromises.push(
|
|
2722
|
-
getLatestNpmVersion("oxlint", "0.16.0").then((v) => {
|
|
2723
|
-
versions.oxlint = v;
|
|
2724
|
-
})
|
|
2725
|
-
);
|
|
2726
|
-
} else if (linter === "biome") {
|
|
2727
|
-
versionPromises.push(
|
|
2728
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
2729
|
-
versions.biome = v;
|
|
2730
|
-
})
|
|
2731
|
-
);
|
|
2732
|
-
}
|
|
2733
|
-
const formatter = generateOptions.formatter ?? "prettier";
|
|
2734
|
-
if (formatter === "prettier") {
|
|
2735
|
-
versionPromises.push(
|
|
2736
|
-
getLatestNpmVersion("prettier", "3.4.2").then((v) => {
|
|
2737
|
-
versions.prettier = v;
|
|
2738
|
-
})
|
|
2739
|
-
);
|
|
2740
|
-
} else if (formatter === "oxfmt") {
|
|
2741
|
-
versionPromises.push(
|
|
2742
|
-
getLatestNpmVersion("oxfmt", "0.1.0").then((v) => {
|
|
2743
|
-
versions.oxfmt = v;
|
|
2744
|
-
})
|
|
2745
|
-
);
|
|
2746
|
-
} else if (formatter === "biome" && linter !== "biome") {
|
|
2747
|
-
versionPromises.push(
|
|
2748
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
2749
|
-
versions.biome = v;
|
|
2750
|
-
})
|
|
2751
|
-
);
|
|
2752
|
-
}
|
|
2753
|
-
await Promise.all(versionPromises);
|
|
2754
|
-
generateOptions.versions = versions;
|
|
2755
|
-
const projectPath = join(cwd(), generateOptions.name);
|
|
2580
|
+
generateOptions.packageManager = await resolvePackageManager(generateOptions);
|
|
2581
|
+
generateOptions.engine = await resolveEngine(generateOptions);
|
|
2582
|
+
generateOptions.versions = await resolveProjectPackageVersions(generateOptions);
|
|
2583
|
+
const projectPath = join$1(cwd(), generateOptions.name);
|
|
2756
2584
|
const spinner = p.spinner();
|
|
2757
2585
|
spinner.start("Creating project...");
|
|
2758
2586
|
try {
|
|
2759
2587
|
const files = generate(generateOptions);
|
|
2760
2588
|
await writeGeneratedFiles(projectPath, files);
|
|
2761
2589
|
spinner.stop(color.green.inverse(" \u2713 Project created! "));
|
|
2762
|
-
if (isNonInteractive)
|
|
2763
|
-
process.exit(0);
|
|
2764
|
-
}
|
|
2590
|
+
if (isNonInteractive) process.exit(0);
|
|
2765
2591
|
const nextSteps = isLibrary ? [
|
|
2766
2592
|
`cd ${generateOptions.name}`,
|
|
2767
2593
|
`${packageManager} install`,
|
|
@@ -2800,7 +2626,7 @@ async function handleInteractiveMonorepoMode(monorepoRoot) {
|
|
|
2800
2626
|
const settingsInfo = [
|
|
2801
2627
|
inheritedSettings.linter && `linter: ${inheritedSettings.linter}`,
|
|
2802
2628
|
inheritedSettings.formatter && `formatter: ${inheritedSettings.formatter}`,
|
|
2803
|
-
inheritedSettings.packageManager && `pm: ${inheritedSettings.packageManager}`
|
|
2629
|
+
inheritedSettings.packageManager && `pm: ${inheritedSettings.packageManager.name}`
|
|
2804
2630
|
].filter(Boolean).join(", ");
|
|
2805
2631
|
p.log.info(`Using workspace settings (${settingsInfo})`);
|
|
2806
2632
|
}
|
|
@@ -2809,39 +2635,25 @@ async function handleInteractiveMonorepoMode(monorepoRoot) {
|
|
|
2809
2635
|
while (addMore) {
|
|
2810
2636
|
addMore = await createPackageInWorkspace(
|
|
2811
2637
|
monorepoRoot,
|
|
2812
|
-
inheritedSettings.packageManager ?? "pnpm",
|
|
2638
|
+
inheritedSettings.packageManager?.name ?? "pnpm",
|
|
2813
2639
|
inheritedSettings,
|
|
2814
2640
|
scope
|
|
2815
2641
|
);
|
|
2816
2642
|
}
|
|
2817
|
-
p.note(
|
|
2818
|
-
[`cd ${monorepoRoot}`, "pnpm install", "pnpm run dev"].join("\n"),
|
|
2819
|
-
"Next steps"
|
|
2820
|
-
);
|
|
2643
|
+
p.note([`cd ${monorepoRoot}`, "pnpm install", "pnpm run dev"].join("\n"), "Next steps");
|
|
2821
2644
|
await promptAndOpenEditor(monorepoRoot);
|
|
2822
2645
|
p.outro(color.green("Happy coding! \u2728"));
|
|
2823
2646
|
process.exit(0);
|
|
2824
2647
|
}
|
|
2825
2648
|
}
|
|
2826
2649
|
async function main() {
|
|
2827
|
-
const program = new Command().name("create-krispya").description(
|
|
2828
|
-
"CLI for creating Vanilla, React, and React Three Fiber projects"
|
|
2829
|
-
).argument("[name]", "name for the project").option("--type <type>", "project type: app or library (default: app)").option(
|
|
2650
|
+
const program = new Command().name("create-krispya").description("CLI for creating Vanilla, React, and React Three Fiber projects").argument("[name]", "name for the project").option("--type <type>", "project type: app or library (default: app)").option(
|
|
2830
2651
|
"--bundler <bundler>",
|
|
2831
2652
|
"library bundler: unbuild or tsdown (default: unbuild, only for libraries)"
|
|
2832
2653
|
).option(
|
|
2833
2654
|
"--template <type>",
|
|
2834
2655
|
"project template: vanilla, vanilla-js, react, react-js, r3f, r3f-js (default: vanilla)"
|
|
2835
|
-
).option(
|
|
2836
|
-
"--linter <type>",
|
|
2837
|
-
"linter: eslint, oxlint, or biome (default: oxlint)"
|
|
2838
|
-
).option(
|
|
2839
|
-
"--formatter <type>",
|
|
2840
|
-
"formatter: prettier, oxfmt, or biome (default: prettier)"
|
|
2841
|
-
).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(
|
|
2842
|
-
"--package-manager <manager>",
|
|
2843
|
-
"specify package manager (e.g. npm, yarn, pnpm)"
|
|
2844
|
-
).option(
|
|
2656
|
+
).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(
|
|
2845
2657
|
"--pnpm-manage-versions",
|
|
2846
2658
|
"enable manage-package-manager-versions in pnpm-workspace.yaml (default: true)"
|
|
2847
2659
|
).option(
|
|
@@ -2850,16 +2662,7 @@ async function main() {
|
|
|
2850
2662
|
).option(
|
|
2851
2663
|
"--node-version <version>",
|
|
2852
2664
|
'set Node.js version for engines.node field (default: "latest")'
|
|
2853
|
-
).option(
|
|
2854
|
-
"--workspace",
|
|
2855
|
-
"Add package to current monorepo workspace (non-interactive)"
|
|
2856
|
-
).option(
|
|
2857
|
-
"--dir <directory>",
|
|
2858
|
-
"Target directory for --workspace (default: apps/ or packages/)"
|
|
2859
|
-
).option("--clear-config", "Clear saved preferences (e.g. editor choice)").option("--config-path", "Print the path to the config file").option(
|
|
2860
|
-
"--check",
|
|
2861
|
-
"Check if current directory is in a valid monorepo workspace"
|
|
2862
|
-
).option("--fix", "Fix monorepo by generating missing .config packages").option("--update", "Update monorepo workspace to latest configuration").option("-y, --yes", "Non-interactive mode - accept all prompts").option(
|
|
2665
|
+
).option("--workspace", "Add package to current monorepo workspace (non-interactive)").option("--dir <directory>", "Target directory for --workspace (default: apps/ or packages/)").option("--clear-config", "Clear saved preferences (e.g. editor choice)").option("--config-path", "Print the path to the config file").option("--check", "Check if current directory is in a valid monorepo workspace").option("--fix", "Fix monorepo by generating missing .config packages").option("--update", "Update monorepo workspace to latest configuration").option("-y, --yes", "Non-interactive mode - accept all prompts").option(
|
|
2863
2666
|
"--path <directory>",
|
|
2864
2667
|
"Run in specified directory instead of current working directory"
|
|
2865
2668
|
).action(async (name, options) => {
|
|
@@ -2921,9 +2724,7 @@ async function main() {
|
|
|
2921
2724
|
if (options.dir && !options.workspace) {
|
|
2922
2725
|
console.error(color.red("Error:") + " --dir requires --workspace flag");
|
|
2923
2726
|
console.log(
|
|
2924
|
-
color.dim(
|
|
2925
|
-
" Example: pnpm create krispya my-lib --workspace --dir examples"
|
|
2926
|
-
)
|
|
2727
|
+
color.dim(" Example: pnpm create krispya my-lib --workspace --dir examples")
|
|
2927
2728
|
);
|
|
2928
2729
|
process.exit(1);
|
|
2929
2730
|
}
|
|
@@ -2963,9 +2764,9 @@ async function main() {
|
|
|
2963
2764
|
viverse: options.viverse ? {} : void 0,
|
|
2964
2765
|
triplex: options.triplex ? {} : void 0
|
|
2965
2766
|
},
|
|
2966
|
-
packageManager: options.packageManager,
|
|
2767
|
+
packageManager: options.packageManager ? { name: options.packageManager } : void 0,
|
|
2967
2768
|
pnpmManageVersions: options.pnpmManageVersions,
|
|
2968
|
-
|
|
2769
|
+
engine: { name: "node", version: options.nodeVersion ?? "latest" }
|
|
2969
2770
|
};
|
|
2970
2771
|
} else {
|
|
2971
2772
|
const presets = hasConfigOptions(options) ? {
|
|
@@ -2975,7 +2776,7 @@ async function main() {
|
|
|
2975
2776
|
linter: options.linter,
|
|
2976
2777
|
formatter: options.formatter,
|
|
2977
2778
|
packageManager: options.packageManager,
|
|
2978
|
-
nodeVersion: options.nodeVersion,
|
|
2779
|
+
engine: options.nodeVersion ? { name: "node", version: options.nodeVersion } : void 0,
|
|
2979
2780
|
pnpmManageVersions: options.pnpmManageVersions,
|
|
2980
2781
|
drei: options.drei,
|
|
2981
2782
|
handle: options.handle,
|