api-quality-spectral-ruleset 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/apq-spectral.yaml
CHANGED
|
@@ -12,6 +12,7 @@ functions:
|
|
|
12
12
|
- apq-required-fields-exist
|
|
13
13
|
- apq-security-check
|
|
14
14
|
- apq-custom-field
|
|
15
|
+
- apq-check-examples-coverage
|
|
15
16
|
extends:
|
|
16
17
|
- spectral:asyncapi
|
|
17
18
|
- spectral:oas
|
|
@@ -116,12 +117,15 @@ rules:
|
|
|
116
117
|
apiq:OAR011:
|
|
117
118
|
description: "URLs should follow the specified naming convention: all literal path segments must be in kebab-case."
|
|
118
119
|
message: "OAR011: The resource names with more than two words must be compliant with the standard naming convention (kebab-case)."
|
|
120
|
+
documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR011.md"
|
|
119
121
|
severity: error
|
|
120
|
-
given:
|
|
122
|
+
given:
|
|
123
|
+
- "$.paths[*]~"
|
|
124
|
+
- "$.servers[*].url"
|
|
121
125
|
then:
|
|
122
126
|
function: pattern
|
|
123
127
|
functionOptions:
|
|
124
|
-
match: "^(
|
|
128
|
+
match: "^(https?:\\/\\/[^\\/]+)?(\\/(?:[a-z0-9]+(?:-[a-z0-9]+)*|\\{[^}]+\\}))*\\/?$"
|
|
125
129
|
apiq:OAR012:
|
|
126
130
|
description: "Path params, query params, object names and property names should follow the configured naming convention. You can configure snake_case (default), kebab-case, camelCase or UpperCamelCase"
|
|
127
131
|
message: "OAR012: Path params, query params, object names and property names must follow the configured naming convention."
|
|
@@ -168,24 +172,29 @@ rules:
|
|
|
168
172
|
message: "OAR016: Numeric types must use a valid format for their type."
|
|
169
173
|
documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR016.md"
|
|
170
174
|
severity: error
|
|
171
|
-
given:
|
|
172
|
-
- "$..[?(@.type == 'integer' && @.format)]"
|
|
173
|
-
- "$..[?(@.type == 'number' && @.format)]"
|
|
175
|
+
given: "$..[?(@.type=='number' || @.type=='integer')]"
|
|
174
176
|
then:
|
|
175
177
|
function: schema
|
|
176
178
|
functionOptions:
|
|
177
179
|
schema:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
180
|
+
required: [format]
|
|
181
|
+
allOf:
|
|
182
|
+
- if:
|
|
183
|
+
properties:
|
|
184
|
+
type:
|
|
185
|
+
const: integer
|
|
186
|
+
then:
|
|
187
|
+
properties:
|
|
188
|
+
format:
|
|
189
|
+
enum: [int32, int64]
|
|
190
|
+
- if:
|
|
191
|
+
properties:
|
|
192
|
+
type:
|
|
193
|
+
const: number
|
|
194
|
+
then:
|
|
195
|
+
properties:
|
|
196
|
+
format:
|
|
197
|
+
enum: [float, double]
|
|
189
198
|
apiq:OAR017:
|
|
190
199
|
description: "Resource path should alternate static and parametrized parts."
|
|
191
200
|
message: "OAR017: Resource path should alternate static and parametrized parts."
|
|
@@ -358,14 +367,14 @@ rules:
|
|
|
358
367
|
function: truthy
|
|
359
368
|
apiq:OAR031:
|
|
360
369
|
description: The examples can help developers to understand the response data structure and representation."
|
|
361
|
-
message: "OAR031: Examples -
|
|
370
|
+
message: "OAR031: Examples - Parameters, Request Body and Responses must have an examples defined."
|
|
362
371
|
severity: error
|
|
363
372
|
given:
|
|
364
373
|
- $.paths.*.*.parameters.*
|
|
365
|
-
- $.paths
|
|
374
|
+
- $.paths.*.*.requestBody
|
|
375
|
+
- $.paths.*.*.responses[?(@property !== "204")]
|
|
366
376
|
then:
|
|
367
|
-
|
|
368
|
-
function: truthy
|
|
377
|
+
function: apq-check-examples-coverage
|
|
369
378
|
apiq:OAR032:
|
|
370
379
|
description: "Ambiguous path parts not encouraged."
|
|
371
380
|
message: "OAR032: When reading a URL, it must be possible to interpret which resources it is referring to in a concrete way. Ambiguous names in resources must be avoided."
|
|
@@ -820,16 +829,32 @@ rules:
|
|
|
820
829
|
- required: ["enum"]
|
|
821
830
|
apiq:OAR076:
|
|
822
831
|
description: "Schema should use well-defined type and format."
|
|
823
|
-
message: "OAR076:
|
|
824
|
-
|
|
825
|
-
|
|
832
|
+
message: "OAR076: Schema should use well-defined type and format."
|
|
833
|
+
documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR076.md"
|
|
834
|
+
severity: error
|
|
835
|
+
given: "$..[?(@.type=='number' || @.type=='integer')]"
|
|
826
836
|
then:
|
|
827
|
-
|
|
828
|
-
function: enumeration
|
|
837
|
+
function: schema
|
|
829
838
|
functionOptions:
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
839
|
+
schema:
|
|
840
|
+
required: [format]
|
|
841
|
+
allOf:
|
|
842
|
+
- if:
|
|
843
|
+
properties:
|
|
844
|
+
type:
|
|
845
|
+
const: integer
|
|
846
|
+
then:
|
|
847
|
+
properties:
|
|
848
|
+
format:
|
|
849
|
+
enum: [int32, int64]
|
|
850
|
+
- if:
|
|
851
|
+
properties:
|
|
852
|
+
type:
|
|
853
|
+
const: number
|
|
854
|
+
then:
|
|
855
|
+
properties:
|
|
856
|
+
format:
|
|
857
|
+
enum: [float, double]
|
|
833
858
|
apiq:OAR077:
|
|
834
859
|
description: "All parameters in query must be snake_case."
|
|
835
860
|
message: "OAR077: All parameters in query must be snake_case."
|
|
@@ -966,9 +991,12 @@ rules:
|
|
|
966
991
|
apiq:OAR091:
|
|
967
992
|
description: "Parameters must contain only $ref references."
|
|
968
993
|
message: "OAR091: Parameters must contain only $ref references."
|
|
994
|
+
documentationUrl: "https://github.com/apiaddicts/apquality-spectral/blob/main/docs/resources/OAR091.md"
|
|
969
995
|
severity: error
|
|
970
|
-
|
|
996
|
+
resolved: false
|
|
997
|
+
given: "$.paths[*][get,post,put,patch,delete].parameters[*]"
|
|
971
998
|
then:
|
|
999
|
+
field: $ref
|
|
972
1000
|
function: truthy
|
|
973
1001
|
apiq:OAR092:
|
|
974
1002
|
description: "RequestBody must contain a $ref."
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} given
|
|
3
|
+
* @param {object} options
|
|
4
|
+
* @param {import('@stoplight/spectral-core').RulesetFunctionContext} context
|
|
5
|
+
*/
|
|
6
|
+
module.exports = (given, options, context) => {
|
|
7
|
+
if (!given || typeof given !== 'object') return [];
|
|
8
|
+
|
|
9
|
+
const hasExample = (node) => {
|
|
10
|
+
if (!node || typeof node !== 'object') return false;
|
|
11
|
+
|
|
12
|
+
if (node.example !== undefined || node.examples !== undefined) return true;
|
|
13
|
+
|
|
14
|
+
if (node.content && typeof node.content === 'object') {
|
|
15
|
+
return Object.values(node.content).some(mediaType => hasExample(mediaType));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (node.schema) {
|
|
19
|
+
return checkSchema(node.schema);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (node.properties || node.items || node.type) {
|
|
23
|
+
return checkSchema(node);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return false;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const checkSchema = (schema) => {
|
|
30
|
+
if (!schema || typeof schema !== 'object') return false;
|
|
31
|
+
|
|
32
|
+
if (schema.example !== undefined || schema.examples !== undefined) return true;
|
|
33
|
+
|
|
34
|
+
if (schema.properties && typeof schema.properties === 'object') {
|
|
35
|
+
return Object.values(schema.properties).some(prop => checkSchema(prop));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (schema.items) {
|
|
39
|
+
return checkSchema(schema.items);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return false;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
if (!hasExample(given)) {
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
message: context.rule.message
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return [];
|
|
54
|
+
};
|