@medplum/core 0.4.0 → 0.4.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.
package/dist/esm/index.js CHANGED
@@ -21,42 +21,59 @@ function __awaiter(thisArg, _arguments, P, generator) {
21
21
  function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
22
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23
23
  });
24
+ }
25
+
26
+ function __classPrivateFieldGet(receiver, state, kind, f) {
27
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
28
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
29
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
30
+ }
31
+
32
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
33
+ if (kind === "m") throw new TypeError("Private method is not writable");
34
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
35
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
36
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
24
37
  }
25
38
 
39
+ var _LRUCache_instances, _LRUCache_max, _LRUCache_cache, _LRUCache_first;
26
40
  /**
27
41
  * LRU cache (least recently used)
28
42
  * Source: https://stackoverflow.com/a/46432113
29
43
  */
30
44
  class LRUCache {
31
45
  constructor(max = 10) {
32
- this.max = max;
33
- this.cache = new Map();
46
+ _LRUCache_instances.add(this);
47
+ _LRUCache_max.set(this, void 0);
48
+ _LRUCache_cache.set(this, void 0);
49
+ __classPrivateFieldSet(this, _LRUCache_max, max, "f");
50
+ __classPrivateFieldSet(this, _LRUCache_cache, new Map(), "f");
34
51
  }
35
52
  clear() {
36
- this.cache.clear();
53
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").clear();
37
54
  }
38
55
  get(key) {
39
- const item = this.cache.get(key);
56
+ const item = __classPrivateFieldGet(this, _LRUCache_cache, "f").get(key);
40
57
  if (item) {
41
- this.cache.delete(key);
42
- this.cache.set(key, item);
58
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key);
59
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, item);
43
60
  }
44
61
  return item;
45
62
  }
46
63
  set(key, val) {
47
- if (this.cache.has(key)) {
48
- this.cache.delete(key);
64
+ if (__classPrivateFieldGet(this, _LRUCache_cache, "f").has(key)) {
65
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key);
49
66
  }
50
- else if (this.cache.size >= this.max) {
51
- this.cache.delete(this.first());
67
+ else if (__classPrivateFieldGet(this, _LRUCache_cache, "f").size >= __classPrivateFieldGet(this, _LRUCache_max, "f")) {
68
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(__classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_first).call(this));
52
69
  }
53
- this.cache.set(key, val);
70
+ __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, val);
54
71
  }
55
- first() {
56
- // This works because the Map class maintains ordered keys.
57
- return this.cache.keys().next().value;
58
- }
59
- }
72
+ }
73
+ _LRUCache_max = new WeakMap(), _LRUCache_cache = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_first = function _LRUCache_first() {
74
+ // This works because the Map class maintains ordered keys.
75
+ return __classPrivateFieldGet(this, _LRUCache_cache, "f").keys().next().value;
76
+ };
60
77
 
61
78
  function formatAddress(address, options) {
62
79
  const builder = [];
@@ -125,6 +142,15 @@ function createReference(resource) {
125
142
  function getReferenceString(resource) {
126
143
  return resource.resourceType + '/' + resource.id;
127
144
  }
145
+ /**
146
+ * Returns the ID portion of a reference.
147
+ * @param reference A FHIR reference.
148
+ * @returns The ID portion of a reference.
149
+ */
150
+ function resolveId(reference) {
151
+ var _a;
152
+ return (_a = reference === null || reference === void 0 ? void 0 : reference.reference) === null || _a === void 0 ? void 0 : _a.split('/')[1];
153
+ }
128
154
  /**
129
155
  * Returns true if the resource is a "ProfileResource".
130
156
  * @param resource The FHIR resource.
@@ -347,18 +373,20 @@ function encryptSHA256(str) {
347
373
  /*
348
374
  * Based on: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
349
375
  */
376
+ var _EventTarget_listeners;
350
377
  class EventTarget {
351
378
  constructor() {
352
- this.listeners = {};
379
+ _EventTarget_listeners.set(this, void 0);
380
+ __classPrivateFieldSet(this, _EventTarget_listeners, {}, "f");
353
381
  }
354
382
  addEventListener(type, callback) {
355
- if (!this.listeners[type]) {
356
- this.listeners[type] = [];
383
+ if (!__classPrivateFieldGet(this, _EventTarget_listeners, "f")[type]) {
384
+ __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type] = [];
357
385
  }
358
- this.listeners[type].push(callback);
386
+ __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type].push(callback);
359
387
  }
360
388
  removeEventListeneer(type, callback) {
361
- const array = this.listeners[type];
389
+ const array = __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type];
362
390
  if (!array) {
363
391
  return;
364
392
  }
@@ -370,13 +398,14 @@ class EventTarget {
370
398
  }
371
399
  }
372
400
  dispatchEvent(event) {
373
- const array = this.listeners[event.type];
401
+ const array = __classPrivateFieldGet(this, _EventTarget_listeners, "f")[event.type];
374
402
  if (array) {
375
403
  array.forEach((listener) => listener.call(this, event));
376
404
  }
377
405
  return !event.defaultPrevented;
378
406
  }
379
- }
407
+ }
408
+ _EventTarget_listeners = new WeakMap();
380
409
 
