@medplum/core 2.0.14 → 2.0.16

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.
Files changed (61) hide show
  1. package/dist/cjs/index.cjs +1244 -1101
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.min.cjs +1 -1
  4. package/dist/esm/base64.mjs +33 -0
  5. package/dist/esm/base64.mjs.map +1 -0
  6. package/dist/esm/cache.mjs +17 -23
  7. package/dist/esm/cache.mjs.map +1 -1
  8. package/dist/esm/client.mjs +500 -413
  9. package/dist/esm/client.mjs.map +1 -1
  10. package/dist/esm/eventtarget.mjs +6 -11
  11. package/dist/esm/eventtarget.mjs.map +1 -1
  12. package/dist/esm/fhirlexer/parse.mjs +15 -23
  13. package/dist/esm/fhirlexer/parse.mjs.map +1 -1
  14. package/dist/esm/fhirlexer/tokenize.mjs +190 -180
  15. package/dist/esm/fhirlexer/tokenize.mjs.map +1 -1
  16. package/dist/esm/fhirmapper/parse.mjs +264 -252
  17. package/dist/esm/fhirmapper/parse.mjs.map +1 -1
  18. package/dist/esm/fhirmapper/tokenize.mjs +0 -1
  19. package/dist/esm/fhirmapper/tokenize.mjs.map +1 -1
  20. package/dist/esm/fhirpath/atoms.mjs +0 -1
  21. package/dist/esm/fhirpath/atoms.mjs.map +1 -1
  22. package/dist/esm/fhirpath/parse.mjs +0 -1
  23. package/dist/esm/fhirpath/parse.mjs.map +1 -1
  24. package/dist/esm/fhirpath/tokenize.mjs +0 -1
  25. package/dist/esm/fhirpath/tokenize.mjs.map +1 -1
  26. package/dist/esm/filter/parse.mjs +0 -2
  27. package/dist/esm/filter/parse.mjs.map +1 -1
  28. package/dist/esm/filter/tokenize.mjs +0 -1
  29. package/dist/esm/filter/tokenize.mjs.map +1 -1
  30. package/dist/esm/format.mjs +24 -15
  31. package/dist/esm/format.mjs.map +1 -1
  32. package/dist/esm/index.min.mjs +1 -1
  33. package/dist/esm/index.mjs +2 -2
  34. package/dist/esm/jwt.mjs +2 -9
  35. package/dist/esm/jwt.mjs.map +1 -1
  36. package/dist/esm/outcomes.mjs +15 -1
  37. package/dist/esm/outcomes.mjs.map +1 -1
  38. package/dist/esm/readablepromise.mjs +18 -23
  39. package/dist/esm/readablepromise.mjs.map +1 -1
  40. package/dist/esm/schema.mjs +146 -123
  41. package/dist/esm/schema.mjs.map +1 -1
  42. package/dist/esm/search/match.mjs +0 -2
  43. package/dist/esm/search/match.mjs.map +1 -1
  44. package/dist/esm/search/search.mjs +15 -9
  45. package/dist/esm/search/search.mjs.map +1 -1
  46. package/dist/esm/storage.mjs +13 -19
  47. package/dist/esm/storage.mjs.map +1 -1
  48. package/dist/types/base64.d.ts +14 -0
  49. package/dist/types/cache.d.ts +3 -1
  50. package/dist/types/client.d.ts +153 -1
  51. package/dist/types/eventtarget.d.ts +1 -1
  52. package/dist/types/fhirlexer/parse.d.ts +5 -2
  53. package/dist/types/fhirlexer/tokenize.d.ts +28 -1
  54. package/dist/types/format.d.ts +3 -1
  55. package/dist/types/outcomes.d.ts +1 -0
  56. package/dist/types/readablepromise.d.ts +4 -1
  57. package/dist/types/schema.d.ts +33 -1
  58. package/dist/types/storage.d.ts +2 -2
  59. package/package.json +1 -1
  60. package/dist/esm/node_modules/tslib/tslib.es6.mjs +0 -30
  61. package/dist/esm/node_modules/tslib/tslib.es6.mjs.map +0 -1
@@ -38,52 +38,20 @@
38
38
  return value;
39
39
  }
40
40
 
41
- /******************************************************************************
42
- Copyright (c) Microsoft Corporation.
43
-
44
- Permission to use, copy, modify, and/or distribute this software for any
45
- purpose with or without fee is hereby granted.
46
-
47
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
48
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
49
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
50
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
51
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
52
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
53
- PERFORMANCE OF THIS SOFTWARE.
54
- ***************************************************************************** */
55
-
56
- function __classPrivateFieldGet(receiver, state, kind, f) {
57
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
58
- 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");
59
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
60
- }
61
-
62
- function __classPrivateFieldSet(receiver, state, value, kind, f) {
63
- if (kind === "m") throw new TypeError("Private method is not writable");
64
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
65
- 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");
66
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
67
- }
68
-
69
- var _LRUCache_instances, _LRUCache_max, _LRUCache_cache, _LRUCache_first;
70
41
  /**
71
42
  * LRU cache (least recently used)
72
43
  * Source: https://stackoverflow.com/a/46432113
73
44
  */
74
45
  class LRUCache {
75
46
  constructor(max = 10) {
76
- _LRUCache_instances.add(this);
77
- _LRUCache_max.set(this, void 0);
78
- _LRUCache_cache.set(this, void 0);
79
- __classPrivateFieldSet(this, _LRUCache_max, max, "f");
80
- __classPrivateFieldSet(this, _LRUCache_cache, new Map(), "f");
47
+ this.max = max;
48
+ this.cache = new Map();
81
49
  }
82
50
  /**
83
51
  * Deletes all values from the cache.
84
52
  */
85
53
  clear() {
86
- __classPrivateFieldGet(this, _LRUCache_cache, "f").clear();
54
+ this.cache.clear();
87
55
  }
88
56
  /**
89
57
  * Returns the value for the given key.
@@ -91,10 +59,10 @@
91
59
  * @returns The value if found; undefined otherwise.
92
60
  */
93
61
  get(key) {
94
- const item = __classPrivateFieldGet(this, _LRUCache_cache, "f").get(key);
62
+ const item = this.cache.get(key);
95
63
  if (item) {
96
- __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key);
97
- __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, item);
64
+ this.cache.delete(key);
65
+ this.cache.set(key, item);
98
66
  }
99
67
  return item;
100
68
  }
@@ -104,33 +72,33 @@
104
72
  * @param val The value to set.
105
73
  */
106
74
  set(key, val) {
107
- if (__classPrivateFieldGet(this, _LRUCache_cache, "f").has(key)) {
108
- __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key);
75
+ if (this.cache.has(key)) {
76
+ this.cache.delete(key);
109
77
  }
110
- else if (__classPrivateFieldGet(this, _LRUCache_cache, "f").size >= __classPrivateFieldGet(this, _LRUCache_max, "f")) {
111
- __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(__classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_first).call(this));
78
+ else if (this.cache.size >= this.max) {
79
+ this.cache.delete(this.first());
112
80
  }
113
- __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, val);
81
+ this.cache.set(key, val);
114
82
  }
115
83
  /**
116
84
  * Deletes the value for the given key.
117
85
  * @param key The key to delete.
118
86
  */
119
87
  delete(key) {
120
- __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key);
88
+ this.cache.delete(key);
121
89
  }
122
90
  /**
123
91
  * Returns the list of all keys in the cache.
124
92
  * @returns The array of keys in the cache.
125
93
  */
126
94
  keys() {
127
- return __classPrivateFieldGet(this, _LRUCache_cache, "f").keys();
95
+ return this.cache.keys();
96
+ }
97
+ first() {
98
+ // This works because the Map class maintains ordered keys.
99
+ return this.cache.keys().next().value;
128
100
  }
129
101
  }
130
- _LRUCache_max = new WeakMap(), _LRUCache_cache = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_first = function _LRUCache_first() {
131
- // This works because the Map class maintains ordered keys.
132
- return __classPrivateFieldGet(this, _LRUCache_cache, "f").keys().next().value;
133
- };
134
102
 
135
103
  /**
136
104
  * Formats a FHIR Address as a string.
@@ -354,8 +322,9 @@
354
322
  return capitalize(builder.join(' ').trim());
355
323
  }
356
324
  /**
357
- * Returns a human-readable string for a FHIR Range datatype, taking into account comparators and one-sided ranges
325
+ * Returns a human-readable string for a FHIR Range datatype, taking into account one-sided ranges
358
326
  * @param range A FHIR Range element
327
+ * @param precision Number of decimal places to display in the rendered quantity values
359
328
  * @param exclusive If true, one-sided ranges will be rendered with the '>' or '<' bounds rather than '>=' or '<='
360
329
  * @returns A human-readable string representation of the Range
361
330
  */
@@ -363,33 +332,41 @@
363
332
  if (exclusive && precision === undefined) {
364
333
  throw new Error('Precision must be specified for exclusive ranges');
365
334
  }
