UNPKG

open-next-cdk

Version:

Deploy a NextJS app using OpenNext packaging to serverless AWS using CDK

179 lines 27.3 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeTokenPlaceholder = exports.TOKEN_PLACEHOLDER_END = exports.TOKEN_PLACEHOLDER_BEGIN = exports.getBuildCmdEnvironment = exports.createArchive = exports.NextjsBuild = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const constructs_1 = require("constructs"); const spawn = require("cross-spawn"); const fs = require("fs-extra"); const NextjsAssetsDeployment_1 = require("./NextjsAssetsDeployment"); const NEXTJS_BUILD_DIR = '.open-next'; const NEXTJS_STATIC_DIR = 'assets'; const NEXTJS_BUILD_MIDDLEWARE_FN_DIR = 'middleware-function'; const NEXTJS_BUILD_IMAGE_FN_DIR = 'image-optimization-function'; const NEXTJS_BUILD_SERVER_FN_DIR = 'server-function'; /** * Represents a built NextJS application. * This construct runs `npm build` in standalone output mode inside your `nextjsPath`. * This construct can be used by higher level constructs or used directly. */ class NextjsBuild extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); this.props = props; const nextJsPath = props.nextJsPath || props.nextjsPath; const openNextPath = props.openNextPath; if (nextJsPath) { if (openNextPath) throw new Error(`Cannot supply both nextJsPath and openNextPath`); if (!fs.existsSync(nextJsPath)) throw new Error(`NextJS application not found at "${nextJsPath}"`); // build app if (nextJsPath) { this.runNpmBuild(nextJsPath); } this.openNextPath = path.join(nextJsPath, NEXTJS_BUILD_DIR); if (!fs.existsSync(this.openNextPath)) throw new Error(`OpenNext package failed to build at "${this.openNextPath}"`); } else if (openNextPath) { this.openNextPath = path.resolve(openNextPath); if (!fs.existsSync(this.openNextPath)) throw new Error(`OpenNext package not found at "${this.openNextPath}"`); } else { throw new Error(`Must supply either nextJsPath or openNextPath`); } // our outputs this.nextStaticDir = this._getNextStaticDir(); this.nextImageFnDir = this._getOutputDir(NEXTJS_BUILD_IMAGE_FN_DIR); this.nextServerFnDir = this._getOutputDir(NEXTJS_BUILD_SERVER_FN_DIR); this.nextMiddlewareFnDir = this._getOutputDir(NEXTJS_BUILD_MIDDLEWARE_FN_DIR, true); } runNpmBuild(nextjsPath) { const { isPlaceholder, quiet } = this.props; if (isPlaceholder) { if (!quiet) console.debug(`Skipping build for placeholder NextjsBuild at ${nextjsPath}`); return; } // validate site path exists if (!fs.existsSync(nextjsPath)) { throw new Error(`Invalid nextjsPath ${nextjsPath} - directory does not exist at "${path.resolve(nextjsPath)}"`); } // Ensure that the site has a build script defined if (!fs.existsSync(path.join(nextjsPath, 'package.json'))) { throw new Error(`No package.json found at "${nextjsPath}".`); } const packageJson = fs.readJsonSync(path.join(nextjsPath, 'package.json')); if (!packageJson.scripts || !packageJson.scripts.build) { throw new Error(`No "build" script found within package.json in "${nextjsPath}".`); } // build environment vars const buildEnv = { ...process.env, ...getBuildCmdEnvironment(this.props.environment), ...(this.props.nodeEnv ? { NODE_ENV: this.props.nodeEnv } : {}), }; const buildPath = this.props.buildPath ?? nextjsPath; const buildCommand = this.props.buildCommand ?? 'npx --yes open-next@1 build'; // run build console.debug(`├ Running "${buildCommand}" in`, buildPath); const cmdParts = buildCommand.split(/\s+/); const buildResult = spawn.sync(cmdParts[0], cmdParts.slice(1), { cwd: buildPath, stdio: this.props.quiet ? 'ignore' : 'inherit', env: buildEnv, shell: true, }); if (buildResult.status !== 0) { throw new Error('The app "build" script failed.'); } } readPublicFileList() { const publicDir = this._getNextStaticDir(); if (!fs.existsSync(publicDir)) return []; return NextjsAssetsDeployment_1.listDirectory(publicDir).map((file) => path.join('/', path.relative(publicDir, file))); } _getNextBuildDir() { return this.openNextPath; } _getOutputDir(subdir, suppressMissing = false) { const { isPlaceholder } = this.props; const nextDir = this._getNextBuildDir(); const standaloneDir = path.join(nextDir, subdir); if (!suppressMissing && !isPlaceholder && !fs.existsSync(standaloneDir)) { throw new Error(`Could not find ${standaloneDir} directory.`); } return standaloneDir; } // contains static files _getNextStaticDir() { return path.join(this._getNextBuildDir(), NEXTJS_STATIC_DIR); } } exports.NextjsBuild = NextjsBuild; _a = JSII_RTTI_SYMBOL_1; NextjsBuild[_a] = { fqn: "open-next-cdk.NextjsBuild", version: "0.0.10" }; // zip up a directory and return path to zip file function createArchive({ directory, zipFileName, zipOutDir, fileGlob = '.', compressionLevel = 1, quiet, }) { // if directory is empty, can skip if (!fs.existsSync(directory) || fs.readdirSync(directory).length === 0) return null; zipOutDir = path.resolve(zipOutDir); fs.mkdirpSync(zipOutDir); // get output path const zipFilePath = path.join(zipOutDir, zipFileName); // delete existing zip file if (fs.existsSync(zipFilePath)) { fs.unlinkSync(zipFilePath); } // run script to create zipfile, preserving symlinks for node_modules (e.g. pnpm structure) let result; const isWindows = process.platform === 'win32'; if (isWindows) { const psCompressionLevel = compressionLevel === 0 ? 'NoCompression' : 'Fastest'; result = spawn.sync('powershell.exe', [ '-NoLogo', '-NoProfile', '-NonInteractive', '-Command', `Compress-Archive -Path '${directory}\\*' -DestinationPath '${zipFilePath}' -CompressionLevel ${psCompressionLevel}`, ], { stdio: 'inherit' }); } else { result = spawn.sync('bash', // getting ENOENT when specifying 'node' here for some reason [ quiet ? '-c' : '-xc', [`cd '${directory}'`, `zip -ryq${compressionLevel} '${zipFilePath}' ${fileGlob}`].join('&&'), ], { stdio: 'inherit' }); } if (result.status !== 0) { throw new Error(`There was a problem generating the package for ${zipFileName} with ${directory}: ${result.error}`); } // check output if (!fs.existsSync(zipFilePath)) { throw new Error(`There was a problem generating the archive for ${directory}; the archive is missing in ${zipFilePath}.`); } return zipFilePath; } exports.createArchive = createArchive; function getBuildCmdEnvironment(siteEnvironment) { // Generate environment placeholders to be replaced // ie. environment => { API_URL: api.url } // environment => API_URL="{NEXT{! API_URL !}}" // const buildCmdEnvironment = {}; Object.entries(siteEnvironment || {}).forEach(([key, value]) => { buildCmdEnvironment[key] = aws_cdk_lib_1.Token.isUnresolved(value) ? exports.makeTokenPlaceholder(key) : value; }); return buildCmdEnvironment; } exports.getBuildCmdEnvironment = getBuildCmdEnvironment; exports.TOKEN_PLACEHOLDER_BEGIN = '{NEXT{! '; exports.TOKEN_PLACEHOLDER_END = ' !}}'; exports.makeTokenPlaceholder = (value) => exports.TOKEN_PLACEHOLDER_BEGIN + value.toString() + exports.TOKEN_PLACEHOLDER_END; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTmV4dGpzQnVpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvTmV4dGpzQnVpbGQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsNkNBQW9DO0FBQ3BDLDJDQUF1QztBQUN2QyxxQ0FBcUM7QUFDckMsK0JBQStCO0FBQy9CLHFFQUF5RDtBQUd6RCxNQUFNLGdCQUFnQixHQUFHLFlBQVksQ0FBQztBQUN0QyxNQUFNLGlCQUFpQixHQUFHLFFBQVEsQ0FBQztBQUNuQyxNQUFNLDhCQUE4QixHQUFHLHFCQUFxQixDQUFDO0FBQzdELE1BQU0seUJBQXlCLEdBQUcsNkJBQTZCLENBQUM7QUFDaEUsTUFBTSwwQkFBMEIsR0FBRyxpQkFBaUIsQ0FBQztBQUlyRDs7OztHQUlHO0FBQ0gsTUFBYSxXQUFZLFNBQVEsc0JBQVM7SUF3QnhDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBdUI7UUFDL0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUVuQixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDeEQsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztRQUV4QyxJQUFJLFVBQVUsRUFBRTtZQUNkLElBQUksWUFBWTtnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7WUFDcEYsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLFVBQVUsR0FBRyxDQUFDLENBQUM7WUFFbkcsWUFBWTtZQUNaLElBQUksVUFBVSxFQUFFO2dCQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDOUI7WUFFRCxJQUFJLENBQUMsWUFBWSxH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VyxDQUFDLEVBQUU7UUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FDYixrREFBa0QsU0FBUywrQkFBK0IsV0FBVyxHQUFHLENBQ3pHLENBQUM7S0FDSDtJQUVELE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUExREQsc0NBMERDO0FBRUQsU0FBZ0Isc0JBQXNCLENBQUMsZUFBMkM7SUFDaEYsbURBQW1EO0lBQ25ELDBDQUEwQztJQUMxQyxtREFBbUQ7SUFDbkQsRUFBRTtJQUNGLE1BQU0sbUJBQW1CLEdBQTJCLEVBQUUsQ0FBQztJQUN2RCxNQUFNLENBQUMsT0FBTyxDQUFDLGVBQWUsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFO1FBQzdELG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxHQUFHLG1CQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyw0QkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQzNGLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxtQkFBbUIsQ0FBQztBQUM3QixDQUFDO0FBWEQsd0RBV0M7QUFFWSxRQUFBLHVCQUF1QixHQUFHLFVBQVUsQ0FBQztBQUNyQyxRQUFBLHFCQUFxQixHQUFHLE1BQU0sQ0FBQztBQUMvQixRQUFBLG9CQUFvQixHQUFHLENBQUMsS0FBYSxFQUFVLEVBQUUsQ0FDNUQsK0JBQXVCLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxHQUFHLDZCQUFxQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBzcGF3biBmcm9tICdjcm9zcy1zcGF3bic7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBsaXN0RGlyZWN0b3J5IH0gZnJvbSAnLi9OZXh0anNBc3NldHNEZXBsb3ltZW50JztcbmltcG9ydCB7IENvbXByZXNzaW9uTGV2ZWwsIE5leHRqc0Jhc2VQcm9wcyB9IGZyb20gJy4vTmV4dGpzQmFzZSc7XG5cbmNvbnN0IE5FWFRKU19CVUlMRF9ESVIgPSAnLm9wZW4tbmV4dCc7XG5jb25zdCBORVhUSlNfU1RBVElDX0RJUiA9ICdhc3NldHMnO1xuY29uc3QgTkVYVEpTX0JVSUxEX01JRERMRVdBUkVfRk5fRElSID0gJ21pZGRsZXdhcmUtZnVuY3Rpb24nO1xuY29uc3QgTkVYVEpTX0JVSUxEX0lNQUdFX0ZOX0RJUiA9ICdpbWFnZS1vcHRpbWl6YXRpb24tZnVuY3Rpb24nO1xuY29uc3QgTkVYVEpTX0JVSUxEX1NFUlZFUl9GTl9ESVIgPSAnc2VydmVyLWZ1bmN0aW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBOZXh0anNCdWlsZFByb3BzIGV4dGVuZHMgTmV4dGpzQmFzZVByb3BzIHt9XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGJ1aWx0IE5leHRKUyBhcHBsaWNhdGlvbi5cbiAqIFRoaXMgY29uc3RydWN0IHJ1bnMgYG5wbSBidWlsZGAgaW4gc3RhbmRhbG9uZSBvdXRwdXQgbW9kZSBpbnNpZGUgeW91ciBgbmV4dGpzUGF0aGAuXG4gKiBUaGlzIGNvbnN0cnVjdCBjYW4gYmUgdXNlZCBieSBoaWdoZXIgbGV2ZWwgY29uc3RydWN0cyBvciB1c2VkIGRpcmVjdGx5LlxuICovXG5leHBvcnQgY2xhc3MgTmV4dGpzQnVpbGQgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvLyBidWlsZCBvdXRwdXQgZGlyZWN0b3JpZXNcbiAgLyoqXG4gICAqIENvbnRhaW5zIGNvZGUgZm9yIG1pZGRsZXdhcmUuIE5vdCBjdXJyZW50bHkgdXNlZC5cbiAgICovXG4gIHB1YmxpYyBuZXh0TWlkZGxld2FyZUZuRGlyPzogc3RyaW5nO1xuICAvKipcbiAgICogQ29udGFpbnMgc2VydmVyIGNvZGUgYW5kIGRlcGVuZGVuY2llcy5cbiAgICovXG4gIHB1YmxpYyBuZXh0U2VydmVyRm5EaXI6IHN0cmluZztcbiAgLyoqXG4gICAqIENvbnRhaW5zIGZ1bmN0aW9uIGZvciBwcm9jZXNzZXNzaW5nIGltYWdlIHJlcXVlc3RzLlxuICAgKiBTaG91bGQgYmUgYXJtNjQuXG4gICAqL1xuICBwdWJsaWMgbmV4dEltYWdlRm5EaXI6IHN0cmluZztcbiAgLyoqXG4gICAqIFN0YXRpYyBmaWxlcyBjb250YWluaW5nIGNsaWVudC1zaWRlIGNvZGUuXG4gICAqL1xuICBwdWJsaWMgbmV4dFN0YXRpY0Rpcjogc3RyaW5nO1xuXG4gIHB1YmxpYyBwcm9wczogTmV4dGpzQnVpbGRQcm9wcztcblxuICByZWFkb25seSBvcGVuTmV4dFBhdGg6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTmV4dGpzQnVpbGRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuXG4gICAgY29uc3QgbmV4dEpzUGF0aCA9IHByb3BzLm5leHRKc1BhdGggfHwgcHJvcHMubmV4dGpzUGF0aDtcbiAgICBjb25zdCBvcGVuTmV4dFBhdGggPSBwcm9wcy5vcGVuTmV4dFBhdGg7XG5cbiAgICBpZiAobmV4dEpzUGF0aCkge1xuICAgICAgaWYgKG9wZW5OZXh0UGF0aCkgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc3VwcGx5IGJvdGggbmV4dEpzUGF0aCBhbmQgb3Blbk5leHRQYXRoYCk7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMobmV4dEpzUGF0aCkpIHRocm93IG5ldyBFcnJvcihgTmV4dEpTIGFwcGxpY2F0aW9uIG5vdCBmb3VuZCBhdCBcIiR7bmV4dEpzUGF0aH1cImApO1xuXG4gICAgICAvLyBidWlsZCBhcHBcbiAgICAgIGlmIChuZXh0SnNQYXRoKSB7XG4gICAgICAgIHRoaXMucnVuTnBtQnVpbGQobmV4dEpzUGF0aCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMub3Blbk5leHRQYXRoID0gcGF0aC5qb2luKG5leHRKc1BhdGgsIE5FWFRKU19CVUlMRF9ESVIpO1xuICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHRoaXMub3Blbk5leHRQYXRoKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBPcGVuTmV4dCBwYWNrYWdlIGZhaWxlZCB0byBidWlsZCBhdCBcIiR7dGhpcy5vcGVuTmV4dFBhdGh9XCJgKTtcbiAgICB9IGVsc2UgaWYgKG9wZW5OZXh0UGF0aCkge1xuICAgICAgdGhpcy5vcGVuTmV4dFBhdGggPSBwYXRoLnJlc29sdmUob3Blbk5leHRQYXRoKTtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyh0aGlzLm9wZW5OZXh0UGF0aCkpIHRocm93IG5ldyBFcnJvcihgT3Blbk5leHQgcGFja2FnZSBub3QgZm91bmQgYXQgXCIke3RoaXMub3Blbk5leHRQYXRofVwiYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTXVzdCBzdXBwbHkgZWl0aGVyIG5leHRKc1BhdGggb3Igb3Blbk5leHRQYXRoYCk7XG4gICAgfVxuXG4gICAgLy8gb3VyIG91dHB1dHNcbiAgICB0aGlzLm5leHRTdGF0aWNEaXIgPSB0aGlzLl9nZXROZXh0U3RhdGljRGlyKCk7XG4gICAgdGhpcy5uZXh0SW1hZ2VGbkRpciA9IHRoaXMuX2dldE91dHB1dERpcihORVhUSlNfQlVJTERfSU1BR0VfRk5fRElSKTtcbiAgICB0aGlzLm5leHRTZXJ2ZXJGbkRpciA9IHRoaXMuX2dldE91dHB1dERpcihORVhUSlNfQlVJTERfU0VSVkVSX0ZOX0RJUik7XG4gICAgdGhpcy5uZXh0TWlkZGxld2FyZUZuRGlyID0gdGhpcy5fZ2V0T3V0cHV0RGlyKE5FWFRKU19CVUlMRF9NSURETEVXQVJFX0ZOX0RJUiwgdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIHJ1bk5wbUJ1aWxkKG5leHRqc1BhdGg6IHN0cmluZykge1xuICAgIGNvbnN0IHsgaXNQbGFjZWhvbGRlciwgcXVpZXQgfSA9IHRoaXMucHJvcHM7XG5cbiAgICBpZiAoaXNQbGFjZWhvbGRlcikge1xuICAgICAgaWYgKCFxdWlldCkgY29uc29sZS5kZWJ1ZyhgU2tpcHBpbmcgYnVpbGQgZm9yIHBsYWNlaG9sZGVyIE5leHRqc0J1aWxkIGF0ICR7bmV4dGpzUGF0aH1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSBzaXRlIHBhdGggZXhpc3RzXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKG5leHRqc1BhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbmV4dGpzUGF0aCAke25leHRqc1BhdGh9IC0gZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0IGF0IFwiJHtwYXRoLnJlc29sdmUobmV4dGpzUGF0aCl9XCJgKTtcbiAgICB9XG4gICAgLy8gRW5zdXJlIHRoYXQgdGhlIHNpdGUgaGFzIGEgYnVpbGQgc2NyaXB0IGRlZmluZWRcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMocGF0aC5qb2luKG5leHRqc1BhdGgsICdwYWNrYWdlLmpzb24nKSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gcGFja2FnZS5qc29uIGZvdW5kIGF0IFwiJHtuZXh0anNQYXRofVwiLmApO1xuICAgIH1cbiAgICBjb25zdCBwYWNrYWdlSnNvbiA9IGZzLnJlYWRKc29uU3luYyhwYXRoLmpvaW4obmV4dGpzUGF0aCwgJ3BhY2thZ2UuanNvbicpKTtcbiAgICBpZiAoIXBhY2thZ2VKc29uLnNjcmlwdHMgfHwgIXBhY2thZ2VKc29uLnNjcmlwdHMuYnVpbGQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gXCJidWlsZFwiIHNjcmlwdCBmb3VuZCB3aXRoaW4gcGFja2FnZS5qc29uIGluIFwiJHtuZXh0anNQYXRofVwiLmApO1xuICAgIH1cblxuICAgIC8vIGJ1aWxkIGVudmlyb25tZW50IHZhcnNcbiAgICBjb25zdCBidWlsZEVudiA9IHtcbiAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgLi4uZ2V0QnVpbGRDbWRFbnZpcm9ubWVudCh0aGlzLnByb3BzLmVudmlyb25tZW50KSxcbiAgICAgIC4uLih0aGlzLnByb3BzLm5vZGVFbnYgPyB7IE5PREVfRU5WOiB0aGlzLnByb3BzLm5vZGVFbnYgfSA6IHt9KSxcbiAgICB9O1xuXG4gICAgY29uc3QgYnVpbGRQYXRoID0gdGhpcy5wcm9wcy5idWlsZFBhdGggPz8gbmV4dGpzUGF0aDtcbiAgICBjb25zdCBidWlsZENvbW1hbmQgPSB0aGlzLnByb3BzLmJ1aWxkQ29tbWFuZCA/PyAnbnB4IC0teWVzIG9wZW4tbmV4dEAxIGJ1aWxkJztcbiAgICAvLyBydW4gYnVpbGRcbiAgICBjb25zb2xlLmRlYnVnKGDilJwgUnVubmluZyBcIiR7YnVpbGRDb21tYW5kfVwiIGluYCwgYnVpbGRQYXRoKTtcbiAgICBjb25zdCBjbWRQYXJ0cyA9IGJ1aWxkQ29tbWFuZC5zcGxpdCgvXFxzKy8pO1xuICAgIGNvbnN0IGJ1aWxkUmVzdWx0ID0gc3Bhd24uc3luYyhjbWRQYXJ0c1swXSwgY21kUGFydHMuc2xpY2UoMSksIHtcbiAgICAgIGN3ZDogYnVpbGRQYXRoLFxuICAgICAgc3RkaW86IHRoaXMucHJvcHMucXVpZXQgPyAnaWdub3JlJyA6ICdpbmhlcml0JyxcbiAgICAgIGVudjogYnVpbGRFbnYsXG4gICAgICBzaGVsbDogdHJ1ZSxcbiAgICB9KTtcbiAgICBpZiAoYnVpbGRSZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBhcHAgXCJidWlsZFwiIHNjcmlwdCBmYWlsZWQuJyk7XG4gICAgfVxuICB9XG5cbiAgcmVhZFB1YmxpY0ZpbGVMaXN0KCkge1xuICAgIGNvbnN0IHB1YmxpY0RpciA9IHRoaXMuX2dldE5leHRTdGF0aWNEaXIoKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMocHVibGljRGlyKSkgcmV0dXJuIFtdO1xuICAgIHJldHVybiBsaXN0RGlyZWN0b3J5KHB1YmxpY0RpcikubWFwKChmaWxlKSA9PiBwYXRoLmpvaW4oJy8nLCBwYXRoLnJlbGF0aXZlKHB1YmxpY0RpciwgZmlsZSkpKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dldE5leHRCdWlsZERpcigpIHtcbiAgICByZXR1cm4gdGhpcy5vcGVuTmV4dFBhdGg7XG4gIH1cblxuICBwcml2YXRlIF9nZXRPdXRwdXREaXIoc3ViZGlyOiBzdHJpbmcsIHN1cHByZXNzTWlzc2luZyA9IGZhbHNlKSB7XG4gICAgY29uc3QgeyBpc1BsYWNlaG9sZGVyIH0gPSB0aGlzLnByb3BzO1xuXG4gICAgY29uc3QgbmV4dERpciA9IHRoaXMuX2dldE5leHRCdWlsZERpcigpO1xuICAgIGNvbnN0IHN0YW5kYWxvbmVEaXIgPSBwYXRoLmpvaW4obmV4dERpciwgc3ViZGlyKTtcblxuICAgIGlmICghc3VwcHJlc3NNaXNzaW5nICYmICFpc1BsYWNlaG9sZGVyICYmICFmcy5leGlzdHNTeW5jKHN0YW5kYWxvbmVEaXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kICR7c3RhbmRhbG9uZURpcn0gZGlyZWN0b3J5LmApO1xuICAgIH1cbiAgICByZXR1cm4gc3RhbmRhbG9uZURpcjtcbiAgfVxuXG4gIC8vIGNvbnRhaW5zIHN0YXRpYyBmaWxlc1xuICBwcml2YXRlIF9nZXROZXh0U3RhdGljRGlyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5fZ2V0TmV4dEJ1aWxkRGlyKCksIE5FWFRKU19TVEFUSUNfRElSKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUFyY2hpdmVBcmdzIHtcbiAgcmVhZG9ubHkgY29tcHJlc3Npb25MZXZlbD86IENvbXByZXNzaW9uTGV2ZWw7XG4gIHJlYWRvbmx5IGRpcmVjdG9yeTogc3RyaW5nO1xuICByZWFkb25seSB6aXBGaWxlTmFtZTogc3RyaW5nO1xuICByZWFkb25seSB6aXBPdXREaXI6IHN0cmluZztcbiAgcmVhZG9ubHkgZmlsZUdsb2I/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbn1cblxuLy8gemlwIHVwIGEgZGlyZWN0b3J5IGFuZCByZXR1cm4gcGF0aCB0byB6aXAgZmlsZVxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFyY2hpdmUoe1xuICBkaXJlY3RvcnksXG4gIHppcEZpbGVOYW1lLFxuICB6aXBPdXREaXIsXG4gIGZpbGVHbG9iID0gJy4nLFxuICBjb21wcmVzc2lvbkxldmVsID0gMSxcbiAgcXVpZXQsXG59OiBDcmVhdGVBcmNoaXZlQXJncyk6IHN0cmluZyB8IG51bGwge1xuICAvLyBpZiBkaXJlY3RvcnkgaXMgZW1wdHksIGNhbiBza2lwXG4gIGlmICghZnMuZXhpc3RzU3luYyhkaXJlY3RvcnkpIHx8IGZzLnJlYWRkaXJTeW5jKGRpcmVjdG9yeSkubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcblxuICB6aXBPdXREaXIgPSBwYXRoLnJlc29sdmUoemlwT3V0RGlyKTtcbiAgZnMubWtkaXJwU3luYyh6aXBPdXREaXIpO1xuICAvLyBnZXQgb3V0cHV0IHBhdGhcbiAgY29uc3QgemlwRmlsZVBhdGggPSBwYXRoLmpvaW4oemlwT3V0RGlyLCB6aXBGaWxlTmFtZSk7XG5cbiAgLy8gZGVsZXRlIGV4aXN0aW5nIHppcCBmaWxlXG4gIGlmIChmcy5leGlzdHNTeW5jKHppcEZpbGVQYXRoKSkge1xuICAgIGZzLnVubGlua1N5bmMoemlwRmlsZVBhdGgpO1xuICB9XG5cbiAgLy8gcnVuIHNjcmlwdCB0byBjcmVhdGUgemlwZmlsZSwgcHJlc2VydmluZyBzeW1saW5rcyBmb3Igbm9kZV9tb2R1bGVzIChlLmcuIHBucG0gc3RydWN0dXJlKVxuICBsZXQgcmVzdWx0O1xuICBjb25zdCBpc1dpbmRvd3MgPSBwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInO1xuICBpZiAoaXNXaW5kb3dzKSB7XG4gICAgY29uc3QgcHNDb21wcmVzc2lvbkxldmVsID0gY29tcHJlc3Npb25MZXZlbCA9PT0gMCA/ICdOb0NvbXByZXNzaW9uJyA6ICdGYXN0ZXN0JztcbiAgICByZXN1bHQgPSBzcGF3bi5zeW5jKFxuICAgICAgJ3Bvd2Vyc2hlbGwuZXhlJyxcbiAgICAgIFtcbiAgICAgICAgJy1Ob0xvZ28nLFxuICAgICAgICAnLU5vUHJvZmlsZScsXG4gICAgICAgICctTm9uSW50ZXJhY3RpdmUnLFxuICAgICAgICAnLUNvbW1hbmQnLFxuICAgICAgICBgQ29tcHJlc3MtQXJjaGl2ZSAtUGF0aCAnJHtkaXJlY3Rvcnl9XFxcXConIC1EZXN0aW5hdGlvblBhdGggJyR7emlwRmlsZVBhdGh9JyAtQ29tcHJlc3Npb25MZXZlbCAke3BzQ29tcHJlc3Npb25MZXZlbH1gLFxuICAgICAgXSxcbiAgICAgIHsgc3RkaW86ICdpbmhlcml0JyB9XG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICByZXN1bHQgPSBzcGF3bi5zeW5jKFxuICAgICAgJ2Jhc2gnLCAvLyBnZXR0aW5nIEVOT0VOVCB3aGVuIHNwZWNpZnlpbmcgJ25vZGUnIGhlcmUgZm9yIHNvbWUgcmVhc29uXG4gICAgICBbXG4gICAgICAgIHF1aWV0ID8gJy1jJyA6ICcteGMnLFxuICAgICAgICBbYGNkICcke2RpcmVjdG9yeX0nYCwgYHppcCAtcnlxJHtjb21wcmVzc2lvbkxldmVsfSAnJHt6aXBGaWxlUGF0aH0nICR7ZmlsZUdsb2J9YF0uam9pbignJiYnKSxcbiAgICAgIF0sXG4gICAgICB7IHN0ZGlvOiAnaW5oZXJpdCcgfVxuICAgICk7XG4gIH1cbiAgaWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIHdhcyBhIHByb2JsZW0gZ2VuZXJhdGluZyB0aGUgcGFja2FnZSBmb3IgJHt6aXBGaWxlTmFtZX0gd2l0aCAke2RpcmVjdG9yeX06ICR7cmVzdWx0LmVycm9yfWApO1xuICB9XG4gIC8vIGNoZWNrIG91dHB1dFxuICBpZiAoIWZzLmV4aXN0c1N5bmMoemlwRmlsZVBhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFRoZXJlIHdhcyBhIHByb2JsZW0gZ2VuZXJhdGluZyB0aGUgYXJjaGl2ZSBmb3IgJHtkaXJlY3Rvcnl9OyB0aGUgYXJjaGl2ZSBpcyBtaXNzaW5nIGluICR7emlwRmlsZVBhdGh9LmBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHppcEZpbGVQYXRoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnVpbGRDbWRFbnZpcm9ubWVudChzaXRlRW52aXJvbm1lbnQ/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIC8vIEdlbmVyYXRlIGVudmlyb25tZW50IHBsYWNlaG9sZGVycyB0byBiZSByZXBsYWNlZFxuICAvLyBpZS4gZW52aXJvbm1lbnQgPT4geyBBUElfVVJMOiBhcGkudXJsIH1cbiAgLy8gICAgIGVudmlyb25tZW50ID0+IEFQSV9VUkw9XCJ7TkVYVHshIEFQSV9VUkwgIX19XCJcbiAgLy9cbiAgY29uc3QgYnVpbGRDbWRFbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBPYmplY3QuZW50cmllcyhzaXRlRW52aXJvbm1lbnQgfHwge30pLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgIGJ1aWxkQ21kRW52aXJvbm1lbnRba2V5XSA9IFRva2VuLmlzVW5yZXNvbHZlZCh2YWx1ZSkgPyBtYWtlVG9rZW5QbGFjZWhvbGRlcihrZXkpIDogdmFsdWU7XG4gIH0pO1xuXG4gIHJldHVybiBidWlsZENtZEVudmlyb25tZW50O1xufVxuXG5leHBvcnQgY29uc3QgVE9LRU5fUExBQ0VIT0xERVJfQkVHSU4gPSAne05FWFR7ISAnO1xuZXhwb3J0IGNvbnN0IFRPS0VOX1BMQUNFSE9MREVSX0VORCA9ICcgIX19JztcbmV4cG9ydCBjb25zdCBtYWtlVG9rZW5QbGFjZWhvbGRlciA9ICh2YWx1ZTogc3RyaW5nKTogc3RyaW5nID0+XG4gIFRPS0VOX1BMQUNFSE9MREVSX0JFR0lOICsgdmFsdWUudG9TdHJpbmcoKSArIFRPS0VOX1BMQUNFSE9MREVSX0VORDtcbiJdfQ==