@schmock/core 2.3.0 → 2.4.0
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/builder.d.ts +31 -10
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +760 -190
- 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 +39 -4
- package/dist/http-helpers.d.ts.map +1 -1
- package/dist/http-helpers.js +147 -49
- package/dist/index.d.ts +292 -34
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/interceptor.d.ts +11 -1
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/interceptor.js +316 -169
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +12 -3
- package/dist/plugin-pipeline.d.ts +3 -3
- package/dist/plugin-pipeline.d.ts.map +1 -1
- package/dist/plugin-pipeline.js +29 -14
- 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 +39 -2
- 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 -6
- package/src/audit-core-builder.test.ts +0 -218
- package/src/audit-response-guard.test.ts +0 -38
- package/src/binary.test.ts +0 -126
- package/src/binary.ts +0 -11
- package/src/builder.test.ts +0 -289
- package/src/builder.ts +0 -748
- 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.test.ts +0 -39
- package/src/http-helpers.ts +0 -149
- package/src/index.ts +0 -152
- package/src/interceptor.test.ts +0 -488
- package/src/interceptor.ts +0 -407
- package/src/namespace.test.ts +0 -274
- package/src/parser.property.test.ts +0 -630
- package/src/parser.test.ts +0 -148
- package/src/parser.ts +0 -64
- package/src/plugin-pipeline.ts +0 -208
- package/src/plugin-system.test.ts +0 -697
- package/src/response-parser.ts +0 -114
- 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 -234
- package/src/smart-defaults.test.ts +0 -361
- package/src/steps/async-support.steps.ts +0 -421
- package/src/steps/audit-core-builder.steps.ts +0 -188
- package/src/steps/audit-onerror-tuple.steps.ts +0 -83
- 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 -555
- package/src/steps/fetch-interceptor.steps.ts +0 -457
- package/src/steps/fluent-api.steps.ts +0 -255
- package/src/steps/http-methods.steps.ts +0 -342
- package/src/steps/lifecycle-events.steps.ts +0 -149
- package/src/steps/performance-reliability.steps.ts +0 -90
- package/src/steps/plugin-integration.steps.ts +0 -334
- package/src/steps/request-history.steps.ts +0 -458
- 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 -227
- package/src/steps/state-concurrency.steps.ts +0 -167
- 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,12 +100,17 @@ 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}
|
|
113
|
+
type RouteKey = `${HttpMethod} /${string}`;
|
|
31
114
|
|
|
32
115
|
/**
|
|
33
116
|
* Plugin interface for extending Schmock functionality
|
|
@@ -40,11 +123,19 @@ 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
|
+
|
|
48
139
|
/**
|
|
49
140
|
* Inspect or transform a request before its route generator executes.
|
|
50
141
|
* Returning a response short-circuits the generator, while returning only
|
|
@@ -118,6 +209,8 @@ namespace Schmock {
|
|
|
118
209
|
requestShortCircuited?: boolean;
|
|
119
210
|
/** Route-specific state */
|
|
120
211
|
routeState?: Record<string, unknown>;
|
|
212
|
+
/** Abort signal associated with the admitted request */
|
|
213
|
+
readonly signal?: AbortSignal;
|
|
121
214
|
}
|
|
122
215
|
|
|
123
216
|
// ===== Callable API Types =====
|
|
@@ -137,6 +230,10 @@ namespace Schmock {
|
|
|
137
230
|
/**
|
|
138
231
|
* Maximum number of requests retained in history (FIFO eviction).
|
|
139
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.
|
|
140
237
|
*/
|
|
141
238
|
maxHistorySize?: number;
|
|
142
239
|
}
|
|
@@ -153,8 +250,10 @@ namespace Schmock {
|
|
|
153
250
|
* Extension point for plugin-specific metadata.
|
|
154
251
|
*
|
|
155
252
|
* Intentionally open: `@schmock/openapi` stores "openapi:*" keys here
|
|
156
|
-
* (e.g. `"openapi:operationId"`, `"openapi:tags"`
|
|
157
|
-
*
|
|
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.
|
|
158
257
|
*
|
|
159
258
|
* **Known tradeoff:** typos in known keys (e.g. `{ contenType: "…" }`) compile
|
|
160
259
|
* silently. Prefer using the explicitly typed properties above when possible.
|
|
@@ -163,9 +262,15 @@ namespace Schmock {
|
|
|
163
262
|
}
|
|
164
263
|
|
|
165
264
|
/**
|
|
166
|
-
* 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 }))`.
|
|
167
272
|
*/
|
|
168
|
-
type Generator = GeneratorFunction | StaticData
|
|
273
|
+
type Generator = GeneratorFunction | StaticData;
|
|
169
274
|
|
|
170
275
|
/**
|
|
171
276
|
* Function that generates responses
|
|
@@ -175,7 +280,11 @@ namespace Schmock {
|
|
|
175
280
|
) => ResponseResult | Promise<ResponseResult>;
|
|
176
281
|
|
|
177
282
|
/**
|
|
178
|
-
* 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.
|
|
179
288
|
*/
|
|
180
289
|
type StaticData =
|
|
181
290
|
| string
|
|
@@ -206,6 +315,16 @@ namespace Schmock {
|
|
|
206
315
|
body?: unknown;
|
|
207
316
|
/** Shared mutable state */
|
|
208
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;
|
|
209
328
|
}
|
|
210
329
|
|
|
211
330
|
/**
|
|
@@ -213,11 +332,22 @@ namespace Schmock {
|
|
|
213
332
|
* - Any value: returns as 200 OK
|
|
214
333
|
* - [status, body]: custom status with body
|
|
215
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.
|
|
216
345
|
*/
|
|
217
346
|
type ResponseResult =
|
|
218
347
|
| ResponseBody
|
|
219
348
|
| [number, unknown]
|
|
220
|
-
| [number, unknown, Record<string, string>]
|
|
349
|
+
| [number, unknown, Record<string, string>]
|
|
350
|
+
| { status: number; body: unknown; headers?: Record<string, string> };
|
|
221
351
|
|
|
222
352
|
/**
|
|
223
353
|
* Response object returned by handle method
|
|
@@ -235,6 +365,7 @@ namespace Schmock {
|
|
|
235
365
|
headers?: Record<string, string>;
|
|
236
366
|
body?: unknown;
|
|
237
367
|
query?: Record<string, string>;
|
|
368
|
+
signal?: AbortSignal;
|
|
238
369
|
}
|
|
239
370
|
|
|
240
371
|
/**
|
|
@@ -267,7 +398,9 @@ namespace Schmock {
|
|
|
267
398
|
* Define a route by calling the instance directly
|
|
268
399
|
*
|
|
269
400
|
* @param route - Route pattern in format 'METHOD /path'
|
|
270
|
-
* @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.
|
|
271
404
|
* @param config - Route-specific configuration
|
|
272
405
|
* @returns The same instance for method chaining
|
|
273
406
|
*
|
|
@@ -360,7 +493,9 @@ namespace Schmock {
|
|
|
360
493
|
// ===== Reset / Lifecycle =====
|
|
361
494
|
|
|
362
495
|
/**
|
|
363
|
-
* 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.
|
|
364
499
|
*/
|
|
365
500
|
reset(): void;
|
|
366
501
|
|
|
@@ -427,9 +562,14 @@ namespace Schmock {
|
|
|
427
562
|
* Intercept globalThis.fetch and route requests through this mock.
|
|
428
563
|
* Client-side equivalent of listen().
|
|
429
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
|
+
*
|
|
430
570
|
* @param options - Intercept configuration
|
|
431
|
-
* @returns Handle with restore() to
|
|
432
|
-
*
|
|
571
|
+
* @returns Handle with restore() to release this lease and update() to
|
|
572
|
+
* change its options without changing its position in the stack
|
|
433
573
|
*/
|
|
434
574
|
intercept(options?: InterceptOptions): InterceptHandle;
|
|
435
575
|
}
|
|
@@ -476,6 +616,7 @@ namespace Schmock {
|
|
|
476
616
|
headers: Record<string, string>;
|
|
477
617
|
body?: unknown;
|
|
478
618
|
query: Record<string, string>;
|
|
619
|
+
readonly signal?: AbortSignal;
|
|
479
620
|
}
|
|
480
621
|
|
|
481
622
|
interface AdapterResponse {
|
|
@@ -515,37 +656,52 @@ namespace Schmock {
|
|
|
515
656
|
}
|
|
516
657
|
|
|
517
658
|
interface InterceptHandle {
|
|
518
|
-
/**
|
|
659
|
+
/** Release this lease; restores original fetch once the last lease goes */
|
|
519
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;
|
|
520
668
|
/** Whether this interceptor is currently active */
|
|
521
669
|
readonly active: boolean;
|
|
522
670
|
}
|
|
523
671
|
|
|
524
672
|
// ===== Lifecycle Events =====
|
|
525
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
|
+
*/
|
|
526
680
|
interface RequestStartEvent {
|
|
527
|
-
method: HttpMethod;
|
|
528
|
-
path: string;
|
|
529
|
-
headers: Record<string, string
|
|
681
|
+
readonly method: HttpMethod;
|
|
682
|
+
readonly path: string;
|
|
683
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
530
684
|
}
|
|
531
685
|
|
|
532
686
|
interface RequestMatchEvent {
|
|
533
|
-
method: HttpMethod;
|
|
534
|
-
path
|
|
535
|
-
|
|
536
|
-
|
|
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>>;
|
|
537
693
|
}
|
|
538
694
|
|
|
539
695
|
interface RequestNotFoundEvent {
|
|
540
|
-
method: HttpMethod;
|
|
541
|
-
path: string;
|
|
696
|
+
readonly method: HttpMethod;
|
|
697
|
+
readonly path: string;
|
|
542
698
|
}
|
|
543
699
|
|
|
544
700
|
interface RequestEndEvent {
|
|
545
|
-
method: HttpMethod;
|
|
546
|
-
path: string;
|
|
547
|
-
status: number;
|
|
548
|
-
duration: number;
|
|
701
|
+
readonly method: HttpMethod;
|
|
702
|
+
readonly path: string;
|
|
703
|
+
readonly status: number;
|
|
704
|
+
readonly duration: number;
|
|
549
705
|
}
|
|
550
706
|
|
|
551
707
|
type SchmockEventMap = {
|
|
@@ -599,6 +755,14 @@ namespace Schmock {
|
|
|
599
755
|
responseHeaders?: Record<string, ResponseHeaderDef>;
|
|
600
756
|
/** Error response schemas keyed by status code */
|
|
601
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>;
|
|
602
766
|
}
|
|
603
767
|
|
|
604
768
|
// ===== Faker Plugin Types =====
|
|
@@ -685,12 +849,51 @@ namespace Schmock {
|
|
|
685
849
|
dispatch(request: OpenApiCallbackRequest): void | Promise<void>;
|
|
686
850
|
}
|
|
687
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
|
+
|
|
688
883
|
/**
|
|
689
884
|
* Options for the OpenAPI plugin
|
|
690
885
|
*/
|
|
691
886
|
interface OpenApiOptions {
|
|
692
887
|
spec: string | object;
|
|
693
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;
|
|
694
897
|
validateRequests?: boolean;
|
|
695
898
|
validateResponses?: boolean;
|
|
696
899
|
/** @deprecated Unsupported. Supplying this option throws OPENAPI_UNSUPPORTED_OPTION. */
|
|
@@ -750,16 +953,69 @@ namespace Schmock {
|
|
|
750
953
|
errors?: boolean;
|
|
751
954
|
watch?: boolean;
|
|
752
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;
|
|
753
998
|
}
|
|
754
999
|
|
|
755
1000
|
/**
|
|
756
|
-
* Running CLI server instance
|
|
1001
|
+
* Running CLI server instance. Import `CliServer` from `@schmock/cli` for
|
|
1002
|
+
* the exact Node.js server type.
|
|
757
1003
|
*/
|
|
758
1004
|
interface CliServer {
|
|
759
|
-
server:
|
|
1005
|
+
server: CliHttpServer;
|
|
760
1006
|
port: number;
|
|
761
1007
|
hostname: string;
|
|
762
|
-
|
|
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>;
|
|
763
1019
|
}
|
|
764
1020
|
}
|
|
765
1021
|
}
|
|
@@ -789,10 +1045,12 @@ namespace Schmock {
|
|
|
789
1045
|
*/
|
|
790
1046
|
export declare function schmock(config?: Schmock.GlobalConfig): Schmock.CallableMockInstance;
|
|
791
1047
|
export { isBinaryBody } from "./binary.js";
|
|
792
|
-
export { HTTP_METHODS, isHttpMethod, isRouteNotFound, isStatusTuple, ROUTE_NOT_FOUND_CODE, toHttpMethod, toRouteKey, } from "./constants.js";
|
|
793
|
-
export { PluginError, ResourceLimitError,
|
|
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";
|
|
794
1050
|
export { badRequest, created, forbidden, noContent, notFound, paginate, serverError, unauthorized, } from "./helpers.js";
|
|
795
|
-
export {
|
|
1051
|
+
export type { HttpIngressErrorCode } from "./http-helpers.js";
|
|
1052
|
+
export { collectBody, HttpIngressError, parseNodeHeaders, parseNodeQuery, writeRejectedSchmockResponse, writeSchmockResponse, } from "./http-helpers.js";
|
|
796
1053
|
export { createFetchInterceptor } from "./interceptor.js";
|
|
797
|
-
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";
|
|
798
1056
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,OAAO,CACrB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,GAC5B,OAAO,CAAC,oBAAoB,CAyD9B;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EACL,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,EACd,MAAM,EACN,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,SAAS,EACT,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CallableMockInstance } from "./builder.js";
|
|
2
|
+
const REQUEST_ADMISSION = Symbol.for("@schmock/core.request-admission");
|
|
2
3
|
/**
|
|
3
4
|
* Create a new Schmock mock instance with callable API.
|
|
4
5
|
*
|
|
@@ -56,18 +57,22 @@ export function schmock(config) {
|
|
|
56
57
|
close: instance.close.bind(instance),
|
|
57
58
|
intercept: (options) => instance.intercept(options),
|
|
58
59
|
});
|
|
60
|
+
Object.defineProperty(callableInstance, REQUEST_ADMISSION, {
|
|
61
|
+
value: () => instance.createRequestAdmission(),
|
|
62
|
+
});
|
|
59
63
|
instance.setCallableRef(callableInstance);
|
|
60
64
|
return callableInstance;
|
|
61
65
|
}
|
|
62
66
|
export { isBinaryBody } from "./binary.js";
|
|
63
67
|
// Re-export constants and utilities
|
|
64
|
-
export { HTTP_METHODS, isHttpMethod, isRouteNotFound, isStatusTuple, ROUTE_NOT_FOUND_CODE, toHttpMethod, toRouteKey, } from "./constants.js";
|
|
68
|
+
export { getResponseException, HTTP_METHODS, isHttpMethod, isRouteNotFound, isStatusTuple, ROUTE_NOT_FOUND_CODE, toHttpMethod, toRouteKey, } from "./constants.js";
|
|
65
69
|
// Re-export errors
|
|
66
|
-
export { PluginError, ResourceLimitError,
|
|
70
|
+
export { InvalidResponseError, PluginError, ResourceLimitError, RouteDefinitionError, RouteNotFoundError, RouteParseError, SchemaGenerationError, SchemaValidationError, SchmockError, } from "./errors.js";
|
|
67
71
|
// Re-export response helpers
|
|
68
72
|
export { badRequest, created, forbidden, noContent, notFound, paginate, serverError, unauthorized, } from "./helpers.js";
|
|
69
73
|
// Re-export HTTP server helpers
|
|
70
|
-
export { collectBody, parseNodeHeaders, parseNodeQuery, writeSchmockResponse, } from "./http-helpers.js";
|
|
74
|
+
export { collectBody, HttpIngressError, parseNodeHeaders, parseNodeQuery, writeRejectedSchmockResponse, writeSchmockResponse, } from "./http-helpers.js";
|
|
71
75
|
// Re-export types
|
|
72
76
|
// Re-export interceptor
|
|
73
77
|
export { createFetchInterceptor } from "./interceptor.js";
|
|
78
|
+
export { normalizeResponse, serializeResponseBody, } from "./response-normalizer.js";
|
package/dist/interceptor.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
type InterceptRequestHandler = (method: Schmock.HttpMethod, path: string, requestOptions?: Schmock.RequestOptions) => Promise<Schmock.Response>;
|
|
2
|
+
interface InterceptRequestAdmission {
|
|
3
|
+
handle: InterceptRequestHandler;
|
|
4
|
+
release(): void;
|
|
5
|
+
}
|
|
1
6
|
/**
|
|
2
7
|
* Create a fetch interceptor that routes requests through mock.handle().
|
|
8
|
+
*
|
|
9
|
+
* `owner` identifies the mock behind the lease. Leases sharing an owner are
|
|
10
|
+
* consulted at most once per request, so a mock held by several leases runs
|
|
11
|
+
* its handler — and emits its lifecycle events — once per network request.
|
|
3
12
|
*/
|
|
4
|
-
export declare function createFetchInterceptor(handle:
|
|
13
|
+
export declare function createFetchInterceptor(handle: InterceptRequestHandler, options?: Schmock.InterceptOptions, admitRequest?: () => InterceptRequestAdmission, owner?: symbol): Schmock.InterceptHandle;
|
|
14
|
+
export {};
|
|
5
15
|
//# sourceMappingURL=interceptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"AAkCA,KAAK,uBAAuB,GAAG,CAC7B,MAAM,EAAE,OAAO,CAAC,UAAU,EAC1B,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,KACpC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAU/B,UAAU,yBAAyB;IACjC,MAAM,EAAE,uBAAuB,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC;CACjB;AAqYD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,uBAAuB,EAC/B,OAAO,GAAE,OAAO,CAAC,gBAAqB,EACtC,YAAY,CAAC,EAAE,MAAM,yBAAyB,EAC9C,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAqKzB"}
|