UNPKG

ng-dynamic-component

Version:

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

274 lines 34.7 kB
import { Inject, Injectable, Injector, Optional, } from '@angular/core'; import { merge, Subject } from 'rxjs'; import { takeUntil, tap } from 'rxjs/operators'; import { DynamicComponentInjectorToken, } from '../component-injector'; import { IoEventArgumentToken } from './event-argument'; import { IoEventContextProviderToken, IoEventContextToken, } from './event-context'; import * as i0 from "@angular/core"; import * as i1 from "../component-io"; /** * @public */ export class IoServiceOptions { constructor() { this.trackOutputChanges = false; } } /** @nocollapse */ IoServiceOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ IoServiceOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoServiceOptions, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * @public */ export class IoService { constructor(injector, differs, // TODO: Replace ComponentFactoryResolver once new API is created // @see https://github.com/angular/angular/issues/44926 // eslint-disable-next-line deprecation/deprecation cfr, options, compInjector, eventArgument, cdr, eventContextProvider, componentIO) { this.injector = injector; this.differs = differs; this.cfr = cfr; this.options = options; this.compInjector = compInjector; this.eventArgument = eventArgument; this.cdr = cdr; this.eventContextProvider = eventContextProvider; this.componentIO = componentIO; this.lastChangedInputs = new Set(); this.inputsDiffer = this.differs.find({}).create(); this.outputsShouldDisconnect$ = new Subject(); this.inputs = {}; this.outputs = {}; if (this.options.trackOutputChanges) { const outputsDiffer = this.differs.find({}).create(); this.outputsChanged = (outputs) => !!outputsDiffer.diff(outputs); } } get compRef() { return this.compInjector.componentRef; } get componentInst() { return this.compRef?.instance; } ngOnDestroy() { this.disconnectOutputs(); } /** * Call update whenever inputs/outputs may or did change. * * It will detect both new and mutated changes. */ update(inputs, outputs) { if (!this.compRef) { this.disconnectOutputs(); return; } const changes = this.updateIO(inputs, outputs); const compChanged = this.isComponentInstChanged(); const inputsChanges = this.getInputsChanges(compChanged); const outputsChanged = this.outputsChanged(this.outputs); if (inputsChanges) { this.updateChangedInputs(inputsChanges); } if (compChanged || inputsChanges) { this.updateInputs(compChanged || !this.lastChangedInputs.size); } if (compChanged || outputsChanged || changes.outputsChanged) { this.bindOutputs(); } } outputsChanged(outputs) { return false; } isComponentInstChanged() { if (this.lastComponentInst !== this.componentInst) { this.lastComponentInst = this.componentInst; return true; } else { return false; } } updateIO(inputs, outputs) { if (!inputs) { inputs = {}; } if (!outputs) { outputs = {}; } const inputsChanged = this.inputs !== inputs; const outputsChanged = this.outputs !== outputs; this.inputs = inputs; this.outputs = outputs; return { inputsChanged, outputsChanged }; } updateInputs(isFirstChange = false) { if (isFirstChange) { this.updateCompFactory(); } const compRef = this.compRef; const inputs = this.inputs; if (!inputs || !compRef) { return; } const ifInputChanged = this.lastChangedInputs.size ? (name) => this.lastChangedInputs.has(name) : () => true; const componentIO = this.componentIO; for (const name of Object.keys(inputs)) { if (ifInputChanged(name)) { componentIO.setInput(compRef, name, inputs[name]); } } } bindOutputs() { this.disconnectOutputs(); const compRef = this.compRef; const outputs = this.outputs; if (!outputs || !compRef) { return; } const resolvedOutputs = this.resolveOutputs(outputs); const componentIO = this.componentIO; merge(...Object.keys(resolvedOutputs).map((name) => componentIO .getOutput(compRef, name) .pipe(tap((event) => resolvedOutputs[name](event))))) .pipe(takeUntil(this.outputsShouldDisconnect$)) .subscribe(() => this.cdr.markForCheck()); } disconnectOutputs() { this.outputsShouldDisconnect$.next(); } getInputsChanges(isCompChanged) { if (isCompChanged) { this.inputsDiffer.diff({}); } return this.inputsDiffer.diff(this.inputs); } updateChangedInputs(differ) { this.lastChangedInputs.clear(); const addRecordKeyToSet = (record) => this.lastChangedInputs.add(record.key); differ.forEachAddedItem(addRecordKeyToSet); differ.forEachChangedItem(addRecordKeyToSet); differ.forEachRemovedItem(addRecordKeyToSet); } // TODO: Replace ComponentFactory once new API is created // @see https://github.com/angular/angular/issues/44926 // eslint-disable-next-line deprecation/deprecation resolveCompFactory() { if (!this.compRef) { return; } try { try { return this.cfr.resolveComponentFactory(this.compRef.componentType); } catch (e) { // Fallback if componentType does not exist (happens on NgComponentOutlet) return this.cfr.resolveComponentFactory(this.compRef.instance.constructor); } } catch (e) { // Factory not available - bailout return; } } updateCompFactory() { this.compFactory = this.resolveCompFactory(); } resolveOutputs(outputs) { this.updateOutputsEventContext(); const processedOutputs = this.processOutputs(outputs); if (!this.compFactory) { return processedOutputs; } return this.remapIO(processedOutputs, this.compFactory.outputs); } updateOutputsEventContext() { if (this.eventContextProvider) { // Resolve custom context from local provider const eventContextInjector = Injector.create({ name: 'EventContext', parent: this.injector, providers: [this.eventContextProvider], }); this.outputsEventContext = eventContextInjector.get(IoEventContextToken); } else { // Try to get global context this.outputsEventContext = this.injector.get(IoEventContextToken, null); } } processOutputs(outputs) { const processedOutputs = {}; Object.keys(outputs).forEach((key) => { const outputExpr = outputs[key]; let outputHandler; if (typeof outputExpr === 'function') { outputHandler = outputExpr; } else { outputHandler = outputExpr && this.processOutputArgs(outputExpr); } if (this.outputsEventContext && outputHandler) { outputHandler = outputHandler.bind(this.outputsEventContext); } processedOutputs[key] = outputHandler; }); return processedOutputs; } processOutputArgs(output) { const eventArgument = this.eventArgument; const args = 'args' in output ? output.args || [] : [eventArgument]; const eventIdx = args.indexOf(eventArgument); const handler = output.handler; // When there is no event argument - use just arguments if (eventIdx === -1) { return function () { return handler.apply(this, args); }; } return function (event) { const argsWithEvent = [...args]; argsWithEvent[eventIdx] = event; return handler.apply(this, argsWithEvent); }; } remapIO(io, mapping) { const newIO = {}; Object.keys(io).forEach((key) => { const newKey = this.findPropByTplInMapping(key, mapping) || key; newIO[newKey] = io[key]; }); return newIO; } findPropByTplInMapping(tplName, mapping) { for (const map of mapping) { if (map.templateName === tplName) { return map.propName; } } return null; } } /** @nocollapse */ IoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService, deps: [{ token: i0.Injector }, { token: i0.KeyValueDiffers }, { token: i0.ComponentFactoryResolver }, { token: IoServiceOptions }, { token: DynamicComponentInjectorToken }, { token: IoEventArgumentToken }, { token: i0.ChangeDetectorRef }, { token: IoEventContextProviderToken, optional: true }, { token: i1.ComponentIO }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ IoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: IoService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.KeyValueDiffers }, { type: i0.ComponentFactoryResolver }, { type: IoServiceOptions }, { type: undefined, decorators: [{ type: Inject, args: [DynamicComponentInjectorToken] }] }, { type: undefined, decorators: [{ type: Inject, args: [IoEventArgumentToken] }] }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{ type: Inject, args: [IoEventContextProviderToken] }, { type: Optional }] }, { type: i1.ComponentIO }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW8uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWR5bmFtaWMtY29tcG9uZW50L3NyYy9saWIvaW8vaW8uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBS0wsTUFBTSxFQUNOLFVBQVUsRUFDVixRQUFRLEVBS1IsUUFBUSxHQUdULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEQsT0FBTyxFQUVMLDZCQUE2QixHQUM5QixNQUFNLHVCQUF1QixDQUFDO0FBRS9CLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3hELE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IsbUJBQW1CLEdBQ3BCLE1BQU0saUJBQWlCLENBQUM7OztBQWtCekI7O0dBRUc7QUFFSCxNQUFNLE9BQU8sZ0JBQWdCO0lBRDdCO1FBRUUsdUJBQWtCLEdBQUcsS0FBSyxDQUFDO0tBQzVCOztnSUFGWSxnQkFBZ0I7b0lBQWhCLGdCQUFnQixjQURILE1BQU07MkZBQ25CLGdCQUFnQjtrQkFENUIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7O0FBS2xDOztHQUVHO0FBRUgsTUFBTSxPQUFPLFNBQVM7SUFzQnBCLFlBQ21CLFFBQWtCLEVBQ2xCLE9BQXdCO0lBQ3pDLGlFQUFpRTtJQUNqRSx1REFBdUQ7SUFDdkQsbURBQW1EO0lBQ2xDLEdBQTZCLEVBQzdCLE9BQXlCLEVBRXpCLFlBQXNDLEVBRXRDLGFBQXFCLEVBQ3JCLEdBQXNCLEVBR3RCLG9CQUFvQyxFQUNwQyxXQUF3QjtRQWZ4QixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLFlBQU8sR0FBUCxPQUFPLENBQWlCO1FBSXhC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QUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUM5QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQztZQUNoRSxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxLQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVPLHNCQUFzQixDQUFDLE9BQWUsRUFBRSxPQUFzQjtRQUNwRSxLQUFLLE1BQU0sR0FBRyxJQUFJLE9BQU8sRUFBRTtZQUN6QixJQUFJLEdBQUcsQ0FBQyxZQUFZLEtBQUssT0FBTyxFQUFFO2dCQUNoQyxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUM7YUFDckI7U0FDRjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQzs7eUhBL1NVLFNBQVMsaUhBNkJRLGdCQUFnQixhQUNsQyw2QkFBNkIsYUFFN0Isb0JBQW9CLDhDQUdwQiwyQkFBMkI7NkhBbkMxQixTQUFTOzJGQUFULFNBQVM7a0JBRHJCLFVBQVU7c0pBOEJtQixnQkFBZ0I7MEJBQ3pDLE1BQU07MkJBQUMsNkJBQTZCOzswQkFFcEMsTUFBTTsyQkFBQyxvQkFBb0I7OzBCQUczQixNQUFNOzJCQUFDLDJCQUEyQjs7MEJBQ2xDLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50RmFjdG9yeSxcbiAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICBDb21wb25lbnRSZWYsXG4gIEluamVjdCxcbiAgSW5qZWN0YWJsZSxcbiAgSW5qZWN0b3IsXG4gIEtleVZhbHVlQ2hhbmdlUmVjb3JkLFxuICBLZXlWYWx1ZUNoYW5nZXMsXG4gIEtleVZhbHVlRGlmZmVycyxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgU3RhdGljUHJvdmlkZXIsXG4gIFR5cGUsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgbWVyZ2UsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge1xuICBEeW5hbWljQ29tcG9uZW50SW5qZWN0b3IsXG4gIER5bmFtaWNDb21wb25lbnRJbmplY3RvclRva2VuLFxufSBmcm9tICcuLi9jb21wb25lbnQtaW5qZWN0b3InO1xuaW1wb3J0IHsgQ29tcG9uZW50SU8gfSBmcm9tICcuLi9jb21wb25lbnQtaW8nO1xuaW1wb3J0IHsgSW9FdmVudEFyZ3VtZW50VG9rZW4gfSBmcm9tICcuL2V2ZW50LWFyZ3VtZW50JztcbmltcG9ydCB7XG4gIElvRXZlbnRDb250ZXh0UHJvdmlkZXJUb2tlbixcbiAgSW9FdmVudENvbnRleHRUb2tlbixcbn0gZnJvbSAnLi9ldmVudC1jb250ZXh0JztcbmltcG9ydCB7IEV2ZW50SGFuZGxlciwgSW5wdXRzVHlwZSwgT3V0cHV0c1R5cGUsIE91dHB1dFdpdGhBcmdzIH0gZnJvbSAnLi90eXBlcyc7XG5cbmludGVyZmFjZSBJT01hcEluZm8ge1xuICBwcm9wTmFtZTogc3RyaW5nO1xuICB0ZW1wbGF0ZU5hbWU6IHN0cmluZztcbn1cblxudHlwZSBJT01hcHBpbmdMaXN0ID0gSU9NYXBJbmZvW107XG5cbnR5cGUgS2V5VmFsdWVDaGFuZ2VzQW55ID0gS2V5VmFsdWVDaGFuZ2VzPHN0cmluZywgdW5rbm93bj47XG5cbmludGVyZmFjZSBPdXRwdXRzVHlwZVByb2Nlc3NlZCBleHRlbmRzIE91dHB1dHNUeXBlIHtcbiAgW2s6IHN0cmluZ106IEV2ZW50SGFuZGxlcjtcbn1cblxuaW50ZXJmYWNlIEFueUNvbXBvbmVudCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHt9XG5cbi8qKlxuICogQHB1YmxpY1xuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIElvU2VydmljZU9wdGlvbnMge1xuICB0cmFja091dHB1dENoYW5nZXMgPSBmYWxzZTtcbn1cblxuLyoqXG4gKiBAcHVibGljXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJb1NlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIGxhc3RDb21wb25lbnRJbnN0OiB1bmtub3duO1xuICBwcml2YXRlIGxhc3RDaGFuZ2VkSW5wdXRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIHByaXZhdGUgaW5wdXRzRGlmZmVyID0gdGhpcy5kaWZmZXJzLmZpbmQoe30pLmNyZWF0ZSgpO1xuICAvLyBUT0RPOiBSZXBsYWNlIENvbXBvbmVudEZhY3Rvcnkgb25jZSBuZXcgQVBJIGlzIGNyZWF0ZWRcbiAgLy8gQHNlZSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy80NDkyNlxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb25cbiAgcHJpdmF0ZSBjb21wRmFjdG9yeT86IENvbXBvbmVudEZhY3Rvcnk8QW55Q29tcG9uZW50PjtcbiAgcHJpdmF0ZSBvdXRwdXRzU2hvdWxkRGlzY29ubmVjdCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBwcml2YXRlIG91dHB1dHNFdmVudENvbnRleHQ6IHVua25vd247XG5cbiAgcHJpdmF0ZSBpbnB1dHM6IElucHV0c1R5cGUgPSB7fTtcbiAgcHJpdmF0ZSBvdXRwdXRzOiBPdXRwdXRzVHlwZSA9IHt9O1xuXG4gIHByaXZhdGUgZ2V0IGNvbXBSZWYoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29tcEluamVjdG9yLmNvbXBvbmVudFJlZiBhcyBDb21wb25lbnRSZWY8QW55Q29tcG9uZW50PiB8IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGdldCBjb21wb25lbnRJbnN0KCkge1xuICAgIHJldHVybiB0aGlzLmNvbXBSZWY/Lmluc3RhbmNlO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSByZWFkb25seSBkaWZmZXJzOiBLZXlWYWx1ZURpZmZlcnMsXG4gICAgLy8gVE9ETzogUmVwbGFjZSBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIgb25jZSBuZXcgQVBJIGlzIGNyZWF0ZWRcbiAgICAvLyBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzQ0OTI2XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uXG4gICAgcHJpdmF0ZSByZWFkb25seSBjZnI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IElvU2VydmljZU9wdGlvbnMsXG4gICAgQEluamVjdChEeW5hbWljQ29tcG9uZW50SW5qZWN0b3JUb2tlbilcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbXBJbmplY3RvcjogRHluYW1pY0NvbXBvbmVudEluamVjdG9yLFxuICAgIEBJbmplY3QoSW9FdmVudEFyZ3VtZW50VG9rZW4pXG4gICAgcHJpdmF0ZSByZWFkb25seSBldmVudEFyZ3VtZW50OiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIEBJbmplY3QoSW9FdmVudENvbnRleHRQcm92aWRlclRva2VuKVxuICAgIEBPcHRpb25hbCgpXG4gICAgcHJpdmF0ZSByZWFkb25seSBldmVudENvbnRleHRQcm92aWRlcjogU3RhdGljUHJvdmlkZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb21wb25lbnRJTzogQ29tcG9uZW50SU8sXG4gICkge1xuICAgIGlmICh0aGlzLm9wdGlvbnMudHJhY2tPdXRwdXRDaGFuZ2VzKSB7XG4gICAgICBjb25zdCBvdXRwdXRzRGlmZmVyID0gdGhpcy5kaWZmZXJzLmZpbmQoe30pLmNyZWF0ZSgpO1xuICAgICAgdGhpcy5vdXRwdXRzQ2hhbmdlZCA9IChvdXRwdXRzKSA9PiAhIW91dHB1dHNEaWZmZXIuZGlmZihvdXRwdXRzKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2Nvbm5lY3RPdXRwdXRzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbCB1cGRhdGUgd2hlbmV2ZXIgaW5wdXRzL291dHB1dHMgbWF5IG9yIGRpZCBjaGFuZ2UuXG4gICAqXG4gICAqIEl0IHdpbGwgZGV0ZWN0IGJvdGggbmV3IGFuZCBtdXRhdGVkIGNoYW5nZXMuXG4gICAqL1xuICB1cGRhdGUoaW5wdXRzPzogSW5wdXRzVHlwZSB8IG51bGwsIG91dHB1dHM/OiBPdXRwdXRzVHlwZSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29tcFJlZikge1xuICAgICAgdGhpcy5kaXNjb25uZWN0T3V0cHV0cygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLnVwZGF0ZUlPKGlucHV0cywgb3V0cHV0cyk7XG5cbiAgICBjb25zdCBjb21wQ2hhbmdlZCA9IHRoaXMuaXNDb21wb25lbnRJbnN0Q2hhbmdlZCgpO1xuXG4gICAgY29uc3QgaW5wdXRzQ2hhbmdlcyA9IHRoaXMuZ2V0SW5wdXRzQ2hhbmdlcyhjb21wQ2hhbmdlZCk7XG4gICAgY29uc3Qgb3V0cHV0c0NoYW5nZWQgPSB0aGlzLm91dHB1dHNDaGFuZ2VkKHRoaXMub3V0cHV0cyk7XG5cbiAgICBpZiAoaW5wdXRzQ2hhbmdlcykge1xuICAgICAgdGhpcy51cGRhdGVDaGFuZ2VkSW5wdXRzKGlucHV0c0NoYW5nZXMpO1xuICAgIH1cblxuICAgIGlmIChjb21wQ2hhbmdlZCB8fCBpbnB1dHNDaGFuZ2VzKSB7XG4gICAgICB0aGlzLnVwZGF0ZUlucHV0cyhjb21wQ2hhbmdlZCB8fCAhdGhpcy5sYXN0Q2hhbmdlZElucHV0cy5zaXplKTtcbiAgICB9XG5cbiAgICBpZiAoY29tcENoYW5nZWQgfHwgb3V0cHV0c0NoYW5nZWQgfHwgY2hhbmdlcy5vdXRwdXRzQ2hhbmdlZCkge1xuICAgICAgdGhpcy5iaW5kT3V0cHV0cygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgb3V0cHV0c0NoYW5nZWQob3V0cHV0czogT3V0cHV0c1R5cGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzQ29tcG9uZW50SW5zdENoYW5nZWQoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMubGFzdENvbXBvbmVudEluc3QgIT09IHRoaXMuY29tcG9uZW50SW5zdCkge1xuICAgICAgdGhpcy5sYXN0Q29tcG9uZW50SW5zdCA9IHRoaXMuY29tcG9uZW50SW5zdDtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVJTyhpbnB1dHM/OiBJbnB1dHNUeXBlIHwgbnVsbCwgb3V0cHV0cz86IE91dHB1dHNUeXBlIHwgbnVsbCkge1xuICAgIGlmICghaW5wdXRzKSB7XG4gICAgICBpbnB1dHMgPSB7fTtcbiAgICB9XG4gICAgaWYgKCFvdXRwdXRzKSB7XG4gICAgICBvdXRwdXRzID0ge307XG4gICAgfVxuXG4gICAgY29uc3QgaW5wdXRzQ2hhbmdlZCA9IHRoaXMuaW5wdXRzICE9PSBpbnB1dHM7XG4gICAgY29uc3Qgb3V0cHV0c0NoYW5nZWQgPSB0aGlzLm91dHB1dHMgIT09IG91dHB1dHM7XG5cbiAgICB0aGlzLmlucHV0cyA9IGlucHV0cztcbiAgICB0aGlzLm91dHB1dHMgPSBvdXRwdXRzO1xuXG4gICAgcmV0dXJuIHsgaW5wdXRzQ2hhbmdlZCwgb3V0cHV0c0NoYW5nZWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlSW5wdXRzKGlzRmlyc3RDaGFuZ2UgPSBmYWxzZSkge1xuICAgIGlmIChpc0ZpcnN0Q2hhbmdlKSB7XG4gICAgICB0aGlzLnVwZGF0ZUNvbXBGYWN0b3J5KCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29tcFJlZiA9IHRoaXMuY29tcFJlZjtcbiAgICBjb25zdCBpbnB1dHMgPSB0aGlzLmlucHV0cztcblxuICAgIGlmICghaW5wdXRzIHx8ICFjb21wUmVmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaWZJbnB1dENoYW5nZWQgPSB0aGlzLmxhc3RDaGFuZ2VkSW5wdXRzLnNpemVcbiAgICAgID8gKG5hbWU6IHN0cmluZykgPT4gdGhpcy5sYXN0Q2hhbmdlZElucHV0cy5oYXMobmFtZSlcbiAgICAgIDogKCkgPT4gdHJ1ZTtcblxuICAgIGNvbnN0IGNvbXBvbmVudElPID0gdGhpcy5jb21wb25lbnRJTztcblxuICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhpbnB1dHMpKSB7XG4gICAgICBpZiAoaWZJbnB1dENoYW5nZWQobmFtZSkpIHtcbiAgICAgICAgY29tcG9uZW50SU8uc2V0SW5wdXQoY29tcFJlZiwgbmFtZSwgaW5wdXRzW25hbWVdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGJpbmRPdXRwdXRzKCkge1xuICAgIHRoaXMuZGlzY29ubmVjdE91dHB1dHMoKTtcblxuICAgIGNvbnN0IGNvbXBSZWYgPSB0aGlzLmNvbXBSZWY7XG4gICAgY29uc3Qgb3V0cHV0cyA9IHRoaXMub3V0cHV0cztcblxuICAgIGlmICghb3V0cHV0cyB8fCAhY29tcFJlZikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc29sdmVkT3V0cHV0cyA9IHRoaXMucmVzb2x2ZU91dHB1dHMob3V0cHV0cyk7XG4gICAgY29uc3QgY29tcG9uZW50SU8gPSB0aGlzLmNvbXBvbmVudElPO1xuXG4gICAgbWVyZ2UoXG4gICAgICAuLi5PYmplY3Qua2V5cyhyZXNvbHZlZE91dHB1dHMpLm1hcCgobmFtZSkgPT5cbiAgICAgICAgY29tcG9uZW50SU9cbiAgICAgICAgICAuZ2V0T3V0cHV0KGNvbXBSZWYsIG5hbWUpXG4gICAgICAgICAgLnBpcGUodGFwKChldmVudCkgPT4gcmVzb2x2ZWRPdXRwdXRzW25hbWVdKGV2ZW50KSkpLFxuICAgICAgKSxcbiAgICApXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5vdXRwdXRzU2hvdWxkRGlzY29ubmVjdCQpKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKSk7XG4gIH1cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RPdXRwdXRzKCkge1xuICAgIHRoaXMub3V0cHV0c1Nob3VsZERpc2Nvbm5lY3QkLm5leHQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SW5wdXRzQ2hhbmdlcyhpc0NvbXBDaGFuZ2VkOiBib29sZWFuKSB7XG4gICAgaWYgKGlzQ29tcENoYW5nZWQpIHtcbiAgICAgIHRoaXMuaW5wdXRzRGlmZmVyLmRpZmYoe30pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlucHV0c0RpZmZlci5kaWZmKHRoaXMuaW5wdXRzKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlQ2hhbmdlZElucHV0cyhkaWZmZXI6IEtleVZhbHVlQ2hhbmdlc0FueSkge1xuICAgIHRoaXMubGFzdENoYW5nZWRJbnB1dHMuY2xlYXIoKTtcblxuICAgIGNvbnN0IGFkZFJlY29yZEtleVRvU2V0ID0gKHJlY29yZDogS2V5VmFsdWVDaGFuZ2VSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT5cbiAgICAgIHRoaXMubGFzdENoYW5nZWRJbnB1dHMuYWRkKHJlY29yZC5rZXkpO1xuXG4gICAgZGlmZmVyLmZvckVhY2hBZGRlZEl0ZW0oYWRkUmVjb3JkS2V5VG9TZXQpO1xuICAgIGRpZmZlci5mb3JFYWNoQ2hhbmdlZEl0ZW0oYWRkUmVjb3JkS2V5VG9TZXQpO1xuICAgIGRpZmZlci5mb3JFYWNoUmVtb3ZlZEl0ZW0oYWRkUmVjb3JkS2V5VG9TZXQpO1xuICB9XG5cbiAgLy8gVE9ETzogUmVwbGFjZSBDb21wb25lbnRGYWN0b3J5IG9uY2UgbmV3IEFQSSBpcyBjcmVhdGVkXG4gIC8vIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci9pc3N1ZXMvNDQ5MjZcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uXG4gIHByaXZhdGUgcmVzb2x2ZUNvbXBGYWN0b3J5KCkge1xuICAgIGlmICghdGhpcy5jb21wUmVmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNmci5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeSh0aGlzLmNvbXBSZWYuY29tcG9uZW50VHlwZSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEZhbGxiYWNrIGlmIGNvbXBvbmVudFR5cGUgZG9lcyBub3QgZXhpc3QgKGhhcHBlbnMgb24gTmdDb21wb25lbnRPdXRsZXQpXG4gICAgICAgIHJldHVybiB0aGlzLmNmci5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeShcbiAgICAgICAgICAodGhpcy5jb21wUmVmLmluc3RhbmNlIGFzIGFueSkuY29uc3RydWN0b3IgYXMgVHlwZTxBbnlDb21wb25lbnQ+LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIEZhY3Rvcnkgbm90IGF2YWlsYWJsZSAtIGJhaWxvdXRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUNvbXBGYWN0b3J5KCkge1xuICAgIHRoaXMuY29tcEZhY3RvcnkgPSB0aGlzLnJlc29sdmVDb21wRmFjdG9yeSgpO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlT3V0cHV0cyhvdXRwdXRzOiBPdXRwdXRzVHlwZSkge1xuICAgIHRoaXMudXBkYXRlT3V0cHV0c0V2ZW50Q29udGV4dCgpO1xuXG4gICAgY29uc3QgcHJvY2Vzc2VkT3V0cHV0cyA9IHRoaXMucHJvY2Vzc091dHB1dHMob3V0cHV0cyk7XG5cbiAgICBpZiAoIXRoaXMuY29tcEZhY3RvcnkpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzZWRPdXRwdXRzO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlbWFwSU8ocHJvY2Vzc2VkT3V0cHV0cywgdGhpcy5jb21wRmFjdG9yeS5vdXRwdXRzKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlT3V0cHV0c0V2ZW50Q29udGV4dCgpIHtcbiAgICBpZiAodGhpcy5ldmVudENvbnRleHRQcm92aWRlcikge1xuICAgICAgLy8gUmVzb2x2ZSBjdXN0b20gY29udGV4dCBmcm9tIGxvY2FsIHByb3ZpZGVyXG4gICAgICBjb25zdCBldmVudENvbnRleHRJbmplY3RvciA9IEluamVjdG9yLmNyZWF0ZSh7XG4gICAgICAgIG5hbWU6ICdFdmVudENvbnRleHQnLFxuICAgICAgICBwYXJlbnQ6IHRoaXMuaW5qZWN0b3IsXG4gICAgICAgIHByb3ZpZGVyczogW3RoaXMuZXZlbnRDb250ZXh0UHJvdmlkZXJdLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMub3V0cHV0c0V2ZW50Q29udGV4dCA9IGV2ZW50Q29udGV4dEluamVjdG9yLmdldChJb0V2ZW50Q29udGV4dFRva2VuKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVHJ5IHRvIGdldCBnbG9iYWwgY29udGV4dFxuICAgICAgdGhpcy5vdXRwdXRzRXZlbnRDb250ZXh0ID0gdGhpcy5pbmplY3Rvci5nZXQoSW9FdmVudENvbnRleHRUb2tlbiwgbnVsbCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzT3V0cHV0cyhvdXRwdXRzOiBPdXRwdXRzVHlwZSkge1xuICAgIGNvbnN0IHByb2Nlc3NlZE91dHB1dHM6IE91dHB1dHNUeXBlUHJvY2Vzc2VkID0ge307XG5cbiAgICBPYmplY3Qua2V5cyhvdXRwdXRzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dEV4cHIgPSBvdXRwdXRzW2tleV0hO1xuICAgICAgbGV0IG91dHB1dEhhbmRsZXI6IEV2ZW50SGFuZGxlcjx1bmtub3duPjtcblxuICAgICAgaWYgKHR5cGVvZiBvdXRwdXRFeHByID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIG91dHB1dEhhbmRsZXIgPSBvdXRwdXRFeHByO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0SGFuZGxlciA9IG91dHB1dEV4cHIgJiYgdGhpcy5wcm9jZXNzT3V0cHV0QXJncyhvdXRwdXRFeHByKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMub3V0cHV0c0V2ZW50Q29udGV4dCAmJiBvdXRwdXRIYW5kbGVyKSB7XG4gICAgICAgIG91dHB1dEhhbmRsZXIgPSBvdXRwdXRIYW5kbGVyLmJpbmQodGhpcy5vdXRwdXRzRXZlbnRDb250ZXh0KTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkT3V0cHV0c1trZXldID0gb3V0cHV0SGFuZGxlcjtcbiAgICB9KTtcblxuICAgIHJldHVybiBwcm9jZXNzZWRPdXRwdXRzO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzT3V0cHV0QXJncyhvdXRwdXQ6IE91dHB1dFdpdGhBcmdzKTogRXZlbnRIYW5kbGVyIHtcbiAgICBjb25zdCBldmVudEFyZ3VtZW50ID0gdGhpcy5ldmVudEFyZ3VtZW50O1xuICAgIGNvbnN0IGFyZ3MgPSAnYXJncycgaW4gb3V0cHV0ID8gb3V0cHV0LmFyZ3MgfHwgW10gOiBbZXZlbnRBcmd1bWVudF07XG4gICAgY29uc3QgZXZlbnRJZHggPSBhcmdzLmluZGV4T2YoZXZlbnRBcmd1bWVudCk7XG4gICAgY29uc3QgaGFuZGxlciA9IG91dHB1dC5oYW5kbGVyO1xuXG4gICAgLy8gV2hlbiB0aGVyZSBpcyBubyBldmVudCBhcmd1bWVudCAtIHVzZSBqdXN0IGFyZ3VtZW50c1xuICAgIGlmIChldmVudElkeCA9PT0gLTEpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbiAodGhpczogdW5rbm93bikge1xuICAgICAgICByZXR1cm4gaGFuZGxlci5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0aGlzOiB1bmtub3duLCBldmVudCkge1xuICAgICAgY29uc3QgYXJnc1dpdGhFdmVudCA9IFsuLi5hcmdzXTtcbiAgICAgIGFyZ3NXaXRoRXZlbnRbZXZlbnRJZHhdID0gZXZlbnQ7XG5cbiAgICAgIHJldHVybiBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3NXaXRoRXZlbnQpO1xuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHJlbWFwSU88VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICBpbzogVCxcbiAgICBtYXBwaW5nOiBJT01hcHBpbmdMaXN0LFxuICApIHtcbiAgICBjb25zdCBuZXdJTzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICAgIE9iamVjdC5rZXlzKGlvKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIGNvbnN0IG5ld0tleSA9IHRoaXMuZmluZFByb3BCeVRwbEluTWFwcGluZyhrZXksIG1hcHBpbmcpIHx8IGtleTtcbiAgICAgIG5ld0lPW25ld0tleV0gPSBpb1trZXldO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ld0lPIGFzIFQ7XG4gIH1cblxuICBwcml2YXRlIGZpbmRQcm9wQnlUcGxJbk1hcHBpbmcodHBsTmFtZTogc3RyaW5nLCBtYXBwaW5nOiBJT01hcHBpbmdMaXN0KSB7XG4gICAgZm9yIChjb25zdCBtYXAgb2YgbWFwcGluZykge1xuICAgICAgaWYgKG1hcC50ZW1wbGF0ZU5hbWUgPT09IHRwbE5hbWUpIHtcbiAgICAgICAgcmV0dXJuIG1hcC5wcm9wTmFtZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cbiJdfQ==