UNPKG

@decaf-ts/db-decorators

Version:

Agnostic database decorators and repository

230 lines 25.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Context = exports.DefaultContextFactory = void 0; const constants_1 = require("./constants.cjs"); const typed_object_accumulator_1 = require("typed-object-accumulator"); /** * @description Default factory for creating context instances. * @summary A factory function that creates new Context instances with the provided repository flags. * It automatically adds a timestamp to the context and returns a properly typed context instance. * @const DefaultContextFactory * @memberOf module:db-decorators */ const DefaultContextFactory = (arg) => { return new Context().accumulate(Object.assign({}, arg, { timestamp: new Date() })); }; exports.DefaultContextFactory = DefaultContextFactory; /** * @description A context management class for handling repository operations. * @summary The Context class provides a mechanism for managing repository operations with flags, * parent-child relationships, and state accumulation. It allows for hierarchical context chains * and maintains operation-specific configurations while supporting type safety through generics. * * @template F - Type extending RepositoryFlags that defines the context configuration * * @param {ObjectAccumulator<F>} cache - The internal cache storing accumulated values * * @class * * @example * ```typescript * // Creating a new context with repository flags * const context = new Context<RepositoryFlags>(); * * // Accumulating values * const enrichedContext = context.accumulate({ * writeOperation: true, * affectedTables: ['users'], * operation: OperationKeys.CREATE * }); * * // Accessing values * const isWrite = enrichedContext.get('writeOperation'); // true * const tables = enrichedContext.get('affectedTables'); // ['users'] * ``` * * @mermaid * sequenceDiagram * participant C as Client * participant Ctx as Context * participant Cache as ObjectAccumulator * * C->>Ctx: new Context() * Ctx->>Cache: create cache * * C->>Ctx: accumulate(value) * Ctx->>Cache: accumulate(value) * Cache-->>Ctx: updated cache * Ctx-->>C: updated context * * C->>Ctx: get(key) * Ctx->>Cache: get(key) * alt Key exists in cache * Cache-->>Ctx: value * else Key not found * Ctx->>Ctx: check parent context * alt Parent exists * Ctx->>Parent: get(key) * Parent-->>Ctx: value * else No parent * Ctx-->>C: throw error * end * end * Ctx-->>C: requested value */ class Context { constructor() { this.cache = new typed_object_accumulator_1.ObjectAccumulator(); Object.defineProperty(this, "cache", { value: new typed_object_accumulator_1.ObjectAccumulator(), writable: false, enumerable: false, configurable: true, }); } static { this.factory = exports.DefaultContextFactory; } /** * @description Accumulates new values into the context. * @summary Merges the provided value object with the existing context state, * creating a new immutable cache state. * * @template F - current accumulator type * @template V - Type extending object for the values to accumulate * @param {V} value - The object containing values to accumulate * @returns A new context instance with accumulated values */ accumulate(value) { Object.defineProperty(this, "cache", { value: this.cache.accumulate(value), writable: false, enumerable: false, configurable: true, }); return this; } get timestamp() { return this.cache.timestamp; } /** * @description Retrieves a value from the context by key. * @summary Attempts to get a value from the current context's cache. * If not found, traverses up the parent context chain. * * @template K - Type extending keyof F for the key to retrieve * @template F - Accumulator type * @param {K} key - The key to retrieve from the context * @returns The value associated with the key * @throws {Error} If the key is not found in the context chain */ get(key) { try { return this.cache.get(key); } catch (e) { if (this.cache.parentContext) return this.cache.parentContext.get(key); throw e; } } /** * @description Creates a child context * @summary Generates a new context instance with current context as parent * * @template M - Type extending Model * @param {OperationKeys} operation - The operation type * @param {Constructor<M>} [model] - Optional model constructor * @returns {C} New child context instance */ child(operation, model) { return Context.childFrom(this, { operation: operation, affectedTables: model ? [model] : [], }); } /** * @description Creates a child context from another context * @summary Generates a new context instance with parent reference * * @template F - Type extending Repository Flags * @template C - Type extending Context<F> * @param {C} context - The parent context * @param {Partial<F>} [overrides] - Optional flag overrides * @returns {C} New child context instance */ static childFrom(context, overrides) { return Context.factory(Object.assign({}, context.cache, overrides || {})); } /** * @description Creates a new context from operation parameters * @summary Generates a context instance for specific operation * * @template F - Type extending Repository Flags * @template M - Type extending Model * @param {OperationKeys.DELETE} operation - The operation type * @param {Partial<F>} overrides - Flag overrides * @param {Constructor<M>} model - The model constructor * @param {any} args - Operation arguments * @returns {Promise<C>} Promise resolving to new context */ static async from(operation, overrides, model, // eslint-disable-next-line @typescript-eslint/no-unused-vars ...args) { return Context.factory(Object.assign({}, constants_1.DefaultRepositoryFlags, overrides, { operation: operation, model: model, })); } /** * @description Prepares arguments for context operations * @summary Creates a context args object with the specified operation parameters * * @template F - Type extending {@link RepositoryFlags} * @template M - Type extending {@link Model} * @param {OperationKeys.DELETE} operation - The operation type * @param {Constructor<M>} model - The model constructor * @param {any[]} args - Operation arguments * @param {Contextual<F>} [contextual] - Optional contextual object * @param {Partial<F>} [overrides] - Optional flag overrides * @returns {Promise<ContextArgs>} Promise resolving to context arguments * * @mermaid * sequenceDiagram * participant C as Context * participant M as Model * participant A as Args * * C->>C: Receive operation request * C->>M: Validate model constructor * C->>C: Create child context * C->>A: Process operation args * A->>C: Return context args * C->>C: Apply overrides * C->>C: Return final context */ static async args(operation, model, args, contextual, overrides) { const last = args.pop(); async function getContext() { if (contextual) return contextual.context(operation, overrides || {}, model, ...args); return Context.from(operation, overrides || {}, model, ...args); } let c; if (last) { if (last instanceof Context) { c = last; args.push(last); } else { c = (await getContext()); args.push(last, c); } } else { c = (await getContext()); args.push(c); } return { context: c, args: args }; } } exports.Context = Context; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXBvc2l0b3J5L0NvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsK0NBQXFEO0FBQ3JELHVFQUE2RDtBQWM3RDs7Ozs7O0dBTUc7QUFDSSxNQUFNLHFCQUFxQixHQUF3QixDQUl4RCxHQUF5QixFQUN6QixFQUFFO0lBQ0YsT0FBTyxJQUFJLE9BQU8sRUFBSyxDQUFDLFVBQVUsQ0FDaEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUUsQ0FBTSxDQUNsRCxDQUFDO0FBQ1QsQ0FBQyxDQUFDO0FBVFcsUUFBQSxxQkFBcUIseUJBU2hDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlERztBQUNILE1BQWEsT0FBTztJQUNsQjtRQVdpQixVQUFLLEdBQ3BCLElBQUksNENBQWlCLEVBQThCLENBQUM7UUFYcEQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFO1lBQ25DLEtBQUssRUFBRSxJQUFJLDRDQUFpQixFQUFLO1lBQ2pDLFFBQVEsRUFBRSxLQUFLO1lBQ2YsVUFBVSxFQUFFLEtBQUs7WUFDakIsWUFBWSxFQUFFLElBQUk7U0FDbkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzthQUVNLFlBQU8sR0FBd0IsNkJBQXFCLEFBQTdDLENBQThDO0lBSzVEOzs7Ozs7Ozs7T0FTRztJQUNILFVBQVUsQ0FBbUIsS0FBUTtRQUNuQyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUU7WUFDbkMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUNuQyxRQUFRLEVBQUUsS0FBSztZQUNmLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLFlBQVksRUFBRSxJQUFJO1NBQ25CLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBaUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQsSUFBSSxTQUFTO1FBQ1gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztJQUM5QixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILEdBQUcsQ0FBb0IsR0FBTTtRQUMzQixJQUFJLENBQUM7WUFDSCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFBQyxPQUFPLENBQVUsRUFBRSxDQUFDO1lBQ3BCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhO2dCQUFFLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sQ0FBQyxDQUFDO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILEtBQUssQ0FDSCxTQUF3QixFQUN4QixLQUFzQjtRQUV0QixPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQ3RCLElBQW9CLEVBQ3BCO1lBQ0UsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtTQUNaLENBQzNCLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsTUFBTSxDQUFDLFNBQVMsQ0FDZCxPQUFVLEVBQ1YsU0FBc0I7UUFFdEIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUNwQixNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FDbEMsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FLZixTQUl3QixFQUN4QixTQUFxQixFQUNyQixLQUFxQjtJQUNyQiw2REFBNkQ7SUFDN0QsR0FBRyxJQUFXO1FBRWQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUNwQixNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxrQ0FBc0IsRUFBRSxTQUFTLEVBQUU7WUFDbkQsU0FBUyxFQUFFLFNBQVM7WUFDcEIsS0FBSyxFQUFFLEtBQUs7U0FDYixDQUFDLENBQ0UsQ0FBQztJQUNULENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0EwQkc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FLZixTQUl3QixFQUN4QixLQUFxQixFQUNyQixJQUFXLEVBQ1gsVUFBMEIsRUFDMUIsU0FBc0I7UUFFdEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXhCLEtBQUssVUFBVSxVQUFVO1lBQ3ZCLElBQUksVUFBVTtnQkFDWixPQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFNBQVMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDeEUsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ2xFLENBQUM7UUFFRCxJQUFJLENBQUksQ0FBQztRQUNULElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxJQUFJLElBQUksWUFBWSxPQUFPLEVBQUUsQ0FBQztnQkFDNUIsQ0FBQyxHQUFHLElBQVMsQ0FBQztnQkFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2xCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixDQUFDLEdBQUcsQ0FBQyxNQUFNLFVBQVUsRUFBRSxDQUFNLENBQUM7Z0JBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLENBQUMsR0FBRyxDQUFDLE1BQU0sVUFBVSxFQUFFLENBQU0sQ0FBQztZQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2YsQ0FBQztRQUVELE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNwQyxDQUFDOztBQXhNSCwwQkF5TUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb250ZXh0QXJncyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBDb250ZXh0dWFsIH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvQ29udGV4dHVhbFwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRGVmYXVsdFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT2JqZWN0QWNjdW11bGF0b3IgfSBmcm9tIFwidHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IHR5cGUgZm9yIGNyZWF0aW5nIGNvbnRleHQgaW5zdGFuY2VzLlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGZ1bmN0aW9uIHR5cGUgdGhhdCBjcmVhdGVzIGNvbnRleHQgaW5zdGFuY2VzIHdpdGggc3BlY2lmaWMgcmVwb3NpdG9yeSBmbGFncy5cbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeUZsYWdzXG4gKiBAdHlwZWRlZiB7RnVuY3Rpb259IENvbnRleHRGYWN0b3J5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IHR5cGUgQ29udGV4dEZhY3Rvcnk8RiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncz4gPSA8QyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICBhcmc6IE9taXQ8RiwgXCJ0aW1lc3RhbXBcIj5cbikgPT4gQztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBmYWN0b3J5IGZvciBjcmVhdGluZyBjb250ZXh0IGluc3RhbmNlcy5cbiAqIEBzdW1tYXJ5IEEgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IGNyZWF0ZXMgbmV3IENvbnRleHQgaW5zdGFuY2VzIHdpdGggdGhlIHByb3ZpZGVkIHJlcG9zaXRvcnkgZmxhZ3MuXG4gKiBJdCBhdXRvbWF0aWNhbGx5IGFkZHMgYSB0aW1lc3RhbXAgdG8gdGhlIGNvbnRleHQgYW5kIHJldHVybnMgYSBwcm9wZXJseSB0eXBlZCBjb250ZXh0IGluc3RhbmNlLlxuICogQGNvbnN0IERlZmF1bHRDb250ZXh0RmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0Q29udGV4dEZhY3Rvcnk6IENvbnRleHRGYWN0b3J5PGFueT4gPSA8XG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuPihcbiAgYXJnOiBPbWl0PEYsIFwidGltZXN0YW1wXCI+XG4pID0+IHtcbiAgcmV0dXJuIG5ldyBDb250ZXh0PEY+KCkuYWNjdW11bGF0ZShcbiAgICBPYmplY3QuYXNzaWduKHt9LCBhcmcsIHsgdGltZXN0YW1wOiBuZXcgRGF0ZSgpIH0pIGFzIEZcbiAgKSBhcyBDO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBjb250ZXh0IG1hbmFnZW1lbnQgY2xhc3MgZm9yIGhhbmRsaW5nIHJlcG9zaXRvcnkgb3BlcmF0aW9ucy5cbiAqIEBzdW1tYXJ5IFRoZSBDb250ZXh0IGNsYXNzIHByb3ZpZGVzIGEgbWVjaGFuaXNtIGZvciBtYW5hZ2luZyByZXBvc2l0b3J5IG9wZXJhdGlvbnMgd2l0aCBmbGFncyxcbiAqIHBhcmVudC1jaGlsZCByZWxhdGlvbnNoaXBzLCBhbmQgc3RhdGUgYWNjdW11bGF0aW9uLiBJdCBhbGxvd3MgZm9yIGhpZXJhcmNoaWNhbCBjb250ZXh0IGNoYWluc1xuICogYW5kIG1haW50YWlucyBvcGVyYXRpb24tc3BlY2lmaWMgY29uZmlndXJhdGlvbnMgd2hpbGUgc3VwcG9ydGluZyB0eXBlIHNhZmV0eSB0aHJvdWdoIGdlbmVyaWNzLlxuICpcbiAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeUZsYWdzIHRoYXQgZGVmaW5lcyB0aGUgY29udGV4dCBjb25maWd1cmF0aW9uXG4gKlxuICogQHBhcmFtIHtPYmplY3RBY2N1bXVsYXRvcjxGPn0gY2FjaGUgLSBUaGUgaW50ZXJuYWwgY2FjaGUgc3RvcmluZyBhY2N1bXVsYXRlZCB2YWx1ZXNcbiAqXG4gKiBAY2xhc3NcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ3JlYXRpbmcgYSBuZXcgY29udGV4dCB3aXRoIHJlcG9zaXRvcnkgZmxhZ3NcbiAqIGNvbnN0IGNvbnRleHQgPSBuZXcgQ29udGV4dDxSZXBvc2l0b3J5RmxhZ3M+KCk7XG4gKlxuICogLy8gQWNjdW11bGF0aW5nIHZhbHVlc1xuICogY29uc3QgZW5yaWNoZWRDb250ZXh0ID0gY29udGV4dC5hY2N1bXVsYXRlKHtcbiAqICAgd3JpdGVPcGVyYXRpb246IHRydWUsXG4gKiAgIGFmZmVjdGVkVGFibGVzOiBbJ3VzZXJzJ10sXG4gKiAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAqIH0pO1xuICpcbiAqIC8vIEFjY2Vzc2luZyB2YWx1ZXNcbiAqIGNvbnN0IGlzV3JpdGUgPSBlbnJpY2hlZENvbnRleHQuZ2V0KCd3cml0ZU9wZXJhdGlvbicpOyAvLyB0cnVlXG4gKiBjb25zdCB0YWJsZXMgPSBlbnJpY2hlZENvbnRleHQuZ2V0KCdhZmZlY3RlZFRhYmxlcycpOyAvLyBbJ3VzZXJzJ11cbiAqIGBgYFxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgQ3R4IGFzIENvbnRleHRcbiAqICAgcGFydGljaXBhbnQgQ2FjaGUgYXMgT2JqZWN0QWNjdW11bGF0b3JcbiAqXG4gKiAgIEMtPj5DdHg6IG5ldyBDb250ZXh0KClcbiAqICAgQ3R4LT4+Q2FjaGU6IGNyZWF0ZSBjYWNoZVxuICpcbiAqICAgQy0+PkN0eDogYWNjdW11bGF0ZSh2YWx1ZSlcbiAqICAgQ3R4LT4+Q2FjaGU6IGFjY3VtdWxhdGUodmFsdWUpXG4gKiAgIENhY2hlLS0+PkN0eDogdXBkYXRlZCBjYWNoZVxuICogICBDdHgtLT4+QzogdXBkYXRlZCBjb250ZXh0XG4gKlxuICogICBDLT4+Q3R4OiBnZXQoa2V5KVxuICogICBDdHgtPj5DYWNoZTogZ2V0KGtleSlcbiAqICAgYWx0IEtleSBleGlzdHMgaW4gY2FjaGVcbiAqICAgICBDYWNoZS0tPj5DdHg6IHZhbHVlXG4gKiAgIGVsc2UgS2V5IG5vdCBmb3VuZFxuICogICAgIEN0eC0+PkN0eDogY2hlY2sgcGFyZW50IGNvbnRleHRcbiAqICAgICBhbHQgUGFyZW50IGV4aXN0c1xuICogICAgICAgQ3R4LT4+UGFyZW50OiBnZXQoa2V5KVxuICogICAgICAgUGFyZW50LS0+PkN0eDogdmFsdWVcbiAqICAgICBlbHNlIE5vIHBhcmVudFxuICogICAgICAgQ3R4LS0+PkM6IHRocm93IGVycm9yXG4gKiAgICAgZW5kXG4gKiAgIGVuZFxuICogICBDdHgtLT4+QzogcmVxdWVzdGVkIHZhbHVlXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250ZXh0PEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3M+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwiY2FjaGVcIiwge1xuICAgICAgdmFsdWU6IG5ldyBPYmplY3RBY2N1bXVsYXRvcjxGPigpLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZmFjdG9yeTogQ29udGV4dEZhY3Rvcnk8YW55PiA9IERlZmF1bHRDb250ZXh0RmFjdG9yeTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNhY2hlOiBGICYgT2JqZWN0QWNjdW11bGF0b3I8Rj4gPVxuICAgIG5ldyBPYmplY3RBY2N1bXVsYXRvcigpIGFzIEYgJiBPYmplY3RBY2N1bXVsYXRvcjxGPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFjY3VtdWxhdGVzIG5ldyB2YWx1ZXMgaW50byB0aGUgY29udGV4dC5cbiAgICogQHN1bW1hcnkgTWVyZ2VzIHRoZSBwcm92aWRlZCB2YWx1ZSBvYmplY3Qgd2l0aCB0aGUgZXhpc3RpbmcgY29udGV4dCBzdGF0ZSxcbiAgICogY3JlYXRpbmcgYSBuZXcgaW1tdXRhYmxlIGNhY2hlIHN0YXRlLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgRiAtIGN1cnJlbnQgYWNjdW11bGF0b3IgdHlwZVxuICAgKiBAdGVtcGxhdGUgViAtIFR5cGUgZXh0ZW5kaW5nIG9iamVjdCBmb3IgdGhlIHZhbHVlcyB0byBhY2N1bXVsYXRlXG4gICAqIEBwYXJhbSB7Vn0gdmFsdWUgLSBUaGUgb2JqZWN0IGNvbnRhaW5pbmcgdmFsdWVzIHRvIGFjY3VtdWxhdGVcbiAgICogQHJldHVybnMgQSBuZXcgY29udGV4dCBpbnN0YW5jZSB3aXRoIGFjY3VtdWxhdGVkIHZhbHVlc1xuICAgKi9cbiAgYWNjdW11bGF0ZTxWIGV4dGVuZHMgb2JqZWN0Pih2YWx1ZTogVikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcImNhY2hlXCIsIHtcbiAgICAgIHZhbHVlOiB0aGlzLmNhY2hlLmFjY3VtdWxhdGUodmFsdWUpLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMgYXMgdW5rbm93biBhcyBDb250ZXh0PEYgJiBWPjtcbiAgfVxuXG4gIGdldCB0aW1lc3RhbXAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUudGltZXN0YW1wO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHRoZSBjb250ZXh0IGJ5IGtleS5cbiAgICogQHN1bW1hcnkgQXR0ZW1wdHMgdG8gZ2V0IGEgdmFsdWUgZnJvbSB0aGUgY3VycmVudCBjb250ZXh0J3MgY2FjaGUuXG4gICAqIElmIG5vdCBmb3VuZCwgdHJhdmVyc2VzIHVwIHRoZSBwYXJlbnQgY29udGV4dCBjaGFpbi5cbiAgICpcbiAgICogQHRlbXBsYXRlIEsgLSBUeXBlIGV4dGVuZGluZyBrZXlvZiBGIGZvciB0aGUga2V5IHRvIHJldHJpZXZlXG4gICAqIEB0ZW1wbGF0ZSBGIC0gQWNjdW11bGF0b3IgdHlwZVxuICAgKiBAcGFyYW0ge0t9IGtleSAtIFRoZSBrZXkgdG8gcmV0cmlldmUgZnJvbSB0aGUgY29udGV4dFxuICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBrZXlcbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBrZXkgaXMgbm90IGZvdW5kIGluIHRoZSBjb250ZXh0IGNoYWluXG4gICAqL1xuICBnZXQ8SyBleHRlbmRzIGtleW9mIEY+KGtleTogSyk6IEZbS10ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoa2V5KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAodGhpcy5jYWNoZS5wYXJlbnRDb250ZXh0KSByZXR1cm4gdGhpcy5jYWNoZS5wYXJlbnRDb250ZXh0LmdldChrZXkpO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBjaGlsZCBjb250ZXh0XG4gICAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhIG5ldyBjb250ZXh0IGluc3RhbmNlIHdpdGggY3VycmVudCBjb250ZXh0IGFzIHBhcmVudFxuICAgKlxuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c30gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiB0eXBlXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFttb2RlbF0gLSBPcHRpb25hbCBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJucyB7Q30gTmV3IGNoaWxkIGNvbnRleHQgaW5zdGFuY2VcbiAgICovXG4gIGNoaWxkPE0gZXh0ZW5kcyBNb2RlbCwgQyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbD86IENvbnN0cnVjdG9yPE0+XG4gICk6IEMge1xuICAgIHJldHVybiBDb250ZXh0LmNoaWxkRnJvbTxGLCBDPihcbiAgICAgIHRoaXMgYXMgdW5rbm93biBhcyBDLFxuICAgICAge1xuICAgICAgICBvcGVyYXRpb246IG9wZXJhdGlvbixcbiAgICAgICAgYWZmZWN0ZWRUYWJsZXM6IG1vZGVsID8gW21vZGVsXSA6IFtdLFxuICAgICAgfSBhcyB1bmtub3duIGFzIFBhcnRpYWw8Rj5cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgY2hpbGQgY29udGV4dCBmcm9tIGFub3RoZXIgY29udGV4dFxuICAgKiBAc3VtbWFyeSBHZW5lcmF0ZXMgYSBuZXcgY29udGV4dCBpbnN0YW5jZSB3aXRoIHBhcmVudCByZWZlcmVuY2VcbiAgICpcbiAgICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5IEZsYWdzXG4gICAqIEB0ZW1wbGF0ZSBDIC0gVHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgcGFyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEY+fSBbb3ZlcnJpZGVzXSAtIE9wdGlvbmFsIGZsYWcgb3ZlcnJpZGVzXG4gICAqIEByZXR1cm5zIHtDfSBOZXcgY2hpbGQgY29udGV4dCBpbnN0YW5jZVxuICAgKi9cbiAgc3RhdGljIGNoaWxkRnJvbTxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLCBDIGV4dGVuZHMgQ29udGV4dDxGPj4oXG4gICAgY29udGV4dDogQyxcbiAgICBvdmVycmlkZXM/OiBQYXJ0aWFsPEY+XG4gICk6IEMge1xuICAgIHJldHVybiBDb250ZXh0LmZhY3RvcnkoXG4gICAgICBPYmplY3QuYXNzaWduKHt9LCBjb250ZXh0LmNhY2hlLCBvdmVycmlkZXMgfHwge30pXG4gICAgKSBhcyB1bmtub3duIGFzIEM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgY29udGV4dCBmcm9tIG9wZXJhdGlvbiBwYXJhbWV0ZXJzXG4gICAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhIGNvbnRleHQgaW5zdGFuY2UgZm9yIHNwZWNpZmljIG9wZXJhdGlvblxuICAgKlxuICAgKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnkgRmxhZ3NcbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXMuREVMRVRFfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIHR5cGVcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEY+fSBvdmVycmlkZXMgLSBGbGFnIG92ZXJyaWRlc1xuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge2FueX0gYXJncyAtIE9wZXJhdGlvbiBhcmd1bWVudHNcbiAgICogQHJldHVybnMge1Byb21pc2U8Qz59IFByb21pc2UgcmVzb2x2aW5nIHRvIG5ldyBjb250ZXh0XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZnJvbTxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbiAgPihcbiAgICBvcGVyYXRpb246XG4gICAgICB8IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICAgICAgfCBPcGVyYXRpb25LZXlzLlVQREFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICBvdmVycmlkZXM6IFBhcnRpYWw8Rj4sXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPEM+IHtcbiAgICByZXR1cm4gQ29udGV4dC5mYWN0b3J5KFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgRGVmYXVsdFJlcG9zaXRvcnlGbGFncywgb3ZlcnJpZGVzLCB7XG4gICAgICAgIG9wZXJhdGlvbjogb3BlcmF0aW9uLFxuICAgICAgICBtb2RlbDogbW9kZWwsXG4gICAgICB9KVxuICAgICkgYXMgQztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYXJndW1lbnRzIGZvciBjb250ZXh0IG9wZXJhdGlvbnNcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIGNvbnRleHQgYXJncyBvYmplY3Qgd2l0aCB0aGUgc3BlY2lmaWVkIG9wZXJhdGlvbiBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcge0BsaW5rIFJlcG9zaXRvcnlGbGFnc31cbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyB7QGxpbmsgTW9kZWx9XG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cy5ERUxFVEV9IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24gdHlwZVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gT3BlcmF0aW9uIGFyZ3VtZW50c1xuICAgKiBAcGFyYW0ge0NvbnRleHR1YWw8Rj59IFtjb250ZXh0dWFsXSAtIE9wdGlvbmFsIGNvbnRleHR1YWwgb2JqZWN0XG4gICAqIEBwYXJhbSB7UGFydGlhbDxGPn0gW292ZXJyaWRlc10gLSBPcHRpb25hbCBmbGFnIG92ZXJyaWRlc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxDb250ZXh0QXJncz59IFByb21pc2UgcmVzb2x2aW5nIHRvIGNvbnRleHQgYXJndW1lbnRzXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEMgYXMgQ29udGV4dFxuICAgKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIEFyZ3NcbiAgICpcbiAgICogICBDLT4+QzogUmVjZWl2ZSBvcGVyYXRpb24gcmVxdWVzdFxuICAgKiAgIEMtPj5NOiBWYWxpZGF0ZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiAgIEMtPj5DOiBDcmVhdGUgY2hpbGQgY29udGV4dFxuICAgKiAgIEMtPj5BOiBQcm9jZXNzIG9wZXJhdGlvbiBhcmdzXG4gICAqICAgQS0+PkM6IFJldHVybiBjb250ZXh0IGFyZ3NcbiAgICogICBDLT4+QzogQXBwbHkgb3ZlcnJpZGVzXG4gICAqICAgQy0+PkM6IFJldHVybiBmaW5hbCBjb250ZXh0XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXJnczxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgPihcbiAgICBvcGVyYXRpb246XG4gICAgICB8IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICAgICAgfCBPcGVyYXRpb25LZXlzLlVQREFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgYXJnczogYW55W10sXG4gICAgY29udGV4dHVhbD86IENvbnRleHR1YWw8Rj4sXG4gICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGPlxuICApOiBQcm9taXNlPENvbnRleHRBcmdzPEYsIEM+PiB7XG4gICAgY29uc3QgbGFzdCA9IGFyZ3MucG9wKCk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiBnZXRDb250ZXh0KCkge1xuICAgICAgaWYgKGNvbnRleHR1YWwpXG4gICAgICAgIHJldHVybiBjb250ZXh0dWFsLmNvbnRleHQob3BlcmF0aW9uLCBvdmVycmlkZXMgfHwge30sIG1vZGVsLCAuLi5hcmdzKTtcbiAgICAgIHJldHVybiBDb250ZXh0LmZyb20ob3BlcmF0aW9uLCBvdmVycmlkZXMgfHwge30sIG1vZGVsLCAuLi5hcmdzKTtcbiAgICB9XG5cbiAgICBsZXQgYzogQztcbiAgICBpZiAobGFzdCkge1xuICAgICAgaWYgKGxhc3QgaW5zdGFuY2VvZiBDb250ZXh0KSB7XG4gICAgICAgIGMgPSBsYXN0IGFzIEM7XG4gICAgICAgIGFyZ3MucHVzaChsYXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGMgPSAoYXdhaXQgZ2V0Q29udGV4dCgpKSBhcyBDO1xuICAgICAgICBhcmdzLnB1c2gobGFzdCwgYyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGMgPSAoYXdhaXQgZ2V0Q29udGV4dCgpKSBhcyBDO1xuICAgICAgYXJncy5wdXNoKGMpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGNvbnRleHQ6IGMsIGFyZ3M6IGFyZ3MgfTtcbiAgfVxufVxuIl19