Skip to content

Commit 34ca221

Browse files
feat(ipa): new IPA rule xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf (#893)
1 parent 6f80306 commit 34ca221

File tree

4 files changed

+173
-0
lines changed

4 files changed

+173
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import testRule from './__helpers__/testRule.js';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf', [
5+
{
6+
name: 'valid schemas',
7+
document: {
8+
components: {
9+
schemas: {
10+
SchemaOneOf: {
11+
discriminator: {
12+
propertyName: 'type',
13+
},
14+
oneOf: [{}],
15+
},
16+
SchemaAnyOf: {
17+
discriminator: {
18+
propertyName: 'type',
19+
},
20+
anyOf: [{}],
21+
},
22+
SchemaAllOf: {
23+
discriminator: {
24+
propertyName: 'type',
25+
},
26+
allOf: [{}],
27+
},
28+
},
29+
},
30+
},
31+
errors: [],
32+
},
33+
{
34+
name: 'invalid schemas',
35+
document: {
36+
components: {
37+
schemas: {
38+
Schema: {
39+
discriminator: {
40+
propertyName: 'type',
41+
},
42+
properties: {
43+
type: {
44+
type: 'string',
45+
},
46+
},
47+
},
48+
NestedSchema: {
49+
properties: {
50+
name: {
51+
type: 'object',
52+
discriminator: {
53+
propertyName: 'first',
54+
},
55+
properties: {
56+
first: {
57+
type: 'string',
58+
},
59+
},
60+
},
61+
address: {
62+
type: 'string',
63+
},
64+
},
65+
},
66+
},
67+
},
68+
},
69+
errors: [
70+
{
71+
code: 'xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf',
72+
message: "Each discriminator property must be accompanied by a 'oneOf', 'anyOf' or 'allOf' property.",
73+
path: ['components', 'schemas', 'Schema'],
74+
severity: DiagnosticSeverity.Warning,
75+
},
76+
{
77+
code: 'xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf',
78+
message: "Each discriminator property must be accompanied by a 'oneOf', 'anyOf' or 'allOf' property.",
79+
path: ['components', 'schemas', 'NestedSchema', 'properties', 'name'],
80+
severity: DiagnosticSeverity.Warning,
81+
},
82+
],
83+
},
84+
{
85+
name: 'invalid schemas with exceptions',
86+
document: {
87+
components: {
88+
schemas: {
89+
Schema: {
90+
discriminator: {
91+
propertyName: 'type',
92+
},
93+
properties: {
94+
type: {
95+
type: 'string',
96+
},
97+
},
98+
'x-xgen-IPA-exception': {
99+
'xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf': 'reason',
100+
},
101+
},
102+
NestedSchema: {
103+
properties: {
104+
name: {
105+
type: 'object',
106+
discriminator: {
107+
propertyName: 'first',
108+
},
109+
properties: {
110+
first: {
111+
type: 'string',
112+
},
113+
},
114+
'x-xgen-IPA-exception': {
115+
'xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf': 'reason',
116+
},
117+
},
118+
address: {
119+
type: 'string',
120+
},
121+
},
122+
},
123+
},
124+
},
125+
},
126+
errors: [],
127+
},
128+
]);

tools/spectral/ipa/rulesets/IPA-125.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ functions:
55
- IPA125OneOfMustHaveDiscriminator
66
- IPA125OneOfNoBaseTypes
77
- IPA125OneOfSchemaPropertySameType
8+
- IPA125DiscriminatorMustAccompanyOneOfAnyOfAllOf
89

910
rules:
1011
xgen-IPA-125-oneOf-must-have-discriminator:
@@ -79,3 +80,15 @@ rules:
7980
given: '$.components.schemas..oneOf'
8081
then:
8182
function: 'IPA125OneOfSchemaPropertySameType'
83+
84+
xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf:
85+
description: |
86+
Each discriminator property must be accompanied by a `oneOf`, `anyOf` or `allOf` property
87+
88+
##### Implementation details
89+
- Rule checks that a `discriminator` property has a `oneOf`, `anyOf` or `allOf` sibling
90+
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf'
91+
severity: warn
92+
given: '$..discriminator'
93+
then:
94+
function: 'IPA125DiscriminatorMustAccompanyOneOfAnyOfAllOf'

tools/spectral/ipa/rulesets/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,14 @@ Rule checks for the following conditions:
10041004
- Applies only to object type schemas with `oneOf`
10051005
- Ensures that if a property is defined in multiple `oneOf` schemas, it must have the same type in each schema (base type or object schema)
10061006

1007+
#### xgen-IPA-125-discriminator-must-accompany-oneOf-anyOf-allOf
1008+
1009+
![warn](https://img.shields.io/badge/warning-yellow)
1010+
Each discriminator property must be accompanied by a `oneOf`, `anyOf` or `allOf` property
1011+
1012+
##### Implementation details
1013+
- Rule checks that a `discriminator` property has a `oneOf`, `anyOf` or `allOf` sibling
1014+
10071015

10081016

10091017
### IPA-126
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { evaluateAndCollectAdoptionStatus } from './utils/collectionUtils.js';
2+
import { resolveObject } from './utils/componentUtils.js';
3+
4+
const ERROR_MESSAGE = "Each discriminator property must be accompanied by a 'oneOf', 'anyOf' or 'allOf' property.";
5+
6+
export default (input, _, { path, documentInventory, rule }) => {
7+
const siblingPath = path.slice(0, path.length - 1);
8+
const siblings = resolveObject(documentInventory.resolved, siblingPath);
9+
10+
const errors = checkViolationsAndReturnErrors(input, siblingPath, Object.keys(siblings));
11+
return evaluateAndCollectAdoptionStatus(errors, rule.name, siblings, siblingPath);
12+
};
13+
14+
function checkViolationsAndReturnErrors(input, path, siblingKeys) {
15+
if (!siblingKeys.includes('oneOf') && !siblingKeys.includes('anyOf') && !siblingKeys.includes('allOf')) {
16+
return [
17+
{
18+
path,
19+
message: ERROR_MESSAGE,
20+
},
21+
];
22+
}
23+
return [];
24+
}

0 commit comments

Comments
 (0)