@websublime/vite-plugin-open-api-server 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/index.d.ts +433 -0
- package/dist/index.js +585 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WebSublime
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @websublime/vite-plugin-open-api-server
|
|
2
|
+
|
|
3
|
+
Vite plugin for OpenAPI mock server with DevTools integration.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Zero-config mock server** - Automatically generates mock endpoints from OpenAPI spec
|
|
8
|
+
- 🔄 **Hot reload** - Handlers and seeds reload automatically on file changes
|
|
9
|
+
- 🎯 **Type-safe handlers** - Full TypeScript support with `defineHandlers()`
|
|
10
|
+
- 🌱 **Seed data** - Define initial data with Faker.js integration
|
|
11
|
+
- 🛠️ **DevTools** - Built-in DevTools for inspecting endpoints and data
|
|
12
|
+
- ⚡ **Seamless Vite integration** - Works with Vite's proxy system
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add -D @websublime/vite-plugin-open-api-server
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### 1. Add the plugin to your Vite config
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// vite.config.ts
|
|
26
|
+
import { defineConfig } from 'vite';
|
|
27
|
+
import vue from '@vitejs/plugin-vue';
|
|
28
|
+
import { openApiServer } from '@websublime/vite-plugin-open-api-server';
|
|
29
|
+
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
plugins: [
|
|
32
|
+
vue(),
|
|
33
|
+
openApiServer({
|
|
34
|
+
spec: './openapi/petstore.yaml',
|
|
35
|
+
port: 4000,
|
|
36
|
+
proxyPath: '/api',
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Create handler files (optional)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// mocks/handlers/pets.handlers.ts
|
|
46
|
+
import { defineHandlers } from '@websublime/vite-plugin-open-api-server';
|
|
47
|
+
|
|
48
|
+
export default defineHandlers({
|
|
49
|
+
getPetById: async ({ req, store }) => {
|
|
50
|
+
const pet = store.get('Pet', req.params.petId);
|
|
51
|
+
if (!pet) {
|
|
52
|
+
return { status: 404, data: { message: 'Pet not found' } };
|
|
53
|
+
}
|
|
54
|
+
return pet;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
createPet: async ({ req, store, faker }) => {
|
|
58
|
+
const newPet = {
|
|
59
|
+
id: faker.number.int({ min: 1000, max: 9999 }),
|
|
60
|
+
...req.body,
|
|
61
|
+
};
|
|
62
|
+
store.create('Pet', newPet);
|
|
63
|
+
return { status: 201, data: newPet };
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Create seed files (optional)
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// mocks/seeds/pets.seeds.ts
|
|
72
|
+
import { defineSeeds } from '@websublime/vite-plugin-open-api-server';
|
|
73
|
+
|
|
74
|
+
export default defineSeeds({
|
|
75
|
+
Pet: ({ seed, faker }) => {
|
|
76
|
+
return seed.count(10, () => ({
|
|
77
|
+
id: faker.number.int({ min: 1, max: 1000 }),
|
|
78
|
+
name: faker.animal.dog(),
|
|
79
|
+
category: {
|
|
80
|
+
id: faker.number.int({ min: 1, max: 5 }),
|
|
81
|
+
name: faker.helpers.arrayElement(['Dogs', 'Cats', 'Birds']),
|
|
82
|
+
},
|
|
83
|
+
status: faker.helpers.arrayElement(['available', 'pending', 'sold']),
|
|
84
|
+
}));
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 4. Start your Vite dev server
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pnpm dev
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The mock server will start automatically and you'll see a startup banner:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
╭──────────────────────────────────────────────────────╮
|
|
99
|
+
│ 🚀 OpenAPI Mock Server │
|
|
100
|
+
╰──────────────────────────────────────────────────────╯
|
|
101
|
+
|
|
102
|
+
API: Swagger Petstore v1.0.0
|
|
103
|
+
Server: http://localhost:4000
|
|
104
|
+
Proxy: /api → localhost:4000
|
|
105
|
+
|
|
106
|
+
Endpoints: 15 │ Handlers: 2 │ Seeds: 1
|
|
107
|
+
|
|
108
|
+
DevTools: http://localhost:4000/_devtools
|
|
109
|
+
API Info: http://localhost:4000/_api
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Configuration
|
|
113
|
+
|
|
114
|
+
| Option | Type | Default | Description |
|
|
115
|
+
|--------|------|---------|-------------|
|
|
116
|
+
| `spec` | `string` | **required** | Path to OpenAPI spec file (YAML or JSON) |
|
|
117
|
+
| `port` | `number` | `4000` | Mock server port |
|
|
118
|
+
| `proxyPath` | `string` | `'/api'` | Vite proxy path prefix |
|
|
119
|
+
| `handlersDir` | `string` | `'./mocks/handlers'` | Directory for handler files |
|
|
120
|
+
| `seedsDir` | `string` | `'./mocks/seeds'` | Directory for seed files |
|
|
121
|
+
| `enabled` | `boolean` | `true` | Enable/disable the plugin |
|
|
122
|
+
| `idFields` | `Record<string, string>` | `{}` | ID field per schema |
|
|
123
|
+
| `timelineLimit` | `number` | `500` | Max timeline events |
|
|
124
|
+
| `devtools` | `boolean` | `true` | Enable DevTools |
|
|
125
|
+
| `cors` | `boolean` | `true` | Enable CORS |
|
|
126
|
+
| `corsOrigin` | `string \| string[]` | `'*'` | CORS origin configuration |
|
|
127
|
+
| `silent` | `boolean` | `false` | Suppress startup banner |
|
|
128
|
+
|
|
129
|
+
## Handler Context
|
|
130
|
+
|
|
131
|
+
Handlers receive a context object with:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
interface HandlerContext {
|
|
135
|
+
req: {
|
|
136
|
+
method: string;
|
|
137
|
+
path: string;
|
|
138
|
+
params: Record<string, string>;
|
|
139
|
+
query: Record<string, string>;
|
|
140
|
+
body: unknown;
|
|
141
|
+
headers: Record<string, string>;
|
|
142
|
+
};
|
|
143
|
+
store: Store;
|
|
144
|
+
faker: Faker;
|
|
145
|
+
logger: Logger;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Response Formats
|
|
150
|
+
|
|
151
|
+
Handlers can return data in several formats:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// Simple data (status 200)
|
|
155
|
+
return { id: 1, name: 'Fluffy' };
|
|
156
|
+
|
|
157
|
+
// With status code
|
|
158
|
+
return { status: 201, data: { id: 1, name: 'Fluffy' } };
|
|
159
|
+
|
|
160
|
+
// With headers
|
|
161
|
+
return {
|
|
162
|
+
status: 200,
|
|
163
|
+
data: { id: 1 },
|
|
164
|
+
headers: { 'X-Custom': 'value' },
|
|
165
|
+
};
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## File Naming Conventions
|
|
169
|
+
|
|
170
|
+
- Handlers: `*.handlers.ts` or `*.handlers.js`
|
|
171
|
+
- Seeds: `*.seeds.ts` or `*.seeds.js`
|
|
172
|
+
|
|
173
|
+
## Response Priority
|
|
174
|
+
|
|
175
|
+
When a request comes in, the server looks for a response in this order:
|
|
176
|
+
|
|
177
|
+
1. **Custom Handler** - If defined for the operationId
|
|
178
|
+
2. **Seed Data** - If data exists in the store
|
|
179
|
+
3. **OpenAPI Example** - If defined in the spec
|
|
180
|
+
4. **Generated Data** - Auto-generated from schema using Faker.js
|
|
181
|
+
|
|
182
|
+
## Internal API
|
|
183
|
+
|
|
184
|
+
The mock server exposes internal endpoints for debugging:
|
|
185
|
+
|
|
186
|
+
- `/_api` - Server info and stats
|
|
187
|
+
- `/_api/registry` - List all endpoints
|
|
188
|
+
- `/_api/store` - View store data
|
|
189
|
+
- `/_api/timeline` - Request/response history
|
|
190
|
+
- `/_api/simulations` - Active error simulations
|
|
191
|
+
- `/_devtools` - DevTools SPA
|
|
192
|
+
|
|
193
|
+
## Requirements
|
|
194
|
+
|
|
195
|
+
- **Node.js**: ^20.19.0 || >=22.12.0
|
|
196
|
+
- **pnpm**: 9.x
|
|
197
|
+
|
|
198
|
+
## Related Packages
|
|
199
|
+
|
|
200
|
+
| Package | Description |
|
|
201
|
+
|---------|-------------|
|
|
202
|
+
| `@websublime/vite-plugin-open-api-core` | Core server, store, router, generator |
|
|
203
|
+
| `@websublime/vite-plugin-open-api-devtools` | Vue DevTools SPA |
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { Plugin, ViteDevServer } from 'vite';
|
|
2
|
+
import { Logger, HandlerFn, AnySeedFn } from '@websublime/vite-plugin-open-api-core';
|
|
3
|
+
export { HandlerContext, HandlerDefinition, HandlerFn, HandlerReturn, SeedContext, SeedDefinition, SeedFn, SeedHelper, defineHandlers, defineSeeds } from '@websublime/vite-plugin-open-api-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vite Plugin Types
|
|
7
|
+
*
|
|
8
|
+
* What: Type definitions for the OpenAPI server Vite plugin
|
|
9
|
+
* How: Defines configuration options and internal types
|
|
10
|
+
* Why: Provides type safety and documentation for plugin consumers
|
|
11
|
+
*
|
|
12
|
+
* @module types
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Plugin configuration options
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { openApiServer } from '@websublime/vite-plugin-open-api-server';
|
|
21
|
+
*
|
|
22
|
+
* export default defineConfig({
|
|
23
|
+
* plugins: [
|
|
24
|
+
* openApiServer({
|
|
25
|
+
* spec: './openapi/petstore.yaml',
|
|
26
|
+
* port: 4000,
|
|
27
|
+
* proxyPath: '/api',
|
|
28
|
+
* handlersDir: './mocks/handlers',
|
|
29
|
+
* seedsDir: './mocks/seeds',
|
|
30
|
+
* }),
|
|
31
|
+
* ],
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
interface OpenApiServerOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Path to OpenAPI spec file (required)
|
|
38
|
+
*
|
|
39
|
+
* Supports:
|
|
40
|
+
* - Local file paths (relative or absolute)
|
|
41
|
+
* - URLs (http:// or https://)
|
|
42
|
+
* - YAML or JSON format
|
|
43
|
+
*
|
|
44
|
+
* @example './openapi/petstore.yaml'
|
|
45
|
+
* @example 'https://petstore3.swagger.io/api/v3/openapi.json'
|
|
46
|
+
*/
|
|
47
|
+
spec: string;
|
|
48
|
+
/**
|
|
49
|
+
* Server port for the mock server
|
|
50
|
+
*
|
|
51
|
+
* The mock server runs on this port, and Vite proxies
|
|
52
|
+
* requests from `proxyPath` to this server.
|
|
53
|
+
*
|
|
54
|
+
* @default 4000
|
|
55
|
+
*/
|
|
56
|
+
port?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Base path for request proxy
|
|
59
|
+
*
|
|
60
|
+
* All requests to this path in your Vite dev server
|
|
61
|
+
* will be proxied to the mock server.
|
|
62
|
+
*
|
|
63
|
+
* @example '/api/v3'
|
|
64
|
+
* @default '/api'
|
|
65
|
+
*/
|
|
66
|
+
proxyPath?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Directory containing handler files
|
|
69
|
+
*
|
|
70
|
+
* Handler files should export an object with operationId keys
|
|
71
|
+
* and handler functions as values. Use `defineHandlers()` for
|
|
72
|
+
* type-safe handler definitions.
|
|
73
|
+
*
|
|
74
|
+
* @example './mocks/handlers'
|
|
75
|
+
* @default './mocks/handlers'
|
|
76
|
+
*/
|
|
77
|
+
handlersDir?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Directory containing seed files
|
|
80
|
+
*
|
|
81
|
+
* Seed files should export an object with schema name keys
|
|
82
|
+
* and seed functions as values. Use `defineSeeds()` for
|
|
83
|
+
* type-safe seed definitions.
|
|
84
|
+
*
|
|
85
|
+
* @example './mocks/seeds'
|
|
86
|
+
* @default './mocks/seeds'
|
|
87
|
+
*/
|
|
88
|
+
seedsDir?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Enable/disable the plugin
|
|
91
|
+
*
|
|
92
|
+
* When false, the plugin does nothing and Vite runs normally.
|
|
93
|
+
* Useful for conditional enabling based on environment.
|
|
94
|
+
*
|
|
95
|
+
* @default true
|
|
96
|
+
*/
|
|
97
|
+
enabled?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* ID field configuration per schema
|
|
100
|
+
*
|
|
101
|
+
* Maps schema names to the field used as the primary identifier.
|
|
102
|
+
* Used by the store for CRUD operations.
|
|
103
|
+
*
|
|
104
|
+
* @example { User: 'username', Order: 'orderId' }
|
|
105
|
+
* @default {} (uses 'id' for all schemas)
|
|
106
|
+
*/
|
|
107
|
+
idFields?: Record<string, string>;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum timeline events to keep
|
|
110
|
+
*
|
|
111
|
+
* The timeline stores request/response history for DevTools.
|
|
112
|
+
* Older events are removed when this limit is exceeded.
|
|
113
|
+
*
|
|
114
|
+
* @default 500
|
|
115
|
+
*/
|
|
116
|
+
timelineLimit?: number;
|
|
117
|
+
/**
|
|
118
|
+
* Enable DevTools integration
|
|
119
|
+
*
|
|
120
|
+
* When true, mounts the DevTools SPA at `/_devtools`
|
|
121
|
+
* and enables Vue DevTools custom tab.
|
|
122
|
+
*
|
|
123
|
+
* @default true
|
|
124
|
+
*/
|
|
125
|
+
devtools?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Enable CORS on the mock server
|
|
128
|
+
*
|
|
129
|
+
* @default true
|
|
130
|
+
*/
|
|
131
|
+
cors?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* CORS origin configuration
|
|
134
|
+
*
|
|
135
|
+
* @default '*'
|
|
136
|
+
*/
|
|
137
|
+
corsOrigin?: string | string[];
|
|
138
|
+
/**
|
|
139
|
+
* Custom logger instance
|
|
140
|
+
*
|
|
141
|
+
* Defaults to a Vite-integrated logger that respects
|
|
142
|
+
* Vite's logging level settings.
|
|
143
|
+
*/
|
|
144
|
+
logger?: Logger;
|
|
145
|
+
/**
|
|
146
|
+
* Suppress startup banner
|
|
147
|
+
*
|
|
148
|
+
* When true, the plugin won't print the startup banner
|
|
149
|
+
* showing server details and loaded handlers/seeds.
|
|
150
|
+
*
|
|
151
|
+
* @default false
|
|
152
|
+
*/
|
|
153
|
+
silent?: boolean;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Resolved plugin options with defaults applied
|
|
157
|
+
*
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
interface ResolvedOptions {
|
|
161
|
+
spec: string;
|
|
162
|
+
port: number;
|
|
163
|
+
proxyPath: string;
|
|
164
|
+
handlersDir: string;
|
|
165
|
+
seedsDir: string;
|
|
166
|
+
enabled: boolean;
|
|
167
|
+
idFields: Record<string, string>;
|
|
168
|
+
timelineLimit: number;
|
|
169
|
+
devtools: boolean;
|
|
170
|
+
cors: boolean;
|
|
171
|
+
corsOrigin: string | string[];
|
|
172
|
+
silent: boolean;
|
|
173
|
+
logger?: Logger;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Vite Plugin Implementation
|
|
178
|
+
*
|
|
179
|
+
* What: Main Vite plugin for OpenAPI mock server
|
|
180
|
+
* How: Uses configureServer hook to start mock server and configure proxy
|
|
181
|
+
* Why: Integrates OpenAPI mock server seamlessly into Vite dev workflow
|
|
182
|
+
*
|
|
183
|
+
* @module plugin
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Create the OpenAPI Server Vite plugin
|
|
188
|
+
*
|
|
189
|
+
* This plugin starts a mock server based on an OpenAPI specification
|
|
190
|
+
* and configures Vite to proxy API requests to it.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* // vite.config.ts
|
|
195
|
+
* import { defineConfig } from 'vite';
|
|
196
|
+
* import vue from '@vitejs/plugin-vue';
|
|
197
|
+
* import { openApiServer } from '@websublime/vite-plugin-open-api-server';
|
|
198
|
+
*
|
|
199
|
+
* export default defineConfig({
|
|
200
|
+
* plugins: [
|
|
201
|
+
* vue(),
|
|
202
|
+
* openApiServer({
|
|
203
|
+
* spec: './openapi/petstore.yaml',
|
|
204
|
+
* port: 4000,
|
|
205
|
+
* proxyPath: '/api',
|
|
206
|
+
* handlersDir: './mocks/handlers',
|
|
207
|
+
* seedsDir: './mocks/seeds',
|
|
208
|
+
* }),
|
|
209
|
+
* ],
|
|
210
|
+
* });
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* @param options - Plugin configuration options
|
|
214
|
+
* @returns Vite plugin
|
|
215
|
+
*/
|
|
216
|
+
declare function openApiServer(options: OpenApiServerOptions): Plugin;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Handler Loading
|
|
220
|
+
*
|
|
221
|
+
* What: Loads handler files from a directory using glob patterns
|
|
222
|
+
* How: Uses Vite's ssrLoadModule to transform and load TypeScript files
|
|
223
|
+
* Why: Enables users to define custom handlers for operationIds in TypeScript
|
|
224
|
+
*
|
|
225
|
+
* @module handlers
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Result of loading handlers
|
|
230
|
+
*/
|
|
231
|
+
interface LoadHandlersResult {
|
|
232
|
+
/** Map of operationId to handler function */
|
|
233
|
+
handlers: Map<string, HandlerFn>;
|
|
234
|
+
/** Number of handler files loaded */
|
|
235
|
+
fileCount: number;
|
|
236
|
+
/** List of loaded file paths (relative) */
|
|
237
|
+
files: string[];
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Load handlers from a directory
|
|
241
|
+
*
|
|
242
|
+
* Searches for handler files matching the pattern `*.handlers.{ts,js,mjs}`
|
|
243
|
+
* in the specified directory. Each file should export an object with
|
|
244
|
+
* operationId keys and handler functions as values.
|
|
245
|
+
*
|
|
246
|
+
* Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* // mocks/handlers/pets.handlers.ts
|
|
251
|
+
* import { defineHandlers } from '@websublime/vite-plugin-open-api-core';
|
|
252
|
+
*
|
|
253
|
+
* export default defineHandlers({
|
|
254
|
+
* getPetById: async ({ req, store }) => {
|
|
255
|
+
* const pet = store.get('Pet', req.params.petId);
|
|
256
|
+
* return pet ?? { status: 404, data: { message: 'Pet not found' } };
|
|
257
|
+
* },
|
|
258
|
+
* });
|
|
259
|
+
* ```
|
|
260
|
+
*
|
|
261
|
+
* @param handlersDir - Directory to search for handler files
|
|
262
|
+
* @param viteServer - Vite dev server instance for ssrLoadModule
|
|
263
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
264
|
+
* @param logger - Optional logger for warnings/errors
|
|
265
|
+
* @returns Promise resolving to loaded handlers
|
|
266
|
+
*/
|
|
267
|
+
declare function loadHandlers(handlersDir: string, viteServer: ViteDevServer, cwd?: string, logger?: Logger): Promise<LoadHandlersResult>;
|
|
268
|
+
/**
|
|
269
|
+
* Get list of handler files in a directory
|
|
270
|
+
*
|
|
271
|
+
* Useful for file watching setup.
|
|
272
|
+
*
|
|
273
|
+
* @param handlersDir - Directory to search
|
|
274
|
+
* @param cwd - Current working directory
|
|
275
|
+
* @returns Promise resolving to list of absolute file paths
|
|
276
|
+
*/
|
|
277
|
+
declare function getHandlerFiles(handlersDir: string, cwd?: string): Promise<string[]>;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Seed Loading
|
|
281
|
+
*
|
|
282
|
+
* What: Loads seed files from a directory using glob patterns
|
|
283
|
+
* How: Uses Vite's ssrLoadModule to transform and load TypeScript files
|
|
284
|
+
* Why: Enables users to define seed data for schemas in TypeScript
|
|
285
|
+
*
|
|
286
|
+
* @module seeds
|
|
287
|
+
*/
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Result of loading seeds
|
|
291
|
+
*/
|
|
292
|
+
interface LoadSeedsResult {
|
|
293
|
+
/** Map of schema name to seed function */
|
|
294
|
+
seeds: Map<string, AnySeedFn>;
|
|
295
|
+
/** Number of seed files loaded */
|
|
296
|
+
fileCount: number;
|
|
297
|
+
/** List of loaded file paths (relative) */
|
|
298
|
+
files: string[];
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Load seeds from a directory
|
|
302
|
+
*
|
|
303
|
+
* Searches for seed files matching the pattern `*.seeds.{ts,js,mjs}`
|
|
304
|
+
* in the specified directory. Each file should export an object with
|
|
305
|
+
* schema name keys and seed functions as values.
|
|
306
|
+
*
|
|
307
|
+
* Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```typescript
|
|
311
|
+
* // mocks/seeds/pets.seeds.ts
|
|
312
|
+
* import { defineSeeds } from '@websublime/vite-plugin-open-api-core';
|
|
313
|
+
*
|
|
314
|
+
* export default defineSeeds({
|
|
315
|
+
* Pet: ({ seed, faker }) => {
|
|
316
|
+
* return seed.count(10, () => ({
|
|
317
|
+
* id: faker.number.int({ min: 1, max: 1000 }),
|
|
318
|
+
* name: faker.animal.dog(),
|
|
319
|
+
* status: faker.helpers.arrayElement(['available', 'pending', 'sold']),
|
|
320
|
+
* }));
|
|
321
|
+
* },
|
|
322
|
+
* });
|
|
323
|
+
* ```
|
|
324
|
+
*
|
|
325
|
+
* @param seedsDir - Directory to search for seed files
|
|
326
|
+
* @param viteServer - Vite dev server instance for ssrLoadModule
|
|
327
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
328
|
+
* @param logger - Optional logger for warnings/errors
|
|
329
|
+
* @returns Promise resolving to loaded seeds
|
|
330
|
+
*/
|
|
331
|
+
declare function loadSeeds(seedsDir: string, viteServer: ViteDevServer, cwd?: string, logger?: Logger): Promise<LoadSeedsResult>;
|
|
332
|
+
/**
|
|
333
|
+
* Get list of seed files in a directory
|
|
334
|
+
*
|
|
335
|
+
* Useful for file watching setup.
|
|
336
|
+
*
|
|
337
|
+
* @param seedsDir - Directory to search
|
|
338
|
+
* @param cwd - Current working directory
|
|
339
|
+
* @returns Promise resolving to list of absolute file paths
|
|
340
|
+
*/
|
|
341
|
+
declare function getSeedFiles(seedsDir: string, cwd?: string): Promise<string[]>;
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Hot Reload
|
|
345
|
+
*
|
|
346
|
+
* What: File watcher for hot reloading handlers and seeds
|
|
347
|
+
* How: Uses chokidar to watch for file changes
|
|
348
|
+
* Why: Enables rapid development iteration without server restart
|
|
349
|
+
*
|
|
350
|
+
* @module hot-reload
|
|
351
|
+
*
|
|
352
|
+
* TODO: Full implementation in Task 3.3
|
|
353
|
+
* This module provides placeholder/basic functionality for Task 3.1
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* File watcher configuration
|
|
358
|
+
*/
|
|
359
|
+
interface FileWatcherOptions {
|
|
360
|
+
/** Directory containing handler files */
|
|
361
|
+
handlersDir?: string;
|
|
362
|
+
/** Directory containing seed files */
|
|
363
|
+
seedsDir?: string;
|
|
364
|
+
/** Callback when a handler file changes */
|
|
365
|
+
onHandlerChange?: (filePath: string) => Promise<void> | void;
|
|
366
|
+
/** Callback when a seed file changes */
|
|
367
|
+
onSeedChange?: (filePath: string) => Promise<void> | void;
|
|
368
|
+
/** Current working directory */
|
|
369
|
+
cwd?: string;
|
|
370
|
+
/** Logger for error messages */
|
|
371
|
+
logger?: Logger;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* File watcher instance
|
|
375
|
+
*/
|
|
376
|
+
interface FileWatcher {
|
|
377
|
+
/** Close the watcher and release resources */
|
|
378
|
+
close(): Promise<void>;
|
|
379
|
+
/** Check if watcher is active */
|
|
380
|
+
readonly isWatching: boolean;
|
|
381
|
+
/** Promise that resolves when all watchers are ready */
|
|
382
|
+
readonly ready: Promise<void>;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Create a file watcher for handlers and seeds
|
|
386
|
+
*
|
|
387
|
+
* Watches for changes to handler and seed files and invokes
|
|
388
|
+
* callbacks when changes are detected. Supports add, change,
|
|
389
|
+
* and unlink events.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const watcher = await createFileWatcher({
|
|
394
|
+
* handlersDir: './mocks/handlers',
|
|
395
|
+
* seedsDir: './mocks/seeds',
|
|
396
|
+
* onHandlerChange: async (file) => {
|
|
397
|
+
* console.log('Handler changed:', file);
|
|
398
|
+
* const handlers = await loadHandlers('./mocks/handlers');
|
|
399
|
+
* server.updateHandlers(handlers.handlers);
|
|
400
|
+
* },
|
|
401
|
+
* onSeedChange: async (file) => {
|
|
402
|
+
* console.log('Seed changed:', file);
|
|
403
|
+
* const seeds = await loadSeeds('./mocks/seeds');
|
|
404
|
+
* // Re-execute seeds...
|
|
405
|
+
* },
|
|
406
|
+
* });
|
|
407
|
+
*
|
|
408
|
+
* // Later, clean up
|
|
409
|
+
* await watcher.close();
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* @param options - Watcher configuration
|
|
413
|
+
* @returns Promise resolving to file watcher instance
|
|
414
|
+
*/
|
|
415
|
+
declare function createFileWatcher(options: FileWatcherOptions): Promise<FileWatcher>;
|
|
416
|
+
/**
|
|
417
|
+
* Debounce a function with async execution guard
|
|
418
|
+
*
|
|
419
|
+
* Useful for preventing multiple rapid reloads when
|
|
420
|
+
* multiple files change at once (e.g., during save all).
|
|
421
|
+
*
|
|
422
|
+
* This implementation prevents overlapping async executions:
|
|
423
|
+
* - If the function is already running, the call is queued
|
|
424
|
+
* - When the running function completes, it executes with the latest args
|
|
425
|
+
* - Multiple calls during execution are coalesced into one
|
|
426
|
+
*
|
|
427
|
+
* @param fn - Function to debounce (can be sync or async)
|
|
428
|
+
* @param delay - Debounce delay in milliseconds
|
|
429
|
+
* @returns Debounced function
|
|
430
|
+
*/
|
|
431
|
+
declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
432
|
+
|
|
433
|
+
export { type FileWatcher, type FileWatcherOptions, type LoadHandlersResult, type LoadSeedsResult, type OpenApiServerOptions, type ResolvedOptions, createFileWatcher, debounce, getHandlerFiles, getSeedFiles, loadHandlers, loadSeeds, openApiServer };
|