@medplum/core 0.9.32 → 0.9.35
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/client.d.ts +18 -2
- package/dist/cjs/index.js +759 -694
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/searchparams.d.ts +1 -3
- package/dist/cjs/types.d.ts +16 -4
- package/dist/cjs/utils.d.ts +1 -1
- package/dist/esm/client.d.ts +18 -2
- package/dist/esm/client.js +27 -8
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/fhirpath/atoms.js +2 -1
- package/dist/esm/fhirpath/atoms.js.map +1 -1
- package/dist/esm/fhirpath/functions.js +3 -1
- package/dist/esm/fhirpath/functions.js.map +1 -1
- package/dist/esm/fhirpath/utils.js +18 -20
- package/dist/esm/fhirpath/utils.js.map +1 -1
- package/dist/esm/format.js +2 -2
- package/dist/esm/format.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/outcomes.js +3 -3
- package/dist/esm/outcomes.js.map +1 -1
- package/dist/esm/searchparams.d.ts +1 -3
- package/dist/esm/searchparams.js +23 -6
- package/dist/esm/searchparams.js.map +1 -1
- package/dist/esm/types.d.ts +16 -4
- package/dist/esm/types.js +63 -34
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -1
- package/dist/esm/utils.js +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/stats.html +4034 -0
package/dist/cjs/index.js
CHANGED
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
}
|
|
130
130
|
function formatHumanName(name, options) {
|
|
131
131
|
const builder = [];
|
|
132
|
-
if (name.prefix && (
|
|
132
|
+
if (name.prefix && (options === null || options === void 0 ? void 0 : options.prefix) !== false) {
|
|
133
133
|
builder.push(...name.prefix);
|
|
134
134
|
}
|
|
135
135
|
if (name.given) {
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
if (name.family) {
|
|
139
139
|
builder.push(name.family);
|
|
140
140
|
}
|
|
141
|
-
if (name.suffix && (
|
|
141
|
+
if (name.suffix && (options === null || options === void 0 ? void 0 : options.suffix) !== false) {
|
|
142
142
|
builder.push(...name.suffix);
|
|
143
143
|
}
|
|
144
144
|
if (name.use && ((options === null || options === void 0 ? void 0 : options.all) || (options === null || options === void 0 ? void 0 : options.use))) {
|
|
@@ -692,7 +692,7 @@
|
|
|
692
692
|
return word.charAt(0).toUpperCase() + word.substring(1);
|
|
693
693
|
}
|
|
694
694
|
function isLowerCase(c) {
|
|
695
|
-
return c === c.toLowerCase();
|
|
695
|
+
return c === c.toLowerCase() && c !== c.toUpperCase();
|
|
696
696
|
}
|
|
697
697
|
/**
|
|
698
698
|
* Tries to find a code string for a given system within a given codeable concept.
|
|
@@ -6070,19 +6070,13 @@
|
|
|
6070
6070
|
function createSchema() {
|
|
6071
6071
|
return { types: {} };
|
|
6072
6072
|
}
|
|
6073
|
-
function createTypeSchema(typeName,
|
|
6073
|
+
function createTypeSchema(typeName, structureDefinition, elementDefinition) {
|
|
6074
6074
|
return {
|
|
6075
|
+
structureDefinition,
|
|
6076
|
+
elementDefinition,
|
|
6075
6077
|
display: typeName,
|
|
6076
|
-
description,
|
|
6078
|
+
description: elementDefinition.definition,
|
|
6077
6079
|
properties: {},
|
|
6078
|
-
searchParams: {
|
|
6079
|
-
_lastUpdated: {
|
|
6080
|
-
base: [typeName],
|
|
6081
|
-
code: '_lastUpdated',
|
|
6082
|
-
type: 'date',
|
|
6083
|
-
expression: typeName + '.meta.lastUpdated',
|
|
6084
|
-
},
|
|
6085
|
-
},
|
|
6086
6080
|
};
|
|
6087
6081
|
}
|
|
6088
6082
|
/**
|
|
@@ -6093,33 +6087,27 @@
|
|
|
6093
6087
|
for (const entry of bundle.entry) {
|
|
6094
6088
|
const resource = entry.resource;
|
|
6095
6089
|
if (resource.resourceType === 'StructureDefinition') {
|
|
6096
|
-
indexStructureDefinition(
|
|
6090
|
+
indexStructureDefinition(resource);
|
|
6097
6091
|
}
|
|
6098
6092
|
}
|
|
6099
6093
|
}
|
|
6100
6094
|
/**
|
|
6101
6095
|
* Indexes a StructureDefinition for fast lookup.
|
|
6102
6096
|
* See comments on IndexedStructureDefinition for more details.
|
|
6103
|
-
* @param schema The output IndexedStructureDefinition.
|
|
6104
6097
|
* @param structureDefinition The original StructureDefinition.
|
|
6105
6098
|
*/
|
|
6106
|
-
function indexStructureDefinition(
|
|
6099
|
+
function indexStructureDefinition(structureDefinition) {
|
|
6107
6100
|
var _a;
|
|
6108
6101
|
const typeName = structureDefinition.name;
|
|
6109
6102
|
if (!typeName) {
|
|
6110
6103
|
return;
|
|
6111
6104
|
}
|
|
6112
|
-
if (!(typeName in schema.types)) {
|
|
6113
|
-
schema.types[typeName] = createTypeSchema(typeName, structureDefinition.description);
|
|
6114
|
-
}
|
|
6115
6105
|
const elements = (_a = structureDefinition.snapshot) === null || _a === void 0 ? void 0 : _a.element;
|
|
6116
6106
|
if (elements) {
|
|
6117
|
-
// Filter out any elements missing path or type
|
|
6118
|
-
const filtered = elements.filter((e) => e.path !== typeName && e.path);
|
|
6119
6107
|
// First pass, build types
|
|
6120
|
-
|
|
6108
|
+
elements.forEach((element) => indexType(structureDefinition, element));
|
|
6121
6109
|
// Second pass, build properties
|
|
6122
|
-
|
|
6110
|
+
elements.forEach((element) => indexProperty(element));
|
|
6123
6111
|
}
|
|
6124
6112
|
}
|
|
6125
6113
|
/**
|
|
@@ -6129,33 +6117,31 @@
|
|
|
6129
6117
|
* @param schema The output IndexedStructureDefinition.
|
|
6130
6118
|
* @param element The input ElementDefinition.
|
|
6131
6119
|
*/
|
|
6132
|
-
function indexType(
|
|
6120
|
+
function indexType(structureDefinition, elementDefinition) {
|
|
6133
6121
|
var _a, _b;
|
|
6134
|
-
const path =
|
|
6135
|
-
const typeCode = (_b = (_a =
|
|
6136
|
-
if (typeCode !== 'Element' && typeCode !== 'BackboneElement') {
|
|
6122
|
+
const path = elementDefinition.path;
|
|
6123
|
+
const typeCode = (_b = (_a = elementDefinition.type) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.code;
|
|
6124
|
+
if (typeCode !== undefined && typeCode !== 'Element' && typeCode !== 'BackboneElement') {
|
|
6137
6125
|
return;
|
|
6138
6126
|
}
|
|
6139
6127
|
const parts = path.split('.');
|
|
6140
6128
|
const typeName = buildTypeName(parts);
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));
|
|
6144
|
-
}
|
|
6129
|
+
globalSchema.types[typeName] = createTypeSchema(typeName, structureDefinition, elementDefinition);
|
|
6130
|
+
globalSchema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));
|
|
6145
6131
|
}
|
|
6146
6132
|
/**
|
|
6147
6133
|
* Indexes PropertySchema from an ElementDefinition.
|
|
6148
6134
|
* @param schema The output IndexedStructureDefinition.
|
|
6149
6135
|
* @param element The input ElementDefinition.
|
|
6150
6136
|
*/
|
|
6151
|
-
function indexProperty(
|
|
6137
|
+
function indexProperty(element) {
|
|
6152
6138
|
const path = element.path;
|
|
6153
6139
|
const parts = path.split('.');
|
|
6154
6140
|
if (parts.length === 1) {
|
|
6155
6141
|
return;
|
|
6156
6142
|
}
|
|
6157
6143
|
const typeName = buildTypeName(parts.slice(0, parts.length - 1));
|
|
6158
|
-
const typeSchema =
|
|
6144
|
+
const typeSchema = globalSchema.types[typeName];
|
|
6159
6145
|
if (!typeSchema) {
|
|
6160
6146
|
return;
|
|
6161
6147
|
}
|
|
@@ -6168,22 +6154,38 @@
|
|
|
6168
6154
|
* @param schema The output IndexedStructureDefinition.
|
|
6169
6155
|
* @param searchParam The SearchParameter resource.
|
|
6170
6156
|
*/
|
|
6171
|
-
function indexSearchParameter(
|
|
6157
|
+
function indexSearchParameter(searchParam) {
|
|
6172
6158
|
if (!searchParam.base) {
|
|
6173
6159
|
return;
|
|
6174
6160
|
}
|
|
6175
6161
|
for (const resourceType of searchParam.base) {
|
|
6176
|
-
const typeSchema =
|
|
6162
|
+
const typeSchema = globalSchema.types[resourceType];
|
|
6177
6163
|
if (!typeSchema) {
|
|
6178
6164
|
continue;
|
|
6179
6165
|
}
|
|
6180
6166
|
if (!typeSchema.searchParams) {
|
|
6181
|
-
typeSchema.searchParams = {
|
|
6167
|
+
typeSchema.searchParams = {
|
|
6168
|
+
_id: {
|
|
6169
|
+
base: [resourceType],
|
|
6170
|
+
code: '_id',
|
|
6171
|
+
type: 'token',
|
|
6172
|
+
expression: resourceType + '.id',
|
|
6173
|
+
},
|
|
6174
|
+
_lastUpdated: {
|
|
6175
|
+
base: [resourceType],
|
|
6176
|
+
code: '_lastUpdated',
|
|
6177
|
+
type: 'date',
|
|
6178
|
+
expression: resourceType + '.meta.lastUpdated',
|
|
6179
|
+
},
|
|
6180
|
+
};
|
|
6182
6181
|
}
|
|
6183
6182
|
typeSchema.searchParams[searchParam.code] = searchParam;
|
|
6184
6183
|
}
|
|
6185
6184
|
}
|
|
6186
6185
|
function buildTypeName(components) {
|
|
6186
|
+
if (components.length === 1) {
|
|
6187
|
+
return components[0];
|
|
6188
|
+
}
|
|
6187
6189
|
return components.map(capitalize).join('');
|
|
6188
6190
|
}
|
|
6189
6191
|
function getPropertyDisplayName(path) {
|
|
@@ -6208,6 +6210,33 @@
|
|
|
6208
6210
|
.replace('_', ' ')
|
|
6209
6211
|
.replace(/\s+/g, ' ');
|
|
6210
6212
|
}
|
|
6213
|
+
/**
|
|
6214
|
+
* Returns an element definition by type and property name.
|
|
6215
|
+
* Handles content references.
|
|
6216
|
+
* @param typeName The type name.
|
|
6217
|
+
* @param propertyName The property name.
|
|
6218
|
+
* @returns The element definition if found.
|
|
6219
|
+
*/
|
|
6220
|
+
function getElementDefinition(typeName, propertyName) {
|
|
6221
|
+
var _a;
|
|
6222
|
+
const typeSchema = globalSchema.types[typeName];
|
|
6223
|
+
if (!typeSchema) {
|
|
6224
|
+
return undefined;
|
|
6225
|
+
}
|
|
6226
|
+
const property = (_a = typeSchema.properties[propertyName]) !== null && _a !== void 0 ? _a : typeSchema.properties[propertyName + '[x]'];
|
|
6227
|
+
if (!property) {
|
|
6228
|
+
return undefined;
|
|
6229
|
+
}
|
|
6230
|
+
if (property.contentReference) {
|
|
6231
|
+
// Content references start with a "#"
|
|
6232
|
+
// Remove the "#" character
|
|
6233
|
+
const contentReference = property.contentReference.substring(1).split('.');
|
|
6234
|
+
const referencePropertyName = contentReference.pop();
|
|
6235
|
+
const referenceTypeName = buildTypeName(contentReference);
|
|
6236
|
+
return getElementDefinition(referenceTypeName, referencePropertyName);
|
|
6237
|
+
}
|
|
6238
|
+
return property;
|
|
6239
|
+
}
|
|
6211
6240
|
/**
|
|
6212
6241
|
* Global schema singleton.
|
|
6213
6242
|
*/
|
|
@@ -6523,8 +6552,10 @@
|
|
|
6523
6552
|
startLogin(loginRequest) {
|
|
6524
6553
|
var _a, _b;
|
|
6525
6554
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6526
|
-
|
|
6527
|
-
|
|
6555
|
+
if (!loginRequest.codeChallenge || !loginRequest.codeChallengeMethod) {
|
|
6556
|
+
yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
|
|
6557
|
+
}
|
|
6558
|
+
return this.post('auth/login', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: (_b = loginRequest.scope) !== null && _b !== void 0 ? _b : DEFAULT_SCOPE, codeChallengeMethod: loginRequest.codeChallengeMethod || 'S256', codeChallenge: loginRequest.codeChallenge || __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeChallenge') }));
|
|
6528
6559
|
});
|
|
6529
6560
|
}
|
|
6530
6561
|
/**
|
|
@@ -6538,8 +6569,10 @@
|
|
|
6538
6569
|
startGoogleLogin(loginRequest) {
|
|
6539
6570
|
var _a, _b;
|
|
6540
6571
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6541
|
-
|
|
6542
|
-
|
|
6572
|
+
if (!loginRequest.codeChallenge || !loginRequest.codeChallengeMethod) {
|
|
6573
|
+
yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
|
|
6574
|
+
}
|
|
6575
|
+
return this.post('auth/google', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: (_b = loginRequest.scope) !== null && _b !== void 0 ? _b : DEFAULT_SCOPE, codeChallengeMethod: loginRequest.codeChallengeMethod || 'S256', codeChallenge: loginRequest.codeChallenge || __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeChallenge') }));
|
|
6543
6576
|
});
|
|
6544
6577
|
}
|
|
6545
6578
|
/**
|
|
@@ -6616,7 +6649,7 @@
|
|
|
6616
6649
|
* ```json
|
|
6617
6650
|
* {
|
|
6618
6651
|
* "resourceType": "Bundle",
|
|
6619
|
-
* "type": "
|
|
6652
|
+
* "type": "searchset",
|
|
6620
6653
|
* "total": 1,
|
|
6621
6654
|
* "entry": [
|
|
6622
6655
|
* {
|
|
@@ -6766,7 +6799,7 @@
|
|
|
6766
6799
|
*
|
|
6767
6800
|
* See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
|
|
6768
6801
|
*
|
|
6769
|
-
* @category
|
|
6802
|
+
* @category Read
|
|
6770
6803
|
* @param resourceType The FHIR resource type.
|
|
6771
6804
|
* @param id The resource ID.
|
|
6772
6805
|
* @returns The resource if available; undefined otherwise.
|
|
@@ -6859,10 +6892,10 @@
|
|
|
6859
6892
|
}`.replace(/\s+/g, ' ');
|
|
6860
6893
|
const response = (yield this.graphql(query));
|
|
6861
6894
|
for (const structureDefinition of response.data.StructureDefinitionList) {
|
|
6862
|
-
indexStructureDefinition(
|
|
6895
|
+
indexStructureDefinition(structureDefinition);
|
|
6863
6896
|
}
|
|
6864
6897
|
for (const searchParameter of response.data.SearchParameterList) {
|
|
6865
|
-
indexSearchParameter(
|
|
6898
|
+
indexSearchParameter(searchParameter);
|
|
6866
6899
|
}
|
|
6867
6900
|
return globalSchema;
|
|
6868
6901
|
});
|
|
@@ -7321,6 +7354,20 @@
|
|
|
7321
7354
|
graphql(query, operationName, variables, options) {
|
|
7322
7355
|
return this.post(this.fhirUrl('$graphql'), { query, operationName, variables }, JSON_CONTENT_TYPE, options);
|
|
7323
7356
|
}
|
|
7357
|
+
/**
|
|
7358
|
+
*
|
|
7359
|
+
* Executes the $graph operation on this resource to fetch a Bundle of resources linked to the target resource
|
|
7360
|
+
* according to a graph definition
|
|
7361
|
+
|
|
7362
|
+
* @category Read
|
|
7363
|
+
* @param resourceType The FHIR resource type.
|
|
7364
|
+
* @param id The resource ID.
|
|
7365
|
+
* @param graphName `name` parameter of the GraphDefinition
|
|
7366
|
+
* @returns A Bundle
|
|
7367
|
+
*/
|
|
7368
|
+
readResourceGraph(resourceType, id, graphName) {
|
|
7369
|
+
return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}`);
|
|
7370
|
+
}
|
|
7324
7371
|
/**
|
|
7325
7372
|
* @category Authentication
|
|
7326
7373
|
* @returns The Login State
|
|
@@ -7516,6 +7563,7 @@
|
|
|
7516
7563
|
options.headers = {};
|
|
7517
7564
|
}
|
|
7518
7565
|
const headers = options.headers;
|
|
7566
|
+
headers['X-Medplum'] = 'extended';
|
|
7519
7567
|
if (!headers['Content-Type']) {
|
|
7520
7568
|
headers['Content-Type'] = FHIR_CONTENT_TYPE;
|
|
7521
7569
|
}
|
|
@@ -7661,6 +7709,28 @@
|
|
|
7661
7709
|
return url.endsWith('/') ? url : url + '/';
|
|
7662
7710
|
}
|
|
7663
7711
|
|
|
7712
|
+
function parseDateString(str) {
|
|
7713
|
+
if (str.startsWith('T')) {
|
|
7714
|
+
// If a time string,
|
|
7715
|
+
// then normalize to full length.
|
|
7716
|
+
return str + 'T00:00:00.000Z'.substring(str.length);
|
|
7717
|
+
}
|
|
7718
|
+
if (str.length <= 10) {
|
|
7719
|
+
// If a local date (i.e., "2021-01-01"),
|
|
7720
|
+
// then return as-is.
|
|
7721
|
+
return str;
|
|
7722
|
+
}
|
|
7723
|
+
try {
|
|
7724
|
+
// Try to normalize to UTC
|
|
7725
|
+
return new Date(str).toISOString();
|
|
7726
|
+
}
|
|
7727
|
+
catch (e) {
|
|
7728
|
+
// Fallback to original input
|
|
7729
|
+
// This happens on unsupported time formats such as "2021-01-01T12"
|
|
7730
|
+
return str;
|
|
7731
|
+
}
|
|
7732
|
+
}
|
|
7733
|
+
|
|
7664
7734
|
/**
|
|
7665
7735
|
* Returns a single element array with a typed boolean value.
|
|
7666
7736
|
* @param value The primitive boolean value.
|
|
@@ -7724,9 +7794,9 @@
|
|
|
7724
7794
|
if (!(input === null || input === void 0 ? void 0 : input.value)) {
|
|
7725
7795
|
return undefined;
|
|
7726
7796
|
}
|
|
7727
|
-
const
|
|
7728
|
-
if (
|
|
7729
|
-
const typedResult = getTypedPropertyValueWithSchema(input, path,
|
|
7797
|
+
const elementDefinition = getElementDefinition(input.type, path);
|
|
7798
|
+
if (elementDefinition) {
|
|
7799
|
+
const typedResult = getTypedPropertyValueWithSchema(input, path, elementDefinition);
|
|
7730
7800
|
if (typedResult) {
|
|
7731
7801
|
return typedResult;
|
|
7732
7802
|
}
|
|
@@ -7737,24 +7807,18 @@
|
|
|
7737
7807
|
* Returns the value of the property and the property type using a type schema.
|
|
7738
7808
|
* @param input The base context (FHIR resource or backbone element).
|
|
7739
7809
|
* @param path The property path.
|
|
7740
|
-
* @param
|
|
7810
|
+
* @param property The property element definition.
|
|
7741
7811
|
* @returns The value of the property and the property type.
|
|
7742
7812
|
*/
|
|
7743
|
-
function getTypedPropertyValueWithSchema(input, path,
|
|
7813
|
+
function getTypedPropertyValueWithSchema(input, path, property) {
|
|
7744
7814
|
var _a;
|
|
7745
|
-
const property = (_a = typeSchema.properties[path]) !== null && _a !== void 0 ? _a : typeSchema.properties[path + '[x]'];
|
|
7746
|
-
if (!property) {
|
|
7747
|
-
return undefined;
|
|
7748
|
-
}
|
|
7749
7815
|
const types = property.type;
|
|
7750
7816
|
if (!types || types.length === 0) {
|
|
7751
7817
|
return undefined;
|
|
7752
7818
|
}
|
|
7753
|
-
let propertyName = undefined;
|
|
7754
7819
|
let resultValue = undefined;
|
|
7755
7820
|
let resultType = 'undefined';
|
|
7756
7821
|
if (types.length === 1) {
|
|
7757
|
-
propertyName = path;
|
|
7758
7822
|
resultValue = input.value[path];
|
|
7759
7823
|
resultType = types[0].code;
|
|
7760
7824
|
}
|
|
@@ -7762,7 +7826,6 @@
|
|
|
7762
7826
|
for (const type of types) {
|
|
7763
7827
|
const path2 = path.replace('[x]', '') + capitalize(type.code);
|
|
7764
7828
|
if (path2 in input.value) {
|
|
7765
|
-
propertyName = path2;
|
|
7766
7829
|
resultValue = input.value[path2];
|
|
7767
7830
|
resultType = type.code;
|
|
7768
7831
|
break;
|
|
@@ -7772,15 +7835,21 @@
|
|
|
7772
7835
|
if (isEmpty(resultValue)) {
|
|
7773
7836
|
return undefined;
|
|
7774
7837
|
}
|
|
7775
|
-
if (resultType === 'BackboneElement') {
|
|
7776
|
-
resultType = buildTypeName(
|
|
7838
|
+
if (resultType === 'Element' || resultType === 'BackboneElement') {
|
|
7839
|
+
resultType = buildTypeName((_a = property.path) === null || _a === void 0 ? void 0 : _a.split('.'));
|
|
7777
7840
|
}
|
|
7778
7841
|
if (Array.isArray(resultValue)) {
|
|
7779
|
-
return resultValue.map((element) => (
|
|
7842
|
+
return resultValue.map((element) => toTypedValueWithType(element, resultType));
|
|
7780
7843
|
}
|
|
7781
7844
|
else {
|
|
7782
|
-
return
|
|
7845
|
+
return toTypedValueWithType(resultValue, resultType);
|
|
7846
|
+
}
|
|
7847
|
+
}
|
|
7848
|
+
function toTypedValueWithType(value, type) {
|
|
7849
|
+
if (type === 'Resource' && typeof value === 'object' && 'resourceType' in value) {
|
|
7850
|
+
type = value.resourceType;
|
|
7783
7851
|
}
|
|
7852
|
+
return { type, value };
|
|
7784
7853
|
}
|
|
7785
7854
|
/**
|
|
7786
7855
|
* Returns the value of the property and the property type using a type schema.
|
|
@@ -8005,7 +8074,6 @@
|
|
|
8005
8074
|
}
|
|
8006
8075
|
/**
|
|
8007
8076
|
* Resource equality.
|
|
8008
|
-
* Ignores meta.versionId and meta.lastUpdated.
|
|
8009
8077
|
* See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality
|
|
8010
8078
|
* @param object1 The first object.
|
|
8011
8079
|
* @param object2 The second object.
|
|
@@ -8033,466 +8101,121 @@
|
|
|
8033
8101
|
}
|
|
8034
8102
|
return true;
|
|
8035
8103
|
}
|
|
8036
|
-
function isObject(
|
|
8037
|
-
return
|
|
8104
|
+
function isObject(obj) {
|
|
8105
|
+
return obj !== null && typeof obj === 'object';
|
|
8038
8106
|
}
|
|
8039
8107
|
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8108
|
+
/**
|
|
8109
|
+
* Temporary placholder for unimplemented methods.
|
|
8110
|
+
*/
|
|
8111
|
+
const stub = () => [];
|
|
8112
|
+
const functions = {
|
|
8113
|
+
/*
|
|
8114
|
+
* 5.1 Existence
|
|
8115
|
+
* See: https://hl7.org/fhirpath/#existence
|
|
8116
|
+
*/
|
|
8117
|
+
/**
|
|
8118
|
+
* Returns true if the input collection is empty ({ }) and false otherwise.
|
|
8119
|
+
*
|
|
8120
|
+
* See: https://hl7.org/fhirpath/#empty-boolean
|
|
8121
|
+
*
|
|
8122
|
+
* @param input The input collection.
|
|
8123
|
+
* @returns True if the input collection is empty ({ }) and false otherwise.
|
|
8124
|
+
*/
|
|
8125
|
+
empty: (input) => {
|
|
8126
|
+
return booleanToTypedValue(input.length === 0);
|
|
8127
|
+
},
|
|
8128
|
+
/**
|
|
8129
|
+
* Returns true if the collection has unknown elements, and false otherwise.
|
|
8130
|
+
* This is the opposite of empty(), and as such is a shorthand for empty().not().
|
|
8131
|
+
* If the input collection is empty ({ }), the result is false.
|
|
8132
|
+
*
|
|
8133
|
+
* The function can also take an optional criteria to be applied to the collection
|
|
8134
|
+
* prior to the determination of the exists. In this case, the function is shorthand
|
|
8135
|
+
* for where(criteria).exists().
|
|
8136
|
+
*
|
|
8137
|
+
* See: https://hl7.org/fhirpath/#existscriteria-expression-boolean
|
|
8138
|
+
*
|
|
8139
|
+
* @param input
|
|
8140
|
+
* @param criteria
|
|
8141
|
+
* @returns True if the collection has unknown elements, and false otherwise.
|
|
8142
|
+
*/
|
|
8143
|
+
exists: (input, criteria) => {
|
|
8144
|
+
if (criteria) {
|
|
8145
|
+
return booleanToTypedValue(input.filter((e) => toJsBoolean(criteria.eval([e]))).length > 0);
|
|
8054
8146
|
}
|
|
8055
|
-
|
|
8056
|
-
|
|
8147
|
+
else {
|
|
8148
|
+
return booleanToTypedValue(input.length > 0);
|
|
8057
8149
|
}
|
|
8058
|
-
}
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8150
|
+
},
|
|
8151
|
+
/**
|
|
8152
|
+
* Returns true if for every element in the input collection, criteria evaluates to true.
|
|
8153
|
+
* Otherwise, the result is false.
|
|
8154
|
+
*
|
|
8155
|
+
* If the input collection is empty ({ }), the result is true.
|
|
8156
|
+
*
|
|
8157
|
+
* See: https://hl7.org/fhirpath/#allcriteria-expression-boolean
|
|
8158
|
+
*
|
|
8159
|
+
* @param input The input collection.
|
|
8160
|
+
* @param criteria The evaluation criteria.
|
|
8161
|
+
* @returns True if for every element in the input collection, criteria evaluates to true.
|
|
8162
|
+
*/
|
|
8163
|
+
all: (input, criteria) => {
|
|
8164
|
+
return booleanToTypedValue(input.every((e) => toJsBoolean(criteria.eval([e]))));
|
|
8165
|
+
},
|
|
8166
|
+
/**
|
|
8167
|
+
* Takes a collection of Boolean values and returns true if all the items are true.
|
|
8168
|
+
* If unknown items are false, the result is false.
|
|
8169
|
+
* If the input is empty ({ }), the result is true.
|
|
8170
|
+
*
|
|
8171
|
+
* See: https://hl7.org/fhirpath/#alltrue-boolean
|
|
8172
|
+
*
|
|
8173
|
+
* @param input The input collection.
|
|
8174
|
+
* @param criteria The evaluation criteria.
|
|
8175
|
+
* @returns True if all the items are true.
|
|
8176
|
+
*/
|
|
8177
|
+
allTrue: (input) => {
|
|
8178
|
+
for (const value of input) {
|
|
8179
|
+
if (!value.value) {
|
|
8180
|
+
return booleanToTypedValue(false);
|
|
8181
|
+
}
|
|
8076
8182
|
}
|
|
8077
|
-
return
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
eval() {
|
|
8095
|
-
return [];
|
|
8096
|
-
}
|
|
8097
|
-
}
|
|
8098
|
-
class UnaryOperatorAtom {
|
|
8099
|
-
constructor(child, impl) {
|
|
8100
|
-
this.child = child;
|
|
8101
|
-
this.impl = impl;
|
|
8102
|
-
}
|
|
8103
|
-
eval(context) {
|
|
8104
|
-
return this.impl(this.child.eval(context));
|
|
8105
|
-
}
|
|
8106
|
-
}
|
|
8107
|
-
class AsAtom {
|
|
8108
|
-
constructor(left, right) {
|
|
8109
|
-
this.left = left;
|
|
8110
|
-
this.right = right;
|
|
8111
|
-
}
|
|
8112
|
-
eval(context) {
|
|
8113
|
-
return this.left.eval(context);
|
|
8114
|
-
}
|
|
8115
|
-
}
|
|
8116
|
-
class ArithemticOperatorAtom {
|
|
8117
|
-
constructor(left, right, impl) {
|
|
8118
|
-
this.left = left;
|
|
8119
|
-
this.right = right;
|
|
8120
|
-
this.impl = impl;
|
|
8121
|
-
}
|
|
8122
|
-
eval(context) {
|
|
8123
|
-
const leftEvalResult = this.left.eval(context);
|
|
8124
|
-
if (leftEvalResult.length !== 1) {
|
|
8125
|
-
return [];
|
|
8183
|
+
return booleanToTypedValue(true);
|
|
8184
|
+
},
|
|
8185
|
+
/**
|
|
8186
|
+
* Takes a collection of Boolean values and returns true if unknown of the items are true.
|
|
8187
|
+
* If all the items are false, or if the input is empty ({ }), the result is false.
|
|
8188
|
+
*
|
|
8189
|
+
* See: https://hl7.org/fhirpath/#anytrue-boolean
|
|
8190
|
+
*
|
|
8191
|
+
* @param input The input collection.
|
|
8192
|
+
* @param criteria The evaluation criteria.
|
|
8193
|
+
* @returns True if unknown of the items are true.
|
|
8194
|
+
*/
|
|
8195
|
+
anyTrue: (input) => {
|
|
8196
|
+
for (const value of input) {
|
|
8197
|
+
if (value.value) {
|
|
8198
|
+
return booleanToTypedValue(true);
|
|
8199
|
+
}
|
|
8126
8200
|
}
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
}
|
|
8146
|
-
}
|
|
8147
|
-
class ConcatAtom {
|
|
8148
|
-
constructor(left, right) {
|
|
8149
|
-
this.left = left;
|
|
8150
|
-
this.right = right;
|
|
8151
|
-
}
|
|
8152
|
-
eval(context) {
|
|
8153
|
-
const leftValue = this.left.eval(context);
|
|
8154
|
-
const rightValue = this.right.eval(context);
|
|
8155
|
-
const result = [...leftValue, ...rightValue];
|
|
8156
|
-
if (result.length > 0 && result.every((e) => typeof e.value === 'string')) {
|
|
8157
|
-
return [{ type: exports.PropertyType.string, value: result.map((e) => e.value).join('') }];
|
|
8158
|
-
}
|
|
8159
|
-
return result;
|
|
8160
|
-
}
|
|
8161
|
-
}
|
|
8162
|
-
class ContainsAtom {
|
|
8163
|
-
constructor(left, right) {
|
|
8164
|
-
this.left = left;
|
|
8165
|
-
this.right = right;
|
|
8166
|
-
}
|
|
8167
|
-
eval(context) {
|
|
8168
|
-
const leftValue = this.left.eval(context);
|
|
8169
|
-
const rightValue = this.right.eval(context);
|
|
8170
|
-
return booleanToTypedValue(leftValue.some((e) => e.value === rightValue[0].value));
|
|
8171
|
-
}
|
|
8172
|
-
}
|
|
8173
|
-
class InAtom {
|
|
8174
|
-
constructor(left, right) {
|
|
8175
|
-
this.left = left;
|
|
8176
|
-
this.right = right;
|
|
8177
|
-
}
|
|
8178
|
-
eval(context) {
|
|
8179
|
-
const leftValue = this.left.eval(context);
|
|
8180
|
-
const rightValue = this.right.eval(context);
|
|
8181
|
-
return booleanToTypedValue(rightValue.some((e) => e.value === leftValue[0].value));
|
|
8182
|
-
}
|
|
8183
|
-
}
|
|
8184
|
-
class DotAtom {
|
|
8185
|
-
constructor(left, right) {
|
|
8186
|
-
this.left = left;
|
|
8187
|
-
this.right = right;
|
|
8188
|
-
}
|
|
8189
|
-
eval(context) {
|
|
8190
|
-
return this.right.eval(this.left.eval(context));
|
|
8191
|
-
}
|
|
8192
|
-
}
|
|
8193
|
-
class UnionAtom {
|
|
8194
|
-
constructor(left, right) {
|
|
8195
|
-
this.left = left;
|
|
8196
|
-
this.right = right;
|
|
8197
|
-
}
|
|
8198
|
-
eval(context) {
|
|
8199
|
-
const leftResult = this.left.eval(context);
|
|
8200
|
-
const rightResult = this.right.eval(context);
|
|
8201
|
-
return removeDuplicates([...leftResult, ...rightResult]);
|
|
8202
|
-
}
|
|
8203
|
-
}
|
|
8204
|
-
class EqualsAtom {
|
|
8205
|
-
constructor(left, right) {
|
|
8206
|
-
this.left = left;
|
|
8207
|
-
this.right = right;
|
|
8208
|
-
}
|
|
8209
|
-
eval(context) {
|
|
8210
|
-
const leftValue = this.left.eval(context);
|
|
8211
|
-
const rightValue = this.right.eval(context);
|
|
8212
|
-
return fhirPathArrayEquals(leftValue, rightValue);
|
|
8213
|
-
}
|
|
8214
|
-
}
|
|
8215
|
-
class NotEqualsAtom {
|
|
8216
|
-
constructor(left, right) {
|
|
8217
|
-
this.left = left;
|
|
8218
|
-
this.right = right;
|
|
8219
|
-
}
|
|
8220
|
-
eval(context) {
|
|
8221
|
-
const leftValue = this.left.eval(context);
|
|
8222
|
-
const rightValue = this.right.eval(context);
|
|
8223
|
-
return fhirPathNot(fhirPathArrayEquals(leftValue, rightValue));
|
|
8224
|
-
}
|
|
8225
|
-
}
|
|
8226
|
-
class EquivalentAtom {
|
|
8227
|
-
constructor(left, right) {
|
|
8228
|
-
this.left = left;
|
|
8229
|
-
this.right = right;
|
|
8230
|
-
}
|
|
8231
|
-
eval(context) {
|
|
8232
|
-
const leftValue = this.left.eval(context);
|
|
8233
|
-
const rightValue = this.right.eval(context);
|
|
8234
|
-
return fhirPathArrayEquivalent(leftValue, rightValue);
|
|
8235
|
-
}
|
|
8236
|
-
}
|
|
8237
|
-
class NotEquivalentAtom {
|
|
8238
|
-
constructor(left, right) {
|
|
8239
|
-
this.left = left;
|
|
8240
|
-
this.right = right;
|
|
8241
|
-
}
|
|
8242
|
-
eval(context) {
|
|
8243
|
-
const leftValue = this.left.eval(context);
|
|
8244
|
-
const rightValue = this.right.eval(context);
|
|
8245
|
-
return fhirPathNot(fhirPathArrayEquivalent(leftValue, rightValue));
|
|
8246
|
-
}
|
|
8247
|
-
}
|
|
8248
|
-
class IsAtom {
|
|
8249
|
-
constructor(left, right) {
|
|
8250
|
-
this.left = left;
|
|
8251
|
-
this.right = right;
|
|
8252
|
-
}
|
|
8253
|
-
eval(context) {
|
|
8254
|
-
const leftValue = this.left.eval(context);
|
|
8255
|
-
if (leftValue.length !== 1) {
|
|
8256
|
-
return [];
|
|
8257
|
-
}
|
|
8258
|
-
const typeName = this.right.name;
|
|
8259
|
-
return booleanToTypedValue(fhirPathIs(leftValue[0], typeName));
|
|
8260
|
-
}
|
|
8261
|
-
}
|
|
8262
|
-
/**
|
|
8263
|
-
* 6.5.1. and
|
|
8264
|
-
* Returns true if both operands evaluate to true,
|
|
8265
|
-
* false if either operand evaluates to false,
|
|
8266
|
-
* and the empty collection otherwise.
|
|
8267
|
-
*/
|
|
8268
|
-
class AndAtom {
|
|
8269
|
-
constructor(left, right) {
|
|
8270
|
-
this.left = left;
|
|
8271
|
-
this.right = right;
|
|
8272
|
-
}
|
|
8273
|
-
eval(context) {
|
|
8274
|
-
var _a, _b, _c, _d;
|
|
8275
|
-
const leftValue = this.left.eval(context);
|
|
8276
|
-
const rightValue = this.right.eval(context);
|
|
8277
|
-
if (((_a = leftValue[0]) === null || _a === void 0 ? void 0 : _a.value) === true && ((_b = rightValue[0]) === null || _b === void 0 ? void 0 : _b.value) === true) {
|
|
8278
|
-
return booleanToTypedValue(true);
|
|
8279
|
-
}
|
|
8280
|
-
if (((_c = leftValue[0]) === null || _c === void 0 ? void 0 : _c.value) === false || ((_d = rightValue[0]) === null || _d === void 0 ? void 0 : _d.value) === false) {
|
|
8281
|
-
return booleanToTypedValue(false);
|
|
8282
|
-
}
|
|
8283
|
-
return [];
|
|
8284
|
-
}
|
|
8285
|
-
}
|
|
8286
|
-
class OrAtom {
|
|
8287
|
-
constructor(left, right) {
|
|
8288
|
-
this.left = left;
|
|
8289
|
-
this.right = right;
|
|
8290
|
-
}
|
|
8291
|
-
eval(context) {
|
|
8292
|
-
const leftValue = this.left.eval(context);
|
|
8293
|
-
if (toJsBoolean(leftValue)) {
|
|
8294
|
-
return leftValue;
|
|
8295
|
-
}
|
|
8296
|
-
const rightValue = this.right.eval(context);
|
|
8297
|
-
if (toJsBoolean(rightValue)) {
|
|
8298
|
-
return rightValue;
|
|
8299
|
-
}
|
|
8300
|
-
return [];
|
|
8301
|
-
}
|
|
8302
|
-
}
|
|
8303
|
-
/**
|
|
8304
|
-
* 6.5.4. xor
|
|
8305
|
-
* Returns true if exactly one of the operands evaluates to true,
|
|
8306
|
-
* false if either both operands evaluate to true or both operands evaluate to false,
|
|
8307
|
-
* and the empty collection otherwise.
|
|
8308
|
-
*/
|
|
8309
|
-
class XorAtom {
|
|
8310
|
-
constructor(left, right) {
|
|
8311
|
-
this.left = left;
|
|
8312
|
-
this.right = right;
|
|
8313
|
-
}
|
|
8314
|
-
eval(context) {
|
|
8315
|
-
const leftResult = this.left.eval(context);
|
|
8316
|
-
const rightResult = this.right.eval(context);
|
|
8317
|
-
if (leftResult.length === 0 && rightResult.length === 0) {
|
|
8318
|
-
return [];
|
|
8319
|
-
}
|
|
8320
|
-
const leftValue = leftResult.length === 0 ? null : leftResult[0].value;
|
|
8321
|
-
const rightValue = rightResult.length === 0 ? null : rightResult[0].value;
|
|
8322
|
-
if ((leftValue === true && rightValue !== true) || (leftValue !== true && rightValue === true)) {
|
|
8323
|
-
return booleanToTypedValue(true);
|
|
8324
|
-
}
|
|
8325
|
-
if ((leftValue === true && rightValue === true) || (leftValue === false && rightValue === false)) {
|
|
8326
|
-
return booleanToTypedValue(false);
|
|
8327
|
-
}
|
|
8328
|
-
return [];
|
|
8329
|
-
}
|
|
8330
|
-
}
|
|
8331
|
-
class FunctionAtom {
|
|
8332
|
-
constructor(name, args, impl) {
|
|
8333
|
-
this.name = name;
|
|
8334
|
-
this.args = args;
|
|
8335
|
-
this.impl = impl;
|
|
8336
|
-
}
|
|
8337
|
-
eval(context) {
|
|
8338
|
-
return this.impl(context, ...this.args);
|
|
8339
|
-
}
|
|
8340
|
-
}
|
|
8341
|
-
class IndexerAtom {
|
|
8342
|
-
constructor(left, expr) {
|
|
8343
|
-
this.left = left;
|
|
8344
|
-
this.expr = expr;
|
|
8345
|
-
}
|
|
8346
|
-
eval(context) {
|
|
8347
|
-
const evalResult = this.expr.eval(context);
|
|
8348
|
-
if (evalResult.length !== 1) {
|
|
8349
|
-
return [];
|
|
8350
|
-
}
|
|
8351
|
-
const index = evalResult[0].value;
|
|
8352
|
-
if (typeof index !== 'number') {
|
|
8353
|
-
throw new Error(`Invalid indexer expression: should return integer}`);
|
|
8354
|
-
}
|
|
8355
|
-
const leftResult = this.left.eval(context);
|
|
8356
|
-
if (!(index in leftResult)) {
|
|
8357
|
-
return [];
|
|
8358
|
-
}
|
|
8359
|
-
return [leftResult[index]];
|
|
8360
|
-
}
|
|
8361
|
-
}
|
|
8362
|
-
|
|
8363
|
-
function parseDateString(str) {
|
|
8364
|
-
if (str.startsWith('T')) {
|
|
8365
|
-
// If a time string,
|
|
8366
|
-
// then normalize to full length.
|
|
8367
|
-
return str + 'T00:00:00.000Z'.substring(str.length);
|
|
8368
|
-
}
|
|
8369
|
-
if (str.length <= 10) {
|
|
8370
|
-
// If a local date (i.e., "2021-01-01"),
|
|
8371
|
-
// then return as-is.
|
|
8372
|
-
return str;
|
|
8373
|
-
}
|
|
8374
|
-
try {
|
|
8375
|
-
// Try to normalize to UTC
|
|
8376
|
-
return new Date(str).toISOString();
|
|
8377
|
-
}
|
|
8378
|
-
catch (e) {
|
|
8379
|
-
// Fallback to original input
|
|
8380
|
-
// This happens on unsupported time formats such as "2021-01-01T12"
|
|
8381
|
-
return str;
|
|
8382
|
-
}
|
|
8383
|
-
}
|
|
8384
|
-
|
|
8385
|
-
/**
|
|
8386
|
-
* Temporary placholder for unimplemented methods.
|
|
8387
|
-
*/
|
|
8388
|
-
const stub = () => [];
|
|
8389
|
-
const functions = {
|
|
8390
|
-
/*
|
|
8391
|
-
* 5.1 Existence
|
|
8392
|
-
* See: https://hl7.org/fhirpath/#existence
|
|
8393
|
-
*/
|
|
8394
|
-
/**
|
|
8395
|
-
* Returns true if the input collection is empty ({ }) and false otherwise.
|
|
8396
|
-
*
|
|
8397
|
-
* See: https://hl7.org/fhirpath/#empty-boolean
|
|
8398
|
-
*
|
|
8399
|
-
* @param input The input collection.
|
|
8400
|
-
* @returns True if the input collection is empty ({ }) and false otherwise.
|
|
8401
|
-
*/
|
|
8402
|
-
empty: (input) => {
|
|
8403
|
-
return booleanToTypedValue(input.length === 0);
|
|
8404
|
-
},
|
|
8405
|
-
/**
|
|
8406
|
-
* Returns true if the collection has unknown elements, and false otherwise.
|
|
8407
|
-
* This is the opposite of empty(), and as such is a shorthand for empty().not().
|
|
8408
|
-
* If the input collection is empty ({ }), the result is false.
|
|
8409
|
-
*
|
|
8410
|
-
* The function can also take an optional criteria to be applied to the collection
|
|
8411
|
-
* prior to the determination of the exists. In this case, the function is shorthand
|
|
8412
|
-
* for where(criteria).exists().
|
|
8413
|
-
*
|
|
8414
|
-
* See: https://hl7.org/fhirpath/#existscriteria-expression-boolean
|
|
8415
|
-
*
|
|
8416
|
-
* @param input
|
|
8417
|
-
* @param criteria
|
|
8418
|
-
* @returns True if the collection has unknown elements, and false otherwise.
|
|
8419
|
-
*/
|
|
8420
|
-
exists: (input, criteria) => {
|
|
8421
|
-
if (criteria) {
|
|
8422
|
-
return booleanToTypedValue(input.filter((e) => toJsBoolean(criteria.eval([e]))).length > 0);
|
|
8423
|
-
}
|
|
8424
|
-
else {
|
|
8425
|
-
return booleanToTypedValue(input.length > 0);
|
|
8426
|
-
}
|
|
8427
|
-
},
|
|
8428
|
-
/**
|
|
8429
|
-
* Returns true if for every element in the input collection, criteria evaluates to true.
|
|
8430
|
-
* Otherwise, the result is false.
|
|
8431
|
-
*
|
|
8432
|
-
* If the input collection is empty ({ }), the result is true.
|
|
8433
|
-
*
|
|
8434
|
-
* See: https://hl7.org/fhirpath/#allcriteria-expression-boolean
|
|
8435
|
-
*
|
|
8436
|
-
* @param input The input collection.
|
|
8437
|
-
* @param criteria The evaluation criteria.
|
|
8438
|
-
* @returns True if for every element in the input collection, criteria evaluates to true.
|
|
8439
|
-
*/
|
|
8440
|
-
all: (input, criteria) => {
|
|
8441
|
-
return booleanToTypedValue(input.every((e) => toJsBoolean(criteria.eval([e]))));
|
|
8442
|
-
},
|
|
8443
|
-
/**
|
|
8444
|
-
* Takes a collection of Boolean values and returns true if all the items are true.
|
|
8445
|
-
* If unknown items are false, the result is false.
|
|
8446
|
-
* If the input is empty ({ }), the result is true.
|
|
8447
|
-
*
|
|
8448
|
-
* See: https://hl7.org/fhirpath/#alltrue-boolean
|
|
8449
|
-
*
|
|
8450
|
-
* @param input The input collection.
|
|
8451
|
-
* @param criteria The evaluation criteria.
|
|
8452
|
-
* @returns True if all the items are true.
|
|
8453
|
-
*/
|
|
8454
|
-
allTrue: (input) => {
|
|
8455
|
-
for (const value of input) {
|
|
8456
|
-
if (!value.value) {
|
|
8457
|
-
return booleanToTypedValue(false);
|
|
8458
|
-
}
|
|
8459
|
-
}
|
|
8460
|
-
return booleanToTypedValue(true);
|
|
8461
|
-
},
|
|
8462
|
-
/**
|
|
8463
|
-
* Takes a collection of Boolean values and returns true if unknown of the items are true.
|
|
8464
|
-
* If all the items are false, or if the input is empty ({ }), the result is false.
|
|
8465
|
-
*
|
|
8466
|
-
* See: https://hl7.org/fhirpath/#anytrue-boolean
|
|
8467
|
-
*
|
|
8468
|
-
* @param input The input collection.
|
|
8469
|
-
* @param criteria The evaluation criteria.
|
|
8470
|
-
* @returns True if unknown of the items are true.
|
|
8471
|
-
*/
|
|
8472
|
-
anyTrue: (input) => {
|
|
8473
|
-
for (const value of input) {
|
|
8474
|
-
if (value.value) {
|
|
8475
|
-
return booleanToTypedValue(true);
|
|
8476
|
-
}
|
|
8477
|
-
}
|
|
8478
|
-
return booleanToTypedValue(false);
|
|
8479
|
-
},
|
|
8480
|
-
/**
|
|
8481
|
-
* Takes a collection of Boolean values and returns true if all the items are false.
|
|
8482
|
-
* If unknown items are true, the result is false.
|
|
8483
|
-
* If the input is empty ({ }), the result is true.
|
|
8484
|
-
*
|
|
8485
|
-
* See: https://hl7.org/fhirpath/#allfalse-boolean
|
|
8486
|
-
*
|
|
8487
|
-
* @param input The input collection.
|
|
8488
|
-
* @param criteria The evaluation criteria.
|
|
8489
|
-
* @returns True if all the items are false.
|
|
8490
|
-
*/
|
|
8491
|
-
allFalse: (input) => {
|
|
8492
|
-
for (const value of input) {
|
|
8493
|
-
if (value.value) {
|
|
8494
|
-
return booleanToTypedValue(false);
|
|
8495
|
-
}
|
|
8201
|
+
return booleanToTypedValue(false);
|
|
8202
|
+
},
|
|
8203
|
+
/**
|
|
8204
|
+
* Takes a collection of Boolean values and returns true if all the items are false.
|
|
8205
|
+
* If unknown items are true, the result is false.
|
|
8206
|
+
* If the input is empty ({ }), the result is true.
|
|
8207
|
+
*
|
|
8208
|
+
* See: https://hl7.org/fhirpath/#allfalse-boolean
|
|
8209
|
+
*
|
|
8210
|
+
* @param input The input collection.
|
|
8211
|
+
* @param criteria The evaluation criteria.
|
|
8212
|
+
* @returns True if all the items are false.
|
|
8213
|
+
*/
|
|
8214
|
+
allFalse: (input) => {
|
|
8215
|
+
for (const value of input) {
|
|
8216
|
+
if (value.value) {
|
|
8217
|
+
return booleanToTypedValue(false);
|
|
8218
|
+
}
|
|
8496
8219
|
}
|
|
8497
8220
|
return booleanToTypedValue(true);
|
|
8498
8221
|
},
|
|
@@ -8641,7 +8364,9 @@
|
|
|
8641
8364
|
*
|
|
8642
8365
|
* See: http://hl7.org/fhirpath/#oftypetype-type-specifier-collection
|
|
8643
8366
|
*/
|
|
8644
|
-
ofType:
|
|
8367
|
+
ofType: (input, criteria) => {
|
|
8368
|
+
return input.filter((e) => e.type === criteria.name);
|
|
8369
|
+
},
|
|
8645
8370
|
/*
|
|
8646
8371
|
* 5.3 Subsetting
|
|
8647
8372
|
*/
|
|
@@ -9686,195 +9411,518 @@
|
|
|
9686
9411
|
if (startDate.length === 0) {
|
|
9687
9412
|
throw new Error('Invalid start date');
|
|
9688
9413
|
}
|
|
9689
|
-
const endDate = functions.toDateTime(endAtom.eval(input));
|
|
9690
|
-
if (endDate.length === 0) {
|
|
9691
|
-
throw new Error('Invalid end date');
|
|
9414
|
+
const endDate = functions.toDateTime(endAtom.eval(input));
|
|
9415
|
+
if (endDate.length === 0) {
|
|
9416
|
+
throw new Error('Invalid end date');
|
|
9417
|
+
}
|
|
9418
|
+
const unit = (_a = unitsAtom.eval(input)[0]) === null || _a === void 0 ? void 0 : _a.value;
|
|
9419
|
+
if (unit !== 'years' && unit !== 'months' && unit !== 'days') {
|
|
9420
|
+
throw new Error('Invalid units');
|
|
9421
|
+
}
|
|
9422
|
+
const age = calculateAge(startDate[0].value, endDate[0].value);
|
|
9423
|
+
return [{ type: exports.PropertyType.Quantity, value: { value: age[unit], unit } }];
|
|
9424
|
+
},
|
|
9425
|
+
/*
|
|
9426
|
+
* 6.3 Types
|
|
9427
|
+
*/
|
|
9428
|
+
/**
|
|
9429
|
+
* The is() function is supported for backwards compatibility with previous
|
|
9430
|
+
* implementations of FHIRPath. Just as with the is keyword, the type argument
|
|
9431
|
+
* is an identifier that must resolve to the name of a type in a model.
|
|
9432
|
+
*
|
|
9433
|
+
* For implementations with compile-time typing, this requires special-case
|
|
9434
|
+
* handling when processing the argument to treat it as a type specifier rather
|
|
9435
|
+
* than an identifier expression:
|
|
9436
|
+
*
|
|
9437
|
+
* @param input
|
|
9438
|
+
* @param typeAtom
|
|
9439
|
+
* @returns
|
|
9440
|
+
*/
|
|
9441
|
+
is: (input, typeAtom) => {
|
|
9442
|
+
let typeName = '';
|
|
9443
|
+
if (typeAtom instanceof SymbolAtom) {
|
|
9444
|
+
typeName = typeAtom.name;
|
|
9445
|
+
}
|
|
9446
|
+
else if (typeAtom instanceof DotAtom) {
|
|
9447
|
+
typeName = typeAtom.left.name + '.' + typeAtom.right.name;
|
|
9448
|
+
}
|
|
9449
|
+
if (!typeName) {
|
|
9450
|
+
return [];
|
|
9451
|
+
}
|
|
9452
|
+
return input.map((value) => ({ type: exports.PropertyType.boolean, value: fhirPathIs(value, typeName) }));
|
|
9453
|
+
},
|
|
9454
|
+
/*
|
|
9455
|
+
* 6.5 Boolean logic
|
|
9456
|
+
*/
|
|
9457
|
+
/**
|
|
9458
|
+
* 6.5.3. not() : Boolean
|
|
9459
|
+
*
|
|
9460
|
+
* Returns true if the input collection evaluates to false, and false if it evaluates to true. Otherwise, the result is empty ({ }):
|
|
9461
|
+
*
|
|
9462
|
+
* @param input
|
|
9463
|
+
* @returns
|
|
9464
|
+
*/
|
|
9465
|
+
not: (input) => {
|
|
9466
|
+
return functions.toBoolean(input).map((value) => ({ type: exports.PropertyType.boolean, value: !value.value }));
|
|
9467
|
+
},
|
|
9468
|
+
/*
|
|
9469
|
+
* Additional functions
|
|
9470
|
+
* See: https://hl7.org/fhir/fhirpath.html#functions
|
|
9471
|
+
*/
|
|
9472
|
+
/**
|
|
9473
|
+
* For each item in the collection, if it is a string that is a uri (or canonical or url), locate the target of the reference, and add it to the resulting collection. If the item does not resolve to a resource, the item is ignored and nothing is added to the output collection.
|
|
9474
|
+
* The items in the collection may also represent a Reference, in which case the Reference.reference is resolved.
|
|
9475
|
+
* @param input The input collection.
|
|
9476
|
+
* @returns
|
|
9477
|
+
*/
|
|
9478
|
+
resolve: (input) => {
|
|
9479
|
+
return input
|
|
9480
|
+
.map((e) => {
|
|
9481
|
+
const value = e.value;
|
|
9482
|
+
let refStr;
|
|
9483
|
+
if (typeof value === 'string') {
|
|
9484
|
+
refStr = value;
|
|
9485
|
+
}
|
|
9486
|
+
else if (typeof value === 'object') {
|
|
9487
|
+
const ref = value;
|
|
9488
|
+
if (ref.resource) {
|
|
9489
|
+
return toTypedValue(ref.resource);
|
|
9490
|
+
}
|
|
9491
|
+
refStr = ref.reference;
|
|
9492
|
+
}
|
|
9493
|
+
if (!refStr) {
|
|
9494
|
+
return { type: exports.PropertyType.BackboneElement, value: null };
|
|
9495
|
+
}
|
|
9496
|
+
const [resourceType, id] = refStr.split('/');
|
|
9497
|
+
return { type: exports.PropertyType.BackboneElement, value: { resourceType, id } };
|
|
9498
|
+
})
|
|
9499
|
+
.filter((e) => !!e.value);
|
|
9500
|
+
},
|
|
9501
|
+
/**
|
|
9502
|
+
* The as operator can be used to treat a value as a specific type.
|
|
9503
|
+
* @param input The input value.
|
|
9504
|
+
* @returns The value as the specific type.
|
|
9505
|
+
*/
|
|
9506
|
+
as: (input) => {
|
|
9507
|
+
return input;
|
|
9508
|
+
},
|
|
9509
|
+
/*
|
|
9510
|
+
* 12. Formal Specifications
|
|
9511
|
+
*/
|
|
9512
|
+
/**
|
|
9513
|
+
* Returns the type of the input.
|
|
9514
|
+
*
|
|
9515
|
+
* 12.2. Model Information
|
|
9516
|
+
*
|
|
9517
|
+
* The model information returned by the reflection function type() is specified as an
|
|
9518
|
+
* XML Schema document (xsd) and included in this specification at the following link:
|
|
9519
|
+
* https://hl7.org/fhirpath/modelinfo.xsd
|
|
9520
|
+
*
|
|
9521
|
+
* See: https://hl7.org/fhirpath/#model-information
|
|
9522
|
+
*
|
|
9523
|
+
* @param input The input collection.
|
|
9524
|
+
* @returns
|
|
9525
|
+
*/
|
|
9526
|
+
type: (input) => {
|
|
9527
|
+
return input.map(({ value }) => {
|
|
9528
|
+
if (typeof value === 'boolean') {
|
|
9529
|
+
return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Boolean' } };
|
|
9530
|
+
}
|
|
9531
|
+
if (typeof value === 'number') {
|
|
9532
|
+
return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Integer' } };
|
|
9533
|
+
}
|
|
9534
|
+
if (value && typeof value === 'object' && 'resourceType' in value) {
|
|
9535
|
+
return {
|
|
9536
|
+
type: exports.PropertyType.BackboneElement,
|
|
9537
|
+
value: { namespace: 'FHIR', name: value.resourceType },
|
|
9538
|
+
};
|
|
9539
|
+
}
|
|
9540
|
+
return { type: exports.PropertyType.BackboneElement, value: null };
|
|
9541
|
+
});
|
|
9542
|
+
},
|
|
9543
|
+
conformsTo: (input, systemAtom) => {
|
|
9544
|
+
const system = systemAtom.eval(input)[0].value;
|
|
9545
|
+
if (!system.startsWith('http://hl7.org/fhir/StructureDefinition/')) {
|
|
9546
|
+
throw new Error('Expected a StructureDefinition URL');
|
|
9547
|
+
}
|
|
9548
|
+
const expectedResourceType = system.replace('http://hl7.org/fhir/StructureDefinition/', '');
|
|
9549
|
+
return input.map((value) => {
|
|
9550
|
+
var _a;
|
|
9551
|
+
return ({
|
|
9552
|
+
type: exports.PropertyType.boolean,
|
|
9553
|
+
value: ((_a = value.value) === null || _a === void 0 ? void 0 : _a.resourceType) === expectedResourceType,
|
|
9554
|
+
});
|
|
9555
|
+
});
|
|
9556
|
+
},
|
|
9557
|
+
};
|
|
9558
|
+
/*
|
|
9559
|
+
* Helper utilities
|
|
9560
|
+
*/
|
|
9561
|
+
function applyStringFunc(func, input, ...argsAtoms) {
|
|
9562
|
+
if (input.length === 0) {
|
|
9563
|
+
return [];
|
|
9564
|
+
}
|
|
9565
|
+
const [{ value }] = validateInput(input, 1);
|
|
9566
|
+
if (typeof value !== 'string') {
|
|
9567
|
+
throw new Error('String function cannot be called with non-string');
|
|
9568
|
+
}
|
|
9569
|
+
const result = func(value, ...argsAtoms.map((atom) => { var _a, _b; return atom && ((_b = (_a = atom.eval(input)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value); }));
|
|
9570
|
+
if (result === undefined) {
|
|
9571
|
+
return [];
|
|
9572
|
+
}
|
|
9573
|
+
if (Array.isArray(result)) {
|
|
9574
|
+
return result.map(toTypedValue);
|
|
9575
|
+
}
|
|
9576
|
+
return [toTypedValue(result)];
|
|
9577
|
+
}
|
|
9578
|
+
function applyMathFunc(func, input, ...argsAtoms) {
|
|
9579
|
+
if (input.length === 0) {
|
|
9580
|
+
return [];
|
|
9581
|
+
}
|
|
9582
|
+
const [{ value }] = validateInput(input, 1);
|
|
9583
|
+
const quantity = isQuantity(value);
|
|
9584
|
+
const numberInput = quantity ? value.value : value;
|
|
9585
|
+
if (typeof numberInput !== 'number') {
|
|
9586
|
+
throw new Error('Math function cannot be called with non-number');
|
|
9587
|
+
}
|
|
9588
|
+
const result = func(numberInput, ...argsAtoms.map((atom) => { var _a, _b; return (_b = (_a = atom.eval(input)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value; }));
|
|
9589
|
+
const type = quantity ? exports.PropertyType.Quantity : input[0].type;
|
|
9590
|
+
const returnValue = quantity ? Object.assign(Object.assign({}, value), { value: result }) : result;
|
|
9591
|
+
return [{ type, value: returnValue }];
|
|
9592
|
+
}
|
|
9593
|
+
function validateInput(input, count) {
|
|
9594
|
+
if (input.length !== count) {
|
|
9595
|
+
throw new Error(`Expected ${count} arguments`);
|
|
9596
|
+
}
|
|
9597
|
+
for (const element of input) {
|
|
9598
|
+
if (element === null || element === undefined) {
|
|
9599
|
+
throw new Error('Expected non-null argument');
|
|
9600
|
+
}
|
|
9601
|
+
}
|
|
9602
|
+
return input;
|
|
9603
|
+
}
|
|
9604
|
+
|
|
9605
|
+
var _SymbolAtom_instances, _SymbolAtom_evalValue;
|
|
9606
|
+
class FhirPathAtom {
|
|
9607
|
+
constructor(original, child) {
|
|
9608
|
+
this.original = original;
|
|
9609
|
+
this.child = child;
|
|
9610
|
+
}
|
|
9611
|
+
eval(context) {
|
|
9612
|
+
try {
|
|
9613
|
+
if (context.length > 0) {
|
|
9614
|
+
return context.map((e) => this.child.eval([e])).flat();
|
|
9615
|
+
}
|
|
9616
|
+
else {
|
|
9617
|
+
return this.child.eval([]);
|
|
9618
|
+
}
|
|
9692
9619
|
}
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
throw new Error('Invalid units');
|
|
9620
|
+
catch (error) {
|
|
9621
|
+
throw new Error(`FhirPathError on "${this.original}": ${error}`);
|
|
9696
9622
|
}
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
*/
|
|
9716
|
-
is: (input, typeAtom) => {
|
|
9717
|
-
let typeName = '';
|
|
9718
|
-
if (typeAtom instanceof SymbolAtom) {
|
|
9719
|
-
typeName = typeAtom.name;
|
|
9623
|
+
}
|
|
9624
|
+
}
|
|
9625
|
+
class LiteralAtom {
|
|
9626
|
+
constructor(value) {
|
|
9627
|
+
this.value = value;
|
|
9628
|
+
}
|
|
9629
|
+
eval() {
|
|
9630
|
+
return [this.value];
|
|
9631
|
+
}
|
|
9632
|
+
}
|
|
9633
|
+
class SymbolAtom {
|
|
9634
|
+
constructor(name) {
|
|
9635
|
+
this.name = name;
|
|
9636
|
+
_SymbolAtom_instances.add(this);
|
|
9637
|
+
}
|
|
9638
|
+
eval(context) {
|
|
9639
|
+
if (this.name === '$this') {
|
|
9640
|
+
return context;
|
|
9720
9641
|
}
|
|
9721
|
-
|
|
9722
|
-
|
|
9642
|
+
return context
|
|
9643
|
+
.map((e) => __classPrivateFieldGet(this, _SymbolAtom_instances, "m", _SymbolAtom_evalValue).call(this, e))
|
|
9644
|
+
.flat()
|
|
9645
|
+
.filter((e) => (e === null || e === void 0 ? void 0 : e.value) !== undefined);
|
|
9646
|
+
}
|
|
9647
|
+
}
|
|
9648
|
+
_SymbolAtom_instances = new WeakSet(), _SymbolAtom_evalValue = function _SymbolAtom_evalValue(typedValue) {
|
|
9649
|
+
const input = typedValue.value;
|
|
9650
|
+
if (!input || typeof input !== 'object') {
|
|
9651
|
+
return undefined;
|
|
9652
|
+
}
|
|
9653
|
+
if ('resourceType' in input && input.resourceType === this.name) {
|
|
9654
|
+
return typedValue;
|
|
9655
|
+
}
|
|
9656
|
+
return getTypedPropertyValue(typedValue, this.name);
|
|
9657
|
+
};
|
|
9658
|
+
class EmptySetAtom {
|
|
9659
|
+
eval() {
|
|
9660
|
+
return [];
|
|
9661
|
+
}
|
|
9662
|
+
}
|
|
9663
|
+
class UnaryOperatorAtom {
|
|
9664
|
+
constructor(child, impl) {
|
|
9665
|
+
this.child = child;
|
|
9666
|
+
this.impl = impl;
|
|
9667
|
+
}
|
|
9668
|
+
eval(context) {
|
|
9669
|
+
return this.impl(this.child.eval(context));
|
|
9670
|
+
}
|
|
9671
|
+
}
|
|
9672
|
+
class AsAtom {
|
|
9673
|
+
constructor(left, right) {
|
|
9674
|
+
this.left = left;
|
|
9675
|
+
this.right = right;
|
|
9676
|
+
}
|
|
9677
|
+
eval(context) {
|
|
9678
|
+
return functions.ofType(this.left.eval(context), this.right);
|
|
9679
|
+
}
|
|
9680
|
+
}
|
|
9681
|
+
class ArithemticOperatorAtom {
|
|
9682
|
+
constructor(left, right, impl) {
|
|
9683
|
+
this.left = left;
|
|
9684
|
+
this.right = right;
|
|
9685
|
+
this.impl = impl;
|
|
9686
|
+
}
|
|
9687
|
+
eval(context) {
|
|
9688
|
+
const leftEvalResult = this.left.eval(context);
|
|
9689
|
+
if (leftEvalResult.length !== 1) {
|
|
9690
|
+
return [];
|
|
9723
9691
|
}
|
|
9724
|
-
|
|
9692
|
+
const rightEvalResult = this.right.eval(context);
|
|
9693
|
+
if (rightEvalResult.length !== 1) {
|
|
9694
|
+
return [];
|
|
9695
|
+
}
|
|
9696
|
+
const leftValue = leftEvalResult[0].value;
|
|
9697
|
+
const rightValue = rightEvalResult[0].value;
|
|
9698
|
+
const leftNumber = isQuantity(leftValue) ? leftValue.value : leftValue;
|
|
9699
|
+
const rightNumber = isQuantity(rightValue) ? rightValue.value : rightValue;
|
|
9700
|
+
const result = this.impl(leftNumber, rightNumber);
|
|
9701
|
+
if (typeof result === 'boolean') {
|
|
9702
|
+
return booleanToTypedValue(result);
|
|
9703
|
+
}
|
|
9704
|
+
else if (isQuantity(leftValue)) {
|
|
9705
|
+
return [{ type: exports.PropertyType.Quantity, value: Object.assign(Object.assign({}, leftValue), { value: result }) }];
|
|
9706
|
+
}
|
|
9707
|
+
else {
|
|
9708
|
+
return [toTypedValue(result)];
|
|
9709
|
+
}
|
|
9710
|
+
}
|
|
9711
|
+
}
|
|
9712
|
+
class ConcatAtom {
|
|
9713
|
+
constructor(left, right) {
|
|
9714
|
+
this.left = left;
|
|
9715
|
+
this.right = right;
|
|
9716
|
+
}
|
|
9717
|
+
eval(context) {
|
|
9718
|
+
const leftValue = this.left.eval(context);
|
|
9719
|
+
const rightValue = this.right.eval(context);
|
|
9720
|
+
const result = [...leftValue, ...rightValue];
|
|
9721
|
+
if (result.length > 0 && result.every((e) => typeof e.value === 'string')) {
|
|
9722
|
+
return [{ type: exports.PropertyType.string, value: result.map((e) => e.value).join('') }];
|
|
9723
|
+
}
|
|
9724
|
+
return result;
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
9727
|
+
class ContainsAtom {
|
|
9728
|
+
constructor(left, right) {
|
|
9729
|
+
this.left = left;
|
|
9730
|
+
this.right = right;
|
|
9731
|
+
}
|
|
9732
|
+
eval(context) {
|
|
9733
|
+
const leftValue = this.left.eval(context);
|
|
9734
|
+
const rightValue = this.right.eval(context);
|
|
9735
|
+
return booleanToTypedValue(leftValue.some((e) => e.value === rightValue[0].value));
|
|
9736
|
+
}
|
|
9737
|
+
}
|
|
9738
|
+
class InAtom {
|
|
9739
|
+
constructor(left, right) {
|
|
9740
|
+
this.left = left;
|
|
9741
|
+
this.right = right;
|
|
9742
|
+
}
|
|
9743
|
+
eval(context) {
|
|
9744
|
+
const leftValue = this.left.eval(context);
|
|
9745
|
+
const rightValue = this.right.eval(context);
|
|
9746
|
+
return booleanToTypedValue(rightValue.some((e) => e.value === leftValue[0].value));
|
|
9747
|
+
}
|
|
9748
|
+
}
|
|
9749
|
+
class DotAtom {
|
|
9750
|
+
constructor(left, right) {
|
|
9751
|
+
this.left = left;
|
|
9752
|
+
this.right = right;
|
|
9753
|
+
}
|
|
9754
|
+
eval(context) {
|
|
9755
|
+
return this.right.eval(this.left.eval(context));
|
|
9756
|
+
}
|
|
9757
|
+
}
|
|
9758
|
+
class UnionAtom {
|
|
9759
|
+
constructor(left, right) {
|
|
9760
|
+
this.left = left;
|
|
9761
|
+
this.right = right;
|
|
9762
|
+
}
|
|
9763
|
+
eval(context) {
|
|
9764
|
+
const leftResult = this.left.eval(context);
|
|
9765
|
+
const rightResult = this.right.eval(context);
|
|
9766
|
+
return removeDuplicates([...leftResult, ...rightResult]);
|
|
9767
|
+
}
|
|
9768
|
+
}
|
|
9769
|
+
class EqualsAtom {
|
|
9770
|
+
constructor(left, right) {
|
|
9771
|
+
this.left = left;
|
|
9772
|
+
this.right = right;
|
|
9773
|
+
}
|
|
9774
|
+
eval(context) {
|
|
9775
|
+
const leftValue = this.left.eval(context);
|
|
9776
|
+
const rightValue = this.right.eval(context);
|
|
9777
|
+
return fhirPathArrayEquals(leftValue, rightValue);
|
|
9778
|
+
}
|
|
9779
|
+
}
|
|
9780
|
+
class NotEqualsAtom {
|
|
9781
|
+
constructor(left, right) {
|
|
9782
|
+
this.left = left;
|
|
9783
|
+
this.right = right;
|
|
9784
|
+
}
|
|
9785
|
+
eval(context) {
|
|
9786
|
+
const leftValue = this.left.eval(context);
|
|
9787
|
+
const rightValue = this.right.eval(context);
|
|
9788
|
+
return fhirPathNot(fhirPathArrayEquals(leftValue, rightValue));
|
|
9789
|
+
}
|
|
9790
|
+
}
|
|
9791
|
+
class EquivalentAtom {
|
|
9792
|
+
constructor(left, right) {
|
|
9793
|
+
this.left = left;
|
|
9794
|
+
this.right = right;
|
|
9795
|
+
}
|
|
9796
|
+
eval(context) {
|
|
9797
|
+
const leftValue = this.left.eval(context);
|
|
9798
|
+
const rightValue = this.right.eval(context);
|
|
9799
|
+
return fhirPathArrayEquivalent(leftValue, rightValue);
|
|
9800
|
+
}
|
|
9801
|
+
}
|
|
9802
|
+
class NotEquivalentAtom {
|
|
9803
|
+
constructor(left, right) {
|
|
9804
|
+
this.left = left;
|
|
9805
|
+
this.right = right;
|
|
9806
|
+
}
|
|
9807
|
+
eval(context) {
|
|
9808
|
+
const leftValue = this.left.eval(context);
|
|
9809
|
+
const rightValue = this.right.eval(context);
|
|
9810
|
+
return fhirPathNot(fhirPathArrayEquivalent(leftValue, rightValue));
|
|
9811
|
+
}
|
|
9812
|
+
}
|
|
9813
|
+
class IsAtom {
|
|
9814
|
+
constructor(left, right) {
|
|
9815
|
+
this.left = left;
|
|
9816
|
+
this.right = right;
|
|
9817
|
+
}
|
|
9818
|
+
eval(context) {
|
|
9819
|
+
const leftValue = this.left.eval(context);
|
|
9820
|
+
if (leftValue.length !== 1) {
|
|
9725
9821
|
return [];
|
|
9726
9822
|
}
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
*
|
|
9737
|
-
* @param input
|
|
9738
|
-
* @returns
|
|
9739
|
-
*/
|
|
9740
|
-
not: (input) => {
|
|
9741
|
-
return functions.toBoolean(input).map((value) => ({ type: exports.PropertyType.boolean, value: !value.value }));
|
|
9742
|
-
},
|
|
9743
|
-
/*
|
|
9744
|
-
* Additional functions
|
|
9745
|
-
* See: https://hl7.org/fhir/fhirpath.html#functions
|
|
9746
|
-
*/
|
|
9747
|
-
/**
|
|
9748
|
-
* For each item in the collection, if it is a string that is a uri (or canonical or url), locate the target of the reference, and add it to the resulting collection. If the item does not resolve to a resource, the item is ignored and nothing is added to the output collection.
|
|
9749
|
-
* The items in the collection may also represent a Reference, in which case the Reference.reference is resolved.
|
|
9750
|
-
* @param input The input collection.
|
|
9751
|
-
* @returns
|
|
9752
|
-
*/
|
|
9753
|
-
resolve: (input) => {
|
|
9754
|
-
return input
|
|
9755
|
-
.map((e) => {
|
|
9756
|
-
const value = e.value;
|
|
9757
|
-
let refStr;
|
|
9758
|
-
if (typeof value === 'string') {
|
|
9759
|
-
refStr = value;
|
|
9760
|
-
}
|
|
9761
|
-
else if (typeof value === 'object') {
|
|
9762
|
-
const ref = value;
|
|
9763
|
-
if (ref.resource) {
|
|
9764
|
-
return toTypedValue(ref.resource);
|
|
9765
|
-
}
|
|
9766
|
-
refStr = ref.reference;
|
|
9767
|
-
}
|
|
9768
|
-
if (!refStr) {
|
|
9769
|
-
return { type: exports.PropertyType.BackboneElement, value: null };
|
|
9770
|
-
}
|
|
9771
|
-
const [resourceType, id] = refStr.split('/');
|
|
9772
|
-
return { type: exports.PropertyType.BackboneElement, value: { resourceType, id } };
|
|
9773
|
-
})
|
|
9774
|
-
.filter((e) => !!e.value);
|
|
9775
|
-
},
|
|
9776
|
-
/**
|
|
9777
|
-
* The as operator can be used to treat a value as a specific type.
|
|
9778
|
-
* @param input The input value.
|
|
9779
|
-
* @returns The value as the specific type.
|
|
9780
|
-
*/
|
|
9781
|
-
as: (input) => {
|
|
9782
|
-
return input;
|
|
9783
|
-
},
|
|
9784
|
-
/*
|
|
9785
|
-
* 12. Formal Specifications
|
|
9786
|
-
*/
|
|
9787
|
-
/**
|
|
9788
|
-
* Returns the type of the input.
|
|
9789
|
-
*
|
|
9790
|
-
* 12.2. Model Information
|
|
9791
|
-
*
|
|
9792
|
-
* The model information returned by the reflection function type() is specified as an
|
|
9793
|
-
* XML Schema document (xsd) and included in this specification at the following link:
|
|
9794
|
-
* https://hl7.org/fhirpath/modelinfo.xsd
|
|
9795
|
-
*
|
|
9796
|
-
* See: https://hl7.org/fhirpath/#model-information
|
|
9797
|
-
*
|
|
9798
|
-
* @param input The input collection.
|
|
9799
|
-
* @returns
|
|
9800
|
-
*/
|
|
9801
|
-
type: (input) => {
|
|
9802
|
-
return input.map(({ value }) => {
|
|
9803
|
-
if (typeof value === 'boolean') {
|
|
9804
|
-
return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Boolean' } };
|
|
9805
|
-
}
|
|
9806
|
-
if (typeof value === 'number') {
|
|
9807
|
-
return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Integer' } };
|
|
9808
|
-
}
|
|
9809
|
-
if (value && typeof value === 'object' && 'resourceType' in value) {
|
|
9810
|
-
return {
|
|
9811
|
-
type: exports.PropertyType.BackboneElement,
|
|
9812
|
-
value: { namespace: 'FHIR', name: value.resourceType },
|
|
9813
|
-
};
|
|
9814
|
-
}
|
|
9815
|
-
return { type: exports.PropertyType.BackboneElement, value: null };
|
|
9816
|
-
});
|
|
9817
|
-
},
|
|
9818
|
-
conformsTo: (input, systemAtom) => {
|
|
9819
|
-
const system = systemAtom.eval(input)[0].value;
|
|
9820
|
-
if (!system.startsWith('http://hl7.org/fhir/StructureDefinition/')) {
|
|
9821
|
-
throw new Error('Expected a StructureDefinition URL');
|
|
9822
|
-
}
|
|
9823
|
-
const expectedResourceType = system.replace('http://hl7.org/fhir/StructureDefinition/', '');
|
|
9824
|
-
return input.map((value) => {
|
|
9825
|
-
var _a;
|
|
9826
|
-
return ({
|
|
9827
|
-
type: exports.PropertyType.boolean,
|
|
9828
|
-
value: ((_a = value.value) === null || _a === void 0 ? void 0 : _a.resourceType) === expectedResourceType,
|
|
9829
|
-
});
|
|
9830
|
-
});
|
|
9831
|
-
},
|
|
9832
|
-
};
|
|
9833
|
-
/*
|
|
9834
|
-
* Helper utilities
|
|
9823
|
+
const typeName = this.right.name;
|
|
9824
|
+
return booleanToTypedValue(fhirPathIs(leftValue[0], typeName));
|
|
9825
|
+
}
|
|
9826
|
+
}
|
|
9827
|
+
/**
|
|
9828
|
+
* 6.5.1. and
|
|
9829
|
+
* Returns true if both operands evaluate to true,
|
|
9830
|
+
* false if either operand evaluates to false,
|
|
9831
|
+
* and the empty collection otherwise.
|
|
9835
9832
|
*/
|
|
9836
|
-
|
|
9837
|
-
|
|
9833
|
+
class AndAtom {
|
|
9834
|
+
constructor(left, right) {
|
|
9835
|
+
this.left = left;
|
|
9836
|
+
this.right = right;
|
|
9837
|
+
}
|
|
9838
|
+
eval(context) {
|
|
9839
|
+
var _a, _b, _c, _d;
|
|
9840
|
+
const leftValue = this.left.eval(context);
|
|
9841
|
+
const rightValue = this.right.eval(context);
|
|
9842
|
+
if (((_a = leftValue[0]) === null || _a === void 0 ? void 0 : _a.value) === true && ((_b = rightValue[0]) === null || _b === void 0 ? void 0 : _b.value) === true) {
|
|
9843
|
+
return booleanToTypedValue(true);
|
|
9844
|
+
}
|
|
9845
|
+
if (((_c = leftValue[0]) === null || _c === void 0 ? void 0 : _c.value) === false || ((_d = rightValue[0]) === null || _d === void 0 ? void 0 : _d.value) === false) {
|
|
9846
|
+
return booleanToTypedValue(false);
|
|
9847
|
+
}
|
|
9838
9848
|
return [];
|
|
9839
9849
|
}
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9850
|
+
}
|
|
9851
|
+
class OrAtom {
|
|
9852
|
+
constructor(left, right) {
|
|
9853
|
+
this.left = left;
|
|
9854
|
+
this.right = right;
|
|
9843
9855
|
}
|
|
9844
|
-
|
|
9845
|
-
|
|
9856
|
+
eval(context) {
|
|
9857
|
+
const leftValue = this.left.eval(context);
|
|
9858
|
+
if (toJsBoolean(leftValue)) {
|
|
9859
|
+
return leftValue;
|
|
9860
|
+
}
|
|
9861
|
+
const rightValue = this.right.eval(context);
|
|
9862
|
+
if (toJsBoolean(rightValue)) {
|
|
9863
|
+
return rightValue;
|
|
9864
|
+
}
|
|
9846
9865
|
return [];
|
|
9847
9866
|
}
|
|
9848
|
-
if (Array.isArray(result)) {
|
|
9849
|
-
return result.map(toTypedValue);
|
|
9850
|
-
}
|
|
9851
|
-
return [toTypedValue(result)];
|
|
9852
9867
|
}
|
|
9853
|
-
|
|
9854
|
-
|
|
9868
|
+
/**
|
|
9869
|
+
* 6.5.4. xor
|
|
9870
|
+
* Returns true if exactly one of the operands evaluates to true,
|
|
9871
|
+
* false if either both operands evaluate to true or both operands evaluate to false,
|
|
9872
|
+
* and the empty collection otherwise.
|
|
9873
|
+
*/
|
|
9874
|
+
class XorAtom {
|
|
9875
|
+
constructor(left, right) {
|
|
9876
|
+
this.left = left;
|
|
9877
|
+
this.right = right;
|
|
9878
|
+
}
|
|
9879
|
+
eval(context) {
|
|
9880
|
+
const leftResult = this.left.eval(context);
|
|
9881
|
+
const rightResult = this.right.eval(context);
|
|
9882
|
+
if (leftResult.length === 0 && rightResult.length === 0) {
|
|
9883
|
+
return [];
|
|
9884
|
+
}
|
|
9885
|
+
const leftValue = leftResult.length === 0 ? null : leftResult[0].value;
|
|
9886
|
+
const rightValue = rightResult.length === 0 ? null : rightResult[0].value;
|
|
9887
|
+
if ((leftValue === true && rightValue !== true) || (leftValue !== true && rightValue === true)) {
|
|
9888
|
+
return booleanToTypedValue(true);
|
|
9889
|
+
}
|
|
9890
|
+
if ((leftValue === true && rightValue === true) || (leftValue === false && rightValue === false)) {
|
|
9891
|
+
return booleanToTypedValue(false);
|
|
9892
|
+
}
|
|
9855
9893
|
return [];
|
|
9856
9894
|
}
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9895
|
+
}
|
|
9896
|
+
class FunctionAtom {
|
|
9897
|
+
constructor(name, args, impl) {
|
|
9898
|
+
this.name = name;
|
|
9899
|
+
this.args = args;
|
|
9900
|
+
this.impl = impl;
|
|
9901
|
+
}
|
|
9902
|
+
eval(context) {
|
|
9903
|
+
return this.impl(context, ...this.args);
|
|
9862
9904
|
}
|
|
9863
|
-
const result = func(numberInput, ...argsAtoms.map((atom) => { var _a, _b; return (_b = (_a = atom.eval(input)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value; }));
|
|
9864
|
-
const type = quantity ? exports.PropertyType.Quantity : input[0].type;
|
|
9865
|
-
const returnValue = quantity ? Object.assign(Object.assign({}, value), { value: result }) : result;
|
|
9866
|
-
return [{ type, value: returnValue }];
|
|
9867
9905
|
}
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9906
|
+
class IndexerAtom {
|
|
9907
|
+
constructor(left, expr) {
|
|
9908
|
+
this.left = left;
|
|
9909
|
+
this.expr = expr;
|
|
9871
9910
|
}
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9911
|
+
eval(context) {
|
|
9912
|
+
const evalResult = this.expr.eval(context);
|
|
9913
|
+
if (evalResult.length !== 1) {
|
|
9914
|
+
return [];
|
|
9915
|
+
}
|
|
9916
|
+
const index = evalResult[0].value;
|
|
9917
|
+
if (typeof index !== 'number') {
|
|
9918
|
+
throw new Error(`Invalid indexer expression: should return integer}`);
|
|
9919
|
+
}
|
|
9920
|
+
const leftResult = this.left.eval(context);
|
|
9921
|
+
if (!(index in leftResult)) {
|
|
9922
|
+
return [];
|
|
9875
9923
|
}
|
|
9924
|
+
return [leftResult[index]];
|
|
9876
9925
|
}
|
|
9877
|
-
return input;
|
|
9878
9926
|
}
|
|
9879
9927
|
|
|
9880
9928
|
var _Tokenizer_instances, _Tokenizer_str, _Tokenizer_pos, _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;
|
|
@@ -10427,7 +10475,7 @@
|
|
|
10427
10475
|
issue: [
|
|
10428
10476
|
{
|
|
10429
10477
|
severity: 'information',
|
|
10430
|
-
code: '
|
|
10478
|
+
code: 'informational',
|
|
10431
10479
|
details: {
|
|
10432
10480
|
text: 'All OK',
|
|
10433
10481
|
},
|
|
@@ -10440,7 +10488,7 @@
|
|
|
10440
10488
|
issue: [
|
|
10441
10489
|
{
|
|
10442
10490
|
severity: 'information',
|
|
10443
|
-
code: '
|
|
10491
|
+
code: 'informational',
|
|
10444
10492
|
details: {
|
|
10445
10493
|
text: 'Created',
|
|
10446
10494
|
},
|
|
@@ -10453,7 +10501,7 @@
|
|
|
10453
10501
|
issue: [
|
|
10454
10502
|
{
|
|
10455
10503
|
severity: 'information',
|
|
10456
|
-
code: '
|
|
10504
|
+
code: 'informational',
|
|
10457
10505
|
details: {
|
|
10458
10506
|
text: 'Not Modified',
|
|
10459
10507
|
},
|
|
@@ -10844,17 +10892,32 @@
|
|
|
10844
10892
|
* 2) The "token" type includes enums and booleans.
|
|
10845
10893
|
* 3) Arrays/multiple values are not reflected at all.
|
|
10846
10894
|
*
|
|
10847
|
-
* @param structureDefinitions Collection of StructureDefinition resources indexed by name.
|
|
10848
10895
|
* @param resourceType The root resource type.
|
|
10849
10896
|
* @param searchParam The search parameter.
|
|
10850
10897
|
* @returns The search parameter type details.
|
|
10851
10898
|
*/
|
|
10852
|
-
function getSearchParameterDetails(
|
|
10899
|
+
function getSearchParameterDetails(resourceType, searchParam) {
|
|
10900
|
+
var _a, _b;
|
|
10901
|
+
let result = (_b = (_a = globalSchema.types[resourceType]) === null || _a === void 0 ? void 0 : _a.searchParamsDetails) === null || _b === void 0 ? void 0 : _b[searchParam.code];
|
|
10902
|
+
if (!result) {
|
|
10903
|
+
result = buildSearchParamterDetails(resourceType, searchParam);
|
|
10904
|
+
}
|
|
10905
|
+
return result;
|
|
10906
|
+
}
|
|
10907
|
+
function setSearchParamterDetails(resourceType, code, details) {
|
|
10908
|
+
const typeSchema = globalSchema.types[resourceType];
|
|
10909
|
+
if (!typeSchema.searchParamsDetails) {
|
|
10910
|
+
typeSchema.searchParamsDetails = {};
|
|
10911
|
+
}
|
|
10912
|
+
typeSchema.searchParamsDetails[code] = details;
|
|
10913
|
+
}
|
|
10914
|
+
function buildSearchParamterDetails(resourceType, searchParam) {
|
|
10853
10915
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
10854
10916
|
if (searchParam.code === '_lastUpdated') {
|
|
10855
10917
|
return { columnName: 'lastUpdated', type: exports.SearchParameterType.DATETIME };
|
|
10856
10918
|
}
|
|
10857
|
-
const
|
|
10919
|
+
const code = searchParam.code;
|
|
10920
|
+
const columnName = convertCodeToColumnName(code);
|
|
10858
10921
|
const expression = (_a = getExpressionForResourceType(resourceType, searchParam.expression)) === null || _a === void 0 ? void 0 : _a.split('.');
|
|
10859
10922
|
if (!expression) {
|
|
10860
10923
|
// This happens on compound types
|
|
@@ -10869,7 +10932,7 @@
|
|
|
10869
10932
|
for (let i = 1; i < expression.length; i++) {
|
|
10870
10933
|
const propertyName = expression[i];
|
|
10871
10934
|
elementDefinition =
|
|
10872
|
-
(_d = (_c = (_b =
|
|
10935
|
+
(_d = (_c = (_b = globalSchema.types[baseType]) === null || _b === void 0 ? void 0 : _b.properties) === null || _c === void 0 ? void 0 : _c[propertyName]) !== null && _d !== void 0 ? _d : (_f = (_e = globalSchema.types[baseType]) === null || _e === void 0 ? void 0 : _e.properties) === null || _f === void 0 ? void 0 : _f[propertyName + '[x]'];
|
|
10873
10936
|
if (!elementDefinition) {
|
|
10874
10937
|
throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);
|
|
10875
10938
|
}
|
|
@@ -10892,7 +10955,9 @@
|
|
|
10892
10955
|
}
|
|
10893
10956
|
}
|
|
10894
10957
|
const type = getSearchParameterType(searchParam, propertyType);
|
|
10895
|
-
|
|
10958
|
+
const result = { columnName, type, elementDefinition, array };
|
|
10959
|
+
setSearchParamterDetails(resourceType, code, result);
|
|
10960
|
+
return result;
|
|
10896
10961
|
}
|
|
10897
10962
|
/**
|
|
10898
10963
|
* Converts a hyphen-delimited code to camelCase string.
|
|
@@ -11008,7 +11073,6 @@
|
|
|
11008
11073
|
exports.capitalize = capitalize;
|
|
11009
11074
|
exports.createReference = createReference;
|
|
11010
11075
|
exports.createSchema = createSchema;
|
|
11011
|
-
exports.createTypeSchema = createTypeSchema;
|
|
11012
11076
|
exports.created = created;
|
|
11013
11077
|
exports.deepClone = deepClone;
|
|
11014
11078
|
exports.deepEquals = deepEquals$1;
|
|
@@ -11036,6 +11100,7 @@
|
|
|
11036
11100
|
exports.getCodeBySystem = getCodeBySystem;
|
|
11037
11101
|
exports.getDateProperty = getDateProperty;
|
|
11038
11102
|
exports.getDisplayString = getDisplayString;
|
|
11103
|
+
exports.getElementDefinition = getElementDefinition;
|
|
11039
11104
|
exports.getExpressionForResourceType = getExpressionForResourceType;
|
|
11040
11105
|
exports.getExtensionValue = getExtensionValue;
|
|
11041
11106
|
exports.getIdentifier = getIdentifier;
|