j2s
Version:
JSON to SQL, build RESTful API server on the fly, which accespts JSON describing SQL query statements, support (almost) full SQL functionality, with configurable access control & pluggable middlewares
631 lines (527 loc) • 66.6 kB
JavaScript
'use strict';
var _bluebird = _interopRequireDefault(require("bluebird"));
var _isString = _interopRequireDefault(require("lodash/isString"));
var _isArray = _interopRequireDefault(require("lodash/isArray"));
var _isPlainObject = _interopRequireDefault(require("lodash/isPlainObject"));
var _isBoolean = _interopRequireDefault(require("lodash/isBoolean"));
var _isFunction = _interopRequireDefault(require("lodash/isFunction"));
var _forIn = _interopRequireDefault(require("lodash/forIn"));
var _forEach = _interopRequireDefault(require("lodash/forEach"));
var _has = _interopRequireDefault(require("lodash/has"));
var _each = _interopRequireDefault(require("lodash/each"));
var _every = _interopRequireDefault(require("lodash/every"));
var _map = _interopRequireDefault(require("lodash/map"));
var _logging = require("./logging");
var _errors = _interopRequireDefault(require("./errors"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
// Constants to denote access control rules
var ALLOW = 'allow';
var DENY = 'deny'; // For different keywords that we defined with `and` or `or` operations,
// we should use different bookshelf model methods,
// this mappings provides simpler way to decide what method name to use.
var methodMap = {
exists: {
and: 'whereExists',
or: 'orWhereExists'
},
not_exists: {
and: 'whereNotExists',
or: 'orWhereNotExists'
},
where: {
and: 'where',
or: 'orWhere'
},
where_not: {
and: 'whereNot',
or: 'orWhereNot'
},
between: {
and: 'whereBetween',
or: 'orWhereBetween'
},
not_between: {
and: 'whereNotBetween',
or: 'orWhereNotBetween'
},
"in": {
and: 'whereIn',
or: 'orWhereIn'
},
not_in: {
and: 'whereNotIn',
or: 'orWhereNotIn'
},
where_null: {
and: 'whereNull',
or: 'orWhereNull'
},
where_not_null: {
and: 'whereNotNull',
or: 'orWhereNotNull'
},
and: 'where',
// for the `and` keyword, conditions should be ANDed together
or: 'orWhere' // for the `or` keyword, conditions should be ORed together
}; // There are many string matching operations in PostgreSQL, here we chain the bookshelf instance
// with like operations according to the column, value, like operations and logical operations.
var addLikeClause = function addLikeClause(knex, builder, col, value, likeOp, logicOp) {
if ((0, _isString["default"])(value)) {
value = [].concat(value);
}
if ((0, _isArray["default"])(value)) {
builder = builder[methodMap.where[logicOp]](function () {
var qb = this;
(0, _each["default"])(value, function (str) {
var preparation = "".concat(col, " ").concat(likeOp, " ?");
if (likeOp.indexOf('like') !== -1) {
str = "%%".concat(str, "%%");
}
qb.orWhere(knex.raw(preparation, [str]));
});
});
return builder;
} else {
throw _errors["default"].ErrLikeShouldBeStringOrList;
}
}; // j2s provides different suffixes that could be appended to columns,
// to specify what kind of comparison operators to use.
var whereSuffixes = {
'gt': function gt(knex, builder, col, value, op) {
return builder[methodMap.where[op]](col, '>', value);
},
'gte': function gte(knex, builder, col, value, op) {
return builder[methodMap.where[op]](col, '>=', value);
},
'lt': function lt(knex, builder, col, value, op) {
return builder[methodMap.where[op]](col, '<', value);
},
'lte': function lte(knex, builder, col, value, op) {
return builder[methodMap.where[op]](col, '<=', value);
},
'ne': function ne(knex, builder, col, value, op) {
return builder[methodMap.where_not[op]](col, value);
},
'like': function like(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, 'like', op);
},
'not_like': function not_like(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, 'not like', op);
},
'ilike': function ilike(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, 'ilike', op);
},
'not_ilike': function not_ilike(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, 'not ilike', op);
},
'reg_like': function reg_like(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, '~', op);
},
'reg_not_like': function reg_not_like(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, '!~', op);
},
'reg_ilike': function reg_ilike(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, '~*', op);
},
'reg_not_ilike': function reg_not_ilike(knex, builder, col, value, op) {
return addLikeClause(knex, builder, col, value, '!~*', op);
},
'between': function between(knex, builder, col, value, op) {
if (!(0, _isArray["default"])(value)) {
throw _errors["default"].ErrBetweenSuffixValueShouldBeList;
}
if (value.length != 2) {
throw _errors["default"].ErrBetweenSuffixValueShouldBeLengthTwo;
}
return builder[methodMap.between[op]](col, value);
},
'not_between': function not_between(knex, builder, col, value, op) {
if (!(0, _isArray["default"])(value)) {
throw _errors["default"].ErrNotBetweenSuffixShouldBeList;
}
if (value.length != 2) {
throw _errors["default"].ErrNotBetweenSuffixShouldBeLengthTwo;
}
return builder[methodMap.not_between[op]](col, value);
},
'in': function _in(knex, builder, col, value, op) {
if (!(0, _isArray["default"])(value)) {
throw _errors["default"].ErrInSuffixShouldBeList;
}
return builder[methodMap["in"][op]](col, value);
},
'not_in': function not_in(knex, builder, col, value, op) {
if (!(0, _isArray["default"])(value)) {
throw erros.ErrNotInSuffixShouldBeList;
}
return builder[methodMap.not_in[op]](col, value);
},
'null': function _null(knex, builder, col, value, op) {
if (!(0, _isBoolean["default"])(value)) {
throw _errors["default"].ErrNullSuffixShouldBeBoolean;
}
if (value) {
return builder[methodMap.where_null[op]](col);
} else {
return builder[methodMap.where_not_null[op]](col);
}
}
}; // For the SQL EXISTS query, recursively parse the query conditions
// to form a subquery.
function existsQuery(knex, table, value) {
this.from(table);
if (!(0, _has["default"])(value, 'where')) {
this.select('*');
parseConditions(knex, this, value);
} else {
builderQuery(knex, this, value);
}
} // accepts knex query builder and conditions object, returns the builder
function parseConditions(knex, builder, conds, op) {
// default logical operation is `and`
if (!op) {
op = 'and';
}
if ((0, _isPlainObject["default"])(conds)) {
conds = [conds];
} // allow conditions to be represented as array of condition objects
(0, _each["default"])(conds, function (cond) {
// loop through key value pairs of the condition object
(0, _forIn["default"])(cond, function (v, k) {
var parts = k.split('__'); // suffix is appended to column names with double underscores
if (parts.length == 1) {
if (k == 'or' || k == 'and') {
// if key is the keyword `and` or `or`, recursively parse the value,
// with according logical operation
builder = builder[methodMap[op]](function () {
parseConditions(knex, this, v, k);
});
} else if (k == 'exists' || k == 'not_exists') {
// handle EXISTS queries, recursively parse them
(0, _forIn["default"])(v, function (value, key) {
builder = builder[methodMap[k][op]](function () {
existsQuery.call(this, knex, key, value);
});
});
} else {
// for simple 'column equals to value' scenario, simply add a raw preparation
var keyBinding = '??';
var valueBinding = '?';
var bindings = [k, v];
if ((0, _isString["default"])(k) && k.indexOf('->') != -1) {
// user want to query with json or jsonb column attributes if key is like 'jsonColumn->someAttr'
var colChain = k.split('->');
keyBinding = (0, _map["default"])(colChain, function (col, index) {
if (index == 0) {
return "??";
}
return "?";
}).join('->').replace(/->\?$/, '->>?'); // it'll be like '??->?->?->>?'
bindings = colChain.concat(v); // bindings is prepanded with json attribute names, like ['jsonCol', 'firstLayerAttr', 'secondLayerAttr', 'value']
}
if ((0, _isString["default"])(v)) {
var words = v.split('.');
var reg = /^([A-Za-z]|[0-9]|_|\$)+$/;
if (words.length == 2 && words[0].match(reg) && words[1].match(reg)) {
// value is an identifier, like 'table_name1.columnName2'
valueBinding = '??';
}
}
var preparation = knex.raw("".concat(keyBinding, " = ").concat(valueBinding), bindings);
builder = builder[methodMap.where[op]](preparation);
}
} else if (parts.length == 2) {
// if column name is followed by suffix,
// call the suffix callback and handle the query
var col = parts[0];
var suffix = parts[1];
if (!(0, _has["default"])(whereSuffixes, suffix)) {
throw _errors["default"].FnErrSuffixNotImplemented(suffix);
}
builder = whereSuffixes[suffix](knex, builder, col, v, op);
}
});
});
return builder;
} // handle JOIN operation, if there's a subquery,
// recursively parse it
function _join(builder, method, value) {
if (!(0, _isPlainObject["default"])(value)) {
throw _errors["default"].ErrJoinShouldBeJSONObject;
}
(0, _forEach["default"])(value, function (v, k) {
if ((0, _has["default"])(v, 'subquery')) {
builder = method.call(builder, function () {
this.from(k);
builderQuery(this, v.subquery).as(v.as);
}, v.on);
} else {
builder = method.call(builder, k, v);
}
});
return builder;
} // j2s provided keywords that maps to SQL operations
var keywords = {
'where': function where(knex, builder, value, key) {
if (key == 'or') {
return parseConditions(knex, builder, value, 'or');
}
return parseConditions(knex, builder, value, 'and');
},
'join': function join(knex, builder, value, key) {
return _join(builder, builder.join, value);
},
'inner_join': function inner_join(knex, builder, value, key) {
return _join(builder, builder.innerJoin, value);
},
'left_join': function left_join(knex, builder, value, key) {
return _join(builder, builder.leftJoin, value);
},
'left_outer_join': function left_outer_join(knex, builder, value, key) {
return _join(builder, builder.leftOuterJoin, value);
},
'right_join': function right_join(knex, builder, value, key) {
return _join(builder, builder.rightJoin, value);
},
'right_outer_join': function right_outer_join(knex, builder, value, key) {
return _join(builder, builder.rightOuterJoin, value);
},
'full_outer_join': function full_outer_join(knex, builder, value, key) {
return _join(builder, builder.fullOuterJoin, value);
},
'cross_join': function cross_join(knex, builder, value, key) {
return builder.crossJoin(value);
},
'union': function union(knex, builder, value, key) {
if (!(0, _isArray["default"])(value)) {
value = [value];
}
return builder.union((0, _map["default"])(value, function (clause) {
return function () {
builderQuery(knex, this, clause);
};
}), true);
},
'union_all': function union_all(knex, builder, value, key) {
return builder.unionAll(function () {
builderQuery(knex, this, value);
}, true);
},
'select': function select(knex, builder, value, key) {
return builder.select.apply(builder, value);
},
'from': function from(knex, builder, value, key) {
if ((0, _isPlainObject["default"])(value)) {
return builder.from(builderQuery(knex, knex.queryBuilder(), value));
}
return builder.from(value);
},
'limit': function limit(knex, builder, value, key) {
return builder.limit(value);
},
'offset': function offset(knex, builder, value, key) {
return builder.offset(value);
},
'with': function _with(knex, builder, value, key) {
if (!(0, _isArray["default"])(value)) {
value = [value];
}
(0, _each["default"])(value, function (elem) {
(0, _each["default"])(elem, function (clause, key) {
if ((0, _isPlainObject["default"])(clause)) {
return builder["with"](key, function () {
builderQuery(knex, this, clause);
});
}
return builder["with"](key, clause);
});
});
return builder;
},
'as': function as(knex, builder, value, key) {
return builder.as(value);
},
'group_by': function group_by(knex, builder, value, key) {
return builder.groupBy(value);
},
'order_by': function order_by(knex, builder, value, key) {
if (!(0, _isArray["default"])(value)) {
throw _errors["default"].ErrOrderByShouldBeList;
} // multiple order by
if ((0, _every["default"])(value, function (elem) {
return (0, _isArray["default"])(elem) && elem.length <= 2;
})) {
(0, _each["default"])(value, function (elem) {
builder.orderBy.apply(builder, elem);
});
return builder;
}
if (value.length > 2) {
throw _errors["default"].ErrOrderByLengthShouldBeTwo;
}
return builder.orderBy.apply(builder, value);
},
'count': function count(knex, builder, value, key) {
if ((0, _isArray["default"])(value)) {
(0, _each["default"])(value, function (col) {
builder = builder.count(col);
});
} else {
builder = builder.count(value);
}
return builder;
},
'min': function min(knex, builder, value, key) {
return builder.min(value);
},
'max': function max(knex, builder, value, key) {
return builder.max(value);
},
'avg': function avg(knex, builder, value, key) {
return builder.avg(value);
},
'sum': function sum(knex, builder, value, key) {
return builder.sum(value);
},
'populate': function populate(knex, builder, value, key) {
// noop
return builder;
},
'add_attr': function add_attr(knex, builder, value, key) {
// noop
return builder;
},
'add_clause': function add_clause(knex, builder, value, key) {
// noop
return builder;
}
}; // accepts a knex query builder, parse the query clauses and chain the methods,
// return the builder
function builderQuery(knex, builder, clauses) {
(0, _forIn["default"])(clauses, function (value, key) {
if (!(0, _has["default"])(keywords, key)) {
throw _errors["default"].FnErrKeywordNotImplemented(key);
}
builder = keywords[key](knex, builder, value, key);
});
_logging.logger.debug("builder query statement: ".concat(builder.toString()));
return builder;
} // accepts a bookshelf model, parse the query clauses and chain the methods,
// return a bookshelf collection
function query(bookshelf, model, clauses) {
var collection = bookshelf.Collection.extend({
model: model
});
var m = collection.query(function (builder) {
builder = builderQuery(bookshelf.knex, builder, clauses);
_logging.logger.verbose("query statement: ".concat(builder.toString()));
});
return m;
} // check access control rules, return a Promise that resolves to true or false
function check(_x, _x2, _x3, _x4, _x5) {
return _check.apply(this, arguments);
}
function _check() {
_check = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(ctx, identityCB, adminCB, instances, rule) {
var identity, isAdmin, i, instance, key;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (identityCB) {
_context.next = 2;
break;
}
return _context.abrupt("return", true);
case 2:
if (!(rule == ALLOW)) {
_context.next = 4;
break;
}
return _context.abrupt("return", true);
case 4:
_context.next = 6;
return identityCB(ctx);
case 6:
identity = _context.sent;
_context.next = 9;
return adminCB(identity);
case 9:
isAdmin = _context.sent;
if (!isAdmin) {
_context.next = 12;
break;
}
return _context.abrupt("return", true);
case 12:
if (!(rule == DENY)) {
_context.next = 14;
break;
}
return _context.abrupt("return", false);
case 14:
if (!(0, _isArray["default"])(instances)) {
instances = instances.toArray();
} // TODO: run checks in parallel
i = 0;
case 16:
if (!(i < instances.length)) {
_context.next = 36;
break;
}
instance = instances[i];
if (!(0, _isPlainObject["default"])(rule)) {
_context.next = 28;
break;
}
_context.t0 = regeneratorRuntime.keys(rule);
case 20:
if ((_context.t1 = _context.t0()).done) {
_context.next = 26;
break;
}
key = _context.t1.value;
if (!(identity[key] != instance.get(rule[key]))) {
_context.next = 24;
break;
}
return _context.abrupt("return", false);
case 24:
_context.next = 20;
break;
case 26:
_context.next = 33;
break;
case 28:
if (!(0, _isFunction["default"])(rule)) {
_context.next = 32;
break;
}
return _context.abrupt("return", rule(identity, instance, ctx));
case 32:
throw _errors["default"].FnErrUnknowRuleType(rule);
case 33:
i++;
_context.next = 16;
break;
case 36:
return _context.abrupt("return", true);
case 37:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _check.apply(this, arguments);
}
module.exports = {
builderQuery: builderQuery,
query: query,
check: check,
ALLOW: ALLOW,
DENY: DENY
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb3JlLmpzIl0sIm5hbWVzIjpbIkFMTE9XIiwiREVOWSIsIm1ldGhvZE1hcCIsImV4aXN0cyIsImFuZCIsIm9yIiwibm90X2V4aXN0cyIsIndoZXJlIiwid2hlcmVfbm90IiwiYmV0d2VlbiIsIm5vdF9iZXR3ZWVuIiwibm90X2luIiwid2hlcmVfbnVsbCIsIndoZXJlX25vdF9udWxsIiwiYWRkTGlrZUNsYXVzZSIsImtuZXgiLCJidWlsZGVyIiwiY29sIiwidmFsdWUiLCJsaWtlT3AiLCJsb2dpY09wIiwiY29uY2F0IiwicWIiLCJzdHIiLCJwcmVwYXJhdGlvbiIsImluZGV4T2YiLCJvcldoZXJlIiwicmF3IiwiZXJyb3JzIiwiRXJyTGlrZVNob3VsZEJlU3RyaW5nT3JMaXN0Iiwid2hlcmVTdWZmaXhlcyIsIm9wIiwiRXJyQmV0d2VlblN1ZmZpeFZhbHVlU2hvdWxkQmVMaXN0IiwibGVuZ3RoIiwiRXJyQmV0d2VlblN1ZmZpeFZhbHVlU2hvdWxkQmVMZW5ndGhUd28iLCJFcnJOb3RCZXR3ZWVuU3VmZml4U2hvdWxkQmVMaXN0IiwiRXJyTm90QmV0d2VlblN1ZmZpeFNob3VsZEJlTGVuZ3RoVHdvIiwiRXJySW5TdWZmaXhTaG91bGRCZUxpc3QiLCJlcnJvcyIsIkVyck5vdEluU3VmZml4U2hvdWxkQmVMaXN0IiwiRXJyTnVsbFN1ZmZpeFNob3VsZEJlQm9vbGVhbiIsImV4aXN0c1F1ZXJ5IiwidGFibGUiLCJmcm9tIiwic2VsZWN0IiwicGFyc2VDb25kaXRpb25zIiwiYnVpbGRlclF1ZXJ5IiwiY29uZHMiLCJjb25kIiwidiIsImsiLCJwYXJ0cyIsInNwbGl0Iiwia2V5IiwiY2FsbCIsImtleUJpbmRpbmciLCJ2YWx1ZUJpbmRpbmciLCJiaW5kaW5ncyIsImNvbENoYWluIiwiaW5kZXgiLCJqb2luIiwicmVwbGFjZSIsIndvcmRzIiwicmVnIiwibWF0Y2giLCJzdWZmaXgiLCJGbkVyclN1ZmZpeE5vdEltcGxlbWVudGVkIiwibWV0aG9kIiwiRXJySm9pblNob3VsZEJlSlNPTk9iamVjdCIsInN1YnF1ZXJ5IiwiYXMiLCJvbiIsImtleXdvcmRzIiwiaW5uZXJKb2luIiwibGVmdEpvaW4iLCJsZWZ0T3V0ZXJKb2luIiwicmlnaHRKb2luIiwicmlnaHRPdXRlckpvaW4iLCJmdWxsT3V0ZXJKb2luIiwiY3Jvc3NKb2luIiwidW5pb24iLCJjbGF1c2UiLCJ1bmlvbkFsbCIsImFwcGx5IiwicXVlcnlCdWlsZGVyIiwibGltaXQiLCJvZmZzZXQiLCJlbGVtIiwiZ3JvdXBCeSIsIkVyck9yZGVyQnlTaG91bGRCZUxpc3QiLCJvcmRlckJ5IiwiRXJyT3JkZXJCeUxlbmd0aFNob3VsZEJlVHdvIiwiY291bnQiLCJtaW4iLCJtYXgiLCJhdmciLCJzdW0iLCJjbGF1c2VzIiwiRm5FcnJLZXl3b3JkTm90SW1wbGVtZW50ZWQiLCJsb2dnZXIiLCJkZWJ1ZyIsInRvU3RyaW5nIiwicXVlcnkiLCJib29rc2hlbGYiLCJtb2RlbCIsImNvbGxlY3Rpb24iLCJDb2xsZWN0aW9uIiwiZXh0ZW5kIiwibSIsInZlcmJvc2UiLCJjaGVjayIsImN0eCIsImlkZW50aXR5Q0IiLCJhZG1pbkNCIiwiaW5zdGFuY2VzIiwicnVsZSIsImlkZW50aXR5IiwiaXNBZG1pbiIsInRvQXJyYXkiLCJpIiwiaW5zdGFuY2UiLCJnZXQiLCJGbkVyclVua25vd1J1bGVUeXBlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRUE7QUFDQSxJQUFNQSxLQUFLLEdBQUcsT0FBZDtBQUNBLElBQU1DLElBQUksR0FBRyxNQUFiLEMsQ0FFQTtBQUNBO0FBQ0E7O0FBQ0EsSUFBTUMsU0FBUyxHQUFHO0FBQ2RDLEVBQUFBLE1BQU0sRUFBRTtBQUNKQyxJQUFBQSxHQUFHLEVBQUUsYUFERDtBQUVKQyxJQUFBQSxFQUFF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QlAsSUFBM0IsQ0E5QmxCOztBQUFBO0FBbUIwQ0ksWUFBQUEsQ0FBQyxFQW5CM0M7QUFBQTtBQUFBOztBQUFBO0FBQUEsNkNBaUNXLElBakNYOztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEc7Ozs7QUFvQ0FJLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNiOUUsRUFBQUEsWUFBWSxFQUFFQSxZQUREO0FBRWJ3RCxFQUFBQSxLQUFLLEVBQUVBLEtBRk07QUFHYlEsRUFBQUEsS0FBSyxFQUFFQSxLQUhNO0FBSWI5RyxFQUFBQSxLQUFLLEVBQUVBLEtBSk07QUFLYkMsRUFBQUEsSUFBSSxFQUFFQTtBQUxPLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgUHJvbWlzZSBmcm9tICdibHVlYmlyZCc7XG5pbXBvcnQgaXNTdHJpbmcgZnJvbSAnbG9kYXNoL2lzU3RyaW5nJztcbmltcG9ydCBpc0FycmF5IGZyb20gJ2xvZGFzaC9pc0FycmF5JztcbmltcG9ydCBpc1BsYWluT2JqZWN0IGZyb20gJ2xvZGFzaC9pc1BsYWluT2JqZWN0JztcbmltcG9ydCBpc0Jvb2xlYW4gZnJvbSAnbG9kYXNoL2lzQm9vbGVhbic7XG5pbXBvcnQgaXNGdW5jdGlvbiBmcm9tICdsb2Rhc2gvaXNGdW5jdGlvbic7XG5pbXBvcnQgZm9ySW4gZnJvbSAnbG9kYXNoL2ZvckluJztcbmltcG9ydCBmb3JFYWNoIGZyb20gJ2xvZGFzaC9mb3JFYWNoJztcbmltcG9ydCBoYXMgZnJvbSAnbG9kYXNoL2hhcyc7XG5pbXBvcnQgZWFjaCBmcm9tICdsb2Rhc2gvZWFjaCc7XG5pbXBvcnQgZXZlcnkgZnJvbSAnbG9kYXNoL2V2ZXJ5JztcbmltcG9ydCBtYXAgZnJvbSAnbG9kYXNoL21hcCc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dpbmcnO1xuaW1wb3J0IGVycm9ycyBmcm9tICcuL2Vycm9ycyc7XG5cbi8vIENvbnN0YW50cyB0byBkZW5vdGUgYWNjZXNzIGNvbnRyb2wgcnVsZXNcbmNvbnN0IEFMTE9XID0gJ2FsbG93JztcbmNvbnN0IERFTlkgPSAnZGVueSc7XG5cbi8vIEZvciBkaWZmZXJlbnQga2V5d29yZHMgdGhhdCB3ZSBkZWZpbmVkIHdpdGggYGFuZGAgb3IgYG9yYCBvcGVyYXRpb25zLFxuLy8gd2Ugc2hvdWxkIHVzZSBkaWZmZXJlbnQgYm9va3NoZWxmIG1vZGVsIG1ldGhvZHMsXG4vLyB0aGlzIG1hcHBpbmdzIHByb3ZpZGVzIHNpbXBsZXIgd2F5IHRvIGRlY2lkZSB3aGF0IG1ldGhvZCBuYW1lIHRvIHVzZS5cbmNvbnN0IG1ldGhvZE1hcCA9IHtcbiAgICBleGlzdHM6IHtcbiAgICAgICAgYW5kOiAnd2hlcmVFeGlzdHMnLFxuICAgICAgICBvcjogJ29yV2hlcmVFeGlzdHMnXG4gICAgfSxcbiAgICBub3RfZXhpc3RzOiB7XG4gICAgICAgIGFuZDogJ3doZXJlTm90RXhpc3RzJyxcbiAgICAgICAgb3I6ICdvcldoZXJlTm90RXhpc3RzJ1xuICAgIH0sXG4gICAgd2hlcmU6IHtcbiAgICAgICAgYW5kOiAnd2hlcmUnLFxuICAgICAgICBvcjogJ29yV2hlcmUnXG4gICAgfSxcbiAgICB3aGVyZV9ub3Q6IHtcbiAgICAgICAgYW5kOiAnd2hlcmVOb3QnLFxuICAgICAgICBvcjogJ29yV2hlcmVOb3QnXG4gICAgfSxcbiAgICBiZXR3ZWVuOiB7XG4gICAgICAgIGFuZDogJ3doZXJlQmV0d2VlbicsXG4gICAgICAgIG9yOiAnb3JXaGVyZUJldHdlZW4nXG4gICAgfSxcbiAgICBub3RfYmV0d2Vlbjoge1xuICAgICAgICBhbmQ6ICd3aGVyZU5vdEJldHdlZW4nLFxuICAgICAgICBvcjogJ29yV2hlcmVOb3RCZXR3ZWVuJ1xuICAgIH0sXG4gICAgaW46IHtcbiAgICAgICAgYW5kOiAnd2hlcmVJbicsXG4gICAgICAgIG9yOiAnb3JXaGVyZUluJ1xuICAgIH0sXG4gICAgbm90X2luOiB7XG4gICAgICAgIGFuZDogJ3doZXJlTm90SW4nLFxuICAgICAgICBvcjogJ29yV2hlcmVOb3RJbidcbiAgICB9LFxuICAgIHdoZXJlX251bGw6IHtcbiAgICAgICAgYW5kOiAnd2hlcmVOdWxsJyxcbiAgICAgICAgb3I6ICdvcldoZXJlTnVsbCdcbiAgICB9LFxuICAgIHdoZXJlX25vdF9udWxsOiB7XG4gICAgICAgIGFuZDogJ3doZXJlTm90TnVsbCcsXG4gICAgICAgIG9yOiAnb3JXaGVyZU5vdE51bGwnXG4gICAgfSxcbiAgICBhbmQ6ICd3aGVyZScsIC8vIGZvciB0aGUgYGFuZGAga2V5d29yZCwgY29uZGl0aW9ucyBzaG91bGQgYmUgQU5EZWQgdG9nZXRoZXJcbiAgICBvcjogJ29yV2hlcmUnIC8vIGZvciB0aGUgYG9yYCBrZXl3b3JkLCBjb25kaXRpb25zIHNob3VsZCBiZSBPUmVkIHRvZ2V0aGVyXG59XG5cbi8vIFRoZXJlIGFyZSBtYW55IHN0cmluZyBtYXRjaGluZyBvcGVyYXRpb25zIGluIFBvc3RncmVTUUwsIGhlcmUgd2UgY2hhaW4gdGhlIGJvb2tzaGVsZiBpbnN0YW5jZVxuLy8gd2l0aCBsaWtlIG9wZXJhdGlvbnMgYWNjb3JkaW5nIHRvIHRoZSBjb2x1bW4sIHZhbHVlLCBsaWtlIG9wZXJhdGlvbnMgYW5kIGxvZ2ljYWwgb3BlcmF0aW9ucy5cbmxldCBhZGRMaWtlQ2xhdXNlID0gZnVuY3Rpb24gKGtuZXgsIGJ1aWxkZXIsIGNvbCwgdmFsdWUsIGxpa2VPcCwgbG9naWNPcCkge1xuICAgIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSBbXS5jb25jYXQodmFsdWUpO1xuICAgIH1cbiAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgYnVpbGRlciA9IGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlW2xvZ2ljT3BdXShmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGxldCBxYiA9IHRoaXM7XG4gICAgICAgICAgICBlYWNoKHZhbHVlLCBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgICAgICBsZXQgcHJlcGFyYXRpb24gPSBgJHtjb2x9ICR7bGlrZU9wfSA/YDtcbiAgICAgICAgICAgICAgICBpZiAobGlrZU9wLmluZGV4T2YoJ2xpa2UnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyID0gYCUlJHtzdHJ9JSVgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBxYi5vcldoZXJlKGtuZXgucmF3KHByZXBhcmF0aW9uLCBbc3RyXSkpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZXJyb3JzLkVyckxpa2VTaG91bGRCZVN0cmluZ09yTGlzdDtcbiAgICB9XG59XG5cbi8vIGoycyBwcm92aWRlcyBkaWZmZXJlbnQgc3VmZml4ZXMgdGhhdCBjb3VsZCBiZSBhcHBlbmRlZCB0byBjb2x1bW5zLFxuLy8gdG8gc3BlY2lmeSB3aGF0IGtpbmQgb2YgY29tcGFyaXNvbiBvcGVyYXRvcnMgdG8gdXNlLlxuY29uc3Qgd2hlcmVTdWZmaXhlcyA9IHtcbiAgICAnZ3QnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlW29wXV0oY29sLCAnPicsIHZhbHVlKTtcbiAgICB9LFxuICAgICdndGUnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlW29wXV0oY29sLCAnPj0nLCB2YWx1ZSk7XG4gICAgfSxcbiAgICAnbHQnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlW29wXV0oY29sLCAnPCcsIHZhbHVlKTtcbiAgICB9LFxuICAgICdsdGUnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlW29wXV0oY29sLCAnPD0nLCB2YWx1ZSk7XG4gICAgfSxcbiAgICAnbmUnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1aWxkZXJbbWV0aG9kTWFwLndoZXJlX25vdFtvcF1dKGNvbCwgdmFsdWUpO1xuICAgIH0sXG4gICAgJ2xpa2UnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGFkZExpa2VDbGF1c2Uoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgJ2xpa2UnLCBvcCk7XG4gICAgfSxcbiAgICAnbm90X2xpa2UnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGFkZExpa2VDbGF1c2Uoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgJ25vdCBsaWtlJywgb3ApO1xuICAgIH0sXG4gICAgJ2lsaWtlJzogKGtuZXgsIGJ1aWxkZXIsIGNvbCwgdmFsdWUsIG9wKSA9PiB7XG4gICAgICAgIHJldHVybiBhZGRMaWtlQ2xhdXNlKGtuZXgsIGJ1aWxkZXIsIGNvbCwgdmFsdWUsICdpbGlrZScsIG9wKTtcbiAgICB9LFxuICAgICdub3RfaWxpa2UnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGFkZExpa2VDbGF1c2Uoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgJ25vdCBpbGlrZScsIG9wKTtcbiAgICB9LFxuICAgICdyZWdfbGlrZSc6IChrbmV4LCBidWlsZGVyLCBjb2wsIHZhbHVlLCBvcCkgPT4ge1xuICAgICAgICByZXR1cm4gYWRkTGlrZUNsYXVzZShrbmV4LCBidWlsZGVyLCBjb2wsIHZhbHVlLCAnficsIG9wKTtcbiAgICB9LFxuICAgICdyZWdfbm90X2xpa2UnOiAoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgb3ApID0+IHtcbiAgICAgICAgcmV0dXJuIGFkZExpa2VDbGF1c2Uoa25leCwgYnVpbGRlciwgY29sLCB2YWx1ZSwgJyF+Jywgb3ApO1xuICAgIH0sXG4gICAgJ3JlZ19pbGlrZSc6IChrbmV4LCBidWlsZGVyLCBjb2wsIHZhbHVlLCBvcCkgPT4ge1xuICAgICAgICByZXR1cm4gYWRkTGlrZUNsYXVzZShrbmV4LCBidWlsZGVyLCBjb2wsIHZhbHVlLCAnfionLCBvcCk7XG4gICAgfSxcbiAgICAncmVnX25vdF9pbGlrZSc6IChrbmV4LCBidWlsZGVyLCBjb2wsIHZhbHVlLCBvcCkgPT4ge1xuICAgICAgICByZXR1cm4gYWRkTGlrZUNsYXVzZShrbmV4LCBidWlsZGVyLCBjb2