Middleware
A pluggable observer attached to every trigger in a runtime. The seven hooks fire at predictable points around dispatch — three of them (onFire, onSkip, onError) often pair to form a complete audit trail; the others (onBeforeMatch, onActionStart, onActionEnd, onCascade) are for tracing, metrics, and devtools.
All hooks are optional. Throwing inside a hook is caught and logged by the runtime but does not abort the run — middleware must not be load-bearing.
Import
Section titled “Import”Definition
Section titled “Definition”name — string
Section titled “name — string”Stable id for the middleware. Required. Useful in error messages and devtools panels.
onFire(ctx) -> void | { cancel: true; reason: string }
Section titled “onFire(ctx) -> void | { cancel: true; reason: string }”Called once per top-level (or cascade) fire(eventName, payload) before any trigger is matched. Return { cancel: true, reason } to abort the entire dispatch — no triggers run and an 'overflow'-style record is not emitted. This is the only short-circuit hook.
FireContext field | Description |
|---|---|
eventName | The event being dispatched. |
payload | The payload, opaque to middleware. |
cascadeDepth | 0 for top-level fires; n inside a cascade. |
parentRunId? | Set when the fire happens inside a running handler. |
parentTriggerId? | Same — id of the upstream trigger. |
parentContext? | Opaque linked-list reference for cycle detection. |
onBeforeMatch(ctx) -> void
Section titled “onBeforeMatch(ctx) -> void”Called once per (event, trigger) pair right after dispatch picks the trigger out of the event index — before any concurrency gate or required check. Purely observational; useful for “which triggers were considered for this event” without instrumenting onSkip and onActionStart separately.
onSkip(ctx) -> void
Section titled “onSkip(ctx) -> void”Called when a trigger is matched but skipped. reason is one of 'disabled', 'required-missing', 'concurrency-take-first', 'aborted', 'cycle', 'overflow', etc. Use this to track “why didn’t my trigger run”.
onActionStart(ctx) -> void
Section titled “onActionStart(ctx) -> void”Called immediately before an action is invoked by a handler. actionName and payload are the arguments. Use for per-action tracing.
onActionEnd(ctx & { durationMs; result? }) -> void
Section titled “onActionEnd(ctx & { durationMs; result? }) -> void”Called when the action returns (or its returned promise resolves). durationMs is the wall-clock time from onActionStart to onActionEnd. The runtime only measures this when at least one middleware listens — there’s no cost when no middleware needs timing.
onError(ctx & { error }) -> void
Section titled “onError(ctx & { error }) -> void”Called when an action throws or its promise rejects. Pair with onActionStart to bracket a full attempt. Errors are also recorded on the inspector snapshot with status: 'errored'.
onCascade(ctx) -> void
Section titled “onCascade(ctx) -> void”Called when a cascade event is suppressed — kind: 'overflow' (cascadeDepth exceeded maxCascadeDepth) or kind: 'cycle' (a trigger appears in its own ancestor chain).