A fully typed, extensible, modular TypeScript type generator for OpenAPI schemas (great with FastAPI). Generate TypeScript types, API clients, and optional hooks with sensible defaults.
Status: Production Ready π | Maintenance: Actively Maintained β | Support: Community & Issues π¬ | Version: v0.1.0
- π§ Zero Configuration - Works out of the box with FastAPI applications
- π― Fully Typed - Generates comprehensive TypeScript types with no
any
types - π§© Modular Architecture - Extensible plugin system for custom generators
- π Fast & Efficient - Optimized for large schemas and complex APIs
- π¦ Multiple Outputs - Types, API clients, React hooks, and more
- π Schema Validation - Built-in OpenAPI schema validation
- π¨ Customizable - Flexible naming conventions and type mappings
- π Well Documented - Comprehensive documentation and examples
npm install schemantic
Generate types and API client from your OpenAPI schema:
# From URL (recommended)
npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated
# From file (local snapshot)
npx schemantic generate --file ./schema.json --output ./src/generated
# With React hooks
npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated --hooks
# With custom options
npx schemantic generate \
--url http://localhost:8000/openapi.json \
--output ./src/generated \
--naming camelCase \
--prefix API \
--suffix Type
You can point Schemantic at any reachable OpenAPI 3.x JSON. Common frameworks expose it at predictable URLs:
- FastAPI (default): http://localhost:8000/openapi.json
- ASP.NET Core (.NET): https://localhost:5001/swagger/v1/swagger.json
Grab a local snapshot if you prefer generating from a file:
# FastAPI
curl -s http://localhost:8000/openapi.json -o ./openapi-schema.json
# ASP.NET Core (.NET)
curl -k -s https://localhost:5001/swagger/v1/swagger.json -o ./openapi-schema.json
# Generate from the snapshot
npx schemantic generate --file ./openapi-schema.json --output ./src/generated --client --types
Notes:
- On .NET dev certs (HTTPS), use
-k
with curl to skip certificate verification locally. - In ASP.NET Core, ensure Swagger is enabled in Development (AddSwaggerGen/UseSwagger) and the Swagger endpoint exposes
/swagger/v1/swagger.json
.
import { Schemantic, SchemanticConfig } from "schemantic";
const config: SchemanticConfig = {
schemaUrl: "http://localhost:8000/openapi.json",
outputDir: "./src/generated",
generateTypes: true,
generateApiClient: true,
useStrictTypes: true,
namingConvention: "camelCase",
};
const Schemantic = new Schemantic(config);
const result = await Schemantic.generate();
if (result.success) {
console.log(`Generated ${result.generatedFiles.length} files`);
console.log(`Types: ${result.statistics.totalTypes}`);
console.log(`Endpoints: ${result.statistics.totalEndpoints}`);
}
const config: SchemanticConfig = {
// Input sources (choose one)
schemaUrl: "http://localhost:8000/openapi.json",
schemaFile: "./schema.json",
schemaData: {
/* OpenAPI schema object */
},
// Output configuration
outputDir: "./src/generated",
outputFileName: "api-client.ts",
// Generation options
generateTypes: true,
generateApiClient: true,
generateHooks: false, // Enable React hooks generation
// TypeScript configuration
useStrictTypes: true,
useOptionalChaining: true,
useNullishCoalescing: true,
// Naming conventions
namingConvention: "camelCase", // 'camelCase' | 'snake_case' | 'PascalCase'
// By default, Schemantic prefixes type names with "API". Customize if desired:
typePrefix: "API",
typeSuffix: "Type",
// Customization
customTypeMappings: {
uuid: "string",
datetime: "Date",
},
// Filtering
excludePaths: ["/health", "/docs"],
includePaths: ["/api/v1/*"],
excludeSchemas: ["Error"],
includeSchemas: ["User", "Product"],
// Plugin configuration
plugins: [
{ name: "jsdoc", enabled: true },
{ name: "validation", enabled: true },
],
};
# Generate types and API client
npx schemantic generate [source] [options]
npx schemantic gen [source] [options]
# Validate OpenAPI schema
npx schemantic validate [source] [options]
npx schemantic check [source] [options]
# Manage plugins
npx schemantic plugin list
npx schemantic plugin load <path>
# Initialize configuration
npx schemantic init [directory] [options]
# Get help
npx schemantic --help
npx schemantic generate --help
# Input options
--url, -u <url> OpenAPI schema URL
--file, -f <file> OpenAPI schema file path
# Output options
--output, -o <dir> Output directory (default: ./src/generated)
# Generation options
--types Generate types only
--client Generate API client only
--hooks Generate React hooks factory
--watch Watch for changes and regenerate
# TypeScript options
--strict Use strict TypeScript types (default: true)
--naming <convention> Naming convention (camelCase|snake_case|PascalCase)
# Customization
--prefix <prefix> Type name prefix (default: API)
--suffix <suffix> Type name suffix
--exclude-paths <paths> Exclude paths (comma-separated)
--include-paths <paths> Include paths (comma-separated)
--exclude-schemas <schemas> Exclude schemas (comma-separated)
--include-schemas <schemas> Include schemas (comma-separated)
# Plugin options
--plugins <plugins> Enable plugins (comma-separated)
--config, -c <file> Configuration file path
# Global options
--interactive, -i Run in interactive mode
--verbose, -v Verbose output
--quiet, -q Quiet output
--no-color Disable colored output
--url, -u <url> OpenAPI schema URL
--file, -f <file> OpenAPI schema file path
--fix Attempt to fix common issues
--template, -t <template> Configuration template (default)
--yes Skip interactive prompts
# Generate from live FastAPI server
npx schemantic generate --url http://localhost:8000/openapi.json
# Generate from local schema file
npx schemantic generate --file ./openapi-schema.json
# Custom output directory
npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/api
# Generate with React hooks
npx schemantic generate --url http://localhost:8000/openapi.json --hooks
# Interactive mode (guided setup)
npx schemantic generate --interactive
# Custom naming and prefixes
npx schemantic generate \
--url http://localhost:8000/openapi.json \
--naming PascalCase \
--prefix "MyAPI" \
--suffix "DTO"
# Filter paths and schemas
npx schemantic generate \
--url http://localhost:8000/openapi.json \
--include-paths "/api/v1/*,/auth/*" \
--exclude-paths "/health,/docs" \
--exclude-schemas "Error,ValidationError"
# Enable plugins
npx schemantic generate \
--url http://localhost:8000/openapi.json \
--plugins jsdoc,validation,react-hooks
# Use configuration file
npx schemantic generate --config ./Schemantic.config.json
# Watch mode for development
npx schemantic generate --url http://localhost:8000/openapi.json --watch
# Generate specific outputs
npx schemantic generate --url http://localhost:8000/openapi.json --types --client
npx schemantic generate --url http://localhost:8000/openapi.json --hooks
# Validate schema
npx schemantic validate --url http://localhost:8000/openapi.json
# Validate local file
npx schemantic validate --file ./openapi-schema.json
# Validate with auto-fix attempts
npx schemantic validate --file ./openapi-schema.json --fix
# Initialize new project configuration
npx schemantic init
# Initialize with default settings
npx schemantic init --yes
# Initialize in specific directory
npx schemantic init ./my-project
# Initialize with template
npx schemantic init --template react
# List available plugins
npx schemantic plugin list
# Load custom plugin
npx schemantic plugin load ./my-custom-plugin.js
npx schemantic plugin load @my-org/Schemantic-plugin
// Generated from OpenAPI schema
export interface APIUser {
id: string;
email: string;
firstName: string;
lastName: string;
createdAt: string;
updatedAt: string;
}
export interface APICreateUserRequest {
email: string;
firstName: string;
lastName: string;
}
export interface APIUpdateUserRequest {
email?: string;
firstName?: string;
lastName?: string;
}
export enum APIUserRole {
ADMIN = "admin",
USER = "user",
MODERATOR = "moderator",
}
Enable hook generation with --hooks
(CLI) or generateHooks: true
(config). A hooks.ts
file will export createApiHooks(client)
which returns per-endpoint hooks.
Example:
import { ECommerceApiClient, createApiHooks } from "./src/generated";
const client = new ECommerceApiClient({ baseUrl: "http://localhost:8000" });
const { useGetProductsProductsGetQuery, useCreateOrderOrdersPostMutation } =
createApiHooks(client);
function ProductsList() {
const { data, loading, error, refetch } = useGetProductsProductsGetQuery({
query: { page: 1, size: 20 },
});
// ... render
}
Notes:
- Hooks mirror the client method signatures: path params, query params, optional body (for mutations), then
RequestInit
as the last arg. - The generated
index.ts
re-exportscreateApiHooks
when hooks are enabled.
// Actual name is derived from your API title; example below shows a generic name.
export class MyApiApiClient {
private baseUrl: string;
private config: ApiClientConfig;
constructor(config: ApiClientConfig) {
this.baseUrl = config.baseUrl.replace(/\/$/, "");
this.config = {
timeout: 30000,
retries: 3,
retryDelay: 1000,
...config,
};
}
async getUsers(): Promise<APIUser[]> {
const url = new URL(`${this.baseUrl}/users`);
const response = await fetch(url.toString(), {
method: "GET",
headers: {
...this.config.headers,
},
});
if (!response.ok) {
throw new ApiClientError(
`Request failed: ${response.status} ${response.statusText}`,
response.status,
response
);
}
return response.json();
}
async createUser(body: APICreateUserRequest): Promise<APIUser> {
const url = new URL(`${this.baseUrl}/users`);
const response = await fetch(url.toString(), {
method: "POST",
headers: {
...this.config.headers,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new ApiClientError(
`Request failed: ${response.status} ${response.statusText}`,
response.status,
response
);
}
return response.json();
}
}
Schemantic includes a powerful plugin system for extending functionality:
- jsdoc - Adds JSDoc comments to generated types
- validation - Adds validation decorators for class-validator
- react-hooks - Generates React hooks for API endpoints
- strict-mode - Adds TypeScript strict mode enhancements
// Enable plugins via configuration
const config: SchemanticConfig = {
// ... other config
plugins: [
{ name: 'jsdoc', enabled: true },
{ name: 'validation', enabled: true },
{ name: 'react-hooks', enabled: true },
],
};
// Or via CLI
npx schemantic generate --plugins jsdoc,validation,react-hooks
import { SchemanticPlugin, GenerationContext, GeneratedType } from "schemantic";
const customPlugin: SchemanticPlugin = {
name: "custom-plugin",
version: "1.0.0",
description: "Custom plugin for special transformations",
beforeTypeGeneration: async (
typeName: string,
schema: any,
context: GenerationContext
) => {
// Transform schema before generation
console.log(`Generating type: ${typeName}`);
},
afterTypeGeneration: async (
typeName: string,
generatedType: GeneratedType,
context: GenerationContext
) => {
// Modify generated type
generatedType.content = `// Custom comment\n${generatedType.content}`;
},
transformSchema: (schema: any, context: GenerationContext) => {
// Transform schema
return schema;
},
customTypeGenerators: {
"custom-type": (schema: any, context: GenerationContext) => {
// Custom type generator
return {
name: "CustomType",
content: "export type CustomType = string;",
dependencies: [],
exports: ["CustomType"],
isInterface: false,
isEnum: false,
isUnion: false,
sourceSchema: schema,
};
},
},
};
π Complete Plugin Development Guide - Learn how to create custom plugins
π Plugin API Reference - Built-in plugins and usage examples
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI(
title="My API",
description="API description",
version="1.0.0",
)
class User(BaseModel):
id: str
email: str
first_name: str
last_name: str
created_at: str
updated_at: str
class CreateUserRequest(BaseModel):
email: str
first_name: str
last_name: str
@app.get("/users", response_model=List[User])
async def get_users():
# Your implementation
pass
@app.post("/users", response_model=User)
async def create_user(user: CreateUserRequest):
# Your implementation
pass
# Start your FastAPI server
uvicorn main:app --reload
# Generate types
npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated
const config: SchemanticConfig = {
// ... other config
customTypeMappings: {
uuid: "string",
datetime: "Date",
decimal: "number",
email: "string",
},
};
const config: SchemanticConfig = {
// ... other config
excludePaths: ["/health", "/docs", "/redoc"],
includePaths: ["/api/v1/*"],
excludeSchemas: ["Error", "ValidationError"],
includeSchemas: ["User", "Product", "Order"],
};
Create a schemantic.config.json
file:
{
"schemaUrl": "http://localhost:8000/openapi.json",
"outputDir": "./generated",
"generateTypes": true,
"generateApiClient": true,
"useStrictTypes": true,
"namingConvention": "camelCase",
"plugins": [
{ "name": "jsdoc", "enabled": true },
{ "name": "validation", "enabled": true }
]
}
Use with CLI:
npx schemantic generate --config schemantic.config.json
Validate your OpenAPI schema before generation:
# Validate schema
npx schemantic validate --url http://localhost:8000/openapi.json
# Validate with verbose output
npx schemantic validate --file schema.json --verbose
// Import from the generated index barrel
import { MyApiApiClient } from "./generated";
import type { APIUser } from "./generated";
const apiClient = new MyApiApiClient({
baseUrl: "http://localhost:8000",
headers: {
Authorization: `Bearer ${token}`,
},
});
// Use in React component
const UsersPage = () => {
const [users, setUsers] = useState<APIUser[]>([]);
useEffect(() => {
const fetchUsers = async () => {
try {
const usersData = await apiClient.getUsers();
setUsers(usersData);
} catch (error) {
console.error("Failed to fetch users:", error);
}
};
fetchUsers();
}, []);
return (
<div>
{users.map((user) => (
<div key={user.id}>
{user.firstName} {user.lastName} - {user.email}
</div>
))}
</div>
);
};
import { MyApiApiClient } from "./generated";
const apiClient = new MyApiApiClient({
baseUrl: "http://localhost:8000",
});
// Use in Node.js application
const main = async () => {
try {
const users = await apiClient.getUsers();
console.log("Users:", users);
const newUser = await apiClient.createUser({
email: "user@example.com",
firstName: "John",
lastName: "Doe",
});
console.log("Created user:", newUser);
} catch (error) {
console.error("API error:", error);
}
};
main();
π Complete FastAPI Tutorial - Build a full-stack e-commerce app with FastAPI, Schemantic, and React. Includes authentication, database models, type-safe API client, and React hooks.
We welcome contributions! Here's how you can help:
Found a bug? Please open an issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Your environment (Node.js version, OS, etc.)
Have an idea? Start a discussion or open an issue!
# Clone the repository
git clone https://github.com/Cstannahill/schemantic.git
cd schemantic
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run linting
npm run lint
# Fix linting issues automatically
npm run lint:fix
- Write tests for new features
- Ensure all tests pass:
npm test
- Check test coverage:
npm run test:coverage
- Test with real FastAPI applications in
local-test/
- Update README.md for new features
- Add examples to documentation
- Update API documentation in
docs/
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes
- Add tests and documentation
- Ensure all checks pass
- Commit with clear messages
- Push and create a Pull Request
- π Documentation - Comprehensive guides and API reference
- π Issue Tracker - Bug reports and feature requests
- π¬ Discussions - Community help and ideas
- οΏ½ Plugin Development - Create custom generators
- π FastAPI Tutorial - Complete integration guide
- Check the documentation first
- Search existing issues
- Ask in discussions
- Create a new issue with detailed information
- Support for OpenAPI 3.1 features
- GraphQL schema support
- Additional framework integrations (Express, NestJS)
- VS Code extension
- Enhanced React Query integration
- Performance optimizations for large schemas
MIT License - see LICENSE file for details.
See CHANGELOG.md for a list of changes and version history.