gdc-common-utils-ts 1.20.2 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/claims/claims-helpers-related-person.d.ts +14 -0
- package/dist/claims/claims-helpers-related-person.js +28 -0
- package/dist/constants/Schemas.d.ts +3 -0
- package/dist/constants/Schemas.js +3 -0
- package/dist/constants/fhir-code-systems.d.ts +1 -0
- package/dist/constants/fhir-code-systems.js +1 -0
- package/dist/constants/fhir-resource-types.d.ts +2 -0
- package/dist/constants/fhir-resource-types.js +1 -0
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.js +3 -0
- package/dist/constants/individual-sections.d.ts +210 -0
- package/dist/constants/individual-sections.js +35 -0
- package/dist/constants/lifecycle.d.ts +17 -0
- package/dist/constants/lifecycle.js +18 -0
- package/dist/constants/observation-category.d.ts +72 -0
- package/dist/constants/observation-category.js +30 -0
- package/dist/constants/schemaorg.d.ts +4 -0
- package/dist/constants/schemaorg.js +4 -0
- package/dist/constants/vital-signs.d.ts +2 -17
- package/dist/constants/vital-signs.js +1 -6
- package/dist/convert/convert-observation.d.ts +20 -2
- package/dist/convert/convert-observation.js +80 -9
- package/dist/examples/index.d.ts +2 -0
- package/dist/examples/index.js +2 -0
- package/dist/examples/invoice.d.ts +37 -0
- package/dist/examples/invoice.js +72 -0
- package/dist/examples/license.d.ts +161 -0
- package/dist/examples/license.js +136 -7
- package/dist/examples/lifecycle.d.ts +44 -0
- package/dist/examples/lifecycle.js +25 -0
- package/dist/examples/related-person.d.ts +348 -0
- package/dist/examples/related-person.js +184 -2
- package/dist/examples/shared.d.ts +110 -8
- package/dist/examples/shared.js +129 -17
- package/dist/examples/vital-signs.d.ts +56 -0
- package/dist/examples/vital-signs.js +159 -0
- package/dist/models/fhir-documents.d.ts +35 -0
- package/dist/models/indexing.d.ts +68 -6
- package/dist/models/indexing.js +294 -11
- package/dist/models/interoperable-claims/index.d.ts +1 -0
- package/dist/models/interoperable-claims/index.js +1 -0
- package/dist/models/interoperable-claims/invoice-claims.d.ts +277 -0
- package/dist/models/interoperable-claims/invoice-claims.js +353 -0
- package/dist/models/interoperable-claims/observation-claims.d.ts +253 -1
- package/dist/models/interoperable-claims/observation-claims.js +249 -3
- package/dist/models/interoperable-claims.d.ts +1 -1
- package/dist/models/interoperable-claims.js +1 -1
- package/dist/models/urlPath.d.ts +3 -1
- package/dist/models/urlPath.js +2 -0
- package/dist/utils/bundle-document-builder.js +22 -4
- package/dist/utils/bundle-editor.d.ts +105 -2
- package/dist/utils/bundle-editor.js +282 -2
- package/dist/utils/clinical-resource-converters.d.ts +4 -4
- package/dist/utils/clinical-resource-converters.js +5 -5
- package/dist/utils/communication-attached-bundle-session.d.ts +11 -0
- package/dist/utils/communication-attached-bundle-session.js +29 -0
- package/dist/utils/consent-lifecycle-result-reader.d.ts +24 -0
- package/dist/utils/consent-lifecycle-result-reader.js +27 -0
- package/dist/utils/employee.d.ts +25 -0
- package/dist/utils/employee.js +57 -0
- package/dist/utils/gw-core-path.d.ts +24 -0
- package/dist/utils/gw-core-path.js +21 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/individual-bundle-vault.d.ts +144 -0
- package/dist/utils/individual-bundle-vault.js +455 -0
- package/dist/utils/individual-organization-lifecycle.d.ts +104 -0
- package/dist/utils/individual-organization-lifecycle.js +179 -0
- package/dist/utils/interoperable-resource-operation.d.ts +158 -0
- package/dist/utils/interoperable-resource-operation.js +244 -0
- package/dist/utils/invoice-bundle.d.ts +82 -0
- package/dist/utils/invoice-bundle.js +240 -0
- package/dist/utils/license-commercial-search.d.ts +118 -0
- package/dist/utils/license-commercial-search.js +228 -0
- package/dist/utils/license-list-search.d.ts +105 -0
- package/dist/utils/license-list-search.js +209 -0
- package/dist/utils/license-offer-order.d.ts +107 -0
- package/dist/utils/license-offer-order.js +262 -0
- package/dist/utils/license.d.ts +6 -0
- package/dist/utils/license.js +6 -0
- package/dist/utils/lifecycle-result-reader.d.ts +33 -0
- package/dist/utils/lifecycle-result-reader.js +99 -0
- package/dist/utils/related-person-list.d.ts +20 -0
- package/dist/utils/related-person-list.js +54 -0
- package/package.json +2 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
3
|
+
import { VitalSignsCodes, VitalSignsUnits } from '../constants/vital-signs.js';
|
|
4
|
+
import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
|
|
5
|
+
import { Format } from '../constants/Schemas.js';
|
|
6
|
+
import { observationFromFlatToFhirR4 } from '../convert/convert-observation.js';
|
|
7
|
+
import { CommunicationAttachedBundleSession } from '../utils/communication-attached-bundle-session.js';
|
|
8
|
+
import { buildVitalSignObservationClaims } from '../utils/individual-bundle-vault.js';
|
|
9
|
+
import { EXAMPLE_COMMUNICATION_IDENTIFIER, EXAMPLE_OBSERVATION_COMPONENT_IDENTIFIER, EXAMPLE_OBSERVATION_COMPONENT_IDENTIFIER_SECONDARY, EXAMPLE_OBSERVATION_IDENTIFIER, EXAMPLE_OBSERVATION_PANEL_IDENTIFIER, EXAMPLE_SUBJECT_DID, EXAMPLE_VITAL_SIGN_DISPLAY_VITAL_SIGNS, EXAMPLE_VITAL_SIGNS_EFFECTIVE_DATE_TIME, EXAMPLE_VITAL_SIGNS_NOTE, EXAMPLE_VITAL_SIGN_VALUE_BODY_TEMPERATURE, EXAMPLE_VITAL_SIGN_VALUE_DIASTOLIC, EXAMPLE_VITAL_SIGN_VALUE_HEART_RATE, EXAMPLE_VITAL_SIGN_VALUE_SYSTOLIC, } from './shared.js';
|
|
10
|
+
/**
|
|
11
|
+
* Shared example inputs for authoring vital-sign Observations in claims-first
|
|
12
|
+
* flows.
|
|
13
|
+
*
|
|
14
|
+
* Reference:
|
|
15
|
+
* - HL7 CIMI Vital Signs with Qualifying Elements IG
|
|
16
|
+
* https://build.fhir.org/ig/HL7/cimi-vital-signs/
|
|
17
|
+
*
|
|
18
|
+
* These examples intentionally cover only direct vital-sign authoring inputs
|
|
19
|
+
* that a person or simple frontend form would create:
|
|
20
|
+
* - heart rate
|
|
21
|
+
* - body temperature
|
|
22
|
+
* - systolic blood pressure
|
|
23
|
+
* - diastolic blood pressure
|
|
24
|
+
*
|
|
25
|
+
* Panel/group authoring is excluded on purpose because panels are typically
|
|
26
|
+
* imported from external FHIR systems or composed by professional workflows.
|
|
27
|
+
*/
|
|
28
|
+
/** Example claims-first input for one heart rate Observation (LOINC 8867-4, UCUM /min). */
|
|
29
|
+
export const EXAMPLE_VITAL_SIGN_HEART_RATE_INPUT = {
|
|
30
|
+
identifier: EXAMPLE_OBSERVATION_IDENTIFIER,
|
|
31
|
+
subject: EXAMPLE_SUBJECT_DID,
|
|
32
|
+
code: VitalSignsCodes.HeartRate,
|
|
33
|
+
unit: VitalSignsUnits.BeatsPerMinute,
|
|
34
|
+
valueQuantity: EXAMPLE_VITAL_SIGN_VALUE_HEART_RATE,
|
|
35
|
+
effectiveDateTime: EXAMPLE_VITAL_SIGNS_EFFECTIVE_DATE_TIME,
|
|
36
|
+
};
|
|
37
|
+
/** Example claims-first input for one body temperature Observation (LOINC 8310-5, UCUM Cel). */
|
|
38
|
+
export const EXAMPLE_VITAL_SIGN_BODY_TEMPERATURE_INPUT = {
|
|
39
|
+
identifier: EXAMPLE_OBSERVATION_PANEL_IDENTIFIER,
|
|
40
|
+
subject: EXAMPLE_SUBJECT_DID,
|
|
41
|
+
code: VitalSignsCodes.BodyTemperature,
|
|
42
|
+
unit: VitalSignsUnits.Celsius,
|
|
43
|
+
valueQuantity: EXAMPLE_VITAL_SIGN_VALUE_BODY_TEMPERATURE,
|
|
44
|
+
effectiveDateTime: EXAMPLE_VITAL_SIGNS_EFFECTIVE_DATE_TIME,
|
|
45
|
+
};
|
|
46
|
+
/** Example claims-first input for one systolic blood pressure Observation (LOINC 8480-6, UCUM mm[Hg]). */
|
|
47
|
+
export const EXAMPLE_VITAL_SIGN_SYSTOLIC_BLOOD_PRESSURE_INPUT = {
|
|
48
|
+
identifier: EXAMPLE_OBSERVATION_COMPONENT_IDENTIFIER,
|
|
49
|
+
subject: EXAMPLE_SUBJECT_DID,
|
|
50
|
+
code: VitalSignsCodes.SystolicBloodPressure,
|
|
51
|
+
unit: VitalSignsUnits.MillimeterOfMercury,
|
|
52
|
+
valueQuantity: EXAMPLE_VITAL_SIGN_VALUE_SYSTOLIC,
|
|
53
|
+
effectiveDateTime: EXAMPLE_VITAL_SIGNS_EFFECTIVE_DATE_TIME,
|
|
54
|
+
};
|
|
55
|
+
/** Example claims-first input for one diastolic blood pressure Observation (LOINC 8462-4, UCUM mm[Hg]). */
|
|
56
|
+
export const EXAMPLE_VITAL_SIGN_DIASTOLIC_BLOOD_PRESSURE_INPUT = {
|
|
57
|
+
identifier: EXAMPLE_OBSERVATION_COMPONENT_IDENTIFIER_SECONDARY,
|
|
58
|
+
subject: EXAMPLE_SUBJECT_DID,
|
|
59
|
+
code: VitalSignsCodes.DiastolicBloodPressure,
|
|
60
|
+
unit: VitalSignsUnits.MillimeterOfMercury,
|
|
61
|
+
valueQuantity: EXAMPLE_VITAL_SIGN_VALUE_DIASTOLIC,
|
|
62
|
+
effectiveDateTime: EXAMPLE_VITAL_SIGNS_EFFECTIVE_DATE_TIME,
|
|
63
|
+
};
|
|
64
|
+
function resolveObservationEntryFullUrl(identifier) {
|
|
65
|
+
return String(identifier || '').startsWith('urn:')
|
|
66
|
+
? String(identifier)
|
|
67
|
+
: `urn:uuid:${String(identifier)}`;
|
|
68
|
+
}
|
|
69
|
+
function toFlatClaims(record) {
|
|
70
|
+
const claims = {};
|
|
71
|
+
for (const [key, value] of Object.entries(record || {})) {
|
|
72
|
+
if (value === undefined || value === null)
|
|
73
|
+
continue;
|
|
74
|
+
claims[key] = typeof value === 'string' ? value : String(value);
|
|
75
|
+
}
|
|
76
|
+
return claims;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Builds one high-level bundle entry for a vital-sign Observation.
|
|
80
|
+
*
|
|
81
|
+
* This is the preferred copy-paste pattern for frontend flows:
|
|
82
|
+
* 1. author flat claims with `buildVitalSignObservationClaims(...)`
|
|
83
|
+
* 2. convert them to one FHIR R4 `Observation`
|
|
84
|
+
* 3. keep the claims in `resource.meta.claims`
|
|
85
|
+
* 4. append the entry to a `Bundle.data` array
|
|
86
|
+
*/
|
|
87
|
+
export function buildVitalSignObservationEntry(input) {
|
|
88
|
+
const claims = buildVitalSignObservationClaims(input);
|
|
89
|
+
const flatClaims = toFlatClaims(claims);
|
|
90
|
+
const resource = observationFromFlatToFhirR4(flatClaims);
|
|
91
|
+
return {
|
|
92
|
+
id: String(claims['Observation.identifier'] || input.identifier),
|
|
93
|
+
fullUrl: resolveObservationEntryFullUrl(String(claims['Observation.identifier'] || input.identifier)),
|
|
94
|
+
type: `${ResourceTypesFhirR4.Observation}-entry-v1.0`,
|
|
95
|
+
resource: {
|
|
96
|
+
...resource,
|
|
97
|
+
meta: {
|
|
98
|
+
...(resource.meta || {}),
|
|
99
|
+
claims: flatClaims,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Builds a high-level bundle with one entry per directly authored vital sign.
|
|
106
|
+
*
|
|
107
|
+
* Included examples:
|
|
108
|
+
* - heart rate
|
|
109
|
+
* - body temperature
|
|
110
|
+
* - systolic blood pressure
|
|
111
|
+
* - diastolic blood pressure
|
|
112
|
+
*
|
|
113
|
+
* Panels are intentionally excluded because the app user normally authors
|
|
114
|
+
* simple observations, not professional/imported panel structures.
|
|
115
|
+
*/
|
|
116
|
+
export function buildExampleVitalSignsObservationBundle() {
|
|
117
|
+
return {
|
|
118
|
+
resourceType: 'Bundle',
|
|
119
|
+
type: 'collection',
|
|
120
|
+
data: [
|
|
121
|
+
buildVitalSignObservationEntry(EXAMPLE_VITAL_SIGN_HEART_RATE_INPUT),
|
|
122
|
+
buildVitalSignObservationEntry(EXAMPLE_VITAL_SIGN_BODY_TEMPERATURE_INPUT),
|
|
123
|
+
buildVitalSignObservationEntry(EXAMPLE_VITAL_SIGN_SYSTOLIC_BLOOD_PRESSURE_INPUT),
|
|
124
|
+
buildVitalSignObservationEntry(EXAMPLE_VITAL_SIGN_DIASTOLIC_BLOOD_PRESSURE_INPUT),
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Builds the same vital-sign bundle through `CommunicationAttachedBundleSession`
|
|
130
|
+
* for flows that already use the in-memory bundle editor/session abstraction.
|
|
131
|
+
*/
|
|
132
|
+
export function buildExampleVitalSignsObservationBundleSession() {
|
|
133
|
+
const session = new CommunicationAttachedBundleSession({
|
|
134
|
+
communicationClaims: {
|
|
135
|
+
'@context': Format.FHIR_API,
|
|
136
|
+
[CommunicationClaim.Identifier]: EXAMPLE_COMMUNICATION_IDENTIFIER,
|
|
137
|
+
[CommunicationClaim.Subject]: EXAMPLE_SUBJECT_DID,
|
|
138
|
+
[CommunicationClaim.Text]: EXAMPLE_VITAL_SIGN_DISPLAY_VITAL_SIGNS,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
const inputs = [
|
|
142
|
+
EXAMPLE_VITAL_SIGN_HEART_RATE_INPUT,
|
|
143
|
+
EXAMPLE_VITAL_SIGN_BODY_TEMPERATURE_INPUT,
|
|
144
|
+
EXAMPLE_VITAL_SIGN_SYSTOLIC_BLOOD_PRESSURE_INPUT,
|
|
145
|
+
EXAMPLE_VITAL_SIGN_DIASTOLIC_BLOOD_PRESSURE_INPUT,
|
|
146
|
+
];
|
|
147
|
+
for (const input of inputs) {
|
|
148
|
+
session.upsertActiveObservationEntry({
|
|
149
|
+
claims: buildVitalSignObservationClaims({
|
|
150
|
+
...input,
|
|
151
|
+
note: EXAMPLE_VITAL_SIGNS_NOTE,
|
|
152
|
+
}),
|
|
153
|
+
fullUrl: resolveObservationEntryFullUrl(input.identifier),
|
|
154
|
+
type: `${ResourceTypesFhirR4.Observation}-entry-v1.0`,
|
|
155
|
+
});
|
|
156
|
+
session.saveAndReleaseActiveEntry();
|
|
157
|
+
}
|
|
158
|
+
return session.getBundleInMemory();
|
|
159
|
+
}
|
|
@@ -23,6 +23,10 @@ export type FhirAttachment = {
|
|
|
23
23
|
url?: string;
|
|
24
24
|
title?: string;
|
|
25
25
|
creation?: string;
|
|
26
|
+
hash?: string;
|
|
27
|
+
};
|
|
28
|
+
export type FhirMeta = {
|
|
29
|
+
claims?: Record<string, unknown>;
|
|
26
30
|
};
|
|
27
31
|
export interface FhirCompositionResource {
|
|
28
32
|
resourceType: 'Composition';
|
|
@@ -46,6 +50,7 @@ export interface FhirCompositionResource {
|
|
|
46
50
|
export interface FhirDocumentReferenceResource {
|
|
47
51
|
resourceType: 'DocumentReference';
|
|
48
52
|
id?: string;
|
|
53
|
+
meta?: FhirMeta;
|
|
49
54
|
status?: string;
|
|
50
55
|
identifier?: Array<{
|
|
51
56
|
system?: string;
|
|
@@ -81,9 +86,39 @@ export interface FhirDocumentReferenceResource {
|
|
|
81
86
|
format?: FhirCoding;
|
|
82
87
|
}>;
|
|
83
88
|
}
|
|
89
|
+
export interface FhirInvoiceResource {
|
|
90
|
+
resourceType: 'Invoice';
|
|
91
|
+
id?: string;
|
|
92
|
+
meta?: FhirMeta;
|
|
93
|
+
status?: string;
|
|
94
|
+
identifier?: Array<{
|
|
95
|
+
system?: string;
|
|
96
|
+
value?: string;
|
|
97
|
+
}>;
|
|
98
|
+
subject?: FhirReference;
|
|
99
|
+
recipient?: FhirReference;
|
|
100
|
+
issuer?: {
|
|
101
|
+
reference?: string;
|
|
102
|
+
display?: string;
|
|
103
|
+
};
|
|
104
|
+
date?: string;
|
|
105
|
+
paymentTerms?: string;
|
|
106
|
+
note?: Array<{
|
|
107
|
+
text?: string;
|
|
108
|
+
}>;
|
|
109
|
+
totalNet?: {
|
|
110
|
+
value?: number;
|
|
111
|
+
currency?: string;
|
|
112
|
+
};
|
|
113
|
+
totalGross?: {
|
|
114
|
+
value?: number;
|
|
115
|
+
currency?: string;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
84
118
|
export interface FhirCommunicationResource {
|
|
85
119
|
resourceType: 'Communication';
|
|
86
120
|
id?: string;
|
|
121
|
+
meta?: FhirMeta;
|
|
87
122
|
status?: string;
|
|
88
123
|
category?: FhirCodeableConcept[];
|
|
89
124
|
subject?: FhirReference;
|
|
@@ -1,11 +1,73 @@
|
|
|
1
|
-
import { ClaimsOrganizationSchemaorg } from
|
|
1
|
+
import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg';
|
|
2
|
+
import type { ParameterData } from './params';
|
|
3
|
+
/**
|
|
4
|
+
* Canonical index profile names used under each resource type.
|
|
5
|
+
*/
|
|
6
|
+
export declare const IndexingClaimSet: Readonly<{
|
|
7
|
+
readonly General: "General";
|
|
8
|
+
readonly Registry: "Registry";
|
|
9
|
+
readonly VitalSigns: "VitalSigns";
|
|
10
|
+
}>;
|
|
11
|
+
export type IndexingClaimSetKey = typeof IndexingClaimSet[keyof typeof IndexingClaimSet];
|
|
2
12
|
/**
|
|
3
13
|
* Defines which claims are allowed to be indexed for different resource types.
|
|
4
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* Preferred shape:
|
|
16
|
+
* `AllowedIndexableClaims[ResourceType][General/category/type]`
|
|
5
17
|
*/
|
|
6
18
|
export declare const AllowedIndexableClaims: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
readonly Organization: {
|
|
20
|
+
/**
|
|
21
|
+
* Claims that can be indexed in the central tenant registry for an Organization.
|
|
22
|
+
*/
|
|
23
|
+
readonly Registry: readonly [ClaimsOrganizationSchemaorg.alternateName, ClaimsOrganizationSchemaorg.identifierValue, ClaimsOrganizationSchemaorg.identifierType, ClaimsOrganizationSchemaorg.addressCountry];
|
|
24
|
+
};
|
|
25
|
+
readonly Observation: {
|
|
26
|
+
/**
|
|
27
|
+
* Searchable/indexable subset for a general Observation row.
|
|
28
|
+
*
|
|
29
|
+
* Keep this aligned with GW managers that build `indexed.attributes` from
|
|
30
|
+
* claims-first payloads. UI-only or long free-text fields stay out.
|
|
31
|
+
*/
|
|
32
|
+
readonly General: readonly ["Observation.identifier", "Observation.subject", "Observation.patient", "Observation.status", "Observation.category", "Observation.code-system", "Observation.code-value", "Observation.code", "Observation.date", "Observation.effectiveDateTime", "Observation.value-concept-system", "Observation.value-concept-value", "Observation.value-concept", "Observation.value-date", "Observation.value-quantity-comparator", "Observation.value-quantity-number", "Observation.value-quantity-unit", "Observation.score-total-number", "Observation.component-tags", "Observation.component-code-values", "Observation.component-names", "Observation.bp-systolic-number", "Observation.bp-diastolic-number", "Observation.has-member", "Observation.encounter", "Observation.device", "Observation.specimen", "Observation.performer", "Observation.based-on", "Observation.focus", "Observation.method", "Observation.language"];
|
|
33
|
+
/**
|
|
34
|
+
* Searchable/indexable subset for a Vital Signs Observation row.
|
|
35
|
+
*
|
|
36
|
+
* This is intentionally narrower than the full persisted claims list and
|
|
37
|
+
* excludes local-language labels, XHTML/narrative, and note text.
|
|
38
|
+
*/
|
|
39
|
+
readonly VitalSigns: readonly ["Observation.identifier", "Observation.subject", "Observation.patient", "Observation.status", "Observation.category", "Observation.code-system", "Observation.code-value", "Observation.code", "Observation.date", "Observation.effectiveDateTime", "Observation.value-concept-system", "Observation.value-concept-value", "Observation.value-concept", "Observation.value-date", "Observation.value-quantity-comparator", "Observation.value-quantity-number", "Observation.value-quantity-unit", "Observation.score-total-number", "Observation.component-tags", "Observation.component-code-values", "Observation.component-names", "Observation.bp-systolic-number", "Observation.bp-diastolic-number", "Observation.has-member", "Observation.method", "Observation.language"];
|
|
40
|
+
};
|
|
41
|
+
readonly Condition: {
|
|
42
|
+
readonly General: readonly ["Condition.identifier", "Condition.subject", "Condition.clinical-status", "Condition.verification-status", "Condition.category", "Condition.code", "Condition.severity", "Condition.onset-datetime", "Condition.recorder"];
|
|
43
|
+
};
|
|
44
|
+
readonly MedicationStatement: {
|
|
45
|
+
readonly General: readonly ["MedicationStatement.identifier", "MedicationStatement.subject", "MedicationStatement.patient", "MedicationStatement.status", "MedicationStatement.category", "MedicationStatement.effective", "MedicationStatement.code", "MedicationStatement.medication", "MedicationStatement.part-of", "MedicationStatement.source", "MedicationStatement.medication-identifier", "MedicationStatement.medication-serial-number", "MedicationStatement.medication-expiration-date"];
|
|
46
|
+
};
|
|
47
|
+
readonly DocumentReference: {
|
|
48
|
+
readonly General: readonly ["DocumentReference.identifier", "DocumentReference.subject", "DocumentReference.author", "DocumentReference.attester", "DocumentReference.basedOn", "DocumentReference.category", "DocumentReference.contenthash", "DocumentReference.contenttype", "DocumentReference.context", "DocumentReference.creation", "DocumentReference.date", "DocumentReference.event-code", "DocumentReference.event-reference", "DocumentReference.format-uri", "DocumentReference.language", "DocumentReference.location", "DocumentReference.modality", "DocumentReference.relatesto", "DocumentReference.relation", "DocumentReference.type"];
|
|
49
|
+
};
|
|
11
50
|
};
|
|
51
|
+
export type AllowedIndexableClaimsKey = keyof typeof AllowedIndexableClaims;
|
|
52
|
+
/**
|
|
53
|
+
* Deprecated compatibility aliases.
|
|
54
|
+
*
|
|
55
|
+
* Prefer `AllowedIndexableClaims[ResourceTypesFhirR4.Observation].General`,
|
|
56
|
+
* `AllowedIndexableClaims[ResourceTypesFhirR4.Observation].VitalSigns`, and
|
|
57
|
+
* `AllowedIndexableClaims.Organization.Registry` in new code.
|
|
58
|
+
*/
|
|
59
|
+
export declare const AllowedIndexableClaimAliases: Readonly<{
|
|
60
|
+
readonly organizationRegistry: readonly [ClaimsOrganizationSchemaorg.alternateName, ClaimsOrganizationSchemaorg.identifierValue, ClaimsOrganizationSchemaorg.identifierType, ClaimsOrganizationSchemaorg.addressCountry];
|
|
61
|
+
readonly observationGeneral: readonly ["Observation.identifier", "Observation.subject", "Observation.patient", "Observation.status", "Observation.category", "Observation.code-system", "Observation.code-value", "Observation.code", "Observation.date", "Observation.effectiveDateTime", "Observation.value-concept-system", "Observation.value-concept-value", "Observation.value-concept", "Observation.value-date", "Observation.value-quantity-comparator", "Observation.value-quantity-number", "Observation.value-quantity-unit", "Observation.score-total-number", "Observation.component-tags", "Observation.component-code-values", "Observation.component-names", "Observation.bp-systolic-number", "Observation.bp-diastolic-number", "Observation.has-member", "Observation.encounter", "Observation.device", "Observation.specimen", "Observation.performer", "Observation.based-on", "Observation.focus", "Observation.method", "Observation.language"];
|
|
62
|
+
readonly observationVitalSigns: readonly ["Observation.identifier", "Observation.subject", "Observation.patient", "Observation.status", "Observation.category", "Observation.code-system", "Observation.code-value", "Observation.code", "Observation.date", "Observation.effectiveDateTime", "Observation.value-concept-system", "Observation.value-concept-value", "Observation.value-concept", "Observation.value-date", "Observation.value-quantity-comparator", "Observation.value-quantity-number", "Observation.value-quantity-unit", "Observation.score-total-number", "Observation.component-tags", "Observation.component-code-values", "Observation.component-names", "Observation.bp-systolic-number", "Observation.bp-diastolic-number", "Observation.has-member", "Observation.method", "Observation.language"];
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Projects a claims-first record to the `ParameterData[]` shape used by GW/KMS
|
|
66
|
+
* before optional HMAC protection.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildIndexParametersFromClaims(claims: Record<string, unknown>, allowedClaims: readonly string[]): ParameterData[];
|
|
69
|
+
/**
|
|
70
|
+
* Sanity guard to keep the indexable subset anchored to the broader claims
|
|
71
|
+
* lists declared by the interoperable-claims contract.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isAllowedObservationIndexableClaim(claimKey: string, variant: 'general' | 'vital-signs'): boolean;
|
package/dist/models/indexing.js
CHANGED
|
@@ -1,18 +1,301 @@
|
|
|
1
1
|
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
// File: src/models/indexing.ts
|
|
3
|
-
import {
|
|
3
|
+
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
4
|
+
import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg.js';
|
|
5
|
+
import { ConditionClaim } from './interoperable-claims/condition-claims.js';
|
|
6
|
+
import { DocumentReferenceClaim } from './interoperable-claims/document-reference-claims.js';
|
|
7
|
+
import { MedicationStatementClaim } from './interoperable-claims/medication-statement-claims.js';
|
|
8
|
+
import { ObservationClaim, ObservationGeneralClaimsList, ObservationVitalSignsClaimsList, } from './interoperable-claims/observation-claims.js';
|
|
9
|
+
/**
|
|
10
|
+
* Canonical index profile names used under each resource type.
|
|
11
|
+
*/
|
|
12
|
+
export const IndexingClaimSet = Object.freeze({
|
|
13
|
+
General: 'General',
|
|
14
|
+
Registry: 'Registry',
|
|
15
|
+
VitalSigns: 'VitalSigns',
|
|
16
|
+
});
|
|
4
17
|
/**
|
|
5
18
|
* Defines which claims are allowed to be indexed for different resource types.
|
|
6
|
-
*
|
|
19
|
+
*
|
|
20
|
+
* Preferred shape:
|
|
21
|
+
* `AllowedIndexableClaims[ResourceType][General/category/type]`
|
|
7
22
|
*/
|
|
8
23
|
export const AllowedIndexableClaims = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
Organization: {
|
|
25
|
+
/**
|
|
26
|
+
* Claims that can be indexed in the central tenant registry for an Organization.
|
|
27
|
+
*/
|
|
28
|
+
[IndexingClaimSet.Registry]: [
|
|
29
|
+
ClaimsOrganizationSchemaorg.alternateName,
|
|
30
|
+
ClaimsOrganizationSchemaorg.identifierValue,
|
|
31
|
+
ClaimsOrganizationSchemaorg.identifierType,
|
|
32
|
+
ClaimsOrganizationSchemaorg.addressCountry,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
[ResourceTypesFhirR4.Observation]: {
|
|
36
|
+
/**
|
|
37
|
+
* Searchable/indexable subset for a general Observation row.
|
|
38
|
+
*
|
|
39
|
+
* Keep this aligned with GW managers that build `indexed.attributes` from
|
|
40
|
+
* claims-first payloads. UI-only or long free-text fields stay out.
|
|
41
|
+
*/
|
|
42
|
+
[IndexingClaimSet.General]: [
|
|
43
|
+
ObservationClaim.Identifier,
|
|
44
|
+
ObservationClaim.Subject,
|
|
45
|
+
ObservationClaim.Patient,
|
|
46
|
+
ObservationClaim.Status,
|
|
47
|
+
ObservationClaim.Category,
|
|
48
|
+
ObservationClaim.CodeSystem,
|
|
49
|
+
ObservationClaim.CodeValue,
|
|
50
|
+
ObservationClaim.Code,
|
|
51
|
+
ObservationClaim.Date,
|
|
52
|
+
ObservationClaim.EffectiveDateTime,
|
|
53
|
+
ObservationClaim.ValueConceptSystem,
|
|
54
|
+
ObservationClaim.ValueConceptValue,
|
|
55
|
+
ObservationClaim.ValueConcept,
|
|
56
|
+
ObservationClaim.ValueDate,
|
|
57
|
+
ObservationClaim.ValueQuantityComparator,
|
|
58
|
+
ObservationClaim.ValueQuantityNumber,
|
|
59
|
+
ObservationClaim.ValueQuantityUnit,
|
|
60
|
+
ObservationClaim.ScoreTotalNumber,
|
|
61
|
+
ObservationClaim.ComponentTags,
|
|
62
|
+
ObservationClaim.ComponentCodeValues,
|
|
63
|
+
ObservationClaim.ComponentNames,
|
|
64
|
+
ObservationClaim.BloodPressureSystolicNumber,
|
|
65
|
+
ObservationClaim.BloodPressureDiastolicNumber,
|
|
66
|
+
ObservationClaim.HasMember,
|
|
67
|
+
ObservationClaim.Encounter,
|
|
68
|
+
ObservationClaim.Device,
|
|
69
|
+
ObservationClaim.Specimen,
|
|
70
|
+
ObservationClaim.Performer,
|
|
71
|
+
ObservationClaim.BasedOn,
|
|
72
|
+
ObservationClaim.Focus,
|
|
73
|
+
ObservationClaim.Method,
|
|
74
|
+
ObservationClaim.Language,
|
|
75
|
+
],
|
|
76
|
+
/**
|
|
77
|
+
* Searchable/indexable subset for a Vital Signs Observation row.
|
|
78
|
+
*
|
|
79
|
+
* This is intentionally narrower than the full persisted claims list and
|
|
80
|
+
* excludes local-language labels, XHTML/narrative, and note text.
|
|
81
|
+
*/
|
|
82
|
+
[IndexingClaimSet.VitalSigns]: [
|
|
83
|
+
ObservationClaim.Identifier,
|
|
84
|
+
ObservationClaim.Subject,
|
|
85
|
+
ObservationClaim.Patient,
|
|
86
|
+
ObservationClaim.Status,
|
|
87
|
+
ObservationClaim.Category,
|
|
88
|
+
ObservationClaim.CodeSystem,
|
|
89
|
+
ObservationClaim.CodeValue,
|
|
90
|
+
ObservationClaim.Code,
|
|
91
|
+
ObservationClaim.Date,
|
|
92
|
+
ObservationClaim.EffectiveDateTime,
|
|
93
|
+
ObservationClaim.ValueConceptSystem,
|
|
94
|
+
ObservationClaim.ValueConceptValue,
|
|
95
|
+
ObservationClaim.ValueConcept,
|
|
96
|
+
ObservationClaim.ValueDate,
|
|
97
|
+
ObservationClaim.ValueQuantityComparator,
|
|
98
|
+
ObservationClaim.ValueQuantityNumber,
|
|
99
|
+
ObservationClaim.ValueQuantityUnit,
|
|
100
|
+
ObservationClaim.ScoreTotalNumber,
|
|
101
|
+
ObservationClaim.ComponentTags,
|
|
102
|
+
ObservationClaim.ComponentCodeValues,
|
|
103
|
+
ObservationClaim.ComponentNames,
|
|
104
|
+
ObservationClaim.BloodPressureSystolicNumber,
|
|
105
|
+
ObservationClaim.BloodPressureDiastolicNumber,
|
|
106
|
+
ObservationClaim.HasMember,
|
|
107
|
+
ObservationClaim.Method,
|
|
108
|
+
ObservationClaim.Language,
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
[ResourceTypesFhirR4.Condition]: {
|
|
112
|
+
[IndexingClaimSet.General]: [
|
|
113
|
+
ConditionClaim.Identifier,
|
|
114
|
+
ConditionClaim.Subject,
|
|
115
|
+
ConditionClaim.ClinicalStatus,
|
|
116
|
+
ConditionClaim.VerificationStatus,
|
|
117
|
+
ConditionClaim.Category,
|
|
118
|
+
ConditionClaim.Code,
|
|
119
|
+
ConditionClaim.Severity,
|
|
120
|
+
ConditionClaim.OnsetDateTime,
|
|
121
|
+
ConditionClaim.Recorder,
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
[ResourceTypesFhirR4.MedicationStatement]: {
|
|
125
|
+
[IndexingClaimSet.General]: [
|
|
126
|
+
MedicationStatementClaim.Identifier,
|
|
127
|
+
MedicationStatementClaim.Subject,
|
|
128
|
+
MedicationStatementClaim.Patient,
|
|
129
|
+
MedicationStatementClaim.Status,
|
|
130
|
+
MedicationStatementClaim.Category,
|
|
131
|
+
MedicationStatementClaim.Effective,
|
|
132
|
+
MedicationStatementClaim.Code,
|
|
133
|
+
MedicationStatementClaim.Medication,
|
|
134
|
+
MedicationStatementClaim.PartOf,
|
|
135
|
+
MedicationStatementClaim.Source,
|
|
136
|
+
MedicationStatementClaim.MedicationIdentifier,
|
|
137
|
+
MedicationStatementClaim.MedicationSerialNumber,
|
|
138
|
+
MedicationStatementClaim.MedicationExpirationDate,
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
[ResourceTypesFhirR4.DocumentReference]: {
|
|
142
|
+
[IndexingClaimSet.General]: [
|
|
143
|
+
DocumentReferenceClaim.Identifier,
|
|
144
|
+
DocumentReferenceClaim.Subject,
|
|
145
|
+
DocumentReferenceClaim.Author,
|
|
146
|
+
DocumentReferenceClaim.Attester,
|
|
147
|
+
DocumentReferenceClaim.BasedOn,
|
|
148
|
+
DocumentReferenceClaim.Category,
|
|
149
|
+
DocumentReferenceClaim.ContentHash,
|
|
150
|
+
DocumentReferenceClaim.ContentType,
|
|
151
|
+
DocumentReferenceClaim.Context,
|
|
152
|
+
DocumentReferenceClaim.Creation,
|
|
153
|
+
DocumentReferenceClaim.Date,
|
|
154
|
+
DocumentReferenceClaim.EventCode,
|
|
155
|
+
DocumentReferenceClaim.EventReference,
|
|
156
|
+
DocumentReferenceClaim.FormatUri,
|
|
157
|
+
DocumentReferenceClaim.Language,
|
|
158
|
+
DocumentReferenceClaim.Location,
|
|
159
|
+
DocumentReferenceClaim.Modality,
|
|
160
|
+
DocumentReferenceClaim.RelatesTo,
|
|
161
|
+
DocumentReferenceClaim.Relation,
|
|
162
|
+
DocumentReferenceClaim.Type,
|
|
163
|
+
],
|
|
164
|
+
},
|
|
18
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Deprecated compatibility aliases.
|
|
168
|
+
*
|
|
169
|
+
* Prefer `AllowedIndexableClaims[ResourceTypesFhirR4.Observation].General`,
|
|
170
|
+
* `AllowedIndexableClaims[ResourceTypesFhirR4.Observation].VitalSigns`, and
|
|
171
|
+
* `AllowedIndexableClaims.Organization.Registry` in new code.
|
|
172
|
+
*/
|
|
173
|
+
export const AllowedIndexableClaimAliases = Object.freeze({
|
|
174
|
+
organizationRegistry: AllowedIndexableClaims.Organization.Registry,
|
|
175
|
+
observationGeneral: AllowedIndexableClaims[ResourceTypesFhirR4.Observation][IndexingClaimSet.General],
|
|
176
|
+
observationVitalSigns: AllowedIndexableClaims[ResourceTypesFhirR4.Observation][IndexingClaimSet.VitalSigns],
|
|
177
|
+
});
|
|
178
|
+
/**
|
|
179
|
+
* Projects a claims-first record to the `ParameterData[]` shape used by GW/KMS
|
|
180
|
+
* before optional HMAC protection.
|
|
181
|
+
*/
|
|
182
|
+
export function buildIndexParametersFromClaims(claims, allowedClaims) {
|
|
183
|
+
const parameters = [];
|
|
184
|
+
for (const claimKey of allowedClaims) {
|
|
185
|
+
const rawValue = claims[claimKey];
|
|
186
|
+
if (rawValue === undefined || rawValue === null || rawValue === '') {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const value = typeof rawValue === 'number' ? rawValue : String(rawValue).trim();
|
|
190
|
+
if (value === '') {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const parameter = {
|
|
194
|
+
name: claimKey,
|
|
195
|
+
value: value,
|
|
196
|
+
type: inferParameterTypeFromClaimKey(claimKey, rawValue),
|
|
197
|
+
...(claimKey === ObservationClaim.ValueQuantityUnit && typeof rawValue === 'string'
|
|
198
|
+
? { unit: rawValue }
|
|
199
|
+
: {}),
|
|
200
|
+
};
|
|
201
|
+
parameters.push(parameter);
|
|
202
|
+
}
|
|
203
|
+
return parameters;
|
|
204
|
+
}
|
|
205
|
+
function inferParameterTypeFromClaimKey(claimKey, rawValue) {
|
|
206
|
+
if (claimKey === ObservationClaim.ValueQuantityNumber
|
|
207
|
+
|| claimKey === ObservationClaim.ScoreTotalNumber
|
|
208
|
+
|| claimKey === ObservationClaim.BloodPressureSystolicNumber
|
|
209
|
+
|| claimKey === ObservationClaim.BloodPressureDiastolicNumber) {
|
|
210
|
+
return 'number';
|
|
211
|
+
}
|
|
212
|
+
if (claimKey === ObservationClaim.Date
|
|
213
|
+
|| claimKey === ObservationClaim.EffectiveDateTime
|
|
214
|
+
|| claimKey === ObservationClaim.ValueDate
|
|
215
|
+
|| claimKey === ConditionClaim.OnsetDateTime
|
|
216
|
+
|| claimKey === MedicationStatementClaim.Effective
|
|
217
|
+
|| claimKey === MedicationStatementClaim.MedicationExpirationDate
|
|
218
|
+
|| claimKey === DocumentReferenceClaim.Creation
|
|
219
|
+
|| claimKey === DocumentReferenceClaim.Date) {
|
|
220
|
+
return 'date';
|
|
221
|
+
}
|
|
222
|
+
if (claimKey === ObservationClaim.Subject
|
|
223
|
+
|| claimKey === ObservationClaim.Patient
|
|
224
|
+
|| claimKey === ObservationClaim.Encounter
|
|
225
|
+
|| claimKey === ObservationClaim.Device
|
|
226
|
+
|| claimKey === ObservationClaim.Specimen
|
|
227
|
+
|| claimKey === ObservationClaim.Performer
|
|
228
|
+
|| claimKey === ObservationClaim.BasedOn
|
|
229
|
+
|| claimKey === ObservationClaim.Focus
|
|
230
|
+
|| claimKey === ObservationClaim.HasMember
|
|
231
|
+
|| claimKey === ConditionClaim.Subject
|
|
232
|
+
|| claimKey === ConditionClaim.Recorder
|
|
233
|
+
|| claimKey === MedicationStatementClaim.Subject
|
|
234
|
+
|| claimKey === MedicationStatementClaim.Patient
|
|
235
|
+
|| claimKey === MedicationStatementClaim.PartOf
|
|
236
|
+
|| claimKey === MedicationStatementClaim.Source
|
|
237
|
+
|| claimKey === DocumentReferenceClaim.Subject
|
|
238
|
+
|| claimKey === DocumentReferenceClaim.Author
|
|
239
|
+
|| claimKey === DocumentReferenceClaim.Attester
|
|
240
|
+
|| claimKey === DocumentReferenceClaim.BasedOn
|
|
241
|
+
|| claimKey === DocumentReferenceClaim.Context
|
|
242
|
+
|| claimKey === DocumentReferenceClaim.EventReference
|
|
243
|
+
|| claimKey === DocumentReferenceClaim.RelatesTo) {
|
|
244
|
+
return 'reference';
|
|
245
|
+
}
|
|
246
|
+
if (claimKey === ObservationClaim.Category
|
|
247
|
+
|| claimKey === ObservationClaim.ComponentTags
|
|
248
|
+
|| claimKey === ObservationClaim.ComponentCodeValues
|
|
249
|
+
|| claimKey === ObservationClaim.CodeSystem
|
|
250
|
+
|| claimKey === ObservationClaim.CodeValue
|
|
251
|
+
|| claimKey === ObservationClaim.Code
|
|
252
|
+
|| claimKey === ObservationClaim.ValueConceptSystem
|
|
253
|
+
|| claimKey === ObservationClaim.ValueConceptValue
|
|
254
|
+
|| claimKey === ObservationClaim.ValueConcept
|
|
255
|
+
|| claimKey === ObservationClaim.Method
|
|
256
|
+
|| claimKey === ObservationClaim.Language
|
|
257
|
+
|| claimKey === ObservationClaim.ValueQuantityComparator
|
|
258
|
+
|| claimKey === ObservationClaim.ValueQuantityUnit
|
|
259
|
+
|| claimKey === ConditionClaim.ClinicalStatus
|
|
260
|
+
|| claimKey === ConditionClaim.VerificationStatus
|
|
261
|
+
|| claimKey === ConditionClaim.Category
|
|
262
|
+
|| claimKey === ConditionClaim.Code
|
|
263
|
+
|| claimKey === ConditionClaim.Severity
|
|
264
|
+
|| claimKey === MedicationStatementClaim.Status
|
|
265
|
+
|| claimKey === MedicationStatementClaim.Category
|
|
266
|
+
|| claimKey === MedicationStatementClaim.Code
|
|
267
|
+
|| claimKey === MedicationStatementClaim.Medication
|
|
268
|
+
|| claimKey === DocumentReferenceClaim.Category
|
|
269
|
+
|| claimKey === DocumentReferenceClaim.ContentType
|
|
270
|
+
|| claimKey === DocumentReferenceClaim.EventCode
|
|
271
|
+
|| claimKey === DocumentReferenceClaim.FormatUri
|
|
272
|
+
|| claimKey === DocumentReferenceClaim.Language
|
|
273
|
+
|| claimKey === DocumentReferenceClaim.Modality
|
|
274
|
+
|| claimKey === DocumentReferenceClaim.Relation
|
|
275
|
+
|| claimKey === DocumentReferenceClaim.Type) {
|
|
276
|
+
return 'token';
|
|
277
|
+
}
|
|
278
|
+
if (claimKey === ObservationClaim.ComponentNames) {
|
|
279
|
+
return 'string';
|
|
280
|
+
}
|
|
281
|
+
if ((claimKey === ObservationClaim.Identifier
|
|
282
|
+
|| claimKey === ConditionClaim.Identifier
|
|
283
|
+
|| claimKey === MedicationStatementClaim.Identifier
|
|
284
|
+
|| claimKey === DocumentReferenceClaim.Identifier)
|
|
285
|
+
&& typeof rawValue === 'string'
|
|
286
|
+
&& /^urn:|^did:|^https?:/i.test(rawValue)) {
|
|
287
|
+
return 'uri';
|
|
288
|
+
}
|
|
289
|
+
return 'string';
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Sanity guard to keep the indexable subset anchored to the broader claims
|
|
293
|
+
* lists declared by the interoperable-claims contract.
|
|
294
|
+
*/
|
|
295
|
+
export function isAllowedObservationIndexableClaim(claimKey, variant) {
|
|
296
|
+
const fullList = variant === 'general' ? ObservationGeneralClaimsList : ObservationVitalSignsClaimsList;
|
|
297
|
+
const allowed = variant === 'general'
|
|
298
|
+
? AllowedIndexableClaims[ResourceTypesFhirR4.Observation][IndexingClaimSet.General]
|
|
299
|
+
: AllowedIndexableClaims[ResourceTypesFhirR4.Observation][IndexingClaimSet.VitalSigns];
|
|
300
|
+
return fullList.some((item) => item === claimKey) && allowed.some((item) => item === claimKey);
|
|
301
|
+
}
|