@vercel/build-utils 13.12.2 → 13.14.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/finalize-lambda.d.ts +44 -6
- package/dist/finalize-lambda.js +42 -6
- package/dist/get-ignore-filter.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +43 -7
- package/dist/process-serverless/get-lambda-environment.d.ts +3 -2
- package/dist/process-serverless/get-lambda-preload-scripts.d.ts +3 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @vercel/build-utils
|
|
2
2
|
|
|
3
|
+
## 13.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Support configuration via vercel.toml ([#15750](https://github.com/vercel/vercel/pull/15750))
|
|
8
|
+
|
|
9
|
+
## 13.13.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 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))
|
|
14
|
+
|
|
3
15
|
## 13.12.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -7,7 +7,26 @@ import type { SupportsStreamingResult } from './process-serverless/get-lambda-su
|
|
|
7
7
|
* Optional wrapper around async work, allowing callers to inject tracing
|
|
8
8
|
* (e.g. dd-trace spans) without coupling the shared code to a tracer.
|
|
9
9
|
*/
|
|
10
|
-
export type TraceFn = <T>(name: string, fn: () => Promise<T>) => Promise<T>;
|
|
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>;
|
|
11
30
|
export interface FinalizeLambdaParams {
|
|
12
31
|
lambda: Lambda | NodejsLambda;
|
|
13
32
|
encryptedEnvFilename?: string;
|
|
@@ -18,10 +37,28 @@ export interface FinalizeLambdaParams {
|
|
|
18
37
|
enableUncompressedLambdaSizeCheck?: boolean;
|
|
19
38
|
/** Optional tracing wrapper for `collectUncompressedSize` and `createZip`. */
|
|
20
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;
|
|
21
52
|
}
|
|
22
53
|
export interface FinalizeLambdaResult {
|
|
23
|
-
|
|
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. */
|
|
24
59
|
digest: string;
|
|
60
|
+
/** Compressed size in bytes. */
|
|
61
|
+
size: number;
|
|
25
62
|
uncompressedBytes: number;
|
|
26
63
|
/** Non-fatal streaming detection error, if any. Caller decides how to log. */
|
|
27
64
|
streamingError?: SupportsStreamingResult['error'];
|
|
@@ -32,10 +69,11 @@ export interface FinalizeLambdaResult {
|
|
|
32
69
|
* This function:
|
|
33
70
|
* 1. Injects encrypted env file into lambda.files when provided
|
|
34
71
|
* 2. Collects uncompressed size when enabled
|
|
35
|
-
* 3. Creates the ZIP
|
|
36
|
-
* 4.
|
|
37
|
-
* 5.
|
|
38
|
-
* 6.
|
|
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
|
|
39
77
|
*
|
|
40
78
|
* Note: This function mutates the `lambda` (files, environment,
|
|
41
79
|
* supportsResponseStreaming).
|
package/dist/finalize-lambda.js
CHANGED
|
@@ -35,7 +35,9 @@ async function finalizeLambda(params) {
|
|
|
35
35
|
bytecodeCachingOptions,
|
|
36
36
|
forceStreamingRuntime,
|
|
37
37
|
enableUncompressedLambdaSizeCheck,
|
|
38
|
-
trace = defaultTrace
|
|
38
|
+
trace = defaultTrace,
|
|
39
|
+
createZip: createZipOverride,
|
|
40
|
+
validateZip
|
|
39
41
|
} = params;
|
|
40
42
|
const encryptedEnv = (0, import_get_encrypted_env_file.getEncryptedEnv)(
|
|
41
43
|
encryptedEnvFilename,
|
|
@@ -58,11 +60,43 @@ async function finalizeLambda(params) {
|
|
|
58
60
|
);
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
|
-
const
|
|
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
|
+
}
|
|
63
93
|
lambda.environment = {
|
|
64
94
|
...lambda.environment,
|
|
65
|
-
...(0, import_get_lambda_environment.getLambdaEnvironment)(
|
|
95
|
+
...(0, import_get_lambda_environment.getLambdaEnvironment)(
|
|
96
|
+
lambda,
|
|
97
|
+
zipResult.buffer ?? { byteLength: zipResult.size },
|
|
98
|
+
bytecodeCachingOptions
|
|
99
|
+
)
|
|
66
100
|
};
|
|
67
101
|
const streamingResult = await (0, import_get_lambda_supports_streaming.getLambdaSupportsStreaming)(
|
|
68
102
|
lambda,
|
|
@@ -70,8 +104,10 @@ async function finalizeLambda(params) {
|
|
|
70
104
|
);
|
|
71
105
|
lambda.supportsResponseStreaming = streamingResult.supportsStreaming;
|
|
72
106
|
return {
|
|
73
|
-
buffer,
|
|
74
|
-
|
|
107
|
+
buffer: zipResult.buffer,
|
|
108
|
+
zipPath: zipResult.zipPath,
|
|
109
|
+
digest: zipResult.digest,
|
|
110
|
+
size: zipResult.size,
|
|
75
111
|
uncompressedBytes,
|
|
76
112
|
streamingError: streamingResult.error
|
|
77
113
|
};
|
|
@@ -83,7 +83,7 @@ async function get_ignore_filter_default(downloadPath, rootDirectory) {
|
|
|
83
83
|
}
|
|
84
84
|
const ignoreFilter = (0, import_ignore.default)().add(clearRelative(ignoreContents[0]));
|
|
85
85
|
return function(p) {
|
|
86
|
-
if (p === "now.json" || p === "vercel.json")
|
|
86
|
+
if (p === "now.json" || p === "vercel.json" || p === "vercel.toml")
|
|
87
87
|
return false;
|
|
88
88
|
return ignoreFilter.test(p).ignored;
|
|
89
89
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -47,5 +47,5 @@ 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
49
|
export { collectUncompressedSize } from './collect-uncompressed-size';
|
|
50
|
-
export { finalizeLambda, type FinalizeLambdaParams, type FinalizeLambdaResult, type TraceFn, } from './finalize-lambda';
|
|
50
|
+
export { finalizeLambda, type CreateZipResult, type CreateZipFn, type FinalizeLambdaParams, type FinalizeLambdaResult, type TraceFn, } from './finalize-lambda';
|
|
51
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
|
@@ -23233,7 +23233,7 @@ async function get_ignore_filter_default(downloadPath, rootDirectory) {
|
|
|
23233
23233
|
}
|
|
23234
23234
|
const ignoreFilter = (0, import_ignore.default)().add(clearRelative(ignoreContents[0]));
|
|
23235
23235
|
return function(p) {
|
|
23236
|
-
if (p === "now.json" || p === "vercel.json")
|
|
23236
|
+
if (p === "now.json" || p === "vercel.json" || p === "vercel.toml")
|
|
23237
23237
|
return false;
|
|
23238
23238
|
return ignoreFilter.test(p).ignored;
|
|
23239
23239
|
};
|
|
@@ -24486,7 +24486,9 @@ async function finalizeLambda(params) {
|
|
|
24486
24486
|
bytecodeCachingOptions,
|
|
24487
24487
|
forceStreamingRuntime,
|
|
24488
24488
|
enableUncompressedLambdaSizeCheck,
|
|
24489
|
-
trace = defaultTrace
|
|
24489
|
+
trace = defaultTrace,
|
|
24490
|
+
createZip: createZipOverride,
|
|
24491
|
+
validateZip
|
|
24490
24492
|
} = params;
|
|
24491
24493
|
const encryptedEnv = getEncryptedEnv(
|
|
24492
24494
|
encryptedEnvFilename,
|
|
@@ -24509,11 +24511,43 @@ async function finalizeLambda(params) {
|
|
|
24509
24511
|
);
|
|
24510
24512
|
}
|
|
24511
24513
|
}
|
|
24512
|
-
const
|
|
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
|
+
}
|
|
24514
24544
|
lambda.environment = {
|
|
24515
24545
|
...lambda.environment,
|
|
24516
|
-
...getLambdaEnvironment(
|
|
24546
|
+
...getLambdaEnvironment(
|
|
24547
|
+
lambda,
|
|
24548
|
+
zipResult.buffer ?? { byteLength: zipResult.size },
|
|
24549
|
+
bytecodeCachingOptions
|
|
24550
|
+
)
|
|
24517
24551
|
};
|
|
24518
24552
|
const streamingResult = await getLambdaSupportsStreaming(
|
|
24519
24553
|
lambda,
|
|
@@ -24521,8 +24555,10 @@ async function finalizeLambda(params) {
|
|
|
24521
24555
|
);
|
|
24522
24556
|
lambda.supportsResponseStreaming = streamingResult.supportsStreaming;
|
|
24523
24557
|
return {
|
|
24524
|
-
buffer,
|
|
24525
|
-
|
|
24558
|
+
buffer: zipResult.buffer,
|
|
24559
|
+
zipPath: zipResult.zipPath,
|
|
24560
|
+
digest: zipResult.digest,
|
|
24561
|
+
size: zipResult.size,
|
|
24526
24562
|
uncompressedBytes,
|
|
24527
24563
|
streamingError: streamingResult.error
|
|
24528
24564
|
};
|
|
@@ -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 {};
|