@medplum/core 0.9.31 → 0.9.34

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.js CHANGED
@@ -129,7 +129,7 @@
129
129
  }
130
130
  function formatHumanName(name, options) {
131
131
  const builder = [];
132
- if (name.prefix && ((options === null || options === void 0 ? void 0 : options.all) || (options === null || options === void 0 ? void 0 : options.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 && ((options === null || options === void 0 ? void 0 : options.all) || (options === null || options === void 0 ? void 0 : options.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, description) {
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
  /**
@@ -6109,17 +6103,12 @@
6109
6103
  if (!typeName) {
6110
6104
  return;
6111
6105
  }
6112
- if (!(typeName in schema.types)) {
6113
- schema.types[typeName] = createTypeSchema(typeName, structureDefinition.description);
6114
- }
6115
6106
  const elements = (_a = structureDefinition.snapshot) === null || _a === void 0 ? void 0 : _a.element;
6116
6107
  if (elements) {
6117
- // Filter out any elements missing path or type
6118
- const filtered = elements.filter((e) => e.path !== typeName && e.path);
6119
6108
  // First pass, build types
6120
- filtered.forEach((element) => indexType(schema, element));
6109
+ elements.forEach((element) => indexType(schema, structureDefinition, element));
6121
6110
  // Second pass, build properties
6122
- filtered.forEach((element) => indexProperty(schema, element));
6111
+ elements.forEach((element) => indexProperty(schema, element));
6123
6112
  }
6124
6113
  }
6125
6114
  /**
@@ -6129,19 +6118,17 @@
6129
6118
  * @param schema The output IndexedStructureDefinition.
6130
6119
  * @param element The input ElementDefinition.
6131
6120
  */
6132
- function indexType(schema, element) {
6121
+ function indexType(schema, structureDefinition, elementDefinition) {
6133
6122
  var _a, _b;
6134
- const path = element.path;
6135
- const typeCode = (_b = (_a = element.type) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.code;
6136
- if (typeCode !== 'Element' && typeCode !== 'BackboneElement') {
6123
+ const path = elementDefinition.path;
6124
+ const typeCode = (_b = (_a = elementDefinition.type) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.code;
6125
+ if (typeCode !== undefined && typeCode !== 'Element' && typeCode !== 'BackboneElement') {
6137
6126
  return;
6138
6127
  }
6139
6128
  const parts = path.split('.');
6140
6129
  const typeName = buildTypeName(parts);
6141
- if (!(typeName in schema.types)) {
6142
- schema.types[typeName] = createTypeSchema(typeName, element.definition);
6143
- schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));
6144
- }
6130
+ schema.types[typeName] = createTypeSchema(typeName, structureDefinition, elementDefinition);
6131
+ schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));
6145
6132
  }
6146
6133
  /**
6147
6134
  * Indexes PropertySchema from an ElementDefinition.
@@ -6178,12 +6165,22 @@
6178
6165
  continue;
6179
6166
  }
6180
6167
  if (!typeSchema.searchParams) {
6181
- typeSchema.searchParams = {};
6168
+ typeSchema.searchParams = {
6169
+ _lastUpdated: {
6170
+ base: [resourceType],
6171
+ code: '_lastUpdated',
6172
+ type: 'date',
6173
+ expression: resourceType + '.meta.lastUpdated',
6174
+ },
6175
+ };
6182
6176
  }
6183
6177
  typeSchema.searchParams[searchParam.code] = searchParam;
6184
6178
  }
6185
6179
  }
6186
6180
  function buildTypeName(components) {
6181
+ if (components.length === 1) {
6182
+ return components[0];
6183
+ }
6187
6184
  return components.map(capitalize).join('');
6188
6185
  }
6189
6186
  function getPropertyDisplayName(path) {
@@ -6523,8 +6520,10 @@
6523
6520
  startLogin(loginRequest) {
6524
6521
  var _a, _b;
6525
6522
  return __awaiter(this, void 0, void 0, function* () {
6526
- yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
6527
- 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: 'S256', codeChallenge: __classPrivateFieldGet(this, _MedplumClient_storage, "f").getString('codeChallenge') }));
6523
+ if (!loginRequest.codeChallenge || !loginRequest.codeChallengeMethod) {
6524
+ yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
6525
+ }
6526
+ 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
6527
  });
6529
6528
  }
6530
6529
  /**
@@ -6538,8 +6537,10 @@
6538
6537
  startGoogleLogin(loginRequest) {
6539
6538
  var _a, _b;
6540
6539
  return __awaiter(this, void 0, void 0, function* () {
6541
- yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
6542
- 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 }));
6540
+ if (!loginRequest.codeChallenge || !loginRequest.codeChallengeMethod) {
6541
+ yield __classPrivateFieldGet(this, _MedplumClient_instances, "m", _MedplumClient_startPkce).call(this);
6542
+ }
6543
+ 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
6544
  });
6544
6545
  }
6545
6546
  /**
@@ -6766,7 +6767,7 @@
6766
6767
  *
6767
6768
  * See the FHIR "read" operation for full details: https://www.hl7.org/fhir/http.html#read
6768
6769
  *
6769
- * @category Caching
6770
+ * @category Read
6770
6771
  * @param resourceType The FHIR resource type.
6771
6772
  * @param id The resource ID.
6772
6773
  * @returns The resource if available; undefined otherwise.
@@ -7321,6 +7322,20 @@
7321
7322
  graphql(query, operationName, variables, options) {
7322
7323
  return this.post(this.fhirUrl('$graphql'), { query, operationName, variables }, JSON_CONTENT_TYPE, options);
7323
7324
  }
7325
+ /**
7326
+ *
7327
+ * Executes the $graph operation on this resource to fetch a Bundle of resources linked to the target resource
7328
+ * according to a graph definition
7329
+
7330
+ * @category Read
7331
+ * @param resourceType The FHIR resource type.
7332
+ * @param id The resource ID.
7333
+ * @param graphName `name` parameter of the GraphDefinition
7334
+ * @returns A Bundle
7335
+ */
7336
+ readResourceGraph(resourceType, id, graphName) {
7337
+ return this.get(`${this.fhirUrl(resourceType, id)}/$graph?graph=${graphName}`);
7338
+ }
7324
7339
  /**
7325
7340
  * @category Authentication
7326
7341
  * @returns The Login State
@@ -7661,6 +7676,28 @@
7661
7676
  return url.endsWith('/') ? url : url + '/';
7662
7677
  }
7663
7678
 
7679
+ function parseDateString(str) {
7680
+ if (str.startsWith('T')) {
7681
+ // If a time string,
7682
+ // then normalize to full length.
7683
+ return str + 'T00:00:00.000Z'.substring(str.length);
7684
+ }
7685
+ if (str.length <= 10) {
7686
+ // If a local date (i.e., "2021-01-01"),
7687
+ // then return as-is.
7688
+ return str;
7689
+ }
7690
+ try {
7691
+ // Try to normalize to UTC
7692
+ return new Date(str).toISOString();
7693
+ }
7694
+ catch (e) {
7695
+ // Fallback to original input
7696
+ // This happens on unsupported time formats such as "2021-01-01T12"
7697
+ return str;
7698
+ }
7699
+ }
7700
+
7664
7701
  /**
7665
7702
  * Returns a single element array with a typed boolean value.
7666
7703
  * @param value The primitive boolean value.
@@ -8005,7 +8042,6 @@
8005
8042
  }
8006
8043
  /**
8007
8044
  * Resource equality.
8008
- * Ignores meta.versionId and meta.lastUpdated.
8009
8045
  * See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality
8010
8046
  * @param object1 The first object.
8011
8047
  * @param object2 The second object.
@@ -8033,478 +8069,133 @@
8033
8069
  }
8034
8070
  return true;
8035
8071
  }
8036
- function isObject(object) {
8037
- return object !== null && typeof object === 'object';
8072
+ function isObject(obj) {
8073
+ return obj !== null && typeof obj === 'object';
8038
8074
  }
8039
8075
 
8040
- var _SymbolAtom_instances, _SymbolAtom_evalValue;
8041
- class FhirPathAtom {
8042
- constructor(original, child) {
8043
- this.original = original;
8044
- this.child = child;
8045
- }
8046
- eval(context) {
8047
- try {
8048
- if (context.length > 0) {
8049
- return context.map((e) => this.child.eval([e])).flat();
8050
- }
8051
- else {
8052
- return this.child.eval([]);
8053
- }
8054
- }
8055
- catch (error) {
8056
- throw new Error(`FhirPathError on "${this.original}": ${error}`);
8057
- }
8058
- }
8059
- }
8060
- class LiteralAtom {
8061
- constructor(value) {
8062
- this.value = value;
8063
- }
8064
- eval() {
8065
- return [this.value];
8066
- }
8067
- }
8068
- class SymbolAtom {
8069
- constructor(name) {
8070
- this.name = name;
8071
- _SymbolAtom_instances.add(this);
8072
- }
8073
- eval(context) {
8074
- if (this.name === '$this') {
8075
- return context;
8076
- }
8077
- return context
8078
- .map((e) => __classPrivateFieldGet(this, _SymbolAtom_instances, "m", _SymbolAtom_evalValue).call(this, e))
8079
- .flat()
8080
- .filter((e) => (e === null || e === void 0 ? void 0 : e.value) !== undefined);
8081
- }
8082
- }
8083
- _SymbolAtom_instances = new WeakSet(), _SymbolAtom_evalValue = function _SymbolAtom_evalValue(typedValue) {
8084
- const input = typedValue.value;
8085
- if (!input || typeof input !== 'object') {
8086
- return undefined;
8087
- }
8088
- if ('resourceType' in input && input.resourceType === this.name) {
8089
- return typedValue;
8090
- }
8091
- return getTypedPropertyValue(typedValue, this.name);
8092
- };
8093
- class EmptySetAtom {
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 [];
8076
+ /**
8077
+ * Temporary placholder for unimplemented methods.
8078
+ */
8079
+ const stub = () => [];
8080
+ const functions = {
8081
+ /*
8082
+ * 5.1 Existence
8083
+ * See: https://hl7.org/fhirpath/#existence
8084
+ */
8085
+ /**
8086
+ * Returns true if the input collection is empty ({ }) and false otherwise.
8087
+ *
8088
+ * See: https://hl7.org/fhirpath/#empty-boolean
8089
+ *
8090
+ * @param input The input collection.
8091
+ * @returns True if the input collection is empty ({ }) and false otherwise.
8092
+ */
8093
+ empty: (input) => {
8094
+ return booleanToTypedValue(input.length === 0);
8095
+ },
8096
+ /**
8097
+ * Returns true if the collection has unknown elements, and false otherwise.
8098
+ * This is the opposite of empty(), and as such is a shorthand for empty().not().
8099
+ * If the input collection is empty ({ }), the result is false.
8100
+ *
8101
+ * The function can also take an optional criteria to be applied to the collection
8102
+ * prior to the determination of the exists. In this case, the function is shorthand
8103
+ * for where(criteria).exists().
8104
+ *
8105
+ * See: https://hl7.org/fhirpath/#existscriteria-expression-boolean
8106
+ *
8107
+ * @param input
8108
+ * @param criteria
8109
+ * @returns True if the collection has unknown elements, and false otherwise.
8110
+ */
8111
+ exists: (input, criteria) => {
8112
+ if (criteria) {
8113
+ return booleanToTypedValue(input.filter((e) => toJsBoolean(criteria.eval([e]))).length > 0);
8126
8114
  }
8127
- const rightEvalResult = this.right.eval(context);
8128
- if (rightEvalResult.length !== 1) {
8129
- return [];
8115
+ else {
8116
+ return booleanToTypedValue(input.length > 0);
8130
8117
  }
8131
- const leftValue = leftEvalResult[0].value;
8132
- const rightValue = rightEvalResult[0].value;
8133
- const leftNumber = isQuantity(leftValue) ? leftValue.value : leftValue;
8134
- const rightNumber = isQuantity(rightValue) ? rightValue.value : rightValue;
8135
- const result = this.impl(leftNumber, rightNumber);
8136
- if (typeof result === 'boolean') {
8137
- return booleanToTypedValue(result);
8118
+ },
8119
+ /**
8120
+ * Returns true if for every element in the input collection, criteria evaluates to true.
8121
+ * Otherwise, the result is false.
8122
+ *
8123
+ * If the input collection is empty ({ }), the result is true.
8124
+ *
8125
+ * See: https://hl7.org/fhirpath/#allcriteria-expression-boolean
8126
+ *
8127
+ * @param input The input collection.
8128
+ * @param criteria The evaluation criteria.
8129
+ * @returns True if for every element in the input collection, criteria evaluates to true.
8130
+ */
8131
+ all: (input, criteria) => {
8132
+ return booleanToTypedValue(input.every((e) => toJsBoolean(criteria.eval([e]))));
8133
+ },
8134
+ /**
8135
+ * Takes a collection of Boolean values and returns true if all the items are true.
8136
+ * If unknown items are false, the result is false.
8137
+ * If the input is empty ({ }), the result is true.
8138
+ *
8139
+ * See: https://hl7.org/fhirpath/#alltrue-boolean
8140
+ *
8141
+ * @param input The input collection.
8142
+ * @param criteria The evaluation criteria.
8143
+ * @returns True if all the items are true.
8144
+ */
8145
+ allTrue: (input) => {
8146
+ for (const value of input) {
8147
+ if (!value.value) {
8148
+ return booleanToTypedValue(false);
8149
+ }
8138
8150
  }
8139
- else if (isQuantity(leftValue)) {
8140
- return [{ type: exports.PropertyType.Quantity, value: Object.assign(Object.assign({}, leftValue), { value: result }) }];
8151
+ return booleanToTypedValue(true);
8152
+ },
8153
+ /**
8154
+ * Takes a collection of Boolean values and returns true if unknown of the items are true.
8155
+ * If all the items are false, or if the input is empty ({ }), the result is false.
8156
+ *
8157
+ * See: https://hl7.org/fhirpath/#anytrue-boolean
8158
+ *
8159
+ * @param input The input collection.
8160
+ * @param criteria The evaluation criteria.
8161
+ * @returns True if unknown of the items are true.
8162
+ */
8163
+ anyTrue: (input) => {
8164
+ for (const value of input) {
8165
+ if (value.value) {
8166
+ return booleanToTypedValue(true);
8167
+ }
8141
8168
  }
8142
- else {
8143
- return [toTypedValue(result)];
8169
+ return booleanToTypedValue(false);
8170
+ },
8171
+ /**
8172
+ * Takes a collection of Boolean values and returns true if all the items are false.
8173
+ * If unknown items are true, the result is false.
8174
+ * If the input is empty ({ }), the result is true.
8175
+ *
8176
+ * See: https://hl7.org/fhirpath/#allfalse-boolean
8177
+ *
8178
+ * @param input The input collection.
8179
+ * @param criteria The evaluation criteria.
8180
+ * @returns True if all the items are false.
8181
+ */
8182
+ allFalse: (input) => {
8183
+ for (const value of input) {
8184
+ if (value.value) {
8185
+ return booleanToTypedValue(false);
8186
+ }
8144
8187
  }
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
- */
8188
+ return booleanToTypedValue(true);
8189
+ },
8394
8190
  /**
8395
- * Returns true if the input collection is empty ({ }) and false otherwise.
8191
+ * Takes a collection of Boolean values and returns true if unknown of the items are false.
8192
+ * If all the items are true, or if the input is empty ({ }), the result is false.
8396
8193
  *
8397
- * See: https://hl7.org/fhirpath/#empty-boolean
8194
+ * See: https://hl7.org/fhirpath/#anyfalse-boolean
8398
8195
  *
8399
8196
  * @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
- }
8496
- }
8497
- return booleanToTypedValue(true);
8498
- },
8499
- /**
8500
- * Takes a collection of Boolean values and returns true if unknown of the items are false.
8501
- * If all the items are true, or if the input is empty ({ }), the result is false.
8502
- *
8503
- * See: https://hl7.org/fhirpath/#anyfalse-boolean
8504
- *
8505
- * @param input The input collection.
8506
- * @param criteria The evaluation criteria.
8507
- * @returns True if for every element in the input collection, criteria evaluates to true.
8197
+ * @param criteria The evaluation criteria.
8198
+ * @returns True if for every element in the input collection, criteria evaluates to true.
8508
8199
  */
8509
8200
  anyFalse: (input) => {
8510
8201
  for (const value of input) {
@@ -8641,7 +8332,9 @@
8641
8332
  *
8642
8333
  * See: http://hl7.org/fhirpath/#oftypetype-type-specifier-collection
8643
8334
  */
8644
- ofType: stub,
8335
+ ofType: (input, criteria) => {
8336
+ return input.filter((e) => e.type === criteria.name);
8337
+ },
8645
8338
  /*
8646
8339
  * 5.3 Subsetting
8647
8340
  */
@@ -9694,187 +9387,510 @@
9694
9387
  if (unit !== 'years' && unit !== 'months' && unit !== 'days') {
9695
9388
  throw new Error('Invalid units');
9696
9389
  }
9697
- const age = calculateAge(startDate[0].value, endDate[0].value);
9698
- return [{ type: exports.PropertyType.Quantity, value: { value: age[unit], unit } }];
9699
- },
9700
- /*
9701
- * 6.3 Types
9702
- */
9703
- /**
9704
- * The is() function is supported for backwards compatibility with previous
9705
- * implementations of FHIRPath. Just as with the is keyword, the type argument
9706
- * is an identifier that must resolve to the name of a type in a model.
9707
- *
9708
- * For implementations with compile-time typing, this requires special-case
9709
- * handling when processing the argument to treat it as a type specifier rather
9710
- * than an identifier expression:
9711
- *
9712
- * @param input
9713
- * @param typeAtom
9714
- * @returns
9715
- */
9716
- is: (input, typeAtom) => {
9717
- let typeName = '';
9718
- if (typeAtom instanceof SymbolAtom) {
9719
- typeName = typeAtom.name;
9390
+ const age = calculateAge(startDate[0].value, endDate[0].value);
9391
+ return [{ type: exports.PropertyType.Quantity, value: { value: age[unit], unit } }];
9392
+ },
9393
+ /*
9394
+ * 6.3 Types
9395
+ */
9396
+ /**
9397
+ * The is() function is supported for backwards compatibility with previous
9398
+ * implementations of FHIRPath. Just as with the is keyword, the type argument
9399
+ * is an identifier that must resolve to the name of a type in a model.
9400
+ *
9401
+ * For implementations with compile-time typing, this requires special-case
9402
+ * handling when processing the argument to treat it as a type specifier rather
9403
+ * than an identifier expression:
9404
+ *
9405
+ * @param input
9406
+ * @param typeAtom
9407
+ * @returns
9408
+ */
9409
+ is: (input, typeAtom) => {
9410
+ let typeName = '';
9411
+ if (typeAtom instanceof SymbolAtom) {
9412
+ typeName = typeAtom.name;
9413
+ }
9414
+ else if (typeAtom instanceof DotAtom) {
9415
+ typeName = typeAtom.left.name + '.' + typeAtom.right.name;
9416
+ }
9417
+ if (!typeName) {
9418
+ return [];
9419
+ }
9420
+ return input.map((value) => ({ type: exports.PropertyType.boolean, value: fhirPathIs(value, typeName) }));
9421
+ },
9422
+ /*
9423
+ * 6.5 Boolean logic
9424
+ */
9425
+ /**
9426
+ * 6.5.3. not() : Boolean
9427
+ *
9428
+ * Returns true if the input collection evaluates to false, and false if it evaluates to true. Otherwise, the result is empty ({ }):
9429
+ *
9430
+ * @param input
9431
+ * @returns
9432
+ */
9433
+ not: (input) => {
9434
+ return functions.toBoolean(input).map((value) => ({ type: exports.PropertyType.boolean, value: !value.value }));
9435
+ },
9436
+ /*
9437
+ * Additional functions
9438
+ * See: https://hl7.org/fhir/fhirpath.html#functions
9439
+ */
9440
+ /**
9441
+ * 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.
9442
+ * The items in the collection may also represent a Reference, in which case the Reference.reference is resolved.
9443
+ * @param input The input collection.
9444
+ * @returns
9445
+ */
9446
+ resolve: (input) => {
9447
+ return input
9448
+ .map((e) => {
9449
+ const value = e.value;
9450
+ let refStr;
9451
+ if (typeof value === 'string') {
9452
+ refStr = value;
9453
+ }
9454
+ else if (typeof value === 'object') {
9455
+ const ref = value;
9456
+ if (ref.resource) {
9457
+ return toTypedValue(ref.resource);
9458
+ }
9459
+ refStr = ref.reference;
9460
+ }
9461
+ if (!refStr) {
9462
+ return { type: exports.PropertyType.BackboneElement, value: null };
9463
+ }
9464
+ const [resourceType, id] = refStr.split('/');
9465
+ return { type: exports.PropertyType.BackboneElement, value: { resourceType, id } };
9466
+ })
9467
+ .filter((e) => !!e.value);
9468
+ },
9469
+ /**
9470
+ * The as operator can be used to treat a value as a specific type.
9471
+ * @param input The input value.
9472
+ * @returns The value as the specific type.
9473
+ */
9474
+ as: (input) => {
9475
+ return input;
9476
+ },
9477
+ /*
9478
+ * 12. Formal Specifications
9479
+ */
9480
+ /**
9481
+ * Returns the type of the input.
9482
+ *
9483
+ * 12.2. Model Information
9484
+ *
9485
+ * The model information returned by the reflection function type() is specified as an
9486
+ * XML Schema document (xsd) and included in this specification at the following link:
9487
+ * https://hl7.org/fhirpath/modelinfo.xsd
9488
+ *
9489
+ * See: https://hl7.org/fhirpath/#model-information
9490
+ *
9491
+ * @param input The input collection.
9492
+ * @returns
9493
+ */
9494
+ type: (input) => {
9495
+ return input.map(({ value }) => {
9496
+ if (typeof value === 'boolean') {
9497
+ return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Boolean' } };
9498
+ }
9499
+ if (typeof value === 'number') {
9500
+ return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Integer' } };
9501
+ }
9502
+ if (value && typeof value === 'object' && 'resourceType' in value) {
9503
+ return {
9504
+ type: exports.PropertyType.BackboneElement,
9505
+ value: { namespace: 'FHIR', name: value.resourceType },
9506
+ };
9507
+ }
9508
+ return { type: exports.PropertyType.BackboneElement, value: null };
9509
+ });
9510
+ },
9511
+ conformsTo: (input, systemAtom) => {
9512
+ const system = systemAtom.eval(input)[0].value;
9513
+ if (!system.startsWith('http://hl7.org/fhir/StructureDefinition/')) {
9514
+ throw new Error('Expected a StructureDefinition URL');
9515
+ }
9516
+ const expectedResourceType = system.replace('http://hl7.org/fhir/StructureDefinition/', '');
9517
+ return input.map((value) => {
9518
+ var _a;
9519
+ return ({
9520
+ type: exports.PropertyType.boolean,
9521
+ value: ((_a = value.value) === null || _a === void 0 ? void 0 : _a.resourceType) === expectedResourceType,
9522
+ });
9523
+ });
9524
+ },
9525
+ };
9526
+ /*
9527
+ * Helper utilities
9528
+ */
9529
+ function applyStringFunc(func, input, ...argsAtoms) {
9530
+ if (input.length === 0) {
9531
+ return [];
9532
+ }
9533
+ const [{ value }] = validateInput(input, 1);
9534
+ if (typeof value !== 'string') {
9535
+ throw new Error('String function cannot be called with non-string');
9536
+ }
9537
+ 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); }));
9538
+ if (result === undefined) {
9539
+ return [];
9540
+ }
9541
+ if (Array.isArray(result)) {
9542
+ return result.map(toTypedValue);
9543
+ }
9544
+ return [toTypedValue(result)];
9545
+ }
9546
+ function applyMathFunc(func, input, ...argsAtoms) {
9547
+ if (input.length === 0) {
9548
+ return [];
9549
+ }
9550
+ const [{ value }] = validateInput(input, 1);
9551
+ const quantity = isQuantity(value);
9552
+ const numberInput = quantity ? value.value : value;
9553
+ if (typeof numberInput !== 'number') {
9554
+ throw new Error('Math function cannot be called with non-number');
9555
+ }
9556
+ 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; }));
9557
+ const type = quantity ? exports.PropertyType.Quantity : input[0].type;
9558
+ const returnValue = quantity ? Object.assign(Object.assign({}, value), { value: result }) : result;
9559
+ return [{ type, value: returnValue }];
9560
+ }
9561
+ function validateInput(input, count) {
9562
+ if (input.length !== count) {
9563
+ throw new Error(`Expected ${count} arguments`);
9564
+ }
9565
+ for (const element of input) {
9566
+ if (element === null || element === undefined) {
9567
+ throw new Error('Expected non-null argument');
9568
+ }
9569
+ }
9570
+ return input;
9571
+ }
9572
+
9573
+ var _SymbolAtom_instances, _SymbolAtom_evalValue;
9574
+ class FhirPathAtom {
9575
+ constructor(original, child) {
9576
+ this.original = original;
9577
+ this.child = child;
9578
+ }
9579
+ eval(context) {
9580
+ try {
9581
+ if (context.length > 0) {
9582
+ return context.map((e) => this.child.eval([e])).flat();
9583
+ }
9584
+ else {
9585
+ return this.child.eval([]);
9586
+ }
9587
+ }
9588
+ catch (error) {
9589
+ throw new Error(`FhirPathError on "${this.original}": ${error}`);
9590
+ }
9591
+ }
9592
+ }
9593
+ class LiteralAtom {
9594
+ constructor(value) {
9595
+ this.value = value;
9596
+ }
9597
+ eval() {
9598
+ return [this.value];
9599
+ }
9600
+ }
9601
+ class SymbolAtom {
9602
+ constructor(name) {
9603
+ this.name = name;
9604
+ _SymbolAtom_instances.add(this);
9605
+ }
9606
+ eval(context) {
9607
+ if (this.name === '$this') {
9608
+ return context;
9609
+ }
9610
+ return context
9611
+ .map((e) => __classPrivateFieldGet(this, _SymbolAtom_instances, "m", _SymbolAtom_evalValue).call(this, e))
9612
+ .flat()
9613
+ .filter((e) => (e === null || e === void 0 ? void 0 : e.value) !== undefined);
9614
+ }
9615
+ }
9616
+ _SymbolAtom_instances = new WeakSet(), _SymbolAtom_evalValue = function _SymbolAtom_evalValue(typedValue) {
9617
+ const input = typedValue.value;
9618
+ if (!input || typeof input !== 'object') {
9619
+ return undefined;
9620
+ }
9621
+ if ('resourceType' in input && input.resourceType === this.name) {
9622
+ return typedValue;
9623
+ }
9624
+ return getTypedPropertyValue(typedValue, this.name);
9625
+ };
9626
+ class EmptySetAtom {
9627
+ eval() {
9628
+ return [];
9629
+ }
9630
+ }
9631
+ class UnaryOperatorAtom {
9632
+ constructor(child, impl) {
9633
+ this.child = child;
9634
+ this.impl = impl;
9635
+ }
9636
+ eval(context) {
9637
+ return this.impl(this.child.eval(context));
9638
+ }
9639
+ }
9640
+ class AsAtom {
9641
+ constructor(left, right) {
9642
+ this.left = left;
9643
+ this.right = right;
9644
+ }
9645
+ eval(context) {
9646
+ return functions.ofType(this.left.eval(context), this.right);
9647
+ }
9648
+ }
9649
+ class ArithemticOperatorAtom {
9650
+ constructor(left, right, impl) {
9651
+ this.left = left;
9652
+ this.right = right;
9653
+ this.impl = impl;
9654
+ }
9655
+ eval(context) {
9656
+ const leftEvalResult = this.left.eval(context);
9657
+ if (leftEvalResult.length !== 1) {
9658
+ return [];
9659
+ }
9660
+ const rightEvalResult = this.right.eval(context);
9661
+ if (rightEvalResult.length !== 1) {
9662
+ return [];
9663
+ }
9664
+ const leftValue = leftEvalResult[0].value;
9665
+ const rightValue = rightEvalResult[0].value;
9666
+ const leftNumber = isQuantity(leftValue) ? leftValue.value : leftValue;
9667
+ const rightNumber = isQuantity(rightValue) ? rightValue.value : rightValue;
9668
+ const result = this.impl(leftNumber, rightNumber);
9669
+ if (typeof result === 'boolean') {
9670
+ return booleanToTypedValue(result);
9671
+ }
9672
+ else if (isQuantity(leftValue)) {
9673
+ return [{ type: exports.PropertyType.Quantity, value: Object.assign(Object.assign({}, leftValue), { value: result }) }];
9674
+ }
9675
+ else {
9676
+ return [toTypedValue(result)];
9677
+ }
9678
+ }
9679
+ }
9680
+ class ConcatAtom {
9681
+ constructor(left, right) {
9682
+ this.left = left;
9683
+ this.right = right;
9684
+ }
9685
+ eval(context) {
9686
+ const leftValue = this.left.eval(context);
9687
+ const rightValue = this.right.eval(context);
9688
+ const result = [...leftValue, ...rightValue];
9689
+ if (result.length > 0 && result.every((e) => typeof e.value === 'string')) {
9690
+ return [{ type: exports.PropertyType.string, value: result.map((e) => e.value).join('') }];
9691
+ }
9692
+ return result;
9693
+ }
9694
+ }
9695
+ class ContainsAtom {
9696
+ constructor(left, right) {
9697
+ this.left = left;
9698
+ this.right = right;
9699
+ }
9700
+ eval(context) {
9701
+ const leftValue = this.left.eval(context);
9702
+ const rightValue = this.right.eval(context);
9703
+ return booleanToTypedValue(leftValue.some((e) => e.value === rightValue[0].value));
9704
+ }
9705
+ }
9706
+ class InAtom {
9707
+ constructor(left, right) {
9708
+ this.left = left;
9709
+ this.right = right;
9710
+ }
9711
+ eval(context) {
9712
+ const leftValue = this.left.eval(context);
9713
+ const rightValue = this.right.eval(context);
9714
+ return booleanToTypedValue(rightValue.some((e) => e.value === leftValue[0].value));
9715
+ }
9716
+ }
9717
+ class DotAtom {
9718
+ constructor(left, right) {
9719
+ this.left = left;
9720
+ this.right = right;
9721
+ }
9722
+ eval(context) {
9723
+ return this.right.eval(this.left.eval(context));
9724
+ }
9725
+ }
9726
+ class UnionAtom {
9727
+ constructor(left, right) {
9728
+ this.left = left;
9729
+ this.right = right;
9730
+ }
9731
+ eval(context) {
9732
+ const leftResult = this.left.eval(context);
9733
+ const rightResult = this.right.eval(context);
9734
+ return removeDuplicates([...leftResult, ...rightResult]);
9735
+ }
9736
+ }
9737
+ class EqualsAtom {
9738
+ constructor(left, right) {
9739
+ this.left = left;
9740
+ this.right = right;
9741
+ }
9742
+ eval(context) {
9743
+ const leftValue = this.left.eval(context);
9744
+ const rightValue = this.right.eval(context);
9745
+ return fhirPathArrayEquals(leftValue, rightValue);
9746
+ }
9747
+ }
9748
+ class NotEqualsAtom {
9749
+ constructor(left, right) {
9750
+ this.left = left;
9751
+ this.right = right;
9752
+ }
9753
+ eval(context) {
9754
+ const leftValue = this.left.eval(context);
9755
+ const rightValue = this.right.eval(context);
9756
+ return fhirPathNot(fhirPathArrayEquals(leftValue, rightValue));
9757
+ }
9758
+ }
9759
+ class EquivalentAtom {
9760
+ constructor(left, right) {
9761
+ this.left = left;
9762
+ this.right = right;
9763
+ }
9764
+ eval(context) {
9765
+ const leftValue = this.left.eval(context);
9766
+ const rightValue = this.right.eval(context);
9767
+ return fhirPathArrayEquivalent(leftValue, rightValue);
9768
+ }
9769
+ }
9770
+ class NotEquivalentAtom {
9771
+ constructor(left, right) {
9772
+ this.left = left;
9773
+ this.right = right;
9774
+ }
9775
+ eval(context) {
9776
+ const leftValue = this.left.eval(context);
9777
+ const rightValue = this.right.eval(context);
9778
+ return fhirPathNot(fhirPathArrayEquivalent(leftValue, rightValue));
9779
+ }
9780
+ }
9781
+ class IsAtom {
9782
+ constructor(left, right) {
9783
+ this.left = left;
9784
+ this.right = right;
9785
+ }
9786
+ eval(context) {
9787
+ const leftValue = this.left.eval(context);
9788
+ if (leftValue.length !== 1) {
9789
+ return [];
9790
+ }
9791
+ const typeName = this.right.name;
9792
+ return booleanToTypedValue(fhirPathIs(leftValue[0], typeName));
9793
+ }
9794
+ }
9795
+ /**
9796
+ * 6.5.1. and
9797
+ * Returns true if both operands evaluate to true,
9798
+ * false if either operand evaluates to false,
9799
+ * and the empty collection otherwise.
9800
+ */
9801
+ class AndAtom {
9802
+ constructor(left, right) {
9803
+ this.left = left;
9804
+ this.right = right;
9805
+ }
9806
+ eval(context) {
9807
+ var _a, _b, _c, _d;
9808
+ const leftValue = this.left.eval(context);
9809
+ const rightValue = this.right.eval(context);
9810
+ 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) {
9811
+ return booleanToTypedValue(true);
9720
9812
  }
9721
- else if (typeAtom instanceof DotAtom) {
9722
- typeName = typeAtom.left.name + '.' + typeAtom.right.name;
9813
+ 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) {
9814
+ return booleanToTypedValue(false);
9723
9815
  }
9724
- if (!typeName) {
9725
- return [];
9816
+ return [];
9817
+ }
9818
+ }
9819
+ class OrAtom {
9820
+ constructor(left, right) {
9821
+ this.left = left;
9822
+ this.right = right;
9823
+ }
9824
+ eval(context) {
9825
+ const leftValue = this.left.eval(context);
9826
+ if (toJsBoolean(leftValue)) {
9827
+ return leftValue;
9726
9828
  }
9727
- return input.map((value) => ({ type: exports.PropertyType.boolean, value: fhirPathIs(value, typeName) }));
9728
- },
9729
- /*
9730
- * 6.5 Boolean logic
9731
- */
9732
- /**
9733
- * 6.5.3. not() : Boolean
9734
- *
9735
- * Returns true if the input collection evaluates to false, and false if it evaluates to true. Otherwise, the result is empty ({ }):
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');
9829
+ const rightValue = this.right.eval(context);
9830
+ if (toJsBoolean(rightValue)) {
9831
+ return rightValue;
9822
9832
  }
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
9835
- */
9836
- function applyStringFunc(func, input, ...argsAtoms) {
9837
- if (input.length === 0) {
9838
9833
  return [];
9839
9834
  }
9840
- const [{ value }] = validateInput(input, 1);
9841
- if (typeof value !== 'string') {
9842
- throw new Error('String function cannot be called with non-string');
9835
+ }
9836
+ /**
9837
+ * 6.5.4. xor
9838
+ * Returns true if exactly one of the operands evaluates to true,
9839
+ * false if either both operands evaluate to true or both operands evaluate to false,
9840
+ * and the empty collection otherwise.
9841
+ */
9842
+ class XorAtom {
9843
+ constructor(left, right) {
9844
+ this.left = left;
9845
+ this.right = right;
9843
9846
  }
9844
- 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); }));
9845
- if (result === undefined) {
9847
+ eval(context) {
9848
+ const leftResult = this.left.eval(context);
9849
+ const rightResult = this.right.eval(context);
9850
+ if (leftResult.length === 0 && rightResult.length === 0) {
9851
+ return [];
9852
+ }
9853
+ const leftValue = leftResult.length === 0 ? null : leftResult[0].value;
9854
+ const rightValue = rightResult.length === 0 ? null : rightResult[0].value;
9855
+ if ((leftValue === true && rightValue !== true) || (leftValue !== true && rightValue === true)) {
9856
+ return booleanToTypedValue(true);
9857
+ }
9858
+ if ((leftValue === true && rightValue === true) || (leftValue === false && rightValue === false)) {
9859
+ return booleanToTypedValue(false);
9860
+ }
9846
9861
  return [];
9847
9862
  }
9848
- if (Array.isArray(result)) {
9849
- return result.map(toTypedValue);
9850
- }
9851
- return [toTypedValue(result)];
9852
9863
  }
9853
- function applyMathFunc(func, input, ...argsAtoms) {
9854
- if (input.length === 0) {
9855
- return [];
9864
+ class FunctionAtom {
9865
+ constructor(name, args, impl) {
9866
+ this.name = name;
9867
+ this.args = args;
9868
+ this.impl = impl;
9856
9869
  }
9857
- const [{ value }] = validateInput(input, 1);
9858
- const quantity = isQuantity(value);
9859
- const numberInput = quantity ? value.value : value;
9860
- if (typeof numberInput !== 'number') {
9861
- throw new Error('Math function cannot be called with non-number');
9870
+ eval(context) {
9871
+ return this.impl(context, ...this.args);
9862
9872
  }
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
9873
  }
9868
- function validateInput(input, count) {
9869
- if (input.length !== count) {
9870
- throw new Error(`Expected ${count} arguments`);
9874
+ class IndexerAtom {
9875
+ constructor(left, expr) {
9876
+ this.left = left;
9877
+ this.expr = expr;
9871
9878
  }
9872
- for (const element of input) {
9873
- if (element === null || element === undefined) {
9874
- throw new Error('Expected non-null argument');
9879
+ eval(context) {
9880
+ const evalResult = this.expr.eval(context);
9881
+ if (evalResult.length !== 1) {
9882
+ return [];
9883
+ }
9884
+ const index = evalResult[0].value;
9885
+ if (typeof index !== 'number') {
9886
+ throw new Error(`Invalid indexer expression: should return integer}`);
9887
+ }
9888
+ const leftResult = this.left.eval(context);
9889
+ if (!(index in leftResult)) {
9890
+ return [];
9875
9891
  }
9892
+ return [leftResult[index]];
9876
9893
  }
9877
- return input;
9878
9894
  }
9879
9895
 
9880
9896
  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;
@@ -11008,7 +11024,6 @@
11008
11024
  exports.capitalize = capitalize;
11009
11025
  exports.createReference = createReference;
11010
11026
  exports.createSchema = createSchema;
11011
- exports.createTypeSchema = createTypeSchema;
11012
11027
  exports.created = created;
11013
11028
  exports.deepClone = deepClone;
11014
11029
  exports.deepEquals = deepEquals$1;