gdc-common-utils-ts 2.1.0 → 2.2.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 +18 -0
- package/dist/claims/claims-helpers-allergy-intolerance.d.ts +8 -0
- package/dist/claims/claims-helpers-allergy-intolerance.js +30 -12
- package/dist/claims/claims-helpers-condition.d.ts +8 -0
- package/dist/claims/claims-helpers-condition.js +30 -12
- package/dist/claims/claims-helpers-consent.d.ts +4 -0
- package/dist/claims/claims-helpers-consent.js +15 -1
- package/dist/claims/claims-helpers-diagnostic-report.d.ts +4 -0
- package/dist/claims/claims-helpers-diagnostic-report.js +17 -2
- package/dist/claims/claims-helpers-medication-statement.d.ts +10 -2
- package/dist/claims/claims-helpers-medication-statement.js +32 -14
- package/dist/constants/didcomm.d.ts +22 -0
- package/dist/constants/didcomm.js +22 -0
- package/dist/constants/fhir-resource-types.d.ts +2 -0
- package/dist/constants/fhir-resource-types.js +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/lifecycle.d.ts +2 -0
- package/dist/constants/lifecycle.js +2 -0
- package/dist/constants/verifiable-credentials.d.ts +9 -0
- package/dist/constants/verifiable-credentials.js +9 -0
- package/dist/examples/bundle-didcomm-payload.js +4 -2
- package/dist/examples/communication-attached-bundle-session.js +27 -27
- package/dist/examples/communication-didcomm-payload.d.ts +8 -4
- package/dist/examples/communication-didcomm-payload.js +17 -11
- package/dist/examples/consent-access.js +2 -1
- package/dist/examples/employee.d.ts +21 -0
- package/dist/examples/employee.js +21 -0
- package/dist/examples/individual-controller.d.ts +27 -0
- package/dist/examples/individual-controller.js +28 -1
- package/dist/examples/inter-tenant-access-contract.js +3 -2
- package/dist/examples/ips-bundle.js +17 -16
- package/dist/examples/lifecycle.js +13 -11
- package/dist/examples/profile-manager-mem.js +2 -1
- package/dist/examples/related-person.d.ts +14 -0
- package/dist/examples/related-person.js +18 -4
- package/dist/examples/shared.d.ts +12 -3
- package/dist/examples/shared.js +13 -4
- package/dist/examples/vital-signs.js +1 -1
- package/dist/examples/wallet-mem.js +4 -2
- package/dist/models/authority-resolution.d.ts +56 -0
- package/dist/models/authority-resolution.js +2 -0
- package/dist/models/bundle-editor-types.d.ts +89 -0
- package/dist/models/bundle-editor-types.js +45 -0
- package/dist/models/bundle.d.ts +5 -0
- package/dist/models/communication-attached-bundle-session.d.ts +6 -4
- package/dist/models/communication-attached-bundle-session.js +6 -4
- package/dist/models/confidential-storage.d.ts +2 -1
- package/dist/models/consent-rule.d.ts +11 -1
- package/dist/models/consent-rule.js +9 -1
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +2 -0
- package/dist/models/individual-onboarding.d.ts +18 -0
- package/dist/models/interoperable-claims/allergy-intolerance-claims.d.ts +12 -1
- package/dist/models/interoperable-claims/allergy-intolerance-claims.js +12 -1
- package/dist/models/interoperable-claims/condition-claims.d.ts +12 -1
- package/dist/models/interoperable-claims/condition-claims.js +12 -1
- package/dist/models/interoperable-claims/diagnostic-report-claims.d.ts +13 -2
- package/dist/models/interoperable-claims/diagnostic-report-claims.js +12 -1
- package/dist/models/interoperable-claims/document-reference-claims.d.ts +1 -0
- package/dist/models/interoperable-claims/document-reference-claims.js +3 -0
- package/dist/models/interoperable-claims/medication-statement-claims.d.ts +17 -0
- package/dist/models/interoperable-claims/medication-statement-claims.js +17 -0
- package/dist/utils/allergy-intolerance-entry-editor.d.ts +51 -0
- package/dist/utils/allergy-intolerance-entry-editor.js +55 -0
- package/dist/utils/authority-resolution.d.ts +37 -0
- package/dist/utils/authority-resolution.js +112 -0
- package/dist/utils/backend-message-manager-mem.d.ts +11 -0
- package/dist/utils/backend-message-manager-mem.js +11 -0
- package/dist/utils/bundle-didcomm-payload.js +3 -2
- package/dist/utils/bundle-document-builder.d.ts +1 -0
- package/dist/utils/bundle-document-builder.js +134 -14
- package/dist/utils/bundle-editor-core.d.ts +181 -0
- package/dist/utils/bundle-editor-core.js +467 -0
- package/dist/utils/bundle-editor-helpers.d.ts +53 -0
- package/dist/utils/bundle-editor-helpers.js +146 -0
- package/dist/utils/bundle-editor-registry.d.ts +6 -0
- package/dist/utils/bundle-editor-registry.js +14 -0
- package/dist/utils/bundle-editor.d.ts +21 -722
- package/dist/utils/bundle-editor.js +21 -1601
- package/dist/utils/bundle-entry-editor.d.ts +96 -0
- package/dist/utils/bundle-entry-editor.js +305 -0
- package/dist/utils/bundle-query.d.ts +1 -0
- package/dist/utils/bundle-query.js +12 -3
- package/dist/utils/bundle-reader.d.ts +48 -0
- package/dist/utils/bundle-reader.js +175 -1
- package/dist/utils/care-plan-entry-editor.d.ts +43 -0
- package/dist/utils/care-plan-entry-editor.js +47 -0
- package/dist/utils/client-assertion.d.ts +38 -0
- package/dist/utils/client-assertion.js +113 -0
- package/dist/utils/clinical-impression-entry-editor.d.ts +43 -0
- package/dist/utils/clinical-impression-entry-editor.js +47 -0
- package/dist/utils/clinical-resource-entry-editor.d.ts +123 -0
- package/dist/utils/clinical-resource-entry-editor.js +296 -0
- package/dist/utils/communication-attached-bundle-session-helpers.js +8 -6
- package/dist/utils/communication-attached-bundle-session.d.ts +29 -3
- package/dist/utils/communication-attached-bundle-session.js +62 -3
- package/dist/utils/communication-didcomm-payload.d.ts +5 -0
- package/dist/utils/communication-didcomm-payload.js +28 -18
- package/dist/utils/communication-document-reference.d.ts +23 -0
- package/dist/utils/communication-document-reference.js +89 -0
- package/dist/utils/communication-editor.d.ts +53 -0
- package/dist/utils/communication-editor.js +97 -0
- package/dist/utils/condition-entry-editor.d.ts +30 -0
- package/dist/utils/condition-entry-editor.js +34 -0
- package/dist/utils/consent-claim-helpers.d.ts +4 -0
- package/dist/utils/consent-claim-helpers.js +15 -1
- package/dist/utils/coverage-entry-editor.d.ts +51 -0
- package/dist/utils/coverage-entry-editor.js +55 -0
- package/dist/utils/device-entry-editor.d.ts +59 -0
- package/dist/utils/device-entry-editor.js +63 -0
- package/dist/utils/device-use-statement-entry-editor.d.ts +43 -0
- package/dist/utils/device-use-statement-entry-editor.js +47 -0
- package/dist/utils/diagnostic-report-entry-editor.d.ts +74 -0
- package/dist/utils/diagnostic-report-entry-editor.js +136 -0
- package/dist/utils/did.d.ts +8 -0
- package/dist/utils/did.js +22 -0
- package/dist/utils/document-reference-entry-editor.d.ts +62 -0
- package/dist/utils/document-reference-entry-editor.js +66 -0
- package/dist/utils/employee-entry-editor.d.ts +36 -0
- package/dist/utils/employee-entry-editor.js +88 -0
- package/dist/utils/employee.d.ts +1 -0
- package/dist/utils/employee.js +2 -1
- package/dist/utils/encounter-entry-editor.d.ts +51 -0
- package/dist/utils/encounter-entry-editor.js +55 -0
- package/dist/utils/flag-entry-editor.d.ts +47 -0
- package/dist/utils/flag-entry-editor.js +51 -0
- package/dist/utils/immunization-entry-editor.d.ts +87 -0
- package/dist/utils/immunization-entry-editor.js +169 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/individual-onboarding-acceptance-credential.d.ts +35 -0
- package/dist/utils/individual-onboarding-acceptance-credential.js +55 -0
- package/dist/utils/individual-smart.d.ts +59 -0
- package/dist/utils/individual-smart.js +135 -0
- package/dist/utils/medication-statement-entry-editor.d.ts +90 -0
- package/dist/utils/medication-statement-entry-editor.js +94 -0
- package/dist/utils/observation-component-entry-editor.d.ts +57 -0
- package/dist/utils/observation-component-entry-editor.js +105 -0
- package/dist/utils/observation-entry-editor.d.ts +29 -0
- package/dist/utils/observation-entry-editor.js +68 -0
- package/dist/utils/procedure-entry-editor.d.ts +71 -0
- package/dist/utils/procedure-entry-editor.js +75 -0
- package/dist/utils/professional-smart.d.ts +87 -0
- package/dist/utils/professional-smart.js +118 -4
- package/dist/utils/same-as.d.ts +40 -0
- package/dist/utils/same-as.js +72 -0
- package/dist/utils/unified-health-id.d.ts +51 -0
- package/dist/utils/unified-health-id.js +92 -0
- package/dist/utils/vital-sign-day-batch.d.ts +25 -0
- package/dist/utils/vital-sign-day-batch.js +115 -0
- package/dist/utils/vital-sign-entry-editor.d.ts +61 -0
- package/dist/utils/vital-sign-entry-editor.js +152 -0
- package/package.json +2 -1
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { getHighestIssueSeverity, isIssueSeverityCode, IssueSeverity, } from '../models/issue.js';
|
|
2
|
+
import { BundleQuery } from './bundle-query.js';
|
|
2
3
|
function cloneEntry(value) {
|
|
3
4
|
return JSON.parse(JSON.stringify(value));
|
|
4
5
|
}
|
|
5
6
|
function asRecord(value) {
|
|
6
7
|
return value && typeof value === 'object' ? value : {};
|
|
7
8
|
}
|
|
9
|
+
function asNonEmptyString(value) {
|
|
10
|
+
if (typeof value !== 'string') {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const normalized = value.trim();
|
|
14
|
+
return normalized || undefined;
|
|
15
|
+
}
|
|
16
|
+
function resolveContainedFlagClaimKey(resourceType) {
|
|
17
|
+
const normalized = asNonEmptyString(resourceType);
|
|
18
|
+
return normalized ? `${normalized}.is-contained` : undefined;
|
|
19
|
+
}
|
|
20
|
+
function resolveContainedParentReferenceClaimKey(resourceType) {
|
|
21
|
+
const normalized = asNonEmptyString(resourceType);
|
|
22
|
+
return normalized ? `${normalized}.contained-parent-reference` : undefined;
|
|
23
|
+
}
|
|
8
24
|
/**
|
|
9
25
|
* Returns the canonical claims view for one bundle entry array index.
|
|
10
26
|
*
|
|
@@ -84,6 +100,27 @@ export class BundleReader {
|
|
|
84
100
|
getEntryClaimsByArrayIndex(index) {
|
|
85
101
|
return getClaimsInBundleEntryAt(this.bundle, index);
|
|
86
102
|
}
|
|
103
|
+
/** Returns true when the entry was imported from one parent resource `contained[]`. */
|
|
104
|
+
isContainedResourceEntryByArrayIndex(index) {
|
|
105
|
+
const claims = this.getEntryClaimsByArrayIndex(index);
|
|
106
|
+
const entryRecord = asRecord(this.getEntries()[index]);
|
|
107
|
+
const resourceRecord = asRecord(entryRecord.resource);
|
|
108
|
+
const resourceType = claims['resourceType'] || resourceRecord.resourceType;
|
|
109
|
+
const claimKey = resolveContainedFlagClaimKey(resourceType);
|
|
110
|
+
return claimKey
|
|
111
|
+
? (claims[claimKey] === true || claims[claimKey] === 'true')
|
|
112
|
+
: false;
|
|
113
|
+
}
|
|
114
|
+
/** Returns the parent resource reference for one contained resource entry. */
|
|
115
|
+
getContainedParentReferenceByArrayIndex(index) {
|
|
116
|
+
const claims = this.getEntryClaimsByArrayIndex(index);
|
|
117
|
+
const entryRecord = asRecord(this.getEntries()[index]);
|
|
118
|
+
const resourceRecord = asRecord(entryRecord.resource);
|
|
119
|
+
const resourceType = claims['resourceType'] || resourceRecord.resourceType;
|
|
120
|
+
const claimKey = resolveContainedParentReferenceClaimKey(resourceType);
|
|
121
|
+
const value = claimKey ? claims[claimKey] : undefined;
|
|
122
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
123
|
+
}
|
|
87
124
|
/** Returns merged claims for the currently opened entry. */
|
|
88
125
|
getActiveEntryClaims() {
|
|
89
126
|
if (this.activeEntryIndex === null) {
|
|
@@ -105,6 +142,109 @@ export class BundleReader {
|
|
|
105
142
|
}
|
|
106
143
|
return undefined;
|
|
107
144
|
}
|
|
145
|
+
/** Returns stable resource IDs filtered from the current bundle in memory. */
|
|
146
|
+
getResourceIds(filters = {}) {
|
|
147
|
+
const query = new BundleQuery(this.bundle);
|
|
148
|
+
return query.getResourceIds(filters);
|
|
149
|
+
}
|
|
150
|
+
/** Returns visible entry indexes after filtering out imported contained children. */
|
|
151
|
+
getVisibleEntryIndexes(filters = {}) {
|
|
152
|
+
return [...this.getVisibleResourceNavigation(filters).entryIndexes];
|
|
153
|
+
}
|
|
154
|
+
/** Returns stable resource IDs excluding entries marked as imported `contained[]` children. */
|
|
155
|
+
getVisibleResourceIds(filters = {}) {
|
|
156
|
+
return [...this.getVisibleResourceNavigation(filters).resourceIds];
|
|
157
|
+
}
|
|
158
|
+
/** Returns the number of visible resources the frontend should iterate over. */
|
|
159
|
+
getVisibleResourceCount(filters = {}) {
|
|
160
|
+
return this.getVisibleResourceIds(filters).length;
|
|
161
|
+
}
|
|
162
|
+
/** Returns one visible entry index by visible-position order. */
|
|
163
|
+
getVisibleEntryIndexByPosition(position, filters = {}) {
|
|
164
|
+
if (!Number.isInteger(position) || position < 0) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
return this.getVisibleEntryIndexes(filters)[position];
|
|
168
|
+
}
|
|
169
|
+
/** Returns the next visible entry index after one raw entry index. */
|
|
170
|
+
getNextVisibleEntryIndex(currentIndex, filters = {}) {
|
|
171
|
+
const visibleIndexes = this.getVisibleEntryIndexes(filters);
|
|
172
|
+
const currentVisiblePosition = visibleIndexes.findIndex((index) => index === currentIndex);
|
|
173
|
+
if (currentVisiblePosition >= 0) {
|
|
174
|
+
return visibleIndexes[currentVisiblePosition + 1];
|
|
175
|
+
}
|
|
176
|
+
return visibleIndexes.find((index) => index > currentIndex);
|
|
177
|
+
}
|
|
178
|
+
/** Returns the previous visible entry index before one raw entry index. */
|
|
179
|
+
getPreviousVisibleEntryIndex(currentIndex, filters = {}) {
|
|
180
|
+
const visibleIndexes = this.getVisibleEntryIndexes(filters);
|
|
181
|
+
const currentVisiblePosition = visibleIndexes.findIndex((index) => index === currentIndex);
|
|
182
|
+
if (currentVisiblePosition > 0) {
|
|
183
|
+
return visibleIndexes[currentVisiblePosition - 1];
|
|
184
|
+
}
|
|
185
|
+
const lowerVisibleIndexes = visibleIndexes.filter((index) => index < currentIndex);
|
|
186
|
+
return lowerVisibleIndexes[lowerVisibleIndexes.length - 1];
|
|
187
|
+
}
|
|
188
|
+
/** Returns bundle entries matching resource IDs produced by `getResourceIds(...)`. */
|
|
189
|
+
getEntriesByIds(resourceIds) {
|
|
190
|
+
const query = new BundleQuery(this.bundle);
|
|
191
|
+
return query.getResourceEntriesByIds(resourceIds);
|
|
192
|
+
}
|
|
193
|
+
/** Resolves the entry URL (`fullUrl`) for a given entry/resource identifier. */
|
|
194
|
+
getEntryUrl(resourceId) {
|
|
195
|
+
const query = new BundleQuery(this.bundle);
|
|
196
|
+
return query.getEntryUrl(resourceId);
|
|
197
|
+
}
|
|
198
|
+
/** Returns the Composition-first document sections when this bundle is one document bundle. */
|
|
199
|
+
getDocumentSections() {
|
|
200
|
+
const composition = this.getDocumentCompositionResource();
|
|
201
|
+
if (!composition) {
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
const sections = Array.isArray(composition.section) ? composition.section : [];
|
|
205
|
+
return sections.map((section, index) => {
|
|
206
|
+
const sectionRecord = asRecord(section);
|
|
207
|
+
const codingList = asRecord(sectionRecord.code).coding;
|
|
208
|
+
const coding = Array.isArray(codingList)
|
|
209
|
+
? asRecord(codingList[0])
|
|
210
|
+
: {};
|
|
211
|
+
const system = asNonEmptyString(coding.system);
|
|
212
|
+
const code = asNonEmptyString(coding.code);
|
|
213
|
+
const claim = system && code ? `${system}|${code}` : code;
|
|
214
|
+
const entryReferences = Array.isArray(sectionRecord.entry)
|
|
215
|
+
? sectionRecord.entry
|
|
216
|
+
.map((entry) => asNonEmptyString(asRecord(entry).reference))
|
|
217
|
+
.filter((reference) => Boolean(reference))
|
|
218
|
+
: [];
|
|
219
|
+
return {
|
|
220
|
+
index,
|
|
221
|
+
code,
|
|
222
|
+
system,
|
|
223
|
+
claim,
|
|
224
|
+
entryReferences,
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/** Returns the number of Composition sections in one document bundle. */
|
|
229
|
+
getDocumentSectionCount() {
|
|
230
|
+
return this.getDocumentSections().length;
|
|
231
|
+
}
|
|
232
|
+
/** Returns one document section by canonical claim (`system|code`) or plain code. */
|
|
233
|
+
getDocumentSectionByCode(sectionCodeOrClaim) {
|
|
234
|
+
const normalized = normalizeOptionalString(sectionCodeOrClaim);
|
|
235
|
+
if (!normalized) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
return this.getDocumentSections().find((section) => section.claim === normalized || section.code === normalized);
|
|
239
|
+
}
|
|
240
|
+
/** Returns the number of resource references inside one document section. */
|
|
241
|
+
getDocumentSectionResourceCount(sectionCodeOrClaim) {
|
|
242
|
+
return this.getDocumentSectionByCode(sectionCodeOrClaim)?.entryReferences.length || 0;
|
|
243
|
+
}
|
|
244
|
+
/** Returns bundle resource references listed under one document section. */
|
|
245
|
+
getDocumentSectionResourceReferences(sectionCodeOrClaim) {
|
|
246
|
+
return [...(this.getDocumentSectionByCode(sectionCodeOrClaim)?.entryReferences || [])];
|
|
247
|
+
}
|
|
108
248
|
/** Returns the active entry response status when present. */
|
|
109
249
|
getEntryResponseStatus() {
|
|
110
250
|
const entry = this.getRequiredActiveEntry();
|
|
@@ -125,9 +265,13 @@ export class BundleReader {
|
|
|
125
265
|
.filter((diagnostics) => typeof diagnostics === 'string' && diagnostics.trim().length > 0);
|
|
126
266
|
}
|
|
127
267
|
/** Returns the number of bundle entries. */
|
|
128
|
-
|
|
268
|
+
getEntryCount() {
|
|
129
269
|
return this.getEntries().length;
|
|
130
270
|
}
|
|
271
|
+
/** Returns the number of bundle entries. */
|
|
272
|
+
getTotalOperations() {
|
|
273
|
+
return this.getEntryCount();
|
|
274
|
+
}
|
|
131
275
|
/** Returns the number of entries with one 2xx response status. */
|
|
132
276
|
getTotalSuccessfulOperations() {
|
|
133
277
|
return this.getEntrySummaries().filter((entry) => entry.isSuccessful).length;
|
|
@@ -189,6 +333,36 @@ export class BundleReader {
|
|
|
189
333
|
const entries = this.getEntries();
|
|
190
334
|
return entries[this.activeEntryIndex];
|
|
191
335
|
}
|
|
336
|
+
getDocumentCompositionResource() {
|
|
337
|
+
if (this.getBundleType() !== 'document') {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const entries = this.getEntries();
|
|
341
|
+
const compositionEntry = entries.find((entry) => {
|
|
342
|
+
const resource = asRecord(asRecord(entry).resource);
|
|
343
|
+
return asNonEmptyString(resource.resourceType) === 'Composition';
|
|
344
|
+
});
|
|
345
|
+
const compositionResource = asRecord(asRecord(compositionEntry).resource);
|
|
346
|
+
return Object.keys(compositionResource).length ? compositionResource : null;
|
|
347
|
+
}
|
|
348
|
+
getVisibleResourceNavigation(filters = {}) {
|
|
349
|
+
const visiblePairs = this.getResourceIds(filters)
|
|
350
|
+
.map((resourceId) => {
|
|
351
|
+
const entryIndex = this.getEntryIndexByIdentifier(resourceId);
|
|
352
|
+
if (entryIndex === undefined || this.isContainedResourceEntryByArrayIndex(entryIndex)) {
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
entryIndex,
|
|
357
|
+
resourceId,
|
|
358
|
+
};
|
|
359
|
+
})
|
|
360
|
+
.filter((value) => Boolean(value));
|
|
361
|
+
return {
|
|
362
|
+
entryIndexes: visiblePairs.map((item) => item.entryIndex),
|
|
363
|
+
resourceIds: visiblePairs.map((item) => item.resourceId),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
192
366
|
getActiveEntryIssues() {
|
|
193
367
|
const entry = this.getRequiredActiveEntry();
|
|
194
368
|
return this.getEntryIssues(entry);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor';
|
|
2
|
+
/**
|
|
3
|
+
* Typed editor for one staged CarePlan resource entry.
|
|
4
|
+
*
|
|
5
|
+
* Use this when a caller needs to stage one care-plan row with claims-first
|
|
6
|
+
* accessors in a bundle authoring flow.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CarePlanEntryEditor extends ClinicalResourceEntryEditor {
|
|
9
|
+
/** Writes the canonical care-plan identifier. */
|
|
10
|
+
setIdentifier(identifier?: string | null): this;
|
|
11
|
+
/** Reads the canonical care-plan identifier. */
|
|
12
|
+
getIdentifier(): string | undefined;
|
|
13
|
+
/** Ensures the care-plan entry has one canonical `urn:uuid:*` identifier. */
|
|
14
|
+
ensureIdentifier(): string;
|
|
15
|
+
/** Writes the subject/patient reference. */
|
|
16
|
+
setSubject(subject?: string | null): this;
|
|
17
|
+
/** Reads the subject/patient reference. */
|
|
18
|
+
getSubject(): string | undefined;
|
|
19
|
+
/** Writes the care-plan status. */
|
|
20
|
+
setStatus(value?: string | null): this;
|
|
21
|
+
/** Reads the care-plan status. */
|
|
22
|
+
getStatus(): string | undefined;
|
|
23
|
+
/** Writes the care-plan intent. */
|
|
24
|
+
setIntent(value?: string | null): this;
|
|
25
|
+
/** Reads the care-plan intent. */
|
|
26
|
+
getIntent(): string | undefined;
|
|
27
|
+
/** Writes the care-plan category. */
|
|
28
|
+
setCategory(value?: string | null): this;
|
|
29
|
+
/** Reads the care-plan category. */
|
|
30
|
+
getCategory(): string | undefined;
|
|
31
|
+
/** Writes the linked encounter reference. */
|
|
32
|
+
setEncounter(value?: string | null): this;
|
|
33
|
+
/** Reads the linked encounter reference. */
|
|
34
|
+
getEncounter(): string | undefined;
|
|
35
|
+
/** Writes the care-plan date. */
|
|
36
|
+
setDate(value?: string | null): this;
|
|
37
|
+
/** Reads the care-plan date. */
|
|
38
|
+
getDate(): string | undefined;
|
|
39
|
+
/** Writes the note text. */
|
|
40
|
+
setNote(value?: string | null): this;
|
|
41
|
+
/** Reads the note text. */
|
|
42
|
+
getNote(): string | undefined;
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor.js';
|
|
2
|
+
import { CarePlanClaim } from '../models/interoperable-claims/care-plan-claims.js';
|
|
3
|
+
import { BundleEditableResourceTypes } from '../models/bundle-editor-types.js';
|
|
4
|
+
import { registerBundleEntryEditor } from './bundle-editor-registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Typed editor for one staged CarePlan resource entry.
|
|
7
|
+
*
|
|
8
|
+
* Use this when a caller needs to stage one care-plan row with claims-first
|
|
9
|
+
* accessors in a bundle authoring flow.
|
|
10
|
+
*/
|
|
11
|
+
export class CarePlanEntryEditor extends ClinicalResourceEntryEditor {
|
|
12
|
+
/** Writes the canonical care-plan identifier. */
|
|
13
|
+
setIdentifier(identifier) { return this.setIdentifierValue(CarePlanClaim.Identifier, identifier); }
|
|
14
|
+
/** Reads the canonical care-plan identifier. */
|
|
15
|
+
getIdentifier() { return this.getIdentifierValue(CarePlanClaim.Identifier); }
|
|
16
|
+
/** Ensures the care-plan entry has one canonical `urn:uuid:*` identifier. */
|
|
17
|
+
ensureIdentifier() { return this.ensureIdentifierValue(CarePlanClaim.Identifier); }
|
|
18
|
+
/** Writes the subject/patient reference. */
|
|
19
|
+
setSubject(subject) { return this.setSubjectClaims(CarePlanClaim.Subject, CarePlanClaim.Patient, subject); }
|
|
20
|
+
/** Reads the subject/patient reference. */
|
|
21
|
+
getSubject() { return this.getSubjectClaims(CarePlanClaim.Subject, CarePlanClaim.Patient); }
|
|
22
|
+
/** Writes the care-plan status. */
|
|
23
|
+
setStatus(value) { return this.setScalarClaim(CarePlanClaim.Status, value); }
|
|
24
|
+
/** Reads the care-plan status. */
|
|
25
|
+
getStatus() { return this.getScalarClaim(CarePlanClaim.Status); }
|
|
26
|
+
/** Writes the care-plan intent. */
|
|
27
|
+
setIntent(value) { return this.setScalarClaim(CarePlanClaim.Intent, value); }
|
|
28
|
+
/** Reads the care-plan intent. */
|
|
29
|
+
getIntent() { return this.getScalarClaim(CarePlanClaim.Intent); }
|
|
30
|
+
/** Writes the care-plan category. */
|
|
31
|
+
setCategory(value) { return this.setScalarClaim(CarePlanClaim.Category, value); }
|
|
32
|
+
/** Reads the care-plan category. */
|
|
33
|
+
getCategory() { return this.getScalarClaim(CarePlanClaim.Category); }
|
|
34
|
+
/** Writes the linked encounter reference. */
|
|
35
|
+
setEncounter(value) { return this.setScalarClaim(CarePlanClaim.Encounter, value); }
|
|
36
|
+
/** Reads the linked encounter reference. */
|
|
37
|
+
getEncounter() { return this.getScalarClaim(CarePlanClaim.Encounter); }
|
|
38
|
+
/** Writes the care-plan date. */
|
|
39
|
+
setDate(value) { return this.setScalarClaim(CarePlanClaim.Date, value); }
|
|
40
|
+
/** Reads the care-plan date. */
|
|
41
|
+
getDate() { return this.getScalarClaim(CarePlanClaim.Date); }
|
|
42
|
+
/** Writes the note text. */
|
|
43
|
+
setNote(value) { return this.setScalarClaim(CarePlanClaim.Note, value); }
|
|
44
|
+
/** Reads the note text. */
|
|
45
|
+
getNote() { return this.getScalarClaim(CarePlanClaim.Note); }
|
|
46
|
+
}
|
|
47
|
+
registerBundleEntryEditor(BundleEditableResourceTypes.carePlan, CarePlanEntryEditor);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type JsonWebKey } from 'node:crypto';
|
|
2
|
+
export type ClientAssertionJwtAlgorithm = 'ES256' | 'ES384' | 'ES512' | 'EdDSA';
|
|
3
|
+
export type BuildClientAssertionJwtInput = {
|
|
4
|
+
clientId: string;
|
|
5
|
+
audience: string;
|
|
6
|
+
issuer?: string;
|
|
7
|
+
subject?: string;
|
|
8
|
+
algorithm?: ClientAssertionJwtAlgorithm;
|
|
9
|
+
expiresIn?: string | number;
|
|
10
|
+
issuedAt?: number | Date;
|
|
11
|
+
nonce?: string;
|
|
12
|
+
additionalClaims?: Record<string, unknown>;
|
|
13
|
+
protectedHeader?: Record<string, unknown>;
|
|
14
|
+
includePublicJwkInHeader?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Builds one signed client-authentication JWT suitable for SMART/OpenID token
|
|
18
|
+
* requests that use `client_assertion`.
|
|
19
|
+
*
|
|
20
|
+
* Defaults:
|
|
21
|
+
* - algorithm: `ES384`
|
|
22
|
+
* - expiration: `5m`
|
|
23
|
+
* - protected header embeds the generated public JWK
|
|
24
|
+
*
|
|
25
|
+
* The helper is intentionally Node-oriented because it relies on
|
|
26
|
+
* `generateKeyPairSync(...)`. Frontends or wallets that already manage their
|
|
27
|
+
* own keys should build the same JWT shape with their own signer and can still
|
|
28
|
+
* reuse the returned contract fields from this JSDoc.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildClientAssertionJwt(input: BuildClientAssertionJwtInput): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Builds one signed client-authentication JWT and exposes the generated public
|
|
33
|
+
* JWK for callers that also need to register or persist the verification key.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildClientAssertionFixture(input: BuildClientAssertionJwtInput): Promise<{
|
|
36
|
+
jwt: string;
|
|
37
|
+
publicJwk: JsonWebKey;
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { generateKeyPairSync } from 'node:crypto';
|
|
3
|
+
import { exportJWK, SignJWT } from 'jose';
|
|
4
|
+
function resolveAlgorithmDefaults(algorithm) {
|
|
5
|
+
switch (algorithm) {
|
|
6
|
+
case 'ES256':
|
|
7
|
+
return generateKeyPairSync('ec', { namedCurve: 'P-256' });
|
|
8
|
+
case 'ES384':
|
|
9
|
+
return generateKeyPairSync('ec', { namedCurve: 'P-384' });
|
|
10
|
+
case 'ES512':
|
|
11
|
+
return generateKeyPairSync('ec', { namedCurve: 'P-521' });
|
|
12
|
+
case 'EdDSA':
|
|
13
|
+
return generateKeyPairSync('ed25519');
|
|
14
|
+
default:
|
|
15
|
+
throw new Error(`Unsupported client assertion algorithm '${algorithm}'.`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function resolveIssuedAt(value) {
|
|
19
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
20
|
+
return Math.trunc(value);
|
|
21
|
+
if (value instanceof Date)
|
|
22
|
+
return Math.trunc(value.getTime() / 1000);
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Builds one signed client-authentication JWT suitable for SMART/OpenID token
|
|
27
|
+
* requests that use `client_assertion`.
|
|
28
|
+
*
|
|
29
|
+
* Defaults:
|
|
30
|
+
* - algorithm: `ES384`
|
|
31
|
+
* - expiration: `5m`
|
|
32
|
+
* - protected header embeds the generated public JWK
|
|
33
|
+
*
|
|
34
|
+
* The helper is intentionally Node-oriented because it relies on
|
|
35
|
+
* `generateKeyPairSync(...)`. Frontends or wallets that already manage their
|
|
36
|
+
* own keys should build the same JWT shape with their own signer and can still
|
|
37
|
+
* reuse the returned contract fields from this JSDoc.
|
|
38
|
+
*/
|
|
39
|
+
export async function buildClientAssertionJwt(input) {
|
|
40
|
+
const clientId = String(input.clientId || '').trim();
|
|
41
|
+
const audience = String(input.audience || '').trim();
|
|
42
|
+
if (!clientId)
|
|
43
|
+
throw new Error('buildClientAssertionJwt requires clientId.');
|
|
44
|
+
if (!audience)
|
|
45
|
+
throw new Error('buildClientAssertionJwt requires audience.');
|
|
46
|
+
const algorithm = input.algorithm || 'ES384';
|
|
47
|
+
const { privateKey, publicKey } = resolveAlgorithmDefaults(algorithm);
|
|
48
|
+
const publicJwk = await exportJWK(publicKey);
|
|
49
|
+
const protectedHeader = {
|
|
50
|
+
alg: algorithm,
|
|
51
|
+
typ: 'JWT',
|
|
52
|
+
...(input.includePublicJwkInHeader === false ? {} : { jwk: publicJwk }),
|
|
53
|
+
...(input.protectedHeader || {}),
|
|
54
|
+
};
|
|
55
|
+
const jwt = new SignJWT({
|
|
56
|
+
...(input.nonce ? { nonce: input.nonce } : {}),
|
|
57
|
+
...(input.additionalClaims || {}),
|
|
58
|
+
})
|
|
59
|
+
.setProtectedHeader(protectedHeader)
|
|
60
|
+
.setIssuer(String(input.issuer || clientId).trim())
|
|
61
|
+
.setSubject(String(input.subject || clientId).trim())
|
|
62
|
+
.setAudience(audience);
|
|
63
|
+
const issuedAt = resolveIssuedAt(input.issuedAt);
|
|
64
|
+
if (typeof issuedAt === 'number') {
|
|
65
|
+
jwt.setIssuedAt(issuedAt);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
jwt.setIssuedAt();
|
|
69
|
+
}
|
|
70
|
+
return jwt
|
|
71
|
+
.setExpirationTime(input.expiresIn ?? '5m')
|
|
72
|
+
.sign(privateKey);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Builds one signed client-authentication JWT and exposes the generated public
|
|
76
|
+
* JWK for callers that also need to register or persist the verification key.
|
|
77
|
+
*/
|
|
78
|
+
export async function buildClientAssertionFixture(input) {
|
|
79
|
+
const algorithm = input.algorithm || 'ES384';
|
|
80
|
+
const { privateKey, publicKey } = resolveAlgorithmDefaults(algorithm);
|
|
81
|
+
const publicJwk = await exportJWK(publicKey);
|
|
82
|
+
const protectedHeader = {
|
|
83
|
+
alg: algorithm,
|
|
84
|
+
typ: 'JWT',
|
|
85
|
+
...(input.includePublicJwkInHeader === false ? {} : { jwk: publicJwk }),
|
|
86
|
+
...(input.protectedHeader || {}),
|
|
87
|
+
};
|
|
88
|
+
const clientId = String(input.clientId || '').trim();
|
|
89
|
+
const audience = String(input.audience || '').trim();
|
|
90
|
+
if (!clientId)
|
|
91
|
+
throw new Error('buildClientAssertionFixture requires clientId.');
|
|
92
|
+
if (!audience)
|
|
93
|
+
throw new Error('buildClientAssertionFixture requires audience.');
|
|
94
|
+
const jwt = new SignJWT({
|
|
95
|
+
...(input.nonce ? { nonce: input.nonce } : {}),
|
|
96
|
+
...(input.additionalClaims || {}),
|
|
97
|
+
})
|
|
98
|
+
.setProtectedHeader(protectedHeader)
|
|
99
|
+
.setIssuer(String(input.issuer || clientId).trim())
|
|
100
|
+
.setSubject(String(input.subject || clientId).trim())
|
|
101
|
+
.setAudience(audience);
|
|
102
|
+
const issuedAt = resolveIssuedAt(input.issuedAt);
|
|
103
|
+
if (typeof issuedAt === 'number') {
|
|
104
|
+
jwt.setIssuedAt(issuedAt);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
jwt.setIssuedAt();
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
jwt: await jwt.setExpirationTime(input.expiresIn ?? '5m').sign(privateKey),
|
|
111
|
+
publicJwk,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor';
|
|
2
|
+
/**
|
|
3
|
+
* Typed editor for one staged ClinicalImpression resource entry.
|
|
4
|
+
*
|
|
5
|
+
* Use this when a caller needs to stage one clinical-impression row with
|
|
6
|
+
* claims-first accessors in a bundle authoring flow.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ClinicalImpressionEntryEditor extends ClinicalResourceEntryEditor {
|
|
9
|
+
/** Writes the canonical clinical-impression identifier. */
|
|
10
|
+
setIdentifier(identifier?: string | null): this;
|
|
11
|
+
/** Reads the canonical clinical-impression identifier. */
|
|
12
|
+
getIdentifier(): string | undefined;
|
|
13
|
+
/** Ensures the entry has one canonical `urn:uuid:*` identifier. */
|
|
14
|
+
ensureIdentifier(): string;
|
|
15
|
+
/** Writes the subject/patient reference. */
|
|
16
|
+
setSubject(subject?: string | null): this;
|
|
17
|
+
/** Reads the subject/patient reference. */
|
|
18
|
+
getSubject(): string | undefined;
|
|
19
|
+
/** Writes the status. */
|
|
20
|
+
setStatus(value?: string | null): this;
|
|
21
|
+
/** Reads the status. */
|
|
22
|
+
getStatus(): string | undefined;
|
|
23
|
+
/** Writes the description. */
|
|
24
|
+
setDescription(value?: string | null): this;
|
|
25
|
+
/** Reads the description. */
|
|
26
|
+
getDescription(): string | undefined;
|
|
27
|
+
/** Writes the linked encounter reference. */
|
|
28
|
+
setEncounter(value?: string | null): this;
|
|
29
|
+
/** Reads the linked encounter reference. */
|
|
30
|
+
getEncounter(): string | undefined;
|
|
31
|
+
/** Writes the effective date/time. */
|
|
32
|
+
setEffectiveDateTime(value?: string | null): this;
|
|
33
|
+
/** Reads the effective date/time. */
|
|
34
|
+
getEffectiveDateTime(): string | undefined;
|
|
35
|
+
/** Writes the assessor reference. */
|
|
36
|
+
setAssessor(value?: string | null): this;
|
|
37
|
+
/** Reads the assessor reference. */
|
|
38
|
+
getAssessor(): string | undefined;
|
|
39
|
+
/** Writes the summary text. */
|
|
40
|
+
setSummary(value?: string | null): this;
|
|
41
|
+
/** Reads the summary text. */
|
|
42
|
+
getSummary(): string | undefined;
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ClinicalResourceEntryEditor } from './clinical-resource-entry-editor.js';
|
|
2
|
+
import { ClinicalImpressionClaim } from '../models/interoperable-claims/clinical-impression-claims.js';
|
|
3
|
+
import { BundleEditableResourceTypes } from '../models/bundle-editor-types.js';
|
|
4
|
+
import { registerBundleEntryEditor } from './bundle-editor-registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Typed editor for one staged ClinicalImpression resource entry.
|
|
7
|
+
*
|
|
8
|
+
* Use this when a caller needs to stage one clinical-impression row with
|
|
9
|
+
* claims-first accessors in a bundle authoring flow.
|
|
10
|
+
*/
|
|
11
|
+
export class ClinicalImpressionEntryEditor extends ClinicalResourceEntryEditor {
|
|
12
|
+
/** Writes the canonical clinical-impression identifier. */
|
|
13
|
+
setIdentifier(identifier) { return this.setIdentifierValue(ClinicalImpressionClaim.Identifier, identifier); }
|
|
14
|
+
/** Reads the canonical clinical-impression identifier. */
|
|
15
|
+
getIdentifier() { return this.getIdentifierValue(ClinicalImpressionClaim.Identifier); }
|
|
16
|
+
/** Ensures the entry has one canonical `urn:uuid:*` identifier. */
|
|
17
|
+
ensureIdentifier() { return this.ensureIdentifierValue(ClinicalImpressionClaim.Identifier); }
|
|
18
|
+
/** Writes the subject/patient reference. */
|
|
19
|
+
setSubject(subject) { return this.setSubjectClaims(ClinicalImpressionClaim.Subject, ClinicalImpressionClaim.Subject, subject); }
|
|
20
|
+
/** Reads the subject/patient reference. */
|
|
21
|
+
getSubject() { return this.getSubjectClaims(ClinicalImpressionClaim.Subject, ClinicalImpressionClaim.Subject); }
|
|
22
|
+
/** Writes the status. */
|
|
23
|
+
setStatus(value) { return this.setScalarClaim(ClinicalImpressionClaim.Status, value); }
|
|
24
|
+
/** Reads the status. */
|
|
25
|
+
getStatus() { return this.getScalarClaim(ClinicalImpressionClaim.Status); }
|
|
26
|
+
/** Writes the description. */
|
|
27
|
+
setDescription(value) { return this.setScalarClaim(ClinicalImpressionClaim.Description, value); }
|
|
28
|
+
/** Reads the description. */
|
|
29
|
+
getDescription() { return this.getScalarClaim(ClinicalImpressionClaim.Description); }
|
|
30
|
+
/** Writes the linked encounter reference. */
|
|
31
|
+
setEncounter(value) { return this.setScalarClaim(ClinicalImpressionClaim.Encounter, value); }
|
|
32
|
+
/** Reads the linked encounter reference. */
|
|
33
|
+
getEncounter() { return this.getScalarClaim(ClinicalImpressionClaim.Encounter); }
|
|
34
|
+
/** Writes the effective date/time. */
|
|
35
|
+
setEffectiveDateTime(value) { return this.setScalarClaim(ClinicalImpressionClaim.EffectiveDateTime, value); }
|
|
36
|
+
/** Reads the effective date/time. */
|
|
37
|
+
getEffectiveDateTime() { return this.getScalarClaim(ClinicalImpressionClaim.EffectiveDateTime); }
|
|
38
|
+
/** Writes the assessor reference. */
|
|
39
|
+
setAssessor(value) { return this.setScalarClaim(ClinicalImpressionClaim.Assessor, value); }
|
|
40
|
+
/** Reads the assessor reference. */
|
|
41
|
+
getAssessor() { return this.getScalarClaim(ClinicalImpressionClaim.Assessor); }
|
|
42
|
+
/** Writes the summary text. */
|
|
43
|
+
setSummary(value) { return this.setScalarClaim(ClinicalImpressionClaim.Summary, value); }
|
|
44
|
+
/** Reads the summary text. */
|
|
45
|
+
getSummary() { return this.getScalarClaim(ClinicalImpressionClaim.Summary); }
|
|
46
|
+
}
|
|
47
|
+
registerBundleEntryEditor(BundleEditableResourceTypes.clinicalImpression, ClinicalImpressionEntryEditor);
|