UNPKG

@dotglitch/ngx-lazy-loader

Version:

A hackable lazy loader for Angular components

216 lines 31.8 kB
import { Inject, Injectable, InjectionToken } from '@angular/core'; import { ComponentResolveStrategy } from './types'; import { stringToSlug } from '../../utils'; import { Logger } from '../../utils/logger'; import * as i0 from "@angular/core"; // Monkey-patch the type of these symbols. const $id = Symbol("id"); const $group = Symbol("group"); export const NGX_LAZY_LOADER_CONFIG = new InjectionToken('config'); export class NgxLazyLoaderService { get err() { return NgxLazyLoaderService.config.logger.err; } get log() { return NgxLazyLoaderService.config.logger.log; } get warn() { return NgxLazyLoaderService.config.logger.warn; } constructor(config = {}) { // Ensure this is singleton and works regardless of special instancing requirements. NgxLazyLoaderService.configure(config); } static configure(config) { const { log, warn, err } = Logger("ngx-lazy-loader", "#009688"); this.config = { componentResolveStrategy: ComponentResolveStrategy.PickFirst, logger: { log, warn, err }, ...config }; config.entries?.forEach(e => this.addComponentToRegistry(e)); // If a custom resolution strategy is provided but no resolution function is passed, // we throw an error if (this.config.componentResolveStrategy == ComponentResolveStrategy.Custom && !this.config.customResolver) { throw new Error("Cannot initialize. Configuration specifies a custom resolve matcher but none was provided"); } if (this.config.loaderDistractorComponent && this.config.loaderDistractorTemplate) throw new Error("Cannot have both a Component and Template for Distractor view."); if (this.config.errorComponent && this.config.errorTemplate) throw new Error("Cannot have both a Component and Template for Error view."); if (this.config.notFoundComponent && this.config.notFoundTemplate) throw new Error("Cannot have both a Component and Template for NotFound view."); } static addComponentToRegistry(registration) { if (!registration) throw new Error("Cannot add <undefined> component into registry."); // Clone the object into our repository and transfer the id into a standardized slug format const id = stringToSlug(registration.id ?? Date.now().toString()); // purge non-basic ASCII chars const group = registration.group || "default"; registration[$id] = id; registration[$group] = id; if (!this.registry[group]) this.registry[group] = []; // Check if we already have a registration for the component // if (this.registry[group] && typeof this.registry[group]['load'] == "function") { // // Warn the developer that the state is problematic // this.config.logger.warn( // `A previous entry already exists for ${id}! The old registration will be overridden.` + // `Please ensure you use groups if you intend to have duplicate component ids. ` + // `If this was intentional, first remove the old component from the registry before adding a new instance` // ); // // If we're in dev mode, break the loader surface // if (isDevMode()) // return; // } this.registry[group].push(registration); } /** * Register an Angular component * @param id identifier that is used to resolve the component * @param group * @param component Angular Component Class constructor */ registerComponent(args) { if (this.isComponentRegistered(args.id, args.group)) { this.log(`Will not re-register component '${args.id}' in group '${args.group || 'default'}' `); return; } NgxLazyLoaderService.addComponentToRegistry({ id: stringToSlug(args.id), matcher: args.matcher, group: stringToSlug(args.group || "default"), load: args.load || (() => args.component) }); } /** * * @param id * @param group */ unregisterComponent(id, group = "default") { const _id = stringToSlug(id); const _group = stringToSlug(group); if (!this.resolveRegistrationEntry(id, group)) throw new Error("Cannot unregister component ${}! Component is not present in registry"); // TODO: handle clearing running instances delete NgxLazyLoaderService.registry[_group][_id]; } /** * Get the registration entry for a component. * Returns null if component is not in the registry. */ resolveRegistrationEntry(value, group = "default") { const _id = stringToSlug(value); const _group = stringToSlug(group); const targetGroup = (NgxLazyLoaderService.registry[_group] || []); let items = targetGroup.filter(t => { if (!t) return false; // No matcher, check id if (!t.matcher) return t[$id] == _id; // Matcher is regex if (t.matcher instanceof RegExp) return t.matcher.test(_id) || t.matcher.test(value); // Matcher is string => regex if (typeof t.matcher == 'string') { const rx = new RegExp(t.matcher, 'ui'); return rx.test(_id) || rx.test(value); } // Matcher is array if (Array.isArray(t.matcher)) { return !!t.matcher.find(e => stringToSlug(e) == _id); } // Custom matcher function if (typeof t.matcher == "function") return t.matcher(_id); return false; }); if (items.length > 1) { this.warn("Resolved multiple components for the provided `[component]` binding. This may cause UI conflicts."); } if (items.length == 0) { return null; } const out = items[0]; if (out.matcher instanceof RegExp) { const result = _id.match(out.matcher) || value.match(out.matcher); return { entry: out, matchGroups: result?.groups }; } return { entry: out }; } /** * Check if a component is currently registered * Can be used to validate regex matchers and aliases. */ isComponentRegistered(value, group = "default") { return !!this.resolveRegistrationEntry(value, group); } /** * * @param bundle * @returns The component `Object` if a component was resolved, `null` if no component was found * `false` if the specified strategy was an invalid selection */ resolveComponent(id, group, modules) { switch (NgxLazyLoaderService.config.componentResolveStrategy) { case ComponentResolveStrategy.PickFirst: { return modules[0]; } // Exact id -> classname match case ComponentResolveStrategy.MatchIdToClassName: { const matches = modules .filter(k => k.name == id); if (matches.length == 0) return null; return matches[0]; } // Fuzzy id -> classname match case ComponentResolveStrategy.FuzzyIdClassName: { const _id = id.replace(/[^a-z0-9_\-]/ig, ''); if (_id.length == 0) { NgxLazyLoaderService.config.logger.err("Fuzzy classname matching stripped all symbols from the ID specified!"); return false; } const rx = new RegExp(`^${id}(component|module)?$`, "i"); const matches = modules .filter(mod => { let kid = mod.name.replace(/[^a-z0-9_\-]/ig, ''); return rx.test(kid); }); if (matches.length > 1) { NgxLazyLoaderService.config.logger.err("Fuzzy classname matching resolved multiple targets!"); return false; } if (matches.length == 0) { NgxLazyLoaderService.config.logger.err("Fuzzy classname matching resolved no targets!"); return null; } return matches[0]; } case ComponentResolveStrategy.Custom: { return NgxLazyLoaderService.config.customResolver(modules); } default: { return false; } } } } // A proxied registry that mutates reference keys NgxLazyLoaderService.registry = {}; /** @nocollapse */ NgxLazyLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgxLazyLoaderService, deps: [{ token: NGX_LAZY_LOADER_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ NgxLazyLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgxLazyLoaderService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgxLazyLoaderService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [NGX_LAZY_LOADER_CONFIG] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWxhenktbG9hZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2xhenktbG9hZGVyL25neC1sYXp5LWxvYWRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUM5RSxPQUFPLEVBQTRELHdCQUF3QixFQUFnRCxNQUFNLFNBQVMsQ0FBQztBQUMzSixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFFNUMsMENBQTBDO0FBQzFDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQWtCLENBQUM7QUFDMUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBa0IsQ0FBQztBQUVoRCxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLGNBQWMsQ0FBc0IsUUFBUSxDQUFDLENBQUM7QUFLeEYsTUFBTSxPQUFPLG9CQUFvQjtJQUM3QixJQUFZLEdBQUcsS0FBSyxPQUFPLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRSxJQUFZLEdBQUcsS0FBSyxPQUFPLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRSxJQUFZLElBQUksS0FBSyxPQUFPLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQVN0RSxZQUE0QyxTQUE4QixFQUFFO1FBQ3hFLG9GQUFvRjtRQUNwRixvQkFBb0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVPLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBMkI7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TyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQWMsQ0FBQyxDQUFDO2FBQ3JFO1lBQ0QsT0FBTyxDQUFDLENBQUM7Z0JBQ0wsT0FBTyxLQUFLLENBQUM7YUFDaEI7U0FDSjtJQUNMLENBQUM7O0FBclBELGlEQUFpRDtBQUNsQyw2QkFBUSxHQUVuQixFQUFFLENBQUM7b0lBUkUsb0JBQW9CLGtCQVlULHNCQUFzQjt3SUFaakMsb0JBQW9CLGNBRmpCLE1BQU07MkZBRVQsb0JBQW9CO2tCQUhoQyxVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQjs7MEJBYWdCLE1BQU07MkJBQUMsc0JBQXNCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rpb25Ub2tlbiwgaXNEZXZNb2RlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21waWxlZENvbXBvbmVudCwgQ29tcGlsZWRNb2R1bGUsIENvbXBvbmVudFJlZ2lzdHJhdGlvbiwgQ29tcG9uZW50UmVzb2x2ZVN0cmF0ZWd5LCBEeW5hbWljUmVnaXN0cmF0aW9uQXJncywgTmd4TGF6eUxvYWRlckNvbmZpZyB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgc3RyaW5nVG9TbHVnIH0gZnJvbSAnLi4vLi4vdXRpbHMnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vLi4vdXRpbHMvbG9nZ2VyJztcblxuLy8gTW9ua2V5LXBhdGNoIHRoZSB0eXBlIG9mIHRoZXNlIHN5bWJvbHMuXG5jb25zdCAkaWQgPSBTeW1ib2woXCJpZFwiKSBhcyBhbnkgYXMgc3RyaW5nO1xuY29uc3QgJGdyb3VwID0gU3ltYm9sKFwiZ3JvdXBcIikgYXMgYW55IGFzIHN0cmluZztcblxuZXhwb3J0IGNvbnN0IE5HWF9MQVpZX0xPQURFUl9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48Tmd4TGF6eUxvYWRlckNvbmZpZz4oJ2NvbmZpZycpO1xuXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIE5neExhenlMb2FkZXJTZXJ2aWNlIHtcbiAgICBwcml2YXRlIGdldCBlcnIoKSB7IHJldHVybiBOZ3hMYXp5TG9hZGVyU2VydmljZS5jb25maWcubG9nZ2VyLmVycjsgfVxuICAgIHByaXZhdGUgZ2V0IGxvZygpIHsgcmV0dXJuIE5neExhenlMb2FkZXJTZXJ2aWNlLmNvbmZpZy5sb2dnZXIubG9nOyB9XG4gICAgcHJpdmF0ZSBnZXQgd2FybigpIHsgcmV0dXJuIE5neExhenlMb2FkZXJTZXJ2aWNlLmNvbmZpZy5sb2dnZXIud2FybjsgfVxuXG4gICAgLy8gQSBwcm94aWVkIHJlZ2lzdHJ5IHRoYXQgbXV0YXRlcyByZWZlcmVuY2Uga2V5c1xuICAgIHByaXZhdGUgc3RhdGljIHJlZ2lzdHJ5OiB7XG4gICAgICAgIFtrZXk6IHN0cmluZ106IENvbXBvbmVudFJlZ2lzdHJhdGlvbltdO1xuICAgIH0gPSB7fTtcblxuICAgIHB1YmxpYyBzdGF0aWMgY29uZmlnOiBOZ3hMYXp5TG9hZGVyQ29uZmlnO1xuXG4gICAgY29uc3RydWN0b3IoQEluamVjdChOR1hfTEFaWV9MT0FERVJfQ09ORklHKSBjb25maWc6IE5neExhenlMb2FkZXJDb25maWcgPSB7fSkge1xuICAgICAgICAvLyBFbnN1cmUgdGhpcyBpcyBzaW5nbGV0b24gYW5kIHdvcmtzIHJlZ2FyZGxlc3Mgb2Ygc3BlY2lhbCBpbnN0YW5jaW5nIHJlcXVpcmVtZW50cy5cbiAgICAgICAgTmd4TGF6eUxvYWRlclNlcnZpY2UuY29uZmlndXJlKGNvbmZpZyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgY29uZmlndXJlKGNvbmZpZzogTmd4TGF6eUxvYWRlckNvbmZpZykge1xuICAgICAgICBjb25zdCB7IGxvZywgd2FybiwgZXJyIH0gPSBMb2dnZXIoXCJuZ3gtbGF6eS1sb2FkZXJcIiwgXCIjMDA5Njg4XCIpO1xuXG4gICAgICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgICAgICAgY29tcG9uZW50UmVzb2x2ZVN0cmF0ZWd5OiBDb21wb25lbnRSZXNvbHZlU3RyYXRlZ3kuUGlja0ZpcnN0LFxuICAgICAgICAgICAgbG9nZ2VyOiB7XG4gICAgICAgICAgICAgICAgbG9nLFxuICAgICAgICAgICAgICAgIHdhcm4sXG4gICAgICAgICAgICAgICAgZXJyXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLi4uY29uZmlnXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uZmlnLmVudHJpZXM/LmZvckVhY2goZSA9PiB0aGlzLmFkZENvbXBvbmVudFRvUmVnaXN0cnkoZSkpXG5cbiAgICAgICAgLy8gSWYgYSBjdXN0b20gcmVzb2x1dGlvbiBzdHJhdGVneSBpcyBwcm92aWRlZCBidXQgbm8gcmVzb2x1dGlvbiBmdW5jdGlvbiBpcyBwYXNzZWQsXG4gICAgICAgIC8vIHdlIHRocm93IGFuIGVycm9yXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmNvbXBvbmVudFJlc29sdmVTdHJhdGVneSA9PSBDb21wb25lbnRSZXNvbHZlU3RyYXRlZ3kuQ3VzdG9tICYmXG4gICAgICAgICAgICAhdGhpcy5jb25maWcuY3VzdG9tUmVzb2x2ZXJcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgaW5pdGlhbGl6ZS4gQ29uZmlndXJhdGlvbiBzcGVjaWZpZXMgYSBjdXN0b20gcmVzb2x2ZSBtYXRjaGVyIGJ1dCBub25lIHdhcyBwcm92aWRlZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5sb2FkZXJEaXN0cmFjdG9yQ29tcG9uZW50ICYmIHRoaXMuY29uZmlnLmxvYWRlckRpc3RyYWN0b3JUZW1wbGF0ZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBoYXZlIGJvdGggYSBDb21wb25lbnQgYW5kIFRlbXBsYXRlIGZvciBEaXN0cmFjdG9yIHZpZXcuXCIpXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5lcnJvckNvbXBvbmVudCAmJiB0aGlzLmNvbmZpZy5lcnJvclRlbXBsYXRlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGhhdmUgYm90aCBhIENvbXBvbmVudCBhbmQgVGVtcGxhdGUgZm9yIEVycm9yIHZpZXcuXCIpXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5ub3RGb3VuZENvbXBvbmVudCAmJiB0aGlzLmNvbmZpZy5ub3RGb3VuZFRlbXBsYXRlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGhhdmUgYm90aCBhIENvbXBvbmVudCBhbmQgVGVtcGxhdGUgZm9yIE5vdEZvdW5kIHZpZXcuXCIpXG5cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhZGRDb21wb25lbnRUb1JlZ2lzdHJ5KHJlZ2lzdHJhdGlvbjogQ29tcG9uZW50UmVnaXN0cmF0aW9uKSB7XG4gICAgICAgIGlmICghcmVnaXN0cmF0aW9uKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFkZCA8dW5kZWZpbmVkPiBjb21wb25lbnQgaW50byByZWdpc3RyeS5cIik7XG5cbiAgICAgICAgLy8gQ2xvbmUgdGhlIG9iamVjdCBpbnRvIG91ciByZXBvc2l0b3J5IGFuZCB0cmFuc2ZlciB0aGUgaWQgaW50byBhIHN0YW5kYXJkaXplZCBzbHVnIGZvcm1hdFxuXG4gICAgICAgIGNvbnN0IGlkID0gc3RyaW5nVG9TbHVnKHJlZ2lzdHJhdGlvbi5pZCA/PyBEYXRlLm5vdygpLnRvU3RyaW5nKCkpOyAvLyBwdXJnZSBub24tYmFzaWMgQVNDSUkgY2hhcnNcbiAgICAgICAgY29uc3QgZ3JvdXAgPSByZWdpc3RyYXRpb24uZ3JvdXAgfHwgXCJkZWZhdWx0XCI7XG5cbiAgICAgICAgcmVnaXN0cmF0aW9uWyRpZF0gPSBpZDtcbiAgICAgICAgcmVnaXN0cmF0aW9uWyRncm91cF0gPSBpZDtcblxuXG4gICAgICAgIGlmICghdGhpcy5yZWdpc3RyeVtncm91cF0pXG4gICAgICAgICAgICB0aGlzLnJlZ2lzdHJ5W2dyb3VwXSA9IFtdO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGFscmVhZHkgaGF2ZSBhIHJlZ2lzdHJhdGlvbiBmb3IgdGhlIGNvbXBvbmVudFxuICAgICAgICAvLyBpZiAodGhpcy5yZWdpc3RyeVtncm91cF0gJiYgdHlwZW9mIHRoaXMucmVnaXN0cnlbZ3JvdXBdWydsb2FkJ10gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIC8vICAgICAvLyBXYXJuIHRoZSBkZXZlbG9wZXIgdGhhdCB0aGUgc3RhdGUgaXMgcHJvYmxlbWF0aWNcbiAgICAgICAgLy8gICAgIHRoaXMuY29uZmlnLmxvZ2dlci53YXJuKFxuICAgICAgICAvLyAgICAgICAgIGBBIHByZXZpb3VzIGVudHJ5IGFscmVhZHkgZXhpc3RzIGZvciAke2lkfSEgVGhlIG9sZCByZWdpc3RyYXRpb24gd2lsbCBiZSBvdmVycmlkZGVuLmAgK1xuICAgICAgICAvLyAgICAgICAgIGBQbGVhc2UgZW5zdXJlIHlvdSB1c2UgZ3JvdXBzIGlmIHlvdSBpbnRlbmQgdG8gaGF2ZSBkdXBsaWNhdGUgY29tcG9uZW50IGlkcy4gYCArXG4gICAgICAgIC8vICAgICAgICAgYElmIHRoaXMgd2FzIGludGVudGlvbmFsLCBmaXJzdCByZW1vdmUgdGhlIG9sZCBjb21wb25lbnQgZnJvbSB0aGUgcmVnaXN0cnkgYmVmb3JlIGFkZGluZyBhIG5ldyBpbnN0YW5jZWBcbiAgICAgICAgLy8gICAgICk7XG5cbiAgICAgICAgLy8gICAgIC8vIElmIHdlJ3JlIGluIGRldiBtb2RlLCBicmVhayB0aGUgbG9hZGVyIHN1cmZhY2VcbiAgICAgICAgLy8gICAgIGlmIChpc0Rldk1vZGUoKSlcbiAgICAgICAgLy8gICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIH1cblxuICAgICAgICB0aGlzLnJlZ2lzdHJ5W2dyb3VwXS5wdXNoKHJlZ2lzdHJhdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYW4gQW5ndWxhciBjb21wb25lbnRcbiAgICAgKiBAcGFyYW0gaWQgaWRlbnRpZmllciB0aGF0IGlzIHVzZWQgdG8gcmVzb2x2ZSB0aGUgY29tcG9uZW50XG4gICAgICogQHBhcmFtIGdyb3VwXG4gICAgICogQHBhcmFtIGNvbXBvbmVudCBBbmd1bGFyIENvbXBvbmVudCBDbGFzcyBjb25zdHJ1Y3RvclxuICAgICAqL1xuICAgIHB1YmxpYyByZWdpc3RlckNvbXBvbmVudDxUIGV4dGVuZHMgeyBuZXcoLi4uYXJnczogYW55W10pOiBJbnN0YW5jZVR5cGU8VD47IH0+KGFyZ3M6IER5bmFtaWNSZWdpc3RyYXRpb25BcmdzPFQ+KSB7XG4gICAgICAgIGlmICh0aGlzLmlzQ29tcG9uZW50UmVnaXN0ZXJlZChhcmdzLmlkLCBhcmdzLmdyb3VwKSkge1xuICAgICAgICAgICAgdGhpcy5sb2coYFdpbGwgbm90IHJlLXJlZ2lzdGVyIGNvbXBvbmVudCAnJHthcmdzLmlkfScgaW4gZ3JvdXAgJyR7YXJncy5ncm91cCB8fCAnZGVmYXVsdCd9JyBgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIE5neExhenlMb2FkZXJTZXJ2aWNlLmFkZENvbXBvbmVudFRvUmVnaXN0cnkoe1xuICAgICAgICAgICAgaWQ6IHN0cmluZ1RvU2x1ZyhhcmdzLmlkKSxcbiAgICAgICAgICAgIG1hdGNoZXI6IGFyZ3MubWF0Y2hlcixcbiAgICAgICAgICAgIGdyb3VwOiBzdHJpbmdUb1NsdWcoYXJncy5ncm91cCB8fCBcImRlZmF1bHRcIiksXG4gICAgICAgICAgICBsb2FkOiBhcmdzLmxvYWQgfHwgKCgpID0+IGFyZ3MuY29tcG9uZW50KVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBpZFxuICAgICAqIEBwYXJhbSBncm91cFxuICAgICAqL1xuICAgIHB1YmxpYyB1bnJlZ2lzdGVyQ29tcG9uZW50KGlkOiBzdHJpbmcsIGdyb3VwID0gXCJkZWZhdWx0XCIpIHtcbiAgICAgICAgY29uc3QgX2lkID0gc3RyaW5nVG9TbHVnKGlkKTtcbiAgICAgICAgY29uc3QgX2dyb3VwID0gc3RyaW5nVG9TbHVnKGdyb3VwKTtcblxuICAgICAgICBpZiAoIXRoaXMucmVzb2x2ZVJlZ2lzdHJhdGlvbkVudHJ5KGlkLCBncm91cCkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgdW5yZWdpc3RlciBjb21wb25lbnQgJHt9ISBDb21wb25lbnQgaXMgbm90IHByZXNlbnQgaW4gcmVnaXN0cnlcIilcblxuICAgICAgICAvLyBUT0RPOiBoYW5kbGUgY2xlYXJpbmcgcnVubmluZyBpbnN0YW5jZXNcbiAgICAgICAgZGVsZXRlIE5neExhenlMb2FkZXJTZXJ2aWNlLnJlZ2lzdHJ5W19ncm91cF1bX2lkXTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgcmVnaXN0cmF0aW9uIGVudHJ5IGZvciBhIGNvbXBvbmVudC5cbiAgICAgKiBSZXR1cm5zIG51bGwgaWYgY29tcG9uZW50IGlzIG5vdCBpbiB0aGUgcmVnaXN0cnkuXG4gICAgICovXG4gICAgcHVibGljIHJlc29sdmVSZWdpc3RyYXRpb25FbnRyeSh2YWx1ZTogc3RyaW5nLCBncm91cCA9IFwiZGVmYXVsdFwiKSB7XG4gICAgICAgIGNvbnN0IF9pZCA9IHN0cmluZ1RvU2x1Zyh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IF9ncm91cCA9IHN0cmluZ1RvU2x1Zyhncm91cCk7XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0R3JvdXAgPSAoTmd4TGF6eUxvYWRlclNlcnZpY2UucmVnaXN0cnlbX2dyb3VwXSB8fCBbXSk7XG5cbiAgICAgICAgbGV0IGl0ZW1zID0gdGFyZ2V0R3JvdXAuZmlsdGVyKHQgPT4ge1xuICAgICAgICAgICAgaWYgKCF0KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIE5vIG1hdGNoZXIsIGNoZWNrIGlkXG4gICAgICAgICAgICBpZiAoIXQubWF0Y2hlcilcbiAgICAgICAgICAgICAgICByZXR1cm4gdFskaWRdID09IF9pZDtcblxuICAgICAgICAgICAgLy8gTWF0Y2hlciBpcyByZWdleFxuICAgICAgICAgICAgaWYgKHQubWF0Y2hlciBpbnN0YW5jZW9mIFJlZ0V4cClcbiAgICAgICAgICAgICAgICByZXR1cm4gdC5tYXRjaGVyLnRlc3QoX2lkKSB8fCB0Lm1hdGNoZXIudGVzdCh2YWx1ZSk7XG5cbiAgICAgICAgICAgIC8vIE1hdGNoZXIgaXMgc3RyaW5nID0+IHJlZ2V4XG4gICAgICAgICAgICBpZiAodHlwZW9mIHQubWF0Y2hlciA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJ4ID0gbmV3IFJlZ0V4cCh0Lm1hdGNoZXIsICd1aScpO1xuICAgICAgICAgICAgICAgIHJldHVybiByeC50ZXN0KF9pZCkgfHwgcngudGVzdCh2YWx1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE1hdGNoZXIgaXMgYXJyYXlcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHQubWF0Y2hlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gISF0Lm1hdGNoZXIuZmluZChlID0+IHN0cmluZ1RvU2x1ZyhlKSA9PSBfaWQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDdXN0b20gbWF0Y2hlciBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0Lm1hdGNoZXIgPT0gXCJmdW5jdGlvblwiKVxuICAgICAgICAgICAgICAgIHJldHVybiB0Lm1hdGNoZXIoX2lkKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgdGhpcy53YXJuKFwiUmVzb2x2ZWQgbXVsdGlwbGUgY29tcG9uZW50cyBmb3IgdGhlIHByb3ZpZGVkIGBbY29tcG9uZW50XWAgYmluZGluZy4gVGhpcyBtYXkgY2F1c2UgVUkgY29uZmxpY3RzLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb3V0ID0gaXRlbXNbMF07XG5cbiAgICAgICAgaWYgKG91dC5tYXRjaGVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBfaWQubWF0Y2gob3V0Lm1hdGNoZXIpIHx8IHZhbHVlLm1hdGNoKG91dC5tYXRjaGVyKTtcblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBlbnRyeTogb3V0LFxuICAgICAgICAgICAgICAgIG1hdGNoR3JvdXBzOiByZXN1bHQ/Lmdyb3Vwc1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGVudHJ5OiBvdXQgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIGNvbXBvbmVudCBpcyBjdXJyZW50bHkgcmVnaXN0ZXJlZFxuICAgICAqIENhbiBiZSB1c2VkIHRvIHZhbGlkYXRlIHJlZ2V4IG1hdGNoZXJzIGFuZCBhbGlhc2VzLlxuICAgICAqL1xuICAgIHB1YmxpYyBpc0NvbXBvbmVudFJlZ2lzdGVyZWQodmFsdWU6IHN0cmluZywgZ3JvdXAgPSBcImRlZmF1bHRcIikge1xuICAgICAgICByZXR1cm4gISF0aGlzLnJlc29sdmVSZWdpc3RyYXRpb25FbnRyeSh2YWx1ZSwgZ3JvdXApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1bmRsZVxuICAgICAqIEByZXR1cm5zIFRoZSBjb21wb25lbnQgYE9iamVjdGAgaWYgYSBjb21wb25lbnQgd2FzIHJlc29sdmVkLCBgbnVsbGAgaWYgbm8gY29tcG9uZW50IHdhcyBmb3VuZFxuICAgICAqIGBmYWxzZWAgaWYgdGhlIHNwZWNpZmllZCBzdHJhdGVneSB3YXMgYW4gaW52YWxpZCBzZWxlY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVzb2x2ZUNvbXBvbmVudChpZDogc3RyaW5nLCBncm91cDogc3RyaW5nLCBtb2R1bGVzOiAoQ29tcGlsZWRDb21wb25lbnQgfCBDb21waWxlZE1vZHVsZSlbXSk6IE9iamVjdCB8IG51bGwgfCBmYWxzZSB7XG5cbiAgICAgICAgc3dpdGNoIChOZ3hMYXp5TG9hZGVyU2VydmljZS5jb25maWcuY29tcG9uZW50UmVzb2x2ZVN0cmF0ZWd5KSB7XG4gICAgICAgICAgICBjYXNlIENvbXBvbmVudFJlc29sdmVTdHJhdGVneS5QaWNrRmlyc3Q6IHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBtb2R1bGVzWzBdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGFjdCBpZCAtPiBjbGFzc25hbWUgbWF0Y2hcbiAgICAgICAgICAgIGNhc2UgQ29tcG9uZW50UmVzb2x2ZVN0cmF0ZWd5Lk1hdGNoSWRUb0NsYXNzTmFtZToge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPVxuICAgICAgICAgICAgICAgICAgICBtb2R1bGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGsgPT4gay5uYW1lID09IGlkKTtcblxuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PSAwKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRnV6enkgaWQgLT4gY2xhc3NuYW1lIG1hdGNoXG4gICAgICAgICAgICBjYXNlIENvbXBvbmVudFJlc29sdmVTdHJhdGVneS5GdXp6eUlkQ2xhc3NOYW1lOiB7XG4gICAgICAgICAgICAgICAgY29uc3QgX2lkID0gaWQucmVwbGFjZSgvW15hLXowLTlfXFwtXS9pZywgJycpO1xuXG4gICAgICAgICAgICAgICAgaWYgKF9pZC5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBOZ3hMYXp5TG9hZGVyU2VydmljZS5jb25maWcubG9nZ2VyLmVycihcIkZ1enp5IGNsYXNzbmFtZSBtYXRjaGluZyBzdHJpcHBlZCBhbGwgc3ltYm9scyBmcm9tIHRoZSBJRCBzcGVjaWZpZWQhXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgcnggPSBuZXcgUmVnRXhwKGBeJHtpZH0oY29tcG9uZW50fG1vZHVsZSk/JGAsIFwiaVwiKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBtb2R1bGVzXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIobW9kID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBraWQgPSBtb2QubmFtZS5yZXBsYWNlKC9bXmEtejAtOV9cXC1dL2lnLCAnJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByeC50ZXN0KGtpZCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBOZ3hMYXp5TG9hZGVyU2VydmljZS5jb25maWcubG9nZ2VyLmVycihcIkZ1enp5IGNsYXNzbmFtZSBtYXRjaGluZyByZXNvbHZlZCBtdWx0aXBsZSB0YXJnZXRzIVwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIE5neExhenlMb2FkZXJTZXJ2aWNlLmNvbmZpZy5sb2dnZXIuZXJyKFwiRnV6enkgY2xhc3NuYW1lIG1hdGNoaW5nIHJlc29sdmVkIG5vIHRhcmdldHMhXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hlc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgQ29tcG9uZW50UmVzb2x2ZVN0cmF0ZWd5LkN1c3RvbToge1xuICAgICAgICAgICAgICAgIHJldHVybiBOZ3hMYXp5TG9hZGVyU2VydmljZS5jb25maWcuY3VzdG9tUmVzb2x2ZXIobW9kdWxlcyBhcyBhbnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==