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,181 @@
1
+ // Copyright 2026 Conéctate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ // File: src/utils/convert-shared.ts
3
+ export function isPlainObject(value) {
4
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
5
+ }
6
+ export function codingFromValue(value) {
7
+ if (!value)
8
+ return undefined;
9
+ const [system, code] = value.split('|');
10
+ if (!code)
11
+ return [{ code: system }];
12
+ return system ? [{ system, code }] : [{ code }];
13
+ }
14
+ export function codingToValue(coding) {
15
+ if (!coding?.code)
16
+ return undefined;
17
+ return coding.system ? `${coding.system}|${coding.code}` : coding.code;
18
+ }
19
+ export function referenceToValue(reference) {
20
+ return reference?.reference;
21
+ }
22
+ export function referenceListToCsv(references) {
23
+ const values = (references || [])
24
+ .map((item) => item?.reference)
25
+ .filter((item) => Boolean(item));
26
+ return values.length ? values.join(',') : undefined;
27
+ }
28
+ export function codingListToCsv(codings) {
29
+ const values = (codings || [])
30
+ .map((item) => codingToValue(item))
31
+ .filter((item) => Boolean(item));
32
+ return values.length ? values.join(',') : undefined;
33
+ }
34
+ export function requireClaim(claims, key) {
35
+ const value = claims[key];
36
+ if (!value)
37
+ throw new Error(`Missing required claim: ${key}`);
38
+ return value;
39
+ }
40
+ export function requireSubjectIdentifier(value, key) {
41
+ if (!value.startsWith('urn:') && !value.startsWith('did:web:')) {
42
+ throw new Error(`Invalid ${key}: expected urn:* or did:web:*`);
43
+ }
44
+ }
45
+ export function requireDidWeb(value, key) {
46
+ if (!value.startsWith('did:web:')) {
47
+ throw new Error(`Invalid ${key}: expected did:web:*`);
48
+ }
49
+ }
50
+ function stringifyClaimLeaf(value) {
51
+ if (value === undefined || value === null)
52
+ return undefined;
53
+ if (typeof value === 'string')
54
+ return value;
55
+ if (typeof value === 'number' || typeof value === 'boolean')
56
+ return String(value);
57
+ return undefined;
58
+ }
59
+ function flattenClaimPath(prefix, value, out) {
60
+ const primitive = stringifyClaimLeaf(value);
61
+ if (primitive !== undefined) {
62
+ out[prefix] = primitive;
63
+ if (typeof value === 'number' || typeof value === 'boolean') {
64
+ out[`${prefix}#type`] = typeof value;
65
+ }
66
+ return;
67
+ }
68
+ if (Array.isArray(value)) {
69
+ value.forEach((entry, index) => {
70
+ flattenClaimPath(`${prefix}[${index}]`, entry, out);
71
+ });
72
+ return;
73
+ }
74
+ if (isPlainObject(value)) {
75
+ for (const [key, nestedValue] of Object.entries(value)) {
76
+ if (key === 'claims' && prefix.endsWith('.meta'))
77
+ continue;
78
+ if (key === 'meta' && isPlainObject(nestedValue) && 'claims' in nestedValue) {
79
+ const nestedMeta = { ...nestedValue };
80
+ delete nestedMeta.claims;
81
+ if (Object.keys(nestedMeta).length === 0)
82
+ continue;
83
+ flattenClaimPath(`${prefix}.${key}`, nestedMeta, out);
84
+ continue;
85
+ }
86
+ flattenClaimPath(`${prefix}.${key}`, nestedValue, out);
87
+ }
88
+ }
89
+ }
90
+ function parseClaimPath(path) {
91
+ const segments = [];
92
+ const re = /([^[.\]]+)|\[(\d+)\]/g;
93
+ let match;
94
+ while ((match = re.exec(path)) !== null) {
95
+ if (match[1])
96
+ segments.push(match[1]);
97
+ else if (match[2])
98
+ segments.push(Number(match[2]));
99
+ }
100
+ return segments;
101
+ }
102
+ function coerceClaimLeaf(value, typeHint) {
103
+ if (typeHint === 'boolean')
104
+ return value === 'true';
105
+ if (typeHint === 'number')
106
+ return Number(value);
107
+ return value;
108
+ }
109
+ function assignInflatedPath(target, path, value, typeHint) {
110
+ const segments = parseClaimPath(path);
111
+ if (segments.length === 0)
112
+ return;
113
+ let cursor = target;
114
+ for (let index = 0; index < segments.length; index += 1) {
115
+ const segment = segments[index];
116
+ const nextSegment = segments[index + 1];
117
+ const isLast = index === segments.length - 1;
118
+ if (typeof segment === 'number') {
119
+ if (!Array.isArray(cursor))
120
+ return;
121
+ if (isLast) {
122
+ cursor[segment] = coerceClaimLeaf(value, typeHint);
123
+ return;
124
+ }
125
+ if (cursor[segment] === undefined)
126
+ cursor[segment] = typeof nextSegment === 'number' ? [] : {};
127
+ cursor = cursor[segment];
128
+ continue;
129
+ }
130
+ if (!isPlainObject(cursor))
131
+ return;
132
+ if (isLast) {
133
+ cursor[segment] = coerceClaimLeaf(value, typeHint);
134
+ return;
135
+ }
136
+ if (cursor[segment] === undefined)
137
+ cursor[segment] = typeof nextSegment === 'number' ? [] : {};
138
+ cursor = cursor[segment];
139
+ }
140
+ }
141
+ /**
142
+ * Generic structural fallback for unsupported resources.
143
+ */
144
+ export function fhirResourceToFlatClaims(resource, context = 'org.hl7.fhir.api') {
145
+ if (!resource?.resourceType) {
146
+ throw new Error('FHIR resource must define resourceType.');
147
+ }
148
+ const out = { '@context': context };
149
+ for (const [key, value] of Object.entries(resource)) {
150
+ if (key === 'resourceType')
151
+ continue;
152
+ flattenClaimPath(`${resource.resourceType}.${key}`, value, out);
153
+ }
154
+ return out;
155
+ }
156
+ /**
157
+ * Generic structural regeneration for unsupported resources.
158
+ */
159
+ export function flatClaimsToFhirResource(claims) {
160
+ const typeHints = new Map();
161
+ for (const [key, value] of Object.entries(claims || {})) {
162
+ if (key.endsWith('#type') && typeof value === 'string') {
163
+ typeHints.set(key.slice(0, -5), value);
164
+ }
165
+ }
166
+ const entries = Object.entries(claims || {}).filter(([key, value]) => key !== '@context' && !key.endsWith('#type') && value !== undefined);
167
+ const firstClaimKey = entries[0]?.[0];
168
+ if (!firstClaimKey || !firstClaimKey.includes('.')) {
169
+ throw new Error('Flat claims must contain at least one contextualized resource claim.');
170
+ }
171
+ const resourceType = firstClaimKey.split('.')[0];
172
+ const resource = { resourceType };
173
+ for (const [key, value] of entries) {
174
+ if (typeof value !== 'string')
175
+ continue;
176
+ if (!key.startsWith(`${resourceType}.`))
177
+ continue;
178
+ assignInflatedPath(resource, key.slice(resourceType.length + 1), value, typeHints.get(key));
179
+ }
180
+ return resource;
181
+ }
@@ -0,0 +1,24 @@
1
+ export * from './convert-shared.js';
2
+ export * from './convert-allergy-intolerance.js';
3
+ export * from './convert-appointment-response.js';
4
+ export * from './convert-appointment.js';
5
+ export * from './convert-care-plan.js';
6
+ export * from './convert-clinical-impression.js';
7
+ export * from './convert-composition.js';
8
+ export * from './convert-consent.js';
9
+ export * from './convert-condition.js';
10
+ export * from './convert-coverage.js';
11
+ export * from './convert-device-use-statement.js';
12
+ export * from './convert-device.js';
13
+ export * from './convert-diagnostic-report.js';
14
+ export * from './convert-document-reference.js';
15
+ export * from './convert-encounter.js';
16
+ export * from './convert-flag.js';
17
+ export * from './convert-immunization.js';
18
+ export * from './convert-location.js';
19
+ export * from './convert-medication-statement.js';
20
+ export * from './convert-observation.js';
21
+ export * from './convert-organization.js';
22
+ export * from './convert-practitioner-role.js';
23
+ export * from './convert-procedure.js';
24
+ export * from './convert-related-person.js';
@@ -0,0 +1,24 @@
1
+ export * from './convert-shared.js';
2
+ export * from './convert-allergy-intolerance.js';
3
+ export * from './convert-appointment-response.js';
4
+ export * from './convert-appointment.js';
5
+ export * from './convert-care-plan.js';
6
+ export * from './convert-clinical-impression.js';
7
+ export * from './convert-composition.js';
8
+ export * from './convert-consent.js';
9
+ export * from './convert-condition.js';
10
+ export * from './convert-coverage.js';
11
+ export * from './convert-device-use-statement.js';
12
+ export * from './convert-device.js';
13
+ export * from './convert-diagnostic-report.js';
14
+ export * from './convert-document-reference.js';
15
+ export * from './convert-encounter.js';
16
+ export * from './convert-flag.js';
17
+ export * from './convert-immunization.js';
18
+ export * from './convert-location.js';
19
+ export * from './convert-medication-statement.js';
20
+ export * from './convert-observation.js';
21
+ export * from './convert-organization.js';
22
+ export * from './convert-practitioner-role.js';
23
+ export * from './convert-procedure.js';
24
+ export * from './convert-related-person.js';
@@ -0,0 +1,9 @@
1
+ import type { FhirBundle, FhirResource } from './fhir-types.js';
2
+ export declare function readBundleResources<TResource extends FhirResource = FhirResource>(bundle: FhirBundle<TResource>): readonly TResource[];
3
+ export declare function findBundleResources<TResource extends FhirResource = FhirResource>(bundle: FhirBundle, resourceType: string): readonly TResource[];
4
+ /** Traverses top-level and native contained resources without changing ownership. */
5
+ export declare function walkBundleResources(bundle: FhirBundle): readonly FhirResource[];
6
+ /** Classifies top-level Bundle resources in encounter order without cloning or mutation. */
7
+ export declare function classifyBundleResources(bundle: FhirBundle): ReadonlyMap<string, readonly FhirResource[]>;
8
+ /** Resolves `ResourceType/id`, `urn:uuid:*`, an entry fullUrl, or a bare resource id. */
9
+ export declare function findBundleResourceByReference(bundle: FhirBundle, reference: string): FhirResource | undefined;
@@ -0,0 +1,43 @@
1
+ export function readBundleResources(bundle) {
2
+ if (bundle.resourceType !== 'Bundle')
3
+ throw new TypeError('fhir_bundle_required');
4
+ return Object.freeze((bundle.entry ?? []).flatMap(entry => entry.resource ? [entry.resource] : []));
5
+ }
6
+ export function findBundleResources(bundle, resourceType) {
7
+ return Object.freeze(readBundleResources(bundle).filter(resource => resource.resourceType === resourceType));
8
+ }
9
+ /** Traverses top-level and native contained resources without changing ownership. */
10
+ export function walkBundleResources(bundle) {
11
+ const output = [];
12
+ const visit = (resource) => {
13
+ output.push(resource);
14
+ for (const child of resource.contained ?? [])
15
+ visit(child);
16
+ };
17
+ for (const resource of readBundleResources(bundle))
18
+ visit(resource);
19
+ return Object.freeze(output);
20
+ }
21
+ /** Classifies top-level Bundle resources in encounter order without cloning or mutation. */
22
+ export function classifyBundleResources(bundle) {
23
+ const classified = new Map();
24
+ for (const resource of readBundleResources(bundle)) {
25
+ const resources = classified.get(resource.resourceType) ?? [];
26
+ resources.push(resource);
27
+ classified.set(resource.resourceType, resources);
28
+ }
29
+ return classified;
30
+ }
31
+ /** Resolves `ResourceType/id`, `urn:uuid:*`, an entry fullUrl, or a bare resource id. */
32
+ export function findBundleResourceByReference(bundle, reference) {
33
+ const target = reference.trim();
34
+ if (!target)
35
+ throw new TypeError('fhir_reference_required');
36
+ const directEntry = bundle.entry?.find(entry => entry.fullUrl === target);
37
+ if (directEntry?.resource)
38
+ return directEntry.resource;
39
+ const [resourceType, id] = target.includes('/')
40
+ ? target.split('/', 2)
41
+ : [undefined, target.startsWith('urn:uuid:') ? target.slice('urn:uuid:'.length) : target];
42
+ return readBundleResources(bundle).find(resource => resource.id === id && (!resourceType || resource.resourceType === resourceType));
43
+ }
@@ -0,0 +1,18 @@
1
+ export type FhirSearchParameterType = 'number' | 'date' | 'string' | 'token' | 'reference' | 'composite' | 'quantity' | 'uri';
2
+ export type FhirSearchPrefix = 'eq' | 'ne' | 'gt' | 'lt' | 'ge' | 'le' | 'sa' | 'eb' | 'ap';
3
+ export type FhirSearchParameter = Readonly<{
4
+ name: string;
5
+ type: FhirSearchParameterType;
6
+ value: string | number;
7
+ prefix?: FhirSearchPrefix;
8
+ system?: string;
9
+ unit?: string;
10
+ }>;
11
+ /** Parses one typed FHIR query value without the lossy integer coercion of the retired UHC helper. */
12
+ export declare function parseFhirSearchParameter(input: Readonly<{
13
+ name: string;
14
+ type: FhirSearchParameterType;
15
+ value: string;
16
+ }>): FhirSearchParameter;
17
+ /** Repeats parameters for AND; callers may use comma-separated values for FHIR OR. */
18
+ export declare function buildFhirSearchQuery(parameters: readonly FhirSearchParameter[]): string;
@@ -0,0 +1,52 @@
1
+ const PREFIX = /^(eq|ne|gt|lt|ge|le|sa|eb|ap)/;
2
+ /** Parses one typed FHIR query value without the lossy integer coercion of the retired UHC helper. */
3
+ export function parseFhirSearchParameter(input) {
4
+ const name = required(input.name, 'fhir_search_name_required');
5
+ const raw = required(input.value, 'fhir_search_value_required');
6
+ if (input.type === 'token') {
7
+ const separator = raw.lastIndexOf('|');
8
+ return Object.freeze({ name, type: input.type, value: separator < 0 ? raw : raw.slice(separator + 1), ...(separator < 0 ? {} : { system: raw.slice(0, separator) }) });
9
+ }
10
+ if (input.type === 'quantity') {
11
+ const match = raw.match(PREFIX);
12
+ const withoutPrefix = match ? raw.slice(2) : raw;
13
+ const [numberValue, system, unit] = withoutPrefix.split('|');
14
+ const value = Number(numberValue);
15
+ if (!Number.isFinite(value))
16
+ throw new TypeError('fhir_search_quantity_invalid');
17
+ return Object.freeze({ name, type: input.type, value, ...(match ? { prefix: match[1] } : {}), ...(system ? { system } : {}), ...(unit ? { unit } : {}) });
18
+ }
19
+ if (input.type === 'number') {
20
+ const match = raw.match(PREFIX);
21
+ const value = Number(match ? raw.slice(2) : raw);
22
+ if (!Number.isFinite(value))
23
+ throw new TypeError('fhir_search_number_invalid');
24
+ return Object.freeze({ name, type: input.type, value, ...(match ? { prefix: match[1] } : {}) });
25
+ }
26
+ if (input.type === 'date') {
27
+ const match = raw.match(PREFIX);
28
+ return Object.freeze({ name, type: input.type, value: match ? raw.slice(2) : raw, ...(match ? { prefix: match[1] } : {}) });
29
+ }
30
+ return Object.freeze({ name, type: input.type, value: raw });
31
+ }
32
+ /** Repeats parameters for AND; callers may use comma-separated values for FHIR OR. */
33
+ export function buildFhirSearchQuery(parameters) {
34
+ const query = new URLSearchParams();
35
+ for (const parameter of parameters) {
36
+ const prefix = parameter.prefix ?? '';
37
+ const scalar = String(parameter.value);
38
+ const value = parameter.type === 'token' && parameter.system
39
+ ? `${parameter.system}|${scalar}`
40
+ : parameter.type === 'quantity' && (parameter.system || parameter.unit)
41
+ ? `${prefix}${scalar}|${parameter.system ?? ''}|${parameter.unit ?? ''}`
42
+ : `${prefix}${scalar}`;
43
+ query.append(required(parameter.name, 'fhir_search_name_required'), value);
44
+ }
45
+ return query.toString();
46
+ }
47
+ function required(value, error) {
48
+ const normalized = value.trim();
49
+ if (!normalized)
50
+ throw new TypeError(error);
51
+ return normalized;
52
+ }
@@ -0,0 +1,11 @@
1
+ import type { FhirContactPoint } from './fhir-types.js';
2
+ /** Builds the FHIR token wire form after rejecting empty or ambiguous input. */
3
+ export declare function makeFhirToken(system: string, code: string): string;
4
+ /** Escapes FHIR search delimiters according to the search value grammar. */
5
+ export declare function escapeFhirSearchValue(value: string): string;
6
+ /** Builds one comma-separated FHIR OR value; repeated query keys remain AND. */
7
+ export declare function joinFhirOrList(values?: readonly (string | number)[]): string | undefined;
8
+ /** Converts valid ContactPoint values to token search values. */
9
+ export declare function telecomToTokens(resource: Readonly<{
10
+ telecom?: readonly FhirContactPoint[];
11
+ }>): readonly string[];
@@ -0,0 +1,26 @@
1
+ /** Builds the FHIR token wire form after rejecting empty or ambiguous input. */
2
+ export function makeFhirToken(system, code) {
3
+ const normalizedSystem = required(system, 'fhir_token_system_required');
4
+ const normalizedCode = required(code, 'fhir_token_code_required');
5
+ if (normalizedSystem.includes('|') || normalizedCode.includes('|'))
6
+ throw new TypeError('fhir_token_invalid');
7
+ return `${normalizedSystem}|${normalizedCode}`;
8
+ }
9
+ /** Escapes FHIR search delimiters according to the search value grammar. */
10
+ export function escapeFhirSearchValue(value) {
11
+ return String(value).replace(/[\\,|$]/g, '\\$&');
12
+ }
13
+ /** Builds one comma-separated FHIR OR value; repeated query keys remain AND. */
14
+ export function joinFhirOrList(values) {
15
+ return values?.length ? values.map(value => escapeFhirSearchValue(String(value))).join(',') : undefined;
16
+ }
17
+ /** Converts valid ContactPoint values to token search values. */
18
+ export function telecomToTokens(resource) {
19
+ return Object.freeze((resource.telecom ?? []).flatMap(point => point.system && point.value?.trim() ? [makeFhirToken(point.system, point.value.trim())] : []));
20
+ }
21
+ function required(value, error) {
22
+ const normalized = value.trim();
23
+ if (!normalized)
24
+ throw new TypeError(error);
25
+ return normalized;
26
+ }
@@ -0,0 +1,77 @@
1
+ /** Version-neutral FHIR primitives used by flat-claim adapters. */
2
+ export type FhirPrimitive = string | number | boolean;
3
+ export type FhirCoding = Readonly<{
4
+ system?: string;
5
+ version?: string;
6
+ code?: string;
7
+ display?: string;
8
+ userSelected?: boolean;
9
+ }>;
10
+ export type FhirCodeableConcept = Readonly<{
11
+ coding?: readonly FhirCoding[];
12
+ text?: string;
13
+ }>;
14
+ export type FhirIdentifier = Readonly<{
15
+ use?: string;
16
+ type?: FhirCodeableConcept;
17
+ system?: string;
18
+ value?: string;
19
+ period?: FhirPeriod;
20
+ assigner?: FhirReference;
21
+ }>;
22
+ export type FhirReference = Readonly<{
23
+ reference?: string;
24
+ type?: string;
25
+ identifier?: FhirIdentifier;
26
+ display?: string;
27
+ }>;
28
+ export type FhirQuantity = Readonly<{
29
+ value?: number;
30
+ comparator?: '<' | '<=' | '>=' | '>';
31
+ unit?: string;
32
+ system?: string;
33
+ code?: string;
34
+ }>;
35
+ export type FhirPeriod = Readonly<{
36
+ start?: string;
37
+ end?: string;
38
+ }>;
39
+ export type FhirAnnotation = Readonly<{
40
+ authorReference?: FhirReference;
41
+ authorString?: string;
42
+ time?: string;
43
+ text: string;
44
+ }>;
45
+ export type FhirContactPoint = Readonly<{
46
+ system?: 'phone' | 'fax' | 'email' | 'pager' | 'url' | 'sms' | 'other';
47
+ value?: string;
48
+ use?: 'home' | 'work' | 'temp' | 'old' | 'mobile';
49
+ rank?: number;
50
+ period?: FhirPeriod;
51
+ }>;
52
+ export type FhirResource = Readonly<{
53
+ resourceType: string;
54
+ id?: string;
55
+ language?: string;
56
+ meta?: Readonly<Record<string, unknown>>;
57
+ contained?: readonly FhirResource[];
58
+ [key: string]: unknown;
59
+ }>;
60
+ export type FhirBundleEntry<TResource extends FhirResource = FhirResource> = Readonly<{
61
+ fullUrl?: string;
62
+ resource?: TResource;
63
+ request?: Readonly<{
64
+ method?: string;
65
+ url?: string;
66
+ }>;
67
+ response?: Readonly<{
68
+ status?: string;
69
+ location?: string;
70
+ }>;
71
+ }>;
72
+ export type FhirBundle<TResource extends FhirResource = FhirResource> = FhirResource & Readonly<{
73
+ resourceType: 'Bundle';
74
+ type?: string;
75
+ total?: number;
76
+ entry?: readonly FhirBundleEntry<TResource>[];
77
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { FhirCoding, FhirIdentifier, FhirQuantity, FhirReference } from './fhir-types.js';
2
+ /** Serializes a Coding as the established `system|code` flat token. */
3
+ export declare function codingToToken(coding: FhirCoding | undefined): string | undefined;
4
+ /** Parses a flat coding token without treating URI colons or slashes as separators. */
5
+ export declare function tokenToCoding(token: string | undefined): FhirCoding | undefined;
6
+ /** Serializes an Identifier without discarding its assigning system. */
7
+ export declare function identifierToToken(identifier: FhirIdentifier | undefined): string | undefined;
8
+ export declare function tokenToIdentifier(token: string | undefined): FhirIdentifier | undefined;
9
+ export declare function referenceToString(reference: FhirReference | undefined): string | undefined;
10
+ export declare function stringToReference(reference: string | undefined): FhirReference | undefined;
11
+ /** Serializes Quantity as `value|system|code`; unit remains display-only. */
12
+ export declare function quantityToToken(quantity: FhirQuantity | undefined): string | undefined;
13
+ export declare function tokenToQuantity(token: string | undefined): FhirQuantity | undefined;
@@ -0,0 +1,53 @@
1
+ /** Serializes a Coding as the established `system|code` flat token. */
2
+ export function codingToToken(coding) {
3
+ const code = coding?.code?.trim();
4
+ if (!code)
5
+ return undefined;
6
+ const system = coding?.system?.trim();
7
+ return system ? `${system}|${code}` : code;
8
+ }
9
+ /** Parses a flat coding token without treating URI colons or slashes as separators. */
10
+ export function tokenToCoding(token) {
11
+ const value = token?.trim();
12
+ if (!value)
13
+ return undefined;
14
+ const separator = value.lastIndexOf('|');
15
+ return separator < 0
16
+ ? Object.freeze({ code: value })
17
+ : Object.freeze({ system: value.slice(0, separator) || undefined, code: value.slice(separator + 1) });
18
+ }
19
+ /** Serializes an Identifier without discarding its assigning system. */
20
+ export function identifierToToken(identifier) {
21
+ const value = identifier?.value?.trim();
22
+ if (!value)
23
+ return undefined;
24
+ const system = identifier?.system?.trim();
25
+ return system ? `${system}|${value}` : value;
26
+ }
27
+ export function tokenToIdentifier(token) {
28
+ const coding = tokenToCoding(token);
29
+ return coding?.code ? Object.freeze({ system: coding.system, value: coding.code }) : undefined;
30
+ }
31
+ export function referenceToString(reference) {
32
+ return reference?.reference?.trim() || undefined;
33
+ }
34
+ export function stringToReference(reference) {
35
+ const value = reference?.trim();
36
+ return value ? Object.freeze({ reference: value }) : undefined;
37
+ }
38
+ /** Serializes Quantity as `value|system|code`; unit remains display-only. */
39
+ export function quantityToToken(quantity) {
40
+ if (quantity?.value === undefined || !Number.isFinite(quantity.value))
41
+ return undefined;
42
+ return [String(quantity.value), quantity.system?.trim() ?? '', quantity.code?.trim() ?? ''].join('|');
43
+ }
44
+ export function tokenToQuantity(token) {
45
+ const value = token?.trim();
46
+ if (!value)
47
+ return undefined;
48
+ const [numberValue, system, code] = value.split('|');
49
+ const numeric = Number(numberValue);
50
+ if (!Number.isFinite(numeric))
51
+ throw new TypeError('fhir_quantity_token_invalid');
52
+ return Object.freeze({ value: numeric, ...(system ? { system } : {}), ...(code ? { code, unit: code } : {}) });
53
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Browser-safe FHIR R5 Group contract for research-team descriptions.
3
+ *
4
+ * Group membership is descriptive. It never grants authorization, permission
5
+ * or a SMART scope; those decisions remain separate Consent and credential
6
+ * contracts.
7
+ *
8
+ * @see https://hl7.org/fhir/R5/group.html
9
+ * @see https://hl7.org/fhir/R5/group-search.html
10
+ */
11
+ export declare const GroupR5Version: "5.0.0";
12
+ export declare const GroupR5TypeSystem: "http://hl7.org/fhir/group-type";
13
+ export declare const GroupR5TypeCodes: readonly ["person", "animal", "practitioner", "device", "careteam", "healthcareservice", "location", "organization", "relatedperson", "specimen"];
14
+ export type GroupR5TypeCode = (typeof GroupR5TypeCodes)[number];
15
+ export declare const GroupR5MembershipSystem: "http://hl7.org/fhir/group-membership-basis";
16
+ export declare const GroupR5MembershipCodes: readonly ["definitional", "enumerated"];
17
+ export type GroupR5MembershipCode = (typeof GroupR5MembershipCodes)[number];
18
+ export declare const GroupR5Bindings: Readonly<{
19
+ readonly type: Readonly<{
20
+ valueSet: "http://hl7.org/fhir/ValueSet/group-type";
21
+ strength: "required";
22
+ }>;
23
+ readonly membership: Readonly<{
24
+ valueSet: "http://hl7.org/fhir/ValueSet/group-membership-basis";
25
+ strength: "required";
26
+ }>;
27
+ }>;
28
+ export type GroupSearchParameterType = 'composite' | 'reference' | 'string' | 'token';
29
+ export type GroupR5SearchParameter = Readonly<{
30
+ code: string;
31
+ type: GroupSearchParameterType;
32
+ expression: string;
33
+ components: readonly string[];
34
+ }>;
35
+ /** Exact resource-specific SearchParameters published by FHIR R5 5.0.0. */
36
+ export declare const GroupR5SearchParameterCatalog: readonly GroupR5SearchParameter[];
37
+ /** Canonical Group flat-claim names. Never repeat these storage keys as literals. */
38
+ export declare const GroupClaim: Readonly<{
39
+ readonly Characteristic: "Group.characteristic";
40
+ readonly CharacteristicReference: "Group.characteristic-reference";
41
+ readonly CharacteristicValue: "Group.characteristic-value";
42
+ readonly Code: "Group.code";
43
+ readonly Exclude: "Group.exclude";
44
+ readonly Identifier: "Group.identifier";
45
+ readonly ManagingEntity: "Group.managing-entity";
46
+ readonly Member: "Group.member";
47
+ readonly Membership: "Group.membership";
48
+ readonly Name: "Group.name";
49
+ readonly Type: "Group.type";
50
+ readonly Value: "Group.value";
51
+ }>;
52
+ declare const standardSearchClaims: readonly ("Group.characteristic" | "Group.code" | "Group.identifier" | "Group.membership" | "Group.name" | "Group.type" | "Group.characteristic-reference" | "Group.characteristic-value" | "Group.exclude" | "Group.managing-entity" | "Group.member" | "Group.value")[];
53
+ /** Canonical claims derived only from the official resource-specific catalogue. */
54
+ export declare const GroupFlatClaimCatalog: Readonly<{
55
+ standardSearch: readonly ("Group.characteristic" | "Group.code" | "Group.identifier" | "Group.membership" | "Group.name" | "Group.type" | "Group.characteristic-reference" | "Group.characteristic-value" | "Group.exclude" | "Group.managing-entity" | "Group.member" | "Group.value")[];
56
+ all: readonly ("Group.characteristic" | "Group.code" | "Group.identifier" | "Group.membership" | "Group.name" | "Group.type" | "Group.characteristic-reference" | "Group.characteristic-value" | "Group.exclude" | "Group.managing-entity" | "Group.member" | "Group.value")[];
57
+ }>;
58
+ export type GroupR5SearchClaim = (typeof standardSearchClaims)[number];
59
+ export type GroupR5SearchClaims = Readonly<Partial<Record<GroupR5SearchClaim, readonly string[]>>>;
60
+ export type GroupR5FlatClaimsResource = Readonly<{
61
+ resourceType: 'Group';
62
+ id: string;
63
+ meta: Readonly<{
64
+ claims: Readonly<Record<string, readonly string[]>>;
65
+ }>;
66
+ }>;
67
+ export type GroupR5Reference = Readonly<{
68
+ reference: string;
69
+ type?: string;
70
+ display?: string;
71
+ }>;
72
+ export type GroupR5Period = Readonly<{
73
+ start?: string;
74
+ end?: string;
75
+ }>;
76
+ export type GroupPractitionerRoleMember = Readonly<{
77
+ entity: Readonly<{
78
+ reference: `PractitionerRole/${string}`;
79
+ type: 'PractitionerRole';
80
+ display?: string;
81
+ }>;
82
+ period?: GroupR5Period;
83
+ inactive?: boolean;
84
+ }>;
85
+ export type GroupR5ResearchTeam = Readonly<Record<string, unknown> & {
86
+ resourceType: 'Group';
87
+ id?: string;
88
+ type: 'practitioner';
89
+ membership: 'enumerated';
90
+ member: readonly GroupPractitionerRoleMember[];
91
+ }>;
92
+ /**
93
+ * Normalizes the members used by an enumerated professional research team.
94
+ * Every entity is a native PractitionerRole reference; a Practitioner or an
95
+ * employee identifier cannot substitute for the registered role assignment.
96
+ */
97
+ export declare function normalizeGroupPractitionerRoleMembers(input: unknown): readonly GroupPractitionerRoleMember[];
98
+ /**
99
+ * Normalizes the Group profile used to describe an explicit professional
100
+ * ResearchStudy team. This data is descriptive and authorization-shaped
101
+ * properties are rejected at every depth.
102
+ */
103
+ export declare function normalizeGroupR5ResearchTeam(input: unknown): GroupR5ResearchTeam;
104
+ /**
105
+ * Projects all populated official resource-specific R5 Group SearchParameters
106
+ * into flat `resource.meta.claims`. A referenced characteristic is indexed by
107
+ * `characteristic-reference`, not as the token-valued `value` parameter.
108
+ *
109
+ * @see https://hl7.org/fhir/R5/group-search.html
110
+ */
111
+ export declare function projectGroupR5SearchClaims(input: unknown): GroupR5SearchClaims;
112
+ /** Projects native-shaped Group input to the claims-only GW persistence shape. */
113
+ export declare function projectGroupR5FlatClaimsResource(input: unknown): GroupR5FlatClaimsResource;
114
+ /** Projects one correlated claims-only GW resource per PractitionerRole member. */
115
+ export declare function projectGroupPractitionerRoleMemberFlatClaimResources(input: Readonly<{
116
+ groupId: string;
117
+ members: unknown;
118
+ }>): readonly GroupR5FlatClaimsResource[];
119
+ /** Validates and freezes a claims-only Group GW resource. */
120
+ export declare function normalizeGroupR5FlatClaimsResource(input: unknown): GroupR5FlatClaimsResource;
121
+ export {};