Askr
Server & APIs

HTTP Contracts

Use http contracts with the current published Askr packages.

  • @askrjs/fetch0.0.1
  • @askrjs/schema0.0.2
  • @askrjs/server/openapi0.0.3

How to use http contracts

Define an executable schema once and reuse its jsonSchema representation in the HTTP contract and generated-client workflow.

  1. Import the published @askrjs/fetch and @askrjs/schema and @askrjs/server/openapi entrypoint.
  2. Keep http contracts configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
import { schema } from '@askrjs/schema';

export const projectInput = schema.object({
  name: schema.string({ minLength: 1 }),
  ownerId: schema.uuid(),
});

const parsed = projectInput.safeParse(await request.json());
const jsonSchema = projectInput.jsonSchema;

Endpoint descriptors

get(), post(), put(), patch(), del(), head(), and options() from @askrjs/fetch each return an EndpointBuilder you chain .params<T>(), .query<T>(), .headers<T>(), .body(codec), .returns(status, codec), and .errors({...}) on to describe one HTTP operation. defineApi({...}, metadata?) collects a map of these builders into an ApiDefinition that both the client and the server side of the contract can share. Paths use OpenAPI-style {name} parameters — colon params and wildcards are rejected, and a declared parameter name must exactly match one in the path.

Typed client boundary

createClient(api, { baseUrl, ... }) turns an ApiDefinition into an object whose methods mirror the keys you passed to defineApi(), each one typed from that endpoint's params, query, headers, and body plus its registered response and error codecs. Call inputs and outputs come straight from the descriptor, so nothing about fetch, headers, or serialization needs to leak into calling code. The same descriptors also drive createFetch() for one-off calls that don't need a full client.

Schemas

@askrjs/schema builds executable schemas — schema.object(), schema.string(), schema.array(), and so on — that double as runtime validators and OpenAPI documentation. Any object with a safeParse(value) method satisfies the Validator contract that @askrjs/fetch's codecs and parameter specs expect, so you aren't locked into @askrjs/schema specifically to validate params, query values, headers, or bodies.

OpenAPI artifacts

@askrjs/server/openapi's createApi() attaches request and response schemas to routes as you register them, and api.toOpenApiDocument() produces a deterministic, deeply frozen OpenAPI 3.1.2 document from that registration. The askr CLI's askr openapi command writes that document to YAML on disk, and askr openapi --check compares it byte-for-byte without writing, which makes it a clean CI gate against undocumented drift.