blast-graph-angular2
Version:
 **with** 
655 lines (654 loc) • 67.3 kB
JavaScript
/**
* @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