@medplum/core 2.0.6 → 2.0.9
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 +248 -334
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/client.mjs +8 -5
- package/dist/esm/client.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +3 -3
- package/dist/esm/outcomes.mjs +21 -3
- package/dist/esm/outcomes.mjs.map +1 -1
- package/dist/esm/search/details.mjs +1 -1
- package/dist/esm/search/details.mjs.map +1 -1
- package/dist/esm/search/search.mjs +215 -111
- package/dist/esm/search/search.mjs.map +1 -1
- package/dist/types/client.d.ts +11 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/outcomes.d.ts +6 -0
- package/dist/types/search/search.d.ts +16 -5
- package/package.json +1 -1
- package/dist/esm/search/parse.mjs +0 -218
- package/dist/esm/search/parse.mjs.map +0 -1
- package/dist/types/search/parse.d.ts +0 -17
- package/tsconfig.build.json +0 -9
package/dist/cjs/index.cjs
CHANGED
|
@@ -1368,7 +1368,7 @@
|
|
|
1368
1368
|
}
|
|
1369
1369
|
class OperationOutcomeError extends Error {
|
|
1370
1370
|
constructor(outcome, cause) {
|
|
1371
|
-
super(outcome
|
|
1371
|
+
super(operationOutcomeToString(outcome));
|
|
1372
1372
|
this.outcome = outcome;
|
|
1373
1373
|
this.cause = cause;
|
|
1374
1374
|
}
|
|
@@ -1403,10 +1403,28 @@
|
|
|
1403
1403
|
return error.message;
|
|
1404
1404
|
}
|
|
1405
1405
|
if (isOperationOutcome(error)) {
|
|
1406
|
-
return error
|
|
1406
|
+
return operationOutcomeToString(error);
|
|
1407
1407
|
}
|
|
1408
1408
|
return JSON.stringify(error);
|
|
1409
1409
|
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Returns a string represenation of the operation outcome.
|
|
1412
|
+
* @param outcome The operation outcome.
|
|
1413
|
+
* @returns The string representation of the operation outcome.
|
|
1414
|
+
*/
|
|
1415
|
+
function operationOutcomeToString(outcome) {
|
|
1416
|
+
const strs = [];
|
|
1417
|
+
if (outcome.issue) {
|
|
1418
|
+
for (const issue of outcome.issue) {
|
|
1419
|
+
let issueStr = issue.details?.text || 'Unknown error';
|
|
1420
|
+
if (issue.expression?.length) {
|
|
1421
|
+
issueStr += ` (${issue.expression.join(', ')})`;
|
|
1422
|
+
}
|
|
1423
|
+
strs.push(issueStr);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
return strs.length > 0 ? strs.join('; ') : 'Unknown error';
|
|
1427
|
+
}
|
|
1410
1428
|
|
|
1411
1429
|
var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_response, _ReadablePromise_error, _a;
|
|
1412
1430
|
/**
|
|
@@ -6352,7 +6370,7 @@
|
|
|
6352
6370
|
// PKCE auth based on:
|
|
6353
6371
|
// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
|
|
6354
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;
|
|
6355
|
-
const MEDPLUM_VERSION = "2.0.
|
|
6373
|
+
const MEDPLUM_VERSION = "2.0.9-a615c4ef";
|
|
6356
6374
|
const DEFAULT_BASE_URL = 'https://api.medplum.com/';
|
|
6357
6375
|
const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
|
|
6358
6376
|
const DEFAULT_CACHE_TIME = 60000; // 60 seconds
|
|
@@ -6444,8 +6462,8 @@
|
|
|
6444
6462
|
}
|
|
6445
6463
|
}
|
|
6446
6464
|
__classPrivateFieldSet(this, _MedplumClient_fetch, options?.fetch || getDefaultFetch(), "f");
|
|
6465
|
+
__classPrivateFieldSet(this, _MedplumClient_storage, options?.storage || new ClientStorage(), "f");
|
|
6447
6466
|
__classPrivateFieldSet(this, _MedplumClient_createPdf, options?.createPdf, "f");
|
|
6448
|
-
__classPrivateFieldSet(this, _MedplumClient_storage, new ClientStorage(), "f");
|
|
6449
6467
|
__classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE), "f");
|
|
6450
6468
|
__classPrivateFieldSet(this, _MedplumClient_cacheTime, options?.cacheTime ?? DEFAULT_CACHE_TIME, "f");
|
|
6451
6469
|
__classPrivateFieldSet(this, _MedplumClient_baseUrl, ensureTrailingSlash(options?.baseUrl) || DEFAULT_BASE_URL, "f");
|
|
@@ -7680,12 +7698,14 @@
|
|
|
7680
7698
|
await __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_refreshProfile).call(this);
|
|
7681
7699
|
}
|
|
7682
7700
|
/**
|
|
7701
|
+
* Returns the current access token.
|
|
7683
7702
|
* @category Authentication
|
|
7684
7703
|
*/
|
|
7685
7704
|
getAccessToken() {
|
|
7686
7705
|
return __classPrivateFieldGet(this, _MedplumClient_accessToken, "f");
|
|
7687
7706
|
}
|
|
7688
7707
|
/**
|
|
7708
|
+
* Sets the current access token.
|
|
7689
7709
|
* @category Authentication
|
|
7690
7710
|
*/
|
|
7691
7711
|
setAccessToken(accessToken) {
|
|
@@ -7761,14 +7781,15 @@
|
|
|
7761
7781
|
* Processes an OAuth authorization code.
|
|
7762
7782
|
* See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
|
|
7763
7783
|
* @param code The authorization code received by URL parameter.
|
|
7784
|
+
* @param loginParams Optional login parameters.
|
|
7764
7785
|
* @category Authentication
|
|
7765
7786
|
*/
|
|
7766
|
-
processCode(code) {
|
|
7787
|
+
processCode(code, loginParams) {
|
|
7767
7788
|
const formBody = new URLSearchParams();
|
|
7768
7789
|
formBody.set('grant_type', 'authorization_code');
|
|
7769
|
-
formBody.set('client_id', __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
|
|
7770
7790
|
formBody.set('code', code);
|
|
7771
|
-
formBody.set('
|
|
7791
|
+
formBody.set('client_id', loginParams?.clientId || __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
|
|
7792
|
+
formBody.set('redirect_uri', loginParams?.redirectUri || getWindowOrigin());
|
|
7772
7793
|
if (typeof sessionStorage !== 'undefined') {
|
|
7773
7794
|
const codeVerifier = sessionStorage.getItem('codeVerifier');
|
|
7774
7795
|
if (codeVerifier) {
|
|
@@ -10698,7 +10719,7 @@
|
|
|
10698
10719
|
},
|
|
10699
10720
|
precedence: 0 /* OperatorPrecedence.FunctionCall */,
|
|
10700
10721
|
};
|
|
10701
|
-
function parseQuantity(str) {
|
|
10722
|
+
function parseQuantity$1(str) {
|
|
10702
10723
|
const parts = str.split(' ');
|
|
10703
10724
|
const value = parseFloat(parts[0]);
|
|
10704
10725
|
let unit = parts[1];
|
|
@@ -10719,7 +10740,7 @@
|
|
|
10719
10740
|
parse: (_, token) => new LiteralAtom({ type: exports.PropertyType.dateTime, value: parseDateString(token.value) }),
|
|
10720
10741
|
})
|
|
10721
10742
|
.registerPrefix('Quantity', {
|
|
10722
|
-
parse: (_, token) => new LiteralAtom({ type: exports.PropertyType.Quantity, value: parseQuantity(token.value) }),
|
|
10743
|
+
parse: (_, token) => new LiteralAtom({ type: exports.PropertyType.Quantity, value: parseQuantity$1(token.value) }),
|
|
10723
10744
|
})
|
|
10724
10745
|
.registerPrefix('Number', {
|
|
10725
10746
|
parse: (_, token) => new LiteralAtom({ type: exports.PropertyType.decimal, value: parseFloat(token.value) }),
|
|
@@ -11935,7 +11956,7 @@
|
|
|
11935
11956
|
if (result.includes('[0]')) {
|
|
11936
11957
|
result = result.replaceAll('[0]', '');
|
|
11937
11958
|
}
|
|
11938
|
-
const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.where('];
|
|
11959
|
+
const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.resolve(', '.where('];
|
|
11939
11960
|
for (const stopString of stopStrings) {
|
|
11940
11961
|
if (result.includes(stopString)) {
|
|
11941
11962
|
result = result.substring(0, result.indexOf(stopString));
|
|
@@ -11976,134 +11997,236 @@
|
|
|
11976
11997
|
Operator["OF_TYPE"] = "of-type";
|
|
11977
11998
|
// All
|
|
11978
11999
|
Operator["MISSING"] = "missing";
|
|
12000
|
+
// Reference
|
|
12001
|
+
Operator["IDENTIFIER"] = "identifier";
|
|
11979
12002
|
})(exports.Operator || (exports.Operator = {}));
|
|
11980
|
-
const MODIFIER_OPERATORS = [
|
|
11981
|
-
exports.Operator.CONTAINS,
|
|
11982
|
-
exports.Operator.EXACT,
|
|
11983
|
-
exports.Operator.TEXT,
|
|
11984
|
-
exports.Operator.NOT,
|
|
11985
|
-
exports.Operator.ABOVE,
|
|
11986
|
-
exports.Operator.BELOW,
|
|
11987
|
-
exports.Operator.IN,
|
|
11988
|
-
exports.Operator.NOT_IN,
|
|
11989
|
-
exports.Operator.OF_TYPE,
|
|
11990
|
-
exports.Operator.MISSING,
|
|
11991
|
-
];
|
|
11992
|
-
const PREFIX_OPERATORS = [
|
|
11993
|
-
exports.Operator.NOT_EQUALS,
|
|
11994
|
-
exports.Operator.GREATER_THAN,
|
|
11995
|
-
exports.Operator.LESS_THAN,
|
|
11996
|
-
exports.Operator.GREATER_THAN_OR_EQUALS,
|
|
11997
|
-
exports.Operator.LESS_THAN_OR_EQUALS,
|
|
11998
|
-
exports.Operator.STARTS_AFTER,
|
|
11999
|
-
exports.Operator.ENDS_BEFORE,
|
|
12000
|
-
exports.Operator.APPROXIMATELY,
|
|
12001
|
-
];
|
|
12002
12003
|
/**
|
|
12003
|
-
*
|
|
12004
|
-
*
|
|
12005
|
-
* See
|
|
12006
|
-
|
|
12004
|
+
* Parameter names may specify a modifier as a suffix.
|
|
12005
|
+
* The modifiers are separated from the parameter name by a colon.
|
|
12006
|
+
* See: https://www.hl7.org/fhir/search.html#modifiers
|
|
12007
|
+
*/
|
|
12008
|
+
const MODIFIER_OPERATORS = {
|
|
12009
|
+
contains: exports.Operator.CONTAINS,
|
|
12010
|
+
exact: exports.Operator.EXACT,
|
|
12011
|
+
above: exports.Operator.ABOVE,
|
|
12012
|
+
below: exports.Operator.BELOW,
|
|
12013
|
+
text: exports.Operator.TEXT,
|
|
12014
|
+
not: exports.Operator.NOT,
|
|
12015
|
+
in: exports.Operator.IN,
|
|
12016
|
+
'not-in': exports.Operator.NOT_IN,
|
|
12017
|
+
'of-type': exports.Operator.OF_TYPE,
|
|
12018
|
+
missing: exports.Operator.MISSING,
|
|
12019
|
+
identifier: exports.Operator.IDENTIFIER,
|
|
12020
|
+
};
|
|
12021
|
+
/**
|
|
12022
|
+
* For the ordered parameter types of number, date, and quantity,
|
|
12023
|
+
* a prefix to the parameter value may be used to control the nature
|
|
12024
|
+
* of the matching.
|
|
12025
|
+
* See: https://www.hl7.org/fhir/search.html#prefix
|
|
12026
|
+
*/
|
|
12027
|
+
const PREFIX_OPERATORS = {
|
|
12028
|
+
eq: exports.Operator.EQUALS,
|
|
12029
|
+
ne: exports.Operator.NOT_EQUALS,
|
|
12030
|
+
lt: exports.Operator.LESS_THAN,
|
|
12031
|
+
le: exports.Operator.LESS_THAN_OR_EQUALS,
|
|
12032
|
+
gt: exports.Operator.GREATER_THAN,
|
|
12033
|
+
ge: exports.Operator.GREATER_THAN_OR_EQUALS,
|
|
12034
|
+
sa: exports.Operator.STARTS_AFTER,
|
|
12035
|
+
eb: exports.Operator.ENDS_BEFORE,
|
|
12036
|
+
ap: exports.Operator.APPROXIMATELY,
|
|
12037
|
+
};
|
|
12038
|
+
/**
|
|
12039
|
+
* Parses a search URL into a search request.
|
|
12040
|
+
* @param resourceType The FHIR resource type.
|
|
12041
|
+
* @param query The collection of query string parameters.
|
|
12042
|
+
* @returns A parsed SearchRequest.
|
|
12043
|
+
*/
|
|
12044
|
+
function parseSearchRequest(resourceType, query) {
|
|
12045
|
+
return parseSearchImpl(resourceType, query);
|
|
12046
|
+
}
|
|
12047
|
+
/**
|
|
12048
|
+
* Parses a search URL into a search request.
|
|
12049
|
+
* @param url The search URL.
|
|
12050
|
+
* @returns A parsed SearchRequest.
|
|
12051
|
+
*/
|
|
12052
|
+
function parseSearchUrl(url) {
|
|
12053
|
+
const resourceType = url.pathname.split('/').filter(Boolean).pop();
|
|
12054
|
+
return parseSearchImpl(resourceType, Object.fromEntries(url.searchParams.entries()));
|
|
12055
|
+
}
|
|
12056
|
+
/**
|
|
12057
|
+
* Parses a URL string into a SearchRequest.
|
|
12007
12058
|
* @param url The URL to parse.
|
|
12008
12059
|
* @returns Parsed search definition.
|
|
12009
12060
|
*/
|
|
12010
12061
|
function parseSearchDefinition(url) {
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
let offset = undefined;
|
|
12021
|
-
let count = undefined;
|
|
12022
|
-
let total = undefined;
|
|
12023
|
-
params.forEach((value, key) => {
|
|
12024
|
-
if (key === '_fields') {
|
|
12025
|
-
fields = value.split(',');
|
|
12026
|
-
}
|
|
12027
|
-
else if (key === '_offset') {
|
|
12028
|
-
offset = parseInt(value);
|
|
12029
|
-
}
|
|
12030
|
-
else if (key === '_count') {
|
|
12031
|
-
count = parseInt(value);
|
|
12032
|
-
}
|
|
12033
|
-
else if (key === '_total') {
|
|
12034
|
-
total = value;
|
|
12035
|
-
}
|
|
12036
|
-
else if (key === '_sort') {
|
|
12037
|
-
sortRules = sortRules || [];
|
|
12038
|
-
sortRules.push(parseSortRule(value));
|
|
12062
|
+
return parseSearchUrl(new URL(url, 'https://example.com/'));
|
|
12063
|
+
}
|
|
12064
|
+
function parseSearchImpl(resourceType, query) {
|
|
12065
|
+
const searchRequest = {
|
|
12066
|
+
resourceType,
|
|
12067
|
+
};
|
|
12068
|
+
for (const [key, value] of Object.entries(query)) {
|
|
12069
|
+
if (Array.isArray(value)) {
|
|
12070
|
+
value.forEach((element) => parseKeyValue(searchRequest, key, element));
|
|
12039
12071
|
}
|
|
12040
12072
|
else {
|
|
12041
|
-
|
|
12042
|
-
filters.push(parseSearchFilter(key, value));
|
|
12073
|
+
parseKeyValue(searchRequest, key, value ?? '');
|
|
12043
12074
|
}
|
|
12044
|
-
}
|
|
12045
|
-
return
|
|
12046
|
-
resourceType,
|
|
12047
|
-
filters,
|
|
12048
|
-
fields,
|
|
12049
|
-
offset,
|
|
12050
|
-
count,
|
|
12051
|
-
total,
|
|
12052
|
-
sortRules,
|
|
12053
|
-
};
|
|
12075
|
+
}
|
|
12076
|
+
return searchRequest;
|
|
12054
12077
|
}
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
* See sorting: http://hl7.org/fhir/r4/search.html#_sort
|
|
12063
|
-
*
|
|
12064
|
-
* @param value The URL parameter value.
|
|
12065
|
-
* @returns The parsed sort rule.
|
|
12066
|
-
*/
|
|
12067
|
-
function parseSortRule(value) {
|
|
12068
|
-
if (value.startsWith('-')) {
|
|
12069
|
-
return { code: value.substring(1), descending: true };
|
|
12078
|
+
function parseKeyValue(searchRequest, key, value) {
|
|
12079
|
+
let code;
|
|
12080
|
+
let modifier;
|
|
12081
|
+
const colonIndex = key.indexOf(':');
|
|
12082
|
+
if (colonIndex >= 0) {
|
|
12083
|
+
code = key.substring(0, colonIndex);
|
|
12084
|
+
modifier = key.substring(colonIndex + 1);
|
|
12070
12085
|
}
|
|
12071
12086
|
else {
|
|
12072
|
-
|
|
12087
|
+
code = key;
|
|
12088
|
+
modifier = '';
|
|
12089
|
+
}
|
|
12090
|
+
switch (code) {
|
|
12091
|
+
case '_sort':
|
|
12092
|
+
parseSortRule(searchRequest, value);
|
|
12093
|
+
break;
|
|
12094
|
+
case '_count':
|
|
12095
|
+
searchRequest.count = parseInt(value);
|
|
12096
|
+
break;
|
|
12097
|
+
case '_offset':
|
|
12098
|
+
searchRequest.offset = parseInt(value);
|
|
12099
|
+
break;
|
|
12100
|
+
case '_total':
|
|
12101
|
+
searchRequest.total = value;
|
|
12102
|
+
break;
|
|
12103
|
+
case '_summary':
|
|
12104
|
+
searchRequest.total = 'estimate';
|
|
12105
|
+
searchRequest.count = 0;
|
|
12106
|
+
break;
|
|
12107
|
+
case '_revinclude':
|
|
12108
|
+
searchRequest.revInclude = value;
|
|
12109
|
+
break;
|
|
12110
|
+
case '_fields':
|
|
12111
|
+
searchRequest.fields = value.split(',');
|
|
12112
|
+
break;
|
|
12113
|
+
default: {
|
|
12114
|
+
const param = globalSchema.types[searchRequest.resourceType]?.searchParams?.[code];
|
|
12115
|
+
if (param) {
|
|
12116
|
+
parseParameter(searchRequest, param, modifier, value);
|
|
12117
|
+
}
|
|
12118
|
+
else {
|
|
12119
|
+
parseUnknownParameter(searchRequest, code, modifier, value);
|
|
12120
|
+
}
|
|
12121
|
+
}
|
|
12073
12122
|
}
|
|
12074
12123
|
}
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
* @returns The parsed search filter.
|
|
12089
|
-
*/
|
|
12090
|
-
function parseSearchFilter(key, value) {
|
|
12091
|
-
let code = key;
|
|
12092
|
-
let operator = exports.Operator.EQUALS;
|
|
12093
|
-
for (const modifier of MODIFIER_OPERATORS) {
|
|
12094
|
-
const modifierIndex = code.indexOf(':' + modifier);
|
|
12095
|
-
if (modifierIndex !== -1) {
|
|
12096
|
-
operator = modifier;
|
|
12097
|
-
code = code.substring(0, modifierIndex);
|
|
12124
|
+
function parseSortRule(searchRequest, value) {
|
|
12125
|
+
for (const field of value.split(',')) {
|
|
12126
|
+
let code;
|
|
12127
|
+
let descending = false;
|
|
12128
|
+
if (field.startsWith('-')) {
|
|
12129
|
+
code = field.substring(1);
|
|
12130
|
+
descending = true;
|
|
12131
|
+
}
|
|
12132
|
+
else {
|
|
12133
|
+
code = field;
|
|
12134
|
+
}
|
|
12135
|
+
if (!searchRequest.sortRules) {
|
|
12136
|
+
searchRequest.sortRules = [];
|
|
12098
12137
|
}
|
|
12138
|
+
searchRequest.sortRules.push({ code, descending });
|
|
12099
12139
|
}
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12140
|
+
}
|
|
12141
|
+
function parseParameter(searchRequest, searchParam, modifier, value) {
|
|
12142
|
+
if (modifier === 'missing') {
|
|
12143
|
+
addFilter(searchRequest, {
|
|
12144
|
+
code: searchParam.code,
|
|
12145
|
+
operator: exports.Operator.MISSING,
|
|
12146
|
+
value,
|
|
12147
|
+
});
|
|
12148
|
+
return;
|
|
12149
|
+
}
|
|
12150
|
+
switch (searchParam.type) {
|
|
12151
|
+
case 'number':
|
|
12152
|
+
case 'date':
|
|
12153
|
+
parsePrefixType(searchRequest, searchParam, value);
|
|
12154
|
+
break;
|
|
12155
|
+
case 'reference':
|
|
12156
|
+
case 'string':
|
|
12157
|
+
case 'token':
|
|
12158
|
+
case 'uri':
|
|
12159
|
+
parseModifierType(searchRequest, searchParam, modifier, value);
|
|
12160
|
+
break;
|
|
12161
|
+
case 'quantity':
|
|
12162
|
+
parseQuantity(searchRequest, searchParam, value);
|
|
12163
|
+
break;
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
function parsePrefixType(searchRequest, param, input) {
|
|
12167
|
+
const { operator, value } = parsePrefix(input);
|
|
12168
|
+
addFilter(searchRequest, {
|
|
12169
|
+
code: param.code,
|
|
12170
|
+
operator,
|
|
12171
|
+
value,
|
|
12172
|
+
});
|
|
12173
|
+
}
|
|
12174
|
+
function parseModifierType(searchRequest, param, modifier, value) {
|
|
12175
|
+
addFilter(searchRequest, {
|
|
12176
|
+
code: param.code,
|
|
12177
|
+
operator: parseModifier(modifier),
|
|
12178
|
+
value,
|
|
12179
|
+
});
|
|
12180
|
+
}
|
|
12181
|
+
function parseQuantity(searchRequest, param, input) {
|
|
12182
|
+
const [prefixNumber, unitSystem, unitCode] = input.split('|');
|
|
12183
|
+
const { operator, value } = parsePrefix(prefixNumber);
|
|
12184
|
+
addFilter(searchRequest, {
|
|
12185
|
+
code: param.code,
|
|
12186
|
+
operator,
|
|
12187
|
+
value,
|
|
12188
|
+
unitSystem,
|
|
12189
|
+
unitCode,
|
|
12190
|
+
});
|
|
12191
|
+
}
|
|
12192
|
+
function parseUnknownParameter(searchRequest, code, modifier, value) {
|
|
12193
|
+
let operator = exports.Operator.EQUALS;
|
|
12194
|
+
if (modifier) {
|
|
12195
|
+
operator = modifier;
|
|
12196
|
+
}
|
|
12197
|
+
else if (value.length >= 2) {
|
|
12198
|
+
const prefix = value.substring(0, 2);
|
|
12199
|
+
if (prefix in PREFIX_OPERATORS) {
|
|
12200
|
+
if (value.length === 2 || value.at(2)?.match(/\d/)) {
|
|
12201
|
+
operator = prefix;
|
|
12202
|
+
value = value.substring(prefix.length);
|
|
12203
|
+
}
|
|
12104
12204
|
}
|
|
12105
12205
|
}
|
|
12106
|
-
|
|
12206
|
+
addFilter(searchRequest, {
|
|
12207
|
+
code,
|
|
12208
|
+
operator,
|
|
12209
|
+
value,
|
|
12210
|
+
});
|
|
12211
|
+
}
|
|
12212
|
+
function parsePrefix(input) {
|
|
12213
|
+
const prefix = input.substring(0, 2);
|
|
12214
|
+
const prefixOperator = PREFIX_OPERATORS[prefix];
|
|
12215
|
+
if (prefixOperator) {
|
|
12216
|
+
return { operator: prefixOperator, value: input.substring(2) };
|
|
12217
|
+
}
|
|
12218
|
+
return { operator: exports.Operator.EQUALS, value: input };
|
|
12219
|
+
}
|
|
12220
|
+
function parseModifier(modifier) {
|
|
12221
|
+
return MODIFIER_OPERATORS[modifier] || exports.Operator.EQUALS;
|
|
12222
|
+
}
|
|
12223
|
+
function addFilter(searchRequest, filter) {
|
|
12224
|
+
if (searchRequest.filters) {
|
|
12225
|
+
searchRequest.filters.push(filter);
|
|
12226
|
+
}
|
|
12227
|
+
else {
|
|
12228
|
+
searchRequest.filters = [filter];
|
|
12229
|
+
}
|
|
12107
12230
|
}
|
|
12108
12231
|
/**
|
|
12109
12232
|
* Formats a search definition object into a query string.
|
|
@@ -12138,8 +12261,8 @@
|
|
|
12138
12261
|
return '?' + params.join('&');
|
|
12139
12262
|
}
|
|
12140
12263
|
function formatFilter(filter) {
|
|
12141
|
-
const modifier =
|
|
12142
|
-
const prefix =
|
|
12264
|
+
const modifier = filter.operator in MODIFIER_OPERATORS ? ':' + filter.operator : '';
|
|
12265
|
+
const prefix = filter.operator != exports.Operator.EQUALS && filter.operator in PREFIX_OPERATORS ? filter.operator : '';
|
|
12143
12266
|
return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
|
|
12144
12267
|
}
|
|
12145
12268
|
function formatSortRules(sortRules) {
|
|
@@ -12300,221 +12423,10 @@
|
|
|
12300
12423
|
return operator === exports.Operator.NOT_EQUALS || operator === exports.Operator.NOT;
|
|
12301
12424
|
}
|
|
12302
12425
|
|
|
12303
|
-
var _SearchParser_instances, _SearchParser_parseKeyValue, _SearchParser_parseSortRule, _SearchParser_parseParameter, _SearchParser_parsePrefixType, _SearchParser_parseModifierType, _SearchParser_parseReference, _SearchParser_parseQuantity, _SearchParser_parseUnknownParameter;
|
|
12304
|
-
/**
|
|
12305
|
-
* Parses a FHIR search query.
|
|
12306
|
-
* See: https://www.hl7.org/fhir/search.html
|
|
12307
|
-
*/
|
|
12308
|
-
/**
|
|
12309
|
-
* For the ordered parameter types of number, date, and quantity,
|
|
12310
|
-
* a prefix to the parameter value may be used to control the nature
|
|
12311
|
-
* of the matching.
|
|
12312
|
-
* See: https://www.hl7.org/fhir/search.html#prefix
|
|
12313
|
-
*/
|
|
12314
|
-
const prefixMap = {
|
|
12315
|
-
eq: exports.Operator.EQUALS,
|
|
12316
|
-
ne: exports.Operator.NOT_EQUALS,
|
|
12317
|
-
lt: exports.Operator.LESS_THAN,
|
|
12318
|
-
le: exports.Operator.LESS_THAN_OR_EQUALS,
|
|
12319
|
-
gt: exports.Operator.GREATER_THAN,
|
|
12320
|
-
ge: exports.Operator.GREATER_THAN_OR_EQUALS,
|
|
12321
|
-
sa: exports.Operator.STARTS_AFTER,
|
|
12322
|
-
eb: exports.Operator.ENDS_BEFORE,
|
|
12323
|
-
ap: exports.Operator.APPROXIMATELY,
|
|
12324
|
-
};
|
|
12325
|
-
/**
|
|
12326
|
-
* Parameter names may specify a modifier as a suffix.
|
|
12327
|
-
* The modifiers are separated from the parameter name by a colon.
|
|
12328
|
-
* See: https://www.hl7.org/fhir/search.html#modifiers
|
|
12329
|
-
*/
|
|
12330
|
-
const modifierMap = {
|
|
12331
|
-
contains: exports.Operator.CONTAINS,
|
|
12332
|
-
exact: exports.Operator.EXACT,
|
|
12333
|
-
above: exports.Operator.ABOVE,
|
|
12334
|
-
below: exports.Operator.BELOW,
|
|
12335
|
-
text: exports.Operator.TEXT,
|
|
12336
|
-
not: exports.Operator.NOT,
|
|
12337
|
-
in: exports.Operator.IN,
|
|
12338
|
-
'not-in': exports.Operator.NOT_IN,
|
|
12339
|
-
'of-type': exports.Operator.OF_TYPE,
|
|
12340
|
-
};
|
|
12341
|
-
/**
|
|
12342
|
-
* Parses a search URL into a search request.
|
|
12343
|
-
* @param resourceType The FHIR resource type.
|
|
12344
|
-
* @param query The collection of query string parameters.
|
|
12345
|
-
* @returns A parsed SearchRequest.
|
|
12346
|
-
*/
|
|
12347
|
-
function parseSearchRequest(resourceType, query) {
|
|
12348
|
-
return new SearchParser(resourceType, query);
|
|
12349
|
-
}
|
|
12350
|
-
/**
|
|
12351
|
-
* Parses a search URL into a search request.
|
|
12352
|
-
* @param url The search URL.
|
|
12353
|
-
* @returns A parsed SearchRequest.
|
|
12354
|
-
*/
|
|
12355
|
-
function parseSearchUrl(url) {
|
|
12356
|
-
const resourceType = url.pathname.split('/').pop();
|
|
12357
|
-
return new SearchParser(resourceType, Object.fromEntries(url.searchParams.entries()));
|
|
12358
|
-
}
|
|
12359
|
-
class SearchParser {
|
|
12360
|
-
constructor(resourceType, query) {
|
|
12361
|
-
_SearchParser_instances.add(this);
|
|
12362
|
-
this.resourceType = resourceType;
|
|
12363
|
-
this.filters = [];
|
|
12364
|
-
this.sortRules = [];
|
|
12365
|
-
for (const [key, value] of Object.entries(query)) {
|
|
12366
|
-
if (Array.isArray(value)) {
|
|
12367
|
-
value.forEach((element) => __classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseKeyValue).call(this, key, element));
|
|
12368
|
-
}
|
|
12369
|
-
else {
|
|
12370
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseKeyValue).call(this, key, value ?? '');
|
|
12371
|
-
}
|
|
12372
|
-
}
|
|
12373
|
-
}
|
|
12374
|
-
}
|
|
12375
|
-
_SearchParser_instances = new WeakSet(), _SearchParser_parseKeyValue = function _SearchParser_parseKeyValue(key, value) {
|
|
12376
|
-
let code;
|
|
12377
|
-
let modifier;
|
|
12378
|
-
const colonIndex = key.indexOf(':');
|
|
12379
|
-
if (colonIndex >= 0) {
|
|
12380
|
-
code = key.substring(0, colonIndex);
|
|
12381
|
-
modifier = key.substring(colonIndex + 1);
|
|
12382
|
-
}
|
|
12383
|
-
else {
|
|
12384
|
-
code = key;
|
|
12385
|
-
modifier = '';
|
|
12386
|
-
}
|
|
12387
|
-
switch (code) {
|
|
12388
|
-
case '_sort':
|
|
12389
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseSortRule).call(this, value);
|
|
12390
|
-
break;
|
|
12391
|
-
case '_count':
|
|
12392
|
-
this.count = parseInt(value);
|
|
12393
|
-
break;
|
|
12394
|
-
case '_offset':
|
|
12395
|
-
this.offset = parseInt(value);
|
|
12396
|
-
break;
|
|
12397
|
-
case '_total':
|
|
12398
|
-
this.total = value;
|
|
12399
|
-
break;
|
|
12400
|
-
case '_summary':
|
|
12401
|
-
this.total = 'estimate';
|
|
12402
|
-
this.count = 0;
|
|
12403
|
-
break;
|
|
12404
|
-
case '_revinclude':
|
|
12405
|
-
this.revInclude = value;
|
|
12406
|
-
break;
|
|
12407
|
-
default: {
|
|
12408
|
-
const param = globalSchema.types[this.resourceType]?.searchParams?.[code];
|
|
12409
|
-
if (param) {
|
|
12410
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseParameter).call(this, param, modifier, value);
|
|
12411
|
-
}
|
|
12412
|
-
else {
|
|
12413
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseUnknownParameter).call(this, code, modifier, value);
|
|
12414
|
-
}
|
|
12415
|
-
}
|
|
12416
|
-
}
|
|
12417
|
-
}, _SearchParser_parseSortRule = function _SearchParser_parseSortRule(value) {
|
|
12418
|
-
for (const field of value.split(',')) {
|
|
12419
|
-
let code;
|
|
12420
|
-
let descending = false;
|
|
12421
|
-
if (field.startsWith('-')) {
|
|
12422
|
-
code = field.substring(1);
|
|
12423
|
-
descending = true;
|
|
12424
|
-
}
|
|
12425
|
-
else {
|
|
12426
|
-
code = field;
|
|
12427
|
-
}
|
|
12428
|
-
this.sortRules.push({ code, descending });
|
|
12429
|
-
}
|
|
12430
|
-
}, _SearchParser_parseParameter = function _SearchParser_parseParameter(searchParam, modifier, value) {
|
|
12431
|
-
if (modifier === 'missing') {
|
|
12432
|
-
this.filters.push({
|
|
12433
|
-
code: searchParam.code,
|
|
12434
|
-
operator: exports.Operator.MISSING,
|
|
12435
|
-
value,
|
|
12436
|
-
});
|
|
12437
|
-
return;
|
|
12438
|
-
}
|
|
12439
|
-
switch (searchParam.type) {
|
|
12440
|
-
case 'number':
|
|
12441
|
-
case 'date':
|
|
12442
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parsePrefixType).call(this, searchParam, value);
|
|
12443
|
-
break;
|
|
12444
|
-
case 'string':
|
|
12445
|
-
case 'token':
|
|
12446
|
-
case 'uri':
|
|
12447
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseModifierType).call(this, searchParam, modifier, value);
|
|
12448
|
-
break;
|
|
12449
|
-
case 'reference':
|
|
12450
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseReference).call(this, searchParam, value);
|
|
12451
|
-
break;
|
|
12452
|
-
case 'quantity':
|
|
12453
|
-
__classPrivateFieldGet(this, _SearchParser_instances, "m", _SearchParser_parseQuantity).call(this, searchParam, value);
|
|
12454
|
-
break;
|
|
12455
|
-
}
|
|
12456
|
-
}, _SearchParser_parsePrefixType = function _SearchParser_parsePrefixType(param, input) {
|
|
12457
|
-
const { operator, value } = parsePrefix(input);
|
|
12458
|
-
this.filters.push({
|
|
12459
|
-
code: param.code,
|
|
12460
|
-
operator,
|
|
12461
|
-
value,
|
|
12462
|
-
});
|
|
12463
|
-
}, _SearchParser_parseModifierType = function _SearchParser_parseModifierType(param, modifier, value) {
|
|
12464
|
-
this.filters.push({
|
|
12465
|
-
code: param.code,
|
|
12466
|
-
operator: parseModifier(modifier),
|
|
12467
|
-
value,
|
|
12468
|
-
});
|
|
12469
|
-
}, _SearchParser_parseReference = function _SearchParser_parseReference(param, value) {
|
|
12470
|
-
this.filters.push({
|
|
12471
|
-
code: param.code,
|
|
12472
|
-
operator: exports.Operator.EQUALS,
|
|
12473
|
-
value: value,
|
|
12474
|
-
});
|
|
12475
|
-
}, _SearchParser_parseQuantity = function _SearchParser_parseQuantity(param, input) {
|
|
12476
|
-
const [prefixNumber, unitSystem, unitCode] = input.split('|');
|
|
12477
|
-
const { operator, value } = parsePrefix(prefixNumber);
|
|
12478
|
-
this.filters.push({
|
|
12479
|
-
code: param.code,
|
|
12480
|
-
operator,
|
|
12481
|
-
value,
|
|
12482
|
-
unitSystem,
|
|
12483
|
-
unitCode,
|
|
12484
|
-
});
|
|
12485
|
-
}, _SearchParser_parseUnknownParameter = function _SearchParser_parseUnknownParameter(code, modifier, value) {
|
|
12486
|
-
let operator = exports.Operator.EQUALS;
|
|
12487
|
-
if (modifier) {
|
|
12488
|
-
operator = modifier;
|
|
12489
|
-
}
|
|
12490
|
-
else {
|
|
12491
|
-
for (const prefix of Object.keys(prefixMap)) {
|
|
12492
|
-
if (value.match(new RegExp('^' + prefix + '\\d'))) {
|
|
12493
|
-
operator = prefix;
|
|
12494
|
-
value = value.substring(prefix.length);
|
|
12495
|
-
}
|
|
12496
|
-
}
|
|
12497
|
-
}
|
|
12498
|
-
this.filters.push({
|
|
12499
|
-
code,
|
|
12500
|
-
operator,
|
|
12501
|
-
value,
|
|
12502
|
-
});
|
|
12503
|
-
};
|
|
12504
|
-
function parsePrefix(input) {
|
|
12505
|
-
const prefix = input.substring(0, 2);
|
|
12506
|
-
if (prefix in prefixMap) {
|
|
12507
|
-
return { operator: prefixMap[prefix], value: input.substring(2) };
|
|
12508
|
-
}
|
|
12509
|
-
return { operator: exports.Operator.EQUALS, value: input };
|
|
12510
|
-
}
|
|
12511
|
-
function parseModifier(modifier) {
|
|
12512
|
-
return modifierMap[modifier] || exports.Operator.EQUALS;
|
|
12513
|
-
}
|
|
12514
|
-
|
|
12515
12426
|
exports.AndAtom = AndAtom;
|
|
12516
12427
|
exports.ArithemticOperatorAtom = ArithemticOperatorAtom;
|
|
12517
12428
|
exports.AsAtom = AsAtom;
|
|
12429
|
+
exports.ClientStorage = ClientStorage;
|
|
12518
12430
|
exports.ConcatAtom = ConcatAtom;
|
|
12519
12431
|
exports.ContainsAtom = ContainsAtom;
|
|
12520
12432
|
exports.DEFAULT_SEARCH_COUNT = DEFAULT_SEARCH_COUNT;
|
|
@@ -12542,6 +12454,7 @@
|
|
|
12542
12454
|
exports.LiteralAtom = LiteralAtom;
|
|
12543
12455
|
exports.MEDPLUM_VERSION = MEDPLUM_VERSION;
|
|
12544
12456
|
exports.MedplumClient = MedplumClient;
|
|
12457
|
+
exports.MemoryStorage = MemoryStorage;
|
|
12545
12458
|
exports.NotEqualsAtom = NotEqualsAtom;
|
|
12546
12459
|
exports.NotEquivalentAtom = NotEquivalentAtom;
|
|
12547
12460
|
exports.OperationOutcomeError = OperationOutcomeError;
|
|
@@ -12648,6 +12561,7 @@
|
|
|
12648
12561
|
exports.normalizeOperationOutcome = normalizeOperationOutcome;
|
|
12649
12562
|
exports.notFound = notFound;
|
|
12650
12563
|
exports.notModified = notModified;
|
|
12564
|
+
exports.operationOutcomeToString = operationOutcomeToString;
|
|
12651
12565
|
exports.parseFhirPath = parseFhirPath;
|
|
12652
12566
|
exports.parseFilterParameter = parseFilterParameter;
|
|
12653
12567
|
exports.parseJWTPayload = parseJWTPayload;
|