@medplum/core 2.0.12 → 2.0.14

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.
@@ -4,6 +4,40 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.medplum = global.medplum || {}, global.medplum.core = {})));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
+ /**
8
+ * More on Bundles can be found here
9
+ * http://hl7.org/fhir/R4/bundle.html
10
+ */
11
+ /**
12
+ * Takes a bundle and creates a Transaction Type bundle
13
+ * @param bundle The Bundle object that we'll receive from the search query
14
+ * @returns transaction type bundle
15
+ */
16
+ function convertToTransactionBundle(bundle) {
17
+ for (const entry of bundle.entry || []) {
18
+ delete entry?.resource?.meta;
19
+ entry.fullUrl = 'urn:uuid:' + entry?.resource?.id;
20
+ delete entry?.resource?.id;
21
+ }
22
+ const input = bundle.entry;
23
+ const jsonString = JSON.stringify({
24
+ resourceType: 'Bundle',
25
+ type: 'transaction',
26
+ entry: input?.map((entry) => ({
27
+ fullUrl: entry.fullUrl,
28
+ request: { method: 'POST', url: entry.resource.resourceType },
29
+ resource: entry.resource,
30
+ })),
31
+ }, replacer, 2);
32
+ return JSON.parse(jsonString);
33
+ }
34
+ function replacer(key, value) {
35
+ if (key === 'reference' && typeof value === 'string' && value.includes('/')) {
36
+ return 'urn:uuid:' + value.split('/')[1];
37
+ }
38
+ return value;
39
+ }
40
+
7
41
  /******************************************************************************
8
42
  Copyright (c) Microsoft Corporation.
9
43
 
@@ -6312,7 +6346,7 @@
6312
6346
  .replace('_', ' ')
6313
6347
  .replace(/\s+/g, ' ');
6314
6348
  }
6315
- const capitalizedWords = new Set(['ID', 'PKCE', 'JWKS', 'URI', 'URL']);
6349
+ const capitalizedWords = new Set(['ID', 'IP', 'PKCE', 'JWKS', 'URI', 'URL']);
6316
6350
  function capitalizeDisplayWord(word) {
6317
6351
  const upper = word.toUpperCase();
6318
6352
  if (capitalizedWords.has(upper)) {
@@ -6369,8 +6403,8 @@
6369
6403
 
6370
6404
  // PKCE auth based on:
6371
6405
  // https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
6372
- var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_autoBatchTime, _MedplumClient_autoBatchQueue, _MedplumClient_clientId, _MedplumClient_clientSecret, _MedplumClient_autoBatchTimerId, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_cacheResource, _MedplumClient_deleteCacheEntry, _MedplumClient_request, _MedplumClient_fetchWithRetry, _MedplumClient_executeAutoBatch, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
6373
- const MEDPLUM_VERSION = "2.0.12-b25d6c05";
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";
6374
6408
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
6375
6409
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
6376
6410
  const DEFAULT_CACHE_TIME = 60000; // 60 seconds
@@ -6444,6 +6478,7 @@
6444
6478
  _MedplumClient_authorizeUrl.set(this, void 0);
6445
6479
  _MedplumClient_tokenUrl.set(this, void 0);
6446
6480
  _MedplumClient_logoutUrl.set(this, void 0);
6481
+ _MedplumClient_exchangeUrl.set(this, void 0);
6447
6482
  _MedplumClient_onUnauthenticated.set(this, void 0);
6448
6483
  _MedplumClient_autoBatchTime.set(this, void 0);
6449
6484
  _MedplumClient_autoBatchQueue.set(this, void 0);
@@ -6467,11 +6502,12 @@
6467
6502
  __classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
6468
6503
  __classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
6469
6504
  __classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
6470
- __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'fhir/R4/', "f");
6505
+ __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + (ensureTrailingSlash(options?.fhirUrlPath) || 'fhir/R4/'), "f");
6471
6506
  __classPrivateFieldSet(this, _MedplumClient_clientId, options?.clientId || '', "f");
6472
6507
  __classPrivateFieldSet(this, _MedplumClient_authorizeUrl, options?.authorizeUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
6473
6508
  __classPrivateFieldSet(this, _MedplumClient_tokenUrl, options?.tokenUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
6474
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");
6475
6511
  __classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options?.onUnauthenticated, "f");
6476
6512
  __classPrivateFieldSet(this, _MedplumClient_autoBatchTime, options?.autoBatchTime ?? 0, "f");
6477
6513
  __classPrivateFieldSet(this, _MedplumClient_autoBatchQueue, [], "f");
@@ -6795,6 +6831,34 @@
6795
6831
  const loginRequest = await this.ensureCodeChallenge(baseLogin);
6796
6832
  window.location.assign(this.getExternalAuthRedirectUri(authorizeUrl, clientId, redirectUri, loginRequest));
6797
6833
  }
6834
+ /**
6835
+ * Exchange an external access token for a Medplum access token.
6836
+ * @param token The access token that was generated by the external identity provider.
6837
+ * @param clientId The ID of the `ClientApplication` in your Medplum project that will be making the exchange request.
6838
+ * @category Authentication
6839
+ */
6840
+ async exchangeExternalAccessToken(token, clientId) {
6841
+ clientId = clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f");
6842
+ if (!clientId) {
6843
+ throw new Error('MedplumClient is missing clientId');
6844
+ }
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();
6861
+ }
6798
6862
  /**
6799
6863
  * Builds the external identity provider redirect URI.
6800
6864
  * @param authorizeUrl The external authorization URL.
@@ -6973,6 +7037,40 @@
6973
7037
  __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
6974
7038
  return promise;
6975
7039
  }
7040
+ /**
7041
+ * Creates an
7042
+ * [async generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator)
7043
+ * over a series of FHIR search requests for paginated search results. Each iteration of the generator yields
7044
+ * the array of resources on each page.
7045
+ *
7046
+ *
7047
+ * ```typescript
7048
+ * for await (const page of medplum.searchResourcePages('Patient', { _count: 10 })) {
7049
+ * for (const patient of page) {
7050
+ * console.log(`Processing Patient resource with ID: ${patient.id}`);
7051
+ * }
7052
+ * }
7053
+ * ```
7054
+ *
7055
+ * @category Search
7056
+ * @param resourceType The FHIR resource type.
7057
+ * @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
7058
+ * @param options Optional fetch options.
7059
+ * @returns An async generator, where each result is an array of resources for each page.
7060
+ */
7061
+ async *searchResourcePages(resourceType, query, options = {}) {
7062
+ let url = this.fhirSearchUrl(resourceType, query);
7063
+ while (url) {
7064
+ const searchParams = new URL(url).searchParams;
7065
+ const bundle = await this.search(resourceType, searchParams, options);
7066
+ const nextLink = bundle?.link?.find((link) => link.relation === 'next');
7067
+ if (!bundle?.entry?.length && !nextLink) {
7068
+ break;
7069
+ }
7070
+ yield bundle?.entry?.map((e) => e.resource) ?? [];
7071
+ url = nextLink?.url ? new URL(nextLink?.url) : undefined;
7072
+ }
7073
+ }
6976
7074
  /**
6977
7075
  * Searches a ValueSet resource using the "expand" operation.
6978
7076
  * See: https://www.hl7.org/fhir/operation-valueset-expand.html
@@ -7835,8 +7933,17 @@
7835
7933
  formBody.set('client_secret', clientSecret);
7836
7934
  return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
7837
7935
  }
7936
+ /**
7937
+ * Invite a user to a project.
7938
+ * @param projectId The project ID.
7939
+ * @param body The InviteBody.
7940
+ * @returns Promise that returns an invite result or an operation outcome.
7941
+ */
7942
+ async invite(projectId, body) {
7943
+ return this.post('admin/projects/' + projectId + '/invite', body);
7944
+ }
7838
7945
  }
