Summary
Generate a first-class TypeScript SDK package that provides type-safe client for the generated OpenAPI API.
Motivation
OpenAPI spec exists, but consumers must write HTTP clients manually or use generic tools. Generated SDK provides:
- Typed methods for all endpoints
- Automatic request/response validation with Zod
- Error handling with typed exceptions
- Built-in authentication support
Scope
In Scope
- Generate SDK as separate npm-installable module
- Client class with all CRUD operations
- Typed request/response methods
- Zod schema validation for responses
- Bearer token authentication support
- Error handling with custom exception types
- Usage examples in generated README
Out of Scope
- Swagger code generation from third-party libs
- GraphQL client
- gRPC client
- Custom HTTP interceptors
Acceptance Criteria
Files to Create/Modify
packages/generators/src/sdk/typescript-sdk-generator.ts (NEW)
packages/generators/src/index.ts (MODIFY)
tests/sdk-generation.test.mjs (NEW)
Example Output
// generated/sdk/client.ts
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
export interface ClientConfig {
baseUrl?: string;
token?: string;
}
export class ForgeClient {
private baseUrl: string;
private token?: string;
constructor(config: ClientConfig = {}) {
this.baseUrl = config.baseUrl || 'http://localhost:3000';
this.token = config.token;
}
setToken(token: string): void {
this.token = token;
}
async #request<T>(
path: string,
method: string,
data?: unknown,
schema?: z.ZodSchema<T>
): Promise<T> {
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
'Content-Type': 'application/json',
...(this.token && { Authorization: `Bearer ${this.token}` }),
},
body: data ? JSON.stringify(data) : undefined,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const json = await response.json();
return schema ? schema.parse(json) : json;
}
users = {
list: async () => {
return this.#request<User[]>(
'/users',
'GET',
undefined,
z.array(UserSchema)
);
},
get: async (id: string) => {
return this.#request<User>(
`/users/${id}`,
'GET',
undefined,
UserSchema
);
},
create: async (data: Omit<User, 'id'>) => {
return this.#request<User>(
'/users',
'POST',
data,
UserSchema
);
},
update: async (id: string, data: Partial<User>) => {
return this.#request<User>(
`/users/${id}`,
'PATCH',
data,
UserSchema
);
},
delete: async (id: string) => {
await this.#request(`/users/${id}`, 'DELETE');
},
};
}
// Usage
const client = new ForgeClient({
baseUrl: 'https://api.example.com',
token: process.env.API_TOKEN,
});
const users = await client.users.list();
const user = await client.users.get(userId);
const newUser = await client.users.create({ name: 'John', email: 'john@example.com' });
Test Strategy
- Generate SDK from OpenAPI spec
- Import SDK in test project
- Test type inference works correctly
- Test all CRUD methods with mock server
- Verify error types are correct
- Verify Zod validation catches bad responses
- Verify Bearer token sent in Authorization header
- Verify query parameters passed correctly
Summary
Generate a first-class TypeScript SDK package that provides type-safe client for the generated OpenAPI API.
Motivation
OpenAPI spec exists, but consumers must write HTTP clients manually or use generic tools. Generated SDK provides:
Scope
In Scope
Out of Scope
Acceptance Criteria
generated/sdk/directoryFiles to Create/Modify
packages/generators/src/sdk/typescript-sdk-generator.ts(NEW)packages/generators/src/index.ts(MODIFY)tests/sdk-generation.test.mjs(NEW)Example Output
Test Strategy