fhir-data-utils-ts 0.3.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codex/skills/govern-fhir-data-utilities/SKILL.md +35 -0
- package/.codex/skills/govern-fhir-observation-components/SKILL.md +11 -0
- package/CHANGELOG.md +63 -0
- package/README.md +44 -0
- package/dist/appointment-communication-test-data.d.ts +63 -0
- package/dist/appointment-communication-test-data.js +77 -0
- package/dist/builders/department-service-graph.d.ts +32 -0
- package/dist/builders/department-service-graph.js +102 -0
- package/dist/builders/device-compliance-graph.d.ts +51 -0
- package/dist/builders/device-compliance-graph.js +115 -0
- package/dist/builders/index.d.ts +3 -0
- package/dist/builders/index.js +3 -0
- package/dist/builders/service-schedule-graph.d.ts +58 -0
- package/dist/builders/service-schedule-graph.js +149 -0
- package/dist/claims/appointment-claims.d.ts +6 -0
- package/dist/claims/appointment-claims.js +6 -0
- package/dist/claims/composition-claims.d.ts +1 -0
- package/dist/claims/composition-claims.js +1 -0
- package/dist/claims/device-metric-claims.d.ts +16 -0
- package/dist/claims/device-metric-claims.js +25 -0
- package/dist/claims/healthcare-service-claims.d.ts +32 -0
- package/dist/claims/healthcare-service-claims.js +54 -0
- package/dist/claims/index.d.ts +4 -0
- package/dist/claims/index.js +4 -0
- package/dist/claims/location-claims.d.ts +3 -0
- package/dist/claims/location-claims.js +6 -0
- package/dist/claims/organization-claims.d.ts +3 -1
- package/dist/claims/organization-claims.js +4 -1
- package/dist/claims/procedure-claims.d.ts +2 -0
- package/dist/claims/procedure-claims.js +4 -0
- package/dist/claims/regulated-authorization-claims.d.ts +17 -0
- package/dist/claims/regulated-authorization-claims.js +27 -0
- package/dist/claims/schedule-slot-claims.d.ts +45 -0
- package/dist/claims/schedule-slot-claims.js +70 -0
- package/dist/constants/fhir-resource-types.d.ts +9 -0
- package/dist/constants/fhir-resource-types.js +3 -0
- package/dist/converters/convert-appointment-communication.d.ts +14 -0
- package/dist/converters/convert-appointment-communication.js +97 -0
- package/dist/converters/convert-appointment.js +16 -7
- package/dist/converters/convert-composition.js +12 -2
- package/dist/converters/convert-device-metric.d.ts +3 -0
- package/dist/converters/convert-device-metric.js +37 -0
- package/dist/converters/convert-document-reference.js +5 -0
- package/dist/converters/convert-healthcare-service.d.ts +7 -0
- package/dist/converters/convert-healthcare-service.js +60 -0
- package/dist/converters/convert-location.d.ts +4 -0
- package/dist/converters/convert-location.js +41 -3
- package/dist/converters/convert-organization.d.ts +2 -0
- package/dist/converters/convert-organization.js +20 -3
- package/dist/converters/convert-procedure.d.ts +2 -0
- package/dist/converters/convert-procedure.js +21 -0
- package/dist/converters/convert-regulated-authorization.d.ts +3 -0
- package/dist/converters/convert-regulated-authorization.js +34 -0
- package/dist/converters/convert-schedule-slot.d.ts +9 -0
- package/dist/converters/convert-schedule-slot.js +96 -0
- package/dist/converters/convert-shared.d.ts +10 -0
- package/dist/converters/convert-shared.js +19 -0
- package/dist/converters/index.d.ts +6 -0
- package/dist/converters/index.js +6 -0
- package/dist/converters/materialize-claims-first-resource.d.ts +16 -0
- package/dist/converters/materialize-claims-first-resource.js +61 -0
- package/dist/fhir-bundle.d.ts +21 -0
- package/dist/fhir-bundle.js +74 -0
- package/dist/group-r5.d.ts +12 -0
- package/dist/group-r5.js +20 -0
- package/dist/healthcare-service-specialty-map.d.ts +32 -0
- package/dist/healthcare-service-specialty-map.js +151 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/observation-claims.d.ts +3 -0
- package/dist/observation-claims.js +3 -0
- package/dist/vital-sign-observations.d.ts +75 -1
- package/dist/vital-sign-observations.js +225 -9
- package/docs/CLINICAL_TYPED_ACCESSOR_BOUNDARY.md +44 -0
- package/docs/COMMUNICATION_BUNDLE_CONTRACT.md +61 -0
- package/docs/HEALTHCARE_SERVICE_DEPARTMENT_CATALOG.md +190 -0
- package/docs/UHC_FHIR_UTILS_MIGRATION.md +20 -1
- package/docs/VITAL_SIGN_DAILY_DOCUMENT.md +79 -0
- package/package.json +5 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Clinical Typed Accessor Boundary
|
|
2
|
+
|
|
3
|
+
This package owns the FHIR-neutral claim and projection layer. It does not own
|
|
4
|
+
the mutable SDK `BundleReader` / `BundleEditor` session API.
|
|
5
|
+
|
|
6
|
+
The clinical fields required by the current GDC typed editors are already
|
|
7
|
+
canonical here and survive the native FHIR R4 boundary:
|
|
8
|
+
|
|
9
|
+
| Clinical field | Canonical flat claim | Native FHIR R4 projection |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Observed allergy reaction severity | `AllergyIntolerance.severity` | `AllergyIntolerance.reaction[].severity` |
|
|
12
|
+
| Medication treatment end | `MedicationStatement.effective-period-end` | `MedicationStatement.effectivePeriod.end` |
|
|
13
|
+
| Immunization administration route | `Immunization.route` | `Immunization.route` |
|
|
14
|
+
| Immunization administration site | `Immunization.site` | `Immunization.site` |
|
|
15
|
+
| Observation reference-range text | `Observation.reference-range-text` | `Observation.referenceRange[].text` |
|
|
16
|
+
|
|
17
|
+
`fhir-data-utils-ts` therefore must preserve these fields in claim catalogs,
|
|
18
|
+
FHIR converters and resource graphs. It must not copy the GDC SDK's mutable
|
|
19
|
+
editor classes or transport-aware Bundle session behavior.
|
|
20
|
+
|
|
21
|
+
The layer split is:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
fhir-data-utils-ts
|
|
25
|
+
canonical claims + R4/R5/R6 import/export
|
|
26
|
+
↓
|
|
27
|
+
sos-data-utils-ts
|
|
28
|
+
product-neutral multichannel field schemas
|
|
29
|
+
↓
|
|
30
|
+
sos-sdk-core-ts / sos-sdk-node-ts
|
|
31
|
+
shared orchestration and runtime adapters
|
|
32
|
+
↓
|
|
33
|
+
vet-* / uhc-*
|
|
34
|
+
product forms, portal editors and telephone/chat dialogue
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
When Vet or UHC adds a visual, chat or telephone editor for one of these
|
|
38
|
+
fields, it must consume the canonical claim key from this package. It must not
|
|
39
|
+
maintain a second literal, converter or incompatible getter/setter model.
|
|
40
|
+
|
|
41
|
+
The mutable GDC Bundle API remains documented separately in
|
|
42
|
+
[`gdc-common-utils-ts`](https://github.com/Global-DataCare/gdc-common-utils-ts/blob/main/docs/101-CLINICAL-ENTRY-GETTERS-SETTERS.md)
|
|
43
|
+
and exposed to Node applications by
|
|
44
|
+
[`gdc-sdk-node-ts`](https://github.com/Global-DataCare/gdc-sdk-node-ts/blob/main/docs/101-CLINICAL-ENTRY-GETTERS-SETTERS.md).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Communication Bundle contract
|
|
2
|
+
|
|
3
|
+
Every cross-participant clinical or administrative exchange uses the same
|
|
4
|
+
two-level FHIR envelope. This is the portable contract for Vet, UHC and
|
|
5
|
+
SOSChain channels; HTTP, DIDComm, encryption and recipient resolution remain
|
|
6
|
+
in their owning SDK or service.
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
outer Bundle (type=batch)
|
|
10
|
+
└── Communication
|
|
11
|
+
└── payload.contentAttachment
|
|
12
|
+
├── contentType = application/fhir+json
|
|
13
|
+
└── data = base64(inner Bundle)
|
|
14
|
+
├── type=document | batch | collection
|
|
15
|
+
└── Appointment, DocumentReference, Observation, ...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The outer batch is the delivery command. The Communication supplies sender,
|
|
19
|
+
recipient, subject, status and conversation context. Its single attachment is
|
|
20
|
+
always the inner Bundle. A PDF, image, audio file or `text/calendar` event is
|
|
21
|
+
not another direct Communication attachment: it is a `DocumentReference`
|
|
22
|
+
resource inside the inner Bundle. This keeps one entry point for parsing,
|
|
23
|
+
authorization, persistence and audit regardless of channel.
|
|
24
|
+
|
|
25
|
+
Inner Bundle types keep their ordinary FHIR meaning:
|
|
26
|
+
|
|
27
|
+
- `document` starts with `Composition` and represents an attested document;
|
|
28
|
+
- `batch` contains executable entries and every entry has `request.method` and
|
|
29
|
+
`request.url`;
|
|
30
|
+
- `collection` groups related resources without execution or document order.
|
|
31
|
+
|
|
32
|
+
## Neutral tools and high-level ownership
|
|
33
|
+
|
|
34
|
+
`fhir-data-utils-ts` owns only the FHIR tools. It validates and projects a
|
|
35
|
+
received exchange without owning mutable application sessions:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { readCommunicationBundlePayloads } from 'fhir-data-utils-ts'
|
|
39
|
+
|
|
40
|
+
const payloads = readCommunicationBundlePayloads(receivedOuterBatch)
|
|
41
|
+
const innerBundle = payloads[0].bundle
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The validator fails closed when the outer resource is not a batch Bundle, an outer
|
|
45
|
+
batch entry lacks its request, the Communication has anything other than one
|
|
46
|
+
FHIR Bundle attachment, or the inner Bundle violates its declared type.
|
|
47
|
+
|
|
48
|
+
`sos-sdk-core` owns the high-level Bundle and Communication editor/reader used
|
|
49
|
+
by SOS, Vet and UHC. `sos-data-utils` owns its cross-sector input contracts and
|
|
50
|
+
fixtures. The historical `gdc-*` editors remain compatibility surfaces until
|
|
51
|
+
their consumers migrate; this package neither imports nor wraps them.
|
|
52
|
+
|
|
53
|
+
At the GW persistence boundary, the validated native resources are projected
|
|
54
|
+
to independent `resource.meta.claims` rows. Direct flat-claim CRUD is an
|
|
55
|
+
internal storage operation; it is not a replacement wire format for this
|
|
56
|
+
cross-participant exchange contract.
|
|
57
|
+
|
|
58
|
+
`projectAppointmentCommunicationBatchToFlatGraph(...)` is the first typed
|
|
59
|
+
projection using this boundary. It preserves Appointment timing and references
|
|
60
|
+
and emits the calendar DocumentReference independently. Consumers must not
|
|
61
|
+
decode the attachment or recreate these claims with literals.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Organization departments and healthcare-service catalogs
|
|
2
|
+
|
|
3
|
+
This contract keeps four different concepts separate:
|
|
4
|
+
|
|
5
|
+
1. A legal provider is a FHIR `Organization`.
|
|
6
|
+
2. A suborganization or department is another `Organization` whose
|
|
7
|
+
`partOf` references exactly one parent Organization.
|
|
8
|
+
3. An offered capability is a `HealthcareService` whose `providedBy`
|
|
9
|
+
references the department that provides it.
|
|
10
|
+
4. A physical or virtual delivery place is a `Location`; one
|
|
11
|
+
`HealthcareService` can reference several Locations.
|
|
12
|
+
|
|
13
|
+
A department and every offered `HealthcareService` remain distinct FHIR
|
|
14
|
+
resources. A claims-first directory projects one
|
|
15
|
+
`Organization/<department-id>` and one `HealthcareService/<service-id>` per
|
|
16
|
+
offered service. A blood bank can therefore expose blood donation and plasma
|
|
17
|
+
donation independently. Each service can own different Location references and
|
|
18
|
+
be the actor of a different Schedule; Slot duration and availability follow
|
|
19
|
+
that Schedule rather than the department.
|
|
20
|
+
|
|
21
|
+
`buildServiceScheduleFlatGraph(...)` implements that boundary. It emits one
|
|
22
|
+
independent claims-first `Schedule` plus independent `Slot` rows. A 15-minute
|
|
23
|
+
blood-donation interval and a one-hour plasma-donation interval are represented
|
|
24
|
+
by different `Slot.start`/`Slot.end` pairs; duration is never an invented flat
|
|
25
|
+
claim. `Schedule.actor` contains the applicable `HealthcareService` and
|
|
26
|
+
`Location`, while `Schedule.service-type-reference` retains the exact service.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const bloodAvailability = buildServiceScheduleFlatGraph({
|
|
30
|
+
scheduleId: 'blood-donation-weekday',
|
|
31
|
+
scheduleIdentifier: 'urn:uuid:blood-donation-weekday',
|
|
32
|
+
name: 'Blood donation weekday schedule',
|
|
33
|
+
healthcareServiceReference: 'HealthcareService/blood-donation',
|
|
34
|
+
locationReference: 'Location/blood-donation-room',
|
|
35
|
+
serviceType: 'http://terminology.hl7.org/CodeSystem/service-type|117',
|
|
36
|
+
planningHorizon: { start: '2026-10-01', end: '2026-10-31' },
|
|
37
|
+
slots: [{
|
|
38
|
+
slotId: 'blood-20261001-0900',
|
|
39
|
+
slotIdentifier: 'urn:uuid:blood-20261001-0900',
|
|
40
|
+
status: 'free',
|
|
41
|
+
start: '2026-10-01T09:00:00-07:00',
|
|
42
|
+
end: '2026-10-01T09:15:00-07:00',
|
|
43
|
+
}],
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The adapters use the published R5 `CodeableReference(HealthcareService)` shape
|
|
48
|
+
for `Schedule.serviceType` and `Slot.serviceType`. Schedule and Slot remain
|
|
49
|
+
separate resources because slots change more frequently than their planning
|
|
50
|
+
container.
|
|
51
|
+
|
|
52
|
+
## Reservable capacity inside one place
|
|
53
|
+
|
|
54
|
+
A public donation or extraction point is a parent `Location`. Each independently
|
|
55
|
+
reservable room, booth, chair or bed is a child `Location.partOf` that parent.
|
|
56
|
+
`buildSchedulableLocationFlatResource(...)` creates those child Locations; a
|
|
57
|
+
clone may reuse coordinates but must use a new Location id and identifier.
|
|
58
|
+
|
|
59
|
+
Equipment is not disguised as a place. An apheresis machine is a FHIR `Device`.
|
|
60
|
+
The Schedule's actor list combines the offered `HealthcareService` with every
|
|
61
|
+
resource that must be available together, for example:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
HealthcareService/plasma-donation
|
|
65
|
+
Location/plasma-donation-station-1
|
|
66
|
+
Device/apheresis-machine-1
|
|
67
|
+
PractitionerRole/plasma-professional-1
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Closing one station suspends its Location or blocks/deactivates its Schedule;
|
|
71
|
+
it does not cancel sibling stations. FHIR R4 materializes the governed physical
|
|
72
|
+
coding as `Location.physicalType`; R5 materializes it as `Location.form`.
|
|
73
|
+
|
|
74
|
+
## Equipment calibration and authorization
|
|
75
|
+
|
|
76
|
+
A machine used as schedule capacity is still a stable `Device`. Its lifecycle
|
|
77
|
+
has two independent evidence streams:
|
|
78
|
+
|
|
79
|
+
- `buildDeviceCalibrationFlatGraph(...)` records the completed technical work
|
|
80
|
+
as a `Procedure` whose subject and focal device are the machine, records the
|
|
81
|
+
corresponding `DeviceMetric.calibration` state/time, and can attach a
|
|
82
|
+
`DocumentReference` carrying the certificate hash. The maintenance
|
|
83
|
+
Organization and acting PractitionerRole are performers, not public
|
|
84
|
+
regulators.
|
|
85
|
+
- `buildDeviceOperatingAuthorizationFlatResource(...)` records an R5
|
|
86
|
+
`RegulatedAuthorization` issued by the regulator to the holder for the
|
|
87
|
+
installed Location, DeviceDefinition, Organization or governed activity.
|
|
88
|
+
FHIR R5 does not allow an individual Device instance as that resource's
|
|
89
|
+
subject, so installation-specific authorization targets the installed
|
|
90
|
+
Location and retains the individual Device through the associated evidence
|
|
91
|
+
graph.
|
|
92
|
+
|
|
93
|
+
Both builders emit only minimal resource identity and `resource.meta.claims`.
|
|
94
|
+
The product authorization layer must validate the submitting organization's
|
|
95
|
+
credential, the acting role, jurisdiction and current assignment; this neutral
|
|
96
|
+
package deliberately does not decide whether an assistant, laboratory
|
|
97
|
+
technician, maintenance technician or inspector is permitted. Scheduling may
|
|
98
|
+
derive machine eligibility only after authoritative readback shows an active
|
|
99
|
+
Device, a current required calibration and a valid operating authorization.
|
|
100
|
+
It must not trust a browser-supplied `available` boolean.
|
|
101
|
+
|
|
102
|
+
`buildDepartmentServicesFlatGraph(...)` authors the department row followed by
|
|
103
|
+
one row for every service. Its input accepts complete `system|value`
|
|
104
|
+
identifiers, complete `system|code` service/category/specialty tokens and typed
|
|
105
|
+
`Organization/...` or `Location/...` references. It rejects bare split
|
|
106
|
+
fragments and duplicate service ids. The builder writes only `resourceType`,
|
|
107
|
+
`id` and `meta.claims`; it never persists a nested FHIR resource.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const [department, bloodDonation, plasmaDonation] = buildDepartmentServicesFlatGraph({
|
|
111
|
+
departmentId: 'blood-bank',
|
|
112
|
+
departmentIdentifier: 'https://example.invalid/departments|blood-bank',
|
|
113
|
+
parentOrganizationReference: 'Organization/provider',
|
|
114
|
+
name: 'Blood bank',
|
|
115
|
+
services: [{
|
|
116
|
+
serviceId: 'blood-donation',
|
|
117
|
+
serviceIdentifier: 'https://example.invalid/services|blood-donation',
|
|
118
|
+
name: 'Blood donation',
|
|
119
|
+
serviceType: ['https://example.invalid/CodeSystem/service-type|blood-donation'],
|
|
120
|
+
locationReferences: ['Location/blood-donation-room'],
|
|
121
|
+
}, {
|
|
122
|
+
serviceId: 'plasma-donation',
|
|
123
|
+
serviceIdentifier: 'https://example.invalid/services|plasma-donation',
|
|
124
|
+
name: 'Plasma donation',
|
|
125
|
+
serviceType: ['https://example.invalid/CodeSystem/service-type|plasma-donation'],
|
|
126
|
+
locationReferences: ['Location/plasma-donation-room'],
|
|
127
|
+
}],
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Two service Locations may carry identical coordinates and copied public media
|
|
132
|
+
when they describe separate operational rooms or check-in configurations. They
|
|
133
|
+
must still have distinct Location identities if schedules or instructions
|
|
134
|
+
differ. If the physical delivery place is genuinely the same resource, both
|
|
135
|
+
services may reference that one Location instead.
|
|
136
|
+
|
|
137
|
+
## Claims-first boundary
|
|
138
|
+
|
|
139
|
+
`HealthcareServiceClaim` contains the complete resource-specific FHIR R4
|
|
140
|
+
search surface. `healthcareServiceFlatToFhirR4` and
|
|
141
|
+
`healthcareServiceFhirR4ToFlat` are the only native-R4 adapter boundary.
|
|
142
|
+
Repeatable coding identities remain complete `system|code` tokens; labels are
|
|
143
|
+
resolved by the terminology service and are not trusted storage identity.
|
|
144
|
+
`HealthcareService.comment` and R5 `Organization.description` are governed
|
|
145
|
+
materialization claims, but are not falsely advertised as R4 SearchParameters.
|
|
146
|
+
|
|
147
|
+
`materializeClaimsFirstResourceToFhirR5(...)` accepts only minimal resource
|
|
148
|
+
identity plus `resource.meta.claims`. It rejects nested native FHIR fields and
|
|
149
|
+
materializes Organization, HealthcareService, Location, Schedule or Slot only for export,
|
|
150
|
+
interop, hashing or credential generation. The resulting R5 object is never
|
|
151
|
+
persisted as a second business source of truth.
|
|
152
|
+
|
|
153
|
+
`LocationClaim` also preserves the official WGS84 longitude, latitude and
|
|
154
|
+
optional altitude needed by a marketplace. Schema.org `Place.image`,
|
|
155
|
+
Organization logos and governed object-storage evidence remain downstream
|
|
156
|
+
catalog concerns because FHIR R4 `Location` has no native image field.
|
|
157
|
+
|
|
158
|
+
## Professional group boundary
|
|
159
|
+
|
|
160
|
+
`normalizeGroupR5ProfessionalServiceTeam` requires one singular
|
|
161
|
+
`Group.managingEntity` reference to one department Organization. A
|
|
162
|
+
professional can belong to several Groups, but one Group cannot span several
|
|
163
|
+
departments in this initial contract. Group membership is descriptive and
|
|
164
|
+
does not grant read, search, appointment, break-glass or communication access.
|
|
165
|
+
|
|
166
|
+
The department needs no independent DID document merely to own a Group or
|
|
167
|
+
HealthcareService. A stable registered Group endpoint can receive a reply for
|
|
168
|
+
the unit. Transport sender, clinical-document author and professional attester
|
|
169
|
+
remain different identities:
|
|
170
|
+
|
|
171
|
+
- product policy may set the legal Organization as `Composition.author`;
|
|
172
|
+
- the acting `PractitionerRole` is the professional attester;
|
|
173
|
+
- the authenticated employee/device is transport audit evidence; and
|
|
174
|
+
- a reply is addressed to the Group endpoint, not authored by the Group.
|
|
175
|
+
|
|
176
|
+
Those authorization, endpoint-registration and authorship policies belong to
|
|
177
|
+
the BFF/high-level SDK, not this neutral package.
|
|
178
|
+
|
|
179
|
+
## C80 to LOINC candidate mapping
|
|
180
|
+
|
|
181
|
+
`SnomedC80ToLoincSpecialtyConceptMap` preserves the supplied 115 distinct C80
|
|
182
|
+
rows and their reviewed relationship to LOINC Subject Matter Domain or
|
|
183
|
+
LL402-9 codes. It is candidate evidence, not an official SNOMED or LOINC map.
|
|
184
|
+
Only rows explicitly classified as strict `equivalent` are returned by
|
|
185
|
+
`findAutomaticLoincSpecialty`. Wider, related, inexact and unmatched rows must
|
|
186
|
+
remain visible for terminology governance and are never applied automatically.
|
|
187
|
+
|
|
188
|
+
Service type and clinical specialty are not interchangeable. For example,
|
|
189
|
+
respite is retained as a related type-of-service candidate rather than being
|
|
190
|
+
silently promoted to a specialty.
|
|
@@ -22,6 +22,7 @@ and transport assumptions must not be copied.
|
|
|
22
22
|
| Old area | Decision | Current destination or gate |
|
|
23
23
|
| --- | --- | --- |
|
|
24
24
|
| `Bundle` and `Composition` traversal | Rewrite from tests | Neutral graph and explicit R4/R5/R6 adapters; preserve author, attester and section boundaries |
|
|
25
|
+
| `gdc-common-utils-ts` Communication attached-Bundle editor/reader | Preserve as read-only migration evidence | Neutral validation/projection tools live here; the replacement high-level editor/reader belongs to `sos-sdk-core`, with shared input contracts in `sos-data-utils` |
|
|
25
26
|
| `CodeableConcept`, `Identifier`, `Reference`, `Quantity` | Rewrite and reuse behavior | Small typed value modules with round-trip tests |
|
|
26
27
|
| `Observation` and resource parameter models | Rewrite | Canonical claim catalogs plus version-specific projection adapters |
|
|
27
28
|
| `Parameters` conversion | Rewrite | A typed FHIR Parameters module; never a transport-specific envelope |
|
|
@@ -45,8 +46,15 @@ and transport assumptions must not be copied.
|
|
|
45
46
|
| `uhc-fhir-utils-typescript` imaging | DICOMDIR structural types only | Byte parsing and pixel extraction require a separately versioned imaging package |
|
|
46
47
|
| `sos-data-utils-ts` | Cross-sector terminology contract and fixtures, Immunization graph and reminder planning | SOS authorization, repository and emergency policy |
|
|
47
48
|
| `vet-data-utils-ts` | Product-neutral FHIR R5 Group and ResearchStudy contracts/search projections | Animal identity, veterinary sections, species, insurance, payment and other Vet policy |
|
|
49
|
+
| Provider catalogs | R4 HealthcareService claims/converter, geocoded Location claims, one-department professional Group normalization and reviewed C80-to-LOINC candidate mappings | Schema.org images/logo storage, marketplace sector policy, endpoint authorization and communication routing |
|
|
48
50
|
| UHC/Vet SDKs | No transport client was copied | SMART clients, Oracle clients, BFF calls and product workflows remain SDK responsibilities |
|
|
49
51
|
|
|
52
|
+
The frozen `gdc-*` implementation remains compatibility evidence. New Vet,
|
|
53
|
+
UHC and SOS code uses the replacement high-level API in `sos-sdk-core`, which
|
|
54
|
+
composes the neutral tools exported here. Neither shared replacement package
|
|
55
|
+
imports `gdc-*`. DIDComm wrapping, post-quantum encryption, endpoint selection
|
|
56
|
+
and delivery retries remain in the SDK/service layer.
|
|
57
|
+
|
|
50
58
|
The migration surface is executable rather than documentary only:
|
|
51
59
|
|
|
52
60
|
- every migrated claim family has a named catalog and shared list helpers;
|
|
@@ -56,10 +64,21 @@ The migration surface is executable rather than documentary only:
|
|
|
56
64
|
searchable metadata without embedding DICOM object bytes;
|
|
57
65
|
- FHIR primitives, typed searches, Bundle traversal and fallback conversion
|
|
58
66
|
have strict success and rejection tests;
|
|
67
|
+
- Communication exchange is authored and read only as outer batch Bundle to
|
|
68
|
+
Communication to inner document/batch/collection Bundle, with files modeled
|
|
69
|
+
as inner DocumentReference resources;
|
|
59
70
|
- Immunization graphs and reminders live once under `src/builders/`; the former
|
|
60
71
|
root modules are deprecated re-export shims;
|
|
61
72
|
- Group and ResearchStudy expose named claim constants, preserve member/party
|
|
62
|
-
correlation as separate rows and reject authorization-shaped data;
|
|
73
|
+
correlation as separate rows and reject authorization-shaped data;
|
|
74
|
+
- Organization departments remain distinct from offered HealthcareServices;
|
|
75
|
+
every independently schedulable service keeps its own stable identity and
|
|
76
|
+
Location references, while professional Group ownership remains explicit;
|
|
77
|
+
- `buildServiceScheduleFlatGraph(...)` and the R5 Schedule/Slot adapters keep
|
|
78
|
+
per-service planning horizons and slot intervals shared between Vet and UHC;
|
|
79
|
+
- schedulable child Locations preserve `partOf`, while Schedule actors can
|
|
80
|
+
combine the service with Location, Device and PractitionerRole capacity;
|
|
81
|
+
and
|
|
63
82
|
- `npm run check` enforces minimum line, function and branch coverage across
|
|
64
83
|
converters, builders and core FHIR modules.
|
|
65
84
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Daily vital-sign document lifecycle
|
|
2
|
+
|
|
3
|
+
This package owns the product-neutral FHIR data contract used by web portals,
|
|
4
|
+
telephone assistants, chatbots and device importers. It does not decide who
|
|
5
|
+
may attest, write an index, anchor a hash on a ledger or contribute data to a
|
|
6
|
+
research study.
|
|
7
|
+
|
|
8
|
+
## Repeated readings
|
|
9
|
+
|
|
10
|
+
`buildRepeatedVitalSignAverage(...)` requires exactly three readings separated
|
|
11
|
+
by two minutes. It returns:
|
|
12
|
+
|
|
13
|
+
- three raw `Observation` graphs with `status=registered`;
|
|
14
|
+
- one arithmetic-mean `Observation` with `status=preliminary`;
|
|
15
|
+
- `Observation.date-when=MORN|AFT|EVE|NIGHT` on raw and mean observations;
|
|
16
|
+
- `Observation.derived-from` references from the mean to all raw observations.
|
|
17
|
+
|
|
18
|
+
Blood pressure remains one native Observation with systolic and diastolic
|
|
19
|
+
components. Its flat representation keeps the established primary
|
|
20
|
+
`Observation.has-member` graph. No `bp-*`, `component-*`, containment or split
|
|
21
|
+
coding claims are written.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const morningBloodPressure = buildRepeatedVitalSignAverage({
|
|
25
|
+
entryId: averageObservationId,
|
|
26
|
+
subjectReference,
|
|
27
|
+
deviceReference,
|
|
28
|
+
kind: 'blood-pressure',
|
|
29
|
+
eventTiming: 'MORN',
|
|
30
|
+
readings: threeTimestampedReadings,
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Temperature accepts governed UCUM Celsius or Fahrenheit units. Body weight
|
|
35
|
+
accepts governed UCUM kilograms or avoirdupois pounds. A UI selects one of the
|
|
36
|
+
exported `VitalSignUnit` constants; it never assembles a UCUM token itself.
|
|
37
|
+
|
|
38
|
+
## One document per local day
|
|
39
|
+
|
|
40
|
+
`buildVitalSignDailyDocument(...)` validates every Observation against an
|
|
41
|
+
explicit IANA time zone and local calendar date. It returns one preliminary
|
|
42
|
+
`Composition` followed by every Observation graph entry. The Composition
|
|
43
|
+
references only the top-level Observations through `Composition.entry`; reduced
|
|
44
|
+
blood-pressure members remain reachable through `Observation.has-member`.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const dailyDraft = buildVitalSignDailyDocument({
|
|
48
|
+
entryId: dailyCompositionId,
|
|
49
|
+
identifier: dailyDocumentIdentifier,
|
|
50
|
+
subjectReference,
|
|
51
|
+
authorReference,
|
|
52
|
+
localDate,
|
|
53
|
+
timeZone,
|
|
54
|
+
observationGraphs: [
|
|
55
|
+
...morningBloodPressure.sourceGraphs,
|
|
56
|
+
morningBloodPressure.averageGraph,
|
|
57
|
+
],
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The draft is readable as preliminary clinical work. It is not final evidence
|
|
62
|
+
and this package does not make it eligible for an individual index, Digital
|
|
63
|
+
Twin or research projection.
|
|
64
|
+
|
|
65
|
+
`finalizeVitalSignDailyDocument(...)` requires a preliminary document, records
|
|
66
|
+
the professional attester and confirmation time, and returns a new immutable
|
|
67
|
+
graph with the Composition and all top-level Observations set to `final`.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const finalDailyDocument = finalizeVitalSignDailyDocument(dailyDraft, {
|
|
71
|
+
attesterReference,
|
|
72
|
+
confirmedAt,
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The owning service may now serialize and hash this one daily document graph.
|
|
77
|
+
Index, ledger and research writes remain separate policy-controlled operations;
|
|
78
|
+
failure in one must not silently claim success in another.
|
|
79
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fhir-data-utils-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "FHIR-version-neutral flat-claim and SearchParameter data utilities",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -103,6 +103,10 @@
|
|
|
103
103
|
"types": "./dist/group-r5.d.ts",
|
|
104
104
|
"default": "./dist/group-r5.js"
|
|
105
105
|
},
|
|
106
|
+
"./healthcare-service-specialty-map": {
|
|
107
|
+
"types": "./dist/healthcare-service-specialty-map.d.ts",
|
|
108
|
+
"default": "./dist/healthcare-service-specialty-map.js"
|
|
109
|
+
},
|
|
106
110
|
"./research-study-r5": {
|
|
107
111
|
"types": "./dist/research-study-r5.d.ts",
|
|
108
112
|
"default": "./dist/research-study-r5.js"
|