@vercel/build-utils 14.5.1 → 14.7.0

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,27 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 14.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 37ff9da: Add build type to deploy manifest.
8
+
9
+ ### Patch Changes
10
+
11
+ - 26b891e: Accept `schedule/v1beta` triggers in the `Lambda` runtime validation and the functions config schema
12
+
13
+ ## 14.6.1
14
+
15
+ ### Patch Changes
16
+
17
+ - aad9541: Run on-disk JavaScript workers with a lazily resolved system Node.js executable in native CLI installations, and install the matching Build Utils preview tarball for dynamically installed Builders.
18
+
19
+ ## 14.6.0
20
+
21
+ ### Minor Changes
22
+
23
+ - e82de48: Add strict function affinity configuration and serialize it into function outputs.
24
+
3
25
  ## 14.5.1
4
26
 
5
27
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  import type { LambdaOptionsBase } from './lambda';
2
2
  import type { Env, Files } from './types';
3
- export interface ContainerImageConfig extends Pick<LambdaOptionsBase, 'handler' | 'architecture' | 'memory' | 'maxDuration' | 'maxConcurrency' | 'environment' | 'regions' | 'functionFailoverRegions' | 'experimentalTriggers' | 'supportsCancellation'> {
3
+ export interface ContainerImageConfig extends Pick<LambdaOptionsBase, 'handler' | 'architecture' | 'memory' | 'maxDuration' | 'affinity' | 'maxConcurrency' | 'environment' | 'regions' | 'functionFailoverRegions' | 'experimentalTriggers' | 'supportsCancellation'> {
4
4
  /**
5
5
  * The OCI image reference, for example
6
6
  * `vcr.vercel.com/team/project/svc@sha256:...`.
@@ -20,6 +20,7 @@ export declare class ContainerImage implements ContainerImageConfig {
20
20
  architecture?: ContainerImageConfig['architecture'];
21
21
  memory?: ContainerImageConfig['memory'];
22
22
  maxDuration?: ContainerImageConfig['maxDuration'];
23
+ affinity?: ContainerImageConfig['affinity'];
23
24
  maxConcurrency?: ContainerImageConfig['maxConcurrency'];
24
25
  regions?: ContainerImageConfig['regions'];
25
26
  functionFailoverRegions?: ContainerImageConfig['functionFailoverRegions'];
@@ -32,6 +32,7 @@ class ContainerImage {
32
32
  this.architecture = params.architecture;
33
33
  this.memory = params.memory;
34
34
  this.maxDuration = params.maxDuration;
35
+ this.affinity = params.affinity;
35
36
  this.maxConcurrency = params.maxConcurrency;
36
37
  this.regions = params.regions;
37
38
  this.functionFailoverRegions = params.functionFailoverRegions;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Returns the executable that should be used to run Node.js scripts.
3
+ *
4
+ * In the standalone Vercel CLI, `process.execPath` points to the CLI binary
5
+ * rather than Node.js. Resolve Node.js lazily from PATH so commands that do not
6
+ * execute on-disk JavaScript can still run when Node.js is unavailable.
7
+ */
8
+ export declare function getNodeExecPath(): string;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var get_node_exec_path_exports = {};
20
+ __export(get_node_exec_path_exports, {
21
+ getNodeExecPath: () => getNodeExecPath
22
+ });
23
+ module.exports = __toCommonJS(get_node_exec_path_exports);
24
+ var import_node_fs = require("node:fs");
25
+ var import_node_path = require("node:path");
26
+ const NODE_EXEC_PATH_ENV = "VERCEL_NODE_EXEC_PATH";
27
+ const NATIVE_CLI_ENV = "VERCEL_VC_NATIVE";
28
+ function getNodeExecPath() {
29
+ const override = process.env[NODE_EXEC_PATH_ENV];
30
+ if (override)
31
+ return override;
32
+ if (!process.env[NATIVE_CLI_ENV])
33
+ return process.execPath;
34
+ const nodeExecPath = findNodeExecPath();
35
+ process.env[NODE_EXEC_PATH_ENV] = nodeExecPath;
36
+ return nodeExecPath;
37
+ }
38
+ function findNodeExecPath() {
39
+ const executableName = process.platform === "win32" ? "node.exe" : "node";
40
+ const cliPath = (0, import_node_fs.realpathSync)(process.execPath);
41
+ for (const directory of (process.env.PATH || "").split(import_node_path.delimiter)) {
42
+ if (!directory)
43
+ continue;
44
+ const candidate = (0, import_node_path.resolve)(directory, executableName);
45
+ try {
46
+ (0, import_node_fs.accessSync)(candidate, import_node_fs.constants.X_OK);
47
+ if ((0, import_node_fs.realpathSync)(candidate) !== cliPath)
48
+ return candidate;
49
+ } catch {
50
+ }
51
+ }
52
+ throw new Error("Could not find the Node.js executable in PATH.");
53
+ }
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ getNodeExecPath
57
+ });
package/dist/index.d.ts CHANGED
@@ -19,9 +19,11 @@ import { getPrefixedEnvVars } from './get-prefixed-env-vars';
19
19
  import { getServiceUrlEnvVars, getExperimentalServiceUrlEnvVars } from './get-service-url-env-vars';
20
20
  import { cloneEnv } from './clone-env';
21
21
  import { hardLinkDir } from './hard-link-dir';
22
+ import { getNodeExecPath } from './get-node-exec-path';
22
23
  import { validateNpmrc } from './validate-npmrc';
23
24
  export type { NodejsLambdaOptions, PrerenderInitialMetadata };
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, };
25
+ export type { LambdaAffinity } from './lambda';
26
+ export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getNodeExecPath, 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, };
25
27
  export { EdgeFunction } from './edge-function';
26
28
  export { ContainerImage } from './container-image';
27
29
  export type { ContainerImageConfig } from './container-image';
