Problem
engine.registerHook(event, handler) accepts an event name the engine never dispatches. It logs a warning, registers the handler anyway, and the handler silently never runs.
The engine dispatches beforeFind / afterFind and the insert / update / delete pairs. beforeFind covers both find and findOne. count() and aggregate() dispatch no hook: they run through the middleware chain only, with the query AST on the operation context.
A downstream consumer registered read filters on beforeFindOne and beforeCount, expecting them to scope single-record reads and list totals. They sat inert through every boot, with about 40 "never dispatches" warnings per boot. The effect:
- Single-record reads were still filtered, because
beforeFind covers findOne.
count was not. A limited list returned a total counting rows the caller could not see.
aggregate was not either. A groupBy query was not narrowed by the filter at all.
Proposal
- Refuse at registration when the event is outside the dispatchable set, in line with ADR-0078 ("no silently inert metadata"). At minimum, make the warning an error in strict or test mode.
- Name the seam in the message. For
beforeCount and beforeFindOne specifically, say that beforeFind already covers findOne, and that count / aggregate filtering belongs in middleware (operation: 'count' | 'aggregate').
- Document in the hook reference that read filters written as hooks do not apply to
count / aggregate, and show the middleware equivalent.
Acceptance
- Registering an undispatchable event fails loudly: it throws, or at least fails in strict mode.
- A test covers each event name that the engine exposes but never dispatches.
- The hook documentation lists which operations each event covers.
Problem
engine.registerHook(event, handler)accepts an event name the engine never dispatches. It logs a warning, registers the handler anyway, and the handler silently never runs.The engine dispatches
beforeFind/afterFindand the insert / update / delete pairs.beforeFindcovers bothfindandfindOne.count()andaggregate()dispatch no hook: they run through the middleware chain only, with the query AST on the operation context.A downstream consumer registered read filters on
beforeFindOneandbeforeCount, expecting them to scope single-record reads and list totals. They sat inert through every boot, with about 40 "never dispatches" warnings per boot. The effect:beforeFindcoversfindOne.countwas not. Alimited list returned atotalcounting rows the caller could not see.aggregatewas not either. AgroupByquery was not narrowed by the filter at all.Proposal
beforeCountandbeforeFindOnespecifically, say thatbeforeFindalready coversfindOne, and thatcount/aggregatefiltering belongs in middleware (operation: 'count' | 'aggregate').count/aggregate, and show the middleware equivalent.Acceptance