Search...

Go

shelving/apimodule

Typed, provider-based framework for HTTP API access. Define your routes as Endpoint definitions, then call them through a composable provider stack — the same pattern the shelving/db module uses for databases.

Go

EndpointStoreclass

Store that loads and tracks the result of calling a single API endpoint with a fixed payload, through an APIProvider.

new EndpointStore<P, R>(endpoint: Endpoint<P, R>, payload: P, provider: APIProvider<P, R>)
Go

APICacheclass

Cache of EndpointCache objects keyed by Endpoint, providing memoised API results across many endpoints.

new APICache<P, R>(provider: APIProvider<P, R>)
Go

APICache.get()method

Get (or create) the EndpointCache for the given endpoint.

get(endpoint: Endpoint<PP, RR>): EndpointCache<PP, RR>
get(endpoint: Endpoint): EndpointCache
Go

APICache.call()method

Fetch (or return a cached result) for the given endpoint and payload.

call(endpoint: Endpoint<PP, RR>, payload: PP, maxAge: number = AVOID_REFRESH, caller: AnyCaller = this.call): Promise<RR>
Go

APICache.invalidate()method

Invalidate a specific store for an endpoint so the next read refetches.

invalidate(endpoint: Endpoint<PP, RR>, payload: PP): void
Go

APICache.invalidateAll()method

Invalidate all stores for an endpoint so the next read of any payload refetches.

invalidateAll(endpoint: Endpoint<PP, RR>): void
Go

APICache.refresh()method

Trigger a refetch on a specific store for an endpoint.

refresh(endpoint: Endpoint<PP, RR>, payload: PP, maxAge?: number): Promise<void>
Go

APICache.refreshAll()method

Trigger a refetch on all stores for an endpoint.

refreshAll(endpoint: Endpoint<PP, RR>, maxAge?: number): Promise<void>
Go

EndpointCacheclass

Cache of EndpointStore objects for a single endpoint, keyed by the rendered request URL of each payload.

new EndpointCache<P, R>(endpoint: Endpoint<P, R>, provider: APIProvider<P, R>)
Go

EndpointCache.get()method

Get (or create) the EndpointStore for the given payload.

get(payload: P, caller: AnyCaller = this.get): EndpointStore<P, R>
Go

EndpointCache.call()method

Fetch (or return a cached result) for the given payload.

call(payload: P, maxAge: number = AVOID_REFRESH, caller: AnyCaller = this.call): Promise<R>
Go

EndpointCache.invalidate()method

Invalidate a specific store so the next read refetches.

invalidate(payload: P, caller: AnyCaller = this.invalidate): void
Go

EndpointCache.invalidateAll()method

Invalidate all stores so the next read of any payload refetches.

invalidateAll(): void
Go

EndpointCache.refresh()method

Trigger a refetch on a specific store.

refresh(payload: P, maxAge?: number, caller: AnyCaller = this.refresh): Promise<void>
Go

EndpointCache.refreshAll()method

Trigger a refetch on all stores.

refreshAll(maxAge?: number): Promise<void>
Go

JSONAPIProviderclass

Client API provider that always sends request bodies as JSON and parses responses as JSON.

new JSONAPIProvider<P, R>()
Go

ValidationAPIProviderclass

Provider that validates payloads and results against the endpoint's schemas, so a source of any type is made type-safe.

new ValidationAPIProvider<P, R>()
Go

ClientAPIProviderOptionsinterface

Options for constructing a ClientAPIProvider.

{
	readonly url: PossibleURL;
	readonly options?: Omit<RequestOptions, "signal">;
	readonly timeout?: number | undefined;
}
Go

ClientAPIProviderclass

A client-side API provider that sends requests over the network using fetch().

new ClientAPIProvider<P, R>({ url, options = {}, timeout = 20_000 }: ClientAPIProviderOptions)
Go

MockEndpointAPIProviderclass

Provider that mocks an API that calls and matches an array of EndpointHandler objects returned from Endpoint.handler()

new MockEndpointAPIProvider<P, R, C>(handlers: EndpointHandlers<C>, context: C, source?: ClientAPIProvider<P, R>)
Go

XMLAPIProviderclass

Client API provider that always sends request bodies as XML and parses responses as plain text.

new XMLAPIProvider<P, R>()
Go

DebugAPIProviderclass

Provider that logs every request, response, and error to the console in detail to help diagnose issues in development.

new DebugAPIProvider<P, R>()
Go

CachedAPIProviderclass

API provider wrapper that serves requests through an APICache so repeated calls reuse cached results.

new CachedAPIProvider<P, R>(source: APIProvider<P, R>, maxAge: number = AVOID_REFRESH)
Go

CachedAPIProvider.invalidate()method

Invalidate the cached result for a specific endpoint and payload.

invalidate(endpoint: Endpoint<PP, RR>, payload: PP): void
Go

CachedAPIProvider.invalidateAll()method

Invalidate every cached result for an endpoint, across all payloads.

invalidateAll(endpoint: Endpoint<PP, RR>): void
Go

CachedAPIProvider.refresh()method

Refresh the cached result for a specific endpoint and payload.

refresh(endpoint: Endpoint<PP, RR>, payload: PP): Promise<void>
Go

CachedAPIProvider.refreshAll()method

Refresh every cached result for an endpoint, across all payloads.

refreshAll(endpoint: Endpoint<PP, RR>): Promise<void>
Go

MockAPIFetchCalltype

Record of a single mocked fetch, pairing the request with the response the handler returned.

{
	readonly request: Request;
	readonly response: Response;
}
Go

MockAPIRequestCalltype

Record of a single request build, capturing the endpoint, payload, options, and built request.

{
	readonly endpoint: AnyEndpoint;
	readonly payload: unknown;
	readonly options: RequestOptions | undefined;
	readonly request: Request;
}
Go

MockAPIResponseCalltype

Record of a single response parse, capturing the endpoint, response, and parsed result.

{
	readonly endpoint: AnyEndpoint;
	readonly response: Response;
	readonly result: unknown;
}
Go

MockAPIProviderclass

Provider that records API calls and serves them from a handler without sending network requests.

new MockAPIProvider<P, R>(handler: RequestHandler = _mockHandler, source: APIProvider<P, R> = new ClientAPIProvider({ url: "https://api.mock.com" }))
Go

APIProviderclass

Abstract base for API providers that send requests to a set of Endpoint definitions rooted at a common base URL.

new APIProvider<P, R>()
Go

APIProvider.renderURL()method

Render the full final URL for an API request to a given endpoint with a given payload.

renderURL(endpoint: Endpoint<PP, RR>, payload: PP, caller?: AnyCaller): URL
Go

APIProvider.createRequest()method

Create a Request that targets this endpoint with a given base URL.

