@vercel/build-utils 14.1.0 → 14.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 14.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - b4f09c1: Support selecting Bun 1.4.x as an explicit runtime and build-time package manager, including local Bun servers.
8
+
3
9
  ## 14.1.0
4
10
 
5
11
  ### Minor Changes
@@ -1,5 +1,5 @@
1
1
  import type { BuildResultV2Typical, BuildResultV3, BuilderFunctions, Config } from '../types';
2
- export declare const SUPPORTED_AL2023_RUNTIMES: readonly ["nodejs20.x", "nodejs22.x", "nodejs24.x", "provided.al2023", "python3.12", "python3.13", "python3.14", "ruby3.3", "bun1.x", "executable"];
2
+ export declare const SUPPORTED_AL2023_RUNTIMES: readonly ["nodejs20.x", "nodejs22.x", "nodejs24.x", "provided.al2023", "python3.12", "python3.13", "python3.14", "ruby3.3", "bun1.4.x", "bun1.x", "executable"];
3
3
  type BuildConfigWithVercelConfig = Config & {
4
4
  vercelConfig?: {
5
5
  functions?: BuilderFunctions;
@@ -43,6 +43,7 @@ const SUPPORTED_AL2023_RUNTIMES = [
43
43
  "python3.13",
44
44
  "python3.14",
45
45
  "ruby3.3",
46
+ "bun1.4.x",
46
47
  "bun1.x",
47
48
  "executable"
48
49
  ];
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns the Bun binary, installing it with the official installer when it is
3
+ * not already available in PATH or Bun's default installation directory.
4
+ */
5
+ export declare function getOrCreateBunBinary(): Promise<string>;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var bun_helpers_exports = {};
30
+ __export(bun_helpers_exports, {
31
+ getOrCreateBunBinary: () => getOrCreateBunBinary
32
+ });
33
+ module.exports = __toCommonJS(bun_helpers_exports);
34
+ var import_os = require("os");
35
+ var import_path = require("path");
36
+ var import_child_process = require("child_process");
37
+ var import_debug = __toESM(require("../debug"));
38
+ function spawnAsync(command, args, options) {
39
+ return new Promise((resolve, reject) => {
40
+ const child = (0, import_child_process.spawn)(command, args, options);
41
+ child.once("error", reject);
42
+ child.once("close", resolve);
43
+ });
44
+ }
45
+ async function getOrCreateBunBinary() {
46
+ const bunCommand = process.platform === "win32" ? "bun.exe" : "bun";
47
+ const installPath = (0, import_path.join)((0, import_os.homedir)(), ".bun", "bin", bunCommand);
48
+ try {
49
+ if (await spawnAsync(bunCommand, ["--version"], { stdio: "ignore" }) === 0) {
50
+ (0, import_debug.default)("Bun already installed and available in PATH");
51
+ return bunCommand;
52
+ }
53
+ } catch {
54
+ (0, import_debug.default)("Bun not found in PATH");
55
+ }
56
+ try {
57
+ if (await spawnAsync(installPath, ["--version"], { stdio: "ignore" }) === 0) {
58
+ (0, import_debug.default)("Bun already installed in default location");
59
+ return installPath;
60
+ }
61
+ } catch {
62
+ (0, import_debug.default)("Bun not found in default location");
63
+ }
64
+ console.log("Installing Bun...");
65
+ try {
66
+ const exitCode = process.platform === "win32" ? await spawnAsync(
67
+ "powershell",
68
+ ["-c", "irm bun.sh/install.ps1 | iex"],
69
+ { stdio: "inherit" }
70
+ ) : await spawnAsync(
71
+ "bash",
72
+ ["-c", "curl -fsSL https://bun.sh/install | bash"],
73
+ { stdio: "inherit" }
74
+ );
75
+ if (exitCode !== 0) {
76
+ throw new Error(`Installation script exited with code ${exitCode}`);
77
+ }
78
+ } catch (error) {
79
+ throw new Error(`Failed to install Bun: ${error}`);
80
+ }
81
+ try {
82
+ if (await spawnAsync(installPath, ["--version"], { stdio: "ignore" }) === 0) {
83
+ (0, import_debug.default)("Bun was installed successfully");
84
+ return installPath;
85
+ }
86
+ } catch {
87
+ }
88
+ throw new Error(
89
+ "Bun installation failed. Please install manually and try again."
90
+ );
91
+ }
92
+ // Annotate the CommonJS export names for ESM import in node:
93
+ 0 && (module.exports = {
94
+ getOrCreateBunBinary
95
+ });
@@ -99,6 +99,12 @@ const NODE_VERSIONS = [
99
99
  })
100
100
  ];
