angular-odata
Version:
Client side OData typescript library for Angular
177 lines • 22 kB
JavaScript
import { of, throwError } from 'rxjs';
import { startWith, tap } from 'rxjs/operators';
import { CACHE_KEY_SEPARATOR, DEFAULT_TIMEOUT } from '../constants';
import { PathSegment } from '../types';
export class ODataCache {
timeout;
entries;
constructor({ timeout = DEFAULT_TIMEOUT }) {
this.timeout = timeout;
this.entries = new Map();
}
/**
* Using the resource on the request build an array of string to identify the scope of the request
* @param req The request with the resource to build the scope
* @returns Array of string to identify the scope of the request
*/
scope(req) {
const segments = req.resource.cloneSegments();
return segments.segments({ key: true }).reduce((acc, s) => {
if (s.name === PathSegment.entitySet)
acc = [...acc, s.path()];
return acc;
}, ['request']);
}
/**
* Using the odata context on the response build an array of string to identify the tags of the response
* @param res The response to build the tags
* @returns Array of string to identify the tags of the response
*/
tags(res) {
const tags = [];
const context = res.context;
if (context.entitySet) {
tags.push(context.key
? `${context.entitySet}(${context.key})`
: context.entitySet);
}
if (context.type)
tags.push(context.type);
return tags;
}
/**
* Build an entry from a payload and some options
* @param payload The payload to store in the cache
* @param timeout The timeout for the entry
* @param tags The tags for the entry
* @returns The entry to store in the cache
*/
buildEntry(payload, { timeout, tags }) {
return {
payload,
lastRead: Date.now(),
timeout: timeout || this.timeout,
tags: tags || [],
};
}
/**
* Build a key from store an entry in the cache
* @param names The names of the entry
* @returns The key for the entry
*/
buildKey(names) {
return names.join(CACHE_KEY_SEPARATOR);
}
/**
* Put some payload in the cache
* @param name The name for the entry
* @param payload The payload to store in the cache
* @param timeout The timeout for the entry
* @param scope The scope for the entry
* @param tags The tags for the entry
*/
put(name, payload, { timeout, scope, tags, } = {}) {
const entry = this.buildEntry(payload, { timeout, tags });
const key = this.buildKey([...(scope || []), name]);
this.entries.set(key, entry);
this.forget();
}
/**
* Return the payload from the cache if it exists and is not expired
* @param name The name of the entry
* @param scope The scope of the entry
* @returns The payload of the entry
*/
get(name, { scope } = {}) {
const key = this.buildKey([...(scope || []), name]);
const entry = this.entries.get(key);
return entry !== undefined && !this.isExpired(entry)
? entry.payload
: undefined;
}
/**
* Remove all cache entries that are matching with the given options
* @param options The options to forget
*/
forget({ name, scope = [], tags = [], } = {}) {
if (name !== undefined)
scope.push(name);
const key = scope.length > 0 ? this.buildKey(scope) : undefined;
this.entries.forEach((entry, k) => {
if (this.isExpired(entry) || // Expired
(key !== undefined && k.startsWith(key)) || // Key
(tags.length > 0 && tags.some((t) => entry.tags.indexOf(t) !== -1)) // Tags
) {
this.entries.delete(k);
}
});
}
/**
* Remove all cache entries
*/
flush() {
this.entries = new Map();
}
/**
* Check if the entry is expired
* @param entry The cache entry
* @returns Boolean indicating if the entry is expired
*/
isExpired(entry) {
return entry.lastRead < Date.now() - (entry.timeout || this.timeout) * 1000;
}
/**
* Using the request, handle the fetching of the response
* @param req The request to fetch
* @param res$ Observable of the response
* @returns
*/
handleRequest(req, res$) {
return req.isFetch()
? this.handleFetch(req, res$)
: req.isMutate()
? this.handleMutate(req, res$)
: res$;
}
handleFetch(req, res$) {
const policy = req.fetchPolicy;
const cached = this.getResponse(req);
if (policy === 'no-cache') {
return res$;
}
if (policy === 'cache-only') {
if (cached) {
return of(cached);
}
else {
return throwError(() => new Error('No Cached'));
}
}
if (policy === 'cache-first' ||
policy === 'cache-and-network' ||
policy === 'network-only') {
res$ = res$.pipe(tap((res) => {
if (res.options.cacheability !== 'no-store')
this.putResponse(req, res);
}));
}
return cached !== undefined && policy !== 'network-only'
? policy === 'cache-and-network'
? res$.pipe(startWith(cached))
: of(cached)
: res$;
}
handleMutate(req, res$) {
const requests = req.isBatch()
? req.resource
.requests()
.filter((r) => r.isMutate())
: [req];
for (var r of requests) {
const scope = this.scope(r);
this.forget({ scope });
}
return res$;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLW9kYXRhL3NyYy9saWIvY2FjaGUvY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFjLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXBFLE9BQU8sRUFBUyxXQUFXLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFnQjlDLE1BQU0sT0FBZ0IsVUFBVTtJQUM5QixPQUFPLENBQVM7SUFDaEIsT0FBTyxDQUFvQztJQUUzQyxZQUFZLEVBQUUsT0FBTyxHQUFHLGVBQWUsRUFBd0I7UUFDN0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztJQUN6RCxDQUFDO0lBS0Q7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxHQUFzQjtRQUMxQixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzlDLE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FDNUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDVCxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUFDLFNBQVM7Z0JBQ2xDLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQVksQ0FBQyxDQUFDO1lBQ3JDLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQyxFQUNELENBQUMsU0FBUyxDQUFDLENBQ1osQ0FBQztJ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QUFZLENBQ2xCLEdBQXNCLEVBQ3RCLElBQW9DO1FBRXBDLE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUU7WUFDNUIsQ0FBQyxDQUFFLEdBQUcsQ0FBQyxRQUErQjtpQkFDakMsUUFBUSxFQUFFO2lCQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2hDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsS0FBSyxJQUFJLENBQUMsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUN2QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUsIG9mLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzdGFydFdpdGgsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IENBQ0hFX0tFWV9TRVBBUkFUT1IsIERFRkFVTFRfVElNRU9VVCB9IGZyb20gJy4uL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBPRGF0YUJhdGNoUmVzb3VyY2UsIE9EYXRhUmVxdWVzdCwgT0RhdGFSZXNwb25zZSB9IGZyb20gJy4uL3Jlc291cmNlcyc7XG5pbXBvcnQgeyBDYWNoZSwgUGF0aFNlZ21lbnQgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKlxuICogQSBjYWNoZSBlbnRyeSB0aGF0IGhvbGRzIGEgcGF5bG9hZCwgYSBsYXN0IHJlYWQgdGltZSwgYW5kIGEgdGltZW91dCBmb3IgdGhlIGVudHJ5LlxuICogQHBhcmFtIHBheWxvYWQgVGhlIHBheWxvYWQgdG8gY2FjaGUuXG4gKiBAcGFyYW0gbGFzdFJlYWQgVGhlIGxhc3QgcmVhZCB0aW1lLlxuICogQHBhcmFtIHRpbWVvdXQgVGhlIHRpbWVvdXQuXG4gKiBAcGFyYW0gdGFncyBTb21lIHRhZ3MgdG8gaWRlbnRpZnkgdGhlIGVudHJ5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9EYXRhQ2FjaGVFbnRyeTxUPiB7XG4gIHBheWxvYWQ6IFQ7XG4gIGxhc3RSZWFkOiBudW1iZXI7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAgdGFnczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBPRGF0YUNhY2hlIGltcGxlbWVudHMgQ2FjaGUge1xuICB0aW1lb3V0OiBudW1iZXI7XG4gIGVudHJpZXM6IE1hcDxzdHJpbmcsIE9EYXRhQ2FjaGVFbnRyeTxhbnk+PjtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWVvdXQgPSBERUZBVUxUX1RJTUVPVVQgfTogeyB0aW1lb3V0PzogbnVtYmVyIH0pIHtcbiAgICB0aGlzLnRpbWVvdXQgPSB0aW1lb3V0O1xuICAgIHRoaXMuZW50cmllcyA9IG5ldyBNYXA8c3RyaW5nLCBPRGF0YUNhY2hlRW50cnk8YW55Pj4oKTtcbiAgfVxuXG4gIGFic3RyYWN0IGdldFJlc3BvbnNlKHJlcTogT0RhdGFSZXF1ZXN0PGFueT4pOiBPRGF0YVJlc3BvbnNlPGFueT4gfCB1bmRlZmluZWQ7XG4gIGFic3RyYWN0IHB1dFJlc3BvbnNlKHJlcTogT0RhdGFSZXF1ZXN0PGFueT4sIHJlczogT0RhdGFSZXNwb25zZTxhbnk+KTogdm9pZDtcblxuICAvKipcbiAgICogVXNpbmcgdGhlIHJlc291cmNlIG9uIHRoZSByZXF1ZXN0IGJ1aWxkIGFuIGFycmF5IG9mIHN0cmluZyB0byBpZGVudGlmeSB0aGUgc2NvcGUgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHJlcSBUaGUgcmVxdWVzdCB3aXRoIHRoZSByZXNvdXJjZSB0byBidWlsZCB0aGUgc2NvcGVcbiAgICogQHJldHVybnMgQXJyYXkgb2Ygc3RyaW5nIHRvIGlkZW50aWZ5IHRoZSBzY29wZSBvZiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc2NvcGUocmVxOiBPRGF0YVJlcXVlc3Q8YW55Pik6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBzZWdtZW50cyA9IHJlcS5yZXNvdXJjZS5jbG9uZVNlZ21lbnRzKCk7XG4gICAgcmV0dXJuIHNlZ21lbnRzLnNlZ21lbnRzKHsga2V5OiB0cnVlIH0pLnJlZHVjZShcbiAgICAgIChhY2MsIHMpID0+IHtcbiAgICAgICAgaWYgKHMubmFtZSA9PT0gUGF0aFNlZ21lbnQuZW50aXR5U2V0KVxuICAgICAgICAgIGFjYyA9IFsuLi5hY2MsIHMucGF0aCgpIGFzIHN0cmluZ107XG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LFxuICAgICAgWydyZXF1ZXN0J10sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2luZyB0aGUgb2RhdGEgY29udGV4dCBvbiB0aGUgcmVzcG9uc2UgYnVpbGQgYW4gYXJyYXkgb2Ygc3RyaW5nIHRvIGlkZW50aWZ5IHRoZSB0YWdzIG9mIHRoZSByZXNwb25zZVxuICAgKiBAcGFyYW0gcmVzIFRoZSByZXNwb25zZSB0byBidWlsZCB0aGUgdGFnc1xuICAgKiBAcmV0dXJucyBBcnJheSBvZiBzdHJpbmcgdG8gaWRlbnRpZnkgdGhlIHRhZ3Mgb2YgdGhlIHJlc3BvbnNlXG4gICAqL1xuICB0YWdzKHJlczogT0RhdGFSZXNwb25zZTxhbnk+KTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHRhZ3MgPSBbXTtcbiAgICBjb25zdCBjb250ZXh0ID0gcmVzLmNvbnRleHQ7XG4gICAgaWYgKGNvbnRleHQuZW50aXR5U2V0KSB7XG4gICAgICB0YWdzLnB1c2goXG4gICAgICAgIGNvbnRleHQua2V5XG4gICAgICAgICAgPyBgJHtjb250ZXh0LmVudGl0eVNldH0oJHtjb250ZXh0LmtleX0pYFxuICAgICAgICAgIDogY29udGV4dC5lbnRpdHlTZXQsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoY29udGV4dC50eXBlKSB0YWdzLnB1c2goY29udGV4dC50eXBlKTtcbiAgICByZXR1cm4gdGFncztcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhbiBlbnRyeSBmcm9tIGEgcGF5bG9hZCBhbmQgc29tZSBvcHRpb25zXG4gICAqIEBwYXJhbSBwYXlsb2FkIFRoZSBwYXlsb2FkIHRvIHN0b3JlIGluIHRoZSBjYWNoZVxuICAgKiBAcGFyYW0gdGltZW91dCBUaGUgdGltZW91dCBmb3IgdGhlIGVudHJ5XG4gICAqIEBwYXJhbSB0YWdzIFRoZSB0YWdzIGZvciB0aGUgZW50cnlcbiAgICogQHJldHVybnMgVGhlIGVudHJ5IHRvIHN0b3JlIGluIHRoZSBjYWNoZVxuICAgKi9cbiAgYnVpbGRFbnRyeTxUPihcbiAgICBwYXlsb2FkOiBULFxuICAgIHsgdGltZW91dCwgdGFncyB9OiB7IHRpbWVvdXQ/OiBudW1iZXI7IHRhZ3M/OiBzdHJpbmdbXSB9LFxuICApOiBPRGF0YUNhY2hlRW50cnk8VD4ge1xuICAgIHJldHVybiB7XG4gICAgICBwYXlsb2FkLFxuICAgICAgbGFzdFJlYWQ6IERhdGUubm93KCksXG4gICAgICB0aW1lb3V0OiB0aW1lb3V0IHx8IHRoaXMudGltZW91dCxcbiAgICAgIHRhZ3M6IHRhZ3MgfHwgW10sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIGtleSBmcm9tIHN0b3JlIGFuIGVudHJ5IGluIHRoZSBjYWNoZVxuICAgKiBAcGFyYW0gbmFtZXMgVGhlIG5hbWVzIG9mIHRoZSBlbnRyeVxuICAgKiBAcmV0dXJucyBUaGUga2V5IGZvciB0aGUgZW50cnlcbiAgICovXG4gIGJ1aWxkS2V5KG5hbWVzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5hbWVzLmpvaW4oQ0FDSEVfS0VZX1NFUEFSQVRPUik7XG4gIH1cblxuICAvKipcbiAgICogUHV0IHNvbWUgcGF5bG9hZCBpbiB0aGUgY2FjaGVcbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgZm9yIHRoZSBlbnRyeVxuICAgKiBAcGFyYW0gcGF5bG9hZCBUaGUgcGF5bG9hZCB0byBzdG9yZSBpbiB0aGUgY2FjaGVcbiAgICogQHBhcmFtIHRpbWVvdXQgVGhlIHRpbWVvdXQgZm9yIHRoZSBlbnRyeVxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHNjb3BlIGZvciB0aGUgZW50cnlcbiAgICogQHBhcmFtIHRhZ3MgVGhlIHRhZ3MgZm9yIHRoZSBlbnRyeVxuICAgKi9cbiAgcHV0PFQ+KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBwYXlsb2FkOiBULFxuICAgIHtcbiAgICAgIHRpbWVvdXQsXG4gICAgICBzY29wZSxcbiAgICAgIHRhZ3MsXG4gICAgfTogeyB0aW1lb3V0PzogbnVtYmVyOyBzY29wZT86IHN0cmluZ1tdOyB0YWdzPzogc3RyaW5nW10gfSA9IHt9LFxuICApIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuYnVpbGRFbnRyeTxUPihwYXlsb2FkLCB7IHRpbWVvdXQsIHRhZ3MgfSk7XG4gICAgY29uc3Qga2V5ID0gdGhpcy5idWlsZEtleShbLi4uKHNjb3BlIHx8IFtdKSwgbmFtZV0pO1xuICAgIHRoaXMuZW50cmllcy5zZXQoa2V5LCBlbnRyeSk7XG4gICAgdGhpcy5mb3JnZXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHBheWxvYWQgZnJvbSB0aGUgY2FjaGUgaWYgaXQgZXhpc3RzIGFuZCBpcyBub3QgZXhwaXJlZFxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZW50cnlcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBzY29wZSBvZiB0aGUgZW50cnlcbiAgICogQHJldHVybnMgVGhlIHBheWxvYWQgb2YgdGhlIGVudHJ5XG4gICAqL1xuICBnZXQ8VD4obmFtZTogc3RyaW5nLCB7IHNjb3BlIH06IHsgc2NvcGU/OiBzdHJpbmdbXSB9ID0ge30pOiBUIHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmJ1aWxkS2V5KFsuLi4oc2NvcGUgfHwgW10pLCBuYW1lXSk7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gICAgcmV0dXJuIGVudHJ5ICE9PSB1bmRlZmluZWQgJiYgIXRoaXMuaXNFeHBpcmVkKGVudHJ5KVxuICAgICAgPyBlbnRyeS5wYXlsb2FkXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYWxsIGNhY2hlIGVudHJpZXMgdGhhdCBhcmUgbWF0Y2hpbmcgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9uc1xuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgb3B0aW9ucyB0byBmb3JnZXRcbiAgICovXG4gIGZvcmdldCh7XG4gICAgbmFtZSxcbiAgICBzY29wZSA9IFtdLFxuICAgIHRhZ3MgPSBbXSxcbiAgfTogeyBuYW1lPzogc3RyaW5nOyBzY29wZT86IHN0cmluZ1tdOyB0YWdzPzogc3RyaW5nW10gfSA9IHt9KSB7XG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkgc2NvcGUucHVzaChuYW1lKTtcbiAgICBjb25zdCBrZXkgPSBzY29wZS5sZW5ndGggPiAwID8gdGhpcy5idWlsZEtleShzY29wZSkgOiB1bmRlZmluZWQ7XG4gICAgdGhpcy5lbnRyaWVzLmZvckVhY2goKGVudHJ5LCBrKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuaXNFeHBpcmVkKGVudHJ5KSB8fCAvLyBFeHBpcmVkXG4gICAgICAgIChrZXkgIT09IHVuZGVmaW5lZCAmJiBrLnN0YXJ0c1dpdGgoa2V5KSkgfHwgLy8gS2V5XG4gICAgICAgICh0YWdzLmxlbmd0aCA+IDAgJiYgdGFncy5zb21lKCh0KSA9PiBlbnRyeS50YWdzLmluZGV4T2YodCkgIT09IC0xKSkgLy8gVGFnc1xuICAgICAgKSB7XG4gICAgICAgIHRoaXMuZW50cmllcy5kZWxldGUoayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFsbCBjYWNoZSBlbnRyaWVzXG4gICAqL1xuICBmbHVzaCgpIHtcbiAgICB0aGlzLmVudHJpZXMgPSBuZXcgTWFwPHN0cmluZywgT0RhdGFDYWNoZUVudHJ5PGFueT4+KCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGVudHJ5IGlzIGV4cGlyZWRcbiAgICogQHBhcmFtIGVudHJ5IFRoZSBjYWNoZSBlbnRyeVxuICAgKiBAcmV0dXJucyBCb29sZWFuIGluZGljYXRpbmcgaWYgdGhlIGVudHJ5IGlzIGV4cGlyZWRcbiAgICovXG4gIGlzRXhwaXJlZChlbnRyeTogT0RhdGFDYWNoZUVudHJ5PGFueT4pIHtcbiAgICByZXR1cm4gZW50cnkubGFzdFJlYWQgPCBEYXRlLm5vdygpIC0gKGVudHJ5LnRpbWVvdXQgfHwgdGhpcy50aW1lb3V0KSAqIDEwMDA7XG4gIH1cblxuICAvKipcbiAgICogVXNpbmcgdGhlIHJlcXVlc3QsIGhhbmRsZSB0aGUgZmV0Y2hpbmcgb2YgdGhlIHJlc3BvbnNlXG4gICAqIEBwYXJhbSByZXEgVGhlIHJlcXVlc3QgdG8gZmV0Y2hcbiAgICogQHBhcmFtIHJlcyQgT2JzZXJ2YWJsZSBvZiB0aGUgcmVzcG9uc2VcbiAgICogQHJldHVybnNcbiAgICovXG4gIGhhbmRsZVJlcXVlc3QoXG4gICAgcmVxOiBPRGF0YVJlcXVlc3Q8YW55PixcbiAgICByZXMkOiBPYnNlcnZhYmxlPE9EYXRhUmVzcG9uc2U8YW55Pj4sXG4gICk6IE9ic2VydmFibGU8T0RhdGFSZXNwb25zZTxhbnk+PiB7XG4gICAgcmV0dXJuIHJlcS5pc0ZldGNoKClcbiAgICAgID8gdGhpcy5oYW5kbGVGZXRjaChyZXEsIHJlcyQpXG4gICAgICA6IHJlcS5pc011dGF0ZSgpXG4gICAgICAgID8gdGhpcy5oYW5kbGVNdXRhdGUocmVxLCByZXMkKVxuICAgICAgICA6IHJlcyQ7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUZldGNoKFxuICAgIHJlcTogT0RhdGFSZXF1ZXN0PGFueT4sXG4gICAgcmVzJDogT2JzZXJ2YWJsZTxPRGF0YVJlc3BvbnNlPGFueT4+LFxuICApOiBPYnNlcnZhYmxlPE9EYXRhUmVzcG9uc2U8YW55Pj4ge1xuICAgIGNvbnN0IHBvbGljeSA9IHJlcS5mZXRjaFBvbGljeTtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmdldFJlc3BvbnNlKHJlcSk7XG4gICAgaWYgKHBvbGljeSA9PT0gJ25vLWNhY2hlJykge1xuICAgICAgcmV0dXJuIHJlcyQ7XG4gICAgfVxuICAgIGlmIChwb2xpY3kgPT09ICdjYWNoZS1vbmx5Jykge1xuICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICByZXR1cm4gb2YoY2FjaGVkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcignTm8gQ2FjaGVkJykpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoXG4gICAgICBwb2xpY3kgPT09ICdjYWNoZS1maXJzdCcgfHxcbiAgICAgIHBvbGljeSA9PT0gJ2NhY2hlLWFuZC1uZXR3b3JrJyB8fFxuICAgICAgcG9saWN5ID09PSAnbmV0d29yay1vbmx5J1xuICAgICkge1xuICAgICAgcmVzJCA9IHJlcyQucGlwZShcbiAgICAgICAgdGFwKChyZXM6IE9EYXRhUmVzcG9uc2U8YW55PikgPT4ge1xuICAgICAgICAgIGlmIChyZXMub3B0aW9ucy5jYWNoZWFiaWxpdHkgIT09ICduby1zdG9yZScpXG4gICAgICAgICAgICB0aGlzLnB1dFJlc3BvbnNlKHJlcSwgcmVzKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkICE9PSB1bmRlZmluZWQgJiYgcG9saWN5ICE9PSAnbmV0d29yay1vbmx5J1xuICAgICAgPyBwb2xpY3kgPT09ICdjYWNoZS1hbmQtbmV0d29yaydcbiAgICAgICAgPyByZXMkLnBpcGUoc3RhcnRXaXRoKGNhY2hlZCkpXG4gICAgICAgIDogb2YoY2FjaGVkKVxuICAgICAgOiByZXMkO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVNdXRhdGUoXG4gICAgcmVxOiBPRGF0YVJlcXVlc3Q8YW55PixcbiAgICByZXMkOiBPYnNlcnZhYmxlPE9EYXRhUmVzcG9uc2U8YW55Pj4sXG4gICk6IE9ic2VydmFibGU8T0RhdGFSZXNwb25zZTxhbnk+PiB7XG4gICAgY29uc3QgcmVxdWVzdHMgPSByZXEuaXNCYXRjaCgpXG4gICAgICA/IChyZXEucmVzb3VyY2UgYXMgT0RhdGFCYXRjaFJlc291cmNlKVxuICAgICAgICAgIC5yZXF1ZXN0cygpXG4gICAgICAgICAgLmZpbHRlcigocikgPT4gci5pc011dGF0ZSgpKVxuICAgICAgOiBbcmVxXTtcbiAgICBmb3IgKHZhciByIG9mIHJlcXVlc3RzKSB7XG4gICAgICBjb25zdCBzY29wZSA9IHRoaXMuc2NvcGUocik7XG4gICAgICB0aGlzLmZvcmdldCh7IHNjb3BlIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzJDtcbiAgfVxufVxuIl19