gdc-common-utils-ts 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +22 -2
  2. package/dist/claims/claims-helpers-allergy-intolerance.d.ts +8 -0
  3. package/dist/claims/claims-helpers-allergy-intolerance.js +30 -12
  4. package/dist/claims/claims-helpers-condition.d.ts +8 -0
  5. package/dist/claims/claims-helpers-condition.js +30 -12
  6. package/dist/claims/claims-helpers-consent.d.ts +4 -0
  7. package/dist/claims/claims-helpers-consent.js +15 -1
  8. package/dist/claims/claims-helpers-diagnostic-report.d.ts +4 -0
  9. package/dist/claims/claims-helpers-diagnostic-report.js +17 -2
  10. package/dist/claims/claims-helpers-medication-statement.d.ts +10 -2
  11. package/dist/claims/claims-helpers-medication-statement.js +32 -14
  12. package/dist/constants/data-collections.js +0 -1
  13. package/dist/constants/didcomm.d.ts +22 -0
  14. package/dist/constants/didcomm.js +22 -0
  15. package/dist/constants/fhir-resource-types.d.ts +16 -0
  16. package/dist/constants/fhir-resource-types.js +7 -0
  17. package/dist/constants/healthcare.d.ts +348 -193
  18. package/dist/constants/healthcare.js +99 -37
  19. package/dist/constants/hl7-roles.d.ts +38 -4
  20. package/dist/constants/hl7-roles.js +92 -4
  21. package/dist/constants/index.d.ts +1 -0
  22. package/dist/constants/index.js +1 -0
  23. package/dist/constants/lifecycle.d.ts +2 -0
  24. package/dist/constants/lifecycle.js +2 -0
  25. package/dist/constants/verifiable-credentials.d.ts +9 -0
  26. package/dist/constants/verifiable-credentials.js +9 -0
  27. package/dist/examples/bundle-didcomm-payload.js +4 -2
  28. package/dist/examples/communication-attached-bundle-session.js +27 -27
  29. package/dist/examples/communication-didcomm-payload.d.ts +8 -4
  30. package/dist/examples/communication-didcomm-payload.js +17 -11
  31. package/dist/examples/consent-access.js +2 -1
  32. package/dist/examples/employee.d.ts +21 -0
  33. package/dist/examples/employee.js +21 -0
  34. package/dist/examples/individual-controller.d.ts +27 -0
  35. package/dist/examples/individual-controller.js +28 -1
  36. package/dist/examples/inter-tenant-access-contract.js +3 -2
  37. package/dist/examples/ips-bundle.js +17 -16
  38. package/dist/examples/lifecycle.js +13 -11
  39. package/dist/examples/profile-manager-mem.js +2 -1
  40. package/dist/examples/related-person.d.ts +14 -0
  41. package/dist/examples/related-person.js +18 -4
  42. package/dist/examples/shared.d.ts +12 -3
  43. package/dist/examples/shared.js +13 -4
  44. package/dist/examples/vital-signs.js +1 -1
  45. package/dist/examples/wallet-mem.js +4 -2
  46. package/dist/i18n/role-codes.i18n.d.ts +9 -1
  47. package/dist/i18n/role-codes.i18n.js +12 -1
  48. package/dist/models/authority-resolution.d.ts +56 -0
  49. package/dist/models/authority-resolution.js +2 -0
  50. package/dist/models/bundle-editor-types.d.ts +89 -0
  51. package/dist/models/bundle-editor-types.js +45 -0
  52. package/dist/models/bundle.d.ts +5 -0
  53. package/dist/models/communication-attached-bundle-session.d.ts +6 -4
  54. package/dist/models/communication-attached-bundle-session.js +6 -4
  55. package/dist/models/confidential-storage.d.ts +2 -1
  56. package/dist/models/consent-rule.d.ts +11 -1
  57. package/dist/models/consent-rule.js +9 -1
  58. package/dist/models/device-license.d.ts +20 -0
  59. package/dist/models/index.d.ts +2 -0
  60. package/dist/models/index.js +2 -0
  61. package/dist/models/individual-onboarding.d.ts +18 -0
  62. package/dist/models/interoperable-claims/allergy-intolerance-claims.d.ts +12 -1
  63. package/dist/models/interoperable-claims/allergy-intolerance-claims.js +12 -1
  64. package/dist/models/interoperable-claims/condition-claims.d.ts +12 -1
  65. package/dist/models/interoperable-claims/condition-claims.js +12 -1
  66. package/dist/models/interoperable-claims/diagnostic-report-claims.d.ts +13 -2
  67. package/dist/models/interoperable-claims/diagnostic-report-claims.js +12 -1
  68. package/dist/models/interoperable-claims/document-reference-claims.d.ts +1 -0
  69. package/dist/models/interoperable-claims/document-reference-claims.js +3 -0
  70. package/dist/models/interoperable-claims/medication-statement-claims.d.ts +17 -0
  71. package/dist/models/interoperable-claims/medication-statement-claims.js +17 -0
  72. package/dist/models/interoperable-claims/related-person-claims.d.ts +13 -0
  73. package/dist/models/interoperable-claims/related-person-claims.js +16 -0
  74. package/dist/utils/allergy-intolerance-entry-editor.d.ts +51 -0
  75. package/dist/utils/allergy-intolerance-entry-editor.js +55 -0
  76. package/dist/utils/authority-resolution.d.ts +37 -0
  77. package/dist/utils/authority-resolution.js +112 -0
  78. package/dist/utils/backend-message-manager-mem.d.ts +11 -0
  79. package/dist/utils/backend-message-manager-mem.js +11 -0
  80. package/dist/utils/bundle-didcomm-payload.js +3 -2
  81. package/dist/utils/bundle-document-builder.d.ts +36 -0
  82. package/dist/utils/bundle-document-builder.js +310 -14
  83. package/dist/utils/bundle-editor-core.d.ts +181 -0
  84. package/dist/utils/bundle-editor-core.js +467 -0
  85. package/dist/utils/bundle-editor-helpers.d.ts +53 -0
  86. package/dist/utils/bundle-editor-helpers.js +146 -0
  87. package/dist/utils/bundle-editor-registry.d.ts +6 -0
  88. package/dist/utils/bundle-editor-registry.js +14 -0
  89. package/dist/utils/bundle-editor.d.ts +21 -722
  90. package/dist/utils/bundle-editor.js +21 -1601
  91. package/dist/utils/bundle-entry-editor.d.ts +96 -0
  92. package/dist/utils/bundle-entry-editor.js +305 -0
  93. package/dist/utils/bundle-query.d.ts +1 -0
  94. package/dist/utils/bundle-query.js +12 -3
  95. package/dist/utils/bundle-reader.d.ts +48 -0
  96. package/dist/utils/bundle-reader.js +175 -1
  97. package/dist/utils/care-plan-entry-editor.d.ts +43 -0
  98. package/dist/utils/care-plan-entry-editor.js +47 -0
  99. package/dist/utils/client-assertion.d.ts +38 -0
  100. package/dist/utils/client-assertion.js +113 -0
  101. package/dist/utils/clinical-impression-entry-editor.d.ts +43 -0
  102. package/dist/utils/clinical-impression-entry-editor.js +47 -0
  103. package/dist/utils/clinical-resource-entry-editor.d.ts +123 -0
  104. package/dist/utils/clinical-resource-entry-editor.js +296 -0
  105. package/dist/utils/clinical-resource-view.d.ts +16 -0
  106. package/dist/utils/clinical-resource-view.js +267 -33
  107. package/dist/utils/communication-attached-bundle-session-helpers.js +8 -6
  108. package/dist/utils/communication-attached-bundle-session.d.ts +29 -3
  109. package/dist/utils/communication-attached-bundle-session.js +62 -3
  110. package/dist/utils/communication-consent-access-editor.d.ts +8 -4
  111. package/dist/utils/communication-consent-access-editor.js +8 -4
  112. package/dist/utils/communication-didcomm-payload.d.ts +5 -0
  113. package/dist/utils/communication-didcomm-payload.js +28 -18
  114. package/dist/utils/communication-document-reference.d.ts +23 -0
  115. package/dist/utils/communication-document-reference.js +89 -0
  116. package/dist/utils/communication-editor.d.ts +53 -0
  117. package/dist/utils/communication-editor.js +97 -0
  118. package/dist/utils/condition-entry-editor.d.ts +30 -0
  119. package/dist/utils/condition-entry-editor.js +34 -0
  120. package/dist/utils/consent-claim-helpers.d.ts +4 -0
  121. package/dist/utils/consent-claim-helpers.js +15 -1
  122. package/dist/utils/consent-duplicate-rules.js +1 -1
  123. package/dist/utils/coverage-entry-editor.d.ts +51 -0
  124. package/dist/utils/coverage-entry-editor.js +55 -0
  125. package/dist/utils/device-entry-editor.d.ts +59 -0
  126. package/dist/utils/device-entry-editor.js +63 -0
  127. package/dist/utils/device-use-statement-entry-editor.d.ts +43 -0
  128. package/dist/utils/device-use-statement-entry-editor.js +47 -0
  129. package/dist/utils/diagnostic-report-entry-editor.d.ts +74 -0
  130. package/dist/utils/diagnostic-report-entry-editor.js +136 -0
  131. package/dist/utils/did.d.ts +8 -0
  132. package/dist/utils/did.js +22 -0
  133. package/dist/utils/document-reference-entry-editor.d.ts +62 -0
  134. package/dist/utils/document-reference-entry-editor.js +66 -0
  135. package/dist/utils/employee-entry-editor.d.ts +36 -0
  136. package/dist/utils/employee-entry-editor.js +88 -0
  137. package/dist/utils/employee.d.ts +1 -0
  138. package/dist/utils/employee.js +2 -1
  139. package/dist/utils/encounter-entry-editor.d.ts +51 -0
  140. package/dist/utils/encounter-entry-editor.js +55 -0
  141. package/dist/utils/flag-entry-editor.d.ts +47 -0
  142. package/dist/utils/flag-entry-editor.js +51 -0
  143. package/dist/utils/immunization-entry-editor.d.ts +87 -0
  144. package/dist/utils/immunization-entry-editor.js +169 -0
  145. package/dist/utils/index.d.ts +7 -0
  146. package/dist/utils/index.js +7 -0
  147. package/dist/utils/individual-onboarding-acceptance-credential.d.ts +35 -0
  148. package/dist/utils/individual-onboarding-acceptance-credential.js +55 -0
  149. package/dist/utils/individual-smart.d.ts +59 -0
  150. package/dist/utils/individual-smart.js +135 -0
  151. package/dist/utils/license-list-search.d.ts +5 -0
  152. package/dist/utils/license-list-search.js +9 -0
  153. package/dist/utils/license.d.ts +45 -1
  154. package/dist/utils/license.js +86 -2
  155. package/dist/utils/medication-statement-entry-editor.d.ts +90 -0
  156. package/dist/utils/medication-statement-entry-editor.js +94 -0
  157. package/dist/utils/observation-component-entry-editor.d.ts +57 -0
  158. package/dist/utils/observation-component-entry-editor.js +105 -0
  159. package/dist/utils/observation-entry-editor.d.ts +29 -0
  160. package/dist/utils/observation-entry-editor.js +68 -0
  161. package/dist/utils/procedure-entry-editor.d.ts +71 -0
  162. package/dist/utils/procedure-entry-editor.js +75 -0
  163. package/dist/utils/professional-smart.d.ts +87 -0
  164. package/dist/utils/professional-smart.js +118 -4
  165. package/dist/utils/related-person-list.d.ts +4 -0
  166. package/dist/utils/related-person-list.js +26 -6
  167. package/dist/utils/same-as.d.ts +40 -0
  168. package/dist/utils/same-as.js +72 -0
  169. package/dist/utils/unified-health-id.d.ts +51 -0
  170. package/dist/utils/unified-health-id.js +92 -0
  171. package/dist/utils/vital-sign-day-batch.d.ts +25 -0
  172. package/dist/utils/vital-sign-day-batch.js +115 -0
  173. package/dist/utils/vital-sign-entry-editor.d.ts +61 -0
  174. package/dist/utils/vital-sign-entry-editor.js +152 -0
  175. package/package.json +2 -1
