CLI diagnostics go to stderr
Without -o, bin/openapi writes the document to stdout, and its warnings went there too, so openapi src > openapi.yaml put them into the file ahead of the YAML. Diagnostics now go to stderr, and stdout carries only the document.
A script that reads warnings from stdout has to read stderr instead. With -o, warnings used to be the only thing on stdout, so a check like openapi src -o openapi.yaml | grep -q warning && exit 1 worked. It now finds nothing and passes. Read both streams with 2>&1.
An operation's security: [] is kept
An operation opts out of a root security requirement with security: []. Spec and hybrid modes dropped the empty list as if it were unset, so the operation documented as requiring the root's authentication. It is now emitted. Classic mode was not affected.
Spec pipeline
One component: key on every reusable attribute
Each reusable OpenApi\Spec attribute names the key it is filed under with component:, in place of a field spelled after its own type. PathItem and MediaType take it too, and can now be reused: a keyed PathItem is a components.pathItems entry from 3.1, and a keyed MediaType a components.mediaTypes entry from 3.2. See Components.
The old spellings keep working and produce the same document. Used as a component key, schema:, parameter:, request:, securityScheme:, response:, header:, link: and example: now trigger a deprecation, and are removed in 8.0. Only their use as a component key is deprecated: response: 404 on a nested response is the nesting key and stays. Classic attributes report nothing.
A schema's title is no longer used as its component key; a schema with no key is reported.
Contributing to a document before resolution
Builder::withSpecification() hands the assembled Specification to a callable after the scan and before resolution. What it adds is resolved, augmented and compiled with the scanned sources, so a $ref in a contribution resolves. That makes it the place for metadata with nothing to scan: an entity registry, a serializer's configuration, another library's attributes. See Extension points.
Two attributes for one key: one survives, and it is reported
Two operations on the same path and method, or two schemas with the same key, used to be settled by the compiler, which kept whichever it wrote last and said nothing. A merger pass now applies one rule to every root collection: the later entry wins, and the collision is reported with both locations. Builder::withMergers() takes your own mergers ahead of it, and getMeta()/setMeta() on every attribute lets a package mark its contributions so its merger can recognise them.
One output change: for two PathItems on the same path, the later one now wins, as everything else does. It used to be the first.
Result now also carries what the spec pipeline logged during the build, not only the compiler's diagnostics.
A clearer ambiguous-merge error
An attribute that matches more than one sibling on the same target, such as a Header stacked beside two Responses, now says what to do about it: nest it in the one it belongs to, or give it a component and reference it from each.
Changes
- feat(Builder): add withSpecification(), a contribution seam before resolution by @DerManoMann in #2218
- chore(deps-dev): bump @redocly/cli from 2.53.3 to 2.54.3 in the npm group across 1 directory by @dependabot[bot] in #2221
- feat(Spec): add component:, one key field on every reusable attribute by @DerManoMann in #2219
- fix(Assembler): say what to do about an ambiguous merge by @DerManoMann in #2222
- feat(Builder): a merger registry, and one entry per key in the Specification by @DerManoMann in #2220
- fix(Compiler): keep an operation's explicit security: [] instead of dropping it as unset by @DerManoMann in #2223
- fix(Console): send diagnostics to stderr, so they stay out of the document on stdout by @DerManoMann in #2224
- fix(Spec): date the component: key deprecations to 6.12, the release that ships them by @DerManoMann in #2230
Full Changelog: 6.11.0...6.12.0