gdc-common-utils-ts 2.3.15 → 2.3.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.
Files changed (28) hide show
  1. package/dist/convert/convert-care-plan.js +12 -1
  2. package/dist/convert/convert-consent.d.ts +3 -0
  3. package/dist/convert/convert-consent.js +32 -0
  4. package/dist/convert/convert-device.js +12 -1
  5. package/dist/convert/convert-document-reference.js +20 -1
  6. package/dist/convert/convert-observation.js +15 -7
  7. package/dist/convert/convert-practitioner-role.d.ts +3 -0
  8. package/dist/convert/convert-practitioner-role.js +34 -0
  9. package/dist/convert/index.d.ts +2 -0
  10. package/dist/convert/index.js +2 -0
  11. package/dist/models/consent-rule.d.ts +2 -0
  12. package/dist/models/consent-rule.js +2 -0
  13. package/dist/models/interoperable-claims/care-plan-claims.d.ts +2 -0
  14. package/dist/models/interoperable-claims/care-plan-claims.js +4 -0
  15. package/dist/models/interoperable-claims/device-claims.d.ts +2 -0
  16. package/dist/models/interoperable-claims/device-claims.js +4 -0
  17. package/dist/models/interoperable-claims/document-reference-claims.d.ts +2 -0
  18. package/dist/models/interoperable-claims/document-reference-claims.js +4 -0
  19. package/dist/models/interoperable-claims/index.d.ts +1 -0
  20. package/dist/models/interoperable-claims/index.js +1 -0
  21. package/dist/models/interoperable-claims/practitioner-role-claims.d.ts +9 -0
  22. package/dist/models/interoperable-claims/practitioner-role-claims.js +24 -0
  23. package/dist/utils/bundle-document-builder.js +5 -1
  24. package/dist/utils/clinical-resource-converters.d.ts +8 -0
  25. package/dist/utils/clinical-resource-converters.js +12 -0
  26. package/dist/utils/clinical-resource-view.d.ts +6 -0
  27. package/dist/utils/clinical-resource-view.js +44 -1
  28. package/package.json +1 -1
@@ -4,13 +4,22 @@ import { CarePlanClaim } from '../models/interoperable-claims/care-plan-claims.j
4
4
  import { codingFromValue, codingToValue, referenceListToCsv, referenceToValue } from './convert-shared.js';
