@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.js CHANGED
@@ -9,24 +9,29 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
  import pc4 from "picocolors";
10
10
  import envinfo from "envinfo";
11
11
  import semver3 from "semver";
12
- import { execSync as execSync3 } from "child_process";
12
+ import { execFileSync as execFileSync3 } from "child_process";
13
13
 
14
14
  // installer.ts
15
- import _2 from "underscore";
15
+ import lodash2 from "lodash";
16
16
  import path3 from "path";
17
17
  import fs4 from "fs";
18
18
  import pc3 from "picocolors";
19
19
  import os3 from "os";
20
20
  import semver2 from "semver";
21
- import { execSync as execSync2 } from "child_process";
21
+ import { execFileSync as execFileSync2 } from "child_process";
22
22
 
23
23
  // helpers.ts
24
- import { execSync } from "child_process";
24
+ import { execFileSync } from "child_process";
25
25
  import spawn from "cross-spawn";
26
26
  import pc from "picocolors";
27
27
  import semver from "semver";
28
28
  import dns from "dns";
29
29
  import { URL as URL2 } from "url";
30
+
31
+ // executable.ts
32
+ var resolveExecutable = (bin) => process.platform === "win32" ? `${bin}.cmd` : bin;
33
+
34
+ // helpers.ts
30
35
  var shouldUseYarn = () => {
31
36
  const { hasMinYarnPnp, hasMaxYarnPnp, yarnVersion } = checkYarnVersion();
32
37
  if (!hasMinYarnPnp) {
@@ -63,6 +68,20 @@ var shouldUsePnpm = () => {
63
68
  }
64
69
  return true;
65
70
  };
71
+ var shouldUseBun = () => {
72
+ const { hasMinBun, bunVersion } = checkBunVersion();
73
+ if (!hasMinBun) {
74
+ console.log(
75
+ pc.yellow(
76
+ `You are using bun version ${pc.bold(
77
+ bunVersion
78
+ )} which is not supported yet. To use bun, install v1.0.0 or higher. See https://bun.sh for instructions on how to install.`
79
+ )
80
+ );
81
+ return false;
82
+ }
83
+ return true;
84
+ };
66
85
  var checkThatNpmCanReadCwd = () => {
67
86
  const cwd = process.cwd();
68
87
  let childOutput = null;
@@ -118,7 +137,7 @@ var checkPnpmVersion = () => {
118
137
  let hasMinPnpm = false;
119
138
  let pnpmVersion = null;
120
139
  try {
121
- pnpmVersion = execSync("pnpm --version").toString().trim();
140
+ pnpmVersion = execFileSync(resolveExecutable("pnpm"), ["--version"]).toString().trim();
122
141
  if (semver.valid(pnpmVersion)) {
123
142
  hasMinPnpm = semver.gte(pnpmVersion, minPnpm);
124
143
  } else {
@@ -131,6 +150,19 @@ var checkPnpmVersion = () => {
131
150
  }
132
151
  return { hasMinPnpm, pnpmVersion };
133
152
  };
153
+ var checkBunVersion = () => {
154
+ const minBun = "1.0.0";
155
+ let hasMinBun = false;
156
+ let bunVersion = null;
157
+ try {
158
+ bunVersion = execFileSync(resolveExecutable("bun"), ["--version"]).toString().trim();
159
+ if (semver.valid(bunVersion)) {
160
+ hasMinBun = semver.gte(bunVersion, minBun);
161
+ }
162
+ } catch {
163
+ }
164
+ return { hasMinBun, bunVersion };
165
+ };
134
166
  var checkYarnVersion = () => {
135
167
  const minYarnPnp = "1.12.0";
136
168
  const maxYarnPnp = "2.0.0";
@@ -138,7 +170,7 @@ var checkYarnVersion = () => {
138
170
  let hasMaxYarnPnp = false;
139
171
  let yarnVersion = null;
140
172
  try {
141
- yarnVersion = execSync("yarnpkg --version").toString().trim();
173
+ yarnVersion = execFileSync(resolveExecutable("yarnpkg"), ["--version"]).toString().trim();
142
174
  if (semver.valid(yarnVersion)) {
143
175
  hasMinYarnPnp = semver.gte(yarnVersion, minYarnPnp);
144
176
  hasMaxYarnPnp = semver.lt(yarnVersion, maxYarnPnp);
@@ -164,7 +196,7 @@ var checkNpmVersion = () => {
164
196
  let hasMinNpm = false;
165
197
  let npmVersion = null;
166
198
  try {
167
- npmVersion = execSync("npm --version").toString().trim();
199
+ npmVersion = execFileSync(resolveExecutable("npm"), ["--version"]).toString().trim();
168
200
  hasMinNpm = semver.gte(npmVersion, "6.0.0");
169
201
  } catch {
170
202
  }
@@ -178,7 +210,11 @@ var getProxy = () => {
178
210
  return process.env.HTTPS_PROXY;
179
211
  }
180
212
  try {
181
- const httpsProxy = execSync("npm config get https-proxy").toString().trim();
213
+ const httpsProxy = execFileSync(resolveExecutable("npm"), [
214
+ "config",
215
+ "get",
216
+ "https-proxy"
217
+ ]).toString().trim();
182
218
  return httpsProxy !== "null" ? httpsProxy : void 0;
183
219
  } catch {
184
220
  }
@@ -210,6 +246,8 @@ import merge from "lodash.merge";
210
246
  import fs2 from "fs";
211
247
  import os2 from "os";
212
248
  import path2 from "path";
249
+ import { fileURLToPath } from "url";
250
+ import debug2 from "debug";
213
251
 
214
252
  // git.ts
215
253
  import os from "os";
@@ -219,6 +257,35 @@ import debug from "debug";
219
257
  import { simpleGit } from "simple-git";
220
258
  import * as fse from "fs-extra";
221
259
  var log = debug("cna:git");
260
+ var formatRepositoryDownloadError = (error, url) => {
261
+ const message = error instanceof Error ? error.message : String(error);
262
+ if (/not found|404|repository not found/i.test(message)) {
263
+ return [
264
+ `Error: Could not fetch template from '${url}'.`,
265
+ " \u2192 The URL returned HTTP 404 or the repository was not found. Please verify the URL is correct.",
266
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
267
+ ].join("\n");
268
+ }
269
+ if (/403|authentication|permission denied|access denied/i.test(message)) {
270
+ return [
271
+ `Error: Could not fetch template from '${url}'.`,
272
+ " \u2192 Access denied (HTTP 403). Check that the repository is public or you have access.",
273
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
274
+ ].join("\n");
275
+ }
276
+ if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(message)) {
277
+ return [
278
+ `Error: Could not fetch template from '${url}'.`,
279
+ " \u2192 Could not reach the repository. Please check your internet connection.",
280
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
281
+ ].join("\n");
282
+ }
283
+ return [
284
+ `Error: Could not fetch template from '${url}'.`,
285
+ ` \u2192 ${message}`,
286
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
287
+ ].join("\n");
288
+ };
222
289
  var filterGit = (src) => {
223
290
  return !/(\\|\/)\.git\b/.test(src);
224
291
  };
@@ -233,6 +300,7 @@ var downloadRepository = async ({
233
300
  cacheDir: optsCacheDir
234
301
  }) => {
235
302
  const absoluteTarget = path.isAbsolute(target) ? target : path.resolve(target);
303
+ const targetExistedBefore = fs.existsSync(absoluteTarget);
236
304
  const isGithub = /^[^/]+\/[^/]+$/.test(url);
237
305
  const gitUrl = isGithub ? `https://github.com/${url}` : url;
238
306
  const id = targetId || Buffer.from(`${gitUrl}@${branch}`).toString("base64");
@@ -283,7 +351,15 @@ var downloadRepository = async ({
283
351
  });
284
352
  completedTargetIds.set(id, true);
285
353
  } catch (error) {
286
- console.error("Error during repository download:", error);
354
+ if (!targetExistedBefore && fs.existsSync(absoluteTarget)) {
355
+ try {
356
+ fse.removeSync(absoluteTarget);
357
+ log("Cleaned up partially created directory: %s", absoluteTarget);
358
+ } catch (cleanupErr) {
359
+ log("Failed to clean up directory: %s", cleanupErr);
360
+ }
361
+ }
362
+ throw new Error(formatRepositoryDownloadError(error, gitUrl));
287
363
  } finally {
288
364
  gitOperationMap.delete(id);
289
365
  }
@@ -293,6 +369,8 @@ var downloadRepository = async ({
293
369
  };
294
370
 
295
371
  // paths.ts
372
+ var log2 = debug2("cna:paths");
373
+ var moduleDir = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath(import.meta.url));
296
374
  var solveValuesFromTemplateOrExtensionUrl = (templateOrExtension) => {
297
375
  const url = new URL(templateOrExtension);
298
376
  const ignorePackage = url.searchParams.get("ignorePackage") === "true";
@@ -346,30 +424,23 @@ var solveRepositoryPath = async ({
346
424
  if (process.env.CNA_SKIP_GIT === "1") {
347
425
  return { dir: target, subdir };
348
426
  }
349
- try {
350
- await downloadRepository({
351
- url,
352
- branch: branch || "",
353
- target,
354
- targetId
355
- });
356
- } catch {
357
- }
427
+ await downloadRepository({
428
+ url,
429
+ branch: branch || "",
430
+ target,
431
+ targetId
432
+ });
358
433
  return { dir: target, subdir };
359
434
  };
360
435
  var solveTemplateOrExtensionPath = async (templateOrExtension) => {
436
+ let parsed;
361
437
  try {
362
- const { url, branch, subdir, protocol, pathname, ignorePackage } = solveValuesFromTemplateOrExtensionUrl(templateOrExtension);
363
- if (protocol === "file:") {
364
- const baseDir = pathname;
365
- return { dir: baseDir, subdir, ignorePackage };
366
- }
367
- const gitData = await solveRepositoryPath({ url, branch, subdir });
368
- return { dir: gitData.dir, subdir: gitData.subdir, ignorePackage };
438
+ parsed = solveValuesFromTemplateOrExtensionUrl(templateOrExtension);
369
439
  } catch {
440
+ log2("Falling back to legacy template path for: %s", templateOrExtension);
370
441
  return {
371
442
  dir: path2.resolve(
372
- __dirname,
443
+ moduleDir,
373
444
  "..",
374
445
  "templatesOrExtensions",
375
446
  templateOrExtension
@@ -378,6 +449,12 @@ var solveTemplateOrExtensionPath = async (templateOrExtension) => {
378
449
  ignorePackage: void 0
379
450
  };
380
451
  }
452
+ const { url, branch, subdir, protocol, pathname, ignorePackage } = parsed;
453
+ if (protocol === "file:") {
454
+ return { dir: pathname, subdir, ignorePackage };
455
+ }
456
+ const gitData = await solveRepositoryPath({ url, branch, subdir });
457
+ return { dir: gitData.dir, subdir: gitData.subdir, ignorePackage };
381
458
  };
382
459
  var getPackagePath = async (templateOrExtension, name = "package", ignorePackage = false) => {
383
460
  const {
@@ -395,6 +472,16 @@ var getPackagePath = async (templateOrExtension, name = "package", ignorePackage
395
472
  }
396
473
  return path2.resolve(dir, name);
397
474
  };
475
+ var getTemplateBaseDirPath = async (templateOrExtensionUrl) => {
476
+ try {
477
+ const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
478
+ templateOrExtensionUrl
479
+ );
480
+ return path2.resolve(dir, subdir);
481
+ } catch {
482
+ return "";
483
+ }
484
+ };
398
485
  var getTemplateDirPath = async (templateOrExtensionUrl) => {
399
486
  const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
400
487
  templateOrExtensionUrl
@@ -428,11 +515,11 @@ var getInstallableSetup = ({
428
515
  devDependencies: getInstallableDeps(devDependencies)
429
516
  };
430
517
  };
431
- var requireIfExists = (path4) => {
432
- if (existsSync(path4)) {
433
- return __require(path4);
518
+ var requireIfExists = (path5) => {
519
+ if (existsSync(path5)) {
520
+ return __require(path5);
434
521
  }
435
- throw new Error(`File ${path4} does not exist`);
522
+ throw new Error(`File ${path5} does not exist`);
436
523
  };
437
524
  var loadPackages = async ({
438
525
  templatesOrExtensions = [],
@@ -442,10 +529,10 @@ var loadPackages = async ({
442
529
  const setup = await Promise.all(
443
530
  templatesOrExtensions.map(async ({ url: templateOrExtension }) => {
444
531
  try {
445
- const template = requireIfExists(
532
+ const template2 = requireIfExists(
446
533
  await getPackagePath(templateOrExtension, "template.json")
447
534
  );
448
- return template.package || {};
535
+ return template2.package || {};
449
536
  } catch {
450
537
  return {};
451
538
  }
@@ -498,12 +585,13 @@ var loadPackages = async ({
498
585
  };
499
586
 
500
587
  // loaders.ts
501
- import _ from "underscore";
502
588
  import fs3 from "fs";
503
589
  import pc2 from "picocolors";
504
590
  import { readdirp } from "readdirp";
505
591
  import { dirname } from "path";
506
592
  import { promisify } from "util";
593
+ import lodash from "lodash";
594
+ var { template } = lodash;
507
595
  var writeFileAsync = promisify(fs3.writeFile);
508
596
  var copyFileAsync = promisify(fs3.copyFile);
509
597
  var SRC_PATH_PATTERN = "[src]/";
@@ -514,8 +602,8 @@ var makeDirectory = (dirPath) => {
514
602
  fs3.mkdirSync(dirPath, { recursive: true });
515
603
  }
516
604
  };
517
- var getModeFromPath = (path4 = "") => {
518
- const matchExts = (...exts) => exts.find((ext) => path4.endsWith(ext));
605
+ var getModeFromPath = (path5 = "") => {
606
+ const matchExts = (...exts) => exts.find((ext) => path5.endsWith(ext));
519
607
  if (matchExts(".append")) {
520
608
  return "append";
521
609
  }
@@ -532,6 +620,11 @@ var batchedCopyFiles = async (operations) => {
532
620
  try {
533
621
  makeDirectory(dirname(operation.dest));
534
622
  await copyFileAsync(operation.src, operation.dest);
623
+ try {
624
+ const srcStat = await promisify(fs3.stat)(operation.src);
625
+ await promisify(fs3.chmod)(operation.dest, srcStat.mode);
626
+ } catch {
627
+ }
535
628
  if (operation.verbose) {
536
629
  console.log(
537
630
  pc2.green(
@@ -598,12 +691,12 @@ var batchedAppendFiles = async (operations) => {
598
691
  });
599
692
  await Promise.all(batchedPromises);
600
693
  };
601
- var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path4 }) => {
694
+ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
602
695
  const operations = [];
603
696
  try {
604
- const newPath = path4.replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
697
+ const newPath = path5.replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
605
698
  operations.push({
606
- src: `${templateDir}/${path4}`,
699
+ src: `${templateDir}/${path5}`,
607
700
  dest: `${root}/${newPath}`,
608
701
  verbose
609
702
  });
@@ -615,12 +708,12 @@ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path
615
708
  }
616
709
  await batchedCopyFiles(operations);
617
710
  };
618
- var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path4 }) => {
711
+ var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
619
712
  const operations = [];
620
713
  try {
621
- const newPath = path4.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
714
+ const newPath = path5.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
622
715
  operations.push({
623
- src: `${templateDir}/${path4}`,
716
+ src: `${templateDir}/${path5}`,
624
717
  dest: `${root}/${newPath}`,
625
718
  verbose
626
719
  });
@@ -642,15 +735,15 @@ var templateLoader = ({
642
735
  runCommand,
643
736
  installCommand,
644
737
  ...customOptions
645
- }) => async ({ path: path4 }) => {
738
+ }) => async ({ path: path5 }) => {
646
739
  const operations = [];
647
740
  try {
648
741
  const flag = mode.includes("append") ? "a+" : "w";
649
- const filePath = `${templateDir}/${path4}`;
742
+ const filePath = `${templateDir}/${path5}`;
650
743
  const file = await promisify(fs3.readFile)(filePath, "utf8");
651
744
  const fileMode = (await promisify(fs3.stat)(filePath)).mode;
652
- const newFile = _.template(file);
653
- const newPath = path4.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
745
+ const newFile = template(file);
746
+ const newPath = path5.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
654
747
  operations.push({
655
748
  path: `${root}/${newPath}`,
656
749
  content: newFile({
@@ -680,13 +773,14 @@ var fileLoader = ({
680
773
  verbose,
681
774
  useYarn,
682
775
  usePnpm,
776
+ useBun,
683
777
  srcDir = DEFAULT_SRC_PATH,
684
778
  runCommand,
685
779
  installCommand,
686
780
  ...customOptions
687
- }) => async ({ path: path4 }) => {
781
+ }) => async ({ path: path5 }) => {
688
782
  try {
689
- const mode = getModeFromPath(path4);
783
+ const mode = getModeFromPath(path5);
690
784
  const loaders = {
691
785
  copy: copyLoader,
692
786
  append: appendLoader,
@@ -702,13 +796,14 @@ var fileLoader = ({
702
796
  verbose,
703
797
  useYarn: !!useYarn,
704
798
  usePnpm: !!usePnpm,
799
+ useBun: !!useBun,
705
800
  mode,
706
801
  srcDir,
707
802
  runCommand,
708
803
  installCommand,
709
804
  ...customOptions
710
805
  })({
711
- path: path4
806
+ path: path5
712
807
  });
713
808
  } catch (err) {
714
809
  if (verbose) {
@@ -725,6 +820,7 @@ var loadFiles = async ({
725
820
  verbose,
726
821
  useYarn = false,
727
822
  usePnpm = false,
823
+ useBun = false,
728
824
  srcDir = DEFAULT_SRC_PATH,
729
825
  runCommand,
730
826
  installCommand,
@@ -755,7 +851,7 @@ var loadFiles = async ({
755
851
  /\byarn\.lock$/,
756
852
  /\bpnpm-lock\.yaml$/
757
853
  ];
758
- const skipManager = usePnpm ? [/\.if-npm\./, /\.if-yarn\./] : useYarn ? [/\.if-npm\./, /\.if-pnpm\./] : [/\.if-yarn\./, /\.if-pnpm\./];
854
+ 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\./];
759
855
  const shouldSkip = (p) => [...skipGlobs, ...skipManager].some((rgx) => rgx.test(p));
760
856
  for await (const entry of readdirp(templateDir, {
761
857
  type: "files",
@@ -775,6 +871,7 @@ var loadFiles = async ({
775
871
  verbose,
776
872
  useYarn,
777
873
  usePnpm,
874
+ useBun,
778
875
  srcDir,
779
876
  runCommand,
780
877
  installCommand,
@@ -810,7 +907,8 @@ var loadFiles = async ({
810
907
  };
811
908
 
812
909
  // installer.ts
813
- var install = async (root, useYarn = false, usePnpm = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
910
+ var { isEmpty } = lodash2;
911
+ var install = async (root, useYarn = false, usePnpm = false, useBun = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
814
912
  let command;
815
913
  let args;
816
914
  if (useYarn) {
@@ -839,6 +937,17 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
839
937
  args.push("--save");
840
938
  }
841
939
  args.push(...dependencies);
940
+ } else if (useBun) {
941
+ command = "bun";
942
+ if (dependencies.length > 0) {
943
+ args = ["add"];
944
+ if (isDevDependencies) {
945
+ args.push("--dev");
946
+ }
947
+ args.push(...dependencies);
948
+ } else {
949
+ args = ["install"];
950
+ }
842
951
  } else {
843
952
  command = "npm";
844
953
  args = ["install", "--loglevel", "error"];
@@ -853,7 +962,7 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
853
962
  args.push("--verbose");
854
963
  }
855
964
  try {
856
- execSync2(`${command} ${args.join(" ")}`, {
965
+ execFileSync2(resolveExecutable(command), args, {
857
966
  cwd: root,
858
967
  stdio: "inherit"
859
968
  });
@@ -862,8 +971,9 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
862
971
  }
863
972
  };
864
973
  var runCommandInProjectDir = async (root, command, args = [], successMessage = "Operation completed successfully.", errorMessage = "Operation failed.") => {
974
+ const [executable, ...baseArgs] = command === "npm run" ? ["npm", "run"] : command === "pnpm run" ? ["pnpm", "run"] : command === "bun run" ? ["bun", "run"] : [command];
865
975
  try {
866
- execSync2(`${command} ${args.join(" ")}`, {
976
+ execFileSync2(resolveExecutable(executable), [...baseArgs, ...args], {
867
977
  cwd: root,
868
978
  stdio: "ignore"
869
979
  });
@@ -891,6 +1001,7 @@ var run = async ({
891
1001
  verbose = false,
892
1002
  useYarn = false,
893
1003
  usePnpm = false,
1004
+ useBun = false,
894
1005
  templatesOrExtensions = [],
895
1006
  dependencies = [],
896
1007
  devDependencies = [],
@@ -900,7 +1011,7 @@ var run = async ({
900
1011
  ...customOptions
901
1012
  }) => {
902
1013
  const isOnline = useYarn ? await checkIfOnline(useYarn) : true;
903
- if (_2.isEmpty(templatesOrExtensions)) {
1014
+ if (isEmpty(templatesOrExtensions)) {
904
1015
  console.log();
905
1016
  console.log(
906
1017
  pc3.yellow(
@@ -920,6 +1031,7 @@ var run = async ({
920
1031
  verbose,
921
1032
  useYarn,
922
1033
  usePnpm,
1034
+ useBun,
923
1035
  runCommand,
924
1036
  installCommand,
925
1037
  ...customOptions
@@ -937,6 +1049,7 @@ var run = async ({
937
1049
  root,
938
1050
  useYarn,
939
1051
  usePnpm,
1052
+ useBun,
940
1053
  dependencies,
941
1054
  verbose,
942
1055
  isOnline,
@@ -950,6 +1063,7 @@ var run = async ({
950
1063
  root,
951
1064
  useYarn,
952
1065
  usePnpm,
1066
+ useBun,
953
1067
  devDependencies,
954
1068
  verbose,
955
1069
  isOnline,
@@ -1074,13 +1188,15 @@ var createApp = async ({
1074
1188
  console.log();
1075
1189
  const useYarn = customOptions.packageManager === "yarn" && shouldUseYarn();
1076
1190
  const usePnpm = customOptions.packageManager === "pnpm" && shouldUsePnpm();
1077
- const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : "npm run";
1078
- const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : "npm install";
1191
+ const useBun = customOptions.packageManager === "bun" && shouldUseBun();
1192
+ const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : useBun ? "bun run" : "npm run";
1193
+ const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : useBun ? "bun install" : "npm install";
1079
1194
  const { packageJson, dependencies, devDependencies } = await loadPackages({
1080
1195
  templatesOrExtensions,
1081
1196
  appName,
1082
1197
  usePnpm,
1083
1198
  useYarn,
1199
+ useBun,
1084
1200
  runCommand,
1085
1201
  ignorePackage
1086
1202
  });
@@ -1090,7 +1206,7 @@ var createApp = async ({
1090
1206
  );
1091
1207
  const originalDirectory = process.cwd();
1092
1208
  process.chdir(root);
1093
- if (!useYarn && !checkThatNpmCanReadCwd()) {
1209
+ if (!useYarn && !useBun && !checkThatNpmCanReadCwd()) {
1094
1210
  process.exit(1);
1095
1211
  }
1096
1212
  if (!semver2.satisfies(process.version, ">=18.0.0")) {
@@ -1103,7 +1219,7 @@ Please update to Node 18 or higher for a better, fully supported experience.
1103
1219
  )
1104
1220
  );
1105
1221
  }
1106
- if (!useYarn) {
1222
+ if (!useYarn && !useBun) {
1107
1223
  const npmInfo = checkNpmVersion();
1108
1224
  if (!npmInfo.hasMinNpm) {
1109
1225
  if (npmInfo.npmVersion) {
@@ -1121,7 +1237,11 @@ Please update to npm 3 or higher for a better, fully supported experience.
1121
1237
  if (useYarn) {
1122
1238
  let yarnUsesDefaultRegistry = true;
1123
1239
  try {
1124
- yarnUsesDefaultRegistry = execSync2("yarnpkg config get registry").toString().trim() === "https://registry.yarnpkg.com";
1240
+ yarnUsesDefaultRegistry = execFileSync2(resolveExecutable("yarnpkg"), [
1241
+ "config",
1242
+ "get",
1243
+ "registry"
1244
+ ]).toString().trim() === "https://registry.yarnpkg.com";
1125
1245
  } catch {
1126
1246
  }
1127
1247
  if (false) {
@@ -1139,6 +1259,7 @@ Please update to npm 3 or higher for a better, fully supported experience.
1139
1259
  verbose,
1140
1260
  useYarn,
1141
1261
  usePnpm,
1262
+ useBun,
1142
1263
  templatesOrExtensions,
1143
1264
  dependencies,
1144
1265
  devDependencies,
@@ -1149,6 +1270,22 @@ Please update to npm 3 or higher for a better, fully supported experience.
1149
1270
  });
1150
1271
  };
1151
1272
 
1273
+ // config.ts
1274
+ import fs5 from "fs";
1275
+ import path4 from "path";
1276
+ var loadTemplateCnaConfig = async (templateUrl) => {
1277
+ try {
1278
+ const basePath = await getTemplateBaseDirPath(templateUrl);
1279
+ if (!basePath) return null;
1280
+ const configPath = path4.join(basePath, "cna.config.json");
1281
+ if (!fs5.existsSync(configPath)) return null;
1282
+ const content = fs5.readFileSync(configPath, "utf8");
1283
+ return JSON.parse(content);
1284
+ } catch {
1285
+ return null;
1286
+ }
1287
+ };
1288
+
1152
1289
  // index.ts
1153
1290
  var checkNodeVersion = (requiredVersion, packageName) => {
1154
1291
  if (!semver3.satisfies(process.version, requiredVersion)) {
@@ -1177,7 +1314,11 @@ var checkForLatestVersion = async (packageName) => {
1177
1314
  return null;
1178
1315
  } catch {
1179
1316
  try {
1180
- return execSync3(`npm view ${packageName} version`).toString().trim();
1317
+ return execFileSync3(resolveExecutable("npm"), [
1318
+ "view",
1319
+ packageName,
1320
+ "version"
1321
+ ]).toString().trim();
1181
1322
  } catch {
1182
1323
  }
1183
1324
  }
@@ -1188,7 +1329,7 @@ var printEnvInfo = async () => {
1188
1329
  const info = await envinfo.run(
1189
1330
  {
1190
1331
  System: ["OS", "CPU", "Memory", "Shell"],
1191
- Binaries: ["Node", "npm", "pnpm", "Yarn", "Watchman"],
1332
+ Binaries: ["Node", "npm", "pnpm", "Yarn", "Bun", "Watchman"],
1192
1333
  Browsers: ["Chrome", "Edge", "Internet Explorer", "Firefox", "Safari"]
1193
1334
  },
1194
1335
  {
@@ -1226,7 +1367,9 @@ export {
1226
1367
  createNodeApp,
1227
1368
  downloadRepository,
1228
1369
  getPackagePath,
1370
+ getTemplateBaseDirPath,
1229
1371
  getTemplateDirPath,
1372
+ loadTemplateCnaConfig,
1230
1373
  printEnvInfo
1231
1374
  };
1232
1375
  //# sourceMappingURL=index.js.map