ng-dynamic-component
Version:
> Dynamic components with full life-cycle support for inputs and outputs
274 lines • 34.7 kB
JavaScript
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==