101
101
  const BUN_VERSIONS = [
102
+ new import_types.BunVersion({
103
+ major: 1,
104
+ minor: 4,
105
+ range: "1.4.x",
106
+ runtime: "bun1.4.x"
107
+ }),
102
108
  new import_types.BunVersion({
103
109
  major: 1,
104
110
  range: "1.x",
@@ -191,11 +197,15 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
191
197
  function getSupportedBunVersion(engineRange) {
192
198
  if ((0, import_semver.validRange)(engineRange)) {
193
199
  const selected = BUN_VERSIONS.find((version) => {
194
- return (0, import_semver.intersects)(version.range, engineRange);
200
+ if (!(0, import_semver.intersects)(version.range, engineRange)) {
201
+ return false;
202
+ }
203
+ return version.minor === void 0 ? true : !(0, import_semver.intersects)(`<${version.major}.${version.minor}.0`, engineRange);
195
204
  });
196
205
  if (selected) {
197
206
  return new import_types.BunVersion({
198
207
  major: selected.major,
208
+ minor: selected.minor,
199
209
  range: selected.range,
200
210
  runtime: selected.runtime
201
211
  });
@@ -135,10 +135,11 @@ export declare function runNpmInstall(destPath: string, args?: string[], spawnOp
135
135
  * Prepares the input environment based on the used package manager and lockfile
136
136
  * versions.
137
137
  */
138
- export declare function getEnvForPackageManager({ cliType, lockfileVersion, packageJsonPackageManager, env, packageJsonEngines, turboSupportsCorepackHome, projectCreatedAt, }: {
138
+ export declare function getEnvForPackageManager({ cliType, lockfileVersion, packageJsonPackageManager, nodeVersion, env, packageJsonEngines, turboSupportsCorepackHome, projectCreatedAt, }: {
139
139
  cliType: CliType;
140
140
  lockfileVersion: number | undefined;
141
141
  packageJsonPackageManager?: string | undefined;
142
+ nodeVersion?: NodeVersion | BunVersion;
142
143
  env: {
143
144
  [x: string]: string | undefined;
144
145
  };
@@ -153,11 +154,12 @@ export declare const PNPM_10_PREFERRED_AT: Date;
153
154
  * Helper to get the binary paths that link to the used package manager.
154
155
  * Note: Make sure it doesn't contain any `console.log` calls.
155
156
  */
156
- export declare function getPathOverrideForPackageManager({ cliType, lockfileVersion, corepackPackageManager, corepackEnabled, packageJsonEngines, projectCreatedAt, }: {
157
+ export declare function getPathOverrideForPackageManager({ cliType, lockfileVersion, corepackPackageManager, corepackEnabled, nodeVersion, packageJsonEngines, projectCreatedAt, }: {
157
158
  cliType: CliType;
158
159
  lockfileVersion: number | undefined;
159
160
  corepackPackageManager: string | undefined;
160
161
  corepackEnabled?: boolean;
162
+ nodeVersion?: NodeVersion | BunVersion;
161
163
  packageJsonEngines?: PackageJson.Engines;
162
164
  projectCreatedAt?: number;
163
165
  }): {
@@ -698,6 +698,7 @@ function getEnvForPackageManager({
698
698
  cliType,
699
699
  lockfileVersion,
700
700
  packageJsonPackageManager,
701
+ nodeVersion,
701
702
  env,
702
703
  packageJsonEngines,
703
704
  turboSupportsCorepackHome,
@@ -717,6 +718,7 @@ function getEnvForPackageManager({
717
718
  lockfileVersion,
718
719
  corepackPackageManager: packageJsonPackageManager,
719
720
  corepackEnabled,
721
+ nodeVersion,
720
722
  packageJsonEngines,
721
723
  projectCreatedAt
722
724
  });
@@ -732,14 +734,23 @@ function getEnvForPackageManager({
732
734
  const newEnv = {
733
735
  ...env
734
736
  };
737
+ const bunRuntimePath = nodeVersion && (0, import_node_version.isBunVersion)(nodeVersion) ? `/bun${nodeVersion.major}${nodeVersion.minor === void 0 ? "" : `.${nodeVersion.minor}`}` : void 0;
735
738
  const alreadyInPath = (newPath2) => {
736
739
  const oldPath = env.PATH ?? "";
737
740
  return oldPath.split(import_path.default.delimiter).includes(newPath2);
738
741
  };
739
- if (newPath && !alreadyInPath(newPath)) {
742
+ const hasSelectedBunPath = cliType === "bun" && nodeVersion === void 0 && (env.PATH ?? "").split(import_path.default.delimiter).some((segment) => /^\/bun\d+(?:\.\d+)?$/.test(segment));
743
+ const pathsToPrepend = Array.from(
744
+ new Set(
745
+ [newPath, bunRuntimePath].filter((value) => !!value)
746
+ )
747
+ ).filter(
748
+ (value) => !alreadyInPath(value) && !(hasSelectedBunPath && value === newPath)
749
+ );
750
+ if (pathsToPrepend.length > 0) {
740
751
  const oldPath = env.PATH + "";
741
- newEnv.PATH = `${newPath}${import_path.default.delimiter}${oldPath}`;
742
- if (detectedLockfile && detectedPackageManager) {
752
+ newEnv.PATH = `${pathsToPrepend.join(import_path.default.delimiter)}${oldPath ? import_path.default.delimiter : ""}${oldPath}`;
753
+ if (newPath && pathsToPrepend.includes(newPath) && detectedLockfile && detectedPackageManager) {
743
754
  const detectedV9PnpmLockfile = detectedLockfile === "pnpm-lock.yaml" && lockfileVersion === 9;
744
755
  const pnpm10UsingPackageJsonPackageManager = detectedPackageManager === "pnpm@10.x" && packageJsonPackageManager;
745
756
  if (pnpm10UsingPackageJsonPackageManager) {
@@ -835,6 +846,7 @@ function getPathOverrideForPackageManager({
835
846
  lockfileVersion,
836
847
  corepackPackageManager,
837
848
  corepackEnabled = true,
849
+ nodeVersion,
838
850
  packageJsonEngines,
839
851
  projectCreatedAt
840
852
  }) {
@@ -862,6 +874,14 @@ function getPathOverrideForPackageManager({
862
874
  );
863
875
  }
864
876
  }
877
+ if (cliType === "bun" && detectedPackageManger && nodeVersion && (0, import_node_version.isBunVersion)(nodeVersion)) {
878
+ const minor = nodeVersion.minor;
879
+ return {
880
+ ...detectedPackageManger,
881
+ path: `/bun${nodeVersion.major}${minor === void 0 ? "" : `.${minor}`}`,
882
+ detectedPackageManager: `bun@${nodeVersion.range}`
883
+ };
884
+ }
865
885
  return detectedPackageManger ?? NO_OVERRIDE;
866
886
  }
867
887
  function checkEnginesPnpmAgainstDetected(enginesPnpm, detectedPackageManger) {
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ import rename from './fs/rename';
11
11
  import { spawnAsync, execCommand, spawnCommand, walkParentDirs, getScriptName, installDependencies, runPackageJsonScript, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, detectPackageManager, getSpawnOptions, getNodeBinPath, getNodeBinPaths, scanParentDirs, findPackageJson, traverseUpDirectories, PipInstallResult, NpmInstallOutput, type CliType } from './fs/run-user-scripts';
12
12
  import { getLatestNodeVersion, getDiscontinuedNodeVersions, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion } from './fs/node-version';
13
13
  import streamToBuffer, { streamToBufferChunks } from './fs/stream-to-buffer';
14
+ import { getOrCreateBunBinary } from './fs/bun-helpers';
14
15
  import debug from './debug';
15
16
  import getIgnoreFilter from './get-ignore-filter';
16
17
  import { getPlatformEnv } from './get-platform-env';
@@ -20,7 +21,7 @@ import { cloneEnv } from './clone-env';
20
21
  import { hardLinkDir } from './hard-link-dir';
21
22
  import { validateNpmrc } from './validate-npmrc';
22
23
  export type { NodejsLambdaOptions, PrerenderClassification };
23
- export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion, detectPackageManager, runNpmInstall, NpmInstallOutput, runBundleInstall, runPipInstall, PipInstallResult, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, getServiceUrlEnvVars, getExperimentalServiceUrlEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, isExternalSymlink, isExternalSymlinkTarget, getSymlinkTarget, getLambdaOptionsFromFunction, sanitizeConsumerName, scanParentDirs, findPackageJson, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, type CliType, };
24
+ export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion, getOrCreateBunBinary, detectPackageManager, runNpmInstall, NpmInstallOutput, runBundleInstall, runPipInstall, PipInstallResult, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, getServiceUrlEnvVars, getExperimentalServiceUrlEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, isExternalSymlink, isExternalSymlinkTarget, getSymlinkTarget, getLambdaOptionsFromFunction, sanitizeConsumerName, scanParentDirs, findPackageJson, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, type CliType, };
24
25
  export { EdgeFunction } from './edge-function';
25
26
  export { ContainerImage } from './container-image';
26
27
  export type { ContainerImageConfig } from './container-image';
package/dist/index.js CHANGED
@@ -341,7 +341,7 @@ var require_BufferList = __commonJS({
341
341
  this.head = this.tail = null;
342
342
  this.length = 0;
343
343
  };
344
- BufferList.prototype.join = function join9(s) {
344
+ BufferList.prototype.join = function join10(s) {
345
345
  if (this.length === 0)
346
346
  return "";
347
347
  var p = this.head;
@@ -11343,7 +11343,7 @@ var require_cross_spawn = __commonJS({
11343
11343
  var cp = require("child_process");
11344
11344
  var parse6 = require_parse();
11345
11345
  var enoent = require_enoent();
11346
- function spawn2(command, args, options) {
11346
+ function spawn3(command, args, options) {
11347
11347
  const parsed = parse6(command, args, options);
11348
11348
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
11349
11349
  enoent.hookChildProcess(spawned, parsed);
@@ -11355,8 +11355,8 @@ var require_cross_spawn = __commonJS({
11355
11355
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
11356
11356
  return result;
11357
11357
  }
11358
- module2.exports = spawn2;
11359
- module2.exports.spawn = spawn2;
11358
+ module2.exports = spawn3;
11359
+ module2.exports.spawn = spawn3;
11360
11360
  module2.exports.sync = spawnSync;
11361
11361
  module2.exports._parse = parse6;
11362
11362
  module2.exports._enoent = enoent;
@@ -34386,6 +34386,7 @@ __export(src_exports, {
34386
34386
  getNodeBinPath: () => getNodeBinPath,
34387
34387
  getNodeBinPaths: () => getNodeBinPaths,
34388
34388
  getNodeVersion: () => getNodeVersion,
34389
+ getOrCreateBunBinary: () => getOrCreateBunBinary,
34389
34390
  getPackageJson: () => getPackageJson,
34390
34391
  getPathForPackageManager: () => getPathForPackageManager,
34391
34392
  getPlatformEnv: () => getPlatformEnv,
@@ -35796,6 +35797,12 @@ var NODE_VERSIONS = [
35796
35797
  })
35797
35798
  ];
35798
35799
  var BUN_VERSIONS = [
35800
+ new BunVersion({
35801
+ major: 1,
35802
+ minor: 4,
35803
+ range: "1.4.x",
35804
+ runtime: "bun1.4.x"
35805
+ }),
35799
35806
  new BunVersion({
35800
35807
  major: 1,
35801
35808
  range: "1.x",
@@ -35885,11 +35892,15 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
35885
35892
  function getSupportedBunVersion(engineRange) {
35886
35893
  if ((0, import_semver.validRange)(engineRange)) {
35887
35894
  const selected = BUN_VERSIONS.find((version) => {
35888
- return (0, import_semver.intersects)(version.range, engineRange);
35895
+ if (!(0, import_semver.intersects)(version.range, engineRange)) {
35896
+ return false;
35897
+ }
35898
+ return version.minor === void 0 ? true : !(0, import_semver.intersects)(`<${version.major}.${version.minor}.0`, engineRange);
35889
35899
  });
35890
35900
  if (selected) {
35891
35901
  return new BunVersion({
35892
35902
  major: selected.major,
35903
+ minor: selected.minor,
35893
35904
  range: selected.range,
35894
35905
  runtime: selected.runtime
35895
35906
  });
@@ -37314,6 +37325,7 @@ function getEnvForPackageManager({
37314
37325
  cliType,
37315
37326
  lockfileVersion,
37316
37327
  packageJsonPackageManager,
37328
+ nodeVersion,
37317
37329
  env,
37318
37330
  packageJsonEngines,
37319
37331
  turboSupportsCorepackHome,
@@ -37333,6 +37345,7 @@ function getEnvForPackageManager({
37333
37345
  lockfileVersion,
37334
37346
  corepackPackageManager: packageJsonPackageManager,
37335
37347
  corepackEnabled,
37348
+ nodeVersion,
37336
37349
  packageJsonEngines,
37337
37350
  projectCreatedAt
37338
37351
  });
@@ -37348,14 +37361,23 @@ function getEnvForPackageManager({
37348
37361
  const newEnv = {
37349
37362
  ...env
37350
37363
  };
37364
+ const bunRuntimePath = nodeVersion && isBunVersion(nodeVersion) ? `/bun${nodeVersion.major}${nodeVersion.minor === void 0 ? "" : `.${nodeVersion.minor}`}` : void 0;
37351
37365
  const alreadyInPath = (newPath2) => {
37352
37366
  const oldPath = env.PATH ?? "";
37353
37367
  return oldPath.split(import_path6.default.delimiter).includes(newPath2);
37354
37368
  };
37355
- if (newPath && !alreadyInPath(newPath)) {
37369
+ const hasSelectedBunPath = cliType === "bun" && nodeVersion === void 0 && (env.PATH ?? "").split(import_path6.default.delimiter).some((segment) => /^\/bun\d+(?:\.\d+)?$/.test(segment));
37370
+ const pathsToPrepend = Array.from(
37371
+ new Set(
37372
+ [newPath, bunRuntimePath].filter((value) => !!value)
37373
+ )
37374
+ ).filter(
37375
+ (value) => !alreadyInPath(value) && !(hasSelectedBunPath && value === newPath)
37376
+ );
37377
+ if (pathsToPrepend.length > 0) {
37356
37378
  const oldPath = env.PATH + "";
37357
- newEnv.PATH = `${newPath}${import_path6.default.delimiter}${oldPath}`;
37358
- if (detectedLockfile && detectedPackageManager) {
37379
+ newEnv.PATH = `${pathsToPrepend.join(import_path6.default.delimiter)}${oldPath ? import_path6.default.delimiter : ""}${oldPath}`;
37380
+ if (newPath && pathsToPrepend.includes(newPath) && detectedLockfile && detectedPackageManager) {
37359
37381
  const detectedV9PnpmLockfile = detectedLockfile === "pnpm-lock.yaml" && lockfileVersion === 9;
37360
37382
  const pnpm10UsingPackageJsonPackageManager = detectedPackageManager === "pnpm@10.x" && packageJsonPackageManager;
37361
37383
  if (pnpm10UsingPackageJsonPackageManager) {
@@ -37451,6 +37473,7 @@ function getPathOverrideForPackageManager({
37451
37473
  lockfileVersion,
37452
37474
  corepackPackageManager,
37453
37475
  corepackEnabled = true,
37476
+ nodeVersion,
37454
37477
  packageJsonEngines,
37455
37478
  projectCreatedAt
37456
37479
  }) {
@@ -37478,6 +37501,14 @@ function getPathOverrideForPackageManager({
37478
37501
  );
37479
37502
  }
37480
37503
  }
37504
+ if (cliType === "bun" && detectedPackageManger && nodeVersion && isBunVersion(nodeVersion)) {
37505
+ const minor = nodeVersion.minor;
37506
+ return {
37507
+ ...detectedPackageManger,
37508
+ path: `/bun${nodeVersion.major}${minor === void 0 ? "" : `.${minor}`}`,
37509
+ detectedPackageManager: `bun@${nodeVersion.range}`
37510
+ };
37511
+ }
37481
37512
  return detectedPackageManger ?? NO_OVERRIDE;
37482
37513
  }
37483
37514
  function checkEnginesPnpmAgainstDetected(enginesPnpm, detectedPackageManger) {
@@ -37788,8 +37819,67 @@ var installDependencies = (0, import_util6.deprecate)(
37788
37819
  "installDependencies() is deprecated. Please use runNpmInstall() instead."
37789
37820
  );
37790
37821
 
37822
+ // src/fs/bun-helpers.ts
37823
+ var import_os2 = require("os");
37824
+ var import_path7 = require("path");
37825
+ var import_child_process = require("child_process");
37826
+ function spawnAsync2(command, args, options) {
37827
+ return new Promise((resolve, reject) => {
37828
+ const child = (0, import_child_process.spawn)(command, args, options);
37829
+ child.once("error", reject);
37830
+ child.once("close", resolve);
37831
+ });
37832
+ }
37833
+ async function getOrCreateBunBinary() {
37834
+ const bunCommand = process.platform === "win32" ? "bun.exe" : "bun";
37835
+ const installPath = (0, import_path7.join)((0, import_os2.homedir)(), ".bun", "bin", bunCommand);
37836
+ try {
37837
+ if (await spawnAsync2(bunCommand, ["--version"], { stdio: "ignore" }) === 0) {
37838
+ debug("Bun already installed and available in PATH");
37839
+ return bunCommand;
37840
+ }
37841
+ } catch {
37842
+ debug("Bun not found in PATH");
37843
+ }
37844
+ try {
37845
+ if (await spawnAsync2(installPath, ["--version"], { stdio: "ignore" }) === 0) {
37846
+ debug("Bun already installed in default location");
37847
+ return installPath;
37848
+ }
37849
+ } catch {
37850
+ debug("Bun not found in default location");
37851
+ }
37852
+ console.log("Installing Bun...");
37853
+ try {
37854
+ const exitCode = process.platform === "win32" ? await spawnAsync2(
37855
+ "powershell",
37856
+ ["-c", "irm bun.sh/install.ps1 | iex"],
37857
+ { stdio: "inherit" }
37858
+ ) : await spawnAsync2(
37859
+ "bash",
37860
+ ["-c", "curl -fsSL https://bun.sh/install | bash"],
37861
+ { stdio: "inherit" }
37862
+ );
37863
+ if (exitCode !== 0) {
37864
+ throw new Error(`Installation script exited with code ${exitCode}`);
37865
+ }
37866
+ } catch (error) {
37867
+ throw new Error(`Failed to install Bun: ${error}`);
37868
+ }
37869
+ try {
37870
+ if (await spawnAsync2(installPath, ["--version"], { stdio: "ignore" }) === 0) {
37871
+ debug("Bun was installed successfully");
37872
+ return installPath;
37873
+ }
37874
+ } catch {
37875
+ }
37876
+ throw new Error(
37877
+ "Bun installation failed. Please install manually and try again."
37878
+ );
37879
+ }
37880
+
37791
37881
  // src/get-ignore-filter.ts
37792
- var import_path7 = __toESM(require("path"));
37882
+ var import_path8 = __toESM(require("path"));
37793
37883
  var import_fs_extra8 = __toESM(require_lib());
37794
37884
  var import_ignore = __toESM(require_ignore());
37795
37885
  function isCodedError(error) {
@@ -37809,12 +37899,12 @@ async function get_ignore_filter_default(downloadPath, rootDirectory) {
37809
37899
  throw error;
37810
37900
  }
37811
37901
  };
37812
- const vercelIgnorePath = import_path7.default.join(
37902
+ const vercelIgnorePath = import_path8.default.join(
37813
37903
  downloadPath,
37814
37904
  rootDirectory || "",
37815
37905
  ".vercelignore"
37816
37906
  );
37817
- const nowIgnorePath = import_path7.default.join(
37907
+ const nowIgnorePath = import_path8.default.join(
37818
37908
  downloadPath,
37819
37909
  rootDirectory || "",
37820
37910
  ".nowignore"
@@ -37979,22 +38069,22 @@ function getExperimentalServiceUrlEnvVars(options) {
37979
38069
  }
37980
38070
 
37981
38071
  // src/hard-link-dir.ts
37982
- var import_path8 = __toESM(require("path"));
38072
+ var import_path9 = __toESM(require("path"));
37983
38073
  var import_fs2 = require("fs");
37984
38074
  async function hardLinkDir(src, destDirs) {
37985
38075
  if (destDirs.length === 0)
37986
38076
  return;
37987
- destDirs = destDirs.filter((destDir) => import_path8.default.relative(destDir, src) !== "");
38077
+ destDirs = destDirs.filter((destDir) => import_path9.default.relative(destDir, src) !== "");
37988
38078
  const files = await import_fs2.promises.readdir(src);
37989
38079
  await Promise.all(
37990
38080
  files.map(async (file) => {
37991
38081
  if (file === "node_modules")
37992
38082
  return;
37993
- const srcFile = import_path8.default.join(src, file);
38083
+ const srcFile = import_path9.default.join(src, file);
37994
38084
  if ((await import_fs2.promises.lstat(srcFile)).isDirectory()) {
37995
38085
  const destSubdirs = await Promise.all(
37996
38086
  destDirs.map(async (destDir) => {
37997
- const destSubdir = import_path8.default.join(destDir, file);
38087
+ const destSubdir = import_path9.default.join(destDir, file);
37998
38088
  try {
37999
38089
  await import_fs2.promises.mkdir(destSubdir, { recursive: true });
38000
38090
  } catch (err) {
@@ -38009,7 +38099,7 @@ async function hardLinkDir(src, destDirs) {
38009
38099
  }
38010
38100
  await Promise.all(
38011
38101
  destDirs.map(async (destDir) => {
38012
- const destFile = import_path8.default.join(destDir, file);
38102
+ const destFile = import_path9.default.join(destDir, file);
38013
38103
  try {
38014
38104
  await linkOrCopyFile(srcFile, destFile);
38015
38105
  } catch (err) {
@@ -38028,7 +38118,7 @@ async function linkOrCopyFile(srcFile, destFile) {
38028
38118
  await linkOrCopy(srcFile, destFile);
38029
38119
  } catch (err) {
38030
38120
  if (err.code === "ENOENT") {
38031
- await import_fs2.promises.mkdir(import_path8.default.dirname(destFile), { recursive: true });
38121
+ await import_fs2.promises.mkdir(import_path9.default.dirname(destFile), { recursive: true });
38032
38122
  await linkOrCopy(srcFile, destFile);
38033
38123
  return;
38034
38124
  }
@@ -38048,10 +38138,10 @@ async function linkOrCopy(srcFile, destFile) {
38048
38138
  }
38049
38139
 
38050
38140
  // src/validate-npmrc.ts
38051
- var import_path9 = require("path");
38141
+ var import_path10 = require("path");
38052
38142
  var import_promises = require("fs/promises");
38053
38143
  async function validateNpmrc(cwd) {
38054
- const npmrc = await (0, import_promises.readFile)((0, import_path9.join)(cwd, ".npmrc"), "utf-8").catch((err) => {
38144
+ const npmrc = await (0, import_promises.readFile)((0, import_path10.join)(cwd, ".npmrc"), "utf-8").catch((err) => {
38055
38145
  if (err.code !== "ENOENT")
38056
38146
  throw err;
38057
38147
  });
@@ -38104,7 +38194,7 @@ async function getProvidedRuntime() {
38104
38194
  }
38105
38195
 
38106
38196
  // src/should-serve.ts
38107
- var import_path10 = require("path");
38197
+ var import_path11 = require("path");
38108
38198
  var shouldServe = ({
38109
38199
  entrypoint,
38110
38200
  files,
@@ -38115,7 +38205,7 @@ var shouldServe = ({
38115
38205
  if (entrypoint === requestPath && hasProp2(files, entrypoint)) {
38116
38206
  return true;
38117
38207
  }
38118
- const { dir, name } = (0, import_path10.parse)(entrypoint);
38208
+ const { dir, name } = (0, import_path11.parse)(entrypoint);
38119
38209
  if (name === "index" && dir === requestPath && hasProp2(files, entrypoint)) {
38120
38210
  return true;
38121
38211
  }
@@ -38378,21 +38468,21 @@ var packageManifestSchema = {
38378
38468
 
38379
38469
  // src/package-manifest.ts
38380
38470
  var import_fs3 = __toESM(require("fs"));
38381
- var import_path11 = require("path");
38471
+ var import_path12 = require("path");
38382
38472
  var MANIFEST_VERSION = "20260304";
38383
38473
  var MANIFEST_FILENAME = "package-manifest.json";
38384
38474
  function manifestPath(runtime) {
38385
- return (0, import_path11.join)(".vercel", runtime, MANIFEST_FILENAME);
38475
+ return (0, import_path12.join)(".vercel", runtime, MANIFEST_FILENAME);
38386
38476
  }
38387
38477
  async function writeProjectManifest(manifest, workPath, runtime) {
38388
- const outPath = (0, import_path11.join)(workPath, manifestPath(runtime));
38389
- await import_fs3.default.promises.mkdir((0, import_path11.dirname)(outPath), { recursive: true });
38478
+ const outPath = (0, import_path12.join)(workPath, manifestPath(runtime));
38479
+ await import_fs3.default.promises.mkdir((0, import_path12.dirname)(outPath), { recursive: true });
38390
38480
  await import_fs3.default.promises.writeFile(outPath, JSON.stringify(manifest, null, 2));
38391
38481
  }
38392
38482
  function createDiagnostics(runtime) {
38393
38483
  return async ({ workPath }) => {
38394
38484
  try {
38395
- const filePath = (0, import_path11.join)(workPath, manifestPath(runtime));
38485
+ const filePath = (0, import_path12.join)(workPath, manifestPath(runtime));
38396
38486
  const data = await import_fs3.default.promises.readFile(filePath, "utf-8");
38397
38487
  return {
38398
38488
  [MANIFEST_FILENAME]: new FileBlob({ data })
@@ -38405,7 +38495,7 @@ function createDiagnostics(runtime) {
38405
38495
 
38406
38496
  // src/node-diagnostics.ts
38407
38497
  var import_fs4 = __toESM(require("fs"));
38408
- var import_path12 = __toESM(require("path"));
38498
+ var import_path13 = __toESM(require("path"));
38409
38499
  var import_js_yaml3 = __toESM(require_js_yaml2());
38410
38500
  var import_parsers = __toESM(require_lib4());
38411
38501
  function classifySource(resolvedUrl) {
@@ -38717,12 +38807,12 @@ async function readPackageJson(startDir) {
38717
38807
  for (; ; ) {
38718
38808
  try {
38719
38809
  const content = await import_fs4.default.promises.readFile(
38720
- import_path12.default.join(current, "package.json"),
38810
+ import_path13.default.join(current, "package.json"),
38721
38811
  "utf-8"
38722
38812
  );
38723
38813
  return JSON.parse(content);
38724
38814
  } catch {
38725
- const parent = import_path12.default.dirname(current);
38815
+ const parent = import_path13.default.dirname(current);
38726
38816
  if (parent === current)
38727
38817
  return null;
38728
38818
  current = parent;
@@ -38810,7 +38900,7 @@ async function generateProjectManifest({
38810
38900
  for (const filename of [".node-version", ".nvmrc"]) {
38811
38901
  try {
38812
38902
  const val = await import_fs4.default.promises.readFile(
38813
- import_path12.default.join(workPath, filename),
38903
+ import_path13.default.join(workPath, filename),
38814
38904
  "utf-8"
38815
38905
  );
38816
38906
  const trimmed = val.trim();
@@ -39836,6 +39926,7 @@ var SUPPORTED_AL2023_RUNTIMES = [
39836
39926
  "python3.13",
39837
39927
  "python3.14",
39838
39928
  "ruby3.3",
39929
+ "bun1.4.x",
39839
39930
  "bun1.x",
39840
39931
  "executable"
39841
39932
  ];
@@ -40176,11 +40267,11 @@ function validateFrameworkVersion(framework) {
40176
40267
  }
40177
40268
 
40178
40269
  // src/deserialize/hydrate-files-map.ts
40179
- var import_path13 = require("path");
40270
+ var import_path14 = require("path");
40180
40271
  async function hydrateFilesMap(files, filesMap, repoRootPath, fileFsRefsCache) {
40181
40272
  for (const [funcPath, projectPath] of Object.entries(filesMap)) {
40182
40273
  files[funcPath] = await fileFsRefCached(
40183
- (0, import_path13.join)(repoRootPath, projectPath),
40274
+ (0, import_path14.join)(repoRootPath, projectPath),
40184
40275
  fileFsRefsCache
40185
40276
  );
40186
40277
  }
@@ -40195,7 +40286,7 @@ async function fileFsRefCached(fsPath, cache) {
40195
40286
  }
40196
40287
 
40197
40288
  // src/deserialize/create-functions-iterator.ts
40198
- var import_path14 = require("path");
40289
+ var import_path15 = require("path");
40199
40290
  var import_fs_extra9 = __toESM(require_lib());
40200
40291
  var SUFFIX = ".func";
40201
40292
  async function* createFunctionsIterator(dir, root = dir) {
@@ -40209,11 +40300,11 @@ async function* createFunctionsIterator(dir, root = dir) {
40209
40300
  paths = [];
40210
40301
  }
40211
40302
  for (const path8 of paths) {
40212
- const abs = (0, import_path14.join)(dir, path8);
40303
+ const abs = (0, import_path15.join)(dir, path8);
40213
40304
  const s = await (0, import_fs_extra9.stat)(abs);
40214
40305
  if (s.isDirectory()) {
40215
40306
  if (path8.endsWith(SUFFIX)) {
40216
- yield (0, import_path14.relative)(root, abs.substring(0, abs.length - SUFFIX.length));
40307
+ yield (0, import_path15.relative)(root, abs.substring(0, abs.length - SUFFIX.length));
40217
40308
  } else {
40218
40309
  yield* createFunctionsIterator(abs, root);
40219
40310
  }
@@ -40235,7 +40326,7 @@ async function maybeReadJSON(path8) {
40235
40326
 
40236
40327
  // src/deserialize/deserialize-build-output.ts
40237
40328
  var fs11 = __toESM(require_lib());
40238
- var import_path15 = require("path");
40329
+ var import_path16 = require("path");
40239
40330
 
40240
40331
  // src/deserialize/deserialize-edge-function.ts
40241
40332
  async function deserializeEdgeFunction(files, config, repoRootPath, fileFsRefsCache) {
@@ -40298,14 +40389,14 @@ function applyOutputOverrides(output, overrides, warn) {
40298
40389
  async function deserializePrerenderFallback(prerenderConfigPath, fallbackConfig) {
40299
40390
  if (typeof fallbackConfig === "string") {
40300
40391
  return file_fs_ref_default.fromFsPath({
40301
- fsPath: (0, import_path15.join)((0, import_path15.dirname)(prerenderConfigPath), fallbackConfig)
40392
+ fsPath: (0, import_path16.join)((0, import_path16.dirname)(prerenderConfigPath), fallbackConfig)
40302
40393
  });
40303
40394
  }
40304
40395
  if (fallbackConfig) {
40305
40396
  return file_fs_ref_default.fromFsPath({
40306
40397
  mode: fallbackConfig.mode,
40307
40398
  contentType: fallbackConfig.contentType,
40308
- fsPath: (0, import_path15.join)((0, import_path15.dirname)(prerenderConfigPath), fallbackConfig.fsPath)
40399
+ fsPath: (0, import_path16.join)((0, import_path16.dirname)(prerenderConfigPath), fallbackConfig.fsPath)
40309
40400
  });
40310
40401
  }
40311
40402
  return null;
@@ -40391,7 +40482,7 @@ async function deserializeBuildOutput(options) {
40391
40482
  getMeta
40392
40483
  } = options;
40393
40484
  let hasServerActions = false;
40394
- const configPath = (0, import_path15.join)(outputDir, "config.json");
40485
+ const configPath = (0, import_path16.join)(outputDir, "config.json");
40395
40486
  const config = await maybeReadJSON(configPath);
40396
40487
  if (!config) {
40397
40488
  throw new Error(`Config file was not found at "${configPath}"`);
@@ -40402,8 +40493,8 @@ async function deserializeBuildOutput(options) {
40402
40493
  );
40403
40494
  }
40404
40495
  validateDeploymentId(config.deploymentId);
40405
- const flags = await maybeReadJSON((0, import_path15.join)(outputDir, "flags.json"));
40406
- const staticDir = (0, import_path15.join)(outputDir, "static");
40496
+ const flags = await maybeReadJSON((0, import_path16.join)(outputDir, "flags.json"));
40497
+ const staticDir = (0, import_path16.join)(outputDir, "static");
40407
40498
  const output = await glob("**", {
40408
40499
  cwd: staticDir,
40409
40500
  follow: true
@@ -40411,19 +40502,19 @@ async function deserializeBuildOutput(options) {
40411
40502
  applyOutputOverrides(output, config.overrides, warn);
40412
40503
  const fileFsRefsCache = /* @__PURE__ */ new Map();
40413
40504
  const prerenders = /* @__PURE__ */ new Map();
40414
- const functionsDir = (0, import_path15.join)(outputDir, "functions");
40505
+ const functionsDir = (0, import_path16.join)(outputDir, "functions");
40415
40506
  const functionSymlinks = /* @__PURE__ */ new Map();
40416
40507
  for await (const path8 of createFunctionsIterator(functionsDir)) {
40417
40508
  let lambda = void 0;
40418
- const fnDir = (0, import_path15.join)(functionsDir, `${path8}.func`);
40509
+ const fnDir = (0, import_path16.join)(functionsDir, `${path8}.func`);
40419
40510
  try {
40420
40511
  const link = await fs11.readlink(fnDir);
40421
- const target = (0, import_path15.join)((0, import_path15.dirname)(path8), link).slice(0, -5);
40512
+ const target = (0, import_path16.join)((0, import_path16.dirname)(path8), link).slice(0, -5);
40422
40513
  functionSymlinks.set(path8, target);
40423
40514
  } catch (err) {
40424
40515
  if (err.code !== "EINVAL")
40425
40516
  throw err;
40426
- const funcConfigPath = (0, import_path15.join)(fnDir, ".vc-config.json");
40517
+ const funcConfigPath = (0, import_path16.join)(fnDir, ".vc-config.json");
40427
40518
  const funcConfig = await maybeReadJSON(
40428
40519
  funcConfigPath
40429
40520
  );
@@ -40457,7 +40548,7 @@ async function deserializeBuildOutput(options) {
40457
40548
  );
40458
40549
  }
40459
40550
  }
40460
- const prerenderConfigPath = (0, import_path15.join)(
40551
+ const prerenderConfigPath = (0, import_path16.join)(
40461
40552
  functionsDir,
40462
40553
  `${path8}.prerender-config.json`
40463
40554
  );
@@ -40557,13 +40648,13 @@ function validatePrerender(prerender) {
40557
40648
  }
40558
40649
 
40559
40650
  // src/collect-build-result/get-content-type.ts
40560
- var import_path16 = require("path");
40651
+ var import_path17 = require("path");
40561
40652
  var import_mime_types = __toESM(require_mime_types());
40562
40653
  function getContentType(path8) {
40563
40654
  if (path8.endsWith(".html")) {
40564
40655
  return "text/html; charset=utf-8";
40565
40656
  }
40566
- return import_mime_types.default.contentType((0, import_path16.extname)(path8)) || "application/octet-stream";
40657
+ return import_mime_types.default.contentType((0, import_path17.extname)(path8)) || "application/octet-stream";
40567
40658
  }
40568
40659
 
40569
40660
  // src/collect-build-result/file-to-build-output-file.ts
@@ -40717,6 +40808,7 @@ function getExtendedPayload({
40717
40808
  getNodeBinPath,
40718
40809
  getNodeBinPaths,
40719
40810
  getNodeVersion,
40811
+ getOrCreateBunBinary,
40720
40812
  getPackageJson,
40721
40813
  getPathForPackageManager,
40722
40814
  getPlatformEnv,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "14.1.0",
3
+ "version": "14.1.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",