@fuego-systems/core 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export * from './scheduling/appointment';
3
3
  export type * from './scheduling/extension';
4
4
  export * from './constants';
5
5
  export * from './plan-definition-group';
6
+ export * from './preparation-groups';
7
+ export * from './resolved-protocol';
6
8
  export * from './practica-mapping';
7
9
  export * from './practica-resolution';
8
10
  export * from './fhir';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,mBAAmB,wBAAwB,CAAA;AAC3C,cAAc,aAAa,CAAA;AAC3B,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,QAAQ,CAAA;AACtB,mBAAmB,YAAY,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,mBAAmB,wBAAwB,CAAA;AAC3C,cAAc,aAAa,CAAA;AAC3B,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,QAAQ,CAAA;AACtB,mBAAmB,YAAY,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA"}
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ __exportStar(require("./scheduling/slot"), exports);
18
18
  __exportStar(require("./scheduling/appointment"), exports);
19
19
  __exportStar(require("./constants"), exports);
20
20
  __exportStar(require("./plan-definition-group"), exports);
21
+ __exportStar(require("./preparation-groups"), exports);
22
+ __exportStar(require("./resolved-protocol"), exports);
21
23
  __exportStar(require("./practica-mapping"), exports);
22
24
  __exportStar(require("./practica-resolution"), exports);
