Skip to content

@btravstack/contract


@btravstack/contract / index

index

Type Aliases

Authenticated

ts
type Authenticated<T, R> = T & object;

Defined in: auth.ts:31

A contract node whose procedures require an authenticated caller.

Type Declaration

NameTypeDefined in
[PRINCIPAL]Rauth.ts:31

Type Parameters

Type Parameter
T
R extends Requirements

IsMarked

ts
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

ts
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

ts
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

NameTypeDefined in
itemsreadonly T[]pagination.ts:15

Type Parameters

Type Parameter
T

PageQuery

ts
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

PropertyModifierTypeDefined in
after?readonlystringpagination.ts:69
before?readonlystringpagination.ts:70
limitreadonlynumberpagination.ts:68

PageRequest

ts
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

ts
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

ts
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

ts
type Requirements = readonly Requirement[];

Defined in: auth.ts:28

Requirements are ORed, in order: the first one a caller satisfies wins.


RequirementsOf

ts
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()

ts
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.

ts
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

ParameterType
...requirementsR

Returns

<T>(node) => Authenticated<T, R>


isAuthenticated()

ts
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

ParameterType
nodeobject

Returns

Requirements | undefined


page()

ts
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

ParameterType
itemsreadonly T[]
cursors{ next: string | null; previous: string | null; }
cursors.nextstring | null
cursors.previousstring | null

Returns

Page<T>


pageRequest()

ts
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

ParameterType
queryQ

Returns

PageRequest & Omit<Q, "after" | "before">

Released under the MIT License.