@medplum/core 2.0.21 → 2.0.22
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 +380 -288
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/client.mjs +132 -102
- 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/fhirpath/functions.mjs +179 -129
- package/dist/esm/fhirpath/functions.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 +1 -0
- 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/schema.mjs +4 -10
- package/dist/esm/schema.mjs.map +1 -1
- package/dist/esm/search/details.mjs +0 -1
- 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 +74 -64
- package/dist/types/crypto.d.ts +3 -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/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 +4 -4
- package/package.json +1 -1
package/dist/esm/client.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
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';
|
|
@@ -7,11 +8,10 @@ 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.22-f51ac45a" ;
|
|
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) {
|
|
@@ -165,6 +164,9 @@ class MedplumClient extends EventTarget {
|
|
|
165
164
|
* @category Authentication
|
|
166
165
|
*/
|
|
167
166
|
clearActiveLogin() {
|
|
167
|
+
if (this.basicAuth) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
168
170
|
this.storage.setString('activeLogin', undefined);
|
|
169
171
|
this.requestCache?.clear();
|
|
170
172
|
this.accessToken = undefined;
|
|
@@ -210,7 +212,6 @@ class MedplumClient extends EventTarget {
|
|
|
210
212
|
* This is a lower level method for custom requests.
|
|
211
213
|
* For common operations, we recommend using higher level methods
|
|
212
214
|
* such as `readResource()`, `search()`, etc.
|
|
213
|
-
*
|
|
214
215
|
* @category HTTP
|
|
215
216
|
* @param url The target URL.
|
|
216
217
|
* @param options Optional fetch options.
|
|
@@ -250,7 +251,6 @@ class MedplumClient extends EventTarget {
|
|
|
250
251
|
* This is a lower level method for custom requests.
|
|
251
252
|
* For common operations, we recommend using higher level methods
|
|
252
253
|
* such as `createResource()`.
|
|
253
|
-
*
|
|
254
254
|
* @category HTTP
|
|
255
255
|
* @param url The target URL.
|
|
256
256
|
* @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.
|
|
@@ -275,7 +275,6 @@ class MedplumClient extends EventTarget {
|
|
|
275
275
|
* This is a lower level method for custom requests.
|
|
276
276
|
* For common operations, we recommend using higher level methods
|
|
277
277
|
* such as `updateResource()`.
|
|
278
|
-
*
|
|
279
278
|
* @category HTTP
|
|
280
279
|
* @param url The target URL.
|
|
281
280
|
* @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.
|
|
@@ -300,7 +299,6 @@ class MedplumClient extends EventTarget {
|
|
|
300
299
|
* This is a lower level method for custom requests.
|
|
301
300
|
* For common operations, we recommend using higher level methods
|
|
302
301
|
* such as `patchResource()`.
|
|
303
|
-
*
|
|
304
302
|
* @category HTTP
|
|
305
303
|
* @param url The target URL.
|
|
306
304
|
* @param operations Array of JSONPatch operations.
|
|
@@ -321,13 +319,12 @@ class MedplumClient extends EventTarget {
|
|
|
321
319
|
* This is a lower level method for custom requests.
|
|
322
320
|
* For common operations, we recommend using higher level methods
|
|
323
321
|
* such as `deleteResource()`.
|
|
324
|
-
*
|
|
325
322
|
* @category HTTP
|
|
326
323
|
* @param url The target URL.
|
|
327
324
|
* @param options Optional fetch options.
|
|
328
325
|
* @returns Promise to the response content.
|
|
329
326
|
*/
|
|
330
|
-
delete(url, options
|
|
327
|
+
delete(url, options) {
|
|
331
328
|
url = url.toString();
|
|
332
329
|
this.invalidateUrl(url);
|
|
333
330
|
return this.request('DELETE', url, options);
|
|
@@ -338,53 +335,54 @@ class MedplumClient extends EventTarget {
|
|
|
338
335
|
* This method is part of the two different user registration flows:
|
|
339
336
|
* 1) New Practitioner and new Project
|
|
340
337
|
* 2) New Patient registration
|
|
341
|
-
*
|
|
342
338
|
* @category Authentication
|
|
343
339
|
* @param newUserRequest Register request including email and password.
|
|
340
|
+
* @param options Optional fetch options.
|
|
344
341
|
* @returns Promise to the authentication response.
|
|
345
342
|
*/
|
|
346
|
-
async startNewUser(newUserRequest) {
|
|
343
|
+
async startNewUser(newUserRequest, options) {
|
|
347
344
|
const { codeChallengeMethod, codeChallenge } = await this.startPkce();
|
|
348
345
|
return this.post('auth/newuser', {
|
|
349
346
|
...newUserRequest,
|
|
350
347
|
codeChallengeMethod,
|
|
351
348
|
codeChallenge,
|
|
352
|
-
});
|
|
349
|
+
}, undefined, options);
|
|
353
350
|
}
|
|
354
351
|
/**
|
|
355
352
|
* Initiates a new project flow.
|
|
356
353
|
*
|
|
357
354
|
* This requires a partial login from `startNewUser` or `startNewGoogleUser`.
|
|
358
|
-
*
|
|
359
355
|
* @param newProjectRequest Register request including email and password.
|
|
356
|
+
* @param options Optional fetch options.
|
|
360
357
|
* @returns Promise to the authentication response.
|
|
361
358
|
*/
|
|
362
|
-
async startNewProject(newProjectRequest) {
|
|
363
|
-
return this.post('auth/newproject', newProjectRequest);
|
|
359
|
+
async startNewProject(newProjectRequest, options) {
|
|
360
|
+
return this.post('auth/newproject', newProjectRequest, undefined, options);
|
|
364
361
|
}
|
|
365
362
|
/**
|
|
366
363
|
* Initiates a new patient flow.
|
|
367
364
|
*
|
|
368
365
|
* This requires a partial login from `startNewUser` or `startNewGoogleUser`.
|
|
369
|
-
*
|
|
370
366
|
* @param newPatientRequest Register request including email and password.
|
|
367
|
+
* @param options Optional fetch options.
|
|
371
368
|
* @returns Promise to the authentication response.
|
|
372
369
|
*/
|
|
373
|
-
async startNewPatient(newPatientRequest) {
|
|
374
|
-
return this.post('auth/newpatient', newPatientRequest);
|
|
370
|
+
async startNewPatient(newPatientRequest, options) {
|
|
371
|
+
return this.post('auth/newpatient', newPatientRequest, undefined, options);
|
|
375
372
|
}
|
|
376
373
|
/**
|
|
377
374
|
* Initiates a user login flow.
|
|
378
375
|
* @category Authentication
|
|
379
376
|
* @param loginRequest Login request including email and password.
|
|
377
|
+
* @param options Optional fetch options.
|
|
380
378
|
* @returns Promise to the authentication response.
|
|
381
379
|
*/
|
|
382
|
-
async startLogin(loginRequest) {
|
|
380
|
+
async startLogin(loginRequest, options) {
|
|
383
381
|
return this.post('auth/login', {
|
|
384
382
|
...(await this.ensureCodeChallenge(loginRequest)),
|
|
385
383
|
clientId: loginRequest.clientId ?? this.clientId,
|
|
386
384
|
scope: loginRequest.scope,
|
|
387
|
-
});
|
|
385
|
+
}, undefined, options);
|
|
388
386
|
}
|
|
389
387
|
/**
|
|
390
388
|
* Tries to sign in with Google authentication.
|
|
@@ -392,14 +390,15 @@ class MedplumClient extends EventTarget {
|
|
|
392
390
|
* See: https://developers.google.com/identity/gsi/web/guides/handle-credential-responses-js-functions
|
|
393
391
|
* @category Authentication
|
|
394
392
|
* @param loginRequest Login request including Google credential response.
|
|
393
|
+
* @param options Optional fetch options.
|
|
395
394
|
* @returns Promise to the authentication response.
|
|
396
395
|
*/
|
|
397
|
-
async startGoogleLogin(loginRequest) {
|
|
396
|
+
async startGoogleLogin(loginRequest, options) {
|
|
398
397
|
return this.post('auth/google', {
|
|
399
398
|
...(await this.ensureCodeChallenge(loginRequest)),
|
|
400
399
|
clientId: loginRequest.clientId ?? this.clientId,
|
|
401
400
|
scope: loginRequest.scope,
|
|
402
|
-
});
|
|
401
|
+
}, undefined, options);
|
|
403
402
|
}
|
|
404
403
|
/**
|
|
405
404
|
* Returns the PKCE code challenge and method.
|
|
@@ -430,6 +429,7 @@ class MedplumClient extends EventTarget {
|
|
|
430
429
|
* This may result in navigating away to the sign in page.
|
|
431
430
|
* @category Authentication
|
|
432
431
|
* @param loginParams Optional login parameters.
|
|
432
|
+
* @returns The user profile resource if available.
|
|
433
433
|
*/
|
|
434
434
|
async signInWithRedirect(loginParams) {
|
|
435
435
|
const urlParams = new URLSearchParams(window.location.search);
|
|
@@ -466,6 +466,7 @@ class MedplumClient extends EventTarget {
|
|
|
466
466
|
* Exchange an external access token for a Medplum access token.
|
|
467
467
|
* @param token The access token that was generated by the external identity provider.
|
|
468
468
|
* @param clientId The ID of the `ClientApplication` in your Medplum project that will be making the exchange request.
|
|
469
|
+
* @returns The user profile resource.
|
|
469
470
|
* @category Authentication
|
|
470
471
|
*/
|
|
471
472
|
async exchangeExternalAccessToken(token, clientId) {
|
|
@@ -564,14 +565,13 @@ class MedplumClient extends EventTarget {
|
|
|
564
565
|
* ```
|
|
565
566
|
*
|
|
566
567
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
567
|
-
*
|
|
568
568
|
* @category Search
|
|
569
569
|
* @param resourceType The FHIR resource type.
|
|
570
570
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
571
571
|
* @param options Optional fetch options.
|
|
572
572
|
* @returns Promise to the search result bundle.
|
|
573
573
|
*/
|
|
574
|
-
search(resourceType, query, options
|
|
574
|
+
search(resourceType, query, options) {
|
|
575
575
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
576
576
|
const cacheKey = url.toString() + '-search';
|
|
577
577
|
const cached = this.getCacheEntry(cacheKey, options);
|
|
@@ -605,14 +605,13 @@ class MedplumClient extends EventTarget {
|
|
|
605
605
|
* The return value is the resource, if available; otherwise, undefined.
|
|
606
606
|
*
|
|
607
607
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
608
|
-
*
|
|
609
608
|
* @category Search
|
|
610
609
|
* @param resourceType The FHIR resource type.
|
|
611
610
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
612
611
|
* @param options Optional fetch options.
|
|
613
612
|
* @returns Promise to the first search result.
|
|
614
613
|
*/
|
|
615
|
-
searchOne(resourceType, query, options
|
|
614
|
+
searchOne(resourceType, query, options) {
|
|
616
615
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
617
616
|
url.searchParams.set('_count', '1');
|
|
618
617
|
url.searchParams.sort();
|
|
@@ -640,14 +639,13 @@ class MedplumClient extends EventTarget {
|
|
|
640
639
|
* The return value is an array of resources.
|
|
641
640
|
*
|
|
642
641
|
* See FHIR search for full details: https://www.hl7.org/fhir/search.html
|
|
643
|
-
*
|
|
644
642
|
* @category Search
|
|
645
643
|
* @param resourceType The FHIR resource type.
|
|
646
644
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
647
645
|
* @param options Optional fetch options.
|
|
648
646
|
* @returns Promise to the array of search results.
|
|
649
647
|
*/
|
|
650
|
-
searchResources(resourceType, query, options
|
|
648
|
+
searchResources(resourceType, query, options) {
|
|
651
649
|
const url = this.fhirSearchUrl(resourceType, query);
|
|
652
650
|
const cacheKey = url.toString() + '-searchResources';
|
|
653
651
|
const cached = this.getCacheEntry(cacheKey, options);
|
|
@@ -672,14 +670,13 @@ class MedplumClient extends EventTarget {
|
|
|
672
670
|
* }
|
|
673
671
|
* }
|
|
674
672
|
* ```
|
|
675
|
-
*
|
|
676
673
|
* @category Search
|
|
677
674
|
* @param resourceType The FHIR resource type.
|
|
678
675
|
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
679
676
|
* @param options Optional fetch options.
|
|
680
|
-
* @
|
|
677
|
+
* @yields An async generator, where each result is an array of resources for each page.
|
|
681
678
|
*/
|
|
682
|
-
async *searchResourcePages(resourceType, query, options
|
|
679
|
+
async *searchResourcePages(resourceType, query, options) {
|
|
683
680
|
let url = this.fhirSearchUrl(resourceType, query);
|
|
684
681
|
while (url) {
|
|
685
682
|
const searchParams = new URL(url).searchParams;
|
|
@@ -695,14 +692,13 @@ class MedplumClient extends EventTarget {
|
|
|
695
692
|
/**
|
|
696
693
|
* Searches a ValueSet resource using the "expand" operation.
|
|
697
694
|
* See: https://www.hl7.org/fhir/operation-valueset-expand.html
|
|
698
|
-
*
|
|
699
695
|
* @category Search
|
|
700
696
|
* @param system The ValueSet system url.
|
|
701
697
|
* @param filter The search string.
|
|
702
698
|
* @param options Optional fetch options.
|
|
703
699
|
* @returns Promise to expanded ValueSet.
|
|
704
700
|
*/
|
|
705
|
-
searchValueSet(system, filter, options
|
|
701
|
+
searchValueSet(system, filter, options) {
|
|
706
702
|
const url = this.fhirUrl('ValueSet', '$expand');
|
|
707
703
|
url.searchParams.set('url', system);
|
|
708
704
|
url.searchParams.set('filter', filter);
|
|
@@ -722,8 +718,7 @@ class MedplumClient extends EventTarget {
|
|
|
722
718
|
/**
|
|
723
719
|
* Returns a cached resource if it is available.
|
|
724
720
|
* @category Caching
|
|
725
|
-
* @param
|
|
726
|
-
* @param id The FHIR resource ID.
|
|
721
|
+
* @param reference The FHIR reference.
|
|
727
722
|
* @returns The resource if it is available in the cache; undefined otherwise.
|
|
728
723
|
*/
|
|
729
724
|
getCachedReference(reference) {
|
|
@@ -751,14 +746,13 @@ class MedplumClient extends EventTarget {
|
|
|
751
746
|
* ```
|
|
752
747
|
*
|
|
753
748
|
* See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
|
|
754
|
-
*
|
|
755
749
|
* @category Read
|
|
756
750
|
* @param resourceType The FHIR resource type.
|
|
757
751
|
* @param id The resource ID.
|
|
758
752
|
* @param options Optional fetch options.
|
|
759
753
|
* @returns The resource if available; undefined otherwise.
|
|
760
754
|
*/
|
|
761
|
-
readResource(resourceType, id, options
|
|
755
|
+
readResource(resourceType, id, options) {
|
|
762
756
|
return this.get(this.fhirUrl(resourceType, id), options);
|
|
763
757
|
}
|
|
764
758
|
/**
|
|
@@ -775,13 +769,12 @@ class MedplumClient extends EventTarget {
|
|
|
775
769
|
* ```
|
|
776
770
|
*
|
|
777
771
|
* See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
|
|
778
|
-
*
|
|
779
772
|
* @category Read
|
|
780
773
|
* @param reference The FHIR reference object.
|
|
781
774
|
* @param options Optional fetch options.
|
|
782
775
|
* @returns The resource if available; undefined otherwise.
|
|
783
776
|
*/
|
|
784
|
-
readReference(reference, options
|
|
777
|
+
readReference(reference, options) {
|
|
785
778
|
const refString = reference?.reference;
|
|
786
779
|
if (!refString) {
|
|
787
780
|
return new ReadablePromise(Promise.reject(new Error('Missing reference')));
|
|
@@ -877,14 +870,13 @@ class MedplumClient extends EventTarget {
|
|
|
877
870
|
* ```
|
|
878
871
|
*
|
|
879
872
|
* See the FHIR "history" operation for full details: https://www.hl7.org/fhir/http.html#history
|
|
880
|
-
*
|
|
881
873
|
* @category Read
|
|
882
874
|
* @param resourceType The FHIR resource type.
|
|
883
875
|
* @param id The resource ID.
|
|
884
876
|
* @param options Optional fetch options.
|
|
885
877
|
* @returns Promise to the resource history.
|
|
886
878
|
*/
|
|
887
|
-
readHistory(resourceType, id, options
|
|
879
|
+
readHistory(resourceType, id, options) {
|
|
888
880
|
return this.get(this.fhirUrl(resourceType, id, '_history'), options);
|
|
889
881
|
}
|
|
890
882
|
/**
|
|
@@ -898,7 +890,6 @@ class MedplumClient extends EventTarget {
|
|
|
898
890
|
* ```
|
|
899
891
|
*
|
|
900
892
|
* See the FHIR "vread" operation for full details: https://www.hl7.org/fhir/http.html#vread
|
|
901
|
-
*
|
|
902
893
|
* @category Read
|
|
903
894
|
* @param resourceType The FHIR resource type.
|
|
904
895
|
* @param id The resource ID.
|
|
@@ -906,7 +897,7 @@ class MedplumClient extends EventTarget {
|
|
|
906
897
|
* @param options Optional fetch options.
|
|
907
898
|
* @returns The resource if available; undefined otherwise.
|
|
908
899
|
*/
|
|
909
|
-
readVersion(resourceType, id, vid, options
|
|
900
|
+
readVersion(resourceType, id, vid, options) {
|
|
910
901
|
return this.get(this.fhirUrl(resourceType, id, '_history', vid), options);
|
|
911
902
|
}
|
|
912
903
|
/**
|
|
@@ -920,13 +911,12 @@ class MedplumClient extends EventTarget {
|
|
|
920
911
|
* ```
|
|
921
912
|
*
|
|
922
913
|
* See the FHIR "patient-everything" operation for full details: https://hl7.org/fhir/operation-patient-everything.html
|
|
923
|
-
*
|
|
924
914
|
* @category Read
|
|
925
915
|
* @param id The Patient Id
|
|
926
916
|
* @param options Optional fetch options.
|
|
927
917
|
* @returns A Bundle of all Resources related to the Patient
|
|
928
918
|
*/
|
|
929
|
-
readPatientEverything(id, options
|
|
919
|
+
readPatientEverything(id, options) {
|
|
930
920
|
return this.get(this.fhirUrl('Patient', id, '$everything'), options);
|
|
931
921
|
}
|
|
932
922
|
/**
|
|
@@ -948,17 +938,17 @@ class MedplumClient extends EventTarget {
|
|
|
948
938
|
* ```
|
|
949
939
|
*
|
|
950
940
|
* See the FHIR "create" operation for full details: https://www.hl7.org/fhir/http.html#create
|
|
951
|
-
*
|
|
952
941
|
* @category Create
|
|
953
942
|
* @param resource The FHIR resource to create.
|
|
943
|
+
* @param options Optional fetch options.
|
|
954
944
|
* @returns The result of the create operation.
|
|
955
945
|
*/
|
|
956
|
-
createResource(resource) {
|
|
946
|
+
createResource(resource, options) {
|
|
957
947
|
if (!resource.resourceType) {
|
|
958
948
|
throw new Error('Missing resourceType');
|
|
959
949
|
}
|
|
960
950
|
this.invalidateSearches(resource.resourceType);
|
|
961
|
-
return this.post(this.fhirUrl(resource.resourceType), resource);
|
|
951
|
+
return this.post(this.fhirUrl(resource.resourceType), resource, undefined, options);
|
|
962
952
|
}
|
|
963
953
|
/**
|
|
964
954
|
* Conditionally create a new FHIR resource only if some equivalent resource does not already exist on the server.
|
|
@@ -994,14 +984,15 @@ class MedplumClient extends EventTarget {
|
|
|
994
984
|
* The query parameter only contains the search parameters (what would be in the URL following the "?").
|
|
995
985
|
*
|
|
996
986
|
* See the FHIR "conditional create" operation for full details: https://www.hl7.org/fhir/http.html#ccreate
|
|
997
|
-
*
|
|
998
987
|
* @category Create
|
|
999
988
|
* @param resource The FHIR resource to create.
|
|
1000
989
|
* @param query The search query for an equivalent resource (should not include resource type or "?").
|
|
990
|
+
* @param options Optional fetch options.
|
|
1001
991
|
* @returns The result of the create operation.
|
|
1002
992
|
*/
|
|
1003
|
-
async createResourceIfNoneExist(resource, query) {
|
|
1004
|
-
return ((await this.searchOne(resource.resourceType, query)) ??
|
|
993
|
+
async createResourceIfNoneExist(resource, query, options) {
|
|
994
|
+
return ((await this.searchOne(resource.resourceType, query, options)) ??
|
|
995
|
+
this.createResource(resource, options));
|
|
1005
996
|
}
|
|
1006
997
|
/**
|
|
1007
998
|
* Creates a FHIR `Binary` resource with the provided data content.
|
|
@@ -1020,11 +1011,11 @@ class MedplumClient extends EventTarget {
|
|
|
1020
1011
|
* ```
|
|
1021
1012
|
*
|
|
1022
1013
|
* See the FHIR "create" operation for full details: https://www.hl7.org/fhir/http.html#create
|
|
1023
|
-
*
|
|
1024
1014
|
* @category Create
|
|
1025
1015
|
* @param data The binary data to upload.
|
|
1026
1016
|
* @param filename Optional filename for the binary.
|
|
1027
1017
|
* @param contentType Content type for the binary.
|
|
1018
|
+
* @param onProgress Optional callback for progress events.
|
|
1028
1019
|
* @returns The result of the create operation.
|
|
1029
1020
|
*/
|
|
1030
1021
|
createBinary(data, filename, contentType, onProgress) {
|
|
@@ -1083,9 +1074,11 @@ class MedplumClient extends EventTarget {
|
|
|
1083
1074
|
* ```
|
|
1084
1075
|
*
|
|
1085
1076
|
* See the pdfmake document definition for full details: https://pdfmake.github.io/docs/0.1/document-definition-object/
|
|
1086
|
-
*
|
|
1087
1077
|
* @category Media
|
|
1088
1078
|
* @param docDefinition The PDF document definition.
|
|
1079
|
+
* @param filename Optional filename for the PDF binary resource.
|
|
1080
|
+
* @param tableLayouts Optional pdfmake custom table layout.
|
|
1081
|
+
* @param fonts Optional pdfmake custom font dictionary.
|
|
1089
1082
|
* @returns The result of the create operation.
|
|
1090
1083
|
*/
|
|
1091
1084
|
async createPdf(docDefinition, filename, tableLayouts, fonts) {
|
|
@@ -1099,13 +1092,13 @@ class MedplumClient extends EventTarget {
|
|
|
1099
1092
|
* Creates a FHIR `Communication` resource with the provided data content.
|
|
1100
1093
|
*
|
|
1101
1094
|
* This is a convenience method to handle commmon cases where a `Communication` resource is created with a `payload`.
|
|
1102
|
-
*
|
|
1103
1095
|
* @category Create
|
|
1104
1096
|
* @param resource The FHIR resource to comment on.
|
|
1105
1097
|
* @param text The text of the comment.
|
|
1098
|
+
* @param options Optional fetch options.
|
|
1106
1099
|
* @returns The result of the create operation.
|
|
1107
1100
|
*/
|
|
1108
|
-
createComment(resource, text) {
|
|
1101
|
+
createComment(resource, text, options) {
|
|
1109
1102
|
const profile = this.getProfile();
|
|
1110
1103
|
let encounter = undefined;
|
|
1111
1104
|
let subject = undefined;
|
|
@@ -1128,7 +1121,7 @@ class MedplumClient extends EventTarget {
|
|
|
1128
1121
|
sender: profile ? createReference(profile) : undefined,
|
|
1129
1122
|
sent: new Date().toISOString(),
|
|
1130
1123
|
payload: [{ contentString: text }],
|
|
1131
|
-
});
|
|
1124
|
+
}, options);
|
|
1132
1125
|
}
|
|
1133
1126
|
/**
|
|
1134
1127
|
* Updates a FHIR resource.
|
|
@@ -1150,12 +1143,12 @@ class MedplumClient extends EventTarget {
|
|
|
1150
1143
|
* ```
|
|
1151
1144
|
*
|
|
1152
1145
|
* See the FHIR "update" operation for full details: https://www.hl7.org/fhir/http.html#update
|
|
1153
|
-
*
|
|
1154
1146
|
* @category Write
|
|
1155
1147
|
* @param resource The FHIR resource to update.
|
|
1148
|
+
* @param options Optional fetch options.
|
|
1156
1149
|
* @returns The result of the update operation.
|
|
1157
1150
|
*/
|
|
1158
|
-
async updateResource(resource) {
|
|
1151
|
+
async updateResource(resource, options) {
|
|
1159
1152
|
if (!resource.resourceType) {
|
|
1160
1153
|
throw new Error('Missing resourceType');
|
|
1161
1154
|
}
|
|
@@ -1163,7 +1156,7 @@ class MedplumClient extends EventTarget {
|
|
|
1163
1156
|
throw new Error('Missing id');
|
|
1164
1157
|
}
|
|
1165
1158
|
this.invalidateSearches(resource.resourceType);
|
|
1166
|
-
let result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
|
|
1159
|
+
let result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource, undefined, options);
|
|
1167
1160
|
if (!result) {
|
|
1168
1161
|
// On 304 not modified, result will be undefined
|
|
1169
1162
|
// Return the user input instead
|
|
@@ -1190,16 +1183,16 @@ class MedplumClient extends EventTarget {
|
|
|
1190
1183
|
* See the FHIR "update" operation for full details: https://www.hl7.org/fhir/http.html#patch
|
|
1191
1184
|
*
|
|
1192
1185
|
* See the JSONPatch specification for full details: https://tools.ietf.org/html/rfc6902
|
|
1193
|
-
*
|
|
1194
1186
|
* @category Write
|
|
1195
1187
|
* @param resourceType The FHIR resource type.
|
|
1196
1188
|
* @param id The resource ID.
|
|
1197
1189
|
* @param operations The JSONPatch operations.
|
|
1190
|
+
* @param options Optional fetch options.
|
|
1198
1191
|
* @returns The result of the patch operations.
|
|
1199
1192
|
*/
|
|
1200
|
-
patchResource(resourceType, id, operations) {
|
|
1193
|
+
patchResource(resourceType, id, operations, options) {
|
|
1201
1194
|
this.invalidateSearches(resourceType);
|
|
1202
|
-
return this.patch(this.fhirUrl(resourceType, id), operations);
|
|
1195
|
+
return this.patch(this.fhirUrl(resourceType, id), operations, options);
|
|
1203
1196
|
}
|
|
1204
1197
|
/**
|
|
1205
1198
|
* Deletes a FHIR resource by resource type and ID.
|
|
@@ -1211,16 +1204,16 @@ class MedplumClient extends EventTarget {
|
|
|
1211
1204
|
* ```
|
|
1212
1205
|
*
|
|
1213
1206
|
* See the FHIR "delete" operation for full details: https://www.hl7.org/fhir/http.html#delete
|
|
1214
|
-
*
|
|
1215
1207
|
* @category Delete
|
|
1216
1208
|
* @param resourceType The FHIR resource type.
|
|
1217
1209
|
* @param id The resource ID.
|
|
1210
|
+
* @param options Optional fetch options.
|
|
1218
1211
|
* @returns The result of the delete operation.
|
|
1219
1212
|
*/
|
|
1220
|
-
deleteResource(resourceType, id) {
|
|
1213
|
+
deleteResource(resourceType, id, options) {
|
|
1221
1214
|
this.deleteCacheEntry(this.fhirUrl(resourceType, id).toString());
|
|
1222
1215
|
this.invalidateSearches(resourceType);
|
|
1223
|
-
return this.delete(this.fhirUrl(resourceType, id));
|
|
1216
|
+
return this.delete(this.fhirUrl(resourceType, id), options);
|
|
1224
1217
|
}
|
|
1225
1218
|
/**
|
|
1226
1219
|
* Executes the validate operation with the provided resource.
|
|
@@ -1235,12 +1228,12 @@ class MedplumClient extends EventTarget {
|
|
|
1235
1228
|
* ```
|
|
1236
1229
|
*
|
|
1237
1230
|
* See the FHIR "$validate" operation for full details: https://www.hl7.org/fhir/resource-operation-validate.html
|
|
1238
|
-
*
|
|
1239
1231
|
* @param resource The FHIR resource.
|
|
1232
|
+
* @param options Optional fetch options.
|
|
1240
1233
|
* @returns The validate operation outcome.
|
|
1241
1234
|
*/
|
|
1242
|
-
validateResource(resource) {
|
|
1243
|
-
return this.post(this.fhirUrl(resource.resourceType, '$validate'), resource);
|
|
1235
|
+
validateResource(resource, options) {
|
|
1236
|
+
return this.post(this.fhirUrl(resource.resourceType, '$validate'), resource, undefined, options);
|
|
1244
1237
|
}
|
|
1245
1238
|
/**
|
|
1246
1239
|
* Executes a bot by ID or Identifier.
|
|
@@ -1250,7 +1243,7 @@ class MedplumClient extends EventTarget {
|
|
|
1250
1243
|
* @param options Optional fetch options.
|
|
1251
1244
|
* @returns The Bot return value.
|
|
1252
1245
|
*/
|
|
1253
|
-
executeBot(idOrIdentifier, body, contentType, options
|
|
1246
|
+
executeBot(idOrIdentifier, body, contentType, options) {
|
|
1254
1247
|
let url;
|
|
1255
1248
|
if (typeof idOrIdentifier === 'string') {
|
|
1256
1249
|
const id = idOrIdentifier;
|
|
@@ -1310,7 +1303,7 @@ class MedplumClient extends EventTarget {
|
|
|
1310
1303
|
* @param options Optional fetch options.
|
|
1311
1304
|
* @returns The FHIR batch/transaction response bundle.
|
|
1312
1305
|
*/
|
|
1313
|
-
executeBatch(bundle, options
|
|
1306
|
+
executeBatch(bundle, options) {
|
|
1314
1307
|
return this.post(this.fhirBaseUrl.slice(0, -1), bundle, undefined, options);
|
|
1315
1308
|
}
|
|
1316
1309
|
/**
|
|
@@ -1347,11 +1340,12 @@ class MedplumClient extends EventTarget {
|
|
|
1347
1340
|
*
|
|
1348
1341
|
* See options here: https://nodemailer.com/extras/mailcomposer/
|
|
1349
1342
|
* @category Media
|
|
1350
|
-
* @param
|
|
1343
|
+
* @param email The MailComposer options.
|
|
1344
|
+
* @param options Optional fetch options.
|
|
1351
1345
|
* @returns Promise to the operation outcome.
|
|
1352
1346
|
*/
|
|
1353
|
-
sendEmail(email) {
|
|
1354
|
-
return this.post('email/v1/send', email, 'application/json');
|
|
1347
|
+
sendEmail(email, options) {
|
|
1348
|
+
return this.post('email/v1/send', email, 'application/json', options);
|
|
1355
1349
|
}
|
|
1356
1350
|
/**
|
|
1357
1351
|
* Executes a GraphQL query.
|
|
@@ -1393,7 +1387,6 @@ class MedplumClient extends EventTarget {
|
|
|
1393
1387
|
* See the GraphQL documentation for more details: https://graphql.org/learn/
|
|
1394
1388
|
*
|
|
1395
1389
|
* See the FHIR GraphQL documentation for FHIR specific details: https://www.hl7.org/fhir/graphql.html
|
|
1396
|
-
*
|
|
1397
1390
|
* @category Read
|
|
1398
1391
|
* @param query The GraphQL query.
|
|
1399
1392
|
* @param operationName Optional GraphQL operation name.
|
|
@@ -1408,15 +1401,15 @@ class MedplumClient extends EventTarget {
|
|
|
1408
1401
|
*
|
|
1409
1402
|
* Executes the $graph operation on this resource to fetch a Bundle of resources linked to the target resource
|
|
1410
1403
|
* according to a graph definition
|
|
1411
|
-
|
|
1412
1404
|
* @category Read
|
|
1413
1405
|
* @param resourceType The FHIR resource type.
|
|
1414
1406
|
* @param id The resource ID.
|
|
1415
1407
|
* @param graphName `name` parameter of the GraphDefinition
|
|
1408
|
+
* @param options Optional fetch options.
|
|
1416
1409
|
* @returns A Bundle
|
|
1417
1410
|
*/
|
|
1418
|
-
readResourceGraph(resourceType, id, graphName) {
|
|
1419
|
-
return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}
|
|
1411
|
+
readResourceGraph(resourceType, id, graphName, options) {
|
|
1412
|
+
return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}`, options);
|
|
1420
1413
|
}
|
|
1421
1414
|
/**
|
|
1422
1415
|
* @category Authentication
|
|
@@ -1426,11 +1419,16 @@ class MedplumClient extends EventTarget {
|
|
|
1426
1419
|
return this.storage.getObject('activeLogin');
|
|
1427
1420
|
}
|
|
1428
1421
|
/**
|
|
1422
|
+
* Sets the active login.
|
|
1423
|
+
* @param login The new active login state.
|
|
1429
1424
|
* @category Authentication
|
|
1430
1425
|
*/
|
|
1431
1426
|
async setActiveLogin(login) {
|
|
1432
1427
|
this.clearActiveLogin();
|
|
1433
1428
|
this.accessToken = login.accessToken;
|
|
1429
|
+
if (this.basicAuth) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1434
1432
|
this.refreshToken = login.refreshToken;
|
|
1435
1433
|
this.storage.setObject('activeLogin', login);
|
|
1436
1434
|
this.addLogin(login);
|
|
@@ -1439,6 +1437,7 @@ class MedplumClient extends EventTarget {
|
|
|
1439
1437
|
}
|
|
1440
1438
|
/**
|
|
1441
1439
|
* Returns the current access token.
|
|
1440
|
+
* @returns The current access token.
|
|
1442
1441
|
* @category Authentication
|
|
1443
1442
|
*/
|
|
1444
1443
|
getAccessToken() {
|
|
@@ -1446,6 +1445,7 @@ class MedplumClient extends EventTarget {
|
|
|
1446
1445
|
}
|
|
1447
1446
|
/**
|
|
1448
1447
|
* Sets the current access token.
|
|
1448
|
+
* @param accessToken The new access token.
|
|
1449
1449
|
* @category Authentication
|
|
1450
1450
|
*/
|
|
1451
1451
|
setAccessToken(accessToken) {
|
|
@@ -1455,6 +1455,8 @@ class MedplumClient extends EventTarget {
|
|
|
1455
1455
|
this.config = undefined;
|
|
1456
1456
|
}
|
|
1457
1457
|
/**
|
|
1458
|
+
* Returns the list of available logins.
|
|
1459
|
+
* @returns The list of available logins.
|
|
1458
1460
|
* @category Authentication
|
|
1459
1461
|
*/
|
|
1460
1462
|
getLogins() {
|
|
@@ -1467,6 +1469,9 @@ class MedplumClient extends EventTarget {
|
|
|
1467
1469
|
}
|
|
1468
1470
|
async refreshProfile() {
|
|
1469
1471
|
this.profilePromise = new Promise((resolve, reject) => {
|
|
1472
|
+
if (this.basicAuth) {
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1470
1475
|
this.get('auth/me')
|
|
1471
1476
|
.then((result) => {
|
|
1472
1477
|
this.profilePromise = undefined;
|
|
@@ -1480,18 +1485,26 @@ class MedplumClient extends EventTarget {
|
|
|
1480
1485
|
return this.profilePromise;
|
|
1481
1486
|
}
|
|
1482
1487
|
/**
|
|
1488
|
+
* Returns true if the client is waiting for authentication.
|
|
1489
|
+
* @returns True if the client is waiting for authentication.
|
|
1483
1490
|
* @category Authentication
|
|
1484
1491
|
*/
|
|
1485
1492
|
isLoading() {
|
|
1486
1493
|
return !!this.profilePromise;
|
|
1487
1494
|
}
|
|
1488
1495
|
/**
|
|
1496
|
+
* Returns the current user profile resource if available.
|
|
1497
|
+
* This method does not wait for loading promises.
|
|
1498
|
+
* @returns The current user profile resource if available.
|
|
1489
1499
|
* @category User Profile
|
|
1490
1500
|
*/
|
|
1491
1501
|
getProfile() {
|
|
1492
1502
|
return this.profile;
|
|
1493
1503
|
}
|
|
1494
1504
|
/**
|
|
1505
|
+
* Returns the current user profile resource if available.
|
|
1506
|
+
* This method waits for loading promises.
|
|
1507
|
+
* @returns The current user profile resource if available.
|
|
1495
1508
|
* @category User Profile
|
|
1496
1509
|
*/
|
|
1497
1510
|
async getProfileAsync() {
|
|
@@ -1501,6 +1514,8 @@ class MedplumClient extends EventTarget {
|
|
|
1501
1514
|
return this.getProfile();
|
|
1502
1515
|
}
|
|
1503
1516
|
/**
|
|
1517
|
+
* Returns the current user configuration if available.
|
|
1518
|
+
* @returns The current user configuration if available.
|
|
1504
1519
|
* @category User Profile
|
|
1505
1520
|
*/
|
|
1506
1521
|
getUserConfiguration() {
|
|
@@ -1508,9 +1523,9 @@ class MedplumClient extends EventTarget {
|
|
|
1508
1523
|
}
|
|
1509
1524
|
/**
|
|
1510
1525
|
* Downloads the URL as a blob.
|
|
1511
|
-
*
|
|
1512
1526
|
* @category Read
|
|
1513
1527
|
* @param url The URL to request.
|
|
1528
|
+
* @param options Optional fetch request init options.
|
|
1514
1529
|
* @returns Promise to the response body as a blob.
|
|
1515
1530
|
*/
|
|
1516
1531
|
async download(url, options = {}) {
|
|
@@ -1524,12 +1539,13 @@ class MedplumClient extends EventTarget {
|
|
|
1524
1539
|
/**
|
|
1525
1540
|
* Upload media to the server and create a Media instance for the uploaded content.
|
|
1526
1541
|
* @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
|
|
1542
|
+
* @param contentType The media type of the content.
|
|
1543
|
+
* @param filename The name of the file to be uploaded, or undefined if not applicable.
|
|
1544
|
+
* @param additionalFields Additional fields for Media.
|
|
1545
|
+
* @param options Optional fetch options.
|
|
1530
1546
|
* @returns Promise that resolves to the created Media
|
|
1531
1547
|
*/
|
|
1532
|
-
async uploadMedia(contents, contentType, filename, additionalFields) {
|
|
1548
|
+
async uploadMedia(contents, contentType, filename, additionalFields, options) {
|
|
1533
1549
|
const binary = await this.createBinary(contents, filename, contentType);
|
|
1534
1550
|
return this.createResource({
|
|
1535
1551
|
...additionalFields,
|
|
@@ -1539,11 +1555,10 @@ class MedplumClient extends EventTarget {
|
|
|
1539
1555
|
url: 'Binary/' + binary.id,
|
|
1540
1556
|
title: filename,
|
|
1541
1557
|
},
|
|
1542
|
-
});
|
|
1558
|
+
}, options);
|
|
1543
1559
|
}
|
|
1544
1560
|
/**
|
|
1545
1561
|
* 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
1562
|
* @param exportLevel Optional export level. Defaults to system level export. 'Group/:id' - Group of Patients, 'Patient' - All Patients.
|
|
1548
1563
|
* @param resourceTypes A string of comma-delimited FHIR resource types.
|
|
1549
1564
|
* @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 +1574,6 @@ class MedplumClient extends EventTarget {
|
|
|
1559
1574
|
if (since) {
|
|
1560
1575
|
url.searchParams.set('_since', since);
|
|
1561
1576
|
}
|
|
1562
|
-
options.method = exportLevel ? 'GET' : 'POST';
|
|
1563
1577
|
this.addFetchOptionsDefaults(options);
|
|
1564
1578
|
const headers = options.headers;
|
|
1565
1579
|
headers['Prefer'] = 'respond-async';
|
|
@@ -1623,10 +1637,10 @@ class MedplumClient extends EventTarget {
|
|
|
1623
1637
|
}
|
|
1624
1638
|
/**
|
|
1625
1639
|
* Makes an HTTP request.
|
|
1626
|
-
* @param
|
|
1627
|
-
* @param
|
|
1628
|
-
* @param
|
|
1629
|
-
* @
|
|
1640
|
+
* @param method The HTTP method (GET, POST, etc).
|
|
1641
|
+
* @param url The target URL.
|
|
1642
|
+
* @param options Optional fetch request init options.
|
|
1643
|
+
* @returns The JSON content body if available.
|
|
1630
1644
|
*/
|
|
1631
1645
|
async request(method, url, options = {}) {
|
|
1632
1646
|
if (this.refreshPromise) {
|
|
@@ -1691,9 +1705,7 @@ class MedplumClient extends EventTarget {
|
|
|
1691
1705
|
let resultResponse;
|
|
1692
1706
|
const retryDelay = 200;
|
|
1693
1707
|
while (checkStatus) {
|
|
1694
|
-
const fetchOptions = {
|
|
1695
|
-
method: 'GET',
|
|
1696
|
-
};
|
|
1708
|
+
const fetchOptions = {};
|
|
1697
1709
|
this.addFetchOptionsDefaults(fetchOptions);
|
|
1698
1710
|
const statusResponse = await this.fetchWithRetry(statusUrl, fetchOptions);
|
|
1699
1711
|
if (statusResponse.status !== 202) {
|
|
@@ -1769,7 +1781,7 @@ class MedplumClient extends EventTarget {
|
|
|
1769
1781
|
if (this.accessToken) {
|
|
1770
1782
|
headers['Authorization'] = 'Bearer ' + this.accessToken;
|
|
1771
1783
|
}
|
|
1772
|
-
if (this.basicAuth) {
|
|
1784
|
+
else if (this.basicAuth) {
|
|
1773
1785
|
headers['Authorization'] = 'Basic ' + this.basicAuth;
|
|
1774
1786
|
}
|
|
1775
1787
|
if (!options.cache) {
|
|
@@ -1813,8 +1825,8 @@ class MedplumClient extends EventTarget {
|
|
|
1813
1825
|
* Otherwise, calls unauthenticated callbacks and rejects.
|
|
1814
1826
|
* @param method The HTTP method of the original request.
|
|
1815
1827
|
* @param url The URL of the original request.
|
|
1816
|
-
* @param
|
|
1817
|
-
* @
|
|
1828
|
+
* @param options Optional fetch request init options.
|
|
1829
|
+
* @returns The result of the retry.
|
|
1818
1830
|
*/
|
|
1819
1831
|
handleUnauthenticated(method, url, options) {
|
|
1820
1832
|
if (this.refresh()) {
|
|
@@ -1830,6 +1842,7 @@ class MedplumClient extends EventTarget {
|
|
|
1830
1842
|
* Starts a new PKCE flow.
|
|
1831
1843
|
* These PKCE values are stateful, and must survive redirects and page refreshes.
|
|
1832
1844
|
* @category Authentication
|
|
1845
|
+
* @returns The PKCE code challenge details.
|
|
1833
1846
|
*/
|
|
1834
1847
|
async startPkce() {
|
|
1835
1848
|
const pkceState = getRandomString();
|
|
@@ -1844,7 +1857,8 @@ class MedplumClient extends EventTarget {
|
|
|
1844
1857
|
/**
|
|
1845
1858
|
* Redirects the user to the login screen for authorization.
|
|
1846
1859
|
* Clears all auth state including local storage and session storage.
|
|
1847
|
-
*
|
|
1860
|
+
* @param loginParams The authorization login parameters.
|
|
1861
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
|
|
1848
1862
|
*/
|
|
1849
1863
|
async requestAuthorization(loginParams) {
|
|
1850
1864
|
const loginRequest = await this.ensureCodeChallenge(loginParams || {});
|
|
@@ -1863,6 +1877,7 @@ class MedplumClient extends EventTarget {
|
|
|
1863
1877
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
|
|
1864
1878
|
* @param code The authorization code received by URL parameter.
|
|
1865
1879
|
* @param loginParams Optional login parameters.
|
|
1880
|
+
* @returns The user profile resource.
|
|
1866
1881
|
* @category Authentication
|
|
1867
1882
|
*/
|
|
1868
1883
|
processCode(code, loginParams) {
|
|
@@ -1881,7 +1896,8 @@ class MedplumClient extends EventTarget {
|
|
|
1881
1896
|
}
|
|
1882
1897
|
/**
|
|
1883
1898
|
* Tries to refresh the auth tokens.
|
|
1884
|
-
*
|
|
1899
|
+
* @returns The refresh promise if available; otherwise undefined.
|
|
1900
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
|
|
1885
1901
|
*/
|
|
1886
1902
|
refresh() {
|
|
1887
1903
|
if (this.refreshPromise) {
|
|
@@ -1934,7 +1950,6 @@ class MedplumClient extends EventTarget {
|
|
|
1934
1950
|
* // Example Search
|
|
1935
1951
|
* await medplum.searchResources('Patient')
|
|
1936
1952
|
* ```
|
|
1937
|
-
*
|
|
1938
1953
|
* @category Authentication
|
|
1939
1954
|
* @param clientId The client ID.
|
|
1940
1955
|
* @param clientSecret The client secret.
|
|
@@ -1957,14 +1972,20 @@ class MedplumClient extends EventTarget {
|
|
|
1957
1972
|
* Makes a POST request to the tokens endpoint.
|
|
1958
1973
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1959
1974
|
* @param formBody Token parameters in URL encoded format.
|
|
1975
|
+
* @returns The user profile resource.
|
|
1960
1976
|
*/
|
|
1961
1977
|
async fetchTokens(formBody) {
|
|
1962
|
-
const
|
|
1978
|
+
const options = {
|
|
1963
1979
|
method: 'POST',
|
|
1964
1980
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1965
1981
|
body: formBody,
|
|
1966
1982
|
credentials: 'include',
|
|
1967
|
-
}
|
|
1983
|
+
};
|
|
1984
|
+
const headers = options.headers;
|
|
1985
|
+
if (this.basicAuth) {
|
|
1986
|
+
headers['Authorization'] = `Basic ${this.basicAuth}`;
|
|
1987
|
+
}
|
|
1988
|
+
const response = await this.fetch(this.tokenUrl, options);
|
|
1968
1989
|
if (!response.ok) {
|
|
1969
1990
|
this.clearActiveLogin();
|
|
1970
1991
|
throw new Error('Failed to fetch tokens');
|
|
@@ -1977,7 +1998,8 @@ class MedplumClient extends EventTarget {
|
|
|
1977
1998
|
* Verifies the tokens received from the auth server.
|
|
1978
1999
|
* Validates the JWT against the JWKS.
|
|
1979
2000
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1980
|
-
* @param tokens
|
|
2001
|
+
* @param tokens The token response.
|
|
2002
|
+
* @returns Promise to complete.
|
|
1981
2003
|
*/
|
|
1982
2004
|
async verifyTokens(tokens) {
|
|
1983
2005
|
const token = tokens.access_token;
|
|
@@ -1988,7 +2010,14 @@ class MedplumClient extends EventTarget {
|
|
|
1988
2010
|
throw new Error('Token expired');
|
|
1989
2011
|
}
|
|
1990
2012
|
// Verify app_client_id
|
|
1991
|
-
|
|
2013
|
+
// external tokenPayload
|
|
2014
|
+
if (tokenPayload.cid) {
|
|
2015
|
+
if (tokenPayload.cid !== this.clientId) {
|
|
2016
|
+
this.clearActiveLogin();
|
|
2017
|
+
throw new Error('Token was not issued for this audience');
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
else if (this.clientId && tokenPayload.client_id !== this.clientId) {
|
|
1992
2021
|
this.clearActiveLogin();
|
|
1993
2022
|
throw new Error('Token was not issued for this audience');
|
|
1994
2023
|
}
|
|
@@ -2042,6 +2071,7 @@ function getDefaultFetch() {
|
|
|
2042
2071
|
}
|
|
2043
2072
|
/**
|
|
2044
2073
|
* Returns the base URL for the current page.
|
|
2074
|
+
* @returns The window origin string.
|
|
2045
2075
|
* @category HTTP
|
|
2046
2076
|
*/
|
|
2047
2077
|
function getWindowOrigin() {
|