Client
Build-time generator that turns a server’s services into a fully typed client SDK.
@ozaco/devkit/clientThe client module generates a fully typed client SDK from your server's services at build time. clientPlugin plugs into any unplugin-compatible bundler (rolldown/tsdown, vite, webpack, esbuild); generate is the same routine exposed as a plain async function for use outside a bundler.
On build start it bundles the entry services module through rolldown — with devkit's std/server/db/ai resolve plugins so the alias specifiers resolve — imports the bundle to obtain live service objects, mounts each on a headless Node gateway, and walks the mounted routes to build a route manifest. From that manifest it emits a source client.ts (in outDir, default .ozaco/gen) for inspection plus a built client.js and client.d.ts (in dist) whose createClient calls connect from the client runtime.
The bundler config only ever passes string options, so registering the plugin never imports any server code — the server and std modules are imported lazily inside generate at build time. Routes are only knowable after mount (their REST settings are lazy futures) and the services use server:* aliases only the bundler resolves, which is why the bundle-write-import-mount dance is necessary.
Plugin
The unplugin factory registered on a bundler.
clientPlugin
Build-time unplugin that generates the client SDK on `buildStart`.
const clientPlugin: UnpluginInstance<ClientPluginOptions, false>
clientPlugin.rolldown(options: ClientPluginOptions)Add to an unplugin-compatible bundler. On buildStart it runs generate(options): bundles and imports the entry services, mounts each service on a headless gateway, collects the route manifest, and writes the source client.ts (in outDir) plus the built client.js and client.d.ts (in dist). Reachable through every unplugin adapter — .rolldown(), .vite(), .webpack(), .esbuild(), and so on.
// tsdown.config.ts
import { clientPlugin } from '@ozaco/devkit/client'
export default defineConfig({
plugins: [clientPlugin.rolldown({ entry: './src/services' })],
})Functions
The imperative generator behind the plugin.
generate
Generate the client SDK once, outside a bundler build.
function generate(options: ClientPluginOptions): Promise<void>The core behind clientPlugin. Resolves entry, bundles it through rolldown with the resolve plugins (aliases resolved; other @ozaco/*, npm and node-builtin specifiers left external), writes a unique temp module and imports it for live service objects, then mounts them on a headless Node gateway and collects the manifest from the mounted routes. Only mounted service routes are captured — listen-registered dynamic routes are not. The whole flow runs on the ozaco runtime (std:io, std:effect, std:result); a failed run throws an Error.
Call it directly from a script when you want to regenerate the client without wiring a bundler plugin.
import { generate } from '@ozaco/devkit/client'
await generate({
entry: './src/services',
outDir: '.ozaco/gen',
dist: 'dist',
})Types
ClientPluginOptions
Configuration for `clientPlugin` and `generate`.
interface ClientPluginOptions {
entry: string
servicesExport?: string
outDir?: string
dist?: string
servicesModule?: string
servicesType?: string
clientModule?: string
platform?: 'node' | 'browser' | 'neutral'
}entry (required) is the module exporting the services record; it is bundled and imported at build time, not by the config.
servicesExport names the export on entry holding that record (default 'services'). servicesType is the type-only export used for the generated Services type (default 'Services'). servicesModule overrides the specifier the built client.d.ts imports that type from (default './<entry basename>', the sibling built declaration). clientModule is the specifier for the generic client runtime (default 'server:client').
outDir is where the inspectable source client.ts is written (default '.ozaco/gen') and dist where the built client.js + client.d.ts go (default 'dist'). platform selects the export conditions and node-builtin handling for the internal rolldown pass (default 'node').