Skip to content

api-contract

The contract of an API one module exposes to another: which methods it promises, and a Standard Schema over each method’s arguments and return value.

The schemas are plain objects over plain functions, which a type guard already is, so a contract can cross a boundary between two copies of a library and still be run by whichever copy reads it. The builders here turn the guards a module already has into the two shapes a method contract needs: one value (an output) and one argument list (an input). zod / valibot / arktype schemas plug into the same slots unchanged; this module just does not make every provider bundle one to describe two arguments.

Running the schemas is left to whoever owns the call path, since that is where an issue can be reported.

Interface Description
ApiContractSchemaBuilders The schema builders of this module with the Standard Schema vendor already bound, as createApiContractSchemaBuilders returns them.
ApiMethodContract The payload schemas for a single API method. Both halves are optional: a method may declare only its input, only its output, neither (the entry then just declares that the method must exist), or both.
CreateArgumentsSchemaOptions Options for createArgumentsSchema.
CreateTypeGuardSchemaParams Parameters for createTypeGuardSchema: the guard, what it expects, and optionally the schema’s vendor.
ExpectedTypeGuard One value a schema accepts, described by a type guard and by what it expects, for the issue message.
ObjectGuardOptions Options for objectGuard.
OptionsGuardOptions Options for optionsGuard.
Function Description
arrayGuard Widens a guard to an array whose every item itemGuard accepts.
createApiContractSchemaBuilders Binds the Standard Schema vendor once, so a contract does not pass it to every schema builder. Destructure the result under the builders’ own names and the calls read exactly as the unbound ones do: ts const \{ createArgumentsSchema, createTypeGuardSchema \} = createApiContractSchemaBuilders('my-plugin');
createArgumentsSchema Builds the input schema of a method contract: a schema over the method’s ARGUMENT LIST, one type guard per parameter. An argument that fails its guard is reported with its index as the issue path, and an argument list longer than the parameter list is refused. A missing argument reaches its guard as undefined, so an optional parameter’s guard accepts undefined (see optionalGuard).
createExpectedTypeGuard Pairs a type guard with what it expects.
createTypeGuardSchema Builds a schema over one value from a type guard: the output schema of a method contract, typically.
defineApiContract States a contract against an API type, so every entry is checked against its method and the schema builders inside it infer their types from the method rather than from a restated tuple. It returns the contract as is.
instanceOfGuard Builds a guard accepting an instance of a class, or of a class derived from it, expecting an instance of the class’s name.
literalGuard Builds a guard accepting exactly the listed values.
nullableGuard Widens a guard to also accept null.
objectGuard Builds a guard accepting an object whose every listed property its guard accepts, as objectTypeGuard does, expecting the properties and what each expects: \{ alias?: a string; path: a string \}, after the ObjectGuardOptions.description when one is given. A key is marked optional when it is listed in ObjectTypeGuardOptions.exactOptionalKeys; without that list, an optional property’s guard says or undefined itself.
optionalGuard Widens a guard to also accept undefined, which is what an optional parameter receives when it is left out.
optionsGuard Builds a guard accepting an options bag: an object whose every option may be absent, or undefined, and must otherwise pass its guard. A key no guard names is let through unless OptionsGuardOptions.shouldRejectUnknownKeys is set. It expects the options and what each expects: \{ prefix?: a string; isHidden?: a boolean \}, after the OptionsGuardOptions.description when one is given.
unionGuard Builds a guard accepting what any of the given guards accepts, expecting their expected texts joined by or.
Type Description
ApiContract The contract an API declares: every key is a method the API promises to expose, and its value optionally carries the payload schemas for that method. Typed over the API when one is named: ApiContract<MyApi> has exactly one entry per function member of MyApi (a missing method, an extra one or a misspelled one does not compile), and each entry’s schemas must produce that method’s parameters and awaited return value. Without a type argument, or for object, it is the loose record a reader that knows nothing about the API sees.
ApiMethodName The names of the function members of an API, which are exactly the keys a typed ApiContract has.
ApiMethods The function members of an API.
ArgumentTypeGuards One type guard per parameter of a method, in order.
OptionGuards One guard per option of an all-optional object type, as optionsGuard takes them: each describes a PRESENT option, so it does not accept undefined. A required property of T takes never, so a type that is not all-optional does not compile.
PropertyGuards One guard per property of an object type, as objectGuard takes them, typed as PropertyTypeGuards types the bare guards.
TypedApiContract The ApiContract of a named API: one entry per function member, each typed against that member. Both schemas are REQUIRED here, so a typed contract is a full description of every signature and a \{\} entry does not compile. Only the loose form leaves them optional.
Variable Description
BOOLEAN_GUARD Accepts a boolean.
NUMBER_GUARD Accepts a number.
STRING_ARRAY_GUARD Accepts an array of strings.
STRING_GUARD Accepts a string. Spread it to say what the string is: \{ ...STRING_GUARD, expected: 'a path' \}.
UNDEFINED_GUARD Accepts undefined, which is the output of a method returning void or Promise<void>.