fix: harden workflow console runtime
This commit is contained in:
@@ -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 () => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user