UNPKG

@dotglitch/ngx-common

Version:

Angular components and utilities that are commonly used.

160 lines 25.4 kB
import { Component, createComponent } from '@angular/core'; import * as React from 'react'; import { createRoot } from 'react-dom/client'; import { ulid } from 'ulidx'; import * as i0 from "@angular/core"; import * as i1 from "../../services/theme.service"; /** * Extend this component to automatically generate * bindings to a React component. * * ! You _must_ override the property `ngReactComponent` * Failure to do so will result in errors * `override readonly ngReactComponent = ReactFlowWrappableComponent;` */ export class ReactMagicWrapperComponent { /** * Wrap an angular component inside of a React memo object. * Will attempt to bind @Input and @Output properties if provided, * and will bind the react arguments directly as @Input properties. * * @experimental * @param componentClass Angular component * @param envInjector An `EnvironmentInjector` instance to be used for the component * @param injector An `ElementInjector` instance * @param _inputs * @param _outputs * @returns */ static { this.WrapAngularComponent = ({ component, appRef, injector, ngZone, staticInputs, staticOutputs, preSiblings, postSiblings, additionalChildren, rootElementName, containerElementName }) => React.memo((args) => { const id = ulid(); React.useEffect(() => { try { const componentInstance = createComponent(component, { environmentInjector: appRef.injector, elementInjector: injector, hostElement: document.getElementById(id) }); appRef.attachView(componentInstance.hostView); // @ts-ignore // component.hostView = hostView; Object.assign(staticInputs, args); const { inputs, outputs } = component['ɵcmp']; // Returns a list of entries that need to be set // This makes it so that unnecessary setters are not invoked. const updated = Object.entries(inputs).filter(([parentKey, childKey]) => { return componentInstance.instance[childKey] != staticInputs[parentKey]; }); updated.forEach(([parentKey, childKey]) => { if (staticInputs.hasOwnProperty(parentKey)) componentInstance.instance[childKey] = staticInputs[parentKey]; }); const outputSubscriptions = {}; // Get a list of unregistered outputs const newOutputs = Object.entries(outputs).filter(([parentKey, childKey]) => { return !outputSubscriptions[parentKey]; }); // Reverse bind via subscription newOutputs.forEach(([parentKey, childKey]) => { if (!staticOutputs.hasOwnProperty(parentKey)) return; const target = componentInstance.instance[childKey]; const outputs = staticOutputs; const sub = target.subscribe((...args) => { // Run the callback in the provided zone ngZone.run(() => { outputs[parentKey](...args); }); }); // Subscription outputSubscriptions[parentKey] = sub; }); // Wrap the destroy method to safely release the subscriptions const originalDestroy = componentInstance.onDestroy?.bind(componentInstance); componentInstance.onDestroy = (cb) => { Object.values(outputSubscriptions).forEach(s => s.unsubscribe()); originalDestroy?.(cb); }; componentInstance.changeDetectorRef.detectChanges(); } catch (err) { console.error(err); } }, []); const elements = [ ...(preSiblings || []), React.createElement(containerElementName || "div", { id }), ...(postSiblings || []), ...(additionalChildren || []) ].filter(e => e); return React.createElement(rootElementName || "div", {}, ...elements); }); } constructor(ngContainer, ngTheme, ngZone) { this.ngContainer = ngContainer; this.ngTheme = ngTheme; this.ngZone = ngZone; this.ngSubscriptions = [ this.ngTheme.subscribe(t => { this.theme = t; this.ngOnChanges(); }) ]; } ngOnInit() { if (!this.ngReactComponent) { throw new Error("ReactMagicWrapperComponent cannot start without a provided ngReactComponent!"); } } ngOnChanges(changes) { this._render(); } ngAfterViewInit() { this._render(); } ngOnDestroy() { this._root?.unmount(); this.ngSubscriptions.forEach(s => s.unsubscribe()); } _render() { if (!this.ngReactComponent) { console.log("Render no component. May be context issue"); return; } ; this.ngZone.runOutsideAngular(() => { try { this._root ??= createRoot(this.ngContainer.element.nativeElement); // List all keys that do not start with `_` nor `ng` const keys = Object.keys(this).filter(k => !/^(?:_|ng)/.test(k)); // Get all property keys from the class const propKeys = keys.filter(k => !k.startsWith("on")); // Get all event handler keys from the class const evtKeys = keys.filter(k => k.startsWith("on")); const props = {}; // Project all key properties onto `props` propKeys.forEach(k => props[k] = this[k]); // Attempt to ensure no zone is lost during the event emitter fires this.ngZone.runGuarded(() => { // Bind all event handlers. // ! important Angular uses EventEmitter, React uses // a different method of event binding evtKeys.forEach(k => props[k] = (...args) => this[k].next(args)); }); this._root.render(React.createElement(this.ngReactComponent, { props: props })); } catch (err) { console.error(err); } }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: ReactMagicWrapperComponent, deps: [{ token: i0.ViewContainerRef }, { token: i1.ThemeService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.2", type: ReactMagicWrapperComponent, isStandalone: true, selector: "app-react-magic-wrapper", usesOnChanges: true, ngImport: i0, template: ``, isInline: true }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: ReactMagicWrapperComponent, decorators: [{ type: Component, args: [{ selector: 'app-react-magic-wrapper', template: ``, standalone: true }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i1.ThemeService }, { type: i0.NgZone }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhY3QtbWFnaWMtd3JhcHBlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vc3JjL2NvbXBvbmVudHMvcmVhY3QtbWFnaWMtd3JhcHBlci9yZWFjdC1tYWdpYy13cmFwcGVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWlDLFNBQVMsRUFBdUosZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9PLE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQy9CLE9BQU8sRUFBRSxVQUFVLEVBQVEsTUFBTSxrQkFBa0IsQ0FBQztBQUdwRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sT0FBTyxDQUFDOzs7QUFHN0I7Ozs7Ozs7R0FPRztBQU1ILE1BQU0sT0FBTywwQkFBMEI7SUFFbkM7Ozs7Ozs7Ozs7OztPQVlHO2FBQ0kseUJBQW9CLEdBQUcsQ0FBQyxFQUMzQixTQUFTLEVBQ1QsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBQ04sWUFBWSxFQUNaLGFBQWEsRUFDYixXQUFXLEVBQ1gsWUFBWSxFQUNaLGtCQUFrQixFQUNsQixlQUFlLEVBQ2Ysb0JBQW9CLEVBYXZCLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUV0QixNQUFNLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNsQixLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNqQixJQUFJLENBQUM7Z0JBRUQsTUFBTSxpQkFBaUIsR0FBRyxlQUFlLENBQUMsU0FBUyxFQUFFO29CQUNqRCxtQkFBbUIsRUFBRSxNQUFNLENBQUMsUUFBUTtvQkFDcEMsZUFBZSxFQUFFLFFBQVE7b0JBQ3pCLFdBQVcsRUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztpQkFDM0MsQ0FBQyxDQUFDO2dCQUVILE1B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Q0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFMUMsbUVBQW1FO2dCQUNuRSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ3hCLDJCQUEyQjtvQkFDM0Isb0RBQW9EO29CQUNwRCxzQ0FBc0M7b0JBQ3RDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNyRSxDQUFDLENBQUMsQ0FBQTtnQkFFRixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0YsQ0FBQztZQUNELE9BQU0sR0FBRyxFQUFFLENBQUM7Z0JBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUN0QixDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDOzhHQWxNUSwwQkFBMEI7a0dBQTFCLDBCQUEwQix3R0FIekIsRUFBRTs7MkZBR0gsMEJBQTBCO2tCQUx0QyxTQUFTO21CQUFDO29CQUNQLFFBQVEsRUFBRSx5QkFBeUI7b0JBQ25DLFFBQVEsRUFBRSxFQUFFO29CQUNaLFVBQVUsRUFBRSxJQUFJO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIEFwcGxpY2F0aW9uUmVmLCBDb21wb25lbnQsIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgRW52aXJvbm1lbnRJbmplY3RvciwgRXZlbnRFbWl0dGVyLCBJbmplY3RvciwgTmdab25lLCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgU2ltcGxlQ2hhbmdlcywgVHlwZSwgVmlld0NvbnRhaW5lclJlZiwgVmlld1JlZiwgY3JlYXRlQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBjcmVhdGVSb290LCBSb290IH0gZnJvbSAncmVhY3QtZG9tL2NsaWVudCc7XG5cbmltcG9ydCB7IFRoZW1lU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RoZW1lLnNlcnZpY2UnO1xuaW1wb3J0IHsgdWxpZCB9IGZyb20gJ3VsaWR4JztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG4vKipcbiAqIEV4dGVuZCB0aGlzIGNvbXBvbmVudCB0byBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlXG4gKiBiaW5kaW5ncyB0byBhIFJlYWN0IGNvbXBvbmVudC5cbiAqXG4gKiAhIFlvdSBfbXVzdF8gb3ZlcnJpZGUgdGhlIHByb3BlcnR5IGBuZ1JlYWN0Q29tcG9uZW50YFxuICogRmFpbHVyZSB0byBkbyBzbyB3aWxsIHJlc3VsdCBpbiBlcnJvcnNcbiAqIGBvdmVycmlkZSByZWFkb25seSBuZ1JlYWN0Q29tcG9uZW50ID0gUmVhY3RGbG93V3JhcHBhYmxlQ29tcG9uZW50O2BcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdhcHAtcmVhY3QtbWFnaWMtd3JhcHBlcicsXG4gICAgdGVtcGxhdGU6IGBgLFxuICAgIHN0YW5kYWxvbmU6IHRydWVcbn0pXG5leHBvcnQgY2xhc3MgUmVhY3RNYWdpY1dyYXBwZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgICAvKipcbiAgICAgKiBXcmFwIGFuIGFuZ3VsYXIgY29tcG9uZW50IGluc2lkZSBvZiBhIFJlYWN0IG1lbW8gb2JqZWN0LlxuICAgICAqIFdpbGwgYXR0ZW1wdCB0byBiaW5kIEBJbnB1dCBhbmQgQE91dHB1dCBwcm9wZXJ0aWVzIGlmIHByb3ZpZGVkLFxuICAgICAqIGFuZCB3aWxsIGJpbmQgdGhlIHJlYWN0IGFyZ3VtZW50cyBkaXJlY3RseSBhcyBASW5wdXQgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgKiBAcGFyYW0gY29tcG9uZW50Q2xhc3MgQW5ndWxhciBjb21wb25lbnRcbiAgICAgKiBAcGFyYW0gZW52SW5qZWN0b3IgICAgQW4gYEVudmlyb25tZW50SW5qZWN0b3JgIGluc3RhbmNlIHRvIGJlIHVzZWQgZm9yIHRoZSBjb21wb25lbnRcbiAgICAgKiBAcGFyYW0gaW5qZWN0b3IgICAgICAgQW4gYEVsZW1lbnRJbmplY3RvcmAgaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gX2lucHV0c1xuICAgICAqIEBwYXJhbSBfb3V0cHV0c1xuICAgICAqIEByZXR1cm5zXG4gICAgICovXG4gICAgc3RhdGljIFdyYXBBbmd1bGFyQ29tcG9uZW50ID0gKHtcbiAgICAgICAgY29tcG9uZW50LFxuICAgICAgICBhcHBSZWYsXG4gICAgICAgIGluamVjdG9yLFxuICAgICAgICBuZ1pvbmUsXG4gICAgICAgIHN0YXRpY0lucHV0cyxcbiAgICAgICAgc3RhdGljT3V0cHV0cyxcbiAgICAgICAgcHJlU2libGluZ3MsXG4gICAgICAgIHBvc3RTaWJsaW5ncyxcbiAgICAgICAgYWRkaXRpb25hbENoaWxkcmVuLFxuICAgICAgICByb290RWxlbWVudE5hbWUsXG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnROYW1lXG4gICAgfToge1xuICAgICAgICBjb21wb25lbnQ6IFR5cGU8YW55PixcbiAgICAgICAgYXBwUmVmOiBPbWl0PEFwcGxpY2F0aW9uUmVmLCAnX3J1bm5pbmdUaWNrJz4sXG4gICAgICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICAgICAgbmdab25lOiBOZ1pvbmUsXG4gICAgICAgIHN0YXRpY0lucHV0cz86IHsgW2tleTogc3RyaW5nXTogYW55IH0sXG4gICAgICAgIHN0YXRpY091dHB1dHM/OiB7IFtrZXk6IHN0cmluZ106IEZ1bmN0aW9uIH0sXG4gICAgICAgIHByZVNpYmxpbmdzPzogUmVhY3QuUmVhY3ROb2RlW10sXG4gICAgICAgIHBvc3RTaWJsaW5ncz86IFJlYWN0LlJlYWN0Tm9kZVtdLFxuICAgICAgICBhZGRpdGlvbmFsQ2hpbGRyZW4/OiBSZWFjdC5SZWFjdE5vZGVbXSxcbiAgICAgICAgcm9vdEVsZW1lbnROYW1lPzogUGFyYW1ldGVyczx0eXBlb2YgUmVhY3QuY3JlYXRlRWxlbWVudD5bMF0sXG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnROYW1lPzogc3RyaW5nXG4gICAgfSkgPT4gUmVhY3QubWVtbygoYXJncykgPT4ge1xuXG4gICAgICAgIGNvbnN0IGlkID0gdWxpZCgpO1xuICAgICAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudEluc3RhbmNlID0gY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudCwge1xuICAgICAgICAgICAgICAgICAgICBlbnZpcm9ubWVudEluamVjdG9yOiBhcHBSZWYuaW5qZWN0b3IsXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRJbmplY3RvcjogaW5qZWN0b3IsXG4gICAgICAgICAgICAgICAgICAgIGhvc3RFbGVtZW50OiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZClcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGFwcFJlZi5hdHRhY2hWaWV3KGNvbXBvbmVudEluc3RhbmNlLmhvc3RWaWV3KTtcbiAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgLy8gY29tcG9uZW50Lmhvc3RWaWV3ID0gaG9zdFZpZXc7XG5cbiAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHN0YXRpY0lucHV0cywgYXJncyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB7IGlucHV0cywgb3V0cHV0cyB9ID0gY29tcG9uZW50WyfJtWNtcCddO1xuXG4gICAgICAgICAgICAgICAgLy8gUmV0dXJucyBhIGxpc3Qgb2YgZW50cmllcyB0aGF0IG5lZWQgdG8gYmUgc2V0XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBtYWtlcyBpdCBzbyB0aGF0IHVubmVjZXNzYXJ5IHNldHRlcnMgYXJlIG5vdCBpbnZva2VkLlxuICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWQgPSBPYmplY3QuZW50cmllcyhpbnB1dHMpLmZpbHRlcigoW3BhcmVudEtleSwgY2hpbGRLZXldOiBbc3RyaW5nLCBzdHJpbmddKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb21wb25lbnRJbnN0YW5jZS5pbnN0YW5jZVtjaGlsZEtleV0gIT0gc3RhdGljSW5wdXRzW3BhcmVudEtleV07XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICB1cGRhdGVkLmZvckVhY2goKFtwYXJlbnRLZXksIGNoaWxkS2V5XTogW3N0cmluZywgc3RyaW5nXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGljSW5wdXRzLmhhc093blByb3BlcnR5KHBhcmVudEtleSkpXG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRJbnN0YW5jZS5pbnN0YW5jZVtjaGlsZEtleV0gPSBzdGF0aWNJbnB1dHNbcGFyZW50S2V5XTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dFN1YnNjcmlwdGlvbnM6IHsgW2tleTogc3RyaW5nXTogU3Vic2NyaXB0aW9uIH0gPSB7fTtcbiAgICAgICAgICAgICAgICAvLyBHZXQgYSBsaXN0IG9mIHVucmVnaXN0ZXJlZCBvdXRwdXRzXG4gICAgICAgICAgICAgICAgY29uc3QgbmV3T3V0cHV0cyA9IE9iamVjdC5lbnRyaWVzKG91dHB1dHMpLmZpbHRlcigoW3BhcmVudEtleSwgY2hpbGRLZXldOiBbc3RyaW5nLCBzdHJpbmddKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhb3V0cHV0U3Vic2NyaXB0aW9uc1twYXJlbnRLZXldO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gUmV2ZXJzZSBiaW5kIHZpYSBzdWJzY3JpcHRpb25cbiAgICAgICAgICAgICAgICBuZXdPdXRwdXRzLmZvckVhY2goKFtwYXJlbnRLZXksIGNoaWxkS2V5XTogW3N0cmluZywgc3RyaW5nXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXN0YXRpY091dHB1dHMuaGFzT3duUHJvcGVydHkocGFyZW50S2V5KSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldDogRXZlbnRFbWl0dGVyPHVua25vd24+ID0gY29tcG9uZW50SW5zdGFuY2UuaW5zdGFuY2VbY2hpbGRLZXldO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRwdXRzID0gc3RhdGljT3V0cHV0cztcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdWIgPSB0YXJnZXQuc3Vic2NyaWJlKCguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSdW4gdGhlIGNhbGxiYWNrIGluIHRoZSBwcm92aWRlZCB6b25lXG4gICAgICAgICAgICAgICAgICAgICAgICBuZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRzW3BhcmVudEtleV0oLi4uYXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICB9KTsgLy8gU3Vic2NyaXB0aW9uXG5cbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0U3Vic2NyaXB0aW9uc1twYXJlbnRLZXldID0gc3ViO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gV3JhcCB0aGUgZGVzdHJveSBtZXRob2QgdG8gc2FmZWx5IHJlbGVhc2UgdGhlIHN1YnNjcmlwdGlvbnNcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5hbERlc3Ryb3kgPSBjb21wb25lbnRJbnN0YW5jZS5vbkRlc3Ryb3k/LmJpbmQoY29tcG9uZW50SW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudEluc3RhbmNlLm9uRGVzdHJveSA9IChjYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBPYmplY3QudmFsdWVzKG91dHB1dFN1YnNjcmlwdGlvbnMpLmZvckVhY2gocyA9PiBzLnVuc3Vic2NyaWJlKCkpO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbERlc3Ryb3k/LihjYik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29tcG9uZW50SW5zdGFuY2UuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2goZXJyKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIFtdKTtcblxuICAgICAgICBjb25zdCBlbGVtZW50cyA9IFtcbiAgICAgICAgICAgIC4uLihwcmVTaWJsaW5ncyB8fCBbXSksXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KGNvbnRhaW5lckVsZW1lbnROYW1lIHx8IFwiZGl2XCIsIHsgaWQgfSksXG4gICAgICAgICAgICAuLi4ocG9zdFNpYmxpbmdzIHx8IFtdKSxcbiAgICAgICAgICAgIC4uLihhZGRpdGlvbmFsQ2hpbGRyZW4gfHwgW10pXG4gICAgICAgIF0uZmlsdGVyKGUgPT4gZSk7XG5cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQocm9vdEVsZW1lbnROYW1lIHx8IFwiZGl2XCIsIHsgfSwgLi4uZWxlbWVudHMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlYWN0IGNvbXBvbmVudCB0byBiZSB3cmFwcGVkLlxuICAgICAqICEgTXVzdCBiZSBvdmVycmlkZGVuIGZvciB0aGlzIHdyYXBwZXIgdG8gd29ya1xuICAgICAqL1xuICAgIG5nUmVhY3RDb21wb25lbnQ6IFJlYWN0LkZ1bmN0aW9uQ29tcG9uZW50PGFueT4gfCBSZWFjdC5Db21wb25lbnRDbGFzczxhbnk+IHwgc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBfcm9vdDogUm9vdDtcbiAgICBwdWJsaWMgdGhlbWU6IHN0cmluZztcbiAgICBwcml2YXRlIG5nU3Vic2NyaXB0aW9ucyA9IFtcbiAgICAgICAgdGhpcy5uZ1RoZW1lLnN1YnNjcmliZSh0ID0+IHtcbiAgICAgICAgICAgIHRoaXMudGhlbWUgPSB0O1xuICAgICAgICAgICAgdGhpcy5uZ09uQ2hhbmdlcygpO1xuICAgICAgICB9KVxuICAgIF07XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBuZ0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBuZ1RoZW1lOiBUaGVtZVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgbmdab25lOiBOZ1pvbmVcbiAgICApIHtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLm5nUmVhY3RDb21wb25lbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWN0TWFnaWNXcmFwcGVyQ29tcG9uZW50IGNhbm5vdCBzdGFydCB3aXRob3V0IGEgcHJvdmlkZWQgbmdSZWFjdENvbXBvbmVudCFcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzPzogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICB0aGlzLl9yZW5kZXIoKTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlcigpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLl9yb290Py51bm1vdW50KCk7XG4gICAgICAgIHRoaXMubmdTdWJzY3JpcHRpb25zLmZvckVhY2gocyA9PiBzLnVuc3Vic2NyaWJlKCkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3JlbmRlcigpIHtcbiAgICAgICAgaWYgKCF0aGlzLm5nUmVhY3RDb21wb25lbnQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmVuZGVyIG5vIGNvbXBvbmVudC4gTWF5IGJlIGNvbnRleHQgaXNzdWVcIilcbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcm9vdCA/Pz0gY3JlYXRlUm9vdCh0aGlzLm5nQ29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICAvLyBMaXN0IGFsbCBrZXlzIHRoYXQgZG8gbm90IHN0YXJ0IHdpdGggYF9gIG5vciBgbmdgXG4gICAgICAgICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHRoaXMpLmZpbHRlcihrID0+ICEvXig/Ol98bmcpLy50ZXN0KGspKTtcblxuICAgICAgICAgICAgICAgIC8vIEdldCBhbGwgcHJvcGVydHkga2V5cyBmcm9tIHRoZSBjbGFzc1xuICAgICAgICAgICAgICAgIGNvbnN0IHByb3BLZXlzID0ga2V5cy5maWx0ZXIoayA9PiAhay5zdGFydHNXaXRoKFwib25cIikpO1xuICAgICAgICAgICAgICAgIC8vIEdldCBhbGwgZXZlbnQgaGFuZGxlciBrZXlzIGZyb20gdGhlIGNsYXNzXG4gICAgICAgICAgICAgICAgY29uc3QgZXZ0S2V5cyA9IGtleXMuZmlsdGVyKGsgPT4gay5zdGFydHNXaXRoKFwib25cIikpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICAvLyBQcm9qZWN0IGFsbCBrZXkgcHJvcGVydGllcyBvbnRvIGBwcm9wc2BcbiAgICAgICAgICAgICAgICBwcm9wS2V5cy5mb3JFYWNoKGsgPT4gcHJvcHNba10gPSB0aGlzW2tdKTtcblxuICAgICAgICAgICAgICAgIC8vIEF0dGVtcHQgdG8gZW5zdXJlIG5vIHpvbmUgaXMgbG9zdCBkdXJpbmcgdGhlIGV2ZW50IGVtaXR0ZXIgZmlyZXNcbiAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW5HdWFyZGVkKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQmluZCBhbGwgZXZlbnQgaGFuZGxlcnMuXG4gICAgICAgICAgICAgICAgICAgIC8vICEgaW1wb3J0YW50IEFuZ3VsYXIgdXNlcyBFdmVudEVtaXR0ZXIsIFJlYWN0IHVzZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYSBkaWZmZXJlbnQgbWV0aG9kIG9mIGV2ZW50IGJpbmRpbmdcbiAgICAgICAgICAgICAgICAgICAgZXZ0S2V5cy5mb3JFYWNoKGsgPT4gcHJvcHNba10gPSAoLi4uYXJncykgPT4gdGhpc1trXS5uZXh0KGFyZ3MpKTtcbiAgICAgICAgICAgICAgICB9KVxuXG4gICAgICAgICAgICAgICAgdGhpcy5fcm9vdC5yZW5kZXIoUmVhY3QuY3JlYXRlRWxlbWVudCh0aGlzLm5nUmVhY3RDb21wb25lbnQsIHsgcHJvcHM6IHByb3BzIGFzIGFueSB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycilcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9XG59XG4iXX0=