create-krispya 0.15.0 → 0.17.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.
@@ -270,6 +270,7 @@ async function detectTooling(root) {
270
270
 
271
271
  const DEFAULT_MINIMUM_RELEASE_AGE_MINUTES = 1440;
272
272
  const MINUTE_IN_MS = 60 * 1e3;
273
+ const SEMVER_PATTERN = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
273
274
  function getMinimumReleaseAgeMinutes(options) {
274
275
  return Math.max(0, options?.minimumReleaseAgeMinutes ?? DEFAULT_MINIMUM_RELEASE_AGE_MINUTES);
275
276
  }
@@ -285,6 +286,62 @@ function isVersionOldEnough(version, time, options) {
285
286
  function getInstallableVersions(versions, time, options) {
286
287
  return [...versions].filter((version) => isVersionOldEnough(version, time, options));
287
288
  }
289
+ function parseSemver(version) {
290
+ const match = version.match(SEMVER_PATTERN);
291
+ if (match == null) return void 0;
292
+ return {
293
+ major: Number.parseInt(match[1], 10),
294
+ minor: Number.parseInt(match[2], 10),
295
+ patch: Number.parseInt(match[3], 10),
296
+ prerelease: match[4]?.split(".") ?? []
297
+ };
298
+ }
299
+ function hasPrerelease(version) {
300
+ return (parseSemver(version)?.prerelease.length ?? 0) > 0;
301
+ }
302
+ function comparePrerelease(aParts, bParts) {
303
+ if (aParts.length === 0 && bParts.length === 0) return 0;
304
+ if (aParts.length === 0) return 1;
305
+ if (bParts.length === 0) return -1;
306
+ const maxLength = Math.max(aParts.length, bParts.length);
307
+ for (let index = 0; index < maxLength; index += 1) {
308
+ const aPart = aParts[index];
309
+ const bPart = bParts[index];
310
+ if (aPart == null) return -1;
311
+ if (bPart == null) return 1;
312
+ if (aPart === bPart) continue;
313
+ const aNumber = /^\d+$/.test(aPart) ? Number.parseInt(aPart, 10) : void 0;
314
+ const bNumber = /^\d+$/.test(bPart) ? Number.parseInt(bPart, 10) : void 0;
315
+ if (aNumber != null && bNumber != null) return aNumber - bNumber;
316
+ if (aNumber != null) return -1;
317
+ if (bNumber != null) return 1;
318
+ return aPart.localeCompare(bPart);
319
+ }
320
+ return 0;
321
+ }
322
+ function compareSemver(a, b) {
323
+ const aParsed = parseSemver(a);
324
+ const bParsed = parseSemver(b);
325
+ if (aParsed == null || bParsed == null) {
326
+ return compareNumericSemver(a, b);
327
+ }
328
+ const majorDifference = aParsed.major - bParsed.major;
329
+ if (majorDifference !== 0) return majorDifference;
330
+ const minorDifference = aParsed.minor - bParsed.minor;
331
+ if (minorDifference !== 0) return minorDifference;
332
+ const patchDifference = aParsed.patch - bParsed.patch;
333
+ if (patchDifference !== 0) return patchDifference;
334
+ return comparePrerelease(aParsed.prerelease, bParsed.prerelease);
335
+ }
336
+ function getLatestChannelVersions(versions, latestVersion) {
337
+ const availableVersions = [...versions];
338
+ if (latestVersion == null) return availableVersions.filter((version) => !hasPrerelease(version));
339
+ const latestIsPrerelease = hasPrerelease(latestVersion);
340
+ return availableVersions.filter((version) => {
341
+ if (!latestIsPrerelease && hasPrerelease(version)) return false;
342
+ return compareSemver(version, latestVersion) <= 0;
343
+ });
344
+ }
288
345
  async function fetchNpmPackageMetadata(packageName) {
289
346
  const response = await fetch(`https://registry.npmjs.org/${packageName}`);
290
347
  return await response.json();
@@ -302,10 +359,10 @@ async function getLatestNpmVersion(packageName, fallback, options) {
302
359
  return latestVersion;
303
360
  }
304
361
  const latestInstallableVersion = getInstallableVersions(
305
- Object.keys(data.versions ?? {}),
362
+ getLatestChannelVersions(Object.keys(data.versions ?? {}), latestVersion),
306
363
  data.time,
307
364
  options
308
- ).sort((a, b) => compareNumericSemver(b, a))[0];
365
+ ).sort((a, b) => compareSemver(b, a))[0];
309
366
  return latestInstallableVersion ?? fallback;
310
367
  } catch {
311
368
  return fallback;
@@ -332,7 +389,7 @@ function compareNumericSemver(a, b) {
332
389
  return 0;
333
390
  }
334
391
  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];
392
+ return getInstallableVersions(versions, time, options).filter((version) => version.split(".")[0] === majorVersion).filter((version) => !hasPrerelease(version)).sort((a, b) => compareSemver(b, a))[0];
336
393
  }
