Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@vercel/build-utils

Package Overview
Dependencies
Maintainers
3
Versions
430
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vercel/build-utils - npm Package Compare versions

Comparing version
13.19.1
to
13.20.0
+57
dist/deserialize/deserialize-build-output-types.d.ts
import type FileFsRef from '../file-fs-ref';
import type { Lambda } from '../lambda';
import type { Prerender } from '../prerender';
import type { BuildResultV2Typical, Files } from '../types';
import type { SerializedEdgeFunction, SerializedLambda, SerializedNodejsLambda, SerializedPrerender } from './serialized-types';
export interface DeserializeBuildOutputPathOverride {
contentType?: string;
mode?: number;
path?: string;
}
export interface DeserializeBuildOutputConfig<TFlags = unknown> {
version?: 3;
wildcard?: BuildResultV2Typical['wildcard'];
images?: BuildResultV2Typical['images'];
routes?: BuildResultV2Typical['routes'];
overrides?: Record<string, DeserializeBuildOutputPathOverride>;
framework?: BuildResultV2Typical['framework'];
crons?: BuildResultV2Typical['crons'];
flags?: TFlags;
deploymentId?: string;
}
export type DeserializeBuildOutputResult<TFlags = unknown, TMeta = unknown> = Omit<BuildResultV2Typical, 'flags'> & {
flags?: TFlags;
meta?: TMeta;
};
export type DeserializeBuildOutputLambdaOptions = {
forceNodejsStreaming?: boolean;
useOnlyStreamingLambda?: boolean;
};
export type GroupLambdasOptions = {
force: 'all' | undefined;
maxBundleSizeMb: number | undefined;
debug: boolean | undefined;
};
export type DeserializeBuildOutputLambda<TLambda extends Lambda> = (files: Files, config: SerializedLambda | SerializedNodejsLambda, repoRootPath: string, fileFsRefsCache: Map<string, FileFsRef>, options?: DeserializeBuildOutputLambdaOptions) => Promise<TLambda>;
export type GroupLambdas<TLambda extends Lambda> = (lambdas: Record<string, TLambda>, options: GroupLambdasOptions) => Promise<Record<string, TLambda>>;
export type InspectSerializedLambda = (path: string, config: SerializedLambda | SerializedNodejsLambda, repoRootPath: string, hasServerActions: boolean) => Promise<boolean>;
export interface DeserializeBuildOutputOptions<TResult extends DeserializeBuildOutputResult = DeserializeBuildOutputResult, TLambda extends Lambda = Lambda> {
outputDir: string;
repoRootPath: string;
maxBundleSizeMb?: number;
debugGroupLambdas?: boolean;
useOnlyStreamingLambda?: boolean;
forceNodejsStreaming?: boolean;
deserializeLambda: DeserializeBuildOutputLambda<TLambda>;
groupLambdas: GroupLambdas<TLambda>;
inspectSerializedLambda?: InspectSerializedLambda;
warn?: (message: string) => void;
includeDeploymentId?: boolean;
getMeta?: (hasServerActions: boolean) => TResult extends {
meta?: infer TMeta;
} ? TMeta : never;
}
export type DeserializeBuildOutputFiles = BuildResultV2Typical['output'];
export type DeserializeBuildOutputPrerenderFallback = Prerender['fallback'];
export type DeserializeBuildOutputSerializedConfig = SerializedEdgeFunction | SerializedLambda | SerializedNodejsLambda;
export type DeserializeBuildOutputSerializedPrerender = SerializedPrerender;
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var deserialize_build_output_types_exports = {};
module.exports = __toCommonJS(deserialize_build_output_types_exports);
import type { Lambda } from '../lambda';
import type { DeserializeBuildOutputConfig, DeserializeBuildOutputOptions, DeserializeBuildOutputResult } from './deserialize-build-output-types';
export declare function validateDeploymentId(deploymentId?: string): void;
export declare function deserializeBuildOutput<TConfig extends DeserializeBuildOutputConfig = DeserializeBuildOutputConfig, TResult extends DeserializeBuildOutputResult = DeserializeBuildOutputResult, TLambda extends Lambda = Lambda>(options: DeserializeBuildOutputOptions<TResult, TLambda>): Promise<TResult>;
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var deserialize_build_output_exports = {};
__export(deserialize_build_output_exports, {
deserializeBuildOutput: () => deserializeBuildOutput,
validateDeploymentId: () => validateDeploymentId
});
module.exports = __toCommonJS(deserialize_build_output_exports);
var fs = __toESM(require("fs-extra"));
var import_path = require("path");
var import_errors = require("../errors");
var import_file_fs_ref = __toESM(require("../file-fs-ref"));
var import_glob = __toESM(require("../fs/glob"));
var import_prerender = require("../prerender");
var import_create_functions_iterator = require("./create-functions-iterator");
var import_deserialize_edge_function = require("./deserialize-edge-function");
var import_maybe_read_json = require("./maybe-read-json");
var import_validate_framework_version = require("./validate-framework-version");
const MAX_DEPLOYMENT_ID_LENGTH = 32;
const VALID_DEPLOYMENT_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
function validateDeploymentId(deploymentId) {
if (deploymentId && deploymentId.length > MAX_DEPLOYMENT_ID_LENGTH) {
throw new import_errors.NowBuildError({
message: `The configured deploymentId "${deploymentId}" exceeds the maximum length of ${MAX_DEPLOYMENT_ID_LENGTH} characters. Please use a shorter deploymentId.`,
code: "VC_BUILD_INVALID_DEPLOYMENT_ID_LENGTH"
});
}
if (deploymentId && !VALID_DEPLOYMENT_ID_PATTERN.test(deploymentId)) {
throw new import_errors.NowBuildError({
message: `The configured deploymentId "${deploymentId}" contains invalid characters. Only alphanumeric characters (a-z, A-Z, 0-9), hyphens (-), and underscores (_) are allowed.`,
code: "VC_BUILD_INVALID_DEPLOYMENT_ID_CHARACTERS"
});
}
}
function applyOutputOverrides(output, overrides, warn) {
for (const [name, override] of Object.entries(overrides || {})) {
const entry = output[name];
if (entry) {
if (override.contentType) {
entry.contentType = override.contentType;
}
if (override.mode) {
entry.mode = override.mode;
}
if (override.path) {
output[override.path] = entry;
delete output[name];
}
} else {
warn?.(
`Warning: Override path "${name}" was not detected as an output path`
);
}
}
}
async function deserializePrerenderFallback(prerenderConfigPath, fallbackConfig) {
if (typeof fallbackConfig === "string") {
return import_file_fs_ref.default.fromFsPath({
fsPath: (0, import_path.join)((0, import_path.dirname)(prerenderConfigPath), fallbackConfig)
});
}
if (fallbackConfig) {
return import_file_fs_ref.default.fromFsPath({
mode: fallbackConfig.mode,
contentType: fallbackConfig.contentType,
fsPath: (0, import_path.join)((0, import_path.dirname)(prerenderConfigPath), fallbackConfig.fsPath)
});
}
return null;
}
function applyFunctionSymlinks(output, prerenders, functionSymlinks) {
for (const [path, target] of functionSymlinks.entries()) {
const targetOutput = prerenders.get(target) || output[target];
let targetFunction;
if (targetOutput?.type === "Prerender") {
targetFunction = targetOutput.lambda;
} else if (targetOutput?.type === "Lambda" || targetOutput?.type === "EdgeFunction") {
targetFunction = targetOutput;
}
if (!targetFunction) {
throw new Error(
`Could not find target "${target}" Lambda or EdgeFunction for path "${path}"`
);
}
const srcOutput = prerenders.get(path);
if (srcOutput) {
if (srcOutput.type === "Prerender") {
if (targetFunction.type === "Lambda") {
srcOutput.lambda = targetFunction;
} else {
throw new Error(
`Unexpected function type "${targetFunction.type}" at path "${path}"`
);
}
} else {
throw new Error(
`Unexpected output type "${srcOutput.type}" at path "${path}"`
);
}
} else {
output[path] = targetFunction;
}
}
}
function appendSortedPrerenders(output, prerenders) {
const sortedPrerenders = Array.from(prerenders.entries()).sort((a, b) => {
return (a[1].group ?? 0) - (b[1].group ?? 0);
}).reduce((o, [path, prerender]) => {
o[path] = prerender;
return o;
}, {});
Object.assign(output, sortedPrerenders);
}
function getBundleableLambdas(output) {
const bundleableLambdas = {};
for (const [outputName, curOutput] of Object.entries(output)) {
if (curOutput.type === "Lambda" && curOutput.experimentalAllowBundling) {
bundleableLambdas[outputName] = curOutput;
} else if (curOutput.type === "Prerender" && curOutput.lambda && curOutput.lambda.experimentalAllowBundling) {
bundleableLambdas[outputName] = curOutput.lambda;
}
}
return bundleableLambdas;
}
function applyGroupedLambdas(output, groupedLambdas) {
for (const outputName of Object.keys(groupedLambdas)) {
const groupedLambda = groupedLambdas[outputName];
const origOutput = output[outputName];
if (origOutput.type === "Lambda") {
output[outputName] = groupedLambda;
} else if (origOutput.type === "Prerender" && origOutput.lambda) {
origOutput.lambda = groupedLambda;
}
}
}
async function deserializeBuildOutput(options) {
const {
outputDir,
repoRootPath,
maxBundleSizeMb,
debugGroupLambdas,
useOnlyStreamingLambda,
forceNodejsStreaming,
deserializeLambda,
groupLambdas,
inspectSerializedLambda,
warn,
includeDeploymentId,
getMeta
} = options;
let hasServerActions = false;
const configPath = (0, import_path.join)(outputDir, "config.json");
const config = await (0, import_maybe_read_json.maybeReadJSON)(configPath);
if (!config) {
throw new Error(`Config file was not found at "${configPath}"`);
}
if (config.version !== 3) {
throw new Error(
`Expected \`version: 3\` in "${configPath}" file (received \`${config.version}\`)`
);
}
validateDeploymentId(config.deploymentId);
const flags = await (0, import_maybe_read_json.maybeReadJSON)(
(0, import_path.join)(outputDir, "flags.json")
);
const staticDir = (0, import_path.join)(outputDir, "static");
const output = await (0, import_glob.default)("**", {
cwd: staticDir,
follow: true
});
applyOutputOverrides(output, config.overrides, warn);
const fileFsRefsCache = /* @__PURE__ */ new Map();
const prerenders = /* @__PURE__ */ new Map();
const functionsDir = (0, import_path.join)(outputDir, "functions");
const functionSymlinks = /* @__PURE__ */ new Map();
for await (const path of (0, import_create_functions_iterator.createFunctionsIterator)(functionsDir)) {
let lambda = void 0;
const fnDir = (0, import_path.join)(functionsDir, `${path}.func`);
try {
const link = await fs.readlink(fnDir);
const target = (0, import_path.join)((0, import_path.dirname)(path), link).slice(0, -5);
functionSymlinks.set(path, target);
} catch (err) {
if (err.code !== "EINVAL")
throw err;
const funcConfigPath = (0, import_path.join)(fnDir, ".vc-config.json");
const funcConfig = await (0, import_maybe_read_json.maybeReadJSON)(
funcConfigPath
);
if (!funcConfig) {
throw new Error(`Could not load function config: "${funcConfigPath}"`);
}
const files = await (0, import_glob.default)("**", { cwd: fnDir, includeDirectories: true });
delete files[".vc-config.json"];
if (funcConfig.type === "EdgeFunction" || funcConfig.runtime === "edge") {
output[path] = await (0, import_deserialize_edge_function.deserializeEdgeFunction)(
files,
funcConfig,
repoRootPath,
fileFsRefsCache
);
continue;
}
lambda = await deserializeLambda(
files,
funcConfig,
repoRootPath,
fileFsRefsCache,
{ useOnlyStreamingLambda, forceNodejsStreaming }
);
if (inspectSerializedLambda) {
hasServerActions = await inspectSerializedLambda(
path,
funcConfig,
repoRootPath,
hasServerActions
);
}
}
const prerenderConfigPath = (0, import_path.join)(
functionsDir,
`${path}.prerender-config.json`
);
const prerenderConfig = await (0, import_maybe_read_json.maybeReadJSON)(
prerenderConfigPath
);
if (prerenderConfig) {
const fallback = await deserializePrerenderFallback(
prerenderConfigPath,
prerenderConfig.fallback
);
const prerender = new import_prerender.Prerender({
...prerenderConfig,
lambda,
fallback
});
prerenders.set(path, prerender);
} else if (lambda) {
output[path] = lambda;
}
}
applyFunctionSymlinks(output, prerenders, functionSymlinks);
appendSortedPrerenders(output, prerenders);
const groupedLambdas = await groupLambdas(
getBundleableLambdas(output),
{
force: void 0,
maxBundleSizeMb,
debug: debugGroupLambdas
}
);
applyGroupedLambdas(output, groupedLambdas);
const framework = (0, import_validate_framework_version.validateFrameworkVersion)(config?.framework?.version);
const meta = getMeta?.(hasServerActions);
return {
wildcard: config.wildcard,
images: config.images,
crons: config.crons,
flags: flags ? flags : config.flags,
routes: config.routes,
output,
framework,
...includeDeploymentId ? { deploymentId: config.deploymentId } : {},
...meta !== void 0 ? { meta } : {}
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
deserializeBuildOutput,
validateDeploymentId
});
+10
-0
# @vercel/build-utils
## 13.20.0
### Minor Changes
- Add framework to package manifest for python and backends builders. ([#16072](https://github.com/vercel/vercel/pull/16072))
### Patch Changes
- Add shared build output deserialization helpers for existing callers. ([#16072](https://github.com/vercel/vercel/pull/16072))
## 13.19.1

@@ -4,0 +14,0 @@

+2
-0

@@ -60,2 +60,4 @@ import FileBlob from './file-blob';

export { maybeReadJSON } from './deserialize/maybe-read-json';
export { deserializeBuildOutput, validateDeploymentId, } from './deserialize/deserialize-build-output';
export type { DeserializeBuildOutputConfig, DeserializeBuildOutputResult, DeserializeBuildOutputPathOverride, DeserializeBuildOutputOptions, DeserializeBuildOutputLambdaOptions, GroupLambdasOptions, DeserializeBuildOutputSerializedConfig, DeserializeBuildOutputSerializedPrerender, } from './deserialize/deserialize-build-output-types';
export { deserializeLambda, type DeserializeLambdaOptions, } from './deserialize/deserialize-lambda';

@@ -62,0 +64,0 @@ export { deserializeEdgeFunction } from './deserialize/deserialize-edge-function';

@@ -14,2 +14,3 @@ import type { Diagnostics } from './types';

runtime: string;
framework?: string;
runtimeVersion?: {

@@ -16,0 +17,0 @@ requested?: string;

@@ -143,2 +143,6 @@ export declare const functionsSchema: {

};
readonly framework: {
readonly type: "string";
readonly description: "Detected framework slug, e.g. \"fastapi\", \"flask\", \"hono\".";
};
readonly runtimeVersion: {

@@ -145,0 +149,0 @@ readonly type: "object";

@@ -190,2 +190,6 @@ "use strict";

},
framework: {
type: "string",
description: 'Detected framework slug, e.g. "fastapi", "flask", "hono".'
},
runtimeVersion: {

@@ -192,0 +196,0 @@ type: "object",

+1
-1
{
"name": "@vercel/build-utils",
"version": "13.19.1",
"version": "13.20.0",
"license": "Apache-2.0",

@@ -5,0 +5,0 @@ "main": "./dist/index.js",

Sorry, the diff of this file is too big to display