@tryloop/oats
Version:
š¾ OATS - OpenAPI TypeScript Sync. The missing link between your OpenAPI specs and TypeScript applications. Automatically watch, generate, and sync TypeScript clients from your API definitions.
325 lines (270 loc) ⢠9.03 kB
Markdown
# š¾ OATS - OpenAPI TypeScript Sync
> Automatically sync OpenAPI specs to TypeScript clients. No manual steps, just real-time updates.
[](https://www.npmjs.com/package/@tryloop/oats)
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org)
## š Quick Start
```bash
# Install
npm install -D @tryloop/oats
# Initialize config
npx oats init
# Start development
npx oats start
```
## šÆ What is OATS?
OATS eliminates the manual 6-step workflow of syncing OpenAPI changes:
1. ~~Wait for backend to regenerate OpenAPI spec~~
2. ~~Copy spec to client generator~~
3. ~~Run generator~~
4. ~~Build client~~
5. ~~Link to frontend~~
6. ~~Restart frontend~~
**With OATS:** Change your API ā Everything syncs automatically āØ
## š Configuration
OATS supports multiple configuration formats:
### JSON Configuration
```json
{
"$schema": "node_modules/@tryloop/oats/schema/oats.schema.json",
"services": {
"backend": {
"path": "./backend",
"port": 8000,
"startCommand": "npm run dev",
"apiSpec": {
"path": "/api/openapi.json"
}
},
"client": {
"path": "./api-client",
"packageName": "@myorg/api-client",
"generator": "@hey-api/openapi-ts"
},
"frontend": {
"path": "./frontend",
"port": 3000,
"startCommand": "npm run dev"
}
}
}
```
### TypeScript Configuration
```typescript
import { defineConfig } from '@tryloop/oats'
export default defineConfig({
services: {
backend: {
path: './backend',
port: 8000,
startCommand: 'npm run dev',
apiSpec: {
path: '/api/openapi.json'
}
},
client: {
path: './api-client',
packageName: '@myorg/api-client',
generator: '@hey-api/openapi-ts'
},
frontend: {
path: './frontend',
port: 3000,
startCommand: 'npm run dev'
}
}
})
```
> **Note**: TypeScript configs are fully supported. OATS includes esbuild for consistent transpilation across all environments.
### JavaScript Configuration
```javascript
const { defineConfig } = require('@tryloop/oats')
module.exports = defineConfig({
// Same structure as TypeScript config
})
```
## š Supported Technologies
### Backend Frameworks
| Language | Frameworks | OpenAPI Support |
|----------|-----------|-----------------|
| **Node.js** | [Express](https://expressjs.com/), [Fastify](https://www.fastify.io/), [NestJS](https://nestjs.com/), [Koa](https://koajs.com/), [Hapi](https://hapi.dev/) | Static files or runtime generation |
| **Python** | [FastAPI](https://fastapi.tiangolo.com/), [Flask](https://flask.palletsprojects.com/), [Django REST](https://www.django-rest-framework.org/) | Runtime endpoints (e.g., `/openapi.json`) |
### Frontend Frameworks
All major frameworks: [React](https://react.dev/), [Vue](https://vuejs.org/), [Angular](https://angular.io/), [Svelte](https://svelte.dev/), [Next.js](https://nextjs.org/), [Nuxt](https://nuxt.com/), [Remix](https://remix.run/)
### TypeScript Client Generators
- [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) (Recommended)
- [swagger-typescript-api](https://github.com/acacode/swagger-typescript-api)
- [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli)
- Custom generators (via `generateCommand`)
## š§ CLI Commands
| Command | Description | Options |
|---------|-------------|---------|
| `oats start` | Start all services with auto-sync | `--config`, `--quiet`, `--init-gen` |
| `oats init` | Create configuration interactively | `--force`, `--yes` |
| `oats validate` | Validate configuration file | `--config` |
| `oats detect` | Auto-detect project structure | - |
## šØ Key Features
### š Real-time Synchronization
- **File watching** with intelligent debouncing
- **Smart change detection** - ignores formatting changes
- **Hash-based caching** - skip unnecessary regeneration
- **Concurrent sync prevention** - no duplicate operations
### š ļø Developer Experience
- **Auto port management** - kills conflicting processes
- **Cross-platform support** - Windows, macOS, Linux
- **Config hot-reload** - changes restart services automatically
- **IntelliSense support** - JSON schema for autocompletion
- **Multiple config formats** - JSON, JS, or TypeScript (with built-in transpilation)
- **Automatic backend URL injection** - Frontend uses local API in dev, production in prod
### š Performance
- **45% faster sync** than manual process
- **Incremental builds** when possible
- **Parallel service startup**
- **Efficient polling** for runtime API specs
## š Examples
### Python FastAPI + React
```json
{
"services": {
"backend": {
"path": "../backend",
"port": 8000,
"runtime": "python",
"python": {
"virtualEnv": ".venv"
},
"startCommand": ".venv/bin/uvicorn main:app --reload",
"apiSpec": {
"path": "/openapi.json"
}
},
"client": {
"path": "../api-client",
"packageName": "@myapp/api",
"generator": "@hey-api/openapi-ts"
},
"frontend": {
"path": "./",
"port": 3000,
"startCommand": "npm start"
}
}
}
```
### NestJS + Next.js Monorepo
```json
{
"services": {
"backend": {
"path": "./apps/api",
"port": 3333,
"startCommand": "nx serve api",
"apiSpec": {
"path": "swagger.json"
}
},
"client": {
"path": "./packages/api-client",
"packageName": "@myapp/api-client",
"generator": "custom",
"generateCommand": "yarn openapi-ts"
},
"frontend": {
"path": "./apps/web",
"port": 4200,
"startCommand": "nx serve web"
}
}
}
```
## š Configuration Reference
### Service Configuration
| Property | Description | Required |
|----------|-------------|----------|
| `path` | Path to service directory | ā
|
| `port` | Port number (backend/frontend) | ā ļø |
| `startCommand` | Command to start service | ā
|
| `runtime` | `"node"` or `"python"` | ā |
| `apiSpec.path` | Path to OpenAPI spec | ā
|
ā ļø Port is required for backend/frontend services, but not for client
### Sync Options
| Option | Default | Description |
|--------|---------|-------------|
| `strategy` | `"smart"` | `"smart"` or `"aggressive"` |
| `debounceMs` | `1000` | Delay before regenerating |
| `autoLink` | `true` | Auto-link packages |
| `pollingInterval` | `5000` | For runtime API specs |
### Log Options
| Option | Default | Description |
|--------|---------|-------------|
| `level` | `"info"` | `"debug"`, `"info"`, `"warn"`, `"error"` |
| `colors` | `true` | Enable colored output |
| `timestamps` | `false` | Show timestamps in logs |
| `showServiceOutput` | `true` | Display output from services |
## š”ļø Troubleshooting
### Port conflicts
OATS automatically handles port conflicts. To disable:
```json
{
"services": {
"backend": {
"env": {
"OATS_AUTO_KILL_PORTS": "false"
}
}
}
}
```
### Client not updating
1. Check package is linked: `npm ls @myorg/api-client`
2. For Vite: Exclude from optimization in `vite.config.ts`
3. Ensure `packageName` matches your client's `package.json`
### Automatic Backend URL Injection
OATS automatically injects your backend URL into your frontend environment:
```typescript
// Your frontend code
const API_URL = import.meta.env.VITE_OATS_BACKEND_BASE_URL || 'https://api.production.com'
```
**How it works:**
1. OATS detects your frontend framework (Vite, CRA, Next.js, etc.)
2. Injects the backend URL with the correct prefix:
- Vite: `VITE_OATS_BACKEND_BASE_URL`
- Create React App: `REACT_APP_OATS_BACKEND_BASE_URL`
- Next.js: `NEXT_PUBLIC_OATS_BACKEND_BASE_URL`
- Vue CLI: `VUE_APP_OATS_BACKEND_BASE_URL`
3. Your app uses local backend when running with OATS, production otherwise
**No configuration needed** - it just works!
### TypeScript config issues
OATS fully supports TypeScript configs (`.ts` files) with built-in transpilation:
- Configs work consistently across all environments
- No additional setup or dependencies required
- Use ESM syntax: `export default defineConfig({...})`
### Command not found
Use npx or add to scripts:
```json
{
"scripts": {
"dev:sync": "oats start"
}
}
```
## š¤ Contributing
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
```bash
# Clone repo
git clone https://github.com/loopkitchen/oats.git
# Install dependencies
yarn install
# Run tests
yarn test
# Start development
yarn dev
```
## š License
MIT Ā© [Hari Shekhar](https://github.com/shekhardtu)
---
<p align="center">
<a href="https://github.com/loopkitchen/oats">GitHub</a> ā¢
<a href="https://www.npmjs.com/package/@tryloop/oats">npm</a> ā¢
<a href="https://github.com/loopkitchen/oats/issues">Issues</a>
</p>