UNPKG

@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
# 🌾 OATS - OpenAPI TypeScript Sync > Automatically sync OpenAPI specs to TypeScript clients. No manual steps, just real-time updates. [![npm version](https://img.shields.io/npm/v/@tryloop/oats.svg)](https://www.npmjs.com/package/@tryloop/oats) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Node.js Version](https://img.shields.io/node/v/@tryloop/oats.svg)](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>