381
410
  /**
382
411
  * Decodes a section of a JWT.
@@ -616,6 +645,7 @@ function parseSearchDefinition(location) {
616
645
  let fields;
617
646
  let page = 0;
618
647
  let count = 10;
648
+ let total = undefined;
619
649
  params.forEach((value, key) => {
620
650
  if (key === '_fields') {
621
651
  fields = value.split(',');
@@ -626,6 +656,9 @@ function parseSearchDefinition(location) {
626
656
  else if (key === '_count') {
627
657
  count = parseInt(value);
628
658
  }
659
+ else if (key === '_total') {
660
+ total = value;
661
+ }
629
662
  else if (key === '_sort') {
630
663
  sortRules.push(parseSortRule(value));
631
664
  }
@@ -639,6 +672,7 @@ function parseSearchDefinition(location) {
639
672
  fields,
640
673
  page,
641
674
  count,
675
+ total,
642
676
  sortRules,
643
677
  };
644
678
  }
@@ -722,6 +756,9 @@ function formatSearchQuery(definition) {
722
756
  if (definition.count && definition.count > 0) {
723
757
  params.push('_count=' + definition.count);
724
758
  }
759
+ if (definition.total) {
760
+ params.push('_total=' + encodeURIComponent(definition.total));
761
+ }
725
762
  if (params.length === 0) {
726
763
  return '';
727
764
  }
@@ -735,6 +772,7 @@ function formatSortRules(sortRules) {
735
772
  return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');
736
773
  }
737
774
 
775
+ var _ClientStorage_storage, _MemoryStorage_data;
738
776
  /**
739
777
  * The ClientStorage class is a utility class for storing strings and objects.
740
778
  *
@@ -744,20 +782,21 @@ function formatSortRules(sortRules) {
744
782
  */
745
783
  class ClientStorage {
746
784
  constructor() {
747
- this.storage = typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage();
785
+ _ClientStorage_storage.set(this, void 0);
786
+ __classPrivateFieldSet(this, _ClientStorage_storage, typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage(), "f");
748
787
  }
749
788
  clear() {
750
- this.storage.clear();
789
+ __classPrivateFieldGet(this, _ClientStorage_storage, "f").clear();
751
790
  }
752
791
  getString(key) {
753
- return this.storage.getItem(key) || undefined;
792
+ return __classPrivateFieldGet(this, _ClientStorage_storage, "f").getItem(key) || undefined;
754
793
  }
755
794
  setString(key, value) {
756
795
  if (value) {
757
- this.storage.setItem(key, value);
796
+ __classPrivateFieldGet(this, _ClientStorage_storage, "f").setItem(key, value);
758
797
  }
759
798
  else {
760
- this.storage.removeItem(key);
799
+ __classPrivateFieldGet(this, _ClientStorage_storage, "f").removeItem(key);
761
800
  }
762
801
  }
763
802
  getObject(key) {
@@ -768,56 +807,59 @@ class ClientStorage {
768
807
  this.setString(key, value ? stringify(value) : undefined);
769
808
  }
770
809
  }
810
+ _ClientStorage_storage = new WeakMap();
771
811
  /**
772
812
  * The MemoryStorage class is a minimal in-memory implementation of the Storage interface.
773
813
  */
774
814
  class MemoryStorage {
775
815
  constructor() {
776
- this.data = new Map();
816
+ _MemoryStorage_data.set(this, void 0);
817
+ __classPrivateFieldSet(this, _MemoryStorage_data, new Map(), "f");
777
818
  }
778
819
  /**
779
820
  * Returns the number of key/value pairs.
780
821
  */
781
822
  get length() {
782
- return this.data.size;
823
+ return __classPrivateFieldGet(this, _MemoryStorage_data, "f").size;
783
824
  }
784
825
  /**
785
826
  * Removes all key/value pairs, if there are any.
786
827
  */
787
828
  clear() {
788
- this.data.clear();
829
+ __classPrivateFieldGet(this, _MemoryStorage_data, "f").clear();
789
830
  }
790
831
  /**
791
832
  * Returns the current value associated with the given key, or null if the given key does not exist.
792
833
  */
793
834
  getItem(key) {
794
835
  var _a;
795
- return (_a = this.data.get(key)) !== null && _a !== void 0 ? _a : null;
836
+ return (_a = __classPrivateFieldGet(this, _MemoryStorage_data, "f").get(key)) !== null && _a !== void 0 ? _a : null;
796
837
  }
797
838
  /**
798
839
  * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
799
840
  */
800
841
  setItem(key, value) {
801
842
  if (value) {
802
- this.data.set(key, value);
843
+ __classPrivateFieldGet(this, _MemoryStorage_data, "f").set(key, value);
803
844
  }
804
845
  else {
805
- this.data.delete(key);
846
+ __classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
806
847
  }
807
848
  }
808
849
  /**
809
850
  * Removes the key/value pair with the given key, if a key/value pair with the given key exists.
810
851
  */
811
852
  removeItem(key) {
812
- this.data.delete(key);
853
+ __classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
813
854
  }
814
855
  /**
815
856
  * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.
816
857
  */
817
858
  key(index) {
818
- return Array.from(this.data.keys())[index];
859
+ return Array.from(__classPrivateFieldGet(this, _MemoryStorage_data, "f").keys())[index];
819
860
  }
820
- }
861
+ }
862
+ _MemoryStorage_data = new WeakMap();
821
863
 
