* Remove extra 'resources' landing page, redirect from main one * Move custom plugins file to its own directory, add redirect to handle * docs: split the custom plugins page into one page per feature * docs: extend decorators explanation and link to it from the custom plugins section * docs: Fix all the links that were broken when I moved things * Apply excellent suggestions from code review Co-authored-by: Heather Cloward <heathercloward@gmail.com> * docs: Add examples of how to use the custom rule * docs: Replace the nested visitor example with an object rather than a function * Update custom-rules.md minor consistency edits * Apply suggestions from code review Co-authored-by: Heather Cloward <heathercloward@gmail.com> * docs: clearer explanation of skip, and finish a broken sentence * Update docs/custom-plugins/index.md Co-authored-by: Heather Cloward <heathercloward@gmail.com> * Apply suggestions from code review Co-authored-by: Adam Altman <adam@redoc.ly> * docs: use object rather than function for visitor --------- Co-authored-by: Heather Cloward <heathercloward@gmail.com> Co-authored-by: Adam Altman <adam@redoc.ly>
2.8 KiB
Type extensions in plugins
Redocly CLI in its core has a type tree which defines the structure of the API definition. Redocly CLI then uses it to do a type-aware traversal of an OpenAPI definition.
The type tree is built from top level Types which can link to child types. For example, here is a visual reference to the OpenAPI types structure. You can also check the code itself for information about specific versions of OpenAPI and other supported document types.
The type tree can be extended by exporting the typeExtension function from a custom plugin.
Type extension example
Consider an OpenAPI that uses an (imaginary) specification extension x-metadata which must contain information about the lifecycle state of the API, and which team owns the API. A snippet of the OpenAPI to show the example clearly:
openapi: 3.1.0
info:
title: Food Empire API
version: 0.5.1
x-metadata:
lifecycle: production
owner-team: Engineering/Integrations
Define the type extension for the new x-metadata section, in this example, we make the lifecycle field required.
const XMetaData = {
properties: {
lifecycle: { type: 'string', enum: ['development', 'staging', 'production']},
'owner-team': { type: 'string'},
},
required: ['lifecycle']
};
Note the quotes around the owner-team key since it contains a hyphen -. These fields are strings but you can also define other data structures if you need to represent something more complex. The built-in type definitions are a good place to look for examples.
To include the new type in the type tree, the plugin must add the type and modify the parent type, which in this example is info. This is done by returning a typeExtension structure, as shown in the example below (this example is in plugins/example-type-extension.js, this filename is used again in the configuration example later):
module.exports = {
id: 'example-type-extension',
typeExtension: {
oas3(types) {
return {
...types,
XMetaData: XMetaData,
Info: {
...types.Info,
properties: {
...types.Info.properties,
'x-metadata': 'XMetaData',
}
}
};
}
}
};
You can use the new type immediately to check the validity of your API document. First, include the plugin in redocly.yaml and enable the spec rule:
extends: []
plugins:
- 'plugins/example-type-extension.js'
rules:
spec: warn
Now lint your API definition with redocly lint openapi.yaml and try removing the lifecycle field from within the x-metadata section. It's a required field, so you see an error if it's missing.