@medplum/core 1.0.6 → 2.0.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"base-schema.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"base-schema.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -71,6 +71,14 @@ export interface MedplumClientOptions {
71
71
  * See: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache
72
72
  */
73
73
  cacheTime?: number;
74
+ /**
75
+ * The length of time in milliseconds to delay requests for auto batching.
76
+ *
77
+ * Auto batching attempts to group multiple requests together into a single batch request.
78
+ *
79
+ * Default value is 0, which disables auto batching.
80
+ */
81
+ autoBatchTime?: number;
74
82
  /**
75
83
  * Fetch implementation.
76
84
  *
@@ -146,6 +154,7 @@ export interface BaseLoginRequest {
146
154
  readonly codeChallengeMethod?: string;
147
155
  readonly googleClientId?: string;
148
156
  readonly launch?: string;
157
+ readonly redirectUri?: string;
149
158
  }
150
159
  export interface EmailPasswordLoginRequest extends BaseLoginRequest {
151
160
  readonly email: string;
@@ -338,6 +347,12 @@ export declare class MedplumClient extends EventTarget {
338
347
  * @category Authentication
339
348
  */
340
349
  clear(): void;
350
+ /**
351
+ * Clears the active login from local storage.
352
+ * Does not clear all local storage (such as other logins).
353
+ * @category Authentication
354
+ */
355
+ clearActiveLogin(): void;
341
356
  /**
342
357
  * Invalidates any cached values or cached requests for the given URL.
343
358
  * @category Caching
@@ -467,10 +482,15 @@ export declare class MedplumClient extends EventTarget {
467
482
  * @returns Promise to the authentication response.
468
483
  */
469
484
  startGoogleLogin(loginRequest: GoogleLoginRequest): Promise<LoginAuthenticationResponse>;
470
- getCodeChallenge(loginRequest: BaseLoginRequest): {
471
- codeChallenge?: string;
472
- codeChallengeMethod?: string;
473
- };
485
+ /**
486
+ * Returns the PKCE code challenge and method.
487
+ * If the login request already includes a code challenge, it is returned.
488
+ * Otherwise, a new PKCE code challenge is generated.
489
+ * @category Authentication
490
+ * @param loginRequest The original login request.
491
+ * @returns The PKCE code challenge and method.
492
+ */
493
+ ensureCodeChallenge<T extends BaseLoginRequest>(loginRequest: T): Promise<T>;
474
494
  /**
475
495
  * Signs out locally.
476
496
  * Does not invalidate tokens with the server.
@@ -482,14 +502,23 @@ export declare class MedplumClient extends EventTarget {
482
502
  * Returns true if the user is signed in.
483
503
  * This may result in navigating away to the sign in page.
484
504
  * @category Authentication
505
+ * @param loginParams Optional login parameters.
485
506
  */
486
- signInWithRedirect(): Promise<ProfileResource | void>;
507
+ signInWithRedirect(loginParams?: Partial<BaseLoginRequest>): Promise<ProfileResource | void>;
487
508
  /**
488
509
  * Tries to sign out the user.
489
510
  * See: https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html
490
511
  * @category Authentication
491
512
  */
492
513
  signOutWithRedirect(): void;
514
+ /**
515
+ * Initiates sign in with an external identity provider.
516
+ * @param authorizeUrl The external authorization URL.
517
+ * @param clientId The external client ID.
518
+ * @param redirectUri The external identity provider redirect URI.
519
+ * @param baseLogin The Medplum login request.
520
+ */
521
+ signInWithExternalAuth(authorizeUrl: string, clientId: string, redirectUri: string, baseLogin: BaseLoginRequest): Promise<void>;
493
522
  /**
494
523
  * Builds a FHIR URL from a collection of URL path components.
495
524
  * For example, `buildUrl('/Patient', '123')` returns `fhir/R4/Patient/123`.
@@ -1154,7 +1183,10 @@ export declare class MedplumClient extends EventTarget {
1154
1183
  * Starts a new PKCE flow.
1155
1184
  * These PKCE values are stateful, and must survive redirects and page refreshes.
1156
1185
  */
1157
- startPkce(): Promise<void>;
1186
+ startPkce(): Promise<{
1187
+ codeChallengeMethod: string;
1188
+ codeChallenge: string;
1189
+ }>;
1158
1190
  /**
1159
1191
  * Processes an OAuth authorization code.
1160
1192
  * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
@@ -10,8 +10,8 @@ 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
- 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 = "1.0.6-5860113c";
13
+ var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_autoBatchTime, _MedplumClient_autoBatchQueue, _MedplumClient_clientId, _MedplumClient_clientSecret, _MedplumClient_autoBatchTimerId, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_request, _MedplumClient_executeAutoBatch, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
14
+ const MEDPLUM_VERSION = "2.0.1-89a5b1c5";
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
@@ -80,12 +80,16 @@ class MedplumClient extends EventTarget {
80
80
  _MedplumClient_requestCache.set(this, void 0);
81
81
  _MedplumClient_cacheTime.set(this, void 0);
82
82
  _MedplumClient_baseUrl.set(this, void 0);
83
+ _MedplumClient_fhirBaseUrl.set(this, void 0);
83
84
  _MedplumClient_authorizeUrl.set(this, void 0);
84
85
  _MedplumClient_tokenUrl.set(this, void 0);
85
86
  _MedplumClient_logoutUrl.set(this, void 0);
86
87
  _MedplumClient_onUnauthenticated.set(this, void 0);
88
+ _MedplumClient_autoBatchTime.set(this, void 0);
89
+ _MedplumClient_autoBatchQueue.set(this, void 0);
87
90
  _MedplumClient_clientId.set(this, void 0);
88
91
  _MedplumClient_clientSecret.set(this, void 0);
92
+ _MedplumClient_autoBatchTimerId.set(this, void 0);
89
93
  _MedplumClient_accessToken.set(this, void 0);
90
94
  _MedplumClient_refreshToken.set(this, void 0);
91
95
  _MedplumClient_refreshPromise.set(this, void 0);
@@ -103,11 +107,14 @@ class MedplumClient extends EventTarget {
103
107
  __classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
104
108
  __classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
105
109
  __classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
110
+ __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'fhir/R4/', "f");
106
111
  __classPrivateFieldSet(this, _MedplumClient_clientId, options?.clientId || '', "f");
107
112
  __classPrivateFieldSet(this, _MedplumClient_authorizeUrl, options?.authorizeUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
108
113
  __classPrivateFieldSet(this, _MedplumClient_tokenUrl, options?.tokenUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
109
114
  __classPrivateFieldSet(this, _MedplumClient_logoutUrl, options?.logoutUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/logout', "f");
110
115
  __classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options?.onUnauthenticated, "f");
116
+ __classPrivateFieldSet(this, _MedplumClient_autoBatchTime, options?.autoBatchTime ?? 0, "f");
117
+ __classPrivateFieldSet(this, _MedplumClient_autoBatchQueue, [], "f");
111
118
  const activeLogin = this.getActiveLogin();
112
119
  if (activeLogin) {
113
120
  __classPrivateFieldSet(this, _MedplumClient_accessToken, activeLogin.accessToken, "f");
@@ -132,6 +139,15 @@ class MedplumClient extends EventTarget {
132
139
  */
133
140
  clear() {
134
141
  __classPrivateFieldGet(this, _MedplumClient_storage, "f").clear();
142
+ this.clearActiveLogin();
143
+ }
144
+ /**
145
+ * Clears the active login from local storage.
146
+ * Does not clear all local storage (such as other logins).
147
+ * @category Authentication
148
+ */
149
+ clearActiveLogin() {
150
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('activeLogin', undefined);
135
151
  __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").clear();
136
152
  __classPrivateFieldSet(this, _MedplumClient_accessToken, undefined, "f");
137
153
  __classPrivateFieldSet(this, _MedplumClient_refreshToken, undefined, "f");
@@ -179,9 +195,27 @@ class MedplumClient extends EventTarget {
179
195
  if (cached) {
180
196
  return cached.value;
181
197
  }
182
- const promise = new ReadablePromise(__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'GET', url, options));
183
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, url, promise);
184
- return promise;
198
+ let promise;
199
+ if (url.startsWith(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f")) && __classPrivateFieldGet(this, _MedplumClient_autoBatchTime, "f") > 0) {
200
+ promise = new Promise((resolve, reject) => {
201
+ __classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f").push({
202
+ method: 'GET',
203
+ url: url.replace(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f"), ''),
204
+ options,
205
+ resolve,
206
+ reject,
207
+ });
208
+ if (!__classPrivateFieldGet(this, _MedplumClient_autoBatchTimerId, "f")) {
209
+ __classPrivateFieldSet(this, _MedplumClient_autoBatchTimerId, setTimeout(() => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_executeAutoBatch).call(this), __classPrivateFieldGet(this, _MedplumClient_autoBatchTime, "f")), "f");
210
+ }
211
+ });
212
+ }
213
+ else {
214
+ promise = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'GET', url, options);
215
+ }
216
+ const readablePromise = new ReadablePromise(promise);
217
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, url, readablePromise);
218
+ return readablePromise;
185
219
  }
