open-next-cdk
Version:
Deploy a NextJS app using OpenNext packaging to serverless AWS using CDK
179 lines • 27.3 kB
JavaScript
;
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==