gdc-common-utils-ts 1.14.0 → 1.14.2
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 +4 -0
- package/dist/constants/healthcare.d.ts +274 -0
- package/dist/constants/healthcare.js +212 -2
- package/dist/examples/communication-bundle-session.d.ts +22 -0
- package/dist/examples/communication-bundle-session.js +81 -0
- package/dist/examples/index.d.ts +1 -0
- package/dist/examples/index.js +1 -0
- package/dist/examples/shared.d.ts +8 -0
- package/dist/examples/shared.js +8 -0
- package/dist/i18n/role-codes.i18n.d.ts +4 -0
- package/dist/i18n/role-codes.i18n.js +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/bundle.d.ts +3 -0
- package/dist/models/interoperable-claims/communication-claims.d.ts +24 -0
- package/dist/models/interoperable-claims/communication-claims.js +24 -0
- package/dist/models/interoperable-claims/medication-statement-claims.d.ts +5 -0
- package/dist/models/interoperable-claims/medication-statement-claims.js +5 -0
- package/dist/utils/bundle-query.d.ts +35 -0
- package/dist/utils/bundle-query.js +178 -0
- package/dist/utils/clinical-resource-view.d.ts +55 -0
- package/dist/utils/clinical-resource-view.js +291 -0
- package/dist/utils/communication-bundle-session.d.ts +110 -0
- package/dist/utils/communication-bundle-session.js +330 -0
- package/dist/utils/consent-claim-helpers.d.ts +66 -0
- package/dist/utils/consent-claim-helpers.js +178 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/medication-claim-helpers.d.ts +47 -0
- package/dist/utils/medication-claim-helpers.js +104 -0
- package/package.json +1 -1
|
@@ -1,11 +1,31 @@
|
|
|
1
|
-
import { LOINC_SYSTEM_URL } from '../models/clinical-sections.js';
|
|
2
|
-
|
|
1
|
+
import { LOINC_SYSTEM_URL, loincI18nKey } from '../models/clinical-sections.js';
|
|
2
|
+
import { clinicalDocTypes, clinicalSectionAdditional, clinicalSectionsBase, } from '../models/clinical-sections.en.js';
|
|
3
|
+
import { HL7_CODING_SYSTEM_PERSONAL_RELATIONSHIP, HL7_CODING_SYSTEM_V3_ROLE_CODE, HL7_PERSONAL_RELATIONSHIP_ROLES, HL7_V3_ROLE_CODE_LEGAL_REPRESENTATIVE, } from './hl7-roles.js';
|
|
4
|
+
import { DataspaceSectors } from './sectors.js';
|
|
5
|
+
export const ISCO08_CODING_SYSTEM = 'org.ilo.isco';
|
|
6
|
+
export const ISCO08_I18N_NAMESPACE = 'org.ilo.isco-08';
|
|
7
|
+
export const HealthcareRoleFamilies = Object.freeze({
|
|
8
|
+
ProfessionalOccupationIsco08: 'professionalOccupationIsco08',
|
|
9
|
+
PersonalRelationshipHl7: 'personalRelationshipHl7',
|
|
10
|
+
LegalRepresentativeHl7: 'legalRepresentativeHl7',
|
|
11
|
+
});
|
|
12
|
+
function defineSection(code, titleEn) {
|
|
3
13
|
return Object.freeze({
|
|
4
14
|
system: LOINC_SYSTEM_URL,
|
|
5
15
|
code,
|
|
6
16
|
claim: `LOINC|${code}`,
|
|
17
|
+
i18nKey: loincI18nKey(code),
|
|
18
|
+
titleEn,
|
|
7
19
|
});
|
|
8
20
|
}
|
|
21
|
+
export const HealthcareSectionFamilies = Object.freeze({
|
|
22
|
+
Summary: 'summary',
|
|
23
|
+
Management: 'management',
|
|
24
|
+
SubjectMatterDomain: 'subjectMatterDomain',
|
|
25
|
+
});
|
|
26
|
+
function buildSectionCatalogByCode(source) {
|
|
27
|
+
return Object.freeze(Object.fromEntries(Object.entries(source).map(([code, titleEn]) => [code, defineSection(code, titleEn)])));
|
|
28
|
+
}
|
|
9
29
|
export const HealthcareBasicSections = Object.freeze({
|
|
10
30
|
PatientSummaryDocument: defineSection('60591-5'),
|
|
11
31
|
AllergiesAndIntolerances: defineSection('48765-2'),
|
|
@@ -32,6 +52,31 @@ export const HealthcareAllSections = Object.freeze({
|
|
|
32
52
|
...HealthcareBasicSections,
|
|
33
53
|
...HealthcareAdditionalSections,
|
|
34
54
|
});
|
|
55
|
+
/**
|
|
56
|
+
* Full section families sourced from the existing section catalogs in
|
|
57
|
+
* `models/clinical-sections.en.ts`.
|
|
58
|
+
*
|
|
59
|
+
* Family mapping used by SDK/business layers:
|
|
60
|
+
* - `summary`: IPS/base summary sections.
|
|
61
|
+
* - `management`: kind-of-document and type-of-service oriented sections.
|
|
62
|
+
* - `subjectMatterDomain`: additional service-domain sections.
|
|
63
|
+
*/
|
|
64
|
+
export const HealthcareSectionsByFamily = Object.freeze({
|
|
65
|
+
[HealthcareSectionFamilies.Summary]: buildSectionCatalogByCode(clinicalSectionsBase),
|
|
66
|
+
[HealthcareSectionFamilies.Management]: buildSectionCatalogByCode(clinicalDocTypes),
|
|
67
|
+
[HealthcareSectionFamilies.SubjectMatterDomain]: buildSectionCatalogByCode(clinicalSectionAdditional),
|
|
68
|
+
});
|
|
69
|
+
export const HealthcareAllSectionsByCode = Object.freeze({
|
|
70
|
+
...HealthcareSectionsByFamily[HealthcareSectionFamilies.Summary],
|
|
71
|
+
...HealthcareSectionsByFamily[HealthcareSectionFamilies.Management],
|
|
72
|
+
...HealthcareSectionsByFamily[HealthcareSectionFamilies.SubjectMatterDomain],
|
|
73
|
+
});
|
|
74
|
+
export function getHealthcareSectionByCode(code) {
|
|
75
|
+
return HealthcareAllSectionsByCode[String(code || '').trim()];
|
|
76
|
+
}
|
|
77
|
+
export function getHealthcareSectionsByFamily(family) {
|
|
78
|
+
return HealthcareSectionsByFamily[family];
|
|
79
|
+
}
|
|
35
80
|
export const HealthcareConsentPurposes = Object.freeze({
|
|
36
81
|
Treatment: 'TREAT',
|
|
37
82
|
EmergencyTreatment: 'ETREAT',
|
|
@@ -45,6 +90,7 @@ export const HealthcareActorRoles = Object.freeze({
|
|
|
45
90
|
Physician: 'ISCO-08|2211',
|
|
46
91
|
NursingProfessional: 'ISCO-08|2221',
|
|
47
92
|
Paramedic: 'ISCO-08|2240',
|
|
93
|
+
Veterinarian: 'ISCO-08|2250',
|
|
48
94
|
});
|
|
49
95
|
export const HealthcareActorRoleCodes = Object.freeze({
|
|
50
96
|
Controller: '1120',
|
|
@@ -52,7 +98,171 @@ export const HealthcareActorRoleCodes = Object.freeze({
|
|
|
52
98
|
PhysicianBroad: '221',
|
|
53
99
|
NursingProfessional: '2221',
|
|
54
100
|
Paramedic: '2240',
|
|
101
|
+
Veterinarian: '2250',
|
|
102
|
+
});
|
|
103
|
+
function buildProfessionalIscoRoles() {
|
|
104
|
+
const entries = [
|
|
105
|
+
[
|
|
106
|
+
HealthcareActorRoleCodes.Controller,
|
|
107
|
+
Object.freeze({
|
|
108
|
+
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
109
|
+
codingSystem: ISCO08_CODING_SYSTEM,
|
|
110
|
+
code: HealthcareActorRoleCodes.Controller,
|
|
111
|
+
claim: HealthcareActorRoles.Controller,
|
|
112
|
+
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.Controller}`,
|
|
113
|
+
titleEn: 'Controller',
|
|
114
|
+
}),
|
|
115
|
+
],
|
|
116
|
+
[
|
|
117
|
+
HealthcareActorRoleCodes.Physician,
|
|
118
|
+
Object.freeze({
|
|
119
|
+
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
120
|
+
codingSystem: ISCO08_CODING_SYSTEM,
|
|
121
|
+
code: HealthcareActorRoleCodes.Physician,
|
|
122
|
+
claim: HealthcareActorRoles.Physician,
|
|
123
|
+
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.Physician}`,
|
|
124
|
+
titleEn: 'Physician',
|
|
125
|
+
}),
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
HealthcareActorRoleCodes.NursingProfessional,
|
|
129
|
+
Object.freeze({
|
|
130
|
+
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
131
|
+
codingSystem: ISCO08_CODING_SYSTEM,
|
|
132
|
+
code: HealthcareActorRoleCodes.NursingProfessional,
|
|
133
|
+
claim: HealthcareActorRoles.NursingProfessional,
|
|
134
|
+
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.NursingProfessional}`,
|
|
135
|
+
titleEn: 'Nursing professional',
|
|
136
|
+
}),
|
|
137
|
+
],
|
|
138
|
+
[
|
|
139
|
+
HealthcareActorRoleCodes.Paramedic,
|
|
140
|
+
Object.freeze({
|
|
141
|
+
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
142
|
+
codingSystem: ISCO08_CODING_SYSTEM,
|
|
143
|
+
code: HealthcareActorRoleCodes.Paramedic,
|
|
144
|
+
claim: HealthcareActorRoles.Paramedic,
|
|
145
|
+
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.Paramedic}`,
|
|
146
|
+
titleEn: 'Paramedic',
|
|
147
|
+
}),
|
|
148
|
+
],
|
|
149
|
+
[
|
|
150
|
+
HealthcareActorRoleCodes.Veterinarian,
|
|
151
|
+
Object.freeze({
|
|
152
|
+
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
153
|
+
codingSystem: ISCO08_CODING_SYSTEM,
|
|
154
|
+
code: HealthcareActorRoleCodes.Veterinarian,
|
|
155
|
+
claim: HealthcareActorRoles.Veterinarian,
|
|
156
|
+
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.Veterinarian}`,
|
|
157
|
+
titleEn: 'Veterinarian',
|
|
158
|
+
}),
|
|
159
|
+
],
|
|
160
|
+
];
|
|
161
|
+
return Object.freeze(Object.fromEntries(entries));
|
|
162
|
+
}
|
|
163
|
+
function buildPersonalRelationshipRoles() {
|
|
164
|
+
return Object.freeze(Object.fromEntries(HL7_PERSONAL_RELATIONSHIP_ROLES.map((item) => [
|
|
165
|
+
item.code,
|
|
166
|
+
Object.freeze({
|
|
167
|
+
family: HealthcareRoleFamilies.PersonalRelationshipHl7,
|
|
168
|
+
codingSystem: HL7_CODING_SYSTEM_PERSONAL_RELATIONSHIP,
|
|
169
|
+
code: item.code,
|
|
170
|
+
claim: `v3-PersonalRelationshipRoleType|${item.code}`,
|
|
171
|
+
i18nKey: `org.hl7.v3.personalRelationship.${item.code}`,
|
|
172
|
+
titleEn: item.display,
|
|
173
|
+
definition: item.definition,
|
|
174
|
+
}),
|
|
175
|
+
])));
|
|
176
|
+
}
|
|
177
|
+
function buildLegalRepresentativeRoles() {
|
|
178
|
+
return Object.freeze(Object.fromEntries(HL7_V3_ROLE_CODE_LEGAL_REPRESENTATIVE.map((item) => [
|
|
179
|
+
item.code,
|
|
180
|
+
Object.freeze({
|
|
181
|
+
family: HealthcareRoleFamilies.LegalRepresentativeHl7,
|
|
182
|
+
codingSystem: HL7_CODING_SYSTEM_V3_ROLE_CODE,
|
|
183
|
+
code: item.code,
|
|
184
|
+
claim: `v3-RoleCode|${item.code}`,
|
|
185
|
+
i18nKey: `org.hl7.v3.roleCode.${item.code}`,
|
|
186
|
+
titleEn: item.display,
|
|
187
|
+
definition: item.definition,
|
|
188
|
+
}),
|
|
189
|
+
])));
|
|
190
|
+
}
|
|
191
|
+
export const HealthcareRolesByFamily = Object.freeze({
|
|
192
|
+
[HealthcareRoleFamilies.ProfessionalOccupationIsco08]: buildProfessionalIscoRoles(),
|
|
193
|
+
[HealthcareRoleFamilies.PersonalRelationshipHl7]: buildPersonalRelationshipRoles(),
|
|
194
|
+
[HealthcareRoleFamilies.LegalRepresentativeHl7]: buildLegalRepresentativeRoles(),
|
|
195
|
+
});
|
|
196
|
+
export const HealthcareAllRolesByClaim = Object.freeze(Object.fromEntries(Object.values(HealthcareRolesByFamily)
|
|
197
|
+
.flatMap((catalog) => Object.values(catalog))
|
|
198
|
+
.map((descriptor) => [descriptor.claim, descriptor])));
|
|
199
|
+
function pickRoleCatalogByCodes(catalog, codes) {
|
|
200
|
+
return Object.freeze(Object.fromEntries(codes
|
|
201
|
+
.map((code) => [code, catalog[code]])
|
|
202
|
+
.filter((entry) => Boolean(entry[1]))));
|
|
203
|
+
}
|
|
204
|
+
export const HealthcareProfessionalRoleCodesBySector = Object.freeze({
|
|
205
|
+
[DataspaceSectors.HealthCare]: Object.freeze([
|
|
206
|
+
HealthcareActorRoleCodes.Controller,
|
|
207
|
+
HealthcareActorRoleCodes.Physician,
|
|
208
|
+
HealthcareActorRoleCodes.NursingProfessional,
|
|
209
|
+
HealthcareActorRoleCodes.Paramedic,
|
|
210
|
+
]),
|
|
211
|
+
[DataspaceSectors.HealthResearch]: Object.freeze([
|
|
212
|
+
HealthcareActorRoleCodes.Controller,
|
|
213
|
+
HealthcareActorRoleCodes.Physician,
|
|
214
|
+
]),
|
|
215
|
+
[DataspaceSectors.HealthTech]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
216
|
+
[DataspaceSectors.HealthInsurance]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
217
|
+
[DataspaceSectors.AnimalCare]: Object.freeze([
|
|
218
|
+
HealthcareActorRoleCodes.Controller,
|
|
219
|
+
HealthcareActorRoleCodes.Veterinarian,
|
|
220
|
+
]),
|
|
221
|
+
[DataspaceSectors.AnimalResearch]: Object.freeze([
|
|
222
|
+
HealthcareActorRoleCodes.Controller,
|
|
223
|
+
HealthcareActorRoleCodes.Veterinarian,
|
|
224
|
+
]),
|
|
225
|
+
[DataspaceSectors.AnimalInsurance]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
226
|
+
[DataspaceSectors.AnimalTech]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
227
|
+
[DataspaceSectors.OneHealthResearch]: Object.freeze([
|
|
228
|
+
HealthcareActorRoleCodes.Controller,
|
|
229
|
+
HealthcareActorRoleCodes.Physician,
|
|
230
|
+
HealthcareActorRoleCodes.Veterinarian,
|
|
231
|
+
]),
|
|
232
|
+
[DataspaceSectors.OneHealthTech]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
233
|
+
});
|
|
234
|
+
export const HealthcareProfessionalRolesBySector = Object.freeze({
|
|
235
|
+
[DataspaceSectors.HealthCare]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthCare]),
|
|
236
|
+
[DataspaceSectors.HealthResearch]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthResearch]),
|
|
237
|
+
[DataspaceSectors.HealthTech]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthTech]),
|
|
238
|
+
[DataspaceSectors.HealthInsurance]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthInsurance]),
|
|
239
|
+
[DataspaceSectors.AnimalCare]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalCare]),
|
|
240
|
+
[DataspaceSectors.AnimalResearch]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalResearch]),
|
|
241
|
+
[DataspaceSectors.AnimalInsurance]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalInsurance]),
|
|
242
|
+
[DataspaceSectors.AnimalTech]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalTech]),
|
|
243
|
+
[DataspaceSectors.OneHealthResearch]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.OneHealthResearch]),
|
|
244
|
+
[DataspaceSectors.OneHealthTech]: pickRoleCatalogByCodes(HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08], HealthcareProfessionalRoleCodesBySector[DataspaceSectors.OneHealthTech]),
|
|
55
245
|
});
|
|
246
|
+
export const HealthcareRolesBySector = Object.freeze(Object.fromEntries(Object.values(DataspaceSectors).map((sector) => [
|
|
247
|
+
sector,
|
|
248
|
+
Object.freeze({
|
|
249
|
+
[HealthcareRoleFamilies.ProfessionalOccupationIsco08]: HealthcareProfessionalRolesBySector[sector] || {},
|
|
250
|
+
[HealthcareRoleFamilies.PersonalRelationshipHl7]: HealthcareRolesByFamily[HealthcareRoleFamilies.PersonalRelationshipHl7],
|
|
251
|
+
[HealthcareRoleFamilies.LegalRepresentativeHl7]: HealthcareRolesByFamily[HealthcareRoleFamilies.LegalRepresentativeHl7],
|
|
252
|
+
}),
|
|
253
|
+
])));
|
|
254
|
+
export function getHealthcareRolesByFamily(family) {
|
|
255
|
+
return HealthcareRolesByFamily[family];
|
|
256
|
+
}
|
|
257
|
+
export function getHealthcareRoleByClaim(claim) {
|
|
258
|
+
return HealthcareAllRolesByClaim[String(claim || '').trim()];
|
|
259
|
+
}
|
|
260
|
+
export function getHealthcareProfessionalRolesBySector(sector) {
|
|
261
|
+
return HealthcareProfessionalRolesBySector[sector] || {};
|
|
262
|
+
}
|
|
263
|
+
export function getHealthcareRolesBySector(sector, family) {
|
|
264
|
+
return HealthcareRolesBySector[sector]?.[family] || {};
|
|
265
|
+
}
|
|
56
266
|
export const HealthcareConsentActions = Object.freeze({
|
|
57
267
|
PatientSummaryDocument: HealthcareBasicSections.PatientSummaryDocument.claim,
|
|
58
268
|
AllergiesAndIntolerances: HealthcareBasicSections.AllergiesAndIntolerances.claim,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BundleEntry, BundleJsonApi } from '../models/bundle';
|
|
2
|
+
/**
|
|
3
|
+
* First developer use case:
|
|
4
|
+
* - edit a Consent entry inside a Communication-attached Bundle
|
|
5
|
+
* - keep active entry in memory
|
|
6
|
+
* - serialize full Bundle to Communication.content-attachment-data on save
|
|
7
|
+
* - release active entry memory when finished
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildConsentEditingCommunicationSessionExample(): {
|
|
10
|
+
communicationClaims: Record<string, unknown>;
|
|
11
|
+
bundleInMemory: BundleJsonApi<BundleEntry>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Second developer use case:
|
|
15
|
+
* - edit MedicationStatement claims to drive a health view
|
|
16
|
+
* - keep bundle attached to Communication as base64 payload
|
|
17
|
+
* - apply save/release lifecycle consistently
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildMedicationEditingCommunicationSessionExample(): {
|
|
20
|
+
communicationClaims: Record<string, unknown>;
|
|
21
|
+
bundleInMemory: BundleJsonApi<BundleEntry>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
// Always create JSDoc, do not use strings inline in keys nor values, use types instead, and reuse the data test examples.
|
|
3
|
+
import { HealthcareBasicSections } from '../constants/healthcare.js';
|
|
4
|
+
import { CommunicationCategoryCodes } from '../constants/communication.js';
|
|
5
|
+
import { ClaimConsent } from '../models/consent-rule.js';
|
|
6
|
+
import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
|
|
7
|
+
import { MedicationStatementClaim } from '../models/interoperable-claims/medication-statement-claims.js';
|
|
8
|
+
import { EXAMPLE_COMMUNICATION_IDENTIFIER, EXAMPLE_CONSENT_DATE, EXAMPLE_CONSENT_IDENTIFIER, EXAMPLE_CONSENT_PERIOD_END, EXAMPLE_CONSENT_PERIOD_START, EXAMPLE_CONSENT_PURPOSE_TREATMENT, EXAMPLE_EMAIL_PROFESSIONAL, EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN, EXAMPLE_IPS_BUNDLE_NOTE_TEXT, EXAMPLE_MEDICATION_STATEMENT_CODE, EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER, EXAMPLE_MEDICATION_STATEMENT_STATUS, EXAMPLE_MEDICATION_STATEMENT_TEXT, EXAMPLE_SUBJECT_DID, } from './shared.js';
|
|
9
|
+
import { CommunicationBundleSession } from '../utils/communication-bundle-session.js';
|
|
10
|
+
/**
|
|
11
|
+
* First developer use case:
|
|
12
|
+
* - edit a Consent entry inside a Communication-attached Bundle
|
|
13
|
+
* - keep active entry in memory
|
|
14
|
+
* - serialize full Bundle to Communication.content-attachment-data on save
|
|
15
|
+
* - release active entry memory when finished
|
|
16
|
+
*/
|
|
17
|
+
export function buildConsentEditingCommunicationSessionExample() {
|
|
18
|
+
const session = new CommunicationBundleSession({
|
|
19
|
+
communicationClaims: {
|
|
20
|
+
'@context': 'org.hl7.fhir.r4',
|
|
21
|
+
[CommunicationClaim.Identifier]: EXAMPLE_COMMUNICATION_IDENTIFIER,
|
|
22
|
+
[CommunicationClaim.Subject]: EXAMPLE_SUBJECT_DID,
|
|
23
|
+
[CommunicationClaim.Category]: CommunicationCategoryCodes.Notification.claim,
|
|
24
|
+
[CommunicationClaim.Text]: EXAMPLE_IPS_BUNDLE_NOTE_TEXT,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
session.upsertActiveConsentEntry({
|
|
28
|
+
claims: {
|
|
29
|
+
'@context': 'org.hl7.fhir.api',
|
|
30
|
+
[ClaimConsent.decision]: 'permit',
|
|
31
|
+
[ClaimConsent.subject]: EXAMPLE_SUBJECT_DID,
|
|
32
|
+
[ClaimConsent.identifier]: EXAMPLE_CONSENT_IDENTIFIER,
|
|
33
|
+
[ClaimConsent.date]: EXAMPLE_CONSENT_DATE,
|
|
34
|
+
[ClaimConsent.periodStart]: EXAMPLE_CONSENT_PERIOD_START,
|
|
35
|
+
[ClaimConsent.periodEnd]: EXAMPLE_CONSENT_PERIOD_END,
|
|
36
|
+
[ClaimConsent.purpose]: EXAMPLE_CONSENT_PURPOSE_TREATMENT,
|
|
37
|
+
[ClaimConsent.action]: HealthcareBasicSections.AllergiesAndIntolerances.claim,
|
|
38
|
+
[ClaimConsent.actorIdentifier]: EXAMPLE_EMAIL_PROFESSIONAL,
|
|
39
|
+
[ClaimConsent.actorRole]: EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN,
|
|
40
|
+
},
|
|
41
|
+
fullUrl: `urn:uuid:${EXAMPLE_CONSENT_IDENTIFIER}`,
|
|
42
|
+
});
|
|
43
|
+
session.saveAndReleaseActiveEntry();
|
|
44
|
+
return {
|
|
45
|
+
communicationClaims: session.getCommunicationClaims(),
|
|
46
|
+
bundleInMemory: session.getBundleInMemory(),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Second developer use case:
|
|
51
|
+
* - edit MedicationStatement claims to drive a health view
|
|
52
|
+
* - keep bundle attached to Communication as base64 payload
|
|
53
|
+
* - apply save/release lifecycle consistently
|
|
54
|
+
*/
|
|
55
|
+
export function buildMedicationEditingCommunicationSessionExample() {
|
|
56
|
+
const session = new CommunicationBundleSession({
|
|
57
|
+
communicationClaims: {
|
|
58
|
+
'@context': 'org.hl7.fhir.r4',
|
|
59
|
+
[CommunicationClaim.Identifier]: EXAMPLE_COMMUNICATION_IDENTIFIER,
|
|
60
|
+
[CommunicationClaim.Subject]: EXAMPLE_SUBJECT_DID,
|
|
61
|
+
[CommunicationClaim.Category]: CommunicationCategoryCodes.Reminder.claim,
|
|
62
|
+
[CommunicationClaim.Text]: EXAMPLE_IPS_BUNDLE_NOTE_TEXT,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
session.upsertActiveMedicationStatementEntry({
|
|
66
|
+
claims: {
|
|
67
|
+
'@context': 'org.hl7.fhir.api',
|
|
68
|
+
[MedicationStatementClaim.Identifier]: EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER,
|
|
69
|
+
[MedicationStatementClaim.Subject]: EXAMPLE_SUBJECT_DID,
|
|
70
|
+
[MedicationStatementClaim.Status]: EXAMPLE_MEDICATION_STATEMENT_STATUS,
|
|
71
|
+
[MedicationStatementClaim.Code]: EXAMPLE_MEDICATION_STATEMENT_CODE,
|
|
72
|
+
[MedicationStatementClaim.MedicationText]: EXAMPLE_MEDICATION_STATEMENT_TEXT,
|
|
73
|
+
},
|
|
74
|
+
fullUrl: `urn:uuid:${EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER}`,
|
|
75
|
+
});
|
|
76
|
+
session.saveAndReleaseActiveEntry();
|
|
77
|
+
return {
|
|
78
|
+
communicationClaims: session.getCommunicationClaims(),
|
|
79
|
+
bundleInMemory: session.getBundleInMemory(),
|
|
80
|
+
};
|
|
81
|
+
}
|
package/dist/examples/index.d.ts
CHANGED
package/dist/examples/index.js
CHANGED
|
@@ -74,6 +74,14 @@ export declare const EXAMPLE_CLINICAL_CODE_PROBLEM: "LOINC|11450-4";
|
|
|
74
74
|
export declare const EXAMPLE_CONSENT_DATE: "2026-05-20";
|
|
75
75
|
export declare const EXAMPLE_CONSENT_PERIOD_END: "2026-05-01T00:00:00Z";
|
|
76
76
|
export declare const EXAMPLE_CONSENT_PURPOSE_TREATMENT: "TREAT";
|
|
77
|
+
export declare const EXAMPLE_CONSENT_IDENTIFIER: "urn:uuid:consent-example-001";
|
|
78
|
+
export declare const EXAMPLE_CONSENT_PERIOD_START: "2026-05-20T00:00:00Z";
|
|
79
|
+
export declare const EXAMPLE_COMMUNICATION_IDENTIFIER: "urn:uuid:communication-example-001";
|
|
80
|
+
export declare const EXAMPLE_IPS_BUNDLE_NOTE_TEXT: "IPS ingestion request";
|
|
81
|
+
export declare const EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER: "urn:uuid:medication-statement-example-001";
|
|
82
|
+
export declare const EXAMPLE_MEDICATION_STATEMENT_STATUS: "active";
|
|
83
|
+
export declare const EXAMPLE_MEDICATION_STATEMENT_CODE: "http://www.nlm.nih.gov/research/umls/rxnorm|313782";
|
|
84
|
+
export declare const EXAMPLE_MEDICATION_STATEMENT_TEXT: "atorvastatin 20 mg oral tablet";
|
|
77
85
|
export declare const EXAMPLE_EMPLOYEE_ACTIVATION_CODE: "ACT-001";
|
|
78
86
|
export declare const EXAMPLE_DEVICE_CLIENT_ID: "did:web:device-001";
|
|
79
87
|
export type ExampleDateRange = Readonly<{
|
package/dist/examples/shared.js
CHANGED
|
@@ -80,6 +80,14 @@ export const EXAMPLE_CLINICAL_CODE_PROBLEM = 'LOINC|11450-4';
|
|
|
80
80
|
export const EXAMPLE_CONSENT_DATE = '2026-05-20';
|
|
81
81
|
export const EXAMPLE_CONSENT_PERIOD_END = '2026-05-01T00:00:00Z';
|
|
82
82
|
export const EXAMPLE_CONSENT_PURPOSE_TREATMENT = HealthcareConsentPurposes.Treatment;
|
|
83
|
+
export const EXAMPLE_CONSENT_IDENTIFIER = 'urn:uuid:consent-example-001';
|
|
84
|
+
export const EXAMPLE_CONSENT_PERIOD_START = '2026-05-20T00:00:00Z';
|
|
85
|
+
export const EXAMPLE_COMMUNICATION_IDENTIFIER = 'urn:uuid:communication-example-001';
|
|
86
|
+
export const EXAMPLE_IPS_BUNDLE_NOTE_TEXT = 'IPS ingestion request';
|
|
87
|
+
export const EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER = 'urn:uuid:medication-statement-example-001';
|
|
88
|
+
export const EXAMPLE_MEDICATION_STATEMENT_STATUS = 'active';
|
|
89
|
+
export const EXAMPLE_MEDICATION_STATEMENT_CODE = 'http://www.nlm.nih.gov/research/umls/rxnorm|313782';
|
|
90
|
+
export const EXAMPLE_MEDICATION_STATEMENT_TEXT = 'atorvastatin 20 mg oral tablet';
|
|
83
91
|
export const EXAMPLE_EMPLOYEE_ACTIVATION_CODE = 'ACT-001';
|
|
84
92
|
export const EXAMPLE_DEVICE_CLIENT_ID = 'did:web:device-001';
|
|
85
93
|
export const EXAMPLE_CLINICAL_DATE_RANGE = {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type RoleCodeI18nKey = `org.ilo.isco-08.${string}` | `org.isco08.${string}` | `org.hl7.v3.personalRelationship.${string}` | `org.hl7.v3.roleCode.${string}`;
|
|
2
|
+
export type RoleCodeI18nMap = Readonly<Record<RoleCodeI18nKey, string>>;
|
|
3
|
+
export declare const roleCodeI18nEn: Readonly<Record<RoleCodeI18nKey, string>>;
|
|
4
|
+
export declare const healthcareRoleI18nEn: Readonly<Record<RoleCodeI18nKey, string>>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HealthcareRolesByFamily } from '../constants/healthcare.js';
|
|
2
|
+
function buildRoleCodeI18nMap() {
|
|
3
|
+
const baseEntries = Object.values(HealthcareRolesByFamily)
|
|
4
|
+
.flatMap((catalog) => Object.values(catalog))
|
|
5
|
+
.map((descriptor) => [descriptor.i18nKey, descriptor.titleEn]);
|
|
6
|
+
const legacyIscoAliases = baseEntries
|
|
7
|
+
.filter(([key]) => key.startsWith('org.ilo.isco-08.'))
|
|
8
|
+
.map(([key, label]) => [key.replace('org.ilo.isco-08.', 'org.isco08.'), label]);
|
|
9
|
+
const entries = [...baseEntries, ...legacyIscoAliases];
|
|
10
|
+
return Object.freeze(Object.fromEntries(entries));
|
|
11
|
+
}
|
|
12
|
+
export const roleCodeI18nEn = buildRoleCodeI18nMap();
|
|
13
|
+
export const healthcareRoleI18nEn = roleCodeI18nEn;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './constants/index.js';
|
|
|
4
4
|
export * from './examples/index.js';
|
|
5
5
|
export * from './hmac.js';
|
|
6
6
|
export * from './i18n/clinical-sections.i18n.js';
|
|
7
|
+
export * from './i18n/role-codes.i18n.js';
|
|
7
8
|
export * from './models/index.js';
|
|
8
9
|
export * from './storage/index.js';
|
|
9
10
|
export * from './utils/index.js';
|
package/dist/models/bundle.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export interface BundleEntryResource {
|
|
|
72
72
|
*/
|
|
73
73
|
export interface BundleEntryRequest {
|
|
74
74
|
id?: string;
|
|
75
|
+
fullUrl?: string;
|
|
75
76
|
type: string;
|
|
76
77
|
request: BundleRequest;
|
|
77
78
|
resource?: BundleEntryResource;
|
|
@@ -84,6 +85,7 @@ export interface BundleEntryRequest {
|
|
|
84
85
|
*/
|
|
85
86
|
export interface BundleEntryResponse {
|
|
86
87
|
id?: string;
|
|
88
|
+
fullUrl?: string;
|
|
87
89
|
type: string;
|
|
88
90
|
response: BundleResponse;
|
|
89
91
|
resource?: BundleEntryResource;
|
|
@@ -126,6 +128,7 @@ export interface ErrorEntry {
|
|
|
126
128
|
*/
|
|
127
129
|
export type BundleEntry = {
|
|
128
130
|
id?: string;
|
|
131
|
+
fullUrl?: string;
|
|
129
132
|
type: string;
|
|
130
133
|
/** @deprecated Legacy claims location. Prefer resource.meta.claims. */
|
|
131
134
|
meta?: BundleEntryMeta;
|
|
@@ -9,21 +9,45 @@
|
|
|
9
9
|
* compatibility readers, but new code must use the canonical key constants
|
|
10
10
|
*/
|
|
11
11
|
export declare const CommunicationClaim: {
|
|
12
|
+
/** Communication category code (`system|code`). */
|
|
12
13
|
readonly Category: "Communication.category";
|
|
14
|
+
/** FHIR Communication status. */
|
|
13
15
|
readonly Status: "Communication.status";
|
|
16
|
+
/** Stable communication identifier. */
|
|
14
17
|
readonly Identifier: "Communication.identifier";
|
|
18
|
+
/** Subject identifier (typically `did:web`). */
|
|
15
19
|
readonly Subject: "Communication.subject";
|
|
20
|
+
/** Recipient identifier(s); CSV allowed. */
|
|
16
21
|
readonly Recipient: "Communication.recipient";
|
|
22
|
+
/** Sender identifier. */
|
|
17
23
|
readonly Sender: "Communication.sender";
|
|
24
|
+
/** Sent timestamp (ISO 8601 DateTime). */
|
|
18
25
|
readonly Sent: "Communication.sent";
|
|
26
|
+
/** Human note text for the communication context. */
|
|
19
27
|
readonly NoteText: "Communication.note-text";
|
|
28
|
+
/** Narrative text (short summary or body). */
|
|
20
29
|
readonly Text: "Communication.text";
|
|
30
|
+
/** Related resource references; CSV allowed. */
|
|
21
31
|
readonly ContentReference: "Communication.content-reference";
|
|
32
|
+
/** Content code (`system|code`) when payload is coded. */
|
|
22
33
|
readonly ContentCode: "Communication.content-code";
|
|
34
|
+
/**
|
|
35
|
+
* Base64 encoded payload for attachment-based communication flows.
|
|
36
|
+
*
|
|
37
|
+
* Recommended lifecycle:
|
|
38
|
+
* - maintain the editable Bundle as object in memory
|
|
39
|
+
* - edit one active entry at a time (`fullUrl`, `resource`, `request`, ...)
|
|
40
|
+
* - re-serialize Bundle JSON to this claim after each save/update
|
|
41
|
+
* - treat this claim as derived data (never manual source of truth)
|
|
42
|
+
*/
|
|
23
43
|
readonly ContentAttachmentData: "Communication.content-attachment-data";
|
|
44
|
+
/** Attachment MIME type (`application/fhir+json`, `application/pdf`, ...). */
|
|
24
45
|
readonly ContentAttachmentType: "Communication.content-attachment-type";
|
|
46
|
+
/** Attachment title for UI/readability contexts. */
|
|
25
47
|
readonly ContentAttachmentTitle: "Communication.content-attachment-title";
|
|
48
|
+
/** External attachment URL when payload is not embedded. */
|
|
26
49
|
readonly ContentAttachmentUrl: "Communication.content-attachment-url";
|
|
50
|
+
/** Parent communication thread/reference (`Communication.part-of`). */
|
|
27
51
|
readonly PartOf: "Communication.part-of";
|
|
28
52
|
};
|
|
29
53
|
export type CommunicationClaimKey = typeof CommunicationClaim[keyof typeof CommunicationClaim];
|
|
@@ -12,20 +12,44 @@
|
|
|
12
12
|
* compatibility readers, but new code must use the canonical key constants
|
|
13
13
|
*/
|
|
14
14
|
export const CommunicationClaim = {
|
|
15
|
+
/** Communication category code (`system|code`). */
|
|
15
16
|
Category: 'Communication.category',
|
|
17
|
+
/** FHIR Communication status. */
|
|
16
18
|
Status: 'Communication.status',
|
|
19
|
+
/** Stable communication identifier. */
|
|
17
20
|
Identifier: 'Communication.identifier',
|
|
21
|
+
/** Subject identifier (typically `did:web`). */
|
|
18
22
|
Subject: 'Communication.subject',
|
|
23
|
+
/** Recipient identifier(s); CSV allowed. */
|
|
19
24
|
Recipient: 'Communication.recipient',
|
|
25
|
+
/** Sender identifier. */
|
|
20
26
|
Sender: 'Communication.sender',
|
|
27
|
+
/** Sent timestamp (ISO 8601 DateTime). */
|
|
21
28
|
Sent: 'Communication.sent',
|
|
29
|
+
/** Human note text for the communication context. */
|
|
22
30
|
NoteText: 'Communication.note-text',
|
|
31
|
+
/** Narrative text (short summary or body). */
|
|
23
32
|
Text: 'Communication.text',
|
|
33
|
+
/** Related resource references; CSV allowed. */
|
|
24
34
|
ContentReference: 'Communication.content-reference',
|
|
35
|
+
/** Content code (`system|code`) when payload is coded. */
|
|
25
36
|
ContentCode: 'Communication.content-code',
|
|
37
|
+
/**
|
|
38
|
+
* Base64 encoded payload for attachment-based communication flows.
|
|
39
|
+
*
|
|
40
|
+
* Recommended lifecycle:
|
|
41
|
+
* - maintain the editable Bundle as object in memory
|
|
42
|
+
* - edit one active entry at a time (`fullUrl`, `resource`, `request`, ...)
|
|
43
|
+
* - re-serialize Bundle JSON to this claim after each save/update
|
|
44
|
+
* - treat this claim as derived data (never manual source of truth)
|
|
45
|
+
*/
|
|
26
46
|
ContentAttachmentData: 'Communication.content-attachment-data',
|
|
47
|
+
/** Attachment MIME type (`application/fhir+json`, `application/pdf`, ...). */
|
|
27
48
|
ContentAttachmentType: 'Communication.content-attachment-type',
|
|
49
|
+
/** Attachment title for UI/readability contexts. */
|
|
28
50
|
ContentAttachmentTitle: 'Communication.content-attachment-title',
|
|
51
|
+
/** External attachment URL when payload is not embedded. */
|
|
29
52
|
ContentAttachmentUrl: 'Communication.content-attachment-url',
|
|
53
|
+
/** Parent communication thread/reference (`Communication.part-of`). */
|
|
30
54
|
PartOf: 'Communication.part-of'
|
|
31
55
|
};
|
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
export declare const MedicationStatementClaim: {
|
|
6
6
|
readonly Identifier: "MedicationStatement.identifier";
|
|
7
7
|
readonly Subject: "MedicationStatement.subject";
|
|
8
|
+
readonly Patient: "MedicationStatement.patient";
|
|
8
9
|
readonly Status: "MedicationStatement.status";
|
|
10
|
+
readonly Category: "MedicationStatement.category";
|
|
9
11
|
readonly Effective: "MedicationStatement.effective";
|
|
10
12
|
readonly Code: "MedicationStatement.code";
|
|
13
|
+
readonly Medication: "MedicationStatement.medication";
|
|
14
|
+
readonly PartOf: "MedicationStatement.part-of";
|
|
15
|
+
readonly Source: "MedicationStatement.source";
|
|
11
16
|
readonly MedicationText: "MedicationStatement.medication-text";
|
|
12
17
|
readonly Note: "MedicationStatement.note";
|
|
13
18
|
readonly DosageInstruction: "MedicationStatement.dosage-instruction";
|
|
@@ -7,9 +7,14 @@
|
|
|
7
7
|
export const MedicationStatementClaim = {
|
|
8
8
|
Identifier: 'MedicationStatement.identifier',
|
|
9
9
|
Subject: 'MedicationStatement.subject',
|
|
10
|
+
Patient: 'MedicationStatement.patient',
|
|
10
11
|
Status: 'MedicationStatement.status',
|
|
12
|
+
Category: 'MedicationStatement.category',
|
|
11
13
|
Effective: 'MedicationStatement.effective',
|
|
12
14
|
Code: 'MedicationStatement.code',
|
|
15
|
+
Medication: 'MedicationStatement.medication',
|
|
16
|
+
PartOf: 'MedicationStatement.part-of',
|
|
17
|
+
Source: 'MedicationStatement.source',
|
|
13
18
|
MedicationText: 'MedicationStatement.medication-text',
|
|
14
19
|
Note: 'MedicationStatement.note',
|
|
15
20
|
DosageInstruction: 'MedicationStatement.dosage-instruction',
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { BundleEntry, BundleJsonApi } from '../models/bundle.js';
|
|
2
|
+
export type BundleResourceIdFilters = Readonly<{
|
|
3
|
+
sections?: string | readonly string[];
|
|
4
|
+
resourceTypes?: string | readonly string[];
|
|
5
|
+
dateFrom?: string;
|
|
6
|
+
dateTo?: string;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* Generic bundle query helper for reusable entry filtering and lookup.
|
|
10
|
+
*
|
|
11
|
+
* This utility is intentionally communication-agnostic and can be reused by
|
|
12
|
+
* any package that works with BundleJsonApi payloads.
|
|
13
|
+
*/
|
|
14
|
+
export declare class BundleQuery {
|
|
15
|
+
private readonly bundle;
|
|
16
|
+
constructor(bundle: BundleJsonApi<BundleEntry>);
|
|
17
|
+
/**
|
|
18
|
+
* Returns stable resource IDs from bundle entries with optional filters.
|
|
19
|
+
*/
|
|
20
|
+
getResourceIds(filters?: BundleResourceIdFilters): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Returns bundle entries matching resource IDs produced by `getResourceIds`.
|
|
23
|
+
*/
|
|
24
|
+
getResourceEntriesByIds(resourceIds: readonly string[]): BundleEntry[];
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the entry URL (`fullUrl`) for a given entry/resource identifier.
|
|
27
|
+
*/
|
|
28
|
+
getEntryUrl(entryId: string): string | undefined;
|
|
29
|
+
private resolveBundleEntryId;
|
|
30
|
+
private resolveIdentifierFromClaims;
|
|
31
|
+
private matchesResourceFilters;
|
|
32
|
+
private matchesSections;
|
|
33
|
+
private resolveEntryDate;
|
|
34
|
+
private matchesDateRange;
|
|
35
|
+
}
|