@vercel/build-utils 13.2.4 → 13.2.6

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,21 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 13.2.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Update http links in Node.js version incompatibility message to https ([#14583](https://github.com/vercel/vercel/pull/14583))
8
+
9
+ - Ensure internal build step runs if a build script is missing ([#14564](https://github.com/vercel/vercel/pull/14564))
10
+
11
+ ## 13.2.5
12
+
13
+ ### Patch Changes
14
+
15
+ - Adding in user configured deploymentId to build output type ([#14497](https://github.com/vercel/vercel/pull/14497))
16
+
17
+ - skip secondary installation for vercel.ts ([#14471](https://github.com/vercel/vercel/pull/14471))
18
+
3
19
  ## 13.2.4
4
20
 
5
21
  ### Patch Changes
@@ -152,7 +152,7 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
152
152
  if (!found) {
153
153
  throw new import_errors.NowBuildError({
154
154
  code: "BUILD_UTILS_NODE_VERSION_INVALID",
155
- link: "http://vercel.link/node-version",
155
+ link: "https://vercel.link/node-version",
156
156
  message: `Found invalid Node.js Version: "${engineRange}". ${getHint(
157
157
  isAuto,
158
158
  availableVersions
@@ -167,7 +167,7 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
167
167
  const intro = `Node.js Version "${selection.range}" is discontinued and must be upgraded.`;
168
168
  throw new import_errors.NowBuildError({
169
169
  code: "BUILD_UTILS_NODE_VERSION_DISCONTINUED",
170
- link: "http://vercel.link/node-version",
170
+ link: "https://vercel.link/node-version",
171
171
  message: `${intro} ${getHint(isAuto)}`
172
172
  });
173
173
  }
@@ -1 +1,7 @@
1
+ import type { PackageJson } from '../types';
1
2
  export declare function readConfigFile<T>(files: string | string[]): Promise<T | null>;
3
+ /**
4
+ * Reads and parses the package.json file from a directory.
5
+ * Returns an empty object if the file doesn't exist or can't be parsed.
6
+ */
7
+ export declare function getPackageJson(dir: string): Promise<PackageJson>;
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var read_config_file_exports = {};
30
30
  __export(read_config_file_exports, {
31
+ getPackageJson: () => getPackageJson,
31
32
  readConfigFile: () => readConfigFile
32
33
  });
33
34
  module.exports = __toCommonJS(read_config_file_exports);
@@ -35,6 +36,7 @@ var import_js_yaml = __toESM(require("js-yaml"));
35
36
  var import_toml = __toESM(require("@iarna/toml"));
36
37
  var import_fs_extra = require("fs-extra");
37
38
  var import_error_utils = require("@vercel/error-utils");
39
+ var import_path = require("path");
38
40
  async function readFileOrNull(file) {
39
41
  try {
40
42
  const data = await (0, import_fs_extra.readFile)(file);
@@ -70,7 +72,16 @@ async function readConfigFile(files) {
70
72
  }
71
73
  return null;
72
74
  }
75
+ async function getPackageJson(dir) {
76
+ const packagePath = (0, import_path.join)(dir, "package.json");
77
+ try {
78
+ return JSON.parse(await (0, import_fs_extra.readFile)(packagePath, "utf8"));
79
+ } catch (err) {
80
+ return {};
81
+ }
82
+ }
73
83
  // Annotate the CommonJS export names for ESM import in node:
74
84
  0 && (module.exports = {
85
+ getPackageJson,
75
86
  readConfigFile
76
87
  });
@@ -92,6 +92,12 @@ export declare function usingCorepack(env: {
92
92
  [x: string]: string | undefined;
93
93
  }, packageJsonPackageManager: string | undefined, turboSupportsCorepackHome: boolean | undefined): boolean;
94
94
  export declare function walkParentDirs({ base, start, filename, }: WalkParentDirsProps): Promise<string | null>;
95
+ /**
96
+ * Reset the customInstallCommandSet. This should be called at the start of each build
97
+ * to prevent custom install commands from being skipped due to the set persisting
98
+ * across multiple builds in the same Node process (e.g., in unit tests).
99
+ */
100
+ export declare function resetCustomInstallCommandSet(): void;
95
101
  export declare function runNpmInstall(destPath: string, args?: string[], spawnOpts?: SpawnOptions, meta?: Meta, projectCreatedAt?: number): Promise<boolean>;
96
102
  /**
97
103
  * Prepares the input environment based on the used package manager and lockfile
@@ -189,7 +195,7 @@ export declare function runCustomInstallCommand({ destPath, installCommand, spaw
189
195
  installCommand: string;
190
196
  spawnOpts?: SpawnOptions;
191
197
  projectCreatedAt?: number;
192
- }): Promise<void>;
198
+ }): Promise<boolean>;
193
199
  export declare function runPackageJsonScript(destPath: string, scriptNames: string | Iterable<string>, spawnOpts?: SpawnOptions, projectCreatedAt?: number): Promise<boolean>;
194
200
  export declare function runBundleInstall(destPath: string, args?: string[], spawnOpts?: SpawnOptions, meta?: Meta): Promise<void>;
195
201
  export declare function runPipInstall(destPath: string, args?: string[], spawnOpts?: SpawnOptions, meta?: Meta): Promise<void>;
@@ -40,6 +40,7 @@ __export(run_user_scripts_exports, {
40
40
  getScriptName: () => getScriptName,
41
41
  getSpawnOptions: () => getSpawnOptions,
42
42
  installDependencies: () => installDependencies,
43
+ resetCustomInstallCommandSet: () => resetCustomInstallCommandSet,
43
44
  runBundleInstall: () => runBundleInstall,
44
45
  runCustomInstallCommand: () => runCustomInstallCommand,
45
46
  runNpmInstall: () => runNpmInstall,
@@ -223,16 +224,16 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
223
224
  const { node } = packageJson.engines;
224
225
  if (configuredVersion && !(0, import_semver.intersects)(configuredVersion, supportedNodeVersion.range)) {
225
226
  console.warn(
226
- `Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${configuredVersion}") will not apply, Node.js Version "${supportedNodeVersion.range}" will be used instead. Learn More: http://vercel.link/node-version`
227
+ `Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${configuredVersion}") will not apply, Node.js Version "${supportedNodeVersion.range}" will be used instead. Learn More: https://vercel.link/node-version`
227
228
  );
228
229
  }
229
230
  if ((0, import_semver.coerce)(node)?.raw === node) {
230
231
  console.warn(
231
- `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version`
232
+ `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: https://vercel.link/node-version`
232
233
  );
233
234
  } else if ((0, import_semver.validRange)(node) && (0, import_semver.intersects)(`${latestVersion.major + 1}.x`, node)) {
234
235
  console.warn(
235
- `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version`
236
+ `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: https://vercel.link/node-version`
236
237
  );
237
238
  }
238
239
  }
@@ -526,6 +527,10 @@ function checkIfAlreadyInstalled(runNpmInstallSet, packageJsonPath) {
526
527
  return { alreadyInstalled, runNpmInstallSet: initializedRunNpmInstallSet };
527
528
  }
528
529
  const runNpmInstallSema = new import_async_sema.default(1);
530
+ let customInstallCommandSet;
531
+ function resetCustomInstallCommandSet() {
532
+ customInstallCommandSet = void 0;
533
+ }
529
534
  async function runNpmInstall(destPath, args = [], spawnOpts, meta, projectCreatedAt) {
530
535
  if (meta?.isDev) {
531
536
  (0, import_debug.default)("Skipping dependency installation because dev mode is enabled");
@@ -557,6 +562,14 @@ async function runNpmInstall(destPath, args = [], spawnOpts, meta, projectCreate
557
562
  if (alreadyInstalled) {
558
563
  return false;
559
564
  }
565
+ if (process.env.VERCEL_INSTALL_COMPLETED === "1") {
566
+ (0, import_debug.default)(
567
+ `Skipping dependency installation for ${packageJsonPath} because VERCEL_INSTALL_COMPLETED is set`
568
+ );
569
+ runNpmInstallSet.add(packageJsonPath);
570
+ meta.runNpmInstallSet = runNpmInstallSet;
571
+ return false;
572
+ }
560
573
  meta.runNpmInstallSet = runNpmInstallSet;
561
574
  }
562
575
  if (cliType === "yarn") {
@@ -946,6 +959,24 @@ async function runCustomInstallCommand({
946
959
  spawnOpts,
947
960
  projectCreatedAt
948
961
  }) {
962
+ const normalizedPath = import_path.default.normalize(destPath);
963
+ const { alreadyInstalled, runNpmInstallSet } = checkIfAlreadyInstalled(
964
+ customInstallCommandSet,
965
+ normalizedPath
966
+ );
967
+ customInstallCommandSet = runNpmInstallSet;
968
+ if (alreadyInstalled) {
969
+ (0, import_debug.default)(
970
+ `Skipping custom install command for ${normalizedPath} because it was already run`
971
+ );
972
+ return false;
973
+ }
974
+ if (process.env.VERCEL_INSTALL_COMPLETED === "1") {
975
+ (0, import_debug.default)(
976
+ `Skipping custom install command for ${normalizedPath} because VERCEL_INSTALL_COMPLETED is set`
977
+ );
978
+ return false;
979
+ }
949
980
  console.log(`Running "install" command: \`${installCommand}\`...`);
950
981
  const {
951
982
  cliType,
@@ -969,6 +1000,7 @@ async function runCustomInstallCommand({
969
1000
  env,
970
1001
  cwd: destPath
971
1002
  });
1003
+ return true;
972
1004
  }
973
1005
  async function runPackageJsonScript(destPath, scriptNames, spawnOpts, projectCreatedAt) {
974
1006
  (0, import_assert.default)(import_path.default.isAbsolute(destPath));
@@ -1066,6 +1098,7 @@ const installDependencies = (0, import_util.deprecate)(
1066
1098
  getScriptName,
1067
1099
  getSpawnOptions,
1068
1100
  installDependencies,
1101
+ resetCustomInstallCommandSet,
1069
1102
  runBundleInstall,
1070
1103
  runCustomInstallCommand,
1071
1104
  runNpmInstall,
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import download, { downloadFile, DownloadedFiles, isSymbolicLink, isDirectory }
8
8
  import getWriteableDirectory from './fs/get-writable-directory';
9
9
  import glob, { GlobOptions } from './fs/glob';
10
10
  import rename from './fs/rename';
11
- import { spawnAsync, execCommand, spawnCommand, walkParentDirs, getScriptName, installDependencies, runPackageJsonScript, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, detectPackageManager, getSpawnOptions, getNodeBinPath, getNodeBinPaths, scanParentDirs, traverseUpDirectories } from './fs/run-user-scripts';
11
+ import { spawnAsync, execCommand, spawnCommand, walkParentDirs, getScriptName, installDependencies, runPackageJsonScript, runNpmInstall, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, detectPackageManager, getSpawnOptions, getNodeBinPath, getNodeBinPaths, scanParentDirs, traverseUpDirectories } 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
14
  import debug from './debug';
@@ -18,9 +18,9 @@ import { getPrefixedEnvVars } from './get-prefixed-env-vars';
18
18
  import { cloneEnv } from './clone-env';
19
19
  import { hardLinkDir } from './hard-link-dir';
20
20
  import { validateNpmrc } from './validate-npmrc';
21
- 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, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, getLambdaOptionsFromFunction, scanParentDirs, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, };
21
+ 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, runBundleInstall, runPipInstall, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, getLambdaOptionsFromFunction, scanParentDirs, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, };
22
22
  export { EdgeFunction } from './edge-function';
23
- export { readConfigFile } from './fs/read-config-file';
23
+ export { readConfigFile, getPackageJson } from './fs/read-config-file';
24
24
  export { normalizePath } from './fs/normalize-path';
25
25
  export { getOsRelease, getProvidedRuntime } from './os';
26
26
  export * from './should-serve';
package/dist/index.js CHANGED
@@ -318,7 +318,7 @@ var require_BufferList = __commonJS({
318
318
  this.head = this.tail = null;
319
319
  this.length = 0;
320
320
  };
321
- BufferList.prototype.join = function join5(s) {
321
+ BufferList.prototype.join = function join6(s) {
322
322
  if (this.length === 0)
323
323
  return "";
324
324
  var p = this.head;
@@ -23752,6 +23752,7 @@ __export(src_exports, {
23752
23752
  getNodeBinPaths: () => getNodeBinPaths,
23753
23753
  getNodeVersion: () => getNodeVersion,
23754
23754
  getOsRelease: () => getOsRelease,
23755
+ getPackageJson: () => getPackageJson,
23755
23756
  getPathForPackageManager: () => getPathForPackageManager,
23756
23757
  getPlatformEnv: () => getPlatformEnv,
23757
23758
  getPrefixedEnvVars: () => getPrefixedEnvVars,
@@ -23776,6 +23777,7 @@ __export(src_exports, {
23776
23777
  normalizePath: () => normalizePath,
23777
23778
  readConfigFile: () => readConfigFile,
23778
23779
  rename: () => rename,
23780
+ resetCustomInstallCommandSet: () => resetCustomInstallCommandSet,
23779
23781
  runBundleInstall: () => runBundleInstall,
23780
23782
  runCustomInstallCommand: () => runCustomInstallCommand,
23781
23783
  runNpmInstall: () => runNpmInstall,
@@ -24831,7 +24833,7 @@ function rename(files, delegate) {
24831
24833
  // src/fs/run-user-scripts.ts
24832
24834
  var import_assert6 = __toESM(require("assert"));
24833
24835
  var import_fs_extra7 = __toESM(require_lib());
24834
- var import_path5 = __toESM(require("path"));
24836
+ var import_path6 = __toESM(require("path"));
24835
24837
  var import_async_sema4 = __toESM(require_async_sema());
24836
24838
  var import_cross_spawn = __toESM(require_cross_spawn());
24837
24839
  var import_semver2 = __toESM(require_semver2());
@@ -24973,7 +24975,7 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
24973
24975
  if (!found) {
24974
24976
  throw new NowBuildError({
24975
24977
  code: "BUILD_UTILS_NODE_VERSION_INVALID",
24976
- link: "http://vercel.link/node-version",
24978
+ link: "https://vercel.link/node-version",
24977
24979
  message: `Found invalid Node.js Version: "${engineRange}". ${getHint(
24978
24980
  isAuto,
24979
24981
  availableVersions
@@ -24988,7 +24990,7 @@ async function getSupportedNodeVersion(engineRange, isAuto = false, availableVer
24988
24990
  const intro = `Node.js Version "${selection.range}" is discontinued and must be upgraded.`;
24989
24991
  throw new NowBuildError({
24990
24992
  code: "BUILD_UTILS_NODE_VERSION_DISCONTINUED",
24991
- link: "http://vercel.link/node-version",
24993
+ link: "https://vercel.link/node-version",
24992
24994
  message: `${intro} ${getHint(isAuto)}`
24993
24995
  });
24994
24996
  }
@@ -25038,6 +25040,7 @@ var import_js_yaml = __toESM(require_js_yaml2());
25038
25040
  var import_toml = __toESM(require_toml());
25039
25041
  var import_fs_extra6 = __toESM(require_lib());
25040
25042
  var import_error_utils = __toESM(require_dist());
25043
+ var import_path5 = require("path");
25041
25044
  async function readFileOrNull(file) {
25042
25045
  try {
25043
25046
  const data = await (0, import_fs_extra6.readFile)(file);
@@ -25073,6 +25076,14 @@ async function readConfigFile(files) {
25073
25076
  }
25074
25077
  return null;
25075
25078
  }
25079
+ async function getPackageJson(dir) {
25080
+ const packagePath = (0, import_path5.join)(dir, "package.json");
25081
+ try {
25082
+ return JSON.parse(await (0, import_fs_extra6.readFile)(packagePath, "utf8"));
25083
+ } catch (err) {
25084
+ return {};
25085
+ }
25086
+ }
25076
25087
 
25077
25088
  // src/clone-env.ts
25078
25089
  var { hasOwnProperty: hasOwnProperty2 } = Object.prototype;
@@ -25143,13 +25154,13 @@ function* traverseUpDirectories({
25143
25154
  start,
25144
25155
  base
25145
25156
  }) {
25146
- let current = import_path5.default.normalize(start);
25147
- const normalizedRoot = base ? import_path5.default.normalize(base) : void 0;
25157
+ let current = import_path6.default.normalize(start);
25158
+ const normalizedRoot = base ? import_path6.default.normalize(base) : void 0;
25148
25159
  while (current) {
25149
25160
  yield current;
25150
25161
  if (current === normalizedRoot)
25151
25162
  break;
25152
- const next = import_path5.default.join(current, "..");
25163
+ const next = import_path6.default.join(current, "..");
25153
25164
  current = next === current ? void 0 : next;
25154
25165
  }
25155
25166
  }
@@ -25159,29 +25170,29 @@ async function readProjectRootInfo({
25159
25170
  }) {
25160
25171
  let curRootPackageJsonPath;
25161
25172
  for (const dir of traverseUpDirectories({ start, base })) {
25162
- const packageJsonPath = import_path5.default.join(dir, "package.json");
25173
+ const packageJsonPath = import_path6.default.join(dir, "package.json");
25163
25174
  if (await import_fs_extra7.default.pathExists(packageJsonPath)) {
25164
25175
  curRootPackageJsonPath = packageJsonPath;
25165
25176
  }
25166
25177
  }
25167
25178
  return curRootPackageJsonPath ? {
25168
25179
  packageJson: await import_fs_extra7.default.readJson(curRootPackageJsonPath),
25169
- rootDir: import_path5.default.dirname(curRootPackageJsonPath)
25180
+ rootDir: import_path6.default.dirname(curRootPackageJsonPath)
25170
25181
  } : void 0;
25171
25182
  }
25172
25183
  async function getNodeBinPath({
25173
25184
  cwd
25174
25185
  }) {
25175
25186
  const { lockfilePath } = await scanParentDirs(cwd);
25176
- const dir = import_path5.default.dirname(lockfilePath || cwd);
25177
- return import_path5.default.join(dir, "node_modules", ".bin");
25187
+ const dir = import_path6.default.dirname(lockfilePath || cwd);
25188
+ return import_path6.default.join(dir, "node_modules", ".bin");
25178
25189
  }
25179
25190
  function getNodeBinPaths({
25180
25191
  start,
25181
25192
  base
25182
25193
  }) {
25183
25194
  return Array.from(traverseUpDirectories({ start, base })).map(
25184
- (dir) => import_path5.default.join(dir, "node_modules/.bin")
25195
+ (dir) => import_path6.default.join(dir, "node_modules/.bin")
25185
25196
  );
25186
25197
  }
25187
25198
  async function chmodPlusX(fsPath) {
@@ -25193,10 +25204,10 @@ async function chmodPlusX(fsPath) {
25193
25204
  await import_fs_extra7.default.chmod(fsPath, base8);
25194
25205
  }
25195
25206
  async function runShellScript(fsPath, args = [], spawnOpts) {
25196
- (0, import_assert6.default)(import_path5.default.isAbsolute(fsPath));
25197
- const destPath = import_path5.default.dirname(fsPath);
25207
+ (0, import_assert6.default)(import_path6.default.isAbsolute(fsPath));
25208
+ const destPath = import_path6.default.dirname(fsPath);
25198
25209
  await chmodPlusX(fsPath);
25199
- const command = `./${import_path5.default.basename(fsPath)}`;
25210
+ const command = `./${import_path6.default.basename(fsPath)}`;
25200
25211
  await spawnAsync(command, args, {
25201
25212
  ...spawnOpts,
25202
25213
  cwd: destPath,
@@ -25214,7 +25225,7 @@ function getSpawnOptions(meta, nodeVersion) {
25214
25225
  if (!meta.isDev) {
25215
25226
  let found = false;
25216
25227
  const oldPath = opts.env.PATH || process.env.PATH || "";
25217
- const pathSegments = oldPath.split(import_path5.default.delimiter).map((segment) => {
25228
+ const pathSegments = oldPath.split(import_path6.default.delimiter).map((segment) => {
25218
25229
  if (/^\/node[0-9]+\/bin/.test(segment)) {
25219
25230
  found = true;
25220
25231
  return `/node${nodeVersion.major}/bin`;
@@ -25224,7 +25235,7 @@ function getSpawnOptions(meta, nodeVersion) {
25224
25235
  if (!found) {
25225
25236
  pathSegments.unshift(`/node${nodeVersion.major}/bin`);
25226
25237
  }
25227
- opts.env.PATH = pathSegments.filter(Boolean).join(import_path5.default.delimiter);
25238
+ opts.env.PATH = pathSegments.filter(Boolean).join(import_path6.default.delimiter);
25228
25239
  }
25229
25240
  return opts;
25230
25241
  }
@@ -25249,23 +25260,23 @@ async function getNodeVersion(destPath, fallbackVersion = process.env.VERCEL_PRO
25249
25260
  const { node } = packageJson.engines;
25250
25261
  if (configuredVersion && !(0, import_semver2.intersects)(configuredVersion, supportedNodeVersion.range)) {
25251
25262
  console.warn(
25252
- `Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${configuredVersion}") will not apply, Node.js Version "${supportedNodeVersion.range}" will be used instead. Learn More: http://vercel.link/node-version`
25263
+ `Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${configuredVersion}") will not apply, Node.js Version "${supportedNodeVersion.range}" will be used instead. Learn More: https://vercel.link/node-version`
25253
25264
  );
25254
25265
  }
25255
25266
  if ((0, import_semver2.coerce)(node)?.raw === node) {
25256
25267
  console.warn(
25257
- `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version`
25268
+ `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: https://vercel.link/node-version`
25258
25269
  );
25259
25270
  } else if ((0, import_semver2.validRange)(node) && (0, import_semver2.intersects)(`${latestVersion.major + 1}.x`, node)) {
25260
25271
  console.warn(
25261
- `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version`
25272
+ `Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: https://vercel.link/node-version`
25262
25273
  );
25263
25274
  }
25264
25275
  }
25265
25276
  return supportedNodeVersion;
25266
25277
  }
25267
25278
  async function scanParentDirs(destPath, readPackageJson = false, base = "/") {
25268
- (0, import_assert6.default)(import_path5.default.isAbsolute(destPath));
25279
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
25269
25280
  const pkgJsonPath = await walkParentDirs({
25270
25281
  base,
25271
25282
  start: destPath,
@@ -25378,8 +25389,8 @@ async function checkTurboSupportsCorepack(turboVersionRange, rootDir) {
25378
25389
  if (turboVersionSpecifierSupportsCorepack(turboVersionRange)) {
25379
25390
  return true;
25380
25391
  }
25381
- const turboJsonPath = import_path5.default.join(rootDir, "turbo.json");
25382
- const turboJsoncPath = import_path5.default.join(rootDir, "turbo.jsonc");
25392
+ const turboJsonPath = import_path6.default.join(rootDir, "turbo.json");
25393
+ const turboJsoncPath = import_path6.default.join(rootDir, "turbo.jsonc");
25383
25394
  const [turboJsonExists, turboJsoncExists] = await Promise.all([
25384
25395
  import_fs_extra7.default.pathExists(turboJsonPath),
25385
25396
  import_fs_extra7.default.pathExists(turboJsoncPath)
@@ -25396,7 +25407,7 @@ async function checkTurboSupportsCorepack(turboVersionRange, rootDir) {
25396
25407
  turboJson = import_json5.default.parse(await import_fs_extra7.default.readFile(turboConfigPath, "utf8"));
25397
25408
  } catch (err) {
25398
25409
  console.warn(
25399
- `WARNING: Failed to parse ${import_path5.default.basename(turboConfigPath)}`
25410
+ `WARNING: Failed to parse ${import_path6.default.basename(turboConfigPath)}`
25400
25411
  );
25401
25412
  }
25402
25413
  }
@@ -25456,10 +25467,10 @@ async function walkParentDirs({
25456
25467
  start,
25457
25468
  filename
25458
25469
  }) {
25459
- (0, import_assert6.default)(import_path5.default.isAbsolute(base), 'Expected "base" to be absolute path');
25460
- (0, import_assert6.default)(import_path5.default.isAbsolute(start), 'Expected "start" to be absolute path');
25470
+ (0, import_assert6.default)(import_path6.default.isAbsolute(base), 'Expected "base" to be absolute path');
25471
+ (0, import_assert6.default)(import_path6.default.isAbsolute(start), 'Expected "start" to be absolute path');
25461
25472
  for (const dir of traverseUpDirectories({ start, base })) {
25462
- const fullPath = import_path5.default.join(dir, filename);
25473
+ const fullPath = import_path6.default.join(dir, filename);
25463
25474
  if (await import_fs_extra7.default.pathExists(fullPath)) {
25464
25475
  return fullPath;
25465
25476
  }
@@ -25473,12 +25484,12 @@ async function walkParentDirsMulti({
25473
25484
  }) {
25474
25485
  let packageManager;
25475
25486
  for (const dir of traverseUpDirectories({ start, base })) {
25476
- const fullPaths = filenames.map((f) => import_path5.default.join(dir, f));
25487
+ const fullPaths = filenames.map((f) => import_path6.default.join(dir, f));
25477
25488
  const existResults = await Promise.all(
25478
25489
  fullPaths.map((f) => import_fs_extra7.default.pathExists(f))
25479
25490
  );
25480
25491
  const foundOneOrMore = existResults.some((b) => b);
25481
- const packageJsonPath = import_path5.default.join(dir, "package.json");
25492
+ const packageJsonPath = import_path6.default.join(dir, "package.json");
25482
25493
  const packageJson = await import_fs_extra7.default.readJSON(packageJsonPath).catch(() => null);
25483
25494
  if (packageJson?.packageManager) {
25484
25495
  packageManager = packageJson.packageManager;
@@ -25552,12 +25563,16 @@ function checkIfAlreadyInstalled(runNpmInstallSet, packageJsonPath) {
25552
25563
  return { alreadyInstalled, runNpmInstallSet: initializedRunNpmInstallSet };
25553
25564
  }
25554
25565
  var runNpmInstallSema = new import_async_sema4.default(1);
25566
+ var customInstallCommandSet;
25567
+ function resetCustomInstallCommandSet() {
25568
+ customInstallCommandSet = void 0;
25569
+ }
25555
25570
  async function runNpmInstall(destPath, args = [], spawnOpts, meta, projectCreatedAt) {
25556
25571
  if (meta?.isDev) {
25557
25572
  debug("Skipping dependency installation because dev mode is enabled");
25558
25573
  return false;
25559
25574
  }
25560
- (0, import_assert6.default)(import_path5.default.isAbsolute(destPath));
25575
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
25561
25576
  try {
25562
25577
  await runNpmInstallSema.acquire();
25563
25578
  const {
@@ -25583,6 +25598,14 @@ async function runNpmInstall(destPath, args = [], spawnOpts, meta, projectCreate
25583
25598
  if (alreadyInstalled) {
25584
25599
  return false;
25585
25600
  }
25601
+ if (process.env.VERCEL_INSTALL_COMPLETED === "1") {
25602
+ debug(
25603
+ `Skipping dependency installation for ${packageJsonPath} because VERCEL_INSTALL_COMPLETED is set`
25604
+ );
25605
+ runNpmInstallSet.add(packageJsonPath);
25606
+ meta.runNpmInstallSet = runNpmInstallSet;
25607
+ return false;
25608
+ }
25586
25609
  meta.runNpmInstallSet = runNpmInstallSet;
25587
25610
  }
25588
25611
  if (cliType === "yarn") {
@@ -25667,11 +25690,11 @@ function getEnvForPackageManager({
25667
25690
  };
25668
25691
  const alreadyInPath = (newPath2) => {
25669
25692
  const oldPath = env.PATH ?? "";
25670
- return oldPath.split(import_path5.default.delimiter).includes(newPath2);
25693
+ return oldPath.split(import_path6.default.delimiter).includes(newPath2);
25671
25694
  };
25672
25695
  if (newPath && !alreadyInPath(newPath)) {
25673
25696
  const oldPath = env.PATH + "";
25674
- newEnv.PATH = `${newPath}${import_path5.default.delimiter}${oldPath}`;
25697
+ newEnv.PATH = `${newPath}${import_path6.default.delimiter}${oldPath}`;
25675
25698
  if (detectedLockfile && detectedPackageManager) {
25676
25699
  const detectedV9PnpmLockfile = detectedLockfile === "pnpm-lock.yaml" && lockfileVersion === 9;
25677
25700
  const pnpm10UsingPackageJsonPackageManager = detectedPackageManager === "pnpm@10.x" && packageJsonPackageManager;
@@ -25950,7 +25973,7 @@ function getPathForPackageManager({
25950
25973
  }
25951
25974
  const alreadyInPath = (newPath) => {
25952
25975
  const oldPath = env.PATH ?? "";
25953
- return oldPath.split(import_path5.default.delimiter).includes(newPath);
25976
+ return oldPath.split(import_path6.default.delimiter).includes(newPath);
25954
25977
  };
25955
25978
  switch (true) {
25956
25979
  case (cliType === "yarn" && !env.YARN_NODE_LINKER):
@@ -25972,6 +25995,24 @@ async function runCustomInstallCommand({
25972
25995
  spawnOpts,
25973
25996
  projectCreatedAt
25974
25997
  }) {
25998
+ const normalizedPath = import_path6.default.normalize(destPath);
25999
+ const { alreadyInstalled, runNpmInstallSet } = checkIfAlreadyInstalled(
26000
+ customInstallCommandSet,
26001
+ normalizedPath
26002
+ );
26003
+ customInstallCommandSet = runNpmInstallSet;
26004
+ if (alreadyInstalled) {
26005
+ debug(
26006
+ `Skipping custom install command for ${normalizedPath} because it was already run`
26007
+ );
26008
+ return false;
26009
+ }
26010
+ if (process.env.VERCEL_INSTALL_COMPLETED === "1") {
26011
+ debug(
26012
+ `Skipping custom install command for ${normalizedPath} because VERCEL_INSTALL_COMPLETED is set`
26013
+ );
26014
+ return false;
26015
+ }
25975
26016
  console.log(`Running "install" command: \`${installCommand}\`...`);
25976
26017
  const {
25977
26018
  cliType,
@@ -25995,9 +26036,10 @@ async function runCustomInstallCommand({
25995
26036
  env,
25996
26037
  cwd: destPath
25997
26038
  });
26039
+ return true;
25998
26040
  }
25999
26041
  async function runPackageJsonScript(destPath, scriptNames, spawnOpts, projectCreatedAt) {
26000
- (0, import_assert6.default)(import_path5.default.isAbsolute(destPath));
26042
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
26001
26043
  const {
26002
26044
  packageJson,
26003
26045
  cliType,
@@ -26047,7 +26089,7 @@ async function runBundleInstall(destPath, args = [], spawnOpts, meta) {
26047
26089
  debug("Skipping dependency installation because dev mode is enabled");
26048
26090
  return;
26049
26091
  }
26050
- (0, import_assert6.default)(import_path5.default.isAbsolute(destPath));
26092
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
26051
26093
  const opts = { ...spawnOpts, cwd: destPath, prettyCommand: "bundle install" };
26052
26094
  await spawnAsync("bundle", args.concat(["install"]), opts);
26053
26095
  }
@@ -26056,7 +26098,7 @@ async function runPipInstall(destPath, args = [], spawnOpts, meta) {
26056
26098
  debug("Skipping dependency installation because dev mode is enabled");
26057
26099
  return;
26058
26100
  }
26059
- (0, import_assert6.default)(import_path5.default.isAbsolute(destPath));
26101
+ (0, import_assert6.default)(import_path6.default.isAbsolute(destPath));
26060
26102
  const opts = { ...spawnOpts, cwd: destPath, prettyCommand: "pip3 install" };
26061
26103
  await spawnAsync(
26062
26104
  "pip3",
@@ -26080,7 +26122,7 @@ var installDependencies = (0, import_util2.deprecate)(
26080
26122
  );
26081
26123
 
26082
26124
  // src/get-ignore-filter.ts
26083
- var import_path6 = __toESM(require("path"));
26125
+ var import_path7 = __toESM(require("path"));
26084
26126
  var import_fs_extra8 = __toESM(require_lib());
26085
26127
  var import_ignore = __toESM(require_ignore());
26086
26128
  function isCodedError(error) {
@@ -26100,12 +26142,12 @@ async function get_ignore_filter_default(downloadPath, rootDirectory) {
26100
26142
  throw error;
26101
26143
  }
26102
26144
  };
26103
- const vercelIgnorePath = import_path6.default.join(
26145
+ const vercelIgnorePath = import_path7.default.join(
26104
26146
  downloadPath,
26105
26147
  rootDirectory || "",
26106
26148
  ".vercelignore"
26107
26149
  );
26108
- const nowIgnorePath = import_path6.default.join(
26150
+ const nowIgnorePath = import_path7.default.join(
26109
26151
  downloadPath,
26110
26152
  rootDirectory || "",
26111
26153
  ".nowignore"
@@ -26168,22 +26210,22 @@ function getPrefixedEnvVars({
26168
26210
  }
26169
26211
 
26170
26212
  // src/hard-link-dir.ts
26171
- var import_path7 = __toESM(require("path"));
26213
+ var import_path8 = __toESM(require("path"));
26172
26214
  var import_fs2 = require("fs");
26173
26215
  async function hardLinkDir(src, destDirs) {
26174
26216
  if (destDirs.length === 0)
26175
26217
  return;
26176
- destDirs = destDirs.filter((destDir) => import_path7.default.relative(destDir, src) !== "");
26218
+ destDirs = destDirs.filter((destDir) => import_path8.default.relative(destDir, src) !== "");
26177
26219
  const files = await import_fs2.promises.readdir(src);
26178
26220
  await Promise.all(
26179
26221
  files.map(async (file) => {
26180
26222
  if (file === "node_modules")
26181
26223
  return;
26182
- const srcFile = import_path7.default.join(src, file);
26224
+ const srcFile = import_path8.default.join(src, file);
26183
26225
  if ((await import_fs2.promises.lstat(srcFile)).isDirectory()) {
26184
26226
  const destSubdirs = await Promise.all(
26185
26227
  destDirs.map(async (destDir) => {
26186
- const destSubdir = import_path7.default.join(destDir, file);
26228
+ const destSubdir = import_path8.default.join(destDir, file);
26187
26229
  try {
26188
26230
  await import_fs2.promises.mkdir(destSubdir, { recursive: true });
26189
26231
  } catch (err) {
@@ -26198,7 +26240,7 @@ async function hardLinkDir(src, destDirs) {
26198
26240
  }
26199
26241
  await Promise.all(
26200
26242
  destDirs.map(async (destDir) => {
26201
- const destFile = import_path7.default.join(destDir, file);
26243
+ const destFile = import_path8.default.join(destDir, file);
26202
26244
  try {
26203
26245
  await linkOrCopyFile(srcFile, destFile);
26204
26246
  } catch (err) {
@@ -26217,7 +26259,7 @@ async function linkOrCopyFile(srcFile, destFile) {
26217
26259
  await linkOrCopy(srcFile, destFile);
26218
26260
  } catch (err) {
26219
26261
  if (err.code === "ENOENT") {
26220
- await import_fs2.promises.mkdir(import_path7.default.dirname(destFile), { recursive: true });
26262
+ await import_fs2.promises.mkdir(import_path8.default.dirname(destFile), { recursive: true });
26221
26263
  await linkOrCopy(srcFile, destFile);
26222
26264
  return;
26223
26265
  }
@@ -26237,10 +26279,10 @@ async function linkOrCopy(srcFile, destFile) {
26237
26279
  }
26238
26280
 
26239
26281
  // src/validate-npmrc.ts
26240
- var import_path8 = require("path");
26282
+ var import_path9 = require("path");
26241
26283
  var import_promises = require("fs/promises");
26242
26284
  async function validateNpmrc(cwd) {
26243
- const npmrc = await (0, import_promises.readFile)((0, import_path8.join)(cwd, ".npmrc"), "utf-8").catch((err) => {
26285
+ const npmrc = await (0, import_promises.readFile)((0, import_path9.join)(cwd, ".npmrc"), "utf-8").catch((err) => {
26244
26286
  if (err.code !== "ENOENT")
26245
26287
  throw err;
26246
26288
  });
@@ -26301,7 +26343,7 @@ async function getProvidedRuntime() {
26301
26343
  }
26302
26344
 
26303
26345
  // src/should-serve.ts
26304
- var import_path9 = require("path");
26346
+ var import_path10 = require("path");
26305
26347
  var shouldServe = ({
26306
26348
  entrypoint,
26307
26349
  files,
@@ -26312,7 +26354,7 @@ var shouldServe = ({
26312
26354
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
26313
26355
  return true;
26314
26356
  }
26315
- const { dir, name } = (0, import_path9.parse)(entrypoint);
26357
+ const { dir, name } = (0, import_path10.parse)(entrypoint);
26316
26358
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
26317
26359
  return true;
26318
26360
  }
@@ -26718,12 +26760,12 @@ function shouldUseExperimentalBackends(framework) {
26718
26760
 
26719
26761
  // src/python.ts
26720
26762
  var import_fs3 = __toESM(require("fs"));
26721
- var import_path10 = require("path");
26763
+ var import_path11 = require("path");
26722
26764
  var import_execa = __toESM(require_execa());
26723
26765
  var isWin2 = process.platform === "win32";
26724
26766
  async function runStdlibPyScript(options) {
26725
26767
  const { scriptName, pythonPath, args = [], cwd } = options;
26726
- const scriptPath = (0, import_path10.join)(__dirname, "..", "lib", "python", `${scriptName}.py`);
26768
+ const scriptPath = (0, import_path11.join)(__dirname, "..", "lib", "python", `${scriptName}.py`);
26727
26769
  if (!import_fs3.default.existsSync(scriptPath)) {
26728
26770
  throw new Error(`Python script not found: ${scriptPath}`);
26729
26771
  }
@@ -26801,6 +26843,7 @@ async function isPythonEntrypoint(file) {
26801
26843
  getNodeBinPaths,
26802
26844
  getNodeVersion,
26803
26845
  getOsRelease,
26846
+ getPackageJson,
26804
26847
  getPathForPackageManager,
26805
26848
  getPlatformEnv,
26806
26849
  getPrefixedEnvVars,
@@ -26825,6 +26868,7 @@ async function isPythonEntrypoint(file) {
26825
26868
  normalizePath,
26826
26869
  readConfigFile,
26827
26870
  rename,
26871
+ resetCustomInstallCommandSet,
26828
26872
  runBundleInstall,
26829
26873
  runCustomInstallCommand,
26830
26874
  runNpmInstall,
package/dist/types.d.ts CHANGED
@@ -346,6 +346,7 @@ export interface ProjectSettings {
346
346
  outputDirectory?: string | null;
347
347
  rootDirectory?: string | null;
348
348
  nodeVersion?: string;
349
+ monorepoManager?: string | null;
349
350
  createdAt?: number;
350
351
  autoExposeSystemEnvs?: boolean;
351
352
  sourceFilesOutsideRootDirectory?: boolean;
@@ -469,6 +470,14 @@ export interface BuildResultV2Typical {
469
470
  flags?: {
470
471
  definitions: FlagDefinitions;
471
472
  };
473
+ /**
474
+ * User-configured deployment ID for skew protection.
475
+ * This allows users to specify a custom deployment identifier
476
+ * in their next.config.js that will be used for version skew protection
477
+ * with pre-built deployments.
478
+ * @example "abc123"
479
+ */
480
+ deploymentId?: string;
472
481
  }
473
482
  export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
474
483
  export interface BuildResultV3 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "13.2.4",
3
+ "version": "13.2.6",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -48,7 +48,7 @@
48
48
  "vitest": "2.0.1",
49
49
  "json5": "2.2.3",
50
50
  "@vercel/error-utils": "2.0.3",
51
- "@vercel/routing-utils": "5.3.1"
51
+ "@vercel/routing-utils": "5.3.2"
52
52
  },
53
53
  "scripts": {
54
54
  "build": "node build.mjs",