@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.
- package/dist/cjs/index.cjs +138 -22
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/bundle.mjs +36 -0
- package/dist/esm/bundle.mjs.map +1 -0
- package/dist/esm/client.mjs +83 -5
- package/dist/esm/client.mjs.map +1 -1
- package/dist/esm/fhirmapper/tokenize.mjs +2 -3
- package/dist/esm/fhirmapper/tokenize.mjs.map +1 -1
- package/dist/esm/fhirpath/atoms.mjs +13 -19
- package/dist/esm/fhirpath/atoms.mjs.map +1 -1
- package/dist/esm/filter/parse.mjs +1 -2
- package/dist/esm/filter/parse.mjs.map +1 -1
- package/dist/esm/filter/tokenize.mjs +2 -3
- package/dist/esm/filter/tokenize.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/schema.mjs +7 -4
- package/dist/esm/schema.mjs.map +1 -1
- package/dist/esm/search/match.mjs +2 -2
- package/dist/esm/search/match.mjs.map +1 -1
- package/dist/esm/search/search.mjs +3 -0
- package/dist/esm/search/search.mjs.map +1 -1
- package/dist/esm/types.mjs +1 -1
- package/dist/esm/types.mjs.map +1 -1
- package/dist/esm/utils.mjs.map +1 -1
- package/dist/types/bundle.d.ts +11 -0
- package/dist/types/client.d.ts +56 -2
- package/dist/types/fhirpath/atoms.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/search/search.d.ts +1 -0
- package/dist/types/utils.d.ts +8 -1
- package/package.json +1 -1
|
@@ -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;;;;"}
|
package/dist/esm/client.mjs
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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
|