@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
130 lines • 20.1 kB
JavaScript
import { Injectable } from '@angular/core';
import { FetchClient } from '@c8y/client';
import { Subject, pipe } from 'rxjs';
import { distinctUntilChanged, filter, map, scan, shareReplay } from 'rxjs/operators';
import { HttpInterceptHandler, HttpRequestHandler } from './http-handler.model';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
export class ApiService {
constructor(client) {
this.client = client;
this.callsSubject = new Subject();
this.interceptors = new Map();
this.interceptorCounter = 0;
this.calls = this.callsSubject.asObservable();
this.hookIntoClientFetch();
this.isLoading$ = this.calls.pipe(filter(({ url }) => !/notification\/realtime/.test(url)), map(({ phase }) => (phase === 'start' ? 1 : -1)), scan((count, item) => count + item, 0), map(count => count > 0), distinctUntilChanged(), shareReplay(1));
}
/**
* Allows to hook into the responses received by the FetchClient.
* This is meant to be used to react on the responses, not for manipulation of the responses.
* @param hookFilter A filter function to filter for specific responses.
* @returns An Observable of the filtered responses.
*/
hookResponse(hookFilter) {
return this.callsSubject.pipe(filter(({ phase }) => phase === 'finish'), filter(hookFilter));
}
/**
* Allows to hook into the requests performed by the FetchClient.
* This is meant to be used to react on the requests, not for manipulation of the requests.
* @param hookFilter A filter function to filter for specific requests.
* @returns An Observable of the filtered requests.
*/
hookRequest(hookFilter) {
return this.callsSubject.pipe(filter(({ phase }) => phase === 'start'), filter(hookFilter));
}
onFinish(call) {
this.callsSubject.next({ phase: 'finish', ...call });
}
onStart(call) {
this.callsSubject.next({ phase: 'start', ...call });
}
/**
* Resolves data from an API call response.
* @returns A Promise containing an object with resolved data, method, and URL.
*/
resolveData(call) {
const { response, method, url } = call;
if ('data' in response) {
return Promise.resolve({ data: response.data, method, url });
}
else {
// No Content success status, for example DELETE request.
if (response?.status === 204) {
return Promise.resolve({ data: null, method, url });
}
const cb = data => ({ data, method, url });
return response.clone().json().then(cb, cb);
}
}
/**
* Can be added to a pipe to exclude any permission call. Permission calls are PUT
* request with only an id in it, to verify if the user has access to this managed object.
* @returns The operator to be added to a pipe.
*/
excludePermissionCall() {
return pipe(filter(({ method, options }) => {
if (method === 'PUT' && options.body && typeof options.body === 'string') {
const parsedBody = JSON.parse(options.body);
const bodyKeys = Object.keys(parsedBody);
return !(bodyKeys.length === 1 && bodyKeys[0] === 'id');
}
return true;
}));
}
/**
* Allows to intercept requests performed via the FetchClient requests.
* @param interceptor The interceptor to be added.
* @param id An optional unique identifier for the interceptor. The chain of interceptors is ordered by this id. And it can be used to remove the interceptor later on.
* @returns The id of the interceptor (same as provided id if one was provided, otherwise an id will be generated).
*/
addInterceptor(interceptor, id) {
if (!id) {
id = `${++this.interceptorCounter}`;
}
this.interceptors.set(id, interceptor);
return id;
}
/**
* Allows to remove a previously added interceptor by it's id.
* @param id The id of the interceptor that should be removed.
* @returns true if an interceptor existed and has been removed, or false if id does not exist.
*/
removeInterceptor(id) {
return this.interceptors.delete(id);
}
/**
* Checks if an interceptor with a given id exists.
* @param id The id of the interceptor.
* @returns - Returns true if an interceptor with the given id exists, otherwise false.
*/
hasInterceptor(id) {
return this.interceptors.has(id);
}
hookIntoClientFetch() {
const fetch = this.client.fetch.bind(this.client);
const requestHandler = new HttpRequestHandler(fetch, this);
this.client.fetch = async (url, options = { method: 'GET' }) => {
const { method } = options;
return this.createInterceptorChain({ url, options, method }, requestHandler).toPromise();
};
}
createInterceptorChain(call, requestHandler) {
let handler = requestHandler;
// Do some sorting to always apply the interceptors in the specific order
const sortedInterceptorIds = Array.from(this.interceptors.keys()).sort((a, b) => b.localeCompare(a));
for (const interceptorId of sortedInterceptorIds) {
handler = new HttpInterceptHandler(this.interceptors.get(interceptorId), handler);
}
return handler.handle(call);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApiService, deps: [{ token: i1.FetchClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApiService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApiService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.FetchClient }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9hcGkvYXBpLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsV0FBVyxFQUFpQyxNQUFNLGFBQWEsQ0FBQztBQUN6RSxPQUFPLEVBQXdDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0UsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXRGLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsa0JBQWtCLEVBRW5CLE1BQU0sc0JBQXNCLENBQUM7OztBQU05QixNQUFNLE9BQU8sVUFBVTtJQU9yQixZQUFvQixNQUFtQjtRQUFuQixXQUFNLEdBQU4sTUFBTSxDQUFhO1FBSi9CLGlCQUFZLEdBQUcsSUFBSSxPQUFPLEVBQVcsQ0FBQztRQUN0QyxpQkFBWSxHQUFHLElBQUksR0FBRyxFQUEyQixDQUFDO1FBQ2xELHVCQUFrQixHQUFHLENBQUMsQ0FBQztRQUc3QixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFM0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FDL0IsTUFBTSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFDeEQsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMs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QUFFLE1BQU0sRUFBRSxFQUFFLGNBQWMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzNGLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFTyxzQkFBc0IsQ0FDNUIsSUFBYSxFQUNiLGNBQWtDO1FBRWxDLElBQUksT0FBTyxHQUFnQixjQUFjLENBQUM7UUFDMUMseUVBQXlFO1FBQ3pFLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQzlFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQ25CLENBQUM7UUFDRixLQUFLLE1BQU0sYUFBYSxJQUFJLG9CQUFvQixFQUFFLENBQUM7WUFDakQsT0FBTyxHQUFHLElBQUksb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QixDQUFDOytHQXBKVSxVQUFVO21IQUFWLFVBQVUsY0FGVCxNQUFNOzs0RkFFUCxVQUFVO2tCQUh0QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZldGNoQ2xpZW50LCBJRmV0Y2hPcHRpb25zLCBJRmV0Y2hSZXNwb25zZSB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IE1vbm9UeXBlT3BlcmF0b3JGdW5jdGlvbiwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgcGlwZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQsIGZpbHRlciwgbWFwLCBzY2FuLCBzaGFyZVJlcGxheSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEFwaUNhbGwsIEFwaUNhbGxPcHRpb25zIH0gZnJvbSAnLi9hcGkubW9kZWwnO1xuaW1wb3J0IHtcbiAgSHR0cEludGVyY2VwdEhhbmRsZXIsXG4gIEh0dHBSZXF1ZXN0SGFuZGxlcixcbiAgUmVxdWVzdFN0YXJ0QW5kRmluaXNoXG59IGZyb20gJy4vaHR0cC1oYW5kbGVyLm1vZGVsJztcbmltcG9ydCB7IEh0dHBIYW5kbGVyLCBIdHRwSW50ZXJjZXB0b3IgfSBmcm9tICcuL2ludGVyY2VwdG9yLm1vZGVsJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQXBpU2VydmljZSBpbXBsZW1lbnRzIFJlcXVlc3RTdGFydEFuZEZpbmlzaCB7XG4gIGNhbGxzOiBPYnNlcnZhYmxlPEFwaUNhbGw+O1xuICBpc0xvYWRpbmckOiBPYnNlcnZhYmxlPGJvb2xlYW4+O1xuICBwcml2YXRlIGNhbGxzU3ViamVjdCA9IG5ldyBTdWJqZWN0PEFwaUNhbGw+KCk7XG4gIHByaXZhdGUgaW50ZXJjZXB0b3JzID0gbmV3IE1hcDxzdHJpbmcsIEh0dHBJbnRlcmNlcHRvcj4oKTtcbiAgcHJpdmF0ZSBpbnRlcmNlcHRvckNvdW50ZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xpZW50OiBGZXRjaENsaWVudCkge1xuICAgIHRoaXMuY2FsbHMgPSB0aGlzLmNhbGxzU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB0aGlzLmhvb2tJbnRvQ2xpZW50RmV0Y2goKTtcblxuICAgIHRoaXMuaXNMb2FkaW5nJCA9IHRoaXMuY2FsbHMucGlwZShcbiAgICAgIGZpbHRlcigoeyB1cmwgfSkgPT4gIS9ub3RpZmljYXRpb25cXC9yZWFsdGltZS8udGVzdCh1cmwpKSxcbiAgICAgIG1hcCgoeyBwaGFzZSB9KSA9PiAocGhhc2UgPT09ICdzdGFydCcgPyAxIDogLTEpKSxcbiAgICAgIHNjYW4oKGNvdW50LCBpdGVtKSA9PiBjb3VudCArIGl0ZW0sIDApLFxuICAgICAgbWFwKGNvdW50ID0+IGNvdW50ID4gMCksXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxuICAgICAgc2hhcmVSZXBsYXkoMSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyB0byBob29rIGludG8gdGhlIHJlc3BvbnNlcyByZWNlaXZlZCBieSB0aGUgRmV0Y2hDbGllbnQuXG4gICAqIFRoaXMgaXMgbWVhbnQgdG8gYmUgdXNlZCB0byByZWFjdCBvbiB0aGUgcmVzcG9uc2VzLCBub3QgZm9yIG1hbmlwdWxhdGlvbiBvZiB0aGUgcmVzcG9uc2VzLlxuICAgKiBAcGFyYW0gaG9va0ZpbHRlciBBIGZpbHRlciBmdW5jdGlvbiB0byBmaWx0ZXIgZm9yIHNwZWNpZmljIHJlc3BvbnNlcy5cbiAgICogQHJldHVybnMgQW4gT2JzZXJ2YWJsZSBvZiB0aGUgZmlsdGVyZWQgcmVzcG9uc2VzLlxuICAgKi9cbiAgaG9va1Jlc3BvbnNlKGhvb2tGaWx0ZXI6IChjYWxsOiBBcGlDYWxsKSA9PiBib29sZWFuKTogT2JzZXJ2YWJsZTxBcGlDYWxsPiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbHNTdWJqZWN0LnBpcGUoXG4gICAgICBmaWx0ZXIoKHsgcGhhc2UgfSkgPT4gcGhhc2UgPT09ICdmaW5pc2gnKSxcbiAgICAgIGZpbHRlcihob29rRmlsdGVyKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQWxsb3dzIHRvIGhvb2sgaW50byB0aGUgcmVxdWVzdHMgcGVyZm9ybWVkIGJ5IHRoZSBGZXRjaENsaWVudC5cbiAgICogVGhpcyBpcyBtZWFudCB0byBiZSB1c2VkIHRvIHJlYWN0IG9uIHRoZSByZXF1ZXN0cywgbm90IGZvciBtYW5pcHVsYXRpb24gb2YgdGhlIHJlcXVlc3RzLlxuICAgKiBAcGFyYW0gaG9va0ZpbHRlciBBIGZpbHRlciBmdW5jdGlvbiB0byBmaWx0ZXIgZm9yIHNwZWNpZmljIHJlcXVlc3RzLlxuICAgKiBAcmV0dXJucyBBbiBPYnNlcnZhYmxlIG9mIHRoZSBmaWx0ZXJlZCByZXF1ZXN0cy5cbiAgICovXG4gIGhvb2tSZXF1ZXN0KGhvb2tGaWx0ZXI6IChjYWxsOiBBcGlDYWxsKSA9PiBib29sZWFuKTogT2JzZXJ2YWJsZTxBcGlDYWxsPiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbHNTdWJqZWN0LnBpcGUoXG4gICAgICBmaWx0ZXIoKHsgcGhhc2UgfSkgPT4gcGhhc2UgPT09ICdzdGFydCcpLFxuICAgICAgZmlsdGVyKGhvb2tGaWx0ZXIpXG4gICAgKTtcbiAgfVxuXG4gIG9uRmluaXNoKGNhbGw6IEFwaUNhbGwpOiB2b2lkIHtcbiAgICB0aGlzLmNhbGxzU3ViamVjdC5uZXh0KHsgcGhhc2U6ICdmaW5pc2gnLCAuLi5jYWxsIH0pO1xuICB9XG5cbiAgb25TdGFydChjYWxsOiBBcGlDYWxsKTogdm9pZCB7XG4gICAgdGhpcy5jYWxsc1N1YmplY3QubmV4dCh7IHBoYXNlOiAnc3RhcnQnLCAuLi5jYWxsIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIGRhdGEgZnJvbSBhbiBBUEkgY2FsbCByZXNwb25zZS5cbiAgICogQHJldHVybnMgQSBQcm9taXNlIGNvbnRhaW5pbmcgYW4gb2JqZWN0IHdpdGggcmVzb2x2ZWQgZGF0YSwgbWV0aG9kLCBhbmQgVVJMLlxuICAgKi9cbiAgcmVzb2x2ZURhdGE8VCA9IHVua25vd24+KGNhbGw6IEFwaUNhbGwpOiBQcm9taXNlPHsgZGF0YTogVDsgbWV0aG9kOiBzdHJpbmc7IHVybDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCB7IHJlc3BvbnNlLCBtZXRob2QsIHVybCB9ID0gY2FsbDtcbiAgICBpZiAoJ2RhdGEnIGluIHJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgZGF0YTogcmVzcG9uc2UuZGF0YSwgbWV0aG9kLCB1cmwgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vIENvbnRlbnQgc3VjY2VzcyBzdGF0dXMsIGZvciBleGFtcGxlIERFTEVURSByZXF1ZXN0LlxuICAgICAgaWYgKChyZXNwb25zZSBhcyBSZXNwb25zZSk/LnN0YXR1cyA9PT0gMjA0KSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiBudWxsLCBtZXRob2QsIHVybCB9KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNiID0gZGF0YSA9PiAoeyBkYXRhLCBtZXRob2QsIHVybCB9KTtcbiAgICAgIHJldHVybiAocmVzcG9uc2UgYXMgUmVzcG9uc2UpLmNsb25lKCkuanNvbigpLnRoZW4oY2IsIGNiKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FuIGJlIGFkZGVkIHRvIGEgcGlwZSB0byBleGNsdWRlIGFueSBwZXJtaXNzaW9uIGNhbGwuIFBlcm1pc3Npb24gY2FsbHMgYXJlIFBVVFxuICAgKiByZXF1ZXN0IHdpdGggb25seSBhbiBpZCBpbiBpdCwgdG8gdmVyaWZ5IGlmIHRoZSB1c2VyIGhhcyBhY2Nlc3MgdG8gdGhpcyBtYW5hZ2VkIG9iamVjdC5cbiAgICogQHJldHVybnMgVGhlIG9wZXJhdG9yIHRvIGJlIGFkZGVkIHRvIGEgcGlwZS5cbiAgICovXG4gIGV4Y2x1ZGVQZXJtaXNzaW9uQ2FsbCgpOiBNb25vVHlwZU9wZXJhdG9yRnVuY3Rpb248QXBpQ2FsbD4ge1xuICAgIHJldHVybiBwaXBlKFxuICAgICAgZmlsdGVyKCh7IG1ldGhvZCwgb3B0aW9ucyB9KSA9PiB7XG4gICAgICAgIGlmIChtZXRob2QgPT09ICdQVVQnICYmIG9wdGlvbnMuYm9keSAmJiB0eXBlb2Ygb3B0aW9ucy5ib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZEJvZHkgPSBKU09OLnBhcnNlKG9wdGlvbnMuYm9keSBhcyBzdHJpbmcpO1xuICAgICAgICAgIGNvbnN0IGJvZHlLZXlzID0gT2JqZWN0LmtleXMocGFyc2VkQm9keSk7XG4gICAgICAgICAgcmV0dXJuICEoYm9keUtleXMubGVuZ3RoID09PSAxICYmIGJvZHlLZXlzWzBdID09PSAnaWQnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgdG8gaW50ZXJjZXB0IHJlcXVlc3RzIHBlcmZvcm1lZCB2aWEgdGhlIEZldGNoQ2xpZW50IHJlcXVlc3RzLlxuICAgKiBAcGFyYW0gaW50ZXJjZXB0b3IgVGhlIGludGVyY2VwdG9yIHRvIGJlIGFkZGVkLlxuICAgKiBAcGFyYW0gaWQgQW4gb3B0aW9uYWwgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBpbnRlcmNlcHRvci4gVGhlIGNoYWluIG9mIGludGVyY2VwdG9ycyBpcyBvcmRlcmVkIGJ5IHRoaXMgaWQuIEFuZCBpdCBjYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGludGVyY2VwdG9yIGxhdGVyIG9uLlxuICAgKiBAcmV0dXJucyBUaGUgaWQgb2YgdGhlIGludGVyY2VwdG9yIChzYW1lIGFzIHByb3ZpZGVkIGlkIGlmIG9uZSB3YXMgcHJvdmlkZWQsIG90aGVyd2lzZSBhbiBpZCB3aWxsIGJlIGdlbmVyYXRlZCkuXG4gICAqL1xuICBhZGRJbnRlcmNlcHRvcihpbnRlcmNlcHRvcjogSHR0cEludGVyY2VwdG9yLCBpZD86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCFpZCkge1xuICAgICAgaWQgPSBgJHsrK3RoaXMuaW50ZXJjZXB0b3JDb3VudGVyfWA7XG4gICAgfVxuICAgIHRoaXMuaW50ZXJjZXB0b3JzLnNldChpZCwgaW50ZXJjZXB0b3IpO1xuICAgIHJldHVybiBpZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgdG8gcmVtb3ZlIGEgcHJldmlvdXNseSBhZGRlZCBpbnRlcmNlcHRvciBieSBpdCdzIGlkLlxuICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBpbnRlcmNlcHRvciB0aGF0IHNob3VsZCBiZSByZW1vdmVkLlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIGFuIGludGVyY2VwdG9yIGV4aXN0ZWQgYW5kIGhhcyBiZWVuIHJlbW92ZWQsIG9yIGZhbHNlIGlmIGlkIGRvZXMgbm90IGV4aXN0LlxuICAgKi9cbiAgcmVtb3ZlSW50ZXJjZXB0b3IoaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmludGVyY2VwdG9ycy5kZWxldGUoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhbiBpbnRlcmNlcHRvciB3aXRoIGEgZ2l2ZW4gaWQgZXhpc3RzLlxuICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBpbnRlcmNlcHRvci5cbiAgICogQHJldHVybnMgLSBSZXR1cm5zIHRydWUgaWYgYW4gaW50ZXJjZXB0b3Igd2l0aCB0aGUgZ2l2ZW4gaWQgZXhpc3RzLCBvdGhlcndpc2UgZmFsc2UuXG4gICAqL1xuICBoYXNJbnRlcmNlcHRvcihpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZXJjZXB0b3JzLmhhcyhpZCk7XG4gIH1cblxuICBwcml2YXRlIGhvb2tJbnRvQ2xpZW50RmV0Y2goKSB7XG4gICAgY29uc3QgZmV0Y2g6IEZldGNoQ2xpZW50WydmZXRjaCddID0gdGhpcy5jbGllbnQuZmV0Y2guYmluZCh0aGlzLmNsaWVudCk7XG4gICAgY29uc3QgcmVxdWVzdEhhbmRsZXIgPSBuZXcgSHR0cFJlcXVlc3RIYW5kbGVyKGZldGNoLCB0aGlzKTtcbiAgICB0aGlzLmNsaWVudC5mZXRjaCA9IGFzeW5jIChcbiAgICAgIHVybCxcbiAgICAgIG9wdGlvbnM6IEFwaUNhbGxPcHRpb25zICYgSUZldGNoT3B0aW9ucyA9IHsgbWV0aG9kOiAnR0VUJyB9XG4gICAgKSA9PiB7XG4gICAgICBjb25zdCB7IG1ldGhvZCB9ID0gb3B0aW9ucztcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUludGVyY2VwdG9yQ2hhaW4oeyB1cmwsIG9wdGlvbnMsIG1ldGhvZCB9LCByZXF1ZXN0SGFuZGxlcikudG9Qcm9taXNlKCk7XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlSW50ZXJjZXB0b3JDaGFpbihcbiAgICBjYWxsOiBBcGlDYWxsLFxuICAgIHJlcXVlc3RIYW5kbGVyOiBIdHRwUmVxdWVzdEhhbmRsZXJcbiAgKTogT2JzZXJ2YWJsZTxJRmV0Y2hSZXNwb25zZT4ge1xuICAgIGxldCBoYW5kbGVyOiBIdHRwSGFuZGxlciA9IHJlcXVlc3RIYW5kbGVyO1xuICAgIC8vIERvIHNvbWUgc29ydGluZyB0byBhbHdheXMgYXBwbHkgdGhlIGludGVyY2VwdG9ycyBpbiB0aGUgc3BlY2lmaWMgb3JkZXJcbiAgICBjb25zdCBzb3J0ZWRJbnRlcmNlcHRvcklkcyA9IEFycmF5LmZyb20odGhpcy5pbnRlcmNlcHRvcnMua2V5cygpKS5zb3J0KChhLCBiKSA9PlxuICAgICAgYi5sb2NhbGVDb21wYXJlKGEpXG4gICAgKTtcbiAgICBmb3IgKGNvbnN0IGludGVyY2VwdG9ySWQgb2Ygc29ydGVkSW50ZXJjZXB0b3JJZHMpIHtcbiAgICAgIGhhbmRsZXIgPSBuZXcgSHR0cEludGVyY2VwdEhhbmRsZXIodGhpcy5pbnRlcmNlcHRvcnMuZ2V0KGludGVyY2VwdG9ySWQpLCBoYW5kbGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXIuaGFuZGxlKGNhbGwpO1xuICB9XG59XG4iXX0=