npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@redocly/client-generator

v0.4.7

Published

Generate typed, zero-dependency TypeScript clients (fetch, auth, retries, middleware, SSE) from OpenAPI descriptions.

Readme

@redocly/client-generator

Generate a typed TypeScript client from an OpenAPI description. See https://github.com/Redocly/redocly-cli for the full project.

[!WARNING] This package is experimental: the generated output, options, and the plugin API may change in any minor release until it is declared stable. Pin your version if you depend on the output, and expect to regenerate when you upgrade. Feedback is very welcome while we stabilize it.

The generated client uses only web-standard APIs (fetch, AbortController, URLSearchParams), so by default it is a single self-contained file with zero runtime dependencies that runs in browsers, Node ≥ 18, Bun, Deno, and edge runtimes. (Running the generator itself requires the Node version in this package's engines field.) Code is printed through per-language text printers; typescript is the only peer dependency — optional, needed only when generation bakes a --setup module, and it must be 6.x there (TypeScript 7's native compiler has no compiler API). Apps that only consume a generated client don't need it at all, and can compile the generated code with any TypeScript, including 7.

This package is the engine behind the generate-client command — install @redocly/cli to run it from the command line or redocly.yaml. How to use the generated client — auth, middleware, retries, pagination, Server-Sent Events, and the add-on generators (zod, tanstack-query, swr, mock, transformers) — is documented in Use the generated client. This README covers using the package programmatically.

Basic usage

Generate a client

import { generateClient } from '@redocly/client-generator';

const result = await generateClient({
  api: './openapi.yaml', // file path or URL; OpenAPI 3.0/3.1/3.2 or Swagger 2.0
  output: './src/api/client.ts',
  generators: ['typescript', 'zod'],
});

console.log(`Wrote ${result.files.length} file(s), ${result.bytes} bytes.`);

Every redocly.yaml client option is accepted with the same name and default — see the client configuration reference. For type-safe authoring of a standalone options object, annotate it with satisfies GenerateClientOptions.

Build extra client instances

The generated module exports its operation descriptors, so an app can build additional instances with independent configuration and credentials over the same generated code:

import { createClient, OPERATIONS, type Ops } from './client.ts';

const internal = createClient<Ops>(OPERATIONS, {
  serverUrl: 'https://api.example.com',
  auth: { basic: { username: 'svc', password: 's3cr3t' } },
});

Write a custom generator

A custom generator reads the same API model the built-ins consume, runs in the same pass, and returns files. Generators print text: Printer handles indentation, and tsType is the same schema→type renderer the built-in sdk uses, so the mapping (refs, arrays, unions, formats, parenthesization) matches the generated client exactly:

// response-map-generator.ts
import { defineGenerator, Printer } from '@redocly/client-generator';
import { tsType } from '@redocly/client-generator/generate';

export default defineGenerator({
  name: 'response-map',
  requires: ['typescript'],
  run({ model, output }) {
    const printer = new Printer();
    // One `ResponseShapes` entry per operation with a JSON success body.
    printer.block(
      'export type ResponseShapes = {',
      () => {
        for (const service of model.services) {
          for (const op of service.operations) {
            const success = op.successResponses.find((r) => r.contentType.includes('json'));
            if (success) printer.line(`${op.name}: ${tsType(success.schema)};`);
          }
        }
      },
      '};'
    );
    return [{ path: output.path.replace(/\.ts$/, '.responses.ts'), content: printer.toString() }];
  },
});

For a trivial artifact, returning a plain string as content works too — no toolkit required. Select the generator in generators by import specifier (a path or a package name), or register it inline via customGenerators and select it by name. A custom generator never adds dependencies to the generated client. See Custom generators.

Pre-configure a published SDK

The setup option takes a module that default-exports a { config, middleware } object (optionally wrapped in defineClientSetup for editor typing); its defaults are included in the generated client so a published SDK ships them built in, and consumers can still override. See Publisher defaults.

API

generateClient

Loads the description, builds the client, and writes the files.

async function generateClient(options: GenerateClientOptions): Promise<GenerateClientResult>;

type GenerateClientResult = {
  outputPath: string; // the `output` anchor path (the entry file in multi-file modes)
  bytes: number; // total bytes written
  files: Array<{ path: string; bytes: number }>; // every file written to disk
};

GenerateClientOptions is the options type (src/types.ts) (api and output required; outputMode, runtime, importExt, argsStyle, errorMode, dateType, serverUrl, mockData, mockSeed, generators, customGenerators, options, setup, pagination, queryKeyPrefix, goPackage, cliOutput, codeSamples, docs, docsFrontmatter optional) plus an optional resolved Redocly config used to load the description.

collectGeneratedFiles

Runs the configured generators against a built model and returns the files in memory, without writing to disk. Imported from @redocly/client-generator/generate — the generation-time entry; the package root stays a small authoring surface:

function collectGeneratedFiles(
  model: ApiModel,
  options: {
    outputPath: string;
    outputMode: OutputMode;
    emit: EmitOptions;
    generators: string[];
    registry?: Map<string, GeneratorDescriptor>; // defaults to the built-ins
  }
): GeneratedFile[];

defineGenerator

Authors a custom generator ({ name, run } plus optional requires/errorModes/dateTypes compatibility metadata, validated up front):

function defineGenerator(generator: CustomGenerator): CustomGenerator;

The @redocly/client-generator/generate entry also exports the TypeScript renderers the built-ins use (tsType, tsJsdoc, codeLiteral, operationSignature, pascalCase, safeIdent). The package root exports the IR types plus the language-neutral toolkit. A custom generator emits TypeScript exactly as the first-party ones do. See the typescript-types-generator example.

defineClientSetup

Optional typing helper for authoring a publisher setup module — a plain default-exported { config, middleware } object works too, with no imports:

function defineClientSetup(setup: {
  config?: ClientConfig;
  middleware?: Middleware[];
}): ClientSetup;

A setup module may import only from @redocly/client-generator, so it never adds a dependency to the client (the import is stripped at generation time).

Examples

Runnable examples — from a zero-install quickstart to middleware, publisher setup, SSE streaming, pagination, and custom generators — live in tests/e2e/generate-client/examples. Each is a standalone Vite app with a checked-in, drift-checked generated client.

Documentation

Development

This package is part of the Redocly CLI monorepo. Run all commands from the repo root:

npm run compile                 # build this package
npm run unit                    # unit tests
VITEST_SUITE=e2e npx vitest run tests/e2e/generate-client/   # behavioral e2e

Each generator that embeds a runtime keeps its sources in its own folder (src/generators/<name>/runtime/ — real, unit-testable modules that generation embeds), the IR lives in src/intermediate-representation/, and the generators in src/generators/.