objection
Version:
An SQL-friendly ORM for Node.js
446 lines (325 loc) • 31.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _create = require('babel-runtime/core-js/object/create');
var _create2 = _interopRequireDefault(_create);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _classUtils = require('../utils/classUtils');
var _QueryBuilderContextBase = require('./QueryBuilderContextBase');
var _QueryBuilderContextBase2 = _interopRequireDefault(_QueryBuilderContextBase);
var _KnexOperation = require('./operations/KnexOperation');
var _KnexOperation2 = _interopRequireDefault(_KnexOperation);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Base functionality to be able to use query builder operation annotations.
*/
var QueryBuilderOperationSupport = function () {
function QueryBuilderOperationSupport(knex, QueryBuilderContext) {
(0, _classCallCheck3.default)(this, QueryBuilderOperationSupport);
/**
* @type {knex}
* @protected
*/
this._knex = knex;
/**
* @type {Array.<QueryBuilderOperation>}
* @protected
*/
this._operations = [];
/**
* @type {QueryBuilderContextBase}
* @protected
*/
this._context = new (QueryBuilderContext || _QueryBuilderContextBase2.default)(this._createUserContextBase());
}
/**
* @param {function=} subclassConstructor
* @return {Constructor.<QueryBuilderOperationSupport>}
*/
QueryBuilderOperationSupport.extend = function extend(subclassConstructor) {
(0, _classUtils.inherits)(subclassConstructor, this);
return subclassConstructor;
};
/**
* @param {Object=} ctx
* @returns {Object|QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.context = function context(ctx) {
if (arguments.length === 0) {
return this._context.userContext;
} else {
var ctxBase = this._createUserContextBase();
this._context.userContext = (0, _assign2.default)(ctxBase, ctx);
return this;
}
};
/**
* @param {Object=} ctx
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.mergeContext = function mergeContext(ctx) {
var oldCtx = this._context.userContext;
this._context.userContext = (0, _assign2.default)(oldCtx, ctx);
return this;
};
/**
* @param {QueryBuilderContextBase=} ctx
* @returns {QueryBuilderContextBase|QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.internalContext = function internalContext(ctx) {
if (arguments.length === 0) {
return this._context;
} else {
this._context = ctx;
return this;
}
};
/**
* @param {Object} opt
* @returns {Object|QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.internalOptions = function internalOptions(opt) {
if (arguments.length === 0) {
return this._context.options;
} else {
this._context.options = (0, _assign2.default)({}, this._context.options, opt);
return this;
}
};
/**
* @param {knex=} knex
* @returns {Object|QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.knex = function knex(_knex) {
if (arguments.length === 0) {
var knex = this._context.knex || this._knex;
if (!knex) {
throw new Error('no database connection available for a query for table ' + this.modelClass().tableName + '. ' + 'You need to bind the model class or the query to a knex instance.');
}
return knex;
} else {
this._knex = _knex;
return this;
}
};
/**
* @param {RegExp|Constructor.<? extends QueryBuilderOperation>} operationSelector
* @return {QueryBuilderBase}
*/
QueryBuilderOperationSupport.prototype.clear = function clear(operationSelector) {
var operations = [];
this.forEachOperation(operationSelector, function (op) {
operations.push(op);
}, false);
this._operations = operations;
return this;
};
/**
* @param {QueryBuilderBase} queryBuilder
* @param {RegExp|Constructor.<? extends QueryBuilderOperation>} operationSelector
* @return {QueryBuilderBase}
*/
QueryBuilderOperationSupport.prototype.copyFrom = function copyFrom(queryBuilder, operationSelector) {
var _this = this;
queryBuilder.forEachOperation(operationSelector, function (op) {
_this._operations.push(op);
});
return this;
};
/**
* @param {RegExp|Constructor.<? extends QueryBuilderOperation>} operationSelector
* @returns {boolean}
*/
QueryBuilderOperationSupport.prototype.has = function has(operationSelector) {
var found = false;
this.forEachOperation(operationSelector, function () {
found = true;
return false;
});
return found;
};
/**
* @param {RegExp|Constructor.<? extends QueryBuilderOperation>} operationSelector
* @returns {boolean}
*/
QueryBuilderOperationSupport.prototype.indexOfOperation = function indexOfOperation(operationSelector) {
var idx = -1;
this.forEachOperation(operationSelector, function (op, i) {
idx = i;
return false;
});
return idx;
};
/**
* @param {RegExp|Constructor.<? extends QueryBuilderOperation>} operationSelector
* @param {function(QueryBuilderOperation)} callback
* @param {boolean} match
* @returns {QueryBuilderBase}
*/
QueryBuilderOperationSupport.prototype.forEachOperation = function forEachOperation(operationSelector, callback) {
var match = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
if (_lodash2.default.isRegExp(operationSelector)) {
this._forEachOperationRegex(operationSelector, callback, match);
} else {
this._forEachOperationInstanceOf(operationSelector, callback, match);
}
return this;
};
/**
* @param {QueryBuilderOperation} operation
* @param {Array.<*>} args
* @param {Boolean=} pushFront
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.callQueryBuilderOperation = function callQueryBuilderOperation(operation, args, pushFront) {
if (operation.call(this, args || [])) {
if (pushFront) {
this._operations.splice(0, 0, operation);
} else {
this._operations.push(operation);
}
}
return this;
};
/**
* @param {string} methodName
* @param {Array.<*>} args
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.callKnexQueryBuilderOperation = function callKnexQueryBuilderOperation(methodName, args, pushFront) {
return this.callQueryBuilderOperation(new _KnexOperation2.default(methodName), args, pushFront);
};
/**
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.clone = function clone() {
return this.baseCloneInto(new this.constructor(this.knex()));
};
/**
* @protected
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.baseCloneInto = function baseCloneInto(builder) {
builder._knex = this._knex;
builder._operations = this._operations.slice();
builder._context = this._context.clone();
return builder;
};
/**
* @returns {knex.QueryBuilder}
*/
QueryBuilderOperationSupport.prototype.build = function build() {
return this.buildInto(this.knex().queryBuilder());
};
/**
* @protected
*/
QueryBuilderOperationSupport.prototype.buildInto = function buildInto(knexBuilder) {
var tmp = new Array(10);
var i = 0;
while (i < this._operations.length) {
var op = this._operations[i];
var ln = this._operations.length;
op.onBeforeBuild(this);
var numNew = this._operations.length - ln;
// onBeforeBuild may call methods that add more operations. If
// this was the case, move the operations to be executed next.
if (numNew > 0) {
while (tmp.length < numNew) {
tmp.push(null);
}
for (var j = 0; j < numNew; ++j) {
tmp[j] = this._operations[ln + j];
}
for (var _j = ln + numNew - 1; _j > i + numNew; --_j) {
this._operations[_j] = this._operations[_j - numNew];
}
for (var _j2 = 0; _j2 < numNew; ++_j2) {
this._operations[i + _j2 + 1] = tmp[_j2];
}
}
++i;
}
// onBuild operations should never add new operations. They should only call
// methods on the knex query builder.
for (var _i = 0, l = this._operations.length; _i < l; ++_i) {
this._operations[_i].onBuild(knexBuilder, this);
}
return knexBuilder;
};
/**
* @returns {string}
*/
QueryBuilderOperationSupport.prototype.toString = function toString() {
return this.build().toString();
};
/**
* @returns {string}
*/
QueryBuilderOperationSupport.prototype.toSql = function toSql() {
return this.toString();
};
/**
* @returns {QueryBuilderOperationSupport}
*/
QueryBuilderOperationSupport.prototype.skipUndefined = function skipUndefined() {
this._context.skipUndefined = true;
return this;
};
/**
* @returns {boolean}
*/
QueryBuilderOperationSupport.prototype.shouldSkipUndefined = function shouldSkipUndefined() {
return this._context.skipUndefined;
};
/**
* @private
*/
QueryBuilderOperationSupport.prototype._createUserContextBase = function _createUserContextBase() {
var _this2 = this;
var ctxProto = {};
Object.defineProperty(ctxProto, 'transaction', {
enumerable: false,
get: function get() {
return _this2.knex();
}
});
return (0, _create2.default)(ctxProto);
};
/**
* @private
*/
QueryBuilderOperationSupport.prototype._forEachOperationRegex = function _forEachOperationRegex(operationSelector, callback, match) {
for (var i = 0, l = this._operations.length; i < l; ++i) {
var op = this._operations[i];
if (operationSelector.test(op.name) === match) {
if (callback(op, i) === false) {
break;
}
}
}
};
/**
* @private
*/
QueryBuilderOperationSupport.prototype._forEachOperationInstanceOf = function _forEachOperationInstanceOf(operationSelector, callback, match) {
for (var i = 0, l = this._operations.length; i < l; ++i) {
var op = this._operations[i];
if (op instanceof operationSelector === match) {
if (callback(op, i) === false) {
break;
}
}
}
};
return QueryBuilderOperationSupport;
}();
exports.default = QueryBuilderOperationSupport;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlF1ZXJ5QnVpbGRlck9wZXJhdGlvblN1cHBvcnQuanMiXSwibmFtZXMiOlsiUXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydCIsImtuZXgiLCJRdWVyeUJ1aWxkZXJDb250ZXh0IiwiX2tuZXgiLCJfb3BlcmF0aW9ucyIsIl9jb250ZXh0IiwiX2NyZWF0ZVVzZXJDb250ZXh0QmFzZSIsImV4dGVuZCIsInN1YmNsYXNzQ29uc3RydWN0b3IiLCJjb250ZXh0IiwiY3R4IiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidXNlckNvbnRleHQiLCJjdHhCYXNlIiwibWVyZ2VDb250ZXh0Iiwib2xkQ3R4IiwiaW50ZXJuYWxDb250ZXh0IiwiaW50ZXJuYWxPcHRpb25zIiwib3B0Iiwib3B0aW9ucyIsIkVycm9yIiwibW9kZWxDbGFzcyIsInRhYmxlTmFtZSIsImNsZWFyIiwib3BlcmF0aW9uU2VsZWN0b3IiLCJvcGVyYXRpb25zIiwiZm9yRWFjaE9wZXJhdGlvbiIsIm9wIiwicHVzaCIsImNvcHlGcm9tIiwicXVlcnlCdWlsZGVyIiwiaGFzIiwiZm91bmQiLCJpbmRleE9mT3BlcmF0aW9uIiwiaWR4IiwiaSIsImNhbGxiYWNrIiwibWF0Y2giLCJpc1JlZ0V4cCIsIl9mb3JFYWNoT3BlcmF0aW9uUmVnZXgiLCJfZm9yRWFjaE9wZXJhdGlvbkluc3RhbmNlT2YiLCJjYWxsUXVlcnlCdWlsZGVyT3BlcmF0aW9uIiwib3BlcmF0aW9uIiwiYXJncyIsInB1c2hGcm9udCIsImNhbGwiLCJzcGxpY2UiLCJjYWxsS25leFF1ZXJ5QnVpbGRlck9wZXJhdGlvbiIsIm1ldGhvZE5hbWUiLCJjbG9uZSIsImJhc2VDbG9uZUludG8iLCJjb25zdHJ1Y3RvciIsImJ1aWxkZXIiLCJzbGljZSIsImJ1aWxkIiwiYnVpbGRJbnRvIiwia25leEJ1aWxkZXIiLCJ0bXAiLCJBcnJheSIsImxuIiwib25CZWZvcmVCdWlsZCIsIm51bU5ldyIsImoiLCJsIiwib25CdWlsZCIsInRvU3RyaW5nIiwidG9TcWwiLCJza2lwVW5kZWZpbmVkIiwic2hvdWxkU2tpcFVuZGVmaW5lZCIsImN0eFByb3RvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0IiwidGVzdCIsIm5hbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7OztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBOzs7O0lBSXFCQSw0QjtBQUVuQix3Q0FBWUMsSUFBWixFQUFrQkMsbUJBQWxCLEVBQXVDO0FBQUE7O0FBQ3JDOzs7O0FBSUEsU0FBS0MsS0FBTCxHQUFhRixJQUFiO0FBQ0E7Ozs7QUFJQSxTQUFLRyxXQUFMLEdBQW1CLEVBQW5CO0FBQ0E7Ozs7QUFJQSxTQUFLQyxRQUFMLEdBQWdCLEtBQUtILHdEQUFMLEVBQXFELEtBQUtJLHNCQUFMLEVBQXJELENBQWhCO0FBQ0Q7O0FBRUQ7Ozs7OzsrQkFJT0MsTSxtQkFBT0MsbUIsRUFBcUI7QUFDakMsOEJBQVNBLG1CQUFULEVBQThCLElBQTlCO0FBQ0EsV0FBT0EsbUJBQVA7QUFDRCxHOztBQUVEOzs7Ozs7eUNBSUFDLE8sb0JBQVFDLEcsRUFBSztBQUNYLFFBQUlDLFVBQVVDLE1BQVYsS0FBcUIsQ0FBekIsRUFBNEI7QUFDMUIsYUFBTyxLQUFLUCxRQUFMLENBQWNRLFdBQXJCO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsVUFBTUMsVUFBVSxLQUFLUixzQkFBTCxFQUFoQjtBQUNBLFdBQUtELFFBQUwsQ0FBY1EsV0FBZCxHQUE0QixzQkFBY0MsT0FBZCxFQUF1QkosR0FBdkIsQ0FBNUI7QUFDQSxhQUFPLElBQVA7QUFDRDtBQUNGLEc7O0FBRUQ7Ozs7Ozt5Q0FJQUssWSx5QkFBYUwsRyxFQUFLO0FBQ2hCLFFBQU1NLFNBQVMsS0FBS1gsUUFBTCxDQUFjUSxXQUE3QjtBQUNBLFNBQUtSLFFBQUwsQ0FBY1EsV0FBZCxHQUE0QixzQkFBY0csTUFBZCxFQUFzQk4sR0FBdEIsQ0FBNUI7QUFDQSxXQUFPLElBQVA7QUFDRCxHOztBQUVEOzs7Ozs7eUNB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LElBQWxCLENBQXVCL0MsR0FBR2dELElBQTFCLE1BQW9DdEMsS0FBeEMsRUFBK0M7QUFDN0MsWUFBSUQsU0FBU1QsRUFBVCxFQUFhUSxDQUFiLE1BQW9CLEtBQXhCLEVBQStCO0FBQzdCO0FBQ0Q7QUFDRjtBQUNGO0FBQ0YsRzs7QUFFRDs7Ozs7eUNBR0FLLDJCLHdDQUE0QmhCLGlCLEVBQW1CWSxRLEVBQVVDLEssRUFBTztBQUM5RCxTQUFLLElBQUlGLElBQUksQ0FBUixFQUFXNEIsSUFBSSxLQUFLNUQsV0FBTCxDQUFpQlEsTUFBckMsRUFBNkN3QixJQUFJNEIsQ0FBakQsRUFBb0QsRUFBRTVCLENBQXRELEVBQXlEO0FBQ3ZELFVBQU1SLEtBQUssS0FBS3hCLFdBQUwsQ0FBaUJnQyxDQUFqQixDQUFYOztBQUVBLFVBQUtSLGNBQWNILGlCQUFmLEtBQXNDYSxLQUExQyxFQUFpRDtBQUMvQyxZQUFJRCxTQUFTVCxFQUFULEVBQWFRLENBQWIsTUFBb0IsS0FBeEIsRUFBK0I7QUFDN0I7QUFDRDtBQUNGO0FBQ0Y7QUFDRixHOzs7OztrQkF6VmtCcEMsNEIiLCJmaWxlIjoiUXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge2luaGVyaXRzfSBmcm9tICcuLi91dGlscy9jbGFzc1V0aWxzJztcbmltcG9ydCBRdWVyeUJ1aWxkZXJDb250ZXh0QmFzZSBmcm9tICcuL1F1ZXJ5QnVpbGRlckNvbnRleHRCYXNlJztcbmltcG9ydCBLbmV4T3BlcmF0aW9uIGZyb20gJy4vb3BlcmF0aW9ucy9LbmV4T3BlcmF0aW9uJztcblxuLyoqXG4gKiBCYXNlIGZ1bmN0aW9uYWxpdHkgdG8gYmUgYWJsZSB0byB1c2UgcXVlcnkgYnVpbGRlciBvcGVyYXRpb24gYW5ub3RhdGlvbnMuXG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydCB7XG5cbiAgY29uc3RydWN0b3Ioa25leCwgUXVlcnlCdWlsZGVyQ29udGV4dCkge1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtrbmV4fVxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICB0aGlzLl9rbmV4ID0ga25leDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7QXJyYXkuPFF1ZXJ5QnVpbGRlck9wZXJhdGlvbj59XG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHRoaXMuX29wZXJhdGlvbnMgPSBbXTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7UXVlcnlCdWlsZGVyQ29udGV4dEJhc2V9XG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHRoaXMuX2NvbnRleHQgPSBuZXcgKFF1ZXJ5QnVpbGRlckNvbnRleHQgfHwgUXVlcnlCdWlsZGVyQ29udGV4dEJhc2UpKHRoaXMuX2NyZWF0ZVVzZXJDb250ZXh0QmFzZSgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uPX0gc3ViY2xhc3NDb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3Rvci48UXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydD59XG4gICAqL1xuICBzdGF0aWMgZXh0ZW5kKHN1YmNsYXNzQ29uc3RydWN0b3IpIHtcbiAgICBpbmhlcml0cyhzdWJjbGFzc0NvbnN0cnVjdG9yLCB0aGlzKTtcbiAgICByZXR1cm4gc3ViY2xhc3NDb25zdHJ1Y3RvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdD19IGN0eFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fFF1ZXJ5QnVpbGRlck9wZXJhdGlvblN1cHBvcnR9XG4gICAqL1xuICBjb250ZXh0KGN0eCkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udGV4dC51c2VyQ29udGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgY3R4QmFzZSA9IHRoaXMuX2NyZWF0ZVVzZXJDb250ZXh0QmFzZSgpO1xuICAgICAgdGhpcy5fY29udGV4dC51c2VyQ29udGV4dCA9IE9iamVjdC5hc3NpZ24oY3R4QmFzZSwgY3R4KTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdD19IGN0eFxuICAgKiBAcmV0dXJucyB7UXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydH1cbiAgICovXG4gIG1lcmdlQ29udGV4dChjdHgpIHtcbiAgICBjb25zdCBvbGRDdHggPSB0aGlzLl9jb250ZXh0LnVzZXJDb250ZXh0O1xuICAgIHRoaXMuX2NvbnRleHQudXNlckNvbnRleHQgPSBPYmplY3QuYXNzaWduKG9sZEN0eCwgY3R4KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1F1ZXJ5QnVpbGRlckNvbnRleHRCYXNlPX0gY3R4XG4gICAqIEByZXR1cm5zIHtRdWVyeUJ1aWxkZXJDb250ZXh0QmFzZXxRdWVyeUJ1aWxkZXJPcGVyYXRpb25TdXBwb3J0fVxuICAgKi9cbiAgaW50ZXJuYWxDb250ZXh0KGN0eCkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fY29udGV4dCA9IGN0eDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0XG4gICAqIEByZXR1cm5zIHtPYmplY3R8UXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydH1cbiAgICovXG4gIGludGVybmFsT3B0aW9ucyhvcHQpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHQub3B0aW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fY29udGV4dC5vcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5fY29udGV4dC5vcHRpb25zLCBvcHQpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7a25leD19IGtuZXhcbiAgICogQHJldHVybnMge09iamVjdHxRdWVyeUJ1aWxkZXJPcGVyYXRpb25TdXBwb3J0fVxuICAgKi9cbiAga25leChrbmV4KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnN0IGtuZXggPSB0aGlzLl9jb250ZXh0LmtuZXggfHwgdGhpcy5fa25leDtcblxuICAgICAgaWYgKCFrbmV4KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgbm8gZGF0YWJhc2UgY29ubmVjdGlvbiBhdmFpbGFibGUgZm9yIGEgcXVlcnkgZm9yIHRhYmxlICR7dGhpcy5tb2RlbENsYXNzKCkudGFibGVOYW1lfS4gYCArXG4gICAgICAgICAgYFlvdSBuZWVkIHRvIGJpbmQgdGhlIG1vZGVsIGNsYXNzIG9yIHRoZSBxdWVyeSB0byBhIGtuZXggaW5zdGFuY2UuYCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBrbmV4O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9rbmV4ID0ga25leDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1JlZ0V4cHxDb25zdHJ1Y3Rvci48PyBleHRlbmRzIFF1ZXJ5QnVpbGRlck9wZXJhdGlvbj59IG9wZXJhdGlvblNlbGVjdG9yXG4gICAqIEByZXR1cm4ge1F1ZXJ5QnVpbGRlckJhc2V9XG4gICAqL1xuICBjbGVhcihvcGVyYXRpb25TZWxlY3Rvcikge1xuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbXTtcblxuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbihvcGVyYXRpb25TZWxlY3RvciwgKG9wKSA9PiB7XG4gICAgICBvcGVyYXRpb25zLnB1c2gob3ApO1xuICAgIH0sIGZhbHNlKTtcblxuICAgIHRoaXMuX29wZXJhdGlvbnMgPSBvcGVyYXRpb25zO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UXVlcnlCdWlsZGVyQmFzZX0gcXVlcnlCdWlsZGVyXG4gICAqIEBwYXJhbSB7UmVnRXhwfENvbnN0cnVjdG9yLjw/IGV4dGVuZHMgUXVlcnlCdWlsZGVyT3BlcmF0aW9uPn0gb3BlcmF0aW9uU2VsZWN0b3JcbiAgICogQHJldHVybiB7UXVlcnlCdWlsZGVyQmFzZX1cbiAgICovXG4gIGNvcHlGcm9tKHF1ZXJ5QnVpbGRlciwgb3BlcmF0aW9uU2VsZWN0b3IpIHtcbiAgICBxdWVyeUJ1aWxkZXIuZm9yRWFjaE9wZXJhdGlvbihvcGVyYXRpb25TZWxlY3RvciwgKG9wKSA9PiB7XG4gICAgICB0aGlzLl9vcGVyYXRpb25zLnB1c2gob3ApO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWdFeHB8Q29uc3RydWN0b3IuPD8gZXh0ZW5kcyBRdWVyeUJ1aWxkZXJPcGVyYXRpb24+fSBvcGVyYXRpb25TZWxlY3RvclxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGhhcyhvcGVyYXRpb25TZWxlY3Rvcikge1xuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uKG9wZXJhdGlvblNlbGVjdG9yLCAoKSA9PiB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZm91bmQ7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWdFeHB8Q29uc3RydWN0b3IuPD8gZXh0ZW5kcyBRdWVyeUJ1aWxkZXJPcGVyYXRpb24+fSBvcGVyYXRpb25TZWxlY3RvclxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGluZGV4T2ZPcGVyYXRpb24ob3BlcmF0aW9uU2VsZWN0b3IpIHtcbiAgICBsZXQgaWR4ID0gLTE7XG5cbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb24ob3BlcmF0aW9uU2VsZWN0b3IsIChvcCwgaSkgPT4ge1xuICAgICAgaWR4ID0gaTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTtcblxuICAgIHJldHVybiBpZHg7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWdFeHB8Q29uc3RydWN0b3IuPD8gZXh0ZW5kcyBRdWVyeUJ1aWxkZXJPcGVyYXRpb24+fSBvcGVyYXRpb25TZWxlY3RvclxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKFF1ZXJ5QnVpbGRlck9wZXJhdGlvbil9IGNhbGxiYWNrXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gbWF0Y2hcbiAgICogQHJldHVybnMge1F1ZXJ5QnVpbGRlckJhc2V9XG4gICAqL1xuICBmb3JFYWNoT3BlcmF0aW9uKG9wZXJhdGlvblNlbGVjdG9yLCBjYWxsYmFjaywgbWF0Y2ggPSB0cnVlKSB7XG4gICAgaWYgKF8uaXNSZWdFeHAob3BlcmF0aW9uU2VsZWN0b3IpKSB7XG4gICAgICB0aGlzLl9mb3JFYWNoT3BlcmF0aW9uUmVnZXgob3BlcmF0aW9uU2VsZWN0b3IsIGNhbGxiYWNrLCBtYXRjaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2ZvckVhY2hPcGVyYXRpb25JbnN0YW5jZU9mKG9wZXJhdGlvblNlbGVjdG9yLCBjYWxsYmFjaywgbWF0Y2gpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UXVlcnlCdWlsZGVyT3BlcmF0aW9ufSBvcGVyYXRpb25cbiAgICogQHBhcmFtIHtBcnJheS48Kj59IGFyZ3NcbiAgICogQHBhcmFtIHtCb29sZWFuPX0gcHVzaEZyb250XG4gICAqIEByZXR1cm5zIHtRdWVyeUJ1aWxkZXJPcGVyYXRpb25TdXBwb3J0fVxuICAgKi9cbiAgIGNhbGxRdWVyeUJ1aWxkZXJPcGVyYXRpb24ob3BlcmF0aW9uLCBhcmdzLCBwdXNoRnJvbnQpIHtcbiAgICBpZiAob3BlcmF0aW9uLmNhbGwodGhpcywgYXJncyB8fCBbXSkpIHtcbiAgICAgIGlmIChwdXNoRnJvbnQpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9ucy5zcGxpY2UoMCwgMCwgb3BlcmF0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX29wZXJhdGlvbnMucHVzaChvcGVyYXRpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lXG4gICAqIEBwYXJhbSB7QXJyYXkuPCo+fSBhcmdzXG4gICAqIEByZXR1cm5zIHtRdWVyeUJ1aWxkZXJPcGVyYXRpb25TdXBwb3J0fVxuICAgKi9cbiAgY2FsbEtuZXhRdWVyeUJ1aWxkZXJPcGVyYXRpb24obWV0aG9kTmFtZSwgYXJncywgcHVzaEZyb250KSB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbFF1ZXJ5QnVpbGRlck9wZXJhdGlvbihuZXcgS25leE9wZXJhdGlvbihtZXRob2ROYW1lKSwgYXJncywgcHVzaEZyb250KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydH1cbiAgICovXG4gIGNsb25lKCkge1xuICAgIHJldHVybiB0aGlzLmJhc2VDbG9uZUludG8obmV3IHRoaXMuY29uc3RydWN0b3IodGhpcy5rbmV4KCkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEByZXR1cm5zIHtRdWVyeUJ1aWxkZXJPcGVyYXRpb25TdXBwb3J0fVxuICAgKi9cbiAgYmFzZUNsb25lSW50byhidWlsZGVyKSB7XG4gICAgYnVpbGRlci5fa25leCA9IHRoaXMuX2tuZXg7XG4gICAgYnVpbGRlci5fb3BlcmF0aW9ucyA9IHRoaXMuX29wZXJhdGlvbnMuc2xpY2UoKTtcbiAgICBidWlsZGVyLl9jb250ZXh0ID0gdGhpcy5fY29udGV4dC5jbG9uZSgpO1xuXG4gICAgcmV0dXJuIGJ1aWxkZXI7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge2tuZXguUXVlcnlCdWlsZGVyfVxuICAgKi9cbiAgYnVpbGQoKSB7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRJbnRvKHRoaXMua25leCgpLnF1ZXJ5QnVpbGRlcigpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBidWlsZEludG8oa25leEJ1aWxkZXIpIHtcbiAgICBjb25zdCB0bXAgPSBuZXcgQXJyYXkoMTApO1xuXG4gICAgbGV0IGkgPSAwO1xuICAgIHdoaWxlIChpIDwgdGhpcy5fb3BlcmF0aW9ucy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG9wID0gdGhpcy5fb3BlcmF0aW9uc1tpXTtcbiAgICAgIGNvbnN0IGxuID0gdGhpcy5fb3BlcmF0aW9ucy5sZW5ndGg7XG5cbiAgICAgIG9wLm9uQmVmb3JlQnVpbGQodGhpcyk7XG5cbiAgICAgIGNvbnN0IG51bU5ldyA9IHRoaXMuX29wZXJhdGlvbnMubGVuZ3RoIC0gbG47XG5cbiAgICAgIC8vIG9uQmVmb3JlQnVpbGQgbWF5IGNhbGwgbWV0aG9kcyB0aGF0IGFkZCBtb3JlIG9wZXJhdGlvbnMuIElmXG4gICAgICAvLyB0aGlzIHdhcyB0aGUgY2FzZSwgbW92ZSB0aGUgb3BlcmF0aW9ucyB0byBiZSBleGVjdXRlZCBuZXh0LlxuICAgICAgaWYgKG51bU5ldyA+IDApIHtcbiAgICAgICAgd2hpbGUgKHRtcC5sZW5ndGggPCBudW1OZXcpIHtcbiAgICAgICAgICB0bXAucHVzaChudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtTmV3OyArK2opIHtcbiAgICAgICAgICB0bXBbal0gPSB0aGlzLl9vcGVyYXRpb25zW2xuICsgal07XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBqID0gbG4gKyBudW1OZXcgLSAxOyBqID4gaSArIG51bU5ldzsgLS1qKSB7XG4gICAgICAgICAgdGhpcy5fb3BlcmF0aW9uc1tqXSA9IHRoaXMuX29wZXJhdGlvbnNbaiAtIG51bU5ld107XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bU5ldzsgKytqKSB7XG4gICAgICAgICAgdGhpcy5fb3BlcmF0aW9uc1tpICsgaiArIDFdID0gdG1wW2pdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgICsraTtcbiAgICB9XG5cbiAgICAvLyBvbkJ1aWxkIG9wZXJhdGlvbnMgc2hvdWxkIG5ldmVyIGFkZCBuZXcgb3BlcmF0aW9ucy4gVGhleSBzaG91bGQgb25seSBjYWxsXG4gICAgLy8gbWV0aG9kcyBvbiB0aGUga25leCBxdWVyeSBidWlsZGVyLlxuICAgIGZvciAobGV0IGkgPSAwLCBsID0gdGhpcy5fb3BlcmF0aW9ucy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgIHRoaXMuX29wZXJhdGlvbnNbaV0ub25CdWlsZChrbmV4QnVpbGRlciwgdGhpcylcbiAgICB9XG5cbiAgICByZXR1cm4ga25leEJ1aWxkZXI7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkKCkudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdG9TcWwoKSB7XG4gICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UXVlcnlCdWlsZGVyT3BlcmF0aW9uU3VwcG9ydH1cbiAgICovXG4gIHNraXBVbmRlZmluZWQoKSB7XG4gICAgdGhpcy5fY29udGV4dC5za2lwVW5kZWZpbmVkID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHNob3VsZFNraXBVbmRlZmluZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbnRleHQuc2tpcFVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2NyZWF0ZVVzZXJDb250ZXh0QmFzZSgpIHtcbiAgICBjb25zdCBjdHhQcm90byA9IHt9O1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGN0eFByb3RvLCAndHJhbnNhY3Rpb24nLCB7XG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGdldDogKCkgPT4gdGhpcy5rbmV4KClcbiAgICB9KTtcblxuICAgIHJldHVybiBPYmplY3QuY3JlYXRlKGN0eFByb3RvKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2ZvckVhY2hPcGVyYXRpb25SZWdleChvcGVyYXRpb25TZWxlY3RvciwgY2FsbGJhY2ssIG1hdGNoKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSB0aGlzLl9vcGVyYXRpb25zLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgY29uc3Qgb3AgPSB0aGlzLl9vcGVyYXRpb25zW2ldO1xuXG4gICAgICBpZiAob3BlcmF0aW9uU2VsZWN0b3IudGVzdChvcC5uYW1lKSA9PT0gbWF0Y2gpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKG9wLCBpKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2ZvckVhY2hPcGVyYXRpb25JbnN0YW5jZU9mKG9wZXJhdGlvblNlbGVjdG9yLCBjYWxsYmFjaywgbWF0Y2gpIHtcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMuX29wZXJhdGlvbnMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICBjb25zdCBvcCA9IHRoaXMuX29wZXJhdGlvbnNbaV07XG5cbiAgICAgIGlmICgob3AgaW5zdGFuY2VvZiBvcGVyYXRpb25TZWxlY3RvcikgPT09IG1hdGNoKSB7XG4gICAgICAgIGlmIChjYWxsYmFjayhvcCwgaSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==