@crvouga/mockingbird-service-junction 3.6.1 → 3.7.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 +10 -0
- package/README.md +206 -7
- package/SUPPORT.md +4 -2
- package/dist/{chunk-VHVGQ3WX.js → chunk-27N4VA23.js} +1039 -274
- package/dist/chunk-27N4VA23.js.map +7 -0
- package/dist/{chunk-HJJCEIVH.js → chunk-NTGGNJKR.js} +137 -17
- package/dist/chunk-NTGGNJKR.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +317 -107
- package/dist/index.js +1 -1
- package/dist/server.d.ts +347 -96
- package/dist/server.js +2 -2
- package/openapi.yaml +207 -0
- package/package.json +1 -1
- package/dist/chunk-HJJCEIVH.js.map +0 -7
- package/dist/chunk-VHVGQ3WX.js.map +0 -7
package/dist/server.d.ts
CHANGED
|
@@ -133,6 +133,12 @@ interface SqliteClient$2 {
|
|
|
133
133
|
transaction<T>(fn: () => T): T;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* What names an id base: a non-negative safe integer (or its decimal string) or `"boot"`,
|
|
138
|
+
* which derives the base from the wall clock when the runtime is created.
|
|
139
|
+
*/
|
|
140
|
+
type IdBase$1 = number | string;
|
|
141
|
+
|
|
136
142
|
/**
|
|
137
143
|
* The single source of time for a service.
|
|
138
144
|
*
|
|
@@ -215,6 +221,15 @@ type FaultRule$1 = {
|
|
|
215
221
|
requestHeaders?: Record<string, string>;
|
|
216
222
|
/** Fault only requests carrying these query parameters. `"*"` matches any value. */
|
|
217
223
|
query?: Record<string, string>;
|
|
224
|
+
/**
|
|
225
|
+
* Fault only requests whose JSON body carries these fields. Each key is a dotted path into
|
|
226
|
+
* the parsed body (`"patient_details.email"`; a number steps into an array, `"items.0.sku"`)
|
|
227
|
+
* and each value is what the field must equal: a string, number, boolean or `null`, compared
|
|
228
|
+
* strictly (`3` is not `"3"`). `"*"` matches any value that is present. A request whose body
|
|
229
|
+
* is missing, is not JSON, or is not a JSON object never matches. Not `body`, which is the
|
|
230
|
+
* response a rule injects.
|
|
231
|
+
*/
|
|
232
|
+
requestBody?: Record<string, RequestBodyValue$1>;
|
|
218
233
|
/**
|
|
219
234
|
* Fault only this namespace. Omit (or `"*"`) to fault every namespace — which is what
|
|
220
235
|
* an in-process caller usually wants, and what a parallel worker usually does not:
|
|
@@ -281,6 +296,8 @@ type FaultRule$1 = {
|
|
|
281
296
|
/** The preset this rule was expanded from, if any. */
|
|
282
297
|
fromPreset?: string;
|
|
283
298
|
};
|
|
299
|
+
/** What a field of the request body must equal in {@link FaultRule.requestBody}. */
|
|
300
|
+
type RequestBodyValue$1 = string | number | boolean | null;
|
|
284
301
|
/** A fault that fired for one request. */
|
|
285
302
|
type FaultHit$1 = {
|
|
286
303
|
id: string;
|
|
@@ -305,6 +322,11 @@ type FaultCandidate$1 = {
|
|
|
305
322
|
/** Request headers and query, for rules that match on them. */
|
|
306
323
|
headers?: Headers;
|
|
307
324
|
query?: URLSearchParams;
|
|
325
|
+
/**
|
|
326
|
+
* The request body parsed as JSON, read only when a rule matches on `requestBody`. Resolve
|
|
327
|
+
* `undefined` for a body that is missing or not JSON. It must leave the request readable.
|
|
328
|
+
*/
|
|
329
|
+
readJson?: () => Promise<unknown>;
|
|
308
330
|
/** The namespace clock, for `from` / `until`. Rules with a window are skipped without it. */
|
|
309
331
|
now?: number;
|
|
310
332
|
/** How to spend a delay for this request. Default: the registry's own sleep. */
|
|
@@ -827,6 +849,12 @@ type ServiceRuntime$1<T extends ServiceInstance$1> = FetchAPI$2 & {
|
|
|
827
849
|
mount(prefix: string): MountedAPI$1;
|
|
828
850
|
readonly sqlite: SqliteClient$2;
|
|
829
851
|
readonly clock: Clock$1;
|
|
852
|
+
/**
|
|
853
|
+
* Change the id base ({@link RuntimeOptions.idBase}) for ids generated from now on, and
|
|
854
|
+
* return the number it resolved to. Set it before the first request so a boot's ids stay
|
|
855
|
+
* one run.
|
|
856
|
+
*/
|
|
857
|
+
setIdBase(base: IdBase$1): number;
|
|
830
858
|
readonly faults: FaultRegistry$1;
|
|
831
859
|
/** Baseline response time per namespace. */
|
|
832
860
|
readonly latency: LatencyRegistry$1;
|
|
@@ -932,6 +960,12 @@ type CommonServeOptions = {
|
|
|
932
960
|
/** Synthetic provider fixture objects supplied by a fleet entry. */
|
|
933
961
|
fixtures?: Record<string, unknown>;
|
|
934
962
|
baseUrl?: string;
|
|
963
|
+
/**
|
|
964
|
+
* Boot settings from `--settings`, `MOCKINGBIRD_SETTINGS` or a fleet entry's `settings`,
|
|
965
|
+
* already checked by the target's {@link ServeTarget.parseSettings}. Pass them to the
|
|
966
|
+
* service's own `settings` option so they become every namespace's defaults.
|
|
967
|
+
*/
|
|
968
|
+
settings?: Record<string, unknown>;
|
|
935
969
|
};
|
|
936
970
|
/**
|
|
937
971
|
* What a service contributes to `serve`: how to build its runtime from CLI flags,
|
|
@@ -944,6 +978,13 @@ type ServeTarget = {
|
|
|
944
978
|
defaultPort: number;
|
|
945
979
|
/** Serve flags beyond the common ones. */
|
|
946
980
|
options?: Record<string, CliOption>;
|
|
981
|
+
/**
|
|
982
|
+
* Check the boot settings a caller supplied (`--settings`, `MOCKINGBIRD_SETTINGS`, a fleet
|
|
983
|
+
* entry's `settings`) against the service's settings schema, returning them normalized
|
|
984
|
+
* or throwing a message naming the bad field. A target without one takes no boot settings,
|
|
985
|
+
* and supplying some is refused before a port is bound.
|
|
986
|
+
*/
|
|
987
|
+
parseSettings?(settings: Record<string, unknown>): Record<string, unknown>;
|
|
947
988
|
create(values: CliValues, common: CommonServeOptions): Promise<ServiceRuntime$1<ServiceInstance$1>> | ServiceRuntime$1<ServiceInstance$1>;
|
|
948
989
|
/** Startup lines after the listen address, e.g. the loaded corpus version. */
|
|
949
990
|
banner?(runtime: ServiceRuntime$1<ServiceInstance$1>): string[];
|
|
@@ -1083,6 +1124,12 @@ interface SqliteClient$1 {
|
|
|
1083
1124
|
transaction<T>(fn: () => T): T;
|
|
1084
1125
|
}
|
|
1085
1126
|
|
|
1127
|
+
/**
|
|
1128
|
+
* What names an id base: a non-negative safe integer (or its decimal string) or `"boot"`,
|
|
1129
|
+
* which derives the base from the wall clock when the runtime is created.
|
|
1130
|
+
*/
|
|
1131
|
+
type IdBase = number | string;
|
|
1132
|
+
|
|
1086
1133
|
/** Options every provider constructor accepts. */
|
|
1087
1134
|
type APIOptions = {
|
|
1088
1135
|
/** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */
|
|
@@ -1178,6 +1225,15 @@ type FaultRule = {
|
|
|
1178
1225
|
requestHeaders?: Record<string, string>;
|
|
1179
1226
|
/** Fault only requests carrying these query parameters. `"*"` matches any value. */
|
|
1180
1227
|
query?: Record<string, string>;
|
|
1228
|
+
/**
|
|
1229
|
+
* Fault only requests whose JSON body carries these fields. Each key is a dotted path into
|
|
1230
|
+
* the parsed body (`"patient_details.email"`; a number steps into an array, `"items.0.sku"`)
|
|
1231
|
+
* and each value is what the field must equal: a string, number, boolean or `null`, compared
|
|
1232
|
+
* strictly (`3` is not `"3"`). `"*"` matches any value that is present. A request whose body
|
|
1233
|
+
* is missing, is not JSON, or is not a JSON object never matches. Not `body`, which is the
|
|
1234
|
+
* response a rule injects.
|
|
1235
|
+
*/
|
|
1236
|
+
requestBody?: Record<string, RequestBodyValue>;
|
|
1181
1237
|
/**
|
|
1182
1238
|
* Fault only this namespace. Omit (or `"*"`) to fault every namespace — which is what
|
|
1183
1239
|
* an in-process caller usually wants, and what a parallel worker usually does not:
|
|
@@ -1244,6 +1300,8 @@ type FaultRule = {
|
|
|
1244
1300
|
/** The preset this rule was expanded from, if any. */
|
|
1245
1301
|
fromPreset?: string;
|
|
1246
1302
|
};
|
|
1303
|
+
/** What a field of the request body must equal in {@link FaultRule.requestBody}. */
|
|
1304
|
+
type RequestBodyValue = string | number | boolean | null;
|
|
1247
1305
|
/** A fault that fired for one request. */
|
|
1248
1306
|
type FaultHit = {
|
|
1249
1307
|
id: string;
|
|
@@ -1268,6 +1326,11 @@ type FaultCandidate = {
|
|
|
1268
1326
|
/** Request headers and query, for rules that match on them. */
|
|
1269
1327
|
headers?: Headers;
|
|
1270
1328
|
query?: URLSearchParams;
|
|
1329
|
+
/**
|
|
1330
|
+
* The request body parsed as JSON, read only when a rule matches on `requestBody`. Resolve
|
|
1331
|
+
* `undefined` for a body that is missing or not JSON. It must leave the request readable.
|
|
1332
|
+
*/
|
|
1333
|
+
readJson?: () => Promise<unknown>;
|
|
1271
1334
|
/** The namespace clock, for `from` / `until`. Rules with a window are skipped without it. */
|
|
1272
1335
|
now?: number;
|
|
1273
1336
|
/** How to spend a delay for this request. Default: the registry's own sleep. */
|
|
@@ -1790,6 +1853,12 @@ type ServiceRuntime<T extends ServiceInstance> = FetchAPI$1 & {
|
|
|
1790
1853
|
mount(prefix: string): MountedAPI;
|
|
1791
1854
|
readonly sqlite: SqliteClient$1;
|
|
1792
1855
|
readonly clock: Clock;
|
|
1856
|
+
/**
|
|
1857
|
+
* Change the id base ({@link RuntimeOptions.idBase}) for ids generated from now on, and
|
|
1858
|
+
* return the number it resolved to. Set it before the first request so a boot's ids stay
|
|
1859
|
+
* one run.
|
|
1860
|
+
*/
|
|
1861
|
+
setIdBase(base: IdBase): number;
|
|
1793
1862
|
readonly faults: FaultRegistry;
|
|
1794
1863
|
/** Baseline response time per namespace. */
|
|
1795
1864
|
readonly latency: LatencyRegistry;
|
|
@@ -1897,48 +1966,6 @@ interface SqliteClient {
|
|
|
1897
1966
|
transaction<T>(fn: () => T): T;
|
|
1898
1967
|
}
|
|
1899
1968
|
|
|
1900
|
-
type LabAccountStatus = "active" | "pending" | "suspended" | "ready_to_launch";
|
|
1901
|
-
type LabAccountDelegatedFlow = "order_delegated" | "result_delegated" | "fully_delegated" | "not_delegated";
|
|
1902
|
-
/** `billing_type` values the vendored create-order body accepts. */
|
|
1903
|
-
declare const BILLING_TYPES: readonly ["client_bill", "commercial_insurance", "patient_bill_passthrough", "patient_bill", "upfront_payment"];
|
|
1904
|
-
type BillingType = (typeof BILLING_TYPES)[number];
|
|
1905
|
-
type LabAccountOmissionPolicy = "platform" | "reject";
|
|
1906
|
-
/**
|
|
1907
|
-
* A lab account as a consumer configures it. Mirrors `ClientFacingLabAccount`, with
|
|
1908
|
-
* every field but `id` and `lab` optional, plus a `states` shorthand for the common
|
|
1909
|
-
* case of an account that client-bills in a fixed set of states.
|
|
1910
|
-
*/
|
|
1911
|
-
type LabAccountInput = {
|
|
1912
|
-
id: string;
|
|
1913
|
-
/** Lab slug, e.g. `"quest"`, `"labcorp"`, `"bioreference"`. */
|
|
1914
|
-
lab: string;
|
|
1915
|
-
status?: LabAccountStatus;
|
|
1916
|
-
delegated_flow?: LabAccountDelegatedFlow;
|
|
1917
|
-
account_name?: string | null;
|
|
1918
|
-
provider_account_id?: string;
|
|
1919
|
-
org_id?: string | null;
|
|
1920
|
-
business_units?: string[] | null;
|
|
1921
|
-
default_clinical_notes?: string | null;
|
|
1922
|
-
/** Billing type → states it is allowed in. Takes precedence over `states`. */
|
|
1923
|
-
allowed_billing?: Record<string, readonly string[]>;
|
|
1924
|
-
/** Shorthand for `allowed_billing: { client_bill: states }`. Default: every state. */
|
|
1925
|
-
states?: readonly string[];
|
|
1926
|
-
/** Teams the account is linked to. Default: the configured team, so it is selectable. */
|
|
1927
|
-
team_id_allowlist?: readonly string[];
|
|
1928
|
-
};
|
|
1929
|
-
|
|
1930
|
-
type LabAccountProfile = "native" | "expected-contract" | "sandbox-observed";
|
|
1931
|
-
type LabAccountSandboxPolicy = {
|
|
1932
|
-
/** Explicit billing refusals observed for this particular fixture/account. */
|
|
1933
|
-
rejectBilling?: Partial<Record<BillingType, string>>;
|
|
1934
|
-
/** Explicit billing/state exceptions observed for this particular fixture/account. */
|
|
1935
|
-
allowBilling?: Partial<Record<BillingType, readonly string[]>>;
|
|
1936
|
-
};
|
|
1937
|
-
type LabAccountBehavior = {
|
|
1938
|
-
profile: LabAccountProfile;
|
|
1939
|
-
accounts: Record<string, LabAccountSandboxPolicy>;
|
|
1940
|
-
};
|
|
1941
|
-
|
|
1942
1969
|
/** Lab-test catalog mirrored from the Junction sandbox (`GET /v3/lab_test`). */
|
|
1943
1970
|
type CatalogMarker = {
|
|
1944
1971
|
id: number;
|
|
@@ -1991,6 +2018,204 @@ type LabTestRecord = {
|
|
|
1991
2018
|
worst_case_tat_days: number | null;
|
|
1992
2019
|
};
|
|
1993
2020
|
|
|
2021
|
+
/**
|
|
2022
|
+
* A-la-carte markers and order-set pricing.
|
|
2023
|
+
*
|
|
2024
|
+
* - `GET /v3/lab_tests/markers`: the markers a team can order one by one.
|
|
2025
|
+
* https://docs.junction.com/api-reference/lab-testing/biomarkers
|
|
2026
|
+
* - `POST /v3/lab_test/estimate_order_set_pricing`: what an order set costs.
|
|
2027
|
+
* https://docs.junction.com/api-reference/lab-testing/estimate-order-set-pricing
|
|
2028
|
+
*
|
|
2029
|
+
* Both follow the published contract. Nothing here is checked against the live sandbox (prices
|
|
2030
|
+
* are contract-owned), so the emulator prices from the catalog it holds: a lab test's `price`
|
|
2031
|
+
* and a marker's `price`, or the `pricing` of a configured {@link MarkerCatalogEntry}.
|
|
2032
|
+
*/
|
|
2033
|
+
|
|
2034
|
+
/** Pricing the way Junction states it: minor units, or why it is not stated. */
|
|
2035
|
+
type MarkerPricing = {
|
|
2036
|
+
base_amount_minor: number;
|
|
2037
|
+
modifiers?: readonly Record<string, unknown>[] | null;
|
|
2038
|
+
} | {
|
|
2039
|
+
unspecified: "refer_to_contract" | "price_unavailable";
|
|
2040
|
+
};
|
|
2041
|
+
/**
|
|
2042
|
+
* A marker the mock offers on top of (or in place of) the ones embedded in catalog lab tests:
|
|
2043
|
+
* `createRuntime({ markerCatalog: [...] })`. Fields not given take the vendor's defaults.
|
|
2044
|
+
*/
|
|
2045
|
+
type MarkerCatalogEntry = {
|
|
2046
|
+
id: number;
|
|
2047
|
+
name: string;
|
|
2048
|
+
slug?: string;
|
|
2049
|
+
description?: string | null;
|
|
2050
|
+
lab_id?: number | null;
|
|
2051
|
+
provider_id?: string | null;
|
|
2052
|
+
type?: "biomarker" | "panel" | null;
|
|
2053
|
+
unit?: string | null;
|
|
2054
|
+
/** Dollars, as the vendor prints them (`"12.50"`); a number is formatted to two decimals. */
|
|
2055
|
+
price?: string | number | null;
|
|
2056
|
+
/** Stated pricing, when `price` cannot say it (modifiers, `refer_to_contract`). */
|
|
2057
|
+
pricing?: MarkerPricing;
|
|
2058
|
+
/** Ask-on-order questions: `{ questions: [...] }`. */
|
|
2059
|
+
aoe?: unknown;
|
|
2060
|
+
/** Default `false`, as at the vendor. */
|
|
2061
|
+
a_la_carte_enabled?: boolean;
|
|
2062
|
+
common_tat_days?: number | null;
|
|
2063
|
+
worst_case_tat_days?: number | null;
|
|
2064
|
+
is_orderable?: boolean | null;
|
|
2065
|
+
/** What the marker reports. Default: none. */
|
|
2066
|
+
expected_results?: readonly ExpectedResult[];
|
|
2067
|
+
components?: readonly MarkerCatalogEntry[] | null;
|
|
2068
|
+
};
|
|
2069
|
+
|
|
2070
|
+
/**
|
|
2071
|
+
* ZIP overlays: aliases and per-ZIP overrides on top of whatever geo mode answers.
|
|
2072
|
+
*
|
|
2073
|
+
* `createRuntime({ zipOverlays: { aliases: { "07105": "85004" }, overrides: { "07105": {
|
|
2074
|
+
* phlebotomy_served: true, no_pscs: true } } } })`. An alias makes one ZIP answer as another
|
|
2075
|
+
* (coverage, recordings and the synthetic model all use the target); an override then edits the
|
|
2076
|
+
* answer for a ZIP: `phlebotomy.is_served` on `area/info`, and an empty PSC list.
|
|
2077
|
+
*/
|
|
2078
|
+
|
|
2079
|
+
type ZipOverride = {
|
|
2080
|
+
/** `phlebotomy.is_served` on `GET /v3/order/area/info` (and its `providers`). */
|
|
2081
|
+
phlebotomy_served?: boolean;
|
|
2082
|
+
/** No patient service centers: `psc/info` lists none and `area/info` counts none. */
|
|
2083
|
+
no_pscs?: boolean;
|
|
2084
|
+
};
|
|
2085
|
+
type ZipOverlays = {
|
|
2086
|
+
/** ZIP → the ZIP it answers as. */
|
|
2087
|
+
aliases?: Record<string, string>;
|
|
2088
|
+
/** ZIP → what to change in its answers. Looked up by the requested ZIP, then by its alias. */
|
|
2089
|
+
overrides?: Record<string, ZipOverride>;
|
|
2090
|
+
};
|
|
2091
|
+
|
|
2092
|
+
type LabAccountStatus = "active" | "pending" | "suspended" | "ready_to_launch";
|
|
2093
|
+
type LabAccountDelegatedFlow = "order_delegated" | "result_delegated" | "fully_delegated" | "not_delegated";
|
|
2094
|
+
/** `billing_type` values the vendored create-order body accepts. */
|
|
2095
|
+
declare const BILLING_TYPES: readonly ["client_bill", "commercial_insurance", "patient_bill_passthrough", "patient_bill", "upfront_payment"];
|
|
2096
|
+
type BillingType = (typeof BILLING_TYPES)[number];
|
|
2097
|
+
type LabAccountOmissionPolicy = "platform" | "reject";
|
|
2098
|
+
/**
|
|
2099
|
+
* A lab account as a consumer configures it. Mirrors `ClientFacingLabAccount`, with
|
|
2100
|
+
* every field but `id` and `lab` optional, plus a `states` shorthand for the common
|
|
2101
|
+
* case of an account that client-bills in a fixed set of states.
|
|
2102
|
+
*/
|
|
2103
|
+
type LabAccountInput = {
|
|
2104
|
+
id: string;
|
|
2105
|
+
/** Lab slug, e.g. `"quest"`, `"labcorp"`, `"bioreference"`. */
|
|
2106
|
+
lab: string;
|
|
2107
|
+
status?: LabAccountStatus;
|
|
2108
|
+
delegated_flow?: LabAccountDelegatedFlow;
|
|
2109
|
+
account_name?: string | null;
|
|
2110
|
+
provider_account_id?: string;
|
|
2111
|
+
org_id?: string | null;
|
|
2112
|
+
business_units?: string[] | null;
|
|
2113
|
+
default_clinical_notes?: string | null;
|
|
2114
|
+
/** Billing type → states it is allowed in. Takes precedence over `states`. */
|
|
2115
|
+
allowed_billing?: Record<string, readonly string[]>;
|
|
2116
|
+
/** Shorthand for `allowed_billing: { client_bill: states }`. Default: every state. */
|
|
2117
|
+
states?: readonly string[];
|
|
2118
|
+
/** Teams the account is linked to. Default: the configured team, so it is selectable. */
|
|
2119
|
+
team_id_allowlist?: readonly string[];
|
|
2120
|
+
};
|
|
2121
|
+
|
|
2122
|
+
type LabAccountProfile = "native" | "expected-contract" | "sandbox-observed" | "observed";
|
|
2123
|
+
/** Which vendor environment an `observed` configuration reproduces. */
|
|
2124
|
+
type LabAccountOracle = "sandbox" | "production";
|
|
2125
|
+
/**
|
|
2126
|
+
* How an order that omits `lab_account_id` and resolves to a Junction-owned (`org_id: null`)
|
|
2127
|
+
* account treats that account's listed `allowed_billing`: `listed` (default) enforces it,
|
|
2128
|
+
* `unchecked` skips the billing/state check (#467). Explicit account selection is unaffected.
|
|
2129
|
+
*/
|
|
2130
|
+
type OmittedAccountBilling = "listed" | "unchecked";
|
|
2131
|
+
type LabAccountSandboxPolicy = {
|
|
2132
|
+
/** Explicit billing refusals observed for this particular fixture/account. */
|
|
2133
|
+
rejectBilling?: Partial<Record<BillingType, string>>;
|
|
2134
|
+
/** Explicit billing/state exceptions observed for this particular fixture/account. */
|
|
2135
|
+
allowBilling?: Partial<Record<BillingType, readonly string[]>>;
|
|
2136
|
+
};
|
|
2137
|
+
type LabAccountBehavior = {
|
|
2138
|
+
profile: LabAccountProfile;
|
|
2139
|
+
/**
|
|
2140
|
+
* The oracle the observations reproduce. `sandbox-observed` is the alias of `observed`
|
|
2141
|
+
* with `oracle: "sandbox"`; `native` and `expected-contract` have none.
|
|
2142
|
+
*/
|
|
2143
|
+
oracle?: LabAccountOracle;
|
|
2144
|
+
accounts: Record<string, LabAccountSandboxPolicy>;
|
|
2145
|
+
/** Lab slug → omitted-account billing policy; unlisted labs are `listed`. */
|
|
2146
|
+
omittedAccountBilling?: Record<string, OmittedAccountBilling>;
|
|
2147
|
+
};
|
|
2148
|
+
|
|
2149
|
+
/**
|
|
2150
|
+
* Opt-in sandbox quirks: behaviors the vendor sandbox shows that a well-behaved client must
|
|
2151
|
+
* tolerate. Every quirk is off by default, so no existing suite changes.
|
|
2152
|
+
*/
|
|
2153
|
+
type JunctionQuirks = {
|
|
2154
|
+
/**
|
|
2155
|
+
* #474: a `POST /v3/order/{id}/cancel` that lands in the same wall-clock second as the
|
|
2156
|
+
* order's creation records its `cancelled.<method>.cancelled` event, but the order's
|
|
2157
|
+
* `status`, `last_event` and `updated_at` do not move; a second cancel is a no-op. Reported
|
|
2158
|
+
* from the sandbox (production unverified).
|
|
2159
|
+
*/
|
|
2160
|
+
sameSecondCancelStatus?: boolean;
|
|
2161
|
+
};
|
|
2162
|
+
|
|
2163
|
+
/**
|
|
2164
|
+
* The test backdoor: users and orders put straight into a namespace, with ids a suite
|
|
2165
|
+
* chooses — the Junction `user_id`s a database fixture already carries, or an order
|
|
2166
|
+
* already in some status — plus the lenient identity mode that adopts unknown users.
|
|
2167
|
+
*
|
|
2168
|
+
* Everything inserted here goes through the records `create_user` and `create_order`
|
|
2169
|
+
* build, so no read path can tell a fixture from an API-created resource.
|
|
2170
|
+
*/
|
|
2171
|
+
|
|
2172
|
+
/** How requests referring to a user the namespace does not hold are answered. */
|
|
2173
|
+
type IdentityMode = "strict" | "adopt-users";
|
|
2174
|
+
type UserFixture = {
|
|
2175
|
+
/** Default: a fresh id, as `create_user` would mint. */
|
|
2176
|
+
user_id?: string;
|
|
2177
|
+
client_user_id: string;
|
|
2178
|
+
/** ISO-8601. Default: the mock clock's now. */
|
|
2179
|
+
created_on?: string;
|
|
2180
|
+
/** An IANA zone, or the full `{ id, source_slug, updated_at }` object. */
|
|
2181
|
+
fallback_time_zone?: string | UserRecord["fallback_time_zone"];
|
|
2182
|
+
/** `YYYY-MM-DD`, or the full `{ value, source_slug, updated_at }` object. */
|
|
2183
|
+
fallback_birth_date?: string | UserRecord["fallback_birth_date"];
|
|
2184
|
+
ingestion_start?: string | null;
|
|
2185
|
+
ingestion_end?: string | null;
|
|
2186
|
+
};
|
|
2187
|
+
type OrderFixture = {
|
|
2188
|
+
/** Default: a fresh id, as `create_order` would mint. */
|
|
2189
|
+
order_id?: string;
|
|
2190
|
+
user_id: string;
|
|
2191
|
+
lab_test_id: string;
|
|
2192
|
+
lab_account_id?: string;
|
|
2193
|
+
/** A transition target (`completed`, `at_lab`, or a full status). Default: just ordered. */
|
|
2194
|
+
status?: string;
|
|
2195
|
+
/** Default: the lab test's own method. */
|
|
2196
|
+
collection_method?: string;
|
|
2197
|
+
patient_details?: Record<string, unknown>;
|
|
2198
|
+
patient_address?: Record<string, unknown>;
|
|
2199
|
+
billing_type?: string;
|
|
2200
|
+
icd_codes?: string[] | null;
|
|
2201
|
+
passthrough?: string | null;
|
|
2202
|
+
clinical_notes?: string | null;
|
|
2203
|
+
/** ISO-8601. Default: the mock clock's now. */
|
|
2204
|
+
created_at?: string;
|
|
2205
|
+
/** Results served for the order, as `PUT /__admin/results/{id}` takes them. */
|
|
2206
|
+
result_fixture?: Omit<ResultFixture, "name"> & {
|
|
2207
|
+
name?: string;
|
|
2208
|
+
};
|
|
2209
|
+
};
|
|
2210
|
+
type JunctionFixtures = {
|
|
2211
|
+
users?: readonly UserFixture[];
|
|
2212
|
+
orders?: readonly OrderFixture[];
|
|
2213
|
+
};
|
|
2214
|
+
type InsertOptions = {
|
|
2215
|
+
/** Publish the webhooks the equivalent API calls would. Default `false`. */
|
|
2216
|
+
emitWebhooks?: boolean;
|
|
2217
|
+
};
|
|
2218
|
+
|
|
1994
2219
|
type JunctionLimits = {
|
|
1995
2220
|
/**
|
|
1996
2221
|
* Live users a team may hold; creating one more answers the sandbox's
|
|
@@ -2139,8 +2364,10 @@ type ResultFixture = {
|
|
|
2139
2364
|
* - `synthetic`: invent plausible coverage. Right for property tests that walk random ZIPs.
|
|
2140
2365
|
* - `corpus`: refuse with a documented Mockingbird error. Right for a mock standing in for
|
|
2141
2366
|
* the vendor, where invented coverage would silently disagree with production.
|
|
2367
|
+
* - `corpus+synthetic`: replay the recording for the ZIPs it covers (a read it cannot answer
|
|
2368
|
+
* still refuses), and invent coverage for every other ZIP.
|
|
2142
2369
|
*/
|
|
2143
|
-
type GeoMode = "synthetic" | "corpus";
|
|
2370
|
+
type GeoMode = "synthetic" | "corpus" | "corpus+synthetic";
|
|
2144
2371
|
type WebhookPublisher = (event: JunctionWebhookEvent) => void;
|
|
2145
2372
|
type JunctionWebhookOptions = {
|
|
2146
2373
|
seed?: number;
|
|
@@ -2148,60 +2375,27 @@ type JunctionWebhookOptions = {
|
|
|
2148
2375
|
timeoutMs?: number;
|
|
2149
2376
|
};
|
|
2150
2377
|
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
/**
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
fallback_birth_date?: string | UserRecord["fallback_birth_date"];
|
|
2172
|
-
ingestion_start?: string | null;
|
|
2173
|
-
ingestion_end?: string | null;
|
|
2174
|
-
};
|
|
2175
|
-
type OrderFixture = {
|
|
2176
|
-
/** Default: a fresh id, as `create_order` would mint. */
|
|
2177
|
-
order_id?: string;
|
|
2178
|
-
user_id: string;
|
|
2179
|
-
lab_test_id: string;
|
|
2180
|
-
lab_account_id?: string;
|
|
2181
|
-
/** A transition target (`completed`, `at_lab`, or a full status). Default: just ordered. */
|
|
2378
|
+
type CatalogOverlay = {
|
|
2379
|
+
/** The lab test to clone, by id or slug. It must be in the catalog the namespace boots with. */
|
|
2380
|
+
from: string;
|
|
2381
|
+
/** Id of the new lab test (a UUID, as `create_order` expects). */
|
|
2382
|
+
id: string;
|
|
2383
|
+
name?: string;
|
|
2384
|
+
slug?: string;
|
|
2385
|
+
/**
|
|
2386
|
+
* Move the clone to a lab: the slug of a lab the catalog lists, or a lab record
|
|
2387
|
+
* (`{ id, slug, name, ... }`), which is added to `GET /v3/lab_tests/labs` when new.
|
|
2388
|
+
* The clone's markers and expected results take that lab's id.
|
|
2389
|
+
*/
|
|
2390
|
+
lab?: string | Record<string, unknown>;
|
|
2391
|
+
/** Drop the ask-on-order questions from every marker of the clone. */
|
|
2392
|
+
stripAoe?: boolean;
|
|
2393
|
+
/** Set `auto_generated` on the clone. Default: as the source. */
|
|
2394
|
+
autoGenerated?: boolean;
|
|
2395
|
+
method?: string;
|
|
2396
|
+
/** Dollars. */
|
|
2397
|
+
price?: number;
|
|
2182
2398
|
status?: string;
|
|
2183
|
-
/** Default: the lab test's own method. */
|
|
2184
|
-
collection_method?: string;
|
|
2185
|
-
patient_details?: Record<string, unknown>;
|
|
2186
|
-
patient_address?: Record<string, unknown>;
|
|
2187
|
-
billing_type?: string;
|
|
2188
|
-
icd_codes?: string[] | null;
|
|
2189
|
-
passthrough?: string | null;
|
|
2190
|
-
clinical_notes?: string | null;
|
|
2191
|
-
/** ISO-8601. Default: the mock clock's now. */
|
|
2192
|
-
created_at?: string;
|
|
2193
|
-
/** Results served for the order, as `PUT /__admin/results/{id}` takes them. */
|
|
2194
|
-
result_fixture?: Omit<ResultFixture, "name"> & {
|
|
2195
|
-
name?: string;
|
|
2196
|
-
};
|
|
2197
|
-
};
|
|
2198
|
-
type JunctionFixtures = {
|
|
2199
|
-
users?: readonly UserFixture[];
|
|
2200
|
-
orders?: readonly OrderFixture[];
|
|
2201
|
-
};
|
|
2202
|
-
type InsertOptions = {
|
|
2203
|
-
/** Publish the webhooks the equivalent API calls would. Default `false`. */
|
|
2204
|
-
emitWebhooks?: boolean;
|
|
2205
2399
|
};
|
|
2206
2400
|
|
|
2207
2401
|
/**
|
|
@@ -2223,6 +2417,13 @@ interface FetchAPI {
|
|
|
2223
2417
|
* NY/NJ client-bill shape a consumer asked for, kept because suites depend on it, and
|
|
2224
2418
|
* listed in `SYNTHETIC_LAB_ACCOUNT_PRESETS`.
|
|
2225
2419
|
*
|
|
2420
|
+
* The 2026-09-21 `bioreference_platform` preset lists `client_bill` in 47 states, but the
|
|
2421
|
+
* current house BioReference account lists only `patient_bill_passthrough` in NJ and NY, so
|
|
2422
|
+
* treat it as illustrative (#475). The `bioreference_current_platform`,
|
|
2423
|
+
* `quest_sandbox_platform` and `sonora_quest_production_platform` presets follow the listings
|
|
2424
|
+
* an agent reported from `GET /v3/lab_test/lab_account` on 2026-10-18 (a consumer-audit
|
|
2425
|
+
* report, not a repository probe); they are additions, so no existing preset changes.
|
|
2426
|
+
*
|
|
2226
2427
|
* `*_platform` presets are Junction's own accounts (`org_id: null`, allowlist `[]`); every
|
|
2227
2428
|
* other active preset is customer-owned (it belongs to an Org and is linked to the team).
|
|
2228
2429
|
*/
|
|
@@ -2364,6 +2565,27 @@ type JunctionAPIOptions = APIOptions & {
|
|
|
2364
2565
|
* when a corpus is given (refuse, loudly), otherwise `synthetic` (invent coverage).
|
|
2365
2566
|
*/
|
|
2366
2567
|
geo?: GeoMode;
|
|
2568
|
+
/**
|
|
2569
|
+
* ZIP aliases and per-ZIP overrides on serviceability answers, whatever the geo mode: an
|
|
2570
|
+
* alias makes a ZIP answer as another, an override sets `phlebotomy.is_served` or empties the
|
|
2571
|
+
* PSC list. Per namespace via `PUT /__admin/geo`.
|
|
2572
|
+
*/
|
|
2573
|
+
zipOverlays?: ZipOverlays;
|
|
2574
|
+
/**
|
|
2575
|
+
* Lab tests derived from catalog ones (new id, name, slug, lab; AOE questions stripped;
|
|
2576
|
+
* `auto_generated`), added to every namespace after the catalog loads and again on `reset()`.
|
|
2577
|
+
*/
|
|
2578
|
+
catalogOverlays?: readonly CatalogOverlay[];
|
|
2579
|
+
/**
|
|
2580
|
+
* Markers `GET /v3/lab_tests/markers` offers on top of those in catalog lab tests, with their
|
|
2581
|
+
* pricing, AOE questions and expected results.
|
|
2582
|
+
*/
|
|
2583
|
+
markerCatalog?: readonly MarkerCatalogEntry[];
|
|
2584
|
+
/**
|
|
2585
|
+
* Name the markers behind each biomarker result line of an add-on order
|
|
2586
|
+
* (`source_markers[].marker_id`). Default off: the line then carries `source_markers: null`.
|
|
2587
|
+
*/
|
|
2588
|
+
addOnSourceMarkers?: boolean;
|
|
2367
2589
|
/**
|
|
2368
2590
|
* The team's lab accounts, replacing the built-in fixtures (and any from the corpus):
|
|
2369
2591
|
* a list of accounts, or `{ presets: [...], accounts: [...] }`. `create_order` routes,
|
|
@@ -2389,6 +2611,8 @@ type JunctionAPIOptions = APIOptions & {
|
|
|
2389
2611
|
labAccountOmissionPolicies?: Record<string, LabAccountOmissionPolicy>;
|
|
2390
2612
|
/** Named policy; native preserves legacy behavior. Sandbox exceptions are account-owned. */
|
|
2391
2613
|
labAccountBehavior?: Partial<LabAccountBehavior>;
|
|
2614
|
+
/** Opt-in sandbox quirks (#474), every one off by default; see {@link JunctionQuirks}. */
|
|
2615
|
+
quirks?: JunctionQuirks;
|
|
2392
2616
|
/** Users and orders to load into every namespace, re-applied on every `reset()`. */
|
|
2393
2617
|
fixtures?: JunctionFixtures;
|
|
2394
2618
|
};
|
|
@@ -2415,6 +2639,7 @@ declare class JunctionAPI implements FetchAPI {
|
|
|
2415
2639
|
private readonly rateWindow;
|
|
2416
2640
|
private corpus;
|
|
2417
2641
|
private labAccountConfig;
|
|
2642
|
+
private readonly catalogOverlays;
|
|
2418
2643
|
constructor(options?: JunctionAPIOptions);
|
|
2419
2644
|
fetch(request: Request): Promise<Response>;
|
|
2420
2645
|
reset(): Promise<void>;
|
|
@@ -2456,6 +2681,9 @@ declare class JunctionAPI implements FetchAPI {
|
|
|
2456
2681
|
/** Effective account policy for this namespace; kept across reset. */
|
|
2457
2682
|
get labAccountBehavior(): LabAccountBehavior;
|
|
2458
2683
|
set labAccountBehavior(input: LabAccountBehavior);
|
|
2684
|
+
/** Opt-in sandbox quirks for this namespace; kept across reset. */
|
|
2685
|
+
get quirks(): JunctionQuirks;
|
|
2686
|
+
set quirks(input: JunctionQuirks);
|
|
2459
2687
|
get defaultBillingTypes(): Record<string, BillingType>;
|
|
2460
2688
|
/** Replace the per-lab default billing types (`{}` restores `client_bill` everywhere). */
|
|
2461
2689
|
set defaultBillingTypes(input: Partial<Record<string, BillingType>>);
|
|
@@ -2473,6 +2701,9 @@ declare class JunctionAPI implements FetchAPI {
|
|
|
2473
2701
|
orders: OrderRecord[];
|
|
2474
2702
|
};
|
|
2475
2703
|
corpusInfo(): CorpusInfo | undefined;
|
|
2704
|
+
/** ZIP aliases and overrides for this namespace; kept across reset. */
|
|
2705
|
+
get zipOverlays(): ZipOverlays;
|
|
2706
|
+
set zipOverlays(overlays: ZipOverlays);
|
|
2476
2707
|
get geoMode(): GeoMode;
|
|
2477
2708
|
set geoMode(mode: GeoMode);
|
|
2478
2709
|
order(id: string): OrderRecord | undefined;
|
|
@@ -2483,6 +2714,16 @@ declare class JunctionAPI implements FetchAPI {
|
|
|
2483
2714
|
* only place the mock reports it.
|
|
2484
2715
|
*/
|
|
2485
2716
|
orderLabAccount(id: string): string | null | undefined;
|
|
2717
|
+
/**
|
|
2718
|
+
* Where `POST /v3/order` carried a lab account id: `labAccountId` at the root (which
|
|
2719
|
+
* selects the account) and `nestedLabAccountId` inside `order_set` (which Junction
|
|
2720
|
+
* ignores). `null` for an order that was not placed through the API (a fixture), and
|
|
2721
|
+
* `undefined` for an unknown order.
|
|
2722
|
+
*/
|
|
2723
|
+
orderLabAccountRequest(id: string): {
|
|
2724
|
+
labAccountId: string | null;
|
|
2725
|
+
nestedLabAccountId: string | null;
|
|
2726
|
+
} | null | undefined;
|
|
2486
2727
|
/** Frozen provider number used by the synthetic requisition; null means unknown. */
|
|
2487
2728
|
requisitionFixture(id: string): {
|
|
2488
2729
|
provider_account_id: string | null;
|
|
@@ -2516,11 +2757,21 @@ type JunctionRuntimeOptions = {
|
|
|
2516
2757
|
corpus?: SealedCorpus;
|
|
2517
2758
|
/** Default: `corpus` when a corpus is loaded, otherwise `synthetic`. */
|
|
2518
2759
|
geo?: GeoMode;
|
|
2760
|
+
/** ZIP aliases and per-ZIP overrides on serviceability answers; see {@link JunctionAPIOptions.zipOverlays}. */
|
|
2761
|
+
zipOverlays?: ZipOverlays;
|
|
2762
|
+
/** Lab tests derived from catalog ones at boot; see {@link JunctionAPIOptions.catalogOverlays}. */
|
|
2763
|
+
catalogOverlays?: readonly CatalogOverlay[];
|
|
2764
|
+
/** Markers `GET /v3/lab_tests/markers` offers; see {@link JunctionAPIOptions.markerCatalog}. */
|
|
2765
|
+
markerCatalog?: readonly MarkerCatalogEntry[];
|
|
2766
|
+
/** Name the markers behind add-on result lines; see {@link JunctionAPIOptions.addOnSourceMarkers}. */
|
|
2767
|
+
addOnSourceMarkers?: boolean;
|
|
2519
2768
|
/** The team's lab accounts, or `{ presets, accounts }`; see {@link JunctionAPIOptions.labAccounts}. */
|
|
2520
2769
|
labAccounts?: LabAccountLayout;
|
|
2521
2770
|
/** Per-lab multiple-account omission policy; default platform. */
|
|
2522
2771
|
labAccountOmissionPolicies?: Record<string, LabAccountOmissionPolicy>;
|
|
2523
2772
|
labAccountBehavior?: Partial<LabAccountBehavior>;
|
|
2773
|
+
/** Opt-in sandbox quirks, every one off by default (#474). */
|
|
2774
|
+
quirks?: JunctionQuirks;
|
|
2524
2775
|
/** The team the mock answers as. Default: the corpus's recorded team, else a fixed id. */
|
|
2525
2776
|
teamId?: string;
|
|
2526
2777
|
/** Sandbox-only restrictions, every one off by default; per namespace via `PUT /__admin/limits`. */
|
package/dist/server.js
CHANGED