366
- const low = range?.low && { ...range.low };
367
- const high = range?.high && { ...range.high };
368
- if (!range || (low?.value === undefined && high?.value === undefined)) {
335
+ // Extract high and low range endpoints, explicitly ignoring any comparator
336
+ // since Range uses SimpleQuantity variants (see http://www.hl7.org/fhir/datatypes.html#Range)
337
+ const low = range?.low && { ...range.low, comparator: undefined };
338
+ const high = range?.high && { ...range.high, comparator: undefined };
339
+ if (low?.value === undefined && high?.value === undefined) {
369
340
  return '';
370
341
  }
371
- if (range.low?.value !== undefined && range.high?.value === undefined) {
342
+ if (low?.value !== undefined && high?.value === undefined) {
343
+ // Lower bound only
372
344
  if (exclusive && precision !== undefined) {
373
- range.low.value = preciseDecrement(range.low.value, precision);
374
- return `> ${formatQuantity(range.low, precision)}`;
345
+ low.value = preciseDecrement(low.value, precision);
346
+ return `> ${formatQuantity(low, precision)}`;
375
347
  }
376
- return `>= ${formatQuantity(range.low, precision)}`;
348
+ return `>= ${formatQuantity(low, precision)}`;
377
349
  }
378
- if (range.low?.value === undefined && range.high?.value !== undefined) {
350
+ else if (low?.value === undefined && high?.value !== undefined) {
351
+ // Upper bound only
379
352
  if (exclusive && precision !== undefined) {
380
- range.high.value = preciseIncrement(range.high.value, precision);
381
- return `< ${formatQuantity(range.high, precision)}`;
353
+ high.value = preciseIncrement(high.value, precision);
354
+ return `< ${formatQuantity(high, precision)}`;
382
355
  }
383
- return `<= ${formatQuantity(range.high, precision)}`;
356
+ return `<= ${formatQuantity(high, precision)}`;
384
357
  }
385
- if (low?.unit === high?.unit) {
386
- delete low?.unit;
358
+ else {
359
+ // Double-sided range
360
+ if (low?.unit === high?.unit) {
361
+ delete low?.unit; // Format like "X - Y units" instead of "X units - Y units"
362
+ }
363
+ return `${formatQuantity(low, precision)} - ${formatQuantity(high, precision)}`;
387
364
  }
388
- return `${formatQuantity(low, precision)} - ${formatQuantity(high, precision)}`;
389
365
  }
390
366
  /**
391
367
  * Returns a human-readable string for a FHIR Quantity datatype, taking into account units and comparators
392
368
  * @param quantity A FHIR Quantity element
369
+ * @param precision Number of decimal places to display in the rendered quantity values
393
370
  * @returns A human-readable string representation of the Quantity
394
371
  */
395
372
  function formatQuantity(quantity, precision) {
@@ -1141,20 +1118,18 @@
1141
1118
  /*
1142
1119
  * Based on: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
1143
1120
  */
1144
- var _EventTarget_listeners;
1145
1121
  class EventTarget {
1146
1122
  constructor() {
1147
- _EventTarget_listeners.set(this, void 0);
1148
- __classPrivateFieldSet(this, _EventTarget_listeners, {}, "f");
1123
+ this.listeners = {};
1149
1124
  }
1150
1125
  addEventListener(type, callback) {
1151
- if (!__classPrivateFieldGet(this, _EventTarget_listeners, "f")[type]) {
1152
- __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type] = [];
1126
+ if (!this.listeners[type]) {
1127
+ this.listeners[type] = [];
1153
1128
  }
1154
- __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type].push(callback);
1129
+ this.listeners[type].push(callback);
1155
1130
  }
1156
1131
  removeEventListeneer(type, callback) {
1157
- const array = __classPrivateFieldGet(this, _EventTarget_listeners, "f")[type];
1132
+ const array = this.listeners[type];
1158
1133
  if (!array) {
1159
1134
  return;
1160
1135
  }
@@ -1166,14 +1141,44 @@
1166
1141
  }
1167
1142
  }
1168
1143
  dispatchEvent(event) {
1169
- const array = __classPrivateFieldGet(this, _EventTarget_listeners, "f")[event.type];
1144
+ const array = this.listeners[event.type];
1170
1145
  if (array) {
1171
1146
  array.forEach((listener) => listener.call(this, event));
1172
1147
  }
1173
1148
  return !event.defaultPrevented;
1174
1149
  }
1175
1150
  }
1176
- _EventTarget_listeners = new WeakMap();
1151
+
1152
+ /**
1153
+ * Decodes a base64 string.
1154
+ * Handles both browser and Node environments.
1155
+ * @param data The base-64 encoded input string.
1156
+ * @returns The decoded string.
1157
+ */
1158
+ function decodeBase64(data) {
1159
+ if (typeof window !== 'undefined') {
1160
+ return window.atob(data);
1161
+ }
1162
+ if (typeof Buffer !== 'undefined') {
1163
+ return Buffer.from(data, 'base64').toString('binary');
1164
+ }
1165
+ throw new Error('Unable to decode base64');
1166
+ }
1167
+ /**
1168
+ * Encodes a base64 string.
1169
+ * Handles both browser and Node environments.
1170
+ * @param data The unencoded input string.
1171
+ * @returns The base-64 encoded string.
1172
+ */
1173
+ function encodeBase64(data) {
1174
+ if (typeof window !== 'undefined') {
1175
+ return window.btoa(data);
1176
+ }
1177
+ if (typeof Buffer !== 'undefined') {
1178
+ return Buffer.from(data, 'binary').toString('base64');
1179
+ }
1180
+ throw new Error('Unable to encode base64');
1181
+ }
1177
1182
 
1178
1183
  /**
1179
1184
  * Decodes a section of a JWT.
@@ -1190,15 +1195,6 @@
1190
1195
  const jsonPayload = decodeURIComponent(uriEncodedPayload);
1191
1196
  return JSON.parse(jsonPayload);
1192
1197
  }
1193
- function decodeBase64(data) {
1194
- if (typeof window !== 'undefined') {
1195
- return window.atob(data);
1196
- }
1197
- if (typeof Buffer !== 'undefined') {
1198
- return Buffer.from(data, 'base64').toString('binary');
1199
- }
1200
- throw new Error('Unable to decode base64');
1201
- }
1202
1198
  /**
1203
1199
  * Parses the JWT payload.
1204
1200
  * @param token JWT token
@@ -1216,6 +1212,7 @@
1216
1212
  const UNAUTHORIZED_ID = 'unauthorized';
1217
1213
  const FORBIDDEN_ID = 'forbidden';
1218
1214
  const TOO_MANY_REQUESTS_ID = 'too-many-requests';
1215
+ const ACCEPTED_ID = 'accepted';
1219
1216
  const allOk = {
1220
1217
  resourceType: 'OperationOutcome',
1221
1218
  id: OK_ID,
@@ -1320,6 +1317,19 @@
1320
1317
  },
1321
1318
  ],
1322
1319
  };
1320
+ const accepted = {
1321
+ resourceType: 'OperationOutcome',
1322
+ id: ACCEPTED_ID,
1323
+ issue: [
1324
+ {
1325
+ severity: 'information',
1326
+ code: 'informational',
1327
+ details: {
1328
+ text: 'Accepted',
1329
+ },
1330
+ },
1331
+ ],
1332
+ };
1323
1333
  function badRequest(details, expression) {
1324
1334
  return {
1325
1335
  resourceType: 'OperationOutcome',
@@ -1460,7 +1470,7 @@
1460
1470
  return strs.length > 0 ? strs.join('; ') : 'Unknown error';
1461
1471
  }
1462
1472
 
1463
- var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_response, _ReadablePromise_error, _a;
1473
+ var _a;
1464
1474
  /**
1465
1475
  * The ReadablePromise class wraps a request promise suitable for React Suspense.
1466
1476
  * See: https://blog.logrocket.com/react-suspense-data-fetching/#wrappromise-js
@@ -1469,33 +1479,30 @@
1469
1479
  class ReadablePromise {
1470
1480
  constructor(requestPromise) {
1471
1481
  this[_a] = 'ReadablePromise';
1472
- _ReadablePromise_suspender.set(this, void 0);
1473
- _ReadablePromise_status.set(this, 'pending');
1474
- _ReadablePromise_response.set(this, void 0);
1475
- _ReadablePromise_error.set(this, void 0);
1476
- __classPrivateFieldSet(this, _ReadablePromise_suspender, requestPromise.then((res) => {
1477
- __classPrivateFieldSet(this, _ReadablePromise_status, 'success', "f");
1478
- __classPrivateFieldSet(this, _ReadablePromise_response, res, "f");
1482
+ this.status = 'pending';
1483
+ this.suspender = requestPromise.then((res) => {
1484
+ this.status = 'success';
1485
+ this.response = res;
1479
1486
  return res;
1480
1487
  }, (err) => {
1481
- __classPrivateFieldSet(this, _ReadablePromise_status, 'error', "f");
1482
- __classPrivateFieldSet(this, _ReadablePromise_error, err, "f");
1488
+ this.status = 'error';
1489
+ this.error = err;
1483
1490
  throw err;
1484
- }), "f");
1491
+ });
1485
1492
  }
1486
1493
  /**
1487
1494
  * Returns true if the promise is pending.
1488
1495
  * @returns True if the Promise is pending.
1489
1496
  */
1490
1497
  isPending() {
1491
- return __classPrivateFieldGet(this, _ReadablePromise_status, "f") === 'pending';
1498
+ return this.status === 'pending';
1492
1499
  }
1493
1500
  /**
1494
1501
  * Returns true if the promise resolved successfully.
1495
1502
  * @returns True if the Promise resolved successfully.
1496
1503
  */
1497
1504
  isOk() {
1498
- return __classPrivateFieldGet(this, _ReadablePromise_status, "f") === 'success';
1505
+ return this.status === 'success';
1499
1506
  }
1500
1507
  /**
1501
1508
  * Attempts to read the value of the promise.
@@ -1505,13 +1512,13 @@
1505
1512
  * @returns The resolved value of the Promise.
1506
1513
  */
1507
1514
  read() {
1508
- switch (__classPrivateFieldGet(this, _ReadablePromise_status, "f")) {
1515
+ switch (this.status) {
1509
1516
  case 'pending':
1510
- throw __classPrivateFieldGet(this, _ReadablePromise_suspender, "f");
1517
+ throw this.suspender;
1511
1518
  case 'error':
1512
- throw __classPrivateFieldGet(this, _ReadablePromise_error, "f");
1519
+ throw this.error;
1513
1520
  default:
1514
- return __classPrivateFieldGet(this, _ReadablePromise_response, "f");
1521
+ return this.response;
1515
1522
  }
1516
1523
  }
1517
1524
  /**
@@ -1521,7 +1528,7 @@
1521
1528
  * @returns A Promise for the completion of which ever callback is executed.
1522
1529
  */
1523
1530
  then(onfulfilled, onrejected) {
1524
- return __classPrivateFieldGet(this, _ReadablePromise_suspender, "f").then(onfulfilled, onrejected);
1531
+ return this.suspender.then(onfulfilled, onrejected);
1525
1532
  }
1526
1533
  /**
1527
1534
  * Attaches a callback for only the rejection of the Promise.
@@ -1529,7 +1536,7 @@
1529
1536
  * @returns A Promise for the completion of the callback.
1530
1537
  */
1531
1538
  catch(onrejected) {
1532
- return __classPrivateFieldGet(this, _ReadablePromise_suspender, "f").catch(onrejected);
1539
+ return this.suspender.catch(onrejected);
1533
1540
  }
1534
1541
  /**
1535
1542
  * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
@@ -1538,12 +1545,11 @@
1538
1545
  * @returns A Promise for the completion of the callback.
1539
1546
  */
1540
1547
  finally(onfinally) {
1541
- return __classPrivateFieldGet(this, _ReadablePromise_suspender, "f").finally(onfinally);
1548
+ return this.suspender.finally(onfinally);
1542
1549
  }
1543
1550
  }
1544
- _ReadablePromise_suspender = new WeakMap(), _ReadablePromise_status = new WeakMap(), _ReadablePromise_response = new WeakMap(), _ReadablePromise_error = new WeakMap(), _a = Symbol.toStringTag;
1551
+ _a = Symbol.toStringTag;
1545
1552
 
1546
- var _ClientStorage_storage, _MemoryStorage_data;
1547
1553
  /**
1548
1554
  * The ClientStorage class is a utility class for storing strings and objects.
1549
1555
  *
@@ -1553,21 +1559,20 @@
1553
1559
  */
1554
1560
  class ClientStorage {
1555
1561
  constructor() {
1556
- _ClientStorage_storage.set(this, void 0);
1557
- __classPrivateFieldSet(this, _ClientStorage_storage, typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage(), "f");
1562
+ this.storage = typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage();
1558
1563
  }
1559
1564
  clear() {
1560
- __classPrivateFieldGet(this, _ClientStorage_storage, "f").clear();
1565
+ this.storage.clear();
1561
1566
  }
1562
1567
  getString(key) {
1563
- return __classPrivateFieldGet(this, _ClientStorage_storage, "f").getItem(key) || undefined;
1568
+ return this.storage.getItem(key) || undefined;
1564
1569
  }
1565
1570
  setString(key, value) {
1566
1571
  if (value) {
1567
- __classPrivateFieldGet(this, _ClientStorage_storage, "f").setItem(key, value);
1572
+ this.storage.setItem(key, value);
1568
1573
  }
1569
1574
  else {
1570
- __classPrivateFieldGet(this, _ClientStorage_storage, "f").removeItem(key);
1575
+ this.storage.removeItem(key);
1571
1576
  }
1572
1577
  }
1573
1578
  getObject(key) {
@@ -1578,58 +1583,55 @@
1578
1583
  this.setString(key, value ? stringify(value) : undefined);
1579
1584
  }
1580
1585
  }
1581
- _ClientStorage_storage = new WeakMap();
1582
1586
  /**
1583
1587
  * The MemoryStorage class is a minimal in-memory implementation of the Storage interface.
1584
1588
  */
1585
1589
  class MemoryStorage {
1586
1590
  constructor() {
1587
- _MemoryStorage_data.set(this, void 0);
1588
- __classPrivateFieldSet(this, _MemoryStorage_data, new Map(), "f");
1591
+ this.data = new Map();
1589
1592
  }
1590
1593
  /**
1591
1594
  * Returns the number of key/value pairs.
1592
1595
  */
1593
1596
  get length() {
1594
- return __classPrivateFieldGet(this, _MemoryStorage_data, "f").size;
1597
+ return this.data.size;
1595
1598
  }
1596
1599
  /**
1597
1600
  * Removes all key/value pairs, if there are any.
1598
1601
  */
1599
1602
  clear() {
1600
- __classPrivateFieldGet(this, _MemoryStorage_data, "f").clear();
1603
+ this.data.clear();
1601
1604
  }
1602
1605
  /**
1603
1606
  * Returns the current value associated with the given key, or null if the given key does not exist.
1604
1607
  */
1605
1608
  getItem(key) {
1606
- return __classPrivateFieldGet(this, _MemoryStorage_data, "f").get(key) ?? null;
1609
+ return this.data.get(key) ?? null;
1607
1610
  }
1608
1611
  /**
1609
1612
  * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
1610
1613
  */
1611
1614
  setItem(key, value) {
1612
1615
  if (value) {
1613
- __classPrivateFieldGet(this, _MemoryStorage_data, "f").set(key, value);
1616
+ this.data.set(key, value);
1614
1617
  }
1615
1618
  else {
1616
- __classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
1619
+ this.data.delete(key);
1617
1620
  }
1618
1621
  }
1619
1622
  /**
1620
1623
  * Removes the key/value pair with the given key, if a key/value pair with the given key exists.
1621
1624
  */
1622
1625
  removeItem(key) {
1623
- __classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
1626
+ this.data.delete(key);
1624
1627
  }
1625
1628
  /**
1626
1629
  * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.
1627
1630
  */
1628
1631
  key(index) {
1629
- return Array.from(__classPrivateFieldGet(this, _MemoryStorage_data, "f").keys())[index];
1632
+ return Array.from(this.data.keys())[index];
1630
1633
  }
1631
1634
  }
1632
- _MemoryStorage_data = new WeakMap();
1633
1635
 
1634
1636
  var types = {
1635
1637
  Element: {
@@ -6402,9 +6404,7 @@
6402
6404
  const globalSchema = baseSchema;
6403
6405
 
6404
6406
  // PKCE auth based on:
6405
- // https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
6406
- var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_exchangeUrl, _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;
6407
- const MEDPLUM_VERSION = "2.0.14-8c7457fd";
6407
+ const MEDPLUM_VERSION = "2.0.16-816ad9bf";
6408
6408
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
6409
6409
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
6410
6410
  const DEFAULT_CACHE_TIME = 60000; // 60 seconds
@@ -6412,6 +6412,35 @@
6412
6412
  const FHIR_CONTENT_TYPE = 'application/fhir+json';
6413
6413
  const PATCH_CONTENT_TYPE = 'application/json-patch+json';
6414
6414
  const system = { resourceType: 'Device', id: 'system', deviceName: [{ name: 'System' }] };
6415
+ /**
6416
+ * OAuth 2.0 Grant Type Identifiers
6417
+ * Standard identifiers defined here: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#name-grant-types
6418
+ * Token exchange extension defined here: https://datatracker.ietf.org/doc/html/rfc8693
6419
+ */
6420
+ exports.OAuthGrantType = void 0;
6421
+ (function (OAuthGrantType) {
6422
+ OAuthGrantType["ClientCredentials"] = "client_credentials";
6423
+ OAuthGrantType["AuthorizationCode"] = "authorization_code";
6424
+ OAuthGrantType["RefreshToken"] = "refresh_token";
6425
+ OAuthGrantType["TokenExchange"] = "urn:ietf:params:oauth:grant-type:token-exchange";
6426
+ })(exports.OAuthGrantType || (exports.OAuthGrantType = {}));
6427
+ /**
6428
+ * OAuth 2.0 Token Type Identifiers
6429
+ * See: https://datatracker.ietf.org/doc/html/rfc8693#name-token-type-identifiers
6430
+ */
6431
+ exports.OAuthTokenType = void 0;
6432
+ (function (OAuthTokenType) {
6433
+ /** Indicates that the token is an OAuth 2.0 access token issued by the given authorization server. */
6434
+ OAuthTokenType["AccessToken"] = "urn:ietf:params:oauth:token-type:access_token";
6435
+ /** Indicates that the token is an OAuth 2.0 refresh token issued by the given authorization server. */
6436
+ OAuthTokenType["RefreshToken"] = "urn:ietf:params:oauth:token-type:refresh_token";
6437
+ /** Indicates that the token is an ID Token as defined in Section 2 of [OpenID.Core]. */
6438
+ OAuthTokenType["IdToken"] = "urn:ietf:params:oauth:token-type:id_token";
6439
+ /** Indicates that the token is a base64url-encoded SAML 1.1 [OASIS.saml-core-1.1] assertion. */
6440
+ OAuthTokenType["Saml1Token"] = "urn:ietf:params:oauth:token-type:saml1";
6441
+ /** Indicates that the token is a base64url-encoded SAML 2.0 [OASIS.saml-core-2.0-os] assertion. */
6442
+ OAuthTokenType["Saml2Token"] = "urn:ietf:params:oauth:token-type:saml2";
6443
+ })(exports.OAuthTokenType || (exports.OAuthTokenType = {}));
6415
6444
  /**
6416
6445
  * The MedplumClient class provides a client for the Medplum FHIR server.
6417
6446
  *
@@ -6467,57 +6496,43 @@
6467
6496
  class MedplumClient extends EventTarget {
6468
6497
  constructor(options) {
6469
6498
  super();
6470
- _MedplumClient_instances.add(this);
6471
- _MedplumClient_fetch.set(this, void 0);
6472
- _MedplumClient_createPdf.set(this, void 0);
6473
- _MedplumClient_storage.set(this, void 0);
6474
- _MedplumClient_requestCache.set(this, void 0);
6475
- _MedplumClient_cacheTime.set(this, void 0);
6476
- _MedplumClient_baseUrl.set(this, void 0);
6477
- _MedplumClient_fhirBaseUrl.set(this, void 0);
6478
- _MedplumClient_authorizeUrl.set(this, void 0);
6479
- _MedplumClient_tokenUrl.set(this, void 0);
6480
- _MedplumClient_logoutUrl.set(this, void 0);
6481
- _MedplumClient_exchangeUrl.set(this, void 0);
6482
- _MedplumClient_onUnauthenticated.set(this, void 0);
6483
- _MedplumClient_autoBatchTime.set(this, void 0);
6484
- _MedplumClient_autoBatchQueue.set(this, void 0);
6485
- _MedplumClient_clientId.set(this, void 0);
6486
- _MedplumClient_clientSecret.set(this, void 0);
6487
- _MedplumClient_autoBatchTimerId.set(this, void 0);
6488
- _MedplumClient_accessToken.set(this, void 0);
6489
- _MedplumClient_refreshToken.set(this, void 0);
6490
- _MedplumClient_refreshPromise.set(this, void 0);
6491
- _MedplumClient_profilePromise.set(this, void 0);
6492
- _MedplumClient_profile.set(this, void 0);
6493
- _MedplumClient_config.set(this, void 0);
6494
6499
  if (options?.baseUrl) {
6495
6500
  if (!options.baseUrl.startsWith('http')) {
6496
6501
  throw new Error('Base URL must start with http or https');
6497
6502
  }
6498
6503
  }
6499
- __classPrivateFieldSet(this, _MedplumClient_fetch, options?.fetch || getDefaultFetch(), "f");
6500
- __classPrivateFieldSet(this, _MedplumClient_storage, options?.storage || new ClientStorage(), "f");
6501
- __classPrivateFieldSet(this, _MedplumClient_createPdf, options?.createPdf, "f");
6502
- __classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
6503
- __classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
6504
- __classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
6505
- __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + (ensureTrailingSlash(options?.fhirUrlPath) || 'fhir/R4/'), "f");
6506
- __classPrivateFieldSet(this, _MedplumClient_clientId, options?.clientId || '', "f");
6507
- __classPrivateFieldSet(this, _MedplumClient_authorizeUrl, options?.authorizeUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
6508
- __classPrivateFieldSet(this, _MedplumClient_tokenUrl, options?.tokenUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
6509
- __classPrivateFieldSet(this, _MedplumClient_logoutUrl, options?.logoutUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/logout', "f");
6510
- __classPrivateFieldSet(this, _MedplumClient_exchangeUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'auth/exchange', "f");
6511
- __classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options?.onUnauthenticated, "f");
6512
- __classPrivateFieldSet(this, _MedplumClient_autoBatchTime, options?.autoBatchTime ?? 0, "f");
6513
- __classPrivateFieldSet(this, _MedplumClient_autoBatchQueue, [], "f");
6504
+ this.fetch = options?.fetch || getDefaultFetch();
6505
+ this.storage = options?.storage || new ClientStorage();
6506
+ this.createPdfImpl = options?.createPdf;
6507
+ this.baseUrl = ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL;
6508
+ this.fhirBaseUrl = this.baseUrl + (ensureTrailingSlash(options?.fhirUrlPath) || 'fhir/R4/');
6509
+ this.clientId = options?.clientId || '';
6510
+ this.authorizeUrl = options?.authorizeUrl || this.baseUrl + 'oauth2/authorize';
6511
+ this.tokenUrl = options?.tokenUrl || this.baseUrl + 'oauth2/token';
6512
+ this.logoutUrl = options?.logoutUrl || this.baseUrl + 'oauth2/logout';
6513
+ this.onUnauthenticated = options?.onUnauthenticated;
6514
+ this.cacheTime = options?.cacheTime ?? DEFAULT_CACHE_TIME;
6515
+ if (this.cacheTime > 0) {
6516
+ this.requestCache = new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE);
6517
+ }
6518
+ else {
6519
+ this.requestCache = undefined;
6520
+ }
6521
+ if (options?.autoBatchTime) {
6522
+ this.autoBatchTime = options?.autoBatchTime ?? 0;
6523
+ this.autoBatchQueue = [];
6524
+ }
6525
+ else {
6526
+ this.autoBatchTime = 0;
6527
+ this.autoBatchQueue = undefined;
6528
+ }
6514
6529
  const activeLogin = this.getActiveLogin();
6515
6530
  if (activeLogin) {
6516
- __classPrivateFieldSet(this, _MedplumClient_accessToken, activeLogin.accessToken, "f");
6517
- __classPrivateFieldSet(this, _MedplumClient_refreshToken, activeLogin.refreshToken, "f");
6518
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this).catch(console.log);
6531
+ this.accessToken = activeLogin.accessToken;
6532
+ this.refreshToken = activeLogin.refreshToken;
6533
+ this.refreshProfile().catch(console.log);
6519
6534
  }
6520
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setupStorageListener).call(this);
6535
+ this.setupStorageListener();
6521
6536
  }
6522
6537
  /**
6523
6538
  * Returns the current base URL for all API requests.
@@ -6527,14 +6542,14 @@
6527
6542
  * @returns The current base URL for all API requests.
6528
6543
  */
6529
6544
  getBaseUrl() {
6530
- return __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f");
6545
+ return this.baseUrl;
6531
6546
  }
6532
6547
  /**
6533
6548
  * Clears all auth state including local storage and session storage.
6534
6549
  * @category Authentication
6535
6550
  */
6536
6551
  clear() {
6537
- __classPrivateFieldGet(this, _MedplumClient_storage, "f").clear();
6552
+ this.storage.clear();
6538
6553
  this.clearActiveLogin();
6539
6554
  }
6540
6555
  /**
@@ -6543,12 +6558,12 @@
6543
6558
  * @category Authentication
6544
6559
  */
6545
6560
  clearActiveLogin() {
6546
- __classPrivateFieldGet(this, _MedplumClient_storage, "f").setString('activeLogin', undefined);
6547
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").clear();
6548
- __classPrivateFieldSet(this, _MedplumClient_accessToken, undefined, "f");
6549
- __classPrivateFieldSet(this, _MedplumClient_refreshToken, undefined, "f");
6550
- __classPrivateFieldSet(this, _MedplumClient_profile, undefined, "f");
6551
- __classPrivateFieldSet(this, _MedplumClient_config, undefined, "f");
6561
+ this.storage.setString('activeLogin', undefined);
6562
+ this.requestCache?.clear();
6563
+ this.accessToken = undefined;
6564
+ this.refreshToken = undefined;
6565
+ this.profile = undefined;
6566
+ this.config = undefined;
6552
6567
  this.dispatchEvent({ type: 'change' });
6553
6568
  }
6554
6569
  /**
@@ -6558,7 +6573,7 @@
6558
6573
  */
6559
6574
  invalidateUrl(url) {
6560
6575
  url = url.toString();
6561
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").delete(url);
6576
+ this.requestCache?.delete(url);
6562
6577
  }
6563
6578
  /**
6564
6579
  * Invalidates all cached search results or cached requests for the given resourceType.
@@ -6566,10 +6581,12 @@
6566
6581
  * @param resourceType The resource type to invalidate.
6567
6582
  */
6568
6583
  invalidateSearches(resourceType) {
6569
- const url = 'fhir/R4/' + resourceType;
6570
- for (const key of __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").keys()) {
6571
- if (key.endsWith(url) || key.includes(url + '?')) {
6572
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").delete(key);
6584
+ const url = this.fhirBaseUrl + resourceType;
6585
+ if (this.requestCache) {
6586
+ for (const key of this.requestCache.keys()) {
6587
+ if (key.endsWith(url) || key.includes(url + '?')) {
6588
+ this.requestCache.delete(key);
6589
+ }
6573
6590
  }
6574
6591
  }
6575
6592
  }
@@ -6587,30 +6604,30 @@
6587
6604
  */
6588
6605
  get(url, options = {}) {
6589
6606
  url = url.toString();
6590
- const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, url, options);
6607
+ const cached = this.getCacheEntry(url, options);
6591
6608
  if (cached) {
6592
6609
  return cached.value;
6593
6610
  }
6594
6611
  let promise;
6595
- if (url.startsWith(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f")) && __classPrivateFieldGet(this, _MedplumClient_autoBatchTime, "f") > 0) {
6612
+ if (url.startsWith(this.fhirBaseUrl) && this.autoBatchQueue) {
6596
6613
  promise = new Promise((resolve, reject) => {
6597
- __classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f").push({
6614
+ this.autoBatchQueue.push({
6598
6615
  method: 'GET',
6599
- url: url.replace(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f"), ''),
6616
+ url: url.replace(this.fhirBaseUrl, ''),
6600
6617
  options,
6601
6618
  resolve,
6602
6619
  reject,
6603
6620
  });
6604
- if (!__classPrivateFieldGet(this, _MedplumClient_autoBatchTimerId, "f")) {
6605
- __classPrivateFieldSet(this, _MedplumClient_autoBatchTimerId, setTimeout(() => __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_executeAutoBatch).call(this), __classPrivateFieldGet(this, _MedplumClient_autoBatchTime, "f")), "f");
6621
+ if (!this.autoBatchTimerId) {
6622
+ this.autoBatchTimerId = setTimeout(() => this.executeAutoBatch(), this.autoBatchTime);
6606
6623
  }
6607
6624
  });
6608
6625
  }
6609
6626
  else {
6610
- promise = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'GET', url, options);
6627
+ promise = this.request('GET', url, options);
6611
6628
  }
6612
6629
  const readablePromise = new ReadablePromise(promise);
6613
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, url, readablePromise);
6630
+ this.setCacheEntry(url, readablePromise);
6614
6631
  return readablePromise;
6615
6632
  }
6616
6633
  /**
@@ -6630,13 +6647,13 @@
6630
6647
  post(url, body, contentType, options = {}) {
6631
6648
  url = url.toString();
6632
6649
  if (body) {
6633
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestBody).call(this, options, body);
6650
+ this.setRequestBody(options, body);
6634
6651
  }
6635
6652
  if (contentType) {
6636
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestContentType).call(this, options, contentType);
6653
+ this.setRequestContentType(options, contentType);
6637
6654
  }
6638
6655
  this.invalidateUrl(url);
6639
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'POST', url, options);
6656
+ return this.request('POST', url, options);
6640
6657
  }
6641
6658
  /**
6642
6659
  * Makes an HTTP PUT request to the specified URL.
@@ -6655,13 +6672,13 @@
6655
6672
  put(url, body, contentType, options = {}) {
6656
6673
  url = url.toString();
6657
6674
  if (body) {
6658
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestBody).call(this, options, body);
6675
+ this.setRequestBody(options, body);
6659
6676
  }
6660
6677
  if (contentType) {
6661
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestContentType).call(this, options, contentType);
6678
+ this.setRequestContentType(options, contentType);
6662
6679
  }
6663
6680
  this.invalidateUrl(url);
6664
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'PUT', url, options);
6681
+ return this.request('PUT', url, options);
6665
6682
  }
6666
6683
  /**
6667
6684
  * Makes an HTTP PATCH request to the specified URL.
@@ -6678,10 +6695,10 @@
6678
6695
  */
6679
6696
  patch(url, operations, options = {}) {
6680
6697
  url = url.toString();
6681
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestBody).call(this, options, operations);
6682
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setRequestContentType).call(this, options, PATCH_CONTENT_TYPE);
6698
+ this.setRequestBody(options, operations);
6699
+ this.setRequestContentType(options, PATCH_CONTENT_TYPE);
6683
6700
  this.invalidateUrl(url);
6684
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'PATCH', url, options);
6701
+ return this.request('PATCH', url, options);
6685
6702
  }
6686
6703
  /**
6687
6704
  * Makes an HTTP DELETE request to the specified URL.
@@ -6699,7 +6716,7 @@
6699
6716
  delete(url, options = {}) {
6700
6717
  url = url.toString();
6701
6718
  this.invalidateUrl(url);
6702
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, 'DELETE', url, options);
6719
+ return this.request('DELETE', url, options);
6703
6720
  }
6704
6721
  /**
6705
6722
  * Initiates a new user flow.
@@ -6751,7 +6768,7 @@
6751
6768
  async startLogin(loginRequest) {
6752
6769
  return this.post('auth/login', {
6753
6770
  ...(await this.ensureCodeChallenge(loginRequest)),
6754
- clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
6771
+ clientId: loginRequest.clientId ?? this.clientId,
6755
6772
  scope: loginRequest.scope,
6756
6773
  });
6757
6774
  }
@@ -6766,7 +6783,7 @@
6766
6783
  async startGoogleLogin(loginRequest) {
6767
6784
  return this.post('auth/google', {
6768
6785
  ...(await this.ensureCodeChallenge(loginRequest)),
6769
- clientId: loginRequest.clientId ?? __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
6786
+ clientId: loginRequest.clientId ?? this.clientId,
6770
6787
  scope: loginRequest.scope,
6771
6788
  });
6772
6789
  }
@@ -6790,7 +6807,7 @@
6790
6807
  * @category Authentication
6791
6808
  */
6792
6809
  async signOut() {
6793
- await this.post(__classPrivateFieldGet(this, _MedplumClient_logoutUrl, "f"), {});
6810
+ await this.post(this.logoutUrl, {});
6794
6811
  this.clear();
6795
6812
  }
6796
6813
  /**
@@ -6804,7 +6821,7 @@
6804
6821
  const urlParams = new URLSearchParams(window.location.search);
6805
6822
  const code = urlParams.get('code');
6806
6823
  if (!code) {
6807
- await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_requestAuthorization).call(this, loginParams);
6824
+ await this.requestAuthorization(loginParams);
6808
6825
  return undefined;
6809
6826
  }
6810
6827
  else {
@@ -6817,7 +6834,7 @@
6817
6834
  * @category Authentication
6818
6835
  */
6819
6836
  signOutWithRedirect() {
6820
- window.location.assign(__classPrivateFieldGet(this, _MedplumClient_logoutUrl, "f"));
6837
+ window.location.assign(this.logoutUrl);
6821
6838
  }
6822
6839
  /**
6823
6840
  * Initiates sign in with an external identity provider.
@@ -6838,26 +6855,16 @@
6838
6855
  * @category Authentication
6839
6856
  */
6840
6857
  async exchangeExternalAccessToken(token, clientId) {
6841
- clientId = clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f");
6858
+ clientId = clientId || this.clientId;
6842
6859
  if (!clientId) {
6843
6860
  throw new Error('MedplumClient is missing clientId');
6844
6861
  }
6845
- const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_exchangeUrl, "f"), {
6846
- method: 'POST',
6847
- headers: { 'Content-Type': 'application/json' },
6848
- body: JSON.stringify({
6849
- clientId: __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
6850
- externalAccessToken: token,
6851
- }),
6852
- credentials: 'include',
6853
- });
6854
- if (!response.ok) {
6855
- this.clearActiveLogin();
6856
- throw new Error('Failed to fetch tokens');
6857
- }
6858
- const tokens = await response.json();
6859
- await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens);
6860
- return this.getProfile();
6862
+ const formBody = new URLSearchParams();
6863
+ formBody.set('grant_type', exports.OAuthGrantType.TokenExchange);
6864
+ formBody.set('subject_token_type', exports.OAuthTokenType.AccessToken);
6865
+ formBody.set('client_id', clientId);
6866
+ formBody.set('subject_token', token);
6867
+ return this.fetchTokens(formBody);
6861
6868
  }
