objection
Version:
An SQL-friendly ORM for Node.js
155 lines (130 loc) • 19.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _jsonFieldExpressionParser = require('../../parsers/jsonFieldExpressionParser');
var _jsonFieldExpressionParser2 = _interopRequireDefault(_jsonFieldExpressionParser);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @typedef {String} FieldExpression
*
* Field expressions allow one to refer to separate JSONB fields inside columns.
*
* Syntax: <column reference>[:<json field reference>]
*
* e.g. `Person.jsonColumnName:details.names[1]` would refer to value `'Second'`
* in column `Person.jsonColumnName` which has
* `{ details: { names: ['First', 'Second', 'Last'] } }` object stored in it.
*
* First part `<column reference>` is compatible with column references used in
* knex e.g. `MyFancyTable.tributeToThBestColumnNameEver`.
*
* Second part describes a path to an attribute inside the referred column.
* It is optional and it always starts with colon which follows directly with
* first path element. e.g. `Table.jsonObjectColumnName:jsonFieldName` or
* `Table.jsonArrayColumn:[321]`.
*
* Syntax supports `[<key or index>]` and `.<key or index>` flavors of reference
* to json keys / array indexes:
*
* e.g. both `Table.myColumn:[1][3]` and `Table.myColumn:1.3` would access correctly
* both of the following objects `[null, [null,null,null, "I was accessed"]]` and
* `{ "1": { "3" : "I was accessed" } }`
*
* Caveats when using special characters in keys:
*
* 1. `objectColumn.key` This is the most common syntax, good if you are
* not using dots or square brackets `[]` in your json object key name.
* 2. Keys containing dots `objectColumn:[keywith.dots]` Column `{ "keywith.dots" : "I was referred" }`
* 3. Keys containing square brackets `column['[]']` `{ "[]" : "This is getting ridiculous..." }`
* 4. Keys containing square brackets and quotes
* `objectColumn:['Double."Quote".[]']` and `objectColumn:["Sinlge.'Quote'.[]"]`
* Column `{ "Double.\"Quote\".[]" : "I was referred", "Single.'Quote'.[]" : "Mee too!" }`
* 99. Keys containing dots, square brackets, single quotes and double quotes in one json key is
* not currently supported
*/
exports.default = {
parseFieldExpression: parseFieldExpression,
whereJsonbRefOnLeftJsonbValOrRefOnRight: whereJsonbRefOnLeftJsonbValOrRefOnRight,
whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams: whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams,
whereJsonFieldRightStringArrayOnLeftQuery: whereJsonFieldRightStringArrayOnLeftQuery,
whereJsonFieldQuery: whereJsonFieldQuery
};
function parseFieldExpression(expression, extractAsText) {
var parsed = _jsonFieldExpressionParser2.default.parse(expression);
var jsonRefs = (0, _lodash2.default)(parsed.access).map('ref').value().join(",");
var extractor = extractAsText ? '#>>' : '#>';
var middleQuotedColumnName = parsed.columnName.split('.').join('"."');
return '"' + middleQuotedColumnName + '"' + extractor + '\'{' + jsonRefs + '}\'';
}
function whereJsonbRefOnLeftJsonbValOrRefOnRight(builder, fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix) {
var queryParams = whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams(fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix);
return builder.whereRaw.apply(builder, queryParams);
}
function whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams(fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix) {
var fieldReference = parseFieldExpression(fieldExpression);
if (_lodash2.default.isString(jsonObjectOrFieldExpression)) {
var rightHandReference = parseFieldExpression(jsonObjectOrFieldExpression);
var refRefQuery = ["(", fieldReference, ")::jsonb", operator, "(", rightHandReference, ")::jsonb"];
if (queryPrefix) {
refRefQuery.unshift(queryPrefix);
}
return [refRefQuery.join(" ")];
} else if (_lodash2.default.isObject(jsonObjectOrFieldExpression)) {
var refValQuery = ["(", fieldReference, ")::jsonb", operator, "?::jsonb"];
if (queryPrefix) {
refValQuery.unshift(queryPrefix);
}
return [refValQuery.join(" "), (0, _stringify2.default)(jsonObjectOrFieldExpression)];
}
throw new Error("Invalid right hand expression.");
}
function whereJsonFieldRightStringArrayOnLeftQuery(builder, fieldExpression, operator, keys) {
var knex = builder._knex;
var fieldReference = parseFieldExpression(fieldExpression);
keys = _lodash2.default.isArray(keys) ? keys : [keys];
var questionMarksArray = _lodash2.default.map(keys, function (key) {
if (!_lodash2.default.isString(key)) {
throw new Error("All keys to find must be strings.");
}
return "?";
});
var rawSqlTemplateString = "array[" + questionMarksArray.join(",") + "]";
var rightHandExpression = knex.raw(rawSqlTemplateString, keys);
return fieldReference + ' ' + operator.replace('?', '\\?') + ' ' + rightHandExpression;
}
function whereJsonFieldQuery(knex, fieldExpression, operator, value) {
var fieldReference = parseFieldExpression(fieldExpression, true);
var normalizedOperator = normalizeOperator(knex, operator);
// json type comparison takes json type in string format
var cast = void 0;
var escapedValue = knex.raw(" ?", [value]);
if (_lodash2.default.isNumber(value)) {
cast = "::NUMERIC";
} else if (_lodash2.default.isBoolean(value)) {
cast = "::BOOLEAN";
} else if (_lodash2.default.isString(value)) {
cast = "::TEXT";
} else if (_lodash2.default.isNull(value)) {
cast = "::TEXT";
escapedValue = 'NULL';
} else {
throw new Error("Value must be string, number, boolean or null.");
}
return '(' + fieldReference + ')' + cast + ' ' + normalizedOperator + ' ' + escapedValue;
}
function normalizeOperator(knex, operator) {
var trimmedLowerCase = operator.trim().toLowerCase();
switch (trimmedLowerCase) {
case "is":
case "is not":
return trimmedLowerCase;
default:
return knex.client.formatter().operator(operator);
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBvc3RncmVzSnNvbkFwaS5qcyJdLCJuYW1lcyI6WyJwYXJzZUZpZWxkRXhwcmVzc2lvbiIsIndoZXJlSnNvbmJSZWZPbkxlZnRKc29uYlZhbE9yUmVmT25SaWdodCIsIndoZXJlSnNvbmJSZWZPbkxlZnRKc29uYlZhbE9yUmVmT25SaWdodFJhd1F1ZXJ5UGFyYW1zIiwid2hlcmVKc29uRmllbGRSaWdodFN0cmluZ0FycmF5T25MZWZ0UXVlcnkiLCJ3aGVyZUpzb25GaWVsZFF1ZXJ5IiwiZXhwcmVzc2lvbiIsImV4dHJhY3RBc1RleHQiLCJwYXJzZWQiLCJwYXJzZSIsImpzb25SZWZzIiwiYWNjZXNzIiwibWFwIiwidmFsdWUiLCJqb2luIiwiZXh0cmFjdG9yIiwibWlkZGxlUXVvdGVkQ29sdW1uTmFtZSIsImNvbHVtbk5hbWUiLCJzcGxpdCIsImJ1aWxkZXIiLCJmaWVsZEV4cHJlc3Npb24iLCJvcGVyYXRvciIsImpzb25PYmplY3RPckZpZWxkRXhwcmVzc2lvbiIsInF1ZXJ5UHJlZml4IiwicXVlcnlQYXJhbXMiLCJ3aGVyZVJhdyIsImFwcGx5IiwiZmllbGRSZWZlcmVuY2UiLCJpc1N0cmluZyIsInJpZ2h0SGFuZFJlZmVyZW5jZSIsInJlZlJlZlF1ZXJ5IiwidW5zaGlmdCIsImlzT2JqZWN0IiwicmVmVmFsUXVlcnkiLCJFcnJvciIsImtleXMiLCJrbmV4IiwiX2tuZXgiLCJpc0FycmF5IiwicXVlc3Rpb25NYXJrc0FycmF5Iiwia2V5IiwicmF3U3FsVGVtcGxhdGVTdHJpbmciLCJyaWdodEhhbmRFeHByZXNzaW9uIiwicmF3IiwicmVwbGFjZSIsIm5vcm1hbGl6ZWRPcGVyYXRvciIsIm5vcm1hbGl6ZU9wZXJhdG9yIiwiY2FzdCIsImVzY2FwZWRWYWx1ZSIsImlzTnVtYmVyIiwiaXNCb29sZWFuIiwiaXNOdWxsIiwidHJpbW1lZExvd2VyQ2FzZSIsInRyaW0iLCJ0b0xvd2VyQ2FzZSIsImNsaWVudCIsImZvcm1hdHRlciJdLCJtYXBwaW5ncyI6Ijs7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QUFDRCxHQUhNLE1BR0E7QUFDTCxVQUFNLElBQUlkLEtBQUosQ0FBVSxnREFBVixDQUFOO0FBQ0Q7O0FBRUQsZUFBV1AsY0FBWCxTQUE2Qm9CLElBQTdCLFNBQXFDRixrQkFBckMsU0FBMkRHLFlBQTNEO0FBQ0Q7O0FBRUQsU0FBU0YsaUJBQVQsQ0FBMkJWLElBQTNCLEVBQWlDZixRQUFqQyxFQUEyQztBQUN6QyxNQUFJK0IsbUJBQW1CL0IsU0FBU2dDLElBQVQsR0FBZ0JDLFdBQWhCLEVBQXZCOztBQUVBLFVBQVFGLGdCQUFSO0FBQ0UsU0FBSyxJQUFMO0FBQ0EsU0FBSyxRQUFMO0FBQ0UsYUFBT0EsZ0JBQVA7QUFDRjtBQUNFLGFBQU9oQixLQUFLbUIsTUFBTCxDQUFZQyxTQUFaLEdBQXdCbkMsUUFBeEIsQ0FBaUNBLFFBQWpDLENBQVA7QUFMSjtBQU9EIiwiZmlsZSI6InBvc3RncmVzSnNvbkFwaS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQganNvbkZpZWxkRXhwcmVzc2lvblBhcnNlciBmcm9tICcuLi8uLi9wYXJzZXJzL2pzb25GaWVsZEV4cHJlc3Npb25QYXJzZXInO1xuXG4vKipcbiAqIEB0eXBlZGVmIHtTdHJpbmd9IEZpZWxkRXhwcmVzc2lvblxuICpcbiAqIEZpZWxkIGV4cHJlc3Npb25zIGFsbG93IG9uZSB0byByZWZlciB0byBzZXBhcmF0ZSBKU09OQiBmaWVsZHMgaW5zaWRlIGNvbHVtbnMuXG4gKlxuICogU3ludGF4OiA8Y29sdW1uIHJlZmVyZW5jZT5bOjxqc29uIGZpZWxkIHJlZmVyZW5jZT5dXG4gKlxuICogZS5nLiBgUGVyc29uLmpzb25Db2x1bW5OYW1lOmRldGFpbHMubmFtZXNbMV1gIHdvdWxkIHJlZmVyIHRvIHZhbHVlIGAnU2Vjb25kJ2BcbiAqIGluIGNvbHVtbiBgUGVyc29uLmpzb25Db2x1bW5OYW1lYCB3aGljaCBoYXNcbiAqIGB7IGRldGFpbHM6IHsgbmFtZXM6IFsnRmlyc3QnLCAnU2Vjb25kJywgJ0xhc3QnXSB9IH1gIG9iamVjdCBzdG9yZWQgaW4gaXQuXG4gKlxuICogRmlyc3QgcGFydCBgPGNvbHVtbiByZWZlcmVuY2U+YCBpcyBjb21wYXRpYmxlIHdpdGggY29sdW1uIHJlZmVyZW5jZXMgdXNlZCBpblxuICoga25leCBlLmcuIGBNeUZhbmN5VGFibGUudHJpYnV0ZVRvVGhCZXN0Q29sdW1uTmFtZUV2ZXJgLlxuICpcbiAqIFNlY29uZCBwYXJ0IGRlc2NyaWJlcyBhIHBhdGggdG8gYW4gYXR0cmlidXRlIGluc2lkZSB0aGUgcmVmZXJyZWQgY29sdW1uLlxuICogSXQgaXMgb3B0aW9uYWwgYW5kIGl0IGFsd2F5cyBzdGFydHMgd2l0aCBjb2xvbiB3aGljaCBmb2xsb3dzIGRpcmVjdGx5IHdpdGhcbiAqIGZpcnN0IHBhdGggZWxlbWVudC4gZS5nLiBgVGFibGUuanNvbk9iamVjdENvbHVtbk5hbWU6anNvbkZpZWxkTmFtZWAgb3JcbiAqIGBUYWJsZS5qc29uQXJyYXlDb2x1bW46WzMyMV1gLlxuICpcbiAqIFN5bnRheCBzdXBwb3J0cyBgWzxrZXkgb3IgaW5kZXg+XWAgYW5kIGAuPGtleSBvciBpbmRleD5gIGZsYXZvcnMgb2YgcmVmZXJlbmNlXG4gKiB0byBqc29uIGtleXMgLyBhcnJheSBpbmRleGVzOlxuICpcbiAqIGUuZy4gYm90aCBgVGFibGUubXlDb2x1bW46WzFdWzNdYCBhbmQgYFRhYmxlLm15Q29sdW1uOjEuM2Agd291bGQgYWNjZXNzIGNvcnJlY3RseVxuICogYm90aCBvZiB0aGUgZm9sbG93aW5nIG9iamVjdHMgYFtudWxsLCBbbnVsbCxudWxsLG51bGwsIFwiSSB3YXMgYWNjZXNzZWRcIl1dYCBhbmRcbiAqIGB7IFwiMVwiOiB7IFwiM1wiIDogXCJJIHdhcyBhY2Nlc3NlZFwiIH0gfWBcbiAqXG4gKiBDYXZlYXRzIHdoZW4gdXNpbmcgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIGtleXM6XG4gKlxuICogMS4gYG9iamVjdENvbHVtbi5rZXlgIFRoaXMgaXMgdGhlIG1vc3QgY29tbW9uIHN5bnRheCwgZ29vZCBpZiB5b3UgYXJlXG4gKiAgICBub3QgdXNpbmcgZG90cyBvciBzcXVhcmUgYnJhY2tldHMgYFtdYCBpbiB5b3VyIGpzb24gb2JqZWN0IGtleSBuYW1lLlxuICogMi4gS2V5cyBjb250YWluaW5nIGRvdHMgYG9iamVjdENvbHVtbjpba2V5d2l0aC5kb3RzXWAgQ29sdW1uIGB7IFwia2V5d2l0aC5kb3RzXCIgOiBcIkkgd2FzIHJlZmVycmVkXCIgfWBcbiAqIDMuIEtleXMgY29udGFpbmluZyBzcXVhcmUgYnJhY2tldHMgYGNvbHVtblsnW10nXWAgYHsgXCJbXVwiIDogXCJUaGlzIGlzIGdldHRpbmcgcmlkaWN1bG91cy4uLlwiIH1gXG4gKiA0LiBLZXlzIGNvbnRhaW5pbmcgc3F1YXJlIGJyYWNrZXRzIGFuZCBxdW90ZXNcbiAqICAgIGBvYmplY3RDb2x1bW46WydEb3VibGUuXCJRdW90ZVwiLltdJ11gIGFuZCBgb2JqZWN0Q29sdW1uOltcIlNpbmxnZS4nUXVvdGUnLltdXCJdYFxuICogICAgQ29sdW1uIGB7IFwiRG91YmxlLlxcXCJRdW90ZVxcXCIuW11cIiA6IFwiSSB3YXMgcmVmZXJyZWRcIiwgIFwiU2luZ2xlLidRdW90ZScuW11cIiA6IFwiTWVlIHRvbyFcIiB9YFxuICogOTkuIEtleXMgY29udGFpbmluZyBkb3RzLCBzcXVhcmUgYnJhY2tldHMsIHNpbmdsZSBxdW90ZXMgYW5kIGRvdWJsZSBxdW90ZXMgaW4gb25lIGpzb24ga2V5IGlzXG4gKiAgICAgbm90IGN1cnJlbnRseSBzdXBwb3J0ZWRcbiAqL1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIHBhcnNlRmllbGRFeHByZXNzaW9uLFxuICB3aGVyZUpzb25iUmVmT25MZWZ0SnNvbmJWYWxPclJlZk9uUmlnaHQsXG4gIHdoZXJlSnNvbmJSZWZPbkxlZnRKc29uYlZhbE9yUmVmT25SaWdodFJhd1F1ZXJ5UGFyYW1zLFxuICB3aGVyZUpzb25GaWVsZFJpZ2h0U3RyaW5nQXJyYXlPbkxlZnRRdWVyeSxcbiAgd2hlcmVKc29uRmllbGRRdWVyeVxufVxuXG5mdW5jdGlvbiBwYXJzZUZpZWxkRXhwcmVzc2lvbihleHByZXNzaW9uLCBleHRyYWN0QXNUZXh0KSB7XG4gIGxldCBwYXJzZWQgPSBqc29uRmllbGRFeHByZXNzaW9uUGFyc2VyLnBhcnNlKGV4cHJlc3Npb24pO1xuICBsZXQganNvblJlZnMgPSBfKHBhcnNlZC5hY2Nlc3MpLm1hcCgncmVmJykudmFsdWUoKS5qb2luKFwiLFwiKTtcbiAgbGV0IGV4dHJhY3RvciA9IGV4dHJhY3RBc1RleHQgPyAnIz4+JyA6ICcjPic7XG4gIGxldCBtaWRkbGVRdW90ZWRDb2x1bW5OYW1lID0gcGFyc2VkLmNvbHVtbk5hbWUuc3BsaXQoJy4nKS5qb2luKCdcIi5cIicpO1xuICByZXR1cm4gYFwiJHttaWRkbGVRdW90ZWRDb2x1bW5OYW1lfVwiJHtleHRyYWN0b3J9J3ske2pzb25SZWZzfX0nYDtcbn1cblxuZnVuY3Rpb24gd2hlcmVKc29uYlJlZk9uTGVmdEpzb25iVmFsT3JSZWZPblJpZ2h0KGJ1aWxkZXIsIGZpZWxkRXhwcmVzc2lvbiwgb3BlcmF0b3IsIGpzb25PYmplY3RPckZpZWxkRXhwcmVzc2lvbiwgcXVlcnlQcmVmaXgpIHtcbiAgbGV0IHF1ZXJ5UGFyYW1zID0gd2hlcmVKc29uYlJlZk9uTGVmdEpzb25iVmFsT3JSZWZPblJpZ2h0UmF3UXVlcnlQYXJhbXMoZmllbGRFeHByZXNzaW9uLCBvcGVyYXRvciwganNvbk9iamVjdE9yRmllbGRFeHByZXNzaW9uLCBxdWVyeVByZWZpeCk7XG4gIHJldHVybiBidWlsZGVyLndoZXJlUmF3LmFwcGx5KGJ1aWxkZXIsIHF1ZXJ5UGFyYW1zKTtcbn1cblxuZnVuY3Rpb24gd2hlcmVKc29uYlJlZk9uTGVmdEpzb25iVmFsT3JSZWZPblJpZ2h0UmF3UXVlcnlQYXJhbXMoZmllbGRFeHByZXNzaW9uLCBvcGVyYXRvciwganNvbk9iamVjdE9yRmllbGRFeHByZXNzaW9uLCBxdWVyeVByZWZpeCkge1xuICBsZXQgZmllbGRSZWZlcmVuY2UgPSBwYXJzZUZpZWxkRXhwcmVzc2lvbihmaWVsZEV4cHJlc3Npb24pO1xuXG4gIGlmIChfLmlzU3RyaW5nKGpzb25PYmplY3RPckZpZWxkRXhwcmVzc2lvbikpIHtcbiAgICBsZXQgcmlnaHRIYW5kUmVmZXJlbmNlID0gcGFyc2VGaWVsZEV4cHJlc3Npb24oanNvbk9iamVjdE9yRmllbGRFeHByZXNzaW9uKTtcbiAgICBsZXQgcmVmUmVmUXVlcnkgPSBbXCIoXCIsIGZpZWxkUmVmZXJlbmNlLCBcIik6Ompzb25iXCIsIG9wZXJhdG9yLCBcIihcIiwgcmlnaHRIYW5kUmVmZXJlbmNlLCBcIik6Ompzb25iXCJdO1xuICAgIGlmIChxdWVyeVByZWZpeCkge1xuICAgICAgcmVmUmVmUXVlcnkudW5zaGlmdChxdWVyeVByZWZpeCk7XG4gICAgfVxuICAgIHJldHVybiBbcmVmUmVmUXVlcnkuam9pbihcIiBcIildO1xuICB9IGVsc2UgaWYgKF8uaXNPYmplY3QoanNvbk9iamVjdE9yRmllbGRFeHByZXNzaW9uKSkge1xuICAgIGxldCByZWZWYWxRdWVyeSA9IFtcIihcIiwgZmllbGRSZWZlcmVuY2UsIFwiKTo6anNvbmJcIiwgb3BlcmF0b3IsIFwiPzo6anNvbmJcIl07XG4gICAgaWYgKHF1ZXJ5UHJlZml4KSB7XG4gICAgICByZWZWYWxRdWVyeS51bnNoaWZ0KHF1ZXJ5UHJlZml4KTtcbiAgICB9XG4gICAgcmV0dXJuIFtyZWZWYWxRdWVyeS5qb2luKFwiIFwiKSwgSlNPTi5zdHJpbmdpZnkoanNvbk9iamVjdE9yRmllbGRFeHByZXNzaW9uKV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHJpZ2h0IGhhbmQgZXhwcmVzc2lvbi5cIik7XG59XG5cbmZ1bmN0aW9uIHdoZXJlSnNvbkZpZWxkUmlnaHRTdHJpbmdBcnJheU9uTGVmdFF1ZXJ5KGJ1aWxkZXIsIGZpZWxkRXhwcmVzc2lvbiwgb3BlcmF0b3IsIGtleXMpIHtcbiAgbGV0IGtuZXggPSBidWlsZGVyLl9rbmV4O1xuICBsZXQgZmllbGRSZWZlcmVuY2UgPSBwYXJzZUZpZWxkRXhwcmVzc2lvbihmaWVsZEV4cHJlc3Npb24pO1xuICBrZXlzID0gXy5pc0FycmF5KGtleXMpID8ga2V5cyA6IFtrZXlzXTtcblxuICBsZXQgcXVlc3Rpb25NYXJrc0FycmF5ID0gXy5tYXAoa2V5cywgZnVuY3Rpb24gKGtleSkge1xuICAgIGlmICghXy5pc1N0cmluZyhrZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBbGwga2V5cyB0byBmaW5kIG11c3QgYmUgc3RyaW5ncy5cIik7XG4gICAgfVxuICAgIHJldHVybiBcIj9cIjtcbiAgfSk7XG5cbiAgbGV0IHJhd1NxbFRlbXBsYXRlU3RyaW5nID0gXCJhcnJheVtcIiArIHF1ZXN0aW9uTWFya3NBcnJheS5qb2luKFwiLFwiKSArIFwiXVwiO1xuICBsZXQgcmlnaHRIYW5kRXhwcmVzc2lvbiA9IGtuZXgucmF3KHJhd1NxbFRlbXBsYXRlU3RyaW5nLCBrZXlzKTtcblxuICByZXR1cm4gYCR7ZmllbGRSZWZlcmVuY2V9ICR7b3BlcmF0b3IucmVwbGFjZSgnPycsICdcXFxcPycpfSAke3JpZ2h0SGFuZEV4cHJlc3Npb259YDtcbn1cblxuZnVuY3Rpb24gd2hlcmVKc29uRmllbGRRdWVyeShrbmV4LCBmaWVsZEV4cHJlc3Npb24sIG9wZXJhdG9yLCB2YWx1ZSkge1xuICBsZXQgZmllbGRSZWZlcmVuY2UgPSBwYXJzZUZpZWxkRXhwcmVzc2lvbihmaWVsZEV4cHJlc3Npb24sIHRydWUpO1xuICBsZXQgbm9ybWFsaXplZE9wZXJhdG9yID0gbm9ybWFsaXplT3BlcmF0b3Ioa25leCwgb3BlcmF0b3IpO1xuXG4gIC8vIGpzb24gdHlwZSBjb21wYXJpc29uIHRha2VzIGpzb24gdHlwZSBpbiBzdHJpbmcgZm9ybWF0XG4gIGxldCBjYXN0O1xuICBsZXQgZXNjYXBlZFZhbHVlID0ga25leC5yYXcoXCIgP1wiLCBbdmFsdWVdKTtcbiAgaWYgKF8uaXNOdW1iZXIodmFsdWUpKSB7XG4gICAgY2FzdCA9IFwiOjpOVU1FUklDXCI7XG4gIH0gZWxzZSBpZiAoXy5pc0Jvb2xlYW4odmFsdWUpKSB7XG4gICAgY2FzdCA9IFwiOjpCT09MRUFOXCI7XG4gIH0gZWxzZSBpZiAoXy5pc1N0cmluZyh2YWx1ZSkpIHtcbiAgICBjYXN0ID0gXCI6OlRFWFRcIjtcbiAgfSBlbHNlIGlmIChfLmlzTnVsbCh2YWx1ZSkpIHtcbiAgICBjYXN0ID0gXCI6OlRFWFRcIjtcbiAgICBlc2NhcGVkVmFsdWUgPSAnTlVMTCc7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVmFsdWUgbXVzdCBiZSBzdHJpbmcsIG51bWJlciwgYm9vbGVhbiBvciBudWxsLlwiKTtcbiAgfVxuXG4gIHJldHVybiBgKCR7ZmllbGRSZWZlcmVuY2V9KSR7Y2FzdH0gJHtub3JtYWxpemVkT3BlcmF0b3J9ICR7ZXNjYXBlZFZhbHVlfWA7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZU9wZXJhdG9yKGtuZXgsIG9wZXJhdG9yKSB7XG4gIGxldCB0cmltbWVkTG93ZXJDYXNlID0gb3BlcmF0b3IudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgc3dpdGNoICh0cmltbWVkTG93ZXJDYXNlKSB7XG4gICAgY2FzZSBcImlzXCI6XG4gICAgY2FzZSBcImlzIG5vdFwiOlxuICAgICAgcmV0dXJuIHRyaW1tZWRMb3dlckNhc2U7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBrbmV4LmNsaWVudC5mb3JtYXR0ZXIoKS5vcGVyYXRvcihvcGVyYXRvcik7XG4gIH1cbn1cbiJdfQ==