fhir-data-utils-ts 0.2.4 → 0.3.1
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 +58 -0
- package/.codex/skills/govern-fhir-data-utilities/agents/openai.yaml +4 -0
- package/.codex/skills/govern-fhir-observation-components/SKILL.md +18 -0
- package/CHANGELOG.md +30 -0
- package/README.md +39 -0
- package/dist/builders/immunization-graph.d.ts +36 -0
- package/dist/builders/immunization-graph.js +115 -0
- package/dist/builders/immunization-reminders.d.ts +35 -0
- package/dist/builders/immunization-reminders.js +104 -0
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.js +2 -0
- package/dist/claim-helpers/claim-list-helpers.d.ts +21 -0
- package/dist/claim-helpers/claim-list-helpers.js +54 -0
- package/dist/claim-helpers/claims-helpers-allergy-intolerance.d.ts +18 -0
- package/dist/claim-helpers/claims-helpers-allergy-intolerance.js +65 -0
- package/dist/claim-helpers/claims-helpers-appointment-response.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-appointment-response.js +20 -0
- package/dist/claim-helpers/claims-helpers-appointment.d.ts +10 -0
- package/dist/claim-helpers/claims-helpers-appointment.js +26 -0
- package/dist/claim-helpers/claims-helpers-care-plan.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-care-plan.js +20 -0
- package/dist/claim-helpers/claims-helpers-clinical-impression.d.ts +10 -0
- package/dist/claim-helpers/claims-helpers-clinical-impression.js +26 -0
- package/dist/claim-helpers/claims-helpers-communication.d.ts +19 -0
- package/dist/claim-helpers/claims-helpers-communication.js +63 -0
- package/dist/claim-helpers/claims-helpers-composition.d.ts +12 -0
- package/dist/claim-helpers/claims-helpers-composition.js +32 -0
- package/dist/claim-helpers/claims-helpers-condition.d.ts +18 -0
- package/dist/claim-helpers/claims-helpers-condition.js +65 -0
- package/dist/claim-helpers/claims-helpers-coverage.d.ts +10 -0
- package/dist/claim-helpers/claims-helpers-coverage.js +26 -0
- package/dist/claim-helpers/claims-helpers-device-use-statement.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-device-use-statement.js +20 -0
- package/dist/claim-helpers/claims-helpers-device.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-device.js +20 -0
- package/dist/claim-helpers/claims-helpers-diagnostic-report.d.ts +16 -0
- package/dist/claim-helpers/claims-helpers-diagnostic-report.js +47 -0
- package/dist/claim-helpers/claims-helpers-document-reference.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-document-reference.js +20 -0
- package/dist/claim-helpers/claims-helpers-encounter.d.ts +10 -0
- package/dist/claim-helpers/claims-helpers-encounter.js +26 -0
- package/dist/claim-helpers/claims-helpers-flag.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-flag.js +20 -0
- package/dist/claim-helpers/claims-helpers-immunization.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-immunization.js +20 -0
- package/dist/claim-helpers/claims-helpers-location.d.ts +10 -0
- package/dist/claim-helpers/claims-helpers-location.js +26 -0
- package/dist/claim-helpers/claims-helpers-medication-statement.d.ts +96 -0
- package/dist/claim-helpers/claims-helpers-medication-statement.js +278 -0
- package/dist/claim-helpers/claims-helpers-observation.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-observation.js +20 -0
- package/dist/claim-helpers/claims-helpers-organization.d.ts +12 -0
- package/dist/claim-helpers/claims-helpers-organization.js +32 -0
- package/dist/claim-helpers/claims-helpers-procedure.d.ts +8 -0
- package/dist/claim-helpers/claims-helpers-procedure.js +20 -0
- package/dist/claim-helpers/claims-helpers-related-person.d.ts +22 -0
- package/dist/claim-helpers/claims-helpers-related-person.js +53 -0
- package/dist/claim-helpers/index.d.ts +23 -0
- package/dist/claim-helpers/index.js +23 -0
- package/dist/claims/allergy-intolerance-claims.d.ts +153 -0
- package/dist/claims/allergy-intolerance-claims.js +194 -0
- package/dist/claims/appointment-claims.d.ts +226 -0
- package/dist/claims/appointment-claims.js +218 -0
- package/dist/claims/appointment-response-claims.d.ts +63 -0
- package/dist/claims/appointment-response-claims.js +58 -0
- package/dist/claims/care-plan-claims.d.ts +37 -0
- package/dist/claims/care-plan-claims.js +59 -0
- package/dist/claims/claim-types.d.ts +9 -0
- package/dist/claims/claim-types.js +3 -0
- package/dist/claims/clinical-impression-claims.d.ts +17 -0
- package/dist/claims/clinical-impression-claims.js +30 -0
- package/dist/claims/communication-claims.d.ts +55 -0
- package/dist/claims/communication-claims.js +57 -0
- package/dist/claims/composition-claims.d.ts +27 -0
- package/dist/claims/composition-claims.js +27 -0
- package/dist/claims/condition-claims.d.ts +79 -0
- package/dist/claims/condition-claims.js +104 -0
- package/dist/claims/consent-claims.d.ts +195 -0
- package/dist/claims/consent-claims.js +74 -0
- package/dist/claims/coverage-claims.d.ts +16 -0
- package/dist/claims/coverage-claims.js +28 -0
- package/dist/claims/device-claims.d.ts +20 -0
- package/dist/claims/device-claims.js +36 -0
- package/dist/claims/device-use-statement-claims.d.ts +17 -0
- package/dist/claims/device-use-statement-claims.js +28 -0
- package/dist/claims/diagnostic-report-claims.d.ts +109 -0
- package/dist/claims/diagnostic-report-claims.js +120 -0
- package/dist/claims/document-reference-claims.d.ts +39 -0
- package/dist/claims/document-reference-claims.js +96 -0
- package/dist/claims/encounter-claims.d.ts +18 -0
- package/dist/claims/encounter-claims.js +32 -0
- package/dist/claims/flag-claims.d.ts +19 -0
- package/dist/claims/flag-claims.js +33 -0
- package/dist/claims/immunization-claims.d.ts +31 -0
- package/dist/claims/immunization-claims.js +54 -0
- package/dist/claims/immunization-recommendation-claims.d.ts +19 -0
- package/dist/claims/immunization-recommendation-claims.js +26 -0
- package/dist/claims/index.d.ts +29 -0
- package/dist/claims/index.js +29 -0
- package/dist/claims/invoice-claims.d.ts +277 -0
- package/dist/claims/invoice-claims.js +357 -0
- package/dist/claims/location-claims.d.ts +22 -0
- package/dist/claims/location-claims.js +34 -0
- package/dist/claims/medication-claims.d.ts +15 -0
- package/dist/claims/medication-claims.js +23 -0
- package/dist/claims/medication-statement-claims.d.ts +539 -0
- package/dist/claims/medication-statement-claims.js +469 -0
- package/dist/claims/organization-claims.d.ts +18 -0
- package/dist/claims/organization-claims.js +27 -0
- package/dist/claims/practitioner-role-claims.d.ts +18 -0
- package/dist/claims/practitioner-role-claims.js +33 -0
- package/dist/claims/procedure-claims.d.ts +24 -0
- package/dist/claims/procedure-claims.js +44 -0
- package/dist/claims/related-person-claims.d.ts +30 -0
- package/dist/claims/related-person-claims.js +44 -0
- package/dist/claims/research-subject-claims.d.ts +4 -0
- package/dist/claims/research-subject-claims.js +4 -0
- package/dist/claims/task-claims.d.ts +61 -0
- package/dist/claims/task-claims.js +64 -0
- package/dist/clinical-terminology.d.ts +73 -0
- package/dist/clinical-terminology.js +77 -0
- package/dist/constants/clinical-statuses.d.ts +102 -0
- package/dist/constants/clinical-statuses.js +93 -0
- package/dist/constants/fhir-code-systems.d.ts +15 -0
- package/dist/constants/fhir-code-systems.js +15 -0
- package/dist/constants/fhir-resource-types.d.ts +162 -0
- package/dist/constants/fhir-resource-types.js +70 -0
- package/dist/constants/fhir-versions.d.ts +10 -0
- package/dist/constants/fhir-versions.js +10 -0
- package/dist/constants/index.d.ts +4 -0
- package/dist/constants/index.js +4 -0
- package/dist/converters/convert-allergy-intolerance.d.ts +3 -0
- package/dist/converters/convert-allergy-intolerance.js +85 -0
- package/dist/converters/convert-appointment-response.d.ts +3 -0
- package/dist/converters/convert-appointment-response.js +32 -0
- package/dist/converters/convert-appointment.d.ts +3 -0
- package/dist/converters/convert-appointment.js +61 -0
- package/dist/converters/convert-care-plan.d.ts +3 -0
- package/dist/converters/convert-care-plan.js +93 -0
- package/dist/converters/convert-clinical-impression.d.ts +3 -0
- package/dist/converters/convert-clinical-impression.js +42 -0
- package/dist/converters/convert-composition.d.ts +3 -0
- package/dist/converters/convert-composition.js +70 -0
- package/dist/converters/convert-condition.d.ts +3 -0
- package/dist/converters/convert-condition.js +51 -0
- package/dist/converters/convert-consent.d.ts +9 -0
- package/dist/converters/convert-consent.js +174 -0
- package/dist/converters/convert-coverage.d.ts +3 -0
- package/dist/converters/convert-coverage.js +51 -0
- package/dist/converters/convert-device-use-statement.d.ts +3 -0
- package/dist/converters/convert-device-use-statement.js +36 -0
- package/dist/converters/convert-device.d.ts +3 -0
- package/dist/converters/convert-device.js +48 -0
- package/dist/converters/convert-diagnostic-report.d.ts +3 -0
- package/dist/converters/convert-diagnostic-report.js +63 -0
- package/dist/converters/convert-document-reference.d.ts +3 -0
- package/dist/converters/convert-document-reference.js +54 -0
- package/dist/converters/convert-encounter.d.ts +3 -0
- package/dist/converters/convert-encounter.js +68 -0
- package/dist/converters/convert-flag.d.ts +3 -0
- package/dist/converters/convert-flag.js +42 -0
- package/dist/converters/convert-immunization.d.ts +3 -0
- package/dist/converters/convert-immunization.js +80 -0
- package/dist/converters/convert-location.d.ts +3 -0
- package/dist/converters/convert-location.js +44 -0
- package/dist/converters/convert-medication-statement.d.ts +3 -0
- package/dist/converters/convert-medication-statement.js +130 -0
- package/dist/converters/convert-observation.d.ts +33 -0
- package/dist/converters/convert-observation.js +246 -0
- package/dist/converters/convert-organization.d.ts +3 -0
- package/dist/converters/convert-organization.js +39 -0
- package/dist/converters/convert-practitioner-role.d.ts +3 -0
- package/dist/converters/convert-practitioner-role.js +62 -0
- package/dist/converters/convert-procedure.d.ts +3 -0
- package/dist/converters/convert-procedure.js +64 -0
- package/dist/converters/convert-related-person.d.ts +3 -0
- package/dist/converters/convert-related-person.js +31 -0
- package/dist/converters/convert-shared.d.ts +33 -0
- package/dist/converters/convert-shared.js +181 -0
- package/dist/converters/index.d.ts +24 -0
- package/dist/converters/index.js +24 -0
- package/dist/fhir-bundle.d.ts +9 -0
- package/dist/fhir-bundle.js +43 -0
- package/dist/fhir-search-parameters.d.ts +18 -0
- package/dist/fhir-search-parameters.js +52 -0
- package/dist/fhir-tokens.d.ts +11 -0
- package/dist/fhir-tokens.js +26 -0
- package/dist/fhir-types.d.ts +77 -0
- package/dist/fhir-types.js +1 -0
- package/dist/fhir-values.d.ts +13 -0
- package/dist/fhir-values.js +53 -0
- package/dist/group-r5.d.ts +121 -0
- package/dist/group-r5.js +301 -0
- package/dist/imaging-types.d.ts +30 -0
- package/dist/imaging-types.js +1 -0
- package/dist/immunization-flat-claims.d.ts +2 -0
- package/dist/immunization-flat-claims.js +2 -0
- package/dist/immunization-reminder-plan.d.ts +2 -0
- package/dist/immunization-reminder-plan.js +2 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +19 -0
- package/dist/observation-claims.d.ts +170 -0
- package/dist/observation-claims.js +184 -0
- package/dist/related-person.d.ts +16 -0
- package/dist/related-person.js +14 -0
- package/dist/research-study-r5.d.ts +163 -0
- package/dist/research-study-r5.js +490 -0
- package/dist/search-models/index.d.ts +7 -0
- package/dist/search-models/index.js +7 -0
- package/dist/search-models/params/AdverseEvent.params.model.d.ts +14 -0
- package/dist/search-models/params/AdverseEvent.params.model.js +16 -0
- package/dist/search-models/params/AllergyIntolerance.params.model.d.ts +24 -0
- package/dist/search-models/params/AllergyIntolerance.params.model.js +27 -0
- package/dist/search-models/params/Appointment.params.model.d.ts +12 -0
- package/dist/search-models/params/Appointment.params.model.js +14 -0
- package/dist/search-models/params/ClinicalImpression.params.model.d.ts +14 -0
- package/dist/search-models/params/ClinicalImpression.params.model.js +15 -0
- package/dist/search-models/params/Condition.params.model.d.ts +16 -0
- package/dist/search-models/params/Condition.params.model.js +17 -0
- package/dist/search-models/params/DetectedIssue.params.model.d.ts +9 -0
- package/dist/search-models/params/DetectedIssue.params.model.js +11 -0
- package/dist/search-models/params/DiagnosticReport.params.model.d.ts +13 -0
- package/dist/search-models/params/DiagnosticReport.params.model.js +14 -0
- package/dist/search-models/params/Encounter.params.model.d.ts +15 -0
- package/dist/search-models/params/Encounter.params.model.js +17 -0
- package/dist/search-models/params/Immunization.params.model.d.ts +14 -0
- package/dist/search-models/params/Immunization.params.model.js +16 -0
- package/dist/search-models/params/Medication.params.model.d.ts +35 -0
- package/dist/search-models/params/Medication.params.model.js +45 -0
- package/dist/search-models/params/Observation.params.model.d.ts +326 -0
- package/dist/search-models/params/Observation.params.model.js +244 -0
- package/dist/search-models/params/Procedure.params.model.d.ts +15 -0
- package/dist/search-models/params/Procedure.params.model.js +17 -0
- package/dist/search-models/params/Search.params.model.d.ts +75 -0
- package/dist/search-models/params/Search.params.model.js +69 -0
- package/dist/search-models/params/ServiceRequest.params.model.d.ts +14 -0
- package/dist/search-models/params/ServiceRequest.params.model.js +16 -0
- package/dist/search-models/params/Specimen.params.model.d.ts +10 -0
- package/dist/search-models/params/Specimen.params.model.js +12 -0
- package/dist/search-models/params/index.d.ts +15 -0
- package/dist/search-models/params/index.js +15 -0
- package/dist/search-models/templates/AdverseEvent.template.model.d.ts +16 -0
- package/dist/search-models/templates/AdverseEvent.template.model.js +2 -0
- package/dist/search-models/templates/AllergyIntolerance.template.model.d.ts +24 -0
- package/dist/search-models/templates/AllergyIntolerance.template.model.js +1 -0
- package/dist/search-models/templates/Appointment.template.model.d.ts +13 -0
- package/dist/search-models/templates/Appointment.template.model.js +1 -0
- package/dist/search-models/templates/ClinicalImpression.template.model.d.ts +16 -0
- package/dist/search-models/templates/ClinicalImpression.template.model.js +1 -0
- package/dist/search-models/templates/Condition.template.model.d.ts +18 -0
- package/dist/search-models/templates/Condition.template.model.js +1 -0
- package/dist/search-models/templates/DetectedIssue.template.model.d.ts +11 -0
- package/dist/search-models/templates/DetectedIssue.template.model.js +1 -0
- package/dist/search-models/templates/DiagnosticReport.template.model.d.ts +15 -0
- package/dist/search-models/templates/DiagnosticReport.template.model.js +1 -0
- package/dist/search-models/templates/Encounter.template.model.d.ts +17 -0
- package/dist/search-models/templates/Encounter.template.model.js +1 -0
- package/dist/search-models/templates/Immunization.template.model.d.ts +18 -0
- package/dist/search-models/templates/Immunization.template.model.js +2 -0
- package/dist/search-models/templates/Medication.template.model.d.ts +37 -0
- package/dist/search-models/templates/Medication.template.model.js +1 -0
- package/dist/search-models/templates/Observation.template.model.d.ts +18 -0
- package/dist/search-models/templates/Observation.template.model.js +1 -0
- package/dist/search-models/templates/Procedure.template.model.d.ts +17 -0
- package/dist/search-models/templates/Procedure.template.model.js +1 -0
- package/dist/search-models/templates/ServiceRequest.template.model.d.ts +16 -0
- package/dist/search-models/templates/ServiceRequest.template.model.js +1 -0
- package/dist/search-models/templates/Specimen.template.model.d.ts +12 -0
- package/dist/search-models/templates/Specimen.template.model.js +1 -0
- package/dist/search-models/templates/index.d.ts +14 -0
- package/dist/search-models/templates/index.js +14 -0
- package/dist/terminology-models/AtcModel.d.ts +15 -0
- package/dist/terminology-models/AtcModel.js +2 -0
- package/dist/terminology-models/CommonModels.d.ts +70 -0
- package/dist/terminology-models/CommonModels.js +55 -0
- package/dist/terminology-models/FhirModels.d.ts +60 -0
- package/dist/terminology-models/FhirModels.js +34 -0
- package/dist/terminology-models/LoincModels.d.ts +24 -0
- package/dist/terminology-models/LoincModels.js +2 -0
- package/dist/terminology-models/SnomedModels.d.ts +13 -0
- package/dist/terminology-models/SnomedModels.js +2 -0
- package/dist/terminology-models/index.d.ts +6 -0
- package/dist/terminology-models/index.js +6 -0
- package/docs/UHC_FHIR_UTILS_MIGRATION.md +51 -8
- package/package.json +83 -2
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
// File: src/utils/convert-observation.ts
|
|
3
|
+
import { ObservationClaim } from '../observation-claims.js';
|
|
4
|
+
import { buildFlatClaimResourceEntry, } from '../flat-claim-resource-graph.js';
|
|
5
|
+
import { codingFromValue, codingListToCsv, codingToValue, referenceListToCsv, referenceToValue } from './convert-shared.js';
|
|
6
|
+
/**
|
|
7
|
+
* Converts flat editable Observation claims into a FHIR R4 Observation.
|
|
8
|
+
*
|
|
9
|
+
* Naming convention:
|
|
10
|
+
* - place the concrete FHIR version suffix at the end of the helper name
|
|
11
|
+
* - prefer `observationFromFlatToFhirR4` / `observationToFlatFhirR4`
|
|
12
|
+
* - avoid `observationFhirR4ToFlat`
|
|
13
|
+
*/
|
|
14
|
+
export function observationFromFlatToFhirR4(claims) {
|
|
15
|
+
const subject = claims[ObservationClaim.Subject] ?? claims[ObservationClaim.Patient];
|
|
16
|
+
const codeToken = claims[ObservationClaim.Code]
|
|
17
|
+
?? codingToValue({
|
|
18
|
+
system: claims[ObservationClaim.CodeSystem],
|
|
19
|
+
code: claims[ObservationClaim.CodeValue],
|
|
20
|
+
});
|
|
21
|
+
const valueConceptToken = claims[ObservationClaim.ValueConcept]
|
|
22
|
+
?? codingToValue({
|
|
23
|
+
system: claims[ObservationClaim.ValueConceptSystem],
|
|
24
|
+
code: claims[ObservationClaim.ValueConceptValue],
|
|
25
|
+
});
|
|
26
|
+
const valueQuantityCoding = codingFromValue(claims[ObservationClaim.ValueQuantityUnit])?.[0];
|
|
27
|
+
const codeCoding = codingFromValue(codeToken)?.map((coding) => ({
|
|
28
|
+
...coding,
|
|
29
|
+
...(claims[ObservationClaim.CodeDisplay] ? { display: claims[ObservationClaim.CodeDisplay] } : {}),
|
|
30
|
+
}));
|
|
31
|
+
const valueConceptCoding = codingFromValue(valueConceptToken)?.map((coding) => ({
|
|
32
|
+
...coding,
|
|
33
|
+
...(claims[ObservationClaim.ValueConceptDisplay]
|
|
34
|
+
? { display: claims[ObservationClaim.ValueConceptDisplay] }
|
|
35
|
+
: {}),
|
|
36
|
+
}));
|
|
37
|
+
const componentCodes = splitClaimList(claims[ObservationClaim.ComponentCode]);
|
|
38
|
+
const componentDisplays = splitClaimList(claims[ObservationClaim.ComponentCodeDisplay]);
|
|
39
|
+
const componentNumbers = splitClaimList(claims[ObservationClaim.ComponentValueQuantityNumber]);
|
|
40
|
+
const componentUnits = splitClaimList(claims[ObservationClaim.ComponentValueQuantityUnit]);
|
|
41
|
+
const referenceUnit = claims[ObservationClaim.ReferenceRangeUnit];
|
|
42
|
+
return {
|
|
43
|
+
resourceType: 'Observation',
|
|
44
|
+
identifier: claims[ObservationClaim.Identifier] ? [{ value: claims[ObservationClaim.Identifier] }] : undefined,
|
|
45
|
+
status: claims[ObservationClaim.Status],
|
|
46
|
+
category: claims[ObservationClaim.Category] ? claims[ObservationClaim.Category].split(',').map((value) => ({ coding: codingFromValue(value.trim()) })) : undefined,
|
|
47
|
+
code: codeToken
|
|
48
|
+
? {
|
|
49
|
+
coding: codeCoding,
|
|
50
|
+
...(claims[ObservationClaim.CodeText] ? { text: claims[ObservationClaim.CodeText] } : {}),
|
|
51
|
+
}
|
|
52
|
+
: undefined,
|
|
53
|
+
subject: subject ? { reference: subject } : undefined,
|
|
54
|
+
effectiveDateTime: claims[ObservationClaim.EffectiveDateTime]
|
|
55
|
+
?? claims[ObservationClaim.EffectiveDateTimeLegacy]
|
|
56
|
+
?? claims[ObservationClaim.Date],
|
|
57
|
+
issued: claims[ObservationClaim.EffectiveDateTime] || claims[ObservationClaim.EffectiveDateTimeLegacy]
|
|
58
|
+
? undefined
|
|
59
|
+
: claims[ObservationClaim.Date],
|
|
60
|
+
performer: claims[ObservationClaim.Performer] ? claims[ObservationClaim.Performer].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
61
|
+
valueCodeableConcept: valueConceptToken
|
|
62
|
+
? {
|
|
63
|
+
coding: valueConceptCoding,
|
|
64
|
+
...(claims[ObservationClaim.ValueConceptText]
|
|
65
|
+
? { text: claims[ObservationClaim.ValueConceptText] }
|
|
66
|
+
: {}),
|
|
67
|
+
}
|
|
68
|
+
: undefined,
|
|
69
|
+
valueDateTime: claims[ObservationClaim.ValueDate],
|
|
70
|
+
valueQuantity: claims[ObservationClaim.ValueQuantityNumber]
|
|
71
|
+
? {
|
|
72
|
+
value: Number(claims[ObservationClaim.ValueQuantityNumber]),
|
|
73
|
+
...(claims[ObservationClaim.ValueQuantityComparator]
|
|
74
|
+
? { comparator: claims[ObservationClaim.ValueQuantityComparator] }
|
|
75
|
+
: {}),
|
|
76
|
+
...(claims[ObservationClaim.ValueQuantityUnit]
|
|
77
|
+
? {
|
|
78
|
+
unit: claims[ObservationClaim.ValueQuantityUnit],
|
|
79
|
+
...(valueQuantityCoding?.system ? { system: valueQuantityCoding.system } : {}),
|
|
80
|
+
...(valueQuantityCoding?.code ? { code: valueQuantityCoding.code } : {}),
|
|
81
|
+
}
|
|
82
|
+
: {}),
|
|
83
|
+
}
|
|
84
|
+
: undefined,
|
|
85
|
+
valueString: claims[ObservationClaim.ValueString],
|
|
86
|
+
note: claims[ObservationClaim.Note] ? [{ text: claims[ObservationClaim.Note] }] : undefined,
|
|
87
|
+
basedOn: claims[ObservationClaim.BasedOn] ? claims[ObservationClaim.BasedOn].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
88
|
+
device: claims[ObservationClaim.Device] ? { reference: claims[ObservationClaim.Device] } : undefined,
|
|
89
|
+
encounter: claims[ObservationClaim.Encounter] ? { reference: claims[ObservationClaim.Encounter] } : undefined,
|
|
90
|
+
focus: claims[ObservationClaim.Focus] ? claims[ObservationClaim.Focus].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
91
|
+
hasMember: claims[ObservationClaim.HasMember] ? claims[ObservationClaim.HasMember].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
92
|
+
method: claims[ObservationClaim.Method] ? { coding: codingFromValue(claims[ObservationClaim.Method]) } : undefined,
|
|
93
|
+
specimen: claims[ObservationClaim.Specimen] ? { reference: claims[ObservationClaim.Specimen] } : undefined,
|
|
94
|
+
referenceRange: claims[ObservationClaim.ReferenceRangeLowNumber] || claims[ObservationClaim.ReferenceRangeHighNumber] || claims[ObservationClaim.ReferenceRangeText]
|
|
95
|
+
? [{
|
|
96
|
+
low: claims[ObservationClaim.ReferenceRangeLowNumber] ? quantityFromClaims(claims[ObservationClaim.ReferenceRangeLowNumber], referenceUnit) : undefined,
|
|
97
|
+
high: claims[ObservationClaim.ReferenceRangeHighNumber] ? quantityFromClaims(claims[ObservationClaim.ReferenceRangeHighNumber], referenceUnit) : undefined,
|
|
98
|
+
text: claims[ObservationClaim.ReferenceRangeText],
|
|
99
|
+
}]
|
|
100
|
+
: undefined,
|
|
101
|
+
component: componentCodes.map((code, index) => ({
|
|
102
|
+
code: { coding: codingFromValue(code)?.map((coding) => ({ ...coding, ...(componentDisplays[index] ? { display: componentDisplays[index] } : {}) })) },
|
|
103
|
+
valueQuantity: componentNumbers[index] ? quantityFromClaims(componentNumbers[index], componentUnits[index]) : undefined,
|
|
104
|
+
})),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Converts a FHIR R4 Observation into the flat editable claims contract.
|
|
109
|
+
*
|
|
110
|
+
* `Observation.category` stays in `Observation.category`.
|
|
111
|
+
* Coded result values belong in `Observation.value-concept-*`.
|
|
112
|
+
*/
|
|
113
|
+
export function observationToFlatFhirR4(resource) {
|
|
114
|
+
if (resource.component?.length) {
|
|
115
|
+
throw new TypeError('observation_component_graph_required');
|
|
116
|
+
}
|
|
117
|
+
const valueCodeableConcept = resource.valueCodeableConcept;
|
|
118
|
+
const codeCoding = resource.code?.coding?.[0];
|
|
119
|
+
const valueConceptCoding = valueCodeableConcept?.coding?.[0];
|
|
120
|
+
const valueQuantity = resource.valueQuantity;
|
|
121
|
+
const referenceRange = resource.referenceRange?.[0];
|
|
122
|
+
const referenceLow = referenceRange?.low;
|
|
123
|
+
const referenceHigh = referenceRange?.high;
|
|
124
|
+
return {
|
|
125
|
+
[ObservationClaim.BasedOn]: referenceListToCsv(resource.basedOn),
|
|
126
|
+
[ObservationClaim.Category]: codingListToCsv(resource.category?.flatMap((item) => item.coding || [])),
|
|
127
|
+
[ObservationClaim.Code]: codingToValue(codeCoding),
|
|
128
|
+
[ObservationClaim.CodeSystem]: codeCoding?.system,
|
|
129
|
+
[ObservationClaim.CodeValue]: codeCoding?.code,
|
|
130
|
+
[ObservationClaim.CodeText]: resource.code?.text,
|
|
131
|
+
[ObservationClaim.CodeDisplay]: codeCoding?.display,
|
|
132
|
+
[ObservationClaim.Date]: resource.effectiveDateTime || resource.issued,
|
|
133
|
+
[ObservationClaim.Device]: referenceToValue(resource.device),
|
|
134
|
+
[ObservationClaim.Encounter]: referenceToValue(resource.encounter),
|
|
135
|
+
[ObservationClaim.Focus]: referenceListToCsv(resource.focus),
|
|
136
|
+
[ObservationClaim.HasMember]: referenceListToCsv(resource.hasMember),
|
|
137
|
+
[ObservationClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
138
|
+
[ObservationClaim.Method]: codingToValue(resource.method?.coding?.[0]),
|
|
139
|
+
[ObservationClaim.Patient]: referenceToValue(resource.subject),
|
|
140
|
+
[ObservationClaim.Performer]: referenceListToCsv(resource.performer),
|
|
141
|
+
[ObservationClaim.Specimen]: referenceToValue(resource.specimen),
|
|
142
|
+
[ObservationClaim.Status]: resource.status,
|
|
143
|
+
[ObservationClaim.Subject]: referenceToValue(resource.subject),
|
|
144
|
+
[ObservationClaim.ValueConcept]: codingToValue(valueConceptCoding),
|
|
145
|
+
[ObservationClaim.ValueConceptSystem]: valueConceptCoding?.system,
|
|
146
|
+
[ObservationClaim.ValueConceptValue]: valueConceptCoding?.code,
|
|
147
|
+
[ObservationClaim.ValueConceptText]: valueCodeableConcept?.text,
|
|
148
|
+
[ObservationClaim.ValueConceptDisplay]: valueConceptCoding?.display,
|
|
149
|
+
[ObservationClaim.ValueDate]: resource.valueDateTime,
|
|
150
|
+
[ObservationClaim.ValueQuantityComparator]: valueQuantity?.comparator,
|
|
151
|
+
[ObservationClaim.ValueQuantityNumber]: valueQuantity?.value !== undefined ? String(valueQuantity.value) : undefined,
|
|
152
|
+
[ObservationClaim.ValueQuantityUnit]: codingToValue(valueQuantity?.system || valueQuantity?.code
|
|
153
|
+
? { system: valueQuantity?.system, code: valueQuantity?.code }
|
|
154
|
+
: undefined) || valueQuantity?.unit,
|
|
155
|
+
[ObservationClaim.ValueString]: resource.valueString,
|
|
156
|
+
[ObservationClaim.Note]: resource.note?.[0]?.text,
|
|
157
|
+
[ObservationClaim.EffectiveDateTime]: resource.effectiveDateTime,
|
|
158
|
+
[ObservationClaim.ReferenceRangeLowNumber]: scalarString(referenceLow?.value),
|
|
159
|
+
[ObservationClaim.ReferenceRangeHighNumber]: scalarString(referenceHigh?.value),
|
|
160
|
+
[ObservationClaim.ReferenceRangeUnit]: codingToValue(referenceLow?.system || referenceLow?.code ? { system: referenceLow?.system, code: referenceLow?.code } : referenceHigh?.system || referenceHigh?.code ? { system: referenceHigh?.system, code: referenceHigh?.code } : undefined) || referenceLow?.unit || referenceHigh?.unit,
|
|
161
|
+
[ObservationClaim.ReferenceRangeText]: referenceRange?.text,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Flattens a native component Observation into a parent plus independently
|
|
166
|
+
* indexable reduced Observation entries. Membership belongs to the parent
|
|
167
|
+
* through `Observation.has-member`; child containment flags are never written.
|
|
168
|
+
*/
|
|
169
|
+
export function observationFhirR4ToFlatGraph(resource, options) {
|
|
170
|
+
const components = resource.component ?? [];
|
|
171
|
+
if (options.componentEntryIds && options.componentEntryIds.length !== components.length) {
|
|
172
|
+
throw new TypeError('observation_component_entry_count_mismatch');
|
|
173
|
+
}
|
|
174
|
+
const componentEntryIds = components.map((_, index) => options.componentEntryIds?.[index] ?? `${options.parentEntryId}-component-${index + 1}`);
|
|
175
|
+
const shared = {
|
|
176
|
+
subject: resource.subject,
|
|
177
|
+
effectiveDateTime: resource.effectiveDateTime,
|
|
178
|
+
issued: resource.issued,
|
|
179
|
+
category: resource.category,
|
|
180
|
+
};
|
|
181
|
+
const parentClaims = definedClaims(observationToFlatFhirR4({ ...resource, component: undefined }));
|
|
182
|
+
if (componentEntryIds.length) {
|
|
183
|
+
parentClaims[ObservationClaim.HasMember] = componentEntryIds
|
|
184
|
+
.map(entryId => `Observation/${entryId}`)
|
|
185
|
+
.join(',');
|
|
186
|
+
}
|
|
187
|
+
const parent = buildFlatClaimResourceEntry({
|
|
188
|
+
entryId: options.parentEntryId,
|
|
189
|
+
resourceType: 'Observation',
|
|
190
|
+
claims: parentClaims,
|
|
191
|
+
});
|
|
192
|
+
const children = components.map((component, index) => {
|
|
193
|
+
const entryId = componentEntryIds[index];
|
|
194
|
+
const claims = definedClaims(observationToFlatFhirR4({
|
|
195
|
+
resourceType: 'Observation',
|
|
196
|
+
identifier: [{ value: entryId }],
|
|
197
|
+
...shared,
|
|
198
|
+
...component,
|
|
199
|
+
status: undefined,
|
|
200
|
+
component: undefined,
|
|
201
|
+
}));
|
|
202
|
+
return buildFlatClaimResourceEntry({ entryId, resourceType: 'Observation', claims });
|
|
203
|
+
});
|
|
204
|
+
return Object.freeze([parent, ...children]);
|
|
205
|
+
}
|
|
206
|
+
/** Reconstructs a native FHIR R4 `Observation.component[]` from its flat graph. */
|
|
207
|
+
export function observationFlatGraphToFhirR4(graph, parentEntryId) {
|
|
208
|
+
const parent = graph.find(entry => entry.entryId === parentEntryId && entry.resourceType === 'Observation');
|
|
209
|
+
if (!parent)
|
|
210
|
+
throw new TypeError('observation_parent_entry_not_found');
|
|
211
|
+
const byReference = new Map(graph.map(entry => [entry.reference, entry]));
|
|
212
|
+
const references = parent.claims[ObservationClaim.HasMember]?.split(',').map(value => value.trim()).filter(Boolean) ?? [];
|
|
213
|
+
const projected = { ...observationFromFlatToFhirR4(parent.claims) };
|
|
214
|
+
delete projected.hasMember;
|
|
215
|
+
projected.component = references.map(reference => {
|
|
216
|
+
const child = byReference.get(reference);
|
|
217
|
+
if (!child || child.resourceType !== 'Observation')
|
|
218
|
+
throw new TypeError('observation_component_entry_not_found');
|
|
219
|
+
const componentObservation = observationFromFlatToFhirR4(child.claims);
|
|
220
|
+
return definedObject({
|
|
221
|
+
code: componentObservation.code,
|
|
222
|
+
valueCodeableConcept: componentObservation.valueCodeableConcept,
|
|
223
|
+
valueDateTime: componentObservation.valueDateTime,
|
|
224
|
+
valueQuantity: componentObservation.valueQuantity,
|
|
225
|
+
valueString: componentObservation.valueString,
|
|
226
|
+
referenceRange: componentObservation.referenceRange,
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
return projected;
|
|
230
|
+
}
|
|
231
|
+
function splitClaimList(value) { return value ? JSON.parse(value) : []; }
|
|
232
|
+
function scalarString(value) { return value === undefined || value === null ? undefined : String(value); }
|
|
233
|
+
function quantityFromClaims(number, unit) {
|
|
234
|
+
const coding = codingFromValue(unit)?.[0];
|
|
235
|
+
return { value: Number(number), ...(unit ? { unit, ...(coding?.system ? { system: coding.system } : {}), ...(coding?.code ? { code: coding.code } : {}) } : {}) };
|
|
236
|
+
}
|
|
237
|
+
function definedClaims(claims) {
|
|
238
|
+
return Object.fromEntries(Object.entries(claims).filter((entry) => typeof entry[1] === 'string'));
|
|
239
|
+
}
|
|
240
|
+
function definedObject(value) {
|
|
241
|
+
return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined));
|
|
242
|
+
}
|
|
243
|
+
/** @deprecated Prefer `observationFromFlatToFhirR4`. */
|
|
244
|
+
export const observationFlatToFhirR4 = observationFromFlatToFhirR4;
|
|
245
|
+
/** @deprecated Prefer `observationToFlatFhirR4`. */
|
|
246
|
+
export const observationFhirR4ToFlat = observationToFlatFhirR4;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
// File: src/convert/convert-organization.ts
|
|
3
|
+
import { OrganizationClaim } from '../claims/organization-claims.js';
|
|
4
|
+
import { codingFromValue, codingToValue, referenceToValue } from './convert-shared.js';
|
|
5
|
+
function splitCsv(value) {
|
|
6
|
+
return String(value || '')
|
|
7
|
+
.split(',')
|
|
8
|
+
.map((item) => item.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
}
|
|
11
|
+
export function organizationFlatToFhirR4(claims) {
|
|
12
|
+
return {
|
|
13
|
+
resourceType: 'Organization',
|
|
14
|
+
identifier: claims[OrganizationClaim.Identifier] ? [{ value: claims[OrganizationClaim.Identifier] }] : undefined,
|
|
15
|
+
active: claims[OrganizationClaim.Active] === undefined ? undefined : claims[OrganizationClaim.Active] === 'true',
|
|
16
|
+
type: claims[OrganizationClaim.Type] ? [{ coding: codingFromValue(claims[OrganizationClaim.Type]) }] : undefined,
|
|
17
|
+
name: claims[OrganizationClaim.Name],
|
|
18
|
+
alias: splitCsv(claims[OrganizationClaim.Alias]),
|
|
19
|
+
partOf: claims[OrganizationClaim.PartOf] ? { reference: claims[OrganizationClaim.PartOf] } : undefined,
|
|
20
|
+
telecom: splitCsv(claims[OrganizationClaim.Telecom]).map((value) => ({ value })),
|
|
21
|
+
address: claims[OrganizationClaim.Address] ? [{ text: claims[OrganizationClaim.Address] }] : undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function organizationFhirR4ToFlat(resource) {
|
|
25
|
+
const alias = resource.alias?.filter(Boolean);
|
|
26
|
+
const telecom = resource.telecom
|
|
27
|
+
?.map((item) => item?.value)
|
|
28
|
+
.filter((item) => Boolean(item));
|
|
29
|
+
return {
|
|
30
|
+
[OrganizationClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
31
|
+
[OrganizationClaim.Active]: resource.active === undefined ? undefined : String(resource.active),
|
|
32
|
+
[OrganizationClaim.Type]: codingToValue(resource.type?.[0]?.coding?.[0]),
|
|
33
|
+
[OrganizationClaim.Name]: resource.name,
|
|
34
|
+
[OrganizationClaim.Alias]: alias?.length ? alias.join(',') : undefined,
|
|
35
|
+
[OrganizationClaim.PartOf]: referenceToValue(resource.partOf),
|
|
36
|
+
[OrganizationClaim.Telecom]: telecom?.length ? telecom.join(',') : undefined,
|
|
37
|
+
[OrganizationClaim.Address]: resource.address?.[0]?.text,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
import { PractitionerRoleClaim } from '../claims/practitioner-role-claims.js';
|
|
3
|
+
import { codingFromValue, codingToValue, referenceListToCsv, referenceToValue, } from './convert-shared.js';
|
|
4
|
+
export function practitionerRoleFhirR4ToFlat(resource, _context = 'org.hl7.fhir.api') {
|
|
5
|
+
const concept = resource.code?.[0];
|
|
6
|
+
return {
|
|
7
|
+
[PractitionerRoleClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
8
|
+
[PractitionerRoleClaim.Active]: resource.active === undefined ? undefined : String(resource.active),
|
|
9
|
+
[PractitionerRoleClaim.Practitioner]: referenceToValue(resource.practitioner),
|
|
10
|
+
[PractitionerRoleClaim.Organization]: referenceToValue(resource.organization),
|
|
11
|
+
[PractitionerRoleClaim.Location]: referenceListToCsv(resource.location),
|
|
12
|
+
[PractitionerRoleClaim.Service]: referenceListToCsv(resource.healthcareService),
|
|
13
|
+
[PractitionerRoleClaim.Specialty]: codingToValue(resource.specialty?.[0]?.coding?.[0]),
|
|
14
|
+
[PractitionerRoleClaim.PeriodStart]: resource.period?.start,
|
|
15
|
+
[PractitionerRoleClaim.PeriodEnd]: resource.period?.end,
|
|
16
|
+
[PractitionerRoleClaim.Code]: codingToValue(concept?.coding?.[0]),
|
|
17
|
+
[PractitionerRoleClaim.CodeText]: concept?.text,
|
|
18
|
+
[PractitionerRoleClaim.CodeDisplay]: concept?.coding?.[0]?.display,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function practitionerRoleFlatToFhirR4(claims) {
|
|
22
|
+
const location = claims[PractitionerRoleClaim.Location]?.split(',').map((reference) => ({ reference: reference.trim() }));
|
|
23
|
+
const healthcareService = claims[PractitionerRoleClaim.Service]?.split(',').map((reference) => ({ reference: reference.trim() }));
|
|
24
|
+
const coding = codingFromValue(claims[PractitionerRoleClaim.Code])?.map((item) => ({
|
|
25
|
+
...item,
|
|
26
|
+
...(claims[PractitionerRoleClaim.CodeDisplay]
|
|
27
|
+
? { display: claims[PractitionerRoleClaim.CodeDisplay] }
|
|
28
|
+
: {}),
|
|
29
|
+
}));
|
|
30
|
+
return {
|
|
31
|
+
resourceType: 'PractitionerRole',
|
|
32
|
+
identifier: claims[PractitionerRoleClaim.Identifier]
|
|
33
|
+
? [{ value: claims[PractitionerRoleClaim.Identifier] }]
|
|
34
|
+
: undefined,
|
|
35
|
+
active: claims[PractitionerRoleClaim.Active] === undefined
|
|
36
|
+
? undefined
|
|
37
|
+
: claims[PractitionerRoleClaim.Active] === 'true',
|
|
38
|
+
practitioner: claims[PractitionerRoleClaim.Practitioner]
|
|
39
|
+
? { reference: claims[PractitionerRoleClaim.Practitioner] }
|
|
40
|
+
: undefined,
|
|
41
|
+
organization: claims[PractitionerRoleClaim.Organization]
|
|
42
|
+
? { reference: claims[PractitionerRoleClaim.Organization] }
|
|
43
|
+
: undefined,
|
|
44
|
+
location,
|
|
45
|
+
healthcareService,
|
|
46
|
+
specialty: claims[PractitionerRoleClaim.Specialty]
|
|
47
|
+
? [{ coding: codingFromValue(claims[PractitionerRoleClaim.Specialty]) }]
|
|
48
|
+
: undefined,
|
|
49
|
+
period: claims[PractitionerRoleClaim.PeriodStart] || claims[PractitionerRoleClaim.PeriodEnd]
|
|
50
|
+
? {
|
|
51
|
+
start: claims[PractitionerRoleClaim.PeriodStart],
|
|
52
|
+
end: claims[PractitionerRoleClaim.PeriodEnd],
|
|
53
|
+
}
|
|
54
|
+
: undefined,
|
|
55
|
+
code: coding || claims[PractitionerRoleClaim.CodeText] ? [{
|
|
56
|
+
...(coding ? { coding } : {}),
|
|
57
|
+
...(claims[PractitionerRoleClaim.CodeText]
|
|
58
|
+
? { text: claims[PractitionerRoleClaim.CodeText] }
|
|
59
|
+
: {}),
|
|
60
|
+
}] : undefined,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
// File: src/utils/convert-procedure.ts
|
|
3
|
+
import { ProcedureClaim } from '../claims/procedure-claims.js';
|
|
4
|
+
import { codingFromValue, codingToValue, referenceListToCsv, referenceToValue } from './convert-shared.js';
|
|
5
|
+
export function procedureFlatToFhirR4(claims) {
|
|
6
|
+
const subject = claims[ProcedureClaim.Subject] ?? claims[ProcedureClaim.Patient];
|
|
7
|
+
return {
|
|
8
|
+
resourceType: 'Procedure',
|
|
9
|
+
identifier: claims[ProcedureClaim.Identifier] ? [{ value: claims[ProcedureClaim.Identifier] }] : undefined,
|
|
10
|
+
status: claims[ProcedureClaim.Status],
|
|
11
|
+
subject: subject ? { reference: subject } : undefined,
|
|
12
|
+
code: claims[ProcedureClaim.Code]
|
|
13
|
+
? {
|
|
14
|
+
coding: codingFromValue(claims[ProcedureClaim.Code])?.map((coding) => ({
|
|
15
|
+
...coding,
|
|
16
|
+
...(claims[ProcedureClaim.CodeDisplay]
|
|
17
|
+
? { display: claims[ProcedureClaim.CodeDisplay] }
|
|
18
|
+
: {}),
|
|
19
|
+
})),
|
|
20
|
+
...(claims[ProcedureClaim.CodeText]
|
|
21
|
+
? { text: claims[ProcedureClaim.CodeText] }
|
|
22
|
+
: {}),
|
|
23
|
+
}
|
|
24
|
+
: undefined,
|
|
25
|
+
performedDateTime: claims[ProcedureClaim.Date],
|
|
26
|
+
note: claims[ProcedureClaim.Note] ? [{ text: claims[ProcedureClaim.Note] }] : undefined,
|
|
27
|
+
basedOn: claims[ProcedureClaim.BasedOn] ? claims[ProcedureClaim.BasedOn].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
28
|
+
bodySite: claims[ProcedureClaim.BodySite] ? [{ coding: codingFromValue(claims[ProcedureClaim.BodySite]) }] : undefined,
|
|
29
|
+
encounter: claims[ProcedureClaim.Encounter] ? { reference: claims[ProcedureClaim.Encounter] } : undefined,
|
|
30
|
+
instantiatesCanonical: claims[ProcedureClaim.InstantiatesCanonical] ? [claims[ProcedureClaim.InstantiatesCanonical]] : undefined,
|
|
31
|
+
instantiatesUri: claims[ProcedureClaim.InstantiatesUri] ? [claims[ProcedureClaim.InstantiatesUri]] : undefined,
|
|
32
|
+
location: claims[ProcedureClaim.Location] ? { reference: claims[ProcedureClaim.Location] } : undefined,
|
|
33
|
+
partOf: claims[ProcedureClaim.PartOf] ? claims[ProcedureClaim.PartOf].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
34
|
+
performer: claims[ProcedureClaim.Performer] ? claims[ProcedureClaim.Performer].split(',').map((reference) => ({ actor: { reference: reference.trim() } })) : undefined,
|
|
35
|
+
reasonCode: claims[ProcedureClaim.ReasonCode] ? [{ coding: codingFromValue(claims[ProcedureClaim.ReasonCode]) }] : undefined,
|
|
36
|
+
reasonReference: claims[ProcedureClaim.ReasonReference] ? claims[ProcedureClaim.ReasonReference].split(',').map((reference) => ({ reference: reference.trim() })) : undefined,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function procedureFhirR4ToFlat(resource) {
|
|
40
|
+
const performer = Array.isArray(resource.performer)
|
|
41
|
+
? resource.performer.map((item) => referenceToValue(item?.actor)).filter((item) => Boolean(item))
|
|
42
|
+
: [];
|
|
43
|
+
return {
|
|
44
|
+
[ProcedureClaim.BasedOn]: referenceListToCsv(resource.basedOn),
|
|
45
|
+
[ProcedureClaim.BodySite]: codingToValue(resource.bodySite?.[0]?.coding?.[0]),
|
|
46
|
+
[ProcedureClaim.Code]: codingToValue(resource.code?.coding?.[0]),
|
|
47
|
+
[ProcedureClaim.CodeText]: resource.code?.text,
|
|
48
|
+
[ProcedureClaim.CodeDisplay]: resource.code?.coding?.[0]?.display,
|
|
49
|
+
[ProcedureClaim.Date]: resource.performedDateTime || resource.performedPeriod?.start,
|
|
50
|
+
[ProcedureClaim.Encounter]: referenceToValue(resource.encounter),
|
|
51
|
+
[ProcedureClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
52
|
+
[ProcedureClaim.InstantiatesCanonical]: Array.isArray(resource.instantiatesCanonical) ? resource.instantiatesCanonical[0] : undefined,
|
|
53
|
+
[ProcedureClaim.InstantiatesUri]: Array.isArray(resource.instantiatesUri) ? resource.instantiatesUri[0] : undefined,
|
|
54
|
+
[ProcedureClaim.Location]: referenceToValue(resource.location),
|
|
55
|
+
[ProcedureClaim.PartOf]: referenceListToCsv(resource.partOf),
|
|
56
|
+
[ProcedureClaim.Patient]: referenceToValue(resource.subject),
|
|
57
|
+
[ProcedureClaim.Performer]: performer.length ? performer.join(',') : undefined,
|
|
58
|
+
[ProcedureClaim.ReasonCode]: codingToValue(resource.reasonCode?.[0]?.coding?.[0]),
|
|
59
|
+
[ProcedureClaim.ReasonReference]: referenceListToCsv(resource.reasonReference),
|
|
60
|
+
[ProcedureClaim.Status]: resource.status,
|
|
61
|
+
[ProcedureClaim.Subject]: referenceToValue(resource.subject),
|
|
62
|
+
[ProcedureClaim.Note]: resource.note?.[0]?.text,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
// File: src/utils/convert-related-person.ts
|
|
3
|
+
import { RelatedPersonClaim } from '../claims/related-person-claims.js';
|
|
4
|
+
import { codingFromValue, codingToValue, referenceToValue } from './convert-shared.js';
|
|
5
|
+
export function relatedPersonFlatToFhirR4(claims) {
|
|
6
|
+
return {
|
|
7
|
+
resourceType: 'RelatedPerson',
|
|
8
|
+
identifier: claims[RelatedPersonClaim.Identifier] ? [{ value: claims[RelatedPersonClaim.Identifier] }] : undefined,
|
|
9
|
+
active: claims[RelatedPersonClaim.Active] === undefined ? undefined : claims[RelatedPersonClaim.Active] === 'true',
|
|
10
|
+
patient: claims[RelatedPersonClaim.Patient] ? { reference: claims[RelatedPersonClaim.Patient] } : undefined,
|
|
11
|
+
relationship: claims[RelatedPersonClaim.Relationship] ? [{ coding: codingFromValue(claims[RelatedPersonClaim.Relationship]) }] : undefined,
|
|
12
|
+
name: claims[RelatedPersonClaim.Name] ? [{ text: claims[RelatedPersonClaim.Name] }] : undefined,
|
|
13
|
+
telecom: claims[RelatedPersonClaim.Telecom] ? [{ value: claims[RelatedPersonClaim.Telecom] }] : undefined,
|
|
14
|
+
gender: claims[RelatedPersonClaim.Gender],
|
|
15
|
+
birthDate: claims[RelatedPersonClaim.BirthDate],
|
|
16
|
+
address: claims[RelatedPersonClaim.Address] ? [{ text: claims[RelatedPersonClaim.Address] }] : undefined,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function relatedPersonFhirR4ToFlat(resource) {
|
|
20
|
+
return {
|
|
21
|
+
[RelatedPersonClaim.Identifier]: resource.identifier?.[0]?.value,
|
|
22
|
+
[RelatedPersonClaim.Active]: resource.active === undefined ? undefined : String(resource.active),
|
|
23
|
+
[RelatedPersonClaim.Patient]: referenceToValue(resource.patient),
|
|
24
|
+
[RelatedPersonClaim.Relationship]: codingToValue(resource.relationship?.[0]?.coding?.[0]),
|
|
25
|
+
[RelatedPersonClaim.Name]: resource.name?.[0]?.text,
|
|
26
|
+
[RelatedPersonClaim.Telecom]: resource.telecom?.[0]?.value,
|
|
27
|
+
[RelatedPersonClaim.Gender]: resource.gender,
|
|
28
|
+
[RelatedPersonClaim.BirthDate]: resource.birthDate,
|
|
29
|
+
[RelatedPersonClaim.Address]: resource.address?.[0]?.text,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { FhirResource } from '../fhir-types.js';
|
|
2
|
+
export type FlatClaims = Record<string, string | undefined>;
|
|
3
|
+
export type { FhirResource } from '../fhir-types.js';
|
|
4
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
5
|
+
export declare function codingFromValue(value?: string): Array<{
|
|
6
|
+
system?: string;
|
|
7
|
+
code: string;
|
|
8
|
+
}> | undefined;
|
|
9
|
+
export declare function codingToValue(coding?: {
|
|
10
|
+
system?: string;
|
|
11
|
+
code?: string;
|
|
12
|
+
}): string | undefined;
|
|
13
|
+
export declare function referenceToValue(reference?: {
|
|
14
|
+
reference?: string;
|
|
15
|
+
}): string | undefined;
|
|
16
|
+
export declare function referenceListToCsv(references?: Array<{
|
|
17
|
+
reference?: string;
|
|
18
|
+
}>): string | undefined;
|
|
19
|
+
export declare function codingListToCsv(codings?: Array<{
|
|
20
|
+
system?: string;
|
|
21
|
+
code?: string;
|
|
22
|
+
}>): string | undefined;
|
|
23
|
+
export declare function requireClaim(claims: FlatClaims, key: string): string;
|
|
24
|
+
export declare function requireSubjectIdentifier(value: string, key: string): void;
|
|
25
|
+
export declare function requireDidWeb(value: string, key: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Generic structural fallback for unsupported resources.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fhirResourceToFlatClaims(resource: FhirResource, context?: string): FlatClaims;
|
|
30
|
+
/**
|
|
31
|
+
* Generic structural regeneration for unsupported resources.
|
|
32
|
+
*/
|
|
33
|
+
export declare function flatClaimsToFhirResource(claims: FlatClaims): FhirResource;
|