UNPKG

ng-dynamic-component

Version:

> Dynamic components with full life-cycle support for inputs and outputs

211 lines 28.4 kB
import { Directive, ElementRef, EventEmitter, Inject, Injector, Input, Optional, Output, } from '@angular/core'; import { DynamicComponentInjectorToken, } from '../component-injector'; import { IoFactoryService } from '../io'; import { extractNgParamTypes, isOnDestroy } from '../util'; import * as i0 from "@angular/core"; import * as i1 from "../io"; import * as i2 from "../reflect"; /** * @public */ export function dynamicDirectiveDef(type, inputs, outputs) { return { type, inputs, outputs }; } /** * @public * @experimental Dynamic directives is an experimental API that may not work as expected. * * NOTE: There is a known issue with OnChanges hook not beign triggered on dynamic directives * since this part of functionality has been removed from the core as Angular now * supports this out of the box for dynamic components. */ export class DynamicDirectivesDirective { constructor(injector, iterableDiffers, ioFactoryService, reflectService, componentInjector) { this.injector = injector; this.iterableDiffers = iterableDiffers; this.ioFactoryService = ioFactoryService; this.reflectService = reflectService; this.componentInjector = componentInjector; this.ndcDynamicDirectivesCreated = new EventEmitter(); this.dirRef = new Map(); this.dirIo = new Map(); this.dirsDiffer = this.iterableDiffers .find([]) .create((_, def) => def.type); } get directives() { return (this.ndcDynamicDirectives || this.ngComponentOutletNdcDynamicDirectives); } get componentRef() { return this.componentInjector?.componentRef; } get compInstance() { return this.componentRef && this.componentRef.instance; } get isCompChanged() { if (this.lastCompInstance !== this.compInstance) { this.lastCompInstance = this.compInstance; return true; } return false; } get hostInjector() { return this.componentRef?.injector; } ngDoCheck() { if (this.maybeDestroyDirectives()) { return; } const dirsChanges = this.dirsDiffer.diff(this.directives); if (!dirsChanges) { return this.updateDirectives(); } this.processDirChanges(dirsChanges); } ngOnDestroy() { this.destroyAllDirectives(); } maybeDestroyDirectives() { if (this.isCompChanged || !this.componentRef) { this.dirsDiffer.diff([]); this.destroyAllDirectives(); } return !this.componentRef; } processDirChanges(changes) { changes.forEachRemovedItem(({ item }) => this.destroyDirective(item)); const createdDirs = []; changes.forEachAddedItem(({ item }) => { const dirRef = this.initDirective(item); if (dirRef) { createdDirs.push(dirRef); } }); if (createdDirs.length) { this.ndcDynamicDirectivesCreated.emit(createdDirs); } } updateDirectives() { this.directives?.forEach((dir) => this.updateDirective(dir)); } updateDirective(dirDef) { const io = this.dirIo.get(dirDef.type); io?.update(dirDef.inputs, dirDef.outputs); } initDirective(dirDef) { if (this.dirRef.has(dirDef.type)) { return; } const instance = this.createDirective(dirDef.type); const directiveRef = { instance, type: dirDef.type, injector: this.hostInjector, hostComponent: this.componentRef.instance, hostView: this.componentRef.hostView, location: this.componentRef.location, changeDetectorRef: this.componentRef.changeDetectorRef, onDestroy: this.componentRef.onDestroy, }; this.initDirIO(directiveRef, dirDef); this.callInitHooks(instance); this.dirRef.set(directiveRef.type, directiveRef); return directiveRef; } destroyAllDirectives() { this.dirRef.forEach((dir) => this.destroyDirRef(dir)); this.dirRef.clear(); this.dirIo.clear(); } destroyDirective(dirDef) { const dirRef = this.dirRef.get(dirDef.type); if (dirRef) { this.destroyDirRef(dirRef); } this.dirRef.delete(dirDef.type); this.dirIo.delete(dirDef.type); } initDirIO(dirRef, dirDef) { const io = this.ioFactoryService.create({ componentRef: this.dirToCompDef(dirRef) }, { trackOutputChanges: true, injector: this.injector }); io.update(dirDef.inputs, dirDef.outputs); this.dirIo.set(dirRef.type, io); } dirToCompDef(dirRef) { return { changeDetectorRef: this.componentRef.changeDetectorRef, hostView: this.componentRef.hostView, location: this.componentRef.location, destroy: this.componentRef.destroy, onDestroy: this.componentRef.onDestroy, injector: this.componentRef.injector, instance: dirRef.instance, componentType: dirRef.type, setInput: (name, value) => (dirRef.instance[name] = value), }; } destroyDirRef(dirRef) { this.dirIo.get(dirRef.type)?.ngOnDestroy(); if (isOnDestroy(dirRef.instance)) { dirRef.instance.ngOnDestroy(); } } createDirective(dirType) { const directiveInjector = Injector.create({ providers: [ { provide: dirType, useClass: dirType, deps: this.resolveDirParamTypes(dirType), }, { provide: ElementRef, useValue: this.componentRef.location }, ], parent: this.hostInjector, name: `DynamicDirectiveInjector:${dirType.name}@${this.componentRef.componentType.name}`, }); return directiveInjector.get(dirType); } resolveDirParamTypes(dirType) { return ( // First try Angular Compiler's metadata extractNgParamTypes(dirType) ?? // Then fallback to Reflect API this.reflectService.getCtorParamTypes(dirType) ?? // Bailout []); } callInitHooks(obj) { this.callHook(obj, 'ngOnInit'); this.callHook(obj, 'ngDoCheck'); this.callHook(obj, 'ngAfterContentInit'); this.callHook(obj, 'ngAfterContentChecked'); this.callHook(obj, 'ngAfterViewInit'); this.callHook(obj, 'ngAfterViewChecked'); } callHook(obj, hook, args = []) { if (obj[hook]) { obj[hook](...args); } } } /** @nocollapse */ DynamicDirectivesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesDirective, deps: [{ token: i0.Injector }, { token: i0.IterableDiffers }, { token: i1.IoFactoryService }, { token: i2.ReflectService }, { token: DynamicComponentInjectorToken, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); /** @nocollapse */ DynamicDirectivesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: DynamicDirectivesDirective, isStandalone: true, selector: "[ndcDynamicDirectives],[ngComponentOutletNdcDynamicDirectives]", inputs: { ndcDynamicDirectives: "ndcDynamicDirectives", ngComponentOutletNdcDynamicDirectives: "ngComponentOutletNdcDynamicDirectives" }, outputs: { ndcDynamicDirectivesCreated: "ndcDynamicDirectivesCreated" }, providers: [IoFactoryService], ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DynamicDirectivesDirective, decorators: [{ type: Directive, args: [{ selector: '[ndcDynamicDirectives],[ngComponentOutletNdcDynamicDirectives]', standalone: true, providers: [IoFactoryService], }] }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.IterableDiffers }, { type: i1.IoFactoryService }, { type: i2.ReflectService }, { type: undefined, decorators: [{ type: Inject, args: [DynamicComponentInjectorToken] }, { type: Optional }] }]; }, propDecorators: { ndcDynamicDirectives: [{ type: Input }], ngComponentOutletNdcDynamicDirectives: [{ type: Input }], ndcDynamicDirectivesCreated: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1kaXJlY3RpdmVzLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWR5bmFtaWMtY29tcG9uZW50L3NyYy9saWIvZHluYW1pYy1kaXJlY3RpdmVzL2R5bmFtaWMtZGlyZWN0aXZlcy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFNBQVMsRUFFVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUlMLFFBQVEsRUFDUixNQUFNLEdBR1AsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUVMLDZCQUE2QixHQUM5QixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFBYyxnQkFBZ0IsRUFBMEIsTUFBTSxPQUFPLENBQUM7QUFDN0UsT0FBTyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7OztBQVkzRDs7R0FFRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FDakMsSUFBYSxFQUNiLE1BQW1CLEVBQ25CLE9BQXFCO0lBRXJCLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBQ25DLENBQUM7QUFpQkQ7Ozs7Ozs7R0FPRztBQU1ILE1BQU0sT0FBTywwQkFBMEI7SUEyQ3JDLFlBQ1UsUUFBa0IsRUFDbEIsZUFBZ0MsRUFDaEMsZ0JBQWtDLEVBQ2xDLGNBQThCLEVBRzlCLGlCQUE0QztRQU41QyxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNoQyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ2xDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUc5QixzQkFBaUIsR0FBakIsaUJBQWlCLENBQTJCO1FBM0N0RCxnQ0FBMkIsR0FBRyxJQUFJLFlBQVksRUFBMkIsQ0FBQztRQThCbEUsV0FB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QUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxnRUFBZ0U7b0JBQzFFLFVBQVUsRUFBRSxJQUFJO29CQUNoQixTQUFTLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztpQkFDOUI7OzBCQWlESSxNQUFNOzJCQUFDLDZCQUE2Qjs7MEJBQ3BDLFFBQVE7NENBL0NYLG9CQUFvQjtzQkFEbkIsS0FBSztnQkFHTixxQ0FBcUM7c0JBRHBDLEtBQUs7Z0JBSU4sMkJBQTJCO3NCQUQxQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudFJlZixcbiAgRGlyZWN0aXZlLFxuICBEb0NoZWNrLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBJdGVyYWJsZUNoYW5nZXMsXG4gIEl0ZXJhYmxlRGlmZmVycyxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBUeXBlLFxuICBWaWV3UmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtcbiAgRHluYW1pY0NvbXBvbmVudEluamVjdG9yLFxuICBEeW5hbWljQ29tcG9uZW50SW5qZWN0b3JUb2tlbixcbn0gZnJvbSAnLi4vY29tcG9uZW50LWluamVjdG9yJztcbmltcG9ydCB7IElucHV0c1R5cGUsIElvRmFjdG9yeVNlcnZpY2UsIElvU2VydmljZSwgT3V0cHV0c1R5cGUgfSBmcm9tICcuLi9pbyc7XG5pbXBvcnQgeyBleHRyYWN0TmdQYXJhbVR5cGVzLCBpc09uRGVzdHJveSB9IGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHsgUmVmbGVjdFNlcnZpY2UgfSBmcm9tICcuLi9yZWZsZWN0JztcblxuLyoqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHluYW1pY0RpcmVjdGl2ZURlZjxUPiB7XG4gIHR5cGU6IFR5cGU8VD47XG4gIGlucHV0cz86IElucHV0c1R5cGU7XG4gIG91dHB1dHM/OiBPdXRwdXRzVHlwZTtcbn1cblxuLyoqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkeW5hbWljRGlyZWN0aXZlRGVmPFQ+KFxuICB0eXBlOiBUeXBlPFQ+LFxuICBpbnB1dHM/OiBJbnB1dHNUeXBlLFxuICBvdXRwdXRzPzogT3V0cHV0c1R5cGUsXG4pOiBEeW5hbWljRGlyZWN0aXZlRGVmPFQ+IHtcbiAgcmV0dXJuIHsgdHlwZSwgaW5wdXRzLCBvdXRwdXRzIH07XG59XG5cbi8qKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdGl2ZVJlZjxUPiB7XG4gIGluc3RhbmNlOiBUO1xuICB0eXBlOiBUeXBlPFQ+O1xuICBpbmplY3RvcjogSW5qZWN0b3I7XG4gIGhvc3RDb21wb25lbnQ6IHVua25vd247XG4gIGhvc3RWaWV3OiBWaWV3UmVmO1xuICBsb2NhdGlvbjogRWxlbWVudFJlZjtcbiAgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xuICBvbkRlc3Ryb3k6IChjYWxsYmFjazogRnVuY3Rpb24pID0+IHZvaWQ7XG59XG5cbi8qKlxuICogQHB1YmxpY1xuICogQGV4cGVyaW1lbnRhbCBEeW5hbWljIGRpcmVjdGl2ZXMgaXMgYW4gZXhwZXJpbWVudGFsIEFQSSB0aGF0IG1heSBub3Qgd29yayBhcyBleHBlY3RlZC5cbiAqXG4gKiBOT1RFOiBUaGVyZSBpcyBhIGtub3duIGlzc3VlIHdpdGggT25DaGFuZ2VzIGhvb2sgbm90IGJlaWduIHRyaWdnZXJlZCBvbiBkeW5hbWljIGRpcmVjdGl2ZXNcbiAqIHNpbmNlIHRoaXMgcGFydCBvZiBmdW5jdGlvbmFsaXR5IGhhcyBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgY29yZSBhcyBBbmd1bGFyIG5vd1xuICogc3VwcG9ydHMgdGhpcyBvdXQgb2YgdGhlIGJveCBmb3IgZHluYW1pYyBjb21wb25lbnRzLlxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbbmRjRHluYW1pY0RpcmVjdGl2ZXNdLFtuZ0NvbXBvbmVudE91dGxldE5kY0R5bmFtaWNEaXJlY3RpdmVzXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW0lvRmFjdG9yeVNlcnZpY2VdLFxufSlcbmV4cG9ydCBjbGFzcyBEeW5hbWljRGlyZWN0aXZlc0RpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uRGVzdHJveSwgRG9DaGVjayB7XG4gIEBJbnB1dCgpXG4gIG5kY0R5bmFtaWNEaXJlY3RpdmVzPzogRHluYW1pY0RpcmVjdGl2ZURlZjx1bmtub3duPltdIHwgbnVsbDtcbiAgQElucHV0KClcbiAgbmdDb21wb25lbnRPdXRsZXROZGNEeW5hbWljRGlyZWN0aXZlcz86IER5bmFtaWNEaXJlY3RpdmVEZWY8dW5rbm93bj5bXSB8IG51bGw7XG5cbiAgQE91dHB1dCgpXG4gIG5kY0R5bmFtaWNEaXJlY3RpdmVzQ3JlYXRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RGlyZWN0aXZlUmVmPHVua25vd24+W10+KCk7XG5cbiAgcHJpdmF0ZSBsYXN0Q29tcEluc3RhbmNlOiB1bmtub3duO1xuXG4gIHByaXZhdGUgZ2V0IGRpcmVjdGl2ZXMoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMubmRjRHluYW1pY0RpcmVjdGl2ZXMgfHwgdGhpcy5uZ0NvbXBvbmVudE91dGxldE5kY0R5bmFtaWNEaXJlY3RpdmVzXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGNvbXBvbmVudFJlZigpIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRJbmplY3Rvcj8uY29tcG9uZW50UmVmO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY29tcEluc3RhbmNlKCkge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudFJlZiAmJiB0aGlzLmNvbXBvbmVudFJlZi5pbnN0YW5jZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGlzQ29tcENoYW5nZWQoKSB7XG4gICAgaWYgKHRoaXMubGFzdENvbXBJbnN0YW5jZSAhPT0gdGhpcy5jb21wSW5zdGFuY2UpIHtcbiAgICAgIHRoaXMubGFzdENvbXBJbnN0YW5jZSA9IHRoaXMuY29tcEluc3RhbmNlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGhvc3RJbmplY3RvcigpIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRSZWY/LmluamVjdG9yO1xuICB9XG5cbiAgcHJpdmF0ZSBkaXJSZWYgPSBuZXcgTWFwPFR5cGU8dW5rbm93bj4sIERpcmVjdGl2ZVJlZjx1bmtub3duPj4oKTtcbiAgcHJpdmF0ZSBkaXJJbyA9IG5ldyBNYXA8VHlwZTx1bmtub3duPiwgSW9TZXJ2aWNlPigpO1xuICBwcml2YXRlIGRpcnNEaWZmZXIgPSB0aGlzLml0ZXJhYmxlRGlmZmVyc1xuICAgIC5maW5kKFtdKVxuICAgIC5jcmVhdGU8RHluYW1pY0RpcmVjdGl2ZURlZjx1bmtub3duPj4oKF8sIGRlZikgPT4gZGVmLnR5cGUpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgaXRlcmFibGVEaWZmZXJzOiBJdGVyYWJsZURpZmZlcnMsXG4gICAgcHJpdmF0ZSBpb0ZhY3RvcnlTZXJ2aWNlOiBJb0ZhY3RvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVmbGVjdFNlcnZpY2U6IFJlZmxlY3RTZXJ2aWNlLFxuICAgIEBJbmplY3QoRHluYW1pY0NvbXBvbmVudEluamVjdG9yVG9rZW4pXG4gICAgQE9wdGlvbmFsKClcbiAgICBwcml2YXRlIGNvbXBvbmVudEluamVjdG9yPzogRHluYW1pY0NvbXBvbmVudEluamVjdG9yLFxuICApIHt9XG5cbiAgbmdEb0NoZWNrKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1heWJlRGVzdHJveURpcmVjdGl2ZXMoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRpcnNDaGFuZ2VzID0gdGhpcy5kaXJzRGlmZmVyLmRpZmYodGhpcy5kaXJlY3RpdmVzKTtcblxuICAgIGlmICghZGlyc0NoYW5nZXMpIHtcbiAgICAgIHJldHVybiB0aGlzLnVwZGF0ZURpcmVjdGl2ZXMoKTtcbiAgICB9XG5cbiAgICB0aGlzLnByb2Nlc3NEaXJDaGFuZ2VzKGRpcnNDaGFuZ2VzKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveUFsbERpcmVjdGl2ZXMoKTtcbiAgfVxuXG4gIHByaXZhdGUgbWF5YmVEZXN0cm95RGlyZWN0aXZlcygpIHtcbiAgICBpZiAodGhpcy5pc0NvbXBDaGFuZ2VkIHx8ICF0aGlzLmNvbXBvbmVudFJlZikge1xuICAgICAgdGhpcy5kaXJzRGlmZmVyLmRpZmYoW10pO1xuICAgICAgdGhpcy5kZXN0cm95QWxsRGlyZWN0aXZlcygpO1xuICAgIH1cblxuICAgIHJldHVybiAhdGhpcy5jb21wb25lbnRSZWY7XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NEaXJDaGFuZ2VzKFxuICAgIGNoYW5nZXM6IEl0ZXJhYmxlQ2hhbmdlczxEeW5hbWljRGlyZWN0aXZlRGVmPHVua25vd24+PixcbiAgKSB7XG4gICAgY2hhbmdlcy5mb3JFYWNoUmVtb3ZlZEl0ZW0oKHsgaXRlbSB9KSA9PiB0aGlzLmRlc3Ryb3lEaXJlY3RpdmUoaXRlbSkpO1xuXG4gICAgY29uc3QgY3JlYXRlZERpcnM6IERpcmVjdGl2ZVJlZjx1bmtub3duPltdID0gW107XG4gICAgY2hhbmdlcy5mb3JFYWNoQWRkZWRJdGVtKCh7IGl0ZW0gfSkgPT4ge1xuICAgICAgY29uc3QgZGlyUmVmID0gdGhpcy5pbml0RGlyZWN0aXZlKGl0ZW0pO1xuXG4gICAgICBpZiAoZGlyUmVmKSB7XG4gICAgICAgIGNyZWF0ZWREaXJzLnB1c2goZGlyUmVmKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChjcmVhdGVkRGlycy5sZW5ndGgpIHtcbiAgICAgIHRoaXMubmRjRHluYW1pY0RpcmVjdGl2ZXNDcmVhdGVkLmVtaXQoY3JlYXRlZERpcnMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRGlyZWN0aXZlcygpIHtcbiAgICB0aGlzLmRpcmVjdGl2ZXM/LmZvckVhY2goKGRpcikgPT4gdGhpcy51cGRhdGVEaXJlY3RpdmUoZGlyKSk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZURpcmVjdGl2ZShkaXJEZWY6IER5bmFtaWNEaXJlY3RpdmVEZWY8dW5rbm93bj4pIHtcbiAgICBjb25zdCBpbyA9IHRoaXMuZGlySW8uZ2V0KGRpckRlZi50eXBlKTtcbiAgICBpbz8udXBkYXRlKGRpckRlZi5pbnB1dHMsIGRpckRlZi5vdXRwdXRzKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdERpcmVjdGl2ZShcbiAgICBkaXJEZWY6IER5bmFtaWNEaXJlY3RpdmVEZWY8dW5rbm93bj4sXG4gICk6IERpcmVjdGl2ZVJlZjx1bmtub3duPiB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuZGlyUmVmLmhhcyhkaXJEZWYudHlwZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXMuY3JlYXRlRGlyZWN0aXZlKGRpckRlZi50eXBlKTtcbiAgICBjb25zdCBkaXJlY3RpdmVSZWY6IERpcmVjdGl2ZVJlZjx1bmtub3duPiA9IHtcbiAgICAgIGluc3RhbmNlLFxuICAgICAgdHlwZTogZGlyRGVmLnR5cGUsXG4gICAgICBpbmplY3RvcjogdGhpcy5ob3N0SW5qZWN0b3IhLFxuICAgICAgaG9zdENvbXBvbmVudDogdGhpcy5jb21wb25lbnRSZWYhLmluc3RhbmNlLFxuICAgICAgaG9zdFZpZXc6IHRoaXMuY29tcG9uZW50UmVmIS5ob3N0VmlldyxcbiAgICAgIGxvY2F0aW9uOiB0aGlzLmNvbXBvbmVudFJlZiEubG9jYXRpb24sXG4gICAgICBjaGFuZ2VEZXRlY3RvclJlZjogdGhpcy5jb21wb25lbnRSZWYhLmNoYW5nZURldGVjdG9yUmVmLFxuICAgICAgb25EZXN0cm95OiB0aGlzLmNvbXBvbmVudFJlZiEub25EZXN0cm95LFxuICAgIH07XG5cbiAgICB0aGlzLmluaXREaXJJTyhkaXJlY3RpdmVSZWYsIGRpckRlZik7XG4gICAgdGhpcy5jYWxsSW5pdEhvb2tzKGluc3RhbmNlKTtcblxuICAgIHRoaXMuZGlyUmVmLnNldChkaXJlY3RpdmVSZWYudHlwZSwgZGlyZWN0aXZlUmVmKTtcblxuICAgIHJldHVybiBkaXJlY3RpdmVSZWY7XG4gIH1cblxuICBwcml2YXRlIGRlc3Ryb3lBbGxEaXJlY3RpdmVzKCkge1xuICAgIHRoaXMuZGlyUmVmLmZvckVhY2goKGRpcikgPT4gdGhpcy5kZXN0cm95RGlyUmVmKGRpcikpO1xuICAgIHRoaXMuZGlyUmVmLmNsZWFyKCk7XG4gICAgdGhpcy5kaXJJby5jbGVhcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBkZXN0cm95RGlyZWN0aXZlKGRpckRlZjogRHluYW1pY0RpcmVjdGl2ZURlZjx1bmtub3duPikge1xuICAgIGNvbnN0IGRpclJlZiA9IHRoaXMuZGlyUmVmLmdldChkaXJEZWYudHlwZSk7XG4gICAgaWYgKGRpclJlZikge1xuICAgICAgdGhpcy5kZXN0cm95RGlyUmVmKGRpclJlZik7XG4gICAgfVxuICAgIHRoaXMuZGlyUmVmLmRlbGV0ZShkaXJEZWYudHlwZSk7XG4gICAgdGhpcy5kaXJJby5kZWxldGUoZGlyRGVmLnR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0RGlySU8oXG4gICAgZGlyUmVmOiBEaXJlY3RpdmVSZWY8YW55PixcbiAgICBkaXJEZWY6IER5bmFtaWNEaXJlY3RpdmVEZWY8YW55PixcbiAgKSB7XG4gICAgY29uc3QgaW8gPSB0aGlzLmlvRmFjdG9yeVNlcnZpY2UuY3JlYXRlKFxuICAgICAgeyBjb21wb25lbnRSZWY6IHRoaXMuZGlyVG9Db21wRGVmKGRpclJlZikgfSxcbiAgICAgIHsgdHJhY2tPdXRwdXRDaGFuZ2VzOiB0cnVlLCBpbmplY3RvcjogdGhpcy5pbmplY3RvciB9LFxuICAgICk7XG4gICAgaW8udXBkYXRlKGRpckRlZi5pbnB1dHMsIGRpckRlZi5vdXRwdXRzKTtcbiAgICB0aGlzLmRpcklvLnNldChkaXJSZWYudHlwZSwgaW8pO1xuICB9XG5cbiAgcHJpdmF0ZSBkaXJUb0NvbXBEZWYoZGlyUmVmOiBEaXJlY3RpdmVSZWY8dW5rbm93bj4pOiBDb21wb25lbnRSZWY8dW5rbm93bj4ge1xuICAgIHJldHVybiB7XG4gICAgICBjaGFuZ2VEZXRlY3RvclJlZjogdGhpcy5jb21wb25lbnRSZWYhLmNoYW5nZURldGVjdG9yUmVmLFxuICAgICAgaG9zdFZpZXc6IHRoaXMuY29tcG9uZW50UmVmIS5ob3N0VmlldyxcbiAgICAgIGxvY2F0aW9uOiB0aGlzLmNvbXBvbmVudFJlZiEubG9jYXRpb24sXG4gICAgICBkZXN0cm95OiB0aGlzLmNvbXBvbmVudFJlZiEuZGVzdHJveSxcbiAgICAgIG9uRGVzdHJveTogdGhpcy5jb21wb25lbnRSZWYhLm9uRGVzdHJveSxcbiAgICAgIGluamVjdG9yOiB0aGlzLmNvbXBvbmVudFJlZiEuaW5qZWN0b3IsXG4gICAgICBpbnN0YW5jZTogZGlyUmVmLmluc3RhbmNlLFxuICAgICAgY29tcG9uZW50VHlwZTogZGlyUmVmLnR5cGUsXG4gICAgICBzZXRJbnB1dDogKG5hbWUsIHZhbHVlKSA9PiAoKGRpclJlZi5pbnN0YW5jZSBhcyBhbnkpW25hbWVdID0gdmFsdWUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGRlc3Ryb3lEaXJSZWYoZGlyUmVmOiBEaXJlY3RpdmVSZWY8dW5rbm93bj4pIHtcbiAgICB0aGlzLmRpcklvLmdldChkaXJSZWYudHlwZSk/Lm5nT25EZXN0cm95KCk7XG5cbiAgICBpZiAoaXNPbkRlc3Ryb3koZGlyUmVmLmluc3RhbmNlKSkge1xuICAgICAgZGlyUmVmLmluc3RhbmNlLm5nT25EZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVEaXJlY3RpdmU8VD4oZGlyVHlwZTogVHlwZTxUPik6IFQge1xuICAgIGNvbnN0IGRpcmVjdGl2ZUluamVjdG9yID0gSW5qZWN0b3IuY3JlYXRlKHtcbiAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogZGlyVHlwZSxcbiAgICAgICAgICB1c2VDbGFzczogZGlyVHlwZSxcbiAgICAgICAgICBkZXBzOiB0aGlzLnJlc29sdmVEaXJQYXJhbVR5cGVzKGRpclR5cGUpLFxuICAgICAgICB9LFxuICAgICAgICB7IHByb3ZpZGU6IEVsZW1lbnRSZWYsIHVzZVZhbHVlOiB0aGlzLmNvbXBvbmVudFJlZiEubG9jYXRpb24gfSxcbiAgICAgIF0sXG4gICAgICBwYXJlbnQ6IHRoaXMuaG9zdEluamVjdG9yLFxuICAgICAgbmFtZTogYER5bmFtaWNEaXJlY3RpdmVJbmplY3Rvcjoke2RpclR5cGUubmFtZX1AJHtcbiAgICAgICAgdGhpcy5jb21wb25lbnRSZWYhLmNvbXBvbmVudFR5cGUubmFtZVxuICAgICAgfWAsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gZGlyZWN0aXZlSW5qZWN0b3IuZ2V0KGRpclR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlRGlyUGFyYW1UeXBlcyhkaXJUeXBlOiBUeXBlPHVua25vd24+KTogdW5rbm93bltdIHtcbiAgICByZXR1cm4gKFxuICAgICAgLy8gRmlyc3QgdHJ5IEFuZ3VsYXIgQ29tcGlsZXIncyBtZXRhZGF0YVxuICAgICAgZXh0cmFjdE5nUGFyYW1UeXBlcyhkaXJUeXBlKSA/P1xuICAgICAgLy8gVGhlbiBmYWxsYmFjayB0byBSZWZsZWN0IEFQSVxuICAgICAgdGhpcy5yZWZsZWN0U2VydmljZS5nZXRDdG9yUGFyYW1UeXBlcyhkaXJUeXBlKSA/P1xuICAgICAgLy8gQmFpbG91dFxuICAgICAgW11cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjYWxsSW5pdEhvb2tzKG9iajogdW5rbm93bikge1xuICAgIHRoaXMuY2FsbEhvb2sob2JqLCAnbmdPbkluaXQnKTtcbiAgICB0aGlzLmNhbGxIb29rKG9iaiwgJ25nRG9DaGVjaycpO1xuICAgIHRoaXMuY2FsbEhvb2sob2JqLCAnbmdBZnRlckNvbnRlbnRJbml0Jyk7XG4gICAgdGhpcy5jYWxsSG9vayhvYmosICduZ0FmdGVyQ29udGVudENoZWNrZWQnKTtcbiAgICB0aGlzLmNhbGxIb29rKG9iaiwgJ25nQWZ0ZXJWaWV3SW5pdCcpO1xuICAgIHRoaXMuY2FsbEhvb2sob2JqLCAnbmdBZnRlclZpZXdDaGVja2VkJyk7XG4gIH1cblxuICBwcml2YXRlIGNhbGxIb29rKG9iajogYW55LCBob29rOiBzdHJpbmcsIGFyZ3M6IHVua25vd25bXSA9IFtdKSB7XG4gICAgaWYgKG9ialtob29rXSkge1xuICAgICAgb2JqW2hvb2tdKC4uLmFyZ3MpO1xuICAgIH1cbiAgfVxufVxuIl19