fhir-data-utils-ts 0.3.7 → 0.6.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.
- package/.codex/skills/govern-fhir-data-utilities/SKILL.md +35 -0
- package/.codex/skills/govern-fhir-observation-components/SKILL.md +11 -0
- package/CHANGELOG.md +63 -0
- package/README.md +44 -0
- package/dist/appointment-communication-test-data.d.ts +63 -0
- package/dist/appointment-communication-test-data.js +77 -0
- package/dist/builders/department-service-graph.d.ts +32 -0
- package/dist/builders/department-service-graph.js +102 -0
- package/dist/builders/device-compliance-graph.d.ts +51 -0
- package/dist/builders/device-compliance-graph.js +115 -0
- package/dist/builders/index.d.ts +3 -0
- package/dist/builders/index.js +3 -0
- package/dist/builders/service-schedule-graph.d.ts +58 -0
- package/dist/builders/service-schedule-graph.js +149 -0
- package/dist/claims/appointment-claims.d.ts +6 -0
- package/dist/claims/appointment-claims.js +6 -0
- package/dist/claims/composition-claims.d.ts +1 -0
- package/dist/claims/composition-claims.js +1 -0
- package/dist/claims/device-metric-claims.d.ts +16 -0
- package/dist/claims/device-metric-claims.js +25 -0
- package/dist/claims/healthcare-service-claims.d.ts +32 -0
- package/dist/claims/healthcare-service-claims.js +54 -0
- package/dist/claims/index.d.ts +4 -0
- package/dist/claims/index.js +4 -0
- package/dist/claims/location-claims.d.ts +3 -0
- package/dist/claims/location-claims.js +6 -0
- package/dist/claims/organization-claims.d.ts +3 -1
- package/dist/claims/organization-claims.js +4 -1
- package/dist/claims/procedure-claims.d.ts +2 -0
- package/dist/claims/procedure-claims.js +4 -0
- package/dist/claims/regulated-authorization-claims.d.ts +17 -0
- package/dist/claims/regulated-authorization-claims.js +27 -0
- package/dist/claims/schedule-slot-claims.d.ts +45 -0
- package/dist/claims/schedule-slot-claims.js +70 -0
- package/dist/constants/fhir-resource-types.d.ts +9 -0
- package/dist/constants/fhir-resource-types.js +3 -0
- package/dist/converters/convert-appointment-communication.d.ts +14 -0
- package/dist/converters/convert-appointment-communication.js +97 -0
- package/dist/converters/convert-appointment.js +16 -7
- package/dist/converters/convert-composition.js +12 -2
- package/dist/converters/convert-device-metric.d.ts +3 -0
- package/dist/converters/convert-device-metric.js +37 -0
- package/dist/converters/convert-document-reference.js +5 -0
- package/dist/converters/convert-healthcare-service.d.ts +7 -0
- package/dist/converters/convert-healthcare-service.js +60 -0
- package/dist/converters/convert-location.d.ts +4 -0
- package/dist/converters/convert-location.js +41 -3
- package/dist/converters/convert-organization.d.ts +2 -0
- package/dist/converters/convert-organization.js +20 -3
- package/dist/converters/convert-procedure.d.ts +2 -0
- package/dist/converters/convert-procedure.js +21 -0
- package/dist/converters/convert-regulated-authorization.d.ts +3 -0
- package/dist/converters/convert-regulated-authorization.js +34 -0
- package/dist/converters/convert-schedule-slot.d.ts +9 -0
- package/dist/converters/convert-schedule-slot.js +96 -0
- package/dist/converters/convert-shared.d.ts +10 -0
- package/dist/converters/convert-shared.js +19 -0
- package/dist/converters/index.d.ts +6 -0
- package/dist/converters/index.js +6 -0
- package/dist/converters/materialize-claims-first-resource.d.ts +16 -0
- package/dist/converters/materialize-claims-first-resource.js +61 -0
- package/dist/fhir-bundle.d.ts +21 -0
- package/dist/fhir-bundle.js +74 -0
- package/dist/group-r5.d.ts +12 -0
- package/dist/group-r5.js +20 -0
- package/dist/healthcare-service-specialty-map.d.ts +32 -0
- package/dist/healthcare-service-specialty-map.js +151 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/observation-claims.d.ts +3 -0
- package/dist/observation-claims.js +3 -0
- package/dist/vital-sign-observations.d.ts +75 -1
- package/dist/vital-sign-observations.js +225 -9
- package/docs/CLINICAL_TYPED_ACCESSOR_BOUNDARY.md +44 -0
- package/docs/COMMUNICATION_BUNDLE_CONTRACT.md +61 -0
- package/docs/HEALTHCARE_SERVICE_DEPARTMENT_CATALOG.md +190 -0
- package/docs/UHC_FHIR_UTILS_MIGRATION.md +20 -1
- package/docs/VITAL_SIGN_DAILY_DOCUMENT.md +79 -0
- package/package.json +5 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
2
|
// File: src/convert/convert-organization.ts
|
|
3
3
|
import { OrganizationClaim } from '../claims/organization-claims.js';
|
|
4
|
-
import { codingFromValue, codingToValue, referenceToValue } from './convert-shared.js';
|
|
4
|
+
import { codingFromValue, codingToValue, identifierFromValue, identifierToValue, referenceToValue } from './convert-shared.js';
|
|
5
5
|
function splitCsv(value) {
|
|
6
6
|
return String(value || '')
|
|
7
7
|
.split(',')
|
|
@@ -11,7 +11,7 @@ function splitCsv(value) {
|
|
|
11
11
|
export function organizationFlatToFhirR4(claims) {
|
|
12
12
|
return {
|
|
13
13
|
resourceType: 'Organization',
|
|
14
|
-
identifier: claims[OrganizationClaim.Identifier] ? [
|
|
14
|
+
identifier: claims[OrganizationClaim.Identifier] ? [identifierFromValue(claims[OrganizationClaim.Identifier])] : undefined,
|
|
15
15
|
active: claims[OrganizationClaim.Active] === undefined ? undefined : claims[OrganizationClaim.Active] === 'true',
|
|
16
16
|
type: claims[OrganizationClaim.Type] ? [{ coding: codingFromValue(claims[OrganizationClaim.Type]) }] : undefined,
|
|
17
17
|
name: claims[OrganizationClaim.Name],
|
|
@@ -27,7 +27,7 @@ export function organizationFhirR4ToFlat(resource) {
|
|
|
27
27
|
?.map((item) => item?.value)
|
|
28
28
|
.filter((item) => Boolean(item));
|
|
29
29
|
return {
|
|
30
|
-
[OrganizationClaim.Identifier]: resource.identifier?.[0]
|
|
30
|
+
[OrganizationClaim.Identifier]: identifierToValue(resource.identifier?.[0]),
|
|
31
31
|
[OrganizationClaim.Active]: resource.active === undefined ? undefined : String(resource.active),
|
|
32
32
|
[OrganizationClaim.Type]: codingToValue(resource.type?.[0]?.coding?.[0]),
|
|
33
33
|
[OrganizationClaim.Name]: resource.name,
|
|
@@ -37,3 +37,20 @@ export function organizationFhirR4ToFlat(resource) {
|
|
|
37
37
|
[OrganizationClaim.Address]: resource.address?.[0]?.text,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
+
/** Materializes canonical Organization claims as native FHIR R5. */
|
|
41
|
+
export function organizationFlatToFhirR5(claims) {
|
|
42
|
+
const identifier = identifierFromValue(claims[OrganizationClaim.Identifier]);
|
|
43
|
+
const telecom = splitCsv(claims[OrganizationClaim.Telecom]).map((value) => ({ value }));
|
|
44
|
+
const address = claims[OrganizationClaim.Address] ? [{ text: claims[OrganizationClaim.Address] }] : [];
|
|
45
|
+
return {
|
|
46
|
+
resourceType: 'Organization',
|
|
47
|
+
identifier: identifier ? [identifier] : undefined,
|
|
48
|
+
active: claims[OrganizationClaim.Active] === undefined ? undefined : claims[OrganizationClaim.Active] === 'true',
|
|
49
|
+
type: claims[OrganizationClaim.Type] ? [{ coding: codingFromValue(claims[OrganizationClaim.Type]) }] : undefined,
|
|
50
|
+
name: claims[OrganizationClaim.Name],
|
|
51
|
+
alias: splitCsv(claims[OrganizationClaim.Alias]),
|
|
52
|
+
description: claims[OrganizationClaim.Description],
|
|
53
|
+
partOf: claims[OrganizationClaim.PartOf] ? { reference: claims[OrganizationClaim.PartOf] } : undefined,
|
|
54
|
+
contact: telecom.length || address.length ? [{ telecom, address }] : undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { FhirResource, FlatClaims } from './convert-shared.js';
|
|
2
2
|
export declare function procedureFlatToFhirR4(claims: FlatClaims): FhirResource;
|
|
3
3
|
export declare function procedureFhirR4ToFlat(resource: FhirResource): FlatClaims;
|
|
4
|
+
/** Explicit FHIR R5 projection, including equipment calibration and inspection. */
|
|
5
|
+
export declare function procedureFlatToFhirR5(claims: FlatClaims): FhirResource;
|
|
@@ -62,3 +62,24 @@ export function procedureFhirR4ToFlat(resource) {
|
|
|
62
62
|
[ProcedureClaim.Note]: resource.note?.[0]?.text,
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
/** Explicit FHIR R5 projection, including equipment calibration and inspection. */
|
|
66
|
+
export function procedureFlatToFhirR5(claims) {
|
|
67
|
+
const resource = procedureFlatToFhirR4(claims);
|
|
68
|
+
const { performedDateTime, reasonCode, reasonReference, ...common } = resource;
|
|
69
|
+
return {
|
|
70
|
+
...common,
|
|
71
|
+
occurrenceDateTime: performedDateTime,
|
|
72
|
+
reason: reasonCode || reasonReference
|
|
73
|
+
? [
|
|
74
|
+
...(Array.isArray(reasonCode) ? reasonCode.map(concept => ({ concept })) : []),
|
|
75
|
+
...(Array.isArray(reasonReference) ? reasonReference.map(reference => ({ reference })) : []),
|
|
76
|
+
]
|
|
77
|
+
: undefined,
|
|
78
|
+
focalDevice: claims[ProcedureClaim.FocalDevice]
|
|
79
|
+
? claims[ProcedureClaim.FocalDevice].split(',').map(reference => ({ manipulated: { reference: reference.trim() } }))
|
|
80
|
+
: undefined,
|
|
81
|
+
report: claims[ProcedureClaim.Report]
|
|
82
|
+
? claims[ProcedureClaim.Report].split(',').map(reference => ({ reference: reference.trim() }))
|
|
83
|
+
: undefined,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RegulatedAuthorizationClaim } from '../claims/regulated-authorization-claims.js';
|
|
2
|
+
import { codingFromValue, codingToValue, referenceToValue } from './convert-shared.js';
|
|
3
|
+
export function regulatedAuthorizationFlatToFhirR5(claims) {
|
|
4
|
+
return {
|
|
5
|
+
resourceType: 'RegulatedAuthorization',
|
|
6
|
+
identifier: claims[RegulatedAuthorizationClaim.Identifier] ? [{ value: claims[RegulatedAuthorizationClaim.Identifier] }] : undefined,
|
|
7
|
+
subject: claims[RegulatedAuthorizationClaim.Subject] ? claims[RegulatedAuthorizationClaim.Subject].split(',').map(reference => ({ reference: reference.trim() })) : undefined,
|
|
8
|
+
type: claims[RegulatedAuthorizationClaim.Type] ? { coding: codingFromValue(claims[RegulatedAuthorizationClaim.Type]) } : undefined,
|
|
9
|
+
region: claims[RegulatedAuthorizationClaim.Region] ? [{ coding: codingFromValue(claims[RegulatedAuthorizationClaim.Region]) }] : undefined,
|
|
10
|
+
status: claims[RegulatedAuthorizationClaim.Status] ? { coding: [{ code: claims[RegulatedAuthorizationClaim.Status] }] } : undefined,
|
|
11
|
+
statusDate: claims[RegulatedAuthorizationClaim.StatusDate],
|
|
12
|
+
validityPeriod: claims[RegulatedAuthorizationClaim.ValidityStart] || claims[RegulatedAuthorizationClaim.ValidityEnd]
|
|
13
|
+
? { start: claims[RegulatedAuthorizationClaim.ValidityStart], end: claims[RegulatedAuthorizationClaim.ValidityEnd] }
|
|
14
|
+
: undefined,
|
|
15
|
+
basis: claims[RegulatedAuthorizationClaim.Basis] ? [{ coding: codingFromValue(claims[RegulatedAuthorizationClaim.Basis]) }] : undefined,
|
|
16
|
+
holder: claims[RegulatedAuthorizationClaim.Holder] ? { reference: claims[RegulatedAuthorizationClaim.Holder] } : undefined,
|
|
17
|
+
regulator: claims[RegulatedAuthorizationClaim.Regulator] ? { reference: claims[RegulatedAuthorizationClaim.Regulator] } : undefined,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function regulatedAuthorizationFhirR5ToFlat(resource) {
|
|
21
|
+
return {
|
|
22
|
+
[RegulatedAuthorizationClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
23
|
+
[RegulatedAuthorizationClaim.Subject]: Array.isArray(resource.subject) ? resource.subject.map(item => item.reference).filter(Boolean).join(',') || undefined : undefined,
|
|
24
|
+
[RegulatedAuthorizationClaim.Type]: codingToValue(resource.type?.coding?.[0]),
|
|
25
|
+
[RegulatedAuthorizationClaim.Region]: codingToValue(resource.region?.[0]?.coding?.[0]),
|
|
26
|
+
[RegulatedAuthorizationClaim.Status]: resource.status?.coding?.[0]?.code,
|
|
27
|
+
[RegulatedAuthorizationClaim.StatusDate]: resource.statusDate,
|
|
28
|
+
[RegulatedAuthorizationClaim.ValidityStart]: resource.validityPeriod?.start,
|
|
29
|
+
[RegulatedAuthorizationClaim.ValidityEnd]: resource.validityPeriod?.end,
|
|
30
|
+
[RegulatedAuthorizationClaim.Basis]: codingToValue(resource.basis?.[0]?.coding?.[0]),
|
|
31
|
+
[RegulatedAuthorizationClaim.Holder]: referenceToValue(resource.holder),
|
|
32
|
+
[RegulatedAuthorizationClaim.Regulator]: referenceToValue(resource.regulator),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FhirResource, FlatClaims } from './convert-shared.js';
|
|
2
|
+
/** Materializes canonical Schedule claims as native FHIR R5. */
|
|
3
|
+
export declare function scheduleFlatToFhirR5(claims: FlatClaims): FhirResource;
|
|
4
|
+
/** Extracts official Schedule search claims plus required materialization fields. */
|
|
5
|
+
export declare function scheduleFhirR5ToFlat(resource: FhirResource): FlatClaims;
|
|
6
|
+
/** Materializes canonical Slot claims as native FHIR R5. */
|
|
7
|
+
export declare function slotFlatToFhirR5(claims: FlatClaims): FhirResource;
|
|
8
|
+
/** Extracts official Slot search claims plus required materialization fields. */
|
|
9
|
+
export declare function slotFhirR5ToFlat(resource: FhirResource): FlatClaims;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
import { ScheduleClaim, SlotClaim } from '../claims/schedule-slot-claims.js';
|
|
3
|
+
import { codingListFromCsv, codingListToCsv, identifierFromValue, identifierToValue, referenceListToCsv, referenceToValue, } from './convert-shared.js';
|
|
4
|
+
const splitCsv = (value) => String(value || '').split(',').map(item => item.trim()).filter(Boolean);
|
|
5
|
+
const referencesFromCsv = (value) => {
|
|
6
|
+
const values = splitCsv(value);
|
|
7
|
+
return values.length ? values.map(reference => ({ reference })) : undefined;
|
|
8
|
+
};
|
|
9
|
+
const conceptsFromCsv = (value) => {
|
|
10
|
+
const codings = codingListFromCsv(value);
|
|
11
|
+
return codings?.map(coding => ({ coding: [coding] }));
|
|
12
|
+
};
|
|
13
|
+
const conceptsToCsv = (value) => codingListToCsv((Array.isArray(value) ? value : []).flatMap(item => item && typeof item === 'object' && Array.isArray(item.coding)
|
|
14
|
+
? item.coding ?? []
|
|
15
|
+
: []));
|
|
16
|
+
const codeableReferencesFromClaims = (concepts, references) => {
|
|
17
|
+
const conceptList = conceptsFromCsv(concepts) ?? [];
|
|
18
|
+
const referenceList = referencesFromCsv(references) ?? [];
|
|
19
|
+
const length = Math.max(conceptList.length, referenceList.length);
|
|
20
|
+
if (!length)
|
|
21
|
+
return undefined;
|
|
22
|
+
return Array.from({ length }, (_, index) => ({
|
|
23
|
+
...(conceptList[index] ? { concept: conceptList[index] } : {}),
|
|
24
|
+
...(referenceList[index] ? { reference: referenceList[index] } : {}),
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
const conceptsFromCodeableReferences = (value) => conceptsToCsv((Array.isArray(value) ? value : []).map(item => item?.concept));
|
|
28
|
+
const referencesFromCodeableReferences = (value) => referenceListToCsv((Array.isArray(value) ? value : []).map(item => item?.reference ?? {}));
|
|
29
|
+
/** Materializes canonical Schedule claims as native FHIR R5. */
|
|
30
|
+
export function scheduleFlatToFhirR5(claims) {
|
|
31
|
+
return {
|
|
32
|
+
resourceType: 'Schedule',
|
|
33
|
+
identifier: claims[ScheduleClaim.Identifier] ? [identifierFromValue(claims[ScheduleClaim.Identifier])] : undefined,
|
|
34
|
+
active: claims[ScheduleClaim.Active] === undefined ? undefined : claims[ScheduleClaim.Active] === 'true',
|
|
35
|
+
serviceCategory: conceptsFromCsv(claims[ScheduleClaim.ServiceCategory]),
|
|
36
|
+
serviceType: codeableReferencesFromClaims(claims[ScheduleClaim.ServiceType], claims[ScheduleClaim.ServiceTypeReference]),
|
|
37
|
+
specialty: conceptsFromCsv(claims[ScheduleClaim.Specialty]),
|
|
38
|
+
name: claims[ScheduleClaim.Name],
|
|
39
|
+
actor: referencesFromCsv(claims[ScheduleClaim.Actor]),
|
|
40
|
+
planningHorizon: claims[ScheduleClaim.PlanningHorizonStart] || claims[ScheduleClaim.PlanningHorizonEnd]
|
|
41
|
+
? { start: claims[ScheduleClaim.PlanningHorizonStart], end: claims[ScheduleClaim.PlanningHorizonEnd] }
|
|
42
|
+
: undefined,
|
|
43
|
+
comment: claims[ScheduleClaim.Comment],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Extracts official Schedule search claims plus required materialization fields. */
|
|
47
|
+
export function scheduleFhirR5ToFlat(resource) {
|
|
48
|
+
const planningHorizon = resource.planningHorizon;
|
|
49
|
+
return {
|
|
50
|
+
[ScheduleClaim.Identifier]: identifierToValue(resource.identifier?.[0]),
|
|
51
|
+
[ScheduleClaim.Active]: resource.active === undefined ? undefined : String(resource.active),
|
|
52
|
+
[ScheduleClaim.ServiceCategory]: conceptsToCsv(resource.serviceCategory),
|
|
53
|
+
[ScheduleClaim.ServiceType]: conceptsFromCodeableReferences(resource.serviceType),
|
|
54
|
+
[ScheduleClaim.ServiceTypeReference]: referencesFromCodeableReferences(resource.serviceType),
|
|
55
|
+
[ScheduleClaim.Specialty]: conceptsToCsv(resource.specialty),
|
|
56
|
+
[ScheduleClaim.Name]: resource.name,
|
|
57
|
+
[ScheduleClaim.Actor]: referenceListToCsv(resource.actor),
|
|
58
|
+
[ScheduleClaim.PlanningHorizonStart]: planningHorizon?.start,
|
|
59
|
+
[ScheduleClaim.PlanningHorizonEnd]: planningHorizon?.end,
|
|
60
|
+
[ScheduleClaim.Comment]: resource.comment,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Materializes canonical Slot claims as native FHIR R5. */
|
|
64
|
+
export function slotFlatToFhirR5(claims) {
|
|
65
|
+
return {
|
|
66
|
+
resourceType: 'Slot',
|
|
67
|
+
identifier: claims[SlotClaim.Identifier] ? [identifierFromValue(claims[SlotClaim.Identifier])] : undefined,
|
|
68
|
+
serviceCategory: conceptsFromCsv(claims[SlotClaim.ServiceCategory]),
|
|
69
|
+
serviceType: codeableReferencesFromClaims(claims[SlotClaim.ServiceType], claims[SlotClaim.ServiceTypeReference]),
|
|
70
|
+
specialty: conceptsFromCsv(claims[SlotClaim.Specialty]),
|
|
71
|
+
appointmentType: conceptsFromCsv(claims[SlotClaim.AppointmentType]),
|
|
72
|
+
schedule: claims[SlotClaim.Schedule] ? { reference: claims[SlotClaim.Schedule] } : undefined,
|
|
73
|
+
status: claims[SlotClaim.Status],
|
|
74
|
+
start: claims[SlotClaim.Start],
|
|
75
|
+
end: claims[SlotClaim.End],
|
|
76
|
+
overbooked: claims[SlotClaim.Overbooked] === undefined ? undefined : claims[SlotClaim.Overbooked] === 'true',
|
|
77
|
+
comment: claims[SlotClaim.Comment],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Extracts official Slot search claims plus required materialization fields. */
|
|
81
|
+
export function slotFhirR5ToFlat(resource) {
|
|
82
|
+
return {
|
|
83
|
+
[SlotClaim.Identifier]: identifierToValue(resource.identifier?.[0]),
|
|
84
|
+
[SlotClaim.ServiceCategory]: conceptsToCsv(resource.serviceCategory),
|
|
85
|
+
[SlotClaim.ServiceType]: conceptsFromCodeableReferences(resource.serviceType),
|
|
86
|
+
[SlotClaim.ServiceTypeReference]: referencesFromCodeableReferences(resource.serviceType),
|
|
87
|
+
[SlotClaim.Specialty]: conceptsToCsv(resource.specialty),
|
|
88
|
+
[SlotClaim.AppointmentType]: conceptsToCsv(resource.appointmentType),
|
|
89
|
+
[SlotClaim.Schedule]: referenceToValue(resource.schedule),
|
|
90
|
+
[SlotClaim.Status]: resource.status,
|
|
91
|
+
[SlotClaim.Start]: resource.start,
|
|
92
|
+
[SlotClaim.End]: resource.end,
|
|
93
|
+
[SlotClaim.Overbooked]: resource.overbooked === undefined ? undefined : String(resource.overbooked),
|
|
94
|
+
[SlotClaim.Comment]: resource.comment,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -15,6 +15,16 @@ export declare function codingToValue(coding?: {
|
|
|
15
15
|
system?: string;
|
|
16
16
|
code?: string;
|
|
17
17
|
}): string | undefined;
|
|
18
|
+
/** Materializes one canonical FHIR token as an Identifier without losing its system. */
|
|
19
|
+
export declare function identifierFromValue(value?: string): {
|
|
20
|
+
system?: string;
|
|
21
|
+
value: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
/** Extracts one Identifier as the canonical `system|value` token used by search claims. */
|
|
24
|
+
export declare function identifierToValue(identifier?: {
|
|
25
|
+
system?: string;
|
|
26
|
+
value?: string;
|
|
27
|
+
}): string | undefined;
|
|
18
28
|
export declare function referenceToValue(reference?: {
|
|
19
29
|
reference?: string;
|
|
20
30
|
}): string | undefined;
|
|
@@ -25,6 +25,25 @@ export function codingToValue(coding) {
|
|
|
25
25
|
return undefined;
|
|
26
26
|
return coding.system ? `${coding.system}|${coding.code}` : coding.code;
|
|
27
27
|
}
|
|
28
|
+
/** Materializes one canonical FHIR token as an Identifier without losing its system. */
|
|
29
|
+
export function identifierFromValue(value) {
|
|
30
|
+
if (!value)
|
|
31
|
+
return undefined;
|
|
32
|
+
const separator = value.indexOf('|');
|
|
33
|
+
if (separator < 0)
|
|
34
|
+
return { value };
|
|
35
|
+
const system = value.slice(0, separator).trim();
|
|
36
|
+
const identifierValue = value.slice(separator + 1).trim();
|
|
37
|
+
if (!identifierValue)
|
|
38
|
+
return undefined;
|
|
39
|
+
return system ? { system, value: identifierValue } : { value: identifierValue };
|
|
40
|
+
}
|
|
41
|
+
/** Extracts one Identifier as the canonical `system|value` token used by search claims. */
|
|
42
|
+
export function identifierToValue(identifier) {
|
|
43
|
+
if (!identifier?.value)
|
|
44
|
+
return undefined;
|
|
45
|
+
return identifier.system ? `${identifier.system}|${identifier.value}` : identifier.value;
|
|
46
|
+
}
|
|
28
47
|
export function referenceToValue(reference) {
|
|
29
48
|
return reference?.reference;
|
|
30
49
|
}
|
|
@@ -2,6 +2,7 @@ export * from './convert-shared.js';
|
|
|
2
2
|
export * from './convert-allergy-intolerance.js';
|
|
3
3
|
export * from './convert-appointment-response.js';
|
|
4
4
|
export * from './convert-appointment.js';
|
|
5
|
+
export * from './convert-appointment-communication.js';
|
|
5
6
|
export * from './convert-care-plan.js';
|
|
6
7
|
export * from './convert-clinical-impression.js';
|
|
7
8
|
export * from './convert-communication-request.js';
|
|
@@ -11,6 +12,7 @@ export * from './convert-condition.js';
|
|
|
11
12
|
export * from './convert-coverage.js';
|
|
12
13
|
export * from './convert-device-use-statement.js';
|
|
13
14
|
export * from './convert-device.js';
|
|
15
|
+
export * from './convert-device-metric.js';
|
|
14
16
|
export * from './convert-diagnostic-report.js';
|
|
15
17
|
export * from './convert-document-reference.js';
|
|
16
18
|
export * from './convert-encounter.js';
|
|
@@ -18,10 +20,14 @@ export * from './convert-flag.js';
|
|
|
18
20
|
export * from './convert-immunization.js';
|
|
19
21
|
export * from './convert-imaging-study.js';
|
|
20
22
|
export * from './convert-location.js';
|
|
23
|
+
export * from './convert-healthcare-service.js';
|
|
21
24
|
export * from './convert-medication-statement.js';
|
|
22
25
|
export * from './convert-observation.js';
|
|
23
26
|
export * from './convert-organization.js';
|
|
24
27
|
export * from './convert-practitioner-role.js';
|
|
25
28
|
export * from './convert-procedure.js';
|
|
29
|
+
export * from './convert-regulated-authorization.js';
|
|
26
30
|
export * from './convert-related-person.js';
|
|
27
31
|
export * from './convert-service-request.js';
|
|
32
|
+
export * from './convert-schedule-slot.js';
|
|
33
|
+
export * from './materialize-claims-first-resource.js';
|
package/dist/converters/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from './convert-shared.js';
|
|
|
2
2
|
export * from './convert-allergy-intolerance.js';
|
|
3
3
|
export * from './convert-appointment-response.js';
|
|
4
4
|
export * from './convert-appointment.js';
|
|
5
|
+
export * from './convert-appointment-communication.js';
|
|
5
6
|
export * from './convert-care-plan.js';
|
|
6
7
|
export * from './convert-clinical-impression.js';
|
|
7
8
|
export * from './convert-communication-request.js';
|
|
@@ -11,6 +12,7 @@ export * from './convert-condition.js';
|
|
|
11
12
|
export * from './convert-coverage.js';
|
|
12
13
|
export * from './convert-device-use-statement.js';
|
|
13
14
|
export * from './convert-device.js';
|
|
15
|
+
export * from './convert-device-metric.js';
|
|
14
16
|
export * from './convert-diagnostic-report.js';
|
|
15
17
|
export * from './convert-document-reference.js';
|
|
16
18
|
export * from './convert-encounter.js';
|
|
@@ -18,10 +20,14 @@ export * from './convert-flag.js';
|
|
|
18
20
|
export * from './convert-immunization.js';
|
|
19
21
|
export * from './convert-imaging-study.js';
|
|
20
22
|
export * from './convert-location.js';
|
|
23
|
+
export * from './convert-healthcare-service.js';
|
|
21
24
|
export * from './convert-medication-statement.js';
|
|
22
25
|
export * from './convert-observation.js';
|
|
23
26
|
export * from './convert-organization.js';
|
|
24
27
|
export * from './convert-practitioner-role.js';
|
|
25
28
|
export * from './convert-procedure.js';
|
|
29
|
+
export * from './convert-regulated-authorization.js';
|
|
26
30
|
export * from './convert-related-person.js';
|
|
27
31
|
export * from './convert-service-request.js';
|
|
32
|
+
export * from './convert-schedule-slot.js';
|
|
33
|
+
export * from './materialize-claims-first-resource.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FhirResource } from '../fhir-types.js';
|
|
2
|
+
export type ClaimsFirstFhirResource = Readonly<{
|
|
3
|
+
resourceType: 'Organization' | 'HealthcareService' | 'Location' | 'Schedule' | 'Slot' | 'DeviceMetric' | 'Procedure' | 'RegulatedAuthorization' | 'DocumentReference';
|
|
4
|
+
id: string;
|
|
5
|
+
meta: Readonly<{
|
|
6
|
+
claims: Readonly<Record<string, unknown>>;
|
|
7
|
+
}>;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Materializes native FHIR R5 only at an explicit adapter boundary.
|
|
11
|
+
*
|
|
12
|
+
* Canonical persistence remains `{ resourceType, id, meta: { claims } }`.
|
|
13
|
+
* Nested native fields are rejected so a materialized representation can never
|
|
14
|
+
* silently become a second business source of truth.
|
|
15
|
+
*/
|
|
16
|
+
export declare function materializeClaimsFirstResourceToFhirR5(input: unknown): FhirResource;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { healthcareServiceFlatToFhirR5 } from './convert-healthcare-service.js';
|
|
2
|
+
import { locationFlatToFhirR5 } from './convert-location.js';
|
|
3
|
+
import { organizationFlatToFhirR5 } from './convert-organization.js';
|
|
4
|
+
import { scheduleFlatToFhirR5, slotFlatToFhirR5 } from './convert-schedule-slot.js';
|
|
5
|
+
import { deviceMetricFlatToFhirR5 } from './convert-device-metric.js';
|
|
6
|
+
import { procedureFlatToFhirR5 } from './convert-procedure.js';
|
|
7
|
+
import { regulatedAuthorizationFlatToFhirR5 } from './convert-regulated-authorization.js';
|
|
8
|
+
import { documentReferenceFlatToFhirR4 } from './convert-document-reference.js';
|
|
9
|
+
const materializers = Object.freeze({
|
|
10
|
+
Organization: organizationFlatToFhirR5,
|
|
11
|
+
HealthcareService: healthcareServiceFlatToFhirR5,
|
|
12
|
+
Location: locationFlatToFhirR5,
|
|
13
|
+
Schedule: scheduleFlatToFhirR5,
|
|
14
|
+
Slot: slotFlatToFhirR5,
|
|
15
|
+
DeviceMetric: deviceMetricFlatToFhirR5,
|
|
16
|
+
Procedure: procedureFlatToFhirR5,
|
|
17
|
+
RegulatedAuthorization: regulatedAuthorizationFlatToFhirR5,
|
|
18
|
+
DocumentReference: documentReferenceFlatToFhirR4,
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Materializes native FHIR R5 only at an explicit adapter boundary.
|
|
22
|
+
*
|
|
23
|
+
* Canonical persistence remains `{ resourceType, id, meta: { claims } }`.
|
|
24
|
+
* Nested native fields are rejected so a materialized representation can never
|
|
25
|
+
* silently become a second business source of truth.
|
|
26
|
+
*/
|
|
27
|
+
export function materializeClaimsFirstResourceToFhirR5(input) {
|
|
28
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
29
|
+
throw new TypeError('claims_first_resource_invalid');
|
|
30
|
+
}
|
|
31
|
+
const resource = input;
|
|
32
|
+
if (Object.keys(resource).some(key => !['resourceType', 'id', 'meta'].includes(key))) {
|
|
33
|
+
throw new TypeError('claims_first_resource_nested_fhir_forbidden');
|
|
34
|
+
}
|
|
35
|
+
const resourceType = String(resource.resourceType || '');
|
|
36
|
+
const materializer = materializers[resourceType];
|
|
37
|
+
if (!materializer)
|
|
38
|
+
throw new TypeError('claims_first_resource_type_unsupported');
|
|
39
|
+
const id = String(resource.id || '').trim();
|
|
40
|
+
if (!id)
|
|
41
|
+
throw new TypeError('claims_first_resource_id_required');
|
|
42
|
+
const meta = resource.meta;
|
|
43
|
+
if (!meta || typeof meta !== 'object' || Array.isArray(meta))
|
|
44
|
+
throw new TypeError('claims_first_resource_claims_required');
|
|
45
|
+
if (Object.keys(meta).some(key => key !== 'claims'))
|
|
46
|
+
throw new TypeError('claims_first_resource_nested_fhir_forbidden');
|
|
47
|
+
const rawClaims = meta.claims;
|
|
48
|
+
if (!rawClaims || typeof rawClaims !== 'object' || Array.isArray(rawClaims)) {
|
|
49
|
+
throw new TypeError('claims_first_resource_claims_required');
|
|
50
|
+
}
|
|
51
|
+
const claims = {};
|
|
52
|
+
for (const [claim, rawValue] of Object.entries(rawClaims)) {
|
|
53
|
+
const values = (Array.isArray(rawValue) ? rawValue : [rawValue])
|
|
54
|
+
.map(value => String(value).trim())
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
if (!values.length)
|
|
57
|
+
throw new TypeError('claims_first_resource_claim_value_invalid');
|
|
58
|
+
claims[claim] = values.join(',');
|
|
59
|
+
}
|
|
60
|
+
return Object.freeze({ ...materializer(claims), id });
|
|
61
|
+
}
|
package/dist/fhir-bundle.d.ts
CHANGED
|
@@ -7,3 +7,24 @@ export declare function walkBundleResources(bundle: FhirBundle): readonly FhirRe
|
|
|
7
7
|
export declare function classifyBundleResources(bundle: FhirBundle): ReadonlyMap<string, readonly FhirResource[]>;
|
|
8
8
|
/** Resolves `ResourceType/id`, `urn:uuid:*`, an entry fullUrl, or a bare resource id. */
|
|
9
9
|
export declare function findBundleResourceByReference(bundle: FhirBundle, reference: string): FhirResource | undefined;
|
|
10
|
+
export type CommunicationInnerBundleType = 'document' | 'batch' | 'collection';
|
|
11
|
+
export type CommunicationBundlePayload = Readonly<{
|
|
12
|
+
communication: FhirResource;
|
|
13
|
+
attachment: Readonly<{
|
|
14
|
+
contentType: 'application/fhir+json';
|
|
15
|
+
data: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
}>;
|
|
18
|
+
bundle: FhirBundle;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Bundle Reader boundary used by every secure Communication flow.
|
|
22
|
+
*
|
|
23
|
+
* The outer operational payload is always a batch Bundle containing
|
|
24
|
+
* Communication entries. Each Communication carries exactly one FHIR JSON
|
|
25
|
+
* attachment whose decoded resource is an inner document, batch or collection
|
|
26
|
+
* Bundle. Individual clinical resources and arbitrary file MIME types are not
|
|
27
|
+
* accepted directly at this boundary; files belong to DocumentReference
|
|
28
|
+
* entries inside the inner Bundle and must be edited through Bundle Editor.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readCommunicationBundlePayloads(input: unknown): readonly CommunicationBundlePayload[];
|
package/dist/fhir-bundle.js
CHANGED
|
@@ -41,3 +41,77 @@ export function findBundleResourceByReference(bundle, reference) {
|
|
|
41
41
|
: [undefined, target.startsWith('urn:uuid:') ? target.slice('urn:uuid:'.length) : target];
|
|
42
42
|
return readBundleResources(bundle).find(resource => resource.id === id && (!resourceType || resource.resourceType === resourceType));
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Bundle Reader boundary used by every secure Communication flow.
|
|
46
|
+
*
|
|
47
|
+
* The outer operational payload is always a batch Bundle containing
|
|
48
|
+
* Communication entries. Each Communication carries exactly one FHIR JSON
|
|
49
|
+
* attachment whose decoded resource is an inner document, batch or collection
|
|
50
|
+
* Bundle. Individual clinical resources and arbitrary file MIME types are not
|
|
51
|
+
* accepted directly at this boundary; files belong to DocumentReference
|
|
52
|
+
* entries inside the inner Bundle and must be edited through Bundle Editor.
|
|
53
|
+
*/
|
|
54
|
+
export function readCommunicationBundlePayloads(input) {
|
|
55
|
+
const outerBatch = requireBundle(input);
|
|
56
|
+
if (outerBatch.type !== 'batch')
|
|
57
|
+
throw new TypeError('fhir_batch_bundle_required');
|
|
58
|
+
validateBatchRequests(outerBatch);
|
|
59
|
+
const payloads = readBundleResources(outerBatch)
|
|
60
|
+
.filter(resource => resource.resourceType === 'Communication')
|
|
61
|
+
.map(communication => {
|
|
62
|
+
const attachment = firstFhirBundleAttachment(communication);
|
|
63
|
+
let decoded;
|
|
64
|
+
try {
|
|
65
|
+
decoded = JSON.parse(decodeBase64Utf8(attachment.data));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
throw new TypeError('fhir_bundle_attachment_invalid');
|
|
69
|
+
}
|
|
70
|
+
const bundle = requireBundle(decoded);
|
|
71
|
+
if (!['document', 'batch', 'collection'].includes(String(bundle.type)))
|
|
72
|
+
throw new TypeError('fhir_inner_bundle_type_invalid');
|
|
73
|
+
validateInnerBundle(bundle);
|
|
74
|
+
return Object.freeze({ communication, attachment, bundle });
|
|
75
|
+
});
|
|
76
|
+
if (!payloads.length)
|
|
77
|
+
throw new TypeError('fhir_communication_required');
|
|
78
|
+
return Object.freeze(payloads);
|
|
79
|
+
}
|
|
80
|
+
function requireBundle(value) {
|
|
81
|
+
if (!value || typeof value !== 'object' || Array.isArray(value) || value.resourceType !== 'Bundle')
|
|
82
|
+
throw new TypeError('fhir_bundle_required');
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
function firstFhirBundleAttachment(resource) {
|
|
86
|
+
const payload = Array.isArray(resource.payload) ? resource.payload : [];
|
|
87
|
+
if (payload.length !== 1)
|
|
88
|
+
throw new TypeError('fhir_single_bundle_attachment_required');
|
|
89
|
+
const item = payload[0];
|
|
90
|
+
if (!item || typeof item !== 'object' || Array.isArray(item))
|
|
91
|
+
throw new TypeError('fhir_bundle_attachment_required');
|
|
92
|
+
const attachment = item.contentAttachment;
|
|
93
|
+
if (!attachment || typeof attachment !== 'object' || Array.isArray(attachment))
|
|
94
|
+
throw new TypeError('fhir_bundle_attachment_required');
|
|
95
|
+
const candidate = attachment;
|
|
96
|
+
if (candidate.contentType !== 'application/fhir+json' || typeof candidate.data !== 'string' || !candidate.data) {
|
|
97
|
+
throw new TypeError('fhir_bundle_attachment_required');
|
|
98
|
+
}
|
|
99
|
+
return Object.freeze({ contentType: candidate.contentType, data: candidate.data, ...(typeof candidate.title === 'string' ? { title: candidate.title } : {}) });
|
|
100
|
+
}
|
|
101
|
+
function decodeBase64Utf8(value) {
|
|
102
|
+
const binary = globalThis.atob(value);
|
|
103
|
+
return new TextDecoder().decode(Uint8Array.from(binary, character => character.charCodeAt(0)));
|
|
104
|
+
}
|
|
105
|
+
function validateInnerBundle(bundle) {
|
|
106
|
+
if (bundle.type === 'document' && readBundleResources(bundle)[0]?.resourceType !== 'Composition') {
|
|
107
|
+
throw new TypeError('fhir_document_composition_first_required');
|
|
108
|
+
}
|
|
109
|
+
if (bundle.type === 'batch')
|
|
110
|
+
validateBatchRequests(bundle);
|
|
111
|
+
}
|
|
112
|
+
function validateBatchRequests(bundle) {
|
|
113
|
+
for (const entry of bundle.entry ?? []) {
|
|
114
|
+
if (!entry.request?.method || !entry.request.url)
|
|
115
|
+
throw new TypeError('fhir_batch_request_required');
|
|
116
|
+
}
|
|
117
|
+
}
|
package/dist/group-r5.d.ts
CHANGED
|
@@ -89,6 +89,12 @@ export type GroupR5ResearchTeam = Readonly<Record<string, unknown> & {
|
|
|
89
89
|
membership: 'enumerated';
|
|
90
90
|
member: readonly GroupPractitionerRoleMember[];
|
|
91
91
|
}>;
|
|
92
|
+
export type GroupR5ProfessionalServiceTeam = GroupR5ResearchTeam & Readonly<{
|
|
93
|
+
managingEntity: Readonly<{
|
|
94
|
+
reference: `Organization/${string}`;
|
|
95
|
+
type: 'Organization';
|
|
96
|
+
}>;
|
|
97
|
+
}>;
|
|
92
98
|
/**
|
|
93
99
|
* Normalizes the members used by an enumerated professional research team.
|
|
94
100
|
* Every entity is a native PractitionerRole reference; a Practitioner or an
|
|
@@ -101,6 +107,12 @@ export declare function normalizeGroupPractitionerRoleMembers(input: unknown): r
|
|
|
101
107
|
* properties are rejected at every depth.
|
|
102
108
|
*/
|
|
103
109
|
export declare function normalizeGroupR5ResearchTeam(input: unknown): GroupR5ResearchTeam;
|
|
110
|
+
/**
|
|
111
|
+
* Normalizes a professional team assigned to one Organization department.
|
|
112
|
+
* `managingEntity` is singular in FHIR R5, so one Group cannot span several
|
|
113
|
+
* departments. Membership remains descriptive and grants no permission.
|
|
114
|
+
*/
|
|
115
|
+
export declare function normalizeGroupR5ProfessionalServiceTeam(input: unknown): GroupR5ProfessionalServiceTeam;
|
|
104
116
|
/**
|
|
105
117
|
* Projects all populated official resource-specific R5 Group SearchParameters
|
|
106
118
|
* into flat `resource.meta.claims`. A referenced characteristic is indexed by
|
package/dist/group-r5.js
CHANGED
|
@@ -131,6 +131,26 @@ export function normalizeGroupR5ResearchTeam(input) {
|
|
|
131
131
|
const member = normalizeGroupPractitionerRoleMembers(input.member);
|
|
132
132
|
return Object.freeze({ ...input, type: 'practitioner', membership: 'enumerated', member });
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Normalizes a professional team assigned to one Organization department.
|
|
136
|
+
* `managingEntity` is singular in FHIR R5, so one Group cannot span several
|
|
137
|
+
* departments. Membership remains descriptive and grants no permission.
|
|
138
|
+
*/
|
|
139
|
+
export function normalizeGroupR5ProfessionalServiceTeam(input) {
|
|
140
|
+
const team = normalizeGroupR5ResearchTeam(input);
|
|
141
|
+
const managingEntity = team.managingEntity;
|
|
142
|
+
if (!isRecord(managingEntity))
|
|
143
|
+
throw new TypeError('group_professional_service_managing_organization_invalid');
|
|
144
|
+
const reference = optionalString(managingEntity.reference);
|
|
145
|
+
const declaredType = optionalString(managingEntity.type);
|
|
146
|
+
if (!reference || !/^Organization\/[A-Za-z0-9.-]{1,64}$/.test(reference) || (declaredType && declaredType !== 'Organization')) {
|
|
147
|
+
throw new TypeError('group_professional_service_managing_organization_invalid');
|
|
148
|
+
}
|
|
149
|
+
return Object.freeze({
|
|
150
|
+
...team,
|
|
151
|
+
managingEntity: Object.freeze({ reference: reference, type: 'Organization' }),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
134
154
|
/**
|
|
135
155
|
* Projects all populated official resource-specific R5 Group SearchParameters
|
|
136
156
|
* into flat `resource.meta.claims`. A referenced characteristic is indexed by
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Candidate SNOMED CT C80 to LOINC specialty map supplied for review.
|
|
3
|
+
*
|
|
4
|
+
* This is not an official SNOMED or LOINC map. The declared relationship is
|
|
5
|
+
* preserved so consumers can automate only strict equivalence and present
|
|
6
|
+
* wider, related, inexact or unmatched rows for professional governance.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ClinicalSpecialtyMappingEquivalence: Readonly<{
|
|
9
|
+
readonly Equivalent: "equivalent";
|
|
10
|
+
readonly Wider: "wider";
|
|
11
|
+
readonly RelatedTo: "relatedto";
|
|
12
|
+
readonly Inexact: "inexact";
|
|
13
|
+
readonly Unmatched: "unmatched";
|
|
14
|
+
}>;
|
|
15
|
+
export type ClinicalSpecialtyMappingEquivalenceCode = typeof ClinicalSpecialtyMappingEquivalence[keyof typeof ClinicalSpecialtyMappingEquivalence];
|
|
16
|
+
export type ClinicalSpecialtyMapping = Readonly<{
|
|
17
|
+
snomedSystem: 'http://snomed.info/sct';
|
|
18
|
+
snomedCode: string;
|
|
19
|
+
snomedDisplay: string;
|
|
20
|
+
loincSystem?: 'http://loinc.org';
|
|
21
|
+
loincCode?: string;
|
|
22
|
+
loincDisplay?: string;
|
|
23
|
+
equivalence: ClinicalSpecialtyMappingEquivalenceCode;
|
|
24
|
+
automatic: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
export declare const SnomedC80ToLoincSpecialtyConceptMap: readonly ClinicalSpecialtyMapping[];
|
|
27
|
+
/** Returns a portable LOINC specialty only for a strict reviewed equivalence. */
|
|
28
|
+
export declare function findAutomaticLoincSpecialty(snomedCode: string): Readonly<{
|
|
29
|
+
system: 'http://loinc.org';
|
|
30
|
+
code: string;
|
|
31
|
+
display: string;
|
|
32
|
+
}> | undefined;
|