@scloud/lambda-local
Version:
Run typical Lambda handlers locally.
92 lines • 13.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.webApiLocal = webApiLocal;
const express_1 = __importDefault(require("express"));
function webApiLocal(lambdaHandler, debug = false) {
const port = +(process.env.port || '3000');
const app = (0, express_1.default)();
// https://stackoverflow.com/questions/12345166/how-to-force-parse-request-body-as-plain-text-instead-of-json-in-express
app.use(express_1.default.text({ type: '*/*' }));
app.use(async (req, res) => {
// const url = new URL(req.originalUrl, 'https://example.com');
// Headers - NB it seems that in Lambda multiValueHeaders always contains the values from headers
const headers = {};
const multiValueHeaders = {};
Object.keys(req.headers).forEach((header) => {
if (req.headers[header] === undefined) {
headers[header] = undefined;
multiValueHeaders[header] = undefined;
}
else if (typeof req.headers[header] === 'string') {
headers[header] = req.headers[header];
multiValueHeaders[header] = (multiValueHeaders[header] || []).concat([req.headers[header]]);
}
else if (Array.isArray(req.headers[header])) {
multiValueHeaders[header] = (multiValueHeaders[header] || []).concat(req.headers[header]);
}
});
// Query string - basic translation
const queryStringParameters = {};
const multiValueQueryStringParameters = {};
for (const name of Object.keys(req.query)) {
const value = req.query[name];
if (typeof value === 'string')
queryStringParameters[name] = value;
}
const event = {
body: typeof req.body === 'string' ? req.body : JSON.stringify(req.body),
headers,
multiValueHeaders,
httpMethod: req.method,
path: req.path,
queryStringParameters,
multiValueQueryStringParameters,
requestContext: {
httpMethod: req.method,
path: req.path,
protocol: req.protocol,
},
};
// Print out the event that will be sent to the handler
if (debug) {
console.log('Event:');
console.log(event.httpMethod, event.path);
console.log(JSON.stringify(event, null, 2));
}
try {
// Invoke the function handler:
const result = await lambdaHandler(event, {});
// Print out the result
if (debug) {
console.log('Result:');
console.log(event.httpMethod, event.path, result.statusCode);
console.log(JSON.stringify(result.body, null, 2));
}
// Headers
res.status(result.statusCode);
for (const key of Object.keys(result.multiValueHeaders || [])) {
res.set(key, result.multiValueHeaders[key].map((value) => `${value}`));
}
;
for (const key of Object.keys(result.headers || [])) {
res.set(key, `${result.headers[key]}`);
}
;
// Body
res.send(result.body);
}
catch (e) {
// Log the error and send a 500 response
console.log(e);
console.log(e.stack);
res.status(500).send(`${e}`);
}
});
app.listen(port, () => {
console.log(`Lambda handler can be invoked at http://localhost:${port}`);
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViQXBpTG9jYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2ViQXBpTG9jYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSxrQ0EwRkM7QUE3RkQsc0RBQXFEO0FBR3JELFNBQWdCLFdBQVcsQ0FBQyxhQUFnRyxFQUFFLEtBQUssR0FBRyxLQUFLO0lBQ3pJLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxJQUFBLGlCQUFPLEdBQUUsQ0FBQztJQUV0Qix3SEFBd0g7SUFDeEgsR0FBRyxDQUFDLEdBQUcsQ0FBQyxpQkFBTyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFdkMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBWSxFQUFFLEdBQWEsRUFBRSxFQUFFO1FBQzVDLCtEQUErRDtRQUMvRCxpR0FBaUc7UUFDakcsTUFBTSxPQUFPLEdBQXVDLEVBQUUsQ0FBQztRQUN2RCxNQUFNLGlCQUFpQixHQUF5QyxFQUFFLENBQUM7UUFDbkUsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDMUMsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN0QyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsU0FBUyxDQUFDO2dCQUM1QixpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUM7WUFDeEMsQ0FBQztpQkFBTSxJQUFJLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDbkQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3RDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUYsQ0FBQztpQkFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQzlDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUM1RixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxtQ0FBbUM7UUFDbkMsTUFBTSxxQkFBcUIsR0FBdUMsRUFBRSxDQUFDO1FBQ3JFLE1BQU0sK0JBQStCLEdBQXlDLEVBQUUsQ0FBQztRQUNqRixLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDMUMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7Z0JBQUUscUJBQXFCLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQ3JFLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBeUI7WUFDbEMsSUFBSSxFQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztZQUN4RSxPQUFPO1lBQ1AsaUJBQWlCO1lBQ2pCLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTTtZQUN0QixJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUk7WUFDZCxxQkFBcUI7WUFDckIsK0JBQStCO1lBQy9CLGNBQWMsRUFBRTtnQkFDZCxVQUFVLEVBQUUsR0FBRyxDQUFDLE1BQU07Z0JBQ3RCLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTtnQkFDZCxRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVE7YUFDOEI7U0FDcEIsQ0FBQztRQUVyQyx1REFBdUQ7UUFDdkQsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMxQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFFRCxJQUFJLENBQUM7WUFFSCwrQkFBK0I7WUFDL0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQWEsQ0FBQyxDQUFDO1lBRXpELHVCQUF1QjtZQUN2QixJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3ZCLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDN0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEQsQ0FBQztZQUVELFVBQVU7WUFDVixHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUM5QixLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzlELEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxpQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzFFLENBQUM7WUFBQSxDQUFDO1lBRUYsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDcEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsT0FBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMxQyxDQUFDO1lBQUEsQ0FBQztZQUVGLE9BQU87WUFDUCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUV4QixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLHdDQUF3QztZQUN4QyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2YsT0FBTyxDQUFDLEdBQUcsQ0FBRSxDQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9CLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtRQUNwQixPQUFPLENBQUMsR0FBRyxDQUFDLHFEQUFxRCxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzNFLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzLCB7IFJlcXVlc3QsIFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBBUElHYXRld2F5UHJveHlFdmVudCwgQVBJR2F0ZXdheVByb3h5UmVzdWx0LCBDb250ZXh0IH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5cbmV4cG9ydCBmdW5jdGlvbiB3ZWJBcGlMb2NhbChsYW1iZGFIYW5kbGVyOiAoZXZlbnQ6IEFQSUdhdGV3YXlQcm94eUV2ZW50LCBjb250ZXh0OiBDb250ZXh0KSA9PiBQcm9taXNlPEFQSUdhdGV3YXlQcm94eVJlc3VsdD4sIGRlYnVnID0gZmFsc2UpIHtcbiAgY29uc3QgcG9ydCA9ICsocHJvY2Vzcy5lbnYucG9ydCB8fCAnMzAwMCcpO1xuICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG5cbiAgLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTIzNDUxNjYvaG93LXRvLWZvcmNlLXBhcnNlLXJlcXVlc3QtYm9keS1hcy1wbGFpbi10ZXh0LWluc3RlYWQtb2YtanNvbi1pbi1leHByZXNzXG4gIGFwcC51c2UoZXhwcmVzcy50ZXh0KHsgdHlwZTogJyovKicgfSkpO1xuXG4gIGFwcC51c2UoYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIC8vIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLm9yaWdpbmFsVXJsLCAnaHR0cHM6Ly9leGFtcGxlLmNvbScpO1xuICAgIC8vIEhlYWRlcnMgLSBOQiBpdCBzZWVtcyB0aGF0IGluIExhbWJkYSBtdWx0aVZhbHVlSGVhZGVycyBhbHdheXMgY29udGFpbnMgdGhlIHZhbHVlcyBmcm9tIGhlYWRlcnNcbiAgICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0ge307XG4gICAgY29uc3QgbXVsdGlWYWx1ZUhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdIHwgdW5kZWZpbmVkPiA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHJlcS5oZWFkZXJzKS5mb3JFYWNoKChoZWFkZXIpID0+IHtcbiAgICAgIGlmIChyZXEuaGVhZGVyc1toZWFkZXJdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaGVhZGVyc1toZWFkZXJdID0gdW5kZWZpbmVkO1xuICAgICAgICBtdWx0aVZhbHVlSGVhZGVyc1toZWFkZXJdID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcmVxLmhlYWRlcnNbaGVhZGVyXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaGVhZGVyc1toZWFkZXJdID0gcmVxLmhlYWRlcnNbaGVhZGVyXTtcbiAgICAgICAgbXVsdGlWYWx1ZUhlYWRlcnNbaGVhZGVyXSA9IChtdWx0aVZhbHVlSGVhZGVyc1toZWFkZXJdIHx8IFtdKS5jb25jYXQoW3JlcS5oZWFkZXJzW2hlYWRlcl1dKTtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXEuaGVhZGVyc1toZWFkZXJdKSkge1xuICAgICAgICBtdWx0aVZhbHVlSGVhZGVyc1toZWFkZXJdID0gKG11bHRpVmFsdWVIZWFkZXJzW2hlYWRlcl0gfHwgW10pLmNvbmNhdChyZXEuaGVhZGVyc1toZWFkZXJdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFF1ZXJ5IHN0cmluZyAtIGJhc2ljIHRyYW5zbGF0aW9uXG4gICAgY29uc3QgcXVlcnlTdHJpbmdQYXJhbWV0ZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0ge307XG4gICAgY29uc3QgbXVsdGlWYWx1ZVF1ZXJ5U3RyaW5nUGFyYW1ldGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nW10gfCB1bmRlZmluZWQ+ID0ge307XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKHJlcS5xdWVyeSkpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gcmVxLnF1ZXJ5W25hbWVdO1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1tuYW1lXSA9IHZhbHVlO1xuICAgIH1cblxuICAgIGNvbnN0IGV2ZW50OiBBUElHYXRld2F5UHJveHlFdmVudCA9IHtcbiAgICAgIGJvZHk6IHR5cGVvZiByZXEuYm9keSA9PT0gJ3N0cmluZycgPyByZXEuYm9keSA6IEpTT04uc3RyaW5naWZ5KHJlcS5ib2R5KSxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBtdWx0aVZhbHVlSGVhZGVycyxcbiAgICAgIGh0dHBNZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICBwYXRoOiByZXEucGF0aCxcbiAgICAgIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycyxcbiAgICAgIG11bHRpVmFsdWVRdWVyeVN0cmluZ1BhcmFtZXRlcnMsXG4gICAgICByZXF1ZXN0Q29udGV4dDoge1xuICAgICAgICBodHRwTWV0aG9kOiByZXEubWV0aG9kLFxuICAgICAgICBwYXRoOiByZXEucGF0aCxcbiAgICAgICAgcHJvdG9jb2w6IHJlcS5wcm90b2NvbCxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBBUElHYXRld2F5UHJveHlFdmVudFsncmVxdWVzdENvbnRleHQnXSxcbiAgICB9IGFzIHVua25vd24gYXMgQVBJR2F0ZXdheVByb3h5RXZlbnQ7XG5cbiAgICAvLyBQcmludCBvdXQgdGhlIGV2ZW50IHRoYXQgd2lsbCBiZSBzZW50IHRvIHRoZSBoYW5kbGVyXG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLmxvZygnRXZlbnQ6Jyk7XG4gICAgICBjb25zb2xlLmxvZyhldmVudC5odHRwTWV0aG9kLCBldmVudC5wYXRoKTtcbiAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGV2ZW50LCBudWxsLCAyKSk7XG4gICAgfVxuXG4gICAgdHJ5IHtcblxuICAgICAgLy8gSW52b2tlIHRoZSBmdW5jdGlvbiBoYW5kbGVyOlxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbGFtYmRhSGFuZGxlcihldmVudCwge30gYXMgQ29udGV4dCk7XG5cbiAgICAgIC8vIFByaW50IG91dCB0aGUgcmVzdWx0XG4gICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1Jlc3VsdDonKTtcbiAgICAgICAgY29uc29sZS5sb2coZXZlbnQuaHR0cE1ldGhvZCwgZXZlbnQucGF0aCwgcmVzdWx0LnN0YXR1c0NvZGUpO1xuICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShyZXN1bHQuYm9keSwgbnVsbCwgMikpO1xuICAgICAgfVxuXG4gICAgICAvLyBIZWFkZXJzXG4gICAgICByZXMuc3RhdHVzKHJlc3VsdC5zdGF0dXNDb2RlKTtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHJlc3VsdC5tdWx0aVZhbHVlSGVhZGVycyB8fCBbXSkpIHtcbiAgICAgICAgcmVzLnNldChrZXksIHJlc3VsdC5tdWx0aVZhbHVlSGVhZGVycyFba2V5XS5tYXAoKHZhbHVlKSA9PiBgJHt2YWx1ZX1gKSk7XG4gICAgICB9O1xuXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhyZXN1bHQuaGVhZGVycyB8fCBbXSkpIHtcbiAgICAgICAgcmVzLnNldChrZXksIGAke3Jlc3VsdC5oZWFkZXJzIVtrZXldfWApO1xuICAgICAgfTtcblxuICAgICAgLy8gQm9keVxuICAgICAgcmVzLnNlbmQocmVzdWx0LmJvZHkpO1xuXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gTG9nIHRoZSBlcnJvciBhbmQgc2VuZCBhIDUwMCByZXNwb25zZVxuICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICBjb25zb2xlLmxvZygoZSBhcyBFcnJvcikuc3RhY2spO1xuICAgICAgcmVzLnN0YXR1cyg1MDApLnNlbmQoYCR7ZX1gKTtcbiAgICB9XG4gIH0pO1xuXG4gIGFwcC5saXN0ZW4ocG9ydCwgKCkgPT4ge1xuICAgIGNvbnNvbGUubG9nKGBMYW1iZGEgaGFuZGxlciBjYW4gYmUgaW52b2tlZCBhdCBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gKTtcbiAgfSk7XG59XG4iXX0=