@create-node-app/core 0.5.7 → 0.6.1

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/index.cjs CHANGED
@@ -35,7 +35,9 @@ __export(index_exports, {
35
35
  createNodeApp: () => createNodeApp,
36
36
  downloadRepository: () => downloadRepository,
37
37
  getPackagePath: () => getPackagePath,
38
+ getTemplateBaseDirPath: () => getTemplateBaseDirPath,
38
39
  getTemplateDirPath: () => getTemplateDirPath,
40
+ loadTemplateCnaConfig: () => loadTemplateCnaConfig,
39
41
  printEnvInfo: () => printEnvInfo
40
42
  });
41
43
  module.exports = __toCommonJS(index_exports);
@@ -45,7 +47,7 @@ var import_semver3 = __toESM(require("semver"), 1);
45
47
  var import_child_process3 = require("child_process");
46
48
 
47
49
  // installer.ts
48
- var import_underscore2 = __toESM(require("underscore"), 1);
50
+ var import_lodash3 = __toESM(require("lodash"), 1);
49
51
  var import_path4 = __toESM(require("path"), 1);
50
52
  var import_fs5 = __toESM(require("fs"), 1);
51
53
  var import_picocolors3 = __toESM(require("picocolors"), 1);
@@ -60,6 +62,11 @@ var import_picocolors = __toESM(require("picocolors"), 1);
60
62
  var import_semver = __toESM(require("semver"), 1);
61
63
  var import_dns = __toESM(require("dns"), 1);
62
64
  var import_url = require("url");
