Backend

SDK Generator

Point it at API routes or an OpenAPI spec and it generates a fully typed TypeScript client SDK with error handling and auth support.

SKILL.md

SKILL.md
---
description: Generate a typed TypeScript client SDK from API routes or OpenAPI spec
allowed-tools: Read, Write, Glob, Grep, Bash
---

# SDK Generator

Analyze API routes or an OpenAPI specification and generate a fully typed TypeScript client SDK that consumers can use to call the API with complete type safety.

## Arguments

- `$ARGUMENTS` — path to the API routes directory (e.g., `src/app/api`) or an OpenAPI/Swagger spec file (`.json` or `.yaml`)

## Steps

1. **Detect the input type.** Check if `$ARGUMENTS` points to:
   - A directory → scan for route handler files (Next.js `route.ts`, Express router files, etc.)
   - A `.json` or `.yaml`/`.yml` file → parse as OpenAPI specification

2. **Extract endpoint definitions.** For each endpoint, capture:
   - **HTTP method** (GET, POST, PUT, PATCH, DELETE)
   - **Path** with parameter placeholders (e.g., `/users/:id``/users/${id}`)
   - **Path parameters** and their types
   - **Query parameters** — name, type, required/optional, defaults
   - **Request body schema** — extract from Zod schemas, TypeScript interfaces, or OpenAPI `requestBody`
   - **Response schema** — extract from return types, Zod output schemas, or OpenAPI `responses`
   - **Authentication requirements** — look for auth middleware, bearer token checks, API key headers

3. **Generate TypeScript types.** Create a types file with:
   - Request types for each endpoint (path params, query params, body)
   - Response types for each endpoint (success and error shapes)
   - Shared types (pagination, error envelope, etc.)
   - Use discriminated unions for error types where possible

4. **Generate the SDK client class.** Create `api-client.ts` with:

   ```typescript
   export class ApiClient {
     private baseUrl: string;
     private headers: Record<string, string>;

     constructor(config: ApiClientConfig) { ... }

     // One method per endpoint:
     async getUser(params: GetUserParams): Promise<GetUserResponse> { ... }
     async createUser(body: CreateUserBody): Promise<CreateUserResponse> { ... }
   }
   ```

   Each method should:
   - Accept a typed params/body object
   - Construct the URL with path parameters interpolated
   - Append query parameters
   - Set appropriate `Content-Type` header
   - Include auth headers from the client config
   - Parse the response as JSON and validate against the response type
   - Throw typed errors for non-2xx responses

5. **Add error handling.** Generate an `ApiError` class:
   ```typescript
   export class ApiError extends Error {
     status: number;
     code: string;
     details?: unknown;
   }
   ```

6. **Add convenience features:**
   - Request/response interceptors (for logging, token refresh, etc.)
   - Configurable timeout per request
   - Abort controller support for cancellation
   - Optional retry with exponential backoff for 5xx errors

7. **Generate an index file** that re-exports everything:
   ```typescript
   export { ApiClient } from './api-client';
   export type { ApiClientConfig } from './api-client';
   export { ApiError } from './errors';
   export * from './types';
   ```

8. **Write all files** to a `generated-sdk/` directory in the project root.

## Rules

- Method names should follow a consistent pattern: `${verb}${Resource}` (e.g., `getUser`, `createPost`, `deleteComment`).
- Use `fetch` as the HTTP client — no external dependencies.
- All generated code must be valid TypeScript with strict mode enabled.
- Include JSDoc comments on every public method with the endpoint path and a brief description.
- If the API has pagination, generate a helper method that auto-paginates and yields all results.
- Mark the generated files with a header comment: `// This file is auto-generated by SDK Generator. Do not edit manually.`

How It Works

This skill eliminates the tedious, error-prone work of manually writing API client code. Every time a backend developer adds an endpoint, frontend developers must write fetch calls with the right URL, method, headers, and type assertions. An SDK generator automates this entirely, and because it reads the actual route handlers (not just documentation), the types are guaranteed to match the implementation.

The zero-dependency approach — using native `fetch` instead of axios or got — means the generated SDK works in any JavaScript environment: browsers, Node.js, Deno, edge runtimes. This is a deliberate architectural choice that maximizes portability.

The interceptors and retry logic elevate the output from a simple HTTP wrapper to a production-grade client. Token refresh interceptors, for example, let consumers handle auth transparently. The abort controller support enables proper cleanup in React components — a detail that hand-written fetch calls often miss, leading to the infamous "can't update state on an unmounted component" warning.