emuhealth 0.7.0 → 0.9.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.
Files changed (71) hide show
  1. package/README.md +7 -1
  2. package/dist/api.d.ts +1 -1
  3. package/dist/api.js +111 -19
  4. package/dist/api.js.map +1 -1
  5. package/dist/{chunk-N3OXS25N.js → chunk-XMIM6S4S.js} +115 -19
  6. package/dist/chunk-XMIM6S4S.js.map +1 -0
  7. package/dist/{dist-G4ZKPBOD.js → dist-2SPD4VKT.js} +400 -41
  8. package/dist/dist-2SPD4VKT.js.map +1 -0
  9. package/dist/{dist-BGTZW3FR.js → dist-7IG4HX3B.js} +262 -17
  10. package/dist/dist-7IG4HX3B.js.map +1 -0
  11. package/dist/{dist-ID2YPHQQ.js → dist-B7QPLCAG.js} +400 -41
  12. package/dist/dist-B7QPLCAG.js.map +1 -0
  13. package/dist/{dist-ID3HOBV6.js → dist-D4XTX54S.js} +331 -29
  14. package/dist/dist-D4XTX54S.js.map +1 -0
  15. package/dist/{dist-NZYMC7MC.js → dist-HUGQE3UQ.js} +375 -41
  16. package/dist/dist-HUGQE3UQ.js.map +1 -0
  17. package/dist/dist-LU2SZMDZ.js +1334 -0
  18. package/dist/dist-LU2SZMDZ.js.map +1 -0
  19. package/dist/{dist-2YZQBLX2.js → dist-LYW423OA.js} +262 -17
  20. package/dist/dist-LYW423OA.js.map +1 -0
  21. package/dist/{dist-WSHMJF6J.js → dist-MOSHZOI2.js} +380 -46
  22. package/dist/dist-MOSHZOI2.js.map +1 -0
  23. package/dist/{dist-OXKMJ5KL.js → dist-O5VNO6R3.js} +404 -45
  24. package/dist/dist-O5VNO6R3.js.map +1 -0
  25. package/dist/{dist-IMZOZNB5.js → dist-P2Q4A2DE.js} +262 -17
  26. package/dist/dist-P2Q4A2DE.js.map +1 -0
  27. package/dist/{dist-2AQ4NEIG.js → dist-QNFWXDSF.js} +400 -41
  28. package/dist/dist-QNFWXDSF.js.map +1 -0
  29. package/dist/{dist-CKAIZSL3.js → dist-R2RM35T5.js} +375 -41
  30. package/dist/dist-R2RM35T5.js.map +1 -0
  31. package/dist/{dist-6GBOXHHG.js → dist-SRMVCWKJ.js} +262 -17
  32. package/dist/dist-SRMVCWKJ.js.map +1 -0
  33. package/dist/dist-SYCRZXDL.js +1571 -0
  34. package/dist/dist-SYCRZXDL.js.map +1 -0
  35. package/dist/{dist-F4OEZZBR.js → dist-TRI7TRKP.js} +262 -17
  36. package/dist/dist-TRI7TRKP.js.map +1 -0
  37. package/dist/dist-UDWI7IO6.js +1108 -0
  38. package/dist/dist-UDWI7IO6.js.map +1 -0
  39. package/dist/{dist-YC3GSNFQ.js → dist-UUOAP6EN.js} +402 -43
  40. package/dist/dist-UUOAP6EN.js.map +1 -0
  41. package/dist/dist-UXGG2BLX.js +1217 -0
  42. package/dist/dist-UXGG2BLX.js.map +1 -0
  43. package/dist/{dist-LHSWVR7A.js → dist-W3BWZ4HD.js} +262 -17
  44. package/dist/dist-W3BWZ4HD.js.map +1 -0
  45. package/dist/{dist-NIYFNDR5.js → dist-XQO4ECK7.js} +262 -17
  46. package/dist/dist-XQO4ECK7.js.map +1 -0
  47. package/dist/{dist-GRGMAU6B.js → dist-YLPKKYLR.js} +416 -40
  48. package/dist/dist-YLPKKYLR.js.map +1 -0
  49. package/dist/index.js +34 -3
  50. package/dist/index.js.map +1 -1
  51. package/dist/project-worker.js +2 -2
  52. package/dist/project-worker.js.map +1 -1
  53. package/package.json +33 -29
  54. package/dist/chunk-N3OXS25N.js.map +0 -1
  55. package/dist/dist-2AQ4NEIG.js.map +0 -1
  56. package/dist/dist-2YZQBLX2.js.map +0 -1
  57. package/dist/dist-6GBOXHHG.js.map +0 -1
  58. package/dist/dist-BGTZW3FR.js.map +0 -1
  59. package/dist/dist-CKAIZSL3.js.map +0 -1
  60. package/dist/dist-F4OEZZBR.js.map +0 -1
  61. package/dist/dist-G4ZKPBOD.js.map +0 -1
  62. package/dist/dist-GRGMAU6B.js.map +0 -1
  63. package/dist/dist-ID2YPHQQ.js.map +0 -1
  64. package/dist/dist-ID3HOBV6.js.map +0 -1
  65. package/dist/dist-IMZOZNB5.js.map +0 -1
  66. package/dist/dist-LHSWVR7A.js.map +0 -1
  67. package/dist/dist-NIYFNDR5.js.map +0 -1
  68. package/dist/dist-NZYMC7MC.js.map +0 -1
  69. package/dist/dist-OXKMJ5KL.js.map +0 -1
  70. package/dist/dist-WSHMJF6J.js.map +0 -1
  71. package/dist/dist-YC3GSNFQ.js.map +0 -1
package/README.md CHANGED
@@ -37,7 +37,7 @@ All services listen on IPv4 loopback (`127.0.0.1`) by default. No config file ne
37
37
 
38
38
  Health and life science services use a fixed range starting at `http://localhost:4100`. Each health service keeps its port no matter which other services run or how many upstream services exist.
39
39
 
40
- - **FHIR R4** on `http://localhost:4100` (create, read, update, JSON Patch, delete, versioning, `_history`, search, batch and transaction Bundles, and a CapabilityStatement at `/metadata`, `Patient/$everything`, Bulk Data `$export` with NDJSON output; starts with 5 generated synthetic patients; SMART App Launch with patient and practitioner pickers, an EHR launch simulator, PKCE, SMART Backend Services with `private_key_jwt`, and scope and patient enforcement for presented tokens; terminology fixtures with `CodeSystem/$lookup` and `$validate-code`; browse it at `/_inspector`)
40
+ - **FHIR R4** on `http://localhost:4100` (create, read, update, JSON Patch, delete, versioning, `_history`, search, batch and transaction Bundles, and a CapabilityStatement at `/metadata`, `Patient/$everything`, Bulk Data `$export` with NDJSON output; starts with 5 generated synthetic patients; SMART App Launch with patient and practitioner pickers, an EHR launch simulator, PKCE, SMART Backend Services with `private_key_jwt`, and scope and patient enforcement for presented tokens; terminology fixtures with `CodeSystem/$lookup` and `$validate-code`; R4B or R5 instead of R4 with `fhir.fhirVersion`, including `$versions` and `fhirVersion` media type negotiation; browse it at `/_inspector`)
41
41
  - **Epic** on `http://localhost:4101` (the FHIR R4 server under Epic's `/api/FHIR/R4` base, OAuth 2.0 at `/oauth2/authorize` and `/oauth2/token` with SMART App Launch and Backend Services, `__epic.dstu2.patient` in token responses, Epic's informational OperationOutcome on empty searches, and Schedules and Slots with `Appointment/$find` and `Appointment/$book`)
42
42
  - **openFDA** on `http://localhost:4102` (`/drug/label.json`, `/drug/event.json`, and `/drug/enforcement.json`, `/device/enforcement.json`, `/food/enforcement.json` recalls with the openFDA query language: `search` with fields, phrases, `.exact`, ranges, `AND`/`OR`/`NOT`, plus `sort`, `count`, `limit`, and `skip`; synthetic labels, adverse event reports, and recalls; browse them at `/_inspector`)
43
43
  - **RxNav** on `http://localhost:4103` (the RxNorm REST API under `/REST`: `rxcui`, `drugs`, `properties`, `related`, `allrelated`, `ndcs`, `approximateTerm`, `spellingsuggestions`, and `displaynames`, with or without `.json`, over a verified RxNorm subset plus concepts you add; browse it at `/_inspector`)
@@ -61,6 +61,12 @@ Health and life science services use a fixed range starting at `http://localhost
61
61
  - **Oura** on `http://localhost:4121` (OAuth 2.0 with a consent page, and API v2 `/v2/usercollection` documents: personal info, daily sleep, activity, readiness, and SpO2 with contributors and scores, sleep periods, and heart rate, with `next_token` paging and scope checks, for synthetic users)
