@oystehr/sdk 4.3.9 → 4.3.11
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/dist/cjs/client/client.cjs +12 -5
- package/dist/cjs/client/client.cjs.map +1 -1
- package/dist/cjs/client/client.d.ts +5 -0
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/cjs/index.min.cjs.map +1 -1
- package/dist/cjs/resources/classes/fhir-ext.cjs +196 -4
- package/dist/cjs/resources/classes/fhir-ext.cjs.map +1 -1
- package/dist/cjs/resources/classes/fhir-ext.d.ts +70 -3
- package/dist/cjs/resources/classes/fhir.cjs +14 -3
- package/dist/cjs/resources/classes/fhir.cjs.map +1 -1
- package/dist/cjs/resources/classes/fhir.d.ts +14 -3
- package/dist/cjs/resources/types/FaxSendParams.d.ts +1 -1
- package/dist/cjs/resources/types/ZambdaCreateParams.d.ts +1 -1
- package/dist/cjs/resources/types/ZambdaUpdateParams.d.ts +1 -1
- package/dist/cjs/resources/types/fhir.d.ts +20 -0
- package/dist/esm/client/client.d.ts +5 -0
- package/dist/esm/client/client.js +12 -5
- package/dist/esm/client/client.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/resources/classes/fhir-ext.d.ts +70 -3
- package/dist/esm/resources/classes/fhir-ext.js +194 -5
- package/dist/esm/resources/classes/fhir-ext.js.map +1 -1
- package/dist/esm/resources/classes/fhir.d.ts +14 -3
- package/dist/esm/resources/classes/fhir.js +15 -4
- package/dist/esm/resources/classes/fhir.js.map +1 -1
- package/dist/esm/resources/types/FaxSendParams.d.ts +1 -1
- package/dist/esm/resources/types/ZambdaCreateParams.d.ts +1 -1
- package/dist/esm/resources/types/ZambdaUpdateParams.d.ts +1 -1
- package/dist/esm/resources/types/fhir.d.ts +20 -0
- package/package.json +1 -1
- package/src/client/client.ts +22 -8
- package/src/resources/classes/fhir-ext.ts +257 -7
- package/src/resources/classes/fhir.ts +14 -3
- package/src/resources/types/FaxSendParams.ts +1 -1
- package/src/resources/types/ZambdaCreateParams.ts +1 -1
- package/src/resources/types/ZambdaUpdateParams.ts +1 -1
- package/src/resources/types/fhir.ts +22 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Address as AddressR4B, HumanName as HumanNameR4B } from 'fhir/r4b';
|
|
2
2
|
import { Address as AddressR5, HumanName as HumanNameR5 } from 'fhir/r5';
|
|
3
|
-
import { BatchBundle, BatchInput, Bundle, FhirAsyncJobHandle, FhirAsyncJobStatus, FhirAsyncWaitOptions, FhirCreateParams, FhirDeleteParams, FhirGetParams, FhirHistoryGetParams, FhirHistorySearchParams, FhirPatchParams, FhirResource, FhirResourceReturnValue, FhirResponseMode, FhirSearchParams, FhirUpdateParams, GenerateFriendlyPatientIdParams, TransactionBundle } from '../..';
|
|
3
|
+
import { BatchBundle, BatchInput, Bundle, FhirAsyncBulkOutputResult, FhirAsyncJobHandle, FhirAsyncJobStatus, FhirAsyncWaitOptions, FhirCreateParams, FhirDeleteParams, FhirGetParams, FhirHistoryGetParams, FhirHistorySearchParams, FhirPatchParams, FhirResource, FhirResourceReturnValue, FhirResponseMode, FhirSearchParams, FhirUpdateParams, GenerateFriendlyPatientIdParams, SearchParam, TransactionBundle } from '../..';
|
|
4
4
|
import { FhirFetcherResponse, OystehrClientRequest, SDKResource } from '../../client/client';
|
|
5
5
|
/**
|
|
6
6
|
* Optional parameter that can be passed to the client methods. It allows
|
|
@@ -16,6 +16,26 @@ export interface OystehrFHIRUpdateClientRequest extends OystehrClientRequest {
|
|
|
16
16
|
*/
|
|
17
17
|
optimisticLockingVersionId?: string;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Optional parameter that can be passed to the FHIR create method. In addition
|
|
21
|
+
* to the standard request options, it supports FHIR conditional create via the
|
|
22
|
+
* 'If-None-Exist' header.
|
|
23
|
+
*/
|
|
24
|
+
export interface OystehrFHIRCreateClientRequest extends OystehrClientRequest {
|
|
25
|
+
/**
|
|
26
|
+
* Perform a FHIR conditional create using the 'If-None-Exist' header. The value is a
|
|
27
|
+
* FHIR search query that identifies whether a matching resource already exists:
|
|
28
|
+
* - if no resource matches, the resource is created as normal;
|
|
29
|
+
* - if exactly one resource matches, no resource is created and the existing one is returned;
|
|
30
|
+
* - if more than one resource matches, the request fails with a 412 Precondition Failed error.
|
|
31
|
+
*
|
|
32
|
+
* Accepts either a raw search query string (e.g. `'identifier=http://acme.org|1234'`) or an
|
|
33
|
+
* array of SearchParam objects (e.g. `[{ name: 'identifier', value: 'http://acme.org|1234' }]`).
|
|
34
|
+
*
|
|
35
|
+
* @see https://www.hl7.org/fhir/http.html#cond-update for the conditional create specification.
|
|
36
|
+
*/
|
|
37
|
+
ifNoneExist?: string | SearchParam[];
|
|
38
|
+
}
|
|
19
39
|
/**
|
|
20
40
|
* Performs a FHIR search and returns the results as a Bundle resource
|
|
21
41
|
*
|
|
@@ -29,10 +49,24 @@ export declare function search<T extends FhirResource>(this: SDKResource, params
|
|
|
29
49
|
export declare function search<T extends FhirResource>(this: SDKResource, params: FhirSearchParams<T>, request?: OystehrClientRequest & {
|
|
30
50
|
mode?: 'sync' | undefined;
|
|
31
51
|
}): Promise<FhirFetcherResponse<Bundle<T>>>;
|
|
32
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Performs an iterative FHIR search over initial request and following "next" urls,
|
|
54
|
+
* collecting all pages into a single Bundle.
|
|
55
|
+
*
|
|
56
|
+
* @param params FHIR search parameters plus optional pageSize that will overwrite _count in params
|
|
57
|
+
* @param request optional OystehrClientRequest object
|
|
58
|
+
* @returns FHIR Bundle resource that contains all entries across all pages. Bundle-level metadata
|
|
59
|
+
* (id, meta, total, etc.) is taken from the first page.
|
|
60
|
+
*/
|
|
61
|
+
export declare function searchAndGetAllPages<T extends FhirResource>(this: SDKResource, params: FhirSearchParams<T> & {
|
|
62
|
+
pageSize?: number;
|
|
63
|
+
}, request?: OystehrClientRequest & {
|
|
64
|
+
mode?: 'sync' | undefined;
|
|
65
|
+
}): Promise<Bundle<T>>;
|
|
66
|
+
export declare function create<T extends FhirResource>(this: SDKResource, params: FhirCreateParams<T>, request: OystehrFHIRCreateClientRequest & {
|
|
33
67
|
mode: Exclude<FhirResponseMode, 'sync'>;
|
|
34
68
|
}): Promise<FhirAsyncJobHandle>;
|
|
35
|
-
export declare function create<T extends FhirResource>(this: SDKResource, params: FhirCreateParams<T>, request?:
|
|
69
|
+
export declare function create<T extends FhirResource>(this: SDKResource, params: FhirCreateParams<T>, request?: OystehrFHIRCreateClientRequest & {
|
|
36
70
|
mode?: 'sync' | undefined;
|
|
37
71
|
}): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>>;
|
|
38
72
|
export declare function get<T extends FhirResource>(this: SDKResource, { resourceType, id }: FhirGetParams<T>, request: OystehrClientRequest & {
|
|
@@ -60,8 +94,41 @@ declare function del<T extends FhirResource>(this: SDKResource, params: FhirDele
|
|
|
60
94
|
mode?: 'sync' | undefined;
|
|
61
95
|
}): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>>;
|
|
62
96
|
export { del as delete };
|
|
97
|
+
/**
|
|
98
|
+
* Fetches the status of an async job. If the job is still in progress, returns an object with status 202. If the job is completed, returns the job result with status 200. If the job has failed, returns an object with status 500 and an OperationOutcome resource describing the failure. If the job has expired, returns an object with status 410.
|
|
99
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.getAsyncJob(jobId)`)
|
|
100
|
+
* @param jobId The ID of the async job to fetch
|
|
101
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
102
|
+
* @returns A Promise that resolves to the FhirAsyncJobStatus
|
|
103
|
+
*/
|
|
63
104
|
export declare function getAsyncJob<T extends FhirResource>(this: SDKResource, jobId: string, request?: OystehrClientRequest): Promise<FhirAsyncJobStatus<T>>;
|
|
105
|
+
/**
|
|
106
|
+
* Waits for an async job to complete by polling its status until it reaches a terminal state (success, failure, or expiration) or the specified timeout is reached. Returns the final job status. Throws if the job fails, expires, or does not complete within the timeout.
|
|
107
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.waitForAsyncJob(jobId)`)
|
|
108
|
+
* @param jobId The ID of the async job to wait for
|
|
109
|
+
* @param options Optional FhirAsyncWaitOptions to configure polling behavior
|
|
110
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
111
|
+
* @returns A Promise that resolves to the final FhirAsyncJobStatus
|
|
112
|
+
*/
|
|
64
113
|
export declare function waitForAsyncJob<T extends FhirResource>(this: SDKResource, jobId: string, options?: FhirAsyncWaitOptions, request?: OystehrClientRequest): Promise<FhirAsyncJobStatus<T>>;
|
|
114
|
+
/**
|
|
115
|
+
* Waits for an async job to complete and retrieves the bulk output manifest and files. Throws if the job fails, expires, or does not complete within the specified timeout.
|
|
116
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.waitForAsyncBulkOutput(jobId)`)
|
|
117
|
+
* @param jobId The ID of the async job to wait for
|
|
118
|
+
* @param options Optional FhirAsyncWaitOptions to configure polling behavior
|
|
119
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
120
|
+
* @returns A Promise that resolves to a FhirAsyncBulkOutputResult containing the bulk output manifest and files
|
|
121
|
+
*/
|
|
122
|
+
export declare function waitForAsyncBulkOutput<T extends FhirResource>(this: SDKResource, jobId: string, options?: FhirAsyncWaitOptions, request?: OystehrClientRequest): Promise<FhirAsyncBulkOutputResult<T>>;
|
|
123
|
+
/**
|
|
124
|
+
* Wrapper around waitForAsyncBulkOutput that transforms the retrieved bulk output files into a single Bundle resource containing all the output resources as entries. This is a convenience method for use cases where you want to work with the bulk output as a Bundle, but it may not be efficient for large outputs due to the overhead of downloading and parsing all files and constructing the Bundle in memory.
|
|
125
|
+
* Can be slow due to downloading and parsing potentially large NDJSON files, so use only if you need the full output as a Bundle resource. For more efficient processing of large bulk outputs, use waitForAsyncBulkOutput directly.
|
|
126
|
+
* @param jobId the ID of the async job to wait for
|
|
127
|
+
* @param options optional FhirAsyncWaitOptions to configure polling behavior
|
|
128
|
+
* @param request optional OystehrClientRequest for authentication and headers
|
|
129
|
+
* @returns a Promise that resolves to a Bundle containing all resources from the bulk output
|
|
130
|
+
*/
|
|
131
|
+
export declare function waitForAsyncBulkBundle<T extends FhirResource>(this: SDKResource, jobId: string, options?: FhirAsyncWaitOptions, request?: OystehrClientRequest): Promise<Bundle<T>>;
|
|
65
132
|
export declare function cancelAsyncJob(this: SDKResource, jobId: string, request?: OystehrClientRequest): Promise<void>;
|
|
66
133
|
export declare function history<T extends FhirResource>(this: SDKResource, { resourceType, id }: FhirHistorySearchParams<T>, request: OystehrClientRequest & {
|
|
67
134
|
mode: Exclude<FhirResponseMode, 'sync'>;
|
|
@@ -193,6 +193,21 @@ function assertRetrievedResource(config, resource) {
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Serializes an If-None-Exist value into a FHIR search query string. A raw string is
|
|
198
|
+
* returned unchanged; an array of SearchParam objects is encoded as a query string
|
|
199
|
+
* (e.g. "identifier=sys|123&active=true").
|
|
200
|
+
*/
|
|
201
|
+
function ifNoneExistToString(value) {
|
|
202
|
+
if (typeof value === 'string') {
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
const search = new URLSearchParams();
|
|
206
|
+
for (const param of value) {
|
|
207
|
+
search.append(param.name, String(param.value));
|
|
208
|
+
}
|
|
209
|
+
return search.toString();
|
|
210
|
+
}
|
|
196
211
|
function isAsyncRequestMode(mode) {
|
|
197
212
|
return mode === 'async-bundle' || mode === 'async-bulk';
|
|
198
213
|
}
|
|
@@ -229,14 +244,59 @@ async function search(params, request) {
|
|
|
229
244
|
};
|
|
230
245
|
return bundle;
|
|
231
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Performs an iterative FHIR search over initial request and following "next" urls,
|
|
249
|
+
* collecting all pages into a single Bundle.
|
|
250
|
+
*
|
|
251
|
+
* @param params FHIR search parameters plus optional pageSize that will overwrite _count in params
|
|
252
|
+
* @param request optional OystehrClientRequest object
|
|
253
|
+
* @returns FHIR Bundle resource that contains all entries across all pages. Bundle-level metadata
|
|
254
|
+
* (id, meta, total, etc.) is taken from the first page.
|
|
255
|
+
*/
|
|
256
|
+
async function searchAndGetAllPages(params, request) {
|
|
257
|
+
const { pageSize, ...searchParams } = params;
|
|
258
|
+
let firstPageParams = searchParams;
|
|
259
|
+
if (pageSize) {
|
|
260
|
+
const baseParams = (searchParams.params ?? []).filter((p) => p.name !== '_count') ?? [];
|
|
261
|
+
firstPageParams = { ...searchParams, params: [...baseParams, { name: '_count', value: pageSize }] };
|
|
262
|
+
}
|
|
263
|
+
const allEntries = [];
|
|
264
|
+
const typedSearch = (search);
|
|
265
|
+
// search returns Bundle, and fhirRequest in the while block returns FhirBundle
|
|
266
|
+
let currentBundle = await typedSearch.call(this, firstPageParams, request);
|
|
267
|
+
const firstBundle = { ...currentBundle, link: currentBundle.link?.filter((link) => link.relation !== 'next') };
|
|
268
|
+
// eslint-disable-next-line no-constant-condition
|
|
269
|
+
while (true) {
|
|
270
|
+
const entries = currentBundle.entry;
|
|
271
|
+
if (entries) {
|
|
272
|
+
allEntries.push(...entries);
|
|
273
|
+
}
|
|
274
|
+
const nextLink = currentBundle.link?.find((link) => link.relation === 'next')?.url;
|
|
275
|
+
if (!nextLink) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
currentBundle = await this.fhirRequest(nextLink, 'GET')({}, request);
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
...firstBundle,
|
|
282
|
+
entry: allEntries.length ? allEntries : undefined,
|
|
283
|
+
unbundle: function () {
|
|
284
|
+
return this.entry?.map((e) => e.resource).filter((r) => r !== undefined) ?? [];
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
232
288
|
async function create(params, request) {
|
|
233
289
|
const tagged = applyTagToResource(this.config, params);
|
|
234
290
|
const { resourceType } = tagged;
|
|
235
291
|
const requestMode = request?.mode;
|
|
292
|
+
const ifNoneExistRequest = {
|
|
293
|
+
...request,
|
|
294
|
+
ifNoneExist: request?.ifNoneExist !== undefined ? ifNoneExistToString(request.ifNoneExist) : undefined,
|
|
295
|
+
};
|
|
236
296
|
if (isAsyncRequestMode(requestMode)) {
|
|
237
|
-
return await this.startAsyncJob(`/${resourceType}`, 'POST', tagged, requestMode,
|
|
297
|
+
return await this.startAsyncJob(`/${resourceType}`, 'POST', tagged, requestMode, ifNoneExistRequest);
|
|
238
298
|
}
|
|
239
|
-
return await this.fhirRequest(`/${resourceType}`, 'POST')(tagged,
|
|
299
|
+
return await this.fhirRequest(`/${resourceType}`, 'POST')(tagged, ifNoneExistRequest);
|
|
240
300
|
}
|
|
241
301
|
async function get({ resourceType, id }, request) {
|
|
242
302
|
const requestMode = request?.mode;
|
|
@@ -299,9 +359,24 @@ function getRetryDelayMs(retryAfter, fallbackMs) {
|
|
|
299
359
|
}
|
|
300
360
|
return fallbackMs;
|
|
301
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* Fetches the status of an async job. If the job is still in progress, returns an object with status 202. If the job is completed, returns the job result with status 200. If the job has failed, returns an object with status 500 and an OperationOutcome resource describing the failure. If the job has expired, returns an object with status 410.
|
|
364
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.getAsyncJob(jobId)`)
|
|
365
|
+
* @param jobId The ID of the async job to fetch
|
|
366
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
367
|
+
* @returns A Promise that resolves to the FhirAsyncJobStatus
|
|
368
|
+
*/
|
|
302
369
|
async function getAsyncJob(jobId, request) {
|
|
303
370
|
return await this.fetchAsyncJobStatus(jobId, request);
|
|
304
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Waits for an async job to complete by polling its status until it reaches a terminal state (success, failure, or expiration) or the specified timeout is reached. Returns the final job status. Throws if the job fails, expires, or does not complete within the timeout.
|
|
374
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.waitForAsyncJob(jobId)`)
|
|
375
|
+
* @param jobId The ID of the async job to wait for
|
|
376
|
+
* @param options Optional FhirAsyncWaitOptions to configure polling behavior
|
|
377
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
378
|
+
* @returns A Promise that resolves to the final FhirAsyncJobStatus
|
|
379
|
+
*/
|
|
305
380
|
async function waitForAsyncJob(jobId, options, request) {
|
|
306
381
|
// 5 seconds poll interval by default
|
|
307
382
|
const pollIntervalMs = options?.pollIntervalMs ?? 5000;
|
|
@@ -323,6 +398,116 @@ async function waitForAsyncJob(jobId, options, request) {
|
|
|
323
398
|
code: 408,
|
|
324
399
|
});
|
|
325
400
|
}
|
|
401
|
+
function parseNdjsonResources(ndjson, sourceUrl) {
|
|
402
|
+
const resources = [];
|
|
403
|
+
const lines = ndjson.split('\n');
|
|
404
|
+
for (let index = 0; index < lines.length; index++) {
|
|
405
|
+
const line = lines[index].trim();
|
|
406
|
+
if (line.length === 0) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
resources.push(JSON.parse(line));
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
throw new OystehrSdkError({
|
|
414
|
+
message: `Failed to parse NDJSON line ${index + 1} from ${sourceUrl}`,
|
|
415
|
+
code: 500,
|
|
416
|
+
cause: error,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return resources;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Waits for an async job to complete and retrieves the bulk output manifest and files. Throws if the job fails, expires, or does not complete within the specified timeout.
|
|
424
|
+
* @param this The SDKResource context (this is an extension method and should be called with the SDKResource instance as the context, e.g. `sdkResource.waitForAsyncBulkOutput(jobId)`)
|
|
425
|
+
* @param jobId The ID of the async job to wait for
|
|
426
|
+
* @param options Optional FhirAsyncWaitOptions to configure polling behavior
|
|
427
|
+
* @param request Optional OystehrClientRequest for authentication and headers
|
|
428
|
+
* @returns A Promise that resolves to a FhirAsyncBulkOutputResult containing the bulk output manifest and files
|
|
429
|
+
*/
|
|
430
|
+
async function waitForAsyncBulkOutput(jobId, options, request) {
|
|
431
|
+
const status = await waitForAsyncJob.call(this, jobId, options, request);
|
|
432
|
+
if (status.status === 404) {
|
|
433
|
+
throw new OystehrSdkError({
|
|
434
|
+
message: `Async job ${jobId} not found`,
|
|
435
|
+
code: 404,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
if (status.status === 410) {
|
|
439
|
+
throw new OystehrSdkError({
|
|
440
|
+
message: `Async job ${jobId} expired`,
|
|
441
|
+
code: 410,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (status.status !== 200 || !('mode' in status) || status.mode !== 'bulk') {
|
|
445
|
+
throw new OystehrSdkError({
|
|
446
|
+
message: `Async job ${jobId} did not complete in bulk mode`,
|
|
447
|
+
code: status.status,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
const accessToken = request?.accessToken ?? this.config.accessToken;
|
|
451
|
+
const projectId = request?.projectId ?? this.config.projectId;
|
|
452
|
+
if (status.manifest.requiresAccessToken && !accessToken) {
|
|
453
|
+
throw new OystehrSdkError({
|
|
454
|
+
message: `Bulk output for async job ${jobId} requires an access token`,
|
|
455
|
+
code: 401,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
const fetchImpl = this.config.fetch ?? fetch;
|
|
459
|
+
const headers = {};
|
|
460
|
+
if (projectId) {
|
|
461
|
+
headers['x-zapehr-project-id'] = projectId;
|
|
462
|
+
headers['x-oystehr-project-id'] = projectId;
|
|
463
|
+
}
|
|
464
|
+
if (status.manifest.requiresAccessToken && accessToken) {
|
|
465
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
466
|
+
}
|
|
467
|
+
const requestHeaders = Object.keys(headers).length > 0 ? headers : undefined;
|
|
468
|
+
const output = await Promise.all(status.manifest.output.map(async (file) => {
|
|
469
|
+
const response = await fetchImpl(new Request(file.url, {
|
|
470
|
+
method: 'GET',
|
|
471
|
+
headers: requestHeaders,
|
|
472
|
+
}));
|
|
473
|
+
if (!response.ok) {
|
|
474
|
+
throw new OystehrSdkError({
|
|
475
|
+
message: `Failed to download bulk output (${file.type}): HTTP ${response.status}`,
|
|
476
|
+
code: response.status,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
const ndjson = await response.text();
|
|
480
|
+
return {
|
|
481
|
+
...file,
|
|
482
|
+
resources: parseNdjsonResources(ndjson, file.url),
|
|
483
|
+
};
|
|
484
|
+
}));
|
|
485
|
+
return {
|
|
486
|
+
manifest: status.manifest,
|
|
487
|
+
output,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Wrapper around waitForAsyncBulkOutput that transforms the retrieved bulk output files into a single Bundle resource containing all the output resources as entries. This is a convenience method for use cases where you want to work with the bulk output as a Bundle, but it may not be efficient for large outputs due to the overhead of downloading and parsing all files and constructing the Bundle in memory.
|
|
492
|
+
* Can be slow due to downloading and parsing potentially large NDJSON files, so use only if you need the full output as a Bundle resource. For more efficient processing of large bulk outputs, use waitForAsyncBulkOutput directly.
|
|
493
|
+
* @param jobId the ID of the async job to wait for
|
|
494
|
+
* @param options optional FhirAsyncWaitOptions to configure polling behavior
|
|
495
|
+
* @param request optional OystehrClientRequest for authentication and headers
|
|
496
|
+
* @returns a Promise that resolves to a Bundle containing all resources from the bulk output
|
|
497
|
+
*/
|
|
498
|
+
async function waitForAsyncBulkBundle(jobId, options, request) {
|
|
499
|
+
const bulkOutput = await waitForAsyncBulkOutput.call(this, jobId, options, request);
|
|
500
|
+
const resources = bulkOutput.output.flatMap((file) => file.resources);
|
|
501
|
+
const bundle = {
|
|
502
|
+
resourceType: 'Bundle',
|
|
503
|
+
type: 'collection',
|
|
504
|
+
entry: resources.map((resource) => ({ resource })),
|
|
505
|
+
unbundle: function () {
|
|
506
|
+
return this.entry?.map((entry) => entry.resource).filter((value) => value !== undefined) ?? [];
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
return bundle;
|
|
510
|
+
}
|
|
326
511
|
async function cancelAsyncJob(jobId, request) {
|
|
327
512
|
await this.fhirRequest(`/async-job/${jobId}`, 'DELETE')({}, request);
|
|
328
513
|
}
|
|
@@ -460,9 +645,13 @@ function batchInputRequestToBundleEntryItem(request, config) {
|
|
|
460
645
|
// POST creates require a full resource
|
|
461
646
|
if (method === 'POST' && 'resource' in request) {
|
|
462
647
|
const resource = applyTagToResource(config, request.resource);
|
|
463
|
-
const { fullUrl } = request;
|
|
648
|
+
const { fullUrl, ifNoneExist } = request;
|
|
464
649
|
return {
|
|
465
|
-
|
|
650
|
+
request: {
|
|
651
|
+
...baseRequest.request,
|
|
652
|
+
// Conditional create: only create the resource if no existing resource matches the query.
|
|
653
|
+
ifNoneExist: ifNoneExist !== undefined ? ifNoneExistToString(ifNoneExist) : undefined,
|
|
654
|
+
},
|
|
466
655
|
resource: resource,
|
|
467
656
|
fullUrl,
|
|
468
657
|
};
|
|
@@ -608,5 +797,5 @@ function formatHumanName(name, options) {
|
|
|
608
797
|
return builder.join(' ').trim();
|
|
609
798
|
}
|
|
610
799
|
|
|
611
|
-
export { batch, cancelAsyncJob, create, del as delete, formatAddress, formatHumanName, generateFriendlyPatientId, get, getAsyncJob, history, patch, search, transaction, update, waitForAsyncJob };
|
|
800
|
+
export { batch, cancelAsyncJob, create, del as delete, formatAddress, formatHumanName, generateFriendlyPatientId, get, getAsyncJob, history, patch, search, searchAndGetAllPages, transaction, update, waitForAsyncBulkBundle, waitForAsyncBulkOutput, waitForAsyncJob };
|
|
612
801
|
//# sourceMappingURL=fhir-ext.js.map
|