@btravstack/contract / index
index
Type Aliases
Authenticated
type Authenticated<T, R> = T & object;Defined in: auth.ts:31
A contract node whose procedures require an authenticated caller.
Type Declaration
| Name | Type | Defined in |
|---|---|---|
[PRINCIPAL] | R | auth.ts:31 |
Type Parameters
| Type Parameter |
|---|
T |
R extends Requirements |
IsMarked
type IsMarked<T> = T extends object ? true : false;Defined in: auth.ts:37
Whether this exact node carries the marker.
Type Parameters
| Type Parameter |
|---|
T |
OneScheme
type OneScheme<Q> = SeveralKeys<keyof Q> extends false ? Q : never;Defined in: auth.ts:25
A requirement naming two schemes is OpenAPI's AND, and nothing here models it: @btravstack/http-server takes the first entry that satisfies, which is OR — so a two-key requirement copied out of an OpenAPI document would execute as a WEAKER rule than the one it states. Refused at the mark instead.
Type Parameters
| Type Parameter |
|---|
Q |
Page
type Page<T> = object &
| {
hasPreviousPage: true;
previousCursor: string;
}
| {
hasPreviousPage: false;
previousCursor?: never;
} &
| {
hasNextPage: true;
nextCursor: string;
}
| {
hasNextPage: false;
nextCursor?: never;
};Defined in: pagination.ts:15
One page of a listing, in the vocabulary a client and a server share.
A flag and its cursor are one fact, spelled once. hasNextPage: true carries the nextCursor that continues the listing; hasNextPage: false has no nextCursor field at all. So "there is more, and nothing to follow it with" — and its twin, a cursor nobody may use — are unrepresentable rather than merely unexpected, and a reader that checks the flag has the cursor in hand, with no null to widen it.
A cursor is an opaque string: the server's to mint and to read, the client's to hand back verbatim. Nothing above the adapter that issued one may interpret it.
Type Declaration
| Name | Type | Defined in |
|---|---|---|
items | readonly T[] | pagination.ts:15 |
Type Parameters
| Type Parameter |
|---|
T |
PageQuery
type PageQuery = object;Defined in: pagination.ts:67
The flat shape a validated page input arrives in, before its two cursors have been narrowed to the one direction PageRequest allows.
A schema states "at most one of these" as a rule over two optional fields; a type states it as a union. This is the former, and pageRequest is the crossing between them.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
after? | readonly | string | pagination.ts:69 |
before? | readonly | string | pagination.ts:70 |
limit | readonly | number | pagination.ts:68 |
PageRequest
type PageRequest =
| {
after?: string;
before?: never;
limit: number;
}
| {
after?: never;
before?: string;
limit: number;
};Defined in: pagination.ts:55
What a caller asks for: a size, and at most one cursor.
after and before are the opaque cursors a previous page handed back, and they are mutually exclusive in the type: a page runs in one direction, and "after X and before Y" is a range query wearing a page's clothes. A union is what makes that unrepresentable rather than merely documented.
PrincipalKey
type PrincipalKey = typeof PRINCIPAL;Defined in: auth.ts:34
The marker's key, so a consumer's mapped type can Exclude it from keyof.
Requirement
type Requirement = Readonly<Record<string, readonly string[]>>;Defined in: auth.ts:13
One OpenAPI security requirement: a scheme, and the scopes it must grant.
The CARRIER — what a marked node holds and isAuthenticated reads back — so it says nothing about arity. OneScheme below is what refuses a second key.
Requirements
type Requirements = readonly Requirement[];Defined in: auth.ts:28
Requirements are ORed, in order: the first one a caller satisfies wins.
RequirementsOf
type RequirementsOf<T> = T extends object ? R : never;Defined in: auth.ts:40
What this exact node requires, or never when it is unmarked.
Type Parameters
| Type Parameter |
|---|
T |
Functions
authenticated()
function authenticated<R>(...requirements): <T>(node) => Authenticated<T, R>;Defined in: auth.ts:71
Marks a contract node as requiring an authenticated caller, with OpenAPI's own requirement shape — a scheme and the scopes it must grant, ORed in the order given.
export const contract = {
orders: authenticated({ user: [] })({ place, find }),
exports: authenticated({ user: ["orders:export"] }, { service: [] })(csvProcedure),
};Applied to a record it is the default for every procedure beneath it; applied to a procedure it replaces that default for itself. Nearest mark wins. Returns the node unchanged and applies after a builder chain, never inside one. See packages/contract/CLAUDE.md.
Type Parameters
| Type Parameter |
|---|
R extends Requirements & { readonly [I in string | number | symbol]: OneScheme<R[I]> } |
Parameters
| Parameter | Type |
|---|---|
...requirements | R |
Returns
<T>(node) => Authenticated<T, R>
isAuthenticated()
function isAuthenticated(node): Requirements | undefined;Defined in: auth.ts:84
What this exact node requires, or undefined when nobody marked it. Ancestry is the caller's to carry — @btravstack/http-server's routerOf walks the tree and passes the nearest mark down.
Parameters
| Parameter | Type |
|---|---|
node | object |
Returns
Requirements | undefined
page()
function page<T>(items, cursors): Page<T>;Defined in: pagination.ts:34
A page from its items and the cursor on each side, null where there is nothing to follow.
The flags are DERIVED rather than given: a cursor is what a caller needs to ask for the page on that side, so a side with no cursor is a side it cannot reach — which is what the flags say. An adapter whose pagination library reports a page the other way round, a hasPreviousPage: true with no cursor to go back with, therefore reports the reachable answer instead.
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type |
|---|---|
items | readonly T[] |
cursors | { next: string | null; previous: string | null; } |
cursors.next | string | null |
cursors.previous | string | null |
Returns
Page<T>
pageRequest()
function pageRequest<Q>(query): PageRequest & Omit<Q, "after" | "before">;Defined in: pagination.ts:82
A validated page input, narrowed into the one-direction PageRequest a port takes, carrying any filters alongside it untouched.
before wins when both are somehow present. That precedence is unreachable through pageRequestOf, whose schema refuses the pair — it exists so this function is total rather than partial, not as a policy a caller should rely on.
Type Parameters
| Type Parameter |
|---|
Q extends PageQuery |
Parameters
| Parameter | Type |
|---|---|
query | Q |
Returns
PageRequest & Omit<Q, "after" | "before">