62
62
  - **Withings** on `http://localhost:4122` (OAuth 2.0 with a consent page and `requesttoken`, Measure `getmeas` for weight, blood pressure, heart pulse, and SpO2, `getactivity`, Sleep `getsummary`, `getdevice`, and Notify subscriptions that call your callback URL, with Withings' status codes in HTTP 200 responses, for synthetic users)
63
63
  - **Terra** on `http://localhost:4123` (widget sessions and a connect page that link synthetic users to providers such as Fitbit, Oura, Withings, and Dexcom, normalized daily, sleep, activity, and body data returned inline or sent to your webhook, and `terra-signature` signed auth, deauth, and data events)
64
+ - **DICOMweb** on `http://localhost:4124` (QIDO-RS search of studies, series, and instances; WADO-RS retrieve of Part 10 instances, `application/dicom+json` metadata, frames, bulk data, and rendered PNGs; STOW-RS store with the standard response; synthetic 64x64 CT and MR phantoms with `2.25` UIDs; browse them at `/_inspector`)
65
+ - **HL7 v2** on `http://localhost:4125` with an MLLP listener on `localhost:2575` (original mode ACKs for any message; ADT admits, transfers, discharges, updates, and merges, ORU results, and ORM and OML orders applied to a synthetic patient registry; `POST /messages` to send over HTTP, `/samples/adt-a01` and others for synthetic messages, and `POST /send` to test your own MLLP receiver; browse messages and patients at `/_inspector`)
66
+ - **Veeva Vault** on `http://localhost:4126` (REST API under `/api/{version}`: `POST /auth` sessions, Vault object records with create, upsert, update, and delete in JSON or CSV, documents with versions and files, object and document metadata, and VQL queries with relationship fields and paging; synthetic products, studies, sites, countries, and trial documents; browse them at `/_inspector`)
67
+ - **Medidata Rave** on `http://localhost:4127` (Rave Web Services under `/RaveWebServices` with HTTP Basic auth: study lists, CRF metadata as ODM, subjects with status and links, ODM clinical data datasets by study, subject, and form, `ClinicalAuditRecords` paging, and `PostODMClinicalData` imports with Rave's `Response` format; synthetic studies with demographics, vital signs, and adverse events; browse subjects at `/_inspector`)
68
+
69
+ End-to-end examples, each with a test that runs the whole flow: a [SMART on FHIR app against Epic](examples/smart-on-fhir-epic), an [HL7 v2 feed into FHIR](examples/hl7v2-to-fhir), and an [incremental EDC sync from Rave](examples/rave-edc-sync).
64
70
 
65
71
  Stripe webhooks configured with a secret include a `Stripe-Signature` header signed over the timestamp and raw request body.
66
72
 
package/dist/api.d.ts CHANGED
@@ -249,7 +249,7 @@ declare function defineConfig<Definitions extends Record<string, EmulatorDefinit
249
249
  tokens?: EmulateConfig["tokens"];
250
250
  }): typeof config;
251
251
 
252
- declare const HEALTH_SERVICE_NAME_LIST: readonly ["fhir", "epic", "openfda", "rxnav", "clinicaltrials", "ncbi", "nppes", "benchling", "redcap", "cerner", "athena", "bluebutton", "cdshooks", "redox", "healthlake", "gcphealthcare", "azurehealth", "stedi", "availity", "dexcom", "fitbit", "oura", "withings", "terra"];
252
+ declare const HEALTH_SERVICE_NAME_LIST: readonly ["fhir", "epic", "openfda", "rxnav", "clinicaltrials", "ncbi", "nppes", "benchling", "redcap", "cerner", "athena", "bluebutton", "cdshooks", "redox", "healthlake", "gcphealthcare", "azurehealth", "stedi", "availity", "dexcom", "fitbit", "oura", "withings", "terra", "dicomweb", "hl7v2", "veeva", "rave"];
253
253
  type HealthServiceName = (typeof HEALTH_SERVICE_NAME_LIST)[number];
254
254
 
255
255
  declare const SERVICE_NAME_LIST: readonly ["vercel", "github", "google", "slack", "apple", "microsoft", "okta", "aws", "resend", "stripe", "mongoatlas", "clerk", "linear", "twilio"];
