@polygonlabs/openapi-registry@3.0.0
Major Changes
-
#81
9edc162Thanks @MaximusHaximus! -registerPathnow rejects coercing schemas (z.coerce.*) in parameter positionsBreaking change
TypedRegistry.registerPaththrows at generate time whenrequest.params,request.query, orrequest.headerscontains a coercing schema (z.coerce.number(),z.coerce.date(), …), including when wrapped in.optional()/.default()/.nullable().Why: in zod v4 a coercing schema's input type is
unknown, so the generated OpenAPI marks the parameterrequired: false, nullable: trueregardless of the author's intent — a required parameter silently documents as optional-and-nullable, and every codegen consumer inherits the misdocumented contract. The audit turns that silent corruption into a loud error on the engineer's machine, in the same spirit as the sealed shared-registry conflict check.Migration
- Parameter converted by the server binding: declare the logical type plainly —
z.coerce.number().int()→z.number().int(). - Wire string with a different runtime type: use a codec that declares both sides — e.g.
Int64Codec/IsoDateCodecfrom@polygonlabs/zod-codecs. Codecs (z.codec(...)) are unaffected by the audit. - Request bodies are not audited — JSON bodies carry typed values on the wire.
The check is also exported directly as
assertNoCoercingParamSchemasfor use outsideTypedRegistry. - Parameter converted by the server binding: declare the logical type plainly —
Minor Changes
-
#81
0fcf6b3Thanks @MaximusHaximus! - Make the auto-injected standard error responses configurable per registrynew TypedRegistry({ standardErrorResponses })now controls the framework-emitted error responses injected into everyregisterPathcall:false— inject nothing; every route documents exactly the responses it declares.{ serverError?, validationError?, notAuthenticated? }— override the schema for individual slots; omitted slots keep their defaults.- Omitted — unchanged default behaviour.
The default shapes document
@polygonlabs/express's error middleware, which is correct for services using it but wrong for any other producer: a spec authored with this registry for a non-Express backend would otherwise advertise 500/400/401 shapes its server never emits, and the injectedErrorResponsecomponent name can collide with the service's own same-named schema of a different shape. The injection rules (when a 400/401/500 is added) are unchanged — only the shapes are configurable.The option is mirrored at the type level: the
Opsaccumulator reports the configured schema types (or omits the slots entirely underfalse), soOperationsOfconsumers and codegen'd clients see the shapes the runtime registry actually holds.inferStandardErrorResponsesaccepts the same options as an optional second argument; existing single-argument calls are unaffected.