@crvouga/mockingbird-service-rxvortex 1.0.0 → 1.1.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/CHANGELOG.md +13 -4
- package/README.md +15 -5
- package/dist/{chunk-DNELVPK4.js → chunk-5KK6W2PE.js} +229 -51
- package/dist/chunk-5KK6W2PE.js.map +7 -0
- package/dist/{chunk-ZAM35JQO.js → chunk-XAWKEXKJ.js} +40 -4
- package/dist/chunk-XAWKEXKJ.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +160 -103
- package/dist/index.js +5 -1
- package/dist/server.d.ts +272 -193
- package/dist/server.js +4 -2
- package/package.json +2 -2
- package/dist/chunk-DNELVPK4.js.map +0 -7
- package/dist/chunk-ZAM35JQO.js.map +0 -7
package/dist/server.d.ts
CHANGED
|
@@ -170,82 +170,6 @@ type FaultRegistry$1 = {
|
|
|
170
170
|
take(candidate: FaultCandidate$1): Promise<FaultHit$1[]>;
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
-
/** One handled request, as the structured log sees it. */
|
|
174
|
-
type RequestLog$1 = {
|
|
175
|
-
service: string;
|
|
176
|
-
namespace: string;
|
|
177
|
-
operationId: string | undefined;
|
|
178
|
-
method: string;
|
|
179
|
-
path: string;
|
|
180
|
-
status: number;
|
|
181
|
-
durationMs: number;
|
|
182
|
-
/** True when the path matched no operation in the contract. */
|
|
183
|
-
unmatched: boolean;
|
|
184
|
-
/** Set when a fault rule produced the response. */
|
|
185
|
-
faultId?: string;
|
|
186
|
-
/** Resource ids the handler touched (`userId`, `orderId`, …), when the service reports them. */
|
|
187
|
-
ids?: Record<string, string>;
|
|
188
|
-
/** Set when the service created a resource the request referred to but that did not exist. */
|
|
189
|
-
adopted?: boolean;
|
|
190
|
-
};
|
|
191
|
-
type MetricsReport$1 = {
|
|
192
|
-
requests: number;
|
|
193
|
-
/** Counts keyed `<operationId> <status>`. */
|
|
194
|
-
byOperation: Record<string, number>;
|
|
195
|
-
/**
|
|
196
|
-
* Paths that matched no operation, most frequent first.
|
|
197
|
-
*
|
|
198
|
-
* This is the early-warning signal: a consumer calling something the mock does
|
|
199
|
-
* not implement shows up here as a count, before it fails a suite as a 404.
|
|
200
|
-
*/
|
|
201
|
-
unmatched: {
|
|
202
|
-
method: string;
|
|
203
|
-
path: string;
|
|
204
|
-
count: number;
|
|
205
|
-
}[];
|
|
206
|
-
faults: number;
|
|
207
|
-
totalDurationMs: number;
|
|
208
|
-
};
|
|
209
|
-
type Metrics$1 = {
|
|
210
|
-
record(entry: RequestLog$1): void;
|
|
211
|
-
report(): MetricsReport$1;
|
|
212
|
-
reset(): void;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
/** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
|
|
216
|
-
type JournalEntry$1 = RequestLog$1 & {
|
|
217
|
-
at: string;
|
|
218
|
-
};
|
|
219
|
-
type JournalQuery$1 = {
|
|
220
|
-
/** Only this namespace. Omit for every namespace, oldest first across all of them. */
|
|
221
|
-
namespace?: string;
|
|
222
|
-
operationId?: string;
|
|
223
|
-
status?: number;
|
|
224
|
-
/** Only entries at or after this instant (epoch ms). */
|
|
225
|
-
since?: number;
|
|
226
|
-
/** At most this many, the most recent kept. */
|
|
227
|
-
limit?: number;
|
|
228
|
-
};
|
|
229
|
-
type Journal$1 = {
|
|
230
|
-
readonly size: number;
|
|
231
|
-
record(entry: JournalEntry$1): void;
|
|
232
|
-
list(query?: JournalQuery$1): JournalEntry$1[];
|
|
233
|
-
/** Forget one namespace's entries, or every namespace's. */
|
|
234
|
-
clear(namespace?: string): void;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
/** Credential → namespace mapping behind `PUT /__admin/credentials`. */
|
|
238
|
-
type CredentialRegistry$1 = {
|
|
239
|
-
set(credential: string, namespace: string): void;
|
|
240
|
-
get(credential: string): string | undefined;
|
|
241
|
-
remove(credential: string): boolean;
|
|
242
|
-
clear(): void;
|
|
243
|
-
entries(): {
|
|
244
|
-
credential: string;
|
|
245
|
-
namespace: string;
|
|
246
|
-
}[];
|
|
247
|
-
};
|
|
248
|
-
|
|
249
173
|
/** A stable identifier for a point in a {@link Timeline}. */
|
|
250
174
|
type CheckpointId$1 = string;
|
|
251
175
|
/** An immutable node in a timeline's checkpoint DAG. */
|
|
@@ -336,6 +260,110 @@ interface FetchAPI$2 {
|
|
|
336
260
|
fetch(request: Request): Promise<Response>;
|
|
337
261
|
}
|
|
338
262
|
|
|
263
|
+
/**
|
|
264
|
+
* One problem with a request body, at a dotted path (`patient.address.city`, `items.0.sku`).
|
|
265
|
+
* `kind` is `media_type` when the body is present but its media type is not one the operation
|
|
266
|
+
* accepts (a `415` on most vendors), `syntax` when it could not be decoded, `required` when
|
|
267
|
+
* the operation needs a body and none arrived, and `schema` for a contract violation.
|
|
268
|
+
*/
|
|
269
|
+
type BodyIssue$1 = {
|
|
270
|
+
path: string;
|
|
271
|
+
message: string;
|
|
272
|
+
kind?: "media_type" | "syntax" | "required" | "schema";
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* What the mock received from a request it rejected, so a 4xx can be attributed after the
|
|
277
|
+
* fact (an empty body, a missing `content-type`, a schema violation) without logging the body.
|
|
278
|
+
*/
|
|
279
|
+
type RejectedRequest$1 = {
|
|
280
|
+
/** The raw `content-type` header, or `null` when the request sent none. */
|
|
281
|
+
contentType: string | null;
|
|
282
|
+
/** Bytes of body received from `content-length` (`0` for none), or `null` when the client sent no length (a streamed / chunked body). */
|
|
283
|
+
bodyBytes: number | null;
|
|
284
|
+
/** The raw `transfer-encoding` header (`chunked`), or `null`. */
|
|
285
|
+
transferEncoding: string | null;
|
|
286
|
+
};
|
|
287
|
+
/** One handled request, as the structured log sees it. */
|
|
288
|
+
type RequestLog$1 = {
|
|
289
|
+
service: string;
|
|
290
|
+
namespace: string;
|
|
291
|
+
operationId: string | undefined;
|
|
292
|
+
method: string;
|
|
293
|
+
path: string;
|
|
294
|
+
status: number;
|
|
295
|
+
durationMs: number;
|
|
296
|
+
/** True when the path matched no operation in the contract. */
|
|
297
|
+
unmatched: boolean;
|
|
298
|
+
/** Set when a fault rule produced the response. */
|
|
299
|
+
faultId?: string;
|
|
300
|
+
/** Resource ids the handler touched (`userId`, `orderId`, …), when the service reports them. */
|
|
301
|
+
ids?: Record<string, string>;
|
|
302
|
+
/** Set when the service created a resource the request referred to but that did not exist. */
|
|
303
|
+
adopted?: boolean;
|
|
304
|
+
/** Set on a rejection (status ≥ 400) the mock produced itself, never on a scripted fault. */
|
|
305
|
+
request?: RejectedRequest$1;
|
|
306
|
+
/** The validation issues behind a rejection, when the service found any. */
|
|
307
|
+
issues?: BodyIssue$1[];
|
|
308
|
+
};
|
|
309
|
+
type MetricsReport$1 = {
|
|
310
|
+
requests: number;
|
|
311
|
+
/** Counts keyed `<operationId> <status>`. */
|
|
312
|
+
byOperation: Record<string, number>;
|
|
313
|
+
/**
|
|
314
|
+
* Paths that matched no operation, most frequent first.
|
|
315
|
+
*
|
|
316
|
+
* This is the early-warning signal: a consumer calling something the mock does
|
|
317
|
+
* not implement shows up here as a count, before it fails a suite as a 404.
|
|
318
|
+
*/
|
|
319
|
+
unmatched: {
|
|
320
|
+
method: string;
|
|
321
|
+
path: string;
|
|
322
|
+
count: number;
|
|
323
|
+
}[];
|
|
324
|
+
faults: number;
|
|
325
|
+
totalDurationMs: number;
|
|
326
|
+
};
|
|
327
|
+
type Metrics$1 = {
|
|
328
|
+
record(entry: RequestLog$1): void;
|
|
329
|
+
report(): MetricsReport$1;
|
|
330
|
+
reset(): void;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
|
|
334
|
+
type JournalEntry$1 = RequestLog$1 & {
|
|
335
|
+
at: string;
|
|
336
|
+
};
|
|
337
|
+
type JournalQuery$1 = {
|
|
338
|
+
/** Only this namespace. Omit for every namespace, oldest first across all of them. */
|
|
339
|
+
namespace?: string;
|
|
340
|
+
operationId?: string;
|
|
341
|
+
status?: number;
|
|
342
|
+
/** Only entries at or after this instant (epoch ms). */
|
|
343
|
+
since?: number;
|
|
344
|
+
/** At most this many, the most recent kept. */
|
|
345
|
+
limit?: number;
|
|
346
|
+
};
|
|
347
|
+
type Journal$1 = {
|
|
348
|
+
readonly size: number;
|
|
349
|
+
record(entry: JournalEntry$1): void;
|
|
350
|
+
list(query?: JournalQuery$1): JournalEntry$1[];
|
|
351
|
+
/** Forget one namespace's entries, or every namespace's. */
|
|
352
|
+
clear(namespace?: string): void;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/** Credential → namespace mapping behind `PUT /__admin/credentials`. */
|
|
356
|
+
type CredentialRegistry$1 = {
|
|
357
|
+
set(credential: string, namespace: string): void;
|
|
358
|
+
get(credential: string): string | undefined;
|
|
359
|
+
remove(credential: string): boolean;
|
|
360
|
+
clear(): void;
|
|
361
|
+
entries(): {
|
|
362
|
+
credential: string;
|
|
363
|
+
namespace: string;
|
|
364
|
+
}[];
|
|
365
|
+
};
|
|
366
|
+
|
|
339
367
|
/**
|
|
340
368
|
* A point-in-time copy of everything a service namespace holds.
|
|
341
369
|
*
|
|
@@ -523,6 +551,20 @@ type Listening = {
|
|
|
523
551
|
close(): Promise<void>;
|
|
524
552
|
};
|
|
525
553
|
|
|
554
|
+
/** One preset catalog row, in the field names `GET /api/v1/preset-catalog-items` uses. */
|
|
555
|
+
type CatalogItem = {
|
|
556
|
+
catalog_id: string;
|
|
557
|
+
medication_name: string;
|
|
558
|
+
medication_strength: string | null;
|
|
559
|
+
package_size: string | null;
|
|
560
|
+
quantity: number | null;
|
|
561
|
+
quantity_units: string | null;
|
|
562
|
+
medication_form: string | null;
|
|
563
|
+
route: string | null;
|
|
564
|
+
states: string[];
|
|
565
|
+
status: "active" | "inactive";
|
|
566
|
+
};
|
|
567
|
+
|
|
526
568
|
/**
|
|
527
569
|
* The single source of time for a service.
|
|
528
570
|
*
|
|
@@ -728,94 +770,6 @@ type FaultRegistry = {
|
|
|
728
770
|
take(candidate: FaultCandidate): Promise<FaultHit[]>;
|
|
729
771
|
};
|
|
730
772
|
|
|
731
|
-
/** One handled request, as the structured log sees it. */
|
|
732
|
-
type RequestLog = {
|
|
733
|
-
service: string;
|
|
734
|
-
namespace: string;
|
|
735
|
-
operationId: string | undefined;
|
|
736
|
-
method: string;
|
|
737
|
-
path: string;
|
|
738
|
-
status: number;
|
|
739
|
-
durationMs: number;
|
|
740
|
-
/** True when the path matched no operation in the contract. */
|
|
741
|
-
unmatched: boolean;
|
|
742
|
-
/** Set when a fault rule produced the response. */
|
|
743
|
-
faultId?: string;
|
|
744
|
-
/** Resource ids the handler touched (`userId`, `orderId`, …), when the service reports them. */
|
|
745
|
-
ids?: Record<string, string>;
|
|
746
|
-
/** Set when the service created a resource the request referred to but that did not exist. */
|
|
747
|
-
adopted?: boolean;
|
|
748
|
-
};
|
|
749
|
-
type MetricsReport = {
|
|
750
|
-
requests: number;
|
|
751
|
-
/** Counts keyed `<operationId> <status>`. */
|
|
752
|
-
byOperation: Record<string, number>;
|
|
753
|
-
/**
|
|
754
|
-
* Paths that matched no operation, most frequent first.
|
|
755
|
-
*
|
|
756
|
-
* This is the early-warning signal: a consumer calling something the mock does
|
|
757
|
-
* not implement shows up here as a count, before it fails a suite as a 404.
|
|
758
|
-
*/
|
|
759
|
-
unmatched: {
|
|
760
|
-
method: string;
|
|
761
|
-
path: string;
|
|
762
|
-
count: number;
|
|
763
|
-
}[];
|
|
764
|
-
faults: number;
|
|
765
|
-
totalDurationMs: number;
|
|
766
|
-
};
|
|
767
|
-
type Metrics = {
|
|
768
|
-
record(entry: RequestLog): void;
|
|
769
|
-
report(): MetricsReport;
|
|
770
|
-
reset(): void;
|
|
771
|
-
};
|
|
772
|
-
|
|
773
|
-
/** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
|
|
774
|
-
type JournalEntry = RequestLog & {
|
|
775
|
-
at: string;
|
|
776
|
-
};
|
|
777
|
-
type JournalQuery = {
|
|
778
|
-
/** Only this namespace. Omit for every namespace, oldest first across all of them. */
|
|
779
|
-
namespace?: string;
|
|
780
|
-
operationId?: string;
|
|
781
|
-
status?: number;
|
|
782
|
-
/** Only entries at or after this instant (epoch ms). */
|
|
783
|
-
since?: number;
|
|
784
|
-
/** At most this many, the most recent kept. */
|
|
785
|
-
limit?: number;
|
|
786
|
-
};
|
|
787
|
-
type Journal = {
|
|
788
|
-
readonly size: number;
|
|
789
|
-
record(entry: JournalEntry): void;
|
|
790
|
-
list(query?: JournalQuery): JournalEntry[];
|
|
791
|
-
/** Forget one namespace's entries, or every namespace's. */
|
|
792
|
-
clear(namespace?: string): void;
|
|
793
|
-
};
|
|
794
|
-
|
|
795
|
-
/** Credential → namespace mapping behind `PUT /__admin/credentials`. */
|
|
796
|
-
type CredentialRegistry = {
|
|
797
|
-
set(credential: string, namespace: string): void;
|
|
798
|
-
get(credential: string): string | undefined;
|
|
799
|
-
remove(credential: string): boolean;
|
|
800
|
-
clear(): void;
|
|
801
|
-
entries(): {
|
|
802
|
-
credential: string;
|
|
803
|
-
namespace: string;
|
|
804
|
-
}[];
|
|
805
|
-
};
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* Sequential id source persisted in SQLite. Ids are deterministic for a given
|
|
809
|
-
* sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
|
|
810
|
-
*/
|
|
811
|
-
declare class IdSequence {
|
|
812
|
-
private readonly sqlite;
|
|
813
|
-
private readonly namespace;
|
|
814
|
-
private readonly salt;
|
|
815
|
-
constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
|
|
816
|
-
next(prefix: string, length?: number): string;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
773
|
/** A stable identifier for a point in a {@link Timeline}. */
|
|
820
774
|
type CheckpointId = string;
|
|
821
775
|
/** An immutable node in a timeline's checkpoint DAG. */
|
|
@@ -906,6 +860,135 @@ interface FetchAPI$1 {
|
|
|
906
860
|
fetch(request: Request): Promise<Response>;
|
|
907
861
|
}
|
|
908
862
|
|
|
863
|
+
/** Options every provider constructor accepts. */
|
|
864
|
+
type APIOptions = {
|
|
865
|
+
/** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */
|
|
866
|
+
sqlite?: SqliteClient$1;
|
|
867
|
+
/** Clock used for `created`-style fields. Default `Date.now`. */
|
|
868
|
+
now?: () => number;
|
|
869
|
+
/**
|
|
870
|
+
* Storage namespace for this instance's records. Instances sharing one SQLite
|
|
871
|
+
* client stay isolated when their namespaces differ. Defaults to the service name.
|
|
872
|
+
*/
|
|
873
|
+
namespace?: string;
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* One problem with a request body, at a dotted path (`patient.address.city`, `items.0.sku`).
|
|
878
|
+
* `kind` is `media_type` when the body is present but its media type is not one the operation
|
|
879
|
+
* accepts (a `415` on most vendors), `syntax` when it could not be decoded, `required` when
|
|
880
|
+
* the operation needs a body and none arrived, and `schema` for a contract violation.
|
|
881
|
+
*/
|
|
882
|
+
type BodyIssue = {
|
|
883
|
+
path: string;
|
|
884
|
+
message: string;
|
|
885
|
+
kind?: "media_type" | "syntax" | "required" | "schema";
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* What the mock received from a request it rejected, so a 4xx can be attributed after the
|
|
890
|
+
* fact (an empty body, a missing `content-type`, a schema violation) without logging the body.
|
|
891
|
+
*/
|
|
892
|
+
type RejectedRequest = {
|
|
893
|
+
/** The raw `content-type` header, or `null` when the request sent none. */
|
|
894
|
+
contentType: string | null;
|
|
895
|
+
/** Bytes of body received from `content-length` (`0` for none), or `null` when the client sent no length (a streamed / chunked body). */
|
|
896
|
+
bodyBytes: number | null;
|
|
897
|
+
/** The raw `transfer-encoding` header (`chunked`), or `null`. */
|
|
898
|
+
transferEncoding: string | null;
|
|
899
|
+
};
|
|
900
|
+
/** One handled request, as the structured log sees it. */
|
|
901
|
+
type RequestLog = {
|
|
902
|
+
service: string;
|
|
903
|
+
namespace: string;
|
|
904
|
+
operationId: string | undefined;
|
|
905
|
+
method: string;
|
|
906
|
+
path: string;
|
|
907
|
+
status: number;
|
|
908
|
+
durationMs: number;
|
|
909
|
+
/** True when the path matched no operation in the contract. */
|
|
910
|
+
unmatched: boolean;
|
|
911
|
+
/** Set when a fault rule produced the response. */
|
|
912
|
+
faultId?: string;
|
|
913
|
+
/** Resource ids the handler touched (`userId`, `orderId`, …), when the service reports them. */
|
|
914
|
+
ids?: Record<string, string>;
|
|
915
|
+
/** Set when the service created a resource the request referred to but that did not exist. */
|
|
916
|
+
adopted?: boolean;
|
|
917
|
+
/** Set on a rejection (status ≥ 400) the mock produced itself, never on a scripted fault. */
|
|
918
|
+
request?: RejectedRequest;
|
|
919
|
+
/** The validation issues behind a rejection, when the service found any. */
|
|
920
|
+
issues?: BodyIssue[];
|
|
921
|
+
};
|
|
922
|
+
type MetricsReport = {
|
|
923
|
+
requests: number;
|
|
924
|
+
/** Counts keyed `<operationId> <status>`. */
|
|
925
|
+
byOperation: Record<string, number>;
|
|
926
|
+
/**
|
|
927
|
+
* Paths that matched no operation, most frequent first.
|
|
928
|
+
*
|
|
929
|
+
* This is the early-warning signal: a consumer calling something the mock does
|
|
930
|
+
* not implement shows up here as a count, before it fails a suite as a 404.
|
|
931
|
+
*/
|
|
932
|
+
unmatched: {
|
|
933
|
+
method: string;
|
|
934
|
+
path: string;
|
|
935
|
+
count: number;
|
|
936
|
+
}[];
|
|
937
|
+
faults: number;
|
|
938
|
+
totalDurationMs: number;
|
|
939
|
+
};
|
|
940
|
+
type Metrics = {
|
|
941
|
+
record(entry: RequestLog): void;
|
|
942
|
+
report(): MetricsReport;
|
|
943
|
+
reset(): void;
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
/** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
|
|
947
|
+
type JournalEntry = RequestLog & {
|
|
948
|
+
at: string;
|
|
949
|
+
};
|
|
950
|
+
type JournalQuery = {
|
|
951
|
+
/** Only this namespace. Omit for every namespace, oldest first across all of them. */
|
|
952
|
+
namespace?: string;
|
|
953
|
+
operationId?: string;
|
|
954
|
+
status?: number;
|
|
955
|
+
/** Only entries at or after this instant (epoch ms). */
|
|
956
|
+
since?: number;
|
|
957
|
+
/** At most this many, the most recent kept. */
|
|
958
|
+
limit?: number;
|
|
959
|
+
};
|
|
960
|
+
type Journal = {
|
|
961
|
+
readonly size: number;
|
|
962
|
+
record(entry: JournalEntry): void;
|
|
963
|
+
list(query?: JournalQuery): JournalEntry[];
|
|
964
|
+
/** Forget one namespace's entries, or every namespace's. */
|
|
965
|
+
clear(namespace?: string): void;
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
/** Credential → namespace mapping behind `PUT /__admin/credentials`. */
|
|
969
|
+
type CredentialRegistry = {
|
|
970
|
+
set(credential: string, namespace: string): void;
|
|
971
|
+
get(credential: string): string | undefined;
|
|
972
|
+
remove(credential: string): boolean;
|
|
973
|
+
clear(): void;
|
|
974
|
+
entries(): {
|
|
975
|
+
credential: string;
|
|
976
|
+
namespace: string;
|
|
977
|
+
}[];
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Sequential id source persisted in SQLite. Ids are deterministic for a given
|
|
982
|
+
* sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
|
|
983
|
+
*/
|
|
984
|
+
declare class IdSequence {
|
|
985
|
+
private readonly sqlite;
|
|
986
|
+
private readonly namespace;
|
|
987
|
+
private readonly salt;
|
|
988
|
+
constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
|
|
989
|
+
next(prefix: string, length?: number): string;
|
|
990
|
+
}
|
|
991
|
+
|
|
909
992
|
/**
|
|
910
993
|
* A point-in-time copy of everything a service namespace holds.
|
|
911
994
|
*
|
|
@@ -1056,19 +1139,6 @@ type ServiceRuntime<T extends ServiceInstance> = FetchAPI$1 & {
|
|
|
1056
1139
|
timeline(namespace?: string): Timeline<ServiceTimelineState>;
|
|
1057
1140
|
};
|
|
1058
1141
|
|
|
1059
|
-
/** Options every provider constructor accepts. */
|
|
1060
|
-
type APIOptions = {
|
|
1061
|
-
/** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */
|
|
1062
|
-
sqlite?: SqliteClient$1;
|
|
1063
|
-
/** Clock used for `created`-style fields. Default `Date.now`. */
|
|
1064
|
-
now?: () => number;
|
|
1065
|
-
/**
|
|
1066
|
-
* Storage namespace for this instance's records. Instances sharing one SQLite
|
|
1067
|
-
* client stay isolated when their namespaces differ. Defaults to the service name.
|
|
1068
|
-
*/
|
|
1069
|
-
namespace?: string;
|
|
1070
|
-
};
|
|
1071
|
-
|
|
1072
1142
|
/** Bind values accepted by Mockingbird's SQLite port (matches sqlite-mem / better-sqlite3). */
|
|
1073
1143
|
type SqliteValue = null | number | bigint | string | Uint8Array | boolean;
|
|
1074
1144
|
/** Mutation counters returned by {@link SqliteStatement.run}. */
|
|
@@ -1098,20 +1168,6 @@ interface SqliteClient {
|
|
|
1098
1168
|
transaction<T>(fn: () => T): T;
|
|
1099
1169
|
}
|
|
1100
1170
|
|
|
1101
|
-
/** One preset catalog row, in the field names `GET /api/v1/preset-catalog-items` uses. */
|
|
1102
|
-
type CatalogItem = {
|
|
1103
|
-
catalog_id: string;
|
|
1104
|
-
medication_name: string;
|
|
1105
|
-
medication_strength: string | null;
|
|
1106
|
-
package_size: string | null;
|
|
1107
|
-
quantity: number | null;
|
|
1108
|
-
quantity_units: string | null;
|
|
1109
|
-
medication_form: string | null;
|
|
1110
|
-
route: string | null;
|
|
1111
|
-
states: string[];
|
|
1112
|
-
status: "active" | "inactive";
|
|
1113
|
-
};
|
|
1114
|
-
|
|
1115
1171
|
/**
|
|
1116
1172
|
* Anything that can answer a Fetch `Request` with a `Response`.
|
|
1117
1173
|
*
|
|
@@ -1164,6 +1220,12 @@ type Settings = {
|
|
|
1164
1220
|
client_secret: string;
|
|
1165
1221
|
}[];
|
|
1166
1222
|
autoAdvance: AutoAdvance | null;
|
|
1223
|
+
/**
|
|
1224
|
+
* What a submit does with a well-formed `preset_catalog_id` the catalog does not hold:
|
|
1225
|
+
* `"reject"` answers 422 as the sandbox does; `"accept"` adds it as an active row named
|
|
1226
|
+
* after the request's `medication_name`. Inactive rows are refused either way.
|
|
1227
|
+
*/
|
|
1228
|
+
unknownPresets: "reject" | "accept";
|
|
1167
1229
|
};
|
|
1168
1230
|
declare class RxVortexState {
|
|
1169
1231
|
private readonly seed;
|
|
@@ -1172,11 +1234,14 @@ declare class RxVortexState {
|
|
|
1172
1234
|
readonly settings: Collection<Settings>;
|
|
1173
1235
|
readonly ids: IdSequence;
|
|
1174
1236
|
constructor(sqlite: SqliteClient, namespace: string, seed: {
|
|
1175
|
-
catalog: readonly CatalogItem[];
|
|
1237
|
+
catalog: readonly CatalogItem[] | undefined;
|
|
1176
1238
|
settings: Partial<Settings>;
|
|
1177
1239
|
});
|
|
1178
1240
|
/** Re-apply the catalog and settings after a reset. */
|
|
1179
1241
|
ensureSeeded(): void;
|
|
1242
|
+
/** Load rows: `replace` drops every other row first, `merge` upserts by `catalog_id`. */
|
|
1243
|
+
putCatalog(items: readonly CatalogItem[], mode: "replace" | "merge"): number;
|
|
1244
|
+
catalogRows(): CatalogItem[];
|
|
1180
1245
|
current(): Settings;
|
|
1181
1246
|
update(patch: Partial<Settings>): Settings;
|
|
1182
1247
|
/** By vendor tracking id first, then by our sender order id (the recovery lookup). */
|
|
@@ -1235,6 +1300,11 @@ declare class RxVortexAPI implements FetchAPI {
|
|
|
1235
1300
|
private iso;
|
|
1236
1301
|
private generateToken;
|
|
1237
1302
|
private createOrder;
|
|
1303
|
+
/**
|
|
1304
|
+
* Under `unknownPresets: "accept"`, a well-formed preset id the catalog lacks becomes an
|
|
1305
|
+
* active row described by the request, so later submits and catalog reads see it.
|
|
1306
|
+
*/
|
|
1307
|
+
private adoptPreset;
|
|
1238
1308
|
private getOrder;
|
|
1239
1309
|
private cancelOrder;
|
|
1240
1310
|
/** Move an order to a vendor status, set the three fields coherently, emit the webhook. */
|
|
@@ -1253,6 +1323,10 @@ type RxVortexRuntimeOptions = {
|
|
|
1253
1323
|
seed?: number | string;
|
|
1254
1324
|
adminKey?: string;
|
|
1255
1325
|
onLog?: (entry: RequestLog) => void;
|
|
1326
|
+
/**
|
|
1327
|
+
* Rows every namespace starts with, and returns to on `POST /__admin/reset` (`serve
|
|
1328
|
+
* --catalog <file>`). Default: `DEFAULT_CATALOG`.
|
|
1329
|
+
*/
|
|
1256
1330
|
catalog?: readonly CatalogItem[];
|
|
1257
1331
|
settings?: Partial<Settings>;
|
|
1258
1332
|
/** Where status webhooks go (`POST /prescriptions/webhooks/rxvortex`), sent with the secret header. */
|
|
@@ -1287,8 +1361,13 @@ type RxVortexServer = Listening & {
|
|
|
1287
1361
|
};
|
|
1288
1362
|
/** Serve the RxVortex mock over `node:http`, with auto-advance ticking every 100 ms. */
|
|
1289
1363
|
declare const createServer: (options?: RxVortexServerOptions) => Promise<RxVortexServer>;
|
|
1364
|
+
/**
|
|
1365
|
+
* Read a catalog file: a JSON array of rows, or the `{data: [...]}` body
|
|
1366
|
+
* `GET /api/v1/preset-catalog-items` answers with, so a recorded response loads as-is.
|
|
1367
|
+
*/
|
|
1368
|
+
declare const loadCatalogFile: (path: string) => CatalogItem[];
|
|
1290
1369
|
/** How `serve` (and `serve --config`) builds the RxVortex mock from flags. */
|
|
1291
1370
|
declare const serveTarget: ServeTarget;
|
|
1292
1371
|
|
|
1293
|
-
export { DEFAULT_PORT, createServer, serveTarget };
|
|
1372
|
+
export { DEFAULT_PORT, createServer, loadCatalogFile, serveTarget };
|
|
1294
1373
|
export type { RxVortexServer, RxVortexServerOptions };
|
package/dist/server.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_PORT,
|
|
3
3
|
createServer,
|
|
4
|
+
loadCatalogFile,
|
|
4
5
|
serveTarget
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-XAWKEXKJ.js";
|
|
7
|
+
import "./chunk-5KK6W2PE.js";
|
|
7
8
|
export {
|
|
8
9
|
DEFAULT_PORT,
|
|
9
10
|
createServer,
|
|
11
|
+
loadCatalogFile,
|
|
10
12
|
serveTarget
|
|
11
13
|
};
|
|
12
14
|
//# sourceMappingURL=server.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/mockingbird-service-rxvortex",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Stateful mock of the RxVortex (Strive) pharmacy API: OAuth token, order submit, status, cancel, recovery by sender order id, preset catalog, and signed status webhooks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"website": "https://www.rxvortex.com",
|
|
57
57
|
"description": "RxVortex is a pharmacy order platform whose API lets telehealth partners submit, track and cancel prescription orders with pharmacies such as Strive."
|
|
58
58
|
},
|
|
59
|
-
"status": "
|
|
59
|
+
"status": "ready"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"generate": "bun ../../openapi/codegen/dist/cli.js",
|