@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
190 lines • 25.1 kB
JavaScript
import { DefaultFlavour } from "./constants.js";
// 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;
}
const toApply = [
...(decorators ? decorators.values() : []),
...(extras ? extras.values() : []),
];
toApply.forEach((d) => d(target, propertyKey, descriptor, 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVjb3JhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9EZWNvcmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsdUJBQW9CO0FBRTdDLDZEQUE2RDtBQUM3RCxTQUFTLHNCQUFzQixDQUFDLE1BQWM7SUFDNUMsT0FBTyxjQUFjLENBQUM7QUFDeEIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQ0c7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUNyQjs7O09BR0c7YUFDWSxlQUFVLEdBU3JCLEVBQUUsQ0FBQztJQUVQOzs7T0FHRzthQUNZLG9CQUFlLEdBQW9CLHNCQUFzQixDQUFDO0lBbUJ6RSxZQUFvQixVQUFrQixjQUFjO1FBQWhDLFlBQU8sR0FBUCxPQUFPLENBQXlCO0lBQUcsQ0FBQztJQUV4RDs7Ozs7T0FLRztJQUNILEdBQUcsQ0FBQyxHQUFXO1FBQ2IsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxRQUFRLENBQ2QsUUFBaUIsS0FBSyxFQUN0QixHQUFHLFVBQW9FO1FBRXZFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztRQUN6RSxJQUNFLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQ25DLENBQUMsS0FBSztZQUNOLElBQUksQ0FBQyxPQUFPLEtBQUssY0FBYztZQUUvQixNQUFNLElBQUksS0FBSyxDQUNiLDJFQUEyRSxDQUM1RSxDQUFDO1FBQ0osSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLGNBQWMsSUFBSSxLQUFLO1lBQzFDLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMs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R0FBRyxNQUFNLENBQUM7SUFDbEUsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsa0JBQWtCLENBQUMsUUFBeUI7UUFDakQsVUFBVSxDQUFDLGVBQWUsR0FBRyxRQUFRLENBQUM7SUFDeEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBVztRQUNwQixPQUFPLElBQUksVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRCxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQWU7UUFDaEMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJFbmQsXG4gIERlY29yYXRpb25CdWlsZGVyTWlkLFxuICBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0LFxuICBGbGF2b3VyUmVzb2x2ZXIsXG4gIElEZWNvcmF0aW9uQnVpbGRlcixcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRGbGF2b3VyIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbmZ1bmN0aW9uIGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXIodGFyZ2V0OiBvYmplY3QpIHtcbiAgcmV0dXJuIERlZmF1bHRGbGF2b3VyO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIGRlY29yYXRvciBtYW5hZ2VtZW50IGNsYXNzIHRoYXQgaGFuZGxlcyBmbGF2b3VyZWQgZGVjb3JhdG9yc1xuICogQHN1bW1hcnkgVGhlIERlY29yYXRpb24gY2xhc3MgcHJvdmlkZXMgYSBidWlsZGVyIHBhdHRlcm4gZm9yIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyBkZWNvcmF0b3JzIHdpdGggZGlmZmVyZW50IGZsYXZvdXJzLlxuICogSXQgc3VwcG9ydHMgcmVnaXN0ZXJpbmcsIGV4dGVuZGluZywgYW5kIGFwcGx5aW5nIGRlY29yYXRvcnMgd2l0aCBjb250ZXh0LWF3YXJlIGZsYXZvdXIgcmVzb2x1dGlvbi5cbiAqIFRoZSBjbGFzcyBpbXBsZW1lbnRzIGEgZmx1ZW50IGludGVyZmFjZSBmb3IgZGVmaW5pbmcsIGV4dGVuZGluZywgYW5kIGFwcGx5aW5nIGRlY29yYXRvcnMgd2l0aCBkaWZmZXJlbnQgZmxhdm91cnMsXG4gKiBhbGxvd2luZyBmb3IgZnJhbWV3b3JrLXNwZWNpZmljIGRlY29yYXRvciBpbXBsZW1lbnRhdGlvbnMgd2hpbGUgbWFpbnRhaW5pbmcgYSBjb25zaXN0ZW50IEFQSS5cbiAqIEB0ZW1wbGF0ZSBUIFR5cGUgb2YgdGhlIGRlY29yYXRvciAoQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcilcbiAqIEBwYXJhbSB7c3RyaW5nfSBbZmxhdm91cl0gT3B0aW9uYWwgZmxhdm91ciBwYXJhbWV0ZXIgZm9yIHRoZSBkZWNvcmF0b3IgY29udGV4dFxuICogQGNsYXNzXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBuZXcgZGVjb3JhdGlvbiBmb3IgJ2NvbXBvbmVudCcgd2l0aCBkZWZhdWx0IGZsYXZvdXJcbiAqIGNvbnN0IGNvbXBvbmVudERlY29yYXRvciA9IG5ldyBEZWNvcmF0aW9uKClcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZShjdXN0b21Db21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIENyZWF0ZSBhIGZsYXZvdXJlZCBkZWNvcmF0aW9uXG4gKiBjb25zdCB2dWVDb21wb25lbnQgPSBuZXcgRGVjb3JhdGlvbigndnVlJylcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZSh2dWVDb21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIEFwcGx5IHRoZSBkZWNvcmF0aW9uXG4gKiBAY29tcG9uZW50RGVjb3JhdG9yXG4gKiBjbGFzcyBNeUNvbXBvbmVudCB7fVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdGlvblxuICogICBwYXJ0aWNpcGFudCBSIGFzIEZsYXZvdXJSZXNvbHZlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIERlY29yYXRvckZhY3RvcnlcbiAqXG4gKiAgIEMtPj5EOiBuZXcgRGVjb3JhdGlvbihmbGF2b3VyKVxuICogICBDLT4+RDogZm9yKGtleSlcbiAqICAgQy0+PkQ6IGRlZmluZShkZWNvcmF0b3JzKVxuICogICBELT4+RDogcmVnaXN0ZXIoa2V5LCBmbGF2b3VyLCBkZWNvcmF0b3JzKVxuICogICBELT4+RjogZGVjb3JhdG9yRmFjdG9yeShrZXksIGZsYXZvdXIpXG4gKiAgIEYtPj5SOiByZXNvbHZlKHRhcmdldClcbiAqICAgUi0tPj5GOiByZXNvbHZlZCBmbGF2b3VyXG4gKiAgIEYtPj5GOiBhcHBseSBkZWNvcmF0b3JzXG4gKiAgIEYtLT4+QzogZGVjb3JhdGVkIHRhcmdldFxuICovXG5leHBvcnQgY2xhc3MgRGVjb3JhdGlvbiBpbXBsZW1lbnRzIElEZWNvcmF0aW9uQnVpbGRlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1hcCBvZiByZWdpc3RlcmVkIGRlY29yYXRvcnNcbiAgICogQHN1bW1hcnkgU3RvcmVzIGFsbCByZWdpc3RlcmVkIGRlY29yYXRvcnMgb3JnYW5pemVkIGJ5IGtleSBhbmQgZmxhdm91clxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZGVjb3JhdG9yczogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBSZWNvcmQ8XG4gICAgICBzdHJpbmcsXG4gICAgICB7XG4gICAgICAgIGRlY29yYXRvcnM/OiBTZXQ8Q2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcj47XG4gICAgICAgIGV4dHJhcz86IFNldDxDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yPjtcbiAgICAgIH1cbiAgICA+XG4gID4gPSB7fTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZ1bmN0aW9uIHRvIHJlc29sdmUgZmxhdm91ciBmcm9tIGEgdGFyZ2V0XG4gICAqIEBzdW1tYXJ5IFJlc29sdmVyIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB0aGUgYXBwcm9wcmlhdGUgZmxhdm91ciBmb3IgYSBnaXZlbiB0YXJnZXRcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGZsYXZvdXJSZXNvbHZlcjogRmxhdm91clJlc29sdmVyID0gZGVmYXVsdEZsYXZvdXJSZXNvbHZlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBkZWNvcmF0b3JzIGZvciB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqL1xuICBwcml2YXRlIGRlY29yYXRvcnM/OiBTZXQ8XG4gICAgQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvclxuICA+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0IG9mIGFkZGl0aW9uYWwgZGVjb3JhdG9yc1xuICAgKi9cbiAgcHJpdmF0ZSBleHRyYXM/OiBTZXQ8Q2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IGRlY29yYXRvciBrZXlcbiAgICovXG4gIHByaXZhdGUga2V5Pzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmxhdm91cjogc3RyaW5nID0gRGVmYXVsdEZsYXZvdXIpIHt9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBrZXkgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBuZXcgZGVjb3JhdGlvbiBjaGFpbiB3aXRoIHRoZSBzcGVjaWZpZWQga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGlkZW50aWZpZXIgZm9yIHRoZSBkZWNvcmF0b3JcbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJNaWR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZ1xuICAgKi9cbiAgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHRoaXMua2V5ID0ga2V5O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBZGRzIGRlY29yYXRvcnMgdG8gdGhlIGN1cnJlbnQgY29udGV4dFxuICAgKiBAc3VtbWFyeSBJbnRlcm5hbCBtZXRob2QgdG8gYWRkIGRlY29yYXRvcnMgd2l0aCBhZGRvbiBzdXBwb3J0XG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2FkZG9uPWZhbHNlXSBXaGV0aGVyIHRoZSBkZWNvcmF0b3JzIGFyZSBhZGRvbnNcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgQXJyYXkgb2YgZGVjb3JhdG9yc1xuICAgKiBAcmV0dXJuIHt0aGlzfSBDdXJyZW50IGluc3RhbmNlIGZvciBjaGFpbmluZ1xuICAgKi9cbiAgcHJpdmF0ZSBkZWNvcmF0ZShcbiAgICBhZGRvbjogYm9vbGVhbiA9IGZhbHNlLFxuICAgIC4uLmRlY29yYXRvcnM6IChDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yKVtdXG4gICk6IHRoaXMge1xuICAgIGlmICghdGhpcy5rZXkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJrZXkgbXVzdCBiZSBwcm92aWRlZCBiZWZvcmUgZGVjb3JhdG9ycyBjYW4gYmUgYWRkZWRcIik7XG4gICAgaWYgKFxuICAgICAgKCFkZWNvcmF0b3JzIHx8ICFkZWNvcmF0b3JzLmxlbmd0aCkgJiZcbiAgICAgICFhZGRvbiAmJlxuICAgICAgdGhpcy5mbGF2b3VyICE9PSBEZWZhdWx0Rmxhdm91clxuICAgIClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJNdXN0IHByb3ZpZGUgb3ZlcnJpZGVzIG9yIGFkZG9ucyB0byBvdmVycmlkZSBvciBleHRlbmQgZGVjYWYncyBkZWNvcmF0b3JzXCJcbiAgICAgICk7XG4gICAgaWYgKHRoaXMuZmxhdm91ciA9PT0gRGVmYXVsdEZsYXZvdXIgJiYgYWRkb24pXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEZWZhdWx0IGZsYXZvdXIgY2Fubm90IGJlIGV4dGVuZGVkXCIpO1xuXG4gICAgdGhpc1thZGRvbiA/IFwiZXh0cmFzXCIgOiBcImRlY29yYXRvcnNcIl0gPSBuZXcgU2V0KFtcbiAgICAgIC4uLih0aGlzW2FkZG9uID8gXCJleHRyYXNcIiA6IFwiZGVjb3JhdG9yc1wiXSB8fCBuZXcgU2V0KCkpLnZhbHVlcygpLFxuICAgICAgLi4uZGVjb3JhdG9ycyxcbiAgICBdKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIHRoZSBiYXNlIGRlY29yYXRvcnNcbiAgICogQHN1bW1hcnkgU2V0cyB0aGUgcHJpbWFyeSBkZWNvcmF0b3JzIGZvciB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqIEBwYXJhbSBkZWNvcmF0b3JzIERlY29yYXRvcnMgdG8gZGVmaW5lXG4gICAqIEByZXR1cm4gQnVpbGRlciBpbnN0YW5jZSBmb3IgZmluaXNoaW5nIHRoZSBjaGFpblxuICAgKi9cbiAgZGVmaW5lKFxuICAgIC4uLmRlY29yYXRvcnM6IChDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yKVtdXG4gICk6IERlY29yYXRpb25CdWlsZGVyRW5kICYgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCB7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdGUoZmFsc2UsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeHRlbmRzIGV4aXN0aW5nIGRlY29yYXRvcnNcbiAgICogQHN1bW1hcnkgQWRkcyBhZGRpdGlvbmFsIGRlY29yYXRvcnMgdG8gdGhlIGN1cnJlbnQgY29udGV4dFxuICAgKiBAcGFyYW0gZGVjb3JhdG9ycyBBZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJCdWlsZH0gQnVpbGRlciBpbnN0YW5jZSBmb3IgYnVpbGRpbmcgdGhlIGRlY29yYXRvclxuICAgKi9cbiAgZXh0ZW5kKFxuICAgIC4uLmRlY29yYXRvcnM6IChDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yKVtdXG4gICk6IERlY29yYXRpb25CdWlsZGVyQnVpbGQge1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKHRydWUsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGRlY29yYXRvckZhY3Rvcnkoa2V5OiBzdHJpbmcsIGY6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7XG4gICAgY29uc3QgY29udGV4dERlY29yYXRvciA9IGZ1bmN0aW9uIGNvbnRleHREZWNvcmF0b3IoXG4gICAgICB0YXJnZXQ6IG9iamVjdCxcbiAgICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgICAgZGVzY3JpcHRvcj86IFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPGFueT5cbiAgICApIHtcbiAgICAgIGNvbnN0IGZsYXZvdXIgPSBEZWNvcmF0aW9uLmZsYXZvdXJSZXNvbHZlcih0YXJnZXQpO1xuICAgICAgbGV0IGRlY29yYXRvcnM7XG4gICAgICBjb25zdCBleHRyYXMgPSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXVxuICAgICAgICA/IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmV4dHJhc1xuICAgICAgICA6IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW0RlZmF1bHRGbGF2b3VyXS5leHRyYXM7XG4gICAgICBpZiAoXG4gICAgICAgIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldICYmXG4gICAgICAgIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdICYmXG4gICAgICAgIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmRlY29yYXRvcnNcbiAgICAgICkge1xuICAgICAgICBkZWNvcmF0b3JzID0gRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtEZWZhdWx0Rmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRvQXBwbHkgPSBbXG4gICAgICAgIC4uLihkZWNvcmF0b3JzID8gZGVjb3JhdG9ycy52YWx1ZXMoKSA6IFtdKSxcbiAgICAgICAgLi4uKGV4dHJhcyA/IGV4dHJhcy52YWx1ZXMoKSA6IFtdKSxcbiAgICAgIF07XG4gICAgICB0b0FwcGx5LmZvckVhY2goKGQpID0+XG4gICAgICAgIChkIGFzIGFueSkodGFyZ2V0LCBwcm9wZXJ0eUtleSwgZGVzY3JpcHRvciwgZGVzY3JpcHRvcilcbiAgICAgICk7XG4gICAgfTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29udGV4dERlY29yYXRvciwgXCJuYW1lXCIsIHtcbiAgICAgIHZhbHVlOiBbZiwga2V5XS5qb2luKFwiX2RlY29yYXRvcl9mb3JfXCIpLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiBjb250ZXh0RGVjb3JhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIHRoZSBmaW5hbCBkZWNvcmF0b3IgZnVuY3Rpb25cbiAgICogQHN1bW1hcnkgQnVpbGRzIGFuZCByZXR1cm5zIHRoZSBkZWNvcmF0b3IgZmFjdG9yeSBmdW5jdGlvblxuICAgKiBAcmV0dXJuIHtmdW5jdGlvbihhbnksIGFueT8sIFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPyk6IGFueX0gVGhlIGdlbmVyYXRlZCBkZWNvcmF0b3IgZnVuY3Rpb25cbiAgICovXG4gIGFwcGx5KCk6IChcbiAgICB0YXJnZXQ6IGFueSxcbiAgICBwcm9wZXJ0eUtleT86IGFueSxcbiAgICBkZXNjcmlwdG9yPzogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8YW55PlxuICApID0+IGFueSB7XG4gICAgaWYgKCF0aGlzLmtleSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGtleSBwcm92aWRlZCBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclwiKTtcbiAgICBEZWNvcmF0aW9uLnJlZ2lzdGVyKHRoaXMua2V5LCB0aGlzLmZsYXZvdXIsIHRoaXMuZGVjb3JhdG9ycywgdGhpcy5leHRyYXMpO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRvckZhY3RvcnkodGhpcy5rZXksIHRoaXMuZmxhdm91cik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBkZWNvcmF0b3JzIGZvciBhIHNwZWNpZmljIGtleSBhbmQgZmxhdm91clxuICAgKiBAc3VtbWFyeSBJbnRlcm5hbCBtZXRob2QgdG8gc3RvcmUgZGVjb3JhdG9ycyBpbiB0aGUgc3RhdGljIHJlZ2lzdHJ5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgRGVjb3JhdG9yIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmxhdm91ciBEZWNvcmF0b3IgZmxhdm91clxuICAgKiBAcGFyYW0gW2RlY29yYXRvcnNdIFByaW1hcnkgZGVjb3JhdG9yc1xuICAgKiBAcGFyYW0gW2V4dHJhc10gQWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWdpc3RlcihcbiAgICBrZXk6IHN0cmluZyxcbiAgICBmbGF2b3VyOiBzdHJpbmcsXG4gICAgZGVjb3JhdG9ycz86IFNldDxDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yPixcbiAgICBleHRyYXM/OiBTZXQ8Q2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcj5cbiAgKSB7XG4gICAgaWYgKCFrZXkpIHRocm93IG5ldyBFcnJvcihcIk5vIGtleSBwcm92aWRlZCBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclwiKTtcbiAgICBpZiAoIWRlY29yYXRvcnMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkZWNvcmF0b3JzIHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZsYXZvdXIgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG5cbiAgICBpZiAoIURlY29yYXRpb24uZGVjb3JhdG9yc1trZXldKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSA9IHt9O1xuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0pXG4gICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSA9IHt9O1xuICAgIGlmIChkZWNvcmF0b3JzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICBpZiAoZXh0cmFzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXMgPSBleHRyYXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGdsb2JhbCBmbGF2b3VyIHJlc29sdmVyXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gZGV0ZXJtaW5lIGRlY29yYXRvciBmbGF2b3Vyc1xuICAgKiBAcGFyYW0ge0ZsYXZvdXJSZXNvbHZlcn0gcmVzb2x2ZXIgRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3Vyc1xuICAgKi9cbiAgc3RhdGljIHNldEZsYXZvdXJSZXNvbHZlcihyZXNvbHZlcjogRmxhdm91clJlc29sdmVyKSB7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIgPSByZXNvbHZlcjtcbiAgfVxuXG4gIHN0YXRpYyBmb3Ioa2V5OiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlck1pZCB7XG4gICAgcmV0dXJuIG5ldyBEZWNvcmF0aW9uKCkuZm9yKGtleSk7XG4gIH1cblxuICBzdGF0aWMgZmxhdm91cmVkQXMoZmxhdm91cjogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJTdGFydCB7XG4gICAgcmV0dXJuIG5ldyBEZWNvcmF0aW9uKGZsYXZvdXIpO1xuICB9XG59XG4iXX0=