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.
fetchApiResult<T> for structured error handling without exceptionsonRequest / onResponse / onError composable around the request pipeline--import-meta-env for import.meta.env accessnpm install --save-dev @metaengine/openapi-fetch
Or use directly with npx:
npx @metaengine/openapi-fetch <input> <output>
fetch (Node 18+, all modern browsers, Bun, Deno)npx @metaengine/openapi-fetch api.yaml ./src/api \
--documentation \
--result-pattern
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
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
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
# 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
| 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 | - |
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
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.
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.
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.
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.
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);
}
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.
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
Try the generator with your own spec at https://www.metaengine.eu/converters.
The NuGet package allows programmatic use in .NET projects. See the website documentation for full C# API reference.
MIT License - see LICENSE file for details.
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.