create-krispya 0.8.0 → 0.9.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.
@@ -210,6 +210,28 @@ async function getLatestNpmVersion(packageName, fallback) {
210
210
  return fallback;
211
211
  }
212
212
  }
213
+ function compareNumericSemver(a, b) {
214
+ const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
215
+ const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
216
+ const maxLength = Math.max(aParts.length, bParts.length);
217
+ for (let index = 0; index < maxLength; index += 1) {
218
+ const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
219
+ if (difference !== 0) {
220
+ return difference;
221
+ }
222
+ }
223
+ return 0;
224
+ }
225
+ async function getLatestNpmMajorVersion(packageName, majorVersion, fallback) {
226
+ try {
227
+ const response = await fetch(`https://registry.npmjs.org/${packageName}`);
228
+ const data = await response.json();
229
+ const latestMatchingVersion = Object.keys(data.versions ?? {}).filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
230
+ return latestMatchingVersion ?? fallback;
231
+ } catch {
232
+ return fallback;
233
+ }
234
+ }
213
235
  async function getLatestPnpmVersion() {
214
236
  return getLatestNpmVersion("pnpm", "10.11.0");
215
237
  }
@@ -478,6 +500,7 @@ const PACKAGE_VERSION_DEFINITIONS = {
478
500
  "react-dom": { fallbackVersion: "19.0.0" },
479
501
  three: { fallbackVersion: "0.175.0", prefix: "~" },
480
502
  tsdown: { fallbackVersion: "0.12.0" },
503
+ typescript: { fallbackVersion: "5.9.3" },
481
504
  "typescript-eslint": { fallbackVersion: "8.18.0" },
482
505
  unbuild: { fallbackVersion: "3.5.0" },
483
506
  vite: { fallbackVersion: "6.3.4" },
@@ -569,11 +592,35 @@ async function resolvePackageManager(options) {
569
592
  }
570
593
  async function resolveEngine(options) {
571
594
  const engine = getEngineSpec(options.engine);
572
- if (engine.version == null && engine.name === "node") {
595
+ if ((engine.version == null || engine.version === "latest") && engine.name === "node") {
573
596
  engine.version = await getLatestNodeVersion();
574
597
  }
575
598
  return engine;
576
599
  }
600
+ function formatNodeTypesVersion(versions = {}, engine) {
601
+ const resolvedVersion = versions["@types/node"];
602
+ if (resolvedVersion != null) {
603
+ return `^${resolvedVersion}`;
604
+ }
605
+ const engineSpec = getEngineSpec(engine);
606
+ if (engineSpec.name === "node" && engineSpec.version) {
607
+ const majorVersion = engineSpec.version.split(".")[0];
608
+ return `^${majorVersion}.0.0`;
609
+ }
610
+ return "^22.0.0";
611
+ }
612
+ async function resolveNodeTypesVersion(engine, versions = {}) {
613
+ if (versions["@types/node"] != null) {
614
+ return versions["@types/node"];
615
+ }
616
+ const engineSpec = getEngineSpec(engine);
617
+ if (engineSpec.name !== "node") {
618
+ return void 0;
619
+ }
620
+ const nodeVersion = engineSpec.version ?? await getLatestNodeVersion();
621
+ const majorVersion = nodeVersion.split(".")[0];
622
+ return getLatestNpmMajorVersion("@types/node", majorVersion, `${majorVersion}.0.0`);
623
+ }
577
624
  async function resolvePackageVersions(packageNames, existingVersions = {}) {
578
625
  const versions = { ...existingVersions };
579
626
  const uniquePackageNames = [...new Set(packageNames)];
@@ -589,7 +636,16 @@ async function resolvePackageVersions(packageNames, existingVersions = {}) {
589
636
  return versions;
590
637
  }
591
638
  async function resolveProjectPackageVersions(options) {
592
- return resolvePackageVersions(collectProjectPackageNames(options), options.versions);
639
+ const packageNames = collectProjectPackageNames(options);
640
+ const versions = await resolvePackageVersions(
641
+ packageNames.filter((packageName) => packageName !== "@types/node"),
642
+ options.versions
643
+ );
644
+ const nodeTypesVersion = await resolveNodeTypesVersion(options.engine, versions);
645
+ if (nodeTypesVersion != null) {
646
+ versions["@types/node"] = nodeTypesVersion;
647
+ }
648
+ return versions;
593
649
  }
594
650
  async function resolveMonorepoRootPackageVersions(params) {
595
651
  const packageNames = /* @__PURE__ */ new Set();
@@ -598,7 +654,12 @@ async function resolveMonorepoRootPackageVersions(params) {
598
654
  if (params.formatter !== "biome" || params.linter !== "biome") {
599
655
  addPackageName(packageNames, explicitVersions, getFormatterPackage(params.formatter));
600
656
  }
601
- return resolvePackageVersions(packageNames, params.versions);
657
+ const versions = await resolvePackageVersions(packageNames, params.versions);
658
+ const nodeTypesVersion = await resolveNodeTypesVersion(params.engine, versions);
659
+ if (nodeTypesVersion != null) {
660
+ versions["@types/node"] = nodeTypesVersion;
661
+ }
662
+ return versions;
602
663
  }
603
664
  function collectProjectPackageNames(options) {
604
665
  const packageNames = /* @__PURE__ */ new Set();
@@ -616,6 +677,13 @@ function collectProjectPackageNames(options) {
616
677
  const formatter = options.formatter ?? "prettier";
617
678
  const bundler = options.libraryBundler ?? "unbuild";
618
679
  const packageManager = getPackageManagerName(options.packageManager);
680
+ const engine = getEngineSpec(options.engine);
681
+ if (getEngineName(engine) === "node") {
682
+ addPackageName(packageNames, explicitVersions, "@types/node");
683
+ }
684
+ if (isTypescript) {
685
+ addPackageName(packageNames, explicitVersions, "typescript");
686
+ }
619
687
  if (!isLibrary) {
620
688
  addPackageName(packageNames, explicitVersions, "vite");
621
689
  }
@@ -739,9 +807,9 @@ function generateTypescriptConfig(baseTemplateOrParams) {
739
807
  const isR3f = baseTemplate === "r3f";
740
808
  const files = {};
741
809
  const devDependencies = {};
742
- if (getEngineName(engine) === "node" && getEngineSpec(engine).version) {
743
- const majorVersion = getEngineSpec(engine).version.split(".")[0];
744
- devDependencies["@types/node"] = `^${majorVersion}.0.0`;
810
+ assignResolvedPackageVersion(devDependencies, versions, "typescript");
811
+ if (getEngineName(engine) === "node") {
812
+ devDependencies["@types/node"] = formatNodeTypesVersion(versions, engine);
745
813
  } else {
746
814
  devDependencies["@types/node"] = "^22.0.0";
747
815
  }
@@ -929,8 +997,10 @@ function generatePackageJson(params) {
929
997
  const allDevDependencies = { ...devDependencies };
930
998
  const engine = getEngineSpec(options.engine);
931
999
  if (getEngineName(engine) === "node" && engine.version) {
932
- const majorVersion = engine.version.split(".")[0];
933
- allDevDependencies["@types/node"] ??= `^${majorVersion}.0.0`;
1000
+ allDevDependencies["@types/node"] ??= formatNodeTypesVersion(
1001
+ options.versions,
1002
+ options.engine
1003
+ );
934
1004
  }
935
1005
  packageJson.scripts = scripts;
936
1006
  packageJson.dependencies = sortKeys(allDependencies);
@@ -1768,8 +1838,7 @@ function generateMonorepo(params) {
1768
1838
  const isPnpm = packageManager.name === "pnpm";
1769
1839
  const devDependencies = {};
1770
1840
  if (engine?.name === "node" && engine.version) {
1771
- const majorVersion = engine.version.split(".")[0];
1772
- devDependencies["@types/node"] = `^${majorVersion}.0.0`;
1841
+ devDependencies["@types/node"] = formatNodeTypesVersion(versions, engine);
1773
1842
  } else {
1774
1843
  devDependencies["@types/node"] = "^22.0.0";
1775
1844
  }
@@ -3250,6 +3319,7 @@ exports.getEngineName = getEngineName;
3250
3319
  exports.getLanguageFromTemplate = getLanguageFromTemplate;
3251
3320
  exports.getLatestNodeVersion = getLatestNodeVersion;
3252
3321
  exports.getLatestNpmCliVersion = getLatestNpmCliVersion;
3322
+ exports.getLatestNpmMajorVersion = getLatestNpmMajorVersion;
3253
3323
  exports.getLatestNpmVersion = getLatestNpmVersion;
3254
3324
  exports.getLatestPnpmVersion = getLatestPnpmVersion;
3255
3325
  exports.getLatestYarnVersion = getLatestYarnVersion;
@@ -204,6 +204,28 @@ async function getLatestNpmVersion(packageName, fallback) {
204
204
  return fallback;
205
205
  }
206
206
  }
207
+ function compareNumericSemver(a, b) {
208
+ const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
209
+ const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
210
+ const maxLength = Math.max(aParts.length, bParts.length);
211
+ for (let index = 0; index < maxLength; index += 1) {
212
+ const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
213
+ if (difference !== 0) {
214
+ return difference;
215
+ }
216
+ }
217
+ return 0;
218
+ }
219
+ async function getLatestNpmMajorVersion(packageName, majorVersion, fallback) {
220
+ try {
221
+ const response = await fetch(`https://registry.npmjs.org/${packageName}`);
222
+ const data = await response.json();
223
+ const latestMatchingVersion = Object.keys(data.versions ?? {}).filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
224
+ return latestMatchingVersion ?? fallback;
225
+ } catch {
226
+ return fallback;
227
+ }
228
+ }
207
229
  async function getLatestPnpmVersion() {
208
230
  return getLatestNpmVersion("pnpm", "10.11.0");
209
231
  }
@@ -472,6 +494,7 @@ const PACKAGE_VERSION_DEFINITIONS = {
472
494
  "react-dom": { fallbackVersion: "19.0.0" },
473
495
  three: { fallbackVersion: "0.175.0", prefix: "~" },
474
496
  tsdown: { fallbackVersion: "0.12.0" },
497
+ typescript: { fallbackVersion: "5.9.3" },
475
498
  "typescript-eslint": { fallbackVersion: "8.18.0" },
476
499
  unbuild: { fallbackVersion: "3.5.0" },
477
500
  vite: { fallbackVersion: "6.3.4" },
@@ -563,11 +586,35 @@ async function resolvePackageManager(options) {
563
586
  }
564
587
  async function resolveEngine(options) {
565
588
  const engine = getEngineSpec(options.engine);
566
- if (engine.version == null && engine.name === "node") {
589
+ if ((engine.version == null || engine.version === "latest") && engine.name === "node") {
567
590
  engine.version = await getLatestNodeVersion();
568
591
  }
569
592
  return engine;
570
593
  }
594
+ function formatNodeTypesVersion(versions = {}, engine) {
595
+ const resolvedVersion = versions["@types/node"];
596
+ if (resolvedVersion != null) {
597
+ return `^${resolvedVersion}`;
598
+ }
599
+ const engineSpec = getEngineSpec(engine);
600
+ if (engineSpec.name === "node" && engineSpec.version) {
601
+ const majorVersion = engineSpec.version.split(".")[0];
602
+ return `^${majorVersion}.0.0`;
603
+ }
604
+ return "^22.0.0";
605
+ }
606
+ async function resolveNodeTypesVersion(engine, versions = {}) {
607
+ if (versions["@types/node"] != null) {
608
+ return versions["@types/node"];
609
+ }
610
+ const engineSpec = getEngineSpec(engine);
611
+ if (engineSpec.name !== "node") {
612
+ return void 0;
613
+ }
614
+ const nodeVersion = engineSpec.version ?? await getLatestNodeVersion();
615
+ const majorVersion = nodeVersion.split(".")[0];
616
+ return getLatestNpmMajorVersion("@types/node", majorVersion, `${majorVersion}.0.0`);
617
+ }
571
618
  async function resolvePackageVersions(packageNames, existingVersions = {}) {
572
619
  const versions = { ...existingVersions };
573
620
  const uniquePackageNames = [...new Set(packageNames)];
@@ -583,7 +630,16 @@ async function resolvePackageVersions(packageNames, existingVersions = {}) {
583
630
  return versions;
584
631
  }
585
632
  async function resolveProjectPackageVersions(options) {
586
- return resolvePackageVersions(collectProjectPackageNames(options), options.versions);
633
+ const packageNames = collectProjectPackageNames(options);
634
+ const versions = await resolvePackageVersions(
635
+ packageNames.filter((packageName) => packageName !== "@types/node"),
636
+ options.versions
637
+ );
638
+ const nodeTypesVersion = await resolveNodeTypesVersion(options.engine, versions);
639
+ if (nodeTypesVersion != null) {
640
+ versions["@types/node"] = nodeTypesVersion;
641
+ }
642
+ return versions;
587
643
  }
588
644
  async function resolveMonorepoRootPackageVersions(params) {
589
645
  const packageNames = /* @__PURE__ */ new Set();
@@ -592,7 +648,12 @@ async function resolveMonorepoRootPackageVersions(params) {
592
648
  if (params.formatter !== "biome" || params.linter !== "biome") {
593
649
  addPackageName(packageNames, explicitVersions, getFormatterPackage(params.formatter));
594
650
  }
595
- return resolvePackageVersions(packageNames, params.versions);
651
+ const versions = await resolvePackageVersions(packageNames, params.versions);
652
+ const nodeTypesVersion = await resolveNodeTypesVersion(params.engine, versions);
653
+ if (nodeTypesVersion != null) {
654
+ versions["@types/node"] = nodeTypesVersion;
655
+ }
656
+ return versions;
596
657
  }
597
658
  function collectProjectPackageNames(options) {
598
659
  const packageNames = /* @__PURE__ */ new Set();
@@ -610,6 +671,13 @@ function collectProjectPackageNames(options) {
610
671
  const formatter = options.formatter ?? "prettier";
611
672
  const bundler = options.libraryBundler ?? "unbuild";
612
673
  const packageManager = getPackageManagerName(options.packageManager);
674
+ const engine = getEngineSpec(options.engine);
675
+ if (getEngineName(engine) === "node") {
676
+ addPackageName(packageNames, explicitVersions, "@types/node");
677
+ }
678
+ if (isTypescript) {
679
+ addPackageName(packageNames, explicitVersions, "typescript");
680
+ }
613
681
  if (!isLibrary) {
614
682
  addPackageName(packageNames, explicitVersions, "vite");
615
683
  }
@@ -733,9 +801,9 @@ function generateTypescriptConfig(baseTemplateOrParams) {
733
801
  const isR3f = baseTemplate === "r3f";
734
802
  const files = {};
735
803
  const devDependencies = {};
736
- if (getEngineName(engine) === "node" && getEngineSpec(engine).version) {
737
- const majorVersion = getEngineSpec(engine).version.split(".")[0];
738
- devDependencies["@types/node"] = `^${majorVersion}.0.0`;
804
+ assignResolvedPackageVersion(devDependencies, versions, "typescript");
805
+ if (getEngineName(engine) === "node") {
806
+ devDependencies["@types/node"] = formatNodeTypesVersion(versions, engine);
739
807
  } else {
740
808
  devDependencies["@types/node"] = "^22.0.0";
741
809
  }
@@ -923,8 +991,10 @@ function generatePackageJson(params) {
923
991
  const allDevDependencies = { ...devDependencies };
924
992
  const engine = getEngineSpec(options.engine);
925
993
  if (getEngineName(engine) === "node" && engine.version) {
926
- const majorVersion = engine.version.split(".")[0];
927
- allDevDependencies["@types/node"] ??= `^${majorVersion}.0.0`;
994
+ allDevDependencies["@types/node"] ??= formatNodeTypesVersion(
995
+ options.versions,
996
+ options.engine
997
+ );
928
998
  }
929
999
  packageJson.scripts = scripts;
930
1000
  packageJson.dependencies = sortKeys(allDependencies);
@@ -1762,8 +1832,7 @@ function generateMonorepo(params) {
1762
1832
  const isPnpm = packageManager.name === "pnpm";
1763
1833
  const devDependencies = {};
1764
1834
  if (engine?.name === "node" && engine.version) {
1765
- const majorVersion = engine.version.split(".")[0];
1766
- devDependencies["@types/node"] = `^${majorVersion}.0.0`;
1835
+ devDependencies["@types/node"] = formatNodeTypesVersion(versions, engine);
1767
1836
  } else {
1768
1837
  devDependencies["@types/node"] = "^22.0.0";
1769
1838
  }
@@ -3223,4 +3292,4 @@ function resolveDependencySemver(name, versions, options = {}) {
3223
3292
  return formatResolvedPackageVersion(versions, name, options.prefix);
3224
3293
  }
3225
3294
 
3226
- export { ALL_AI_PLATFORMS as A, validatePackageName as B, generateMonorepo as C, getLatestNodeVersion as D, getLatestNpmCliVersion as E, getLatestNpmVersion as F, getLatestPnpmVersion as G, getLatestYarnVersion as H, monorepo as I, getBaseTemplate as a, getLanguageFromTemplate as b, getPackageManagerName as c, generateRandomName as d, detectTooling as e, generateAiFiles as f, getEngineName as g, generateVscodeFiles as h, generateTypescriptConfigPackage as i, generateOxlintConfigPackage as j, generateEslintConfigPackage as k, generateOxfmtConfigPackage as l, generatePrettierConfigPackage as m, generateGitignore as n, getResolvedPackageVersion as o, parseWorkspaceYamlContent as p, formatResolvedPackageVersion as q, resolveMonorepoRootPackageVersions as r, resolvePackageManager as s, resolveEngine as t, resolveProjectPackageVersions as u, generate as v, parsePackageManager as w, parseEngine as x, AI_PLATFORM_LABELS as y, AI_PLATFORM_HINTS as z };
3295
+ export { ALL_AI_PLATFORMS as A, validatePackageName as B, generateMonorepo as C, getLatestNodeVersion as D, getLatestNpmCliVersion as E, getLatestNpmMajorVersion as F, getLatestNpmVersion as G, getLatestPnpmVersion as H, getLatestYarnVersion as I, monorepo as J, getBaseTemplate as a, getLanguageFromTemplate as b, getPackageManagerName as c, generateRandomName as d, detectTooling as e, generateAiFiles as f, getEngineName as g, generateVscodeFiles as h, generateTypescriptConfigPackage as i, generateOxlintConfigPackage as j, generateEslintConfigPackage as k, generateOxfmtConfigPackage as l, generatePrettierConfigPackage as m, generateGitignore as n, getResolvedPackageVersion as o, parseWorkspaceYamlContent as p, formatResolvedPackageVersion as q, resolveMonorepoRootPackageVersions as r, resolvePackageManager as s, resolveEngine as t, resolveProjectPackageVersions as u, generate as v, parsePackageManager as w, parseEngine as x, AI_PLATFORM_LABELS as y, AI_PLATFORM_HINTS as z };
package/dist/cli.cjs CHANGED
@@ -10,7 +10,6 @@ const node_module = require('node:module');
10
10
  const node_path = require('node:path');
11
11
  const node_process = require('node:process');
12
12
  const undici = require('undici');
13
- const child_process = require('child_process');
14
13
  const index = require('./chunks/index.cjs');
15
14
  const Conf = require('conf');
16
15
  const promises = require('fs/promises');
@@ -36,31 +35,6 @@ const p__namespace = /*#__PURE__*/_interopNamespaceCompat(p);
36
35
  const color__default = /*#__PURE__*/_interopDefaultCompat(color);
37
36
  const Conf__default = /*#__PURE__*/_interopDefaultCompat(Conf);
38
37
 
39
- const editorNames = {
40
- cursor: "Cursor",
41
- code: "VS Code",
42
- webstorm: "WebStorm",
43
- skip: "Skip"
44
- };
45
- function openInEditor(editor, path, reuseWindow) {
46
- return new Promise((resolve, reject) => {
47
- const isWindows = process.platform === "win32";
48
- const useReuseFlag = reuseWindow && (editor === "cursor" || editor === "code");
49
- const args = useReuseFlag ? ["-r", path] : [path];
50
- const child = isWindows ? child_process.spawn(`${editor} ${useReuseFlag ? "-r " : ""}"${path}"`, {
51
- detached: true,
52
- stdio: "ignore",
53
- shell: true
54
- }) : child_process.spawn(editor, args, {
55
- detached: true,
56
- stdio: "ignore"
57
- });
58
- child.on("error", reject);
59
- child.unref();
60
- setTimeout(resolve, 100);
61
- });
62
- }
63
-
64
38
  function formatConfigSummary(options, inherited) {
65
39
  const lines = [];
66
40
  const VALUE_COL = 27;
@@ -170,18 +144,6 @@ function formatMonorepoConfigSummary(options) {
170
144
  const config = new Conf__default({
171
145
  projectName: "create-krispya"
172
146
  });
173
- function getPreferredEditor() {
174
- return config.get("preferredEditor");
175
- }
176
- function setPreferredEditor(editor) {
177
- config.set("preferredEditor", editor);
178
- }
179
- function getReuseWindow() {
180
- return config.get("reuseWindow") ?? false;
181
- }
182
- function setReuseWindow(reuse) {
183
- config.set("reuseWindow", reuse);
184
- }
185
147
  function getAiPlatforms() {
186
148
  return config.get("aiPlatforms");
187
149
  }
@@ -600,7 +562,7 @@ async function promptForOptions(name, presets) {
600
562
  options: [
601
563
  { value: "app", label: "Application" },
602
564
  { value: "library", label: "Library" },
603
- { value: "monorepo", label: "Monorepo" }
565
+ { value: "monorepo", label: "Monorepo", hint: "experimental" }
604
566
  ],
605
567
  initialValue: presets?.type ?? "app"
606
568
  });
@@ -661,8 +623,8 @@ function presetsToInheritedSettings(presets) {
661
623
  async function promptForPackageOptions(projectName, projectType, inheritedSettings, presets) {
662
624
  const builtInOptions = [
663
625
  { value: "vanilla", label: "Vanilla" },
664
- { value: "react", label: "React" },
665
- { value: "r3f", label: "React Three Fiber" }
626
+ { value: "react", label: "React", hint: "experimental" },
627
+ { value: "r3f", label: "React Three Fiber", hint: "experimental" }
666
628
  ];
667
629
  const customTemplates = getCustomTemplates();
668
630
  const customOptions = Object.keys(customTemplates).map((name) => ({
@@ -1834,67 +1796,6 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
1834
1796
  return false;
1835
1797
  }
1836
1798
  }
1837
- async function promptAndOpenEditor(projectPath) {
1838
- const savedEditor = getPreferredEditor();
1839
- let selectedEditor;
1840
- if (savedEditor && savedEditor !== "skip") {
1841
- const useDefault = await p__namespace.confirm({
1842
- message: `Open in editor? ${color__default.dim(`(${editorNames[savedEditor]})`)}`,
1843
- initialValue: true
1844
- });
1845
- if (p__namespace.isCancel(useDefault)) {
1846
- selectedEditor = void 0;
1847
- } else if (useDefault) {
1848
- selectedEditor = savedEditor;
1849
- } else {
1850
- selectedEditor = "skip";
1851
- }
1852
- } else {
1853
- const openEditor = await p__namespace.select({
1854
- message: "Open project in editor?",
1855
- options: [
1856
- { value: "skip", label: "Skip" },
1857
- { value: "cursor", label: "Cursor" },
1858
- { value: "code", label: "VS Code" },
1859
- { value: "webstorm", label: "WebStorm" }
1860
- ],
1861
- initialValue: "skip"
1862
- });
1863
- if (!p__namespace.isCancel(openEditor)) {
1864
- selectedEditor = openEditor;
1865
- const saveChoice = await p__namespace.confirm({
1866
- message: `Save ${editorNames[selectedEditor] ?? "Skip"} as default editor?`,
1867
- initialValue: true
1868
- });
1869
- if (!p__namespace.isCancel(saveChoice) && saveChoice) {
1870
- setPreferredEditor(selectedEditor);
1871
- if (selectedEditor === "cursor" || selectedEditor === "code") {
1872
- const reuseChoice = await p__namespace.confirm({
1873
- message: "Reuse current window when opening projects?",
1874
- initialValue: false
1875
- });
1876
- if (!p__namespace.isCancel(reuseChoice)) {
1877
- setReuseWindow(reuseChoice);
1878
- }
1879
- }
1880
- }
1881
- }
1882
- }
1883
- if (selectedEditor && selectedEditor !== "skip") {
1884
- try {
1885
- await openInEditor(
1886
- selectedEditor,
1887
- projectPath,
1888
- getReuseWindow()
1889
- );
1890
- p__namespace.log.success(`Opening in ${editorNames[selectedEditor]}...`);
1891
- } catch {
1892
- p__namespace.log.warn(
1893
- `Could not open ${editorNames[selectedEditor]}. Make sure the CLI command is in your PATH.`
1894
- );
1895
- }
1896
- }
1897
- }
1898
1799
  async function handleCheckCommand() {
1899
1800
  const monorepoRoot = await detectMonorepoRoot();
1900
1801
  if (!monorepoRoot) {
@@ -2522,6 +2423,7 @@ async function handleMonorepoCreation(generateOptions, isNonInteractive) {
2522
2423
  generateOptions.versions = await index.resolveMonorepoRootPackageVersions({
2523
2424
  linter: generateOptions.linter ?? "oxlint",
2524
2425
  formatter: generateOptions.formatter ?? "prettier",
2426
+ engine: generateOptions.engine,
2525
2427
  versions: generateOptions.versions
2526
2428
  });
2527
2429
  const aiPlatforms = await promptForAiPlatforms(isNonInteractive);
@@ -2579,7 +2481,6 @@ async function handleMonorepoCreation(generateOptions, isNonInteractive) {
2579
2481
  `${packageManager} run dev`
2580
2482
  ].join("\n");
2581
2483
  p__namespace.note(nextSteps, "Next steps");
2582
- await promptAndOpenEditor(projectPath);
2583
2484
  p__namespace.outro(color__default.green("Happy coding! \u2728"));
2584
2485
  process.exit(0);
2585
2486
  } catch (error) {
@@ -2619,7 +2520,6 @@ async function handleStandaloneProjectCreation(generateOptions, isNonInteractive
2619
2520
  `${packageManager} run dev`
2620
2521
  ].join("\n");
2621
2522
  p__namespace.note(nextSteps, "Next steps");
2622
- await promptAndOpenEditor(projectPath);
2623
2523
  p__namespace.outro(color__default.green("Happy coding! \u2728"));
2624
2524
  } catch (error) {
2625
2525
  spinner.stop("Failed to create project");
@@ -2662,7 +2562,6 @@ async function handleInteractiveMonorepoMode(monorepoRoot) {
2662
2562
  );
2663
2563
  }
2664
2564
  p__namespace.note([`cd ${monorepoRoot}`, "pnpm install", "pnpm run dev"].join("\n"), "Next steps");
2665
- await promptAndOpenEditor(monorepoRoot);
2666
2565
  p__namespace.outro(color__default.green("Happy coding! \u2728"));
2667
2566
  process.exit(0);
2668
2567
  }
@@ -2683,7 +2582,7 @@ async function main() {
2683
2582
  ).option(
2684
2583
  "--node-version <version>",
2685
2584
  'set Node.js version for engines.node field (default: "latest")'
2686
- ).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(
2585
+ ).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").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(
2687
2586
  "--path <directory>",
2688
2587
  "Run in specified directory instead of current working directory"
2689
2588
  ).action(async (name, options) => {
package/dist/cli.mjs CHANGED
@@ -8,38 +8,12 @@ import { createRequire } from 'node:module';
8
8
  import { join as join$1, dirname as dirname$1, resolve } from 'node:path';
9
9
  import { cwd } from 'node:process';
10
10
  import { fetch } from 'undici';
11
- import { spawn } from 'child_process';
12
11
  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
12
  import Conf from 'conf';
14
13
  import { readFile, mkdir, writeFile, rm, access, readdir, constants as constants$1 } from 'fs/promises';
15
14
  import { constants } from 'fs';
16
15
  import { join, dirname } from 'path';
17
16
 
18
- const editorNames = {
19
- cursor: "Cursor",
20
- code: "VS Code",
21
- webstorm: "WebStorm",
22
- skip: "Skip"
23
- };
24
- function openInEditor(editor, path, reuseWindow) {
25
- return new Promise((resolve, reject) => {
26
- const isWindows = process.platform === "win32";
27
- const useReuseFlag = reuseWindow && (editor === "cursor" || editor === "code");
28
- const args = useReuseFlag ? ["-r", path] : [path];
29
- const child = isWindows ? spawn(`${editor} ${useReuseFlag ? "-r " : ""}"${path}"`, {
30
- detached: true,
31
- stdio: "ignore",
32
- shell: true
33
- }) : spawn(editor, args, {
34
- detached: true,
35
- stdio: "ignore"
36
- });
37
- child.on("error", reject);
38
- child.unref();
39
- setTimeout(resolve, 100);
40
- });
41
- }
42
-
43
17
  function formatConfigSummary(options, inherited) {
44
18
  const lines = [];
45
19
  const VALUE_COL = 27;
@@ -149,18 +123,6 @@ function formatMonorepoConfigSummary(options) {
149
123
  const config = new Conf({
150
124
  projectName: "create-krispya"
151
125
  });
152
- function getPreferredEditor() {
153
- return config.get("preferredEditor");
154
- }
155
- function setPreferredEditor(editor) {
156
- config.set("preferredEditor", editor);
157
- }
158
- function getReuseWindow() {
159
- return config.get("reuseWindow") ?? false;
160
- }
161
- function setReuseWindow(reuse) {
162
- config.set("reuseWindow", reuse);
163
- }
164
126
  function getAiPlatforms() {
165
127
  return config.get("aiPlatforms");
166
128
  }
@@ -579,7 +541,7 @@ async function promptForOptions(name, presets) {
579
541
  options: [
580
542
  { value: "app", label: "Application" },
581
543
  { value: "library", label: "Library" },
582
- { value: "monorepo", label: "Monorepo" }
544
+ { value: "monorepo", label: "Monorepo", hint: "experimental" }
583
545
  ],
584
546
  initialValue: presets?.type ?? "app"
585
547
  });
@@ -640,8 +602,8 @@ function presetsToInheritedSettings(presets) {
640
602
  async function promptForPackageOptions(projectName, projectType, inheritedSettings, presets) {
641
603
  const builtInOptions = [
642
604
  { value: "vanilla", label: "Vanilla" },
643
- { value: "react", label: "React" },
644
- { value: "r3f", label: "React Three Fiber" }
605
+ { value: "react", label: "React", hint: "experimental" },
606
+ { value: "r3f", label: "React Three Fiber", hint: "experimental" }
645
607
  ];
646
608
  const customTemplates = getCustomTemplates();
647
609
  const customOptions = Object.keys(customTemplates).map((name) => ({
@@ -1813,67 +1775,6 @@ async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedS
1813
1775
  return false;
1814
1776
  }
1815
1777
  }
1816
- async function promptAndOpenEditor(projectPath) {
1817
- const savedEditor = getPreferredEditor();
1818
- let selectedEditor;
1819
- if (savedEditor && savedEditor !== "skip") {
1820
- const useDefault = await p.confirm({
1821
- message: `Open in editor? ${color.dim(`(${editorNames[savedEditor]})`)}`,
1822
- initialValue: true
1823
- });
1824
- if (p.isCancel(useDefault)) {
1825
- selectedEditor = void 0;
1826
- } else if (useDefault) {
1827
- selectedEditor = savedEditor;
1828
- } else {
1829
- selectedEditor = "skip";
1830
- }
1831
- } else {
1832
- const openEditor = await p.select({
1833
- message: "Open project in editor?",
1834
- options: [
1835
- { value: "skip", label: "Skip" },
1836
- { value: "cursor", label: "Cursor" },
1837
- { value: "code", label: "VS Code" },
1838
- { value: "webstorm", label: "WebStorm" }
1839
- ],
1840
- initialValue: "skip"
1841
- });
1842
- if (!p.isCancel(openEditor)) {
1843
- selectedEditor = openEditor;
1844
- const saveChoice = await p.confirm({
1845
- message: `Save ${editorNames[selectedEditor] ?? "Skip"} as default editor?`,
1846
- initialValue: true
1847
- });
1848
- if (!p.isCancel(saveChoice) && saveChoice) {
1849
- setPreferredEditor(selectedEditor);
1850
- if (selectedEditor === "cursor" || selectedEditor === "code") {
1851
- const reuseChoice = await p.confirm({
1852
- message: "Reuse current window when opening projects?",
1853
- initialValue: false
1854
- });
1855
- if (!p.isCancel(reuseChoice)) {
1856
- setReuseWindow(reuseChoice);
1857
- }
1858
- }
1859
- }
1860
- }
1861
- }
1862
- if (selectedEditor && selectedEditor !== "skip") {
1863
- try {
1864
- await openInEditor(
1865
- selectedEditor,
1866
- projectPath,
1867
- getReuseWindow()
1868
- );
1869
- p.log.success(`Opening in ${editorNames[selectedEditor]}...`);
1870
- } catch {
1871
- p.log.warn(
1872
- `Could not open ${editorNames[selectedEditor]}. Make sure the CLI command is in your PATH.`
1873
- );
1874
- }
1875
- }
1876
- }
1877
1778
  async function handleCheckCommand() {
1878
1779
  const monorepoRoot = await detectMonorepoRoot();
1879
1780
  if (!monorepoRoot) {
@@ -2494,13 +2395,14 @@ async function handleWorkspaceCommand(name, options) {
2494
2395
  }
2495
2396
  }
2496
2397
  async function handleMonorepoCreation(generateOptions, isNonInteractive) {
2497
- const { generateMonorepo } = await import('./chunks/index.mjs').then(function (n) { return n.I; });
2398
+ const { generateMonorepo } = await import('./chunks/index.mjs').then(function (n) { return n.J; });
2498
2399
  const packageManager = getPackageManagerName(generateOptions.packageManager);
2499
2400
  generateOptions.packageManager = await resolvePackageManager(generateOptions);
2500
2401
  generateOptions.engine = await resolveEngine(generateOptions);
2501
2402
  generateOptions.versions = await resolveMonorepoRootPackageVersions({
2502
2403
  linter: generateOptions.linter ?? "oxlint",
2503
2404
  formatter: generateOptions.formatter ?? "prettier",
2405
+ engine: generateOptions.engine,
2504
2406
  versions: generateOptions.versions
2505
2407
  });
2506
2408
  const aiPlatforms = await promptForAiPlatforms(isNonInteractive);
@@ -2558,7 +2460,6 @@ async function handleMonorepoCreation(generateOptions, isNonInteractive) {
2558
2460
  `${packageManager} run dev`
2559
2461
  ].join("\n");
2560
2462
  p.note(nextSteps, "Next steps");
2561
- await promptAndOpenEditor(projectPath);
2562
2463
  p.outro(color.green("Happy coding! \u2728"));
2563
2464
  process.exit(0);
2564
2465
  } catch (error) {
@@ -2598,7 +2499,6 @@ async function handleStandaloneProjectCreation(generateOptions, isNonInteractive
2598
2499
  `${packageManager} run dev`
2599
2500
  ].join("\n");
2600
2501
  p.note(nextSteps, "Next steps");
2601
- await promptAndOpenEditor(projectPath);
2602
2502
  p.outro(color.green("Happy coding! \u2728"));
2603
2503
  } catch (error) {
2604
2504
  spinner.stop("Failed to create project");
@@ -2641,7 +2541,6 @@ async function handleInteractiveMonorepoMode(monorepoRoot) {
2641
2541
  );
2642
2542
  }
2643
2543
  p.note([`cd ${monorepoRoot}`, "pnpm install", "pnpm run dev"].join("\n"), "Next steps");
2644
- await promptAndOpenEditor(monorepoRoot);
2645
2544
  p.outro(color.green("Happy coding! \u2728"));
2646
2545
  process.exit(0);
2647
2546
  }
@@ -2662,7 +2561,7 @@ async function main() {
2662
2561
  ).option(
2663
2562
  "--node-version <version>",
2664
2563
  'set Node.js version for engines.node field (default: "latest")'
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(
2564
+ ).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").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(
2666
2565
  "--path <directory>",
2667
2566
  "Run in specified directory instead of current working directory"
2668
2567
  ).action(async (name, options) => {
package/dist/index.cjs CHANGED
@@ -16,6 +16,7 @@ exports.getBaseTemplate = index.getBaseTemplate;
16
16
  exports.getLanguageFromTemplate = index.getLanguageFromTemplate;
17
17
  exports.getLatestNodeVersion = index.getLatestNodeVersion;
18
18
  exports.getLatestNpmCliVersion = index.getLatestNpmCliVersion;
19
+ exports.getLatestNpmMajorVersion = index.getLatestNpmMajorVersion;
19
20
  exports.getLatestNpmVersion = index.getLatestNpmVersion;
20
21
  exports.getLatestPnpmVersion = index.getLatestPnpmVersion;
21
22
  exports.getLatestYarnVersion = index.getLatestYarnVersion;
package/dist/index.d.cts CHANGED
@@ -126,6 +126,14 @@ declare function getBaseTemplate(template: Template): BaseTemplate;
126
126
  * @returns The latest version string (e.g., "1.0.0")
127
127
  */
128
128
  declare function getLatestNpmVersion(packageName: string, fallback: string): Promise<string>;
129
+ /**
130
+ * Fetches the latest npm version within a specific major version.
131
+ * @param packageName The name of the npm package
132
+ * @param majorVersion The required major version
133
+ * @param fallback Fallback version if fetch fails or no match exists
134
+ * @returns The latest matching version string (e.g., "25.3.5")
135
+ */
136
+ declare function getLatestNpmMajorVersion(packageName: string, majorVersion: string, fallback: string): Promise<string>;
129
137
  /**
130
138
  * Fetches the latest version of pnpm from the npm registry
131
139
  * @returns The latest pnpm version string (e.g., "10.24.0")
@@ -216,5 +224,5 @@ declare function generateMonorepo(params: MonorepoParams): MonorepoResult;
216
224
  */
217
225
  declare function generate(options: GenerateOptions): Record<string, File>;
218
226
 
219
- export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
227
+ export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmMajorVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
220
228
  export type { AiPlatform, BaseTemplate, CodeInjectionLocation, ConfigStrategy, DependencyVersionOptions, DetectedTooling, EngineName, EngineSpec, File, Formatter, GenerateDreiOptions, GenerateFiberOptions, GenerateGithubPagesOptions, GenerateHandleOptions, GenerateKootaOptions, GenerateLevaOptions, GenerateOffscreenOptions, GenerateOptions, GeneratePostprocessingOptions, GenerateRapierOptions, GenerateTriplexOptions, GenerateUikitOptions, GenerateViverseOptions, GenerateXrOptions, GenerateZustandOptions, Generator, LibraryBundler, Linter, PackageManagerName, PackageManagerSpec, PackageVersions, ProjectType, Template, Testing, VersionRangePrefix };
package/dist/index.d.mts CHANGED
@@ -126,6 +126,14 @@ declare function getBaseTemplate(template: Template): BaseTemplate;
126
126
  * @returns The latest version string (e.g., "1.0.0")
127
127
  */
128
128
  declare function getLatestNpmVersion(packageName: string, fallback: string): Promise<string>;
129
+ /**
130
+ * Fetches the latest npm version within a specific major version.
131
+ * @param packageName The name of the npm package
132
+ * @param majorVersion The required major version
133
+ * @param fallback Fallback version if fetch fails or no match exists
134
+ * @returns The latest matching version string (e.g., "25.3.5")
135
+ */
136
+ declare function getLatestNpmMajorVersion(packageName: string, majorVersion: string, fallback: string): Promise<string>;
129
137
  /**
130
138
  * Fetches the latest version of pnpm from the npm registry
131
139
  * @returns The latest pnpm version string (e.g., "10.24.0")
@@ -216,5 +224,5 @@ declare function generateMonorepo(params: MonorepoParams): MonorepoResult;
216
224
  */
217
225
  declare function generate(options: GenerateOptions): Record<string, File>;
218
226
 
219
- export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
227
+ export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmMajorVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
220
228
  export type { AiPlatform, BaseTemplate, CodeInjectionLocation, ConfigStrategy, DependencyVersionOptions, DetectedTooling, EngineName, EngineSpec, File, Formatter, GenerateDreiOptions, GenerateFiberOptions, GenerateGithubPagesOptions, GenerateHandleOptions, GenerateKootaOptions, GenerateLevaOptions, GenerateOffscreenOptions, GenerateOptions, GeneratePostprocessingOptions, GenerateRapierOptions, GenerateTriplexOptions, GenerateUikitOptions, GenerateViverseOptions, GenerateXrOptions, GenerateZustandOptions, Generator, LibraryBundler, Linter, PackageManagerName, PackageManagerSpec, PackageVersions, ProjectType, Template, Testing, VersionRangePrefix };
package/dist/index.d.ts CHANGED
@@ -126,6 +126,14 @@ declare function getBaseTemplate(template: Template): BaseTemplate;
126
126
  * @returns The latest version string (e.g., "1.0.0")
127
127
  */
128
128
  declare function getLatestNpmVersion(packageName: string, fallback: string): Promise<string>;
129
+ /**
130
+ * Fetches the latest npm version within a specific major version.
131
+ * @param packageName The name of the npm package
132
+ * @param majorVersion The required major version
133
+ * @param fallback Fallback version if fetch fails or no match exists
134
+ * @returns The latest matching version string (e.g., "25.3.5")
135
+ */
136
+ declare function getLatestNpmMajorVersion(packageName: string, majorVersion: string, fallback: string): Promise<string>;
129
137
  /**
130
138
  * Fetches the latest version of pnpm from the npm registry
131
139
  * @returns The latest pnpm version string (e.g., "10.24.0")
@@ -216,5 +224,5 @@ declare function generateMonorepo(params: MonorepoParams): MonorepoResult;
216
224
  */
217
225
  declare function generate(options: GenerateOptions): Record<string, File>;
218
226
 
219
- export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
227
+ export { detectTooling, generate, generateMonorepo, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestNodeVersion, getLatestNpmCliVersion, getLatestNpmMajorVersion, getLatestNpmVersion, getLatestPnpmVersion, getLatestYarnVersion, parseWorkspaceYamlContent, validatePackageName };
220
228
  export type { AiPlatform, BaseTemplate, CodeInjectionLocation, ConfigStrategy, DependencyVersionOptions, DetectedTooling, EngineName, EngineSpec, File, Formatter, GenerateDreiOptions, GenerateFiberOptions, GenerateGithubPagesOptions, GenerateHandleOptions, GenerateKootaOptions, GenerateLevaOptions, GenerateOffscreenOptions, GenerateOptions, GeneratePostprocessingOptions, GenerateRapierOptions, GenerateTriplexOptions, GenerateUikitOptions, GenerateViverseOptions, GenerateXrOptions, GenerateZustandOptions, Generator, LibraryBundler, Linter, PackageManagerName, PackageManagerSpec, PackageVersions, ProjectType, Template, Testing, VersionRangePrefix };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { e as detectTooling, v as generate, C as generateMonorepo, d as generateRandomName, a as getBaseTemplate, b as getLanguageFromTemplate, D as getLatestNodeVersion, E as getLatestNpmCliVersion, F as getLatestNpmVersion, G as getLatestPnpmVersion, H as getLatestYarnVersion, p as parseWorkspaceYamlContent, B as validatePackageName } from './chunks/index.mjs';
1
+ export { e as detectTooling, v as generate, C as generateMonorepo, d as generateRandomName, a as getBaseTemplate, b as getLanguageFromTemplate, D as getLatestNodeVersion, E as getLatestNpmCliVersion, F as getLatestNpmMajorVersion, G as getLatestNpmVersion, H as getLatestPnpmVersion, I as getLatestYarnVersion, p as parseWorkspaceYamlContent, B as validatePackageName } from './chunks/index.mjs';
2
2
  import 'fs/promises';
3
3
  import 'fs';
4
4
  import 'path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-krispya",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "🌹 CLI for creating web projects with (my) sensible defaults",
5
5
  "keywords": [
6
6
  "cli",
@@ -40,6 +40,7 @@
40
40
  "oxlint": "^1.51.0",
41
41
  "prettier": "^3.8.1",
42
42
  "tsx": "^4.21.0",
43
+ "typescript": "^5.9.3",
43
44
  "unbuild": "^3.5.0",
44
45
  "vitest": "^4.0.18"
45
46
  },