first commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# `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<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.
|
||||
Reference in New Issue
Block a user