@@ -17,16 +17,17 @@ const GENERIC_ASSERTER_CLAIM_SUFFIX = '.asserter';
17
17
  export function toClinicalResourceCommonView(entry) {
18
18
  const claims = readClaims(entry);
19
19
  const resourceType = resolveResourceType(entry, claims);
20
- const title = resolveTitle(resourceType, claims);
20
+ const resource = entry.resource;
21
+ const title = resolveTitle(resourceType, claims, resource);
21
22
  return {
22
23
  title,
23
24
  resourceType,
24
- identifier: resolveIdentifier(resourceType, claims),
25
- date: resolveDate(resourceType, claims),
26
- periodStart: resolvePeriodStart(resourceType, claims),
27
- periodEnd: resolvePeriodEnd(resourceType, claims),
25
+ identifier: resolveIdentifier(resourceType, claims, resource),
26
+ date: resolveDate(resourceType, claims, resource),
27
+ periodStart: resolvePeriodStart(resourceType, claims, resource),
28
+ periodEnd: resolvePeriodEnd(resourceType, claims, resource),
28
29
  fullUrl: trimValue(entry.fullUrl),
29
- actors: resolveActors(resourceType, claims),
30
+ actors: resolveActors(resourceType, claims, resource),
30
31
  claims,
31
32
  };
32
33
  }
