UNPKG

@orbit/memory

Version:

Orbit source for managing in-memory records.

260 lines 41.1 kB
import { Orbit } from '@orbit/core'; import { ImmutableMap } from '@orbit/immutable'; import { SimpleRecordTransformBuffer, SyncRecordCache } from '@orbit/record-cache'; import { coalesceRecordOperations, equalRecordIdentities } from '@orbit/records'; import { clone, toArray } from '@orbit/utils'; const { assert, deprecate } = Orbit; /** * A cache used to access records in memory. * * Because data is stored in immutable maps, this type of cache can be forked * efficiently. */ export class MemoryCache extends SyncRecordCache { constructor(settings) { const { base, trackUpdateOperations } = settings; super(settings); this._base = base; // Track update operations if explicitly told to do so, or if a `base` // cache has been specified. this._isTrackingUpdateOperations = trackUpdateOperations !== null && trackUpdateOperations !== void 0 ? trackUpdateOperations : base !== undefined; this.reset(); } get base() { return this._base; } /** * Create a clone, or "fork", from a "base" cache. * * The forked cache will have the same `schema` and `keyMap` as its base * source. The forked cache will start with the same immutable document as the * base source. Its contents and log will evolve independently. * * @returns the forked cache */ fork(settings = {}) { var _a, _b, _c, _d, _e; // required settings settings.base = this; settings.schema = this.schema; settings.keyMap = this._keyMap; // customizable settings (_a = settings.queryBuilder) !== null && _a !== void 0 ? _a : (settings.queryBuilder = this._queryBuilder); (_b = settings.transformBuilder) !== null && _b !== void 0 ? _b : (settings.transformBuilder = this._transformBuilder); (_c = settings.defaultQueryOptions) !== null && _c !== void 0 ? _c : (settings.defaultQueryOptions = this._defaultQueryOptions); (_d = settings.defaultTransformOptions) !== null && _d !== void 0 ? _d : (settings.defaultTransformOptions = this._defaultTransformOptions); if (settings.autoValidate !== false) { (_e = settings.validatorFor) !== null && _e !== void 0 ? _e : (settings.validatorFor = this._validatorFor); if (settings.autoValidate === undefined && settings.validatorFor === undefined) { settings.autoValidate = false; } } return new MemoryCache(settings); } merge(forkedCache, options) { let { coalesce, ...remainingOptions } = options !== null && options !== void 0 ? options : {}; assert('MemoryCache#merge can only merge a forked cache that is configured with `trackUpdateOperations: true`.', forkedCache.isTrackingUpdateOperations); let ops = forkedCache.getAllUpdateOperations(); if (coalesce !== false) { ops = coalesceRecordOperations(ops); } if (options === null || options === void 0 ? void 0 : options.fullResponse) { return this.update(ops, remainingOptions); } else { return this.update(ops, remainingOptions); } } /** * Rebase resets this cache's state to that of its base cache, then re-applies * any tracked update operations. * * Rebasing requires both a `base` cache as well as tracking of update * operations (which is enabled by default when a `base` cache is assigned). */ rebase() { const base = this._base; assert('A `base` cache must be defined for `rebase` to work', base !== undefined); assert('MemoryCache#rebase requires that the cache is configured with `trackUpdateOperations: true`.', this._isTrackingUpdateOperations); // get update ops prior to resetting state let ops = this.getAllUpdateOperations(); // reset the state of the cache to match its base cache this.reset(); // reapply update ops this.update(ops); } getRecordSync(identity) { return this._records[identity.type].get(identity.id); } getRecordsSync(typeOrIdentities) { if (typeOrIdentities === undefined) { const types = Object.keys(this.schema.models); const records = []; types.forEach((type) => Array.prototype.push.apply(records, Array.from(this._records[type].values()))); return records; } else if (typeof typeOrIdentities === 'string') { const type = typeOrIdentities; return Array.from(this._records[type].values()); } else { const records = []; const identities = typeOrIdentities; for (let identity of identities) { let record = this.getRecordSync(identity); if (record) { records.push(record); } } return records; } } setRecordSync(record) { this._records[record.type].set(record.id, record); } setRecordsSync(records) { let typedMap = {}; for (let record of records) { typedMap[record.type] = typedMap[record.type] || []; typedMap[record.type].push([record.id, record]); } for (let type in typedMap) { this._records[type].setMany(typedMap[type]); } } removeRecordSync(recordIdentity) { const recordMap = this._records[recordIdentity.type]; const record = recordMap.get(recordIdentity.id); if (record) { recordMap.remove(recordIdentity.id); return record; } else { return undefined; } } removeRecordsSync(recordIdentities) { const records = []; const typedIds = {}; for (let recordIdentity of recordIdentities) { let record = this.getRecordSync(recordIdentity); if (record) { records.push(record); typedIds[record.type] = typedIds[record.type] || []; typedIds[record.type].push(recordIdentity.id); } } for (let type in typedIds) { this._records[type].removeMany(typedIds[type]); } return records; } getInverseRelationshipsSync(recordIdentityOrIdentities) { const results = []; const identities = Array.isArray(recordIdentityOrIdentities) ? recordIdentityOrIdentities : [recordIdentityOrIdentities]; for (let identity of identities) { const result = this._inverseRelationships[identity.type].get(identity.id); if (result) { Array.prototype.push.apply(results, result); } } return results; } addInverseRelationshipsSync(relationships) { relationships.forEach((r) => { let rels = this._inverseRelationships[r.relatedRecord.type].get(r.relatedRecord.id); rels = rels ? [...rels, clone(r)] : [clone(r)]; this._inverseRelationships[r.relatedRecord.type].set(r.relatedRecord.id, rels); }); } removeInverseRelationshipsSync(relationships) { relationships.forEach((r) => { let rels = this._inverseRelationships[r.relatedRecord.type].get(r.relatedRecord.id); if (rels) { let newRels = rels.filter((rel) => !(equalRecordIdentities(rel.record, r.record) && rel.relationship === r.relationship)); this._inverseRelationships[r.relatedRecord.type].set(r.relatedRecord.id, newRels); } }); } /** * Resets the cache's to its initial state, which will be either empty or a * clone of its `base` cache, if it has one. */ reset() { let base = this._base; if (arguments.length > 0) { deprecate('Calling MemoryCache#reset with a `base` argument is deprecated. Instead configure your MemoryCache with a `base` cache.'); base !== null && base !== void 0 ? base : (base = arguments[0]); } this._records = {}; if (this._isTrackingUpdateOperations) { this._updateOperations = []; } Object.keys(this._schema.models).forEach((type) => { let baseRecords = base === null || base === void 0 ? void 0 : base._records[type]; this._records[type] = new ImmutableMap(baseRecords); }); this._resetInverseRelationships(base); this._processors.forEach((processor) => processor.reset(base)); this.emit('reset'); } /** * Upgrade the cache based on the current state of the schema. */ upgrade() { Object.keys(this._schema.models).forEach((type) => { if (!this._records[type]) { this._records[type] = new ImmutableMap(); } }); this._resetInverseRelationships(); for (let processor of this._processors) { processor.upgrade(); } } get isTrackingUpdateOperations() { return this._isTrackingUpdateOperations; } getAllUpdateOperations() { assert('MemoryCache#getAllUpdateOperations requires that cache be configured with `trackUpdateOperations: true`.', this._isTrackingUpdateOperations); return this._updateOperations; } ///////////////////////////////////////////////////////////////////////////// // Protected methods ///////////////////////////////////////////////////////////////////////////// _update(transform, options) { if (this._isTrackingUpdateOperations) { Array.prototype.push.apply(this._updateOperations, toArray(transform.operations)); } return super._update(transform, options); } /** * Override `_getTransformBuffer` on base `SyncRecordCache` to provide a * `transformBuffer` if a custom one hasn't been provided via the constructor * setting. */ _getTransformBuffer() { if (this._transformBuffer === undefined) { const { schema, keyMap } = this; this._transformBuffer = new SimpleRecordTransformBuffer({ schema, keyMap }); } return this._transformBuffer; } _resetInverseRelationships(base) { const inverseRelationships = {}; Object.keys(this._schema.models).forEach((type) => { let baseRelationships = base && base._inverseRelationships[type]; inverseRelationships[type] = new ImmutableMap(baseRelationships); }); this._inverseRelationships = inverseRelationships; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LWNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbW9yeS1jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBT3BDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBTUwsMkJBQTJCLEVBQzNCLGVBQWUsRUFFaEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLHFCQUFxQixFQVF0QixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxLQUFLLEVBQVEsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXBELE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsS0FBSyxDQUFDO0FBb0NwQzs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxXQU9YLFNBQVEsZUFBeUM7SUFTakQsWUFBWSxRQUF1RDtRQUNqRSxNQUFNLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLEdBQUcsUUFBUSxDQUFDO1FBRWpELEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVoQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztRQUVsQixzRUFBc0U7UUFDdEUsNEJBQTRCO1FBQzVCLElBQUksQ0FBQywyQkFBMkI7WUFDOUIscUJBQXFCLGFBQXJCLHFCQUFxQixjQUFyQixxQkFBcUIsR0FBSSxJQUFJLEtBQUssU0FBUyxDQUFDO1FBRTlDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsSUFBSSxDQUNGLFdBQW1FLEVBQUU7O1FBRXJFLG9CQUFvQjtRQUNwQixRQUFRLENBQUMsSUFBSSxHQUFHLElBQUks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LENBQUMsZ0JBQWdCLENBQUM7SUFDL0IsQ0FBQztJQUVTLDBCQUEwQixDQUNsQyxJQUE0QztRQUU1QyxNQUFNLG9CQUFvQixHQUV0QixFQUFFLENBQUM7UUFDUCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDaEQsSUFBSSxpQkFBaUIsR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pFLG9CQUFvQixDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksWUFBWSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDbkUsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMscUJBQXFCLEdBQUcsb0JBQW9CLENBQUM7SUFDcEQsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3JiaXQgfSBmcm9tICdAb3JiaXQvY29yZSc7XG5pbXBvcnQge1xuICBEZWZhdWx0UmVxdWVzdE9wdGlvbnMsXG4gIEZ1bGxSZXF1ZXN0T3B0aW9ucyxcbiAgRnVsbFJlc3BvbnNlLFxuICBSZXF1ZXN0T3B0aW9uc1xufSBmcm9tICdAb3JiaXQvZGF0YSc7XG5pbXBvcnQgeyBJbW11dGFibGVNYXAgfSBmcm9tICdAb3JiaXQvaW1tdXRhYmxlJztcbmltcG9ydCB7XG4gIFJlY29yZENhY2hlUXVlcnlPcHRpb25zLFxuICBSZWNvcmRDYWNoZVRyYW5zZm9ybU9wdGlvbnMsXG4gIFJlY29yZENhY2hlVXBkYXRlRGV0YWlscyxcbiAgUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHksXG4gIFJlY29yZFRyYW5zZm9ybUJ1ZmZlcixcbiAgU2ltcGxlUmVjb3JkVHJhbnNmb3JtQnVmZmVyLFxuICBTeW5jUmVjb3JkQ2FjaGUsXG4gIFN5bmNSZWNvcmRDYWNoZVNldHRpbmdzXG59IGZyb20gJ0BvcmJpdC9yZWNvcmQtY2FjaGUnO1xuaW1wb3J0IHtcbiAgY29hbGVzY2VSZWNvcmRPcGVyYXRpb25zLFxuICBlcXVhbFJlY29yZElkZW50aXRpZXMsXG4gIEluaXRpYWxpemVkUmVjb3JkLFxuICBSZWNvcmRJZGVudGl0eSxcbiAgUmVjb3JkT3BlcmF0aW9uLFxuICBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFJlY29yZFRyYW5zZm9ybSxcbiAgUmVjb3JkVHJhbnNmb3JtQnVpbGRlcixcbiAgUmVjb3JkVHJhbnNmb3JtUmVzdWx0XG59IGZyb20gJ0BvcmJpdC9yZWNvcmRzJztcbmltcG9ydCB7IGNsb25lLCBEaWN0LCB0b0FycmF5IH0gZnJvbSAnQG9yYml0L3V0aWxzJztcblxuY29uc3QgeyBhc3NlcnQsIGRlcHJlY2F0ZSB9ID0gT3JiaXQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5Q2FjaGVNZXJnZU9wdGlvbnMge1xuICBjb2FsZXNjZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5Q2FjaGVTZXR0aW5nczxcbiAgUU8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlUXVlcnlPcHRpb25zLFxuICBUTyBleHRlbmRzIFJlcXVlc3RPcHRpb25zID0gUmVjb3JkQ2FjaGVUcmFuc2Zvcm1PcHRpb25zLFxuICBRQiA9IFJlY29yZFF1ZXJ5QnVpbGRlcixcbiAgVEIgPSBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICBRUkQgPSB1bmtub3duLFxuICBUUkQgZXh0ZW5kcyBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMgPSBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHNcbj4gZXh0ZW5kcyBTeW5jUmVjb3JkQ2FjaGVTZXR0aW5nczxRTywgVE8sIFFCLCBUQj4ge1xuICBiYXNlPzogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPjtcbiAgdHJhY2tVcGRhdGVPcGVyYXRpb25zPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZW1vcnlDYWNoZUNsYXNzPFxuICBRTyBleHRlbmRzIFJlcXVlc3RPcHRpb25zID0gUmVjb3JkQ2FjaGVRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRDYWNoZVRyYW5zZm9ybU9wdGlvbnMsXG4gIFFCID0gUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBUQiA9IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXIsXG4gIFFSRCA9IHVua25vd24sXG4gIFRSRCBleHRlbmRzIFJlY29yZENhY2hlVXBkYXRlRGV0YWlscyA9IFJlY29yZENhY2hlVXBkYXRlRGV0YWlsc1xuPiB7XG4gIG5ldyAoc2V0dGluZ3M6IE1lbW9yeUNhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPik6IE1lbW9yeUNhY2hlPFxuICAgIFFPLFxuICAgIFRPLFxuICAgIFFCLFxuICAgIFRCLFxuICAgIFFSRCxcbiAgICBUUkRcbiAgPjtcbn1cblxuLyoqXG4gKiBBIGNhY2hlIHVzZWQgdG8gYWNjZXNzIHJlY29yZHMgaW4gbWVtb3J5LlxuICpcbiAqIEJlY2F1c2UgZGF0YSBpcyBzdG9yZWQgaW4gaW1tdXRhYmxlIG1hcHMsIHRoaXMgdHlwZSBvZiBjYWNoZSBjYW4gYmUgZm9ya2VkXG4gKiBlZmZpY2llbnRseS5cbiAqL1xuZXhwb3J0IGNsYXNzIE1lbW9yeUNhY2hlPFxuICBRTyBleHRlbmRzIFJlcXVlc3RPcHRpb25zID0gUmVjb3JkQ2FjaGVRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRDYWNoZVRyYW5zZm9ybU9wdGlvbnMsXG4gIFFCID0gUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBUQiA9IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXIsXG4gIFFSRCA9IHVua25vd24sXG4gIFRSRCBleHRlbmRzIFJlY29yZENhY2hlVXBkYXRlRGV0YWlscyA9IFJlY29yZENhY2hlVXBkYXRlRGV0YWlsc1xuPiBleHRlbmRzIFN5bmNSZWNvcmRDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+IHtcbiAgcHJvdGVjdGVkIF9iYXNlPzogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPjtcbiAgcHJvdGVjdGVkIF9yZWNvcmRzITogRGljdDxJbW11dGFibGVNYXA8c3RyaW5nLCBJbml0aWFsaXplZFJlY29yZD4+O1xuICBwcm90ZWN0ZWQgX2ludmVyc2VSZWxhdGlvbnNoaXBzITogRGljdDxcbiAgICBJbW11dGFibGVNYXA8c3RyaW5nLCBSZWNvcmRSZWxhdGlvbnNoaXBJZGVudGl0eVtdPlxuICA+O1xuICBwcm90ZWN0ZWQgX3VwZGF0ZU9wZXJhdGlvbnM/OiBSZWNvcmRPcGVyYXRpb25bXTtcbiAgcHJvdGVjdGVkIF9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9uczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihzZXR0aW5nczogTWVtb3J5Q2FjaGVTZXR0aW5nczxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+KSB7XG4gICAgY29uc3QgeyBiYXNlLCB0cmFja1VwZGF0ZU9wZXJhdGlvbnMgfSA9IHNldHRpbmdzO1xuXG4gICAgc3VwZXIoc2V0dGluZ3MpO1xuXG4gICAgdGhpcy5fYmFzZSA9IGJhc2U7XG5cbiAgICAvLyBUcmFjayB1cGRhdGUgb3BlcmF0aW9ucyBpZiBleHBsaWNpdGx5IHRvbGQgdG8gZG8gc28sIG9yIGlmIGEgYGJhc2VgXG4gICAgLy8gY2FjaGUgaGFzIGJlZW4gc3BlY2lmaWVkLlxuICAgIHRoaXMuX2lzVHJhY2tpbmdVcGRhdGVPcGVyYXRpb25zID1cbiAgICAgIHRyYWNrVXBkYXRlT3BlcmF0aW9ucyA/PyBiYXNlICE9PSB1bmRlZmluZWQ7XG5cbiAgICB0aGlzLnJlc2V0KCk7XG4gIH1cblxuICBnZXQgYmFzZSgpOiBNZW1vcnlDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fYmFzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBjbG9uZSwgb3IgXCJmb3JrXCIsIGZyb20gYSBcImJhc2VcIiBjYWNoZS5cbiAgICpcbiAgICogVGhlIGZvcmtlZCBjYWNoZSB3aWxsIGhhdmUgdGhlIHNhbWUgYHNjaGVtYWAgYW5kIGBrZXlNYXBgIGFzIGl0cyBiYXNlXG4gICAqIHNvdXJjZS4gVGhlIGZvcmtlZCBjYWNoZSB3aWxsIHN0YXJ0IHdpdGggdGhlIHNhbWUgaW1tdXRhYmxlIGRvY3VtZW50IGFzIHRoZVxuICAgKiBiYXNlIHNvdXJjZS4gSXRzIGNvbnRlbnRzIGFuZCBsb2cgd2lsbCBldm9sdmUgaW5kZXBlbmRlbnRseS5cbiAgICpcbiAgICogQHJldHVybnMgdGhlIGZvcmtlZCBjYWNoZVxuICAgKi9cbiAgZm9yayhcbiAgICBzZXR0aW5nczogUGFydGlhbDxNZW1vcnlDYWNoZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4+ID0ge31cbiAgKTogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPiB7XG4gICAgLy8gcmVxdWlyZWQgc2V0dGluZ3NcbiAgICBzZXR0aW5ncy5iYXNlID0gdGhpcztcbiAgICBzZXR0aW5ncy5zY2hlbWEgPSB0aGlzLnNjaGVtYTtcbiAgICBzZXR0aW5ncy5rZXlNYXAgPSB0aGlzLl9rZXlNYXA7XG5cbiAgICAvLyBjdXN0b21pemFibGUgc2V0dGluZ3NcbiAgICBzZXR0aW5ncy5xdWVyeUJ1aWxkZXIgPz89IHRoaXMuX3F1ZXJ5QnVpbGRlcjtcbiAgICBzZXR0aW5ncy50cmFuc2Zvcm1CdWlsZGVyID8/PSB0aGlzLl90cmFuc2Zvcm1CdWlsZGVyO1xuICAgIHNldHRpbmdzLmRlZmF1bHRRdWVyeU9wdGlvbnMgPz89IHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnM7XG4gICAgc2V0dGluZ3MuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPz89IHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zO1xuICAgIGlmIChzZXR0aW5ncy5hdXRvVmFsaWRhdGUgIT09IGZhbHNlKSB7XG4gICAgICBzZXR0aW5ncy52YWxpZGF0b3JGb3IgPz89IHRoaXMuX3ZhbGlkYXRvckZvcjtcbiAgICAgIGlmIChcbiAgICAgICAgc2V0dGluZ3MuYXV0b1ZhbGlkYXRlID09PSB1bmRlZmluZWQgJiZcbiAgICAgICAgc2V0dGluZ3MudmFsaWRhdG9yRm9yID09PSB1bmRlZmluZWRcbiAgICAgICkge1xuICAgICAgICBzZXR0aW5ncy5hdXRvVmFsaWRhdGUgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IE1lbW9yeUNhY2hlKFxuICAgICAgc2V0dGluZ3MgYXMgTWVtb3J5Q2FjaGVTZXR0aW5nczxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXJnZXMgdGhlIG9wZXJhdGlvbnMgZnJvbSBhIGZvcmtlZCBjYWNoZSBiYWNrIHRvIHRoaXMgY2FjaGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgY2FsbGluZyBgdXBkYXRlYCB3aXRoIHRoZSBvcGVyYXRpb25zXG4gICAqL1xuICBtZXJnZTxSZXF1ZXN0RGF0YSBleHRlbmRzIFJlY29yZFRyYW5zZm9ybVJlc3VsdCA9IFJlY29yZFRyYW5zZm9ybVJlc3VsdD4oXG4gICAgZm9ya2VkQ2FjaGU6IE1lbW9yeUNhY2hlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4sXG4gICAgb3B0aW9ucz86IERlZmF1bHRSZXF1ZXN0T3B0aW9uczxUTz4gJiBNZW1vcnlDYWNoZU1lcmdlT3B0aW9uc1xuICApOiBSZXF1ZXN0RGF0YTtcbiAgbWVyZ2U8UmVxdWVzdERhdGEgZXh0ZW5kcyBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgPSBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQ+KFxuICAgIGZvcmtlZENhY2hlOiBNZW1vcnlDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+LFxuICAgIG9wdGlvbnM6IEZ1bGxSZXF1ZXN0T3B0aW9uczxUTz4gJiBNZW1vcnlDYWNoZU1lcmdlT3B0aW9uc1xuICApOiBGdWxsUmVzcG9uc2U8UmVxdWVzdERhdGEsIFRSRCwgUmVjb3JkT3BlcmF0aW9uPjtcbiAgbWVyZ2U8UmVxdWVzdERhdGEgZXh0ZW5kcyBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgPSBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQ+KFxuICAgIGZvcmtlZENhY2hlOiBNZW1vcnlDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+LFxuICAgIG9wdGlvbnM/OiBUTyAmIE1lbW9yeUNhY2hlTWVyZ2VPcHRpb25zXG4gICk6IFJlcXVlc3REYXRhIHwgRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUUkQsIFJlY29yZE9wZXJhdGlvbj4ge1xuICAgIGxldCB7IGNvYWxlc2NlLCAuLi5yZW1haW5pbmdPcHRpb25zIH0gPSBvcHRpb25zID8/IHt9O1xuXG4gICAgYXNzZXJ0KFxuICAgICAgJ01lbW9yeUNhY2hlI21lcmdlIGNhbiBvbmx5IG1lcmdlIGEgZm9ya2VkIGNhY2hlIHRoYXQgaXMgY29uZmlndXJlZCB3aXRoIGB0cmFja1VwZGF0ZU9wZXJhdGlvbnM6IHRydWVgLicsXG4gICAgICBmb3JrZWRDYWNoZS5pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9uc1xuICAgICk7XG5cbiAgICBsZXQgb3BzID0gZm9ya2VkQ2FjaGUuZ2V0QWxsVXBkYXRlT3BlcmF0aW9ucygpO1xuXG4gICAgaWYgKGNvYWxlc2NlICE9PSBmYWxzZSkge1xuICAgICAgb3BzID0gY29hbGVzY2VSZWNvcmRPcGVyYXRpb25zKG9wcyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmZ1bGxSZXNwb25zZSkge1xuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlPFJlcXVlc3REYXRhPihcbiAgICAgICAgb3BzLFxuICAgICAgICByZW1haW5pbmdPcHRpb25zIGFzIEZ1bGxSZXF1ZXN0T3B0aW9uczxUTz5cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnVwZGF0ZTxSZXF1ZXN0RGF0YT4oXG4gICAgICAgIG9wcyxcbiAgICAgICAgcmVtYWluaW5nT3B0aW9ucyBhcyBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8VE8+XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWJhc2UgcmVzZXRzIHRoaXMgY2FjaGUncyBzdGF0ZSB0byB0aGF0IG9mIGl0cyBiYXNlIGNhY2hlLCB0aGVuIHJlLWFwcGxpZXNcbiAgICogYW55IHRyYWNrZWQgdXBkYXRlIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIFJlYmFzaW5nIHJlcXVpcmVzIGJvdGggYSBgYmFzZWAgY2FjaGUgYXMgd2VsbCBhcyB0cmFja2luZyBvZiB1cGRhdGVcbiAgICogb3BlcmF0aW9ucyAod2hpY2ggaXMgZW5hYmxlZCBieSBkZWZhdWx0IHdoZW4gYSBgYmFzZWAgY2FjaGUgaXMgYXNzaWduZWQpLlxuICAgKi9cbiAgcmViYXNlKCk6IHZvaWQge1xuICAgIGNvbnN0IGJhc2UgPSB0aGlzLl9iYXNlO1xuXG4gICAgYXNzZXJ0KFxuICAgICAgJ0EgYGJhc2VgIGNhY2hlIG11c3QgYmUgZGVmaW5lZCBmb3IgYHJlYmFzZWAgdG8gd29yaycsXG4gICAgICBiYXNlICE9PSB1bmRlZmluZWRcbiAgICApO1xuXG4gICAgYXNzZXJ0KFxuICAgICAgJ01lbW9yeUNhY2hlI3JlYmFzZSByZXF1aXJlcyB0aGF0IHRoZSBjYWNoZSBpcyBjb25maWd1cmVkIHdpdGggYHRyYWNrVXBkYXRlT3BlcmF0aW9uczogdHJ1ZWAuJyxcbiAgICAgIHRoaXMuX2lzVHJhY2tpbmdVcGRhdGVPcGVyYXRpb25zXG4gICAgKTtcblxuICAgIC8vIGdldCB1cGRhdGUgb3BzIHByaW9yIHRvIHJlc2V0dGluZyBzdGF0ZVxuICAgIGxldCBvcHMgPSB0aGlzLmdldEFsbFVwZGF0ZU9wZXJhdGlvbnMoKTtcblxuICAgIC8vIHJlc2V0IHRoZSBzdGF0ZSBvZiB0aGUgY2FjaGUgdG8gbWF0Y2ggaXRzIGJhc2UgY2FjaGVcbiAgICB0aGlzLnJlc2V0KCk7XG5cbiAgICAvLyByZWFwcGx5IHVwZGF0ZSBvcHNcbiAgICB0aGlzLnVwZGF0ZShvcHMpO1xuICB9XG5cbiAgZ2V0UmVjb3JkU3luYyhpZGVudGl0eTogUmVjb3JkSWRlbnRpdHkpOiBJbml0aWFsaXplZFJlY29yZCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3JlY29yZHNbaWRlbnRpdHkudHlwZV0uZ2V0KGlkZW50aXR5LmlkKTtcbiAgfVxuXG4gIGdldFJlY29yZHNTeW5jKFxuICAgIHR5cGVPcklkZW50aXRpZXM/OiBzdHJpbmcgfCBSZWNvcmRJZGVudGl0eVtdXG4gICk6IEluaXRpYWxpemVkUmVjb3JkW10ge1xuICAgIGlmICh0eXBlT3JJZGVudGl0aWVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHR5cGVzID0gT2JqZWN0LmtleXModGhpcy5zY2hlbWEubW9kZWxzKTtcbiAgICAgIGNvbnN0IHJlY29yZHM6IEluaXRpYWxpemVkUmVjb3JkW10gPSBbXTtcbiAgICAgIHR5cGVzLmZvckVhY2goKHR5cGUpID0+XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KFxuICAgICAgICAgIHJlY29yZHMsXG4gICAgICAgICAgQXJyYXkuZnJvbSh0aGlzLl9yZWNvcmRzW3R5cGVdLnZhbHVlcygpKVxuICAgICAgICApXG4gICAgICApO1xuICAgICAgcmV0dXJuIHJlY29yZHM7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdHlwZU9ySWRlbnRpdGllcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHR5cGU6IHN0cmluZyA9IHR5cGVPcklkZW50aXRpZXM7XG4gICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLl9yZWNvcmRzW3R5cGVdLnZhbHVlcygpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVjb3JkczogSW5pdGlhbGl6ZWRSZWNvcmRbXSA9IFtdO1xuICAgICAgY29uc3QgaWRlbnRpdGllczogUmVjb3JkSWRlbnRpdHlbXSA9IHR5cGVPcklkZW50aXRpZXM7XG4gICAgICBmb3IgKGxldCBpZGVudGl0eSBvZiBpZGVudGl0aWVzKSB7XG4gICAgICAgIGxldCByZWNvcmQgPSB0aGlzLmdldFJlY29yZFN5bmMoaWRlbnRpdHkpO1xuICAgICAgICBpZiAocmVjb3JkKSB7XG4gICAgICAgICAgcmVjb3Jkcy5wdXNoKHJlY29yZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZWNvcmRzO1xuICAgIH1cbiAgfVxuXG4gIHNldFJlY29yZFN5bmMocmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCk6IHZvaWQge1xuICAgIHRoaXMuX3JlY29yZHNbcmVjb3JkLnR5cGVdLnNldChyZWNvcmQuaWQsIHJlY29yZCk7XG4gIH1cblxuICBzZXRSZWNvcmRzU3luYyhyZWNvcmRzOiBJbml0aWFsaXplZFJlY29yZFtdKTogdm9pZCB7XG4gICAgbGV0IHR5cGVkTWFwOiBhbnkgPSB7fTtcbiAgICBmb3IgKGxldCByZWNvcmQgb2YgcmVjb3Jkcykge1xuICAgICAgdHlwZWRNYXBbcmVjb3JkLnR5cGVdID0gdHlwZWRNYXBbcmVjb3JkLnR5cGVdIHx8IFtdO1xuICAgICAgdHlwZWRNYXBbcmVjb3JkLnR5cGVdLnB1c2goW3JlY29yZC5pZCwgcmVjb3JkXSk7XG4gICAgfVxuICAgIGZvciAobGV0IHR5cGUgaW4gdHlwZWRNYXApIHtcbiAgICAgIHRoaXMuX3JlY29yZHNbdHlwZV0uc2V0TWFueSh0eXBlZE1hcFt0eXBlXSk7XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlUmVjb3JkU3luYyhcbiAgICByZWNvcmRJZGVudGl0eTogUmVjb3JkSWRlbnRpdHlcbiAgKTogSW5pdGlhbGl6ZWRSZWNvcmQgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJlY29yZE1hcCA9IHRoaXMuX3JlY29yZHNbcmVjb3JkSWRlbnRpdHkudHlwZV07XG4gICAgY29uc3QgcmVjb3JkID0gcmVjb3JkTWFwLmdldChyZWNvcmRJZGVudGl0eS5pZCk7XG4gICAgaWYgKHJlY29yZCkge1xuICAgICAgcmVjb3JkTWFwLnJlbW92ZShyZWNvcmRJZGVudGl0eS5pZCk7XG4gICAgICByZXR1cm4gcmVjb3JkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHJlbW92ZVJlY29yZHNTeW5jKHJlY29yZElkZW50aXRpZXM6IFJlY29yZElkZW50aXR5W10pOiBJbml0aWFsaXplZFJlY29yZFtdIHtcbiAgICBjb25zdCByZWNvcmRzID0gW107XG4gICAgY29uc3QgdHlwZWRJZHM6IGFueSA9IHt9O1xuICAgIGZvciAobGV0IHJlY29yZElkZW50aXR5IG9mIHJlY29yZElkZW50aXRpZXMpIHtcbiAgICAgIGxldCByZWNvcmQgPSB0aGlzLmdldFJlY29yZFN5bmMocmVjb3JkSWRlbnRpdHkpO1xuICAgICAgaWYgKHJlY29yZCkge1xuICAgICAgICByZWNvcmRzLnB1c2gocmVjb3JkKTtcbiAgICAgICAgdHlwZWRJZHNbcmVjb3JkLnR5cGVdID0gdHlwZWRJZHNbcmVjb3JkLnR5cGVdIHx8IFtdO1xuICAgICAgICB0eXBlZElkc1tyZWNvcmQudHlwZV0ucHVzaChyZWNvcmRJZGVudGl0eS5pZCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAobGV0IHR5cGUgaW4gdHlwZWRJZHMpIHtcbiAgICAgIHRoaXMuX3JlY29yZHNbdHlwZV0ucmVtb3ZlTWFueSh0eXBlZElkc1t0eXBlXSk7XG4gICAgfVxuICAgIHJldHVybiByZWNvcmRzO1xuICB9XG5cbiAgZ2V0SW52ZXJzZVJlbGF0aW9uc2hpcHNTeW5jKFxuICAgIHJlY29yZElkZW50aXR5T3JJZGVudGl0aWVzOiBSZWNvcmRJZGVudGl0eSB8IFJlY29yZElkZW50aXR5W11cbiAgKTogUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHlbXSB7XG4gICAgY29uc3QgcmVzdWx0czogUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHlbXSA9IFtdO1xuICAgIGNvbnN0IGlkZW50aXRpZXM6IFJlY29yZElkZW50aXR5W10gPSBBcnJheS5pc0FycmF5KFxuICAgICAgcmVjb3JkSWRlbnRpdHlPcklkZW50aXRpZXNcbiAgICApXG4gICAgICA/IHJlY29yZElkZW50aXR5T3JJZGVudGl0aWVzXG4gICAgICA6IFtyZWNvcmRJZGVudGl0eU9ySWRlbnRpdGllc107XG5cbiAgICBmb3IgKGxldCBpZGVudGl0eSBvZiBpZGVudGl0aWVzKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9pbnZlcnNlUmVsYXRpb25zaGlwc1tpZGVudGl0eS50eXBlXS5nZXQoaWRlbnRpdHkuaWQpO1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShyZXN1bHRzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgYWRkSW52ZXJzZVJlbGF0aW9uc2hpcHNTeW5jKFxuICAgIHJlbGF0aW9uc2hpcHM6IFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W11cbiAgKTogdm9pZCB7XG4gICAgcmVsYXRpb25zaGlwcy5mb3JFYWNoKChyKSA9PiB7XG4gICAgICBsZXQgcmVscyA9IHRoaXMuX2ludmVyc2VSZWxhdGlvbnNoaXBzW3IucmVsYXRlZFJlY29yZC50eXBlXS5nZXQoXG4gICAgICAgIHIucmVsYXRlZFJlY29yZC5pZFxuICAgICAgKTtcbiAgICAgIHJlbHMgPSByZWxzID8gWy4uLnJlbHMsIGNsb25lKHIpXSA6IFtjbG9uZShyKV07XG4gICAgICB0aGlzLl9pbnZlcnNlUmVsYXRpb25zaGlwc1tyLnJlbGF0ZWRSZWNvcmQudHlwZV0uc2V0KFxuICAgICAgICByLnJlbGF0ZWRSZWNvcmQuaWQsXG4gICAgICAgIHJlbHNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVJbnZlcnNlUmVsYXRpb25zaGlwc1N5bmMoXG4gICAgcmVsYXRpb25zaGlwczogUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHlbXVxuICApOiB2b2lkIHtcbiAgICByZWxhdGlvbnNoaXBzLmZvckVhY2goKHIpID0+IHtcbiAgICAgIGxldCByZWxzID0gdGhpcy5faW52ZXJzZVJlbGF0aW9uc2hpcHNbci5yZWxhdGVkUmVjb3JkLnR5cGVdLmdldChcbiAgICAgICAgci5yZWxhdGVkUmVjb3JkLmlkXG4gICAgICApO1xuICAgICAgaWYgKHJlbHMpIHtcbiAgICAgICAgbGV0IG5ld1JlbHMgPSByZWxzLmZpbHRlcihcbiAgICAgICAgICAocmVsKSA9PlxuICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgZXF1YWxSZWNvcmRJZGVudGl0aWVzKHJlbC5yZWNvcmQsIHIucmVjb3JkKSAmJlxuICAgICAgICAgICAgICByZWwucmVsYXRpb25zaGlwID09PSByLnJlbGF0aW9uc2hpcFxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLl9pbnZlcnNlUmVsYXRpb25zaGlwc1tyLnJlbGF0ZWRSZWNvcmQudHlwZV0uc2V0KFxuICAgICAgICAgIHIucmVsYXRlZFJlY29yZC5pZCxcbiAgICAgICAgICBuZXdSZWxzXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBjYWNoZSdzIHRvIGl0cyBpbml0aWFsIHN0YXRlLCB3aGljaCB3aWxsIGJlIGVpdGhlciBlbXB0eSBvciBhXG4gICAqIGNsb25lIG9mIGl0cyBgYmFzZWAgY2FjaGUsIGlmIGl0IGhhcyBvbmUuXG4gICAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICBsZXQgYmFzZSA9IHRoaXMuX2Jhc2U7XG5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGRlcHJlY2F0ZShcbiAgICAgICAgJ0NhbGxpbmcgTWVtb3J5Q2FjaGUjcmVzZXQgd2l0aCBhIGBiYXNlYCBhcmd1bWVudCBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkIGNvbmZpZ3VyZSB5b3VyIE1lbW9yeUNhY2hlIHdpdGggYSBgYmFzZWAgY2FjaGUuJ1xuICAgICAgKTtcbiAgICAgIGJhc2UgPz89IGFyZ3VtZW50c1swXTtcbiAgICB9XG5cbiAgICB0aGlzLl9yZWNvcmRzID0ge307XG5cbiAgICBpZiAodGhpcy5faXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnMpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZU9wZXJhdGlvbnMgPSBbXTtcbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLl9zY2hlbWEubW9kZWxzKS5mb3JFYWNoKCh0eXBlKSA9PiB7XG4gICAgICBsZXQgYmFzZVJlY29yZHMgPSBiYXNlPy5fcmVjb3Jkc1t0eXBlXTtcblxuICAgICAgdGhpcy5fcmVjb3Jkc1t0eXBlXSA9IG5ldyBJbW11dGFibGVNYXA8c3RyaW5nLCBJbml0aWFsaXplZFJlY29yZD4oXG4gICAgICAgIGJhc2VSZWNvcmRzXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGhpcy5fcmVzZXRJbnZlcnNlUmVsYXRpb25zaGlwcyhiYXNlKTtcblxuICAgIHRoaXMuX3Byb2Nlc3NvcnMuZm9yRWFjaCgocHJvY2Vzc29yKSA9PiBwcm9jZXNzb3IucmVzZXQoYmFzZSkpO1xuXG4gICAgdGhpcy5lbWl0KCdyZXNldCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZ3JhZGUgdGhlIGNhY2hlIGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBzY2hlbWEuXG4gICAqL1xuICB1cGdyYWRlKCk6IHZvaWQge1xuICAgIE9iamVjdC5rZXlzKHRoaXMuX3NjaGVtYS5tb2RlbHMpLmZvckVhY2goKHR5cGUpID0+IHtcbiAgICAgIGlmICghdGhpcy5fcmVjb3Jkc1t0eXBlXSkge1xuICAgICAgICB0aGlzLl9yZWNvcmRzW3R5cGVdID0gbmV3IEltbXV0YWJsZU1hcDxzdHJpbmcsIEluaXRpYWxpemVkUmVjb3JkPigpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5fcmVzZXRJbnZlcnNlUmVsYXRpb25zaGlwcygpO1xuXG4gICAgZm9yIChsZXQgcHJvY2Vzc29yIG9mIHRoaXMuX3Byb2Nlc3NvcnMpIHtcbiAgICAgIHByb2Nlc3Nvci51cGdyYWRlKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzVHJhY2tpbmdVcGRhdGVPcGVyYXRpb25zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9ucztcbiAgfVxuXG4gIGdldEFsbFVwZGF0ZU9wZXJhdGlvbnMoKTogUmVjb3JkT3BlcmF0aW9uW10ge1xuICAgIGFzc2VydChcbiAgICAgICdNZW1vcnlDYWNoZSNnZXRBbGxVcGRhdGVPcGVyYXRpb25zIHJlcXVpcmVzIHRoYXQgY2FjaGUgYmUgY29uZmlndXJlZCB3aXRoIGB0cmFja1VwZGF0ZU9wZXJhdGlvbnM6IHRydWVgLicsXG4gICAgICB0aGlzLl9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9uc1xuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy5fdXBkYXRlT3BlcmF0aW9ucyBhcyBSZWNvcmRPcGVyYXRpb25bXTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFByb3RlY3RlZCBtZXRob2RzXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgcHJvdGVjdGVkIF91cGRhdGU8XG4gICAgUmVxdWVzdERhdGEgZXh0ZW5kcyBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgPSBSZWNvcmRUcmFuc2Zvcm1SZXN1bHRcbiAgPihcbiAgICB0cmFuc2Zvcm06IFJlY29yZFRyYW5zZm9ybSxcbiAgICBvcHRpb25zPzogVE9cbiAgKTogRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUUkQsIFJlY29yZE9wZXJhdGlvbj4ge1xuICAgIGlmICh0aGlzLl9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9ucykge1xuICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoXG4gICAgICAgIHRoaXMuX3VwZGF0ZU9wZXJhdGlvbnMsXG4gICAgICAgIHRvQXJyYXkodHJhbnNmb3JtLm9wZXJhdGlvbnMpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gc3VwZXIuX3VwZGF0ZTxSZXF1ZXN0RGF0YT4odHJhbnNmb3JtLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZSBgX2dldFRyYW5zZm9ybUJ1ZmZlcmAgb24gYmFzZSBgU3luY1JlY29yZENhY2hlYCB0byBwcm92aWRlIGFcbiAgICogYHRyYW5zZm9ybUJ1ZmZlcmAgaWYgYSBjdXN0b20gb25lIGhhc24ndCBiZWVuIHByb3ZpZGVkIHZpYSB0aGUgY29uc3RydWN0b3JcbiAgICogc2V0dGluZy5cbiAgICovXG4gIHByb3RlY3RlZCBfZ2V0VHJhbnNmb3JtQnVmZmVyKCk6IFJlY29yZFRyYW5zZm9ybUJ1ZmZlciB7XG4gICAgaWYgKHRoaXMuX3RyYW5zZm9ybUJ1ZmZlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB7IHNjaGVtYSwga2V5TWFwIH0gPSB0aGlzO1xuICAgICAgdGhpcy5fdHJhbnNmb3JtQnVmZmVyID0gbmV3IFNpbXBsZVJlY29yZFRyYW5zZm9ybUJ1ZmZlcih7XG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAga2V5TWFwXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zZm9ybUJ1ZmZlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBfcmVzZXRJbnZlcnNlUmVsYXRpb25zaGlwcyhcbiAgICBiYXNlPzogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPlxuICApOiB2b2lkIHtcbiAgICBjb25zdCBpbnZlcnNlUmVsYXRpb25zaGlwczogRGljdDxcbiAgICAgIEltbXV0YWJsZU1hcDxzdHJpbmcsIFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W10+XG4gICAgPiA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHRoaXMuX3NjaGVtYS5tb2RlbHMpLmZvckVhY2goKHR5cGUpID0+IHtcbiAgICAgIGxldCBiYXNlUmVsYXRpb25zaGlwcyA9IGJhc2UgJiYgYmFzZS5faW52ZXJzZVJlbGF0aW9uc2hpcHNbdHlwZV07XG4gICAgICBpbnZlcnNlUmVsYXRpb25zaGlwc1t0eXBlXSA9IG5ldyBJbW11dGFibGVNYXAoYmFzZVJlbGF0aW9uc2hpcHMpO1xuICAgIH0pO1xuICAgIHRoaXMuX2ludmVyc2VSZWxhdGlvbnNoaXBzID0gaW52ZXJzZVJlbGF0aW9uc2hpcHM7XG4gIH1cbn1cbiJdfQ==