6862
6869
  /**
6863
6870
  * Builds the external identity provider redirect URI.
@@ -6885,7 +6892,7 @@
6885
6892
  * @returns The well-formed FHIR URL.
6886
6893
  */
6887
6894
  fhirUrl(...path) {
6888
- return new URL(__classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + path.join('/'));
6895
+ return new URL(this.fhirBaseUrl + path.join('/'));
6889
6896
  }
6890
6897
  /**
6891
6898
  * Builds a FHIR search URL from a search query or structured query object.
@@ -6953,7 +6960,7 @@
6953
6960
  search(resourceType, query, options = {}) {
6954
6961
  const url = this.fhirSearchUrl(resourceType, query);
6955
6962
  const cacheKey = url.toString() + '-search';
6956
- const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, options);
6963
+ const cached = this.getCacheEntry(cacheKey, options);
6957
6964
  if (cached) {
6958
6965
  return cached.value;
6959
6966
  }
@@ -6961,12 +6968,12 @@
6961
6968
  const bundle = await this.get(url, options);
6962
6969
  if (bundle.entry) {
6963
6970
  for (const entry of bundle.entry) {
6964
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_cacheResource).call(this, entry.resource);
6971
+ this.cacheResource(entry.resource);
6965
6972
  }
6966
6973
  }
6967
6974
  return bundle;
6968
6975
  })());
6969
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
6976
+ this.setCacheEntry(cacheKey, promise);
6970
6977
  return promise;
6971
6978
  }
6972
6979
  /**
@@ -6996,12 +7003,12 @@
6996
7003
  url.searchParams.set('_count', '1');
6997
7004
  url.searchParams.sort();
6998
7005
  const cacheKey = url.toString() + '-searchOne';
6999
- const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, options);
7006
+ const cached = this.getCacheEntry(cacheKey, options);
7000
7007
  if (cached) {
7001
7008
  return cached.value;
7002
7009
  }
7003
7010
  const promise = new ReadablePromise(this.search(resourceType, url.searchParams, options).then((b) => b.entry?.[0]?.resource));
7004
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
7011
+ this.setCacheEntry(cacheKey, promise);
7005
7012
  return promise;
7006
7013
  }
7007
7014
  /**
@@ -7029,12 +7036,12 @@
7029
7036
  searchResources(resourceType, query, options = {}) {
7030
7037
  const url = this.fhirSearchUrl(resourceType, query);
7031
7038
  const cacheKey = url.toString() + '-searchResources';
7032
- const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, options);
7039
+ const cached = this.getCacheEntry(cacheKey, options);
7033
7040
  if (cached) {
7034
7041
  return cached.value;
7035
7042
  }
7036
7043
  const promise = new ReadablePromise(this.search(resourceType, query, options).then((b) => b.entry?.map((e) => e.resource) ?? []));
7037
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
7044
+ this.setCacheEntry(cacheKey, promise);
7038
7045
  return promise;
7039
7046
  }
7040
7047
  /**
@@ -7095,7 +7102,7 @@
7095
7102
  * @returns The resource if it is available in the cache; undefined otherwise.
7096
7103
  */
7097
7104
  getCached(resourceType, id) {
7098
- const cached = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(this.fhirUrl(resourceType, id).toString())?.value;
7105
+ const cached = this.requestCache?.get(this.fhirUrl(resourceType, id).toString())?.value;
7099
7106
  return cached && cached.isOk() ? cached.read() : undefined;
7100
7107
  }
7101
7108
  /**
@@ -7197,7 +7204,7 @@
7197
7204
  return Promise.resolve(globalSchema);
7198
7205
  }
7199
7206
  const cacheKey = resourceType + '-requestSchema';
7200
- const cached = __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_getCacheEntry).call(this, cacheKey, undefined);
7207
+ const cached = this.getCacheEntry(cacheKey, undefined);
7201
7208
  if (cached) {
7202
7209
  return cached.value;
7203
7210
  }
@@ -7240,7 +7247,7 @@
7240
7247
  }
7241
7248
  return globalSchema;
7242
7249
  })());
7243
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
7250
+ this.setCacheEntry(cacheKey, promise);
7244
7251
  return promise;
7245
7252
  }
7246
7253
  /**
@@ -7438,7 +7445,7 @@
7438
7445
  };
7439
7446
  xhr.open('POST', url);
7440
7447
  xhr.withCredentials = true;
7441
- xhr.setRequestHeader('Authorization', 'Bearer ' + __classPrivateFieldGet(this, _MedplumClient_accessToken, "f"));
7448
+ xhr.setRequestHeader('Authorization', 'Bearer ' + this.accessToken);
7442
7449
  xhr.setRequestHeader('Cache-Control', 'no-cache, no-store, max-age=0');
7443
7450
  xhr.setRequestHeader('Content-Type', contentType);
7444
7451
  xhr.setRequestHeader('X-Medplum', 'extended');
@@ -7468,10 +7475,10 @@
7468
7475
  * @returns The result of the create operation.
7469
7476
  */
7470
7477
  async createPdf(docDefinition, filename, tableLayouts, fonts) {
7471
- if (!__classPrivateFieldGet(this, _MedplumClient_createPdf, "f")) {
7478
+ if (!this.createPdfImpl) {
7472
7479
  throw new Error('PDF creation not enabled');
7473
7480
  }
7474
- const blob = await __classPrivateFieldGet(this, _MedplumClient_createPdf, "f").call(this, docDefinition, tableLayouts, fonts);
7481
+ const blob = await this.createPdfImpl(docDefinition, tableLayouts, fonts);
7475
7482
  return this.createBinary(blob, filename, 'application/pdf');
7476
7483
  }
7477
7484
  /**
@@ -7549,7 +7556,7 @@
7549
7556
  // return result ?? resource;
7550
7557
  result = resource;
7551
7558
  }
7552
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_cacheResource).call(this, result);
7559
+ this.cacheResource(result);
7553
7560
  return result;
7554
7561
  }
7555
7562
  /**
@@ -7597,7 +7604,7 @@
7597
7604
  * @returns The result of the delete operation.
7598
7605
  */
7599
7606
  deleteResource(resourceType, id) {
7600
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_deleteCacheEntry).call(this, this.fhirUrl(resourceType, id).toString());
7607
+ this.deleteCacheEntry(this.fhirUrl(resourceType, id).toString());
7601
7608
  this.invalidateSearches(resourceType);
7602
7609
  return this.delete(this.fhirUrl(resourceType, id));
7603
7610
  }
@@ -7689,7 +7696,7 @@
7689
7696
  * @returns The FHIR batch/transaction response bundle.
7690
7697
  */
7691
7698
  executeBatch(bundle) {
7692
- return this.post('fhir/R4', bundle);
7699
+ return this.post(this.fhirBaseUrl.slice(0, -1), bundle);
7693
7700
  }
7694
7701
  /**
7695
7702
  * Sends an email using the Medplum Email API.
@@ -7801,61 +7808,80 @@
7801
7808
  * @returns The Login State
7802
7809
  */
7803
7810
  getActiveLogin() {
7804
- return __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('activeLogin');
7811
+ return this.storage.getObject('activeLogin');
7805
7812
  }
7806
7813
  /**
7807
7814
  * @category Authentication
7808
7815
  */
7809
7816
  async setActiveLogin(login) {
7810
7817
  this.clearActiveLogin();
7811
- __classPrivateFieldSet(this, _MedplumClient_accessToken, login.accessToken, "f");
7812
- __classPrivateFieldSet(this, _MedplumClient_refreshToken, login.refreshToken, "f");
7813
- __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('activeLogin', login);
7814
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addLogin).call(this, login);
7815
- __classPrivateFieldSet(this, _MedplumClient_refreshPromise, undefined, "f");
7816
- await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
7818
+ this.accessToken = login.accessToken;
7819
+ this.refreshToken = login.refreshToken;
7820
+ this.storage.setObject('activeLogin', login);
7821
+ this.addLogin(login);
7822
+ this.refreshPromise = undefined;
7823
+ await this.refreshProfile();
7817
7824
  }
7818
7825
  /**
7819
7826
  * Returns the current access token.
7820
7827
  * @category Authentication
7821
7828
  */
7822
7829
  getAccessToken() {
7823
- return __classPrivateFieldGet(this, _MedplumClient_accessToken, "f");
7830
+ return this.accessToken;
7824
7831
  }
7825
7832
  /**
7826
7833
  * Sets the current access token.
7827
7834
  * @category Authentication
7828
7835
  */
7829
7836
  setAccessToken(accessToken) {
7830
- __classPrivateFieldSet(this, _MedplumClient_accessToken, accessToken, "f");
7831
- __classPrivateFieldSet(this, _MedplumClient_refreshToken, undefined, "f");
7832
- __classPrivateFieldSet(this, _MedplumClient_profile, undefined, "f");
7833
- __classPrivateFieldSet(this, _MedplumClient_config, undefined, "f");
7837
+ this.accessToken = accessToken;
7838
+ this.refreshToken = undefined;
7839
+ this.profile = undefined;
7840
+ this.config = undefined;
7834
7841
  }
7835
7842
  /**
7836
7843
  * @category Authentication
7837
7844
  */
7838
7845
  getLogins() {
7839
- return __classPrivateFieldGet(this, _MedplumClient_storage, "f").getObject('logins') ?? [];
7846
+ return this.storage.getObject('logins') ?? [];
7847
+ }
7848
+ addLogin(newLogin) {
7849
+ const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
7850
+ logins.push(newLogin);
7851
+ this.storage.setObject('logins', logins);
7852
+ }
7853
+ async refreshProfile() {
7854
+ this.profilePromise = new Promise((resolve, reject) => {
7855
+ this.get('auth/me')
7856
+ .then((result) => {
7857
+ this.profilePromise = undefined;
7858
+ this.profile = result.profile;
7859
+ this.config = result.config;
7860
+ this.dispatchEvent({ type: 'change' });
7861
+ resolve(this.profile);
7862
+ })
7863
+ .catch(reject);
7864
+ });
7865
+ return this.profilePromise;
7840
7866
  }
7841
7867
  /**
7842
7868
  * @category Authentication
7843
7869
  */
7844
7870
  isLoading() {
7845
- return !!__classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
7871
+ return !!this.profilePromise;
7846
7872
  }
7847
7873
  /**
7848
7874
  * @category User Profile
7849
7875
  */
7850
7876
  getProfile() {
7851
- return __classPrivateFieldGet(this, _MedplumClient_profile, "f");
7877
+ return this.profile;
7852
7878
  }
7853
7879
  /**
7854
7880
  * @category User Profile
7855
7881
  */
7856
7882
  async getProfileAsync() {
7857
- if (__classPrivateFieldGet(this, _MedplumClient_profilePromise, "f")) {
7858
- await __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
7883
+ if (this.profilePromise) {
7884
+ await this.profilePromise;
7859
7885
  }
7860
7886
  return this.getProfile();
7861
7887
  }
@@ -7863,7 +7889,7 @@
7863
7889
  * @category User Profile
7864
7890
  */
7865
7891
  getUserConfiguration() {
7866
- return __classPrivateFieldGet(this, _MedplumClient_config, "f");
7892
+ return this.config;
7867
7893
  }
7868
7894
  /**
7869
7895
  * Downloads the URL as a blob.
@@ -7873,13 +7899,234 @@
7873
7899
  * @returns Promise to the response body as a blob.
7874
7900
  */
7875
7901
  async download(url, options = {}) {
7876
- if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
7877
- await __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
7902
+ if (this.refreshPromise) {
7903
+ await this.refreshPromise;
7878
7904
  }
7879
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addFetchOptionsDefaults).call(this, options);
7880
- const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url.toString(), options);
7905
+ this.addFetchOptionsDefaults(options);
7906
+ const response = await this.fetch(url.toString(), options);
7881
7907
  return response.blob();
7882
7908
  }
