@medplum/core 2.0.21 → 2.0.23
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/index.cjs +720 -494
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/client.mjs +197 -114
- package/dist/esm/client.mjs.map +1 -1
- package/dist/esm/crypto.mjs +3 -1
- package/dist/esm/crypto.mjs.map +1 -1
- package/dist/esm/fhirlexer/parse.mjs.map +1 -1
- package/dist/esm/fhirlexer/tokenize.mjs +2 -2
- package/dist/esm/fhirlexer/tokenize.mjs.map +1 -1
- package/dist/esm/fhirpath/atoms.mjs +63 -56
- package/dist/esm/fhirpath/atoms.mjs.map +1 -1
- package/dist/esm/fhirpath/functions.mjs +370 -252
- package/dist/esm/fhirpath/functions.mjs.map +1 -1
- package/dist/esm/fhirpath/parse.mjs +4 -2
- package/dist/esm/fhirpath/parse.mjs.map +1 -1
- package/dist/esm/format.mjs +6 -4
- package/dist/esm/format.mjs.map +1 -1
- package/dist/esm/hl7.mjs +1 -1
- package/dist/esm/hl7.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/jwt.mjs +4 -2
- package/dist/esm/jwt.mjs.map +1 -1
- package/dist/esm/outcomes.mjs +14 -11
- package/dist/esm/outcomes.mjs.map +1 -1
- package/dist/esm/schema.mjs +4 -10
- package/dist/esm/schema.mjs.map +1 -1
- package/dist/esm/search/details.mjs +4 -5
- package/dist/esm/search/details.mjs.map +1 -1
- package/dist/esm/search/match.mjs +1 -0
- package/dist/esm/search/match.mjs.map +1 -1
- package/dist/esm/search/search.mjs +1 -1
- package/dist/esm/search/search.mjs.map +1 -1
- package/dist/esm/storage.mjs +8 -0
- package/dist/esm/storage.mjs.map +1 -1
- package/dist/esm/types.mjs +1 -0
- package/dist/esm/types.mjs.map +1 -1
- package/dist/esm/utils.mjs +8 -7
- package/dist/esm/utils.mjs.map +1 -1
- package/dist/types/client.d.ts +128 -69
- package/dist/types/crypto.d.ts +3 -1
- package/dist/types/fhirlexer/parse.d.ts +7 -3
- package/dist/types/fhirpath/atoms.d.ts +21 -21
- package/dist/types/fhirpath/functions.d.ts +2 -2
- package/dist/types/fhirpath/parse.d.ts +2 -1
- package/dist/types/hl7.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/jwt.d.ts +2 -1
- package/dist/types/outcomes.d.ts +7 -1
- package/dist/types/schema.d.ts +4 -10
- package/dist/types/search/details.d.ts +0 -1
- package/dist/types/search/search.d.ts +1 -1
- package/dist/types/storage.d.ts +8 -0
- package/dist/types/typeschema/types.d.ts +0 -1
- package/dist/types/utils.d.ts +5 -12
- package/package.json +1 -1
package/dist/esm/client.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
import { encodeBase64 } from './base64.mjs';
|
|
1
2
|
import { LRUCache } from './cache.mjs';
|
|
2
3
|
import { getRandomString, encryptSHA256 } from './crypto.mjs';
|
|
3
4
|
import { EventTarget } from './eventtarget.mjs';
|
|
4
5
|
import { parseJWTPayload } from './jwt.mjs';
|
|
5
|
-
import { OperationOutcomeError, notFound, normalizeOperationOutcome, isOk } from './outcomes.mjs';
|
|
6
|
+
import { OperationOutcomeError, notFound, normalizeOperationOutcome, isOk, badRequest } from './outcomes.mjs';
|
|
6
7
|
import { ReadablePromise } from './readablepromise.mjs';
|
|
7
8
|
import { ClientStorage } from './storage.mjs';
|
|
8
9
|
import { globalSchema, indexStructureDefinition, indexSearchParameter } from './types.mjs';
|
|
9
10
|
import { createReference, arrayBufferToBase64 } from './utils.mjs';
|
|
10
|
-
import { encodeBase64 } from './base64.mjs';
|
|
11
11
|
|
|
12
12
|
// PKCE auth based on:
|
|
13
13
|
// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
|
|
14
|
-
const MEDPLUM_VERSION = "2.0.
|
|
14
|
+
const MEDPLUM_VERSION = "2.0.23-b244eeae" ;
|
|
15
15
|
const DEFAULT_BASE_URL = 'https://api.medplum.com/';
|
|
16
16
|
const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
|
|
17
17
|
const DEFAULT_CACHE_TIME = 60000; // 60 seconds
|
|
@@ -98,7 +98,6 @@ var OAuthTokenType;
|
|
|
98
98
|
* <head>
|
|
99
99
|
* <meta name="algolia:pageRank" content="100" />
|
|
100
100
|
* </head>
|
|
101
|
-
|
|
102
101
|
*/
|
|
103
102
|
class MedplumClient extends EventTarget {
|
|
104
103
|
constructor(options) {
|
|
@@ -151,6 +150,16 @@ class MedplumClient extends EventTarget {
|
|
|
151
150
|
getBaseUrl() {
|
|
152
151
|
return this.baseUrl;
|
|
153
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Returns the current authorize URL.
|
|
155
|
+
* By default, this is set to `https://api.medplum.com/oauth2/authorize`.
|
|
156
|
+
* This can be overridden by setting the `authorizeUrl` option when creating the client.
|
|
157
|
+
* @category HTTP
|
|
158
|
+
* @returns The current authorize URL.
|
|
159
|
+
*/
|
|
160
|
+
getAuthorizeUrl() {
|
|
161
|
+
return this.authorizeUrl;
|
|
162
|
+
}
|
|
154
163
|
/**
|
|
155
164
|
* Clears all auth state including local storage and session storage.
|
|
156
165
|
* @category Authentication
|
|
@@ -165,12 +174,14 @@ class MedplumClient extends EventTarget {
|
|
|
165
174
|
* @category Authentication
|
|
166
175
|
*/
|
|
167
176
|
clearActiveLogin() {
|
|
177
|
+
if (this.basicAuth) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
168
180
|
this.storage.setString('activeLogin', undefined);
|
|
169
181
|
this.requestCache?.clear();
|
|
170
182
|
this.accessToken = undefined;
|
|
171
183
|
this.refreshToken = undefined;
|
|
172
|
-
this.
|
|
173
|
-
this.config = undefined;
|
|
184
|
+
this.sessionDetails = undefined;
|
|
174
185
|
this.dispatchEvent({ type: 'change' });
|
|
175
186
|
}
|
|
176
187
|
/**
|
|
@@ -210,7 +221,6 @@ class MedplumClient extends EventTarget {
|
|
|
210
221
|
* This is a lower level method for custom requests.
|
|
211
222
|
* For common operations, we recommend using higher level methods
|
|
212
223
|
* such as `readResource()`, `search()`, etc.
|
|
213
|
-
*
|
|
214
224
|
* @category HTTP
|
|
215
225
|
* @param url The target URL.
|
|
216
226
|
* @param options Optional fetch options.
|
|
@@ -250,7 +260,6 @@ class MedplumClient extends EventTarget {
|
|
|
250
260
|
* This is a lower level method for custom requests.
|
|
251
261
|
* For common operations, we recommend using higher level methods
|
|
252
262
|
* such as `createResource()`.
|
|
253
|
-
*
|
|
254
263
|
* @category HTTP
|
|
255
264
|
* @param url The target URL.
|
|
256
265
|
* @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.
|
|
@@ -275,7 +284,6 @@ class MedplumClient extends EventTarget {
|
|
|
275
284
|
* This is a lower level method for custom requests.
|
|
276
285
|
* For common operations, we recommend using higher level methods
|
|
277
286
|
* such as `updateResource()`.
|
|
278
|
-
*
|
|
279
287
|
* @category HTTP
|
|
280
288
|
* @param url The target URL.
|
|
281
289
|
* @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.
|
|
@@ -300,7 +308,6 @@ class MedplumClient extends EventTarget {
|
|
|
300
308
|
* This is a lower level method for custom requests.
|
|
301
309
|
* For common operations, we recommend using higher level methods
|
|
302
310
|
* such as `patchResource()`.
|
|
303
|
-
*
|
|
304
311
|
* @category HTTP
|
|
305
312
|
* @param url The target URL.
|
|
306
313
|
* @param operations Array of JSONPatch operations.
|
|
@@ -321,13 +328,12 @@ class MedplumClient extends EventTarget {
|
|
|
321
328
|
* This is a lower level method for custom requests.
|
|
322
329
|
* For common operations, we recommend using higher level methods
|
|
323
330
|
* such as `deleteResource()`.
|
|
324
|
-
*
|
|
325
331
|
* @category HTTP
|
|
326
332
|
* @param url The target URL.
|
|
327
333
|
* @param options Optional fetch options.
|
|
328
334
|
* @returns Promise to the response content.
|
|
329
335
|
*/
|
|
330
|
-
delete(url, options
|
|
336
|
+
delete(url, options) {
|
|
331
337
|
url = url.toString();
|
|
332
338
|
this.invalidateUrl(url);
|
|
333
339
|
return this.request('DELETE', url, options);
|
|
@@ -338,53 +344,54 @@ class MedplumClient extends EventTarget {
|
|
|
338
344
|
* This method is part of the two different user registration flows:
|
|
339
345
|
* 1) New Practitioner and new Project
|
|
340
346
|
* 2) New Patient registration
|
|
341
|
-
*
|
|
342
347
|
* @category Authentication
|
|
343
348
|
* @param newUserRequest Register request including email and password.
|
|
349
|
+
* @param options Optional fetch options.
|
|
344
350
|
* @returns Promise to the authentication response.
|
|
345
351
|
*/
|
|
346
|
-
async startNewUser(newUserRequest) {
|
|
352
|
+
async startNewUser(newUserRequest, options) {
|
|
347
353
|
const { codeChallengeMethod, codeChallenge } = await this.startPkce();
|
|
348
354
|
return this.post('auth/newuser', {
|
|
349
355
|
...newUserRequest,
|
|
350
356
|
codeChallengeMethod,
|
|
351
357
|
codeChallenge,
|
|
352
|
-
});
|
|
358
|
+
}, undefined, options);
|
|
353
359
|
}
|
|
354
360
|
/**
|
|
355
361
|
* Initiates a new project flow.
|
|
356
362
|
*
|
|
357
363
|
* This requires a partial login from `startNewUser` or `startNewGoogleUser`.
|
|
358
|
-
*
|
|
359
364
|
* @param newProjectRequest Register request including email and password.
|
|
365
|
+
* @param options Optional fetch options.
|
|
360
366
|
* @returns Promise to the authentication response.
|
|
361
367
|
*/
|
|
362
|
-
async startNewProject(newProjectRequest) {
|
|
363
|
-
return this.post('auth/newproject', newProjectRequest);
|
|
368
|
+
async startNewProject(newProjectRequest, options) {
|
|
369
|
+
return this.post('auth/newproject', newProjectRequest, undefined, options);
|
|
364
370
|
}
|
|
365
371
|
/**
|
|
366
372
|
* Initiates a new patient flow.
|
|
367
373
|
*
|
|
368
374
|
* This requires a partial login from `startNewUser` or `startNewGoogleUser`.
|
|
369
|
-
*
|
|
370
375
|
* @param newPatientRequest Register request including email and password.
|
|
376
|
+
* @param options Optional fetch options.
|
|
371
377
|
* @returns Promise to the authentication response.
|
|
372
378
|
*/
|
|
373
|
-
async startNewPatient(newPatientRequest) {
|
|
374
|
-
return this.post('auth/newpatient', newPatientRequest);
|
|
379
|
+
async startNewPatient(newPatientRequest, options) {
|
|
380
|
+
return this.post('auth/newpatient', newPatientRequest, undefined, options);
|
|
375
381
|
}
|
|
376
382
|
/**
|
|
377
383
|
* Initiates a user login flow.
|
|
378
384
|
* @category Authentication
|
|
379
385
|
* @param loginRequest Login request including email and password.
|
|
386
|
+
* @param options Optional fetch options.
|
|
380
387
|
* @returns Promise to the authentication response.
|
|
381
388
|
*/
|
|
382
|
-
async startLogin(loginRequest) {
|
|
389
|
+
async startLogin(loginRequest, options) {
|
|
383
390
|
return this.post('auth/login', {
|
|
384
391
|
...(await this.ensureCodeChallenge(loginRequest)),
|
|
385
392
|
clientId: loginRequest.clientId ?? this.clientId,
|
|
386
393
|
scope: loginRequest.scope,
|
|
387
|
-
});
|
|
394
|
+
}, undefined, options);
|
|
388
395
|
}
|
|
389
396
|
/**
|
|
390
397
|
* Tries to sign in with Google authentication.
|
|
@@ -392,14 +399,15 @@ class MedplumClient extends EventTarget {
|
|
|
392
399
|
* See: https://developers.google.com/identity/gsi/web/guides/handle-credential-responses-js-functions
|
|
393
400
|
* @category Authentication
|
|
394
401
|
* @param loginRequest Login request including Google credential response.
|
|
402
|
+
* @param options Optional fetch options.
|
|
395
403
|
* @returns Promise to the authentication response.
|
|
396
404
|
*/
|
|
397
|
-
async startGoogleLogin(loginRequest) {
|
|
405
|
+
async startGoogleLogin(loginRequest, options) {
|
|
398
406
|
return this.post('auth/google', {
|
|
399
407
|
...(await this.ensureCodeChallenge(loginRequest)),
|
|
400
408
|
clientId: loginRequest.clientId ?? this.clientId,
|
|
401
409
|
scope: loginRequest.scope,
|
|
402
|
-
});
|
|
410
|
+
}, undefined, options);
|
|
403
411
|
}
|
|
404
412
|
/**
|
|
405
413
|
* Returns the PKCE code challenge and method.
|
|
@@ -430,6 +438,7 @@ class MedplumClient extends EventTarget {
|
|
|
430
438
|
* This may result in navigating away to the sign in page.
|
|
431
439
|
* @category Authentication
|
|
432
440
|
* @param loginParams Optional login parameters.
|
|
441
|
+
* @returns The user profile resource if available.
|
|
433
442
|
*/
|
|
434
443
|
async signInWithRedirect(loginParams) {
|
|
435
444
|
const urlParams = new URLSearchParams(window.location.search);
|
|
@@ -466,6 +475,7 @@ class MedplumClient extends EventTarget {
|
|
|
466
475
|
* Exchange an external access token for a Medplum access token.
|
|
467
476
|
* @param token The access token that was generated by the external identity provider.
|
|
468
477
|
* @param clientId The ID of the `ClientApplication` in your Medplum project that will be making the exchange request.
|
|
478
|
+
* @returns The user profile resource.
|
|
469
479
|
* @category Authentication
|
|
470
480
|
*/
|
|
471
481
|
async exchangeExternalAccessToken(token, clientId) {
|
|
@@ -564,14 +574,13 @@ class MedplumClient extends EventTarget {
|
|
|
564
574
|
* ```
|
|
565
575
|
*
|
|
566
576
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
567
|
-
*
|
|
568
577
|
* @category Search
|
|
569
578
|
* @param resourceType The FHIR resource type.
|
|
570
579
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
571
580
|
* @param options Optional fetch options.
|
|
572
581
|
* @returns Promise to the search result bundle.
|
|
573
582
|
*/
|
|
574
|
-
search(resourceType, query, options
|
|
583
|
+
search(resourceType, query, options) {
|
|
575
584
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
576
585
|
const cacheKey = url.toString() + '-search';
|
|
577
586
|
const cached = this.getCacheEntry(cacheKey, options);
|
|
@@ -605,14 +614,13 @@ class MedplumClient extends EventTarget {
|
|
|
605
614
|
* The return value is the resource, if available; otherwise, undefined.
|
|
606
615
|
*
|
|
607
616
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
608
|
-
*
|
|
609
617
|
* @category Search
|
|
610
618
|
* @param resourceType The FHIR resource type.
|
|
611
619
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
612
620
|
* @param options Optional fetch options.
|
|
613
621
|
* @returns Promise to the first search result.
|
|
614
622
|
*/
|
|
615
|
-
searchOne(resourceType, query, options
|
|
623
|
+
searchOne(resourceType, query, options) {
|
|
616
624
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
617
625
|
url.searchParams.set('_count', '1');
|
|
618
626
|
url.searchParams.sort();
|
|
@@ -640,14 +648,13 @@ class MedplumClient extends EventTarget {
|
|
|
640
648
|
* The return value is an array of resources.
|
|
641
649
|
*
|
|
642
650
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
643
|
-
*
|
|
644
651
|
* @category Search
|
|
645
652
|
* @param resourceType The FHIR resource type.
|
|
646
653
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
647
654
|
* @param options Optional fetch options.
|
|
648
655
|
* @returns Promise to the array of search results.
|
|
649
656
|
*/
|
|
650
|
-
searchResources(resourceType, query, options
|
|
657
|
+
searchResources(resourceType, query, options) {
|
|
651
658
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
652
659
|
const cacheKey = url.toString() + '-searchResources';
|
|
653
660
|
const cached = this.getCacheEntry(cacheKey, options);
|
|
@@ -672,14 +679,13 @@ class MedplumClient extends EventTarget {
|
|
|
672
679
|
* }
|
|
673
680
|
* }
|
|
674
681
|
* ```
|
|
675
|
-
*
|
|
676
682
|
* @category Search
|
|
677
683
|
* @param resourceType The FHIR resource type.
|
|
678
684
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
679
685
|
* @param options Optional fetch options.
|
|
680
|
-
* @
|
|
686
|
+
* @yields An async generator, where each result is an array of resources for each page.
|
|
681
687
|
*/
|
|
682
|
-
async *searchResourcePages(resourceType, query, options
|
|
688
|
+
async *searchResourcePages(resourceType, query, options) {
|
|
683
689
|
let url = this.fhirSearchUrl(resourceType, query);
|
|
684
690
|
while (url) {
|
|
685
691
|
const searchParams = new URL(url).searchParams;
|
|
@@ -695,14 +701,13 @@ class MedplumClient extends EventTarget {
|
|
|
695
701
|
/**
|
|
696
702
|
* Searches a ValueSet resource using the "expand" operation.
|
|
697
703
|
* See: https://www.hl7.org/fhir/operation-valueset-expand.html
|
|
698
|
-
*
|
|
699
704
|
* @category Search
|
|
700
705
|
* @param system The ValueSet system url.
|
|
701
706
|
* @param filter The search string.
|
|
702
707
|
* @param options Optional fetch options.
|
|
703
708
|
* @returns Promise to expanded ValueSet.
|
|
704
709
|
*/
|
|
705
|
-
searchValueSet(system, filter, options
|
|
710
|
+
searchValueSet(system, filter, options) {
|
|
706
711
|
const url = this.fhirUrl('ValueSet', '$expand');
|
|
707
712
|
url.searchParams.set('url', system);
|
|
708
713
|
url.searchParams.set('filter', filter);
|
|
@@ -722,8 +727,7 @@ class MedplumClient extends EventTarget {
|
|
|
722
727
|
/**
|
|
723
728
|
* Returns a cached resource if it is available.
|
|
724
729
|
* @category Caching
|
|
725
|
-
* @param
|
|
726
|
-
* @param id The FHIR resource ID.
|
|
730
|
+
* @param reference The FHIR reference.
|
|
727
731
|
* @returns The resource if it is available in the cache; undefined otherwise.
|
|
728
732
|
*/
|
|
729
733
|
getCachedReference(reference) {
|
|
@@ -751,14 +755,13 @@ class MedplumClient extends EventTarget {
|
|
|
751
755
|
* ```
|
|
752
756
|
*
|
|
753
757
|
* See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
|
|
754
|
-
*
|
|
755
758
|
* @category Read
|
|
756
759
|
* @param resourceType The FHIR resource type.
|
|
757
760
|
* @param id The resource ID.
|
|
758
761
|
* @param options Optional fetch options.
|
|
759
762
|
* @returns The resource if available; undefined otherwise.
|
|
760
763
|
*/
|
|
761
|
-
readResource(resourceType, id, options
|
|
764
|
+
readResource(resourceType, id, options) {
|
|
762
765
|
return this.get(this.fhirUrl(resourceType, id), options);
|
|
763
766
|
}
|
|
764
767
|
/**
|
|
@@ -775,13 +778,12 @@ class MedplumClient extends EventTarget {
|
|
|
775
778
|
* ```
|
|
776
779
|
*
|
|
777
780
|
* See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
|
|
778
|
-
*
|
|
779
781
|
* @category Read
|
|
780
782
|
* @param reference The FHIR reference object.
|
|
781
783
|
* @param options Optional fetch options.
|
|
782
784
|
* @returns The resource if available; undefined otherwise.
|
|
783
785
|
*/
|
|
784
|
-
readReference(reference, options
|
|
786
|
+
readReference(reference, options) {
|
|
785
787
|
const refString = reference?.reference;
|
|
786
788
|
if (!refString) {
|
|
787
789
|
return new ReadablePromise(Promise.reject(new Error('Missing reference')));
|
|
@@ -877,14 +879,13 @@ class MedplumClient extends EventTarget {
|
|
|
877
879
|
* ```
|
|
878
880
|
*
|
|
879
881
|
* See the FHIR "history" operation for full details: https://www.hl7.org/fhir/http.html#history
|
|
880
|
-
*
|
|
881
882
|
* @category Read
|
|
882
883
|
* @param resourceType The FHIR resource type.
|
|
883
884
|
* @param id The resource ID.
|
|
884
885
|
* @param options Optional fetch options.
|
|
885
886
|
* @returns Promise to the resource history.
|
|
886
887
|
*/
|
|
887
|
-
readHistory(resourceType, id, options
|
|
888
|
+
readHistory(resourceType, id, options) {
|
|
888
889
|
return this.get(this.fhirUrl(resourceType, id, '_history'), options);
|
|
889
890
|
}
|
|
890
891
|
/**
|
|
@@ -898,7 +899,6 @@ class MedplumClient extends EventTarget {
|
|
|
898
899
|
* ```
|
|
899
900
|
*
|
|
900
901
|
* See the FHIR "vread" operation for full details: https://www.hl7.org/fhir/http.html#vread
|
|
901
|
-
*
|
|
902
902
|
* @category Read
|
|
903
903
|
* @param resourceType The FHIR resource type.
|
|
904
904
|
* @param id The resource ID.
|
|
@@ -906,7 +906,7 @@ class MedplumClient extends EventTarget {
|
|
|
906
906
|
* @param options Optional fetch options.
|
|
907
907
|
* @returns The resource if available; undefined otherwise.
|
|
908
908
|
*/
|
|
909
|
-
readVersion(resourceType, id, vid, options
|
|
909
|
+
readVersion(resourceType, id, vid, options) {
|
|
910
910
|
return this.get(this.fhirUrl(resourceType, id, '_history', vid), options);
|
|
911
911
|
}
|
|
912
912
|
/**
|
|
@@ -920,13 +920,12 @@ class MedplumClient extends EventTarget {
|
|
|
920
920
|
* ```
|
|
921
921
|
*
|
|
922
922
|
* See the FHIR "patient-everything" operation for full details: https://hl7.org/fhir/operation-patient-everything.html
|
|
923
|
-
*
|
|
924
923
|
* @category Read
|
|
925
924
|
* @param id The Patient Id
|
|
926
925
|
* @param options Optional fetch options.
|
|
927
926
|
* @returns A Bundle of all Resources related to the Patient
|
|
928
927
|
*/
|
|
929
|
-
readPatientEverything(id, options
|
|
928
|
+
readPatientEverything(id, options) {
|
|
930
929
|
return this.get(this.fhirUrl('Patient', id, '$everything'), options);
|
|
931
930
|
}
|
|
932
931
|
/**
|
|
@@ -948,17 +947,17 @@ class MedplumClient extends EventTarget {
|
|
|
948
947
|
* ```
|
|
949
948
|
*
|
|
950
949
|
* See the FHIR "create" operation for full details: https://www.hl7.org/fhir/http.html#create
|
|
951
|
-
*
|
|
952
950
|
* @category Create
|
|
953
951
|
* @param resource The FHIR resource to create.
|
|
952
|
+
* @param options Optional fetch options.
|
|
954
953
|
* @returns The result of the create operation.
|
|
955
954
|
*/
|
|
956
|
-
createResource(resource) {
|
|
955
|
+
createResource(resource, options) {
|
|
957
956
|
if (!resource.resourceType) {
|
|
958
957
|
throw new Error('Missing resourceType');
|
|
959
958
|
}
|
|
960
959
|
this.invalidateSearches(resource.resourceType);
|
|
961
|
-
return this.post(this.fhirUrl(resource.resourceType), resource);
|
|
960
|
+
return this.post(this.fhirUrl(resource.resourceType), resource, undefined, options);
|
|
962
961
|
}
|
|
963
962
|
/**
|
|
964
963
|
* Conditionally create a new FHIR resource only if some equivalent resource does not already exist on the server.
|
|
@@ -994,14 +993,15 @@ class MedplumClient extends EventTarget {
|
|
|
994
993
|
* The query parameter only contains the search parameters (what would be in the URL following the "?").
|
|
995
994
|
*
|
|
996
995
|
* See the FHIR "conditional create" operation for full details: https://www.hl7.org/fhir/http.html#ccreate
|
|
997
|
-
*
|
|
998
996
|
* @category Create
|
|
999
997
|
* @param resource The FHIR resource to create.
|
|
1000
998
|
* @param query The search query for an equivalent resource (should not include resource type or "?").
|
|
999
|
+
* @param options Optional fetch options.
|
|
1001
1000
|
* @returns The result of the create operation.
|
|
1002
1001
|
*/
|
|
1003
|
-
async createResourceIfNoneExist(resource, query) {
|
|
1004
|
-
return ((await this.searchOne(resource.resourceType, query)) ??
|
|
1002
|
+
async createResourceIfNoneExist(resource, query, options) {
|
|
1003
|
+
return ((await this.searchOne(resource.resourceType, query, options)) ??
|
|
1004
|
+
this.createResource(resource, options));
|
|
1005
1005
|
}
|
|
1006
1006
|
/**
|
|
1007
1007
|
* Creates a FHIR `Binary` resource with the provided data content.
|
|
@@ -1020,11 +1020,11 @@ class MedplumClient extends EventTarget {
|
|
|
1020
1020
|
* ```
|
|
1021
1021
|
*
|
|
1022
1022
|
* See the FHIR "create" operation for full details: https://www.hl7.org/fhir/http.html#create
|
|
1023
|
-
*
|
|
1024
1023
|
* @category Create
|
|
1025
1024
|
* @param data The binary data to upload.
|
|
1026
1025
|
* @param filename Optional filename for the binary.
|
|
1027
1026
|
* @param contentType Content type for the binary.
|
|
1027
|
+
* @param onProgress Optional callback for progress events.
|
|
1028
1028
|
* @returns The result of the create operation.
|
|
1029
1029
|
*/
|
|
1030
1030
|
createBinary(data, filename, contentType, onProgress) {
|
|
@@ -1083,9 +1083,11 @@ class MedplumClient extends EventTarget {
|
|
|
1083
1083
|
* ```
|
|
1084
1084
|
*
|
|
1085
1085
|
* See the pdfmake document definition for full details: https://pdfmake.github.io/docs/0.1/document-definition-object/
|
|
1086
|
-
*
|
|
1087
1086
|
* @category Media
|
|
1088
1087
|
* @param docDefinition The PDF document definition.
|
|
1088
|
+
* @param filename Optional filename for the PDF binary resource.
|
|
1089
|
+
* @param tableLayouts Optional pdfmake custom table layout.
|
|
1090
|
+
* @param fonts Optional pdfmake custom font dictionary.
|
|
1089
1091
|
* @returns The result of the create operation.
|
|
1090
1092
|
*/
|
|
1091
1093
|
async createPdf(docDefinition, filename, tableLayouts, fonts) {
|
|
@@ -1099,13 +1101,13 @@ class MedplumClient extends EventTarget {
|
|
|
1099
1101
|
* Creates a FHIR `Communication` resource with the provided data content.
|
|
1100
1102
|
*
|
|
1101
1103
|
* This is a convenience method to handle commmon cases where a `Communication` resource is created with a `payload`.
|
|
1102
|
-
*
|
|
1103
1104
|
* @category Create
|
|
1104
1105
|
* @param resource The FHIR resource to comment on.
|
|
1105
1106
|
* @param text The text of the comment.
|
|
1107
|
+
* @param options Optional fetch options.
|
|
1106
1108
|
* @returns The result of the create operation.
|
|
1107
1109
|
*/
|
|
1108
|
-
createComment(resource, text) {
|
|
1110
|
+
createComment(resource, text, options) {
|
|
1109
1111
|
const profile = this.getProfile();
|
|
1110
1112
|
let encounter = undefined;
|
|
1111
1113
|
let subject = undefined;
|
|
@@ -1128,7 +1130,7 @@ class MedplumClient extends EventTarget {
|
|
|
1128
1130
|
sender: profile ? createReference(profile) : undefined,
|
|
1129
1131
|
sent: new Date().toISOString(),
|
|
1130
1132
|
payload: [{ contentString: text }],
|
|
1131
|
-
});
|
|
1133
|
+
}, options);
|
|
1132
1134
|
}
|
|
1133
1135
|
/**
|
|
1134
1136
|
* Updates a FHIR resource.
|
|
@@ -1150,12 +1152,12 @@ class MedplumClient extends EventTarget {
|
|
|
1150
1152
|
* ```
|
|
1151
1153
|
*
|
|
1152
1154
|
* See the FHIR "update" operation for full details: https://www.hl7.org/fhir/http.html#update
|
|
1153
|
-
*
|
|
1154
1155
|
* @category Write
|
|
1155
1156
|
* @param resource The FHIR resource to update.
|
|
1157
|
+
* @param options Optional fetch options.
|
|
1156
1158
|
* @returns The result of the update operation.
|
|
1157
1159
|
*/
|
|
1158
|
-
async updateResource(resource) {
|
|
1160
|
+
async updateResource(resource, options) {
|
|
1159
1161
|
if (!resource.resourceType) {
|
|
1160
1162
|
throw new Error('Missing resourceType');
|
|
1161
1163
|
}
|
|
@@ -1163,7 +1165,7 @@ class MedplumClient extends EventTarget {
|
|
|
1163
1165
|
throw new Error('Missing id');
|
|
1164
1166
|
}
|
|
1165
1167
|
this.invalidateSearches(resource.resourceType);
|
|
1166
|
-
let result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
|
|
1168
|
+
let result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource, undefined, options);
|
|
1167
1169
|
if (!result) {
|
|
1168
1170
|
// On 304 not modified, result will be undefined
|
|
1169
1171
|
// Return the user input instead
|
|
@@ -1190,16 +1192,16 @@ class MedplumClient extends EventTarget {
|
|
|
1190
1192
|
* See the FHIR "update" operation for full details: https://www.hl7.org/fhir/http.html#patch
|
|
1191
1193
|
*
|
|
1192
1194
|
* See the JSONPatch specification for full details: https://tools.ietf.org/html/rfc6902
|
|
1193
|
-
*
|
|
1194
1195
|
* @category Write
|
|
1195
1196
|
* @param resourceType The FHIR resource type.
|
|
1196
1197
|
* @param id The resource ID.
|
|
1197
1198
|
* @param operations The JSONPatch operations.
|
|
1199
|
+
* @param options Optional fetch options.
|
|
1198
1200
|
* @returns The result of the patch operations.
|
|
1199
1201
|
*/
|
|
1200
|
-
patchResource(resourceType, id, operations) {
|
|
1202
|
+
patchResource(resourceType, id, operations, options) {
|
|
1201
1203
|
this.invalidateSearches(resourceType);
|
|
1202
|
-
return this.patch(this.fhirUrl(resourceType, id), operations);
|
|
1204
|
+
return this.patch(this.fhirUrl(resourceType, id), operations, options);
|
|
1203
1205
|
}
|
|
1204
1206
|
/**
|
|
1205
1207
|
* Deletes a FHIR resource by resource type and ID.
|
|
@@ -1211,16 +1213,16 @@ class MedplumClient extends EventTarget {
|
|
|
1211
1213
|
* ```
|
|
1212
1214
|
*
|
|
1213
1215
|
* See the FHIR "delete" operation for full details: https://www.hl7.org/fhir/http.html#delete
|
|
1214
|
-
*
|
|
1215
1216
|
* @category Delete
|
|
1216
1217
|
* @param resourceType The FHIR resource type.
|
|
1217
1218
|
* @param id The resource ID.
|
|
1219
|
+
* @param options Optional fetch options.
|
|
1218
1220
|
* @returns The result of the delete operation.
|
|
1219
1221
|
*/
|
|
1220
|
-
deleteResource(resourceType, id) {
|
|
1222
|
+
deleteResource(resourceType, id, options) {
|
|
1221
1223
|
this.deleteCacheEntry(this.fhirUrl(resourceType, id).toString());
|
|
1222
1224
|
this.invalidateSearches(resourceType);
|
|
1223
|
-
return this.delete(this.fhirUrl(resourceType, id));
|
|
1225
|
+
return this.delete(this.fhirUrl(resourceType, id), options);
|
|
1224
1226
|
}
|
|
1225
1227
|
/**
|
|
1226
1228
|
* Executes the validate operation with the provided resource.
|
|
@@ -1235,12 +1237,12 @@ class MedplumClient extends EventTarget {
|
|
|
1235
1237
|
* ```
|
|
1236
1238
|
*
|
|
1237
1239
|
* See the FHIR "$validate" operation for full details: https://www.hl7.org/fhir/resource-operation-validate.html
|
|
1238
|
-
*
|
|
1239
1240
|
* @param resource The FHIR resource.
|
|
1241
|
+
* @param options Optional fetch options.
|
|
1240
1242
|
* @returns The validate operation outcome.
|
|
1241
1243
|
*/
|
|
1242
|
-
validateResource(resource) {
|
|
1243
|
-
return this.post(this.fhirUrl(resource.resourceType, '$validate'), resource);
|
|
1244
|
+
validateResource(resource, options) {
|
|
1245
|
+
return this.post(this.fhirUrl(resource.resourceType, '$validate'), resource, undefined, options);
|
|
1244
1246
|
}
|
|
1245
1247
|
/**
|
|
1246
1248
|
* Executes a bot by ID or Identifier.
|
|
@@ -1250,7 +1252,7 @@ class MedplumClient extends EventTarget {
|
|
|
1250
1252
|
* @param options Optional fetch options.
|
|
1251
1253
|
* @returns The Bot return value.
|
|
1252
1254
|
*/
|
|
1253
|
-
executeBot(idOrIdentifier, body, contentType, options
|
|
1255
|
+
executeBot(idOrIdentifier, body, contentType, options) {
|
|
1254
1256
|
let url;
|
|
1255
1257
|
if (typeof idOrIdentifier === 'string') {
|
|
1256
1258
|
const id = idOrIdentifier;
|
|
@@ -1310,7 +1312,7 @@ class MedplumClient extends EventTarget {
|
|
|
1310
1312
|
* @param options Optional fetch options.
|
|
1311
1313
|
* @returns The FHIR batch/transaction response bundle.
|
|
1312
1314
|
*/
|
|
1313
|
-
executeBatch(bundle, options
|
|
1315
|
+
executeBatch(bundle, options) {
|
|
1314
1316
|
return this.post(this.fhirBaseUrl.slice(0, -1), bundle, undefined, options);
|
|
1315
1317
|
}
|
|
1316
1318
|
/**
|
|
@@ -1347,11 +1349,12 @@ class MedplumClient extends EventTarget {
|
|
|
1347
1349
|
*
|
|
1348
1350
|
* See options here: https://nodemailer.com/extras/mailcomposer/
|
|
1349
1351
|
* @category Media
|
|
1350
|
-
* @param
|
|
1352
|
+
* @param email The MailComposer options.
|
|
1353
|
+
* @param options Optional fetch options.
|
|
1351
1354
|
* @returns Promise to the operation outcome.
|
|
1352
1355
|
*/
|
|
1353
|
-
sendEmail(email) {
|
|
1354
|
-
return this.post('email/v1/send', email, 'application/json');
|
|
1356
|
+
sendEmail(email, options) {
|
|
1357
|
+
return this.post('email/v1/send', email, 'application/json', options);
|
|
1355
1358
|
}
|
|
1356
1359
|
/**
|
|
1357
1360
|
* Executes a GraphQL query.
|
|
@@ -1393,7 +1396,6 @@ class MedplumClient extends EventTarget {
|
|
|
1393
1396
|
* See the GraphQL documentation for more details: https://graphql.org/learn/
|
|
1394
1397
|
*
|
|
1395
1398
|
* See the FHIR GraphQL documentation for FHIR specific details: https://www.hl7.org/fhir/graphql.html
|
|
1396
|
-
*
|
|
1397
1399
|
* @category Read
|
|
1398
1400
|
* @param query The GraphQL query.
|
|
1399
1401
|
* @param operationName Optional GraphQL operation name.
|
|
@@ -1408,15 +1410,15 @@ class MedplumClient extends EventTarget {
|
|
|
1408
1410
|
*
|
|
1409
1411
|
* Executes the $graph operation on this resource to fetch a Bundle of resources linked to the target resource
|
|
1410
1412
|
* according to a graph definition
|
|
1411
|
-
|
|
1412
1413
|
* @category Read
|
|
1413
1414
|
* @param resourceType The FHIR resource type.
|
|
1414
1415
|
* @param id The resource ID.
|
|
1415
1416
|
* @param graphName `name` parameter of the GraphDefinition
|
|
1417
|
+
* @param options Optional fetch options.
|
|
1416
1418
|
* @returns A Bundle
|
|
1417
1419
|
*/
|
|
1418
|
-
readResourceGraph(resourceType, id, graphName) {
|
|
1419
|
-
return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}
|
|
1420
|
+
readResourceGraph(resourceType, id, graphName, options) {
|
|
1421
|
+
return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}`, options);
|
|
1420
1422
|
}
|
|
1421
1423
|
/**
|
|
1422
1424
|
* @category Authentication
|
|
@@ -1426,11 +1428,16 @@ class MedplumClient extends EventTarget {
|
|
|
1426
1428
|
return this.storage.getObject('activeLogin');
|
|
1427
1429
|
}
|
|
1428
1430
|
/**
|
|
1431
|
+
* Sets the active login.
|
|
1432
|
+
* @param login The new active login state.
|
|
1429
1433
|
* @category Authentication
|
|
1430
1434
|
*/
|
|
1431
1435
|
async setActiveLogin(login) {
|
|
1432
1436
|
this.clearActiveLogin();
|
|
1433
1437
|
this.accessToken = login.accessToken;
|
|
1438
|
+
if (this.basicAuth) {
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1434
1441
|
this.refreshToken = login.refreshToken;
|
|
1435
1442
|
this.storage.setObject('activeLogin', login);
|
|
1436
1443
|
this.addLogin(login);
|
|
@@ -1439,6 +1446,7 @@ class MedplumClient extends EventTarget {
|
|
|
1439
1446
|
}
|
|
1440
1447
|
/**
|
|
1441
1448
|
* Returns the current access token.
|
|
1449
|
+
* @returns The current access token.
|
|
1442
1450
|
* @category Authentication
|
|
1443
1451
|
*/
|
|
1444
1452
|
getAccessToken() {
|
|
@@ -1446,15 +1454,17 @@ class MedplumClient extends EventTarget {
|
|
|
1446
1454
|
}
|
|
1447
1455
|
/**
|
|
1448
1456
|
* Sets the current access token.
|
|
1457
|
+
* @param accessToken The new access token.
|
|
1449
1458
|
* @category Authentication
|
|
1450
1459
|
*/
|
|
1451
1460
|
setAccessToken(accessToken) {
|
|
1452
1461
|
this.accessToken = accessToken;
|
|
1453
1462
|
this.refreshToken = undefined;
|
|
1454
|
-
this.
|
|
1455
|
-
this.config = undefined;
|
|
1463
|
+
this.sessionDetails = undefined;
|
|
1456
1464
|
}
|
|
1457
1465
|
/**
|
|
1466
|
+
* Returns the list of available logins.
|
|
1467
|
+
* @returns The list of available logins.
|
|
1458
1468
|
* @category Authentication
|
|
1459
1469
|
*/
|
|
1460
1470
|
getLogins() {
|
|
@@ -1467,31 +1477,73 @@ class MedplumClient extends EventTarget {
|
|
|
1467
1477
|
}
|
|
1468
1478
|
async refreshProfile() {
|
|
1469
1479
|
this.profilePromise = new Promise((resolve, reject) => {
|
|
1480
|
+
if (this.basicAuth) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1470
1483
|
this.get('auth/me')
|
|
1471
1484
|
.then((result) => {
|
|
1472
1485
|
this.profilePromise = undefined;
|
|
1473
|
-
this.
|
|
1474
|
-
this.config = result.config;
|
|
1486
|
+
this.sessionDetails = result;
|
|
1475
1487
|
this.dispatchEvent({ type: 'change' });
|
|
1476
|
-
resolve(
|
|
1488
|
+
resolve(result.profile);
|
|
1477
1489
|
})
|
|
1478
1490
|
.catch(reject);
|
|
1479
1491
|
});
|
|
1480
1492
|
return this.profilePromise;
|
|
1481
1493
|
}
|
|
1482
1494
|
/**
|
|
1495
|
+
* Returns true if the client is waiting for authentication.
|
|
1496
|
+
* @returns True if the client is waiting for authentication.
|
|
1483
1497
|
* @category Authentication
|
|
1484
1498
|
*/
|
|
1485
1499
|
isLoading() {
|
|
1486
1500
|
return !!this.profilePromise;
|
|
1487
1501
|
}
|
|
1488
1502
|
/**
|
|
1503
|
+
* Returns true if the current user is authenticated as a super admin.
|
|
1504
|
+
* @returns True if the current user is authenticated as a super admin.
|
|
1505
|
+
* @category Authentication
|
|
1506
|
+
*/
|
|
1507
|
+
isSuperAdmin() {
|
|
1508
|
+
return !!this.sessionDetails?.project?.superAdmin;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Returns true if the current user is authenticated as a project admin.
|
|
1512
|
+
* @returns True if the current user is authenticated as a project admin.
|
|
1513
|
+
* @category Authentication
|
|
1514
|
+
*/
|
|
1515
|
+
isProjectAdmin() {
|
|
1516
|
+
return !!this.sessionDetails?.membership?.admin;
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Returns the current project if available.
|
|
1520
|
+
* @returns The current project if available.
|
|
1521
|
+
* @category User Profile
|
|
1522
|
+
*/
|
|
1523
|
+
getProject() {
|
|
1524
|
+
return this.sessionDetails?.project;
|
|
1525
|
+
}
|
|
1526
|
+
/**
|
|
1527
|
+
* Returns the current project membership if available.
|
|
1528
|
+
* @returns The current project membership if available.
|
|
1529
|
+
* @category User Profile
|
|
1530
|
+
*/
|
|
1531
|
+
getProjectMembership() {
|
|
1532
|
+
return this.sessionDetails?.membership;
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Returns the current user profile resource if available.
|
|
1536
|
+
* This method does not wait for loading promises.
|
|
1537
|
+
* @returns The current user profile resource if available.
|
|
1489
1538
|
* @category User Profile
|
|
1490
1539
|
*/
|
|
1491
1540
|
getProfile() {
|
|
1492
|
-
return this.profile;
|
|
1541
|
+
return this.sessionDetails?.profile;
|
|
1493
1542
|
}
|
|
1494
1543
|
/**
|
|
1544
|
+
* Returns the current user profile resource if available.
|
|
1545
|
+
* This method waits for loading promises.
|
|
1546
|
+
* @returns The current user profile resource if available.
|
|
1495
1547
|
* @category User Profile
|
|
1496
1548
|
*/
|
|
1497
1549
|
async getProfileAsync() {
|
|
@@ -1501,16 +1553,26 @@ class MedplumClient extends EventTarget {
|
|
|
1501
1553
|
return this.getProfile();
|
|
1502
1554
|
}
|
|
1503
1555
|
/**
|
|
1556
|
+
* Returns the current user configuration if available.
|
|
1557
|
+
* @returns The current user configuration if available.
|
|
1504
1558
|
* @category User Profile
|
|
1505
1559
|
*/
|
|
1506
1560
|
getUserConfiguration() {
|
|
1507
|
-
return this.config;
|
|
1561
|
+
return this.sessionDetails?.config;
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Returns the current user access policy if available.
|
|
1565
|
+
* @returns The current user access policy if available.
|
|
1566
|
+
* @category User Profile
|
|
1567
|
+
*/
|
|
1568
|
+
getAccessPolicy() {
|
|
1569
|
+
return this.sessionDetails?.accessPolicy;
|
|
1508
1570
|
}
|
|
1509
1571
|
/**
|
|
1510
1572
|
* Downloads the URL as a blob.
|
|
1511
|
-
*
|
|
1512
1573
|
* @category Read
|
|
1513
1574
|
* @param url The URL to request.
|
|
1575
|
+
* @param options Optional fetch request init options.
|
|
1514
1576
|
* @returns Promise to the response body as a blob.
|
|
1515
1577
|
*/
|
|
1516
1578
|
async download(url, options = {}) {
|
|
@@ -1524,12 +1586,13 @@ class MedplumClient extends EventTarget {
|
|
|
1524
1586
|
/**
|
|
1525
1587
|
* Upload media to the server and create a Media instance for the uploaded content.
|
|
1526
1588
|
* @param contents The contents of the media file, as a string, Uint8Array, File, or Blob.
|
|
1527
|
-
* @param contentType The media type of the content
|
|
1528
|
-
* @param filename The name of the file to be uploaded, or undefined if not applicable
|
|
1529
|
-
* @param additionalFields
|
|
1589
|
+
* @param contentType The media type of the content.
|
|
1590
|
+
* @param filename The name of the file to be uploaded, or undefined if not applicable.
|
|
1591
|
+
* @param additionalFields Additional fields for Media.
|
|
1592
|
+
* @param options Optional fetch options.
|
|
1530
1593
|
* @returns Promise that resolves to the created Media
|
|
1531
1594
|
*/
|
|
1532
|
-
async uploadMedia(contents, contentType, filename, additionalFields) {
|
|
1595
|
+
async uploadMedia(contents, contentType, filename, additionalFields, options) {
|
|
1533
1596
|
const binary = await this.createBinary(contents, filename, contentType);
|
|
1534
1597
|
return this.createResource({
|
|
1535
1598
|
...additionalFields,
|
|
@@ -1539,11 +1602,10 @@ class MedplumClient extends EventTarget {
|
|
|
1539
1602
|
url: 'Binary/' + binary.id,
|
|
1540
1603
|
title: filename,
|
|
1541
1604
|
},
|
|
1542
|
-
});
|
|
1605
|
+
}, options);
|
|
1543
1606
|
}
|
|
1544
1607
|
/**
|
|
1545
1608
|
* Performs Bulk Data Export operation request flow. See The FHIR "Bulk Data Export" for full details: https://build.fhir.org/ig/HL7/bulk-data/export.html#bulk-data-export
|
|
1546
|
-
*
|
|
1547
1609
|
* @param exportLevel Optional export level. Defaults to system level export. 'Group/:id' - Group of Patients, 'Patient' - All Patients.
|
|
1548
1610
|
* @param resourceTypes A string of comma-delimited FHIR resource types.
|
|
1549
1611
|
* @param since Resources will be included in the response if their state has changed after the supplied time (e.g. if Resource.meta.lastUpdated is later than the supplied _since time).
|
|
@@ -1559,7 +1621,6 @@ class MedplumClient extends EventTarget {
|
|
|
1559
1621
|
if (since) {
|
|
1560
1622
|
url.searchParams.set('_since', since);
|
|
1561
1623
|
}
|
|
1562
|
-
options.method = exportLevel ? 'GET' : 'POST';
|
|
1563
1624
|
this.addFetchOptionsDefaults(options);
|
|
1564
1625
|
const headers = options.headers;
|
|
1565
1626
|
headers['Prefer'] = 'respond-async';
|
|
@@ -1623,10 +1684,10 @@ class MedplumClient extends EventTarget {
|
|
|
1623
1684
|
}
|
|
1624
1685
|
/**
|
|
1625
1686
|
* Makes an HTTP request.
|
|
1626
|
-
* @param
|
|
1627
|
-
* @param
|
|
1628
|
-
* @param
|
|
1629
|
-
* @
|
|
1687
|
+
* @param method The HTTP method (GET, POST, etc).
|
|
1688
|
+
* @param url The target URL.
|
|
1689
|
+
* @param options Optional fetch request init options.
|
|
1690
|
+
* @returns The JSON content body if available.
|
|
1630
1691
|
*/
|
|
1631
1692
|
async request(method, url, options = {}) {
|
|
1632
1693
|
if (this.refreshPromise) {
|
|
@@ -1691,9 +1752,7 @@ class MedplumClient extends EventTarget {
|
|
|
1691
1752
|
let resultResponse;
|
|
1692
1753
|
const retryDelay = 200;
|
|
1693
1754
|
while (checkStatus) {
|
|
1694
|
-
const fetchOptions = {
|
|
1695
|
-
method: 'GET',
|
|
1696
|
-
};
|
|
1755
|
+
const fetchOptions = {};
|
|
1697
1756
|
this.addFetchOptionsDefaults(fetchOptions);
|
|
1698
1757
|
const statusResponse = await this.fetchWithRetry(statusUrl, fetchOptions);
|
|
1699
1758
|
if (statusResponse.status !== 202) {
|
|
@@ -1769,7 +1828,7 @@ class MedplumClient extends EventTarget {
|
|
|
1769
1828
|
if (this.accessToken) {
|
|
1770
1829
|
headers['Authorization'] = 'Bearer ' + this.accessToken;
|
|
1771
1830
|
}
|
|
1772
|
-
if (this.basicAuth) {
|
|
1831
|
+
else if (this.basicAuth) {
|
|
1773
1832
|
headers['Authorization'] = 'Basic ' + this.basicAuth;
|
|
1774
1833
|
}
|
|
1775
1834
|
if (!options.cache) {
|
|
@@ -1813,8 +1872,8 @@ class MedplumClient extends EventTarget {
|
|
|
1813
1872
|
* Otherwise, calls unauthenticated callbacks and rejects.
|
|
1814
1873
|
* @param method The HTTP method of the original request.
|
|
1815
1874
|
* @param url The URL of the original request.
|
|
1816
|
-
* @param
|
|
1817
|
-
* @
|
|
1875
|
+
* @param options Optional fetch request init options.
|
|
1876
|
+
* @returns The result of the retry.
|
|
1818
1877
|
*/
|
|
1819
1878
|
handleUnauthenticated(method, url, options) {
|
|
1820
1879
|
if (this.refresh()) {
|
|
@@ -1830,6 +1889,7 @@ class MedplumClient extends EventTarget {
|
|
|
1830
1889
|
* Starts a new PKCE flow.
|
|
1831
1890
|
* These PKCE values are stateful, and must survive redirects and page refreshes.
|
|
1832
1891
|
* @category Authentication
|
|
1892
|
+
* @returns The PKCE code challenge details.
|
|
1833
1893
|
*/
|
|
1834
1894
|
async startPkce() {
|
|
1835
1895
|
const pkceState = getRandomString();
|
|
@@ -1844,7 +1904,8 @@ class MedplumClient extends EventTarget {
|
|
|
1844
1904
|
/**
|
|
1845
1905
|
* Redirects the user to the login screen for authorization.
|
|
1846
1906
|
* Clears all auth state including local storage and session storage.
|
|
1847
|
-
*
|
|
1907
|
+
* @param loginParams The authorization login parameters.
|
|
1908
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
|
|
1848
1909
|
*/
|
|
1849
1910
|
async requestAuthorization(loginParams) {
|
|
1850
1911
|
const loginRequest = await this.ensureCodeChallenge(loginParams || {});
|
|
@@ -1863,6 +1924,7 @@ class MedplumClient extends EventTarget {
|
|
|
1863
1924
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
|
|
1864
1925
|
* @param code The authorization code received by URL parameter.
|
|
1865
1926
|
* @param loginParams Optional login parameters.
|
|
1927
|
+
* @returns The user profile resource.
|
|
1866
1928
|
* @category Authentication
|
|
1867
1929
|
*/
|
|
1868
1930
|
processCode(code, loginParams) {
|
|
@@ -1881,7 +1943,8 @@ class MedplumClient extends EventTarget {
|
|
|
1881
1943
|
}
|
|
1882
1944
|
/**
|
|
1883
1945
|
* Tries to refresh the auth tokens.
|
|
1884
|
-
*
|
|
1946
|
+
* @returns The refresh promise if available; otherwise undefined.
|
|
1947
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
|
|
1885
1948
|
*/
|
|
1886
1949
|
refresh() {
|
|
1887
1950
|
if (this.refreshPromise) {
|
|
@@ -1934,7 +1997,6 @@ class MedplumClient extends EventTarget {
|
|
|
1934
1997
|
* // Example Search
|
|
1935
1998
|
* await medplum.searchResources('Patient')
|
|
1936
1999
|
* ```
|
|
1937
|
-
*
|
|
1938
2000
|
* @category Authentication
|
|
1939
2001
|
* @param clientId The client ID.
|
|
1940
2002
|
* @param clientSecret The client secret.
|
|
@@ -1948,7 +2010,7 @@ class MedplumClient extends EventTarget {
|
|
|
1948
2010
|
* Invite a user to a project.
|
|
1949
2011
|
* @param projectId The project ID.
|
|
1950
2012
|
* @param body The InviteBody.
|
|
1951
|
-
* @returns Promise that returns
|
|
2013
|
+
* @returns Promise that returns a project membership or an operation outcome.
|
|
1952
2014
|
*/
|
|
1953
2015
|
async invite(projectId, body) {
|
|
1954
2016
|
return this.post('admin/projects/' + projectId + '/invite', body);
|
|
@@ -1957,17 +2019,29 @@ class MedplumClient extends EventTarget {
|
|
|
1957
2019
|
* Makes a POST request to the tokens endpoint.
|
|
1958
2020
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1959
2021
|
* @param formBody Token parameters in URL encoded format.
|
|
2022
|
+
* @returns The user profile resource.
|
|
1960
2023
|
*/
|
|
1961
2024
|
async fetchTokens(formBody) {
|
|
1962
|
-
const
|
|
2025
|
+
const options = {
|
|
1963
2026
|
method: 'POST',
|
|
1964
2027
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1965
2028
|
body: formBody,
|
|
1966
2029
|
credentials: 'include',
|
|
1967
|
-
}
|
|
2030
|
+
};
|
|
2031
|
+
const headers = options.headers;
|
|
2032
|
+
if (this.basicAuth) {
|
|
2033
|
+
headers['Authorization'] = `Basic ${this.basicAuth}`;
|
|
2034
|
+
}
|
|
2035
|
+
const response = await this.fetch(this.tokenUrl, options);
|
|
1968
2036
|
if (!response.ok) {
|
|
1969
2037
|
this.clearActiveLogin();
|
|
1970
|
-
|
|
2038
|
+
try {
|
|
2039
|
+
const error = await response.json();
|
|
2040
|
+
throw new OperationOutcomeError(badRequest(error.error_description));
|
|
2041
|
+
}
|
|
2042
|
+
catch (err) {
|
|
2043
|
+
throw new OperationOutcomeError(badRequest('Failed to fetch tokens'), err);
|
|
2044
|
+
}
|
|
1971
2045
|
}
|
|
1972
2046
|
const tokens = await response.json();
|
|
1973
2047
|
await this.verifyTokens(tokens);
|
|
@@ -1977,7 +2051,8 @@ class MedplumClient extends EventTarget {
|
|
|
1977
2051
|
* Verifies the tokens received from the auth server.
|
|
1978
2052
|
* Validates the JWT against the JWKS.
|
|
1979
2053
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1980
|
-
* @param tokens
|
|
2054
|
+
* @param tokens The token response.
|
|
2055
|
+
* @returns Promise to complete.
|
|
1981
2056
|
*/
|
|
1982
2057
|
async verifyTokens(tokens) {
|
|
1983
2058
|
const token = tokens.access_token;
|
|
@@ -1988,7 +2063,14 @@ class MedplumClient extends EventTarget {
|
|
|
1988
2063
|
throw new Error('Token expired');
|
|
1989
2064
|
}
|
|
1990
2065
|
// Verify app_client_id
|
|
1991
|
-
|
|
2066
|
+
// external tokenPayload
|
|
2067
|
+
if (tokenPayload.cid) {
|
|
2068
|
+
if (tokenPayload.cid !== this.clientId) {
|
|
2069
|
+
this.clearActiveLogin();
|
|
2070
|
+
throw new Error('Token was not issued for this audience');
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
else if (this.clientId && tokenPayload.client_id !== this.clientId) {
|
|
1992
2074
|
this.clearActiveLogin();
|
|
1993
2075
|
throw new Error('Token was not issued for this audience');
|
|
1994
2076
|
}
|
|
@@ -2042,6 +2124,7 @@ function getDefaultFetch() {
|
|
|
2042
2124
|
}
|
|
2043
2125
|
/**
|
|
2044
2126
|
* Returns the base URL for the current page.
|
|
2127
|
+
* @returns The window origin string.
|
|
2045
2128
|
* @category HTTP
|
|
2046
2129
|
*/
|
|
2047
2130
|
function getWindowOrigin() {
|