fix: harden workflow console runtime

This commit is contained in:
lda
2026-07-02 17:35:16 +07:00 Verified
parent bcf31583af
commit ea1276badd
22 changed files with 684 additions and 128 deletions
+21 -2
View File
@@ -64,6 +64,25 @@ describe("connectToServer", () => {
expect(result.error.code).toBe("invalid_target");
}
});
it("accepts future server error codes without rejecting the response", async () => {
mockFetch.mockReturnValue(
jsonResponse(
{
ok: false,
error: { code: "new_server_code", message: "future failure" },
exchange: { request: null, response: null },
},
502,
),
);
const result = await connectToServer("http://127.0.0.1:8000/rpc");
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error.code).toBe("new_server_code");
}
});
});
describe("callOperation", () => {
@@ -135,7 +154,7 @@ describe("error handling", () => {
await expect(
connectToServer("http://127.0.0.1:8000/rpc"),
).rejects.toThrow("empty response");
).rejects.toThrow("console backend returned an empty response (HTTP 200)");
});
it("throws for structurally malformed JSON response", async () => {
@@ -143,7 +162,7 @@ describe("error handling", () => {
await expect(
connectToServer("http://127.0.0.1:8000/rpc"),
).rejects.toThrow("malformed response");
).rejects.toThrow("malformed response from server:");
});
it("throws on network failure", async () => {
+3 -1
View File
@@ -13,7 +13,9 @@ const fetchJson = async <T>(
const res = await fetch(url, init);
const text = await res.text();
if (!text) {
throw new Error("empty response from server");
throw new Error(
`console backend returned an empty response (HTTP ${res.status})`,
);
}
let data: unknown;
try {
+5 -3
View File
@@ -1,6 +1,6 @@
import * as v from "valibot";
const BrowserErrorCodeSchema = v.union([
const KnownBrowserErrorCodeSchema = v.union([
v.literal("invalid_target"),
v.literal("unknown_operation"),
v.literal("upstream_unreachable"),
@@ -10,6 +10,7 @@ const BrowserErrorCodeSchema = v.union([
v.literal("rpc_decode_error"),
v.literal("response_too_large"),
]);
const BrowserErrorCodeSchema = v.union([KnownBrowserErrorCodeSchema, v.string()]);
const ExchangeSchema = v.object({
request: v.nullish(v.unknown(), null),
@@ -67,8 +68,9 @@ export type OperationName = v.InferOutput<typeof OperationNameSchema>;
const parseDto = <T>(schema: v.GenericSchema<unknown, T>, data: unknown): T => {
try {
return v.parse(schema, data);
} catch {
throw new Error("malformed response from server");
} catch (error) {
const details = error instanceof Error ? `: ${error.message}` : "";
throw new Error(`malformed response from server${details}`);
}
};