7909
+ //
7910
+ // Private helpers
7911
+ //
7912
+ /**
7913
+ * Returns the cache entry if available and not expired.
7914
+ * @param key The cache key to retrieve.
7915
+ * @param options Optional fetch options for cache settings.
7916
+ * @returns The cached entry if found.
7917
+ */
7918
+ getCacheEntry(key, options) {
7919
+ if (!this.requestCache || options?.cache === 'no-cache' || options?.cache === 'reload') {
7920
+ return undefined;
7921
+ }
7922
+ const entry = this.requestCache.get(key);
7923
+ if (!entry || entry.requestTime + this.cacheTime < Date.now()) {
7924
+ return undefined;
7925
+ }
7926
+ return entry;
7927
+ }
7928
+ /**
7929
+ * Adds a readable promise to the cache.
7930
+ * @param key The cache key to store.
7931
+ * @param value The readable promise to store.
7932
+ */
7933
+ setCacheEntry(key, value) {
7934
+ if (this.requestCache) {
7935
+ this.requestCache.set(key, { requestTime: Date.now(), value });
7936
+ }
7937
+ }
7938
+ /**
7939
+ * Adds a concrete value as the cache entry for the given resource.
7940
+ * This is used in cases where the resource is loaded indirectly.
7941
+ * For example, when a resource is loaded as part of a Bundle.
7942
+ * @param resource The resource to cache.
7943
+ */
7944
+ cacheResource(resource) {
7945
+ if (resource?.id) {
7946
+ this.setCacheEntry(this.fhirUrl(resource.resourceType, resource.id).toString(), new ReadablePromise(Promise.resolve(resource)));
7947
+ }
7948
+ }
7949
+ /**
7950
+ * Deletes a cache entry.
7951
+ * @param key The cache key to delete.
7952
+ */
7953
+ deleteCacheEntry(key) {
7954
+ if (this.requestCache) {
7955
+ this.requestCache.delete(key);
7956
+ }
7957
+ }
7958
+ /**
7959
+ * Makes an HTTP request.
7960
+ * @param {string} method
7961
+ * @param {string} url
7962
+ * @param {string=} contentType
7963
+ * @param {Object=} body
7964
+ */
7965
+ async request(method, url, options = {}) {
7966
+ if (this.refreshPromise) {
7967
+ await this.refreshPromise;
7968
+ }
7969
+ if (!url.startsWith('http')) {
7970
+ url = this.baseUrl + url;
7971
+ }
7972
+ options.method = method;
7973
+ this.addFetchOptionsDefaults(options);
7974
+ const response = await this.fetchWithRetry(url, options);
7975
+ if (response.status === 401) {
7976
+ // Refresh and try again
7977
+ return this.handleUnauthenticated(method, url, options);
7978
+ }
7979
+ if (response.status === 204 || response.status === 304) {
7980
+ // No content or change
7981
+ return undefined;
7982
+ }
7983
+ let obj = undefined;
7984
+ try {
7985
+ obj = await response.json();
7986
+ }
7987
+ catch (err) {
7988
+ console.error('Error parsing response', response.status, err);
7989
+ throw err;
7990
+ }
7991
+ if (response.status >= 400) {
7992
+ throw new OperationOutcomeError(normalizeOperationOutcome(obj));
7993
+ }
7994
+ return obj;
7995
+ }
7996
+ async fetchWithRetry(url, options) {
7997
+ const maxRetries = 3;
7998
+ const retryDelay = 200;
7999
+ let response = undefined;
8000
+ for (let retry = 0; retry < maxRetries; retry++) {
8001
+ response = (await this.fetch(url, options));
8002
+ if (response.status < 500) {
8003
+ return response;
8004
+ }
8005
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
8006
+ }
8007
+ return response;
8008
+ }
8009
+ /**
8010
+ * Executes a batch of requests that were automatically batched together.
8011
+ */
8012
+ async executeAutoBatch() {
8013
+ // Get the current queue
8014
+ const entries = [...this.autoBatchQueue];
8015
+ // Clear the queue
8016
+ this.autoBatchQueue.length = 0;
8017
+ // Clear the timer
8018
+ this.autoBatchTimerId = undefined;
8019
+ // If there is only one request in the batch, just execute it
8020
+ if (entries.length === 1) {
8021
+ const entry = entries[0];
8022
+ try {
8023
+ entry.resolve(await this.request(entry.method, this.fhirBaseUrl + entry.url, entry.options));
8024
+ }
8025
+ catch (err) {
8026
+ entry.reject(new OperationOutcomeError(normalizeOperationOutcome(err)));
8027
+ }
8028
+ return;
8029
+ }
8030
+ // Build the batch request
8031
+ const batch = {
8032
+ resourceType: 'Bundle',
8033
+ type: 'batch',
8034
+ entry: entries.map((e) => ({
8035
+ request: {
8036
+ method: e.method,
8037
+ url: e.url,
8038
+ },
8039
+ resource: e.options.body ? JSON.parse(e.options.body) : undefined,
8040
+ })),
8041
+ };
8042
+ // Execute the batch request
8043
+ const response = (await this.post(this.fhirBaseUrl.slice(0, -1), batch));
8044
+ // Process the response
8045
+ for (let i = 0; i < entries.length; i++) {
8046
+ const entry = entries[i];
8047
+ const responseEntry = response.entry?.[i];
8048
+ if (responseEntry?.response?.outcome && !isOk(responseEntry.response.outcome)) {
8049
+ entry.reject(new OperationOutcomeError(responseEntry.response.outcome));
8050
+ }
8051
+ else {
8052
+ entry.resolve(responseEntry?.resource);
8053
+ }
8054
+ }
8055
+ }
8056
+ /**
8057
+ * Adds default options to the fetch options.
8058
+ * @param options The options to add defaults to.
8059
+ */
8060
+ addFetchOptionsDefaults(options) {
8061
+ let headers = options.headers;
8062
+ if (!headers) {
8063
+ headers = {};
8064
+ options.headers = headers;
8065
+ }
8066
+ headers['X-Medplum'] = 'extended';
8067
+ if (options.body && !headers['Content-Type']) {
8068
+ headers['Content-Type'] = FHIR_CONTENT_TYPE;
8069
+ }
8070
+ if (this.accessToken) {
8071
+ headers['Authorization'] = 'Bearer ' + this.accessToken;
8072
+ }
8073
+ if (this.basicAuth) {
8074
+ headers['Authorization'] = 'Basic ' + this.basicAuth;
8075
+ }
8076
+ if (!options.cache) {
8077
+ options.cache = 'no-cache';
8078
+ }
8079
+ if (!options.credentials) {
8080
+ options.credentials = 'include';
8081
+ }
8082
+ }
8083
+ /**
8084
+ * Sets the "Content-Type" header on fetch options.
8085
+ * @param options The fetch options.
8086
+ * @param contentType The new content type to set.
8087
+ */
8088
+ setRequestContentType(options, contentType) {
8089
+ if (!options.headers) {
8090
+ options.headers = {};
8091
+ }
8092
+ const headers = options.headers;
8093
+ headers['Content-Type'] = contentType;
8094
+ }
8095
+ /**
8096
+ * Sets the body on fetch options.
8097
+ * @param options The fetch options.
8098
+ * @param data The new content body.
8099
+ */
8100
+ setRequestBody(options, data) {
8101
+ if (typeof data === 'string' ||
8102
+ (typeof Blob !== 'undefined' && data instanceof Blob) ||
8103
+ (typeof File !== 'undefined' && data instanceof File) ||
8104
+ (typeof Uint8Array !== 'undefined' && data instanceof Uint8Array)) {
8105
+ options.body = data;
8106
+ }
8107
+ else if (data) {
8108
+ options.body = JSON.stringify(data);
8109
+ }
8110
+ }
8111
+ /**
8112
+ * Handles an unauthenticated response from the server.
8113
+ * First, tries to refresh the access token and retry the request.
8114
+ * Otherwise, calls unauthenticated callbacks and rejects.
8115
+ * @param method The HTTP method of the original request.
8116
+ * @param url The URL of the original request.
8117
+ * @param contentType The content type of the original request.
8118
+ * @param body The body of the original request.
8119
+ */
8120
+ handleUnauthenticated(method, url, options) {
8121
+ if (this.refresh()) {
8122
+ return this.request(method, url, options);
8123
+ }
8124
+ this.clearActiveLogin();
8125
+ if (this.onUnauthenticated) {
8126
+ this.onUnauthenticated();
8127
+ }
8128
+ return Promise.reject(new Error('Unauthenticated'));
8129
+ }
7883
8130
  /**
7884
8131
  * Starts a new PKCE flow.
7885
8132
  * These PKCE values are stateful, and must survive redirects and page refreshes.
@@ -7895,6 +8142,23 @@
7895
8142
  sessionStorage.setItem('codeChallenge', codeChallenge);
7896
8143
  return { codeChallengeMethod: 'S256', codeChallenge };
7897
8144
  }
8145
+ /**
8146
+ * Redirects the user to the login screen for authorization.
8147
+ * Clears all auth state including local storage and session storage.
8148
+ * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
8149
+ */
8150
+ async requestAuthorization(loginParams) {
8151
+ const loginRequest = await this.ensureCodeChallenge(loginParams || {});
8152
+ const url = new URL(this.authorizeUrl);
8153
+ url.searchParams.set('response_type', 'code');
8154
+ url.searchParams.set('state', sessionStorage.getItem('pkceState'));
8155
+ url.searchParams.set('client_id', loginRequest.clientId || this.clientId);
8156
+ url.searchParams.set('redirect_uri', loginRequest.redirectUri || getWindowOrigin());
8157
+ url.searchParams.set('code_challenge_method', loginRequest.codeChallengeMethod);
8158
+ url.searchParams.set('code_challenge', loginRequest.codeChallenge);
8159
+ url.searchParams.set('scope', loginRequest.scope || 'openid profile');
8160
+ window.location.assign(url.toString());
8161
+ }
7898
8162
  /**
7899
8163
  * Processes an OAuth authorization code.
7900
8164
  * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
@@ -7904,9 +8168,9 @@
7904
8168
  */
7905
8169
  processCode(code, loginParams) {
7906
8170
  const formBody = new URLSearchParams();
7907
- formBody.set('grant_type', 'authorization_code');
8171
+ formBody.set('grant_type', exports.OAuthGrantType.AuthorizationCode);
7908
8172
  formBody.set('code', code);
7909
- formBody.set('client_id', loginParams?.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
8173
+ formBody.set('client_id', loginParams?.clientId || this.clientId);
7910
8174
  formBody.set('redirect_uri', loginParams?.redirectUri || getWindowOrigin());
7911
8175
  if (typeof sessionStorage !== 'undefined') {
7912
8176
  const codeVerifier = sessionStorage.getItem('codeVerifier');
@@ -7914,7 +8178,29 @@
7914
8178
  formBody.set('code_verifier', codeVerifier);
7915
8179
  }
7916
8180
  }
7917
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
8181
+ return this.fetchTokens(formBody);
8182
+ }
8183
+ /**
8184
+ * Tries to refresh the auth tokens.
8185
+ * See: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
8186
+ */
8187
+ refresh() {
8188
+ if (this.refreshPromise) {
8189
+ return this.refreshPromise;
8190
+ }
8191
+ if (this.refreshToken) {
8192
+ const formBody = new URLSearchParams();
8193
+ formBody.set('grant_type', exports.OAuthGrantType.RefreshToken);
8194
+ formBody.set('client_id', this.clientId);
8195
+ formBody.set('refresh_token', this.refreshToken);
8196
+ this.refreshPromise = this.fetchTokens(formBody);
8197
+ return this.refreshPromise;
8198
+ }
8199
+ if (this.clientId && this.clientSecret) {
8200
+ this.refreshPromise = this.startClientLogin(this.clientId, this.clientSecret);
8201
+ return this.refreshPromise;
8202
+ }
8203
+ return undefined;
7918
8204
  }
7919
8205
  /**
7920
8206
  * Starts a new OAuth2 client credentials flow.
@@ -7925,13 +8211,24 @@
7925
8211
  * @returns Promise that resolves to the client profile.
7926
8212
  */
7927
8213
  async startClientLogin(clientId, clientSecret) {
7928
- __classPrivateFieldSet(this, _MedplumClient_clientId, clientId, "f");
7929
- __classPrivateFieldSet(this, _MedplumClient_clientSecret, clientSecret, "f");
8214
+ this.clientId = clientId;
8215
+ this.clientSecret = clientSecret;
7930
8216
  const formBody = new URLSearchParams();
7931
- formBody.set('grant_type', 'client_credentials');
8217
+ formBody.set('grant_type', exports.OAuthGrantType.ClientCredentials);
7932
8218
  formBody.set('client_id', clientId);
7933
8219
  formBody.set('client_secret', clientSecret);
7934
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
8220
+ return this.fetchTokens(formBody);
8221
+ }
8222
+ /**
8223
+ * Sets the client ID and secret for basic auth.
8224
+ * @category Authentication
8225
+ * @param clientId The client ID.
8226
+ * @param clientSecret The client secret.
8227
+ */
8228
+ setBasicAuth(clientId, clientSecret) {
8229
+ this.clientId = clientId;
8230
+ this.clientSecret = clientSecret;
8231
+ this.basicAuth = encodeBase64(clientId + ':' + clientSecret);
7935
8232
  }
7936
8233
  /**
7937
8234
  * Invite a user to a project.
@@ -7942,280 +8239,72 @@
7942
8239
  async invite(projectId, body) {
7943
8240
  return this.post('admin/projects/' + projectId + '/invite', body);
7944
8241
  }
7945
- }
7946
- _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_exchangeUrl = 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) {
7947
- const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
7948
- logins.push(newLogin);
7949
- __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
7950
- }, _MedplumClient_refreshProfile = async function _MedplumClient_refreshProfile() {
7951
- __classPrivateFieldSet(this, _MedplumClient_profilePromise, new Promise((resolve, reject) => {
7952
- this.get('auth/me')
7953
- .then((result) => {
7954
- __classPrivateFieldSet(this, _MedplumClient_profilePromise, undefined, "f");
7955
- __classPrivateFieldSet(this, _MedplumClient_profile, result.profile, "f");
7956
- __classPrivateFieldSet(this, _MedplumClient_config, result.config, "f");
7957
- this.dispatchEvent({ type: 'change' });
7958
- resolve(__classPrivateFieldGet(this, _MedplumClient_profile, "f"));
7959
- })
7960
- .catch(reject);
7961
- }), "f");
7962
- return __classPrivateFieldGet(this, _MedplumClient_profilePromise, "f");
7963
- }, _MedplumClient_getCacheEntry = function _MedplumClient_getCacheEntry(key, options) {
7964
- if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") <= 0 || options?.cache === 'no-cache' || options?.cache === 'reload') {
7965
- return undefined;
7966
- }
7967
- const entry = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(key);
7968
- if (!entry || entry.requestTime + __classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") < Date.now()) {
7969
- return undefined;
7970
- }
7971
- return entry;
7972
- }, _MedplumClient_setCacheEntry = function _MedplumClient_setCacheEntry(key, value) {
7973
- if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") > 0) {
7974
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").set(key, { requestTime: Date.now(), value });
7975
- }
7976
- }, _MedplumClient_cacheResource = function _MedplumClient_cacheResource(resource) {
7977
- if (resource?.id) {
7978
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, this.fhirUrl(resource.resourceType, resource.id).toString(), new ReadablePromise(Promise.resolve(resource)));
7979
- }
7980
- }, _MedplumClient_deleteCacheEntry = function _MedplumClient_deleteCacheEntry(key) {
7981
- if (__classPrivateFieldGet(this, _MedplumClient_cacheTime, "f") > 0) {
7982
- __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").delete(key);
7983
- }
7984
- }, _MedplumClient_request =
7985
- /**
7986
- * Makes an HTTP request.
7987
- * @param {string} method
7988
- * @param {string} url
7989
- * @param {string=} contentType
7990
- * @param {Object=} body
7991
- */
7992
- async function _MedplumClient_request(method, url, options = {}) {
7993
- if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
7994
- await __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
7995
- }
7996
- if (!url.startsWith('http')) {
7997
- url = __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + url;
7998
- }
7999
- options.method = method;
8000
- __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_addFetchOptionsDefaults).call(this, options);
8001
- const response = await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchWithRetry).call(this, url, options);
8002
- if (response.status === 401) {
8003
- // Refresh and try again
8004
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_handleUnauthenticated).call(this, method, url, options);
8242
+ /**
8243
+ * Makes a POST request to the tokens endpoint.
8244
+ * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
8245
+ * @param formBody Token parameters in URL encoded format.
8246
+ */
8247
+ async fetchTokens(formBody) {
8248
+ const response = await this.fetch(this.tokenUrl, {
8249
+ method: 'POST',
8250
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
8251
+ body: formBody,
8252
+ credentials: 'include',
8253
+ });
8254
+ if (!response.ok) {
8255
+ this.clearActiveLogin();
8256
+ throw new Error('Failed to fetch tokens');
8257
+ }
8258
+ const tokens = await response.json();
8259
+ await this.verifyTokens(tokens);
8260
+ return this.getProfile();
8005
8261
  }
