UNPKG

@data-client/endpoint

Version:

Declarative Network Interface Definitions

332 lines (308 loc) 44.6 kB
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; import _extends from "@babel/runtime/helpers/esm/extends"; const _excluded = ["pk", "schema", "key"]; import { INVALID } from '../special.js'; /** * Turns any class into an Entity. * @see https://dataclient.io/rest/api/EntityMixin */ // id is in Instance, so we default to that as pk // pk was specified in options, so we don't need to redefine export default function EntityMixin(Base, options = {}) { /** * Entity defines a single (globally) unique object. * @see https://dataclient.io/rest/api/Entity */ class EntityMixin extends Base { static toString() { return this.key; } static toJSON() { return { key: this.key, schema: this.schema }; } /** Defines nested entities */ /** * A unique identifier for each Entity * * @see https://dataclient.io/rest/api/Entity#pk * @param [parent] When normalizing, the object which included the entity * @param [key] When normalizing, the key where this entity was found * @param [args] ...args sent to Endpoint */ /** Returns the globally unique identifier for the static Entity */ // default implementation in class static block at bottom of definition /** Defines indexes to enable lookup by */ /** * A unique identifier for each Entity * * @see https://dataclient.io/rest/api/Entity#pk * @param [value] POJO of the entity or subset used * @param [parent] When normalizing, the object which included the entity * @param [key] When normalizing, the key where this entity was found * @param [args] ...args sent to Endpoint */ static pk(value, parent, key, args) { return this.prototype.pk.call(value, parent, key, args); } /** Return true to merge incoming data; false keeps existing entity * * @see https://dataclient.io/rest/api/Entity#shouldUpdate */ static shouldUpdate(existingMeta, incomingMeta, existing, incoming) { return true; } /** Determines the order of incoming entity vs entity already in store\ * * @see https://dataclient.io/rest/api/Entity#shouldReorder * @returns true if incoming entity should be first argument of merge() */ static shouldReorder(existingMeta, incomingMeta, existing, incoming) { return incomingMeta.fetchedAt < existingMeta.fetchedAt; } /** Creates new instance copying over defined values of arguments * * @see https://dataclient.io/rest/api/Entity#merge */ static merge(existing, incoming) { return _extends({}, existing, incoming); } /** Run when an existing entity is found in the store * * @see https://dataclient.io/rest/api/Entity#mergeWithStore */ static mergeWithStore(existingMeta, incomingMeta, existing, incoming) { const shouldUpdate = this.shouldUpdate(existingMeta, incomingMeta, existing, incoming); if (shouldUpdate) { // distinct types are not mergeable (like delete symbol), so just replace if (typeof incoming !== typeof existing) { return incoming; } else { return this.shouldReorder(existingMeta, incomingMeta, existing, incoming) ? this.merge(incoming, existing) : this.merge(existing, incoming); } } else { return existing; } } /** Run when an existing entity is found in the store * * @see https://dataclient.io/rest/api/Entity#mergeMetaWithStore */ static mergeMetaWithStore(existingMeta, incomingMeta, existing, incoming) { return this.shouldReorder(existingMeta, incomingMeta, existing, incoming) ? existingMeta : incomingMeta; } /** Factory method to convert from Plain JS Objects. * * @param [props] Plain Object of properties to assign. */ static fromJS( // TODO: this should only accept members that are not functions props = {}) { // we type guarded abstract case above, so ok to force typescript to allow constructor call const instance = new this(props); // we can't rely on constructors and override the defaults provided as property assignments // all occur after the constructor Object.assign(instance, props); return instance; } /** Called when denormalizing an entity to create an instance when 'valid' * * @see https://dataclient.io/rest/api/Entity#createIfValid * @param [props] Plain Object of properties to assign. */ static createIfValid( // TODO: this should only accept members that are not functions props) { if (this.validate(props)) { return undefined; } return this.fromJS(props); } /** Do any transformations when first receiving input * * @see https://dataclient.io/rest/api/Entity#process */ static process(input, parent, key, args) { return _extends({}, input); } static normalize(input, parent, key, args, visit, addEntity, getEntity, checkLoop) { const processedEntity = this.process(input, parent, key, args); let id; if (typeof processedEntity === 'undefined') { id = this.pk(input, parent, key, args); addEntity(this, INVALID, id); return id; } id = this.pk(processedEntity, parent, key, args); if (id === undefined || id === '' || id === 'undefined') { // create a random id if a valid one cannot be computed // this is useful for optimistic creates that don't need real ids - just something to hold their place id = `MISS-${Math.random()}`; // 'creates' conceptually should allow missing PK to make optimistic creates easy if (process.env.NODE_ENV !== 'production' && !visit.creating) { let why; if (!('pk' in options) && EntityMixin.prototype.pk === this.prototype.pk && !('id' in processedEntity)) { why = `'id' missing but needed for default pk(). Try defining pk() for your Entity.`; } else { why = `This is likely due to a malformed response. Try inspecting the network response or fetch() return value. Or use debugging tools: https://dataclient.io/docs/getting-started/debugging`; } const error = new Error(`Missing usable primary key when normalizing response. ${why} Learn more about primary keys: https://dataclient.io/rest/api/Entity#pk Entity: ${this.key} Value (processed): ${processedEntity && JSON.stringify(processedEntity, null, 2)} `); error.status = 400; throw error; } } else { id = `${id}`; } /* Circular reference short-circuiter */ if (checkLoop(this.key, id, input)) return id; const errorMessage = this.validate(processedEntity); throwValidationError(errorMessage); Object.keys(this.schema).forEach(key => { if (Object.hasOwn(processedEntity, key)) { processedEntity[key] = visit(this.schema[key], processedEntity[key], processedEntity, key, args); } }); addEntity(this, processedEntity, id); return id; } static validate(processedEntity) { return; } static queryKey(args, queryKey, getEntity, getIndex) { if (!args[0]) return; const id = queryKeyCandidate(this, args, getIndex); // ensure this actually has entity or we shouldn't try to use it in our query if (getEntity(this.key, id)) return id; } static denormalize(input, args, unvisit) { if (typeof input === 'symbol') { return input; } // note: iteration order must be stable for (const key of Object.keys(this.schema)) { const schema = this.schema[key]; const value = unvisit(schema, input[key]); if (typeof value === 'symbol') { // if default is not 'falsy', then this is required, so propagate INVALID symbol if (this.defaults[key]) { return value; } input[key] = undefined; } else { input[key] = value; } } return input; } /** All instance defaults set */ static get defaults() { // we use hasOwn because we don't want to use a parents' defaults if (!Object.hasOwn(this, '__defaults')) Object.defineProperty(this, '__defaults', { value: new this(), writable: true, configurable: true }); return this.__defaults; } } const staticProps = _objectWithoutPropertiesLoose(options, _excluded); // remaining options Object.assign(EntityMixin, staticProps); if ('schema' in options) { EntityMixin.schema = options.schema; } else if (!Base.schema) { EntityMixin.schema = {}; } if ('pk' in options) { if (typeof options.pk === 'function') { EntityMixin.prototype.pk = function (parent, key) { return options.pk(this, parent, key); }; } else { EntityMixin.prototype.pk = function () { return this[options.pk]; }; } // default to 'id' field if the base class doesn't have a pk } else if (typeof Base.prototype.pk !== 'function') { EntityMixin.prototype.pk = function () { return this.id; }; } if ('key' in options) { Object.defineProperty(EntityMixin, 'key', { value: options.key, configurable: true, writable: true, enumerable: true }); } else if (!('key' in Base)) { function set(value) { Object.defineProperty(this, 'key', { value, writable: true, enumerable: true, configurable: true }); } const baseGet = function baseGet() { const name = this.name === 'EntityMixin' ? Base.name : this.name; /* istanbul ignore next */ if (process.env.NODE_ENV !== 'production' && (name === '' || name === 'EntityMixin' || name === '_temp')) throw new Error('Entity classes without a name must define `static key`\nSee: https://dataclient.io/rest/api/Entity#key'); return name; }; const get = /* istanbul ignore if */ typeof document !== 'undefined' && document.CLS_MANGLE ? /* istanbul ignore next */function () { document.CLS_MANGLE == null || document.CLS_MANGLE(this); Object.defineProperty(EntityMixin, 'key', { get: baseGet, set, enumerable: true, configurable: true }); return baseGet.call(this); } : baseGet; Object.defineProperty(EntityMixin, 'key', { get, set, enumerable: true, configurable: true }); } return EntityMixin; } function indexFromParams(params, indexes) { if (!indexes) return undefined; return indexes.find(index => Object.hasOwn(params, index)); } // part of the reason for pulling this out is that all functions that throw are deoptimized function throwValidationError(errorMessage) { if (errorMessage) { const error = new Error(errorMessage); error.status = 400; throw error; } } function queryKeyCandidate(schema, args, getIndex) { if (['string', 'number'].includes(typeof args[0])) { return `${args[0]}`; } const id = schema.pk(args[0], undefined, '', args); // Was able to infer the entity's primary key from params if (id !== undefined && id !== '') return id; // now attempt lookup in indexes const indexName = indexFromParams(args[0], schema.indexes); if (!indexName) return; const value = args[0][indexName]; return getIndex(schema.key, indexName, value)[value]; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJJTlZBTElEIiwiRW50aXR5TWl4aW4iLCJCYXNlIiwib3B0aW9ucyIsInRvU3RyaW5nIiwia2V5IiwidG9KU09OIiwic2NoZW1hIiwicGsiLCJ2YWx1ZSIsInBhcmVudCIsImFyZ3MiLCJwcm90b3R5cGUiLCJjYWxsIiwic2hvdWxkVXBkYXRlIiwiZXhpc3RpbmdNZXRhIiwiaW5jb21pbmdNZXRhIiwiZXhpc3RpbmciLCJpbmNvbWluZyIsInNob3VsZFJlb3JkZXIiLCJmZXRjaGVkQXQiLCJtZXJnZSIsIl9leHRlbmRzIiwibWVyZ2VXaXRoU3RvcmUiLCJtZXJnZU1ldGFXaXRoU3RvcmUiLCJmcm9tSlMiLCJwcm9wcyIsImluc3RhbmNlIiwiT2JqZWN0IiwiYXNzaWduIiwiY3JlYXRlSWZWYWxpZCIsInZhbGlkYXRlIiwidW5kZWZpbmVkIiwicHJvY2VzcyIsImlucHV0Iiwibm9ybWFsaXplIiwidmlzaXQiLCJhZGRFbnRpdHkiLCJnZXRFbnRpdHkiLCJjaGVja0xvb3AiLCJwcm9jZXNzZWRFbnRpdHkiLCJpZCIsIk1hdGgiLCJyYW5kb20iLCJlbnYiLCJOT0RFX0VOViIsImNyZWF0aW5nIiwid2h5IiwiZXJyb3IiLCJFcnJvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJzdGF0dXMiLCJlcnJvck1lc3NhZ2UiLCJ0aHJvd1ZhbGlkYXRpb25FcnJvciIsImtleXMiLCJmb3JFYWNoIiwiaGFzT3duIiwicXVlcnlLZXkiLCJnZXRJbmRleCIsInF1ZXJ5S2V5Q2FuZGlkYXRlIiwiZGVub3JtYWxpemUiLCJ1bnZpc2l0IiwiZGVmYXVsdHMiLCJkZWZpbmVQcm9wZXJ0eSIsIndyaXRhYmxlIiwiY29uZmlndXJhYmxlIiwiX19kZWZhdWx0cyIsInN0YXRpY1Byb3BzIiwiX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzTG9vc2UiLCJfZXhjbHVkZWQiLCJlbnVtZXJhYmxlIiwic2V0IiwiYmFzZUdldCIsIm5hbWUiLCJnZXQiLCJkb2N1bWVudCIsIkNMU19NQU5HTEUiLCJpbmRleEZyb21QYXJhbXMiLCJwYXJhbXMiLCJpbmRleGVzIiwiZmluZCIsImluZGV4IiwiaW5jbHVkZXMiLCJpbmRleE5hbWUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NoZW1hcy9FbnRpdHlNaXhpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7XG4gIFNjaGVtYSxcbiAgR2V0SW5kZXgsXG4gIEdldEVudGl0eSxcbiAgQ2hlY2tMb29wLFxuICBWaXNpdCxcbn0gZnJvbSAnLi4vaW50ZXJmYWNlLmpzJztcbmltcG9ydCB7IEFic3RyYWN0SW5zdGFuY2VUeXBlIH0gZnJvbSAnLi4vbm9ybWFsLmpzJztcbmltcG9ydCB7IElOVkFMSUQgfSBmcm9tICcuLi9zcGVjaWFsLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgSUVudGl0eUNsYXNzLFxuICBJRW50aXR5SW5zdGFuY2UsXG4gIEVudGl0eU9wdGlvbnMsXG4gIFJlcXVpcmVkUEtPcHRpb25zLFxuICBJRENsYXNzLFxuICBDb25zdHJ1Y3RvcixcbiAgUEtDbGFzcyxcbn0gZnJvbSAnLi9FbnRpdHlUeXBlcy5qcyc7XG5cbi8qKlxuICogVHVybnMgYW55IGNsYXNzIGludG8gYW4gRW50aXR5LlxuICogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vcmVzdC9hcGkvRW50aXR5TWl4aW5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gRW50aXR5TWl4aW48VEJhc2UgZXh0ZW5kcyBQS0NsYXNzPihcbiAgQmFzZTogVEJhc2UsXG4gIG9wdD86IEVudGl0eU9wdGlvbnM8SW5zdGFuY2VUeXBlPFRCYXNlPj4sXG4pOiBJRW50aXR5Q2xhc3M8VEJhc2U+ICYgVEJhc2U7XG5cbi8vIGlkIGlzIGluIEluc3RhbmNlLCBzbyB3ZSBkZWZhdWx0IHRvIHRoYXQgYXMgcGtcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIEVudGl0eU1peGluPFRCYXNlIGV4dGVuZHMgSURDbGFzcz4oXG4gIEJhc2U6IFRCYXNlLFxuICBvcHQ/OiBFbnRpdHlPcHRpb25zPEluc3RhbmNlVHlwZTxUQmFzZT4+LFxuKTogSUVudGl0eUNsYXNzPFRCYXNlPiAmIFRCYXNlICYgKG5ldyAoLi4uYXJnczogYW55W10pID0+IElFbnRpdHlJbnN0YW5jZSk7XG5cbi8vIHBrIHdhcyBzcGVjaWZpZWQgaW4gb3B0aW9ucywgc28gd2UgZG9uJ3QgbmVlZCB0byByZWRlZmluZVxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gRW50aXR5TWl4aW48VEJhc2UgZXh0ZW5kcyBDb25zdHJ1Y3Rvcj4oXG4gIEJhc2U6IFRCYXNlLFxuICBvcHQ6IFJlcXVpcmVkUEtPcHRpb25zPEluc3RhbmNlVHlwZTxUQmFzZT4+LFxuKTogSUVudGl0eUNsYXNzPFRCYXNlPiAmIFRCYXNlICYgKG5ldyAoLi4uYXJnczogYW55W10pID0+IElFbnRpdHlJbnN0YW5jZSk7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIEVudGl0eU1peGluPFRCYXNlIGV4dGVuZHMgQ29uc3RydWN0b3I+KFxuICBCYXNlOiBUQmFzZSxcbiAgb3B0aW9uczogRW50aXR5T3B0aW9uczxJbnN0YW5jZVR5cGU8VEJhc2U+PiA9IHt9LFxuKSB7XG4gIC8qKlxuICAgKiBFbnRpdHkgZGVmaW5lcyBhIHNpbmdsZSAoZ2xvYmFsbHkpIHVuaXF1ZSBvYmplY3QuXG4gICAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eVxuICAgKi9cbiAgYWJzdHJhY3QgY2xhc3MgRW50aXR5TWl4aW4gZXh0ZW5kcyBCYXNlIHtcbiAgICBzdGF0aWMgdG9TdHJpbmcoKSB7XG4gICAgICByZXR1cm4gdGhpcy5rZXk7XG4gICAgfVxuXG4gICAgc3RhdGljIHRvSlNPTigpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGtleTogdGhpcy5rZXksXG4gICAgICAgIHNjaGVtYTogdGhpcy5zY2hlbWEsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKiBEZWZpbmVzIG5lc3RlZCBlbnRpdGllcyAqL1xuICAgIGRlY2xhcmUgc3RhdGljIHNjaGVtYTogeyBbazogc3RyaW5nXTogU2NoZW1hIH07XG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciBlYWNoIEVudGl0eVxuICAgICAqXG4gICAgICogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vcmVzdC9hcGkvRW50aXR5I3BrXG4gICAgICogQHBhcmFtIFtwYXJlbnRdIFdoZW4gbm9ybWFsaXppbmcsIHRoZSBvYmplY3Qgd2hpY2ggaW5jbHVkZWQgdGhlIGVudGl0eVxuICAgICAqIEBwYXJhbSBba2V5XSBXaGVuIG5vcm1hbGl6aW5nLCB0aGUga2V5IHdoZXJlIHRoaXMgZW50aXR5IHdhcyBmb3VuZFxuICAgICAqIEBwYXJhbSBbYXJnc10gLi4uYXJncyBzZW50IHRvIEVuZHBvaW50XG4gICAgICovXG4gICAgZGVjbGFyZSBwazogKFxuICAgICAgcGFyZW50PzogYW55LFxuICAgICAga2V5Pzogc3RyaW5nLFxuICAgICAgYXJncz86IHJlYWRvbmx5IGFueVtdLFxuICAgICkgPT4gc3RyaW5nIHwgbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqIFJldHVybnMgdGhlIGdsb2JhbGx5IHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgc3RhdGljIEVudGl0eSAqL1xuICAgIGRlY2xhcmUgc3RhdGljIGtleTogc3RyaW5nO1xuICAgIC8vIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gaW4gY2xhc3Mgc3RhdGljIGJsb2NrIGF0IGJvdHRvbSBvZiBkZWZpbml0aW9uXG5cbiAgICAvKiogRGVmaW5lcyBpbmRleGVzIHRvIGVuYWJsZSBsb29rdXAgYnkgKi9cbiAgICBkZWNsYXJlIHN0YXRpYyBpbmRleGVzPzogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciBlYWNoIEVudGl0eVxuICAgICAqXG4gICAgICogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vcmVzdC9hcGkvRW50aXR5I3BrXG4gICAgICogQHBhcmFtIFt2YWx1ZV0gUE9KTyBvZiB0aGUgZW50aXR5IG9yIHN1YnNldCB1c2VkXG4gICAgICogQHBhcmFtIFtwYXJlbnRdIFdoZW4gbm9ybWFsaXppbmcsIHRoZSBvYmplY3Qgd2hpY2ggaW5jbHVkZWQgdGhlIGVudGl0eVxuICAgICAqIEBwYXJhbSBba2V5XSBXaGVuIG5vcm1hbGl6aW5nLCB0aGUga2V5IHdoZXJlIHRoaXMgZW50aXR5IHdhcyBmb3VuZFxuICAgICAqIEBwYXJhbSBbYXJnc10gLi4uYXJncyBzZW50IHRvIEVuZHBvaW50XG4gICAgICovXG4gICAgc3RhdGljIHBrPFQgZXh0ZW5kcyB0eXBlb2YgRW50aXR5TWl4aW4+KFxuICAgICAgdGhpczogVCxcbiAgICAgIHZhbHVlOiBQYXJ0aWFsPEFic3RyYWN0SW5zdGFuY2VUeXBlPFQ+PixcbiAgICAgIHBhcmVudD86IGFueSxcbiAgICAgIGtleT86IHN0cmluZyxcbiAgICAgIGFyZ3M/OiByZWFkb25seSBhbnlbXSxcbiAgICApOiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgICAgcmV0dXJuIHRoaXMucHJvdG90eXBlLnBrLmNhbGwodmFsdWUsIHBhcmVudCwga2V5LCBhcmdzKTtcbiAgICB9XG5cbiAgICAvKiogUmV0dXJuIHRydWUgdG8gbWVyZ2UgaW5jb21pbmcgZGF0YTsgZmFsc2Uga2VlcHMgZXhpc3RpbmcgZW50aXR5XG4gICAgICpcbiAgICAgKiBAc2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9yZXN0L2FwaS9FbnRpdHkjc2hvdWxkVXBkYXRlXG4gICAgICovXG4gICAgc3RhdGljIHNob3VsZFVwZGF0ZShcbiAgICAgIGV4aXN0aW5nTWV0YTogeyBkYXRlOiBudW1iZXI7IGZldGNoZWRBdDogbnVtYmVyIH0sXG4gICAgICBpbmNvbWluZ01ldGE6IHsgZGF0ZTogbnVtYmVyOyBmZXRjaGVkQXQ6IG51bWJlciB9LFxuICAgICAgZXhpc3Rpbmc6IGFueSxcbiAgICAgIGluY29taW5nOiBhbnksXG4gICAgKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKiogRGV0ZXJtaW5lcyB0aGUgb3JkZXIgb2YgaW5jb21pbmcgZW50aXR5IHZzIGVudGl0eSBhbHJlYWR5IGluIHN0b3JlXFxcbiAgICAgKlxuICAgICAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eSNzaG91bGRSZW9yZGVyXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiBpbmNvbWluZyBlbnRpdHkgc2hvdWxkIGJlIGZpcnN0IGFyZ3VtZW50IG9mIG1lcmdlKClcbiAgICAgKi9cbiAgICBzdGF0aWMgc2hvdWxkUmVvcmRlcihcbiAgICAgIGV4aXN0aW5nTWV0YTogeyBkYXRlOiBudW1iZXI7IGZldGNoZWRBdDogbnVtYmVyIH0sXG4gICAgICBpbmNvbWluZ01ldGE6IHsgZGF0ZTogbnVtYmVyOyBmZXRjaGVkQXQ6IG51bWJlciB9LFxuICAgICAgZXhpc3Rpbmc6IGFueSxcbiAgICAgIGluY29taW5nOiBhbnksXG4gICAgKSB7XG4gICAgICByZXR1cm4gaW5jb21pbmdNZXRhLmZldGNoZWRBdCA8IGV4aXN0aW5nTWV0YS5mZXRjaGVkQXQ7XG4gICAgfVxuXG4gICAgLyoqIENyZWF0ZXMgbmV3IGluc3RhbmNlIGNvcHlpbmcgb3ZlciBkZWZpbmVkIHZhbHVlcyBvZiBhcmd1bWVudHNcbiAgICAgKlxuICAgICAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eSNtZXJnZVxuICAgICAqL1xuICAgIHN0YXRpYyBtZXJnZShleGlzdGluZzogYW55LCBpbmNvbWluZzogYW55KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5leGlzdGluZyxcbiAgICAgICAgLi4uaW5jb21pbmcsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKiBSdW4gd2hlbiBhbiBleGlzdGluZyBlbnRpdHkgaXMgZm91bmQgaW4gdGhlIHN0b3JlXG4gICAgICpcbiAgICAgKiBAc2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9yZXN0L2FwaS9FbnRpdHkjbWVyZ2VXaXRoU3RvcmVcbiAgICAgKi9cbiAgICBzdGF0aWMgbWVyZ2VXaXRoU3RvcmUoXG4gICAgICBleGlzdGluZ01ldGE6IHtcbiAgICAgICAgZGF0ZTogbnVtYmVyO1xuICAgICAgICBmZXRjaGVkQXQ6IG51bWJlcjtcbiAgICAgIH0sXG4gICAgICBpbmNvbWluZ01ldGE6IHsgZGF0ZTogbnVtYmVyOyBmZXRjaGVkQXQ6IG51bWJlciB9LFxuICAgICAgZXhpc3Rpbmc6IGFueSxcbiAgICAgIGluY29taW5nOiBhbnksXG4gICAgKSB7XG4gICAgICBjb25zdCBzaG91bGRVcGRhdGUgPSB0aGlzLnNob3VsZFVwZGF0ZShcbiAgICAgICAgZXhpc3RpbmdNZXRhLFxuICAgICAgICBpbmNvbWluZ01ldGEsXG4gICAgICAgIGV4aXN0aW5nLFxuICAgICAgICBpbmNvbWluZyxcbiAgICAgICk7XG5cbiAgICAgIGlmIChzaG91bGRVcGRhdGUpIHtcbiAgICAgICAgLy8gZGlzdGluY3QgdHlwZXMgYXJlIG5vdCBtZXJnZWFibGUgKGxpa2UgZGVsZXRlIHN5bWJvbCksIHNvIGp1c3QgcmVwbGFjZVxuICAgICAgICBpZiAodHlwZW9mIGluY29taW5nICE9PSB0eXBlb2YgZXhpc3RpbmcpIHtcbiAgICAgICAgICByZXR1cm4gaW5jb21pbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgdGhpcy5zaG91bGRSZW9yZGVyKGV4aXN0aW5nTWV0YSwgaW5jb21pbmdNZXRhLCBleGlzdGluZywgaW5jb21pbmcpXG4gICAgICAgICAgICApID9cbiAgICAgICAgICAgICAgdGhpcy5tZXJnZShpbmNvbWluZywgZXhpc3RpbmcpXG4gICAgICAgICAgICA6IHRoaXMubWVyZ2UoZXhpc3RpbmcsIGluY29taW5nKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGV4aXN0aW5nO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBSdW4gd2hlbiBhbiBleGlzdGluZyBlbnRpdHkgaXMgZm91bmQgaW4gdGhlIHN0b3JlXG4gICAgICpcbiAgICAgKiBAc2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9yZXN0L2FwaS9FbnRpdHkjbWVyZ2VNZXRhV2l0aFN0b3JlXG4gICAgICovXG4gICAgc3RhdGljIG1lcmdlTWV0YVdpdGhTdG9yZShcbiAgICAgIGV4aXN0aW5nTWV0YToge1xuICAgICAgICBmZXRjaGVkQXQ6IG51bWJlcjtcbiAgICAgICAgZGF0ZTogbnVtYmVyO1xuICAgICAgICBleHBpcmVzQXQ6IG51bWJlcjtcbiAgICAgIH0sXG4gICAgICBpbmNvbWluZ01ldGE6IHsgZmV0Y2hlZEF0OiBudW1iZXI7IGRhdGU6IG51bWJlcjsgZXhwaXJlc0F0OiBudW1iZXIgfSxcbiAgICAgIGV4aXN0aW5nOiBhbnksXG4gICAgICBpbmNvbWluZzogYW55LFxuICAgICkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgICB0aGlzLnNob3VsZFJlb3JkZXIoZXhpc3RpbmdNZXRhLCBpbmNvbWluZ01ldGEsIGV4aXN0aW5nLCBpbmNvbWluZylcbiAgICAgICAgKSA/XG4gICAgICAgICAgZXhpc3RpbmdNZXRhXG4gICAgICAgIDogaW5jb21pbmdNZXRhO1xuICAgIH1cblxuICAgIC8qKiBGYWN0b3J5IG1ldGhvZCB0byBjb252ZXJ0IGZyb20gUGxhaW4gSlMgT2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBbcHJvcHNdIFBsYWluIE9iamVjdCBvZiBwcm9wZXJ0aWVzIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBzdGF0aWMgZnJvbUpTPFQgZXh0ZW5kcyB0eXBlb2YgRW50aXR5TWl4aW4+KFxuICAgICAgdGhpczogVCxcbiAgICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkIG9ubHkgYWNjZXB0IG1lbWJlcnMgdGhhdCBhcmUgbm90IGZ1bmN0aW9uc1xuICAgICAgcHJvcHM6IFBhcnRpYWw8QWJzdHJhY3RJbnN0YW5jZVR5cGU8VD4+ID0ge30sXG4gICAgKTogQWJzdHJhY3RJbnN0YW5jZVR5cGU8VD4ge1xuICAgICAgLy8gd2UgdHlwZSBndWFyZGVkIGFic3RyYWN0IGNhc2UgYWJvdmUsIHNvIG9rIHRvIGZvcmNlIHR5cGVzY3JpcHQgdG8gYWxsb3cgY29uc3RydWN0b3IgY2FsbFxuICAgICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgKHRoaXMgYXMgYW55KShwcm9wcykgYXMgQWJzdHJhY3RJbnN0YW5jZVR5cGU8VD47XG4gICAgICAvLyB3ZSBjYW4ndCByZWx5IG9uIGNvbnN0cnVjdG9ycyBhbmQgb3ZlcnJpZGUgdGhlIGRlZmF1bHRzIHByb3ZpZGVkIGFzIHByb3BlcnR5IGFzc2lnbm1lbnRzXG4gICAgICAvLyBhbGwgb2NjdXIgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yXG4gICAgICBPYmplY3QuYXNzaWduKGluc3RhbmNlLCBwcm9wcyk7XG4gICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyoqIENhbGxlZCB3aGVuIGRlbm9ybWFsaXppbmcgYW4gZW50aXR5IHRvIGNyZWF0ZSBhbiBpbnN0YW5jZSB3aGVuICd2YWxpZCdcbiAgICAgKlxuICAgICAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eSNjcmVhdGVJZlZhbGlkXG4gICAgICogQHBhcmFtIFtwcm9wc10gUGxhaW4gT2JqZWN0IG9mIHByb3BlcnRpZXMgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJZlZhbGlkPFQgZXh0ZW5kcyB0eXBlb2YgRW50aXR5TWl4aW4+KFxuICAgICAgdGhpczogVCxcbiAgICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkIG9ubHkgYWNjZXB0IG1lbWJlcnMgdGhhdCBhcmUgbm90IGZ1bmN0aW9uc1xuICAgICAgcHJvcHM6IFBhcnRpYWw8QWJzdHJhY3RJbnN0YW5jZVR5cGU8VD4+LFxuICAgICk6IEFic3RyYWN0SW5zdGFuY2VUeXBlPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICAgIGlmICh0aGlzLnZhbGlkYXRlKHByb3BzKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkIGFzIGFueTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmZyb21KUyhwcm9wcyk7XG4gICAgfVxuXG4gICAgLyoqIERvIGFueSB0cmFuc2Zvcm1hdGlvbnMgd2hlbiBmaXJzdCByZWNlaXZpbmcgaW5wdXRcbiAgICAgKlxuICAgICAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eSNwcm9jZXNzXG4gICAgICovXG4gICAgc3RhdGljIHByb2Nlc3MoXG4gICAgICBpbnB1dDogYW55LFxuICAgICAgcGFyZW50OiBhbnksXG4gICAgICBrZXk6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICAgIGFyZ3M6IGFueSxcbiAgICApOiBhbnkge1xuICAgICAgcmV0dXJuIHsgLi4uaW5wdXQgfTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbm9ybWFsaXplKFxuICAgICAgaW5wdXQ6IGFueSxcbiAgICAgIHBhcmVudDogYW55LFxuICAgICAga2V5OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICBhcmdzOiByZWFkb25seSBhbnlbXSxcbiAgICAgIHZpc2l0OiBWaXNpdCxcbiAgICAgIGFkZEVudGl0eTogKC4uLmFyZ3M6IGFueSkgPT4gYW55LFxuICAgICAgZ2V0RW50aXR5OiBHZXRFbnRpdHksXG4gICAgICBjaGVja0xvb3A6IENoZWNrTG9vcCxcbiAgICApOiBhbnkge1xuICAgICAgY29uc3QgcHJvY2Vzc2VkRW50aXR5ID0gdGhpcy5wcm9jZXNzKGlucHV0LCBwYXJlbnQsIGtleSwgYXJncyk7XG4gICAgICBsZXQgaWQ6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgIGlmICh0eXBlb2YgcHJvY2Vzc2VkRW50aXR5ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICBpZCA9IHRoaXMucGsoaW5wdXQsIHBhcmVudCwga2V5LCBhcmdzKTtcbiAgICAgICAgYWRkRW50aXR5KHRoaXMsIElOVkFMSUQsIGlkKTtcbiAgICAgICAgcmV0dXJuIGlkO1xuICAgICAgfVxuICAgICAgaWQgPSB0aGlzLnBrKHByb2Nlc3NlZEVudGl0eSwgcGFyZW50LCBrZXksIGFyZ3MpO1xuICAgICAgaWYgKGlkID09PSB1bmRlZmluZWQgfHwgaWQgPT09ICcnIHx8IGlkID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAvLyBjcmVhdGUgYSByYW5kb20gaWQgaWYgYSB2YWxpZCBvbmUgY2Fubm90IGJlIGNvbXB1dGVkXG4gICAgICAgIC8vIHRoaXMgaXMgdXNlZnVsIGZvciBvcHRpbWlzdGljIGNyZWF0ZXMgdGhhdCBkb24ndCBuZWVkIHJlYWwgaWRzIC0ganVzdCBzb21ldGhpbmcgdG8gaG9sZCB0aGVpciBwbGFjZVxuICAgICAgICBpZCA9IGBNSVNTLSR7TWF0aC5yYW5kb20oKX1gO1xuICAgICAgICAvLyAnY3JlYXRlcycgY29uY2VwdHVhbGx5IHNob3VsZCBhbGxvdyBtaXNzaW5nIFBLIHRvIG1ha2Ugb3B0aW1pc3RpYyBjcmVhdGVzIGVhc3lcbiAgICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgIXZpc2l0LmNyZWF0aW5nKSB7XG4gICAgICAgICAgbGV0IHdoeTogc3RyaW5nO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICEoJ3BrJyBpbiBvcHRpb25zKSAmJlxuICAgICAgICAgICAgRW50aXR5TWl4aW4ucHJvdG90eXBlLnBrID09PSB0aGlzLnByb3RvdHlwZS5wayAmJlxuICAgICAgICAgICAgISgnaWQnIGluIHByb2Nlc3NlZEVudGl0eSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHdoeSA9IGAnaWQnIG1pc3NpbmcgYnV0IG5lZWRlZCBmb3IgZGVmYXVsdCBwaygpLiBUcnkgZGVmaW5pbmcgcGsoKSBmb3IgeW91ciBFbnRpdHkuYDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2h5ID0gYFRoaXMgaXMgbGlrZWx5IGR1ZSB0byBhIG1hbGZvcm1lZCByZXNwb25zZS5cbiAgVHJ5IGluc3BlY3RpbmcgdGhlIG5ldHdvcmsgcmVzcG9uc2Ugb3IgZmV0Y2goKSByZXR1cm4gdmFsdWUuXG4gIE9yIHVzZSBkZWJ1Z2dpbmcgdG9vbHM6IGh0dHBzOi8vZGF0YWNsaWVudC5pby9kb2NzL2dldHRpbmctc3RhcnRlZC9kZWJ1Z2dpbmdgO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBNaXNzaW5nIHVzYWJsZSBwcmltYXJ5IGtleSB3aGVuIG5vcm1hbGl6aW5nIHJlc3BvbnNlLlxuXG4gICR7d2h5fVxuICBMZWFybiBtb3JlIGFib3V0IHByaW1hcnkga2V5czogaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL0VudGl0eSNwa1xuXG4gIEVudGl0eTogJHt0aGlzLmtleX1cbiAgVmFsdWUgKHByb2Nlc3NlZCk6ICR7XG4gICAgcHJvY2Vzc2VkRW50aXR5ICYmIEpTT04uc3RyaW5naWZ5KHByb2Nlc3NlZEVudGl0eSwgbnVsbCwgMilcbiAgfVxuYCxcbiAgICAgICAgICApO1xuICAgICAgICAgIChlcnJvciBhcyBhbnkpLnN0YXR1cyA9IDQwMDtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWQgPSBgJHtpZH1gO1xuICAgICAgfVxuXG4gICAgICAvKiBDaXJjdWxhciByZWZlcmVuY2Ugc2hvcnQtY2lyY3VpdGVyICovXG4gICAgICBpZiAoY2hlY2tMb29wKHRoaXMua2V5LCBpZCwgaW5wdXQpKSByZXR1cm4gaWQ7XG5cbiAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IHRoaXMudmFsaWRhdGUocHJvY2Vzc2VkRW50aXR5KTtcbiAgICAgIHRocm93VmFsaWRhdGlvbkVycm9yKGVycm9yTWVzc2FnZSk7XG5cbiAgICAgIE9iamVjdC5rZXlzKHRoaXMuc2NoZW1hKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGlmIChPYmplY3QuaGFzT3duKHByb2Nlc3NlZEVudGl0eSwga2V5KSkge1xuICAgICAgICAgIHByb2Nlc3NlZEVudGl0eVtrZXldID0gdmlzaXQoXG4gICAgICAgICAgICB0aGlzLnNjaGVtYVtrZXldLFxuICAgICAgICAgICAgcHJvY2Vzc2VkRW50aXR5W2tleV0sXG4gICAgICAgICAgICBwcm9jZXNzZWRFbnRpdHksXG4gICAgICAgICAgICBrZXksXG4gICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBhZGRFbnRpdHkodGhpcywgcHJvY2Vzc2VkRW50aXR5LCBpZCk7XG4gICAgICByZXR1cm4gaWQ7XG4gICAgfVxuXG4gICAgc3RhdGljIHZhbGlkYXRlKHByb2Nlc3NlZEVudGl0eTogYW55KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzdGF0aWMgcXVlcnlLZXkoXG4gICAgICBhcmdzOiByZWFkb25seSBhbnlbXSxcbiAgICAgIHF1ZXJ5S2V5OiBhbnksXG4gICAgICBnZXRFbnRpdHk6IEdldEVudGl0eSxcbiAgICAgIGdldEluZGV4OiBHZXRJbmRleCxcbiAgICApOiBhbnkge1xuICAgICAgaWYgKCFhcmdzWzBdKSByZXR1cm47XG4gICAgICBjb25zdCBpZCA9IHF1ZXJ5S2V5Q2FuZGlkYXRlKHRoaXMsIGFyZ3MsIGdldEluZGV4KTtcbiAgICAgIC8vIGVuc3VyZSB0aGlzIGFjdHVhbGx5IGhhcyBlbnRpdHkgb3Igd2Ugc2hvdWxkbid0IHRyeSB0byB1c2UgaXQgaW4gb3VyIHF1ZXJ5XG4gICAgICBpZiAoZ2V0RW50aXR5KHRoaXMua2V5LCBpZCkpIHJldHVybiBpZDtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGVub3JtYWxpemU8VCBleHRlbmRzIHR5cGVvZiBFbnRpdHlNaXhpbj4oXG4gICAgICB0aGlzOiBULFxuICAgICAgaW5wdXQ6IGFueSxcbiAgICAgIGFyZ3M6IGFueVtdLFxuICAgICAgdW52aXNpdDogKHNjaGVtYTogYW55LCBpbnB1dDogYW55KSA9PiBhbnksXG4gICAgKTogQWJzdHJhY3RJbnN0YW5jZVR5cGU8VD4ge1xuICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0IGFzIGFueTtcbiAgICAgIH1cblxuICAgICAgLy8gbm90ZTogaXRlcmF0aW9uIG9yZGVyIG11c3QgYmUgc3RhYmxlXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyh0aGlzLnNjaGVtYSkpIHtcbiAgICAgICAgY29uc3Qgc2NoZW1hID0gdGhpcy5zY2hlbWFba2V5XTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB1bnZpc2l0KHNjaGVtYSwgaW5wdXRba2V5XSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgICAvLyBpZiBkZWZhdWx0IGlzIG5vdCAnZmFsc3knLCB0aGVuIHRoaXMgaXMgcmVxdWlyZWQsIHNvIHByb3BhZ2F0ZSBJTlZBTElEIHN5bWJvbFxuICAgICAgICAgIGlmICh0aGlzLmRlZmF1bHRzW2tleV0pIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZSBhcyBhbnk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlucHV0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW5wdXRba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaW5wdXQ7XG4gICAgfVxuXG4gICAgLyoqIEFsbCBpbnN0YW5jZSBkZWZhdWx0cyBzZXQgKi9cbiAgICBzdGF0aWMgZ2V0IGRlZmF1bHRzKCkge1xuICAgICAgLy8gd2UgdXNlIGhhc093biBiZWNhdXNlIHdlIGRvbid0IHdhbnQgdG8gdXNlIGEgcGFyZW50cycgZGVmYXVsdHNcbiAgICAgIGlmICghT2JqZWN0Lmhhc093bih0aGlzLCAnX19kZWZhdWx0cycpKVxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ19fZGVmYXVsdHMnLCB7XG4gICAgICAgICAgdmFsdWU6IG5ldyAodGhpcyBhcyBhbnkpKCksXG4gICAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgIHJldHVybiAodGhpcyBhcyBhbnkpLl9fZGVmYXVsdHM7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgeyBwaywgc2NoZW1hLCBrZXksIC4uLnN0YXRpY1Byb3BzIH0gPSBvcHRpb25zO1xuICAvLyByZW1haW5pbmcgb3B0aW9uc1xuICBPYmplY3QuYXNzaWduKEVudGl0eU1peGluLCBzdGF0aWNQcm9wcyk7XG5cbiAgaWYgKCdzY2hlbWEnIGluIG9wdGlvbnMpIHtcbiAgICBFbnRpdHlNaXhpbi5zY2hlbWEgPSBvcHRpb25zLnNjaGVtYSBhcyBhbnk7XG4gIH0gZWxzZSBpZiAoIShCYXNlIGFzIGFueSkuc2NoZW1hKSB7XG4gICAgRW50aXR5TWl4aW4uc2NoZW1hID0ge307XG4gIH1cbiAgaWYgKCdwaycgaW4gb3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgRW50aXR5TWl4aW4ucHJvdG90eXBlLnBrID0gZnVuY3Rpb24gKHBhcmVudD86IGFueSwga2V5Pzogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiAob3B0aW9ucy5wayBhcyBhbnkpKHRoaXMsIHBhcmVudCwga2V5KTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIEVudGl0eU1peGluLnByb3RvdHlwZS5wayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzIGFzIGFueSlbb3B0aW9ucy5wa107XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBkZWZhdWx0IHRvICdpZCcgZmllbGQgaWYgdGhlIGJhc2UgY2xhc3MgZG9lc24ndCBoYXZlIGEgcGtcbiAgfSBlbHNlIGlmICh0eXBlb2YgQmFzZS5wcm90b3R5cGUucGsgIT09ICdmdW5jdGlvbicpIHtcbiAgICBFbnRpdHlNaXhpbi5wcm90b3R5cGUucGsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gKHRoaXMgYXMgYW55KS5pZDtcbiAgICB9O1xuICB9XG4gIGlmICgna2V5JyBpbiBvcHRpb25zKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVudGl0eU1peGluLCAna2V5Jywge1xuICAgICAgdmFsdWU6IG9wdGlvbnMua2V5LFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICB9IGVsc2UgaWYgKCEoJ2tleScgaW4gQmFzZSkpIHtcbiAgICBmdW5jdGlvbiBzZXQodGhpczogYW55LCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ2tleScsIHtcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG4gICAgY29uc3QgYmFzZUdldCA9IGZ1bmN0aW9uICh0aGlzOiB7IG5hbWU6IHN0cmluZyB9KTogc3RyaW5nIHtcbiAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLm5hbWUgPT09ICdFbnRpdHlNaXhpbicgPyBCYXNlLm5hbWUgOiB0aGlzLm5hbWU7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgaWYgKFxuICAgICAgICBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmXG4gICAgICAgIChuYW1lID09PSAnJyB8fCBuYW1lID09PSAnRW50aXR5TWl4aW4nIHx8IG5hbWUgPT09ICdfdGVtcCcpXG4gICAgICApXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnRW50aXR5IGNsYXNzZXMgd2l0aG91dCBhIG5hbWUgbXVzdCBkZWZpbmUgYHN0YXRpYyBrZXlgXFxuU2VlOiBodHRwczovL2RhdGFjbGllbnQuaW8vcmVzdC9hcGkvRW50aXR5I2tleScsXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9O1xuICAgIGNvbnN0IGdldCA9XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgKGRvY3VtZW50IGFzIGFueSkuQ0xTX01BTkdMRSA/XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIGZ1bmN0aW9uICh0aGlzOiB7XG4gICAgICAgICAgbmFtZTogc3RyaW5nO1xuICAgICAgICAgIGtleTogc3RyaW5nO1xuICAgICAgICB9KTogc3RyaW5nIHtcbiAgICAgICAgICAoZG9jdW1lbnQgYXMgYW55KS5DTFNfTUFOR0xFPy4odGhpcyk7XG4gICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVudGl0eU1peGluLCAna2V5Jywge1xuICAgICAgICAgICAgZ2V0OiBiYXNlR2V0LFxuICAgICAgICAgICAgc2V0LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gYmFzZUdldC5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICA6IGJhc2VHZXQ7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW50aXR5TWl4aW4sICdrZXknLCB7XG4gICAgICBnZXQsXG4gICAgICBzZXQsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIEVudGl0eU1peGluIGFzIGFueTtcbn1cblxuZnVuY3Rpb24gaW5kZXhGcm9tUGFyYW1zPEkgZXh0ZW5kcyBzdHJpbmc+KFxuICBwYXJhbXM6IFJlYWRvbmx5PG9iamVjdD4sXG4gIGluZGV4ZXM/OiBSZWFkb25seTxJW10+LFxuKSB7XG4gIGlmICghaW5kZXhlcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIGluZGV4ZXMuZmluZChpbmRleCA9PiBPYmplY3QuaGFzT3duKHBhcmFtcywgaW5kZXgpKTtcbn1cblxuLy8gcGFydCBvZiB0aGUgcmVhc29uIGZvciBwdWxsaW5nIHRoaXMgb3V0IGlzIHRoYXQgYWxsIGZ1bmN0aW9ucyB0aGF0IHRocm93IGFyZSBkZW9wdGltaXplZFxuZnVuY3Rpb24gdGhyb3dWYWxpZGF0aW9uRXJyb3IoZXJyb3JNZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgaWYgKGVycm9yTWVzc2FnZSkge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgKGVycm9yIGFzIGFueSkuc3RhdHVzID0gNDAwO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmZ1bmN0aW9uIHF1ZXJ5S2V5Q2FuZGlkYXRlKFxuICBzY2hlbWE6IGFueSxcbiAgYXJnczogcmVhZG9ubHkgYW55W10sXG4gIGdldEluZGV4OiBHZXRJbmRleCxcbikge1xuICBpZiAoWydzdHJpbmcnLCAnbnVtYmVyJ10uaW5jbHVkZXModHlwZW9mIGFyZ3NbMF0pKSB7XG4gICAgcmV0dXJuIGAke2FyZ3NbMF19YDtcbiAgfVxuICBjb25zdCBpZCA9IHNjaGVtYS5wayhhcmdzWzBdLCB1bmRlZmluZWQsICcnLCBhcmdzKTtcbiAgLy8gV2FzIGFibGUgdG8gaW5mZXIgdGhlIGVudGl0eSdzIHByaW1hcnkga2V5IGZyb20gcGFyYW1zXG4gIGlmIChpZCAhPT0gdW5kZWZpbmVkICYmIGlkICE9PSAnJykgcmV0dXJuIGlkO1xuICAvLyBub3cgYXR0ZW1wdCBsb29rdXAgaW4gaW5kZXhlc1xuICBjb25zdCBpbmRleE5hbWUgPSBpbmRleEZyb21QYXJhbXMoYXJnc1swXSwgc2NoZW1hLmluZGV4ZXMpO1xuICBpZiAoIWluZGV4TmFtZSkgcmV0dXJuO1xuICBjb25zdCB2YWx1ZSA9IChhcmdzWzBdIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2luZGV4TmFtZV07XG4gIHJldHVybiBnZXRJbmRleChzY2hlbWEua2V5LCBpbmRleE5hbWUsIHZhbHVlKVt2YWx1ZV07XG59XG4iXSwibWFwcGluZ3MiOiI7OztBQVFBLFNBQVNBLE9BQU8sUUFBUSxlQUFlOztBQVd2QztBQUNBO0FBQ0E7QUFDQTs7QUFNQTs7QUFNQTs7QUFNQSxlQUFlLFNBQVNDLFdBQVdBLENBQ2pDQyxJQUFXLEVBQ1hDLE9BQTJDLEdBQUcsQ0FBQyxDQUFDLEVBQ2hEO0VBQ0E7QUFDRjtBQUNBO0FBQ0E7RUFDRSxNQUFlRixXQUFXLFNBQVNDLElBQUksQ0FBQztJQUN0QyxPQUFPRSxRQUFRQSxDQUFBLEVBQUc7TUFDaEIsT0FBTyxJQUFJLENBQUNDLEdBQUc7SUFDakI7SUFFQSxPQUFPQyxNQUFNQSxDQUFBLEVBQUc7TUFDZCxPQUFPO1FBQ0xELEdBQUcsRUFBRSxJQUFJLENBQUNBLEdBQUc7UUFDYkUsTUFBTSxFQUFFLElBQUksQ0FBQ0E7TUFDZixDQUFDO0lBQ0g7O0lBRUE7O0lBR0E7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7SUFPSTs7SUFFQTs7SUFFQTs7SUFHQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSSxPQUFPQyxFQUFFQSxDQUVQQyxLQUF1QyxFQUN2Q0MsTUFBWSxFQUNaTCxHQUFZLEVBQ1pNLElBQXFCLEVBQ1E7TUFDN0IsT0FBTyxJQUFJLENBQUNDLFNBQVMsQ0FBQ0osRUFBRSxDQUFDSyxJQUFJLENBQUNKLEtBQUssRUFBRUMsTUFBTSxFQUFFTCxHQUFHLEVBQUVNLElBQUksQ0FBQztJQUN6RDs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtJQUNJLE9BQU9HLFlBQVlB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