fhir-data-utils-ts 0.6.19 → 0.6.21

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.
@@ -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 copied from frozen gdc-common-utils, former UHC utilities, SOS, Vet or UHC packages; raw flat-claim literals; duplicate root and family modules; Observation components; Immunization graphs; Group or ResearchStudy projections; package exports; coverage gates; or downstream promotion.
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. Read `docs/UHC_FHIR_UTILS_MIGRATION.md` and inventory every relevant source
11
- family before declaring a migration complete.
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, treat `uhc-helpers-typescript` as the early
19
- flow source, the later UHC common models/data/common/crypto split as the
20
- preferred implementation evidence, and `gdc-common-utils-ts` as its later
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 the cross-product high-level editor/reader in `sos-sdk-core`
72
- and its data contracts in `sos-data-utils`. Neither replacement package may
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 code from gdc-common-utils-ts or uhc-fhir-utils-typescript.
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`, their
13
- tests, and `docs/UHC_FHIR_UTILS_MIGRATION.md` before changing behavior.
14
- 3. Treat every `gdc-*` repository and `uhc-fhir-utils-typescript` as read-only
15
- compatibility evidence unless the user explicitly changes that scope.
16
- 4. Keep product policies in SOS, Vet or UHC packages. This package owns only
17
- neutral FHIR data semantics.
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 old UHC package, `gdc-common-utils-ts`, `sos-data-utils-ts`,
83
- `vet-data-utils-ts`, and the UHC/Vet/SOS SDKs before calling a migration
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
- `docs/UHC_FHIR_UTILS_MIGRATION.md`; an unmentioned file is an incomplete
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 DataConv, Vet or UHC ingestion, ResearchSubject batches, contained clinical resources, coding-review UI/API contracts, examples, fixtures or tests.
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 Vet, UHC or DataConv consumers.
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 SOSChain, Vet, UHC or frozen `gdc-*` packages.
64
- - DataConv applies the contract during import. Vet and UHC consume the same
65
- contract and may add sector policy without forking its claim shape.
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,23 @@
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.21 - 2026-10-21
9
+
10
+ - Add the shared CommunicationRequest form, flat-claim and materialization
11
+ fields needed for categorized public alerts, related attachments and bounded
12
+ occurrence periods without introducing a proprietary alert resource.
13
+
14
+ ## 0.6.20 - 2026-10-12
15
+
16
+ - Export the deduplicated official LOINC Document Ontology subject-matter-
17
+ domain catalogue supplied from the LOINC Knowledge Base for human-health
18
+ selectors. Keep it explicitly separate from veterinary service types.
19
+
20
+ ## 0.6.19 - 2026-10-12
21
+
5
22
  - Add the official `HealthcareService.appointmentRequired` flat claim and
6
23
  R4/R5 materialization round trip. Availability remains authoritative in the
7
24
  associated Schedule and Slot resources and is not duplicated on the service.
@@ -50,8 +67,8 @@
50
67
  - Give every reusable IPS authoring schema canonical initial claims so portal
51
68
  components do not invent resource status defaults.
52
69
 
53
- - Recover the useful locale-aware intent of the historical UHC
54
- internationalization helpers as strict FHIR temporal presentation tools.
70
+ - Recover useful locale-aware behavior from historical compatibility helpers
71
+ as strict FHIR temporal presentation tools.
55
72
  Date-only values retain their calendar day, instants render with the user's
56
73
  locale and IANA time zone, editor date/time fields compose a canonical FHIR
57
74
  instant with optional seconds defaulted to `00`, and inclusive ranges treat
@@ -78,8 +95,8 @@
78
95
  document so portals can update the Composition without duplicating LOINC
79
96
  section codes.
80
97
 
81
- - Recover neutral SHC and EU DGC QR prefix classification from the later UHC
82
- data-utility lineage, with exported repository-safe `*.data.ts` examples.
98
+ - Recover neutral SHC and EU DGC QR prefix classification from compatibility
99
+ evidence, with exported repository-safe `*.data.ts` examples.
83
100
  Recognition explicitly provides no decoding, verification or authorization.
84
101
 
85
102
  - Export one repository-safe, telephone-free IPS demo document with all sixteen
@@ -91,8 +108,8 @@
91
108
  historical source modules remain compatibility reexports.
92
109
  - Remove notification-channel policy from the general root and `builders`
93
110
  surfaces. The historical reminder subpath and non-standard `Task.channel`
94
- claim remain deprecated compatibility only while product packages migrate;
95
- SOS/Vet/UHC own channel choices and dispatch behavior.
111
+ claim remain deprecated compatibility only while consumers migrate;
112
+ downstream applications own channel choices and dispatch behavior.
96
113
 
97
114
  ## 0.6.2 - 2026-09-30
98
115
 
@@ -115,7 +132,7 @@
115
132
  the frozen shared implementation: outer batch Bundle, one FHIR Bundle
116
133
  attachment per Communication, and validated document/batch/collection inner
117
134
  Bundles. Reject direct clinical or binary Communication payloads while
118
- leaving high-level mutable editors to `sos-sdk-core`.
135
+ leaving high-level mutable editors downstream.
119
136
  - Add a typed Appointment exchange projection that preserves start/end,
120
137
  participants, slots and supporting information while keeping an ICS calendar
121
138
  file as an independent DocumentReference flat-claim resource.
@@ -246,9 +263,9 @@
246
263
  modifying that frozen source repository.
247
264
  - Recover strict FHIR primitives, value/search/token utilities, Bundle readers,
248
265
  resource search/template types, terminology model types, RelatedPerson and
249
- telecom helpers, and DICOMDIR structural types from the retired UHC package.
266
+ telecom helpers, and DICOMDIR structural types from compatibility evidence.
250
267
  - Move cross-sector terminology, Immunization graph/reminder, Group R5 and
251
- ResearchStudy R5 contracts that existed only in SOS or Vet data packages.
268
+ ResearchStudy R5 contracts into their neutral standards-based owner.
252
269
  - Require component Observations to use independently indexable graph entries;
253
270
  deprecated JSON-array component claims remain read-only compatibility input.
254
271
  - Add stable package subpaths for every migrated contract family.
@@ -285,12 +302,12 @@
285
302
  JSON repeatable-component encoding, generic component index projection and
286
303
  explicit R4/R5 projection boundary. Historical component CSV and `bp-*`
287
304
  aliases remain read-only compatibility inputs.
288
- - Record the reuse/rewrite/retire audit of the original
289
- `uhc-fhir-utils-typescript` architecture without adding its obsolete product,
290
- transport, SHA-1, DICOM or build dependencies to the neutral package.
305
+ - Record the reuse/rewrite/retire audit of historical compatibility utilities
306
+ without adding obsolete product, transport, SHA-1, DICOM or build
307
+ dependencies to the neutral package.
291
308
  - Add the neutral contained-resource coding-review contract: canonical imported
292
309
  `*-text`, resource-scoped `meta.codingProposals[]`, batch traversal, candidate
293
- confirmation and reusable governed fixtures for DataConv, Vet and UHC.
310
+ confirmation and reusable governed fixtures for downstream consumers.
294
311
  - Add channel-neutral FHIR-like vital-sign Observation builders and lossless device-batch normalization while preserving device source without inventing professional attestation.
295
312
  - Introduce product-neutral flat-claim resource graphs, parent-owned
296
313
  `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 GDC, SOS, Vet or UHC packages.
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
- ## Where this package sits
11
+ ## Public source history
12
12
 
