@btravstack/contract / zod
zod
Type Aliases
PageLimits
type PageLimits = object;Defined in: zod.ts:12
How large a page may be, and how large it is when the caller says nothing.
Both are the API's decision rather than the framework's, so both are overridable — the defaults are a listing that behaves reasonably when nobody has thought about it yet.
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
defaultLimit? | readonly | number | The size of a page whose caller named none. Default 20. | zod.ts:14 |
maxLimit? | readonly | number | The largest page a caller may ask for. Default 100. | zod.ts:16 |
SortOptions
type SortOptions<Keys> = object;Defined in: zod.ts:97
Type Parameters
| Type Parameter |
|---|
Keys extends readonly string[] |
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
defaultSort | readonly | Sort<Keys[number]> | The sort served when a caller names none. Required: an implicit default is a listing sorted by something nobody chose. | zod.ts:101 |
sortableBy | readonly | Keys | The keys this listing may be sorted on, from sortableBy. | zod.ts:99 |
Functions
pageOf()
function pageOf<Item>(item): ZodUnion<readonly [ZodObject<{
hasNextPage: ZodLiteral<false>;
hasPreviousPage: ZodLiteral<false>;
items: ZodArray<Item>;
}, $strict>, ZodObject<{
hasNextPage: ZodLiteral<true>;
hasPreviousPage: ZodLiteral<false>;
items: ZodArray<Item>;
nextCursor: ZodString;
}, $strict>, ZodObject<{
hasNextPage: ZodLiteral<false>;
hasPreviousPage: ZodLiteral<true>;
items: ZodArray<Item>;
previousCursor: ZodString;
}, $strict>, ZodObject<{
hasNextPage: ZodLiteral<true>;
hasPreviousPage: ZodLiteral<true>;
items: ZodArray<Item>;
nextCursor: ZodString;
previousCursor: ZodString;
}, $strict>]>;Defined in: zod.ts:48
The schema of one page of item: the four pages that exist, as four closed objects.
A union rather than an intersection, because allOf of closed objects validates nothing in JSON Schema and the emitted OpenAPI document is an interop surface. strictObject, so a cursor on a closed side is refused rather than stripped: the arms differ by which fields they carry, and the schema this generates already says additionalProperties: false — a stripping parser would accept what its own published schema rejects.
What it parses to is assignable to Page<T>, which pagination.test-d.ts pins, and every page page builds parses against it, which pagination.spec.ts pins — so a field dropped, loosened or renamed on either side fails a check. Widening Page<T> with a field no page carries is the one drift neither sees.
Type Parameters
| Type Parameter |
|---|
Item extends ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>> |
Parameters
| Parameter | Type |
|---|---|
item | Item |
Returns
ZodUnion<readonly [ZodObject<{ hasNextPage: ZodLiteral<false>; hasPreviousPage: ZodLiteral<false>; items: ZodArray<Item>; }, $strict>, ZodObject<{ hasNextPage: ZodLiteral<true>; hasPreviousPage: ZodLiteral<false>; items: ZodArray<Item>; nextCursor: ZodString; }, $strict>, ZodObject<{ hasNextPage: ZodLiteral<false>; hasPreviousPage: ZodLiteral<true>; items: ZodArray<Item>; previousCursor: ZodString; }, $strict>, ZodObject<{ hasNextPage: ZodLiteral<true>; hasPreviousPage: ZodLiteral<true>; items: ZodArray<Item>; nextCursor: ZodString; previousCursor: ZodString; }, $strict>]>
pageRequestOf()
Call Signature
function pageRequestOf<Filters>(filters, limits?): ZodObject<{ [k in string | number | symbol]: ((("limit" | "after" | "before") & keyof Filters) extends never ? { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber> } & { -readonly [P in string | number | symbol]: Filters[P] } : { [K in "limit" | "after" | "before" as K extends keyof Filters ? never : K]: { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber> }[K] } & { [K in string | number | symbol]: { -readonly [P in string | number | symbol]: Filters[P] }[K] })[k] }>;Defined in: zod.ts:167
The schema of a page input: a bounded limit, the two opaque cursors, at most one of them, whatever else this listing filters by, and — for a listing that names SortOptions.sortableBy — the sort it runs in.
The pair is refused by the schema rather than by the handler, so the refusal is published in the OpenAPI document and answered as a validation error rather than as application logic. What survives it is still two optional fields; pageRequest is what turns a parsed input into the one-direction PageRequest a port takes.
filters is required, and {} is how a listing says it has none — an absent argument and an empty shape would be the same call spelled two ways. limit, after, before and sort are the page's own and cannot be among them: a filter replacing one would silently unbound the limit, re-type a cursor or shadow the sort, so the shape refuses it at the call.
Type Parameters
| Type Parameter |
|---|
Filters extends ReservedKeysFree |
Parameters
| Parameter | Type |
|---|---|
filters | Filters |
limits? | PageLimits |
Returns
ZodObject<{ [k in string | number | symbol]: ((("limit" | "after" | "before") & keyof Filters) extends never ? { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber> } & { -readonly [P in string | number | symbol]: Filters[P] } : { [K in "limit" | "after" | "before" as K extends keyof Filters ? never : K]: { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber> }[K] } & { [K in string | number | symbol]: { -readonly [P in string | number | symbol]: Filters[P] }[K] })[k] }>
Call Signature
function pageRequestOf<Filters, Keys>(filters, options): ZodObject<{ [k in string | number | symbol]: ((("limit" | "after" | "before" | "sort") & keyof Filters) extends never ? { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber>; sort: ZodPrefault<ZodObject<{ direction: ZodEnum<{ asc: ...; desc: ... }>; field: ZodEnum<{ [k in (...)]: (...) }> }, $strict>> } & { -readonly [P in string | number | symbol]: Filters[P] } : { [K in "limit" | "after" | "before" | "sort" as K extends keyof Filters ? never : K]: { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber>; sort: ZodPrefault<ZodObject<{ direction: ...; field: ... }, $strict>> }[K] } & { [K in string | number | symbol]: { -readonly [P in string | number | symbol]: Filters[P] }[K] })[k] }>;Defined in: zod.ts:171
The schema of a page input: a bounded limit, the two opaque cursors, at most one of them, whatever else this listing filters by, and — for a listing that names SortOptions.sortableBy — the sort it runs in.
The pair is refused by the schema rather than by the handler, so the refusal is published in the OpenAPI document and answered as a validation error rather than as application logic. What survives it is still two optional fields; pageRequest is what turns a parsed input into the one-direction PageRequest a port takes.
filters is required, and {} is how a listing says it has none — an absent argument and an empty shape would be the same call spelled two ways. limit, after, before and sort are the page's own and cannot be among them: a filter replacing one would silently unbound the limit, re-type a cursor or shadow the sort, so the shape refuses it at the call.
Type Parameters
| Type Parameter |
|---|
Filters extends ReservedKeysFree |
Keys extends readonly [string, string] |
Parameters
| Parameter | Type |
|---|---|
filters | Filters |
options | PageLimits & SortOptions<Keys> |
Returns
ZodObject<{ [k in string | number | symbol]: ((("limit" | "after" | "before" | "sort") & keyof Filters) extends never ? { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber>; sort: ZodPrefault<ZodObject<{ direction: ZodEnum<{ asc: ...; desc: ... }>; field: ZodEnum<{ [k in (...)]: (...) }> }, $strict>> } & { -readonly [P in string | number | symbol]: Filters[P] } : { [K in "limit" | "after" | "before" | "sort" as K extends keyof Filters ? never : K]: { after: ZodOptional<ZodString>; before: ZodOptional<ZodString>; limit: ZodPrefault<ZodNumber>; sort: ZodPrefault<ZodObject<{ direction: ...; field: ... }, $strict>> }[K] } & { [K in string | number | symbol]: { -readonly [P in string | number | symbol]: Filters[P] }[K] })[k] }>
sortableBy()
function sortableBy<Item, Keys>(_item, keys): Keys;Defined in: zod.ts:89
The sortable vocabulary of a listing, checked against the item it answers.
A curated set rather than every key: what a listing sorts on is an index decision, and publishing every column invites a caller to sort by one with no index behind it. A name outside the item's shape is a compile error here, so a typo cannot reach the wire as a 400.
Type Parameters
Parameters
| Parameter | Type |
|---|---|
_item | Item |
keys | Keys |
Returns
Keys