UNPKG

cdk-nextjs-standalone

Version:

Deploy a NextJS app to AWS using CDK and OpenNext.

146 lines 18.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = void 0; exports.signRequest = signRequest; exports.getRegionFromLambdaUrl = getRegionFromLambdaUrl; exports.cfHeadersToHeaderBag = cfHeadersToHeaderBag; exports.headerBagToCfHeaders = headerBagToCfHeaders; exports.queryStringToQueryParamBag = queryStringToQueryParamBag; /* eslint-disable import/no-extraneous-dependencies */ const sha256_js_1 = require("@aws-crypto/sha256-js"); const signature_v4_1 = require("@smithy/signature-v4"); const debug = false; /** * This Lambda@Edge handler fixes s3 requests, fixes the host header, and * signs requests as they're destined for Lambda Function URL that requires * IAM Auth. */ const handler = async (event) => { const request = event.Records[0].cf.request; if (debug) console.log('input request', JSON.stringify(request, null, 2)); escapeQuerystring(request); await signRequest(request); if (debug) console.log('output request', JSON.stringify(request), null, 2); return request; }; exports.handler = handler; /** * Lambda URL will reject query parameters with brackets so we need to encode * https://github.dev/pwrdrvr/lambda-url-signing/blob/main/packages/edge-to-origin/src/translate-request.ts#L19-L31 */ function escapeQuerystring(request) { request.querystring = request.querystring.replace(/\[/g, '%5B').replace(/]/g, '%5D'); } let sigv4; /** * When `NextjsDistributionProps.functionUrlAuthType` is set to * `lambda.FunctionUrlAuthType.AWS_IAM` we need to sign the `CloudFrontRequest`s * with AWS IAM SigV4 so that CloudFront can invoke the Nextjs server and image * optimization functions via function URLs. When configured, this lambda@edge * function has the permission, lambda:InvokeFunctionUrl, to invoke both * functions. * @link https://medium.com/@dario_26152/restrict-access-to-lambda-functionurl-to-cloudfront-using-aws-iam-988583834705 */ async function signRequest(request) { if (!sigv4) { const region = getRegionFromLambdaUrl(request.origin?.custom?.domainName || ''); sigv4 = getSigV4(region); } // remove x-forwarded-for b/c it changes from hop to hop delete request.headers['x-forwarded-for']; const headerBag = cfHeadersToHeaderBag(request.headers); let body; if (request.body?.data) { body = Buffer.from(request.body.data, 'base64').toString(); } const params = queryStringToQueryParamBag(request.querystring); const signed = await sigv4.sign({ method: request.method, headers: headerBag, hostname: headerBag.host, path: request.uri, body, query: params, protocol: 'https', }); request.headers = headerBagToCfHeaders(signed.headers); } function getSigV4(region) { const accessKeyId = process.env.AWS_ACCESS_KEY_ID; const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; const sessionToken = process.env.AWS_SESSION_TOKEN; if (!region) throw new Error('AWS_REGION missing'); if (!accessKeyId) throw new Error('AWS_ACCESS_KEY_ID missing'); if (!secretAccessKey) throw new Error('AWS_SECRET_ACCESS_KEY missing'); if (!sessionToken) throw new Error('AWS_SESSION_TOKEN missing'); return new signature_v4_1.SignatureV4({ service: 'lambda', region, credentials: { accessKeyId, secretAccessKey, sessionToken, }, sha256: sha256_js_1.Sha256, }); } function getRegionFromLambdaUrl(url) { const region = url.split('.').at(2); if (!region) throw new Error("Region couldn't be extracted from Lambda Function URL"); return region; } /** * Converts CloudFront headers (can have array of header values) to simple * header bag (object) required by `sigv4.sign` * * NOTE: only includes headers allowed by origin policy to prevent signature * mismatch */ function cfHeadersToHeaderBag(headers) { let headerBag = {}; // assume first header value is the best match // headerKey is case insensitive whereas key (adjacent property value that is // not destructured) is case sensitive. we arbitrarily use case insensitive key for (const [headerKey, [{ value }]] of Object.entries(headers)) { headerBag[headerKey] = value; // if there is an authorization from CloudFront, move it as // it will be overwritten when the headers are signed if (headerKey === 'authorization') { headerBag['origin-authorization'] = value; } } return headerBag; } /** * Converts simple header bag (object) to CloudFront headers */ function headerBagToCfHeaders(headerBag) { const cfHeaders = {}; for (const [headerKey, value] of Object.entries(headerBag)) { /* When your Lambda function adds or modifies request headers and you don't include the header key field, Lambda@Edge automatically inserts a header key using the header name that you provide. Regardless of how you've formatted the header name, the header key that's inserted automatically is formatted with initial capitalization for each part, separated by hyphens (-). See: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html */ cfHeaders[headerKey] = [{ value }]; } return cfHeaders; } /** * Converts CloudFront querystring to QueryParamaterBag for IAM Sig V4 */ function queryStringToQueryParamBag(querystring) { const oldParams = new URLSearchParams(querystring); const newParams = {}; for (const [k, v] of oldParams) { newParams[k] = v; } return newParams; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi1mbi11cmwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGFtYmRhcy9zaWduLWZuLXVybC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUEwQ0Esa0NBdUJDO0FBc0JELHdEQUlDO0FBYUQsb0RBY0M7QUFLRCxvREFVQztBQUtELGdFQU9DO0FBakpELHNEQUFzRDtBQUN0RCxxREFBK0M7QUFDL0MsdURBQW1EO0FBR25ELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQztBQUVwQjs7OztHQUlHO0FBQ0ksTUFBTSxPQUFPLEdBQTZCLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRTtJQUMvRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUM7SUFDNUMsSUFBSSxLQUFLO1FBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFMUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0IsTUFBTSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFM0IsSUFBSSxLQUFLO1FBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRSxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDLENBQUM7QUFUVyxRQUFBLE9BQU8sV0FTbEI7QUFFRjs7O0dBR0c7QUFDSCxTQUFTLGlCQUFpQixDQUFDLE9BQTBCO0lBQ25ELE9BQU8sQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFD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cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IFNoYTI1NiB9IGZyb20gJ0Bhd3MtY3J5cHRvL3NoYTI1Ni1qcyc7XG5pbXBvcnQgeyBTaWduYXR1cmVWNCB9IGZyb20gJ0BzbWl0aHkvc2lnbmF0dXJlLXY0JztcbmltcG9ydCB0eXBlIHsgQ2xvdWRGcm9udEhlYWRlcnMsIENsb3VkRnJvbnRSZXF1ZXN0LCBDbG91ZEZyb250UmVxdWVzdEhhbmRsZXIgfSBmcm9tICdhd3MtbGFtYmRhJztcblxuY29uc3QgZGVidWcgPSBmYWxzZTtcblxuLyoqXG4gKiBUaGlzIExhbWJkYUBFZGdlIGhhbmRsZXIgZml4ZXMgczMgcmVxdWVzdHMsIGZpeGVzIHRoZSBob3N0IGhlYWRlciwgYW5kXG4gKiBzaWducyByZXF1ZXN0cyBhcyB0aGV5J3JlIGRlc3RpbmVkIGZvciBMYW1iZGEgRnVuY3Rpb24gVVJMIHRoYXQgcmVxdWlyZXNcbiAqIElBTSBBdXRoLlxuICovXG5leHBvcnQgY29uc3QgaGFuZGxlcjogQ2xvdWRGcm9udFJlcXVlc3RIYW5kbGVyID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gIGNvbnN0IHJlcXVlc3QgPSBldmVudC5SZWNvcmRzWzBdLmNmLnJlcXVlc3Q7XG4gIGlmIChkZWJ1ZykgY29uc29sZS5sb2coJ2lucHV0IHJlcXVlc3QnLCBKU09OLnN0cmluZ2lmeShyZXF1ZXN0LCBudWxsLCAyKSk7XG5cbiAgZXNjYXBlUXVlcnlzdHJpbmcocmVxdWVzdCk7XG4gIGF3YWl0IHNpZ25SZXF1ZXN0KHJlcXVlc3QpO1xuXG4gIGlmIChkZWJ1ZykgY29uc29sZS5sb2coJ291dHB1dCByZXF1ZXN0JywgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCksIG51bGwsIDIpO1xuICByZXR1cm4gcmVxdWVzdDtcbn07XG5cbi8qKlxuICogTGFtYmRhIFVSTCB3aWxsIHJlamVjdCBxdWVyeSBwYXJhbWV0ZXJzIHdpdGggYnJhY2tldHMgc28gd2UgbmVlZCB0byBlbmNvZGVcbiAqIGh0dHBzOi8vZ2l0aHViLmRldi9wd3JkcnZyL2xhbWJkYS11cmwtc2lnbmluZy9ibG9iL21haW4vcGFja2FnZXMvZWRnZS10by1vcmlnaW4vc3JjL3RyYW5zbGF0ZS1yZXF1ZXN0LnRzI0wxOS1MMzFcbiAqL1xuZnVuY3Rpb24gZXNjYXBlUXVlcnlzdHJpbmcocmVxdWVzdDogQ2xvdWRGcm9udFJlcXVlc3QpIHtcbiAgcmVxdWVzdC5xdWVyeXN0cmluZyA9IHJlcXVlc3QucXVlcnlzdHJpbmcucmVwbGFjZSgvXFxbL2csICclNUInKS5yZXBsYWNlKC9dL2csICclNUQnKTtcbn1cblxubGV0IHNpZ3Y0OiBTaWduYXR1cmVWNDtcblxuLyoqXG4gKiBXaGVuIGBOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5mdW5jdGlvblVybEF1dGhUeXBlYCBpcyBzZXQgdG9cbiAqIGBsYW1iZGEuRnVuY3Rpb25VcmxBdXRoVHlwZS5BV1NfSUFNYCB3ZSBuZWVkIHRvIHNpZ24gdGhlIGBDbG91ZEZyb250UmVxdWVzdGBzXG4gKiB3aXRoIEFXUyBJQU0gU2lnVjQgc28gdGhhdCBDbG91ZEZyb250IGNhbiBpbnZva2UgdGhlIE5leHRqcyBzZXJ2ZXIgYW5kIGltYWdlXG4gKiBvcHRpbWl6YXRpb24gZnVuY3Rpb25zIHZpYSBmdW5jdGlvbiBVUkxzLiBXaGVuIGNvbmZpZ3VyZWQsIHRoaXMgbGFtYmRhQGVkZ2VcbiAqIGZ1bmN0aW9uIGhhcyB0aGUgcGVybWlzc2lvbiwgbGFtYmRhOkludm9rZUZ1bmN0aW9uVXJsLCB0byBpbnZva2UgYm90aFxuICogZnVuY3Rpb25zLlxuICogQGxpbmsgaHR0cHM6Ly9tZWRpdW0uY29tL0BkYXJpb18yNjE1Mi9yZXN0cmljdC1hY2Nlc3MtdG8tbGFtYmRhLWZ1bmN0aW9udXJsLXRvLWNsb3VkZnJvbnQtdXNpbmctYXdzLWlhbS05ODg1ODM4MzQ3MDVcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25SZXF1ZXN0KHJlcXVlc3Q6IENsb3VkRnJvbnRSZXF1ZXN0KSB7XG4gIGlmICghc2lndjQpIHtcbiAgICBjb25zdCByZWdpb24gPSBnZXRSZWdpb25Gcm9tTGFtYmRhVXJsKHJlcXVlc3Qub3JpZ2luPy5jdXN0b20/LmRvbWFpbk5hbWUgfHwgJycpO1xuICAgIHNpZ3Y0ID0gZ2V0U2lnVjQocmVnaW9uKTtcbiAgfVxuICAvLyByZW1vdmUgeC1mb3J3YXJkZWQtZm9yIGIvYyBpdCBjaGFuZ2VzIGZyb20gaG9wIHRvIGhvcFxuICBkZWxldGUgcmVxdWVzdC5oZWFkZXJzWyd4LWZvcndhcmRlZC1mb3InXTtcbiAgY29uc3QgaGVhZGVyQmFnID0gY2ZIZWFkZXJzVG9IZWFkZXJCYWcocmVxdWVzdC5oZWFkZXJzKTtcbiAgbGV0IGJvZHk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgaWYgKHJlcXVlc3QuYm9keT8uZGF0YSkge1xuICAgIGJvZHkgPSBCdWZmZXIuZnJvbShyZXF1ZXN0LmJvZHkuZGF0YSwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCk7XG4gIH1cbiAgY29uc3QgcGFyYW1zID0gcXVlcnlTdHJpbmdUb1F1ZXJ5UGFyYW1CYWcocmVxdWVzdC5xdWVyeXN0cmluZyk7XG4gIGNvbnN0IHNpZ25lZCA9IGF3YWl0IHNpZ3Y0LnNpZ24oe1xuICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgaGVhZGVyczogaGVhZGVyQmFnLFxuICAgIGhvc3RuYW1lOiBoZWFkZXJCYWcuaG9zdCxcbiAgICBwYXRoOiByZXF1ZXN0LnVyaSxcbiAgICBib2R5LFxuICAgIHF1ZXJ5OiBwYXJhbXMsXG4gICAgcHJvdG9jb2w6ICdodHRwcycsXG4gIH0pO1xuICByZXF1ZXN0LmhlYWRlcnMgPSBoZWFkZXJCYWdUb0NmSGVhZGVycyhzaWduZWQuaGVhZGVycyk7XG59XG5cbmZ1bmN0aW9uIGdldFNpZ1Y0KHJlZ2lvbjogc3RyaW5nKTogU2lnbmF0dXJlVjQge1xuICBjb25zdCBhY2Nlc3NLZXlJZCA9IHByb2Nlc3MuZW52LkFXU19BQ0NFU1NfS0VZX0lEO1xuICBjb25zdCBzZWNyZXRBY2Nlc3NLZXkgPSBwcm9jZXNzLmVudi5BV1NfU0VDUkVUX0FDQ0VTU19LRVk7XG4gIGNvbnN0IHNlc3Npb25Ub2tlbiA9IHByb2Nlc3MuZW52LkFXU19TRVNTSU9OX1RPS0VOO1xuICBpZiAoIXJlZ2lvbikgdGhyb3cgbmV3IEVycm9yKCdBV1NfUkVHSU9OIG1pc3NpbmcnKTtcbiAgaWYgKCFhY2Nlc3NLZXlJZCkgdGhyb3cgbmV3IEVycm9yKCdBV1NfQUNDRVNTX0tFWV9JRCBtaXNzaW5nJyk7XG4gIGlmICghc2VjcmV0QWNjZXNzS2V5KSB0aHJvdyBuZXcgRXJyb3IoJ0FXU19TRUNSRVRfQUNDRVNTX0tFWSBtaXNzaW5nJyk7XG4gIGlmICghc2Vzc2lvblRva2VuKSB0aHJvdyBuZXcgRXJyb3IoJ0FXU19TRVNTSU9OX1RPS0VOIG1pc3NpbmcnKTtcbiAgcmV0dXJuIG5ldyBTaWduYXR1cmVWNCh7XG4gICAgc2VydmljZTogJ2xhbWJkYScsXG4gICAgcmVnaW9uLFxuICAgIGNyZWRlbnRpYWxzOiB7XG4gICAgICBhY2Nlc3NLZXlJZCxcbiAgICAgIHNlY3JldEFjY2Vzc0tleSxcbiAgICAgIHNlc3Npb25Ub2tlbixcbiAgICB9LFxuICAgIHNoYTI1NjogU2hhMjU2LFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlZ2lvbkZyb21MYW1iZGFVcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCByZWdpb24gPSB1cmwuc3BsaXQoJy4nKS5hdCgyKTtcbiAgaWYgKCFyZWdpb24pIHRocm93IG5ldyBFcnJvcihcIlJlZ2lvbiBjb3VsZG4ndCBiZSBleHRyYWN0ZWQgZnJvbSBMYW1iZGEgRnVuY3Rpb24gVVJMXCIpO1xuICByZXR1cm4gcmVnaW9uO1xufVxuXG4vKipcbiAqIEJhZyBvciBNYXAgdXNlZCBmb3IgSGVhZGVyQmFnIG9yIFF1ZXJ5U3RyaW5nUGFyYW1ldGVyQmFnIGZvciBgc2lndjQuc2lnbigpYFxuICovXG50eXBlIEJhZyA9IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4vKipcbiAqIENvbnZlcnRzIENsb3VkRnJvbnQgaGVhZGVycyAoY2FuIGhhdmUgYXJyYXkgb2YgaGVhZGVyIHZhbHVlcykgdG8gc2ltcGxlXG4gKiBoZWFkZXIgYmFnIChvYmplY3QpIHJlcXVpcmVkIGJ5IGBzaWd2NC5zaWduYFxuICpcbiAqIE5PVEU6IG9ubHkgaW5jbHVkZXMgaGVhZGVycyBhbGxvd2VkIGJ5IG9yaWdpbiBwb2xpY3kgdG8gcHJldmVudCBzaWduYXR1cmVcbiAqIG1pc21hdGNoXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjZkhlYWRlcnNUb0hlYWRlckJhZyhoZWFkZXJzOiBDbG91ZEZyb250SGVhZGVycyk6IEJhZyB7XG4gIGxldCBoZWFkZXJCYWc6IEJhZyA9IHt9O1xuICAvLyBhc3N1bWUgZmlyc3QgaGVhZGVyIHZhbHVlIGlzIHRoZSBiZXN0IG1hdGNoXG4gIC8vIGhlYWRlcktleSBpcyBjYXNlIGluc2Vuc2l0aXZlIHdoZXJlYXMga2V5IChhZGphY2VudCBwcm9wZXJ0eSB2YWx1ZSB0aGF0IGlzXG4gIC8vIG5vdCBkZXN0cnVjdHVyZWQpIGlzIGNhc2Ugc2Vuc2l0aXZlLiB3ZSBhcmJpdHJhcmlseSB1c2UgY2FzZSBpbnNlbnNpdGl2ZSBrZXlcbiAgZm9yIChjb25zdCBbaGVhZGVyS2V5LCBbeyB2YWx1ZSB9XV0gb2YgT2JqZWN0LmVudHJpZXMoaGVhZGVycykpIHtcbiAgICBoZWFkZXJCYWdbaGVhZGVyS2V5XSA9IHZhbHVlO1xuICAgIC8vIGlmIHRoZXJlIGlzIGFuIGF1dGhvcml6YXRpb24gZnJvbSBDbG91ZEZyb250LCBtb3ZlIGl0IGFzXG4gICAgLy8gaXQgd2lsbCBiZSBvdmVyd3JpdHRlbiB3aGVuIHRoZSBoZWFkZXJzIGFyZSBzaWduZWRcbiAgICBpZiAoaGVhZGVyS2V5ID09PSAnYXV0aG9yaXphdGlvbicpIHtcbiAgICAgIGhlYWRlckJhZ1snb3JpZ2luLWF1dGhvcml6YXRpb24nXSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gaGVhZGVyQmFnO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHNpbXBsZSBoZWFkZXIgYmFnIChvYmplY3QpIHRvIENsb3VkRnJvbnQgaGVhZGVyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGVhZGVyQmFnVG9DZkhlYWRlcnMoaGVhZGVyQmFnOiBCYWcpOiBDbG91ZEZyb250SGVhZGVycyB7XG4gIGNvbnN0IGNmSGVhZGVyczogQ2xvdWRGcm9udEhlYWRlcnMgPSB7fTtcbiAgZm9yIChjb25zdCBbaGVhZGVyS2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoaGVhZGVyQmFnKSkge1xuICAgIC8qXG4gICAgICBXaGVuIHlvdXIgTGFtYmRhIGZ1bmN0aW9uIGFkZHMgb3IgbW9kaWZpZXMgcmVxdWVzdCBoZWFkZXJzIGFuZCB5b3UgZG9uJ3QgaW5jbHVkZSB0aGUgaGVhZGVyIGtleSBmaWVsZCwgTGFtYmRhQEVkZ2UgYXV0b21hdGljYWxseSBpbnNlcnRzIGEgaGVhZGVyIGtleSB1c2luZyB0aGUgaGVhZGVyIG5hbWUgdGhhdCB5b3UgcHJvdmlkZS4gUmVnYXJkbGVzcyBvZiBob3cgeW91J3ZlIGZvcm1hdHRlZCB0aGUgaGVhZGVyIG5hbWUsIHRoZSBoZWFkZXIga2V5IHRoYXQncyBpbnNlcnRlZCBhdXRvbWF0aWNhbGx5IGlzIGZvcm1hdHRlZCB3aXRoIGluaXRpYWwgY2FwaXRhbGl6YXRpb24gZm9yIGVhY2ggcGFydCwgc2VwYXJhdGVkIGJ5IGh5cGhlbnMgKC0pLlxuICAgICAgU2VlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvbGFtYmRhLWV2ZW50LXN0cnVjdHVyZS5odG1sXG4gICAgKi9cbiAgICBjZkhlYWRlcnNbaGVhZGVyS2V5XSA9IFt7IHZhbHVlIH1dO1xuICB9XG4gIHJldHVybiBjZkhlYWRlcnM7XG59XG5cbi8qKlxuICogQ29udmVydHMgQ2xvdWRGcm9udCBxdWVyeXN0cmluZyB0byBRdWVyeVBhcmFtYXRlckJhZyBmb3IgSUFNIFNpZyBWNFxuICovXG5leHBvcnQgZnVuY3Rpb24gcXVlcnlTdHJpbmdUb1F1ZXJ5UGFyYW1CYWcocXVlcnlzdHJpbmc6IHN0cmluZyk6IEJhZyB7XG4gIGNvbnN0IG9sZFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMocXVlcnlzdHJpbmcpO1xuICBjb25zdCBuZXdQYXJhbXM6IEJhZyA9IHt9O1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBvbGRQYXJhbXMpIHtcbiAgICBuZXdQYXJhbXNba10gPSB2O1xuICB9XG4gIHJldHVybiBuZXdQYXJhbXM7XG59XG4iXX0=