@awell-health/awell-extensions 2.1.147 → 2.1.149

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 (37) hide show
  1. package/dist/extensions/markdown.json +1 -1
  2. package/dist/extensions/medplum/actions/createResource/createResource.js +1 -0
  3. package/dist/extensions/medplum/actions/createResource/createResource.js.map +1 -1
  4. package/dist/extensions/metriport/actions/index.d.ts +21 -1
  5. package/dist/extensions/metriport/actions/webhookBundle/bundle/__testdata__/patientAdmitBundle.d.ts +22 -0
  6. package/dist/extensions/metriport/actions/webhookBundle/bundle/__testdata__/patientAdmitBundle.js +262 -0
  7. package/dist/extensions/metriport/actions/webhookBundle/bundle/__testdata__/patientAdmitBundle.js.map +1 -0
  8. package/dist/extensions/metriport/actions/webhookBundle/bundle/account.d.ts +10 -0
  9. package/dist/extensions/metriport/actions/webhookBundle/bundle/account.js +26 -0
  10. package/dist/extensions/metriport/actions/webhookBundle/bundle/account.js.map +1 -0
  11. package/dist/extensions/metriport/actions/webhookBundle/bundle/constants.d.ts +31 -0
  12. package/dist/extensions/metriport/actions/webhookBundle/bundle/constants.js +41 -0
  13. package/dist/extensions/metriport/actions/webhookBundle/bundle/constants.js.map +1 -0
  14. package/dist/extensions/metriport/actions/webhookBundle/bundle/entries.d.ts +27 -0
  15. package/dist/extensions/metriport/actions/webhookBundle/bundle/entries.js +67 -0
  16. package/dist/extensions/metriport/actions/webhookBundle/bundle/entries.js.map +1 -0
  17. package/dist/extensions/metriport/actions/webhookBundle/bundle/index.d.ts +35 -0
  18. package/dist/extensions/metriport/actions/webhookBundle/bundle/index.js +68 -0
  19. package/dist/extensions/metriport/actions/webhookBundle/bundle/index.js.map +1 -0
  20. package/dist/extensions/metriport/actions/webhookBundle/bundle/provenance.d.ts +16 -0
  21. package/dist/extensions/metriport/actions/webhookBundle/bundle/provenance.js +92 -0
  22. package/dist/extensions/metriport/actions/webhookBundle/bundle/provenance.js.map +1 -0
  23. package/dist/extensions/metriport/actions/webhookBundle/bundle/references.d.ts +28 -0
  24. package/dist/extensions/metriport/actions/webhookBundle/bundle/references.js +65 -0
  25. package/dist/extensions/metriport/actions/webhookBundle/bundle/references.js.map +1 -0
  26. package/dist/extensions/metriport/actions/webhookBundle/dataPoints.d.ts +9 -0
  27. package/dist/extensions/metriport/actions/webhookBundle/dataPoints.js +9 -0
  28. package/dist/extensions/metriport/actions/webhookBundle/dataPoints.js.map +1 -1
  29. package/dist/extensions/metriport/actions/webhookBundle/fields.d.ts +21 -0
  30. package/dist/extensions/metriport/actions/webhookBundle/fields.js +31 -0
  31. package/dist/extensions/metriport/actions/webhookBundle/fields.js.map +1 -1
  32. package/dist/extensions/metriport/actions/webhookBundle/getWebhookBundle.js +16 -1
  33. package/dist/extensions/metriport/actions/webhookBundle/getWebhookBundle.js.map +1 -1
  34. package/dist/extensions/metriport/actions/webhookBundle/validation.d.ts +6 -0
  35. package/dist/extensions/metriport/actions/webhookBundle/validation.js +2 -0
  36. package/dist/extensions/metriport/actions/webhookBundle/validation.js.map +1 -1
  37. package/package.json +1 -1
@@ -160,7 +160,7 @@
160
160
  "changelog": "# MessageBird changelog"
161
161
  },
