@create-node-app/core 0.6.0 → 0.6.2

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
@@ -5,28 +5,40 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
+ // ../../node_modules/tsup/assets/esm_shims.js
9
+ import path from "path";
10
+ import { fileURLToPath } from "url";
11
+ var getFilename = () => fileURLToPath(import.meta.url);
12
+ var getDirname = () => path.dirname(getFilename());
13
+ var __dirname = /* @__PURE__ */ getDirname();
14
+
8
15
  // index.ts
9
16
  import pc4 from "picocolors";
10
17
  import envinfo from "envinfo";
11
18
  import semver3 from "semver";
12
- import { execSync as execSync3 } from "child_process";
19
+ import { execFileSync as execFileSync3 } from "child_process";
13
20
 
14
21
  // installer.ts
15
- import _2 from "underscore";
16
- import path3 from "path";
22
+ import lodash2 from "lodash";
23
+ import path4 from "path";
17
24
  import fs4 from "fs";
18
25
  import pc3 from "picocolors";
19
26
  import os3 from "os";
20
27
  import semver2 from "semver";
21
- import { execSync as execSync2 } from "child_process";
28
+ import { execFileSync as execFileSync2 } from "child_process";
22
29
 
23
30
  // helpers.ts
24
- import { execSync } from "child_process";
31
+ import { execFileSync } from "child_process";
25
32
  import spawn from "cross-spawn";
26
33
  import pc from "picocolors";
27
34
  import semver from "semver";
28
35
  import dns from "dns";
29
36
  import { URL as URL2 } from "url";