@@ -72,6 +73,51 @@ export function toClinicalResourceExpandedView(entry) {
72
73
  export function toClinicalResourceExpandedViews(bundle) {
73
74
  return readBundleEntries(bundle).map((entry) => toClinicalResourceExpandedView(entry));
74
75
  }
76
+ /**
77
+ * Builds section cards from the references authored in an IPS Composition.
78
+ *
79
+ * The Composition is authoritative for grouping. Resource type is deliberately
80
+ * not used to guess a section because Observation and supporting resources can
81
+ * be referenced from several IPS sections.
82
+ */
83
+ export function toClinicalSectionViews(bundle) {
84
+ const entries = readBundleEntries(bundle);
85
+ const composition = entries.find((entry) => entry.resource?.resourceType === ResourceTypesFhirR4.Composition);
86
+ if (!composition?.resource) {
87
+ return [];
88
+ }
89
+ const entryIndex = indexEntriesByFhirReference(entries);
90
+ return flattenCompositionSections(asArray(composition.resource.section)).map((section) => {
91
+ const references = asArray(section.entry)
92
+ .map((item) => trimValue(asRecord(item).reference))
93
+ .filter(Boolean);
94
+ const resolvedEntries = [];
95
+ const unresolvedReferences = [];
96
+ references.forEach((reference) => {
97
+ const resolved = resolveIndexedEntry(entryIndex, reference);
98
+ if (resolved) {
99
+ resolvedEntries.push(resolved);
100
+ }
101
+ else {
102
+ unresolvedReferences.push(reference);
103
+ }
104
+ });
105
+ const code = resolveCodeableConceptToken(section.code);
106
+ const title = trimValue(section.title)
107
+ || resolveCodeableConceptLabel(section.code)
108
+ || code
109
+ || 'Section';
110
+ return {
111
+ ...(code ? { code } : {}),
112
+ title,
113
+ ...(resolveCodeableConceptLabel(section.emptyReason)
114
+ ? { emptyReason: resolveCodeableConceptLabel(section.emptyReason) }
115
+ : {}),
116
+ resources: resolvedEntries.map((entry) => toClinicalResourceCardView(entry)),
117
+ unresolvedReferences,
118
+ };
119
+ });
120
+ }
75
121
  /**
76
122
  * Returns the most useful local text plus international display pair that can
77
123
  * be inferred from one FHIR-like resource and its `meta.claims`.
@@ -158,18 +204,19 @@ function resolveResourceType(entry, claims) {
158
204
  }
159
205
  return 'Unknown';
160
206
  }
161
- function resolveTitle(resourceType, claims) {
207
+ function resolveTitle(resourceType, claims, resource) {
162
208
  if (resourceType === ResourceTypesFhirR4.Communication) {
163
209
  return (trimValue(claims[CommunicationClaim.ContentAttachmentTitle])
164
210
  || trimValue(claims[CommunicationClaim.Text])
165
211
  || trimValue(claims[CommunicationClaim.NoteText])
212
+ || resolveFhirResourceTitle(resourceType, resource)
166
213
  || resourceType);
167
214
  }
168
215
  if (resourceType === ResourceTypesFhirR4.Consent) {
169
216
  const firstCategory = splitCsv(claims[ClaimConsent.category])[0];
170
217
  const firstAction = splitCsv(claims[ClaimConsent.action])[0];
171
218
  const firstPurpose = splitCsv(claims[ClaimConsent.purpose])[0];
172
- return firstCategory || firstAction || firstPurpose || resourceType;
219
+ return firstCategory || firstAction || firstPurpose || resolveFhirResourceTitle(resourceType, resource) || resourceType;
173
220
  }
174
221
  if (resourceType === ResourceTypesFhirR4.MedicationStatement) {
175
222
  const text = firstClaimValue(claims, [
@@ -180,7 +227,7 @@ function resolveTitle(resourceType, claims) {
180
227
  MedicationStatementClaim.Code,
181
228
  MedicationStatementClaimsFhirApi.Code,
182
229
  ]);
183
- return text || firstCode || resourceType;
230
+ return text || firstCode || resolveFhirResourceTitle(resourceType, resource) || resourceType;
184
231
  }
185
232
  if (resourceType === ResourceTypesFhirR4.Condition) {
186
233
  const firstCode = firstClaimCsvValue(claims, [
@@ -191,7 +238,7 @@ function resolveTitle(resourceType, claims) {
191
238
  ConditionClaim.Category,
192
239
  ConditionClaimsFhirApi.Category,
193
240
  ]);
194
- return firstCode || firstCategory || resourceType;
241
+ return firstCode || firstCategory || resolveFhirResourceTitle(resourceType, resource) || resourceType;
195
242
  }
196
243
  if (resourceType === ResourceTypesFhirR4.AllergyIntolerance) {
197
244
  const firstCode = firstClaimCsvValue(claims, [
@@ -202,78 +249,78 @@ function resolveTitle(resourceType, claims) {
202
249
  AllergyIntoleranceClaim.Category,
203
250
  AllergyIntoleranceClaimsFhirApi.Category,
204
251
  ]);
205
- return firstCode || firstCategory || resourceType;
252
+ return firstCode || firstCategory || resolveFhirResourceTitle(resourceType, resource) || resourceType;
206
253
  }
207
- return resourceType;
254
+ return resolveFhirResourceTitle(resourceType, resource) || resourceType;
208
255
  }
209
- function resolveIdentifier(resourceType, claims) {
256
+ function resolveIdentifier(resourceType, claims, resource) {
210
257
  if (resourceType === ResourceTypesFhirR4.Communication) {
211
- return trimValue(claims[CommunicationClaim.Identifier]);
258
+ return trimValue(claims[CommunicationClaim.Identifier]) || resolveFhirIdentifier(resource);
212
259
  }
213
260
  if (resourceType === ResourceTypesFhirR4.Consent) {
214
- return trimValue(claims[ClaimConsent.identifier]);
261
+ return trimValue(claims[ClaimConsent.identifier]) || resolveFhirIdentifier(resource);
215
262
  }
216
263
  if (resourceType === ResourceTypesFhirR4.MedicationStatement) {
217
264
  return firstClaimValue(claims, [
218
265
  MedicationStatementClaim.Identifier,
219
266
  MedicationStatementClaimsFhirApi.Identifier,
220
- ]);
267
+ ]) || resolveFhirIdentifier(resource);
221
268
  }
222
269
  if (resourceType === ResourceTypesFhirR4.Condition) {
223
270
  return firstClaimValue(claims, [
224
271
  ConditionClaim.Identifier,
225
272
  ConditionClaimsFhirApi.Identifier,
226
- ]);
273
+ ]) || resolveFhirIdentifier(resource);
227
274
  }
228
275
  if (resourceType === ResourceTypesFhirR4.AllergyIntolerance) {
229
276
  return firstClaimValue(claims, [
230
277
  AllergyIntoleranceClaim.Identifier,
231
278
  AllergyIntoleranceClaimsFhirApi.Identifier,
232
- ]);
279
+ ]) || resolveFhirIdentifier(resource);
233
280
  }
234
- return undefined;
281
+ return resolveFhirIdentifier(resource);
235
282
  }
236
- function resolveDate(resourceType, claims) {
283
+ function resolveDate(resourceType, claims, resource) {
237
284
  if (resourceType === ResourceTypesFhirR4.Communication) {
238
- return trimValue(claims[CommunicationClaim.Sent]);
285
+ return trimValue(claims[CommunicationClaim.Sent]) || resolveFhirDate(resourceType, resource);
239
286
  }
240
287
  if (resourceType === ResourceTypesFhirR4.Consent) {
241
- return trimValue(claims[ClaimConsent.date]);
288
+ return trimValue(claims[ClaimConsent.date]) || resolveFhirDate(resourceType, resource);
242
289
  }
243
290
  if (resourceType === ResourceTypesFhirR4.MedicationStatement) {
244
291
  return firstClaimValue(claims, [
245
292
  MedicationStatementClaim.Effective,
246
293
  MedicationStatementClaimsFhirApi.Effective,
247
- ]);
294
+ ]) || resolveFhirDate(resourceType, resource);
248
295
  }
249
296
  if (resourceType === ResourceTypesFhirR4.Condition) {
250
297
  return firstClaimValue(claims, [
251
298
  ConditionClaim.OnsetDateTime,
252
299
  ConditionClaimsFhirApi.OnsetDateTime,
253
- ]);
300
+ ]) || resolveFhirDate(resourceType, resource);
254
301
  }
255
302
  if (resourceType === ResourceTypesFhirR4.AllergyIntolerance) {
256
303
  return firstClaimValue(claims, [
257
304
  AllergyIntoleranceClaim.OnsetDateTime,
258
305
  AllergyIntoleranceClaimsFhirApi.OnsetDateTime,
259
- ]);
306
+ ]) || resolveFhirDate(resourceType, resource);
260
307
  }
261
308
  const genericDate = findBySuffix(claims, '.date');
262
- return genericDate || undefined;
309
+ return genericDate || resolveFhirDate(resourceType, resource) || undefined;
263
310
  }
264
- function resolvePeriodStart(resourceType, claims) {
311
+ function resolvePeriodStart(resourceType, claims, resource) {
265
312
  if (resourceType === ResourceTypesFhirR4.Consent) {
266
- return trimValue(claims[ClaimConsent.periodStart]);
313
+ return trimValue(claims[ClaimConsent.periodStart]) || resolveFhirPeriod(resource).start;
267
314
  }
268
- return findBySuffix(claims, '.period-start') || undefined;
315
+ return findBySuffix(claims, '.period-start') || resolveFhirPeriod(resource).start || undefined;
269
316
  }
270
- function resolvePeriodEnd(resourceType, claims) {
317
+ function resolvePeriodEnd(resourceType, claims, resource) {
271
318
  if (resourceType === ResourceTypesFhirR4.Consent) {
272
- return trimValue(claims[ClaimConsent.periodEnd]);
319
+ return trimValue(claims[ClaimConsent.periodEnd]) || resolveFhirPeriod(resource).end;
273
320
  }
274
- return findBySuffix(claims, '.period-end') || undefined;
321
+ return findBySuffix(claims, '.period-end') || resolveFhirPeriod(resource).end || undefined;
275
322
  }
276
- function resolveActors(resourceType, claims) {
323
+ function resolveActors(resourceType, claims, resource) {
277
324
  const out = [];
278
325
  if (resourceType === ResourceTypesFhirR4.Consent) {
279
326
  const identifiers = splitCsv(claims[ClaimConsent.actorIdentifier]);
@@ -350,6 +397,7 @@ function resolveActors(resourceType, claims) {
350
397
  appendGenericActorType(out, claims, GENERIC_CREATOR_CLAIM_SUFFIX, 'creator');
351
398
  appendGenericActorType(out, claims, GENERIC_PERFORMER_CLAIM_SUFFIX, 'performer');
352
399
  appendGenericActorType(out, claims, GENERIC_ASSERTER_CLAIM_SUFFIX, 'asserter');
400
+ appendFhirActors(out, resource);
353
401
  return out;
354
402
  }
355
403
  function resolveXhtml(entry, claims) {
@@ -464,6 +512,192 @@ function resolveResourceCodeDisplay(resource) {
464
512
  }
465
513
  return undefined;
466
514
  }
515
+ function resolveFhirResourceTitle(resourceType, resource) {
516
+ if (!resource) {
517
+ return undefined;
518
+ }
519
+ const codeableConceptCandidates = [];
520
+ if (resourceType === ResourceTypesFhirR4.MedicationStatement
521
+ || resourceType === ResourceTypesFhirR4.MedicationRequest) {
522
+ codeableConceptCandidates.push(resource.medicationCodeableConcept);
523
+ const medicationDisplay = trimValue(asRecord(resource.medicationReference).display);
524
+ if (medicationDisplay)
525
+ return medicationDisplay;
526
+ }
527
+ if (resourceType === ResourceTypesFhirR4.Immunization) {
528
+ codeableConceptCandidates.push(resource.vaccineCode);
529
+ }
530
+ if (resourceType === ResourceTypesFhirR4.Device) {
531
+ const deviceName = asArray(resource.deviceName)
532
+ .map((item) => trimValue(asRecord(item).name))
533
+ .find(Boolean);
534
+ if (deviceName)
535
+ return deviceName;
536
+ codeableConceptCandidates.push(resource.type);
537
+ }
538
+ if (resourceType === ResourceTypesFhirR4.DeviceUseStatement) {
539
+ const deviceDisplay = trimValue(asRecord(resource.device).display);
540
+ if (deviceDisplay)
541
+ return deviceDisplay;
542
+ }
543
+ codeableConceptCandidates.push(resource.code, resource.title, resource.name, resource.description, resource.scope, resource.category);
544
+ for (const candidate of codeableConceptCandidates) {
545
+ const plainText = trimValue(candidate);
546
+ if (plainText && typeof candidate !== 'object') {
547
+ return plainText;
548
+ }
549
+ const label = resolveCodeableConceptLabel(candidate);
550
+ if (label) {
551
+ return label;
552
+ }
553
+ for (const item of asArray(candidate)) {
554
+ const arrayLabel = resolveCodeableConceptLabel(item);
555
+ if (arrayLabel)
556
+ return arrayLabel;
557
+ }
558
+ }
559
+ return undefined;
560
+ }
561
+ function resolveFhirIdentifier(resource) {
562
+ if (!resource)
563
+ return undefined;
564
+ for (const identifier of asArray(resource.identifier)) {
565
+ const record = asRecord(identifier);
566
+ const value = trimValue(record.value);
567
+ if (value)
568
+ return value;
569
+ }
570
+ return trimValue(resource.id) || undefined;
571
+ }
572
+ function resolveFhirDate(resourceType, resource) {
573
+ if (!resource)
574
+ return undefined;
575
+ const period = resolveFhirPeriod(resource);
576
+ const candidates = resourceType === ResourceTypesFhirR4.MedicationRequest
577
+ ? [resource.authoredOn, period.start]
578
+ : resourceType === ResourceTypesFhirR4.Immunization
579
+ ? [resource.occurrenceDateTime, resource.occurrenceString, resource.recorded]
580
+ : resourceType === ResourceTypesFhirR4.Procedure
581
+ ? [resource.performedDateTime, resource.performedString, period.start]
582
+ : [
583
+ resource.effectiveDateTime,
584
+ resource.effectiveInstant,
585
+ resource.occurrenceDateTime,
586
+ resource.onsetDateTime,
587
+ resource.dateTime,
588
+ resource.date,
589
+ resource.issued,
590
+ resource.recordedDate,
591
+ resource.recordedOn,
592
+ resource.authoredOn,
593
+ resource.created,
594
+ period.start,
595
+ ];
596
+ return firstDefinedText(candidates.map((candidate) => trimValue(candidate) || undefined));
597
+ }
598
+ function resolveFhirPeriod(resource) {
599
+ if (!resource)
600
+ return {};
601
+ const candidates = [
602
+ resource.effectivePeriod,
603
+ resource.performedPeriod,
604
+ resource.occurrencePeriod,
605
+ resource.timingPeriod,
606
+ resource.period,
607
+ resource.onsetPeriod,
608
+ ];
609
+ for (const candidate of candidates) {
610
+ const period = asRecord(candidate);
611
+ const start = trimValue(period.start);
612
+ const end = trimValue(period.end);
613
+ if (start || end) {
614
+ return {
615
+ ...(start ? { start } : {}),
616
+ ...(end ? { end } : {}),
617
+ };
618
+ }
619
+ }
620
+ return {};
621
+ }
622
+ function appendFhirActors(out, resource) {
623
+ if (!resource)
624
+ return;
625
+ appendFhirReference(out, resource.subject || resource.patient, 'subject');
626
+ appendFhirReference(out, resource.informationSource || resource.source, 'source');
627
+ appendFhirReference(out, resource.sender, 'sender');
628
+ appendFhirReference(out, resource.recipient, 'recipient');
629
+ appendFhirReference(out, resource.recorder || resource.asserter, 'asserter');
630
+ appendFhirReference(out, resource.author, 'creator');
631
+ appendFhirReference(out, resource.performer, 'performer');
632
+ }
633
+ function appendFhirReference(out, value, type) {
634
+ const values = Array.isArray(value) ? value : [value];
635
+ values.forEach((item) => {
636
+ const record = asRecord(item);
637
+ const actor = asRecord(record.actor);
638
+ const identifierRecord = asRecord(record.identifier);
639
+ const actorIdentifierRecord = asRecord(actor.identifier);
640
+ const identifier = firstDefinedText([
641
+ trimValue(record.reference) || undefined,
642
+ trimValue(actor.reference) || undefined,
643
+ trimValue(identifierRecord.value) || undefined,
644
+ trimValue(actorIdentifierRecord.value) || undefined,
645
+ trimValue(record.display) || undefined,
646
+ trimValue(actor.display) || undefined,
647
+ ]);
648
+ if (identifier)
649
+ pushActor(out, { identifier, type });
650
+ });
651
+ }
652
+ function resolveCodeableConceptLabel(value) {
653
+ const concept = asRecord(value);
654
+ const localText = trimValue(concept.text) || undefined;
655
+ const internationalDisplay = asArray(concept.coding)
656
+ .map((coding) => trimValue(asRecord(coding).display))
657
+ .find(Boolean);
658
+ return buildCombinedLabel(localText, internationalDisplay);
659
+ }
660
+ function resolveCodeableConceptToken(value) {
661
+ const coding = asArray(asRecord(value).coding)
662
+ .map((item) => asRecord(item))
663
+ .find((item) => trimValue(item.code));
664
+ if (!coding)
665
+ return undefined;
666
+ const system = trimValue(coding.system);
667
+ const code = trimValue(coding.code);
668
+ return system ? `${system}|${code}` : code;
669
+ }
670
+ function flattenCompositionSections(values) {
671
+ const out = [];
672
+ values.forEach((value) => {
673
+ const section = asRecord(value);
674
+ out.push(section);
675
+ out.push(...flattenCompositionSections(asArray(section.section)));
676
+ });
677
+ return out;
678
+ }
679
+ function indexEntriesByFhirReference(entries) {
680
+ const index = new Map();
681
+ entries.forEach((entry) => {
682
+ const fullUrl = trimValue(entry.fullUrl);
683
+ const resourceType = trimValue(entry.resource?.resourceType);
684
+ const id = trimValue(entry.resource?.id);
685
+ if (fullUrl)
686
+ index.set(fullUrl, entry);
687
+ if (resourceType && id)
688
+ index.set(`${resourceType}/${id}`, entry);
689
+ if (id)
690
+ index.set(`urn:uuid:${id}`, entry);
691
+ });
692
+ return index;
693
+ }
694
+ function resolveIndexedEntry(index, reference) {
695
+ const direct = index.get(reference);
696
+ if (direct)
697
+ return direct;
698
+ const relativeReference = reference.match(/([A-Za-z]+\/[^/]+)$/)?.[1];
699
+ return relativeReference ? index.get(relativeReference) : undefined;
700
+ }
467
701
  function firstDefinedText(values) {
468
702
  for (const value of values) {
469
703
  const normalized = trimValue(value);
@@ -39,7 +39,9 @@ export function ensureEntryResource(entry, mode) {
39
39
  throw new Error('Active entry does not contain a valid resource object.');
40
40
  }
41
41
  export function validateBundleLike(bundle, mode) {
42
- const looksLikeBundle = bundle && bundle.resourceType === ResourceTypesFhirR4.Bundle && Array.isArray(bundle.data);
42
+ const looksLikeBundle = bundle
43
+ && bundle.resourceType === ResourceTypesFhirR4.Bundle
44
+ && (Array.isArray(bundle.data) || Array.isArray(bundle.entry));
43
45
  if (looksLikeBundle || mode === 'normalize') {
44
46
  return;
45
47
  }
@@ -75,19 +77,19 @@ export function asTrimmedString(value) {
75
77
  }
76
78
  export function resolveContainedDocumentsClaimKey(resourceType) {
77
79
  if (resourceType === ResourceTypesFhirR4.Consent) {
78
- return ClaimConsent.containedDocuments;
80
+ return ClaimConsent.containedReferenceList;
79
81
  }
80
82
  if (resourceType === ResourceTypesFhirR4.MedicationStatement) {
81
- return MedicationStatementClaim.ContainedDocuments;
83
+ return MedicationStatementClaim.ContainedReferenceList;
82
84
  }
83
85
  if (resourceType === ResourceTypesFhirR4.Condition) {
84
- return ConditionClaim.ContainedDocuments;
86
+ return ConditionClaim.ContainedReferenceList;
85
87
  }
86
88
  if (resourceType === ResourceTypesFhirR4.AllergyIntolerance) {
87
- return AllergyIntoleranceClaim.ContainedDocuments;
89
+ return AllergyIntoleranceClaim.ContainedReferenceList;
88
90
  }
89
91
  if (resourceType === ResourceTypesFhirR4.DiagnosticReport) {
90
- return DiagnosticReportClaim.ContainedDocuments;
92
+ return DiagnosticReportClaim.ContainedReferenceList;
91
93
  }
92
94
  return '';
93
95
  }
@@ -2,7 +2,7 @@ import { BundleEntry, BundleJsonApi } from '../models/bundle';
2
2
  import { type ActiveEntrySelection, type AddContainedDocumentToActiveEntryInput, type CommunicationAttachedBundleSessionOptions, type UpsertClaimsResourceEntryInput, type UpsertEntryInput } from '../models/communication-attached-bundle-session';
3
3
  import { type BundleResourceIdFilters } from './bundle-query';
4
4
  import type { MedicationStatementClaimsFlat } from '../models/interoperable-claims/medication-statement-claims';
5
- export { BundleEntryClaimsContext, CommunicationAttachmentClaimsContext, ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session';
5
+ export { BundleEntryClaimsContext, CommunicationClaimsContext, CommunicationAttachmentClaimsContext, ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session';
6
6
  export type { ActiveEntrySelection, AddContainedDocumentToActiveEntryInput, CommunicationAttachedBundleSessionMode, CommunicationAttachedBundleSessionOptions, ConsentEditorClassifiedActors, ConsentEditorClassifiedPurpose, ConsentEditorClassifiedRole, ConsentEditorClassifiedRoles, ConsentEditorClassifiedTarget, ConsentEditorScopeCode, ConsentEditorTargetKind, ConsentViewModel, UpsertClaimsResourceEntryInput, UpsertEntryInput, } from '../models/communication-attached-bundle-session';
7
7
  /**
8
8
  * Communication editing session with bundle-in-memory as source of truth.
@@ -24,8 +24,32 @@ export declare class CommunicationAttachedBundleSession {
24
24
  constructor(options?: CommunicationAttachedBundleSessionOptions);
25
25
  /** Returns a deep copy of communication claims. */
26
26
  getCommunicationClaims(): Record<string, unknown>;
27
+ /** Returns the canonical outer Communication identifier. */
28
+ getCommunicationIdentifier(): string;
29
+ /** Sets the canonical outer Communication identifier. */
30
+ setCommunicationIdentifier(value: unknown): this;
31
+ /** Returns the canonical outer Communication subject. */
32
+ getCommunicationSubject(): string;
33
+ /** Sets the canonical outer Communication subject. */
34
+ setCommunicationSubject(value: unknown): this;
35
+ /** Returns the canonical outer Communication categories. */
36
+ getCommunicationCategoryList(): string[];
37
+ /** Replaces the canonical outer Communication categories. */
38
+ setCommunicationCategory(value: string | readonly string[]): this;
39
+ /** Returns the canonical outer Communication topic. */
40
+ getCommunicationTopic(): string;
41
+ /** Sets the canonical outer Communication topic. */
42
+ setCommunicationTopic(value: unknown): this;
43
+ /** Returns the canonical outer Communication text. */
44
+ getCommunicationText(): string;
45
+ /** Sets the canonical outer Communication text. */
46
+ setCommunicationText(value: unknown): this;
27
47
  /** Returns a deep copy of the current in-memory bundle. */
28
48
  getBundleInMemory(): BundleJsonApi<BundleEntry>;
49
+ /** Replaces the attached clinical bundle and resyncs the outer Communication attachment. */
50
+ setAttachedBundle(bundle: BundleJsonApi<BundleEntry>): this;
51
+ /** Alias of `getBundleInMemory()` with communication wording. */
52
+ getAttachedBundle(): BundleJsonApi<BundleEntry>;
29
53
  /** Returns the active entry index, or null when no entry is selected. */
30
54
  getActiveEntryIndex(): number | null;
31
55
  /** Returns the active entry position, or null when no entry is selected. */
@@ -86,7 +110,8 @@ export declare class CommunicationAttachedBundleSession {
86
110
  upsertActiveMedicationStatementEntry(input: UpsertClaimsResourceEntryInput<MedicationStatementClaimsFlat | Record<string, unknown>>): this;
87
111
  /**
88
112
  * DocumentReference helper for bundle-contained attachments linked from
89
- * other clinical resources through `*.contained-documents`.
113
+ * other clinical resources through `*.contained-reference-list`
114
+ * (with `*.contained-documents` kept as legacy compatibility alias).
90
115
  */
91
116
  upsertActiveDocumentReferenceEntry(input: UpsertClaimsResourceEntryInput<Record<string, unknown>>): this;
92
117
  /**
@@ -145,7 +170,8 @@ export declare class CommunicationAttachedBundleSession {
145
170
  upsertActiveRelatedPersonEntry(input: UpsertClaimsResourceEntryInput<Record<string, unknown>>): this;
146
171
  /**
147
172
  * Creates or updates a linked `DocumentReference` entry and stores its
148
- * identifier under the active resource `*.contained-documents` claim.
173
+ * identifier/reference under the active resource
174
+ * `*.contained-reference-list` claim.
149
175
  */
150
176
  addContainedDocumentToActiveEntry(input: AddContainedDocumentToActiveEntryInput): this;
151
177
  /**
@@ -6,8 +6,9 @@ import { DocumentReferenceClaim } from '../models/interoperable-claims/document-
6
6
  import { BundleEntryClaimsContext, } from '../models/communication-attached-bundle-session.js';
7
7
  import { BundleQuery } from './bundle-query.js';
8
8
  import { addClaimValues } from '../claims/claim-list-helpers.js';
9
+ import { getCommunicationCategoryList, getCommunicationIdentifier, getCommunicationSubject, getCommunicationText, getCommunicationTopic, setCommunicationCategory, setCommunicationIdentifier, setCommunicationSubject, setCommunicationText, setCommunicationTopic, } from '../claims/claims-helpers-communication.js';
9
10
  import { asTrimmedString, cloneBundle, cloneEntry, cloneUnknownValue, createEmptyBundle, encodeBundleToBase64, ensureEntryResource, resolveBundleEntryCanonicalIdValue, resolveBundleEntryIdentifier, resolveContainedDocumentsClaimKey, resolveSubjectFromClaims, runtimeUuid, setIfMissing, validateBundleLike, } from './communication-attached-bundle-session-helpers.js';
10
- export { BundleEntryClaimsContext, CommunicationAttachmentClaimsContext, ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session.js';
11
+ export { BundleEntryClaimsContext, CommunicationClaimsContext, CommunicationAttachmentClaimsContext, ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session.js';
11
12
  /**
12
13
  * Communication editing session with bundle-in-memory as source of truth.
13
14
  *
@@ -41,10 +42,66 @@ export class CommunicationAttachedBundleSession {
41
42
  ...this.communicationClaims,
42
43
  };
43
44
  }
45
+ /** Returns the canonical outer Communication identifier. */
46
+ getCommunicationIdentifier() {
47
+ return getCommunicationIdentifier(this.communicationClaims);
48
+ }
49
+ /** Sets the canonical outer Communication identifier. */
50
+ setCommunicationIdentifier(value) {
51
+ this.communicationClaims = setCommunicationIdentifier(this.communicationClaims, value);
52
+ return this;
53
+ }
54
+ /** Returns the canonical outer Communication subject. */
55
+ getCommunicationSubject() {
56
+ return getCommunicationSubject(this.communicationClaims);
57
+ }
58
+ /** Sets the canonical outer Communication subject. */
59
+ setCommunicationSubject(value) {
60
+ this.communicationClaims = setCommunicationSubject(this.communicationClaims, value);
61
+ return this;
62
+ }
63
+ /** Returns the canonical outer Communication categories. */
64
+ getCommunicationCategoryList() {
65
+ return getCommunicationCategoryList(this.communicationClaims);
66
+ }
67
+ /** Replaces the canonical outer Communication categories. */
68
+ setCommunicationCategory(value) {
69
+ this.communicationClaims = setCommunicationCategory(this.communicationClaims, value);
70
+ return this;
71
+ }
72
+ /** Returns the canonical outer Communication topic. */
73
+ getCommunicationTopic() {
74
+ return getCommunicationTopic(this.communicationClaims);
75
+ }
76
+ /** Sets the canonical outer Communication topic. */
77
+ setCommunicationTopic(value) {
78
+ this.communicationClaims = setCommunicationTopic(this.communicationClaims, value);
79
+ return this;
80
+ }
81
+ /** Returns the canonical outer Communication text. */
82
+ getCommunicationText() {
83
+ return getCommunicationText(this.communicationClaims);
84
+ }
85
+ /** Sets the canonical outer Communication text. */
86
+ setCommunicationText(value) {
87
+ this.communicationClaims = setCommunicationText(this.communicationClaims, value);
88
+ return this;
89
+ }
44
90
  /** Returns a deep copy of the current in-memory bundle. */
45
91
  getBundleInMemory() {
46
92
  return cloneBundle(this.bundleInMemory);
47
93
  }
94
+ /** Replaces the attached clinical bundle and resyncs the outer Communication attachment. */
95
+ setAttachedBundle(bundle) {
96
+ validateBundleLike(bundle, this.mode);
97
+ this.bundleInMemory = cloneBundle(bundle);
98
+ this.syncAttachmentFromBundle();
99
+ return this;
100
+ }
101
+ /** Alias of `getBundleInMemory()` with communication wording. */
102
+ getAttachedBundle() {
103
+ return this.getBundleInMemory();
104
+ }
48
105
  /** Returns the active entry index, or null when no entry is selected. */
49
106
  getActiveEntryIndex() {
50
107
  return this.activeEntryIndex;
@@ -230,7 +287,8 @@ export class CommunicationAttachedBundleSession {
230
287
  }
231
288
  /**
232
289
  * DocumentReference helper for bundle-contained attachments linked from
233
- * other clinical resources through `*.contained-documents`.
290
+ * other clinical resources through `*.contained-reference-list`
291
+ * (with `*.contained-documents` kept as legacy compatibility alias).
234
292
  */
235
293
  upsertActiveDocumentReferenceEntry(input) {
236
294
  return this.upsertActiveClaimsResourceEntry(ResourceTypesFhirR4.DocumentReference, input);
@@ -329,7 +387,8 @@ export class CommunicationAttachedBundleSession {
329
387
  }
330
388
  /**
331
389
  * Creates or updates a linked `DocumentReference` entry and stores its
332
- * identifier under the active resource `*.contained-documents` claim.
390
+ * identifier/reference under the active resource
391
+ * `*.contained-reference-list` claim.
333
392
  */
334
393
  addContainedDocumentToActiveEntry(input) {
335
394
  if (this.activeEntryIndex === null) {
@@ -4,11 +4,15 @@ import type { CommunicationAttachedBundleSessionOptions, ConsentEditorClassified
4
4
  import type { ConsentDuplicateRuleConflict } from './consent-duplicate-rules';
5
5
  import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session';
6
6
  /**
7
- * High-level consent-access editor alias for onboarding and app-facing code.
7
+ * High-level access-policy editor for onboarding and app-facing code.
8
8
  *
9
- * This keeps the business intent explicit for developers who are editing
10
- * Consent access rules inside a Communication-carried bundle and should not
11
- * need to start from the lower-level generic session name.
9
+ * This edits permit/deny rules governing who may access which data, for which
10
+ * purpose and scope, inside a Communication-carried bundle. It does not model
11
+ * informed consent for a clinical procedure, treatment or intervention.
12
+ *
13
+ * The name deliberately separates authorization consent from clinical
14
+ * intervention consent while retaining the FHIR-like `Consent` resource used
15
+ * by the existing access-rule contract.
12
16
  */
13
17
  export declare class ConsentAccessEditor extends CommunicationAttachedBundleSession {
14
18
  /** Returns duplicate atomic consent-rule conflicts across the current bundle. */
@@ -7,11 +7,15 @@ import { detectDuplicateConsentRuleConflicts } from './consent-duplicate-rules.j
7
7
  import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session.js';
8
8
  import { asTrimmedString, buildClassifiedConsentTarget, buildConsentViewModel, buildSectionCatalogOptions, classifyConsentActors, classifyConsentPurposes, classifyConsentRoles, classifyConsentTargetsFromClaims, CSV_SEPARATOR, flattenClassifiedActors, flattenClassifiedRoles, flattenClassifiedTargets, normalizeCsvValues, splitCsv, } from './communication-attached-bundle-session-helpers.js';
9
9
  /**
10
- * High-level consent-access editor alias for onboarding and app-facing code.
10
+ * High-level access-policy editor for onboarding and app-facing code.
11
11
  *
12
- * This keeps the business intent explicit for developers who are editing
13
- * Consent access rules inside a Communication-carried bundle and should not
14
- * need to start from the lower-level generic session name.
12
+ * This edits permit/deny rules governing who may access which data, for which
13
+ * purpose and scope, inside a Communication-carried bundle. It does not model
14
+ * informed consent for a clinical procedure, treatment or intervention.
15
+ *
16
+ * The name deliberately separates authorization consent from clinical
17
+ * intervention consent while retaining the FHIR-like `Consent` resource used
18
+ * by the existing access-rule contract.
15
19
  */
16
20
  export class ConsentAccessEditor extends CommunicationAttachedBundleSession {
17
21
  /** Returns duplicate atomic consent-rule conflicts across the current bundle. */
@@ -27,6 +27,11 @@ export declare function buildDidcommPayloadFromCommunicationClaims(input: BuildD
27
27
  * one DIDComm-style payload.
28
28
  */
29
29
  export declare function getFirstCommunicationClaimsFromDidcommPayload(payload: IDecodedDidcommPayload): Record<string, unknown>;
30
+ /**
31
+ * Reads canonical communication claims from every `body.data[]` entry of one
32
+ * DIDComm-style payload.
33
+ */
34
+ export declare function getCommunicationClaimsListFromDidcommPayload(payload: IDecodedDidcommPayload): Record<string, unknown>[];
30
35
  /**
31
36
  * Decodes the attached bundle carried in `Communication.content-attachment-data`.
32
37
  */