@medplum/core 2.0.1 → 2.0.3

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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -224,7 +224,7 @@ export interface BotEvent<T = Resource | Hl7Message | string | Record<string, an
224
224
  }
225
225
  /**
226
226
  * JSONPatch patch operation.
227
- * Compatible with fast-json-patch Operation.
227
+ * Compatible with fast-json-patch and rfc6902 Operation.
228
228
  */
229
229
  export interface PatchOperation {
230
230
  readonly op: 'add' | 'remove' | 'replace' | 'copy' | 'move' | 'test';
@@ -496,7 +496,7 @@ export declare class MedplumClient extends EventTarget {
496
496
  * Does not invalidate tokens with the server.
497
497
  * @category Authentication
498
498
  */
499
- signOut(): void;
499
+ signOut(): Promise<void>;
500
500
  /**
501
501
  * Tries to sign in the user.
502
502
  * Returns true if the user is signed in.
@@ -517,8 +517,19 @@ export declare class MedplumClient extends EventTarget {
517
517
  * @param clientId The external client ID.
518
518
  * @param redirectUri The external identity provider redirect URI.
519
519
  * @param baseLogin The Medplum login request.
520
+ * @category Authentication
520
521
  */
521
522
  signInWithExternalAuth(authorizeUrl: string, clientId: string, redirectUri: string, baseLogin: BaseLoginRequest): Promise<void>;
523
+ /**
524
+ * Builds the external identity provider redirect URI.
525
+ * @param authorizeUrl The external authorization URL.
526
+ * @param clientId The external client ID.
527
+ * @param redirectUri The external identity provider redirect URI.
528
+ * @param loginRequest The Medplum login request.
529
+ * @returns The external identity provider redirect URI.
530
+ * @category Authentication
531
+ */
532
+ getExternalAuthRedirectUri(authorizeUrl: string, clientId: string, redirectUri: string, loginRequest: BaseLoginRequest): string;
522
533
  /**
523
534
  * Builds a FHIR URL from a collection of URL path components.
524
535
  * For example, `buildUrl('/Patient', '123')` returns `fhir/R4/Patient/123`.
@@ -3,6 +3,7 @@ import { LRUCache } from './cache.mjs';
3
3
  import { getRandomString, encryptSHA256 } from './crypto.mjs';
4
4
  import { EventTarget } from './eventtarget.mjs';
5
5
  import { parseJWTPayload } from './jwt.mjs';
6
+ import { isOk } from './outcomes.mjs';
6
7
  import { ReadablePromise } from './readablepromise.mjs';
7
8
  import { ClientStorage } from './storage.mjs';
8
9
  import { globalSchema, indexStructureDefinition, indexSearchParameter } from './types.mjs';
@@ -10,14 +11,15 @@ import { createReference, arrayBufferToBase64 } from './utils.mjs';
10
11
 
11
12
  // PKCE auth based on:
12
13
  // 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_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";
14
+ 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_cacheResource, _MedplumClient_deleteCacheEntry, _MedplumClient_request, _MedplumClient_fetchWithRetry, _MedplumClient_executeAutoBatch, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
15
+ const MEDPLUM_VERSION = "2.0.3-e39c01ab";
15
16
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
16
17
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
17
18
  const DEFAULT_CACHE_TIME = 60000; // 60 seconds
18
19
  const JSON_CONTENT_TYPE = 'application/json';
19
20
  const FHIR_CONTENT_TYPE = 'application/fhir+json';
20
21
  const PATCH_CONTENT_TYPE = 'application/json-patch+json';
22
+ const system = { resourceType: 'Device', id: 'system', deviceName: [{ name: 'System' }] };
21
23
  /**
22
24
  * The MedplumClient class provides a client for the Medplum FHIR server.
23
25
  *
@@ -101,7 +103,7 @@ class MedplumClient extends EventTarget {
101
103
  throw new Error('Base URL must start with http or https');
102
104
  }
103
105
  }
104
- __classPrivateFieldSet(this, _MedplumClient_fetch, options?.fetch || window.fetch.bind(window), "f");
106
+ __classPrivateFieldSet(this, _MedplumClient_fetch, options?.fetch || getDefaultFetch(), "f");
105
107
  __classPrivateFieldSet(this, _MedplumClient_createPdf, options?.createPdf, "f");
106
108
  __classPrivateFieldSet(this, _MedplumClient_storage, new ClientStorage(), "f");
107
109
  __classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
@@ -393,7 +395,8 @@ class MedplumClient extends EventTarget {
393
395
  * Does not invalidate tokens with the server.
394
396
  * @category Authentication
395
397
  */
396
- signOut() {
398
+ async signOut() {
399
+ await this.post(__classPrivateFieldGet(this, _MedplumClient_logoutUrl, "f"), {});
397
400
  this.clear();
398
401
  }
399
402
  /**
@@ -428,16 +431,29 @@ class MedplumClient extends EventTarget {
428
431
  * @param clientId The external client ID.
429
432
  * @param redirectUri The external identity provider redirect URI.
430
433
  * @param baseLogin The Medplum login request.
434
+ * @category Authentication
431
435
  */
432
436
  async signInWithExternalAuth(authorizeUrl, clientId, redirectUri, baseLogin) {
433
437
  const loginRequest = await this.ensureCodeChallenge(baseLogin);
438
+ window.location.assign(this.getExternalAuthRedirectUri(authorizeUrl, clientId, redirectUri, loginRequest));
439
+ }
440
+ /**
441
+ * Builds the external identity provider redirect URI.
442
+ * @param authorizeUrl The external authorization URL.
443
+ * @param clientId The external client ID.
444
+ * @param redirectUri The external identity provider redirect URI.
445
+ * @param loginRequest The Medplum login request.
446
+ * @returns The external identity provider redirect URI.
447
+ * @category Authentication
448
+ */
449
+ getExternalAuthRedirectUri(authorizeUrl, clientId, redirectUri, loginRequest) {
434
450
  const url = new URL(authorizeUrl);
435
451
  url.searchParams.set('response_type', 'code');
436
452
  url.searchParams.set('client_id', clientId);
437
453
  url.searchParams.set('redirect_uri', redirectUri);
438
454
  url.searchParams.set('scope', 'openid profile email');
439
455
  url.searchParams.set('state', JSON.stringify(loginRequest));
440
- window.location.assign(url.toString());
456
+ return url.toString();
441
457
  }
442
458
  /**
443
459
  * Builds a FHIR URL from a collection of URL path components.
@@ -512,7 +528,23 @@ class MedplumClient extends EventTarget {
512
528
  * @returns Promise to the search result bundle.
513
529
  */
514
530
  search(resourceType, query, options = {}) {
515
- return this.get(this.fhirSearchUrl(resourceType, query), options);
531
+ const url = this.fhirSearchUrl(resourceType, query);
532
+ const cacheKey = url.toString() + '-search';
533
+ const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, options);
534
+ if (cached) {
535
+ return cached.value;
536
+ }
537
+ const promise = new ReadablePromise((async () => {
538
+ const bundle = await this.get(url, options);
539
+ if (bundle.entry) {
540
+ for (const entry of bundle.entry) {
541
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_cacheResource).call(this, entry.resource);
542
+ }
543
+ }
544
+ return bundle;
545
+ })());
546
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
547
+ return promise;
516
548
  }
517
549
  /**
518
550
  * Sends a FHIR search request for a single resource.
@@ -621,6 +653,9 @@ class MedplumClient extends EventTarget {
621
653
  if (!refString) {
622
654
  return undefined;
623
655
  }
656
+ if (refString === 'system') {
657
+ return system;
658
+ }
624
659
  const [resourceType, id] = refString.split('/');
625
660
  if (!resourceType || !id) {
626
661
  return undefined;
@@ -673,6 +708,9 @@ class MedplumClient extends EventTarget {
673
708
  if (!refString) {
674
709
  return new ReadablePromise(Promise.reject(new Error('Missing reference')));
675
710
  }
711
+ if (refString === 'system') {
712
+ return new ReadablePromise(Promise.resolve(system));
713
+ }
676
714
  const [resourceType, id] = refString.split('/');
677
715
  if (!resourceType || !id) {
678
716
  return new ReadablePromise(Promise.reject(new Error('Invalid reference')));
@@ -697,11 +735,17 @@ class MedplumClient extends EventTarget {
697
735
  * @param resourceType The FHIR resource type.
698
736
  * @returns Promise to a schema with the requested resource type.
699
737
  */
700
- async requestSchema(resourceType) {
738
+ requestSchema(resourceType) {
701
739
  if (resourceType in globalSchema.types) {
702
- return globalSchema;
740
+ return Promise.resolve(globalSchema);
703
741
  }
704
- const query = `{
742
+ const cacheKey = resourceType + '-requestSchema';
743
+ const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, undefined);
744
+ if (cached) {
745
+ return cached.value;
746
+ }
747
+ const promise = new ReadablePromise((async () => {
748
+ const query = `{
705
749
  StructureDefinitionList(name: "${resourceType}") {
706
750
  name,
707
751
  description,
@@ -730,14 +774,17 @@ class MedplumClient extends EventTarget {
730
774
  target
731
775
  }
732
776
  }`.replace(/\s+/g, ' ');
733
- const response = (await this.graphql(query));
734
- for (const structureDefinition of response.data.StructureDefinitionList) {
735
- indexStructureDefinition(structureDefinition);
736
- }
737
- for (const searchParameter of response.data.SearchParameterList) {
738
- indexSearchParameter(searchParameter);
739
- }
740
- return globalSchema;
777
+ const response = (await this.graphql(query));
778
+ for (const structureDefinition of response.data.StructureDefinitionList) {
779
+ indexStructureDefinition(structureDefinition);
780
+ }
781
+ for (const searchParameter of response.data.SearchParameterList) {
782
+ indexSearchParameter(searchParameter);
783
+ }
784
+ return globalSchema;
785
+ })());
786
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
787
+ return promise;
741
788
  }
742
789
  /**
743
790
  * Reads resource history by resource type and ID.
@@ -1038,10 +1085,15 @@ class MedplumClient extends EventTarget {
1038
1085
  throw new Error('Missing id');
1039
1086
  }
1040
1087
  this.invalidateSearches(resource.resourceType);
1041
- const result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
1042
- // On 304 not modified, result will be undefined
1043
- // Return the user input instead
1044
- return result ?? resource;
1088
+ let result = await this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
1089
+ if (!result) {
1090
+ // On 304 not modified, result will be undefined
1091
+ // Return the user input instead
1092
+ // return result ?? resource;
1093
+ result = resource;
1094
+ }
1095
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_cacheResource).call(this, result);
1096
+ return result;
1045
1097
  }
1046
1098
  /**
1047
1099
  * Updates a FHIR resource using JSONPatch operations.
@@ -1088,6 +1140,7 @@ class MedplumClient extends EventTarget {
1088
1140
  * @returns The result of the delete operation.
1089
1141
  */
1090
1142
  deleteResource(resourceType, id) {
1143
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_deleteCacheEntry).call(this, this.fhirUrl(resourceType, id).toString());
1091
1144
  this.invalidateSearches(resourceType);
1092
1145
  return this.delete(this.fhirUrl(resourceType, id));
1093
1146
  }
@@ -1372,7 +1425,7 @@ class MedplumClient extends EventTarget {
1372
1425
  formBody.set('grant_type', 'authorization_code');
1373
1426
  formBody.set('client_id', __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
1374
1427
  formBody.set('code', code);
1375
- formBody.set('redirect_uri', getBaseUrl());
1428
+ formBody.set('redirect_uri', getWindowOrigin());
1376
1429
  const codeVerifier = sessionStorage.getItem('codeVerifier');
1377
1430
  if (codeVerifier) {
1378
1431
  formBody.set('code_verifier', codeVerifier);
@@ -1427,6 +1480,14 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(),
1427
1480
  if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") > 0) {
1428
1481
  __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").set(key, { requestTime: Date.now(), value });
1429
1482
  }
1483
+ }, _MedplumClient_cacheResource = function _MedplumClient_cacheResource(resource) {
1484
+ if (resource?.id) {
1485
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, this.fhirUrl(resource.resourceType, resource.id).toString(), new ReadablePromise(Promise.resolve(resource)));
1486
+ }
1487
+ }, _MedplumClient_deleteCacheEntry = function _MedplumClient_deleteCacheEntry(key) {
1488
+ if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") > 0) {
1489
+ __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").delete(key);
1490
+ }
1430
1491
  }, _MedplumClient_request =
1431
1492
  /**
1432
1493
  * Makes an HTTP request.
@@ -1444,7 +1505,7 @@ async function _MedplumClient_request(method, url, options = {}) {
1444
1505
  }
1445
1506
  options.method = method;
1446
1507
  __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addFetchOptionsDefaults).call(this, options);
1447
- const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options);
1508
+ const response = await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchWithRetry).call(this, url, options);
1448
1509
  if (response.status === 401) {
1449
1510
  // Refresh and try again
1450
1511
  return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_handleUnauthenticated).call(this, method, url, options);
@@ -1453,11 +1514,30 @@ async function _MedplumClient_request(method, url, options = {}) {
1453
1514
  // No content or change
1454
1515
  return undefined;
1455
1516
  }
1456
- const obj = await response.json();
1517
+ let obj = undefined;
1518
+ try {
1519
+ obj = await response.json();
1520
+ }
1521
+ catch (err) {
1522
+ console.error('Error parsing response', response.status, err);
1523
+ throw err;
1524
+ }
1457
1525
  if (response.status >= 400) {
1458
1526
  throw obj;
1459
1527
  }
1460
1528
  return obj;
1529
+ }, _MedplumClient_fetchWithRetry = async function _MedplumClient_fetchWithRetry(url, options) {
1530
+ const maxRetries = 3;
1531
+ const retryDelay = 200;
1532
+ let response = undefined;
1533
+ for (let retry = 0; retry < maxRetries; retry++) {
1534
+ response = (await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options));
1535
+ if (response.status < 500) {
1536
+ return response;
1537
+ }
1538
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
1539
+ }
1540
+ return response;
1461
1541
  }, _MedplumClient_executeAutoBatch =
1462
1542
  /**
1463
1543
  * Executes a batch of requests that were automatically batched together.
@@ -1493,7 +1573,12 @@ async function _MedplumClient_executeAutoBatch() {
1493
1573
  for (let i = 0; i < entries.length; i++) {
1494
1574
  const entry = entries[i];
1495
1575
  const responseEntry = response.entry?.[i];
1496
- entry.resolve(responseEntry?.resource);
1576
+ if (responseEntry?.response?.outcome && !isOk(responseEntry.response.outcome)) {
1577
+ entry.reject(responseEntry.response.outcome);
1578
+ }
1579
+ else {
1580
+ entry.resolve(responseEntry?.resource);
1581
+ }
1497
1582
  }
1498
1583
  }, _MedplumClient_addFetchOptionsDefaults = function _MedplumClient_addFetchOptionsDefaults(options) {
1499
1584
  if (!options.headers) {
@@ -1550,7 +1635,7 @@ async function _MedplumClient_requestAuthorization(loginParams) {
1550
1635
  url.searchParams.set('response_type', 'code');
1551
1636
  url.searchParams.set('state', sessionStorage.getItem('pkceState'));
1552
1637
  url.searchParams.set('client_id', loginRequest.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
1553
- url.searchParams.set('redirect_uri', loginRequest.redirectUri || getBaseUrl());
1638
+ url.searchParams.set('redirect_uri', loginRequest.redirectUri || getWindowOrigin());
1554
1639
  url.searchParams.set('code_challenge_method', loginRequest.codeChallengeMethod);
1555
1640
  url.searchParams.set('code_challenge', loginRequest.codeChallenge);
1556
1641
  url.searchParams.set('scope', loginRequest.scope || 'openid profile');
@@ -1633,12 +1718,34 @@ async function _MedplumClient_verifyTokens(tokens) {
1633
1718
  // Silently ignore if this environment does not support storage events
1634
1719
  }
1635
1720
  };
1721
+ /**
1722
+ * Returns the current window if available.
1723
+ * All access to the current window should use this to support SSR such as Next.js.
1724
+ * @returns The current window or undefined if not available.
1725
+ */
1726
+ function getWindow() {
1727
+ return typeof window === 'undefined' ? undefined : window;
1728
+ }
1729
+ /**
1730
+ * Returns the default fetch method.
1731
+ * The default fetch is currently only available in browser environments.
1732
+ * If you want to use SSR such as Next.js, you should pass a custom fetch function.
1733
+ * @returns The default fetch function for the current environment.
1734
+ */
1735
+ function getDefaultFetch() {
1736
+ const window = getWindow();
1737
+ if (!window) {
1738
+ throw new Error('Fetch not available in this environment');
1739
+ }
1740
+ return window.fetch.bind(window);
1741
+ }
1636
1742
  /**
1637
1743
  * Returns the base URL for the current page.
1638
1744
  * @category HTTP
1639
1745
  */
1640
- function getBaseUrl() {
1641
- return window.location.protocol + '//' + window.location.host + '/';
1746
+ function getWindowOrigin() {
1747
+ const window = getWindow();
1748
+ return window ? window.location.protocol + '//' + window.location.host + '/' : '';
1642
1749
  }
1643
1750
  function ensureTrailingSlash(url) {
1644
1751
  if (!url) {