open-next-cdk
Version:
Deploy a NextJS app using OpenNext packaging to serverless AWS using CDK
123 lines • 17.4 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getS3ReplaceValues = exports.NextjsS3EnvRewriter = exports.replaceTokenGlobs = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const fs = require("fs");
const os = require("os");
const path = require("path");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const iam = require("aws-cdk-lib/aws-iam");
const lambda = require("aws-cdk-lib/aws-lambda");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
const cr = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const BundleFunction_1 = require("./BundleFunction");
const NextjsBuild_1 = require("./NextjsBuild");
// files to rewrite CloudFormation tokens in environment variables
exports.replaceTokenGlobs = ['**/*.html', '**/*.js', '**/*.cjs', '**/*.mjs', '**/*.json'];
/**
* Rewrites variables in S3 objects after a deployment happens to
* replace CloudFormation tokens with their values.
* These values are not resolved at build time because they are
* only known at deploy time.
*/
class NextjsS3EnvRewriter extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
const { s3Bucket, s3keys, replacementConfig, debug, cloudfrontDistributionId } = props;
if (s3keys.length === 0)
return;
const app = aws_cdk_lib_1.App.of(this);
const tmpDir = props.tempBuildDir
? path.resolve(path.join(props.tempBuildDir, 'static'))
: fs.mkdtempSync(path.join(os.tmpdir(), 'static-'));
// create a custom resource to find and replace tokenized strings in static files
// must happen after deployment when tokens can be resolved
// compile function
const inputPath = path.resolve(__dirname, '../assets/lambda/S3EnvRewriter.ts');
const outputPath = path.join(tmpDir, 'deployment-scripts', 'S3EnvRewriter.cjs');
const handlerDir = BundleFunction_1.bundleFunction({
inputPath,
outputPath,
bundleOptions: {
bundle: true,
sourcemap: true,
external: ['aws-sdk'],
target: 'node16',
platform: 'node',
format: 'cjs',
},
});
// rewriter lambda function
const rewriteFn = new lambda.Function(this, 'RewriteOnEventHandler', {
runtime: aws_lambda_1.Runtime.NODEJS_16_X,
memorySize: 1024,
timeout: aws_cdk_lib_1.Duration.minutes(5),
handler: 'S3EnvRewriter.handler',
code: lambda.Code.fromAsset(handlerDir),
initialPolicy: [
new iam.PolicyStatement({
actions: ['s3:GetObject', 's3:PutObject'],
resources: [s3Bucket.arnForObjects('*')],
}),
...(cloudfrontDistributionId
? [
new iam.PolicyStatement({
actions: ['cloudfront:CreateInvalidation'],
resources: [`arn:aws:cloudfront::${app.account}:distribution/${cloudfrontDistributionId}`],
}),
]
: []),
],
});
// grant permission to read env var config if provided
if (replacementConfig.jsonS3Bucket && replacementConfig.jsonS3Key) {
const bucket = typeof replacementConfig.jsonS3Bucket === 'string'
? aws_s3_1.Bucket.fromBucketName(this, 'EnvConfigBucket', replacementConfig.jsonS3Bucket)
: replacementConfig.jsonS3Bucket;
rewriteFn.addToRolePolicy(new iam.PolicyStatement({
actions: ['s3:GetObject'],
resources: [bucket.arnForObjects(replacementConfig.jsonS3Key)],
}));
}
// custom resource to run the rewriter after files are copied and we can resolve token values
const provider = new cr.Provider(this, 'RewriteStaticProvider', {
onEventHandler: rewriteFn,
});
// params for the rewriter function
const properties = {
bucket: s3Bucket.bucketName,
s3keys,
replacementConfig: {
...replacementConfig,
jsonS3Bucket: replacementConfig.jsonS3Bucket?.bucketName,
},
debug,
cloudfrontDistributionId,
};
this.rewriteNode = new aws_cdk_lib_1.CustomResource(this, 'RewriteStatic', {
serviceToken: provider.serviceToken,
properties,
});
}
}
exports.NextjsS3EnvRewriter = NextjsS3EnvRewriter;
_a = JSII_RTTI_SYMBOL_1;
NextjsS3EnvRewriter[_a] = { fqn: "open-next-cdk.NextjsS3EnvRewriter", version: "0.0.10" };
// inline env vars for client and server code
// these are values to replace in built code after it's deployed to S3/lambda
function getS3ReplaceValues(environment, publicOnly) {
const replacements = {};
Object.entries(environment || {})
.filter(([, value]) => aws_cdk_lib_1.Token.isUnresolved(value))
.filter(([key]) => !publicOnly || key.startsWith('NEXT_PUBLIC_')) // don't replace server-only env vars
.forEach(([key, value]) => {
const token = NextjsBuild_1.makeTokenPlaceholder(key);
replacements[token] = value.toString();
});
return replacements;
}
exports.getS3ReplaceValues = getS3ReplaceValues;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTmV4dGpzUzNFbnZSZXdyaXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9OZXh0anNTM0VudlJld3JpdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsNkNBQW1FO0FBQ25FLDJDQUEyQztBQUMzQyxpREFBaUQ7QUFDakQsdURBQWlEO0FBQ2pELCtDQUFxRDtBQUNyRCxtREFBbUQ7QUFDbkQsMkNBQXVDO0FBQ3ZDLHFEQUFrRDtBQUVsRCwrQ0FBcUQ7QUFFckQsa0VBQWtFO0FBQ3JELFFBQUEsaUJBQWlCLEdBQUcsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFpQi9GOzs7OztHQUtHO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxzQkFBUztJQUdoRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQStCO1FBQ3ZFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsS0FBSyxFQUFFLHdCQUF3QixFQUFFLEdBQUcsS0FBSyxDQUFDO1FBRXZGLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTztRQUVoQyxNQUFNLEdBQUcsR0FBRyxpQkFBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQVEsQ0FBQztRQUVoQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsWUFBWTtZQUMvQixDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDdkQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVB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Q0wsd0JBQXdCO1NBQ3pCLENBQUM7UUFDRixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksNEJBQWMsQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQzNELFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWTtZQUNuQyxVQUFVO1NBQ1gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF6Rkgsa0RBMEZDOzs7QUFFRCw2Q0FBNkM7QUFDN0MsNkVBQTZFO0FBQzdFLFNBQWdCLGtCQUFrQixDQUFDLFdBQW1DLEVBQUUsVUFBbUI7SUFDekYsTUFBTSxZQUFZLEdBQTJCLEVBQUUsQ0FBQztJQUVoRCxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7U0FDOUIsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxtQkFBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNoRCxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLFVBQVUsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMscUNBQXFDO1NBQ3RHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUU7UUFDeEIsTUFBTSxLQUFLLEdBQUcsa0NBQW9CLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN6QyxDQUFDLENBQUMsQ0FBQztJQUVMLE9BQU8sWUFBWSxDQUFDO0FBQ3RCLENBQUM7QUFaRCxnREFZQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBBcHAsIEN1c3RvbVJlc291cmNlLCBEdXJhdGlvbiwgVG9rZW4gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBSdW50aW1lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBCdWNrZXQsIElCdWNrZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGJ1bmRsZUZ1bmN0aW9uIH0gZnJvbSAnLi9CdW5kbGVGdW5jdGlvbic7XG5pbXBvcnQgeyBOZXh0anNCYXNlUHJvcHMgfSBmcm9tICcuL05leHRqc0Jhc2UnO1xuaW1wb3J0IHsgbWFrZVRva2VuUGxhY2Vob2xkZXIgfSBmcm9tICcuL05leHRqc0J1aWxkJztcblxuLy8gZmlsZXMgdG8gcmV3cml0ZSBDbG91ZEZvcm1hdGlvbiB0b2tlbnMgaW4gZW52aXJvbm1lbnQgdmFyaWFibGVzXG5leHBvcnQgY29uc3QgcmVwbGFjZVRva2VuR2xvYnMgPSBbJyoqLyouaHRtbCcsICcqKi8qLmpzJywgJyoqLyouY2pzJywgJyoqLyoubWpzJywgJyoqLyouanNvbiddO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJld3JpdGVSZXBsYWNlbWVudHNDb25maWcge1xuICByZWFkb25seSBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+OyAvLyByZXBsYWNlIGtleXMgd2l0aCB2YWx1ZXMgaW4gZmlsZXNcbiAgcmVhZG9ubHkganNvblMzQnVja2V0PzogSUJ1Y2tldDtcbiAgcmVhZG9ubHkganNvblMzS2V5Pzogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBSZXdyaXRlclBhcmFtcyB7XG4gIHJlYWRvbmx5IHMzQnVja2V0OiBJQnVja2V0O1xuICByZWFkb25seSBzM2tleXM6IHN0cmluZ1tdOyAvLyBmaWxlcyB0byByZXdyaXRlXG4gIHJlYWRvbmx5IHJlcGxhY2VtZW50Q29uZmlnOiBSZXdyaXRlUmVwbGFjZW1lbnRzQ29uZmlnO1xuICByZWFkb25seSBkZWJ1Zz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNsb3VkZnJvbnREaXN0cmlidXRpb25JZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOZXh0anNTM0VudlJld3JpdGVyUHJvcHMgZXh0ZW5kcyBOZXh0anNCYXNlUHJvcHMsIFJld3JpdGVyUGFyYW1zIHt9XG5cbi8qKlxuICogUmV3cml0ZXMgdmFyaWFibGVzIGluIFMzIG9iamVjdHMgYWZ0ZXIgYSBkZXBsb3ltZW50IGhhcHBlbnMgdG9cbiAqIHJlcGxhY2UgQ2xvdWRGb3JtYXRpb24gdG9rZW5zIHdpdGggdGhlaXIgdmFsdWVzLlxuICogVGhlc2UgdmFsdWVzIGFyZSBub3QgcmVzb2x2ZWQgYXQgYnVpbGQgdGltZSBiZWNhdXNlIHRoZXkgYXJlXG4gKiBvbmx5IGtub3duIGF0IGRlcGxveSB0aW1lLlxuICovXG5leHBvcnQgY2xhc3MgTmV4dGpzUzNFbnZSZXdyaXRlciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZXdyaXRlTm9kZT86IENvbnN0cnVjdDtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTmV4dGpzUzNFbnZSZXdyaXRlclByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IHsgczNCdWNrZXQsIHMza2V5cywgcmVwbGFjZW1lbnRDb25maWcsIGRlYnVnLCBjbG91ZGZyb250RGlzdHJpYnV0aW9uSWQgfSA9IHByb3BzO1xuXG4gICAgaWYgKHMza2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIGNvbnN0IGFwcCA9IEFwcC5vZih0aGlzKSBhcyBBcHA7XG5cbiAgICBjb25zdCB0bXBEaXIgPSBwcm9wcy50ZW1wQnVpbGREaXJcbiAgICAgID8gcGF0aC5yZXNvbHZlKHBhdGguam9pbihwcm9wcy50ZW1wQnVpbGREaXIsICdzdGF0aWMnKSlcbiAgICAgIDogZnMubWtkdGVtcFN5bmMocGF0aC5qb2luKG9zLnRtcGRpcigpLCAnc3RhdGljLScpKTtcblxuICAgIC8vIGNyZWF0ZSBhIGN1c3RvbSByZXNvdXJjZSB0byBmaW5kIGFuZCByZXBsYWNlIHRva2VuaXplZCBzdHJpbmdzIGluIHN0YXRpYyBmaWxlc1xuICAgIC8vIG11c3QgaGFwcGVuIGFmdGVyIGRlcGxveW1lbnQgd2hlbiB0b2tlbnMgY2FuIGJlIHJlc29sdmVkXG4gICAgLy8gY29tcGlsZSBmdW5jdGlvblxuICAgIGNvbnN0IGlucHV0UGF0aCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9hc3NldHMvbGFtYmRhL1MzRW52UmV3cml0ZXIudHMnKTtcbiAgICBjb25zdCBvdXRwdXRQYXRoID0gcGF0aC5qb2luKHRtcERpciwgJ2RlcGxveW1lbnQtc2NyaXB0cycsICdTM0VudlJld3JpdGVyLmNqcycpO1xuICAgIGNvbnN0IGhhbmRsZXJEaXIgPSBidW5kbGVGdW5jdGlvbih7XG4gICAgICBpbnB1dFBhdGgsXG4gICAgICBvdXRwdXRQYXRoLFxuICAgICAgYnVuZGxlT3B0aW9uczoge1xuICAgICAgICBidW5kbGU6IHRydWUsXG4gICAgICAgIHNvdXJjZW1hcDogdHJ1ZSxcbiAgICAgICAgZXh0ZXJuYWw6IFsnYXdzLXNkayddLFxuICAgICAgICB0YXJnZXQ6ICdub2RlMTYnLFxuICAgICAgICBwbGF0Zm9ybTogJ25vZGUnLFxuICAgICAgICBmb3JtYXQ6ICdjanMnLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIHJld3JpdGVyIGxhbWJkYSBmdW5jdGlvblxuICAgIGNvbnN0IHJld3JpdGVGbiA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgJ1Jld3JpdGVPbkV2ZW50SGFuZGxlcicsIHtcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzE2X1gsXG4gICAgICBtZW1vcnlTaXplOiAxMDI0LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGhhbmRsZXI6ICdTM0VudlJld3JpdGVyLmhhbmRsZXInLFxuICAgICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGhhbmRsZXJEaXIpLFxuICAgICAgaW5pdGlhbFBvbGljeTogW1xuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogWydzMzpHZXRPYmplY3QnLCAnczM6UHV0T2JqZWN0J10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbczNCdWNrZXQuYXJuRm9yT2JqZWN0cygnKicpXSxcbiAgICAgICAgfSksXG4gICAgICAgIC4uLihjbG91ZGZyb250RGlzdHJpYnV0aW9uSWRcbiAgICAgICAgICA/IFtcbiAgICAgICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgICAgIGFjdGlvbnM6IFsnY2xvdWRmcm9udDpDcmVhdGVJbnZhbGlkYXRpb24nXSxcbiAgICAgICAgICAgICAgICByZXNvdXJjZXM6IFtgYXJuOmF3czpjbG91ZGZyb250Ojoke2FwcC5hY2NvdW50fTpkaXN0cmlidXRpb24vJHtjbG91ZGZyb250RGlzdHJpYnV0aW9uSWR9YF0sXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXVxuICAgICAgICAgIDogW10pLFxuICAgICAgXSxcbiAgICB9KTtcbiAgICAvLyBncmFudCBwZXJtaXNzaW9uIHRvIHJlYWQgZW52IHZhciBjb25maWcgaWYgcHJvdmlkZWRcbiAgICBpZiAocmVwbGFjZW1lbnRDb25maWcuanNvblMzQnVja2V0ICYmIHJlcGxhY2VtZW50Q29uZmlnLmpzb25TM0tleSkge1xuICAgICAgY29uc3QgYnVja2V0OiBJQnVja2V0ID1cbiAgICAgICAgdHlwZW9mIHJlcGxhY2VtZW50Q29uZmlnLmpzb25TM0J1Y2tldCA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IEJ1Y2tldC5mcm9tQnVja2V0TmFtZSh0aGlzLCAnRW52Q29uZmlnQnVja2V0JywgcmVwbGFjZW1lbnRDb25maWcuanNvblMzQnVja2V0KVxuICAgICAgICAgIDogcmVwbGFjZW1lbnRDb25maWcuanNvblMzQnVja2V0O1xuICAgICAgcmV3cml0ZUZuLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnczM6R2V0T2JqZWN0J10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbYnVja2V0LmFybkZvck9iamVjdHMocmVwbGFjZW1lbnRDb25maWcuanNvblMzS2V5KV0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGN1c3RvbSByZXNvdXJjZSB0byBydW4gdGhlIHJld3JpdGVyIGFmdGVyIGZpbGVzIGFyZSBjb3BpZWQgYW5kIHdlIGNhbiByZXNvbHZlIHRva2VuIHZhbHVlc1xuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IGNyLlByb3ZpZGVyKHRoaXMsICdSZXdyaXRlU3RhdGljUHJvdmlkZXInLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogcmV3cml0ZUZuLFxuICAgIH0pO1xuICAgIC8vIHBhcmFtcyBmb3IgdGhlIHJld3JpdGVyIGZ1bmN0aW9uXG4gICAgY29uc3QgcHJvcGVydGllcyA9IHtcbiAgICAgIGJ1Y2tldDogczNCdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgIHMza2V5cyxcbiAgICAgIHJlcGxhY2VtZW50Q29uZmlnOiB7XG4gICAgICAgIC4uLnJlcGxhY2VtZW50Q29uZmlnLFxuICAgICAgICBqc29uUzNCdWNrZXQ6IHJlcGxhY2VtZW50Q29uZmlnLmpzb25TM0J1Y2tldD8uYnVja2V0TmFtZSxcbiAgICAgIH0sXG4gICAgICBkZWJ1ZyxcbiAgICAgIGNsb3VkZnJvbnREaXN0cmlidXRpb25JZCxcbiAgICB9O1xuICAgIHRoaXMucmV3cml0ZU5vZGUgPSBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1Jld3JpdGVTdGF0aWMnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHByb3BlcnRpZXMsXG4gICAgfSk7XG4gIH1cbn1cblxuLy8gaW5saW5lIGVudiB2YXJzIGZvciBjbGllbnQgYW5kIHNlcnZlciBjb2RlXG4vLyB0aGVzZSBhcmUgdmFsdWVzIHRvIHJlcGxhY2UgaW4gYnVpbHQgY29kZSBhZnRlciBpdCdzIGRlcGxveWVkIHRvIFMzL2xhbWJkYVxuZXhwb3J0IGZ1bmN0aW9uIGdldFMzUmVwbGFjZVZhbHVlcyhlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgcHVibGljT25seTogYm9vbGVhbik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCByZXBsYWNlbWVudHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBPYmplY3QuZW50cmllcyhlbnZpcm9ubWVudCB8fCB7fSlcbiAgICAuZmlsdGVyKChbLCB2YWx1ZV0pID0+IFRva2VuLmlzVW5yZXNvbHZlZCh2YWx1ZSkpXG4gICAgLmZpbHRlcigoW2tleV0pID0+ICFwdWJsaWNPbmx5IHx8IGtleS5zdGFydHNXaXRoKCdORVhUX1BVQkxJQ18nKSkgLy8gZG9uJ3QgcmVwbGFjZSBzZXJ2ZXItb25seSBlbnYgdmFyc1xuICAgIC5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGNvbnN0IHRva2VuID0gbWFrZVRva2VuUGxhY2Vob2xkZXIoa2V5KTtcbiAgICAgIHJlcGxhY2VtZW50c1t0b2tlbl0gPSB2YWx1ZS50b1N0cmluZygpO1xuICAgIH0pO1xuXG4gIHJldHVybiByZXBsYWNlbWVudHM7XG59XG4iXX0=