Skip to contentVersion [0.5.0]
Added
- Three new presets:
presets.sse, presets.webhooks, presets.public. (#106) The
presets namespace now includes configurations for Server-Sent Events (disables compression
and timeout, restricts to text/event-stream), webhook receivers (requires Idempotency-Key
header, restricts to application/json), and public read-only APIs (restricts to
application/json, enables rate limiting, sets Cache-Control: public, max-age=300).
All presets are deeply frozen RouterOptions objects following the same spread-override
semantics as presets.jsonApi. SSE routes should set noSend: true per-route (route option,
not valid in defaults).
onResponse post-send lifecycle hook at router and route levels. (#140)
Observation callback fired after send() completes. Configurable at router level
(createRouter({onResponse})) for all routes, and/or per-route ({onResponse} in route
config). Both levels fire independently — route-level first, then router-level. Hook
errors are swallowed. Receives (req, res, responseInfo, domainAcc). Does not fire when
catchHandler takes over (error path).
catchHandler now receives domain accumulator as 4th argument. (#105) Custom error
handlers (catchHandler) are now called with (req, res, err, domainAcc) instead of
(req, res, err). The domain accumulator contains route params, parsed body, auth identity,
and other pipeline data available at the time the error was thrown. The accumulator may be
partially populated if the error occurred mid-pipeline. Backwards compatible — existing
3-argument handlers continue to work unchanged.
- Semantic config validation at registration time. (#104) Routes with
body: false and
validate: {body: schema} now throw at registration time instead of producing a guaranteed
500 error on every request. The check uses resolved values (route config > defaults) so
contradictions originating from defaults are also caught. Always throws regardless of
strict setting (same rationale as value type errors).
- New type export:
GracefulLog. (#102) Interface for the logger shape accepted by
graceful() and guaranteed in lifecycle callbacks. Consumers can use GracefulLog to type
a custom logger without extracting it from GracefulOptions.
Changed
- Bumped
@centralping/ergo peer dependency ceiling to >=0.5.0 <0.7.0 (was >=0.5.0 <0.6.0).
Ceiling expanded to include @centralping/ergo@0.6.0.
Fixed
- Declared
@types/node as optional peer dependency for TypeScript consumers. (#103)
TypeScript consumers compiling with skipLibCheck: false received errors from
ergo-router’s .d.ts files because import('node:http') type references require
@types/node. The package is now declared as an optional peer dependency (>= 22,
matching engines.node), following the ecosystem standard used by Express, Fastify,
and Koa. JavaScript-only consumers are unaffected.
- openapi sub-path export now has TypeScript declarations. (#101) The
./openapi sub-path
export was missing its .d.ts file because openapi.js was not included in the
tsconfig.json compilation input. TypeScript consumers importing
@centralping/ergo-router/openapi now get proper type information instead of any.
graceful() callbacks receive non-optional log parameter. (#102) The onStartup and
onShutdown callback context now correctly types log as always-defined (GracefulLog),
matching the runtime behavior where log defaults to console. Previously, log was typed
as GracefulLog | undefined, forcing consumers to use optional chaining or non-null
assertions.
Documentation
- Route Config table now includes all valid config keys. Added
noSend, send, and
catchHandler (Route Option Keys) and idempotency (Pipeline Key) to the README Route
Config table. Previously only Pipeline Keys and Annotation Keys were listed. (#98)
router.use() documented in Route Methods section. Added signature, behavior
description (prepended to every declarative/array pipeline), and the array-pipelines-only
caveat. (#98)
@example in index.js now uses router.listen() instead of raw node:http. (#115)
The package entry point example previously demonstrated http.createServer(router.handle())
which is inconsistent with the README Quick Start and website guides. Updated to use the
built-in router.listen() convenience method.