@vercel/build-utils 13.12.1 → 13.13.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 +12 -0
- package/dist/collect-uncompressed-size.d.ts +6 -0
- package/dist/collect-uncompressed-size.js +59 -0
- package/dist/finalize-lambda.d.ts +81 -0
- package/dist/finalize-lambda.js +118 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +322 -16
- package/dist/process-serverless/get-lambda-environment.d.ts +3 -2
- package/dist/process-serverless/get-lambda-preload-scripts.d.ts +3 -2
- package/dist/validate-lambda-size.d.ts +46 -0
- package/dist/validate-lambda-size.js +117 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @vercel/build-utils
|
|
2
2
|
|
|
3
|
+
## 13.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Extend `finalizeLambda` with pluggable ZIP strategy (`createZip`), pre-digest validation hook (`validateZip`), and optional trace tags. Widen `getLambdaEnvironment` buffer param to `{ byteLength: number }`. ([#15856](https://github.com/vercel/vercel/pull/15856))
|
|
8
|
+
|
|
9
|
+
## 13.12.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Extract finalize/validate function utils for build-utils ([#15776](https://github.com/vercel/vercel/pull/15776))
|
|
14
|
+
|
|
3
15
|
## 13.12.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Files } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Collects the total uncompressed size of a set of Lambda files.
|
|
4
|
+
* Handles both FileBlob (in-memory) and FileFsRef (on-disk) file types.
|
|
5
|
+
*/
|
|
6
|
+
export declare const collectUncompressedSize: (files: Files, ignoreFn?: ((fileKey: string) => boolean) | undefined) => Promise<number>;
|
|
@@ -0,0 +1,59 @@
|
|
|
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 collect_uncompressed_size_exports = {};
|
|
20
|
+
__export(collect_uncompressed_size_exports, {
|
|
21
|
+
collectUncompressedSize: () => collectUncompressedSize
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(collect_uncompressed_size_exports);
|
|
24
|
+
var import_promises = require("fs/promises");
|
|
25
|
+
const fileSizeCache = /* @__PURE__ */ new Map();
|
|
26
|
+
const getFileSize = (path) => {
|
|
27
|
+
if (!path)
|
|
28
|
+
return Promise.resolve(0);
|
|
29
|
+
const cached = fileSizeCache.get(path);
|
|
30
|
+
if (cached) {
|
|
31
|
+
return cached;
|
|
32
|
+
}
|
|
33
|
+
const promise = (0, import_promises.lstat)(path).then((stats) => stats.size);
|
|
34
|
+
fileSizeCache.set(path, promise);
|
|
35
|
+
return promise;
|
|
36
|
+
};
|
|
37
|
+
const collectUncompressedSize = async (files, ignoreFn) => {
|
|
38
|
+
let size = 0;
|
|
39
|
+
await Promise.all(
|
|
40
|
+
Object.keys(files).map(async (fileKey) => {
|
|
41
|
+
if (ignoreFn?.(fileKey)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const file = files[fileKey];
|
|
45
|
+
if (file.type === "FileBlob") {
|
|
46
|
+
size += file.data.length;
|
|
47
|
+
} else if (file.type === "FileFsRef") {
|
|
48
|
+
const fsRef = file;
|
|
49
|
+
const curSize = fsRef.size ?? await getFileSize(fsRef.fsPath);
|
|
50
|
+
size += curSize;
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
return size;
|
|
55
|
+
};
|
|
56
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
57
|
+
0 && (module.exports = {
|
|
58
|
+
collectUncompressedSize
|
|
59
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Lambda } from './lambda';
|
|
3
|
+
import type { NodejsLambda } from './nodejs-lambda';
|
|
4
|
+
import type { BytecodeCachingOptions } from './process-serverless/get-lambda-preload-scripts';
|
|
5
|
+
import type { SupportsStreamingResult } from './process-serverless/get-lambda-supports-streaming';
|
|
6
|
+
/**
|
|
7
|
+
* Optional wrapper around async work, allowing callers to inject tracing
|
|
8
|
+
* (e.g. dd-trace spans) without coupling the shared code to a tracer.
|
|
9
|
+
*/
|
|
10
|
+
export type TraceFn = <T>(name: string, fn: () => Promise<T>, tags?: Record<string, string>) => Promise<T>;
|
|
11
|
+
/**
|
|
12
|
+
* Result of a custom ZIP creation strategy.
|
|
13
|
+
*/
|
|
14
|
+
export interface CreateZipResult {
|
|
15
|
+
/** The zip as a Buffer (in-memory), or null for disk-based paths. */
|
|
16
|
+
buffer: Buffer | null;
|
|
17
|
+
/** Path to the zip file on disk, or undefined for in-memory. */
|
|
18
|
+
zipPath?: string;
|
|
19
|
+
/** SHA-256 hex digest of the zip contents. */
|
|
20
|
+
digest: string;
|
|
21
|
+
/** Compressed size in bytes. */
|
|
22
|
+
size: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Custom ZIP creation strategy. When provided, replaces the default
|
|
26
|
+
* in-memory `lambda.createZip()` + `sha256()` path. This allows callers
|
|
27
|
+
* to stream large zips to disk instead.
|
|
28
|
+
*/
|
|
29
|
+
export type CreateZipFn = (lambda: Lambda | NodejsLambda) => Promise<CreateZipResult>;
|
|
30
|
+
export interface FinalizeLambdaParams {
|
|
31
|
+
lambda: Lambda | NodejsLambda;
|
|
32
|
+
encryptedEnvFilename?: string;
|
|
33
|
+
encryptedEnvContent?: string;
|
|
34
|
+
bytecodeCachingOptions: BytecodeCachingOptions;
|
|
35
|
+
forceStreamingRuntime: boolean;
|
|
36
|
+
/** When true, collect the uncompressed size of lambda files before zipping. */
|
|
37
|
+
enableUncompressedLambdaSizeCheck?: boolean;
|
|
38
|
+
/** Optional tracing wrapper for `collectUncompressedSize` and `createZip`. */
|
|
39
|
+
trace?: TraceFn;
|
|
40
|
+
/** Custom ZIP creation strategy. Defaults to in-memory lambda.createZip(). */
|
|
41
|
+
createZip?: CreateZipFn;
|
|
42
|
+
/**
|
|
43
|
+
* Called after ZIP creation but before digest/environment/streaming.
|
|
44
|
+
* Throw to abort (e.g. size validation). For the default in-memory path,
|
|
45
|
+
* this runs before sha256.
|
|
46
|
+
*/
|
|
47
|
+
validateZip?: (zip: {
|
|
48
|
+
buffer: Buffer | null;
|
|
49
|
+
zipPath?: string;
|
|
50
|
+
size: number;
|
|
51
|
+
}) => void;
|
|
52
|
+
}
|
|
53
|
+
export interface FinalizeLambdaResult {
|
|
54
|
+
/** The zip as a Buffer, or null when a custom createZip returns a disk path. */
|
|
55
|
+
buffer: Buffer | null;
|
|
56
|
+
/** Path to zip on disk (set by custom createZip), undefined for in-memory. */
|
|
57
|
+
zipPath?: string;
|
|
58
|
+
/** SHA-256 hex digest. */
|
|
59
|
+
digest: string;
|
|
60
|
+
/** Compressed size in bytes. */
|
|
61
|
+
size: number;
|
|
62
|
+
uncompressedBytes: number;
|
|
63
|
+
/** Non-fatal streaming detection error, if any. Caller decides how to log. */
|
|
64
|
+
streamingError?: SupportsStreamingResult['error'];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Core Lambda finalization logic shared between BYOF and build-container.
|
|
68
|
+
*
|
|
69
|
+
* This function:
|
|
70
|
+
* 1. Injects encrypted env file into lambda.files when provided
|
|
71
|
+
* 2. Collects uncompressed size when enabled
|
|
72
|
+
* 3. Creates the ZIP (in-memory or via custom strategy)
|
|
73
|
+
* 4. Runs optional validateZip hook (e.g. size check)
|
|
74
|
+
* 5. Computes SHA-256 digest (default path only; custom path provides its own)
|
|
75
|
+
* 6. Merges environment variables (bytecode caching, helpers, etc.)
|
|
76
|
+
* 7. Detects streaming support
|
|
77
|
+
*
|
|
78
|
+
* Note: This function mutates the `lambda` (files, environment,
|
|
79
|
+
* supportsResponseStreaming).
|
|
80
|
+
*/
|
|
81
|
+
export declare function finalizeLambda(params: FinalizeLambdaParams): Promise<FinalizeLambdaResult>;
|
|
@@ -0,0 +1,118 @@
|
|
|
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 finalize_lambda_exports = {};
|
|
20
|
+
__export(finalize_lambda_exports, {
|
|
21
|
+
finalizeLambda: () => finalizeLambda
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(finalize_lambda_exports);
|
|
24
|
+
var import_get_encrypted_env_file = require("./process-serverless/get-encrypted-env-file");
|
|
25
|
+
var import_get_lambda_environment = require("./process-serverless/get-lambda-environment");
|
|
26
|
+
var import_get_lambda_supports_streaming = require("./process-serverless/get-lambda-supports-streaming");
|
|
27
|
+
var import_stream_to_digest_async = require("./fs/stream-to-digest-async");
|
|
28
|
+
var import_collect_uncompressed_size = require("./collect-uncompressed-size");
|
|
29
|
+
const defaultTrace = (_name, fn) => fn();
|
|
30
|
+
async function finalizeLambda(params) {
|
|
31
|
+
const {
|
|
32
|
+
lambda,
|
|
33
|
+
encryptedEnvFilename,
|
|
34
|
+
encryptedEnvContent,
|
|
35
|
+
bytecodeCachingOptions,
|
|
36
|
+
forceStreamingRuntime,
|
|
37
|
+
enableUncompressedLambdaSizeCheck,
|
|
38
|
+
trace = defaultTrace,
|
|
39
|
+
createZip: createZipOverride,
|
|
40
|
+
validateZip
|
|
41
|
+
} = params;
|
|
42
|
+
const encryptedEnv = (0, import_get_encrypted_env_file.getEncryptedEnv)(
|
|
43
|
+
encryptedEnvFilename,
|
|
44
|
+
encryptedEnvContent
|
|
45
|
+
);
|
|
46
|
+
if (encryptedEnv) {
|
|
47
|
+
const [envFilename, envFile] = encryptedEnv;
|
|
48
|
+
lambda.zipBuffer = void 0;
|
|
49
|
+
lambda.files = {
|
|
50
|
+
...lambda.files,
|
|
51
|
+
[envFilename]: envFile
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
let uncompressedBytes = 0;
|
|
55
|
+
if (enableUncompressedLambdaSizeCheck) {
|
|
56
|
+
if (lambda.files) {
|
|
57
|
+
uncompressedBytes = await trace(
|
|
58
|
+
"collectUncompressedSize",
|
|
59
|
+
() => (0, import_collect_uncompressed_size.collectUncompressedSize)(lambda.files ?? {})
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const zipTags = {
|
|
64
|
+
fileCount: String(Object.keys(lambda.files ?? {}).length),
|
|
65
|
+
uncompressedBytes: String(uncompressedBytes)
|
|
66
|
+
};
|
|
67
|
+
let zipResult;
|
|
68
|
+
if (createZipOverride) {
|
|
69
|
+
zipResult = await trace(
|
|
70
|
+
"createZip",
|
|
71
|
+
() => createZipOverride(lambda),
|
|
72
|
+
zipTags
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
const buffer = lambda.zipBuffer || await trace("createZip", () => lambda.createZip(), zipTags);
|
|
76
|
+
zipResult = {
|
|
77
|
+
buffer,
|
|
78
|
+
digest: "",
|
|
79
|
+
// computed in step 5
|
|
80
|
+
size: buffer.byteLength
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (validateZip) {
|
|
84
|
+
validateZip({
|
|
85
|
+
buffer: zipResult.buffer,
|
|
86
|
+
zipPath: zipResult.zipPath,
|
|
87
|
+
size: zipResult.size
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!createZipOverride && zipResult.buffer) {
|
|
91
|
+
zipResult.digest = (0, import_stream_to_digest_async.sha256)(zipResult.buffer);
|
|
92
|
+
}
|
|
93
|
+
lambda.environment = {
|
|
94
|
+
...lambda.environment,
|
|
95
|
+
...(0, import_get_lambda_environment.getLambdaEnvironment)(
|
|
96
|
+
lambda,
|
|
97
|
+
zipResult.buffer ?? { byteLength: zipResult.size },
|
|
98
|
+
bytecodeCachingOptions
|
|
99
|
+
)
|
|
100
|
+
};
|
|
101
|
+
const streamingResult = await (0, import_get_lambda_supports_streaming.getLambdaSupportsStreaming)(
|
|
102
|
+
lambda,
|
|
103
|
+
forceStreamingRuntime
|
|
104
|
+
);
|
|
105
|
+
lambda.supportsResponseStreaming = streamingResult.supportsStreaming;
|
|
106
|
+
return {
|
|
107
|
+
buffer: zipResult.buffer,
|
|
108
|
+
zipPath: zipResult.zipPath,
|
|
109
|
+
digest: zipResult.digest,
|
|
110
|
+
size: zipResult.size,
|
|
111
|
+
uncompressedBytes,
|
|
112
|
+
streamingError: streamingResult.error
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
116
|
+
0 && (module.exports = {
|
|
117
|
+
finalizeLambda
|
|
118
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -46,3 +46,6 @@ export { getLambdaByOutputPath } from './collect-build-result/get-lambda-by-outp
|
|
|
46
46
|
export { isRouteMiddleware } from './collect-build-result/is-route-middleware';
|
|
47
47
|
export { getPrerenderChain } from './collect-build-result/get-prerender-chain';
|
|
48
48
|
export { streamWithExtendedPayload, type ExtendedBodyData, } from './collect-build-result/stream-with-extended-payload';
|
|
49
|
+
export { collectUncompressedSize } from './collect-uncompressed-size';
|
|
50
|
+
export { finalizeLambda, type CreateZipResult, type CreateZipFn, type FinalizeLambdaParams, type FinalizeLambdaResult, type TraceFn, } from './finalize-lambda';
|
|
51
|
+
export { validateLambdaSize, validateUncompressedLambdaSize, FunctionSizeError, MAX_LAMBDA_SIZE, MAX_LAMBDA_UNCOMPRESSED_SIZE, validateEnvWrapperSupport, ENV_WRAPPER_SUPPORTED_FAMILIES, } from './validate-lambda-size';
|
package/dist/index.js
CHANGED
|
@@ -11924,18 +11924,18 @@ var require_sync = __commonJS({
|
|
|
11924
11924
|
if (this.follow)
|
|
11925
11925
|
return this._readdir(abs, false);
|
|
11926
11926
|
var entries;
|
|
11927
|
-
var
|
|
11927
|
+
var lstat3;
|
|
11928
11928
|
var stat;
|
|
11929
11929
|
try {
|
|
11930
|
-
|
|
11930
|
+
lstat3 = this.fs.lstatSync(abs);
|
|
11931
11931
|
} catch (er) {
|
|
11932
11932
|
if (er.code === "ENOENT") {
|
|
11933
11933
|
return null;
|
|
11934
11934
|
}
|
|
11935
11935
|
}
|
|
11936
|
-
var isSym =
|
|
11936
|
+
var isSym = lstat3 && lstat3.isSymbolicLink();
|
|
11937
11937
|
this.symlinks[abs] = isSym;
|
|
11938
|
-
if (!isSym &&
|
|
11938
|
+
if (!isSym && lstat3 && !lstat3.isDirectory())
|
|
11939
11939
|
this.cache[abs] = "FILE";
|
|
11940
11940
|
else
|
|
11941
11941
|
entries = this._readdir(abs, false);
|
|
@@ -12060,23 +12060,23 @@ var require_sync = __commonJS({
|
|
|
12060
12060
|
var exists;
|
|
12061
12061
|
var stat = this.statCache[abs];
|
|
12062
12062
|
if (!stat) {
|
|
12063
|
-
var
|
|
12063
|
+
var lstat3;
|
|
12064
12064
|
try {
|
|
12065
|
-
|
|
12065
|
+
lstat3 = this.fs.lstatSync(abs);
|
|
12066
12066
|
} catch (er) {
|
|
12067
12067
|
if (er && (er.code === "ENOENT" || er.code === "ENOTDIR")) {
|
|
12068
12068
|
this.statCache[abs] = false;
|
|
12069
12069
|
return false;
|
|
12070
12070
|
}
|
|
12071
12071
|
}
|
|
12072
|
-
if (
|
|
12072
|
+
if (lstat3 && lstat3.isSymbolicLink()) {
|
|
12073
12073
|
try {
|
|
12074
12074
|
stat = this.fs.statSync(abs);
|
|
12075
12075
|
} catch (er) {
|
|
12076
|
-
stat =
|
|
12076
|
+
stat = lstat3;
|
|
12077
12077
|
}
|
|
12078
12078
|
} else {
|
|
12079
|
-
stat =
|
|
12079
|
+
stat = lstat3;
|
|
12080
12080
|
}
|
|
12081
12081
|
}
|
|
12082
12082
|
this.statCache[abs] = stat;
|
|
@@ -12493,12 +12493,12 @@ var require_glob = __commonJS({
|
|
|
12493
12493
|
var lstatcb = inflight(lstatkey, lstatcb_);
|
|
12494
12494
|
if (lstatcb)
|
|
12495
12495
|
self2.fs.lstat(abs, lstatcb);
|
|
12496
|
-
function lstatcb_(er,
|
|
12496
|
+
function lstatcb_(er, lstat3) {
|
|
12497
12497
|
if (er && er.code === "ENOENT")
|
|
12498
12498
|
return cb();
|
|
12499
|
-
var isSym =
|
|
12499
|
+
var isSym = lstat3 && lstat3.isSymbolicLink();
|
|
12500
12500
|
self2.symlinks[abs] = isSym;
|
|
12501
|
-
if (!isSym &&
|
|
12501
|
+
if (!isSym && lstat3 && !lstat3.isDirectory()) {
|
|
12502
12502
|
self2.cache[abs] = "FILE";
|
|
12503
12503
|
cb();
|
|
12504
12504
|
} else
|
|
@@ -12666,16 +12666,16 @@ var require_glob = __commonJS({
|
|
|
12666
12666
|
var statcb = inflight("stat\0" + abs, lstatcb_);
|
|
12667
12667
|
if (statcb)
|
|
12668
12668
|
self2.fs.lstat(abs, statcb);
|
|
12669
|
-
function lstatcb_(er,
|
|
12670
|
-
if (
|
|
12669
|
+
function lstatcb_(er, lstat3) {
|
|
12670
|
+
if (lstat3 && lstat3.isSymbolicLink()) {
|
|
12671
12671
|
return self2.fs.stat(abs, function(er2, stat2) {
|
|
12672
12672
|
if (er2)
|
|
12673
|
-
self2._stat2(f, abs, null,
|
|
12673
|
+
self2._stat2(f, abs, null, lstat3, cb);
|
|
12674
12674
|
else
|
|
12675
12675
|
self2._stat2(f, abs, er2, stat2, cb);
|
|
12676
12676
|
});
|
|
12677
12677
|
} else {
|
|
12678
|
-
self2._stat2(f, abs, er,
|
|
12678
|
+
self2._stat2(f, abs, er, lstat3, cb);
|
|
12679
12679
|
}
|
|
12680
12680
|
}
|
|
12681
12681
|
};
|
|
@@ -19806,6 +19806,95 @@ var require_ignore = __commonJS({
|
|
|
19806
19806
|
}
|
|
19807
19807
|
});
|
|
19808
19808
|
|
|
19809
|
+
// ../../node_modules/.pnpm/bytes@3.1.2/node_modules/bytes/index.js
|
|
19810
|
+
var require_bytes = __commonJS({
|
|
19811
|
+
"../../node_modules/.pnpm/bytes@3.1.2/node_modules/bytes/index.js"(exports, module2) {
|
|
19812
|
+
"use strict";
|
|
19813
|
+
module2.exports = bytes2;
|
|
19814
|
+
module2.exports.format = format;
|
|
19815
|
+
module2.exports.parse = parse6;
|
|
19816
|
+
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
|
19817
|
+
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
|
19818
|
+
var map = {
|
|
19819
|
+
b: 1,
|
|
19820
|
+
kb: 1 << 10,
|
|
19821
|
+
mb: 1 << 20,
|
|
19822
|
+
gb: 1 << 30,
|
|
19823
|
+
tb: Math.pow(1024, 4),
|
|
19824
|
+
pb: Math.pow(1024, 5)
|
|
19825
|
+
};
|
|
19826
|
+
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
|
|
19827
|
+
function bytes2(value, options) {
|
|
19828
|
+
if (typeof value === "string") {
|
|
19829
|
+
return parse6(value);
|
|
19830
|
+
}
|
|
19831
|
+
if (typeof value === "number") {
|
|
19832
|
+
return format(value, options);
|
|
19833
|
+
}
|
|
19834
|
+
return null;
|
|
19835
|
+
}
|
|
19836
|
+
function format(value, options) {
|
|
19837
|
+
if (!Number.isFinite(value)) {
|
|
19838
|
+
return null;
|
|
19839
|
+
}
|
|
19840
|
+
var mag = Math.abs(value);
|
|
19841
|
+
var thousandsSeparator = options && options.thousandsSeparator || "";
|
|
19842
|
+
var unitSeparator = options && options.unitSeparator || "";
|
|
19843
|
+
var decimalPlaces = options && options.decimalPlaces !== void 0 ? options.decimalPlaces : 2;
|
|
19844
|
+
var fixedDecimals = Boolean(options && options.fixedDecimals);
|
|
19845
|
+
var unit = options && options.unit || "";
|
|
19846
|
+
if (!unit || !map[unit.toLowerCase()]) {
|
|
19847
|
+
if (mag >= map.pb) {
|
|
19848
|
+
unit = "PB";
|
|
19849
|
+
} else if (mag >= map.tb) {
|
|
19850
|
+
unit = "TB";
|
|
19851
|
+
} else if (mag >= map.gb) {
|
|
19852
|
+
unit = "GB";
|
|
19853
|
+
} else if (mag >= map.mb) {
|
|
19854
|
+
unit = "MB";
|
|
19855
|
+
} else if (mag >= map.kb) {
|
|
19856
|
+
unit = "KB";
|
|
19857
|
+
} else {
|
|
19858
|
+
unit = "B";
|
|
19859
|
+
}
|
|
19860
|
+
}
|
|
19861
|
+
var val = value / map[unit.toLowerCase()];
|
|
19862
|
+
var str = val.toFixed(decimalPlaces);
|
|
19863
|
+
if (!fixedDecimals) {
|
|
19864
|
+
str = str.replace(formatDecimalsRegExp, "$1");
|
|
19865
|
+
}
|
|
19866
|
+
if (thousandsSeparator) {
|
|
19867
|
+
str = str.split(".").map(function(s, i) {
|
|
19868
|
+
return i === 0 ? s.replace(formatThousandsRegExp, thousandsSeparator) : s;
|
|
19869
|
+
}).join(".");
|
|
19870
|
+
}
|
|
19871
|
+
return str + unitSeparator + unit;
|
|
19872
|
+
}
|
|
19873
|
+
function parse6(val) {
|
|
19874
|
+
if (typeof val === "number" && !isNaN(val)) {
|
|
19875
|
+
return val;
|
|
19876
|
+
}
|
|
19877
|
+
if (typeof val !== "string") {
|
|
19878
|
+
return null;
|
|
19879
|
+
}
|
|
19880
|
+
var results = parseRegExp.exec(val);
|
|
19881
|
+
var floatValue;
|
|
19882
|
+
var unit = "b";
|
|
19883
|
+
if (!results) {
|
|
19884
|
+
floatValue = parseInt(val, 10);
|
|
19885
|
+
unit = "b";
|
|
19886
|
+
} else {
|
|
19887
|
+
floatValue = parseFloat(results[1]);
|
|
19888
|
+
unit = results[4].toLowerCase();
|
|
19889
|
+
}
|
|
19890
|
+
if (isNaN(floatValue)) {
|
|
19891
|
+
return null;
|
|
19892
|
+
}
|
|
19893
|
+
return Math.floor(map[unit] * floatValue);
|
|
19894
|
+
}
|
|
19895
|
+
}
|
|
19896
|
+
});
|
|
19897
|
+
|
|
19809
19898
|
// src/index.ts
|
|
19810
19899
|
var src_exports = {};
|
|
19811
19900
|
__export(src_exports, {
|
|
@@ -19814,11 +19903,15 @@ __export(src_exports, {
|
|
|
19814
19903
|
BUILDER_COMPILE_STEP: () => BUILDER_COMPILE_STEP,
|
|
19815
19904
|
BUILDER_INSTALLER_STEP: () => BUILDER_INSTALLER_STEP,
|
|
19816
19905
|
BunVersion: () => BunVersion,
|
|
19906
|
+
ENV_WRAPPER_SUPPORTED_FAMILIES: () => ENV_WRAPPER_SUPPORTED_FAMILIES,
|
|
19817
19907
|
EdgeFunction: () => EdgeFunction,
|
|
19818
19908
|
FileBlob: () => FileBlob,
|
|
19819
19909
|
FileFsRef: () => file_fs_ref_default,
|
|
19820
19910
|
FileRef: () => FileRef,
|
|
19911
|
+
FunctionSizeError: () => FunctionSizeError,
|
|
19821
19912
|
Lambda: () => Lambda,
|
|
19913
|
+
MAX_LAMBDA_SIZE: () => MAX_LAMBDA_SIZE,
|
|
19914
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE: () => MAX_LAMBDA_UNCOMPRESSED_SIZE,
|
|
19822
19915
|
NODE_VERSIONS: () => NODE_VERSIONS,
|
|
19823
19916
|
NodeVersion: () => NodeVersion,
|
|
19824
19917
|
NodejsLambda: () => NodejsLambda,
|
|
@@ -19830,6 +19923,7 @@ __export(src_exports, {
|
|
|
19830
19923
|
Version: () => Version,
|
|
19831
19924
|
buildsSchema: () => buildsSchema,
|
|
19832
19925
|
cloneEnv: () => cloneEnv,
|
|
19926
|
+
collectUncompressedSize: () => collectUncompressedSize,
|
|
19833
19927
|
createLambda: () => createLambda,
|
|
19834
19928
|
debug: () => debug,
|
|
19835
19929
|
defaultCachePathGlob: () => defaultCachePathGlob,
|
|
@@ -19837,6 +19931,7 @@ __export(src_exports, {
|
|
|
19837
19931
|
download: () => download,
|
|
19838
19932
|
downloadFile: () => downloadFile,
|
|
19839
19933
|
execCommand: () => execCommand,
|
|
19934
|
+
finalizeLambda: () => finalizeLambda,
|
|
19840
19935
|
findPackageJson: () => findPackageJson,
|
|
19841
19936
|
functionsSchema: () => functionsSchema,
|
|
19842
19937
|
generateNodeBuilderFunctions: () => generateNodeBuilderFunctions,
|
|
@@ -19908,7 +20003,10 @@ __export(src_exports, {
|
|
|
19908
20003
|
streamToDigestAsync: () => streamToDigestAsync,
|
|
19909
20004
|
streamWithExtendedPayload: () => streamWithExtendedPayload,
|
|
19910
20005
|
traverseUpDirectories: () => traverseUpDirectories,
|
|
20006
|
+
validateEnvWrapperSupport: () => validateEnvWrapperSupport,
|
|
20007
|
+
validateLambdaSize: () => validateLambdaSize,
|
|
19911
20008
|
validateNpmrc: () => validateNpmrc,
|
|
20009
|
+
validateUncompressedLambdaSize: () => validateUncompressedLambdaSize,
|
|
19912
20010
|
walkParentDirs: () => walkParentDirs
|
|
19913
20011
|
});
|
|
19914
20012
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -24343,6 +24441,197 @@ var MultipartContentStream = class extends import_stream.Readable {
|
|
|
24343
24441
|
_read() {
|
|
24344
24442
|
}
|
|
24345
24443
|
};
|
|
24444
|
+
|
|
24445
|
+
// src/collect-uncompressed-size.ts
|
|
24446
|
+
var import_promises2 = require("fs/promises");
|
|
24447
|
+
var fileSizeCache = /* @__PURE__ */ new Map();
|
|
24448
|
+
var getFileSize = (path7) => {
|
|
24449
|
+
if (!path7)
|
|
24450
|
+
return Promise.resolve(0);
|
|
24451
|
+
const cached = fileSizeCache.get(path7);
|
|
24452
|
+
if (cached) {
|
|
24453
|
+
return cached;
|
|
24454
|
+
}
|
|
24455
|
+
const promise = (0, import_promises2.lstat)(path7).then((stats) => stats.size);
|
|
24456
|
+
fileSizeCache.set(path7, promise);
|
|
24457
|
+
return promise;
|
|
24458
|
+
};
|
|
24459
|
+
var collectUncompressedSize = async (files, ignoreFn) => {
|
|
24460
|
+
let size = 0;
|
|
24461
|
+
await Promise.all(
|
|
24462
|
+
Object.keys(files).map(async (fileKey) => {
|
|
24463
|
+
if (ignoreFn?.(fileKey)) {
|
|
24464
|
+
return;
|
|
24465
|
+
}
|
|
24466
|
+
const file = files[fileKey];
|
|
24467
|
+
if (file.type === "FileBlob") {
|
|
24468
|
+
size += file.data.length;
|
|
24469
|
+
} else if (file.type === "FileFsRef") {
|
|
24470
|
+
const fsRef = file;
|
|
24471
|
+
const curSize = fsRef.size ?? await getFileSize(fsRef.fsPath);
|
|
24472
|
+
size += curSize;
|
|
24473
|
+
}
|
|
24474
|
+
})
|
|
24475
|
+
);
|
|
24476
|
+
return size;
|
|
24477
|
+
};
|
|
24478
|
+
|
|
24479
|
+
// src/finalize-lambda.ts
|
|
24480
|
+
var defaultTrace = (_name, fn) => fn();
|
|
24481
|
+
async function finalizeLambda(params) {
|
|
24482
|
+
const {
|
|
24483
|
+
lambda,
|
|
24484
|
+
encryptedEnvFilename,
|
|
24485
|
+
encryptedEnvContent,
|
|
24486
|
+
bytecodeCachingOptions,
|
|
24487
|
+
forceStreamingRuntime,
|
|
24488
|
+
enableUncompressedLambdaSizeCheck,
|
|
24489
|
+
trace = defaultTrace,
|
|
24490
|
+
createZip: createZipOverride,
|
|
24491
|
+
validateZip
|
|
24492
|
+
} = params;
|
|
24493
|
+
const encryptedEnv = getEncryptedEnv(
|
|
24494
|
+
encryptedEnvFilename,
|
|
24495
|
+
encryptedEnvContent
|
|
24496
|
+
);
|
|
24497
|
+
if (encryptedEnv) {
|
|
24498
|
+
const [envFilename, envFile] = encryptedEnv;
|
|
24499
|
+
lambda.zipBuffer = void 0;
|
|
24500
|
+
lambda.files = {
|
|
24501
|
+
...lambda.files,
|
|
24502
|
+
[envFilename]: envFile
|
|
24503
|
+
};
|
|
24504
|
+
}
|
|
24505
|
+
let uncompressedBytes = 0;
|
|
24506
|
+
if (enableUncompressedLambdaSizeCheck) {
|
|
24507
|
+
if (lambda.files) {
|
|
24508
|
+
uncompressedBytes = await trace(
|
|
24509
|
+
"collectUncompressedSize",
|
|
24510
|
+
() => collectUncompressedSize(lambda.files ?? {})
|
|
24511
|
+
);
|
|
24512
|
+
}
|
|
24513
|
+
}
|
|
24514
|
+
const zipTags = {
|
|
24515
|
+
fileCount: String(Object.keys(lambda.files ?? {}).length),
|
|
24516
|
+
uncompressedBytes: String(uncompressedBytes)
|
|
24517
|
+
};
|
|
24518
|
+
let zipResult;
|
|
24519
|
+
if (createZipOverride) {
|
|
24520
|
+
zipResult = await trace(
|
|
24521
|
+
"createZip",
|
|
24522
|
+
() => createZipOverride(lambda),
|
|
24523
|
+
zipTags
|
|
24524
|
+
);
|
|
24525
|
+
} else {
|
|
24526
|
+
const buffer = lambda.zipBuffer || await trace("createZip", () => lambda.createZip(), zipTags);
|
|
24527
|
+
zipResult = {
|
|
24528
|
+
buffer,
|
|
24529
|
+
digest: "",
|
|
24530
|
+
// computed in step 5
|
|
24531
|
+
size: buffer.byteLength
|
|
24532
|
+
};
|
|
24533
|
+
}
|
|
24534
|
+
if (validateZip) {
|
|
24535
|
+
validateZip({
|
|
24536
|
+
buffer: zipResult.buffer,
|
|
24537
|
+
zipPath: zipResult.zipPath,
|
|
24538
|
+
size: zipResult.size
|
|
24539
|
+
});
|
|
24540
|
+
}
|
|
24541
|
+
if (!createZipOverride && zipResult.buffer) {
|
|
24542
|
+
zipResult.digest = sha256(zipResult.buffer);
|
|
24543
|
+
}
|
|
24544
|
+
lambda.environment = {
|
|
24545
|
+
...lambda.environment,
|
|
24546
|
+
...getLambdaEnvironment(
|
|
24547
|
+
lambda,
|
|
24548
|
+
zipResult.buffer ?? { byteLength: zipResult.size },
|
|
24549
|
+
bytecodeCachingOptions
|
|
24550
|
+
)
|
|
24551
|
+
};
|
|
24552
|
+
const streamingResult = await getLambdaSupportsStreaming(
|
|
24553
|
+
lambda,
|
|
24554
|
+
forceStreamingRuntime
|
|
24555
|
+
);
|
|
24556
|
+
lambda.supportsResponseStreaming = streamingResult.supportsStreaming;
|
|
24557
|
+
return {
|
|
24558
|
+
buffer: zipResult.buffer,
|
|
24559
|
+
zipPath: zipResult.zipPath,
|
|
24560
|
+
digest: zipResult.digest,
|
|
24561
|
+
size: zipResult.size,
|
|
24562
|
+
uncompressedBytes,
|
|
24563
|
+
streamingError: streamingResult.error
|
|
24564
|
+
};
|
|
24565
|
+
}
|
|
24566
|
+
|
|
24567
|
+
// src/validate-lambda-size.ts
|
|
24568
|
+
var import_bytes = __toESM(require_bytes());
|
|
24569
|
+
var MAX_LAMBDA_SIZE = (0, import_bytes.default)("300mb");
|
|
24570
|
+
var MAX_LAMBDA_UNCOMPRESSED_SIZE = 250 * 1024 * 1024;
|
|
24571
|
+
var FunctionSizeError = class extends NowBuildError {
|
|
24572
|
+
constructor(outputPath, size) {
|
|
24573
|
+
super({
|
|
24574
|
+
code: "NOW_SANDBOX_WORKER_MAX_LAMBDA_SIZE",
|
|
24575
|
+
message: `The Vercel Function "${outputPath}" is ${(0, import_bytes.default)(
|
|
24576
|
+
size
|
|
24577
|
+
).toLowerCase()} which exceeds the maximum size limit of ${(0, import_bytes.default)(
|
|
24578
|
+
MAX_LAMBDA_SIZE
|
|
24579
|
+
).toLowerCase()}.`,
|
|
24580
|
+
link: "https://vercel.link/serverless-function-size",
|
|
24581
|
+
action: "Learn More"
|
|
24582
|
+
});
|
|
24583
|
+
this.size = size;
|
|
24584
|
+
this.maxSize = MAX_LAMBDA_SIZE;
|
|
24585
|
+
}
|
|
24586
|
+
};
|
|
24587
|
+
function validateLambdaSize(outputPath, runtime, size) {
|
|
24588
|
+
if (runtime.startsWith("python")) {
|
|
24589
|
+
return;
|
|
24590
|
+
}
|
|
24591
|
+
if (size > MAX_LAMBDA_SIZE) {
|
|
24592
|
+
throw new FunctionSizeError(outputPath, size);
|
|
24593
|
+
}
|
|
24594
|
+
}
|
|
24595
|
+
function validateUncompressedLambdaSize(outputPath, uncompressedBytes) {
|
|
24596
|
+
if (uncompressedBytes >= MAX_LAMBDA_UNCOMPRESSED_SIZE) {
|
|
24597
|
+
throw new NowBuildError({
|
|
24598
|
+
code: "NOW_SANDBOX_WORKER_MAX_UNCOMPRESSED_LAMBDA_SIZE",
|
|
24599
|
+
message: `The Vercel Function "${outputPath}" is ${(0, import_bytes.default)(
|
|
24600
|
+
uncompressedBytes
|
|
24601
|
+
).toLowerCase()} uncompressed which exceeds the maximum uncompressed size limit of ${(0, import_bytes.default)(
|
|
24602
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE
|
|
24603
|
+
).toLowerCase()}.`,
|
|
24604
|
+
link: "https://vercel.link/serverless-function-size",
|
|
24605
|
+
action: "Learn More"
|
|
24606
|
+
});
|
|
24607
|
+
}
|
|
24608
|
+
}
|
|
24609
|
+
var ENV_WRAPPER_SUPPORTED_FAMILIES = [
|
|
24610
|
+
"nodejs",
|
|
24611
|
+
"python",
|
|
24612
|
+
"ruby",
|
|
24613
|
+
"java",
|
|
24614
|
+
"dotnetcore",
|
|
24615
|
+
"bun",
|
|
24616
|
+
"executable"
|
|
24617
|
+
];
|
|
24618
|
+
function validateEnvWrapperSupport(encryptedEnvFilename, encryptedEnvContent, lambda) {
|
|
24619
|
+
if (!encryptedEnvFilename || !encryptedEnvContent) {
|
|
24620
|
+
return;
|
|
24621
|
+
}
|
|
24622
|
+
if (!lambda.supportsWrapper && !ENV_WRAPPER_SUPPORTED_FAMILIES.some(
|
|
24623
|
+
(family) => lambda.runtime.startsWith(family)
|
|
24624
|
+
)) {
|
|
24625
|
+
throw new Error(
|
|
24626
|
+
`Serverless Function runtime ${lambda.runtime} does not support more than 4KB for environment variables`
|
|
24627
|
+
);
|
|
24628
|
+
}
|
|
24629
|
+
if (typeof lambda.createZip !== "function") {
|
|
24630
|
+
throw new Error(
|
|
24631
|
+
`Serverless Function with runtime ${lambda.runtime} has no createZip function`
|
|
24632
|
+
);
|
|
24633
|
+
}
|
|
24634
|
+
}
|
|
24346
24635
|
// Annotate the CommonJS export names for ESM import in node:
|
|
24347
24636
|
0 && (module.exports = {
|
|
24348
24637
|
BACKEND_BUILDERS,
|
|
@@ -24350,11 +24639,15 @@ var MultipartContentStream = class extends import_stream.Readable {
|
|
|
24350
24639
|
BUILDER_COMPILE_STEP,
|
|
24351
24640
|
BUILDER_INSTALLER_STEP,
|
|
24352
24641
|
BunVersion,
|
|
24642
|
+
ENV_WRAPPER_SUPPORTED_FAMILIES,
|
|
24353
24643
|
EdgeFunction,
|
|
24354
24644
|
FileBlob,
|
|
24355
24645
|
FileFsRef,
|
|
24356
24646
|
FileRef,
|
|
24647
|
+
FunctionSizeError,
|
|
24357
24648
|
Lambda,
|
|
24649
|
+
MAX_LAMBDA_SIZE,
|
|
24650
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE,
|
|
24358
24651
|
NODE_VERSIONS,
|
|
24359
24652
|
NodeVersion,
|
|
24360
24653
|
NodejsLambda,
|
|
@@ -24366,6 +24659,7 @@ var MultipartContentStream = class extends import_stream.Readable {
|
|
|
24366
24659
|
Version,
|
|
24367
24660
|
buildsSchema,
|
|
24368
24661
|
cloneEnv,
|
|
24662
|
+
collectUncompressedSize,
|
|
24369
24663
|
createLambda,
|
|
24370
24664
|
debug,
|
|
24371
24665
|
defaultCachePathGlob,
|
|
@@ -24373,6 +24667,7 @@ var MultipartContentStream = class extends import_stream.Readable {
|
|
|
24373
24667
|
download,
|
|
24374
24668
|
downloadFile,
|
|
24375
24669
|
execCommand,
|
|
24670
|
+
finalizeLambda,
|
|
24376
24671
|
findPackageJson,
|
|
24377
24672
|
functionsSchema,
|
|
24378
24673
|
generateNodeBuilderFunctions,
|
|
@@ -24444,11 +24739,22 @@ var MultipartContentStream = class extends import_stream.Readable {
|
|
|
24444
24739
|
streamToDigestAsync,
|
|
24445
24740
|
streamWithExtendedPayload,
|
|
24446
24741
|
traverseUpDirectories,
|
|
24742
|
+
validateEnvWrapperSupport,
|
|
24743
|
+
validateLambdaSize,
|
|
24447
24744
|
validateNpmrc,
|
|
24745
|
+
validateUncompressedLambdaSize,
|
|
24448
24746
|
walkParentDirs
|
|
24449
24747
|
});
|
|
24450
24748
|
/*! Bundled license information:
|
|
24451
24749
|
|
|
24750
|
+
bytes/index.js:
|
|
24751
|
+
(*!
|
|
24752
|
+
* bytes
|
|
24753
|
+
* Copyright(c) 2012-2014 TJ Holowaychuk
|
|
24754
|
+
* Copyright(c) 2015 Jed Watson
|
|
24755
|
+
* MIT Licensed
|
|
24756
|
+
*)
|
|
24757
|
+
|
|
24452
24758
|
smol-toml/dist/error.js:
|
|
24453
24759
|
(*!
|
|
24454
24760
|
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { type BytecodeCachingOptions } from './get-lambda-preload-scripts';
|
|
3
2
|
interface LambdaLike {
|
|
4
3
|
awsLambdaHandler?: string;
|
|
@@ -14,5 +13,7 @@ interface LambdaLike {
|
|
|
14
13
|
* Buffer is required just to determine if Bytecode Caching should be enabled
|
|
15
14
|
* but it doesn't need to be super precise.
|
|
16
15
|
*/
|
|
17
|
-
export declare function getLambdaEnvironment(lambda: LambdaLike, buffer:
|
|
16
|
+
export declare function getLambdaEnvironment(lambda: LambdaLike, buffer: {
|
|
17
|
+
byteLength: number;
|
|
18
|
+
}, options: BytecodeCachingOptions): Record<string, string>;
|
|
18
19
|
export {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
export interface BytecodeCachingOptions {
|
|
3
2
|
vercelEnv: string | undefined;
|
|
4
3
|
useBytecodeCaching: string | undefined;
|
|
@@ -17,5 +16,7 @@ interface LambdaLike {
|
|
|
17
16
|
* The `buffer` parameter is needed to decide wether or not to enable Bytecode
|
|
18
17
|
* Caching so it doesn't **need** to be exact (we can leave out the env layer)
|
|
19
18
|
*/
|
|
20
|
-
export declare function getLambdaPreloadScripts(lambda: LambdaLike, buffer:
|
|
19
|
+
export declare function getLambdaPreloadScripts(lambda: LambdaLike, buffer: {
|
|
20
|
+
byteLength: number;
|
|
21
|
+
}, options: BytecodeCachingOptions): string[];
|
|
21
22
|
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { NowBuildError } from './errors';
|
|
3
|
+
/**
|
|
4
|
+
* Max compressed ZIP size (300 MB).
|
|
5
|
+
* Limit is 250 MB uncompressed; we set 300 MB compressed as a safety
|
|
6
|
+
* buffer. Python is exempt because AI workloads commonly exceed this.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MAX_LAMBDA_SIZE: number;
|
|
9
|
+
/**
|
|
10
|
+
* Max uncompressed size (250 MB).
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_LAMBDA_UNCOMPRESSED_SIZE: number;
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown when a Lambda's compressed ZIP exceeds the allowed size.
|
|
15
|
+
*/
|
|
16
|
+
export declare class FunctionSizeError extends NowBuildError {
|
|
17
|
+
size: number;
|
|
18
|
+
maxSize: number;
|
|
19
|
+
constructor(outputPath: string, size: number);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validates the compressed size of a Lambda function.
|
|
23
|
+
* Python runtimes are exempt because AI workloads commonly exceed 300 MB.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateLambdaSize(outputPath: string, runtime: string, size: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Validates the uncompressed size of a Lambda function.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateUncompressedLambdaSize(outputPath: string, uncompressedBytes: number): void;
|
|
30
|
+
/**
|
|
31
|
+
* Runtimes that support env wrapper.
|
|
32
|
+
*/
|
|
33
|
+
export declare const ENV_WRAPPER_SUPPORTED_FAMILIES: string[];
|
|
34
|
+
interface LambdaLikeForEnvWrapper {
|
|
35
|
+
createZip?: () => Promise<Buffer>;
|
|
36
|
+
runtime: string;
|
|
37
|
+
supportsWrapper?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* When the function requires a file for the encrypted environment variables,
|
|
41
|
+
* it needs to support wrappers. Also, the function must have a `createZip`
|
|
42
|
+
* function since we need to "re-compress" to include the file in the final
|
|
43
|
+
* lambda.
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateEnvWrapperSupport(encryptedEnvFilename: string | undefined, encryptedEnvContent: string | undefined, lambda: LambdaLikeForEnvWrapper): void;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var validate_lambda_size_exports = {};
|
|
30
|
+
__export(validate_lambda_size_exports, {
|
|
31
|
+
ENV_WRAPPER_SUPPORTED_FAMILIES: () => ENV_WRAPPER_SUPPORTED_FAMILIES,
|
|
32
|
+
FunctionSizeError: () => FunctionSizeError,
|
|
33
|
+
MAX_LAMBDA_SIZE: () => MAX_LAMBDA_SIZE,
|
|
34
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE: () => MAX_LAMBDA_UNCOMPRESSED_SIZE,
|
|
35
|
+
validateEnvWrapperSupport: () => validateEnvWrapperSupport,
|
|
36
|
+
validateLambdaSize: () => validateLambdaSize,
|
|
37
|
+
validateUncompressedLambdaSize: () => validateUncompressedLambdaSize
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(validate_lambda_size_exports);
|
|
40
|
+
var import_errors = require("./errors");
|
|
41
|
+
var import_bytes = __toESM(require("bytes"));
|
|
42
|
+
const MAX_LAMBDA_SIZE = (0, import_bytes.default)("300mb");
|
|
43
|
+
const MAX_LAMBDA_UNCOMPRESSED_SIZE = 250 * 1024 * 1024;
|
|
44
|
+
class FunctionSizeError extends import_errors.NowBuildError {
|
|
45
|
+
constructor(outputPath, size) {
|
|
46
|
+
super({
|
|
47
|
+
code: "NOW_SANDBOX_WORKER_MAX_LAMBDA_SIZE",
|
|
48
|
+
message: `The Vercel Function "${outputPath}" is ${(0, import_bytes.default)(
|
|
49
|
+
size
|
|
50
|
+
).toLowerCase()} which exceeds the maximum size limit of ${(0, import_bytes.default)(
|
|
51
|
+
MAX_LAMBDA_SIZE
|
|
52
|
+
).toLowerCase()}.`,
|
|
53
|
+
link: "https://vercel.link/serverless-function-size",
|
|
54
|
+
action: "Learn More"
|
|
55
|
+
});
|
|
56
|
+
this.size = size;
|
|
57
|
+
this.maxSize = MAX_LAMBDA_SIZE;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function validateLambdaSize(outputPath, runtime, size) {
|
|
61
|
+
if (runtime.startsWith("python")) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (size > MAX_LAMBDA_SIZE) {
|
|
65
|
+
throw new FunctionSizeError(outputPath, size);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function validateUncompressedLambdaSize(outputPath, uncompressedBytes) {
|
|
69
|
+
if (uncompressedBytes >= MAX_LAMBDA_UNCOMPRESSED_SIZE) {
|
|
70
|
+
throw new import_errors.NowBuildError({
|
|
71
|
+
code: "NOW_SANDBOX_WORKER_MAX_UNCOMPRESSED_LAMBDA_SIZE",
|
|
72
|
+
message: `The Vercel Function "${outputPath}" is ${(0, import_bytes.default)(
|
|
73
|
+
uncompressedBytes
|
|
74
|
+
).toLowerCase()} uncompressed which exceeds the maximum uncompressed size limit of ${(0, import_bytes.default)(
|
|
75
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE
|
|
76
|
+
).toLowerCase()}.`,
|
|
77
|
+
link: "https://vercel.link/serverless-function-size",
|
|
78
|
+
action: "Learn More"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const ENV_WRAPPER_SUPPORTED_FAMILIES = [
|
|
83
|
+
"nodejs",
|
|
84
|
+
"python",
|
|
85
|
+
"ruby",
|
|
86
|
+
"java",
|
|
87
|
+
"dotnetcore",
|
|
88
|
+
"bun",
|
|
89
|
+
"executable"
|
|
90
|
+
];
|
|
91
|
+
function validateEnvWrapperSupport(encryptedEnvFilename, encryptedEnvContent, lambda) {
|
|
92
|
+
if (!encryptedEnvFilename || !encryptedEnvContent) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!lambda.supportsWrapper && !ENV_WRAPPER_SUPPORTED_FAMILIES.some(
|
|
96
|
+
(family) => lambda.runtime.startsWith(family)
|
|
97
|
+
)) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Serverless Function runtime ${lambda.runtime} does not support more than 4KB for environment variables`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (typeof lambda.createZip !== "function") {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Serverless Function with runtime ${lambda.runtime} has no createZip function`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
ENV_WRAPPER_SUPPORTED_FAMILIES,
|
|
111
|
+
FunctionSizeError,
|
|
112
|
+
MAX_LAMBDA_SIZE,
|
|
113
|
+
MAX_LAMBDA_UNCOMPRESSED_SIZE,
|
|
114
|
+
validateEnvWrapperSupport,
|
|
115
|
+
validateLambdaSize,
|
|
116
|
+
validateUncompressedLambdaSize
|
|
117
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/build-utils",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.13.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.js",
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
"@vercel/python-analysis": "0.11.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
+
"bytes": "3.1.2",
|
|
19
20
|
"smol-toml": "1.5.2",
|
|
20
21
|
"@types/async-retry": "^1.2.1",
|
|
22
|
+
"@types/bytes": "3.1.1",
|
|
21
23
|
"@types/cross-spawn": "6.0.0",
|
|
22
24
|
"@types/end-of-stream": "^1.4.0",
|
|
23
25
|
"@types/fs-extra": "9.0.13",
|