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: main:
root: ./test.yaml root: ./test.yaml
extends: extends:
- recommended - recommended

View File

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

View File

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

View File

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

View File

@@ -17,6 +17,8 @@ Error was generated by the configuration spec rule.
❌ Your config has 1 error. ❌ 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... validating ../__fixtures__/valid-openapi.yaml...
../__fixtures__/valid-openapi.yaml: validated in <test>ms ../__fixtures__/valid-openapi.yaml: validated in <test>ms

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
apis: apis:
main: main:
root: ./openapi.yaml root: ./openapi.yaml
extends: 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: main:
root: ./openapi.yaml root: ./openapi.yaml
rules: rules:
spec: error spec: error
no-unused-components: error no-unused-components: error

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,18 +11,18 @@ Configure flexible rules to meet any situation not covered by the [built-in rule
```yaml ```yaml
rules: 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 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 ## 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. To restrict the evaluation, use the `where` feature to limit what is evaluated.
```yaml ```yaml
assert/no-pdf-in-ok-response: rule/no-pdf-in-ok-response:
where: where:
- subject: - subject:
type: Operation type: Operation
@@ -109,11 +109,11 @@ assert/no-pdf-in-ok-response:
- 'application/pdf' - '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`. The following example asserts that the `limit` parameter must have a schema with `type: integer`.
```yaml ```yaml
assert/limit-is-integer: rule/limit-is-integer:
subject: subject:
type: Schema type: Schema
property: type property: type
@@ -145,7 +145,7 @@ The following example shows how to configure those assertions:
```yaml ```yaml
rules: rules:
assert/tag-description: rule/tag-description:
subject: subject:
type: Tag type: Tag
property: description property: description
@@ -154,7 +154,7 @@ rules:
minLength: 30 minLength: 30
pattern: /\.$/ pattern: /\.$/
message: Tag description must be at least 30 characters and end with a full stop. message: Tag description must be at least 30 characters and end with a full stop.
assert/operation-description: rule/operation-description:
subject: subject:
type: Operation type: Operation
property: description property: description
@@ -164,7 +164,7 @@ rules:
pattern: /\.$/ pattern: /\.$/
message: Operation description must be at least 30 characters and end with a full stop. message: Operation description must be at least 30 characters and end with a full stop.
severity: warn severity: warn
assert/info-description: rule/info-description:
subject: subject:
type: Info type: Info
property: description property: description
@@ -173,7 +173,7 @@ rules:
minLength: 30 minLength: 30
pattern: /\.$/ pattern: /\.$/
message: Info description must be at least 30 characters and end with a full stop. message: Info description must be at least 30 characters and end with a full stop.
assert/operation-summary: rule/operation-summary:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -212,7 +212,7 @@ location | `Location Object` | Location in the source document. See [Location Ob
`.redocly.yaml` `.redocly.yaml`
```yaml ```yaml
assert/operation-summary-check: rule/operation-summary-check:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -273,7 +273,7 @@ The following example asserts the casing style is `PascalCase` for `NamedExample
```yaml ```yaml
rules: rules:
assert/named-examples-pascal-case: rule/named-examples-pascal-case:
subject: subject:
type: NamedExamples type: NamedExamples
assertions: assertions:
@@ -295,7 +295,7 @@ The following example asserts that only `application/json` can be used as a key
```yaml keys ```yaml keys
rules: rules:
assert/media-type-map-application-json: rule/media-type-map-application-json:
subject: subject:
type: MediaTypesMap type: MediaTypesMap
assertions: assertions:
@@ -309,7 +309,7 @@ The following example asserts that `x-codeSamples` is defined.
```yaml ```yaml
rules: rules:
assert/x-code-samples-defined: rule/x-code-samples-defined:
subject: subject:
type: Operation type: Operation
property: x-codeSamples property: x-codeSamples
@@ -321,7 +321,7 @@ The following example asserts that `x-code-samples` is undefined.
```yaml ```yaml
rules: rules:
assert/x-code-samples-undefined: rule/x-code-samples-undefined:
subject: subject:
type: Operation type: Operation
property: x-code-samples property: x-code-samples
@@ -337,7 +337,7 @@ The following example asserts that `x-code-samples` and `x-internal` are not def
```yaml ```yaml
rules: rules:
assert/no-x-code-samples-and-x-internal: rule/no-x-code-samples-and-x-internal:
subject: subject:
type: Operation type: Operation
assertions: assertions:
@@ -353,7 +353,7 @@ It has the same effect as the `const` assertion.
```yaml keys ```yaml keys
rules: rules:
assert/media-type-map-application-json: rule/media-type-map-application-json:
subject: subject:
type: MediaTypesMap type: MediaTypesMap
assertions: assertions:
@@ -366,7 +366,7 @@ The following example asserts that the operation summary must match one of the l
```yaml values ```yaml values
rules: rules:
assert/operation-summary-match: rule/operation-summary-match:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -386,7 +386,7 @@ The following example asserts that the maximum length of each operation summary
```yaml ```yaml
rules: rules:
assert/operation-summary-max-length: rule/operation-summary-max-length:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -401,7 +401,7 @@ The following example asserts that the minimum length of each operation summary
```yaml ```yaml
rules: rules:
assert/operation-summary-min-length: rule/operation-summary-min-length:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -417,7 +417,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml ```yaml
rules: rules:
assert/operation-no-both-description-and-external-docs: rule/operation-no-both-description-and-external-docs:
subject: subject:
type: Operation type: Operation
assertions: assertions:
@@ -433,7 +433,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml Schema example ```yaml Schema example
rules: rules:
assert/schema-properties-both-created-at-and-updated-at: rule/schema-properties-both-created-at-and-updated-at:
subject: subject:
type: SchemaProperties type: SchemaProperties
assertions: assertions:
@@ -446,7 +446,7 @@ The following example asserts that when `PUT` requests have either `200` or `201
```yaml Response example ```yaml Response example
rules: rules:
assert/put-200-and-201: rule/put-200-and-201:
subject: subject:
type: Responses type: Responses
where: where:
@@ -469,7 +469,7 @@ The following example asserts that the operation summary is not empty.
```yaml ```yaml
rules: rules:
assert/operation-summary-non-empty: rule/operation-summary-non-empty:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -483,7 +483,7 @@ The following example asserts that the operation summary doesn't start with "The
```yaml ```yaml
rules: rules:
assert/operation-summary-contains-test: rule/operation-summary-contains-test:
subject: subject:
type: Operation type: Operation
property: The summary property: The summary
@@ -497,7 +497,7 @@ The following example asserts that the operation summary contains "test".
```yaml ```yaml
rules: rules:
assert/operation-summary-contains-test: rule/operation-summary-contains-test:
subject: subject:
type: Operation type: Operation
property: summary property: summary
@@ -511,7 +511,7 @@ The following example asserts that schema in MediaType contains a Reference obje
```yaml ```yaml
rules: rules:
assert/mediatype-schema-has-ref: rule/mediatype-schema-has-ref:
subject: subject:
type: MediaType type: MediaType
property: schema property: schema
@@ -523,7 +523,7 @@ Also, you can specify a Regular Expression to check if the reference object conf
```yaml ```yaml
rules: rules:
assert/mediatype-schema-ref-pattern: rule/mediatype-schema-ref-pattern:
subject: subject:
type: MediaType type: MediaType
property: schema property: schema
@@ -540,7 +540,7 @@ The difference between `mutuallyRequired` is that neither `200` and `201` need t
```yaml Response example ```yaml Response example
rules: rules:
assert/put-200-and-201: rule/put-200-and-201:
subject: subject:
type: Responses type: Responses
where: where:
@@ -564,7 +564,7 @@ This assertion evaluates only property keys for the node, but not property value
```yaml Response example ```yaml Response example
rules: rules:
assert/operation-no-both-description-and-external-docs: rule/operation-no-both-description-and-external-docs:
subject: subject:
type: Operation type: Operation
assertions: assertions:
@@ -587,7 +587,7 @@ The following example asserts that the maximum length of each description is 20
```yaml ```yaml
rules: rules:
assert/description-max-length: rule/description-max-length:
subject: subject:
type: any type: any
property: description property: description
@@ -602,7 +602,7 @@ The following example asserts that every path item has a GET operation defined.
```yaml ```yaml
rules: rules:
assert/path-item-get-operation-defined: rule/path-item-get-operation-defined:
subject: subject:
type: PathItem type: PathItem
property: get property: get
@@ -615,7 +615,7 @@ Notice we don't need to include `property` in this approach.
```yaml ```yaml
rules: rules:
assert/path-item-operation-required: rule/path-item-operation-required:
subject: subject:
type: PathItem type: PathItem
assertions: assertions:
@@ -628,7 +628,7 @@ The following example asserts that Tags have both name and description defined.
```yaml ```yaml
rules: rules:
assert/tag-name-and-desc-defined: rule/tag-name-and-desc-defined:
subject: subject:
type: Tag type: Tag
property: property:
@@ -643,7 +643,7 @@ Another way to compose that rule is to require the subject keys:
```yaml ```yaml
rules: rules:
assert/tag-name-and-desc-required: rule/tag-name-and-desc-required:
subject: subject:
type: Tag type: Tag
assertions: assertions:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -414,7 +414,13 @@ function groupStyleguideAssertionRules({
// Collect assertion rules // Collect assertion rules
const assertions: Assertion[] = []; const assertions: Assertion[] = [];
for (const [ruleKey, rule] of Object.entries(rules)) { 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; const assertion = rule as RawAssertion;
if (plugins) { if (plugins) {
@@ -427,7 +433,7 @@ function groupStyleguideAssertionRules({
} }
assertions.push({ assertions.push({
...assertion, ...assertion,
assertionId: ruleKey.replace('assert/', ''), assertionId: ruleKey.replace(/rule\/|assert\//, ''),
}); });
} else { } else {
// If it's not an assertion, keep it as is // If it's not an assertion, keep it as is

View File

@@ -291,7 +291,7 @@ export function transformConfig(
const { styleguideConfig, rawConfigRest } = extractFlatConfig(rest); const { styleguideConfig, rawConfigRest } = extractFlatConfig(rest);
return { const transformedConfig: RawConfig = {
theme: { theme: {
openapi: { openapi: {
...referenceDocs, ...referenceDocs,
@@ -307,6 +307,22 @@ export function transformConfig(
styleguide: styleguideConfig || lint, styleguide: styleguideConfig || lint,
...rawConfigRest, ...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 { export function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig {

View File

@@ -225,7 +225,10 @@ const ConfigRootTheme: NodeType = {
const Rules: NodeType = { const Rules: NodeType = {
properties: {}, properties: {},
additionalProperties: (value: unknown, key: string) => { 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'; return 'Assert';
} else if (builtInRulesList.includes(key) || isCustomRuleId(key)) { } else if (builtInRulesList.includes(key) || isCustomRuleId(key)) {
if (typeof value === 'string') { if (typeof value === 'string') {