@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.
Files changed (177) hide show
  1. package/README.md +643 -0
  2. package/dist/__tests__/mock-server.test.d.ts +5 -0
  3. package/dist/__tests__/mock-server.test.d.ts.map +1 -0
  4. package/dist/__tests__/mock-server.test.js +599 -0
  5. package/dist/__tests__/mock-server.test.js.map +1 -0
  6. package/dist/admin/__tests__/admin-router.test.d.ts +2 -0
  7. package/dist/admin/__tests__/admin-router.test.d.ts.map +1 -0
  8. package/dist/admin/__tests__/admin-router.test.js +621 -0
  9. package/dist/admin/__tests__/admin-router.test.js.map +1 -0
  10. package/dist/admin/admin-router.d.ts +27 -0
  11. package/dist/admin/admin-router.d.ts.map +1 -0
  12. package/dist/admin/admin-router.js +616 -0
  13. package/dist/admin/admin-router.js.map +1 -0
  14. package/dist/admin/index.d.ts +4 -0
  15. package/dist/admin/index.d.ts.map +1 -0
  16. package/dist/admin/index.js +10 -0
  17. package/dist/admin/index.js.map +1 -0
  18. package/dist/admin/types.d.ts +185 -0
  19. package/dist/admin/types.d.ts.map +1 -0
  20. package/dist/admin/types.js +33 -0
  21. package/dist/admin/types.js.map +1 -0
  22. package/dist/config/__tests__/config-discovery.test.d.ts +2 -0
  23. package/dist/config/__tests__/config-discovery.test.d.ts.map +1 -0
  24. package/dist/config/__tests__/config-discovery.test.js +52 -0
  25. package/dist/config/__tests__/config-discovery.test.js.map +1 -0
  26. package/dist/config/__tests__/config-loader.test.d.ts +2 -0
  27. package/dist/config/__tests__/config-loader.test.d.ts.map +1 -0
  28. package/dist/config/__tests__/config-loader.test.js +124 -0
  29. package/dist/config/__tests__/config-loader.test.js.map +1 -0
  30. package/dist/config/__tests__/file-loader.test.d.ts +2 -0
  31. package/dist/config/__tests__/file-loader.test.d.ts.map +1 -0
  32. package/dist/config/__tests__/file-loader.test.js +63 -0
  33. package/dist/config/__tests__/file-loader.test.js.map +1 -0
  34. package/dist/config/__tests__/fixtures/mock-config/endpoints/products.d.ts +25 -0
  35. package/dist/config/__tests__/fixtures/mock-config/endpoints/products.d.ts.map +1 -0
  36. package/dist/config/__tests__/fixtures/mock-config/endpoints/products.js +25 -0
  37. package/dist/config/__tests__/fixtures/mock-config/endpoints/products.js.map +1 -0
  38. package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.d.ts +11 -0
  39. package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.d.ts.map +1 -0
  40. package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.js +11 -0
  41. package/dist/config/__tests__/fixtures/mock-config/flows/error-flow.js.map +1 -0
  42. package/dist/config/config-discovery.d.ts +23 -0
  43. package/dist/config/config-discovery.d.ts.map +1 -0
  44. package/dist/config/config-discovery.js +60 -0
  45. package/dist/config/config-discovery.js.map +1 -0
  46. package/dist/config/config-loader.d.ts +56 -0
  47. package/dist/config/config-loader.d.ts.map +1 -0
  48. package/dist/config/config-loader.js +162 -0
  49. package/dist/config/config-loader.js.map +1 -0
  50. package/dist/config/config-writer.d.ts +96 -0
  51. package/dist/config/config-writer.d.ts.map +1 -0
  52. package/dist/config/config-writer.js +248 -0
  53. package/dist/config/config-writer.js.map +1 -0
  54. package/dist/config/file-loader.d.ts +16 -0
  55. package/dist/config/file-loader.d.ts.map +1 -0
  56. package/dist/config/file-loader.js +90 -0
  57. package/dist/config/file-loader.js.map +1 -0
  58. package/dist/config/index.d.ts +7 -0
  59. package/dist/config/index.d.ts.map +1 -0
  60. package/dist/config/index.js +23 -0
  61. package/dist/config/index.js.map +1 -0
  62. package/dist/config/types.d.ts +47 -0
  63. package/dist/config/types.d.ts.map +1 -0
  64. package/dist/config/types.js +7 -0
  65. package/dist/config/types.js.map +1 -0
  66. package/dist/index.d.ts +28 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +31 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/mock-server.d.ts +243 -0
  71. package/dist/mock-server.d.ts.map +1 -0
  72. package/dist/mock-server.js +387 -0
  73. package/dist/mock-server.js.map +1 -0
  74. package/dist/resolver/__tests__/response-resolver.test.d.ts +2 -0
  75. package/dist/resolver/__tests__/response-resolver.test.d.ts.map +1 -0
  76. package/dist/resolver/__tests__/response-resolver.test.js +358 -0
  77. package/dist/resolver/__tests__/response-resolver.test.js.map +1 -0
  78. package/dist/resolver/index.d.ts +4 -0
  79. package/dist/resolver/index.d.ts.map +1 -0
  80. package/dist/resolver/index.js +9 -0
  81. package/dist/resolver/index.js.map +1 -0
  82. package/dist/resolver/response-resolver.d.ts +73 -0
  83. package/dist/resolver/response-resolver.d.ts.map +1 -0
  84. package/dist/resolver/response-resolver.js +167 -0
  85. package/dist/resolver/response-resolver.js.map +1 -0
  86. package/dist/resolver/types.d.ts +47 -0
  87. package/dist/resolver/types.d.ts.map +1 -0
  88. package/dist/resolver/types.js +9 -0
  89. package/dist/resolver/types.js.map +1 -0
  90. package/dist/schemas/__tests__/config.validator.test.d.ts +2 -0
  91. package/dist/schemas/__tests__/config.validator.test.d.ts.map +1 -0
  92. package/dist/schemas/__tests__/config.validator.test.js +66 -0
  93. package/dist/schemas/__tests__/config.validator.test.js.map +1 -0
  94. package/dist/schemas/__tests__/endpoint.schema.test.d.ts +2 -0
  95. package/dist/schemas/__tests__/endpoint.schema.test.d.ts.map +1 -0
  96. package/dist/schemas/__tests__/endpoint.schema.test.js +103 -0
  97. package/dist/schemas/__tests__/endpoint.schema.test.js.map +1 -0
  98. package/dist/schemas/__tests__/flow.schema.test.d.ts +2 -0
  99. package/dist/schemas/__tests__/flow.schema.test.d.ts.map +1 -0
  100. package/dist/schemas/__tests__/flow.schema.test.js +92 -0
  101. package/dist/schemas/__tests__/flow.schema.test.js.map +1 -0
  102. package/dist/schemas/config.validator.d.ts +39 -0
  103. package/dist/schemas/config.validator.d.ts.map +1 -0
  104. package/dist/schemas/config.validator.js +117 -0
  105. package/dist/schemas/config.validator.js.map +1 -0
  106. package/dist/schemas/endpoint.schema.d.ts +108 -0
  107. package/dist/schemas/endpoint.schema.d.ts.map +1 -0
  108. package/dist/schemas/endpoint.schema.js +87 -0
  109. package/dist/schemas/endpoint.schema.js.map +1 -0
  110. package/dist/schemas/flow.schema.d.ts +46 -0
  111. package/dist/schemas/flow.schema.d.ts.map +1 -0
  112. package/dist/schemas/flow.schema.js +73 -0
  113. package/dist/schemas/flow.schema.js.map +1 -0
  114. package/dist/schemas/http.schema.d.ts +15 -0
  115. package/dist/schemas/http.schema.d.ts.map +1 -0
  116. package/dist/schemas/http.schema.js +32 -0
  117. package/dist/schemas/http.schema.js.map +1 -0
  118. package/dist/schemas/index.d.ts +6 -0
  119. package/dist/schemas/index.d.ts.map +1 -0
  120. package/dist/schemas/index.js +33 -0
  121. package/dist/schemas/index.js.map +1 -0
  122. package/dist/schemas/scenario.schema.d.ts +54 -0
  123. package/dist/schemas/scenario.schema.d.ts.map +1 -0
  124. package/dist/schemas/scenario.schema.js +75 -0
  125. package/dist/schemas/scenario.schema.js.map +1 -0
  126. package/dist/server/__tests__/mock-server-app.test.d.ts +2 -0
  127. package/dist/server/__tests__/mock-server-app.test.d.ts.map +1 -0
  128. package/dist/server/__tests__/mock-server-app.test.js +296 -0
  129. package/dist/server/__tests__/mock-server-app.test.js.map +1 -0
  130. package/dist/server/index.d.ts +4 -0
  131. package/dist/server/index.d.ts.map +1 -0
  132. package/dist/server/index.js +10 -0
  133. package/dist/server/index.js.map +1 -0
  134. package/dist/server/mock-server-app.d.ts +119 -0
  135. package/dist/server/mock-server-app.d.ts.map +1 -0
  136. package/dist/server/mock-server-app.js +304 -0
  137. package/dist/server/mock-server-app.js.map +1 -0
  138. package/dist/server/types.d.ts +38 -0
  139. package/dist/server/types.d.ts.map +1 -0
  140. package/dist/server/types.js +11 -0
  141. package/dist/server/types.js.map +1 -0
  142. package/dist/state/__tests__/state-manager.test.d.ts +2 -0
  143. package/dist/state/__tests__/state-manager.test.d.ts.map +1 -0
  144. package/dist/state/__tests__/state-manager.test.js +275 -0
  145. package/dist/state/__tests__/state-manager.test.js.map +1 -0
  146. package/dist/state/index.d.ts +3 -0
  147. package/dist/state/index.d.ts.map +1 -0
  148. package/dist/state/index.js +7 -0
  149. package/dist/state/index.js.map +1 -0
  150. package/dist/state/state-manager.d.ts +92 -0
  151. package/dist/state/state-manager.d.ts.map +1 -0
  152. package/dist/state/state-manager.js +198 -0
  153. package/dist/state/state-manager.js.map +1 -0
  154. package/dist/state/types.d.ts +30 -0
  155. package/dist/state/types.d.ts.map +1 -0
  156. package/dist/state/types.js +2 -0
  157. package/dist/state/types.js.map +1 -0
  158. package/dist/ui/assets/index-SADMOgPE.js +10 -0
  159. package/dist/ui/assets/index-rj7m-XdG.css +1 -0
  160. package/dist/ui/index.html +29 -0
  161. package/dist/watcher/__tests__/config-watcher.test.d.ts +2 -0
  162. package/dist/watcher/__tests__/config-watcher.test.d.ts.map +1 -0
  163. package/dist/watcher/__tests__/config-watcher.test.js +372 -0
  164. package/dist/watcher/__tests__/config-watcher.test.js.map +1 -0
  165. package/dist/watcher/config-watcher.d.ts +100 -0
  166. package/dist/watcher/config-watcher.d.ts.map +1 -0
  167. package/dist/watcher/config-watcher.js +358 -0
  168. package/dist/watcher/config-watcher.js.map +1 -0
  169. package/dist/watcher/index.d.ts +7 -0
  170. package/dist/watcher/index.d.ts.map +1 -0
  171. package/dist/watcher/index.js +8 -0
  172. package/dist/watcher/index.js.map +1 -0
  173. package/dist/watcher/types.d.ts +64 -0
  174. package/dist/watcher/types.d.ts.map +1 -0
  175. package/dist/watcher/types.js +15 -0
  176. package/dist/watcher/types.js.map +1 -0
  177. 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
+ ![Admin UI Screenshot](./docs/admin-ui.png)
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,5 @@
1
+ /**
2
+ * Tests for MockServer - the public API
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=mock-server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mock-server.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}