8006
- if (response.status === 204 || response.status === 304) {
8007
- // No content or change
8008
- return undefined;
8262
+ /**
8263
+ * Verifies the tokens received from the auth server.
8264
+ * Validates the JWT against the JWKS.
8265
+ * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
8266
+ * @param tokens
8267
+ */
8268
+ async verifyTokens(tokens) {
8269
+ const token = tokens.access_token;
8270
+ // Verify token has not expired
8271
+ const tokenPayload = parseJWTPayload(token);
8272
+ if (Date.now() >= tokenPayload.exp * 1000) {
8273
+ this.clearActiveLogin();
8274
+ throw new Error('Token expired');
8275
+ }
8276
+ // Verify app_client_id
8277
+ if (this.clientId && tokenPayload.client_id !== this.clientId) {
8278
+ this.clearActiveLogin();
8279
+ throw new Error('Token was not issued for this audience');
8280
+ }
8281
+ return this.setActiveLogin({
8282
+ accessToken: token,
8283
+ refreshToken: tokens.refresh_token,
8284
+ project: tokens.project,
8285
+ profile: tokens.profile,
8286
+ });
8009
8287
  }
8010
- let obj = undefined;
8011
- try {
8012
- obj = await response.json();
8013
- }
8014
- catch (err) {
8015
- console.error('Error parsing response', response.status, err);
8016
- throw err;
8017
- }
8018
- if (response.status >= 400) {
8019
- throw new OperationOutcomeError(normalizeOperationOutcome(obj));
8020
- }
8021
- return obj;
8022
- }, _MedplumClient_fetchWithRetry = async function _MedplumClient_fetchWithRetry(url, options) {
8023
- const maxRetries = 3;
8024
- const retryDelay = 200;
8025
- let response = undefined;
8026
- for (let retry = 0; retry < maxRetries; retry++) {
8027
- response = (await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, url, options));
8028
- if (response.status < 500) {
8029
- return response;
8030
- }
8031
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
8032
- }
8033
- return response;
8034
- }, _MedplumClient_executeAutoBatch =
8035
- /**
8036
- * Executes a batch of requests that were automatically batched together.
8037
- */
8038
- async function _MedplumClient_executeAutoBatch() {
8039
- // Get the current queue
8040
- const entries = [...__classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f")];
8041
- // Clear the queue
8042
- __classPrivateFieldGet(this, _MedplumClient_autoBatchQueue, "f").length = 0;
8043
- // Clear the timer
8044
- __classPrivateFieldSet(this, _MedplumClient_autoBatchTimerId, undefined, "f");
8045
- // If there is only one request in the batch, just execute it
8046
- if (entries.length === 1) {
8047
- const entry = entries[0];
8288
+ /**
8289
+ * Sets up a listener for window storage events.
8290
+ * This synchronizes state across browser windows and browser tabs.
8291
+ */
8292
+ setupStorageListener() {
8048
8293
  try {
8049
- entry.resolve(await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, entry.method, __classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + entry.url, entry.options));
8294
+ window.addEventListener('storage', (e) => {
8295
+ if (e.key === null || e.key === 'activeLogin') {
8296
+ // Storage events fire when different tabs make changes.
8297
+ // On storage clear (key === null) or activeLogin change (key === 'activeLogin')
8298
+ // Refresh the page to ensure the active login is up to date.
8299
+ window.location.reload();
8300
+ }
8301
+ });
8050
8302
  }
8051
8303
  catch (err) {
8052
- entry.reject(new OperationOutcomeError(normalizeOperationOutcome(err)));
8053
- }
8054
- return;
8055
- }
8056
- // Build the batch request
8057
- const batch = {
8058
- resourceType: 'Bundle',
8059
- type: 'batch',
8060
- entry: entries.map((e) => ({
8061
- request: {
8062
- method: e.method,
8063
- url: e.url,
8064
- },
8065
- resource: e.options.body ? JSON.parse(e.options.body) : undefined,
8066
- })),
8067
- };
8068
- // Execute the batch request
8069
- const response = (await this.post('fhir/R4', batch));
8070
- // Process the response
8071
- for (let i = 0; i < entries.length; i++) {
8072
- const entry = entries[i];
8073
- const responseEntry = response.entry?.[i];
8074
- if (responseEntry?.response?.outcome && !isOk(responseEntry.response.outcome)) {
8075
- entry.reject(new OperationOutcomeError(responseEntry.response.outcome));
8304
+ // Silently ignore if this environment does not support storage events
8076
8305
  }
8077
- else {
8078
- entry.resolve(responseEntry?.resource);
8079
- }
8080
- }
8081
- }, _MedplumClient_addFetchOptionsDefaults = function _MedplumClient_addFetchOptionsDefaults(options) {
8082
- if (!options.headers) {
8083
- options.headers = {};
8084
- }
8085
- const headers = options.headers;
8086
- headers['X-Medplum'] = 'extended';
8087
- if (!headers['Content-Type']) {
8088
- headers['Content-Type'] = FHIR_CONTENT_TYPE;
8089
- }
8090
- if (__classPrivateFieldGet(this, _MedplumClient_accessToken, "f")) {
8091
- headers['Authorization'] = 'Bearer ' + __classPrivateFieldGet(this, _MedplumClient_accessToken, "f");
8092
- }
8093
- if (!options.cache) {
8094
- options.cache = 'no-cache';
8095
- }
8096
- if (!options.credentials) {
8097
- options.credentials = 'include';
8098
- }
8099
- }, _MedplumClient_setRequestContentType = function _MedplumClient_setRequestContentType(options, contentType) {
8100
- if (!options.headers) {
8101
- options.headers = {};
8102
- }
8103
- const headers = options.headers;
8104
- headers['Content-Type'] = contentType;
8105
- }, _MedplumClient_setRequestBody = function _MedplumClient_setRequestBody(options, data) {
8106
- if (typeof data === 'string' ||
8107
- (typeof Blob !== 'undefined' && data instanceof Blob) ||
8108
- (typeof File !== 'undefined' && data instanceof File) ||
8109
- (typeof Uint8Array !== 'undefined' && data instanceof Uint8Array)) {
8110
- options.body = data;
8111
- }
8112
- else if (data) {
8113
- options.body = JSON.stringify(data);
8114
- }
8115
- }, _MedplumClient_handleUnauthenticated = function _MedplumClient_handleUnauthenticated(method, url, options) {
8116
- if (__classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refresh).call(this)) {
8117
- return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, method, url, options);
8118
- }
8119
- this.clearActiveLogin();
8120
- if (__classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f")) {
8121
- __classPrivateFieldGet(this, _MedplumClient_onUnauthenticated, "f").call(this);
8122
- }
8123
- return Promise.reject(new Error('Unauthenticated'));
8124
- }, _MedplumClient_requestAuthorization =
8125
- /**
8126
- * Redirects the user to the login screen for authorization.
8127
- * Clears all auth state including local storage and session storage.
8128
- * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
8129
- */
8130
- async function _MedplumClient_requestAuthorization(loginParams) {
8131
- const loginRequest = await this.ensureCodeChallenge(loginParams || {});
8132
- const url = new URL(__classPrivateFieldGet(this, _MedplumClient_authorizeUrl, "f"));
8133
- url.searchParams.set('response_type', 'code');
8134
- url.searchParams.set('state', sessionStorage.getItem('pkceState'));
8135
- url.searchParams.set('client_id', loginRequest.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
8136
- url.searchParams.set('redirect_uri', loginRequest.redirectUri || getWindowOrigin());
8137
- url.searchParams.set('code_challenge_method', loginRequest.codeChallengeMethod);
8138
- url.searchParams.set('code_challenge', loginRequest.codeChallenge);
8139
- url.searchParams.set('scope', loginRequest.scope || 'openid profile');
8140
- window.location.assign(url.toString());
8141
- }, _MedplumClient_refresh = function _MedplumClient_refresh() {
8142
- if (__classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f")) {
8143
- return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
8144
- }
8145
- if (__classPrivateFieldGet(this, _MedplumClient_refreshToken, "f")) {
8146
- const formBody = new URLSearchParams();
8147
- formBody.set('grant_type', 'refresh_token');
8148
- formBody.set('client_id', __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
8149
- formBody.set('refresh_token', __classPrivateFieldGet(this, _MedplumClient_refreshToken, "f"));
8150
- __classPrivateFieldSet(this, _MedplumClient_refreshPromise, __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody), "f");
8151
- return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
8152
- }
8153
- if (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") && __classPrivateFieldGet(this, _MedplumClient_clientSecret, "f")) {
8154
- __classPrivateFieldSet(this, _MedplumClient_refreshPromise, this.startClientLogin(__classPrivateFieldGet(this, _MedplumClient_clientId, "f"), __classPrivateFieldGet(this, _MedplumClient_clientSecret, "f")), "f");
8155
- return __classPrivateFieldGet(this, _MedplumClient_refreshPromise, "f");
8156
- }
8157
- return undefined;
8158
- }, _MedplumClient_fetchTokens =
8159
- /**
8160
- * Makes a POST request to the tokens endpoint.
8161
- * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
8162
- * @param formBody Token parameters in URL encoded format.
8163
- */
8164
- async function _MedplumClient_fetchTokens(formBody) {
8165
- const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_tokenUrl, "f"), {
8166
- method: 'POST',
8167
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
8168
- body: formBody,
8169
- credentials: 'include',
8170
- });
8171
- if (!response.ok) {
8172
- this.clearActiveLogin();
8173
- throw new Error('Failed to fetch tokens');
8174
- }
8175
- const tokens = await response.json();
8176
- await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens);
8177
- return this.getProfile();
8178
- }, _MedplumClient_verifyTokens =
8179
- /**
8180
- * Verifies the tokens received from the auth server.
8181
- * Validates the JWT against the JWKS.
8182
- * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
8183
- * @param tokens
8184
- */
8185
- async function _MedplumClient_verifyTokens(tokens) {
8186
- const token = tokens.access_token;
8187
- // Verify token has not expired
8188
- const tokenPayload = parseJWTPayload(token);
8189
- if (Date.now() >= tokenPayload.exp * 1000) {
8190
- this.clearActiveLogin();
8191
- throw new Error('Token expired');
8192
- }
8193
- // Verify app_client_id
8194
- if (__classPrivateFieldGet(this, _MedplumClient_clientId, "f") && tokenPayload.client_id !== __classPrivateFieldGet(this, _MedplumClient_clientId, "f")) {
8195
- this.clearActiveLogin();
8196
- throw new Error('Token was not issued for this audience');
8197
- }
8198
- return this.setActiveLogin({
8199
- accessToken: token,
8200
- refreshToken: tokens.refresh_token,
8201
- project: tokens.project,
8202
- profile: tokens.profile,
8203
- });
8204
- }, _MedplumClient_setupStorageListener = function _MedplumClient_setupStorageListener() {
8205
- try {
8206
- window.addEventListener('storage', (e) => {
8207
- if (e.key === null || e.key === 'activeLogin') {
8208
- // Storage events fire when different tabs make changes.
8209
- // On storage clear (key === null) or activeLogin change (key === 'activeLogin')
8210
- // Refresh the page to ensure the active login is up to date.
8211
- window.location.reload();
8212
- }
8213
- });
8214
8306
  }
8215
- catch (err) {
8216
- // Silently ignore if this environment does not support storage events
8217
- }
8218
- };
8307
+ }
8219
8308
  /**
8220
8309
  * Returns the default fetch method.
8221
8310
  * The default fetch is currently only available in browser environments.
@@ -8245,7 +8334,6 @@
8245
8334
  return url.endsWith('/') ? url : url + '/';
8246
8335
  }
8247
8336
 
8248
- var _ParserBuilder_prefixParselets, _ParserBuilder_infixParselets, _Parser_tokens, _Parser_prefixParselets, _Parser_infixParselets;
8249
8337
  class PrefixOperatorAtom {
8250
8338
  constructor(operator, child) {
8251
8339
  this.operator = operator;
@@ -8267,15 +8355,15 @@
8267
8355
  }
8268
8356
  class ParserBuilder {
8269
8357
  constructor() {
8270
- _ParserBuilder_prefixParselets.set(this, {});
8271
- _ParserBuilder_infixParselets.set(this, {});
8358
+ this.prefixParselets = {};
8359
+ this.infixParselets = {};
8272
8360
  }
8273
8361
  registerInfix(tokenType, parselet) {
8274
- __classPrivateFieldGet(this, _ParserBuilder_infixParselets, "f")[tokenType] = parselet;
8362
+ this.infixParselets[tokenType] = parselet;
8275
8363
  return this;
8276
8364
  }
8277
8365
  registerPrefix(tokenType, parselet) {
8278
- __classPrivateFieldGet(this, _ParserBuilder_prefixParselets, "f")[tokenType] = parselet;
8366
+ this.prefixParselets[tokenType] = parselet;
8279
8367
  return this;
8280
8368
  }
8281
8369
  prefix(tokenType, precedence, builder) {
@@ -8296,21 +8384,17 @@
8296
8384
  });
8297
8385
  }
8298
8386
  construct(input) {
8299
- return new Parser(input, __classPrivateFieldGet(this, _ParserBuilder_prefixParselets, "f"), __classPrivateFieldGet(this, _ParserBuilder_infixParselets, "f"));
8387
+ return new Parser(input, this.prefixParselets, this.infixParselets);
8300
8388
  }
8301
8389
  }
8302
- _ParserBuilder_prefixParselets = new WeakMap(), _ParserBuilder_infixParselets = new WeakMap();
8303
8390
  class Parser {
8304
8391
  constructor(tokens, prefixParselets, infixParselets) {
8305
- _Parser_tokens.set(this, void 0);
8306
- _Parser_prefixParselets.set(this, void 0);
8307
- _Parser_infixParselets.set(this, void 0);
8308
- __classPrivateFieldSet(this, _Parser_tokens, tokens, "f");
8309
- __classPrivateFieldSet(this, _Parser_prefixParselets, prefixParselets, "f");
8310
- __classPrivateFieldSet(this, _Parser_infixParselets, infixParselets, "f");
8392
+ this.tokens = tokens;
8393
+ this.prefixParselets = prefixParselets;
8394
+ this.infixParselets = infixParselets;
8311
8395
  }
8312
8396
  hasMore() {
8313
- return __classPrivateFieldGet(this, _Parser_tokens, "f").length > 0;
8397
+ return this.tokens.length > 0;
8314
8398
  }
8315
8399
  match(expected) {
8316
8400
  const token = this.peek();
@@ -8322,7 +8406,7 @@
8322
8406
  }
8323
8407
  consumeAndParse(precedence = Infinity) {
8324
8408
  const token = this.consume();
8325
- const prefix = __classPrivateFieldGet(this, _Parser_prefixParselets, "f")[token.id];
8409
+ const prefix = this.prefixParselets[token.id];
8326
8410
  if (!prefix) {
8327
8411
  throw Error(`Parse error at "${token.value}" (line ${token.line}, column ${token.column}). No matching prefix parselet.`);
8328
8412
  }
@@ -8346,7 +8430,7 @@
8346
8430
  return Infinity;
8347
8431
  }
8348
8432
  consume(expectedId, expectedValue) {
8349
- if (!__classPrivateFieldGet(this, _Parser_tokens, "f").length) {
8433
+ if (!this.tokens.length) {
8350
8434
  throw Error('Cant consume unknown more tokens.');
8351
8435
  }
8352
8436
  if (expectedId && this.peek()?.id !== expectedId) {
@@ -8357,21 +8441,19 @@
8357
8441
  const actual = this.peek();
8358
8442
  throw Error(`Expected "${expectedValue}" but got "${actual.value}" at line ${actual.line} column ${actual.column}.`);
8359
8443
  }
8360
- return __classPrivateFieldGet(this, _Parser_tokens, "f").shift();
8444
+ return this.tokens.shift();
8361
8445
  }
8362
8446
  peek() {
8363
- return __classPrivateFieldGet(this, _Parser_tokens, "f").length > 0 ? __classPrivateFieldGet(this, _Parser_tokens, "f")[0] : undefined;
8447
+ return this.tokens.length > 0 ? this.tokens[0] : undefined;
8364
8448
  }
8365
8449
  removeComments() {
8366
- __classPrivateFieldSet(this, _Parser_tokens, __classPrivateFieldGet(this, _Parser_tokens, "f").filter((t) => t.id !== 'Comment'), "f");
8450
+ this.tokens = this.tokens.filter((t) => t.id !== 'Comment');
8367
8451
  }
8368
8452
  getInfixParselet(token) {
8369
- return __classPrivateFieldGet(this, _Parser_infixParselets, "f")[token.id === 'Symbol' ? token.value : token.id];
8453
+ return this.infixParselets[token.id === 'Symbol' ? token.value : token.id];
8370
8454
  }
8371
8455
  }
8372
- _Parser_tokens = new WeakMap(), _Parser_prefixParselets = new WeakMap(), _Parser_infixParselets = new WeakMap();
8373
8456
 
8374
- var _Tokenizer_instances, _Tokenizer_str, _Tokenizer_keywords, _Tokenizer_operators, _Tokenizer_dateTimeLiterals, _Tokenizer_symbolRegex, _Tokenizer_result, _Tokenizer_pos, _Tokenizer_markStack, _Tokenizer_prevToken, _Tokenizer_peekToken, _Tokenizer_consumeToken, _Tokenizer_consumeWhitespace, _Tokenizer_consumeMultiLineComment, _Tokenizer_consumeSingleLineComment, _Tokenizer_consumeString, _Tokenizer_consumeBacktickSymbol, _Tokenizer_consumeDateTime, _Tokenizer_consumeNumber, _Tokenizer_consumeSymbol, _Tokenizer_consumeOperator, _Tokenizer_consumeWhile, _Tokenizer_curr, _Tokenizer_prev, _Tokenizer_peek, _Tokenizer_mark, _Tokenizer_reset, _Tokenizer_advance, _Tokenizer_buildToken;
8375
8457
  const STANDARD_UNITS = [
8376
8458
  'year',
8377
8459
  'years',
@@ -8392,190 +8474,203 @@
8392
8474
  ];
8393
8475
  class Tokenizer {
8394
8476
  constructor(str, keywords, operators, options) {
8395
- _Tokenizer_instances.add(this);
8396
- _Tokenizer_str.set(this, void 0);
8397
- _Tokenizer_keywords.set(this, void 0);
8398
- _Tokenizer_operators.set(this, void 0);
8399
- _Tokenizer_dateTimeLiterals.set(this, void 0);
8400
- _Tokenizer_symbolRegex.set(this, void 0);
8401
- _Tokenizer_result.set(this, []);
8402
- _Tokenizer_pos.set(this, { index: 0, line: 1, column: 0 });
8403
- _Tokenizer_markStack.set(this, []);
8404
- __classPrivateFieldSet(this, _Tokenizer_str, str, "f");
8405
- __classPrivateFieldSet(this, _Tokenizer_keywords, keywords, "f");
8406
- __classPrivateFieldSet(this, _Tokenizer_operators, operators, "f");
8407
- __classPrivateFieldSet(this, _Tokenizer_dateTimeLiterals, !!options?.dateTimeLiterals, "f");
8408
- __classPrivateFieldSet(this, _Tokenizer_symbolRegex, options?.symbolRegex ?? /[$\w]/, "f");
8477
+ this.result = [];
8478
+ this.pos = { index: 0, line: 1, column: 0 };
8479
+ this.markStack = [];
8480
+ this.str = str;
8481
+ this.keywords = keywords;
8482
+ this.operators = operators;
8483
+ this.dateTimeLiterals = !!options?.dateTimeLiterals;
8484
+ this.symbolRegex = options?.symbolRegex ?? /[$\w]/;
8409
8485
  }
8410
8486
  tokenize() {
8411
- while (__classPrivateFieldGet(this, _Tokenizer_pos, "f").index < __classPrivateFieldGet(this, _Tokenizer_str, "f").length) {
8412
- const token = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeToken).call(this);
8487
+ while (this.pos.index < this.str.length) {
8488
+ const token = this.consumeToken();
8413
8489
  if (token) {
8414
- __classPrivateFieldGet(this, _Tokenizer_result, "f").push(token);
8490
+ this.result.push(token);
8415
8491
  }
8416
8492
  }
8417
- return __classPrivateFieldGet(this, _Tokenizer_result, "f");
8493
+ return this.result;
8418
8494
  }
8419
- }
8420
- _Tokenizer_str = new WeakMap(), _Tokenizer_keywords = new WeakMap(), _Tokenizer_operators = new WeakMap(), _Tokenizer_dateTimeLiterals = new WeakMap(), _Tokenizer_symbolRegex = new WeakMap(), _Tokenizer_result = new WeakMap(), _Tokenizer_pos = new WeakMap(), _Tokenizer_markStack = new WeakMap(), _Tokenizer_instances = new WeakSet(), _Tokenizer_prevToken = function _Tokenizer_prevToken() {
8421
- return __classPrivateFieldGet(this, _Tokenizer_result, "f").slice(-1)[0];
8422
- }, _Tokenizer_peekToken = function _Tokenizer_peekToken() {
8423
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_mark).call(this);
8424
- const token = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeToken).call(this);
8425
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_reset).call(this);
8426
- return token;
8427
- }, _Tokenizer_consumeToken = function _Tokenizer_consumeToken() {
8428
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhitespace).call(this);
8429
- const c = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this);
8430
- if (!c) {
8431
- return undefined;
8495
+ prevToken() {
8496
+ return this.result.slice(-1)[0];
8432
8497
  }
8433
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_mark).call(this);
8434
- const next = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peek).call(this);
8435
- if (c === '/' && next === '*') {
8436
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeMultiLineComment).call(this);
8437
- }
8438
- if (c === '/' && next === '/') {
8439
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeSingleLineComment).call(this);
8440
- }
8441
- if (c === "'" || c === '"') {
8442
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeString).call(this, c);
8443
- }
8444
- if (c === '`') {
8445
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeBacktickSymbol).call(this);
8446
- }
8447
- if (c === '@') {
8448
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeDateTime).call(this);
8449
- }
8450
- if (c.match(/\d/)) {
8451
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeNumber).call(this);
8452
- }
8453
- if (c.match(/\w/)) {
8454
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeSymbol).call(this);
8455
- }
8456
- if (c === '$' && next.match(/\w/)) {
8457
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeSymbol).call(this);
8458
- }
8459
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeOperator).call(this);
8460
- }, _Tokenizer_consumeWhitespace = function _Tokenizer_consumeWhitespace() {
8461
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/\s/));
8462
- }, _Tokenizer_consumeMultiLineComment = function _Tokenizer_consumeMultiLineComment() {
8463
- const start = __classPrivateFieldGet(this, _Tokenizer_pos, "f").index;
8464
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) !== '*' || __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peek).call(this) !== '/');
8465
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8466
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8467
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'Comment', __classPrivateFieldGet(this, _Tokenizer_str, "f").substring(start, __classPrivateFieldGet(this, _Tokenizer_pos, "f").index));
8468
- }, _Tokenizer_consumeSingleLineComment = function _Tokenizer_consumeSingleLineComment() {
8469
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'Comment', __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) !== '\n'));
8470
- }, _Tokenizer_consumeString = function _Tokenizer_consumeString(endChar) {
8471
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8472
- const result = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'String', __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_prev).call(this) === '\\' || __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) !== endChar));
8473
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8474
- return result;
8475
- }, _Tokenizer_consumeBacktickSymbol = function _Tokenizer_consumeBacktickSymbol() {
8476
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8477
- const result = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'Symbol', __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) !== '`'));
8478
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8479
- return result;
8480
- }, _Tokenizer_consumeDateTime = function _Tokenizer_consumeDateTime() {
8481
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this); // Consume "@"
8482
- const start = __classPrivateFieldGet(this, _Tokenizer_pos, "f").index;
8483
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/[\d-]/));
8484
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === 'T') {
8485
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8486
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/[\d:]/));
8487
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '.' && __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peek).call(this).match(/\d/)) {
8488
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8489
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/\d/));
8490
- }
8491
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === 'Z') {
8492
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8493
- }
8494
- else if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '+' || __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '-') {
8495
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8496
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/[\d:]/));
8497
- }
8498
- }
8499
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'DateTime', __classPrivateFieldGet(this, _Tokenizer_str, "f").substring(start, __classPrivateFieldGet(this, _Tokenizer_pos, "f").index));
8500
- }, _Tokenizer_consumeNumber = function _Tokenizer_consumeNumber() {
8501
- const start = __classPrivateFieldGet(this, _Tokenizer_pos, "f").index;
8502
- let id = 'Number';
8503
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/\d/));
8504
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '.' && __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peek).call(this).match(/\d/)) {
8505
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8506
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/\d/));
8507
- }
8508
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '-' && __classPrivateFieldGet(this, _Tokenizer_dateTimeLiterals, "f")) {
8509
- // Rewind to one character before the start, and then treat as dateTime literal.
8510
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").index = start - 1;
8511
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeDateTime).call(this);
8512
- }
8513
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === ' ') {
8514
- if (isUnitToken(__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peekToken).call(this))) {
8515
- id = 'Quantity';
8516
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeToken).call(this);
8517
- }
8518
- }
8519
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, id, __classPrivateFieldGet(this, _Tokenizer_str, "f").substring(start, __classPrivateFieldGet(this, _Tokenizer_pos, "f").index));
8520
- }, _Tokenizer_consumeSymbol = function _Tokenizer_consumeSymbol() {
8521
- const value = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(__classPrivateFieldGet(this, _Tokenizer_symbolRegex, "f")));
8522
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_prevToken).call(this)?.value !== '.' && __classPrivateFieldGet(this, _Tokenizer_keywords, "f").includes(value)) {
8523
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, value, value);
8524
- }
8525
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, 'Symbol', value);
8526
- }, _Tokenizer_consumeOperator = function _Tokenizer_consumeOperator() {
8527
- const c = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this);
8528
- const next = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peek).call(this);
8529
- const twoCharOp = c + next;
8530
- if (__classPrivateFieldGet(this, _Tokenizer_operators, "f").includes(twoCharOp)) {
8531
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8532
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8533
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, twoCharOp, twoCharOp);
8534
- }
8535
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8536
- return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, c, c);
8537
- }, _Tokenizer_consumeWhile = function _Tokenizer_consumeWhile(condition) {
8538
- const start = __classPrivateFieldGet(this, _Tokenizer_pos, "f").index;
8539
- while (__classPrivateFieldGet(this, _Tokenizer_pos, "f").index < __classPrivateFieldGet(this, _Tokenizer_str, "f").length && condition()) {
8540
- __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
8541
- }
8542
- return __classPrivateFieldGet(this, _Tokenizer_str, "f").substring(start, __classPrivateFieldGet(this, _Tokenizer_pos, "f").index);
8543
- }, _Tokenizer_curr = function _Tokenizer_curr() {
8544
- return __classPrivateFieldGet(this, _Tokenizer_str, "f")[__classPrivateFieldGet(this, _Tokenizer_pos, "f").index];
8545
- }, _Tokenizer_prev = function _Tokenizer_prev() {
8546
- return __classPrivateFieldGet(this, _Tokenizer_str, "f")[__classPrivateFieldGet(this, _Tokenizer_pos, "f").index - 1] ?? '';
8547
- }, _Tokenizer_peek = function _Tokenizer_peek() {
8548
- return __classPrivateFieldGet(this, _Tokenizer_str, "f")[__classPrivateFieldGet(this, _Tokenizer_pos, "f").index + 1] ?? '';
8549
- }, _Tokenizer_mark = function _Tokenizer_mark() {
8550
- __classPrivateFieldGet(this, _Tokenizer_markStack, "f").push({ ...__classPrivateFieldGet(this, _Tokenizer_pos, "f") });
8551
- }, _Tokenizer_reset = function _Tokenizer_reset() {
8552
- const mark = __classPrivateFieldGet(this, _Tokenizer_markStack, "f").pop();
8553
- if (!mark) {
8554
- throw new Error('No mark to reset to');
8555
- }
8556
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").index = mark.index;
8557
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").line = mark.line;
8558
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").column = mark.column;
8559
- }, _Tokenizer_advance = function _Tokenizer_advance() {
8560
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").index++;
8561
- if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '\n') {
8562
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").line++;
8563
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").column = 0;
8498
+ peekToken() {
8499
+ this.mark();
8500
+ const token = this.consumeToken();
8501
+ this.reset();
8502
+ return token;
8564
8503
  }
8565
- else {
8566
- __classPrivateFieldGet(this, _Tokenizer_pos, "f").column++;
8504
+ consumeToken() {
8505
+ this.consumeWhitespace();
8506
+ const c = this.curr();
8507
+ if (!c) {
8508
+ return undefined;
8509
+ }
8510
+ this.mark();
8511
+ const next = this.peek();
8512
+ if (c === '/' && next === '*') {
8513
+ return this.consumeMultiLineComment();
8514
+ }
8515
+ if (c === '/' && next === '/') {
8516
+ return this.consumeSingleLineComment();
8517
+ }
8518
+ if (c === "'" || c === '"') {
8519
+ return this.consumeString(c);
8520
+ }
8521
+ if (c === '`') {
8522
+ return this.consumeBacktickSymbol();
8523
+ }
8524
+ if (c === '@') {
8525
+ return this.consumeDateTime();
8526
+ }
8527
+ if (c.match(/\d/)) {
8528
+ return this.consumeNumber();
8529
+ }
8530
+ if (c.match(/\w/)) {
8531
+ return this.consumeSymbol();
8532
+ }
8533
+ if (c === '$' && next.match(/\w/)) {
8534
+ return this.consumeSymbol();
8535
+ }
8536
+ return this.consumeOperator();
8567
8537
  }
8568
- }, _Tokenizer_buildToken = function _Tokenizer_buildToken(id, value) {
8569
- const mark = __classPrivateFieldGet(this, _Tokenizer_markStack, "f").pop();
8570
- if (!mark) {
8571
- throw new Error('No mark for token');
8538
+ consumeWhitespace() {
8539
+ this.consumeWhile(() => this.curr().match(/\s/));
8572
8540
  }
8573
- return {
8574
- id,
8575
- value,
8576
- ...mark,
8577
- };
8578
- };
8541
+ consumeMultiLineComment() {
8542
+ const start = this.pos.index;
8543
+ this.consumeWhile(() => this.curr() !== '*' || this.peek() !== '/');
8544
+ this.advance();
8545
+ this.advance();
8546
+ return this.buildToken('Comment', this.str.substring(start, this.pos.index));
8547
+ }
8548
+ consumeSingleLineComment() {
8549
+ return this.buildToken('Comment', this.consumeWhile(() => this.curr() !== '\n'));
8550
+ }
8551
+ consumeString(endChar) {
8552
+ this.advance();
8553
+ const result = this.buildToken('String', this.consumeWhile(() => this.prev() === '\\' || this.curr() !== endChar));
8554
+ this.advance();
8555
+ return result;
8556
+ }
8557
+ consumeBacktickSymbol() {
8558
+ this.advance();
8559
+ const result = this.buildToken('Symbol', this.consumeWhile(() => this.curr() !== '`'));
8560
+ this.advance();
8561
+ return result;
8562
+ }
8563
+ consumeDateTime() {
8564
+ this.advance(); // Consume "@"
8565
+ const start = this.pos.index;
8566
+ this.consumeWhile(() => this.curr().match(/[\d-]/));
8567
+ if (this.curr() === 'T') {
8568
+ this.advance();
8569
+ this.consumeWhile(() => this.curr().match(/[\d:]/));
8570
+ if (this.curr() === '.' && this.peek().match(/\d/)) {
8571
+ this.advance();
8572
+ this.consumeWhile(() => this.curr().match(/\d/));
8573
+ }
8574
+ if (this.curr() === 'Z') {
8575
+ this.advance();
8576
+ }
8577
+ else if (this.curr() === '+' || this.curr() === '-') {
8578
+ this.advance();
8579
+ this.consumeWhile(() => this.curr().match(/[\d:]/));
8580
+ }
8581
+ }
8582
+ return this.buildToken('DateTime', this.str.substring(start, this.pos.index));
8583
+ }
8584
+ consumeNumber() {
8585
+ const start = this.pos.index;
8586
+ let id = 'Number';
8587
+ this.consumeWhile(() => this.curr().match(/\d/));
8588
+ if (this.curr() === '.' && this.peek().match(/\d/)) {
8589
+ this.advance();
8590
+ this.consumeWhile(() => this.curr().match(/\d/));
8591
+ }
8592
+ if (this.curr() === '-' && this.dateTimeLiterals) {
8593
+ // Rewind to one character before the start, and then treat as dateTime literal.
8594
+ this.pos.index = start - 1;
8595
+ return this.consumeDateTime();
8596
+ }
8597
+ if (this.curr() === ' ') {
8598
+ if (isUnitToken(this.peekToken())) {
8599
+ id = 'Quantity';
8600
+ this.consumeToken();
8601
+ }
8602
+ }
8603
+ return this.buildToken(id, this.str.substring(start, this.pos.index));
8604
+ }
8605
+ consumeSymbol() {
8606
+ const value = this.consumeWhile(() => this.curr().match(this.symbolRegex));
8607
+ if (this.prevToken()?.value !== '.' && this.keywords.includes(value)) {
8608
+ return this.buildToken(value, value);
8609
+ }
8610
+ return this.buildToken('Symbol', value);
8611
+ }
8612
+ consumeOperator() {
8613
+ const c = this.curr();
8614
+ const next = this.peek();
8615
+ const twoCharOp = c + next;
8616
+ if (this.operators.includes(twoCharOp)) {
8617
+ this.advance();
8618
+ this.advance();
8619
+ return this.buildToken(twoCharOp, twoCharOp);
8620
+ }
8621
+ this.advance();
8622
+ return this.buildToken(c, c);
8623
+ }
8624
+ consumeWhile(condition) {
8625
+ const start = this.pos.index;
8626
+ while (this.pos.index < this.str.length && condition()) {
8627
+ this.advance();
8628
+ }
8629
+ return this.str.substring(start, this.pos.index);
8630
+ }
8631
+ curr() {
8632
+ return this.str[this.pos.index];
8633
+ }
8634
+ prev() {
8635
+ return this.str[this.pos.index - 1] ?? '';
8636
+ }
8637
+ peek() {
8638
+ return this.str[this.pos.index + 1] ?? '';
8639
+ }
8640
+ mark() {
8641
+ this.markStack.push({ ...this.pos });
8642
+ }
8643
+ reset() {
8644
+ const mark = this.markStack.pop();
8645
+ if (!mark) {
8646
+ throw new Error('No mark to reset to');
8647
+ }
8648
+ this.pos.index = mark.index;
8649
+ this.pos.line = mark.line;
8650
+ this.pos.column = mark.column;
8651
+ }
8652
+ advance() {
8653
+ this.pos.index++;
8654
+ if (this.curr() === '\n') {
8655
+ this.pos.line++;
8656
+ this.pos.column = 0;
8657
+ }
8658
+ else {
8659
+ this.pos.column++;
8660
+ }
8661
+ }
8662
+ buildToken(id, value) {
8663
+ const mark = this.markStack.pop();
8664
+ if (!mark) {
8665
+ throw new Error('No mark for token');
8666
+ }
8667
+ return {
8668
+ id,
8669
+ value,
8670
+ ...mark,
8671
+ };
8672
+ }
8673
+ }
8579
8674
  function isUnitToken(token) {
8580
8675
  if (token) {
8581
8676
  if (token.id === 'String') {
@@ -10960,10 +11055,8 @@
10960
11055
  return new Tokenizer(str, FHIRPATH_KEYWORDS, MAPPING_LANGUAGE_OPERATORS$1).tokenize();
10961
11056
  }
10962
11057
 
10963
- var _StructureMapParser_instances, _StructureMapParser_parseUses, _StructureMapParser_parseImport, _StructureMapParser_parseGroup, _StructureMapParser_parseParameters, _StructureMapParser_parseParameter, _StructureMapParser_parseRules, _StructureMapParser_parseRule, _StructureMapParser_parseRuleSources, _StructureMapParser_parseRuleSource, _StructureMapParser_parseRuleTargets, _StructureMapParser_parseRuleTarget, _StructureMapParser_parseRuleTargetTransform, _StructureMapParser_parseRuleTargetSymbol, _StructureMapParser_parseRuleTargetFunction, _StructureMapParser_parseRuleTargetLiteral, _StructureMapParser_parseRuleContext, _StructureMapParser_parseRuleDependents, _StructureMapParser_parseConceptMap;
10964
11058
  class StructureMapParser {
10965
11059
  constructor(parser) {
10966
- _StructureMapParser_instances.add(this);
10967
11060
  this.parser = parser;
10968
11061
  this.structureMap = { resourceType: 'StructureMap' };
10969
11062
  }
@@ -10978,16 +11071,16 @@
10978
11071
  const next = this.parser.peek()?.value;
10979
11072
  switch (next) {
10980
11073
  case 'uses':
10981
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseUses).call(this);
11074
+ this.parseUses();
10982
11075
  break;
10983
11076
  case 'imports':
10984
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseImport).call(this);
11077
+ this.parseImport();
10985
11078
  break;
10986
11079
  case 'group':
10987
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseGroup).call(this);
11080
+ this.parseGroup();
10988
11081
  break;
10989
11082
  case 'conceptmap':
10990
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseConceptMap).call(this);
11083
+ this.parseConceptMap();
10991
11084
  break;
10992
11085
  default:
10993
11086
  throw new Error(`Unexpected token: ${next}`);
@@ -10995,263 +11088,280 @@
10995
11088
  }
10996
11089
  return this.structureMap;
10997
11090
  }
10998
- }
10999
- _StructureMapParser_instances = new WeakSet(), _StructureMapParser_parseUses = function _StructureMapParser_parseUses() {
11000
- // 'uses' url structureAlias? 'as' modelMode
11001
- // uses "http://hl7.org/fhir/StructureDefinition/tutorial-left" as source
11002
- this.parser.consume('Symbol', 'uses');
11003
- const result = {};
11004
- result.url = this.parser.consume('String').value;
11005
- if (this.parser.peek()?.value === 'alias') {
11006
- this.parser.consume('Symbol', 'alias');
11007
- result.alias = this.parser.consume('Symbol').value;
11008
- }
11009
- this.parser.consume('Symbol', 'as');
11010
- result.mode = this.parser.consume().value;
11011
- if (!this.structureMap.structure) {
11012
- this.structureMap.structure = [];
11013
- }
11014
- this.structureMap.structure.push(result);
11015
- }, _StructureMapParser_parseImport = function _StructureMapParser_parseImport() {
11016
- this.parser.consume('Symbol', 'imports');
11017
- if (!this.structureMap.import) {
11018
- this.structureMap.import = [];
11019
- }
11020
- this.structureMap.import.push(this.parser.consume('String').value);
11021
- }, _StructureMapParser_parseGroup = function _StructureMapParser_parseGroup() {
11022
- // 'group' identifier parameters extends? typeMode? rules
11023
- // group tutorial(source src : TLeft, target tgt : TRight) {
11024
- const result = {};
11025
- this.parser.consume('Symbol', 'group');
11026
- result.name = this.parser.consume('Symbol').value;
11027
- result.input = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseParameters).call(this);
11028
- if (this.parser.peek()?.value === 'extends') {
11029
- this.parser.consume('Symbol', 'extends');
11030
- result.extends = this.parser.consume('Symbol').value;
11031
- }
11032
- if (this.parser.peek()?.value === '<<') {
11033
- this.parser.consume('<<');
11034
- result.typeMode = this.parser.consume().value;
11035
- if (this.parser.peek()?.value === '+') {
11036
- this.parser.consume('+');
11037
- result.typeMode = 'type-and-types';
11038
- }
11039
- this.parser.consume('>>');
11040
- }
11041
- else {
11042
- result.typeMode = 'none';
11043
- }
11044
- result.rule = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRules).call(this);
11045
- if (!this.structureMap.group) {
11046
- this.structureMap.group = [];
11047
- }
11048
- this.structureMap.group.push(result);
11049
- }, _StructureMapParser_parseParameters = function _StructureMapParser_parseParameters() {
11050
- const parameters = [];
11051
- this.parser.consume('(');
11052
- while (this.parser.hasMore() && this.parser.peek()?.value !== ')') {
11053
- parameters.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseParameter).call(this));
11054
- if (this.parser.peek()?.value === ',') {
11055
- this.parser.consume(',');
11091
+ parseUses() {
11092
+ // 'uses' url structureAlias? 'as' modelMode
11093
+ // uses "http://hl7.org/fhir/StructureDefinition/tutorial-left" as source
11094
+ this.parser.consume('Symbol', 'uses');
11095
+ const result = {};
11096
+ result.url = this.parser.consume('String').value;
11097
+ if (this.parser.peek()?.value === 'alias') {
11098
+ this.parser.consume('Symbol', 'alias');
11099
+ result.alias = this.parser.consume('Symbol').value;
11056
11100
  }
11057
- }
11058
- this.parser.consume(')');
11059
- return parameters;
11060
- }, _StructureMapParser_parseParameter = function _StructureMapParser_parseParameter() {
11061
- // inputMode identifier type?
11062
- // ':' identifier
11063
- // source src : TLeft
11064
- const result = {};
11065
- result.mode = this.parser.consume().value;
11066
- result.name = this.parser.consume('Symbol').value;
11067
- if (this.parser.peek()?.value === ':') {
11068
- this.parser.consume(':');
11069
- result.type = this.parser.consume('Symbol').value;
11070
- }
11071
- return result;
11072
- }, _StructureMapParser_parseRules = function _StructureMapParser_parseRules() {
11073
- const rules = [];
11074
- this.parser.consume('{');
11075
- while (this.parser.hasMore() && this.parser.peek()?.value !== '}') {
11076
- rules.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRule).call(this));
11077
- }
11078
- this.parser.consume('}');
11079
- return rules;
11080
- }, _StructureMapParser_parseRule = function _StructureMapParser_parseRule() {
11081
- const result = {
11082
- source: __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSources).call(this),
11083
- };
11084
- if (this.parser.peek()?.value === '->') {
11085
- this.parser.consume('->');
11086
- result.target = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargets).call(this);
11087
- }
11088
- if (this.parser.peek()?.value === 'then') {
11089
- this.parser.consume('Symbol', 'then');
11090
- if (this.parser.peek()?.id === '{') {
11091
- result.rule = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRules).call(this);
11101
+ this.parser.consume('Symbol', 'as');
11102
+ result.mode = this.parser.consume().value;
11103
+ if (!this.structureMap.structure) {
11104
+ this.structureMap.structure = [];
11105
+ }
11106
+ this.structureMap.structure.push(result);
11107
+ }
11108
+ parseImport() {
11109
+ this.parser.consume('Symbol', 'imports');
11110
+ if (!this.structureMap.import) {
11111
+ this.structureMap.import = [];
11112
+ }
11113
+ this.structureMap.import.push(this.parser.consume('String').value);
11114
+ }
11115
+ parseGroup() {
11116
+ // 'group' identifier parameters extends? typeMode? rules
11117
+ // group tutorial(source src : TLeft, target tgt : TRight) {
11118
+ const result = {};
11119
+ this.parser.consume('Symbol', 'group');
11120
+ result.name = this.parser.consume('Symbol').value;
11121
+ result.input = this.parseParameters();
11122
+ if (this.parser.peek()?.value === 'extends') {
11123
+ this.parser.consume('Symbol', 'extends');
11124
+ result.extends = this.parser.consume('Symbol').value;
11125
+ }
11126
+ if (this.parser.peek()?.value === '<<') {
11127
+ this.parser.consume('<<');
11128
+ result.typeMode = this.parser.consume().value;
11129
+ if (this.parser.peek()?.value === '+') {
11130
+ this.parser.consume('+');
11131
+ result.typeMode = 'type-and-types';
11132
+ }
11133
+ this.parser.consume('>>');
11092
11134
  }
11093
11135
  else {
11094
- result.dependent = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleDependents).call(this);
11136
+ result.typeMode = 'none';
11095
11137
  }
11138
+ result.rule = this.parseRules();
11139
+ if (!this.structureMap.group) {
11140
+ this.structureMap.group = [];
11141
+ }
11142
+ this.structureMap.group.push(result);
11096
11143
  }
11097
- if (this.parser.peek()?.id === 'String') {
11098
- result.name = this.parser.consume().value;
11099
- }
11100
- else {
11101
- result.name = result.source?.[0]?.element;
11102
- }
11103
- this.parser.consume(';');
11104
- return result;
11105
- }, _StructureMapParser_parseRuleSources = function _StructureMapParser_parseRuleSources() {
11106
- const sources = [__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSource).call(this)];
11107
- while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
11108
- this.parser.consume(',');
11109
- sources.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSource).call(this));
11110
- }
11111
- return sources;
11112
- }, _StructureMapParser_parseRuleSource = function _StructureMapParser_parseRuleSource() {
11113
- const result = {};
11114
- const context = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleContext).call(this);
11115
- if (context.includes('.')) {
11116
- const parts = context.split('.');
11117
- result.context = parts[0];
11118
- result.element = parts[1];
11119
- }
11120
- else {
11121
- result.context = context;
11122
- }
11123
- if (this.parser.hasMore() && this.parser.peek()?.value === ':') {
11124
- this.parser.consume(':');
11125
- result.type = this.parser.consume().value;
11126
- }
11127
- if (this.parser.hasMore() && this.parser.peek()?.value === 'default') {
11128
- this.parser.consume('default');
11129
- this.parser.consumeAndParse();
11130
- }
11131
- if (this.parser.peek()?.value === 'first' ||
11132
- this.parser.peek()?.value === 'not_first' ||
11133
- this.parser.peek()?.value === 'last' ||
11134
- this.parser.peek()?.value === 'not_last' ||
11135
- this.parser.peek()?.value === 'only_one') {
11136
- result.listMode = this.parser.consume().value;
11144
+ parseParameters() {
11145
+ const parameters = [];
11146
+ this.parser.consume('(');
11147
+ while (this.parser.hasMore() && this.parser.peek()?.value !== ')') {
11148
+ parameters.push(this.parseParameter());
11149
+ if (this.parser.peek()?.value === ',') {
11150
+ this.parser.consume(',');
11151
+ }
11152
+ }
11153
+ this.parser.consume(')');
11154
+ return parameters;
11137
11155
  }
11138
- if (this.parser.peek()?.value === 'as') {
11139
- this.parser.consume('Symbol', 'as');
11140
- result.variable = this.parser.consume().value;
11156
+ parseParameter() {
11157
+ // inputMode identifier type?
11158
+ // ':' identifier
11159
+ // source src : TLeft
11160
+ const result = {};
11161
+ result.mode = this.parser.consume().value;
11162
+ result.name = this.parser.consume('Symbol').value;
11163
+ if (this.parser.peek()?.value === ':') {
11164
+ this.parser.consume(':');
11165
+ result.type = this.parser.consume('Symbol').value;
11166
+ }
11167
+ return result;
11141
11168
  }
11142
- if (this.parser.peek()?.value === 'where') {
11143
- this.parser.consume('Symbol', 'where');
11144
- const whereFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11145
- result.condition = whereFhirPath.toString();
11169
+ parseRules() {
11170
+ const rules = [];
11171
+ this.parser.consume('{');
11172
+ while (this.parser.hasMore() && this.parser.peek()?.value !== '}') {
11173
+ rules.push(this.parseRule());
11174
+ }
11175
+ this.parser.consume('}');
11176
+ return rules;
11177
+ }
11178
+ parseRule() {
11179
+ const result = {
11180
+ source: this.parseRuleSources(),
11181
+ };
11182
+ if (this.parser.peek()?.value === '->') {
11183
+ this.parser.consume('->');
11184
+ result.target = this.parseRuleTargets();
11185
+ }
11186
+ if (this.parser.peek()?.value === 'then') {
11187
+ this.parser.consume('Symbol', 'then');
11188
+ if (this.parser.peek()?.id === '{') {
11189
+ result.rule = this.parseRules();
11190
+ }
11191
+ else {
11192
+ result.dependent = this.parseRuleDependents();
11193
+ }
11194
+ }
11195
+ if (this.parser.peek()?.id === 'String') {
11196
+ result.name = this.parser.consume().value;
11197
+ }
11198
+ else {
11199
+ result.name = result.source?.[0]?.element;
11200
+ }
11201
+ this.parser.consume(';');
11202
+ return result;
11146
11203
  }
11147
- if (this.parser.peek()?.value === 'check') {
11148
- this.parser.consume('Symbol', 'check');
11149
- const checkFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11150
- result.check = checkFhirPath.toString();
11204
+ parseRuleSources() {
11205
+ const sources = [this.parseRuleSource()];
11206
+ while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
11207
+ this.parser.consume(',');
11208
+ sources.push(this.parseRuleSource());
11209
+ }
11210
+ return sources;
11151
11211
  }
11152
- return result;
11153
- }, _StructureMapParser_parseRuleTargets = function _StructureMapParser_parseRuleTargets() {
11154
- const targets = [__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTarget).call(this)];
11155
- while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
11156
- this.parser.consume(',');
11157
- targets.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTarget).call(this));
11158
- }
11159
- return targets;
11160
- }, _StructureMapParser_parseRuleTarget = function _StructureMapParser_parseRuleTarget() {
11161
- const result = {};
11162
- const context = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleContext).call(this);
11163
- if (context.includes('.')) {
11164
- const parts = context.split('.');
11165
- result.contextType = 'variable';
11166
- result.context = parts[0];
11167
- result.element = parts[1];
11212
+ parseRuleSource() {
11213
+ const result = {};
11214
+ const context = this.parseRuleContext();
11215
+ if (context.includes('.')) {
11216
+ const parts = context.split('.');
11217
+ result.context = parts[0];
11218
+ result.element = parts[1];
11219
+ }
11220
+ else {
11221
+ result.context = context;
11222
+ }
11223
+ if (this.parser.hasMore() && this.parser.peek()?.value === ':') {
11224
+ this.parser.consume(':');
11225
+ result.type = this.parser.consume().value;
11226
+ }
11227
+ if (this.parser.hasMore() && this.parser.peek()?.value === 'default') {
11228
+ this.parser.consume('default');
11229
+ this.parser.consumeAndParse();
11230
+ }
11231
+ if (this.parser.peek()?.value === 'first' ||
11232
+ this.parser.peek()?.value === 'not_first' ||
11233
+ this.parser.peek()?.value === 'last' ||
11234
+ this.parser.peek()?.value === 'not_last' ||
11235
+ this.parser.peek()?.value === 'only_one') {
11236
+ result.listMode = this.parser.consume().value;
11237
+ }
11238
+ if (this.parser.peek()?.value === 'as') {
11239
+ this.parser.consume('Symbol', 'as');
11240
+ result.variable = this.parser.consume().value;
11241
+ }
11242
+ if (this.parser.peek()?.value === 'where') {
11243
+ this.parser.consume('Symbol', 'where');
11244
+ const whereFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11245
+ result.condition = whereFhirPath.toString();
11246
+ }
11247
+ if (this.parser.peek()?.value === 'check') {
11248
+ this.parser.consume('Symbol', 'check');
11249
+ const checkFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11250
+ result.check = checkFhirPath.toString();
11251
+ }
11252
+ return result;
11168
11253
  }
11169
- else {
11170
- result.context = context;
11254
+ parseRuleTargets() {
11255
+ const targets = [this.parseRuleTarget()];
11256
+ while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
11257
+ this.parser.consume(',');
11258
+ targets.push(this.parseRuleTarget());
11259
+ }
11260
+ return targets;
11171
11261
  }
11172
- if (this.parser.peek()?.value === '=') {
11173
- this.parser.consume('=');
11174
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetTransform).call(this, result);
11262
+ parseRuleTarget() {
11263
+ const result = {};
11264
+ const context = this.parseRuleContext();
11265
+ if (context.includes('.')) {
11266
+ const parts = context.split('.');
11267
+ result.contextType = 'variable';
11268
+ result.context = parts[0];
11269
+ result.element = parts[1];
11270
+ }
11271
+ else {
11272
+ result.context = context;
11273
+ }
11274
+ if (this.parser.peek()?.value === '=') {
11275
+ this.parser.consume('=');
11276
+ this.parseRuleTargetTransform(result);
11277
+ }
11278
+ if (this.parser.peek()?.value === 'as') {
11279
+ this.parser.consume('Symbol', 'as');
11280
+ result.variable = this.parser.consume().value;
11281
+ }
11282
+ if (this.parser.peek()?.value === 'first' ||
11283
+ this.parser.peek()?.value === 'share' ||
11284
+ this.parser.peek()?.value === 'last' ||
11285
+ this.parser.peek()?.value === 'collate') {
11286
+ result.listMode = [this.parser.consume().value];
11287
+ }
11288
+ return result;
11175
11289
  }
11176
- if (this.parser.peek()?.value === 'as') {
11177
- this.parser.consume('Symbol', 'as');
11178
- result.variable = this.parser.consume().value;
11290
+ parseRuleTargetTransform(result) {
11291
+ result.transform = 'copy';
11292
+ const transformFhirPath = this.parser.consumeAndParse(6 /* OperatorPrecedence.As */);
11293
+ if (transformFhirPath instanceof SymbolAtom) {
11294
+ this.parseRuleTargetSymbol(result, transformFhirPath);
11295
+ }
11296
+ else if (transformFhirPath instanceof FunctionAtom) {
11297
+ this.parseRuleTargetFunction(result, transformFhirPath);
11298
+ }
11299
+ else if (transformFhirPath instanceof LiteralAtom) {
11300
+ this.parseRuleTargetLiteral(result, transformFhirPath);
11301
+ }
11302
+ else {
11303
+ throw new Error(`Unexpected FHIRPath: ${transformFhirPath}`);
11304
+ }
11179
11305
  }
