api-alchemy
v0.2.0
Published
Automatically generates TypeScript types and schemas from real API traffic during development.
Maintainers
Readme
api-alchemy
Automatically generates TypeScript types and schemas from real API traffic during development.
Features
- 🚀 Zero Configuration: Works out of the box with minimal setup
- 📡 Fetch Interception: Wraps native
fetchto capture responses - 🔄 Schema Inference: Automatically infers JSON schemas from responses
- 🧬 Schema Merging: Evolves schemas as new response variations appear
- 📝 TypeScript Generation: Generates clean, type-safe interfaces
- 💾 Persistence: Saves schemas and generated types to disk
- ⚡ Non-blocking: Inference runs asynchronously without blocking requests
Installation
npm install api-alchemyQuick Start
Using Fetch Wrapper
Wrap your fetch call to start capturing API responses:
import { instrumentFetch } from 'api-alchemy';
// Instrument fetch globally
global.fetch = instrumentFetch(fetch);
// Use fetch normally - types are generated automatically
const response = await fetch('https://api.github.com/users/torvalds');
const user = await response.json();As your application runs, generated types appear in .api-alchemy/generated/:
// Example: .api-alchemy/generated/get-users-id.ts
export interface GetUsersIdResponse {
id: number;
login: string;
avatar_url: string;
type: string;
name?: string;
company?: string;
}Configuration
import { startApiScribe } from 'api-alchemy';
startApiScribe({
outputDir: './api-types', // Default: ./api-types
enabled: process.env.NODE_ENV === 'development'
});How It Works
Pipeline
HTTP Request
↓
Fetch Wrapper (Interception)
↓
Extract JSON Response
↓
Schema Inference (detect types & structure)
↓
Schema Merge (combine variations)
↓
TypeScript Code Generation
↓
Save to Disk (.api-alchemy/generated/)Endpoint Normalization
Dynamic URL segments are automatically converted to placeholders:
https://api.github.com/users/123 → GET /users/:id
https://api.github.com/repos/foo/bar → GET /repos/:owner/:repo
https://api.example.com/items/abc123 → GET /items/:idThese become type names:
GET /users/:id → GetUsersIdResponse
GET /repos/:owner/:repo → GetReposOwnerRepoResponseSchema Merging
When the same endpoint returns different response shapes, fields are merged intelligently:
First response:
{ "id": 1, "name": "Alice" }Second response:
{ "id": 2, "name": "Bob", "avatar": "https://..." }Merged schema:
interface Response {
id: number;
name: string;
avatar?: string; // Optional, appeared later
}Output Structure
.api-alchemy/
├── schemas/
│ ├── get-users-id.json
│ └── get-repos-owner-repo.json
├── generated/
│ ├── get-users-id.ts
│ └── get-repos-owner-repo.ts
└── observations.jsonTypeScript Integration
Generated types are fully TypeScript-compatible:
import type { GetUsersIdResponse } from './.api-alchemy/generated/get-users-id';
const response = await fetch('https://api.github.com/users/torvalds');
const user: GetUsersIdResponse = await response.json();
// Full type safety
console.log(user.login); // ✓ OK
console.log(user.notexists); // ✗ TypeScript errorPerformance
- Non-blocking: Schema inference happens asynchronously via
setImmediate - Minimal overhead: Negligible performance impact on requests
- Batched writes: File operations are debounced
Edge Cases Handled
- Empty responses
- Non-JSON responses (skipped)
- Circular object detection
- Type unions (conflicting schemas)
- Optional fields (inferred from frequency)
- Large response bodies
Development vs Production
api-alchemy is designed for development only:
if (process.env.NODE_ENV === 'development') {
global.fetch = instrumentFetch(fetch);
}Or use a conditional import:
if (process.env.NODE_ENV === 'development') {
const { instrumentFetch } = await import('api-alchemy');
global.fetch = instrumentFetch(fetch);
}Testing
Run tests with:
npm testTests cover:
- Schema inference from various JSON structures
- Schema merging and type union detection
- Endpoint normalization (IDs, UUIDs, hashes)
- TypeScript code generation
- Type naming conventions
Future Features
- [ ] Zod schema generation
- [ ] OpenAPI/Swagger output
- [ ] Axios interceptor
- [ ] GraphQL schema inference
- [ ] CLI for schema generation
- [ ] IDE integration / Intellisense
- [ ] Schema versioning
- [ ] Traffic replay
License
ISC
Contributing
Contributions welcome! Please open an issue or PR on GitHub.
