Extend

Create a Generator

Build and ship your own code generator or client from a Kizuna API using createGenerator.

Beta

The generator API is new and still settling. createGenerator and the walked route shape may change while v2 is in beta, so pin your version if you depend on them.

createGenerator from kizunajs/generator lets you walk your api and produce any output, such as a typed client for another language, documentation, or a route manifest.

The Swift and Kotlin clients, the OpenAPI document, and kizuna routes are all written with it.

Whether a generator goes first-party comes down to demand, not age. If enough teams need a target, we will add it. What we will not take on is one a handful of people need, since we maintain everything we merge. The generator API is public, so you can build and publish your own today.

How it works

You provide a factory function that receives your options and returns two methods:

  • processRoute is called once for every route in the api
  • finalize is called after all routes are processed and returns your output

createGenerator handles walking the api, flattening nested route groups, and resolving each route's deprecated declaration automatically.

createGenerator

generator.ts
import { createGenerator, type GeneratorRouteContext } from 'kizunajs/generator';

interface MyOptions {
    prefix?: string;
}

export const generateRouteList = createGenerator((options: MyOptions) => {
    const lines: string[] = [];

    return {
        processRoute({ routeKey, route, deprecated }: GeneratorRouteContext) {
            const prefix = options.prefix ?? '';
            const tag = deprecated ? ' (deprecated)' : '';
            lines.push(`${prefix}${route.method} ${route.path}${tag}`);
        },
        finalize() {
            return lines;
        },
    };
});
scripts/list-routes.ts
import kizuna from '../kizuna.config';
import { generateRouteList } from './generator';

const list = generateRouteList(kizuna.api, {
    prefix: '> ',
});

GeneratorRouteContext

Each processRoute call receives:

PropertyTypeDescription
routeKeystringDot-separated key path, e.g. users.getUser
routeRouteDefinitionThe full route definition
routeTagsstring[]The tags of every k.routes group the route sits inside, outermost first
deprecatedbooleantrue when the route is deprecated
deprecationMessagestring | undefinedThe route's deprecated string, or the object form's message

Deprecation

Route deprecation arrives on the context, read from the route's deprecated declaration. Fields declare theirs in Zod metadata; read it off any schema you walk with readDeprecation from kizunajs/generator:

import { readDeprecation } from 'kizunajs/generator';

const deprecation = readDeprecation(fieldSchema);
if (deprecation) {
    // deprecation.message is the string form's message, or undefined
}

See Deprecations for the authoring side.

Examples

A schema's declared example values read off the same surface, with readMetaExamples. It takes example first and then examples, each of which holds one value or a list, and answers with them in order:

import { readMetaExamples } from 'kizunajs/generator';

const [example] = readMetaExamples(fieldSchema);

On this page