package/dist/api.js CHANGED
@@ -1968,7 +1968,11 @@ var HEALTH_SERVICE_NAME_LIST = [
1968
1968
  "fitbit",
1969
1969
  "oura",
1970
1970
  "withings",
1971
- "terra"
1971
+ "terra",
1972
+ "dicomweb",
1973
+ "hl7v2",
1974
+ "veeva",
1975
+ "rave"
1972
1976
  ];
1973
1977
  var HEALTH_SERVICE_NAMES = HEALTH_SERVICE_NAME_LIST;
1974
1978
  var HEALTH_SERVICE_REGISTRY = {
@@ -1976,7 +1980,7 @@ var HEALTH_SERVICE_REGISTRY = {
1976
1980
  label: "FHIR R4 server emulator",
1977
1981
  endpoints: "create, read, vread, update (including create on update), JSON Patch, logical delete, _history, search with includes and chaining, batch and transaction Bundles, CapabilityStatement at /metadata, Patient/$everything, Bulk Data $export, SMART App Launch and Backend Services, ETag and If-Match, generated synthetic patients, terminology $lookup and $validate-code, inspector at /_inspector",
1978
1982
  async load() {
1979
- const mod = await import("./dist-GRGMAU6B.js");
1983
+ const mod = await import("./dist-YLPKKYLR.js");
1980
1984
  return { plugin: mod.fhirPlugin, seedFromConfig: mod.seedFromConfig };
1981
1985
  },
1982
1986
  defaultFallback() {
@@ -2001,7 +2005,7 @@ var HEALTH_SERVICE_REGISTRY = {
2001
2005
  label: "Epic FHIR R4 emulator",
2002
2006
  endpoints: "Epic URL shape (/api/FHIR/R4) over the full FHIR server, OAuth 2.0 at /oauth2/authorize and /oauth2/token with SMART App Launch and Backend Services, __epic.dstu2.patient in token responses, informational OperationOutcome (4101) on empty searches, Schedules and Slots with Appointment/$find and Appointment/$book, generated synthetic patients, inspector at /_inspector",
2003
2007
  async load() {
2004
- const mod = await import("./dist-2AQ4NEIG.js");
2008
+ const mod = await import("./dist-QNFWXDSF.js");
2005
2009
  return { plugin: mod.epicPlugin, seedFromConfig: mod.seedFromConfig };
2006
2010
  },
2007
2011
  defaultFallback() {
@@ -2154,7 +2158,7 @@ var HEALTH_SERVICE_REGISTRY = {
2154
2158
  label: "Oracle Health (Cerner) Millennium FHIR R4 emulator",
2155
2159
  endpoints: "Millennium tenant URL shape (/r4/{tenant}) over the full FHIR server, persona OAuth endpoints under /tenants/{tenant}/protocols/oauth2/profiles/smart-v1, system accounts with client_credentials and a client secret, tenant and username in token responses, Millennium's required search parameters, generated synthetic patients, inspector at /_inspector",
2156
2160
  async load() {
2157
- const mod = await import("./dist-ID2YPHQQ.js");
2161
+ const mod = await import("./dist-B7QPLCAG.js");
2158
2162
  return { plugin: mod.cernerPlugin, seedFromConfig: mod.seedFromConfig };
2159
2163
  },
2160
2164
  defaultFallback() {
@@ -2181,7 +2185,7 @@ var HEALTH_SERVICE_REGISTRY = {
2181
2185
  label: "athenahealth API emulator",
2182
2186
  endpoints: "OAuth client credentials at /oauth2/v1/token; proprietary REST under /v1/{practiceid}: departments, providers, patients (search, read, create), chart problems, allergies, medications, vitals, appointments open, booked, book, cancel, with offset and limit paging; FHIR R4 under /fhir/r4 with ah-practice; synthetic records; inspector at /_inspector",
2183
2187
  async load() {
2184
- const mod = await import("./dist-G4ZKPBOD.js");
2188
+ const mod = await import("./dist-2SPD4VKT.js");
2185
2189
  return { plugin: mod.athenaPlugin, seedFromConfig: mod.seedFromConfig };
2186
2190
  },
2187
2191
  defaultFallback() {
@@ -2204,7 +2208,7 @@ var HEALTH_SERVICE_REGISTRY = {
2204
2208
  label: "CMS Blue Button 2.0 emulator",
2205
2209
  endpoints: "Patient access OAuth at /v2/o/authorize/ and /v2/o/token/ with a beneficiary picker, /v2/connect/userinfo, FHIR R4 at /v2/fhir with Patient (synthetic MBIs), Coverage (Parts A, B, D), and ExplanationOfBenefit (carrier and Part D claims), read-only and token-only; synthetic beneficiaries",
2206
2210
  async load() {
2207
- const mod = await import("./dist-OXKMJ5KL.js");
2211
+ const mod = await import("./dist-O5VNO6R3.js");
2208
2212
  return { plugin: mod.bluebuttonPlugin, seedFromConfig: mod.seedFromConfig };
2209
2213
  },
2210
2214
  defaultFallback() {
@@ -2231,7 +2235,7 @@ var HEALTH_SERVICE_REGISTRY = {
2231
2235
  label: "CDS Hooks emulator (simulated EHR and sample services)",
2232
2236
  endpoints: "Simulated EHR: POST /ehr/fire reads your CDS service discovery and fires patient-view, order-sign, order-select, or encounter-start with a signed JWT (JWKS at /.well-known/jwks.json), context, prefetch, and fhirAuthorization from its FHIR server at /fhir, then validates the cards; GET /ehr/invocations; sample CDS services at /cds-services (patient-greeting, allergy-check) with feedback; inspector form at /_inspector",
2233
2237
  async load() {
2234
- const mod = await import("./dist-YC3GSNFQ.js");
2238
+ const mod = await import("./dist-UUOAP6EN.js");
2235
2239
  return { plugin: mod.cdshooksPlugin, seedFromConfig: mod.seedFromConfig };
2236
2240
  },
2237
2241
  defaultFallback() {
@@ -2247,7 +2251,7 @@ var HEALTH_SERVICE_REGISTRY = {
2247
2251
  label: "Redox API emulator",
2248
2252
  endpoints: "Authentication (/auth/authenticate, /auth/refreshToken, /v2/auth/token), POST /endpoint for Redox JSON data models (PatientSearch Query, ClinicalSummary PatientQuery, PatientAdmin NewPatient and PatientUpdate, Scheduling New, Reschedule, Cancel, Results, Notes, Media) with Meta.Errors, destination webhooks with the verification-token header, the challenge handshake, and POST /ehr/send to simulate EHR events; synthetic records; inspector at /_inspector",
2249
2253
  async load() {
2250
- const mod = await import("./dist-ID3HOBV6.js");
2254
+ const mod = await import("./dist-D4XTX54S.js");
2251
2255
  return { plugin: mod.redoxPlugin, seedFromConfig: mod.seedFromConfig };
2252
2256
  },
2253
2257
  defaultFallback() {
@@ -2268,7 +2272,7 @@ var HEALTH_SERVICE_REGISTRY = {
2268
2272
  label: "AWS HealthLake emulator",
2269
2273
  endpoints: "HealthLake JSON control plane at POST / (X-Amz-Target HealthLake.*: Create, Describe, List, Delete FHIR datastores; Start, Describe, List import and export jobs) and a FHIR R4 data plane per datastore at /datastore/{id}/r4, with SigV4 verification for service healthlake; a default datastore preloaded with synthetic data; inspector at /_inspector",
2270
2274
  async load() {
2271
- const mod = await import("./dist-WSHMJF6J.js");
2275
+ const mod = await import("./dist-MOSHZOI2.js");
2272
2276
  return { plugin: mod.healthlakePlugin, seedFromConfig: mod.seedFromConfig };
2273
2277
  },
2274
2278
  defaultFallback() {
@@ -2291,7 +2295,7 @@ var HEALTH_SERVICE_REGISTRY = {
2291
2295
  label: "Google Cloud Healthcare API emulator (FHIR stores)",
2292
2296
  endpoints: "Cloud Healthcare API v1 under /v1/projects/{project}/locations/{location}: datasets (create as operations, get, list, delete, operations), FHIR stores (create, get, list, patch with updateMask, delete, :export and :import operations), and a FHIR R4 API per store at .../fhirStores/{store}/fhir honoring enableUpdateCreate; any Bearer token; Google JSON errors; inspector at /_inspector",
2293
2297
  async load() {
2294
- const mod = await import("./dist-CKAIZSL3.js");
2298
+ const mod = await import("./dist-R2RM35T5.js");
2295
2299
  return { plugin: mod.gcphealthcarePlugin, seedFromConfig: mod.seedFromConfig };
2296
2300
  },
2297
2301
  defaultFallback() {
@@ -2320,7 +2324,7 @@ var HEALTH_SERVICE_REGISTRY = {
2320
2324
  label: "Azure Health Data Services emulator (FHIR services)",
2321
2325
  endpoints: "FHIR services per workspace at /{workspace}-{fhirservice} (the path form of {workspace}-{fhirservice}.fhir.azurehealthcareapis.com), each a full FHIR R4 server; Entra ID Bearer tokens required (public metadata), verified against an issuer's JWKS such as the emuhealth Microsoft emulator when azurehealth.entra is set; inspector at /_inspector",
2322
2326
  async load() {
2323
- const mod = await import("./dist-NZYMC7MC.js");
2327
+ const mod = await import("./dist-HUGQE3UQ.js");
2324
2328
  return { plugin: mod.azurehealthPlugin, seedFromConfig: mod.seedFromConfig };
2325
2329
  },
2326
2330
  defaultFallback() {
@@ -2346,7 +2350,7 @@ var HEALTH_SERVICE_REGISTRY = {
2346
2350
  label: "Stedi healthcare clearinghouse emulator",
2347
2351
  endpoints: "Stedi 2024-04-01 healthcare APIs with an API key: eligibility v3 (270/271), professional claims v3 submission (837P) with immediate adjudication, claim status v2 (276/277), 835 ERA reports by transaction, transactions list, payers; transaction.processed.v2 events to webhooks; synthetic payers and members; inspector at /_inspector",
2348
2352
  async load() {
2349
- const mod = await import("./dist-NIYFNDR5.js");
2353
+ const mod = await import("./dist-XQO4ECK7.js");
2350
2354
  return { plugin: mod.stediPlugin, seedFromConfig: mod.seedFromConfig };
2351
2355
  },
2352
2356
  defaultFallback() {
@@ -2365,7 +2369,7 @@ var HEALTH_SERVICE_REGISTRY = {
2365
2369
  label: "Availity API emulator",
2366
2370
  endpoints: "Availity HIPAA transaction APIs under /availity: OAuth client credentials (/v1/token), availity-payer-list, v1/configurations, asynchronous v1/coverages (270/271) and v1/claim-statuses (276/277) polled until statusCode 4, v2/service-reviews (278) with Location polling, and Demo plan X-Api-Mock-Scenario-ID scenarios; synthetic payers, members, and claims; inspector at /_inspector",
2367
2371
  async load() {
2368
- const mod = await import("./dist-BGTZW3FR.js");
2372
+ const mod = await import("./dist-7IG4HX3B.js");
2369
2373
  return { plugin: mod.availityPlugin, seedFromConfig: mod.seedFromConfig };
2370
2374
  },
2371
2375
  defaultFallback() {
@@ -2385,7 +2389,7 @@ var HEALTH_SERVICE_REGISTRY = {
2385
2389
  label: "Dexcom API v3 emulator",
2386
2390
  endpoints: "OAuth 2.0 at /v2/oauth2/login (consent page with synthetic users) and /v2/oauth2/token; /v3/users/self/egvs (5 minute glucose, 30 day windows), events, devices, alerts, calibrations, dataRange; synthetic G7 users; inspector at /_inspector",
2387
2391
  async load() {
2388
- const mod = await import("./dist-6GBOXHHG.js");
2392
+ const mod = await import("./dist-SRMVCWKJ.js");
2389
2393
  return { plugin: mod.dexcomPlugin, seedFromConfig: mod.seedFromConfig };
2390
2394
  },
2391
2395
  defaultFallback() {
@@ -2407,7 +2411,7 @@ var HEALTH_SERVICE_REGISTRY = {
2407
2411
  label: "Fitbit Web API emulator",
2408
2412
  endpoints: "OAuth 2.0 (/oauth2/authorize consent page, /oauth2/token with Basic auth, /oauth2/revoke); /1/user/-/profile.json, activities/date, activity time series (steps, distance, calories), heart rate with intraday, /1.2 sleep with stages, weight logs; scopes, error envelope, rate limit headers; synthetic users; inspector at /_inspector",
2409
2413
  async load() {
2410
- const mod = await import("./dist-F4OEZZBR.js");
2414
+ const mod = await import("./dist-TRI7TRKP.js");
2411
2415
  return { plugin: mod.fitbitPlugin, seedFromConfig: mod.seedFromConfig };
2412
2416
  },
2413
2417
  defaultFallback() {
@@ -2429,7 +2433,7 @@ var HEALTH_SERVICE_REGISTRY = {
2429
2433
  label: "Oura API v2 emulator",
2430
2434
  endpoints: "OAuth 2.0 (/oauth/authorize consent page, /oauth/token); /v2/usercollection personal_info, daily_sleep, daily_activity, daily_readiness, daily_spo2, sleep (periods), heartrate, workout, session, ring_configuration, with start_date and end_date, next_token paging, documents by id, scopes, and {detail} errors; synthetic users; inspector at /_inspector",
2431
2435
  async load() {
2432
- const mod = await import("./dist-2YZQBLX2.js");
2436
+ const mod = await import("./dist-LYW423OA.js");
2433
2437
  return { plugin: mod.ouraPlugin, seedFromConfig: mod.seedFromConfig };
2434
2438
  },
2435
2439
  defaultFallback() {
@@ -2451,7 +2455,7 @@ var HEALTH_SERVICE_REGISTRY = {
2451
2455
  label: "Withings API emulator",
2452
2456
  endpoints: "OAuth 2.0 (/oauth2_user/authorize2 consent page, /v2/oauth2 action=requesttoken); /measure getmeas (weight, blood pressure, heart pulse, SpO2), /v2/measure getactivity, /v2/sleep getsummary, /v2/user getdevice, /notify subscribe, list, revoke with callbacks; HTTP 200 with status codes; synthetic users; inspector at /_inspector",
2453
2457
  async load() {
2454
- const mod = await import("./dist-IMZOZNB5.js");
2458
+ const mod = await import("./dist-P2Q4A2DE.js");
2455
2459
  return { plugin: mod.withingsPlugin, seedFromConfig: mod.seedFromConfig };
2456
2460
  },
2457
2461
  defaultFallback() {
@@ -2473,7 +2477,7 @@ var HEALTH_SERVICE_REGISTRY = {
2473
2477
  label: "Terra API emulator",
2474
2478
  endpoints: "dev-id and x-api-key auth; /v2/auth/generateWidgetSession and /v2/auth/authenticateUser with a connect page (provider, then a synthetic account), /v2/auth/deauthenticateUser, /v2/userInfo, /v2/subscriptions; normalized /v2/daily, sleep, activity, body (with glucose for CGM providers) inline (to_webhook=false) or to your webhook signed with terra-signature; inspector at /_inspector",
2475
2479
  async load() {
2476
- const mod = await import("./dist-LHSWVR7A.js");
2480
+ const mod = await import("./dist-W3BWZ4HD.js");
2477
2481
  return { plugin: mod.terraPlugin, seedFromConfig: mod.seedFromConfig };
2478
2482
  },
2479
2483
  defaultFallback() {
@@ -2487,6 +2491,85 @@ var HEALTH_SERVICE_REGISTRY = {
2487
2491
  }
2488
2492
  }
2489
2493
  }
2494
+ },
2495
+ dicomweb: {
2496
+ label: "DICOMweb (QIDO-RS, WADO-RS, STOW-RS) emulator",
2497
+ endpoints: "QIDO-RS search at /studies, /series, /instances (keyword or tag matching, wildcards, date ranges, fuzzymatching, includefield, limit, offset); WADO-RS retrieve as multipart/related application/dicom, metadata as application/dicom+json, frames, bulk data, and rendered PNG; STOW-RS store with the standard response and failure reasons; DELETE; synthetic CT and MR studies; inspector at /_inspector",
2498
+ async load() {
2499
+ const mod = await import("./dist-UXGG2BLX.js");
2500
+ return { plugin: mod.dicomwebPlugin, seedFromConfig: mod.seedFromConfig };
2501
+ },
2502
+ defaultFallback() {
2503
+ return { login: "dicomweb-user", id: 1, scopes: [] };
2504
+ },
2505
+ initConfig: {
2506
+ dicomweb: {
2507
+ generate: {
2508
+ studies: 3,
2509
+ instancesPerSeries: 3
2510
+ }
2511
+ }
2512
+ }
2513
+ },
2514
+ hl7v2: {
2515
+ label: "HL7 v2 (MLLP) emulator",
2516
+ endpoints: "MLLP listener on port 2575 that returns original mode ACKs (AA, AE, AR); ADT admit, transfer, discharge, update, cancel, and merge, ORU results, and ORM and OML orders applied to a synthetic patient registry; HTTP API to post messages, list messages and patients, get sample messages, and send to your MLLP receiver; inspector at /_inspector",
2517
+ async load() {
2518
+ const mod = await import("./dist-UDWI7IO6.js");
2519
+ return { plugin: mod.hl7v2Plugin, seedFromConfig: mod.seedFromConfig, listen: mod.listen };
2520
+ },
2521
+ defaultFallback() {
2522
+ return { login: "hl7v2-user", id: 1, scopes: [] };
2523
+ },
2524
+ initConfig: {
2525
+ hl7v2: {
2526
+ mllp: {
2527
+ port: 2575
2528
+ }
2529
+ }
2530
+ }
2531
+ },
2532
+ veeva: {
2533
+ label: "Veeva Vault REST API emulator",
2534
+ endpoints: "Vault REST API under /api/{version}: username and password auth with session IDs, Vault object records (list, retrieve, create, upsert with idParam, update, delete; JSON or CSV), documents (list, retrieve, versions, file download, create, update, delete), object and document metadata, and VQL queries with relationships and paging; synthetic products, studies, sites, countries, and trial documents; inspector at /_inspector",
2535
+ async load() {
2536
+ const mod = await import("./dist-SYCRZXDL.js");
2537
+ return { plugin: mod.veevaPlugin, seedFromConfig: mod.seedFromConfig };
2538
+ },
2539
+ defaultFallback() {
2540
+ return { login: "veeva-user", id: 1, scopes: [] };
2541
+ },
2542
+ initConfig: {
2543
+ veeva: {
2544
+ users: [
2545
+ {
2546
+ username: "admin@synthetic-vault.example",
2547
+ password: "synthetic-password"
2548
+ }
2549
+ ]
2550
+ }
2551
+ }
2552
+ },
2553
+ rave: {
2554
+ label: "Medidata Rave Web Services (RWS) emulator",
2555
+ endpoints: "Rave Web Services under /RaveWebServices: version and diagnostics, HTTP Basic auth, study and metadata study lists, CRF versions and full ODM metadata, subjects with status and links, ODM clinical data datasets by study, subject, CRF version, and form, ClinicalAuditRecords with paging, and webservice.aspx?PostODMClinicalData imports that apply transactionally; synthetic studies EMU-101 and EMU-202 in Prod and UAT; inspector at /_inspector",
2556
+ async load() {
2557
+ const mod = await import("./dist-LU2SZMDZ.js");
2558
+ return { plugin: mod.ravePlugin, seedFromConfig: mod.seedFromConfig };
2559
+ },
2560
+ defaultFallback() {
2561
+ return { login: "rave-user", id: 1, scopes: [] };
2562
+ },
2563
+ initConfig: {
2564
+ rave: {
2565
+ users: [
2566
+ {
2567
+ username: "rws.synthetic",
2568
+ password: "synthetic-password"
2569
+ }
2570
+ ]
2571
+ }
2572
+ }
2490
2573
  }
2491
2574
  };
2492
2575
  var HEALTH_PORT_OFFSET = 100;
@@ -3182,6 +3265,7 @@ async function createBuiltinEmulator(options) {
3182
3265
  }
3183
3266
  const loaded = await entry.load();
3184
3267
  let handler;
3268
+ let listener;
3185
3269
  const httpServer = serve({
3186
3270
  fetch: (request) => handler ? handler(request) : new Response("Starting", { status: 503 }),
3187
3271
  port,
@@ -3226,6 +3310,13 @@ async function createBuiltinEmulator(options) {
3226
3310
  }
3227
3311
  };
3228
3312
  seed();
3313
+ listener = await loaded.listen?.({
3314
+ store,
3315
+ webhooks,
3316
+ baseUrl,
3317
+ config: svcSeedConfig,
3318
+ hostname: options.hostname
3319
+ });
3229
3320
  handler = app.fetch;
3230
3321
  let closing;
3231
3322
  return {
@@ -3240,10 +3331,11 @@ async function createBuiltinEmulator(options) {
3240
3331
  seed();
3241
3332
  },
3242
3333
  close() {
3243
- return closing ??= closeHttpServer(httpServer);
3334
+ return closing ??= Promise.all([closeHttpServer(httpServer), listener?.close()]).then(() => void 0);
3244
3335
  }
3245
3336
  };
3246
3337
  } catch (error) {
3338
+ await listener?.close();
3247
3339
  await closeHttpServer(httpServer);
3248
3340
  throw error;
3249
3341
  }