package/dist/index.js CHANGED
@@ -2374,8 +2374,8 @@ var require_universalify = __commonJS({
2374
2374
  if (typeof args[args.length - 1] === "function")
2375
2375
  fn.apply(this, args);
2376
2376
  else {
2377
- return new Promise((resolve, reject) => {
2378
- args.push((err, res) => err != null ? reject(err) : resolve(res));
2377
+ return new Promise((resolve2, reject) => {
2378
+ args.push((err, res) => err != null ? reject(err) : resolve2(res));
2379
2379
  fn.apply(this, args);
2380
2380
  });
2381
2381
  }
@@ -2398,7 +2398,7 @@ var require_universalify = __commonJS({
2398
2398
  // ../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/polyfills.js
2399
2399
  var require_polyfills = __commonJS({
2400
2400
  "../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/polyfills.js"(exports, module2) {
2401
- var constants = require("constants");
2401
+ var constants2 = require("constants");
2402
2402
  var origCwd = process.cwd;
2403
2403
  var cwd = null;
2404
2404
  var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
@@ -2423,7 +2423,7 @@ var require_polyfills = __commonJS({
2423
2423
  var chdir;
2424
2424
  module2.exports = patch;
2425
2425
  function patch(fs11) {
2426
- if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
2426
+ if (constants2.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
2427
2427
  patchLchmod(fs11);
2428
2428
  }
2429
2429
  if (!fs11.lutimes) {
@@ -2530,7 +2530,7 @@ var require_polyfills = __commonJS({
2530
2530
  fs12.lchmod = function(path8, mode, callback) {
2531
2531
  fs12.open(
2532
2532
  path8,
2533
- constants.O_WRONLY | constants.O_SYMLINK,
2533
+ constants2.O_WRONLY | constants2.O_SYMLINK,
2534
2534
  mode,
2535
2535
  function(err, fd) {
2536
2536
  if (err) {
@@ -2548,7 +2548,7 @@ var require_polyfills = __commonJS({
2548
2548
  );
2549
2549
  };
2550
2550
  fs12.lchmodSync = function(path8, mode) {
2551
- var fd = fs12.openSync(path8, constants.O_WRONLY | constants.O_SYMLINK, mode);
2551
+ var fd = fs12.openSync(path8, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
2552
2552
  var threw = true;
2553
2553
  var ret;
2554
2554
  try {
@@ -2568,9 +2568,9 @@ var require_polyfills = __commonJS({
2568
2568
  };
2569
2569
  }
2570
2570
  function patchLutimes(fs12) {
2571
- if (constants.hasOwnProperty("O_SYMLINK") && fs12.futimes) {
2571
+ if (constants2.hasOwnProperty("O_SYMLINK") && fs12.futimes) {
2572
2572
  fs12.lutimes = function(path8, at, mt, cb) {
2573
- fs12.open(path8, constants.O_SYMLINK, function(er, fd) {
2573
+ fs12.open(path8, constants2.O_SYMLINK, function(er, fd) {
2574
2574
  if (er) {
2575
2575
  if (cb)
2576
2576
  cb(er);
@@ -2585,7 +2585,7 @@ var require_polyfills = __commonJS({
2585
2585
  });
2586
2586
  };
2587
2587
  fs12.lutimesSync = function(path8, at, mt) {
2588
- var fd = fs12.openSync(path8, constants.O_SYMLINK);
2588
+ var fd = fs12.openSync(path8, constants2.O_SYMLINK);
2589
2589
  var ret;
2590
2590
  var threw = true;
2591
2591
  try {
@@ -3256,19 +3256,19 @@ var require_fs = __commonJS({
3256
3256
  if (typeof callback === "function") {
3257
3257
  return fs11.exists(filename, callback);
3258
3258
  }
3259
- return new Promise((resolve) => {
3260
- return fs11.exists(filename, resolve);
3259
+ return new Promise((resolve2) => {
3260
+ return fs11.exists(filename, resolve2);
3261
3261
  });
3262
3262
  };
3263
3263
  exports.read = function(fd, buffer, offset, length, position, callback) {
3264
3264
  if (typeof callback === "function") {
3265
3265
  return fs11.read(fd, buffer, offset, length, position, callback);
3266
3266
  }
3267
- return new Promise((resolve, reject) => {
3267
+ return new Promise((resolve2, reject) => {
3268
3268
  fs11.read(fd, buffer, offset, length, position, (err, bytesRead, buffer2) => {
3269
3269
  if (err)
3270
3270
  return reject(err);
3271
- resolve({ bytesRead, buffer: buffer2 });
3271
+ resolve2({ bytesRead, buffer: buffer2 });
3272
3272
  });
3273
3273
  });
3274
3274
  };
@@ -3276,11 +3276,11 @@ var require_fs = __commonJS({
3276
3276
  if (typeof args[args.length - 1] === "function") {
3277
3277
  return fs11.write(fd, buffer, ...args);
3278
3278
  }
3279
- return new Promise((resolve, reject) => {
3279
+ return new Promise((resolve2, reject) => {
3280
3280
  fs11.write(fd, buffer, ...args, (err, bytesWritten, buffer2) => {
3281
3281
  if (err)
3282
3282
  return reject(err);
3283
- resolve({ bytesWritten, buffer: buffer2 });
3283
+ resolve2({ bytesWritten, buffer: buffer2 });
3284
3284
  });
3285
3285
  });
3286
3286
  };
@@ -3289,11 +3289,11 @@ var require_fs = __commonJS({
3289
3289
  if (typeof args[args.length - 1] === "function") {
3290
3290
  return fs11.writev(fd, buffers, ...args);
3291
3291
  }
3292
- return new Promise((resolve, reject) => {
3292
+ return new Promise((resolve2, reject) => {
3293
3293
  fs11.writev(fd, buffers, ...args, (err, bytesWritten, buffers2) => {
3294
3294
  if (err)
3295
3295
  return reject(err);
3296
- resolve({ bytesWritten, buffers: buffers2 });
3296
+ resolve2({ bytesWritten, buffers: buffers2 });
3297
3297
  });
3298
3298
  });
3299
3299
  };
@@ -5405,12 +5405,12 @@ var require_async_sema = __commonJS({
5405
5405
  if (token) {
5406
5406
  return token;
5407
5407
  }
5408
- return new Promise((resolve, reject) => {
5408
+ return new Promise((resolve2, reject) => {
5409
5409
  if (this.pauseFn && !this.paused) {
5410
5410
  this.paused = true;
5411
5411
  this.pauseFn();
5412
5412
  }
5413
- this.waiting.push({ resolve, reject });
5413
+ this.waiting.push({ resolve: resolve2, reject });
5414
5414
  });
5415
5415
  }
5416
5416
  async v() {
@@ -5668,7 +5668,7 @@ var require_lib2 = __commonJS({
5668
5668
  "../../node_modules/.pnpm/async-retry@1.2.3/node_modules/async-retry/lib/index.js"(exports, module2) {
5669
5669
  var retrier = require_retry2();
5670
5670
  function retry2(fn, opts) {
5671
- function run(resolve, reject) {
5671
+ function run(resolve2, reject) {
5672
5672
  var options = opts || {};
5673
5673
  var op = retrier.operation(options);
5674
5674
  function bail(err) {
@@ -5693,7 +5693,7 @@ var require_lib2 = __commonJS({
5693
5693
  onError(err, num);
5694
5694
  return;
5695
5695
  }
5696
- Promise.resolve(val).then(resolve).catch(function catchIt(err) {
5696
+ Promise.resolve(val).then(resolve2).catch(function catchIt(err) {
5697
5697
  onError(err, num);
5698
5698
  });
5699
5699
  }
@@ -7670,7 +7670,7 @@ var require_old = __commonJS({
7670
7670
  splitRootRe = /^[\/]*/;
7671
7671
  }
7672
7672
  var splitRootRe;
7673
- exports.realpathSync = function realpathSync(p, cache) {
7673
+ exports.realpathSync = function realpathSync2(p, cache) {
7674
7674
  p = pathModule.resolve(p);
7675
7675
  if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
7676
7676
  return cache[p];
@@ -7835,8 +7835,8 @@ var require_fs2 = __commonJS({
7835
7835
  "../../node_modules/.pnpm/fs.realpath@1.0.0/node_modules/fs.realpath/index.js"(exports, module2) {
7836
7836
  module2.exports = realpath;
7837
7837
  realpath.realpath = realpath;
7838
- realpath.sync = realpathSync;
7839
- realpath.realpathSync = realpathSync;
7838
+ realpath.sync = realpathSync2;
7839
+ realpath.realpathSync = realpathSync2;
7840
7840
  realpath.monkeypatch = monkeypatch;
7841
7841
  realpath.unmonkeypatch = unmonkeypatch;
7842
7842
  var fs11 = require("fs");
@@ -7864,7 +7864,7 @@ var require_fs2 = __commonJS({
7864
7864
  }
7865
7865
  });
7866
7866
  }
7867
- function realpathSync(p, cache) {
7867
+ function realpathSync2(p, cache) {
7868
7868
  if (ok) {
7869
7869
  return origRealpathSync(p, cache);
7870
7870
  }
@@ -7880,7 +7880,7 @@ var require_fs2 = __commonJS({
7880
7880
  }
7881
7881
  function monkeypatch() {
7882
7882
  fs11.realpath = realpath;
7883
- fs11.realpathSync = realpathSync;
7883
+ fs11.realpathSync = realpathSync2;
7884
7884
  }
7885
7885
  function unmonkeypatch() {
7886
7886
  fs11.realpath = origRealpath;
@@ -9849,12 +9849,12 @@ var require_isexe = __commonJS({
9849
9849
  if (typeof Promise !== "function") {
9850
9850
  throw new TypeError("callback not provided");
9851
9851
  }
9852
- return new Promise(function(resolve, reject) {
9852
+ return new Promise(function(resolve2, reject) {
9853
9853
  isexe(path8, options || {}, function(er, is) {
9854
9854
  if (er) {
9855
9855
  reject(er);
9856
9856
  } else {
9857
- resolve(is);
9857
+ resolve2(is);
9858
9858
  }
9859
9859
  });
9860
9860
  });
@@ -23415,7 +23415,7 @@ var require_dist2 = __commonJS({
23415
23415
  return x;
23416
23416
  } : _d;
23417
23417
  var endsWith = "[" + escapeString(options.endsWith || "") + "]|$";
23418
- var delimiter = "[" + escapeString(options.delimiter || "/#?") + "]";
23418
+ var delimiter2 = "[" + escapeString(options.delimiter || "/#?") + "]";
23419
23419
  var route = start ? "^" : "";
23420
23420
  for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
23421
23421
  var token = tokens_1[_i];
@@ -23444,19 +23444,19 @@ var require_dist2 = __commonJS({
23444
23444
  }
23445
23445
  if (end) {
23446
23446
  if (!strict)
23447
- route += delimiter + "?";
23447
+ route += delimiter2 + "?";
23448
23448
  route += !options.endsWith ? "$" : "(?=" + endsWith + ")";
23449
23449
  } else {
23450
23450
  var endToken = tokens[tokens.length - 1];
23451
- var isEndDelimited = typeof endToken === "string" ? delimiter.indexOf(endToken[endToken.length - 1]) > -1 : (
23451
+ var isEndDelimited = typeof endToken === "string" ? delimiter2.indexOf(endToken[endToken.length - 1]) > -1 : (
23452
23452
  // tslint:disable-next-line
23453
23453
  endToken === void 0
23454
23454
  );
23455
23455
  if (!strict) {
23456
- route += "(?:" + delimiter + "(?=" + endsWith + "))?";
23456
+ route += "(?:" + delimiter2 + "(?=" + endsWith + "))?";
23457
23457
  }
23458
23458
  if (!isEndDelimited) {
23459
- route += "(?=" + delimiter + "|" + endsWith + ")";
23459
+ route += "(?=" + delimiter2 + "|" + endsWith + ")";
23460
23460
  }
23461
23461
  }
23462
23462
  return new RegExp(route, flags(options));
@@ -23567,7 +23567,7 @@ var require_dist3 = __commonJS({
23567
23567
  options = {};
23568
23568
  }
23569
23569
  var tokens = lexer(str);
23570
- var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a, _b = options.delimiter, delimiter = _b === void 0 ? "/#?" : _b;
23570
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a, _b = options.delimiter, delimiter2 = _b === void 0 ? "/#?" : _b;
23571
23571
  var result = [];
23572
23572
  var key = 0;
23573
23573
  var i = 0;
@@ -23592,7 +23592,7 @@ var require_dist3 = __commonJS({
23592
23592
  return result2;
23593
23593
  };
23594
23594
  var isSafe = function(value2) {
23595
- for (var _i = 0, delimiter_1 = delimiter; _i < delimiter_1.length; _i++) {
23595
+ for (var _i = 0, delimiter_1 = delimiter2; _i < delimiter_1.length; _i++) {
23596
23596
  var char2 = delimiter_1[_i];
23597
23597
  if (value2.indexOf(char2) > -1)
23598
23598
  return true;
@@ -23606,8 +23606,8 @@ var require_dist3 = __commonJS({
23606
23606
  throw new TypeError('Must have text between two parameters, missing text after "'.concat(prev.name, '"'));
23607
23607
  }
23608
23608
  if (!prevText || isSafe(prevText))
23609
- return "[^".concat(escapeString(delimiter), "]+?");
23610
- return "(?:(?!".concat(escapeString(prevText), ")[^").concat(escapeString(delimiter), "])+?");
23609
+ return "[^".concat(escapeString(delimiter2), "]+?");
23610
+ return "(?:(?!".concat(escapeString(prevText), ")[^").concat(escapeString(delimiter2), "])+?");
23611
23611
  };
23612
23612
  while (i < tokens.length) {
23613
23613
  var char = tryConsume("CHAR");
@@ -23803,9 +23803,9 @@ var require_dist3 = __commonJS({
23803
23803
  }
23804
23804
  var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function(x) {
23805
23805
  return x;
23806
- } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
23806
+ } : _d, _e = options.delimiter, delimiter2 = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
23807
23807
  var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
23808
- var delimiterRe = "[".concat(escapeString(delimiter), "]");
23808
+ var delimiterRe = "[".concat(escapeString(delimiter2), "]");
23809
23809
  var route = start ? "^" : "";
23810
23810
  for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
23811
23811
  var token = tokens_1[_i];
@@ -34387,6 +34387,7 @@ __export(src_exports, {
34387
34387
  getMaxDurationSchema: () => getMaxDurationSchema,
34388
34388
  getNodeBinPath: () => getNodeBinPath,
34389
34389
  getNodeBinPaths: () => getNodeBinPaths,
34390
+ getNodeExecPath: () => getNodeExecPath,
34390
34391
  getNodeVersion: () => getNodeVersion,
34391
34392
  getOrCreateBunBinary: () => getOrCreateBunBinary,
34392
34393
  getPackageJson: () => getPackageJson,
@@ -34494,7 +34495,7 @@ var FileBlob = class _FileBlob {
34494
34495
  (0, import_assert.default)(typeof mode === "number");
34495
34496
  (0, import_assert.default)(typeof stream.pipe === "function");
34496
34497
  const chunks = [];
34497
- await new Promise((resolve, reject) => {
34498
+ await new Promise((resolve2, reject) => {
34498
34499
  stream.on(
34499
34500
  "data",
34500
34501
  (chunk) => (
@@ -34506,7 +34507,7 @@ var FileBlob = class _FileBlob {
34506
34507
  )
34507
34508
  );
34508
34509
  stream.on("error", (error) => reject(error));
34509
- stream.on("end", () => resolve());
34510
+ stream.on("end", () => resolve2());
34510
34511
  });
34511
34512
  const data = Buffer.concat(chunks);
34512
34513
  return new _FileBlob({ mode, contentType, data });
@@ -34567,13 +34568,13 @@ var FileFsRef = class _FileFsRef {
34567
34568
  (0, import_assert2.default)(typeof stream.pipe === "function");
34568
34569
  (0, import_assert2.default)(typeof fsPath === "string");
34569
34570
  await import_fs_extra.default.mkdirp(import_path.default.dirname(fsPath));
34570
- await new Promise((resolve, reject) => {
34571
+ await new Promise((resolve2, reject) => {
34571
34572
  const dest = import_fs_extra.default.createWriteStream(fsPath, {
34572
34573
  mode: mode & 511
34573
34574
  });
34574
34575
  stream.pipe(dest);
34575
34576
  stream.on("error", reject);
34576
- dest.on("finish", resolve);
34577
+ dest.on("finish", resolve2);
34577
34578
  dest.on("error", reject);
34578
34579
  });
34579
34580
  return _FileFsRef.fromFsPath({ mode, contentType, fsPath });
@@ -34830,7 +34831,7 @@ var import_fs_extra2 = __toESM(require_lib());
34830
34831
  // src/fs/stream-to-buffer.ts
34831
34832
  var import_end_of_stream = __toESM(require_end_of_stream());
34832
34833
  function streamToBuffer(stream) {
34833
- return new Promise((resolve, reject) => {
34834
+ return new Promise((resolve2, reject) => {
34834
34835
  const buffers = [];
34835
34836
  stream.on("data", (chunk) => {
34836
34837
  const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
@@ -34844,13 +34845,13 @@ function streamToBuffer(stream) {
34844
34845
  try {
34845
34846
  switch (buffers.length) {
34846
34847
  case 0:
34847
- resolve(Buffer.allocUnsafe(0));
34848
+ resolve2(Buffer.allocUnsafe(0));
34848
34849
  break;
34849
34850
  case 1:
34850
- resolve(Buffer.from(buffers[0]));
34851
+ resolve2(Buffer.from(buffers[0]));
34851
34852
  break;
34852
34853
  default:
34853
- resolve(Buffer.concat(buffers));
34854
+ resolve2(Buffer.concat(buffers));
34854
34855
  }
34855
34856
  } catch (concatErr) {
34856
34857
  reject(concatErr);
@@ -35053,6 +35054,7 @@ var Lambda = class {
35053
35054
  runtime,
35054
35055
  runtimeLanguage,
35055
35056
  maxDuration,
35057
+ affinity,
35056
35058
  maxConcurrency,
35057
35059
  architecture,
35058
35060
  memory,
@@ -35106,6 +35108,12 @@ var Lambda = class {
35106
35108
  '"maxDuration" is not a number or "max"'
35107
35109
  );
35108
35110
  }
35111
+ if (affinity !== void 0) {
35112
+ (0, import_assert4.default)(
35113
+ typeof affinity === "object" && affinity !== null && affinity.mode === "strict" && Object.keys(affinity).length === 1,
35114
+ '"affinity" must be an object with only `mode: "strict"`'
35115
+ );
35116
+ }
35109
35117
  if (maxConcurrency !== void 0) {
35110
35118
  (0, import_assert4.default)(
35111
35119
  Number.isInteger(maxConcurrency) && maxConcurrency >= 1,
@@ -35174,61 +35182,63 @@ var Lambda = class {
35174
35182
  `${prefix} is not an object`
35175
35183
  );
35176
35184
  (0, import_assert4.default)(
35177
- trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta",
35178
- `${prefix}.type must be "queue/v1beta" or "queue/v2beta"`
35179
- );
35180
- (0, import_assert4.default)(
35181
- typeof trigger.topic === "string",
35182
- `${prefix}.topic is required and must be a string`
35183
- );
35184
- (0, import_assert4.default)(trigger.topic.length > 0, `${prefix}.topic cannot be empty`);
35185
- (0, import_assert4.default)(
35186
- typeof trigger.consumer === "string",
35187
- `${prefix}.consumer is required and must be a string`
35188
- );
35189
- (0, import_assert4.default)(
35190
- trigger.consumer.length > 0,
35191
- `${prefix}.consumer cannot be empty`
35185
+ trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta" || trigger.type === "schedule/v1beta",
35186
+ `${prefix}.type must be "queue/v1beta", "queue/v2beta", or "schedule/v1beta"`
35192
35187
  );
35193
- if (trigger.maxDeliveries !== void 0) {
35188
+ if (trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta") {
35194
35189
  (0, import_assert4.default)(
35195
- typeof trigger.maxDeliveries === "number",
35196
- `${prefix}.maxDeliveries must be a number`
35190
+ typeof trigger.topic === "string",
35191
+ `${prefix}.topic is required and must be a string`
35197
35192
  );
35193
+ (0, import_assert4.default)(trigger.topic.length > 0, `${prefix}.topic cannot be empty`);
35198
35194
  (0, import_assert4.default)(
35199
- Number.isInteger(trigger.maxDeliveries) && trigger.maxDeliveries >= 1,
35200
- `${prefix}.maxDeliveries must be at least 1`
35201
- );
35202
- }
35203
- if (trigger.retryAfterSeconds !== void 0) {
35204
- (0, import_assert4.default)(
35205
- typeof trigger.retryAfterSeconds === "number",
35206
- `${prefix}.retryAfterSeconds must be a number`
35207
- );
35208
- (0, import_assert4.default)(
35209
- trigger.retryAfterSeconds > 0,
35210
- `${prefix}.retryAfterSeconds must be a positive number`
35211
- );
35212
- }
35213
- if (trigger.initialDelaySeconds !== void 0) {
35214
- (0, import_assert4.default)(
35215
- typeof trigger.initialDelaySeconds === "number",
35216
- `${prefix}.initialDelaySeconds must be a number`
35195
+ typeof trigger.consumer === "string",
35196
+ `${prefix}.consumer is required and must be a string`
35217
35197
  );
35218
35198
  (0, import_assert4.default)(
35219
- trigger.initialDelaySeconds >= 0,
35220
- `${prefix}.initialDelaySeconds must be a non-negative number`
35221
- );
35222
- }
35223
- if (trigger.maxConcurrency !== void 0) {
35224
- (0, import_assert4.default)(
35225
- typeof trigger.maxConcurrency === "number",
35226
- `${prefix}.maxConcurrency must be a number`
35227
- );
35228
- (0, import_assert4.default)(
35229
- Number.isInteger(trigger.maxConcurrency) && trigger.maxConcurrency >= 1,
35230
- `${prefix}.maxConcurrency must be at least 1`
35199
+ trigger.consumer.length > 0,
35200
+ `${prefix}.consumer cannot be empty`
35231
35201
  );
35202
+ if (trigger.maxDeliveries !== void 0) {
35203
+ (0, import_assert4.default)(
35204
+ typeof trigger.maxDeliveries === "number",
35205
+ `${prefix}.maxDeliveries must be a number`
35206
+ );
35207
+ (0, import_assert4.default)(
35208
+ Number.isInteger(trigger.maxDeliveries) && trigger.maxDeliveries >= 1,
35209
+ `${prefix}.maxDeliveries must be at least 1`
35210
+ );
35211
+ }
35212
+ if (trigger.retryAfterSeconds !== void 0) {
35213
+ (0, import_assert4.default)(
35214
+ typeof trigger.retryAfterSeconds === "number",
35215
+ `${prefix}.retryAfterSeconds must be a number`
35216
+ );
35217
+ (0, import_assert4.default)(
35218
+ trigger.retryAfterSeconds > 0,
35219
+ `${prefix}.retryAfterSeconds must be a positive number`
35220
+ );
35221
+ }
35222
+ if (trigger.initialDelaySeconds !== void 0) {
35223
+ (0, import_assert4.default)(
35224
+ typeof trigger.initialDelaySeconds === "number",
35225
+ `${prefix}.initialDelaySeconds must be a number`
35226
+ );
35227
+ (0, import_assert4.default)(
35228
+ trigger.initialDelaySeconds >= 0,
35229
+ `${prefix}.initialDelaySeconds must be a non-negative number`
35230
+ );
35231
+ }
35232
+ if (trigger.maxConcurrency !== void 0) {
35233
+ (0, import_assert4.default)(
35234
+ typeof trigger.maxConcurrency === "number",
35235
+ `${prefix}.maxConcurrency must be a number`
35236
+ );
35237
+ (0, import_assert4.default)(
35238
+ Number.isInteger(trigger.maxConcurrency) && trigger.maxConcurrency >= 1,
35239
+ `${prefix}.maxConcurrency must be at least 1`
35240
+ );
35241
+ }
35232
35242
  }
35233
35243
  }
35234
35244
  }
@@ -35247,6 +35257,7 @@ var Lambda = class {
35247
35257
  this.architecture = getDefaultLambdaArchitecture(architecture);
35248
35258
  this.memory = memory;
35249
35259
  this.maxDuration = maxDuration;
35260
+ this.affinity = affinity;
35250
35261
  this.maxConcurrency = maxConcurrency;
35251
35262
  this.environment = environment;
35252
35263
  this.allowQuery = allowQuery;
@@ -35305,7 +35316,7 @@ async function createZip(files) {
35305
35316
  }
35306
35317
  }
35307
35318
  const zipFile = new import_yazl.ZipFile();
35308
- const zipBuffer = await new Promise((resolve, reject) => {
35319
+ const zipBuffer = await new Promise((resolve2, reject) => {
35309
35320
  for (const name of names) {
35310
35321
  const file = files[name];
35311
35322
  const opts = { mode: file.mode, mtime };
@@ -35321,7 +35332,7 @@ async function createZip(files) {
35321
35332
  }
35322
35333
  }
35323
35334
  zipFile.end();
35324
- streamToBuffer(zipFile.outputStream).then(resolve).catch(reject);
35335
+ streamToBuffer(zipFile.outputStream).then(resolve2).catch(reject);
35325
35336
  });
35326
35337
  return zipBuffer;
35327
35338
  }
@@ -35356,6 +35367,7 @@ async function getLambdaOptionsFromFunction({
35356
35367
  architecture: fn.architecture,
35357
35368
  memory: fn.memory,
35358
35369
  maxDuration: fn.maxDuration,
35370
+ affinity: fn.affinity,
35359
35371
  maxConcurrency: fn.maxConcurrency,
35360
35372
  regions: fn.regions,
35361
35373
  functionFailoverRegions: fn.functionFailoverRegions,
@@ -36705,7 +36717,7 @@ var NO_OVERRIDE = {
36705
36717
  path: void 0
36706
36718
  };
36707
36719
  function spawnAsync(command, args, opts = {}) {
36708
- return new Promise((resolve, reject) => {
36720
+ return new Promise((resolve2, reject) => {
36709
36721
  const stderrLogs = [];
36710
36722
  const hasCustomStreams = opts.outputStream || opts.errorStream;
36711
36723
  if (hasCustomStreams) {
@@ -36727,7 +36739,7 @@ function spawnAsync(command, args, opts = {}) {
36727
36739
  child.on("error", reject);
36728
36740
  child.on("close", (code, signal) => {
36729
36741
  if (code === 0 || opts.ignoreNon0Exit) {
36730
- return resolve();
36742
+ return resolve2();
36731
36743
  }
36732
36744
  const cmd = opts.prettyCommand ? `Command "${opts.prettyCommand}"` : "Command";
36733
36745
  reject(
@@ -37976,10 +37988,10 @@ var import_os2 = require("os");
37976
37988
  var import_path7 = require("path");
37977
37989
  var import_child_process = require("child_process");
37978
37990
  function spawnAsync2(command, args, options) {
37979
- return new Promise((resolve, reject) => {
37991
+ return new Promise((resolve2, reject) => {
37980
37992
  const child = (0, import_child_process.spawn)(command, args, options);
37981
37993
  child.once("error", reject);
37982
- child.once("close", resolve);
37994
+ child.once("close", resolve2);
37983
37995
  });
37984
37996
  }
37985
37997
  async function getOrCreateBunBinary() {
@@ -38289,6 +38301,38 @@ async function linkOrCopy(srcFile, destFile) {
38289
38301
  }
38290
38302
  }
38291
38303
 
38304
+ // src/get-node-exec-path.ts
38305
+ var import_node_fs = require("fs");
38306
+ var import_node_path = require("path");
38307
+ var NODE_EXEC_PATH_ENV = "VERCEL_NODE_EXEC_PATH";
38308
+ var NATIVE_CLI_ENV = "VERCEL_VC_NATIVE";
38309
+ function getNodeExecPath() {
38310
+ const override = process.env[NODE_EXEC_PATH_ENV];
38311
+ if (override)
38312
+ return override;
38313
+ if (!process.env[NATIVE_CLI_ENV])
38314
+ return process.execPath;
38315
+ const nodeExecPath = findNodeExecPath();
38316
+ process.env[NODE_EXEC_PATH_ENV] = nodeExecPath;
38317
+ return nodeExecPath;
38318
+ }
38319
+ function findNodeExecPath() {
38320
+ const executableName = process.platform === "win32" ? "node.exe" : "node";
38321
+ const cliPath = (0, import_node_fs.realpathSync)(process.execPath);
38322
+ for (const directory of (process.env.PATH || "").split(import_node_path.delimiter)) {
38323
+ if (!directory)
38324
+ continue;
38325
+ const candidate = (0, import_node_path.resolve)(directory, executableName);
38326
+ try {
38327
+ (0, import_node_fs.accessSync)(candidate, import_node_fs.constants.X_OK);
38328
+ if ((0, import_node_fs.realpathSync)(candidate) !== cliPath)
38329
+ return candidate;
38330
+ } catch {
38331
+ }
38332
+ }
38333
+ throw new Error("Could not find the Node.js executable in PATH.");
38334
+ }
38335
+
38292
38336
  // src/validate-npmrc.ts
38293
38337
  var import_path10 = require("path");
38294
38338
  var import_promises = require("fs/promises");
@@ -38332,6 +38376,7 @@ var ContainerImage = class {
38332
38376
  this.architecture = params.architecture;
38333
38377
  this.memory = params.memory;
38334
38378
  this.maxDuration = params.maxDuration;
38379
+ this.affinity = params.affinity;
38335
38380
  this.maxConcurrency = params.maxConcurrency;
38336
38381
  this.regions = params.regions;
38337
38382
  this.functionFailoverRegions = params.functionFailoverRegions;
@@ -38457,8 +38502,23 @@ var triggerEventSchemaV2 = {
38457
38502
  required: ["type", "topic"],
38458
38503
  additionalProperties: false
38459
38504
  };
38505
+ var scheduleTriggerEventSchemaV1 = {
38506
+ type: "object",
38507
+ properties: {
38508
+ type: {
38509
+ type: "string",
38510
+ const: "schedule/v1beta"
38511
+ }
38512
+ },
38513
+ required: ["type"],
38514
+ additionalProperties: false
38515
+ };
38460
38516
  var triggerEventSchema = {
38461
- oneOf: [triggerEventSchemaV1, triggerEventSchemaV2]
38517
+ oneOf: [
38518
+ triggerEventSchemaV1,
38519
+ triggerEventSchemaV2,
38520
+ scheduleTriggerEventSchemaV1
38521
+ ]
38462
38522
  };
38463
38523
  var getFunctionsSchema = () => ({
38464
38524
  type: "object",
@@ -38483,6 +38543,17 @@ var getFunctionsSchema = () => ({
38483
38543
  maximum: 10240
38484
38544
  },
38485
38545
  maxDuration: getMaxDurationSchema(),
38546
+ affinity: {
38547
+ type: "object",
38548
+ additionalProperties: false,
38549
+ required: ["mode"],
38550
+ properties: {
38551
+ mode: {
38552
+ type: "string",
38553
+ const: "strict"
38554
+ }
38555
+ }
38556
+ },
38486
38557
  maxConcurrency: {
38487
38558
  type: "integer",
38488
38559
  minimum: 1
@@ -38561,7 +38632,12 @@ var packageManifestSchema = {
38561
38632
  },
38562
38633
  serviceType: {
38563
38634
  type: "string",
38564
- description: 'Service type: one of "web", "schedule", "queue", "workflow".'
38635
+ description: 'Deployment topology for service builds: "web", "schedule", "queue", or "workflow".'
38636
+ },
38637
+ buildType: {
38638
+ type: "string",
38639
+ enum: ["app", "api-dir", "middleware"],
38640
+ description: 'What triggered this build: "app" (full application build), "api-dir" (api/ directory build), or "middleware" (middleware build).'
38565
38641
  },
38566
38642
  runtimeVersion: {
38567
38643
  type: "object",
@@ -39005,8 +39081,21 @@ async function generateProjectManifest({
39005
39081
  }) {
39006
39082
  try {
39007
39083
  const pkgJson = await readPackageJson(workPath);
39008
- if (!pkgJson)
39084
+ if (!pkgJson) {
39085
+ await writeProjectManifest(
39086
+ {
39087
+ version: MANIFEST_VERSION,
39088
+ runtime: "node",
39089
+ ...framework ? { framework } : {},
39090
+ ...serviceType ? { serviceType } : {},
39091
+ runtimeVersion: { resolved: String(nodeVersion.major) },
39092
+ dependencies: []
39093
+ },
39094
+ workPath,
39095
+ outputRuntime
39096
+ );
39009
39097
  return;
39098
+ }
39010
39099
  const { directScopes, directRequested } = buildDirectMaps(pkgJson);
39011
39100
  const lockMap = lockfilePath ? await parseLockfile(cliType, lockfilePath, lockfileVersion) : /* @__PURE__ */ new Map();
39012
39101
  const directDeps = [];
@@ -39386,8 +39475,8 @@ async function isPackageInstalled(packageName, path8) {
39386
39475
  var defaultCachePathGlob = "**/{node_modules,.yarn/cache}/**";
39387
39476
 
39388
39477
  // src/generate-node-builder-functions.ts
39389
- var import_node_path = require("path");
39390
- var import_node_fs = __toESM(require("fs"));
39478
+ var import_node_path2 = require("path");
39479
+ var import_node_fs2 = __toESM(require("fs"));
39391
39480
  var import_node_module = require("module");
39392
39481
  function generateNodeBuilderFunctions(frameworkName, regex, validFilenames, validExtensions, nodeBuild, opts) {
39393
39482
  const entrypointsForMessage = validFilenames.map((filename) => `- ${filename}.{${validExtensions.join(",")}}`).join("\n");
@@ -39459,9 +39548,9 @@ function generateNodeBuilderFunctions(frameworkName, regex, validFilenames, vali
39459
39548
  const {
39460
39549
  entrypoint: entrypointFromOutputDir,
39461
39550
  entrypointsNotMatchingRegex: entrypointsNotMatchingRegex2
39462
- } = findEntrypoint(await glob(entrypointGlob, (0, import_node_path.join)(args.workPath, dir)));
39551
+ } = findEntrypoint(await glob(entrypointGlob, (0, import_node_path2.join)(args.workPath, dir)));
39463
39552
  if (entrypointFromOutputDir) {
39464
- return (0, import_node_path.join)(dir, entrypointFromOutputDir);
39553
+ return (0, import_node_path2.join)(dir, entrypointFromOutputDir);
39465
39554
  }
39466
39555
  if (entrypointsNotMatchingRegex2.length > 0) {
39467
39556
  throw new Error(
@@ -39533,7 +39622,7 @@ ${entrypointsForMessage}`
39533
39622
  };
39534
39623
  };
39535
39624
  const checkMatchesRegex = (file) => {
39536
- const content = import_node_fs.default.readFileSync(file.fsPath, "utf-8");
39625
+ const content = import_node_fs2.default.readFileSync(file.fsPath, "utf-8");
39537
39626
  const matchesContent = content.match(regex);
39538
39627
  return matchesContent !== null;
39539
39628
  };
@@ -39541,7 +39630,7 @@ ${entrypointsForMessage}`
39541
39630
  const packageJson = files["package.json"];
39542
39631
  if (packageJson) {
39543
39632
  if (packageJson.type === "FileFsRef") {
39544
- const packageJsonContent = import_node_fs.default.readFileSync(packageJson.fsPath, "utf-8");
39633
+ const packageJsonContent = import_node_fs2.default.readFileSync(packageJson.fsPath, "utf-8");
39545
39634
  let packageJsonJson;
39546
39635
  try {
39547
39636
  packageJsonJson = JSON.parse(packageJsonContent);
@@ -39959,7 +40048,7 @@ function getLambdaSupportsStreaming(lambda, forceStreamingRuntime) {
39959
40048
  // src/fs/stream-to-digest-async.ts
39960
40049
  var import_crypto = require("crypto");
39961
40050
  async function streamToDigestAsync(stream) {
39962
- return await new Promise((resolve, reject) => {
40051
+ return await new Promise((resolve2, reject) => {
39963
40052
  stream.once("error", reject);
39964
40053
  let count = 0;
39965
40054
  const sha2562 = (0, import_crypto.createHash)("sha256");
@@ -39970,7 +40059,7 @@ async function streamToDigestAsync(stream) {
39970
40059
  md5: md52.digest("hex"),
39971
40060
  size: count
39972
40061
  };
39973
- resolve(res);
40062
+ resolve2(res);
39974
40063
  });
39975
40064
  stream.on("readable", () => {
39976
40065
  let chunk;
@@ -40984,6 +41073,7 @@ function getExtendedPayload({
40984
41073
  getMaxDurationSchema,
40985
41074
  getNodeBinPath,
40986
41075
  getNodeBinPaths,
41076
+ getNodeExecPath,
40987
41077
  getNodeVersion,
40988
41078
  getOrCreateBunBinary,
40989
41079
  getPackageJson,
package/dist/lambda.d.ts CHANGED
@@ -20,6 +20,9 @@ export declare function sanitizeConsumerName(functionPath: string): string;
20
20
  export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer;
21
21
  export type LambdaExecutableRuntimeLanguages = 'rust' | 'go';
22
22
  export type LambdaArchitecture = 'x86_64' | 'arm64';
23
+ export interface LambdaAffinity {
24
+ mode: 'strict';
25
+ }
23
26
  export interface LambdaOptionsBase {
24
27
  handler: string;
25
28
  runtime: string;
@@ -27,6 +30,7 @@ export interface LambdaOptionsBase {
27
30
  architecture?: LambdaArchitecture;
28
31
  memory?: number;
29
32
  maxDuration?: MaxDuration;
33
+ affinity?: LambdaAffinity;
30
34
  maxConcurrency?: number;
31
35
  environment?: Env;
32
36
  allowQuery?: string[];
@@ -103,6 +107,7 @@ export declare class Lambda {
103
107
  architecture: LambdaArchitecture;
104
108
  memory?: number;
105
109
  maxDuration?: MaxDuration;
110
+ affinity?: LambdaAffinity;
106
111
  /** Maximum number of requests that one function instance can process concurrently. */
107
112
  maxConcurrency?: number;
108
113
  environment: Env;
@@ -156,4 +161,4 @@ export declare class Lambda {
156
161
  */
157
162
  export declare function createLambda(opts: LambdaOptions): Promise<Lambda>;
158
163
  export declare function createZip(files: Files): Promise<Buffer>;
159
- export declare function getLambdaOptionsFromFunction({ sourceFile, config, }: GetLambdaOptionsFromFunctionOptions): Promise<Pick<LambdaOptions, 'architecture' | 'memory' | 'maxDuration' | 'maxConcurrency' | 'regions' | 'functionFailoverRegions' | 'experimentalTriggers' | 'supportsCancellation'>>;
164
+ export declare function getLambdaOptionsFromFunction({ sourceFile, config, }: GetLambdaOptionsFromFunctionOptions): Promise<Pick<LambdaOptions, 'architecture' | 'memory' | 'maxDuration' | 'affinity' | 'maxConcurrency' | 'regions' | 'functionFailoverRegions' | 'experimentalTriggers' | 'supportsCancellation'>>;
package/dist/lambda.js CHANGED
@@ -80,6 +80,7 @@ class Lambda {
80
80
  runtime,
81
81
  runtimeLanguage,
82
82
  maxDuration,
83
+ affinity,
83
84
  maxConcurrency,
84
85
  architecture,
85
86
  memory,
@@ -133,6 +134,12 @@ class Lambda {
133
134
  '"maxDuration" is not a number or "max"'
134
135
  );
135
136
  }
137
+ if (affinity !== void 0) {
138
+ (0, import_assert.default)(
139
+ typeof affinity === "object" && affinity !== null && affinity.mode === "strict" && Object.keys(affinity).length === 1,
140
+ '"affinity" must be an object with only `mode: "strict"`'
141
+ );
142
+ }
136
143
  if (maxConcurrency !== void 0) {
137
144
  (0, import_assert.default)(
138
145
  Number.isInteger(maxConcurrency) && maxConcurrency >= 1,
@@ -201,61 +208,63 @@ class Lambda {
201
208
  `${prefix} is not an object`
202
209
  );
203
210
  (0, import_assert.default)(
204
- trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta",
205
- `${prefix}.type must be "queue/v1beta" or "queue/v2beta"`
206
- );
207
- (0, import_assert.default)(
208
- typeof trigger.topic === "string",
209
- `${prefix}.topic is required and must be a string`
210
- );
211
- (0, import_assert.default)(trigger.topic.length > 0, `${prefix}.topic cannot be empty`);
212
- (0, import_assert.default)(
213
- typeof trigger.consumer === "string",
214
- `${prefix}.consumer is required and must be a string`
211
+ trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta" || trigger.type === "schedule/v1beta",
212
+ `${prefix}.type must be "queue/v1beta", "queue/v2beta", or "schedule/v1beta"`
215
213
  );
216
- (0, import_assert.default)(
217
- trigger.consumer.length > 0,
218
- `${prefix}.consumer cannot be empty`
219
- );
220
- if (trigger.maxDeliveries !== void 0) {
221
- (0, import_assert.default)(
222
- typeof trigger.maxDeliveries === "number",
223
- `${prefix}.maxDeliveries must be a number`
224
- );
225
- (0, import_assert.default)(
226
- Number.isInteger(trigger.maxDeliveries) && trigger.maxDeliveries >= 1,
227
- `${prefix}.maxDeliveries must be at least 1`
228
- );
229
- }
230
- if (trigger.retryAfterSeconds !== void 0) {
231
- (0, import_assert.default)(
232
- typeof trigger.retryAfterSeconds === "number",
233
- `${prefix}.retryAfterSeconds must be a number`
234
- );
214
+ if (trigger.type === "queue/v1beta" || trigger.type === "queue/v2beta") {
235
215
  (0, import_assert.default)(
236
- trigger.retryAfterSeconds > 0,
237
- `${prefix}.retryAfterSeconds must be a positive number`
216
+ typeof trigger.topic === "string",
217
+ `${prefix}.topic is required and must be a string`
238
218
  );
239
- }
240
- if (trigger.initialDelaySeconds !== void 0) {
219
+ (0, import_assert.default)(trigger.topic.length > 0, `${prefix}.topic cannot be empty`);
241
220
  (0, import_assert.default)(
242
- typeof trigger.initialDelaySeconds === "number",
243
- `${prefix}.initialDelaySeconds must be a number`
221
+ typeof trigger.consumer === "string",
222
+ `${prefix}.consumer is required and must be a string`
244
223
  );
245
224
  (0, import_assert.default)(
246
- trigger.initialDelaySeconds >= 0,
247
- `${prefix}.initialDelaySeconds must be a non-negative number`
248
- );
249
- }
250
- if (trigger.maxConcurrency !== void 0) {
251
- (0, import_assert.default)(
252
- typeof trigger.maxConcurrency === "number",
253
- `${prefix}.maxConcurrency must be a number`
254
- );
255
- (0, import_assert.default)(
256
- Number.isInteger(trigger.maxConcurrency) && trigger.maxConcurrency >= 1,
257
- `${prefix}.maxConcurrency must be at least 1`
225
+ trigger.consumer.length > 0,
226
+ `${prefix}.consumer cannot be empty`
258
227
  );
228
+ if (trigger.maxDeliveries !== void 0) {
229
+ (0, import_assert.default)(
230
+ typeof trigger.maxDeliveries === "number",
231
+ `${prefix}.maxDeliveries must be a number`
232
+ );
233
+ (0, import_assert.default)(
234
+ Number.isInteger(trigger.maxDeliveries) && trigger.maxDeliveries >= 1,
235
+ `${prefix}.maxDeliveries must be at least 1`
236
+ );
237
+ }
238
+ if (trigger.retryAfterSeconds !== void 0) {
239
+ (0, import_assert.default)(
240
+ typeof trigger.retryAfterSeconds === "number",
241
+ `${prefix}.retryAfterSeconds must be a number`
242
+ );
243
+ (0, import_assert.default)(
244
+ trigger.retryAfterSeconds > 0,
245
+ `${prefix}.retryAfterSeconds must be a positive number`
246
+ );
247
+ }
248
+ if (trigger.initialDelaySeconds !== void 0) {
249
+ (0, import_assert.default)(
250
+ typeof trigger.initialDelaySeconds === "number",
251
+ `${prefix}.initialDelaySeconds must be a number`
252
+ );
253
+ (0, import_assert.default)(
254
+ trigger.initialDelaySeconds >= 0,
255
+ `${prefix}.initialDelaySeconds must be a non-negative number`
256
+ );
257
+ }
258
+ if (trigger.maxConcurrency !== void 0) {
259
+ (0, import_assert.default)(
260
+ typeof trigger.maxConcurrency === "number",
261
+ `${prefix}.maxConcurrency must be a number`
262
+ );
263
+ (0, import_assert.default)(
264
+ Number.isInteger(trigger.maxConcurrency) && trigger.maxConcurrency >= 1,
265
+ `${prefix}.maxConcurrency must be at least 1`
266
+ );
267
+ }
259
268
  }
260
269
  }
261
270
  }
@@ -274,6 +283,7 @@ class Lambda {
274
283
  this.architecture = getDefaultLambdaArchitecture(architecture);
275
284
  this.memory = memory;
276
285
  this.maxDuration = maxDuration;
286
+ this.affinity = affinity;
277
287
  this.maxConcurrency = maxConcurrency;
278
288
  this.environment = environment;
279
289
  this.allowQuery = allowQuery;
@@ -383,6 +393,7 @@ async function getLambdaOptionsFromFunction({
383
393
  architecture: fn.architecture,
384
394
  memory: fn.memory,
385
395
  maxDuration: fn.maxDuration,
396
+ affinity: fn.affinity,
386
397
  maxConcurrency: fn.maxConcurrency,
387
398
  regions: fn.regions,
388
399
  functionFailoverRegions: fn.functionFailoverRegions,
@@ -392,8 +392,21 @@ async function generateProjectManifest({
392
392
  }) {
393
393
  try {
394
394
  const pkgJson = await readPackageJson(workPath);
395
- if (!pkgJson)
395
+ if (!pkgJson) {
396
+ await (0, import_package_manifest.writeProjectManifest)(
397
+ {
398
+ version: import_package_manifest.MANIFEST_VERSION,
399
+ runtime: "node",
400
+ ...framework ? { framework } : {},
401
+ ...serviceType ? { serviceType } : {},
402
+ runtimeVersion: { resolved: String(nodeVersion.major) },
403
+ dependencies: []
404
+ },
405
+ workPath,
406
+ outputRuntime
407
+ );
396
408
  return;
409
+ }
397
410
  const { directScopes, directRequested } = buildDirectMaps(pkgJson);
398
411
  const lockMap = lockfilePath ? await parseLockfile(cliType, lockfilePath, lockfileVersion) : /* @__PURE__ */ new Map();
399
412
  const directDeps = [];
@@ -8,11 +8,20 @@ export interface PackageManifestDependency {
8
8
  source?: string;
9
9
  sourceUrl?: string;
10
10
  }
11
+ /**
12
+ * What triggered this build pipeline entry.
13
+ *
14
+ * - `'app'` — full application build
15
+ * - `'api-dir'` — api/ directory build
16
+ * - `'middleware'` — middleware build
17
+ */
18
+ export type BuildType = 'app' | 'api-dir' | 'middleware';
11
19
  export interface PackageManifest {
12
20
  version?: string;
13
21
  runtime: string;
14
22
  framework?: string;
15
23
  serviceType?: string;
24
+ buildType?: BuildType;
16
25
  runtimeVersion?: {
17
26
  requested?: string;
18
27
  requestedSource?: string;
package/dist/schemas.d.ts CHANGED
@@ -31,6 +31,17 @@ export declare const getFunctionsSchema: () => {
31
31
  enum: string[];
32
32
  })[];
33
33
  };
34
+ affinity: {
35
+ type: string;
36
+ additionalProperties: boolean;
37
+ required: string[];
38
+ properties: {
39
+ mode: {
40
+ type: string;
41
+ const: string;
42
+ };
43
+ };
44
+ };
34
45
  maxConcurrency: {
35
46
  type: string;
36
47
  minimum: number;
@@ -65,26 +76,6 @@ export declare const getFunctionsSchema: () => {
65
76
  type: string;
66
77
  const: string;
67
78
  };
68
- topic: {
69
- type: string;
70
- minLength: number;
71
- };
72
- maxDeliveries: {
73
- type: string;
74
- minimum: number;
75
- };
76
- retryAfterSeconds: {
77
- type: string;
78
- exclusiveMinimum: number;
79
- };
80
- initialDelaySeconds: {
81
- type: string;
82
- minimum: number;
83
- };
84
- maxConcurrency: {
85
- type: string;
86
- minimum: number;
87
- };
88
79
  };
89
80
  required: string[];
90
81
  additionalProperties: boolean;
@@ -137,6 +128,17 @@ export declare const functionsSchema: {
137
128
  enum: string[];
138
129
  })[];
139
130
  };
131
+ affinity: {
132
+ type: string;
133
+ additionalProperties: boolean;
134
+ required: string[];
135
+ properties: {
136
+ mode: {
137
+ type: string;
138
+ const: string;
139
+ };
140
+ };
141
+ };
140
142
  maxConcurrency: {
141
143
  type: string;
142
144
  minimum: number;
@@ -171,26 +173,6 @@ export declare const functionsSchema: {
171
173
  type: string;
172
174
  const: string;
173
175
  };
174
- topic: {
175
- type: string;
176
- minLength: number;
177
- };
178
- maxDeliveries: {
179
- type: string;
180
- minimum: number;
181
- };
182
- retryAfterSeconds: {
183
- type: string;
184
- exclusiveMinimum: number;
185
- };
186
- initialDelaySeconds: {
187
- type: string;
188
- minimum: number;
189
- };
190
- maxConcurrency: {
191
- type: string;
192
- minimum: number;
193
- };
194
176
  };
195
177
  required: string[];
196
178
  additionalProperties: boolean;
@@ -254,7 +236,12 @@ export declare const packageManifestSchema: {
254
236
  };
255
237
  readonly serviceType: {
256
238
  readonly type: "string";
257
- readonly description: "Service type: one of \"web\", \"schedule\", \"queue\", \"workflow\".";
239
+ readonly description: "Deployment topology for service builds: \"web\", \"schedule\", \"queue\", or \"workflow\".";
240
+ };
241
+ readonly buildType: {
242
+ readonly type: "string";
243
+ readonly enum: readonly ["app", "api-dir", "middleware"];
244
+ readonly description: "What triggered this build: \"app\" (full application build), \"api-dir\" (api/ directory build), or \"middleware\" (middleware build).";
258
245
  };
259
246
  readonly runtimeVersion: {
260
247
  readonly type: "object";
package/dist/schemas.js CHANGED
@@ -91,8 +91,23 @@ const triggerEventSchemaV2 = {
91
91
  required: ["type", "topic"],
92
92
  additionalProperties: false
93
93
  };
94
+ const scheduleTriggerEventSchemaV1 = {
95
+ type: "object",
96
+ properties: {
97
+ type: {
98
+ type: "string",
99
+ const: "schedule/v1beta"
100
+ }
101
+ },
102
+ required: ["type"],
103
+ additionalProperties: false
104
+ };
94
105
  const triggerEventSchema = {
95
- oneOf: [triggerEventSchemaV1, triggerEventSchemaV2]
106
+ oneOf: [
107
+ triggerEventSchemaV1,
108
+ triggerEventSchemaV2,
109
+ scheduleTriggerEventSchemaV1
110
+ ]
96
111
  };
97
112
  const getFunctionsSchema = () => ({
98
113
  type: "object",
@@ -117,6 +132,17 @@ const getFunctionsSchema = () => ({
117
132
  maximum: 10240
118
133
  },
119
134
  maxDuration: (0, import_max_duration.getMaxDurationSchema)(),
135
+ affinity: {
136
+ type: "object",
137
+ additionalProperties: false,
138
+ required: ["mode"],
139
+ properties: {
140
+ mode: {
141
+ type: "string",
142
+ const: "strict"
143
+ }
144
+ }
145
+ },
120
146
  maxConcurrency: {
121
147
  type: "integer",
122
148
  minimum: 1
@@ -195,7 +221,12 @@ const packageManifestSchema = {
195
221
  },
196
222
  serviceType: {
197
223
  type: "string",
198
- description: 'Service type: one of "web", "schedule", "queue", "workflow".'
224
+ description: 'Deployment topology for service builds: "web", "schedule", "queue", or "workflow".'
225
+ },
226
+ buildType: {
227
+ type: "string",
228
+ enum: ["app", "api-dir", "middleware"],
229
+ description: 'What triggered this build: "app" (full application build), "api-dir" (api/ directory build), or "middleware" (middleware build).'
199
230
  },
200
231
  runtimeVersion: {
201
232
  type: "object",
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type FileRef from './file-ref';
2
2
  import type FileFsRef from './file-fs-ref';
3
3
  import type FileBlob from './file-blob';
4
- import type { Lambda, LambdaArchitecture } from './lambda';
4
+ import type { Lambda, LambdaAffinity, LambdaArchitecture } from './lambda';
5
5
  import type { Prerender } from './prerender';
6
6
  import type { EdgeFunction } from './edge-function';
7
7
  import type { ContainerImage } from './container-image';
@@ -415,6 +415,7 @@ export interface BuilderFunctions {
415
415
  architecture?: LambdaArchitecture;
416
416
  memory?: number;
417
417
  maxDuration?: MaxDuration;
418
+ affinity?: LambdaAffinity;
418
419
  maxConcurrency?: number;
419
420
  regions?: string[];
420
421
  functionFailoverRegions?: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "14.5.1",
3
+ "version": "14.7.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -52,8 +52,8 @@
52
52
  "vitest": "4.1.10",
53
53
  "typescript": "4.9.5",
54
54
  "yazl": "2.5.1",
55
- "@vercel/routing-utils": "6.5.0",
56
- "@vercel/error-utils": "2.2.1"
55
+ "@vercel/error-utils": "2.2.1",
56
+ "@vercel/routing-utils": "6.5.0"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "node build.mjs",