@medplum/core 1.0.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/cjs/client.d.ts +22 -6
- package/dist/cjs/format.d.ts +2 -1
- package/dist/cjs/{index.js → index.cjs} +355 -376
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.min.cjs +1 -0
- package/dist/cjs/search.d.ts +2 -1
- package/dist/cjs/utils.d.ts +8 -1
- package/dist/esm/{base-schema.json.js → base-schema.json.mjs} +1 -1
- package/dist/esm/{base-schema.json.js.map → base-schema.json.mjs.map} +1 -1
- package/dist/esm/{cache.js → cache.mjs} +2 -2
- package/dist/esm/cache.mjs.map +1 -0
- package/dist/esm/client.d.ts +22 -6
- package/dist/esm/{client.js → client.mjs} +256 -260
- package/dist/esm/client.mjs.map +1 -0
- package/dist/esm/{crypto.js → crypto.mjs} +4 -7
- package/dist/esm/crypto.mjs.map +1 -0
- package/dist/esm/{eventtarget.js → eventtarget.mjs} +2 -2
- package/dist/esm/eventtarget.mjs.map +1 -0
- package/dist/esm/fhirlexer/{parse.js → parse.mjs} +5 -6
- package/dist/esm/fhirlexer/parse.mjs.map +1 -0
- package/dist/esm/fhirlexer/{tokenize.js → tokenize.mjs} +11 -11
- package/dist/esm/fhirlexer/tokenize.mjs.map +1 -0
- package/dist/esm/fhirpath/{atoms.js → atoms.mjs} +11 -12
- package/dist/esm/fhirpath/atoms.mjs.map +1 -0
- package/dist/esm/fhirpath/{date.js → date.mjs} +1 -1
- package/dist/esm/fhirpath/date.mjs.map +1 -0
- package/dist/esm/fhirpath/{functions.js → functions.mjs} +16 -22
- package/dist/esm/fhirpath/functions.mjs.map +1 -0
- package/dist/esm/fhirpath/{parse.js → parse.mjs} +9 -10
- package/dist/esm/fhirpath/parse.mjs.map +1 -0
- package/dist/esm/fhirpath/{tokenize.js → tokenize.mjs} +3 -3
- package/dist/esm/fhirpath/tokenize.mjs.map +1 -0
- package/dist/esm/fhirpath/{utils.js → utils.mjs} +6 -7
- package/dist/esm/fhirpath/utils.mjs.map +1 -0
- package/dist/esm/format.d.ts +2 -1
- package/dist/esm/{format.js → format.mjs} +29 -21
- package/dist/esm/format.mjs.map +1 -0
- package/dist/esm/{hl7.js → hl7.mjs} +8 -9
- package/dist/esm/hl7.mjs.map +1 -0
- package/dist/esm/index.min.mjs +1 -0
- package/dist/esm/{index.js → index.mjs} +17 -17
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/{jwt.js → jwt.mjs} +1 -1
- package/dist/esm/jwt.mjs.map +1 -0
- package/dist/esm/{match.js → match.mjs} +12 -13
- package/dist/esm/match.mjs.map +1 -0
- package/dist/esm/node_modules/tslib/{tslib.es6.js → tslib.es6.mjs} +2 -12
- package/dist/esm/node_modules/tslib/tslib.es6.mjs.map +1 -0
- package/dist/esm/{outcomes.js → outcomes.mjs} +3 -5
- package/dist/esm/outcomes.mjs.map +1 -0
- package/dist/esm/{readablepromise.js → readablepromise.mjs} +2 -2
- package/dist/esm/readablepromise.mjs.map +1 -0
- package/dist/esm/search.d.ts +2 -1
- package/dist/esm/{search.js → search.mjs} +1 -1
- package/dist/esm/search.mjs.map +1 -0
- package/dist/esm/{searchparams.js → searchparams.mjs} +8 -9
- package/dist/esm/searchparams.mjs.map +1 -0
- package/dist/esm/{storage.js → storage.mjs} +4 -5
- package/dist/esm/storage.mjs.map +1 -0
- package/dist/esm/{types.js → types.mjs} +6 -9
- package/dist/esm/types.mjs.map +1 -0
- package/dist/esm/utils.d.ts +8 -1
- package/dist/esm/{utils.js → utils.mjs} +31 -27
- package/dist/esm/utils.mjs.map +1 -0
- package/package.json +5 -5
- package/rollup.config.mjs +6 -7
- package/dist/cjs/fhirmapper/testall.d.ts +0 -1
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/index.min.js +0 -2
- package/dist/cjs/index.min.js.map +0 -1
- package/dist/esm/cache.js.map +0 -1
- package/dist/esm/client.js.map +0 -1
- package/dist/esm/crypto.js.map +0 -1
- package/dist/esm/eventtarget.js.map +0 -1
- package/dist/esm/fhirlexer/parse.js.map +0 -1
- package/dist/esm/fhirlexer/tokenize.js.map +0 -1
- package/dist/esm/fhirmapper/testall.d.ts +0 -1
- package/dist/esm/fhirpath/atoms.js.map +0 -1
- package/dist/esm/fhirpath/date.js.map +0 -1
- package/dist/esm/fhirpath/functions.js.map +0 -1
- package/dist/esm/fhirpath/parse.js.map +0 -1
- package/dist/esm/fhirpath/tokenize.js.map +0 -1
- package/dist/esm/fhirpath/utils.js.map +0 -1
- package/dist/esm/format.js.map +0 -1
- package/dist/esm/hl7.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/index.min.js +0 -2
- package/dist/esm/index.min.js.map +0 -1
- package/dist/esm/jwt.js.map +0 -1
- package/dist/esm/match.js.map +0 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +0 -1
- package/dist/esm/outcomes.js.map +0 -1
- package/dist/esm/readablepromise.js.map +0 -1
- package/dist/esm/search.js.map +0 -1
- package/dist/esm/searchparams.js.map +0 -1
- package/dist/esm/storage.js.map +0 -1
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { __classPrivateFieldSet, __classPrivateFieldGet
|
|
2
|
-
import { LRUCache } from './cache.
|
|
3
|
-
import { getRandomString, encryptSHA256 } from './crypto.
|
|
4
|
-
import { EventTarget } from './eventtarget.
|
|
5
|
-
import { parseJWTPayload } from './jwt.
|
|
6
|
-
import { ReadablePromise } from './readablepromise.
|
|
7
|
-
import { ClientStorage } from './storage.
|
|
8
|
-
import { globalSchema, indexStructureDefinition, indexSearchParameter } from './types.
|
|
9
|
-
import { createReference, arrayBufferToBase64 } from './utils.
|
|
1
|
+
import { __classPrivateFieldSet, __classPrivateFieldGet } from './node_modules/tslib/tslib.es6.mjs';
|
|
2
|
+
import { LRUCache } from './cache.mjs';
|
|
3
|
+
import { getRandomString, encryptSHA256 } from './crypto.mjs';
|
|
4
|
+
import { EventTarget } from './eventtarget.mjs';
|
|
5
|
+
import { parseJWTPayload } from './jwt.mjs';
|
|
6
|
+
import { ReadablePromise } from './readablepromise.mjs';
|
|
7
|
+
import { ClientStorage } from './storage.mjs';
|
|
8
|
+
import { globalSchema, indexStructureDefinition, indexSearchParameter } from './types.mjs';
|
|
9
|
+
import { createReference, arrayBufferToBase64 } from './utils.mjs';
|
|
10
10
|
|
|
11
11
|
// PKCE auth based on:
|
|
12
12
|
// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
|
|
13
13
|
var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_clientId, _MedplumClient_clientSecret, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_request, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
|
|
14
|
-
const MEDPLUM_VERSION = "
|
|
14
|
+
const MEDPLUM_VERSION = "2.0.0-7fe99080";
|
|
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
|
|
@@ -72,7 +72,6 @@ const PATCH_CONTENT_TYPE = 'application/json-patch+json';
|
|
|
72
72
|
*/
|
|
73
73
|
class MedplumClient extends EventTarget {
|
|
74
74
|
constructor(options) {
|
|
75
|
-
var _a, _b;
|
|
76
75
|
super();
|
|
77
76
|
_MedplumClient_instances.add(this);
|
|
78
77
|
_MedplumClient_fetch.set(this, void 0);
|
|
@@ -93,22 +92,22 @@ class MedplumClient extends EventTarget {
|
|
|
93
92
|
_MedplumClient_profilePromise.set(this, void 0);
|
|
94
93
|
_MedplumClient_profile.set(this, void 0);
|
|
95
94
|
_MedplumClient_config.set(this, void 0);
|
|
96
|
-
if (options
|
|
95
|
+
if (options?.baseUrl) {
|
|
97
96
|
if (!options.baseUrl.startsWith('http')) {
|
|
98
97
|
throw new Error('Base URL must start with http or https');
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
|
-
__classPrivateFieldSet(this, _MedplumClient_fetch,
|
|
102
|
-
__classPrivateFieldSet(this, _MedplumClient_createPdf, options
|
|
100
|
+
__classPrivateFieldSet(this, _MedplumClient_fetch, options?.fetch || window.fetch.bind(window), "f");
|
|
101
|
+
__classPrivateFieldSet(this, _MedplumClient_createPdf, options?.createPdf, "f");
|
|
103
102
|
__classPrivateFieldSet(this, _MedplumClient_storage, new ClientStorage(), "f");
|
|
104
|
-
__classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(
|
|
105
|
-
__classPrivateFieldSet(this, _MedplumClient_cacheTime,
|
|
106
|
-
__classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options
|
|
107
|
-
__classPrivateFieldSet(this, _MedplumClient_clientId,
|
|
108
|
-
__classPrivateFieldSet(this, _MedplumClient_authorizeUrl,
|
|
109
|
-
__classPrivateFieldSet(this, _MedplumClient_tokenUrl,
|
|
110
|
-
__classPrivateFieldSet(this, _MedplumClient_logoutUrl,
|
|
111
|
-
__classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options
|
|
103
|
+
__classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
|
|
104
|
+
__classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
|
|
105
|
+
__classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
|
|
106
|
+
__classPrivateFieldSet(this, _MedplumClient_clientId, options?.clientId || '', "f");
|
|
107
|
+
__classPrivateFieldSet(this, _MedplumClient_authorizeUrl, options?.authorizeUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
|
|
108
|
+
__classPrivateFieldSet(this, _MedplumClient_tokenUrl, options?.tokenUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
|
|
109
|
+
__classPrivateFieldSet(this, _MedplumClient_logoutUrl, options?.logoutUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/logout', "f");
|
|
110
|
+
__classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options?.onUnauthenticated, "f");
|
|
112
111
|
const activeLogin = this.getActiveLogin();
|
|
113
112
|
if (activeLogin) {
|
|
114
113
|
__classPrivateFieldSet(this, _MedplumClient_accessToken, activeLogin.accessToken, "f");
|
|
@@ -133,6 +132,15 @@ class MedplumClient extends EventTarget {
|
|
|
133
132
|
*/
|
|
134
133
|
clear() {
|
|
135
134
|
__classPrivateFieldGet(this, _MedplumClient_storage, "f").clear();
|
|
135
|
+
this.clearActiveLogin();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clears the active login from local storage.
|
|
139
|
+
* Does not clear all local storage (such as other logins).
|
|
140
|
+
* @category Authentication
|
|
141
|
+
*/
|
|
142
|
+
clearActiveLogin() {
|
|
143
|
+
__classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('activeLogin', undefined);
|
|
136
144
|
__classPrivateFieldGet(this, _MedplumClient_requestCache, "f").clear();
|
|
137
145
|
__classPrivateFieldSet(this, _MedplumClient_accessToken, undefined, "f");
|
|
138
146
|
__classPrivateFieldSet(this, _MedplumClient_refreshToken, undefined, "f");
|
|
@@ -283,10 +291,12 @@ class MedplumClient extends EventTarget {
|
|
|
283
291
|
* @param newUserRequest Register request including email and password.
|
|
284
292
|
* @returns Promise to the authentication response.
|
|
285
293
|
*/
|
|
286
|
-
startNewUser(newUserRequest) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
294
|
+
async startNewUser(newUserRequest) {
|
|
295
|
+
const { codeChallengeMethod, codeChallenge } = await this.startPkce();
|
|
296
|
+
return this.post('auth/newuser', {
|
|
297
|
+
...newUserRequest,
|
|
298
|
+
codeChallengeMethod,
|
|
299
|
+
codeChallenge,
|
|
290
300
|
});
|
|
291
301
|
}
|
|
292
302
|
/**
|
|
@@ -297,10 +307,8 @@ class MedplumClient extends EventTarget {
|
|
|
297
307
|
* @param newProjectRequest Register request including email and password.
|
|
298
308
|
* @returns Promise to the authentication response.
|
|
299
309
|
*/
|
|
300
|
-
startNewProject(newProjectRequest) {
|
|
301
|
-
return
|
|
302
|
-
return this.post('auth/newproject', newProjectRequest);
|
|
303
|
-
});
|
|
310
|
+
async startNewProject(newProjectRequest) {
|
|
311
|
+
return this.post('auth/newproject', newProjectRequest);
|
|
304
312
|
}
|
|
305
313
|
/**
|
|
306
314
|
* Initiates a new patient flow.
|
|
@@ -310,10 +318,8 @@ class MedplumClient extends EventTarget {
|
|
|
310
318
|
* @param newPatientRequest Register request including email and password.
|
|
311
319
|
* @returns Promise to the authentication response.
|
|
312
320
|
*/
|
|
313
|
-
startNewPatient(newPatientRequest) {
|
|
314
|
-
return
|
|
315
|
-
return this.post('auth/newpatient', newPatientRequest);
|
|
316
|
-
});
|
|
321
|
+
async startNewPatient(newPatientRequest) {
|
|
322
|
+
return this.post('auth/newpatient', newPatientRequest);
|
|
317
323
|
}
|
|
318
324
|
/**
|
|
319
325
|
* Initiates a user login flow.
|
|
@@ -321,12 +327,11 @@ class MedplumClient extends EventTarget {
|
|
|
321
327
|
* @param loginRequest Login request including email and password.
|
|
322
328
|
* @returns Promise to the authentication response.
|
|
323
329
|
*/
|
|
324
|
-
startLogin(loginRequest) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
codeChallenge }));
|
|
330
|
+
async startLogin(loginRequest) {
|
|
331
|
+
return this.post('auth/login', {
|
|
332
|
+
...(await this.ensureCodeChallenge(loginRequest)),
|
|
333
|
+
clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
|
|
334
|
+
scope: loginRequest.scope,
|
|
330
335
|
});
|
|
331
336
|
}
|
|
332
337
|
/**
|
|
@@ -337,29 +342,26 @@ class MedplumClient extends EventTarget {
|
|
|
337
342
|
* @param loginRequest Login request including Google credential response.
|
|
338
343
|
* @returns Promise to the authentication response.
|
|
339
344
|
*/
|
|
340
|
-
startGoogleLogin(loginRequest) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
codeChallenge }));
|
|
345
|
+
async startGoogleLogin(loginRequest) {
|
|
346
|
+
return this.post('auth/google', {
|
|
347
|
+
...(await this.ensureCodeChallenge(loginRequest)),
|
|
348
|
+
clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
|
|
349
|
+
scope: loginRequest.scope,
|
|
346
350
|
});
|
|
347
351
|
}
|
|
348
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Returns the PKCE code challenge and method.
|
|
354
|
+
* If the login request already includes a code challenge, it is returned.
|
|
355
|
+
* Otherwise, a new PKCE code challenge is generated.
|
|
356
|
+
* @category Authentication
|
|
357
|
+
* @param loginRequest The original login request.
|
|
358
|
+
* @returns The PKCE code challenge and method.
|
|
359
|
+
*/
|
|
360
|
+
async ensureCodeChallenge(loginRequest) {
|
|
349
361
|
if (loginRequest.codeChallenge) {
|
|
350
|
-
return
|
|
351
|
-
codeChallenge: loginRequest.codeChallenge,
|
|
352
|
-
codeChallengeMethod: loginRequest.codeChallengeMethod,
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
const codeChallenge = sessionStorage.getItem('codeChallenge');
|
|
356
|
-
if (codeChallenge) {
|
|
357
|
-
return {
|
|
358
|
-
codeChallenge,
|
|
359
|
-
codeChallengeMethod: 'S256',
|
|
360
|
-
};
|
|
362
|
+
return loginRequest;
|
|
361
363
|
}
|
|
362
|
-
return {};
|
|
364
|
+
return { ...loginRequest, ...(await this.startPkce()) };
|
|
363
365
|
}
|
|
364
366
|
/**
|
|
365
367
|
* Signs out locally.
|
|
@@ -374,19 +376,18 @@ class MedplumClient extends EventTarget {
|
|
|
374
376
|
* Returns true if the user is signed in.
|
|
375
377
|
* This may result in navigating away to the sign in page.
|
|
376
378
|
* @category Authentication
|
|
379
|
+
* @param loginParams Optional login parameters.
|
|
377
380
|
*/
|
|
378
|
-
signInWithRedirect() {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
});
|
|
381
|
+
async signInWithRedirect(loginParams) {
|
|
382
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
383
|
+
const code = urlParams.get('code');
|
|
384
|
+
if (!code) {
|
|
385
|
+
await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_requestAuthorization).call(this, loginParams);
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
return this.processCode(code);
|
|
390
|
+
}
|
|
390
391
|
}
|
|
391
392
|
/**
|
|
392
393
|
* Tries to sign out the user.
|
|
@@ -502,7 +503,7 @@ class MedplumClient extends EventTarget {
|
|
|
502
503
|
if (cached) {
|
|
503
504
|
return cached.value;
|
|
504
505
|
}
|
|
505
|
-
const promise = new ReadablePromise(this.search(resourceType, url.searchParams, options).then((b) =>
|
|
506
|
+
const promise = new ReadablePromise(this.search(resourceType, url.searchParams, options).then((b) => b.entry?.[0]?.resource));
|
|
506
507
|
__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
|
|
507
508
|
return promise;
|
|
508
509
|
}
|
|
@@ -535,7 +536,7 @@ class MedplumClient extends EventTarget {
|
|
|
535
536
|
if (cached) {
|
|
536
537
|
return cached.value;
|
|
537
538
|
}
|
|
538
|
-
const promise = new ReadablePromise(this.search(resourceType, query, options).then((b) =>
|
|
539
|
+
const promise = new ReadablePromise(this.search(resourceType, query, options).then((b) => b.entry?.map((e) => e.resource) ?? []));
|
|
539
540
|
__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
|
|
540
541
|
return promise;
|
|
541
542
|
}
|
|
@@ -563,8 +564,7 @@ class MedplumClient extends EventTarget {
|
|
|
563
564
|
* @returns The resource if it is available in the cache; undefined otherwise.
|
|
564
565
|
*/
|
|
565
566
|
getCached(resourceType, id) {
|
|
566
|
-
|
|
567
|
-
const cached = (_a = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(this.fhirUrl(resourceType, id).toString())) === null || _a === void 0 ? void 0 : _a.value;
|
|
567
|
+
const cached = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(this.fhirUrl(resourceType, id).toString())?.value;
|
|
568
568
|
return cached && cached.isOk() ? cached.read() : undefined;
|
|
569
569
|
}
|
|
570
570
|
/**
|
|
@@ -627,7 +627,7 @@ class MedplumClient extends EventTarget {
|
|
|
627
627
|
* @returns The resource if available; undefined otherwise.
|
|
628
628
|
*/
|
|
629
629
|
readReference(reference, options = {}) {
|
|
630
|
-
const refString = reference
|
|
630
|
+
const refString = reference?.reference;
|
|
631
631
|
if (!refString) {
|
|
632
632
|
return new ReadablePromise(Promise.reject(new Error('Missing reference')));
|
|
633
633
|
}
|
|
@@ -655,12 +655,11 @@ class MedplumClient extends EventTarget {
|
|
|
655
655
|
* @param resourceType The FHIR resource type.
|
|
656
656
|
* @returns Promise to a schema with the requested resource type.
|
|
657
657
|
*/
|
|
658
|
-
requestSchema(resourceType) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const query = `{
|
|
658
|
+
async requestSchema(resourceType) {
|
|
659
|
+
if (resourceType in globalSchema.types) {
|
|
660
|
+
return globalSchema;
|
|
661
|
+
}
|
|
662
|
+
const query = `{
|
|
664
663
|
StructureDefinitionList(name: "${resourceType}") {
|
|
665
664
|
name,
|
|
666
665
|
description,
|
|
@@ -689,15 +688,14 @@ class MedplumClient extends EventTarget {
|
|
|
689
688
|
target
|
|
690
689
|
}
|
|
691
690
|
}`.replace(/\s+/g, ' ');
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
});
|
|
691
|
+
const response = (await this.graphql(query));
|
|
692
|
+
for (const structureDefinition of response.data.StructureDefinitionList) {
|
|
693
|
+
indexStructureDefinition(structureDefinition);
|
|
694
|
+
}
|
|
695
|
+
for (const searchParameter of response.data.SearchParameterList) {
|
|
696
|
+
indexSearchParameter(searchParameter);
|
|
697
|
+
}
|
|
698
|
+
return globalSchema;
|
|
701
699
|
}
|
|
702
700
|
/**
|
|
703
701
|
* Reads resource history by resource type and ID.
|
|
@@ -835,11 +833,8 @@ class MedplumClient extends EventTarget {
|
|
|
835
833
|
* @param query The search query for an equivalent resource (should not include resource type or "?").
|
|
836
834
|
* @returns The result of the create operation.
|
|
837
835
|
*/
|
|
838
|
-
createResourceIfNoneExist(resource, query) {
|
|
839
|
-
|
|
840
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
841
|
-
return ((_a = (yield this.searchOne(resource.resourceType, query))) !== null && _a !== void 0 ? _a : this.createResource(resource));
|
|
842
|
-
});
|
|
836
|
+
async createResourceIfNoneExist(resource, query) {
|
|
837
|
+
return ((await this.searchOne(resource.resourceType, query)) ?? this.createResource(resource));
|
|
843
838
|
}
|
|
844
839
|
/**
|
|
845
840
|
* Creates a FHIR `Binary` resource with the provided data content.
|
|
@@ -926,14 +921,12 @@ class MedplumClient extends EventTarget {
|
|
|
926
921
|
* @param docDefinition The PDF document definition.
|
|
927
922
|
* @returns The result of the create operation.
|
|
928
923
|
*/
|
|
929
|
-
createPdf(docDefinition, filename, tableLayouts, fonts) {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
return this.createBinary(blob, filename, 'application/pdf');
|
|
936
|
-
});
|
|
924
|
+
async createPdf(docDefinition, filename, tableLayouts, fonts) {
|
|
925
|
+
if (!__classPrivateFieldGet(this, _MedplumClient_createPdf, "f")) {
|
|
926
|
+
throw new Error('PDF creation not enabled');
|
|
927
|
+
}
|
|
928
|
+
const blob = await __classPrivateFieldGet(this, _MedplumClient_createPdf, "f").call(this, docDefinition, tableLayouts, fonts);
|
|
929
|
+
return this.createBinary(blob, filename, 'application/pdf');
|
|
937
930
|
}
|
|
938
931
|
/**
|
|
939
932
|
* Creates a FHIR `Communication` resource with the provided data content.
|
|
@@ -995,20 +988,18 @@ class MedplumClient extends EventTarget {
|
|
|
995
988
|
* @param resource The FHIR resource to update.
|
|
996
989
|
* @returns The result of the update operation.
|
|
997
990
|
*/
|
|
998
|
-
updateResource(resource) {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
return result !== null && result !== void 0 ? result : resource;
|
|
1011
|
-
});
|
|
991
|
+
async updateResource(resource) {
|
|
992
|
+
if (!resource.resourceType) {
|
|
993
|
+
throw new Error('Missing resourceType');
|
|
994
|
+
}
|
|
995
|
+
if (!resource.id) {
|
|
996
|
+
throw new Error('Missing id');
|
|
997
|
+
}
|
|
998
|
+
this.invalidateSearches(resource.resourceType);
|
|
999
|
+
const result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
|
|
1000
|
+
// On 304 not modified, result will be undefined
|
|
1001
|
+
// Return the user input instead
|
|
1002
|
+
return result ?? resource;
|
|
1012
1003
|
}
|
|
1013
1004
|
/**
|
|
1014
1005
|
* Updates a FHIR resource using JSONPatch operations.
|
|
@@ -1243,18 +1234,14 @@ class MedplumClient extends EventTarget {
|
|
|
1243
1234
|
/**
|
|
1244
1235
|
* @category Authentication
|
|
1245
1236
|
*/
|
|
1246
|
-
setActiveLogin(login) {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
__classPrivateFieldGet(this, _MedplumClient_requestCache, "f").clear();
|
|
1255
|
-
__classPrivateFieldSet(this, _MedplumClient_refreshPromise, undefined, "f");
|
|
1256
|
-
yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
|
|
1257
|
-
});
|
|
1237
|
+
async setActiveLogin(login) {
|
|
1238
|
+
this.clearActiveLogin();
|
|
1239
|
+
__classPrivateFieldSet(this, _MedplumClient_accessToken, login.accessToken, "f");
|
|
1240
|
+
__classPrivateFieldSet(this, _MedplumClient_refreshToken, login.refreshToken, "f");
|
|
1241
|
+
__classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('activeLogin', login);
|
|
1242
|
+
__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addLogin).call(this, login);
|
|
1243
|
+
__classPrivateFieldSet(this, _MedplumClient_refreshPromise, undefined, "f");
|
|
1244
|
+
await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
|
|
1258
1245
|
}
|
|
1259
1246
|
/**
|
|
1260
1247
|
* @category Authentication
|
|
@@ -1275,8 +1262,7 @@ class MedplumClient extends EventTarget {
|
|
|
1275
1262
|
* @category Authentication
|
|
1276
1263
|
*/
|
|
1277
1264
|
getLogins() {
|
|
1278
|
-
|
|
1279
|
-
return (_a = __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('logins')) !== null && _a !== void 0 ? _a : [];
|
|
1265
|
+
return __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('logins') ?? [];
|
|
1280
1266
|
}
|
|
1281
1267
|
/**
|
|
1282
1268
|
* @category Authentication
|
|
@@ -1293,13 +1279,11 @@ class MedplumClient extends EventTarget {
|
|
|
1293
1279
|
/**
|
|
1294
1280
|
* @category User Profile
|
|
1295
1281
|
*/
|
|
1296
|
-
getProfileAsync() {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
return this.getProfile();
|
|
1302
|
-
});
|
|
1282
|
+
async getProfileAsync() {
|
|
1283
|
+
if (__classPrivateFieldGet(this, _MedplumClient_profilePromise, "f")) {
|
|
1284
|
+
await __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
|
|
1285
|
+
}
|
|
1286
|
+
return this.getProfile();
|
|
1303
1287
|
}
|
|
1304
1288
|
/**
|
|
1305
1289
|
* @category User Profile
|
|
@@ -1314,30 +1298,27 @@ class MedplumClient extends EventTarget {
|
|
|
1314
1298
|
* @param url The URL to request.
|
|
1315
1299
|
* @returns Promise to the response body as a blob.
|
|
1316
1300
|
*/
|
|
1317
|
-
download(url, options = {}) {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
return response.blob();
|
|
1325
|
-
});
|
|
1301
|
+
async download(url, options = {}) {
|
|
1302
|
+
if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
|
|
1303
|
+
await __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
|
|
1304
|
+
}
|
|
1305
|
+
__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addFetchOptionsDefaults).call(this, options);
|
|
1306
|
+
const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url.toString(), options);
|
|
1307
|
+
return response.blob();
|
|
1326
1308
|
}
|
|
1327
1309
|
/**
|
|
1328
1310
|
* Starts a new PKCE flow.
|
|
1329
1311
|
* These PKCE values are stateful, and must survive redirects and page refreshes.
|
|
1330
1312
|
*/
|
|
1331
|
-
startPkce() {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
});
|
|
1313
|
+
async startPkce() {
|
|
1314
|
+
const pkceState = getRandomString();
|
|
1315
|
+
sessionStorage.setItem('pkceState', pkceState);
|
|
1316
|
+
const codeVerifier = getRandomString();
|
|
1317
|
+
sessionStorage.setItem('codeVerifier', codeVerifier);
|
|
1318
|
+
const arrayHash = await encryptSHA256(codeVerifier);
|
|
1319
|
+
const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
1320
|
+
sessionStorage.setItem('codeChallenge', codeChallenge);
|
|
1321
|
+
return { codeChallengeMethod: 'S256', codeChallenge };
|
|
1341
1322
|
}
|
|
1342
1323
|
/**
|
|
1343
1324
|
* Processes an OAuth authorization code.
|
|
@@ -1364,39 +1345,35 @@ class MedplumClient extends EventTarget {
|
|
|
1364
1345
|
* @param clientSecret The client secret.
|
|
1365
1346
|
* @returns Promise that resolves to the client profile.
|
|
1366
1347
|
*/
|
|
1367
|
-
startClientLogin(clientId, clientSecret) {
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
|
|
1376
|
-
});
|
|
1348
|
+
async startClientLogin(clientId, clientSecret) {
|
|
1349
|
+
__classPrivateFieldSet(this, _MedplumClient_clientId, clientId, "f");
|
|
1350
|
+
__classPrivateFieldSet(this, _MedplumClient_clientSecret, clientSecret, "f");
|
|
1351
|
+
const formBody = new URLSearchParams();
|
|
1352
|
+
formBody.set('grant_type', 'client_credentials');
|
|
1353
|
+
formBody.set('client_id', clientId);
|
|
1354
|
+
formBody.set('client_secret', clientSecret);
|
|
1355
|
+
return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
|
|
1377
1356
|
}
|
|
1378
1357
|
}
|
|
1379
1358
|
_MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(), _MedplumClient_storage = new WeakMap(), _MedplumClient_requestCache = new WeakMap(), _MedplumClient_cacheTime = new WeakMap(), _MedplumClient_baseUrl = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_clientSecret = new WeakMap(), _MedplumClient_accessToken = new WeakMap(), _MedplumClient_refreshToken = new WeakMap(), _MedplumClient_refreshPromise = new WeakMap(), _MedplumClient_profilePromise = new WeakMap(), _MedplumClient_profile = new WeakMap(), _MedplumClient_config = new WeakMap(), _MedplumClient_instances = new WeakSet(), _MedplumClient_addLogin = function _MedplumClient_addLogin(newLogin) {
|
|
1380
|
-
const logins = this.getLogins().filter((login) =>
|
|
1359
|
+
const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
|
|
1381
1360
|
logins.push(newLogin);
|
|
1382
1361
|
__classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
|
|
1383
|
-
}, _MedplumClient_refreshProfile = function _MedplumClient_refreshProfile() {
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
return __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
|
|
1397
|
-
});
|
|
1362
|
+
}, _MedplumClient_refreshProfile = async function _MedplumClient_refreshProfile() {
|
|
1363
|
+
__classPrivateFieldSet(this, _MedplumClient_profilePromise, new Promise((resolve, reject) => {
|
|
1364
|
+
this.get('auth/me')
|
|
1365
|
+
.then((result) => {
|
|
1366
|
+
__classPrivateFieldSet(this, _MedplumClient_profilePromise, undefined, "f");
|
|
1367
|
+
__classPrivateFieldSet(this, _MedplumClient_profile, result.profile, "f");
|
|
1368
|
+
__classPrivateFieldSet(this, _MedplumClient_config, result.config, "f");
|
|
1369
|
+
this.dispatchEvent({ type: 'change' });
|
|
1370
|
+
resolve(__classPrivateFieldGet(this, _MedplumClient_profile, "f"));
|
|
1371
|
+
})
|
|
1372
|
+
.catch(reject);
|
|
1373
|
+
}), "f");
|
|
1374
|
+
return __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
|
|
1398
1375
|
}, _MedplumClient_getCacheEntry = function _MedplumClient_getCacheEntry(key, options) {
|
|
1399
|
-
if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") <= 0 ||
|
|
1376
|
+
if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") <= 0 || options?.cache === 'no-cache' || options?.cache === 'reload') {
|
|
1400
1377
|
return undefined;
|
|
1401
1378
|
}
|
|
1402
1379
|
const entry = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(key);
|
|
@@ -1408,31 +1385,37 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(),
|
|
|
1408
1385
|
if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") > 0) {
|
|
1409
1386
|
__classPrivateFieldGet(this, _MedplumClient_requestCache, "f").set(key, { requestTime: Date.now(), value });
|
|
1410
1387
|
}
|
|
1411
|
-
}, _MedplumClient_request =
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1388
|
+
}, _MedplumClient_request =
|
|
1389
|
+
/**
|
|
1390
|
+
* Makes an HTTP request.
|
|
1391
|
+
* @param {string} method
|
|
1392
|
+
* @param {string} url
|
|
1393
|
+
* @param {string=} contentType
|
|
1394
|
+
* @param {Object=} body
|
|
1395
|
+
*/
|
|
1396
|
+
async function _MedplumClient_request(method, url, options = {}) {
|
|
1397
|
+
if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
|
|
1398
|
+
await __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
|
|
1399
|
+
}
|
|
1400
|
+
if (!url.startsWith('http')) {
|
|
1401
|
+
url = __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + url;
|
|
1402
|
+
}
|
|
1403
|
+
options.method = method;
|
|
1404
|
+
__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addFetchOptionsDefaults).call(this, options);
|
|
1405
|
+
const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options);
|
|
1406
|
+
if (response.status === 401) {
|
|
1407
|
+
// Refresh and try again
|
|
1408
|
+
return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_handleUnauthenticated).call(this, method, url, options);
|
|
1409
|
+
}
|
|
1410
|
+
if (response.status === 204 || response.status === 304) {
|
|
1411
|
+
// No content or change
|
|
1412
|
+
return undefined;
|
|
1413
|
+
}
|
|
1414
|
+
const obj = await response.json();
|
|
1415
|
+
if (response.status >= 400) {
|
|
1416
|
+
throw obj;
|
|
1417
|
+
}
|
|
1418
|
+
return obj;
|
|
1436
1419
|
}, _MedplumClient_addFetchOptionsDefaults = function _MedplumClient_addFetchOptionsDefaults(options) {
|
|
1437
1420
|
if (!options.headers) {
|
|
1438
1421
|
options.headers = {};
|
|
@@ -1471,23 +1454,28 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(),
|
|
|
1471
1454
|
if (__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refresh).call(this)) {
|
|
1472
1455
|
return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, method, url, options);
|
|
1473
1456
|
}
|
|
1474
|
-
this.
|
|
1457
|
+
this.clearActiveLogin();
|
|
1475
1458
|
if (__classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f")) {
|
|
1476
1459
|
__classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f").call(this);
|
|
1477
1460
|
}
|
|
1478
1461
|
return Promise.reject(new Error('Unauthenticated'));
|
|
1479
|
-
}, _MedplumClient_requestAuthorization =
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1462
|
+
}, _MedplumClient_requestAuthorization =
|
|
1463
|
+
/**
|
|
1464
|
+
* Redirects the user to the login screen for authorization.
|
|
1465
|
+
* Clears all auth state including local storage and session storage.
|
|
1466
|
+
* See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
|
|
1467
|
+
*/
|
|
1468
|
+
async function _MedplumClient_requestAuthorization(loginParams) {
|
|
1469
|
+
const loginRequest = await this.ensureCodeChallenge(loginParams || {});
|
|
1470
|
+
const url = new URL(__classPrivateFieldGet(this, _MedplumClient_authorizeUrl, "f"));
|
|
1471
|
+
url.searchParams.set('response_type', 'code');
|
|
1472
|
+
url.searchParams.set('state', sessionStorage.getItem('pkceState'));
|
|
1473
|
+
url.searchParams.set('client_id', loginRequest.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
|
|
1474
|
+
url.searchParams.set('redirect_uri', loginRequest.redirectUri || getBaseUrl());
|
|
1475
|
+
url.searchParams.set('code_challenge_method', loginRequest.codeChallengeMethod);
|
|
1476
|
+
url.searchParams.set('code_challenge', loginRequest.codeChallenge);
|
|
1477
|
+
url.searchParams.set('scope', loginRequest.scope || 'openid profile');
|
|
1478
|
+
window.location.assign(url.toString());
|
|
1491
1479
|
}, _MedplumClient_refresh = function _MedplumClient_refresh() {
|
|
1492
1480
|
if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
|
|
1493
1481
|
return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
|
|
@@ -1505,43 +1493,51 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(),
|
|
|
1505
1493
|
return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
|
|
1506
1494
|
}
|
|
1507
1495
|
return undefined;
|
|
1508
|
-
}, _MedplumClient_fetchTokens =
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
return response.json();
|
|
1521
|
-
})
|
|
1522
|
-
.then((tokens) => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens))
|
|
1523
|
-
.then(() => this.getProfile());
|
|
1496
|
+
}, _MedplumClient_fetchTokens =
|
|
1497
|
+
/**
|
|
1498
|
+
* Makes a POST request to the tokens endpoint.
|
|
1499
|
+
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1500
|
+
* @param formBody Token parameters in URL encoded format.
|
|
1501
|
+
*/
|
|
1502
|
+
async function _MedplumClient_fetchTokens(formBody) {
|
|
1503
|
+
const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f"), {
|
|
1504
|
+
method: 'POST',
|
|
1505
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1506
|
+
body: formBody,
|
|
1507
|
+
credentials: 'include',
|
|
1524
1508
|
});
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1509
|
+
if (!response.ok) {
|
|
1510
|
+
this.clearActiveLogin();
|
|
1511
|
+
throw new Error('Failed to fetch tokens');
|
|
1512
|
+
}
|
|
1513
|
+
const tokens = await response.json();
|
|
1514
|
+
await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens);
|
|
1515
|
+
return this.getProfile();
|
|
1516
|
+
}, _MedplumClient_verifyTokens =
|
|
1517
|
+
/**
|
|
1518
|
+
* Verifies the tokens received from the auth server.
|
|
1519
|
+
* Validates the JWT against the JWKS.
|
|
1520
|
+
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
|
1521
|
+
* @param tokens
|
|
1522
|
+
*/
|
|
1523
|
+
async function _MedplumClient_verifyTokens(tokens) {
|
|
1524
|
+
const token = tokens.access_token;
|
|
1525
|
+
// Verify token has not expired
|
|
1526
|
+
const tokenPayload = parseJWTPayload(token);
|
|
1527
|
+
if (Date.now() >= tokenPayload.exp * 1000) {
|
|
1528
|
+
this.clearActiveLogin();
|
|
1529
|
+
throw new Error('Token expired');
|
|
1530
|
+
}
|
|
1531
|
+
// Verify app_client_id
|
|
1532
|
+
if (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") && tokenPayload.client_id !== __classPrivateFieldGet(this, _MedplumClient_clientId, "f")) {
|
|
1533
|
+
this.clearActiveLogin();
|
|
1534
|
+
throw new Error('Token was not issued for this audience');
|
|
1535
|
+
}
|
|
1536
|
+
return this.setActiveLogin({
|
|
1537
|
+
accessToken: token,
|
|
1538
|
+
refreshToken: tokens.refresh_token,
|
|
1539
|
+
project: tokens.project,
|
|
1540
|
+
profile: tokens.profile,
|
|
1545
1541
|
});
|
|
1546
1542
|
}, _MedplumClient_setupStorageListener = function _MedplumClient_setupStorageListener() {
|
|
1547
1543
|
try {
|
|
@@ -1573,4 +1569,4 @@ function ensureTrailingSlash(url) {
|
|
|
1573
1569
|
}
|
|
1574
1570
|
|
|
1575
1571
|
export { MEDPLUM_VERSION, MedplumClient };
|
|
1576
|
-
//# sourceMappingURL=client.
|
|
1572
|
+
//# sourceMappingURL=client.mjs.map
|