feat: support rule/ as a prefix for configurable rules (#1062)

* feat: support rule/ as a prefix for configurable rules

* chore: Run prettier

* feat: Add a warning about use of the old syntax

* docs: update configurable rules doc to reflect updated rule/ notation

* Update packages/core/src/config/config-resolvers.ts

Co-authored-by: Andrew Tatomyr <andrew.tatomyr@redocly.com>

* chore: run prettier

* chore: move deprication warning inside config transformer

---------

Co-authored-by: Andrew Tatomyr <andrew.tatomyr@redocly.com>
This commit is contained in:
Lorna Jane Mitchell
2023-05-30 09:57:30 +01:00
committed by GitHub
parent 04ff9e53d7
commit 3e287a80eb
62 changed files with 377 additions and 352 deletions

View File

@@ -2,5 +2,5 @@ apis:
main:
root: ./test.yaml
extends:
extends:
- recommended

View File

@@ -2,5 +2,5 @@ apis:
main:
root: ./test.yaml
extends:
extends:
- recommended

View File

@@ -4,5 +4,5 @@ apis:
bar:
root: ./bar.yaml
extends:
extends:
- recommended

View File

@@ -5,4 +5,4 @@ apis:
decorators:
plugin/resolve-x: on
plugins:
- "./plugin.js"
- './plugin.js'

View File

@@ -17,6 +17,8 @@ Error was generated by the configuration spec rule.
❌ Your config has 1 error.
The 'assert/' syntax in assert/path-item-mutually-required is deprecated. Update your configuration to use 'rule/' instead. Examples and more information: https://redocly.com/docs/cli/rules/configurable-rules/
validating ../__fixtures__/valid-openapi.yaml...
../__fixtures__/valid-openapi.yaml: validated in <test>ms

View File

@@ -5,5 +5,5 @@ apis:
rules:
context:
extends:
extends:
- recommended

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-mutually-required:
subject:
rule/path-item-mutually-required:
subject:
type: Operation
assertions:
defined: true

View File

@@ -1,13 +1,13 @@
apis:
main:
root: ./openapi.yaml
plugins:
- ./plugin.js
rules:
assert/minLength:
subject:
rule/minLength:
subject:
type: Schema
assertions:
local/checkSchema:
local/checkSchema:
required: minLength

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/named-parameters-camelCase:
rule/named-parameters-camelCase:
subject:
type: NamedParameters
message: Parameters must use camelCase

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-get:
subject:
rule/operation-get:
subject:
type: Operation
filterInParentKeys: [get]
property: operationId
@@ -13,17 +13,16 @@ rules:
casing: camelCase
message: Operation id for get operation should be camelCase
assert/operation-id-camel-case:
rule/operation-id-camel-case:
subject:
type: Operation
property: operationId
message: Operation id should be camelCase
assertions:
assertions:
casing: camelCase
assert/camel-case-on-value:
subject:
rule/camel-case-on-value:
subject:
type: NamedParameters
assertions:
casing: camelCase

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-get:
rule/operation-get:
subject:
type: Operation
property: operationId
@@ -12,7 +12,7 @@ rules:
casing: kebab-case
message: Operation id should be kebab-case
assert/operation-id-kebab-case:
rule/operation-id-kebab-case:
subject:
type: Operation
property: operationId

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-get:
rule/operation-get:
subject:
type: Operation
property: operationId
@@ -12,7 +12,7 @@ rules:
casing: PascalCase
message: Operation id should be PascalCase
assert/operation-id-pascal-case:
rule/operation-id-pascal-case:
subject:
type: Operation
property: operationId

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-id-pascal-case:
subject:
rule/operation-id-pascal-case:
subject:
type: Operation
property: operationId
filterInParentKeys: [get]
@@ -12,10 +12,10 @@ rules:
assertions:
casing: PascalCase
assert/operation-id-snake-case:
subject:
rule/operation-id-snake-case:
subject:
type: Operation
property: operationId
message: Operation id should be snake_case
assertions:
assertions:
casing: snake_case

View File

@@ -4,15 +4,15 @@ apis:
plugins:
- ./plugin.js
rules:
assert/operation-summary-length-custom:
subject:
rule/operation-summary-length-custom:
subject:
type: Operation
property: summary
message: Custom message {{problems}}
assertions:
minLength: 16
local/checkWordsStarts:
words:
local/checkWordsStarts:
words:
- Create
- Retrieve
- Merge
@@ -22,18 +22,17 @@ rules:
- Update
- Approve
- Reject
local/checkWordsCount:
local/checkWordsCount:
min: 3
assert/operation-summary-length:
subject:
rule/operation-summary-length:
subject:
type: Operation
property: summary
assertions:
assertions:
minLength: 16
local/checkWordsStarts:
words:
local/checkWordsStarts:
words:
- Create
- Retrieve
- Merge
@@ -43,18 +42,18 @@ rules:
- Update
- Approve
- Reject
local/checkWordsCount:
local/checkWordsCount:
min: 3
assert/operation-summary-length-with-where:
rule/operation-summary-length-with-where:
where:
- subject:
- subject:
type: Operation
property: summary
assertions:
local/checkWordsCount:
local/checkWordsCount:
min: 3
subject:
subject:
type: Schema
property: type
assertions:

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/response-content-defined:
rule/response-content-defined:
subject:
type: Response
property: content
@@ -11,7 +11,7 @@ rules:
message: Response content should be defined
assertions:
defined: true
assert/operation-security:
rule/operation-security:
subject:
type: Operation
property: security

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-summary-value:
rule/operation-summary-value:
subject:
type: Operation
property: summary
@@ -13,5 +13,5 @@ rules:
- test example
assertions:
enum:
- test summary
- test example
- test summary
- test example

View File

@@ -3,10 +3,10 @@ apis:
root: ./openapi.yaml
rules:
assert/media-type-application-json:
rule/media-type-application-json:
subject:
type: MediaTypesMap
message: Only application/json can be used
assertions:
assertions:
enum:
- application/json
- application/json

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/tag-description-pattern:
subject:
rule/tag-description-pattern:
subject:
type: Tag
property: description
message: Tag description must be at least 13 characters and end with a full stop.
@@ -13,22 +13,22 @@ rules:
minLength: 13
pattern: /\.$/
# property example
assert/path-item-get-defined:
subject:
rule/path-item-get-defined:
subject:
type: PathItem
property: get
message: Every path item must have a GET operation.
assertions:
assertions:
defined: true
assert/path-item-get-required:
subject:
rule/path-item-get-required:
subject:
type: PathItem
message: Every path item must have a GET(required) operation.
assertions:
required:
- get
assert/tag-name-and-desc:
subject:
- get
rule/tag-name-and-desc:
subject:
type: Tag
property:
- name
@@ -37,14 +37,14 @@ rules:
assertions:
defined: true
# context example
assert/operation-w-context:
rule/operation-w-context:
subject:
type: MediaTypesMap
where:
- subject:
type: Operation
filterOutParentKeys:
- put
- put
assertions:
defined: true
- subject:
@@ -53,20 +53,20 @@ rules:
assertions:
defined: true
assertions:
disallowed: [ 'application/pdf' ]
disallowed: ['application/pdf']
message: Media type should not be pdf
# enum example
assert/media-type-pdf:
subject:
rule/media-type-pdf:
subject:
type: MediaTypesMap
message: Only application/pdf can be used
severity: error
assertions:
enum:
- application/pdf
assert/operation-summary-suggest:
subject:
- application/pdf
rule/operation-summary-suggest:
subject:
type: Operation
property: summary
message: Summary must be one of the predefined values
@@ -74,13 +74,13 @@ rules:
- change to 'My resource'
- change to 'My collection'
severity: error
assertions:
assertions:
enum:
- My resource
- My collection
- My resource
- My collection
# pattern example
assert/operation-summary-pattern:
subject:
rule/operation-summary-pattern:
subject:
type: Operation
property: summary
message: Summary should match a regex
@@ -88,8 +88,8 @@ rules:
assertions:
pattern: /resource/
# casing
assert/operation-id-camel-case:
subject:
rule/operation-id-camel-case:
subject:
type: Operation
property: operationId
message: NamedExamples key must be in camelCase
@@ -97,17 +97,17 @@ rules:
assertions:
casing: camelCase
# mutuallyExclusive example
assert/operation-mutually-exclusive:
subject:
rule/operation-mutually-exclusive:
subject:
type: Operation
message: "Operation must not define both properties together: description and externalDocs"
message: 'Operation must not define both properties together: description and externalDocs'
severity: error
assertions:
mutuallyExclusive:
- description
- externalDocs
- description
- externalDocs
# mutuallyRequired example
assert/operation-mutually-required:
rule/operation-mutually-required:
subject:
type: SchemaProperties
where:
@@ -117,78 +117,78 @@ rules:
defined: true
message: The created_at and updated_at properties are mutually required
severity: error
assertions:
assertions:
mutuallyRequired:
- created_at
- updated_at
- created_at
- updated_at
# mutuallyRequired example with context
assert/operation-mutually-required-w-context:
subject:
rule/operation-mutually-required-w-context:
subject:
type: Responses
where:
- subject:
type: Operation
filterInParentKeys:
- subject:
type: Operation
filterInParentKeys:
- put
assertions:
defined: true
assertions:
defined: true
message: Must mutually define 200 and 201 responses for PUT requests.
severity: error
assertions:
assertions:
mutuallyRequired:
- '200'
- '201'
- '200'
- '201'
# disallowed example
assert/operation-disallowed:
subject:
rule/operation-disallowed:
subject:
type: Operation
message: x-code-samples and x-internal must not be defined
severity: error
assertions:
assertions:
disallowed:
- x-code-samples
- x-internal
- x-code-samples
- x-internal
# defined example
assert/operation-x-code-samples-defined:
subject:
rule/operation-x-code-samples-defined:
subject:
type: Operation
property: x-codeSamples
message: x-codeSamples must be defined
severity: error
assertions:
assertions:
defined: true
# undefined example
assert/operation-x-code-samples-undefined:
subject:
rule/operation-x-code-samples-undefined:
subject:
type: Operation
property: x-code-samples
message: x-code-samples is deprecated
suggest:
- x-codeSamples instead of x-code-samples
severity: error
assertions:
assertions:
defined: false
# nonEmpty example
assert/operation-summary-non-empty:
subject:
rule/operation-summary-non-empty:
subject:
type: Operation
property: summary
message: Operation summary should not be empty
severity: error
assertions:
assertions:
nonEmpty: true
# minLength example
assert/operation-summary-min-length:
subject:
rule/operation-summary-min-length:
subject:
type: Operation
property: summary
message: Operation summary must have minimum of 2 chars length
severity: error
assertions:
assertions:
minLength: 2
# maxLength example
assert/operation-summary-max-length:
subject:
rule/operation-summary-max-length:
subject:
type: Operation
property: summary
message: Operation summary must have a maximum of 2 characters
@@ -196,16 +196,16 @@ rules:
assertions:
maxLength: 2
# Example map subject example
assert/exampleMap:
subject:
rule/exampleMap:
subject:
type: ExamplesMap
message: Examples names must use camelCase
assertions:
casing: camelCase
severity: error
# any subject type example
assert/anyType:
subject:
rule/anyType:
subject:
type: any
property: description
assertions:

View File

@@ -4,20 +4,20 @@ apis:
extends: []
rules:
assert/TagList:
subject:
type: TagList
rule/TagList:
subject:
type: TagList
assertions:
defined: false
assert/ServerList:
subject:
rule/ServerList:
subject:
type: ServerList
assertions:
maxLength: 0
assert/SecurityRequirementList:
subject:
rule/SecurityRequirementList:
subject:
type: SecurityRequirementList
assertions:
assertions:
minLength: 1

View File

@@ -3,33 +3,33 @@ apis:
root: ./openapi.yaml
rules:
assert/headerMap:
subject:
type: HeadersMap
rule/headerMap:
subject:
type: HeadersMap
property: x-next
assertions:
defined: false
assert/encodingMap:
subject:
rule/encodingMap:
subject:
type: EncodingMap
assertions:
casing: kebab-case
assert/linkMap:
subject:
rule/linkMap:
subject:
type: LinksMap
assertions:
assertions:
pattern: /^pet/
assert/serverVariableMap:
subject:
rule/serverVariableMap:
subject:
type: ServerVariablesMap
assertions:
assertions:
casing: flatcase
assert/callbackMap:
subject:
rule/callbackMap:
subject:
type: CallbacksMap
assertions:
casing: snake_case

View File

@@ -2,7 +2,7 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/match-parent-keys-with-defined:
rule/match-parent-keys-with-defined:
subject:
type: Operation
matchParentKeys: /^p/
@@ -11,7 +11,7 @@ rules:
defined: true
const: true
assert/match-parent-keys-example-without-defined:
rule/match-parent-keys-example-without-defined:
subject:
type: Operation
matchParentKeys: /^p/

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/tags-max-length:
subject:
rule/tags-max-length:
subject:
type: Operation
property: tags
message: Operation tags should have maximum 2 items

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/description-max-length:
subject:
rule/description-max-length:
subject:
type: Info
property: description
message: Info description should be maximum 10 chars length

View File

@@ -3,10 +3,10 @@ apis:
root: ./openapi.yaml
rules:
assert/tags-min-length:
subject:
rule/tags-min-length:
subject:
type: Operation
property: tags
message: Operation tags should have minimum 4 items
assertions:
assertions:
minLength: 4

View File

@@ -3,10 +3,10 @@ apis:
root: ./openapi.yaml
rules:
assert/description-min-length:
subject:
rule/description-min-length:
subject:
type: Info
property: description
message: Info description should be minimum 20 chars length
assertions:
assertions:
minLength: 20

View File

@@ -3,17 +3,17 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-mutually-exclusive:
rule/path-item-mutually-exclusive:
where:
- subject:
type: PathItem
property: get
assertions:
defined: true
subject:
subject:
type: Operation
message: Operation should not have summary and tags fields simultaneously
assertions:
mutuallyExclusive:
- summary
- tags
- summary
- tags

View File

@@ -3,17 +3,17 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-mutually-required:
rule/path-item-mutually-required:
where:
- subject:
type: PathItem
property: get
assertions:
defined: true
subject:
subject:
type: Operation
message: Operation should have summary and security fields simultaneously
assertions:
mutuallyRequired:
- summary
- security
- summary
- security

View File

@@ -3,10 +3,10 @@ apis:
root: ./openapi.yaml
rules:
assert/summary-non-empty:
subject:
rule/summary-non-empty:
subject:
type: Operation
property: summary
message: Operation summary should not be empty
assertions:
assertions:
nonEmpty: true

View File

@@ -3,11 +3,11 @@ apis:
root: ./openapi.yaml
rules:
assert/summary-non-empty:
subject:
rule/summary-non-empty:
subject:
type: Operation
property: summary
message: Operation summary should not be empty
assertions:
assertions:
nonEmpty: true
severity: off

View File

@@ -3,11 +3,11 @@ apis:
root: ./openapi.yaml
rules:
assert/summary-non-empty:
subject:
rule/summary-non-empty:
subject:
type: Operation
property: summary
message: Operation summary should not be empty
assertions:
assertions:
nonEmpty: true
severity: warn

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/summary-pattern:
rule/summary-pattern:
subject:
type: Operation
property: summary

View File

@@ -2,7 +2,7 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/no-description-future-past:
rule/no-description-future-past:
subject:
type: any
property: description

View File

@@ -1,16 +1,16 @@
apis:
main:
root: ./openapi.yaml
rules:
assert/query-in-parameters:
rules:
rule/query-in-parameters:
where:
- subject:
- subject:
type: Parameter
property: name
assertions:
const: statusId
subject:
subject:
type: Parameter
property: in
assertions:
assertions:
const: path

View File

@@ -3,21 +3,21 @@ apis:
root: ./openapi.yaml
rules:
assert/ref-forbidden:
rule/ref-forbidden:
where:
- subject:
type: Response
assertions:
assertions:
defined: true
subject:
type: MediaType
property: schema
message: Response MediaType schema should NOT have a ref
assertions:
assertions:
ref: false
assert/ref-forbidden-no-property:
subject:
rule/ref-forbidden-no-property:
subject:
type: PathItem
message: PathItems should NOT should have a ref
assertions:
assertions:
ref: false

View File

@@ -3,20 +3,20 @@ apis:
root: ./openapi.yaml
rules:
assert/ref-pattern:
rule/ref-pattern:
where:
- subject:
type: Response
assertions:
defined: true
subject:
subject:
type: MediaType
property: schema
message: Response MediaType schema should contain ref to components/schemas folder
assertions:
ref: ^(\.\/)?components\/schemas\/.*\.yaml$
assert/ref-pattern-no-properties:
subject:
rule/ref-pattern-no-properties:
subject:
type: PathItem
message: PathItem should contain ref to components/paths folder
assertions:

View File

@@ -3,20 +3,20 @@ apis:
root: ./openapi.yaml
rules:
assert/ref-required:
rule/ref-required:
where:
- subject:
type: Response
assertions:
defined: true
subject:
subject:
type: MediaType
property: schema
message: Response MediaType schema should have a ref
assertions:
ref: true
assert/ref-required-no-property:
subject:
rule/ref-required-no-property:
subject:
type: PathItem
message: PathItems should have refs
assertions:

View File

@@ -3,12 +3,12 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-require-any-description-or-external:
subject:
rule/operation-require-any-description-or-external:
subject:
type: Operation
message: 'Operation must have one of properties defined: description or externalDocs'
severity: error
assertions:
requireAny:
- description
- externalDocs
- description
- externalDocs

View File

@@ -3,14 +3,14 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-suggest:
rule/path-item-suggest:
where:
- subject:
type: PathItem
property: get
assertions:
defined: true
subject:
subject:
type: Operation
property: summary
message: Operation summary should have at least 10 chars length

View File

@@ -2,7 +2,7 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/no-type-integer-in-parameter:
rule/no-type-integer-in-parameter:
where:
- subject:
type: Parameter
@@ -11,7 +11,7 @@ rules:
defined: true
enum:
- en-US
subject:
subject:
type: Schema
property: type
assertions:

View File

@@ -2,27 +2,27 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/type-integer-in-schema-response:
rule/type-integer-in-schema-response:
where:
- subject:
type: Operation
filterInParentKeys: [get]
assertions:
defined: true
- subject:
- subject:
type: Response
filterInParentKeys: ['201', '200']
assertions:
assertions:
defined: true
- subject:
- subject:
type: MediaType
property: example
assertions:
assertions:
defined: true
const: example
subject:
subject:
type: Schema
property: type
assertions:
assertions:
const: string

View File

@@ -3,8 +3,8 @@ apis:
root: ./openapi.yaml
rules:
assert/summary-undefined:
subject:
rule/summary-undefined:
subject:
type: Operation
property: summary
message: Operation summary should be undefined

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/vendor-extension:
rule/vendor-extension:
subject:
type: SpecExtension
property: prop
@@ -11,7 +11,7 @@ rules:
severity: error
assertions:
enum: [foo, bar]
assert/vendor-extension-in-info-section:
rule/vendor-extension-in-info-section:
subject:
type: SpecExtension
property: prop2
@@ -26,11 +26,11 @@ rules:
enum: [foo, bar]
# built-in vendor extension should be processed as generic SpecExtension too
# assert/vendor-extension-built-in:
# rule/vendor-extension-built-in:
# subject:
# type: SpecExtension
# filterInParentKeys: ['x-logo']
# property: url
# severity: error
# assertions:
# defined: true
# defined: true

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/tag-description:
rule/tag-description:
subject:
type: Tag
property: description
@@ -13,22 +13,22 @@ rules:
minLength: 13
pattern: /\.$/
# property example
assert/path-item-get-defined:
subject:
rule/path-item-get-defined:
subject:
type: PathItem
property: get
message: Every path item must have a GET operation.
assertions:
defined: true
assert/path-item-get-required:
subject:
rule/path-item-get-required:
subject:
type: PathItem
message: Every path item must have a GET operation.
assertions:
required:
- get
assert/tag-name-and-desc:
subject:
rule/tag-name-and-desc:
subject:
type: Tag
property:
- name
@@ -38,29 +38,29 @@ rules:
defined: true
# context example
assert/media-type-map-not-pdf:
rule/media-type-map-not-pdf:
subject:
type: MediaTypesMap
assertions:
disallowed: ['application/pdf']
message: Media type should not be pdf
where:
- subject:
where:
- subject:
type: Operation
filterOutParentKeys:
- put
assertions:
assertions:
defined: true
- subject:
type: Response
filterInParentKeys: ['201', '200']
property: description
assertions:
assertions:
defined: true
# enum example
assert/media-type-map-enum:
subject:
rule/media-type-map-enum:
subject:
type: MediaTypesMap
message: Only application/json and application/pdf can be used
severity: error
@@ -69,8 +69,8 @@ rules:
- application/json
- application/pdf
assert/operation-summary-suggest:
subject:
rule/operation-summary-suggest:
subject:
type: Operation
property: summary
message: Summary must be one of the predefined values
@@ -78,14 +78,14 @@ rules:
- change to 'My resource'
- change to 'My collection'
severity: error
assertions:
assertions:
enum:
- My resource
- My collection
# pattern example
assert/operation-summary-pattern:
subject:
rule/operation-summary-pattern:
subject:
type: Operation
property: summary
message: Summary should match a regex
@@ -93,8 +93,8 @@ rules:
assertions:
pattern: /resource/
# casing
assert/operation-id-casing:
subject:
rule/operation-id-casing:
subject:
type: Operation
property: operationId
message: NamedExamples key must be in camelCase
@@ -102,8 +102,8 @@ rules:
assertions:
casing: camelCase
# mutuallyExclusive example
assert/operation-mutually-exclusive:
subject:
rule/operation-mutually-exclusive:
subject:
type: Operation
message: 'Operation must not define both properties together: description and externalDocs'
severity: error
@@ -112,8 +112,8 @@ rules:
- description
- externalDocs
# mutuallyRequired example
assert/schema-properties-mutually-required:
subject:
rule/schema-properties-mutually-required:
subject:
type: SchemaProperties
assertions:
mutuallyRequired:
@@ -123,32 +123,32 @@ rules:
severity: error
where:
- subject:
- subject:
type: Response
assertions:
defined: true
# mutuallyRequired example with context
assert/response-map-required-with-context:
subject:
rule/response-map-required-with-context:
subject:
type: Responses
assertions:
assertions:
mutuallyRequired:
- '200'
- '201'
where:
- subject:
- subject:
type: Operation
filterInParentKeys:
- put
assertions:
assertions:
defined: true
message: Must mutually define 200 and 201 responses for PUT requests.
severity: error
# requireAny example
assert/operation-require-any-description-or-external:
subject:
rule/operation-require-any-description-or-external:
subject:
type: Operation
message: 'Operation must have one of properties defined: description or externalDocs'
severity: error
@@ -158,29 +158,29 @@ rules:
- externalDocs
# disallowed example
assert/operation-disallowed:
subject:
rule/operation-disallowed:
subject:
type: Operation
message: x-code-samples and x-internal must not be defined
severity: error
assertions:
assertions:
disallowed:
- x-code-samples
- x-internal
# defined example
assert/operation-defined:
rule/operation-defined:
subject:
type: Operation
property: x-codeSamples
message: x-codeSamples must be defined
severity: error
assertions:
assertions:
defined: true
# nonEmpty example
assert/operation-non-empty:
subject:
rule/operation-non-empty:
subject:
type: Operation
property: summary
message: Operation summary should not be empty
@@ -189,8 +189,8 @@ rules:
nonEmpty: true
# minLength example
assert/operation-min-length:
subject:
rule/operation-min-length:
subject:
type: Operation
property: summary
message: Operation summary must have minimum of 2 chars length
@@ -199,8 +199,8 @@ rules:
minLength: 2
# maxLength example
assert/operation-max-length:
subject:
rule/operation-max-length:
subject:
type: Operation
property: summary
message: Operation summary must have a maximum of 2 characters
@@ -209,8 +209,8 @@ rules:
maxLength: 20
# ref example
assert/ref:
subject:
rule/ref:
subject:
type: PathItem
message: No refs on Path Items
severity: error

View File

@@ -1,8 +1,8 @@
apis:
api@legacy:
root: ./openapi.yaml
lint:
rules:
lint:
rules:
operation-4xx-response: error
lint:

View File

@@ -1,8 +1,8 @@
apis:
api@legacy:
root: ./openapi.yaml
styleguide:
rules:
styleguide:
rules:
operation-4xx-response: error
styleguide:

View File

@@ -1,8 +1,8 @@
apis:
main:
root: ./openapi.yaml
extends:
- ./nested-config.yaml
extends:
- ./nested-config.yaml
rules:
info-contact: warn
operation-4xx-response: off

View File

@@ -1,5 +1,5 @@
apis:
main:
main:
root: ./openapi.yaml
extends:

View File

@@ -1,6 +1,6 @@
apis:
main:
main:
root: ./openapi.yaml
extends:
- recommended # This is the default (and built in) configuration.
- recommended # This is the default (and built in) configuration.

View File

@@ -2,6 +2,6 @@ apis:
main:
root: ./openapi.yaml
rules:
rules:
spec: error
no-unused-components: error

View File

@@ -1,5 +1,5 @@
apis:
main:
main:
root: ./openapi.yaml
rules:
required-string-property-missing-min-length: error
rules:
required-string-property-missing-min-length: error

View File

@@ -1,5 +1,5 @@
apis:
main:
main:
root: ./openapi.yaml
rules:

View File

@@ -2,6 +2,6 @@ apis:
main:
root: ./openapi.yaml
rules:
rules:
spec: error
required-string-property-missing-min-length: error

View File

@@ -2,6 +2,6 @@ apis:
main:
root: ./openapi.yaml
rules:
rules:
operation-operationId: warn
operation-summary: error

View File

@@ -11,18 +11,18 @@ Configure flexible rules to meet any situation not covered by the [built-in rule
```yaml
rules:
assert/assertion-name:
rule/my-rule-name:
...
assert/one-more-assertion-name:
rule/one-more-rule-name:
...
```
A configurable rule describes the contents that the linter expects to find in your API definition. During the validation process, the linter goes through your API definition and checks if its contents match the expectations. If something was described in an assertion, but the API definition doesn't correspond to the description, the linter shows you a warning or error message in the log.
A configurable rule describes the contents that the linter expects to find in your API definition. During the validation process, the linter goes through your API definition and checks if its contents match the expectations. If something was described in a configurable rule, but the API definition doesn't correspond to the description, the linter shows you a warning or error message in the log.
Pattern Property | Type | Description
-- | -- | --
assert/{string} | [Configurable rule object](#configurable-rule-object) | Configurable rule definitions enforce your custom API design standards. Add or edit your configurable rules in the configuration file. A configurable rule is a rule that starts with a `assert/` prefix followed by a unique rule name. Rule names display in the lint log if the assertions fail. More than one assertion may be defined, and any configurable rule may have multiple assertions.
rule/{string} | [Configurable rule object](#configurable-rule-object) | Configurable rule definitions enforce your custom API design standards. Add or edit your configurable rules in the configuration file. A configurable rule is a rule that starts with a `rule/` prefix followed by a unique rule name. Rule names display in the lint log if the assertions fail. More than one configurable rule may be defined, and any configurable rule may have multiple assertions.
## Configurable rule object
@@ -87,7 +87,7 @@ Without the `where`, the assertion would evaluate every `MediaTypesMap` property
To restrict the evaluation, use the `where` feature to limit what is evaluated.
```yaml
assert/no-pdf-in-ok-response:
rule/no-pdf-in-ok-response:
where:
- subject:
type: Operation
@@ -109,11 +109,11 @@ assert/no-pdf-in-ok-response:
- 'application/pdf'
```
Where enables complex assertions based on sibling values.
The `where` section enables complex assertions based on sibling values.
The following example asserts that the `limit` parameter must have a schema with `type: integer`.
```yaml
assert/limit-is-integer:
rule/limit-is-integer:
subject:
type: Schema
property: type
@@ -145,7 +145,7 @@ The following example shows how to configure those assertions:
```yaml
rules:
assert/tag-description:
rule/tag-description:
subject:
type: Tag
property: description
@@ -154,7 +154,7 @@ rules:
minLength: 30
pattern: /\.$/
message: Tag description must be at least 30 characters and end with a full stop.
assert/operation-description:
rule/operation-description:
subject:
type: Operation
property: description
@@ -164,7 +164,7 @@ rules:
pattern: /\.$/
message: Operation description must be at least 30 characters and end with a full stop.
severity: warn
assert/info-description:
rule/info-description:
subject:
type: Info
property: description
@@ -173,7 +173,7 @@ rules:
minLength: 30
pattern: /\.$/
message: Info description must be at least 30 characters and end with a full stop.
assert/operation-summary:
rule/operation-summary:
subject:
type: Operation
property: summary
@@ -212,7 +212,7 @@ location | `Location Object` | Location in the source document. See [Location Ob
`.redocly.yaml`
```yaml
assert/operation-summary-check:
rule/operation-summary-check:
subject:
type: Operation
property: summary
@@ -273,7 +273,7 @@ The following example asserts the casing style is `PascalCase` for `NamedExample
```yaml
rules:
assert/named-examples-pascal-case:
rule/named-examples-pascal-case:
subject:
type: NamedExamples
assertions:
@@ -295,7 +295,7 @@ The following example asserts that only `application/json` can be used as a key
```yaml keys
rules:
assert/media-type-map-application-json:
rule/media-type-map-application-json:
subject:
type: MediaTypesMap
assertions:
@@ -309,7 +309,7 @@ The following example asserts that `x-codeSamples` is defined.
```yaml
rules:
assert/x-code-samples-defined:
rule/x-code-samples-defined:
subject:
type: Operation
property: x-codeSamples
@@ -321,7 +321,7 @@ The following example asserts that `x-code-samples` is undefined.
```yaml
rules:
assert/x-code-samples-undefined:
rule/x-code-samples-undefined:
subject:
type: Operation
property: x-code-samples
@@ -337,7 +337,7 @@ The following example asserts that `x-code-samples` and `x-internal` are not def
```yaml
rules:
assert/no-x-code-samples-and-x-internal:
rule/no-x-code-samples-and-x-internal:
subject:
type: Operation
assertions:
@@ -353,7 +353,7 @@ It has the same effect as the `const` assertion.
```yaml keys
rules:
assert/media-type-map-application-json:
rule/media-type-map-application-json:
subject:
type: MediaTypesMap
assertions:
@@ -366,7 +366,7 @@ The following example asserts that the operation summary must match one of the l
```yaml values
rules:
assert/operation-summary-match:
rule/operation-summary-match:
subject:
type: Operation
property: summary
@@ -386,7 +386,7 @@ The following example asserts that the maximum length of each operation summary
```yaml
rules:
assert/operation-summary-max-length:
rule/operation-summary-max-length:
subject:
type: Operation
property: summary
@@ -401,7 +401,7 @@ The following example asserts that the minimum length of each operation summary
```yaml
rules:
assert/operation-summary-min-length:
rule/operation-summary-min-length:
subject:
type: Operation
property: summary
@@ -417,7 +417,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml
rules:
assert/operation-no-both-description-and-external-docs:
rule/operation-no-both-description-and-external-docs:
subject:
type: Operation
assertions:
@@ -433,7 +433,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml Schema example
rules:
assert/schema-properties-both-created-at-and-updated-at:
rule/schema-properties-both-created-at-and-updated-at:
subject:
type: SchemaProperties
assertions:
@@ -446,7 +446,7 @@ The following example asserts that when `PUT` requests have either `200` or `201
```yaml Response example
rules:
assert/put-200-and-201:
rule/put-200-and-201:
subject:
type: Responses
where:
@@ -469,7 +469,7 @@ The following example asserts that the operation summary is not empty.
```yaml
rules:
assert/operation-summary-non-empty:
rule/operation-summary-non-empty:
subject:
type: Operation
property: summary
@@ -483,7 +483,7 @@ The following example asserts that the operation summary doesn't start with "The
```yaml
rules:
assert/operation-summary-contains-test:
rule/operation-summary-contains-test:
subject:
type: Operation
property: The summary
@@ -497,7 +497,7 @@ The following example asserts that the operation summary contains "test".
```yaml
rules:
assert/operation-summary-contains-test:
rule/operation-summary-contains-test:
subject:
type: Operation
property: summary
@@ -511,7 +511,7 @@ The following example asserts that schema in MediaType contains a Reference obje
```yaml
rules:
assert/mediatype-schema-has-ref:
rule/mediatype-schema-has-ref:
subject:
type: MediaType
property: schema
@@ -523,7 +523,7 @@ Also, you can specify a Regular Expression to check if the reference object conf
```yaml
rules:
assert/mediatype-schema-ref-pattern:
rule/mediatype-schema-ref-pattern:
subject:
type: MediaType
property: schema
@@ -540,7 +540,7 @@ The difference between `mutuallyRequired` is that neither `200` and `201` need t
```yaml Response example
rules:
assert/put-200-and-201:
rule/put-200-and-201:
subject:
type: Responses
where:
@@ -564,7 +564,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml Response example
rules:
assert/operation-no-both-description-and-external-docs:
rule/operation-no-both-description-and-external-docs:
subject:
type: Operation
assertions:
@@ -587,7 +587,7 @@ The following example asserts that the maximum length of each description is 20
```yaml
rules:
assert/description-max-length:
rule/description-max-length:
subject:
type: any
property: description
@@ -602,7 +602,7 @@ The following example asserts that every path item has a GET operation defined.
```yaml
rules:
assert/path-item-get-operation-defined:
rule/path-item-get-operation-defined:
subject:
type: PathItem
property: get
@@ -615,7 +615,7 @@ Notice we don't need to include `property` in this approach.
```yaml
rules:
assert/path-item-operation-required:
rule/path-item-operation-required:
subject:
type: PathItem
assertions:
@@ -628,7 +628,7 @@ The following example asserts that Tags have both name and description defined.
```yaml
rules:
assert/tag-name-and-desc-defined:
rule/tag-name-and-desc-defined:
subject:
type: Tag
property:
@@ -643,7 +643,7 @@ Another way to compose that rule is to require the subject keys:
```yaml
rules:
assert/tag-name-and-desc-required:
rule/tag-name-and-desc-required:
subject:
type: Tag
assertions:

View File

@@ -60,7 +60,7 @@ describe('lint', () => {
no-invalid-media-type-examples: error
path-http-verbs-order: error
boolean-parameter-prefixes: off
assert/operation-summary-length:
rule/operation-summary-length:
subject:
type: Operation
property: summary

View File

@@ -2,7 +2,7 @@ plugins:
- plugin.js
rules:
operation-2xx-response: error
assert/path-item-get-defined:
rule/path-item-get-defined:
subject: PathItem
property: get
message: Every path item must have a GET operation.

View File

@@ -1,17 +1,17 @@
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
assert/tag-description:
subject:
type: Tag
property: description
message: Tag description must have at least 3 words.
severity: error
assertions:
test-plugin/checkWordsCount:
min: 3
plugins:
- plugin.js
extends:
- recommended
- test-plugin/all
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
rule/tag-description:
subject:
type: Tag
property: description
message: Tag description must have at least 3 words.
severity: error
assertions:
test-plugin/checkWordsCount:
min: 3
plugins:
- plugin.js
extends:
- recommended
- test-plugin/all

View File

@@ -1,7 +1,7 @@
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
assert/tag-description:
rule/tag-description:
subject: Tag
property: description
message: Tag description must be at least 13 characters and end with a full stop.

View File

@@ -1,15 +1,15 @@
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
assert/tag-description:
subject: Tag
property: description
message: Tag description must have at least 3 words.
severity: error
test-plugin/checkWordsCount2:
min: 3
plugins:
- plugin.js
extends:
- recommended
- test-plugin/all
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
rule/tag-description:
subject: Tag
property: description
message: Tag description must have at least 3 words.
severity: error
test-plugin/checkWordsCount2:
min: 3
plugins:
- plugin.js
extends:
- recommended
- test-plugin/all

View File

@@ -414,7 +414,13 @@ function groupStyleguideAssertionRules({
// Collect assertion rules
const assertions: Assertion[] = [];
for (const [ruleKey, rule] of Object.entries(rules)) {
if (ruleKey.startsWith('assert/') && typeof rule === 'object' && rule !== null) {
// keep the old assert/ syntax as an alias
if (
(ruleKey.startsWith('rule/') || ruleKey.startsWith('assert/')) &&
typeof rule === 'object' &&
rule !== null
) {
const assertion = rule as RawAssertion;
if (plugins) {
@@ -427,7 +433,7 @@ function groupStyleguideAssertionRules({
}
assertions.push({
...assertion,
assertionId: ruleKey.replace('assert/', ''),
assertionId: ruleKey.replace(/rule\/|assert\//, ''),
});
} else {
// If it's not an assertion, keep it as is

View File

@@ -291,7 +291,7 @@ export function transformConfig(
const { styleguideConfig, rawConfigRest } = extractFlatConfig(rest);
return {
const transformedConfig: RawConfig = {
theme: {
openapi: {
...referenceDocs,
@@ -307,6 +307,22 @@ export function transformConfig(
styleguide: styleguideConfig || lint,
...rawConfigRest,
};
showDeprecationMessages(transformedConfig);
return transformedConfig;
}
function showDeprecationMessages(config: RawConfig) {
let allRules = { ...config.styleguide?.rules };
for (const api of Object.values(config.apis || {})) {
allRules = { ...allRules, ...api?.styleguide?.rules };
}
for (const ruleKey of Object.keys(allRules)) {
if (ruleKey.startsWith('assert/')) {
logger.warn(
`\nThe 'assert/' syntax in ${ruleKey} is deprecated. Update your configuration to use 'rule/' instead. Examples and more information: https://redocly.com/docs/cli/rules/configurable-rules/\n`
);
}
}
}
export function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig {

View File

@@ -225,7 +225,10 @@ const ConfigRootTheme: NodeType = {
const Rules: NodeType = {
properties: {},
additionalProperties: (value: unknown, key: string) => {
if (key.startsWith('assert/')) {
if (key.startsWith('rule/')) {
return 'Assert';
} else if (key.startsWith('assert/')) {
// keep the old assert/ prefix as an alias
return 'Assert';
} else if (builtInRulesList.includes(key) || isCustomRuleId(key)) {
if (typeof value === 'string') {