2.0 KiB
schemas/paste.schema.ts
Purpose
PasteSchema validates the HIBP v3 Paste
payload returned by
/pasteaccount/{email}. Older paste records can omit Title and Date,
so this schema makes them optional while still enforcing structural shape
on the required fields. Defending this boundary keeps getPastesForAccount
honest about its return type.
Features
- Required:
Source,Id,EmailCount(non-negative int). - Optional:
Title,Date(older paste records may lack metadata). - Throws
ZodErroron type mismatch; the breach client maps that toHIBP.MALFORMED_RESPONSE.
Usage: Basic Example
import { PasteSchema } from "@suaveplan/hibp";
const paste = PasteSchema.parse({
Source: "Pastebin",
Id: "ABC",
EmailCount: 100,
});
Usage: Advanced Example
import { PasteSchema, type Paste } from "@suaveplan/hibp";
export function summarisePastes(items: unknown[]): {
pastes: Paste[];
totalEmails: number;
} {
const pastes = items.map((x) => PasteSchema.parse(x));
return {
pastes,
totalEmails: pastes.reduce((n, p) => n + p.EmailCount, 0),
};
}
API Reference
PasteSchema: ZodObject— v3 paste shape.Paste—z.infer<typeof PasteSchema>type alias.
Implementation Notes
The optional Title / Date fields are deliberately not defaulted; if
they are absent in the upstream payload, they remain undefined in the
parsed value so callers can branch on presence. We considered defaulting
Date to null for consistency but rejected it as a divergence from the
documented contract. The schema rejects unknown nested types eagerly: a
server-side rename like Source → source (lowercase) will surface as a
HIBP.MALFORMED_RESPONSE from getPastesForAccount, which is the
correct behaviour — a silent rename would be far worse than a typed
throw. Callers can wrap individual parse calls in try if partial
tolerance is desired, but the default policy is fail-fast.