Skip to content
Merged
10 changes: 10 additions & 0 deletions ark/schema/__tests__/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ contextualize(() => {
])
})

it("serialization tolerates indexed entries without toJSON (e.g. HTTP JSON.stringify)", () => {
;(errors as unknown as { push(...items: unknown[]): number }).push({
message: "foreign issue",
path: ["_"]
})
const parsed = JSON.parse(JSON.stringify(errors)) as unknown[]
attest(parsed.length).equals(2)
attest(parsed[1]).equals({ message: "foreign issue", path: ["_"] })
Comment thread
gabroberge marked this conversation as resolved.
Outdated
})
Comment thread
gabroberge marked this conversation as resolved.

it("flatByPath", () => {
attest(errors.flatByPath).snap({
n: [
Expand Down
23 changes: 22 additions & 1 deletion ark/schema/shared/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,29 @@ export class ArkErrors
return this
}

/**
* Also Standard Schema `issues`; HTTP stacks may `JSON.stringify` this array,
* so indexed entries must not assume {@link ArkError}.
*/
private static indexedIssueToJson(issue: unknown): JsonObject {
Comment thread
gabroberge marked this conversation as resolved.
Outdated
if (issue === undefined) return { message: "undefined" }
if (issue === null) return { message: "null" }
if (typeof issue !== "object") return { message: String(issue) }

const toJSON = (issue as { toJSON?: unknown }).toJSON
if (typeof toJSON === "function") return toJSON.call(issue)
Comment thread
gabroberge marked this conversation as resolved.
Outdated

const { message, path } = issue as Record<string, unknown>
if (typeof message === "string") {
if (path === undefined) return { message }
return { message, path } as JsonObject
Comment thread
gabroberge marked this conversation as resolved.
Outdated
}

return { message: String(issue) }
}

toJSON(): JsonArray {
return [...this.map(e => e.toJSON())]
return [...this.map(ArkErrors.indexedIssueToJson)]
}

toString(): string {
Expand Down
Loading