UNPKG

@hapiness/ng-elements-loader

Version:

Service to load Angular Custom Elements inside Angular's applications

160 lines (154 loc) 29.3 kB
import { Compiler, ComponentFactoryResolver, Injectable, Injector, defineInjectable, inject, INJECTOR } from '@angular/core'; import { createCustomElement } from '@angular/elements'; import { forkJoin, from, merge, of, throwError } from 'rxjs'; import { filter, flatMap, map, tap, toArray } from 'rxjs/operators'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ElementsLoaderService { /** * @param {?} _injector * @param {?} _compiler * @param {?} _componentFactoryResolver */ constructor(_injector, _compiler, _componentFactoryResolver) { this._injector = _injector; this._compiler = _compiler; this._componentFactoryResolver = _componentFactoryResolver; this._elementsToLoad = new Map(); } /** * Queries the document element for any custom elements that have not yet been registered with * the browser. Custom elements that are registered will be removed from the list of unregistered * elements so that they will not be queried in subsequent calls. Compile the module and its component * to be registered as custom elements. * This function is used in JIT mode * @param {?} data * @return {?} */ loadContainingCustomElements(data) { return of(data) .pipe(flatMap((_) => !!_ ? of([].concat(_)) : throwError(new Error('Parameter must be a `CustomElementModuleSelector` or an array of it'))), flatMap((_) => !!_.length ? of(_) : throwError(new Error('`CustomElementModuleSelector` array must have at least one element'))), flatMap((_) => from(_)), filter(_ => !!_.selector && !!_.module), toArray(), tap((_) => _.forEach((e) => this._elementsToLoad.set(e.selector, e.module))), flatMap(() => this._customElements(true))); } /** * Queries the document element for any custom elements that have not yet been registered with * the browser. Custom elements that are registered will be removed from the list of unregistered * elements so that they will not be queried in subsequent calls. Component will be registered as * custom elements. * This function is used in AOT mode * @param {?} data * @return {?} */ registerContainingCustomElements(data) { return of(data) .pipe(flatMap((_) => !!_ ? of([].concat(_)) : throwError(new Error('Parameter must be a `CustomElementComponentSelector` or an array of it'))), flatMap((_) => !!_.length ? of(_) : throwError(new Error('`CustomElementComponentSelector` array must have at least one element'))), flatMap((_) => from(_)), filter(_ => !!_.selector && !!_.component), toArray(), tap((_) => _.forEach((e) => this._elementsToLoad.set(e.selector, e.component))), flatMap(() => this._customElements(false))); } /** * Main process to load custom elements * @private * @param {?} compileModuleAndAllComponents * @return {?} */ _customElements(compileModuleAndAllComponents) { return of(of(Array.from(this._elementsToLoad.keys()))) .pipe(flatMap(obs => merge(obs.pipe(filter(_ => !!_ && !!_.length), flatMap(_ => forkJoin(_.map(s => this._register(s, compileModuleAndAllComponents))))), obs.pipe(filter(_ => !_ || !_.length), map(_ => (/** @type {?} */ (undefined))))))); } /** * Registers the custom element defined on the WithCustomElement module factory * @private * @param {?} selector * @param {?} compileModuleAndAllComponents * @return {?} */ _register(selector, compileModuleAndAllComponents) { return of(of(this._elementsToLoad.has(selector))) .pipe(flatMap((obs) => merge(obs .pipe(filter(_ => !!_), // selector inside elements to load flatMap(_ => of(of(customElements.get(selector))) .pipe(flatMap((o) => merge(o.pipe(filter(__ => !!__), // selector already loaded tap(__ => this._elementsToLoad.delete(selector)) // so delete it ), o.pipe(filter(__ => !__), // selector never loaded flatMap(__ => this._createCustomElement(selector, compileModuleAndAllComponents)) // so create custom element )))))), obs .pipe(filter(_ => !_), // selector not in elements to load map(_ => (/** @type {?} */ (undefined))))))); } /** * Create custom element for current selector * @private * @param {?} selector * @param {?} compileModuleAndAllComponents * @return {?} */ _createCustomElement(selector, compileModuleAndAllComponents) { return of(of(compileModuleAndAllComponents)) .pipe(flatMap((obs) => merge(obs.pipe(filter(_ => !!_), flatMap(_ => this._componentAndInjectorFromCompiledModule((/** @type {?} */ (this._elementsToLoad.get(selector)))))), obs.pipe(filter(_ => !_), flatMap(_ => this._componentAndInjectorFromComponentFactory((/** @type {?} */ (this._elementsToLoad.get(selector)))))))), map((_) => createCustomElement(_.component, { injector: _.injector })), tap((customElement) => (/** @type {?} */ (customElements)).define(selector, customElement)), tap(_ => this._elementsToLoad.delete(selector)), flatMap(_ => from(customElements.whenDefined(selector)))); } /** * Compile module and all components to retrieve the component and the injector for custom element creation. * This function is only used in JIT mode. * @private * @param {?} elementModule * @return {?} */ _componentAndInjectorFromCompiledModule(elementModule) { return from(this._compiler.compileModuleAndAllComponentsAsync(elementModule)) .pipe(map((moduleWithComponentFactories) => moduleWithComponentFactories.ngModuleFactory), map((elementModuleFactory) => elementModuleFactory.create(this._injector)), flatMap((elementModuleRef) => !!elementModuleRef.instance.customElementComponent ? of((/** @type {?} */ ({ component: elementModuleRef.instance.customElementComponent, injector: elementModuleRef.injector }))) : throwError(new Error('WithCustomElementComponent interface must' + ' be implemented by all modules that declare a component that can be used as a custom element.')))); } /** * Resolve component to get module injector for custom element creation. * This function is only used in AOT mode. * @private * @template T * @param {?} elementComponent * @return {?} */ _componentAndInjectorFromComponentFactory(elementComponent) { return of(this._componentFactoryResolver.resolveComponentFactory(elementComponent)) .pipe(map((componentFactory) => componentFactory.ngModule), map((elementModuleRef) => (/** @type {?} */ (({ component: elementComponent, injector: elementModuleRef.injector }))))); } } ElementsLoaderService.decorators = [ { type: Injectable, args: [(/** @type {?} */ ({ providedIn: 'root' })),] } ]; /** @nocollapse */ ElementsLoaderService.ctorParameters = () => [ { type: Injector }, { type: Compiler }, { type: ComponentFactoryResolver } ]; /** @nocollapse */ ElementsLoaderService.ngInjectableDef = defineInjectable({ factory: function ElementsLoaderService_Factory() { return new ElementsLoaderService(inject(INJECTOR), inject(Compiler), inject(ComponentFactoryResolver)); }, token: ElementsLoaderService, providedIn: "root" }); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { ElementsLoaderService }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFwaW5lc3MtbmctZWxlbWVudHMtbG9hZGVyLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9AaGFwaW5lc3MvbmctZWxlbWVudHMtbG9hZGVyL2xpYi9lbGVtZW50cy1sb2FkZXIuc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIENvbXBpbGVyLFxuICAgIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgICBJbmplY3RhYmxlLFxuICAgIEluamVjdG9yLFxuICAgIE1vZHVsZVdpdGhDb21wb25lbnRGYWN0b3JpZXMsXG4gICAgTmdNb2R1bGVGYWN0b3J5LFxuICAgIE5nTW9kdWxlUmVmLFxuICAgIFR5cGVcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBjcmVhdGVDdXN0b21FbGVtZW50IH0gZnJvbSAnQGFuZ3VsYXIvZWxlbWVudHMnO1xuaW1wb3J0IHsgZm9ya0pvaW4sIGZyb20sIG1lcmdlLCBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCBmbGF0TWFwLCBtYXAsIHRhcCwgdG9BcnJheSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gICAgQ3VzdG9tRWxlbWVudENvbXBvbmVudFNlbGVjdG9yLFxuICAgIEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvcixcbiAgICBXaXRoQ3VzdG9tRWxlbWVudENvbXBvbmVudFxufSBmcm9tICcuL2VsZW1lbnRzLXJlZ2lzdHJ5JztcblxuLy8gaW50ZXJmYWNlIHRvIG1hcCBkYXRhIGluc2VydGVkIGluIGNyZWF0ZUN1c3RvbUVsZW1lbnQoKVxuaW50ZXJmYWNlIEN1c3RvbUVsZW1lbnREYXRhIHtcbiAgICBjb21wb25lbnQ6IFR5cGU8YW55PjtcbiAgICBpbmplY3RvcjogSW5qZWN0b3I7XG59XG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0gYXMgYW55KVxuZXhwb3J0IGNsYXNzIEVsZW1lbnRzTG9hZGVyU2VydmljZSB7XG4gICAgLyoqIE1hcCBvZiB1bnJlZ2lzdGVyZWQgY3VzdG9tIGVsZW1lbnRzIGFuZCB0aGVpciByZXNwZWN0aXZlIG1vZHVsZSB0byBsb2FkLiAqL1xuICAgIHByaXZhdGUgX2VsZW1lbnRzVG9Mb2FkOiBNYXA8c3RyaW5nLCBUeXBlPGFueT4+O1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfaW5qZWN0b3I6IEluamVjdG9yLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgX2NvbXBpbGVyOiBDb21waWxlcixcbiAgICAgICAgICAgICAgICBwcml2YXRlIF9jb21wb25lbnRGYWN0b3J5UmVzb2x2ZXI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcikge1xuICAgICAgICB0aGlzLl9lbGVtZW50c1RvTG9hZCA9IG5ldyBNYXA8c3RyaW5nLCBUeXBlPGFueT4+KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgZG9jdW1lbnQgZWxlbWVudCBmb3IgYW55IGN1c3RvbSBlbGVtZW50cyB0aGF0IGhhdmUgbm90IHlldCBiZWVuIHJlZ2lzdGVyZWQgd2l0aFxuICAgICAqIHRoZSBicm93c2VyLiBDdXN0b20gZWxlbWVudHMgdGhhdCBhcmUgcmVnaXN0ZXJlZCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgbGlzdCBvZiB1bnJlZ2lzdGVyZWRcbiAgICAgKiBlbGVtZW50cyBzbyB0aGF0IHRoZXkgd2lsbCBub3QgYmUgcXVlcmllZCBpbiBzdWJzZXF1ZW50IGNhbGxzLiBDb21waWxlIHRoZSBtb2R1bGUgYW5kIGl0cyBjb21wb25lbnRcbiAgICAgKiB0byBiZSByZWdpc3RlcmVkIGFzIGN1c3RvbSBlbGVtZW50cy5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gSklUIG1vZGVcbiAgICAgKi9cbiAgICBsb2FkQ29udGFpbmluZ0N1c3RvbUVsZW1lbnRzKGRhdGE6IEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvciB8IEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvcltdKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG9mKGRhdGEpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmbGF0TWFwKChfOiBDdXN0b21FbGVtZW50TW9kdWxlU2VsZWN0b3IgfCBDdXN0b21FbGVtZW50TW9kdWxlU2VsZWN0b3JbXSkgPT5cbiAgICAgICAgICAgICAgICAgICAgISFfID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG9mKFtdLmNvbmNhdChfKSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihuZXcgRXJyb3IoJ1BhcmFtZXRlciBtdXN0IGJlIGEgYEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvcmAgb3IgYW4gYXJyYXkgb2YgaXQnKSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZsYXRNYXAoKF86IEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvcltdKSA9PlxuICAgICAgICAgICAgICAgICAgICAhIV8ubGVuZ3RoID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG9mKF8pIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93RXJyb3IobmV3IEVycm9yKCdgQ3VzdG9tRWxlbWVudE1vZHVsZVNlbGVjdG9yYCBhcnJheSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGVsZW1lbnQnKSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZsYXRNYXAoKF86IEN1c3RvbUVsZW1lbnRNb2R1bGVTZWxlY3RvcltdKSA9PiBmcm9tKF8pKSxcbiAgICAgICAgICAgICAgICBmaWx0ZXIoXyA9PiAhIV8uc2VsZWN0b3IgJiYgISFfLm1vZHVsZSksXG4gICAgICAgICAgICAgICAgdG9BcnJheSgpLFxuICAgICAgICAgICAgICAgIHRhcCgoXzogQ3VzdG9tRWxlbWVudE1vZHVsZVNlbGVjdG9yW10pID0+XG4gICAgICAgICAgICAgICAgICAgIF8uZm9yRWFjaCgoZTogQ3VzdG9tRWxlbWVudE1vZHVsZVNlbGVjdG9yKSA9PiB0aGlzLl9lbGVtZW50c1RvTG9hZC5zZXQoZS5zZWxlY3RvciwgZS5tb2R1bGUpKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgZmxhdE1hcCgoKSA9PiB0aGlzLl9jdXN0b21FbGVtZW50cyh0cnVlKSlcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgZG9jdW1lbnQgZWxlbWVudCBmb3IgYW55IGN1c3RvbSBlbGVtZW50cyB0aGF0IGhhdmUgbm90IHlldCBiZWVuIHJlZ2lzdGVyZWQgd2l0aFxuICAgICAqIHRoZSBicm93c2VyLiBDdXN0b20gZWxlbWVudHMgdGhhdCBhcmUgcmVnaXN0ZXJlZCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgbGlzdCBvZiB1bnJlZ2lzdGVyZWRcbiAgICAgKiBlbGVtZW50cyBzbyB0aGF0IHRoZXkgd2lsbCBub3QgYmUgcXVlcmllZCBpbiBzdWJzZXF1ZW50IGNhbGxzLiBDb21wb25lbnQgd2lsbCBiZSByZWdpc3RlcmVkIGFzXG4gICAgICogY3VzdG9tIGVsZW1lbnRzLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBpbiBBT1QgbW9kZVxuICAgICAqL1xuICAgIHJlZ2lzdGVyQ29udGFpbmluZ0N1c3RvbUVsZW1lbnRzKGRhdGE6IEN1c3RvbUVsZW1lbnRDb21wb25lbnRTZWxlY3RvciB8IEN1c3RvbUVsZW1lbnRDb21wb25lbnRTZWxlY3RvcltdKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG9mKGRhdGEpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmbGF0TWFwKChfOiBDdXN0b21FbGVtZW50Q29tcG9uZW50U2VsZWN0b3IgfCBDdXN0b21FbGVtZW50Q29tcG9uZW50U2VsZWN0b3JbXSkgPT5cbiAgICAgICAgICAgICAgICAgICAgISFfID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG9mKFtdLmNvbmNhdChfKSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihuZXcgRXJyb3IoJ1BhcmFtZXRlciBtdXN0IGJlIGEgYEN1c3RvbUVsZW1lbnRDb21wb25lbnRTZWxlY3RvcmAgb3IgYW4gYXJyYXkgb2YgaXQnKSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZsYXRNYXAoKF86IEN1c3RvbUVsZW1lbnRDb21wb25lbnRTZWxlY3RvcltdKSA9PlxuICAgICAgICAgICAgICAgICAgICAhIV8ubGVuZ3RoID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG9mKF8pIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93RXJyb3IobmV3IEVycm9yKCdgQ3VzdG9tRWxlbWVudENvbXBvbmVudFNlbGVjdG9yYCBhcnJheSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGVsZW1lbnQnKSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGZsYXRNYXAoKF86IEN1c3RvbUVsZW1lbnRDb21wb25lbnRTZWxlY3RvcltdKSA9PiBmcm9tKF8pKSxcbiAgICAgICAgICAgICAgICBmaWx0ZXIoXyA9PiAhIV8uc2VsZWN0b3IgJiYgISFfLmNvbXBvbmVudCksXG4gICAgICAgICAgICAgICAgdG9BcnJheSgpLFxuICAgICAgICAgICAgICAgIHRhcCgoXzogQ3VzdG9tRWxlbWVudENvbXBvbmVudFNlbGVjdG9yW10pID0+XG4gICAgICAgICAgICAgICAgICAgIF8uZm9yRWFjaCgoZTogQ3VzdG9tRWxlbWVudENvbXBvbmVudFNlbGVjdG9yKSA9PiB0aGlzLl9lbGVtZW50c1RvTG9hZC5zZXQoZS5zZWxlY3RvciwgZS5jb21wb25lbnQpKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgZmxhdE1hcCgoKSA9PiB0aGlzLl9jdXN0b21FbGVtZW50cyhmYWxzZSkpXG4gICAgICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1haW4gcHJvY2VzcyB0byBsb2FkIGN1c3RvbSBlbGVtZW50c1xuICAgICAqL1xuICAgIHByaXZhdGUgX2N1c3RvbUVsZW1lbnRzKGNvbXBpbGVNb2R1bGVBbmRBbGxDb21wb25lbnRzOiBib29sZWFuKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG9mKG9mKEFycmF5LmZyb20odGhpcy5fZWxlbWVudHNUb0xvYWQua2V5cygpKSkpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmbGF0TWFwKG9icyA9PlxuICAgICAgICAgICAgICAgICAgICBtZXJnZShcbiAgICAgICAgICAgICAgICAgICAgICAgIG9icy5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihfID0+ICEhXyAmJiAhIV8ubGVuZ3RoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbGF0TWFwKF8gPT4gZm9ya0pvaW4oXy5tYXAocyA9PiB0aGlzLl9yZWdpc3RlcihzLCBjb21waWxlTW9kdWxlQW5kQWxsQ29tcG9uZW50cykpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoXyA9PiAhXyB8fCAhXy5sZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcChfID0+IHVuZGVmaW5lZCBhcyBhbnkpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyB0aGUgY3VzdG9tIGVsZW1lbnQgZGVmaW5lZCBvbiB0aGUgV2l0aEN1c3RvbUVsZW1lbnQgbW9kdWxlIGZhY3RvcnlcbiAgICAgKi9cbiAgICBwcml2YXRlIF9yZWdpc3RlcihzZWxlY3Rvcjogc3RyaW5nLCBjb21waWxlTW9kdWxlQW5kQWxsQ29tcG9uZW50czogYm9vbGVhbik6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgICAgICByZXR1cm4gb2YoXG4gICAgICAgICAgICBvZih0aGlzLl9lbGVtZW50c1RvTG9hZC5oYXMoc2VsZWN0b3IpKVxuICAgICAgICApXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmbGF0TWFwKChvYnM6IE9ic2VydmFibGU8Ym9vbGVhbj4pID0+XG4gICAgICAgICAgICAgICAgICAgIG1lcmdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgb2JzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihfID0+ICEhXyksIC8vIHNlbGVjdG9yIGluc2lkZSBlbGVtZW50cyB0byBsb2FkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZsYXRNYXAoXyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2YoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2YoY3VzdG9tRWxlbWVudHMuZ2V0KHNlbGVjdG9yKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmxhdE1hcCgobzogT2JzZXJ2YWJsZTxib29sZWFuPikgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8ucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKF9fID0+ICEhX18pLCAvLyBzZWxlY3RvciBhbHJlYWR5IGxvYWRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAoX18gPT4gdGhpcy5fZWxlbWVudHNUb0xvYWQuZGVsZXRlKHNlbGVjdG9yKSkgLy8gc28gZGVsZXRlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihfXyA9PiAhX18pLCAvLyBzZWxlY3RvciBuZXZlciBsb2FkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmxhdE1hcChfXyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlQ3VzdG9tRWxlbWVudChzZWxlY3RvciwgY29tcGlsZU1vZHVsZUFuZEFsbENvbXBvbmVudHMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgLy8gc28gY3JlYXRlIGN1c3RvbSBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoXyA9PiAhXyksIC8vIHNlbGVjdG9yIG5vdCBpbiBlbGVtZW50cyB0byBsb2FkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcChfID0+IHVuZGVmaW5lZCBhcyBhbnkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgY3VzdG9tIGVsZW1lbnQgZm9yIGN1cnJlbnQgc2VsZWN0b3JcbiAgICAgKi9cbiAgICBwcml2YXRlIF9jcmVhdGVDdXN0b21FbGVtZW50KHNlbGVjdG9yOiBzdHJpbmcsIGNvbXBpbGVNb2R1bGVBbmRBbGxDb21wb25lbnRzOiBib29sZWFuKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBvZihcbiAgICAgICAgICAgIG9mKGNvbXBpbGVNb2R1bGVBbmRBbGxDb21wb25lbnRzKVxuICAgICAgICApXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmbGF0TWFwKChvYnM6IE9ic2VydmFibGU8Ym9vbGVhbj4pID0+XG4gICAgICAgICAgICAgICAgICAgIG1lcmdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgb2JzLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKF8gPT4gISFfKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbGF0TWFwKF8gPT4gdGhpcy5fY29tcG9uZW50QW5kSW5qZWN0b3JGcm9tQ29tcGlsZWRNb2R1bGUodGhpcy5fZWxlbWVudHNUb0xvYWQuZ2V0KHNlbGVjdG9yKSEpKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9icy5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihfID0+ICFfKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbGF0TWFwKF8gPT4gdGhpcy5fY29tcG9uZW50QW5kSW5qZWN0b3JGcm9tQ29tcG9uZW50RmFjdG9yeSh0aGlzLl9lbGVtZW50c1RvTG9hZC5nZXQoc2VsZWN0b3IpISkpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIG1hcCgoXzogQ3VzdG9tRWxlbWVudERhdGEpID0+IGNyZWF0ZUN1c3RvbUVsZW1lbnQoXy5jb21wb25lbnQsIHsgaW5qZWN0b3I6IF8uaW5qZWN0b3IgfSkpLFxuICAgICAgICAgICAgICAgIHRhcCgoY3VzdG9tRWxlbWVudDogYW55KSA9PiBjdXN0b21FbGVtZW50cyEuZGVmaW5lKHNlbGVjdG9yLCBjdXN0b21FbGVtZW50KSksXG4gICAgICAgICAgICAgICAgdGFwKF8gPT4gdGhpcy5fZWxlbWVudHNUb0xvYWQuZGVsZXRlKHNlbGVjdG9yKSksXG4gICAgICAgICAgICAgICAgZmxhdE1hcChfID0+IGZyb20oY3VzdG9tRWxlbWVudHMud2hlbkRlZmluZWQoc2VsZWN0b3IpKSlcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGlsZSBtb2R1bGUgYW5kIGFsbCBjb21wb25lbnRzIHRvIHJldHJpZXZlIHRoZSBjb21wb25lbnQgYW5kIHRoZSBpbmplY3RvciBmb3IgY3VzdG9tIGVsZW1lbnQgY3JlYXRpb24uXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBvbmx5IHVzZWQgaW4gSklUIG1vZGUuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfY29tcG9uZW50QW5kSW5qZWN0b3JGcm9tQ29tcGlsZWRNb2R1bGUoZWxlbWVudE1vZHVsZTogVHlwZTxXaXRoQ3VzdG9tRWxlbWVudENvbXBvbmVudD4pOlxuICAgICAgICBPYnNlcnZhYmxlPEN1c3RvbUVsZW1lbnREYXRhIHwgbmV2ZXI+IHtcbiAgICAgICAgcmV0dXJuIGZyb20odGhpcy5fY29tcGlsZXIuY29tcGlsZU1vZHVsZUFuZEFsbENvbXBvbmVudHNBc3luYyhlbGVtZW50TW9kdWxlKSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgobW9kdWxlV2l0aENvbXBvbmVudEZhY3RvcmllczogTW9kdWxlV2l0aENvbXBvbmVudEZhY3RvcmllczxXaXRoQ3VzdG9tRWxlbWVudENvbXBvbmVudD4pID0+XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZVdpdGhDb21wb25lbnRGYWN0b3JpZXMubmdNb2R1bGVGYWN0b3J5XG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBtYXAoKGVsZW1lbnRNb2R1bGVGYWN0b3J5OiBOZ01vZHVsZUZhY3Rvcnk8V2l0aEN1c3RvbUVsZW1lbnRDb21wb25lbnQ+KSA9PiBlbGVtZW50TW9kdWxlRmFjdG9yeS5jcmVhdGUodGhpcy5faW5qZWN0b3IpKSxcbiAgICAgICAgICAgICAgICBmbGF0TWFwKChlbGVtZW50TW9kdWxlUmVmOiBOZ01vZHVsZVJlZjxXaXRoQ3VzdG9tRWxlbWVudENvbXBvbmVudD4pID0+XG4gICAgICAgICAgICAgICAgICAgICEhZWxlbWVudE1vZHVsZVJlZi5pbnN0YW5jZS5jdXN0b21FbGVtZW50Q29tcG9uZW50ID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG9mKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnQ6IGVsZW1lbnRNb2R1bGVSZWYuaW5zdGFuY2UuY3VzdG9tRWxlbWVudENvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmplY3RvcjogZWxlbWVudE1vZHVsZVJlZi5pbmplY3RvclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBhcyBDdXN0b21FbGVtZW50RGF0YSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgRXJyb3IoJ1dpdGhDdXN0b21FbGVtZW50Q29tcG9uZW50IGludGVyZmFjZSBtdXN0JyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcgYmUgaW1wbGVtZW50ZWQgYnkgYWxsIG1vZHVsZXMgdGhhdCBkZWNsYXJlIGEgY29tcG9uZW50IHRoYXQgY2FuIGJlIHVzZWQgYXMgYSBjdXN0b20gZWxlbWVudC4nKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzb2x2ZSBjb21wb25lbnQgdG8gZ2V0IG1vZHVsZSBpbmplY3RvciAgZm9yIGN1c3RvbSBlbGVtZW50IGNyZWF0aW9uLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgb25seSB1c2VkIGluIEFPVCBtb2RlLlxuICAgICAqL1xuICAgIHByaXZhdGUgX2NvbXBvbmVudEFuZEluamVjdG9yRnJvbUNvbXBvbmVudEZhY3Rvcnk8VD4oZWxlbWVudENvbXBvbmVudDogVHlwZTxUPik6IE9ic2VydmFibGU8Q3VzdG9tRWxlbWVudERhdGE+IHtcbiAgICAgICAgcmV0dXJuIG9mKHRoaXMuX2NvbXBvbmVudEZhY3RvcnlSZXNvbHZlci5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeTxUPihlbGVtZW50Q29tcG9uZW50KSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgoY29tcG9uZW50RmFjdG9yeTogYW55KSA9PiBjb21wb25lbnRGYWN0b3J5Lm5nTW9kdWxlKSxcbiAgICAgICAgICAgICAgICBtYXAoKGVsZW1lbnRNb2R1bGVSZWY6IE5nTW9kdWxlUmVmPGFueT4pID0+XG4gICAgICAgICAgICAgICAgICAgICh7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnQ6IGVsZW1lbnRDb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmplY3RvcjogZWxlbWVudE1vZHVsZVJlZi5pbmplY3RvclxuICAgICAgICAgICAgICAgICAgICB9KSBhcyBDdXN0b21FbGVtZW50RGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgfVxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE1BNEJhLHFCQUFxQjs7Ozs7O0lBSTlCLFlBQW9CLFNBQW1CLEVBQ25CLFNBQW1CLEVBQ25CLHlCQUFtRDtRQUZuRCxjQUFTLEdBQVQsU0FBUyxDQUFVO1FBQ25CLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFDbkIsOEJBQXlCLEdBQXpCLHlCQUF5QixDQUEwQjtRQUNuRSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksR0FBRyxFQUFxQixDQUFDO0tBQ3ZEOzs7Ozs7Ozs7O0lBU0QsNEJBQTRCLENBQUMsSUFBaUU7UUFDMUYsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDO2FBQ1YsSUFBSSxDQUNELE9BQU8sQ0FBQyxDQUFDLENBQThELEtBQ25FLENBQUMsQ0FBQyxDQUFDO1lBQ0MsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEIsVUFBVSxDQUFDLElBQUksS0FBSyxDQUFDLHFFQUFxRSxDQUFDLENBQUMsQ0FDbkcsRUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFnQyxLQUNyQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07WUFDTixFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ0wsVUFBVSxDQUFDLElBQUksS0FBSyxDQUFDLG9FQUFvRSxDQUFDLENBQUMsQ0FDbEcsRUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFnQyxLQUFLLElBQUksQ0FB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