typed-object-accumulator
Version:
Class capable of accumulation properties and types
173 lines (170 loc) • 19.3 kB
JavaScript
/**
* @class ObjectAccumulator
* @template T - The type of the accumulated object, extends object
* @description A class that accumulates objects and provides type-safe access to their properties.
* It allows for dynamic addition of properties while maintaining type information.
* @summary Accumulates objects and maintains type information for accumulated properties
* @memberOf utils
*/
class ObjectAccumulator {
constructor() {
Object.defineProperty(this, "__size", {
value: 0,
writable: true,
configurable: false,
enumerable: false,
});
}
/**
* @protected
* @description Expands the accumulator with properties from a new object
* @summary Adds new properties to the accumulator
* @template V - The type of the object being expanded
* @param {V} value - The object to expand with
* @returns {void}
*/
expand(value) {
Object.entries(value).forEach(([k, v]) => {
Object.defineProperty(this, k, {
get: () => v,
set: (val) => {
v = val;
},
configurable: true,
enumerable: true,
});
});
}
/**
* @description Accumulates a new object into the accumulator
* @summary Adds properties from a new object to the accumulator, maintaining type information
* @template V - The type of the object being accumulated
* @param {V} value - The object to accumulate
* @returns A new ObjectAccumulator instance with updated type information
* @mermaid
* sequenceDiagram
* participant A as Accumulator
* participant O as Object
* A->>O: Get entries
* loop For each entry
* A->>A: Define property
* end
* A->>A: Update size
* A->>A: Return updated accumulator
*/
accumulate(value) {
this.expand(value);
this.__size = this.__size + Object.keys(value).length;
return this;
}
/**
* @description Retrieves a value from the accumulator by its key
* @summary Gets a value from the accumulated object using a type-safe key
* @template T - value type
* @template K - The key type, must be a key of this
* @param {K} key - The key of the value to retrieve
* @returns The value associated with the key
*/
get(key) {
if (!(key in this))
throw new Error(`Key ${key} does not exist in accumulator. Available keys: ${this.keys().join(", ")}`);
return this[key];
}
/**
* @description Retrieves a value from the accumulator by its key
* @summary Gets a value from the accumulated object using a type-safe key
* @param {string} key - The key of the value to retrieve
* @param {any} value - The key of the value to retrieve
*/
put(key, value) {
return this.accumulate({ [key]: value });
}
/**
* @description Checks if a key exists in the accumulator
* @summary Determines whether the accumulator contains a specific key
* @param {string} key - The key to check for existence
* @returns {boolean} True if the key exists, false otherwise
*/
has(key) {
return !!this[key];
}
/**
* @description Removes a key-value pair from the accumulator
* @summary Deletes a property from the accumulated object
* @param {string} key - The key of the property to remove
* @returns {} The accumulator instance with the specified property removed
*/
remove(key) {
if (!(key in this))
return this;
delete this[key];
this.__size--;
return this;
}
/**
* @description Retrieves all keys from the accumulator
* @summary Gets an array of all accumulated property keys
* @returns {string[]} An array of keys as strings
*/
keys() {
return Object.keys(this);
}
/**
* @description Retrieves all values from the accumulator
* @summary Gets an array of all accumulated property values
* @returns An array of values
*/
values() {
return Object.values(this);
}
/**
* @description Gets the number of key-value pairs in the accumulator
* @summary Returns the count of accumulated properties
* @returns {number} The number of key-value pairs
*/
size() {
return this.__size;
}
/**
* @description Clears all accumulated key-value pairs
* @summary Removes all properties from the accumulator and returns a new empty instance
* @returns {ObjectAccumulator<never>} A new empty ObjectAccumulator instance
*/
clear() {
return new ObjectAccumulator();
}
/**
* @description Executes a callback for each key-value pair in the accumulator
* @summary Iterates over all accumulated properties, calling a function for each
* @param {function(any, string, number): void} callback - The function to execute for each entry
* @returns {void}
*/
forEach(callback) {
Object.entries(this).forEach(([key, value], i) => callback(value, key, i));
}
/**
* @description Creates a new array with the results of calling a provided function on every element in the accumulator
* @summary Maps each accumulated property to a new value using a callback function
* @template R - The type of the mapped values
* @param {function(any, string,number): R} callback - Function that produces an element of the new array
* @returns {R[]} A new array with each element being the result of the callback function
*/
map(callback) {
return Object.entries(this).map(([key, value], i) => callback(value, key, i));
}
}
/**
* @module typed-object-accumulator
* @description A TypeScript library for accumulating objects with type safety
* @summary This module provides utilities for dynamically accumulating object properties while maintaining type information. It exports the {@link ObjectAccumulator} class and version information.
*/
/**
* @description Represents the current version of the typed-object-accumulator module
* @summary The actual version number is replaced during the build process with the package version
* @const VERSION
* @type {string}
* @memberOf module:typed-object-accumulator
*/
const VERSION = "0.1.4";
export { ObjectAccumulator, VERSION };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yLmVzbS5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9hY2N1bXVsYXRvci50cyIsIi4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBjbGFzcyBPYmplY3RBY2N1bXVsYXRvclxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgYWNjdW11bGF0ZWQgb2JqZWN0LCBleHRlbmRzIG9iamVjdFxuICogQGRlc2NyaXB0aW9uIEEgY2xhc3MgdGhhdCBhY2N1bXVsYXRlcyBvYmplY3RzIGFuZCBwcm92aWRlcyB0eXBlLXNhZmUgYWNjZXNzIHRvIHRoZWlyIHByb3BlcnRpZXMuXG4gKiBJdCBhbGxvd3MgZm9yIGR5bmFtaWMgYWRkaXRpb24gb2YgcHJvcGVydGllcyB3aGlsZSBtYWludGFpbmluZyB0eXBlIGluZm9ybWF0aW9uLlxuICogQHN1bW1hcnkgQWNjdW11bGF0ZXMgb2JqZWN0cyBhbmQgbWFpbnRhaW5zIHR5cGUgaW5mb3JtYXRpb24gZm9yIGFjY3VtdWxhdGVkIHByb3BlcnRpZXNcbiAqIEBtZW1iZXJPZiB1dGlsc1xuICovXG5leHBvcnQgY2xhc3MgT2JqZWN0QWNjdW11bGF0b3I8VCBleHRlbmRzIG9iamVjdD4ge1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzaXplIG9mIHRoZSBhY2N1bXVsYXRlZCBvYmplY3RcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIHByaXZhdGUgX19zaXplITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9fc2l6ZVwiLCB7XG4gICAgICB2YWx1ZTogMCxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQGRlc2NyaXB0aW9uIEV4cGFuZHMgdGhlIGFjY3VtdWxhdG9yIHdpdGggcHJvcGVydGllcyBmcm9tIGEgbmV3IG9iamVjdFxuICAgKiBAc3VtbWFyeSBBZGRzIG5ldyBwcm9wZXJ0aWVzIHRvIHRoZSBhY2N1bXVsYXRvclxuICAgKiBAdGVtcGxhdGUgViAtIFRoZSB0eXBlIG9mIHRoZSBvYmplY3QgYmVpbmcgZXhwYW5kZWRcbiAgICogQHBhcmFtIHtWfSB2YWx1ZSAtIFRoZSBvYmplY3QgdG8gZXhwYW5kIHdpdGhcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBwcm90ZWN0ZWQgZXhwYW5kPFYgZXh0ZW5kcyBvYmplY3Q+KHZhbHVlOiBWKTogdm9pZCB7XG4gICAgT2JqZWN0LmVudHJpZXModmFsdWUpLmZvckVhY2goKFtrLCB2XSkgPT4ge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGssIHtcbiAgICAgICAgZ2V0OiAoKSA9PiB2LFxuICAgICAgICBzZXQ6ICh2YWw6IFZba2V5b2YgVl0pID0+IHtcbiAgICAgICAgICB2ID0gdmFsO1xuICAgICAgICB9LFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWNjdW11bGF0ZXMgYSBuZXcgb2JqZWN0IGludG8gdGhlIGFjY3VtdWxhdG9yXG4gICAqIEBzdW1tYXJ5IEFkZHMgcHJvcGVydGllcyBmcm9tIGEgbmV3IG9iamVjdCB0byB0aGUgYWNjdW11bGF0b3IsIG1haW50YWluaW5nIHR5cGUgaW5mb3JtYXRpb25cbiAgICogQHRlbXBsYXRlIFYgLSBUaGUgdHlwZSBvZiB0aGUgb2JqZWN0IGJlaW5nIGFjY3VtdWxhdGVkXG4gICAqIEBwYXJhbSB7Vn0gdmFsdWUgLSBUaGUgb2JqZWN0IHRvIGFjY3VtdWxhdGVcbiAgICogQHJldHVybnMgQSBuZXcgT2JqZWN0QWNjdW11bGF0b3IgaW5zdGFuY2Ugd2l0aCB1cGRhdGVkIHR5cGUgaW5mb3JtYXRpb25cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBBY2N1bXVsYXRvclxuICAgKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JqZWN0XG4gICAqICAgQS0+Pk86IEdldCBlbnRyaWVzXG4gICAqICAgbG9vcCBGb3IgZWFjaCBlbnRyeVxuICAgKiAgICAgQS0+PkE6IERlZmluZSBwcm9wZXJ0eVxuICAgKiAgIGVuZFxuICAgKiAgIEEtPj5BOiBVcGRhdGUgc2l6ZVxuICAgKiAgIEEtPj5BOiBSZXR1cm4gdXBkYXRlZCBhY2N1bXVsYXRvclxuICAgKi9cbiAgYWNjdW11bGF0ZTxWIGV4dGVuZHMgb2JqZWN0Pih2YWx1ZTogVik6IFQgJiBWICYgT2JqZWN0QWNjdW11bGF0b3I8VCAmIFY+IHtcbiAgICB0aGlzLmV4cGFuZCh2YWx1ZSk7XG4gICAgdGhpcy5fX3NpemUgPSB0aGlzLl9fc2l6ZSArIE9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGg7XG4gICAgcmV0dXJuIHRoaXMgYXMgdW5rbm93biBhcyBUICYgViAmIE9iamVjdEFjY3VtdWxhdG9yPFQgJiBWPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgdmFsdWUgZnJvbSB0aGUgYWNjdW11bGF0b3IgYnkgaXRzIGtleVxuICAgKiBAc3VtbWFyeSBHZXRzIGEgdmFsdWUgZnJvbSB0aGUgYWNjdW11bGF0ZWQgb2JqZWN0IHVzaW5nIGEgdHlwZS1zYWZlIGtleVxuICAgKiBAdGVtcGxhdGUgVCAtIHZhbHVlIHR5cGVcbiAgICogQHRlbXBsYXRlIEsgLSBUaGUga2V5IHR5cGUsIG11c3QgYmUgYSBrZXkgb2YgdGhpc1xuICAgKiBAcGFyYW0ge0t9IGtleSAtIFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJldHJpZXZlXG4gICAqIEByZXR1cm5zIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleVxuICAgKi9cbiAgZ2V0PEsgZXh0ZW5kcyBrZXlvZiBUPihrZXk6IEspOiBUW0tdIHtcbiAgICBpZiAoIShrZXkgaW4gdGhpcykpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBLZXkgJHtrZXkgYXMgc3RyaW5nfSBkb2VzIG5vdCBleGlzdCBpbiBhY2N1bXVsYXRvci4gQXZhaWxhYmxlIGtleXM6ICR7dGhpcy5rZXlzKCkuam9pbihcbiAgICAgICAgICBcIiwgXCJcbiAgICAgICAgKX1gXG4gICAgICApO1xuICAgIHJldHVybiAodGhpcyBhcyBhbnkpW2tleSBhcyBLXSBhcyBUW0tdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHRoZSBhY2N1bXVsYXRvciBieSBpdHMga2V5XG4gICAqIEBzdW1tYXJ5IEdldHMgYSB2YWx1ZSBmcm9tIHRoZSBhY2N1bXVsYXRlZCBvYmplY3QgdXNpbmcgYSB0eXBlLXNhZmUga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZXRyaWV2ZVxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgLSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZXRyaWV2ZVxuICAgKi9cbiAgcHV0KGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuYWNjdW11bGF0ZSh7IFtrZXldOiB2YWx1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGEga2V5IGV4aXN0cyBpbiB0aGUgYWNjdW11bGF0b3JcbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBhY2N1bXVsYXRvciBjb250YWlucyBhIHNwZWNpZmljIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSB0byBjaGVjayBmb3IgZXhpc3RlbmNlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBrZXkgZXhpc3RzLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIGhhcyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXNba2V5IGFzIGtleW9mIHRoaXNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZW1vdmVzIGEga2V5LXZhbHVlIHBhaXIgZnJvbSB0aGUgYWNjdW11bGF0b3JcbiAgICogQHN1bW1hcnkgRGVsZXRlcyBhIHByb3BlcnR5IGZyb20gdGhlIGFjY3VtdWxhdGVkIG9iamVjdFxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gcmVtb3ZlXG4gICAqIEByZXR1cm5zIHt9IFRoZSBhY2N1bXVsYXRvciBpbnN0YW5jZSB3aXRoIHRoZSBzcGVjaWZpZWQgcHJvcGVydHkgcmVtb3ZlZFxuICAgKi9cbiAgcmVtb3ZlKFxuICAgIGtleToga2V5b2YgdGhpcyB8IHN0cmluZ1xuICApOlxuICAgIHwgKE9taXQ8dGhpcywgdHlwZW9mIGtleT4gJiBPYmplY3RBY2N1bXVsYXRvcjxPbWl0PHRoaXMsIHR5cGVvZiBrZXk+PilcbiAgICB8IHRoaXMge1xuICAgIGlmICghKGtleSBpbiB0aGlzKSkgcmV0dXJuIHRoaXM7XG5cbiAgICBkZWxldGUgdGhpc1trZXkgYXMga2V5b2YgdGhpc107XG4gICAgdGhpcy5fX3NpemUtLTtcbiAgICByZXR1cm4gdGhpcyBhcyB1bmtub3duIGFzIE9taXQ8dGhpcywgdHlwZW9mIGtleT4gJlxuICAgICAgT2JqZWN0QWNjdW11bGF0b3I8T21pdDx0aGlzLCB0eXBlb2Yga2V5Pj47XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbGwga2V5cyBmcm9tIHRoZSBhY2N1bXVsYXRvclxuICAgKiBAc3VtbWFyeSBHZXRzIGFuIGFycmF5IG9mIGFsbCBhY2N1bXVsYXRlZCBwcm9wZXJ0eSBrZXlzXG4gICAqIEByZXR1cm5zIHtzdHJpbmdbXX0gQW4gYXJyYXkgb2Yga2V5cyBhcyBzdHJpbmdzXG4gICAqL1xuICBrZXlzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbGwgdmFsdWVzIGZyb20gdGhlIGFjY3VtdWxhdG9yXG4gICAqIEBzdW1tYXJ5IEdldHMgYW4gYXJyYXkgb2YgYWxsIGFjY3VtdWxhdGVkIHByb3BlcnR5IHZhbHVlc1xuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB2YWx1ZXNcbiAgICovXG4gIHZhbHVlcygpOiBUW2tleW9mIFRdW10ge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBudW1iZXIgb2Yga2V5LXZhbHVlIHBhaXJzIGluIHRoZSBhY2N1bXVsYXRvclxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBjb3VudCBvZiBhY2N1bXVsYXRlZCBwcm9wZXJ0aWVzXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFRoZSBudW1iZXIgb2Yga2V5LXZhbHVlIHBhaXJzXG4gICAqL1xuICBzaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX19zaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDbGVhcnMgYWxsIGFjY3VtdWxhdGVkIGtleS12YWx1ZSBwYWlyc1xuICAgKiBAc3VtbWFyeSBSZW1vdmVzIGFsbCBwcm9wZXJ0aWVzIGZyb20gdGhlIGFjY3VtdWxhdG9yIGFuZCByZXR1cm5zIGEgbmV3IGVtcHR5IGluc3RhbmNlXG4gICAqIEByZXR1cm5zIHtPYmplY3RBY2N1bXVsYXRvcjxuZXZlcj59IEEgbmV3IGVtcHR5IE9iamVjdEFjY3VtdWxhdG9yIGluc3RhbmNlXG4gICAqL1xuICBjbGVhcigpOiBPYmplY3RBY2N1bXVsYXRvcjxuZXZlcj4ge1xuICAgIHJldHVybiBuZXcgT2JqZWN0QWNjdW11bGF0b3IoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSBjYWxsYmFjayBmb3IgZWFjaCBrZXktdmFsdWUgcGFpciBpbiB0aGUgYWNjdW11bGF0b3JcbiAgICogQHN1bW1hcnkgSXRlcmF0ZXMgb3ZlciBhbGwgYWNjdW11bGF0ZWQgcHJvcGVydGllcywgY2FsbGluZyBhIGZ1bmN0aW9uIGZvciBlYWNoXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oYW55LCBzdHJpbmcsIG51bWJlcik6IHZvaWR9IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgZm9yIGVhY2ggZW50cnlcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmb3JFYWNoKFxuICAgIGNhbGxiYWNrOiAodmFsdWU6IHRoaXNba2V5b2YgdGhpc10sIGtleToga2V5b2YgdGhpcywgaTogbnVtYmVyKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIE9iamVjdC5lbnRyaWVzKHRoaXMpLmZvckVhY2goKFtrZXksIHZhbHVlXSwgaSkgPT5cbiAgICAgIGNhbGxiYWNrKHZhbHVlLCBrZXkgYXMga2V5b2YgdGhpcywgaSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IGFycmF5IHdpdGggdGhlIHJlc3VsdHMgb2YgY2FsbGluZyBhIHByb3ZpZGVkIGZ1bmN0aW9uIG9uIGV2ZXJ5IGVsZW1lbnQgaW4gdGhlIGFjY3VtdWxhdG9yXG4gICAqIEBzdW1tYXJ5IE1hcHMgZWFjaCBhY2N1bXVsYXRlZCBwcm9wZXJ0eSB0byBhIG5ldyB2YWx1ZSB1c2luZyBhIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIG1hcHBlZCB2YWx1ZXNcbiAgICogQHBhcmFtIHtmdW5jdGlvbihhbnksIHN0cmluZyxudW1iZXIpOiBSfSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gZWxlbWVudCBvZiB0aGUgbmV3IGFycmF5XG4gICAqIEByZXR1cm5zIHtSW119IEEgbmV3IGFycmF5IHdpdGggZWFjaCBlbGVtZW50IGJlaW5nIHRoZSByZXN1bHQgb2YgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAqL1xuICBtYXA8Uj4oXG4gICAgY2FsbGJhY2s6ICh2YWx1ZTogdGhpc1trZXlvZiB0aGlzXSwga2V5OiBrZXlvZiB0aGlzLCBpOiBudW1iZXIpID0+IFJcbiAgKTogUltdIHtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcykubWFwKChba2V5LCB2YWx1ZV0sIGkpID0+XG4gICAgICBjYWxsYmFjayh2YWx1ZSwga2V5IGFzIGtleW9mIHRoaXMsIGkpXG4gICAgKTtcbiAgfVxufVxuIiwiLyoqXG4gKiBAbW9kdWxlIHR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclxuICogQGRlc2NyaXB0aW9uIEEgVHlwZVNjcmlwdCBsaWJyYXJ5IGZvciBhY2N1bXVsYXRpbmcgb2JqZWN0cyB3aXRoIHR5cGUgc2FmZXR5XG4gKiBAc3VtbWFyeSBUaGlzIG1vZHVsZSBwcm92aWRlcyB1dGlsaXRpZXMgZm9yIGR5bmFtaWNhbGx5IGFjY3VtdWxhdGluZyBvYmplY3QgcHJvcGVydGllcyB3aGlsZSBtYWludGFpbmluZyB0eXBlIGluZm9ybWF0aW9uLiBJdCBleHBvcnRzIHRoZSB7QGxpbmsgT2JqZWN0QWNjdW11bGF0b3J9IGNsYXNzIGFuZCB2ZXJzaW9uIGluZm9ybWF0aW9uLlxuICovXG5cbmV4cG9ydCAqIGZyb20gXCIuL2FjY3VtdWxhdG9yXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgdHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yIG1vZHVsZVxuICogQHN1bW1hcnkgVGhlIGFjdHVhbCB2ZXJzaW9uIG51bWJlciBpcyByZXBsYWNlZCBkdXJpbmcgdGhlIGJ1aWxkIHByb2Nlc3Mgd2l0aCB0aGUgcGFja2FnZSB2ZXJzaW9uXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O0FBT0c7TUFDVSxpQkFBaUIsQ0FBQTtBQVE1QixJQUFBLFdBQUEsR0FBQTtBQUNFLFFBQUEsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFO0FBQ3BDLFlBQUEsS0FBSyxFQUFFLENBQUM7QUFDUixZQUFBLFFBQVEsRUFBRSxJQUFJO0FBQ2QsWUFBQSxZQUFZLEVBQUUsS0FBSztBQUNuQixZQUFBLFVBQVUsRUFBRSxLQUFLO0FBQ2xCLFNBQUEsQ0FBQzs7QUFHSjs7Ozs7OztBQU9HO0FBQ08sSUFBQSxNQUFNLENBQW1CLEtBQVEsRUFBQTtBQUN6QyxRQUFBLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUk7QUFDdkMsWUFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUU7QUFDN0IsZ0JBQUEsR0FBRyxFQUFFLE1BQU0sQ0FBQztBQUNaLGdCQUFBLEdBQUcsRUFBRSxDQUFDLEdBQWUsS0FBSTtvQkFDdkIsQ0FBQyxHQUFHLEdBQUc7aUJBQ1I7QUFDRCxnQkFBQSxZQUFZLEVBQUUsSUFBSTtBQUNsQixnQkFBQSxVQUFVLEVBQUUsSUFBSTtBQUNqQixhQUFBLENBQUM7QUFDSixTQUFDLENBQUM7O0FBR0o7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkc7QUFDSCxJQUFBLFVBQVUsQ0FBbUIsS0FBUSxFQUFBO0FBQ25DLFFBQUEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7QUFDbEIsUUFBQSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNO0FBQ3JELFFBQUEsT0FBTyxJQUFtRDs7QUFHNUQ7Ozs7Ozs7QUFPRztBQUNILElBQUEsR0FBRyxDQUFvQixHQUFNLEVBQUE7QUFDM0IsUUFBQSxJQUFJLEVBQUUsR0FBRyxJQUFJLElBQUksQ0FBQztBQUNoQixZQUFBLE1BQU0sSUFBSSxLQUFLLENBQ2IsQ0FBTyxJQUFBLEVBQUEsR0FBYSxtREFBbUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FDckYsSUFBSSxDQUNMLENBQUEsQ0FBRSxDQUNKO0FBQ0gsUUFBQSxPQUFRLElBQVksQ0FBQyxHQUFRLENBQVM7O0FBR3hDOzs7OztBQUtHO0lBQ0gsR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUFVLEVBQUE7QUFDekIsUUFBQSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxLQUFLLEVBQUUsQ0FBQzs7QUFHMUM7Ozs7O0FBS0c7QUFDSCxJQUFBLEdBQUcsQ0FBQyxHQUFXLEVBQUE7QUFDYixRQUFBLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFpQixDQUFDOztBQUdsQzs7Ozs7QUFLRztBQUNILElBQUEsTUFBTSxDQUNKLEdBQXdCLEVBQUE7QUFJeEIsUUFBQSxJQUFJLEVBQUUsR0FBRyxJQUFJLElBQUksQ0FBQztBQUFFLFlBQUEsT0FBTyxJQUFJO0FBRS9CLFFBQUEsT0FBTyxJQUFJLENBQUMsR0FBaUIsQ0FBQztRQUM5QixJQUFJLENBQUMsTUFBTSxFQUFFO0FBQ2IsUUFBQSxPQUFPLElBQ29DOztBQUc3Qzs7OztBQUlHO0lBQ0gsSUFBSSxHQUFBO0FBQ0YsUUFBQSxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDOztBQUcxQjs7OztBQUlHO0lBQ0gsTUFBTSxHQUFBO0FBQ0osUUFBQSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDOztBQUc1Qjs7OztBQUlHO0lBQ0gsSUFBSSxHQUFBO1FBQ0YsT0FBTyxJQUFJLENBQUMsTUFBTTs7QUFHcEI7Ozs7QUFJRztJQUNILEtBQUssR0FBQTtRQUNILE9BQU8sSUFBSSxpQkFBaUIsRUFBRTs7QUFHaEM7Ozs7O0FBS0c7QUFDSCxJQUFBLE9BQU8sQ0FDTCxRQUF1RSxFQUFBO0FBRXZFLFFBQUEsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQzNDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsR0FBaUIsRUFBRSxDQUFDLENBQUMsQ0FDdEM7O0FBR0g7Ozs7OztBQU1HO0FBQ0gsSUFBQSxHQUFHLENBQ0QsUUFBb0UsRUFBQTtBQUVwRSxRQUFBLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQzlDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsR0FBaUIsRUFBRSxDQUFDLENBQUMsQ0FDdEM7O0FBRUo7O0FDOUxEOzs7O0FBSUc7QUFJSDs7Ozs7O0FBTUc7QUFDSSxNQUFNLE9BQU8sR0FBRzs7OzsifQ==