@crvouga/mockingbird-service-formbricks 2.2.0 → 2.3.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/CHANGELOG.md +23 -1
- package/dist/{chunk-XS5QMW2C.js → chunk-4KQ2ITDL.js} +2 -2
- package/dist/chunk-URWHM2ZP.js +5073 -0
- package/dist/chunk-URWHM2ZP.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +183 -179
- package/dist/index.js +1 -1
- package/dist/server.d.ts +302 -294
- package/dist/server.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-OFA5MXAJ.js +0 -5018
- package/dist/chunk-OFA5MXAJ.js.map +0 -7
- /package/dist/{chunk-XS5QMW2C.js.map → chunk-4KQ2ITDL.js.map} +0 -0
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -10,36 +10,6 @@ interface FetchAPI$1 {
|
|
|
10
10
|
fetch(request: Request): Promise<Response>;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* The single source of time for a service.
|
|
15
|
-
*
|
|
16
|
-
* Every timestamp a mock writes reads from here, so a suite moves time instead of
|
|
17
|
-
* sleeping: appointment windows, result delays and expiries become reachable in
|
|
18
|
-
* milliseconds. A frozen clock also makes timestamps reproducible from a seed.
|
|
19
|
-
*/
|
|
20
|
-
type ClockState = {
|
|
21
|
-
/** Current epoch milliseconds. */
|
|
22
|
-
now: number;
|
|
23
|
-
/** True while time does not advance on its own. */
|
|
24
|
-
frozen: boolean;
|
|
25
|
-
/** Milliseconds this clock adds to its underlying source. */
|
|
26
|
-
offsetMs: number;
|
|
27
|
-
};
|
|
28
|
-
type Clock = {
|
|
29
|
-
now(): number;
|
|
30
|
-
/** Pin the clock to an exact instant, keeping it frozen if it already was. */
|
|
31
|
-
set(epochMs: number): void;
|
|
32
|
-
/** Move the clock forward, or back with a negative delta. */
|
|
33
|
-
advance(deltaMs: number): void;
|
|
34
|
-
/** Stop time at the current instant. */
|
|
35
|
-
freeze(): void;
|
|
36
|
-
/** Resume from the current instant. */
|
|
37
|
-
unfreeze(): void;
|
|
38
|
-
/** Drop back to the underlying source, live. */
|
|
39
|
-
reset(): void;
|
|
40
|
-
state(): ClockState;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
13
|
/** Bind values accepted by Mockingbird's SQLite port (matches sqlite-mem / better-sqlite3). */
|
|
44
14
|
type SqliteValue$1 = null | number | bigint | string | Uint8Array | boolean;
|
|
45
15
|
/** Mutation counters returned by {@link SqliteStatement.run}. */
|
|
@@ -112,144 +82,16 @@ declare class Collection<T> {
|
|
|
112
82
|
}
|
|
113
83
|
|
|
114
84
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* mulberry32: small, fast, and stable across runtimes, which matters more here
|
|
119
|
-
* than statistical quality.
|
|
120
|
-
*/
|
|
121
|
-
type Rng = {
|
|
122
|
-
/** Next value in `[0, 1)`. */
|
|
123
|
-
next(): number;
|
|
124
|
-
/** Next integer in `[min, max]`. */
|
|
125
|
-
int(min: number, max: number): number;
|
|
126
|
-
/** Restart the stream from its seed. */
|
|
127
|
-
reset(): void;
|
|
128
|
-
/** Serializable engine state used by deterministic checkpoints. */
|
|
129
|
-
state(): number;
|
|
130
|
-
/** Restore a state previously returned by {@link state}. */
|
|
131
|
-
setState(state: number): void;
|
|
132
|
-
seed: number;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* A deliberate failure injected in front of an operation.
|
|
137
|
-
*
|
|
138
|
-
* This is how a suite reaches the vendor's failure modes without the vendor: the
|
|
139
|
-
* quota error that only appears when a shared sandbox is full, the 429 that only
|
|
140
|
-
* appears under load, the 5xx that proves a retry path works.
|
|
141
|
-
*/
|
|
142
|
-
type FaultRule = {
|
|
143
|
-
/** Stable id, so a suite can retire exactly the rule it added. */
|
|
144
|
-
id: string;
|
|
145
|
-
/** Fault only this operation. Omit to match every operation. */
|
|
146
|
-
operationId?: string;
|
|
147
|
-
/** Fault only this HTTP method, case-insensitive. Omit to match every method. */
|
|
148
|
-
method?: string;
|
|
149
|
-
/** Fault only paths starting with this prefix. Omit to match every path. */
|
|
150
|
-
pathPrefix?: string;
|
|
151
|
-
/**
|
|
152
|
-
* Fault only this namespace. Omit (or `"*"`) to fault every namespace — which is what
|
|
153
|
-
* an in-process caller usually wants, and what a parallel worker usually does not:
|
|
154
|
-
* rules added through `POST /__admin/faults` default to the calling namespace.
|
|
155
|
-
*/
|
|
156
|
-
namespace?: string;
|
|
157
|
-
/**
|
|
158
|
-
* Status of the injected response. Omit for a rule that only delays (`delayMs` /
|
|
159
|
-
* `latencyMs`), only drops the connection (`drop`), or only switches on an `effect`:
|
|
160
|
-
* the request then still reaches the service.
|
|
161
|
-
*/
|
|
162
|
-
status?: number;
|
|
163
|
-
/** Response body, serialized as JSON. A string is sent as-is. */
|
|
164
|
-
body?: unknown;
|
|
165
|
-
headers?: Record<string, string>;
|
|
166
|
-
/** Retire the rule after this many faults. Omit to keep it until removed. */
|
|
167
|
-
count?: number;
|
|
168
|
-
/** Fault this fraction of matching requests, `0`–`1`. Default `1`. */
|
|
169
|
-
rate?: number;
|
|
170
|
-
/** Hold the response back this long, to exercise timeouts. */
|
|
171
|
-
delayMs?: number;
|
|
172
|
-
/** Alias of `delayMs`. */
|
|
173
|
-
latencyMs?: number;
|
|
174
|
-
/**
|
|
175
|
-
* Drop the connection instead of answering: an in-process `fetch` rejects with a
|
|
176
|
-
* `TypeError`, and a served mock destroys the socket. Models "unknown outcome" failures.
|
|
177
|
-
*/
|
|
178
|
-
drop?: boolean;
|
|
179
|
-
/**
|
|
180
|
-
* A named service behaviour to switch on for the matching request instead of (or
|
|
181
|
-
* before) a canned response, e.g. `created_but_500` or `numeric_tracking_id`. Services
|
|
182
|
-
* read it with `faultEffects(request)`.
|
|
183
|
-
*/
|
|
184
|
-
effect?: string;
|
|
185
|
-
/** Parameters for `effect`. */
|
|
186
|
-
params?: Record<string, unknown>;
|
|
187
|
-
/** From the preset this rule was expanded from, if any. */
|
|
188
|
-
preset?: string;
|
|
189
|
-
};
|
|
190
|
-
/** A fault that fired for one request. */
|
|
191
|
-
type FaultHit = {
|
|
192
|
-
id: string;
|
|
193
|
-
/** The injected response; absent when the rule only delays, drops, or sets an effect. */
|
|
194
|
-
response?: Response;
|
|
195
|
-
drop?: boolean;
|
|
196
|
-
effect?: {
|
|
197
|
-
name: string;
|
|
198
|
-
params: Record<string, unknown>;
|
|
199
|
-
};
|
|
200
|
-
};
|
|
201
|
-
/**
|
|
202
|
-
* A named, documented fault a suite switches on by name
|
|
203
|
-
* (`POST /__admin/faults {"preset": "rate_limited"}`): one or more rules, and optionally a
|
|
204
|
-
* webhook delivery fault.
|
|
85
|
+
* Sequential id source persisted in SQLite. Ids are deterministic for a given
|
|
86
|
+
* sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
|
|
205
87
|
*/
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
};
|
|
214
|
-
/** What a request looks like to the fault matcher. */
|
|
215
|
-
type FaultCandidate = {
|
|
216
|
-
operationId: string | undefined;
|
|
217
|
-
method: string;
|
|
218
|
-
path: string;
|
|
219
|
-
namespace: string;
|
|
220
|
-
};
|
|
221
|
-
type FaultRegistry = {
|
|
222
|
-
isolateNamespaces(): void;
|
|
223
|
-
snapshot(namespace: string): {
|
|
224
|
-
rules: (FaultRule & {
|
|
225
|
-
remaining: number | null;
|
|
226
|
-
hits: number;
|
|
227
|
-
position: number;
|
|
228
|
-
})[];
|
|
229
|
-
rngState: number;
|
|
230
|
-
};
|
|
231
|
-
add(rule: FaultRule): FaultRule;
|
|
232
|
-
list(): (FaultRule & {
|
|
233
|
-
remaining: number | null;
|
|
234
|
-
hits: number;
|
|
235
|
-
})[];
|
|
236
|
-
remove(id: string): boolean;
|
|
237
|
-
clear(): void;
|
|
238
|
-
restore(namespace: string, state: {
|
|
239
|
-
rules: (FaultRule & {
|
|
240
|
-
remaining: number | null;
|
|
241
|
-
hits: number;
|
|
242
|
-
position: number;
|
|
243
|
-
})[];
|
|
244
|
-
rngState: number;
|
|
245
|
-
}): void;
|
|
246
|
-
/**
|
|
247
|
-
* Every fault this request should get, in rule order, stopping at the first that answers
|
|
248
|
-
* or drops (effect-only and delay-only rules let later rules match too). Consumes one of
|
|
249
|
-
* each matching rule's remaining uses.
|
|
250
|
-
*/
|
|
251
|
-
take(candidate: FaultCandidate): Promise<FaultHit[]>;
|
|
252
|
-
};
|
|
88
|
+
declare class IdSequence {
|
|
89
|
+
private readonly sqlite;
|
|
90
|
+
private readonly namespace;
|
|
91
|
+
private readonly salt;
|
|
92
|
+
constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
|
|
93
|
+
next(prefix: string, length?: number): string;
|
|
94
|
+
}
|
|
253
95
|
|
|
254
96
|
/** A stable identifier for a point in a {@link Timeline}. */
|
|
255
97
|
type CheckpointId = string;
|
|
@@ -588,6 +430,176 @@ type OperationContext = {
|
|
|
588
430
|
now: () => number;
|
|
589
431
|
};
|
|
590
432
|
|
|
433
|
+
/**
|
|
434
|
+
* The single source of time for a service.
|
|
435
|
+
*
|
|
436
|
+
* Every timestamp a mock writes reads from here, so a suite moves time instead of
|
|
437
|
+
* sleeping: appointment windows, result delays and expiries become reachable in
|
|
438
|
+
* milliseconds. A frozen clock also makes timestamps reproducible from a seed.
|
|
439
|
+
*/
|
|
440
|
+
type ClockState = {
|
|
441
|
+
/** Current epoch milliseconds. */
|
|
442
|
+
now: number;
|
|
443
|
+
/** True while time does not advance on its own. */
|
|
444
|
+
frozen: boolean;
|
|
445
|
+
/** Milliseconds this clock adds to its underlying source. */
|
|
446
|
+
offsetMs: number;
|
|
447
|
+
};
|
|
448
|
+
type Clock = {
|
|
449
|
+
now(): number;
|
|
450
|
+
/** Pin the clock to an exact instant, keeping it frozen if it already was. */
|
|
451
|
+
set(epochMs: number): void;
|
|
452
|
+
/** Move the clock forward, or back with a negative delta. */
|
|
453
|
+
advance(deltaMs: number): void;
|
|
454
|
+
/** Stop time at the current instant. */
|
|
455
|
+
freeze(): void;
|
|
456
|
+
/** Resume from the current instant. */
|
|
457
|
+
unfreeze(): void;
|
|
458
|
+
/** Drop back to the underlying source, live. */
|
|
459
|
+
reset(): void;
|
|
460
|
+
state(): ClockState;
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Seeded pseudo-random numbers, so anything a mock invents — ids, jitter, which
|
|
465
|
+
* request a percentage fault hits — is reproducible from a seed.
|
|
466
|
+
*
|
|
467
|
+
* mulberry32: small, fast, and stable across runtimes, which matters more here
|
|
468
|
+
* than statistical quality.
|
|
469
|
+
*/
|
|
470
|
+
type Rng = {
|
|
471
|
+
/** Next value in `[0, 1)`. */
|
|
472
|
+
next(): number;
|
|
473
|
+
/** Next integer in `[min, max]`. */
|
|
474
|
+
int(min: number, max: number): number;
|
|
475
|
+
/** Restart the stream from its seed. */
|
|
476
|
+
reset(): void;
|
|
477
|
+
/** Serializable engine state used by deterministic checkpoints. */
|
|
478
|
+
state(): number;
|
|
479
|
+
/** Restore a state previously returned by {@link state}. */
|
|
480
|
+
setState(state: number): void;
|
|
481
|
+
seed: number;
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* A deliberate failure injected in front of an operation.
|
|
486
|
+
*
|
|
487
|
+
* This is how a suite reaches the vendor's failure modes without the vendor: the
|
|
488
|
+
* quota error that only appears when a shared sandbox is full, the 429 that only
|
|
489
|
+
* appears under load, the 5xx that proves a retry path works.
|
|
490
|
+
*/
|
|
491
|
+
type FaultRule = {
|
|
492
|
+
/** Stable id, so a suite can retire exactly the rule it added. */
|
|
493
|
+
id: string;
|
|
494
|
+
/** Fault only this operation. Omit to match every operation. */
|
|
495
|
+
operationId?: string;
|
|
496
|
+
/** Fault only this HTTP method, case-insensitive. Omit to match every method. */
|
|
497
|
+
method?: string;
|
|
498
|
+
/** Fault only paths starting with this prefix. Omit to match every path. */
|
|
499
|
+
pathPrefix?: string;
|
|
500
|
+
/**
|
|
501
|
+
* Fault only this namespace. Omit (or `"*"`) to fault every namespace — which is what
|
|
502
|
+
* an in-process caller usually wants, and what a parallel worker usually does not:
|
|
503
|
+
* rules added through `POST /__admin/faults` default to the calling namespace.
|
|
504
|
+
*/
|
|
505
|
+
namespace?: string;
|
|
506
|
+
/**
|
|
507
|
+
* Status of the injected response. Omit for a rule that only delays (`delayMs` /
|
|
508
|
+
* `latencyMs`), only drops the connection (`drop`), or only switches on an `effect`:
|
|
509
|
+
* the request then still reaches the service.
|
|
510
|
+
*/
|
|
511
|
+
status?: number;
|
|
512
|
+
/** Response body, serialized as JSON. A string is sent as-is. */
|
|
513
|
+
body?: unknown;
|
|
514
|
+
headers?: Record<string, string>;
|
|
515
|
+
/** Retire the rule after this many faults. Omit to keep it until removed. */
|
|
516
|
+
count?: number;
|
|
517
|
+
/** Fault this fraction of matching requests, `0`–`1`. Default `1`. */
|
|
518
|
+
rate?: number;
|
|
519
|
+
/** Hold the response back this long, to exercise timeouts. */
|
|
520
|
+
delayMs?: number;
|
|
521
|
+
/** Alias of `delayMs`. */
|
|
522
|
+
latencyMs?: number;
|
|
523
|
+
/**
|
|
524
|
+
* Drop the connection instead of answering: an in-process `fetch` rejects with a
|
|
525
|
+
* `TypeError`, and a served mock destroys the socket. Models "unknown outcome" failures.
|
|
526
|
+
*/
|
|
527
|
+
drop?: boolean;
|
|
528
|
+
/**
|
|
529
|
+
* A named service behaviour to switch on for the matching request instead of (or
|
|
530
|
+
* before) a canned response, e.g. `created_but_500` or `numeric_tracking_id`. Services
|
|
531
|
+
* read it with `faultEffects(request)`.
|
|
532
|
+
*/
|
|
533
|
+
effect?: string;
|
|
534
|
+
/** Parameters for `effect`. */
|
|
535
|
+
params?: Record<string, unknown>;
|
|
536
|
+
/** From the preset this rule was expanded from, if any. */
|
|
537
|
+
preset?: string;
|
|
538
|
+
};
|
|
539
|
+
/** A fault that fired for one request. */
|
|
540
|
+
type FaultHit = {
|
|
541
|
+
id: string;
|
|
542
|
+
/** The injected response; absent when the rule only delays, drops, or sets an effect. */
|
|
543
|
+
response?: Response;
|
|
544
|
+
drop?: boolean;
|
|
545
|
+
effect?: {
|
|
546
|
+
name: string;
|
|
547
|
+
params: Record<string, unknown>;
|
|
548
|
+
};
|
|
549
|
+
};
|
|
550
|
+
/**
|
|
551
|
+
* A named, documented fault a suite switches on by name
|
|
552
|
+
* (`POST /__admin/faults {"preset": "rate_limited"}`): one or more rules, and optionally a
|
|
553
|
+
* webhook delivery fault.
|
|
554
|
+
*/
|
|
555
|
+
type FaultPreset = {
|
|
556
|
+
description: string;
|
|
557
|
+
rules?: Omit<FaultRule, "id">[];
|
|
558
|
+
webhook?: {
|
|
559
|
+
mode: "duplicate" | "reorder" | "drop";
|
|
560
|
+
count?: number;
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
/** What a request looks like to the fault matcher. */
|
|
564
|
+
type FaultCandidate = {
|
|
565
|
+
operationId: string | undefined;
|
|
566
|
+
method: string;
|
|
567
|
+
path: string;
|
|
568
|
+
namespace: string;
|
|
569
|
+
};
|
|
570
|
+
type FaultRegistry = {
|
|
571
|
+
isolateNamespaces(): void;
|
|
572
|
+
snapshot(namespace: string): {
|
|
573
|
+
rules: (FaultRule & {
|
|
574
|
+
remaining: number | null;
|
|
575
|
+
hits: number;
|
|
576
|
+
position: number;
|
|
577
|
+
})[];
|
|
578
|
+
rngState: number;
|
|
579
|
+
};
|
|
580
|
+
add(rule: FaultRule): FaultRule;
|
|
581
|
+
list(): (FaultRule & {
|
|
582
|
+
remaining: number | null;
|
|
583
|
+
hits: number;
|
|
584
|
+
})[];
|
|
585
|
+
remove(id: string): boolean;
|
|
586
|
+
clear(): void;
|
|
587
|
+
restore(namespace: string, state: {
|
|
588
|
+
rules: (FaultRule & {
|
|
589
|
+
remaining: number | null;
|
|
590
|
+
hits: number;
|
|
591
|
+
position: number;
|
|
592
|
+
})[];
|
|
593
|
+
rngState: number;
|
|
594
|
+
}): void;
|
|
595
|
+
/**
|
|
596
|
+
* Every fault this request should get, in rule order, stopping at the first that answers
|
|
597
|
+
* or drops (effect-only and delay-only rules let later rules match too). Consumes one of
|
|
598
|
+
* each matching rule's remaining uses.
|
|
599
|
+
*/
|
|
600
|
+
take(candidate: FaultCandidate): Promise<FaultHit[]>;
|
|
601
|
+
};
|
|
602
|
+
|
|
591
603
|
/**
|
|
592
604
|
* One problem with a request body, at a dotted path (`patient.address.city`, `items.0.sku`).
|
|
593
605
|
* `kind` is `media_type` when the body is present but its media type is not one the operation
|
|
@@ -629,6 +641,10 @@ type RequestLog = {
|
|
|
629
641
|
ids?: Record<string, string>;
|
|
630
642
|
/** Set when the service created a resource the request referred to but that did not exist. */
|
|
631
643
|
adopted?: boolean;
|
|
644
|
+
/** Explicit durable acceptance, independent of response delivery. */
|
|
645
|
+
accepted?: boolean;
|
|
646
|
+
/** Checkpoint captured at explicit acceptance. */
|
|
647
|
+
checkpoint?: string;
|
|
632
648
|
/** Set on a rejection (status ≥ 400) the mock produced itself, never on a scripted fault. */
|
|
633
649
|
request?: RejectedRequest;
|
|
634
650
|
/** The validation issues behind a rejection, when the service found any. */
|
|
@@ -692,18 +708,6 @@ type CredentialRegistry = {
|
|
|
692
708
|
}[];
|
|
693
709
|
};
|
|
694
710
|
|
|
695
|
-
/**
|
|
696
|
-
* Sequential id source persisted in SQLite. Ids are deterministic for a given
|
|
697
|
-
* sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
|
|
698
|
-
*/
|
|
699
|
-
declare class IdSequence {
|
|
700
|
-
private readonly sqlite;
|
|
701
|
-
private readonly namespace;
|
|
702
|
-
private readonly salt;
|
|
703
|
-
constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
|
|
704
|
-
next(prefix: string, length?: number): string;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
711
|
/**
|
|
708
712
|
* A point-in-time copy of everything a service namespace holds.
|
|
709
713
|
*
|