162
162
  "metriport": {
163
- "readme": "---\ntitle: Metriport\ndescription: Metriport is Plaid for healthcare data.\n---\n# Metriport\n\nMetriport is Plaid for healthcare data. We help digital health companies access and manage patient health and medical data, through an open-source and universal API.\n\nThrough a single integration, our API enables modern health companies to get the comprehensive patient data they need from both HIEs and EHRs, as well as popular wearable devices.\n\nAs a developer-first interoperability solution, Metriport is powering the next wave of innovative companies, accelerating a revolution in digital health.\n\nTo learn more visit [https://www.metriport.com/](https://www.metriport.com/)\n# Extension settings\n\nIn order to set up this extension, **you will need to provide a Metriport API key**. You can obtain an API key via the Metriport dashboard by selecting the `Developers tab`. To learn more on how to get started with Metriport visit our [quick start docs](https://docs.metriport.com/medical-api/getting-started/quickstart) for our Medical API. Also, to better understand how our API keys work check out the [API Keys section](https://docs.metriport.com/home/api-info/api-keys) of our docs as well.\n\n# Custom Actions\n\n**GENERAL NOTE: Make sure to create Organizations and Facilities in Metriport before using this extension. A Patient must be associated with a Facility by providing the facilityId when stated in the actions.**\n\n## Create Patient\n\nCreates a Patient in Metriport for the specified Facility where the Patient is receiving care.\n\nOptionally, providing a **Cohort** ID enrolls the Patient in real-time monitoring by adding them to that cohort. Note that enrolling a Patient in real-time monitoring has downstream consequences: once you start receiving updates about the Patient, you are expected to contribute data back to Metriport.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/create-patient) for more info.\n\n## Update Patient\n\nUpdates the specified Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/update-patient) for more info.\n\n## Get Patient\n\nRetrieves the specified Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/get-patient) for more info.\n\n## Remove Patient\n\nRemoves a Patient at Metriport and at HIEs the Patient is linked to.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/delete-patient) for more info.\n\n## List Documents\n\nLists all Documents that can be retrieved for a Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/list-documents) for more info.\n\n**NOTE: It also returns the status of querying Document references across HIEs, indicating whether there is an asynchronous query in progress (status processing) or not (status completed). If the query is in progress, you will also receive the total number of Documents to be queried as well as the ones that have already been completed.**\n\n## Query Documents\n\nTriggers a Document query for the specified Patient across HIEs.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/start-document-query) for more info.\n\n**NOTE: When executed, this endpoint triggers an asynchronous Document query with HIEs and immediately returns the status of Document query, processing .**\n\n## Get Document Url\n\nGets a presigned URL for downloading the specified Document.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/get-document) for more info.\n\n**NOTE: This endpoint returns a URL which you can use to download the specified Document using the file name provided from the List Documents endpoint.**\n\n## Remove Patient from Cohort\n\nRemoves the specified Patient from a cohort.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/cohort/remove-patients-from-cohort) for more info.\n\n## Get Webhook Bundle\n\nFetches the FHIR bundle from a Metriport webhook payload URL — e.g. the [Encounter Bundle](https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle) from an ADT notification, or a discharge summary. Pass the `bundleUrl` data point emitted by the **Enrollment** webhook; the action downloads the bundle and returns it on the `bundle` data point.\n\n**NOTE: Metriport pre-signed URLs are only valid for 10 minutes, so this action should run early in the care flow, shortly after the enrollment webhook fires.**\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `url` | string | The pre-signed payload URL to fetch (the webhook's `bundleUrl` data point). |\n\n| Data point | Type | Description |\n| --- | --- | --- |\n| `bundle` | json | The FHIR bundle fetched from the URL. |\n\n# Webhooks\n\n## Enrollment\n\nAn enrollment trigger that starts a care flow when Metriport sends a [real-time patient notification](https://docs.metriport.com/medical-api/handling-data/realtime-patient-notifications).\n\nMetriport POSTs every notification type to the same endpoint, so this webhook discriminates on the notification `type` and only enrolls on two events. The `eventType` data point carries the raw Metriport webhook type:\n\n- `patient.admit` (HL7 ADT^A01) → `eventType` = `patient.admit`. The payload carries a pre-signed URL to the [FHIR Encounter Bundle](https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle).\n- `medical.discharge-summary` → `eventType` = `medical.discharge-summary`. This event is currently undocumented by Metriport and is modelled on the published `medical.*` webhook family (a `patients` array).\n\nThe webhook validates the request, emits the data points (including the pre-signed bundle URL on `bundleUrl`), and replies immediately — it does **not** download the bundle. Fetch the bundle later in the care flow with the **Get Webhook Bundle** action, using the `bundleUrl` data point. Because the URL expires after 10 minutes, run that action early.\n\nUse the `eventType` data point in your care flow to branch on admit vs discharge. Every other notification type (`patient.discharge`, `patient.transfer`, ...) is acknowledged with a `200` but does not enroll a patient. Metriport [verification `ping` messages](https://docs.metriport.com/medical-api/getting-started/webhooks#the-ping-message) are answered with a `200` that echoes the ping value back as `pong: <value>`.\n\n### Data points\n\n| Data point | Type | Description |\n| --- | --- | --- |\n| `eventType` | string | The Metriport webhook type: `patient.admit` or `medical.discharge-summary` |\n| `metriportPatientId` | string | The Metriport patient ID (also used as the patient identifier for enrollment) |\n| `externalId` | string | Your external patient ID, if provided to Metriport |\n| `admitTimestamp` | date | When the patient was admitted (admit events only) |\n| `whenSourceSent` | date | When the source sent the notification, if available (admit events) |\n| `messageId` | string | The Metriport message ID for the notification |\n| `bundleUrl` | string | Pre-signed URL to the FHIR bundle; fetch it with the **Get Webhook Bundle** action (valid for 10 minutes) |\n\n### Verifying incoming requests\n\nOptionally set the **Webhook Key** setting to the webhook key from the Metriport dashboard (Settings/Developers tab). Metriport [authenticates each webhook](https://docs.metriport.com/medical-api/getting-started/webhooks#authentication) with an HMAC-SHA256 signature of the raw request body, keyed with your webhook key and sent in the `x-metriport-signature` header. When the setting is populated, the webhook recomputes the HMAC over the raw body and rejects any request whose signature is missing or does not match (`401`). When left empty, requests are not verified.\n\n## More Info\n\nFor more information on how to integrate with Metriport please visit our [Medical API docs](https://docs.metriport.com/medical-api/getting-started/quickstart)\n",
163
+ "readme": "---\ntitle: Metriport\ndescription: Metriport is Plaid for healthcare data.\n---\n# Metriport\n\nMetriport is Plaid for healthcare data. We help digital health companies access and manage patient health and medical data, through an open-source and universal API.\n\nThrough a single integration, our API enables modern health companies to get the comprehensive patient data they need from both HIEs and EHRs, as well as popular wearable devices.\n\nAs a developer-first interoperability solution, Metriport is powering the next wave of innovative companies, accelerating a revolution in digital health.\n\nTo learn more visit [https://www.metriport.com/](https://www.metriport.com/)\n# Extension settings\n\nIn order to set up this extension, **you will need to provide a Metriport API key**. You can obtain an API key via the Metriport dashboard by selecting the `Developers tab`. To learn more on how to get started with Metriport visit our [quick start docs](https://docs.metriport.com/medical-api/getting-started/quickstart) for our Medical API. Also, to better understand how our API keys work check out the [API Keys section](https://docs.metriport.com/home/api-info/api-keys) of our docs as well.\n\n# Custom Actions\n\n**GENERAL NOTE: Make sure to create Organizations and Facilities in Metriport before using this extension. A Patient must be associated with a Facility by providing the facilityId when stated in the actions.**\n\n## Create Patient\n\nCreates a Patient in Metriport for the specified Facility where the Patient is receiving care.\n\nOptionally, providing a **Cohort** ID enrolls the Patient in real-time monitoring by adding them to that cohort. Note that enrolling a Patient in real-time monitoring has downstream consequences: once you start receiving updates about the Patient, you are expected to contribute data back to Metriport.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/create-patient) for more info.\n\n## Update Patient\n\nUpdates the specified Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/update-patient) for more info.\n\n## Get Patient\n\nRetrieves the specified Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/get-patient) for more info.\n\n## Remove Patient\n\nRemoves a Patient at Metriport and at HIEs the Patient is linked to.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/patient/delete-patient) for more info.\n\n## List Documents\n\nLists all Documents that can be retrieved for a Patient.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/list-documents) for more info.\n\n**NOTE: It also returns the status of querying Document references across HIEs, indicating whether there is an asynchronous query in progress (status processing) or not (status completed). If the query is in progress, you will also receive the total number of Documents to be queried as well as the ones that have already been completed.**\n\n## Query Documents\n\nTriggers a Document query for the specified Patient across HIEs.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/start-document-query) for more info.\n\n**NOTE: When executed, this endpoint triggers an asynchronous Document query with HIEs and immediately returns the status of Document query, processing .**\n\n## Get Document Url\n\nGets a presigned URL for downloading the specified Document.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/document/get-document) for more info.\n\n**NOTE: This endpoint returns a URL which you can use to download the specified Document using the file name provided from the List Documents endpoint.**\n\n## Remove Patient from Cohort\n\nRemoves the specified Patient from a cohort.\n\nVisit [endpoint docs](https://docs.metriport.com/medical-api/api-reference/cohort/remove-patients-from-cohort) for more info.\n\n## Get Webhook Bundle\n\nFetches the FHIR bundle from a Metriport webhook payload URL — e.g. the [Encounter Bundle](https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle) from an ADT notification, or a discharge summary. Pass the `bundleUrl` data point emitted by the **Enrollment** webhook; the action downloads the bundle and returns it on the `bundle` data point.\n\nWhen the payload is a Patient Encounter Bundle, the action also rewrites it into an executable FHIR transaction and returns that on the `transactionBundle` data point, ready to hand to the Medplum **Find or create resource** action.\n\n**NOTE: Metriport pre-signed URLs are only valid for 10 minutes, so this action should run early in the care flow, shortly after the enrollment webhook fires.**\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `url` | string | The pre-signed payload URL to fetch (the webhook's `bundleUrl` data point). |\n| `eventType` | string (optional) | The Metriport notification type — wire this from the enrollment webhook's `eventType` data point. Recorded on the import Provenance so admit, transfer and discharge can be told apart. |\n| `provenanceReason` | text (optional) | Free-text reason recorded on the import Provenance, describing why the data was imported. |\n\n| Data point | Type | Description |\n| --- | --- | --- |\n| `bundle` | json | The FHIR bundle fetched from the URL, exactly as Metriport sent it. |\n| `transactionBundle` | json | The same data rewritten as an executable FHIR transaction. Omitted when the payload is not a Patient Encounter Bundle. |\n\n### Building the transaction bundle\n\nMetriport delivers a bundle of `type: 'collection'`, which is **not executable**. Handing it straight to Medplum does nothing useful: no entry carries `request` metadata saying what to do with it, and every internal reference points at a Metriport UUID that means nothing in Medplum. The action therefore builds a second, executable bundle rather than passing the original through.\n\nThe transformation is a pure function with no Medplum access of its own — this extension holds Metriport credentials only. That rules out reading Medplum to reconcile against what is already there, so every lookup is expressed declaratively and resolved by the server when the transaction executes.\n\n**The Patient is never written.** Awell/Medplum is the source of truth for patient demographics, so the Patient entry is dropped entirely and every reference to it becomes a conditional reference:\n\n```\nPatient?identifier=https://awellhealth.com/patients|<awell patient id>\n```\n\nOmitting the entry guarantees structurally that a Metriport ADT feed can never overwrite the patient record.\n\n**Everything else is written idempotently.** Each Metriport resource is stamped with an identifier derived from its Metriport id and written with a conditional update:\n\n```\nidentifier: { system: 'https://metriport.com/fhir/encounter', value: '<metriport id>' }\nrequest: PUT Encounter?identifier=https://metriport.com/fhir/encounter|<metriport id>\n```\n\nA conditional update creates on zero matches and updates on one, so a redelivered notification updates in place instead of duplicating Conditions, Observations, Practitioners and Locations — and the admit and discharge notifications for one visit converge on a single Encounter. Existing identifiers are kept, so the Encounter keeps its HL7 `VN` visit number alongside ours.\n\n**References are rewritten to Metriport's own `fullUrl`s.** Metriport resolves its relationships correctly, but emits them in a form FHIR cannot match: entries carry `urn:uuid:` fullUrls while references to them are relative.\n\n```\nfullUrl: urn:uuid:3ca5e8d2-7c84-45ab-91e7-834f8becde12\nreference: Location/3ca5e8d2-7c84-45ab-91e7-834f8becde12\n```\n\nA transaction resolves an internal reference by matching it against `fullUrl` verbatim, and a relative reference does not match a `urn:uuid:` one — Medplum would read it as a reference to a *Medplum* Location with that id, which does not exist. Rewriting the reference to the entry's `fullUrl` closes the gap while keeping Metriport's identity. This is also why the result is a `transaction` and not a `batch`: `urn:uuid` resolution is a transaction feature.\n\n**`meta` is stripped from every resource.** Medplum's `meta.accounts` is inherited from the compartment of the Patient a resource references, but specifying `meta` at all on a create or update replaces those inherited accounts instead of adding to them. Metriport's Encounter arrives with a `meta`, so it is removed. `resource.id` is dropped too, for a separate reason: Medplum assigns identity, and the entry's `fullUrl` already carries the local identity the transaction needs.\n\n**Two entries are synthesised.** An `Organization` named *Metriport Realtime Monitoring*, created with `ifNoneExist` so an existing one is reused rather than overwritten; and a `Provenance` recording the import — what it created, when, which Metriport bundle it came from, and which ADT event triggered it (`patient.admit` → `A01`, `patient.transfer` → `A02`, `patient.discharge` → `A03`).\n\n`extensions/metriport/actions/webhookBundle/bundle/transform.test.ts` asserts the complete output for a real `patient.admit` bundle, if you want to see the whole before/after in one place.\n\n### Wiring it into a care flow\n\n1. **Enrollment** webhook fires and emits `bundleUrl` and `eventType`.\n2. **Get Webhook Bundle** — pass `bundleUrl` to `url` and `eventType` to `eventType`. Run this early; the URL expires after 10 minutes.\n3. Medplum **Find or create resource** — pass the `transactionBundle` data point to its `resourceJson` field. No changes to that action are needed; it detects a Bundle and executes it.\n\n**PREREQUISITE: for imported resources to be tagged with the Metriport organization, the Medplum Patient must already carry it in `meta.accounts` before the notification arrives.** Resources created without a `meta` inherit their accounts from the compartment of the Patient they reference, so tagging the Patient once causes every subsequent import to inherit it automatically. Note that this only covers resources *in* the patient compartment — `Location` and `Practitioner` are shared directory resources and are intentionally created untagged, since scoping a hospital or a physician to one patient's tenant would be wrong.\n\n**NOTE: the conditional Patient reference only resolves if your Medplum Patients carry an identifier under the `https://awellhealth.com/patients` system with the Awell patient id as its value. A conditional reference that matches no Patient fails the whole transaction.**\n\n### When the transaction bundle is omitted\n\n`Get Webhook Bundle` serves several Metriport webhook types and only ADT notifications carry encounter bundles. For any payload that is not a `collection` bundle, `transactionBundle` is simply omitted and `bundle` is emitted on its own — the action still succeeds.\n\nA `collection` bundle that is missing its Patient or Encounter entry is treated differently: that is an encounter bundle which does not describe an encounter, so the action **fails** rather than silently emitting a partial result.\n\n# Webhooks\n\n## Enrollment\n\nAn enrollment trigger that starts a care flow when Metriport sends a [real-time patient notification](https://docs.metriport.com/medical-api/handling-data/realtime-patient-notifications).\n\nMetriport POSTs every notification type to the same endpoint, so this webhook discriminates on the notification `type` and only enrolls on two events. The `eventType` data point carries the raw Metriport webhook type:\n\n- `patient.admit` (HL7 ADT^A01) → `eventType` = `patient.admit`. The payload carries a pre-signed URL to the [FHIR Encounter Bundle](https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle).\n- `medical.discharge-summary` → `eventType` = `medical.discharge-summary`. This event is currently undocumented by Metriport and is modelled on the published `medical.*` webhook family (a `patients` array).\n\nThe webhook validates the request, emits the data points (including the pre-signed bundle URL on `bundleUrl`), and replies immediately — it does **not** download the bundle. Fetch the bundle later in the care flow with the **Get Webhook Bundle** action, using the `bundleUrl` data point. Because the URL expires after 10 minutes, run that action early.\n\nUse the `eventType` data point in your care flow to branch on admit vs discharge. Every other notification type (`patient.discharge`, `patient.transfer`, ...) is acknowledged with a `200` but does not enroll a patient. Metriport [verification `ping` messages](https://docs.metriport.com/medical-api/getting-started/webhooks#the-ping-message) are answered with a `200` that echoes the ping value back as `pong: <value>`.\n\n### Data points\n\n| Data point | Type | Description |\n| --- | --- | --- |\n| `eventType` | string | The Metriport webhook type: `patient.admit` or `medical.discharge-summary` |\n| `metriportPatientId` | string | The Metriport patient ID (also used as the patient identifier for enrollment) |\n| `externalId` | string | Your external patient ID, if provided to Metriport |\n| `admitTimestamp` | date | When the patient was admitted (admit events only) |\n| `whenSourceSent` | date | When the source sent the notification, if available (admit events) |\n| `messageId` | string | The Metriport message ID for the notification |\n| `bundleUrl` | string | Pre-signed URL to the FHIR bundle; fetch it with the **Get Webhook Bundle** action (valid for 10 minutes) |\n\n### Verifying incoming requests\n\nOptionally set the **Webhook Key** setting to the webhook key from the Metriport dashboard (Settings/Developers tab). Metriport [authenticates each webhook](https://docs.metriport.com/medical-api/getting-started/webhooks#authentication) with an HMAC-SHA256 signature of the raw request body, keyed with your webhook key and sent in the `x-metriport-signature` header. When the setting is populated, the webhook recomputes the HMAC over the raw body and rejects any request whose signature is missing or does not match (`401`). When left empty, requests are not verified.\n\n## More Info\n\nFor more information on how to integrate with Metriport please visit our [Medical API docs](https://docs.metriport.com/medical-api/getting-started/quickstart)\n",
164
164
  "changelog": "# Metriport changelog\n\n## July 2026\n\n- Add `enrollment` webhook: an enrollment trigger for Metriport real-time patient notifications. The `eventType` data point carries the Metriport webhook type (`patient.admit` or `medical.discharge-summary`) so care flows can distinguish on it. The webhook validates and replies immediately, emitting the pre-signed FHIR bundle URL on the `bundleUrl` data point rather than downloading the bundle inline.\n- Add `Get Webhook Bundle` action: fetches the FHIR bundle from a Metriport webhook payload URL (the webhook's `bundleUrl`), for use later in the care flow.\n- Add optional `Webhook Key` setting used to verify incoming webhook requests via Metriport's HMAC-SHA256 signature (`x-metriport-signature` header), computed over the raw request body."
165
165
  },
