fusion-plugin-rpc
Version:
Fetch data on the server and client with an RPC style interface.
272 lines (227 loc) • 28.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _koaBodyparser = _interopRequireDefault(require("koa-bodyparser"));
var _formidable = _interopRequireDefault(require("formidable"));
var _fusionCore = require("fusion-core");
var _fusionPluginUniversalEvents = require("fusion-plugin-universal-events");
var _missingHandlerError = _interopRequireDefault(require("./missing-handler-error"));
var _responseError = _interopRequireDefault(require("./response-error"));
var _tokens = require("./tokens.js");
var _utils = require("./utils.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/** Copyright (c) 2018 Uber Technologies, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
/* eslint-env node */
const statKey = 'rpc:method';
/* Helper function */
function hasHandler(handlers, method) {
return Object.prototype.hasOwnProperty.call(handlers, method);
}
class RPC {
constructor(emitter, handlers, ctx) {
if (!ctx || !ctx.headers) {
throw new Error('fusion-plugin-rpc requires `ctx`');
}
this.ctx = ctx;
this.emitter = emitter;
this.handlers = handlers;
return this;
}
async request(method, args) {
const startTime = ms();
if (!this.ctx) {
throw new Error('fusion-plugin-rpc requires `ctx`');
}
if (!this.emitter) {
throw new Error('fusion-plugin-rpc requires `emitter`');
}
const scopedEmitter = this.emitter.from(this.ctx);
if (!this.handlers) {
throw new Error('fusion-plugin-rpc requires `handlers`');
}
if (!hasHandler(this.handlers, method)) {
const e = new _missingHandlerError.default(method);
if (scopedEmitter) {
scopedEmitter.emit('rpc:error', {
method,
origin: 'server',
error: e
});
}
throw e;
}
try {
const result = await this.handlers[method](args, this.ctx);
if (scopedEmitter) {
scopedEmitter.emit(statKey, {
method,
status: 'success',
origin: 'server',
timing: ms() - startTime
});
}
return result;
} catch (e) {
if (scopedEmitter) {
scopedEmitter.emit(statKey, {
method,
error: e,
status: 'failure',
origin: 'server',
timing: ms() - startTime
});
}
throw e;
}
}
}
const pluginFactory = () => (0, _fusionCore.createPlugin)({
deps: {
RouteTags: _fusionCore.RouteTagsToken.optional,
emitter: _fusionPluginUniversalEvents.UniversalEventsToken,
handlers: _tokens.RPCHandlersToken,
bodyParserOptions: _tokens.BodyParserOptionsToken.optional,
rpcConfig: _tokens.RPCHandlersConfigToken.optional
},
provides: deps => {
const {
emitter,
handlers
} = deps;
const service = {
from: (0, _fusionCore.memoize)(ctx => new RPC(emitter, handlers, ctx))
};
return service;
},
middleware: deps => {
const {
emitter,
handlers,
bodyParserOptions,
rpcConfig
} = deps;
if (!handlers) throw new Error('Missing handlers registered to RPCHandlersToken');
if (!emitter) throw new Error('Missing emitter registered to UniversalEventsToken');
const parseBody = (0, _koaBodyparser.default)(bodyParserOptions);
const apiPath = (0, _utils.formatApiPath)(rpcConfig && rpcConfig.apiPath ? rpcConfig.apiPath : 'api');
return async (ctx, next) => {
await next();
const routeTags = deps.RouteTags && deps.RouteTags.from(ctx) || {};
const scopedEmitter = emitter.from(ctx);
if (ctx.method === 'POST' && ctx.path.startsWith(apiPath)) {
const startTime = ms(); // eslint-disable-next-line no-useless-escape
const pathMatch = new RegExp(`${apiPath}([^/]+)`, 'i');
const [, method] = ctx.path.match(pathMatch) || [];
if (hasHandler(handlers, method)) {
routeTags.name = method;
let body;
try {
if (ctx.req && ctx.req.headers && ctx.req.headers['content-type'] && ctx.req.headers['content-type'].indexOf('multipart/form-data') !== -1) {
const form = new _formidable.default.IncomingForm();
body = await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
}
resolve({ ...fields,
...files
});
});
});
} else {
await parseBody(ctx, () => Promise.resolve());
}
} catch (e) {
ctx.body = {
status: 'failure',
data: {
message: e.message,
code: e.type || 'ERR_BAD_BODY',
meta: e.meta
}
};
if (scopedEmitter) {
scopedEmitter.emit(statKey, {
method,
error: e,
status: 'failure',
origin: 'browser',
timing: ms() - startTime
});
} // don't try to call handler
return;
}
try {
const result = await handlers[method](body || ctx.request.body, ctx);
ctx.body = {
status: 'success',
data: result
};
if (scopedEmitter) {
scopedEmitter.emit(statKey, {
method,
status: 'success',
origin: 'browser',
timing: ms() - startTime
});
}
} catch (e) {
const error = e instanceof _responseError.default ? e : new Error(process.env.NODE_ENV !== "production" ? 'UnknownError - Use ResponseError from fusion-plugin-rpc (or fusion-plugin-rpc-redux-react if you are using React) package for more detailed error messages' : 'Internal Server Error');
ctx.body = {
status: 'failure',
data: {
message: error.message,
// $FlowFixMe
code: error.code,
// $FlowFixMe
meta: error.meta
}
};
if (scopedEmitter) {
scopedEmitter.emit(statKey, {
method,
error: e,
status: 'failure',
origin: 'browser',
timing: ms() - startTime
});
}
}
} else {
const e = new _missingHandlerError.default(method);
ctx.body = {
status: 'failure',
data: {
message: e.message,
code: e.code
}
};
ctx.status = 404;
if (scopedEmitter) {
scopedEmitter.emit('rpc:error', {
origin: 'browser',
method,
error: e
});
}
}
}
};
}
});
/* Helper functions */
function ms() {
const [seconds, ns] = process.hrtime();
return Math.round(seconds * 1000 + ns / 1e6);
}
var _default = false && pluginFactory();
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9zZXJ2ZXIuanMiXSwibmFtZXMiOlsic3RhdEtleSIsImhhc0hhbmRsZXIiLCJoYW5kbGVycyIsIm1ldGhvZCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIlJQQyIsImNvbnN0cnVjdG9yIiwiZW1pdHRlciIsImN0eCIsImhlYWRlcnMiLCJFcnJvciIsInJlcXVlc3QiLCJhcmdzIiwic3RhcnRUaW1lIiwibXMiLCJzY29wZWRFbWl0dGVyIiwiZnJvbSIsImUiLCJNaXNzaW5nSGFuZGxlckVycm9yIiwiZW1pdCIsIm9yaWdpbiIsImVycm9yIiwicmVzdWx0Iiwic3RhdHVzIiwidGltaW5nIiwicGx1Z2luRmFjdG9yeSIsImRlcHMiLCJSb3V0ZVRhZ3MiLCJSb3V0ZVRhZ3NUb2tlbiIsIm9wdGlvbmFsIiwiVW5pdmVyc2FsRXZlbnRzVG9rZW4iLCJSUENIYW5kbGVyc1Rva2VuIiwiYm9keVBhcnNlck9wdGlvbnMiLCJCb2R5UGFyc2VyT3B0aW9uc1Rva2VuIiwicnBjQ29uZmlnIiwiUlBDSGFuZGxlcnNDb25maWdUb2tlbiIsInByb3ZpZGVzIiwic2VydmljZSIsIm1pZGRsZXdhcmUiLCJwYXJzZUJvZHkiLCJhcGlQYXRoIiwibmV4dCIsInJvdXRlVGFncyIsInBhdGgiLCJzdGFydHNXaXRoIiwicGF0aE1hdGNoIiwiUmVnRXhwIiwibWF0Y2giLCJuYW1lIiwiYm9keSIsInJlcSIsImluZGV4T2YiLCJmb3JtIiwiZm9ybWlkYWJsZSIsIkluY29taW5nRm9ybSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicGFyc2UiLCJlcnIiLCJmaWVsZHMiLCJmaWxlcyIsImRhdGEiLCJtZXNzYWdlIiwiY29kZSIsInR5cGUiLCJtZXRhIiwiUmVzcG9uc2VFcnJvciIsInNlY29uZHMiLCJucyIsInByb2Nlc3MiLCJocnRpbWUiLCJNYXRoIiwicm91bmQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFVQTs7QUFDQTs7QUFF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OCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuLyogZXNsaW50LWVudiBub2RlICovXG5cbmltcG9ydCBib2R5cGFyc2VyIGZyb20gJ2tvYS1ib2R5cGFyc2VyJztcbmltcG9ydCBmb3JtaWRhYmxlIGZyb20gJ2Zvcm1pZGFibGUnO1xuXG5pbXBvcnQge2NyZWF0ZVBsdWdpbiwgbWVtb2l6ZSwgUm91dGVUYWdzVG9rZW59IGZyb20gJ2Z1c2lvbi1jb3JlJztcbmltcG9ydCB0eXBlIHtDb250ZXh0fSBmcm9tICdmdXNpb24tY29yZSc7XG5pbXBvcnQge1VuaXZlcnNhbEV2ZW50c1Rva2VufSBmcm9tICdmdXNpb24tcGx1Z2luLXVuaXZlcnNhbC1ldmVudHMnO1xuaW1wb3J0IHR5cGUge0ZldGNofSBmcm9tICdmdXNpb24tdG9rZW5zJztcblxuaW1wb3J0IE1pc3NpbmdIYW5kbGVyRXJyb3IgZnJvbSAnLi9taXNzaW5nLWhhbmRsZXItZXJyb3InO1xuaW1wb3J0IFJlc3BvbnNlRXJyb3IgZnJvbSAnLi9yZXNwb25zZS1lcnJvcic7XG5pbXBvcnQge1xuICBCb2R5UGFyc2VyT3B0aW9uc1Rva2VuLFxuICBSUENIYW5kbGVyc1Rva2VuLFxuICBSUENIYW5kbGVyc0NvbmZpZ1Rva2VuLFxufSBmcm9tICcuL3Rva2Vucy5qcyc7XG5pbXBvcnQgdHlwZSB7SGFuZGxlclR5cGV9IGZyb20gJy4vdG9rZW5zLmpzJztcbmltcG9ydCB0eXBlIHtSUENQbHVnaW5UeXBlLCBJRW1pdHRlcn0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQge2Zvcm1hdEFwaVBhdGh9IGZyb20gJy4vdXRpbHMuanMnO1xuXG5jb25zdCBzdGF0S2V5ID0gJ3JwYzptZXRob2QnO1xuXG4vKiBIZWxwZXIgZnVuY3Rpb24gKi9cbmZ1bmN0aW9uIGhhc0hhbmRsZXIoaGFuZGxlcnM6IEhhbmRsZXJUeXBlLCBtZXRob2Q6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGhhbmRsZXJzLCBtZXRob2QpO1xufVxuXG5jbGFzcyBSUEMge1xuICBjdHg6ID9Db250ZXh0O1xuICBlbWl0dGVyOiA/SUVtaXR0ZXI7XG4gIGhhbmRsZXJzOiA/SGFuZGxlclR5cGU7XG4gIGZldGNoOiA/RmV0Y2g7XG5cbiAgY29uc3RydWN0b3IoZW1pdHRlcjogSUVtaXR0ZXIsIGhhbmRsZXJzOiBhbnksIGN0eDogQ29udGV4dCk6IFJQQyB7XG4gICAgaWYgKCFjdHggfHwgIWN0eC5oZWFkZXJzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Z1c2lvbi1wbHVnaW4tcnBjIHJlcXVpcmVzIGBjdHhgJyk7XG4gICAgfVxuICAgIHRoaXMuY3R4ID0gY3R4O1xuICAgIHRoaXMuZW1pdHRlciA9IGVtaXR0ZXI7XG4gICAgdGhpcy5oYW5kbGVycyA9IGhhbmRsZXJzO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBhc3luYyByZXF1ZXN0PFRBcmdzLCBUUmVzdWx0PihtZXRob2Q6IHN0cmluZywgYXJnczogVEFyZ3MpOiBQcm9taXNlPFRSZXN1bHQ+IHtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBtcygpO1xuXG4gICAgaWYgKCF0aGlzLmN0eCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdmdXNpb24tcGx1Z2luLXJwYyByZXF1aXJlcyBgY3R4YCcpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuZW1pdHRlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdmdXNpb24tcGx1Z2luLXJwYyByZXF1aXJlcyBgZW1pdHRlcmAnKTtcbiAgICB9XG4gICAgY29uc3Qgc2NvcGVkRW1pdHRlciA9IHRoaXMuZW1pdHRlci5mcm9tKHRoaXMuY3R4KTtcblxuICAgIGlmICghdGhpcy5oYW5kbGVycykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdmdXNpb24tcGx1Z2luLXJwYyByZXF1aXJlcyBgaGFuZGxlcnNgJyk7XG4gICAgfVxuICAgIGlmICghaGFzSGFuZGxlcih0aGlzLmhhbmRsZXJzLCBtZXRob2QpKSB7XG4gICAgICBjb25zdCBlID0gbmV3IE1pc3NpbmdIYW5kbGVyRXJyb3IobWV0aG9kKTtcbiAgICAgIGlmIChzY29wZWRFbWl0dGVyKSB7XG4gICAgICAgIHNjb3BlZEVtaXR0ZXIuZW1pdCgncnBjOmVycm9yJywge1xuICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICBvcmlnaW46ICdzZXJ2ZXInLFxuICAgICAgICAgIGVycm9yOiBlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmhhbmRsZXJzW21ldGhvZF0oYXJncywgdGhpcy5jdHgpO1xuICAgICAgaWYgKHNjb3BlZEVtaXR0ZXIpIHtcbiAgICAgICAgc2NvcGVkRW1pdHRlci5lbWl0KHN0YXRLZXksIHtcbiAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgc3RhdHVzOiAnc3VjY2VzcycsXG4gICAgICAgICAgb3JpZ2luOiAnc2VydmVyJyxcbiAgICAgICAgICB0aW1pbmc6IG1zKCkgLSBzdGFydFRpbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoc2NvcGVkRW1pdHRlcikge1xuICAgICAgICBzY29wZWRFbWl0dGVyLmVtaXQoc3RhdEtleSwge1xuICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICBlcnJvcjogZSxcbiAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICBvcmlnaW46ICdzZXJ2ZXInLFxuICAgICAgICAgIHRpbWluZzogbXMoKSAtIHN0YXJ0VGltZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCBwbHVnaW5GYWN0b3J5OiAoKSA9PiBSUENQbHVnaW5UeXBlID0gKCkgPT5cbiAgY3JlYXRlUGx1Z2luKHtcbiAgICBkZXBzOiB7XG4gICAgICBSb3V0ZVRhZ3M6IFJvdXRlVGFnc1Rva2VuLm9wdGlvbmFsLFxuICAgICAgZW1pdHRlcjogVW5pdmVyc2FsRXZlbnRzVG9rZW4sXG4gICAgICBoYW5kbGVyczogUlBDSGFuZGxlcnNUb2tlbixcbiAgICAgIGJvZHlQYXJzZXJPcHRpb25zOiBCb2R5UGFyc2VyT3B0aW9uc1Rva2VuLm9wdGlvbmFsLFxuICAgICAgcnBjQ29uZmlnOiBSUENIYW5kbGVyc0NvbmZpZ1Rva2VuLm9wdGlvbmFsLFxuICAgIH0sXG5cbiAgICBwcm92aWRlczogKGRlcHMpID0+IHtcbiAgICAgIGNvbnN0IHtlbWl0dGVyLCBoYW5kbGVyc30gPSBkZXBzO1xuXG4gICAgICBjb25zdCBzZXJ2aWNlID0ge1xuICAgICAgICBmcm9tOiBtZW1vaXplKChjdHgpID0+IG5ldyBSUEMoZW1pdHRlciwgaGFuZGxlcnMsIGN0eCkpLFxuICAgICAgfTtcbiAgICAgIHJldHVybiBzZXJ2aWNlO1xuICAgIH0sXG5cbiAgICBtaWRkbGV3YXJlOiAoZGVwcykgPT4ge1xuICAgICAgY29uc3Qge2VtaXR0ZXIsIGhhbmRsZXJzLCBib2R5UGFyc2VyT3B0aW9ucywgcnBjQ29uZmlnfSA9IGRlcHM7XG4gICAgICBpZiAoIWhhbmRsZXJzKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgaGFuZGxlcnMgcmVnaXN0ZXJlZCB0byBSUENIYW5kbGVyc1Rva2VuJyk7XG4gICAgICBpZiAoIWVtaXR0ZXIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBlbWl0dGVyIHJlZ2lzdGVyZWQgdG8gVW5pdmVyc2FsRXZlbnRzVG9rZW4nKTtcbiAgICAgIGNvbnN0IHBhcnNlQm9keSA9IGJvZHlwYXJzZXIoYm9keVBhcnNlck9wdGlvbnMpO1xuXG4gICAgICBjb25zdCBhcGlQYXRoID0gZm9ybWF0QXBpUGF0aChcbiAgICAgICAgcnBjQ29uZmlnICYmIHJwY0NvbmZpZy5hcGlQYXRoID8gcnBjQ29uZmlnLmFwaVBhdGggOiAnYXBpJ1xuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGFzeW5jIChjdHgsIG5leHQpID0+IHtcbiAgICAgICAgYXdhaXQgbmV4dCgpO1xuICAgICAgICBjb25zdCByb3V0ZVRhZ3MgPSAoZGVwcy5Sb3V0ZVRhZ3MgJiYgZGVwcy5Sb3V0ZVRhZ3MuZnJvbShjdHgpKSB8fCB7fTtcbiAgICAgICAgY29uc3Qgc2NvcGVkRW1pdHRlciA9IGVtaXR0ZXIuZnJvbShjdHgpO1xuICAgICAgICBpZiAoY3R4Lm1ldGhvZCA9PT0gJ1BPU1QnICYmIGN0eC5wYXRoLnN0YXJ0c1dpdGgoYXBpUGF0aCkpIHtcbiAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBtcygpO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWVzY2FwZVxuICAgICAgICAgIGNvbnN0IHBhdGhNYXRjaCA9IG5ldyBSZWdFeHAoYCR7YXBpUGF0aH0oW14vXSspYCwgJ2knKTtcbiAgICAgICAgICBjb25zdCBbLCBtZXRob2RdID0gY3R4LnBhdGgubWF0Y2gocGF0aE1hdGNoKSB8fCBbXTtcbiAgICAgICAgICBpZiAoaGFzSGFuZGxlcihoYW5kbGVycywgbWV0aG9kKSkge1xuICAgICAgICAgICAgcm91dGVUYWdzLm5hbWUgPSBtZXRob2Q7XG4gICAgICAgICAgICBsZXQgYm9keTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBjdHgucmVxICYmXG4gICAgICAgICAgICAgICAgY3R4LnJlcS5oZWFkZXJzICYmXG4gICAgICAgICAgICAgICAgY3R4LnJlcS5oZWFkZXJzWydjb250ZW50LXR5cGUnXSAmJlxuICAgICAgICAgICAgICAgIGN0eC5yZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10uaW5kZXhPZihcbiAgICAgICAgICAgICAgICAgICdtdWx0aXBhcnQvZm9ybS1kYXRhJ1xuICAgICAgICAgICAgICAgICkgIT09IC0xXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZvcm0gPSBuZXcgZm9ybWlkYWJsZS5JbmNvbWluZ0Zvcm0oKTtcbiAgICAgICAgICAgICAgICBib2R5ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgZm9ybS5wYXJzZShjdHgucmVxLCAoZXJyLCBmaWVsZHM6IHtbc3RyaW5nXTogYW55fSwgZmlsZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgLi4uZmllbGRzLFxuICAgICAgICAgICAgICAgICAgICAgIC4uLmZpbGVzLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IHBhcnNlQm9keShjdHgsICgpID0+IFByb21pc2UucmVzb2x2ZSgpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICBjdHguYm9keSA9IHtcbiAgICAgICAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICBjb2RlOiBlLnR5cGUgfHwgJ0VSUl9CQURfQk9EWScsXG4gICAgICAgICAgICAgICAgICBtZXRhOiBlLm1ldGEsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgaWYgKHNjb3BlZEVtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgICBzY29wZWRFbWl0dGVyLmVtaXQoc3RhdEtleSwge1xuICAgICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgZXJyb3I6IGUsXG4gICAgICAgICAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbjogJ2Jyb3dzZXInLFxuICAgICAgICAgICAgICAgICAgdGltaW5nOiBtcygpIC0gc3RhcnRUaW1lLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIGRvbid0IHRyeSB0byBjYWxsIGhhbmRsZXJcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyc1ttZXRob2RdKFxuICAgICAgICAgICAgICAgIGJvZHkgfHwgY3R4LnJlcXVlc3QuYm9keSxcbiAgICAgICAgICAgICAgICBjdHhcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY3R4LmJvZHkgPSB7XG4gICAgICAgICAgICAgICAgc3RhdHVzOiAnc3VjY2VzcycsXG4gICAgICAgICAgICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBpZiAoc2NvcGVkRW1pdHRlcikge1xuICAgICAgICAgICAgICAgIHNjb3BlZEVtaXR0ZXIuZW1pdChzdGF0S2V5LCB7XG4gICAgICAgICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICAgICAgICBzdGF0dXM6ICdzdWNjZXNzJyxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbjogJ2Jyb3dzZXInLFxuICAgICAgICAgICAgICAgICAgdGltaW5nOiBtcygpIC0gc3RhcnRUaW1lLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID1cbiAgICAgICAgICAgICAgICBlIGluc3RhbmNlb2YgUmVzcG9uc2VFcnJvclxuICAgICAgICAgICAgICAgICAgPyBlXG4gICAgICAgICAgICAgICAgICA6IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBfX0RFVl9fXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdVbmtub3duRXJyb3IgLSBVc2UgUmVzcG9uc2VFcnJvciBmcm9tIGZ1c2lvbi1wbHVnaW4tcnBjIChvciBmdXNpb24tcGx1Z2luLXJwYy1yZWR1eC1yZWFjdCBpZiB5b3UgYXJlIHVzaW5nIFJlYWN0KSBwYWNrYWdlIGZvciBtb3JlIGRldGFpbGVkIGVycm9yIG1lc3NhZ2VzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAnSW50ZXJuYWwgU2VydmVyIEVycm9yJ1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjdHguYm9keSA9IHtcbiAgICAgICAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgLy8gJEZsb3dGaXhNZVxuICAgICAgICAgICAgICAgICAgY29kZTogZXJyb3IuY29kZSxcbiAgICAgICAgICAgICAgICAgIC8vICRGbG93Rml4TWVcbiAgICAgICAgICAgICAgICAgIG1ldGE6IGVycm9yLm1ldGEsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgaWYgKHNjb3BlZEVtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgICBzY29wZWRFbWl0dGVyLmVtaXQoc3RhdEtleSwge1xuICAgICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgZXJyb3I6IGUsXG4gICAgICAgICAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbjogJ2Jyb3dzZXInLFxuICAgICAgICAgICAgICAgICAgdGltaW5nOiBtcygpIC0gc3RhcnRUaW1lLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGUgPSBuZXcgTWlzc2luZ0hhbmRsZXJFcnJvcihtZXRob2QpO1xuICAgICAgICAgICAgY3R4LmJvZHkgPSB7XG4gICAgICAgICAgICAgIHN0YXR1czogJ2ZhaWx1cmUnLFxuICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIGNvZGU6IGUuY29kZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjdHguc3RhdHVzID0gNDA0O1xuICAgICAgICAgICAgaWYgKHNjb3BlZEVtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgc2NvcGVkRW1pdHRlci5lbWl0KCdycGM6ZXJyb3InLCB7XG4gICAgICAgICAgICAgICAgb3JpZ2luOiAnYnJvd3NlcicsXG4gICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSxcbiAgfSk7XG5cbi8qIEhlbHBlciBmdW5jdGlvbnMgKi9cbmZ1bmN0aW9uIG1zKCkge1xuICBjb25zdCBbc2Vjb25kcywgbnNdID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgcmV0dXJuIE1hdGgucm91bmQoc2Vjb25kcyAqIDEwMDAgKyBucyAvIDFlNik7XG59XG5cbmV4cG9ydCBkZWZhdWx0ICgoX19OT0RFX18gJiYgcGx1Z2luRmFjdG9yeSgpOiBhbnkpOiBSUENQbHVnaW5UeXBlKTtcbiJdfQ==