UNPKG

@phema/cql-execution

Version:

An execution framework for the Clinical Quality Language (CQL)

1,222 lines (936 loc) 33.3 kB
"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } var _require = require('./expression'), Expression = _require.Expression, UnimplementedExpression = _require.UnimplementedExpression; var _require2 = require('../datatypes/datetime'), DateTime = _require2.DateTime, _Date = _require2.Date; var _require3 = require('../datatypes/clinical'), Concept = _require3.Concept; var _require4 = require('../datatypes/quantity'), Quantity = _require4.Quantity, parseQuantity = _require4.parseQuantity; var _require5 = require('../util/math'), isValidDecimal = _require5.isValidDecimal, isValidInteger = _require5.isValidInteger, limitDecimalPrecision = _require5.limitDecimalPrecision; var _require6 = require('../util/util'), normalizeMillisecondsField = _require6.normalizeMillisecondsField; var _require7 = require('../datatypes/ratio'), Ratio = _require7.Ratio; var _require8 = require('../datatypes/uncertainty'), Uncertainty = _require8.Uncertainty; // TODO: Casting and Conversion needs unit tests! var As = /*#__PURE__*/function (_Expression) { _inherits(As, _Expression); var _super = _createSuper(As); function As(json) { var _this; _classCallCheck(this, As); _this = _super.call(this, json); if (json.asTypeSpecifier) { _this.asTypeSpecifier = json.asTypeSpecifier; } else if (json.asType) { // convert it to a NamedTypedSpecifier _this.asTypeSpecifier = { name: json.asType, type: 'NamedTypeSpecifier' }; } _this.strict = json.strict != null ? json.strict : false; return _this; } _createClass(As, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); // If it is null, return null if (arg == null) { return null; } if (ctx.matchesTypeSpecifier(arg, this.asTypeSpecifier)) { // TODO: request patient source to change type identification return arg; } else if (this.strict) { var argTypeString = specifierToString(guessSpecifierType(arg)); var asTypeString = specifierToString(this.asTypeSpecifier); throw new Error("Cannot cast ".concat(argTypeString, " as ").concat(asTypeString)); } else { return null; } } }]); return As; }(Expression); var ToBoolean = /*#__PURE__*/function (_Expression2) { _inherits(ToBoolean, _Expression2); var _super2 = _createSuper(ToBoolean); function ToBoolean(json) { _classCallCheck(this, ToBoolean); return _super2.call(this, json); } _createClass(ToBoolean, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { var strArg = arg.toString().toLowerCase(); if (['true', 't', 'yes', 'y', '1'].includes(strArg)) { return true; } else if (['false', 'f', 'no', 'n', '0'].includes(strArg)) { return false; } } return null; } }]); return ToBoolean; }(Expression); var ToConcept = /*#__PURE__*/function (_Expression3) { _inherits(ToConcept, _Expression3); var _super3 = _createSuper(ToConcept); function ToConcept(json) { _classCallCheck(this, ToConcept); return _super3.call(this, json); } _createClass(ToConcept, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { return new Concept([arg], arg.display); } else { return null; } } }]); return ToConcept; }(Expression); var ToDate = /*#__PURE__*/function (_Expression4) { _inherits(ToDate, _Expression4); var _super4 = _createSuper(ToDate); function ToDate(json) { _classCallCheck(this, ToDate); return _super4.call(this, json); } _createClass(ToDate, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg == null) { return null; } else if (arg.isDateTime) { return arg.getDate(); } else { return _Date.parse(arg.toString()); } } }]); return ToDate; }(Expression); var ToDateTime = /*#__PURE__*/function (_Expression5) { _inherits(ToDateTime, _Expression5); var _super5 = _createSuper(ToDateTime); function ToDateTime(json) { _classCallCheck(this, ToDateTime); return _super5.call(this, json); } _createClass(ToDateTime, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg == null) { return null; } else if (arg.isDate) { return arg.getDateTime(); } else { return DateTime.parse(arg.toString()); } } }]); return ToDateTime; }(Expression); var ToDecimal = /*#__PURE__*/function (_Expression6) { _inherits(ToDecimal, _Expression6); var _super6 = _createSuper(ToDecimal); function ToDecimal(json) { _classCallCheck(this, ToDecimal); return _super6.call(this, json); } _createClass(ToDecimal, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { if (arg.isUncertainty) { var low = limitDecimalPrecision(parseFloat(arg.low.toString())); var high = limitDecimalPrecision(parseFloat(arg.high.toString())); return new Uncertainty(low, high); } else { var decimal = limitDecimalPrecision(parseFloat(arg.toString())); if (isValidDecimal(decimal)) { return decimal; } } } return null; } }]); return ToDecimal; }(Expression); var ToInteger = /*#__PURE__*/function (_Expression7) { _inherits(ToInteger, _Expression7); var _super7 = _createSuper(ToInteger); function ToInteger(json) { _classCallCheck(this, ToInteger); return _super7.call(this, json); } _createClass(ToInteger, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { var integer = parseInt(arg.toString()); if (isValidInteger(integer)) { return integer; } } return null; } }]); return ToInteger; }(Expression); var ToQuantity = /*#__PURE__*/function (_Expression8) { _inherits(ToQuantity, _Expression8); var _super8 = _createSuper(ToQuantity); function ToQuantity(json) { _classCallCheck(this, ToQuantity); return _super8.call(this, json); } _createClass(ToQuantity, [{ key: "exec", value: function exec(ctx) { return this.convertValue(this.execArgs(ctx)); } }, { key: "convertValue", value: function convertValue(val) { if (val == null) { return null; } else if (typeof val === 'number') { return new Quantity(val, '1'); } else if (val.isRatio) { // numerator and denominator are guaranteed non-null return val.numerator.dividedBy(val.denominator); } else if (val.isUncertainty) { return new Uncertainty(this.convertValue(val.low), this.convertValue(val.high)); } else { // it's a string or something else we'll try to parse as a string return parseQuantity(val.toString()); } } }]); return ToQuantity; }(Expression); var ToRatio = /*#__PURE__*/function (_Expression9) { _inherits(ToRatio, _Expression9); var _super9 = _createSuper(ToRatio); function ToRatio(json) { _classCallCheck(this, ToRatio); return _super9.call(this, json); } _createClass(ToRatio, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { // Argument will be of form '<quantity>:<quantity>' var denominator, numerator; try { // String will be split into an array. Numerator will be at index 1, Denominator will be at index 4 var splitRatioString = arg.toString().match(/^(\d+(\.\d+)?\s*('.+')?)\s*:\s*(\d+(\.\d+)?\s*('.+')?)$/); if (splitRatioString == null) { return null; } numerator = parseQuantity(splitRatioString[1]); denominator = parseQuantity(splitRatioString[4]); } catch (error) { // If the input string is not formatted correctly, or cannot be // interpreted as a valid Quantity value, the result is null. return null; } // The value element of a Quantity must be present. if (numerator == null || denominator == null) { return null; } return new Ratio(numerator, denominator); } else { return null; } } }]); return ToRatio; }(Expression); var ToString = /*#__PURE__*/function (_Expression10) { _inherits(ToString, _Expression10); var _super10 = _createSuper(ToString); function ToString(json) { _classCallCheck(this, ToString); return _super10.call(this, json); } _createClass(ToString, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { return arg.toString(); } else { return null; } } }]); return ToString; }(Expression); var ToTime = /*#__PURE__*/function (_Expression11) { _inherits(ToTime, _Expression11); var _super11 = _createSuper(ToTime); function ToTime(json) { _classCallCheck(this, ToTime); return _super11.call(this, json); } _createClass(ToTime, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg != null) { var timeString = arg.toString(); // Return null if string doesn't represent a valid ISO-8601 Time // hh:mm:ss.fff or hh:mm:ss.fff var matches = /^T?((\d{2})(:(\d{2})(:(\d{2})(\.(\d+))?)?)?)?(Z|(([+-])(\d{2})(:?(\d{2}))?))?$/.exec(timeString); if (matches == null) { return null; } var hours = matches[2]; var minutes = matches[4]; var seconds = matches[6]; // Validate h/m/s if they exist, but allow null if (hours != null) { if (hours < 0 || hours > 23) { return null; } hours = parseInt(hours, 10); } if (minutes != null) { if (minutes < 0 || minutes > 59) { return null; } minutes = parseInt(minutes, 10); } if (seconds != null) { if (seconds < 0 || seconds > 59) { return null; } seconds = parseInt(seconds, 10); } var milliseconds = matches[8]; if (milliseconds != null) { milliseconds = parseInt(normalizeMillisecondsField(milliseconds)); } // Time is implemented as Datetime with year 0, month 1, day 1 and null timezoneOffset return new DateTime(0, 1, 1, hours, minutes, seconds, milliseconds, null); } else { return null; } } }]); return ToTime; }(Expression); var Convert = /*#__PURE__*/function (_Expression12) { _inherits(Convert, _Expression12); var _super12 = _createSuper(Convert); function Convert(json) { var _this2; _classCallCheck(this, Convert); _this2 = _super12.call(this, json); _this2.operand = json.operand; _this2.toType = json.toType; return _this2; } _createClass(Convert, [{ key: "exec", value: function exec(ctx) { switch (this.toType) { case '{urn:hl7-org:elm-types:r1}Boolean': return new ToBoolean({ type: 'ToBoolean', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Concept': return new ToConcept({ type: 'ToConcept', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Decimal': return new ToDecimal({ type: 'ToDecimal', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Integer': return new ToInteger({ type: 'ToInteger', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}String': return new ToString({ type: 'ToString', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Quantity': return new ToQuantity({ type: 'ToQuantity', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}DateTime': return new ToDateTime({ type: 'ToDateTime', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Date': return new ToDate({ type: 'ToDate', operand: this.operand }).execute(ctx); case '{urn:hl7-org:elm-types:r1}Time': return new ToTime({ type: 'ToTime', operand: this.operand }).execute(ctx); default: return this.execArgs(ctx); } } }]); return Convert; }(Expression); var ConvertsToBoolean = /*#__PURE__*/function (_Expression13) { _inherits(ConvertsToBoolean, _Expression13); var _super13 = _createSuper(ConvertsToBoolean); function ConvertsToBoolean(json) { var _this3; _classCallCheck(this, ConvertsToBoolean); _this3 = _super13.call(this, json); _this3.operand = json.operand; return _this3; } _createClass(ConvertsToBoolean, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToBoolean, this.operand, ctx); } } }]); return ConvertsToBoolean; }(Expression); var ConvertsToDate = /*#__PURE__*/function (_Expression14) { _inherits(ConvertsToDate, _Expression14); var _super14 = _createSuper(ConvertsToDate); function ConvertsToDate(json) { var _this4; _classCallCheck(this, ConvertsToDate); _this4 = _super14.call(this, json); _this4.operand = json.operand; return _this4; } _createClass(ConvertsToDate, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToDate, this.operand, ctx); } } }]); return ConvertsToDate; }(Expression); var ConvertsToDateTime = /*#__PURE__*/function (_Expression15) { _inherits(ConvertsToDateTime, _Expression15); var _super15 = _createSuper(ConvertsToDateTime); function ConvertsToDateTime(json) { var _this5; _classCallCheck(this, ConvertsToDateTime); _this5 = _super15.call(this, json); _this5.operand = json.operand; return _this5; } _createClass(ConvertsToDateTime, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToDateTime, this.operand, ctx); } } }]); return ConvertsToDateTime; }(Expression); var ConvertsToDecimal = /*#__PURE__*/function (_Expression16) { _inherits(ConvertsToDecimal, _Expression16); var _super16 = _createSuper(ConvertsToDecimal); function ConvertsToDecimal(json) { var _this6; _classCallCheck(this, ConvertsToDecimal); _this6 = _super16.call(this, json); _this6.operand = json.operand; return _this6; } _createClass(ConvertsToDecimal, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToDecimal, this.operand, ctx); } } }]); return ConvertsToDecimal; }(Expression); var ConvertsToInteger = /*#__PURE__*/function (_Expression17) { _inherits(ConvertsToInteger, _Expression17); var _super17 = _createSuper(ConvertsToInteger); function ConvertsToInteger(json) { var _this7; _classCallCheck(this, ConvertsToInteger); _this7 = _super17.call(this, json); _this7.operand = json.operand; return _this7; } _createClass(ConvertsToInteger, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToInteger, this.operand, ctx); } } }]); return ConvertsToInteger; }(Expression); var ConvertsToQuantity = /*#__PURE__*/function (_Expression18) { _inherits(ConvertsToQuantity, _Expression18); var _super18 = _createSuper(ConvertsToQuantity); function ConvertsToQuantity(json) { var _this8; _classCallCheck(this, ConvertsToQuantity); _this8 = _super18.call(this, json); _this8.operand = json.operand; return _this8; } _createClass(ConvertsToQuantity, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToQuantity, this.operand, ctx); } } }]); return ConvertsToQuantity; }(Expression); var ConvertsToRatio = /*#__PURE__*/function (_Expression19) { _inherits(ConvertsToRatio, _Expression19); var _super19 = _createSuper(ConvertsToRatio); function ConvertsToRatio(json) { var _this9; _classCallCheck(this, ConvertsToRatio); _this9 = _super19.call(this, json); _this9.operand = json.operand; return _this9; } _createClass(ConvertsToRatio, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToRatio, this.operand, ctx); } } }]); return ConvertsToRatio; }(Expression); var ConvertsToString = /*#__PURE__*/function (_Expression20) { _inherits(ConvertsToString, _Expression20); var _super20 = _createSuper(ConvertsToString); function ConvertsToString(json) { var _this10; _classCallCheck(this, ConvertsToString); _this10 = _super20.call(this, json); _this10.operand = json.operand; return _this10; } _createClass(ConvertsToString, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToString, this.operand, ctx); } } }]); return ConvertsToString; }(Expression); var ConvertsToTime = /*#__PURE__*/function (_Expression21) { _inherits(ConvertsToTime, _Expression21); var _super21 = _createSuper(ConvertsToTime); function ConvertsToTime(json) { var _this11; _classCallCheck(this, ConvertsToTime); _this11 = _super21.call(this, json); _this11.operand = json.operand; return _this11; } _createClass(ConvertsToTime, [{ key: "exec", value: function exec(ctx) { var operatorValue = this.execArgs(ctx); if (operatorValue === null) { return null; } else { return canConvertToType(ToTime, this.operand, ctx); } } }]); return ConvertsToTime; }(Expression); function canConvertToType(toFunction, operand, ctx) { try { var value = new toFunction({ type: toFunction.name, operand: operand }).execute(ctx); if (value != null) { return true; } else { return false; } } catch (error) { return false; } } var ConvertQuantity = /*#__PURE__*/function (_Expression22) { _inherits(ConvertQuantity, _Expression22); var _super22 = _createSuper(ConvertQuantity); function ConvertQuantity(json) { _classCallCheck(this, ConvertQuantity); return _super22.call(this, json); } _createClass(ConvertQuantity, [{ key: "exec", value: function exec(ctx) { var _this$execArgs = this.execArgs(ctx), _this$execArgs2 = _slicedToArray(_this$execArgs, 2), quantity = _this$execArgs2[0], newUnit = _this$execArgs2[1]; if (quantity != null && newUnit != null) { try { return quantity.convertUnit(newUnit); } catch (error) { // Cannot convert input to target unit, spec says to return null return null; } } } }]); return ConvertQuantity; }(Expression); var CanConvertQuantity = /*#__PURE__*/function (_Expression23) { _inherits(CanConvertQuantity, _Expression23); var _super23 = _createSuper(CanConvertQuantity); function CanConvertQuantity(json) { _classCallCheck(this, CanConvertQuantity); return _super23.call(this, json); } _createClass(CanConvertQuantity, [{ key: "exec", value: function exec(ctx) { var _this$execArgs3 = this.execArgs(ctx), _this$execArgs4 = _slicedToArray(_this$execArgs3, 2), quantity = _this$execArgs4[0], newUnit = _this$execArgs4[1]; if (quantity != null && newUnit != null) { try { quantity.convertUnit(newUnit); return true; } catch (error) { return false; } } return null; } }]); return CanConvertQuantity; }(Expression); var Is = /*#__PURE__*/function (_Expression24) { _inherits(Is, _Expression24); var _super24 = _createSuper(Is); function Is(json) { var _this12; _classCallCheck(this, Is); _this12 = _super24.call(this, json); if (json.isTypeSpecifier) { _this12.isTypeSpecifier = json.isTypeSpecifier; } else if (json.isType) { // Convert it to a NamedTypeSpecifier _this12.isTypeSpecifier = { name: json.isType, type: 'NamedTypeSpecifier' }; } return _this12; } _createClass(Is, [{ key: "exec", value: function exec(ctx) { var arg = this.execArgs(ctx); if (arg === null) { return false; } if (typeof arg._is !== 'function' && !isSystemType(this.isTypeSpecifier)) { // We need an _is implementation in order to check non System types throw new Error("Patient Source does not support Is operation for localId: ".concat(this.localId)); } return ctx.matchesTypeSpecifier(arg, this.isTypeSpecifier); } }]); return Is; }(Expression); function isSystemType(spec) { switch (spec.type) { case 'NamedTypeSpecifier': return spec.name.startsWith('{urn:hl7-org:elm-types:r1}'); case 'ListTypeSpecifier': return isSystemType(spec.elementType); case 'TupleTypeSpecifier': return spec.element.every(function (e) { return isSystemType(e.elementType); }); case 'IntervalTypeSpecifier': return isSystemType(spec.pointType); case 'ChoiceTypeSpecifier': return spec.choice.every(function (c) { return isSystemType(c); }); default: return false; } } function specifierToString(spec) { if (typeof spec === 'string') { return spec; } else if (spec == null || spec.type == null) { return ''; } switch (spec.type) { case 'NamedTypeSpecifier': return spec.name; case 'ListTypeSpecifier': return "List<".concat(specifierToString(spec.elementType), ">"); case 'TupleTypeSpecifier': return "Tuple<".concat(spec.element.map(function (e) { return "".concat(e.name, " ").concat(specifierToString(e.elementType)); }).join(', '), ">"); case 'IntervalTypeSpecifier': return "Interval<".concat(specifierToString(spec.pointType), ">"); case 'ChoiceTypeSpecifier': return "Choice<".concat(spec.choice.map(function (c) { return specifierToString(c); }).join(', '), ">"); default: return JSON.stringify(spec); } } function guessSpecifierType(val) { if (val == null) { return 'Null'; } var typeHierarchy = typeof val._typeHierarchy === 'function' && val._typeHierarchy(); if (typeHierarchy && typeHierarchy.length > 0) { return typeHierarchy[0]; } else if (typeof val === 'boolean') { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Boolean' }; } else if (typeof val === 'number' && Math.floor(val) === val) { // it could still be a decimal, but we have to just take our best guess! return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Integer' }; } else if (typeof val === 'number') { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Decimal' }; } else if (typeof val === 'string') { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}String' }; } else if (val.isConcept) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Concept' }; } else if (val.isCode) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Code' }; } else if (val.isDate) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Date' }; } else if (val.isTime && val.isTime()) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}Time' }; } else if (val.isDateTime) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}DateTime' }; } else if (val.isQuantity) { return { type: 'NamedTypeSpecifier', name: '{urn:hl7-org:elm-types:r1}DateTime' }; } else if (Array.isArray(val)) { // Get unique types from the array (by converting to string and putting in a Set) var typesAsStrings = Array.from(new Set(val.map(function (v) { return JSON.stringify(guessSpecifierType(v)); }))); var types = typesAsStrings.map(function (ts) { return /^{/.test(ts) ? JSON.parse(ts) : ts; }); return { type: 'ListTypeSpecifier', elementType: types.length == 1 ? types[0] : { type: 'ChoiceTypeSpecifier', choice: types } }; } else if (val.isInterval) { return { type: 'IntervalTypeSpecifier', pointType: val.pointType }; } else if (_typeof(val) === 'object' && Object.keys(val).length > 0) { return { type: 'TupleTypeSpecifier', element: Object.keys(val).map(function (k) { return { name: k, elementType: guessSpecifierType(val[k]) }; }) }; } return 'Unknown'; } var IntervalTypeSpecifier = /*#__PURE__*/function (_UnimplementedExpress) { _inherits(IntervalTypeSpecifier, _UnimplementedExpress); var _super25 = _createSuper(IntervalTypeSpecifier); function IntervalTypeSpecifier() { _classCallCheck(this, IntervalTypeSpecifier); return _super25.apply(this, arguments); } return IntervalTypeSpecifier; }(UnimplementedExpression); var ListTypeSpecifier = /*#__PURE__*/function (_UnimplementedExpress2) { _inherits(ListTypeSpecifier, _UnimplementedExpress2); var _super26 = _createSuper(ListTypeSpecifier); function ListTypeSpecifier() { _classCallCheck(this, ListTypeSpecifier); return _super26.apply(this, arguments); } return ListTypeSpecifier; }(UnimplementedExpression); var NamedTypeSpecifier = /*#__PURE__*/function (_UnimplementedExpress3) { _inherits(NamedTypeSpecifier, _UnimplementedExpress3); var _super27 = _createSuper(NamedTypeSpecifier); function NamedTypeSpecifier() { _classCallCheck(this, NamedTypeSpecifier); return _super27.apply(this, arguments); } return NamedTypeSpecifier; }(UnimplementedExpression); var TupleTypeSpecifier = /*#__PURE__*/function (_UnimplementedExpress4) { _inherits(TupleTypeSpecifier, _UnimplementedExpress4); var _super28 = _createSuper(TupleTypeSpecifier); function TupleTypeSpecifier() { _classCallCheck(this, TupleTypeSpecifier); return _super28.apply(this, arguments); } return TupleTypeSpecifier; }(UnimplementedExpression); module.exports = { As: As, CanConvertQuantity: CanConvertQuantity, Convert: Convert, ConvertQuantity: ConvertQuantity, ConvertsToBoolean: ConvertsToBoolean, ConvertsToDate: ConvertsToDate, ConvertsToDateTime: ConvertsToDateTime, ConvertsToDecimal: ConvertsToDecimal, ConvertsToInteger: ConvertsToInteger, ConvertsToQuantity: ConvertsToQuantity, ConvertsToRatio: ConvertsToRatio, ConvertsToString: ConvertsToString, ConvertsToTime: ConvertsToTime, IntervalTypeSpecifier: IntervalTypeSpecifier, Is: Is, ListTypeSpecifier: ListTypeSpecifier, NamedTypeSpecifier: NamedTypeSpecifier, ToBoolean: ToBoolean, ToConcept: ToConcept, ToDate: ToDate, ToDateTime: ToDateTime, ToDecimal: ToDecimal, ToInteger: ToInteger, ToQuantity: ToQuantity, ToRatio: ToRatio, ToString: ToString, ToTime: ToTime, TupleTypeSpecifier: TupleTypeSpecifier };