loopback-softdelete-mixin2
Version:
A mixin to provide soft deletes by adding a deletedAt attribute for loopback Models
176 lines (131 loc) • 17 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends6 = require('babel-runtime/helpers/extends');
var _extends7 = _interopRequireDefault(_extends6);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _debug2 = require('./debug');
var _debug3 = _interopRequireDefault(_debug2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var debug = (0, _debug3.default)();
exports.default = function (Model, _ref) {
var _ref$deletedAt = _ref.deletedAt;
var deletedAt = _ref$deletedAt === undefined ? 'deletedAt' : _ref$deletedAt;
var _ref$scrub = _ref.scrub;
var scrub = _ref$scrub === undefined ? false : _ref$scrub;
debug('SoftDelete mixin for Model %s', Model.modelName);
debug('options', { deletedAt: deletedAt, scrub: scrub });
var properties = Model.definition.properties;
var idName = Model.dataSource.idName(Model.modelName);
var scrubbed = {};
if (scrub !== false) {
var propertiesToScrub = scrub;
if (!Array.isArray(propertiesToScrub)) {
propertiesToScrub = (0, _keys2.default)(properties).filter(function (prop) {
return !properties[prop][idName] && prop !== deletedAt;
});
}
scrubbed = propertiesToScrub.reduce(function (obj, prop) {
return (0, _extends7.default)({}, obj, (0, _defineProperty3.default)({}, prop, null));
}, {});
}
Model.defineProperty(deletedAt, { type: Date, required: false });
Model.destroyAll = function softDestroyAll(where, cb) {
return Model.updateAll(where, (0, _extends7.default)({}, scrubbed, (0, _defineProperty3.default)({}, deletedAt, new Date()))).then(function (result) {
return typeof cb === 'function' ? cb(null, result) : result;
}).catch(function (error) {
return typeof cb === 'function' ? cb(error) : _promise2.default.reject(error);
});
};
Model.remove = Model.destroyAll;
Model.deleteAll = Model.destroyAll;
Model.destroyById = function softDestroyById(id, cb) {
return Model.updateAll((0, _defineProperty3.default)({}, idName, id), (0, _extends7.default)({}, scrubbed, (0, _defineProperty3.default)({}, deletedAt, new Date()))).then(function (result) {
return typeof cb === 'function' ? cb(null, result) : result;
}).catch(function (error) {
return typeof cb === 'function' ? cb(error) : _promise2.default.reject(error);
});
};
Model.removeById = Model.destroyById;
Model.deleteById = Model.destroyById;
Model.prototype.destroy = function softDestroy(options, cb) {
var callback = cb === undefined && typeof options === 'function' ? options : cb;
return this.updateAttributes((0, _extends7.default)({}, scrubbed, (0, _defineProperty3.default)({}, deletedAt, new Date()))).then(function (result) {
return typeof cb === 'function' ? callback(null, result) : result;
}).catch(function (error) {
return typeof cb === 'function' ? callback(error) : _promise2.default.reject(error);
});
};
Model.prototype.remove = Model.prototype.destroy;
Model.prototype.delete = Model.prototype.destroy;
// Emulate default scope but with more flexibility.
var queryNonDeleted = (0, _defineProperty3.default)({}, deletedAt, null);
var _findOrCreate = Model.findOrCreate;
Model.findOrCreate = function findOrCreateDeleted() {
var query = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
if (!query.deleted) {
if (!query.where || (0, _keys2.default)(query.where).length === 0) {
query.where = queryNonDeleted;
} else {
query.where = { and: [query.where, queryNonDeleted] };
}
}
for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
rest[_key - 1] = arguments[_key];
}
return _findOrCreate.call.apply(_findOrCreate, [Model, query].concat(rest));
};
var _find = Model.find;
Model.find = function findDeleted() {
var query = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
if (!query.deleted) {
if (!query.where || (0, _keys2.default)(query.where).length === 0) {
query.where = queryNonDeleted;
} else {
query.where = { and: [query.where, queryNonDeleted] };
}
}
for (var _len2 = arguments.length, rest = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
rest[_key2 - 1] = arguments[_key2];
}
return _find.call.apply(_find, [Model, query].concat(rest));
};
var _count = Model.count;
Model.count = function countDeleted() {
var where = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
// Because count only receives a 'where', there's nowhere to ask for the deleted entities.
var whereNotDeleted = void 0;
if (!where || (0, _keys2.default)(where).length === 0) {
whereNotDeleted = queryNonDeleted;
} else {
whereNotDeleted = { and: [where, queryNonDeleted] };
}
for (var _len3 = arguments.length, rest = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
rest[_key3 - 1] = arguments[_key3];
}
return _count.call.apply(_count, [Model, whereNotDeleted].concat(rest));
};
var _update = Model.update;
Model.update = Model.updateAll = function updateDeleted() {
var where = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
// Because update/updateAll only receives a 'where', there's nowhere to ask for the deleted entities.
var whereNotDeleted = void 0;
if (!where || (0, _keys2.default)(where).length === 0) {
whereNotDeleted = queryNonDeleted;
} else {
whereNotDeleted = { and: [where, queryNonDeleted] };
}
for (var _len4 = arguments.length, rest = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
rest[_key4 - 1] = arguments[_key4];
}
return _update.call.apply(_update, [Model, whereNotDeleted].concat(rest));
};
};
module.exports = exports['default'];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvZnQtZGVsZXRlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7Ozs7O0FBQ0EsSUFBTSxRQUFRLHNCQUFkOztrQkFFZSxVQUFDLEtBQUQsUUFBdUQ7QUFBQSw0QkFBN0MsU0FBNkM7QUFBQSxNQUE3QyxTQUE2QyxrQ0FBakMsV0FBaUM7QUFBQSx3QkFBcEIsS0FBb0I7QUFBQSxNQUFwQixLQUFvQiw4QkFBWixLQUFZOztBQUNwRSxRQUFNLCtCQUFOLEVBQXVDLE1BQU0sU0FBN0M7O0FBRUEsUUFBTSxTQUFOLEVBQWlCLEVBQUUsb0JBQUYsRUFBYSxZQUFiLEVBQWpCOztBQUVBLE1BQU0sYUFBYSxNQUFNLFVBQU4sQ0FBaUIsVUFBcEM7QUFDQSxNQUFNLFNBQVMsTUFBTSxVQUFOLENBQWlCLE1BQWpCLENBQXdCLE1BQU0sU0FBOUIsQ0FBZjs7QUFFQSxNQUFJLFdBQVcsRUFBZjtBQUNBLE1BQUksVUFBVSxLQUFkLEVBQXFCO0FBQ25CLFFBQUksb0JBQW9CLEtBQXhCO0FBQ0EsUUFBSSxDQUFDLE1BQU0sT0FBTixDQUFjLGlCQUFkLENBQUwsRUFBdUM7QUFDckMsMEJBQW9CLG9CQUFZLFVBQVosRUFDakIsTUFEaUIsQ0FDVjtBQUFBLGVBQVEsQ0FBQyxXQUFXLElBQVgsRUFBaUIsTUFBakIsQ0FBRCxJQUE2QixTQUFTLFNBQTlDO0FBQUEsT0FEVSxDQUFwQjtBQUVEO0FBQ0QsZUFBVyxrQkFBa0IsTUFBbEIsQ0FBeUIsVUFBQyxHQUFELEVBQU0sSUFBTjtBQUFBLHdDQUFxQixHQUFyQixvQ0FBMkIsSUFBM0IsRUFBa0MsSUFBbEM7QUFBQSxLQUF6QixFQUFvRSxFQUFwRSxDQUFYO0FBQ0Q7O0FBRUQsUUFBTSxjQUFOLENBQXFCLFNBQXJCLEVBQWdDLEVBQUMsTUFBTSxJQUFQLEVBQWEsVUFBVSxLQUF2QixFQUFoQzs7QUFFQSxRQUFNLFVBQU4sR0FBbUIsU0FBUyxjQUFULENBQXdCLEtBQXhCLEVBQStCLEVBQS9CLEVBQW1DO0FBQ3BELFdBQU8sTUFBTSxTQUFOLENBQWdCLEtBQWhCLDZCQUE0QixRQUE1QixvQ0FBdUMsU0FBdkMsRUFBbUQsSUFBSSxJQUFKLEVBQW5ELElBQ0osSUFESSxDQUNDO0FBQUEsYUFBVyxPQUFPLEVBQVAsS0FBYyxVQUFmLEdBQTZCLEdBQUcsSUFBSCxFQUFTLE1BQVQsQ0FBN0IsR0FBZ0QsTUFBMUQ7QUFBQSxLQURELEVBRUosS0FGSSxDQUVFO0FBQUEsYUFBVSxPQUFPLEVBQVAsS0FBYyxVQUFmLEdBQTZCLEdBQUcsS0FBSCxDQUE3QixHQUF5QyxrQkFBUSxNQUFSLENBQWUsS0FBZixDQUFsRDtBQUFBLEtBRkYsQ0FBUDtBQUdELEdBSkQ7O0FBTUEsUUFBTSxNQUFOLEdBQWUsTUFBTSxVQUFyQjtBQUNBLFFBQU0sU0FBTixHQUFrQixNQUFNLFVBQXhCOztBQUVBLFFBQU0sV0FBTixHQUFvQixTQUFTLGVBQVQsQ0FBeUIsRUFBekIsRUFBNkIsRUFBN0IsRUFBaUM7QUFDbkQsV0FBTyxNQUFNLFNBQU4sbUNBQW1CLE1BQW5CLEVBQTRCLEVBQTVCLDhCQUF1QyxRQUF2QyxvQ0FBa0QsU0FBbEQsRUFBOEQsSUFBSSxJQUFKLEVBQTlELElBQ0osSUFESSxDQUNDO0FBQUEsYUFBVyxPQUFPLEVBQVAsS0FBYyxVQUFmLEdBQTZCLEdBQUcsSUFBSCxFQUFTLE1BQVQsQ0FBN0IsR0FBZ0QsTUFBMUQ7QUFBQSxLQURELEVBRUosS0FGSSxDQUVFO0FBQUEsYUFBVSxPQUFPLEVBQVAsS0FBYyxVQUFmLEdBQTZCLEdBQUcsS0FBSCxDQUE3QixHQUF5QyxrQkFBUSxNQUFSLENBQWUsS0FBZixDQUFsRDtBQUFBLEtBRkYsQ0FBUDtBQUdELEdBSkQ7O0FBTUEsUUFBTSxVQUFOLEdBQW1CLE1BQU0sV0FBekI7QUFDQSxRQUFNLFVBQU4sR0FBbUIsTUFBTSxXQUF6Qjs7QUFFQSxRQUFNLFNBQU4sQ0FBZ0IsT0FBaEIsR0FBMEIsU0FBUyxXQUFULENBQXFCLE9BQXJCLEVBQThCLEVBQTlCLEVBQWtDO0FBQzFELFFBQU0sV0FBWSxPQUFPLFNBQVAsSUFBb0IsT0FBTyxPQUFQLEtBQW1CLFVBQXhDLEdBQXNELE9BQXRELEdBQWdFLEVBQWpGOztBQUVBLFdBQU8sS0FBSyxnQkFBTCw0QkFBMkIsUUFBM0Isb0NBQXNDLFNBQXRDLEVBQWtELElBQUksSUFBSixFQUFsRCxJQUNKLElBREksQ0FDQztBQUFBLGFBQVcsT0FBTyxFQUFQLEtBQWMsVUFBZixHQUE2QixTQUFTLElBQVQsRUFBZSxNQUFmLENBQTdCLEdBQXNELE1BQWhFO0FBQUEsS0FERCxFQUVKLEtBRkksQ0FFRTtBQUFBLGFBQVUsT0FBTyxFQUFQLEtBQWMsVUFBZixHQUE2QixTQUFTLEtBQVQsQ0FBN0IsR0FBK0Msa0JBQVEsTUFBUixDQUFlLEtBQWYsQ0FBeEQ7QUFBQSxLQUZGLENBQVA7QUFHRCxHQU5EOztBQVFBLFFBQU0sU0FBTixDQUFnQixNQUFoQixHQUF5QixNQUFNLFNBQU4sQ0FBZ0IsT0FBekM7QUFDQSxRQUFNLFNBQU4sQ0FBZ0IsTUFBaEIsR0FBeUIsTUFBTSxTQUFOLENBQWdCLE9BQXpDOztBQUVBO0FBQ0EsTUFBTSxvREFBb0IsU0FBcEIsRUFBZ0MsSUFBaEMsQ0FBTjs7QUFFQSxNQUFNLGdCQUFnQixNQUFNLFlBQTVCO0FBQ0EsUUFBTSxZQUFOLEdBQXFCLFNBQVMsbUJBQVQsR0FBa0Q7QUFBQSxRQUFyQixLQUFxQix5REFBYixFQUFhOztBQUNyRSxRQUFJLENBQUMsTUFBTSxPQUFYLEVBQW9CO0FBQ2xCLFVBQUksQ0FBQyxNQUFNLEtBQVAsSUFBZ0Isb0JBQVksTUFBTSxLQUFsQixFQUF5QixNQUF6QixLQUFvQyxDQUF4RCxFQUEyRDtBQUN6RCxjQUFNLEtBQU4sR0FBYyxlQUFkO0FBQ0QsT0FGRCxNQUVPO0FBQ0wsY0FBTSxLQUFOLEdBQWMsRUFBRSxLQUFLLENBQUUsTUFBTSxLQUFSLEVBQWUsZUFBZixDQUFQLEVBQWQ7QUFDRDtBQUNGOztBQVBvRSxzQ0FBTixJQUFNO0FBQU4sVUFBTTtBQUFBOztBQVNyRSxXQUFPLGNBQWMsSUFBZCx1QkFBbUIsS0FBbkIsRUFBMEIsS0FBMUIsU0FBb0MsSUFBcEMsRUFBUDtBQUNELEdBVkQ7O0FBWUEsTUFBTSxRQUFRLE1BQU0sSUFBcEI7QUFDQSxRQUFNLElBQU4sR0FBYSxTQUFTLFdBQVQsR0FBMEM7QUFBQSxRQUFyQixLQUFxQix5REFBYixFQUFhOztBQUNyRCxRQUFJLENBQUMsTUFBTSxPQUFYLEVBQW9CO0FBQ2xCLFVBQUksQ0FBQyxNQUFNLEtBQVAsSUFBZ0Isb0JBQVksTUFBTSxLQUFsQixFQUF5QixNQUF6QixLQUFvQyxDQUF4RCxFQUEyRDtBQUN6RCxjQUFNLEtBQU4sR0FBYyxlQUFkO0FBQ0QsT0FGRCxNQUVPO0FBQ0wsY0FBTSxLQUFOLEdBQWMsRUFBRSxLQUFLLENBQUUsTUFBTSxLQUFSLEVBQWUsZUFBZixDQUFQLEVBQWQ7QUFDRDtBQUNGOztBQVBvRCx1Q0FBTixJQUFNO0FBQU4sVUFBTTtBQUFBOztBQVNyRCxXQUFPLE1BQU0sSUFBTixlQUFXLEtBQVgsRUFBa0IsS0FBbEIsU0FBNEIsSUFBNUIsRUFBUDtBQUNELEdBVkQ7O0FBWUEsTUFBTSxTQUFTLE1BQU0sS0FBckI7QUFDQSxRQUFNLEtBQU4sR0FBYyxTQUFTLFlBQVQsR0FBMkM7QUFBQSxRQUFyQixLQUFxQix5REFBYixFQUFhOztBQUN2RDtBQUNBLFFBQUksd0JBQUo7QUFDQSxRQUFJLENBQUMsS0FBRCxJQUFVLG9CQUFZLEtBQVosRUFBbUIsTUFBbkIsS0FBOEIsQ0FBNUMsRUFBK0M7QUFDN0Msd0JBQWtCLGVBQWxCO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsd0JBQWtCLEVBQUUsS0FBSyxDQUFFLEtBQUYsRUFBUyxlQUFULENBQVAsRUFBbEI7QUFDRDs7QUFQc0QsdUNBQU4sSUFBTTtBQUFOLFVBQU07QUFBQTs7QUFRdkQsV0FBTyxPQUFPLElBQVAsZ0JBQVksS0FBWixFQUFtQixlQUFuQixTQUF1QyxJQUF2QyxFQUFQO0FBQ0QsR0FURDs7QUFXQSxNQUFNLFVBQVUsTUFBTSxNQUF0QjtBQUNBLFFBQU0sTUFBTixHQUFlLE1BQU0sU0FBTixHQUFrQixTQUFTLGFBQVQsR0FBNEM7QUFBQSxRQUFyQixLQUFxQix5REFBYixFQUFhOztBQUMzRTtBQUNBLFFBQUksd0JBQUo7QUFDQSxRQUFJLENBQUMsS0FBRCxJQUFVLG9CQUFZLEtBQVosRUFBbUIsTUFBbkIsS0FBOEIsQ0FBNUMsRUFBK0M7QUFDN0Msd0JBQWtCLGVBQWxCO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsd0JBQWtCLEVBQUUsS0FBSyxDQUFFLEtBQUYsRUFBUyxlQUFULENBQVAsRUFBbEI7QUFDRDs7QUFQMEUsdUNBQU4sSUFBTTtBQUFOLFVBQU07QUFBQTs7QUFRM0UsV0FBTyxRQUFRLElBQVIsaUJBQWEsS0FBYixFQUFvQixlQUFwQixTQUF3QyxJQUF4QyxFQUFQO0FBQ0QsR0FURDtBQVVELEMiLCJmaWxlIjoic29mdC1kZWxldGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgX2RlYnVnIGZyb20gJy4vZGVidWcnO1xuY29uc3QgZGVidWcgPSBfZGVidWcoKTtcblxuZXhwb3J0IGRlZmF1bHQgKE1vZGVsLCB7IGRlbGV0ZWRBdCA9ICdkZWxldGVkQXQnLCBzY3J1YiA9IGZhbHNlIH0pID0+IHtcbiAgZGVidWcoJ1NvZnREZWxldGUgbWl4aW4gZm9yIE1vZGVsICVzJywgTW9kZWwubW9kZWxOYW1lKTtcblxuICBkZWJ1Zygnb3B0aW9ucycsIHsgZGVsZXRlZEF0LCBzY3J1YiB9KTtcblxuICBjb25zdCBwcm9wZXJ0aWVzID0gTW9kZWwuZGVmaW5pdGlvbi5wcm9wZXJ0aWVzO1xuICBjb25zdCBpZE5hbWUgPSBNb2RlbC5kYXRhU291cmNlLmlkTmFtZShNb2RlbC5tb2RlbE5hbWUpO1xuXG4gIGxldCBzY3J1YmJlZCA9IHt9O1xuICBpZiAoc2NydWIgIT09IGZhbHNlKSB7XG4gICAgbGV0IHByb3BlcnRpZXNUb1NjcnViID0gc2NydWI7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHByb3BlcnRpZXNUb1NjcnViKSkge1xuICAgICAgcHJvcGVydGllc1RvU2NydWIgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKVxuICAgICAgICAuZmlsdGVyKHByb3AgPT4gIXByb3BlcnRpZXNbcHJvcF1baWROYW1lXSAmJiBwcm9wICE9PSBkZWxldGVkQXQpO1xuICAgIH1cbiAgICBzY3J1YmJlZCA9IHByb3BlcnRpZXNUb1NjcnViLnJlZHVjZSgob2JqLCBwcm9wKSA9PiAoeyAuLi5vYmosIFtwcm9wXTogbnVsbCB9KSwge30pO1xuICB9XG5cbiAgTW9kZWwuZGVmaW5lUHJvcGVydHkoZGVsZXRlZEF0LCB7dHlwZTogRGF0ZSwgcmVxdWlyZWQ6IGZhbHNlfSk7XG5cbiAgTW9kZWwuZGVzdHJveUFsbCA9IGZ1bmN0aW9uIHNvZnREZXN0cm95QWxsKHdoZXJlLCBjYikge1xuICAgIHJldHVybiBNb2RlbC51cGRhdGVBbGwod2hlcmUsIHsgLi4uc2NydWJiZWQsIFtkZWxldGVkQXRdOiBuZXcgRGF0ZSgpIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4gKHR5cGVvZiBjYiA9PT0gJ2Z1bmN0aW9uJykgPyBjYihudWxsLCByZXN1bHQpIDogcmVzdWx0KVxuICAgICAgLmNhdGNoKGVycm9yID0+ICh0eXBlb2YgY2IgPT09ICdmdW5jdGlvbicpID8gY2IoZXJyb3IpIDogUHJvbWlzZS5yZWplY3QoZXJyb3IpKTtcbiAgfTtcblxuICBNb2RlbC5yZW1vdmUgPSBNb2RlbC5kZXN0cm95QWxsO1xuICBNb2RlbC5kZWxldGVBbGwgPSBNb2RlbC5kZXN0cm95QWxsO1xuXG4gIE1vZGVsLmRlc3Ryb3lCeUlkID0gZnVuY3Rpb24gc29mdERlc3Ryb3lCeUlkKGlkLCBjYikge1xuICAgIHJldHVybiBNb2RlbC51cGRhdGVBbGwoeyBbaWROYW1lXTogaWQgfSwgeyAuLi5zY3J1YmJlZCwgW2RlbGV0ZWRBdF06IG5ldyBEYXRlKCl9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+ICh0eXBlb2YgY2IgPT09ICdmdW5jdGlvbicpID8gY2IobnVsbCwgcmVzdWx0KSA6IHJlc3VsdClcbiAgICAgIC5jYXRjaChlcnJvciA9PiAodHlwZW9mIGNiID09PSAnZnVuY3Rpb24nKSA/IGNiKGVycm9yKSA6IFByb21pc2UucmVqZWN0KGVycm9yKSk7XG4gIH07XG5cbiAgTW9kZWwucmVtb3ZlQnlJZCA9IE1vZGVsLmRlc3Ryb3lCeUlkO1xuICBNb2RlbC5kZWxldGVCeUlkID0gTW9kZWwuZGVzdHJveUJ5SWQ7XG5cbiAgTW9kZWwucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiBzb2Z0RGVzdHJveShvcHRpb25zLCBjYikge1xuICAgIGNvbnN0IGNhbGxiYWNrID0gKGNiID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9wdGlvbnMgPT09ICdmdW5jdGlvbicpID8gb3B0aW9ucyA6IGNiO1xuXG4gICAgcmV0dXJuIHRoaXMudXBkYXRlQXR0cmlidXRlcyh7IC4uLnNjcnViYmVkLCBbZGVsZXRlZEF0XTogbmV3IERhdGUoKSB9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+ICh0eXBlb2YgY2IgPT09ICdmdW5jdGlvbicpID8gY2FsbGJhY2sobnVsbCwgcmVzdWx0KSA6IHJlc3VsdClcbiAgICAgIC5jYXRjaChlcnJvciA9PiAodHlwZW9mIGNiID09PSAnZnVuY3Rpb24nKSA/IGNhbGxiYWNrKGVycm9yKSA6IFByb21pc2UucmVqZWN0KGVycm9yKSk7XG4gIH07XG5cbiAgTW9kZWwucHJvdG90eXBlLnJlbW92ZSA9IE1vZGVsLnByb3RvdHlwZS5kZXN0cm95O1xuICBNb2RlbC5wcm90b3R5cGUuZGVsZXRlID0gTW9kZWwucHJvdG90eXBlLmRlc3Ryb3k7XG5cbiAgLy8gRW11bGF0ZSBkZWZhdWx0IHNjb3BlIGJ1dCB3aXRoIG1vcmUgZmxleGliaWxpdHkuXG4gIGNvbnN0IHF1ZXJ5Tm9uRGVsZXRlZCA9IHtbZGVsZXRlZEF0XTogbnVsbH07XG5cbiAgY29uc3QgX2ZpbmRPckNyZWF0ZSA9IE1vZGVsLmZpbmRPckNyZWF0ZTtcbiAgTW9kZWwuZmluZE9yQ3JlYXRlID0gZnVuY3Rpb24gZmluZE9yQ3JlYXRlRGVsZXRlZChxdWVyeSA9IHt9LCAuLi5yZXN0KSB7XG4gICAgaWYgKCFxdWVyeS5kZWxldGVkKSB7XG4gICAgICBpZiAoIXF1ZXJ5LndoZXJlIHx8IE9iamVjdC5rZXlzKHF1ZXJ5LndoZXJlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcXVlcnkud2hlcmUgPSBxdWVyeU5vbkRlbGV0ZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBxdWVyeS53aGVyZSA9IHsgYW5kOiBbIHF1ZXJ5LndoZXJlLCBxdWVyeU5vbkRlbGV0ZWQgXSB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfZmluZE9yQ3JlYXRlLmNhbGwoTW9kZWwsIHF1ZXJ5LCAuLi5yZXN0KTtcbiAgfTtcblxuICBjb25zdCBfZmluZCA9IE1vZGVsLmZpbmQ7XG4gIE1vZGVsLmZpbmQgPSBmdW5jdGlvbiBmaW5kRGVsZXRlZChxdWVyeSA9IHt9LCAuLi5yZXN0KSB7XG4gICAgaWYgKCFxdWVyeS5kZWxldGVkKSB7XG4gICAgICBpZiAoIXF1ZXJ5LndoZXJlIHx8IE9iamVjdC5rZXlzKHF1ZXJ5LndoZXJlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcXVlcnkud2hlcmUgPSBxdWVyeU5vbkRlbGV0ZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBxdWVyeS53aGVyZSA9IHsgYW5kOiBbIHF1ZXJ5LndoZXJlLCBxdWVyeU5vbkRlbGV0ZWQgXSB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfZmluZC5jYWxsKE1vZGVsLCBxdWVyeSwgLi4ucmVzdCk7XG4gIH07XG5cbiAgY29uc3QgX2NvdW50ID0gTW9kZWwuY291bnQ7XG4gIE1vZGVsLmNvdW50ID0gZnVuY3Rpb24gY291bnREZWxldGVkKHdoZXJlID0ge30sIC4uLnJlc3QpIHtcbiAgICAvLyBCZWNhdXNlIGNvdW50IG9ubHkgcmVjZWl2ZXMgYSAnd2hlcmUnLCB0aGVyZSdzIG5vd2hlcmUgdG8gYXNrIGZvciB0aGUgZGVsZXRlZCBlbnRpdGllcy5cbiAgICBsZXQgd2hlcmVOb3REZWxldGVkO1xuICAgIGlmICghd2hlcmUgfHwgT2JqZWN0LmtleXMod2hlcmUpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgd2hlcmVOb3REZWxldGVkID0gcXVlcnlOb25EZWxldGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZU5vdERlbGV0ZWQgPSB7IGFuZDogWyB3aGVyZSwgcXVlcnlOb25EZWxldGVkIF0gfTtcbiAgICB9XG4gICAgcmV0dXJuIF9jb3VudC5jYWxsKE1vZGVsLCB3aGVyZU5vdERlbGV0ZWQsIC4uLnJlc3QpO1xuICB9O1xuXG4gIGNvbnN0IF91cGRhdGUgPSBNb2RlbC51cGRhdGU7XG4gIE1vZGVsLnVwZGF0ZSA9IE1vZGVsLnVwZGF0ZUFsbCA9IGZ1bmN0aW9uIHVwZGF0ZURlbGV0ZWQod2hlcmUgPSB7fSwgLi4ucmVzdCkge1xuICAgIC8vIEJlY2F1c2UgdXBkYXRlL3VwZGF0ZUFsbCBvbmx5IHJlY2VpdmVzIGEgJ3doZXJlJywgdGhlcmUncyBub3doZXJlIHRvIGFzayBmb3IgdGhlIGRlbGV0ZWQgZW50aXRpZXMuXG4gICAgbGV0IHdoZXJlTm90RGVsZXRlZDtcbiAgICBpZiAoIXdoZXJlIHx8IE9iamVjdC5rZXlzKHdoZXJlKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHdoZXJlTm90RGVsZXRlZCA9IHF1ZXJ5Tm9uRGVsZXRlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hlcmVOb3REZWxldGVkID0geyBhbmQ6IFsgd2hlcmUsIHF1ZXJ5Tm9uRGVsZXRlZCBdIH07XG4gICAgfVxuICAgIHJldHVybiBfdXBkYXRlLmNhbGwoTW9kZWwsIHdoZXJlTm90RGVsZXRlZCwgLi4ucmVzdCk7XG4gIH07XG59O1xuIl0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9
;