vercel 59.5.0 → 59.6.2
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/dist/chunks/{add-W3FFMTX4.js → add-4GQZ22ZN.js} +11 -11
- package/dist/chunks/{add-MH3WV6PV.js → add-HJSEM4YJ.js} +11 -11
- package/dist/chunks/{add-Z5FM6TFI.js → add-SIGUSM3Y.js} +12 -12
- package/dist/chunks/{build-VYYFBJL7.js → build-XOMJDX4M.js} +11 -11
- package/dist/chunks/{chunk-NSU2BTRS.js → chunk-2O5J3KMT.js} +4 -4
- package/dist/chunks/{chunk-RZ5NP6HN.js → chunk-2YRAWYGE.js} +1 -1
- package/dist/chunks/{chunk-JNU3DTEV.js → chunk-37V5P4VO.js} +9 -9
- package/dist/chunks/{chunk-LLM3ZNXJ.js → chunk-3F5EGINT.js} +2 -2
- package/dist/chunks/{chunk-KQRVZWJU.js → chunk-3T7WSWZH.js} +1 -1
- package/dist/chunks/{chunk-R6IGDGX3.js → chunk-5XECIWME.js} +1 -1
- package/dist/chunks/{chunk-AWSLWAOC.js → chunk-6JPVTPTU.js} +3 -3
- package/dist/chunks/{chunk-M3OSDZPY.js → chunk-6M2KZUED.js} +16 -7
- package/dist/chunks/{chunk-HT2XWSAJ.js → chunk-7AEEQOD4.js} +2 -29
- package/dist/chunks/{chunk-QG4PCM45.js → chunk-7HE63HCR.js} +102 -15
- package/dist/chunks/{chunk-V4YLY44R.js → chunk-7R6M3BHM.js} +2 -2
- package/dist/chunks/{chunk-XBN2O34P.js → chunk-7ST552E3.js} +17 -4
- package/dist/chunks/{chunk-CV4S27SS.js → chunk-ASBP32T6.js} +1 -1
- package/dist/chunks/{chunk-CQJRLNTX.js → chunk-AYLY3ZVL.js} +2 -2
- package/dist/chunks/{chunk-AWCID36T.js → chunk-BMKU5KEL.js} +1 -1
- package/dist/chunks/{chunk-UUVMIXT4.js → chunk-DE7MBNHQ.js} +4 -4
- package/dist/chunks/{chunk-YIHOS3ZF.js → chunk-FRAXI2WT.js} +1 -1
- package/dist/chunks/{chunk-FA3MO56Q.js → chunk-FRZULOVH.js} +5 -5
- package/dist/chunks/{chunk-7XX4ZEOV.js → chunk-FWKSJYDV.js} +1 -1
- package/dist/chunks/{chunk-OHER4DGX.js → chunk-FXD67VN5.js} +25 -9
- package/dist/chunks/{chunk-TIWAL2YU.js → chunk-GISTGGBO.js} +6 -6
- package/dist/chunks/{chunk-CSCSGSQG.js → chunk-GZQQNLF5.js} +5 -5
- package/dist/chunks/{chunk-PIMIKY4X.js → chunk-IJ4X426J.js} +1 -1
- package/dist/chunks/{chunk-TDXNNIZ6.js → chunk-JH4WQRIU.js} +2 -2
- package/dist/chunks/{chunk-TVXCXIRO.js → chunk-L3UXB2CW.js} +1 -1
- package/dist/chunks/{chunk-4JTF6RD7.js → chunk-LXZVOR6F.js} +4 -4
- package/dist/chunks/{chunk-L7CEMAJG.js → chunk-NGGLYKNU.js} +27 -5
- package/dist/chunks/{chunk-VWYNSJXI.js → chunk-NGNN6WF2.js} +8 -8
- package/dist/chunks/{chunk-GGPE5377.js → chunk-O26N2UPI.js} +1 -1
- package/dist/chunks/{chunk-5LX2JDZP.js → chunk-O75LSD3C.js} +1 -1
- package/dist/chunks/{chunk-MRMNMFMD.js → chunk-PRH6KRUT.js} +1 -1
- package/dist/chunks/{chunk-OX7KI3LF.js → chunk-QFAS4OVW.js} +18 -0
- package/dist/chunks/{chunk-PBHBX6UL.js → chunk-R5PULMHT.js} +3 -3
- package/dist/chunks/{chunk-PPUWG2UB.js → chunk-SF3AYAIF.js} +58 -25
- package/dist/chunks/{chunk-TAZ5ZAKG.js → chunk-SWI6F4X3.js} +2 -2
- package/dist/chunks/{chunk-ZKUHCL6O.js → chunk-V3MDDR2X.js} +5 -5
- package/dist/chunks/{chunk-E6LFKMI2.js → chunk-VJ5NAOWB.js} +791 -122
- package/dist/chunks/{chunk-G75NFPIT.js → chunk-WNAKOXGK.js} +1 -1
- package/dist/chunks/{chunk-JJQP3PYM.js → chunk-WZ2S3A2A.js} +5 -5
- package/dist/chunks/{chunk-CYNB6LL4.js → chunk-XNFHNTS2.js} +1 -1
- package/dist/chunks/{chunk-47VQ6H2S.js → chunk-YJKZQEHS.js} +2 -2
- package/dist/chunks/{chunk-GUWPUX2Y.js → chunk-ZNMTDLYH.js} +4 -4
- package/dist/chunks/{chunk-VLPLCJZC.js → chunk-ZSFEACZU.js} +1 -1
- package/dist/chunks/{clear-TNGRDA7D.js → clear-BWT2FJY4.js} +11 -11
- package/dist/chunks/{compile-vercel-config-ERLXKKWW.js → compile-vercel-config-DGM4NISW.js} +7 -7
- package/dist/chunks/{config-H22EE765.js → config-NJAN3RMU.js} +11 -11
- package/dist/chunks/{config-7EDKML5Q.js → config-RSE6Z4LB.js} +9 -9
- package/dist/chunks/{constants-YMCRE6IG.js → constants-WEQVJSYS.js} +1 -1
- package/dist/chunks/{delete-Q4S5F2AI.js → delete-LROBRBAH.js} +9 -9
- package/dist/chunks/{delete-LORYIZHY.js → delete-SSL2PK2F.js} +8 -8
- package/dist/chunks/{disable-HKWCBDJC.js → disable-ASG5JDZR.js} +8 -8
- package/dist/chunks/{discard-UCCRF2JQ.js → discard-PV47B6IL.js} +8 -8
- package/dist/chunks/{edit-AWL35PYQ.js → edit-5ATYIOLX.js} +10 -10
- package/dist/chunks/{edit-6IM6VRBR.js → edit-REI7HXGG.js} +10 -10
- package/dist/chunks/{enable-GN3D3L3V.js → enable-LZXL7XAG.js} +8 -8
- package/dist/chunks/{exec-CNBOV577.js → exec-XH4K34JM.js} +3 -3
- package/dist/chunks/{export-HHRVFALV.js → export-ZAZFQU2E.js} +8 -8
- package/dist/chunks/{image-4DCU4VPP.js → image-QPHN5V7L.js} +6 -6
- package/dist/chunks/{import-builders-DVG3HOTF.js → import-builders-W3YE2V6A.js} +9 -9
- package/dist/chunks/{inspect-TUW67CFZ.js → inspect-BFGK72WY.js} +10 -10
- package/dist/chunks/{inspect-TGOJDKIT.js → inspect-FRXJRM6T.js} +9 -9
- package/dist/chunks/{inspect-B3OWUFLH.js → inspect-RDMC2Z3Q.js} +11 -11
- package/dist/chunks/{inspect-VPME6UC7.js → inspect-SJEZVGPK.js} +11 -11
- package/dist/chunks/{inspect-VLGKNHJW.js → inspect-SSOM3FXS.js} +11 -11
- package/dist/chunks/{list-K552ITMK.js → list-2HTR7Q3J.js} +9 -9
- package/dist/chunks/{list-TK2JO7BK.js → list-PHDUZVMR.js} +8 -8
- package/dist/chunks/{list-2DPKDHRV.js → list-W33GXKDA.js} +10 -10
- package/dist/chunks/{login-HRWEKW5P.js → login-JWAFHVDG.js} +21 -12
- package/dist/chunks/{ls-M5TYGFP5.js → ls-3AN2DZHN.js} +11 -11
- package/dist/chunks/{ls-YIF3KLF3.js → ls-3MH2OCP3.js} +11 -11
- package/dist/chunks/{ls-TM6NTZEB.js → ls-D2POUHI7.js} +9 -9
- package/dist/chunks/{ls-JSV2WZVF.js → ls-KDFU224B.js} +11 -11
- package/dist/chunks/{ls-IOXGXEY4.js → ls-KX2VBOGV.js} +10 -10
- package/dist/chunks/{ls-O2WYF5UL.js → ls-RWKNJQNT.js} +11 -11
- package/dist/chunks/{open-FWAVEWGU.js → open-IEYRB6RL.js} +9 -9
- package/dist/chunks/{permissions-DPFYL47Z.js → permissions-ZWZUMEHR.js} +7 -7
- package/dist/chunks/{publish-63CGFKQR.js → publish-UWZYBDHK.js} +8 -8
- package/dist/chunks/{push-T5ZTBW3P.js → push-IAEQ3FBF.js} +11 -11
- package/dist/chunks/{query-B6O3EMEV.js → query-NNOZYSED.js} +11 -11
- package/dist/chunks/{reorder-ANV4NMKH.js → reorder-TKBM244W.js} +8 -8
- package/dist/chunks/{reply-C73KGOCG.js → reply-FLBSBMTW.js} +10 -10
- package/dist/chunks/{resolve-IHSIVPEE.js → resolve-GJYPMWUE.js} +9 -9
- package/dist/chunks/{restore-GSUNXP2O.js → restore-PNI3TM3U.js} +8 -8
- package/dist/chunks/{rm-4O74PS4Q.js → rm-76CSSSSV.js} +11 -11
- package/dist/chunks/{rm-M7IJC2WZ.js → rm-FN7LTIIL.js} +11 -11
- package/dist/chunks/{rm-YDTK5ESZ.js → rm-FTE33UHE.js} +10 -10
- package/dist/chunks/{rm-RV5SQFQA.js → rm-FXA5DLXQ.js} +11 -13
- package/dist/chunks/{rm-PRINF4OU.js → rm-PGJ4KR6U.js} +11 -11
- package/dist/chunks/{routes-SZI2G4SE.js → routes-2OLIBRYX.js} +3 -3
- package/dist/chunks/{rule-inspect-ZZC53FLP.js → rule-inspect-LJIGPTWS.js} +10 -10
- package/dist/chunks/{rules-SAOSSGFI.js → rules-6BMNO6M5.js} +10 -10
- package/dist/chunks/{schema-23ZFAKDU.js → schema-45SJNY5L.js} +4 -4
- package/dist/chunks/{schema-2Q3QRMRO.js → schema-HATXEQDP.js} +9 -9
- package/dist/chunks/{set-L47ZCZBJ.js → set-C3UQUQ42.js} +9 -9
- package/dist/chunks/{tags-2TWLM77N.js → tags-BTVDROFG.js} +5 -5
- package/dist/chunks/{types-G3PEUIJH.js → types-JGANJ5EQ.js} +3 -3
- package/dist/chunks/{update-SZH2VBD6.js → update-B6PSOHUW.js} +12 -12
- package/dist/commands/build/builder-worker.cjs +281 -0
- package/dist/commands/build/index.js +690 -235
- package/dist/commands/deploy/index.js +103 -31
- package/dist/commands/dev/index.js +669 -140
- package/dist/commands/env/index.js +1167 -542
- package/dist/commands/link/index.js +10 -10
- package/dist/commands/list/index.js +10 -10
- package/dist/commands-bulk.js +1978 -953
- package/dist/index.js +18 -18
- package/dist/version.mjs +1 -1
- package/package.json +47 -47
- package/dist/chunks/chunk-HGRWPPYB.js +0 -18
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
toRule,
|
|
24
24
|
writeConfigJson,
|
|
25
25
|
writeSamplingRules
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-V3MDDR2X.js";
|
|
27
27
|
import "./chunk-5GGUB4EO.js";
|
|
28
28
|
import {
|
|
29
29
|
validateJsonOutput
|
|
@@ -36,22 +36,22 @@ import {
|
|
|
36
36
|
} from "./chunk-GY5I4AYD.js";
|
|
37
37
|
import {
|
|
38
38
|
help
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-2YRAWYGE.js";
|
|
40
|
+
import "./chunk-VJ5NAOWB.js";
|
|
41
|
+
import "./chunk-FXD67VN5.js";
|
|
42
42
|
import {
|
|
43
43
|
TelemetryClient
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import "./chunk-
|
|
44
|
+
} from "./chunk-XNFHNTS2.js";
|
|
45
|
+
import "./chunk-NGGLYKNU.js";
|
|
46
46
|
import "./chunk-GGP5R3FU.js";
|
|
47
47
|
import {
|
|
48
48
|
printError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-AYLY3ZVL.js";
|
|
50
50
|
import {
|
|
51
51
|
parseArguments
|
|
52
52
|
} from "./chunk-57RHXXXG.js";
|
|
53
53
|
import "./chunk-RKDCNQ4S.js";
|
|
54
|
-
import "./chunk-
|
|
54
|
+
import "./chunk-BMKU5KEL.js";
|
|
55
55
|
import {
|
|
56
56
|
getCommandName,
|
|
57
57
|
getCommandNamePlain,
|
|
@@ -61,7 +61,7 @@ import "./chunk-P4QNYOFB.js";
|
|
|
61
61
|
import "./chunk-52QYYTM5.js";
|
|
62
62
|
import {
|
|
63
63
|
output_manager_default
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-QFAS4OVW.js";
|
|
65
65
|
import {
|
|
66
66
|
require_source
|
|
67
67
|
} from "./chunk-S7KYDPEM.js";
|
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
AGENT_REASON,
|
|
15
15
|
buildCommandWithGlobalFlags,
|
|
16
16
|
outputAgentError
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-NGGLYKNU.js";
|
|
18
|
+
import "./chunk-BMKU5KEL.js";
|
|
19
19
|
import "./chunk-Q2DGFCO7.js";
|
|
20
20
|
import "./chunk-P4QNYOFB.js";
|
|
21
21
|
import {
|
|
22
22
|
output_manager_default
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QFAS4OVW.js";
|
|
24
24
|
import "./chunk-S7KYDPEM.js";
|
|
25
25
|
import "./chunk-TZ2YI2VH.js";
|
|
26
26
|
|
|
@@ -53,9 +53,9 @@ async function tags(client, argv, telemetry) {
|
|
|
53
53
|
}
|
|
54
54
|
switch (subcommand) {
|
|
55
55
|
case "ls":
|
|
56
|
-
return (await import("./ls-
|
|
56
|
+
return (await import("./ls-3MH2OCP3.js")).default(client, args, telemetry);
|
|
57
57
|
case "inspect":
|
|
58
|
-
return (await import("./inspect-
|
|
58
|
+
return (await import("./inspect-RDMC2Z3Q.js")).default(client, args, telemetry);
|
|
59
59
|
default:
|
|
60
60
|
output_manager_default.error(`Unhandled tags subcommand: ${subcommand}`);
|
|
61
61
|
return 1;
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-4KD5BYHB.js";
|
|
13
13
|
import {
|
|
14
14
|
printError
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-AYLY3ZVL.js";
|
|
16
16
|
import {
|
|
17
17
|
parseArguments
|
|
18
18
|
} from "./chunk-57RHXXXG.js";
|
|
@@ -21,14 +21,14 @@ import {
|
|
|
21
21
|
} from "./chunk-RKDCNQ4S.js";
|
|
22
22
|
import {
|
|
23
23
|
isAPIError
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-BMKU5KEL.js";
|
|
25
25
|
import {
|
|
26
26
|
getFlagsSpecification
|
|
27
27
|
} from "./chunk-Q2DGFCO7.js";
|
|
28
28
|
import "./chunk-P4QNYOFB.js";
|
|
29
29
|
import {
|
|
30
30
|
output_manager_default
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QFAS4OVW.js";
|
|
32
32
|
import {
|
|
33
33
|
require_source
|
|
34
34
|
} from "./chunk-S7KYDPEM.js";
|
|
@@ -8,16 +8,16 @@ import {
|
|
|
8
8
|
parseCustomAlertQueryBody,
|
|
9
9
|
resolveCustomAlertProjectName,
|
|
10
10
|
setMissingCustomAlertProjectScope
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GZQQNLF5.js";
|
|
12
12
|
import {
|
|
13
13
|
emitRulesArgParseError,
|
|
14
14
|
handleRulesApiError,
|
|
15
15
|
parseRulesFlagsAndScope,
|
|
16
16
|
rulesItemPath
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-R5PULMHT.js";
|
|
18
|
+
import "./chunk-2O5J3KMT.js";
|
|
19
|
+
import "./chunk-3T7WSWZH.js";
|
|
20
|
+
import "./chunk-LXZVOR6F.js";
|
|
21
21
|
import "./chunk-AINIBIP4.js";
|
|
22
22
|
import {
|
|
23
23
|
validateJsonOutput
|
|
@@ -25,25 +25,25 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
rulesUpdateSubcommand
|
|
27
27
|
} from "./chunk-XM3LOQIX.js";
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-VJ5NAOWB.js";
|
|
29
|
+
import "./chunk-FXD67VN5.js";
|
|
30
|
+
import "./chunk-XNFHNTS2.js";
|
|
31
31
|
import {
|
|
32
32
|
AGENT_REASON,
|
|
33
33
|
buildCommandWithGlobalFlags,
|
|
34
34
|
outputAgentError
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-NGGLYKNU.js";
|
|
36
36
|
import "./chunk-GGP5R3FU.js";
|
|
37
37
|
import {
|
|
38
38
|
printError
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-AYLY3ZVL.js";
|
|
40
40
|
import {
|
|
41
41
|
parseArguments
|
|
42
42
|
} from "./chunk-57RHXXXG.js";
|
|
43
43
|
import "./chunk-RKDCNQ4S.js";
|
|
44
44
|
import {
|
|
45
45
|
isAPIError
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-BMKU5KEL.js";
|
|
47
47
|
import {
|
|
48
48
|
getFlagsSpecification,
|
|
49
49
|
packageName
|
|
@@ -52,7 +52,7 @@ import "./chunk-P4QNYOFB.js";
|
|
|
52
52
|
import "./chunk-52QYYTM5.js";
|
|
53
53
|
import {
|
|
54
54
|
output_manager_default
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-QFAS4OVW.js";
|
|
56
56
|
import "./chunk-S7KYDPEM.js";
|
|
57
57
|
import "./chunk-TZ2YI2VH.js";
|
|
58
58
|
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forked worker that runs a single builder's `build()` (and `diagnostics()`) in its own
|
|
3
|
+
* process for `vc build`. Running each build out-of-process gives it isolated stdout/stderr
|
|
4
|
+
* — which the parent pipes and can prefix per line with the service name — and isolated
|
|
5
|
+
* env, which is a prerequisite for running builds in parallel.
|
|
6
|
+
*
|
|
7
|
+
* This is modeled on the `vc dev` worker (../dev/builder-worker.cjs) and shares its IPC
|
|
8
|
+
* contract (`ready` / `build` / `buildResult`), but it serializes Lambda/EdgeFunction outputs
|
|
9
|
+
* by preserving their `files` map (as FileFsRef/FileBlob descriptors) instead of zipping them.
|
|
10
|
+
* `vc build`'s writeLambda relies on `lambda.files` for the FileFsRef-by-reference optimization,
|
|
11
|
+
* the `filePathMap`, and `standalone` symlink handling — all of which are lost if we ship only
|
|
12
|
+
* a `zipBuffer` the way the dev worker does.
|
|
13
|
+
*
|
|
14
|
+
* Like the dev worker, this file is copied verbatim into `dist` next to the compiled `build`
|
|
15
|
+
* command, so it must only `require` `@vercel/build-utils` and Node built-ins.
|
|
16
|
+
*/
|
|
17
|
+
const { FileFsRef, Span } = require('@vercel/build-utils');
|
|
18
|
+
const fs = require('node:fs');
|
|
19
|
+
const path = require('node:path');
|
|
20
|
+
const os = require('node:os');
|
|
21
|
+
const crypto = require('node:crypto');
|
|
22
|
+
|
|
23
|
+
// Trace events produced by the builder's own spans (children of buildOptions.span) are collected
|
|
24
|
+
// here and shipped back to the parent, which reports them under its `vc.builder` span so forked
|
|
25
|
+
// builds keep full trace fidelity. Included on both success and error messages so a failed build
|
|
26
|
+
// still contributes the spans it managed to record. Emptied after each send so a later phase
|
|
27
|
+
// (the deferred pre-deploy step) ships only the events it newly recorded.
|
|
28
|
+
let collectedTraceEvents = [];
|
|
29
|
+
const traceReporter = { report: event => collectedTraceEvents.push(event) };
|
|
30
|
+
// Take the events collected so far and reset the buffer, so the next send starts fresh.
|
|
31
|
+
function drainTraceEvents() {
|
|
32
|
+
const events = collectedTraceEvents;
|
|
33
|
+
collectedTraceEvents = [];
|
|
34
|
+
return events;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Above this size a FileBlob's Buffer is written to a temp file rather than sent inline over
|
|
38
|
+
// IPC. Even under structured-clone serialization the whole Buffer is copied into a single IPC
|
|
39
|
+
// message; spilling very large blobs to disk bounds that per-message memory spike.
|
|
40
|
+
const BLOB_FILE_THRESHOLD = 256 * 1024 * 1024; // 256MB
|
|
41
|
+
|
|
42
|
+
process.on('unhandledRejection', err => {
|
|
43
|
+
// biome-ignore lint/suspicious/noConsole: intentional console usage
|
|
44
|
+
console.error('Exiting builder due to build error:');
|
|
45
|
+
// biome-ignore lint/suspicious/noConsole: intentional console usage
|
|
46
|
+
console.error(err);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// A builder may register a pre-deploy callback during build(). The CLI runs pre-deploys only
|
|
51
|
+
// after every build succeeds, so we hold the callback here and run it when the parent sends a
|
|
52
|
+
// `runPreDeploy` message, keeping the builder-computed env the callback captured.
|
|
53
|
+
let preDeployCallback;
|
|
54
|
+
|
|
55
|
+
// Key under which processMessage stashes the diagnostics it collected for a build that threw, so
|
|
56
|
+
// the error path in onMessage can ship them. A Symbol, so `serializeError` (which copies own
|
|
57
|
+
// property *names*) can't fold it into the error the parent writes into builds.json.
|
|
58
|
+
const DIAGNOSTICS = Symbol('diagnostics');
|
|
59
|
+
|
|
60
|
+
process.on('message', onMessage);
|
|
61
|
+
|
|
62
|
+
// Convert an Error into a plain object with all its properties enumerable. Structured-clone IPC
|
|
63
|
+
// reconstructs a native Error but keeps only `name`/`message`/`stack` — custom props a builder
|
|
64
|
+
// sets (e.g. NowBuildError's `code`/`link`, which the parent writes into builds.json) would be
|
|
65
|
+
// dropped. A plain object clones losslessly; the parent rebuilds an Error from it.
|
|
66
|
+
function serializeError(err) {
|
|
67
|
+
if (!err || typeof err !== 'object') return err;
|
|
68
|
+
const plain = { name: err.name, message: err.message, stack: err.stack };
|
|
69
|
+
for (const key of Object.getOwnPropertyNames(err)) {
|
|
70
|
+
plain[key] = err[key];
|
|
71
|
+
}
|
|
72
|
+
return plain;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function onMessage(message) {
|
|
76
|
+
if (message && message.type === 'runPreDeploy') {
|
|
77
|
+
runPreDeploy();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
processMessage(message).catch(err => {
|
|
81
|
+
process.removeListener('message', onMessage);
|
|
82
|
+
process.send(
|
|
83
|
+
{
|
|
84
|
+
type: 'buildResult',
|
|
85
|
+
error: serializeError(err),
|
|
86
|
+
// A failed build is exactly when diagnostics matter most, so ship whatever the builder
|
|
87
|
+
// recorded before it threw. `processMessage` collects them in a `finally` and stashes
|
|
88
|
+
// them on the error (see DIAGNOSTICS) on its way out.
|
|
89
|
+
diagnostics: err?.[DIAGNOSTICS],
|
|
90
|
+
traceEvents: drainTraceEvents(),
|
|
91
|
+
},
|
|
92
|
+
() => process.exit(1)
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function runPreDeploy() {
|
|
98
|
+
Promise.resolve()
|
|
99
|
+
.then(() => preDeployCallback?.())
|
|
100
|
+
.then(
|
|
101
|
+
() =>
|
|
102
|
+
process.send(
|
|
103
|
+
{ type: 'preDeployResult', traceEvents: drainTraceEvents() },
|
|
104
|
+
() => process.exit(0)
|
|
105
|
+
),
|
|
106
|
+
err => {
|
|
107
|
+
process.send(
|
|
108
|
+
{
|
|
109
|
+
type: 'preDeployResult',
|
|
110
|
+
error: serializeError(err),
|
|
111
|
+
traceEvents: drainTraceEvents(),
|
|
112
|
+
},
|
|
113
|
+
() => process.exit(1)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Re-prototype a plain object sent over IPC back into a FileFsRef instance.
|
|
120
|
+
function rehydrateFile(obj) {
|
|
121
|
+
return Object.assign(Object.create(FileFsRef.prototype), obj);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Serialize a Files map for transport. FileFsRef entries are cheap path references and pass
|
|
125
|
+
// through as-is; FileBlob entries carry a Buffer, which is left inline unless it exceeds the
|
|
126
|
+
// threshold, in which case it is spilled to a temp file the parent reads and unlinks.
|
|
127
|
+
function serializeFiles(files) {
|
|
128
|
+
if (!files) return files;
|
|
129
|
+
for (const name of Object.keys(files)) {
|
|
130
|
+
const file = files[name];
|
|
131
|
+
if (file && file.type === 'FileBlob' && Buffer.isBuffer(file.data)) {
|
|
132
|
+
if (file.data.length > BLOB_FILE_THRESHOLD) {
|
|
133
|
+
const tmp = path.join(
|
|
134
|
+
os.tmpdir(),
|
|
135
|
+
`vercel-build-blob-${crypto.randomBytes(8).toString('hex')}`
|
|
136
|
+
);
|
|
137
|
+
fs.writeFileSync(tmp, file.data);
|
|
138
|
+
file.dataPath = tmp;
|
|
139
|
+
delete file.data;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return files;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Collect diagnostics from the same builder instance that just built. diagnostics() returns a
|
|
147
|
+
// Files map (e.g. { 'package-manifest.json': FileBlob }); serialize it like build outputs so the
|
|
148
|
+
// parent can validate/write it. Traced here in the worker (the span rides back with the rest), and
|
|
149
|
+
// failures must not propagate — diagnostics are best-effort and never fail (or mask) a build.
|
|
150
|
+
async function collectDiagnostics(builder, buildOptions) {
|
|
151
|
+
try {
|
|
152
|
+
const diagnostics = await buildOptions.span
|
|
153
|
+
.child('vc.builder.diagnostics')
|
|
154
|
+
.trace(
|
|
155
|
+
async () => (await builder.diagnostics?.(buildOptions)) || undefined
|
|
156
|
+
);
|
|
157
|
+
if (diagnostics) serializeFiles(diagnostics);
|
|
158
|
+
return diagnostics;
|
|
159
|
+
} catch (err) {
|
|
160
|
+
// Surface to the worker's stderr (piped/inherited to the parent) but don't fail the build.
|
|
161
|
+
// biome-ignore lint/suspicious/noConsole: intentional console usage
|
|
162
|
+
console.error(`[vc] collecting diagnostics failed: ${err}`);
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function processMessage(message) {
|
|
168
|
+
const { requirePath, buildOptions, expectsPreDeploy } = message;
|
|
169
|
+
const builder = require(requirePath);
|
|
170
|
+
|
|
171
|
+
// `files` arrive as plain objects — turn them back into FileFsRef instances the builder expects.
|
|
172
|
+
for (const name of Object.keys(buildOptions.files)) {
|
|
173
|
+
buildOptions.files[name] = rehydrateFile(buildOptions.files[name]);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Give the builder a span backed by our collecting reporter so the child spans it records are
|
|
177
|
+
// shipped back to the parent. The parent dropped the real Span (a class instance can't cross
|
|
178
|
+
// IPC), so we reconstruct one here; it has no parent id — the parent reparents this root under
|
|
179
|
+
// its own `vc.builder` span via Span.reportChildEvents when the events are reported.
|
|
180
|
+
buildOptions.span = new Span({
|
|
181
|
+
name: 'vc.builder.worker',
|
|
182
|
+
reporter: traceReporter,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Capture any pre-deploy callback the builder registers during build(); the parent triggers
|
|
186
|
+
// it later via a `runPreDeploy` message. Only wired when the parent said a pre-deploy command
|
|
187
|
+
// is configured for this build.
|
|
188
|
+
if (expectsPreDeploy) {
|
|
189
|
+
buildOptions.registerPreDeploy = callback => {
|
|
190
|
+
preDeployCallback = callback;
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Build in a try/finally so diagnostics are collected on both outcomes, mirroring `doBuild`'s
|
|
195
|
+
// handling on the in-process path: a build that threw is exactly when its diagnostics matter
|
|
196
|
+
// most.
|
|
197
|
+
let result;
|
|
198
|
+
let diagnostics;
|
|
199
|
+
let buildError;
|
|
200
|
+
try {
|
|
201
|
+
result = await builder.build(buildOptions);
|
|
202
|
+
} catch (err) {
|
|
203
|
+
buildError = err;
|
|
204
|
+
throw err;
|
|
205
|
+
} finally {
|
|
206
|
+
diagnostics = await collectDiagnostics(builder, buildOptions);
|
|
207
|
+
// A failed build has no result message to carry the diagnostics, so stash them on the error
|
|
208
|
+
// for `onMessage` to ship. Symbol-keyed, so `serializeError` (which copies own property
|
|
209
|
+
// *names*) can't fold them into the error the parent writes into builds.json.
|
|
210
|
+
if (buildError && typeof buildError === 'object') {
|
|
211
|
+
Object.defineProperty(buildError, DIAGNOSTICS, { value: diagnostics });
|
|
212
|
+
}
|
|
213
|
+
// Stop the worker root span so it (and its recorded children) are collected before the events
|
|
214
|
+
// are drained and shipped for the parent to report under its `vc.builder` span.
|
|
215
|
+
buildOptions.span.stop();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Locate the concrete V2/V3 result and its version WITHOUT unwrapping the wire payload:
|
|
219
|
+
// the parent (and writeBuildResult) still expect a BuildResultVX wrapper for
|
|
220
|
+
// `builder.version === -1` builders, so we serialize the inner outputs in place and send
|
|
221
|
+
// the original `result` back untouched in shape.
|
|
222
|
+
let effectiveVersion = builder.version;
|
|
223
|
+
let concrete = result;
|
|
224
|
+
if (builder.version === -1) {
|
|
225
|
+
effectiveVersion = result.resultVersion;
|
|
226
|
+
concrete = result.result;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// The IPC channel uses `serialization: 'advanced'` (V8 structured clone), which preserves
|
|
230
|
+
// Buffers, cycles (e.g. `@vercel/next`'s `result.childProcesses`), and shared object identity
|
|
231
|
+
// — the same Lambda referenced by many V2 keys or many `Prerender.lambda` fields arrives as
|
|
232
|
+
// ONE instance, which writeBuildResult relies on for symlink dedup. So the only remaining job
|
|
233
|
+
// here is spilling oversized FileBlob Buffers to temp files (see serializeFiles). We still walk
|
|
234
|
+
// every reachable `files` map, using `seen` so a shared Lambda is spilled at most once.
|
|
235
|
+
const seen = new Set();
|
|
236
|
+
const serializeOutput = output => {
|
|
237
|
+
if (!output || typeof output !== 'object' || seen.has(output)) return;
|
|
238
|
+
seen.add(output);
|
|
239
|
+
if (output.type === 'Lambda' || output.type === 'EdgeFunction') {
|
|
240
|
+
serializeFiles(output.files);
|
|
241
|
+
} else if (output.type === 'Prerender') {
|
|
242
|
+
// Prerender wraps a `lambda` (with its own `files`) and a `fallback` file.
|
|
243
|
+
if (output.lambda) serializeOutput(output.lambda);
|
|
244
|
+
if (output.fallback) serializeFiles({ fallback: output.fallback });
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// Build Output API results (`{ buildOutputPath }`) have no in-memory `output` to serialize —
|
|
249
|
+
// their outputs live on disk and the parent reads them from there.
|
|
250
|
+
if (concrete.output) {
|
|
251
|
+
if (effectiveVersion === 3) {
|
|
252
|
+
serializeOutput(concrete.output);
|
|
253
|
+
} else {
|
|
254
|
+
for (const value of Object.values(concrete.output)) {
|
|
255
|
+
serializeOutput(value);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// With a pending pre-deploy the worker stays alive to run the callback (which holds the
|
|
261
|
+
// builder-computed env) when the parent later sends `runPreDeploy`; the parent tears the
|
|
262
|
+
// worker down once done. Without one, the parent kills the worker as soon as it has the result.
|
|
263
|
+
// Drain the collected events here so the deferred pre-deploy step ships only what it records.
|
|
264
|
+
const hasPreDeploy = Boolean(preDeployCallback);
|
|
265
|
+
process.send({
|
|
266
|
+
type: 'buildResult',
|
|
267
|
+
result,
|
|
268
|
+
// The concrete result's shape (single V3 output vs. a V2 map of named outputs) can't be
|
|
269
|
+
// inferred reliably from the payload — a V2 map may legitimately hold a key named `type`
|
|
270
|
+
// — so tell the parent which one it is instead of making it guess.
|
|
271
|
+
outputVersion: effectiveVersion,
|
|
272
|
+
diagnostics,
|
|
273
|
+
hasPreDeploy,
|
|
274
|
+
// Builders share state through `meta` (e.g. runNpmInstall's dedup set). This worker had a
|
|
275
|
+
// structured-clone copy, so send it back for the parent to merge into the shared meta.
|
|
276
|
+
meta: buildOptions.meta,
|
|
277
|
+
traceEvents: drainTraceEvents(),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
process.send({ type: 'ready' });
|