All versions since [0.1.0-beta.1]
[0.1.0-beta.1]
Changed
- BREAKING: Renamed package from
ergoto@centralping/ergo. - Updated
content-typedependency to v2.0.0 (string-only parse API). - Added TypeScript declaration files (
.d.ts) generated from JSDoc. - Added
CHANGELOG.mdto published npm tarball. - Updated release workflow to support pre-release dist-tags.
[0.1.0-beta.4]
Added
- JSON Schema
formatkeyword support viaajv-formats. Standard formats (email,uri,date-time,uuid, etc.) are validated by default. Opt out withformats: falseor select specific formats with an array (e.g.formats: ['email', 'uri']). (#58)
Fixed
- BREAKING:
accepts()now defaultsthrowIfFailtotrue, enforcing 406 responses for unsatisfied content negotiation per the Fast Fail pipeline contract. SetthrowIfFail: falseto restore the previous informational-only behavior. (#55) body()default types now includeapplication/merge-patch+json(RFC 7386) andapplication/json-patch+json(RFC 6902), resolving 415 rejections for valid PATCH content types that ergo-router’sstrictPatchallows. (#56)validate()params validation now checksacc.route.params(ergo-router convention) with fallback toacc.params(standalone), fixing silent no-op validation when used with ergo-router. (#57)
[0.2.0]
Added
- OpenTelemetry tracing integration.
@opentelemetry/apias a regular dependency with pipeline-level distributed tracing. Newtracing()middleware factory starts anergo.pipelinespan per request, ends it aftersend(), and propagates W3C trace context. Logger automatically includestraceIdandspanIdwhen the tracing middleware is active. Per-stage child spans available viaperStage: trueoption. Zero overhead when the tracing middleware is not included in the pipeline. (#89) - Pipeline debug tracing. Pass
{debug: true}as the second argument tohandler()to enable pipeline tracing. When enabled,responseAcc._traceis initialized with{steps: [], breakAt: undefined}. Thecompose-withserial and concurrent runners record each middleware label instepsand setbreakAtto the label that triggered a pipeline break. On error responses (>= 400),_traceappears as an RFC 9457 extension member. (#86) - compose() accumulator type inference.
compose()now infers the domain accumulator type from[fn, setPath]tuples. For pipelines with 1–12 tuples, TypeScript infers which keys exist on the accumulator and their types. Accessing a key from middleware not in the pipeline is a compile-time error. Pipelines with >12 tuples or only plain functions fall back toPromise<object>.compose.all()has the same overloaded inference. (#87) - Middleware result type exports. New consumer-facing type interfaces for middleware
accumulator values:
UrlResult,BodyResult,CookieJar,LogEntry,AcceptsResult,PreferResult,RateLimitResult,ResponseAccumulator, andMiddlewareTuple. Import from@centralping/ergo/types. (#87) - Hand-written type override system.
types-override/directory holds hand-written.d.tsfiles that replace auto-generated declarations aftertscruns. Used forcompose-with.d.tswhere JSDoc cannot express the required variadic generic types. (#87) - Pagination helpers. New
paginatenamespace export withparseOffsetParams,parseCursorParams,offsetResponse, andcursorResponse. Parses query parameters with bounded defaults, generates RFC 8288 Link headers andX-Total-Count, and returns pipeline-compatible response objects. Available viaimport {paginate} from '@centralping/ergo'orimport {parseOffsetParams} from '@centralping/ergo/lib/paginate'. (#85) - CI type-checking gate validates generated
.d.tsfiles withskipLibCheck: falseandstrict: truevianpm run check-types. Prevents shipping broken type declarations. (#83) - TypeScript usage example alongside the JavaScript Quick Start in
README.md. (#74)
Fixed
formatLinkHeader()now rejects href values containing CR, LF, or NUL characters with aTypeError, preventingERR_INVALID_CHARcrashes when malformed hrefs reachres.setHeader(). (#103)instancefield on all error paths. The RFC 9457instancefield (urn:uuid:{requestId}) is now populated from thex-request-idresponse header on all error paths — pipeline breaks (return-value), caught errors, andendWithProblem(412). Previously,instancewas only populated in thecatchblock, missing the v2 return-value error model entirely. (#95)validate()now emits a one-timeprocess.emitWarningdiagnostic with codeERGO_VALIDATE_UNKNOWN_KEYwhen the schema map contains unrecognized keys (e.g.validate({schemas: {body: ...}})instead ofvalidate({body: ...})). Previously, unrecognized keys were silently ignored and validation became a no-op. (#84)- BREAKING:
validate()now returns a 500 response when a body schema is configured butacc.bodyis absent, indicatingbody()was not placed beforevalidate()in the pipeline. A one-timeprocess.emitWarningdiagnostic is emitted with codeERGO_VALIDATE_NO_BODY. Previously, body validation was silently skipped, allowing invalid request data to reach the execute handler unchecked. Correctly ordered pipelines are unaffected. (#93) - BREAKING:
idempotency()now distinguishes missing from malformedIdempotency-Keyheaders. A malformed header (present but not a valid RFC 8941 sf-string) always returns400with format guidance, regardless of therequiredoption. Previously, a malformed header withrequired: falsesilently passed through as if the header were absent. (#90) - BREAKING (types only): All middleware factory
.d.tsdeclarations now emit inferred function signatures instead ofFunction.compose()/composeWith()return(...args) => Promise<object>instead ofFunction.csrf()andlogger()emit full object types instead ofobject. No runtime behavior changes. (#75) .d.tsdeclarations now compile withskipLibCheck: false. Middleware parameter types forcookie(),cors(),url(), andlib/corsare specific instead of{}. (#83)
[0.3.0]
Added
http/paginate.jsdeclarative pagination middleware factory. Wrapslib/paginate.jsutilities into a pipeline-compatible middleware supporting offset and cursor strategies. Placed in Stage 1 (Negotiation) afterurl. Reads parsed query fromdomainAcc.url.queryand stores structured pagination parameters atacc.paginate. (#114)send()paginateoption. Whentrue, readsdomainAcc.paginateandresponseAcc.paginateto auto-generate RFC 8288 Link headers (first,prev,next,last) andX-Total-Countfor offset pagination responses. Supports both offset and cursor strategies. (#114)'paginate'added toSEND_RESERVEDto prevent pagination metadata from leaking as RFC 9457 extension members. (#114)errorFormatteroption forsend()andhandler(). Pluggable error body formatter forstatusCode >= 400responses. When provided, receives the RFC 9457 Problem Details object (plain object) and{requestId, statusCode, method}context. The return value becomes the response body, serialized asapplication/jsoninstead ofapplication/problem+json. Applies to both the main error path and 412 conditional responses (endWithProblem). Teams with existing error contracts can adopt ergo without changing their client-facing error format. (#110)redactErrorsoption forhandler(). Controls whether caught 5xx exception messages appear in the RFC 9457 responsedetailfield. Defaults totrue(secure — generic status text only). Set tofalseduring development to surfaceerr.messagein error responses without exposing stack traces. (#109)- Typed middleware options and results. All 21 middleware factory functions now have
hand-written
.d.tsoverrides intypes-override/http/with named options interfaces (AcceptsOptions,BodyOptions,CorsOptions,ValidateOptions, etc.) and precise return types. Consumers get autocomplete and type-checking for factory parameters and pipeline accumulator values withoutas anycasts. Import options/result types from@centralping/ergo/types. (#108) - New result type interfaces:
AuthorizationResult,TracingResult,IdempotencyResult. (#108) - New utility types:
AjvFormatName(26-member string literal union tracking ajv-formats 3.x),AuthorizationStrategy,ValidateSchemas,CookieJar(now includes jar methods). (#108) types-override/http/main.d.tsoverride provides typed re-exports for all middleware,httpErrors,fromConnect, andpaginatenamespace. (#108)
Changed
- Breaking:
paginateexport from@centralping/ergochanged fromlib/paginate.jsutility namespace ({parseOffsetParams, parseCursorParams, offsetResponse, cursorResponse}) tohttp/paginate.jsfactory function. Consumers usingpaginate.parseOffsetParams()must switch to deep import:import {parseOffsetParams} from '@centralping/ergo/lib/paginate'. (#114)
Fixed
envelopecallback type signature corrected. Changed from(body: unknown, statusCode: number) => unknownto(body: unknown, ctx: {requestId: string; statusCode: number; method: string}) => unknownto match the actual implementation which passes a context object, not a bare status code. AffectsSendOptionsandHandlerOptions. (#110)PreferResultnow matches runtime. Corrected from{[k: string]: {value?: string}}to{[k: string]: string | true}— the runtime returns flat preference values, not wrapped objects. (#108)CookieJarnow includes jar methods. Addedset(),get(),clear(),toHeader(),size, andisJarto match the actual cookie jar API. Previously typed as a bare index signature. (#108)LogEntrynow includes trace correlation fields. Added optionaltraceIdandspanIdproperties populated when the tracing middleware is active. (#108)
Removed
RateLimitResultremoved. The rate-limit middleware only returns{response: {headers}}— it never stores a domain accumulator value. The interface described a shape that did not exist at runtime. (#108)
[0.4.0]
Changed
- BREAKING: Middleware composition uses config objects instead of tuples. (#117)
Domain-producing middleware now uses
{fn, setPath}config objects instead of[fn, setPath]tuples. Response-only middleware (cors, securityHeaders, cacheControl, rateLimit, precondition, validate, jsonApiQuery) are plain functions — no wrapper needed.normalizeOp()now discriminates viatypeof op === 'function'(wasArray.isArray)MiddlewareTupletype renamed toMiddlewareOpwith{fn, setPath}shape- All 20 middleware inner functions are now named (
fn.nameprovides trace labels) - Migration:
[myFn(), 'key']→{fn: myFn(), setPath: 'key'}
Fixed
- handler.js JSDoc and
HandlerOptionstype now document thepaginateoption forwarded tosend(). (#118)
[0.4.1]
Added
- Factory-time option key validation with Levenshtein suggestions. (#126)
All 18 middleware factories now validate incoming option keys at factory invocation
time via a shared
lib/validate-options.jsutility. Unknown keys emit a deduplicatedprocess.emitWarningwith{type: 'ErgoWarning'}and a “did you mean?” suggestion when the Levenshtein edit distance is within threshold.handler()validates the union of its own keys andsend()keys;send()validates independently. timingoption onhandler()forX-Response-Timeheader. (#127) Passtiming: truefor defaults ortiming: {header?, precision?}for custom configuration. Measures the full request lifecycle (pipeline + error handling + send) via ares.writeHeadinterception. Zero overhead when disabled (default). Shared primitivelib/response-time.jsavailable for deep import by@centralping/ergo-router.
Changed
- README TypeScript Quick Start updated to reflect shipped type infrastructure. (#131)
Removed the forward-looking caveat about future type inference improvements — all
prerequisite features have shipped (compose overloads #87, typed middleware #108,
ergo-router accumulator inference ergo-router#91). Simplified the TS example by removing
the
AuthResultinterface and explicitIncomingMessage/ServerResponseimports. Replaced the caveat with a factual note explaining whenaccannotations are needed (standalonecompose()with interleaved bare functions) and directing users to@centralping/ergo-router’sdefineGet/definePosthelpers for annotation-free inference.