@vercel/build-utils 13.36.3 → 14.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # @vercel/build-utils
2
2
 
3
+ ## 14.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6d7fbfa: Bump all workspace packages to trigger a full publish from vercel-internal.
8
+ - Updated dependencies [6d7fbfa]
9
+ - @vercel/python-analysis@0.13.1
10
+
11
+ ## 14.0.0
12
+
13
+ ### Major Changes
14
+
15
+ - 5c33351: Remove `getOsRelease()`, and stop deriving the provided runtime from the build host.
16
+
17
+ `getProvidedRuntime()` is retained and now always resolves to `'provided.al2023'`. It previously read `/etc/os-release` and returned `'provided.al2'` on Amazon Linux 2 hosts, so the emitted runtime depended on where the build ran — a `vercel build` on an AL2 machine produced output that is rejected at deploy time, because `provided.al2` is no longer an accepted Lambda runtime. Custom runtimes calling `getProvidedRuntime()` need no changes and are fixed by this release.
18
+
19
+ `getOsRelease()` is removed with no replacement.
20
+
21
+ `validateBuildResult()` no longer accepts an `osRelease` option. Its runtime allowlist check was previously skipped unless the caller passed `osRelease.VERSION === '2023'`; it now always runs.
22
+
23
+ ### Minor Changes
24
+
25
+ - b747ab4: Replace the inferred PPR fields on `Prerender` with the Next.js prerender taxonomy.
26
+
27
+ `hasPostponed`, `hasFallback`, `isDynamicRoute` and `htmlSize` were derived by
28
+ `@vercel/next` from build artifacts (the `.meta` postponed state, which manifest
29
+ section a route came from, and a `statSync` of the `.html` shell). Next.js
30
+ `>= 16.3.0-canary.96` publishes its own classification in the prerender
31
+ manifest, so those four fields are removed in favour of a single optional
32
+ `prerenderClassification` on `Prerender` / `PrerenderOptions`:
33
+
34
+ - `routeType` — `'route' | 'page' | 'shell' | 'fallback'`
35
+ - `response` — `'empty' | 'initial' | 'complete'`
36
+ - `compute` — `'blocking' | 'resuming' | 'static'`
37
+ - `htmlSize` — byte size of the prerendered HTML shell, when the entry has one
38
+
39
+ The values are carried through unvalidated so a taxonomy value added by a future
40
+ Next.js release cannot hard-fail a deploy. `@vercel/next` sets the field only
41
+ when Next.js supplied the complete group — absence is legitimate for
42
+ `notFoundRoutes` and Pages Router `fallback: false` templates — and only on the
43
+ primary output of each prerender group, so a route is classified exactly once.
44
+
45
+ - 5619873: Fix api dir builds receiving incorrect framework or runtime.
46
+
47
+ ### Patch Changes
48
+
49
+ - Updated dependencies [08a2618]
50
+ - @vercel/python-analysis@0.13.0
51
+
3
52
  ## 13.36.3
4
53
 
5
54
  ### Patch Changes
@@ -9,13 +9,11 @@ export interface ValidateBuildResultParams {
9
9
  allowInvalidRuntime?: boolean;
10
10
  buildConfig?: BuildConfigWithVercelConfig;
11
11
  buildResponse: BuildResultV2Typical | BuildResultV3;
12
- osRelease?: OsRelease | null;
13
12
  vercelBaseUrl?: string;
14
13
  }
15
14
  export interface ValidateBuildResultResult {
16
15
  buildOutputMap: BuildResultV2Typical['output'];
17
16
  customFunctionConfiguration?: BuilderFunctions[string];
18
17
  }
19
- type OsRelease = Record<string, string>;
20
- export declare function validateBuildResult({ allowInvalidRuntime, buildConfig, buildResponse, osRelease, vercelBaseUrl, }: ValidateBuildResultParams): Promise<ValidateBuildResultResult>;
18
+ export declare function validateBuildResult({ allowInvalidRuntime, buildConfig, buildResponse, vercelBaseUrl, }: ValidateBuildResultParams): Promise<ValidateBuildResultResult>;
21
19
  export {};
