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: "$.paths[*]~"
122
+ given:
123
+ - "$.paths[*]~"
124
+ - "$.servers[*].url"
121
125
  then:
122
126
  function: pattern
123
127
  functionOptions:
124
- match: "^(\/|[a-z0-9-]+|{[a-zA-Z0-9_|-]+})+$"
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
- oneOf:
179
- - properties:
180
- type:
181
- const: integer
182
- format:
183
- enum: [int32, int64]
184
- - properties:
185
- type:
186
- const: number
187
- format:
188
- enum: [float, double]
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 - Parameters, Request Body and Responses must have an examples defined."
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.*.*[responses,requestBody]..content.*
374
+ - $.paths.*.*.requestBody
375
+ - $.paths.*.*.responses[?(@property !== "204")]
366
376
  then:
367
- field: examples
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: Invalid combination: type '{{value.type}}' with format '{{value.format}}'"
824
- severity: "error"
825
- given: "$..[?(@.type=='number')]"
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
- field: format
828
- function: enumeration
837
+ function: schema
829
838
  functionOptions:
830
- values:
831
- - float
832
- - double
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
- given: "$.paths[*][get,post,put,patch,delete].parameters[*].$ref"
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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-quality-spectral-ruleset",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Spectral ruleset by API Quality",
5
5
  "main": "apq-spectral.yaml",
6
6
  "files": [