13
- ```text
14
- fhir-data-utils-ts
15
- └─ FHIR SearchParameters, flat-claim graphs and R4/R5/R6 projection rules
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
- terminology-api-node-ts reads the neutral FHIR and shared SOS contracts.
23
- It never depends on Vet or UHC product packages.
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; the shared high-level editor/reader belongs
52
- to `sos-sdk-core`, with cross-sector contracts in `sos-data-utils`. See
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
- - the recovered UHC resource search/template types, terminology model types,
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 previously located only in SOS or Vet packages.
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
- shared SOS multichannel schemas and the mutable Bundle getters/setters exposed
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
- DataConv, Vet and UHC share one neutral review contract from
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 the three SOSChain
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 SOS/Vet/UHC data package, not to the general FHIR data package.
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 SOS/Vet/UHC data package, not to the general FHIR data package.
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.' },
@@ -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 SOS, Vet or UHC channels. */
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
- occurrenceDateTime: claims[CommunicationRequestClaim.Occurrence],
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, [CommunicationRequestClaim.Occurrence]: resource.occurrenceDateTime,
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], occurrenceDateTime: claims[CommunicationRequestClaim.Occurrence],
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
- [CommunicationRequestClaim.Occurrence]: resource.occurrenceDateTime,
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] } }];
@@ -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
- subject: referenceSchema(), encounter: referenceSchema(), requester: referenceSchema(),
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(), payloadReference: referenceSchema(),
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]: dateTime(input.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
- subject: claims[CommunicationRequestClaim.Subject], encounter: claims[CommunicationRequestClaim.Encounter],
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; }
@@ -6,3 +6,4 @@ export * from './health-credential-qr.data.js';
6
6
  export * from './ips-clinical-artifact-schemas.data.js';
7
7
  export * from './clinical-document-encounter-journey.data.js';
8
8
  export * from './communication-request-form-schema.data.js';
9
+ export * from './loinc-subject-matter-domain.data.js';
@@ -6,3 +6,4 @@ export * from './health-credential-qr.data.js';
6
6
  export * from './ips-clinical-artifact-schemas.data.js';
7
7
  export * from './clinical-document-encounter-journey.data.js';
8
8
  export * from './communication-request-form-schema.data.js';
9
+ export * from './loinc-subject-matter-domain.data.js';