@ortoo/angular-resource
Version:
Magical CRUD resource management for angular
262 lines • 35.7 kB
JavaScript
// tslint:disable only-arrow-functions
import { EventEmitter } from './emitter';
import { uniq } from 'lodash';
import { isFunction } from 'lodash';
import { isString } from 'lodash';
import { isUndefined } from 'lodash';
import * as utils from './utils';
export function createServerResourceFactory(socket) {
function ServerResourceFactory(url, rootKey, rootKeyPlural) {
let sock = socket(url, rootKey, rootKeyPlural);
// Object holding the resources (keys are the object ids)
let _resources = {};
let _internalRes = {};
function toObject() {
return utils.toObject(this);
}
// Returns the object or a list of objects (depending on ids passed in)
// The array or object will have the $promise attribute to use.
function get(ids, force, transform) {
if (isFunction(force)) {
transform = force;
force = false;
}
if (!transform) {
transform = (val) => { return val; };
}
let singleId = false;
let results = [];
function transformResults() {
if (singleId) {
return results[0];
}
else {
return results;
}
}
// If we've been passed
if (isString(ids)) {
singleId = true;
ids = [ids];
}
// Make sure we have no repeated items in the array
ids = uniq(ids);
// Go and load in the results, compiling a list of resources we need to go and fetch
let unknownIds = [];
ids.forEach(function (id) {
let res = _resources[id];
if (res) {
results.push(transform(res, id));
// If we are forcing then we want to go and refetch assuming we've already resolved
// If we haven't resolved then we are going to refresh the data anyway so don't do
// anything here. If we aren't resolved and we aren't fetching then we want to
// go and refresh the data because we could have been created from somewhere that
// isn't the server
if ((force && res.$resolved) || !(res.$resolved || res.$fetching)) {
unknownIds.push(id);
res.$fetching = true;
// If we've already resolved then create a new promise object on the resource
if (res.$resolved) {
res.$deferred = new utils.Deferred();
res.$promise = this.$deferred.promise;
res.$resolved = false;
}
}
}
else {
// Haven't seen this id yet. Create a new resource and store it off
res = _resources[id] = (new ServerResource());
res.$fetching = true;
results.push(transform(res, id));
unknownIds.push(id);
}
});
// Do we have any ids to fetch. If so go and get them
if (unknownIds.length > 0) {
let req = sock.get(unknownIds);
req.then(function (response) {
// We might not get a response (say if the app is offline). In this case
// we just resolve everything as is.
if (isUndefined(response)) {
unknownIds.forEach(function (id) {
let res = _resources[id];
res.$fetching = false;
if (!res.$resolved) {
res.$resolved = true;
res.$deferred.resolve(res);
}
});
}
else {
response.forEach(function (resdata) {
if (resdata._id) {
let id = resdata._id;
let res = _resources[id];
res.$fetching = false;
updateVal(res, resdata);
// We've got the data for the first time - resolve the deferred
if (!res.$resolved) {
res.$deferred.resolve(res);
res.$resolved = true;
}
}
});
// If any of our unknown ids hasn't been resolved then we assume its deleted...
unknownIds.forEach(function (id) {
let res = _resources[id];
if (!res) {
return;
}
res.$fetching = false;
if (!res.$resolved) {
res.$deleted = true;
res.$emitter.emit('update', null, res.$toObject());
}
});
}
}, function (reason) {
// Handle an error...
// Clean up any of our unknown ids - we don't know about them
unknownIds.forEach(function (id) {
let res = _resources[id];
res.$fetching = false;
res.$deferred.reject(reason);
delete _resources[id];
});
});
}
if (!singleId) {
// Wait for all the promises to be resolved before resolving
let promises = [];
results.forEach(function (res) {
promises.push(res.$promise);
});
let tmpProm = Promise.all(promises);
results.$promise = tmpProm.then(function () {
// Return the results array as we resolve
return results;
});
}
return transformResults();
}
// Perform a save
function save(patch) {
utils.applyPatch(this, patch);
// We update if we have an _id - otherwise we create.
if (this._id) {
return updateResource(this, patch);
}
else {
// This is an initial create
return createResource(this);
}
}
function updateResource(res, patch) {
let req = sock.patch(res._id, patch);
return req.then(function (response) {
updateVal(res, response);
// Resolve the deferred
_resources[res._id] = res;
if (!res.$resolved) {
res.$deferred.resolve(res);
res.$resolved = true;
}
return res;
}).catch(function (reason) {
// Something went wrong - go and fetch the object again so we are up to date
if (res._id) {
res.$refresh();
}
throw reason;
});
}
function createResource(res) {
let data = res.$toObject();
let req = sock.create(data);
return req.then(function (response) {
// There could be a race condition here where we could end up creating the id map
// earlier (maybe...?)
updateVal(res, response);
_resources[res._id] = res;
if (!res.$resolved) {
res.$deferred.resolve(res);
res.$resolved = true;
}
});
}
function remove() {
let res = this;
res.$deleted = true;
let req = sock.remove(res._id);
return req.then(function (response) {
if (response) {
delete _resources[res._id];
}
else {
res.$deleted = false;
}
return response;
});
}
// Updates the value from the server
function updateVal(res, val) {
// Do we have a null value (indicating the resource has been deleted?)
if (val) {
// Convert any JSON dates into dates
val = utils.convertJsonDates(val);
let oldData = res.$toObject();
utils.removeResValues(res);
utils.setResValues(res, val);
// Make sure we have store this resource off
_resources[res._id] = res;
res.$emitter.emit('update', res.$toObject(), oldData);
}
else {
// Deleted - clean me up scotty
delete _resources[res._id];
res.$emitter.emit('update', null, res.$toObject());
}
}
function _updateVal(val) {
return updateVal(this, val);
}
function refresh() {
if (this._id) {
get(this._id, true);
}
}
// The main constructor for theServerResource class
function ServerResourceConstructor(val, id) {
let res = this;
this.$emitter = new EventEmitter();
this.$deferred = new utils.Deferred();
this.$promise = this.$deferred.promise; // An initial promise for our initial
// fetch or create of data
this.$resolved = false; // Have we had an initial resolution of the promise
this.$deleted = false; // Has the resource been deleted
this.$fetching = false; // Are we currently fetching data for this resource
this.$id = id ? id : utils.uuid();
_internalRes[this.$id] = this;
if (val) {
for (let key of Object.keys(val)) {
res[key] = val[key];
}
}
// If we have an id then add us to the store
if (this._id) {
_resources[this._id] = this;
}
}
const ServerResource = ServerResourceConstructor;
ServerResource.get = get;
ServerResource.prototype.$save = save;
ServerResource.prototype.$remove = remove;
ServerResource.prototype.$delete = remove;
ServerResource.prototype.$refresh = refresh;
ServerResource.prototype.$toObject = toObject;
ServerResource.prototype.$updateVal = _updateVal;
return ServerResource;
}
return ServerResourceFactory;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6Ii9Ab3J0b28vYW5ndWxhci1yZXNvdXJjZS8iLCJzb3VyY2VzIjpbInNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUd6QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRXJDLE9BQU8sS0FBSyxLQUFLLE1BQU0sU0FBUyxDQUFDO0FBRWpDLE1BQU0sc0NBQXNDLE1BQXFCO0lBRS9ELCtCQUErQixHQUFXLEVBQUUsT0FBZSxFQUFFLGFBQXFCO1FBQ2hGLElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBRS9DLHlEQUF5RDtRQUN6RCxJQUFJLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDcEIsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBRXRCO1lBQ0UsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUIsQ0FBQztRQUVELHVFQUF1RTtRQUN2RSwrREFBK0Q7UUFDL0QsYUFBYSxHQUF3QixFQUFFLEtBQWUsRUFBRSxTQUFvQjtZQUUxRSxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN0QixTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUNsQixLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ2hCLENBQUM7WUFFRCxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsU0FBUyxHQUFHLENBQUMsR0FBUSxP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QUFDLENBQUM7Z0JBQ2IsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7WUFDOUIsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLGNBQWMsR0FBb0IseUJBQXlCLENBQUM7UUFDbEUsY0FBYyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFFekIsY0FBYyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ3RDLGNBQWMsQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUMxQyxjQUFjLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7UUFDMUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQzVDLGNBQWMsQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQztRQUM5QyxjQUFjLENBQUMsU0FBUyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFFakQsTUFBTSxDQUFDLGNBQWMsQ0FBQztJQUN4QixDQUFDO0lBRUQsTUFBTSxDQUFDLHFCQUFxQixDQUFDO0FBQy9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSBvbmx5LWFycm93LWZ1bmN0aW9uc1xuXG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICcuL2VtaXR0ZXInO1xuaW1wb3J0IHsgSlNPTlBhdGNoLCBNb2RlbEFycmF5LCBTZXJ2ZXJNb2RlbCwgU2VydmVyUmVzb3VyY2UgYXMgSVNlcnZlclJlc291cmNlLCBTb2NrZXRGYWN0b3J5IH0gZnJvbSAnLi90eXBlcyc7XG5cbmltcG9ydCB7IHVuaXEgfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgaXNGdW5jdGlvbiB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBpc1VuZGVmaW5lZCB9IGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VydmVyUmVzb3VyY2VGYWN0b3J5KHNvY2tldDogU29ja2V0RmFjdG9yeSkge1xuXG4gIGZ1bmN0aW9uIFNlcnZlclJlc291cmNlRmFjdG9yeSh1cmw6IHN0cmluZywgcm9vdEtleTogc3RyaW5nLCByb290S2V5UGx1cmFsOiBzdHJpbmcpOiBJU2VydmVyUmVzb3VyY2Uge1xuICAgIGxldCBzb2NrID0gc29ja2V0KHVybCwgcm9vdEtleSwgcm9vdEtleVBsdXJhbCk7XG5cbiAgICAvLyBPYmplY3QgaG9sZGluZyB0aGUgcmVzb3VyY2VzIChrZXlzIGFyZSB0aGUgb2JqZWN0IGlkcylcbiAgICBsZXQgX3Jlc291cmNlcyA9IHt9O1xuICAgIGxldCBfaW50ZXJuYWxSZXMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIHRvT2JqZWN0KCkge1xuICAgICAgcmV0dXJuIHV0aWxzLnRvT2JqZWN0KHRoaXMpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgdGhlIG9iamVjdCBvciBhIGxpc3Qgb2Ygb2JqZWN0cyAoZGVwZW5kaW5nIG9uIGlkcyBwYXNzZWQgaW4pXG4gICAgLy8gVGhlIGFycmF5IG9yIG9iamVjdCB3aWxsIGhhdmUgdGhlICRwcm9taXNlIGF0dHJpYnV0ZSB0byB1c2UuXG4gICAgZnVuY3Rpb24gZ2V0KGlkczogKHN0cmluZ1tdIHwgc3RyaW5nKSwgZm9yY2U/OiBib29sZWFuLCB0cmFuc2Zvcm0/OiBGdW5jdGlvbikge1xuXG4gICAgICBpZiAoaXNGdW5jdGlvbihmb3JjZSkpIHtcbiAgICAgICAgdHJhbnNmb3JtID0gZm9yY2U7XG4gICAgICAgIGZvcmNlID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICghdHJhbnNmb3JtKSB7XG4gICAgICAgIHRyYW5zZm9ybSA9ICh2YWw6IGFueSkgPT4geyByZXR1cm4gdmFsOyB9O1xuICAgICAgfVxuXG4gICAgICBsZXQgc2luZ2xlSWQgPSBmYWxzZTtcbiAgICAgIGxldCByZXN1bHRzOiBNb2RlbEFycmF5PFNlcnZlck1vZGVsPiA9IFtdO1xuXG4gICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1SZXN1bHRzKCkge1xuICAgICAgICBpZiAoc2luZ2xlSWQpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0c1swXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiB3ZSd2ZSBiZWVuIHBhc3NlZFxuICAgICAgaWYgKGlzU3RyaW5nKGlkcykpIHtcbiAgICAgICAgc2luZ2xlSWQgPSB0cnVlO1xuICAgICAgICBpZHMgPSBbaWRzXTtcbiAgICAgIH1cblxuICAgICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgbm8gcmVwZWF0ZWQgaXRlbXMgaW4gdGhlIGFycmF5XG4gICAgICBpZHMgPSB1bmlxKGlkcyk7XG5cbiAgICAgIC8vIEdvIGFuZCBsb2FkIGluIHRoZSByZXN1bHRzLCBjb21waWxpbmcgYSBsaXN0IG9mIHJlc291cmNlcyB3ZSBuZWVkIHRvIGdvIGFuZCBmZXRjaFxuICAgICAgbGV0IHVua25vd25JZHM6IHN0cmluZ1tdID0gW107XG4gICAgICBpZHMuZm9yRWFjaChmdW5jdGlvbihpZCkge1xuICAgICAgICBsZXQgcmVzOiBTZXJ2ZXJNb2RlbCA9IF9yZXNvdXJjZXNbaWRdO1xuICAgICAgICBpZiAocmVzKSB7XG4gICAgICAgICAgcmVzdWx0cy5wdXNoKHRyYW5zZm9ybShyZXMsIGlkKSk7XG5cbiAgICAgICAgICAvLyBJZiB3ZSBhcmUgZm9yY2luZyB0aGVuIHdlIHdhbnQgdG8gZ28gYW5kIHJlZmV0Y2ggYXNzdW1pbmcgd2UndmUgYWxyZWFkeSByZXNvbHZlZFxuICAgICAgICAgIC8vIElmIHdlIGhhdmVuJ3QgcmVzb2x2ZWQgdGhlbiB3ZSBhcmUgZ29pbmcgdG8gcmVmcmVzaCB0aGUgZGF0YSBhbnl3YXkgc28gZG9uJ3QgZG9cbiAgICAgICAgICAvLyBhbnl0aGluZyBoZXJlLiBJZiB3ZSBhcmVuJ3QgcmVzb2x2ZWQgYW5kIHdlIGFyZW4ndCBmZXRjaGluZyB0aGVuIHdlIHdhbnQgdG9cbiAgICAgICAgICAvLyBnbyBhbmQgcmVmcmVzaCB0aGUgZGF0YSBiZWNhdXNlIHdlIGNvdWxkIGhhdmUgYmVlbiBjcmVhdGVkIGZyb20gc29tZXdoZXJlIHRoYXRcbiAgICAgICAgICAvLyBpc24ndCB0aGUgc2VydmVyXG4gICAgICAgICAgaWYgKChmb3JjZSAmJiByZXMuJHJlc29sdmVkKSB8fCAhKHJlcy4kcmVzb2x2ZWQgfHwgcmVzLiRmZXRjaGluZykpIHtcbiAgICAgICAgICAgIHVua25vd25JZHMucHVzaChpZCk7XG4gICAgICAgICAgICByZXMuJGZldGNoaW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgd2UndmUgYWxyZWFkeSByZXNvbHZlZCB0aGVuIGNyZWF0ZSBhIG5ldyBwcm9taXNlIG9iamVjdCBvbiB0aGUgcmVzb3VyY2VcbiAgICAgICAgICAgIGlmIChyZXMuJHJlc29sdmVkKSB7XG4gICAgICAgICAgICAgIHJlcy4kZGVmZXJyZWQgPSBuZXcgdXRpbHMuRGVmZXJyZWQ8U2VydmVyTW9kZWw+KCk7XG4gICAgICAgICAgICAgIHJlcy4kcHJvbWlzZSA9IHRoaXMuJGRlZmVycmVkLnByb21pc2U7XG4gICAgICAgICAgICAgIHJlcy4kcmVzb2x2ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSGF2ZW4ndCBzZWVuIHRoaXMgaWQgeWV0LiBDcmVhdGUgYSBuZXcgcmVzb3VyY2UgYW5kIHN0b3JlIGl0IG9mZlxuICAgICAgICAgIHJlcyA9IF9yZXNvdXJjZXNbaWRdID0gPFNlcnZlck1vZGVsPiAobmV3ICg8YW55PiBTZXJ2ZXJSZXNvdXJjZSkoKSk7XG4gICAgICAgICAgcmVzLiRmZXRjaGluZyA9IHRydWU7XG4gICAgICAgICAgcmVzdWx0cy5wdXNoKHRyYW5zZm9ybShyZXMsIGlkKSk7XG4gICAgICAgICAgdW5rbm93bklkcy5wdXNoKGlkKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIERvIHdlIGhhdmUgYW55IGlkcyB0byBmZXRjaC4gSWYgc28gZ28gYW5kIGdldCB0aGVtXG4gICAgICBpZiAodW5rbm93bklkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxldCByZXEgPSBzb2NrLmdldCh1bmtub3duSWRzKTtcbiAgICAgICAgcmVxLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2U6IGFueSkge1xuXG4gICAgICAgICAgLy8gV2UgbWlnaHQgbm90IGdldCBhIHJlc3BvbnNlIChzYXkgaWYgdGhlIGFwcCBpcyBvZmZsaW5lKS4gSW4gdGhpcyBjYXNlXG4gICAgICAgICAgLy8gd2UganVzdCByZXNvbHZlIGV2ZXJ5dGhpbmcgYXMgaXMuXG4gICAgICAgICAgaWYgKGlzVW5kZWZpbmVkKHJlc3BvbnNlKSkge1xuICAgICAgICAgICAgdW5rbm93bklkcy5mb3JFYWNoKGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgICAgICAgIGxldCByZXMgPSBfcmVzb3VyY2VzW2lkXTtcbiAgICAgICAgICAgICAgcmVzLiRmZXRjaGluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgIGlmICghcmVzLiRyZXNvbHZlZCkge1xuICAgICAgICAgICAgICAgIHJlcy4kcmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJlcy4kZGVmZXJyZWQucmVzb2x2ZShyZXMpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UuZm9yRWFjaChmdW5jdGlvbihyZXNkYXRhOiBhbnkpIHtcbiAgICAgICAgICAgICAgaWYgKHJlc2RhdGEuX2lkKSB7XG4gICAgICAgICAgICAgICAgbGV0IGlkID0gcmVzZGF0YS5faWQ7XG4gICAgICAgICAgICAgICAgbGV0IHJlcyA9IF9yZXNvdXJjZXNbaWRdO1xuICAgICAgICAgICAgICAgIHJlcy4kZmV0Y2hpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB1cGRhdGVWYWwocmVzLCByZXNkYXRhKTtcblxuICAgICAgICAgICAgICAgIC8vIFdlJ3ZlIGdvdCB0aGUgZGF0YSBmb3IgdGhlIGZpcnN0IHRpbWUgLSByZXNvbHZlIHRoZSBkZWZlcnJlZFxuICAgICAgICAgICAgICAgIGlmICghcmVzLiRyZXNvbHZlZCkge1xuICAgICAgICAgICAgICAgICAgcmVzLiRkZWZlcnJlZC5yZXNvbHZlKHJlcyk7XG4gICAgICAgICAgICAgICAgICByZXMuJHJlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBJZiBhbnkgb2Ygb3VyIHVua25vd24gaWRzIGhhc24ndCBiZWVuIHJlc29sdmVkIHRoZW4gd2UgYXNzdW1lIGl0cyBkZWxldGVkLi4uXG4gICAgICAgICAgICB1bmtub3duSWRzLmZvckVhY2goZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgICAgbGV0IHJlcyA9IF9yZXNvdXJjZXNbaWRdO1xuICAgICAgICAgICAgICBpZiAoIXJlcykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHJlcy4kZmV0Y2hpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgaWYgKCFyZXMuJHJlc29sdmVkKSB7XG4gICAgICAgICAgICAgICAgcmVzLiRkZWxldGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXMuJGVtaXR0ZXIuZW1pdCgndXBkYXRlJywgbnVsbCwgcmVzLiR0b09iamVjdCgpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCBmdW5jdGlvbihyZWFzb246IGFueSkge1xuICAgICAgICAgIC8vIEhhbmRsZSBhbiBlcnJvci4uLlxuICAgICAgICAgIC8vIENsZWFuIHVwIGFueSBvZiBvdXIgdW5rbm93biBpZHMgLSB3ZSBkb24ndCBrbm93IGFib3V0IHRoZW1cbiAgICAgICAgICB1bmtub3duSWRzLmZvckVhY2goZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgIGxldCByZXMgPSBfcmVzb3VyY2VzW2lkXTtcbiAgICAgICAgICAgIHJlcy4kZmV0Y2hpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlcy4kZGVmZXJyZWQucmVqZWN0KHJlYXNvbik7XG4gICAgICAgICAgICBkZWxldGUgX3Jlc291cmNlc1tpZF07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXNpbmdsZUlkKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIGFsbCB0aGUgcHJvbWlzZXMgdG8gYmUgcmVzb2x2ZWQgYmVmb3JlIHJlc29sdmluZ1xuICAgICAgICBsZXQgcHJvbWlzZXM6IEFycmF5PFByb21pc2U8YW55Pj4gPSBbXTtcbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKGZ1bmN0aW9uKHJlcykge1xuICAgICAgICAgIHByb21pc2VzLnB1c2gocmVzLiRwcm9taXNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IHRtcFByb20gPSBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgIHJlc3VsdHMuJHByb21pc2UgPSB0bXBQcm9tLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLy8gUmV0dXJuIHRoZSByZXN1bHRzIGFycmF5IGFzIHdlIHJlc29sdmVcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cmFuc2Zvcm1SZXN1bHRzKCk7XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBhIHNhdmVcbiAgICBmdW5jdGlvbiBzYXZlKHRoaXM6IFNlcnZlck1vZGVsLCBwYXRjaDogSlNPTlBhdGNoKSB7XG4gICAgICB1dGlscy5hcHBseVBhdGNoKHRoaXMsIHBhdGNoKTtcblxuICAgICAgLy8gV2UgdXBkYXRlIGlmIHdlIGhhdmUgYW4gX2lkIC0gb3RoZXJ3aXNlIHdlIGNyZWF0ZS5cbiAgICAgIGlmICh0aGlzLl9pZCkge1xuICAgICAgICByZXR1cm4gdXBkYXRlUmVzb3VyY2UodGhpcywgcGF0Y2gpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVGhpcyBpcyBhbiBpbml0aWFsIGNyZWF0ZVxuICAgICAgICByZXR1cm4gY3JlYXRlUmVzb3VyY2UodGhpcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlUmVzb3VyY2UocmVzOiBhbnksIHBhdGNoOiBKU09OUGF0Y2gpIHtcbiAgICAgIGxldCByZXEgPSBzb2NrLnBhdGNoKHJlcy5faWQsIHBhdGNoKTtcbiAgICAgIHJldHVybiByZXEudGhlbihmdW5jdGlvbihyZXNwb25zZTogYW55KSB7XG4gICAgICAgIHVwZGF0ZVZhbChyZXMsIHJlc3BvbnNlKTtcbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgZGVmZXJyZWRcbiAgICAgICAgX3Jlc291cmNlc1tyZXMuX2lkXSA9IHJlcztcbiAgICAgICAgaWYgKCFyZXMuJHJlc29sdmVkKSB7XG4gICAgICAgICAgcmVzLiRkZWZlcnJlZC5yZXNvbHZlKHJlcyk7XG4gICAgICAgICAgcmVzLiRyZXNvbHZlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuXG4gICAgICB9KS5jYXRjaChmdW5jdGlvbihyZWFzb246IGFueSkge1xuICAgICAgICAvLyBTb21ldGhpbmcgd2VudCB3cm9uZyAtIGdvIGFuZCBmZXRjaCB0aGUgb2JqZWN0IGFnYWluIHNvIHdlIGFyZSB1cCB0byBkYXRlXG4gICAgICAgIGlmIChyZXMuX2lkKSB7XG4gICAgICAgICAgcmVzLiRyZWZyZXNoKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyByZWFzb247XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVSZXNvdXJjZShyZXM6IGFueSkge1xuICAgICAgbGV0IGRhdGEgPSByZXMuJHRvT2JqZWN0KCk7XG5cbiAgICAgIGxldCByZXEgPSBzb2NrLmNyZWF0ZShkYXRhKTtcbiAgICAgIHJldHVybiByZXEudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAvLyBUaGVyZSBjb3VsZCBiZSBhIHJhY2UgY29uZGl0aW9uIGhlcmUgd2hlcmUgd2UgY291bGQgZW5kIHVwIGNyZWF0aW5nIHRoZSBpZCBtYXBcbiAgICAgICAgLy8gZWFybGllciAobWF5YmUuLi4/KVxuICAgICAgICB1cGRhdGVWYWwocmVzLCByZXNwb25zZSk7XG4gICAgICAgIF9yZXNvdXJjZXNbcmVzLl9pZF0gPSByZXM7XG5cbiAgICAgICAgaWYgKCFyZXMuJHJlc29sdmVkKSB7XG4gICAgICAgICAgcmVzLiRkZWZlcnJlZC5yZXNvbHZlKHJlcyk7XG4gICAgICAgICAgcmVzLiRyZXNvbHZlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbW92ZSgpIHtcblxuICAgICAgbGV0IHJlcyA9IHRoaXM7XG4gICAgICByZXMuJGRlbGV0ZWQgPSB0cnVlO1xuXG4gICAgICBsZXQgcmVxID0gc29jay5yZW1vdmUocmVzLl9pZCk7XG4gICAgICByZXR1cm4gcmVxLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgZGVsZXRlIF9yZXNvdXJjZXNbcmVzLl9pZF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzLiRkZWxldGVkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGVzIHRoZSB2YWx1ZSBmcm9tIHRoZSBzZXJ2ZXJcbiAgICBmdW5jdGlvbiB1cGRhdGVWYWwocmVzOiBhbnksIHZhbDogYW55KSB7XG5cbiAgICAgIC8vIERvIHdlIGhhdmUgYSBudWxsIHZhbHVlIChpbmRpY2F0aW5nIHRoZSByZXNvdXJjZSBoYXMgYmVlbiBkZWxldGVkPylcbiAgICAgIGlmICh2YWwpIHtcbiAgICAgICAgLy8gQ29udmVydCBhbnkgSlNPTiBkYXRlcyBpbnRvIGRhdGVzXG4gICAgICAgIHZhbCA9IHV0aWxzLmNvbnZlcnRKc29uRGF0ZXModmFsKTtcblxuICAgICAgICBsZXQgb2xkRGF0YSA9IHJlcy4kdG9PYmplY3QoKTtcbiAgICAgICAgdXRpbHMucmVtb3ZlUmVzVmFsdWVzKHJlcyk7XG4gICAgICAgIHV0aWxzLnNldFJlc1ZhbHVlcyhyZXMsIHZhbCk7XG5cbiAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgc3RvcmUgdGhpcyByZXNvdXJjZSBvZmZcbiAgICAgICAgX3Jlc291cmNlc1tyZXMuX2lkXSA9IHJlcztcbiAgICAgICAgcmVzLiRlbWl0dGVyLmVtaXQoJ3VwZGF0ZScsIHJlcy4kdG9PYmplY3QoKSwgb2xkRGF0YSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEZWxldGVkIC0gY2xlYW4gbWUgdXAgc2NvdHR5XG4gICAgICAgIGRlbGV0ZSBfcmVzb3VyY2VzW3Jlcy5faWRdO1xuICAgICAgICByZXMuJGVtaXR0ZXIuZW1pdCgndXBkYXRlJywgbnVsbCwgcmVzLiR0b09iamVjdCgpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfdXBkYXRlVmFsKHRoaXM6IFNlcnZlck1vZGVsLCB2YWw6IGFueSkge1xuICAgICAgcmV0dXJuIHVwZGF0ZVZhbCh0aGlzLCB2YWwpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlZnJlc2godGhpczogU2VydmVyTW9kZWwpIHtcbiAgICAgIGlmICh0aGlzLl9pZCkge1xuICAgICAgICBnZXQodGhpcy5faWQsIHRydWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRoZSBtYWluIGNvbnN0cnVjdG9yIGZvciB0aGVTZXJ2ZXJSZXNvdXJjZSBjbGFzc1xuICAgIGZ1bmN0aW9uIFNlcnZlclJlc291cmNlQ29uc3RydWN0b3IodmFsPzogYW55LCBpZD86IHN0cmluZyk6IHZvaWQge1xuICAgICAgbGV0IHJlcyA9IHRoaXM7XG4gICAgICB0aGlzLiRlbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgICB0aGlzLiRkZWZlcnJlZCA9IG5ldyB1dGlscy5EZWZlcnJlZCgpO1xuICAgICAgdGhpcy4kcHJvbWlzZSA9IHRoaXMuJGRlZmVycmVkLnByb21pc2U7IC8vIEFuIGluaXRpYWwgcHJvbWlzZSBmb3Igb3VyIGluaXRpYWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmZXRjaCBvciBjcmVhdGUgb2YgZGF0YVxuICAgICAgdGhpcy4kcmVzb2x2ZWQgPSBmYWxzZTsgLy8gSGF2ZSB3ZSBoYWQgYW4gaW5pdGlhbCByZXNvbHV0aW9uIG9mIHRoZSBwcm9taXNlXG4gICAgICB0aGlzLiRkZWxldGVkID0gZmFsc2U7IC8vIEhhcyB0aGUgcmVzb3VyY2UgYmVlbiBkZWxldGVkXG4gICAgICB0aGlzLiRmZXRjaGluZyA9IGZhbHNlOyAvLyBBcmUgd2UgY3VycmVudGx5IGZldGNoaW5nIGRhdGEgZm9yIHRoaXMgcmVzb3VyY2VcblxuICAgICAgdGhpcy4kaWQgPSBpZCA/IGlkIDogdXRpbHMudXVpZCgpO1xuXG4gICAgICBfaW50ZXJuYWxSZXNbdGhpcy4kaWRdID0gdGhpcztcblxuICAgICAgaWYgKHZhbCkge1xuICAgICAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXModmFsKSkge1xuICAgICAgICAgIHJlc1trZXldID0gdmFsW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSWYgd2UgaGF2ZSBhbiBpZCB0aGVuIGFkZCB1cyB0byB0aGUgc3RvcmVcbiAgICAgIGlmICh0aGlzLl9pZCkge1xuICAgICAgICBfcmVzb3VyY2VzW3RoaXMuX2lkXSA9IHRoaXM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgU2VydmVyUmVzb3VyY2U6IElTZXJ2ZXJSZXNvdXJjZSA9IFNlcnZlclJlc291cmNlQ29uc3RydWN0b3I7XG4gICAgU2VydmVyUmVzb3VyY2UuZ2V0ID0gZ2V0O1xuXG4gICAgU2VydmVyUmVzb3VyY2UucHJvdG90eXBlLiRzYXZlID0gc2F2ZTtcbiAgICBTZXJ2ZXJSZXNvdXJjZS5wcm90b3R5cGUuJHJlbW92ZSA9IHJlbW92ZTtcbiAgICBTZXJ2ZXJSZXNvdXJjZS5wcm90b3R5cGUuJGRlbGV0ZSA9IHJlbW92ZTtcbiAgICBTZXJ2ZXJSZXNvdXJjZS5wcm90b3R5cGUuJHJlZnJlc2ggPSByZWZyZXNoO1xuICAgIFNlcnZlclJlc291cmNlLnByb3RvdHlwZS4kdG9PYmplY3QgPSB0b09iamVjdDtcbiAgICBTZXJ2ZXJSZXNvdXJjZS5wcm90b3R5cGUuJHVwZGF0ZVZhbCA9IF91cGRhdGVWYWw7XG5cbiAgICByZXR1cm4gU2VydmVyUmVzb3VyY2U7XG4gIH1cblxuICByZXR1cm4gU2VydmVyUmVzb3VyY2VGYWN0b3J5O1xufVxuIl19