@superblocksteam/sdk 2.0.146 → 2.0.147
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/.turbo/turbo-build.log +1 -1
- package/dist/dev-utils/dev-server-metrics.d.mts +9 -0
- package/dist/dev-utils/dev-server-metrics.d.mts.map +1 -1
- package/dist/dev-utils/dev-server-metrics.mjs +14 -0
- package/dist/dev-utils/dev-server-metrics.mjs.map +1 -1
- package/dist/dev-utils/dev-server.d.mts +28 -0
- package/dist/dev-utils/dev-server.d.mts.map +1 -1
- package/dist/dev-utils/dev-server.mjs +55 -20
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/dev-utils/dev-server.process-errors.test.d.mts +2 -0
- package/dist/dev-utils/dev-server.process-errors.test.d.mts.map +1 -0
- package/dist/dev-utils/dev-server.process-errors.test.mjs +68 -0
- package/dist/dev-utils/dev-server.process-errors.test.mjs.map +1 -0
- package/dist/dev-utils/fatal-exit.d.mts +13 -0
- package/dist/dev-utils/fatal-exit.d.mts.map +1 -1
- package/dist/dev-utils/fatal-exit.mjs +103 -0
- package/dist/dev-utils/fatal-exit.mjs.map +1 -1
- package/dist/dev-utils/fatal-exit.test.mjs +138 -1
- package/dist/dev-utils/fatal-exit.test.mjs.map +1 -1
- package/dist/dev-utils/recoverable-build-error.d.mts +31 -0
- package/dist/dev-utils/recoverable-build-error.d.mts.map +1 -0
- package/dist/dev-utils/recoverable-build-error.mjs +92 -0
- package/dist/dev-utils/recoverable-build-error.mjs.map +1 -0
- package/dist/dev-utils/recoverable-build-error.test.d.mts +2 -0
- package/dist/dev-utils/recoverable-build-error.test.d.mts.map +1 -0
- package/dist/dev-utils/recoverable-build-error.test.mjs +176 -0
- package/dist/dev-utils/recoverable-build-error.test.mjs.map +1 -0
- package/package.json +6 -6
- package/src/dev-utils/dev-server-metrics.mts +19 -0
- package/src/dev-utils/dev-server.mts +85 -31
- package/src/dev-utils/dev-server.process-errors.test.mts +103 -0
- package/src/dev-utils/fatal-exit.mts +128 -0
- package/src/dev-utils/fatal-exit.test.mts +202 -0
- package/src/dev-utils/recoverable-build-error.mts +151 -0
- package/src/dev-utils/recoverable-build-error.test.mts +236 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -124,4 +124,107 @@ export function isRecoverableShutdownError(reason) {
|
|
|
124
124
|
}
|
|
125
125
|
return RECOVERABLE_SHUTDOWN_CODES.has(code);
|
|
126
126
|
}
|
|
127
|
+
// Every alternative here has to be specific to Vite/esbuild output. A false
|
|
128
|
+
// positive marks a genuine crash recoverable, which keeps a broken pod alive
|
|
129
|
+
// and suppresses the `dev_server_fatal_exit` signal we alert on. That is why
|
|
130
|
+
// `Could not resolve` requires esbuild's quoted specifier
|
|
131
|
+
// (`Could not resolve "buffer/"`): the bare phrase also appears in package
|
|
132
|
+
// manager output ("Could not resolve dependency:") and DNS failures
|
|
133
|
+
// ("could not resolve host").
|
|
134
|
+
const VITE_BUILD_MESSAGE_MARKERS = /Could not resolve ["']|Build failed with \d+ error|Pre-transform error|Failed to resolve import|Transform failed/i;
|
|
135
|
+
/**
|
|
136
|
+
* An esbuild `BuildFailure` carries `errors: Message[]`, where each `Message`
|
|
137
|
+
* has a `text` string. Requiring that inner shape keeps the check specific:
|
|
138
|
+
* a bare `errors` array is far too common to treat as proof of a build failure.
|
|
139
|
+
*/
|
|
140
|
+
function hasEsbuildBuildFailureShape(reason) {
|
|
141
|
+
const errors = reason.errors;
|
|
142
|
+
return (Array.isArray(errors) &&
|
|
143
|
+
errors.length > 0 &&
|
|
144
|
+
errors.every((entry) => typeof entry === "object" &&
|
|
145
|
+
entry !== null &&
|
|
146
|
+
typeof entry.text === "string"));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Vite/esbuild build failures that should keep the dev-server process alive and
|
|
150
|
+
* surface through `devServerStatus.serverErrors` instead of `process.exit(1)`.
|
|
151
|
+
*
|
|
152
|
+
* Deliberately narrow: anything not positively identified as a build failure
|
|
153
|
+
* must stay fatal, so genuine crashes still exit and emit
|
|
154
|
+
* `dev_server_fatal_exit`. Rollup/Vite plugin errors are matched by their
|
|
155
|
+
* message rather than by structural fields like `id`/`plugin`/`loc`, which are
|
|
156
|
+
* far too common to be evidence of a build failure on their own.
|
|
157
|
+
*/
|
|
158
|
+
export function isViteBuildError(reason) {
|
|
159
|
+
if (typeof reason !== "object" || reason === null) {
|
|
160
|
+
if (typeof reason === "string") {
|
|
161
|
+
return VITE_BUILD_MESSAGE_MARKERS.test(reason);
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
if (hasEsbuildBuildFailureShape(reason)) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
const message = reason instanceof Error
|
|
169
|
+
? reason.message
|
|
170
|
+
: typeof reason.message === "string"
|
|
171
|
+
? reason.message
|
|
172
|
+
: undefined;
|
|
173
|
+
if (message && VITE_BUILD_MESSAGE_MARKERS.test(message)) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
/** Pull usable esbuild `Message.text` strings off any object-shaped reason. */
|
|
179
|
+
function extractEsbuildErrorTexts(reason) {
|
|
180
|
+
if (typeof reason !== "object" || reason === null) {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
const errors = reason.errors;
|
|
184
|
+
if (!Array.isArray(errors)) {
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
187
|
+
// Read defensively. `isViteBuildError` can classify on a message marker alone
|
|
188
|
+
// without re-validating the array, so entries here may be anything. This
|
|
189
|
+
// function runs inside the `uncaughtException` / `unhandledRejection`
|
|
190
|
+
// listeners before the fatal-exit line is written, and a throw there tears the
|
|
191
|
+
// process down immediately.
|
|
192
|
+
return errors
|
|
193
|
+
.map((entry) => typeof entry === "object" &&
|
|
194
|
+
entry !== null &&
|
|
195
|
+
typeof entry.text === "string"
|
|
196
|
+
? entry.text.trim()
|
|
197
|
+
: "")
|
|
198
|
+
.filter((text) => text.length > 0);
|
|
199
|
+
}
|
|
200
|
+
/** Best-effort text extraction for Vite/esbuild rejection reasons. */
|
|
201
|
+
export function extractViteBuildErrorMessage(reason) {
|
|
202
|
+
if (typeof reason === "string") {
|
|
203
|
+
return reason;
|
|
204
|
+
}
|
|
205
|
+
// Real optimizeDeps rejections are esbuild `BuildFailure` values — Error
|
|
206
|
+
// subclasses with `errors: Message[]`. Prefer those structured texts over the
|
|
207
|
+
// stack so the overlay and Clark see `Could not resolve "buffer/"`, not a
|
|
208
|
+
// noisy stack trace.
|
|
209
|
+
const esbuildTexts = extractEsbuildErrorTexts(reason);
|
|
210
|
+
if (esbuildTexts.length > 0) {
|
|
211
|
+
return esbuildTexts.join("\n");
|
|
212
|
+
}
|
|
213
|
+
if (reason instanceof Error) {
|
|
214
|
+
return reason.stack ?? reason.message;
|
|
215
|
+
}
|
|
216
|
+
if (typeof reason === "object" && reason !== null) {
|
|
217
|
+
const candidate = reason;
|
|
218
|
+
if (typeof candidate.message === "string" && candidate.message.trim()) {
|
|
219
|
+
return candidate.message;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
return JSON.stringify(reason);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return String(reason);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return String(reason);
|
|
229
|
+
}
|
|
127
230
|
//# sourceMappingURL=fatal-exit.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fatal-exit.mjs","sourceRoot":"","sources":["../../src/dev-utils/fatal-exit.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAoBH,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAiBxD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC;QACZ,KAAK,GAAG,CAAC;QACT,KAAK,KAAK,CAAC;QACX,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAuB;IACvD,OAAO;QACL,uBAAuB;QACvB,SAAS,gBAAgB,EAAE;QAC3B,WAAW,MAAM,CAAC,OAAO,EAAE;QAC3B,aAAa,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE;QACxC,UAAU,MAAM,CAAC,MAAM,IAAI,MAAM,EAAE;QACnC,WAAW,MAAM,CAAC,MAAM,EAAE;KAC3B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAkB;IAC1D,CAAC;IACD,EAAE;IACF,mBAAmB;CACpB,CAAC,CAAC;AAEH,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,GAAG,MAA2B,CAAC;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
|
1
|
+
{"version":3,"file":"fatal-exit.mjs","sourceRoot":"","sources":["../../src/dev-utils/fatal-exit.mts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { buildFatalExitLog, FATAL_EXIT_EVENT, isRecoverableShutdownError, parseIsWarm, } from "./fatal-exit.mjs";
|
|
2
|
+
import { buildFatalExitLog, FATAL_EXIT_EVENT, extractViteBuildErrorMessage, isRecoverableShutdownError, isViteBuildError, parseIsWarm, } from "./fatal-exit.mjs";
|
|
3
3
|
describe("parseIsWarm", () => {
|
|
4
4
|
it("treats the same truthy spellings as the entrypoint shell", () => {
|
|
5
5
|
for (const value of ["true", "1", "yes", "on", "TRUE", "Yes", " on "]) {
|
|
@@ -102,4 +102,141 @@ describe("isRecoverableShutdownError", () => {
|
|
|
102
102
|
expect(isRecoverableShutdownError({ code: "ERR_OTHER" })).toBe(false);
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
|
+
describe("isViteBuildError", () => {
|
|
106
|
+
it("matches esbuild BuildFailure shapes", () => {
|
|
107
|
+
expect(isViteBuildError({
|
|
108
|
+
errors: [
|
|
109
|
+
{
|
|
110
|
+
text: 'Could not resolve "buffer/"',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
warnings: [],
|
|
114
|
+
})).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
it("matches Rollup/Vite plugin errors via their message", () => {
|
|
117
|
+
expect(isViteBuildError(Object.assign(new Error('Failed to resolve import "buffer/" from "helpers.js"'), {
|
|
118
|
+
frame: "5: import buffer from 'buffer/'",
|
|
119
|
+
id: "/app/node_modules/plotly.js/src/traces/image/helpers.js",
|
|
120
|
+
loc: { column: 0, file: "helpers.js", line: 5 },
|
|
121
|
+
plugin: "vite:import-analysis",
|
|
122
|
+
}))).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
it("does not match non-build rejections that merely carry Rollup-ish fields", () => {
|
|
125
|
+
// `id` is ubiquitous in this process (RuntimeErrorData, ConsoleLogEntry,
|
|
126
|
+
// socket payloads), and `typeof null === "object"` makes a bare `loc` check
|
|
127
|
+
// match too. Structural fields alone must never mark a rejection
|
|
128
|
+
// recoverable: that would swallow genuine crashes and suppress the
|
|
129
|
+
// dev_server_fatal_exit signal we alert on.
|
|
130
|
+
expect(isViteBuildError({ id: "abc123", message: "boom" })).toBe(false);
|
|
131
|
+
expect(isViteBuildError({ loc: null })).toBe(false);
|
|
132
|
+
expect(isViteBuildError({ plugin: "some-plugin" })).toBe(false);
|
|
133
|
+
expect(isViteBuildError({ frame: "..." })).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
it("ignores esbuild-ish objects whose errors array is not esbuild messages", () => {
|
|
136
|
+
expect(isViteBuildError({ errors: [] })).toBe(false);
|
|
137
|
+
expect(isViteBuildError({ errors: ["nope"] })).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
it("keeps AggregateError fatal even though it carries an errors array", () => {
|
|
140
|
+
// The only thing separating an AggregateError from an esbuild BuildFailure
|
|
141
|
+
// is the `typeof entry.text === "string"` requirement. Without this test,
|
|
142
|
+
// simplifying that shape check would silently reclassify every
|
|
143
|
+
// `Promise.any` rejection and undici `AggregateError [ECONNREFUSED]` as a
|
|
144
|
+
// recoverable build error — keeping a genuinely broken pod alive and
|
|
145
|
+
// dropping it out of the fatal-exit population we alert on.
|
|
146
|
+
expect(isViteBuildError(new AggregateError([
|
|
147
|
+
new Error("connect ECONNREFUSED"),
|
|
148
|
+
new Error("connect ECONNREFUSED"),
|
|
149
|
+
], "All promises were rejected"))).toBe(false);
|
|
150
|
+
expect(isViteBuildError({
|
|
151
|
+
errors: [new Error("connect ECONNREFUSED 127.0.0.1:5432")],
|
|
152
|
+
})).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
it("matches known Vite/esbuild message markers", () => {
|
|
155
|
+
expect(isViteBuildError('Build failed with 1 error:\nCould not resolve "buffer/"')).toBe(true);
|
|
156
|
+
expect(isViteBuildError("Pre-transform error: Failed to resolve import")).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
it("does not match plain runtime errors", () => {
|
|
159
|
+
expect(isViteBuildError(new TypeError("Cannot read property 'x'"))).toBe(false);
|
|
160
|
+
expect(isViteBuildError(undefined)).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
it("requires esbuild's quoted specifier before trusting 'Could not resolve'", () => {
|
|
163
|
+
// esbuild always quotes the specifier (`Could not resolve "buffer/"`).
|
|
164
|
+
// Matching the bare phrase pulls in package-manager and DNS failures, and
|
|
165
|
+
// calling those recoverable would keep a genuinely broken pod alive while
|
|
166
|
+
// suppressing the dev_server_fatal_exit signal we alert on.
|
|
167
|
+
expect(isViteBuildError(new Error("Could not resolve dependency: peer react@^18.0.0"))).toBe(false);
|
|
168
|
+
expect(isViteBuildError("getaddrinfo ENOTFOUND: could not resolve host cdn.example.com")).toBe(false);
|
|
169
|
+
expect(isViteBuildError('Could not resolve "buffer/"')).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
describe("extractViteBuildErrorMessage", () => {
|
|
173
|
+
it("joins esbuild error texts", () => {
|
|
174
|
+
expect(extractViteBuildErrorMessage({
|
|
175
|
+
errors: [{ text: 'Could not resolve "buffer/"' }],
|
|
176
|
+
})).toBe('Could not resolve "buffer/"');
|
|
177
|
+
});
|
|
178
|
+
it("prefers errors[].text over stack for esbuild BuildFailure-shaped Errors", () => {
|
|
179
|
+
// Real optimizeDeps rejections are Error subclasses carrying `errors:
|
|
180
|
+
// Message[]`. The old `instanceof Error` early return sent the stack to the
|
|
181
|
+
// overlay instead of the resolve/transform line Clark needs.
|
|
182
|
+
class FakeBuildFailure extends Error {
|
|
183
|
+
errors;
|
|
184
|
+
constructor(message, errors) {
|
|
185
|
+
super(message);
|
|
186
|
+
this.errors = errors;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const reason = new FakeBuildFailure("Build failed with 1 error", [
|
|
190
|
+
{ text: 'Could not resolve "buffer/"' },
|
|
191
|
+
]);
|
|
192
|
+
expect(extractViteBuildErrorMessage(reason)).toBe('Could not resolve "buffer/"');
|
|
193
|
+
expect(extractViteBuildErrorMessage(reason)).not.toMatch(/^\s*at /m);
|
|
194
|
+
});
|
|
195
|
+
it("still uses stack for plain Errors without structured texts", () => {
|
|
196
|
+
const err = new Error("something broke");
|
|
197
|
+
expect(extractViteBuildErrorMessage(err)).toContain("something broke");
|
|
198
|
+
});
|
|
199
|
+
// This function runs inside the `uncaughtException` / `unhandledRejection`
|
|
200
|
+
// listeners, before the fatal-exit line is written. A throw here does not
|
|
201
|
+
// degrade to the fatal path — Node tears the process down immediately, so the
|
|
202
|
+
// real error never reaches the logs and the misleading TypeError shows up in
|
|
203
|
+
// its place. `isViteBuildError` accepts a message-marker match without
|
|
204
|
+
// re-validating `errors`, so a malformed `errors` array does reach us.
|
|
205
|
+
it("survives an errors array that is not esbuild messages", () => {
|
|
206
|
+
for (const errors of [
|
|
207
|
+
[{ text: 42 }],
|
|
208
|
+
[null],
|
|
209
|
+
[undefined],
|
|
210
|
+
["plain string"],
|
|
211
|
+
[{ text: { nested: true } }],
|
|
212
|
+
]) {
|
|
213
|
+
expect(() => extractViteBuildErrorMessage({
|
|
214
|
+
errors,
|
|
215
|
+
message: "Transform failed with 1 error",
|
|
216
|
+
})).not.toThrow();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
it("falls back to the message when no entry carries usable text", () => {
|
|
220
|
+
// Returning "" here would be classified, counted, and then rendered
|
|
221
|
+
// nowhere: the UI dispatches `loadError(rawError)` and an empty string is
|
|
222
|
+
// falsy, so the overlay never appears.
|
|
223
|
+
expect(extractViteBuildErrorMessage({
|
|
224
|
+
errors: [{}],
|
|
225
|
+
message: "Build failed with 1 error",
|
|
226
|
+
})).toBe("Build failed with 1 error");
|
|
227
|
+
expect(extractViteBuildErrorMessage({
|
|
228
|
+
errors: [{ text: 42 }],
|
|
229
|
+
message: "Transform failed with 1 error",
|
|
230
|
+
})).toBe("Transform failed with 1 error");
|
|
231
|
+
});
|
|
232
|
+
it("still prefers usable entry text over the outer message", () => {
|
|
233
|
+
expect(extractViteBuildErrorMessage({
|
|
234
|
+
errors: [{ text: 'Could not resolve "buffer/"' }, { text: 42 }],
|
|
235
|
+
message: "Build failed with 1 error",
|
|
236
|
+
})).toBe('Could not resolve "buffer/"');
|
|
237
|
+
});
|
|
238
|
+
it("never returns an empty string for an object with no usable text at all", () => {
|
|
239
|
+
expect(extractViteBuildErrorMessage({ errors: [{}] })).not.toBe("");
|
|
240
|
+
});
|
|
241
|
+
});
|
|
105
242
|
//# sourceMappingURL=fatal-exit.test.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fatal-exit.test.mjs","sourceRoot":"","sources":["../../src/dev-utils/fatal-exit.test.mts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fatal-exit.test.mjs","sourceRoot":"","sources":["../../src/dev-utils/fatal-exit.test.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DevServerBuildError, ServerError } from "@superblocksteam/library-shared/types";
|
|
2
|
+
/** Maximum build errors retained on `devServerStatus.serverErrors`. */
|
|
3
|
+
export declare const MAX_DEV_SERVER_BUILD_ERRORS = 5;
|
|
4
|
+
type DevServerStatus = {
|
|
5
|
+
serverErrors: ServerError[];
|
|
6
|
+
};
|
|
7
|
+
export declare function buildDevServerBuildErrorDedupeKey(entry: Pick<DevServerBuildError, "category" | "unresolvedSpecifier">): string;
|
|
8
|
+
export declare function buildDevServerBuildError(reason: unknown): DevServerBuildError;
|
|
9
|
+
export declare function upsertDevServerBuildError(devServerStatus: DevServerStatus, entry: DevServerBuildError): void;
|
|
10
|
+
type RecoverableBuildErrorHandler = "uncaughtException" | "unhandledRejection";
|
|
11
|
+
type RecoverableBuildErrorMetrics = {
|
|
12
|
+
recordRecoverableBuildError: (labels: {
|
|
13
|
+
category: string;
|
|
14
|
+
handler: RecoverableBuildErrorHandler;
|
|
15
|
+
}) => void;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* When a Vite/esbuild build error reaches the process-level handler, keep the
|
|
19
|
+
* pod alive and record it for the editor's `/_sb_connect` readiness path.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleRecoverableBuildError(params: {
|
|
22
|
+
devServerStatus?: DevServerStatus;
|
|
23
|
+
devServerMetrics: RecoverableBuildErrorMetrics;
|
|
24
|
+
handler: RecoverableBuildErrorHandler;
|
|
25
|
+
logger: {
|
|
26
|
+
warn: (message: string, meta?: unknown) => void;
|
|
27
|
+
};
|
|
28
|
+
reason: unknown;
|
|
29
|
+
}): boolean;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=recoverable-build-error.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverable-build-error.d.mts","sourceRoot":"","sources":["../../src/dev-utils/recoverable-build-error.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACZ,MAAM,uCAAuC,CAAC;AAW/C,uEAAuE;AACvE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,KAAK,eAAe,GAAG;IAAE,YAAY,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AAEvD,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,qBAAqB,CAAC,GACnE,MAAM,CAER;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,mBAAmB,CAwB7E;AAED,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,mBAAmB,GACzB,IAAI,CA4BN;AAED,KAAK,4BAA4B,GAAG,mBAAmB,GAAG,oBAAoB,CAAC;AAE/E,KAAK,4BAA4B,GAAG;IAClC,2BAA2B,EAAE,CAAC,MAAM,EAAE;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,4BAA4B,CAAC;KACvC,KAAK,IAAI,CAAC;CACZ,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gBAAgB,EAAE,4BAA4B,CAAC;IAC/C,OAAO,EAAE,4BAA4B,CAAC;IACtC,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KACjD,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CA6CV"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { extractViteBuildErrorMessage, isViteBuildError, } from "./fatal-exit.mjs";
|
|
2
|
+
import { diagnoseViteBuildLogMessage, truncateViteRawLog, } from "./vite-dev-server-diagnostics.mjs";
|
|
3
|
+
/** Maximum build errors retained on `devServerStatus.serverErrors`. */
|
|
4
|
+
export const MAX_DEV_SERVER_BUILD_ERRORS = 5;
|
|
5
|
+
export function buildDevServerBuildErrorDedupeKey(entry) {
|
|
6
|
+
return `${entry.category}:${entry.unresolvedSpecifier ?? ""}`;
|
|
7
|
+
}
|
|
8
|
+
export function buildDevServerBuildError(reason) {
|
|
9
|
+
const fullMessage = extractViteBuildErrorMessage(reason);
|
|
10
|
+
// Classify against the full text so a specifier past the cap is still found,
|
|
11
|
+
// but store the capped copy: this string is persisted on `serverErrors`,
|
|
12
|
+
// logged, sent over `/_sb_connect`, and rendered in the editor overlay.
|
|
13
|
+
const diagnostic = diagnoseViteBuildLogMessage(fullMessage);
|
|
14
|
+
const rawError = truncateViteRawLog(fullMessage);
|
|
15
|
+
if (diagnostic.category === "module_resolve") {
|
|
16
|
+
return {
|
|
17
|
+
type: "dev-server/build",
|
|
18
|
+
timestamp: new Date().toISOString(),
|
|
19
|
+
category: diagnostic.category,
|
|
20
|
+
unresolvedSpecifier: diagnostic.unresolvedSpecifier,
|
|
21
|
+
rawError,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
type: "dev-server/build",
|
|
26
|
+
timestamp: new Date().toISOString(),
|
|
27
|
+
category: diagnostic.category,
|
|
28
|
+
rawError,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function upsertDevServerBuildError(devServerStatus, entry) {
|
|
32
|
+
const dedupeKey = buildDevServerBuildErrorDedupeKey(entry);
|
|
33
|
+
devServerStatus.serverErrors = devServerStatus.serverErrors.filter((existing) => existing.type !== "dev-server/build" ||
|
|
34
|
+
buildDevServerBuildErrorDedupeKey(existing) !== dedupeKey);
|
|
35
|
+
devServerStatus.serverErrors.push(entry);
|
|
36
|
+
// Cap build errors only. `serverErrors` is shared with the startup path,
|
|
37
|
+
// which pushes a dependency-install/upgrade entry once per pod before Vite
|
|
38
|
+
// serves anything; those sit at the front and can never be re-reported, so a
|
|
39
|
+
// whole-array cap keeping the newest entries would evict them first.
|
|
40
|
+
let excess = devServerStatus.serverErrors.filter((existing) => existing.type === "dev-server/build").length - MAX_DEV_SERVER_BUILD_ERRORS;
|
|
41
|
+
if (excess > 0) {
|
|
42
|
+
devServerStatus.serverErrors = devServerStatus.serverErrors.filter((existing) => {
|
|
43
|
+
if (excess > 0 && existing.type === "dev-server/build") {
|
|
44
|
+
excess -= 1;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* When a Vite/esbuild build error reaches the process-level handler, keep the
|
|
53
|
+
* pod alive and record it for the editor's `/_sb_connect` readiness path.
|
|
54
|
+
*/
|
|
55
|
+
export function handleRecoverableBuildError(params) {
|
|
56
|
+
// Never throw. This runs inside the process-level `uncaughtException` /
|
|
57
|
+
// `unhandledRejection` listeners, ahead of the caller's `fatalExitHandled`
|
|
58
|
+
// latch and its fatal-exit log line. Node does not degrade a throw from those
|
|
59
|
+
// listeners to the normal fatal path — it tears the process down immediately,
|
|
60
|
+
// losing the real error, the metric, and `gracefulShutdown`, and leaving a
|
|
61
|
+
// misleading TypeError in their place. Returning `false` instead routes the
|
|
62
|
+
// caller to its fatal path, which logs the original reason.
|
|
63
|
+
//
|
|
64
|
+
// `isViteBuildError` classifies on a message marker without re-validating
|
|
65
|
+
// `errors`, so a malformed array reaches the extraction below; that specific
|
|
66
|
+
// hazard is handled in `extractViteBuildErrorMessage`, and this guard covers
|
|
67
|
+
// whatever else the diagnostic, upsert, and metric steps can raise.
|
|
68
|
+
try {
|
|
69
|
+
if (!isViteBuildError(params.reason)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const entry = buildDevServerBuildError(params.reason);
|
|
73
|
+
if (params.devServerStatus) {
|
|
74
|
+
upsertDevServerBuildError(params.devServerStatus, entry);
|
|
75
|
+
}
|
|
76
|
+
params.devServerMetrics.recordRecoverableBuildError({
|
|
77
|
+
category: entry.category,
|
|
78
|
+
handler: params.handler,
|
|
79
|
+
});
|
|
80
|
+
params.logger.warn(`Ignoring recoverable Vite build error (${params.handler})`, { error: entry });
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch (recordError) {
|
|
84
|
+
// Falling through to the fatal path is the safe direction: the pod exits
|
|
85
|
+
// and the caller logs the original reason. Note the bookkeeping failure
|
|
86
|
+
// separately so a malformed-reason bug stays diagnosable instead of looking
|
|
87
|
+
// like a plain crash.
|
|
88
|
+
params.logger.warn(`Failed to record recoverable Vite build error (${params.handler}); treating as fatal`, { recordError });
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=recoverable-build-error.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverable-build-error.mjs","sourceRoot":"","sources":["../../src/dev-utils/recoverable-build-error.mts"],"names":[],"mappings":"AAKA,OAAO,EACL,4BAA4B,EAC5B,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAE3C,uEAAuE;AACvE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAI7C,MAAM,UAAU,iCAAiC,CAC/C,KAAoE;IAEpE,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAe;IACtD,MAAM,WAAW,GAAG,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACzD,6EAA6E;IAC7E,yEAAyE;IACzE,wEAAwE;IACxE,MAAM,UAAU,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,UAAU,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QAC7C,OAAO;YACL,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;YACnD,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,eAAgC,EAChC,KAA0B;IAE1B,MAAM,SAAS,GAAG,iCAAiC,CAAC,KAAK,CAAC,CAAC;IAC3D,eAAe,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,MAAM,CAChE,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,IAAI,KAAK,kBAAkB;QACpC,iCAAiC,CAAC,QAAQ,CAAC,KAAK,SAAS,CAC5D,CAAC;IACF,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEzC,yEAAyE;IACzE,2EAA2E;IAC3E,6EAA6E;IAC7E,qEAAqE;IACrE,IAAI,MAAM,GACR,eAAe,CAAC,YAAY,CAAC,MAAM,CACjC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,kBAAkB,CACnD,CAAC,MAAM,GAAG,2BAA2B,CAAC;IACzC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,eAAe,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,MAAM,CAChE,CAAC,QAAQ,EAAE,EAAE;YACX,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBACvD,MAAM,IAAI,CAAC,CAAC;gBACZ,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAQ3C;IACC,wEAAwE;IACxE,2EAA2E;IAC3E,8EAA8E;IAC9E,8EAA8E;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,4DAA4D;IAC5D,EAAE;IACF,0EAA0E;IAC1E,6EAA6E;IAC7E,6EAA6E;IAC7E,oEAAoE;IACpE,IAAI,CAAC;QACH,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,yBAAyB,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,CAAC;YAClD,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,0CAA0C,MAAM,CAAC,OAAO,GAAG,EAC3D,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,WAAW,EAAE,CAAC;QACrB,yEAAyE;QACzE,wEAAwE;QACxE,4EAA4E;QAC5E,sBAAsB;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,kDAAkD,MAAM,CAAC,OAAO,sBAAsB,EACtF,EAAE,WAAW,EAAE,CAChB,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverable-build-error.test.d.mts","sourceRoot":"","sources":["../../src/dev-utils/recoverable-build-error.test.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { buildDevServerBuildError, buildDevServerBuildErrorDedupeKey, handleRecoverableBuildError, MAX_DEV_SERVER_BUILD_ERRORS, upsertDevServerBuildError, } from "./recoverable-build-error.mjs";
|
|
3
|
+
import { VITE_ERROR_RAW_LOG_MAX_CHARS } from "./vite-dev-server-diagnostics.mjs";
|
|
4
|
+
describe("buildDevServerBuildError", () => {
|
|
5
|
+
it("classifies module resolve failures with the unresolved specifier", () => {
|
|
6
|
+
const entry = buildDevServerBuildError({
|
|
7
|
+
errors: [{ text: 'Could not resolve "buffer/"' }],
|
|
8
|
+
});
|
|
9
|
+
expect(entry.type).toBe("dev-server/build");
|
|
10
|
+
expect(entry.category).toBe("module_resolve");
|
|
11
|
+
expect(entry.unresolvedSpecifier).toBe("buffer/");
|
|
12
|
+
expect(entry.rawError).toContain("buffer/");
|
|
13
|
+
});
|
|
14
|
+
it("truncates rawError to the same cap the logging pipeline uses", () => {
|
|
15
|
+
// rawError is persisted on serverErrors, logged, shipped over
|
|
16
|
+
// /_sb_connect, and rendered in the editor overlay. A pathological stack or
|
|
17
|
+
// a failure listing hundreds of specifiers must not reach any of those
|
|
18
|
+
// unbounded.
|
|
19
|
+
const entry = buildDevServerBuildError({
|
|
20
|
+
errors: [
|
|
21
|
+
{
|
|
22
|
+
text: `Could not resolve "buffer/"\n${"x".repeat(VITE_ERROR_RAW_LOG_MAX_CHARS * 2)}`,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
expect(entry.rawError.length).toBeLessThan(VITE_ERROR_RAW_LOG_MAX_CHARS + 100);
|
|
27
|
+
expect(entry.rawError).toContain("(truncated)");
|
|
28
|
+
// Classification still reads the full text, so the specifier survives even
|
|
29
|
+
// when it sits past the cap.
|
|
30
|
+
expect(entry.category).toBe("module_resolve");
|
|
31
|
+
expect(entry.unresolvedSpecifier).toBe("buffer/");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe("upsertDevServerBuildError", () => {
|
|
35
|
+
it("dedupes by category and unresolved specifier and caps the list", () => {
|
|
36
|
+
const devServerStatus = { serverErrors: [] };
|
|
37
|
+
const first = buildDevServerBuildError({
|
|
38
|
+
errors: [{ text: 'Could not resolve "buffer/"' }],
|
|
39
|
+
});
|
|
40
|
+
const second = buildDevServerBuildError({
|
|
41
|
+
errors: [{ text: 'Could not resolve "buffer/"' }],
|
|
42
|
+
});
|
|
43
|
+
upsertDevServerBuildError(devServerStatus, first);
|
|
44
|
+
upsertDevServerBuildError(devServerStatus, second);
|
|
45
|
+
expect(devServerStatus.serverErrors).toHaveLength(1);
|
|
46
|
+
expect(devServerStatus.serverErrors[0]?.timestamp).toBe(second.timestamp);
|
|
47
|
+
for (let index = 0; index < MAX_DEV_SERVER_BUILD_ERRORS + 2; index++) {
|
|
48
|
+
upsertDevServerBuildError(devServerStatus, buildDevServerBuildError({
|
|
49
|
+
errors: [{ text: `Could not resolve "pkg-${index}/"` }],
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
expect(devServerStatus.serverErrors.length).toBeLessThanOrEqual(MAX_DEV_SERVER_BUILD_ERRORS);
|
|
53
|
+
});
|
|
54
|
+
it("uses a stable dedupe key", () => {
|
|
55
|
+
expect(buildDevServerBuildErrorDedupeKey({
|
|
56
|
+
category: "module_resolve",
|
|
57
|
+
unresolvedSpecifier: "buffer/",
|
|
58
|
+
})).toBe("module_resolve:buffer/");
|
|
59
|
+
});
|
|
60
|
+
it("keeps startup errors when a burst of build errors exceeds the cap", () => {
|
|
61
|
+
// `serverErrors` is shared with the startup path, which pushes a
|
|
62
|
+
// `dependency-install` / `dependency-upgrade` entry once per pod before
|
|
63
|
+
// Vite ever serves a request. Those sit at the front of the array, so a
|
|
64
|
+
// cap that counted every entry and kept only the newest would evict the
|
|
65
|
+
// install failure first — the one entry the user most needs to act on, and
|
|
66
|
+
// one that can never be re-reported.
|
|
67
|
+
const installError = {
|
|
68
|
+
type: "dev-server/dependency-install",
|
|
69
|
+
timestamp: new Date("2026-01-01T00:00:00.000Z").toISOString(),
|
|
70
|
+
category: "not_in_registry",
|
|
71
|
+
message: "npm ERR! 404 Not Found - GET https://registry/plotly.js",
|
|
72
|
+
};
|
|
73
|
+
const devServerStatus = { serverErrors: [installError] };
|
|
74
|
+
for (let index = 0; index < MAX_DEV_SERVER_BUILD_ERRORS + 3; index++) {
|
|
75
|
+
upsertDevServerBuildError(devServerStatus, buildDevServerBuildError({
|
|
76
|
+
errors: [{ text: `Could not resolve "pkg-${index}/"` }],
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
expect(devServerStatus.serverErrors).toContain(installError);
|
|
80
|
+
expect(devServerStatus.serverErrors.filter((entry) => entry.type === "dev-server/build")).toHaveLength(MAX_DEV_SERVER_BUILD_ERRORS);
|
|
81
|
+
});
|
|
82
|
+
it("evicts the oldest build error rather than an arbitrary entry", () => {
|
|
83
|
+
const devServerStatus = { serverErrors: [] };
|
|
84
|
+
for (let index = 0; index < MAX_DEV_SERVER_BUILD_ERRORS + 1; index++) {
|
|
85
|
+
upsertDevServerBuildError(devServerStatus, buildDevServerBuildError({
|
|
86
|
+
errors: [{ text: `Could not resolve "pkg-${index}/"` }],
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
const specifiers = devServerStatus.serverErrors.map((entry) => entry.unresolvedSpecifier);
|
|
90
|
+
expect(specifiers).not.toContain("pkg-0/");
|
|
91
|
+
expect(specifiers).toContain(`pkg-${MAX_DEV_SERVER_BUILD_ERRORS}/`);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe("handleRecoverableBuildError", () => {
|
|
95
|
+
it("records a build error and returns true for esbuild failures", () => {
|
|
96
|
+
const devServerStatus = { serverErrors: [] };
|
|
97
|
+
const recordRecoverableBuildError = vi.fn();
|
|
98
|
+
const metrics = {
|
|
99
|
+
recordRecoverableBuildError,
|
|
100
|
+
};
|
|
101
|
+
const handled = handleRecoverableBuildError({
|
|
102
|
+
devServerStatus,
|
|
103
|
+
devServerMetrics: metrics,
|
|
104
|
+
handler: "unhandledRejection",
|
|
105
|
+
logger: { warn: vi.fn() },
|
|
106
|
+
reason: {
|
|
107
|
+
errors: [{ text: 'Could not resolve "buffer/"' }],
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
expect(handled).toBe(true);
|
|
111
|
+
expect(devServerStatus.serverErrors).toHaveLength(1);
|
|
112
|
+
expect(recordRecoverableBuildError).toHaveBeenCalledWith({
|
|
113
|
+
category: "module_resolve",
|
|
114
|
+
handler: "unhandledRejection",
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
// This runs inside the `uncaughtException` / `unhandledRejection` listeners
|
|
118
|
+
// before the caller writes its fatal-exit line. An escaping throw there does
|
|
119
|
+
// not degrade to the fatal path: Node tears the process down immediately, so
|
|
120
|
+
// the real error never reaches the logs, no metric is emitted, and
|
|
121
|
+
// `gracefulShutdown` never runs. Returning false instead routes the caller to
|
|
122
|
+
// its normal fatal path, which logs the original reason.
|
|
123
|
+
it("falls back to the fatal path instead of throwing when recording fails", () => {
|
|
124
|
+
const logger = { warn: vi.fn() };
|
|
125
|
+
const handled = handleRecoverableBuildError({
|
|
126
|
+
devServerStatus: { serverErrors: [] },
|
|
127
|
+
devServerMetrics: {
|
|
128
|
+
recordRecoverableBuildError: () => {
|
|
129
|
+
throw new Error("meter unavailable");
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
handler: "uncaughtException",
|
|
133
|
+
logger,
|
|
134
|
+
reason: { errors: [{ text: 'Could not resolve "buffer/"' }] },
|
|
135
|
+
});
|
|
136
|
+
expect(handled).toBe(false);
|
|
137
|
+
// The bookkeeping failure is noted separately so a malformed reason is
|
|
138
|
+
// diagnosable rather than looking like a plain crash.
|
|
139
|
+
expect(logger.warn).toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
it("keeps the recoverable path for a reason whose errors array is malformed", () => {
|
|
142
|
+
// `isViteBuildError` accepts this via the message marker without
|
|
143
|
+
// re-validating `errors`, which is how a malformed array reaches the
|
|
144
|
+
// extraction step.
|
|
145
|
+
const devServerStatus = { serverErrors: [] };
|
|
146
|
+
const logger = { warn: vi.fn() };
|
|
147
|
+
const handled = handleRecoverableBuildError({
|
|
148
|
+
devServerStatus,
|
|
149
|
+
devServerMetrics: { recordRecoverableBuildError: vi.fn() },
|
|
150
|
+
handler: "unhandledRejection",
|
|
151
|
+
logger,
|
|
152
|
+
reason: {
|
|
153
|
+
errors: [{ text: 42 }],
|
|
154
|
+
message: "Transform failed with 1 error",
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
expect(handled).toBe(true);
|
|
158
|
+
expect(devServerStatus.serverErrors).toHaveLength(1);
|
|
159
|
+
expect(devServerStatus.serverErrors[0].rawError).toContain("Transform failed");
|
|
160
|
+
});
|
|
161
|
+
it("returns false for non-build errors", () => {
|
|
162
|
+
const devServerStatus = { serverErrors: [] };
|
|
163
|
+
const metrics = {
|
|
164
|
+
recordRecoverableBuildError: vi.fn(),
|
|
165
|
+
};
|
|
166
|
+
expect(handleRecoverableBuildError({
|
|
167
|
+
devServerStatus,
|
|
168
|
+
devServerMetrics: metrics,
|
|
169
|
+
handler: "uncaughtException",
|
|
170
|
+
logger: { warn: vi.fn() },
|
|
171
|
+
reason: new TypeError("boom"),
|
|
172
|
+
})).toBe(false);
|
|
173
|
+
expect(devServerStatus.serverErrors).toHaveLength(0);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
//# sourceMappingURL=recoverable-build-error.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverable-build-error.test.mjs","sourceRoot":"","sources":["../../src/dev-utils/recoverable-build-error.test.mts"],"names":[],"mappings":"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"}
|