vet-data-utils-ts 0.5.32 → 0.5.36
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 +19 -0
- package/dist/clinical-bundle-reader.js +20 -1
- package/dist/clinical-terminology.d.ts +30 -2
- package/dist/clinical-terminology.js +7 -31
- package/dist/immunization-coding-review.d.ts +51 -0
- package/dist/immunization-coding-review.js +59 -0
- package/dist/immunization-draft.d.ts +1 -1
- package/dist/immunization-draft.js +8 -2
- package/dist/immunization-flat-claims.d.ts +17 -2
- package/dist/immunization-flat-claims.js +109 -20
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/professional-access-policy.d.ts +2 -0
- package/dist/professional-access-policy.js +2 -0
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
# vet-data-utils-ts
|
|
2
|
+
## Blocking local-first SDK release
|
|
3
|
+
|
|
4
|
+
The canonical contract is [`SDK_LAYERING.md`](https://github.com/Fundacion-UNID/sos-data-utils-ts/blob/main/docs/SDK_LAYERING.md). Its
|
|
5
|
+
indivisible order is **local packages -> full local test matrix -> merge every
|
|
6
|
+
validated branch to `main` -> publish bottom-up -> install exact registry
|
|
7
|
+
versions and commit lockfiles on `main` -> staging**. Never publish to discover
|
|
8
|
+
deterministic failures and never commit a local package reference. Staging
|
|
9
|
+
begins only after exact registry packages are installed and verified.
|
|
10
|
+
|
|
2
11
|
|
|
3
12
|
## Lost-animal access and behavior
|
|
4
13
|
|
|
@@ -189,6 +198,16 @@ for immunologicals); ordinary human ATC is not substituted for it. Veterinary
|
|
|
189
198
|
allergy product coding may also use ATCvet, while manifestations use an allowed
|
|
190
199
|
SNOMED source.
|
|
191
200
|
|
|
201
|
+
Terminology-assisted entry uses the neutral coding-review contract from
|
|
202
|
+
`fhir-data-utils-ts/coding-review-flat-claims`. Spoken, typed or imported text
|
|
203
|
+
is `Immunization.vaccine-code-text`; an unconfirmed candidate stays in
|
|
204
|
+
`meta.codingProposals[]` beside the Immunization's `meta.claims`, targets
|
|
205
|
+
`Immunization.vaccine-code`, and is never copied to `ResearchSubject.meta`.
|
|
206
|
+
Confirmation adds the selected `system|code` and official `-display` without
|
|
207
|
+
overwriting local `-text`. Vet policy supplies ATCvet/species constraints; it
|
|
208
|
+
does not redefine the shared shape. Consumers reuse exported fixtures and
|
|
209
|
+
builders rather than repeating governed literals.
|
|
210
|
+
|
|
192
211
|
`vet-data-utils-ts/veterinary-biologic-product` keeps three independent axes:
|
|
193
212
|
|
|
194
213
|
- WHO ATCvet QI is the international medicine classification;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeClaimsFromFhirResource } from 'gdc-common-utils-ts/utils/interoperable-resource-operation';
|
|
2
|
+
import { normalizeFhirApiClaimKey } from 'gdc-common-utils-ts/utils/fhir-api-claim-helpers';
|
|
2
3
|
const PRIMARY_CODE_PROJECTIONS = Object.freeze({
|
|
3
4
|
Condition: { field: 'Condition.code', code: 'Condition.code', text: 'Condition.code-text', display: 'Condition.code-display' },
|
|
4
5
|
Procedure: { field: 'Procedure.code', code: 'Procedure.code', text: 'Procedure.code-text', display: 'Procedure.code-display' },
|
|
@@ -42,7 +43,7 @@ async function projectResource(resource, options) {
|
|
|
42
43
|
const existingMeta = asRecord(resource.meta);
|
|
43
44
|
const existingClaims = asRecord(existingMeta.claims);
|
|
44
45
|
const claims = Object.keys(existingClaims).length
|
|
45
|
-
?
|
|
46
|
+
? presentationClaims(existingClaims)
|
|
46
47
|
: normalizeClaimsFromFhirResource(resource, {});
|
|
47
48
|
const projection = PRIMARY_CODE_PROJECTIONS[resourceType];
|
|
48
49
|
if (projection) {
|
|
@@ -69,6 +70,24 @@ async function projectResource(resource, options) {
|
|
|
69
70
|
meta: { ...existingMeta, claims },
|
|
70
71
|
};
|
|
71
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Keeps structural FHIR metadata on the resource while preventing derived
|
|
75
|
+
* paths such as `Immunization.meta.versionId` from becoming editable/search
|
|
76
|
+
* claims in the presentation copy.
|
|
77
|
+
*/
|
|
78
|
+
function presentationClaims(source) {
|
|
79
|
+
return Object.fromEntries(Object.entries(source).filter(([claim]) => {
|
|
80
|
+
if (claim.startsWith('@'))
|
|
81
|
+
return true;
|
|
82
|
+
try {
|
|
83
|
+
normalizeFhirApiClaimKey(claim);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
72
91
|
function parseCodingToken(value) {
|
|
73
92
|
const separator = value.lastIndexOf('|');
|
|
74
93
|
if (separator <= 0 || separator === value.length - 1)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/** @deprecated Import `ClinicalTerminologySystems` from sos-data-utils-ts. */
|
|
1
2
|
export declare const VeterinaryClinicalTerminologySystems: Readonly<{
|
|
2
3
|
readonly Loinc: "http://loinc.org";
|
|
3
4
|
readonly SnomedCt: "http://snomed.info/sct";
|
|
4
5
|
readonly Icd10: "http://hl7.org/fhir/sid/icd-10";
|
|
5
|
-
|
|
6
|
+
readonly Atc: "http://www.whocc.no/atc";
|
|
6
7
|
readonly AtcVet: "http://www.whocc.no/atcvet";
|
|
7
8
|
}>;
|
|
8
9
|
/**
|
|
@@ -11,15 +12,19 @@ export declare const VeterinaryClinicalTerminologySystems: Readonly<{
|
|
|
11
12
|
* canonical SNOMED system URI.
|
|
12
13
|
* https://www.snomed.org/gps
|
|
13
14
|
*/
|
|
15
|
+
/** @deprecated Import `ClinicalTerminologySourceScopes` from sos-data-utils-ts. */
|
|
14
16
|
export declare const VeterinaryTerminologySourceScopes: Readonly<{
|
|
15
17
|
readonly Loinc: "LNC";
|
|
16
18
|
readonly SnomedGps: "SNOMED_GPS";
|
|
19
|
+
readonly SnomedIps: "SNOMED_IPS";
|
|
17
20
|
readonly SnomedCt: "SNOMED_CT";
|
|
18
21
|
readonly SnomedVeterinary: "SNOMEDCT_VET";
|
|
19
22
|
readonly Icd10: "ICD10";
|
|
23
|
+
readonly Atc: "ATC";
|
|
20
24
|
readonly AtcVet: "ATCVET";
|
|
21
25
|
}>;
|
|
22
26
|
/** Deterministic standards-based data for the isolated local terminology upstream. */
|
|
27
|
+
/** @deprecated Import `CLINICAL_TERMINOLOGY_TEST_DATA` from sos-data-utils-ts. */
|
|
23
28
|
export declare const VET_TERMINOLOGY_TEST_DATA: Readonly<{
|
|
24
29
|
readonly localApiKey: "local-playwright-umls-key";
|
|
25
30
|
readonly bodyTemperature: Readonly<{
|
|
@@ -35,8 +40,31 @@ export declare const VET_TERMINOLOGY_TEST_DATA: Readonly<{
|
|
|
35
40
|
code: "3135009";
|
|
36
41
|
display: "otitis externa";
|
|
37
42
|
}>;
|
|
43
|
+
readonly canineRabiesVaccine: Readonly<{
|
|
44
|
+
scope: "ATCVET";
|
|
45
|
+
system: "http://www.whocc.no/atcvet";
|
|
46
|
+
code: "QI07AA02";
|
|
47
|
+
text: "virus de la rabia";
|
|
48
|
+
display: "rabies virus";
|
|
49
|
+
ncbiTaxonomyId: "9615";
|
|
50
|
+
}>;
|
|
51
|
+
readonly humanInactivatedInfluenzaVaccine: Readonly<{
|
|
52
|
+
scope: "ATC";
|
|
53
|
+
system: "http://www.whocc.no/atc";
|
|
54
|
+
code: "J07BB02";
|
|
55
|
+
text: "vacuna contra la gripe inactivada de virus fraccionados o ant\u00EDgeno de superficie";
|
|
56
|
+
display: "influenza, inactivated, split virus or surface antigen";
|
|
57
|
+
ncbiTaxonomyId: "9606";
|
|
58
|
+
}>;
|
|
59
|
+
readonly rabiesDisease: Readonly<{
|
|
60
|
+
scope: "SNOMED_GPS";
|
|
61
|
+
umlsSource: "SNOMEDCT_US";
|
|
62
|
+
system: "http://snomed.info/sct";
|
|
63
|
+
code: "14168008";
|
|
64
|
+
display: "Rabies";
|
|
65
|
+
}>;
|
|
38
66
|
}>;
|
|
39
|
-
export type VeterinaryTerminologySourceScope = typeof VeterinaryTerminologySourceScopes[keyof typeof VeterinaryTerminologySourceScopes]
|
|
67
|
+
export type VeterinaryTerminologySourceScope = Exclude<typeof VeterinaryTerminologySourceScopes[keyof typeof VeterinaryTerminologySourceScopes], 'ATC' | 'SNOMED_IPS'>;
|
|
40
68
|
export type VeterinaryTerminologyCapability = Readonly<{
|
|
41
69
|
type: 'terminology-capability';
|
|
42
70
|
id: string;
|
|
@@ -1,41 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Icd10: 'http://hl7.org/fhir/sid/icd-10',
|
|
5
|
-
/** WHO Collaborating Centre ATCvet classification, distinct from human ATC. */
|
|
6
|
-
AtcVet: 'http://www.whocc.no/atcvet',
|
|
7
|
-
});
|
|
1
|
+
import { CLINICAL_TERMINOLOGY_TEST_DATA, ClinicalTerminologySourceScopes, ClinicalTerminologySystems, } from 'sos-data-utils-ts/clinical-terminology';
|
|
2
|
+
/** @deprecated Import `ClinicalTerminologySystems` from sos-data-utils-ts. */
|
|
3
|
+
export const VeterinaryClinicalTerminologySystems = ClinicalTerminologySystems;
|
|
8
4
|
/**
|
|
9
5
|
* Source scopes are authorization/content boundaries, not Coding.system URIs.
|
|
10
6
|
* GPS, full SNOMED CT and the veterinary extension intentionally share the
|
|
11
7
|
* canonical SNOMED system URI.
|
|
12
8
|
* https://www.snomed.org/gps
|
|
13
9
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
SnomedGps: 'SNOMED_GPS',
|
|
17
|
-
SnomedCt: 'SNOMED_CT',
|
|
18
|
-
SnomedVeterinary: 'SNOMEDCT_VET',
|
|
19
|
-
Icd10: 'ICD10',
|
|
20
|
-
AtcVet: 'ATCVET',
|
|
21
|
-
});
|
|
10
|
+
/** @deprecated Import `ClinicalTerminologySourceScopes` from sos-data-utils-ts. */
|
|
11
|
+
export const VeterinaryTerminologySourceScopes = ClinicalTerminologySourceScopes;
|
|
22
12
|
/** Deterministic standards-based data for the isolated local terminology upstream. */
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
bodyTemperature: Object.freeze({
|
|
26
|
-
source: VeterinaryTerminologySourceScopes.Loinc,
|
|
27
|
-
system: VeterinaryClinicalTerminologySystems.Loinc,
|
|
28
|
-
code: '8310-5',
|
|
29
|
-
display: 'Body temperature:Temp:Pt:^Patient:Qn',
|
|
30
|
-
}),
|
|
31
|
-
otitisExternaSpanish: Object.freeze({
|
|
32
|
-
scope: VeterinaryTerminologySourceScopes.SnomedCt,
|
|
33
|
-
umlsSource: 'SCTSPA',
|
|
34
|
-
system: VeterinaryClinicalTerminologySystems.SnomedCt,
|
|
35
|
-
code: '3135009',
|
|
36
|
-
display: 'otitis externa',
|
|
37
|
-
}),
|
|
38
|
-
});
|
|
13
|
+
/** @deprecated Import `CLINICAL_TERMINOLOGY_TEST_DATA` from sos-data-utils-ts. */
|
|
14
|
+
export const VET_TERMINOLOGY_TEST_DATA = CLINICAL_TERMINOLOGY_TEST_DATA;
|
|
39
15
|
/**
|
|
40
16
|
* ISO 3166-1 alpha-2 territories enumerated by the official SNOMED
|
|
41
17
|
* International member page on 2026-09-05.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type FlatClaimCodingCandidate, type FlatClaimCodingReviewResource } from 'fhir-data-utils-ts/coding-review-flat-claims';
|
|
2
|
+
/** Governed claim coordinates reused by Vet gateways, portals and assistants. */
|
|
3
|
+
export declare const VeterinaryImmunizationCodingReviewClaims: Readonly<{
|
|
4
|
+
code: "Immunization.vaccine-code";
|
|
5
|
+
display: string;
|
|
6
|
+
localText: string;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* Builds an unconfirmed veterinary Immunization coding review from text spoken,
|
|
10
|
+
* typed or imported by a channel. The neutral helper owns proposal placement;
|
|
11
|
+
* this wrapper contributes veterinary resource coordinates and ATCvet policy.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildVeterinaryImmunizationCodingReview(input: Readonly<{
|
|
14
|
+
entryId: string;
|
|
15
|
+
animalReference: string;
|
|
16
|
+
administrationDate: string;
|
|
17
|
+
localText: string;
|
|
18
|
+
language: string;
|
|
19
|
+
proposalId: string;
|
|
20
|
+
candidates: readonly FlatClaimCodingCandidate[];
|
|
21
|
+
}>): FlatClaimCodingReviewResource;
|
|
22
|
+
/** Package-owned synthetic example for assistants, portals and downstream tests. */
|
|
23
|
+
export declare const VETERINARY_IMMUNIZATION_CODING_REVIEW_EXAMPLE: Readonly<{
|
|
24
|
+
input: Readonly<{
|
|
25
|
+
entryId: "00000000-0000-4000-8000-000000000201";
|
|
26
|
+
animalReference: "Patient/00000000-0000-4000-8000-000000000202";
|
|
27
|
+
administrationDate: "2024-05-23";
|
|
28
|
+
localText: "vacuna contra la rabia";
|
|
29
|
+
language: "es-ES";
|
|
30
|
+
proposalId: "veterinary-immunization-proposal-example";
|
|
31
|
+
candidates: readonly Readonly<{
|
|
32
|
+
id: "veterinary-immunization-candidate-example";
|
|
33
|
+
system: "http://www.whocc.no/atcvet";
|
|
34
|
+
code: "QI07AA02";
|
|
35
|
+
display: "Inactivated rabies virus vaccines";
|
|
36
|
+
}>[];
|
|
37
|
+
}>;
|
|
38
|
+
claims: Readonly<{
|
|
39
|
+
code: "Immunization.vaccine-code";
|
|
40
|
+
display: string;
|
|
41
|
+
localText: string;
|
|
42
|
+
}>;
|
|
43
|
+
expected: Readonly<{
|
|
44
|
+
resourceType: string;
|
|
45
|
+
id: string;
|
|
46
|
+
meta: Readonly<{
|
|
47
|
+
claims: Readonly<Record<string, string>>;
|
|
48
|
+
codingProposals?: readonly import("fhir-data-utils-ts/coding-review-flat-claims").FlatClaimCodingProposal[];
|
|
49
|
+
}>;
|
|
50
|
+
}>;
|
|
51
|
+
}>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { buildFlatClaimCodingReviewResource, deriveCodingDisplayClaim, deriveCodingLocalTextClaim, } from 'fhir-data-utils-ts/coding-review-flat-claims';
|
|
2
|
+
import { VeterinaryClinicalTerminologySystems } from './clinical-terminology.js';
|
|
3
|
+
const IMMUNIZATION_RESOURCE_TYPE = 'Immunization';
|
|
4
|
+
const IMMUNIZATION_VACCINE_CODE_CLAIM = `${IMMUNIZATION_RESOURCE_TYPE}.vaccine-code`;
|
|
5
|
+
/** Governed claim coordinates reused by Vet gateways, portals and assistants. */
|
|
6
|
+
export const VeterinaryImmunizationCodingReviewClaims = Object.freeze({
|
|
7
|
+
code: IMMUNIZATION_VACCINE_CODE_CLAIM,
|
|
8
|
+
display: deriveCodingDisplayClaim(IMMUNIZATION_VACCINE_CODE_CLAIM),
|
|
9
|
+
localText: deriveCodingLocalTextClaim(IMMUNIZATION_VACCINE_CODE_CLAIM),
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Builds an unconfirmed veterinary Immunization coding review from text spoken,
|
|
13
|
+
* typed or imported by a channel. The neutral helper owns proposal placement;
|
|
14
|
+
* this wrapper contributes veterinary resource coordinates and ATCvet policy.
|
|
15
|
+
*/
|
|
16
|
+
export function buildVeterinaryImmunizationCodingReview(input) {
|
|
17
|
+
const candidates = input.candidates.map((candidate) => {
|
|
18
|
+
if (candidate.system !== VeterinaryClinicalTerminologySystems.AtcVet) {
|
|
19
|
+
throw new TypeError('veterinary_immunization_candidate_system_invalid');
|
|
20
|
+
}
|
|
21
|
+
return candidate;
|
|
22
|
+
});
|
|
23
|
+
return buildFlatClaimCodingReviewResource({
|
|
24
|
+
resourceType: IMMUNIZATION_RESOURCE_TYPE,
|
|
25
|
+
resourceId: input.entryId,
|
|
26
|
+
targetClaim: VeterinaryImmunizationCodingReviewClaims.code,
|
|
27
|
+
localText: input.localText,
|
|
28
|
+
language: input.language,
|
|
29
|
+
baseClaims: {
|
|
30
|
+
'Immunization.status': 'completed',
|
|
31
|
+
'Immunization.patient': input.animalReference,
|
|
32
|
+
'Immunization.date': input.administrationDate,
|
|
33
|
+
},
|
|
34
|
+
proposalId: input.proposalId,
|
|
35
|
+
candidates,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const EXAMPLE_ENTRY_ID = '00000000-0000-4000-8000-000000000201';
|
|
39
|
+
const EXAMPLE_ANIMAL_ID = '00000000-0000-4000-8000-000000000202';
|
|
40
|
+
const EXAMPLE_INPUT = Object.freeze({
|
|
41
|
+
entryId: EXAMPLE_ENTRY_ID,
|
|
42
|
+
animalReference: `Patient/${EXAMPLE_ANIMAL_ID}`,
|
|
43
|
+
administrationDate: '2024-05-23',
|
|
44
|
+
localText: 'vacuna contra la rabia',
|
|
45
|
+
language: 'es-ES',
|
|
46
|
+
proposalId: 'veterinary-immunization-proposal-example',
|
|
47
|
+
candidates: Object.freeze([Object.freeze({
|
|
48
|
+
id: 'veterinary-immunization-candidate-example',
|
|
49
|
+
system: VeterinaryClinicalTerminologySystems.AtcVet,
|
|
50
|
+
code: 'QI07AA02',
|
|
51
|
+
display: 'Inactivated rabies virus vaccines',
|
|
52
|
+
})]),
|
|
53
|
+
});
|
|
54
|
+
/** Package-owned synthetic example for assistants, portals and downstream tests. */
|
|
55
|
+
export const VETERINARY_IMMUNIZATION_CODING_REVIEW_EXAMPLE = Object.freeze({
|
|
56
|
+
input: EXAMPLE_INPUT,
|
|
57
|
+
claims: VeterinaryImmunizationCodingReviewClaims,
|
|
58
|
+
expected: buildVeterinaryImmunizationCodingReview(EXAMPLE_INPUT),
|
|
59
|
+
});
|
|
@@ -39,5 +39,5 @@ export declare function confirmVeterinaryImmunizationDraft(draft: VeterinaryImmu
|
|
|
39
39
|
export declare function materializeVeterinaryImmunizationDraft(draft: VeterinaryImmunizationDraft, context: Readonly<{
|
|
40
40
|
entryId: string;
|
|
41
41
|
animalReference: string;
|
|
42
|
-
performerReference
|
|
42
|
+
performerReference?: string;
|
|
43
43
|
}>): readonly FlatClaimResourceEntry[];
|
|
@@ -46,14 +46,19 @@ export function materializeVeterinaryImmunizationDraft(draft, context) {
|
|
|
46
46
|
return buildVeterinaryImmunizationFlatGraph({
|
|
47
47
|
entryId: required(context.entryId, 'veterinary_immunization_entry_id_required'),
|
|
48
48
|
animalReference: required(context.animalReference, 'veterinary_immunization_animal_reference_required'),
|
|
49
|
-
|
|
49
|
+
...(context.performerReference ? {
|
|
50
|
+
performerReference: required(context.performerReference, 'veterinary_immunization_performer_invalid'),
|
|
51
|
+
} : {}),
|
|
50
52
|
administrationDate: draft.administrationDate,
|
|
51
53
|
vaccineCode: draft.vaccineCode,
|
|
52
54
|
targetDiseases: draft.targetDiseases,
|
|
53
55
|
...(draft.routeCode ? { route: { system: 'http://terminology.hl7.org/CodeSystem/v3-RouteOfAdministration', code: draft.routeCode } } : {}),
|
|
54
56
|
...(draft.siteCode ? { site: { system: 'http://terminology.hl7.org/CodeSystem/v3-ActSite', code: draft.siteCode } } : {}),
|
|
55
57
|
...(draft.doseValue ? { dose: { value: draft.doseValue, ...(draft.doseUnit ? { unit: draft.doseUnit } : {}) } } : {}),
|
|
56
|
-
...(draft.nextDoseDate ? {
|
|
58
|
+
...(draft.nextDoseDate ? {
|
|
59
|
+
nextDoseDate: draft.nextDoseDate,
|
|
60
|
+
recommendationDate: required(draft.confirmedAt, 'veterinary_immunization_confirmation_time_required'),
|
|
61
|
+
} : {}),
|
|
57
62
|
...(hasMedication ? { medication: {
|
|
58
63
|
entryId: `${context.entryId}-medication`,
|
|
59
64
|
productName: draft.productName || draft.vaccineCode.display || `${draft.vaccineCode.system}|${draft.vaccineCode.code}`,
|
|
@@ -75,6 +80,7 @@ function coding(value, error) {
|
|
|
75
80
|
return Object.freeze({
|
|
76
81
|
system: required(candidate.system, error), code: required(candidate.code, error),
|
|
77
82
|
...(text(candidate.display) ? { display: text(candidate.display) } : {}),
|
|
83
|
+
...(text(candidate.text) ? { text: text(candidate.text) } : {}),
|
|
78
84
|
});
|
|
79
85
|
}
|
|
80
86
|
function date(value, error) {
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { type FlatClaimResourceEntry } from 'sos-data-utils-ts/flat-claim-resource-graph';
|
|
2
|
+
import { type ImmunizationReminderChannel } from 'sos-data-utils-ts/immunization-reminder-plan';
|
|
2
3
|
export type VeterinaryImmunizationCoding = Readonly<{
|
|
3
4
|
system: string;
|
|
4
5
|
code: string;
|
|
5
6
|
display?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Canonical requested-language term entered or selected by the channel.
|
|
9
|
+
* A neutral coding proposal targets `Immunization.vaccine-code`; accepting
|
|
10
|
+
* it must preserve this value as `Immunization.vaccine-code-text`.
|
|
11
|
+
*/
|
|
12
|
+
text?: string;
|
|
6
13
|
}>;
|
|
7
14
|
export type VeterinaryImmunizationFlatInput = Readonly<{
|
|
8
15
|
entryId: string;
|
|
@@ -10,7 +17,8 @@ export type VeterinaryImmunizationFlatInput = Readonly<{
|
|
|
10
17
|
animalReference: string;
|
|
11
18
|
administrationDate: string;
|
|
12
19
|
vaccineCode: VeterinaryImmunizationCoding;
|
|
13
|
-
|
|
20
|
+
/** Present only when the administering professional is known. */
|
|
21
|
+
performerReference?: string;
|
|
14
22
|
targetDiseases?: readonly VeterinaryImmunizationCoding[];
|
|
15
23
|
route?: VeterinaryImmunizationCoding;
|
|
16
24
|
site?: VeterinaryImmunizationCoding;
|
|
@@ -19,6 +27,10 @@ export type VeterinaryImmunizationFlatInput = Readonly<{
|
|
|
19
27
|
unit?: string;
|
|
20
28
|
}>;
|
|
21
29
|
nextDoseDate?: string;
|
|
30
|
+
/** FHIR dateTime when the recommendation was created; required with nextDoseDate. */
|
|
31
|
+
recommendationDate?: string;
|
|
32
|
+
/** Ordered candidates only; dispatch rechecks current preference and Consent. */
|
|
33
|
+
reminderChannels?: readonly ImmunizationReminderChannel[];
|
|
22
34
|
medication?: Readonly<{
|
|
23
35
|
entryId: string;
|
|
24
36
|
productName: string;
|
|
@@ -36,7 +48,10 @@ export type VeterinaryImmunizationFlatInput = Readonly<{
|
|
|
36
48
|
attachmentEntryIds?: readonly string[];
|
|
37
49
|
}>;
|
|
38
50
|
/**
|
|
39
|
-
* Creates a version-neutral flat graph
|
|
51
|
+
* Creates a version-neutral flat graph after coding review is confirmed.
|
|
52
|
+
* Unconfirmed `meta.codingProposals[]` use the neutral `fhir-data-utils-ts`
|
|
53
|
+
* contract and remain on the same resource, outside `meta.claims`.
|
|
54
|
+
* SearchParameter names are preferred
|
|
40
55
|
* (`Immunization.date`, `Medication.expiration-date`) and product evidence is
|
|
41
56
|
* kept in Medication instead of overloading credential validity.
|
|
42
57
|
*/
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { buildDocumentReferenceFlatEntry, buildFlatClaimResourceEntry, linkFlatClaimResourceEntries, } from 'sos-data-utils-ts/flat-claim-resource-graph';
|
|
2
|
+
import { ImmunizationReminderChannels, buildImmunizationReminderTasks, } from 'sos-data-utils-ts/immunization-reminder-plan';
|
|
2
3
|
/**
|
|
3
|
-
* Creates a version-neutral flat graph
|
|
4
|
+
* Creates a version-neutral flat graph after coding review is confirmed.
|
|
5
|
+
* Unconfirmed `meta.codingProposals[]` use the neutral `fhir-data-utils-ts`
|
|
6
|
+
* contract and remain on the same resource, outside `meta.claims`.
|
|
7
|
+
* SearchParameter names are preferred
|
|
4
8
|
* (`Immunization.date`, `Medication.expiration-date`) and product evidence is
|
|
5
9
|
* kept in Medication instead of overloading credential validity.
|
|
6
10
|
*/
|
|
@@ -11,14 +15,24 @@ export function buildVeterinaryImmunizationFlatGraph(input) {
|
|
|
11
15
|
'Immunization.patient': required(input.animalReference, 'veterinary_immunization_animal_reference_required'),
|
|
12
16
|
'Immunization.date': isoDate(input.administrationDate, 'veterinary_immunization_date_invalid'),
|
|
13
17
|
'Immunization.vaccine-code': vaccineCode,
|
|
14
|
-
'Immunization.performer': required(input.performerReference, 'veterinary_immunization_performer_required'),
|
|
15
18
|
};
|
|
16
19
|
if (input.identifier)
|
|
17
20
|
claims['Immunization.identifier'] = required(input.identifier, 'veterinary_immunization_identifier_invalid');
|
|
18
21
|
if (input.vaccineCode.display)
|
|
19
22
|
claims['Immunization.vaccine-code-display'] = input.vaccineCode.display.trim();
|
|
20
|
-
if (input.
|
|
23
|
+
if (input.vaccineCode.text)
|
|
24
|
+
claims['Immunization.vaccine-code-text'] = input.vaccineCode.text.trim();
|
|
25
|
+
if (input.performerReference)
|
|
26
|
+
claims['Immunization.performer'] = required(input.performerReference, 'veterinary_immunization_performer_invalid');
|
|
27
|
+
if (input.targetDiseases?.length) {
|
|
21
28
|
claims['Immunization.target-disease'] = input.targetDiseases.map(codingToken).join(',');
|
|
29
|
+
if (input.targetDiseases.some(({ display }) => display?.trim())) {
|
|
30
|
+
claims['Immunization.target-disease-display'] = joinCsv(input.targetDiseases.map(({ display }) => display?.trim() ?? ''));
|
|
31
|
+
}
|
|
32
|
+
if (input.targetDiseases.some(({ text }) => text?.trim())) {
|
|
33
|
+
claims['Immunization.target-disease-text'] = joinCsv(input.targetDiseases.map(({ text }) => text?.trim() ?? ''));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
22
36
|
if (input.route)
|
|
23
37
|
claims['Immunization.route'] = codingToken(input.route);
|
|
24
38
|
if (input.site)
|
|
@@ -30,18 +44,34 @@ export function buildVeterinaryImmunizationFlatGraph(input) {
|
|
|
30
44
|
}
|
|
31
45
|
const immunization = buildFlatClaimResourceEntry({ entryId: input.entryId, resourceType: 'Immunization', claims });
|
|
32
46
|
const children = [];
|
|
47
|
+
let recommendationId;
|
|
48
|
+
let reminderTasks = [];
|
|
33
49
|
if (input.medication)
|
|
34
50
|
children.push(buildMedicationEntry(input.medication));
|
|
35
51
|
if (input.nextDoseDate) {
|
|
52
|
+
recommendationId = `${input.entryId}-recommendation`;
|
|
36
53
|
children.push(buildFlatClaimResourceEntry({
|
|
37
|
-
entryId:
|
|
54
|
+
entryId: recommendationId,
|
|
38
55
|
resourceType: 'ImmunizationRecommendation',
|
|
39
56
|
claims: {
|
|
40
57
|
'ImmunizationRecommendation.patient': input.animalReference,
|
|
41
|
-
|
|
58
|
+
// FHIR date is when the forecast was created, not when coverage ends.
|
|
59
|
+
'ImmunizationRecommendation.date': isoDate(required(input.recommendationDate, 'veterinary_immunization_recommendation_date_required'), 'veterinary_immunization_recommendation_date_invalid'),
|
|
42
60
|
'ImmunizationRecommendation.vaccine-code': vaccineCode,
|
|
61
|
+
'ImmunizationRecommendation.forecast-status': 'http://terminology.hl7.org/CodeSystem/immunization-recommendation-status|due',
|
|
62
|
+
'ImmunizationRecommendation.date-criterion-code': 'http://loinc.org|30980-7',
|
|
63
|
+
'ImmunizationRecommendation.date-criterion-value': isoDate(input.nextDoseDate, 'veterinary_immunization_next_dose_date_invalid'),
|
|
64
|
+
'ImmunizationRecommendation.supporting-immunization': `Immunization/${input.entryId}`,
|
|
43
65
|
},
|
|
44
66
|
}));
|
|
67
|
+
reminderTasks = buildImmunizationReminderTasks({
|
|
68
|
+
entryIdPrefix: recommendationId,
|
|
69
|
+
recommendationReference: `ImmunizationRecommendation/${recommendationId}`,
|
|
70
|
+
subjectReference: input.animalReference,
|
|
71
|
+
coverageEndDate: input.nextDoseDate,
|
|
72
|
+
channelCandidates: input.reminderChannels ?? ImmunizationReminderChannels,
|
|
73
|
+
});
|
|
74
|
+
children.push(...reminderTasks);
|
|
45
75
|
}
|
|
46
76
|
for (const attachment of input.attachments ?? []) {
|
|
47
77
|
if (attachment.resourceType !== 'DocumentReference')
|
|
@@ -52,11 +82,18 @@ export function buildVeterinaryImmunizationFlatGraph(input) {
|
|
|
52
82
|
const childEntryIds = [
|
|
53
83
|
...(input.medication ? [input.medication.entryId] : []),
|
|
54
84
|
...(input.nextDoseDate ? [`${input.entryId}-recommendation`] : []),
|
|
85
|
+
...(input.attachments ?? []).map(({ entryId }) => entryId),
|
|
55
86
|
...(input.attachmentEntryIds ?? []),
|
|
56
87
|
];
|
|
57
|
-
|
|
88
|
+
const linkedImmunization = childEntryIds.length
|
|
58
89
|
? linkFlatClaimResourceEntries(graph, { parentEntryId: input.entryId, childEntryIds })
|
|
59
90
|
: graph;
|
|
91
|
+
return recommendationId && reminderTasks.length
|
|
92
|
+
? linkFlatClaimResourceEntries(linkedImmunization, {
|
|
93
|
+
parentEntryId: recommendationId,
|
|
94
|
+
childEntryIds: reminderTasks.map(({ entryId }) => entryId),
|
|
95
|
+
})
|
|
96
|
+
: linkedImmunization;
|
|
60
97
|
}
|
|
61
98
|
function buildMedicationEntry(input) {
|
|
62
99
|
const claims = {
|
|
@@ -91,23 +128,29 @@ export function exportVeterinaryImmunizationFlatGraph(graph, release) {
|
|
|
91
128
|
function exportEntry(entry, release, byReference) {
|
|
92
129
|
const claims = entry.claims;
|
|
93
130
|
if (entry.resourceType === 'Immunization') {
|
|
94
|
-
const vaccineCode = codeableConcept(claims['Immunization.vaccine-code'], claims['Immunization.vaccine-code-display']);
|
|
131
|
+
const vaccineCode = codeableConcept(claims['Immunization.vaccine-code'], claims['Immunization.vaccine-code-display'], claims['Immunization.vaccine-code-text']);
|
|
95
132
|
const children = splitCsv(claims['Immunization.contained-reference-list']).map((reference) => byReference.get(reference)).filter(Boolean);
|
|
96
133
|
const medication = children.find((child) => child?.resourceType === 'Medication');
|
|
97
134
|
const resource = {
|
|
98
135
|
resourceType: 'Immunization', id: entry.entryId, status: claims['Immunization.status'],
|
|
99
136
|
vaccineCode, patient: { reference: claims['Immunization.patient'] },
|
|
100
137
|
occurrenceDateTime: claims['Immunization.date'],
|
|
101
|
-
performer: [{ actor: { reference: claims['Immunization.performer'] } }],
|
|
102
138
|
};
|
|
139
|
+
if (claims['Immunization.performer'])
|
|
140
|
+
resource.performer = [{ actor: { reference: claims['Immunization.performer'] } }];
|
|
103
141
|
if (claims['Immunization.identifier'])
|
|
104
142
|
resource.identifier = [{ value: claims['Immunization.identifier'] }];
|
|
105
143
|
if (claims['Immunization.route'])
|
|
106
144
|
resource.route = codeableConcept(claims['Immunization.route']);
|
|
107
145
|
if (claims['Immunization.site'])
|
|
108
146
|
resource.site = codeableConcept(claims['Immunization.site']);
|
|
109
|
-
if (claims['Immunization.target-disease'])
|
|
110
|
-
|
|
147
|
+
if (claims['Immunization.target-disease']) {
|
|
148
|
+
const displays = splitCsvKeepingEmpty(claims['Immunization.target-disease-display']);
|
|
149
|
+
const texts = splitCsvKeepingEmpty(claims['Immunization.target-disease-text']);
|
|
150
|
+
resource.protocolApplied = [{
|
|
151
|
+
targetDisease: splitCsv(claims['Immunization.target-disease']).map((code, index) => (codeableConcept(code, displays[index], texts[index]))),
|
|
152
|
+
}];
|
|
153
|
+
}
|
|
111
154
|
if (medication && release !== 'R4')
|
|
112
155
|
resource.administeredProduct = { reference: { reference: medication.reference } };
|
|
113
156
|
return resource;
|
|
@@ -117,7 +160,7 @@ function exportEntry(entry, release, byReference) {
|
|
|
117
160
|
const expirationDate = claims['Medication.expiration-date'];
|
|
118
161
|
const resource = {
|
|
119
162
|
resourceType: 'Medication', id: entry.entryId,
|
|
120
|
-
code: codeableConcept(claims['Medication.code'], claims['Medication.code-text']),
|
|
163
|
+
code: codeableConcept(claims['Medication.code'], undefined, claims['Medication.code-text']),
|
|
121
164
|
};
|
|
122
165
|
if (claims['Medication.identifier'])
|
|
123
166
|
resource.identifier = splitCsv(claims['Medication.identifier']).map(identifierFromToken);
|
|
@@ -132,7 +175,15 @@ function exportEntry(entry, release, byReference) {
|
|
|
132
175
|
resourceType: 'ImmunizationRecommendation', id: entry.entryId,
|
|
133
176
|
patient: { reference: claims['ImmunizationRecommendation.patient'] },
|
|
134
177
|
date: claims['ImmunizationRecommendation.date'],
|
|
135
|
-
recommendation: [{
|
|
178
|
+
recommendation: [{
|
|
179
|
+
vaccineCode: [codeableConcept(claims['ImmunizationRecommendation.vaccine-code'])],
|
|
180
|
+
forecastStatus: codeableConcept(claims['ImmunizationRecommendation.forecast-status']),
|
|
181
|
+
dateCriterion: [{
|
|
182
|
+
code: codeableConcept(claims['ImmunizationRecommendation.date-criterion-code']),
|
|
183
|
+
value: claims['ImmunizationRecommendation.date-criterion-value'],
|
|
184
|
+
}],
|
|
185
|
+
supportingImmunization: [{ reference: claims['ImmunizationRecommendation.supporting-immunization'] }],
|
|
186
|
+
}],
|
|
136
187
|
};
|
|
137
188
|
if (entry.resourceType === 'DocumentReference')
|
|
138
189
|
return {
|
|
@@ -146,12 +197,15 @@ function exportEntry(entry, release, byReference) {
|
|
|
146
197
|
};
|
|
147
198
|
return { resourceType: entry.resourceType, id: entry.entryId, meta: { claims: { ...claims } } };
|
|
148
199
|
}
|
|
149
|
-
function codeableConcept(token, display) {
|
|
200
|
+
function codeableConcept(token, display, text) {
|
|
150
201
|
const value = required(token, 'veterinary_coding_required');
|
|
151
202
|
const separator = value.lastIndexOf('|');
|
|
152
203
|
if (separator <= 0 || separator === value.length - 1)
|
|
153
|
-
return { text: display || value };
|
|
154
|
-
return {
|
|
204
|
+
return { text: text || display || value };
|
|
205
|
+
return {
|
|
206
|
+
coding: [{ system: value.slice(0, separator), code: value.slice(separator + 1), ...(display ? { display } : {}) }],
|
|
207
|
+
...(text ? { text } : {}),
|
|
208
|
+
};
|
|
155
209
|
}
|
|
156
210
|
function identifierFromToken(token) {
|
|
157
211
|
const separator = token.lastIndexOf('|');
|
|
@@ -172,7 +226,36 @@ function required(value, error) {
|
|
|
172
226
|
return value.trim();
|
|
173
227
|
}
|
|
174
228
|
function splitCsv(value) {
|
|
175
|
-
return value
|
|
229
|
+
return splitCsvKeepingEmpty(value).filter(Boolean);
|
|
230
|
+
}
|
|
231
|
+
function splitCsvKeepingEmpty(value) {
|
|
232
|
+
if (value === undefined)
|
|
233
|
+
return [];
|
|
234
|
+
const values = [];
|
|
235
|
+
let current = '';
|
|
236
|
+
let quoted = false;
|
|
237
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
238
|
+
const character = value[index];
|
|
239
|
+
if (character === '"' && quoted && value[index + 1] === '"') {
|
|
240
|
+
current += '"';
|
|
241
|
+
index += 1;
|
|
242
|
+
}
|
|
243
|
+
else if (character === '"')
|
|
244
|
+
quoted = !quoted;
|
|
245
|
+
else if (character === ',' && !quoted) {
|
|
246
|
+
values.push(current.trim());
|
|
247
|
+
current = '';
|
|
248
|
+
}
|
|
249
|
+
else
|
|
250
|
+
current += character;
|
|
251
|
+
}
|
|
252
|
+
values.push(current.trim());
|
|
253
|
+
return values;
|
|
254
|
+
}
|
|
255
|
+
function joinCsv(values) {
|
|
256
|
+
return values.map((value) => value.includes(',') || value.includes('"')
|
|
257
|
+
? `"${value.replaceAll('"', '""')}"`
|
|
258
|
+
: value).join(',');
|
|
176
259
|
}
|
|
177
260
|
function uniqueEntries(entries) {
|
|
178
261
|
const byId = new Map();
|
|
@@ -194,9 +277,13 @@ export const NALA_VACCINATION_FLAT_GRAPH_TEST_DATA = uniqueEntries([
|
|
|
194
277
|
...buildVeterinaryImmunizationFlatGraph({
|
|
195
278
|
entryId: 'nala-rabies', animalReference: 'Patient/nala', administrationDate: '2024-05-23',
|
|
196
279
|
performerReference: 'PractitionerRole/certificate-veterinarian',
|
|
197
|
-
vaccineCode: {
|
|
198
|
-
|
|
280
|
+
vaccineCode: {
|
|
281
|
+
system: atcVet, code: 'QI07AA02', display: 'Inactivated rabies virus vaccines',
|
|
282
|
+
text: 'Vacuna contra el virus de la rabia',
|
|
283
|
+
},
|
|
284
|
+
targetDiseases: [{ system: 'http://snomed.info/sct', code: '14168008', display: 'Rabies', text: 'Rabia' }],
|
|
199
285
|
nextDoseDate: '2027-05-23',
|
|
286
|
+
recommendationDate: '2026-09-20T12:00:00.000Z',
|
|
200
287
|
medication: {
|
|
201
288
|
entryId: 'nala-rabies-product', productName: 'Imrab 3 TF',
|
|
202
289
|
productCode: { system: atcVet, code: 'QI07AA02' }, manufacturer: 'Boehringer Ingelheim',
|
|
@@ -213,12 +300,14 @@ export const NALA_VACCINATION_FLAT_GRAPH_TEST_DATA = uniqueEntries([
|
|
|
213
300
|
entryId: 'nala-da2plp', animalReference: 'Patient/nala', administrationDate: '2024-05-23',
|
|
214
301
|
performerReference: 'PractitionerRole/certificate-veterinarian',
|
|
215
302
|
vaccineCode: { system: atcVet, code: 'QI07AI02', display: 'Canine viral and bacterial combination vaccines' },
|
|
216
|
-
nextDoseDate: '2025-05-23',
|
|
303
|
+
nextDoseDate: '2025-05-23', recommendationDate: '2026-09-20T12:00:00.000Z',
|
|
304
|
+
attachments: [certificate], attachmentEntryIds: [certificate.entryId],
|
|
217
305
|
}),
|
|
218
306
|
...buildVeterinaryImmunizationFlatGraph({
|
|
219
307
|
entryId: 'nala-lyme', animalReference: 'Patient/nala', administrationDate: '2024-05-23',
|
|
220
308
|
performerReference: 'PractitionerRole/certificate-veterinarian',
|
|
221
309
|
vaccineCode: { system: atcVet, code: 'QI07AB04', display: 'Borrelia vaccines' },
|
|
222
|
-
nextDoseDate: '2025-05-23',
|
|
310
|
+
nextDoseDate: '2025-05-23', recommendationDate: '2026-09-20T12:00:00.000Z',
|
|
311
|
+
attachments: [certificate], attachmentEntryIds: [certificate.entryId],
|
|
223
312
|
}),
|
|
224
313
|
]);
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './group.js';
|
|
|
11
11
|
export * from './health-dcat.js';
|
|
12
12
|
export * from './immunization.js';
|
|
13
13
|
export * from './immunization-flat-claims.js';
|
|
14
|
+
export * from './immunization-coding-review.js';
|
|
14
15
|
export * from './immunization-draft.js';
|
|
15
16
|
export * from './international-health-card.js';
|
|
16
17
|
export * from './index-projection-tags.js';
|
|
@@ -20,6 +21,7 @@ export * from './lost-animal-access.js';
|
|
|
20
21
|
export * from './organization-application.js';
|
|
21
22
|
export * from './payment.js';
|
|
22
23
|
export * from './place-service-directory.js';
|
|
24
|
+
export * from './professional-access-policy.js';
|
|
23
25
|
export * from './provenance.js';
|
|
24
26
|
export * from './research-study.js';
|
|
25
27
|
export * from './sectors.js';
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export * from './group.js';
|
|
|
11
11
|
export * from './health-dcat.js';
|
|
12
12
|
export * from './immunization.js';
|
|
13
13
|
export * from './immunization-flat-claims.js';
|
|
14
|
+
export * from './immunization-coding-review.js';
|
|
14
15
|
export * from './immunization-draft.js';
|
|
15
16
|
export * from './international-health-card.js';
|
|
16
17
|
export * from './index-projection-tags.js';
|
|
@@ -20,6 +21,7 @@ export * from './lost-animal-access.js';
|
|
|
20
21
|
export * from './organization-application.js';
|
|
21
22
|
export * from './payment.js';
|
|
22
23
|
export * from './place-service-directory.js';
|
|
24
|
+
export * from './professional-access-policy.js';
|
|
23
25
|
export * from './provenance.js';
|
|
24
26
|
export * from './research-study.js';
|
|
25
27
|
export * from './sectors.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vet-data-utils-ts",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.36",
|
|
4
4
|
"description": "Browser-safe governed VetChain data contracts",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Connecting Solution & Applications Ltd",
|
|
@@ -60,6 +60,10 @@
|
|
|
60
60
|
"types": "./dist/immunization-flat-claims.d.ts",
|
|
61
61
|
"default": "./dist/immunization-flat-claims.js"
|
|
62
62
|
},
|
|
63
|
+
"./immunization-coding-review": {
|
|
64
|
+
"types": "./dist/immunization-coding-review.d.ts",
|
|
65
|
+
"default": "./dist/immunization-coding-review.js"
|
|
66
|
+
},
|
|
63
67
|
"./immunization-draft": {
|
|
64
68
|
"types": "./dist/immunization-draft.d.ts",
|
|
65
69
|
"default": "./dist/immunization-draft.js"
|
|
@@ -100,6 +104,10 @@
|
|
|
100
104
|
"types": "./dist/place-service-directory.d.ts",
|
|
101
105
|
"default": "./dist/place-service-directory.js"
|
|
102
106
|
},
|
|
107
|
+
"./professional-access-policy": {
|
|
108
|
+
"types": "./dist/professional-access-policy.d.ts",
|
|
109
|
+
"default": "./dist/professional-access-policy.js"
|
|
110
|
+
},
|
|
103
111
|
"./research-study": {
|
|
104
112
|
"types": "./dist/research-study.d.ts",
|
|
105
113
|
"default": "./dist/research-study.js"
|
|
@@ -149,9 +157,10 @@
|
|
|
149
157
|
"typescript": "^5.5.4"
|
|
150
158
|
},
|
|
151
159
|
"dependencies": {
|
|
160
|
+
"fhir-data-utils-ts": "0.2.4",
|
|
152
161
|
"gdc-common-utils-ts": "2.9.12",
|
|
153
162
|
"pako": "^2.2.0",
|
|
154
|
-
"sos-data-utils-ts": "0.3.
|
|
163
|
+
"sos-data-utils-ts": "0.3.6"
|
|
155
164
|
},
|
|
156
165
|
"engines": {
|
|
157
166
|
"node": ">=20"
|