@@ -55,7 +55,6 @@ async function validateBuildResult({
55
55
  allowInvalidRuntime = false,
56
56
  buildConfig,
57
57
  buildResponse,
58
- osRelease,
59
58
  vercelBaseUrl
60
59
  }) {
61
60
  if (!("output" in buildResponse)) {
@@ -71,33 +70,31 @@ async function validateBuildResult({
71
70
  });
72
71
  }
73
72
  const buildOutputMap = getAndVerifyOutputLambdasOrEdgeFuncs(buildResponse);
74
- if (osRelease?.VERSION === "2023") {
75
- const invalidRuntimes = [];
76
- for (const [name, entry] of Object.entries(buildOutputMap)) {
77
- let lambda;
78
- if (entry.type === "Prerender") {
79
- lambda = entry.lambda;
80
- } else if (entry.type === "Lambda") {
81
- lambda = entry;
82
- }
83
- if (!lambda)
84
- continue;
85
- if (!isSupportedAl2023Runtime(lambda.runtime)) {
86
- invalidRuntimes.push({ name, lambda });
87
- }
73
+ const invalidRuntimes = [];
74
+ for (const [name, entry] of Object.entries(buildOutputMap)) {
75
+ let lambda;
76
+ if (entry.type === "Prerender") {
77
+ lambda = entry.lambda;
78
+ } else if (entry.type === "Lambda") {
79
+ lambda = entry;
88
80
  }
89
- if (invalidRuntimes.length > 0 && !allowInvalidRuntime) {
90
- throw new import_errors.NowBuildError({
91
- code: "NOW_SANDBOX_WORKER_INVALID_RUNTIME",
92
- message: `The following Serverless Functions contain an invalid "runtime":
93
- ${invalidRuntimes.map(({ name, lambda }) => ` - ${name} (${lambda.runtime})`).join("\n")}`,
94
- link: getVercelUrl(
95
- "/docs/functions/runtimes#official-runtimes",
96
- vercelBaseUrl
97
- )
98
- });
81
+ if (!lambda)
82
+ continue;
83
+ if (!isSupportedAl2023Runtime(lambda.runtime)) {
84
+ invalidRuntimes.push({ name, lambda });
99
85
  }
100
86
  }
87
+ if (invalidRuntimes.length > 0 && !allowInvalidRuntime) {
88
+ throw new import_errors.NowBuildError({
89
+ code: "NOW_SANDBOX_WORKER_INVALID_RUNTIME",
90
+ message: `The following Serverless Functions contain an invalid "runtime":
91
+ ${invalidRuntimes.map(({ name, lambda }) => ` - ${name} (${lambda.runtime})`).join("\n")}`,
92
+ link: getVercelUrl(
93
+ "/docs/functions/runtimes#official-runtimes",
94
+ vercelBaseUrl
95
+ )
96
+ });
97
+ }
101
98
  const customFunctionConfiguration = getCustomFunctionConfigMaybe(buildConfig);
102
99
  if (customFunctionConfiguration?.runtime) {
103
100
  throw new import_errors.NowBuildError({
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import FileFsRef from './file-fs-ref';
3
3
  import FileRef from './file-ref';
4
4
  import { Lambda, createLambda, getLambdaOptionsFromFunction, sanitizeConsumerName } from './lambda';
5
5
  import { NodejsLambda, type NodejsLambdaOptions } from './nodejs-lambda';
6
- import { Prerender } from './prerender';
6
+ import { Prerender, type PrerenderClassification } from './prerender';
7
7
  import download, { downloadFile, DownloadedFiles, isSymbolicLink, isDirectory, isExternalSymlink, isExternalSymlinkTarget, getSymlinkTarget } from './fs/download';
8
8
  import getWriteableDirectory from './fs/get-writable-directory';
9
9
  import glob, { GlobOptions } from './fs/glob';
@@ -19,14 +19,14 @@ import { getServiceUrlEnvVars, getExperimentalServiceUrlEnvVars } from './get-se
19
19
  import { cloneEnv } from './clone-env';
20
20
  import { hardLinkDir } from './hard-link-dir';
21
21
  import { validateNpmrc } from './validate-npmrc';
22
- export type { NodejsLambdaOptions };
22
+ export type { NodejsLambdaOptions, PrerenderClassification };
23
23
  export { FileBlob, FileFsRef, FileRef, Lambda, NodejsLambda, createLambda, Prerender, download, downloadFile, DownloadedFiles, getWriteableDirectory, glob, GlobOptions, rename, spawnAsync, getScriptName, installDependencies, runPackageJsonScript, execCommand, spawnCommand, walkParentDirs, getNodeBinPath, getNodeBinPaths, getSupportedNodeVersion, isBunVersion, getSupportedBunVersion, detectPackageManager, runNpmInstall, NpmInstallOutput, runBundleInstall, runPipInstall, PipInstallResult, runShellScript, runCustomInstallCommand, resetCustomInstallCommandSet, getEnvForPackageManager, getNodeVersion, getPathForPackageManager, getLatestNodeVersion, getDiscontinuedNodeVersions, getSpawnOptions, getPlatformEnv, getPrefixedEnvVars, getServiceUrlEnvVars, getExperimentalServiceUrlEnvVars, streamToBuffer, streamToBufferChunks, debug, isSymbolicLink, isDirectory, isExternalSymlink, isExternalSymlinkTarget, getSymlinkTarget, getLambdaOptionsFromFunction, sanitizeConsumerName, scanParentDirs, findPackageJson, getIgnoreFilter, cloneEnv, hardLinkDir, traverseUpDirectories, validateNpmrc, type CliType, };
24
24
  export { EdgeFunction } from './edge-function';
25
25
  export { ContainerImage } from './container-image';
26
26
  export type { ContainerImageConfig } from './container-image';
27
27
  export { readConfigFile, getPackageJson } from './fs/read-config-file';
28
28
  export { normalizePath } from './fs/normalize-path';
29
- export { getOsRelease, getProvidedRuntime } from './os';
29
+ export { getProvidedRuntime } from './provided-runtime';
30
30
  export * from './should-serve';
31
31
  export * from './schemas';
32
32
  export { DEFAULT_MAX_DURATION_LIMIT, SKIP_MAX_DURATION_LIMIT_ENV, getMaxDurationLimit, getMaxDurationSchema, } from './max-duration';
package/dist/index.js CHANGED
@@ -2918,8 +2918,8 @@ var require_graceful_fs = __commonJS({
2918
2918
  fs13.createReadStream = createReadStream;
2919
2919
  fs13.createWriteStream = createWriteStream;
2920
2920
  var fs$readFile = fs13.readFile;
2921
- fs13.readFile = readFile4;
2922
- function readFile4(path8, options, cb) {
2921
+ fs13.readFile = readFile3;
2922
+ function readFile3(path8, options, cb) {
2923
2923
  if (typeof options === "function")
2924
2924
  cb = options, options = null;
2925
2925
  return go$readFile(path8, options, cb);
@@ -4667,7 +4667,7 @@ var require_jsonfile = __commonJS({
4667
4667
  }
4668
4668
  return obj;
4669
4669
  }
4670
- var readFile4 = universalify.fromPromise(_readFile);
4670
+ var readFile3 = universalify.fromPromise(_readFile);
4671
4671
  function readFileSync(file, options = {}) {
4672
4672
  if (typeof options === "string") {
4673
4673
  options = { encoding: options };
@@ -4699,7 +4699,7 @@ var require_jsonfile = __commonJS({
4699
4699
  return fs12.writeFileSync(file, str, options);
4700
4700
  }
4701
4701
  module2.exports = {
4702
- readFile: readFile4,
4702
+ readFile: readFile3,
4703
4703
  readFileSync,
4704
4704
  writeFile,
4705
4705
  writeFileSync
@@ -15412,7 +15412,7 @@ var require_dist = __commonJS({
15412
15412
  errorToString: () => errorToString,
15413
15413
  errorToStringFriendly: () => errorToStringFriendly,
15414
15414
  getSystemErrorMessage: () => getSystemErrorMessage,
15415
- isErrnoException: () => isErrnoException3,
15415
+ isErrnoException: () => isErrnoException2,
15416
15416
  isError: () => isError,
15417
15417
  isErrorLike: () => isErrorLike,
15418
15418
  isObject: () => isObject,
@@ -15425,7 +15425,7 @@ var require_dist = __commonJS({
15425
15425
  var isError = (error) => {
15426
15426
  return import_node_util.default.types.isNativeError(error);
15427
15427
  };
15428
- var isErrnoException3 = (error) => {
15428
+ var isErrnoException2 = (error) => {
15429
15429
  return isError(error) && "code" in error;
15430
15430
  };
15431
15431
  var nativeGetSystemErrorMessage = import_node_util.default.getSystemErrorMessage;
@@ -15442,7 +15442,7 @@ var require_dist = __commonJS({
15442
15442
  };
15443
15443
  var getSystemErrorMessage = nativeGetSystemErrorMessage ?? getSystemErrorMessageFallback;
15444
15444
  var errorToStringFriendly = (error, fallback) => {
15445
- if (isErrnoException3(error) && typeof error.errno === "number") {
15445
+ if (isErrnoException2(error) && typeof error.errno === "number") {
15446
15446
  return getSystemErrorMessage(error.errno);
15447
15447
  }
15448
15448
  return errorToString(error, fallback);
@@ -15454,7 +15454,7 @@ var require_dist = __commonJS({
15454
15454
  return isErrorLike(error) ? Object.assign(new Error(errorMessage), error) : new Error(errorMessage);
15455
15455
  };
15456
15456
  function isSpawnError(v) {
15457
- return isErrnoException3(v) && "spawnargs" in v;
15457
+ return isErrnoException2(v) && "spawnargs" in v;
15458
15458
  }
15459
15459
  }
15460
15460
  });
@@ -31618,7 +31618,6 @@ __export(src_exports, {
31618
31618
  getNodeBinPath: () => getNodeBinPath,
31619
31619
  getNodeBinPaths: () => getNodeBinPaths,
31620
31620
  getNodeVersion: () => getNodeVersion,
31621
- getOsRelease: () => getOsRelease,
31622
31621
  getPackageJson: () => getPackageJson,
31623
31622
  getPathForPackageManager: () => getPathForPackageManager,
31624
31623
  getPlatformEnv: () => getPlatformEnv,
@@ -32616,13 +32615,6 @@ var NodejsLambda = class extends Lambda {
32616
32615
  };
32617
32616
 
32618
32617
  // src/prerender.ts
32619
- function assertOptionalBoolean(value, name) {
32620
- if (value !== void 0 && typeof value !== "boolean") {
32621
- throw new Error(
32622
- `The \`${name}\` argument for \`Prerender\` must be a boolean or undefined.`
32623
- );
32624
- }
32625
- }
32626
32618
  var Prerender = class {
32627
32619
  constructor({
32628
32620
  expiration,
@@ -32642,27 +32634,13 @@ var Prerender = class {
32642
32634
  chain,
32643
32635
  exposeErrBody,
32644
32636
  partialFallback,
32645
- hasPostponed,
32646
- hasFallback,
32647
- htmlSize,
32648
- isDynamicRoute
32637
+ prerenderClassification
32649
32638
  }) {
32650
32639
  this.type = "Prerender";
32651
32640
  this.expiration = expiration;
32652
32641
  this.staleExpiration = staleExpiration;
32653
32642
  this.sourcePath = sourcePath;
32654
- assertOptionalBoolean(hasPostponed, "hasPostponed");
32655
- this.hasPostponed = hasPostponed;
32656
- assertOptionalBoolean(hasFallback, "hasFallback");
32657
- this.hasFallback = hasFallback;
32658
- assertOptionalBoolean(isDynamicRoute, "isDynamicRoute");
32659
- this.isDynamicRoute = isDynamicRoute;
32660
- if (htmlSize !== void 0 && (!Number.isInteger(htmlSize) || htmlSize < 0)) {
32661
- throw new Error(
32662
- "The `htmlSize` argument for `Prerender` must be a non-negative integer or undefined."
32663
- );
32664
- }
32665
- this.htmlSize = htmlSize;
32643
+ this.prerenderClassification = prerenderClassification;
32666
32644
  this.lambda = lambda;
32667
32645
  if (this.lambda) {
32668
32646
  this.lambda.operationType = this.lambda.operationType || "ISR";
@@ -35035,7 +35013,7 @@ function clearRelative(s) {
35035
35013
  return s.replace(/(\n|^)\.\//g, "$1");
35036
35014
  }
35037
35015
  async function get_ignore_filter_default(downloadPath, rootDirectory) {
35038
- const readFile4 = async (p) => {
35016
+ const readFile3 = async (p) => {
35039
35017
  try {
35040
35018
  return await import_fs_extra8.default.readFile(p, "utf8");
35041
35019
  } catch (error) {
@@ -35058,7 +35036,7 @@ async function get_ignore_filter_default(downloadPath, rootDirectory) {
35058
35036
  const ignoreContents = [];
35059
35037
  try {
35060
35038
  ignoreContents.push(
35061
- ...(await Promise.all([readFile4(vercelIgnorePath), readFile4(nowIgnorePath)])).filter(Boolean)
35039
+ ...(await Promise.all([readFile3(vercelIgnorePath), readFile3(nowIgnorePath)])).filter(Boolean)
35062
35040
  );
35063
35041
  } catch (error) {
35064
35042
  if (isCodedError(error) && error.code === "ENOTDIR") {
@@ -35334,37 +35312,9 @@ var ContainerImage = class {
35334
35312
  }
35335
35313
  };
35336
35314
 
35337
- // src/os.ts
35338
- var import_fs_extra9 = __toESM(require_lib());
35339
- var import_error_utils2 = __toESM(require_dist());
35340
- async function getOsRelease() {
35341
- try {
35342
- const data = await (0, import_fs_extra9.readFile)("/etc/os-release", "utf8");
35343
- return await parseOsRelease(data);
35344
- } catch (err) {
35345
- if ((0, import_error_utils2.isErrnoException)(err) && err.code === "ENOENT") {
35346
- return null;
35347
- }
35348
- throw err;
35349
- }
35350
- }
35351
- async function parseOsRelease(data) {
35352
- const obj = {};
35353
- for (const line of data.trim().split("\n")) {
35354
- const m = /(?<key>.*)="(?<value>.*)"/.exec(line);
35355
- if (!m?.groups) {
35356
- continue;
35357
- }
35358
- obj[m.groups.key] = m.groups.value;
35359
- }
35360
- return obj;
35361
- }
35315
+ // src/provided-runtime.ts
35362
35316
  async function getProvidedRuntime() {
35363
- const os = await getOsRelease();
35364
- if (!os) {
35365
- return "provided.al2023";
35366
- }
35367
- return os.PRETTY_NAME === "Amazon Linux 2" ? "provided.al2" : "provided.al2023";
35317
+ return "provided.al2023";
35368
35318
  }
35369
35319
 
35370
35320
  // src/should-serve.ts
@@ -36022,7 +35972,8 @@ async function generateProjectManifest({
36022
35972
  lockfilePath,
36023
35973
  lockfileVersion,
36024
35974
  framework,
36025
- serviceType
35975
+ serviceType,
35976
+ outputRuntime = "node"
36026
35977
  }) {
36027
35978
  try {
36028
35979
  const pkgJson = await readPackageJson(workPath);
@@ -36097,7 +36048,7 @@ async function generateProjectManifest({
36097
36048
  ...transitiveDeps.sort((a, b) => a.name.localeCompare(b.name))
36098
36049
  ]
36099
36050
  };
36100
- await writeProjectManifest(manifest, workPath, "node");
36051
+ await writeProjectManifest(manifest, workPath, outputRuntime);
36101
36052
  } catch (err) {
36102
36053
  debug(
36103
36054
  `generateProjectManifest: ${err instanceof Error ? err.message : String(err)}`
@@ -36221,7 +36172,8 @@ async function generateRubyProjectManifest({
36221
36172
  workPath,
36222
36173
  gemfileLockPath,
36223
36174
  framework,
36224
- serviceType
36175
+ serviceType,
36176
+ outputRuntime = "ruby"
36225
36177
  }) {
36226
36178
  try {
36227
36179
  if (!gemfileLockPath)
@@ -36275,7 +36227,7 @@ async function generateRubyProjectManifest({
36275
36227
  ...transitiveEntries.sort((a, b) => a.name.localeCompare(b.name))
36276
36228
  ]
36277
36229
  };
36278
- await writeProjectManifest(manifest, workPath, "ruby");
36230
+ await writeProjectManifest(manifest, workPath, outputRuntime);
36279
36231
  } catch {
36280
36232
  }
36281
36233
  }
@@ -37074,7 +37026,6 @@ async function validateBuildResult({
37074
37026
  allowInvalidRuntime = false,
37075
37027
  buildConfig,
37076
37028
  buildResponse,
37077
- osRelease,
37078
37029
  vercelBaseUrl
37079
37030
  }) {
37080
37031
  if (!("output" in buildResponse)) {
@@ -37090,32 +37041,30 @@ async function validateBuildResult({
37090
37041
  });
37091
37042
  }
37092
37043
  const buildOutputMap = getAndVerifyOutputLambdasOrEdgeFuncs(buildResponse);
37093
- if (osRelease?.VERSION === "2023") {
37094
- const invalidRuntimes = [];
37095
- for (const [name, entry] of Object.entries(buildOutputMap)) {
37096
- let lambda;
37097
- if (entry.type === "Prerender") {
37098
- lambda = entry.lambda;
37099
- } else if (entry.type === "Lambda") {
37100
- lambda = entry;
37101
- }
37102
- if (!lambda)
37103
- continue;
37104
- if (!isSupportedAl2023Runtime(lambda.runtime)) {
37105
- invalidRuntimes.push({ name, lambda });
37106
- }
37044
+ const invalidRuntimes = [];
37045
+ for (const [name, entry] of Object.entries(buildOutputMap)) {
37046
+ let lambda;
37047
+ if (entry.type === "Prerender") {
37048
+ lambda = entry.lambda;
37049
+ } else if (entry.type === "Lambda") {
37050
+ lambda = entry;
37051
+ }
37052
+ if (!lambda)
37053
+ continue;
37054
+ if (!isSupportedAl2023Runtime(lambda.runtime)) {
37055
+ invalidRuntimes.push({ name, lambda });
37107
37056
  }
37108
- if (invalidRuntimes.length > 0 && !allowInvalidRuntime) {
37109
- throw new NowBuildError({
37110
- code: "NOW_SANDBOX_WORKER_INVALID_RUNTIME",
37111
- message: `The following Serverless Functions contain an invalid "runtime":
37057
+ }
37058
+ if (invalidRuntimes.length > 0 && !allowInvalidRuntime) {
37059
+ throw new NowBuildError({
37060
+ code: "NOW_SANDBOX_WORKER_INVALID_RUNTIME",
37061
+ message: `The following Serverless Functions contain an invalid "runtime":
37112
37062
  ${invalidRuntimes.map(({ name, lambda }) => ` - ${name} (${lambda.runtime})`).join("\n")}`,
37113
- link: getVercelUrl(
37114
- "/docs/functions/runtimes#official-runtimes",
37115
- vercelBaseUrl
37116
- )
37117
- });
37118
- }
37063
+ link: getVercelUrl(
37064
+ "/docs/functions/runtimes#official-runtimes",
37065
+ vercelBaseUrl
37066
+ )
37067
+ });
37119
37068
  }
37120
37069
  const customFunctionConfiguration = getCustomFunctionConfigMaybe(buildConfig);
37121
37070
  if (customFunctionConfiguration?.runtime) {
@@ -37425,12 +37374,12 @@ async function fileFsRefCached(fsPath, cache) {
37425
37374
 
37426
37375
  // src/deserialize/create-functions-iterator.ts
37427
37376
  var import_path14 = require("path");
37428
- var import_fs_extra10 = __toESM(require_lib());
37377
+ var import_fs_extra9 = __toESM(require_lib());
37429
37378
  var SUFFIX = ".func";
37430
37379
  async function* createFunctionsIterator(dir, root = dir) {
37431
37380
  let paths;
37432
37381
  try {
37433
- paths = await (0, import_fs_extra10.readdir)(dir);
37382
+ paths = await (0, import_fs_extra9.readdir)(dir);
37434
37383
  } catch (err) {
37435
37384
  if (err.code !== "ENOENT" && err.code !== "ENOTDIR") {
37436
37385
  throw err;
@@ -37439,7 +37388,7 @@ async function* createFunctionsIterator(dir, root = dir) {
37439
37388
  }
37440
37389
  for (const path8 of paths) {
37441
37390
  const abs = (0, import_path14.join)(dir, path8);
37442
- const s = await (0, import_fs_extra10.stat)(abs);
37391
+ const s = await (0, import_fs_extra9.stat)(abs);
37443
37392
  if (s.isDirectory()) {
37444
37393
  if (path8.endsWith(SUFFIX)) {
37445
37394
  yield (0, import_path14.relative)(root, abs.substring(0, abs.length - SUFFIX.length));
@@ -37451,10 +37400,10 @@ async function* createFunctionsIterator(dir, root = dir) {
37451
37400
  }
37452
37401
 
37453
37402
  // src/deserialize/maybe-read-json.ts
37454
- var import_fs_extra11 = __toESM(require_lib());
37403
+ var import_fs_extra10 = __toESM(require_lib());
37455
37404
  async function maybeReadJSON(path8) {
37456
37405
  try {
37457
- return await (0, import_fs_extra11.readJSON)(path8);
37406
+ return await (0, import_fs_extra10.readJSON)(path8);
37458
37407
  } catch (err) {
37459
37408
  if (err.code !== "ENOENT")
37460
37409
  throw err;
@@ -37763,10 +37712,10 @@ async function deserializeLambda(files, config, repoRootPath, fileFsRefsCache, o
37763
37712
  }
37764
37713
 
37765
37714
  // src/collect-build-result/validate-regular-file.ts
37766
- var import_fs_extra12 = __toESM(require_lib());
37715
+ var import_fs_extra11 = __toESM(require_lib());
37767
37716
  async function validateRegularFile(file) {
37768
37717
  if ("fsPath" in file && typeof file.fsPath === "string") {
37769
- const stat2 = await (0, import_fs_extra12.lstat)(file.fsPath);
37718
+ const stat2 = await (0, import_fs_extra11.lstat)(file.fsPath);
37770
37719
  if (!stat2.isFile() && !stat2.isDirectory() && !stat2.isSymbolicLink()) {
37771
37720
  throw new NowBuildError({
37772
37721
  message: `Output file path is actually not a (regular) file: \`${file.fsPath}\``,
@@ -37946,7 +37895,6 @@ function getExtendedPayload({
37946
37895
  getNodeBinPath,
37947
37896
  getNodeBinPaths,
37948
37897
  getNodeVersion,
37949
- getOsRelease,
37950
37898
  getPackageJson,
37951
37899
  getPathForPackageManager,
37952
37900
  getPlatformEnv,
@@ -1,6 +1,6 @@
1
1
  import type { NodeVersion } from './types';
2
2
  type CliType = 'yarn' | 'npm' | 'pnpm' | 'bun' | 'vlt';
3
- export declare function generateProjectManifest({ workPath, nodeVersion, cliType, lockfilePath, lockfileVersion, framework, serviceType, }: {
3
+ export declare function generateProjectManifest({ workPath, nodeVersion, cliType, lockfilePath, lockfileVersion, framework, serviceType, outputRuntime, }: {
4
4
  workPath: string;
5
5
  nodeVersion: NodeVersion;
6
6
  cliType: CliType;
@@ -8,5 +8,6 @@ export declare function generateProjectManifest({ workPath, nodeVersion, cliType
8
8
  lockfileVersion: number | undefined;
9
9
  framework?: string;
10
10
  serviceType?: string;
11
+ outputRuntime?: string;
11
12
  }): Promise<void>;
12
13
  export {};
@@ -387,7 +387,8 @@ async function generateProjectManifest({
387
387
  lockfilePath,
388
388
  lockfileVersion,
389
389
  framework,
390
- serviceType
390
+ serviceType,
391
+ outputRuntime = "node"
391
392
  }) {
392
393
  try {
393
394
  const pkgJson = await readPackageJson(workPath);
@@ -462,7 +463,7 @@ async function generateProjectManifest({
462
463
  ...transitiveDeps.sort((a, b) => a.name.localeCompare(b.name))
463
464
  ]
464
465
  };
465
- await (0, import_package_manifest.writeProjectManifest)(manifest, workPath, "node");
466
+ await (0, import_package_manifest.writeProjectManifest)(manifest, workPath, outputRuntime);
466
467
  } catch (err) {
467
468
  (0, import_debug.default)(
468
469
  `generateProjectManifest: ${err instanceof Error ? err.message : String(err)}`
@@ -1,5 +1,19 @@
1
1
  import type { File, HasField, Chain } from './types';
2
2
  import { Lambda } from './lambda';
3
+ /**
4
+ * The framework's own description of what it prerendered, mirroring the
5
+ * Next.js prerender taxonomy rather than re-deriving it from build artifacts.
6
+ */
7
+ export interface PrerenderClassification {
8
+ /** What kind of entry this is within its route group. */
9
+ routeType: 'route' | 'page' | 'shell' | 'fallback';
10
+ /** How much of the response the prerender contains. */
11
+ response: 'empty' | 'initial' | 'complete';
12
+ /** What has to happen at request time to finish the response. */
13
+ compute: 'blocking' | 'resuming' | 'static';
14
+ /** Byte size of the prerendered HTML shell, when the entry has one. */
15
+ htmlSize?: number;
16
+ }
3
17
  interface PrerenderOptions {
4
18
  expiration: number | false;
5
19
  staleExpiration?: number;
@@ -18,10 +32,7 @@ interface PrerenderOptions {
18
32
  chain?: Chain;
19
33
  exposeErrBody?: boolean;
20
34
  partialFallback?: boolean;
21
- hasPostponed?: boolean;
22
- hasFallback?: boolean;
23
- htmlSize?: number;
24
- isDynamicRoute?: boolean;
35
+ prerenderClassification?: PrerenderClassification;
25
36
  }
26
37
  export declare class Prerender {
27
38
  type: 'Prerender';
@@ -52,31 +63,11 @@ export declare class Prerender {
52
63
  exposeErrBody?: boolean;
53
64
  partialFallback?: boolean;
54
65
  /**
55
- * Set to `true` when the route's `.meta` postponed state is present (React
56
- * suspended during build prerender). `false` when the framework prerendered
57
- * a Prerender route without postponing. `undefined` when the framework did
58
- * not provide the signal.
59
- */
60
- hasPostponed?: boolean;
61
- /**
62
- * `true` when the route's dynamic template had a static fallback page (the
63
- * prerender-manifest `fallback` was a string). `false` for blocking/omitted
64
- * dynamic templates (manifest `fallback` was `null`/`false`). `undefined` for
65
- * concrete prerenders, where the notion of a fallback doesn't apply.
66
- */
67
- hasFallback?: boolean;
68
- /**
69
- * Byte size on disk of the route's prerendered `.html` shell. `0` for an
70
- * empty shell (PPR template that postponed everything). `undefined` when
71
- * there's no `.html` on disk (pages router, route handlers, edge).
72
- */
73
- htmlSize?: number;
74
- /**
75
- * `true` when this entry came from a dynamic route template (the
76
- * prerender-manifest `dynamicRoutes` section: fallback, blocking, or omitted)
77
- * rather than a concrete prerender.
66
+ * The framework's classification of this prerender. `undefined` when the
67
+ * framework did not provide one, which is legitimate: not-found routes and
68
+ * Pages Router `fallback: false` templates have no classification.
78
69
  */
79
- isDynamicRoute?: boolean;
80
- constructor({ expiration, staleExpiration, lambda, fallback, group, bypassToken, allowQuery, allowHeader, initialHeaders, initialStatus, passQuery, sourcePath, experimentalBypassFor, experimentalStreamingLambdaPath, chain, exposeErrBody, partialFallback, hasPostponed, hasFallback, htmlSize, isDynamicRoute, }: PrerenderOptions);
70
+ prerenderClassification?: PrerenderClassification;
71
+ constructor({ expiration, staleExpiration, lambda, fallback, group, bypassToken, allowQuery, allowHeader, initialHeaders, initialStatus, passQuery, sourcePath, experimentalBypassFor, experimentalStreamingLambdaPath, chain, exposeErrBody, partialFallback, prerenderClassification, }: PrerenderOptions);
81
72
  }
82
73
  export {};
package/dist/prerender.js CHANGED
@@ -21,13 +21,6 @@ __export(prerender_exports, {
21
21
  Prerender: () => Prerender
22
22
  });
23
23
  module.exports = __toCommonJS(prerender_exports);
24
- function assertOptionalBoolean(value, name) {
25
- if (value !== void 0 && typeof value !== "boolean") {
26
- throw new Error(
27
- `The \`${name}\` argument for \`Prerender\` must be a boolean or undefined.`
28
- );
29
- }
30
- }
31
24
  class Prerender {
32
25
  constructor({
33
26
  expiration,
@@ -47,27 +40,13 @@ class Prerender {
47
40
  chain,
48
41
  exposeErrBody,
49
42
  partialFallback,
50
- hasPostponed,
51
- hasFallback,
52
- htmlSize,
53
- isDynamicRoute
43
+ prerenderClassification
54
44
  }) {
55
45
  this.type = "Prerender";
56
46
  this.expiration = expiration;
57
47
  this.staleExpiration = staleExpiration;
58
48
  this.sourcePath = sourcePath;
59
- assertOptionalBoolean(hasPostponed, "hasPostponed");
60
- this.hasPostponed = hasPostponed;
61
- assertOptionalBoolean(hasFallback, "hasFallback");
62
- this.hasFallback = hasFallback;
63
- assertOptionalBoolean(isDynamicRoute, "isDynamicRoute");
64
- this.isDynamicRoute = isDynamicRoute;
65
- if (htmlSize !== void 0 && (!Number.isInteger(htmlSize) || htmlSize < 0)) {
66
- throw new Error(
67
- "The `htmlSize` argument for `Prerender` must be a non-negative integer or undefined."
68
- );
69
- }
70
- this.htmlSize = htmlSize;
49
+ this.prerenderClassification = prerenderClassification;
71
50
  this.lambda = lambda;
72
51
  if (this.lambda) {
73
52
  this.lambda.operationType = this.lambda.operationType || "ISR";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The Lambda runtime that custom runtimes must target.
3
+ *
4
+ * Builds run on Amazon Linux 2023, so this is a constant. It is deliberately
5
+ * not derived from the build host's `/etc/os-release`: `vercel build` also runs
6
+ * on developer machines and in CI, and the emitted runtime has to match the
7
+ * deploy target rather than wherever the build happened to run.
8
+ *
9
+ * This stays a function so that custom runtimes pick up any future base image
10
+ * migration without having to change their own code.
11
+ */
12
+ export declare function getProvidedRuntime(): Promise<'provided.al2023'>;
@@ -0,0 +1,30 @@
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 provided_runtime_exports = {};
20
+ __export(provided_runtime_exports, {
21
+ getProvidedRuntime: () => getProvidedRuntime
22
+ });
23
+ module.exports = __toCommonJS(provided_runtime_exports);
24
+ async function getProvidedRuntime() {
25
+ return "provided.al2023";
26
+ }
27
+ // Annotate the CommonJS export names for ESM import in node:
28
+ 0 && (module.exports = {
29
+ getProvidedRuntime
30
+ });
@@ -12,10 +12,11 @@ export declare function parseGemfileLock(content: string): {
12
12
  gems: Map<string, GemEntry>;
13
13
  directGems: Map<string, string | undefined>;
14
14
  };
15
- export declare function generateRubyProjectManifest({ workPath, gemfileLockPath, framework, serviceType, }: {
15
+ export declare function generateRubyProjectManifest({ workPath, gemfileLockPath, framework, serviceType, outputRuntime, }: {
16
16
  workPath: string;
17
17
  gemfileLockPath: string | undefined;
18
18
  framework?: string | null;
19
19
  serviceType?: string | null;
20
+ outputRuntime?: string;
20
21
  }): Promise<void>;
21
22
  export {};
@@ -154,7 +154,8 @@ async function generateRubyProjectManifest({
154
154
  workPath,
155
155
  gemfileLockPath,
156
156
  framework,
157
- serviceType
157
+ serviceType,
158
+ outputRuntime = "ruby"
158
159
  }) {
159
160
  try {
160
161
  if (!gemfileLockPath)
@@ -208,7 +209,7 @@ async function generateRubyProjectManifest({
208
209
  ...transitiveEntries.sort((a, b) => a.name.localeCompare(b.name))
209
210
  ]
210
211
  };
211
- await (0, import_package_manifest.writeProjectManifest)(manifest, workPath, "ruby");
212
+ await (0, import_package_manifest.writeProjectManifest)(manifest, workPath, outputRuntime);
212
213
  } catch {
213
214
  }
214
215
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "13.36.3",
3
+ "version": "14.0.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -13,7 +13,7 @@
13
13
  "dependencies": {
14
14
  "cjs-module-lexer": "1.2.3",
15
15
  "es-module-lexer": "1.5.0",
16
- "@vercel/python-analysis": "0.12.0"
16
+ "@vercel/python-analysis": "0.13.1"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/async-retry": "^1.2.1",
@@ -53,8 +53,8 @@
53
53
  "vitest": "2.0.1",
54
54
  "typescript": "4.9.5",
55
55
  "yazl": "2.5.1",
56
- "@vercel/routing-utils": "6.4.0",
57
- "@vercel/error-utils": "2.2.0"
56
+ "@vercel/routing-utils": "6.4.1",
57
+ "@vercel/error-utils": "2.2.1"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "node build.mjs",
package/dist/os.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare function getOsRelease(): Promise<Record<string, string> | null>;
2
- export declare function parseOsRelease(data: string): Promise<Record<string, string>>;
3
- export declare function getProvidedRuntime(): Promise<"provided.al2023" | "provided.al2">;
package/dist/os.js DELETED
@@ -1,62 +0,0 @@
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 os_exports = {};
20
- __export(os_exports, {
21
- getOsRelease: () => getOsRelease,
22
- getProvidedRuntime: () => getProvidedRuntime,
23
- parseOsRelease: () => parseOsRelease
24
- });
25
- module.exports = __toCommonJS(os_exports);
26
- var import_fs_extra = require("fs-extra");
27
- var import_error_utils = require("@vercel/error-utils");
28
- async function getOsRelease() {
29
- try {
30
- const data = await (0, import_fs_extra.readFile)("/etc/os-release", "utf8");
31
- return await parseOsRelease(data);
32
- } catch (err) {
33
- if ((0, import_error_utils.isErrnoException)(err) && err.code === "ENOENT") {
34
- return null;
35
- }
36
- throw err;
37
- }
38
- }
39
- async function parseOsRelease(data) {
40
- const obj = {};
41
- for (const line of data.trim().split("\n")) {
42
- const m = /(?<key>.*)="(?<value>.*)"/.exec(line);
43
- if (!m?.groups) {
44
- continue;
45
- }
46
- obj[m.groups.key] = m.groups.value;
47
- }
48
- return obj;
49
- }
50
- async function getProvidedRuntime() {
51
- const os = await getOsRelease();
52
- if (!os) {
53
- return "provided.al2023";
54
- }
55
- return os.PRETTY_NAME === "Amazon Linux 2" ? "provided.al2" : "provided.al2023";
56
- }
57
- // Annotate the CommonJS export names for ESM import in node:
58
- 0 && (module.exports = {
59
- getOsRelease,
60
- getProvidedRuntime,
61
- parseOsRelease
62
- });