23
25
  __exportStar(require("./fhir"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAiC;AACjC,2DAAwC;AAExC,8CAA2B;AAC3B,0DAAuC;AACvC,qDAAkC;AAClC,wDAAqC;AACrC,yCAAsB;AAEtB,sDAAmC;AACnC,yDAAsC","sourcesContent":["export * from './scheduling/slot'\nexport * from './scheduling/appointment'\nexport type * from './scheduling/extension'\nexport * from './constants'\nexport * from './plan-definition-group'\nexport * from './practica-mapping'\nexport * from './practica-resolution'\nexport * from './fhir'\nexport type * from './db/types'\nexport * from './search/normalizer'\nexport * from './search/alias-builder'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAiC;AACjC,2DAAwC;AAExC,8CAA2B;AAC3B,0DAAuC;AACvC,uDAAoC;AACpC,sDAAmC;AACnC,qDAAkC;AAClC,wDAAqC;AACrC,yCAAsB;AAEtB,sDAAmC;AACnC,yDAAsC","sourcesContent":["export * from './scheduling/slot'\nexport * from './scheduling/appointment'\nexport type * from './scheduling/extension'\nexport * from './constants'\nexport * from './plan-definition-group'\nexport * from './preparation-groups'\nexport * from './resolved-protocol'\nexport * from './practica-mapping'\nexport * from './practica-resolution'\nexport * from './fhir'\nexport type * from './db/types'\nexport * from './search/normalizer'\nexport * from './search/alias-builder'\n"]}
@@ -229,6 +229,16 @@ export declare function readProtocolSelection(pd: PlanDefinition): ProtocolSelec
229
229
  * @returns the variant's mandatory-addon overrides (empty when none)
230
230
  */
231
231
  export declare function readMandatoryAddonOverrides(variantAction: PlanDefinitionAction): MandatoryAddonOverride[];
232
+ /**
233
+ * Extracts the canonicals of an order-set PD's **default** mandatory add-ons:
234
+ * the `action[id='addons']` sub-actions flagged `requiredBehavior: 'must'`.
235
+ * These are the defaults that {@link resolveVariantMandatoryAddons} combines
236
+ * with a selected variant's `mandatory-addons` overrides.
237
+ *
238
+ * @param orderSetPd - an order-set PlanDefinition
239
+ * @returns canonicals of the default mandatory add-ons (empty when none)
240
+ */
241
+ export declare function getOrderSetDefaultMandatoryRefs(orderSetPd: PlanDefinition): string[];
232
242
  /**
233
243
  * Resolves the effective mandatory add-on canonicals for a selected variant:
234
244
  * the order-set PD defaults, plus the variant's `'add'` overrides, minus its
@@ -1 +1 @@
1
- {"version":3,"file":"plan-definition-group.d.ts","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan-definition-group.d.ts","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGxF;;;;;;;;GAQG;AACH,eAAO,MAAM,kCAAkC,qBAAqB,CAAA;AAcpE;;;;;GAKG;AACH,MAAM,MAAM,4BAA4B,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,sFAAsF;IACtF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAA;IAC7C,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,SAAS,sBAAsB,EAAE,CAAA;CACpE;AAED,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IACrD;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAA;CACrE;AAID,0DAA0D;AAC1D,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AAEpD,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAI5D;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAE,EAAE,EAAE,cAAc,GAAG,kBAAkB,EAAE,CAM5E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAE,EAAE,EAAE,cAAc,GAAG,mBAAmB,GAAG,SAAS,CASvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAE,EAAE,EAAE,cAAc,GAAG,kBAAkB,EAAE,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,0CAA0C,CAAE,EAAE,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAElG;AAID;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,wBAAwB,EAAE,EAC5C,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,cAAc,CAmEhB;AAID;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED,gEAAgE;AAChE,MAAM,WAAW,sBAAsB;IACrC,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAED,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;IACrC,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,SAAS,sBAAsB,EAAE,CAAA;CACnD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,cAAc,EAClB,SAAS,EAAE,iBAAiB,GAC3B,cAAc,CAiChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,cAAc,EAClB,SAAS,EAAE,iBAAiB,GAC3B,gBAAgB,CA4BlB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAE,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAwB5E;AA+CD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,oBAAoB,GAClC,sBAAsB,EAAE,CAc1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAE,UAAU,EAAE,cAAc,GAAG,MAAM,EAAE,CAMrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,aAAa,EAAE,oBAAoB,GAAG,SAAS,GAC9C,MAAM,EAAE,CAYV"}
@@ -11,6 +11,7 @@ exports.configureProtocolGroup = configureProtocolGroup;
11
11
  exports.resolveProtocolSelection = resolveProtocolSelection;
12
12
  exports.readProtocolSelection = readProtocolSelection;
13
13
  exports.readMandatoryAddonOverrides = readMandatoryAddonOverrides;
14
+ exports.getOrderSetDefaultMandatoryRefs = getOrderSetDefaultMandatoryRefs;
14
15
  exports.resolveVariantMandatoryAddons = resolveVariantMandatoryAddons;
15
16
  const constants_1 = require("./constants");
16
17
  /**
@@ -339,6 +340,21 @@ function readMandatoryAddonOverrides(variantAction) {
339
340
  }
340
341
  return result;
341
342
  }
343
+ /**
344
+ * Extracts the canonicals of an order-set PD's **default** mandatory add-ons:
345
+ * the `action[id='addons']` sub-actions flagged `requiredBehavior: 'must'`.
346
+ * These are the defaults that {@link resolveVariantMandatoryAddons} combines
347
+ * with a selected variant's `mandatory-addons` overrides.
348
+ *
349
+ * @param orderSetPd - an order-set PlanDefinition
350
+ * @returns canonicals of the default mandatory add-ons (empty when none)
351
+ */
352
+ function getOrderSetDefaultMandatoryRefs(orderSetPd) {
353
+ var _a, _b, _c;
354
+ return ((_c = (_b = (_a = orderSetPd.action) === null || _a === void 0 ? void 0 : _a.find((a) => a.id === 'addons')) === null || _b === void 0 ? void 0 : _b.action) !== null && _c !== void 0 ? _c : [])
355
+ .filter((addon) => addon.requiredBehavior === 'must' && Boolean(addon.definitionCanonical))
356
+ .map((addon) => addon.definitionCanonical);
357
+ }
342
358
  /**
343
359
  * Resolves the effective mandatory add-on canonicals for a selected variant:
344
360
  * the order-set PD defaults, plus the variant's `'add'` overrides, minus its
@@ -1 +1 @@
1
- {"version":3,"file":"plan-definition-group.js","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Duration, PlanDefinition, PlanDefinitionAction } from '@medplum/fhirtypes'\nimport { EGES_PRACTICA_SYSTEM, PD_HEALTHCARE_SERVICE_EXTENSION_URL, PD_TYPE_PROTOCOL_GROUP, PD_TYPE_SYSTEM, SERVICE_TYPE_SYSTEM } from './constants'\n\n/**\n * `action.id` of the per-variant group that overrides the order-set PD's\n * default mandatory add-ons (the tipo-3 `getMandatoryAddonIds` path). It lives\n * as a direct child of a protocol-group variant action, kept structurally\n * separate from the variant's own add-on sub-actions (the tipo-2\n * `resolveProtocolSelection` path) so the two never conflate. Its group node\n * carries no `definitionCanonical`, so `resolveProtocolSelection`,\n * `getProtocolActions` and friends skip it and never descend into it.\n */\nexport const MANDATORY_ADDON_OVERRIDE_ACTION_ID = 'mandatory-addons'\n\n/**\n * FHIR-standard ActionType code system. Each override sub-action carries a\n * `type.coding` from this system: `create` = add the add-on to the variant's\n * mandatory set, `remove` = drop a PD-default mandatory add-on. `requiredBehavior`\n * is not used for this because FHIR's value set has no \"exclude\" member.\n */\nconst ACTION_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/action-type'\nconst ACTION_TYPE_ADD = 'create'\nconst ACTION_TYPE_REMOVE = 'remove'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * How a variant alters one order-set default mandatory add-on:\n * - `'add'` forces the add-on mandatory for this variant even if the order-set\n * PD marks it optional (or does not list it as mandatory).\n * - `'remove'` drops an add-on that the order-set PD marks mandatory by default.\n */\nexport type MandatoryAddonOverrideAction = 'add' | 'remove'\n\n/**\n * A single per-variant override of the order-set's default mandatory add-on set\n * (the tipo-3 path). Referenced by the add-on's `ActivityDefinition` canonical\n * (`${EGES_PRACTICA_SYSTEM}/{pra_id}`) — the same canonical the order-set PD\n * uses — so add/remove resolve by exact canonical match against the defaults.\n */\nexport interface MandatoryAddonOverride {\n /** Add-on `ActivityDefinition` canonical, e.g. `${EGES_PRACTICA_SYSTEM}/{pra_id}`. */\n readonly ref: string\n /** Whether the variant adds or removes this add-on relative to the PD default. */\n readonly action: MandatoryAddonOverrideAction\n /** Optional human label, for the admin editor. */\n readonly display?: string\n}\n\n/** Information about a single action inside a protocol-group PD. */\nexport interface ProtocolActionInfo {\n readonly actionId: string\n readonly isDefault: boolean\n /** Short label for the variant (e.g. \"Helicoidal\") */\n readonly label: string\n /** User-facing question to select this variant */\n readonly question: string\n readonly protocolRef: string\n readonly protocolDisplay: string\n readonly protocolCode: string\n /**\n * EGES pra_id of the referenced práctica, when stamped on the action's\n * `code[]` (an `EGES_PRACTICA_SYSTEM` coding alongside the service-type\n * coding). Persisted by {@link buildProtocolGroup} so admin UIs can show\n * the id without re-reading each order-set PD.\n */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Whether this action is pre-selected in a **configured** protocol-group.\n * Set by {@link configureProtocolGroup} via FHIR `precheckBehavior`.\n * `undefined` means the PD has not been configured (use `isDefault` as fallback).\n */\n readonly prechecked?: boolean\n /**\n * Only meaningful on addon (sub-action) entries. When `true`, the addon is\n * always included whenever its parent action is selected — it is not shown\n * as a togglable option in the consumer UI. Encoded in FHIR as\n * `PlanDefinitionAction.requiredBehavior === 'must'`.\n */\n readonly mandatory?: boolean\n /** Optional sub-actions (addons) with `any` selection behavior. */\n readonly addons: readonly ProtocolActionInfo[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Empty when the variant inherits the PD defaults unchanged.\n * Only meaningful on top-level variant entries.\n */\n readonly mandatoryAddonOverrides: readonly MandatoryAddonOverride[]\n}\n\n/** Entry used to build a protocol-group PD action. */\nexport interface ProtocolGroupActionEntry {\n readonly id: string\n readonly isDefault: boolean\n readonly label: string\n readonly question: string\n readonly ref: string\n readonly display: string\n readonly code: string\n /** EGES pra_id of the referenced práctica, stamped on the action's `code[]`. */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with the parent action and is hidden from the consumer UI.\n */\n readonly mandatory?: boolean\n /** Optional sub-action entries (addons). */\n readonly addons?: readonly ProtocolGroupActionEntry[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Only meaningful on top-level variant entries; ignored on\n * addon entries.\n */\n readonly mandatoryAddonOverrides?: readonly MandatoryAddonOverride[]\n}\n\n// ─── Backward-compat aliases ────────────────────────────────────────────────\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport type ProtocolVariantInfo = ProtocolActionInfo\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport interface ProtocolDefaultInfo {\n readonly ref: string\n readonly display: string\n readonly code: string\n readonly duration?: Duration\n}\n\n// ─── Detection ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the PlanDefinition is a protocol-group (wrapping multiple concrete PDs).\n *\n * @param pd - the PlanDefinition to check\n * @returns whether the PlanDefinition is a protocol-group\n */\nexport function isProtocolGroup (pd: PlanDefinition): boolean {\n return (pd.type?.coding ?? []).some(\n (c) => c.system === PD_TYPE_SYSTEM && c.code === PD_TYPE_PROTOCOL_GROUP\n )\n}\n\n// ─── Extraction ──────────────────────────────────────────────────────────────\n\n/**\n * Extracts all protocol actions from a protocol-group PD (preserving order).\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of action info objects (the one with `isDefault === true` is the default)\n */\nexport function getProtocolActions (pd: PlanDefinition): ProtocolActionInfo[] {\n return (pd.action ?? [])\n .filter((a): a is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(a.definitionCanonical)\n )\n .map((a) => extractActionInfo(a, a.id === 'default'))\n}\n\n/**\n * Extracts the default protocol action from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns the default protocol info, or undefined if not found\n */\nexport function getDefaultProtocol (pd: PlanDefinition): ProtocolDefaultInfo | undefined {\n const action = (pd.action ?? []).find((a) => a.id === 'default')\n if (!action?.definitionCanonical) { return undefined }\n return {\n ref: action.definitionCanonical,\n display: action.title ?? '',\n code: getActionServiceCode(action),\n duration: action.timingDuration\n }\n}\n\n/**\n * Extracts the non-default variant actions from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of variant info objects\n */\nexport function getProtocolVariants (pd: PlanDefinition): ProtocolActionInfo[] {\n return getProtocolActions(pd).filter((a) => !a.isDefault)\n}\n\n/**\n * Extracts the HealthcareService reference linked to a protocol-group PD.\n *\n * @param pd - the PlanDefinition to inspect\n * @returns the referenced HealthcareService, if present\n */\nexport function getProtocolGroupHealthcareServiceReference (pd: PlanDefinition): string | undefined {\n return pd.extension?.find((e) => e.url === PD_HEALTHCARE_SERVICE_EXTENSION_URL)?.valueReference?.reference\n}\n\n// ─── Construction ────────────────────────────────────────────────────────────\n\n/**\n * Builds a protocol-group PlanDefinition resource.\n *\n * @param title - human-readable title for the group (e.g. \"TAC de hombro — Protocolos\")\n * @param entries - protocol action entries (at least one should have `isDefault: true`)\n * @param existingId - optional ID to reuse when updating an existing group PD\n * @param hsReference - optional HealthcareService reference stored on the group PD\n * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string,\n hsReference?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n addon.id,\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label,\n addon.mandatory,\n addon.praId\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : e.id,\n e.display,\n e.ref,\n e.code,\n e.duration,\n e.question,\n e.label,\n undefined,\n e.praId\n )\n\n // Top-level actions use exactly-one selection behavior\n action.selectionBehavior = 'exactly-one'\n\n const overrideGroup = buildMandatoryAddonOverrideGroup(e.mandatoryAddonOverrides)\n const childActions = overrideGroup ? [...subActions, overrideGroup] : subActions\n\n if (childActions.length > 0) {\n action.action = childActions\n // When an action has sub-actions (addons), they use `any` grouping\n action.groupingBehavior = 'logical-group'\n }\n\n return action\n })\n\n const pd: PlanDefinition = {\n resourceType: 'PlanDefinition',\n status: 'active',\n title,\n type: {\n coding: [{ system: PD_TYPE_SYSTEM, code: PD_TYPE_PROTOCOL_GROUP }]\n },\n action: actions\n }\n\n if (hsReference) {\n pd.extension = [\n {\n url: PD_HEALTHCARE_SERVICE_EXTENSION_URL,\n valueReference: { reference: hsReference }\n }\n ]\n }\n\n if (existingId) {\n pd.id = existingId\n }\n\n return pd\n}\n\n// ─── Selection / Configuration ──────────────────────────────────────────────\n\n/**\n * A user's selection within a protocol-group PlanDefinition.\n *\n * Represents the patient's choices when configuring a HealthcareService:\n * one main action (from the `exactly-one` selection) plus zero or more\n * addon sub-actions.\n */\nexport interface ProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds: readonly string[]\n}\n\n/** Resolved booking parameters for a single protocol action. */\nexport interface ResolvedProtocolAction {\n /** The `definitionCanonical` reference to the order-set PlanDefinition. */\n readonly protocolRef: string\n /** The service-type code for slot searching / billing. */\n readonly serviceType: string\n /** Estimated duration for this action. */\n readonly duration?: Duration\n}\n\n/** Fully resolved booking parameters produced by {@link resolveProtocolSelection}. */\nexport interface ResolvedProtocol {\n /** Resolved main action. */\n readonly main: ResolvedProtocolAction\n /** Resolved addon actions (empty when none selected). */\n readonly addons: readonly ResolvedProtocolAction[]\n}\n\n/**\n * Returns a **configured** copy of a protocol-group PlanDefinition by stamping\n * `precheckBehavior` on every action according to the given selection.\n *\n * - The selected top-level action gets `precheckBehavior: \"yes\"`, all others `\"no\"`.\n * - Within the selected action, each addon sub-action is stamped according to\n * whether its id appears in `selection.addonIds`. **Mandatory addons**\n * (`requiredBehavior === 'must'`) are always stamped `\"yes\"` regardless of\n * the caller-provided ids.\n * - Unselected top-level actions have all their sub-actions stamped as `\"no\"`.\n *\n * The returned PD is a shallow copy — the original is never mutated.\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns a new PlanDefinition with `precheckBehavior` set on every action\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function configureProtocolGroup (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): PlanDefinition {\n const actions = pd.action ?? []\n const found = actions.some((a) => a.id === selection.actionId)\n if (!found) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n\n return {\n ...pd,\n action: actions.map((a) => {\n const isSelected = a.id === selection.actionId\n const subActions = (a.action ?? []).map((sub) => {\n // The mandatory-addons override group is server-side configuration,\n // not a selectable addon — never stamp it as prechecked, even if a\n // (buggy) caller passes its id among the addonIds.\n const isOverrideGroup = sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID\n const isMandatory = sub.requiredBehavior === 'must'\n const isOn = isSelected && !isOverrideGroup && (isMandatory || addonSet.has(sub.id ?? ''))\n return {\n ...sub,\n precheckBehavior: isOn ? 'yes' as const : 'no' as const\n }\n })\n\n return {\n ...a,\n precheckBehavior: isSelected ? 'yes' as const : 'no' as const,\n ...(a.action ? { action: subActions } : {})\n }\n })\n }\n}\n\n/**\n * Resolves a protocol-group PlanDefinition + selection into concrete booking\n * parameters (service-type codes, definitionCanonical references, durations).\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns the resolved main + addon protocol references and codes\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function resolveProtocolSelection (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): ResolvedProtocol {\n const actions = pd.action ?? []\n const selected = actions.find((a) => a.id === selection.actionId)\n if (!selected?.definitionCanonical) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n const resolvedAddons: ResolvedProtocolAction[] = (selected.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string; id: string } => {\n if (!sub.id || !sub.definitionCanonical) { return false }\n const isMandatory = sub.requiredBehavior === 'must'\n return isMandatory || addonSet.has(sub.id)\n })\n .map((sub) => ({\n protocolRef: sub.definitionCanonical,\n serviceType: getActionServiceCode(sub),\n duration: sub.timingDuration\n }))\n\n return {\n main: {\n protocolRef: selected.definitionCanonical,\n serviceType: getActionServiceCode(selected),\n duration: selected.timingDuration\n },\n addons: resolvedAddons\n }\n}\n\n/**\n * Reads the current selection from a **configured** protocol-group PlanDefinition\n * (one whose actions have been stamped with `precheckBehavior` via\n * {@link configureProtocolGroup}).\n *\n * Falls back to `id === \"default\"` with mandatory addons of that default\n * action when no action has `precheckBehavior: \"yes\"`.\n *\n * @param pd - a (possibly configured) protocol-group PlanDefinition\n * @returns the selection encoded in the PD, or the default selection\n */\nexport function readProtocolSelection (pd: PlanDefinition): ProtocolSelection {\n const actions = pd.action ?? []\n\n // Look for an action explicitly marked as prechecked\n const prechecked = actions.find((a) => a.precheckBehavior === 'yes')\n if (prechecked?.id) {\n const addonIds = (prechecked.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } => {\n if (!sub.id || sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID) { return false }\n if (sub.requiredBehavior === 'must') { return true }\n return sub.precheckBehavior === 'yes'\n })\n .map((sub) => sub.id)\n return { actionId: prechecked.id, addonIds }\n }\n\n // Fallback: default action with its mandatory addons (if any)\n const defaultAction = actions.find((a) => a.id === 'default') ?? actions[0]\n const mandatoryAddonIds = (defaultAction?.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } =>\n Boolean(sub.id) && sub.requiredBehavior === 'must'\n )\n .map((sub) => sub.id)\n return { actionId: defaultAction?.id ?? '', addonIds: mandatoryAddonIds }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────────────────\n\nfunction getActionServiceCode (action: PlanDefinitionAction): string {\n const coding = (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === SERVICE_TYPE_SYSTEM)\n return coding?.code ?? ''\n}\n\nfunction getActionPraId (action: PlanDefinitionAction): string | undefined {\n return (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === EGES_PRACTICA_SYSTEM)?.code\n}\n\nfunction precheckToBool (value: string | undefined): boolean | undefined {\n if (value === 'yes') { return true }\n if (value === 'no') { return false }\n return undefined\n}\n\nfunction extractActionInfo (a: PlanDefinitionAction & { definitionCanonical: string }, isDefault: boolean): ProtocolActionInfo {\n const subActions = (a.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(sub.definitionCanonical) && sub.id !== MANDATORY_ADDON_OVERRIDE_ACTION_ID\n )\n .map((sub) => extractActionInfo(sub, false))\n\n return {\n actionId: a.id ?? '',\n isDefault,\n label: a.textEquivalent ?? a.title ?? '',\n question: a.description ?? '',\n protocolRef: a.definitionCanonical,\n protocolDisplay: a.title ?? '',\n protocolCode: getActionServiceCode(a),\n praId: getActionPraId(a),\n duration: a.timingDuration,\n prechecked: precheckToBool(a.precheckBehavior),\n mandatory: a.requiredBehavior === 'must' ? true : undefined,\n addons: subActions,\n mandatoryAddonOverrides: readMandatoryAddonOverrides(a)\n }\n}\n\n/**\n * Reads the per-variant mandatory-addon overrides out of a variant action's\n * `mandatory-addons` group. Returns `[]` when the variant declares none.\n *\n * @param variantAction - a protocol-group top-level variant action\n * @returns the variant's mandatory-addon overrides (empty when none)\n */\nexport function readMandatoryAddonOverrides (\n variantAction: PlanDefinitionAction\n): MandatoryAddonOverride[] {\n const group = (variantAction.action ?? []).find((sub) => sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID)\n const result: MandatoryAddonOverride[] = []\n for (const sub of group?.action ?? []) {\n if (!sub.definitionCanonical) { continue }\n const action = overrideActionFromActionType(sub)\n if (!action) { continue }\n result.push(\n sub.title !== undefined\n ? { ref: sub.definitionCanonical, action, display: sub.title }\n : { ref: sub.definitionCanonical, action }\n )\n }\n return result\n}\n\n/**\n * Resolves the effective mandatory add-on canonicals for a selected variant:\n * the order-set PD defaults, plus the variant's `'add'` overrides, minus its\n * `'remove'` overrides. Order-set defaults and overrides are matched by exact\n * canonical string. Deduplicated; input order of the defaults is preserved,\n * with any added canonicals appended.\n *\n * @param defaultRefs - canonicals of the order-set PD's default mandatory add-ons\n * @param variantAction - the selected protocol-group variant action, or undefined\n * @returns the resolved set of mandatory add-on canonicals\n */\nexport function resolveVariantMandatoryAddons (\n defaultRefs: readonly string[],\n variantAction: PlanDefinitionAction | undefined\n): string[] {\n const resolved = new Set(defaultRefs)\n if (variantAction) {\n for (const override of readMandatoryAddonOverrides(variantAction)) {\n if (override.action === 'add') {\n resolved.add(override.ref)\n } else {\n resolved.delete(override.ref)\n }\n }\n }\n return Array.from(resolved)\n}\n\n/**\n * Maps an override sub-action's `type.coding` (ActionType) back to add/remove.\n *\n * @param sub - an override group sub-action\n * @returns `'add'` for `create`, `'remove'` for `remove`, else undefined\n */\nfunction overrideActionFromActionType (\n sub: PlanDefinitionAction\n): MandatoryAddonOverrideAction | undefined {\n const code = (sub.type?.coding ?? []).find((c) => c.system === ACTION_TYPE_SYSTEM)?.code\n if (code === ACTION_TYPE_ADD) { return 'add' }\n if (code === ACTION_TYPE_REMOVE) { return 'remove' }\n return undefined\n}\n\n/**\n * Builds the `mandatory-addons` override group child for a variant, or returns\n * `undefined` when the variant declares no overrides. Each override becomes a\n * sub-action referencing the add-on's canonical, with `requiredBehavior`\n * `'must'` (add) or `'prohibited'` (remove).\n *\n * @param overrides - the variant's mandatory-addon overrides (may be undefined)\n * @returns the override group action, or undefined when there are no overrides\n */\nfunction buildMandatoryAddonOverrideGroup (\n overrides: readonly MandatoryAddonOverride[] | undefined\n): PlanDefinitionAction | undefined {\n if (!overrides || overrides.length === 0) {\n return undefined\n }\n return {\n id: MANDATORY_ADDON_OVERRIDE_ACTION_ID,\n title: 'Adicionales obligatorios (override por variante)',\n selectionBehavior: 'any',\n action: overrides.map((o) => {\n const sub: PlanDefinitionAction = {\n definitionCanonical: o.ref,\n type: {\n coding: [{ system: ACTION_TYPE_SYSTEM, code: o.action === 'add' ? ACTION_TYPE_ADD : ACTION_TYPE_REMOVE }]\n }\n }\n if (o.display) {\n sub.title = o.display\n }\n return sub\n })\n }\n}\n\nfunction buildAction (\n id: string,\n title: string,\n ref: string,\n code: string,\n duration?: Duration,\n question?: string,\n labelOverride?: string,\n mandatory?: boolean,\n praId?: string\n): PlanDefinitionAction {\n const action: PlanDefinitionAction = {\n id,\n title,\n definitionCanonical: ref\n }\n if (code || praId) {\n action.code = [{\n coding: [\n ...(code ? [{ system: SERVICE_TYPE_SYSTEM, code }] : []),\n ...(praId ? [{ system: EGES_PRACTICA_SYSTEM, code: praId }] : [])\n ]\n }]\n }\n if (duration) {\n action.timingDuration = duration\n }\n if (question) {\n action.description = question\n }\n if (labelOverride) {\n action.textEquivalent = labelOverride\n }\n if (mandatory) {\n action.requiredBehavior = 'must'\n }\n return action\n}\n"]}
1
+ {"version":3,"file":"plan-definition-group.js","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Duration, PlanDefinition, PlanDefinitionAction } from '@medplum/fhirtypes'\nimport { EGES_PRACTICA_SYSTEM, PD_HEALTHCARE_SERVICE_EXTENSION_URL, PD_TYPE_PROTOCOL_GROUP, PD_TYPE_SYSTEM, SERVICE_TYPE_SYSTEM } from './constants'\n\n/**\n * `action.id` of the per-variant group that overrides the order-set PD's\n * default mandatory add-ons (the tipo-3 `getMandatoryAddonIds` path). It lives\n * as a direct child of a protocol-group variant action, kept structurally\n * separate from the variant's own add-on sub-actions (the tipo-2\n * `resolveProtocolSelection` path) so the two never conflate. Its group node\n * carries no `definitionCanonical`, so `resolveProtocolSelection`,\n * `getProtocolActions` and friends skip it and never descend into it.\n */\nexport const MANDATORY_ADDON_OVERRIDE_ACTION_ID = 'mandatory-addons'\n\n/**\n * FHIR-standard ActionType code system. Each override sub-action carries a\n * `type.coding` from this system: `create` = add the add-on to the variant's\n * mandatory set, `remove` = drop a PD-default mandatory add-on. `requiredBehavior`\n * is not used for this because FHIR's value set has no \"exclude\" member.\n */\nconst ACTION_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/action-type'\nconst ACTION_TYPE_ADD = 'create'\nconst ACTION_TYPE_REMOVE = 'remove'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * How a variant alters one order-set default mandatory add-on:\n * - `'add'` forces the add-on mandatory for this variant even if the order-set\n * PD marks it optional (or does not list it as mandatory).\n * - `'remove'` drops an add-on that the order-set PD marks mandatory by default.\n */\nexport type MandatoryAddonOverrideAction = 'add' | 'remove'\n\n/**\n * A single per-variant override of the order-set's default mandatory add-on set\n * (the tipo-3 path). Referenced by the add-on's `ActivityDefinition` canonical\n * (`${EGES_PRACTICA_SYSTEM}/{pra_id}`) — the same canonical the order-set PD\n * uses — so add/remove resolve by exact canonical match against the defaults.\n */\nexport interface MandatoryAddonOverride {\n /** Add-on `ActivityDefinition` canonical, e.g. `${EGES_PRACTICA_SYSTEM}/{pra_id}`. */\n readonly ref: string\n /** Whether the variant adds or removes this add-on relative to the PD default. */\n readonly action: MandatoryAddonOverrideAction\n /** Optional human label, for the admin editor. */\n readonly display?: string\n}\n\n/** Information about a single action inside a protocol-group PD. */\nexport interface ProtocolActionInfo {\n readonly actionId: string\n readonly isDefault: boolean\n /** Short label for the variant (e.g. \"Helicoidal\") */\n readonly label: string\n /** User-facing question to select this variant */\n readonly question: string\n readonly protocolRef: string\n readonly protocolDisplay: string\n readonly protocolCode: string\n /**\n * EGES pra_id of the referenced práctica, when stamped on the action's\n * `code[]` (an `EGES_PRACTICA_SYSTEM` coding alongside the service-type\n * coding). Persisted by {@link buildProtocolGroup} so admin UIs can show\n * the id without re-reading each order-set PD.\n */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Whether this action is pre-selected in a **configured** protocol-group.\n * Set by {@link configureProtocolGroup} via FHIR `precheckBehavior`.\n * `undefined` means the PD has not been configured (use `isDefault` as fallback).\n */\n readonly prechecked?: boolean\n /**\n * Only meaningful on addon (sub-action) entries. When `true`, the addon is\n * always included whenever its parent action is selected — it is not shown\n * as a togglable option in the consumer UI. Encoded in FHIR as\n * `PlanDefinitionAction.requiredBehavior === 'must'`.\n */\n readonly mandatory?: boolean\n /** Optional sub-actions (addons) with `any` selection behavior. */\n readonly addons: readonly ProtocolActionInfo[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Empty when the variant inherits the PD defaults unchanged.\n * Only meaningful on top-level variant entries.\n */\n readonly mandatoryAddonOverrides: readonly MandatoryAddonOverride[]\n}\n\n/** Entry used to build a protocol-group PD action. */\nexport interface ProtocolGroupActionEntry {\n readonly id: string\n readonly isDefault: boolean\n readonly label: string\n readonly question: string\n readonly ref: string\n readonly display: string\n readonly code: string\n /** EGES pra_id of the referenced práctica, stamped on the action's `code[]`. */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with the parent action and is hidden from the consumer UI.\n */\n readonly mandatory?: boolean\n /** Optional sub-action entries (addons). */\n readonly addons?: readonly ProtocolGroupActionEntry[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Only meaningful on top-level variant entries; ignored on\n * addon entries.\n */\n readonly mandatoryAddonOverrides?: readonly MandatoryAddonOverride[]\n}\n\n// ─── Backward-compat aliases ────────────────────────────────────────────────\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport type ProtocolVariantInfo = ProtocolActionInfo\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport interface ProtocolDefaultInfo {\n readonly ref: string\n readonly display: string\n readonly code: string\n readonly duration?: Duration\n}\n\n// ─── Detection ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the PlanDefinition is a protocol-group (wrapping multiple concrete PDs).\n *\n * @param pd - the PlanDefinition to check\n * @returns whether the PlanDefinition is a protocol-group\n */\nexport function isProtocolGroup (pd: PlanDefinition): boolean {\n return (pd.type?.coding ?? []).some(\n (c) => c.system === PD_TYPE_SYSTEM && c.code === PD_TYPE_PROTOCOL_GROUP\n )\n}\n\n// ─── Extraction ──────────────────────────────────────────────────────────────\n\n/**\n * Extracts all protocol actions from a protocol-group PD (preserving order).\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of action info objects (the one with `isDefault === true` is the default)\n */\nexport function getProtocolActions (pd: PlanDefinition): ProtocolActionInfo[] {\n return (pd.action ?? [])\n .filter((a): a is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(a.definitionCanonical)\n )\n .map((a) => extractActionInfo(a, a.id === 'default'))\n}\n\n/**\n * Extracts the default protocol action from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns the default protocol info, or undefined if not found\n */\nexport function getDefaultProtocol (pd: PlanDefinition): ProtocolDefaultInfo | undefined {\n const action = (pd.action ?? []).find((a) => a.id === 'default')\n if (!action?.definitionCanonical) { return undefined }\n return {\n ref: action.definitionCanonical,\n display: action.title ?? '',\n code: getActionServiceCode(action),\n duration: action.timingDuration\n }\n}\n\n/**\n * Extracts the non-default variant actions from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of variant info objects\n */\nexport function getProtocolVariants (pd: PlanDefinition): ProtocolActionInfo[] {\n return getProtocolActions(pd).filter((a) => !a.isDefault)\n}\n\n/**\n * Extracts the HealthcareService reference linked to a protocol-group PD.\n *\n * @param pd - the PlanDefinition to inspect\n * @returns the referenced HealthcareService, if present\n */\nexport function getProtocolGroupHealthcareServiceReference (pd: PlanDefinition): string | undefined {\n return pd.extension?.find((e) => e.url === PD_HEALTHCARE_SERVICE_EXTENSION_URL)?.valueReference?.reference\n}\n\n// ─── Construction ────────────────────────────────────────────────────────────\n\n/**\n * Builds a protocol-group PlanDefinition resource.\n *\n * @param title - human-readable title for the group (e.g. \"TAC de hombro — Protocolos\")\n * @param entries - protocol action entries (at least one should have `isDefault: true`)\n * @param existingId - optional ID to reuse when updating an existing group PD\n * @param hsReference - optional HealthcareService reference stored on the group PD\n * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string,\n hsReference?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n addon.id,\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label,\n addon.mandatory,\n addon.praId\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : e.id,\n e.display,\n e.ref,\n e.code,\n e.duration,\n e.question,\n e.label,\n undefined,\n e.praId\n )\n\n // Top-level actions use exactly-one selection behavior\n action.selectionBehavior = 'exactly-one'\n\n const overrideGroup = buildMandatoryAddonOverrideGroup(e.mandatoryAddonOverrides)\n const childActions = overrideGroup ? [...subActions, overrideGroup] : subActions\n\n if (childActions.length > 0) {\n action.action = childActions\n // When an action has sub-actions (addons), they use `any` grouping\n action.groupingBehavior = 'logical-group'\n }\n\n return action\n })\n\n const pd: PlanDefinition = {\n resourceType: 'PlanDefinition',\n status: 'active',\n title,\n type: {\n coding: [{ system: PD_TYPE_SYSTEM, code: PD_TYPE_PROTOCOL_GROUP }]\n },\n action: actions\n }\n\n if (hsReference) {\n pd.extension = [\n {\n url: PD_HEALTHCARE_SERVICE_EXTENSION_URL,\n valueReference: { reference: hsReference }\n }\n ]\n }\n\n if (existingId) {\n pd.id = existingId\n }\n\n return pd\n}\n\n// ─── Selection / Configuration ──────────────────────────────────────────────\n\n/**\n * A user's selection within a protocol-group PlanDefinition.\n *\n * Represents the patient's choices when configuring a HealthcareService:\n * one main action (from the `exactly-one` selection) plus zero or more\n * addon sub-actions.\n */\nexport interface ProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds: readonly string[]\n}\n\n/** Resolved booking parameters for a single protocol action. */\nexport interface ResolvedProtocolAction {\n /** The `definitionCanonical` reference to the order-set PlanDefinition. */\n readonly protocolRef: string\n /** The service-type code for slot searching / billing. */\n readonly serviceType: string\n /** Estimated duration for this action. */\n readonly duration?: Duration\n}\n\n/** Fully resolved booking parameters produced by {@link resolveProtocolSelection}. */\nexport interface ResolvedProtocol {\n /** Resolved main action. */\n readonly main: ResolvedProtocolAction\n /** Resolved addon actions (empty when none selected). */\n readonly addons: readonly ResolvedProtocolAction[]\n}\n\n/**\n * Returns a **configured** copy of a protocol-group PlanDefinition by stamping\n * `precheckBehavior` on every action according to the given selection.\n *\n * - The selected top-level action gets `precheckBehavior: \"yes\"`, all others `\"no\"`.\n * - Within the selected action, each addon sub-action is stamped according to\n * whether its id appears in `selection.addonIds`. **Mandatory addons**\n * (`requiredBehavior === 'must'`) are always stamped `\"yes\"` regardless of\n * the caller-provided ids.\n * - Unselected top-level actions have all their sub-actions stamped as `\"no\"`.\n *\n * The returned PD is a shallow copy — the original is never mutated.\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns a new PlanDefinition with `precheckBehavior` set on every action\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function configureProtocolGroup (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): PlanDefinition {\n const actions = pd.action ?? []\n const found = actions.some((a) => a.id === selection.actionId)\n if (!found) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n\n return {\n ...pd,\n action: actions.map((a) => {\n const isSelected = a.id === selection.actionId\n const subActions = (a.action ?? []).map((sub) => {\n // The mandatory-addons override group is server-side configuration,\n // not a selectable addon — never stamp it as prechecked, even if a\n // (buggy) caller passes its id among the addonIds.\n const isOverrideGroup = sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID\n const isMandatory = sub.requiredBehavior === 'must'\n const isOn = isSelected && !isOverrideGroup && (isMandatory || addonSet.has(sub.id ?? ''))\n return {\n ...sub,\n precheckBehavior: isOn ? 'yes' as const : 'no' as const\n }\n })\n\n return {\n ...a,\n precheckBehavior: isSelected ? 'yes' as const : 'no' as const,\n ...(a.action ? { action: subActions } : {})\n }\n })\n }\n}\n\n/**\n * Resolves a protocol-group PlanDefinition + selection into concrete booking\n * parameters (service-type codes, definitionCanonical references, durations).\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns the resolved main + addon protocol references and codes\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function resolveProtocolSelection (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): ResolvedProtocol {\n const actions = pd.action ?? []\n const selected = actions.find((a) => a.id === selection.actionId)\n if (!selected?.definitionCanonical) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n const resolvedAddons: ResolvedProtocolAction[] = (selected.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string; id: string } => {\n if (!sub.id || !sub.definitionCanonical) { return false }\n const isMandatory = sub.requiredBehavior === 'must'\n return isMandatory || addonSet.has(sub.id)\n })\n .map((sub) => ({\n protocolRef: sub.definitionCanonical,\n serviceType: getActionServiceCode(sub),\n duration: sub.timingDuration\n }))\n\n return {\n main: {\n protocolRef: selected.definitionCanonical,\n serviceType: getActionServiceCode(selected),\n duration: selected.timingDuration\n },\n addons: resolvedAddons\n }\n}\n\n/**\n * Reads the current selection from a **configured** protocol-group PlanDefinition\n * (one whose actions have been stamped with `precheckBehavior` via\n * {@link configureProtocolGroup}).\n *\n * Falls back to `id === \"default\"` with mandatory addons of that default\n * action when no action has `precheckBehavior: \"yes\"`.\n *\n * @param pd - a (possibly configured) protocol-group PlanDefinition\n * @returns the selection encoded in the PD, or the default selection\n */\nexport function readProtocolSelection (pd: PlanDefinition): ProtocolSelection {\n const actions = pd.action ?? []\n\n // Look for an action explicitly marked as prechecked\n const prechecked = actions.find((a) => a.precheckBehavior === 'yes')\n if (prechecked?.id) {\n const addonIds = (prechecked.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } => {\n if (!sub.id || sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID) { return false }\n if (sub.requiredBehavior === 'must') { return true }\n return sub.precheckBehavior === 'yes'\n })\n .map((sub) => sub.id)\n return { actionId: prechecked.id, addonIds }\n }\n\n // Fallback: default action with its mandatory addons (if any)\n const defaultAction = actions.find((a) => a.id === 'default') ?? actions[0]\n const mandatoryAddonIds = (defaultAction?.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } =>\n Boolean(sub.id) && sub.requiredBehavior === 'must'\n )\n .map((sub) => sub.id)\n return { actionId: defaultAction?.id ?? '', addonIds: mandatoryAddonIds }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────────────────\n\nfunction getActionServiceCode (action: PlanDefinitionAction): string {\n const coding = (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === SERVICE_TYPE_SYSTEM)\n return coding?.code ?? ''\n}\n\nfunction getActionPraId (action: PlanDefinitionAction): string | undefined {\n return (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === EGES_PRACTICA_SYSTEM)?.code\n}\n\nfunction precheckToBool (value: string | undefined): boolean | undefined {\n if (value === 'yes') { return true }\n if (value === 'no') { return false }\n return undefined\n}\n\nfunction extractActionInfo (a: PlanDefinitionAction & { definitionCanonical: string }, isDefault: boolean): ProtocolActionInfo {\n const subActions = (a.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(sub.definitionCanonical) && sub.id !== MANDATORY_ADDON_OVERRIDE_ACTION_ID\n )\n .map((sub) => extractActionInfo(sub, false))\n\n return {\n actionId: a.id ?? '',\n isDefault,\n label: a.textEquivalent ?? a.title ?? '',\n question: a.description ?? '',\n protocolRef: a.definitionCanonical,\n protocolDisplay: a.title ?? '',\n protocolCode: getActionServiceCode(a),\n praId: getActionPraId(a),\n duration: a.timingDuration,\n prechecked: precheckToBool(a.precheckBehavior),\n mandatory: a.requiredBehavior === 'must' ? true : undefined,\n addons: subActions,\n mandatoryAddonOverrides: readMandatoryAddonOverrides(a)\n }\n}\n\n/**\n * Reads the per-variant mandatory-addon overrides out of a variant action's\n * `mandatory-addons` group. Returns `[]` when the variant declares none.\n *\n * @param variantAction - a protocol-group top-level variant action\n * @returns the variant's mandatory-addon overrides (empty when none)\n */\nexport function readMandatoryAddonOverrides (\n variantAction: PlanDefinitionAction\n): MandatoryAddonOverride[] {\n const group = (variantAction.action ?? []).find((sub) => sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID)\n const result: MandatoryAddonOverride[] = []\n for (const sub of group?.action ?? []) {\n if (!sub.definitionCanonical) { continue }\n const action = overrideActionFromActionType(sub)\n if (!action) { continue }\n result.push(\n sub.title !== undefined\n ? { ref: sub.definitionCanonical, action, display: sub.title }\n : { ref: sub.definitionCanonical, action }\n )\n }\n return result\n}\n\n/**\n * Extracts the canonicals of an order-set PD's **default** mandatory add-ons:\n * the `action[id='addons']` sub-actions flagged `requiredBehavior: 'must'`.\n * These are the defaults that {@link resolveVariantMandatoryAddons} combines\n * with a selected variant's `mandatory-addons` overrides.\n *\n * @param orderSetPd - an order-set PlanDefinition\n * @returns canonicals of the default mandatory add-ons (empty when none)\n */\nexport function getOrderSetDefaultMandatoryRefs (orderSetPd: PlanDefinition): string[] {\n return (orderSetPd.action?.find((a) => a.id === 'addons')?.action ?? [])\n .filter((addon): addon is PlanDefinitionAction & { definitionCanonical: string } =>\n addon.requiredBehavior === 'must' && Boolean(addon.definitionCanonical)\n )\n .map((addon) => addon.definitionCanonical)\n}\n\n/**\n * Resolves the effective mandatory add-on canonicals for a selected variant:\n * the order-set PD defaults, plus the variant's `'add'` overrides, minus its\n * `'remove'` overrides. Order-set defaults and overrides are matched by exact\n * canonical string. Deduplicated; input order of the defaults is preserved,\n * with any added canonicals appended.\n *\n * @param defaultRefs - canonicals of the order-set PD's default mandatory add-ons\n * @param variantAction - the selected protocol-group variant action, or undefined\n * @returns the resolved set of mandatory add-on canonicals\n */\nexport function resolveVariantMandatoryAddons (\n defaultRefs: readonly string[],\n variantAction: PlanDefinitionAction | undefined\n): string[] {\n const resolved = new Set(defaultRefs)\n if (variantAction) {\n for (const override of readMandatoryAddonOverrides(variantAction)) {\n if (override.action === 'add') {\n resolved.add(override.ref)\n } else {\n resolved.delete(override.ref)\n }\n }\n }\n return Array.from(resolved)\n}\n\n/**\n * Maps an override sub-action's `type.coding` (ActionType) back to add/remove.\n *\n * @param sub - an override group sub-action\n * @returns `'add'` for `create`, `'remove'` for `remove`, else undefined\n */\nfunction overrideActionFromActionType (\n sub: PlanDefinitionAction\n): MandatoryAddonOverrideAction | undefined {\n const code = (sub.type?.coding ?? []).find((c) => c.system === ACTION_TYPE_SYSTEM)?.code\n if (code === ACTION_TYPE_ADD) { return 'add' }\n if (code === ACTION_TYPE_REMOVE) { return 'remove' }\n return undefined\n}\n\n/**\n * Builds the `mandatory-addons` override group child for a variant, or returns\n * `undefined` when the variant declares no overrides. Each override becomes a\n * sub-action referencing the add-on's canonical, with `requiredBehavior`\n * `'must'` (add) or `'prohibited'` (remove).\n *\n * @param overrides - the variant's mandatory-addon overrides (may be undefined)\n * @returns the override group action, or undefined when there are no overrides\n */\nfunction buildMandatoryAddonOverrideGroup (\n overrides: readonly MandatoryAddonOverride[] | undefined\n): PlanDefinitionAction | undefined {\n if (!overrides || overrides.length === 0) {\n return undefined\n }\n return {\n id: MANDATORY_ADDON_OVERRIDE_ACTION_ID,\n title: 'Adicionales obligatorios (override por variante)',\n selectionBehavior: 'any',\n action: overrides.map((o) => {\n const sub: PlanDefinitionAction = {\n definitionCanonical: o.ref,\n type: {\n coding: [{ system: ACTION_TYPE_SYSTEM, code: o.action === 'add' ? ACTION_TYPE_ADD : ACTION_TYPE_REMOVE }]\n }\n }\n if (o.display) {\n sub.title = o.display\n }\n return sub\n })\n }\n}\n\nfunction buildAction (\n id: string,\n title: string,\n ref: string,\n code: string,\n duration?: Duration,\n question?: string,\n labelOverride?: string,\n mandatory?: boolean,\n praId?: string\n): PlanDefinitionAction {\n const action: PlanDefinitionAction = {\n id,\n title,\n definitionCanonical: ref\n }\n if (code || praId) {\n action.code = [{\n coding: [\n ...(code ? [{ system: SERVICE_TYPE_SYSTEM, code }] : []),\n ...(praId ? [{ system: EGES_PRACTICA_SYSTEM, code: praId }] : [])\n ]\n }]\n }\n if (duration) {\n action.timingDuration = duration\n }\n if (question) {\n action.description = question\n }\n if (labelOverride) {\n action.textEquivalent = labelOverride\n }\n if (mandatory) {\n action.requiredBehavior = 'must'\n }\n return action\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import type { PlanDefinition, ServiceRequest } from '@medplum/fhirtypes';
2
+ /**
3
+ * Preparation-group building shared by every preparation consumer (the
4
+ * confirmation-email bot today, the appointments portal next): given a
5
+ * session's ServiceRequests plus the order-set and mandatory-component
6
+ * PlanDefinitions resolved for each ({@link classifyResolvedProtocolBundle}
7
+ * output, keyed by ServiceRequest id), produces per-study groups of sanitized
8
+ * preparation blocks with the dedupe/titling rules of #193/#198.
9
+ */
10
+ export interface PreparationBlock {
11
+ display: string;
12
+ htmlContent: string;
13
+ textContent: string;
14
+ }
15
+ /**
16
+ * One study's preparation blocks. `studyName` is omitted when the whole
17
+ * session collapses to a single shared block set (single-study sessions
18
+ * included), so consumers can render it unlabeled.
19
+ */
20
+ export interface PreparationGroup {
21
+ studyName?: string;
22
+ blocks: PreparationBlock[];
23
+ }
24
+ /**
25
+ * Builds the per-study preparation groups for a booking session.
26
+ *
27
+ * @param serviceRequests - The session's ServiceRequests (one per study).
28
+ * @param orderSetPdsBySrId - Bookable order-set PDs (`match` entries), keyed by ServiceRequest id.
29
+ * @param componentPdsBySrId - Mandatory-component PDs (`include` entries, #193), keyed by ServiceRequest id.
30
+ * @returns Per-study groups; a single unlabeled group when every study shares the same block set.
31
+ */
32
+ export declare function buildPreparationGroups(serviceRequests: ServiceRequest[], orderSetPdsBySrId: Map<string, PlanDefinition[]>, componentPdsBySrId: Map<string, PlanDefinition[]>): PreparationGroup[];
33
+ //# sourceMappingURL=preparation-groups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preparation-groups.d.ts","sourceRoot":"","sources":["../src/preparation-groups.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxE;;;;;;;GAOG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAC3B;AAgBD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,cAAc,EAAE,EACjC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,EAChD,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,GAChD,gBAAgB,EAAE,CAsBpB"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildPreparationGroups = buildPreparationGroups;
4
+ const core_1 = require("@medplum/core");
5
+ /**
6
+ * Builds the per-study preparation groups for a booking session.
7
+ *
8
+ * @param serviceRequests - The session's ServiceRequests (one per study).
9
+ * @param orderSetPdsBySrId - Bookable order-set PDs (`match` entries), keyed by ServiceRequest id.
10
+ * @param componentPdsBySrId - Mandatory-component PDs (`include` entries, #193), keyed by ServiceRequest id.
11
+ * @returns Per-study groups; a single unlabeled group when every study shares the same block set.
12
+ */
13
+ function buildPreparationGroups(serviceRequests, orderSetPdsBySrId, componentPdsBySrId) {
14
+ const groups = serviceRequests
15
+ .filter((sr) => Boolean(sr.id))
16
+ .map((sr) => { var _a, _b; return buildStudyGroup(sr, (_a = orderSetPdsBySrId.get(sr.id)) !== null && _a !== void 0 ? _a : [], (_b = componentPdsBySrId.get(sr.id)) !== null && _b !== void 0 ? _b : []); });
17
+ if (groups.length === 0) {
18
+ return [];
19
+ }
20
+ // When every study yields the same block set the instructions are not
21
+ // ambiguous, so a single unlabeled group is rendered (this also preserves
22
+ // the unlabeled single-study layout). Empty groups participate in the
23
+ // comparison: a study without preparations next to one with them must keep
24
+ // the study headings, or the patient cannot tell which study they apply to.
25
+ // Compared as a sorted key set — assembly order depends on the order the
26
+ // PDs come back from $resolve-protocol, which may differ between studies
27
+ // that share the same blocks.
28
+ const serialized = groups.map((g) => JSON.stringify(g.blocks.map((b) => `${b.display}\u0000${b.htmlContent}`).sort()));
29
+ if (serialized.every((s) => s === serialized[0])) {
30
+ return groups[0].blocks.length > 0 ? [{ blocks: groups[0].blocks }] : [];
31
+ }
32
+ return groups.filter((g) => g.blocks.length > 0);
33
+ }
34
+ function buildStudyGroup(sr, orderSetPds, componentPds) {
35
+ var _a, _b, _c, _d, _e, _f;
36
+ const assembling = new Map();
37
+ const collect = (pd, componentName, isModule) => {
38
+ var _a, _b, _c;
39
+ for (const art of (_a = pd.relatedArtifact) !== null && _a !== void 0 ? _a : []) {
40
+ if (art.type !== 'documentation') {
41
+ continue;
42
+ }
43
+ const data = (_b = art.document) === null || _b === void 0 ? void 0 : _b.data;
44
+ if (!data) {
45
+ continue;
46
+ }
47
+ const rawHtml = (0, core_1.decodeBase64)(data);
48
+ const baseDisplay = (_c = art.display) !== null && _c !== void 0 ? _c : 'Indicaciones';
49
+ const key = `${baseDisplay}::${rawHtml}`;
50
+ const existing = assembling.get(key);
51
+ if (existing) {
52
+ if (componentName && !existing.isModule && !existing.componentNames.includes(componentName)) {
53
+ existing.componentNames.push(componentName);
54
+ }
55
+ continue;
56
+ }
57
+ assembling.set(key, {
58
+ baseDisplay,
59
+ componentNames: componentName ? [componentName] : [],
60
+ isModule,
61
+ rawHtml
62
+ });
63
+ }
64
+ };
65
+ for (const pd of orderSetPds) {
66
+ collect(pd, undefined, true);
67
+ }
68
+ for (const pd of componentPds) {
69
+ // A title-less component PD still assembles as a component block (just
70
+ // unprefixed) so a later titled component sharing the same prep can
71
+ // surface its práctica name instead of being silently absorbed.
72
+ collect(pd, ((_a = pd.title) === null || _a === void 0 ? void 0 : _a.trim()) || undefined, false);
73
+ }
74
+ const blocks = Array.from(assembling.values()).map((b) => ({
75
+ display: b.componentNames.length > 0 ? `${b.componentNames.join(', ')} — ${b.baseDisplay}` : b.baseDisplay,
76
+ htmlContent: sanitizeHtmlForEmail(b.rawHtml),
77
+ textContent: htmlToPlainText(b.rawHtml)
78
+ }));
79
+ return {
80
+ studyName: (_c = (_b = sr.code) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : (_f = (_e = (_d = sr.code) === null || _d === void 0 ? void 0 : _d.coding) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.display,
81
+ blocks
82
+ };
83
+ }
84
+ // Dependency-free HTML sanitization for the preparation blocks. The previous
85
+ // `sanitize-html` dependency does not load in the Medplum bot VM runtime, so we
86
+ // inline a tight whitelist instead: preparation HTML is produced by the EGES RTF
87
+ // migrator (`parseRtfToHtml`), which only ever emits this handful of tags and
88
+ // HTML-escapes all text. Sanitizing again here is defense in depth — only these
89
+ // tags survive, every attribute is dropped, and script-like elements are removed
90
+ // together with their content.
91
+ const PREPARATION_ALLOWED_TAGS = new Set(['p', 'strong', 'em', 'br']);
92
+ // Elements whose entire content (not just the wrapper) must be discarded.
93
+ const STRIP_WITH_CONTENT_TAGS = ['script', 'style', 'textarea', 'noscript', 'iframe', 'title'];
94
+ const BASIC_HTML_ENTITIES = {
95
+ '&amp;': '&',
96
+ '&lt;': '<',
97
+ '&gt;': '>',
98
+ '&quot;': '"',
99
+ '&#39;': "'",
100
+ '&apos;': "'",
101
+ '&nbsp;': ' '
102
+ };
103
+ function stripDangerousElements(html) {
104
+ let out = html;
105
+ for (const tag of STRIP_WITH_CONTENT_TAGS) {
106
+ // Paired element with its content, then any unterminated opener.
107
+ out = out.replace(new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?</${tag}\\s*>`, 'gi'), '');
108
+ out = out.replace(new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*$`, 'gi'), '');
109
+ }
110
+ return out.replace(/<!--[\s\S]*?-->/g, '');
111
+ }
112
+ function sanitizeHtmlForEmail(html) {
113
+ return stripDangerousElements(html)
114
+ .replace(/<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*?>/g, (match, rawName) => {
115
+ const name = rawName.toLowerCase();
116
+ if (!PREPARATION_ALLOWED_TAGS.has(name)) {
117
+ return '';
118
+ }
119
+ if (name === 'br') {
120
+ return '<br />';
121
+ }
122
+ return match.startsWith('</') ? `</${name}>` : `<${name}>`;
123
+ })
124
+ .trim();
125
+ }
126
+ function decodeBasicEntities(text) {
127
+ return text.replace(/&(?:amp|lt|gt|quot|apos|nbsp|#39);/g, (match) => { var _a; return (_a = BASIC_HTML_ENTITIES[match]) !== null && _a !== void 0 ? _a : match; });
128
+ }
129
+ function htmlToPlainText(html) {
130
+ const withBreaks = stripDangerousElements(html)
131
+ .replace(/<br\s*\/?>/gi, '\n')
132
+ .replace(/<\/p>\s*<p>/gi, '\n\n')
133
+ .replace(/<\/?p>/gi, '');
134
+ const withoutTags = withBreaks.replace(/<\/?[a-zA-Z][^>]*>/g, '');
135
+ return decodeBasicEntities(withoutTags)
136
+ .replace(/\n{3,}/g, '\n\n')
137
+ .trim();
138
+ }
139
+ //# sourceMappingURL=preparation-groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preparation-groups.js","sourceRoot":"","sources":["../src/preparation-groups.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PlanDefinition, ServiceRequest } from '@medplum/fhirtypes'\nimport { decodeBase64 } from '@medplum/core'\n\n/**\n * Preparation-group building shared by every preparation consumer (the\n * confirmation-email bot today, the appointments portal next): given a\n * session's ServiceRequests plus the order-set and mandatory-component\n * PlanDefinitions resolved for each ({@link classifyResolvedProtocolBundle}\n * output, keyed by ServiceRequest id), produces per-study groups of sanitized\n * preparation blocks with the dedupe/titling rules of #193/#198.\n */\n\nexport interface PreparationBlock {\n display: string\n htmlContent: string\n textContent: string\n}\n\n/**\n * One study's preparation blocks. `studyName` is omitted when the whole\n * session collapses to a single shared block set (single-study sessions\n * included), so consumers can render it unlabeled.\n */\nexport interface PreparationGroup {\n studyName?: string\n blocks: PreparationBlock[]\n}\n\n/**\n * Working shape of a block while a study group is being assembled. Component\n * blocks (from mandatory-component PDs) track the práctica names they came\n * from, so two components sharing an identical prep merge into one block that\n * lists both names; a component prep identical to a module-level one collapses\n * into the module block (which needs no práctica prefix).\n */\ninterface AssemblingBlock {\n baseDisplay: string\n componentNames: string[]\n isModule: boolean\n rawHtml: string\n}\n\n/**\n * Builds the per-study preparation groups for a booking session.\n *\n * @param serviceRequests - The session's ServiceRequests (one per study).\n * @param orderSetPdsBySrId - Bookable order-set PDs (`match` entries), keyed by ServiceRequest id.\n * @param componentPdsBySrId - Mandatory-component PDs (`include` entries, #193), keyed by ServiceRequest id.\n * @returns Per-study groups; a single unlabeled group when every study shares the same block set.\n */\nexport function buildPreparationGroups (\n serviceRequests: ServiceRequest[],\n orderSetPdsBySrId: Map<string, PlanDefinition[]>,\n componentPdsBySrId: Map<string, PlanDefinition[]>\n): PreparationGroup[] {\n const groups = serviceRequests\n .filter((sr): sr is ServiceRequest & { id: string } => Boolean(sr.id))\n .map((sr) => buildStudyGroup(sr, orderSetPdsBySrId.get(sr.id) ?? [], componentPdsBySrId.get(sr.id) ?? []))\n if (groups.length === 0) {\n return []\n }\n // When every study yields the same block set the instructions are not\n // ambiguous, so a single unlabeled group is rendered (this also preserves\n // the unlabeled single-study layout). Empty groups participate in the\n // comparison: a study without preparations next to one with them must keep\n // the study headings, or the patient cannot tell which study they apply to.\n // Compared as a sorted key set — assembly order depends on the order the\n // PDs come back from $resolve-protocol, which may differ between studies\n // that share the same blocks.\n const serialized = groups.map((g) =>\n JSON.stringify(g.blocks.map((b) => `${b.display}\\u0000${b.htmlContent}`).sort())\n )\n if (serialized.every((s) => s === serialized[0])) {\n return groups[0].blocks.length > 0 ? [{ blocks: groups[0].blocks }] : []\n }\n return groups.filter((g) => g.blocks.length > 0)\n}\n\nfunction buildStudyGroup (\n sr: ServiceRequest,\n orderSetPds: PlanDefinition[],\n componentPds: PlanDefinition[]\n): PreparationGroup {\n const assembling = new Map<string, AssemblingBlock>()\n\n const collect = (pd: PlanDefinition, componentName: string | undefined, isModule: boolean): void => {\n for (const art of pd.relatedArtifact ?? []) {\n if (art.type !== 'documentation') { continue }\n const data = art.document?.data\n if (!data) { continue }\n const rawHtml = decodeBase64(data)\n const baseDisplay = art.display ?? 'Indicaciones'\n const key = `${baseDisplay}::${rawHtml}`\n const existing = assembling.get(key)\n if (existing) {\n if (componentName && !existing.isModule && !existing.componentNames.includes(componentName)) {\n existing.componentNames.push(componentName)\n }\n continue\n }\n assembling.set(key, {\n baseDisplay,\n componentNames: componentName ? [componentName] : [],\n isModule,\n rawHtml\n })\n }\n }\n\n for (const pd of orderSetPds) {\n collect(pd, undefined, true)\n }\n for (const pd of componentPds) {\n // A title-less component PD still assembles as a component block (just\n // unprefixed) so a later titled component sharing the same prep can\n // surface its práctica name instead of being silently absorbed.\n collect(pd, pd.title?.trim() || undefined, false)\n }\n\n const blocks: PreparationBlock[] = Array.from(assembling.values()).map((b) => ({\n display: b.componentNames.length > 0 ? `${b.componentNames.join(', ')} — ${b.baseDisplay}` : b.baseDisplay,\n htmlContent: sanitizeHtmlForEmail(b.rawHtml),\n textContent: htmlToPlainText(b.rawHtml)\n }))\n\n return {\n studyName: sr.code?.text ?? sr.code?.coding?.[0]?.display,\n blocks\n }\n}\n\n// Dependency-free HTML sanitization for the preparation blocks. The previous\n// `sanitize-html` dependency does not load in the Medplum bot VM runtime, so we\n// inline a tight whitelist instead: preparation HTML is produced by the EGES RTF\n// migrator (`parseRtfToHtml`), which only ever emits this handful of tags and\n// HTML-escapes all text. Sanitizing again here is defense in depth — only these\n// tags survive, every attribute is dropped, and script-like elements are removed\n// together with their content.\nconst PREPARATION_ALLOWED_TAGS = new Set(['p', 'strong', 'em', 'br'])\n\n// Elements whose entire content (not just the wrapper) must be discarded.\nconst STRIP_WITH_CONTENT_TAGS = ['script', 'style', 'textarea', 'noscript', 'iframe', 'title']\n\nconst BASIC_HTML_ENTITIES: Record<string, string> = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&#39;': \"'\",\n '&apos;': \"'\",\n '&nbsp;': ' '\n}\n\nfunction stripDangerousElements (html: string): string {\n let out = html\n for (const tag of STRIP_WITH_CONTENT_TAGS) {\n // Paired element with its content, then any unterminated opener.\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*>[\\\\s\\\\S]*?</${tag}\\\\s*>`, 'gi'), '')\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*>[\\\\s\\\\S]*$`, 'gi'), '')\n }\n return out.replace(/<!--[\\s\\S]*?-->/g, '')\n}\n\nfunction sanitizeHtmlForEmail (html: string): string {\n return stripDangerousElements(html)\n .replace(/<\\/?([a-zA-Z][a-zA-Z0-9]*)\\b[^>]*?>/g, (match, rawName: string) => {\n const name = rawName.toLowerCase()\n if (!PREPARATION_ALLOWED_TAGS.has(name)) { return '' }\n if (name === 'br') { return '<br />' }\n return match.startsWith('</') ? `</${name}>` : `<${name}>`\n })\n .trim()\n}\n\nfunction decodeBasicEntities (text: string): string {\n return text.replace(/&(?:amp|lt|gt|quot|apos|nbsp|#39);/g, (match) => BASIC_HTML_ENTITIES[match] ?? match)\n}\n\nfunction htmlToPlainText (html: string): string {\n const withBreaks = stripDangerousElements(html)\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/p>\\s*<p>/gi, '\\n\\n')\n .replace(/<\\/?p>/gi, '')\n const withoutTags = withBreaks.replace(/<\\/?[a-zA-Z][^>]*>/g, '')\n return decodeBasicEntities(withoutTags)\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import type { Bundle, PlanDefinition } from '@medplum/fhirtypes';
2
+ /** A `$resolve-protocol` bundle entry with its `search.mode` preserved. */
3
+ export interface ResolvedProtocolEntry {
4
+ pd: PlanDefinition;
5
+ mode?: string;
6
+ }
7
+ export interface ClassifiedResolvedProtocol {
8
+ /** The configured protocol-group PD (absent in single-variant order-set mode, #194). */
9
+ protocolGroup?: PlanDefinition;
10
+ /** Bookable order-set PDs (`search.mode: 'match'`). */
11
+ orderSets: PlanDefinition[];
12
+ /** Mandatory-component PDs (`search.mode: 'include'`, #193) — preparation sources, not bookable. */
13
+ components: PlanDefinition[];
14
+ }
15
+ /**
16
+ * Splits `$resolve-protocol` results by `search.mode`: `match` entries are the
17
+ * bookable order-sets, non-protocol-group `include` entries are the
18
+ * mandatory-component PDs (#193/#194). Entries without a mode are treated as
19
+ * bookable, preserving the legacy classification.
20
+ *
21
+ * @param entries - Bundle entries with their `search.mode` preserved.
22
+ * @returns The configured protocol-group, bookable order-sets, and components.
23
+ */
24
+ export declare function classifyResolvedProtocolEntries(entries: ResolvedProtocolEntry[]): ClassifiedResolvedProtocol;
25
+ /**
26
+ * Convenience over {@link classifyResolvedProtocolEntries} that reads a raw
27
+ * `$resolve-protocol` response Bundle, keeping each entry's `search.mode` and
28
+ * ignoring non-PlanDefinition resources.
29
+ *
30
+ * @param bundle - The `$resolve-protocol` response Bundle.
31
+ * @returns The configured protocol-group, bookable order-sets, and components.
32
+ */
33
+ export declare function classifyResolvedProtocolBundle(bundle: Bundle<PlanDefinition>): ClassifiedResolvedProtocol;
34
+ //# sourceMappingURL=resolved-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-protocol.d.ts","sourceRoot":"","sources":["../src/resolved-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGhE,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,cAAc,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,wFAAwF;IACxF,aAAa,CAAC,EAAE,cAAc,CAAA;IAC9B,uDAAuD;IACvD,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,oGAAoG;IACpG,UAAU,EAAE,cAAc,EAAE,CAAA;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,0BAA0B,CAc7G;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAAE,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,GAAG,0BAA0B,CAQ1G"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classifyResolvedProtocolEntries = classifyResolvedProtocolEntries;
4
+ exports.classifyResolvedProtocolBundle = classifyResolvedProtocolBundle;
5
+ const plan_definition_group_1 = require("./plan-definition-group");
6
+ /**
7
+ * Splits `$resolve-protocol` results by `search.mode`: `match` entries are the
8
+ * bookable order-sets, non-protocol-group `include` entries are the
9
+ * mandatory-component PDs (#193/#194). Entries without a mode are treated as
10
+ * bookable, preserving the legacy classification.
11
+ *
12
+ * @param entries - Bundle entries with their `search.mode` preserved.
13
+ * @returns The configured protocol-group, bookable order-sets, and components.
14
+ */
15
+ function classifyResolvedProtocolEntries(entries) {
16
+ let protocolGroup;
17
+ const orderSets = [];
18
+ const components = [];
19
+ for (const { pd, mode } of entries) {
20
+ if (!protocolGroup && (0, plan_definition_group_1.isProtocolGroup)(pd)) {
21
+ protocolGroup = pd;
22
+ }
23
+ else if (mode === 'include') {
24
+ components.push(pd);
25
+ }
26
+ else {
27
+ orderSets.push(pd);
28
+ }
29
+ }
30
+ return { protocolGroup, orderSets, components };
31
+ }
32
+ /**
33
+ * Convenience over {@link classifyResolvedProtocolEntries} that reads a raw
34
+ * `$resolve-protocol` response Bundle, keeping each entry's `search.mode` and
35
+ * ignoring non-PlanDefinition resources.
36
+ *
37
+ * @param bundle - The `$resolve-protocol` response Bundle.
38
+ * @returns The configured protocol-group, bookable order-sets, and components.
39
+ */
40
+ function classifyResolvedProtocolBundle(bundle) {
41
+ var _a, _b, _c;
42
+ const entries = [];
43
+ for (const entry of (_a = bundle.entry) !== null && _a !== void 0 ? _a : []) {
44
+ if (((_b = entry.resource) === null || _b === void 0 ? void 0 : _b.resourceType) === 'PlanDefinition') {
45
+ entries.push({ pd: entry.resource, mode: (_c = entry.search) === null || _c === void 0 ? void 0 : _c.mode });
46
+ }
47
+ }
48
+ return classifyResolvedProtocolEntries(entries);
49
+ }
50
+ //# sourceMappingURL=resolved-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-protocol.js","sourceRoot":"","sources":["../src/resolved-protocol.ts"],"names":[],"mappings":";;AA2BA,0EAcC;AAUD,wEAQC;AA1DD,mEAAyD;AAiBzD;;;;;;;;GAQG;AACH,SAAgB,+BAA+B,CAAE,OAAgC;IAC/E,IAAI,aAAyC,CAAA;IAC7C,MAAM,SAAS,GAAqB,EAAE,CAAA;IACtC,MAAM,UAAU,GAAqB,EAAE,CAAA;IACvC,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,IAAI,IAAA,uCAAe,EAAC,EAAE,CAAC,EAAE,CAAC;YAC1C,aAAa,GAAG,EAAE,CAAA;QACpB,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,8BAA8B,CAAE,MAA8B;;IAC5E,MAAM,OAAO,GAA4B,EAAE,CAAA;IAC3C,KAAK,MAAM,KAAK,IAAI,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,YAAY,MAAK,gBAAgB,EAAE,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAA,KAAK,CAAC,MAAM,0CAAE,IAAI,EAAE,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;IACD,OAAO,+BAA+B,CAAC,OAAO,CAAC,CAAA;AACjD,CAAC","sourcesContent":["import type { Bundle, PlanDefinition } from '@medplum/fhirtypes'\nimport { isProtocolGroup } from './plan-definition-group'\n\n/** A `$resolve-protocol` bundle entry with its `search.mode` preserved. */\nexport interface ResolvedProtocolEntry {\n pd: PlanDefinition\n mode?: string\n}\n\nexport interface ClassifiedResolvedProtocol {\n /** The configured protocol-group PD (absent in single-variant order-set mode, #194). */\n protocolGroup?: PlanDefinition\n /** Bookable order-set PDs (`search.mode: 'match'`). */\n orderSets: PlanDefinition[]\n /** Mandatory-component PDs (`search.mode: 'include'`, #193) — preparation sources, not bookable. */\n components: PlanDefinition[]\n}\n\n/**\n * Splits `$resolve-protocol` results by `search.mode`: `match` entries are the\n * bookable order-sets, non-protocol-group `include` entries are the\n * mandatory-component PDs (#193/#194). Entries without a mode are treated as\n * bookable, preserving the legacy classification.\n *\n * @param entries - Bundle entries with their `search.mode` preserved.\n * @returns The configured protocol-group, bookable order-sets, and components.\n */\nexport function classifyResolvedProtocolEntries (entries: ResolvedProtocolEntry[]): ClassifiedResolvedProtocol {\n let protocolGroup: PlanDefinition | undefined\n const orderSets: PlanDefinition[] = []\n const components: PlanDefinition[] = []\n for (const { pd, mode } of entries) {\n if (!protocolGroup && isProtocolGroup(pd)) {\n protocolGroup = pd\n } else if (mode === 'include') {\n components.push(pd)\n } else {\n orderSets.push(pd)\n }\n }\n return { protocolGroup, orderSets, components }\n}\n\n/**\n * Convenience over {@link classifyResolvedProtocolEntries} that reads a raw\n * `$resolve-protocol` response Bundle, keeping each entry's `search.mode` and\n * ignoring non-PlanDefinition resources.\n *\n * @param bundle - The `$resolve-protocol` response Bundle.\n * @returns The configured protocol-group, bookable order-sets, and components.\n */\nexport function classifyResolvedProtocolBundle (bundle: Bundle<PlanDefinition>): ClassifiedResolvedProtocol {\n const entries: ResolvedProtocolEntry[] = []\n for (const entry of bundle.entry ?? []) {\n if (entry.resource?.resourceType === 'PlanDefinition') {\n entries.push({ pd: entry.resource, mode: entry.search?.mode })\n }\n }\n return classifyResolvedProtocolEntries(entries)\n}\n"]}