# `schemas/paste.schema.ts` ## Purpose `PasteSchema` validates the [HIBP v3 `Paste` payload](https://haveibeenpwned.com/API/v3#PastesForAccount) 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 `ZodError` on type mismatch; the breach client maps that to `HIBP.MALFORMED_RESPONSE`. ## Usage: Basic Example ```ts import { PasteSchema } from "@suaveplan/hibp"; const paste = PasteSchema.parse({ Source: "Pastebin", Id: "ABC", EmailCount: 100, }); ``` ## Usage: Advanced Example ```ts 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` 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.