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.
Files changed (285) hide show
  1. package/.codex/skills/govern-fhir-data-utilities/SKILL.md +58 -0
  2. package/.codex/skills/govern-fhir-data-utilities/agents/openai.yaml +4 -0
  3. package/.codex/skills/govern-fhir-observation-components/SKILL.md +18 -0
  4. package/CHANGELOG.md +30 -0
  5. package/README.md +39 -0
  6. package/dist/builders/immunization-graph.d.ts +36 -0
  7. package/dist/builders/immunization-graph.js +115 -0
  8. package/dist/builders/immunization-reminders.d.ts +35 -0
  9. package/dist/builders/immunization-reminders.js +104 -0
  10. package/dist/builders/index.d.ts +2 -0
  11. package/dist/builders/index.js +2 -0
  12. package/dist/claim-helpers/claim-list-helpers.d.ts +21 -0
  13. package/dist/claim-helpers/claim-list-helpers.js +54 -0
  14. package/dist/claim-helpers/claims-helpers-allergy-intolerance.d.ts +18 -0
  15. package/dist/claim-helpers/claims-helpers-allergy-intolerance.js +65 -0
  16. package/dist/claim-helpers/claims-helpers-appointment-response.d.ts +8 -0
  17. package/dist/claim-helpers/claims-helpers-appointment-response.js +20 -0
  18. package/dist/claim-helpers/claims-helpers-appointment.d.ts +10 -0
  19. package/dist/claim-helpers/claims-helpers-appointment.js +26 -0
  20. package/dist/claim-helpers/claims-helpers-care-plan.d.ts +8 -0
  21. package/dist/claim-helpers/claims-helpers-care-plan.js +20 -0
  22. package/dist/claim-helpers/claims-helpers-clinical-impression.d.ts +10 -0
  23. package/dist/claim-helpers/claims-helpers-clinical-impression.js +26 -0
  24. package/dist/claim-helpers/claims-helpers-communication.d.ts +19 -0
  25. package/dist/claim-helpers/claims-helpers-communication.js +63 -0
  26. package/dist/claim-helpers/claims-helpers-composition.d.ts +12 -0
  27. package/dist/claim-helpers/claims-helpers-composition.js +32 -0
  28. package/dist/claim-helpers/claims-helpers-condition.d.ts +18 -0
  29. package/dist/claim-helpers/claims-helpers-condition.js +65 -0
  30. package/dist/claim-helpers/claims-helpers-coverage.d.ts +10 -0
  31. package/dist/claim-helpers/claims-helpers-coverage.js +26 -0
  32. package/dist/claim-helpers/claims-helpers-device-use-statement.d.ts +8 -0
  33. package/dist/claim-helpers/claims-helpers-device-use-statement.js +20 -0
  34. package/dist/claim-helpers/claims-helpers-device.d.ts +8 -0
  35. package/dist/claim-helpers/claims-helpers-device.js +20 -0
  36. package/dist/claim-helpers/claims-helpers-diagnostic-report.d.ts +16 -0
  37. package/dist/claim-helpers/claims-helpers-diagnostic-report.js +47 -0
  38. package/dist/claim-helpers/claims-helpers-document-reference.d.ts +8 -0
  39. package/dist/claim-helpers/claims-helpers-document-reference.js +20 -0
  40. package/dist/claim-helpers/claims-helpers-encounter.d.ts +10 -0
  41. package/dist/claim-helpers/claims-helpers-encounter.js +26 -0
  42. package/dist/claim-helpers/claims-helpers-flag.d.ts +8 -0
  43. package/dist/claim-helpers/claims-helpers-flag.js +20 -0
  44. package/dist/claim-helpers/claims-helpers-immunization.d.ts +8 -0
  45. package/dist/claim-helpers/claims-helpers-immunization.js +20 -0
  46. package/dist/claim-helpers/claims-helpers-location.d.ts +10 -0
  47. package/dist/claim-helpers/claims-helpers-location.js +26 -0
  48. package/dist/claim-helpers/claims-helpers-medication-statement.d.ts +96 -0
  49. package/dist/claim-helpers/claims-helpers-medication-statement.js +278 -0
  50. package/dist/claim-helpers/claims-helpers-observation.d.ts +8 -0
  51. package/dist/claim-helpers/claims-helpers-observation.js +20 -0
  52. package/dist/claim-helpers/claims-helpers-organization.d.ts +12 -0
  53. package/dist/claim-helpers/claims-helpers-organization.js +32 -0
  54. package/dist/claim-helpers/claims-helpers-procedure.d.ts +8 -0
  55. package/dist/claim-helpers/claims-helpers-procedure.js +20 -0
  56. package/dist/claim-helpers/claims-helpers-related-person.d.ts +22 -0
  57. package/dist/claim-helpers/claims-helpers-related-person.js +53 -0
  58. package/dist/claim-helpers/index.d.ts +23 -0
  59. package/dist/claim-helpers/index.js +23 -0
  60. package/dist/claims/allergy-intolerance-claims.d.ts +153 -0
  61. package/dist/claims/allergy-intolerance-claims.js +194 -0
  62. package/dist/claims/appointment-claims.d.ts +226 -0
  63. package/dist/claims/appointment-claims.js +218 -0
  64. package/dist/claims/appointment-response-claims.d.ts +63 -0
  65. package/dist/claims/appointment-response-claims.js +58 -0
  66. package/dist/claims/care-plan-claims.d.ts +37 -0
  67. package/dist/claims/care-plan-claims.js +59 -0
  68. package/dist/claims/claim-types.d.ts +9 -0
  69. package/dist/claims/claim-types.js +3 -0
  70. package/dist/claims/clinical-impression-claims.d.ts +17 -0
  71. package/dist/claims/clinical-impression-claims.js +30 -0
  72. package/dist/claims/communication-claims.d.ts +55 -0
  73. package/dist/claims/communication-claims.js +57 -0
  74. package/dist/claims/composition-claims.d.ts +27 -0
  75. package/dist/claims/composition-claims.js +27 -0
  76. package/dist/claims/condition-claims.d.ts +79 -0
  77. package/dist/claims/condition-claims.js +104 -0
  78. package/dist/claims/consent-claims.d.ts +195 -0
  79. package/dist/claims/consent-claims.js +74 -0
  80. package/dist/claims/coverage-claims.d.ts +16 -0
  81. package/dist/claims/coverage-claims.js +28 -0
  82. package/dist/claims/device-claims.d.ts +20 -0
  83. package/dist/claims/device-claims.js +36 -0
  84. package/dist/claims/device-use-statement-claims.d.ts +17 -0
  85. package/dist/claims/device-use-statement-claims.js +28 -0
  86. package/dist/claims/diagnostic-report-claims.d.ts +109 -0
  87. package/dist/claims/diagnostic-report-claims.js +120 -0
  88. package/dist/claims/document-reference-claims.d.ts +39 -0
  89. package/dist/claims/document-reference-claims.js +96 -0
  90. package/dist/claims/encounter-claims.d.ts +18 -0
  91. package/dist/claims/encounter-claims.js +32 -0
  92. package/dist/claims/flag-claims.d.ts +19 -0
  93. package/dist/claims/flag-claims.js +33 -0
  94. package/dist/claims/immunization-claims.d.ts +31 -0
  95. package/dist/claims/immunization-claims.js +54 -0
  96. package/dist/claims/immunization-recommendation-claims.d.ts +19 -0
  97. package/dist/claims/immunization-recommendation-claims.js +26 -0
  98. package/dist/claims/index.d.ts +29 -0
  99. package/dist/claims/index.js +29 -0
  100. package/dist/claims/invoice-claims.d.ts +277 -0
  101. package/dist/claims/invoice-claims.js +357 -0
  102. package/dist/claims/location-claims.d.ts +22 -0
  103. package/dist/claims/location-claims.js +34 -0
  104. package/dist/claims/medication-claims.d.ts +15 -0
  105. package/dist/claims/medication-claims.js +23 -0
  106. package/dist/claims/medication-statement-claims.d.ts +539 -0
  107. package/dist/claims/medication-statement-claims.js +469 -0
  108. package/dist/claims/organization-claims.d.ts +18 -0
  109. package/dist/claims/organization-claims.js +27 -0
  110. package/dist/claims/practitioner-role-claims.d.ts +18 -0
  111. package/dist/claims/practitioner-role-claims.js +33 -0
  112. package/dist/claims/procedure-claims.d.ts +24 -0
  113. package/dist/claims/procedure-claims.js +44 -0
  114. package/dist/claims/related-person-claims.d.ts +30 -0
  115. package/dist/claims/related-person-claims.js +44 -0
  116. package/dist/claims/research-subject-claims.d.ts +4 -0
  117. package/dist/claims/research-subject-claims.js +4 -0
  118. package/dist/claims/task-claims.d.ts +61 -0
  119. package/dist/claims/task-claims.js +64 -0
  120. package/dist/clinical-terminology.d.ts +73 -0
  121. package/dist/clinical-terminology.js +77 -0
  122. package/dist/constants/clinical-statuses.d.ts +102 -0
  123. package/dist/constants/clinical-statuses.js +93 -0
  124. package/dist/constants/fhir-code-systems.d.ts +15 -0
  125. package/dist/constants/fhir-code-systems.js +15 -0
  126. package/dist/constants/fhir-resource-types.d.ts +162 -0
  127. package/dist/constants/fhir-resource-types.js +70 -0
  128. package/dist/constants/fhir-versions.d.ts +10 -0
  129. package/dist/constants/fhir-versions.js +10 -0
  130. package/dist/constants/index.d.ts +4 -0
  131. package/dist/constants/index.js +4 -0
  132. package/dist/converters/convert-allergy-intolerance.d.ts +3 -0
  133. package/dist/converters/convert-allergy-intolerance.js +85 -0
  134. package/dist/converters/convert-appointment-response.d.ts +3 -0
  135. package/dist/converters/convert-appointment-response.js +32 -0
  136. package/dist/converters/convert-appointment.d.ts +3 -0
  137. package/dist/converters/convert-appointment.js +61 -0
  138. package/dist/converters/convert-care-plan.d.ts +3 -0
  139. package/dist/converters/convert-care-plan.js +93 -0
  140. package/dist/converters/convert-clinical-impression.d.ts +3 -0
  141. package/dist/converters/convert-clinical-impression.js +42 -0
  142. package/dist/converters/convert-composition.d.ts +3 -0
  143. package/dist/converters/convert-composition.js +70 -0
  144. package/dist/converters/convert-condition.d.ts +3 -0
  145. package/dist/converters/convert-condition.js +51 -0
  146. package/dist/converters/convert-consent.d.ts +9 -0
  147. package/dist/converters/convert-consent.js +174 -0
  148. package/dist/converters/convert-coverage.d.ts +3 -0
  149. package/dist/converters/convert-coverage.js +51 -0
  150. package/dist/converters/convert-device-use-statement.d.ts +3 -0
  151. package/dist/converters/convert-device-use-statement.js +36 -0
  152. package/dist/converters/convert-device.d.ts +3 -0
  153. package/dist/converters/convert-device.js +48 -0
  154. package/dist/converters/convert-diagnostic-report.d.ts +3 -0
  155. package/dist/converters/convert-diagnostic-report.js +63 -0
  156. package/dist/converters/convert-document-reference.d.ts +3 -0
  157. package/dist/converters/convert-document-reference.js +54 -0
  158. package/dist/converters/convert-encounter.d.ts +3 -0
  159. package/dist/converters/convert-encounter.js +68 -0
  160. package/dist/converters/convert-flag.d.ts +3 -0
  161. package/dist/converters/convert-flag.js +42 -0
  162. package/dist/converters/convert-immunization.d.ts +3 -0
  163. package/dist/converters/convert-immunization.js +80 -0
  164. package/dist/converters/convert-location.d.ts +3 -0
  165. package/dist/converters/convert-location.js +44 -0
  166. package/dist/converters/convert-medication-statement.d.ts +3 -0
  167. package/dist/converters/convert-medication-statement.js +130 -0
  168. package/dist/converters/convert-observation.d.ts +33 -0
  169. package/dist/converters/convert-observation.js +246 -0
  170. package/dist/converters/convert-organization.d.ts +3 -0
  171. package/dist/converters/convert-organization.js +39 -0
  172. package/dist/converters/convert-practitioner-role.d.ts +3 -0
  173. package/dist/converters/convert-practitioner-role.js +62 -0
  174. package/dist/converters/convert-procedure.d.ts +3 -0
  175. package/dist/converters/convert-procedure.js +64 -0
  176. package/dist/converters/convert-related-person.d.ts +3 -0
  177. package/dist/converters/convert-related-person.js +31 -0
  178. package/dist/converters/convert-shared.d.ts +33 -0
  179. package/dist/converters/convert-shared.js +181 -0
  180. package/dist/converters/index.d.ts +24 -0
  181. package/dist/converters/index.js +24 -0
  182. package/dist/fhir-bundle.d.ts +9 -0
  183. package/dist/fhir-bundle.js +43 -0
  184. package/dist/fhir-search-parameters.d.ts +18 -0
  185. package/dist/fhir-search-parameters.js +52 -0
  186. package/dist/fhir-tokens.d.ts +11 -0
  187. package/dist/fhir-tokens.js +26 -0
  188. package/dist/fhir-types.d.ts +77 -0
  189. package/dist/fhir-types.js +1 -0
  190. package/dist/fhir-values.d.ts +13 -0
  191. package/dist/fhir-values.js +53 -0
  192. package/dist/group-r5.d.ts +121 -0
  193. package/dist/group-r5.js +301 -0
  194. package/dist/imaging-types.d.ts +30 -0
  195. package/dist/imaging-types.js +1 -0
  196. package/dist/immunization-flat-claims.d.ts +2 -0
  197. package/dist/immunization-flat-claims.js +2 -0
  198. package/dist/immunization-reminder-plan.d.ts +2 -0
  199. package/dist/immunization-reminder-plan.js +2 -0
  200. package/dist/index.d.ts +19 -0
  201. package/dist/index.js +19 -0
  202. package/dist/observation-claims.d.ts +170 -0
  203. package/dist/observation-claims.js +184 -0
  204. package/dist/related-person.d.ts +16 -0
  205. package/dist/related-person.js +14 -0
  206. package/dist/research-study-r5.d.ts +163 -0
  207. package/dist/research-study-r5.js +490 -0
  208. package/dist/search-models/index.d.ts +7 -0
  209. package/dist/search-models/index.js +7 -0
  210. package/dist/search-models/params/AdverseEvent.params.model.d.ts +14 -0
  211. package/dist/search-models/params/AdverseEvent.params.model.js +16 -0
  212. package/dist/search-models/params/AllergyIntolerance.params.model.d.ts +24 -0
  213. package/dist/search-models/params/AllergyIntolerance.params.model.js +27 -0
  214. package/dist/search-models/params/Appointment.params.model.d.ts +12 -0
  215. package/dist/search-models/params/Appointment.params.model.js +14 -0
  216. package/dist/search-models/params/ClinicalImpression.params.model.d.ts +14 -0
  217. package/dist/search-models/params/ClinicalImpression.params.model.js +15 -0
  218. package/dist/search-models/params/Condition.params.model.d.ts +16 -0
  219. package/dist/search-models/params/Condition.params.model.js +17 -0
  220. package/dist/search-models/params/DetectedIssue.params.model.d.ts +9 -0
  221. package/dist/search-models/params/DetectedIssue.params.model.js +11 -0
  222. package/dist/search-models/params/DiagnosticReport.params.model.d.ts +13 -0
  223. package/dist/search-models/params/DiagnosticReport.params.model.js +14 -0
  224. package/dist/search-models/params/Encounter.params.model.d.ts +15 -0
  225. package/dist/search-models/params/Encounter.params.model.js +17 -0
  226. package/dist/search-models/params/Immunization.params.model.d.ts +14 -0
  227. package/dist/search-models/params/Immunization.params.model.js +16 -0
  228. package/dist/search-models/params/Medication.params.model.d.ts +35 -0
  229. package/dist/search-models/params/Medication.params.model.js +45 -0
  230. package/dist/search-models/params/Observation.params.model.d.ts +326 -0
  231. package/dist/search-models/params/Observation.params.model.js +244 -0
  232. package/dist/search-models/params/Procedure.params.model.d.ts +15 -0
  233. package/dist/search-models/params/Procedure.params.model.js +17 -0
  234. package/dist/search-models/params/Search.params.model.d.ts +75 -0
  235. package/dist/search-models/params/Search.params.model.js +69 -0
  236. package/dist/search-models/params/ServiceRequest.params.model.d.ts +14 -0
  237. package/dist/search-models/params/ServiceRequest.params.model.js +16 -0
  238. package/dist/search-models/params/Specimen.params.model.d.ts +10 -0
  239. package/dist/search-models/params/Specimen.params.model.js +12 -0
  240. package/dist/search-models/params/index.d.ts +15 -0
  241. package/dist/search-models/params/index.js +15 -0
  242. package/dist/search-models/templates/AdverseEvent.template.model.d.ts +16 -0
  243. package/dist/search-models/templates/AdverseEvent.template.model.js +2 -0
  244. package/dist/search-models/templates/AllergyIntolerance.template.model.d.ts +24 -0
  245. package/dist/search-models/templates/AllergyIntolerance.template.model.js +1 -0
  246. package/dist/search-models/templates/Appointment.template.model.d.ts +13 -0
  247. package/dist/search-models/templates/Appointment.template.model.js +1 -0
  248. package/dist/search-models/templates/ClinicalImpression.template.model.d.ts +16 -0
  249. package/dist/search-models/templates/ClinicalImpression.template.model.js +1 -0
  250. package/dist/search-models/templates/Condition.template.model.d.ts +18 -0
  251. package/dist/search-models/templates/Condition.template.model.js +1 -0
  252. package/dist/search-models/templates/DetectedIssue.template.model.d.ts +11 -0
  253. package/dist/search-models/templates/DetectedIssue.template.model.js +1 -0
  254. package/dist/search-models/templates/DiagnosticReport.template.model.d.ts +15 -0
  255. package/dist/search-models/templates/DiagnosticReport.template.model.js +1 -0
  256. package/dist/search-models/templates/Encounter.template.model.d.ts +17 -0
  257. package/dist/search-models/templates/Encounter.template.model.js +1 -0
  258. package/dist/search-models/templates/Immunization.template.model.d.ts +18 -0
  259. package/dist/search-models/templates/Immunization.template.model.js +2 -0
  260. package/dist/search-models/templates/Medication.template.model.d.ts +37 -0
  261. package/dist/search-models/templates/Medication.template.model.js +1 -0
  262. package/dist/search-models/templates/Observation.template.model.d.ts +18 -0
  263. package/dist/search-models/templates/Observation.template.model.js +1 -0
  264. package/dist/search-models/templates/Procedure.template.model.d.ts +17 -0
  265. package/dist/search-models/templates/Procedure.template.model.js +1 -0
  266. package/dist/search-models/templates/ServiceRequest.template.model.d.ts +16 -0
  267. package/dist/search-models/templates/ServiceRequest.template.model.js +1 -0
  268. package/dist/search-models/templates/Specimen.template.model.d.ts +12 -0
  269. package/dist/search-models/templates/Specimen.template.model.js +1 -0
  270. package/dist/search-models/templates/index.d.ts +14 -0
  271. package/dist/search-models/templates/index.js +14 -0
  272. package/dist/terminology-models/AtcModel.d.ts +15 -0
  273. package/dist/terminology-models/AtcModel.js +2 -0
  274. package/dist/terminology-models/CommonModels.d.ts +70 -0
  275. package/dist/terminology-models/CommonModels.js +55 -0
  276. package/dist/terminology-models/FhirModels.d.ts +60 -0
  277. package/dist/terminology-models/FhirModels.js +34 -0
  278. package/dist/terminology-models/LoincModels.d.ts +24 -0
  279. package/dist/terminology-models/LoincModels.js +2 -0
  280. package/dist/terminology-models/SnomedModels.d.ts +13 -0
  281. package/dist/terminology-models/SnomedModels.js +2 -0
  282. package/dist/terminology-models/index.d.ts +6 -0
  283. package/dist/terminology-models/index.js +6 -0
  284. package/docs/UHC_FHIR_UTILS_MIGRATION.md +51 -8
  285. 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,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared.js';
2
+ export declare function organizationFlatToFhirR4(claims: FlatClaims): FhirResource;
3
+ export declare function organizationFhirR4ToFlat(resource: FhirResource): FlatClaims;
@@ -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,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared.js';
2
+ export declare function practitionerRoleFhirR4ToFlat(resource: FhirResource, _context?: string): FlatClaims;
3
+ export declare function practitionerRoleFlatToFhirR4(claims: FlatClaims): FhirResource;
@@ -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,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared.js';
2
+ export declare function procedureFlatToFhirR4(claims: FlatClaims): FhirResource;
3
+ export declare function procedureFhirR4ToFlat(resource: FhirResource): FlatClaims;
@@ -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,3 @@
1
+ import type { FhirResource, FlatClaims } from './convert-shared.js';
2
+ export declare function relatedPersonFlatToFhirR4(claims: FlatClaims): FhirResource;
3
+ export declare function relatedPersonFhirR4ToFlat(resource: FhirResource): FlatClaims;
@@ -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;