@phema/cql-execution
Version:
An execution framework for the Clinical Quality Language (CQL)
1,352 lines (1,123 loc) • 1.17 MB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
/* eslint-disable
no-undef,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
window.cql = require('../../lib/cql');
window.executeSimpleELM = function (
elm,
patientSource,
valueSets,
libraryName,
version,
executionDateTime,
parameters = {}
) {
let lib;
if (Array.isArray(elm)) {
if (elm.length > 1) {
const rep = new window.cql.Repository(elm);
lib = rep.resolve(libraryName, version);
} else {
lib = new window.cql.Library(elm[0]);
}
} else {
lib = new window.cql.Library(elm);
}
const codeService = new window.cql.CodeService(valueSets);
const executor = new window.cql.Executor(lib, codeService, parameters);
return executor.exec(patientSource, executionDateTime);
};
},{"../../lib/cql":4}],2:[function(require,module,exports){
"use strict";
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; }
var _require = require('./datatypes/datatypes'),
Code = _require.Code,
ValueSet = _require.ValueSet;
var CodeService = /*#__PURE__*/function () {
function CodeService() {
var valueSetsJson = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, CodeService);
this.valueSets = {};
for (var oid in valueSetsJson) {
this.valueSets[oid] = {};
for (var version in valueSetsJson[oid]) {
var codes = valueSetsJson[oid][version].map(function (code) {
return new Code(code.code, code.system, code.version);
});
this.valueSets[oid][version] = new ValueSet(oid, version, codes);
}
}
}
_createClass(CodeService, [{
key: "findValueSetsByOid",
value: function findValueSetsByOid(oid) {
return this.valueSets[oid] ? Object.values(this.valueSets[oid]) : [];
}
}, {
key: "findValueSet",
value: function findValueSet(oid, version) {
if (version != null) {
return this.valueSets[oid] != null ? this.valueSets[oid][version] : undefined;
} else {
var results = this.findValueSetsByOid(oid);
if (results.length === 0) {
return null;
} else {
return results.reduce(function (a, b) {
if (a.version > b.version) {
return a;
} else {
return b;
}
});
}
}
}
}]);
return CodeService;
}();
module.exports.CodeService = CodeService;
},{"./datatypes/datatypes":6}],3:[function(require,module,exports){
"use strict";
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); }
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; }
var DT = require('./datatypes/datatypes');
var Record = /*#__PURE__*/function () {
function Record(json) {
_classCallCheck(this, Record);
this.json = json;
this.id = this.json.id;
}
_createClass(Record, [{
key: "_is",
value: function _is(typeSpecifier) {
return this._typeHierarchy().some(function (t) {
return t.type === typeSpecifier.type && t.name == typeSpecifier.name;
});
}
}, {
key: "_typeHierarchy",
value: function _typeHierarchy() {
return [{
name: "{https://github.com/cqframework/cql-execution/simple}".concat(this.json.recordType),
type: 'NamedTypeSpecifier'
}, {
name: '{https://github.com/cqframework/cql-execution/simple}Record',
type: 'NamedTypeSpecifier'
}, {
name: '{urn:hl7-org:elm-types:r1}Any',
type: 'NamedTypeSpecifier'
}];
}
}, {
key: "_recursiveGet",
value: function _recursiveGet(field) {
if (field != null && field.indexOf('.') >= 0) {
var _field$split = field.split('.', 2),
_field$split2 = _slicedToArray(_field$split, 2),
root = _field$split2[0],
rest = _field$split2[1];
return new Record(this._recursiveGet(root))._recursiveGet(rest);
}
return this.json[field];
}
}, {
key: "get",
value: function get(field) {
// the model should return the correct type for the field. For this simple model example,
// we just cheat and use the shape of the value to determine it. Real implementations should
// have a more sophisticated approach
var value = this._recursiveGet(field);
if (typeof value === 'string' && /\d{4}-\d{2}-\d{2}(T[\d\-.]+)?/.test(value)) {
return this.getDate(field);
}
if (value != null && _typeof(value) === 'object' && value.code != null && value.system != null) {
return this.getCode(field);
}
if (value != null && _typeof(value) === 'object' && (value.low != null || value.high != null)) {
return this.getInterval(field);
}
return value;
}
}, {
key: "getId",
value: function getId() {
return this.id;
}
}, {
key: "getDate",
value: function getDate(field) {
var val = this._recursiveGet(field);
if (val != null) {
return DT.DateTime.parse(val);
} else {
return null;
}
}
}, {
key: "getInterval",
value: function getInterval(field) {
var val = this._recursiveGet(field);
if (val != null && _typeof(val) === 'object') {
var low = val.low != null ? DT.DateTime.parse(val.low) : null;
var high = val.high != null ? DT.DateTime.parse(val.high) : null;
return new DT.Interval(low, high);
}
}
}, {
key: "getDateOrInterval",
value: function getDateOrInterval(field) {
var val = this._recursiveGet(field);
if (val != null && _typeof(val) === 'object') {
return this.getInterval(field);
} else {
return this.getDate(field);
}
}
}, {
key: "getCode",
value: function getCode(field) {
var val = this._recursiveGet(field);
if (val != null && _typeof(val) === 'object') {
return new DT.Code(val.code, val.system, val.version);
}
}
}]);
return Record;
}();
var Patient = /*#__PURE__*/function (_Record) {
_inherits(Patient, _Record);
var _super = _createSuper(Patient);
function Patient(json) {
var _this;
_classCallCheck(this, Patient);
_this = _super.call(this, json);
_this.name = json.name;
_this.gender = json.gender;
_this.birthDate = json.birthDate != null ? DT.DateTime.parse(json.birthDate) : undefined;
_this.records = {};
(json.records || []).forEach(function (r) {
if (_this.records[r.recordType] == null) {
_this.records[r.recordType] = [];
}
_this.records[r.recordType].push(new Record(r));
});
return _this;
}
_createClass(Patient, [{
key: "findRecords",
value: function findRecords(profile) {
if (profile == null) {
return [];
}
var recordType = profile.match(/(\{https:\/\/github\.com\/cqframework\/cql-execution\/simple\})?(.*)/)[2];
if (recordType === 'Patient') {
return [this];
} else {
return this.records[recordType] || [];
}
}
}]);
return Patient;
}(Record);
var PatientSource = /*#__PURE__*/function () {
function PatientSource(patients) {
_classCallCheck(this, PatientSource);
this.patients = patients;
this.nextPatient();
}
_createClass(PatientSource, [{
key: "currentPatient",
value: function currentPatient() {
return this.current;
}
}, {
key: "nextPatient",
value: function nextPatient() {
var currentJSON = this.patients.shift();
this.current = currentJSON ? new Patient(currentJSON) : undefined;
return this.current;
}
}]);
return PatientSource;
}();
module.exports.Patient = Patient;
module.exports.PatientSource = PatientSource;
},{"./datatypes/datatypes":6}],4:[function(require,module,exports){
"use strict";
var library = require('./elm/library');
var expression = require('./elm/expression');
var repository = require('./runtime/repository');
var context = require('./runtime/context');
var exec = require('./runtime/executor');
var results = require('./runtime/results');
var datatypes = require('./datatypes/datatypes');
var patient = require('./cql-patient');
var codeservice = require('./cql-code-service'); // Library-related classes
module.exports.Library = library.Library;
module.exports.Repository = repository.Repository;
module.exports.Expression = expression.Expression; // Execution-related classes
module.exports.Context = context.Context;
module.exports.Executor = exec.Executor;
module.exports.PatientContext = context.PatientContext;
module.exports.UnfilteredContext = context.UnfilteredContext;
module.exports.Results = results.Results; // PatientSource-related classes
module.exports.Patient = patient.Patient;
module.exports.PatientSource = patient.PatientSource; // TerminologyService-related classes
module.exports.CodeService = codeservice.CodeService; // DataType classes
module.exports.Code = datatypes.Code;
module.exports.CodeSystem = datatypes.CodeSystem;
module.exports.Concept = datatypes.Concept;
module.exports.Date = datatypes.Date;
module.exports.DateTime = datatypes.DateTime;
module.exports.Interval = datatypes.Interval;
module.exports.Quantity = datatypes.Quantity;
module.exports.Ratio = datatypes.Ratio;
module.exports.ValueSet = datatypes.ValueSet;
},{"./cql-code-service":2,"./cql-patient":3,"./datatypes/datatypes":6,"./elm/expression":22,"./elm/library":27,"./runtime/context":41,"./runtime/executor":42,"./runtime/repository":43,"./runtime/results":44}],5:[function(require,module,exports){
"use strict";
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
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 _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; }
var _require = require('../util/util'),
typeIsArray = _require.typeIsArray;
var Code = /*#__PURE__*/function () {
function Code(code, system, version, display) {
_classCallCheck(this, Code);
this.code = code;
this.system = system;
this.version = version;
this.display = display;
}
_createClass(Code, [{
key: "isCode",
get: function get() {
return true;
}
}, {
key: "hasMatch",
value: function hasMatch(code) {
if (typeof code === 'string') {
// the specific behavior for this is not in the specification. Matching codesystem behavior.
return code === this.code;
} else {
return codesInList(toCodeList(code), [this]);
}
}
}]);
return Code;
}();
var Concept = /*#__PURE__*/function () {
function Concept(codes, display) {
_classCallCheck(this, Concept);
this.codes = codes || [];
this.display = display;
}
_createClass(Concept, [{
key: "isConcept",
get: function get() {
return true;
}
}, {
key: "hasMatch",
value: function hasMatch(code) {
return codesInList(toCodeList(code), this.codes);
}
}]);
return Concept;
}();
var ValueSet = /*#__PURE__*/function () {
function ValueSet(oid, version, codes) {
_classCallCheck(this, ValueSet);
this.oid = oid;
this.version = version;
this.codes = codes || [];
}
_createClass(ValueSet, [{
key: "isValueSet",
get: function get() {
return true;
}
}, {
key: "hasMatch",
value: function hasMatch(code) {
var codesList = toCodeList(code); // InValueSet String Overload
if (codesList.length === 1 && typeof codesList[0] === 'string') {
var matchFound = false;
var multipleCodeSystemsExist = false;
var _iterator = _createForOfIteratorHelper(this.codes),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var codeItem = _step.value;
// Confirm all code systems match
if (codeItem.system !== this.codes[0].system) {
multipleCodeSystemsExist = true;
}
if (codeItem.code === codesList[0]) {
matchFound = true;
}
if (multipleCodeSystemsExist && matchFound) {
throw new Error('In (valueset) is ambiguous -- multiple codes with multiple code systems exist in value set.');
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return matchFound;
} else {
return codesInList(codesList, this.codes);
}
}
}]);
return ValueSet;
}();
function toCodeList(c) {
if (c == null) {
return [];
} else if (typeIsArray(c)) {
var list = [];
var _iterator2 = _createForOfIteratorHelper(c),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var c2 = _step2.value;
list = list.concat(toCodeList(c2));
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return list;
} else if (typeIsArray(c.codes)) {
return c.codes;
} else {
return [c];
}
}
function codesInList(cl1, cl2) {
// test each code in c1 against each code in c2 looking for a match
return cl1.some(function (c1) {
return cl2.some(function (c2) {
// only the left argument (cl1) can contain strings. cl2 will only contain codes.
if (typeof c1 === 'string') {
// for "string in codesystem" this should compare the string to
// the code's "code" field according to the specification.
return c1 === c2.code;
} else {
return codesMatch(c1, c2);
}
});
});
}
function codesMatch(code1, code2) {
return code1.code === code2.code && code1.system === code2.system;
}
var CodeSystem = function CodeSystem(id, version) {
_classCallCheck(this, CodeSystem);
this.id = id;
this.version = version;
};
module.exports = {
Code: Code,
Concept: Concept,
ValueSet: ValueSet,
CodeSystem: CodeSystem
};
},{"../util/util":48}],6:[function(require,module,exports){
"use strict";
var logic = require('./logic');
var clinical = require('./clinical');
var uncertainty = require('./uncertainty');
var datetime = require('./datetime');
var interval = require('./interval');
var quantity = require('./quantity');
var ratio = require('./ratio');
var libs = [logic, clinical, uncertainty, datetime, interval, quantity, ratio];
for (var _i = 0, _libs = libs; _i < _libs.length; _i++) {
var lib = _libs[_i];
for (var _i2 = 0, _Object$keys = Object.keys(lib); _i2 < _Object$keys.length; _i2++) {
var element = _Object$keys[_i2];
module.exports[element] = lib[element];
}
}
},{"./clinical":5,"./datetime":7,"./interval":9,"./logic":10,"./quantity":11,"./ratio":12,"./uncertainty":13}],7:[function(require,module,exports){
"use strict";
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
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 _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
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 _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; }
var _require = require('./uncertainty'),
Uncertainty = _require.Uncertainty;
var _require2 = require('../util/util'),
jsDate = _require2.jsDate,
normalizeMillisecondsField = _require2.normalizeMillisecondsField,
normalizeMillisecondsFieldInString = _require2.normalizeMillisecondsFieldInString;
var luxon = require('luxon'); // It's easiest and most performant to organize formats by length of the supported strings.
// This way we can test strings only against the formats that have a chance of working.
// NOTE: Formats use Luxon formats, documented here: https://moment.github.io/luxon/docs/manual/parsing.html#table-of-tokens
var LENGTH_TO_DATE_FORMAT_MAP = function () {
var ltdfMap = new Map();
ltdfMap.set(4, 'yyyy');
ltdfMap.set(7, 'yyyy-MM');
ltdfMap.set(10, 'yyyy-MM-dd');
return ltdfMap;
}();
var LENGTH_TO_DATETIME_FORMATS_MAP = function () {
var formats = {
yyyy: '2012',
'yyyy-MM': '2012-01',
'yyyy-MM-dd': '2012-01-31',
"yyyy-MM-dd'T''Z'": '2012-01-31TZ',
"yyyy-MM-dd'T'ZZ": '2012-01-31T-04:00',
"yyyy-MM-dd'T'HH": '2012-01-31T12',
"yyyy-MM-dd'T'HH'Z'": '2012-01-31T12Z',
"yyyy-MM-dd'T'HHZZ": '2012-01-31T12-04:00',
"yyyy-MM-dd'T'HH:mm": '2012-01-31T12:30',
"yyyy-MM-dd'T'HH:mm'Z'": '2012-01-31T12:30Z',
"yyyy-MM-dd'T'HH:mmZZ": '2012-01-31T12:30-04:00',
"yyyy-MM-dd'T'HH:mm:ss": '2012-01-31T12:30:59',
"yyyy-MM-dd'T'HH:mm:ss'Z'": '2012-01-31T12:30:59Z',
"yyyy-MM-dd'T'HH:mm:ssZZ": '2012-01-31T12:30:59-04:00',
"yyyy-MM-dd'T'HH:mm:ss.SSS": '2012-01-31T12:30:59.000',
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'": '2012-01-31T12:30:59.000Z',
"yyyy-MM-dd'T'HH:mm:ss.SSSZZ": '2012-01-31T12:30:59.000-04:00'
};
var ltdtfMap = new Map();
Object.keys(formats).forEach(function (k) {
var example = formats[k];
if (!ltdtfMap.has(example.length)) {
ltdtfMap.set(example.length, [k]);
} else {
ltdtfMap.get(example.length).push(k);
}
});
return ltdtfMap;
}();
function wholeLuxonDuration(duration, unit) {
var value = duration.get(unit);
return value >= 0 ? Math.floor(value) : Math.ceil(value);
}
function truncateLuxonDateTime(luxonDT, unit) {
// Truncating by week (to the previous Sunday) requires different logic than the rest
if (unit === DateTime.Unit.WEEK) {
// Sunday is ISO weekday 7
if (luxonDT.weekday !== 7) {
luxonDT = luxonDT.set({
weekday: 7
}).minus({
weeks: 1
});
}
unit = DateTime.Unit.DAY;
}
return luxonDT.startOf(unit);
}
var DateTime = /*#__PURE__*/function () {
function DateTime() {
var year = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var month = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var day = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var hour = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var minute = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
var second = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
var millisecond = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
var timezoneOffset = arguments.length > 7 ? arguments[7] : undefined;
_classCallCheck(this, DateTime);
// from the spec: If no timezone is specified, the timezone of the evaluation request timestamp is used.
// NOTE: timezoneOffset will be explicitly null for the Time overload, whereas
// it will be undefined if simply unspecified
this.year = year;
this.month = month;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
this.millisecond = millisecond;
this.timezoneOffset = timezoneOffset;
if (this.timezoneOffset === undefined) {
this.timezoneOffset = new jsDate().getTimezoneOffset() / 60 * -1;
}
}
_createClass(DateTime, [{
key: "isDateTime",
get: function get() {
return true;
}
}, {
key: "copy",
value: function copy() {
return new DateTime(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond, this.timezoneOffset);
}
}, {
key: "successor",
value: function successor() {
if (this.millisecond != null) {
return this.add(1, DateTime.Unit.MILLISECOND);
} else if (this.second != null) {
return this.add(1, DateTime.Unit.SECOND);
} else if (this.minute != null) {
return this.add(1, DateTime.Unit.MINUTE);
} else if (this.hour != null) {
return this.add(1, DateTime.Unit.HOUR);
} else if (this.day != null) {
return this.add(1, DateTime.Unit.DAY);
} else if (this.month != null) {
return this.add(1, DateTime.Unit.MONTH);
} else if (this.year != null) {
return this.add(1, DateTime.Unit.YEAR);
}
}
}, {
key: "predecessor",
value: function predecessor() {
if (this.millisecond != null) {
return this.add(-1, DateTime.Unit.MILLISECOND);
} else if (this.second != null) {
return this.add(-1, DateTime.Unit.SECOND);
} else if (this.minute != null) {
return this.add(-1, DateTime.Unit.MINUTE);
} else if (this.hour != null) {
return this.add(-1, DateTime.Unit.HOUR);
} else if (this.day != null) {
return this.add(-1, DateTime.Unit.DAY);
} else if (this.month != null) {
return this.add(-1, DateTime.Unit.MONTH);
} else if (this.year != null) {
return this.add(-1, DateTime.Unit.YEAR);
}
}
}, {
key: "convertToTimezoneOffset",
value: function convertToTimezoneOffset() {
var timezoneOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var shiftedLuxonDT = this.toLuxonDateTime().setZone(luxon.FixedOffsetZone.instance(timezoneOffset * 60));
var shiftedDT = DateTime.fromLuxonDateTime(shiftedLuxonDT);
return shiftedDT.reducedPrecision(this.getPrecision());
}
}, {
key: "differenceBetween",
value: function differenceBetween(other, unitField) {
other = this._implicitlyConvert(other);
if (other == null || !other.isDateTime) {
return null;
} // According to CQL spec:
// * "Difference calculations are performed by truncating the datetime values at the next precision,
// and then performing the corresponding duration calculation on the truncated values."
// * "When difference is calculated for hours or finer units, timezone offsets should be normalized
// prior to truncation to correctly consider real (actual elapsed) time. When difference is calculated
// for days or coarser units, however, the time components (including timezone offset) should be truncated
// without normalization to correctly reflect the difference in calendar days, months, and years."
var a = this.toLuxonUncertainty();
var b = other.toLuxonUncertainty(); // If unit is days or above, reset all the DateTimes to UTC since TZ offset should not be considered;
// Otherwise, we don't actually have to "normalize" to a common TZ because Luxon takes TZ into account.
if ([DateTime.Unit.YEAR, DateTime.Unit.MONTH, DateTime.Unit.WEEK, DateTime.Unit.DAY].includes(unitField)) {
a.low = a.low.toUTC(0, {
keepLocalTime: true
});
a.high = a.high.toUTC(0, {
keepLocalTime: true
});
b.low = b.low.toUTC(0, {
keepLocalTime: true
});
b.high = b.high.toUTC(0, {
keepLocalTime: true
});
} // Truncate all dates at precision below specified unit
a.low = truncateLuxonDateTime(a.low, unitField);
a.high = truncateLuxonDateTime(a.high, unitField);
b.low = truncateLuxonDateTime(b.low, unitField);
b.high = truncateLuxonDateTime(b.high, unitField); // Return the duration based on the normalize and truncated values
return new Uncertainty(wholeLuxonDuration(b.low.diff(a.high, unitField), unitField), wholeLuxonDuration(b.high.diff(a.low, unitField), unitField));
}
}, {
key: "durationBetween",
value: function durationBetween(other, unitField) {
other = this._implicitlyConvert(other);
if (other == null || !other.isDateTime) {
return null;
}
var a = this.toLuxonUncertainty();
var b = other.toLuxonUncertainty();
return new Uncertainty(wholeLuxonDuration(b.low.diff(a.high, unitField), unitField), wholeLuxonDuration(b.high.diff(a.low, unitField), unitField));
}
}, {
key: "isUTC",
value: function isUTC() {
// A timezoneOffset of 0 indicates UTC time.
return !this.timezoneOffset;
}
}, {
key: "getPrecision",
value: function getPrecision() {
var result = null;
if (this.year != null) {
result = DateTime.Unit.YEAR;
} else {
return result;
}
if (this.month != null) {
result = DateTime.Unit.MONTH;
} else {
return result;
}
if (this.day != null) {
result = DateTime.Unit.DAY;
} else {
return result;
}
if (this.hour != null) {
result = DateTime.Unit.HOUR;
} else {
return result;
}
if (this.minute != null) {
result = DateTime.Unit.MINUTE;
} else {
return result;
}
if (this.second != null) {
result = DateTime.Unit.SECOND;
} else {
return result;
}
if (this.millisecond != null) {
result = DateTime.Unit.MILLISECOND;
}
return result;
}
}, {
key: "toLuxonDateTime",
value: function toLuxonDateTime() {
var offsetMins = this.timezoneOffset != null ? this.timezoneOffset * 60 : new jsDate().getTimezoneOffset() * -1;
return luxon.DateTime.fromObject({
year: this.year,
month: this.month,
day: this.day,
hour: this.hour,
minute: this.minute,
second: this.second,
millisecond: this.millisecond,
zone: luxon.FixedOffsetZone.instance(offsetMins)
});
}
}, {
key: "toLuxonUncertainty",
value: function toLuxonUncertainty() {
var low = this.toLuxonDateTime();
var high = low.endOf(this.getPrecision());
return new Uncertainty(low, high);
}
}, {
key: "toJSDate",
value: function toJSDate() {
var ignoreTimezone = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var luxonDT = this.toLuxonDateTime(); // I don't know if anyone is using "ignoreTimezone" anymore (we aren't), but just in case
if (ignoreTimezone) {
var offset = new jsDate().getTimezoneOffset() * -1;
luxonDT = luxonDT.setZone(luxon.FixedOffsetZone.instance(offset), {
keepLocalTime: true
});
}
return luxonDT.toJSDate();
}
}, {
key: "toJSON",
value: function toJSON() {
return this.toString();
}
}, {
key: "_pad",
value: function _pad(num) {
return String('0' + num).slice(-2);
}
}, {
key: "toString",
value: function toString() {
if (this.isTime()) {
return this.toStringTime();
} else {
return this.toStringDateTime();
}
}
}, {
key: "toStringTime",
value: function toStringTime() {
var str = '';
if (this.hour != null) {
str += this._pad(this.hour);
if (this.minute != null) {
str += ':' + this._pad(this.minute);
if (this.second != null) {
str += ':' + this._pad(this.second);
if (this.millisecond != null) {
str += '.' + String('00' + this.millisecond).slice(-3);
}
}
}
}
return str;
}
}, {
key: "toStringDateTime",
value: function toStringDateTime() {
var str = '';
if (this.year != null) {
str += this.year;
if (this.month != null) {
str += '-' + this._pad(this.month);
if (this.day != null) {
str += '-' + this._pad(this.day);
if (this.hour != null) {
str += 'T' + this._pad(this.hour);
if (this.minute != null) {
str += ':' + this._pad(this.minute);
if (this.second != null) {
str += ':' + this._pad(this.second);
if (this.millisecond != null) {
str += '.' + String('00' + this.millisecond).slice(-3);
}
}
}
}
}
}
}
if (str.indexOf('T') !== -1 && this.timezoneOffset != null) {
str += this.timezoneOffset < 0 ? '-' : '+';
var offsetHours = Math.floor(Math.abs(this.timezoneOffset));
str += this._pad(offsetHours);
var offsetMin = (Math.abs(this.timezoneOffset) - offsetHours) * 60;
str += ':' + this._pad(offsetMin);
}
return str;
}
}, {
key: "getDateTime",
value: function getDateTime() {
return this;
}
}, {
key: "getDate",
value: function getDate() {
return new _Date(this.year, this.month, this.day);
}
}, {
key: "getTime",
value: function getTime() {
// Times no longer have timezoneOffets, so we must explicitly set it to null
return new DateTime(0, 1, 1, this.hour, this.minute, this.second, this.millisecond, null);
}
}, {
key: "isTime",
value: function isTime() {
return this.year === 0 && this.month === 1 && this.day === 1;
}
}, {
key: "_implicitlyConvert",
value: function _implicitlyConvert(other) {
if (other != null && other.isDate) {
return other.getDateTime();
}
return other;
}
}, {
key: "reducedPrecision",
value: function reducedPrecision() {
var unitField = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DateTime.Unit.MILLISECOND;
var reduced = this.copy();
if (unitField !== DateTime.Unit.MILLISECOND) {
var fieldIndex = DateTime.FIELDS.indexOf(unitField);
var fieldsToRemove = DateTime.FIELDS.slice(fieldIndex + 1);
var _iterator = _createForOfIteratorHelper(fieldsToRemove),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var field = _step.value;
reduced[field] = null;
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
return reduced;
}
}], [{
key: "parse",
value: function parse(string) {
if (string === null) {
return null;
}
var matches = /(\d{4})(-(\d{2}))?(-(\d{2}))?(T((\d{2})(:(\d{2})(:(\d{2})(\.(\d+))?)?)?)?(Z|(([+-])(\d{2})(:?(\d{2}))?))?)?/.exec(string);
if (matches == null) {
return null;
}
var years = matches[1];
var months = matches[3];
var days = matches[5];
var hours = matches[8];
var minutes = matches[10];
var seconds = matches[12];
var milliseconds = matches[14];
if (milliseconds != null) {
milliseconds = normalizeMillisecondsField(milliseconds);
}
if (milliseconds != null) {
string = normalizeMillisecondsFieldInString(string, matches[14]);
}
if (!isValidDateTimeStringFormat(string)) {
return null;
} // convert the args to integers
var args = [years, months, days, hours, minutes, seconds, milliseconds].map(function (arg) {
return arg != null ? parseInt(arg) : arg;
}); // convert timezone offset to decimal and add it to arguments
if (matches[18] != null) {
var num = parseInt(matches[18]) + (matches[20] != null ? parseInt(matches[20]) / 60 : 0);
args.push(matches[17] === '+' ? num : num * -1);
} else if (matches[15] === 'Z') {
args.push(0);
}
return _construct(DateTime, _toConsumableArray(args));
}
}, {
key: "fromJSDate",
value: function fromJSDate(date, timezoneOffset) {
//This is from a JS Date, not a CQL Date
if (date instanceof DateTime) {
return date;
}
if (timezoneOffset != null) {
date = new jsDate(date.getTime() + timezoneOffset * 60 * 60 * 1000);
return new DateTime(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds(), timezoneOffset);
} else {
return new DateTime(date.getFullYear(), date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
}
}
}, {
key: "fromLuxonDateTime",
value: function fromLuxonDateTime(luxonDT) {
if (luxonDT instanceof DateTime) {
return luxonDT;
}
return new DateTime(luxonDT.year, luxonDT.month, luxonDT.day, luxonDT.hour, luxonDT.minute, luxonDT.second, luxonDT.millisecond, luxonDT.offset / 60);
}
}]);
return DateTime;
}();
DateTime.Unit = {
YEAR: 'year',
MONTH: 'month',
WEEK: 'week',
DAY: 'day',
HOUR: 'hour',
MINUTE: 'minute',
SECOND: 'second',
MILLISECOND: 'millisecond'
};
DateTime.FIELDS = [DateTime.Unit.YEAR, DateTime.Unit.MONTH, DateTime.Unit.DAY, DateTime.Unit.HOUR, DateTime.Unit.MINUTE, DateTime.Unit.SECOND, DateTime.Unit.MILLISECOND];
var _Date = /*#__PURE__*/function () {
function _Date() {
var year = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var month = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var day = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
_classCallCheck(this, _Date);
this.year = year;
this.month = month;
this.day = day;
}
_createClass(_Date, [{
key: "isDate",
get: function get() {
return true;
}
}, {
key: "copy",
value: function copy() {
return new _Date(this.year, this.month, this.day);
}
}, {
key: "successor",
value: function successor() {
if (this.day != null) {
return this.add(1, _Date.Unit.DAY);
} else if (this.month != null) {
return this.add(1, _Date.Unit.MONTH);
} else if (this.year != null) {
return this.add(1, _Date.Unit.YEAR);
}
}
}, {
key: "predecessor",
value: function predecessor() {
if (this.day != null) {
return this.add(-1, _Date.Unit.DAY);
} else if (this.month != null) {
return this.add(-1, _Date.Unit.MONTH);
} else if (this.year != null) {
return this.add(-1, _Date.Unit.YEAR);
}
}
}, {
key: "differenceBetween",
value: function differenceBetween(other, unitField) {
if (other != null && other.isDateTime) {
return this.getDateTime().differenceBetween(other, unitField);
}
if (other == null || !other.isDate) {
return null;
} // According to CQL spec:
// * "Difference calculations are performed by truncating the datetime values at the next precision,
// and then performing the corresponding duration calculation on the truncated values."
var a = this.toLuxonUncertainty();
var b = other.toLuxonUncertainty(); // Truncate all dates at precision below specified unit
a.low = truncateLuxonDateTime(a.low, unitField);
a.high = truncateLuxonDateTime(a.high, unitField);
b.low = truncateLuxonDateTime(b.low, unitField);
b.high = truncateLuxonDateTime(b.high, unitField); // Return the duration based on the normalize and truncated values
return new Uncertainty(wholeLuxonDuration(b.low.diff(a.high, unitField), unitField), wholeLuxonDuration(b.high.diff(a.low, unitField), unitField));
}
}, {
key: "durationBetween",
value: function durationBetween(other, unitField) {
if (other != null && other.isDateTime) {
return this.getDateTime().durationBetween(other, unitField);
}
if (other == null || !other.isDate) {
return null;
}
var a = this.toLuxonUncertainty();
var b = other.toLuxonUncertainty();
return new Uncertainty(wholeLuxonDuration(b.low.diff(a.high, unitField), unitField), wholeLuxonDuration(b.high.diff(a.low, unitField), unitField));
}
}, {
key: "getPrecision",
value: function getPrecision() {
var result = null;
if (this.year != null) {
result = _Date.Unit.YEAR;
} else {
return result;
}
if (this.month != null) {
result = _Date.Unit.MONTH;
} else {
return result;
}
if (this.day != null) {
result = _Date.Unit.DAY;
} else {
return result;
}
return result;
}
}, {
key: "toLuxonDateTime",
value: function toLuxonDateTime() {
return luxon.DateTime.fromObject({
year: this.year,
month: this.month,
day: this.day,
zone: luxon.FixedOffsetZone.utcInstance
});
}
}, {
key: "toLuxonUncertainty",
value: function toLuxonUncertainty() {
var low = this.toLuxonDateTime();
var high = low.endOf(this.getPrecision()).startOf('day'); // Date type is always at T00:00:00.0
return new Uncertainty(low, high);
}
}, {
key: "toJSDate",
value: function toJSDate() {
var _ref = [this.year, this.month != null ? this.month - 1 : 0, this.day != null ? this.day : 1],
y = _ref[0],
mo = _ref[1],
d = _ref[2];
return new jsDate(y, mo, d);
}
}, {
key: "toJSON",
value: function toJSON() {
return this.toString();
}
}, {
key: "toString",
value: function toString() {
var str = '';
if (this.year != null) {
str += this.year.toString();
if (this.month != null) {
str += '-' + this.month.toString().padStart(2, '0');
if (this.day != null) {
str += '-' + this.day.toString().padStart(2, '0');
}
}
}
return str;
}
}, {
key: "getDateTime",
value: function getDateTime() {
// from the spec: the result will be a DateTime with the time components set to zero,
// except for the timezone offset, which will be set to the timezone offset of the evaluation
// request timestamp. (this last part is acheived by just not passing in timezone offset)
if (this.year != null && this.month != null && this.day != null) {
return new DateTime(this.year, this.month, this.day, 0, 0, 0, 0); // from spec: no component may be specified at a precision below an unspecified precision.
// For example, hour may be null, but if it is, minute, second, and millisecond must all be null as well.
} else {
return new DateTime(this.year, this.month, this.day);
}
}
}, {
key: "reducedPrecision",
value: function reducedPrecision() {
var unitField = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _Date.Unit.DAY;
var reduced = this.copy();
if (unitField !== _Date.Unit.DAY) {
var fieldIndex = _Date.FIELDS.indexOf(unitField);
var fieldsToRemove = _Date.FIELDS.slice(fieldIndex + 1);
var _iterator2 = _createForOfIteratorHelper(fieldsToRemove),