@genialis/resolwe
Version:
Resolwe frontend libraries
521 lines (520 loc) • 68.2 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var _ = require("lodash");
var jQuery = require("jquery");
var Rx = require("rx");
var queryobserver_1 = require("./queryobserver");
var error_1 = require("../core/errors/error");
var index_1 = require("./index");
var lang_1 = require("../core/utils/lang");
var random = require("../core/utils/random");
var MockQueryObserverManager = /** @class */ (function (_super) {
__extends(MockQueryObserverManager, _super);
function MockQueryObserverManager() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* @inheritdoc
*/
MockQueryObserverManager.prototype.remove = function (observerId) {
this._deleteObserver(observerId);
// Call the unsubscribe method immediately during tests. The actual query
// observer manager will defer these calls instead.
this._unsubscribe(observerId).subscribe(function () {
// Subscribe to process the (mock) request.
});
};
/**
* @inheritdoc
*/
MockQueryObserverManager.prototype.chainAfterUnsubscribe = function (makeObservable) {
// Do not defer makeObservable during tests.
return makeObservable();
};
return MockQueryObserverManager;
}(queryobserver_1.QueryObserverManager));
var MockConnection = /** @class */ (function () {
function MockConnection() {
this._logUnhandledRequests = false;
this._mockItems = {};
this._mockResponses = {};
this._simulateDelay = false;
this._messages = new Rx.Subject();
this._isConnected = new Rx.BehaviorSubject(false);
this._errors = new Rx.Subject();
this._queryObserverManager = new MockQueryObserverManager(this, this._errors);
}
/**
* @inheritdoc
*/
MockConnection.prototype.connect = function (restUri, websocketUri) {
this._isConnected.onNext(true);
this.messages().subscribe(this._queryObserverManager.update.bind(this._queryObserverManager));
};
/**
* @inheritdoc
*/
MockConnection.prototype.disconnect = function () {
this._isConnected.onNext(false);
};
/**
* @inheritdoc
*/
MockConnection.prototype.isConnected = function () {
return this._isConnected;
};
MockConnection.prototype._registerMockRequestHandler = function (method, path, handler) {
if (!this._mockResponses[method])
this._mockResponses[method] = [];
var handlers = this._mockResponses[method];
if (_.any(handlers, function (existingHandler) { return existingHandler.path === path; })) {
console.error("Method " + method + " for path " + path + " already registered");
}
handlers.push({
path: path,
handler: handler,
});
};
MockConnection.prototype._handleMockResponse = function (method, responsePath, parameters, data) {
var matchingHandlers = _.filter(this._mockResponses[method], function (match) {
if (match.path instanceof RegExp)
return match.path.test(responsePath);
return match.path === responsePath;
});
if (_.isEmpty(matchingHandlers)) {
if (this._logUnhandledRequests) {
var prettyPath = decodeURIComponent(this.createUriFromPath(responsePath, parameters));
console.info("Mock API " + method + ": " + prettyPath + " requested, but didnt match any handler", {
mockItems: _.keys(this._mockItems),
lookedForMockItem: responsePath.split('/').slice(2).join('/'),
mockResponses: this._mockResponses[method],
lookedForMockResponse: responsePath,
});
}
return Rx.Observable.just({});
}
if (_.size(matchingHandlers) > 1) {
console.error("Multiple handlers matched for method " + method + " on path " + responsePath);
}
// TODO: Support mocking errors as well.
var _a = matchingHandlers[0], path = _a.path, handler = _a.handler;
if (path instanceof RegExp) {
return Rx.Observable.just(handler(parameters, data, path.exec(responsePath)));
}
return Rx.Observable.just(handler(parameters, data));
};
/**
* @inheritdoc
*/
MockConnection.prototype.simulateDelay = function (value) {
this._simulateDelay = value;
};
/**
* @inheritdoc
*/
MockConnection.prototype.logUnhandledRequests = function (value) {
this._logUnhandledRequests = value;
};
/**
* @inheritdoc
*/
MockConnection.prototype.get = function (path, parameters) {
if (!_.startsWith(path, '/api/'))
return this._handleMockResponse('get', path, parameters, {});
var reactive = _.has(parameters, 'observe');
var atoms = path.split('/');
var resource = atoms.slice(2).join('/');
if (!reactive && !_.has(this._mockItems, resource)) {
return this._handleMockResponse('get', path, parameters, {});
}
var items = this._getMockItemsFor(resource);
if (items.blackhole)
return Rx.Observable.never();
var observable;
if (!reactive) {
// Non-reactive query.
observable = Rx.Observable.just(items.queryEvaluator(parameters, items.items));
}
else {
// Reactive query.
var observer = {
observerId: random.randomUuid(),
query: _.omit(parameters, 'observe'),
items: {},
};
items.observers.push(observer);
observable = Rx.Observable.just({
observer: observer.observerId,
items: this._updateMockObserver(observer, items, false),
});
}
return this._simulateDelay ? observable.delay(100) : observable;
};
/**
* @inheritdoc
*/
MockConnection.prototype.post = function (path, data, parameters) {
return this._handleMockResponse('post', path, parameters, data);
};
/**
* @inheritdoc
*/
MockConnection.prototype.put = function (path, data, parameters) {
return this._handleMockResponse('put', path, parameters, data);
};
/**
* @inheritdoc
*/
MockConnection.prototype.patch = function (path, data, parameters) {
return this._handleMockResponse('patch', path, parameters, data);
};
/**
* @inheritdoc
*/
MockConnection.prototype.delete = function (path, data, parameters) {
return this._handleMockResponse('delete', path, parameters, data);
};
/**
* @inheritdoc
*/
MockConnection.prototype.createUriFromPath = function (path, queryParameters) {
var parameters = !_.isEmpty(queryParameters) ? '?' + jQuery.param(queryParameters) : '';
return path + parameters;
};
/**
* @inheritdoc
*/
MockConnection.prototype.csrfCookie = function () {
return 'cookie';
};
/**
* @inheritdoc
*/
MockConnection.prototype.messages = function () {
return this._messages;
};
/**
* @inheritdoc
*/
MockConnection.prototype.errors = function () {
throw new error_1.GenError('Throwing errors in mocked connection not supported');
};
/**
* @inheritdoc
*/
MockConnection.prototype.sessionId = function () {
return 'session-id';
};
/**
* @inheritdoc
*/
MockConnection.prototype.queryObserverManager = function () {
return this._queryObserverManager;
};
MockConnection.prototype._getMockItemsFor = function (resource) {
var mockItems = this._mockItems[resource];
if (!mockItems) {
// If the resource doesn't exist, we always return an empty resource, so that the
// processing doesn't fail, it just always contains no items.
console.error("Mock API resource '" + resource + "' referenced, but has not been defined.");
return {
primaryKey: 'id',
items: [],
observers: [],
queryEvaluator: function (query, items) { return items; },
blackhole: false,
};
}
return mockItems;
};
MockConnection.prototype._updateMockObserver = function (observer, items, notify) {
if (notify === void 0) { notify = true; }
var oldItems = observer.items;
var newItems = {};
// Evaluate query on all the new items.
var newItemsArray = items.queryEvaluator(observer.query, items.items);
_.each(newItemsArray, function (item, index) {
item._order = index;
newItems[item[items.primaryKey]] = item;
});
observer.items = newItems;
if (notify) {
var removed = _.filter(oldItems, function (item, itemId) { return !newItems[itemId]; });
var added = _.filter(newItems, function (item, itemId) { return !oldItems[itemId]; });
var changed = _.filter(newItems, function (newItem, itemId) {
if (!oldItems[itemId])
return false;
return !_.isEqual(newItem, oldItems[itemId]);
});
for (var _i = 0, _a = [[added, queryobserver_1.MESSAGE_ADDED], [removed, queryobserver_1.MESSAGE_REMOVED], [changed, queryobserver_1.MESSAGE_CHANGED]]; _i < _a.length; _i++) {
var _b = _a[_i], changes = _b[0], type = _b[1];
for (var _c = 0, changes_1 = changes; _c < changes_1.length; _c++) {
var item = changes_1[_c];
this._messages.onNext({
msg: type,
observer: observer.observerId,
primary_key: items.primaryKey,
order: item._order,
item: _.cloneDeep(_.omit(item, '_order')),
});
}
}
}
return _.map(newItemsArray, function (item) { return _.omit(item, '_order'); });
};
MockConnection.prototype._notifyMockObservers = function (items) {
for (var _i = 0, _a = items.observers; _i < _a.length; _i++) {
var observer = _a[_i];
this._updateMockObserver(observer, items);
}
};
// Developer-facing API below.
/**
* @inheritdoc
*/
MockConnection.prototype.reset = function () {
this._mockItems = {};
this._mockResponses = {};
};
/**
* @inheritdoc
*/
MockConnection.prototype.createResource = function (resource, primaryKey, queryEvaluator) {
if (primaryKey === void 0) { primaryKey = 'id'; }
if (queryEvaluator === void 0) { queryEvaluator = function (query, items) { return items; }; }
this._mockItems[resource] = {
primaryKey: primaryKey,
items: [],
observers: [],
queryEvaluator: queryEvaluator,
blackhole: false,
};
};
/**
* @inheritdoc
*/
MockConnection.prototype.createBlackholeResource = function (resource) {
this._mockItems[resource] = {
primaryKey: null,
items: [],
observers: [],
queryEvaluator: null,
blackhole: true,
};
};
/**
* @inheritdoc
*/
MockConnection.prototype.addItem = function (resource, item) {
var items = this._getMockItemsFor(resource);
items.items.push(_.cloneDeep(item));
this._notifyMockObservers(items);
};
/**
* @inheritdoc
*/
MockConnection.prototype.addItems = function (resource, items) {
var existingItems = this._getMockItemsFor(resource);
existingItems.items.push.apply(existingItems.items, _.cloneDeep(items));
this._notifyMockObservers(existingItems);
};
/**
* @inheritdoc
*/
MockConnection.prototype.updateItem = function (resource, item) {
var _a;
var items = this._getMockItemsFor(resource);
var index = _.findIndex(items.items, (_a = {}, _a[items.primaryKey] = item[items.primaryKey], _a));
items.items[index] = item;
this._notifyMockObservers(items);
};
/**
* @inheritdoc
*/
MockConnection.prototype.removeItem = function (resource, itemId) {
var _a;
var items = this._getMockItemsFor(resource);
var index = _.findIndex(items.items, (_a = {}, _a[items.primaryKey] = itemId, _a));
_.pullAt(items.items, index);
this._notifyMockObservers(items);
};
/**
* @inheritdoc
*/
MockConnection.prototype.whenGet = function (path, handler) {
this._registerMockRequestHandler('get', path, handler);
};
/**
* @inheritdoc
*/
MockConnection.prototype.whenPost = function (path, handler) {
this._registerMockRequestHandler('post', path, handler);
};
/**
* @inheritdoc
*/
MockConnection.prototype.whenPut = function (path, handler) {
this._registerMockRequestHandler('put', path, handler);
};
/**
* @inheritdoc
*/
MockConnection.prototype.whenPatch = function (path, handler) {
this._registerMockRequestHandler('patch', path, handler);
};
/**
* @inheritdoc
*/
MockConnection.prototype.whenDelete = function (path, handler) {
this._registerMockRequestHandler('delete', path, handler);
};
return MockConnection;
}());
exports.MockConnection = MockConnection;
/**
* Mock API mixin, which may be used in tests to simulate the backend.
*/
var MockApiMixin = /** @class */ (function () {
function MockApiMixin() {
}
/**
* @inheritdoc
*/
MockApiMixin.prototype.reset = function () {
this.connection.reset();
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.simulateDelay = function (value) {
this.connection.simulateDelay(value);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.logUnhandledRequests = function (value) {
this.connection.logUnhandledRequests(value);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.createResource = function (resource, primaryKey, query) {
this.connection.createResource(resource, primaryKey, query);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.createBlackholeResource = function (resource) {
this.connection.createBlackholeResource(resource);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.addItem = function (resource, item) {
this.connection.addItem(resource, item);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.addItems = function (resource, items) {
this.connection.addItems(resource, items);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.updateItem = function (resource, item) {
this.connection.updateItem(resource, item);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.removeItem = function (resource, itemId) {
this.connection.removeItem(resource, itemId);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.whenGet = function (path, handler) {
this.connection.whenGet(path, handler);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.whenPost = function (path, handler) {
this.connection.whenPost(path, handler);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.whenPut = function (path, handler) {
this.connection.whenPut(path, handler);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.whenPatch = function (path, handler) {
this.connection.whenPatch(path, handler);
};
/**
* @inheritdoc
*/
MockApiMixin.prototype.whenDelete = function (path, handler) {
this.connection.whenDelete(path, handler);
};
return MockApiMixin;
}());
exports.MockApiMixin = MockApiMixin;
exports.MockApiBase = lang_1.compose([index_1.ResolweApi, MockApiMixin]);
var MockApi = /** @class */ (function (_super) {
__extends(MockApi, _super);
// @ngInject
function MockApi() {
return _super.call(this, new MockConnection(), null, null) || this;
}
return MockApi;
}(exports.MockApiBase));
exports.MockApi = MockApi;
/**
* Helper function for supporting pagination, which can be used as a [[MockQueryEvaluator]].
*/
function paginateQuery(query, items) {
var limit = query.limit || 0;
var offset = query.offset || 0;
return items.slice(offset, limit > 0 ? offset + limit : undefined);
}
exports.paginateQuery = paginateQuery;
/**
* Helper function for supporting ordering.
*/
function orderingQuery(query, items) {
if (!query.ordering)
return items;
var ordering = query.ordering.split(',');
var orderingDirections = _.map(ordering, function (column) { return column[0] === '-' ? 'desc' : 'asc'; });
var orderingColumns = _.map(ordering, function (column) { return column[0] === '-' ? column.substr(1) : column; });
return _.sortByOrder(items, orderingColumns, orderingDirections);
}
exports.orderingQuery = orderingQuery;
/**
* Helper function for supporting filtering by slug, which can be used as a [[MockQueryEvaluator]].
*/
function slugQuery(query, items) {
if (!query.slug)
return items;
return _.filter(items, function (item) { return item.slug === query.slug; });
}
exports.slugQuery = slugQuery;
//# sourceMappingURL=data:application/json;charset=utf8;base64,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SUMiLCJmaWxlIjoiYXBpL21vY2suanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBqUXVlcnkgZnJvbSAnanF1ZXJ5JztcbmltcG9ydCAqIGFzIFJ4IGZyb20gJ3J4JztcblxuaW1wb3J0IHtDb25uZWN0aW9uLCBNZXNzYWdlfSBmcm9tICcuL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IHtRdWVyeU9ic2VydmVyTWFuYWdlciwgTUVTU0FHRV9BRERFRCwgTUVTU0FHRV9DSEFOR0VELCBNRVNTQUdFX1JFTU9WRUR9IGZyb20gJy4vcXVlcnlvYnNlcnZlcic7XG5pbXBvcnQge0dlbkVycm9yfSBmcm9tICcuLi9jb3JlL2Vycm9ycy9lcnJvcic7XG5pbXBvcnQge0FQSUVycm9yfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQge1F1ZXJ5LCBDb2xsZWN0aW9uLCBEYXRhfSBmcm9tICcuL3R5cGVzL3Jlc3QnO1xuaW1wb3J0IHtSZXNvbHdlQXBpfSBmcm9tICcuL2luZGV4JztcbmltcG9ydCB7Y29tcG9zZX0gZnJvbSAnLi4vY29yZS91dGlscy9sYW5nJztcbmltcG9ydCAqIGFzIHJhbmRvbSBmcm9tICcuLi9jb3JlL3V0aWxzL3JhbmRvbSc7XG5cbi8qKlxuICogTW9jayByZXF1ZXN0IGhhbmRsZXIgZnVuY3Rpb24uIEl0IHJlY2VpdmVzIGFueSBxdWVyeSBhcmd1bWVudHMgYW5kIGRhdGEgdGhhdFxuICogd2FzIHVzZWQgdG8gbWFrZSB0aGUgcmVxdWVzdC4gSWYgYSByZWd1bGFyIGV4cHJlc3Npb24gd2FzIHVzZWQgdG8gZGVmaW5lIHRoZVxuICogcGF0aCBtYXRjaCwgdGhlIHJlc3VsdCBvZiBwZXJmb3JtaW5nIGBSZWdFeHAuZXhlY2AgaXMgYWxzbyBnaXZlbiBhcyBhbiBhcmd1bWVudFxuICogYW5kIGNhbiBiZSB1c2VkIHRvIGV4dHJhY3QgcmVnZXhwIG1hdGNoZXMuXG4gKlxuICogQHBhcmFtIHBhcmFtZXRlcnMgUXVlcnkgcGFyYW1ldGVyc1xuICogQHBhcmFtIGRhdGEgUmVxdWVzdCBkYXRhXG4gKiBAcGFyYW0gcGF0aCBSZWd1bGFyIGV4cHJlc3Npb24gbWF0Y2hlc1xuICogQHJldHVybiBWYWx1ZSB0aGF0IHNob3VsZCBiZSByZXR1cm5lZCBhcyBhIHJlc3BvbnNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9ja1JlcXVlc3RIYW5kbGVyPFQ+IHtcbiAgICAocGFyYW1ldGVyczogYW55LCBkYXRhOiBhbnksIHBhdGg/OiBSZWdFeHBFeGVjQXJyYXkpOiBUO1xufVxuXG4vKipcbiAqIEEgZnVuY3Rpb24sIHdoaWNoIG1vY2tzIGV2YWx1YXRpb24gb2YgYSBxdWVyeS4gSXQgcmVjZWl2ZXMgdGhlIG9yaWdpbmFsIHF1ZXJ5XG4gKiBvYmplY3QgYW5kIGEgbGlzdCBvZiBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIG1vY2sgZGF0YWJhc2UuIEl0IG1heSByZXR1cm4gYVxuICogbW9kaWZpZWQgbGlzdCBvZiBpdGVtcywgdHJhbnNmb3JtZWQgYmFzZWQgb24gdGhlIHF1ZXJ5LCBvciB0aGUgaXRlbXMgdW5jaGFuZ2VkLlxuICpcbiAqIEBwYXJhbSBxdWVyeSBUaGUgb3JpZ2luYWwgcXVlcnkgb2JqZWN0XG4gKiBAcGFyYW0gaXRlbXMgQSBsaXN0IG9mIGl0ZW1zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9ja1F1ZXJ5RXZhbHVhdG9yPFQ+IHtcbiAgICAocXVlcnk6IGFueSwgaXRlbXM6IFRbXSk6IFRbXTtcbn1cblxuLyoqXG4gKiBEZXZlbG9wZXItZmFjaW5nIGludGVyZmFjZSBmb3IgY29uZmlndXJpbmcgcmVzcG9uc2VzIHRoYXQgdGhlIG1vY2tlZFxuICogYmFja2VuZCBzaG91bGQgcmV0dXJuLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1vY2tCYXNlIHtcbiAgICAvKipcbiAgICAgKiBSZXNldHMgYWxsIHJlZ2lzdGVyZWQgbW9jayBBUEkgcmVzb3VyY2VzIGFuZCBoYW5kbGVycy4gVGhpcyBtZXRob2QgY2FuIGJlIHVzZWRcbiAgICAgKiB0byByZWluaXRpYWxpemUgdGhlIG1vY2sgQVBJIGJldHdlZW4gdGVzdCBjYXNlcy5cbiAgICAgKi9cbiAgICByZXNldCgpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBkZWxheSBzaW11bGF0aW9uLlxuICAgICAqL1xuICAgIHNpbXVsYXRlRGVsYXkodmFsdWU6IGJvb2xlYW4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBsb2dnaW5nIHJlcXVlc3RzIHdpdGhvdXQgbWF0Y2hpbmcgaGFuZGxlcnMuXG4gICAgICovXG4gICAgbG9nVW5oYW5kbGVkUmVxdWVzdHModmFsdWU6IGJvb2xlYW4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBtb2NrIHJlc291cmNlIHRoYXQgd2lsbCBoYW5kbGUgcmVhY3RpdmUgcXVlcmllcy4gQSByZXNvdXJjZVxuICAgICAqIG11c3QgYmUgY3JlYXRlZCBiZWZvcmUgaXQgY2FuIGJlIHVzZWQgaW4gW1thZGRJdGVtXV0sIFtbdXBkYXRlSXRlbV1dIGFuZFxuICAgICAqIFtbcmVtb3ZlSXRlbV1dLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJlc291cmNlIE5hbWUgb2YgdGhlIHJlc291cmNlIChlZy4gJ2NvbGxlY3Rpb24nKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwcmltYXJ5S2V5IE5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgaG9sZHMgdGhlIHByaW1hcnkga2V5XG4gICAgICogQHBhcmFtIHtNb2NrUXVlcnlFdmFsdWF0b3I8VD59IHF1ZXJ5IE1vY2sgcXVlcnkgZXZhbHVhdG9yIGZ1bmN0aW9uXG4gICAgICovXG4gICAgY3JlYXRlUmVzb3VyY2U8VD4ocmVzb3VyY2U6IHN0cmluZywgcHJpbWFyeUtleT86IHN0cmluZywgcXVlcnk/OiBNb2NrUXVlcnlFdmFsdWF0b3I8VD4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBtb2NrIHJlc291cmNlIHRoYXQgd2lsbCBibGFja2hvbGUgcmVxdWVzdHMuIEFueSBxdWVyaWVzXG4gICAgICogc3VibWl0dGVkIHRvIHRoaXMgcmVzb3VyY2Ugd2lsbCBuZXZlciBjb21wbGV0ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByZXNvdXJjZSBOYW1lIG9mIHRoZSByZXNvdXJjZSAoZWcuICdjb2xsZWN0aW9uJylcbiAgICAgKi9cbiAgICBjcmVhdGVCbGFja2hvbGVSZXNvdXJjZShyZXNvdXJjZTogc3RyaW5nKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYW4gaXRlbSB0byB0aGUgbW9jayBkYXRhYmFzZSBiYWNraW5nIHRoZSBzcGVjaWZpYyByZXNvdXJjZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByZXNvdXJjZSBOYW1lIG9mIHRoZSByZXNvdXJjZVxuICAgICAqIEBwYXJhbSB7VH0gaXRlbSBJdGVtIHRvIGFkZFxuICAgICAqL1xuICAgIGFkZEl0ZW08VD4ocmVzb3VyY2U6IHN0cmluZywgaXRlbTogVCk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIG11bHRpcGxlIGl0ZW1zIHRvIHRoZSBtb2NrIGRhdGFiYXNlIGJhY2tpbmcgdGhlIHNwZWNpZmljIHJlc291cmNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJlc291cmNlIE5hbWUgb2YgdGhlIHJlc291cmNlXG4gICAgICogQHBhcmFtIHtUW119IGl0ZW1zIEl0ZW1zIHRvIGFkZFxuICAgICAqL1xuICAgIGFkZEl0ZW1zPFQ+KHJlc291cmNlOiBzdHJpbmcsIGl0ZW1zOiBUW10pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyBhbiBleGlzdGluZyBpdGVtIGluIHRoZSBtb2NrIGRhdGFiYXNlIGJhY2tpbmcgdGhlIHNwZWNpZmljXG4gICAgICogcmVzb3VyY2UuIEl0ZW1zIGFyZSBtYXRjaGVkIGJhc2VkIG9uIHRoZSBwcmltYXJ5IGtleSBjb25maWd1cmVkIGZvciB0aGVcbiAgICAgKiByZWZlcmVuY2VkIHJlc291cmNlIGluIFtbY3JlYXRlUmVzb3VyY2VdXS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByZXNvdXJjZSBOYW1lIG9mIHRoZSByZXNvdXJjZVxuICAgICAqIEBwYXJhbSB7VH0gaXRlbSBJdGVtIHRvIHVwZGF0ZVxuICAgICAqL1xuICAgIHVwZGF0ZUl0ZW08VD4ocmVzb3VyY2U6IHN0cmluZywgaXRlbTogVCk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFuIGl0ZW0gZnJvbSB0aGUgbW9jayBkYXRhYmFzZSBiYWNraW5nIHRoZSBzcGVjaWZpYyByZXNvdXJjZS5cbiAgICAgKiBJdGVtcyBhcmUgbWF0Y2hlZCBiYXNlZCBvbiB0aGUgcHJpbWFyeSBrZXkgY29uZmlndXJlZCBmb3IgdGhlIHJlZmVyZW5jZWRcbiAgICAgKiByZXNvdXJjZSBpbiBbW2NyZWF0ZVJlc291cmNlXV0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcmVzb3VyY2UgTmFtZSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGl0ZW1JZCBQcmltYXJ5IGtleSB2YWx1ZSBvZiB0aGUgaXRlbSB0byByZW1vdmVcbiAgICAgKi9cbiAgICByZW1vdmVJdGVtKHJlc291cmNlOiBzdHJpbmcsIGl0ZW1JZDogc3RyaW5nIHwgbnVtYmVyKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyZXMgYSBtb2NrIEdFVCByZXF1ZXN0IGhhbmRsZXIgZm9yIGEgc3BlY2lmaWMgcGF0aC4gVGhlIHBhdGggY2FuXG4gICAgICogZWl0aGVyIGJlIGEgc3RyaW5nIG9yIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8UmVnRXhwfSBwYXRoIFBhdGggdG8gcmVnaXN0ZXIgdGhlIGhhbmRsZXIgZm9yXG4gICAgICogQHBhcmFtIHtNb2NrUmVxdWVzdEhhbmRsZXI8VD59IGhhbmRsZXIgUmVxdWVzdCBoYW5kbGVyXG4gICAgICovXG4gICAgd2hlbkdldDxUPihwYXRoOiBzdHJpbmcgfCBSZWdFeHAsIGhhbmRsZXI6IE1vY2tSZXF1ZXN0SGFuZGxlcjxUPik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcmVzIGEgbW9jayBQT1NUIHJlcXVlc3QgaGFuZGxlciBmb3IgYSBzcGVjaWZpYyBwYXRoLiBUaGUgcGF0aCBjYW5cbiAgICAgKiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xSZWdFeHB9IHBhdGggUGF0aCB0byByZWdpc3RlciB0aGUgaGFuZGxlciBmb3JcbiAgICAgKiBAcGFyYW0ge01vY2tSZXF1ZXN0SGFuZGxlcjxUPn0gaGFuZGxlciBSZXF1ZXN0IGhhbmRsZXJcbiAgICAgKi9cbiAgICB3aGVuUG9zdDxUPihwYXRoOiBzdHJpbmcgfCBSZWdFeHAsIGhhbmRsZXI6IE1vY2tSZXF1ZXN0SGFuZGxlcjxUPik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcmVzIGEgbW9jayBQVVQgcmVxdWVzdCBoYW5kbGVyIGZvciBhIHNwZWNpZmljIHBhdGguIFRoZSBwYXRoIGNhblxuICAgICAqIGVpdGhlciBiZSBhIHN0cmluZyBvciBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfFJlZ0V4cH0gcGF0aCBQYXRoIHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgICAqIEBwYXJhbSB7TW9ja1JlcXVlc3RIYW5kbGVyPFQ+fSBoYW5kbGVyIFJlcXVlc3QgaGFuZGxlclxuICAgICAqL1xuICAgIHdoZW5QdXQ8VD4ocGF0aDogc3RyaW5nIHwgUmVnRXhwLCBoYW5kbGVyOiBNb2NrUmVxdWVzdEhhbmRsZXI8VD4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJlcyBhIG1vY2sgUEFUQ0ggcmVxdWVzdCBoYW5kbGVyIGZvciBhIHNwZWNpZmljIHBhdGguIFRoZSBwYXRoIGNhblxuICAgICAqIGVpdGhlciBiZSBhIHN0cmluZyBvciBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfFJlZ0V4cH0gcGF0aCBQYXRoIHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgICAqIEBwYXJhbSB7TW9ja1JlcXVlc3RIYW5kbGVyPFQ+fSBoYW5kbGVyIFJlcXVlc3QgaGFuZGxlclxuICAgICAqL1xuICAgIHdoZW5QYXRjaDxUPihwYXRoOiBzdHJpbmcgfCBSZWdFeHAsIGhhbmRsZXI6IE1vY2tSZXF1ZXN0SGFuZGxlcjxUPik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcmVzIGEgbW9jayBERUxFVEUgcmVxdWVzdCBoYW5kbGVyIGZvciBhIHNwZWNpZmljIHBhdGguIFRoZSBwYXRoIGNhblxuICAgICAqIGVpdGhlciBiZSBhIHN0cmluZyBvciBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfFJlZ0V4cH0gcGF0aCBQYXRoIHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgICAqIEBwYXJhbSB7TW9ja1JlcXVlc3RIYW5kbGVyPFQ+fSBoYW5kbGVyIFJlcXVlc3QgaGFuZGxlclxuICAgICAqL1xuICAgIHdoZW5EZWxldGU8VD4ocGF0aDogc3RyaW5nIHwgUmVnRXhwLCBoYW5kbGVyOiBNb2NrUmVxdWVzdEhhbmRsZXI8VD4pOiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgTW9ja09ic2VydmVyIHtcbiAgICBvYnNlcnZlcklkOiBzdHJpbmc7XG4gICAgcXVlcnk6IGFueTtcbiAgICBpdGVtczogXy5EaWN0aW9uYXJ5PGFueT47XG59XG5cbmludGVyZmFjZSBNb2NrSXRlbXMge1xuICAgIHByaW1hcnlLZXk6IHN0cmluZztcbiAgICBvYnNlcnZlcnM6IE1vY2tPYnNlcnZlcltdO1xuICAgIGl0ZW1zOiBhbnlbXTtcbiAgICBxdWVyeUV2YWx1YXRvcjogTW9ja1F1ZXJ5RXZhbHVhdG9yPGFueT47XG4gICAgYmxhY2tob2xlOiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgTW9ja0l0ZW1TdG9yZSB7XG4gICAgW2luZGV4OiBzdHJpbmddOiBNb2NrSXRlbXM7XG59XG5cbmludGVyZmFjZSBNb2NrUmVzcG9uc2VEZXNjcmlwdG9yIHtcbiAgICBwYXRoOiBzdHJpbmcgfCBSZWdFeHA7XG4gICAgaGFuZGxlcjogTW9ja1JlcXVlc3RIYW5kbGVyPGFueT47XG59XG5cbmludGVyZmFjZSBNb2NrUmVzcG9uc2VTdG9yZSB7XG4gICAgW21ldGhvZDogc3RyaW5nXTogTW9ja1Jlc3BvbnNlRGVzY3JpcHRvcltdO1xufVxuXG5jbGFzcyBNb2NrUXVlcnlPYnNlcnZlck1hbmFnZXIgZXh0ZW5kcyBRdWVyeU9ic2VydmVyTWFuYWdlciB7XG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVtb3ZlKG9ic2VydmVySWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLl9kZWxldGVPYnNlcnZlcihvYnNlcnZlcklkKTtcbiAgICAgICAgLy8gQ2FsbCB0aGUgdW5zdWJzY3JpYmUgbWV0aG9kIGltbWVkaWF0ZWx5IGR1cmluZyB0ZXN0cy4gVGhlIGFjdHVhbCBxdWVyeVxuICAgICAgICAvLyBvYnNlcnZlciBtYW5hZ2VyIHdpbGwgZGVmZXIgdGhlc2UgY2FsbHMgaW5zdGVhZC5cbiAgICAgICAgdGhpcy5fdW5zdWJzY3JpYmUob2JzZXJ2ZXJJZCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIC8vIFN1YnNjcmliZSB0byBwcm9jZXNzIHRoZSAobW9jaykgcmVxdWVzdC5cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgY2hhaW5BZnRlclVuc3Vic2NyaWJlPFQ+KG1ha2VPYnNlcnZhYmxlOiAoKSA9PiBSeC5PYnNlcnZhYmxlPFQ+KTogUnguT2JzZXJ2YWJsZTxUPiB7XG4gICAgICAgIC8vIERvIG5vdCBkZWZlciBtYWtlT2JzZXJ2YWJsZSBkdXJpbmcgdGVzdHMuXG4gICAgICAgIHJldHVybiBtYWtlT2JzZXJ2YWJsZSgpO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1vY2tDb25uZWN0aW9uIGltcGxlbWVudHMgQ29ubmVjdGlvbiwgTW9ja0Jhc2Uge1xuICAgIHByaXZhdGUgX2xvZ1VuaGFuZGxlZFJlcXVlc3RzOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfbW9ja0l0ZW1zOiBNb2NrSXRlbVN0b3JlID0ge307XG4gICAgcHJpdmF0ZSBfbW9ja1Jlc3BvbnNlczogTW9ja1Jlc3BvbnNlU3RvcmUgPSB7fTtcbiAgICBwcml2YXRlIF9tZXNzYWdlczogUnguU3ViamVjdDxNZXNzYWdlPjtcbiAgICBwcml2YXRlIF9pc0Nvbm5lY3RlZDogUnguQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+O1xuICAgIHByaXZhdGUgX3F1ZXJ5T2JzZXJ2ZXJNYW5hZ2VyOiBRdWVyeU9ic2VydmVyTWFuYWdlcjtcbiAgICBwcml2YXRlIF9lcnJvcnM6IFJ4LlN1YmplY3Q8QVBJRXJyb3I+O1xuICAgIHByaXZhdGUgX3NpbXVsYXRlRGVsYXk6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLl9tZXNzYWdlcyA9IG5ldyBSeC5TdWJqZWN0PE1lc3NhZ2U+KCk7XG4gICAgICAgIHRoaXMuX2lzQ29ubmVjdGVkID0gbmV3IFJ4LkJlaGF2aW9yU3ViamVjdChmYWxzZSk7XG4gICAgICAgIHRoaXMuX2Vycm9ycyA9IG5ldyBSeC5TdWJqZWN0PEFQSUVycm9yPigpO1xuICAgICAgICB0aGlzLl9xdWVyeU9ic2VydmVyTWFuYWdlciA9IG5ldyBNb2NrUXVlcnlPYnNlcnZlck1hbmFnZXIodGhpcywgdGhpcy5fZXJyb3JzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBjb25uZWN0KHJlc3RVcmk6IHN0cmluZywgd2Vic29ja2V0VXJpOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5faXNDb25uZWN0ZWQub25OZXh0KHRydWUpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VzKCkuc3Vic2NyaWJlKHRoaXMuX3F1ZXJ5T2JzZXJ2ZXJNYW5hZ2VyLnVwZGF0ZS5iaW5kKHRoaXMuX3F1ZXJ5T2JzZXJ2ZXJNYW5hZ2VyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZGlzY29ubmVjdCgpIHtcbiAgICAgICAgdGhpcy5faXNDb25uZWN0ZWQub25OZXh0KGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBpc0Nvbm5lY3RlZCgpOiBSeC5PYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzQ29ubmVjdGVkO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3JlZ2lzdGVyTW9ja1JlcXVlc3RIYW5kbGVyPFQ+KG1ldGhvZDogc3RyaW5nLCBwYXRoOiBzdHJpbmcgfCBSZWdFeHAsIGhhbmRsZXI6IE1vY2tSZXF1ZXN0SGFuZGxlcjxUPikge1xuICAgICAgICBpZiAoIXRoaXMuX21vY2tSZXNwb25zZXNbbWV0aG9kXSkgdGhpcy5fbW9ja1Jlc3BvbnNlc1ttZXRob2RdID0gW107XG4gICAgICAgIGNvbnN0IGhhbmRsZXJzID0gdGhpcy5fbW9ja1Jlc3BvbnNlc1ttZXRob2RdO1xuXG4gICAgICAgIGlmIChfLmFueShoYW5kbGVycywgKGV4aXN0aW5nSGFuZGxlcikgPT4gZXhpc3RpbmdIYW5kbGVyLnBhdGggPT09IHBhdGgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBNZXRob2QgJHttZXRob2R9IGZvciBwYXRoICR7cGF0aH0gYWxyZWFkeSByZWdpc3RlcmVkYCk7XG4gICAgICAgIH1cblxuICAgICAgICBoYW5kbGVycy5wdXNoKHtcbiAgICAgICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgICAgICBoYW5kbGVyOiBoYW5kbGVyLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9oYW5kbGVNb2NrUmVzcG9uc2UobWV0aG9kOiBzdHJpbmcsIHJlc3BvbnNlUGF0aDogc3RyaW5nLCBwYXJhbWV0ZXJzOiBhbnksIGRhdGE6IGFueSk6IFJ4Lk9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIGNvbnN0IG1hdGNoaW5nSGFuZGxlcnMgPSBfLmZpbHRlcih0aGlzLl9tb2NrUmVzcG9uc2VzW21ldGhvZF0sIChtYXRjaCkgPT4ge1xuICAgICAgICAgICAgaWYgKG1hdGNoLnBhdGggaW5zdGFuY2VvZiBSZWdFeHApIHJldHVybiBtYXRjaC5wYXRoLnRlc3QocmVzcG9uc2VQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaC5wYXRoID09PSByZXNwb25zZVBhdGg7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChfLmlzRW1wdHkobWF0Y2hpbmdIYW5kbGVycykpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9sb2dVbmhhbmRsZWRSZXF1ZXN0cykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHByZXR0eVBhdGggPSBkZWNvZGVVUklDb21wb25lbnQodGhpcy5jcmVhdGVVcmlGcm9tUGF0aChyZXNwb25zZVBhdGgsIHBhcmFtZXRlcnMpKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oYE1vY2sgQVBJICR7bWV0aG9kfTogJHtwcmV0dHlQYXRofSByZXF1ZXN0ZWQsIGJ1dCBkaWRudCBtYXRjaCBhbnkgaGFuZGxlcmAsIHtcbiAgICAgICAgICAgICAgICAgICAgbW9ja0l0ZW1zOiBfLmtleXModGhpcy5fbW9ja0l0ZW1zKSxcbiAgICAgICAgICAgICAgICAgICAgbG9va2VkRm9yTW9ja0l0ZW06IHJlc3BvbnNlUGF0aC5zcGxpdCgnLycpLnNsaWNlKDIpLmpvaW4oJy8nKSxcbiAgICAgICAgICAgICAgICAgICAgbW9ja1Jlc3BvbnNlczogdGhpcy5fbW9ja1Jlc3BvbnNlc1ttZXRob2RdLFxuICAgICAgICAgICAgICAgICAgICBsb29rZWRGb3JNb2NrUmVzcG9uc2U6IHJlc3BvbnNlUGF0aCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBSeC5PYnNlcnZhYmxlLmp1c3Qoe30pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKF8uc2l6ZShtYXRjaGluZ0hhbmRsZXJzKSA+IDEpIHtcbiAgICAgICAgICAgIGNv