11180
- if (this.parser.peek()?.value === 'first' ||
11181
- this.parser.peek()?.value === 'share' ||
11182
- this.parser.peek()?.value === 'last' ||
11183
- this.parser.peek()?.value === 'collate') {
11184
- result.listMode = [this.parser.consume().value];
11306
+ parseRuleTargetSymbol(result, literalAtom) {
11307
+ result.parameter = [{ valueId: literalAtom.name }];
11185
11308
  }
11186
- return result;
11187
- }, _StructureMapParser_parseRuleTargetTransform = function _StructureMapParser_parseRuleTargetTransform(result) {
11188
- result.transform = 'copy';
11189
- const transformFhirPath = this.parser.consumeAndParse(6 /* OperatorPrecedence.As */);
11190
- if (transformFhirPath instanceof SymbolAtom) {
11191
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetSymbol).call(this, result, transformFhirPath);
11309
+ parseRuleTargetFunction(result, functionAtom) {
11310
+ const functionName = functionAtom.name;
11311
+ switch (functionName) {
11312
+ case 'create':
11313
+ result.parameter = [
11314
+ {
11315
+ valueString: (functionAtom.args?.[0]).value.value,
11316
+ },
11317
+ ];
11318
+ break;
11319
+ case 'translate':
11320
+ result.parameter = [{}];
11321
+ break;
11322
+ default:
11323
+ throw new Error('Unknown target function: ' + functionName);
11324
+ }
11192
11325
  }
11193
- else if (transformFhirPath instanceof FunctionAtom) {
11194
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetFunction).call(this, result, transformFhirPath);
11326
+ parseRuleTargetLiteral(result, literalAtom) {
11327
+ switch (literalAtom.value.type) {
11328
+ case 'boolean':
11329
+ result.parameter = [{ valueBoolean: literalAtom.value.value }];
11330
+ break;
11331
+ case 'decimal':
11332
+ result.parameter = [{ valueDecimal: literalAtom.value.value }];
11333
+ break;
11334
+ case 'string':
11335
+ result.parameter = [{ valueString: literalAtom.value.value }];
11336
+ break;
11337
+ default:
11338
+ throw new Error('Unknown target literal type: ' + literalAtom.value.type);
11339
+ }
11195
11340
  }
11196
- else if (transformFhirPath instanceof LiteralAtom) {
11197
- __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetLiteral).call(this, result, transformFhirPath);
11341
+ parseRuleContext() {
11342
+ let identifier = this.parser.consume().value;
11343
+ while (this.parser.peek()?.value === '.') {
11344
+ this.parser.consume('.');
11345
+ identifier += '.' + this.parser.consume().value;
11346
+ }
11347
+ return identifier;
11198
11348
  }
11199
- else {
11200
- throw new Error(`Unexpected FHIRPath: ${transformFhirPath}`);
11201
- }
11202
- }, _StructureMapParser_parseRuleTargetSymbol = function _StructureMapParser_parseRuleTargetSymbol(result, literalAtom) {
11203
- result.parameter = [{ valueId: literalAtom.name }];
11204
- }, _StructureMapParser_parseRuleTargetFunction = function _StructureMapParser_parseRuleTargetFunction(result, functionAtom) {
11205
- const functionName = functionAtom.name;
11206
- switch (functionName) {
11207
- case 'create':
11208
- result.parameter = [
11209
- {
11210
- valueString: (functionAtom.args?.[0]).value.value,
11211
- },
11212
- ];
11213
- break;
11214
- case 'translate':
11215
- result.parameter = [{}];
11216
- break;
11217
- default:
11218
- throw new Error('Unknown target function: ' + functionName);
11349
+ parseRuleDependents() {
11350
+ const atom = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11351
+ return [
11352
+ {
11353
+ name: atom.name,
11354
+ variable: atom.args.map((arg) => arg.name),
11355
+ },
11356
+ ];
11219
11357
  }
11220
- }, _StructureMapParser_parseRuleTargetLiteral = function _StructureMapParser_parseRuleTargetLiteral(result, literalAtom) {
11221
- switch (literalAtom.value.type) {
11222
- case 'boolean':
11223
- result.parameter = [{ valueBoolean: literalAtom.value.value }];
11224
- break;
11225
- case 'decimal':
11226
- result.parameter = [{ valueDecimal: literalAtom.value.value }];
11227
- break;
11228
- case 'string':
11229
- result.parameter = [{ valueString: literalAtom.value.value }];
11230
- break;
11231
- default:
11232
- throw new Error('Unknown target literal type: ' + literalAtom.value.type);
11233
- }
11234
- }, _StructureMapParser_parseRuleContext = function _StructureMapParser_parseRuleContext() {
11235
- let identifier = this.parser.consume().value;
11236
- while (this.parser.peek()?.value === '.') {
11237
- this.parser.consume('.');
11238
- identifier += '.' + this.parser.consume().value;
11239
- }
11240
- return identifier;
11241
- }, _StructureMapParser_parseRuleDependents = function _StructureMapParser_parseRuleDependents() {
11242
- const atom = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
11243
- return [
11244
- {
11245
- name: atom.name,
11246
- variable: atom.args.map((arg) => arg.name),
11247
- },
11248
- ];
11249
- }, _StructureMapParser_parseConceptMap = function _StructureMapParser_parseConceptMap() {
11250
- while (this.parser.peek()?.value !== '}') {
11251
- this.parser.consume();
11358
+ parseConceptMap() {
11359
+ while (this.parser.peek()?.value !== '}') {
11360
+ this.parser.consume();
11361
+ }
11362
+ this.parser.consume('}');
11252
11363
  }
11253
- this.parser.consume('}');
11254
- };
11364
+ }
11255
11365
  const fhirPathParserBuilder$1 = initFhirPathParserBuilder()
11256
11366
  .registerInfix('->', { precedence: 100 /* OperatorPrecedence.Arrow */ })
11257
11367
  .registerInfix(';', { precedence: 200 /* OperatorPrecedence.Semicolon */ });
@@ -11562,7 +11672,6 @@
11562
11672
  }