822
864
  /**
823
865
  * List of property types.
@@ -1006,6 +1048,8 @@ function getPropertyDisplayName(property) {
1006
1048
  }
1007
1049
 
1008
1050
  // PKCE auth ased on:
1051
+ // https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
1052
+ var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_storage, _MedplumClient_schema, _MedplumClient_resourceCache, _MedplumClient_baseUrl, _MedplumClient_clientId, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_request, _MedplumClient_buildFetchOptions, _MedplumClient_handleUnauthenticated, _MedplumClient_startPkce, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
1009
1053
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
1010
1054
  const DEFAULT_SCOPE = 'launch/patient openid fhirUser offline_access user/*.*';
1011
1055
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
@@ -1016,6 +1060,23 @@ class MedplumClient extends EventTarget {
1016
1060
  constructor(options) {
1017
1061
  var _a;
1018
1062
  super();
1063
+ _MedplumClient_instances.add(this);
1064
+ _MedplumClient_fetch.set(this, void 0);
1065
+ _MedplumClient_storage.set(this, void 0);
1066
+ _MedplumClient_schema.set(this, void 0);
1067
+ _MedplumClient_resourceCache.set(this, void 0);
1068
+ _MedplumClient_baseUrl.set(this, void 0);
1069
+ _MedplumClient_clientId.set(this, void 0);
1070
+ _MedplumClient_authorizeUrl.set(this, void 0);
1071
+ _MedplumClient_tokenUrl.set(this, void 0);
1072
+ _MedplumClient_logoutUrl.set(this, void 0);
1073
+ _MedplumClient_onUnauthenticated.set(this, void 0);
1074
+ _MedplumClient_accessToken.set(this, void 0);
1075
+ _MedplumClient_refreshToken.set(this, void 0);
1076
+ _MedplumClient_refreshPromise.set(this, void 0);
1077
+ _MedplumClient_profilePromise.set(this, void 0);
1078
+ _MedplumClient_profile.set(this, void 0);
1079
+ _MedplumClient_config.set(this, void 0);
1019
1080
  if (options === null || options === void 0 ? void 0 : options.baseUrl) {
1020
1081
  if (!options.baseUrl.startsWith('http')) {
1021
1082
  throw new Error('Base URL must start with http or https');
@@ -1024,39 +1085,47 @@ class MedplumClient extends EventTarget {
1024
1085
  throw new Error('Base URL must end with a trailing slash');
1025
1086
  }
1026
1087
  }
1027
- this.fetch = (options === null || options === void 0 ? void 0 : options.fetch) || window.fetch.bind(window);
1028
- this.storage = new ClientStorage();
1029
- this.schema = createSchema();
1030
- this.resourceCache = new LRUCache((_a = options === null || options === void 0 ? void 0 : options.resourceCacheSize) !== null && _a !== void 0 ? _a : DEFAULT_RESOURCE_CACHE_SIZE);
1031
- this.baseUrl = (options === null || options === void 0 ? void 0 : options.baseUrl) || DEFAULT_BASE_URL;
1032
- this.clientId = (options === null || options === void 0 ? void 0 : options.clientId) || '';
1033
- this.authorizeUrl = (options === null || options === void 0 ? void 0 : options.authorizeUrl) || this.baseUrl + 'oauth2/authorize';
1034
- this.tokenUrl = (options === null || options === void 0 ? void 0 : options.tokenUrl) || this.baseUrl + 'oauth2/token';
1035
- this.logoutUrl = (options === null || options === void 0 ? void 0 : options.logoutUrl) || this.baseUrl + 'oauth2/logout';
1036
- this.onUnauthenticated = options === null || options === void 0 ? void 0 : options.onUnauthenticated;
1037
- this.loading = false;
1038
- this.refreshProfile().catch(console.log);
1039
- this.setupStorageListener();
1088
+ __classPrivateFieldSet(this, _MedplumClient_fetch, (options === null || options === void 0 ? void 0 : options.fetch) || window.fetch.bind(window), "f");
1089
+ __classPrivateFieldSet(this, _MedplumClient_storage, new ClientStorage(), "f");
1090
+ __classPrivateFieldSet(this, _MedplumClient_schema, createSchema(), "f");
1091
+ __classPrivateFieldSet(this, _MedplumClient_resourceCache, new LRUCache((_a = options === null || options === void 0 ? void 0 : options.resourceCacheSize) !== null && _a !== void 0 ? _a : DEFAULT_RESOURCE_CACHE_SIZE), "f");
1092
+ __classPrivateFieldSet(this, _MedplumClient_baseUrl, (options === null || options === void 0 ? void 0 : options.baseUrl) || DEFAULT_BASE_URL, "f");
1093
+ __classPrivateFieldSet(this, _MedplumClient_clientId, (options === null || options === void 0 ? void 0 : options.clientId) || '', "f");
1094
+ __classPrivateFieldSet(this, _MedplumClient_authorizeUrl, (options === null || options === void 0 ? void 0 : options.authorizeUrl) || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
1095
+ __classPrivateFieldSet(this, _MedplumClient_tokenUrl, (options === null || options === void 0 ? void 0 : options.tokenUrl) || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
1096
+ __classPrivateFieldSet(this, _MedplumClient_logoutUrl, (options === null || options === void 0 ? void 0 : options.logoutUrl) || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/logout', "f");
1097
+ __classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options === null || options === void 0 ? void 0 : options.onUnauthenticated, "f");
1098
+ const activeLogin = this.getActiveLogin();
1099
+ if (activeLogin) {
1100
+ __classPrivateFieldSet(this, _MedplumClient_accessToken, activeLogin.accessToken, "f");
1101
+ __classPrivateFieldSet(this, _MedplumClient_refreshToken, activeLogin.refreshToken, "f");
1102
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this).catch(console.log);
1103
+ }
1104
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setupStorageListener).call(this);
1040
1105
  }
1041
1106
  /**
1042
1107
  * Clears all auth state including local storage and session storage.
1043
1108
  */
1044
1109
  clear() {
1045
- this.storage.clear();
1046
- this.resourceCache.clear();
1110
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").clear();
1111
+ __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").clear();
1112
+ __classPrivateFieldSet(this, _MedplumClient_accessToken, undefined, "f");
1113
+ __classPrivateFieldSet(this, _MedplumClient_refreshToken, undefined, "f");
1114
+ __classPrivateFieldSet(this, _MedplumClient_profile, undefined, "f");
1115
+ __classPrivateFieldSet(this, _MedplumClient_config, undefined, "f");
1047
1116
  this.dispatchEvent({ type: 'change' });
1048
1117
  }
1049
1118
  get(url) {
1050
- return this.request('GET', url);
1119
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'GET', url);
1051
1120
  }
1052
1121
  post(url, body, contentType) {
1053
- return this.request('POST', url, contentType, body);
1122
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'POST', url, contentType, body);
1054
1123
  }
1055
1124
  put(url, body, contentType) {
1056
- return this.request('PUT', url, contentType, body);
1125
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'PUT', url, contentType, body);
1057
1126
  }
1058
1127
  delete(url) {
1059
- return this.request('DELETE', url);
1128
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'DELETE', url);
1060
1129
  }
1061
1130
  /**
1062
1131
  * Tries to register a new user.
@@ -1078,12 +1147,12 @@ class MedplumClient extends EventTarget {
1078
1147
  */
