oidc-client
Version:
OpenID Connect (OIDC) & OAuth2 client library
247 lines • 37.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const core_1 = require("@angular-devkit/core");
const schematics_1 = require("@angular-devkit/schematics");
const ts = require("typescript");
const ast_utils_1 = require("../utility/ast-utils");
const change_1 = require("../utility/change");
const config_1 = require("../utility/config");
const ng_ast_utils_1 = require("../utility/ng-ast-utils");
const project_1 = require("../utility/project");
const project_targets_1 = require("../utility/project-targets");
const workspace_models_1 = require("../utility/workspace-models");
function getSourceFile(host, path) {
const buffer = host.read(path);
if (!buffer) {
throw new schematics_1.SchematicsException(`Could not find ${path}.`);
}
const content = buffer.toString();
const source = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
return source;
}
function getServerModulePath(host, project, architect) {
const mainPath = architect.server.options.main;
const mainSource = getSourceFile(host, mainPath);
const allNodes = ast_utils_1.getSourceNodes(mainSource);
const expNode = allNodes.filter(node => node.kind === ts.SyntaxKind.ExportDeclaration)[0];
if (!expNode) {
return null;
}
const relativePath = expNode.moduleSpecifier;
const modulePath = core_1.normalize(`/${project.root}/src/${relativePath.text}.ts`);
return modulePath;
}
function getComponentTemplateInfo(host, componentPath) {
const compSource = getSourceFile(host, componentPath);
const compMetadata = ast_utils_1.getDecoratorMetadata(compSource, 'Component', '@angular/core')[0];
return {
templateProp: getMetadataProperty(compMetadata, 'template'),
templateUrlProp: getMetadataProperty(compMetadata, 'templateUrl'),
};
}
function getComponentTemplate(host, compPath, tmplInfo) {
let template = '';
if (tmplInfo.templateProp) {
template = tmplInfo.templateProp.getFullText();
}
else if (tmplInfo.templateUrlProp) {
const templateUrl = tmplInfo.templateUrlProp.initializer.text;
const dir = core_1.dirname(core_1.normalize(compPath));
const templatePath = core_1.join(dir, templateUrl);
const buffer = host.read(templatePath);
if (buffer) {
template = buffer.toString();
}
}
return template;
}
function getBootstrapComponentPath(host, project) {
const projectTargets = project_targets_1.getProjectTargets(project);
if (!projectTargets.build) {
throw project_targets_1.targetBuildNotFoundError();
}
const mainPath = projectTargets.build.options.main;
const modulePath = ng_ast_utils_1.getAppModulePath(host, mainPath);
const moduleSource = getSourceFile(host, modulePath);
const metadataNode = ast_utils_1.getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core')[0];
const bootstrapProperty = getMetadataProperty(metadataNode, 'bootstrap');
const arrLiteral = bootstrapProperty
.initializer;
const componentSymbol = arrLiteral.elements[0].getText();
const relativePath = ast_utils_1.getSourceNodes(moduleSource)
.filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
.filter(imp => {
return ast_utils_1.findNode(imp, ts.SyntaxKind.Identifier, componentSymbol);
})
.map((imp) => {
const pathStringLiteral = imp.moduleSpecifier;
return pathStringLiteral.text;
})[0];
return core_1.join(core_1.dirname(core_1.normalize(modulePath)), relativePath + '.ts');
}
// end helper functions.
function validateProject(options) {
return (host, context) => {
const routerOutletCheckRegex = /<router\-outlet.*?>([\s\S]*?)<\/router\-outlet>/;
const clientProject = project_1.getProject(host, options.clientProject);
if (clientProject.projectType !== 'application') {
throw new schematics_1.SchematicsException(`App shell requires a project type of "application".`);
}
const componentPath = getBootstrapComponentPath(host, clientProject);
const tmpl = getComponentTemplateInfo(host, componentPath);
const template = getComponentTemplate(host, componentPath, tmpl);
if (!routerOutletCheckRegex.test(template)) {
const errorMsg = `Prerequisite for app shell is to define a router-outlet in your root component.`;
context.logger.error(errorMsg);
throw new schematics_1.SchematicsException(errorMsg);
}
};
}
function addUniversalTarget(options) {
return (host, context) => {
const architect = project_targets_1.getProjectTargets(host, options.clientProject);
if (architect.server) {
return host;
}
// Copy options.
const universalOptions = Object.assign({}, options);
// Delete non-universal options.
delete universalOptions.universalProject;
delete universalOptions.route;
delete universalOptions.name;
delete universalOptions.outDir;
delete universalOptions.root;
delete universalOptions.index;
delete universalOptions.sourceDir;
return schematics_1.schematic('universal', universalOptions);
};
}
function addAppShellConfigToWorkspace(options) {
return (host) => {
if (!options.route) {
throw new schematics_1.SchematicsException(`Route is not defined`);
}
const workspace = config_1.getWorkspace(host);
const projectTargets = project_targets_1.getProjectTargets(workspace, options.clientProject);
projectTargets['app-shell'] = {
builder: workspace_models_1.Builders.AppShell,
options: {
browserTarget: `${options.clientProject}:build`,
serverTarget: `${options.clientProject}:server`,
route: options.route,
},
configurations: {
production: {
browserTarget: `${options.clientProject}:build:production`,
serverTarget: `${options.clientProject}:server:production`,
},
},
};
return config_1.updateWorkspace(workspace);
};
}
function addRouterModule(options) {
return (host) => {
const projectTargets = project_targets_1.getProjectTargets(host, options.clientProject);
if (!projectTargets.build) {
throw project_targets_1.targetBuildNotFoundError();
}
const mainPath = projectTargets.build.options.main;
const modulePath = ng_ast_utils_1.getAppModulePath(host, mainPath);
const moduleSource = getSourceFile(host, modulePath);
const changes = ast_utils_1.addImportToModule(moduleSource, modulePath, 'RouterModule', '@angular/router');
const recorder = host.beginUpdate(modulePath);
changes.forEach((change) => {
if (change instanceof change_1.InsertChange) {
recorder.insertLeft(change.pos, change.toAdd);
}
});
host.commitUpdate(recorder);
return host;
};
}
function getMetadataProperty(metadata, propertyName) {
const properties = metadata.properties;
const property = properties
.filter(prop => prop.kind === ts.SyntaxKind.PropertyAssignment)
.filter((prop) => {
const name = prop.name;
switch (name.kind) {
case ts.SyntaxKind.Identifier:
return name.getText() === propertyName;
case ts.SyntaxKind.StringLiteral:
return name.text === propertyName;
}
return false;
})[0];
return property;
}
function addServerRoutes(options) {
return (host) => {
const clientProject = project_1.getProject(host, options.clientProject);
const architect = project_targets_1.getProjectTargets(clientProject);
// const mainPath = universalArchitect.build.options.main;
const modulePath = getServerModulePath(host, clientProject, architect);
if (modulePath === null) {
throw new schematics_1.SchematicsException('Universal/server module not found.');
}
let moduleSource = getSourceFile(host, modulePath);
if (!ast_utils_1.isImported(moduleSource, 'Routes', '@angular/router')) {
const recorder = host.beginUpdate(modulePath);
const routesChange = ast_utils_1.insertImport(moduleSource, modulePath, 'Routes', '@angular/router');
if (routesChange.toAdd) {
recorder.insertLeft(routesChange.pos, routesChange.toAdd);
}
const imports = ast_utils_1.getSourceNodes(moduleSource)
.filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
.sort((a, b) => a.getStart() - b.getStart());
const insertPosition = imports[imports.length - 1].getEnd();
const routeText = `\n\nconst routes: Routes = [ { path: '${options.route}', component: AppShellComponent }];`;
recorder.insertRight(insertPosition, routeText);
host.commitUpdate(recorder);
}
moduleSource = getSourceFile(host, modulePath);
if (!ast_utils_1.isImported(moduleSource, 'RouterModule', '@angular/router')) {
const recorder = host.beginUpdate(modulePath);
const routerModuleChange = ast_utils_1.insertImport(moduleSource, modulePath, 'RouterModule', '@angular/router');
if (routerModuleChange.toAdd) {
recorder.insertLeft(routerModuleChange.pos, routerModuleChange.toAdd);
}
const metadataChange = ast_utils_1.addSymbolToNgModuleMetadata(moduleSource, modulePath, 'imports', 'RouterModule.forRoot(routes)');
if (metadataChange) {
metadataChange.forEach((change) => {
recorder.insertRight(change.pos, change.toAdd);
});
}
host.commitUpdate(recorder);
}
return host;
};
}
function addShellComponent(options) {
const componentOptions = {
name: 'app-shell',
module: options.rootModuleFileName,
project: options.clientProject,
};
return schematics_1.schematic('component', componentOptions);
}
function default_1(options) {
return schematics_1.chain([
validateProject(options),
addUniversalTarget(options),
addAppShellConfigToWorkspace(options),
addRouterModule(options),
addServerRoutes(options),
addShellComponent(options),
]);
}
exports.default = default_1;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInBhY2thZ2VzL3NjaGVtYXRpY3MvYW5ndWxhci9hcHAtc2hlbGwvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7O0dBTUc7QUFDSCwrQ0FBOEU7QUFDOUUsMkRBT29DO0FBQ3BDLGlDQUFpQztBQUVqQyxvREFROEI7QUFDOUIsOENBQXlEO0FBQ3pELDhDQUFrRTtBQUNsRSwwREFBMkQ7QUFDM0QsZ0RBQWdEO0FBQ2hELGdFQUF5RjtBQUN6RixrRUFBeUU7QUFHekUsU0FBUyxhQUFhLENBQUMsSUFBVSxFQUFFLElBQVk7SUFDN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxJQUFJLGdDQUFtQixDQUFDLGtCQUFrQixJQUFJLEdBQUcsQ0FBQyxDQUFDO0tBQzFEO0lBQ0QsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBRWhGLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUMxQixJQUFVLEVBQ1YsT0FBZ0QsRUFDaEQsU0FBK0M7SUFFL0MsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQy9DLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDakQsTUFBTSxRQUFRLEdBQUcsMEJBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM1QyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLElB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S0FBSyxDQUFDLENBQUM7Z0JBQ2pELENBQUMsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzdCO1FBR0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxPQUF3QjtJQUNqRCxNQUFNLGdCQUFnQixHQUFxQjtRQUN6QyxJQUFJLEVBQUUsV0FBVztRQUNqQixNQUFNLEVBQUUsT0FBTyxDQUFDLGtCQUFrQjtRQUNsQyxPQUFPLEVBQUUsT0FBTyxDQUFDLGFBQWE7S0FDL0IsQ0FBQztJQUVGLE9BQU8sc0JBQVMsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRUQsbUJBQXlCLE9BQXdCO0lBQy9DLE9BQU8sa0JBQUssQ0FBQztRQUNYLGVBQWUsQ0FBQyxPQUFPLENBQUM7UUFDeEIsa0JBQWtCLENBQUMsT0FBTyxDQUFDO1FBQzNCLDRCQUE0QixDQUFDLE9BQU8sQ0FBQztRQUNyQyxlQUFlLENBQUMsT0FBTyxDQUFDO1FBQ3hCLGVBQWUsQ0FBQyxPQUFPLENBQUM7UUFDeEIsaUJBQWlCLENBQUMsT0FBTyxDQUFDO0tBQzNCLENBQUMsQ0FBQztBQUNMLENBQUM7QUFURCw0QkFTQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7IGRpcm5hbWUsIGV4cGVyaW1lbnRhbCwgam9pbiwgbm9ybWFsaXplIH0gZnJvbSAnQGFuZ3VsYXItZGV2a2l0L2NvcmUnO1xuaW1wb3J0IHtcbiAgUnVsZSxcbiAgU2NoZW1hdGljQ29udGV4dCxcbiAgU2NoZW1hdGljc0V4Y2VwdGlvbixcbiAgVHJlZSxcbiAgY2hhaW4sXG4gIHNjaGVtYXRpYyxcbn0gZnJvbSAnQGFuZ3VsYXItZGV2a2l0L3NjaGVtYXRpY3MnO1xuaW1wb3J0ICogYXMgdHMgZnJvbSAndHlwZXNjcmlwdCc7XG5pbXBvcnQgeyBTY2hlbWEgYXMgQ29tcG9uZW50T3B0aW9ucyB9IGZyb20gJy4uL2NvbXBvbmVudC9zY2hlbWEnO1xuaW1wb3J0IHtcbiAgYWRkSW1wb3J0VG9Nb2R1bGUsXG4gIGFkZFN5bWJvbFRvTmdNb2R1bGVNZXRhZGF0YSxcbiAgZmluZE5vZGUsXG4gIGdldERlY29yYXRvck1ldGFkYXRhLFxuICBnZXRTb3VyY2VOb2RlcyxcbiAgaW5zZXJ0SW1wb3J0LFxuICBpc0ltcG9ydGVkLFxufSBmcm9tICcuLi91dGlsaXR5L2FzdC11dGlscyc7XG5pbXBvcnQgeyBDaGFuZ2UsIEluc2VydENoYW5nZSB9IGZyb20gJy4uL3V0aWxpdHkvY2hhbmdlJztcbmltcG9ydCB7IGdldFdvcmtzcGFjZSwgdXBkYXRlV29ya3NwYWNlIH0gZnJvbSAnLi4vdXRpbGl0eS9jb25maWcnO1xuaW1wb3J0IHsgZ2V0QXBwTW9kdWxlUGF0aCB9IGZyb20gJy4uL3V0aWxpdHkvbmctYXN0LXV0aWxzJztcbmltcG9ydCB7IGdldFByb2plY3QgfSBmcm9tICcuLi91dGlsaXR5L3Byb2plY3QnO1xuaW1wb3J0IHsgZ2V0UHJvamVjdFRhcmdldHMsIHRhcmdldEJ1aWxkTm90Rm91bmRFcnJvciB9IGZyb20gJy4uL3V0aWxpdHkvcHJvamVjdC10YXJnZXRzJztcbmltcG9ydCB7IEJ1aWxkZXJzLCBXb3Jrc3BhY2VQcm9qZWN0IH0gZnJvbSAnLi4vdXRpbGl0eS93b3Jrc3BhY2UtbW9kZWxzJztcbmltcG9ydCB7IFNjaGVtYSBhcyBBcHBTaGVsbE9wdGlvbnMgfSBmcm9tICcuL3NjaGVtYSc7XG5cbmZ1bmN0aW9uIGdldFNvdXJjZUZpbGUoaG9zdDogVHJlZSwgcGF0aDogc3RyaW5nKTogdHMuU291cmNlRmlsZSB7XG4gIGNvbnN0IGJ1ZmZlciA9IGhvc3QucmVhZChwYXRoKTtcbiAgaWYgKCFidWZmZXIpIHtcbiAgICB0aHJvdyBuZXcgU2NoZW1hdGljc0V4Y2VwdGlvbihgQ291bGQgbm90IGZpbmQgJHtwYXRofS5gKTtcbiAgfVxuICBjb25zdCBjb250ZW50ID0gYnVmZmVyLnRvU3RyaW5nKCk7XG4gIGNvbnN0IHNvdXJjZSA9IHRzLmNyZWF0ZVNvdXJjZUZpbGUocGF0aCwgY29udGVudCwgdHMuU2NyaXB0VGFyZ2V0LkxhdGVzdCwgdHJ1ZSk7XG5cbiAgcmV0dXJuIHNvdXJjZTtcbn1cblxuZnVuY3Rpb24gZ2V0U2VydmVyTW9kdWxlUGF0aChcbiAgaG9zdDogVHJlZSxcbiAgcHJvamVjdDogZXhwZXJpbWVudGFsLndvcmtzcGFjZS5Xb3Jrc3BhY2VQcm9qZWN0LFxuICBhcmNoaXRlY3Q6IGV4cGVyaW1lbnRhbC53b3Jrc3BhY2UuV29ya3NwYWNlVG9vbCxcbik6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBtYWluUGF0aCA9IGFyY2hpdGVjdC5zZXJ2ZXIub3B0aW9ucy5tYWluO1xuICBjb25zdCBtYWluU291cmNlID0gZ2V0U291cmNlRmlsZShob3N0LCBtYWluUGF0aCk7XG4gIGNvbnN0IGFsbE5vZGVzID0gZ2V0U291cmNlTm9kZXMobWFpblNvdXJjZSk7XG4gIGNvbnN0IGV4cE5vZGUgPSBhbGxOb2Rlcy5maWx0ZXIobm9kZSA9PiBub2RlLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuRXhwb3J0RGVjbGFyYXRpb24pWzBdO1xuICBpZiAoIWV4cE5vZGUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCByZWxhdGl2ZVBhdGggPSAoZXhwTm9kZSBhcyB0cy5FeHBvcnREZWNsYXJhdGlvbikubW9kdWxlU3BlY2lmaWVyIGFzIHRzLlN0cmluZ0xpdGVyYWw7XG4gIGNvbnN0IG1vZHVsZVBhdGggPSBub3JtYWxpemUoYC8ke3Byb2plY3Qucm9vdH0vc3JjLyR7cmVsYXRpdmVQYXRoLnRleHR9LnRzYCk7XG5cbiAgcmV0dXJuIG1vZHVsZVBhdGg7XG59XG5cbmludGVyZmFjZSBUZW1wbGF0ZUluZm8ge1xuICB0ZW1wbGF0ZVByb3A/OiB0cy5Qcm9wZXJ0eUFzc2lnbm1lbnQ7XG4gIHRlbXBsYXRlVXJsUHJvcD86IHRzLlByb3BlcnR5QXNzaWdubWVudDtcbn1cblxuZnVuY3Rpb24gZ2V0Q29tcG9uZW50VGVtcGxhdGVJbmZvKGhvc3Q6IFRyZWUsIGNvbXBvbmVudFBhdGg6IHN0cmluZyk6IFRlbXBsYXRlSW5mbyB7XG4gIGNvbnN0IGNvbXBTb3VyY2UgPSBnZXRTb3VyY2VGaWxlKGhvc3QsIGNvbXBvbmVudFBhdGgpO1xuICBjb25zdCBjb21wTWV0YWRhdGEgPSBnZXREZWNvcmF0b3JNZXRhZGF0YShjb21wU291cmNlLCAnQ29tcG9uZW50JywgJ0Bhbmd1bGFyL2NvcmUnKVswXTtcblxuICByZXR1cm4ge1xuICAgIHRlbXBsYXRlUHJvcDogZ2V0TWV0YWRhdGFQcm9wZXJ0eShjb21wTWV0YWRhdGEsICd0ZW1wbGF0ZScpLFxuICAgIHRlbXBsYXRlVXJsUHJvcDogZ2V0TWV0YWRhdGFQcm9wZXJ0eShjb21wTWV0YWRhdGEsICd0ZW1wbGF0ZVVybCcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRDb21wb25lbnRUZW1wbGF0ZShob3N0OiBUcmVlLCBjb21wUGF0aDogc3RyaW5nLCB0bXBsSW5mbzogVGVtcGxhdGVJbmZvKTogc3RyaW5nIHtcbiAgbGV0IHRlbXBsYXRlID0gJyc7XG5cbiAgaWYgKHRtcGxJbmZvLnRlbXBsYXRlUHJvcCkge1xuICAgIHRlbXBsYXRlID0gdG1wbEluZm8udGVtcGxhdGVQcm9wLmdldEZ1bGxUZXh0KCk7XG4gIH0gZWxzZSBpZiAodG1wbEluZm8udGVtcGxhdGVVcmxQcm9wKSB7XG4gICAgY29uc3QgdGVtcGxhdGVVcmwgPSAodG1wbEluZm8udGVtcGxhdGVVcmxQcm9wLmluaXRpYWxpemVyIGFzIHRzLlN0cmluZ0xpdGVyYWwpLnRleHQ7XG4gICAgY29uc3QgZGlyID0gZGlybmFtZShub3JtYWxpemUoY29tcFBhdGgpKTtcbiAgICBjb25zdCB0ZW1wbGF0ZVBhdGggPSBqb2luKGRpciwgdGVtcGxhdGVVcmwpO1xuICAgIGNvbnN0IGJ1ZmZlciA9IGhvc3QucmVhZCh0ZW1wbGF0ZVBhdGgpO1xuICAgIGlmIChidWZmZXIpIHtcbiAgICAgIHRlbXBsYXRlID0gYnVmZmVyLnRvU3RyaW5nKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRlbXBsYXRlO1xufVxuXG5mdW5jdGlvbiBnZXRCb290c3RyYXBDb21wb25lbnRQYXRoKFxuICBob3N0OiBUcmVlLFxuICBwcm9qZWN0OiBXb3Jrc3BhY2VQcm9qZWN0LFxuKTogc3RyaW5nIHtcbiAgY29uc3QgcHJvamVjdFRhcmdldHMgPSBnZXRQcm9qZWN0VGFyZ2V0cyhwcm9qZWN0KTtcbiAgaWYgKCFwcm9qZWN0VGFyZ2V0cy5idWlsZCkge1xuICAgIHRocm93IHRhcmdldEJ1aWxkTm90Rm91bmRFcnJvcigpO1xuICB9XG5cbiAgY29uc3QgbWFpblBhdGggPSBwcm9qZWN0VGFyZ2V0cy5idWlsZC5vcHRpb25zLm1haW47XG4gIGNvbnN0IG1vZHVsZVBhdGggPSBnZXRBcHBNb2R1bGVQYXRoKGhvc3QsIG1haW5QYXRoKTtcbiAgY29uc3QgbW9kdWxlU291cmNlID0gZ2V0U291cmNlRmlsZShob3N0LCBtb2R1bGVQYXRoKTtcblxuICBjb25zdCBtZXRhZGF0YU5vZGUgPSBnZXREZWNvcmF0b3JNZXRhZGF0YShtb2R1bGVTb3VyY2UsICdOZ01vZHVsZScsICdAYW5ndWxhci9jb3JlJylbMF07XG4gIGNvbnN0IGJvb3RzdHJhcFByb3BlcnR5ID0gZ2V0TWV0YWRhdGFQcm9wZXJ0eShtZXRhZGF0YU5vZGUsICdib290c3RyYXAnKTtcblxuICBjb25zdCBhcnJMaXRlcmFsID0gKGJvb3RzdHJhcFByb3BlcnR5IGFzIHRzLlByb3BlcnR5QXNzaWdubWVudClcbiAgICAuaW5pdGlhbGl6ZXIgYXMgdHMuQXJyYXlMaXRlcmFsRXhwcmVzc2lvbjtcblxuICBjb25zdCBjb21wb25lbnRTeW1ib2wgPSBhcnJMaXRlcmFsLmVsZW1lbnRzWzBdLmdldFRleHQoKTtcblxuICBjb25zdCByZWxhdGl2ZVBhdGggPSBnZXRTb3VyY2VOb2Rlcyhtb2R1bGVTb3VyY2UpXG4gICAgLmZpbHRlcihub2RlID0+IG5vZGUua2luZCA9PT0gdHMuU3ludGF4S2luZC5JbXBvcnREZWNsYXJhdGlvbilcbiAgICAuZmlsdGVyKGltcCA9PiB7XG4gICAgICByZXR1cm4gZmluZE5vZGUoaW1wLCB0cy5TeW50YXhLaW5kLklkZW50aWZpZXIsIGNvbXBvbmVudFN5bWJvbCk7XG4gICAgfSlcbiAgICAubWFwKChpbXA6IHRzLkltcG9ydERlY2xhcmF0aW9uKSA9PiB7XG4gICAgICBjb25zdCBwYXRoU3RyaW5nTGl0ZXJhbCA9IGltcC5tb2R1bGVTcGVjaWZpZXIgYXMgdHMuU3RyaW5nTGl0ZXJhbDtcblxuICAgICAgcmV0dXJuIHBhdGhTdHJpbmdMaXRlcmFsLnRleHQ7XG4gICAgfSlbMF07XG5cbiAgcmV0dXJuIGpvaW4oZGlybmFtZShub3JtYWxpemUobW9kdWxlUGF0aCkpLCByZWxhdGl2ZVBhdGggKyAnLnRzJyk7XG59XG4vLyBlbmQgaGVscGVyIGZ1bmN0aW9ucy5cblxuZnVuY3Rpb24gdmFsaWRhdGVQcm9qZWN0KG9wdGlvbnM6IEFwcFNoZWxsT3B0aW9ucyk6IFJ1bGUge1xuICByZXR1cm4gKGhvc3Q6IFRyZWUsIGNvbnRleHQ6IFNjaGVtYXRpY0NvbnRleHQpID0+IHtcbiAgICBjb25zdCByb3V0ZXJPdXRsZXRDaGVja1JlZ2V4ID0gLzxyb3V0ZXJcXC1vdXRsZXQuKj8+KFtcXHNcXFNdKj8pPFxcL3JvdXRlclxcLW91dGxldD4vO1xuXG4gICAgY29uc3QgY2xpZW50UHJvamVjdCA9IGdldFByb2plY3QoaG9zdCwgb3B0aW9ucy5jbGllbnRQcm9qZWN0KTtcbiAgICBpZiAoY2xpZW50UHJvamVjdC5wcm9qZWN0VHlwZSAhPT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgdGhyb3cgbmV3IFNjaGVtYXRpY3NFeGNlcHRpb24oYEFwcCBzaGVsbCByZXF1aXJlcyBhIHByb2plY3QgdHlwZSBvZiBcImFwcGxpY2F0aW9uXCIuYCk7XG4gICAgfVxuICAgIGNvbnN0IGNvbXBvbmVudFBhdGggPSBnZXRCb290c3RyYXBDb21wb25lbnRQYXRoKGhvc3QsIGNsaWVudFByb2plY3QpO1xuICAgIGNvbnN0IHRtcGwgPSBnZXRDb21wb25lbnRUZW1wbGF0ZUluZm8oaG9zdCwgY29tcG9uZW50UGF0aCk7XG4gICAgY29uc3QgdGVtcGxhdGUgPSBnZXRDb21wb25lbnRUZW1wbGF0ZShob3N0LCBjb21wb25lbnRQYXRoLCB0bXBsKTtcbiAgICBpZiAoIXJvdXRlck91dGxldENoZWNrUmVnZXgudGVzdCh0ZW1wbGF0ZSkpIHtcbiAgICAgIGNvbnN0IGVycm9yTXNnID1cbiAgICAgICAgYFByZXJlcXVpc2l0ZSBmb3IgYXBwIHNoZWxsIGlzIHRvIGRlZmluZSBhIHJvdXRlci1vdXRsZXQgaW4geW91ciByb290IGNvbXBvbmVudC5gO1xuICAgICAgY29udGV4dC5sb2dnZXIuZXJyb3IoZXJyb3JNc2cpO1xuICAgICAgdGhyb3cgbmV3IFNjaGVtYXRpY3NFeGNlcHRpb24oZXJyb3JNc2cpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gYWRkVW5pdmVyc2FsVGFyZ2V0KG9wdGlvbnM6IEFwcFNoZWxsT3B0aW9ucyk6IFJ1bGUge1xuICByZXR1cm4gKGhvc3Q6IFRyZWUsIGNvbnRleHQ6IFNjaGVtYXRpY0NvbnRleHQpID0+IHtcbiAgICBjb25zdCBhcmNoaXRlY3QgPSBnZXRQcm9qZWN0VGFyZ2V0cyhob3N0LCBvcHRpb25zLmNsaWVudFByb2plY3QpO1xuICAgIGlmIChhcmNoaXRlY3Quc2VydmVyKSB7XG4gICAgICByZXR1cm4gaG9zdDtcbiAgICB9XG5cbiAgICAvLyBDb3B5IG9wdGlvbnMuXG4gICAgY29uc3QgdW5pdmVyc2FsT3B0aW9ucyA9IHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfTtcblxuICAgIC8vIERlbGV0ZSBub24tdW5pdmVyc2FsIG9wdGlvbnMuXG4gICAgZGVsZXRlIHVuaXZlcnNhbE9wdGlvbnMudW5pdmVyc2FsUHJvamVjdDtcbiAgICBkZWxldGUgdW5pdmVyc2FsT3B0aW9ucy5yb3V0ZTtcbiAgICBkZWxldGUgdW5pdmVyc2FsT3B0aW9ucy5uYW1lO1xuICAgIGRlbGV0ZSB1bml2ZXJzYWxPcHRpb25zLm91dERpcjtcbiAgICBkZWxldGUgdW5pdmVyc2FsT3B0aW9ucy5yb290O1xuICAgIGRlbGV0ZSB1bml2ZXJzYWxPcHRpb25zLmluZGV4O1xuICAgIGRlbGV0ZSB1bml2ZXJzYWxPcHRpb25zLnNvdXJjZURpcjtcblxuICAgIHJldHVybiBzY2hlbWF0aWMoJ3VuaXZlcnNhbCcsIHVuaXZlcnNhbE9wdGlvbnMpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhZGRBcHBTaGVsbENvbmZpZ1RvV29ya3NwYWNlKG9wdGlvbnM6IEFwcFNoZWxsT3B0aW9ucyk6IFJ1bGUge1xuICByZXR1cm4gKGhvc3Q6IFRyZWUpID0+IHtcbiAgICBpZiAoIW9wdGlvbnMucm91dGUpIHtcbiAgICAgIHRocm93IG5ldyBTY2hlbWF0aWNzRXhjZXB0aW9uKGBSb3V0ZSBpcyBub3QgZGVmaW5lZGApO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtzcGFjZSA9IGdldFdvcmtzcGFjZShob3N0KTtcbiAgICBjb25zdCBwcm9qZWN0VGFyZ2V0cyA9IGdldFByb2plY3RUYXJnZXRzKHdvcmtzcGFjZSwgb3B0aW9ucy5jbGllbnRQcm9qZWN0KTtcbiAgICBwcm9qZWN0VGFyZ2V0c1snYXBwLXNoZWxsJ10gPSB7XG4gICAgICBidWlsZGVyOiBCdWlsZGVycy5BcHBTaGVsbCxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgYnJvd3NlclRhcmdldDogYCR7b3B0aW9ucy5jbGllbnRQcm9qZWN0fTpidWlsZGAsXG4gICAgICAgIHNlcnZlclRhcmdldDogYCR7b3B0aW9ucy5jbGllbnRQcm9qZWN0fTpzZXJ2ZXJgLFxuICAgICAgICByb3V0ZTogb3B0aW9ucy5yb3V0ZSxcbiAgICAgIH0sXG4gICAgICBjb25maWd1cmF0aW9uczoge1xuICAgICAgICBwcm9kdWN0aW9uOiB7XG4gICAgICAgICAgYnJvd3NlclRhcmdldDogYCR7b3B0aW9ucy5jbGllbnRQcm9qZWN0fTpidWlsZDpwcm9kdWN0aW9uYCxcbiAgICAgICAgICBzZXJ2ZXJUYXJnZXQ6IGAke29wdGlvbnMuY2xpZW50UHJvamVjdH06c2VydmVyOnByb2R1Y3Rpb25gLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHVwZGF0ZVdvcmtzcGFjZSh3b3Jrc3BhY2UpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhZGRSb3V0ZXJNb2R1bGUob3B0aW9uczogQXBwU2hlbGxPcHRpb25zKTogUnVsZSB7XG4gIHJldHVybiAoaG9zdDogVHJlZSkgPT4ge1xuICAgIGNvbnN0IHByb2plY3RUYXJnZXRzID0gZ2V0UHJvamVjdFRhcmdldHMoaG9zdCwgb3B0aW9ucy5jbGllbnRQcm9qZWN0KTtcbiAgICBpZiAoIXByb2plY3RUYXJnZXRzLmJ1aWxkKSB7XG4gICAgICB0aHJvdyB0YXJnZXRCdWlsZE5vdEZvdW5kRXJyb3IoKTtcbiAgICB9XG4gICAgY29uc3QgbWFpblBhdGggPSBwcm9qZWN0VGFyZ2V0cy5idWlsZC5vcHRpb25zLm1haW47XG4gICAgY29uc3QgbW9kdWxlUGF0aCA9IGdldEFwcE1vZHVsZVBhdGgoaG9zdCwgbWFpblBhdGgpO1xuICAgIGNvbnN0IG1vZHVsZVNvdXJjZSA9IGdldFNvdXJjZUZpbGUoaG9zdCwgbW9kdWxlUGF0aCk7XG4gICAgY29uc3QgY2hhbmdlcyA9IGFkZEltcG9ydFRvTW9kdWxlKG1vZHVsZVNvdXJjZSwgbW9kdWxlUGF0aCwgJ1JvdXRlck1vZHVsZScsICdAYW5ndWxhci9yb3V0ZXInKTtcbiAgICBjb25zdCByZWNvcmRlciA9IGhvc3QuYmVnaW5VcGRhdGUobW9kdWxlUGF0aCk7XG4gICAgY2hhbmdlcy5mb3JFYWNoKChjaGFuZ2U6IENoYW5nZSkgPT4ge1xuICAgICAgaWYgKGNoYW5nZSBpbnN0YW5jZW9mIEluc2VydENoYW5nZSkge1xuICAgICAgICByZWNvcmRlci5pbnNlcnRMZWZ0KGNoYW5nZS5wb3MsIGNoYW5nZS50b0FkZCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaG9zdC5jb21taXRVcGRhdGUocmVjb3JkZXIpO1xuXG4gICAgcmV0dXJuIGhvc3Q7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldE1ldGFkYXRhUHJvcGVydHkobWV0YWRhdGE6IHRzLk5vZGUsIHByb3BlcnR5TmFtZTogc3RyaW5nKTogdHMuUHJvcGVydHlBc3NpZ25tZW50IHtcbiAgY29uc3QgcHJvcGVydGllcyA9IChtZXRhZGF0YSBhcyB0cy5PYmplY3RMaXRlcmFsRXhwcmVzc2lvbikucHJvcGVydGllcztcbiAgY29uc3QgcHJvcGVydHkgPSBwcm9wZXJ0aWVzXG4gICAgLmZpbHRlcihwcm9wID0+IHByb3Aua2luZCA9PT0gdHMuU3ludGF4S2luZC5Qcm9wZXJ0eUFzc2lnbm1lbnQpXG4gICAgLmZpbHRlcigocHJvcDogdHMuUHJvcGVydHlBc3NpZ25tZW50KSA9PiB7XG4gICAgICBjb25zdCBuYW1lID0gcHJvcC5uYW1lO1xuICAgICAgc3dpdGNoIChuYW1lLmtpbmQpIHtcbiAgICAgICAgY2FzZSB0cy5TeW50YXhLaW5kLklkZW50aWZpZXI6XG4gICAgICAgICAgcmV0dXJuIChuYW1lIGFzIHRzLklkZW50aWZpZXIpLmdldFRleHQoKSA9PT0gcHJvcGVydHlOYW1lO1xuICAgICAgICBjYXNlIHRzLlN5bnRheEtpbmQuU3RyaW5nTGl0ZXJhbDpcbiAgICAgICAgICByZXR1cm4gKG5hbWUgYXMgdHMuU3RyaW5nTGl0ZXJhbCkudGV4dCA9PT0gcHJvcGVydHlOYW1lO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSlbMF07XG5cbiAgcmV0dXJuIHByb3BlcnR5IGFzIHRzLlByb3BlcnR5QXNzaWdubWVudDtcbn1cblxuZnVuY3Rpb24gYWRkU2VydmVyUm91dGVzKG9wdGlvbnM6IEFwcFNoZWxsT3B0aW9ucyk6IFJ1bGUge1xuICByZXR1cm4gKGhvc3Q6IFRyZWUpID0+IHtcbiAgICBjb25zdCBjbGllbnRQcm9qZWN0ID0gZ2V0UHJvamVjdChob3N0LCBvcHRpb25zLmNsaWVudFByb2plY3QpO1xuICAgIGNvbnN0IGFyY2hpdGVjdCA9IGdldFByb2plY3RUYXJnZXRzKGNsaWVudFByb2plY3QpO1xuICAgIC8vIGNvbnN0IG1haW5QYXRoID0gdW5pdmVyc2FsQXJjaGl0ZWN0LmJ1aWxkLm9wdGlvbnMubWFpbjtcbiAgICBjb25zdCBtb2R1bGVQYXRoID0gZ2V0U2VydmVyTW9kdWxlUGF0aChob3N0LCBjbGllbnRQcm9qZWN0LCBhcmNoaXRlY3QpO1xuICAgIGlmIChtb2R1bGVQYXRoID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgU2NoZW1hdGljc0V4Y2VwdGlvbignVW5pdmVyc2FsL3NlcnZlciBtb2R1bGUgbm90IGZvdW5kLicpO1xuICAgIH1cblxuICAgIGxldCBtb2R1bGVTb3VyY2UgPSBnZXRTb3VyY2VGaWxlKGhvc3QsIG1vZHVsZVBhdGgpO1xuICAgIGlmICghaXNJbXBvcnRlZChtb2R1bGVTb3VyY2UsICdSb3V0ZXMnLCAnQGFuZ3VsYXIvcm91dGVyJykpIHtcbiAgICAgIGNvbnN0IHJlY29yZGVyID0gaG9zdC5iZWdpblVwZGF0ZShtb2R1bGVQYXRoKTtcbiAgICAgIGNvbnN0IHJvdXRlc0NoYW5nZSA9IGluc2VydEltcG9ydChtb2R1bGVTb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kdWxlUGF0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUm91dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQGFuZ3VsYXIvcm91dGVyJykgYXMgSW5zZXJ0Q2hhbmdlO1xuICAgICAgaWYgKHJvdXRlc0NoYW5nZS50b0FkZCkge1xuICAgICAgICByZWNvcmRlci5pbnNlcnRMZWZ0KHJvdXRlc0NoYW5nZS5wb3MsIHJvdXRlc0NoYW5nZS50b0FkZCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGltcG9ydHMgPSBnZXRTb3VyY2VOb2Rlcyhtb2R1bGVTb3VyY2UpXG4gICAgICAgIC5maWx0ZXIobm9kZSA9PiBub2RlLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuSW1wb3J0RGVjbGFyYXRpb24pXG4gICAgICAgIC5zb3J0KChhLCBiKSA9PiBhLmdldFN0YXJ0KCkgLSBiLmdldFN0YXJ0KCkpO1xuICAgICAgY29uc3QgaW5zZXJ0UG9zaXRpb24gPSBpbXBvcnRzW2ltcG9ydHMubGVuZ3RoIC0gMV0uZ2V0RW5kKCk7XG4gICAgICBjb25zdCByb3V0ZVRleHQgPVxuICAgICAgICBgXFxuXFxuY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbIHsgcGF0aDogJyR7b3B0aW9ucy5yb3V0ZX0nLCBjb21wb25lbnQ6IEFwcFNoZWxsQ29tcG9uZW50IH1dO2A7XG4gICAgICByZWNvcmRlci5pbnNlcnRSaWdodChpbnNlcnRQb3NpdGlvbiwgcm91dGVUZXh0KTtcbiAgICAgIGhvc3QuY29tbWl0VXBkYXRlKHJlY29yZGVyKTtcbiAgICB9XG5cbiAgICBtb2R1bGVTb3VyY2UgPSBnZXRTb3VyY2VGaWxlKGhvc3QsIG1vZHVsZVBhdGgpO1xuICAgIGlmICghaXNJbXBvcnRlZChtb2R1bGVTb3VyY2UsICdSb3V0ZXJNb2R1bGUnLCAnQGFuZ3VsYXIvcm91dGVyJykpIHtcbiAgICAgIGNvbnN0IHJlY29yZGVyID0gaG9zdC5iZWdpblVwZGF0ZShtb2R1bGVQYXRoKTtcbiAgICAgIGNvbnN0IHJvdXRlck1vZHVsZUNoYW5nZSA9IGluc2VydEltcG9ydChtb2R1bGVTb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kdWxlUGF0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUm91dGVyTW9kdWxlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQGFuZ3VsYXIvcm91dGVyJykgYXMgSW5zZXJ0Q2hhbmdlO1xuXG4gICAgICBpZiAocm91dGVyTW9kdWxlQ2hhbmdlLnRvQWRkKSB7XG4gICAgICAgIHJlY29yZGVyLmluc2VydExlZnQocm91dGVyTW9kdWxlQ2hhbmdlLnBvcywgcm91dGVyTW9kdWxlQ2hhbmdlLnRvQWRkKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWV0YWRhdGFDaGFuZ2UgPSBhZGRTeW1ib2xUb05nTW9kdWxlTWV0YWRhdGEoXG4gICAgICAgICAgbW9kdWxlU291cmNlLCBtb2R1bGVQYXRoLCAnaW1wb3J0cycsICdSb3V0ZXJNb2R1bGUuZm9yUm9vdChyb3V0ZXMpJyk7XG4gICAgICBpZiAobWV0YWRhdGFDaGFuZ2UpIHtcbiAgICAgICAgbWV0YWRhdGFDaGFuZ2UuZm9yRWFjaCgoY2hhbmdlOiBJbnNlcnRDaGFuZ2UpID0+IHtcbiAgICAgICAgICByZWNvcmRlci5pbnNlcnRSaWdodChjaGFuZ2UucG9zLCBjaGFuZ2UudG9BZGQpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGhvc3QuY29tbWl0VXBkYXRlKHJlY29yZGVyKTtcbiAgICB9XG5cblxuICAgIHJldHVybiBob3N0O1xuICB9O1xufVxuXG5mdW5jdGlvbiBhZGRTaGVsbENvbXBvbmVudChvcHRpb25zOiBBcHBTaGVsbE9wdGlvbnMpOiBSdWxlIHtcbiAgY29uc3QgY29tcG9uZW50T3B0aW9uczogQ29tcG9uZW50T3B0aW9ucyA9IHtcbiAgICBuYW1lOiAnYXBwLXNoZWxsJyxcbiAgICBtb2R1bGU6IG9wdGlvbnMucm9vdE1vZHVsZUZpbGVOYW1lLFxuICAgIHByb2plY3Q6IG9wdGlvbnMuY2xpZW50UHJvamVjdCxcbiAgfTtcblxuICByZXR1cm4gc2NoZW1hdGljKCdjb21wb25lbnQnLCBjb21wb25lbnRPcHRpb25zKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gKG9wdGlvbnM6IEFwcFNoZWxsT3B0aW9ucyk6IFJ1bGUge1xuICByZXR1cm4gY2hhaW4oW1xuICAgIHZhbGlkYXRlUHJvamVjdChvcHRpb25zKSxcbiAgICBhZGRVbml2ZXJzYWxUYXJnZXQob3B0aW9ucyksXG4gICAgYWRkQXBwU2hlbGxDb25maWdUb1dvcmtzcGFjZShvcHRpb25zKSxcbiAgICBhZGRSb3V0ZXJNb2R1bGUob3B0aW9ucyksXG4gICAgYWRkU2VydmVyUm91dGVzKG9wdGlvbnMpLFxuICAgIGFkZFNoZWxsQ29tcG9uZW50KG9wdGlvbnMpLFxuICBdKTtcbn1cbiJdfQ==