Generate API Schema
Generate OpenAPI schema for your Client
Generate TypeScript types from your OpenAPI documentation for end-to-end type safety. Use openapi-typescript to automatically create type-safe API clients that stay in sync with your backend.
What is API Schema Generation?
API schema generation converts your OpenAPI documentation into TypeScript types. This enables:
- End-to-End Type Safety: Frontend and backend share the same types
- Autocomplete: Get intelligent code completion for API requests and responses
- Compile-Time Errors: Catch API mismatches before runtime
- Zero Manual Typing: Types update automatically when your API changes
With Adonis Open Swagger generating OpenAPI docs and openapi-typescript generating types, you get a fully type-safe development workflow.
Prerequisites
Before generating API schema, ensure:
- ✅ Your AdonisJS server is running (typically on
http://localhost:3333) - ✅ Adonis Open Swagger is configured and generating documentation
- ✅ Your API endpoints are decorated with Swagger decorators
- ✅ OpenAPI JSON is accessible at
/docs/json(default endpoint)
Generating Types
Use openapi-typescript to generate TypeScript types from your OpenAPI documentation:
bunx openapi-typescript http://localhost:3333/docs/json -o ./app/types/api-schema.tsCommand Breakdown
openapi-typescript: The CLI tool that generates TypeScript typeshttp://localhost:3333/docs/json: Your OpenAPI JSON endpoint-o ./app/types/api-schema.ts: Output file path for generated types
Using Generated Types
Once generated, import and use the types in your frontend application:
OpenAPI Fetch
Use with popular API client libraries for even better DX:
import createClient from "openapi-fetch";
import type { paths } from "./types/api-schema";
// Create type-safe client
const client = createClient<paths>({
baseUrl: "http://localhost:3333",
});
// Fully typed requests and responses
const { data, error } = await client.GET("/users/{id}", {
params: { path: { id: "123" } },
});
const { data: newUser } = await client.POST("/users", {
body: {
full_name: "John Doe",
email: "john@example.com",
password: "secure123",
},
});Automation
Add to package.json Scripts
Automate type generation by adding a script to your package.json:
{
"scripts": {
"generate:types": "openapi-typescript http://localhost:3333/docs/json -o ./app/types/api-schema.ts",
"dev": "npm run generate:types && next dev"
}
}Now run:
npm run generate:typesWatch Mode for Development
Regenerate types automatically when your API changes:
{
"scripts": {
"generate:types:watch": "nodemon --watch 'app/**/*.ts' --exec 'npm run generate:types'"
}
}CI/CD Integration
Add type generation to your CI/CD pipeline:
- name: Start API server
run: npm run dev &
- name: Wait for server
run: npx wait-on http://localhost:3333/docs/json
- name: Generate API types
run: npm run generate:types
- name: Type check
run: npm run type-checkAdvanced Options
Custom Configuration
Create an openapi-ts.config.ts file for advanced configuration:
import { defineConfig } from "@hey-api/openapi-ts";
export default defineConfig({
input: "http://localhost:3333/docs/json",
output: "./app/types/api-schema.ts",
client: "fetch",
schemas: true,
services: true,
});Multiple Environments
Generate types for different environments:
{
"scripts": {
"generate:types:dev": "openapi-typescript http://localhost:3333/docs/json -o ./types/api-schema.ts",
"generate:types:staging": "openapi-typescript https://staging.api.com/docs/json -o ./types/api-schema.ts",
"generate:types:prod": "openapi-typescript https://api.com/docs/json -o ./types/api-schema.ts"
}
}Best Practices
1. Version Control Generated Types
Do commit generated types to version control:
# ❌ Don't ignore generated types
# app/types/api-schema.tsWhy? Team members can use types immediately without running the generator.
2. Regenerate After API Changes
Always regenerate types after modifying:
- Controller methods
- Swagger decorators
- Request/response schemas
- Route definitions
3. Use Type Guards
Add runtime validation for extra safety:
import type { paths } from "./types/api-schema";
type User =
paths["/users/{id}"]["get"]["responses"]["200"]["content"]["application/json"];
function isUser(data: unknown): data is User {
return (
typeof data === "object" && data !== null && "id" in data && "email" in data
);
}4. Organize Types
Create type aliases for commonly used types:
import type { paths } from "./api-schema";
// Reusable type aliases
export type User =
paths["/users/{id}"]["get"]["responses"]["200"]["content"]["application/json"];
export type CreateUserRequest =
paths["/users"]["post"]["requestBody"]["content"]["application/json"];
export type UpdateUserRequest =
paths["/users/{id}"]["put"]["requestBody"]["content"]["application/json"];5. Handle Errors Gracefully
Type error responses too:
type ErrorResponse =
paths["/users/{id}"]["get"]["responses"]["404"]["content"]["application/json"];
async function getUser(id: string): Promise<User | ErrorResponse> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
return (await response.json()) as ErrorResponse;
}
return (await response.json()) as User;
}Troubleshooting
Server Not Running
Error: Failed to fetch http://localhost:3333/docs/json
Solution: Ensure your AdonisJS server is running:
node ace serve --watchInvalid OpenAPI Schema
Error: OpenAPI schema validation failed
Solution: Check your Swagger decorators and schemas are correctly defined. Visit http://localhost:3333/docs to see if documentation renders properly.
Types Not Updating
Problem: Generated types don't reflect recent API changes
Solution:
- Restart your AdonisJS server
- Clear any caches
- Regenerate types:
npm run generate:types - Restart your TypeScript server in your IDE
Path Not Found
Error: Cannot find module './types/api-schema'
Solution: Ensure the output path in your generation command matches your import path:
# If importing from './types/api-schema'
bunx openapi-typescript http://localhost:3333/docs/json -o ./types/api-schema.tsLast updated on