UNPKG

@decaf-ts/decorator-validation

Version:
192 lines 25.2 kB
import { DefaultFlavour } from "./constants"; // eslint-disable-next-line @typescript-eslint/no-unused-vars function defaultFlavourResolver(target) { return DefaultFlavour; } /** * @description A decorator management class that handles flavoured decorators * @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours. * It supports registering, extending, and applying decorators with context-aware flavour resolution. * The class implements a fluent interface for defining, extending, and applying decorators with different flavours, * allowing for framework-specific decorator implementations while maintaining a consistent API. * @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator) * @param {string} [flavour] Optional flavour parameter for the decorator context * @class * @category Model * @example * ```typescript * // Create a new decoration for 'component' with default flavour * const componentDecorator = new Decoration() * .for('component') * .define(customComponentDecorator); * * // Create a flavoured decoration * const vueComponent = new Decoration('vue') * .for('component') * .define(vueComponentDecorator); * * // Apply the decoration * @componentDecorator * class MyComponent {} * ``` * @mermaid * sequenceDiagram * participant C as Client * participant D as Decoration * participant R as FlavourResolver * participant F as DecoratorFactory * * C->>D: new Decoration(flavour) * C->>D: for(key) * C->>D: define(decorators) * D->>D: register(key, flavour, decorators) * D->>F: decoratorFactory(key, flavour) * F->>R: resolve(target) * R-->>F: resolved flavour * F->>F: apply decorators * F-->>C: decorated target */ export class Decoration { /** * @description Static map of registered decorators * @summary Stores all registered decorators organized by key and flavour */ static { this.decorators = {}; } /** * @description Function to resolve flavour from a target * @summary Resolver function that determines the appropriate flavour for a given target */ static { this.flavourResolver = defaultFlavourResolver; } constructor(flavour = DefaultFlavour) { this.flavour = flavour; } /** * @description Sets the key for the decoration builder * @summary Initializes a new decoration chain with the specified key * @param {string} key The identifier for the decorator * @return {DecorationBuilderMid} Builder instance for method chaining */ for(key) { this.key = key; return this; } /** * @description Adds decorators to the current context * @summary Internal method to add decorators with addon support * @param {boolean} [addon=false] Whether the decorators are addons * @param decorators Array of decorators * @return {this} Current instance for chaining */ decorate(addon = false, ...decorators) { if (!this.key) throw new Error("key must be provided before decorators can be added"); if ((!decorators || !decorators.length) && !addon && this.flavour !== DefaultFlavour) throw new Error("Must provide overrides or addons to override or extend decaf's decorators"); if (this.flavour === DefaultFlavour && addon) throw new Error("Default flavour cannot be extended"); this[addon ? "extras" : "decorators"] = new Set([ ...(this[addon ? "extras" : "decorators"] || new Set()).values(), ...decorators, ]); return this; } /** * @description Defines the base decorators * @summary Sets the primary decorators for the current context * @param decorators Decorators to define * @return Builder instance for finishing the chain */ define(...decorators) { return this.decorate(false, ...decorators); } /** * @description Extends existing decorators * @summary Adds additional decorators to the current context * @param decorators Additional decorators * @return {DecorationBuilderBuild} Builder instance for building the decorator */ extend(...decorators) { return this.decorate(true, ...decorators); } decoratorFactory(key, f = DefaultFlavour) { const contextDecorator = function contextDecorator(target, propertyKey, descriptor) { const flavour = Decoration.flavourResolver(target); let decorators; const extras = Decoration.decorators[key][flavour] ? Decoration.decorators[key][flavour].extras : Decoration.decorators[key][DefaultFlavour].extras; if (Decoration.decorators[key] && Decoration.decorators[key][flavour] && Decoration.decorators[key][flavour].decorators) { decorators = Decoration.decorators[key][flavour].decorators; } else { decorators = Decoration.decorators[key][DefaultFlavour].decorators; } [ ...(decorators ? decorators.values() : []), ...(extras ? extras.values() : []), ].forEach((d) => d(target, propertyKey, descriptor, descriptor)); // return apply( // // )(target, propertyKey, descriptor); }; Object.defineProperty(contextDecorator, "name", { value: [f, key].join("_decorator_for_"), writable: false, }); return contextDecorator; } /** * @description Creates the final decorator function * @summary Builds and returns the decorator factory function * @return {function(any, any?, TypedPropertyDescriptor?): any} The generated decorator function */ apply() { if (!this.key) throw new Error("No key provided for the decoration builder"); Decoration.register(this.key, this.flavour, this.decorators, this.extras); return this.decoratorFactory(this.key, this.flavour); } /** * @description Registers decorators for a specific key and flavour * @summary Internal method to store decorators in the static registry * @param {string} key Decorator key * @param {string} flavour Decorator flavour * @param [decorators] Primary decorators * @param [extras] Additional decorators */ static register(key, flavour, decorators, extras) { if (!key) throw new Error("No key provided for the decoration builder"); if (!decorators) throw new Error("No decorators provided for the decoration builder"); if (!flavour) throw new Error("No flavour provided for the decoration builder"); if (!Decoration.decorators[key]) Decoration.decorators[key] = {}; if (!Decoration.decorators[key][flavour]) Decoration.decorators[key][flavour] = {}; if (decorators) Decoration.decorators[key][flavour].decorators = decorators; if (extras) Decoration.decorators[key][flavour].extras = extras; } /** * @description Sets the global flavour resolver * @summary Configures the function used to determine decorator flavours * @param {FlavourResolver} resolver Function to resolve flavours */ static setFlavourResolver(resolver) { Decoration.flavourResolver = resolver; } static for(key) { return new Decoration().for(key); } static flavouredAs(flavour) { return new Decoration(flavour); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVjb3JhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9EZWNvcmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFN0MsNkRBQTZEO0FBQzdELFNBQVMsc0JBQXNCLENBQUMsTUFBYztJQUM1QyxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBDRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBQ3JCOzs7T0FHRzthQUNZLGVBQVUsR0FTckIsRUFBRSxDQUFDO0lBRVA7OztPQUdHO2FBQ1ksb0JBQWUsR0FBb0Isc0JBQXNCLENBQUM7SUFtQnpFLFlBQW9CLFVBQWtCLGNBQWM7UUFBaEMsWUFBTyxHQUFQLE9BQU8sQ0FBeUI7SUFBRyxDQUFDO0lBRXhEOzs7OztPQUtHO0lBQ0gsR0FBRyxDQUFDLEdBQVc7UUFDYixJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLFFBQVEsQ0FDZCxRQUFpQixLQUFLLEVBQ3RCLEdBQUcsVUFBb0U7UUFFdkUsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHO1lBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1FBQ3pFLElBQ0UsQ0FBQyxDQUFDLFVBQVUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFDbkMsQ0FBQyxLQUFLO1lBQ04sSUFBSSxDQUFDLE9BQU8sS0FBSyxjQUFjO1lBRS9CLE1BQU0sSUFBSSxLQUFLLENBQ2IsMkVBQTJFLENBQzVFLENBQUM7UUFDSixJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssY0FBYyxJQUFJLEtBQUs7WUFDMUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FB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QUMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ2xFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLGtCQUFrQixDQUFDLFFBQXlCO1FBQ2pELFVBQVUsQ0FBQyxlQUFlLEdBQUcsUUFBUSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQVc7UUFDcEIsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFlO1FBQ2hDLE9BQU8sSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIERlY29yYXRpb25CdWlsZGVyQnVpbGQsXG4gIERlY29yYXRpb25CdWlsZGVyRW5kLFxuICBEZWNvcmF0aW9uQnVpbGRlck1pZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJTdGFydCxcbiAgRmxhdm91clJlc29sdmVyLFxuICBJRGVjb3JhdGlvbkJ1aWxkZXIsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWZhdWx0Rmxhdm91ciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG5mdW5jdGlvbiBkZWZhdWx0Rmxhdm91clJlc29sdmVyKHRhcmdldDogb2JqZWN0KSB7XG4gIHJldHVybiBEZWZhdWx0Rmxhdm91cjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBkZWNvcmF0b3IgbWFuYWdlbWVudCBjbGFzcyB0aGF0IGhhbmRsZXMgZmxhdm91cmVkIGRlY29yYXRvcnNcbiAqIEBzdW1tYXJ5IFRoZSBEZWNvcmF0aW9uIGNsYXNzIHByb3ZpZGVzIGEgYnVpbGRlciBwYXR0ZXJuIGZvciBjcmVhdGluZyBhbmQgbWFuYWdpbmcgZGVjb3JhdG9ycyB3aXRoIGRpZmZlcmVudCBmbGF2b3Vycy5cbiAqIEl0IHN1cHBvcnRzIHJlZ2lzdGVyaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggY29udGV4dC1hd2FyZSBmbGF2b3VyIHJlc29sdXRpb24uXG4gKiBUaGUgY2xhc3MgaW1wbGVtZW50cyBhIGZsdWVudCBpbnRlcmZhY2UgZm9yIGRlZmluaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggZGlmZmVyZW50IGZsYXZvdXJzLFxuICogYWxsb3dpbmcgZm9yIGZyYW1ld29yay1zcGVjaWZpYyBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb25zIHdoaWxlIG1haW50YWluaW5nIGEgY29uc2lzdGVudCBBUEkuXG4gKiBAdGVtcGxhdGUgVCBUeXBlIG9mIHRoZSBkZWNvcmF0b3IgKENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IpXG4gKiBAcGFyYW0ge3N0cmluZ30gW2ZsYXZvdXJdIE9wdGlvbmFsIGZsYXZvdXIgcGFyYW1ldGVyIGZvciB0aGUgZGVjb3JhdG9yIGNvbnRleHRcbiAqIEBjbGFzc1xuICogQGNhdGVnb3J5IE1vZGVsXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ3JlYXRlIGEgbmV3IGRlY29yYXRpb24gZm9yICdjb21wb25lbnQnIHdpdGggZGVmYXVsdCBmbGF2b3VyXG4gKiBjb25zdCBjb21wb25lbnREZWNvcmF0b3IgPSBuZXcgRGVjb3JhdGlvbigpXG4gKiAgIC5mb3IoJ2NvbXBvbmVudCcpXG4gKiAgIC5kZWZpbmUoY3VzdG9tQ29tcG9uZW50RGVjb3JhdG9yKTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBmbGF2b3VyZWQgZGVjb3JhdGlvblxuICogY29uc3QgdnVlQ29tcG9uZW50ID0gbmV3IERlY29yYXRpb24oJ3Z1ZScpXG4gKiAgIC5mb3IoJ2NvbXBvbmVudCcpXG4gKiAgIC5kZWZpbmUodnVlQ29tcG9uZW50RGVjb3JhdG9yKTtcbiAqXG4gKiAvLyBBcHBseSB0aGUgZGVjb3JhdGlvblxuICogQGNvbXBvbmVudERlY29yYXRvclxuICogY2xhc3MgTXlDb21wb25lbnQge31cbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudFxuICogICBwYXJ0aWNpcGFudCBEIGFzIERlY29yYXRpb25cbiAqICAgcGFydGljaXBhbnQgUiBhcyBGbGF2b3VyUmVzb2x2ZXJcbiAqICAgcGFydGljaXBhbnQgRiBhcyBEZWNvcmF0b3JGYWN0b3J5XG4gKlxuICogICBDLT4+RDogbmV3IERlY29yYXRpb24oZmxhdm91cilcbiAqICAgQy0+PkQ6IGZvcihrZXkpXG4gKiAgIEMtPj5EOiBkZWZpbmUoZGVjb3JhdG9ycylcbiAqICAgRC0+PkQ6IHJlZ2lzdGVyKGtleSwgZmxhdm91ciwgZGVjb3JhdG9ycylcbiAqICAgRC0+PkY6IGRlY29yYXRvckZhY3Rvcnkoa2V5LCBmbGF2b3VyKVxuICogICBGLT4+UjogcmVzb2x2ZSh0YXJnZXQpXG4gKiAgIFItLT4+RjogcmVzb2x2ZWQgZmxhdm91clxuICogICBGLT4+RjogYXBwbHkgZGVjb3JhdG9yc1xuICogICBGLS0+PkM6IGRlY29yYXRlZCB0YXJnZXRcbiAqL1xuZXhwb3J0IGNsYXNzIERlY29yYXRpb24gaW1wbGVtZW50cyBJRGVjb3JhdGlvbkJ1aWxkZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBtYXAgb2YgcmVnaXN0ZXJlZCBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyBhbGwgcmVnaXN0ZXJlZCBkZWNvcmF0b3JzIG9yZ2FuaXplZCBieSBrZXkgYW5kIGZsYXZvdXJcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGRlY29yYXRvcnM6IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgUmVjb3JkPFxuICAgICAgc3RyaW5nLFxuICAgICAge1xuICAgICAgICBkZWNvcmF0b3JzPzogU2V0PENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3I+O1xuICAgICAgICBleHRyYXM/OiBTZXQ8Q2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcj47XG4gICAgICB9XG4gICAgPlxuICA+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGdW5jdGlvbiB0byByZXNvbHZlIGZsYXZvdXIgZnJvbSBhIHRhcmdldFxuICAgKiBAc3VtbWFyeSBSZXNvbHZlciBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgdGhlIGFwcHJvcHJpYXRlIGZsYXZvdXIgZm9yIGEgZ2l2ZW4gdGFyZ2V0XG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBmbGF2b3VyUmVzb2x2ZXI6IEZsYXZvdXJSZXNvbHZlciA9IGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXQgb2YgZGVjb3JhdG9ycyBmb3IgdGhlIGN1cnJlbnQgY29udGV4dFxuICAgKi9cbiAgcHJpdmF0ZSBkZWNvcmF0b3JzPzogU2V0PFxuICAgIENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3JcbiAgPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBhZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgZXh0cmFzPzogU2V0PENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3I+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBkZWNvcmF0b3Iga2V5XG4gICAqL1xuICBwcml2YXRlIGtleT86IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZsYXZvdXI6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUga2V5IGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IGRlY29yYXRpb24gY2hhaW4gd2l0aCB0aGUgc3BlY2lmaWVkIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBCdWlsZGVyIGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmdcbiAgICovXG4gIGZvcihrZXk6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyTWlkIHtcbiAgICB0aGlzLmtleSA9IGtleTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkcyBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgbWV0aG9kIHRvIGFkZCBkZWNvcmF0b3JzIHdpdGggYWRkb24gc3VwcG9ydFxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthZGRvbj1mYWxzZV0gV2hldGhlciB0aGUgZGVjb3JhdG9ycyBhcmUgYWRkb25zXG4gICAqIEBwYXJhbSBkZWNvcmF0b3JzIEFycmF5IG9mIGRlY29yYXRvcnNcbiAgICogQHJldHVybiB7dGhpc30gQ3VycmVudCBpbnN0YW5jZSBmb3IgY2hhaW5pbmdcbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdGUoXG4gICAgYWRkb246IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAuLi5kZWNvcmF0b3JzOiAoQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcilbXVxuICApOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwia2V5IG11c3QgYmUgcHJvdmlkZWQgYmVmb3JlIGRlY29yYXRvcnMgY2FuIGJlIGFkZGVkXCIpO1xuICAgIGlmIChcbiAgICAgICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpICYmXG4gICAgICAhYWRkb24gJiZcbiAgICAgIHRoaXMuZmxhdm91ciAhPT0gRGVmYXVsdEZsYXZvdXJcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiTXVzdCBwcm92aWRlIG92ZXJyaWRlcyBvciBhZGRvbnMgdG8gb3ZlcnJpZGUgb3IgZXh0ZW5kIGRlY2FmJ3MgZGVjb3JhdG9yc1wiXG4gICAgICApO1xuICAgIGlmICh0aGlzLmZsYXZvdXIgPT09IERlZmF1bHRGbGF2b3VyICYmIGFkZG9uKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRGVmYXVsdCBmbGF2b3VyIGNhbm5vdCBiZSBleHRlbmRlZFwiKTtcblxuICAgIHRoaXNbYWRkb24gPyBcImV4dHJhc1wiIDogXCJkZWNvcmF0b3JzXCJdID0gbmV3IFNldChbXG4gICAgICAuLi4odGhpc1thZGRvbiA/IFwiZXh0cmFzXCIgOiBcImRlY29yYXRvcnNcIl0gfHwgbmV3IFNldCgpKS52YWx1ZXMoKSxcbiAgICAgIC4uLmRlY29yYXRvcnMsXG4gICAgXSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyB0aGUgYmFzZSBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IFNldHMgdGhlIHByaW1hcnkgZGVjb3JhdG9ycyBmb3IgdGhlIGN1cnJlbnQgY29udGV4dFxuICAgKiBAcGFyYW0gZGVjb3JhdG9ycyBEZWNvcmF0b3JzIHRvIGRlZmluZVxuICAgKiBAcmV0dXJuIEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGZpbmlzaGluZyB0aGUgY2hhaW5cbiAgICovXG4gIGRlZmluZShcbiAgICAuLi5kZWNvcmF0b3JzOiAoQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcilbXVxuICApOiBEZWNvcmF0aW9uQnVpbGRlckVuZCAmIERlY29yYXRpb25CdWlsZGVyQnVpbGQge1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKGZhbHNlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBleGlzdGluZyBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IEFkZHMgYWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgQWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyQnVpbGR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHRoZSBkZWNvcmF0b3JcbiAgICovXG4gIGV4dGVuZChcbiAgICAuLi5kZWNvcmF0b3JzOiAoQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcilbXVxuICApOiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICByZXR1cm4gdGhpcy5kZWNvcmF0ZSh0cnVlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBkZWNvcmF0b3JGYWN0b3J5KGtleTogc3RyaW5nLCBmOiBzdHJpbmcgPSBEZWZhdWx0Rmxhdm91cikge1xuICAgIGNvbnN0IGNvbnRleHREZWNvcmF0b3IgPSBmdW5jdGlvbiBjb250ZXh0RGVjb3JhdG9yKFxuICAgICAgdGFyZ2V0OiBvYmplY3QsXG4gICAgICBwcm9wZXJ0eUtleT86IGFueSxcbiAgICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICAgKSB7XG4gICAgICBjb25zdCBmbGF2b3VyID0gRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIodGFyZ2V0KTtcbiAgICAgIGxldCBkZWNvcmF0b3JzO1xuICAgICAgY29uc3QgZXh0cmFzID0gRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl1cbiAgICAgICAgPyBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXNcbiAgICAgICAgOiBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtEZWZhdWx0Rmxhdm91cl0uZXh0cmFzO1xuICAgICAgaWYgKFxuICAgICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSAmJlxuICAgICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSAmJlxuICAgICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzXG4gICAgICApIHtcbiAgICAgICAgZGVjb3JhdG9ycyA9IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmRlY29yYXRvcnM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWNvcmF0b3JzID0gRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bRGVmYXVsdEZsYXZvdXJdLmRlY29yYXRvcnM7XG4gICAgICB9XG4gICAgICBbXG4gICAgICAgIC4uLihkZWNvcmF0b3JzID8gZGVjb3JhdG9ycy52YWx1ZXMoKSA6IFtdKSxcbiAgICAgICAgLi4uKGV4dHJhcyA/IGV4dHJhcy52YWx1ZXMoKSA6IFtdKSxcbiAgICAgIF0uZm9yRWFjaCgoZCkgPT4gKGQgYXMgYW55KSh0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yLCBkZXNjcmlwdG9yKSk7XG4gICAgICAvLyByZXR1cm4gYXBwbHkoXG4gICAgICAvL1xuICAgICAgLy8gKSh0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yKTtcbiAgICB9O1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0RGVjb3JhdG9yLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IFtmLCBrZXldLmpvaW4oXCJfZGVjb3JhdG9yX2Zvcl9cIiksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnRleHREZWNvcmF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgdGhlIGZpbmFsIGRlY29yYXRvciBmdW5jdGlvblxuICAgKiBAc3VtbWFyeSBCdWlsZHMgYW5kIHJldHVybnMgdGhlIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55PywgVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I/KTogYW55fSBUaGUgZ2VuZXJhdGVkIGRlY29yYXRvciBmdW5jdGlvblxuICAgKi9cbiAgYXBwbHkoKTogKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICkgPT4gYW55IHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIERlY29yYXRpb24ucmVnaXN0ZXIodGhpcy5rZXksIHRoaXMuZmxhdm91ciwgdGhpcy5kZWNvcmF0b3JzLCB0aGlzLmV4dHJhcyk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdG9yRmFjdG9yeSh0aGlzLmtleSwgdGhpcy5mbGF2b3VyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGRlY29yYXRvcnMgZm9yIGEgc3BlY2lmaWMga2V5IGFuZCBmbGF2b3VyXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBzdG9yZSBkZWNvcmF0b3JzIGluIHRoZSBzdGF0aWMgcmVnaXN0cnlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0b3Iga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIERlY29yYXRvciBmbGF2b3VyXG4gICAqIEBwYXJhbSBbZGVjb3JhdG9yc10gUHJpbWFyeSBkZWNvcmF0b3JzXG4gICAqIEBwYXJhbSBbZXh0cmFzXSBBZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZsYXZvdXI6IHN0cmluZyxcbiAgICBkZWNvcmF0b3JzPzogU2V0PENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3I+LFxuICAgIGV4dHJhcz86IFNldDxDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yPlxuICApIHtcbiAgICBpZiAoIWtleSkgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZGVjb3JhdG9ycylcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGRlY29yYXRvcnMgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG4gICAgaWYgKCFmbGF2b3VyKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZmxhdm91ciBwcm92aWRlZCBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclwiKTtcblxuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV0pIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldID0ge307XG4gICAgaWYgKCFEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSlcbiAgICAgIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdID0ge307XG4gICAgaWYgKGRlY29yYXRvcnMpIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmRlY29yYXRvcnMgPSBkZWNvcmF0b3JzO1xuICAgIGlmIChleHRyYXMpIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmV4dHJhcyA9IGV4dHJhcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgZ2xvYmFsIGZsYXZvdXIgcmVzb2x2ZXJcbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgZnVuY3Rpb24gdXNlZCB0byBkZXRlcm1pbmUgZGVjb3JhdG9yIGZsYXZvdXJzXG4gICAqIEBwYXJhbSB7Rmxhdm91clJlc29sdmVyfSByZXNvbHZlciBGdW5jdGlvbiB0byByZXNvbHZlIGZsYXZvdXJzXG4gICAqL1xuICBzdGF0aWMgc2V0Rmxhdm91clJlc29sdmVyKHJlc29sdmVyOiBGbGF2b3VyUmVzb2x2ZXIpIHtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJSZXNvbHZlciA9IHJlc29sdmVyO1xuICB9XG5cbiAgc3RhdGljIGZvcihrZXk6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyTWlkIHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oKS5mb3Ioa2V5KTtcbiAgfVxuXG4gIHN0YXRpYyBmbGF2b3VyZWRBcyhmbGF2b3VyOiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0IHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oZmxhdm91cik7XG4gIH1cbn1cbiJdfQ==