fhir-data-utils-ts 0.6.20 → 0.6.22
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 +8 -11
- package/.codex/skills/govern-fhir-observation-components/SKILL.md +11 -13
- package/.codex/skills/preserve-fhir-flat-coding-review/SKILL.md +5 -5
- package/CHANGELOG.md +31 -13
- package/README.md +18 -26
- package/dist/builders/immunization-reminders.d.ts +1 -1
- package/dist/builders/immunization-reminders.js +1 -1
- package/dist/claims/communication-request-claims.d.ts +2 -0
- package/dist/claims/communication-request-claims.js +4 -0
- package/dist/claims/index.d.ts +1 -0
- package/dist/claims/index.js +1 -0
- package/dist/claims/us-core-patient-demographics-claims.d.ts +19 -0
- package/dist/claims/us-core-patient-demographics-claims.js +26 -0
- package/dist/clinical-terminology.d.ts +1 -1
- package/dist/converters/convert-communication-request.js +23 -4
- package/dist/converters/convert-us-core-patient-demographics.d.ts +29 -0
- package/dist/converters/convert-us-core-patient-demographics.js +114 -0
- package/dist/converters/index.d.ts +1 -0
- package/dist/converters/index.js +1 -0
- package/dist/data/communication-request-form-schema.data.d.ts +24 -0
- package/dist/data/communication-request-form-schema.data.js +28 -4
- package/dist/fhir-search-parameters.d.ts +1 -1
- package/dist/fhir-search-parameters.js +1 -1
- package/dist/imaging-types.d.ts +1 -1
- package/dist/search-models/index.d.ts +1 -1
- package/dist/search-models/index.js +1 -1
- package/docs/CARE_EMERGENCY_ALERT_CONTRACTS.md +2 -2
- package/docs/CLINICAL_TYPED_ACCESSOR_BOUNDARY.md +6 -11
- package/docs/COMMUNICATION_BUNDLE_CONTRACT.md +6 -7
- package/package.json +1 -1
- package/docs/UHC_FHIR_UTILS_MIGRATION.md +0 -181
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: govern-fhir-data-utilities
|
|
3
|
-
description: Complete or audit migrations, claim catalogs, converters, builders, tests and releases in fhir-data-utils-ts. Use for shared FHIR types or utilities
|
|
3
|
+
description: Complete or audit migrations, claim catalogs, converters, builders, tests and releases in fhir-data-utils-ts. Use for shared FHIR types or utilities recovered from standards-based compatibility evidence; raw flat-claim literals; duplicate root and family modules; Observation components; Immunization graphs; Group or ResearchStudy projections; package exports; coverage gates; or downstream promotion.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Govern FHIR Data Utilities
|
|
7
7
|
|
|
8
8
|
## Keep ownership explicit
|
|
9
9
|
|
|
10
|
-
1.
|
|
11
|
-
|
|
10
|
+
1. Inventory every relevant standards-based source family before declaring a
|
|
11
|
+
migration complete.
|
|
12
12
|
2. Treat `gdc-*` repositories as read-only evidence unless the user explicitly
|
|
13
13
|
changes that scope. Never patch them as part of this migration.
|
|
14
14
|
3. Keep neutral FHIR data semantics here. Keep HTTP, SMART, DIDComm, storage,
|
|
15
15
|
authorization and product policy in their owning services or sector packages.
|
|
16
16
|
4. Define every flat key once in its owning named catalog. Import that symbol in
|
|
17
17
|
converters, builders, tests and examples; never repeat a claim-path literal.
|
|
18
|
-
5. For SHC and DGC archaeology,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
consolidation. Do not copy an earlier helper when a later governed contract
|
|
22
|
-
exists.
|
|
18
|
+
5. For SHC and DGC archaeology, prefer the latest governed standards-based
|
|
19
|
+
implementation evidence. Do not copy an earlier helper when a later
|
|
20
|
+
governed contract exists.
|
|
23
21
|
|
|
24
22
|
## Separate catalogs, adapters and builders
|
|
25
23
|
|
|
@@ -68,9 +66,8 @@ description: Complete or audit migrations, claim catalogs, converters, builders,
|
|
|
68
66
|
subscriber persistence, authentication or product notification policy.
|
|
69
67
|
- Validate and project the canonical outer `Bundle[type=batch]` ->
|
|
70
68
|
`Communication` -> inner `Bundle[type=document|batch|collection]` structure
|
|
71
|
-
here, but keep
|
|
72
|
-
|
|
73
|
-
import frozen `gdc-*`. Arbitrary files are DocumentReference entries in the
|
|
69
|
+
here, but keep high-level editors/readers and application data contracts in
|
|
70
|
+
downstream libraries. Arbitrary files are DocumentReference entries in the
|
|
74
71
|
inner Bundle, never a second direct Communication attachment. Direct
|
|
75
72
|
flat-claim CRUD is an internal persistence boundary, not this wire format.
|
|
76
73
|
- Keep ImagingStudy searchable metadata, clinical references and protected
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: govern-fhir-observation-components
|
|
3
|
-
description: Implement or audit neutral FHIR Observation claim catalogs, vital-sign terminology, parent-owned component graphs, reduced component indexes, historical array and bp aliases, and R4/R5 projection adapters. Use when changing Observation.component, blood pressure, assessment scales, device readings, flat claims, portal or assistant vital-sign builders, or migrating
|
|
3
|
+
description: Implement or audit neutral FHIR Observation claim catalogs, vital-sign terminology, parent-owned component graphs, reduced component indexes, historical array and bp aliases, and R4/R5 projection adapters. Use when changing Observation.component, blood pressure, assessment scales, device readings, flat claims, portal or assistant vital-sign builders, or migrating neutral compatibility code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Govern FHIR Observation Components
|
|
@@ -9,12 +9,12 @@ description: Implement or audit neutral FHIR Observation claim catalogs, vital-s
|
|
|
9
9
|
|
|
10
10
|
1. Treat native FHIR import/export as an adapter boundary. Keep flat claims as
|
|
11
11
|
the version-neutral internal contract.
|
|
12
|
-
2. Read `src/observation-claims.ts`, `src/vital-sign-observations.ts
|
|
13
|
-
tests
|
|
14
|
-
3. Treat
|
|
15
|
-
|
|
16
|
-
4. Keep product policies
|
|
17
|
-
|
|
12
|
+
2. Read `src/observation-claims.ts`, `src/vital-sign-observations.ts` and their
|
|
13
|
+
tests before changing behavior.
|
|
14
|
+
3. Treat external compatibility repositories as read-only evidence unless the
|
|
15
|
+
user explicitly changes that scope.
|
|
16
|
+
4. Keep product policies downstream. This package owns only neutral FHIR data
|
|
17
|
+
semantics.
|
|
18
18
|
|
|
19
19
|
## Preserve the component contract
|
|
20
20
|
|
|
@@ -79,15 +79,13 @@ description: Implement or audit neutral FHIR Observation claim catalogs, vital-s
|
|
|
79
79
|
|
|
80
80
|
## Audit migrations completely
|
|
81
81
|
|
|
82
|
-
- Inventory the
|
|
83
|
-
|
|
84
|
-
complete.
|
|
82
|
+
- Inventory the relevant standards-based source and compatibility evidence
|
|
83
|
+
before calling a migration complete.
|
|
85
84
|
- Move only neutral FHIR data types, claim catalogs, conversion rules and pure
|
|
86
85
|
helpers here. Keep transport clients and sector authorization/policy in
|
|
87
86
|
their owning package.
|
|
88
|
-
- Record every migrated, retired or intentionally retained family in
|
|
89
|
-
|
|
90
|
-
audit.
|
|
87
|
+
- Record every migrated, retired or intentionally retained family in neutral
|
|
88
|
+
repository documentation; an unmentioned file is an incomplete audit.
|
|
91
89
|
- Expose each supported family through a stable package subpath and prove the
|
|
92
90
|
packed artifact, not only root source imports.
|
|
93
91
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: preserve-fhir-flat-coding-review
|
|
3
|
-
description: Preserve the neutral flat-claim contract for imported local clinical text, terminology proposals and confirmed codings. Use when changing
|
|
3
|
+
description: Preserve the neutral flat-claim contract for imported local clinical text, terminology proposals and confirmed codings. Use when changing ingestion, ResearchSubject batches, contained clinical resources, coding-review UI/API contracts, examples, fixtures or tests.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Preserve FHIR Flat Coding Review
|
|
@@ -24,7 +24,7 @@ redeclare governed claim paths, code systems, UUIDs or example values.
|
|
|
24
24
|
`userSelected` as a draft or promotion flag.
|
|
25
25
|
- Group review UI with the package-owned clinical families: allergies and
|
|
26
26
|
intolerances, procedures, diagnostics and immunizations. Do not duplicate
|
|
27
|
-
resource-type lists in
|
|
27
|
+
resource-type lists in downstream consumers.
|
|
28
28
|
- A localized generated label may use a language-qualified `-text_<BCP47>`
|
|
29
29
|
companion. It must not overwrite the imported local text before explicit
|
|
30
30
|
review.
|
|
@@ -60,9 +60,9 @@ redeclare governed claim paths, code systems, UUIDs or example values.
|
|
|
60
60
|
## Boundaries
|
|
61
61
|
|
|
62
62
|
- This is FHIR-neutral shared data behavior. It belongs in
|
|
63
|
-
`fhir-data-utils-ts`, not
|
|
64
|
-
-
|
|
65
|
-
|
|
63
|
+
`fhir-data-utils-ts`, not in downstream or frozen compatibility packages.
|
|
64
|
+
- Importers and sector applications consume the same contract and may add
|
|
65
|
+
policy without forking its claim shape.
|
|
66
66
|
- Do not put HTTP clients, gateway policy, product authorization or terminology
|
|
67
67
|
catalogs in this package.
|
|
68
68
|
- Tests and examples import package-owned fixtures/builders. Do not scatter raw
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Re-establish the public repository from a clean source snapshot while
|
|
6
|
+
retaining this changelog as the package release record.
|
|
7
|
+
|
|
8
|
+
## 0.6.22 - 2026-10-22
|
|
9
|
+
|
|
10
|
+
- Add FHIR-owned flat claims and a lossless R4 extension round trip for the
|
|
11
|
+
optional US Core Patient race and ethnicity extensions. Preserve OMB and
|
|
12
|
+
detailed Coding tokens separately from the required human-readable text;
|
|
13
|
+
derive the official `Patient.race` and `Patient.ethnicity` token-search
|
|
14
|
+
claims instead of accepting them from a browser; and do not expose these
|
|
15
|
+
jurisdictional fields as universal demographics or org.schema properties.
|
|
16
|
+
|
|
17
|
+
## 0.6.21 - 2026-10-21
|
|
18
|
+
|
|
19
|
+
- Add the shared CommunicationRequest form, flat-claim and materialization
|
|
20
|
+
fields needed for categorized public alerts, related attachments and bounded
|
|
21
|
+
occurrence periods without introducing a proprietary alert resource.
|
|
22
|
+
|
|
5
23
|
## 0.6.20 - 2026-10-12
|
|
6
24
|
|
|
7
25
|
- Export the deduplicated official LOINC Document Ontology subject-matter-
|
|
@@ -58,8 +76,8 @@
|
|
|
58
76
|
- Give every reusable IPS authoring schema canonical initial claims so portal
|
|
59
77
|
components do not invent resource status defaults.
|
|
60
78
|
|
|
61
|
-
- Recover
|
|
62
|
-
|
|
79
|
+
- Recover useful locale-aware behavior from historical compatibility helpers
|
|
80
|
+
as strict FHIR temporal presentation tools.
|
|
63
81
|
Date-only values retain their calendar day, instants render with the user's
|
|
64
82
|
locale and IANA time zone, editor date/time fields compose a canonical FHIR
|
|
65
83
|
instant with optional seconds defaulted to `00`, and inclusive ranges treat
|
|
@@ -86,8 +104,8 @@
|
|
|
86
104
|
document so portals can update the Composition without duplicating LOINC
|
|
87
105
|
section codes.
|
|
88
106
|
|
|
89
|
-
- Recover neutral SHC and EU DGC QR prefix classification from
|
|
90
|
-
|
|
107
|
+
- Recover neutral SHC and EU DGC QR prefix classification from compatibility
|
|
108
|
+
evidence, with exported repository-safe `*.data.ts` examples.
|
|
91
109
|
Recognition explicitly provides no decoding, verification or authorization.
|
|
92
110
|
|
|
93
111
|
- Export one repository-safe, telephone-free IPS demo document with all sixteen
|
|
@@ -99,8 +117,8 @@
|
|
|
99
117
|
historical source modules remain compatibility reexports.
|
|
100
118
|
- Remove notification-channel policy from the general root and `builders`
|
|
101
119
|
surfaces. The historical reminder subpath and non-standard `Task.channel`
|
|
102
|
-
claim remain deprecated compatibility only while
|
|
103
|
-
|
|
120
|
+
claim remain deprecated compatibility only while consumers migrate;
|
|
121
|
+
downstream applications own channel choices and dispatch behavior.
|
|
104
122
|
|
|
105
123
|
## 0.6.2 - 2026-09-30
|
|
106
124
|
|
|
@@ -123,7 +141,7 @@
|
|
|
123
141
|
the frozen shared implementation: outer batch Bundle, one FHIR Bundle
|
|
124
142
|
attachment per Communication, and validated document/batch/collection inner
|
|
125
143
|
Bundles. Reject direct clinical or binary Communication payloads while
|
|
126
|
-
leaving high-level mutable editors
|
|
144
|
+
leaving high-level mutable editors downstream.
|
|
127
145
|
- Add a typed Appointment exchange projection that preserves start/end,
|
|
128
146
|
participants, slots and supporting information while keeping an ICS calendar
|
|
129
147
|
file as an independent DocumentReference flat-claim resource.
|
|
@@ -254,9 +272,9 @@
|
|
|
254
272
|
modifying that frozen source repository.
|
|
255
273
|
- Recover strict FHIR primitives, value/search/token utilities, Bundle readers,
|
|
256
274
|
resource search/template types, terminology model types, RelatedPerson and
|
|
257
|
-
telecom helpers, and DICOMDIR structural types from
|
|
275
|
+
telecom helpers, and DICOMDIR structural types from compatibility evidence.
|
|
258
276
|
- Move cross-sector terminology, Immunization graph/reminder, Group R5 and
|
|
259
|
-
ResearchStudy R5 contracts
|
|
277
|
+
ResearchStudy R5 contracts into their neutral standards-based owner.
|
|
260
278
|
- Require component Observations to use independently indexable graph entries;
|
|
261
279
|
deprecated JSON-array component claims remain read-only compatibility input.
|
|
262
280
|
- Add stable package subpaths for every migrated contract family.
|
|
@@ -293,12 +311,12 @@
|
|
|
293
311
|
JSON repeatable-component encoding, generic component index projection and
|
|
294
312
|
explicit R4/R5 projection boundary. Historical component CSV and `bp-*`
|
|
295
313
|
aliases remain read-only compatibility inputs.
|
|
296
|
-
- Record the reuse/rewrite/retire audit of
|
|
297
|
-
|
|
298
|
-
|
|
314
|
+
- Record the reuse/rewrite/retire audit of historical compatibility utilities
|
|
315
|
+
without adding obsolete product, transport, SHA-1, DICOM or build
|
|
316
|
+
dependencies to the neutral package.
|
|
299
317
|
- Add the neutral contained-resource coding-review contract: canonical imported
|
|
300
318
|
`*-text`, resource-scoped `meta.codingProposals[]`, batch traversal, candidate
|
|
301
|
-
confirmation and reusable governed fixtures for
|
|
319
|
+
confirmation and reusable governed fixtures for downstream consumers.
|
|
302
320
|
- Add channel-neutral FHIR-like vital-sign Observation builders and lossless device-batch normalization while preserving device source without inventing professional attestation.
|
|
303
321
|
- Introduce product-neutral flat-claim resource graphs, parent-owned
|
|
304
322
|
`contained-reference-list`, narrative `language`/`xhtml`, and governed
|
package/README.md
CHANGED
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
FHIR-neutral data contracts for flat claims, governed SearchParameter names,
|
|
4
4
|
resource graphs and explicit R4/R5/R6 projection adapters. This package has no
|
|
5
|
-
network clients and no dependency on
|
|
5
|
+
network clients and no dependency on downstream product packages.
|
|
6
6
|
|
|
7
7
|
Release order is local-first: local tarball consumers, complete local matrix,
|
|
8
8
|
merge and push `main`, publish bottom-up, install exact registry versions, then
|
|
9
9
|
staging. Never commit `file:`, Git or workspace dependencies.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Public source history
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
↓
|
|
17
|
-
sos-data-utils-ts
|
|
18
|
-
└─ cross-sector clinical catalogs and shared SOS/Vet/UHC data contracts
|
|
19
|
-
├─ vet-data-utils-ts: animal species and veterinary policy
|
|
20
|
-
└─ uhc-data-utils-ts: human-health policy
|
|
13
|
+
The public repository begins from a clean 2026 source snapshot. The retained
|
|
14
|
+
[`CHANGELOG.md`](CHANGELOG.md) records package releases without republishing
|
|
15
|
+
the former Git push history.
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
## Ownership boundary
|
|
18
|
+
|
|
19
|
+
This package owns only standards-based FHIR SearchParameters, flat-claim
|
|
20
|
+
graphs, validation and explicit R4/R5/R6 projection rules. Sector terminology,
|
|
21
|
+
product policy, transport, authorization, mutable editors, network clients and
|
|
22
|
+
application workflows belong downstream and are deliberately unnamed here.
|
|
25
23
|
|
|
26
24
|
FHIR resource graphs use independent entries. A parent links children only
|
|
27
25
|
through `<ResourceType>.contained-reference-list`; children do not carry
|
|
@@ -48,8 +46,8 @@ Cross-participant data always uses an outer FHIR batch Bundle containing
|
|
|
48
46
|
Communication entries. Each Communication carries exactly one
|
|
49
47
|
`application/fhir+json` inner document, batch or collection Bundle; arbitrary
|
|
50
48
|
files are DocumentReference resources inside that Bundle. This package owns
|
|
51
|
-
strict parsing and projection tools;
|
|
52
|
-
|
|
49
|
+
strict parsing and projection tools; mutable editors, transport and
|
|
50
|
+
cross-sector policy belong downstream. See
|
|
53
51
|
[Communication Bundle contract](docs/COMMUNICATION_BUNDLE_CONTRACT.md).
|
|
54
52
|
|
|
55
53
|
Reservable equipment remains a `Device` actor of its service-specific
|
|
@@ -70,10 +68,10 @@ The root export and stable subpaths provide:
|
|
|
70
68
|
- complete flat-claim catalogs and claim helpers for the resource families
|
|
71
69
|
formerly scattered through `gdc-common-utils-ts`;
|
|
72
70
|
- explicit R4/R5 conversion adapters, including Consent and PractitionerRole;
|
|
73
|
-
-
|
|
71
|
+
- resource search/template types, terminology model types,
|
|
74
72
|
RelatedPerson/telecom helpers and type-only DICOMDIR tree contract;
|
|
75
73
|
- cross-sector terminology, Immunization graphs/reminders, and FHIR R5 Group
|
|
76
|
-
and ResearchStudy contracts
|
|
74
|
+
and ResearchStudy contracts;
|
|
77
75
|
- native FHIR R5 SubscriptionTopic/Subscription configuration builders,
|
|
78
76
|
official search catalogs and a strict notification-Bundle parser; terminal
|
|
79
77
|
asynchronous job messages remain claims-first Communication resources.
|
|
@@ -156,18 +154,13 @@ top-level Observations with a professional attester. Ledger hashing, index
|
|
|
156
154
|
updates, Digital Twin and research eligibility remain owning-service policy.
|
|
157
155
|
See [Daily vital-sign document lifecycle](docs/VITAL_SIGN_DAILY_DOCUMENT.md).
|
|
158
156
|
|
|
159
|
-
See [the UHC FHIR utilities migration](docs/UHC_FHIR_UTILS_MIGRATION.md) for the
|
|
160
|
-
reuse/rewrite/retire inventory and the rule for moving frozen contracts without
|
|
161
|
-
changing any `gdc-*` repository.
|
|
162
|
-
|
|
163
157
|
See [Clinical typed accessor boundary](docs/CLINICAL_TYPED_ACCESSOR_BOUNDARY.md)
|
|
164
158
|
for the exact division between canonical clinical claims/converters here,
|
|
165
|
-
|
|
166
|
-
by runtime SDKs.
|
|
159
|
+
downstream schemas and mutable Bundle getters/setters.
|
|
167
160
|
|
|
168
161
|
## Coding review for imported clinical text
|
|
169
162
|
|
|
170
|
-
|
|
163
|
+
Coding review uses one neutral contract from
|
|
171
164
|
`fhir-data-utils-ts/coding-review-flat-claims`:
|
|
172
165
|
|
|
173
166
|
- imported wording is the canonical `<ResourceType>.<code-field>-text` claim;
|
|
@@ -209,8 +202,7 @@ packed artifact and installs it in an isolated consumer before publication.
|
|
|
209
202
|
|
|
210
203
|
## Care, emergency and population-alert graphs
|
|
211
204
|
|
|
212
|
-
The package provides the neutral FHIR foundation for
|
|
213
|
-
journeys proven first in VetChain/PetChain: Location-linked Encounter care
|
|
205
|
+
The package provides the neutral FHIR foundation for Location-linked Encounter care
|
|
214
206
|
journeys, emergency ServiceRequest plus triage Task, and cohort
|
|
215
207
|
CommunicationRequest against a frozen Group snapshot. See
|
|
216
208
|
[the contract guide](docs/CARE_EMERGENCY_ALERT_CONTRACTS.md). Product policy,
|
|
@@ -7,7 +7,7 @@ export declare const ImmunizationReminderTaskValues: Readonly<{
|
|
|
7
7
|
}>;
|
|
8
8
|
/**
|
|
9
9
|
* @deprecated Compatibility only. Notification-channel policy belongs to the
|
|
10
|
-
* consuming
|
|
10
|
+
* consuming downstream package, not to the general FHIR data package.
|
|
11
11
|
*/
|
|
12
12
|
export declare const ImmunizationReminderChannels: readonly ["push", "email", "sms", "whatsapp", "telephone"];
|
|
13
13
|
export type ImmunizationReminderChannel = (typeof ImmunizationReminderChannels)[number];
|
|
@@ -10,7 +10,7 @@ export const ImmunizationReminderTaskValues = Object.freeze({
|
|
|
10
10
|
});
|
|
11
11
|
/**
|
|
12
12
|
* @deprecated Compatibility only. Notification-channel policy belongs to the
|
|
13
|
-
* consuming
|
|
13
|
+
* consuming downstream package, not to the general FHIR data package.
|
|
14
14
|
*/
|
|
15
15
|
export const ImmunizationReminderChannels = Object.freeze([
|
|
16
16
|
'push',
|
|
@@ -20,6 +20,8 @@ export declare const CommunicationRequestClaim: Readonly<{
|
|
|
20
20
|
readonly InformationProvider: "CommunicationRequest.information-provider";
|
|
21
21
|
readonly AuthoredOn: "CommunicationRequest.authored-on";
|
|
22
22
|
readonly Occurrence: "CommunicationRequest.occurrence";
|
|
23
|
+
readonly OccurrencePeriodStart: "CommunicationRequest.occurrence-period-start";
|
|
24
|
+
readonly OccurrencePeriodEnd: "CommunicationRequest.occurrence-period-end";
|
|
23
25
|
readonly ReasonCode: "CommunicationRequest.reason-code";
|
|
24
26
|
readonly ReasonReference: "CommunicationRequest.reason-reference";
|
|
25
27
|
readonly PayloadContent: "CommunicationRequest.payload-content";
|
|
@@ -19,6 +19,8 @@ export const CommunicationRequestClaim = Object.freeze({
|
|
|
19
19
|
InformationProvider: 'CommunicationRequest.information-provider',
|
|
20
20
|
AuthoredOn: 'CommunicationRequest.authored-on',
|
|
21
21
|
Occurrence: 'CommunicationRequest.occurrence',
|
|
22
|
+
OccurrencePeriodStart: 'CommunicationRequest.occurrence-period-start',
|
|
23
|
+
OccurrencePeriodEnd: 'CommunicationRequest.occurrence-period-end',
|
|
22
24
|
ReasonCode: 'CommunicationRequest.reason-code',
|
|
23
25
|
ReasonReference: 'CommunicationRequest.reason-reference',
|
|
24
26
|
PayloadContent: 'CommunicationRequest.payload-content',
|
|
@@ -48,6 +50,8 @@ export const CommunicationRequestClaimSpecs = Object.freeze([
|
|
|
48
50
|
{ key: CommunicationRequestClaim.InformationProvider, meaning: 'Actors expected to provide or review message information.', example: 'PractitionerRole/doctor-1' },
|
|
49
51
|
{ key: CommunicationRequestClaim.AuthoredOn, meaning: 'Request authoring time.', example: '2026-09-26T11:00:00Z' },
|
|
50
52
|
{ key: CommunicationRequestClaim.Occurrence, meaning: 'Requested delivery time.', example: '2026-09-26T11:30:00Z' },
|
|
53
|
+
{ key: CommunicationRequestClaim.OccurrencePeriodStart, meaning: 'Start of the requested delivery period.', example: '2026-09-26T11:30:00Z' },
|
|
54
|
+
{ key: CommunicationRequestClaim.OccurrencePeriodEnd, meaning: 'End of the requested delivery period.', example: '2026-09-27T11:30:00Z' },
|
|
51
55
|
{ key: CommunicationRequestClaim.ReasonCode, meaning: 'Coded reasons for the request.', example: 'http://snomed.info/sct|246205007' },
|
|
52
56
|
{ key: CommunicationRequestClaim.ReasonReference, meaning: 'Resource references supporting the request reason.', example: 'Condition/condition-1' },
|
|
53
57
|
{ key: CommunicationRequestClaim.PayloadContent, meaning: 'R4 string payload compatibility value.', example: 'Family update ready for review.' },
|
package/dist/claims/index.d.ts
CHANGED
package/dist/claims/index.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ClaimSpec } from './claim-types.js';
|
|
2
|
+
/** Canonical claims for the optional US Core Patient race and ethnicity extensions. */
|
|
3
|
+
export declare const UsCorePatientDemographicClaim: Readonly<{
|
|
4
|
+
readonly RaceOmbCategory: "Patient.extension:us-core-race.extension:ombCategory";
|
|
5
|
+
readonly RaceDetailed: "Patient.extension:us-core-race.extension:detailed";
|
|
6
|
+
readonly RaceText: "Patient.extension:us-core-race.extension:text";
|
|
7
|
+
readonly EthnicityOmbCategory: "Patient.extension:us-core-ethnicity.extension:ombCategory";
|
|
8
|
+
readonly EthnicityDetailed: "Patient.extension:us-core-ethnicity.extension:detailed";
|
|
9
|
+
readonly EthnicityText: "Patient.extension:us-core-ethnicity.extension:text";
|
|
10
|
+
}>;
|
|
11
|
+
/** Derived claims backed by the two official optional US Core SearchParameters. */
|
|
12
|
+
export declare const UsCorePatientDemographicSearchClaim: Readonly<{
|
|
13
|
+
readonly Race: "Patient.race";
|
|
14
|
+
readonly Ethnicity: "Patient.ethnicity";
|
|
15
|
+
}>;
|
|
16
|
+
export type UsCorePatientDemographicClaimKey = typeof UsCorePatientDemographicClaim[keyof typeof UsCorePatientDemographicClaim];
|
|
17
|
+
export type UsCorePatientDemographicSearchClaimKey = typeof UsCorePatientDemographicSearchClaim[keyof typeof UsCorePatientDemographicSearchClaim];
|
|
18
|
+
export declare const UsCorePatientDemographicClaimSpecs: readonly ClaimSpec[];
|
|
19
|
+
export declare const UsCorePatientDemographicSearchClaimSpecs: readonly ClaimSpec[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Canonical claims for the optional US Core Patient race and ethnicity extensions. */
|
|
2
|
+
export const UsCorePatientDemographicClaim = Object.freeze({
|
|
3
|
+
RaceOmbCategory: 'Patient.extension:us-core-race.extension:ombCategory',
|
|
4
|
+
RaceDetailed: 'Patient.extension:us-core-race.extension:detailed',
|
|
5
|
+
RaceText: 'Patient.extension:us-core-race.extension:text',
|
|
6
|
+
EthnicityOmbCategory: 'Patient.extension:us-core-ethnicity.extension:ombCategory',
|
|
7
|
+
EthnicityDetailed: 'Patient.extension:us-core-ethnicity.extension:detailed',
|
|
8
|
+
EthnicityText: 'Patient.extension:us-core-ethnicity.extension:text',
|
|
9
|
+
});
|
|
10
|
+
/** Derived claims backed by the two official optional US Core SearchParameters. */
|
|
11
|
+
export const UsCorePatientDemographicSearchClaim = Object.freeze({
|
|
12
|
+
Race: 'Patient.race',
|
|
13
|
+
Ethnicity: 'Patient.ethnicity',
|
|
14
|
+
});
|
|
15
|
+
export const UsCorePatientDemographicClaimSpecs = Object.freeze([
|
|
16
|
+
{ key: UsCorePatientDemographicClaim.RaceOmbCategory, meaning: 'Comma-separated OMB race Coding tokens.', example: 'urn:oid:2.16.840.1.113883.6.238|2028-9' },
|
|
17
|
+
{ key: UsCorePatientDemographicClaim.RaceDetailed, meaning: 'Comma-separated detailed race Coding tokens.', example: 'urn:oid:2.16.840.1.113883.6.238|2036-2' },
|
|
18
|
+
{ key: UsCorePatientDemographicClaim.RaceText, meaning: 'Patient-supplied race text required when the US Core race extension is present.', example: 'Asian' },
|
|
19
|
+
{ key: UsCorePatientDemographicClaim.EthnicityOmbCategory, meaning: 'OMB ethnicity Coding token.', example: 'urn:oid:2.16.840.1.113883.6.238|2135-2' },
|
|
20
|
+
{ key: UsCorePatientDemographicClaim.EthnicityDetailed, meaning: 'Comma-separated detailed ethnicity Coding tokens.', example: 'urn:oid:2.16.840.1.113883.6.238|2148-5' },
|
|
21
|
+
{ key: UsCorePatientDemographicClaim.EthnicityText, meaning: 'Patient-supplied ethnicity text required when the US Core ethnicity extension is present.', example: 'Hispanic or Latino' },
|
|
22
|
+
]);
|
|
23
|
+
export const UsCorePatientDemographicSearchClaimSpecs = Object.freeze([
|
|
24
|
+
{ key: UsCorePatientDemographicSearchClaim.Race, meaning: 'Derived token list for the official optional US Core race SearchParameter.', example: 'urn:oid:2.16.840.1.113883.6.238|2028-9' },
|
|
25
|
+
{ key: UsCorePatientDemographicSearchClaim.Ethnicity, meaning: 'Derived token list for the official optional US Core ethnicity SearchParameter.', example: 'urn:oid:2.16.840.1.113883.6.238|2135-2' },
|
|
26
|
+
]);
|
|
@@ -18,7 +18,7 @@ export declare const ClinicalTerminologySourceScopes: Readonly<{
|
|
|
18
18
|
readonly AtcVet: "ATCVET";
|
|
19
19
|
}>;
|
|
20
20
|
export type ClinicalTerminologySourceScope = typeof ClinicalTerminologySourceScopes[keyof typeof ClinicalTerminologySourceScopes];
|
|
21
|
-
/** Product-neutral terminology candidate returned to
|
|
21
|
+
/** Product-neutral terminology candidate returned to downstream channels. */
|
|
22
22
|
export type ClinicalTerminologyCandidate = Readonly<{
|
|
23
23
|
/** Governed source-scope identifier returned by the deployment capability. */
|
|
24
24
|
source: string;
|
|
@@ -18,7 +18,7 @@ export function communicationRequestFlatToFhirR4(claims) {
|
|
|
18
18
|
requester: claims[CommunicationRequestClaim.Requester] ? { reference: claims[CommunicationRequestClaim.Requester] } : undefined,
|
|
19
19
|
sender: firstReference(claims[CommunicationRequestClaim.InformationProvider]),
|
|
20
20
|
recipient: referenceCsv(claims[CommunicationRequestClaim.Recipient]), authoredOn: claims[CommunicationRequestClaim.AuthoredOn],
|
|
21
|
-
|
|
21
|
+
...occurrenceToFhir(claims),
|
|
22
22
|
reasonCode: claims[CommunicationRequestClaim.ReasonCode] ? [{ coding: codingListFromCsv(claims[CommunicationRequestClaim.ReasonCode]) }] : undefined,
|
|
23
23
|
reasonReference: referenceCsv(claims[CommunicationRequestClaim.ReasonReference]),
|
|
24
24
|
payload: payloadR4(claims),
|
|
@@ -44,7 +44,8 @@ export function communicationRequestFhirR4ToFlat(resource) {
|
|
|
44
44
|
[CommunicationRequestClaim.Requester]: referenceToValue(resource.requester),
|
|
45
45
|
[CommunicationRequestClaim.InformationProvider]: referenceToValue(resource.sender),
|
|
46
46
|
[CommunicationRequestClaim.Recipient]: referenceListToCsv(resource.recipient),
|
|
47
|
-
[CommunicationRequestClaim.AuthoredOn]: resource.authoredOn,
|
|
47
|
+
[CommunicationRequestClaim.AuthoredOn]: resource.authoredOn,
|
|
48
|
+
...occurrenceToFlat(resource),
|
|
48
49
|
[CommunicationRequestClaim.ReasonCode]: codingListToCsv(resource.reasonCode?.flatMap(value => value.coding ?? [])),
|
|
49
50
|
[CommunicationRequestClaim.ReasonReference]: referenceListToCsv(resource.reasonReference),
|
|
50
51
|
...payloadToFlat(resource),
|
|
@@ -82,7 +83,7 @@ function communicationRequestFlatToFhirR5Resource(claims) {
|
|
|
82
83
|
requester: claims[CommunicationRequestClaim.Requester] ? { reference: claims[CommunicationRequestClaim.Requester] } : undefined,
|
|
83
84
|
recipient: referenceCsv(claims[CommunicationRequestClaim.Recipient]),
|
|
84
85
|
informationProvider: referenceCsv(claims[CommunicationRequestClaim.InformationProvider]),
|
|
85
|
-
authoredOn: claims[CommunicationRequestClaim.AuthoredOn],
|
|
86
|
+
authoredOn: claims[CommunicationRequestClaim.AuthoredOn], ...occurrenceToFhir(claims),
|
|
86
87
|
reason: reasonsR5(claims), payload: payloadR5(claims), note: annotation(claims[CommunicationRequestClaim.Note]),
|
|
87
88
|
};
|
|
88
89
|
}
|
|
@@ -107,7 +108,7 @@ function communicationRequestFhirR5ResourceToFlat(resource) {
|
|
|
107
108
|
[CommunicationRequestClaim.Recipient]: referenceListToCsv(resource.recipient),
|
|
108
109
|
[CommunicationRequestClaim.InformationProvider]: referenceListToCsv(resource.informationProvider),
|
|
109
110
|
[CommunicationRequestClaim.AuthoredOn]: resource.authoredOn,
|
|
110
|
-
|
|
111
|
+
...occurrenceToFlat(resource),
|
|
111
112
|
[CommunicationRequestClaim.ReasonCode]: codingListToCsv(reasons?.flatMap(value => value.concept?.coding ?? [])),
|
|
112
113
|
[CommunicationRequestClaim.ReasonReference]: reasons?.map(value => value.reference?.reference).filter((value) => Boolean(value)).join(',') || undefined,
|
|
113
114
|
...payloadToFlat(resource), [CommunicationRequestClaim.Note]: annotationText(resource.note),
|
|
@@ -134,6 +135,24 @@ function optionalBoolean(value) {
|
|
|
134
135
|
}
|
|
135
136
|
function annotation(value) { return value ? [{ text: value }] : undefined; }
|
|
136
137
|
function annotationText(value) { return value?.[0]?.text; }
|
|
138
|
+
function occurrenceToFhir(claims) {
|
|
139
|
+
const occurrenceDateTime = claims[CommunicationRequestClaim.Occurrence];
|
|
140
|
+
const start = claims[CommunicationRequestClaim.OccurrencePeriodStart];
|
|
141
|
+
const end = claims[CommunicationRequestClaim.OccurrencePeriodEnd];
|
|
142
|
+
if (occurrenceDateTime && (start || end))
|
|
143
|
+
throw new TypeError('communication_request_occurrence_choice_invalid');
|
|
144
|
+
return occurrenceDateTime ? { occurrenceDateTime } : start || end ? { occurrencePeriod: compact({ start, end }) } : {};
|
|
145
|
+
}
|
|
146
|
+
function occurrenceToFlat(resource) {
|
|
147
|
+
const period = resource.occurrencePeriod;
|
|
148
|
+
if (resource.occurrenceDateTime && period)
|
|
149
|
+
throw new TypeError('communication_request_occurrence_choice_invalid');
|
|
150
|
+
return compact({
|
|
151
|
+
[CommunicationRequestClaim.Occurrence]: resource.occurrenceDateTime,
|
|
152
|
+
[CommunicationRequestClaim.OccurrencePeriodStart]: period?.start,
|
|
153
|
+
[CommunicationRequestClaim.OccurrencePeriodEnd]: period?.end,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
137
156
|
function payloadR4(claims) {
|
|
138
157
|
if (claims[CommunicationRequestClaim.PayloadReference])
|
|
139
158
|
return [{ contentReference: { reference: claims[CommunicationRequestClaim.PayloadReference] } }];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { UsCorePatientDemographicSearchClaimKey } from '../claims/us-core-patient-demographics-claims.js';
|
|
2
|
+
import type { FhirCoding, FhirResource } from '../fhir-types.js';
|
|
3
|
+
import type { FlatClaims } from './convert-shared.js';
|
|
4
|
+
export declare const UsCorePatientRaceExtensionUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race";
|
|
5
|
+
export declare const UsCorePatientEthnicityExtensionUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity";
|
|
6
|
+
export type UsCorePatientSearchParameterDefinition = Readonly<{
|
|
7
|
+
canonicalUrl: string;
|
|
8
|
+
code: 'race' | 'ethnicity';
|
|
9
|
+
base: 'Patient';
|
|
10
|
+
type: 'token';
|
|
11
|
+
expression: string;
|
|
12
|
+
claim: UsCorePatientDemographicSearchClaimKey;
|
|
13
|
+
sourceClaims: readonly string[];
|
|
14
|
+
multipleOr: true;
|
|
15
|
+
multipleAnd: true;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const UsCorePatientDemographicSearchParameters: readonly UsCorePatientSearchParameterDefinition[];
|
|
18
|
+
export type FhirExtension = Readonly<{
|
|
19
|
+
url: string;
|
|
20
|
+
extension?: readonly FhirExtension[];
|
|
21
|
+
valueCoding?: FhirCoding;
|
|
22
|
+
valueString?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** Materializes only the optional US Core extensions enabled by canonical claims. */
|
|
25
|
+
export declare function usCorePatientDemographicsFlatToFhirR4Extensions(claims: FlatClaims): readonly FhirExtension[];
|
|
26
|
+
/** Reads the two governed US Core extensions without treating them as universal demographics. */
|
|
27
|
+
export declare function usCorePatientDemographicsFhirR4ToFlat(resource: FhirResource): FlatClaims;
|
|
28
|
+
/** Derives the official token-search claims; callers never submit these independently. */
|
|
29
|
+
export declare function deriveUsCorePatientDemographicSearchClaims(claims: FlatClaims): FlatClaims;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { UsCorePatientDemographicClaim, UsCorePatientDemographicSearchClaim } from '../claims/us-core-patient-demographics-claims.js';
|
|
2
|
+
import { codingListFromCsv, codingListToCsv } from './convert-shared.js';
|
|
3
|
+
export const UsCorePatientRaceExtensionUrl = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race';
|
|
4
|
+
export const UsCorePatientEthnicityExtensionUrl = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity';
|
|
5
|
+
export const UsCorePatientDemographicSearchParameters = Object.freeze([
|
|
6
|
+
Object.freeze({
|
|
7
|
+
canonicalUrl: 'http://hl7.org/fhir/us/core/SearchParameter/us-core-race',
|
|
8
|
+
code: 'race', base: 'Patient', type: 'token',
|
|
9
|
+
expression: `Patient.extension.where(url = '${UsCorePatientRaceExtensionUrl}').extension.value.code`,
|
|
10
|
+
claim: UsCorePatientDemographicSearchClaim.Race,
|
|
11
|
+
sourceClaims: Object.freeze([UsCorePatientDemographicClaim.RaceOmbCategory, UsCorePatientDemographicClaim.RaceDetailed]),
|
|
12
|
+
multipleOr: true, multipleAnd: true,
|
|
13
|
+
}),
|
|
14
|
+
Object.freeze({
|
|
15
|
+
canonicalUrl: 'http://hl7.org/fhir/us/core/SearchParameter/us-core-ethnicity',
|
|
16
|
+
code: 'ethnicity', base: 'Patient', type: 'token',
|
|
17
|
+
expression: `Patient.extension.where(url = '${UsCorePatientEthnicityExtensionUrl}').extension.value.code`,
|
|
18
|
+
claim: UsCorePatientDemographicSearchClaim.Ethnicity,
|
|
19
|
+
sourceClaims: Object.freeze([UsCorePatientDemographicClaim.EthnicityOmbCategory, UsCorePatientDemographicClaim.EthnicityDetailed]),
|
|
20
|
+
multipleOr: true, multipleAnd: true,
|
|
21
|
+
}),
|
|
22
|
+
]);
|
|
23
|
+
/** Materializes only the optional US Core extensions enabled by canonical claims. */
|
|
24
|
+
export function usCorePatientDemographicsFlatToFhirR4Extensions(claims) {
|
|
25
|
+
return [
|
|
26
|
+
buildExtension({
|
|
27
|
+
url: UsCorePatientRaceExtensionUrl,
|
|
28
|
+
omb: claims[UsCorePatientDemographicClaim.RaceOmbCategory],
|
|
29
|
+
detailed: claims[UsCorePatientDemographicClaim.RaceDetailed],
|
|
30
|
+
text: claims[UsCorePatientDemographicClaim.RaceText],
|
|
31
|
+
textError: 'us_core_patient_race_text_required',
|
|
32
|
+
}),
|
|
33
|
+
buildExtension({
|
|
34
|
+
url: UsCorePatientEthnicityExtensionUrl,
|
|
35
|
+
omb: claims[UsCorePatientDemographicClaim.EthnicityOmbCategory],
|
|
36
|
+
detailed: claims[UsCorePatientDemographicClaim.EthnicityDetailed],
|
|
37
|
+
text: claims[UsCorePatientDemographicClaim.EthnicityText],
|
|
38
|
+
textError: 'us_core_patient_ethnicity_text_required',
|
|
39
|
+
singleOmbCategory: true,
|
|
40
|
+
}),
|
|
41
|
+
].filter((extension) => Boolean(extension));
|
|
42
|
+
}
|
|
43
|
+
/** Reads the two governed US Core extensions without treating them as universal demographics. */
|
|
44
|
+
export function usCorePatientDemographicsFhirR4ToFlat(resource) {
|
|
45
|
+
if (resource.resourceType !== 'Patient')
|
|
46
|
+
throw new TypeError('us_core_patient_resource_required');
|
|
47
|
+
const extensions = Array.isArray(resource.extension) ? resource.extension : [];
|
|
48
|
+
return {
|
|
49
|
+
...readExtension(extensions, UsCorePatientRaceExtensionUrl, {
|
|
50
|
+
omb: UsCorePatientDemographicClaim.RaceOmbCategory,
|
|
51
|
+
detailed: UsCorePatientDemographicClaim.RaceDetailed,
|
|
52
|
+
text: UsCorePatientDemographicClaim.RaceText,
|
|
53
|
+
textError: 'us_core_patient_race_text_required',
|
|
54
|
+
}),
|
|
55
|
+
...readExtension(extensions, UsCorePatientEthnicityExtensionUrl, {
|
|
56
|
+
omb: UsCorePatientDemographicClaim.EthnicityOmbCategory,
|
|
57
|
+
detailed: UsCorePatientDemographicClaim.EthnicityDetailed,
|
|
58
|
+
text: UsCorePatientDemographicClaim.EthnicityText,
|
|
59
|
+
textError: 'us_core_patient_ethnicity_text_required',
|
|
60
|
+
singleOmbCategory: true,
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Derives the official token-search claims; callers never submit these independently. */
|
|
65
|
+
export function deriveUsCorePatientDemographicSearchClaims(claims) {
|
|
66
|
+
return {
|
|
67
|
+
[UsCorePatientDemographicSearchClaim.Race]: mergeTokenClaims(claims[UsCorePatientDemographicClaim.RaceOmbCategory], claims[UsCorePatientDemographicClaim.RaceDetailed]),
|
|
68
|
+
[UsCorePatientDemographicSearchClaim.Ethnicity]: mergeTokenClaims(claims[UsCorePatientDemographicClaim.EthnicityOmbCategory], claims[UsCorePatientDemographicClaim.EthnicityDetailed]),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function buildExtension(input) {
|
|
72
|
+
const omb = codingListFromCsv(input.omb) ?? [];
|
|
73
|
+
const detailed = codingListFromCsv(input.detailed) ?? [];
|
|
74
|
+
const text = String(input.text || '').trim();
|
|
75
|
+
if (!omb.length && !detailed.length && !text)
|
|
76
|
+
return undefined;
|
|
77
|
+
if (!text)
|
|
78
|
+
throw new TypeError(input.textError);
|
|
79
|
+
if (input.singleOmbCategory && omb.length > 1)
|
|
80
|
+
throw new TypeError('us_core_patient_ethnicity_omb_category_cardinality');
|
|
81
|
+
return Object.freeze({
|
|
82
|
+
url: input.url,
|
|
83
|
+
extension: Object.freeze([
|
|
84
|
+
...omb.map((valueCoding) => Object.freeze({ url: 'ombCategory', valueCoding })),
|
|
85
|
+
...detailed.map((valueCoding) => Object.freeze({ url: 'detailed', valueCoding })),
|
|
86
|
+
Object.freeze({ url: 'text', valueString: text }),
|
|
87
|
+
]),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function readExtension(extensions, url, keys) {
|
|
91
|
+
const matches = extensions.filter((extension) => extension.url === url);
|
|
92
|
+
if (!matches.length)
|
|
93
|
+
return {};
|
|
94
|
+
if (matches.length > 1)
|
|
95
|
+
throw new TypeError('us_core_patient_extension_cardinality');
|
|
96
|
+
const children = matches[0]?.extension ?? [];
|
|
97
|
+
const omb = children.filter((extension) => extension.url === 'ombCategory' && extension.valueCoding).map((extension) => extension.valueCoding);
|
|
98
|
+
const detailed = children.filter((extension) => extension.url === 'detailed' && extension.valueCoding).map((extension) => extension.valueCoding);
|
|
99
|
+
const texts = children.filter((extension) => extension.url === 'text' && extension.valueString).map((extension) => extension.valueString.trim()).filter(Boolean);
|
|
100
|
+
if (texts.length !== 1)
|
|
101
|
+
throw new TypeError(keys.textError);
|
|
102
|
+
if (keys.singleOmbCategory && omb.length > 1)
|
|
103
|
+
throw new TypeError('us_core_patient_ethnicity_omb_category_cardinality');
|
|
104
|
+
return {
|
|
105
|
+
[keys.omb]: codingListToCsv(omb),
|
|
106
|
+
[keys.detailed]: codingListToCsv(detailed),
|
|
107
|
+
[keys.text]: texts[0],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function mergeTokenClaims(...values) {
|
|
111
|
+
const tokens = values.flatMap((value) => String(value || '').split(',')).map((value) => value.trim()).filter(Boolean);
|
|
112
|
+
const unique = [...new Set(tokens)];
|
|
113
|
+
return unique.length ? unique.join(',') : undefined;
|
|
114
|
+
}
|
package/dist/converters/index.js
CHANGED
|
@@ -7,13 +7,17 @@ export type CommunicationRequestFormData = Readonly<{
|
|
|
7
7
|
status: typeof CommunicationRequestStatuses[number];
|
|
8
8
|
intent: typeof CommunicationRequestIntents[number];
|
|
9
9
|
priority?: typeof CommunicationRequestPriorities[number];
|
|
10
|
+
category?: string;
|
|
10
11
|
subject: string;
|
|
12
|
+
about?: readonly string[];
|
|
11
13
|
encounter?: string;
|
|
12
14
|
requester: string;
|
|
13
15
|
recipients: readonly string[];
|
|
14
16
|
informationProviders?: readonly string[];
|
|
15
17
|
authoredOn?: string;
|
|
16
18
|
occurrence?: string;
|
|
19
|
+
occurrencePeriodStart?: string;
|
|
20
|
+
occurrencePeriodEnd?: string;
|
|
17
21
|
payloadReference?: string;
|
|
18
22
|
payloadAttachmentContentType?: string;
|
|
19
23
|
payloadAttachmentData?: string;
|
|
@@ -45,10 +49,22 @@ export declare const FHIR_COMMUNICATION_REQUEST_FORM_SCHEMA: Readonly<{
|
|
|
45
49
|
type: "string";
|
|
46
50
|
enum: readonly ["routine", "urgent", "asap", "stat"];
|
|
47
51
|
}>;
|
|
52
|
+
category: Readonly<{
|
|
53
|
+
type: "string";
|
|
54
|
+
pattern: "^https?://[^|,]+\\|[^|,]+$";
|
|
55
|
+
}>;
|
|
48
56
|
subject: Readonly<{
|
|
49
57
|
type: "string";
|
|
50
58
|
pattern: "^[A-Za-z][A-Za-z0-9]+/[A-Za-z0-9.-]{1,64}$";
|
|
51
59
|
}>;
|
|
60
|
+
about: Readonly<{
|
|
61
|
+
type: "array";
|
|
62
|
+
uniqueItems: true;
|
|
63
|
+
items: Readonly<{
|
|
64
|
+
type: "string";
|
|
65
|
+
pattern: "^[A-Za-z][A-Za-z0-9]+/[A-Za-z0-9.-]{1,64}$";
|
|
66
|
+
}>;
|
|
67
|
+
}>;
|
|
52
68
|
encounter: Readonly<{
|
|
53
69
|
type: "string";
|
|
54
70
|
pattern: "^[A-Za-z][A-Za-z0-9]+/[A-Za-z0-9.-]{1,64}$";
|
|
@@ -82,6 +98,14 @@ export declare const FHIR_COMMUNICATION_REQUEST_FORM_SCHEMA: Readonly<{
|
|
|
82
98
|
type: "string";
|
|
83
99
|
format: "date-time";
|
|
84
100
|
}>;
|
|
101
|
+
occurrencePeriodStart: Readonly<{
|
|
102
|
+
type: "string";
|
|
103
|
+
format: "date-time";
|
|
104
|
+
}>;
|
|
105
|
+
occurrencePeriodEnd: Readonly<{
|
|
106
|
+
type: "string";
|
|
107
|
+
format: "date-time";
|
|
108
|
+
}>;
|
|
85
109
|
payloadReference: Readonly<{
|
|
86
110
|
type: "string";
|
|
87
111
|
pattern: "^[A-Za-z][A-Za-z0-9]+/[A-Za-z0-9.-]{1,64}$";
|
|
@@ -20,10 +20,14 @@ export const FHIR_COMMUNICATION_REQUEST_FORM_SCHEMA = Object.freeze({
|
|
|
20
20
|
status: Object.freeze({ type: 'string', enum: CommunicationRequestStatuses }),
|
|
21
21
|
intent: Object.freeze({ type: 'string', enum: CommunicationRequestIntents }),
|
|
22
22
|
priority: Object.freeze({ type: 'string', enum: CommunicationRequestPriorities }),
|
|
23
|
-
|
|
23
|
+
category: codingSchema(),
|
|
24
|
+
subject: referenceSchema(),
|
|
25
|
+
about: Object.freeze({ type: 'array', uniqueItems: true, items: referenceSchema() }),
|
|
26
|
+
encounter: referenceSchema(), requester: referenceSchema(),
|
|
24
27
|
recipients: Object.freeze({ type: 'array', minItems: 1, uniqueItems: true, items: referenceSchema() }),
|
|
25
28
|
informationProviders: Object.freeze({ type: 'array', uniqueItems: true, items: referenceSchema() }),
|
|
26
|
-
authoredOn: dateTimeSchema(), occurrence: dateTimeSchema(),
|
|
29
|
+
authoredOn: dateTimeSchema(), occurrence: dateTimeSchema(),
|
|
30
|
+
occurrencePeriodStart: dateTimeSchema(), occurrencePeriodEnd: dateTimeSchema(), payloadReference: referenceSchema(),
|
|
27
31
|
payloadAttachmentContentType: Object.freeze({ type: 'string', minLength: 1 }),
|
|
28
32
|
payloadAttachmentData: Object.freeze({ type: 'string', minLength: 1, contentEncoding: 'base64' }),
|
|
29
33
|
payloadAttachmentTitle: Object.freeze({ type: 'string', minLength: 1 }),
|
|
@@ -38,21 +42,34 @@ export function communicationRequestFormDataToFlatClaims(input) {
|
|
|
38
42
|
const recipients = references(input.recipients, 'communication_request_recipient_required');
|
|
39
43
|
const providers = input.informationProviders?.length
|
|
40
44
|
? references(input.informationProviders, 'communication_request_information_provider_invalid') : undefined;
|
|
45
|
+
const about = input.about?.length ? references(input.about, 'communication_request_about_invalid') : undefined;
|
|
41
46
|
if (input.payloadAttachmentData && !input.payloadAttachmentContentType) {
|
|
42
47
|
throw new TypeError('communication_request_attachment_content_type_required');
|
|
43
48
|
}
|
|
49
|
+
const occurrence = dateTime(input.occurrence);
|
|
50
|
+
const occurrencePeriodStart = dateTime(input.occurrencePeriodStart);
|
|
51
|
+
const occurrencePeriodEnd = dateTime(input.occurrencePeriodEnd);
|
|
52
|
+
if (occurrence && (occurrencePeriodStart || occurrencePeriodEnd))
|
|
53
|
+
throw new TypeError('communication_request_occurrence_choice_invalid');
|
|
54
|
+
if (occurrencePeriodStart && occurrencePeriodEnd && Date.parse(occurrencePeriodEnd) <= Date.parse(occurrencePeriodStart)) {
|
|
55
|
+
throw new TypeError('communication_request_occurrence_period_invalid');
|
|
56
|
+
}
|
|
44
57
|
return compact({
|
|
45
58
|
[CommunicationRequestClaim.Identifier]: optional(input.identifier),
|
|
46
59
|
[CommunicationRequestClaim.Status]: input.status,
|
|
47
60
|
[CommunicationRequestClaim.Intent]: input.intent,
|
|
48
61
|
[CommunicationRequestClaim.Priority]: optional(input.priority),
|
|
62
|
+
[CommunicationRequestClaim.Category]: coding(input.category),
|
|
49
63
|
[CommunicationRequestClaim.Subject]: reference(input.subject, 'communication_request_subject_invalid'),
|
|
64
|
+
[CommunicationRequestClaim.About]: about?.join(','),
|
|
50
65
|
[CommunicationRequestClaim.Encounter]: input.encounter ? reference(input.encounter, 'communication_request_encounter_invalid') : undefined,
|
|
51
66
|
[CommunicationRequestClaim.Requester]: reference(input.requester, 'communication_request_requester_invalid'),
|
|
52
67
|
[CommunicationRequestClaim.Recipient]: recipients.join(','),
|
|
53
68
|
[CommunicationRequestClaim.InformationProvider]: providers?.join(','),
|
|
54
69
|
[CommunicationRequestClaim.AuthoredOn]: dateTime(input.authoredOn),
|
|
55
|
-
[CommunicationRequestClaim.Occurrence]:
|
|
70
|
+
[CommunicationRequestClaim.Occurrence]: occurrence,
|
|
71
|
+
[CommunicationRequestClaim.OccurrencePeriodStart]: occurrencePeriodStart,
|
|
72
|
+
[CommunicationRequestClaim.OccurrencePeriodEnd]: occurrencePeriodEnd,
|
|
56
73
|
[CommunicationRequestClaim.PayloadReference]: input.payloadReference ? reference(input.payloadReference, 'communication_request_payload_reference_invalid') : undefined,
|
|
57
74
|
[CommunicationRequestClaim.PayloadAttachmentContentType]: optional(input.payloadAttachmentContentType),
|
|
58
75
|
[CommunicationRequestClaim.PayloadAttachmentData]: optional(input.payloadAttachmentData),
|
|
@@ -64,10 +81,14 @@ export function communicationRequestFlatClaimsToFormData(claims) {
|
|
|
64
81
|
return compact({
|
|
65
82
|
identifier: claims[CommunicationRequestClaim.Identifier], status: claims[CommunicationRequestClaim.Status],
|
|
66
83
|
intent: claims[CommunicationRequestClaim.Intent], priority: claims[CommunicationRequestClaim.Priority],
|
|
67
|
-
|
|
84
|
+
category: claims[CommunicationRequestClaim.Category],
|
|
85
|
+
subject: claims[CommunicationRequestClaim.Subject], about: splitOptional(claims[CommunicationRequestClaim.About]),
|
|
86
|
+
encounter: claims[CommunicationRequestClaim.Encounter],
|
|
68
87
|
requester: claims[CommunicationRequestClaim.Requester], recipients: split(claims[CommunicationRequestClaim.Recipient]),
|
|
69
88
|
informationProviders: splitOptional(claims[CommunicationRequestClaim.InformationProvider]),
|
|
70
89
|
authoredOn: claims[CommunicationRequestClaim.AuthoredOn], occurrence: claims[CommunicationRequestClaim.Occurrence],
|
|
90
|
+
occurrencePeriodStart: claims[CommunicationRequestClaim.OccurrencePeriodStart],
|
|
91
|
+
occurrencePeriodEnd: claims[CommunicationRequestClaim.OccurrencePeriodEnd],
|
|
71
92
|
payloadReference: claims[CommunicationRequestClaim.PayloadReference],
|
|
72
93
|
payloadAttachmentContentType: claims[CommunicationRequestClaim.PayloadAttachmentContentType],
|
|
73
94
|
payloadAttachmentData: claims[CommunicationRequestClaim.PayloadAttachmentData],
|
|
@@ -75,12 +96,15 @@ export function communicationRequestFlatClaimsToFormData(claims) {
|
|
|
75
96
|
});
|
|
76
97
|
}
|
|
77
98
|
function referenceSchema() { return Object.freeze({ type: 'string', pattern: '^[A-Za-z][A-Za-z0-9]+/[A-Za-z0-9.-]{1,64}$' }); }
|
|
99
|
+
function codingSchema() { return Object.freeze({ type: 'string', pattern: '^https?://[^|,]+\\|[^|,]+$' }); }
|
|
78
100
|
function dateTimeSchema() { return Object.freeze({ type: 'string', format: 'date-time' }); }
|
|
79
101
|
function optional(value) { const text = String(value ?? '').trim(); return text || undefined; }
|
|
80
102
|
function dateTime(value) { const text = optional(value); if (text && Number.isNaN(Date.parse(text)))
|
|
81
103
|
throw new TypeError('communication_request_datetime_invalid'); return text; }
|
|
82
104
|
function reference(value, error) { const text = optional(value); if (!text || !/^[A-Za-z][A-Za-z0-9]+\/[A-Za-z0-9.-]{1,64}$/u.test(text))
|
|
83
105
|
throw new TypeError(error); return text; }
|
|
106
|
+
function coding(value) { const text = optional(value); if (text && !/^https?:\/\/[^|,]+\|[^|,]+$/u.test(text))
|
|
107
|
+
throw new TypeError('communication_request_category_invalid'); return text; }
|
|
84
108
|
function references(values, error) { if (!Array.isArray(values) || !values.length)
|
|
85
109
|
throw new TypeError(error); const result = [...new Set(values.map(value => reference(value, error)))]; if (result.length !== values.length)
|
|
86
110
|
throw new TypeError(error); return result; }
|
|
@@ -8,7 +8,7 @@ export type FhirSearchParameter = Readonly<{
|
|
|
8
8
|
system?: string;
|
|
9
9
|
unit?: string;
|
|
10
10
|
}>;
|
|
11
|
-
/** Parses one typed FHIR query value without
|
|
11
|
+
/** Parses one typed FHIR query value without lossy integer coercion. */
|
|
12
12
|
export declare function parseFhirSearchParameter(input: Readonly<{
|
|
13
13
|
name: string;
|
|
14
14
|
type: FhirSearchParameterType;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PREFIX = /^(eq|ne|gt|lt|ge|le|sa|eb|ap)/;
|
|
2
|
-
/** Parses one typed FHIR query value without
|
|
2
|
+
/** Parses one typed FHIR query value without lossy integer coercion. */
|
|
3
3
|
export function parseFhirSearchParameter(input) {
|
|
4
4
|
const name = required(input.name, 'fhir_search_name_required');
|
|
5
5
|
const raw = required(input.value, 'fhir_search_value_required');
|
package/dist/imaging-types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resource-specific search models
|
|
2
|
+
* Resource-specific FHIR search models.
|
|
3
3
|
* Runtime parsing and serialization use `fhir-search-parameters`; these are
|
|
4
4
|
* compile-time compatibility surfaces, not a second query implementation.
|
|
5
5
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resource-specific search models
|
|
2
|
+
* Resource-specific FHIR search models.
|
|
3
3
|
* Runtime parsing and serialization use `fhir-search-parameters`; these are
|
|
4
4
|
* compile-time compatibility surfaces, not a second query implementation.
|
|
5
5
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Care, emergency and population-alert FHIR contracts
|
|
2
2
|
|
|
3
|
-
This package owns only the product-neutral FHIR representation used by
|
|
4
|
-
|
|
3
|
+
This package owns only the product-neutral FHIR representation used by three
|
|
4
|
+
care and emergency journeys.
|
|
5
5
|
Authorization, controller discovery, encryption, transport, storage and UI
|
|
6
6
|
policy remain in their owning product or service layers.
|
|
7
7
|
|
|
@@ -24,19 +24,14 @@ The layer split is:
|
|
|
24
24
|
fhir-data-utils-ts
|
|
25
25
|
canonical claims + R4/R5/R6 import/export
|
|
26
26
|
↓
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
27
|
+
downstream libraries
|
|
28
|
+
multichannel schemas, mutable editors, orchestration and product policy
|
|
35
29
|
```
|
|
36
30
|
|
|
37
|
-
When
|
|
38
|
-
fields, it must consume the canonical claim key from this package. It
|
|
39
|
-
maintain a second literal, converter or incompatible getter/setter
|
|
31
|
+
When a downstream application adds a visual, chat or telephone editor for one
|
|
32
|
+
of these fields, it must consume the canonical claim key from this package. It
|
|
33
|
+
must not maintain a second literal, converter or incompatible getter/setter
|
|
34
|
+
model.
|
|
40
35
|
|
|
41
36
|
The mutable GDC Bundle API remains documented separately in
|
|
42
37
|
[`gdc-common-utils-ts`](https://github.com/Global-DataCare/gdc-common-utils-ts/blob/main/docs/101-CLINICAL-ENTRY-GETTERS-SETTERS.md)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Communication Bundle contract
|
|
2
2
|
|
|
3
3
|
Every cross-participant clinical or administrative exchange uses the same
|
|
4
|
-
two-level FHIR envelope. This is the portable contract for
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
two-level FHIR envelope. This is the portable contract for downstream
|
|
5
|
+
channels; HTTP, DIDComm, encryption and recipient resolution remain in their
|
|
6
|
+
owning library or service.
|
|
7
7
|
|
|
8
8
|
```text
|
|
9
9
|
outer Bundle (type=batch)
|
|
@@ -45,10 +45,9 @@ The validator fails closed when the outer resource is not a batch Bundle, an out
|
|
|
45
45
|
batch entry lacks its request, the Communication has anything other than one
|
|
46
46
|
FHIR Bundle attachment, or the inner Bundle violates its declared type.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
their consumers migrate; this package neither imports nor wraps them.
|
|
48
|
+
Downstream libraries own high-level Bundle and Communication editors/readers,
|
|
49
|
+
cross-sector input contracts, fixtures, transport and product policy. This
|
|
50
|
+
package neither imports nor wraps those consumer surfaces.
|
|
52
51
|
|
|
53
52
|
At the GW persistence boundary, the validated native resources are projected
|
|
54
53
|
to independent `resource.meta.claims` rows. Direct flat-claim CRUD is an
|
package/package.json
CHANGED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
# UHC FHIR utilities migration
|
|
2
|
-
|
|
3
|
-
`uhc-fhir-utils-typescript` is an archaeological source, not a dependency of
|
|
4
|
-
this package. Its useful behavior must be recovered behind neutral, typed and
|
|
5
|
-
version-explicit contracts. Its product branding, obsolete security choices
|
|
6
|
-
and transport assumptions must not be copied.
|
|
7
|
-
|
|
8
|
-
The wider historical lineage began with early helpers in
|
|
9
|
-
`uhc-helpers-typescript`, was then split and improved across
|
|
10
|
-
`uhc-common-models-typescript`, `uhc-common-utils-typescript`,
|
|
11
|
-
`data-utils-typescript` and the crypto utilities, and later contributed to
|
|
12
|
-
`gdc-common-utils-ts`. For SHC and DGC, the later split packages are the
|
|
13
|
-
preferred behavioural and type evidence; the early helper remains UI-flow
|
|
14
|
-
evidence only.
|
|
15
|
-
|
|
16
|
-
## Migration rules
|
|
17
|
-
|
|
18
|
-
1. Add the smallest failing contract test here before porting behavior.
|
|
19
|
-
2. Use official FHIR R4/R5/R6 structures at import/export boundaries and flat
|
|
20
|
-
claims as the version-neutral representation between those boundaries.
|
|
21
|
-
3. Copy no raw claim, terminology, identifier or profile literal into a
|
|
22
|
-
consumer. Define it once in its owning neutral or sector data package.
|
|
23
|
-
4. Preserve historical inputs with explicit read adapters. New writers emit
|
|
24
|
-
only the current canonical representation.
|
|
25
|
-
5. Do not change `gdc-*` while those repositories are frozen. They are
|
|
26
|
-
read-only compatibility evidence until every consumer uses this package.
|
|
27
|
-
|
|
28
|
-
## Reuse, rewrite or retire
|
|
29
|
-
|
|
30
|
-
| Old area | Decision | Current destination or gate |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| `Bundle` and `Composition` traversal | Rewrite from tests | Neutral graph and explicit R4/R5/R6 adapters; preserve author, attester and section boundaries |
|
|
33
|
-
| `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` |
|
|
34
|
-
| `CodeableConcept`, `Identifier`, `Reference`, `Quantity` | Rewrite and reuse behavior | Small typed value modules with round-trip tests |
|
|
35
|
-
| `Observation` and resource parameter models | Rewrite | Canonical claim catalogs plus version-specific projection adapters |
|
|
36
|
-
| `Parameters` conversion | Rewrite | A typed FHIR Parameters module; never a transport-specific envelope |
|
|
37
|
-
| Anonymization field inventory | Test input only | A separately reviewed policy contract; old field lists do not become policy automatically |
|
|
38
|
-
| ATC, LOINC, SNOMED and EMA JSON | Validate before reuse | Terminology service fixtures, never authoritative embedded catalogs |
|
|
39
|
-
| DICOM parsing | Extract later | Separate imaging package; do not add `dicom-parser` to the neutral core |
|
|
40
|
-
| ImagingStudy metadata | Rewrite | Neutral flat claims and R4 projection for subject, encounter, modality, procedure and protected endpoint references; DICOM bytes remain outside |
|
|
41
|
-
| SHA-1 attachment hashing | Retire | No compatibility writer; historical read/verification belongs in a versioned adapter |
|
|
42
|
-
| `MessageHeader` transport conventions | Retire | Transport is outside the FHIR data contract |
|
|
43
|
-
| UHC-branded templates and defaults | Retire or move downstream | Product policy belongs in UHC packages, not here |
|
|
44
|
-
| Babel/Yarn/Jest build plumbing and broad `any` models | Retire | Node 24, TypeScript strict mode and `node:test` |
|
|
45
|
-
|
|
46
|
-
## Completed source inventory
|
|
47
|
-
|
|
48
|
-
| Source | Migrated here | Deliberately remains outside |
|
|
49
|
-
| --- | --- | --- |
|
|
50
|
-
| `gdc-common-utils-ts` interoperable claims | All product-neutral claim catalogs, specs and claim helpers, including Consent and the complete SOS Task surface | Schema.org/Gaia-X mapping and runtime policy |
|
|
51
|
-
| `gdc-common-utils-ts` converters | Every product-neutral R4/R5 converter present there; Observation component writing was corrected to use a resource graph | Network, persistence and authorization orchestration |
|
|
52
|
-
| `uhc-fhir-utils-typescript` models | ATC/FHIR/LOINC/SNOMED model types, all resource search parameter enums and template interfaces, strict replacement FHIR primitives | Embedded terminology JSON is not authoritative data |
|
|
53
|
-
| `uhc-fhir-utils-typescript` helpers | Coding/token, Identifier, Reference, Quantity, telecom, RelatedPerson search projection and non-mutating Bundle traversal/classification/reference lookup | Message transport, SHA-1 writers, COVID-era product presets and mutation-heavy manager facades |
|
|
54
|
-
| Later UHC data/common packages | SHC and EU DGC QR prefix classification plus repository-safe examples | Signature verification, issuer trust, credential import and authorization remain separate future contracts |
|
|
55
|
-
| `uhc-fhir-utils-typescript` imaging | DICOMDIR structural types only | Byte parsing and pixel extraction require a separately versioned imaging package |
|
|
56
|
-
| `sos-data-utils-ts` | Cross-sector terminology contract and fixtures, Immunization graph and reminder planning | SOS authorization, repository and emergency policy |
|
|
57
|
-
| `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 |
|
|
58
|
-
| 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 |
|
|
59
|
-
| UHC/Vet SDKs | No transport client was copied | SMART clients, Oracle clients, BFF calls and product workflows remain SDK responsibilities |
|
|
60
|
-
|
|
61
|
-
The frozen `gdc-*` implementation remains compatibility evidence. New Vet,
|
|
62
|
-
UHC and SOS code uses the replacement high-level API in `sos-sdk-core`, which
|
|
63
|
-
composes the neutral tools exported here. Neither shared replacement package
|
|
64
|
-
imports `gdc-*`. DIDComm wrapping, post-quantum encryption, endpoint selection
|
|
65
|
-
and delivery retries remain in the SDK/service layer.
|
|
66
|
-
|
|
67
|
-
The migration surface is executable rather than documentary only:
|
|
68
|
-
|
|
69
|
-
- every migrated claim family has a named catalog and shared list helpers;
|
|
70
|
-
- every migrated product-neutral converter participates in the converter
|
|
71
|
-
round-trip matrix, with rich optional-field fixtures for complex resources;
|
|
72
|
-
- Encounter retains its originating Appointment and ImagingStudy retains
|
|
73
|
-
searchable metadata without embedding DICOM object bytes;
|
|
74
|
-
- FHIR primitives, typed searches, Bundle traversal and fallback conversion
|
|
75
|
-
have strict success and rejection tests;
|
|
76
|
-
- Communication exchange is authored and read only as outer batch Bundle to
|
|
77
|
-
Communication to inner document/batch/collection Bundle, with files modeled
|
|
78
|
-
as inner DocumentReference resources;
|
|
79
|
-
- Immunization graphs and reminders live once under `src/builders/`; the former
|
|
80
|
-
root modules are deprecated re-export shims;
|
|
81
|
-
- Group and ResearchStudy expose named claim constants, preserve member/party
|
|
82
|
-
correlation as separate rows and reject authorization-shaped data;
|
|
83
|
-
- Organization departments remain distinct from offered HealthcareServices;
|
|
84
|
-
every independently schedulable service keeps its own stable identity and
|
|
85
|
-
Location references, while professional Group ownership remains explicit;
|
|
86
|
-
- `buildServiceScheduleFlatGraph(...)` and the R5 Schedule/Slot adapters keep
|
|
87
|
-
per-service planning horizons and slot intervals shared between Vet and UHC;
|
|
88
|
-
- schedulable child Locations preserve `partOf`, while Schedule actors can
|
|
89
|
-
combine the service with Location, Device and PractitionerRole capacity;
|
|
90
|
-
and
|
|
91
|
-
- `npm run check` enforces minimum line, function and branch coverage across
|
|
92
|
-
converters, builders and core FHIR modules.
|
|
93
|
-
|
|
94
|
-
This inventory is a boundary decision, not permission to leave another copy in
|
|
95
|
-
new code. Consumers must move to this package bottom-up after its immutable
|
|
96
|
-
release. Existing packages may retain compatibility re-exports only during
|
|
97
|
-
that promotion.
|
|
98
|
-
|
|
99
|
-
## Observation and component contract
|
|
100
|
-
|
|
101
|
-
FHIR blood pressure is one native `Observation` with systolic and diastolic
|
|
102
|
-
entries in `Observation.component[]`. Canonical flat storage is instead a
|
|
103
|
-
resource graph: the primary Observation owns `Observation.has-member`, and
|
|
104
|
-
each referenced reduced Observation owns its identifier, subject, category,
|
|
105
|
-
date, component code, numeric value and unit. Reduced entries deliberately
|
|
106
|
-
carry no `Observation.status`, so normal top-level listings ignore them while
|
|
107
|
-
component-level indexes can query their ordinary Observation claims.
|
|
108
|
-
|
|
109
|
-
The R4/R5 export adapter resolves the primary entry's members and reconstructs
|
|
110
|
-
one native `Observation.component[]`; it does not export three independent
|
|
111
|
-
native Observations. Component entries do not use `is-contained`,
|
|
112
|
-
`contained-parent-reference` or `contained-reference-list`.
|
|
113
|
-
|
|
114
|
-
Diagnostic laboratory authoring is owned here by
|
|
115
|
-
`buildDiagnosticReportFlatGraph(...)`: `DiagnosticReport.code` identifies the
|
|
116
|
-
report/panel, independent Observation entries carry atomic results, and
|
|
117
|
-
independent DocumentReference entries carry PDF/image evidence. Sector roles,
|
|
118
|
-
confirmation, ledger eligibility, consent and research policy remain outside
|
|
119
|
-
this package.
|
|
120
|
-
|
|
121
|
-
Aligned JSON arrays and the older comma-separated `Observation.component-*`
|
|
122
|
-
claims are accepted only by the migration reader. No current writer emits
|
|
123
|
-
either representation.
|
|
124
|
-
|
|
125
|
-
The historical `Observation.bp-systolic-number` and
|
|
126
|
-
`Observation.bp-diastolic-number` fields are accepted only when reading data
|
|
127
|
-
that has no component graph or historical component claims. New writers and
|
|
128
|
-
generic component indexes never emit them. This prevents a new custom claim
|
|
129
|
-
family for every assessment scale.
|
|
130
|
-
|
|
131
|
-
## Consumer promotion sequence
|
|
132
|
-
|
|
133
|
-
1. Release this package, pin the immutable version in the lowest downstream
|
|
134
|
-
package, and run that consumer's complete local matrix.
|
|
135
|
-
2. Remove the corresponding frozen dependency only after no consumer imports
|
|
136
|
-
that family from it.
|
|
137
|
-
3. Migrate imaging/DICOM byte parsing and terminology payloads as separate changes because
|
|
138
|
-
they have different dependencies, security rules and release gates.
|
|
139
|
-
|
|
140
|
-
## Ownership map for new work
|
|
141
|
-
|
|
142
|
-
| Change | Owning surface |
|
|
143
|
-
| --- | --- |
|
|
144
|
-
| Add or rename a flat storage key | `src/claims/<resource>-claims.ts` |
|
|
145
|
-
| Convert a native R4/R5 resource | `src/converters/convert-<resource>.ts` |
|
|
146
|
-
| Author several correlated resources | `src/builders/` |
|
|
147
|
-
| Preserve an obsolete input | Explicit read-only compatibility adapter |
|
|
148
|
-
| Add transport, SMART or persistence behavior | Owning SDK/service, never this package |
|
|
149
|
-
| Add sector terminology or policy | SOS, Vet or UHC data package |
|
|
150
|
-
| Configure an R5 SubscriptionTopic/Subscription | Native builder and official search catalog in `subscription-r5`; registration remains in the owning service |
|
|
151
|
-
| Persist or deliver a subscription event | GW/BFF transport and storage, never this package |
|
|
152
|
-
|
|
153
|
-
Converters and builders import catalog symbols. Tests may spell native FHIR
|
|
154
|
-
wire fields, but do not duplicate flat-claim paths except when proving that a
|
|
155
|
-
malformed or invented path is rejected.
|
|
156
|
-
|
|
157
|
-
## Schema-driven editor boundary
|
|
158
|
-
|
|
159
|
-
`clinicalArtifactFhirR4ToFlat(...)` and
|
|
160
|
-
`clinicalArtifactEditorClaimsFromFhirR4(...)` are import/read adapters. They
|
|
161
|
-
turn a native FHIR R4 clinical resource into canonical flat claims and never
|
|
162
|
-
own a portal form, authorization or transport decision.
|
|
163
|
-
|
|
164
|
-
The cross-channel JSON Schema and the `BundleEditor`/`BundleReader` round trip
|
|
165
|
-
belong to `sos-data-utils-ts`. A shared React component consumes both layers:
|
|
166
|
-
FHIR conversion for native imports, then the SOS JSON Schema to select and
|
|
167
|
-
validate editable values and create the claims-first changes Bundle. Portals
|
|
168
|
-
must not add resource-specific claim mappers between those shared layers.
|
|
169
|
-
|
|
170
|
-
## Subscription notification boundary
|
|
171
|
-
|
|
172
|
-
FHIR R5 `SubscriptionTopic` and `Subscription` are native configuration
|
|
173
|
-
resources, not flat clinical persistence. This package owns their strict typed
|
|
174
|
-
builders, the official R5 resource-specific SearchParameter catalogs and the
|
|
175
|
-
parser for `Bundle[type=subscription-notification]`. It also owns the minimal
|
|
176
|
-
claims-first terminal Task `Communication` shape so producers and receivers do
|
|
177
|
-
not duplicate claim paths.
|
|
178
|
-
|
|
179
|
-
HTTP delivery, authentication, durable outbox/inbox storage and browser or
|
|
180
|
-
email/push fan-out remain in GW, DataConv and the product BFFs. The neutral
|
|
181
|
-
package contains no HTTP client and no gateway policy.
|