UNPKG

plywood

Version:
252 lines (251 loc) 9.02 kB
import { __extends } from "tslib"; import * as hasOwnProp from 'has-own-prop'; import { SimpleArray } from 'immutable-class'; import { repeat } from '../helper'; import { Expression } from './baseExpression'; export var POSSIBLE_TYPES = { 'NULL': 1, 'BOOLEAN': 1, 'NUMBER': 1, 'TIME': 1, 'STRING': 1, 'IP': 1, 'NUMBER_RANGE': 1, 'TIME_RANGE': 1, 'SET': 1, 'SET/NULL': 1, 'SET/BOOLEAN': 1, 'SET/NUMBER': 1, 'SET/TIME': 1, 'SET/STRING': 1, 'SET/NUMBER_RANGE': 1, 'SET/TIME_RANGE': 1, 'SET/IP': 1, 'DATASET': 1, 'TIME_SERIES': 1, }; var GENERATIONS_REGEXP = /^\^+/; var TYPE_REGEXP = /:([A-Z\/_]+)$/; var RefExpression = (function (_super) { __extends(RefExpression, _super); function RefExpression(parameters) { var _this = _super.call(this, parameters, dummyObject) || this; _this._ensureOp('ref'); var name = parameters.name; if (typeof name !== 'string' || name.length === 0) { throw new TypeError('must have a nonempty `name`'); } _this.name = name; var nest = parameters.nest; if (typeof nest !== 'number') { throw new TypeError('must have nest'); } if (nest < 0) { throw new Error('nest must be non-negative'); } _this.nest = nest; var myType = parameters.type; if (myType) { if (!RefExpression.validType(myType)) { throw new TypeError("unsupported type '".concat(myType, "'")); } _this.type = myType; } _this.simple = true; _this.ignoreCase = parameters.ignoreCase; return _this; } RefExpression.fromJS = function (parameters) { var value = Expression.jsToValue(parameters); value.nest = parameters.nest || 0; value.name = parameters.name; value.ignoreCase = parameters.ignoreCase; return new RefExpression(value); }; RefExpression.parse = function (str) { var refValue = { op: 'ref' }; var match; match = str.match(GENERATIONS_REGEXP); if (match) { var nest = match[0].length; refValue.nest = nest; str = str.substr(nest); } else { refValue.nest = 0; } match = str.match(TYPE_REGEXP); if (match) { refValue.type = match[1]; str = str.substr(0, str.length - match[0].length); } if (str[0] === '{' && str[str.length - 1] === '}') { str = str.substr(1, str.length - 2); } refValue.name = str; return new RefExpression(refValue); }; RefExpression.validType = function (typeName) { return hasOwnProp(POSSIBLE_TYPES, typeName); }; RefExpression.findProperty = function (obj, key) { return hasOwnProp(obj, key) ? key : null; }; RefExpression.findPropertyCI = function (obj, key) { var lowerKey = key.toLowerCase(); if (obj == null) return null; return SimpleArray.find(Object.keys(obj), function (v) { return v.toLowerCase() === lowerKey; }); }; RefExpression.prototype.valueOf = function () { var value = _super.prototype.valueOf.call(this); value.name = this.name; value.nest = this.nest; if (this.type) value.type = this.type; if (this.ignoreCase) value.ignoreCase = true; return value; }; RefExpression.prototype.toJS = function () { var js = _super.prototype.toJS.call(this); js.name = this.name; if (this.nest) js.nest = this.nest; if (this.type) js.type = this.type; if (this.ignoreCase) js.ignoreCase = true; return js; }; RefExpression.prototype.toString = function () { var _a = this, name = _a.name, nest = _a.nest, type = _a.type, ignoreCase = _a.ignoreCase; var str = name; if (!RefExpression.SIMPLE_NAME_REGEXP.test(name)) { str = '{' + str + '}'; } if (nest) { str = repeat('^', nest) + str; } if (type) { str += ':' + type; } return (ignoreCase ? 'i$' : '$') + str; }; RefExpression.prototype.changeName = function (name) { var value = this.valueOf(); value.name = name; return new RefExpression(value); }; RefExpression.prototype.getFn = function () { var _a = this, name = _a.name, nest = _a.nest, ignoreCase = _a.ignoreCase; if (nest) throw new Error('can not getFn on a nested function'); return function (d) { var property = ignoreCase ? RefExpression.findPropertyCI(d, name) : name; return property != null ? d[property] : null; }; }; RefExpression.prototype.calc = function (datum) { var _a = this, name = _a.name, nest = _a.nest, ignoreCase = _a.ignoreCase; if (nest) throw new Error('can not calc on a nested expression'); var property = ignoreCase ? RefExpression.findPropertyCI(datum, name) : name; return property != null ? datum[property] : null; }; RefExpression.prototype.getSQL = function (dialect, _minimal) { if (_minimal === void 0) { _minimal = false; } if (this.nest) throw new Error("can not call getSQL on unresolved expression: ".concat(this)); return dialect.maybeNamespacedName(this.name); }; RefExpression.prototype.equals = function (other) { return (_super.prototype.equals.call(this, other) && this.name === other.name && this.nest === other.nest && this.ignoreCase === other.ignoreCase); }; RefExpression.prototype.changeInTypeContext = function (typeContext) { var _a = this, nest = _a.nest, ignoreCase = _a.ignoreCase, name = _a.name; var myTypeContext = typeContext; for (var i = nest; i > 0; i--) { myTypeContext = myTypeContext.parent; if (!myTypeContext) throw new Error("went too deep on ".concat(this)); } var myName = ignoreCase ? RefExpression.findPropertyCI(myTypeContext.datasetType, name) : name; if (myName == null) throw new Error("could not resolve ".concat(this)); var nestDiff = 0; while (myTypeContext && !hasOwnProp(myTypeContext.datasetType, myName)) { myTypeContext = myTypeContext.parent; nestDiff++; } if (!myTypeContext) { throw new Error("could not resolve ".concat(this)); } var myFullType = myTypeContext.datasetType[myName]; var myType = myFullType.type; if (this.type && this.type !== myType) { throw new TypeError("type mismatch in ".concat(this, " (has: ").concat(this.type, " needs: ").concat(myType, ")")); } if (!this.type || nestDiff > 0 || ignoreCase) { return new RefExpression({ name: myName, nest: nest + nestDiff, type: myType, }); } else { return this; } }; RefExpression.prototype.updateTypeContext = function (typeContext) { if (this.type !== 'DATASET') return typeContext; var _a = this, nest = _a.nest, name = _a.name; var myTypeContext = typeContext; for (var i = nest; i > 0; i--) { myTypeContext = myTypeContext.parent; if (!myTypeContext) throw new Error('went too deep on ' + this.toString()); } var myFullType = myTypeContext.datasetType[name]; return { parent: typeContext, type: 'DATASET', datasetType: myFullType.datasetType, }; }; RefExpression.prototype.incrementNesting = function (by) { if (by === void 0) { by = 1; } var value = this.valueOf(); value.nest += by; return new RefExpression(value); }; RefExpression.prototype.upgradeToType = function (targetType) { var type = this.type; if (targetType === 'TIME' && (!type || type === 'STRING')) { return this.changeType(targetType); } return this; }; RefExpression.prototype.toCaseInsensitive = function () { var value = this.valueOf(); value.ignoreCase = true; return new RefExpression(value); }; RefExpression.prototype.changeType = function (newType) { var value = this.valueOf(); value.type = newType; return new RefExpression(value); }; RefExpression.SIMPLE_NAME_REGEXP = /^([a-z_]\w*)$/i; RefExpression.op = 'Ref'; return RefExpression; }(Expression)); export { RefExpression }; Expression._ = new RefExpression({ name: '_', nest: 0 }); Expression.register(RefExpression);