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

@@ -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

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

View File

@@ -5,7 +5,7 @@ apis:
plugins:
- ./plugin.js
rules:
assert/minLength:
rule/minLength:
subject:
type: Schema
assertions:

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,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-get:
rule/operation-get:
subject:
type: Operation
filterInParentKeys: [get]
@@ -13,8 +13,7 @@ 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
@@ -22,7 +21,7 @@ rules:
assertions:
casing: camelCase
assert/camel-case-on-value:
rule/camel-case-on-value:
subject:
type: NamedParameters
assertions:

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,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/operation-id-pascal-case:
rule/operation-id-pascal-case:
subject:
type: Operation
property: operationId
@@ -12,7 +12,7 @@ rules:
assertions:
casing: PascalCase
assert/operation-id-snake-case:
rule/operation-id-snake-case:
subject:
type: Operation
property: operationId

View File

@@ -4,7 +4,7 @@ apis:
plugins:
- ./plugin.js
rules:
assert/operation-summary-length-custom:
rule/operation-summary-length-custom:
subject:
type: Operation
property: summary
@@ -25,8 +25,7 @@ rules:
local/checkWordsCount:
min: 3
assert/operation-summary-length:
rule/operation-summary-length:
subject:
type: Operation
property: summary
@@ -46,7 +45,7 @@ rules:
local/checkWordsCount:
min: 3
assert/operation-summary-length-with-where:
rule/operation-summary-length-with-where:
where:
- subject:
type: Operation

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

View File

@@ -3,7 +3,7 @@ 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

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/tag-description-pattern:
rule/tag-description-pattern:
subject:
type: Tag
property: description
@@ -13,21 +13,21 @@ rules:
minLength: 13
pattern: /\.$/
# property example
assert/path-item-get-defined:
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:
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:
rule/tag-name-and-desc:
subject:
type: Tag
property:
@@ -37,7 +37,7 @@ rules:
assertions:
defined: true
# context example
assert/operation-w-context:
rule/operation-w-context:
subject:
type: MediaTypesMap
where:
@@ -57,7 +57,7 @@ rules:
message: Media type should not be pdf
# enum example
assert/media-type-pdf:
rule/media-type-pdf:
subject:
type: MediaTypesMap
message: Only application/pdf can be used
@@ -65,7 +65,7 @@ rules:
assertions:
enum:
- application/pdf
assert/operation-summary-suggest:
rule/operation-summary-suggest:
subject:
type: Operation
property: summary
@@ -79,7 +79,7 @@ rules:
- My resource
- My collection
# pattern example
assert/operation-summary-pattern:
rule/operation-summary-pattern:
subject:
type: Operation
property: summary
@@ -88,7 +88,7 @@ rules:
assertions:
pattern: /resource/
# casing
assert/operation-id-camel-case:
rule/operation-id-camel-case:
subject:
type: Operation
property: operationId
@@ -97,17 +97,17 @@ rules:
assertions:
casing: camelCase
# mutuallyExclusive example
assert/operation-mutually-exclusive:
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
# mutuallyRequired example
assert/operation-mutually-required:
rule/operation-mutually-required:
subject:
type: SchemaProperties
where:
@@ -122,7 +122,7 @@ rules:
- created_at
- updated_at
# mutuallyRequired example with context
assert/operation-mutually-required-w-context:
rule/operation-mutually-required-w-context:
subject:
type: Responses
where:
@@ -139,7 +139,7 @@ rules:
- '200'
- '201'
# disallowed example
assert/operation-disallowed:
rule/operation-disallowed:
subject:
type: Operation
message: x-code-samples and x-internal must not be defined
@@ -149,7 +149,7 @@ rules:
- x-code-samples
- x-internal
# defined example
assert/operation-x-code-samples-defined:
rule/operation-x-code-samples-defined:
subject:
type: Operation
property: x-codeSamples
@@ -158,7 +158,7 @@ rules:
assertions:
defined: true
# undefined example
assert/operation-x-code-samples-undefined:
rule/operation-x-code-samples-undefined:
subject:
type: Operation
property: x-code-samples
@@ -169,7 +169,7 @@ rules:
assertions:
defined: false
# nonEmpty example
assert/operation-summary-non-empty:
rule/operation-summary-non-empty:
subject:
type: Operation
property: summary
@@ -178,7 +178,7 @@ rules:
assertions:
nonEmpty: true
# minLength example
assert/operation-summary-min-length:
rule/operation-summary-min-length:
subject:
type: Operation
property: summary
@@ -187,7 +187,7 @@ rules:
assertions:
minLength: 2
# maxLength example
assert/operation-summary-max-length:
rule/operation-summary-max-length:
subject:
type: Operation
property: summary
@@ -196,7 +196,7 @@ rules:
assertions:
maxLength: 2
# Example map subject example
assert/exampleMap:
rule/exampleMap:
subject:
type: ExamplesMap
message: Examples names must use camelCase
@@ -204,7 +204,7 @@ rules:
casing: camelCase
severity: error
# any subject type example
assert/anyType:
rule/anyType:
subject:
type: any
property: description