166
166
  "nexuzhealth": {
@@ -45,6 +45,7 @@ exports.createResource = {
45
45
  if (resourceData.resourceType === 'Bundle') {
46
46
  helpers.log({ resourceData }, '[createResource] Executing Medplum bundle');
47
47
  const result = await medplumSdk.executeBatch(resourceData);
48
+ helpers.log({ batchResult: result }, '[Medplum extension] Medplum batch result');
48
49
  const resourceIds = (_c = (_b = result.entry) === null || _b === void 0 ? void 0 : _b.map((entry) => {
49
50
  var _a, _b;
50
51
  if (((_a = entry.response) === null || _a === void 0 ? void 0 : _a.location) !== undefined &&
@@ -1 +1 @@
1
- {"version":3,"file":"createResource.js","sourceRoot":"","sources":["../../../../../extensions/medplum/actions/createResource/createResource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createResource.js","sourceRoot":"","sources":["../../../../../extensions/medplum/actions/createResource/createResource.ts"],"names":[],"mappings":"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"}
@@ -559,6 +559,26 @@ export declare const actions: {
559
559
  type: import("@awell-health/extensions-core").FieldType.STRING;
560
560
  required: true;
561
561
  };
562
+ eventType: {
563
+ id: string;
564
+ label: string;
565
+ description: string;
566
+ type: import("@awell-health/extensions-core").FieldType.STRING;
567
+ required: false;
568
+ options: {
569
+ dropdownOptions: {
570
+ label: string;
571
+ value: import("../webhooks/types").MetriportWebhookType;
572
+ }[];
573
+ };
574
+ };
575
+ provenanceReason: {
576
+ id: string;
577
+ label: string;
578
+ description: string;
579
+ type: import("@awell-health/extensions-core").FieldType.TEXT;
580
+ required: false;
581
+ };
562
582
  }, {
563
583
  apiKey: {
564
584
  key: string;
@@ -581,7 +601,7 @@ export declare const actions: {
581
601
  description: string;
582
602
  required: false;
583
603
  };
584
- }, "bundle">;
604
+ }, "bundle" | "transactionBundle">;
585
605
  removePatientFromCohort: import("@awell-health/extensions-core").Action<{
586
606
  cohortId: {
587
607
  id: string;
@@ -0,0 +1,22 @@
1
+ import { type Bundle } from '@medplum/fhirtypes';
2
+ /**
3
+ * A real `patient.admit` Patient Encounter Bundle from Metriport's demo data.
4
+ *
5
+ * Deliberately kept verbatim, including the quirks the transformation has to
6
+ * cope with:
7
+ * - `type: 'collection'`, so no entry carries `request` metadata
8
+ * - internal references use Metriport's own UUIDs (`Patient/78a4d9e5-…`)
9
+ * rather than the `urn:uuid:` form the `fullUrl`s use
10
+ * - the Encounter arrives with a `meta` (`api.metriport.com/created-at`
11
+ * extension and a `versionId`) that must be stripped
12
+ * - references point in both directions: Encounter → Condition via
13
+ * `diagnosis`, and Condition → Encounter via `encounter`
14
+ *
15
+ * https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle
16
+ */
17
+ export declare const patientAdmitBundle: Bundle;
18
+ export declare const METRIPORT_PATIENT_ID = "78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d";
19
+ export declare const METRIPORT_ENCOUNTER_ID = "c60544e1-2e37-45fb-8160-3d583902cfde";
20
+ export declare const METRIPORT_LOCATION_ID = "3ca5e8d2-7c84-45ab-91e7-834f8becde12";
21
+ export declare const METRIPORT_PRACTITIONER_ID = "49e3c8f1-d67a-47b8-b9a2-cf23e8d0e941";
22
+ export declare const METRIPORT_CONDITION_ID = "8724f6e9-c531-48ba-9d34-7e2a81c05fb3";
@@ -0,0 +1,262 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.METRIPORT_CONDITION_ID = exports.METRIPORT_PRACTITIONER_ID = exports.METRIPORT_LOCATION_ID = exports.METRIPORT_ENCOUNTER_ID = exports.METRIPORT_PATIENT_ID = exports.patientAdmitBundle = void 0;
4
+ /**
5
+ * A real `patient.admit` Patient Encounter Bundle from Metriport's demo data.
6
+ *
7
+ * Deliberately kept verbatim, including the quirks the transformation has to
8
+ * cope with:
9
+ * - `type: 'collection'`, so no entry carries `request` metadata
10
+ * - internal references use Metriport's own UUIDs (`Patient/78a4d9e5-…`)
11
+ * rather than the `urn:uuid:` form the `fullUrl`s use
12
+ * - the Encounter arrives with a `meta` (`api.metriport.com/created-at`
13
+ * extension and a `versionId`) that must be stripped
14
+ * - references point in both directions: Encounter → Condition via
15
+ * `diagnosis`, and Condition → Encounter via `encounter`
16
+ *
17
+ * https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle
18
+ */
19
+ exports.patientAdmitBundle = {
20
+ resourceType: 'Bundle',
21
+ id: 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
22
+ type: 'collection',
23
+ timestamp: '2025-03-15T16:45:10.000+00:00',
24
+ entry: [
25
+ {
26
+ fullUrl: 'urn:uuid:78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d',
27
+ resource: {
28
+ resourceType: 'Patient',
29
+ id: '78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d',
30
+ name: [
31
+ {
32
+ use: 'official',
33
+ family: 'Johnson',
34
+ given: ['Sarah'],
35
+ },
36
+ ],
37
+ gender: 'female',
38
+ birthDate: '1975-06-15',
39
+ },
40
+ },
41
+ {
42
+ fullUrl: 'urn:uuid:c60544e1-2e37-45fb-8160-3d583902cfde',
43
+ resource: {
44
+ resourceType: 'Encounter',
45
+ id: 'c60544e1-2e37-45fb-8160-3d583902cfde',
46
+ meta: {
47
+ extension: [
48
+ {
49
+ url: 'https://api.metriport.com/created-at',
50
+ valueInstant: '2025-03-15T16:45:10.000+00:00',
51
+ },
52
+ ],
53
+ versionId: '0.1.0',
54
+ },
55
+ status: 'in-progress',
56
+ period: { start: '2024-07-22T19:50:00.000Z' },
57
+ class: {
58
+ system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode',
59
+ code: 'AMB',
60
+ display: 'Ambulatory',
61
+ },
62
+ serviceType: {
63
+ coding: [
64
+ {
65
+ code: '394592004',
66
+ display: 'Cardiology',
67
+ },
68
+ ],
69
+ text: 'Cardiology',
70
+ },
71
+ subject: {
72
+ reference: 'Patient/78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d',
73
+ type: 'Patient',
74
+ display: 'Sarah Johnson',
75
+ },
76
+ location: [
77
+ {
78
+ location: {
79
+ reference: 'Location/3ca5e8d2-7c84-45ab-91e7-834f8becde12',
80
+ type: 'Location',
81
+ display: 'Memorial Hospital',
82
+ },
83
+ },
84
+ ],
85
+ participant: [
86
+ {
87
+ type: [
88
+ {
89
+ coding: [
90
+ {
91
+ system: 'http://terminology.hl7.org/CodeSystem/v3-ParticipationType',
92
+ code: 'ATND',
93
+ display: 'attender',
94
+ },
95
+ ],
96
+ },
97
+ ],
98
+ individual: {
99
+ reference: 'Practitioner/49e3c8f1-d67a-47b8-b9a2-cf23e8d0e941',
100
+ type: 'Practitioner',
101
+ display: 'Dr. Maria Rodriguez',
102
+ },
103
+ period: {
104
+ start: '2024-03-15T14:20:00.000Z',
105
+ },
106
+ },
107
+ ],
108
+ reasonCode: [
109
+ {
110
+ text: 'Chest pain',
111
+ },
112
+ ],
113
+ diagnosis: [
114
+ {
115
+ condition: {
116
+ reference: 'Condition/8724f6e9-c531-48ba-9d34-7e2a81c05fb3',
117
+ type: 'Condition',
118
+ display: 'Stable Angina',
119
+ },
120
+ use: {
121
+ coding: [
122
+ {
123
+ system: 'https://terminology.hl7.org/5.2.0/CodeSystem-v2-0052.html',
124
+ code: 'AD',
125
+ display: 'Final diagnosis',
126
+ },
127
+ ],
128
+ },
129
+ rank: 1,
130
+ },
131
+ ],
132
+ identifier: [
133
+ {
134
+ type: {
135
+ coding: [
136
+ {
137
+ system: 'http://terminology.hl7.org/CodeSystem/v2-0203',
138
+ code: 'VN',
139
+ display: 'visit number',
140
+ },
141
+ ],
142
+ text: 'visit number',
143
+ },
144
+ value: '987654321',
145
+ },
146
+ ],
147
+ },
148
+ },
149
+ {
150
+ fullUrl: 'urn:uuid:3ca5e8d2-7c84-45ab-91e7-834f8becde12',
151
+ resource: {
152
+ resourceType: 'Location',
153
+ id: '3ca5e8d2-7c84-45ab-91e7-834f8becde12',
154
+ status: 'active',
155
+ name: 'Memorial Hospital',
156
+ mode: 'instance',
157
+ type: [
158
+ {
159
+ coding: [
160
+ {
161
+ system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode',
162
+ code: 'HOSP',
163
+ display: 'Hospital',
164
+ },
165
+ ],
166
+ },
167
+ ],
168
+ },
169
+ },
170
+ {
171
+ fullUrl: 'urn:uuid:49e3c8f1-d67a-47b8-b9a2-cf23e8d0e941',
172
+ resource: {
173
+ resourceType: 'Practitioner',
174
+ id: '49e3c8f1-d67a-47b8-b9a2-cf23e8d0e941',
175
+ name: [
176
+ {
177
+ use: 'official',
178
+ family: 'Rodriguez',
179
+ given: ['Maria'],
180
+ prefix: ['Dr.'],
181
+ },
182
+ ],
183
+ qualification: [
184
+ {
185
+ code: {
186
+ coding: [
187
+ {
188
+ system: 'http://terminology.hl7.org/CodeSystem/v2-0360',
189
+ code: 'MD',
190
+ display: 'Doctor of Medicine',
191
+ },
192
+ ],
193
+ },
194
+ },
195
+ ],
196
+ },
197
+ },
198
+ {
199
+ fullUrl: 'urn:uuid:8724f6e9-c531-48ba-9d34-7e2a81c05fb3',
200
+ resource: {
201
+ resourceType: 'Condition',
202
+ id: '8724f6e9-c531-48ba-9d34-7e2a81c05fb3',
203
+ clinicalStatus: {
204
+ coding: [
205
+ {
206
+ system: 'http://terminology.hl7.org/CodeSystem/condition-clinical',
207
+ code: 'active',
208
+ display: 'Active',
209
+ },
210
+ ],
211
+ },
212
+ verificationStatus: {
213
+ coding: [
214
+ {
215
+ system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
216
+ code: 'confirmed',
217
+ display: 'Confirmed',
218
+ },
219
+ ],
220
+ },
221
+ category: [
222
+ {
223
+ coding: [
224
+ {
225
+ system: 'http://terminology.hl7.org/CodeSystem/condition-category',
226
+ code: 'encounter-diagnosis',
227
+ display: 'Encounter Diagnosis',
228
+ },
229
+ ],
230
+ },
231
+ ],
232
+ code: {
233
+ coding: [
234
+ {
235
+ system: 'http://snomed.info/sct',
236
+ code: '194828000',
237
+ display: 'Stable angina',
238
+ },
239
+ ],
240
+ text: 'Stable Angina',
241
+ },
242
+ subject: {
243
+ reference: 'Patient/78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d',
244
+ type: 'Patient',
245
+ display: 'Sarah Johnson',
246
+ },
247
+ encounter: {
248
+ reference: 'Encounter/c60544e1-2e37-45fb-8160-3d583902cfde',
249
+ type: 'Encounter',
250
+ },
251
+ onsetDateTime: '2024-03-15T14:20:00.000Z',
252
+ recordedDate: '2024-03-15T16:45:00.000Z',
253
+ },
254
+ },
255
+ ],
256
+ };
257
+ exports.METRIPORT_PATIENT_ID = '78a4d9e5-f2b3-42c8-9a84-52f3e21c2b9d';
258
+ exports.METRIPORT_ENCOUNTER_ID = 'c60544e1-2e37-45fb-8160-3d583902cfde';
259
+ exports.METRIPORT_LOCATION_ID = '3ca5e8d2-7c84-45ab-91e7-834f8becde12';
260
+ exports.METRIPORT_PRACTITIONER_ID = '49e3c8f1-d67a-47b8-b9a2-cf23e8d0e941';
261
+ exports.METRIPORT_CONDITION_ID = '8724f6e9-c531-48ba-9d34-7e2a81c05fb3';
262
+ //# sourceMappingURL=patientAdmitBundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patientAdmitBundle.js","sourceRoot":"","sources":["../../../../../../../extensions/metriport/actions/webhookBundle/bundle/__testdata__/patientAdmitBundle.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACU,QAAA,kBAAkB,GAAW;IACxC,YAAY,EAAE,QAAQ;IACtB,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,YAAY;IAClB,SAAS,EAAE,+BAA+B;IAC1C,KAAK,EAAE;QACL;YACE,OAAO,EAAE,+CAA+C;YACxD,QAAQ,EAAE;gBACR,YAAY,EAAE,SAAS;gBACvB,EAAE,EAAE,sCAAsC;gBAC1C,IAAI,EAAE;oBACJ;wBACE,GAAG,EAAE,UAAU;wBACf,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE,CAAC,OAAO,CAAC;qBACjB;iBACF;gBACD,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,YAAY;aACxB;SACF;QACD;YACE,OAAO,EAAE,+CAA+C;YACxD,QAAQ,EAAE;gBACR,YAAY,EAAE,WAAW;gBACzB,EAAE,EAAE,sCAAsC;gBAC1C,IAAI,EAAE;oBACJ,SAAS,EAAE;wBACT;4BACE,GAAG,EAAE,sCAAsC;4BAC3C,YAAY,EAAE,+BAA+B;yBAC9C;qBACF;oBACD,SAAS,EAAE,OAAO;iBACnB;gBACD,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,EAAE,KAAK,EAAE,0BAA0B,EAAE;gBAC7C,KAAK,EAAE;oBACL,MAAM,EAAE,kDAAkD;oBAC1D,IAAI,EAAE,KAAK;oBACX,OAAO,EAAE,YAAY;iBACtB;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE;wBACN;4BACE,IAAI,EAAE,WAAW;4BACjB,OAAO,EAAE,YAAY;yBACtB;qBACF;oBACD,IAAI,EAAE,YAAY;iBACnB;gBACD,OAAO,EAAE;oBACP,SAAS,EAAE,8CAA8C;oBACzD,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,eAAe;iBACzB;gBACD,QAAQ,EAAE;oBACR;wBACE,QAAQ,EAAE;4BACR,SAAS,EAAE,+CAA+C;4BAC1D,IAAI,EAAE,UAAU;4BAChB,OAAO,EAAE,mBAAmB;yBAC7B;qBACF;iBACF;gBACD,WAAW,EAAE;oBACX;wBACE,IAAI,EAAE;4BACJ;gCACE,MAAM,EAAE;oCACN;wCACE,MAAM,EACJ,4DAA4D;wCAC9D,IAAI,EAAE,MAAM;wCACZ,OAAO,EAAE,UAAU;qCACpB;iCACF;6BACF;yBACF;wBACD,UAAU,EAAE;4BACV,SAAS,EAAE,mDAAmD;4BAC9D,IAAI,EAAE,cAAc;4BACpB,OAAO,EAAE,qBAAqB;yBAC/B;wBACD,MAAM,EAAE;4BACN,KAAK,EAAE,0BAA0B;yBAClC;qBACF;iBACF;gBACD,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE,YAAY;qBACnB;iBACF;gBACD,SAAS,EAAE;oBACT;wBACE,SAAS,EAAE;4BACT,SAAS,EAAE,gDAAgD;4BAC3D,IAAI,EAAE,WAAW;4BACjB,OAAO,EAAE,eAAe;yBACzB;wBACD,GAAG,EAAE;4BACH,MAAM,EAAE;gCACN;oCACE,MAAM,EACJ,2DAA2D;oCAC7D,IAAI,EAAE,IAAI;oCACV,OAAO,EAAE,iBAAiB;iCAC3B;6BACF;yBACF;wBACD,IAAI,EAAE,CAAC;qBACR;iBACF;gBACD,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE;4BACJ,MAAM,EAAE;gCACN;oCACE,MAAM,EAAE,+CAA+C;oCACvD,IAAI,EAAE,IAAI;oCACV,OAAO,EAAE,cAAc;iCACxB;6BACF;4BACD,IAAI,EAAE,cAAc;yBACrB;wBACD,KAAK,EAAE,WAAW;qBACnB;iBACF;aACF;SACF;QACD;YACE,OAAO,EAAE,+CAA+C;YACxD,QAAQ,EAAE;gBACR,YAAY,EAAE,UAAU;gBACxB,EAAE,EAAE,sCAAsC;gBAC1C,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE;oBACJ;wBACE,MAAM,EAAE;4BACN;gCACE,MAAM,EAAE,mDAAmD;gCAC3D,IAAI,EAAE,MAAM;gCACZ,OAAO,EAAE,UAAU;6BACpB;yBACF;qBACF;iBACF;aACF;SACF;QACD;YACE,OAAO,EAAE,+CAA+C;YACxD,QAAQ,EAAE;gBACR,YAAY,EAAE,cAAc;gBAC5B,EAAE,EAAE,sCAAsC;gBAC1C,IAAI,EAAE;oBACJ;wBACE,GAAG,EAAE,UAAU;wBACf,MAAM,EAAE,WAAW;wBACnB,KAAK,EAAE,CAAC,OAAO,CAAC;wBAChB,MAAM,EAAE,CAAC,KAAK,CAAC;qBAChB;iBACF;gBACD,aAAa,EAAE;oBACb;wBACE,IAAI,EAAE;4BACJ,MAAM,EAAE;gCACN;oCACE,MAAM,EAAE,+CAA+C;oCACvD,IAAI,EAAE,IAAI;oCACV,OAAO,EAAE,oBAAoB;iCAC9B;6BACF;yBACF;qBACF;iBACF;aACF;SACF;QACD;YACE,OAAO,EAAE,+CAA+C;YACxD,QAAQ,EAAE;gBACR,YAAY,EAAE,WAAW;gBACzB,EAAE,EAAE,sCAAsC;gBAC1C,cAAc,EAAE;oBACd,MAAM,EAAE;wBACN;4BACE,MAAM,EACJ,0DAA0D;4BAC5D,IAAI,EAAE,QAAQ;4BACd,OAAO,EAAE,QAAQ;yBAClB;qBACF;iBACF;gBACD,kBAAkB,EAAE;oBAClB,MAAM,EAAE;wBACN;4BACE,MAAM,EACJ,4DAA4D;4BAC9D,IAAI,EAAE,WAAW;4BACjB,OAAO,EAAE,WAAW;yBACrB;qBACF;iBACF;gBACD,QAAQ,EAAE;oBACR;wBACE,MAAM,EAAE;4BACN;gCACE,MAAM,EACJ,0DAA0D;gCAC5D,IAAI,EAAE,qBAAqB;gCAC3B,OAAO,EAAE,qBAAqB;6BAC/B;yBACF;qBACF;iBACF;gBACD,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN;4BACE,MAAM,EAAE,wBAAwB;4BAChC,IAAI,EAAE,WAAW;4BACjB,OAAO,EAAE,eAAe;yBACzB;qBACF;oBACD,IAAI,EAAE,eAAe;iBACtB;gBACD,OAAO,EAAE;oBACP,SAAS,EAAE,8CAA8C;oBACzD,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,eAAe;iBACzB;gBACD,SAAS,EAAE;oBACT,SAAS,EAAE,gDAAgD;oBAC3D,IAAI,EAAE,WAAW;iBAClB;gBACD,aAAa,EAAE,0BAA0B;gBACzC,YAAY,EAAE,0BAA0B;aACzC;SACF;KACF;CACF,CAAA;AAEY,QAAA,oBAAoB,GAAG,sCAAsC,CAAA;AAC7D,QAAA,sBAAsB,GAAG,sCAAsC,CAAA;AAC/D,QAAA,qBAAqB,GAAG,sCAAsC,CAAA;AAC9D,QAAA,yBAAyB,GAAG,sCAAsC,CAAA;AAClE,QAAA,sBAAsB,GAAG,sCAAsC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { type BundleEntry, type Organization } from '@medplum/fhirtypes';
2
+ /**
3
+ * The Organization used as the account for imported resources.
4
+ *
5
+ * POST with `ifNoneExist` rather than a conditional update: if the organization
6
+ * already exists the create is skipped and the `fullUrl` resolves to the
7
+ * existing resource, so we never overwrite contents we don't own. `Provenance`
8
+ * references this entry as the assembling agent.
9
+ */
10
+ export declare const buildAccountOrganizationEntry: () => BundleEntry<Organization>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAccountOrganizationEntry = void 0;
4
+ const constants_1 = require("./constants");
5
+ /**
6
+ * The Organization used as the account for imported resources.
7
+ *
8
+ * POST with `ifNoneExist` rather than a conditional update: if the organization
9
+ * already exists the create is skipped and the `fullUrl` resolves to the
10
+ * existing resource, so we never overwrite contents we don't own. `Provenance`
11
+ * references this entry as the assembling agent.
12
+ */
13
+ const buildAccountOrganizationEntry = () => ({
14
+ fullUrl: constants_1.ACCOUNT_ORGANIZATION_FULL_URL,
15
+ resource: {
16
+ resourceType: 'Organization',
17
+ name: constants_1.METRIPORT_ACCOUNT_ORGANIZATION_NAME,
18
+ },
19
+ request: {
20
+ method: 'POST',
21
+ url: 'Organization',
22
+ ifNoneExist: `name:exact=${constants_1.METRIPORT_ACCOUNT_ORGANIZATION_NAME}`,
23
+ },
24
+ });
25
+ exports.buildAccountOrganizationEntry = buildAccountOrganizationEntry;
26
+ //# sourceMappingURL=account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/account.ts"],"names":[],"mappings":";;;AACA,2CAGoB;AAEpB;;;;;;;GAOG;AACI,MAAM,6BAA6B,GAAG,GAA8B,EAAE,CAAC,CAAC;IAC7E,OAAO,EAAE,yCAA6B;IACtC,QAAQ,EAAE;QACR,YAAY,EAAE,cAAc;QAC5B,IAAI,EAAE,+CAAmC;KAC1C;IACD,OAAO,EAAE;QACP,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,cAAc;QACnB,WAAW,EAAE,cAAc,+CAAmC,EAAE;KACjE;CACF,CAAC,CAAA;AAXW,QAAA,6BAA6B,iCAWxC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Identifier system for the Awell patient id, used to resolve the Medplum
3
+ * Patient by conditional reference rather than by lookup.
4
+ */
5
+ export declare const AWELL_PATIENT_IDENTIFIER_SYSTEM = "https://awellhealth.com/patients";
6
+ /**
7
+ * Prefix for the identifier we stamp on every Metriport-sourced resource,
8
+ * completed with the lowercased resource type — e.g.
9
+ * `https://metriport.com/fhir/encounter`. Lets each resource be written with a
10
+ * conditional update, which makes a redelivered notification idempotent.
11
+ */
12
+ export declare const METRIPORT_IDENTIFIER_SYSTEM_PREFIX = "https://metriport.com/fhir/";
13
+ /** Identifier system for the source bundle, recorded on `Provenance.entity`. */
14
+ export declare const METRIPORT_BUNDLE_IDENTIFIER_SYSTEM = "https://metriport.com/fhir/bundle";
15
+ /** Name of the Organization used as the account for imported resources. */
16
+ export declare const METRIPORT_ACCOUNT_ORGANIZATION_NAME = "Metriport Realtime Monitoring";
17
+ /**
18
+ * Fixed `fullUrl` for the account Organization entry. The urn is scoped to a
19
+ * single bundle, so a constant keeps bundle construction pure — no UUID
20
+ * generation — and keeps the tests literal.
21
+ */
22
+ export declare const ACCOUNT_ORGANIZATION_FULL_URL = "urn:uuid:00000000-0000-4000-8000-000000000001";
23
+ /** Fixed `fullUrl` for the Provenance entry, for the same reason. */
24
+ export declare const PROVENANCE_FULL_URL = "urn:uuid:00000000-0000-4000-8000-000000000002";
25
+ /**
26
+ * Resource types with no `identifier` element in FHIR R4, which therefore
27
+ * cannot be written with a conditional update and fall back to POST.
28
+ */
29
+ export declare const RESOURCE_TYPES_WITHOUT_IDENTIFIER: string[];
30
+ export declare const metriportIdentifierSystem: (resourceType: string) => string;
31
+ export declare const awellPatientReference: (awellPatientId: string) => string;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.awellPatientReference = exports.metriportIdentifierSystem = exports.RESOURCE_TYPES_WITHOUT_IDENTIFIER = exports.PROVENANCE_FULL_URL = exports.ACCOUNT_ORGANIZATION_FULL_URL = exports.METRIPORT_ACCOUNT_ORGANIZATION_NAME = exports.METRIPORT_BUNDLE_IDENTIFIER_SYSTEM = exports.METRIPORT_IDENTIFIER_SYSTEM_PREFIX = exports.AWELL_PATIENT_IDENTIFIER_SYSTEM = void 0;
4
+ /**
5
+ * Identifier system for the Awell patient id, used to resolve the Medplum
6
+ * Patient by conditional reference rather than by lookup.
7
+ */
8
+ exports.AWELL_PATIENT_IDENTIFIER_SYSTEM = 'https://awellhealth.com/patients';
9
+ /**
10
+ * Prefix for the identifier we stamp on every Metriport-sourced resource,
11
+ * completed with the lowercased resource type — e.g.
12
+ * `https://metriport.com/fhir/encounter`. Lets each resource be written with a
13
+ * conditional update, which makes a redelivered notification idempotent.
14
+ */
15
+ exports.METRIPORT_IDENTIFIER_SYSTEM_PREFIX = 'https://metriport.com/fhir/';
16
+ /** Identifier system for the source bundle, recorded on `Provenance.entity`. */
17
+ exports.METRIPORT_BUNDLE_IDENTIFIER_SYSTEM = 'https://metriport.com/fhir/bundle';
18
+ /** Name of the Organization used as the account for imported resources. */
19
+ exports.METRIPORT_ACCOUNT_ORGANIZATION_NAME = 'Metriport Realtime Monitoring';
20
+ /**
21
+ * Fixed `fullUrl` for the account Organization entry. The urn is scoped to a
22
+ * single bundle, so a constant keeps bundle construction pure — no UUID
23
+ * generation — and keeps the tests literal.
24
+ */
25
+ exports.ACCOUNT_ORGANIZATION_FULL_URL = 'urn:uuid:00000000-0000-4000-8000-000000000001';
26
+ /** Fixed `fullUrl` for the Provenance entry, for the same reason. */
27
+ exports.PROVENANCE_FULL_URL = 'urn:uuid:00000000-0000-4000-8000-000000000002';
28
+ /**
29
+ * Resource types with no `identifier` element in FHIR R4, which therefore
30
+ * cannot be written with a conditional update and fall back to POST.
31
+ */
32
+ exports.RESOURCE_TYPES_WITHOUT_IDENTIFIER = [
33
+ 'Provenance',
34
+ 'AuditEvent',
35
+ 'Binary',
36
+ ];
37
+ const metriportIdentifierSystem = (resourceType) => `${exports.METRIPORT_IDENTIFIER_SYSTEM_PREFIX}${resourceType.toLowerCase()}`;
38
+ exports.metriportIdentifierSystem = metriportIdentifierSystem;
39
+ const awellPatientReference = (awellPatientId) => `Patient?identifier=${exports.AWELL_PATIENT_IDENTIFIER_SYSTEM}|${awellPatientId}`;
40
+ exports.awellPatientReference = awellPatientReference;
41
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/constants.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,+BAA+B,GAC1C,kCAAkC,CAAA;AAEpC;;;;;GAKG;AACU,QAAA,kCAAkC,GAAG,6BAA6B,CAAA;AAE/E,gFAAgF;AACnE,QAAA,kCAAkC,GAC7C,mCAAmC,CAAA;AAErC,2EAA2E;AAC9D,QAAA,mCAAmC,GAC9C,+BAA+B,CAAA;AAEjC;;;;GAIG;AACU,QAAA,6BAA6B,GACxC,+CAA+C,CAAA;AAEjD,qEAAqE;AACxD,QAAA,mBAAmB,GAC9B,+CAA+C,CAAA;AAEjD;;;GAGG;AACU,QAAA,iCAAiC,GAAG;IAC/C,YAAY;IACZ,YAAY;IACZ,QAAQ;CACT,CAAA;AAEM,MAAM,yBAAyB,GAAG,CAAC,YAAoB,EAAU,EAAE,CACxE,GAAG,0CAAkC,GAAG,YAAY,CAAC,WAAW,EAAE,EAAE,CAAA;AADzD,QAAA,yBAAyB,6BACgC;AAE/D,MAAM,qBAAqB,GAAG,CAAC,cAAsB,EAAU,EAAE,CACtE,sBAAsB,uCAA+B,IAAI,cAAc,EAAE,CAAA;AAD9D,QAAA,qBAAqB,yBACyC"}
@@ -0,0 +1,27 @@
1
+ import { type BundleEntry, type Resource } from '@medplum/fhirtypes';
2
+ /**
3
+ * Turns a Metriport resource into an executable bundle entry.
4
+ *
5
+ * The resource is stamped with an identifier derived from its Metriport id and
6
+ * written with a conditional update, which makes the import idempotent: a
7
+ * redelivered notification updates in place instead of creating duplicates, and
8
+ * admit + discharge notifications converge on the same Encounter. Full
9
+ * replacement is the right semantic here, since Metriport is the source of
10
+ * truth for these resources.
11
+ *
12
+ * Two fields are removed:
13
+ * - `id`, because the server assigns identity — `fullUrl` carries the local
14
+ * identity the transaction needs to resolve references
15
+ * - `meta`, because specifying it at all causes Medplum to overwrite the
16
+ * `meta.accounts` a resource would otherwise inherit from the patient's
17
+ * compartment. Metriport's Encounter arrives with one.
18
+ *
19
+ * `fullUrl` is Metriport's own, passed through untouched, so the local identity
20
+ * in the transaction is the one Metriport already assigned rather than
21
+ * something we invent. The `urn:uuid:` fallback only covers a bundle that omits
22
+ * it — which Metriport's encounter bundles do not.
23
+ *
24
+ * Resource types with no `identifier` element in FHIR R4 cannot be addressed by
25
+ * a conditional update, so they fall back to POST.
26
+ */
27
+ export declare const buildResourceEntry: (resource: Resource, fullUrl?: string) => BundleEntry;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildResourceEntry = void 0;
4
+ const constants_1 = require("./constants");
5
+ /**
6
+ * Turns a Metriport resource into an executable bundle entry.
7
+ *
8
+ * The resource is stamped with an identifier derived from its Metriport id and
9
+ * written with a conditional update, which makes the import idempotent: a
10
+ * redelivered notification updates in place instead of creating duplicates, and
11
+ * admit + discharge notifications converge on the same Encounter. Full
12
+ * replacement is the right semantic here, since Metriport is the source of
13
+ * truth for these resources.
14
+ *
15
+ * Two fields are removed:
16
+ * - `id`, because the server assigns identity — `fullUrl` carries the local
17
+ * identity the transaction needs to resolve references
18
+ * - `meta`, because specifying it at all causes Medplum to overwrite the
19
+ * `meta.accounts` a resource would otherwise inherit from the patient's
20
+ * compartment. Metriport's Encounter arrives with one.
21
+ *
22
+ * `fullUrl` is Metriport's own, passed through untouched, so the local identity
23
+ * in the transaction is the one Metriport already assigned rather than
24
+ * something we invent. The `urn:uuid:` fallback only covers a bundle that omits
25
+ * it — which Metriport's encounter bundles do not.
26
+ *
27
+ * Resource types with no `identifier` element in FHIR R4 cannot be addressed by
28
+ * a conditional update, so they fall back to POST.
29
+ */
30
+ const buildResourceEntry = (resource, fullUrl) => {
31
+ var _a;
32
+ const { id, resourceType } = resource;
33
+ if (id === undefined) {
34
+ throw new Error(`[Metriport bundle] ${resourceType} entry is missing an id, so it cannot be reconciled`);
35
+ }
36
+ // Shallow clone, then drop the two fields Medplum must assign itself. Nested
37
+ // objects are shared with the input, but nothing nested is modified — the
38
+ // identifier list below is replaced rather than appended to in place.
39
+ const stripped = { ...resource };
40
+ delete stripped.id;
41
+ delete stripped.meta;
42
+ const localIdentity = fullUrl !== null && fullUrl !== void 0 ? fullUrl : `urn:uuid:${id}`;
43
+ if (constants_1.RESOURCE_TYPES_WITHOUT_IDENTIFIER.includes(resourceType)) {
44
+ return {
45
+ fullUrl: localIdentity,
46
+ resource: stripped,
47
+ request: { method: 'POST', url: resourceType },
48
+ };
49
+ }
50
+ const system = (0, constants_1.metriportIdentifierSystem)(resourceType);
51
+ const identifiable = stripped;
52
+ const existing = (_a = identifiable.identifier) !== null && _a !== void 0 ? _a : [];
53
+ const alreadyStamped = existing.some((identifier) => identifier.system === system && identifier.value === id);
54
+ identifiable.identifier = alreadyStamped
55
+ ? existing
56
+ : [...existing, { system, value: id }];
57
+ return {
58
+ fullUrl: localIdentity,
59
+ resource: stripped,
60
+ request: {
61
+ method: 'PUT',
62
+ url: `${resourceType}?identifier=${system}|${id}`,
63
+ },
64
+ };
65
+ };
66
+ exports.buildResourceEntry = buildResourceEntry;
67
+ //# sourceMappingURL=entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entries.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/entries.ts"],"names":[],"mappings":";;;AAKA,2CAGoB;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACI,MAAM,kBAAkB,GAAG,CAChC,QAAkB,EAClB,OAAgB,EACH,EAAE;;IACf,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAA;IAErC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,sBAAsB,YAAY,qDAAqD,CACxF,CAAA;IACH,CAAC;IAED,6EAA6E;IAC7E,0EAA0E;IAC1E,sEAAsE;IACtE,MAAM,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAA;IAChC,OAAO,QAAQ,CAAC,EAAE,CAAA;IAClB,OAAO,QAAQ,CAAC,IAAI,CAAA;IAEpB,MAAM,aAAa,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,YAAY,EAAE,EAAE,CAAA;IAEjD,IAAI,6CAAiC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE;SAC/C,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,qCAAyB,EAAC,YAAY,CAAC,CAAA;IACtD,MAAM,YAAY,GAAG,QAAyC,CAAA;IAC9D,MAAM,QAAQ,GAAG,MAAA,YAAY,CAAC,UAAU,mCAAI,EAAE,CAAA;IAC9C,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAClC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,MAAM,IAAI,UAAU,CAAC,KAAK,KAAK,EAAE,CACxE,CAAA;IAED,YAAY,CAAC,UAAU,GAAG,cAAc;QACtC,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;IAExC,OAAO;QACL,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE;YACP,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,GAAG,YAAY,eAAe,MAAM,IAAI,EAAE,EAAE;SAClD;KACF,CAAA;AACH,CAAC,CAAA;AAhDY,QAAA,kBAAkB,sBAgD9B"}
@@ -0,0 +1,35 @@
1
+ import { type Bundle } from '@medplum/fhirtypes';
2
+ export interface BuildTransactionBundleArgs {
3
+ /** The `collection` bundle fetched from Metriport's pre-signed URL. */
4
+ bundle: Bundle;
5
+ /** The Awell patient id, used to resolve the Medplum Patient. */
6
+ awellPatientId: string;
7
+ /** The Metriport webhook type, e.g. `patient.admit`. Drives Provenance.activity. */
8
+ eventType?: string;
9
+ /** Free-text reason recorded on the Provenance. */
10
+ reason?: string;
11
+ /** Fallback for `Provenance.recorded`; injectable so tests stay deterministic. */
12
+ now?: string;
13
+ }
14
+ /**
15
+ * Converts a Metriport Patient Encounter Bundle into a bundle Medplum can
16
+ * execute, plus a Provenance recording the import.
17
+ *
18
+ * Pure and synchronous: every lookup that would otherwise need a Medplum read
19
+ * is expressed declaratively instead — a conditional reference for the Patient,
20
+ * conditional updates for the Metriport resources, and `ifNoneExist` for the
21
+ * account Organization.
22
+ *
23
+ * Returns `undefined` for a bundle that is not a `collection`, since that is
24
+ * simply one of Metriport's other webhook types and the calling action still
25
+ * has a raw `bundle` to emit.
26
+ *
27
+ * Throws when a `collection` bundle is missing its Patient or Encounter entry.
28
+ * That combination is an encounter bundle that does not describe an encounter —
29
+ * malformed rather than merely different — and every reference the
30
+ * transformation rewrites hangs off those two resources, so there is nothing
31
+ * sensible to import.
32
+ *
33
+ * https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle
34
+ */
35
+ export declare const buildTransactionBundle: ({ bundle, awellPatientId, eventType, reason, now, }: BuildTransactionBundleArgs) => Bundle | undefined;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTransactionBundle = void 0;
4
+ const account_1 = require("./account");
5
+ const entries_1 = require("./entries");
6
+ const provenance_1 = require("./provenance");
7
+ const references_1 = require("./references");
8
+ /**
9
+ * Converts a Metriport Patient Encounter Bundle into a bundle Medplum can
10
+ * execute, plus a Provenance recording the import.
11
+ *
12
+ * Pure and synchronous: every lookup that would otherwise need a Medplum read
13
+ * is expressed declaratively instead — a conditional reference for the Patient,
14
+ * conditional updates for the Metriport resources, and `ifNoneExist` for the
15
+ * account Organization.
16
+ *
17
+ * Returns `undefined` for a bundle that is not a `collection`, since that is
18
+ * simply one of Metriport's other webhook types and the calling action still
19
+ * has a raw `bundle` to emit.
20
+ *
21
+ * Throws when a `collection` bundle is missing its Patient or Encounter entry.
22
+ * That combination is an encounter bundle that does not describe an encounter —
23
+ * malformed rather than merely different — and every reference the
24
+ * transformation rewrites hangs off those two resources, so there is nothing
25
+ * sensible to import.
26
+ *
27
+ * https://docs.metriport.com/medical-api/handling-data/patient-encounter-bundle
28
+ */
29
+ const buildTransactionBundle = ({ bundle, awellPatientId, eventType, reason, now, }) => {
30
+ var _a, _b, _c;
31
+ if (bundle.type !== 'collection')
32
+ return undefined;
33
+ // Entries are kept whole rather than reduced to resources: each one carries
34
+ // the `fullUrl` Metriport assigned, which becomes the entry's local identity
35
+ // in the transaction.
36
+ const entries = ((_a = bundle.entry) !== null && _a !== void 0 ? _a : []).filter((entry) => entry.resource !== undefined);
37
+ const hasPatient = entries.some((entry) => entry.resource.resourceType === 'Patient');
38
+ const hasEncounter = entries.some((entry) => entry.resource.resourceType === 'Encounter');
39
+ const missing = [
40
+ ...(hasPatient ? [] : ['Patient']),
41
+ ...(hasEncounter ? [] : ['Encounter']),
42
+ ];
43
+ if (missing.length > 0) {
44
+ throw new Error(`[Metriport bundle] Collection bundle has no ${missing.join(' or ')} entry, so it is not a valid Patient Encounter Bundle`);
45
+ }
46
+ const referenceMap = (0, references_1.buildReferenceMap)(bundle, awellPatientId);
47
+ // The Patient is referenced conditionally rather than written: Medplum is the
48
+ // source of truth for it, so Metriport demographics must not overwrite it.
49
+ const resourceEntries = entries
50
+ .filter((entry) => entry.resource.resourceType !== 'Patient')
51
+ .map((entry) => (0, entries_1.buildResourceEntry)((0, references_1.rewriteReferences)(entry.resource, referenceMap), entry.fullUrl));
52
+ const provenance = (0, provenance_1.buildProvenance)({
53
+ targetReferences: resourceEntries
54
+ .map((entry) => entry.fullUrl)
55
+ .filter((fullUrl) => fullUrl !== undefined),
56
+ sourceBundleId: bundle.id,
57
+ recorded: (_c = (_b = bundle.timestamp) !== null && _b !== void 0 ? _b : now) !== null && _c !== void 0 ? _c : new Date().toISOString(),
58
+ reason,
59
+ eventType,
60
+ });
61
+ return {
62
+ resourceType: 'Bundle',
63
+ type: 'transaction',
64
+ entry: [(0, account_1.buildAccountOrganizationEntry)(), ...resourceEntries, provenance],
65
+ };
66
+ };
67
+ exports.buildTransactionBundle = buildTransactionBundle;
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/index.ts"],"names":[],"mappings":";;;AAKA,uCAAyD;AACzD,uCAA8C;AAC9C,6CAA8C;AAC9C,6CAAmE;AAenE;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,MAAM,sBAAsB,GAAG,CAAC,EACrC,MAAM,EACN,cAAc,EACd,SAAS,EACT,MAAM,EACN,GAAG,GACwB,EAAsB,EAAE;;IACnD,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,SAAS,CAAA;IAElD,4EAA4E;IAC5E,6EAA6E;IAC7E,sBAAsB;IACtB,MAAM,OAAO,GAAG,CAAC,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAC,MAAM,CACzC,CAAC,KAAK,EAAiD,EAAE,CACvD,KAAK,CAAC,QAAQ,KAAK,SAAS,CAC/B,CAAA;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAC7B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,KAAK,SAAS,CACrD,CAAA;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,KAAK,WAAW,CACvD,CAAA;IAED,MAAM,OAAO,GAAG;QACd,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;KACvC,CAAA;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,+CAA+C,OAAO,CAAC,IAAI,CACzD,MAAM,CACP,uDAAuD,CACzD,CAAA;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAA,8BAAiB,EAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAE9D,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,eAAe,GAAkB,OAAO;SAC3C,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,KAAK,SAAS,CAAC;SAC5D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,IAAA,4BAAkB,EAChB,IAAA,8BAAiB,EAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,EAC/C,KAAK,CAAC,OAAO,CACd,CACF,CAAA;IAEH,MAAM,UAAU,GAAG,IAAA,4BAAe,EAAC;QACjC,gBAAgB,EAAE,eAAe;aAC9B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;aAC7B,MAAM,CAAC,CAAC,OAAO,EAAqB,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC;QAChE,cAAc,EAAE,MAAM,CAAC,EAAE;QACzB,QAAQ,EAAE,MAAA,MAAA,MAAM,CAAC,SAAS,mCAAI,GAAG,mCAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC7D,MAAM;QACN,SAAS;KACV,CAAC,CAAA;IAEF,OAAO;QACL,YAAY,EAAE,QAAQ;QACtB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,CAAC,IAAA,uCAA6B,GAAE,EAAE,GAAG,eAAe,EAAE,UAAU,CAAC;KACzE,CAAA;AACH,CAAC,CAAA;AAjEY,QAAA,sBAAsB,0BAiElC"}
@@ -0,0 +1,16 @@
1
+ import { type BundleEntry, type CodeableConcept, type Provenance } from '@medplum/fhirtypes';
2
+ export declare const eventTypeToActivity: (eventType: string | undefined) => CodeableConcept | undefined;
3
+ /**
4
+ * Builds the Provenance entry recording this import, so a care flow can trace
5
+ * every resource back to the Metriport notification that produced it.
6
+ *
7
+ * POST rather than a conditional update: Provenance has no `identifier` element
8
+ * in FHIR R4, and each delivery is a distinct import event.
9
+ */
10
+ export declare const buildProvenance: ({ targetReferences, sourceBundleId, recorded, reason, eventType, }: {
11
+ targetReferences: string[];
12
+ sourceBundleId: string | undefined;
13
+ recorded: string;
14
+ reason?: string;
15
+ eventType?: string;
16
+ }) => BundleEntry<Provenance>;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildProvenance = exports.eventTypeToActivity = void 0;
4
+ const constants_1 = require("./constants");
5
+ const HL7_EVENT_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/v2-0003';
6
+ /**
7
+ * Metriport's ADT notification types map onto the HL7 v2 event codes they
8
+ * originate from, so admission vs. discharge is derived from the webhook rather
9
+ * than configured by hand.
10
+ */
11
+ const ACTIVITY_BY_EVENT_TYPE = {
12
+ 'patient.admit': {
13
+ coding: [
14
+ {
15
+ system: HL7_EVENT_TYPE_SYSTEM,
16
+ code: 'A01',
17
+ display: 'ADT/ACK - Admit/visit notification',
18
+ },
19
+ ],
20
+ },
21
+ 'patient.transfer': {
22
+ coding: [
23
+ {
24
+ system: HL7_EVENT_TYPE_SYSTEM,
25
+ code: 'A02',
26
+ display: 'ADT/ACK - Transfer a patient',
27
+ },
28
+ ],
29
+ },
30
+ 'patient.discharge': {
31
+ coding: [
32
+ {
33
+ system: HL7_EVENT_TYPE_SYSTEM,
34
+ code: 'A03',
35
+ display: 'ADT/ACK - Discharge/end visit',
36
+ },
37
+ ],
38
+ },
39
+ };
40
+ const eventTypeToActivity = (eventType) => eventType === undefined ? undefined : ACTIVITY_BY_EVENT_TYPE[eventType];
41
+ exports.eventTypeToActivity = eventTypeToActivity;
42
+ /**
43
+ * Builds the Provenance entry recording this import, so a care flow can trace
44
+ * every resource back to the Metriport notification that produced it.
45
+ *
46
+ * POST rather than a conditional update: Provenance has no `identifier` element
47
+ * in FHIR R4, and each delivery is a distinct import event.
48
+ */
49
+ const buildProvenance = ({ targetReferences, sourceBundleId, recorded, reason, eventType, }) => {
50
+ const activity = (0, exports.eventTypeToActivity)(eventType);
51
+ const provenance = {
52
+ resourceType: 'Provenance',
53
+ target: targetReferences.map((reference) => ({ reference })),
54
+ recorded,
55
+ agent: [
56
+ {
57
+ type: {
58
+ coding: [
59
+ {
60
+ system: 'http://terminology.hl7.org/CodeSystem/provenance-participant-type',
61
+ code: 'assembler',
62
+ display: 'Assembler',
63
+ },
64
+ ],
65
+ },
66
+ who: { reference: constants_1.ACCOUNT_ORGANIZATION_FULL_URL },
67
+ },
68
+ ],
69
+ entity: [
70
+ {
71
+ role: 'source',
72
+ what: {
73
+ identifier: {
74
+ system: constants_1.METRIPORT_BUNDLE_IDENTIFIER_SYSTEM,
75
+ value: sourceBundleId,
76
+ },
77
+ },
78
+ },
79
+ ],
80
+ ...(reason !== undefined && reason !== ''
81
+ ? { reason: [{ text: reason }] }
82
+ : {}),
83
+ ...(activity !== undefined ? { activity } : {}),
84
+ };
85
+ return {
86
+ fullUrl: constants_1.PROVENANCE_FULL_URL,
87
+ resource: provenance,
88
+ request: { method: 'POST', url: 'Provenance' },
89
+ };
90
+ };
91
+ exports.buildProvenance = buildProvenance;
92
+ //# sourceMappingURL=provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/provenance.ts"],"names":[],"mappings":";;;AAKA,2CAIoB;AAEpB,MAAM,qBAAqB,GAAG,+CAA+C,CAAA;AAE7E;;;;GAIG;AACH,MAAM,sBAAsB,GAAoC;IAC9D,eAAe,EAAE;QACf,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,qBAAqB;gBAC7B,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,oCAAoC;aAC9C;SACF;KACF;IACD,kBAAkB,EAAE;QAClB,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,qBAAqB;gBAC7B,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,8BAA8B;aACxC;SACF;KACF;IACD,mBAAmB,EAAE;QACnB,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,qBAAqB;gBAC7B,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,+BAA+B;aACzC;SACF;KACF;CACF,CAAA;AAEM,MAAM,mBAAmB,GAAG,CACjC,SAA6B,EACA,EAAE,CAC/B,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAA;AAH5D,QAAA,mBAAmB,uBAGyC;AAEzE;;;;;;GAMG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,MAAM,EACN,SAAS,GAOV,EAA2B,EAAE;IAC5B,MAAM,QAAQ,GAAG,IAAA,2BAAmB,EAAC,SAAS,CAAC,CAAA;IAE/C,MAAM,UAAU,GAAe;QAC7B,YAAY,EAAE,YAAY;QAC1B,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,QAAQ;QACR,KAAK,EAAE;YACL;gBACE,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN;4BACE,MAAM,EACJ,mEAAmE;4BACrE,IAAI,EAAE,WAAW;4BACjB,OAAO,EAAE,WAAW;yBACrB;qBACF;iBACF;gBACD,GAAG,EAAE,EAAE,SAAS,EAAE,yCAA6B,EAAE;aAClD;SACF;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE;oBACJ,UAAU,EAAE;wBACV,MAAM,EAAE,8CAAkC;wBAC1C,KAAK,EAAE,cAAc;qBACtB;iBACF;aACF;SACF;QACD,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE;YACvC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE;YAChC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAA;IAED,OAAO;QACL,OAAO,EAAE,+BAAmB;QAC5B,QAAQ,EAAE,UAAU;QACpB,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE;KAC/C,CAAA;AACH,CAAC,CAAA;AAxDY,QAAA,eAAe,mBAwD3B"}
@@ -0,0 +1,28 @@
1
+ import { type Bundle } from '@medplum/fhirtypes';
2
+ /** Maps a Metriport `<ResourceType>/<id>` reference to its rewritten form. */
3
+ export type ReferenceMap = Record<string, string>;
4
+ /**
5
+ * Metriport emits internal references using its own resource ids
6
+ * (`"reference": "Patient/78a4d9e5-…"`), which resolve to nothing in Medplum.
7
+ * This builds the lookup used to rewrite them:
8
+ *
9
+ * - the Patient becomes a conditional reference on the Awell identifier, since
10
+ * Medplum already holds that record and it is not part of the transaction
11
+ * - everything else becomes the entry's own `fullUrl`, resolved by the
12
+ * transaction to whatever that entry created or updated
13
+ *
14
+ * Metriport's ids already line up across the bundle; what does not line up is
15
+ * the *form*. Metriport emits `urn:uuid:<id>` fullUrls but `<Type>/<id>`
16
+ * references, and FHIR resolves an intra-bundle reference by matching it
17
+ * against `fullUrl` verbatim — a relative reference does not match a
18
+ * `urn:uuid:` fullUrl. Rewriting to the fullUrl closes that gap without
19
+ * inventing identity of our own.
20
+ */
21
+ export declare const buildReferenceMap: (bundle: Bundle, awellPatientId: string) => ReferenceMap;
22
+ /**
23
+ * Recursively rewrites every `reference` field found in the map, returning a
24
+ * new object. Only the `reference` key is considered, so values that merely
25
+ * look like references (a `display` of "Patient/123", say) are left alone, as
26
+ * are absolute URLs and references to resources outside the bundle.
27
+ */
28
+ export declare const rewriteReferences: <T>(value: T, map: ReferenceMap) => T;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rewriteReferences = exports.buildReferenceMap = void 0;
4
+ const constants_1 = require("./constants");
5
+ /**
6
+ * Metriport emits internal references using its own resource ids
7
+ * (`"reference": "Patient/78a4d9e5-…"`), which resolve to nothing in Medplum.
8
+ * This builds the lookup used to rewrite them:
9
+ *
10
+ * - the Patient becomes a conditional reference on the Awell identifier, since
11
+ * Medplum already holds that record and it is not part of the transaction
12
+ * - everything else becomes the entry's own `fullUrl`, resolved by the
13
+ * transaction to whatever that entry created or updated
14
+ *
15
+ * Metriport's ids already line up across the bundle; what does not line up is
16
+ * the *form*. Metriport emits `urn:uuid:<id>` fullUrls but `<Type>/<id>`
17
+ * references, and FHIR resolves an intra-bundle reference by matching it
18
+ * against `fullUrl` verbatim — a relative reference does not match a
19
+ * `urn:uuid:` fullUrl. Rewriting to the fullUrl closes that gap without
20
+ * inventing identity of our own.
21
+ */
22
+ const buildReferenceMap = (bundle, awellPatientId) => {
23
+ var _a, _b;
24
+ const map = {};
25
+ for (const entry of (_a = bundle.entry) !== null && _a !== void 0 ? _a : []) {
26
+ const resource = entry.resource;
27
+ if ((resource === null || resource === void 0 ? void 0 : resource.id) === undefined)
28
+ continue;
29
+ const key = `${resource.resourceType}/${resource.id}`;
30
+ map[key] =
31
+ resource.resourceType === 'Patient'
32
+ ? (0, constants_1.awellPatientReference)(awellPatientId)
33
+ : // Metriport always sends one; the urn is only a fallback for a
34
+ // bundle that omits it.
35
+ (_b = entry.fullUrl) !== null && _b !== void 0 ? _b : `urn:uuid:${resource.id}`;
36
+ }
37
+ return map;
38
+ };
39
+ exports.buildReferenceMap = buildReferenceMap;
40
+ /**
41
+ * Recursively rewrites every `reference` field found in the map, returning a
42
+ * new object. Only the `reference` key is considered, so values that merely
43
+ * look like references (a `display` of "Patient/123", say) are left alone, as
44
+ * are absolute URLs and references to resources outside the bundle.
45
+ */
46
+ const rewriteReferences = (value, map) => {
47
+ var _a;
48
+ if (Array.isArray(value)) {
49
+ return value.map((item) => (0, exports.rewriteReferences)(item, map));
50
+ }
51
+ if (value === null || typeof value !== 'object')
52
+ return value;
53
+ const result = {};
54
+ for (const [key, child] of Object.entries(value)) {
55
+ if (key === 'reference' && typeof child === 'string') {
56
+ result[key] = (_a = map[child]) !== null && _a !== void 0 ? _a : child;
57
+ }
58
+ else {
59
+ result[key] = (0, exports.rewriteReferences)(child, map);
60
+ }
61
+ }
62
+ return result;
63
+ };
64
+ exports.rewriteReferences = rewriteReferences;
65
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../../../../../../extensions/metriport/actions/webhookBundle/bundle/references.ts"],"names":[],"mappings":";;;AACA,2CAAmD;AAKnD;;;;;;;;;;;;;;;;GAgBG;AACI,MAAM,iBAAiB,GAAG,CAC/B,MAAc,EACd,cAAsB,EACR,EAAE;;IAChB,MAAM,GAAG,GAAiB,EAAE,CAAA;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;QAC/B,IAAI,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,EAAE,MAAK,SAAS;YAAE,SAAQ;QAExC,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAA;QACrD,GAAG,CAAC,GAAG,CAAC;YACN,QAAQ,CAAC,YAAY,KAAK,SAAS;gBACjC,CAAC,CAAC,IAAA,iCAAqB,EAAC,cAAc,CAAC;gBACvC,CAAC,CAAC,+DAA+D;oBAC/D,wBAAwB;oBACxB,MAAA,KAAK,CAAC,OAAO,mCAAI,YAAY,QAAQ,CAAC,EAAE,EAAE,CAAA;IAClD,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AApBY,QAAA,iBAAiB,qBAoB7B;AAED;;;;;GAKG;AACI,MAAM,iBAAiB,GAAG,CAAI,KAAQ,EAAE,GAAiB,EAAK,EAAE;;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,yBAAiB,EAAC,IAAI,EAAE,GAAG,CAAC,CAAiB,CAAA;IAC1E,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE7D,MAAM,MAAM,GAA4B,EAAE,CAAA;IAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,GAAG,KAAK,WAAW,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAA,GAAG,CAAC,KAAK,CAAC,mCAAI,KAAK,CAAA;QACnC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,IAAA,yBAAiB,EAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC;IAED,OAAO,MAAW,CAAA;AACpB,CAAC,CAAA;AAlBY,QAAA,iBAAiB,qBAkB7B"}
@@ -3,4 +3,13 @@ export declare const dataPoints: {
3
3
  key: string;
4
4
  valueType: "json";
5
5
  };
6
+ /**
7
+ * The `bundle` rewritten as an executable FHIR transaction, ready to hand to
8
+ * the Medplum `Find or create resource` action. Omitted when the payload is
9
+ * not a Patient Encounter Bundle.
10
+ */
11
+ transactionBundle: {
12
+ key: string;
13
+ valueType: "json";
14
+ };
6
15
  };
@@ -6,5 +6,14 @@ exports.dataPoints = {
6
6
  key: 'bundle',
7
7
  valueType: 'json',
8
8
  },
9
+ /**
10
+ * The `bundle` rewritten as an executable FHIR transaction, ready to hand to
11
+ * the Medplum `Find or create resource` action. Omitted when the payload is
12
+ * not a Patient Encounter Bundle.
13
+ */
14
+ transactionBundle: {
15
+ key: 'transactionBundle',
16
+ valueType: 'json',
17
+ },
9
18
  };
10
19
  //# sourceMappingURL=dataPoints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataPoints.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/dataPoints.ts"],"names":[],"mappings":";;;AAEa,QAAA,UAAU,GAAG;IACxB,MAAM,EAAE;QACN,GAAG,EAAE,QAAQ;QACb,SAAS,EAAE,MAAM;KAClB;CAC4C,CAAA"}
1
+ {"version":3,"file":"dataPoints.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/dataPoints.ts"],"names":[],"mappings":";;;AAEa,QAAA,UAAU,GAAG;IACxB,MAAM,EAAE;QACN,GAAG,EAAE,QAAQ;QACb,SAAS,EAAE,MAAM;KAClB;IACD;;;;OAIG;IACH,iBAAiB,EAAE;QACjB,GAAG,EAAE,mBAAmB;QACxB,SAAS,EAAE,MAAM;KAClB;CAC4C,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { FieldType } from '@awell-health/extensions-core';
2
+ import { MetriportWebhookType } from '../../webhooks/types';
2
3
  export declare const fields: {
3
4
  url: {
4
5
  id: string;
@@ -7,4 +8,24 @@ export declare const fields: {
7
8
  type: FieldType.STRING;
8
9
  required: true;
9
10
  };
11
+ eventType: {
12
+ id: string;
13
+ label: string;
14
+ description: string;
15
+ type: FieldType.STRING;
16
+ required: false;
17
+ options: {
18
+ dropdownOptions: {
19
+ label: string;
20
+ value: MetriportWebhookType;
21
+ }[];
22
+ };
23
+ };
24
+ provenanceReason: {
25
+ id: string;
26
+ label: string;
27
+ description: string;
28
+ type: FieldType.TEXT;
29
+ required: false;
30
+ };
10
31
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fields = void 0;
4
4
  const extensions_core_1 = require("@awell-health/extensions-core");
5
+ const types_1 = require("../../webhooks/types");
5
6
  exports.fields = {
6
7
  url: {
7
8
  id: 'url',
@@ -10,5 +11,35 @@ exports.fields = {
10
11
  type: extensions_core_1.FieldType.STRING,
11
12
  required: true,
12
13
  },
14
+ eventType: {
15
+ id: 'eventType',
16
+ label: 'Event Type',
17
+ description: 'The Metriport notification type, as emitted on the enrollment webhook `eventType` data point. Recorded on the Provenance of the importable bundle so admission, transfer and discharge imports can be told apart. Leave empty to omit it.',
18
+ type: extensions_core_1.FieldType.STRING,
19
+ required: false,
20
+ options: {
21
+ dropdownOptions: [
22
+ {
23
+ label: 'Admission (patient.admit)',
24
+ value: types_1.MetriportWebhookType.PatientAdmit,
25
+ },
26
+ {
27
+ label: 'Transfer (patient.transfer)',
28
+ value: types_1.MetriportWebhookType.PatientTransfer,
29
+ },
30
+ {
31
+ label: 'Discharge (patient.discharge)',
32
+ value: types_1.MetriportWebhookType.PatientDischarge,
33
+ },
34
+ ],
35
+ },
36
+ },
37
+ provenanceReason: {
38
+ id: 'provenanceReason',
39
+ label: 'Provenance Reason',
40
+ description: 'Free-text reason recorded on the Provenance of the importable bundle, describing why this data was imported. Lets imported bundles be traced back to the clinical event that triggered them.',
41
+ type: extensions_core_1.FieldType.TEXT,
42
+ required: false,
43
+ },
13
44
  };
14
45
  //# sourceMappingURL=fields.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/fields.ts"],"names":[],"mappings":";;;AAAA,mEAAqE;AAExD,QAAA,MAAM,GAAG;IACpB,GAAG,EAAE;QACH,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,qQAAqQ;QACvQ,IAAI,EAAE,2BAAS,CAAC,MAAM;QACtB,QAAQ,EAAE,IAAI;KACf;CAC8B,CAAA"}
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/fields.ts"],"names":[],"mappings":";;;AAAA,mEAAqE;AACrE,gDAA2D;AAE9C,QAAA,MAAM,GAAG;IACpB,GAAG,EAAE;QACH,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,qQAAqQ;QACvQ,IAAI,EAAE,2BAAS,CAAC,MAAM;QACtB,QAAQ,EAAE,IAAI;KACf;IACD,SAAS,EAAE;QACT,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,2OAA2O;QAC7O,IAAI,EAAE,2BAAS,CAAC,MAAM;QACtB,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE;YACP,eAAe,EAAE;gBACf;oBACE,KAAK,EAAE,2BAA2B;oBAClC,KAAK,EAAE,4BAAoB,CAAC,YAAY;iBACzC;gBACD;oBACE,KAAK,EAAE,6BAA6B;oBACpC,KAAK,EAAE,4BAAoB,CAAC,eAAe;iBAC5C;gBACD;oBACE,KAAK,EAAE,+BAA+B;oBACtC,KAAK,EAAE,4BAAoB,CAAC,gBAAgB;iBAC7C;aACF;SACF;KACF;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,kBAAkB;QACtB,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,8LAA8L;QAChM,IAAI,EAAE,2BAAS,CAAC,IAAI;QACpB,QAAQ,EAAE,KAAK;KAChB;CAC8B,CAAA"}
@@ -7,6 +7,7 @@ const fields_1 = require("./fields");
7
7
  const validation_1 = require("./validation");
8
8
  const dataPoints_1 = require("./dataPoints");
9
9
  const fetchBundle_1 = require("./fetchBundle");
10
+ const bundle_1 = require("./bundle");
10
11
  exports.getWebhookBundle = {
11
12
  key: 'getWebhookBundle',
12
13
  category: extensions_core_1.Category.EHR_INTEGRATIONS,
@@ -18,11 +19,25 @@ exports.getWebhookBundle = {
18
19
  dataPoints: dataPoints_1.dataPoints,
19
20
  onActivityCreated: async (payload, onComplete, onError) => {
20
21
  try {
21
- const { url } = validation_1.getWebhookBundleSchema.parse(payload.fields);
22
+ const { url, eventType, provenanceReason } = validation_1.getWebhookBundleSchema.parse(payload.fields);
22
23
  const bundle = await (0, fetchBundle_1.fetchBundle)(url);
24
+ // Only ADT notifications carry Patient Encounter Bundles; for the other
25
+ // webhook types this is undefined and the data point is simply omitted.
26
+ // A collection bundle missing its Patient or Encounter throws instead —
27
+ // it claims to be an encounter bundle but cannot be imported, so failing
28
+ // the activity is better than silently emitting the raw bundle alone.
29
+ const transactionBundle = (0, bundle_1.buildTransactionBundle)({
30
+ bundle,
31
+ awellPatientId: payload.patient.id,
32
+ eventType,
33
+ reason: provenanceReason,
34
+ });
23
35
  await onComplete({
24
36
  data_points: {
25
37
  bundle: JSON.stringify(bundle),
38
+ ...(transactionBundle !== undefined
39
+ ? { transactionBundle: JSON.stringify(transactionBundle) }
40
+ : {}),
26
41
  },
27
42
  });
28
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getWebhookBundle.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/getWebhookBundle.ts"],"names":[],"mappings":";;;AAAA,mEAAqE;AAErE,4DAA8D;AAC9D,qCAAiC;AACjC,6CAAqD;AACrD,6CAAyC;AACzC,+CAA2C;AAE9B,QAAA,gBAAgB,GAIzB;IACF,GAAG,EAAE,kBAAkB;IACvB,QAAQ,EAAE,0BAAQ,CAAC,gBAAgB;IACnC,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EACT,0PAA0P;IAC5P,MAAM,EAAN,eAAM;IACN,WAAW,EAAE,IAAI;IACjB,0BAA0B,EAAE,IAAI;IAChC,UAAU,EAAV,uBAAU;IACV,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAiB,EAAE;QACvE,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,EAAE,GAAG,mCAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YAE5D,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAW,EAAC,GAAG,CAAC,CAAA;YAErC,MAAM,UAAU,CAAC;gBACf,WAAW,EAAE;oBACX,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;iBAC/B;aACF,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAA,iCAAkB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;CACF,CAAA"}
1
+ {"version":3,"file":"getWebhookBundle.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/getWebhookBundle.ts"],"names":[],"mappings":";;;AAAA,mEAAqE;AAErE,4DAA8D;AAC9D,qCAAiC;AACjC,6CAAqD;AACrD,6CAAyC;AACzC,+CAA2C;AAC3C,qCAAiD;AAEpC,QAAA,gBAAgB,GAIzB;IACF,GAAG,EAAE,kBAAkB;IACvB,QAAQ,EAAE,0BAAQ,CAAC,gBAAgB;IACnC,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EACT,0PAA0P;IAC5P,MAAM,EAAN,eAAM;IACN,WAAW,EAAE,IAAI;IACjB,0BAA0B,EAAE,IAAI;IAChC,UAAU,EAAV,uBAAU;IACV,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAiB,EAAE;QACvE,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,mCAAsB,CAAC,KAAK,CACvE,OAAO,CAAC,MAAM,CACf,CAAA;YAED,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAW,EAAC,GAAG,CAAC,CAAA;YAErC,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,yEAAyE;YACzE,sEAAsE;YACtE,MAAM,iBAAiB,GAAG,IAAA,+BAAsB,EAAC;gBAC/C,MAAM;gBACN,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;gBAClC,SAAS;gBACT,MAAM,EAAE,gBAAgB;aACzB,CAAC,CAAA;YAEF,MAAM,UAAU,CAAC;gBACf,WAAW,EAAE;oBACX,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;oBAC9B,GAAG,CAAC,iBAAiB,KAAK,SAAS;wBACjC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAE;wBAC1D,CAAC,CAAC,EAAE,CAAC;iBACR;aACF,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAA,iCAAkB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;CACF,CAAA"}
@@ -1,8 +1,14 @@
1
1
  import { z } from 'zod';
2
2
  export declare const getWebhookBundleSchema: z.ZodObject<{
3
3
  url: z.ZodString;
4
+ eventType: z.ZodOptional<z.ZodString>;
5
+ provenanceReason: z.ZodOptional<z.ZodString>;
4
6
  }, "strip", z.ZodTypeAny, {
5
7
  url: string;
8
+ eventType?: string | undefined;
9
+ provenanceReason?: string | undefined;
6
10
  }, {
7
11
  url: string;
12
+ eventType?: string | undefined;
13
+ provenanceReason?: string | undefined;
8
14
  }>;
@@ -7,5 +7,7 @@ exports.getWebhookBundleSchema = zod_1.z.object({
7
7
  .string({ errorMap: () => ({ message: 'Missing url' }) })
8
8
  .trim()
9
9
  .url({ message: 'A valid bundle URL is required' }),
10
+ eventType: zod_1.z.string().trim().optional(),
11
+ provenanceReason: zod_1.z.string().trim().optional(),
10
12
  });
11
13
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/validation.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEV,QAAA,sBAAsB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,OAAC;SACH,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;SACxD,IAAI,EAAE;SACN,GAAG,CAAC,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC;CACtD,CAAC,CAAA"}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../../../extensions/metriport/actions/webhookBundle/validation.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEV,QAAA,sBAAsB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,OAAC;SACH,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;SACxD,IAAI,EAAE;SACN,GAAG,CAAC,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC;IACrD,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awell-health/awell-extensions",
3
- "version": "2.1.147",
3
+ "version": "2.1.149",
4
4
  "packageManager": "yarn@4.5.3",
5
5
  "main": "dist/src/index.js",
6
6
  "repository": {