@schmock/core 2.2.3 → 2.3.1
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 +35 -0
- package/dist/abort.d.ts +3 -0
- package/dist/abort.d.ts.map +1 -0
- package/dist/abort.js +30 -0
- package/dist/binary.d.ts +8 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +9 -0
- package/dist/builder.d.ts +31 -10
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +804 -203
- package/dist/constants.d.ts +38 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +123 -2
- package/dist/errors.d.ts +14 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +41 -6
- package/dist/helpers.d.ts +9 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +18 -2
- package/dist/http-helpers.d.ts +52 -5
- package/dist/http-helpers.d.ts.map +1 -1
- package/dist/http-helpers.js +153 -37
- package/dist/index.d.ts +381 -60
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/interceptor.d.ts +11 -1
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/interceptor.js +354 -156
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +12 -3
- package/dist/plugin-pipeline.d.ts +11 -4
- package/dist/plugin-pipeline.d.ts.map +1 -1
- package/dist/plugin-pipeline.js +117 -39
- package/dist/response-normalizer.d.ts +16 -0
- package/dist/response-normalizer.d.ts.map +1 -0
- package/dist/response-normalizer.js +316 -0
- package/dist/response-parser.d.ts.map +1 -1
- package/dist/response-parser.js +85 -18
- package/dist/route-matcher.d.ts +3 -0
- package/dist/route-matcher.d.ts.map +1 -1
- package/dist/route-matcher.js +12 -6
- package/dist/types.d.ts +7 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +18 -8
- package/src/audit-core-builder.test.ts +0 -218
- package/src/audit-response-guard.test.ts +0 -38
- package/src/builder.test.ts +0 -289
- package/src/builder.ts +0 -701
- package/src/constants.test.ts +0 -99
- package/src/constants.ts +0 -73
- package/src/debug.test.ts +0 -241
- package/src/delay.test.ts +0 -319
- package/src/dist-shape.test.ts +0 -35
- package/src/errors.test.ts +0 -223
- package/src/errors.ts +0 -130
- package/src/factory.test.ts +0 -133
- package/src/helpers.test.ts +0 -147
- package/src/helpers.ts +0 -58
- package/src/http-helpers.ts +0 -113
- package/src/index.ts +0 -151
- package/src/interceptor.test.ts +0 -291
- package/src/interceptor.ts +0 -320
- package/src/namespace.test.ts +0 -274
- package/src/parser.property.test.ts +0 -594
- package/src/parser.test.ts +0 -148
- package/src/parser.ts +0 -64
- package/src/plugin-pipeline.ts +0 -103
- package/src/plugin-system.test.ts +0 -602
- package/src/response-parser.ts +0 -75
- package/src/response-parsing.test.ts +0 -333
- package/src/route-matcher.ts +0 -69
- package/src/route-matching.test.ts +0 -394
- package/src/server.test.ts +0 -165
- package/src/smart-defaults.test.ts +0 -361
- package/src/steps/async-support.steps.ts +0 -400
- package/src/steps/audit-core-builder.steps.ts +0 -188
- package/src/steps/audit-onerror-tuple.steps.ts +0 -99
- package/src/steps/basic-usage.steps.ts +0 -245
- package/src/steps/developer-experience.steps.ts +0 -204
- package/src/steps/error-handling.steps.ts +0 -345
- package/src/steps/fluent-api.steps.ts +0 -255
- package/src/steps/http-methods.steps.ts +0 -331
- package/src/steps/interceptor.steps.ts +0 -260
- package/src/steps/lifecycle-events.steps.ts +0 -142
- package/src/steps/performance-reliability.steps.ts +0 -423
- package/src/steps/plugin-integration.steps.ts +0 -280
- package/src/steps/request-history.steps.ts +0 -276
- package/src/steps/response-delay.steps.ts +0 -88
- package/src/steps/route-key-format.steps.ts +0 -99
- package/src/steps/standalone-server.steps.ts +0 -233
- package/src/steps/state-concurrency.steps.ts +0 -739
- package/src/steps/stateful-workflows.steps.ts +0 -353
- package/src/types.ts +0 -36
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,84 @@ declare global {
|
|
|
7
7
|
|
|
8
8
|
namespace Schmock {
|
|
9
9
|
type JSONSchema7 = import("json-schema").JSONSchema7;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A `Schema` or the boolean shorthand, wherever draft-07 allows a subschema.
|
|
13
|
+
*/
|
|
14
|
+
type SchemaDefinition = Schema | boolean;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* JSON Schema draft-07 plus the keywords Schmock's own tooling understands,
|
|
18
|
+
* applied recursively so nested subschemas accept them too.
|
|
19
|
+
*
|
|
20
|
+
* `JSONSchema7` rejects these keywords in an object literal, which is why
|
|
21
|
+
* schemas carrying them otherwise need a cast at every level that uses one.
|
|
22
|
+
* A `Schema` is assignable to `JSONSchema7`, so it can be handed to
|
|
23
|
+
* `fakerPlugin`, `validationPlugin` or any other schema-typed option.
|
|
24
|
+
*
|
|
25
|
+
* Only `@schmock/*` packages know these keywords. `@schmock/validation`
|
|
26
|
+
* registers them on its own Ajv instance; a strict Ajv of your own throws
|
|
27
|
+
* `strict mode: unknown keyword` until you do the same.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const schema: Schmock.Schema = {
|
|
32
|
+
* type: 'object',
|
|
33
|
+
* properties: {
|
|
34
|
+
* name: { type: 'string', faker: 'person.fullName' },
|
|
35
|
+
* nickname: { type: ['string', 'null'], schmockNullable: true },
|
|
36
|
+
* active: { type: 'boolean', schmockTrueProbability: 0.8 },
|
|
37
|
+
* },
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
interface Schema
|
|
42
|
+
extends Omit<
|
|
43
|
+
JSONSchema7,
|
|
44
|
+
| "properties"
|
|
45
|
+
| "patternProperties"
|
|
46
|
+
| "additionalProperties"
|
|
47
|
+
| "items"
|
|
48
|
+
| "additionalItems"
|
|
49
|
+
| "contains"
|
|
50
|
+
| "propertyNames"
|
|
51
|
+
| "allOf"
|
|
52
|
+
| "anyOf"
|
|
53
|
+
| "oneOf"
|
|
54
|
+
| "not"
|
|
55
|
+
| "if"
|
|
56
|
+
| "then"
|
|
57
|
+
| "else"
|
|
58
|
+
| "$defs"
|
|
59
|
+
| "definitions"
|
|
60
|
+
| "dependencies"
|
|
61
|
+
> {
|
|
62
|
+
/** json-schema-faker method path, e.g. `"person.fullName"`. */
|
|
63
|
+
faker?: string | Record<string, unknown>;
|
|
64
|
+
/** Marks a null-permitting field: ~5% of generated values are `null`. */
|
|
65
|
+
schmockNullable?: boolean;
|
|
66
|
+
/** Probability (0–1) that a generated boolean is `true`. */
|
|
67
|
+
schmockTrueProbability?: number;
|
|
68
|
+
|
|
69
|
+
properties?: Record<string, SchemaDefinition>;
|
|
70
|
+
patternProperties?: Record<string, SchemaDefinition>;
|
|
71
|
+
additionalProperties?: SchemaDefinition;
|
|
72
|
+
items?: SchemaDefinition | SchemaDefinition[];
|
|
73
|
+
additionalItems?: SchemaDefinition;
|
|
74
|
+
contains?: SchemaDefinition;
|
|
75
|
+
propertyNames?: SchemaDefinition;
|
|
76
|
+
allOf?: SchemaDefinition[];
|
|
77
|
+
anyOf?: SchemaDefinition[];
|
|
78
|
+
oneOf?: SchemaDefinition[];
|
|
79
|
+
not?: SchemaDefinition;
|
|
80
|
+
if?: SchemaDefinition;
|
|
81
|
+
then?: SchemaDefinition;
|
|
82
|
+
else?: SchemaDefinition;
|
|
83
|
+
$defs?: Record<string, SchemaDefinition>;
|
|
84
|
+
definitions?: Record<string, SchemaDefinition>;
|
|
85
|
+
dependencies?: Record<string, SchemaDefinition | string[]>;
|
|
86
|
+
}
|
|
87
|
+
|
|
10
88
|
/**
|
|
11
89
|
* HTTP methods supported by Schmock
|
|
12
90
|
*/
|
|
@@ -22,13 +100,18 @@ namespace Schmock {
|
|
|
22
100
|
/**
|
|
23
101
|
* Route key format: 'METHOD /path'
|
|
24
102
|
*
|
|
103
|
+
* The path must start with '/': transports always deliver a leading-slash
|
|
104
|
+
* pathname, so a slash-less key would register a route no request can reach.
|
|
105
|
+
* `parseRouteKey` rejects it at runtime; the template type surfaces the same
|
|
106
|
+
* mistake at compile time.
|
|
107
|
+
*
|
|
25
108
|
* @example
|
|
26
109
|
* 'GET /users'
|
|
27
110
|
* 'POST /users/:id'
|
|
28
111
|
* 'DELETE /api/posts/:postId/comments/:commentId'
|
|
29
112
|
*/
|
|
30
|
-
type RouteKey = `${HttpMethod}
|
|
31
|
-
|
|
113
|
+
type RouteKey = `${HttpMethod} /${string}`;
|
|
114
|
+
|
|
32
115
|
/**
|
|
33
116
|
* Plugin interface for extending Schmock functionality
|
|
34
117
|
*/
|
|
@@ -40,11 +123,28 @@ namespace Schmock {
|
|
|
40
123
|
|
|
41
124
|
/**
|
|
42
125
|
* Called once when the plugin is added via .pipe()
|
|
43
|
-
*
|
|
44
|
-
*
|
|
126
|
+
* Route registrations are committed atomically only when this hook returns
|
|
127
|
+
* synchronously. The scoped instance must not be retained or used later.
|
|
128
|
+
* Returning a Promise is unsupported and leaves the plugin inactive.
|
|
129
|
+
* @param instance - A synchronous, installation-scoped callable instance
|
|
45
130
|
*/
|
|
46
131
|
install?(instance: CallableMockInstance): void;
|
|
47
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Called during reset after every request admitted with this plugin settles.
|
|
135
|
+
* Cleanup runs in reverse registration order and must complete synchronously.
|
|
136
|
+
*/
|
|
137
|
+
uninstall?(instance: CallableMockInstance): void;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Inspect or transform a request before its route generator executes.
|
|
141
|
+
* Returning a response short-circuits the generator, while returning only
|
|
142
|
+
* a context allows request changes to flow into the generator.
|
|
143
|
+
*/
|
|
144
|
+
beforeRequest?(
|
|
145
|
+
context: PluginContext,
|
|
146
|
+
): PluginResult | void | Promise<PluginResult | void>;
|
|
147
|
+
|
|
48
148
|
/**
|
|
49
149
|
* Process the request through this plugin
|
|
50
150
|
* First plugin to set response becomes the generator, others transform
|
|
@@ -52,16 +152,22 @@ namespace Schmock {
|
|
|
52
152
|
* @param response - Response from previous plugin (if any)
|
|
53
153
|
* @returns Updated context and response
|
|
54
154
|
*/
|
|
55
|
-
process(
|
|
155
|
+
process(
|
|
156
|
+
context: PluginContext,
|
|
157
|
+
response?: unknown,
|
|
158
|
+
): PluginResult | Promise<PluginResult>;
|
|
56
159
|
|
|
57
160
|
/**
|
|
58
|
-
* Called when an
|
|
59
|
-
*
|
|
161
|
+
* Called when this plugin or an earlier pipeline stage fails. If this hook
|
|
162
|
+
* does not recover, downstream handlers are tried in registration order.
|
|
60
163
|
* @param error - The error that occurred
|
|
61
164
|
* @param context - Plugin context
|
|
62
165
|
* @returns Modified error, response data, or void to continue error propagation
|
|
63
166
|
*/
|
|
64
|
-
onError?(
|
|
167
|
+
onError?(
|
|
168
|
+
error: Error,
|
|
169
|
+
context: PluginContext,
|
|
170
|
+
): Error | ResponseResult | void | Promise<Error | ResponseResult | void>;
|
|
65
171
|
}
|
|
66
172
|
|
|
67
173
|
/**
|
|
@@ -99,8 +205,12 @@ namespace Schmock {
|
|
|
99
205
|
body?: unknown;
|
|
100
206
|
/** Shared state between plugins for this request */
|
|
101
207
|
state: Map<string, unknown>;
|
|
208
|
+
/** True when a beforeRequest hook supplied the response instead of the route generator. */
|
|
209
|
+
requestShortCircuited?: boolean;
|
|
102
210
|
/** Route-specific state */
|
|
103
211
|
routeState?: Record<string, unknown>;
|
|
212
|
+
/** Abort signal associated with the admitted request */
|
|
213
|
+
readonly signal?: AbortSignal;
|
|
104
214
|
}
|
|
105
215
|
|
|
106
216
|
// ===== Callable API Types =====
|
|
@@ -120,6 +230,10 @@ namespace Schmock {
|
|
|
120
230
|
/**
|
|
121
231
|
* Maximum number of requests retained in history (FIFO eviction).
|
|
122
232
|
* Defaults to unbounded; set this to cap memory growth in long-running servers.
|
|
233
|
+
*
|
|
234
|
+
* Must be a non-negative integer — `0` disables history entirely, and any
|
|
235
|
+
* other value (negative, fractional, NaN, Infinity) is rejected with a
|
|
236
|
+
* `SchmockError` (`INVALID_CONFIG`) when the mock is created.
|
|
123
237
|
*/
|
|
124
238
|
maxHistorySize?: number;
|
|
125
239
|
}
|
|
@@ -136,8 +250,10 @@ namespace Schmock {
|
|
|
136
250
|
* Extension point for plugin-specific metadata.
|
|
137
251
|
*
|
|
138
252
|
* Intentionally open: `@schmock/openapi` stores "openapi:*" keys here
|
|
139
|
-
* (e.g. `"openapi:operationId"`, `"openapi:tags"`
|
|
140
|
-
*
|
|
253
|
+
* (e.g. `"openapi:operationId"`, `"openapi:tags"`, `"openapi:owner"`,
|
|
254
|
+
* `"openapi:requestContent"`), and
|
|
255
|
+
* third-party plugins may do the same. Removing this signature would be a
|
|
256
|
+
* breaking change.
|
|
141
257
|
*
|
|
142
258
|
* **Known tradeoff:** typos in known keys (e.g. `{ contenType: "…" }`) compile
|
|
143
259
|
* silently. Prefer using the explicitly typed properties above when possible.
|
|
@@ -146,22 +262,40 @@ namespace Schmock {
|
|
|
146
262
|
}
|
|
147
263
|
|
|
148
264
|
/**
|
|
149
|
-
* Generator types that can be passed to route definitions
|
|
265
|
+
* Generator types that can be passed to route definitions.
|
|
266
|
+
*
|
|
267
|
+
* Core dispatches on exactly two shapes: a function is called per request,
|
|
268
|
+
* and anything else is returned verbatim as static data. There is no
|
|
269
|
+
* schema-generation arm — a JSON Schema handed to a route is serialized back
|
|
270
|
+
* to the client as a literal schema document. Schema-driven responses come
|
|
271
|
+
* from a plugin: `.pipe(fakerPlugin({ schema }))`.
|
|
150
272
|
*/
|
|
151
|
-
type Generator =
|
|
152
|
-
| GeneratorFunction
|
|
153
|
-
| StaticData
|
|
154
|
-
| JSONSchema7;
|
|
273
|
+
type Generator = GeneratorFunction | StaticData;
|
|
155
274
|
|
|
156
275
|
/**
|
|
157
276
|
* Function that generates responses
|
|
158
277
|
*/
|
|
159
|
-
type GeneratorFunction = (
|
|
278
|
+
type GeneratorFunction = (
|
|
279
|
+
context: RequestContext,
|
|
280
|
+
) => ResponseResult | Promise<ResponseResult>;
|
|
160
281
|
|
|
161
282
|
/**
|
|
162
|
-
* Static data (non-function) that gets returned as-is
|
|
283
|
+
* Static data (non-function) that gets returned as-is.
|
|
284
|
+
*
|
|
285
|
+
* `Record<string, unknown>` accepts object literals but not a value whose
|
|
286
|
+
* declared type is an interface without an index signature (e.g. a variable
|
|
287
|
+
* typed `JSONSchema7`); pass such values as literals or widen them.
|
|
163
288
|
*/
|
|
164
|
-
type StaticData =
|
|
289
|
+
type StaticData =
|
|
290
|
+
| string
|
|
291
|
+
| number
|
|
292
|
+
| boolean
|
|
293
|
+
| null
|
|
294
|
+
| undefined
|
|
295
|
+
| Record<string, unknown>
|
|
296
|
+
| unknown[]
|
|
297
|
+
| ArrayBuffer
|
|
298
|
+
| ArrayBufferView;
|
|
165
299
|
|
|
166
300
|
/**
|
|
167
301
|
* Context passed to generator functions
|
|
@@ -181,6 +315,16 @@ namespace Schmock {
|
|
|
181
315
|
body?: unknown;
|
|
182
316
|
/** Shared mutable state */
|
|
183
317
|
state: Record<string, unknown>;
|
|
318
|
+
/**
|
|
319
|
+
* Per-request plugin state — the same `Map` as `PluginContext.state`.
|
|
320
|
+
*
|
|
321
|
+
* Lets a generator hand request-scoped data to the plugins that post-process
|
|
322
|
+
* its response (e.g. mutations staged until the final status is known).
|
|
323
|
+
* Absent when a generator is invoked outside the request pipeline.
|
|
324
|
+
*/
|
|
325
|
+
pluginState?: Map<string, unknown>;
|
|
326
|
+
/** Abort signal associated with the request */
|
|
327
|
+
readonly signal?: AbortSignal;
|
|
184
328
|
}
|
|
185
329
|
|
|
186
330
|
/**
|
|
@@ -188,11 +332,22 @@ namespace Schmock {
|
|
|
188
332
|
* - Any value: returns as 200 OK
|
|
189
333
|
* - [status, body]: custom status with body
|
|
190
334
|
* - [status, body, headers]: custom status, body, and headers
|
|
335
|
+
* - { status, body, headers? }: object envelope, equivalent to the tuple
|
|
336
|
+
* forms and produced by plugin error recovery
|
|
337
|
+
*
|
|
338
|
+
* The object envelope is detected by shape, so any returned object carrying a
|
|
339
|
+
* numeric `status` alongside a `body` is unwrapped rather than delivered as
|
|
340
|
+
* the payload — a domain object such as `{ status: 200, body: "draft" }` is
|
|
341
|
+
* indistinguishable from an envelope. An object whose `headers` is present
|
|
342
|
+
* but not a string record is *not* an envelope and is delivered whole. To
|
|
343
|
+
* return such a shape as data, nest it (`{ value: { status, body } }`) or use
|
|
344
|
+
* an explicit `[status, body]` tuple for the envelope instead.
|
|
191
345
|
*/
|
|
192
346
|
type ResponseResult =
|
|
193
347
|
| ResponseBody
|
|
194
348
|
| [number, unknown]
|
|
195
|
-
| [number, unknown, Record<string, string>]
|
|
349
|
+
| [number, unknown, Record<string, string>]
|
|
350
|
+
| { status: number; body: unknown; headers?: Record<string, string> };
|
|
196
351
|
|
|
197
352
|
/**
|
|
198
353
|
* Response object returned by handle method
|
|
@@ -210,6 +365,7 @@ namespace Schmock {
|
|
|
210
365
|
headers?: Record<string, string>;
|
|
211
366
|
body?: unknown;
|
|
212
367
|
query?: Record<string, string>;
|
|
368
|
+
signal?: AbortSignal;
|
|
213
369
|
}
|
|
214
370
|
|
|
215
371
|
/**
|
|
@@ -240,12 +396,14 @@ namespace Schmock {
|
|
|
240
396
|
interface CallableMockInstance {
|
|
241
397
|
/**
|
|
242
398
|
* Define a route by calling the instance directly
|
|
243
|
-
*
|
|
399
|
+
*
|
|
244
400
|
* @param route - Route pattern in format 'METHOD /path'
|
|
245
|
-
* @param generator - Response generator
|
|
401
|
+
* @param generator - Response generator: a function called per request, or
|
|
402
|
+
* static data returned verbatim. There is no schema arm — use
|
|
403
|
+
* `.pipe(fakerPlugin({ schema }))` for schema-driven responses.
|
|
246
404
|
* @param config - Route-specific configuration
|
|
247
405
|
* @returns The same instance for method chaining
|
|
248
|
-
*
|
|
406
|
+
*
|
|
249
407
|
* @example
|
|
250
408
|
* ```typescript
|
|
251
409
|
* const mock = schmock()
|
|
@@ -253,19 +411,22 @@ namespace Schmock {
|
|
|
253
411
|
* mock('POST /users', userData, { contentType: 'application/json' })
|
|
254
412
|
* ```
|
|
255
413
|
*/
|
|
256
|
-
(
|
|
414
|
+
(
|
|
415
|
+
route: RouteKey,
|
|
416
|
+
generator: Generator,
|
|
417
|
+
config?: RouteConfig,
|
|
418
|
+
): CallableMockInstance;
|
|
257
419
|
|
|
258
420
|
/**
|
|
259
421
|
* Add a plugin to the pipeline
|
|
260
|
-
*
|
|
422
|
+
*
|
|
261
423
|
* @param plugin - Plugin to add to the pipeline
|
|
262
424
|
* @returns The same instance for method chaining
|
|
263
|
-
*
|
|
425
|
+
*
|
|
264
426
|
* @example
|
|
265
427
|
* ```typescript
|
|
428
|
+
* mock.pipe(authPlugin()).pipe(corsPlugin())
|
|
266
429
|
* mock('GET /users', generator, config)
|
|
267
|
-
* .pipe(authPlugin())
|
|
268
|
-
* .pipe(corsPlugin())
|
|
269
430
|
* ```
|
|
270
431
|
*/
|
|
271
432
|
pipe(plugin: Plugin): CallableMockInstance;
|
|
@@ -285,7 +446,11 @@ namespace Schmock {
|
|
|
285
446
|
* })
|
|
286
447
|
* ```
|
|
287
448
|
*/
|
|
288
|
-
handle(
|
|
449
|
+
handle(
|
|
450
|
+
method: HttpMethod,
|
|
451
|
+
path: string,
|
|
452
|
+
options?: RequestOptions,
|
|
453
|
+
): Promise<Response>;
|
|
289
454
|
|
|
290
455
|
// ===== Request Spy / History API =====
|
|
291
456
|
|
|
@@ -328,7 +493,9 @@ namespace Schmock {
|
|
|
328
493
|
// ===== Reset / Lifecycle =====
|
|
329
494
|
|
|
330
495
|
/**
|
|
331
|
-
* Clear
|
|
496
|
+
* Clear routes, state, plugins, listeners, and history, and stop the Node
|
|
497
|
+
* server. An explicitly acquired fetch interception remains active until
|
|
498
|
+
* its InterceptHandle is restored.
|
|
332
499
|
*/
|
|
333
500
|
reset(): void;
|
|
334
501
|
|
|
@@ -347,12 +514,18 @@ namespace Schmock {
|
|
|
347
514
|
/**
|
|
348
515
|
* Register an event listener
|
|
349
516
|
*/
|
|
350
|
-
on<E extends SchmockEvent>(
|
|
517
|
+
on<E extends SchmockEvent>(
|
|
518
|
+
event: E,
|
|
519
|
+
listener: (data: SchmockEventMap[E]) => void,
|
|
520
|
+
): CallableMockInstance;
|
|
351
521
|
|
|
352
522
|
/**
|
|
353
523
|
* Remove an event listener
|
|
354
524
|
*/
|
|
355
|
-
off<E extends SchmockEvent>(
|
|
525
|
+
off<E extends SchmockEvent>(
|
|
526
|
+
event: E,
|
|
527
|
+
listener: (data: SchmockEventMap[E]) => void,
|
|
528
|
+
): CallableMockInstance;
|
|
356
529
|
|
|
357
530
|
// ===== Introspection =====
|
|
358
531
|
|
|
@@ -389,9 +562,14 @@ namespace Schmock {
|
|
|
389
562
|
* Intercept globalThis.fetch and route requests through this mock.
|
|
390
563
|
* Client-side equivalent of listen().
|
|
391
564
|
*
|
|
565
|
+
* A mock may hold any number of concurrent leases — nested providers,
|
|
566
|
+
* separate roots, or an adapter alongside a manual call. Each lease owns
|
|
567
|
+
* its own options and is released independently; the newest lease is
|
|
568
|
+
* consulted first.
|
|
569
|
+
*
|
|
392
570
|
* @param options - Intercept configuration
|
|
393
|
-
* @returns Handle with restore() to
|
|
394
|
-
*
|
|
571
|
+
* @returns Handle with restore() to release this lease and update() to
|
|
572
|
+
* change its options without changing its position in the stack
|
|
395
573
|
*/
|
|
396
574
|
intercept(options?: InterceptOptions): InterceptHandle;
|
|
397
575
|
}
|
|
@@ -438,6 +616,7 @@ namespace Schmock {
|
|
|
438
616
|
headers: Record<string, string>;
|
|
439
617
|
body?: unknown;
|
|
440
618
|
query: Record<string, string>;
|
|
619
|
+
readonly signal?: AbortSignal;
|
|
441
620
|
}
|
|
442
621
|
|
|
443
622
|
interface AdapterResponse {
|
|
@@ -477,37 +656,52 @@ namespace Schmock {
|
|
|
477
656
|
}
|
|
478
657
|
|
|
479
658
|
interface InterceptHandle {
|
|
480
|
-
/**
|
|
659
|
+
/** Release this lease; restores original fetch once the last lease goes */
|
|
481
660
|
restore(): void;
|
|
661
|
+
/**
|
|
662
|
+
* Reconfigure this lease in place, keeping its position in the
|
|
663
|
+
* interception stack. Options are replaced wholesale — omitted fields fall
|
|
664
|
+
* back to their defaults, so `update({})` restores `passthrough: true`.
|
|
665
|
+
* No-op once the lease has been restored.
|
|
666
|
+
*/
|
|
667
|
+
update(options?: InterceptOptions): void;
|
|
482
668
|
/** Whether this interceptor is currently active */
|
|
483
669
|
readonly active: boolean;
|
|
484
670
|
}
|
|
485
671
|
|
|
486
672
|
// ===== Lifecycle Events =====
|
|
487
673
|
|
|
674
|
+
/**
|
|
675
|
+
* Every lifecycle event carries `path`: the ORIGINAL request path in its
|
|
676
|
+
* canonical percent-encoded form, namespace prefix included. The
|
|
677
|
+
* namespace-stripped route form is available only as `routePath` on
|
|
678
|
+
* `request:match`.
|
|
679
|
+
*/
|
|
488
680
|
interface RequestStartEvent {
|
|
489
|
-
method: HttpMethod;
|
|
490
|
-
path: string;
|
|
491
|
-
headers: Record<string, string
|
|
681
|
+
readonly method: HttpMethod;
|
|
682
|
+
readonly path: string;
|
|
683
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
492
684
|
}
|
|
493
685
|
|
|
494
686
|
interface RequestMatchEvent {
|
|
495
|
-
method: HttpMethod;
|
|
496
|
-
path
|
|
497
|
-
|
|
498
|
-
|
|
687
|
+
readonly method: HttpMethod;
|
|
688
|
+
/** Original request path, namespace prefix included */
|
|
689
|
+
readonly path: string;
|
|
690
|
+
/** Registered route path, namespace prefix stripped */
|
|
691
|
+
readonly routePath: string;
|
|
692
|
+
readonly params: Readonly<Record<string, string>>;
|
|
499
693
|
}
|
|
500
694
|
|
|
501
695
|
interface RequestNotFoundEvent {
|
|
502
|
-
method: HttpMethod;
|
|
503
|
-
path: string;
|
|
696
|
+
readonly method: HttpMethod;
|
|
697
|
+
readonly path: string;
|
|
504
698
|
}
|
|
505
699
|
|
|
506
700
|
interface RequestEndEvent {
|
|
507
|
-
method: HttpMethod;
|
|
508
|
-
path: string;
|
|
509
|
-
status: number;
|
|
510
|
-
duration: number;
|
|
701
|
+
readonly method: HttpMethod;
|
|
702
|
+
readonly path: string;
|
|
703
|
+
readonly status: number;
|
|
704
|
+
readonly duration: number;
|
|
511
705
|
}
|
|
512
706
|
|
|
513
707
|
type SchmockEventMap = {
|
|
@@ -555,10 +749,20 @@ namespace Schmock {
|
|
|
555
749
|
interface CrudOperationMeta {
|
|
556
750
|
/** Full success response schema (wrapper + items) */
|
|
557
751
|
responseSchema?: JSONSchema7;
|
|
752
|
+
/** Concrete success status selected from the operation contract. */
|
|
753
|
+
responseStatus?: number;
|
|
558
754
|
/** Response headers from spec */
|
|
559
755
|
responseHeaders?: Record<string, ResponseHeaderDef>;
|
|
560
756
|
/** Error response schemas keyed by status code */
|
|
561
757
|
errorSchemas?: Map<number, JSONSchema7>;
|
|
758
|
+
/** Declared media types for the success response, in spec order. */
|
|
759
|
+
responseContentTypes?: string[];
|
|
760
|
+
/**
|
|
761
|
+
* Success response schemas keyed by declared media type (OAS3 `content`).
|
|
762
|
+
* When present it takes precedence over `responseSchema`, so anything that
|
|
763
|
+
* replaces `responseSchema` must clear this map too.
|
|
764
|
+
*/
|
|
765
|
+
responseSchemasByMediaType?: Map<string, JSONSchema7>;
|
|
562
766
|
}
|
|
563
767
|
|
|
564
768
|
// ===== Faker Plugin Types =====
|
|
@@ -627,22 +831,72 @@ namespace Schmock {
|
|
|
627
831
|
passthrough?: boolean;
|
|
628
832
|
errorFormatter?: (error: Error, request: unknown) => unknown;
|
|
629
833
|
transformRequest?: (request: unknown) => AdapterRequestOverride;
|
|
630
|
-
transformResponse?: (
|
|
631
|
-
response: Response,
|
|
632
|
-
request: unknown,
|
|
633
|
-
) => Response;
|
|
834
|
+
transformResponse?: (response: Response, request: unknown) => Response;
|
|
634
835
|
}
|
|
635
836
|
|
|
636
837
|
// ===== OpenAPI Plugin Options =====
|
|
637
838
|
|
|
839
|
+
/** A callback request resolved from an OpenAPI callback expression. */
|
|
840
|
+
interface OpenApiCallbackRequest {
|
|
841
|
+
url: string;
|
|
842
|
+
method: HttpMethod;
|
|
843
|
+
headers: Record<string, string>;
|
|
844
|
+
body?: unknown;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/** Explicit application-owned delivery for OpenAPI callbacks. */
|
|
848
|
+
interface OpenApiCallbackOptions {
|
|
849
|
+
dispatch(request: OpenApiCallbackRequest): void | Promise<void>;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Policy governing `$ref`s that leave the root spec document.
|
|
854
|
+
*
|
|
855
|
+
* A spec is untrusted input — on the CLI it is a path a caller hands over —
|
|
856
|
+
* and `$ref` is a file-read and network primitive, so nothing outside the
|
|
857
|
+
* root document resolves unless it is opted into here.
|
|
858
|
+
*/
|
|
859
|
+
interface OpenApiRefPolicy {
|
|
860
|
+
/** Allow any `$ref` that leaves the root document. Default `false`. */
|
|
861
|
+
external?: boolean;
|
|
862
|
+
/** Allow `http(s)` `$ref`s. Requires `external`. Default `false`. */
|
|
863
|
+
allowHttp?: boolean;
|
|
864
|
+
/**
|
|
865
|
+
* Hostnames an `http(s)` `$ref` may target. Empty or omitted means any
|
|
866
|
+
* host, still minus loopback, link-local and private ranges.
|
|
867
|
+
*/
|
|
868
|
+
allowedHosts?: string[];
|
|
869
|
+
/** Per-request timeout for http `$ref`s, in ms. Default 5000. */
|
|
870
|
+
timeoutMs?: number;
|
|
871
|
+
/**
|
|
872
|
+
* Redirects to follow for an http `$ref`. Default 0.
|
|
873
|
+
*
|
|
874
|
+
* `fetch` exposes no numeric redirect cap, so this behaves as a boolean:
|
|
875
|
+
* `0` refuses redirects, any positive value follows up to the platform
|
|
876
|
+
* default. Use `allowedHosts` when the exact destination matters.
|
|
877
|
+
*/
|
|
878
|
+
redirects?: number;
|
|
879
|
+
/** Maximum size of a single http `$ref` document, in bytes. Default 1 MB. */
|
|
880
|
+
maxBytes?: number;
|
|
881
|
+
}
|
|
882
|
+
|
|
638
883
|
/**
|
|
639
884
|
* Options for the OpenAPI plugin
|
|
640
885
|
*/
|
|
641
886
|
interface OpenApiOptions {
|
|
642
887
|
spec: string | object;
|
|
643
888
|
seed?: SeedConfig;
|
|
889
|
+
/**
|
|
890
|
+
* Validate the spec against the OpenAPI schema and specification when it is
|
|
891
|
+
* loaded. Default `false`: incomplete specs are deliberately tolerated, and
|
|
892
|
+
* validation is expensive on large documents.
|
|
893
|
+
*/
|
|
894
|
+
strict?: boolean;
|
|
895
|
+
/** External `$ref` resolution policy. External refs are off by default. */
|
|
896
|
+
refs?: OpenApiRefPolicy;
|
|
644
897
|
validateRequests?: boolean;
|
|
645
898
|
validateResponses?: boolean;
|
|
899
|
+
/** @deprecated Unsupported. Supplying this option throws OPENAPI_UNSUPPORTED_OPTION. */
|
|
646
900
|
queryFeatures?: {
|
|
647
901
|
pagination?: boolean;
|
|
648
902
|
sorting?: boolean;
|
|
@@ -652,12 +906,24 @@ namespace Schmock {
|
|
|
652
906
|
debug?: boolean;
|
|
653
907
|
fakerSeed?: number;
|
|
654
908
|
security?: boolean;
|
|
909
|
+
/**
|
|
910
|
+
* Enable callback delivery through an application-supplied dispatcher.
|
|
911
|
+
* Callbacks are disabled when this option is omitted; Schmock never
|
|
912
|
+
* performs callback network requests implicitly.
|
|
913
|
+
*/
|
|
914
|
+
callbacks?: OpenApiCallbackOptions;
|
|
655
915
|
/** Replace response schemas for specific routes. Key format: "METHOD /path" or "METHOD /path STATUS" */
|
|
656
916
|
schemas?: Record<string, import("json-schema").JSONSchema7>;
|
|
657
917
|
/** Called before generating a response body. Return a schema to replace the original, or void to keep it. */
|
|
658
918
|
onSchema?: (
|
|
659
919
|
schema: import("json-schema").JSONSchema7,
|
|
660
|
-
context: {
|
|
920
|
+
context: {
|
|
921
|
+
method: string;
|
|
922
|
+
path: string;
|
|
923
|
+
params: Record<string, string>;
|
|
924
|
+
query: Record<string, string>;
|
|
925
|
+
headers: Record<string, string>;
|
|
926
|
+
},
|
|
661
927
|
) => import("json-schema").JSONSchema7 | undefined;
|
|
662
928
|
}
|
|
663
929
|
|
|
@@ -687,18 +953,70 @@ namespace Schmock {
|
|
|
687
953
|
errors?: boolean;
|
|
688
954
|
watch?: boolean;
|
|
689
955
|
admin?: boolean;
|
|
956
|
+
/**
|
|
957
|
+
* Bearer token required by every `/schmock-admin/*` request
|
|
958
|
+
* (`--admin-token`). When `admin` is on and this is omitted, a random
|
|
959
|
+
* token is minted once and surfaced on {@link CliServer.adminToken}.
|
|
960
|
+
*/
|
|
961
|
+
adminToken?: string;
|
|
962
|
+
/**
|
|
963
|
+
* How many requests the mock retains for `GET /schmock-admin/history`
|
|
964
|
+
* (`--admin-history-limit`, default 500). Ignored — history is disabled
|
|
965
|
+
* entirely — when `admin` is off.
|
|
966
|
+
*/
|
|
967
|
+
adminHistoryLimit?: number;
|
|
968
|
+
/** Validate the spec against the OpenAPI schema at startup (`--strict`). */
|
|
969
|
+
strict?: boolean;
|
|
970
|
+
/** Resolve `$ref`s outside the spec document (`--refs-external`). */
|
|
971
|
+
refsExternal?: boolean;
|
|
972
|
+
/**
|
|
973
|
+
* Hosts an `http(s)` `$ref` may target (`--refs-allow-http`). Supplying
|
|
974
|
+
* this also enables http resolution, which still requires `refsExternal`.
|
|
975
|
+
*/
|
|
976
|
+
refsAllowHttp?: string[];
|
|
977
|
+
/**
|
|
978
|
+
* How long {@link CliServer.close} waits for in-flight requests before
|
|
979
|
+
* the remaining sockets are destroyed (default 5000 ms). A half-sent
|
|
980
|
+
* request never completes on its own, so without a bound the close would
|
|
981
|
+
* hang.
|
|
982
|
+
*/
|
|
983
|
+
shutdownGraceMs?: number;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/** Browser-safe subset of the Node server exposed by a CLI instance. */
|
|
987
|
+
interface CliHttpServer {
|
|
988
|
+
readonly listening: boolean;
|
|
989
|
+
address():
|
|
990
|
+
| string
|
|
991
|
+
| { address: string; family: string; port: number }
|
|
992
|
+
| null;
|
|
993
|
+
close(callback?: (error?: Error) => void): this;
|
|
994
|
+
closeAllConnections(): void;
|
|
995
|
+
closeIdleConnections(): void;
|
|
996
|
+
ref(): this;
|
|
997
|
+
unref(): this;
|
|
690
998
|
}
|
|
691
999
|
|
|
692
1000
|
/**
|
|
693
|
-
* Running CLI server instance
|
|
1001
|
+
* Running CLI server instance. Import `CliServer` from `@schmock/cli` for
|
|
1002
|
+
* the exact Node.js server type.
|
|
694
1003
|
*/
|
|
695
1004
|
interface CliServer {
|
|
696
|
-
server:
|
|
1005
|
+
server: CliHttpServer;
|
|
697
1006
|
port: number;
|
|
698
1007
|
hostname: string;
|
|
699
|
-
|
|
1008
|
+
/**
|
|
1009
|
+
* The bearer token this server requires on `/schmock-admin/*`. Present
|
|
1010
|
+
* only when admin is enabled.
|
|
1011
|
+
*/
|
|
1012
|
+
adminToken?: string;
|
|
1013
|
+
/**
|
|
1014
|
+
* Stop watching, stop accepting, and settle once the socket is released —
|
|
1015
|
+
* within {@link CliOptions.shutdownGraceMs}. Memoized: closing twice is
|
|
1016
|
+
* safe and resolves twice.
|
|
1017
|
+
*/
|
|
1018
|
+
close(): Promise<void>;
|
|
700
1019
|
}
|
|
701
|
-
|
|
702
1020
|
}
|
|
703
1021
|
}
|
|
704
1022
|
// >>> schmock ambient namespace <<<
|
|
@@ -726,10 +1044,13 @@ namespace Schmock {
|
|
|
726
1044
|
* @returns A callable mock instance
|
|
727
1045
|
*/
|
|
728
1046
|
export declare function schmock(config?: Schmock.GlobalConfig): Schmock.CallableMockInstance;
|
|
729
|
-
export {
|
|
730
|
-
export {
|
|
1047
|
+
export { isBinaryBody } from "./binary.js";
|
|
1048
|
+
export { getResponseException, HTTP_METHODS, isHttpMethod, isRouteNotFound, isStatusTuple, ROUTE_NOT_FOUND_CODE, toHttpMethod, toRouteKey, } from "./constants.js";
|
|
1049
|
+
export { InvalidResponseError, PluginError, ResourceLimitError, RouteDefinitionError, RouteNotFoundError, RouteParseError, SchemaGenerationError, SchemaValidationError, SchmockError, } from "./errors.js";
|
|
731
1050
|
export { badRequest, created, forbidden, noContent, notFound, paginate, serverError, unauthorized, } from "./helpers.js";
|
|
732
|
-
export {
|
|
1051
|
+
export type { HttpIngressErrorCode } from "./http-helpers.js";
|
|
1052
|
+
export { collectBody, HttpIngressError, parseNodeHeaders, parseNodeQuery, writeRejectedSchmockResponse, writeSchmockResponse, } from "./http-helpers.js";
|
|
733
1053
|
export { createFetchInterceptor } from "./interceptor.js";
|
|
734
|
-
export
|
|
1054
|
+
export { normalizeResponse, serializeResponseBody, } from "./response-normalizer.js";
|
|
1055
|
+
export type { AdapterRequest, AdapterRequestOverride, AdapterResponse, AngularAdapterOptions, CallableMockInstance, CrudOperationMeta, ExpressAdapterOptions, FakerPluginOptions, Generator, GeneratorFunction, GlobalConfig, HttpMethod, InterceptHandle, InterceptOptions, OpenApiCallbackOptions, OpenApiCallbackRequest, OpenApiOptions, Plugin, PluginContext, PluginResult, RequestContext, RequestOptions, RequestRecord, ResourceOverride, Response, ResponseBody, ResponseHeaderDef, ResponseResult, RouteConfig, RouteInfo, RouteKey, Schema, SchemaDefinition, SchemaGenerationContext, SeedConfig, SeedSource, ServerInfo, StaticData, } from "./types.js";
|
|
735
1056
|
//# sourceMappingURL=index.d.ts.map
|