UNPKG

apollo-angular

Version:

Use your GraphQL data in your Angular app, with the Apollo Client

142 lines 19.1 kB
import { Injectable } from '@angular/core'; import { Observable as LinkObservable } from '@apollo/client/core'; import { print } from 'graphql'; import { TestOperation } from './operation'; import * as i0 from "@angular/core"; /** * A testing backend for `Apollo`. * * `ApolloTestingBackend` works by keeping a list of all open operations. * As operations come in, they're added to the list. Users can assert that specific * operations were made and then flush them. In the end, a `verify()` method asserts * that no unexpected operations were made. */ export class ApolloTestingBackend { constructor() { /** * List of pending operations which have not yet been expected. */ this.open = []; } /** * Handle an incoming operation by queueing it in the list of open operations. */ handle(op) { return new LinkObservable((observer) => { const testOp = new TestOperation(op, observer); this.open.push(testOp); }); } /** * Helper function to search for operations in the list of open operations. */ _match(match) { if (typeof match === 'string') { return this.open.filter((testOp) => testOp.operation.operationName === match); } else if (typeof match === 'function') { return this.open.filter((testOp) => match(testOp.operation)); } else { if (this.isDocumentNode(match)) { return this.open.filter((testOp) => print(testOp.operation.query) === print(match)); } return this.open.filter((testOp) => this.matchOp(match, testOp)); } } matchOp(match, testOp) { const variables = JSON.stringify(match.variables); const extensions = JSON.stringify(match.extensions); const sameName = this.compare(match.operationName, testOp.operation.operationName); const sameVariables = this.compare(variables, testOp.operation.variables); const sameQuery = print(testOp.operation.query) === print(match.query); const sameExtensions = this.compare(extensions, testOp.operation.extensions); return sameName && sameVariables && sameQuery && sameExtensions; } compare(expected, value) { const prepare = (val) => typeof val === 'string' ? val : JSON.stringify(val); const received = prepare(value); return !expected || received === expected; } /** * Search for operations in the list of open operations, and return all that match * without asserting anything about the number of matches. */ match(match) { const results = this._match(match); results.forEach((result) => { const index = this.open.indexOf(result); if (index !== -1) { this.open.splice(index, 1); } }); return results; } /** * Expect that a single outstanding request matches the given matcher, and return * it. * * operations returned through this API will no longer be in the list of open operations, * and thus will not match twice. */ expectOne(match, description) { description = description || this.descriptionFromMatcher(match); const matches = this.match(match); if (matches.length > 1) { throw new Error(`Expected one matching operation for criteria "${description}", found ${matches.length} operations.`); } if (matches.length === 0) { throw new Error(`Expected one matching operation for criteria "${description}", found none.`); } return matches[0]; } /** * Expect that no outstanding operations match the given matcher, and throw an error * if any do. */ expectNone(match, description) { description = description || this.descriptionFromMatcher(match); const matches = this.match(match); if (matches.length > 0) { throw new Error(`Expected zero matching operations for criteria "${description}", found ${matches.length}.`); } } /** * Validate that there are no outstanding operations. */ verify() { const open = this.open; if (open.length > 0) { // Show the methods and URLs of open operations in the error, for convenience. const operations = open .map((testOp) => testOp.operation.operationName) .join(', '); throw new Error(`Expected no open operations, found ${open.length}: ${operations}`); } } isDocumentNode(docOrOp) { return !docOrOp.operationName; } descriptionFromMatcher(matcher) { if (typeof matcher === 'string') { return `Match operationName: ${matcher}`; } else if (typeof matcher === 'object') { if (this.isDocumentNode(matcher)) { return `Match DocumentNode`; } const name = matcher.operationName || '(any)'; const variables = JSON.stringify(matcher.variables) || '(any)'; return `Match operation: ${name}, variables: ${variables}`; } else { return `Match by function: ${matcher.name}`; } } } ApolloTestingBackend.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.5", ngImport: i0, type: ApolloTestingBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); ApolloTestingBackend.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.5", ngImport: i0, type: ApolloTestingBackend }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.5", ngImport: i0, type: ApolloTestingBackend, decorators: [{ type: Injectable }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2VuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3Rpbmcvc3JjL2JhY2tlbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQWMsVUFBVSxJQUFJLGNBQWMsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQzlFLE9BQU8sRUFBQyxLQUFLLEVBQWUsTUFBTSxTQUFTLENBQUM7QUFHNUMsT0FBTyxFQUFDLGFBQWEsRUFBWSxNQUFNLGFBQWEsQ0FBQzs7QUFFckQ7Ozs7Ozs7R0FPRztBQUVILE1BQU0sT0FBTyxvQkFBb0I7SUFEakM7UUFFRTs7V0FFRztRQUNLLFNBQUksR0FBb0IsRUFBRSxDQUFDO0tBeUpwQztJQXZKQzs7T0FFRztJQUNJLE1BQU0sQ0FBQyxFQUFhO1FBQ3pCLE9BQU8sSUFBSSxjQUFjLENBQUMsQ0FBQyxRQUF1QixFQUFFLEVBQUU7WUFDcEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxhQUFhLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ssTUFBTSxDQUFDLEtBQXFCO1FBQ2xDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFO1lBQzdCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQ3JCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsS0FBSyxLQUFLLENBQ3JELENBQUM7U0FDSDthQUFNLElBQUksT0FBTyxLQUFLLEtBQUssVUFBVSxFQUFFO1lBQ3RDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FB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QyxhQUFhLENBQUM7SUFDL0MsQ0FBQztJQUVPLHNCQUFzQixDQUFDLE9BQXVCO1FBQ3BELElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO1lBQy9CLE9BQU8sd0JBQXdCLE9BQU8sRUFBRSxDQUFDO1NBQzFDO2FBQU0sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7WUFDdEMsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNoQyxPQUFPLG9CQUFvQixDQUFDO2FBQzdCO1lBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUM7WUFDOUMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksT0FBTyxDQUFDO1lBRS9ELE9BQU8sb0JBQW9CLElBQUksZ0JBQWdCLFNBQVMsRUFBRSxDQUFDO1NBQzVEO2FBQU07WUFDTCxPQUFPLHNCQUFzQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDN0M7SUFDSCxDQUFDOztpSEE1SlUsb0JBQW9CO3FIQUFwQixvQkFBb0I7MkZBQXBCLG9CQUFvQjtrQkFEaEMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmVyfSBmcm9tICdyeGpzJztcbmltcG9ydCB7RmV0Y2hSZXN1bHQsIE9ic2VydmFibGUgYXMgTGlua09ic2VydmFibGV9IGZyb20gJ0BhcG9sbG8vY2xpZW50L2NvcmUnO1xuaW1wb3J0IHtwcmludCwgRG9jdW1lbnROb2RlfSBmcm9tICdncmFwaHFsJztcblxuaW1wb3J0IHtBcG9sbG9UZXN0aW5nQ29udHJvbGxlciwgTWF0Y2hPcGVyYXRpb259IGZyb20gJy4vY29udHJvbGxlcic7XG5pbXBvcnQge1Rlc3RPcGVyYXRpb24sIE9wZXJhdGlvbn0gZnJvbSAnLi9vcGVyYXRpb24nO1xuXG4vKipcbiAqIEEgdGVzdGluZyBiYWNrZW5kIGZvciBgQXBvbGxvYC5cbiAqXG4gKiBgQXBvbGxvVGVzdGluZ0JhY2tlbmRgIHdvcmtzIGJ5IGtlZXBpbmcgYSBsaXN0IG9mIGFsbCBvcGVuIG9wZXJhdGlvbnMuXG4gKiBBcyBvcGVyYXRpb25zIGNvbWUgaW4sIHRoZXkncmUgYWRkZWQgdG8gdGhlIGxpc3QuIFVzZXJzIGNhbiBhc3NlcnQgdGhhdCBzcGVjaWZpY1xuICogb3BlcmF0aW9ucyB3ZXJlIG1hZGUgYW5kIHRoZW4gZmx1c2ggdGhlbS4gSW4gdGhlIGVuZCwgYSBgdmVyaWZ5KClgIG1ldGhvZCBhc3NlcnRzXG4gKiB0aGF0IG5vIHVuZXhwZWN0ZWQgb3BlcmF0aW9ucyB3ZXJlIG1hZGUuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBcG9sbG9UZXN0aW5nQmFja2VuZCBpbXBsZW1lbnRzIEFwb2xsb1Rlc3RpbmdDb250cm9sbGVyIHtcbiAgLyoqXG4gICAqIExpc3Qgb2YgcGVuZGluZyBvcGVyYXRpb25zIHdoaWNoIGhhdmUgbm90IHlldCBiZWVuIGV4cGVjdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBvcGVuOiBUZXN0T3BlcmF0aW9uW10gPSBbXTtcblxuICAvKipcbiAgICogSGFuZGxlIGFuIGluY29taW5nIG9wZXJhdGlvbiBieSBxdWV1ZWluZyBpdCBpbiB0aGUgbGlzdCBvZiBvcGVuIG9wZXJhdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlKG9wOiBPcGVyYXRpb24pOiBMaW5rT2JzZXJ2YWJsZTxGZXRjaFJlc3VsdD4ge1xuICAgIHJldHVybiBuZXcgTGlua09ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxhbnk+KSA9PiB7XG4gICAgICBjb25zdCB0ZXN0T3AgPSBuZXcgVGVzdE9wZXJhdGlvbihvcCwgb2JzZXJ2ZXIpO1xuICAgICAgdGhpcy5vcGVuLnB1c2godGVzdE9wKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gc2VhcmNoIGZvciBvcGVyYXRpb25zIGluIHRoZSBsaXN0IG9mIG9wZW4gb3BlcmF0aW9ucy5cbiAgICovXG4gIHByaXZhdGUgX21hdGNoKG1hdGNoOiBNYXRjaE9wZXJhdGlvbik6IFRlc3RPcGVyYXRpb25bXSB7XG4gICAgaWYgKHR5cGVvZiBtYXRjaCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB0aGlzLm9wZW4uZmlsdGVyKFxuICAgICAgICAodGVzdE9wKSA9PiB0ZXN0T3Aub3BlcmF0aW9uLm9wZXJhdGlvbk5hbWUgPT09IG1hdGNoLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYXRjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHRoaXMub3Blbi5maWx0ZXIoKHRlc3RPcCkgPT4gbWF0Y2godGVzdE9wLm9wZXJhdGlvbikpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5pc0RvY3VtZW50Tm9kZShtYXRjaCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3Blbi5maWx0ZXIoXG4gICAgICAgICAgKHRlc3RPcCkgPT4gcHJpbnQodGVzdE9wLm9wZXJhdGlvbi5xdWVyeSkgPT09IHByaW50KG1hdGNoKSxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub3Blbi5maWx0ZXIoKHRlc3RPcCkgPT4gdGhpcy5tYXRjaE9wKG1hdGNoLCB0ZXN0T3ApKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1hdGNoT3AobWF0Y2g6IE9wZXJhdGlvbiwgdGVzdE9wOiBUZXN0T3BlcmF0aW9uKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdmFyaWFibGVzID0gSlNPTi5zdHJpbmdpZnkobWF0Y2gudmFyaWFibGVzKTtcbiAgICBjb25zdCBleHRlbnNpb25zID0gSlNPTi5zdHJpbmdpZnkobWF0Y2guZXh0ZW5zaW9ucyk7XG5cbiAgICBjb25zdCBzYW1lTmFtZSA9IHRoaXMuY29tcGFyZShcbiAgICAgIG1hdGNoLm9wZXJhdGlvbk5hbWUsXG4gICAgICB0ZXN0T3Aub3BlcmF0aW9uLm9wZXJhdGlvbk5hbWUsXG4gICAgKTtcbiAgICBjb25zdCBzYW1lVmFyaWFibGVzID0gdGhpcy5jb21wYXJlKHZhcmlhYmxlcywgdGVzdE9wLm9wZXJhdGlvbi52YXJpYWJsZXMpO1xuXG4gICAgY29uc3Qgc2FtZVF1ZXJ5ID0gcHJpbnQodGVzdE9wLm9wZXJhdGlvbi5xdWVyeSkgPT09IHByaW50KG1hdGNoLnF1ZXJ5KTtcblxuICAgIGNvbnN0IHNhbWVFeHRlbnNpb25zID0gdGhpcy5jb21wYXJlKFxuICAgICAgZXh0ZW5zaW9ucyxcbiAgICAgIHRlc3RPcC5vcGVyYXRpb24uZXh0ZW5zaW9ucyxcbiAgICApO1xuXG4gICAgcmV0dXJuIHNhbWVOYW1lICYmIHNhbWVWYXJpYWJsZXMgJiYgc2FtZVF1ZXJ5ICYmIHNhbWVFeHRlbnNpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBjb21wYXJlKGV4cGVjdGVkPzogc3RyaW5nLCB2YWx1ZT86IE9iamVjdCB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHByZXBhcmUgPSAodmFsOiBhbnkpID0+XG4gICAgICB0eXBlb2YgdmFsID09PSAnc3RyaW5nJyA/IHZhbCA6IEpTT04uc3RyaW5naWZ5KHZhbCk7XG4gICAgY29uc3QgcmVjZWl2ZWQgPSBwcmVwYXJlKHZhbHVlKTtcblxuICAgIHJldHVybiAhZXhwZWN0ZWQgfHwgcmVjZWl2ZWQgPT09IGV4cGVjdGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlYXJjaCBmb3Igb3BlcmF0aW9ucyBpbiB0aGUgbGlzdCBvZiBvcGVuIG9wZXJhdGlvbnMsIGFuZCByZXR1cm4gYWxsIHRoYXQgbWF0Y2hcbiAgICogd2l0aG91dCBhc3NlcnRpbmcgYW55dGhpbmcgYWJvdXQgdGhlIG51bWJlciBvZiBtYXRjaGVzLlxuICAgKi9cbiAgcHVibGljIG1hdGNoKG1hdGNoOiBNYXRjaE9wZXJhdGlvbik6IFRlc3RPcGVyYXRpb25bXSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IHRoaXMuX21hdGNoKG1hdGNoKTtcblxuICAgIHJlc3VsdHMuZm9yRWFjaCgocmVzdWx0KSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMub3Blbi5pbmRleE9mKHJlc3VsdCk7XG4gICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgIHRoaXMub3Blbi5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGVjdCB0aGF0IGEgc2luZ2xlIG91dHN0YW5kaW5nIHJlcXVlc3QgbWF0Y2hlcyB0aGUgZ2l2ZW4gbWF0Y2hlciwgYW5kIHJldHVyblxuICAgKiBpdC5cbiAgICpcbiAgICogb3BlcmF0aW9ucyByZXR1cm5lZCB0aHJvdWdoIHRoaXMgQVBJIHdpbGwgbm8gbG9uZ2VyIGJlIGluIHRoZSBsaXN0IG9mIG9wZW4gb3BlcmF0aW9ucyxcbiAgICogYW5kIHRodXMgd2lsbCBub3QgbWF0Y2ggdHdpY2UuXG4gICAqL1xuICBwdWJsaWMgZXhwZWN0T25lKG1hdGNoOiBNYXRjaE9wZXJhdGlvbiwgZGVzY3JpcHRpb24/OiBzdHJpbmcpOiBUZXN0T3BlcmF0aW9uIHtcbiAgICBkZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uIHx8IHRoaXMuZGVzY3JpcHRpb25Gcm9tTWF0Y2hlcihtYXRjaCk7XG4gICAgY29uc3QgbWF0Y2hlcyA9IHRoaXMubWF0Y2gobWF0Y2gpO1xuICAgIGlmIChtYXRjaGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkIG9uZSBtYXRjaGluZyBvcGVyYXRpb24gZm9yIGNyaXRlcmlhIFwiJHtkZXNjcmlwdGlvbn1cIiwgZm91bmQgJHttYXRjaGVzLmxlbmd0aH0gb3BlcmF0aW9ucy5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKG1hdGNoZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCBvbmUgbWF0Y2hpbmcgb3BlcmF0aW9uIGZvciBjcml0ZXJpYSBcIiR7ZGVzY3JpcHRpb259XCIsIGZvdW5kIG5vbmUuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBtYXRjaGVzWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGVjdCB0aGF0IG5vIG91dHN0YW5kaW5nIG9wZXJhdGlvbnMgbWF0Y2ggdGhlIGdpdmVuIG1hdGNoZXIsIGFuZCB0aHJvdyBhbiBlcnJvclxuICAgKiBpZiBhbnkgZG8uXG4gICAqL1xuICBwdWJsaWMgZXhwZWN0Tm9uZShtYXRjaDogTWF0Y2hPcGVyYXRpb24sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZCB7XG4gICAgZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbiB8fCB0aGlzLmRlc2NyaXB0aW9uRnJvbU1hdGNoZXIobWF0Y2gpO1xuICAgIGNvbnN0IG1hdGNoZXMgPSB0aGlzLm1hdGNoKG1hdGNoKTtcbiAgICBpZiAobWF0Y2hlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCB6ZXJvIG1hdGNoaW5nIG9wZXJhdGlvbnMgZm9yIGNyaXRlcmlhIFwiJHtkZXNjcmlwdGlvbn1cIiwgZm91bmQgJHttYXRjaGVzLmxlbmd0aH0uYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgdGhlcmUgYXJlIG5vIG91dHN0YW5kaW5nIG9wZXJhdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgdmVyaWZ5KCk6IHZvaWQge1xuICAgIGNvbnN0IG9wZW4gPSB0aGlzLm9wZW47XG5cbiAgICBpZiAob3Blbi5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBTaG93IHRoZSBtZXRob2RzIGFuZCBVUkxzIG9mIG9wZW4gb3BlcmF0aW9ucyBpbiB0aGUgZXJyb3IsIGZvciBjb252ZW5pZW5jZS5cbiAgICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBvcGVuXG4gICAgICAgIC5tYXAoKHRlc3RPcCkgPT4gdGVzdE9wLm9wZXJhdGlvbi5vcGVyYXRpb25OYW1lKVxuICAgICAgICAuam9pbignLCAnKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkIG5vIG9wZW4gb3BlcmF0aW9ucywgZm91bmQgJHtvcGVuLmxlbmd0aH06ICR7b3BlcmF0aW9uc31gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzRG9jdW1lbnROb2RlKFxuICAgIGRvY09yT3A6IERvY3VtZW50Tm9kZSB8IE9wZXJhdGlvbixcbiAgKTogZG9jT3JPcCBpcyBEb2N1bWVudE5vZGUge1xuICAgIHJldHVybiAhKGRvY09yT3AgYXMgT3BlcmF0aW9uKS5vcGVyYXRpb25OYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBkZXNjcmlwdGlvbkZyb21NYXRjaGVyKG1hdGNoZXI6IE1hdGNoT3BlcmF0aW9uKTogc3RyaW5nIHtcbiAgICBpZiAodHlwZW9mIG1hdGNoZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gYE1hdGNoIG9wZXJhdGlvbk5hbWU6ICR7bWF0Y2hlcn1gO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1hdGNoZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAodGhpcy5pc0RvY3VtZW50Tm9kZShtYXRjaGVyKSkge1xuICAgICAgICByZXR1cm4gYE1hdGNoIERvY3VtZW50Tm9kZWA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hbWUgPSBtYXRjaGVyLm9wZXJhdGlvbk5hbWUgfHwgJyhhbnkpJztcbiAgICAgIGNvbnN0IHZhcmlhYmxlcyA9IEpTT04uc3RyaW5naWZ5KG1hdGNoZXIudmFyaWFibGVzKSB8fCAnKGFueSknO1xuXG4gICAgICByZXR1cm4gYE1hdGNoIG9wZXJhdGlvbjogJHtuYW1lfSwgdmFyaWFibGVzOiAke3ZhcmlhYmxlc31gO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYE1hdGNoIGJ5IGZ1bmN0aW9uOiAke21hdGNoZXIubmFtZX1gO1xuICAgIH1cbiAgfVxufVxuIl19