UNPKG

@ortoo/angular-resource

Version:

Magical CRUD resource management for angular

262 lines 35.7 kB
// 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