UNPKG

@dotgov/core

Version:

DGS core.

307 lines 38.4 kB
import { Inject, Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { StorageService } from './storage.service'; import { LoginMetadata } from './../models/login.metadata'; import { AppConfigService } from './settings.service'; export class ApiResponse { constructor(data, error) { this.data = data; this.error = error; } } export class ApiService extends StorageService { constructor(httpClient, appConfig, customAuthenticator, environment) { super(); this.httpClient = httpClient; this.appConfig = appConfig; this.customAuthenticator = customAuthenticator; this.environment = environment; this.sanitizeMark = '___mk___'; } /** * Make GET request to api * @param point * @param args * @param parameters * @param options */ get(point, args = [], parameters = {}, options = {}) { return this.request('GET', point, parameters, options, undefined, ...args); } /** * Make DELETE request to api * @param point * @param args * @param parameters * @param options */ delete(point, args = [], parameters = {}, options = {}, body = {}) { return this.request('DELETE', point, parameters, options, body, ...args); } /** * Make OPTIONS request to api * @param point * @param args * @param parameters * @param options */ options(point, args = [], parameters = {}, options = {}) { return this.request('OPTIONS', point, parameters, options, undefined, ...args); } /** * Make POST request to api * @param point * @param args * @param parameters * @param options */ post(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('POST', point, parameters, options, body, ...args); } /** * Make PATCH request to api * @param point * @param args * @param parameters * @param options */ patch(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('PATCH', point, parameters, options, body, ...args); } /** * Make PUT request to api * @param point * @param args * @param parameters * @param options */ put(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('PUT', point, parameters, options, body, ...args); } /** * Return generated url * @param point * @param args * @param parameters * @param body * @param options */ getURL(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('getURL', point, parameters, options, body, ...args); } get apiRenameList() { return ['Name', 'Title']; } get API() { return AppConfigService.settings.apiUrl; } rename(origin, target) { this.languages.forEach(lang => { const from = `${origin}_${lang}`; const to = `${origin}`; if (target) { return; } if (target.hasOwnProperty(from) && !target.hasOwnProperty(to)) { target[to] = target[from]; delete target[from]; } }); } /** * Generates final url from api_url + view + query parameters; * @param url * @param parameters * @param args */ generateUrl(url, parameters, ...args) { const endUrl = `${url}${args.length ? `/${args.join('/')}` : ''}`; const queryParams = Object.keys(parameters) .map(key => `${key}=${this.sanitize(parameters[key])}`) .join('&'); return `${endUrl}${queryParams ? `?${queryParams}` : ''}`; } sanitize(item) { const exists = item !== undefined && item !== null; const isNum = val => val.constructor === Number; const isString = val => val.constructor === String; if (!exists) { return item; } if (isString(item)) { return item.trim(); } if (isNum(item)) { return item; } if (item && Array.isArray(item)) { item = item.map(curr => { if (!curr) { return curr; } if (curr.hasOwnProperty('value')) { curr.value = !!curr.value ? curr.value.toString() : null; } return curr; }); } return JSON.stringify(item); } /** * If data contains fields like Name_ru/Name_ro/Name_en transform it into Name. * @param data */ resolve(response) { if (response && response.data && Array.isArray(response.data)) { response.data.forEach(item => { this.apiRenameList.forEach(renameOrigin => { this.rename(renameOrigin, item); }); }); } // Already been sanitized if (response && response.hasOwnProperty(this.sanitizeMark)) { return response; } return { data: response, error: null, [this.sanitizeMark]: true, }; } /** * Private Abstract request function * @param method * @param point * @param parameters * @param options * @param args */ request(method, point, parameters, options, body = null, ...args) { if (!method) { console.warn('Something went wrong with API service.'); return; } let apiUrl = this.API; // If is already complete url i should not concat with api url. const fullUrl = new RegExp('^(?:[a-z]+:)?//', 'i'); if (fullUrl.test(point)) { apiUrl = ''; } method = method.toLowerCase(); const url = this.generateUrl((options['apiUrl'] || apiUrl) + point, parameters, ...args); if (method === 'geturl') { return url; } const cacheUrl = `${url}|${method}`; return new Promise(resolve => { const cache = super.get(cacheUrl); const progress = super.getProgress(cacheUrl); const skipCache = options['skipCache'] || false; if (cache && skipCache !== true) { // Extract response from already finished request return resolve(cache); } else if (progress && skipCache !== true) { // Extract response from already existing request in progress progress.subscribe(response => { super.deleteProgress(cacheUrl); const resolvedData = this.resolve(response); return resolve(resolvedData); }); } else { const cachingMethod = method === 'get' || method === 'options'; let callParameters = []; // Add headers const defaultHeaders = { 'Pragma': 'no-cache', 'Cache-control': -1, 'ngsw-bypass': '' }; const headers = Object.assign(defaultHeaders, options['headers'] || {}); this.authenticator(headers, options); options['headers'] = new HttpHeaders(this.cleanHeaders(headers)); if (cachingMethod) { callParameters = [url, options]; // Request not in cache/progress so we set it. super.setProgress(cacheUrl); } else if (method === 'delete') { callParameters = [url, options, body || {}]; } else { callParameters = [url, body || {}, options]; } this.httpClient[method](...callParameters) .toPromise() .then(rawData => { const resolvedData = this.resolve(rawData); if (cachingMethod) { super.set(cacheUrl, resolvedData); } const getProgress = super.getProgress(cacheUrl); if (getProgress) { getProgress.emit(resolvedData); super.deleteProgress(cacheUrl); } return resolve(resolvedData); }) .catch(error => { const res = { data: null, error }; const getProgress = super.getProgress(cacheUrl); if (getProgress) { getProgress.emit(res); super.deleteProgress(cacheUrl); } return resolve(res); }); } }); } authenticator(headers, options) { if (!this.customAuthenticator) { return this.defaultAuthenticator(headers, options); } return this.customAuthenticator(headers, options); } defaultAuthenticator(headers, options) { const auth = JSON.parse(localStorage.getItem('auth')); const externalSessionIndex = JSON.parse(localStorage.getItem(LoginMetadata.externalSessionIndexKey)); if (auth && !headers.hasOwnProperty('Authorization')) { headers['Authorization'] = `${auth.tokenType} ${auth.token}`; } if (externalSessionIndex && !headers.hasOwnProperty(LoginMetadata.externalSessionIndexKey)) { headers[`x-${LoginMetadata.externalSessionIndexKey}`] = `${externalSessionIndex}`; } const contextFromStorage = localStorage.getItem(LoginMetadata.userContext); const userContext = localStorage.getItem(LoginMetadata.activeRole) || (contextFromStorage && contextFromStorage !== 'undefined' && contextFromStorage !== 'null' ? JSON.parse(contextFromStorage) : {}).role; if (!options['skipRole'] && userContext) { headers['x-Current-Role'] = `${userContext}`; } } cleanHeaders(headers) { const cleaned = {}; Object.keys(headers).forEach(key => { const value = headers[key]; if (value !== null && value !== undefined) { cleaned[key] = value; } }); return cleaned; } get languages() { return ['en', 'ro', 'ru']; } } ApiService.decorators = [ { type: Injectable } ]; ApiService.ctorParameters = () => [ { type: HttpClient }, { type: AppConfigService }, { type: undefined, decorators: [{ type: Inject, args: ['authenticator',] }] }, { type: undefined, decorators: [{ type: Inject, args: ['environment',] }] } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2FwaS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDL0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUV0RCxNQUFNLE9BQU8sV0FBVztJQUN0QixZQUNTLElBQTRDLEVBQzVDLEtBQXVCO1FBRHZCLFNBQUksR0FBSixJQUFJLENBQXdDO1FBQzVDLFVBQUssR0FBTCxLQUFLLENBQWtCO0lBQzVCLENBQUM7Q0FDTjtBQUdELE1BQU0sT0FBTyxVQUFXLFNBQVEsY0FBYztJQUc1QyxZQUNVLFVBQXNCLEVBQ3RCLFNBQTJCLEVBQ0YsbUJBQW1CLEVBQ3JCLFdBQTRCO1FBRTNELEtBQUssRUFBRSxDQUFDO1FBTEEsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0QixjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQUNGLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBQTtRQUNyQixnQkFBVyxHQUFYLFdBQVcsQ0FBaUI7UUFOckQsaUJBQVksR0FBRyxVQUFVLENBQUM7SUFTbEMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILEdBQUcsQ0FDRCxLQUFhLEVBQ2IsT0FBaUIsRUFBRSxFQUNuQixhQUFxQixFQUFFLEVBQ3ZCLFVBQWtCLEVBQUU7UUFFcEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxTQUFT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YUFBYSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IElER1NFbnZpcm9ubWVudCB9IGZyb20gJy4vLi4vbW9kZWxzL2Vudmlyb25tZW50JztcclxuaW1wb3J0IHsgTG9naW5NZXRhZGF0YSB9IGZyb20gJy4vLi4vbW9kZWxzL2xvZ2luLm1ldGFkYXRhJztcclxuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uL21vZGVscy9hdXRoJztcclxuaW1wb3J0IHsgQXBwQ29uZmlnU2VydmljZSB9IGZyb20gJy4vc2V0dGluZ3Muc2VydmljZSc7XHJcblxyXG5leHBvcnQgY2xhc3MgQXBpUmVzcG9uc2Uge1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHVibGljIGRhdGE/OiB7IGNvdW50OiBudW1iZXIsIGRhdGE6IE9iamVjdCB9IHwgYW55LFxyXG4gICAgcHVibGljIGVycm9yPzogYW55IHwgdW5kZWZpbmVkLFxyXG4gICkgeyB9XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEFwaVNlcnZpY2UgZXh0ZW5kcyBTdG9yYWdlU2VydmljZSB7XHJcbiAgcHJpdmF0ZSBzYW5pdGl6ZU1hcmsgPSAnX19fbWtfX18nO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgaHR0cENsaWVudDogSHR0cENsaWVudCxcclxuICAgIHByaXZhdGUgYXBwQ29uZmlnOiBBcHBDb25maWdTZXJ2aWNlLFxyXG4gICAgQEluamVjdCgnYXV0aGVudGljYXRvcicpIHByaXZhdGUgY3VzdG9tQXV0aGVudGljYXRvcixcclxuICAgIEBJbmplY3QoJ2Vudmlyb25tZW50JykgcHJpdmF0ZSBlbnZpcm9ubWVudDogSURHU0Vudmlyb25tZW50LFxyXG4gICkge1xyXG4gICAgc3VwZXIoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgR0VUIHJlcXVlc3QgdG8gYXBpXHJcbiAgICogQHBhcmFtIHBvaW50XHJcbiAgICogQHBhcmFtIGFyZ3NcclxuICAgKiBAcGFyYW0gcGFyYW1ldGVyc1xyXG4gICAqIEBwYXJhbSBvcHRpb25zXHJcbiAgICovXHJcbiAgZ2V0KFxyXG4gICAgcG9pbnQ6IHN0cmluZyxcclxuICAgIGFyZ3M6IHN0cmluZ1tdID0gW10sXHJcbiAgICBwYXJhbWV0ZXJzOiBPYmplY3QgPSB7fSxcclxuICAgIG9wdGlvbnM6IE9iamVjdCA9IHt9LFxyXG4gICk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KCdHRVQnLCBwb2ludCwgcGFyYW1ldGVycywgb3B0aW9ucywgdW5kZWZpbmVkLCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgREVMRVRFIHJlcXVlc3QgdG8gYXBpXHJcbiAgICogQHBhcmFtIHBvaW50XHJcbiAgICogQHBhcmFtIGFyZ3NcclxuICAgKiBAcGFyYW0gcGFyYW1ldGVyc1xyXG4gICAqIEBwYXJhbSBvcHRpb25zXHJcbiAgICovXHJcbiAgZGVsZXRlKFxyXG4gICAgcG9pbnQ6IHN0cmluZyxcclxuICAgIGFyZ3M6IHN0cmluZ1tdID0gW10sXHJcbiAgICBwYXJhbWV0ZXJzOiBPYmplY3QgPSB7fSxcclxuICAgIG9wdGlvbnM6IE9iamVjdCA9IHt9LFxyXG4gICAgYm9keTogb2JqZWN0IHwgc3RyaW5nID0ge30sXHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3QoJ0RFTEVURScsIHBvaW50LCBwYXJhbWV0ZXJzLCBvcHRpb25zLCBib2R5LCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgT1BUSU9OUyByZXF1ZXN0IHRvIGFwaVxyXG4gICAqIEBwYXJhbSBwb2ludFxyXG4gICAqIEBwYXJhbSBhcmdzXHJcbiAgICogQHBhcmFtIHBhcmFtZXRlcnNcclxuICAgKiBAcGFyYW0gb3B0aW9uc1xyXG4gICAqL1xyXG4gIG9wdGlvbnMoXHJcbiAgICBwb2ludDogc3RyaW5nLFxyXG4gICAgYXJnczogc3RyaW5nW10gPSBbXSxcclxuICAgIHBhcmFtZXRlcnM6IE9iamVjdCA9IHt9LFxyXG4gICAgb3B0aW9uczogT2JqZWN0ID0ge30sXHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3QoJ09QVElPTlMnLCBwb2ludCwgcGFyYW1ldGVycywgb3B0aW9ucywgdW5kZWZpbmVkLCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgUE9TVCByZXF1ZXN0IHRvIGFwaVxyXG4gICAqIEBwYXJhbSBwb2ludFxyXG4gICAqIEBwYXJhbSBhcmdzXHJcbiAgICogQHBhcmFtIHBhcmFtZXRlcnNcclxuICAgKiBAcGFyYW0gb3B0aW9uc1xyXG4gICAqL1xyXG4gIHBvc3QoXHJcbiAgICBwb2ludDogc3RyaW5nLFxyXG4gICAgYXJnczogc3RyaW5nW10gPSBbXSxcclxuICAgIHBhcmFtZXRlcnM6IE9iamVjdCA9IHt9LFxyXG4gICAgYm9keTogb2JqZWN0IHwgc3RyaW5nID0ge30sXHJcbiAgICBvcHRpb25zOiBPYmplY3QgPSB7fSxcclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdCgnUE9TVCcsIHBvaW50LCBwYXJhbWV0ZXJzLCBvcHRpb25zLCBib2R5LCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgUEFUQ0ggcmVxdWVzdCB0byBhcGlcclxuICAgKiBAcGFyYW0gcG9pbnRcclxuICAgKiBAcGFyYW0gYXJnc1xyXG4gICAqIEBwYXJhbSBwYXJhbWV0ZXJzXHJcbiAgICogQHBhcmFtIG9wdGlvbnNcclxuICAgKi9cclxuICBwYXRjaChcclxuICAgIHBvaW50OiBzdHJpbmcsXHJcbiAgICBhcmdzOiBzdHJpbmdbXSA9IFtdLFxyXG4gICAgcGFyYW1ldGVyczogT2JqZWN0ID0ge30sXHJcbiAgICBib2R5OiBvYmplY3QgfCBzdHJpbmcgPSB7fSxcclxuICAgIG9wdGlvbnM6IE9iamVjdCA9IHt9LFxyXG4gICk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KCdQQVRDSCcsIHBvaW50LCBwYXJhbWV0ZXJzLCBvcHRpb25zLCBib2R5LCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ha2UgUFVUIHJlcXVlc3QgdG8gYXBpXHJcbiAgICogQHBhcmFtIHBvaW50XHJcbiAgICogQHBhcmFtIGFyZ3NcclxuICAgKiBAcGFyYW0gcGFyYW1ldGVyc1xyXG4gICAqIEBwYXJhbSBvcHRpb25zXHJcbiAgICovXHJcbiAgcHV0KFxyXG4gICAgcG9pbnQ6IHN0cmluZyxcclxuICAgIGFyZ3M6IHN0cmluZ1tdID0gW10sXHJcbiAgICBwYXJhbWV0ZXJzOiBPYmplY3QgPSB7fSxcclxuICAgIGJvZHk6IG9iamVjdCB8IHN0cmluZyA9IHt9LFxyXG4gICAgb3B0aW9uczogT2JqZWN0ID0ge30sXHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3QoJ1BVVCcsIHBvaW50LCBwYXJhbWV0ZXJzLCBvcHRpb25zLCBib2R5LCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybiBnZW5lcmF0ZWQgdXJsXHJcbiAgICogQHBhcmFtIHBvaW50XHJcbiAgICogQHBhcmFtIGFyZ3NcclxuICAgKiBAcGFyYW0gcGFyYW1ldGVyc1xyXG4gICAqIEBwYXJhbSBib2R5XHJcbiAgICogQHBhcmFtIG9wdGlvbnNcclxuICAgKi9cclxuICBnZXRVUkwoXHJcbiAgICBwb2ludDogc3RyaW5nLFxyXG4gICAgYXJnczogc3RyaW5nW10gPSBbXSxcclxuICAgIHBhcmFtZXRlcnM6IE9iamVjdCA9IHt9LFxyXG4gICAgYm9keTogb2JqZWN0IHwgc3RyaW5nID0ge30sXHJcbiAgICBvcHRpb25zOiBPYmplY3QgPSB7fSxcclxuICApIHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3QoJ2dldFVSTCcsIHBvaW50LCBwYXJhbWV0ZXJzLCBvcHRpb25zLCBib2R5LCAuLi5hcmdzKTtcclxuICB9XHJcblxyXG4gIGdldCBhcGlSZW5hbWVMaXN0KCkge1xyXG4gICAgcmV0dXJuIFsnTmFtZScsICdUaXRsZSddO1xyXG4gIH1cclxuXHJcbiAgZ2V0IEFQSSgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIEFwcENvbmZpZ1NlcnZpY2Uuc2V0dGluZ3MuYXBpVXJsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZW5hbWUob3JpZ2luLCB0YXJnZXQpIHtcclxuICAgIHRoaXMubGFuZ3VhZ2VzLmZvckVhY2gobGFuZyA9PiB7XHJcbiAgICAgIGNvbnN0IGZyb20gPSBgJHtvcmlnaW59XyR7bGFuZ31gO1xyXG4gICAgICBjb25zdCB0byA9IGAke29yaWdpbn1gO1xyXG4gICAgICBpZiAodGFyZ2V0KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0YXJnZXQuaGFzT3duUHJvcGVydHkoZnJvbSkgJiYgIXRhcmdldC5oYXNPd25Qcm9wZXJ0eSh0bykpIHtcclxuICAgICAgICB0YXJnZXRbdG9dID0gdGFyZ2V0W2Zyb21dO1xyXG4gICAgICAgIGRlbGV0ZSB0YXJnZXRbZnJvbV07XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIGZpbmFsIHVybCBmcm9tIGFwaV91cmwgKyB2aWV3ICsgcXVlcnkgcGFyYW1ldGVycztcclxuICAgKiBAcGFyYW0gdXJsXHJcbiAgICogQHBhcmFtIHBhcmFtZXRlcnNcclxuICAgKiBAcGFyYW0gYXJnc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2VuZXJhdGVVcmwodXJsOiBzdHJpbmcsIHBhcmFtZXRlcnM6IE9iamVjdCwgLi4uYXJncyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBlbmRVcmwgPSBgJHt1cmx9JHthcmdzLmxlbmd0aCA/IGAvJHthcmdzLmpvaW4oJy8nKX1gIDogJyd9YDtcclxuICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1ldGVycylcclxuICAgICAgLm1hcChrZXkgPT4gYCR7a2V5fT0ke3RoaXMuc2FuaXRpemUocGFyYW1ldGVyc1trZXldKX1gKVxyXG4gICAgICAuam9pbignJicpO1xyXG5cclxuICAgIHJldHVybiBgJHtlbmRVcmx9JHtxdWVyeVBhcmFtcyA/IGA/JHtxdWVyeVBhcmFtc31gIDogJyd9YDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2FuaXRpemUoaXRlbTogYW55KSB7XHJcbiAgICBjb25zdCBleGlzdHMgPSBpdGVtICE9PSB1bmRlZmluZWQgJiYgaXRlbSAhPT0gbnVsbDtcclxuICAgIGNvbnN0IGlzTnVtID0gdmFsID0+IHZhbC5jb25zdHJ1Y3RvciA9PT0gTnVtYmVyO1xyXG4gICAgY29uc3QgaXNTdHJpbmcgPSB2YWwgPT4gdmFsLmNvbnN0cnVjdG9yID09PSBTdHJpbmc7XHJcbiAgICBpZiAoIWV4aXN0cykge1xyXG4gICAgICByZXR1cm4gaXRlbTtcclxuICAgIH1cclxuICAgIGlmIChpc1N0cmluZyhpdGVtKSkge1xyXG4gICAgICByZXR1cm4gaXRlbS50cmltKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoaXNOdW0oaXRlbSkpIHtcclxuICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICB9XHJcbiAgICBpZiAoaXRlbSAmJiBBcnJheS5pc0FycmF5KGl0ZW0pKSB7XHJcbiAgICAgIGl0ZW0gPSBpdGVtLm1hcChjdXJyID0+IHtcclxuICAgICAgICBpZiAoIWN1cnIpIHtcclxuICAgICAgICAgIHJldHVybiBjdXJyO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY3Vyci5oYXNPd25Qcm9wZXJ0eSgndmFsdWUnKSkge1xyXG4gICAgICAgICAgY3Vyci52YWx1ZSA9ICEhY3Vyci52YWx1ZSA/IGN1cnIudmFsdWUudG9TdHJpbmcoKTogbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGN1cnI7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGl0ZW0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSWYgZGF0YSBjb250YWlucyBmaWVsZHMgbGlrZSBOYW1lX3J1L05hbWVfcm8vTmFtZV9lbiB0cmFuc2Zvcm0gaXQgaW50byBOYW1lLlxyXG4gICAqIEBwYXJhbSBkYXRhXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZXNvbHZlKHJlc3BvbnNlOiBhbnkpIHtcclxuICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5kYXRhICYmIEFycmF5LmlzQXJyYXkocmVzcG9uc2UuZGF0YSkpIHtcclxuICAgICAgcmVzcG9uc2UuZGF0YS5mb3JFYWNoKGl0ZW0gPT4ge1xyXG4gICAgICAgIHRoaXMuYXBpUmVuYW1lTGlzdC5mb3JFYWNoKHJlbmFtZU9yaWdpbiA9PiB7XHJcbiAgICAgICAgICB0aGlzLnJlbmFtZShyZW5hbWVPcmlnaW4sIGl0ZW0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIC8vIEFscmVhZHkgYmVlbiBzYW5pdGl6ZWRcclxuICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5oYXNPd25Qcm9wZXJ0eSh0aGlzLnNhbml0aXplTWFyaykpIHtcclxuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogcmVzcG9uc2UsXHJcbiAgICAgIGVycm9yOiBudWxsLFxyXG4gICAgICBbdGhpcy5zYW5pdGl6ZU1hcmtdOiB0cnVlLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFByaXZhdGUgQWJzdHJhY3QgcmVxdWVzdCBmdW5jdGlvblxyXG4gICAqIEBwYXJhbSBtZXRob2RcclxuICAgKiBAcGFyYW0gcG9pbnRcclxuICAgKiBAcGFyYW0gcGFyYW1ldGVyc1xyXG4gICAqIEBwYXJhbSBvcHRpb25zXHJcbiAgICogQHBhcmFtIGFyZ3NcclxuICAgKi9cclxuICBwcml2YXRlIHJlcXVlc3QoXHJcbiAgICBtZXRob2Q6IHN0cmluZyxcclxuICAgIHBvaW50OiBzdHJpbmcsXHJcbiAgICBwYXJhbWV0ZXJzOiBPYmplY3QsXHJcbiAgICBvcHRpb25zOiBPYmplY3QsXHJcbiAgICBib2R5OiBPYmplY3QgPSBudWxsLFxyXG4gICAgLi4uYXJnc1xyXG4gICk6IFByb21pc2U8YW55PiB8IGFueSB7XHJcbiAgICBpZiAoIW1ldGhvZCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ1NvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggQVBJIHNlcnZpY2UuJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGxldCBhcGlVcmwgPSB0aGlzLkFQSTtcclxuICAgIC8vIElmIGlzIGFscmVhZHkgY29tcGxldGUgdXJsIGkgc2hvdWxkIG5vdCBjb25jYXQgd2l0aCBhcGkgdXJsLlxyXG4gICAgY29uc3QgZnVsbFVybCA9IG5ldyBSZWdFeHAoJ14oPzpbYS16XSs6KT8vLycsICdpJyk7XHJcbiAgICBpZiAoZnVsbFVybC50ZXN0KHBvaW50KSkge1xyXG4gICAgICBhcGlVcmwgPSAnJztcclxuICAgIH1cclxuICAgIG1ldGhvZCA9IG1ldGhvZC50b0xvd2VyQ2FzZSgpO1xyXG4gICAgY29uc3QgdXJsID0gdGhpcy5nZW5lcmF0ZVVybCgob3B0aW9uc1snYXBpVXJsJ10gfHwgYXBpVXJsKSArIHBvaW50LCBwYXJhbWV0ZXJzLCAuLi5hcmdzKTtcclxuICAgIGlmIChtZXRob2QgPT09ICdnZXR1cmwnKSB7XHJcbiAgICAgIHJldHVybiB1cmw7XHJcbiAgICB9XHJcbiAgICBjb25zdCBjYWNoZVVybCA9IGAke3VybH18JHttZXRob2R9YDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcclxuICAgICAgY29uc3QgY2FjaGUgPSBzdXBlci5nZXQoY2FjaGVVcmwpO1xyXG4gICAgICBjb25zdCBwcm9ncmVzcyA9IHN1cGVyLmdldFByb2dyZXNzKGNhY2hlVXJsKTtcclxuICAgICAgY29uc3Qgc2tpcENhY2hlID0gb3B0aW9uc1snc2tpcENhY2hlJ10gfHwgZmFsc2U7XHJcblxyXG4gICAgICBpZiAoY2FjaGUgJiYgc2tpcENhY2hlICE9PSB0cnVlKSB7XHJcbiAgICAgICAgLy8gRXh0cmFjdCByZXNwb25zZSBmcm9tIGFscmVhZHkgZmluaXNoZWQgcmVxdWVzdFxyXG4gICAgICAgIHJldHVybiByZXNvbHZlKGNhY2hlKTtcclxuICAgICAgfSBlbHNlIGlmIChwcm9ncmVzcyAmJiBza2lwQ2FjaGUgIT09IHRydWUpIHtcclxuICAgICAgICAvLyBFeHRyYWN0IHJlc3BvbnNlIGZyb20gYWxyZWFkeSBleGlzdGluZyByZXF1ZXN0IGluIHByb2dyZXNzXHJcbiAgICAgICAgcHJvZ3Jlc3Muc3Vic2NyaWJlKHJlc3BvbnNlID0+IHtcclxuICAgICAgICAgIHN1cGVyLmRlbGV0ZVByb2dyZXNzKGNhY2hlVXJsKTtcclxuICAgICAgICAgIGNvbnN0IHJlc29sdmVkRGF0YSA9IHRoaXMucmVzb2x2ZShyZXNwb25zZSk7XHJcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXNvbHZlZERhdGEpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IGNhY2hpbmdNZXRob2QgPSBtZXRob2QgPT09ICdnZXQnIHx8IG1ldGhvZCA9PT0gJ29wdGlvbnMnO1xyXG5cclxuICAgICAgICBsZXQgY2FsbFBhcmFtZXRlcnMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gQWRkIGhlYWRlcnNcclxuICAgICAgICBjb25zdCBkZWZhdWx0SGVhZGVycyA9IHtcclxuICAgICAgICAgICdQcmFnbWEnOiAnbm8tY2FjaGUnLFxyXG4gICAgICAgICAgJ0NhY2hlLWNvbnRyb2wnOiAtMSxcclxuICAgICAgICAgICduZ3N3LWJ5cGFzcyc6ICcnXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgaGVhZGVycyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdEhlYWRlcnMsIG9wdGlvbnNbJ2hlYWRlcnMnXSB8fCB7fSk7XHJcbiAgICAgICAgdGhpcy5hdXRoZW50aWNhdG9yKGhlYWRlcnMsIG9wdGlvbnMpO1xyXG4gICAgICAgIG9wdGlvbnNbJ2hlYWRlcnMnXSA9IG5ldyBIdHRwSGVhZGVycyh0aGlzLmNsZWFuSGVhZGVycyhoZWFkZXJzKSk7XHJcblxyXG4gICAgICAgIGlmIChjYWNoaW5nTWV0aG9kKSB7XHJcbiAgICAgICAgICBjYWxsUGFyYW1ldGVycyA9IFt1cmwsIG9wdGlvbnNdO1xyXG4gICAgICAgICAgLy8gUmVxdWVzdCBub3QgaW4gY2FjaGUvcHJvZ3Jlc3Mgc28gd2Ugc2V0IGl0LlxyXG4gICAgICAgICAgc3VwZXIuc2V0UHJvZ3Jlc3MoY2FjaGVVcmwpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAobWV0aG9kID09PSAnZGVsZXRlJykge1xyXG4gICAgICAgICAgY2FsbFBhcmFtZXRlcnMgPSBbdXJsLCBvcHRpb25zLCBib2R5IHx8IHt9XTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY2FsbFBhcmFtZXRlcnMgPSBbdXJsLCBib2R5IHx8IHt9LCBvcHRpb25zXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5odHRwQ2xpZW50W21ldGhvZF0oLi4uY2FsbFBhcmFtZXRlcnMpXHJcbiAgICAgICAgICAudG9Qcm9taXNlKClcclxuICAgICAgICAgIC50aGVuKHJhd0RhdGEgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZERhdGEgPSB0aGlzLnJlc29sdmUocmF3RGF0YSk7XHJcbiAgICAgICAgICAgIGlmIChjYWNoaW5nTWV0aG9kKSB7XHJcbiAgICAgICAgICAgICAgc3VwZXIuc2V0KGNhY2hlVXJsLCByZXNvbHZlZERhdGEpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IGdldFByb2dyZXNzID0gc3VwZXIuZ2V0UHJvZ3Jlc3MoY2FjaGVVcmwpO1xyXG4gICAgICAgICAgICBpZiAoZ2V0UHJvZ3Jlc3MpIHtcclxuICAgICAgICAgICAgICBnZXRQcm9ncmVzcy5lbWl0KHJlc29sdmVkRGF0YSk7XHJcbiAgICAgICAgICAgICAgc3VwZXIuZGVsZXRlUHJvZ3Jlc3MoY2FjaGVVcmwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc29sdmVkRGF0YSk7XHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcclxuICAgICAgICAgICAgY29uc3QgcmVzID0geyBkYXRhOiBudWxsLCBlcnJvciB9O1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZ2V0UHJvZ3Jlc3MgPSBzdXBlci5nZXRQcm9ncmVzcyhjYWNoZVVybCk7XHJcbiAgICAgICAgICAgIGlmIChnZXRQcm9ncmVzcykge1xyXG4gICAgICAgICAgICAgIGdldFByb2dyZXNzLmVtaXQocmVzKTtcclxuICAgICAgICAgICAgICBzdXBlci5kZWxldGVQcm9ncmVzcyhjYWNoZVVybCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXV0aGVudGljYXRvcihoZWFkZXJzLCBvcHRpb25zKSB7XHJcbiAgICBpZiAoIXRoaXMuY3VzdG9tQXV0aGVudGljYXRvcikge1xyXG4gICAgICByZXR1cm4gdGhpcy5kZWZhdWx0QXV0aGVudGljYXRvcihoZWFkZXJzLCBvcHRpb25zKTtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLmN1c3RvbUF1dGhlbnRpY2F0b3IoaGVhZGVycywgb3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGRlZmF1bHRBdXRoZW50aWNhdG9yKGhlYWRlcnMsIG9wdGlvbnMpIHtcclxuICAgIGNvbnN0IGF1dGg6IEF1dGggPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdhdXRoJykpO1xyXG4gICAgY29uc3QgZXh0ZXJuYWxTZXNzaW9uSW5kZXggPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKExvZ2luTWV0YWRhdGEuZXh0ZXJuYWxTZXNzaW9uSW5kZXhLZXkpKTtcclxuICAgIGlmIChhdXRoICYmICFoZWFkZXJzLmhhc093blByb3BlcnR5KCdBdXRob3JpemF0aW9uJykpIHtcclxuICAgICAgaGVhZGVyc1snQXV0aG9yaXphdGlvbiddID0gYCR7YXV0aC50b2tlblR5cGV9ICR7YXV0aC50b2tlbn1gO1xyXG4gICAgfVxyXG4gICAgaWYgKGV4dGVybmFsU2Vzc2lvbkluZGV4ICYmICFoZWFkZXJzLmhhc093blByb3BlcnR5KExvZ2luTWV0YWRhdGEuZXh0ZXJuYWxTZXNzaW9uSW5kZXhLZXkpKSB7XHJcbiAgICAgIGhlYWRlcnNbYHgtJHtMb2dpbk1ldGFkYXRhLmV4dGVybmFsU2Vzc2lvbkluZGV4S2V5fWBdID0gYCR7ZXh0ZXJuYWxTZXNzaW9uSW5kZXh9YDtcclxuICAgIH1cclxuICAgIGNvbnN0IGNvbnRleHRGcm9tU3RvcmFnZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKExvZ2luTWV0YWRhdGEudXNlckNvbnRleHQpO1xyXG4gICAgY29uc3QgdXNlckNvbnRleHQgPVxyXG4gICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShMb2dpbk1ldGFkYXRhLmFjdGl2ZVJvbGUpIHx8XHJcbiAgICAgIChjb250ZXh0RnJvbVN0b3JhZ2UgJiYgY29udGV4dEZyb21TdG9yYWdlICE9PSAndW5kZWZpbmVkJyAmJiBjb250ZXh0RnJvbVN0b3JhZ2UgIT09ICdudWxsJyA/IEpTT04ucGFyc2UoY29udGV4dEZyb21TdG9yYWdlKSA6IHt9KS5yb2xlO1xyXG4gICAgaWYgKCFvcHRpb25zWydza2lwUm9sZSddICYmIHVzZXJDb250ZXh0KSB7XHJcbiAgICAgIGhlYWRlcnNbJ3gtQ3VycmVudC1Sb2xlJ10gPSBgJHt1c2VyQ29udGV4dH1gO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhbkhlYWRlcnMoaGVhZGVycykge1xyXG4gICAgY29uc3QgY2xlYW5lZCA9IHt9O1xyXG4gICAgT2JqZWN0LmtleXMoaGVhZGVycykuZm9yRWFjaChrZXkgPT4ge1xyXG4gICAgICBjb25zdCB2YWx1ZSA9IGhlYWRlcnNba2V5XTtcclxuICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBjbGVhbmVkW2tleV0gPSB2YWx1ZTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gY2xlYW5lZDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0IGxhbmd1YWdlcygpIHtcclxuICAgIHJldHVybiBbJ2VuJywgJ3JvJywgJ3J1J107XHJcbiAgfVxyXG59XHJcbiJdfQ==