View File

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

View File

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

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,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/tags-max-length:
rule/tags-max-length:
subject:
type: Operation
property: tags

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/description-max-length:
rule/description-max-length:
subject:
type: Info
property: description

View File

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

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/description-min-length:
rule/description-min-length:
subject:
type: Info
property: description

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-mutually-exclusive:
rule/path-item-mutually-exclusive:
where:
- subject:
type: PathItem

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-mutually-required:
rule/path-item-mutually-required:
where:
- subject:
type: PathItem

View File

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

View File

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

View File

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

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

@@ -2,7 +2,7 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/query-in-parameters:
rule/query-in-parameters:
where:
- subject:
type: Parameter

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/path-item-suggest:
rule/path-item-suggest:
where:
- subject:
type: PathItem

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

View File

@@ -2,7 +2,7 @@ apis:
main:
root: ./openapi.yaml
rules:
assert/type-integer-in-schema-response:
rule/type-integer-in-schema-response:
where:
- subject:
type: Operation

View File

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

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,7 +26,7 @@ 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']

View File

@@ -3,7 +3,7 @@ apis:
root: ./openapi.yaml
rules:
assert/tag-description:
rule/tag-description:
subject:
type: Tag
property: description
@@ -13,21 +13,21 @@ rules:
minLength: 13
pattern: /\.$/
# property example
assert/path-item-get-defined:
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:
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:
rule/tag-name-and-desc:
subject:
type: Tag
property:
@@ -38,7 +38,7 @@ rules:
defined: true
# context example
assert/media-type-map-not-pdf:
rule/media-type-map-not-pdf:
subject:
type: MediaTypesMap
assertions:
@@ -59,7 +59,7 @@ rules:
defined: true
# enum example
assert/media-type-map-enum:
rule/media-type-map-enum:
subject:
type: MediaTypesMap
message: Only application/json and application/pdf can be used
@@ -69,7 +69,7 @@ rules:
- application/json
- application/pdf
assert/operation-summary-suggest:
rule/operation-summary-suggest:
subject:
type: Operation
property: summary
@@ -84,7 +84,7 @@ rules:
- My collection
# pattern example
assert/operation-summary-pattern:
rule/operation-summary-pattern:
subject:
type: Operation
property: summary
@@ -93,7 +93,7 @@ rules:
assertions:
pattern: /resource/
# casing
assert/operation-id-casing:
rule/operation-id-casing:
subject:
type: Operation
property: operationId
@@ -102,7 +102,7 @@ rules:
assertions:
casing: camelCase
# mutuallyExclusive example
assert/operation-mutually-exclusive:
rule/operation-mutually-exclusive:
subject:
type: Operation
message: 'Operation must not define both properties together: description and externalDocs'
@@ -112,7 +112,7 @@ rules:
- description
- externalDocs
# mutuallyRequired example
assert/schema-properties-mutually-required:
rule/schema-properties-mutually-required:
subject:
type: SchemaProperties
assertions:
@@ -129,7 +129,7 @@ rules:
defined: true
# mutuallyRequired example with context
assert/response-map-required-with-context:
rule/response-map-required-with-context:
subject:
type: Responses
assertions:
@@ -147,7 +147,7 @@ rules:
severity: error
# requireAny example
assert/operation-require-any-description-or-external:
rule/operation-require-any-description-or-external:
subject:
type: Operation
message: 'Operation must have one of properties defined: description or externalDocs'
@@ -158,7 +158,7 @@ rules:
- externalDocs
# disallowed example
assert/operation-disallowed:
rule/operation-disallowed:
subject:
type: Operation
message: x-code-samples and x-internal must not be defined
@@ -169,7 +169,7 @@ rules:
- x-internal
# defined example
assert/operation-defined:
rule/operation-defined:
subject:
type: Operation
property: x-codeSamples
@@ -179,7 +179,7 @@ rules:
defined: true
# nonEmpty example
assert/operation-non-empty:
rule/operation-non-empty:
subject:
type: Operation
property: summary
@@ -189,7 +189,7 @@ rules:
nonEmpty: true
# minLength example
assert/operation-min-length:
rule/operation-min-length:
subject:
type: Operation
property: summary
@@ -199,7 +199,7 @@ rules:
minLength: 2
# maxLength example
assert/operation-max-length:
rule/operation-max-length:
subject:
type: Operation
property: summary
@@ -209,7 +209,7 @@ rules:
maxLength: 20
# ref example
assert/ref:
rule/ref:
subject:
type: PathItem
message: No refs on Path Items

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,7 +1,7 @@
rules:
no-invalid-media-type-examples: warn
operation-4xx-response: off
assert/tag-description:
rule/tag-description:
subject:
type: Tag
property: description

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,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 have at least 3 words.

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') {