37
+
38
+ // executable.ts
39
+ var resolveExecutable = (bin) => process.platform === "win32" ? `${bin}.cmd` : bin;
40
+
41
+ // helpers.ts
30
42
  var shouldUseYarn = () => {
31
43
  const { hasMinYarnPnp, hasMaxYarnPnp, yarnVersion } = checkYarnVersion();
32
44
  if (!hasMinYarnPnp) {
@@ -63,6 +75,20 @@ var shouldUsePnpm = () => {
63
75
  }
64
76
  return true;
65
77
  };
78
+ var shouldUseBun = () => {
79
+ const { hasMinBun, bunVersion } = checkBunVersion();
80
+ if (!hasMinBun) {
81
+ console.log(
82
+ pc.yellow(
83
+ `You are using bun version ${pc.bold(
84
+ bunVersion
85
+ )} which is not supported yet. To use bun, install v1.0.0 or higher. See https://bun.sh for instructions on how to install.`
86
+ )
87
+ );
88
+ return false;
89
+ }
90
+ return true;
91
+ };
66
92
  var checkThatNpmCanReadCwd = () => {
67
93
  const cwd = process.cwd();
68
94
  let childOutput = null;
@@ -118,7 +144,7 @@ var checkPnpmVersion = () => {
118
144
  let hasMinPnpm = false;
119
145
  let pnpmVersion = null;
120
146
  try {
121
- pnpmVersion = execSync("pnpm --version").toString().trim();
147
+ pnpmVersion = execFileSync(resolveExecutable("pnpm"), ["--version"]).toString().trim();
122
148
  if (semver.valid(pnpmVersion)) {
123
149
  hasMinPnpm = semver.gte(pnpmVersion, minPnpm);
124
150
  } else {
@@ -131,6 +157,19 @@ var checkPnpmVersion = () => {
131
157
  }
132
158
  return { hasMinPnpm, pnpmVersion };
133
159
  };
160
+ var checkBunVersion = () => {
161
+ const minBun = "1.0.0";
162
+ let hasMinBun = false;
163
+ let bunVersion = null;
164
+ try {
165
+ bunVersion = execFileSync(resolveExecutable("bun"), ["--version"]).toString().trim();
166
+ if (semver.valid(bunVersion)) {
167
+ hasMinBun = semver.gte(bunVersion, minBun);
168
+ }
169
+ } catch {
170
+ }
171
+ return { hasMinBun, bunVersion };
172
+ };
134
173
  var checkYarnVersion = () => {
135
174
  const minYarnPnp = "1.12.0";
136
175
  const maxYarnPnp = "2.0.0";
@@ -138,7 +177,7 @@ var checkYarnVersion = () => {
138
177
  let hasMaxYarnPnp = false;
139
178
  let yarnVersion = null;
140
179
  try {
141
- yarnVersion = execSync("yarnpkg --version").toString().trim();
180
+ yarnVersion = execFileSync(resolveExecutable("yarnpkg"), ["--version"]).toString().trim();
142
181
  if (semver.valid(yarnVersion)) {
143
182
  hasMinYarnPnp = semver.gte(yarnVersion, minYarnPnp);
144
183
  hasMaxYarnPnp = semver.lt(yarnVersion, maxYarnPnp);
@@ -164,7 +203,7 @@ var checkNpmVersion = () => {
164
203
  let hasMinNpm = false;
165
204
  let npmVersion = null;
166
205
  try {
167
- npmVersion = execSync("npm --version").toString().trim();
206
+ npmVersion = execFileSync(resolveExecutable("npm"), ["--version"]).toString().trim();
168
207
  hasMinNpm = semver.gte(npmVersion, "6.0.0");
169
208
  } catch {
170
209
  }
@@ -178,7 +217,11 @@ var getProxy = () => {
178
217
  return process.env.HTTPS_PROXY;
179
218
  }
180
219
  try {
181
- const httpsProxy = execSync("npm config get https-proxy").toString().trim();
220
+ const httpsProxy = execFileSync(resolveExecutable("npm"), [
221
+ "config",
222
+ "get",
223
+ "https-proxy"
224
+ ]).toString().trim();
182
225
  return httpsProxy !== "null" ? httpsProxy : void 0;
183
226
  } catch {
184
227
  }
@@ -209,16 +252,46 @@ import merge from "lodash.merge";
209
252
  // paths.ts
210
253
  import fs2 from "fs";
211
254
  import os2 from "os";
212
- import path2 from "path";
255
+ import path3 from "path";
256
+ import debug2 from "debug";
213
257
 
214
258
  // git.ts
215
259
  import os from "os";
216
- import path from "path";
260
+ import path2 from "path";
217
261
  import fs from "fs";
218
262
  import debug from "debug";
219
263
  import { simpleGit } from "simple-git";
220
264
  import * as fse from "fs-extra";
221
265
  var log = debug("cna:git");
266
+ var formatRepositoryDownloadError = (error, url) => {
267
+ const message = error instanceof Error ? error.message : String(error);
268
+ if (/not found|404|repository not found/i.test(message)) {
269
+ return [
270
+ `Error: Could not fetch template from '${url}'.`,
271
+ " \u2192 The URL returned HTTP 404 or the repository was not found. Please verify the URL is correct.",
272
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
273
+ ].join("\n");
274
+ }
275
+ if (/403|authentication|permission denied|access denied/i.test(message)) {
276
+ return [
277
+ `Error: Could not fetch template from '${url}'.`,
278
+ " \u2192 Access denied (HTTP 403). Check that the repository is public or you have access.",
279
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
280
+ ].join("\n");
281
+ }
282
+ if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(message)) {
283
+ return [
284
+ `Error: Could not fetch template from '${url}'.`,
285
+ " \u2192 Could not reach the repository. Please check your internet connection.",
286
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
287
+ ].join("\n");
288
+ }
289
+ return [
290
+ `Error: Could not fetch template from '${url}'.`,
291
+ ` \u2192 ${message}`,
292
+ " \u2192 Run 'npx create-awesome-node-app --list-templates' to see available templates."
293
+ ].join("\n");
294
+ };
222
295
  var filterGit = (src) => {
223
296
  return !/(\\|\/)\.git\b/.test(src);
224
297
  };
@@ -232,12 +305,13 @@ var downloadRepository = async ({
232
305
  targetId,
233
306
  cacheDir: optsCacheDir
234
307
  }) => {
235
- const absoluteTarget = path.isAbsolute(target) ? target : path.resolve(target);
308
+ const absoluteTarget = path2.isAbsolute(target) ? target : path2.resolve(target);
309
+ const targetExistedBefore = fs.existsSync(absoluteTarget);
236
310
  const isGithub = /^[^/]+\/[^/]+$/.test(url);
237
311
  const gitUrl = isGithub ? `https://github.com/${url}` : url;
238
312
  const id = targetId || Buffer.from(`${gitUrl}@${branch}`).toString("base64");
239
- let cacheDir = optsCacheDir || path.join(os.homedir(), ".cache", "cna", id);
240
- cacheDir = path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cacheDir);
313
+ let cacheDir = optsCacheDir || path2.join(os.homedir(), ".cache", "cna", id);
314
+ cacheDir = path2.isAbsolute(cacheDir) ? cacheDir : path2.resolve(cacheDir);
241
315
  log("cache folder: %s", cacheDir);
242
316
  if (completedTargetIds.has(id)) {
243
317
  log(
@@ -283,7 +357,15 @@ var downloadRepository = async ({
283
357
  });
284
358
  completedTargetIds.set(id, true);
285
359
  } catch (error) {
286
- console.error("Error during repository download:", error);
360
+ if (!targetExistedBefore && fs.existsSync(absoluteTarget)) {
361
+ try {
362
+ fse.removeSync(absoluteTarget);
363
+ log("Cleaned up partially created directory: %s", absoluteTarget);
364
+ } catch (cleanupErr) {
365
+ log("Failed to clean up directory: %s", cleanupErr);
366
+ }
367
+ }
368
+ throw new Error(formatRepositoryDownloadError(error, gitUrl));
287
369
  } finally {
288
370
  gitOperationMap.delete(id);
289
371
  }
@@ -293,6 +375,8 @@ var downloadRepository = async ({
293
375
  };
294
376
 
295
377
  // paths.ts
378
+ var log2 = debug2("cna:paths");
379
+ var moduleDir = __dirname;
296
380
  var solveValuesFromTemplateOrExtensionUrl = (templateOrExtension) => {
297
381
  const url = new URL(templateOrExtension);
298
382
  const ignorePackage = url.searchParams.get("ignorePackage") === "true";
@@ -342,34 +426,27 @@ var solveRepositoryPath = async ({
342
426
  const targetWithSubdir = Buffer.from(`${url}#${branch}#${subdir}`).toString(
343
427
  "base64"
344
428
  );
345
- const target = path2.join(os2.homedir(), ".cna", targetWithSubdir);
429
+ const target = path3.join(os2.homedir(), ".cna", targetWithSubdir);
346
430
  if (process.env.CNA_SKIP_GIT === "1") {
347
431
  return { dir: target, subdir };
348
432
  }
349
- try {
350
- await downloadRepository({
351
- url,
352
- branch: branch || "",
353
- target,
354
- targetId
355
- });
356
- } catch {
357
- }
433
+ await downloadRepository({
434
+ url,
435
+ branch: branch || "",
436
+ target,
437
+ targetId
438
+ });
358
439
  return { dir: target, subdir };
359
440
  };
360
441
  var solveTemplateOrExtensionPath = async (templateOrExtension) => {
442
+ let parsed;
361
443
  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 };
444
+ parsed = solveValuesFromTemplateOrExtensionUrl(templateOrExtension);
369
445
  } catch {
446
+ log2("Falling back to legacy template path for: %s", templateOrExtension);
370
447
  return {
371
- dir: path2.resolve(
372
- __dirname,
448
+ dir: path3.resolve(
449
+ moduleDir,
373
450
  "..",
374
451
  "templatesOrExtensions",
375
452
  templateOrExtension
@@ -378,6 +455,12 @@ var solveTemplateOrExtensionPath = async (templateOrExtension) => {
378
455
  ignorePackage: void 0
379
456
  };
380
457
  }
458
+ const { url, branch, subdir, protocol, pathname, ignorePackage } = parsed;
459
+ if (protocol === "file:") {
460
+ return { dir: pathname, subdir, ignorePackage };
461
+ }
462
+ const gitData = await solveRepositoryPath({ url, branch, subdir });
463
+ return { dir: gitData.dir, subdir: gitData.subdir, ignorePackage };
381
464
  };
382
465
  var getPackagePath = async (templateOrExtension, name = "package", ignorePackage = false) => {
383
466
  const {
@@ -391,16 +474,16 @@ var getPackagePath = async (templateOrExtension, name = "package", ignorePackage
391
474
  );
392
475
  }
393
476
  if (subdir) {
394
- return path2.resolve(dir, subdir, name);
477
+ return path3.resolve(dir, subdir, name);
395
478
  }
396
- return path2.resolve(dir, name);
479
+ return path3.resolve(dir, name);
397
480
  };
398
481
  var getTemplateBaseDirPath = async (templateOrExtensionUrl) => {
399
482
  try {
400
483
  const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
401
484
  templateOrExtensionUrl
402
485
  );
403
- return path2.resolve(dir, subdir);
486
+ return path3.resolve(dir, subdir);
404
487
  } catch {
405
488
  return "";
406
489
  }
@@ -409,8 +492,8 @@ var getTemplateDirPath = async (templateOrExtensionUrl) => {
409
492
  const { dir, subdir = "" } = await solveTemplateOrExtensionPath(
410
493
  templateOrExtensionUrl
411
494
  );
412
- let templateDirPath = path2.resolve(dir, subdir);
413
- const templateDirPathWithTemplate = path2.resolve(templateDirPath, "template");
495
+ let templateDirPath = path3.resolve(dir, subdir);
496
+ const templateDirPathWithTemplate = path3.resolve(templateDirPath, "template");
414
497
  return new Promise((resolve) => {
415
498
  fs2.stat(templateDirPathWithTemplate, (_err, stats) => {
416
499
  if (_err) {
@@ -438,11 +521,11 @@ var getInstallableSetup = ({
438
521
  devDependencies: getInstallableDeps(devDependencies)
439
522
  };
440
523
  };
441
- var requireIfExists = (path5) => {
442
- if (existsSync(path5)) {
443
- return __require(path5);
524
+ var requireIfExists = (path6) => {
525
+ if (existsSync(path6)) {
526
+ return __require(path6);
444
527
  }
445
- throw new Error(`File ${path5} does not exist`);
528
+ throw new Error(`File ${path6} does not exist`);
446
529
  };
447
530
  var loadPackages = async ({
448
531
  templatesOrExtensions = [],
@@ -452,10 +535,10 @@ var loadPackages = async ({
452
535
  const setup = await Promise.all(
453
536
  templatesOrExtensions.map(async ({ url: templateOrExtension }) => {
454
537
  try {
455
- const template = requireIfExists(
538
+ const template2 = requireIfExists(
456
539
  await getPackagePath(templateOrExtension, "template.json")
457
540
  );
458
- return template.package || {};
541
+ return template2.package || {};
459
542
  } catch {
460
543
  return {};
461
544
  }
@@ -508,12 +591,13 @@ var loadPackages = async ({
508
591
  };
509
592
 
510
593
  // loaders.ts
511
- import _ from "underscore";
512
594
  import fs3 from "fs";
513
595
  import pc2 from "picocolors";
514
596
  import { readdirp } from "readdirp";
515
597
  import { dirname } from "path";
516
598
  import { promisify } from "util";
599
+ import lodash from "lodash";
600
+ var { template } = lodash;
517
601
  var writeFileAsync = promisify(fs3.writeFile);
518
602
  var copyFileAsync = promisify(fs3.copyFile);
519
603
  var SRC_PATH_PATTERN = "[src]/";
@@ -524,8 +608,8 @@ var makeDirectory = (dirPath) => {
524
608
  fs3.mkdirSync(dirPath, { recursive: true });
525
609
  }
526
610
  };
527
- var getModeFromPath = (path5 = "") => {
528
- const matchExts = (...exts) => exts.find((ext) => path5.endsWith(ext));
611
+ var getModeFromPath = (path6 = "") => {
612
+ const matchExts = (...exts) => exts.find((ext) => path6.endsWith(ext));
529
613
  if (matchExts(".append")) {
530
614
  return "append";
531
615
  }
@@ -542,6 +626,11 @@ var batchedCopyFiles = async (operations) => {
542
626
  try {
543
627
  makeDirectory(dirname(operation.dest));
544
628
  await copyFileAsync(operation.src, operation.dest);
629
+ try {
630
+ const srcStat = await promisify(fs3.stat)(operation.src);
631
+ await promisify(fs3.chmod)(operation.dest, srcStat.mode);
632
+ } catch {
633
+ }
545
634
  if (operation.verbose) {
546
635
  console.log(
547
636
  pc2.green(
@@ -608,12 +697,12 @@ var batchedAppendFiles = async (operations) => {
608
697
  });
609
698
  await Promise.all(batchedPromises);
610
699
  };
611
- var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
700
+ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path6 }) => {
612
701
  const operations = [];
613
702
  try {
614
- const newPath = path5.replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
703
+ const newPath = path6.replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
615
704
  operations.push({
616
- src: `${templateDir}/${path5}`,
705
+ src: `${templateDir}/${path6}`,
617
706
  dest: `${root}/${newPath}`,
618
707
  verbose
619
708
  });
@@ -625,12 +714,12 @@ var copyLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path
625
714
  }
626
715
  await batchedCopyFiles(operations);
627
716
  };
628
- var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path5 }) => {
717
+ var appendLoader = ({ root, templateDir, verbose, srcDir }) => async ({ path: path6 }) => {
629
718
  const operations = [];
630
719
  try {
631
- const newPath = path5.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
720
+ const newPath = path6.replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
632
721
  operations.push({
633
- src: `${templateDir}/${path5}`,
722
+ src: `${templateDir}/${path6}`,
634
723
  dest: `${root}/${newPath}`,
635
724
  verbose
636
725
  });
@@ -652,15 +741,15 @@ var templateLoader = ({
652
741
  runCommand,
653
742
  installCommand,
654
743
  ...customOptions
655
- }) => async ({ path: path5 }) => {
744
+ }) => async ({ path: path6 }) => {
656
745
  const operations = [];
657
746
  try {
658
747
  const flag = mode.includes("append") ? "a+" : "w";
659
- const filePath = `${templateDir}/${path5}`;
748
+ const filePath = `${templateDir}/${path6}`;
660
749
  const file = await promisify(fs3.readFile)(filePath, "utf8");
661
750
  const fileMode = (await promisify(fs3.stat)(filePath)).mode;
662
- const newFile = _.template(file);
663
- const newPath = path5.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
751
+ const newFile = template(file);
752
+ const newPath = path6.replace(/.template$/, "").replace(/.append$/, "").replace(/.if-(npm|yarn|pnpm|bun)$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
664
753
  operations.push({
665
754
  path: `${root}/${newPath}`,
666
755
  content: newFile({
@@ -690,13 +779,14 @@ var fileLoader = ({
690
779
  verbose,
691
780
  useYarn,
692
781
  usePnpm,
782
+ useBun,
693
783
  srcDir = DEFAULT_SRC_PATH,
694
784
  runCommand,
695
785
  installCommand,
696
786
  ...customOptions
697
- }) => async ({ path: path5 }) => {
787
+ }) => async ({ path: path6 }) => {
698
788
  try {
699
- const mode = getModeFromPath(path5);
789
+ const mode = getModeFromPath(path6);
700
790
  const loaders = {
701
791
  copy: copyLoader,
702
792
  append: appendLoader,
@@ -712,13 +802,14 @@ var fileLoader = ({
712
802
  verbose,
713
803
  useYarn: !!useYarn,
714
804
  usePnpm: !!usePnpm,
805
+ useBun: !!useBun,
715
806
  mode,
716
807
  srcDir,
717
808
  runCommand,
718
809
  installCommand,
719
810
  ...customOptions
720
811
  })({
721
- path: path5
812
+ path: path6
722
813
  });
723
814
  } catch (err) {
724
815
  if (verbose) {
@@ -735,6 +826,7 @@ var loadFiles = async ({
735
826
  verbose,
736
827
  useYarn = false,
737
828
  usePnpm = false,
829
+ useBun = false,
738
830
  srcDir = DEFAULT_SRC_PATH,
739
831
  runCommand,
740
832
  installCommand,
@@ -765,7 +857,7 @@ var loadFiles = async ({
765
857
  /\byarn\.lock$/,
766
858
  /\bpnpm-lock\.yaml$/
767
859
  ];
768
- const skipManager = usePnpm ? [/\.if-npm\./, /\.if-yarn\./] : useYarn ? [/\.if-npm\./, /\.if-pnpm\./] : [/\.if-yarn\./, /\.if-pnpm\./];
860
+ 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\./];
769
861
  const shouldSkip = (p) => [...skipGlobs, ...skipManager].some((rgx) => rgx.test(p));
770
862
  for await (const entry of readdirp(templateDir, {
771
863
  type: "files",
@@ -785,6 +877,7 @@ var loadFiles = async ({
785
877
  verbose,
786
878
  useYarn,
787
879
  usePnpm,
880
+ useBun,
788
881
  srcDir,
789
882
  runCommand,
790
883
  installCommand,
@@ -820,7 +913,8 @@ var loadFiles = async ({
820
913
  };
821
914
 
822
915
  // installer.ts
823
- var install = async (root, useYarn = false, usePnpm = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
916
+ var { isEmpty } = lodash2;
917
+ var install = async (root, useYarn = false, usePnpm = false, useBun = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
824
918
  let command;
825
919
  let args;
826
920
  if (useYarn) {
@@ -849,6 +943,17 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
849
943
  args.push("--save");
850
944
  }
851
945
  args.push(...dependencies);
946
+ } else if (useBun) {
947
+ command = "bun";
948
+ if (dependencies.length > 0) {
949
+ args = ["add"];
950
+ if (isDevDependencies) {
951
+ args.push("--dev");
952
+ }
953
+ args.push(...dependencies);
954
+ } else {
955
+ args = ["install"];
956
+ }
852
957
  } else {
853
958
  command = "npm";
854
959
  args = ["install", "--loglevel", "error"];
@@ -863,7 +968,7 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
863
968
  args.push("--verbose");
864
969
  }
865
970
  try {
866
- execSync2(`${command} ${args.join(" ")}`, {
971
+ execFileSync2(resolveExecutable(command), args, {
867
972
  cwd: root,
868
973
  stdio: "inherit"
869
974
  });
@@ -872,8 +977,9 @@ var install = async (root, useYarn = false, usePnpm = false, dependencies = [],
872
977
  }
873
978
  };
874
979
  var runCommandInProjectDir = async (root, command, args = [], successMessage = "Operation completed successfully.", errorMessage = "Operation failed.") => {
980
+ const [executable, ...baseArgs] = command === "npm run" ? ["npm", "run"] : command === "pnpm run" ? ["pnpm", "run"] : command === "bun run" ? ["bun", "run"] : [command];
875
981
  try {
876
- execSync2(`${command} ${args.join(" ")}`, {
982
+ execFileSync2(resolveExecutable(executable), [...baseArgs, ...args], {
877
983
  cwd: root,
878
984
  stdio: "ignore"
879
985
  });
@@ -901,6 +1007,7 @@ var run = async ({
901
1007
  verbose = false,
902
1008
  useYarn = false,
903
1009
  usePnpm = false,
1010
+ useBun = false,
904
1011
  templatesOrExtensions = [],
905
1012
  dependencies = [],
906
1013
  devDependencies = [],
@@ -910,7 +1017,7 @@ var run = async ({
910
1017
  ...customOptions
911
1018
  }) => {
912
1019
  const isOnline = useYarn ? await checkIfOnline(useYarn) : true;
913
- if (_2.isEmpty(templatesOrExtensions)) {
1020
+ if (isEmpty(templatesOrExtensions)) {
914
1021
  console.log();
915
1022
  console.log(
916
1023
  pc3.yellow(
@@ -930,6 +1037,7 @@ var run = async ({
930
1037
  verbose,
931
1038
  useYarn,
932
1039
  usePnpm,
1040
+ useBun,
933
1041
  runCommand,
934
1042
  installCommand,
935
1043
  ...customOptions
@@ -947,6 +1055,7 @@ var run = async ({
947
1055
  root,
948
1056
  useYarn,
949
1057
  usePnpm,
1058
+ useBun,
950
1059
  dependencies,
951
1060
  verbose,
952
1061
  isOnline,
@@ -960,6 +1069,7 @@ var run = async ({
960
1069
  root,
961
1070
  useYarn,
962
1071
  usePnpm,
1072
+ useBun,
963
1073
  devDependencies,
964
1074
  verbose,
965
1075
  isOnline,
@@ -989,7 +1099,7 @@ var run = async ({
989
1099
  packageJson2.dependencies = updateDependencies(dependencies);
990
1100
  packageJson2.devDependencies = updateDependencies(devDependencies);
991
1101
  fs4.writeFileSync(
992
- path3.join(root, "package.json"),
1102
+ path4.join(root, "package.json"),
993
1103
  JSON.stringify(packageJson2, null, 2) + os3.EOL
994
1104
  );
995
1105
  console.log();
@@ -1075,8 +1185,8 @@ var createApp = async ({
1075
1185
  ignorePackage = false,
1076
1186
  ...customOptions
1077
1187
  }) => {
1078
- const root = path3.resolve(name);
1079
- const appName = path3.basename(root);
1188
+ const root = path4.resolve(name);
1189
+ const appName = path4.basename(root);
1080
1190
  fs4.mkdirSync(name, {
1081
1191
  recursive: true
1082
1192
  });
@@ -1084,23 +1194,25 @@ var createApp = async ({
1084
1194
  console.log();
1085
1195
  const useYarn = customOptions.packageManager === "yarn" && shouldUseYarn();
1086
1196
  const usePnpm = customOptions.packageManager === "pnpm" && shouldUsePnpm();
1087
- const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : "npm run";
1088
- const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : "npm install";
1197
+ const useBun = customOptions.packageManager === "bun" && shouldUseBun();
1198
+ const runCommand = useYarn ? "yarn" : usePnpm ? "pnpm run" : useBun ? "bun run" : "npm run";
1199
+ const installCommand = useYarn ? "yarn" : usePnpm ? "pnpm install" : useBun ? "bun install" : "npm install";
1089
1200
  const { packageJson, dependencies, devDependencies } = await loadPackages({
1090
1201
  templatesOrExtensions,
1091
1202
  appName,
1092
1203
  usePnpm,
1093
1204
  useYarn,
1205
+ useBun,
1094
1206
  runCommand,
1095
1207
  ignorePackage
1096
1208
  });
1097
1209
  fs4.writeFileSync(
1098
- path3.join(root, "package.json"),
1210
+ path4.join(root, "package.json"),
1099
1211
  JSON.stringify(packageJson, null, 2) + os3.EOL
1100
1212
  );
1101
1213
  const originalDirectory = process.cwd();
1102
1214
  process.chdir(root);
1103
- if (!useYarn && !checkThatNpmCanReadCwd()) {
1215
+ if (!useYarn && !useBun && !checkThatNpmCanReadCwd()) {
1104
1216
  process.exit(1);
1105
1217
  }
1106
1218
  if (!semver2.satisfies(process.version, ">=18.0.0")) {
@@ -1113,7 +1225,7 @@ Please update to Node 18 or higher for a better, fully supported experience.
1113
1225
  )
1114
1226
  );
1115
1227
  }
1116
- if (!useYarn) {
1228
+ if (!useYarn && !useBun) {
1117
1229
  const npmInfo = checkNpmVersion();
1118
1230
  if (!npmInfo.hasMinNpm) {
1119
1231
  if (npmInfo.npmVersion) {
@@ -1131,13 +1243,17 @@ Please update to npm 3 or higher for a better, fully supported experience.
1131
1243
  if (useYarn) {
1132
1244
  let yarnUsesDefaultRegistry = true;
1133
1245
  try {
1134
- yarnUsesDefaultRegistry = execSync2("yarnpkg config get registry").toString().trim() === "https://registry.yarnpkg.com";
1246
+ yarnUsesDefaultRegistry = execFileSync2(resolveExecutable("yarnpkg"), [
1247
+ "config",
1248
+ "get",
1249
+ "registry"
1250
+ ]).toString().trim() === "https://registry.yarnpkg.com";
1135
1251
  } catch {
1136
1252
  }
1137
1253
  if (false) {
1138
1254
  fs4.cpSync(
1139
1255
  __require.resolve("./yarn.lock.cached"),
1140
- path3.join(root, "yarn.lock"),
1256
+ path4.join(root, "yarn.lock"),
1141
1257
  { force: true }
1142
1258
  );
1143
1259
  }
@@ -1149,6 +1265,7 @@ Please update to npm 3 or higher for a better, fully supported experience.
1149
1265
  verbose,
1150
1266
  useYarn,
1151
1267
  usePnpm,
1268
+ useBun,
1152
1269
  templatesOrExtensions,
1153
1270
  dependencies,
1154
1271
  devDependencies,
@@ -1161,12 +1278,12 @@ Please update to npm 3 or higher for a better, fully supported experience.
1161
1278
 
1162
1279
  // config.ts
1163
1280
  import fs5 from "fs";
1164
- import path4 from "path";
1281
+ import path5 from "path";
1165
1282
  var loadTemplateCnaConfig = async (templateUrl) => {
1166
1283
  try {
1167
1284
  const basePath = await getTemplateBaseDirPath(templateUrl);
1168
1285
  if (!basePath) return null;
1169
- const configPath = path4.join(basePath, "cna.config.json");
1286
+ const configPath = path5.join(basePath, "cna.config.json");
1170
1287
  if (!fs5.existsSync(configPath)) return null;
1171
1288
  const content = fs5.readFileSync(configPath, "utf8");
1172
1289
  return JSON.parse(content);
@@ -1203,7 +1320,11 @@ var checkForLatestVersion = async (packageName) => {
1203
1320
  return null;
1204
1321
  } catch {
1205
1322
  try {
1206
- return execSync3(`npm view ${packageName} version`).toString().trim();
1323
+ return execFileSync3(resolveExecutable("npm"), [
1324
+ "view",
1325
+ packageName,
1326
+ "version"
1327
+ ]).toString().trim();
1207
1328
  } catch {
1208
1329
  }
1209
1330
  }
@@ -1214,7 +1335,7 @@ var printEnvInfo = async () => {
1214
1335
  const info = await envinfo.run(
1215
1336
  {
1216
1337
  System: ["OS", "CPU", "Memory", "Shell"],
1217
- Binaries: ["Node", "npm", "pnpm", "Yarn", "Watchman"],
1338
+ Binaries: ["Node", "npm", "pnpm", "Yarn", "Bun", "Watchman"],
1218
1339
  Browsers: ["Chrome", "Edge", "Internet Explorer", "Firefox", "Safari"]
1219
1340
  },
1220
1341
  {