|
| 1 | +# @intrig/plugin-nest |
| 2 | + |
| 3 | +NestJS plugin for Intrig that generates injectable services from OpenAPI specifications. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This plugin generates type-safe NestJS services from OpenAPI specs, organized by API tags. Each service contains methods corresponding to REST endpoints, fully typed with request/response schemas. |
| 8 | + |
| 9 | +## Features |
| 10 | + |
| 11 | +- **Tag-based Service Organization**: Groups endpoints by OpenAPI tags into separate injectable services |
| 12 | +- **Type-safe Generated Code**: Full TypeScript types from OpenAPI schemas |
| 13 | +- **NestJS HttpService Integration**: Uses `@nestjs/axios` for HTTP operations |
| 14 | +- **Promise-based API**: All methods return promises (observables converted with `firstValueFrom`) |
| 15 | +- **Dependency Injection Ready**: All services are decorated with `@Injectable()` |
| 16 | +- **Module Export**: Single `IntrigModule` exports all generated services |
| 17 | + |
| 18 | +## Installation |
| 19 | + |
| 20 | +```bash |
| 21 | +npm install @intrig/plugin-nest |
| 22 | +``` |
| 23 | + |
| 24 | +## Usage |
| 25 | + |
| 26 | +### 1. Configure Intrig |
| 27 | + |
| 28 | +In your `intrig.config.json`: |
| 29 | + |
| 30 | +```json |
| 31 | +{ |
| 32 | + "generator": "nest", |
| 33 | + "sources": [ |
| 34 | + { |
| 35 | + "id": "petstore", |
| 36 | + "name": "Petstore API", |
| 37 | + "specUrl": "https://petstore3.swagger.io/api/v3/openapi.json" |
| 38 | + } |
| 39 | + ] |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +### 2. Generate Services |
| 44 | + |
| 45 | +```bash |
| 46 | +npx intrig build |
| 47 | +``` |
| 48 | + |
| 49 | +This generates: |
| 50 | +- `@intrig/nest/IntrigModule` - NestJS module |
| 51 | +- Service classes per tag (e.g., `UsersService`, `ProductsService`) |
| 52 | +- TypeScript types for all schemas |
| 53 | +- Full type safety for requests and responses |
| 54 | + |
| 55 | +### 3. Import IntrigModule |
| 56 | + |
| 57 | +In your `app.module.ts`: |
| 58 | + |
| 59 | +```typescript |
| 60 | +import { Module } from '@nestjs/common'; |
| 61 | +import { IntrigModule } from '@intrig/nest'; |
| 62 | + |
| 63 | +@Module({ |
| 64 | + imports: [IntrigModule], |
| 65 | + // ... |
| 66 | +}) |
| 67 | +export class AppModule {} |
| 68 | +``` |
| 69 | + |
| 70 | +### 4. Inject and Use Services |
| 71 | + |
| 72 | +```typescript |
| 73 | +import { Injectable } from '@nestjs/common'; |
| 74 | +import { UsersService } from '@intrig/nest'; |
| 75 | + |
| 76 | +@Injectable() |
| 77 | +export class MyService { |
| 78 | + constructor(private readonly usersService: UsersService) {} |
| 79 | + |
| 80 | + async getUser(id: string) { |
| 81 | + return this.usersService.getUser(id); |
| 82 | + } |
| 83 | + |
| 84 | + async createUser(data: CreateUserDto) { |
| 85 | + return this.usersService.createUser(data); |
| 86 | + } |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +## Generated Code Structure |
| 91 | + |
| 92 | +``` |
| 93 | +node_modules/@intrig/nest/ |
| 94 | +├── intrig.module.ts # Main NestJS module |
| 95 | +├── index.ts # Barrel exports |
| 96 | +├── users/ |
| 97 | +│ └── users.service.ts # UsersService (from 'users' tag) |
| 98 | +├── products/ |
| 99 | +│ └── products.service.ts # ProductsService (from 'products' tag) |
| 100 | +└── components/ |
| 101 | + └── schemas/ # TypeScript types |
| 102 | + ├── User.ts |
| 103 | + ├── Product.ts |
| 104 | + └── ... |
| 105 | +``` |
| 106 | + |
| 107 | +## Example Generated Service |
| 108 | + |
| 109 | +```typescript |
| 110 | +import { Injectable } from '@nestjs/common'; |
| 111 | +import { HttpService } from '@nestjs/axios'; |
| 112 | +import { firstValueFrom } from 'rxjs'; |
| 113 | +import { User } from '../components/schemas/User'; |
| 114 | +import { CreateUserDto } from '../components/schemas/CreateUserDto'; |
| 115 | + |
| 116 | +@Injectable() |
| 117 | +export class UsersService { |
| 118 | + constructor(private readonly httpService: HttpService) {} |
| 119 | + |
| 120 | + async getUser(id: string): Promise<User> { |
| 121 | + const response = await firstValueFrom( |
| 122 | + this.httpService.get<User>(`/users/${id}`) |
| 123 | + ); |
| 124 | + return response.data; |
| 125 | + } |
| 126 | + |
| 127 | + async createUser(data: CreateUserDto): Promise<User> { |
| 128 | + const response = await firstValueFrom( |
| 129 | + this.httpService.post<User>('/users', data) |
| 130 | + ); |
| 131 | + return response.data; |
| 132 | + } |
| 133 | + |
| 134 | + async deleteUser(id: string): Promise<void> { |
| 135 | + await firstValueFrom( |
| 136 | + this.httpService.delete(`/users/${id}`) |
| 137 | + ); |
| 138 | + } |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +## Configuration Options |
| 143 | + |
| 144 | +### Plugin Options |
| 145 | + |
| 146 | +```typescript |
| 147 | +export type NestPluginOptions = { |
| 148 | + baseURL?: string; // Optional base URL for HTTP client |
| 149 | +}; |
| 150 | +``` |
| 151 | + |
| 152 | +Currently, the plugin doesn't require specific options. The `baseURL` option is reserved for future use to configure the HTTP client's base URL. |
| 153 | + |
| 154 | +## Architecture |
| 155 | + |
| 156 | +- **Services**: One service per OpenAPI tag |
| 157 | +- **Methods**: One async method per endpoint operation |
| 158 | +- **Types**: Generated from OpenAPI schemas (no runtime validation) |
| 159 | +- **HTTP Client**: NestJS `HttpService` (axios wrapper) |
| 160 | +- **Error Handling**: Let NestJS exception filters handle errors |
| 161 | + |
| 162 | +## Comparison with React Plugin |
| 163 | + |
| 164 | +| Feature | React Plugin | NestJS Plugin | |
| 165 | +|---------|-------------|---------------| |
| 166 | +| **Target** | Browser (React hooks) | Server (NestJS services) | |
| 167 | +| **State Management** | Yes (React state) | No | |
| 168 | +| **Caching** | Yes (built-in) | No (use NestJS interceptors) | |
| 169 | +| **Validation** | Zod schemas | TypeScript types only | |
| 170 | +| **Organization** | By source | By OpenAPI tag | |
| 171 | +| **DI** | React Context | NestJS DI | |
| 172 | + |
| 173 | +## Development |
| 174 | + |
| 175 | +### Build |
| 176 | + |
| 177 | +```bash |
| 178 | +nx build @intrig/plugin-nest |
| 179 | +``` |
| 180 | + |
| 181 | +### Test |
| 182 | + |
| 183 | +```bash |
| 184 | +nx test @intrig/plugin-nest |
| 185 | +``` |
| 186 | + |
| 187 | +## License |
| 188 | + |
| 189 | +MIT |
0 commit comments