@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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * More on Bundles can be found here
3
+ * http://hl7.org/fhir/R4/bundle.html
4
+ */
5
+ /**
6
+ * Takes a bundle and creates a Transaction Type bundle
7
+ * @param bundle The Bundle object that we'll receive from the search query
8
+ * @returns transaction type bundle
9
+ */
10
+ function convertToTransactionBundle(bundle) {
11
+ for (const entry of bundle.entry || []) {
12
+ delete entry?.resource?.meta;
13
+ entry.fullUrl = 'urn:uuid:' + entry?.resource?.id;
14
+ delete entry?.resource?.id;
15
+ }
16
+ const input = bundle.entry;
17
+ const jsonString = JSON.stringify({
18
+ resourceType: 'Bundle',
19
+ type: 'transaction',
20
+ entry: input?.map((entry) => ({
21
+ fullUrl: entry.fullUrl,
22
+ request: { method: 'POST', url: entry.resource.resourceType },
23
+ resource: entry.resource,
24
+ })),
25
+ }, replacer, 2);
26
+ return JSON.parse(jsonString);
27
+ }
28
+ function replacer(key, value) {
29
+ if (key === 'reference' && typeof value === 'string' && value.includes('/')) {
30
+ return 'urn:uuid:' + value.split('/')[1];
31
+ }
32
+ return value;
33
+ }
34
+
35
+ export { convertToTransactionBundle };
36
+ //# sourceMappingURL=bundle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.mjs","sources":["../../src/bundle.ts"],"sourcesContent":["import { Bundle } from '@medplum/fhirtypes';\n\n/**\n * More on Bundles can be found here\n * http://hl7.org/fhir/R4/bundle.html\n */\n\n/**\n * Takes a bundle and creates a Transaction Type bundle\n * @param bundle The Bundle object that we'll receive from the search query\n * @returns transaction type bundle\n */\nexport function convertToTransactionBundle(bundle: Bundle): Bundle {\n for (const entry of bundle.entry || []) {\n delete entry?.resource?.meta;\n entry.fullUrl = 'urn:uuid:' + entry?.resource?.id;\n delete entry?.resource?.id;\n }\n const input = bundle.entry;\n const jsonString = JSON.stringify(\n {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: input?.map((entry: any) => ({\n fullUrl: entry.fullUrl,\n request: { method: 'POST', url: entry.resource.resourceType },\n resource: entry.resource,\n })),\n },\n replacer,\n 2\n );\n return JSON.parse(jsonString);\n}\n\nfunction replacer(key: string, value: string): string {\n if (key === 'reference' && typeof value === 'string' && value.includes('/')) {\n return 'urn:uuid:' + value.split('/')[1];\n }\n return value;\n}\n"],"names":[],"mappings":"AAEA;;;AAGG;AAEH;;;;AAIG;AACG,SAAU,0BAA0B,CAAC,MAAc,EAAA;IACvD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE;AACtC,QAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC;QAC7B,KAAK,CAAC,OAAO,GAAG,WAAW,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;AAClD,QAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;AAC5B,KAAA;AACD,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;AAC3B,IAAA,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAC/B;AACE,QAAA,YAAY,EAAE,QAAQ;AACtB,QAAA,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,KAAU,MAAM;YACjC,OAAO,EAAE,KAAK,CAAC,OAAO;AACtB,YAAA,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE;YAC7D,QAAQ,EAAE,KAAK,CAAC,QAAQ;AACzB,SAAA,CAAC,CAAC;AACJ,KAAA,EACD,QAAQ,EACR,CAAC,CACF,CAAC;AACF,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,KAAa,EAAA;AAC1C,IAAA,IAAI,GAAG,KAAK,WAAW,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;QAC3E,OAAO,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,KAAA;AACD,IAAA,OAAO,KAAK,CAAC;AACf;;;;"}
@@ -11,8 +11,8 @@ import { createReference, arrayBufferToBase64 } from './utils.mjs';
11
11
 