11563
11673
  }
11564
11674
 
11565
- var _FhirSchemaValidator_instances, _FhirSchemaValidator_issues, _FhirSchemaValidator_root, _FhirSchemaValidator_validateObject, _FhirSchemaValidator_checkProperties, _FhirSchemaValidator_checkProperty, _FhirSchemaValidator_checkPropertyValue, _FhirSchemaValidator_validatePrimitiveType, _FhirSchemaValidator_validateString, _FhirSchemaValidator_validateNumber, _FhirSchemaValidator_checkAdditionalProperties, _FhirSchemaValidator_checkAdditionalProperty, _FhirSchemaValidator_checkPrimitiveElement, _FhirSchemaValidator_createIssue;
11566
11675
  /*
11567
11676
  * This file provides schema validation utilities for FHIR JSON objects.
11568
11677
  *
@@ -11724,14 +11833,11 @@
11724
11833
  }
11725
11834
  class FhirSchemaValidator {
11726
11835
  constructor(root) {
11727
- _FhirSchemaValidator_instances.add(this);
11728
- _FhirSchemaValidator_issues.set(this, void 0);
11729
- _FhirSchemaValidator_root.set(this, void 0);
11730
- __classPrivateFieldSet(this, _FhirSchemaValidator_issues, [], "f");
11731
- __classPrivateFieldSet(this, _FhirSchemaValidator_root, root, "f");
11836
+ this.issues = [];
11837
+ this.root = root;
11732
11838
  }
11733
11839
  validate() {
11734
- const resource = __classPrivateFieldGet(this, _FhirSchemaValidator_root, "f");
11840
+ const resource = this.root;
11735
11841
  if (!resource) {
11736
11842
  throw new OperationOutcomeError(validationError('Resource is null'));
11737
11843
  }
@@ -11740,142 +11846,172 @@
11740
11846
  throw new OperationOutcomeError(validationError('Missing resource type'));
11741
11847
  }
11742
11848
  // Check for "null" once for the entire object hierarchy
11743
- checkForNull(resource, '', __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f"));
11744
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, toTypedValue(resource), resourceType);
11745
- if (__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").length > 0) {
11849
+ checkForNull(resource, '', this.issues);
11850
+ this.validateObject(toTypedValue(resource), resourceType);
11851
+ if (this.issues.length > 0) {
11746
11852
  throw new OperationOutcomeError({
11747
11853
  resourceType: 'OperationOutcome',
11748
- issue: __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f"),
11854
+ issue: this.issues,
11749
11855
  });
11750
11856
  }
11751
11857
  }
11752
- }
11753
- _FhirSchemaValidator_issues = new WeakMap(), _FhirSchemaValidator_root = new WeakMap(), _FhirSchemaValidator_instances = new WeakSet(), _FhirSchemaValidator_validateObject = function _FhirSchemaValidator_validateObject(typedValue, path) {
11754
- const definition = globalSchema.types[typedValue.type];
11755
- if (!definition) {
11756
- throw new OperationOutcomeError(validationError('Unknown type: ' + typedValue.type));
11757
- }
11758
- const propertyDefinitions = definition.properties;
11759
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkProperties).call(this, path, propertyDefinitions, typedValue);
11760
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkAdditionalProperties).call(this, path, typedValue, propertyDefinitions);
11761
- }, _FhirSchemaValidator_checkProperties = function _FhirSchemaValidator_checkProperties(path, propertyDefinitions, typedValue) {
11762
- for (const [key, elementDefinition] of Object.entries(propertyDefinitions)) {
11763
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkProperty).call(this, path + '.' + key, elementDefinition, typedValue);
11858
+ validateObject(typedValue, path) {
11859
+ const definition = globalSchema.types[typedValue.type];
11860
+ if (!definition) {
11861
+ throw new OperationOutcomeError(validationError('Unknown type: ' + typedValue.type));
11862
+ }
11863
+ const propertyDefinitions = definition.properties;
11864
+ this.checkProperties(path, propertyDefinitions, typedValue);
11865
+ this.checkAdditionalProperties(path, typedValue, propertyDefinitions);
11764
11866
  }
11765
- }, _FhirSchemaValidator_checkProperty = function _FhirSchemaValidator_checkProperty(path, elementDefinition, typedValue) {
11766
- const propertyName = path.split('.').pop();
11767
- const value = getTypedPropertyValue(typedValue, propertyName);
11768
- if (isEmpty(value)) {
11769
- if (elementDefinition.min !== undefined && elementDefinition.min > 0) {
11770
- __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Missing required property'));
11867
+ checkProperties(path, propertyDefinitions, typedValue) {
11868
+ for (const [key, elementDefinition] of Object.entries(propertyDefinitions)) {
11869
+ this.checkProperty(path + '.' + key, elementDefinition, typedValue);
11771
11870
  }
11772
- return;
11773
11871
  }
11774
- if (elementDefinition.max === '*') {
11775
- if (!Array.isArray(value)) {
11776
- __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Expected array for property'));
11872
+ checkProperty(path, elementDefinition, typedValue) {
11873
+ const propertyName = path.split('.').pop();
11874
+ const value = getTypedPropertyValue(typedValue, propertyName);
11875
+ if (isEmpty(value)) {
11876
+ if (elementDefinition.min !== undefined && elementDefinition.min > 0) {
11877
+ this.issues.push(createStructureIssue(path, 'Missing required property'));
11878
+ }
11777
11879
  return;
11778
11880
  }
11779
- for (const item of value) {
11780
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPropertyValue).call(this, path, elementDefinition, item);
11881
+ if (elementDefinition.max === '*') {
11882
+ if (!Array.isArray(value)) {
11883
+ this.issues.push(createStructureIssue(path, 'Expected array for property'));
11884
+ return;
11885
+ }
11886
+ for (const item of value) {
11887
+ this.checkPropertyValue(path, elementDefinition, item);
11888
+ }
11889
+ }
11890
+ else {
11891
+ if (Array.isArray(value)) {
11892
+ this.issues.push(createStructureIssue(path, 'Expected single value for property'));
11893
+ return;
11894
+ }
11895
+ this.checkPropertyValue(path, elementDefinition, value);
11781
11896
  }
11782
11897
  }
11783
- else {
11784
- if (Array.isArray(value)) {
11785
- __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Expected single value for property'));
11898
+ checkPropertyValue(path, elementDefinition, typedValue) {
11899
+ if (typedValue.value === null) {
11900
+ // Null handled separately
11786
11901
  return;
11787
11902
  }
11788
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPropertyValue).call(this, path, elementDefinition, value);
11789
- }
11790
- }, _FhirSchemaValidator_checkPropertyValue = function _FhirSchemaValidator_checkPropertyValue(path, elementDefinition, typedValue) {
11791
- if (typedValue.value === null) {
11792
- // Null handled separately
11793
- return;
11794
- }
11795
- if (isLowerCase(typedValue.type.charAt(0))) {
11796
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validatePrimitiveType).call(this, elementDefinition, typedValue);
11797
- }
11798
- else {
11799
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, typedValue, path);
11800
- }
11801
- }, _FhirSchemaValidator_validatePrimitiveType = function _FhirSchemaValidator_validatePrimitiveType(elementDefinition, typedValue) {
11802
- const { type, value } = typedValue;
11803
- if (value === null) {
11804
- // Null handled separately, so this code should never be reached
11805
- // Leaving this check in place for now, in case we change the null handling
11806
- return;
11807
- }
11808
- // First, make sure the value is the correct JS type
11809
- const expectedType = fhirTypeToJsType[typedValue.type];
11810
- if (typeof value !== expectedType) {
11811
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid type for ' + type);
11812
- return;
11813
- }
11814
- // Then, perform additional checks for specialty types
11815
- if (expectedType === 'string') {
11816
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateString).call(this, elementDefinition, type, value);
11817
- }
11818
- else if (expectedType === 'number') {
11819
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateNumber).call(this, elementDefinition, type, value);
11903
+ if (isLowerCase(typedValue.type.charAt(0))) {
11904
+ this.validatePrimitiveType(elementDefinition, typedValue);
11905
+ }
11906
+ else {
11907
+ this.validateObject(typedValue, path);
11908
+ }
11820
11909
  }
11821
- }, _FhirSchemaValidator_validateString = function _FhirSchemaValidator_validateString(elementDefinition, type, value) {
11822
- if (!value.trim()) {
11823
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid empty string');
11824
- return;
11910
+ validatePrimitiveType(elementDefinition, typedValue) {
11911
+ const { type, value } = typedValue;
11912
+ if (value === null) {
11913
+ // Null handled separately, so this code should never be reached
11914
+ // Leaving this check in place for now, in case we change the null handling
11915
+ return;
11916
+ }
11917
+ // First, make sure the value is the correct JS type
11918
+ const expectedType = fhirTypeToJsType[typedValue.type];
11919
+ if (typeof value !== expectedType) {
11920
+ this.createIssue(elementDefinition, 'Invalid type for ' + type);
11921
+ return;
11922
+ }
11923
+ // Then, perform additional checks for specialty types
11924
+ if (expectedType === 'string') {
11925
+ this.validateString(elementDefinition, type, value);
11926
+ }
11927
+ else if (expectedType === 'number') {
11928
+ this.validateNumber(elementDefinition, type, value);
11929
+ }
11825
11930
  }
11826
- // Try to get the regex
11827
- const valueDefinition = globalSchema.types[type]?.properties?.['value'];
11828
- if (valueDefinition?.type) {
11829
- const regex = getExtensionValue(valueDefinition.type[0], 'http://hl7.org/fhir/StructureDefinition/regex');
11830
- if (regex) {
11831
- if (!value.match(new RegExp(regex))) {
11832
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid ' + type + ' format');
11931
+ validateString(elementDefinition, type, value) {
11932
+ if (!value.trim()) {
11933
+ this.createIssue(elementDefinition, 'Invalid empty string');
11934
+ return;
11935
+ }
11936
+ // Try to get the regex
11937
+ const valueDefinition = globalSchema.types[type]?.properties?.['value'];
11938
+ if (valueDefinition?.type) {
11939
+ const regex = getExtensionValue(valueDefinition.type[0], 'http://hl7.org/fhir/StructureDefinition/regex');
11940
+ if (regex) {
11941
+ if (!value.match(new RegExp(regex))) {
11942
+ this.createIssue(elementDefinition, 'Invalid ' + type + ' format');
11943
+ }
11833
11944
  }
11834
11945
  }
11835
11946
  }
11836
- }, _FhirSchemaValidator_validateNumber = function _FhirSchemaValidator_validateNumber(elementDefinition, type, value) {
11837
- if (isNaN(value) || !isFinite(value)) {
11838
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid ' + type + ' value');
11839
- return;
11840
- }
11841
- if (isIntegerType(type) && !Number.isInteger(value)) {
11842
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is not an integer');
11843
- }
11844
- if (type === exports.PropertyType.positiveInt && value <= 0) {
11845
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is less than or equal to zero');
11846
- }
11847
- if (type === exports.PropertyType.unsignedInt && value < 0) {
11848
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is negative');
11947
+ validateNumber(elementDefinition, type, value) {
11948
+ if (isNaN(value) || !isFinite(value)) {
11949
+ this.createIssue(elementDefinition, 'Invalid ' + type + ' value');
11950
+ return;
11951
+ }
11952
+ if (isIntegerType(type) && !Number.isInteger(value)) {
11953
+ this.createIssue(elementDefinition, 'Number is not an integer');
11954
+ }
11955
+ if (type === exports.PropertyType.positiveInt && value <= 0) {
11956
+ this.createIssue(elementDefinition, 'Number is less than or equal to zero');
11957
+ }
11958
+ if (type === exports.PropertyType.unsignedInt && value < 0) {
11959
+ this.createIssue(elementDefinition, 'Number is negative');
11960
+ }
11849
11961
  }
11850
- }, _FhirSchemaValidator_checkAdditionalProperties = function _FhirSchemaValidator_checkAdditionalProperties(path, typedValue, propertyDefinitions) {
11851
- const object = typedValue.value;
11852
- for (const key of Object.keys(object)) {
11853
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkAdditionalProperty).call(this, path, key, typedValue, propertyDefinitions);
11962
+ checkAdditionalProperties(path, typedValue, propertyDefinitions) {
11963
+ const object = typedValue.value;
11964
+ for (const key of Object.keys(object)) {
11965
+ this.checkAdditionalProperty(path, key, typedValue, propertyDefinitions);
11966
+ }
11854
11967
  }
11855
- }, _FhirSchemaValidator_checkAdditionalProperty = function _FhirSchemaValidator_checkAdditionalProperty(path, key, typedValue, propertyDefinitions) {
11856
- if (!baseResourceProperties.has(key) &&
11857
- !(key in propertyDefinitions) &&
11858
- !isChoiceOfType(key, typedValue, propertyDefinitions) &&
11859
- !__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPrimitiveElement).call(this, path, key, typedValue)) {
11860
- const expression = `${path}.${key}`;
11861
- __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(expression, `Invalid additional property "${expression}"`));
11968
+ /**
11969
+ * Checks if the given property is allowed on the given object.
11970
+ * @param path The path of the current object.
11971
+ * @param key The key of a property to check.
11972
+ * @param typedValue The current object.
11973
+ * @param propertyDefinitions The property definitions of the current object.
11974
+ */
11975
+ checkAdditionalProperty(path, key, typedValue, propertyDefinitions) {
11976
+ if (!baseResourceProperties.has(key) &&
11977
+ !(key in propertyDefinitions) &&
11978
+ !isChoiceOfType(key, typedValue, propertyDefinitions) &&
11979
+ !this.checkPrimitiveElement(path, key, typedValue)) {
11980
+ const expression = `${path}.${key}`;
11981
+ this.issues.push(createStructureIssue(expression, `Invalid additional property "${expression}"`));
11982
+ }
11862
11983
  }
