UNPKG

blast-graph-angular2

Version:

![Alt text](./resources/images/b-circle-trans-100.png) **with** ![Alt text](./resources/images/angular.png)

655 lines (654 loc) 67.3 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { BlastService } from './blast-angular2'; import { BlastException } from './blast-exception'; import { GraphRequest } from './graph-request'; import { PathDetails } from './path-details'; import { CollectionTraversor } from './collection-traversor'; import { Operation } from './operation'; import { GraphResponseMessage } from './graph-response-message'; import { GraphMessageType } from './graph-message-type'; import { Attachment } from './attachment'; import { encodeRequest, decodeResponse } from './utils'; import { LogService } from './log-service'; /** @type {?} */ export var useKebab = true; var GraphBlastService = /** @class */ (function (_super) { tslib_1.__extends(GraphBlastService, _super); function GraphBlastService(_url, _logging, _connectNow, _protocols, _config) { var _this = _super.call(this, _url, _connectNow, _protocols, _config) || this; _this._url = _url; _this._logging = _logging; _this._connectNow = _connectNow; _this._protocols = _protocols; _this._config = _config; _this._correlatedGraphRequestMap = []; _this._collectionMap = {}; _this._correlationId = 0; _this._logService = new LogService(); _this._logService.setLog(_logging); return _this; } /** * @param {?} collection * @param {?} entity * @return {?} */ GraphBlastService.prototype.add = /** * @param {?} collection * @param {?} entity * @return {?} */ function (collection, entity) { return this.sendGraphRequest(new GraphRequest('add', collection, entity)); }; /** * @param {?} key * @param {?} entity * @return {?} */ GraphBlastService.prototype.update = /** * @param {?} key * @param {?} entity * @return {?} */ function (key, entity) { return this.sendGraphRequest(new GraphRequest('update', key, entity)); }; /** * @param {?} key * @return {?} */ GraphBlastService.prototype.remove = /** * @param {?} key * @return {?} */ function (key) { return this.sendGraphRequest(new GraphRequest('remove', key)); }; /** * @return {?} */ GraphBlastService.prototype.randomId = /** * @return {?} */ function () { /** * @return {?} */ function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }; /** * @param {?} key * @param {?} data * @param {?=} parameters * @return {?} */ GraphBlastService.prototype.attach = /** * @param {?} key * @param {?} data * @param {?=} parameters * @return {?} */ function (key, data, parameters) { // attach(key: string, data: any, parameters?: PathParameters): Promise<any> { if (key.trim().length === 0) { key = 'root'; } /** @type {?} */ var isArray = false; if (Object.prototype.toString.call(data) === '[object Array]') { isArray = true; } /** @type {?} */ var pathDetails = PathDetails.splitPath(key); if (pathDetails[pathDetails.length - 1].getKeyField() !== undefined && isArray) { this.handlePromiseError(new BlastException('Can only attach to a type of {} when keyField:keyValue is last element of path')); return; } if (pathDetails[pathDetails.length - 1].getKeyField() === undefined && !isArray) { this.handlePromiseError(new BlastException('Can only attach to a type of [] when last element of path is a collection')); return; } /** @type {?} */ var attachmentId = this.randomId(); /** @type {?} */ var attachment = new Attachment(attachmentId, key, this._logService); if (isArray) { attachment.setListData(data); } else { attachment.setData(data); } this._collectionMap[attachmentId] = attachment; // console.log('added to collection', key, clientCollection, this._collectionMap); // return this.sendGraphRequest(new GraphRequest('attach', key, parameters, attachmentId)); this.sendGraphRequest(new GraphRequest('attach', key, null, parameters, attachmentId)); return attachment; }; /** * @param {?} blastException * @return {?} */ GraphBlastService.prototype.handlePromiseError = /** * @param {?} blastException * @return {?} */ function (blastException) { return new Promise(function (resolve, reject) { reject(blastException.message); }); // console.error('Exception:', blastException.message); // const promise: Promise<any> = new Promise((onFulfilled, onRejected) => { // onRejected(blastException.message); // }); // return promise; }; /** * @param {?} key * @return {?} */ GraphBlastService.prototype.detach = /** * @param {?} key * @return {?} */ function (key) { return this.sendGraphRequest(new GraphRequest('detach', key)); }; /** * @return {?} */ GraphBlastService.prototype.detachAll = /** * @return {?} */ function () { return this.sendGraphRequest(new GraphRequest('detachAll')); }; /** * @return {?} */ GraphBlastService.prototype.getAttachments = /** * @return {?} */ function () { return this.sendGraphRequest(new GraphRequest('attachments')); }; /** * @param {?} key * @param {?=} parameters * @return {?} */ GraphBlastService.prototype.fetch = /** * @param {?} key * @param {?=} parameters * @return {?} */ function (key, parameters) { return this.sendGraphRequest(new GraphRequest('fetch', key, parameters)); }; /** * @return {?} */ GraphBlastService.prototype.fetchRoot = /** * @return {?} */ function () { return this.sendGraphRequest(new GraphRequest('fetch', '')); }; /** * @return {?} */ GraphBlastService.prototype.getSchema = /** * @return {?} */ function () { return this.sendGraphRequest(new GraphRequest('schema')); }; /** * @return {?} */ GraphBlastService.prototype.loggingOn = /** * @return {?} */ function () { this._logService.setLog(true); }; /** * @return {?} */ GraphBlastService.prototype.loggingOff = /** * @return {?} */ function () { this._logService.setLog(false); }; /** * @param {?} request * @return {?} */ GraphBlastService.prototype.sendGraphRequest = /** * @param {?} request * @return {?} */ function (request) { /** @type {?} */ var complete; /** @type {?} */ var err; /** @type {?} */ var promise = new Promise(function (onFulfilled, onRejected) { complete = onFulfilled; err = onRejected; }); request.setCorrelationInfo(++this._correlationId, complete, err); // we add the requestDO to a map - used to marry response with request this._correlatedGraphRequestMap[request._correlationId] = request; // console.log('request.getMessage()', request.getMessage()); // send the message if (useKebab) { this.send(encodeRequest(request.getMessage())); } else { this.send(request.getMessage()); } // return the promise - will be fulfilled when we get a response from the server return promise; }; /** * @param {?} startIndex * @param {?} pathDetails * @param {?} addLastKey * @return {?} */ GraphBlastService.prototype.buildPath = /** * @param {?} startIndex * @param {?} pathDetails * @param {?} addLastKey * @return {?} */ function (startIndex, pathDetails, addLastKey) { /** @type {?} */ var builder = ''; for (var x = startIndex; x < pathDetails.length; x++) { if (builder.length > 0) { builder = builder + '/'; } builder = builder + pathDetails[x].getCollection(); if (x < pathDetails.length - 1 || addLastKey) { builder = builder + '/'; if (pathDetails[x].getKeyField() != null) { builder = builder + pathDetails[x].getKeyField() + ':' + pathDetails[x].getKeyValue(); } } } return builder; }; /** * @param {?} key * @param {?} path * @param {?} operation * @return {?} */ GraphBlastService.prototype.calculateTruePath = /** * @param {?} key * @param {?} path * @param {?} operation * @return {?} */ function (key, path, operation) { /** @type {?} */ var keyDetails = PathDetails.splitPath(key); /** @type {?} */ var pathDetails = PathDetails.splitPath(path); /** @type {?} */ var truePath = ''; if (keyDetails[keyDetails.length - 1].isRoot()) { truePath = this.buildPath(0, pathDetails, operation === Operation.UPDATE); } else if (keyDetails[keyDetails.length - 1].getKeyField() == null) { // collection is an array for (var x = 0; x < pathDetails.length; x++) { // loop through until collection in path matches last collection in key if (pathDetails[x].getCollection() === keyDetails[keyDetails.length - 1].getCollection()) { truePath = this.buildPath(x, pathDetails, operation === Operation.UPDATE); break; } } } else { // collection is a map if (keyDetails.length === pathDetails.length) { truePath = this.buildPath(pathDetails.length - 1, pathDetails, operation === Operation.UPDATE); } else { truePath = this.buildPath(keyDetails.length, pathDetails, operation === Operation.UPDATE); } } return truePath; }; /** * @param {?} collection * @param {?} instruction * @return {?} */ GraphBlastService.prototype.applyChangeToRecord = /** * @param {?} collection * @param {?} instruction * @return {?} */ function (collection, instruction) { for (var x = 0; x < instruction.getChanges().length; x++) { // name = name of field, value = new value collection[instruction.getChanges()[x]['name']] = instruction.getChanges()[x]['value']; } }; /** * @param {?} value * @return {?} */ GraphBlastService.prototype.getGraphMessage = /** * @param {?} value * @return {?} */ function (value) { if (useKebab) { return new GraphResponseMessage(JSON.parse(decodeResponse(value))); } else { return new GraphResponseMessage(JSON.parse(value)); } }; /** * @param {?} graphRequest * @param {?} graphMessage * @return {?} */ GraphBlastService.prototype.handleInitialLoad = /** * @param {?} graphRequest * @param {?} graphMessage * @return {?} */ function (graphRequest, graphMessage) { /** @type {?} */ var attachment = this._collectionMap[graphMessage.getAttachmentId()]; // console.log('retrieve [initial load] from collection', graphMessage.getAttachmentId(), attachment, this._collectionMap); if (attachment == null) { console.error('Failed to find collection for key: ', graphMessage.getAttachmentId()); graphRequest._onError('Failed to find collection for key: ' + graphMessage.getAttachmentId()); return; } if (attachment.isList()) { // as its initial load we can just add to collection if (graphMessage.getData() !== null && graphMessage.getData() !== undefined) { Array.prototype.push.apply(attachment.getListData(), graphMessage.getData()); attachment.load(graphMessage.getData()); graphRequest._onFulFilled(attachment.getListData()); } else { attachment.load(undefined); graphRequest._onFulFilled(attachment.getListData()); } } else { this.mergeMap(attachment.getData(), graphMessage.getData()); graphRequest._onFulFilled(attachment.getData()); } }; /** * @param {?} message * @return {?} */ GraphBlastService.prototype.handleJsonMessage = /** * @param {?} message * @return {?} */ function (message) { try { this._logService.log('raw message ', message); /** @type {?} */ var graphMessage = new GraphResponseMessage(decodeResponse(message)); this._logService.log('graph message ', graphMessage); this.handleCommand(graphMessage); return true; } catch (blastException) { // not a valid graph message, so return false so can be handled by normal flow console.error(blastException); return false; } }; /** * @param {?} graphMessage * @return {?} */ GraphBlastService.prototype.handleCommand = /** * @param {?} graphMessage * @return {?} */ function (graphMessage) { this.handleTheCommand(graphMessage); }; /** * @param {?} graphMessage * @return {?} */ GraphBlastService.prototype.handleTheCommand = /** * @param {?} graphMessage * @return {?} */ function (graphMessage) { // console.log('handle command', graphMessage); try { // 1st pass - handle responses that don't have a future attached switch (graphMessage.getCommand()) { case GraphMessageType.GRAPH_ADD_RESPONSE: case GraphMessageType.GRAPH_UPDATE_RESPONSE: case GraphMessageType.GRAPH_REMOVE_RESPONSE: this.handleGraphModify(graphMessage); return; } /** @type {?} */ var graphRequest = this._correlatedGraphRequestMap[graphMessage.getCorrelationId()]; if (graphRequest === undefined) { throw new BlastException('Failed to find correlation id: ' + graphMessage.getCorrelationId()); } switch (graphMessage.getCommand()) { case GraphMessageType.GRAPH_DETACH_RESPONSE: case GraphMessageType.GRAPH_DETACH_ALL_RESPONSE: case GraphMessageType.GRAPH_OK_RESPONSE: graphRequest._onFulFilled(graphMessage); break; case GraphMessageType.GRAPH_FAIL_RESPONSE: graphRequest._onFulFilled(graphMessage); break; case GraphMessageType.GRAPH_INITIAL_LOAD_RESPONSE: this.handleInitialLoad(graphRequest, graphMessage); break; case GraphMessageType.GRAPH_CLIENT_ATTACHMENTS_RESPONSE: case GraphMessageType.GRAPH_SCHEMA_RESPONSE: case GraphMessageType.GRAPH_FETCH_RESPONSE: graphRequest._onFulFilled(graphMessage.getData()); break; case GraphMessageType.GRAPH_ADD_RESPONSE: case GraphMessageType.GRAPH_UPDATE_RESPONSE: case GraphMessageType.GRAPH_REMOVE_RESPONSE: break; } } catch (blastException) { // console.log('Exception', blastException); // eventHandler.onError(new WebSocketException(ex.getMessage(), ex)); } }; /** * @param {?} graphMessage * @return {?} */ GraphBlastService.prototype.handleGraphModify = /** * @param {?} graphMessage * @return {?} */ function (graphMessage) { // console.log('Handling ...', graphMessage); if (this.shouldAbandonProcessing(graphMessage)) { // 'No Instruction or no changes - doing nothing' return; } /** @type {?} */ var attachment = this._collectionMap[graphMessage.getAttachmentId()]; // console.log('retrieve [modify] from collection', graphMessage.getAttachmentId(), clientCollection, this._collectionMap); if (attachment === undefined) { // 'Cannot find collection for {}', graphMessage.getKey()); return; } /** @type {?} */ var path = this.calculateTruePath(graphMessage.getKey(), graphMessage.getInstruction().getPath(), graphMessage.getInstruction().getOperation()); /** @type {?} */ var parentList = []; /** @type {?} */ var record = {}; // console.log('Ready to ...', graphMessage.getInstruction().getOperation()); switch (graphMessage.getInstruction().getOperation()) { case Operation.ADD: // console.log('Okay Im Adding'); if (attachment.isList()) { CollectionTraversor.findList(path, attachment.getListData()).push(graphMessage.getInstruction().getRecord()); } else { CollectionTraversor.findList(path, attachment.getData()).push(graphMessage.getInstruction().getRecord()); } attachment.added(graphMessage.getInstruction().getRecord()); break; case Operation.UPDATE: // console.log('Okay Im Updating'); if (attachment.isList()) { record = CollectionTraversor.findRecord(path, attachment.getListData()); this.applyChangeToRecord(record, graphMessage.getInstruction()); attachment.changed(record); } else { if (path.length === 0 || graphMessage.getKey().endsWith(path)) { // if key = markets/id:101/runners/id:103 and path = runners/id:103 // then data is not actually hierarchal record = attachment.getData(); } else { record = CollectionTraversor.findRecord(path, attachment.getData()); } this.applyChangeToRecord(record, graphMessage.getInstruction()); attachment.changed(record); } break; case Operation.REMOVE: /** @type {?} */ var pathDetails = PathDetails.splitPath(graphMessage.getInstruction().getPath()); /** @type {?} */ var recordKey = pathDetails[pathDetails.length - 1].getCollection() + '/' + pathDetails[pathDetails.length - 1].getKeyField() + ':' + pathDetails[pathDetails.length - 1].getKeyValue(); /** @type {?} */ var recordIndex = void 0; if (attachment.isList()) { parentList = attachment.getListData(); // record = CollectionTraversor.findRecord(recordKey, clientCollection.getListData()); recordIndex = CollectionTraversor.findRecordIndexInList(pathDetails[pathDetails.length - 1].getKeyField(), pathDetails[pathDetails.length - 1].getKeyValue(), attachment.getListData()); } else { parentList = CollectionTraversor.findList(path, attachment.getData()); if (recordKey.length === 0 || graphMessage.getKey().endsWith(recordKey)) { // record = clientCollection.getData(); recordIndex = 0; } else { // record = CollectionTraversor.findRecord(recordKey, clientCollection.getData()); recordIndex = CollectionTraversor.findRecordIndexInList(pathDetails[pathDetails.length - 1].getKeyField(), pathDetails[pathDetails.length - 1].getKeyValue(), parentList); } } // parentList.remove(record); parentList.splice(recordIndex, 1); attachment.removed(record); break; } }; /** * @param {?} graphMessage * @return {?} */ GraphBlastService.prototype.shouldAbandonProcessing = /** * @param {?} graphMessage * @return {?} */ function (graphMessage) { if (!graphMessage.getInstruction()) { return true; } /** @type {?} */ var operationRemove = graphMessage.getInstruction().getOperation() === Operation.REMOVE; /** @type {?} */ var noChanges = (!graphMessage.getInstruction().getChanges() || graphMessage.getInstruction().getChanges().length === 0); /** @type {?} */ var noRecord = graphMessage.getInstruction().getRecord(); return operationRemove && noChanges && noRecord; }; /** * @param {?} baseObject * @param {?} changedObject * @return {?} */ GraphBlastService.prototype.mergeMap = /** * @param {?} baseObject * @param {?} changedObject * @return {?} */ function (baseObject, changedObject) { for (var p in changedObject) { if (changedObject.hasOwnProperty(p)) { try { // Property in destination object set; update its value. if (changedObject[p].constructor === Object) { baseObject[p] = this.mergeMap(baseObject[p], changedObject[p]); } else { baseObject[p] = changedObject[p]; } } catch (e) { // Property in destination object not set; create it and set its value. baseObject[p] = changedObject[p]; } } } }; return GraphBlastService; }(BlastService)); export { GraphBlastService }; if (false) { /** @type {?} */ GraphBlastService.prototype._correlatedGraphRequestMap; /** @type {?} */ GraphBlastService.prototype._collectionMap; /** @type {?} */ GraphBlastService.prototype._correlationId; /** @type {?} */ GraphBlastService.prototype._logService; /** @type {?} */ GraphBlastService.prototype._url; /** @type {?} */ GraphBlastService.prototype._logging; /** @type {?} */ GraphBlastService.prototype._connectNow; /** @type {?} */ GraphBlastService.prototype._protocols; /** @type {?} */ GraphBlastService.prototype._config; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxhc3QtZ3JhcGgtYW5ndWxhcjIuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9ibGFzdC1ncmFwaC1hbmd1bGFyMi8iLCJzb3VyY2VzIjpbInNyYy9ibGFzdC1ncmFwaC1hbmd1bGFyMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBQyxZQUFZLEVBQXFCLE1BQU0sa0JBQWtCLENBQUM7QUFDbEUsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBRWpELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUU3QyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDM0QsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUU5RCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBQyxhQUFhLEVBQUUsY0FBYyxFQUFDLE1BQU0sU0FBUyxDQUFDO0FBQ3RELE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7O0FBRXpDLFdBQWEsUUFBUSxHQUFHLElBQUksQ0FBQztBQUU3QixJQUFBO0lBQXVDLDZDQUFZO0lBTS9DLDJCQUFvQixJQUFZLEVBQ3BCLFVBQ0EsYUFDQSxZQUNBO1FBSlosWUFNSSxrQkFBTSxJQUFJLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsU0FHaEQ7UUFUbUIsVUFBSSxHQUFKLElBQUksQ0FBUTtRQUNwQixjQUFRLEdBQVIsUUFBUTtRQUNSLGlCQUFXLEdBQVgsV0FBVztRQUNYLGdCQUFVLEdBQVYsVUFBVTtRQUNWLGFBQU8sR0FBUCxP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SUFBSSxDQUFDOztvQkFFRCxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUM7d0JBQzFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztxQkFDbEU7b0JBQUMsSUFBSSxDQUFDLENBQUM7d0JBQ0osVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztxQkFDcEM7aUJBQ0o7Z0JBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7O29CQUVULFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ3BDO2FBQ0o7U0FDSjtLQUNKOzRCQWxjTDtFQWlCdUMsWUFBWSxFQW1ibEQsQ0FBQTtBQW5iRCw2QkFtYkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0JsYXN0U2VydmljZSwgQmxhc3RTZXJ2aWNlQ29uZmlnfSBmcm9tICcuL2JsYXN0LWFuZ3VsYXIyJztcbmltcG9ydCB7Qmxhc3RFeGNlcHRpb259IGZyb20gJy4vYmxhc3QtZXhjZXB0aW9uJztcblxuaW1wb3J0IHtHcmFwaFJlcXVlc3R9IGZyb20gJy4vZ3JhcGgtcmVxdWVzdCc7XG5pbXBvcnQge1BhdGhQYXJhbWV0ZXJzfSBmcm9tICcuL3BhdGgtcGFyYW1ldGVycyc7XG5pbXBvcnQge1BhdGhEZXRhaWxzfSBmcm9tICcuL3BhdGgtZGV0YWlscyc7XG5pbXBvcnQge0NvbGxlY3Rpb25UcmF2ZXJzb3J9IGZyb20gJy4vY29sbGVjdGlvbi10cmF2ZXJzb3InO1xuaW1wb3J0IHtPcGVyYXRpb259IGZyb20gJy4vb3BlcmF0aW9uJztcbmltcG9ydCB7R3JhcGhSZXNwb25zZU1lc3NhZ2V9IGZyb20gJy4vZ3JhcGgtcmVzcG9uc2UtbWVzc2FnZSc7XG5pbXBvcnQge0luc3RydWN0aW9ufSBmcm9tICcuL2luc3RydWN0aW9uJztcbmltcG9ydCB7R3JhcGhNZXNzYWdlVHlwZX0gZnJvbSAnLi9ncmFwaC1tZXNzYWdlLXR5cGUnO1xuaW1wb3J0IHtBdHRhY2htZW50fSBmcm9tICcuL2F0dGFjaG1lbnQnO1xuaW1wb3J0IHtlbmNvZGVSZXF1ZXN0LCBkZWNvZGVSZXNwb25zZX0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge0xvZ1NlcnZpY2V9IGZyb20gJy4vbG9nLXNlcnZpY2UnO1xuXG5leHBvcnQgY29uc3QgdXNlS2ViYWIgPSB0cnVlO1xuXG5leHBvcnQgY2xhc3MgR3JhcGhCbGFzdFNlcnZpY2UgZXh0ZW5kcyBCbGFzdFNlcnZpY2Uge1xuICAgIHByaXZhdGUgX2NvcnJlbGF0ZWRHcmFwaFJlcXVlc3RNYXA6IEdyYXBoUmVxdWVzdFtdID0gW107XG4gICAgcHJpdmF0ZSBfY29sbGVjdGlvbk1hcDogYW55ID0ge307XG4gICAgcHJpdmF0ZSBfY29ycmVsYXRpb25JZCA9IDA7XG4gICAgX2xvZ1NlcnZpY2U6IExvZ1NlcnZpY2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF91cmw6IHN0cmluZyxcbiAgICAgICAgcHJpdmF0ZSBfbG9nZ2luZzogYm9vbGVhbixcbiAgICAgICAgcHJpdmF0ZSBfY29ubmVjdE5vdz86IGJvb2xlYW4sXG4gICAgICAgIHByaXZhdGUgX3Byb3RvY29scz86IEFycmF5PHN0cmluZz4sXG4gICAgICAgIHByaXZhdGUgX2NvbmZpZz86IEJsYXN0U2VydmljZUNvbmZpZ1xuICAgICkge1xuICAgICAgICBzdXBlcihfdXJsLCBfY29ubmVjdE5vdywgX3Byb3RvY29scywgX2NvbmZpZyk7XG4gICAgICAgIHRoaXMuX2xvZ1NlcnZpY2UgPSBuZXcgTG9nU2VydmljZSgpO1xuICAgICAgICB0aGlzLl9sb2dTZXJ2aWNlLnNldExvZyhfbG9nZ2luZyk7XG4gICAgfVxuXG4gICAgYWRkKGNvbGxlY3Rpb246IHN0cmluZywgZW50aXR5OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ2FkZCcsIGNvbGxlY3Rpb24sIGVudGl0eSkpO1xuICAgIH1cblxuICAgIHVwZGF0ZShrZXk6IHN0cmluZywgZW50aXR5OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ3VwZGF0ZScsIGtleSwgZW50aXR5KSk7XG4gICAgfVxuXG4gICAgcmVtb3ZlKGtleTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZEdyYXBoUmVxdWVzdChuZXcgR3JhcGhSZXF1ZXN0KCdyZW1vdmUnLCBrZXkpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJhbmRvbUlkKCk6IHN0cmluZyB7XG4gICAgICAgIGZ1bmN0aW9uIHM0KCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKDEgKyBNYXRoLnJhbmRvbSgpKSAqIDB4MTAwMDApXG4gICAgICAgICAgICAgICAgLnRvU3RyaW5nKDE2KVxuICAgICAgICAgICAgICAgIC5zdWJzdHJpbmcoMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHM0KCkgKyBzNCgpICsgJy0nICsgczQoKSArICctJyArIHM0KCkgKyAnLScgK1xuICAgICAgICAgICAgczQoKSArICctJyArIHM0KCkgKyBzNCgpICsgczQoKTtcbiAgICB9XG5cbiAgICBhdHRhY2goa2V5OiBzdHJpbmcsIGRhdGE6IGFueSwgcGFyYW1ldGVycz86IFBhdGhQYXJhbWV0ZXJzKTogQXR0YWNobWVudCB7XG4gICAgICAgIC8vICAgIGF0dGFjaChrZXk6IHN0cmluZywgZGF0YTogYW55LCBwYXJhbWV0ZXJzPzogUGF0aFBhcmFtZXRlcnMpOiBQcm9taXNlPGFueT4ge1xuXG4gICAgICAgIGlmIChrZXkudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAga2V5ID0gJ3Jvb3QnO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGlzQXJyYXkgPSBmYWxzZTtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgICAgICAgaXNBcnJheSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwZXJmb3JtIHBhdGggYW5kIHBhdGgtPmNvbGxlY3Rpb24gdmFsaWRhdGlvblxuICAgICAgICBjb25zdCBwYXRoRGV0YWlsczogUGF0aERldGFpbHNbXSA9IFBhdGhEZXRhaWxzLnNwbGl0UGF0aChrZXkpO1xuICAgICAgICBpZiAocGF0aERldGFpbHNbcGF0aERldGFpbHMubGVuZ3RoIC0gMV0uZ2V0S2V5RmllbGQoKSAhPT0gdW5kZWZpbmVkICYmIGlzQXJyYXkpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlUHJvbWlzZUVycm9yKG5ldyBCbGFzdEV4Y2VwdGlvbignQ2FuIG9ubHkgYXR0YWNoIHRvIGEgdHlwZSBvZiB7fSB3aGVuIGtleUZpZWxkOmtleVZhbHVlIGlzIGxhc3QgZWxlbWVudCBvZiBwYXRoJykpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoRGV0YWlsc1twYXRoRGV0YWlscy5sZW5ndGggLSAxXS5nZXRLZXlGaWVsZCgpID09PSB1bmRlZmluZWQgJiYgIWlzQXJyYXkpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlUHJvbWlzZUVycm9yKG5ldyBCbGFzdEV4Y2VwdGlvbignQ2FuIG9ubHkgYXR0YWNoIHRvIGEgdHlwZSBvZiBbXSB3aGVuIGxhc3QgZWxlbWVudCBvZiBwYXRoIGlzIGEgY29sbGVjdGlvbicpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGF0dGFjaG1lbnRJZCA9IHRoaXMucmFuZG9tSWQoKTtcbiAgICAgICAgLy8gYWRkIGNvbGxlY3Rpb24gdG8gbWFwIG9mIGNvbGxlY3Rpb25zXG5cbiAgICAgICAgY29uc3QgYXR0YWNobWVudDogQXR0YWNobWVudCA9IG5ldyBBdHRhY2htZW50KGF0dGFjaG1lbnRJZCwga2V5LCB0aGlzLl9sb2dTZXJ2aWNlKTtcbiAgICAgICAgaWYgKGlzQXJyYXkpIHtcbiAgICAgICAgICAgIGF0dGFjaG1lbnQuc2V0TGlzdERhdGEoZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhdHRhY2htZW50LnNldERhdGEoZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY29sbGVjdGlvbk1hcFthdHRhY2htZW50SWRdID0gYXR0YWNobWVudDtcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ2FkZGVkIHRvIGNvbGxlY3Rpb24nLCBrZXksIGNsaWVudENvbGxlY3Rpb24sIHRoaXMuX2NvbGxlY3Rpb25NYXApO1xuXG4gICAgICAgIC8vICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ2F0dGFjaCcsIGtleSwgcGFyYW1ldGVycywgYXR0YWNobWVudElkKSk7XG4gICAgICAgIHRoaXMuc2VuZEdyYXBoUmVxdWVzdChuZXcgR3JhcGhSZXF1ZXN0KCdhdHRhY2gnLCBrZXksIG51bGwsIHBhcmFtZXRlcnMsIGF0dGFjaG1lbnRJZCkpO1xuICAgICAgICByZXR1cm4gYXR0YWNobWVudDtcbiAgICB9XG5cbiAgICBoYW5kbGVQcm9taXNlRXJyb3IoYmxhc3RFeGNlcHRpb246IEJsYXN0RXhjZXB0aW9uKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKFxuICAgICAgICAgICAgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChibGFzdEV4Y2VwdGlvbi5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgLy8gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0V4Y2VwdGlvbjonLCBibGFzdEV4Y2VwdGlvbi5tZXNzYWdlKTtcbiAgICAgICAgLy8gICAgICAgIGNvbnN0IHByb21pc2U6IFByb21pc2U8YW55PiA9IG5ldyBQcm9taXNlKChvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkgPT4ge1xuICAgICAgICAvLyAgICAgICAgICAgIG9uUmVqZWN0ZWQoYmxhc3RFeGNlcHRpb24ubWVzc2FnZSk7XG4gICAgICAgIC8vICAgICAgICB9KTtcbiAgICAgICAgLy8gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIGRldGFjaChrZXk6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ2RldGFjaCcsIGtleSkpO1xuICAgIH1cblxuICAgIGRldGFjaEFsbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZEdyYXBoUmVxdWVzdChuZXcgR3JhcGhSZXF1ZXN0KCdkZXRhY2hBbGwnKSk7XG4gICAgfVxuXG4gICAgZ2V0QXR0YWNobWVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRHcmFwaFJlcXVlc3QobmV3IEdyYXBoUmVxdWVzdCgnYXR0YWNobWVudHMnKSk7XG4gICAgfVxuXG4gICAgZmV0Y2goa2V5OiBzdHJpbmcsIHBhcmFtZXRlcnM/OiBQYXRoUGFyYW1ldGVycykge1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ2ZldGNoJywga2V5LCBwYXJhbWV0ZXJzKSk7XG4gICAgfVxuXG4gICAgZmV0Y2hSb290KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kR3JhcGhSZXF1ZXN0KG5ldyBHcmFwaFJlcXVlc3QoJ2ZldGNoJywgJycpKTtcbiAgICB9XG5cbiAgICBnZXRTY2hlbWEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRHcmFwaFJlcXVlc3QobmV3IEdyYXBoUmVxdWVzdCgnc2NoZW1hJykpO1xuICAgIH1cblxuICAgIGxvZ2dpbmdPbigpIHtcbiAgICAgICAgdGhpcy5fbG9nU2VydmljZS5zZXRMb2codHJ1ZSk7XG4gICAgfVxuXG4gICAgbG9nZ2luZ09mZigpIHtcbiAgICAgICAgdGhpcy5fbG9nU2VydmljZS5zZXRMb2coZmFsc2UpO1xuICAgIH1cblxuICAgIHNlbmRHcmFwaFJlcXVlc3QocmVxdWVzdDogR3JhcGhSZXF1ZXN0KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgbGV0IGNvbXBsZXRlLCBlcnI7XG5cbiAgICAgICAgLy8gIGNyZWF0ZSBhbiBlbXB0eSByZXNwb25zZSAtIHdlIHVzZSB0aGUgb25GdWxGaWxsIGFuZCBvblJlamVjdCBmdW5jdGlvbnMgb24gdGhlIHJlc3BvbnNlXG4gICAgICAgIGNvbnN0IHByb21pc2U6IFByb21pc2U8YW55PiA9IG5ldyBQcm9taXNlKChvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkgPT4ge1xuICAgICAgICAgICAgY29tcGxldGUgPSBvbkZ1bGZpbGxlZDsgZXJyID0gb25SZWplY3RlZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVxdWVzdC5zZXRDb3JyZWxhdGlvbkluZm8oKyt0aGlzLl9jb3JyZWxhdGlvbklkLCBjb21wbGV0ZSwgZXJyKTtcblxuICAgICAgICAvLyAgd2UgYWRkIHRoZSByZXF1ZXN0RE8gdG8gYSBtYXAgLSB1c2VkIHRvIG1hcnJ5IHJlc3BvbnNlIHdpdGggcmVxdWVzdFxuICAgICAgICB0aGlzLl9jb3JyZWxhdGVkR3JhcGhSZXF1ZXN0TWFwW3JlcXVlc3QuX2NvcnJlbGF0aW9uSWRdID0gcmVxdWVzdDtcblxuXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdyZXF1ZXN0LmdldE1lc3NhZ2UoKScsIHJlcXVlc3QuZ2V0TWVzc2FnZSgpKTtcbiAgICAgICAgLy8gIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICAgICAgaWYgKHVzZUtlYmFiKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmQoZW5jb2RlUmVxdWVzdChyZXF1ZXN0LmdldE1lc3NhZ2UoKSkpO1xuIC