UNPKG

@nguniversal/express-engine

Version:

Express Engine for running Server Angular Apps

267 lines 37.9 kB
"use strict"; /** * @license * Copyright Google LLC 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 */ Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@angular-devkit/core"); const schematics_1 = require("@angular-devkit/schematics"); const utility_1 = require("@schematics/angular/utility"); const json_file_1 = require("@schematics/angular/utility/json-file"); const ng_ast_utils_1 = require("@schematics/angular/utility/ng-ast-utils"); const project_targets_1 = require("@schematics/angular/utility/project-targets"); const ts = require("typescript"); const utils_1 = require("../utils"); const SERVE_SSR_TARGET_NAME = 'serve-ssr'; const PRERENDER_TARGET_NAME = 'prerender'; function addScriptsRule(options) { return async (host) => { const pkgPath = '/package.json'; const buffer = host.read(pkgPath); if (buffer === null) { throw new schematics_1.SchematicsException('Could not find package.json'); } const serverDist = await (0, utils_1.getOutputPath)(host, options.project, 'server'); const pkg = JSON.parse(buffer.toString()); pkg.scripts = { ...pkg.scripts, 'dev:ssr': `ng run ${options.project}:${SERVE_SSR_TARGET_NAME}`, 'serve:ssr': `node ${serverDist}/main.js`, 'build:ssr': `ng build && ng run ${options.project}:server`, 'prerender': `ng run ${options.project}:${PRERENDER_TARGET_NAME}`, }; host.overwrite(pkgPath, JSON.stringify(pkg, null, 2)); }; } function updateWorkspaceConfigRule(options) { return () => { return (0, utility_1.updateWorkspace)((workspace) => { const projectName = options.project; const project = workspace.projects.get(projectName); if (!project) { return; } const serverTarget = project.targets.get('server'); serverTarget.options.main = (0, core_1.join)((0, core_1.normalize)(project.root), (0, utils_1.stripTsExtension)(options.serverFileName) + '.ts'); const serveSSRTarget = project.targets.get(SERVE_SSR_TARGET_NAME); if (serveSSRTarget) { return; } project.targets.add({ name: SERVE_SSR_TARGET_NAME, builder: '@nguniversal/builders:ssr-dev-server', defaultConfiguration: 'development', options: {}, configurations: { development: { browserTarget: `${projectName}:build:development`, serverTarget: `${projectName}:server:development`, }, production: { browserTarget: `${projectName}:build:production`, serverTarget: `${projectName}:server:production`, }, }, }); const prerenderTarget = project.targets.get(PRERENDER_TARGET_NAME); if (prerenderTarget) { return; } project.targets.add({ name: PRERENDER_TARGET_NAME, builder: '@nguniversal/builders:prerender', defaultConfiguration: 'production', options: { routes: ['/'], }, configurations: { production: { browserTarget: `${projectName}:build:production`, serverTarget: `${projectName}:server:production`, }, development: { browserTarget: `${projectName}:build:development`, serverTarget: `${projectName}:server:development`, }, }, }); }); }; } function updateServerTsConfigRule(options) { return async (host) => { const project = await (0, utils_1.getProject)(host, options.project); const serverTarget = project.targets.get('server'); if (!serverTarget || !serverTarget.options) { return; } const tsConfigPath = serverTarget.options.tsConfig; if (!tsConfigPath || typeof tsConfigPath !== 'string') { // No tsconfig path return; } const tsConfig = new json_file_1.JSONFile(host, tsConfigPath); const filesAstNode = tsConfig.get(['files']); const serverFilePath = (0, utils_1.stripTsExtension)(options.serverFileName) + '.ts'; if (Array.isArray(filesAstNode) && !filesAstNode.some(({ text }) => text === serverFilePath)) { tsConfig.modify(['files'], [...filesAstNode, serverFilePath]); } }; } function routingInitialNavigationRule(options) { return async (host) => { const project = await (0, utils_1.getProject)(host, options.project); const serverTarget = project.targets.get('server'); if (!serverTarget || !serverTarget.options) { return; } const tsConfigPath = serverTarget.options.tsConfig; if (!tsConfigPath || typeof tsConfigPath !== 'string' || !host.exists(tsConfigPath)) { // No tsconfig path return; } const parseConfigHost = { useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames, readDirectory: ts.sys.readDirectory, fileExists: function (fileName) { return host.exists(fileName); }, readFile: function (fileName) { return host.read(fileName).toString(); }, }; const { config } = ts.readConfigFile(tsConfigPath, parseConfigHost.readFile); const parsed = ts.parseJsonConfigFileContent(config, parseConfigHost, (0, core_1.dirname)((0, core_1.normalize)(tsConfigPath))); const tsHost = ts.createCompilerHost(parsed.options, true); // Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset, // which breaks the CLI UpdateRecorder. // See: https://github.com/angular/angular/pull/30719 tsHost.readFile = function (fileName) { return host .read(fileName) .toString() .replace(/^\uFEFF/, ''); }; tsHost.directoryExists = function (directoryName) { // When the path is file getDir will throw. try { const dir = host.getDir(directoryName); return !!(dir.subdirs.length || dir.subfiles.length); } catch { return false; } }; tsHost.fileExists = function (fileName) { return host.exists(fileName); }; tsHost.realpath = function (path) { return path; }; tsHost.getCurrentDirectory = function () { return host.root.path; }; const program = ts.createProgram(parsed.fileNames, parsed.options, tsHost); const typeChecker = program.getTypeChecker(); const sourceFiles = program .getSourceFiles() .filter((f) => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); const printer = ts.createPrinter(); const routerModule = 'RouterModule'; const routerSource = '@angular/router'; sourceFiles.forEach((sourceFile) => { const routerImport = (0, utils_1.findImport)(sourceFile, routerSource, routerModule); if (!routerImport) { return; } let routerModuleNode; ts.forEachChild(sourceFile, function visitNode(node) { if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression) && node.expression.name.text === 'forRoot') { const imp = (0, utils_1.getImportOfIdentifier)(typeChecker, node.expression.expression); if (imp && imp.name === routerModule && imp.importModule === routerSource) { routerModuleNode = node; } } ts.forEachChild(node, visitNode); }); if (routerModuleNode) { const print = printer.printNode(ts.EmitHint.Unspecified, (0, utils_1.addInitialNavigation)(routerModuleNode), sourceFile); const recorder = host.beginUpdate(sourceFile.fileName); recorder.remove(routerModuleNode.getStart(), routerModuleNode.getWidth()); recorder.insertRight(routerModuleNode.getStart(), print); host.commitUpdate(recorder); } }); }; } function addDependencies() { return (_host) => { return (0, schematics_1.chain)([ (0, utility_1.addDependency)('@nguniversal/builders', '^16.2.0', { type: utility_1.DependencyType.Dev, }), (0, utility_1.addDependency)('@nguniversal/express-engine', '^16.2.0', { type: utility_1.DependencyType.Default, }), (0, utility_1.addDependency)('express', '^4.15.2', { type: utility_1.DependencyType.Default, }), (0, utility_1.addDependency)('@types/express', '^4.17.0', { type: utility_1.DependencyType.Dev, }), ]); }; } function addServerFile(options, isStandalone) { return async (host) => { const project = await (0, utils_1.getProject)(host, options.project); const browserDistDirectory = await (0, utils_1.getOutputPath)(host, options.project, 'build'); return (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [ (0, schematics_1.template)({ ...core_1.strings, ...options, stripTsExtension: utils_1.stripTsExtension, browserDistDirectory, isStandalone, }), (0, schematics_1.move)(project.root), ])); }; } function default_1(options) { return async (host) => { const project = await (0, utils_1.getProject)(host, options.project); const universalOptions = { ...options, skipInstall: true, }; const clientBuildTarget = project.targets.get('build'); if (!clientBuildTarget) { throw (0, project_targets_1.targetBuildNotFoundError)(); } const clientBuildOptions = (clientBuildTarget.options || {}); const isStandalone = (0, ng_ast_utils_1.isStandaloneApp)(host, clientBuildOptions.main); delete universalOptions.serverFileName; delete universalOptions.serverPort; return (0, schematics_1.chain)([ project.targets.has('server') ? (0, schematics_1.noop)() : (0, schematics_1.externalSchematic)('@schematics/angular', 'universal', universalOptions), addScriptsRule(options), updateServerTsConfigRule(options), updateWorkspaceConfigRule(options), isStandalone ? (0, schematics_1.noop)() : routingInitialNavigationRule(options), addServerFile(options, isStandalone), addDependencies(), ]); }; } exports.default = default_1; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9tb2R1bGVzL2V4cHJlc3MtZW5naW5lL3NjaGVtYXRpY3MvaW5zdGFsbC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUVILCtDQUF5RTtBQUN6RSwyREFZb0M7QUFFcEMseURBQTZGO0FBQzdGLHFFQUFpRTtBQUNqRSwyRUFBMkU7QUFDM0UsaUZBQXVGO0FBRXZGLGlDQUFpQztBQUVqQyxvQ0FPa0I7QUFJbEIsTUFBTSxxQkFBcUIsR0FBRyxXQUFXLENBQUM7QUFDMUMsTUFBTSxxQkFBcUIsR0FBRyxXQUFXLENBQUM7QUFFMUMsU0FBUyxjQUFjLENBQUMsT0FBNEI7SUFDbEQsT0FBTyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDcEIsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsSUFBSSxNQUFNLEtBQUssSUFBSSxFQUFFO1lBQ25CLE1BQU0sSUFBSSxnQ0FBbUIsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1NBQzlEO1FBRUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFBLHFCQUFhLEVBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDeEUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQVEsQ0FBQztRQUNqRCxHQUFHLENBQUMsT0FBTyxHQUFHO1lBQ1osR0FBRyxHQUFHLENBQUMsT0FBTztZQUNkLFNBQVMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxPQUFPLElBQUkscUJBQXFCLEVBQUU7WUFDL0QsV0FBVyxFQUFFLFFBQVEsVUFBVSxVQUFVO1lBQ3pDLFdBQVcsRUFBRSxzQkFBc0IsT0FBTyxDQUFDLE9B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UUFFMUMsTUFBTSxZQUFZLEdBQUcsSUFBQSw4QkFBZSxFQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVwRSxPQUFPLGdCQUFnQixDQUFDLGNBQWMsQ0FBQztRQUN2QyxPQUFPLGdCQUFnQixDQUFDLFVBQVUsQ0FBQztRQUVuQyxPQUFPLElBQUEsa0JBQUssRUFBQztZQUNYLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztnQkFDM0IsQ0FBQyxDQUFDLElBQUEsaUJBQUksR0FBRTtnQkFDUixDQUFDLENBQUMsSUFBQSw4QkFBaUIsRUFBQyxxQkFBcUIsRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLENBQUM7WUFDM0UsY0FBYyxDQUFDLE9BQU8sQ0FBQztZQUN2Qix3QkFBd0IsQ0FBQyxPQUFPLENBQUM7WUFDakMseUJBQXlCLENBQUMsT0FBTyxDQUFDO1lBQ2xDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBQSxpQkFBSSxHQUFFLENBQUMsQ0FBQyxDQUFDLDRCQUE0QixDQUFDLE9BQU8sQ0FBQztZQUM3RCxhQUFhLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQztZQUNwQyxlQUFlLEVBQUU7U0FDbEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQWhDRCw0QkFnQ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHsgZGlybmFtZSwgam9pbiwgbm9ybWFsaXplLCBzdHJpbmdzIH0gZnJvbSAnQGFuZ3VsYXItZGV2a2l0L2NvcmUnO1xuaW1wb3J0IHtcbiAgUnVsZSxcbiAgU2NoZW1hdGljc0V4Y2VwdGlvbixcbiAgVHJlZSxcbiAgYXBwbHksXG4gIGNoYWluLFxuICBleHRlcm5hbFNjaGVtYXRpYyxcbiAgbWVyZ2VXaXRoLFxuICBtb3ZlLFxuICBub29wLFxuICB0ZW1wbGF0ZSxcbiAgdXJsLFxufSBmcm9tICdAYW5ndWxhci1kZXZraXQvc2NoZW1hdGljcyc7XG5pbXBvcnQgeyBTY2hlbWEgYXMgVW5pdmVyc2FsT3B0aW9ucyB9IGZyb20gJ0BzY2hlbWF0aWNzL2FuZ3VsYXIvdW5pdmVyc2FsL3NjaGVtYSc7XG5pbXBvcnQgeyBEZXBlbmRlbmN5VHlwZSwgYWRkRGVwZW5kZW5jeSwgdXBkYXRlV29ya3NwYWNlIH0gZnJvbSAnQHNjaGVtYXRpY3MvYW5ndWxhci91dGlsaXR5JztcbmltcG9ydCB7IEpTT05GaWxlIH0gZnJvbSAnQHNjaGVtYXRpY3MvYW5ndWxhci91dGlsaXR5L2pzb24tZmlsZSc7XG5pbXBvcnQgeyBpc1N0YW5kYWxvbmVBcHAgfSBmcm9tICdAc2NoZW1hdGljcy9hbmd1bGFyL3V0aWxpdHkvbmctYXN0LXV0aWxzJztcbmltcG9ydCB7IHRhcmdldEJ1aWxkTm90Rm91bmRFcnJvciB9IGZyb20gJ0BzY2hlbWF0aWNzL2FuZ3VsYXIvdXRpbGl0eS9wcm9qZWN0LXRhcmdldHMnO1xuaW1wb3J0IHsgQnJvd3NlckJ1aWxkZXJPcHRpb25zIH0gZnJvbSAnQHNjaGVtYXRpY3MvYW5ndWxhci91dGlsaXR5L3dvcmtzcGFjZS1tb2RlbHMnO1xuaW1wb3J0ICogYXMgdHMgZnJvbSAndHlwZXNjcmlwdCc7XG5cbmltcG9ydCB7XG4gIGFkZEluaXRpYWxOYXZpZ2F0aW9uLFxuICBmaW5kSW1wb3J0LFxuICBnZXRJbXBvcnRPZklkZW50aWZpZXIsXG4gIGdldE91dHB1dFBhdGgsXG4gIGdldFByb2plY3QsXG4gIHN0cmlwVHNFeHRlbnNpb24sXG59IGZyb20gJy4uL3V0aWxzJztcblxuaW1wb3J0IHsgU2NoZW1hIGFzIEFkZFVuaXZlcnNhbE9wdGlvbnMgfSBmcm9tICcuL3NjaGVtYSc7XG5cbmNvbnN0IFNFUlZFX1NTUl9UQVJHRVRfTkFNRSA9ICdzZXJ2ZS1zc3InO1xuY29uc3QgUFJFUkVOREVSX1RBUkdFVF9OQU1FID0gJ3ByZXJlbmRlcic7XG5cbmZ1bmN0aW9uIGFkZFNjcmlwdHNSdWxlKG9wdGlvbnM6IEFkZFVuaXZlcnNhbE9wdGlvbnMpOiBSdWxlIHtcbiAgcmV0dXJuIGFzeW5jIChob3N0KSA9PiB7XG4gICAgY29uc3QgcGtnUGF0aCA9ICcvcGFja2FnZS5qc29uJztcbiAgICBjb25zdCBidWZmZXIgPSBob3N0LnJlYWQocGtnUGF0aCk7XG4gICAgaWYgKGJ1ZmZlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IFNjaGVtYXRpY3NFeGNlcHRpb24oJ0NvdWxkIG5vdCBmaW5kIHBhY2thZ2UuanNvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlcnZlckRpc3QgPSBhd2FpdCBnZXRPdXRwdXRQYXRoKGhvc3QsIG9wdGlvbnMucHJvamVjdCwgJ3NlcnZlcicpO1xuICAgIGNvbnN0IHBrZyA9IEpTT04ucGFyc2UoYnVmZmVyLnRvU3RyaW5nKCkpIGFzIGFueTtcbiAgICBwa2cuc2NyaXB0cyA9IHtcbiAgICAgIC4uLnBrZy5zY3JpcHRzLFxuICAgICAgJ2Rldjpzc3InOiBgbmcgcnVuICR7b3B0aW9ucy5wcm9qZWN0fToke1NFUlZFX1NTUl9UQVJHRVRfTkFNRX1gLFxuICAgICAgJ3NlcnZlOnNzcic6IGBub2RlICR7c2VydmVyRGlzdH0vbWFpbi5qc2AsXG4gICAgICAnYnVpbGQ6c3NyJzogYG5nIGJ1aWxkICYmIG5nIHJ1biAke29wdGlvbnMucHJvamVjdH06c2VydmVyYCxcbiAgICAgICdwcmVyZW5kZXInOiBgbmcgcnVuICR7b3B0aW9ucy5wcm9qZWN0fToke1BSRVJFTkRFUl9UQVJHRVRfTkFNRX1gLFxuICAgIH07XG5cbiAgICBob3N0Lm92ZXJ3cml0ZShwa2dQYXRoLCBKU09OLnN0cmluZ2lmeShwa2csIG51bGwsIDIpKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlV29ya3NwYWNlQ29uZmlnUnVsZShvcHRpb25zOiBBZGRVbml2ZXJzYWxPcHRpb25zKTogUnVsZSB7XG4gIHJldHVybiAoKSA9PiB7XG4gICAgcmV0dXJuIHVwZGF0ZVdvcmtzcGFjZSgod29ya3NwYWNlKSA9PiB7XG4gICAgICBjb25zdCBwcm9qZWN0TmFtZSA9IG9wdGlvbnMucHJvamVjdDtcbiAgICAgIGNvbnN0IHByb2plY3QgPSB3b3Jrc3BhY2UucHJvamVjdHMuZ2V0KHByb2plY3ROYW1lKTtcbiAgICAgIGlmICghcHJvamVjdCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlcnZlclRhcmdldCA9IHByb2plY3QudGFyZ2V0cy5nZXQoJ3NlcnZlcicpO1xuICAgICAgc2VydmVyVGFyZ2V0Lm9wdGlvbnMubWFpbiA9IGpvaW4oXG4gICAgICAgIG5vcm1hbGl6ZShwcm9qZWN0LnJvb3QpLFxuICAgICAgICBzdHJpcFRzRXh0ZW5zaW9uKG9wdGlvbnMuc2VydmVyRmlsZU5hbWUpICsgJy50cycsXG4gICAgICApO1xuXG4gICAgICBjb25zdCBzZXJ2ZVNTUlRhcmdldCA9IHByb2plY3QudGFyZ2V0cy5nZXQoU0VSVkVfU1NSX1RBUkdFVF9OQU1FKTtcbiAgICAgIGlmIChzZXJ2ZVNTUlRhcmdldCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHByb2plY3QudGFyZ2V0cy5hZGQoe1xuICAgICAgICBuYW1lOiBTRVJWRV9TU1JfVEFSR0VUX05BTUUsXG4gICAgICAgIGJ1aWxkZXI6ICdAbmd1bml2ZXJzYWwvYnVpbGRlcnM6c3NyLWRldi1zZXJ2ZXInLFxuICAgICAgICBkZWZhdWx0Q29uZmlndXJhdGlvbjogJ2RldmVsb3BtZW50JyxcbiAgICAgICAgb3B0aW9uczoge30sXG4gICAgICAgIGNvbmZpZ3VyYXRpb25zOiB7XG4gICAgICAgICAgZGV2ZWxvcG1lbnQ6IHtcbiAgICAgICAgICAgIGJyb3dzZXJUYXJnZXQ6IGAke3Byb2plY3ROYW1lfTpidWlsZDpkZXZlbG9wbWVudGAsXG4gICAgICAgICAgICBzZXJ2ZXJUYXJnZXQ6IGAke3Byb2plY3ROYW1lfTpzZXJ2ZXI6ZGV2ZWxvcG1lbnRgLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHJvZHVjdGlvbjoge1xuICAgICAgICAgICAgYnJvd3NlclRhcmdldDogYCR7cHJvamVjdE5hbWV9OmJ1aWxkOnByb2R1Y3Rpb25gLFxuICAgICAgICAgICAgc2VydmVyVGFyZ2V0OiBgJHtwcm9qZWN0TmFtZX06c2VydmVyOnByb2R1Y3Rpb25gLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcHJlcmVuZGVyVGFyZ2V0ID0gcHJvamVjdC50YXJnZXRzLmdldChQUkVSRU5ERVJfVEFSR0VUX05BTUUpO1xuICAgICAgaWYgKHByZXJlbmRlclRhcmdldCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHByb2plY3QudGFyZ2V0cy5hZGQoe1xuICAgICAgICBuYW1lOiBQUkVSRU5ERVJfVEFSR0VUX05BTUUsXG4gICAgICAgIGJ1aWxkZXI6ICdAbmd1bml2ZXJzYWwvYnVpbGRlcnM6cHJlcmVuZGVyJyxcbiAgICAgICAgZGVmYXVsdENvbmZpZ3VyYXRpb246ICdwcm9kdWN0aW9uJyxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgIHJvdXRlczogWycvJ10sXG4gICAgICAgIH0sXG4gICAgICAgIGNvbmZpZ3VyYXRpb25zOiB7XG4gICAgICAgICAgcHJvZHVjdGlvbjoge1xuICAgICAgICAgICAgYnJvd3NlclRhcmdldDogYCR7cHJvamVjdE5hbWV9OmJ1aWxkOnByb2R1Y3Rpb25gLFxuICAgICAgICAgICAgc2VydmVyVGFyZ2V0OiBgJHtwcm9qZWN0TmFtZX06c2VydmVyOnByb2R1Y3Rpb25gLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZGV2ZWxvcG1lbnQ6IHtcbiAgICAgICAgICAgIGJyb3dzZXJUYXJnZXQ6IGAke3Byb2plY3ROYW1lfTpidWlsZDpkZXZlbG9wbWVudGAsXG4gICAgICAgICAgICBzZXJ2ZXJUYXJnZXQ6IGAke3Byb2plY3ROYW1lfTpzZXJ2ZXI6ZGV2ZWxvcG1lbnRgLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlU2VydmVyVHNDb25maWdSdWxlKG9wdGlvbnM6IEFkZFVuaXZlcnNhbE9wdGlvbnMpOiBSdWxlIHtcbiAgcmV0dXJuIGFzeW5jIChob3N0KSA9PiB7XG4gICAgY29uc3QgcHJvamVjdCA9IGF3YWl0IGdldFByb2plY3QoaG9zdCwgb3B0aW9ucy5wcm9qZWN0KTtcbiAgICBjb25zdCBzZXJ2ZXJUYXJnZXQgPSBwcm9qZWN0LnRhcmdldHMuZ2V0KCdzZXJ2ZXInKTtcbiAgICBpZiAoIXNlcnZlclRhcmdldCB8fCAhc2VydmVyVGFyZ2V0Lm9wdGlvbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0c0NvbmZpZ1BhdGggPSBzZXJ2ZXJUYXJnZXQub3B0aW9ucy50c0NvbmZpZztcbiAgICBpZiAoIXRzQ29uZmlnUGF0aCB8fCB0eXBlb2YgdHNDb25maWdQYXRoICE9PSAnc3RyaW5nJykge1xuICAgICAgLy8gTm8gdHNjb25maWcgcGF0aFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRzQ29uZmlnID0gbmV3IEpTT05GaWxlKGhvc3QsIHRzQ29uZmlnUGF0aCk7XG4gICAgY29uc3QgZmlsZXNBc3ROb2RlID0gdHNDb25maWcuZ2V0KFsnZmlsZXMnXSk7XG4gICAgY29uc3Qgc2VydmVyRmlsZVBhdGggPSBzdHJpcFRzRXh0ZW5zaW9uKG9wdGlvbnMuc2VydmVyRmlsZU5hbWUpICsgJy50cyc7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmlsZXNBc3ROb2RlKSAmJiAhZmlsZXNBc3ROb2RlLnNvbWUoKHsgdGV4dCB9KSA9PiB0ZXh0ID09PSBzZXJ2ZXJGaWxlUGF0aCkpIHtcbiAgICAgIHRzQ29uZmlnLm1vZGlmeShbJ2ZpbGVzJ10sIFsuLi5maWxlc0FzdE5vZGUsIHNlcnZlckZpbGVQYXRoXSk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiByb3V0aW5nSW5pdGlhbE5hdmlnYXRpb25SdWxlKG9wdGlvbnM6IFVuaXZlcnNhbE9wdGlvbnMpOiBSdWxlIHtcbiAgcmV0dXJuIGFzeW5jIChob3N0KSA9PiB7XG4gICAgY29uc3QgcHJvamVjdCA9IGF3YWl0IGdldFByb2plY3QoaG9zdCwgb3B0aW9ucy5wcm9qZWN0KTtcbiAgICBjb25zdCBzZXJ2ZXJUYXJnZXQgPSBwcm9qZWN0LnRhcmdldHMuZ2V0KCdzZXJ2ZXInKTtcbiAgICBpZiAoIXNlcnZlclRhcmdldCB8fCAhc2VydmVyVGFyZ2V0Lm9wdGlvbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0c0NvbmZpZ1BhdGggPSBzZXJ2ZXJUYXJnZXQub3B0aW9ucy50c0NvbmZpZztcbiAgICBpZiAoIXRzQ29uZmlnUGF0aCB8fCB0eXBlb2YgdHNDb25maWdQYXRoICE9PSAnc3RyaW5nJyB8fCAhaG9zdC5leGlzdHModHNDb25maWdQYXRoKSkge1xuICAgICAgLy8gTm8gdHNjb25maWcgcGF0aFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlQ29uZmlnSG9zdDogdHMuUGFyc2VDb25maWdIb3N0ID0ge1xuICAgICAgdXNlQ2FzZVNlbnNpdGl2ZUZpbGVOYW1lczogdHMuc3lzLnVzZUNhc2VTZW5zaXRpdmVGaWxlTmFtZXMsXG4gICAgICByZWFkRGlyZWN0b3J5OiB0cy5zeXMucmVhZERpcmVjdG9yeSxcbiAgICAgIGZpbGVFeGlzdHM6IGZ1bmN0aW9uIChmaWxlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBob3N0LmV4aXN0cyhmaWxlTmFtZSk7XG4gICAgICB9LFxuICAgICAgcmVhZEZpbGU6IGZ1bmN0aW9uIChmaWxlTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGhvc3QucmVhZChmaWxlTmFtZSkudG9TdHJpbmcoKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCB7IGNvbmZpZyB9ID0gdHMucmVhZENvbmZpZ0ZpbGUodHNDb25maWdQYXRoLCBwYXJzZUNvbmZpZ0hvc3QucmVhZEZpbGUpO1xuICAgIGNvbnN0IHBhcnNlZCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KFxuICAgICAgY29uZmlnLFxuICAgICAgcGFyc2VDb25maWdIb3N0LFxuICAgICAgZGlybmFtZShub3JtYWxpemUodHNDb25maWdQYXRoKSksXG4gICAgKTtcbiAgICBjb25zdCB0c0hvc3QgPSB0cy5jcmVhdGVDb21waWxlckhvc3QocGFyc2VkLm9wdGlvbnMsIHRydWUpO1xuICAgIC8vIFN0cmlwIEJPTSBhcyBvdGhlcndpc2UgVFNDIG1ldGhvZHMgKEV4OiBnZXRXaWR0aCkgd2lsbCByZXR1cm4gYW4gb2Zmc2V0LFxuICAgIC8vIHdoaWNoIGJyZWFrcyB0aGUgQ0xJIFVwZGF0ZVJlY29yZGVyLlxuICAgIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci9wdWxsLzMwNzE5XG4gICAgdHNIb3N0LnJlYWRGaWxlID0gZnVuY3Rpb24gKGZpbGVOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGhvc3RcbiAgICAgICAgLnJlYWQoZmlsZU5hbWUpXG4gICAgICAgIC50b1N0cmluZygpXG4gICAgICAgIC5yZXBsYWNlKC9eXFx1RkVGRi8sICcnKTtcbiAgICB9O1xuICAgIHRzSG9zdC5kaXJlY3RvcnlFeGlzdHMgPSBmdW5jdGlvbiAoZGlyZWN0b3J5TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAvLyBXaGVuIHRoZSBwYXRoIGlzIGZpbGUgZ2V0RGlyIHdpbGwgdGhyb3cuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkaXIgPSBob3N0LmdldERpcihkaXJlY3RvcnlOYW1lKTtcblxuICAgICAgICByZXR1cm4gISEoZGlyLnN1YmRpcnMubGVuZ3RoIHx8IGRpci5zdWJmaWxlcy5sZW5ndGgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHRzSG9zdC5maWxlRXhpc3RzID0gZnVuY3Rpb24gKGZpbGVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiBob3N0LmV4aXN0cyhmaWxlTmFtZSk7XG4gICAgfTtcbiAgICB0c0hvc3QucmVhbHBhdGggPSBmdW5jdGlvbiAocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiBwYXRoO1xuICAgIH07XG4gICAgdHNIb3N0LmdldEN1cnJlbnREaXJlY3RvcnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gaG9zdC5yb290LnBhdGg7XG4gICAgfTtcblxuICAgIGNvbnN0IHByb2dyYW0gPSB0cy5jcmVhdGVQcm9ncmFtKHBhcnNlZC5maWxlTmFtZXMsIHBhcnNlZC5vcHRpb25zLCB0c0hvc3QpO1xuICAgIGNvbnN0IHR5cGVDaGVja2VyID0gcHJvZ3JhbS5nZXRUeXBlQ2hlY2tlcigpO1xuICAgIGNvbnN0IHNvdXJjZUZpbGVzID0gcHJvZ3JhbVxuICAgICAgLmdldFNvdXJjZUZpbGVzKClcbiAgICAgIC5maWx0ZXIoKGYpID0+ICFmLmlzRGVjbGFyYXRpb25GaWxlICYmICFwcm9ncmFtLmlzU291cmNlRmlsZUZyb21FeHRlcm5hbExpYnJhcnkoZikpO1xuICAgIGNvbnN0IHByaW50ZXIgPSB0cy5jcmVhdGVQcmludGVyKCk7XG4gICAgY29uc3Qgcm91dGVyTW9kdWxlID0gJ1JvdXRlck1vZHVsZSc7XG4gICAgY29uc3Qgcm91dGVyU291cmNlID0gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbiAgICBzb3VyY2VGaWxlcy5mb3JFYWNoKChzb3VyY2VGaWxlKSA9PiB7XG4gICAgICBjb25zdCByb3V0ZXJJbXBvcnQgPSBmaW5kSW1wb3J0KHNvdXJjZUZpbGUsIHJvdXRlclNvdXJjZSwgcm91dGVyTW9kdWxlKTtcbiAgICAgIGlmICghcm91dGVySW1wb3J0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IHJvdXRlck1vZHVsZU5vZGU6IHRzLkNhbGxFeHByZXNzaW9uO1xuICAgICAgdHMuZm9yRWFjaENoaWxkKHNvdXJjZUZpbGUsIGZ1bmN0aW9uIHZpc2l0Tm9kZShub2RlOiB0cy5Ob2RlKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0cy5pc0NhbGxFeHByZXNzaW9uKG5vZGUpICYmXG4gICAgICAgICAgdHMuaXNQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24obm9kZS5leHByZXNzaW9uKSAmJlxuICAgICAgICAgIHRzLmlzSWRlbnRpZmllcihub2RlLmV4cHJlc3Npb24uZXhwcmVzc2lvbikgJiZcbiAgICAgICAgICBub2RlLmV4cHJlc3Npb24ubmFtZS50ZXh0ID09PSAnZm9yUm9vdCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgaW1wID0gZ2V0SW1wb3J0T2ZJZGVudGlmaWVyKHR5cGVDaGVja2VyLCBub2RlLmV4cHJlc3Npb24uZXhwcmVzc2lvbik7XG5cbiAgICAgICAgICBpZiAoaW1wICYmIGltcC5uYW1lID09PSByb3V0ZXJNb2R1bGUgJiYgaW1wLmltcG9ydE1vZHVsZSA9PT0gcm91dGVyU291cmNlKSB7XG4gICAgICAgICAgICByb3V0ZXJNb2R1bGVOb2RlID0gbm9kZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0cy5mb3JFYWNoQ2hpbGQobm9kZSwgdmlzaXROb2RlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAocm91dGVyTW9kdWxlTm9kZSkge1xuICAgICAgICBjb25zdCBwcmludCA9IHByaW50ZXIucHJpbnROb2RlKFxuICAgICAgICAgIHRzLkVtaXRIaW50LlVuc3BlY2lmaWVkLFxuICAgICAgICAgIGFkZEluaXRpYWxOYXZpZ2F0aW9uKHJvdXRlck1vZHVsZU5vZGUpLFxuICAgICAgICAgIHNvdXJjZUZpbGUsXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgcmVjb3JkZXIgPSBob3N0LmJlZ2luVXBkYXRlKHNvdXJjZUZpbGUuZmlsZU5hbWUpO1xuICAgICAgICByZWNvcmRlci5yZW1vdmUocm91dGVyTW9kdWxlTm9kZS5nZXRTdGFydCgpLCByb3V0ZXJNb2R1bGVOb2RlLmdldFdpZHRoKCkpO1xuICAgICAgICByZWNvcmRlci5pbnNlcnRSaWdodChyb3V0ZXJNb2R1bGVOb2RlLmdldFN0YXJ0KCksIHByaW50KTtcbiAgICAgICAgaG9zdC5jb21taXRVcGRhdGUocmVjb3JkZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhZGREZXBlbmRlbmNpZXMoKTogUnVsZSB7XG4gIHJldHVybiAoX2hvc3Q6IFRyZWUpID0+IHtcbiAgICByZXR1cm4gY2hhaW4oW1xuICAgICAgYWRkRGVwZW5kZW5jeSgnQG5ndW5pdmVyc2FsL2J1aWxkZXJzJywgJ14wLjAuMC1QTEFDRUhPTERFUicsIHtcbiAgICAgICAgdHlwZTogRGVwZW5kZW5jeVR5cGUuRGV2LFxuICAgICAgfSksXG4gICAgICBhZGREZXBlbmRlbmN5KCdAbmd1bml2ZXJzYWwvZXhwcmVzcy1lbmdpbmUnLCAnXjAuMC4wLVBMQUNFSE9MREVSJywge1xuICAgICAgICB0eXBlOiBEZXBlbmRlbmN5VHlwZS5EZWZhdWx0LFxuICAgICAgfSksXG4gICAgICBhZGREZXBlbmRlbmN5KCdleHByZXNzJywgJ0VYUFJFU1NfVkVSU0lPTicsIHtcbiAgICAgICAgdHlwZTogRGVwZW5kZW5jeVR5cGUuRGVmYXVsdCxcbiAgICAgIH0pLFxuICAgICAgYWRkRGVwZW5kZW5jeSgnQHR5cGVzL2V4cHJlc3MnLCAnRVhQUkVTU19UWVBFU19WRVJTSU9OJywge1xuICAgICAgICB0eXBlOiBEZXBlbmRlbmN5VHlwZS5EZXYsXG4gICAgICB9KSxcbiAgICBdKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYWRkU2VydmVyRmlsZShvcHRpb25zOiBVbml2ZXJzYWxPcHRpb25zLCBpc1N0YW5kYWxvbmU6IGJvb2xlYW4pOiBSdWxlIHtcbiAgcmV0dXJuIGFzeW5jIChob3N0KSA9PiB7XG4gICAgY29uc3QgcHJvamVjdCA9IGF3YWl0IGdldFByb2plY3QoaG9zdCwgb3B0aW9ucy5wcm9qZWN0KTtcbiAgICBjb25zdCBicm93c2VyRGlzdERpcmVjdG9yeSA9IGF3YWl0IGdldE91dHB1dFBhdGgoaG9zdCwgb3B0aW9ucy5wcm9qZWN0LCAnYnVpbGQnKTtcblxuICAgIHJldHVybiBtZXJnZVdpdGgoXG4gICAgICBhcHBseSh1cmwoJy4vZmlsZXMnKSwgW1xuICAgICAgICB0ZW1wbGF0ZSh7XG4gICAgICAgICAgLi4uc3RyaW5ncyxcbiAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgIHN0cmlwVHNFeHRlbnNpb24sXG4gICAgICAgICAgYnJvd3NlckRpc3REaXJlY3RvcnksXG4gICAgICAgICAgaXNTdGFuZGFsb25lLFxuICAgICAgICB9KSxcbiAgICAgICAgbW92ZShwcm9qZWN0LnJvb3QpLFxuICAgICAgXSksXG4gICAgKTtcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gKG9wdGlvbnM6IEFkZFVuaXZlcnNhbE9wdGlvbnMpOiBSdWxlIHtcbiAgcmV0dXJuIGFzeW5jIChob3N0KSA9PiB7XG4gICAgY29uc3QgcHJvamVjdCA9IGF3YWl0IGdldFByb2plY3QoaG9zdCwgb3B0aW9ucy5wcm9qZWN0KTtcbiAgICBjb25zdCB1bml2ZXJzYWxPcHRpb25zID0ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHNraXBJbnN0YWxsOiB0cnVlLFxuICAgIH07XG4gICAgY29uc3QgY2xpZW50QnVpbGRUYXJnZXQgPSBwcm9qZWN0LnRhcmdldHMuZ2V0KCdidWlsZCcpO1xuICAgIGlmICghY2xpZW50QnVpbGRUYXJnZXQpIHtcbiAgICAgIHRocm93IHRhcmdldEJ1aWxkTm90Rm91bmRFcnJvcigpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsaWVudEJ1aWxkT3B0aW9ucyA9IChjbGllbnRCdWlsZFRhcmdldC5vcHRpb25zIHx8XG4gICAgICB7fSkgYXMgdW5rbm93biBhcyBCcm93c2VyQnVpbGRlck9wdGlvbnM7XG5cbiAgICBjb25zdCBpc1N0YW5kYWxvbmUgPSBpc1N0YW5kYWxvbmVBcHAoaG9zdCwgY2xpZW50QnVpbGRPcHRpb25zLm1haW4pO1xuXG4gICAgZGVsZXRlIHVuaXZlcnNhbE9wdGlvbnMuc2VydmVyRmlsZU5hbWU7XG4gICAgZGVsZXRlIHVuaXZlcnNhbE9wdGlvbnMuc2VydmVyUG9ydDtcblxuICAgIHJldHVybiBjaGFpbihbXG4gICAgICBwcm9qZWN0LnRhcmdldHMuaGFzKCdzZXJ2ZXInKVxuICAgICAgICA/IG5vb3AoKVxuICAgICAgICA6IGV4dGVybmFsU2NoZW1hdGljKCdAc2NoZW1hdGljcy9hbmd1bGFyJywgJ3VuaXZlcnNhbCcsIHVuaXZlcnNhbE9wdGlvbnMpLFxuICAgICAgYWRkU2NyaXB0c1J1bGUob3B0aW9ucyksXG4gICAgICB1cGRhdGVTZXJ2ZXJUc0NvbmZpZ1J1bGUob3B0aW9ucyksXG4gICAgICB1cGRhdGVXb3Jrc3BhY2VDb25maWdSdWxlKG9wdGlvbnMpLFxuICAgICAgaXNTdGFuZGFsb25lID8gbm9vcCgpIDogcm91dGluZ0luaXRpYWxOYXZpZ2F0aW9uUnVsZShvcHRpb25zKSxcbiAgICAgIGFkZFNlcnZlckZpbGUob3B0aW9ucywgaXNTdGFuZGFsb25lKSxcbiAgICAgIGFkZERlcGVuZGVuY2llcygpLFxuICAgIF0pO1xuICB9O1xufVxuIl19