createRequest(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request
Go

APIProvider.fetch()method

Send a Request and return its Response (defaults to the JavaScript fetch() API).

fetch(request: Request): Promise<Response>
Go

APIProvider.parseResponse()method

Parse an HTTP Response for this endpoint into a result value.

parseResponse(_endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>
Go

APIProvider.call()method

Send a payload to an Endpoint and retrieve the parsed result.

call(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Promise<RR>
Go

LoggingAPIProviderclass

Provider that logs fetches to the console to keep useful request/response logs in production.

new LoggingAPIProvider<P, R>(source: APIProvider<P, R>, onRequest: Callback<[Request]> = logRequest, onResponse: Callback<[Response, Request]> = logRequestResponse, onError: Callback<[reason: unknown, Request]> = logRequestError)
Go

EndpointCallbacktype

A function that handles an endpoint request, receiving a validated payload and returning a result.

(payload: P, request: Request, context: C) => R | Response | Promise<R | Response>
Go

EndpointHandlerinterface

A typed endpoint definition paired with its implementation callback.

{
	readonly endpoint: Endpoint<P, R>;
	readonly callback: EndpointCallback<P, R, C>;
}
Go

AnyEndpointHandlertype

An EndpointHandler with any payload and result type, for use where the specific types don't matter.

EndpointHandler<any, any, C>
Go

EndpointHandlerstype

A collection of endpoint handlers that can be matched and invoked by handleEndpoints().

Iterable<AnyEndpointHandler<C>>
Go

handleEndpoints()function

Handle a Request with the first matching endpoint handler after stripping any base-path prefix from the request pathname.

handleEndpoints(base: PossibleURL, handlers: EndpointHandlers<C>, request: Request, context: C, caller?: AnyCaller): Promise<Response>
handleEndpoints(base: PossibleURL, handlers: EndpointHandlers<void>, request: Request, context?: undefined, caller?: AnyCaller): Promise<Response>
Go

Endpointclass

A typed API resource definition pairing a method and path with payload and result schemas.

new Endpoint<P, R>(method: RequestMethod, path: AbsolutePath, payload: Schema<P>, result: Schema<R>)
Go

Endpoint.renderPath()method

Render the path for this endpoint with the given payload.

renderPath(payload: P, caller: AnyCaller = this.renderPath): AbsolutePath
Go

Endpoint.match()method

Match a method/path pair against this endpoint and return any matched {placeholder} params.

match(method: RequestMethod, path: AbsolutePath, caller: AnyCaller = this.match): RequestParams | undefined
Go

Endpoint.handler()method

Create an endpoint handler pairing for this endpoint.

handler(callback: EndpointCallback<P, R, C>): EndpointHandler<P, R, C>
Go

Endpoint.toString()method

Convert this endpoint to a string in METHOD /path form, e.g. GET /user/{id}

toString(): string
Go

AnyEndpointtype

An Endpoint with any payload and result type, for use where the specific types don't matter.

Endpoint<any, any>
Go

Endpointstype

An immutable list of endpoints.

ImmutableArray<AnyEndpoint>
Go

PayloadTypetype

Extract the payload type from an Endpoint.

X extends Endpoint<infer Y, unknown> ? Y : never
Go

EndpointTypetype

Extract the result type from an Endpoint.

X extends Endpoint<unknown, infer Y> ? Y : never
Go

HEAD()function

Define a HEAD endpoint at a path, with validated payload and result types.

HEAD(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
HEAD(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
HEAD(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

GET()function

Define a GET endpoint at a path, with validated payload and result types.

GET(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
GET(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
GET(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

POST()function

Define a POST endpoint at a path, with validated payload and result types.

POST(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
POST(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
POST(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

PUT()function

Define a PUT endpoint at a path, with validated payload and result types.

PUT(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
PUT(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
PUT(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

PATCH()function

Define a PATCH endpoint at a path, with validated payload and result types.

PATCH(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
PATCH(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
PATCH(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

DELETE()function

Define a DELETE endpoint at a path, with validated payload and result types.

DELETE(path: AbsolutePath, payload?: Schema<P>, result?: Schema<R>): Endpoint<P, R>
DELETE(path: AbsolutePath, payload: Schema<P>): Endpoint<P, undefined>
DELETE(path: AbsolutePath, payload: undefined, result: Schema<R>): Endpoint<undefined, R>
Go

shelving/bunmodule

DBProvider implementation for PostgreSQL using Bun's built-in Bun.sql API. No external database driver is required.

Go

BunPostgresProviderclass

PostgreSQL database provider backed by Bun's built-in Bun.SQL driver.

new BunPostgresProvider<I, T>(sql: SQL)
Go

shelving/cloudflaremodule

DBProvider implementations for Cloudflare Workers. Two backends are available: Workers KV for simple key-value storage and D1 for relational SQL.

Go

CloudflareKVProviderclass

Cloudflare Workers KV database provider.

new CloudflareKVProvider<I, T>(kv: KVNamespace)
Go

CloudflareD1Providerclass

SQLite database provider backed by Cloudflare D1.

new CloudflareD1Provider<I, T>(db: D1Database)
Go

KVNamespaceinterface

Minimal interface matching the Cloudflare Workers KV namespace runtime object.

{
	get(key: string, options: { type: "json" }): Promise<unknown>;
	put(key: string, value: string): Promise<void>;
	delete(key: string): Promise<void>;
}
Go

KVNamespace.get()method

get(key: string, options: { type: "json" }): Promise<unknown>
Go

KVNamespace.put()method

put(key: string, value: string): Promise<void>
Go

KVNamespace.delete()method

delete(key: string): Promise<void>
Go

D1Valuetype

Value that can be passed through the D1 Worker API as a bound parameter.

boolean | null | number | string
Go

D1Metainterface

Metadata returned by the D1 Worker API alongside a query result.

{
	readonly changed_db?: boolean | undefined;
	readonly duration?: number | undefined;
	readonly last_row_id?: number | undefined;
	readonly rows_read?: number | undefined;
	readonly rows_written?: number | undefined;
}
Go

D1Resultinterface

Result object returned by D1PreparedStatement.run().

{
	readonly success: boolean;
	readonly meta?: D1Meta | undefined;
	readonly results?: readonly T[] | undefined;
}
Go

D1ExecResultinterface

Result object returned by D1Database.exec().

{
	readonly count: number;
	readonly duration: number;
}
Go

D1PreparedStatementinterface

Minimal prepared statement interface for D1 databases and sessions.

{
	bind(...values: D1Value[]): D1PreparedStatement;
	first<T = Record<string, unknown>>(column?: string): Promise<T | null>;
	raw<T = unknown[]>(options?: { columnNames?: boolean }): Promise<readonly T[]>;
	run<T extends Record<string, unknown> = Record<string, unknown>>(): Promise<D1Result<T>>;
}
Go

D1PreparedStatement.bind()method

bind(...values: D1Value[]): D1PreparedStatement
Go

D1PreparedStatement.first()method

first(column?: string): Promise<T | null>
Go

D1PreparedStatement.raw()method

raw(options?: { columnNames?: boolean }): Promise<readonly T[]>
Go

D1PreparedStatement.run()method

run(): Promise<D1Result<T>>
Go

D1Databaseinterface

Minimal D1 binding/session interface used by CloudflareD1Provider.

{
	batch<T extends Record<string, unknown> = Record<string, unknown>>(
		statements: readonly D1PreparedStatement[],
	): Promise<readonly D1Result<T>[]>;
	exec?(query: string): Promise<D1ExecResult>;
	prepare(query: string): D1PreparedStatement;
}
Go

D1Database.batch()method

batch(statements: readonly D1PreparedStatement[]): Promise<readonly D1Result<T>[]>
Go

D1Database.exec()method

exec(query: string): Promise<D1ExecResult>
Go

D1Database.prepare()method

prepare(query: string): D1PreparedStatement
Go

shelving/dbmodule

Typed database provider abstraction. Define your schema once as a Collection, then swap providers (in-memory, SQLite, Firestore, Cloudflare D1, …) without changing any call sites. Providers are composable wrappers — add validation, logging, or caching by stacking them in a chain.

Go

IDconstant

Default identifier schema (integer) used when a collection doesn't supply its own.

Go

Collectionclass

Declarative definition of a database collection/table.

new Collection<N, I, T>(name: N, id: Schema<I>, data: Schemas<T> | DataSchema<T>)
Go

COLLECTION()function

Create a Collection from a name, an identifier schema, and a data schema.

COLLECTION(name: K, id: Schema<I>, data: Schemas<T> | DataSchema<T>): Collection<K, I, T>
Go

CollectionNametype

Extract the string name from a Collection instance.

C extends Collection<infer N, infer _I, infer _T> ? N : never
Go

CollectionIdentifiertype

Extract the Identifier type from a Collection instance.

C extends Collection<infer _N, infer I, infer _T> ? I : never
Go

CollectionDatatype

Extract the Data type from a Collection instance.

C extends Collection<infer _N, infer _I, infer T> ? T : never
Go

CollectionItemtype

Extract the Item type from a Collection instance.

Item<CollectionIdentifier<C>, CollectionData<C>>
Go

OptionalCollectionItemtype

Extract the optional (possibly undefined) Item type from a Collection instance.

OptionalItem<CollectionIdentifier<C>, CollectionData<C>>
Go

CollectionItemstype

Extract the array of Item types from a Collection instance.

Items<CollectionIdentifier<C>, CollectionData<C>>
Go

Collectionstype

A readonly array of Collection instances, optionally narrowed to a standardised Identifier and Data type.

ImmutableArray<Collection<string, I, D>>
Go

CollectionNamestype

Extract the union of string collection names from a Collections type.

C[number]["name"]
Go

CollectionsDatabasetype

Convert a Collections array type to a database-style object mapping in { name: data } format.

{
	[E in C[number] as E extends Collection<infer N, Identifier, Data> ? N : never]: E extends Collection<string, Identifier, infer T>
		? T
		: never;
}
Go

ItemStoreclass

Store that fetches and tracks a single item by ID in a collection from a database provider.

new ItemStore<I, T>(collection: Collection<string, I, T>, id: I, provider: DBProvider<I>, memory?: MemoryDBProvider<I>)
Go

QueryStoreclass

Store that runs a query against a collection from a database provider and tracks its matching items.

new QueryStore<I, T>(collection: Collection<string, I, T>, query: Query<Item<I, T>>, provider: DBProvider<I>, memory?: MemoryDBProvider<I>)
Go

DBCacheclass

Cache of CollectionCache objects for multiple collections.

new DBCache<I, T>(provider: DBProvider<I, T>)
Go

DBCache.get()method

Get (or create) the CollectionCache for the given collection.

get(collection: Collection<string, II, TT>): CollectionCache<II, TT>
get(collection: Collection<string, I, T>): CollectionCache<I, T>
Go

DBCache.getItem()method

Get (or create) an ItemStore for a collection/id in one hop.

getItem(collection: Collection<string, II, TT>, id: II): ItemStore<II, TT>