UNPKG

seneca

Version:

A Microservices Framework for Node.js

308 lines 9.84 kB
/* Copyright © 2014-2022 Richard Rodger and other contributors, MIT License. */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.Outward = void 0; var Util = require('util'); var Common = require('./common'); // Internal implementations. var intern = {}; function outward_make_error(spec) { const ctx = spec.ctx; const data = spec.data; if (!ctx.options.legacy.error) { if (data.res && !data.meta.error && data.res.meta$ && data.res.meta$.err) { var res = new Error(data.res.message); for (var p in data.res) { res[p] = data.res[p]; } data.res = res; } } } // Store result in action cache // TODO: replace with history function outward_act_cache(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var res = data.res; var meta = data.meta; var actid = meta.id; var private$ = ctx.seneca.private$; if (actid != null && so.history.active) { var actdetails = private$.history.get(actid); if (actdetails) { actdetails.result.push({ when: Date.now(), res: res }); } } } function outward_act_stats(spec) { const ctx = spec.ctx; const data = spec.data; if (!ctx.actdef || ctx.cached$) { return; } var private$ = ctx.seneca.private$; var stats = private$.stats.act; var meta = data.meta; ++stats.done; // TODO: need to provide guarantees for inputs to avoid superfluous null checks if (meta && null == meta.prior) { private$.timestats.point(ctx.duration, ctx.actdef.pattern); } var pattern = ctx.actdef.pattern; var actstats = (private$.stats.actmap[pattern] = private$.stats.actmap[pattern] || {}); if (meta && meta.error) { ++stats.fails; ++actstats.fails; } else { ++actstats.done; } } function outward_res_object(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var msg = data.msg; var res = data.res; if (void 0 === data.res) { data.res = null; } var not_object = res != null && !((res && 'object' === typeof res) || res instanceof Error || !!res.meta$ || !!res.entity$ || !!res.force$); // Responding with an Error as data is not allowed. // https://github.com/senecajs/seneca/issues/711 if (data.out instanceof Error) { not_object = true; } var not_legacy = !(msg.cmd === 'generate_id' || msg.note === true || msg.cmd === 'native' || msg.cmd === 'quickcode'); if (so.strict.result && not_legacy && not_object) { data.res = ctx.seneca.private$.error('result_not_objarr', { pattern: ctx.actdef.pattern, args: Util.inspect(Common.clean(msg)).replace(/\n/g, ''), result: res, }); data.meta.error = true; } } function outward_announce(spec) { const ctx = spec.ctx; const data = spec.data; // if (!ctx.actdef) return var meta = data.meta; if (meta.error) { return; } if ('function' === typeof ctx.seneca.on_act_out) { ctx.seneca.on_act_out(ctx.actdef, data.res, data.meta); } ctx.seneca.emit('act-out', data.msg, data.res, data.meta); ctx.seneca.log.debug(ctx.actlog(ctx.actdef, data.msg, data.meta, ctx.origmsg, { kind: 'act', case: 'OUT', duration: ctx.duration, res: data.res, did: ctx.seneca.did, })); } function outward_trace(spec) { const ctx = spec.ctx; const data = spec.data; var private$ = ctx.seneca.private$; var meta = data.meta; var reply_meta = data.reply_meta; if (meta && reply_meta) { meta.trace = meta.trace || []; meta.trace.push({ desc: Common.make_trace_desc(reply_meta), trace: reply_meta.trace || [], }); } var parent_meta = private$.act && private$.act.parent; if (parent_meta) { parent_meta.trace = parent_meta.trace || []; parent_meta.trace.push({ desc: Common.make_trace_desc(meta), trace: meta.trace || [], }); } } function outward_msg_meta(spec) { const data = spec.data; var meta = data.meta; var reply_meta = data.reply_meta; if (meta && reply_meta) { meta.custom = Object.assign(meta.custom, reply_meta.custom); } } function outward_act_error(spec) { const ctx = spec.ctx; const data = spec.data; var delegate = ctx.seneca; var actdef = ctx.actdef; var meta = data.meta; if (meta.error) { data.error_desc = intern.act_error(delegate, ctx, data); if (meta.fatal) { // TODO: this should not happen here inside outward processing return delegate.die(data.error_desc.err); } data.has_callback = data.error_desc.call_cb; if (delegate && 'function' === typeof delegate.on_act_err) { // TODO: data.res does not seem right here delegate.on_act_err(actdef, data.res, meta); } data.err = data.error_desc.err; delete data.err.meta$; data.res = null; data.meta = data.error_desc.err.meta$ || data.meta; } else { data.err = null; } } function outward_res_entity(spec) { const ctx = spec.ctx; const data = spec.data; var delegate = ctx.seneca; if (data.res && data.res.entity$ && delegate.make$) { data.res = delegate.make$(data.res); } } function outward_sub(spec) { const ctx = spec.ctx; const data = spec.data; var meta = data.meta; var private$ = ctx.seneca.private$; // Only entry msg of prior chain is published if (meta.prior) { return; } var submsg = ctx.seneca.util.clean(data.msg); // Find all subscription matches, even partial. // Example: a:1,b:2 matches subs for a:1; a:1,b:1; b:1 var sub_actions_list = private$.subrouter.outward.find(submsg, false, true); submsg.out$ = true; // TODO: document this var result = data.res || data.err || null; for (var alI = 0; alI < sub_actions_list.length; alI++) { var sub_actions = sub_actions_list[alI]; // Also an array. for (var sI = 0; sI < sub_actions.length; sI++) { var sub_action = sub_actions[sI]; try { sub_action.call(ctx.seneca, submsg, result, data.meta); } catch (sub_err) { // DESIGN: this should be all that is needed. return { op: 'stop', out: { kind: 'error', code: 'sub_outward_action_failed', error: sub_err, }, }; } } } } intern.act_error = function (instance, ctx, data) { var duration = ctx.duration; var act_callpoint = ctx.callpoint; var actdef = ctx.actdef || {}; var origmsg = ctx.origmsg; var reply = ctx.reply; var meta = data.meta; var msg = data.msg; var opts = instance.options(); var call_cb = true; var err = data.res || data.err; if (!err.seneca) { var details = Object.assign({}, err.details, { message: err.eraro && err.orig ? err.orig.message : err.message, pattern: actdef.pattern, fn: actdef.func, callback: reply, instance: instance.toString(), callpoint: act_callpoint, }); if (opts.legacy.error) { err = ctx.error(err, 'act_execute', details); } else { var seneca_err = ctx.error('act_execute', { pattern: actdef.pattern, message: err.message, callpoint: act_callpoint, }); delete seneca_err.stack; err.meta$ = err.meta$ || meta || {}; err.meta$.data = instance.util.clean(origmsg); if (err.meta$.err) { var errmeta = Object.assign({}, meta); errmeta.err = seneca_err; err.meta$.err_trace = err.meta$.err_trace || []; err.meta$.err_trace.push(errmeta); } else { err.meta$.err = seneca_err; } } } else if (err.orig && 'string' === typeof err.orig.code && err.orig.code.indexOf('perm/') === 0) { // Special legacy case for seneca-perm err = err.orig; } if (opts.legacy.error) { err.details = err.details || {}; err.details.plugin = err.details.plugin || {}; } var entry = ctx.actlog(actdef, msg, meta, origmsg, { // kind is act as this log entry relates to an action kind: 'act', case: 'ERR', duration: duration, }); entry = ctx.errlog(err, entry); if (null == err.callpoint) { err.callpoint = Common.error.callpoint(err); } instance.log.error(entry); instance.emit('act-err', msg, err); // Seneca 4 arguments instance.emit('act-err-4', 'callback', msg, meta, err); // when fatal$ is set, prefer to die instead if ('function' === typeof opts.errhandler && (!msg || !meta.fatal)) { call_cb = !opts.errhandler.call(instance, err, err.meta$ || meta); } return { call_cb: call_cb, err: err, }; }; const Outward = { test$: { intern: intern }, outward_act_cache, outward_res_object, outward_act_stats, outward_make_error, outward_announce, outward_trace, outward_act_error, outward_res_entity, outward_msg_meta, outward_sub, }; exports.Outward = Outward; //# sourceMappingURL=outward.js.map