1079
1148
  startLogin(email, password, remember) {
1080
1149
  return __awaiter(this, void 0, void 0, function* () {
1081
- yield this.startPkce();
1150
+ yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
1082
1151
  return this.post('auth/login', {
1083
- clientId: this.clientId,
1152
+ clientId: __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
1084
1153
  scope: DEFAULT_SCOPE,
1085
1154
  codeChallengeMethod: 'S256',
1086
- codeChallenge: this.storage.getString('codeChallenge'),
1155
+ codeChallenge: __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeChallenge'),
1087
1156
  email,
1088
1157
  password,
1089
1158
  remember: !!remember,
@@ -1099,7 +1168,7 @@ class MedplumClient extends EventTarget {
1099
1168
  */
1100
1169
  startGoogleLogin(googleResponse) {
1101
1170
  return __awaiter(this, void 0, void 0, function* () {
1102
- yield this.startPkce();
1171
+ yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
1103
1172
  return this.post('auth/google', googleResponse);
1104
1173
  });
1105
1174
  }
@@ -1120,7 +1189,7 @@ class MedplumClient extends EventTarget {
1120
1189
  const urlParams = new URLSearchParams(window.location.search);
1121
1190
  const code = urlParams.get('code');
1122
1191
  if (!code) {
1123
- this.requestAuthorization();
1192
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_requestAuthorization).call(this);
1124
1193
  return undefined;
1125
1194
  }
1126
1195
  else {
@@ -1132,7 +1201,7 @@ class MedplumClient extends EventTarget {
1132
1201
  * See: https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html
1133
1202
  */
1134
1203
  signOutWithRedirect() {
1135
- window.location.assign(this.logoutUrl);
1204
+ window.location.assign(__classPrivateFieldGet(this, _MedplumClient_logoutUrl, "f"));
1136
1205
  }
1137
1206
  /**
1138
1207
  * Builds a FHIR URL from a collection of URL path components.
@@ -1141,7 +1210,7 @@ class MedplumClient extends EventTarget {
1141
1210
  * @returns The well-formed FHIR URL.
1142
1211
  */
1143
1212
  fhirUrl(...path) {
1144
- const builder = [this.baseUrl, 'fhir/R4'];
1213
+ const builder = [__classPrivateFieldGet(this, _MedplumClient_baseUrl, "f"), 'fhir/R4'];
1145
1214
  path.forEach((p) => builder.push('/', encodeURIComponent(p)));
1146
1215
  return builder.join('');
1147
1216
  }
@@ -1172,7 +1241,7 @@ class MedplumClient extends EventTarget {
1172
1241
  * @returns The resource if it is available in the cache; undefined otherwise.
1173
1242
  */
1174
1243
  getCached(resourceType, id) {
1175
- const cached = this.resourceCache.get(resourceType + '/' + id);
1244
+ const cached = __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").get(resourceType + '/' + id);
1176
1245
  if (cached && !('then' in cached)) {
1177
1246
  return cached;
1178
1247
  }
@@ -1185,7 +1254,7 @@ class MedplumClient extends EventTarget {
1185
1254
  * @returns The resource if it is available in the cache; undefined otherwise.
1186
1255
  */
1187
1256
  getCachedReference(reference) {
1188
- const cached = this.resourceCache.get(reference.reference);
1257
+ const cached = __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").get(reference.reference);
1189
1258
  if (cached && !('then' in cached)) {
1190
1259
  return cached;
1191
1260
  }
@@ -1194,14 +1263,14 @@ class MedplumClient extends EventTarget {
1194
1263
  read(resourceType, id) {
1195
1264
  const cacheKey = resourceType + '/' + id;
1196
1265
  const promise = this.get(this.fhirUrl(resourceType, id)).then((resource) => {
1197
- this.resourceCache.set(cacheKey, resource);
1266
+ __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").set(cacheKey, resource);
1198
1267
  return resource;
1199
1268
  });
1200
- this.resourceCache.set(cacheKey, promise);
1269
+ __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").set(cacheKey, promise);
1201
1270
  return promise;
1202
1271
  }
1203
1272
  readCached(resourceType, id) {
1204
- const cached = this.resourceCache.get(resourceType + '/' + id);
1273
+ const cached = __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").get(resourceType + '/' + id);
1205
1274
  return cached ? Promise.resolve(cached) : this.read(resourceType, id);
1206
1275
  }
1207
1276
  readReference(reference) {
@@ -1228,7 +1297,7 @@ class MedplumClient extends EventTarget {
1228
1297
  * @returns The schema if immediately available, undefined otherwise.
1229
1298
  */
1230
1299
  getSchema() {
1231
- return this.schema;
1300
+ return __classPrivateFieldGet(this, _MedplumClient_schema, "f");
1232
1301
  }
1233
1302
  /**
1234
1303
  * Requests the schema for a resource type.
@@ -1238,8 +1307,8 @@ class MedplumClient extends EventTarget {
1238
1307
  */
1239
1308
  requestSchema(resourceType) {
1240
1309
  return __awaiter(this, void 0, void 0, function* () {
1241
- if (resourceType in this.schema.types) {
1242
- return Promise.resolve(this.schema);
1310
+ if (resourceType in __classPrivateFieldGet(this, _MedplumClient_schema, "f").types) {
1311
+ return Promise.resolve(__classPrivateFieldGet(this, _MedplumClient_schema, "f"));
1243
1312
  }
1244
1313
  const query = `{
1245
1314
  StructureDefinitionList(name: "${encodeURIComponent(resourceType)}") {
@@ -1270,12 +1339,12 @@ class MedplumClient extends EventTarget {
1270
1339
  }`.replace(/\s+/g, ' ');
1271
1340
  const response = (yield this.graphql(query));
1272
1341
  for (const structureDefinition of response.data.StructureDefinitionList) {
1273
- indexStructureDefinition(this.schema, structureDefinition);
1342
+ indexStructureDefinition(__classPrivateFieldGet(this, _MedplumClient_schema, "f"), structureDefinition);
1274
1343
  }
1275
1344
  for (const searchParameter of response.data.SearchParameterList) {
1276
- indexSearchParameter(this.schema, searchParameter);
1345
+ indexSearchParameter(__classPrivateFieldGet(this, _MedplumClient_schema, "f"), searchParameter);
1277
1346
  }
1278
- return this.schema;
1347
+ return __classPrivateFieldGet(this, _MedplumClient_schema, "f");
1279
1348
  });
1280
1349
  }
1281
1350
  readHistory(resourceType, id) {
@@ -1303,7 +1372,7 @@ class MedplumClient extends EventTarget {
1303
1372
  return this.put(this.fhirUrl(resource.resourceType, resource.id), resource);
1304
1373
  }
1305
1374
  patch(resourceType, id, operations) {
1306
- return this.request('PATCH', this.fhirUrl(resourceType, id), PATCH_CONTENT_TYPE, operations);
1375
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'PATCH', this.fhirUrl(resourceType, id), PATCH_CONTENT_TYPE, operations);
1307
1376
  }
1308
1377
  deleteResource(resourceType, id) {
1309
1378
  return this.delete(this.fhirUrl(resourceType, id));
@@ -1312,159 +1381,55 @@ class MedplumClient extends EventTarget {
1312
1381
  return this.post(this.fhirUrl('$graphql'), { query }, JSON_CONTENT_TYPE);
1313
1382
  }
1314
1383
  getActiveLogin() {
1315
- return this.storage.getObject('activeLogin');
1384
+ return __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('activeLogin');
1316
1385
  }
1317
1386
  setActiveLogin(login) {
1318
1387
  return __awaiter(this, void 0, void 0, function* () {
1319
- this.storage.setObject('activeLogin', login);
1320
- this.addLogin(login);
1321
- this.resourceCache.clear();
1322
- this.refreshPromise = undefined;
1323
- yield this.refreshProfile();
1388
+ __classPrivateFieldSet(this, _MedplumClient_accessToken, login.accessToken, "f");
1389
+ __classPrivateFieldSet(this, _MedplumClient_refreshToken, login.refreshToken, "f");
1390
+ __classPrivateFieldSet(this, _MedplumClient_profile, undefined, "f");
1391
+ __classPrivateFieldSet(this, _MedplumClient_config, undefined, "f");
1392
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('activeLogin', login);
1393
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addLogin).call(this, login);
1394
+ __classPrivateFieldGet(this, _MedplumClient_resourceCache, "f").clear();
1395
+ __classPrivateFieldSet(this, _MedplumClient_refreshPromise, undefined, "f");
1396
+ yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
1324
1397
  });
1325
1398
  }
1326
1399
  getLogins() {
1327
1400
  var _a;
1328
- return (_a = this.storage.getObject('logins')) !== null && _a !== void 0 ? _a : [];
1401
+ return (_a = __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('logins')) !== null && _a !== void 0 ? _a : [];
1329
1402
  }
1330
- addLogin(newLogin) {
1331
- const logins = this.getLogins().filter((login) => { var _a, _b; return ((_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference) !== ((_b = newLogin.profile) === null || _b === void 0 ? void 0 : _b.reference); });
1332
- logins.push(newLogin);
1333
- this.storage.setObject('logins', logins);
1334
- }
1335
- refreshProfile() {
1336
- var _a;
1337
- return __awaiter(this, void 0, void 0, function* () {
1338
- const reference = (_a = this.getActiveLogin()) === null || _a === void 0 ? void 0 : _a.profile;
1339
- if (reference === null || reference === void 0 ? void 0 : reference.reference) {
1340
- this.loading = true;
1341
- this.storage.setObject('profile', yield this.readCachedReference(reference));
1342
- this.loading = false;
1343
- this.dispatchEvent({ type: 'change' });
1344
- }
1345
- return this.getProfile();
1346
- });
1403
+ isLoading() {
1404
+ return !!__classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
1347
1405
  }
1348
1406
  getProfile() {
1349
- return this.storage.getObject('profile');
1350
- }
1351
- isLoading() {
1352
- return this.loading;
1407
+ return __classPrivateFieldGet(this, _MedplumClient_profile, "f");
1353
1408
  }
1354
- /**
1355
- * Makes an HTTP request.
1356
- * @param {string} method
1357
- * @param {string} url
1358
- * @param {string=} contentType
1359
- * @param {Object=} body
1360
- */
1361
- request(method, url, contentType, body) {
1362
- var _a;
1409
+ getProfileAsync() {
1363
1410
  return __awaiter(this, void 0, void 0, function* () {
1364
- if (this.refreshPromise) {
1365
- yield this.refreshPromise;
1411
+ if (__classPrivateFieldGet(this, _MedplumClient_profilePromise, "f")) {
1412
+ yield __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
1366
1413
  }
1367
- if (!url.startsWith('http')) {
1368
- url = this.baseUrl + url;
1369
- }
1370
- const headers = {
1371
- 'Content-Type': contentType || FHIR_CONTENT_TYPE,
1372
- };
1373
- const accessToken = (_a = this.getActiveLogin()) === null || _a === void 0 ? void 0 : _a.accessToken;
1374
- if (accessToken) {
1375
- headers['Authorization'] = 'Bearer ' + accessToken;
1376
- }
1377
- const options = {
1378
- method: method,
1379
- cache: 'no-cache',
1380
- credentials: 'include',
1381
- headers,
1382
- };
1383
- if (body) {
1384
- if (typeof body === 'string' || (typeof File !== 'undefined' && body instanceof File)) {
1385
- options.body = body;
1386
- }
1387
- else {
1388
- options.body = stringify(body);
1389
- }
1390
- }
1391
- const response = yield this.fetch(url, options);
1392
- if (response.status === 401) {
1393
- // Refresh and try again
1394
- return this.handleUnauthenticated(method, url, contentType, body);
1395
- }
1396
- if (response.status === 204 || response.status === 304) {
1397
- // No content or change
1398
- return undefined;
1399
- }
1400
- const obj = yield response.json();
1401
- if (obj.resourceType === 'OperationOutcome' && !isOk(obj)) {
1402
- return Promise.reject(obj);
1403
- }
1404
- return obj;
1405
- });
1406
- }
1407
- /**
1408
- * Handles an unauthenticated response from the server.
1409
- * First, tries to refresh the access token and retry the request.
1410
- * Otherwise, calls unauthenticated callbacks and rejects.
1411
- * @param method The HTTP method of the original request.
1412
- * @param url The URL of the original request.
1413
- * @param contentType The content type of the original request.
1414
- * @param body The body of the original request.
1415
- */
1416
- handleUnauthenticated(method, url, contentType, body) {
1417
- return __awaiter(this, void 0, void 0, function* () {
1418
- return this.refresh()
1419
- .then(() => this.request(method, url, contentType, body))
1420
- .catch((error) => {
1421
- this.clear();
1422
- if (this.onUnauthenticated) {
1423
- this.onUnauthenticated();
1424
- }
1425
- return Promise.reject(error);
1426
- });
1414
+ return this.getProfile();
1427
1415
  });
1428
1416
  }
1429
- /**
1430
- * Starts a new PKCE flow.
1431
- * These PKCE values are stateful, and must survive redirects and page refreshes.
1432
- */
1433
- startPkce() {
1434
- return __awaiter(this, void 0, void 0, function* () {
1435
- const pkceState = getRandomString();
1436
- this.storage.setString('pkceState', pkceState);
1437
- const codeVerifier = getRandomString();
1438
- this.storage.setString('codeVerifier', codeVerifier);
1439
- const arrayHash = yield encryptSHA256(codeVerifier);
1440
- const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
1441
- this.storage.setString('codeChallenge', codeChallenge);
1442
- });
1417
+ getUserConfiguration() {
1418
+ return __classPrivateFieldGet(this, _MedplumClient_config, "f");
1443
1419
  }
1444
1420
  /**
1445
- * Redirects the user to the login screen for authorization.
1446
- * Clears all auth state including local storage and session storage.
1447
- * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
1421
+ * Downloads the URL as a blob.
1422
+ * @param url The URL to request.
1423
+ * @returns Promise to the response body as a blob.
1448
1424
  */
1449
- requestAuthorization() {
1425
+ download(url) {
1450
1426
  return __awaiter(this, void 0, void 0, function* () {
1451
- if (!this.authorizeUrl) {
1452
- throw new Error('Missing authorize URL');
1427
+ if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
1428
+ yield __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
1453
1429
  }
1454
- this.startPkce();
1455
- window.location.assign(this.authorizeUrl +
1456
- '?response_type=code' +
1457
- '&state=' +
1458
- encodeURIComponent(this.storage.getString('pkceState')) +
1459
- '&client_id=' +
1460
- encodeURIComponent(this.clientId) +
1461
- '&redirect_uri=' +
1462
- encodeURIComponent(getBaseUrl()) +
1463
- '&scope=' +
1464
- encodeURIComponent(DEFAULT_SCOPE) +
1465
- '&code_challenge_method=S256' +
1466
- '&code_challenge=' +
1467
- encodeURIComponent(this.storage.getString('codeChallenge')));
1430
+ const options = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_buildFetchOptions).call(this, 'GET');
1431
+ const response = yield __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options);
1432
+ return response.blob();
1468
1433
  });
1469
1434
  }
1470
1435
  /**
@@ -1473,18 +1438,18 @@ class MedplumClient extends EventTarget {
1473
1438
  * @param code The authorization code received by URL parameter.
1474
1439
  */
1475
1440
  processCode(code) {
1476
- const pkceState = this.storage.getString('pkceState');
1441
+ const pkceState = __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('pkceState');
1477
1442
  if (!pkceState) {
1478
1443
  this.clear();
1479
1444
  throw new Error('Invalid PCKE state');
1480
1445
  }
1481
- const codeVerifier = this.storage.getString('codeVerifier');
1446
+ const codeVerifier = __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeVerifier');
1482
1447
  if (!codeVerifier) {
1483
1448
  this.clear();
1484
1449
  throw new Error('Invalid PCKE code verifier');
1485
1450
  }
1486
- return this.fetchTokens('grant_type=authorization_code' +
1487
- (this.clientId ? '&client_id=' + encodeURIComponent(this.clientId) : '') +
1451
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, 'grant_type=authorization_code' +
1452
+ (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") ? '&client_id=' + encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_clientId, "f")) : '') +
1488
1453
  '&code_verifier=' +
1489
1454
  encodeURIComponent(codeVerifier) +
1490
1455
  '&redirect_uri=' +
@@ -1492,102 +1457,185 @@ class MedplumClient extends EventTarget {
1492
1457
  '&code=' +
1493
1458
  encodeURIComponent(code));
1494
1459
  }
1495
- /**
1496
- * Tries to refresh the auth tokens.
1497
- * See: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
1498
- */
1499
- refresh() {
1500
- var _a;
1501
- return __awaiter(this, void 0, void 0, function* () {
1502
- if (this.refreshPromise) {
1503
- return this.refreshPromise;
1504
- }
1505
- const refreshToken = (_a = this.getActiveLogin()) === null || _a === void 0 ? void 0 : _a.refreshToken;
1506
- if (!refreshToken) {
1507
- this.clear();
1508
- return Promise.reject('Invalid refresh token');
1509
- }
1510
- this.refreshPromise = this.fetchTokens('grant_type=refresh_token' +
1511
- '&client_id=' +
1512
- encodeURIComponent(this.clientId) +
1513
- '&refresh_token=' +
1514
- encodeURIComponent(refreshToken));
1515
- yield this.refreshPromise;
1516
- });
1460
+ }
1461
+ _MedplumClient_fetch = new WeakMap(), _MedplumClient_storage = new WeakMap(), _MedplumClient_schema = new WeakMap(), _MedplumClient_resourceCache = new WeakMap(), _MedplumClient_baseUrl = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = 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) {
1462
+ const logins = this.getLogins().filter((login) => { var _a, _b; return ((_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference) !== ((_b = newLogin.profile) === null || _b === void 0 ? void 0 : _b.reference); });
1463
+ logins.push(newLogin);
1464
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
1465
+ }, _MedplumClient_refreshProfile = function _MedplumClient_refreshProfile() {
1466
+ return __awaiter(this, void 0, void 0, function* () {
1467
+ __classPrivateFieldSet(this, _MedplumClient_profilePromise, new Promise((resolve, reject) => {
1468
+ this.get('auth/me')
1469
+ .then((result) => {
1470
+ __classPrivateFieldSet(this, _MedplumClient_profilePromise, undefined, "f");
1471
+ __classPrivateFieldSet(this, _MedplumClient_profile, result.profile, "f");
1472
+ __classPrivateFieldSet(this, _MedplumClient_config, result.config, "f");
1473
+ this.dispatchEvent({ type: 'change' });
1474
+ resolve(__classPrivateFieldGet(this, _MedplumClient_profile, "f"));
1475
+ })
1476
+ .catch(reject);
1477
+ }), "f");
1478
+ return __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
1479
+ });
1480
+ }, _MedplumClient_request = function _MedplumClient_request(method, url, contentType, body) {
1481
+ return __awaiter(this, void 0, void 0, function* () {
1482
+ if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
1483
+ yield __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
1484
+ }
1485
+ if (!url.startsWith('http')) {
1486
+ url = __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + url;
1487
+ }
1488
+ const options = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_buildFetchOptions).call(this, method, contentType, body);
1489
+ const response = yield __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options);
1490
+ if (response.status === 401) {
1491
+ // Refresh and try again
1492
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_handleUnauthenticated).call(this, method, url, contentType, body);
1493
+ }
1494
+ if (response.status === 204 || response.status === 304) {
1495
+ // No content or change
1496
+ return undefined;
1497
+ }
1498
+ const obj = yield response.json();
1499
+ if (obj.resourceType === 'OperationOutcome' && !isOk(obj)) {
1500
+ return Promise.reject(obj);
1501
+ }
1502
+ return obj;
1503
+ });
1504
+ }, _MedplumClient_buildFetchOptions = function _MedplumClient_buildFetchOptions(method, contentType, body) {
1505
+ const headers = {
1506
+ 'Content-Type': contentType || FHIR_CONTENT_TYPE,
1507
+ };
1508
+ if (__classPrivateFieldGet(this, _MedplumClient_accessToken, "f")) {
1509
+ headers['Authorization'] = 'Bearer ' + __classPrivateFieldGet(this, _MedplumClient_accessToken, "f");
1510
+ }
1511
+ const options = {
1512
+ method: method,
1513
+ cache: 'no-cache',
1514
+ credentials: 'include',
1515
+ headers,
1516
+ };
1517
+ if (body) {
1518
+ if (typeof body === 'string' || (typeof File !== 'undefined' && body instanceof File)) {
1519
+ options.body = body;
1520
+ }
1521
+ else {
1522
+ options.body = stringify(body);
1523
+ }
1517
1524
  }
1518
- /**
1519
- * Makes a POST request to the tokens endpoint.
1520
- * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
1521
- * @param formBody Token parameters in URL encoded format.
1522
- */
1523
- fetchTokens(formBody) {
1524
- return __awaiter(this, void 0, void 0, function* () {
1525
- if (!this.tokenUrl) {
1526
- return Promise.reject('Missing token URL');
1525
+ return options;
1526
+ }, _MedplumClient_handleUnauthenticated = function _MedplumClient_handleUnauthenticated(method, url, contentType, body) {
1527
+ return __awaiter(this, void 0, void 0, function* () {
1528
+ return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refresh).call(this)
1529
+ .then(() => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, method, url, contentType, body))
1530
+ .catch((error) => {
1531
+ this.clear();
1532
+ if (__classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f")) {
1533
+ __classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f").call(this);
1527
1534
  }
1528
- return this.fetch(this.tokenUrl, {
1529
- method: 'POST',
1530
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1531
- body: formBody,
1532
- })
1533
- .then((response) => {
1534
- if (!response.ok) {
1535
- return Promise.reject('Failed to fetch tokens');
1536
- }
1537
- return response.json();
1538
- })
1539
- .then((tokens) => this.verifyTokens(tokens))
1540
- .then(() => this.getProfile());
1535
+ return Promise.reject(error);
1541
1536
  });
1542
- }
1543
- /**
1544
- * Verifies the tokens received from the auth server.
1545
- * Validates the JWT against the JWKS.
1546
- * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
1547
- * @param tokens
1548
- */
1549
- verifyTokens(tokens) {
1550
- return __awaiter(this, void 0, void 0, function* () {
1551
- const token = tokens.access_token;
1552
- // Verify token has not expired
1553
- const tokenPayload = parseJWTPayload(token);
1554
- if (Date.now() >= tokenPayload.exp * 1000) {
1555
- this.clear();
1556
- return Promise.reject('Token expired');
1537
+ });
1538
+ }, _MedplumClient_startPkce = function _MedplumClient_startPkce() {
1539
+ return __awaiter(this, void 0, void 0, function* () {
1540
+ const pkceState = getRandomString();
1541
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('pkceState', pkceState);
1542
+ const codeVerifier = getRandomString();
1543
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('codeVerifier', codeVerifier);
1544
+ const arrayHash = yield encryptSHA256(codeVerifier);
1545
+ const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
1546
+ __classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('codeChallenge', codeChallenge);
1547
+ });
1548
+ }, _MedplumClient_requestAuthorization = function _MedplumClient_requestAuthorization() {
1549
+ return __awaiter(this, void 0, void 0, function* () {
1550
+ if (!__classPrivateFieldGet(this, _MedplumClient_authorizeUrl, "f")) {
1551
+ throw new Error('Missing authorize URL');
1552
+ }
1553
+ __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
1554
+ window.location.assign(__classPrivateFieldGet(this, _MedplumClient_authorizeUrl, "f") +
1555
+ '?response_type=code' +
1556
+ '&state=' +
1557
+ encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('pkceState')) +
1558
+ '&client_id=' +
1559
+ encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_clientId, "f")) +
1560
+ '&redirect_uri=' +
1561
+ encodeURIComponent(getBaseUrl()) +
1562
+ '&scope=' +
1563
+ encodeURIComponent(DEFAULT_SCOPE) +
1564
+ '&code_challenge_method=S256' +
1565
+ '&code_challenge=' +
1566
+ encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeChallenge')));
1567
+ });
1568
+ }, _MedplumClient_refresh = function _MedplumClient_refresh() {
1569
+ return __awaiter(this, void 0, void 0, function* () {
1570
+ if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
1571
+ return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
1572
+ }
1573
+ if (!__classPrivateFieldGet(this, _MedplumClient_refreshToken, "f")) {
1574
+ this.clear();
1575
+ return Promise.reject('Invalid refresh token');
1576
+ }
1577
+ __classPrivateFieldSet(this, _MedplumClient_refreshPromise, __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, 'grant_type=refresh_token' +
1578
+ '&client_id=' +
1579
+ encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_clientId, "f")) +
1580
+ '&refresh_token=' +
1581
+ encodeURIComponent(__classPrivateFieldGet(this, _MedplumClient_refreshToken, "f"))), "f");
1582
+ yield __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
1583
+ });
1584
+ }, _MedplumClient_fetchTokens = function _MedplumClient_fetchTokens(formBody) {
1585
+ return __awaiter(this, void 0, void 0, function* () {
1586
+ if (!__classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f")) {
1587
+ return Promise.reject('Missing token URL');
1588
+ }
1589
+ return __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f"), {
1590
+ method: 'POST',
1591
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1592
+ body: formBody,
1593
+ })
1594
+ .then((response) => {
1595
+ if (!response.ok) {
1596
+ return Promise.reject('Failed to fetch tokens');
1557
1597
  }
1558
- // Verify app_client_id
1559
- if (this.clientId && tokenPayload.client_id !== this.clientId) {
1560
- this.clear();
1561
- return Promise.reject('Token was not issued for this audience');
1598
+ return response.json();
1599
+ })
1600
+ .then((tokens) => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens))
1601
+ .then(() => this.getProfile());
1602
+ });
1603
+ }, _MedplumClient_verifyTokens = function _MedplumClient_verifyTokens(tokens) {
1604
+ return __awaiter(this, void 0, void 0, function* () {
1605
+ const token = tokens.access_token;
1606
+ // Verify token has not expired
1607
+ const tokenPayload = parseJWTPayload(token);
1608
+ if (Date.now() >= tokenPayload.exp * 1000) {
1609
+ this.clear();
1610
+ return Promise.reject('Token expired');
1611
+ }
1612
+ // Verify app_client_id
1613
+ if (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") && tokenPayload.client_id !== __classPrivateFieldGet(this, _MedplumClient_clientId, "f")) {
1614
+ this.clear();
1615
+ return Promise.reject('Token was not issued for this audience');
1616
+ }
1617
+ yield this.setActiveLogin({
1618
+ accessToken: token,
1619
+ refreshToken: tokens.refresh_token,
1620
+ project: tokens.project,
1621
+ profile: tokens.profile,
1622
+ });
1623
+ });
1624
+ }, _MedplumClient_setupStorageListener = function _MedplumClient_setupStorageListener() {
1625
+ try {
1626
+ window.addEventListener('storage', (e) => {
1627
+ if (e.key === null || e.key === 'activeLogin') {
1628
+ // Storage events fire when different tabs make changes.
1629
+ // On storage clear (key === null) or activeLogin change (key === 'activeLogin')
1630
+ // Refresh the page to ensure the active login is up to date.
1631
+ window.location.reload();
1562
1632
  }
1563
- yield this.setActiveLogin({
1564
- accessToken: token,
1565
- refreshToken: tokens.refresh_token,
1566
- project: tokens.project,
1567
- profile: tokens.profile,
1568
- });
1569
1633
  });
1570
1634
  }
1571
- /**
1572
- * Sets up a listener for window storage events.
1573
- * This synchronizes state across browser windows and browser tabs.
1574
- */
1575
- setupStorageListener() {
1576
- try {
1577
- window.addEventListener('storage', (e) => {
1578
- if (e.key === null || e.key === 'activeLogin') {
1579
- // Storage events fire when different tabs make changes.
1580
- // On storage clear (key === null) or activeLogin change (key === 'activeLogin')
1581
- // Refresh the page to ensure the active login is up to date.
1582
- window.location.reload();
1583
- }
1584
- });
1585
- }
1586
- catch (err) {
1587
- // Silently ignore if this environment does not support storage events
1588
- }
1635
+ catch (err) {
1636
+ // Silently ignore if this environment does not support storage events
1589
1637
  }
1590
- }
1638
+ };
1591
1639
  /**
1592
1640
  * Returns the base URL for the current page.
1593
1641
  */
@@ -1717,5 +1765,5 @@ function simplifyExpression(input) {
1717
1765
  return result;
1718
1766
  }
1719
1767
 
1720
- export { MedplumClient, OperationOutcomeError, Operator, PropertyType, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, capitalize, createReference, createSchema, created, deepEquals, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getDateProperty, getDisplayString, getExpressionForResourceType, getImageSrc, getPropertyDisplayName, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isOk, isProfileResource, notFound, notModified, parseSearchDefinition, stringify };
1768
+ export { MedplumClient, OperationOutcomeError, Operator, PropertyType, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, capitalize, createReference, createSchema, created, deepEquals, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getDateProperty, getDisplayString, getExpressionForResourceType, getImageSrc, getPropertyDisplayName, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isOk, isProfileResource, notFound, notModified, parseSearchDefinition, resolveId, stringify };
1721
1769
  //# sourceMappingURL=index.js.map