Skip to content

meta-engine/openapi-fetch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

MetaEngine OpenAPI Fetch

npm version npm downloads License: MIT

Generate framework-agnostic TypeScript services and models from OpenAPI/Swagger specifications using the native Fetch API.

Runs on Node, browsers, Vite, SvelteKit, Next.js, Bun, Deno, and any TS runtime that ships fetch. No runtime dependencies in the generated code.


Quick Links


Features

  • Framework-agnostic — works in any TS runtime with fetch
  • Native Fetch API — zero runtime dependencies in generated code
  • Production-ready — Bearer auth, timeouts, retries, custom headers, middleware, all via CLI flags
  • TypeScript — fully typed clients and models
  • Result pattern — opt into ApiResult<T> for structured error handling without exceptions
  • Middleware hooksonRequest / onResponse / onError composable around the request pipeline
  • Vite + SvelteKit--import-meta-env for import.meta.env access
  • Tree-shakeable — separate file per model and per service

Installation

npm install --save-dev @metaengine/openapi-fetch

Or use directly with npx:

npx @metaengine/openapi-fetch <input> <output>

Requirements

  • Node.js 18.0 or later
  • .NET 8.0 or later runtime (Download)
  • A TS runtime that supports fetch (Node 18+, all modern browsers, Bun, Deno)

Quick Start

Basic

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --documentation \
  --result-pattern

Production setup

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --bearer-auth API_TOKEN \
  --timeout 30 \
  --retries 3 \
  --custom-header X-Tenant-ID=TENANT_ID \
  --error-handling

With npm scripts

Add to your package.json:

{
  "scripts": {
    "generate:api": "metaengine-openapi-fetch api.yaml ./src/api --bearer-auth API_TOKEN --timeout 30 --retries 3"
  }
}

Then run:

npm run generate:api

Runtime-specific examples

Vite / SvelteKit (uses import.meta.env):

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --import-meta-env \
  --base-url-env VITE_API_URL

Next.js:

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --base-url-env NEXT_PUBLIC_API_URL

Plain Node / Bun / Deno:

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --base-url-env API_BASE_URL

More examples

# From URL
npx @metaengine/openapi-fetch https://api.example.com/openapi.json ./src/api

# Filter by OpenAPI tags
npx @metaengine/openapi-fetch api.yaml ./src/api --include-tags users,auth

# Multiple custom headers from env vars
npx @metaengine/openapi-fetch api.yaml ./src/api \
  --custom-header X-Tenant-ID=TENANT_ID \
  --custom-header X-App-Id=APP_ID

CLI Options

Option Description Default
--include-tags <tags> Filter by OpenAPI tags (comma-separated, case-insensitive) -
--base-url-env <name> Environment variable name for base URL API_BASE_URL
--service-suffix <suffix> Service naming suffix Api
--options-threshold <n> Parameter count for options object 4
--documentation Generate JSDoc comments false
--import-meta-env Use import.meta.env for env access (Vite, SvelteKit) false
--result-pattern Return ApiResult<T> instead of T for structured error handling false
--middleware Emit middleware hooks (onRequest, onResponse, onError) in client false
--error-handling Smart error handling based on HTTP status semantics false
--bearer-auth <env-var-name> Bearer token from env var (adds Authorization: Bearer <token>) -
--timeout <seconds> Request timeout in seconds for all operations -
--retries <max-attempts> Enable retries with exponential backoff (status codes 429, 503) -
--custom-header <header=envVarName> Static header from env var. Repeatable. -
--strict-validation Strict OpenAPI validation false
--date-transformation Convert date strings in responses to Date objects false
--clean Clean output directory (remove files not in generation) false
--verbose Enable verbose logging false
--type-mapping <slug=target> Override TS type for an OpenAPI format. Repeatable. See Type mapping overrides -
--help, -h Show help message -

Generated Code Structure

output/
  ├── models/                    # One file per model
  │   ├── user.ts               # export interface User { ... }
  │   ├── product.ts
  │   └── ...
  ├── api/                       # One file per service/tag
  │   ├── users.api.ts          # All user operations
  │   ├── products.api.ts
  │   └── ...
  ├── client.ts                  # ClientConfig, createClient, getDefaultClient
  └── errors.ts                  # ApiError, error helpers

Production-ready features

Bearer authentication

npx @metaengine/openapi-fetch api.yaml ./src/api --bearer-auth API_TOKEN

Generated client.ts reads process.env.API_TOKEN (or import.meta.env.API_TOKEN with --import-meta-env) and adds Authorization: Bearer <token> to every request. Missing env vars produce a clear error message at startup, not a silent 401.

Timeout

npx @metaengine/openapi-fetch api.yaml ./src/api --timeout 30

Uses AbortSignal.timeout(seconds * 1000) and composes correctly with consumer-supplied AbortSignal via AbortSignal.any.

Retries with exponential backoff

npx @metaengine/openapi-fetch api.yaml ./src/api --retries 5

Retries on 429 and 503 only (configurable defaults from the underlying engine). Exponential backoff: base 0.5s, max delay 30s.

Custom headers from env vars

npx @metaengine/openapi-fetch api.yaml ./src/api \
  --custom-header X-Tenant-ID=TENANT_ID \
  --custom-header X-App-Id=APP_ID

Repeatable. Each header value comes from a separate env var, validated at startup.

Result pattern

npx @metaengine/openapi-fetch api.yaml ./src/api --result-pattern

Operations return ApiResult<T> instead of throwing — useful when you want to handle errors as values rather than exceptions:

const result = await usersApi.getUser('123');
if (result.ok) {
  console.log(result.data.name);
} else {
  console.error(result.error.code, result.error.message);
}

Middleware

npx @metaengine/openapi-fetch api.yaml ./src/api --middleware

Generated client emits a Middleware interface and accepts an optional middleware array on ClientConfig:

const client = createClient({
  baseUrl: 'https://api.example.com',
  middleware: [
    {
      onRequest: (req) => { console.log('→', req.url); return req; },
      onResponse: (res) => { console.log('←', res.status); return res; },
      onError: (err) => { console.error('✗', err); throw err; },
    },
  ],
});

Middleware composes with --bearer-auth, --timeout, and --error-handling.


Type mapping overrides

Use --type-mapping to override the TS type emitted for a given OpenAPI (type, format) pair. Repeatable. Unknown slugs and unknown targets are hard errors.

Slug OpenAPI (type, format) Default --type-mapping value
int64 (integer, int64) number int64=bigint
decimal (number, decimal) number decimal=string
date-time (string, date-time) Date date-time=string
date (string, date) Date date=string
npx @metaengine/openapi-fetch api.yaml ./src/api \
  --type-mapping int64=bigint \
  --type-mapping date-time=string

See it live

Try the generator with your own spec at https://www.metaengine.eu/converters.


Programmatic Usage

The NuGet package allows programmatic use in .NET projects. See the website documentation for full C# API reference.


Support


License

MIT License - see LICENSE file for details.


About This Repository

This is the documentation and issue tracking repository for MetaEngine OpenAPI Fetch. The compiled NPM package is available at @metaengine/openapi-fetch.

Source code is proprietary, but the package is free to use under MIT license.

About

Generate framework-agnostic TypeScript services and models from OpenAPI specs using the native Fetch API — runs on Node, browsers, Vite, SvelteKit, Next.js, Bun, Deno

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors