UNPKG

seneca

Version:

A Microservices Framework for Node.js

414 lines 13.8 kB
"use strict"; /* Copyright © 2010-2023 Richard Rodger and other contributors, MIT License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Inward = void 0; const common_1 = require("./common"); const intern = {}; function inward_msg_modify(spec) { const ctx = spec.ctx; const data = spec.data; var meta = data.meta; if (ctx.actdef) { var fixed = ctx.actdef.fixed; var custom = ctx.actdef.custom; if (fixed) { Object.assign(data.msg, fixed); } if (custom) { meta.custom = meta.custom || {}; Object.assign(meta.custom, custom); } } } function inward_limit_msg(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var meta = data.meta; if (meta.parents && so.limits.maxparents < meta.parents.length) { return { op: 'stop', out: { kind: 'error', code: 'maxparents', info: { maxparents: so.limits.maxparents, numparents: meta.parents.length, parents: meta.parents.map((p) => p[common_1.TRACE_PATTERN] + ' ' + p[common_1.TRACE_ACTION]), args: (0, common_1.inspect)((0, common_1.clean)(data.msg)).replace(/\n/g, ''), }, }, }; } } function inward_announce(spec) { const ctx = spec.ctx; const data = spec.data; if (!ctx.actdef) return; // Only intended for use in a per-delegate context. if ('function' === typeof ctx.seneca.on_act_in) { ctx.seneca.on_act_in(ctx.actdef, data.msg, data.meta); } ctx.seneca.emit('act-in', data.msg, null, data.meta); } // TODO: allow if not a top level call - close gracefully function inward_closed(spec) { const ctx = spec.ctx; const data = spec.data; if (ctx.seneca.flags.closed && !data.meta.closing) { return { op: 'stop', out: { kind: 'error', code: 'closed', info: { args: (0, common_1.inspect)((0, common_1.clean)(data.msg)).replace(/\n/g, ''), }, }, }; } } function inward_act_stats(spec) { const ctx = spec.ctx; if (!ctx.actdef) { return; } var private$ = ctx.seneca.private$; ++private$.stats.act.calls; var pattern = ctx.actdef.pattern; var actstats = (private$.stats.actmap[pattern] = private$.stats.actmap[pattern] || {}); ++actstats.calls; } function inward_act_default(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var msg = data.msg; var meta = data.meta; // TODO: existence of pattern action needs own indicator flag if (!ctx.actdef) { var default$ = meta.dflt || (!so.strict.find ? {} : meta.dflt); if (null != default$ && ('object' === typeof default$ || Array.isArray(default$))) { return { op: 'stop', out: { kind: 'result', result: default$, log: { level: 'debug', data: { kind: 'act', case: 'DEFAULT', }, }, }, }; } else if (null != default$) { return { op: 'stop', out: { kind: 'error', code: 'act_default_bad', info: { args: (0, common_1.inspect)((0, common_1.clean)(msg)).replace(/\n/g, ''), xdefault: (0, common_1.inspect)(default$), }, }, }; } } } function inward_act_not_found(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var msg = data.msg; // console.log('NO ACTDEF', ctx.actdef, msg, data) if (!ctx.actdef) { return { op: 'stop', out: { kind: 'error', code: 'act_not_found', info: { args: (0, common_1.inspect)((0, common_1.clean)(msg)).replace(/\n/g, '') }, log: { level: so.trace.unknown ? 'warn' : 'debug', data: { kind: 'act', case: 'UNKNOWN', }, }, }, }; } } function inward_validate_msg(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var msg = data.msg; var err = null; if (so.valid.active && so.valid.message) { if (ctx.actdef.gubu) { // TODO: gubu option to provide Error without throwing // TODO: how to expose gubu builders, Required, etc? // TODO: use original msg for error try { data.msg = ctx.actdef.gubu(msg); } catch (e) { err = e; } } else if ('function' === typeof ctx.actdef.validate) { // FIX: this is assumed to be synchronous // seneca-parambulator and seneca-joi need to be updated ctx.actdef.validate(msg, function (verr) { err = verr; }); } } if (err) { return { op: 'stop', out: { kind: 'error', code: so.legacy.error_codes ? 'act_invalid_args' : 'act_invalid_msg', info: { pattern: ctx.actdef.pattern, message: err.message, msg: (0, common_1.clean)(msg), error: err, props: err.gubu ? err.props : [], }, log: { level: so.trace.invalid ? 'warn' : null, data: { kind: 'act', case: 'INVALID', }, }, }, }; } } // Check if actid has already been seen, and if action cache is active, // then provide cached result, if any. Return true in this case. function inward_act_cache(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; 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) { private$.stats.act.cache++; var latest = actdetails.result[actdetails.result.length - 1] || {}; var out = { op: 'stop', out: { kind: latest.err ? 'error' : 'result', result: latest.res || null, error: latest.err || null, log: { level: 'debug', data: { kind: 'act', case: 'CACHE', cachetime: latest.when, }, }, }, }; ctx.cached$ = true; return out; } } } function inward_warnings(spec) { const ctx = spec.ctx; const data = spec.data; var so = ctx.options; var msg = data.msg; if (so.debug.deprecation && ctx.actdef.deprecate) { ctx.seneca.log.warn({ kind: 'act', case: 'DEPRECATED', msg: msg, pattern: ctx.actdef.pattern, notice: ctx.actdef.deprecate, callpoint: ctx.callpoint, }); } } function inward_msg_meta(spec) { const ctx = spec.ctx; const data = spec.data; var meta = data.meta; meta.pattern = ctx.actdef.pattern; meta.client_pattern = ctx.actdef.client_pattern; meta.action = ctx.actdef.id; meta.plugin = Object.assign({}, meta.plugin, ctx.actdef.plugin); meta.start = null == meta.start ? ctx.start : meta.start; meta.parents = meta.parents || []; meta.trace = meta.trace || []; var parent = ctx.seneca.private$.act && ctx.seneca.private$.act.parent; // Use parent custom object if present, // otherwise use object provided by caller, // otherwise create a new one. // This preserves the same custom object ref throughout a call chain. var parentcustom = (parent && parent.custom) || meta.custom || {}; if (parent) { meta.parents = meta.parents.concat(parent.parents || []); meta.parents.unshift((0, common_1.make_trace_desc)(parent)); } meta.custom = Object.assign(parentcustom, meta.custom, ctx.seneca.fixedmeta && ctx.seneca.fixedmeta.custom); // meta.explain is an array that explanation objects can be appended to. // The same array is used through the action call tree, and must be provided by // calling code at the top level via the explain$ directive. if (data.msg.explain$ && Array.isArray(data.msg.explain$)) { meta.explain = data.msg.explain$; } else if (parent && parent.explain) { meta.explain = parent.explain; } if (ctx.seneca.private$.explain) { meta.explain = meta.explain || []; ctx.seneca.private$.explain.push(meta.explain); } } function inward_prepare_delegate(spec) { const ctx = spec.ctx; const data = spec.data; const meta = data.meta; const plugin = ctx.seneca.private$.plugins[meta.plugin.fullname]; if (plugin) { ctx.seneca.plugin = plugin; ctx.seneca.shared = plugin.shared; } ctx.seneca.fixedargs.tx$ = data.meta.tx; data.reply = data.reply.bind(ctx.seneca); data.reply.seneca = ctx.seneca; const reply = data.reply; // DEPRECATE ctx.seneca.good = function good(out) { ctx.seneca.log.warn('seneca.good is deprecated and will be removed in 4.0.0'); reply(null, out); }; // DEPRECATE ctx.seneca.bad = function bad(err) { ctx.seneca.log.warn('seneca.bad is deprecated and will be removed in 4.0.0'); reply(err); }; ctx.seneca.reply = function reply(err, out) { reply(err, out); }; ctx.seneca.explain = intern.explain.bind(ctx.seneca, meta); if (meta.explain) { ctx.seneca.explain({ explain$: true, msg$: (0, common_1.clean)(data.msg) }); } } function inward_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.inward.find(submsg, false, true); submsg.in$ = true; 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, null, data.meta); } catch (sub_err) { // DESIGN: this should be all that is needed. return { op: 'stop', out: { kind: 'error', code: 'sub_inward_action_failed', error: sub_err, }, }; } } } } intern.explain = function (meta, entry) { var orig_explain = this.explain; var explain = meta.explain; if (true === entry || false === entry) { return orig_explain.call(this, entry); } else if (explain) { if (null != entry) { if (entry.explain$) { entry.explain$ = { start: meta.start, pattern: meta.pattern, action: meta.action, id: meta.id, instance: meta.instance, tag: meta.tag, seneca: meta.seneca, version: meta.version, gate: meta.gate, fatal: meta.fatal, local: meta.local, closing: meta.closing, timeout: meta.timeout, dflt: meta.dflt, custom: meta.custom, plugin: meta.plugin, prior: meta.prior, caller: meta.caller, parents: meta.parents, remote: meta.remote, sync: meta.sync, trace: meta.trace, sub: meta.sub, data: meta.data, err: meta.err, err_trace: meta.err_trace, error: meta.error, empty: meta.empty, }; } explain.push(entry && 'object' === typeof entry ? entry : { content: entry }); } } return explain && this.explain; }; let Inward = { inward_msg_modify, inward_closed, inward_act_cache, inward_act_default, inward_act_not_found, inward_validate_msg, inward_warnings, inward_msg_meta, inward_limit_msg, inward_act_stats, inward_prepare_delegate, inward_announce, inward_sub, intern, }; exports.Inward = Inward; //# sourceMappingURL=inward.js.map