@zze/mock-server 0.2.4
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/README.md +643 -0
- package/dist/__tests__/mock-server.test.d.ts +5 -0
- package/dist/__tests__/mock-server.test.d.ts.map +1 -0
- package/dist/__tests__/mock-server.test.js +599 -0
- package/dist/__tests__/mock-server.test.js.map +1 -0
- package/dist/admin/__tests__/admin-router.test.d.ts +2 -0
- package/dist/admin/__tests__/admin-router.test.d.ts.map +1 -0
- package/dist/admin/__tests__/admin-router.test.js +621 -0
- package/dist/admin/__tests__/admin-router.test.js.map +1 -0
- package/dist/admin/admin-router.d.ts +27 -0
- package/dist/admin/admin-router.d.ts.map +1 -0
- package/dist/admin/admin-router.js +616 -0
- package/dist/admin/admin-router.js.map +1 -0
- package/dist/admin/index.d.ts +4 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +10 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/types.d.ts +185 -0
- package/dist/admin/types.d.ts.map +1 -0
- package/dist/admin/types.js +33 -0
- package/dist/admin/types.js.map +1 -0
- package/dist/config/__tests__/config-discovery.test.d.ts +2 -0
- package/dist/config/__tests__/config-discovery.test.d.ts.map +1 -0
- package/dist/config/__tests__/config-discovery.test.js +52 -0
- package/dist/config/__tests__/config-discovery.test.js.map +1 -0
- package/dist/config/__tests__/config-loader.test.d.ts +2 -0
- package/dist/config/__tests__/config-loader.test.d.ts.map +1 -0
- package/dist/config/__tests__/config-loader.test.js +124 -0
- package/dist/config/__tests__/config-loader.test.js.map +1 -0
- package/dist/config/__tests__/file-loader.test.d.ts +2 -0
- package/dist/config/__tests__/file-loader.test.d.ts.map +1 -0
- package/dist/config/__tests__/file-loader.test.js +63 -0
- package/dist/config/__tests__/file-loader.test.js.map +1 -0
- package/dist/config/__tests__/fixtures/mock-config/endpoints/products.d.ts +25 -0
- package/dist/config/__tests__/fixtures/mock-config/endpoints/products.d.ts.map +1 -0
- package/dist/config/__tests__/fixtures/mock-config/endpoints/products.js +25 -0
- package/dist/config/__tests__/fixtures/mock-config/endpoints/products.js.map +1 -0
- package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.d.ts +11 -0
- package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.d.ts.map +1 -0
- package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.js +11 -0
- package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.js.map +1 -0
- package/dist/config/config-discovery.d.ts +23 -0
- package/dist/config/config-discovery.d.ts.map +1 -0
- package/dist/config/config-discovery.js +60 -0
- package/dist/config/config-discovery.js.map +1 -0
- package/dist/config/config-loader.d.ts +56 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +162 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/config-writer.d.ts +96 -0
- package/dist/config/config-writer.d.ts.map +1 -0
- package/dist/config/config-writer.js +248 -0
- package/dist/config/config-writer.js.map +1 -0
- package/dist/config/file-loader.d.ts +16 -0
- package/dist/config/file-loader.d.ts.map +1 -0
- package/dist/config/file-loader.js +90 -0
- package/dist/config/file-loader.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +47 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +7 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/mock-server.d.ts +243 -0
- package/dist/mock-server.d.ts.map +1 -0
- package/dist/mock-server.js +387 -0
- package/dist/mock-server.js.map +1 -0
- package/dist/resolver/__tests__/response-resolver.test.d.ts +2 -0
- package/dist/resolver/__tests__/response-resolver.test.d.ts.map +1 -0
- package/dist/resolver/__tests__/response-resolver.test.js +358 -0
- package/dist/resolver/__tests__/response-resolver.test.js.map +1 -0
- package/dist/resolver/index.d.ts +4 -0
- package/dist/resolver/index.d.ts.map +1 -0
- package/dist/resolver/index.js +9 -0
- package/dist/resolver/index.js.map +1 -0
- package/dist/resolver/response-resolver.d.ts +73 -0
- package/dist/resolver/response-resolver.d.ts.map +1 -0
- package/dist/resolver/response-resolver.js +167 -0
- package/dist/resolver/response-resolver.js.map +1 -0
- package/dist/resolver/types.d.ts +47 -0
- package/dist/resolver/types.d.ts.map +1 -0
- package/dist/resolver/types.js +9 -0
- package/dist/resolver/types.js.map +1 -0
- package/dist/schemas/__tests__/config.validator.test.d.ts +2 -0
- package/dist/schemas/__tests__/config.validator.test.d.ts.map +1 -0
- package/dist/schemas/__tests__/config.validator.test.js +66 -0
- package/dist/schemas/__tests__/config.validator.test.js.map +1 -0
- package/dist/schemas/__tests__/endpoint.schema.test.d.ts +2 -0
- package/dist/schemas/__tests__/endpoint.schema.test.d.ts.map +1 -0
- package/dist/schemas/__tests__/endpoint.schema.test.js +103 -0
- package/dist/schemas/__tests__/endpoint.schema.test.js.map +1 -0
- package/dist/schemas/__tests__/flow.schema.test.d.ts +2 -0
- package/dist/schemas/__tests__/flow.schema.test.d.ts.map +1 -0
- package/dist/schemas/__tests__/flow.schema.test.js +92 -0
- package/dist/schemas/__tests__/flow.schema.test.js.map +1 -0
- package/dist/schemas/config.validator.d.ts +39 -0
- package/dist/schemas/config.validator.d.ts.map +1 -0
- package/dist/schemas/config.validator.js +117 -0
- package/dist/schemas/config.validator.js.map +1 -0
- package/dist/schemas/endpoint.schema.d.ts +108 -0
- package/dist/schemas/endpoint.schema.d.ts.map +1 -0
- package/dist/schemas/endpoint.schema.js +87 -0
- package/dist/schemas/endpoint.schema.js.map +1 -0
- package/dist/schemas/flow.schema.d.ts +46 -0
- package/dist/schemas/flow.schema.d.ts.map +1 -0
- package/dist/schemas/flow.schema.js +73 -0
- package/dist/schemas/flow.schema.js.map +1 -0
- package/dist/schemas/http.schema.d.ts +15 -0
- package/dist/schemas/http.schema.d.ts.map +1 -0
- package/dist/schemas/http.schema.js +32 -0
- package/dist/schemas/http.schema.js.map +1 -0
- package/dist/schemas/index.d.ts +6 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +33 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/scenario.schema.d.ts +54 -0
- package/dist/schemas/scenario.schema.d.ts.map +1 -0
- package/dist/schemas/scenario.schema.js +75 -0
- package/dist/schemas/scenario.schema.js.map +1 -0
- package/dist/server/__tests__/mock-server-app.test.d.ts +2 -0
- package/dist/server/__tests__/mock-server-app.test.d.ts.map +1 -0
- package/dist/server/__tests__/mock-server-app.test.js +296 -0
- package/dist/server/__tests__/mock-server-app.test.js.map +1 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +10 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mock-server-app.d.ts +119 -0
- package/dist/server/mock-server-app.d.ts.map +1 -0
- package/dist/server/mock-server-app.js +304 -0
- package/dist/server/mock-server-app.js.map +1 -0
- package/dist/server/types.d.ts +38 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +11 -0
- package/dist/server/types.js.map +1 -0
- package/dist/state/__tests__/state-manager.test.d.ts +2 -0
- package/dist/state/__tests__/state-manager.test.d.ts.map +1 -0
- package/dist/state/__tests__/state-manager.test.js +275 -0
- package/dist/state/__tests__/state-manager.test.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +7 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/state-manager.d.ts +92 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +198 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/state/types.d.ts +30 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +2 -0
- package/dist/state/types.js.map +1 -0
- package/dist/ui/assets/index-SADMOgPE.js +10 -0
- package/dist/ui/assets/index-rj7m-XdG.css +1 -0
- package/dist/ui/index.html +29 -0
- package/dist/watcher/__tests__/config-watcher.test.d.ts +2 -0
- package/dist/watcher/__tests__/config-watcher.test.d.ts.map +1 -0
- package/dist/watcher/__tests__/config-watcher.test.js +372 -0
- package/dist/watcher/__tests__/config-watcher.test.js.map +1 -0
- package/dist/watcher/config-watcher.d.ts +100 -0
- package/dist/watcher/config-watcher.d.ts.map +1 -0
- package/dist/watcher/config-watcher.js +358 -0
- package/dist/watcher/config-watcher.js.map +1 -0
- package/dist/watcher/index.d.ts +7 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js +8 -0
- package/dist/watcher/index.js.map +1 -0
- package/dist/watcher/types.d.ts +64 -0
- package/dist/watcher/types.d.ts.map +1 -0
- package/dist/watcher/types.js +15 -0
- package/dist/watcher/types.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
# @zze/mock-server
|
|
2
|
+
|
|
3
|
+
A reusable Node.js mock server for simulating backend APIs during local microfrontend development.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Zero-config TypeScript support** - Write configs in JSON, JS, or TS
|
|
8
|
+
- 🔄 **Hot reload** - Automatic config reloading on file changes
|
|
9
|
+
- 🎭 **Scenarios** - Define multiple response scenarios per endpoint
|
|
10
|
+
- 🌊 **Flows** - Activate groups of scenarios to simulate user journeys
|
|
11
|
+
- 🎨 **Admin UI** - Visual dashboard at `/mock-admin` to control the server
|
|
12
|
+
- 🔌 **REST API** - Programmatic control via admin endpoints
|
|
13
|
+
- 📦 **Single package** - Everything bundled, no external dependencies needed
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install --save-dev @zze/mock-server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Create your config directory structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
your-project/
|
|
27
|
+
├── mock-config/
|
|
28
|
+
│ ├── endpoints/
|
|
29
|
+
│ │ └── users.json
|
|
30
|
+
│ └── flows/
|
|
31
|
+
│ └── error-flow.json
|
|
32
|
+
└── package.json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Define an endpoint
|
|
36
|
+
|
|
37
|
+
**mock-config/endpoints/users.json**
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"id": "get-users",
|
|
41
|
+
"path": "/users",
|
|
42
|
+
"method": "GET",
|
|
43
|
+
"defaultScenarioId": "success",
|
|
44
|
+
"scenarios": [
|
|
45
|
+
{
|
|
46
|
+
"id": "success",
|
|
47
|
+
"name": "Success Response",
|
|
48
|
+
"status": 200,
|
|
49
|
+
"body": [
|
|
50
|
+
{ "id": 1, "name": "Alice" },
|
|
51
|
+
{ "id": 2, "name": "Bob" }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "empty",
|
|
56
|
+
"name": "Empty List",
|
|
57
|
+
"status": 200,
|
|
58
|
+
"body": []
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "error",
|
|
62
|
+
"name": "Server Error",
|
|
63
|
+
"status": 500,
|
|
64
|
+
"body": { "error": "Internal server error" }
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Start the server
|
|
71
|
+
|
|
72
|
+
**Option A: Programmatic (recommended)**
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
// scripts/mock-server.ts
|
|
76
|
+
import { MockServer } from '@zze/mock-server';
|
|
77
|
+
|
|
78
|
+
const server = new MockServer({
|
|
79
|
+
configPath: './mock-config',
|
|
80
|
+
port: 3001,
|
|
81
|
+
apiPrefix: '/api',
|
|
82
|
+
hotReload: true
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
await server.start();
|
|
86
|
+
console.log('🎭 Mock server running at http://localhost:3001');
|
|
87
|
+
console.log('📊 Admin UI at http://localhost:3001/mock-admin');
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Run with:
|
|
91
|
+
```bash
|
|
92
|
+
npx tsx scripts/mock-server.ts
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Option B: Simple script in package.json**
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"scripts": {
|
|
100
|
+
"mock": "tsx scripts/mock-server.ts"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 4. Make requests
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Default scenario
|
|
109
|
+
curl http://localhost:3001/api/users
|
|
110
|
+
# → [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
|
|
111
|
+
|
|
112
|
+
# Open admin UI to switch scenarios
|
|
113
|
+
open http://localhost:3001/mock-admin
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Configuration
|
|
119
|
+
|
|
120
|
+
### Endpoint Config
|
|
121
|
+
|
|
122
|
+
Each endpoint file defines an API endpoint with multiple response scenarios.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
interface EndpointConfig {
|
|
126
|
+
id: string; // Unique identifier
|
|
127
|
+
path: string; // URL path (supports Express patterns)
|
|
128
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
129
|
+
defaultScenarioId: string; // ID of the default scenario
|
|
130
|
+
scenarios: ScenarioConfig[]; // Available response scenarios
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Scenario Config
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
interface ScenarioConfig {
|
|
138
|
+
id: string; // Unique within endpoint
|
|
139
|
+
name: string; // Display name in admin UI
|
|
140
|
+
status: number; // HTTP status code (100-599)
|
|
141
|
+
body?: any; // Response body (JSON or function)
|
|
142
|
+
headers?: Record<string, string>; // Custom response headers
|
|
143
|
+
delay?: number; // Response delay in ms
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Flow Config
|
|
148
|
+
|
|
149
|
+
Flows activate multiple scenarios at once to simulate complex user journeys.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface FlowConfig {
|
|
153
|
+
id: string; // Unique identifier
|
|
154
|
+
name: string; // Display name
|
|
155
|
+
description?: string; // Optional description
|
|
156
|
+
category?: string; // Optional category for grouping in UI
|
|
157
|
+
endpointScenarios: { // Map of endpointId → scenarioId
|
|
158
|
+
[endpointId: string]: string;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Example: mock-config/flows/error-flow.json**
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"id": "all-errors",
|
|
167
|
+
"name": "All Errors Flow",
|
|
168
|
+
"description": "Returns errors for all endpoints",
|
|
169
|
+
"category": "Error States",
|
|
170
|
+
"endpointScenarios": {
|
|
171
|
+
"get-users": "error",
|
|
172
|
+
"get-products": "error",
|
|
173
|
+
"create-order": "validation-error"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## TypeScript Configs
|
|
181
|
+
|
|
182
|
+
You can write configs in TypeScript for type safety and dynamic responses:
|
|
183
|
+
|
|
184
|
+
**mock-config/endpoints/users.ts**
|
|
185
|
+
```typescript
|
|
186
|
+
import type { EndpointConfig } from '@zze/mock-server';
|
|
187
|
+
|
|
188
|
+
const endpoint: EndpointConfig = {
|
|
189
|
+
id: 'get-users',
|
|
190
|
+
path: '/users',
|
|
191
|
+
method: 'GET',
|
|
192
|
+
defaultScenarioId: 'success',
|
|
193
|
+
scenarios: [
|
|
194
|
+
{
|
|
195
|
+
id: 'success',
|
|
196
|
+
name: 'Success',
|
|
197
|
+
status: 200,
|
|
198
|
+
body: (req) => {
|
|
199
|
+
// Dynamic response based on request
|
|
200
|
+
const limit = parseInt(req.query.limit as string) || 10;
|
|
201
|
+
return Array.from({ length: limit }, (_, i) => ({
|
|
202
|
+
id: i + 1,
|
|
203
|
+
name: `User ${i + 1}`,
|
|
204
|
+
timestamp: new Date().toISOString()
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export default endpoint;
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Admin UI
|
|
217
|
+
|
|
218
|
+
The built-in admin UI is available at `/mock-admin` and provides:
|
|
219
|
+
|
|
220
|
+
- **Endpoints Panel**: View all endpoints, expand to see scenarios, click to activate
|
|
221
|
+
- Create new endpoints with the JSON editor
|
|
222
|
+
- Edit existing endpoint configurations
|
|
223
|
+
- Delete endpoints with confirmation
|
|
224
|
+
- **Flows Panel**: View and activate user flows with category grouping
|
|
225
|
+
- Create new flows with the endpoint/scenario picker
|
|
226
|
+
- Edit or duplicate existing flows
|
|
227
|
+
- Delete flows with confirmation
|
|
228
|
+
- Collapsible category groups for organization
|
|
229
|
+
- Search/filter flows by name
|
|
230
|
+
- **State Panel**: See current active flow and scenario count
|
|
231
|
+
- **Controls**: Refresh data, reset to defaults
|
|
232
|
+
|
|
233
|
+

|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Admin REST API
|
|
238
|
+
|
|
239
|
+
Control the mock server programmatically:
|
|
240
|
+
|
|
241
|
+
### State & Config
|
|
242
|
+
|
|
243
|
+
| Method | Endpoint | Description |
|
|
244
|
+
|--------|----------|-------------|
|
|
245
|
+
| GET | `/mock-admin/api/config` | Get all endpoints and flows |
|
|
246
|
+
| GET | `/mock-admin/api/state` | Get current active state |
|
|
247
|
+
| POST | `/mock-admin/api/scenarios/activate` | Activate a scenario |
|
|
248
|
+
| POST | `/mock-admin/api/flows/activate` | Activate/deactivate a flow |
|
|
249
|
+
| POST | `/mock-admin/api/reset` | Reset to default state |
|
|
250
|
+
|
|
251
|
+
### Endpoint CRUD
|
|
252
|
+
|
|
253
|
+
| Method | Endpoint | Description |
|
|
254
|
+
|--------|----------|-------------|
|
|
255
|
+
| POST | `/mock-admin/api/endpoints` | Create a new endpoint |
|
|
256
|
+
| PUT | `/mock-admin/api/endpoints/:id` | Update an existing endpoint |
|
|
257
|
+
| DELETE | `/mock-admin/api/endpoints/:id` | Delete an endpoint |
|
|
258
|
+
|
|
259
|
+
### Flow CRUD
|
|
260
|
+
|
|
261
|
+
| Method | Endpoint | Description |
|
|
262
|
+
|--------|----------|-------------|
|
|
263
|
+
| POST | `/mock-admin/api/flows` | Create a new flow |
|
|
264
|
+
| PUT | `/mock-admin/api/flows/:id` | Update an existing flow |
|
|
265
|
+
| DELETE | `/mock-admin/api/flows/:id` | Delete a flow |
|
|
266
|
+
| POST | `/mock-admin/api/flows/:id/duplicate` | Duplicate an existing flow |
|
|
267
|
+
|
|
268
|
+
### Examples
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Get current config
|
|
272
|
+
curl http://localhost:3001/mock-admin/api/config
|
|
273
|
+
|
|
274
|
+
# Activate a scenario
|
|
275
|
+
curl -X POST http://localhost:3001/mock-admin/api/scenarios/activate \
|
|
276
|
+
-H "Content-Type: application/json" \
|
|
277
|
+
-d '{"endpointId": "get-users", "scenarioId": "error"}'
|
|
278
|
+
|
|
279
|
+
# Activate a flow
|
|
280
|
+
curl -X POST http://localhost:3001/mock-admin/api/flows/activate \
|
|
281
|
+
-H "Content-Type: application/json" \
|
|
282
|
+
-d '{"flowId": "all-errors"}'
|
|
283
|
+
|
|
284
|
+
# Deactivate flow
|
|
285
|
+
curl -X POST http://localhost:3001/mock-admin/api/flows/activate \
|
|
286
|
+
-H "Content-Type: application/json" \
|
|
287
|
+
-d '{"flowId": null}'
|
|
288
|
+
|
|
289
|
+
# Reset to defaults
|
|
290
|
+
curl -X POST http://localhost:3001/mock-admin/api/reset
|
|
291
|
+
|
|
292
|
+
# Create a new endpoint
|
|
293
|
+
curl -X POST http://localhost:3001/mock-admin/api/endpoints \
|
|
294
|
+
-H "Content-Type: application/json" \
|
|
295
|
+
-d '{"endpoint": {"id": "new-endpoint", "method": "GET", "path": "/api/test", "scenarios": [{"id": "default", "name": "Default", "response": {"status": 200, "body": {}}}]}}'
|
|
296
|
+
|
|
297
|
+
# Update an endpoint
|
|
298
|
+
curl -X PUT http://localhost:3001/mock-admin/api/endpoints/new-endpoint \
|
|
299
|
+
-H "Content-Type: application/json" \
|
|
300
|
+
-d '{"endpoint": {"id": "new-endpoint", "method": "GET", "path": "/api/test-updated", "scenarios": [{"id": "default", "name": "Default", "response": {"status": 200, "body": {"updated": true}}}]}}'
|
|
301
|
+
|
|
302
|
+
# Delete an endpoint
|
|
303
|
+
curl -X DELETE http://localhost:3001/mock-admin/api/endpoints/new-endpoint
|
|
304
|
+
|
|
305
|
+
# Create a new flow
|
|
306
|
+
curl -X POST http://localhost:3001/mock-admin/api/flows \
|
|
307
|
+
-H "Content-Type: application/json" \
|
|
308
|
+
-d '{"flow": {"id": "my-flow", "name": "My Flow", "category": "Testing", "endpointScenarios": {"get-users": "error"}}}'
|
|
309
|
+
|
|
310
|
+
# Update a flow
|
|
311
|
+
curl -X PUT http://localhost:3001/mock-admin/api/flows/my-flow \
|
|
312
|
+
-H "Content-Type: application/json" \
|
|
313
|
+
-d '{"flow": {"id": "my-flow", "name": "My Updated Flow", "category": "Testing", "endpointScenarios": {"get-users": "success"}}}'
|
|
314
|
+
|
|
315
|
+
# Duplicate a flow
|
|
316
|
+
curl -X POST http://localhost:3001/mock-admin/api/flows/my-flow/duplicate \
|
|
317
|
+
-H "Content-Type: application/json" \
|
|
318
|
+
-d '{"newId": "my-flow-copy"}'
|
|
319
|
+
|
|
320
|
+
# Delete a flow
|
|
321
|
+
curl -X DELETE http://localhost:3001/mock-admin/api/flows/my-flow
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Programmatic API
|
|
327
|
+
|
|
328
|
+
### MockServer Class
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { MockServer } from '@zze/mock-server';
|
|
332
|
+
|
|
333
|
+
const server = new MockServer({
|
|
334
|
+
configPath: './mock-config', // Required
|
|
335
|
+
port: 3001, // Default: 3001
|
|
336
|
+
apiPrefix: '/api', // Default: '/api'
|
|
337
|
+
hotReload: true // Default: true
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Lifecycle Methods
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// Start the server
|
|
345
|
+
await server.start();
|
|
346
|
+
|
|
347
|
+
// Stop the server
|
|
348
|
+
await server.stop();
|
|
349
|
+
|
|
350
|
+
// Restart (stop + start)
|
|
351
|
+
await server.restart();
|
|
352
|
+
|
|
353
|
+
// Manually reload config
|
|
354
|
+
await server.reload();
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### State & Info
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
// Get server state
|
|
361
|
+
const state = server.getState();
|
|
362
|
+
// {
|
|
363
|
+
// running: true,
|
|
364
|
+
// port: 3001,
|
|
365
|
+
// endpointCount: 5,
|
|
366
|
+
// flowCount: 2,
|
|
367
|
+
// hotReloadActive: true,
|
|
368
|
+
// activeFlowId: null,
|
|
369
|
+
// activeScenarios: { 'get-users': 'error' }
|
|
370
|
+
// }
|
|
371
|
+
|
|
372
|
+
// Get loaded endpoints
|
|
373
|
+
const endpoints = server.getEndpoints();
|
|
374
|
+
|
|
375
|
+
// Get loaded flows
|
|
376
|
+
const flows = server.getFlows();
|
|
377
|
+
|
|
378
|
+
// Get config path
|
|
379
|
+
const configPath = server.getConfigPath();
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Control Methods
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// Activate a specific scenario
|
|
386
|
+
server.activateScenario('get-users', 'error');
|
|
387
|
+
|
|
388
|
+
// Activate a flow
|
|
389
|
+
server.activateFlow('all-errors');
|
|
390
|
+
|
|
391
|
+
// Deactivate flow
|
|
392
|
+
server.activateFlow(null);
|
|
393
|
+
|
|
394
|
+
// Reset to defaults
|
|
395
|
+
server.reset();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Event Handlers
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// Listen for config reloads
|
|
402
|
+
const unsubscribe = server.onReload((event) => {
|
|
403
|
+
console.log('Config reloaded:', event.changedFiles);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Listen for errors
|
|
407
|
+
server.onError((error) => {
|
|
408
|
+
console.error('Server error:', error);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Unsubscribe when done
|
|
412
|
+
unsubscribe();
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Advanced: Access Express App
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
// Get the Express app instance (for custom middleware)
|
|
419
|
+
const app = server.getApp();
|
|
420
|
+
if (app) {
|
|
421
|
+
app.use('/custom', customMiddleware);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Get the HTTP server (for WebSocket, etc.)
|
|
425
|
+
const httpServer = server.getHttpServer();
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Path Parameters & Patterns
|
|
431
|
+
|
|
432
|
+
Endpoints support Express-style path patterns:
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{
|
|
436
|
+
"id": "get-user-by-id",
|
|
437
|
+
"path": "/users/:id",
|
|
438
|
+
"method": "GET",
|
|
439
|
+
"defaultScenarioId": "success",
|
|
440
|
+
"scenarios": [
|
|
441
|
+
{
|
|
442
|
+
"id": "success",
|
|
443
|
+
"name": "User Found",
|
|
444
|
+
"status": 200,
|
|
445
|
+
"body": { "id": 1, "name": "Alice" }
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"id": "not-found",
|
|
449
|
+
"name": "Not Found",
|
|
450
|
+
"status": 404,
|
|
451
|
+
"body": { "error": "User not found" }
|
|
452
|
+
}
|
|
453
|
+
]
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Dynamic response using path params (TypeScript):
|
|
458
|
+
```typescript
|
|
459
|
+
{
|
|
460
|
+
id: 'success',
|
|
461
|
+
name: 'User Found',
|
|
462
|
+
status: 200,
|
|
463
|
+
body: (req) => ({
|
|
464
|
+
id: parseInt(req.params.id),
|
|
465
|
+
name: `User ${req.params.id}`
|
|
466
|
+
})
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Response Delays
|
|
473
|
+
|
|
474
|
+
Simulate network latency:
|
|
475
|
+
|
|
476
|
+
```json
|
|
477
|
+
{
|
|
478
|
+
"id": "slow-response",
|
|
479
|
+
"name": "Slow Response",
|
|
480
|
+
"status": 200,
|
|
481
|
+
"body": { "data": "loaded" },
|
|
482
|
+
"delay": 2000
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Custom Headers
|
|
489
|
+
|
|
490
|
+
Add custom response headers:
|
|
491
|
+
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"id": "with-headers",
|
|
495
|
+
"name": "With Custom Headers",
|
|
496
|
+
"status": 200,
|
|
497
|
+
"headers": {
|
|
498
|
+
"X-Custom-Header": "custom-value",
|
|
499
|
+
"Cache-Control": "no-cache"
|
|
500
|
+
},
|
|
501
|
+
"body": { "data": "ok" }
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Hot Reload
|
|
508
|
+
|
|
509
|
+
When `hotReload: true` (default), the server watches your config directory and automatically reloads when files change:
|
|
510
|
+
|
|
511
|
+
- Add/remove endpoint files
|
|
512
|
+
- Modify scenarios
|
|
513
|
+
- Add/remove flows
|
|
514
|
+
|
|
515
|
+
Changes take effect immediately without restarting the server. A 300ms debounce prevents rapid reloads during saves.
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Integration with Tests
|
|
520
|
+
|
|
521
|
+
Use the mock server in your test setup:
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
// test/setup.ts
|
|
525
|
+
import { MockServer } from '@zze/mock-server';
|
|
526
|
+
|
|
527
|
+
let server: MockServer;
|
|
528
|
+
|
|
529
|
+
beforeAll(async () => {
|
|
530
|
+
server = new MockServer({
|
|
531
|
+
configPath: './test/mock-config',
|
|
532
|
+
port: 3099,
|
|
533
|
+
hotReload: false
|
|
534
|
+
});
|
|
535
|
+
await server.start();
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
afterAll(async () => {
|
|
539
|
+
await server.stop();
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
beforeEach(() => {
|
|
543
|
+
server.reset();
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// In tests
|
|
547
|
+
it('handles error response', async () => {
|
|
548
|
+
server.activateScenario('get-users', 'error');
|
|
549
|
+
|
|
550
|
+
const response = await fetch('http://localhost:3099/api/users');
|
|
551
|
+
expect(response.status).toBe(500);
|
|
552
|
+
});
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Troubleshooting
|
|
558
|
+
|
|
559
|
+
### Port already in use
|
|
560
|
+
|
|
561
|
+
```
|
|
562
|
+
Error: listen EADDRINUSE: address already in use :::3001
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Change the port or kill the existing process:
|
|
566
|
+
```bash
|
|
567
|
+
lsof -i :3001 | grep LISTEN | awk '{print $2}' | xargs kill
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Config not loading
|
|
571
|
+
|
|
572
|
+
- Ensure `configPath` points to a directory with `endpoints/` and `flows/` subdirectories
|
|
573
|
+
- Check file extensions: `.json`, `.js`, or `.ts`
|
|
574
|
+
- Validate JSON syntax
|
|
575
|
+
- Check for required fields: `id`, `path`, `method`, `defaultScenarioId`, `scenarios`
|
|
576
|
+
|
|
577
|
+
### TypeScript configs not working
|
|
578
|
+
|
|
579
|
+
Ensure you have `typescript` installed. The package uses `jiti` for zero-config TS loading.
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## API Reference
|
|
584
|
+
|
|
585
|
+
### Types
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
// Main options
|
|
589
|
+
interface MockServerOptions {
|
|
590
|
+
configPath: string;
|
|
591
|
+
port?: number;
|
|
592
|
+
apiPrefix?: string;
|
|
593
|
+
hotReload?: boolean;
|
|
594
|
+
watcherOptions?: WatcherOptions;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Server state
|
|
598
|
+
interface MockServerState {
|
|
599
|
+
running: boolean;
|
|
600
|
+
port: number | null;
|
|
601
|
+
endpointCount: number;
|
|
602
|
+
flowCount: number;
|
|
603
|
+
hotReloadActive: boolean;
|
|
604
|
+
activeFlowId: string | null;
|
|
605
|
+
activeScenarios: Record<string, string | null>;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Reload event
|
|
609
|
+
interface ReloadEvent {
|
|
610
|
+
changedFiles: WatcherEvent[];
|
|
611
|
+
timestamp: Date;
|
|
612
|
+
}
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Exports
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
// Main class
|
|
619
|
+
export { MockServer, createMockServer };
|
|
620
|
+
|
|
621
|
+
// Types
|
|
622
|
+
export type {
|
|
623
|
+
MockServerOptions,
|
|
624
|
+
MockServerState,
|
|
625
|
+
EndpointConfig,
|
|
626
|
+
ScenarioConfig,
|
|
627
|
+
FlowConfig,
|
|
628
|
+
HttpMethod,
|
|
629
|
+
ResponseBody,
|
|
630
|
+
ServerOptions,
|
|
631
|
+
ReloadEvent,
|
|
632
|
+
WatcherOptions
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
// Constants
|
|
636
|
+
export { ADMIN_UI_PATH }; // '/mock-admin'
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## License
|
|
642
|
+
|
|
643
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mock-server.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|