7839
- _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(), _MedplumClient_storage = new WeakMap(), _MedplumClient_requestCache = new WeakMap(), _MedplumClient_cacheTime = new WeakMap(), _MedplumClient_baseUrl = new WeakMap(), _MedplumClient_fhirBaseUrl = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = new WeakMap(), _MedplumClient_autoBatchTime = new WeakMap(), _MedplumClient_autoBatchQueue = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_clientSecret = new WeakMap(), _MedplumClient_autoBatchTimerId = new WeakMap(), _MedplumClient_accessToken = new WeakMap(), _MedplumClient_refreshToken = new WeakMap(), _MedplumClient_refreshPromise = new WeakMap(), _MedplumClient_profilePromise = new WeakMap(), _MedplumClient_profile = new WeakMap(), _MedplumClient_config = new WeakMap(), _MedplumClient_instances = new WeakSet(), _MedplumClient_addLogin = function _MedplumClient_addLogin(newLogin) {
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) {
7840
7947
  const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
7841
7948
  logins.push(newLogin);
7842
7949
  __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
@@ -7938,7 +8045,12 @@
7938
8045
  // If there is only one request in the batch, just execute it
7939
8046
  if (entries.length === 1) {
7940
8047
  const entry = entries[0];
7941
- entry.resolve(await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, entry.method, __classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + entry.url, entry.options));
8048
+ 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));
8050
+ }
8051
+ catch (err) {
8052
+ entry.reject(new OperationOutcomeError(normalizeOperationOutcome(err)));
8053
+ }
7942
8054
  return;
