@ugm/sdk-gen
v1.0.6
Published
CLI tool that generates fully-typed SDK clients from OpenAPI specifications
Maintainers
Readme
sdk-gen
CLI tool that generates fully-typed SDK clients from OpenAPI specifications.
Features
- Generates TypeScript and Python SDK clients
- Supports OpenAPI 3.0 specifications (JSON or YAML)
- Streaming endpoint detection and support
- AbortSignal support — all generated methods accept an optional
AbortSignalfor request cancellation - Optional publishable package generation with proper package files
- Name mappings for customizing operation/schema names and grouping operations into services
- OpenAPI 3.1 nullable fix for compatibility with 3.0-style code generators
Installation
From npm
npm install @ugm/sdk-genFrom source
git clone https://github.com/ugmurthy/sdk-gen.git
cd sdk-gen
npm install
npm run buildGlobal CLI (optional)
To use sdk-gen as a global command:
npm linkAlternatively, run via npm or node directly (see examples below).
Usage
sdk-gen <spec-file> --lang <ts|python> --output <dir> [options]Options
| Option | Description |
| ------------------- | -------------------------------------------------- |
| --lang <language> | Target language: ts or python (required) |
| --output <dir> | Output directory for generated SDK (required) |
| --package | Generate as publishable package |
| --name <name> | Package name (required with --package) |
| --force | Overwrite existing files without prompting |
| --fix-nullable | Convert OpenAPI 3.1-style nullable types to 3.0 format |
| --mappings <file> | JSON file with name mappings for operations and schemas |
Examples
Generate TypeScript SDK from YAML
sdk-gen ./api-spec.yaml --lang ts --output ./sdkGenerate Python SDK from JSON
sdk-gen ./openapi.json --lang python --output ./python-sdkGenerate a publishable TypeScript package
sdk-gen ./petstore.yaml --lang ts --output ./petstore-sdk --package --name petstore-clientGenerate a publishable Python package
sdk-gen ./api.yaml --lang python --output ./my-api-sdk --package --name my-api-clientForce overwrite existing files
sdk-gen ./spec.yaml --lang ts --output ./sdk --forceFix OpenAPI 3.1 nullable types
sdk-gen ./spec.yaml --lang ts --output ./sdk --fix-nullableUse custom name mappings
# First run generates a default mappings file if it doesn't exist
sdk-gen ./spec.yaml --lang ts --output ./sdk --mappings ./mappings.json
# Edit mappings.json, then re-run to apply mappings
sdk-gen ./spec.yaml --lang ts --output ./sdk --mappings ./mappings.jsonName Mappings
The --mappings option allows you to customize operation and schema names in the generated SDK, and optionally group operations into service classes.
How It Works
- First run: If the mappings file doesn't exist, sdk-gen generates a default template with all operations and schemas mapped to their original names, then exits.
- Edit the file: Customize the mappings as needed.
- Re-run: Run sdk-gen again to generate the SDK with your custom mappings applied.
Mappings File Format
{
"operations": {
"getApiV2Health": "getApiV2Health",
"getApiV2AuthMe": { "service": "auth", "method": "me" },
"postApiV2AuthApiKeys": { "service": "auth", "method": "createApiKey" },
"getApiV2Users": { "service": "users", "method": "list" },
"getApiV2UsersById": { "service": "users", "method": "get" }
},
"schemas": {
"UserResponse": "User",
"CreateUserRequest": "CreateUserInput"
}
}Mapping Types
Simple String Mapping
Rename an operation or schema:
"getApiV2Health": "healthCheck"Service Grouping
Group operations into service classes with custom method names:
"getApiV2UsersById": { "service": "users", "method": "get" }This generates a users service with a get() method instead of a flat getApiV2UsersById() function.
Example Output
With service grouping, your SDK usage changes from:
// Without mappings (flat functions)
const user = await client.getApiV2UsersById({ id: '123' });
// With service grouping
const user = await client.users.get({ id: '123' });AbortSignal Support
All generated TypeScript methods accept an optional AbortSignal for request cancellation:
const controller = new AbortController();
// Non-streaming — pass signal via options
const user = await client.users.get({ id: '123' }, { signal: controller.signal });
// Streaming — pass signal as last argument
for await (const chunk of client.events.stream({ signal: controller.signal })) {
console.log(chunk);
}
// Cancel the request
controller.abort();Example with test fixture
# If globally linked
sdk-gen ./test-fixtures/petstore.yaml --lang ts --output ./generated-sdk
# Or via npm
npm start -- ./test-fixtures/petstore.yaml --lang ts --output ./generated-sdk
# Or via node directly
node dist/cli.js ./test-fixtures/petstore.yaml --lang ts --output ./generated-sdkLicense
MIT