186
220
  /**
187
221
  * Makes an HTTP POST request to the specified URL.
@@ -283,11 +317,11 @@ class MedplumClient extends EventTarget {
283
317
  * @returns Promise to the authentication response.
284
318
  */
285
319
  async startNewUser(newUserRequest) {
286
- await this.startPkce();
320
+ const { codeChallengeMethod, codeChallenge } = await this.startPkce();
287
321
  return this.post('auth/newuser', {
288
322
  ...newUserRequest,
289
- codeChallengeMethod: 'S256',
290
- codeChallenge: sessionStorage.getItem('codeChallenge'),
323
+ codeChallengeMethod,
324
+ codeChallenge,
291
325
  });
292
326
  }
293
327
  /**
@@ -319,13 +353,10 @@ class MedplumClient extends EventTarget {
319
353
  * @returns Promise to the authentication response.
320
354
  */
321
355
  async startLogin(loginRequest) {
322
- const { codeChallenge, codeChallengeMethod } = this.getCodeChallenge(loginRequest);
323
356
  return this.post('auth/login', {
324
- ...loginRequest,
357
+ ...(await this.ensureCodeChallenge(loginRequest)),
325
358
  clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
326
359
  scope: loginRequest.scope,
327
- codeChallengeMethod,
328
- codeChallenge,
329
360
  });
330
361
  }