337
394
  async function getLatestNpmMajorVersion(packageName, majorVersion, fallback, options) {
338
395
  try {
@@ -461,6 +518,9 @@ function getPnpmProfile(spec) {
461
518
  requirements: getPnpmRequirements(major)
462
519
  };
463
520
  }
521
+ function formatPnpmWorkspaceYamlKey(key) {
522
+ return key.startsWith("@") ? JSON.stringify(key) : key;
523
+ }
464
524
  function renderPnpmWorkspaceConfig(options) {
465
525
  const {
466
526
  profile,
@@ -482,7 +542,7 @@ function renderPnpmWorkspaceConfig(options) {
482
542
  if (profile.capabilities.pnpmBuildDependencyPolicy === "allowBuilds") {
483
543
  lines.push("allowBuilds:");
484
544
  for (const [dependency, allowed] of Object.entries(buildDependencies)) {
485
- lines.push(` ${dependency}: ${allowed ? "true" : "false"}`);
545
+ lines.push(` ${formatPnpmWorkspaceYamlKey(dependency)}: ${allowed ? "true" : "false"}`);
486
546
  }
487
547
  } else {
488
548
  const allowedDependencies = Object.entries(buildDependencies).filter(([, allowed]) => allowed).map(([dependency]) => dependency);
@@ -607,6 +667,8 @@ function getConfigPath() {
607
667
  }
608
668
 
609
669
  const ALL_AI_PLATFORMS = ["agents", "claude"];
670
+ const AI_FILE_MANAGED_BEGIN = "<!-- managed:start -->";
671
+ const AI_FILE_MANAGED_END = "<!-- managed:end -->";
610
672
  const AI_PLATFORM_LABELS = {
611
673
  agents: "AGENTS.md",
612
674
  claude: "CLAUDE.md"
@@ -618,12 +680,14 @@ const AI_PLATFORM_HINTS = {
618
680
  function renderAiFiles(files, params) {
619
681
  const { platforms, isMonorepo, configStrategy, hasTypecheck, ...rest } = params;
620
682
  if (platforms.length === 0) return;
621
- const content = generateWorkspace({
622
- ...rest,
623
- isMonorepo: !!isMonorepo,
624
- configStrategy: configStrategy ?? "stealth",
625
- hasTypecheck: hasTypecheck ?? false
626
- });
683
+ const content = renderManagedAiFileContent(
684
+ generateWorkspace({
685
+ ...rest,
686
+ isMonorepo: !!isMonorepo,
687
+ configStrategy: configStrategy ?? "stealth",
688
+ hasTypecheck: hasTypecheck ?? false
689
+ })
690
+ );
627
691
  const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
628
692
  const hasAgents = platforms.includes("agents");
629
693
  const hasClaude = platforms.includes("claude");
@@ -637,18 +701,89 @@ function renderAiFiles(files, params) {
637
701
  }
638
702
  }
639
703
  }
704
+ function renderManagedAiFileContent(content) {
705
+ return [AI_FILE_MANAGED_BEGIN, content.trimEnd(), AI_FILE_MANAGED_END, ""].join("\n");
706
+ }
707
+ function getManagedBlockRange$1(content) {
708
+ const beginIndex = content.indexOf(AI_FILE_MANAGED_BEGIN);
709
+ const endIndex = content.indexOf(AI_FILE_MANAGED_END);
710
+ if (beginIndex === -1 && endIndex === -1) {
711
+ return { status: "missing" };
712
+ }
713
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) {
714
+ return { status: "conflicted" };
715
+ }
716
+ return {
717
+ status: "found",
718
+ beginIndex,
719
+ endIndex: endIndex + AI_FILE_MANAGED_END.length
720
+ };
721
+ }
722
+ function getManagedInnerContent(content) {
723
+ const range = getManagedBlockRange$1(content);
724
+ if (range.status !== "found") return void 0;
725
+ return content.slice(
726
+ range.beginIndex + AI_FILE_MANAGED_BEGIN.length,
727
+ range.endIndex - AI_FILE_MANAGED_END.length
728
+ ).replace(/^\r?\n/, "").replace(/\r?\n$/, "");
729
+ }
730
+ function mergeMissingManagedAiBlock(currentContent, expectedContent, legacyContent) {
731
+ if (currentContent.trim() === "") return expectedContent;
732
+ if (legacyContent != null && currentContent.startsWith(legacyContent)) {
733
+ const suffix = currentContent.slice(legacyContent.length);
734
+ return suffix === "" ? expectedContent : `${expectedContent.trimEnd()}${suffix}`;
735
+ }
736
+ return `${expectedContent.trimEnd()}
737
+
738
+ ${currentContent.trim()}
739
+ `;
740
+ }
741
+ function isManagedAiFilePath(path) {
742
+ return path === "AGENTS.md" || path === "CLAUDE.md";
743
+ }
744
+ function mergeAiFileContent(currentContent, expectedContent) {
745
+ if (!expectedContent.includes(AI_FILE_MANAGED_BEGIN)) {
746
+ return {
747
+ content: expectedContent,
748
+ mergeSafe: false
749
+ };
750
+ }
751
+ const range = getManagedBlockRange$1(currentContent);
752
+ if (range.status === "found") {
753
+ return {
754
+ content: `${currentContent.slice(0, range.beginIndex)}${expectedContent.trimEnd()}${currentContent.slice(
755
+ range.endIndex
756
+ )}`,
757
+ mergeSafe: true
758
+ };
759
+ }
760
+ if (range.status === "conflicted") {
761
+ return {
762
+ content: expectedContent,
763
+ mergeSafe: false
764
+ };
765
+ }
766
+ return {
767
+ content: mergeMissingManagedAiBlock(
768
+ currentContent,
769
+ expectedContent,
770
+ getManagedInnerContent(expectedContent)
771
+ ),
772
+ mergeSafe: true
773
+ };
774
+ }
640
775
  function generateWorkspace(ctx) {
641
776
  const { packageManager, linter, formatter, hasTypecheck } = ctx;
642
777
  const exampleFiles = "src/App.tsx src/core/systems/move-entity.ts";
643
778
  const commands = getAfterEditingCommands(ctx, exampleFiles);
644
779
  const sections = [
645
- "# Workspace Tools",
780
+ "## Workspace Tools",
646
781
  "",
647
782
  `- **Package Manager:** ${packageManager}`,
648
783
  `- **Linter:** ${linter}`,
649
784
  `- **Formatter:** ${formatter}`,
650
785
  "",
651
- "## After Editing",
786
+ "### After Editing",
652
787
  ""
653
788
  ];
654
789
  if (hasTypecheck) {
@@ -1104,6 +1239,54 @@ function isEnabledOption(option) {
1104
1239
  return option != null && option !== false;
1105
1240
  }
1106
1241
 
1242
+ function renderJson(value, options = {}) {
1243
+ const json = JSON.stringify(value, null, 2);
1244
+ const content = options.inlineArrays === false ? json : inlinePrimitiveArrays(json, options);
1245
+ return `${content}
1246
+ `;
1247
+ }
1248
+ function inlinePrimitiveArrays(json, options) {
1249
+ const printWidth = options.printWidth ?? 102;
1250
+ const lines = json.split("\n");
1251
+ const output = [];
1252
+ for (let index = 0; index < lines.length; index++) {
1253
+ const line = lines[index];
1254
+ const openIndex = line.indexOf("[");
1255
+ if (openIndex === -1 || line.slice(openIndex).trim() !== "[") {
1256
+ output.push(line);
1257
+ continue;
1258
+ }
1259
+ const items = [];
1260
+ let cursor = index + 1;
1261
+ let closingComma = "";
1262
+ for (; cursor < lines.length; cursor++) {
1263
+ const item = lines[cursor].trim();
1264
+ const closingMatch = item.match(/^\](,?)$/);
1265
+ if (closingMatch) {
1266
+ closingComma = closingMatch[1] ?? "";
1267
+ break;
1268
+ }
1269
+ if (!/^(?:"(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?|true|false|null),?$/.test(item)) {
1270
+ items.length = 0;
1271
+ break;
1272
+ }
1273
+ items.push(item.replace(/,$/, ""));
1274
+ }
1275
+ if (items.length === 0 || cursor >= lines.length) {
1276
+ output.push(line);
1277
+ continue;
1278
+ }
1279
+ const nextLine = `${line.slice(0, openIndex)}[${items.join(", ")}]${closingComma}`;
1280
+ if (nextLine.length > printWidth) {
1281
+ output.push(line);
1282
+ continue;
1283
+ }
1284
+ output.push(nextLine);
1285
+ index = cursor;
1286
+ }
1287
+ return output.join("\n");
1288
+ }
1289
+
1107
1290
  function renderTypescriptConfig(baseTemplateOrParams) {
1108
1291
  const params = typeof baseTemplateOrParams === "string" ? { baseTemplate: baseTemplateOrParams } : baseTemplateOrParams;
1109
1292
  const {
@@ -1135,15 +1318,11 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1135
1318
  const baseConfig = isReact || isR3f ? "@config/typescript/react.json" : "@config/typescript/app.json";
1136
1319
  files["tsconfig.json"] = {
1137
1320
  type: "text",
1138
- content: JSON.stringify(
1139
- {
1140
- $schema: "https://json.schemastore.org/tsconfig",
1141
- extends: baseConfig,
1142
- include: ["src/**/*", "tests/**/*"]
1143
- },
1144
- null,
1145
- 2
1146
- )
1321
+ content: renderJson({
1322
+ $schema: "https://json.schemastore.org/tsconfig",
1323
+ extends: baseConfig,
1324
+ include: ["src/**/*", "tests/**/*"]
1325
+ })
1147
1326
  };
1148
1327
  return { files, devDependencies };
1149
1328
  }
@@ -1155,7 +1334,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1155
1334
  };
1156
1335
  files["tsconfig.json"] = {
1157
1336
  type: "text",
1158
- content: JSON.stringify(tsConfig, null, 2)
1337
+ content: renderJson(tsConfig)
1159
1338
  };
1160
1339
  const tsConfigApp = {
1161
1340
  $schema: "https://json.schemastore.org/tsconfig",
@@ -1178,7 +1357,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1178
1357
  };
1179
1358
  files[".config/tsconfig.app.json"] = {
1180
1359
  type: "text",
1181
- content: JSON.stringify(tsConfigApp, null, 2)
1360
+ content: renderJson(tsConfigApp)
1182
1361
  };
1183
1362
  const tsConfigNode = {
1184
1363
  $schema: "https://json.schemastore.org/tsconfig",
@@ -1200,7 +1379,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1200
1379
  };
1201
1380
  files[".config/tsconfig.node.json"] = {
1202
1381
  type: "text",
1203
- content: JSON.stringify(tsConfigNode, null, 2)
1382
+ content: renderJson(tsConfigNode)
1204
1383
  };
1205
1384
  } else {
1206
1385
  const tsConfig = {
@@ -1210,7 +1389,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1210
1389
  };
1211
1390
  files["tsconfig.json"] = {
1212
1391
  type: "text",
1213
- content: JSON.stringify(tsConfig, null, 2)
1392
+ content: renderJson(tsConfig)
1214
1393
  };
1215
1394
  const tsConfigApp = {
1216
1395
  $schema: "https://json.schemastore.org/tsconfig",
@@ -1233,7 +1412,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1233
1412
  };
1234
1413
  files["tsconfig.app.json"] = {
1235
1414
  type: "text",
1236
- content: JSON.stringify(tsConfigApp, null, 2)
1415
+ content: renderJson(tsConfigApp)
1237
1416
  };
1238
1417
  const tsConfigNode = {
1239
1418
  $schema: "https://json.schemastore.org/tsconfig",
@@ -1255,7 +1434,7 @@ function renderTypescriptConfig(baseTemplateOrParams) {
1255
1434
  };
1256
1435
  files["tsconfig.node.json"] = {
1257
1436
  type: "text",
1258
- content: JSON.stringify(tsConfigNode, null, 2)
1437
+ content: renderJson(tsConfigNode)
1259
1438
  };
1260
1439
  }
1261
1440
  return { files, devDependencies };
@@ -1443,7 +1622,7 @@ function renderPackageJson(params) {
1443
1622
  }
1444
1623
  files["package.json"] = {
1445
1624
  type: "text",
1446
- content: JSON.stringify(packageJson, null, 2)
1625
+ content: renderJson(packageJson, { inlineArrays: false })
1447
1626
  };
1448
1627
  if (isPnpm && !options.workspaceRoot) {
1449
1628
  files["pnpm-workspace.yaml"] = {
@@ -1815,6 +1994,8 @@ function renderTestFiles(params) {
1815
1994
  return files;
1816
1995
  }
1817
1996
 
1997
+ const GITIGNORE_MANAGED_BEGIN = "# managed:start";
1998
+ const GITIGNORE_MANAGED_END = "# managed:end";
1818
1999
  const COMMON_GITIGNORE_LINES = [
1819
2000
  "node_modules",
1820
2001
  "dist",
@@ -1824,13 +2005,77 @@ const COMMON_GITIGNORE_LINES = [
1824
2005
  "!.env.example",
1825
2006
  ".pnpm-store"
1826
2007
  ];
2008
+ function getCoreGitignoreLines(variant) {
2009
+ return variant === "workspace-root" ? [...COMMON_GITIGNORE_LINES, ".DS_Store"] : COMMON_GITIGNORE_LINES;
2010
+ }
2011
+ function renderManagedGitignoreBlock(variant) {
2012
+ return [GITIGNORE_MANAGED_BEGIN, ...getCoreGitignoreLines(variant), GITIGNORE_MANAGED_END].join(
2013
+ "\n"
2014
+ );
2015
+ }
1827
2016
  function renderGitignore(variant) {
1828
- const lines = variant === "workspace-root" ? [...COMMON_GITIGNORE_LINES, ".DS_Store"] : COMMON_GITIGNORE_LINES;
1829
2017
  return {
1830
2018
  type: "text",
1831
- content: lines.join("\n")
2019
+ content: renderManagedGitignoreBlock(variant)
1832
2020
  };
1833
2021
  }
2022
+ function getManagedBlockRange(content) {
2023
+ const beginIndex = content.indexOf(GITIGNORE_MANAGED_BEGIN);
2024
+ const endIndex = content.indexOf(GITIGNORE_MANAGED_END);
2025
+ if (beginIndex === -1 && endIndex === -1) {
2026
+ return { status: "missing" };
2027
+ }
2028
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) {
2029
+ return { status: "conflicted" };
2030
+ }
2031
+ return {
2032
+ status: "found",
2033
+ beginIndex,
2034
+ endIndex: endIndex + GITIGNORE_MANAGED_END.length
2035
+ };
2036
+ }
2037
+ function trimBlankEdges(lines) {
2038
+ let start = 0;
2039
+ let end = lines.length;
2040
+ while (start < end && lines[start]?.trim() === "") {
2041
+ start++;
2042
+ }
2043
+ while (end > start && lines[end - 1]?.trim() === "") {
2044
+ end--;
2045
+ }
2046
+ return lines.slice(start, end);
2047
+ }
2048
+ function mergeGitignoreContent(currentContent, variant) {
2049
+ const managedBlock = renderManagedGitignoreBlock(variant);
2050
+ const range = getManagedBlockRange(currentContent);
2051
+ if (range.status === "found") {
2052
+ return {
2053
+ content: `${currentContent.slice(0, range.beginIndex)}${managedBlock}${currentContent.slice(
2054
+ range.endIndex
2055
+ )}`,
2056
+ mergeSafe: true
2057
+ };
2058
+ }
2059
+ if (range.status === "conflicted") {
2060
+ return {
2061
+ content: managedBlock,
2062
+ mergeSafe: false
2063
+ };
2064
+ }
2065
+ const coreLines = new Set(getCoreGitignoreLines(variant));
2066
+ const customLines = trimBlankEdges(
2067
+ currentContent.split(/\r?\n/).filter((line) => !coreLines.has(line.trim()))
2068
+ );
2069
+ return {
2070
+ content: customLines.length > 0 ? `${managedBlock}
2071
+
2072
+ ${customLines.join("\n")}` : managedBlock,
2073
+ mergeSafe: true
2074
+ };
2075
+ }
2076
+ function detectGitignoreVariant(content) {
2077
+ return content.split(/\r?\n/).includes(".DS_Store") ? "workspace-root" : "standalone";
2078
+ }
1834
2079
 
1835
2080
  const defaultFormatterMetaConfig = {
1836
2081
  printWidth: 102,
@@ -1842,6 +2087,8 @@ const defaultFormatterMetaConfig = {
1842
2087
  bracketSpacing: true,
1843
2088
  arrowParens: "always",
1844
2089
  ignorePatterns: [
2090
+ "dist/",
2091
+ "**/dist/",
1845
2092
  "package-lock.json",
1846
2093
  "npm-shrinkwrap.json",
1847
2094
  "pnpm-lock.yaml",
@@ -2001,13 +2248,9 @@ function renderVscodeFiles$1(params) {
2001
2248
  const uniqueRecommendations = [...new Set(recommendations)];
2002
2249
  files[".vscode/extensions.json"] = {
2003
2250
  type: "text",
2004
- content: JSON.stringify(
2005
- {
2006
- recommendations: uniqueRecommendations
2007
- },
2008
- null,
2009
- 2
2010
- )
2251
+ content: renderJson({
2252
+ recommendations: uniqueRecommendations
2253
+ })
2011
2254
  };
2012
2255
  }
2013
2256
  const resolvedSettings = {
@@ -2020,7 +2263,7 @@ function renderVscodeFiles$1(params) {
2020
2263
  );
2021
2264
  files[".vscode/settings.json"] = {
2022
2265
  type: "text",
2023
- content: JSON.stringify(sortedSettings, null, 2)
2266
+ content: renderJson(sortedSettings)
2024
2267
  };
2025
2268
  }
2026
2269
  return files;
@@ -2195,15 +2438,14 @@ function renderTypescriptConfigPackage(files) {
2195
2438
  const basePath = ".config/typescript";
2196
2439
  files[`${basePath}/package.json`] = {
2197
2440
  type: "text",
2198
- content: JSON.stringify(
2441
+ content: renderJson(
2199
2442
  {
2200
2443
  name: "@config/typescript",
2201
2444
  version: "0.1.0",
2202
2445
  private: true,
2203
2446
  files: ["base.json", "app.json", "node.json", "react.json"]
2204
2447
  },
2205
- null,
2206
- 2
2448
+ { inlineArrays: false }
2207
2449
  )
2208
2450
  };
2209
2451
  files[`${basePath}/README.md`] = {
@@ -2233,82 +2475,65 @@ In your package's \`tsconfig.json\`:
2233
2475
  };
2234
2476
  files[`${basePath}/base.json`] = {
2235
2477
  type: "text",
2236
- content: JSON.stringify(
2237
- {
2238
- $schema: "https://json.schemastore.org/tsconfig",
2239
- compilerOptions: {
2240
- target: "ESNext",
2241
- module: "ESNext",
2242
- moduleResolution: "bundler",
2243
- esModuleInterop: true,
2244
- allowSyntheticDefaultImports: true,
2245
- strict: true,
2246
- skipLibCheck: true,
2247
- composite: true,
2248
- rewriteRelativeImportExtensions: true,
2249
- erasableSyntaxOnly: true
2250
- }
2251
- },
2252
- null,
2253
- 2
2254
- )
2478
+ content: renderJson({
2479
+ $schema: "https://json.schemastore.org/tsconfig",
2480
+ compilerOptions: {
2481
+ target: "ESNext",
2482
+ module: "ESNext",
2483
+ moduleResolution: "bundler",
2484
+ esModuleInterop: true,
2485
+ allowSyntheticDefaultImports: true,
2486
+ strict: true,
2487
+ skipLibCheck: true,
2488
+ composite: true,
2489
+ rewriteRelativeImportExtensions: true,
2490
+ erasableSyntaxOnly: true
2491
+ }
2492
+ })
2255
2493
  };
2256
2494
  files[`${basePath}/app.json`] = {
2257
2495
  type: "text",
2258
- content: JSON.stringify(
2259
- {
2260
- $schema: "https://json.schemastore.org/tsconfig",
2261
- extends: "./base.json",
2262
- compilerOptions: {
2263
- lib: ["DOM", "DOM.Iterable", "ESNext"]
2264
- }
2265
- },
2266
- null,
2267
- 2
2268
- )
2496
+ content: renderJson({
2497
+ $schema: "https://json.schemastore.org/tsconfig",
2498
+ extends: "./base.json",
2499
+ compilerOptions: {
2500
+ lib: ["DOM", "DOM.Iterable", "ESNext"]
2501
+ }
2502
+ })
2269
2503
  };
2270
2504
  files[`${basePath}/node.json`] = {
2271
2505
  type: "text",
2272
- content: JSON.stringify(
2273
- {
2274
- $schema: "https://json.schemastore.org/tsconfig",
2275
- extends: "./base.json",
2276
- compilerOptions: {
2277
- lib: ["ESNext"]
2278
- }
2279
- },
2280
- null,
2281
- 2
2282
- )
2506
+ content: renderJson({
2507
+ $schema: "https://json.schemastore.org/tsconfig",
2508
+ extends: "./base.json",
2509
+ compilerOptions: {
2510
+ lib: ["ESNext"]
2511
+ }
2512
+ })
2283
2513
  };
2284
2514
  files[`${basePath}/react.json`] = {
2285
2515
  type: "text",
2286
- content: JSON.stringify(
2287
- {
2288
- $schema: "https://json.schemastore.org/tsconfig",
2289
- extends: "./app.json",
2290
- compilerOptions: {
2291
- jsx: "react-jsx"
2292
- }
2293
- },
2294
- null,
2295
- 2
2296
- )
2516
+ content: renderJson({
2517
+ $schema: "https://json.schemastore.org/tsconfig",
2518
+ extends: "./app.json",
2519
+ compilerOptions: {
2520
+ jsx: "react-jsx"
2521
+ }
2522
+ })
2297
2523
  };
2298
2524
  }
2299
2525
  function renderOxlintConfigPackage(files) {
2300
2526
  const basePath = ".config/oxlint";
2301
2527
  files[`${basePath}/package.json`] = {
2302
2528
  type: "text",
2303
- content: JSON.stringify(
2529
+ content: renderJson(
2304
2530
  {
2305
2531
  name: "@config/oxlint",
2306
2532
  version: "0.1.0",
2307
2533
  private: true,
2308
2534
  files: ["base.json", "react.json"]
2309
2535
  },
2310
- null,
2311
- 2
2536
+ { inlineArrays: false }
2312
2537
  )
2313
2538
  };
2314
2539
  files[`${basePath}/README.md`] = {
@@ -2333,25 +2558,21 @@ oxlint -c node_modules/@config/oxlint/base.json
2333
2558
  };
2334
2559
  files[`${basePath}/base.json`] = {
2335
2560
  type: "text",
2336
- content: JSON.stringify(
2561
+ content: renderJson(
2337
2562
  renderOxlintConfig({
2338
2563
  schemaPath: "./node_modules/oxlint/configuration_schema.json",
2339
2564
  typescript: true
2340
- }),
2341
- null,
2342
- 2
2565
+ })
2343
2566
  )
2344
2567
  };
2345
2568
  files[`${basePath}/react.json`] = {
2346
2569
  type: "text",
2347
- content: JSON.stringify(
2570
+ content: renderJson(
2348
2571
  renderOxlintConfig({
2349
2572
  schemaPath: "./node_modules/oxlint/configuration_schema.json",
2350
2573
  react: true,
2351
2574
  typescript: true
2352
- }),
2353
- null,
2354
- 2
2575
+ })
2355
2576
  )
2356
2577
  };
2357
2578
  }
@@ -2359,7 +2580,7 @@ function renderEslintConfigPackage(files) {
2359
2580
  const basePath = ".config/eslint";
2360
2581
  files[`${basePath}/package.json`] = {
2361
2582
  type: "text",
2362
- content: JSON.stringify(
2583
+ content: renderJson(
2363
2584
  {
2364
2585
  name: "@config/eslint",
2365
2586
  version: "0.1.0",
@@ -2375,8 +2596,7 @@ function renderEslintConfigPackage(files) {
2375
2596
  "typescript-eslint": "^8.18.0"
2376
2597
  }
2377
2598
  },
2378
- null,
2379
- 2
2599
+ { inlineArrays: false }
2380
2600
  )
2381
2601
  };
2382
2602
  files[`${basePath}/README.md`] = {
@@ -2411,52 +2631,52 @@ export default [...react];
2411
2631
  };
2412
2632
  files[`${basePath}/base.js`] = {
2413
2633
  type: "text",
2414
- content: `import js from "@eslint/js";
2415
- import tseslint from "typescript-eslint";
2634
+ content: `import js from '@eslint/js';
2635
+ import tseslint from 'typescript-eslint';
2416
2636
 
2417
2637
  export default tseslint.config(
2418
2638
  js.configs.recommended,
2419
2639
  ...tseslint.configs.recommended,
2420
2640
  {
2421
2641
  rules: {
2422
- "@typescript-eslint/no-unused-vars": [
2423
- "error",
2642
+ '@typescript-eslint/no-unused-vars': [
2643
+ 'error',
2424
2644
  {
2425
- argsIgnorePattern: "^_",
2426
- varsIgnorePattern: "^_",
2427
- caughtErrorsIgnorePattern: "^_",
2645
+ argsIgnorePattern: '^_',
2646
+ varsIgnorePattern: '^_',
2647
+ caughtErrorsIgnorePattern: '^_',
2428
2648
  },
2429
2649
  ],
2430
2650
  },
2431
2651
  },
2432
2652
  {
2433
- ignores: ["dist/**", "node_modules/**"],
2653
+ ignores: ['dist/**', 'node_modules/**'],
2434
2654
  }
2435
2655
  );
2436
2656
  `
2437
2657
  };
2438
2658
  files[`${basePath}/react.js`] = {
2439
2659
  type: "text",
2440
- content: `import js from "@eslint/js";
2441
- import tseslint from "typescript-eslint";
2660
+ content: `import js from '@eslint/js';
2661
+ import tseslint from 'typescript-eslint';
2442
2662
 
2443
2663
  export default tseslint.config(
2444
2664
  js.configs.recommended,
2445
2665
  ...tseslint.configs.recommended,
2446
2666
  {
2447
2667
  rules: {
2448
- "@typescript-eslint/no-unused-vars": [
2449
- "error",
2668
+ '@typescript-eslint/no-unused-vars': [
2669
+ 'error',
2450
2670
  {
2451
- argsIgnorePattern: "^_",
2452
- varsIgnorePattern: "^_",
2453
- caughtErrorsIgnorePattern: "^_",
2671
+ argsIgnorePattern: '^_',
2672
+ varsIgnorePattern: '^_',
2673
+ caughtErrorsIgnorePattern: '^_',
2454
2674
  },
2455
2675
  ],
2456
2676
  },
2457
2677
  },
2458
2678
  {
2459
- ignores: ["dist/**", "node_modules/**"],
2679
+ ignores: ['dist/**', 'node_modules/**'],
2460
2680
  }
2461
2681
  );
2462
2682
  `
@@ -2466,7 +2686,7 @@ function renderPrettierConfigPackage(files) {
2466
2686
  const basePath = ".config/prettier";
2467
2687
  files[`${basePath}/package.json`] = {
2468
2688
  type: "text",
2469
- content: JSON.stringify(
2689
+ content: renderJson(
2470
2690
  {
2471
2691
  name: "@config/prettier",
2472
2692
  version: "0.1.0",
@@ -2477,8 +2697,7 @@ function renderPrettierConfigPackage(files) {
2477
2697
  },
2478
2698
  files: ["base.json", "prettierignore"]
2479
2699
  },
2480
- null,
2481
- 2
2700
+ { inlineArrays: false }
2482
2701
  )
2483
2702
  };
2484
2703
  files[`${basePath}/README.md`] = {
@@ -2510,7 +2729,7 @@ Or in \`.prettierrc.json\`:
2510
2729
  };
2511
2730
  files[`${basePath}/base.json`] = {
2512
2731
  type: "text",
2513
- content: JSON.stringify(toPrettierConfig(), null, 2)
2732
+ content: renderJson(toPrettierConfig())
2514
2733
  };
2515
2734
  files[`${basePath}/prettierignore`] = {
2516
2735
  type: "text",
@@ -2521,15 +2740,14 @@ function renderOxfmtConfigPackage(files) {
2521
2740
  const basePath = ".config/oxfmt";
2522
2741
  files[`${basePath}/package.json`] = {
2523
2742
  type: "text",
2524
- content: JSON.stringify(
2743
+ content: renderJson(
2525
2744
  {
2526
2745
  name: "@config/oxfmt",
2527
2746
  version: "0.1.0",
2528
2747
  private: true,
2529
2748
  files: ["base.json"]
2530
2749
  },
2531
- null,
2532
- 2
2750
+ { inlineArrays: false }
2533
2751
  )
2534
2752
  };
2535
2753
  files[`${basePath}/README.md`] = {
@@ -2553,7 +2771,7 @@ oxfmt -c node_modules/@config/oxfmt/base.json --write .
2553
2771
  };
2554
2772
  files[`${basePath}/base.json`] = {
2555
2773
  type: "text",
2556
- content: JSON.stringify(toOxfmtConfig(), null, 2)
2774
+ content: renderJson(toOxfmtConfig())
2557
2775
  };
2558
2776
  }
2559
2777
 
@@ -2613,7 +2831,7 @@ function renderMonorepo(params) {
2613
2831
  }
2614
2832
  files["package.json"] = {
2615
2833
  type: "text",
2616
- content: JSON.stringify(rootPackageJson, null, 2)
2834
+ content: renderJson(rootPackageJson, { inlineArrays: false })
2617
2835
  };
2618
2836
  if (isPnpm) {
2619
2837
  files["pnpm-workspace.yaml"] = {
@@ -2683,7 +2901,7 @@ export default [...base];
2683
2901
  };
2684
2902
  files["biome.json"] = {
2685
2903
  type: "text",
2686
- content: JSON.stringify(biomeConfig, null, 2)
2904
+ content: renderJson(biomeConfig)
2687
2905
  };
2688
2906
  }
2689
2907
  if (formatter === "oxfmt") {
@@ -2813,7 +3031,7 @@ function planBiome(builder, options) {
2813
3031
  if (isStealth) {
2814
3032
  builder.addFile(".config/biome.json", {
2815
3033
  type: "text",
2816
- content: JSON.stringify(biomeConfig, null, 2)
3034
+ content: renderJson(biomeConfig)
2817
3035
  });
2818
3036
  if (options.linter) {
2819
3037
  builder.addScripts(packageJsonScripts.lint.biome(".config"));
@@ -2824,7 +3042,7 @@ function planBiome(builder, options) {
2824
3042
  } else {
2825
3043
  builder.addFile("biome.json", {
2826
3044
  type: "text",
2827
- content: JSON.stringify(biomeConfig, null, 2)
3045
+ content: renderJson(biomeConfig)
2828
3046
  });
2829
3047
  if (options.linter) {
2830
3048
  builder.addScripts(packageJsonScripts.lint.biome());
@@ -3101,13 +3319,13 @@ function planOxfmt(builder, options) {
3101
3319
  if (isStealth) {
3102
3320
  builder.addFile(".config/oxfmt.json", {
3103
3321
  type: "text",
3104
- content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
3322
+ content: renderJson(toOxfmtConfig(options.config))
3105
3323
  });
3106
3324
  builder.addScripts(packageJsonScripts.format.oxfmt(".config/oxfmt.json"));
3107
3325
  } else {
3108
3326
  builder.addFile("oxfmt.json", {
3109
3327
  type: "text",
3110
- content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
3328
+ content: renderJson(toOxfmtConfig(options.config))
3111
3329
  });
3112
3330
  builder.addScripts(packageJsonScripts.format.oxfmt("oxfmt.json"));
3113
3331
  }
@@ -3152,13 +3370,13 @@ function planOxlint(builder, options) {
3152
3370
  if (isStealth) {
3153
3371
  builder.addFile(".config/oxlint.json", {
3154
3372
  type: "text",
3155
- content: JSON.stringify(oxlintConfig, null, 2)
3373
+ content: renderJson(oxlintConfig)
3156
3374
  });
3157
3375
  builder.addScripts(packageJsonScripts.lint.oxlint(".config/oxlint.json"));
3158
3376
  } else {
3159
3377
  builder.addFile("oxlint.json", {
3160
3378
  type: "text",
3161
- content: JSON.stringify(oxlintConfig, null, 2)
3379
+ content: renderJson(oxlintConfig)
3162
3380
  });
3163
3381
  builder.addScripts(packageJsonScripts.lint.oxlint());
3164
3382
  }
@@ -3197,7 +3415,7 @@ function planPrettier(builder, options) {
3197
3415
  if (isStealth) {
3198
3416
  builder.addFile(".config/prettier.json", {
3199
3417
  type: "text",
3200
- content: JSON.stringify(toPrettierConfig(options.config), null, 2)
3418
+ content: renderJson(toPrettierConfig(options.config))
3201
3419
  });
3202
3420
  builder.addFile(".config/prettierignore", {
3203
3421
  type: "text",
@@ -3209,7 +3427,7 @@ function planPrettier(builder, options) {
3209
3427
  } else {
3210
3428
  builder.addFile(".prettierrc", {
3211
3429
  type: "text",
3212
- content: JSON.stringify(toPrettierConfig(options.config), null, 2)
3430
+ content: renderJson(toPrettierConfig(options.config))
3213
3431
  });
3214
3432
  builder.addFile(".prettierignore", {
3215
3433
  type: "text",
@@ -4193,4 +4411,4 @@ async function planWorkspace(input) {
4193
4411
  };
4194
4412
  }
4195
4413
 
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 };
4414
+ export { resolveWorkspacePlanInput as $, ALL_AI_PLATFORMS as A, renderEditorConfig as B, renderGitignore as C, toPrettierIgnoreContent as D, mergePackageJsonScripts as E, getPackageManagerProfile as F, renderPnpmWorkspaceConfig as G, renderViteConfig as H, mergeGitignoreContent as I, detectGitignoreVariant as J, isManagedAiFilePath as K, mergeAiFileContent as L, packageJsonScripts as M, resolveDefaultPackageJsonScripts as N, formatResolvedPackageVersion as O, getSemverMajorString as P, formatPackageManager as Q, renderOxlintConfig as R, resolvePackageManager as S, getSemverMajor as T, compareNumericSemver as U, getPackageDirectoryName as V, planProject as W, resolveProjectPlanInput as X, validatePackageName as Y, clearConfig as Z, getConfigPath as _, getPackageManagerName as a, planWorkspace as a0, DEFAULT_MINIMUM_RELEASE_AGE_MINUTES as a1, assignResolvedPackageVersion as a2, formatEngine as a3, formatNodeTypesVersion as a4, getEngineSpec as a5, getLatestNodeVersion as a6, getLatestNpmCliVersion as a7, getLatestNpmMajorVersion as a8, getLatestNpmMajorVersionAtOrBelow as a9, getLatestNpmVersion as aa, getLatestPnpmVersion as ab, getLatestYarnVersion as ac, getPackageFallbackVersion as ad, getPackageManagerSpec as ae, isPackageManagerName as af, materializeJobs as ag, merge as ah, projectPlanInputToOptions as ai, resolveEngine as aj, resolvePackageManagerProfile as ak, resolvePackageVersions as al, resolveProjectFacts as am, resolveProjectPackageVersions as an, resolveWorkspaceFacts as ao, setAiPlatforms as ap, setConfigStrategy as aq, unique as ar, workspacePlanInputToMonorepoParams as as, 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, renderJson as w, renderVscodeFiles as x, renderAiFiles as y, renderVscodeFiles$1 as z };