@shooks/query-gen v0.0.1
OpenAPI Code Generator with Zod and React Query
A powerful TypeScript code generator that creates type-safe API clients from OpenAPI specifications using Zod for runtime validation and React Query for data fetching.
Features
- š„ Type-safe API clients generated from OpenAPI specs
- š”ļø Runtime validation with Zod schemas
- ā” React Query hooks for seamless data fetching
- š Organized output with separate modules for models, endpoints, and hooks
- šÆ DRY design with minimal code duplication
- š§ Customizable with flexible configuration options
- š Well-documented generated code
Installation
npm install -g openapi-gen
# or with yarn
yarn global add openapi-gen
# or with pnpm
pnpm add -g openapi-gen
Quick Start
1. Initialize a new project
openapi-gen init
This creates an example OpenAPI specification and package.json scripts.
2. Generate code from your OpenAPI spec
openapi-gen generate -i openapi.json -o src/api
3. Install required dependencies
npm install zod @tanstack/react-query
4. Use the generated code
import { useGetUser, useCreateUser } from './api/hooks';
function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading } = useGetUser(userId);
const createUser = useCreateUser();
if (isLoading) return <div>Loading...</div>;
return (
<div>
<h1>{user?.name}</h1>
<p>{user?.email}</p>
</div>
);
}
CLI Usage
Generate Command
openapi-gen generate [options]
Options:
-i, --input <path>
- Path to OpenAPI spec file (JSON/YAML) or URL (required)-o, --output <dir>
- Output directory for generated code (default: "./generated")--no-hooks
- Skip generating React Query hooks--base-url <url>
- Base URL for API calls--client-name <name>
- Name for the API client class (default: "ApiClient")
Examples:
# Generate from local file
openapi-gen gen -i ./api-spec.yaml -o ./src/api
# Generate from URL
openapi-gen gen -i https://api.example.com/openapi.json -o ./src/api
# Generate without React Query hooks
openapi-gen gen -i ./spec.json -o ./src/api --no-hooks
# Generate with custom base URL
openapi-gen gen -i ./spec.json -o ./src/api --base-url https://api.staging.com
Init Command
openapi-gen init [options]
Options:
-d, --dir <directory>
- Directory to initialize (default: ".")
Generated Code Structure
The generator creates a well-organized structure:
generated/
āāā models/ # Zod schemas and TypeScript types
ā āāā User.ts
ā āāā CreateUser.ts
ā āāā index.ts
āāā endpoints/ # API client classes grouped by tags
ā āāā UsersApi.ts
ā āāā ProductsApi.ts
ā āāā index.ts
āāā hooks/ # React Query hooks (optional)
ā āāā Users.ts
ā āāā Products.ts
ā āāā queryKeys.ts
ā āāā index.ts
āāā ApiClient.ts # Base HTTP client with Zod validation
āāā index.ts # Main exports
Models (Zod Schemas)
Each OpenAPI schema becomes a Zod schema with TypeScript types:
// generated/models/User.ts
import { z } from 'zod';
export const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string(),
role: z.enum(['admin', 'user']),
createdAt: z.string().datetime(),
});
export type User = z.infer<typeof UserSchema>;
API Client Classes
Endpoint classes extend the base client and provide type-safe methods:
// generated/endpoints/UsersApi.ts
import { ApiClient } from '../ApiClient';
import { UserSchema, User, CreateUserSchema, CreateUser } from '../models';
export class UsersApi extends ApiClient {
getUsers(page?: number, limit?: number): Promise<User[]> {
return this.get('/users', z.array(UserSchema), {
queryParams: { page, limit }
});
}
createUser(data: CreateUser): Promise<User> {
return this.post('/users', UserSchema, {
body: data,
bodySchema: CreateUserSchema
});
}
getUserById(id: string): Promise<User> {
return this.get(`/users/${id}`, UserSchema);
}
}
React Query Hooks
Ready-to-use hooks for your React components:
// generated/hooks/Users.ts
import { useQuery, useMutation } from '@tanstack/react-query';
import { UsersApi } from '../endpoints/UsersApi';
const usersApi = new UsersApi(process.env.REACT_APP_API_BASE_URL || '');
export function useGetUsers(page?: number, limit?: number) {
return useQuery({
queryKey: ['getUsers', page, limit],
queryFn: () => usersApi.getUsers(page, limit),
});
}
export function useCreateUser() {
return useMutation({
mutationFn: (variables: { email: string; name: string; role?: string }) => {
return usersApi.createUser(variables);
},
});
}
Configuration
Base API Client
The generated ApiClient
provides a robust foundation with:
- Automatic request/response validation using Zod schemas
- Configurable timeouts and headers
- Error handling with meaningful error messages
- Support for all HTTP methods (GET, POST, PUT, PATCH, DELETE)
Environment Variables
For React applications, you can configure the base URL using environment variables:
REACT_APP_API_BASE_URL=https://api.example.com/v1
TypeScript Configuration
Ensure your tsconfig.json
includes the generated code:
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*"]
}
Advanced Usage
Custom API Client
You can extend the generated API client for custom functionality:
import { UsersApi } from './generated';
class CustomUsersApi extends UsersApi {
constructor(baseUrl: string, authToken: string) {
super({
baseUrl,
headers: {
'Authorization': `Bearer ${authToken}`,
},
});
}
// Add custom methods
async getCurrentUser(): Promise<User> {
return this.getUserById('me');
}
}
Query Key Management
The generator creates query key factories for cache management:
import { useQueryClient } from '@tanstack/react-query';
import { useGetUserKey } from './generated/hooks';
function InvalidateUser({ userId }: { userId: string }) {
const queryClient = useQueryClient();
const handleInvalidate = () => {
queryClient.invalidateQueries({ queryKey: useGetUserKey(userId) });
};
return <button onClick={handleInvalidate}>Refresh User</button>;
}
Error Handling
The generated client includes comprehensive error handling:
try {
const user = await usersApi.getUserById('123');
} catch (error) {
if (error instanceof Error) {
console.error('API Error:', error.message);
// Error message includes HTTP status and response details
}
}
OpenAPI Support
This generator supports OpenAPI 3.0+ specifications and handles:
- ā All primitive types (string, number, boolean, array, object)
- ā String formats (email, uri, uuid, date-time, etc.)
- ā Enums and string literals
- ā Object validation with required/optional properties
- ā Array validation with min/max items
- ā Number validation with min/max values
- ā String validation with length and pattern constraints
- ā Union types (oneOf, anyOf)
- ā Intersection types (allOf)
- ā Reference resolution ($ref)
- ā Path parameters
- ā Query parameters
- ā Request/response headers
- ā Request body validation
- ā Multiple response types
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - see LICENSE file for details.
Related Projects
- Zod - TypeScript schema validation
- TanStack Query - Data fetching library
- OpenAPI Generator - Alternative code generators
- Orval - Similar OpenAPI to TypeScript generator
2 months ago