UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

264 lines 33.7 kB
import { DOCUMENT, registerLocaleData } from '@angular/common'; import { Inject, Injectable, Optional } from '@angular/core'; import { TranslateService as NgxTranslateService } from '@ngx-translate/core'; import { keys } from 'lodash-es'; import { OptionsService } from '../common/options.service'; import { AppStateService } from '../common/ui-state.service'; import { getAngularLocalesLanguageString } from './i18n.module'; import { loadLocale } from './load-locale'; import { defineLocale, deLocale, enGbLocale, esLocale, frLocale, jaLocale, koLocale, nlLocale, plLocale, ptBrLocale, zhCnLocale } from 'ngx-bootstrap/chronos'; import { BsLocaleService } from 'ngx-bootstrap/datepicker'; import * as i0 from "@angular/core"; import * as i1 from "@ngx-translate/core"; import * as i2 from "../common/ui-state.service"; import * as i3 from "../common/options.service"; import * as i4 from "ngx-bootstrap/datepicker"; /** * A service to manage the language of the application. */ export class TranslateService { static { this.SAVE_LANGUAGE_KEY = 'c8y_language'; } static defaultLang() { return window.localStorage.getItem(TranslateService.SAVE_LANGUAGE_KEY); } constructor(ngxTranslate, ui, options, document, bsLocaleService) { this.ngxTranslate = ngxTranslate; this.ui = ui; this.options = options; this.document = document; this.bsLocaleService = bsLocaleService; this.langsDetail = this.options.get('languages', {}); this.langs = keys(this.langsDetail).filter(k => this.langsDetail[k]); this.DEFAULT_SEPARATOR = '_'; const queryStringLang = this.queryStringLang(); if (queryStringLang) { this.saveInLocalStorage(queryStringLang); } } /** * Switches the app to given locale (incl. Angular, Bootstrap, translations). * @param localeCode The locale code. Supported formats: * - two-letter codes for language only, for example: `en`, `de` * - four-letter codes for language and country, separated with underscore or dash, for example: `zh_CN`, `zh_cn`, `zh-CN`, `zh-cn` */ async switchToLanguage(localeCode) { const { langCountryCode: ngxLocaleCode, langCode: ngxLocaleCodeFallback } = this.parseLocaleCode(localeCode, '-'); try { await this.loadLocales(ngxLocaleCode); } catch (e) { if (ngxLocaleCodeFallback !== ngxLocaleCode) { await this.loadLocales(ngxLocaleCodeFallback); } else { throw e; } } const { langCode: bsLocaleCode, langCountryCode: ngxTranslateLocaleCode } = this.parseLocaleCode(localeCode); this.setBsLocale(bsLocaleCode); this.setLanguage(ngxTranslateLocaleCode); } async loadLocales(moduleLang) { const module = await loadLocale(getAngularLocalesLanguageString(moduleLang)); registerLocaleData(module.default); } setLanguage(lang) { this.ngxTranslate.setDefaultLang(this.options.get('defaultLanguage', 'en')); this.ngxTranslate.use(lang).subscribe(() => { this.ui.state$.next({ ...this.ui.state, lang }); }); this.document.documentElement.lang = lang; } /** * Finds the first supported language */ firstSupportedLanguage() { const languages = [this.queryStringLang(), this.localStorageLang()] .concat([this.options.get('defaultLanguage')]) .concat(this.browserLangs()) .concat(['en']) .filter(Boolean) .map(lang => lang.toLowerCase()); const preferredLanguage = languages.find(lang => this.getSupported(lang)); return this.getSupported(preferredLanguage); } /** * Converts a iso language code to a PO language code (e.g. de-de gets de_de). * @param lang The iso language code. */ convertToLanguageCodePO(lang) { const sep = lang.indexOf('-') > -1 ? '-' : this.DEFAULT_SEPARATOR; const [langMain, langSpecific] = lang.split(sep); const langLast = langSpecific ? `${this.DEFAULT_SEPARATOR}${langSpecific}` : ''; return `${langMain}${langLast}`; } /** * Returns the language in the native language. * @param lang The language two-letter code. * @return The native name. */ getNativeLanguage(lang) { const langData = (this.langsDetail || {})[lang] || {}; return langData.nativeName || lang; } saveInLocalStorage(lang) { window.localStorage.setItem(TranslateService.SAVE_LANGUAGE_KEY, lang); } getSupported(localeCode) { if (!localeCode) { return undefined; } const localeCodeParsed = this.parseLocaleCode(localeCode); const localeCodesParsed = this.langs.map(lang => this.parseLocaleCode(lang)); const langCountryCodeMatch = localeCodesParsed.find(({ langCountryCode }) => langCountryCode === localeCodeParsed.langCountryCode); if (langCountryCodeMatch) { return langCountryCodeMatch.langCountryCode; } const langCodeMatch = localeCodesParsed.find(({ langCode }) => langCode === localeCodeParsed.langCode); if (langCodeMatch) { return langCodeMatch.langCountryCode; } return undefined; } /** * Gets the language from the query parameter. * @return The language two-letter code. */ queryStringLang() { return this.getQueryParameter('lang'); } parseLocaleCode(localeCode, outputSeparator = '_') { // - 2 letter language code // - optional region code that's either 2 letters OR 3 digits const matches = localeCode.match(/^([a-z]{2})([_-]([a-z]{2}|[0-9]{3}))?$/i); if (!matches) { throw new Error(`Could not parse locale code "${localeCode}". Expected format: language code (2 letters) optionally followed by region code (2 letters or 3 digits) separated with "_" or "-", e.g. "en-US" or "es-419".`); } const langCode = matches[1].toLowerCase(); const regionCode = matches[3]?.toUpperCase(); const langCountryCode = `${langCode}${regionCode ? `${outputSeparator}${regionCode}` : ''}`; return { langCode, langCountryCode }; } /** * Gets the language from local storage. * @return The language two-letter code. */ localStorageLang() { return window.localStorage.getItem(TranslateService.SAVE_LANGUAGE_KEY); } /** * Determines which language is set in the browser. * @return The languages the browser supports as string array. */ browserLangs() { const { navigator } = window; const browserLanguagePropertyKeys = [ 'languages', 'language', 'browserLanguage', 'systemLanguage', 'userLanguage' ]; return browserLanguagePropertyKeys.reduce((languages, property) => { const propertyLanguages = navigator[property]; if (typeof propertyLanguages === 'string') { languages.push(propertyLanguages); } else if (Array.isArray(propertyLanguages)) { languages = languages.concat(propertyLanguages); } return languages; }, []); } getQueryParameter(queryKey) { // TODO: replace this with URLSearchParams, ie 11 still doesn't support :() const query = window.location.search.substring(1); let result; query.split('&').find(pair => { const [key, value] = pair.split('='); if (key === queryKey) { result = value; } return result; }); return result; } /** * Sets locale for ngx-bootstrap. * @param lang A two-letter language code. * @private */ setBsLocale(lang) { switch (lang) { case 'de': { defineLocale(lang, deLocale); this.bsLocaleService.use(lang); break; } case 'en': { // 'en-gb' is created because overwriting default 'en' breaks date-picker somehow defineLocale('en-gb', enGbLocale); this.bsLocaleService.use('en-gb'); break; } case 'es': { defineLocale(lang, esLocale); this.bsLocaleService.use(lang); break; } case 'fr': { defineLocale(lang, frLocale); this.bsLocaleService.use(lang); break; } case 'ja': { defineLocale(lang, jaLocale); this.bsLocaleService.use(lang); break; } case 'ko': { defineLocale(lang, koLocale); this.bsLocaleService.use(lang); break; } case 'nl': { defineLocale(lang, nlLocale); this.bsLocaleService.use(lang); break; } case 'pl': { defineLocale(lang, plLocale); this.bsLocaleService.use(lang); break; } case 'pt': { defineLocale(lang, ptBrLocale); this.bsLocaleService.use(lang); break; } case 'zh': { defineLocale(lang, zhCnLocale); this.bsLocaleService.use(lang); break; } default: { defineLocale('en-gb', enGbLocale); this.bsLocaleService.use('en-gb'); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslateService, deps: [{ token: i1.TranslateService }, { token: i2.AppStateService }, { token: i3.OptionsService }, { token: DOCUMENT }, { token: i4.BsLocaleService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslateService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslateService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i2.AppStateService }, { type: i3.OptionsService }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: i4.BsLocaleService, decorators: [{ type: Optional }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL2kxOG4vdHJhbnNsYXRlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBQUUsZ0JBQWdCLElBQUksbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM5RSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUNMLFlBQVksRUFDWixRQUFRLEVBQ1IsVUFBVSxFQUNWLFFBQVEsRUFDUixRQUFRLEVBQ1IsUUFBUSxFQUNSLFFBQVEsRUFDUixRQUFRLEVBQ1IsUUFBUSxFQUNSLFVBQVUsRUFDVixVQUFVLEVBQ1gsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7OztBQUUzRDs7R0FFRztBQUlILE1BQU0sT0FBTyxnQkFBZ0I7YUFDcEIsc0JBQWlCLEdBQUcsY0FBYyxBQUFqQixDQUFrQjtJQUMxQyxNQUFNLENBQUMsV0FBVztRQUNoQixPQUFPLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDekUsQ0FBQztJQUtELFlBQ1UsWUFBaUMs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QUMsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQy9CLE1BQU07WUFDUixDQUFDO1lBQ0QsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNWLFlBQVksQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUMvQixNQUFNO1lBQ1IsQ0FBQztZQUNELEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDVixZQUFZLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUMvQixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDL0IsTUFBTTtZQUNSLENBQUM7WUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNSLFlBQVksQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzsrR0FqUVUsZ0JBQWdCLCtHQWFqQixRQUFRO21IQWJQLGdCQUFnQixjQUZmLE1BQU07OzRGQUVQLGdCQUFnQjtrQkFINUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQWNJLE1BQU07MkJBQUMsUUFBUTs7MEJBQ2YsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERPQ1VNRU5ULCByZWdpc3RlckxvY2FsZURhdGEgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSBhcyBOZ3hUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBrZXlzIH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IE9wdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi4vY29tbW9uL29wdGlvbnMuc2VydmljZSc7XG5pbXBvcnQgeyBBcHBTdGF0ZVNlcnZpY2UgfSBmcm9tICcuLi9jb21tb24vdWktc3RhdGUuc2VydmljZSc7XG5pbXBvcnQgeyBnZXRBbmd1bGFyTG9jYWxlc0xhbmd1YWdlU3RyaW5nIH0gZnJvbSAnLi9pMThuLm1vZHVsZSc7XG5pbXBvcnQgeyBsb2FkTG9jYWxlIH0gZnJvbSAnLi9sb2FkLWxvY2FsZSc7XG5pbXBvcnQge1xuICBkZWZpbmVMb2NhbGUsXG4gIGRlTG9jYWxlLFxuICBlbkdiTG9jYWxlLFxuICBlc0xvY2FsZSxcbiAgZnJMb2NhbGUsXG4gIGphTG9jYWxlLFxuICBrb0xvY2FsZSxcbiAgbmxMb2NhbGUsXG4gIHBsTG9jYWxlLFxuICBwdEJyTG9jYWxlLFxuICB6aENuTG9jYWxlXG59IGZyb20gJ25neC1ib290c3RyYXAvY2hyb25vcyc7XG5pbXBvcnQgeyBCc0xvY2FsZVNlcnZpY2UgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2RhdGVwaWNrZXInO1xuXG4vKipcbiAqIEEgc2VydmljZSB0byBtYW5hZ2UgdGhlIGxhbmd1YWdlIG9mIHRoZSBhcHBsaWNhdGlvbi5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgVHJhbnNsYXRlU2VydmljZSB7XG4gIHN0YXRpYyBTQVZFX0xBTkdVQUdFX0tFWSA9ICdjOHlfbGFuZ3VhZ2UnO1xuICBzdGF0aWMgZGVmYXVsdExhbmcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShUcmFuc2xhdGVTZXJ2aWNlLlNBVkVfTEFOR1VBR0VfS0VZKTtcbiAgfVxuICBsYW5nc0RldGFpbDogYW55ID0gdGhpcy5vcHRpb25zLmdldCgnbGFuZ3VhZ2VzJywge30pO1xuICBsYW5nczogYW55ID0ga2V5cyh0aGlzLmxhbmdzRGV0YWlsKS5maWx0ZXIoayA9PiB0aGlzLmxhbmdzRGV0YWlsW2tdKTtcbiAgcHJpdmF0ZSBERUZBVUxUX1NFUEFSQVRPUiA9ICdfJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG5neFRyYW5zbGF0ZTogTmd4VHJhbnNsYXRlU2VydmljZSxcbiAgICBwcml2YXRlIHVpOiBBcHBTdGF0ZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvcHRpb25zOiBPcHRpb25zU2VydmljZSxcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCxcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGJzTG9jYWxlU2VydmljZTogQnNMb2NhbGVTZXJ2aWNlXG4gICkge1xuICAgIGNvbnN0IHF1ZXJ5U3RyaW5nTGFuZyA9IHRoaXMucXVlcnlTdHJpbmdMYW5nKCk7XG4gICAgaWYgKHF1ZXJ5U3RyaW5nTGFuZykge1xuICAgICAgdGhpcy5zYXZlSW5Mb2NhbFN0b3JhZ2UocXVlcnlTdHJpbmdMYW5nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3dpdGNoZXMgdGhlIGFwcCB0byBnaXZlbiBsb2NhbGUgKGluY2wuIEFuZ3VsYXIsIEJvb3RzdHJhcCwgdHJhbnNsYXRpb25zKS5cbiAgICogQHBhcmFtIGxvY2FsZUNvZGUgVGhlIGxvY2FsZSBjb2RlLiBTdXBwb3J0ZWQgZm9ybWF0czpcbiAgICogLSB0d28tbGV0dGVyIGNvZGVzIGZvciBsYW5ndWFnZSBvbmx5LCBmb3IgZXhhbXBsZTogYGVuYCwgYGRlYFxuICAgKiAtIGZvdXItbGV0dGVyIGNvZGVzIGZvciBsYW5ndWFnZSBhbmQgY291bnRyeSwgc2VwYXJhdGVkIHdpdGggdW5kZXJzY29yZSBvciBkYXNoLCBmb3IgZXhhbXBsZTogYHpoX0NOYCwgYHpoX2NuYCwgYHpoLUNOYCwgYHpoLWNuYFxuICAgKi9cbiAgYXN5bmMgc3dpdGNoVG9MYW5ndWFnZShsb2NhbGVDb2RlOiBzdHJpbmcpIHtcbiAgICBjb25zdCB7IGxhbmdDb3VudHJ5Q29kZTogbmd4TG9jYWxlQ29kZSwgbGFuZ0NvZGU6IG5neExvY2FsZUNvZGVGYWxsYmFjayB9ID1cbiAgICAgIHRoaXMucGFyc2VMb2NhbGVDb2RlKGxvY2FsZUNvZGUsICctJyk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubG9hZExvY2FsZXMobmd4TG9jYWxlQ29kZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKG5neExvY2FsZUNvZGVGYWxsYmFjayAhPT0gbmd4TG9jYWxlQ29kZSkge1xuICAgICAgICBhd2FpdCB0aGlzLmxvYWRMb2NhbGVzKG5neExvY2FsZUNvZGVGYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHsgbGFuZ0NvZGU6IGJzTG9jYWxlQ29kZSwgbGFuZ0NvdW50cnlDb2RlOiBuZ3hUcmFuc2xhdGVMb2NhbGVDb2RlIH0gPVxuICAgICAgdGhpcy5wYXJzZUxvY2FsZUNvZGUobG9jYWxlQ29kZSk7XG4gICAgdGhpcy5zZXRCc0xvY2FsZShic0xvY2FsZUNvZGUpO1xuICAgIHRoaXMuc2V0TGFuZ3VhZ2Uobmd4VHJhbnNsYXRlTG9jYWxlQ29kZSk7XG4gIH1cblxuICBhc3luYyBsb2FkTG9jYWxlcyhtb2R1bGVMYW5nKSB7XG4gICAgY29uc3QgbW9kdWxlOiBhbnkgPSBhd2FpdCBsb2FkTG9jYWxlKGdldEFuZ3VsYXJMb2NhbGVzTGFuZ3VhZ2VTdHJpbmcobW9kdWxlTGFuZykpO1xuICAgIHJlZ2lzdGVyTG9jYWxlRGF0YShtb2R1bGUuZGVmYXVsdCk7XG4gIH1cblxuICBzZXRMYW5ndWFnZShsYW5nOiBzdHJpbmcpIHtcbiAgICB0aGlzLm5neFRyYW5zbGF0ZS5zZXREZWZhdWx0TGFuZyh0aGlzLm9wdGlvbnMuZ2V0KCdkZWZhdWx0TGFuZ3VhZ2UnLCAnZW4nKSk7XG4gICAgdGhpcy5uZ3hUcmFuc2xhdGUudXNlKGxhbmcpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLnVpLnN0YXRlJC5uZXh0KHsgLi4udGhpcy51aS5zdGF0ZSwgbGFuZyB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmxhbmcgPSBsYW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBmaXJzdCBzdXBwb3J0ZWQgbGFuZ3VhZ2VcbiAgICovXG4gIGZpcnN0U3VwcG9ydGVkTGFuZ3VhZ2UoKSB7XG4gICAgY29uc3QgbGFuZ3VhZ2VzID0gW3RoaXMucXVlcnlTdHJpbmdMYW5nKCksIHRoaXMubG9jYWxTdG9yYWdlTGFuZygpXVxuICAgICAgLmNvbmNhdChbdGhpcy5vcHRpb25zLmdldCgnZGVmYXVsdExhbmd1YWdlJyldKVxuICAgICAgLmNvbmNhdCh0aGlzLmJyb3dzZXJMYW5ncygpKVxuICAgICAgLmNvbmNhdChbJ2VuJ10pXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAubWFwKGxhbmcgPT4gbGFuZy50b0xvd2VyQ2FzZSgpKTtcblxuICAgIGNvbnN0IHByZWZlcnJlZExhbmd1YWdlID0gbGFuZ3VhZ2VzLmZpbmQobGFuZyA9PiB0aGlzLmdldFN1cHBvcnRlZChsYW5nKSk7XG4gICAgcmV0dXJuIHRoaXMuZ2V0U3VwcG9ydGVkKHByZWZlcnJlZExhbmd1YWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGlzbyBsYW5ndWFnZSBjb2RlIHRvIGEgUE8gbGFuZ3VhZ2UgY29kZSAoZS5nLiBkZS1kZSBnZXRzIGRlX2RlKS5cbiAgICogQHBhcmFtIGxhbmcgVGhlIGlzbyBsYW5ndWFnZSBjb2RlLlxuICAgKi9cbiAgY29udmVydFRvTGFuZ3VhZ2VDb2RlUE8obGFuZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBzZXAgPSBsYW5nLmluZGV4T2YoJy0nKSA+IC0xID8gJy0nIDogdGhpcy5ERUZBVUxUX1NFUEFSQVRPUjtcbiAgICBjb25zdCBbbGFuZ01haW4sIGxhbmdTcGVjaWZpY10gPSBsYW5nLnNwbGl0KHNlcCk7XG4gICAgY29uc3QgbGFuZ0xhc3QgPSBsYW5nU3BlY2lmaWMgPyBgJHt0aGlzLkRFRkFVTFRfU0VQQVJBVE9SfSR7bGFuZ1NwZWNpZmljfWAgOiAnJztcbiAgICByZXR1cm4gYCR7bGFuZ01haW59JHtsYW5nTGFzdH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGxhbmd1YWdlIGluIHRoZSBuYXRpdmUgbGFuZ3VhZ2UuXG4gICAqIEBwYXJhbSBsYW5nIFRoZSBsYW5ndWFnZSB0d28tbGV0dGVyIGNvZGUuXG4gICAqIEByZXR1cm4gVGhlIG5hdGl2ZSBuYW1lLlxuICAgKi9cbiAgZ2V0TmF0aXZlTGFuZ3VhZ2UobGFuZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBsYW5nRGF0YSA9ICh0aGlzLmxhbmdzRGV0YWlsIHx8IHt9KVtsYW5nXSB8fCB7fTtcbiAgICByZXR1cm4gbGFuZ0RhdGEubmF0aXZlTmFtZSB8fCBsYW5nO1xuICB9XG5cbiAgc2F2ZUluTG9jYWxTdG9yYWdlKGxhbmc6IHN0cmluZykge1xuICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShUcmFuc2xhdGVTZXJ2aWNlLlNBVkVfTEFOR1VBR0VfS0VZLCBsYW5nKTtcbiAgfVxuXG4gIGdldFN1cHBvcnRlZChsb2NhbGVDb2RlOiBzdHJpbmcpIHtcbiAgICBpZiAoIWxvY2FsZUNvZGUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IGxvY2FsZUNvZGVQYXJzZWQgPSB0aGlzLnBhcnNlTG9jYWxlQ29kZShsb2NhbGVDb2RlKTtcbiAgICBjb25zdCBsb2NhbGVDb2Rlc1BhcnNlZCA9IHRoaXMubGFuZ3MubWFwKGxhbmcgPT4gdGhpcy5wYXJzZUxvY2FsZUNvZGUobGFuZykpO1xuICAgIGNvbnN0IGxhbmdDb3VudHJ5Q29kZU1hdGNoID0gbG9jYWxlQ29kZXNQYXJzZWQuZmluZChcbiAgICAgICh7IGxhbmdDb3VudHJ5Q29kZSB9KSA9PiBsYW5nQ291bnRyeUNvZGUgPT09IGxvY2FsZUNvZGVQYXJzZWQubGFuZ0NvdW50cnlDb2RlXG4gICAgKTtcbiAgICBpZiAobGFuZ0NvdW50cnlDb2RlTWF0Y2gpIHtcbiAgICAgIHJldHVybiBsYW5nQ291bnRyeUNvZGVNYXRjaC5sYW5nQ291bnRyeUNvZGU7XG4gICAgfVxuICAgIGNvbnN0IGxhbmdDb2RlTWF0Y2ggPSBsb2NhbGVDb2Rlc1BhcnNlZC5maW5kKFxuICAgICAgKHsgbGFuZ0NvZGUgfSkgPT4gbGFuZ0NvZGUgPT09IGxvY2FsZUNvZGVQYXJzZWQubGFuZ0NvZGVcbiAgICApO1xuICAgIGlmIChsYW5nQ29kZU1hdGNoKSB7XG4gICAgICByZXR1cm4gbGFuZ0NvZGVNYXRjaC5sYW5nQ291bnRyeUNvZGU7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbGFuZ3VhZ2UgZnJvbSB0aGUgcXVlcnkgcGFyYW1ldGVyLlxuICAgKiBAcmV0dXJuIFRoZSBsYW5ndWFnZSB0d28tbGV0dGVyIGNvZGUuXG4gICAqL1xuICBxdWVyeVN0cmluZ0xhbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0UXVlcnlQYXJhbWV0ZXIoJ2xhbmcnKTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VMb2NhbGVDb2RlKFxuICAgIGxvY2FsZUNvZGU6IHN0cmluZyxcbiAgICBvdXRwdXRTZXBhcmF0b3IgPSAnXydcbiAgKTogeyBsYW5nQ29kZTogc3RyaW5nOyBsYW5nQ291bnRyeUNvZGU6IHN0cmluZyB9IHtcbiAgICAvLyAtIDIgbGV0dGVyIGxhbmd1YWdlIGNvZGVcbiAgICAvLyAtIG9wdGlvbmFsIHJlZ2lvbiBjb2RlIHRoYXQncyBlaXRoZXIgMiBsZXR0ZXJzIE9SIDMgZGlnaXRzXG4gICAgY29uc3QgbWF0Y2hlcyA9IGxvY2FsZUNvZGUubWF0Y2goL14oW2Etel17Mn0pKFtfLV0oW2Etel17Mn18WzAtOV17M30pKT8kL2kpO1xuICAgIGlmICghbWF0Y2hlcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IHBhcnNlIGxvY2FsZSBjb2RlIFwiJHtsb2NhbGVDb2RlfVwiLiBFeHBlY3RlZCBmb3JtYXQ6IGxhbmd1YWdlIGNvZGUgKDIgbGV0dGVycykgb3B0aW9uYWxseSBmb2xsb3dlZCBieSByZWdpb24gY29kZSAoMiBsZXR0ZXJzIG9yIDMgZGlnaXRzKSBzZXBhcmF0ZWQgd2l0aCBcIl9cIiBvciBcIi1cIiwgZS5nLiBcImVuLVVTXCIgb3IgXCJlcy00MTlcIi5gXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBsYW5nQ29kZSA9IG1hdGNoZXNbMV0udG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCByZWdpb25Db2RlID0gbWF0Y2hlc1szXT8udG9VcHBlckNhc2UoKTtcbiAgICBjb25zdCBsYW5nQ291bnRyeUNvZGUgPSBgJHtsYW5nQ29kZX0ke3JlZ2lvbkNvZGUgPyBgJHtvdXRwdXRTZXBhcmF0b3J9JHtyZWdpb25Db2RlfWAgOiAnJ31gO1xuICAgIHJldHVybiB7IGxhbmdDb2RlLCBsYW5nQ291bnRyeUNvZGUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsYW5ndWFnZSBmcm9tIGxvY2FsIHN0b3JhZ2UuXG4gICAqIEByZXR1cm4gVGhlIGxhbmd1YWdlIHR3by1sZXR0ZXIgY29kZS5cbiAgICovXG4gIHByaXZhdGUgbG9jYWxTdG9yYWdlTGFuZygpIHtcbiAgICByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFRyYW5zbGF0ZVNlcnZpY2UuU0FWRV9MQU5HVUFHRV9LRVkpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hpY2ggbGFuZ3VhZ2UgaXMgc2V0IGluIHRoZSBicm93c2VyLlxuICAgKiBAcmV0dXJuIFRoZSBsYW5ndWFnZXMgdGhlIGJyb3dzZXIgc3VwcG9ydHMgYXMgc3RyaW5nIGFycmF5LlxuICAgKi9cbiAgcHJpdmF0ZSBicm93c2VyTGFuZ3MoKSB7XG4gICAgY29uc3QgeyBuYXZpZ2F0b3IgfSA9IHdpbmRvdztcbiAgICBjb25zdCBicm93c2VyTGFuZ3VhZ2VQcm9wZXJ0eUtleXMgPSBbXG4gICAgICAnbGFuZ3VhZ2VzJyxcbiAgICAgICdsYW5ndWFnZScsXG4gICAgICAnYnJvd3Nlckxhbmd1YWdlJyxcbiAgICAgICdzeXN0ZW1MYW5ndWFnZScsXG4gICAgICAndXNlckxhbmd1YWdlJ1xuICAgIF07XG4gICAgcmV0dXJuIGJyb3dzZXJMYW5ndWFnZVByb3BlcnR5S2V5cy5yZWR1Y2UoKGxhbmd1YWdlcywgcHJvcGVydHkpID0+IHtcbiAgICAgIGNvbnN0IHByb3BlcnR5TGFuZ3VhZ2VzID0gbmF2aWdhdG9yW3Byb3BlcnR5XTtcbiAgICAgIGlmICh0eXBlb2YgcHJvcGVydHlMYW5ndWFnZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxhbmd1YWdlcy5wdXNoKHByb3BlcnR5TGFuZ3VhZ2VzKTtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwcm9wZXJ0eUxhbmd1YWdlcykpIHtcbiAgICAgICAgbGFuZ3VhZ2VzID0gbGFuZ3VhZ2VzLmNvbmNhdChwcm9wZXJ0eUxhbmd1YWdlcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbGFuZ3VhZ2VzO1xuICAgIH0sIFtdKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UXVlcnlQYXJhbWV0ZXIocXVlcnlLZXkpIHtcbiAgICAvLyBUT0RPOiByZXBsYWNlIHRoaXMgd2l0aCBVUkxTZWFyY2hQYXJhbXMsIGllIDExIHN0aWxsIGRvZXNuJ3Qgc3VwcG9ydCA6KClcbiAgICBjb25zdCBxdWVyeSA9IHdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyaW5nKDEpO1xuICAgIGxldCByZXN1bHQ7XG4gICAgcXVlcnkuc3BsaXQoJyYnKS5maW5kKHBhaXIgPT4ge1xuICAgICAgY29uc3QgW2tleSwgdmFsdWVdID0gcGFpci5zcGxpdCgnPScpO1xuICAgICAgaWYgKGtleSA9PT0gcXVlcnlLZXkpIHtcbiAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBsb2NhbGUgZm9yIG5neC1ib290c3RyYXAuXG4gICAqIEBwYXJhbSBsYW5nIEEgdHdvLWxldHRlciBsYW5ndWFnZSBjb2RlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBzZXRCc0xvY2FsZShsYW5nKSB7XG4gICAgc3dpdGNoIChsYW5nKSB7XG4gICAgICBjYXNlICdkZSc6IHtcbiAgICAgICAgZGVmaW5lTG9jYWxlKGxhbmcsIGRlTG9jYWxlKTtcbiAgICAgICAgdGhpcy5ic0xvY2FsZVNlcnZpY2UudXNlKGxhbmcpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VuJzoge1xuICAgICAgICAvLyAnZW4tZ2InIGlzIGNyZWF0ZWQgYmVjYXVzZSBvdmVyd3JpdGluZyBkZWZhdWx0ICdlbicgYnJlYWtzIGRhdGUtcGlja2VyIHNvbWVob3dcbiAgICAgICAgZGVmaW5lTG9jYWxlKCdlbi1nYicsIGVuR2JMb2NhbGUpO1xuICAgICAgICB0aGlzLmJzTG9jYWxlU2VydmljZS51c2UoJ2VuLWdiJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnZXMnOiB7XG4gICAgICAgIGRlZmluZUxvY2FsZShsYW5nLCBlc0xvY2FsZSk7XG4gICAgICAgIHRoaXMuYnNMb2NhbGVTZXJ2aWNlLnVzZShsYW5nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdmcic6IHtcbiAgICAgICAgZGVmaW5lTG9jYWxlKGxhbmcsIGZyTG9jYWxlKTtcbiAgICAgICAgdGhpcy5ic0xvY2FsZVNlcnZpY2UudXNlKGxhbmcpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2phJzoge1xuICAgICAgICBkZWZpbmVMb2NhbGUobGFuZywgamFMb2NhbGUpO1xuICAgICAgICB0aGlzLmJzTG9jYWxlU2VydmljZS51c2UobGFuZyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAna28nOiB7XG4gICAgICAgIGRlZmluZUxvY2FsZShsYW5nLCBrb0xvY2FsZSk7XG4gICAgICAgIHRoaXMuYnNMb2NhbGVTZXJ2aWNlLnVzZShsYW5nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdubCc6IHtcbiAgICAgICAgZGVmaW5lTG9jYWxlKGxhbmcsIG5sTG9jYWxlKTtcbiAgICAgICAgdGhpcy5ic0xvY2FsZVNlcnZpY2UudXNlKGxhbmcpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3BsJzoge1xuICAgICAgICBkZWZpbmVMb2NhbGUobGFuZywgcGxMb2NhbGUpO1xuICAgICAgICB0aGlzLmJzTG9jYWxlU2VydmljZS51c2UobGFuZyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAncHQnOiB7XG4gICAgICAgIGRlZmluZUxvY2FsZShsYW5nLCBwdEJyTG9jYWxlKTtcbiAgICAgICAgdGhpcy5ic0xvY2FsZVNlcnZpY2UudXNlKGxhbmcpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3poJzoge1xuICAgICAgICBkZWZpbmVMb2NhbGUobGFuZywgemhDbkxvY2FsZSk7XG4gICAgICAgIHRoaXMuYnNMb2NhbGVTZXJ2aWNlLnVzZShsYW5nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGRlZmluZUxvY2FsZSgnZW4tZ2InLCBlbkdiTG9jYWxlKTtcbiAgICAgICAgdGhpcy5ic0xvY2FsZVNlcnZpY2UudXNlKCdlbi1nYicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19