UNPKG

@orbit/record-cache

Version:

Orbit base classes used to access and maintain a set of records.

278 lines 51.7 kB
import { Assertion, Orbit } from '@orbit/core'; import { buildQuery, buildTransform, OperationTerm } from '@orbit/data'; import { recordsReferencedByOperations } from '@orbit/records'; import { deepGet, toArray } from '@orbit/utils'; import { AsyncOperationProcessor } from './async-operation-processor'; import { AsyncLiveQuery } from './live-query/async-live-query'; import { AsyncCacheIntegrityProcessor } from './operation-processors/async-cache-integrity-processor'; import { AsyncSchemaConsistencyProcessor } from './operation-processors/async-schema-consistency-processor'; import { AsyncSchemaValidationProcessor } from './operation-processors/async-schema-validation-processor'; import { AsyncInverseTransformOperators } from './operators/async-inverse-transform-operators'; import { AsyncQueryOperators } from './operators/async-query-operators'; import { AsyncTransformOperators } from './operators/async-transform-operators'; import { RecordCache } from './record-cache'; const { assert, deprecate } = Orbit; export class AsyncRecordCache extends RecordCache { constructor(settings) { var _a, _b, _c; super(settings); this._queryOperators = (_a = settings.queryOperators) !== null && _a !== void 0 ? _a : AsyncQueryOperators; this._transformOperators = (_b = settings.transformOperators) !== null && _b !== void 0 ? _b : AsyncTransformOperators; this._inverseTransformOperators = (_c = settings.inverseTransformOperators) !== null && _c !== void 0 ? _c : AsyncInverseTransformOperators; this._debounceLiveQueries = settings.debounceLiveQueries !== false; this._transformBuffer = settings.transformBuffer; const processors = settings.processors ? settings.processors : [AsyncSchemaConsistencyProcessor, AsyncCacheIntegrityProcessor]; if (settings.autoValidate !== false && settings.processors === undefined) { processors.push(AsyncSchemaValidationProcessor); } this._processors = processors.map((Processor) => { let processor = new Processor(this); assert('Each processor must extend AsyncOperationProcessor', processor instanceof AsyncOperationProcessor); return processor; }); } get processors() { return this._processors; } getQueryOperator(op) { return this._queryOperators[op]; } getTransformOperator(op) { return this._transformOperators[op]; } getInverseTransformOperator(op) { return this._inverseTransformOperators[op]; } async applyRecordChangesetAsync(changeset) { const { setRecords, removeRecords, addInverseRelationships, removeInverseRelationships } = changeset; const promises = []; if (setRecords && setRecords.length > 0) { promises.push(await this.setRecordsAsync(setRecords)); } if (removeRecords && removeRecords.length > 0) { promises.push(await this.removeRecordsAsync(removeRecords)); } if (addInverseRelationships && addInverseRelationships.length > 0) { promises.push(await this.addInverseRelationshipsAsync(addInverseRelationships)); } if (removeInverseRelationships && removeInverseRelationships.length > 0) { promises.push(await this.removeInverseRelationshipsAsync(removeInverseRelationships)); } await Promise.all(promises); } async getRelatedRecordAsync(identity, relationship) { const record = await this.getRecordAsync(identity); if (record) { return deepGet(record, ['relationships', relationship, 'data']); } return undefined; } async getRelatedRecordsAsync(identity, relationship) { const record = await this.getRecordAsync(identity); if (record) { return deepGet(record, ['relationships', relationship, 'data']); } return undefined; } async query(queryOrExpressions, options, id) { const query = buildQuery(queryOrExpressions, options, id, this._queryBuilder); const response = await this._query(query, options); if (options === null || options === void 0 ? void 0 : options.fullResponse) { return response; } else { return response.data; } } async update(transformOrOperations, options, id) { const transform = buildTransform(transformOrOperations, options, id, this._transformBuilder); const response = await this._update(transform, options); if (options === null || options === void 0 ? void 0 : options.fullResponse) { return response; } else { return response.data; } } /** * Patches the cache with an operation or operations. * * @deprecated since v0.17 */ async patch(operationOrOperations) { deprecate('AsyncRecordCache#patch has been deprecated. Use AsyncRecordCache#update instead.'); // TODO - Why is this `this` cast necessary for TS to understand the correct // method overload? const { data, details } = await this.update(operationOrOperations, { fullResponse: true }); return { inverse: (details === null || details === void 0 ? void 0 : details.inverseOperations) || [], data: Array.isArray(data) ? data : [data] }; } liveQuery(queryOrExpressions, options, id) { const query = buildQuery(queryOrExpressions, options, id, this.queryBuilder); let debounce = options && options.debounce; if (typeof debounce !== 'boolean') { debounce = this._debounceLiveQueries; } return new AsyncLiveQuery({ debounce, cache: this, query }); } ///////////////////////////////////////////////////////////////////////////// // Protected methods ///////////////////////////////////////////////////////////////////////////// async _query(query, // eslint-disable-next-line @typescript-eslint/no-unused-vars options) { let data; if (Array.isArray(query.expressions)) { data = []; for (let expression of query.expressions) { const queryOperator = this.getQueryOperator(expression.op); if (!queryOperator) { throw new Error(`Unable to find query operator: ${expression.op}`); } data.push(await queryOperator(this, expression, this.getQueryOptions(query, expression))); } } else { const expression = query.expressions; const queryOperator = this.getQueryOperator(expression.op); if (!queryOperator) { throw new Error(`Unable to find query operator: ${expression.op}`); } data = await queryOperator(this, expression, this.getQueryOptions(query, expression)); } return { data: data }; } async _update(transform, options) { var _a, _b; if ((_a = this.getTransformOptions(transform)) === null || _a === void 0 ? void 0 : _a.useBuffer) { const buffer = await this._initTransformBuffer(transform); buffer.startTrackingChanges(); const response = buffer.update(transform, { fullResponse: true }); const changes = buffer.stopTrackingChanges(); await this.applyRecordChangesetAsync(changes); const { appliedOperations, appliedOperationResults } = response.details; for (let i = 0, len = appliedOperations.length; i < len; i++) { this.emit('patch', appliedOperations[i], appliedOperationResults[i]); } return response; } else { const response = { data: [] }; if (options === null || options === void 0 ? void 0 : options.fullResponse) { response.details = { appliedOperations: [], appliedOperationResults: [], inverseOperations: [] }; } let data; if (Array.isArray(transform.operations)) { await this._applyTransformOperations(transform, transform.operations, response, true); data = response.data; } else { await this._applyTransformOperation(transform, transform.operations, response, true); if (Array.isArray(response.data)) { data = response.data[0]; } } if (options === null || options === void 0 ? void 0 : options.fullResponse) { (_b = response.details) === null || _b === void 0 ? void 0 : _b.inverseOperations.reverse(); } return { ...response, data }; } } _getTransformBuffer() { if (this._transformBuffer === undefined) { throw new Assertion('transformBuffer must be provided to cache via constructor settings'); } return this._transformBuffer; } async _initTransformBuffer(transform) { const buffer = this._getTransformBuffer(); const records = recordsReferencedByOperations(toArray(transform.operations)); const inverseRelationships = await this.getInverseRelationshipsAsync(records); const relatedRecords = inverseRelationships.map((ir) => ir.record); Array.prototype.push.apply(records, relatedRecords); buffer.resetState(); buffer.setRecordsSync(await this.getRecordsAsync(records)); buffer.addInverseRelationshipsSync(inverseRelationships); return buffer; } async _applyTransformOperations(transform, ops, response, primary = false) { for (let op of ops) { await this._applyTransformOperation(transform, op, response, primary); } } async _applyTransformOperation(transform, operation, response, primary = false) { var _a, _b, _c, _d; if (operation instanceof OperationTerm) { operation = operation.toOperation(); } for (let processor of this._processors) { await processor.validate(operation); } const inverseTransformOperator = this.getInverseTransformOperator(operation.op); const inverseOp = await inverseTransformOperator(this, operation, this.getTransformOptions(transform, operation)); if (inverseOp) { (_b = (_a = response.details) === null || _a === void 0 ? void 0 : _a.inverseOperations) === null || _b === void 0 ? void 0 : _b.push(inverseOp); // Query and perform related `before` operations for (let processor of this._processors) { await this._applyTransformOperations(transform, await processor.before(operation), response); } // Query related `after` operations before performing // the requested operation. These will be applied on success. let preparedOps = []; for (let processor of this._processors) { preparedOps.push(await processor.after(operation)); } // Perform the requested operation let transformOperator = this.getTransformOperator(operation.op); let data = await transformOperator(this, operation, this.getTransformOptions(transform, operation)); if (primary) { (_c = response.data) === null || _c === void 0 ? void 0 : _c.push(data); } if (response.details) { response.details.appliedOperationResults.push(data); response.details.appliedOperations.push(operation); } // Query and perform related `immediate` operations for (let processor of this._processors) { await processor.immediate(operation); } // Emit event this.emit('patch', operation, data); // Perform prepared operations after performing the requested operation for (let ops of preparedOps) { await this._applyTransformOperations(transform, ops, response); } // Query and perform related `finally` operations for (let processor of this._processors) { await this._applyTransformOperations(transform, await processor.finally(operation), response); } } else if (primary) { (_d = response.data) === null || _d === void 0 ? void 0 : _d.push(undefined); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtcmVjb3JkLWNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FzeW5jLXJlY29yZC1jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsVUFBVSxFQUNWLGNBQWMsRUFJZCxhQUFhLEVBSWQsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQVlMLDZCQUE2QixFQUs5QixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxPQUFPLEVBQVEsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RELE9BQU8sRUFDTCx1QkFBdUIsRUFFeEIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDL0QsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sd0RBQXdELENBQUM7QUFDdEcsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sMkRBQTJELENBQUM7QUFDNUcsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sMERBQTBELENBQUM7QUFDMUcsT0FBTyxFQUVMLDhCQUE4QixFQUMvQixNQUFNLCtDQUErQyxDQUFDO0FBQ3ZELE9BQU8sRUFFTCxtQkFBbUIsRUFDcEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLEVBRUwsdUJBQXVCLEVBQ3hCLE1BQU0sdUNBQXVDLENBQUM7QUFNL0MsT0FBTyxFQUNMLFdBQVcsRUFJWixNQUFNLGdCQUFnQixDQUFDO0FBSXhCLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsS0FBSyxDQUFDO0FBZ0JwQyxNQUFNLE9BQWdCLGdCQVFwQixTQUFRLFdBQTJCO0lBWW5DLFlBQVksUUFBa0Q7O1FBQzVELEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVoQixJQUFJLENBQUMsZUFBZSxH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b3JlJztcbmltcG9ydCB7XG4gIGJ1aWxkUXVlcnksXG4gIGJ1aWxkVHJhbnNmb3JtLFxuICBEZWZhdWx0UmVxdWVzdE9wdGlvbnMsXG4gIEZ1bGxSZXF1ZXN0T3B0aW9ucyxcbiAgRnVsbFJlc3BvbnNlLFxuICBPcGVyYXRpb25UZXJtLFxuICBRdWVyeU9yRXhwcmVzc2lvbnMsXG4gIFJlcXVlc3RPcHRpb25zLFxuICBUcmFuc2Zvcm1Pck9wZXJhdGlvbnNcbn0gZnJvbSAnQG9yYml0L2RhdGEnO1xuaW1wb3J0IHtcbiAgQXN5bmNSZWNvcmRRdWVyeWFibGUsXG4gIEFzeW5jUmVjb3JkVXBkYXRhYmxlLFxuICBJbml0aWFsaXplZFJlY29yZCxcbiAgUmVjb3JkSWRlbnRpdHksXG4gIFJlY29yZE9wZXJhdGlvbixcbiAgUmVjb3JkT3BlcmF0aW9uUmVzdWx0LFxuICBSZWNvcmRPcGVyYXRpb25UZXJtLFxuICBSZWNvcmRRdWVyeSxcbiAgUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBSZWNvcmRRdWVyeUV4cHJlc3Npb24sXG4gIFJlY29yZFF1ZXJ5UmVzdWx0LFxuICByZWNvcmRzUmVmZXJlbmNlZEJ5T3BlcmF0aW9ucyxcbiAgUmVjb3JkVHJhbnNmb3JtLFxuICBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyRnVuYyxcbiAgUmVjb3JkVHJhbnNmb3JtUmVzdWx0XG59IGZyb20gJ0BvcmJpdC9yZWNvcmRzJztcbmltcG9ydCB7IGRlZXBHZXQsIERpY3QsIHRvQXJyYXkgfSBmcm9tICdAb3JiaXQvdXRpbHMnO1xuaW1wb3J0IHtcbiAgQXN5bmNPcGVyYXRpb25Qcm9jZXNzb3IsXG4gIEFzeW5jT3BlcmF0aW9uUHJvY2Vzc29yQ2xhc3Ncbn0gZnJvbSAnLi9hc3luYy1vcGVyYXRpb24tcHJvY2Vzc29yJztcbmltcG9ydCB7IEFzeW5jTGl2ZVF1ZXJ5IH0gZnJvbSAnLi9saXZlLXF1ZXJ5L2FzeW5jLWxpdmUtcXVlcnknO1xuaW1wb3J0IHsgQXN5bmNDYWNoZUludGVncml0eVByb2Nlc3NvciB9IGZyb20gJy4vb3BlcmF0aW9uLXByb2Nlc3NvcnMvYXN5bmMtY2FjaGUtaW50ZWdyaXR5LXByb2Nlc3Nvcic7XG5pbXBvcnQgeyBBc3luY1NjaGVtYUNvbnNpc3RlbmN5UHJvY2Vzc29yIH0gZnJvbSAnLi9vcGVyYXRpb24tcHJvY2Vzc29ycy9hc3luYy1zY2hlbWEtY29uc2lzdGVuY3ktcHJvY2Vzc29yJztcbmltcG9ydCB7IEFzeW5jU2NoZW1hVmFsaWRhdGlvblByb2Nlc3NvciB9IGZyb20gJy4vb3BlcmF0aW9uLXByb2Nlc3NvcnMvYXN5bmMtc2NoZW1hLXZhbGlkYXRpb24tcHJvY2Vzc29yJztcbmltcG9ydCB7XG4gIEFzeW5jSW52ZXJzZVRyYW5zZm9ybU9wZXJhdG9yLFxuICBBc3luY0ludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcnNcbn0gZnJvbSAnLi9vcGVyYXRvcnMvYXN5bmMtaW52ZXJzZS10cmFuc2Zvcm0tb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIEFzeW5jUXVlcnlPcGVyYXRvcixcbiAgQXN5bmNRdWVyeU9wZXJhdG9yc1xufSBmcm9tICcuL29wZXJhdG9ycy9hc3luYy1xdWVyeS1vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgQXN5bmNUcmFuc2Zvcm1PcGVyYXRvcixcbiAgQXN5bmNUcmFuc2Zvcm1PcGVyYXRvcnNcbn0gZnJvbSAnLi9vcGVyYXRvcnMvYXN5bmMtdHJhbnNmb3JtLW9wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBBc3luY1JlY29yZEFjY2Vzc29yLFxuICBSZWNvcmRDaGFuZ2VzZXQsXG4gIFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5XG59IGZyb20gJy4vcmVjb3JkLWFjY2Vzc29yJztcbmltcG9ydCB7XG4gIFJlY29yZENhY2hlLFxuICBSZWNvcmRDYWNoZVF1ZXJ5T3B0aW9ucyxcbiAgUmVjb3JkQ2FjaGVTZXR0aW5ncyxcbiAgUmVjb3JkQ2FjaGVUcmFuc2Zvcm1PcHRpb25zXG59IGZyb20gJy4vcmVjb3JkLWNhY2hlJztcbmltcG9ydCB7IFJlY29yZFRyYW5zZm9ybUJ1ZmZlciB9IGZyb20gJy4vcmVjb3JkLXRyYW5zZm9ybS1idWZmZXInO1xuaW1wb3J0IHsgUGF0Y2hSZXN1bHQsIFJlY29yZENhY2hlVXBkYXRlRGV0YWlscyB9IGZyb20gJy4vcmVzcG9uc2UnO1xuXG5jb25zdCB7IGFzc2VydCwgZGVwcmVjYXRlIH0gPSBPcmJpdDtcblxuZXhwb3J0IGludGVyZmFjZSBBc3luY1JlY29yZENhY2hlU2V0dGluZ3M8XG4gIFFPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRDYWNoZVF1ZXJ5T3B0aW9ucyxcbiAgVE8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlVHJhbnNmb3JtT3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlclxuPiBleHRlbmRzIFJlY29yZENhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEI+IHtcbiAgcHJvY2Vzc29ycz86IEFzeW5jT3BlcmF0aW9uUHJvY2Vzc29yQ2xhc3NbXTtcbiAgcXVlcnlPcGVyYXRvcnM/OiBEaWN0PEFzeW5jUXVlcnlPcGVyYXRvcj47XG4gIHRyYW5zZm9ybU9wZXJhdG9ycz86IERpY3Q8QXN5bmNUcmFuc2Zvcm1PcGVyYXRvcj47XG4gIGludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcnM/OiBEaWN0PEFzeW5jSW52ZXJzZVRyYW5zZm9ybU9wZXJhdG9yPjtcbiAgZGVib3VuY2VMaXZlUXVlcmllcz86IGJvb2xlYW47XG4gIHRyYW5zZm9ybUJ1ZmZlcj86IFJlY29yZFRyYW5zZm9ybUJ1ZmZlcjtcbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEFzeW5jUmVjb3JkQ2FjaGU8XG4gICAgUU8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlUXVlcnlPcHRpb25zLFxuICAgIFRPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRDYWNoZVRyYW5zZm9ybU9wdGlvbnMsXG4gICAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gICAgVEIgPSBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICAgIFF1ZXJ5UmVzcG9uc2VEZXRhaWxzID0gdW5rbm93bixcbiAgICBUcmFuc2Zvcm1SZXNwb25zZURldGFpbHMgZXh0ZW5kcyBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMgPSBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHNcbiAgPlxuICBleHRlbmRzIFJlY29yZENhY2hlPFFPLCBUTywgUUIsIFRCPlxuICBpbXBsZW1lbnRzXG4gICAgQXN5bmNSZWNvcmRBY2Nlc3NvcixcbiAgICBBc3luY1JlY29yZFF1ZXJ5YWJsZTxRdWVyeVJlc3BvbnNlRGV0YWlscywgUUIsIFFPPixcbiAgICBBc3luY1JlY29yZFVwZGF0YWJsZTxUcmFuc2Zvcm1SZXNwb25zZURldGFpbHMsIFRCLCBUTz4ge1xuICBwcm90ZWN0ZWQgX3Byb2Nlc3NvcnM6IEFzeW5jT3BlcmF0aW9uUHJvY2Vzc29yW107XG4gIHByb3RlY3RlZCBfcXVlcnlPcGVyYXRvcnM6IERpY3Q8QXN5bmNRdWVyeU9wZXJhdG9yPjtcbiAgcHJvdGVjdGVkIF90cmFuc2Zvcm1PcGVyYXRvcnM6IERpY3Q8QXN5bmNUcmFuc2Zvcm1PcGVyYXRvcj47XG4gIHByb3RlY3RlZCBfaW52ZXJzZVRyYW5zZm9ybU9wZXJhdG9yczogRGljdDxBc3luY0ludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcj47XG4gIHByb3RlY3RlZCBfZGVib3VuY2VMaXZlUXVlcmllczogYm9vbGVhbjtcbiAgcHJvdGVjdGVkIF90cmFuc2Zvcm1CdWZmZXI/OiBSZWNvcmRUcmFuc2Zvcm1CdWZmZXI7XG5cbiAgY29uc3RydWN0b3Ioc2V0dGluZ3M6IEFzeW5jUmVjb3JkQ2FjaGVTZXR0aW5nczxRTywgVE8sIFFCLCBUQj4pIHtcbiAgICBzdXBlcihzZXR0aW5ncyk7XG5cbiAgICB0aGlzLl9xdWVyeU9wZXJhdG9ycyA9IHNldHRpbmdzLnF1ZXJ5T3BlcmF0b3JzID8/IEFzeW5jUXVlcnlPcGVyYXRvcnM7XG4gICAgdGhpcy5fdHJhbnNmb3JtT3BlcmF0b3JzID1cbiAgICAgIHNldHRpbmdzLnRyYW5zZm9ybU9wZXJhdG9ycyA/PyBBc3luY1RyYW5zZm9ybU9wZXJhdG9ycztcbiAgICB0aGlzLl9pbnZlcnNlVHJhbnNmb3JtT3BlcmF0b3JzID1cbiAgICAgIHNldHRpbmdzLmludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcnMgPz8gQXN5bmNJbnZlcnNlVHJhbnNmb3JtT3BlcmF0b3JzO1xuICAgIHRoaXMuX2RlYm91bmNlTGl2ZVF1ZXJpZXMgPSBzZXR0aW5ncy5kZWJvdW5jZUxpdmVRdWVyaWVzICE9PSBmYWxzZTtcbiAgICB0aGlzLl90cmFuc2Zvcm1CdWZmZXIgPSBzZXR0aW5ncy50cmFuc2Zvcm1CdWZmZXI7XG5cbiAgICBjb25zdCBwcm9jZXNzb3JzOiBBc3luY09wZXJhdGlvblByb2Nlc3NvckNsYXNzW10gPSBzZXR0aW5ncy5wcm9jZXNzb3JzXG4gICAgICA/IHNldHRpbmdzLnByb2Nlc3NvcnNcbiAgICAgIDogW0FzeW5jU2NoZW1hQ29uc2lzdGVuY3lQcm9jZXNzb3IsIEFzeW5jQ2FjaGVJbnRlZ3JpdHlQcm9jZXNzb3JdO1xuXG4gICAgaWYgKHNldHRpbmdzLmF1dG9WYWxpZGF0ZSAhPT0gZmFsc2UgJiYgc2V0dGluZ3MucHJvY2Vzc29ycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9jZXNzb3JzLnB1c2goQXN5bmNTY2hlbWFWYWxpZGF0aW9uUHJvY2Vzc29yKTtcbiAgICB9XG5cbiAgICB0aGlzLl9wcm9jZXNzb3JzID0gcHJvY2Vzc29ycy5tYXAoKFByb2Nlc3NvcikgPT4ge1xuICAgICAgbGV0IHByb2Nlc3NvciA9IG5ldyBQcm9jZXNzb3IodGhpcyk7XG4gICAgICBhc3NlcnQoXG4gICAgICAgICdFYWNoIHByb2Nlc3NvciBtdXN0IGV4dGVuZCBBc3luY09wZXJhdGlvblByb2Nlc3NvcicsXG4gICAgICAgIHByb2Nlc3NvciBpbnN0YW5jZW9mIEFzeW5jT3BlcmF0aW9uUHJvY2Vzc29yXG4gICAgICApO1xuICAgICAgcmV0dXJuIHByb2Nlc3NvcjtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBwcm9jZXNzb3JzKCk6IEFzeW5jT3BlcmF0aW9uUHJvY2Vzc29yW10ge1xuICAgIHJldHVybiB0aGlzLl9wcm9jZXNzb3JzO1xuICB9XG5cbiAgZ2V0UXVlcnlPcGVyYXRvcihvcDogc3RyaW5nKTogQXN5bmNRdWVyeU9wZXJhdG9yIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlPcGVyYXRvcnNbb3BdO1xuICB9XG5cbiAgZ2V0VHJhbnNmb3JtT3BlcmF0b3Iob3A6IHN0cmluZyk6IEFzeW5jVHJhbnNmb3JtT3BlcmF0b3Ige1xuICAgIHJldHVybiB0aGlzLl90cmFuc2Zvcm1PcGVyYXRvcnNbb3BdO1xuICB9XG5cbiAgZ2V0SW52ZXJzZVRyYW5zZm9ybU9wZXJhdG9yKG9wOiBzdHJpbmcpOiBBc3luY0ludmVyc2VUcmFuc2Zvcm1PcGVyYXRvciB7XG4gICAgcmV0dXJuIHRoaXMuX2ludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcnNbb3BdO1xuICB9XG5cbiAgLy8gQWJzdHJhY3QgbWV0aG9kcyBmb3IgZ2V0dGluZyByZWNvcmRzIGFuZCByZWxhdGlvbnNoaXBzXG4gIGFic3RyYWN0IGdldFJlY29yZEFzeW5jKFxuICAgIHJlY29yZElkZW50aXR5OiBSZWNvcmRJZGVudGl0eVxuICApOiBQcm9taXNlPEluaXRpYWxpemVkUmVjb3JkIHwgdW5kZWZpbmVkPjtcbiAgYWJzdHJhY3QgZ2V0UmVjb3Jkc0FzeW5jKFxuICAgIHR5cGVPcklkZW50aXRpZXM/OiBzdHJpbmcgfCBSZWNvcmRJZGVudGl0eVtdXG4gICk6IFByb21pc2U8SW5pdGlhbGl6ZWRSZWNvcmRbXT47XG4gIGFic3RyYWN0IGdldEludmVyc2VSZWxhdGlvbnNoaXBzQXN5bmMoXG4gICAgcmVjb3JkSWRlbnRpdHlPcklkZW50aXRpZXM6IFJlY29yZElkZW50aXR5IHwgUmVjb3JkSWRlbnRpdHlbXVxuICApOiBQcm9taXNlPFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W10+O1xuXG4gIC8vIEFic3RyYWN0IG1ldGhvZHMgZm9yIHNldHRpbmcgcmVjb3JkcyBhbmQgcmVsYXRpb25zaGlwc1xuICBhYnN0cmFjdCBzZXRSZWNvcmRBc3luYyhyZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkKTogUHJvbWlzZTx2b2lkPjtcbiAgYWJzdHJhY3Qgc2V0UmVjb3Jkc0FzeW5jKHJlY29yZHM6IEluaXRpYWxpemVkUmVjb3JkW10pOiBQcm9taXNlPHZvaWQ+O1xuICBhYnN0cmFjdCByZW1vdmVSZWNvcmRBc3luYyhcbiAgICByZWNvcmRJZGVudGl0eTogUmVjb3JkSWRlbnRpdHlcbiAgKTogUHJvbWlzZTxJbml0aWFsaXplZFJlY29yZCB8IHVuZGVmaW5lZD47XG4gIGFic3RyYWN0IHJlbW92ZVJlY29yZHNBc3luYyhcbiAgICByZWNvcmRJZGVudGl0aWVzOiBSZWNvcmRJZGVudGl0eVtdXG4gICk6IFByb21pc2U8SW5pdGlhbGl6ZWRSZWNvcmRbXT47XG4gIGFic3RyYWN0IGFkZEludmVyc2VSZWxhdGlvbnNoaXBzQXN5bmMoXG4gICAgcmVsYXRpb25zaGlwczogUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHlbXVxuICApOiBQcm9taXNlPHZvaWQ+O1xuICBhYnN0cmFjdCByZW1vdmVJbnZlcnNlUmVsYXRpb25zaGlwc0FzeW5jKFxuICAgIHJlbGF0aW9uc2hpcHM6IFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W11cbiAgKTogUHJvbWlzZTx2b2lkPjtcblxuICBhc3luYyBhcHBseVJlY29yZENoYW5nZXNldEFzeW5jKGNoYW5nZXNldDogUmVjb3JkQ2hhbmdlc2V0KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qge1xuICAgICAgc2V0UmVjb3JkcyxcbiAgICAgIHJlbW92ZVJlY29yZHMsXG4gICAgICBhZGRJbnZlcnNlUmVsYXRpb25zaGlwcyxcbiAgICAgIHJlbW92ZUludmVyc2VSZWxhdGlvbnNoaXBzXG4gICAgfSA9IGNoYW5nZXNldDtcblxuICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICBpZiAoc2V0UmVjb3JkcyAmJiBzZXRSZWNvcmRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHByb21pc2VzLnB1c2goYXdhaXQgdGhpcy5zZXRSZWNvcmRzQXN5bmMoc2V0UmVjb3JkcykpO1xuICAgIH1cbiAgICBpZiAocmVtb3ZlUmVjb3JkcyAmJiByZW1vdmVSZWNvcmRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHByb21pc2VzLnB1c2goYXdhaXQgdGhpcy5yZW1vdmVSZWNvcmRzQXN5bmMocmVtb3ZlUmVjb3JkcykpO1xuICAgIH1cbiAgICBpZiAoYWRkSW52ZXJzZVJlbGF0aW9uc2hpcHMgJiYgYWRkSW52ZXJzZVJlbGF0aW9uc2hpcHMubGVuZ3RoID4gMCkge1xuICAgICAgcHJvbWlzZXMucHVzaChcbiAgICAgICAgYXdhaXQgdGhpcy5hZGRJbnZlcnNlUmVsYXRpb25zaGlwc0FzeW5jKGFkZEludmVyc2VSZWxhdGlvbnNoaXBzKVxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlbW92ZUludmVyc2VSZWxhdGlvbnNoaXBzICYmIHJlbW92ZUludmVyc2VSZWxhdGlvbnNoaXBzLmxlbmd0aCA+IDApIHtcbiAgICAgIHByb21pc2VzLnB1c2goXG4gICAgICAgIGF3YWl0IHRoaXMucmVtb3ZlSW52ZXJzZVJlbGF0aW9uc2hpcHNBc3luYyhyZW1vdmVJbnZlcnNlUmVsYXRpb25zaGlwcylcbiAgICAgICk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICB9XG5cbiAgYXN5bmMgZ2V0UmVsYXRlZFJlY29yZEFzeW5jKFxuICAgIGlkZW50aXR5OiBSZWNvcmRJZGVudGl0eSxcbiAgICByZWxhdGlvbnNoaXA6IHN0cmluZ1xuICApOiBQcm9taXNlPFJlY29yZElkZW50aXR5IHwgbnVsbCB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHRoaXMuZ2V0UmVjb3JkQXN5bmMoaWRlbnRpdHkpO1xuICAgIGlmIChyZWNvcmQpIHtcbiAgICAgIHJldHVybiBkZWVwR2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddKTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGFzeW5jIGdldFJlbGF0ZWRSZWNvcmRzQXN5bmMoXG4gICAgaWRlbnRpdHk6IFJlY29yZElkZW50aXR5LFxuICAgIHJlbGF0aW9uc2hpcDogc3RyaW5nXG4gICk6IFByb21pc2U8UmVjb3JkSWRlbnRpdHlbXSB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHRoaXMuZ2V0UmVjb3JkQXN5bmMoaWRlbnRpdHkpO1xuICAgIGlmIChyZWNvcmQpIHtcbiAgICAgIHJldHVybiBkZWVwR2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddKTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWVyaWVzIHRoZSBjYWNoZS5cbiAgICovXG4gIHF1ZXJ5PFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkUXVlcnlSZXN1bHQgPSBSZWNvcmRRdWVyeVJlc3VsdD4oXG4gICAgcXVlcnlPckV4cHJlc3Npb25zOiBRdWVyeU9yRXhwcmVzc2lvbnM8UmVjb3JkUXVlcnlFeHByZXNzaW9uLCBRQj4sXG4gICAgb3B0aW9ucz86IERlZmF1bHRSZXF1ZXN0T3B0aW9uczxRTz4sXG4gICAgaWQ/OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxSZXF1ZXN0RGF0YT47XG4gIHF1ZXJ5PFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkUXVlcnlSZXN1bHQgPSBSZWNvcmRRdWVyeVJlc3VsdD4oXG4gICAgcXVlcnlPckV4cHJlc3Npb25zOiBRdWVyeU9yRXhwcmVzc2lvbnM8UmVjb3JkUXVlcnlFeHByZXNzaW9uLCBRQj4sXG4gICAgb3B0aW9uczogRnVsbFJlcXVlc3RPcHRpb25zPFFPPixcbiAgICBpZD86IHN0cmluZ1xuICApOiBQcm9taXNlPEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgUXVlcnlSZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj4+O1xuICBhc3luYyBxdWVyeTxSZXF1ZXN0RGF0YSBleHRlbmRzIFJlY29yZFF1ZXJ5UmVzdWx0ID0gUmVjb3JkUXVlcnlSZXN1bHQ+KFxuICAgIHF1ZXJ5T3JFeHByZXNzaW9uczogUXVlcnlPckV4cHJlc3Npb25zPFJlY29yZFF1ZXJ5RXhwcmVzc2lvbiwgUUI+LFxuICAgIG9wdGlvbnM/OiBRTyxcbiAgICBpZD86IHN0cmluZ1xuICApOiBQcm9taXNlPFxuICAgIHwgUmVxdWVzdERhdGFcbiAgICB8IEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgUXVlcnlSZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj5cbiAgPiB7XG4gICAgY29uc3QgcXVlcnkgPSBidWlsZFF1ZXJ5KFxuICAgICAgcXVlcnlPckV4cHJlc3Npb25zLFxuICAgICAgb3B0aW9ucyxcbiAgICAgIGlkLFxuICAgICAgdGhpcy5fcXVlcnlCdWlsZGVyXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fcXVlcnk8UmVxdWVzdERhdGE+KHF1ZXJ5LCBvcHRpb25zKTtcblxuICAgIGlmIChvcHRpb25zPy5mdWxsUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEgYXMgUmVxdWVzdERhdGE7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIGNhY2hlLlxuICAgKi9cbiAgdXBkYXRlPFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0PihcbiAgICB0cmFuc2Zvcm1Pck9wZXJhdGlvbnM6IFRyYW5zZm9ybU9yT3BlcmF0aW9uczxSZWNvcmRPcGVyYXRpb24sIFRCPixcbiAgICBvcHRpb25zPzogRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPixcbiAgICBpZD86IHN0cmluZ1xuICApOiBQcm9taXNlPFJlcXVlc3REYXRhPjtcbiAgdXBkYXRlPFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0PihcbiAgICB0cmFuc2Zvcm1Pck9wZXJhdGlvbnM6IFRyYW5zZm9ybU9yT3BlcmF0aW9uczxSZWNvcmRPcGVyYXRpb24sIFRCPixcbiAgICBvcHRpb25zOiBGdWxsUmVxdWVzdE9wdGlvbnM8VE8+LFxuICAgIGlkPzogc3RyaW5nXG4gICk6IFByb21pc2U8XG4gICAgRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUcmFuc2Zvcm1SZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj5cbiAgPjtcbiAgYXN5bmMgdXBkYXRlPFxuICAgIFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0XG4gID4oXG4gICAgdHJhbnNmb3JtT3JPcGVyYXRpb25zOiBUcmFuc2Zvcm1Pck9wZXJhdGlvbnM8UmVjb3JkT3BlcmF0aW9uLCBUQj4sXG4gICAgb3B0aW9ucz86IFRPLFxuICAgIGlkPzogc3RyaW5nXG4gICk6IFByb21pc2U8XG4gICAgfCBSZXF1ZXN0RGF0YVxuICAgIHwgRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUcmFuc2Zvcm1SZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj5cbiAgPiB7XG4gICAgY29uc3QgdHJhbnNmb3JtID0gYnVpbGRUcmFuc2Zvcm0oXG4gICAgICB0cmFuc2Zvcm1Pck9wZXJhdGlvbnMsXG4gICAgICBvcHRpb25zLFxuICAgICAgaWQsXG4gICAgICB0aGlzLl90cmFuc2Zvcm1CdWlsZGVyXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fdXBkYXRlPFJlcXVlc3REYXRhPih0cmFuc2Zvcm0sIG9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnM/LmZ1bGxSZXNwb25zZSkge1xuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuZGF0YSBhcyBSZXF1ZXN0RGF0YTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGF0Y2hlcyB0aGUgY2FjaGUgd2l0aCBhbiBvcGVyYXRpb24gb3Igb3BlcmF0aW9ucy5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAgICovXG4gIGFzeW5jIHBhdGNoKFxuICAgIG9wZXJhdGlvbk9yT3BlcmF0aW9uczpcbiAgICAgIHwgUmVjb3JkT3BlcmF0aW9uXG4gICAgICB8IFJlY29yZE9wZXJhdGlvbltdXG4gICAgICB8IFJlY29yZE9wZXJhdGlvblRlcm1cbiAgICAgIHwgUmVjb3JkT3BlcmF0aW9uVGVybVtdXG4gICAgICB8IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXJGdW5jXG4gICk6IFByb21pc2U8UGF0Y2hSZXN1bHQ+IHtcbiAgICBkZXByZWNhdGUoXG4gICAgICAnQXN5bmNSZWNvcmRDYWNoZSNwYXRjaCBoYXMgYmVlbiBkZXByZWNhdGVkLiBVc2UgQXN5bmNSZWNvcmRDYWNoZSN1cGRhdGUgaW5zdGVhZC4nXG4gICAgKTtcblxuICAgIC8vIFRPRE8gLSBXaHkgaXMgdGhpcyBgdGhpc2AgY2FzdCBuZWNlc3NhcnkgZm9yIFRTIHRvIHVuZGVyc3RhbmQgdGhlIGNvcnJlY3RcbiAgICAvLyBtZXRob2Qgb3ZlcmxvYWQ/XG4gICAgY29uc3QgeyBkYXRhLCBkZXRhaWxzIH0gPSBhd2FpdCAodGhpcyBhcyBhbnkpLnVwZGF0ZShcbiAgICAgIG9wZXJhdGlvbk9yT3BlcmF0aW9ucyxcbiAgICAgIHtcbiAgICAgICAgZnVsbFJlc3BvbnNlOiB0cnVlXG4gICAgICB9XG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbnZlcnNlOiBkZXRhaWxzPy5pbnZlcnNlT3BlcmF0aW9ucyB8fCBbXSxcbiAgICAgIGRhdGE6IEFycmF5LmlzQXJyYXkoZGF0YSkgPyBkYXRhIDogW2RhdGFdXG4gICAgfTtcbiAgfVxuXG4gIGxpdmVRdWVyeShcbiAgICBxdWVyeU9yRXhwcmVzc2lvbnM6IFF1ZXJ5T3JFeHByZXNzaW9uczxSZWNvcmRRdWVyeUV4cHJlc3Npb24sIFFCPixcbiAgICBvcHRpb25zPzogRGVmYXVsdFJlcXVlc3RPcHRpb25zPFFPPixcbiAgICBpZD86IHN0cmluZ1xuICApOiBBc3luY0xpdmVRdWVyeTxRTywgVE8sIFFCLCBUQj4ge1xuICAgIGNvbnN0IHF1ZXJ5ID0gYnVpbGRRdWVyeShcbiAgICAgIHF1ZXJ5T3JFeHByZXNzaW9ucyxcbiAgICAgIG9wdGlvbnMsXG4gICAgICBpZCxcbiAgICAgIHRoaXMucXVlcnlCdWlsZGVyXG4gICAgKTtcblxuICAgIGxldCBkZWJvdW5jZSA9IG9wdGlvbnMgJiYgKG9wdGlvbnMgYXMgYW55KS5kZWJvdW5jZTtcbiAgICBpZiAodHlwZW9mIGRlYm91bmNlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIGRlYm91bmNlID0gdGhpcy5fZGVib3VuY2VMaXZlUXVlcmllcztcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEFzeW5jTGl2ZVF1ZXJ5PFFPLCBUTywgUUIsIFRCPih7XG4gICAgICBkZWJvdW5jZSxcbiAgICAgIGNhY2hlOiB0aGlzLFxuICAgICAgcXVlcnlcbiAgICB9KTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFByb3RlY3RlZCBtZXRob2RzXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgcHJvdGVjdGVkIGFzeW5jIF9xdWVyeTxcbiAgICBSZXF1ZXN0RGF0YSBleHRlbmRzIFJlY29yZFF1ZXJ5UmVzdWx0ID0gUmVjb3JkUXVlcnlSZXN1bHRcbiAgPihcbiAgICBxdWVyeTogUmVjb3JkUXVlcnksXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9wdGlvbnM/OiBRT1xuICApOiBQcm9taXNlPEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgUXVlcnlSZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj4+IHtcbiAgICBsZXQgZGF0YTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHF1ZXJ5LmV4cHJlc3Npb25zKSkge1xuICAgICAgZGF0YSA9IFtdO1xuICAgICAgZm9yIChsZXQgZXhwcmVzc2lvbiBvZiBxdWVyeS5leHByZXNzaW9ucykge1xuICAgICAgICBjb25zdCBxdWVyeU9wZXJhdG9yID0gdGhpcy5nZXRRdWVyeU9wZXJhdG9yKGV4cHJlc3Npb24ub3ApO1xuICAgICAgICBpZiAoIXF1ZXJ5T3BlcmF0b3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBmaW5kIHF1ZXJ5IG9wZXJhdG9yOiAke2V4cHJlc3Npb24ub3B9YCk7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YS5wdXNoKFxuICAgICAgICAgIGF3YWl0IHF1ZXJ5T3BlcmF0b3IoXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgZXhwcmVzc2lvbixcbiAgICAgICAgICAgIHRoaXMuZ2V0UXVlcnlPcHRpb25zKHF1ZXJ5LCBleHByZXNzaW9uKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZXhwcmVzc2lvbiA9IHF1ZXJ5LmV4cHJlc3Npb25zIGFzIFJlY29yZFF1ZXJ5RXhwcmVzc2lvbjtcbiAgICAgIGNvbnN0IHF1ZXJ5T3BlcmF0b3IgPSB0aGlzLmdldFF1ZXJ5T3BlcmF0b3IoZXhwcmVzc2lvbi5vcCk7XG4gICAgICBpZiAoIXF1ZXJ5T3BlcmF0b3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZmluZCBxdWVyeSBvcGVyYXRvcjogJHtleHByZXNzaW9uLm9wfWApO1xuICAgICAgfVxuICAgICAgZGF0YSA9IGF3YWl0IHF1ZXJ5T3BlcmF0b3IoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIGV4cHJlc3Npb24sXG4gICAgICAgIHRoaXMuZ2V0UXVlcnlPcHRpb25zKHF1ZXJ5LCBleHByZXNzaW9uKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBkYXRhOiBkYXRhIGFzIFJlcXVlc3REYXRhIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgX3VwZGF0ZTxcbiAgICBSZXF1ZXN0RGF0YSBleHRlbmRzIFJlY29yZFRyYW5zZm9ybVJlc3VsdCA9IFJlY29yZFRyYW5zZm9ybVJlc3VsdFxuICA+KFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtLFxuICAgIG9wdGlvbnM/OiBUT1xuICApOiBQcm9taXNlPFxuICAgIEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgVHJhbnNmb3JtUmVzcG9uc2VEZXRhaWxzLCBSZWNvcmRPcGVyYXRpb24+XG4gID4ge1xuICAgIGlmICh0aGlzLmdldFRyYW5zZm9ybU9wdGlvbnModHJhbnNmb3JtKT8udXNlQnVmZmVyKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCB0aGlzLl9pbml0VHJhbnNmb3JtQnVmZmVyKHRyYW5zZm9ybSk7XG5cbiAgICAgIGJ1ZmZlci5zdGFydFRyYWNraW5nQ2hhbmdlcygpO1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGJ1ZmZlci51cGRhdGUodHJhbnNmb3JtLCB7XG4gICAgICAgIGZ1bGxSZXNwb25zZTogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGNoYW5nZXMgPSBidWZmZXIuc3RvcFRyYWNraW5nQ2hhbmdlcygpO1xuXG4gICAgICBhd2FpdCB0aGlzLmFwcGx5UmVjb3JkQ2hhbmdlc2V0QXN5bmMoY2hhbmdlcyk7XG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYXBwbGllZE9wZXJhdGlvbnMsXG4gICAgICAgIGFwcGxpZWRPcGVyYXRpb25SZXN1bHRzXG4gICAgICB9ID0gcmVzcG9uc2UuZGV0YWlscyBhcyBUcmFuc2Zvcm1SZXNwb25zZURldGFpbHM7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBhcHBsaWVkT3BlcmF0aW9ucy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB0aGlzLmVtaXQoJ3BhdGNoJywgYXBwbGllZE9wZXJhdGlvbnNbaV0sIGFwcGxpZWRPcGVyYXRpb25SZXN1bHRzW2ldKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3BvbnNlIGFzIEZ1bGxSZXNwb25zZTxcbiAgICAgICAgUmVxdWVzdERhdGEsXG4gICAgICAgIFRyYW5zZm9ybVJlc3BvbnNlRGV0YWlscyxcbiAgICAgICAgUmVjb3JkT3BlcmF0aW9uXG4gICAgICA+O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IHtcbiAgICAgICAgZGF0YTogW11cbiAgICAgIH0gYXMgRnVsbFJlc3BvbnNlPFxuICAgICAgICBSZWNvcmRPcGVyYXRpb25SZXN1bHRbXSxcbiAgICAgICAgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzLFxuICAgICAgICBSZWNvcmRPcGVyYXRpb25cbiAgICAgID47XG5cbiAgICAgIGlmIChvcHRpb25zPy5mdWxsUmVzcG9uc2UpIHtcbiAgICAgICAgcmVzcG9uc2UuZGV0YWlscyA9IHtcbiAgICAgICAgICBhcHBsaWVkT3BlcmF0aW9uczogW10sXG4gICAgICAgICAgYXBwbGllZE9wZXJhdGlvblJlc3VsdHM6IFtdLFxuICAgICAgICAgIGludmVyc2VPcGVyYXRpb25zOiBbXVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBsZXQgZGF0YTogUmVjb3JkVHJhbnNmb3JtUmVzdWx0O1xuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm0ub3BlcmF0aW9ucykpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fYXBwbHlUcmFuc2Zvcm1PcGVyYXRpb25zKFxuICAgICAgICAgIHRyYW5zZm9ybSxcbiAgICAgICAgICB0cmFuc2Zvcm0ub3BlcmF0aW9ucyxcbiAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICAgIGRhdGEgPSByZXNwb25zZS5kYXRhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fYXBwbHlUcmFuc2Zvcm1PcGVyYXRpb24oXG4gICAgICAgICAgdHJhbnNmb3JtLFxuICAgICAgICAgIHRyYW5zZm9ybS5vcGVyYXRpb25zLFxuICAgICAgICAgIHJlc3BvbnNlLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzcG9uc2UuZGF0YSkpIHtcbiAgICAgICAgICBkYXRhID0gcmVzcG9uc2UuZGF0YVswXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucz8uZnVsbFJlc3BvbnNlKSB7XG4gICAgICAgIHJlc3BvbnNlLmRldGFpbHM/LmludmVyc2VPcGVyYXRpb25zLnJldmVyc2UoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ucmVzcG9uc2UsXG4gICAgICAgIGRhdGFcbiAgICAgIH0gYXMgRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUcmFuc2Zvcm1SZXNwb25zZURldGFpbHMsIFJlY29yZE9wZXJhdGlvbj47XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9nZXRUcmFuc2Zvcm1CdWZmZXIoKTogUmVjb3JkVHJhbnNmb3JtQnVmZmVyIHtcbiAgICBpZiAodGhpcy5fdHJhbnNmb3JtQnVmZmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBBc3NlcnRpb24oXG4gICAgICAgICd0cmFuc2Zvcm1CdWZmZXIgbXVzdCBiZSBwcm92aWRlZCB0byBjYWNoZSB2aWEgY29uc3RydWN0b3Igc2V0dGluZ3MnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fdHJhbnNmb3JtQnVmZmVyO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIF9pbml0VHJhbnNmb3JtQnVmZmVyKFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtXG4gICk6IFByb21pc2U8UmVjb3JkVHJhbnNmb3JtQnVmZmVyPiB7XG4gICAgY29uc3QgYnVmZmVyID0gdGhpcy5fZ2V0VHJhbnNmb3JtQnVmZmVyKCk7XG5cbiAgICBjb25zdCByZWNvcmRzID0gcmVjb3Jkc1JlZmVyZW5jZWRCeU9wZXJhdGlvbnMoXG4gICAgICB0b0FycmF5KHRyYW5zZm9ybS5vcGVyYXRpb25zKVxuICAgICk7XG4gICAgY29uc3QgaW52ZXJzZVJlbGF0aW9uc2hpcHMgPSBhd2FpdCB0aGlzLmdldEludmVyc2VSZWxhdGlvbnNoaXBzQXN5bmMoXG4gICAgICByZWNvcmRzXG4gICAgKTtcbiAgICBjb25zdCByZWxhdGVkUmVjb3JkcyA9IGludmVyc2VSZWxhdGlvbnNoaXBzLm1hcCgoaXIpID0+IGlyLnJlY29yZCk7XG4gICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkocmVjb3JkcywgcmVsYXRlZFJlY29yZHMpO1xuXG4gICAgYnVmZmVyLnJlc2V0U3RhdGUoKTtcbiAgICBidWZmZXIuc2V0UmVjb3Jkc1N5bmMoYXdhaXQgdGhpcy5nZXRSZWNvcmRzQXN5bmMocmVjb3JkcykpO1xuICAgIGJ1ZmZlci5hZGRJbnZlcnNlUmVsYXRpb25zaGlwc1N5bmMoaW52ZXJzZVJlbGF0aW9uc2hpcHMpO1xuXG4gICAgcmV0dXJuIGJ1ZmZlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBfYXBwbHlUcmFuc2Zvcm1PcGVyYXRpb25zKFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtLFxuICAgIG9wczogUmVjb3JkT3BlcmF0aW9uW10gfCBSZWNvcmRPcGVyYXRpb25UZXJtW10sXG4gICAgcmVzcG9uc2U6IEZ1bGxSZXNwb25zZTxcbiAgICAgIFJlY29yZE9wZXJhdGlvblJlc3VsdFtdLFxuICAgICAgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzLFxuICAgICAgUmVjb3JkT3BlcmF0aW9uXG4gICAgPixcbiAgICBwcmltYXJ5ID0gZmFsc2VcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yIChsZXQgb3Agb2Ygb3BzKSB7XG4gICAgICBhd2FpdCB0aGlzLl9hcHBseVRyYW5zZm9ybU9wZXJhdGlvbih0cmFuc2Zvcm0sIG9wLCByZXNwb25zZSwgcHJpbWFyeSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIF9hcHBseVRyYW5zZm9ybU9wZXJhdGlvbihcbiAgICB0cmFuc2Zvcm06IFJlY29yZFRyYW5zZm9ybSxcbiAgICBvcGVyYXRpb246IFJlY29yZE9wZXJhdGlvbiB8IFJlY29yZE9wZXJhdGlvblRlcm0sXG4gICAgcmVzcG9uc2U6IEZ1bGxSZXNwb25zZTxcbiAgICAgIFJlY29yZE9wZXJhdGlvblJlc3VsdFtdLFxuICAgICAgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzLFxuICAgICAgUmVjb3JkT3BlcmF0aW9uXG4gICAgPixcbiAgICBwcmltYXJ5ID0gZmFsc2VcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKG9wZXJhdGlvbiBpbnN0YW5jZW9mIE9wZXJhdGlvblRlcm0pIHtcbiAgICAgIG9wZXJhdGlvbiA9IG9wZXJhdGlvbi50b09wZXJhdGlvbigpIGFzIFJlY29yZE9wZXJhdGlvbjtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBwcm9jZXNzb3Igb2YgdGhpcy5fcHJvY2Vzc29ycykge1xuICAgICAgYXdhaXQgcHJvY2Vzc29yLnZhbGlkYXRlKG9wZXJhdGlvbik7XG4gICAgfVxuXG4gICAgY29uc3QgaW52ZXJzZVRyYW5zZm9ybU9wZXJhdG9yID0gdGhpcy5nZXRJbnZlcnNlVHJhbnNmb3JtT3BlcmF0b3IoXG4gICAgICBvcGVyYXRpb24ub3BcbiAgICApO1xuICAgIGNvbnN0IGludmVyc2VPcDpcbiAgICAgIHwgUmVjb3JkT3BlcmF0aW9uXG4gICAgICB8IHVuZGVmaW5lZCA9IGF3YWl0IGludmVyc2VUcmFuc2Zvcm1PcGVyYXRvcihcbiAgICAgIHRoaXMsXG4gICAgICBvcGVyYXRpb24sXG4gICAgICB0aGlzLmdldFRyYW5zZm9ybU9wdGlvbnModHJhbnNmb3JtLCBvcGVyYXRpb24pXG4gICAgKTtcbiAgICBpZiAoaW52ZXJzZU9wKSB7XG4gICAgICByZXNwb25zZS5kZXRhaWxzPy5pbnZlcnNlT3BlcmF0aW9ucz8ucHVzaChpbnZlcnNlT3ApO1xuXG4gICAgICAvLyBRdWVyeSBhbmQgcGVyZm9ybSByZWxhdGVkIGBiZWZvcmVgIG9wZXJhdGlvbnNcbiAgICAgIGZvciAobGV0IHByb2Nlc3NvciBvZiB0aGlzLl9wcm9jZXNzb3JzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2FwcGx5VHJhbnNmb3JtT3BlcmF0aW9ucyhcbiAgICAgICAgICB0cmFuc2Zvcm0sXG4gICAgICAgICAgYXdhaXQgcHJvY2Vzc29yLmJlZm9yZShvcGVyYXRpb24pLFxuICAgICAgICAgIHJlc3BvbnNlXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIFF1ZXJ5IHJlbGF0ZWQgYGFmdGVyYCBvcGVyYXRpb25zIGJlZm9yZSBwZXJmb3JtaW5nXG4gICAgICAvLyB0aGUgcmVxdWVzdGVkIG9wZXJhdGlvbi4gVGhlc2Ugd2lsbCBiZSBhcHBsaWVkIG9uIHN1Y2Nlc3MuXG4gICAgICBsZXQgcHJlcGFyZWRPcHMgPSBbXTtcbiAgICAgIGZvciAobGV0IHByb2Nlc3NvciBvZiB0aGlzLl9wcm9jZXNzb3JzKSB7XG4gICAgICAgIHByZXBhcmVkT3BzLnB1c2goYXdhaXQgcHJvY2Vzc29yLmFmdGVyKG9wZXJhdGlvbikpO1xuICAgICAgfVxuXG4gICAgICAvLyBQZXJmb