65
+
66
+ // executable.ts
67
+ var resolveExecutable = (bin) => process.platform === "win32" ? `${bin}.cmd` : bin;
68
+
69
+ // helpers.ts
63
70
  var shouldUseYarn = () => {
64
71
  const { hasMinYarnPnp, hasMaxYarnPnp, yarnVersion } = checkYarnVersion();
65
72
  if (!hasMinYarnPnp) {
@@ -96,6 +103,20 @@ var shouldUsePnpm = () => {
96
103
  }
97
104
  return true;
98
105
  };
106
+ var shouldUseBun = () => {
107
+ const { hasMinBun, bunVersion } = checkBunVersion();
108
+ if (!hasMinBun) {
109
+ console.log(
110
+ import_picocolors.default.yellow(
111
+ `You are using bun version ${import_picocolors.default.bold(
112
+ bunVersion
113
+ )} which is not supported yet. To use bun, install v1.0.0 or higher. See https://bun.sh for instructions on how to install.`
114
+ )
115
+ );
116
+ return false;
117
+ }
118
+ return true;
119
+ };
99
120
  var checkThatNpmCanReadCwd = () => {
100
121
  const cwd = process.cwd();
101
122
  let childOutput = null;
@@ -151,7 +172,7 @@ var checkPnpmVersion = () => {
151
172
  let hasMinPnpm = false;
152
173
  let pnpmVersion = null;
153
174
  try {
154
- pnpmVersion = (0, import_child_process.execSync)("pnpm --version").toString().trim();
175
+ pnpmVersion = (0, import_child_process.execFileSync)(resolveExecutable("pnpm"), ["--version"]).toString().trim();
155
176
  if (import_semver.default.valid(pnpmVersion)) {
156
177
  hasMinPnpm = import_semver.default.gte(pnpmVersion, minPnpm);
157
178
  } else {
@@ -164,6 +185,19 @@ var checkPnpmVersion = () => {
164
185
  }
165
186
  return { hasMinPnpm, pnpmVersion };
166
187
  };
188
+ var checkBunVersion = () => {
189
+ const minBun = "1.0.0";
190
+ let hasMinBun = false;
191
+ let bunVersion = null;
192
+ try {
193
+ bunVersion = (0, import_child_process.execFileSync)(resolveExecutable("bun"), ["--version"]).toString().trim();
194
+ if (import_semver.default.valid(bunVersion)) {
195
+ hasMinBun = import_semver.default.gte(bunVersion, minBun);
196
+ }
197
+ } catch {
198
+ }
199
+ return { hasMinBun, bunVersion };
200
+ };
167
201
  var checkYarnVersion = () => {
168
202
  const minYarnPnp = "1.12.0";
169
203
  const maxYarnPnp = "2.0.0";
@@ -171,7 +205,7 @@ var checkYarnVersion = () => {
171
205
  let hasMaxYarnPnp = false;
172
206
  let yarnVersion = null;
173
207
  try {
174
- yarnVersion = (0, import_child_process.execSync)("yarnpkg --version").toString().trim();
208
+ yarnVersion = (0, import_child_process.execFileSync)(resolveExecutable("yarnpkg"), ["--version"]).toString().trim();
175
209
  if (import_semver.default.valid(yarnVersion)) {
176
210
  hasMinYarnPnp = import_semver.default.gte(yarnVersion, minYarnPnp);
177
211
  hasMaxYarnPnp = import_semver.default.lt(yarnVersion, maxYarnPnp);
@@ -197,7 +231,7 @@ var checkNpmVersion = () => {
197
231
  let hasMinNpm = false;
198
232
  let npmVersion = null;
199
233
  try {
200
- npmVersion = (0, import_child_process.execSync)("npm --version").toString().trim();
234
+ npmVersion = (0, import_child_process.execFileSync)(resolveExecutable("npm"), ["--version"]).toString().trim();
201
235
  hasMinNpm = import_semver.default.gte(npmVersion, "6.0.0");
202
236
  } catch {
203
237
  }
@@ -211,7 +245,11 @@ var getProxy = () => {
211
245
  return process.env.HTTPS_PROXY;
212
246
  }
213
247
  try {
214
- const httpsProxy = (0, import_child_process.execSync)("npm config get https-proxy").toString().trim();
248
+ const httpsProxy = (0, import_child_process.execFileSync)(resolveExecutable("npm"), [
249
+ "config",
250
+ "get",
251
+ "https-proxy"
252
+ ]).toString().trim();
215
253
  return httpsProxy !== "null" ? httpsProxy : void 0;
216
254
  } catch {
217
255
  }
@@ -243,6 +281,8 @@ var import_lodash = __toESM(require("lodash.merge"), 1);
243
281
  var import_fs2 = __toESM(require("fs"), 1);
244
282
  var import_os2 = __toESM(require("os"), 1);
245
283
  var import_path2 = __toESM(require("path"), 1);
284
+ var import_url2 = require("url");
285
+ var import_debug2 = __toESM(require("debug"), 1);
246
286
 
247
287
  // git.ts
248
288
  var import_os = __toESM(require("os"), 1);
@@ -252,6 +292,35 @@ var import_debug = __toESM(require("debug"), 1);
252
292
  var import_simple_git = require("simple-git");
253
293
  var fse = __toESM(require("fs-extra"), 1);
254
294
  var log = (0, import_debug.default)("cna:git");
295
+ var formatRepositoryDownloadError = (error, url) => {
296
+ const message = error instanceof Error ? error.message : String(error);
297
+ if (/not found|404|repository not found/i.test(message)) {
298
+ return [
299
+ `Error: Could not fetch template from '${url}'.`,
300
+ " \u2192 The URL returned HTTP 404 or the repository was not found. Please verify the URL is correct.",
301
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
302
+ ].join("\n");
303
+ }
304
+ if (/403|authentication|permission denied|access denied/i.test(message)) {
305
+ return [
306
+ `Error: Could not fetch template from '${url}'.`,
307
+ " \u2192 Access denied (HTTP 403). Check that the repository is public or you have access.",
308
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
309
+ ].join("\n");
310
+ }
311
+ if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(message)) {
312
+ return [
313
+ `Error: Could not fetch template from '${url}'.`,
314
+ " \u2192 Could not reach the repository. Please check your internet connection.",
315
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
316
+ ].join("\n");
317
+ }
318
+ return [
319
+ `Error: Could not fetch template from '${url}'.`,
320
+ ` \u2192 ${message}`,
321
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
322
+ ].join("\n");
323
+ };
255
324
  var filterGit = (src) => {
256
325
  return !/(\\|\/)\.git\b/.test(src);
257
326
  };
@@ -266,6 +335,7 @@ var downloadRepository = async ({
266
335
  cacheDir: optsCacheDir
267
336
  }) => {
268
337
  const absoluteTarget = import_path.default.isAbsolute(target) ? target : import_path.default.resolve(target);
338
+ const targetExistedBefore = import_fs.default.existsSync(absoluteTarget);
269
339
  const isGithub = /^[^/]+\/[^/]+$/.test(url);
270
340
  const gitUrl = isGithub ? `https://github.com/${url}` : url;
271
341
  const id = targetId || Buffer.from(`${gitUrl}@${branch}`).toString("base64");
@@ -316,7 +386,15 @@ var downloadRepository = async ({
316
386
  });
317
387
  completedTargetIds.set(id, true);
318
388
  } catch (error) {
319
- console.error("Error during repository download:", error);
389
+ if (!targetExistedBefore && import_fs.default.existsSync(absoluteTarget)) {
390
+ try {
391
+ fse.removeSync(absoluteTarget);
392
+ log("Cleaned up partially created directory: %s", absoluteTarget);
393
+ } catch (cleanupErr) {
394
+ log("Failed to clean up directory: %s", cleanupErr);
395
+ }
396
+ }
397
+ throw new Error(formatRepositoryDownloadError(error, gitUrl));
320
398
  } finally {
321
399
  gitOperationMap.delete(id);
322
400
  }
@@ -326,6 +404,9 @@ var downloadRepository = async ({
326
404
  };
327
405
 
328
406
  // paths.ts
407
+ var import_meta = {};
408
+ var log2 = (0, import_debug2.default)("cna:paths");
409
+ var moduleDir = typeof __dirname !== "undefined" ? __dirname : import_path2.default.dirname((0, import_url2.fileURLToPath)(import_meta.url));
329
410
  var solveValuesFromTemplateOrExtensionUrl = (templateOrExtension) => {
330
411
  const url = new URL(templateOrExtension);
331
412
  const ignorePackage = url.searchParams.get("ignorePackage") === "true";
@@ -379,30 +460,23 @@ var solveRepositoryPath = async ({
379
460
  if (process.env.CNA_SKIP_GIT === "1") {
380
461
  return { dir: target, subdir };
381
462
  }
382
- try {
383
- await downloadRepository({
384
- url,
385
- branch: branch || "",
386
- target,
387
- targetId
388
- });
389
- } catch {
390
- }
463
+ await downloadRepository({
464
+ url,
465
+ branch: branch || "",
466
+ target,
467
+ targetId
468
+ });
391
469
  return { dir: target, subdir };
392
470
  };
393
471
  var solveTemplateOrExtensionPath = async (templateOrExtension) => {
472
+ let parsed;
394
473
  try {
395
- const { url, branch, subdir, protocol, pathname, ignorePackage } = solveValuesFromTemplateOrExtensionUrl(templateOrExtension);
396
- if (protocol === "file:") {
397
- const baseDir = pathname;
398
- return { dir: baseDir, subdir, ignorePackage };
399
- }
400
- const gitData = await solveRepositoryPath({ url, branch, subdir });
401
- return { dir: gitData.dir, subdir: gitData.subdir, ignorePackage };
474
+ parsed = solveValuesFromTemplateOrExtensionUrl(templateOrExtension);
402
475
  } catch {
476
+ log2("Falling back to legacy template path for: %s", templateOrExtension);
403
477
  return {
404
478
  dir: import_path2.default.resolve(
405
- __dirname,
479
+ moduleDir,
406
480
  "..",
407
481
  "templatesOrExtensions",
408
482
  templateOrExtension
@@ -411,6 +485,12 @@ var solveTemplateOrExtensionPath = async (templateOrExtension) => {
411
485
  ignorePackage: void 0
412
486
  };
413
487
  }
488
+ const { url, branch, subdir, protocol, pathname, ignorePackage } = parsed;
489
+ if (protocol === "file:") {
490
+ return { dir: pathname, subdir, ignorePackage };
491
+ }
492
+ const gitData = await solveRepositoryPath({ url, branch, subdir });
493
+ return { dir: gitData.dir, subdir: gitData.subdir, ignorePackage };
414
494
  };
415
495
  var getPackagePath = async (templateOrExtension, name = "package", ignorePackage = false) => {
416
496
  const {
@@ -428,6 +508,16 @@ var getPackagePath = async (templateOrExtension, name = "package", ignorePackage
428
508
  }
429
509
  return import_path2.default.resolve(dir, name);
430
510
  };
511
+ var getTemplateBaseDirPath = async (templateOrExtensionUrl) => {
512
+ try {
513
+ const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
514
+ templateOrExtensionUrl
515
+ );
516
+ return import_path2.default.resolve(dir, subdir);
517
+ } catch {
518
+ return "";
519
+ }
520
+ };
431
521
  var getTemplateDirPath = async (templateOrExtensionUrl) => {
432
522
  const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
433
523
  templateOrExtensionUrl
@@ -461,11 +551,11 @@ var getInstallableSetup = ({
461
551
  devDependencies: getInstallableDeps(devDependencies)
462
552
  };
463
553
  };
464
- var requireIfExists = (path4) => {
465
- if ((0, import_fs3.existsSync)(path4)) {
466
- return require(path4);
554
+ var requireIfExists = (path5) => {
555
+ if ((0, import_fs3.existsSync)(path5)) {
556
+ return require(path5);
467
557
  }
468
- throw new Error(`File ${path4} does not exist`);
558
+ throw new Error(`File ${path5} does not exist`);
469
559
  };
470
560
  var loadPackages = async ({
471
561
  templatesOrExtensions = [],
@@ -475,10 +565,10 @@ var loadPackages = async ({
475
565
  const setup = await Promise.all(
476
566
  templatesOrExtensions.map(async ({ url: templateOrExtension }) => {
477
567
  try {
478
- const template = requireIfExists(
568
+ const template2 = requireIfExists(
479
569
  await getPackagePath(templateOrExtension, "template.json")
480
570
  );
481
- return template.package || {};
571
+ return template2.package || {};
482
572
  } catch {
483
573
  return {};
484
574
  }
@@ -531,12 +621,13 @@ var loadPackages = async ({
531
621
  };
532
622
 
533
623
  // loaders.ts
534
- var import_underscore = __toESM(require("underscore"), 1);
535
624
  var import_fs4 = __toESM(require("fs"), 1);
536
625
  var import_picocolors2 = __toESM(require("picocolors"), 1);
537
626
  var import_readdirp = require("readdirp");
538
627
  var import_path3 = require("path");
539
628
  var import_util = require("util");
629
+ var import_lodash2 = __toESM(require("lodash"), 1);
630
+ var { template } = import_lodash2.default;
540
631
  var writeFileAsync = (0, import_util.promisify)(import_fs4.default.writeFile);
541
632
  var copyFileAsync = (0, import_util.promisify)(import_fs4.default.copyFile);
542
633
  var SRC_PATH_PATTERN = "[src]/";
@@ -547,8 +638,8 @@ var makeDirectory = (dirPath) => {
547
638
  import_fs4.default.mkdirSync(dirPath, { recursive: true });
548
639
  }
549
640
  };
550
- var getModeFromPath = (path4 = "") => {
551
- const matchExts = (...exts) => exts.find((ext) => path4.endsWith(ext));
641
+ var getModeFromPath = (path5 = "") => {
642
+ const matchExts = (...exts) => exts.find((ext) => path5.endsWith(ext));
552
643
  if (matchExts(".append")) {
553
644
  return "append";
554
645
  }
@@ -565,6 +656,11 @@ var batchedCopyFiles = async (operations) => {
565
656
  try {
566
657
  makeDirectory((0, import_path3.dirname)(operation.dest));
567
658
  await copyFileAsync(operation.src, operation.dest);
659
+ try {
660
+ const srcStat = await (0, import_util.promisify)(import_fs4.default.stat)(operation.src);
661
+ await (0, import_util.promisify)(import_fs4.default.chmod)(operation.dest, srcStat.mode);
662
+ } catch {
663
+ }
568
664
  if (operation.verbose) {
569
665
  console.log(
570
666
  import_picocolors2.default.green(
@@ -631,12 +727,12 @@ var batchedAppendFiles = async (operations) => {
631
727
  });
632
728
  await Promise.all(batchedPromises);
633
729
  };
634
- var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path4 }) => {
730
+ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
635
731
  const operations = [];
636
732
  try {
637
- const newPath = path4.replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
733
+ const newPath = path5.replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
638
734
  operations.push({
639
- src: `${templateDir}/${path4}`,
735
+ src: `${templateDir}/${path5}`,
640
736
  dest: `${root}/${newPath}`,
641
737
  verbose
642
738
  });
@@ -648,12 +744,12 @@ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path
648
744
  }
649
745
  await batchedCopyFiles(operations);
650
746
  };
651
- var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path4 }) => {
747
+ var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
652
748
  const operations = [];
653
749
  try {
654
- const newPath = path4.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
750
+ const newPath = path5.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
655
751
  operations.push({
656
- src: `${templateDir}/${path4}`,
752
+ src: `${templateDir}/${path5}`,
657
753
  dest: `${root}/${newPath}`,
658
754
  verbose
659
755
  });
@@ -675,15 +771,15 @@ var templateLoader = ({
675
771
  runCommand,
676
772
  installCommand,
677
773
  ...customOptions
678
- }) => async ({ path: path4 }) => {
774
+ }) => async ({ path: path5 }) => {
679
775
  const operations = [];
680
776
  try {
681
777
  const flag = mode.includes("append") ? "a+" : "w";
682
- const filePath = `${templateDir}/${path4}`;
778
+ const filePath = `${templateDir}/${path5}`;
683
779
  const file = await (0, import_util.promisify)(import_fs4.default.readFile)(filePath, "utf8");
684
780
  const fileMode = (await (0, import_util.promisify)(import_fs4.default.stat)(filePath)).mode;
685
- const newFile = import_underscore.default.template(file);
686
- const newPath = path4.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
781
+ const newFile = template(file);
782
+ const newPath = path5.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
687
783
  operations.push({
688
784
  path: `${root}/${newPath}`,
689
785
  content: newFile({
@@ -713,13 +809,14 @@ var fileLoader = ({
713
809
  verbose,
714
810
  useYarn,
715
811
  usePnpm,
812
+ useBun,
716
813
  srcDir = DEFAULT_SRC_PATH,
717
814
  runCommand,
718
815
  installCommand,
719
816
  ...customOptions
720
- }) => async ({ path: path4 }) => {
817
+ }) => async ({ path: path5 }) => {
721
818
  try {
722
- const mode = getModeFromPath(path4);
819
+ const mode = getModeFromPath(path5);
723
820
  const loaders = {
724
821
  copy: copyLoader,
725
822
  append: appendLoader,
@@ -735,13 +832,14 @@ var fileLoader = ({
735
832
  verbose,
736
833
  useYarn: !!useYarn,
737
834
  usePnpm: !!usePnpm,
835
+ useBun: !!useBun,
738
836
  mode,
739
837
  srcDir,
740
838
  runCommand,
741
839
  installCommand,
742
840
  ...customOptions
743
841
  })({
744
- path: path4
842
+ path: path5
745
843
  });
746
844
  } catch (err) {
747
845
  if (verbose) {
@@ -758,6 +856,7 @@ var loadFiles = async ({
758
856
  verbose,
759
857
  useYarn = false,
760
858
  usePnpm = false,
859
+ useBun = false,
761
860
  srcDir = DEFAULT_SRC_PATH,
762
861
  runCommand,
763
862
  installCommand,
@@ -788,7 +887,7 @@ var loadFiles = async ({
788
887
  /\byarn\.lock$/,
789
888
  /\bpnpm-lock\.yaml$/
790
889
  ];
791
- const skipManager = usePnpm ? [/\.if-npm\./, /\.if-yarn\./] : useYarn ? [/\.if-npm\./, /\.if-pnpm\./] : [/\.if-yarn\./, /\.if-pnpm\./];
890
+ const skipManager = usePnpm ? [/\.if-npm\./, /\.if-yarn\./, /\.if-bun\./] : useYarn ? [/\.if-npm\./, /\.if-pnpm\./, /\.if-bun\./] : useBun ? [/\.if-yarn\./, /\.if-pnpm\./] : [/\.if-yarn\./, /\.if-pnpm\./, /\.if-bun\./];
792
891
  const shouldSkip = (p) => [...skipGlobs, ...skipManager].some((rgx) => rgx.test(p));
793
892
  for await (const entry of (0, import_readdirp.readdirp)(templateDir, {
794
893
  type: "files",
@@ -808,6 +907,7 @@ var loadFiles = async ({
808
907
  verbose,
809
908
  useYarn,
810
909
  usePnpm,
910
+ useBun,
811
911
  srcDir,
812
912
  runCommand,
813
913
  installCommand,
@@ -843,7 +943,8 @@ var loadFiles = async ({
843
943
  };
844
944
 
845
945
  // installer.ts
846
- var install = async (root, useYarn = false, usePnpm = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
946
+ var { isEmpty } = import_lodash3.default;
947
+ var install = async (root, useYarn = false, usePnpm = false, useBun = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
847
948
  let command;
848
949
  let args;
849
950
  if (useYarn) {
@@ -872,6 +973,17 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
872
973
  args.push("--save");
873
974
  }
874
975
  args.push(...dependencies);
976
+ } else if (useBun) {
977
+ command = "bun";
978
+ if (dependencies.length > 0) {
979
+ args = ["add"];
980
+ if (isDevDependencies) {
981
+ args.push("--dev");
982
+ }
983
+ args.push(...dependencies);
984
+ } else {
985
+ args = ["install"];
986
+ }
875
987
  } else {
876
988
  command = "npm";
877
989
  args = ["install", "--loglevel", "error"];
@@ -886,7 +998,7 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
886
998
  args.push("--verbose");
887
999
  }
888
1000
  try {
889
- (0, import_child_process2.execSync)(`${command} ${args.join(" ")}`, {
1001
+ (0, import_child_process2.execFileSync)(resolveExecutable(command), args, {
890
1002
  cwd: root,
891
1003
  stdio: "inherit"
892
1004
  });
@@ -895,8 +1007,9 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
895
1007
  }
896
1008
  };
897
1009
  var runCommandInProjectDir = async (root, command, args = [], successMessage = "Operation completed successfully.", errorMessage = "Operation failed.") => {
1010
+ const [executable, ...baseArgs] = command === "npm run" ? ["npm", "run"] : command === "pnpm run" ? ["pnpm", "run"] : command === "bun run" ? ["bun", "run"] : [command];
898
1011
  try {
899
- (0, import_child_process2.execSync)(`${command} ${args.join(" ")}`, {
1012
+ (0, import_child_process2.execFileSync)(resolveExecutable(executable), [...baseArgs, ...args], {
900
1013
  cwd: root,
901
1014
  stdio: "ignore"
902
1015
  });
@@ -924,6 +1037,7 @@ var run = async ({
924
1037
  verbose = false,
925
1038
  useYarn = false,
926
1039
  usePnpm = false,
1040
+ useBun = false,
927
1041
  templatesOrExtensions = [],
928
1042
  dependencies = [],
929
1043
  devDependencies = [],
@@ -933,7 +1047,7 @@ var run = async ({
933
1047
  ...customOptions
934
1048
  }) => {
935
1049
  const isOnline = useYarn ? await checkIfOnline(useYarn) : true;
936
- if (import_underscore2.default.isEmpty(templatesOrExtensions)) {
1050
+ if (isEmpty(templatesOrExtensions)) {
937
1051
  console.log();
938
1052
  console.log(
939
1053
  import_picocolors3.default.yellow(
@@ -953,6 +1067,7 @@ var run = async ({
953
1067
  verbose,
954
1068
  useYarn,
955
1069
  usePnpm,
1070
+ useBun,
956
1071
  runCommand,
957
1072
  installCommand,
958
1073
  ...customOptions
@@ -970,6 +1085,7 @@ var run = async ({
970
1085
  root,
971
1086
  useYarn,
972
1087
  usePnpm,
1088
+ useBun,
973
1089
  dependencies,
974
1090
  verbose,
975
1091
  isOnline,
@@ -983,6 +1099,7 @@ var run = async ({
983
1099
  root,
984
1100
  useYarn,
985
1101
  usePnpm,
1102
+ useBun,
986
1103
  devDependencies,
987
1104
  verbose,
988
1105
  isOnline,
@@ -1107,13 +1224,15 @@ var createApp = async ({
1107
1224
  console.log();
1108
1225
  const useYarn = customOptions.packageManager === "yarn" && shouldUseYarn();
1109
1226
  const usePnpm = customOptions.packageManager === "pnpm" && shouldUsePnpm();
1110
- const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : "npm run";
1111
- const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : "npm install";
1227
+ const useBun = customOptions.packageManager === "bun" && shouldUseBun();
1228
+ const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : useBun ? "bun run" : "npm run";
1229
+ const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : useBun ? "bun install" : "npm install";
1112
1230
  const { packageJson, dependencies, devDependencies } = await loadPackages({
1113
1231
  templatesOrExtensions,
1114
1232
  appName,
1115
1233
  usePnpm,
1116
1234
  useYarn,
1235
+ useBun,
1117
1236
  runCommand,
1118
1237
  ignorePackage
1119
1238
  });
@@ -1123,7 +1242,7 @@ var createApp = async ({
1123
1242
  );
1124
1243
  const originalDirectory = process.cwd();
1125
1244
  process.chdir(root);
1126
- if (!useYarn && !checkThatNpmCanReadCwd()) {
1245
+ if (!useYarn && !useBun && !checkThatNpmCanReadCwd()) {
1127
1246
  process.exit(1);
1128
1247
  }
1129
1248
  if (!import_semver2.default.satisfies(process.version, ">=18.0.0")) {
@@ -1136,7 +1255,7 @@ Please update to Node 18 or higher for a better, fully supported experience.
1136
1255
  )
1137
1256
  );
1138
1257
  }
1139
- if (!useYarn) {
1258
+ if (!useYarn && !useBun) {
1140
1259
  const npmInfo = checkNpmVersion();
1141
1260
  if (!npmInfo.hasMinNpm) {
1142
1261
  if (npmInfo.npmVersion) {
@@ -1154,7 +1273,11 @@ Please update to npm 3 or higher for a better, fully supported experience.
1154
1273
  if (useYarn) {
1155
1274
  let yarnUsesDefaultRegistry = true;
1156
1275
  try {
1157
- yarnUsesDefaultRegistry = (0, import_child_process2.execSync)("yarnpkg config get registry").toString().trim() === "https://registry.yarnpkg.com";
1276
+ yarnUsesDefaultRegistry = (0, import_child_process2.execFileSync)(resolveExecutable("yarnpkg"), [
1277
+ "config",
1278
+ "get",
1279
+ "registry"
1280
+ ]).toString().trim() === "https://registry.yarnpkg.com";
1158
1281
  } catch {
1159
1282
  }
1160
1283
  if (false) {
@@ -1172,6 +1295,7 @@ Please update to npm 3 or higher for a better, fully supported experience.
1172
1295
  verbose,
1173
1296
  useYarn,
1174
1297
  usePnpm,
1298
+ useBun,
1175
1299
  templatesOrExtensions,
1176
1300
  dependencies,
1177
1301
  devDependencies,
@@ -1182,6 +1306,22 @@ Please update to npm 3 or higher for a better, fully supported experience.
1182
1306
  });
1183
1307
  };
1184
1308
 
1309
+ // config.ts
1310
+ var import_fs6 = __toESM(require("fs"), 1);
1311
+ var import_path5 = __toESM(require("path"), 1);
1312
+ var loadTemplateCnaConfig = async (templateUrl) => {
1313
+ try {
1314
+ const basePath = await getTemplateBaseDirPath(templateUrl);
1315
+ if (!basePath) return null;
1316
+ const configPath = import_path5.default.join(basePath, "cna.config.json");
1317
+ if (!import_fs6.default.existsSync(configPath)) return null;
1318
+ const content = import_fs6.default.readFileSync(configPath, "utf8");
1319
+ return JSON.parse(content);
1320
+ } catch {
1321
+ return null;
1322
+ }
1323
+ };
1324
+
1185
1325
  // index.ts
1186
1326
  var checkNodeVersion = (requiredVersion, packageName) => {
1187
1327
  if (!import_semver3.default.satisfies(process.version, requiredVersion)) {
@@ -1210,7 +1350,11 @@ var checkForLatestVersion = async (packageName) => {
1210
1350
  return null;
1211
1351
  } catch {
1212
1352
  try {
1213
- return (0, import_child_process3.execSync)(`npm view ${packageName} version`).toString().trim();
1353
+ return (0, import_child_process3.execFileSync)(resolveExecutable("npm"), [
1354
+ "view",
1355
+ packageName,
1356
+ "version"
1357
+ ]).toString().trim();
1214
1358
  } catch {
1215
1359
  }
1216
1360
  }
@@ -1221,7 +1365,7 @@ var printEnvInfo = async () => {
1221
1365
  const info = await import_envinfo.default.run(
1222
1366
  {
1223
1367
  System: ["OS", "CPU", "Memory", "Shell"],
1224
- Binaries: ["Node", "npm", "pnpm", "Yarn", "Watchman"],
1368
+ Binaries: ["Node", "npm", "pnpm", "Yarn", "Bun", "Watchman"],
1225
1369
  Browsers: ["Chrome", "Edge", "Internet Explorer", "Firefox", "Safari"]
1226
1370
  },
1227
1371
  {
@@ -1260,7 +1404,9 @@ var createNodeApp = async (programName, options, transformOptions) => {
1260
1404
  createNodeApp,
1261
1405
  downloadRepository,
1262
1406
  getPackagePath,
1407
+ getTemplateBaseDirPath,
1263
1408
  getTemplateDirPath,
1409
+ loadTemplateCnaConfig,
1264
1410
  printEnvInfo
1265
1411
  });
1266
1412
  //# sourceMappingURL=index.cjs.map