12
12
  // PKCE auth based on:
13
13
  // https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
14
- var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_autoBatchTime, _MedplumClient_autoBatchQueue, _MedplumClient_clientId, _MedplumClient_clientSecret, _MedplumClient_autoBatchTimerId, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_cacheResource, _MedplumClient_deleteCacheEntry, _MedplumClient_request, _MedplumClient_fetchWithRetry, _MedplumClient_executeAutoBatch, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
15
- const MEDPLUM_VERSION = "2.0.12-b25d6c05";
14
+ var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_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;
15
+ const MEDPLUM_VERSION = "2.0.14-8c7457fd";
16
16
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
17
17
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
18
18
  const DEFAULT_CACHE_TIME = 60000; // 60 seconds
@@ -86,6 +86,7 @@ class MedplumClient extends EventTarget {
86
86
  _MedplumClient_authorizeUrl.set(this, void 0);
87
87
  _MedplumClient_tokenUrl.set(this, void 0);
88
88
  _MedplumClient_logoutUrl.set(this, void 0);
89
+ _MedplumClient_exchangeUrl.set(this, void 0);
89
90
  _MedplumClient_onUnauthenticated.set(this, void 0);
90
91
  _MedplumClient_autoBatchTime.set(this, void 0);
91
92
  _MedplumClient_autoBatchQueue.set(this, void 0);
@@ -109,11 +110,12 @@ class MedplumClient extends EventTarget {
109
110
  __classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
110
111
  __classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
111
112
  __classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
112
- __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'fhir/R4/', "f");
113
+ __classPrivateFieldSet(this, _MedplumClient_fhirBaseUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + (ensureTrailingSlash(options?.fhirUrlPath) || 'fhir/R4/'), "f");
113
114
  __classPrivateFieldSet(this, _MedplumClient_clientId, options?.clientId || '', "f");
114
115
  __classPrivateFieldSet(this, _MedplumClient_authorizeUrl, options?.authorizeUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/authorize', "f");
115
116
  __classPrivateFieldSet(this, _MedplumClient_tokenUrl, options?.tokenUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/token', "f");
116
117
  __classPrivateFieldSet(this, _MedplumClient_logoutUrl, options?.logoutUrl || __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'oauth2/logout', "f");
118
+ __classPrivateFieldSet(this, _MedplumClient_exchangeUrl, __classPrivateFieldGet(this, _MedplumClient_baseUrl, "f") + 'auth/exchange', "f");
117
119
  __classPrivateFieldSet(this, _MedplumClient_onUnauthenticated, options?.onUnauthenticated, "f");
118
120
  __classPrivateFieldSet(this, _MedplumClient_autoBatchTime, options?.autoBatchTime ?? 0, "f");
119
121
  __classPrivateFieldSet(this, _MedplumClient_autoBatchQueue, [], "f");
@@ -437,6 +439,34 @@ class MedplumClient extends EventTarget {
437
439
  const loginRequest = await this.ensureCodeChallenge(baseLogin);
438
440
  window.location.assign(this.getExternalAuthRedirectUri(authorizeUrl, clientId, redirectUri, loginRequest));
439
441
  }
442
+ /**
443
+ * Exchange an external access token for a Medplum access token.
444
+ * @param token The access token that was generated by the external identity provider.
445
+ * @param clientId The ID of the `ClientApplication` in your Medplum project that will be making the exchange request.
446
+ * @category Authentication
447
+ */
448
+ async exchangeExternalAccessToken(token, clientId) {
449
+ clientId = clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f");
450
+ if (!clientId) {
451
+ throw new Error('MedplumClient is missing clientId');
452
+ }
453
+ const response = await __classPrivateFieldGet(this, _MedplumClient_fetch, "f").call(this, __classPrivateFieldGet(this, _MedplumClient_exchangeUrl, "f"), {
454
+ method: 'POST',
455
+ headers: { 'Content-Type': 'application/json' },
456
+ body: JSON.stringify({
457
+ clientId: __classPrivateFieldGet(this, _MedplumClient_clientId, "f"),
458
+ externalAccessToken: token,
459
+ }),
460
+ credentials: 'include',
461
+ });
462
+ if (!response.ok) {
463
+ this.clearActiveLogin();
464
+ throw new Error('Failed to fetch tokens');
465
+ }
466
+ const tokens = await response.json();
467
+ await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_verifyTokens).call(this, tokens);
468
+ return this.getProfile();
469
+ }
440
470
  /**
441
471
  * Builds the external identity provider redirect URI.
442
472
  * @param authorizeUrl The external authorization URL.
@@ -615,6 +645,40 @@ class MedplumClient extends EventTarget {
615
645
  __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_setCacheEntry).call(this, cacheKey, promise);
616
646
  return promise;
617
647
  }
648
+ /**
649
+ * Creates an
650
+ * [async generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator)
651
+ * over a series of FHIR search requests for paginated search results. Each iteration of the generator yields
652
+ * the array of resources on each page.
653
+ *
654
+ *
655
+ * ```typescript
656
+ * for await (const page of medplum.searchResourcePages('Patient', { _count: 10 })) {
657
+ * for (const patient of page) {
658
+ * console.log(`Processing Patient resource with ID: ${patient.id}`);
659
+ * }
660
+ * }
661
+ * ```
662
+ *
663
+ * @category Search
664
+ * @param resourceType The FHIR resource type.
665
+ * @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
666
+ * @param options Optional fetch options.
667
+ * @returns An async generator, where each result is an array of resources for each page.
668
+ */
669
+ async *searchResourcePages(resourceType, query, options = {}) {
670
+ let url = this.fhirSearchUrl(resourceType, query);
671
+ while (url) {
672
+ const searchParams = new URL(url).searchParams;
673
+ const bundle = await this.search(resourceType, searchParams, options);
674
+ const nextLink = bundle?.link?.find((link) => link.relation === 'next');
675
+ if (!bundle?.entry?.length && !nextLink) {
676
+ break;
677
+ }
678
+ yield bundle?.entry?.map((e) => e.resource) ?? [];
679
+ url = nextLink?.url ? new URL(nextLink?.url) : undefined;
680
+ }
681
+ }
618
682
  /**
619
683
  * Searches a ValueSet resource using the "expand" operation.
620
684
  * See: https://www.hl7.org/fhir/operation-valueset-expand.html
@@ -1477,8 +1541,17 @@ class MedplumClient extends EventTarget {
1477
1541
  formBody.set('client_secret', clientSecret);
1478
1542
  return __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_fetchTokens).call(this, formBody);
1479
1543
  }
1544
+ /**
1545
+ * Invite a user to a project.
1546
+ * @param projectId The project ID.
1547
+ * @param body The InviteBody.
1548
+ * @returns Promise that returns an invite result or an operation outcome.
1549
+ */
1550
+ async invite(projectId, body) {
1551
+ return this.post('admin/projects/' + projectId + '/invite', body);
1552
+ }
1480
1553
  }
1481
- _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) {
1554
+ _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) {
1482
1555
  const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);
1483
1556
  logins.push(newLogin);
1484
1557
  __classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
@@ -1580,7 +1653,12 @@ async function _MedplumClient_executeAutoBatch() {
1580
1653
  // If there is only one request in the batch, just execute it
1581
1654
  if (entries.length === 1) {
1582
1655
  const entry = entries[0];
1583
- entry.resolve(await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, entry.method, __classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + entry.url, entry.options));
1656
+ try {
1657
+ entry.resolve(await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_request).call(this, entry.method, __classPrivateFieldGet(this, _MedplumClient_fhirBaseUrl, "f") + entry.url, entry.options));
1658
+ }
1659
+ catch (err) {
1660
+ entry.reject(new OperationOutcomeError(normalizeOperationOutcome(err)));
1661
+ }
1584
1662
  return;
1585
1663
  }
1586
1664
  // Build the batch request