Create a TypeScript Client Wrapper
Build and ship your own TypeScript client wrapper using the types and the route metadata @kizunajs/fetch carries.
The wrapper surface is new and still settling. The types @kizunajs/fetch exports may change while v2 is in beta, so pin your version if you depend on it.
A wrapper builds on the fetch client your app already has, the one kizuna generate writes. Wrap it to build hooks, an SDK layer, or any other integration. @kizunajs/tanstack-query is one of these, and it takes the client and nothing else.
Whether a client goes first-party comes down to demand, not age. If it is something most teams on Kizuna would reach for, we will add it. What we will not take on is one a handful of people need, since we maintain everything we merge. The client API is public, so you can build and publish your own today.
Pattern
import { apiClient } from './api-client';
export function createMyClient() {
return {
getUser: (id: string) =>
apiClient.users.getUser({
params: {
id,
},
}),
createUser: (data: Parameters<typeof apiClient.users.createUser>[0]['body']) =>
apiClient.users.createUser({
body: data,
}),
};
}Reading the route off a method
A wrapper that treats routes generically, rather than naming each one, needs to know what each method answers: its method, its path, which statuses it declares. Every client method carries its own route, and routeOf reads it:
import { routeOf } from '@kizunajs/fetch';
const route = routeOf(apiClient.users.getUser);
route?.method; // 'GET'
route?.path; // '/users/:id'This is what lets a wrapper take the client alone. A GET gets query semantics, anything else gets mutation semantics, and the declared statuses say which responses are data. routeOf answers undefined for anything that is not a client method, so a group or a stray value is easy to skip while walking the client.
Types
The types from @kizunajs/fetch:
| Type | Description |
|---|---|
Client<T, Codes> | The full typed client shape for a set of routes |
ClientArgs<Route> | What one route's method accepts: params, query, body, headers |
ClientResponse<Route, Codes> | The discriminated union one route's method resolves to |
ClientConfig | What createClient takes |
These are generic over a route or a set of routes, so pass typeof route to type a single wrapper method and typeof routes to type a whole surface.