UNPKG

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
'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