331
362
  /**
@@ -337,30 +368,25 @@ class MedplumClient extends EventTarget {
337
368
  * @returns Promise to the authentication response.
338
369
  */
339
370
  async startGoogleLogin(loginRequest) {
340
- const { codeChallenge, codeChallengeMethod } = this.getCodeChallenge(loginRequest);
341
371
  return this.post('auth/google', {
342
- ...loginRequest,
372
+ ...(await this.ensureCodeChallenge(loginRequest)),
343
373
  clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
344
374
  scope: loginRequest.scope,
345
- codeChallengeMethod,
346
- codeChallenge,
347
375
  });
348
376
  }
349
- getCodeChallenge(loginRequest) {
377
+ /**
378
+ * Returns the PKCE code challenge and method.
379
+ * If the login request already includes a code challenge, it is returned.
380
+ * Otherwise, a new PKCE code challenge is generated.
381
+ * @category Authentication
382
+ * @param loginRequest The original login request.
383
+ * @returns The PKCE code challenge and method.
384
+ */
385
+ async ensureCodeChallenge(loginRequest) {
350
386
  if (loginRequest.codeChallenge) {
351
- return {
352
- codeChallenge: loginRequest.codeChallenge,
353
- codeChallengeMethod: loginRequest.codeChallengeMethod,
354
- };
355
- }
356
- const codeChallenge = sessionStorage.getItem('codeChallenge');
357
- if (codeChallenge) {
358
- return {
359
- codeChallenge,
360
- codeChallengeMethod: 'S256',
361
- };
387
+ return loginRequest;
362
388
  }
363
- return {};
389
+ return { ...loginRequest, ...(await this.startPkce()) };
364
390
  }
365
391
  /**
366
392
  * Signs out locally.
@@ -375,12 +401,13 @@ class MedplumClient extends EventTarget {
375
401
  * Returns true if the user is signed in.
376
402
  * This may result in navigating away to the sign in page.
377
403
  * @category Authentication
404
+ * @param loginParams Optional login parameters.
378
405
  */
379
- async signInWithRedirect() {
406
+ async signInWithRedirect(loginParams) {
380
407
  const urlParams = new URLSearchParams(window.location.search);
381
408
  const code = urlParams.get('code');
382
409
  if (!code) {
383
- await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_requestAuthorization).call(this);
410
+ await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_requestAuthorization).call(this, loginParams);
384
411
  return undefined;
385
412
  }
386
413
  else {
@@ -395,6 +422,23 @@ class MedplumClient extends EventTarget {
395
422
  signOutWithRedirect() {
396
423
  window.location.assign(__classPrivateFieldGet(this, _MedplumClient_logoutUrl, "f"));
397
424
  }
425
+ /**
426
+ * Initiates sign in with an external identity provider.
427
+ * @param authorizeUrl The external authorization URL.
428
+ * @param clientId The external client ID.
429
+ * @param redirectUri The external identity provider redirect URI.
430
+ * @param baseLogin The Medplum login request.
431
+ */
432
+ async signInWithExternalAuth(authorizeUrl, clientId, redirectUri, baseLogin) {
433
+ const loginRequest = await this.ensureCodeChallenge(baseLogin);
434
+ const url = new URL(authorizeUrl);
435
+ url.searchParams.set('response_type', 'code');
436
+ url.searchParams.set('client_id', clientId);
437
+ url.searchParams.set('redirect_uri', redirectUri);
438
+ url.searchParams.set('scope', 'openid profile email');
439
+ url.searchParams.set('state', JSON.stringify(loginRequest));
440
+ window.location.assign(url.toString());
441
+ }
398
442
  /**
399
443
  * Builds a FHIR URL from a collection of URL path components.
400
444
  * For example, `buildUrl('/Patient', '123')` returns `fhir/R4/Patient/123`.
@@ -403,7 +447,7 @@ class MedplumClient extends EventTarget {
403
447
  * @returns The well-formed FHIR URL.
404
448
  */
405
449
  fhirUrl(...path) {
406
- return new URL(__classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'fhir/R4/' + path.join('/'));
450
+ return new URL(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + path.join('/'));
407
451
  }
408
452
  /**
409
453
  * Builds a FHIR search URL from a search query or structured query object.
@@ -1233,13 +1277,11 @@ class MedplumClient extends EventTarget {
1233
1277
  * @category Authentication
1234
1278
  */
1235
1279
  async setActiveLogin(login) {
1280
+ this.clearActiveLogin();
1236
1281
  __classPrivateFieldSet(this, _MedplumClient_accessToken, login.accessToken, "f");
1237
1282
  __classPrivateFieldSet(this, _MedplumClient_refreshToken, login.refreshToken, "f");
1238
- __classPrivateFieldSet(this, _MedplumClient_profile, undefined, "f");
1239
- __classPrivateFieldSet(this, _MedplumClient_config, undefined, "f");
1240
1283
  __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('activeLogin', login);
1241
1284
  __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addLogin).call(this, login);
1242
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").clear();
1243
1285
  __classPrivateFieldSet(this, _MedplumClient_refreshPromise, undefined, "f");
1244
1286
  await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
1245
1287
  }
@@ -1318,6 +1360,7 @@ class MedplumClient extends EventTarget {
1318
1360
  const arrayHash = await encryptSHA256(codeVerifier);
1319
1361
  const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
1320
1362
  sessionStorage.setItem('codeChallenge', codeChallenge);
1363
+ return { codeChallengeMethod: 'S256', codeChallenge };
1321
1364
  }
1322
1365
  /**
1323
1366
  * Processes an OAuth authorization code.
@@ -1354,7 +1397,7 @@ class MedplumClient extends EventTarget {
1354
1397
  return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
1355
1398
  }
1356
1399
  }
1357
- _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) {
1400
+ _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_fhirBaseUrl = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = new WeakMap(), _MedplumClient_autoBatchTime = new WeakMap(), _MedplumClient_autoBatchQueue = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_clientSecret = new WeakMap(), _MedplumClient_autoBatchTimerId = 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) {
1358
1401
  const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
1359
1402
  logins.push(newLogin);
1360
1403
  __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
@@ -1415,6 +1458,43 @@ async function _MedplumClient_request(method, url, options = {}) {
1415
1458
  throw obj;
1416
1459
  }
1417
1460
  return obj;
1461
+ }, _MedplumClient_executeAutoBatch =
1462
+ /**
1463
+ * Executes a batch of requests that were automatically batched together.
1464
+ */
1465
+ async function _MedplumClient_executeAutoBatch() {
1466
+ // Get the current queue
1467
+ const entries = [...__classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f")];
1468
+ // Clear the queue
1469
+ __classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f").length = 0;
1470
+ // Clear the timer
1471
+ __classPrivateFieldSet(this, _MedplumClient_autoBatchTimerId, undefined, "f");
1472
+ // If there is only one request in the batch, just execute it
1473
+ if (entries.length === 1) {
1474
+ const entry = entries[0];
1475
+ entry.resolve(await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, entry.method, __classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + entry.url, entry.options));
1476
+ return;
1477
+ }
1478
+ // Build the batch request
1479
+ const batch = {
1480
+ resourceType: 'Bundle',
1481
+ type: 'batch',
1482
+ entry: entries.map((e) => ({
1483
+ request: {
1484
+ method: e.method,
1485
+ url: e.url,
1486
+ },
1487
+ resource: e.options.body ? JSON.parse(e.options.body) : undefined,
1488
+ })),
1489
+ };
1490
+ // Execute the batch request
1491
+ const response = (await this.post('fhir/R4', batch));
1492
+ // Process the response
1493
+ for (let i = 0; i < entries.length; i++) {
1494
+ const entry = entries[i];
1495
+ const responseEntry = response.entry?.[i];
1496
+ entry.resolve(responseEntry?.resource);
1497
+ }
1418
1498
  }, _MedplumClient_addFetchOptionsDefaults = function _MedplumClient_addFetchOptionsDefaults(options) {
1419
1499
  if (!options.headers) {
1420
1500
  options.headers = {};
@@ -1453,7 +1533,7 @@ async function _MedplumClient_request(method, url, options = {}) {
1453
1533
  if (__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refresh).call(this)) {
1454
1534
  return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, method, url, options);
1455
1535
  }
1456
- this.clear();
1536
+ this.clearActiveLogin();
1457
1537
  if (__classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f")) {
1458
1538
  __classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f").call(this);
1459
1539
  }
@@ -1464,15 +1544,16 @@ async function _MedplumClient_request(method, url, options = {}) {
1464
1544
  * Clears all auth state including local storage and session storage.
1465
1545
  * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
1466
1546
  */
1467
- async function _MedplumClient_requestAuthorization() {
1468
- await this.startPkce();
1547
+ async function _MedplumClient_requestAuthorization(loginParams) {
1548
+ const loginRequest = await this.ensureCodeChallenge(loginParams || {});
1469
1549
  const url = new URL(__classPrivateFieldGet(this, _MedplumClient_authorizeUrl, "f"));
1470
1550
  url.searchParams.set('response_type', 'code');
1471
1551
  url.searchParams.set('state', sessionStorage.getItem('pkceState'));
1472
- url.searchParams.set('client_id', __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
1473
- url.searchParams.set('redirect_uri', getBaseUrl());
1474
- url.searchParams.set('code_challenge_method', 'S256');
1475
- url.searchParams.set('code_challenge', sessionStorage.getItem('codeChallenge'));
1552
+ url.searchParams.set('client_id', loginRequest.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
1553
+ url.searchParams.set('redirect_uri', loginRequest.redirectUri || getBaseUrl());
1554
+ url.searchParams.set('code_challenge_method', loginRequest.codeChallengeMethod);
1555
+ url.searchParams.set('code_challenge', loginRequest.codeChallenge);
1556
+ url.searchParams.set('scope', loginRequest.scope || 'openid profile');
1476
1557
  window.location.assign(url.toString());
1477
1558
  }, _MedplumClient_refresh = function _MedplumClient_refresh() {
1478
1559
  if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
@@ -1498,20 +1579,19 @@ async function _MedplumClient_requestAuthorization() {
1498
1579
  * @param formBody Token parameters in URL encoded format.
1499
1580
  */
1500
1581
  async function _MedplumClient_fetchTokens(formBody) {
1501
- return __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f"), {
1582
+ const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f"), {
1502
1583
  method: 'POST',
1503
1584
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1504
1585
  body: formBody,
1505
1586
  credentials: 'include',
1506
- })
1507
- .then((response) => {
1508
- if (!response.ok) {
1509
- throw new Error('Failed to fetch tokens');
1510
- }
1511
- return response.json();
1512
- })
1513
- .then((tokens) => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens))
1514
- .then(() => this.getProfile());
1587
+ });
1588
+ if (!response.ok) {
1589
+ this.clearActiveLogin();
1590
+ throw new Error('Failed to fetch tokens');
1591
+ }
1592
+ const tokens = await response.json();
1593
+ await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens);
1594
+ return this.getProfile();
1515
1595
  }, _MedplumClient_verifyTokens =
1516
1596
  /**
1517
1597
  * Verifies the tokens received from the auth server.
@@ -1524,15 +1604,15 @@ async function _MedplumClient_verifyTokens(tokens) {
1524
1604
  // Verify token has not expired
1525
1605
  const tokenPayload = parseJWTPayload(token);
1526
1606
  if (Date.now() >= tokenPayload.exp * 1000) {
1527
- this.clear();
1607
+ this.clearActiveLogin();
1528
1608
  throw new Error('Token expired');
1529
1609
  }
1530
1610
  // Verify app_client_id
1531
1611
  if (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") && tokenPayload.client_id !== __classPrivateFieldGet(this, _MedplumClient_clientId, "f")) {
1532
- this.clear();
1612
+ this.clearActiveLogin();
1533
1613
  throw new Error('Token was not issued for this audience');
1534
1614
  }
1535
- await this.setActiveLogin({
1615
+ return this.setActiveLogin({
1536
1616
  accessToken: token,
1537
1617
  refreshToken: tokens.refresh_token,
1538
1618
  project: tokens.project,