gdc-common-utils-ts 2.3.26 → 2.3.27
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 +5 -0
- package/dist/convert/convert-care-plan.js +25 -1
- package/dist/convert/convert-condition.js +12 -0
- package/dist/convert/convert-consent.js +59 -13
- package/dist/convert/convert-device-use-statement.js +3 -1
- package/dist/convert/convert-immunization.js +12 -2
- package/dist/convert/convert-medication-statement.js +35 -1
- package/dist/convert/convert-observation.js +43 -2
- package/dist/convert/convert-practitioner-role.d.ts +1 -1
- package/dist/convert/convert-practitioner-role.js +41 -13
- package/dist/convert/convert-shared.js +1 -1
- package/dist/models/consent-rule.d.ts +7 -0
- package/dist/models/consent-rule.js +7 -0
- package/dist/models/indexing.d.ts +4 -4
- package/dist/models/interoperable-claims/appointment-claims.d.ts +54 -54
- package/dist/models/interoperable-claims/appointment-claims.js +28 -29
- package/dist/models/interoperable-claims/appointment-response-claims.d.ts +11 -11
- package/dist/models/interoperable-claims/appointment-response-claims.js +11 -11
- package/dist/models/interoperable-claims/care-plan-claims.d.ts +11 -0
- package/dist/models/interoperable-claims/care-plan-claims.js +11 -0
- package/dist/models/interoperable-claims/condition-claims.d.ts +2 -0
- package/dist/models/interoperable-claims/condition-claims.js +2 -0
- package/dist/models/interoperable-claims/device-use-statement-claims.d.ts +3 -2
- package/dist/models/interoperable-claims/device-use-statement-claims.js +3 -2
- package/dist/models/interoperable-claims/immunization-claims.d.ts +4 -0
- package/dist/models/interoperable-claims/immunization-claims.js +4 -0
- package/dist/models/interoperable-claims/medication-statement-claims.d.ts +6 -0
- package/dist/models/interoperable-claims/medication-statement-claims.js +6 -0
- package/dist/models/interoperable-claims/observation-claims.d.ts +12 -4
- package/dist/models/interoperable-claims/observation-claims.js +10 -2
- package/dist/models/interoperable-claims/practitioner-role-claims.d.ts +9 -0
- package/dist/models/interoperable-claims/practitioner-role-claims.js +9 -0
- package/dist/models/params.d.ts +1 -1
- package/dist/utils/bundle-document-builder.js +37 -16
- package/dist/utils/bundle-entry-editor.d.ts +13 -0
- package/dist/utils/bundle-entry-editor.js +18 -0
- package/dist/utils/clinical-resource-converters.js +6 -4
- package/dist/utils/clinical-resource-view.d.ts +55 -0
- package/dist/utils/clinical-resource-view.js +137 -1
- package/dist/utils/communication-bundle-document-request.js +1 -1
- package/dist/utils/communication-fhir-r4.js +1 -1
- package/dist/utils/fhir-api-claim-helpers.d.ts +2 -0
- package/dist/utils/fhir-api-claim-helpers.js +16 -0
- package/dist/utils/ips-bundle-claims.d.ts +3 -4
- package/dist/utils/ips-bundle-claims.js +7 -7
- package/dist/utils/medication-statement-entry-editor.js +10 -10
- package/dist/utils/observation-component-entry-editor.d.ts +2 -2
- package/dist/utils/observation-component-entry-editor.js +2 -2
- package/package.json +1 -1
|
@@ -5,7 +5,9 @@ import { ConditionClaim } from '../models/interoperable-claims/condition-claims.
|
|
|
5
5
|
import { DiagnosticReportClaim } from '../models/interoperable-claims/diagnostic-report-claims.js';
|
|
6
6
|
import { MedicationStatementClaim } from '../models/interoperable-claims/medication-statement-claims.js';
|
|
7
7
|
import { ClaimConsent } from '../models/consent-rule.js';
|
|
8
|
-
import { allergyIntoleranceFlatToFhirR4, appointmentFlatToFhirR4, carePlanFlatToFhirR4, clinicalImpressionFlatToFhirR4, compositionFlatToFhirR4, conditionFlatToFhirR4, consentFlatToFhirR4, convertFhirResourceToClaims, coverageFlatToFhirR4, deviceFlatToFhirR4, documentReferenceFlatToFhirR4, diagnosticReportFlatToFhirR4, encounterFlatToFhirR4, flagFlatToFhirR4, flatClaimsToFhirResource, immunizationFlatToFhirR4, locationFlatToFhirR4, medicationStatementFlatToFhirR4, observationFromFlatToFhirR4, organizationFlatToFhirR4, procedureFlatToFhirR4, practitionerRoleFlatToFhirR4, relatedPersonFlatToFhirR4, } from './clinical-resource-converters.js';
|
|
8
|
+
import { allergyIntoleranceFlatToFhirR4, appointmentResponseFlatToFhirR4, appointmentFlatToFhirR4, carePlanFlatToFhirR4, clinicalImpressionFlatToFhirR4, compositionFlatToFhirR4, conditionFlatToFhirR4, consentFlatToFhirR4, convertFhirResourceToClaims, coverageFlatToFhirR4, deviceFlatToFhirR4, deviceUseStatementFlatToFhirR4, documentReferenceFlatToFhirR4, diagnosticReportFlatToFhirR4, encounterFlatToFhirR4, flagFlatToFhirR4, flatClaimsToFhirResource, immunizationFlatToFhirR4, locationFlatToFhirR4, medicationStatementFlatToFhirR4, observationFromFlatToFhirR4, organizationFlatToFhirR4, procedureFlatToFhirR4, practitionerRoleFlatToFhirR4, relatedPersonFlatToFhirR4, } from './clinical-resource-converters.js';
|
|
9
|
+
/** Version-independent FHIR SearchParameter claim context. */
|
|
10
|
+
const FHIR_API_CLAIMS_CONTEXT = 'org.hl7.fhir.api';
|
|
9
11
|
function asTrimmedString(value) {
|
|
10
12
|
if (value === undefined || value === null)
|
|
11
13
|
return '';
|
|
@@ -22,8 +24,7 @@ export function getSimpleClaimAttributeName(key) {
|
|
|
22
24
|
if (!value)
|
|
23
25
|
return '';
|
|
24
26
|
const knownPrefixes = [
|
|
25
|
-
|
|
26
|
-
'org.hl7.fhir.api.',
|
|
27
|
+
`${FHIR_API_CLAIMS_CONTEXT}.`,
|
|
27
28
|
];
|
|
28
29
|
for (const prefix of knownPrefixes) {
|
|
29
30
|
if (value.startsWith(prefix)) {
|
|
@@ -39,19 +40,13 @@ export function extractFlatClaimValue(record, key) {
|
|
|
39
40
|
const direct = record[normalizedKey];
|
|
40
41
|
if (typeof direct === 'string' && direct.trim())
|
|
41
42
|
return direct.trim();
|
|
42
|
-
const
|
|
43
|
-
if (typeof contextualizedR4 === 'string' && contextualizedR4.trim())
|
|
44
|
-
return contextualizedR4.trim();
|
|
45
|
-
const contextualizedApi = record[`org.hl7.fhir.api.${normalizedKey}`];
|
|
43
|
+
const contextualizedApi = record[`${FHIR_API_CLAIMS_CONTEXT}.${normalizedKey}`];
|
|
46
44
|
if (typeof contextualizedApi === 'string' && contextualizedApi.trim())
|
|
47
45
|
return contextualizedApi.trim();
|
|
48
46
|
const nested = record?.meta?.claims?.[normalizedKey];
|
|
49
47
|
if (typeof nested === 'string' && nested.trim())
|
|
50
48
|
return nested.trim();
|
|
51
|
-
const
|
|
52
|
-
if (typeof nestedR4 === 'string' && nestedR4.trim())
|
|
53
|
-
return nestedR4.trim();
|
|
54
|
-
const nestedApi = record?.meta?.claims?.[`org.hl7.fhir.api.${normalizedKey}`];
|
|
49
|
+
const nestedApi = record?.meta?.claims?.[`${FHIR_API_CLAIMS_CONTEXT}.${normalizedKey}`];
|
|
55
50
|
if (typeof nestedApi === 'string' && nestedApi.trim())
|
|
56
51
|
return nestedApi.trim();
|
|
57
52
|
return '';
|
|
@@ -59,12 +54,33 @@ export function extractFlatClaimValue(record, key) {
|
|
|
59
54
|
function claimsToFlatStrings(claims) {
|
|
60
55
|
const out = {};
|
|
61
56
|
for (const [key, value] of Object.entries(claims || {})) {
|
|
62
|
-
if (value === undefined || value === null)
|
|
57
|
+
if (value === undefined || value === null || key === '@context')
|
|
58
|
+
continue;
|
|
59
|
+
const canonicalKey = getSimpleClaimAttributeName(key);
|
|
60
|
+
if (canonicalKey === key)
|
|
61
|
+
continue;
|
|
62
|
+
out[canonicalKey] = typeof value === 'string' ? value : String(value);
|
|
63
|
+
}
|
|
64
|
+
for (const [key, value] of Object.entries(claims || {})) {
|
|
65
|
+
if (value === undefined || value === null || key === '@context')
|
|
66
|
+
continue;
|
|
67
|
+
const canonicalKey = getSimpleClaimAttributeName(key);
|
|
68
|
+
if (canonicalKey !== key)
|
|
63
69
|
continue;
|
|
64
70
|
out[key] = typeof value === 'string' ? value : String(value);
|
|
65
71
|
}
|
|
66
72
|
return out;
|
|
67
73
|
}
|
|
74
|
+
/** Rejects version-specific FHIR resource contexts from the claims contract. */
|
|
75
|
+
function assertFhirApiClaimsContext(claims) {
|
|
76
|
+
const context = asTrimmedString(claims?.['@context']);
|
|
77
|
+
const hasVersionSpecificContext = context.startsWith('org.hl7.fhir.')
|
|
78
|
+
&& context !== FHIR_API_CLAIMS_CONTEXT;
|
|
79
|
+
const hasVersionSpecificExpandedKey = Object.keys(claims || {}).some((key) => key.startsWith('org.hl7.fhir.') && !key.startsWith(`${FHIR_API_CLAIMS_CONTEXT}.`));
|
|
80
|
+
if (hasVersionSpecificContext || hasVersionSpecificExpandedKey) {
|
|
81
|
+
throw new Error(`FHIR claims require @context ${FHIR_API_CLAIMS_CONTEXT}. Version-specific FHIR resource contexts are not claim namespaces.`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
68
84
|
function ensureClaimsIdentifier(claims, resource) {
|
|
69
85
|
const resourceType = asTrimmedString(resource?.resourceType);
|
|
70
86
|
const identifierKey = resourceType ? `${resourceType}.identifier` : '';
|
|
@@ -202,7 +218,7 @@ export function prepareBundleDocumentForSubject(bundle, subjectDid, options = {}
|
|
|
202
218
|
if (!resource || typeof resource !== 'object')
|
|
203
219
|
continue;
|
|
204
220
|
replacePatientSubjectReference(resource, normalizedSubjectDid);
|
|
205
|
-
const generated = convertFhirResourceToClaims(resource, options.context ||
|
|
221
|
+
const generated = convertFhirResourceToClaims(resource, options.context || FHIR_API_CLAIMS_CONTEXT);
|
|
206
222
|
const existing = resource?.meta?.claims;
|
|
207
223
|
const claims = {
|
|
208
224
|
...generated,
|
|
@@ -324,7 +340,7 @@ export function detectClaimsResourceType(claims) {
|
|
|
324
340
|
return ResourceTypesFhirR4.DocumentReference;
|
|
325
341
|
const firstContextualized = keys
|
|
326
342
|
.map((key) => getSimpleClaimAttributeName(key))
|
|
327
|
-
.find((key) => key.includes('.'));
|
|
343
|
+
.find((key) => key.includes('.') && !key.startsWith(`${ResourceTypesFhirR4.Composition}.`));
|
|
328
344
|
if (firstContextualized) {
|
|
329
345
|
return firstContextualized.split('.')[0];
|
|
330
346
|
}
|
|
@@ -332,10 +348,11 @@ export function detectClaimsResourceType(claims) {
|
|
|
332
348
|
}
|
|
333
349
|
export function convertClaimsToFhirResource(claims, version = 'r4') {
|
|
334
350
|
void version;
|
|
351
|
+
assertFhirApiClaimsContext(claims);
|
|
335
352
|
const flatClaims = claimsToFlatStrings(claims);
|
|
336
353
|
const resourceType = detectClaimsResourceType(claims);
|
|
337
354
|
const resource = convertClaimsToFhirResourceByType(flatClaims, resourceType);
|
|
338
|
-
const language = resourceType ? asTrimmedString(
|
|
355
|
+
const language = resourceType ? asTrimmedString(flatClaims[`${resourceType}.language`]) : '';
|
|
339
356
|
return language ? { ...resource, language } : resource;
|
|
340
357
|
}
|
|
341
358
|
function convertClaimsToFhirResourceByType(flatClaims, resourceType) {
|
|
@@ -348,6 +365,8 @@ function convertClaimsToFhirResourceByType(flatClaims, resourceType) {
|
|
|
348
365
|
return conditionFlatToFhirR4(flatClaims);
|
|
349
366
|
case ResourceTypesFhirR4.DocumentReference:
|
|
350
367
|
return documentReferenceFlatToFhirR4(flatClaims);
|
|
368
|
+
case ResourceTypesFhirR4.DeviceUseStatement:
|
|
369
|
+
return deviceUseStatementFlatToFhirR4(flatClaims);
|
|
351
370
|
case 'Immunization':
|
|
352
371
|
return immunizationFlatToFhirR4(flatClaims);
|
|
353
372
|
case 'Location':
|
|
@@ -370,6 +389,8 @@ function convertClaimsToFhirResourceByType(flatClaims, resourceType) {
|
|
|
370
389
|
return compositionFlatToFhirR4(flatClaims);
|
|
371
390
|
case 'Appointment':
|
|
372
391
|
return appointmentFlatToFhirR4(flatClaims);
|
|
392
|
+
case 'AppointmentResponse':
|
|
393
|
+
return appointmentResponseFlatToFhirR4(flatClaims);
|
|
373
394
|
case 'Encounter':
|
|
374
395
|
return encounterFlatToFhirR4(flatClaims);
|
|
375
396
|
case 'RelatedPerson':
|
|
@@ -397,7 +418,7 @@ function convertClaimsToFhirResourceByType(flatClaims, resourceType) {
|
|
|
397
418
|
* not yet part of the clinical claims-first pipeline:
|
|
398
419
|
* `Composition`, `Patient`, `Practitioner`, `PractitionerRole`.
|
|
399
420
|
*/
|
|
400
|
-
export function extractBundleDocumentClaimsList(bundle, context = 'org.hl7.fhir.
|
|
421
|
+
export function extractBundleDocumentClaimsList(bundle, context = 'org.hl7.fhir.api') {
|
|
401
422
|
const entries = Array.isArray(bundle?.entry) ? bundle.entry : [];
|
|
402
423
|
const ignoredResourceTypes = new Set([
|
|
403
424
|
ResourceTypesFhirR4.Composition,
|
|
@@ -75,6 +75,19 @@ export declare class BundleEntryEditor {
|
|
|
75
75
|
hasClaim(key: string): boolean;
|
|
76
76
|
/** Writes one claim on this entry. */
|
|
77
77
|
setClaim(key: string, value: unknown): this;
|
|
78
|
+
/**
|
|
79
|
+
* Writes one viewer/editor field using the canonical short FHIR API claim.
|
|
80
|
+
* Expanded `org.hl7.fhir.api.*` input is normalized; versioned FHIR claim
|
|
81
|
+
* namespaces and structural/camelCase paths are rejected.
|
|
82
|
+
*/
|
|
83
|
+
setFhirApiClaim(key: string, value: unknown): this;
|
|
84
|
+
/** Reads one short or expanded FHIR API claim through the canonical short key. */
|
|
85
|
+
getFhirApiClaim(key: string): unknown;
|
|
86
|
+
/** Applies a complete field collection returned by a clinical card view. */
|
|
87
|
+
setFhirApiClaimFields(fields: readonly Readonly<{
|
|
88
|
+
claim: string;
|
|
89
|
+
value: unknown;
|
|
90
|
+
}>[]): this;
|
|
78
91
|
/** Appends one claim value on this entry. */
|
|
79
92
|
addClaim(key: string, value: unknown): this;
|
|
80
93
|
/** Removes one claim from this entry. */
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
8
8
|
import { BundleEditableResourceTypes, } from '../models/bundle-editor-types.js';
|
|
9
|
+
import { normalizeFhirApiClaimKey } from './fhir-api-claim-helpers.js';
|
|
9
10
|
import { EmployeeResourceTypes, } from './employee.js';
|
|
10
11
|
import { cloneClaimValue, normalizeOptionalIdentifier } from './bundle-editor-helpers.js';
|
|
11
12
|
import { createRegisteredBundleEntryEditor } from './bundle-editor-registry.js';
|
|
@@ -241,6 +242,23 @@ export class BundleEntryEditor {
|
|
|
241
242
|
};
|
|
242
243
|
return this;
|
|
243
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Writes one viewer/editor field using the canonical short FHIR API claim.
|
|
247
|
+
* Expanded `org.hl7.fhir.api.*` input is normalized; versioned FHIR claim
|
|
248
|
+
* namespaces and structural/camelCase paths are rejected.
|
|
249
|
+
*/
|
|
250
|
+
setFhirApiClaim(key, value) {
|
|
251
|
+
return this.setClaim(normalizeFhirApiClaimKey(key), value);
|
|
252
|
+
}
|
|
253
|
+
/** Reads one short or expanded FHIR API claim through the canonical short key. */
|
|
254
|
+
getFhirApiClaim(key) {
|
|
255
|
+
return this.getClaim(normalizeFhirApiClaimKey(key));
|
|
256
|
+
}
|
|
257
|
+
/** Applies a complete field collection returned by a clinical card view. */
|
|
258
|
+
setFhirApiClaimFields(fields) {
|
|
259
|
+
fields.forEach((field) => this.setFhirApiClaim(field.claim, field.value));
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
244
262
|
/** Appends one claim value on this entry. */
|
|
245
263
|
addClaim(key, value) {
|
|
246
264
|
const normalizedKey = String(key).trim();
|
|
@@ -99,12 +99,14 @@ export const practitionerRoleFhirToFlat = practitionerRoleFhirR4ToFlat;
|
|
|
99
99
|
* resource-specific converter exists. Unsupported resources fall back to the
|
|
100
100
|
* generic structural flattening.
|
|
101
101
|
*/
|
|
102
|
-
export function convertFhirResourceToClaims(resource, context = 'org.hl7.fhir.
|
|
102
|
+
export function convertFhirResourceToClaims(resource, context = 'org.hl7.fhir.api') {
|
|
103
103
|
const claims = convertFhirResourceToClaimsByType(resource, context);
|
|
104
104
|
const language = typeof resource.language === 'string' ? resource.language.trim() : '';
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
return {
|
|
106
|
+
'@context': context,
|
|
107
|
+
...claims,
|
|
108
|
+
...(language ? { [`${resource.resourceType}.language`]: language } : {}),
|
|
109
|
+
};
|
|
108
110
|
}
|
|
109
111
|
function convertFhirResourceToClaimsByType(resource, context) {
|
|
110
112
|
switch (resource.resourceType) {
|
|
@@ -20,9 +20,54 @@ export type ClinicalResourceCommonView = Readonly<{
|
|
|
20
20
|
export type ClinicalResourceCardView = Readonly<{
|
|
21
21
|
title: string;
|
|
22
22
|
resourceType: string;
|
|
23
|
+
/** Stable business identifier used to reconcile repeated readbacks. */
|
|
24
|
+
identifier?: string;
|
|
23
25
|
date?: string;
|
|
26
|
+
periodStart?: string;
|
|
27
|
+
periodEnd?: string;
|
|
24
28
|
fullUrl?: string;
|
|
25
29
|
actorsCount: number;
|
|
30
|
+
/** Resource status resolved from canonical claims first, then native FHIR. */
|
|
31
|
+
status?: string;
|
|
32
|
+
/** Observation scalar value for result cards. */
|
|
33
|
+
value?: string | number;
|
|
34
|
+
/** Observation quantity unit for result cards. */
|
|
35
|
+
unit?: string;
|
|
36
|
+
/** Immunization lot number. */
|
|
37
|
+
lotNumber?: string;
|
|
38
|
+
/** Immunization dose sequence. */
|
|
39
|
+
doseSequence?: string;
|
|
40
|
+
/** AllergyIntolerance criticality. */
|
|
41
|
+
criticality?: string;
|
|
42
|
+
/** AllergyIntolerance onset date/time. */
|
|
43
|
+
onsetDateTime?: string;
|
|
44
|
+
/** MedicationStatement human-readable dosage instruction. */
|
|
45
|
+
dosageInstruction?: string;
|
|
46
|
+
category?: string;
|
|
47
|
+
severity?: string;
|
|
48
|
+
recordedDate?: string;
|
|
49
|
+
source?: string;
|
|
50
|
+
route?: string;
|
|
51
|
+
site?: string;
|
|
52
|
+
doseQuantityValue?: number;
|
|
53
|
+
doseQuantityUnit?: string;
|
|
54
|
+
referenceRangeText?: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Complete editable field surface resolved from `resource.meta.claims`.
|
|
58
|
+
*
|
|
59
|
+
* `claim` always uses the short, version-independent FHIR API form
|
|
60
|
+
* (`<ResourceType>.<search-param>`). Consumers can therefore render and
|
|
61
|
+
* hydrate fields that do not yet have a dedicated card convenience member.
|
|
62
|
+
*/
|
|
63
|
+
fields: readonly ClinicalResourceClaimFieldView[];
|
|
64
|
+
}>;
|
|
65
|
+
export type ClinicalResourceClaimFieldView = Readonly<{
|
|
66
|
+
/** Canonical short FHIR API claim, for example `Immunization.lot-number`. */
|
|
67
|
+
claim: string;
|
|
68
|
+
/** Concrete FHIR API SearchParameter name, for example `lot-number`. */
|
|
69
|
+
parameter: string;
|
|
70
|
+
value: unknown;
|
|
26
71
|
}>;
|
|
27
72
|
export type ClinicalTerminologyTranslationInput = Readonly<{
|
|
28
73
|
resourceType: string;
|
|
@@ -110,6 +155,16 @@ export declare function toClinicalResourceCommonViews(bundle: ClinicalResourceBu
|
|
|
110
155
|
* Maps one bundle entry to a minimal card view for section counters/list cards.
|
|
111
156
|
*/
|
|
112
157
|
export declare function toClinicalResourceCardView(entry: ClinicalResourceEntryLike, options?: ClinicalResourceDisplayOptions): ClinicalResourceCardView;
|
|
158
|
+
/**
|
|
159
|
+
* Normalizes all clinical `meta.claims` into the short FHIR API vocabulary
|
|
160
|
+
* consumed by generic clinical viewers and editors.
|
|
161
|
+
*
|
|
162
|
+
* Short claims take precedence over their expanded
|
|
163
|
+
* `org.hl7.fhir.api.<ResourceType>.<search-param>` equivalent. Versioned
|
|
164
|
+
* `org.hl7.fhir.<version>.*` namespaces are rejected because they are native
|
|
165
|
+
* FHIR representation namespaces, never claims vocabularies.
|
|
166
|
+
*/
|
|
167
|
+
export declare function toClinicalResourceClaimFieldViews(claims: ClinicalViewClaims): ClinicalResourceClaimFieldView[];
|
|
113
168
|
/**
|
|
114
169
|
* Maps all entries from a Bundle into minimal card views.
|
|
115
170
|
*/
|
|
@@ -14,6 +14,7 @@ import { MedicationStatementClaim, MedicationStatementClaimsFhirApi, MedicationS
|
|
|
14
14
|
import { ObservationClaim } from '../models/interoperable-claims/observation-claims.js';
|
|
15
15
|
import { PractitionerRoleClaim } from '../models/interoperable-claims/practitioner-role-claims.js';
|
|
16
16
|
import { ProcedureClaim } from '../models/interoperable-claims/procedure-claims.js';
|
|
17
|
+
import { normalizeFhirApiClaimKey } from './fhir-api-claim-helpers.js';
|
|
17
18
|
const CONSENT_ACTOR_REFERENCE_CLAIM = 'Consent.actor-reference';
|
|
18
19
|
const GENERIC_CREATOR_CLAIM_SUFFIX = '.creator';
|
|
19
20
|
const GENERIC_PERFORMER_CLAIM_SUFFIX = '.performer';
|
|
@@ -49,14 +50,112 @@ export function toClinicalResourceCommonViews(bundle, options = {}) {
|
|
|
49
50
|
*/
|
|
50
51
|
export function toClinicalResourceCardView(entry, options = {}) {
|
|
51
52
|
const common = toClinicalResourceCommonView(entry, options);
|
|
53
|
+
const resource = entry.resource;
|
|
54
|
+
const status = resolveCardStatus(common.resourceType, common.claims, resource);
|
|
55
|
+
const value = resolveCardValue(common.resourceType, common.claims, resource);
|
|
56
|
+
const unit = resolveCardUnit(common.resourceType, common.claims, resource);
|
|
57
|
+
const lotNumber = readCanonicalClaimValue(common.claims, ImmunizationClaim.LotNumber)
|
|
58
|
+
|| trimValue(resource?.lotNumber);
|
|
59
|
+
const doseSequence = readCanonicalClaimValue(common.claims, ImmunizationClaim.DoseSequence)
|
|
60
|
+
|| trimValue(asRecord(asArray(resource?.protocolApplied)[0]).doseNumberString);
|
|
61
|
+
const criticality = readCanonicalClaimValue(common.claims, AllergyIntoleranceClaim.Criticality)
|
|
62
|
+
|| trimValue(resource?.criticality);
|
|
63
|
+
const onsetDateTime = readCanonicalClaimValue(common.claims, AllergyIntoleranceClaim.OnsetDateTime)
|
|
64
|
+
|| trimValue(resource?.onsetDateTime);
|
|
65
|
+
const dosageInstruction = readCanonicalClaimValue(common.claims, MedicationStatementClaim.DosageInstruction)
|
|
66
|
+
|| trimValue(asRecord(asArray(resource?.dosage)[0]).text);
|
|
67
|
+
const fields = toClinicalResourceClaimFieldViews(common.claims);
|
|
68
|
+
const category = readCanonicalClaimValue(common.claims, `${common.resourceType}.category`);
|
|
69
|
+
const severity = readCanonicalClaimValue(common.claims, `${common.resourceType}.severity`);
|
|
70
|
+
const recordedDate = readCanonicalClaimValue(common.claims, ConditionClaim.RecordedDate);
|
|
71
|
+
const source = readCanonicalClaimValue(common.claims, MedicationStatementClaim.Source);
|
|
72
|
+
const route = readCanonicalClaimValue(common.claims, ImmunizationClaim.Route);
|
|
73
|
+
const site = readCanonicalClaimValue(common.claims, ImmunizationClaim.Site);
|
|
74
|
+
const doseQuantityValueRaw = readCanonicalClaimValue(common.claims, MedicationStatementClaim.DoseQuantityValue);
|
|
75
|
+
const doseQuantityValue = doseQuantityValueRaw === undefined ? undefined : Number(doseQuantityValueRaw);
|
|
76
|
+
const doseQuantityUnit = readCanonicalClaimValue(common.claims, MedicationStatementClaim.DoseQuantityUnit);
|
|
77
|
+
const referenceRangeText = readCanonicalClaimValue(common.claims, ObservationClaim.ReferenceRangeText);
|
|
78
|
+
const description = readCanonicalClaimValue(common.claims, CarePlanClaim.Description);
|
|
52
79
|
return {
|
|
53
80
|
title: common.title,
|
|
54
81
|
resourceType: common.resourceType,
|
|
82
|
+
...(common.identifier ? { identifier: common.identifier } : {}),
|
|
55
83
|
date: common.date,
|
|
84
|
+
...(common.periodStart ? { periodStart: common.periodStart } : {}),
|
|
85
|
+
...(common.periodEnd ? { periodEnd: common.periodEnd } : {}),
|
|
56
86
|
fullUrl: common.fullUrl,
|
|
57
87
|
actorsCount: common.actors.length,
|
|
88
|
+
fields,
|
|
89
|
+
...(status ? { status } : {}),
|
|
90
|
+
...(value !== undefined ? { value } : {}),
|
|
91
|
+
...(unit ? { unit } : {}),
|
|
92
|
+
...(lotNumber ? { lotNumber } : {}),
|
|
93
|
+
...(doseSequence ? { doseSequence } : {}),
|
|
94
|
+
...(criticality ? { criticality } : {}),
|
|
95
|
+
...(onsetDateTime ? { onsetDateTime } : {}),
|
|
96
|
+
...(dosageInstruction ? { dosageInstruction } : {}),
|
|
97
|
+
...(category ? { category } : {}),
|
|
98
|
+
...(severity ? { severity } : {}),
|
|
99
|
+
...(recordedDate ? { recordedDate } : {}),
|
|
100
|
+
...(source ? { source } : {}),
|
|
101
|
+
...(route ? { route } : {}),
|
|
102
|
+
...(site ? { site } : {}),
|
|
103
|
+
...(doseQuantityValue !== undefined && Number.isFinite(doseQuantityValue) ? { doseQuantityValue } : {}),
|
|
104
|
+
...(doseQuantityUnit ? { doseQuantityUnit } : {}),
|
|
105
|
+
...(referenceRangeText ? { referenceRangeText } : {}),
|
|
106
|
+
...(description ? { description } : {}),
|
|
58
107
|
};
|
|
59
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Normalizes all clinical `meta.claims` into the short FHIR API vocabulary
|
|
111
|
+
* consumed by generic clinical viewers and editors.
|
|
112
|
+
*
|
|
113
|
+
* Short claims take precedence over their expanded
|
|
114
|
+
* `org.hl7.fhir.api.<ResourceType>.<search-param>` equivalent. Versioned
|
|
115
|
+
* `org.hl7.fhir.<version>.*` namespaces are rejected because they are native
|
|
116
|
+
* FHIR representation namespaces, never claims vocabularies.
|
|
117
|
+
*/
|
|
118
|
+
export function toClinicalResourceClaimFieldViews(claims) {
|
|
119
|
+
const fields = new Map();
|
|
120
|
+
const entries = Object.entries(claims || {});
|
|
121
|
+
for (const [rawClaim, value] of entries) {
|
|
122
|
+
if (rawClaim.startsWith('@') || value === undefined)
|
|
123
|
+
continue;
|
|
124
|
+
if (rawClaim.startsWith('org.hl7.fhir.') && !rawClaim.startsWith('org.hl7.fhir.api.')) {
|
|
125
|
+
throw new Error(`FHIR meta.claims must use org.hl7.fhir.api, not version-specific key: ${rawClaim}`);
|
|
126
|
+
}
|
|
127
|
+
if (!rawClaim.startsWith('org.hl7.fhir.api.') && !/^[A-Z][A-Za-z0-9]+\./.test(rawClaim))
|
|
128
|
+
continue;
|
|
129
|
+
const claim = normalizeFhirApiClaimKey(rawClaim);
|
|
130
|
+
const separator = claim.indexOf('.');
|
|
131
|
+
if (separator <= 0 || separator === claim.length - 1)
|
|
132
|
+
continue;
|
|
133
|
+
if (!fields.has(claim)) {
|
|
134
|
+
fields.set(claim, {
|
|
135
|
+
claim,
|
|
136
|
+
parameter: claim.slice(separator + 1),
|
|
137
|
+
value,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Apply canonical short keys last so they win over expanded aliases even
|
|
142
|
+
// when the expanded property appeared later in insertion order.
|
|
143
|
+
for (const [claim, value] of entries) {
|
|
144
|
+
if (claim.startsWith('@') || claim.startsWith('org.hl7.fhir.') || value === undefined)
|
|
145
|
+
continue;
|
|
146
|
+
if (!/^[A-Z][A-Za-z0-9]+\./.test(claim))
|
|
147
|
+
continue;
|
|
148
|
+
const separator = claim.indexOf('.');
|
|
149
|
+
if (separator <= 0 || separator === claim.length - 1)
|
|
150
|
+
continue;
|
|
151
|
+
fields.set(claim, {
|
|
152
|
+
claim,
|
|
153
|
+
parameter: claim.slice(separator + 1),
|
|
154
|
+
value,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return [...fields.values()].sort((left, right) => left.claim.localeCompare(right.claim));
|
|
158
|
+
}
|
|
60
159
|
/**
|
|
61
160
|
* Maps all entries from a Bundle into minimal card views.
|
|
62
161
|
*/
|
|
@@ -196,6 +295,42 @@ export function getNarrative(resource) {
|
|
|
196
295
|
source: 'derived-from-claims',
|
|
197
296
|
};
|
|
198
297
|
}
|
|
298
|
+
function resolveCardStatus(resourceType, claims, resource) {
|
|
299
|
+
const claimsStatus = resourceType === ResourceTypesFhirR4.AllergyIntolerance
|
|
300
|
+
? readCanonicalClaimValue(claims, AllergyIntoleranceClaim.ClinicalStatus)
|
|
301
|
+
: readCanonicalClaimValue(claims, `${resourceType}.status`);
|
|
302
|
+
if (claimsStatus)
|
|
303
|
+
return claimsStatus;
|
|
304
|
+
const nativeStatus = trimValue(resource?.status);
|
|
305
|
+
if (nativeStatus)
|
|
306
|
+
return nativeStatus;
|
|
307
|
+
return trimValue(asRecord(asArray(asRecord(resource?.clinicalStatus).coding)[0]).code) || undefined;
|
|
308
|
+
}
|
|
309
|
+
function resolveCardValue(resourceType, claims, resource) {
|
|
310
|
+
if (resourceType !== ResourceTypesFhirR4.Observation)
|
|
311
|
+
return undefined;
|
|
312
|
+
const claimNumber = readCanonicalClaimValue(claims, ObservationClaim.ValueQuantityNumber);
|
|
313
|
+
if (claimNumber !== undefined) {
|
|
314
|
+
const numeric = Number(claimNumber);
|
|
315
|
+
if (Number.isFinite(numeric))
|
|
316
|
+
return numeric;
|
|
317
|
+
}
|
|
318
|
+
const claimString = readCanonicalClaimValue(claims, ObservationClaim.ValueString);
|
|
319
|
+
if (claimString)
|
|
320
|
+
return claimString;
|
|
321
|
+
const nativeNumber = asRecord(resource?.valueQuantity).value;
|
|
322
|
+
if (typeof nativeNumber === 'number' && Number.isFinite(nativeNumber))
|
|
323
|
+
return nativeNumber;
|
|
324
|
+
return trimValue(resource?.valueString) || undefined;
|
|
325
|
+
}
|
|
326
|
+
function resolveCardUnit(resourceType, claims, resource) {
|
|
327
|
+
if (resourceType !== ResourceTypesFhirR4.Observation)
|
|
328
|
+
return undefined;
|
|
329
|
+
return readCanonicalClaimValue(claims, ObservationClaim.ValueQuantityUnit)
|
|
330
|
+
|| trimValue(asRecord(resource?.valueQuantity).unit)
|
|
331
|
+
|| trimValue(asRecord(resource?.valueQuantity).code)
|
|
332
|
+
|| undefined;
|
|
333
|
+
}
|
|
199
334
|
function readClaims(entry) {
|
|
200
335
|
const resourceClaims = asRecord(entry?.resource?.meta?.claims);
|
|
201
336
|
const legacyClaims = asRecord(entry?.meta?.claims);
|
|
@@ -397,7 +532,8 @@ function resolveIdentifier(resourceType, claims, resource) {
|
|
|
397
532
|
AllergyIntoleranceClaimsFhirApi.Identifier,
|
|
398
533
|
]) || resolveFhirIdentifier(resource);
|
|
399
534
|
}
|
|
400
|
-
return
|
|
535
|
+
return readCanonicalClaimValue(claims, `${resourceType}.identifier`)
|
|
536
|
+
|| resolveFhirIdentifier(resource);
|
|
401
537
|
}
|
|
402
538
|
function resolveDate(resourceType, claims, resource) {
|
|
403
539
|
if (resourceType === ResourceTypesFhirR4.Communication) {
|
|
@@ -67,7 +67,7 @@ export function buildBundleDocumentRequestCommunicationClaims(input) {
|
|
|
67
67
|
: `Request ${documentTypeDescriptor.id} Bundle search with sections: ${sections.join(', ')}`)).trim();
|
|
68
68
|
const noteText = String(input.noteText || text).trim();
|
|
69
69
|
const claims = {
|
|
70
|
-
'@context': 'org.hl7.fhir.
|
|
70
|
+
'@context': 'org.hl7.fhir.api',
|
|
71
71
|
[CommunicationClaim.Identifier]: communicationIdentifier,
|
|
72
72
|
[CommunicationClaim.Status]: String(input.status || 'completed').trim(),
|
|
73
73
|
[CommunicationClaim.Category]: CommunicationCategoryCodes.Notification.claim,
|
|
@@ -121,7 +121,7 @@ export function extractCommunicationClaimsFromResourceFhirR4(resource, options =
|
|
|
121
121
|
return { ...existingClaims };
|
|
122
122
|
}
|
|
123
123
|
const claims = {};
|
|
124
|
-
claims['@context'] = 'org.hl7.fhir.
|
|
124
|
+
claims['@context'] = 'org.hl7.fhir.api';
|
|
125
125
|
const identifierValue = resource?.identifier?.[0]?.value;
|
|
126
126
|
const status = resource?.status;
|
|
127
127
|
const sent = resource?.sent;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
const FHIR_API_PREFIX = 'org.hl7.fhir.api.';
|
|
3
|
+
const FHIR_VERSIONED_PREFIX = 'org.hl7.fhir.';
|
|
4
|
+
const SHORT_FHIR_API_CLAIM = /^[A-Z][A-Za-z0-9]+\.[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
5
|
+
/** Returns the canonical short FHIR API claim or throws for another vocabulary. */
|
|
6
|
+
export function normalizeFhirApiClaimKey(claimKey) {
|
|
7
|
+
const raw = String(claimKey || '').trim();
|
|
8
|
+
if (raw.startsWith(FHIR_VERSIONED_PREFIX) && !raw.startsWith(FHIR_API_PREFIX)) {
|
|
9
|
+
throw new Error(`FHIR claims must use org.hl7.fhir.api, not version-specific key: ${raw}`);
|
|
10
|
+
}
|
|
11
|
+
const normalized = raw.startsWith(FHIR_API_PREFIX) ? raw.slice(FHIR_API_PREFIX.length) : raw;
|
|
12
|
+
if (!SHORT_FHIR_API_CLAIM.test(normalized)) {
|
|
13
|
+
throw new Error(`Invalid FHIR API claim key: ${raw}`);
|
|
14
|
+
}
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
@@ -17,10 +17,9 @@ export type FhirMetaTagCoding = Readonly<{
|
|
|
17
17
|
display?: string;
|
|
18
18
|
}>;
|
|
19
19
|
/**
|
|
20
|
-
* Removes the
|
|
20
|
+
* Removes the version-independent FHIR API context from a flattened claim key.
|
|
21
21
|
*
|
|
22
22
|
* Examples:
|
|
23
|
-
* - `org.hl7.fhir.r4.Immunization.vaccine-code` -> `Immunization.vaccine-code`
|
|
24
23
|
* - `org.hl7.fhir.api.MedicationStatement.subject` -> `MedicationStatement.subject`
|
|
25
24
|
* - `Consent.identifier` -> `Consent.identifier`
|
|
26
25
|
*/
|
|
@@ -35,8 +34,8 @@ export declare function extractResourceMetaClaimsFromBundle(bundle: BundleLike):
|
|
|
35
34
|
/**
|
|
36
35
|
* Builds FHIR `meta.tag[]` codings from a flat claims record.
|
|
37
36
|
*
|
|
38
|
-
* The generated `code`
|
|
39
|
-
*
|
|
37
|
+
* The generated `code` removes the sole valid FHIR claims context,
|
|
38
|
+
* `org.hl7.fhir.api`, so UI/frontends receive the canonical short key.
|
|
40
39
|
*/
|
|
41
40
|
export declare function createFhirMetaTagsFromClaims(claims: Record<string, unknown>, options?: Readonly<{
|
|
42
41
|
system?: string;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
export const DEFAULT_META_CLAIM_TAG_SYSTEM = 'urn:gdc:fhir:meta-claim';
|
|
3
3
|
/**
|
|
4
|
-
* Removes the
|
|
4
|
+
* Removes the version-independent FHIR API context from a flattened claim key.
|
|
5
5
|
*
|
|
6
6
|
* Examples:
|
|
7
|
-
* - `org.hl7.fhir.r4.Immunization.vaccine-code` -> `Immunization.vaccine-code`
|
|
8
7
|
* - `org.hl7.fhir.api.MedicationStatement.subject` -> `MedicationStatement.subject`
|
|
9
8
|
* - `Consent.identifier` -> `Consent.identifier`
|
|
10
9
|
*/
|
|
@@ -12,9 +11,10 @@ export function toVersionAgnosticMetaClaimKey(claimKey) {
|
|
|
12
11
|
const raw = String(claimKey || '').trim();
|
|
13
12
|
if (!raw)
|
|
14
13
|
return '';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (raw.startsWith('org.hl7.fhir.') && !raw.startsWith('org.hl7.fhir.api.')) {
|
|
15
|
+
throw new Error('FHIR claims require @context org.hl7.fhir.api.');
|
|
16
|
+
}
|
|
17
|
+
return raw.replace(/^org\.hl7\.fhir\.api\./i, '');
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Extracts all `resource.meta.claims` blocks from a FHIR/JSON:API bundle.
|
|
@@ -35,8 +35,8 @@ export function extractResourceMetaClaimsFromBundle(bundle) {
|
|
|
35
35
|
/**
|
|
36
36
|
* Builds FHIR `meta.tag[]` codings from a flat claims record.
|
|
37
37
|
*
|
|
38
|
-
* The generated `code`
|
|
39
|
-
*
|
|
38
|
+
* The generated `code` removes the sole valid FHIR claims context,
|
|
39
|
+
* `org.hl7.fhir.api`, so UI/frontends receive the canonical short key.
|
|
40
40
|
*/
|
|
41
41
|
export function createFhirMetaTagsFromClaims(claims, options) {
|
|
42
42
|
const system = String(options?.system || DEFAULT_META_CLAIM_TAG_SYSTEM).trim();
|
|
@@ -63,25 +63,25 @@ export class MedicationStatementEntryEditor extends ClinicalResourceEntryEditor
|
|
|
63
63
|
/** Returns the medication category/section tags. */
|
|
64
64
|
getCategoryList() { return this.getCsvClaimList(MedicationStatementClaim.Category); }
|
|
65
65
|
/** Sets the numeric dose quantity value. */
|
|
66
|
-
setDoseQuantityValue(value) { return this.setNumberClaim(
|
|
66
|
+
setDoseQuantityValue(value) { return this.setNumberClaim(MedicationStatementClaim.DoseQuantityValue, value); }
|
|
67
67
|
/** Returns the numeric dose quantity value. */
|
|
68
|
-
getDoseQuantityValue() { return this.getNumberClaim(
|
|
68
|
+
getDoseQuantityValue() { return this.getNumberClaim(MedicationStatementClaim.DoseQuantityValue); }
|
|
69
69
|
/** Sets the dose quantity unit token. */
|
|
70
|
-
setDoseQuantityUnit(value) { return this.setScalarClaim(
|
|
70
|
+
setDoseQuantityUnit(value) { return this.setScalarClaim(MedicationStatementClaim.DoseQuantityUnit, value); }
|
|
71
71
|
/** Returns the dose quantity unit token. */
|
|
72
|
-
getDoseQuantityUnit() { return this.getScalarClaim(
|
|
72
|
+
getDoseQuantityUnit() { return this.getScalarClaim(MedicationStatementClaim.DoseQuantityUnit); }
|
|
73
73
|
/** Sets the timing frequency for structured dosage authoring. */
|
|
74
|
-
setTimingFrequency(value) { return this.setNumberClaim(
|
|
74
|
+
setTimingFrequency(value) { return this.setNumberClaim(MedicationStatementClaim.TimingFrequency, value); }
|
|
75
75
|
/** Returns the timing frequency. */
|
|
76
|
-
getTimingFrequency() { return this.getNumberClaim(
|
|
76
|
+
getTimingFrequency() { return this.getNumberClaim(MedicationStatementClaim.TimingFrequency); }
|
|
77
77
|
/** Sets the timing period for structured dosage authoring. */
|
|
78
|
-
setTimingPeriod(value) { return this.setNumberClaim(
|
|
78
|
+
setTimingPeriod(value) { return this.setNumberClaim(MedicationStatementClaim.TimingPeriod, value); }
|
|
79
79
|
/** Returns the timing period. */
|
|
80
|
-
getTimingPeriod() { return this.getNumberClaim(
|
|
80
|
+
getTimingPeriod() { return this.getNumberClaim(MedicationStatementClaim.TimingPeriod); }
|
|
81
81
|
/** Sets the timing period unit token. */
|
|
82
|
-
setTimingPeriodUnit(value) { return this.setScalarClaim(
|
|
82
|
+
setTimingPeriodUnit(value) { return this.setScalarClaim(MedicationStatementClaim.TimingPeriodUnit, value); }
|
|
83
83
|
/** Returns the timing period unit token. */
|
|
84
|
-
getTimingPeriodUnit() { return this.getScalarClaim(
|
|
84
|
+
getTimingPeriodUnit() { return this.getScalarClaim(MedicationStatementClaim.TimingPeriodUnit); }
|
|
85
85
|
/** Marks whether this dosage is `as needed`. */
|
|
86
86
|
setDosageAsNeeded(value) { return this.setBooleanClaim(MedicationStatementClaimsFhirApiExtended.DosageAsNeeded, value); }
|
|
87
87
|
/** Returns whether this dosage is `as needed`. */
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
* - Move shared helpers to reusable helper/base modules instead of duplicating logic here.
|
|
7
7
|
*/
|
|
8
8
|
import { type CodingDescriptor } from '../constants/vital-signs';
|
|
9
|
-
import {
|
|
9
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor';
|
|
10
10
|
/**
|
|
11
11
|
* Typed editor for one staged ObservationComponent resource entry.
|
|
12
12
|
*
|
|
13
13
|
* Keep this surface thin and claim-focused so 101 tests can teach one
|
|
14
14
|
* resource at a time without exposing bundle-internal plumbing.
|
|
15
15
|
*/
|
|
16
|
-
export declare class ObservationComponentEntryEditor extends
|
|
16
|
+
export declare class ObservationComponentEntryEditor extends ClinicalResourceEntryEditor {
|
|
17
17
|
setCode(code: CodingDescriptor | string): this;
|
|
18
18
|
getCode(): string | undefined;
|
|
19
19
|
setCodeSystem(system: string): this;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ObservationClaim } from '../models/interoperable-claims/observation-claims.js';
|
|
2
2
|
import { normalizeOptionalIdentifier } from './bundle-editor-helpers.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor.js';
|
|
4
4
|
/**
|
|
5
5
|
* Typed editor for one staged ObservationComponent resource entry.
|
|
6
6
|
*
|
|
7
7
|
* Keep this surface thin and claim-focused so 101 tests can teach one
|
|
8
8
|
* resource at a time without exposing bundle-internal plumbing.
|
|
9
9
|
*/
|
|
10
|
-
export class ObservationComponentEntryEditor extends
|
|
10
|
+
export class ObservationComponentEntryEditor extends ClinicalResourceEntryEditor {
|
|
11
11
|
setCode(code) {
|
|
12
12
|
const token = typeof code === 'string' ? code.trim() : code.claim;
|
|
13
13
|
this.setClaim(ObservationClaim.Code, token);
|