7943
8055
  }
7944
8056
  // Build the batch request
@@ -10371,7 +10483,6 @@
10371
10483
  return input;
10372
10484
  }
10373
10485
 
10374
- var _SymbolAtom_instances, _SymbolAtom_evalValue;
10375
10486
  class FhirPathAtom {
10376
10487
  constructor(original, child) {
10377
10488
  this.original = original;
@@ -10411,32 +10522,28 @@
10411
10522
  }
10412
10523
  class SymbolAtom {
10413
10524
  constructor(name) {
10414
- _SymbolAtom_instances.add(this);
10415
10525
  this.name = name;
10416
10526
  }
10417
10527
  eval(context) {
10418
10528
  if (this.name === '$this') {
10419
10529
  return context;
10420
10530
  }
10421
- return context
10422
- .map((e) => __classPrivateFieldGet(this, _SymbolAtom_instances, "m", _SymbolAtom_evalValue).call(this, e))
10423
- .flat()
10424
- .filter((e) => e?.value !== undefined);
10531
+ return context.flatMap((e) => this.evalValue(e)).filter((e) => e?.value !== undefined);
10532
+ }
10533
+ evalValue(typedValue) {
10534
+ const input = typedValue.value;
10535
+ if (!input || typeof input !== 'object') {
10536
+ return undefined;
10537
+ }
10538
+ if (isResource(input) && input.resourceType === this.name) {
10539
+ return typedValue;
10540
+ }
10541
+ return getTypedPropertyValue(typedValue, this.name);
10425
10542
  }
10426
10543
  toString() {
10427
10544
  return this.name;
10428
10545
  }
10429
10546
  }
10430
- _SymbolAtom_instances = new WeakSet(), _SymbolAtom_evalValue = function _SymbolAtom_evalValue(typedValue) {
10431
- const input = typedValue.value;
10432
- if (!input || typeof input !== 'object') {
10433
- return undefined;
10434
- }
10435
- if (isResource(input) && input.resourceType === this.name) {
10436
- return typedValue;
10437
- }
10438
- return getTypedPropertyValue(typedValue, this.name);
10439
- };
10440
10547
  class EmptySetAtom {
10441
10548
  eval() {
10442
10549
  return [];
@@ -11674,6 +11781,10 @@
11674
11781
  }
11675
11782
  }
11676
11783
  else {
11784
+ if (Array.isArray(value)) {
11785
+ __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Expected single value for property'));
11786
+ return;
11787
+ }
11677
11788
  __classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPropertyValue).call(this, path, elementDefinition, value);
11678
11789
  }
11679
11790
  }, _FhirSchemaValidator_checkPropertyValue = function _FhirSchemaValidator_checkPropertyValue(path, elementDefinition, typedValue) {
@@ -12134,6 +12245,9 @@
12134
12245
  searchRequest.total = 'estimate';
12135
12246
  searchRequest.count = 0;
12136
12247
  break;
12248
+ case '_include':
12249
+ searchRequest.include = value;
12250
+ break;
12137
12251
  case '_revinclude':
12138
12252
  searchRequest.revInclude = value;
12139
12253
  break;
@@ -12330,6 +12444,7 @@
12330
12444
  case 'reference':
12331
12445
  return matchesReferenceFilter(resource, filter, searchParam);
12332
12446
  case 'string':
12447
+ case 'uri':
12333
12448
  return matchesStringFilter(resource, filter, searchParam);
12334
12449
  case 'token':
12335
12450
  return matchesTokenFilter(resource, filter, searchParam);
@@ -12509,6 +12624,7 @@
12509
12624
  exports.calculateAgeString = calculateAgeString;
12510
12625
  exports.capitalize = capitalize;
12511
12626
  exports.checkForNull = checkForNull;
12627
+ exports.convertToTransactionBundle = convertToTransactionBundle;
12512
12628
  exports.createReference = createReference;
12513
12629
  exports.createStructureIssue = createStructureIssue;
12514
12630
  exports.created = created;