UNPKG

angular-odata

Version:

Client side OData typescript library for Angular

177 lines 22 kB
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