11863
- }, _FhirSchemaValidator_checkPrimitiveElement = function _FhirSchemaValidator_checkPrimitiveElement(path, key, typedValue) {
11864
- // Primitive element starts with underscore
11865
- if (!key.startsWith('_')) {
11866
- return false;
11984
+ /**
11985
+ * Checks the element for a primitive.
11986
+ *
11987
+ * FHIR elements with primitive data types are represented in two parts:
11988
+ * 1) A JSON property with the name of the element, which has a JSON type of number, boolean, or string
11989
+ * 2) a JSON property with _ prepended to the name of the element, which, if present, contains the value's id and/or extensions
11990
+ *
11991
+ * See: https://hl7.org/fhir/json.html#primitive
11992
+ *
11993
+ * @param path The path to the property
11994
+ * @param key
11995
+ * @param typedValue
11996
+ */
11997
+ checkPrimitiveElement(path, key, typedValue) {
11998
+ // Primitive element starts with underscore
11999
+ if (!key.startsWith('_')) {
12000
+ return false;
12001
+ }
12002
+ // Validate the non-underscore property exists
12003
+ const primitiveKey = key.slice(1);
12004
+ if (!(primitiveKey in typedValue.value)) {
12005
+ return false;
12006
+ }
12007
+ // Then validate the element
12008
+ this.validateObject({ type: 'Element', value: typedValue.value[key] }, path);
12009
+ return true;
11867
12010
  }
11868
- // Validate the non-underscore property exists
11869
- const primitiveKey = key.slice(1);
11870
- if (!(primitiveKey in typedValue.value)) {
11871
- return false;
12011
+ createIssue(elementDefinition, message) {
12012
+ this.issues.push(createStructureIssue(elementDefinition.path, message));
11872
12013
  }
11873
- // Then validate the element
11874
- __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, { type: 'Element', value: typedValue.value[key] }, path);
11875
- return true;
11876
- }, _FhirSchemaValidator_createIssue = function _FhirSchemaValidator_createIssue(elementDefinition, message) {
11877
- __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(elementDefinition.path, message));
11878
- };
12014
+ }
11879
12015
  function isIntegerType(propertyType) {
11880
12016
  return (propertyType === exports.PropertyType.integer ||
11881
12017
  propertyType === exports.PropertyType.positiveInt ||
@@ -12183,7 +12319,18 @@
12183
12319
  * @returns A parsed SearchRequest.
12184
12320
  */
12185
12321
  function parseSearchRequest(resourceType, query) {
12186
- return parseSearchImpl(resourceType, query);
12322
+ const queryArray = [];
12323
+ for (const [key, value] of Object.entries(query)) {
12324
+ if (Array.isArray(value)) {
12325
+ for (let i = 0; i < value.length; i++) {
12326
+ queryArray.push([key, value[i]]);
12327
+ }
12328
+ }
12329
+ else {
12330
+ queryArray.push([key, value || '']);
12331
+ }
12332
+ }
12333
+ return parseSearchImpl(resourceType, queryArray);
12187
12334
  }
12188
12335
  /**
12189
12336
  * Parses a search URL into a search request.
@@ -12192,7 +12339,7 @@
12192
12339
  */
12193
12340
  function parseSearchUrl(url) {
12194
12341
  const resourceType = url.pathname.split('/').filter(Boolean).pop();
12195
- return parseSearchImpl(resourceType, Object.fromEntries(url.searchParams.entries()));
12342
+ return parseSearchImpl(resourceType, url.searchParams.entries());
12196
12343
  }
12197
12344
  /**
12198
12345
  * Parses a URL string into a SearchRequest.
@@ -12206,13 +12353,8 @@
12206
12353
  const searchRequest = {
12207
12354
  resourceType,
12208
12355
  };
12209
- for (const [key, value] of Object.entries(query)) {
12210
- if (Array.isArray(value)) {
12211
- value.forEach((element) => parseKeyValue(searchRequest, key, element));
12212
- }
12213
- else {
12214
- parseKeyValue(searchRequest, key, value ?? '');
12215
- }
12356
+ for (const [key, value] of query) {
12357
+ parseKeyValue(searchRequest, key, value);
12216
12358
  }
12217
12359
  return searchRequest;
12218
12360
  }
@@ -12613,6 +12755,7 @@
12613
12755
  exports.UnaryOperatorAtom = UnaryOperatorAtom;
12614
12756
  exports.UnionAtom = UnionAtom;
12615
12757
  exports.XorAtom = XorAtom;
12758
+ exports.accepted = accepted;
12616
12759
  exports.allOk = allOk;
12617
12760
  exports.arrayBufferToBase64 = arrayBufferToBase64;
12618
12761
  exports.arrayBufferToHex = arrayBufferToHex;