create-krispya 0.13.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 +476 -188
- 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 +483 -194
- 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.B2px1YOh.mjs → create-krispya.BYCdQkPo.mjs} +634 -380
- package/dist/shared/{create-krispya.CiGwBdQ3.cjs → create-krispya.Wf4wp5cQ.cjs} +664 -379
- package/package.json +9 -9
|
@@ -1,185 +1,27 @@
|
|
|
1
|
-
import { readFile, access } from 'fs/promises';
|
|
1
|
+
import { readFile, access, constants as constants$1 } from 'fs/promises';
|
|
2
2
|
import { constants } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
+
import Conf from 'conf';
|
|
4
5
|
import color from 'chalk';
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"*.jpg binary",
|
|
10
|
-
"*.jpeg binary",
|
|
11
|
-
"*.gif binary",
|
|
12
|
-
"*.ico binary",
|
|
13
|
-
"*.mov binary",
|
|
14
|
-
"*.mp4 binary",
|
|
15
|
-
"*.mp3 binary",
|
|
16
|
-
"*.flv binary",
|
|
17
|
-
"*.fla binary",
|
|
18
|
-
"*.wav binary",
|
|
19
|
-
"*.swf binary",
|
|
20
|
-
"*.gz binary",
|
|
21
|
-
"*.zip binary",
|
|
22
|
-
"*.7z binary",
|
|
23
|
-
"*.ttf binary",
|
|
24
|
-
"*.eot binary",
|
|
25
|
-
"*.woff binary",
|
|
26
|
-
"*.pyc binary",
|
|
27
|
-
"*.pdf binary",
|
|
28
|
-
"*.glb binary",
|
|
29
|
-
"*.gltf binary"
|
|
30
|
-
].join("\n");
|
|
31
|
-
|
|
32
|
-
const ALL_AI_PLATFORMS = ["agents", "claude"];
|
|
33
|
-
const AI_PLATFORM_LABELS = {
|
|
34
|
-
agents: "AGENTS.md",
|
|
35
|
-
claude: "CLAUDE.md"
|
|
36
|
-
};
|
|
37
|
-
const AI_PLATFORM_HINTS = {
|
|
38
|
-
agents: "OpenAI, Cursor, Windsurf, etc.",
|
|
39
|
-
claude: "Claude Code"
|
|
40
|
-
};
|
|
41
|
-
function renderAiFiles(files, params) {
|
|
42
|
-
const { platforms, isMonorepo, configStrategy, hasTypecheck, ...rest } = params;
|
|
43
|
-
if (platforms.length === 0) return;
|
|
44
|
-
const content = generateWorkspace({
|
|
45
|
-
...rest,
|
|
46
|
-
isMonorepo: !!isMonorepo,
|
|
47
|
-
configStrategy: configStrategy ?? "stealth",
|
|
48
|
-
hasTypecheck: hasTypecheck ?? false
|
|
49
|
-
});
|
|
50
|
-
const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
|
|
51
|
-
const hasAgents = platforms.includes("agents");
|
|
52
|
-
const hasClaude = platforms.includes("claude");
|
|
53
|
-
const isSingleton = platforms.length === 1;
|
|
54
|
-
if (hasAgents) files["AGENTS.md"] = { type: "text", content };
|
|
55
|
-
if (hasClaude) {
|
|
56
|
-
if (isSingleton) {
|
|
57
|
-
files["CLAUDE.md"] = { type: "text", content };
|
|
58
|
-
} else {
|
|
59
|
-
files["CLAUDE.md"] = { type: "text", content: pointer };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function generateWorkspace(ctx) {
|
|
64
|
-
const { packageManager, linter, formatter, hasTypecheck } = ctx;
|
|
65
|
-
const exampleFiles = "src/App.tsx src/core/systems/move-entity.ts";
|
|
66
|
-
const commands = getAfterEditingCommands(ctx, exampleFiles);
|
|
67
|
-
const sections = [
|
|
68
|
-
"# Workspace Tools",
|
|
69
|
-
"",
|
|
70
|
-
`- **Package Manager:** ${packageManager}`,
|
|
71
|
-
`- **Linter:** ${linter}`,
|
|
72
|
-
`- **Formatter:** ${formatter}`,
|
|
73
|
-
"",
|
|
74
|
-
"## After Editing",
|
|
75
|
-
""
|
|
76
|
-
];
|
|
77
|
-
if (hasTypecheck) {
|
|
78
|
-
sections.push(
|
|
79
|
-
"\u2705 After editing files, check the types for errors and then format and lint only the files changed for the current task."
|
|
80
|
-
);
|
|
81
|
-
} else {
|
|
82
|
-
sections.push(
|
|
83
|
-
"\u2705 After editing files, format and lint only the files changed for the current task."
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
sections.push("", "```sh", "# Example");
|
|
87
|
-
if (hasTypecheck) {
|
|
88
|
-
sections.push(runScript(packageManager, "typecheck"));
|
|
89
|
-
}
|
|
90
|
-
sections.push(
|
|
91
|
-
"# Run format and lint for only files modified",
|
|
92
|
-
commands.format,
|
|
93
|
-
commands.lint,
|
|
94
|
-
"```",
|
|
95
|
-
"",
|
|
96
|
-
"\u274C Avoid unless explicitly approved:",
|
|
97
|
-
"",
|
|
98
|
-
"```sh",
|
|
99
|
-
runScript(packageManager, "format"),
|
|
100
|
-
runScript(packageManager, "lint"),
|
|
101
|
-
"```",
|
|
102
|
-
""
|
|
103
|
-
);
|
|
104
|
-
return sections.join("\n");
|
|
105
|
-
}
|
|
106
|
-
function getAfterEditingCommands(ctx, files) {
|
|
107
|
-
return {
|
|
108
|
-
format: getFormatChangedFilesCommand(ctx, files),
|
|
109
|
-
lint: getLintChangedFilesCommand(ctx, files)
|
|
110
|
-
};
|
|
7
|
+
const PACKAGE_MANAGER_NAMES = /* @__PURE__ */ new Set(["pnpm", "npm", "yarn"]);
|
|
8
|
+
function isPackageManagerName(value) {
|
|
9
|
+
return PACKAGE_MANAGER_NAMES.has(value);
|
|
111
10
|
}
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const configPath = getPrettierConfigPath(ctx);
|
|
116
|
-
const ignorePath = getPrettierIgnorePath(ctx);
|
|
117
|
-
const configFlag2 = configPath == null ? "" : ` --config ${configPath}`;
|
|
118
|
-
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
119
|
-
return `${exec} prettier${configFlag2}${ignoreFlag} --write ${files}`;
|
|
120
|
-
}
|
|
121
|
-
if (ctx.formatter === "oxfmt") {
|
|
122
|
-
const configPath = getOxfmtConfigPath(ctx);
|
|
123
|
-
return `${exec} oxfmt -c ${configPath} --write ${files}`;
|
|
124
|
-
}
|
|
125
|
-
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
126
|
-
return `${exec} biome format${configFlag} --write ${files}`;
|
|
127
|
-
}
|
|
128
|
-
function getLintChangedFilesCommand(ctx, files) {
|
|
129
|
-
const exec = getExecCommand(ctx.packageManager);
|
|
130
|
-
if (ctx.linter === "oxlint") {
|
|
131
|
-
if (!ctx.isMonorepo) {
|
|
132
|
-
return runScript(ctx.packageManager, "lint", files);
|
|
133
|
-
}
|
|
134
|
-
return `${exec} oxlint ${files}`;
|
|
135
|
-
}
|
|
136
|
-
if (ctx.linter === "eslint") {
|
|
137
|
-
const configFlag2 = ctx.configStrategy === "stealth" ? " --config .config/eslint.config.js" : "";
|
|
138
|
-
return `${exec} eslint${configFlag2} ${files}`;
|
|
11
|
+
function parsePackageManagerSpec(value) {
|
|
12
|
+
if (value == null || value.length === 0) {
|
|
13
|
+
return void 0;
|
|
139
14
|
}
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (ctx.isMonorepo) return ".config/prettier/base.json";
|
|
145
|
-
if (ctx.configStrategy === "stealth") return ".config/prettier.json";
|
|
146
|
-
return void 0;
|
|
147
|
-
}
|
|
148
|
-
function getPrettierIgnorePath(ctx) {
|
|
149
|
-
if (ctx.isMonorepo) return ".config/prettier/prettierignore";
|
|
150
|
-
if (ctx.configStrategy === "stealth") return ".config/prettierignore";
|
|
151
|
-
return void 0;
|
|
152
|
-
}
|
|
153
|
-
function getOxfmtConfigPath(ctx) {
|
|
154
|
-
if (ctx.isMonorepo) return ".config/oxfmt/base.json";
|
|
155
|
-
if (ctx.configStrategy === "stealth") return ".config/oxfmt.json";
|
|
156
|
-
return "oxfmt.json";
|
|
157
|
-
}
|
|
158
|
-
function runScript(packageManager, script, args) {
|
|
159
|
-
const suffix = args == null ? "" : ` ${args}`;
|
|
160
|
-
if (packageManager === "npm") {
|
|
161
|
-
return `npm run ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
15
|
+
const atIndex = value.indexOf("@");
|
|
16
|
+
const name = atIndex === -1 ? value : value.slice(0, atIndex);
|
|
17
|
+
if (!isPackageManagerName(name)) {
|
|
18
|
+
return void 0;
|
|
162
19
|
}
|
|
163
|
-
if (
|
|
164
|
-
return
|
|
20
|
+
if (atIndex === -1) {
|
|
21
|
+
return { name };
|
|
165
22
|
}
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
function getExecCommand(packageManager) {
|
|
169
|
-
if (packageManager === "npm") return "npm exec --";
|
|
170
|
-
if (packageManager === "yarn") return "yarn exec";
|
|
171
|
-
return `${packageManager} exec`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function getLanguageFromTemplate(template) {
|
|
175
|
-
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
176
|
-
}
|
|
177
|
-
function getBaseTemplate(template) {
|
|
178
|
-
return template.replace("-js", "");
|
|
179
|
-
}
|
|
180
|
-
function shouldEnableReactCompiler(options) {
|
|
181
|
-
const template = options.template ?? "vanilla";
|
|
182
|
-
return getBaseTemplate(template) === "react" && (options.projectType ?? "app") === "app";
|
|
23
|
+
const version = value.slice(atIndex + 1);
|
|
24
|
+
return version.length > 0 ? { name, version } : { name };
|
|
183
25
|
}
|
|
184
26
|
|
|
185
27
|
function unique(...array) {
|
|
@@ -268,6 +110,10 @@ function validatePackageName(name) {
|
|
|
268
110
|
}
|
|
269
111
|
return validateNameSegment(name, "Package name");
|
|
270
112
|
}
|
|
113
|
+
function getPackageDirectoryName(name) {
|
|
114
|
+
const slashIndex = name.indexOf("/");
|
|
115
|
+
return slashIndex === -1 ? name : name.slice(slashIndex + 1);
|
|
116
|
+
}
|
|
271
117
|
|
|
272
118
|
function generateRandomName() {
|
|
273
119
|
const adjectives = [
|
|
@@ -379,150 +225,600 @@ async function detectLinterFromConfig(root) {
|
|
|
379
225
|
return "biome";
|
|
380
226
|
}
|
|
381
227
|
}
|
|
382
|
-
return void 0;
|
|
228
|
+
return void 0;
|
|
229
|
+
}
|
|
230
|
+
async function detectFormatterFromConfig(root) {
|
|
231
|
+
if (await pathExists(join(root, ".config/prettier"))) return "prettier";
|
|
232
|
+
if (await pathExists(join(root, ".config/oxfmt"))) return "oxfmt";
|
|
233
|
+
if (await pathExists(join(root, "biome.json"))) {
|
|
234
|
+
try {
|
|
235
|
+
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
236
|
+
const config = JSON.parse(content);
|
|
237
|
+
if (config.formatter?.enabled !== false) return "biome";
|
|
238
|
+
} catch {
|
|
239
|
+
return "biome";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
function detectLinterFromDeps(devDeps) {
|
|
245
|
+
if (!devDeps) return void 0;
|
|
246
|
+
if (devDeps["@biomejs/biome"]) return "biome";
|
|
247
|
+
if (devDeps.eslint) return "eslint";
|
|
248
|
+
if (devDeps.oxlint) return "oxlint";
|
|
249
|
+
return void 0;
|
|
250
|
+
}
|
|
251
|
+
function detectFormatterFromDeps(devDeps) {
|
|
252
|
+
if (!devDeps) return void 0;
|
|
253
|
+
if (devDeps["@biomejs/biome"]) return "biome";
|
|
254
|
+
if (devDeps.prettier) return "prettier";
|
|
255
|
+
if (devDeps.oxfmt) return "oxfmt";
|
|
256
|
+
return void 0;
|
|
257
|
+
}
|
|
258
|
+
async function detectTooling(root) {
|
|
259
|
+
try {
|
|
260
|
+
const pkgPath = join(root, "package.json");
|
|
261
|
+
const content = await readFile(pkgPath, "utf-8");
|
|
262
|
+
const pkg = JSON.parse(content);
|
|
263
|
+
const linter = detectLinterFromScript(pkg.scripts?.lint) ?? await detectLinterFromConfig(root) ?? detectLinterFromDeps(pkg.devDependencies);
|
|
264
|
+
const formatter = detectFormatterFromScript(pkg.scripts?.format) ?? await detectFormatterFromConfig(root) ?? detectFormatterFromDeps(pkg.devDependencies);
|
|
265
|
+
return { linter, formatter };
|
|
266
|
+
} catch {
|
|
267
|
+
return { linter: void 0, formatter: void 0 };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const DEFAULT_MINIMUM_RELEASE_AGE_MINUTES = 1440;
|
|
272
|
+
const MINUTE_IN_MS = 60 * 1e3;
|
|
273
|
+
function getMinimumReleaseAgeMinutes(options) {
|
|
274
|
+
return Math.max(0, options?.minimumReleaseAgeMinutes ?? DEFAULT_MINIMUM_RELEASE_AGE_MINUTES);
|
|
275
|
+
}
|
|
276
|
+
function isVersionOldEnough(version, time, options) {
|
|
277
|
+
const minimumReleaseAgeMinutes = getMinimumReleaseAgeMinutes(options);
|
|
278
|
+
if (minimumReleaseAgeMinutes === 0) return true;
|
|
279
|
+
const publishedAt = time?.[version];
|
|
280
|
+
if (publishedAt == null) return false;
|
|
281
|
+
const publishedTime = Date.parse(publishedAt);
|
|
282
|
+
if (!Number.isFinite(publishedTime)) return false;
|
|
283
|
+
return (options?.now ?? Date.now()) - publishedTime >= minimumReleaseAgeMinutes * MINUTE_IN_MS;
|
|
284
|
+
}
|
|
285
|
+
function getInstallableVersions(versions, time, options) {
|
|
286
|
+
return [...versions].filter((version) => isVersionOldEnough(version, time, options));
|
|
287
|
+
}
|
|
288
|
+
async function fetchNpmPackageMetadata(packageName) {
|
|
289
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}`);
|
|
290
|
+
return await response.json();
|
|
291
|
+
}
|
|
292
|
+
async function getLatestNpmVersion(packageName, fallback, options) {
|
|
293
|
+
try {
|
|
294
|
+
if (getMinimumReleaseAgeMinutes(options) === 0) {
|
|
295
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
296
|
+
const data2 = await response.json();
|
|
297
|
+
return data2.version;
|
|
298
|
+
}
|
|
299
|
+
const data = await fetchNpmPackageMetadata(packageName);
|
|
300
|
+
const latestVersion = data["dist-tags"]?.latest;
|
|
301
|
+
if (latestVersion != null && isVersionOldEnough(latestVersion, data.time, options)) {
|
|
302
|
+
return latestVersion;
|
|
303
|
+
}
|
|
304
|
+
const latestInstallableVersion = getInstallableVersions(
|
|
305
|
+
Object.keys(data.versions ?? {}),
|
|
306
|
+
data.time,
|
|
307
|
+
options
|
|
308
|
+
).sort((a, b) => compareNumericSemver(b, a))[0];
|
|
309
|
+
return latestInstallableVersion ?? fallback;
|
|
310
|
+
} catch {
|
|
311
|
+
return fallback;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function getSemverMajor(version) {
|
|
315
|
+
if (version == null) return void 0;
|
|
316
|
+
const major = Number.parseInt(version, 10);
|
|
317
|
+
return Number.isFinite(major) ? major : void 0;
|
|
318
|
+
}
|
|
319
|
+
function getSemverMajorString(version) {
|
|
320
|
+
return String(getSemverMajor(version) ?? version.split(".")[0]);
|
|
321
|
+
}
|
|
322
|
+
function compareNumericSemver(a, b) {
|
|
323
|
+
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
324
|
+
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
325
|
+
const maxLength = Math.max(aParts.length, bParts.length);
|
|
326
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
327
|
+
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
328
|
+
if (difference !== 0) {
|
|
329
|
+
return difference;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return 0;
|
|
333
|
+
}
|
|
334
|
+
function getLatestMatchingMajorVersion(versions, majorVersion, time, options) {
|
|
335
|
+
return getInstallableVersions(versions, time, options).filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
|
|
336
|
+
}
|
|
337
|
+
async function getLatestNpmMajorVersion(packageName, majorVersion, fallback, options) {
|
|
338
|
+
try {
|
|
339
|
+
const data = await fetchNpmPackageMetadata(packageName);
|
|
340
|
+
const latestMatchingVersion = getLatestMatchingMajorVersion(
|
|
341
|
+
Object.keys(data.versions ?? {}),
|
|
342
|
+
majorVersion,
|
|
343
|
+
data.time,
|
|
344
|
+
options
|
|
345
|
+
);
|
|
346
|
+
return latestMatchingVersion ?? fallback;
|
|
347
|
+
} catch {
|
|
348
|
+
return fallback;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
async function getLatestNpmMajorVersionAtOrBelow(packageName, majorVersion, fallback, options) {
|
|
352
|
+
try {
|
|
353
|
+
const data = await fetchNpmPackageMetadata(packageName);
|
|
354
|
+
const versions = Object.keys(data.versions ?? {});
|
|
355
|
+
const requestedMajor = getSemverMajor(majorVersion);
|
|
356
|
+
if (requestedMajor !== void 0) {
|
|
357
|
+
for (let major = requestedMajor; major >= 0; major -= 1) {
|
|
358
|
+
const latestMatchingVersion = getLatestMatchingMajorVersion(
|
|
359
|
+
versions,
|
|
360
|
+
String(major),
|
|
361
|
+
data.time,
|
|
362
|
+
options
|
|
363
|
+
);
|
|
364
|
+
if (latestMatchingVersion != null) {
|
|
365
|
+
return latestMatchingVersion;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return fallback;
|
|
370
|
+
} catch {
|
|
371
|
+
return fallback;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async function getLatestPnpmVersion() {
|
|
375
|
+
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
376
|
+
}
|
|
377
|
+
async function getLatestYarnVersion() {
|
|
378
|
+
return getLatestNpmVersion("yarn", "4.6.0");
|
|
379
|
+
}
|
|
380
|
+
async function getLatestNpmCliVersion() {
|
|
381
|
+
return getLatestNpmVersion("npm", "11.0.0");
|
|
382
|
+
}
|
|
383
|
+
async function getLatestNodeVersion() {
|
|
384
|
+
try {
|
|
385
|
+
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
386
|
+
const data = await response.json();
|
|
387
|
+
const latestVersion = data[0];
|
|
388
|
+
if (latestVersion) {
|
|
389
|
+
return latestVersion.version.replace(/^v/, "");
|
|
390
|
+
}
|
|
391
|
+
return "25.0.0";
|
|
392
|
+
} catch {
|
|
393
|
+
return "25.0.0";
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function parseWorkspaceYamlContent(content) {
|
|
398
|
+
const directories = [];
|
|
399
|
+
let inPackagesSection = false;
|
|
400
|
+
for (const line of content.split("\n")) {
|
|
401
|
+
const trimmed = line.trim();
|
|
402
|
+
if (trimmed === "packages:") {
|
|
403
|
+
inPackagesSection = true;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
410
|
+
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
411
|
+
if (entry && !entry.startsWith(".")) {
|
|
412
|
+
directories.push(entry);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return directories;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const pnpm10Capabilities = {
|
|
420
|
+
pnpmWorkspaceVersionPolicy: "manage-package-manager-versions",
|
|
421
|
+
pnpmBuildDependencyPolicy: "onlyBuiltDependencies"
|
|
422
|
+
};
|
|
423
|
+
const pnpm10Requirements = {
|
|
424
|
+
node: "18.12"
|
|
425
|
+
};
|
|
426
|
+
const pnpm11Capabilities = {
|
|
427
|
+
pnpmWorkspaceVersionPolicy: "pmOnFail",
|
|
428
|
+
pnpmBuildDependencyPolicy: "allowBuilds"
|
|
429
|
+
};
|
|
430
|
+
const pnpm11Requirements = {
|
|
431
|
+
node: "22.13"
|
|
432
|
+
};
|
|
433
|
+
function getPnpmCapabilities(major) {
|
|
434
|
+
switch (major) {
|
|
435
|
+
case 10:
|
|
436
|
+
return pnpm10Capabilities;
|
|
437
|
+
case 11:
|
|
438
|
+
return pnpm11Capabilities;
|
|
439
|
+
default:
|
|
440
|
+
if (major != null && major >= 12) return pnpm11Capabilities;
|
|
441
|
+
else return pnpm10Capabilities;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function getPnpmRequirements(major) {
|
|
445
|
+
switch (major) {
|
|
446
|
+
case 10:
|
|
447
|
+
return pnpm10Requirements;
|
|
448
|
+
case 11:
|
|
449
|
+
return pnpm11Requirements;
|
|
450
|
+
default:
|
|
451
|
+
if (major != null && major >= 12) return pnpm11Requirements;
|
|
452
|
+
else return pnpm10Requirements;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function getPnpmProfile(spec) {
|
|
456
|
+
const major = getSemverMajor(spec.version);
|
|
457
|
+
return {
|
|
458
|
+
...spec,
|
|
459
|
+
major,
|
|
460
|
+
capabilities: getPnpmCapabilities(major),
|
|
461
|
+
requirements: getPnpmRequirements(major)
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function renderPnpmWorkspaceConfig(options) {
|
|
465
|
+
const {
|
|
466
|
+
profile,
|
|
467
|
+
manageVersions = true,
|
|
468
|
+
packages = [],
|
|
469
|
+
buildDependencies = { esbuild: true }
|
|
470
|
+
} = options;
|
|
471
|
+
const lines = [];
|
|
472
|
+
if (manageVersions) {
|
|
473
|
+
if (profile.capabilities.pnpmWorkspaceVersionPolicy === "pmOnFail") {
|
|
474
|
+
lines.push("pmOnFail: download", "");
|
|
475
|
+
} else {
|
|
476
|
+
lines.push("manage-package-manager-versions: true", "");
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (packages.length > 0) {
|
|
480
|
+
lines.push("packages:", ...packages.map((pattern) => ` - "${pattern}"`), "");
|
|
481
|
+
}
|
|
482
|
+
if (profile.capabilities.pnpmBuildDependencyPolicy === "allowBuilds") {
|
|
483
|
+
lines.push("allowBuilds:");
|
|
484
|
+
for (const [dependency, allowed] of Object.entries(buildDependencies)) {
|
|
485
|
+
lines.push(` ${dependency}: ${allowed ? "true" : "false"}`);
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
const allowedDependencies = Object.entries(buildDependencies).filter(([, allowed]) => allowed).map(([dependency]) => dependency);
|
|
489
|
+
lines.push("onlyBuiltDependencies:");
|
|
490
|
+
for (const dependency of allowedDependencies) {
|
|
491
|
+
lines.push(` - ${dependency}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return lines.join("\n");
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function getPackageManagerProfile(spec) {
|
|
498
|
+
const major = getSemverMajor(spec.version);
|
|
499
|
+
if (spec.name === "pnpm") {
|
|
500
|
+
return getPnpmProfile(spec);
|
|
501
|
+
}
|
|
502
|
+
return {
|
|
503
|
+
...spec,
|
|
504
|
+
major,
|
|
505
|
+
capabilities: {},
|
|
506
|
+
requirements: {}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function getPackageManagerSpec(packageManager) {
|
|
511
|
+
return packageManager ?? { name: "pnpm" };
|
|
512
|
+
}
|
|
513
|
+
function getPackageManagerName(packageManager) {
|
|
514
|
+
return getPackageManagerSpec(packageManager).name;
|
|
515
|
+
}
|
|
516
|
+
function formatPackageManager(packageManager) {
|
|
517
|
+
const spec = getPackageManagerSpec(packageManager);
|
|
518
|
+
return spec.version ? `${spec.name}@${spec.version}` : spec.name;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async function resolvePackageManager(options) {
|
|
522
|
+
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
523
|
+
if (packageManager.version == null) {
|
|
524
|
+
if (packageManager.name === "pnpm") {
|
|
525
|
+
packageManager.version = await getLatestPnpmVersion();
|
|
526
|
+
} else if (packageManager.name === "yarn") {
|
|
527
|
+
packageManager.version = await getLatestYarnVersion();
|
|
528
|
+
} else if (packageManager.name === "npm") {
|
|
529
|
+
packageManager.version = await getLatestNpmCliVersion();
|
|
530
|
+
}
|
|
531
|
+
} else if (/^\d+$/.test(packageManager.version)) {
|
|
532
|
+
const fallback = `${packageManager.version}.0.0`;
|
|
533
|
+
packageManager.version = await getLatestNpmMajorVersion(
|
|
534
|
+
packageManager.name,
|
|
535
|
+
packageManager.version,
|
|
536
|
+
fallback
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
return packageManager;
|
|
540
|
+
}
|
|
541
|
+
async function resolvePackageManagerProfile(options) {
|
|
542
|
+
return getPackageManagerProfile(await resolvePackageManager(options));
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function getEngineSpec(engine) {
|
|
546
|
+
return engine ?? { name: "node" };
|
|
547
|
+
}
|
|
548
|
+
function getEngineName(engine) {
|
|
549
|
+
return getEngineSpec(engine).name;
|
|
550
|
+
}
|
|
551
|
+
function formatEngine(engine) {
|
|
552
|
+
const spec = getEngineSpec(engine);
|
|
553
|
+
return spec.version ? `${spec.name}@${spec.version}` : spec.name;
|
|
554
|
+
}
|
|
555
|
+
function parseEngine(engines) {
|
|
556
|
+
if (engines == null) {
|
|
557
|
+
return void 0;
|
|
558
|
+
}
|
|
559
|
+
const [name, range] = Object.entries(engines).find(
|
|
560
|
+
([engineName]) => engineName !== "npm" && engineName !== "pnpm" && engineName !== "yarn"
|
|
561
|
+
) ?? [];
|
|
562
|
+
if (name == null) {
|
|
563
|
+
return void 0;
|
|
564
|
+
}
|
|
565
|
+
const version = range?.match(/(\d+(?:\.\d+(?:\.\d+)?)?)/)?.[1];
|
|
566
|
+
return { name, version };
|
|
567
|
+
}
|
|
568
|
+
async function resolveEngine(options) {
|
|
569
|
+
const engine = getEngineSpec(options.engine);
|
|
570
|
+
if ((engine.version == null || engine.version === "latest") && engine.name === "node") {
|
|
571
|
+
engine.version = await getLatestNodeVersion();
|
|
572
|
+
}
|
|
573
|
+
return engine;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function getLanguageFromTemplate(template) {
|
|
577
|
+
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
578
|
+
}
|
|
579
|
+
function getBaseTemplate(template) {
|
|
580
|
+
return template.replace("-js", "");
|
|
581
|
+
}
|
|
582
|
+
function shouldEnableReactCompiler(options) {
|
|
583
|
+
const template = options.template ?? "vanilla";
|
|
584
|
+
return getBaseTemplate(template) === "react" && (options.projectType ?? "app") === "app";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const config = new Conf({
|
|
588
|
+
projectName: "create-krispya"
|
|
589
|
+
});
|
|
590
|
+
function getAiPlatforms() {
|
|
591
|
+
return config.get("aiPlatforms");
|
|
592
|
+
}
|
|
593
|
+
function setAiPlatforms(platforms) {
|
|
594
|
+
config.set("aiPlatforms", platforms);
|
|
595
|
+
}
|
|
596
|
+
function getConfigStrategy() {
|
|
597
|
+
return config.get("configStrategy") ?? "stealth";
|
|
598
|
+
}
|
|
599
|
+
function setConfigStrategy(strategy) {
|
|
600
|
+
config.set("configStrategy", strategy);
|
|
601
|
+
}
|
|
602
|
+
function clearConfig() {
|
|
603
|
+
config.clear();
|
|
604
|
+
}
|
|
605
|
+
function getConfigPath() {
|
|
606
|
+
return config.path;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const ALL_AI_PLATFORMS = ["agents", "claude"];
|
|
610
|
+
const AI_PLATFORM_LABELS = {
|
|
611
|
+
agents: "AGENTS.md",
|
|
612
|
+
claude: "CLAUDE.md"
|
|
613
|
+
};
|
|
614
|
+
const AI_PLATFORM_HINTS = {
|
|
615
|
+
agents: "OpenAI, Cursor, Windsurf, etc.",
|
|
616
|
+
claude: "Claude Code"
|
|
617
|
+
};
|
|
618
|
+
function renderAiFiles(files, params) {
|
|
619
|
+
const { platforms, isMonorepo, configStrategy, hasTypecheck, ...rest } = params;
|
|
620
|
+
if (platforms.length === 0) return;
|
|
621
|
+
const content = generateWorkspace({
|
|
622
|
+
...rest,
|
|
623
|
+
isMonorepo: !!isMonorepo,
|
|
624
|
+
configStrategy: configStrategy ?? "stealth",
|
|
625
|
+
hasTypecheck: hasTypecheck ?? false
|
|
626
|
+
});
|
|
627
|
+
const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
|
|
628
|
+
const hasAgents = platforms.includes("agents");
|
|
629
|
+
const hasClaude = platforms.includes("claude");
|
|
630
|
+
const isSingleton = platforms.length === 1;
|
|
631
|
+
if (hasAgents) files["AGENTS.md"] = { type: "text", content };
|
|
632
|
+
if (hasClaude) {
|
|
633
|
+
if (isSingleton) {
|
|
634
|
+
files["CLAUDE.md"] = { type: "text", content };
|
|
635
|
+
} else {
|
|
636
|
+
files["CLAUDE.md"] = { type: "text", content: pointer };
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
function generateWorkspace(ctx) {
|
|
641
|
+
const { packageManager, linter, formatter, hasTypecheck } = ctx;
|
|
642
|
+
const exampleFiles = "src/App.tsx src/core/systems/move-entity.ts";
|
|
643
|
+
const commands = getAfterEditingCommands(ctx, exampleFiles);
|
|
644
|
+
const sections = [
|
|
645
|
+
"# Workspace Tools",
|
|
646
|
+
"",
|
|
647
|
+
`- **Package Manager:** ${packageManager}`,
|
|
648
|
+
`- **Linter:** ${linter}`,
|
|
649
|
+
`- **Formatter:** ${formatter}`,
|
|
650
|
+
"",
|
|
651
|
+
"## After Editing",
|
|
652
|
+
""
|
|
653
|
+
];
|
|
654
|
+
if (hasTypecheck) {
|
|
655
|
+
sections.push(
|
|
656
|
+
"\u2705 After editing files, check the types for errors and then format and lint only the files changed for the current task."
|
|
657
|
+
);
|
|
658
|
+
} else {
|
|
659
|
+
sections.push(
|
|
660
|
+
"\u2705 After editing files, format and lint only the files changed for the current task."
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
sections.push("", "```sh", "# Example");
|
|
664
|
+
if (hasTypecheck) {
|
|
665
|
+
sections.push(runScript(packageManager, "typecheck"));
|
|
666
|
+
}
|
|
667
|
+
sections.push(
|
|
668
|
+
"# Run format and lint for only files modified",
|
|
669
|
+
commands.format,
|
|
670
|
+
commands.lint,
|
|
671
|
+
"```",
|
|
672
|
+
"",
|
|
673
|
+
"\u274C Avoid unless explicitly approved:",
|
|
674
|
+
"",
|
|
675
|
+
"```sh",
|
|
676
|
+
runScript(packageManager, "format"),
|
|
677
|
+
runScript(packageManager, "lint"),
|
|
678
|
+
"```",
|
|
679
|
+
""
|
|
680
|
+
);
|
|
681
|
+
return sections.join("\n");
|
|
682
|
+
}
|
|
683
|
+
function getAfterEditingCommands(ctx, files) {
|
|
684
|
+
return {
|
|
685
|
+
format: getFormatChangedFilesCommand(ctx, files),
|
|
686
|
+
lint: getLintChangedFilesCommand(ctx, files)
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function getFormatChangedFilesCommand(ctx, files) {
|
|
690
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
691
|
+
if (ctx.formatter === "prettier") {
|
|
692
|
+
const configPath = getPrettierConfigPath(ctx);
|
|
693
|
+
const ignorePath = getPrettierIgnorePath(ctx);
|
|
694
|
+
const configFlag2 = configPath == null ? "" : ` --config ${configPath}`;
|
|
695
|
+
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
696
|
+
return `${exec} prettier${configFlag2}${ignoreFlag} --write ${files}`;
|
|
697
|
+
}
|
|
698
|
+
if (ctx.formatter === "oxfmt") {
|
|
699
|
+
const configPath = getOxfmtConfigPath(ctx);
|
|
700
|
+
return `${exec} oxfmt -c ${configPath} --write ${files}`;
|
|
701
|
+
}
|
|
702
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
703
|
+
return `${exec} biome format${configFlag} --write ${files}`;
|
|
383
704
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
390
|
-
const config = JSON.parse(content);
|
|
391
|
-
if (config.formatter?.enabled !== false) return "biome";
|
|
392
|
-
} catch {
|
|
393
|
-
return "biome";
|
|
705
|
+
function getLintChangedFilesCommand(ctx, files) {
|
|
706
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
707
|
+
if (ctx.linter === "oxlint") {
|
|
708
|
+
if (!ctx.isMonorepo) {
|
|
709
|
+
return runScript(ctx.packageManager, "lint", files);
|
|
394
710
|
}
|
|
711
|
+
return `${exec} oxlint ${files}`;
|
|
395
712
|
}
|
|
396
|
-
|
|
713
|
+
if (ctx.linter === "eslint") {
|
|
714
|
+
const configFlag2 = ctx.configStrategy === "stealth" ? " --config .config/eslint.config.js" : "";
|
|
715
|
+
return `${exec} eslint${configFlag2} ${files}`;
|
|
716
|
+
}
|
|
717
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
718
|
+
return `${exec} biome lint${configFlag} ${files}`;
|
|
397
719
|
}
|
|
398
|
-
function
|
|
399
|
-
if (
|
|
400
|
-
if (
|
|
401
|
-
if (devDeps.eslint) return "eslint";
|
|
402
|
-
if (devDeps.oxlint) return "oxlint";
|
|
720
|
+
function getPrettierConfigPath(ctx) {
|
|
721
|
+
if (ctx.isMonorepo) return ".config/prettier/base.json";
|
|
722
|
+
if (ctx.configStrategy === "stealth") return ".config/prettier.json";
|
|
403
723
|
return void 0;
|
|
404
724
|
}
|
|
405
|
-
function
|
|
406
|
-
if (
|
|
407
|
-
if (
|
|
408
|
-
if (devDeps.prettier) return "prettier";
|
|
409
|
-
if (devDeps.oxfmt) return "oxfmt";
|
|
725
|
+
function getPrettierIgnorePath(ctx) {
|
|
726
|
+
if (ctx.isMonorepo) return ".config/prettier/prettierignore";
|
|
727
|
+
if (ctx.configStrategy === "stealth") return ".config/prettierignore";
|
|
410
728
|
return void 0;
|
|
411
729
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const pkg = JSON.parse(content);
|
|
417
|
-
const linter = detectLinterFromScript(pkg.scripts?.lint) ?? await detectLinterFromConfig(root) ?? detectLinterFromDeps(pkg.devDependencies);
|
|
418
|
-
const formatter = detectFormatterFromScript(pkg.scripts?.format) ?? await detectFormatterFromConfig(root) ?? detectFormatterFromDeps(pkg.devDependencies);
|
|
419
|
-
return { linter, formatter };
|
|
420
|
-
} catch {
|
|
421
|
-
return { linter: void 0, formatter: void 0 };
|
|
422
|
-
}
|
|
730
|
+
function getOxfmtConfigPath(ctx) {
|
|
731
|
+
if (ctx.isMonorepo) return ".config/oxfmt/base.json";
|
|
732
|
+
if (ctx.configStrategy === "stealth") return ".config/oxfmt.json";
|
|
733
|
+
return "oxfmt.json";
|
|
423
734
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const data = await response.json();
|
|
429
|
-
return data.version;
|
|
430
|
-
} catch {
|
|
431
|
-
return fallback;
|
|
735
|
+
function runScript(packageManager, script, args) {
|
|
736
|
+
const suffix = args == null ? "" : ` ${args}`;
|
|
737
|
+
if (packageManager === "npm") {
|
|
738
|
+
return `npm run ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
432
739
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
436
|
-
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
437
|
-
const maxLength = Math.max(aParts.length, bParts.length);
|
|
438
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
439
|
-
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
440
|
-
if (difference !== 0) {
|
|
441
|
-
return difference;
|
|
442
|
-
}
|
|
740
|
+
if (packageManager === "yarn") {
|
|
741
|
+
return `yarn ${script}${suffix}`;
|
|
443
742
|
}
|
|
444
|
-
return
|
|
445
|
-
}
|
|
446
|
-
function getLatestMatchingMajorVersion(versions, majorVersion) {
|
|
447
|
-
return [...versions].filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
|
|
743
|
+
return `${packageManager} ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
448
744
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
const latestMatchingVersion = getLatestMatchingMajorVersion(
|
|
454
|
-
Object.keys(data.versions ?? {}),
|
|
455
|
-
majorVersion
|
|
456
|
-
);
|
|
457
|
-
return latestMatchingVersion ?? fallback;
|
|
458
|
-
} catch {
|
|
459
|
-
return fallback;
|
|
460
|
-
}
|
|
745
|
+
function getExecCommand(packageManager) {
|
|
746
|
+
if (packageManager === "npm") return "npm exec --";
|
|
747
|
+
if (packageManager === "yarn") return "yarn exec";
|
|
748
|
+
return `${packageManager} exec`;
|
|
461
749
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
for (let major = requestedMajor; major >= 0; major -= 1) {
|
|
470
|
-
const latestMatchingVersion = getLatestMatchingMajorVersion(versions, String(major));
|
|
471
|
-
if (latestMatchingVersion != null) {
|
|
472
|
-
return latestMatchingVersion;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
750
|
+
|
|
751
|
+
async function checkAnyExists(paths) {
|
|
752
|
+
for (const path of paths) {
|
|
753
|
+
try {
|
|
754
|
+
await access(path, constants$1.F_OK);
|
|
755
|
+
return true;
|
|
756
|
+
} catch {
|
|
475
757
|
}
|
|
476
|
-
return fallback;
|
|
477
|
-
} catch {
|
|
478
|
-
return fallback;
|
|
479
758
|
}
|
|
759
|
+
return false;
|
|
480
760
|
}
|
|
481
|
-
async function
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
async function getLatestYarnVersion() {
|
|
485
|
-
return getLatestNpmVersion("yarn", "4.6.0");
|
|
486
|
-
}
|
|
487
|
-
async function getLatestNpmCliVersion() {
|
|
488
|
-
return getLatestNpmVersion("npm", "11.0.0");
|
|
489
|
-
}
|
|
490
|
-
async function getLatestNodeVersion() {
|
|
761
|
+
async function validateWorkspace(monorepoRoot) {
|
|
762
|
+
const errors = [];
|
|
763
|
+
const tsConfigPath = join(monorepoRoot, ".config/typescript/package.json");
|
|
491
764
|
try {
|
|
492
|
-
|
|
493
|
-
const data = await response.json();
|
|
494
|
-
const latestVersion = data[0];
|
|
495
|
-
if (latestVersion) {
|
|
496
|
-
return latestVersion.version.replace(/^v/, "");
|
|
497
|
-
}
|
|
498
|
-
return "25.0.0";
|
|
765
|
+
await access(tsConfigPath, constants$1.F_OK);
|
|
499
766
|
} catch {
|
|
500
|
-
|
|
767
|
+
errors.push("Missing .config/typescript package");
|
|
501
768
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
514
|
-
break;
|
|
515
|
-
}
|
|
516
|
-
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
517
|
-
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
518
|
-
if (entry && !entry.startsWith(".")) {
|
|
519
|
-
directories.push(entry);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
769
|
+
const linterPaths = [
|
|
770
|
+
join(monorepoRoot, ".config/oxlint/package.json"),
|
|
771
|
+
join(monorepoRoot, ".config/eslint/package.json"),
|
|
772
|
+
join(monorepoRoot, "eslint.config.js"),
|
|
773
|
+
join(monorepoRoot, "biome.json")
|
|
774
|
+
];
|
|
775
|
+
const hasLinter = await checkAnyExists(linterPaths);
|
|
776
|
+
if (!hasLinter) {
|
|
777
|
+
errors.push(
|
|
778
|
+
"Missing linter config (.config/oxlint, .config/eslint, eslint.config.js, or biome.json)"
|
|
779
|
+
);
|
|
522
780
|
}
|
|
523
|
-
|
|
781
|
+
const formatterPaths = [
|
|
782
|
+
join(monorepoRoot, ".config/oxfmt/package.json"),
|
|
783
|
+
join(monorepoRoot, ".config/prettier/package.json"),
|
|
784
|
+
join(monorepoRoot, ".prettierrc.json"),
|
|
785
|
+
join(monorepoRoot, "biome.json")
|
|
786
|
+
];
|
|
787
|
+
const hasFormatter = await checkAnyExists(formatterPaths);
|
|
788
|
+
if (!hasFormatter) {
|
|
789
|
+
errors.push(
|
|
790
|
+
"Missing formatter config (.config/oxfmt, .config/prettier, .prettierrc.json, or biome.json)"
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
return { valid: errors.length === 0, errors };
|
|
524
794
|
}
|
|
525
795
|
|
|
796
|
+
const gitAttributesContent = [
|
|
797
|
+
"* text eol=lf",
|
|
798
|
+
"*.png binary",
|
|
799
|
+
"*.jpg binary",
|
|
800
|
+
"*.jpeg binary",
|
|
801
|
+
"*.gif binary",
|
|
802
|
+
"*.ico binary",
|
|
803
|
+
"*.mov binary",
|
|
804
|
+
"*.mp4 binary",
|
|
805
|
+
"*.mp3 binary",
|
|
806
|
+
"*.flv binary",
|
|
807
|
+
"*.fla binary",
|
|
808
|
+
"*.wav binary",
|
|
809
|
+
"*.swf binary",
|
|
810
|
+
"*.gz binary",
|
|
811
|
+
"*.zip binary",
|
|
812
|
+
"*.7z binary",
|
|
813
|
+
"*.ttf binary",
|
|
814
|
+
"*.eot binary",
|
|
815
|
+
"*.woff binary",
|
|
816
|
+
"*.pyc binary",
|
|
817
|
+
"*.pdf binary",
|
|
818
|
+
"*.glb binary",
|
|
819
|
+
"*.gltf binary"
|
|
820
|
+
].join("\n");
|
|
821
|
+
|
|
526
822
|
const PACKAGE_VERSION_DEFINITIONS = {
|
|
527
823
|
"@babel/core": { fallbackVersion: "7.29.0" },
|
|
528
824
|
"@biomejs/biome": { fallbackVersion: "2.0.0" },
|
|
@@ -594,68 +890,6 @@ function formatResolvedPackageVersion(versions, packageName, prefix) {
|
|
|
594
890
|
function assignResolvedPackageVersion(target, versions, packageName, prefix) {
|
|
595
891
|
target[packageName] = formatResolvedPackageVersion(versions, packageName, prefix);
|
|
596
892
|
}
|
|
597
|
-
function getPackageManagerSpec(packageManager) {
|
|
598
|
-
return packageManager ?? { name: "pnpm" };
|
|
599
|
-
}
|
|
600
|
-
function getPackageManagerName(packageManager) {
|
|
601
|
-
return getPackageManagerSpec(packageManager).name;
|
|
602
|
-
}
|
|
603
|
-
function formatPackageManager(packageManager) {
|
|
604
|
-
const spec = getPackageManagerSpec(packageManager);
|
|
605
|
-
return spec.version ? `${spec.name}@${spec.version}` : spec.name;
|
|
606
|
-
}
|
|
607
|
-
function parsePackageManager(packageManager) {
|
|
608
|
-
if (packageManager == null || packageManager.length === 0) {
|
|
609
|
-
return void 0;
|
|
610
|
-
}
|
|
611
|
-
const atIndex = packageManager.indexOf("@");
|
|
612
|
-
if (atIndex === -1) {
|
|
613
|
-
return { name: packageManager };
|
|
614
|
-
}
|
|
615
|
-
return {
|
|
616
|
-
name: packageManager.slice(0, atIndex),
|
|
617
|
-
version: packageManager.slice(atIndex + 1)
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
function getEngineSpec(engine) {
|
|
621
|
-
return engine ?? { name: "node" };
|
|
622
|
-
}
|
|
623
|
-
function getEngineName(engine) {
|
|
624
|
-
return getEngineSpec(engine).name;
|
|
625
|
-
}
|
|
626
|
-
function parseEngine(engines) {
|
|
627
|
-
if (engines == null) {
|
|
628
|
-
return void 0;
|
|
629
|
-
}
|
|
630
|
-
const [name, range] = Object.entries(engines).find(
|
|
631
|
-
([engineName]) => engineName !== "npm" && engineName !== "pnpm" && engineName !== "yarn"
|
|
632
|
-
) ?? [];
|
|
633
|
-
if (name == null) {
|
|
634
|
-
return void 0;
|
|
635
|
-
}
|
|
636
|
-
const version = range?.match(/(\d+(?:\.\d+(?:\.\d+)?)?)/)?.[1];
|
|
637
|
-
return { name, version };
|
|
638
|
-
}
|
|
639
|
-
async function resolvePackageManager(options) {
|
|
640
|
-
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
641
|
-
if (packageManager.version == null) {
|
|
642
|
-
if (packageManager.name === "pnpm") {
|
|
643
|
-
packageManager.version = await getLatestPnpmVersion();
|
|
644
|
-
} else if (packageManager.name === "yarn") {
|
|
645
|
-
packageManager.version = await getLatestYarnVersion();
|
|
646
|
-
} else if (packageManager.name === "npm") {
|
|
647
|
-
packageManager.version = await getLatestNpmCliVersion();
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
return packageManager;
|
|
651
|
-
}
|
|
652
|
-
async function resolveEngine(options) {
|
|
653
|
-
const engine = getEngineSpec(options.engine);
|
|
654
|
-
if ((engine.version == null || engine.version === "latest") && engine.name === "node") {
|
|
655
|
-
engine.version = await getLatestNodeVersion();
|
|
656
|
-
}
|
|
657
|
-
return engine;
|
|
658
|
-
}
|
|
659
893
|
function formatNodeTypesVersion(versions = {}, _engine) {
|
|
660
894
|
const resolvedVersion = versions["@types/node"];
|
|
661
895
|
if (resolvedVersion != null) {
|
|
@@ -672,7 +906,7 @@ async function resolveNodeTypesVersion(engine, versions = {}) {
|
|
|
672
906
|
return void 0;
|
|
673
907
|
}
|
|
674
908
|
const nodeVersion = engineSpec.version ?? await getLatestNodeVersion();
|
|
675
|
-
const majorVersion = nodeVersion
|
|
909
|
+
const majorVersion = getSemverMajorString(nodeVersion);
|
|
676
910
|
return getLatestNpmMajorVersionAtOrBelow(
|
|
677
911
|
"@types/node",
|
|
678
912
|
majorVersion,
|
|
@@ -1195,12 +1429,12 @@ function renderPackageJson(params) {
|
|
|
1195
1429
|
if (!isMonorepoPackage) {
|
|
1196
1430
|
const engines = {};
|
|
1197
1431
|
if (packageManager.version != null) {
|
|
1198
|
-
const majorVersion = packageManager.version
|
|
1432
|
+
const majorVersion = getSemverMajorString(packageManager.version);
|
|
1199
1433
|
engines[packageManager.name] = `>=${majorVersion}.0.0`;
|
|
1200
1434
|
packageJson.packageManager = formatPackageManager(packageManager);
|
|
1201
1435
|
}
|
|
1202
1436
|
if (engine.version != null) {
|
|
1203
|
-
const majorVersion = engine.version
|
|
1437
|
+
const majorVersion = getSemverMajorString(engine.version);
|
|
1204
1438
|
engines[engine.name] = `>=${majorVersion}.0.0`;
|
|
1205
1439
|
}
|
|
1206
1440
|
if (Object.keys(engines).length > 0) {
|
|
@@ -1212,15 +1446,12 @@ function renderPackageJson(params) {
|
|
|
1212
1446
|
content: JSON.stringify(packageJson, null, 2)
|
|
1213
1447
|
};
|
|
1214
1448
|
if (isPnpm && !options.workspaceRoot) {
|
|
1215
|
-
const manageVersions = options.pnpmManageVersions ?? true;
|
|
1216
|
-
const workspaceLines = [];
|
|
1217
|
-
if (manageVersions) {
|
|
1218
|
-
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
1219
|
-
}
|
|
1220
|
-
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
1221
1449
|
files["pnpm-workspace.yaml"] = {
|
|
1222
1450
|
type: "text",
|
|
1223
|
-
content:
|
|
1451
|
+
content: renderPnpmWorkspaceConfig({
|
|
1452
|
+
profile: getPackageManagerProfile(packageManager),
|
|
1453
|
+
manageVersions: options.pnpmManageVersions ?? true
|
|
1454
|
+
})
|
|
1224
1455
|
};
|
|
1225
1456
|
}
|
|
1226
1457
|
return { files };
|
|
@@ -2369,12 +2600,12 @@ function renderMonorepo(params) {
|
|
|
2369
2600
|
};
|
|
2370
2601
|
const engines = {};
|
|
2371
2602
|
if (isPnpm && packageManager.version) {
|
|
2372
|
-
const majorVersion = packageManager.version
|
|
2603
|
+
const majorVersion = getSemverMajorString(packageManager.version);
|
|
2373
2604
|
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
2374
2605
|
rootPackageJson.packageManager = formatPackageManager(packageManager);
|
|
2375
2606
|
}
|
|
2376
2607
|
if (engine?.version) {
|
|
2377
|
-
const majorVersion = engine.version
|
|
2608
|
+
const majorVersion = getSemverMajorString(engine.version);
|
|
2378
2609
|
engines[engine.name] = `>=${majorVersion}.0.0`;
|
|
2379
2610
|
}
|
|
2380
2611
|
if (Object.keys(engines).length > 0) {
|
|
@@ -2385,15 +2616,13 @@ function renderMonorepo(params) {
|
|
|
2385
2616
|
content: JSON.stringify(rootPackageJson, null, 2)
|
|
2386
2617
|
};
|
|
2387
2618
|
if (isPnpm) {
|
|
2388
|
-
const workspaceLines = [];
|
|
2389
|
-
if (pnpmManageVersions) {
|
|
2390
|
-
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
2391
|
-
}
|
|
2392
|
-
workspaceLines.push("packages:", ' - ".config/*"', ' - "apps/*"', ' - "packages/*"', "");
|
|
2393
|
-
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
2394
2619
|
files["pnpm-workspace.yaml"] = {
|
|
2395
2620
|
type: "text",
|
|
2396
|
-
content:
|
|
2621
|
+
content: renderPnpmWorkspaceConfig({
|
|
2622
|
+
profile: getPackageManagerProfile(packageManager),
|
|
2623
|
+
manageVersions: pnpmManageVersions,
|
|
2624
|
+
packages: [".config/*", "apps/*", "packages/*"]
|
|
2625
|
+
})
|
|
2397
2626
|
};
|
|
2398
2627
|
}
|
|
2399
2628
|
files["tsconfig.json"] = {
|
|
@@ -3618,6 +3847,21 @@ async function resolveWorkspaceFacts(input) {
|
|
|
3618
3847
|
});
|
|
3619
3848
|
}
|
|
3620
3849
|
|
|
3850
|
+
function materializeJobs(jobs) {
|
|
3851
|
+
const files = {};
|
|
3852
|
+
for (const job of jobs) {
|
|
3853
|
+
if (job.type === "write-file") {
|
|
3854
|
+
files[job.path] = job.file;
|
|
3855
|
+
} else if (job.type === "merge-pnpm-workspace") {
|
|
3856
|
+
files[job.path] = {
|
|
3857
|
+
type: "text",
|
|
3858
|
+
content: job.content
|
|
3859
|
+
};
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
return files;
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3621
3865
|
async function planProject(input) {
|
|
3622
3866
|
const planInput = isProjectPlanInput(input) ? input : resolveProjectPlanInput(input);
|
|
3623
3867
|
return createProjectPlan(await resolveProjectFacts(planInput));
|
|
@@ -3896,8 +4140,13 @@ function createProjectPlan(planInput) {
|
|
|
3896
4140
|
platforms: planInput.aiAgents.config.platforms
|
|
3897
4141
|
});
|
|
3898
4142
|
}
|
|
4143
|
+
const jobs = Object.entries(files).map(([path, file]) => ({
|
|
4144
|
+
type: "write-file",
|
|
4145
|
+
path,
|
|
4146
|
+
file
|
|
4147
|
+
}));
|
|
3899
4148
|
return {
|
|
3900
|
-
files,
|
|
4149
|
+
files: materializeJobs(jobs),
|
|
3901
4150
|
dependencies,
|
|
3902
4151
|
devDependencies,
|
|
3903
4152
|
peerDependencies,
|
|
@@ -3925,8 +4174,13 @@ async function planWorkspace(input) {
|
|
|
3925
4174
|
const planInput = isWorkspacePlanInput(input) ? input : resolveWorkspacePlanInput(input);
|
|
3926
4175
|
const resolvedInput = await resolveWorkspaceFacts(planInput);
|
|
3927
4176
|
const { files } = renderMonorepo(workspacePlanInputToMonorepoParams(resolvedInput));
|
|
4177
|
+
const jobs = Object.entries(files).map(([path, file]) => ({
|
|
4178
|
+
type: "write-file",
|
|
4179
|
+
path,
|
|
4180
|
+
file
|
|
4181
|
+
}));
|
|
3928
4182
|
return {
|
|
3929
|
-
files,
|
|
4183
|
+
files: materializeJobs(jobs),
|
|
3930
4184
|
dependencies: {},
|
|
3931
4185
|
devDependencies: {},
|
|
3932
4186
|
peerDependencies: {},
|
|
@@ -3939,4 +4193,4 @@ async function planWorkspace(input) {
|
|
|
3939
4193
|
};
|
|
3940
4194
|
}
|
|
3941
4195
|
|
|
3942
|
-
export { ALL_AI_PLATFORMS as A,
|
|
4196
|
+
export { formatNodeTypesVersion as $, ALL_AI_PLATFORMS as A, renderGitignore as B, toPrettierIgnoreContent as C, mergePackageJsonScripts as D, getPackageManagerProfile as E, renderPnpmWorkspaceConfig as F, renderViteConfig as G, packageJsonScripts as H, resolveDefaultPackageJsonScripts as I, formatResolvedPackageVersion as J, getSemverMajorString as K, formatPackageManager as L, renderOxlintConfig as M, resolvePackageManager as N, getSemverMajor as O, compareNumericSemver as P, getPackageDirectoryName as Q, planProject as R, resolveProjectPlanInput as S, validatePackageName as T, clearConfig as U, getConfigPath as V, resolveWorkspacePlanInput as W, planWorkspace as X, DEFAULT_MINIMUM_RELEASE_AGE_MINUTES as Y, assignResolvedPackageVersion as Z, formatEngine as _, getPackageManagerName as a, getEngineSpec as a0, getLatestNodeVersion as a1, getLatestNpmCliVersion as a2, getLatestNpmMajorVersion as a3, getLatestNpmMajorVersionAtOrBelow as a4, getLatestNpmVersion as a5, getLatestPnpmVersion as a6, getLatestYarnVersion as a7, getPackageFallbackVersion as a8, getPackageManagerSpec as a9, isPackageManagerName as aa, materializeJobs as ab, merge as ac, projectPlanInputToOptions as ad, resolveEngine as ae, resolvePackageManagerProfile as af, resolvePackageVersions as ag, resolveProjectFacts as ah, resolveProjectPackageVersions as ai, resolveWorkspaceFacts as aj, setAiPlatforms as ak, setConfigStrategy as al, unique as am, workspacePlanInputToMonorepoParams as an, getBaseTemplate as b, getLanguageFromTemplate as c, generateRandomName as d, getConfigStrategy as e, getAiPlatforms as f, getEngineName as g, AI_PLATFORM_LABELS as h, AI_PLATFORM_HINTS as i, detectTooling as j, parseEngine as k, parseWorkspaceYamlContent as l, renderOxlintConfigPackage as m, renderEslintConfigPackage as n, renderOxfmtConfigPackage as o, parsePackageManagerSpec as p, renderPrettierConfigPackage as q, renderTypescriptConfigPackage as r, shouldEnableReactCompiler as s, resolveMonorepoRootPackageVersions as t, getResolvedPackageVersion as u, validateWorkspace as v, renderVscodeFiles as w, renderAiFiles as x, renderVscodeFiles$1 as y, renderEditorConfig as z };
|