5
5
  export function carePlanFlatToFhirR4(claims) {
6
6
  const subject = claims[CarePlanClaim.Subject] ?? claims[CarePlanClaim.Patient];
7
+ const categoryCoding = codingFromValue(claims[CarePlanClaim.Category])?.map((coding) => ({
8
+ ...coding,
9
+ ...(claims[CarePlanClaim.CategoryDisplay] ? { display: claims[CarePlanClaim.CategoryDisplay] } : {}),
10
+ }));
7
11
  return {
8
12
  resourceType: 'CarePlan',
9
13
  identifier: claims[CarePlanClaim.Identifier] ? [{ value: claims[CarePlanClaim.Identifier] }] : undefined,
10
14
  status: claims[CarePlanClaim.Status],
11
15
  intent: claims[CarePlanClaim.Intent],
12
16
  subject: subject ? { reference: subject } : undefined,
13
- category: claims[CarePlanClaim.Category] ? [{ coding: codingFromValue(claims[CarePlanClaim.Category]) }] : undefined,
17
+ category: claims[CarePlanClaim.Category] || claims[CarePlanClaim.CategoryText] || claims[CarePlanClaim.CategoryDisplay]
18
+ ? [{
19
+ ...(categoryCoding ? { coding: categoryCoding } : {}),
20
+ ...(claims[CarePlanClaim.CategoryText] ? { text: claims[CarePlanClaim.CategoryText] } : {}),
21
+ }]
22
+ : undefined,
14
23
  created: claims[CarePlanClaim.Date],
15
24
  note: claims[CarePlanClaim.Note] ? [{ text: claims[CarePlanClaim.Note] }] : undefined,
16
25
  basedOn: claims[CarePlanClaim.BasedOn] ? claims[CarePlanClaim.BasedOn].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
@@ -41,6 +50,8 @@ export function carePlanFhirR4ToFlat(resource) {
41
50
  [CarePlanClaim.BasedOn]: referenceListToCsv(resource.basedOn),
42
51
  [CarePlanClaim.CareTeam]: referenceListToCsv(resource.careTeam),
43
52
  [CarePlanClaim.Category]: codingToValue(resource.category?.[0]?.coding?.[0]),
53
+ [CarePlanClaim.CategoryText]: resource.category?.[0]?.text,
54
+ [CarePlanClaim.CategoryDisplay]: resource.category?.[0]?.coding?.[0]?.display,
44
55
  [CarePlanClaim.Condition]: referenceListToCsv(resource.addresses),
45
56
  [CarePlanClaim.Date]: resource.created || period?.start,
46
57
  [CarePlanClaim.Encounter]: referenceToValue(resource.encounter),
@@ -0,0 +1,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared';
2
+ export declare function consentFhirR4ToFlat(resource: FhirResource, context?: string): FlatClaims;
3
+ export declare function consentFlatToFhirR4(claims: FlatClaims): FhirResource;
@@ -0,0 +1,32 @@
1
+ // Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ import { ClaimConsent } from '../models/consent-rule.js';
3
+ import { codingFromValue, codingToValue, fhirResourceToFlatClaims, flatClaimsToFhirResource, } from './convert-shared.js';
4
+ export function consentFhirR4ToFlat(resource, context = 'org.hl7.fhir.r4') {
5
+ const concept = resource.category?.[0];
6
+ return {
7
+ ...fhirResourceToFlatClaims(resource, context),
8
+ [ClaimConsent.category]: codingToValue(concept?.coding?.[0]),
9
+ [ClaimConsent.categoryText]: concept?.text,
10
+ [ClaimConsent.categoryDisplay]: concept?.coding?.[0]?.display,
11
+ };
12
+ }
13
+ export function consentFlatToFhirR4(claims) {
14
+ const structuralClaims = { ...claims };
15
+ delete structuralClaims[ClaimConsent.category];
16
+ delete structuralClaims[ClaimConsent.categoryText];
17
+ delete structuralClaims[ClaimConsent.categoryDisplay];
18
+ const resource = flatClaimsToFhirResource(structuralClaims);
19
+ const coding = codingFromValue(claims[ClaimConsent.category])?.map((item) => ({
20
+ ...item,
21
+ ...(claims[ClaimConsent.categoryDisplay]
22
+ ? { display: claims[ClaimConsent.categoryDisplay] }
23
+ : {}),
24
+ }));
25
+ if (coding || claims[ClaimConsent.categoryText]) {
26
+ resource.category = [{
27
+ ...(coding ? { coding } : {}),
28
+ ...(claims[ClaimConsent.categoryText] ? { text: claims[ClaimConsent.categoryText] } : {}),
29
+ }];
30
+ }
31
+ return resource;
32
+ }
@@ -3,6 +3,10 @@
3
3
  import { DeviceClaim } from '../models/interoperable-claims/device-claims.js';
4
4
  import { codingFromValue, codingToValue, referenceToValue } from './convert-shared.js';
5
5
  export function deviceFlatToFhirR4(claims) {
6
+ const typeCoding = codingFromValue(claims[DeviceClaim.Type])?.map((coding) => ({
7
+ ...coding,
8
+ ...(claims[DeviceClaim.TypeDisplay] ? { display: claims[DeviceClaim.TypeDisplay] } : {}),
9
+ }));
6
10
  return {
7
11
  resourceType: 'Device',
8
12
  identifier: claims[DeviceClaim.Identifier] ? [{ value: claims[DeviceClaim.Identifier] }] : undefined,
@@ -14,7 +18,12 @@ export function deviceFlatToFhirR4(claims) {
14
18
  patient: claims[DeviceClaim.Patient] ? { reference: claims[DeviceClaim.Patient] } : undefined,
15
19
  serialNumber: claims[DeviceClaim.SerialNumber],
16
20
  status: claims[DeviceClaim.Status],
17
- type: claims[DeviceClaim.Type] ? { coding: codingFromValue(claims[DeviceClaim.Type]) } : undefined,
21
+ type: claims[DeviceClaim.Type] || claims[DeviceClaim.TypeText] || claims[DeviceClaim.TypeDisplay]
22
+ ? {
23
+ ...(typeCoding ? { coding: typeCoding } : {}),
24
+ ...(claims[DeviceClaim.TypeText] ? { text: claims[DeviceClaim.TypeText] } : {}),
25
+ }
26
+ : undefined,
18
27
  udiCarrier: claims[DeviceClaim.UdiCarrier] ? [{ carrierHRF: claims[DeviceClaim.UdiCarrier] }] : undefined,
19
28
  url: claims[DeviceClaim.Url],
20
29
  };
@@ -31,6 +40,8 @@ export function deviceFhirR4ToFlat(resource) {
31
40
  [DeviceClaim.SerialNumber]: resource.serialNumber,
32
41
  [DeviceClaim.Status]: resource.status,
33
42
  [DeviceClaim.Type]: codingToValue(resource.type?.coding?.[0]),
43
+ [DeviceClaim.TypeText]: resource.type?.text,
44
+ [DeviceClaim.TypeDisplay]: resource.type?.coding?.[0]?.display,
34
45
  [DeviceClaim.UdiCarrier]: resource.udiCarrier?.[0]?.carrierHRF,
35
46
  [DeviceClaim.Url]: resource.url,
36
47
  };
@@ -1,14 +1,29 @@
1
1
  // Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
2
  // File: src/utils/convert-document-reference.ts
3
3
  import { DocumentReferenceClaim } from '../models/interoperable-claims/document-reference-claims.js';
4
- import { requireClaim } from './convert-shared.js';
4
+ import { codingFromValue, codingToValue, requireClaim } from './convert-shared.js';
5
5
  export function documentReferenceFlatToFhirR4(claims) {
6
6
  const subject = requireClaim(claims, DocumentReferenceClaim.Subject);
7
+ const typeCoding = codingFromValue(claims[DocumentReferenceClaim.Type])?.map((coding) => ({
8
+ ...coding,
9
+ ...(claims[DocumentReferenceClaim.TypeDisplay] ? { display: claims[DocumentReferenceClaim.TypeDisplay] } : {}),
10
+ }));
7
11
  return {
8
12
  resourceType: 'DocumentReference',
9
13
  identifier: claims[DocumentReferenceClaim.Identifier] ? [{ value: claims[DocumentReferenceClaim.Identifier] }] : undefined,
10
14
  subject: { reference: subject },
11
15
  description: claims[DocumentReferenceClaim.Description],
16
+ category: claims[DocumentReferenceClaim.Category]
17
+ ? [{ coding: codingFromValue(claims[DocumentReferenceClaim.Category]) }]
18
+ : undefined,
19
+ type: claims[DocumentReferenceClaim.Type]
20
+ || claims[DocumentReferenceClaim.TypeText]
21
+ || claims[DocumentReferenceClaim.TypeDisplay]
22
+ ? {
23
+ ...(typeCoding ? { coding: typeCoding } : {}),
24
+ ...(claims[DocumentReferenceClaim.TypeText] ? { text: claims[DocumentReferenceClaim.TypeText] } : {}),
25
+ }
26
+ : undefined,
12
27
  date: claims[DocumentReferenceClaim.Date],
13
28
  content: [{ attachment: {
14
29
  contentType: claims[DocumentReferenceClaim.ContentType],
@@ -25,6 +40,10 @@ export function documentReferenceFhirR4ToFlat(resource) {
25
40
  [DocumentReferenceClaim.Identifier]: resource.identifier?.[0]?.value,
26
41
  [DocumentReferenceClaim.Subject]: resource.subject?.reference,
27
42
  [DocumentReferenceClaim.Description]: resource.description,
43
+ [DocumentReferenceClaim.Category]: codingToValue(resource.category?.[0]?.coding?.[0]),
44
+ [DocumentReferenceClaim.Type]: codingToValue(resource.type?.coding?.[0]),
45
+ [DocumentReferenceClaim.TypeText]: resource.type?.text,
46
+ [DocumentReferenceClaim.TypeDisplay]: resource.type?.coding?.[0]?.display,
28
47
  [DocumentReferenceClaim.Date]: resource.date,
29
48
  [DocumentReferenceClaim.ContentType]: attachment?.contentType,
30
49
  [DocumentReferenceClaim.ContentData]: attachment?.data,
@@ -23,6 +23,16 @@ export function observationFromFlatToFhirR4(claims) {
23
23
  code: claims[ObservationClaim.ValueConceptValue],
24
24
  });
25
25
  const valueQuantityCoding = codingFromValue(claims[ObservationClaim.ValueQuantityUnit])?.[0];
26
+ const codeCoding = codingFromValue(codeToken)?.map((coding) => ({
27
+ ...coding,
28
+ ...(claims[ObservationClaim.CodeDisplay] ? { display: claims[ObservationClaim.CodeDisplay] } : {}),
29
+ }));
30
+ const valueConceptCoding = codingFromValue(valueConceptToken)?.map((coding) => ({
31
+ ...coding,
32
+ ...(claims[ObservationClaim.ValueConceptDisplay]
33
+ ? { display: claims[ObservationClaim.ValueConceptDisplay] }
34
+ : {}),
35
+ }));
26
36
  return {
27
37
  resourceType: 'Observation',
28
38
  identifier: claims[ObservationClaim.Identifier] ? [{ value: claims[ObservationClaim.Identifier] }] : undefined,
@@ -30,10 +40,8 @@ export function observationFromFlatToFhirR4(claims) {
30
40
  category: claims[ObservationClaim.Category] ? claims[ObservationClaim.Category].split(',').map((value) => ({ coding: codingFromValue(value.trim()) })) : undefined,
31
41
  code: codeToken
32
42
  ? {
33
- coding: codingFromValue(codeToken),
34
- ...(claims[ObservationClaim.CodeText] || claims[ObservationClaim.CodeDisplay]
35
- ? { text: claims[ObservationClaim.CodeText] ?? claims[ObservationClaim.CodeDisplay] }
36
- : {}),
43
+ coding: codeCoding,
44
+ ...(claims[ObservationClaim.CodeText] ? { text: claims[ObservationClaim.CodeText] } : {}),
37
45
  }
38
46
  : undefined,
39
47
  subject: subject ? { reference: subject } : undefined,
@@ -42,9 +50,9 @@ export function observationFromFlatToFhirR4(claims) {
42
50
  performer: claims[ObservationClaim.Performer] ? claims[ObservationClaim.Performer].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
43
51
  valueCodeableConcept: valueConceptToken
44
52
  ? {
45
- coding: codingFromValue(valueConceptToken),
46
- ...(claims[ObservationClaim.ValueConceptText] || claims[ObservationClaim.ValueConceptDisplay]
47
- ? { text: claims[ObservationClaim.ValueConceptText] ?? claims[ObservationClaim.ValueConceptDisplay] }
53
+ coding: valueConceptCoding,
54
+ ...(claims[ObservationClaim.ValueConceptText]
55
+ ? { text: claims[ObservationClaim.ValueConceptText] }
48
56
  : {}),
49
57
  }
50
58
  : undefined,
@@ -0,0 +1,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared';
2
+ export declare function practitionerRoleFhirR4ToFlat(resource: FhirResource, context?: string): FlatClaims;
3
+ export declare function practitionerRoleFlatToFhirR4(claims: FlatClaims): FhirResource;
@@ -0,0 +1,34 @@
1
+ // Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ import { PractitionerRoleClaim } from '../models/interoperable-claims/practitioner-role-claims.js';
3
+ import { codingFromValue, codingToValue, fhirResourceToFlatClaims, flatClaimsToFhirResource, } from './convert-shared.js';
4
+ export function practitionerRoleFhirR4ToFlat(resource, context = 'org.hl7.fhir.r4') {
5
+ const concept = resource.code?.[0];
6
+ return {
7
+ ...fhirResourceToFlatClaims(resource, context),
8
+ [PractitionerRoleClaim.Code]: codingToValue(concept?.coding?.[0]),
9
+ [PractitionerRoleClaim.CodeText]: concept?.text,
10
+ [PractitionerRoleClaim.CodeDisplay]: concept?.coding?.[0]?.display,
11
+ };
12
+ }
13
+ export function practitionerRoleFlatToFhirR4(claims) {
14
+ const structuralClaims = { ...claims };
15
+ delete structuralClaims[PractitionerRoleClaim.Code];
16
+ delete structuralClaims[PractitionerRoleClaim.CodeText];
17
+ delete structuralClaims[PractitionerRoleClaim.CodeDisplay];
18
+ const resource = flatClaimsToFhirResource(structuralClaims);
19
+ const coding = codingFromValue(claims[PractitionerRoleClaim.Code])?.map((item) => ({
20
+ ...item,
21
+ ...(claims[PractitionerRoleClaim.CodeDisplay]
22
+ ? { display: claims[PractitionerRoleClaim.CodeDisplay] }
23
+ : {}),
24
+ }));
25
+ if (coding || claims[PractitionerRoleClaim.CodeText]) {
26
+ resource.code = [{
27
+ ...(coding ? { coding } : {}),
28
+ ...(claims[PractitionerRoleClaim.CodeText]
29
+ ? { text: claims[PractitionerRoleClaim.CodeText] }
30
+ : {}),
31
+ }];
32
+ }
33
+ return resource;
34
+ }
@@ -20,4 +20,6 @@ export * from './convert-encounter';
20
20
  export * from './convert-related-person';
21
21
  export * from './convert-coverage';
22
22
  export * from './convert-clinical-impression';
23
+ export * from './convert-consent';
24
+ export * from './convert-practitioner-role';
23
25
  export * from './schemaorg-to-gaia-x';
@@ -20,4 +20,6 @@ export * from './convert-encounter.js';
20
20
  export * from './convert-related-person.js';
21
21
  export * from './convert-coverage.js';
22
22
  export * from './convert-clinical-impression.js';
23
+ export * from './convert-consent.js';
24
+ export * from './convert-practitioner-role.js';
23
25
  export * from './schemaorg-to-gaia-x.js';
@@ -2,6 +2,8 @@ export declare enum ClaimConsent {
2
2
  'decision' = "Consent.decision",
3
3
  'action' = "Consent.action",
4
4
  'category' = "Consent.category",
5
+ 'categoryText' = "Consent.category-text",
6
+ 'categoryDisplay' = "Consent.category-display",
5
7
  'resourceType' = "Consent.resourceType",
6
8
  'subject' = "Consent.subject",
7
9
  'actorIdentifier' = "Consent.actor-identifier",
@@ -4,6 +4,8 @@ export var ClaimConsent;
4
4
  ClaimConsent["decision"] = "Consent.decision";
5
5
  ClaimConsent["action"] = "Consent.action";
6
6
  ClaimConsent["category"] = "Consent.category";
7
+ ClaimConsent["categoryText"] = "Consent.category-text";
8
+ ClaimConsent["categoryDisplay"] = "Consent.category-display";
7
9
  ClaimConsent["resourceType"] = "Consent.resourceType";
8
10
  ClaimConsent["subject"] = "Consent.subject";
9
11
  ClaimConsent["actorIdentifier"] = "Consent.actor-identifier";
@@ -6,6 +6,8 @@ export declare const CarePlanClaim: {
6
6
  readonly BasedOn: "CarePlan.based-on";
7
7
  readonly CareTeam: "CarePlan.care-team";
8
8
  readonly Category: "CarePlan.category";
9
+ readonly CategoryText: "CarePlan.category-text";
10
+ readonly CategoryDisplay: "CarePlan.category-display";
9
11
  readonly Condition: "CarePlan.condition";
10
12
  readonly Date: "CarePlan.date";
11
13
  readonly Encounter: "CarePlan.encounter";
@@ -7,6 +7,8 @@ export const CarePlanClaim = {
7
7
  BasedOn: 'CarePlan.based-on',
8
8
  CareTeam: 'CarePlan.care-team',
9
9
  Category: 'CarePlan.category',
10
+ CategoryText: 'CarePlan.category-text',
11
+ CategoryDisplay: 'CarePlan.category-display',
10
12
  Condition: 'CarePlan.condition',
11
13
  Date: 'CarePlan.date',
12
14
  Encounter: 'CarePlan.encounter',
@@ -28,6 +30,8 @@ export const CarePlanClaimSpecs = [
28
30
  { key: CarePlanClaim.BasedOn, meaning: 'Based-on reference.', example: 'CarePlan/plan-parent' },
29
31
  { key: CarePlanClaim.CareTeam, meaning: 'Care team references (CSV).', example: 'CareTeam/team-1' },
30
32
  { key: CarePlanClaim.Category, meaning: 'Care plan category token.', example: 'http://snomed.info/sct|736373009' },
33
+ { key: CarePlanClaim.CategoryText, meaning: 'Local-language care plan category label.', example: 'Plan de control de peso' },
34
+ { key: CarePlanClaim.CategoryDisplay, meaning: 'Canonical/international care plan category display.', example: 'Weight management plan' },
31
35
  { key: CarePlanClaim.Condition, meaning: 'Condition references (CSV).', example: 'Condition/cond-1' },
32
36
  { key: CarePlanClaim.Date, meaning: 'Care plan creation or period date.', example: '2026-06-01T10:00:00Z' },
33
37
  { key: CarePlanClaim.Encounter, meaning: 'Encounter reference.', example: 'Encounter/enc-1' },
@@ -10,6 +10,8 @@ export declare const DeviceClaim: {
10
10
  readonly SerialNumber: "Device.serial-number";
11
11
  readonly Status: "Device.status";
12
12
  readonly Type: "Device.type";
13
+ readonly TypeText: "Device.type-text";
14
+ readonly TypeDisplay: "Device.type-display";
13
15
  readonly UdiCarrier: "Device.udi-carrier";
14
16
  readonly Url: "Device.url";
15
17
  readonly Note: "Device.note";
@@ -11,6 +11,8 @@ export const DeviceClaim = {
11
11
  SerialNumber: 'Device.serial-number',
12
12
  Status: 'Device.status',
13
13
  Type: 'Device.type',
14
+ TypeText: 'Device.type-text',
15
+ TypeDisplay: 'Device.type-display',
14
16
  UdiCarrier: 'Device.udi-carrier',
15
17
  Url: 'Device.url',
16
18
  Note: 'Device.note',
@@ -26,6 +28,8 @@ export const DeviceClaimSpecs = [
26
28
  { key: DeviceClaim.SerialNumber, meaning: 'Serial number.', example: 'SN-12345' },
27
29
  { key: DeviceClaim.Status, meaning: 'Device status.', example: 'active' },
28
30
  { key: DeviceClaim.Type, meaning: 'Device type token.', example: 'http://snomed.info/sct|706172005' },
31
+ { key: DeviceClaim.TypeText, meaning: 'Local-language device type label.', example: 'Bomba de insulina' },
32
+ { key: DeviceClaim.TypeDisplay, meaning: 'Canonical/international device type display.', example: 'Insulin pump' },
29
33
  { key: DeviceClaim.UdiCarrier, meaning: 'UDI carrier string.', example: '(01)09504000059118(17)220101(10)ABCD1234' },
30
34
  { key: DeviceClaim.Url, meaning: 'Canonical URL.', example: 'https://device.example.org/catalogue/123' },
31
35
  { key: DeviceClaim.Note, meaning: 'Clinical note text.', example: 'Patient-owned continuous glucose monitor.' },
@@ -22,6 +22,8 @@ export declare const DocumentReferenceClaim: {
22
22
  readonly Relation: "DocumentReference.relation";
23
23
  readonly Subject: "DocumentReference.subject";
24
24
  readonly Type: "DocumentReference.type";
25
+ readonly TypeText: "DocumentReference.type-text";
26
+ readonly TypeDisplay: "DocumentReference.type-display";
25
27
  readonly UserSelected: "DocumentReference.user-selected";
26
28
  };
27
29
  export type DocumentReferenceClaimKey = typeof DocumentReferenceClaim[keyof typeof DocumentReferenceClaim];
@@ -24,6 +24,8 @@ export const DocumentReferenceClaim = {
24
24
  Relation: 'DocumentReference.relation',
25
25
  Subject: 'DocumentReference.subject',
26
26
  Type: 'DocumentReference.type',
27
+ TypeText: 'DocumentReference.type-text',
28
+ TypeDisplay: 'DocumentReference.type-display',
27
29
  UserSelected: 'DocumentReference.user-selected',
28
30
  };
29
31
  /**
@@ -53,6 +55,8 @@ export const DocumentReferenceClaimSpecs = [
53
55
  { key: DocumentReferenceClaim.Relation, meaning: 'Relation type to related document.', example: 'appends' },
54
56
  { key: DocumentReferenceClaim.Subject, meaning: 'URN for the section in the individual index.', example: 'urn:uhix:section:vitals' },
55
57
  { key: DocumentReferenceClaim.Type, meaning: 'Lower-level, sector-specific type.', example: 'http://hl7.org/fhir/ValueSet/c80-doc-typecodes|34133-9' },
58
+ { key: DocumentReferenceClaim.TypeText, meaning: 'Local-language document type label.', example: 'Resumen clínico' },
59
+ { key: DocumentReferenceClaim.TypeDisplay, meaning: 'Canonical/international document type display.', example: 'Patient summary Document' },
56
60
  { key: DocumentReferenceClaim.UserSelected, meaning: 'Custom provenance flag telling whether the document was explicitly created or selected by the end user/controller.', example: 'true' },
57
61
  ];
58
62
  /**
@@ -13,6 +13,7 @@ export * from './device-claims';
13
13
  export * from './observation-claims';
14
14
  export * from './immunization-claims';
15
15
  export * from './procedure-claims';
16
+ export * from './practitioner-role-claims';
16
17
  export * from './care-plan-claims';
17
18
  export * from './flag-claims';
18
19
  export * from './appointment-claims';
@@ -15,6 +15,7 @@ export * from './device-claims.js';
15
15
  export * from './observation-claims.js';
16
16
  export * from './immunization-claims.js';
17
17
  export * from './procedure-claims.js';
18
+ export * from './practitioner-role-claims.js';
18
19
  export * from './care-plan-claims.js';
19
20
  export * from './flag-claims.js';
20
21
  export * from './appointment-claims.js';
@@ -0,0 +1,9 @@
1
+ import type { ClaimSpec } from './types';
2
+ /** Canonical claims used to preserve the primary coded PractitionerRole label. */
3
+ export declare const PractitionerRoleClaim: {
4
+ readonly Code: "PractitionerRole.code";
5
+ readonly CodeText: "PractitionerRole.code-text";
6
+ readonly CodeDisplay: "PractitionerRole.code-display";
7
+ };
8
+ export type PractitionerRoleClaimKey = typeof PractitionerRoleClaim[keyof typeof PractitionerRoleClaim];
9
+ export declare const PractitionerRoleClaimSpecs: ClaimSpec[];
@@ -0,0 +1,24 @@
1
+ // Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ /** Canonical claims used to preserve the primary coded PractitionerRole label. */
3
+ export const PractitionerRoleClaim = {
4
+ Code: 'PractitionerRole.code',
5
+ CodeText: 'PractitionerRole.code-text',
6
+ CodeDisplay: 'PractitionerRole.code-display',
7
+ };
8
+ export const PractitionerRoleClaimSpecs = [
9
+ {
10
+ key: PractitionerRoleClaim.Code,
11
+ meaning: 'Primary practitioner role code token.',
12
+ example: 'http://snomed.info/sct|158965000',
13
+ },
14
+ {
15
+ key: PractitionerRoleClaim.CodeText,
16
+ meaning: 'Local-language practitioner role label.',
17
+ example: 'Médico',
18
+ },
19
+ {
20
+ key: PractitionerRoleClaim.CodeDisplay,
21
+ meaning: 'Canonical/international practitioner role display.',
22
+ example: 'Doctor',
23
+ },
24
+ ];
@@ -5,7 +5,7 @@ import { ConditionClaim } from '../models/interoperable-claims/condition-claims.
5
5
  import { DiagnosticReportClaim } from '../models/interoperable-claims/diagnostic-report-claims.js';
6
6
  import { MedicationStatementClaim } from '../models/interoperable-claims/medication-statement-claims.js';
7
7
  import { ClaimConsent } from '../models/consent-rule.js';
8
- import { allergyIntoleranceFlatToFhirR4, appointmentFlatToFhirR4, carePlanFlatToFhirR4, clinicalImpressionFlatToFhirR4, compositionFlatToFhirR4, conditionFlatToFhirR4, convertFhirResourceToClaims, coverageFlatToFhirR4, deviceFlatToFhirR4, documentReferenceFlatToFhirR4, diagnosticReportFlatToFhirR4, encounterFlatToFhirR4, flagFlatToFhirR4, flatClaimsToFhirResource, immunizationFlatToFhirR4, locationFlatToFhirR4, medicationStatementFlatToFhirR4, observationFromFlatToFhirR4, organizationFlatToFhirR4, procedureFlatToFhirR4, relatedPersonFlatToFhirR4, } from './clinical-resource-converters.js';
8
+ import { allergyIntoleranceFlatToFhirR4, appointmentFlatToFhirR4, carePlanFlatToFhirR4, clinicalImpressionFlatToFhirR4, compositionFlatToFhirR4, conditionFlatToFhirR4, consentFlatToFhirR4, convertFhirResourceToClaims, coverageFlatToFhirR4, deviceFlatToFhirR4, documentReferenceFlatToFhirR4, diagnosticReportFlatToFhirR4, encounterFlatToFhirR4, flagFlatToFhirR4, flatClaimsToFhirResource, immunizationFlatToFhirR4, locationFlatToFhirR4, medicationStatementFlatToFhirR4, observationFromFlatToFhirR4, organizationFlatToFhirR4, procedureFlatToFhirR4, practitionerRoleFlatToFhirR4, relatedPersonFlatToFhirR4, } from './clinical-resource-converters.js';
9
9
  function asTrimmedString(value) {
10
10
  if (value === undefined || value === null)
11
11
  return '';
@@ -378,6 +378,10 @@ function convertClaimsToFhirResourceByType(flatClaims, resourceType) {
378
378
  return coverageFlatToFhirR4(flatClaims);
379
379
  case 'ClinicalImpression':
380
380
  return clinicalImpressionFlatToFhirR4(flatClaims);
381
+ case ResourceTypesFhirR4.Consent:
382
+ return consentFlatToFhirR4(flatClaims);
383
+ case ResourceTypesFhirR4.PractitionerRole:
384
+ return practitionerRoleFlatToFhirR4(flatClaims);
381
385
  default:
382
386
  return flatClaimsToFhirResource(flatClaims);
383
387
  }
@@ -21,6 +21,8 @@ export { encounterFlatToFhirR4, encounterFhirR4ToFlat, } from '../convert/conver
21
21
  export { relatedPersonFlatToFhirR4, relatedPersonFhirR4ToFlat, } from '../convert/convert-related-person';
22
22
  export { coverageFlatToFhirR4, coverageFhirR4ToFlat, } from '../convert/convert-coverage';
23
23
  export { clinicalImpressionFlatToFhirR4, clinicalImpressionFhirR4ToFlat, } from '../convert/convert-clinical-impression';
24
+ export { consentFlatToFhirR4, consentFhirR4ToFlat, } from '../convert/convert-consent';
25
+ export { practitionerRoleFlatToFhirR4, practitionerRoleFhirR4ToFlat, } from '../convert/convert-practitioner-role';
24
26
  import type { FhirResource, FlatClaims } from '../convert/convert-shared';
25
27
  import { medicationStatementFhirR4ToFlat, medicationStatementFlatToFhirR4 } from '../convert/convert-medication-statement';
26
28
  import { allergyIntoleranceFhirR4ToFlat, allergyIntoleranceFlatToFhirR4 } from '../convert/convert-allergy-intolerance';
@@ -43,6 +45,8 @@ import { encounterFhirR4ToFlat, encounterFlatToFhirR4 } from '../convert/convert
43
45
  import { relatedPersonFhirR4ToFlat, relatedPersonFlatToFhirR4 } from '../convert/convert-related-person';
44
46
  import { coverageFhirR4ToFlat, coverageFlatToFhirR4 } from '../convert/convert-coverage';
45
47
  import { clinicalImpressionFhirR4ToFlat, clinicalImpressionFlatToFhirR4 } from '../convert/convert-clinical-impression';
48
+ import { consentFhirR4ToFlat, consentFlatToFhirR4 } from '../convert/convert-consent';
49
+ import { practitionerRoleFhirR4ToFlat, practitionerRoleFlatToFhirR4 } from '../convert/convert-practitioner-role';
46
50
  export declare const medicationStatementFlatToFhir: typeof medicationStatementFlatToFhirR4;
47
51
  export declare const medicationStatementFhirToFlat: typeof medicationStatementFhirR4ToFlat;
48
52
  export declare const allergyIntoleranceFlatToFhir: typeof allergyIntoleranceFlatToFhirR4;
@@ -85,6 +89,10 @@ export declare const coverageFlatToFhir: typeof coverageFlatToFhirR4;
85
89
  export declare const coverageFhirToFlat: typeof coverageFhirR4ToFlat;
86
90
  export declare const clinicalImpressionFlatToFhir: typeof clinicalImpressionFlatToFhirR4;
87
91
  export declare const clinicalImpressionFhirToFlat: typeof clinicalImpressionFhirR4ToFlat;
92
+ export declare const consentFlatToFhir: typeof consentFlatToFhirR4;
93
+ export declare const consentFhirToFlat: typeof consentFhirR4ToFlat;
94
+ export declare const practitionerRoleFlatToFhir: typeof practitionerRoleFlatToFhirR4;
95
+ export declare const practitionerRoleFhirToFlat: typeof practitionerRoleFhirR4ToFlat;
88
96
  /**
89
97
  * Converts a FHIR resource to the semantic flat-claims contract when a
90
98
  * resource-specific converter exists. Unsupported resources fall back to the
@@ -22,6 +22,8 @@ export { encounterFlatToFhirR4, encounterFhirR4ToFlat, } from '../convert/conver
22
22
  export { relatedPersonFlatToFhirR4, relatedPersonFhirR4ToFlat, } from '../convert/convert-related-person.js';
23
23
  export { coverageFlatToFhirR4, coverageFhirR4ToFlat, } from '../convert/convert-coverage.js';
24
24
  export { clinicalImpressionFlatToFhirR4, clinicalImpressionFhirR4ToFlat, } from '../convert/convert-clinical-impression.js';
25
+ export { consentFlatToFhirR4, consentFhirR4ToFlat, } from '../convert/convert-consent.js';
26
+ export { practitionerRoleFlatToFhirR4, practitionerRoleFhirR4ToFlat, } from '../convert/convert-practitioner-role.js';
25
27
  import { fhirResourceToFlatClaims } from '../convert/convert-shared.js';
26
28
  import { medicationStatementFhirR4ToFlat, medicationStatementFlatToFhirR4 } from '../convert/convert-medication-statement.js';
27
29
  import { allergyIntoleranceFhirR4ToFlat, allergyIntoleranceFlatToFhirR4 } from '../convert/convert-allergy-intolerance.js';
@@ -44,6 +46,8 @@ import { encounterFhirR4ToFlat, encounterFlatToFhirR4 } from '../convert/convert
44
46
  import { relatedPersonFhirR4ToFlat, relatedPersonFlatToFhirR4 } from '../convert/convert-related-person.js';
45
47
  import { coverageFhirR4ToFlat, coverageFlatToFhirR4 } from '../convert/convert-coverage.js';
46
48
  import { clinicalImpressionFhirR4ToFlat, clinicalImpressionFlatToFhirR4 } from '../convert/convert-clinical-impression.js';
49
+ import { consentFhirR4ToFlat, consentFlatToFhirR4 } from '../convert/convert-consent.js';
50
+ import { practitionerRoleFhirR4ToFlat, practitionerRoleFlatToFhirR4 } from '../convert/convert-practitioner-role.js';
47
51
  export const medicationStatementFlatToFhir = medicationStatementFlatToFhirR4;
48
52
  export const medicationStatementFhirToFlat = medicationStatementFhirR4ToFlat;
49
53
  export const allergyIntoleranceFlatToFhir = allergyIntoleranceFlatToFhirR4;
@@ -86,6 +90,10 @@ export const coverageFlatToFhir = coverageFlatToFhirR4;
86
90
  export const coverageFhirToFlat = coverageFhirR4ToFlat;
87
91
  export const clinicalImpressionFlatToFhir = clinicalImpressionFlatToFhirR4;
88
92
  export const clinicalImpressionFhirToFlat = clinicalImpressionFhirR4ToFlat;
93
+ export const consentFlatToFhir = consentFlatToFhirR4;
94
+ export const consentFhirToFlat = consentFhirR4ToFlat;
95
+ export const practitionerRoleFlatToFhir = practitionerRoleFlatToFhirR4;
96
+ export const practitionerRoleFhirToFlat = practitionerRoleFhirR4ToFlat;
89
97
  /**
90
98
  * Converts a FHIR resource to the semantic flat-claims contract when a
91
99
  * resource-specific converter exists. Unsupported resources fall back to the
@@ -142,6 +150,10 @@ function convertFhirResourceToClaimsByType(resource, context) {
142
150
  return coverageFhirR4ToFlat(resource);
143
151
  case 'ClinicalImpression':
144
152
  return clinicalImpressionFhirR4ToFlat(resource);
153
+ case 'Consent':
154
+ return consentFhirR4ToFlat(resource, context);
155
+ case 'PractitionerRole':
156
+ return practitionerRoleFhirR4ToFlat(resource, context);
145
157
  default:
146
158
  return fhirResourceToFlatClaims(resource, context);
147
159
  }
@@ -37,6 +37,12 @@ export type ClinicalResourceDisplayOptions = Readonly<{
37
37
  /**
38
38
  * Product terminology lookup keyed by canonical `system|code`.
39
39
  *
40
+ * The token is resolved claims-first from the resource-specific primary
41
+ * coded claim (for example `Observation.code`, `Immunization.vaccine-code`
42
+ * or `Device.type`). Other coded claims on the resource are never guessed.
43
+ * This keeps translations available when a `$summary` readback retains
44
+ * `Coding.display` but omits native coding identity fields.
45
+ *
40
46
  * Return `undefined` when the product has no translation so the shared
41
47
  * reader can fall back to the international `Coding.display`.
42
48
  */
@@ -3,10 +3,17 @@ import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
3
3
  import { ClaimConsent } from '../models/consent-rule.js';
4
4
  import { AllergyIntoleranceClaim, AllergyIntoleranceClaimsFhirApi, } from '../models/interoperable-claims/allergy-intolerance-claims.js';
5
5
  import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
6
+ import { CarePlanClaim } from '../models/interoperable-claims/care-plan-claims.js';
6
7
  import { ConditionClaim, ConditionClaimsFhirApi, } from '../models/interoperable-claims/condition-claims.js';
8
+ import { DeviceClaim } from '../models/interoperable-claims/device-claims.js';
9
+ import { DiagnosticReportClaim } from '../models/interoperable-claims/diagnostic-report-claims.js';
10
+ import { DocumentReferenceClaim } from '../models/interoperable-claims/document-reference-claims.js';
11
+ import { FlagClaim } from '../models/interoperable-claims/flag-claims.js';
7
12
  import { ImmunizationClaim } from '../models/interoperable-claims/immunization-claims.js';
8
13
  import { MedicationStatementClaim, MedicationStatementClaimsFhirApi, MedicationStatementClaimsFhirApiExtended, } from '../models/interoperable-claims/medication-statement-claims.js';
9
14
  import { ObservationClaim } from '../models/interoperable-claims/observation-claims.js';
15
+ import { PractitionerRoleClaim } from '../models/interoperable-claims/practitioner-role-claims.js';
16
+ import { ProcedureClaim } from '../models/interoperable-claims/procedure-claims.js';
10
17
  const CONSENT_ACTOR_REFERENCE_CLAIM = 'Consent.actor-reference';
11
18
  const GENERIC_CREATOR_CLAIM_SUFFIX = '.creator';
12
19
  const GENERIC_PERFORMER_CLAIM_SUFFIX = '.performer';
@@ -315,7 +322,8 @@ function resolveTitle(resourceType, claims, resource, options = {}) {
315
322
  resource,
316
323
  options,
317
324
  concept: primaryConcept,
318
- token: resolveCodeableConceptToken(primaryConcept),
325
+ token: resolvePrimaryClaimCodeToken(resourceType, claims)
326
+ || resolveCodeableConceptToken(primaryConcept),
319
327
  }) || resolveFhirResourceTitle(resourceType, resource) || resourceType;
320
328
  }
321
329
  function resolveLocalizedCodedTitle(input) {
@@ -613,6 +621,41 @@ function findBySuffix(claims, keySuffix) {
613
621
  function findFirstClaimBySuffixes(claims, suffixes) {
614
622
  return firstDefinedText(suffixes.map((suffix) => findBySuffix(claims, suffix)));
615
623
  }
624
+ function resolvePrimaryClaimCodeToken(resourceType, claims) {
625
+ const claimKey = resourceType === ResourceTypesFhirR4.Observation
626
+ ? ObservationClaim.Code
627
+ : resourceType === ResourceTypesFhirR4.Flag
628
+ ? FlagClaim.Code
629
+ : resourceType === ResourceTypesFhirR4.Immunization
630
+ ? ImmunizationClaim.VaccineCode
631
+ : resourceType === ResourceTypesFhirR4.Procedure
632
+ ? ProcedureClaim.Code
633
+ : resourceType === ResourceTypesFhirR4.DiagnosticReport
634
+ ? DiagnosticReportClaim.Code
635
+ : resourceType === ResourceTypesFhirR4.Device
636
+ ? DeviceClaim.Type
637
+ : resourceType === ResourceTypesFhirR4.DocumentReference
638
+ ? DocumentReferenceClaim.Type
639
+ : resourceType === ResourceTypesFhirR4.CarePlan
640
+ ? CarePlanClaim.Category
641
+ : resourceType === ResourceTypesFhirR4.PractitionerRole
642
+ ? PractitionerRoleClaim.Code
643
+ : undefined;
644
+ const token = claimKey ? readCanonicalClaimValue(claims, claimKey) : undefined;
645
+ if (token)
646
+ return splitCsv(token)[0];
647
+ if (resourceType === ResourceTypesFhirR4.Observation) {
648
+ const system = readCanonicalClaimValue(claims, ObservationClaim.CodeSystem);
649
+ const code = readCanonicalClaimValue(claims, ObservationClaim.CodeValue);
650
+ if (code)
651
+ return system ? `${system}|${code}` : code;
652
+ }
653
+ return undefined;
654
+ }
655
+ function readCanonicalClaimValue(claims, claimKey) {
656
+ return trimValue(claims[claimKey])
657
+ || findBySuffix(claims, `.${claimKey.toLowerCase()}`);
658
+ }
616
659
  function resolveResourceCodeText(resource) {
617
660
  return trimValue(asRecord(resource?.code).text) || undefined;
618
661
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.3.15",
3
+ "version": "2.3.17",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },