@redocly/openapi-core 1.0.0-beta.126 → 1.0.0-beta.127

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.
Files changed (275) hide show
  1. package/lib/bundle.js +5 -2
  2. package/lib/rules/common/spec.js +1 -0
  3. package/lib/rules/oas2/request-mime-type.d.ts +1 -1
  4. package/lib/rules/oas2/response-mime-type.d.ts +1 -1
  5. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +2 -2
  6. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +3 -3
  7. package/lib/rules/oas3/request-mime-type.d.ts +1 -1
  8. package/lib/rules/oas3/response-mime-type.d.ts +1 -1
  9. package/lib/walk.d.ts +6 -5
  10. package/lib/walk.js +23 -27
  11. package/package.json +1 -1
  12. package/__tests__/utils.ts +0 -88
  13. package/src/__tests__/__snapshots__/bundle.test.ts.snap +0 -437
  14. package/src/__tests__/bundle.test.ts +0 -236
  15. package/src/__tests__/codeframes.test.ts +0 -530
  16. package/src/__tests__/fixtures/.redocly.lint-ignore.yaml +0 -5
  17. package/src/__tests__/fixtures/extension.js +0 -24
  18. package/src/__tests__/fixtures/refs/definitions.yaml +0 -3
  19. package/src/__tests__/fixtures/refs/examples.yaml +0 -8
  20. package/src/__tests__/fixtures/refs/external-request-body.yaml +0 -13
  21. package/src/__tests__/fixtures/refs/externalref.yaml +0 -35
  22. package/src/__tests__/fixtures/refs/hosted.yaml +0 -35
  23. package/src/__tests__/fixtures/refs/openapi-with-external-refs-conflicting-names.yaml +0 -21
  24. package/src/__tests__/fixtures/refs/openapi-with-external-refs.yaml +0 -33
  25. package/src/__tests__/fixtures/refs/openapi-with-url-refs.yaml +0 -18
  26. package/src/__tests__/fixtures/refs/param-b.yaml +0 -1
  27. package/src/__tests__/fixtures/refs/param-c.yaml +0 -1
  28. package/src/__tests__/fixtures/refs/rename.yaml +0 -1
  29. package/src/__tests__/fixtures/refs/requestBody.yaml +0 -9
  30. package/src/__tests__/fixtures/refs/schema-a.yaml +0 -1
  31. package/src/__tests__/fixtures/refs/simple.yaml +0 -1
  32. package/src/__tests__/fixtures/refs/vendor.schema.yaml +0 -20
  33. package/src/__tests__/fixtures/resolve/External.yaml +0 -10
  34. package/src/__tests__/fixtures/resolve/External2.yaml +0 -4
  35. package/src/__tests__/fixtures/resolve/description.md +0 -3
  36. package/src/__tests__/fixtures/resolve/externalInfo.yaml +0 -4
  37. package/src/__tests__/fixtures/resolve/externalLicense.yaml +0 -1
  38. package/src/__tests__/fixtures/resolve/openapi-with-back.yaml +0 -13
  39. package/src/__tests__/fixtures/resolve/openapi-with-md-description.yaml +0 -5
  40. package/src/__tests__/fixtures/resolve/openapi.yaml +0 -28
  41. package/src/__tests__/fixtures/resolve/schemas/type-a.yaml +0 -10
  42. package/src/__tests__/fixtures/resolve/schemas/type-b.yaml +0 -6
  43. package/src/__tests__/fixtures/resolve/transitive/a.yaml +0 -1
  44. package/src/__tests__/fixtures/resolve/transitive/components.yaml +0 -5
  45. package/src/__tests__/fixtures/resolve/transitive/schemas.yaml +0 -3
  46. package/src/__tests__/format.test.ts +0 -76
  47. package/src/__tests__/js-yaml.test.ts +0 -73
  48. package/src/__tests__/lint.test.ts +0 -388
  49. package/src/__tests__/logger-browser.test.ts +0 -53
  50. package/src/__tests__/logger.test.ts +0 -47
  51. package/src/__tests__/login.test.ts +0 -17
  52. package/src/__tests__/normalizeVisitors.test.ts +0 -151
  53. package/src/__tests__/output-browser.test.ts +0 -18
  54. package/src/__tests__/output.test.ts +0 -15
  55. package/src/__tests__/ref-utils.test.ts +0 -120
  56. package/src/__tests__/resolve-http.test.ts +0 -77
  57. package/src/__tests__/resolve.test.ts +0 -430
  58. package/src/__tests__/utils-browser.test.ts +0 -11
  59. package/src/__tests__/utils.test.ts +0 -144
  60. package/src/__tests__/walk.test.ts +0 -1545
  61. package/src/benchmark/benches/lint-with-many-rules.bench.ts +0 -35
  62. package/src/benchmark/benches/lint-with-nested-rule.bench.ts +0 -39
  63. package/src/benchmark/benches/lint-with-no-rules.bench.ts +0 -20
  64. package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +0 -35
  65. package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +0 -32
  66. package/src/benchmark/benches/rebilly.yaml +0 -32275
  67. package/src/benchmark/benches/recommended-oas3.bench.ts +0 -22
  68. package/src/benchmark/benches/resolve-with-no-external.bench.ts +0 -23
  69. package/src/benchmark/benchmark.js +0 -311
  70. package/src/benchmark/colors.js +0 -29
  71. package/src/benchmark/fork.js +0 -83
  72. package/src/benchmark/utils.ts +0 -36
  73. package/src/bundle.ts +0 -399
  74. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +0 -161
  75. package/src/config/__tests__/__snapshots__/config.test.ts.snap +0 -144
  76. package/src/config/__tests__/config-resolvers.test.ts +0 -491
  77. package/src/config/__tests__/config.test.ts +0 -307
  78. package/src/config/__tests__/fixtures/ingore-file.ts +0 -8
  79. package/src/config/__tests__/fixtures/load-redocly.yaml +0 -2
  80. package/src/config/__tests__/fixtures/plugin-config.yaml +0 -2
  81. package/src/config/__tests__/fixtures/plugin.js +0 -56
  82. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +0 -11
  83. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +0 -69
  84. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +0 -7
  85. package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +0 -17
  86. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +0 -18
  87. package/src/config/__tests__/fixtures/resolve-config/local-config-with-wrong-custom-function.yaml +0 -15
  88. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +0 -9
  89. package/src/config/__tests__/fixtures/resolve-config/plugin.js +0 -80
  90. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +0 -3
  91. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +0 -4
  92. package/src/config/__tests__/load.test.ts +0 -167
  93. package/src/config/__tests__/resolve-plugins.test.ts +0 -27
  94. package/src/config/__tests__/utils.test.ts +0 -204
  95. package/src/config/all.ts +0 -73
  96. package/src/config/builtIn.ts +0 -37
  97. package/src/config/config-resolvers.ts +0 -465
  98. package/src/config/config.ts +0 -330
  99. package/src/config/index.ts +0 -7
  100. package/src/config/load.ts +0 -144
  101. package/src/config/minimal.ts +0 -60
  102. package/src/config/recommended.ts +0 -60
  103. package/src/config/rules.ts +0 -54
  104. package/src/config/types.ts +0 -216
  105. package/src/config/utils.ts +0 -333
  106. package/src/decorators/__tests__/filter-in.test.ts +0 -310
  107. package/src/decorators/__tests__/filter-out.test.ts +0 -335
  108. package/src/decorators/__tests__/media-type-examples-override.test.ts +0 -665
  109. package/src/decorators/__tests__/remove-x-internal.test.ts +0 -316
  110. package/src/decorators/__tests__/resources/request.yaml +0 -3
  111. package/src/decorators/__tests__/resources/response.yaml +0 -3
  112. package/src/decorators/common/filters/filter-helper.ts +0 -72
  113. package/src/decorators/common/filters/filter-in.ts +0 -18
  114. package/src/decorators/common/filters/filter-out.ts +0 -18
  115. package/src/decorators/common/info-description-override.ts +0 -24
  116. package/src/decorators/common/info-override.ts +0 -15
  117. package/src/decorators/common/media-type-examples-override.ts +0 -79
  118. package/src/decorators/common/operation-description-override.ts +0 -30
  119. package/src/decorators/common/registry-dependencies.ts +0 -25
  120. package/src/decorators/common/remove-x-internal.ts +0 -59
  121. package/src/decorators/common/tag-description-override.ts +0 -25
  122. package/src/decorators/oas2/index.ts +0 -20
  123. package/src/decorators/oas3/index.ts +0 -22
  124. package/src/env.ts +0 -5
  125. package/src/format/codeframes.ts +0 -216
  126. package/src/format/format.ts +0 -375
  127. package/src/index.ts +0 -71
  128. package/src/js-yaml/index.ts +0 -14
  129. package/src/lint.ts +0 -130
  130. package/src/logger.ts +0 -34
  131. package/src/oas-types.ts +0 -57
  132. package/src/output.ts +0 -7
  133. package/src/redocly/__tests__/redocly-client.test.ts +0 -146
  134. package/src/redocly/index.ts +0 -187
  135. package/src/redocly/redocly-client-types.ts +0 -10
  136. package/src/redocly/registry-api-types.ts +0 -32
  137. package/src/redocly/registry-api.ts +0 -149
  138. package/src/ref-utils.ts +0 -85
  139. package/src/resolve.ts +0 -417
  140. package/src/rules/__tests__/fixtures/code-sample.php +0 -9
  141. package/src/rules/__tests__/fixtures/invalid-yaml.yaml +0 -1
  142. package/src/rules/__tests__/fixtures/ref.yaml +0 -1
  143. package/src/rules/__tests__/no-unresolved-refs.test.ts +0 -257
  144. package/src/rules/__tests__/utils.test.ts +0 -160
  145. package/src/rules/ajv.ts +0 -102
  146. package/src/rules/common/__tests__/info-license.test.ts +0 -62
  147. package/src/rules/common/__tests__/license-url.test.ts +0 -63
  148. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +0 -96
  149. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +0 -210
  150. package/src/rules/common/__tests__/no-identical-paths.test.ts +0 -58
  151. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +0 -85
  152. package/src/rules/common/__tests__/operation-2xx-response.test.ts +0 -192
  153. package/src/rules/common/__tests__/operation-4xx-response.test.ts +0 -231
  154. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +0 -76
  155. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +0 -45
  156. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +0 -167
  157. package/src/rules/common/__tests__/operation-singular-tag.test.ts +0 -72
  158. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +0 -95
  159. package/src/rules/common/__tests__/path-not-include-query.test.ts +0 -64
  160. package/src/rules/common/__tests__/path-params-defined.test.ts +0 -202
  161. package/src/rules/common/__tests__/paths-kebab-case.test.ts +0 -108
  162. package/src/rules/common/__tests__/scalar-property-missing-example.test.ts +0 -264
  163. package/src/rules/common/__tests__/security-defined.test.ts +0 -175
  164. package/src/rules/common/__tests__/spec.test.ts +0 -555
  165. package/src/rules/common/__tests__/tag-description.test.ts +0 -65
  166. package/src/rules/common/__tests__/tags-alphabetical.test.ts +0 -64
  167. package/src/rules/common/assertions/__tests__/asserts.test.ts +0 -869
  168. package/src/rules/common/assertions/__tests__/index.test.ts +0 -100
  169. package/src/rules/common/assertions/__tests__/utils.test.ts +0 -236
  170. package/src/rules/common/assertions/asserts.ts +0 -357
  171. package/src/rules/common/assertions/index.ts +0 -56
  172. package/src/rules/common/assertions/utils.ts +0 -331
  173. package/src/rules/common/info-contact.ts +0 -15
  174. package/src/rules/common/info-license-url.ts +0 -10
  175. package/src/rules/common/info-license.ts +0 -15
  176. package/src/rules/common/no-ambiguous-paths.ts +0 -50
  177. package/src/rules/common/no-enum-type-mismatch.ts +0 -52
  178. package/src/rules/common/no-http-verbs-in-paths.ts +0 -36
  179. package/src/rules/common/no-identical-paths.ts +0 -24
  180. package/src/rules/common/no-invalid-parameter-examples.ts +0 -36
  181. package/src/rules/common/no-invalid-schema-examples.ts +0 -27
  182. package/src/rules/common/no-path-trailing-slash.ts +0 -15
  183. package/src/rules/common/operation-2xx-response.ts +0 -24
  184. package/src/rules/common/operation-4xx-response.ts +0 -24
  185. package/src/rules/common/operation-description.ts +0 -13
  186. package/src/rules/common/operation-operationId-unique.ts +0 -21
  187. package/src/rules/common/operation-operationId-url-safe.ts +0 -19
  188. package/src/rules/common/operation-operationId.ts +0 -17
  189. package/src/rules/common/operation-parameters-unique.ts +0 -48
  190. package/src/rules/common/operation-singular-tag.ts +0 -17
  191. package/src/rules/common/operation-summary.ts +0 -13
  192. package/src/rules/common/operation-tag-defined.ts +0 -26
  193. package/src/rules/common/parameter-description.ts +0 -22
  194. package/src/rules/common/path-declaration-must-exist.ts +0 -15
  195. package/src/rules/common/path-excludes-patterns.ts +0 -23
  196. package/src/rules/common/path-http-verbs-order.ts +0 -30
  197. package/src/rules/common/path-not-include-query.ts +0 -17
  198. package/src/rules/common/path-params-defined.ts +0 -65
  199. package/src/rules/common/path-segment-plural.ts +0 -31
  200. package/src/rules/common/paths-kebab-case.ts +0 -19
  201. package/src/rules/common/required-string-property-missing-min-length.ts +0 -44
  202. package/src/rules/common/response-contains-header.ts +0 -35
  203. package/src/rules/common/scalar-property-missing-example.ts +0 -58
  204. package/src/rules/common/security-defined.ts +0 -65
  205. package/src/rules/common/spec.ts +0 -174
  206. package/src/rules/common/tag-description.ts +0 -10
  207. package/src/rules/common/tags-alphabetical.ts +0 -20
  208. package/src/rules/no-unresolved-refs.ts +0 -51
  209. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +0 -110
  210. package/src/rules/oas2/__tests__/response-contains-header.test.ts +0 -174
  211. package/src/rules/oas2/__tests__/response-contains-property.test.ts +0 -155
  212. package/src/rules/oas2/__tests__/spec/fixtures/description.md +0 -1
  213. package/src/rules/oas2/__tests__/spec/info.test.ts +0 -355
  214. package/src/rules/oas2/__tests__/spec/operation.test.ts +0 -123
  215. package/src/rules/oas2/__tests__/spec/paths.test.ts +0 -245
  216. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +0 -35
  217. package/src/rules/oas2/__tests__/spec/utils.ts +0 -32
  218. package/src/rules/oas2/boolean-parameter-prefixes.ts +0 -26
  219. package/src/rules/oas2/index.ts +0 -89
  220. package/src/rules/oas2/remove-unused-components.ts +0 -81
  221. package/src/rules/oas2/request-mime-type.ts +0 -17
  222. package/src/rules/oas2/response-contains-property.ts +0 -36
  223. package/src/rules/oas2/response-mime-type.ts +0 -17
  224. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +0 -111
  225. package/src/rules/oas3/__tests__/fixtures/common.yaml +0 -11
  226. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +0 -205
  227. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +0 -65
  228. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +0 -473
  229. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +0 -60
  230. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +0 -79
  231. package/src/rules/oas3/__tests__/no-unused-components.test.ts +0 -131
  232. package/src/rules/oas3/__tests__/operation-4xx-problem-details-rfc7807.test.ts +0 -145
  233. package/src/rules/oas3/__tests__/response-contains-header.test.ts +0 -389
  234. package/src/rules/oas3/__tests__/response-contains-property.test.ts +0 -403
  235. package/src/rules/oas3/__tests__/spec/callbacks.test.ts +0 -41
  236. package/src/rules/oas3/__tests__/spec/fixtures/description.md +0 -1
  237. package/src/rules/oas3/__tests__/spec/info.test.ts +0 -391
  238. package/src/rules/oas3/__tests__/spec/operation.test.ts +0 -253
  239. package/src/rules/oas3/__tests__/spec/paths.test.ts +0 -284
  240. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +0 -77
  241. package/src/rules/oas3/__tests__/spec/servers.test.ts +0 -505
  242. package/src/rules/oas3/__tests__/spec/spec.test.ts +0 -298
  243. package/src/rules/oas3/__tests__/spec/utils.ts +0 -32
  244. package/src/rules/oas3/__tests__/spec-components-invalid-map-name.test.ts +0 -305
  245. package/src/rules/oas3/boolean-parameter-prefixes.ts +0 -28
  246. package/src/rules/oas3/index.ts +0 -109
  247. package/src/rules/oas3/no-empty-servers.ts +0 -22
  248. package/src/rules/oas3/no-example-value-and-externalValue.ts +0 -14
  249. package/src/rules/oas3/no-invalid-media-type-examples.ts +0 -49
  250. package/src/rules/oas3/no-server-example.com.ts +0 -14
  251. package/src/rules/oas3/no-server-trailing-slash.ts +0 -15
  252. package/src/rules/oas3/no-server-variables-empty-enum.ts +0 -66
  253. package/src/rules/oas3/no-undefined-server-variable.ts +0 -30
  254. package/src/rules/oas3/no-unused-components.ts +0 -75
  255. package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +0 -36
  256. package/src/rules/oas3/remove-unused-components.ts +0 -95
  257. package/src/rules/oas3/request-mime-type.ts +0 -31
  258. package/src/rules/oas3/response-contains-property.ts +0 -38
  259. package/src/rules/oas3/response-mime-type.ts +0 -31
  260. package/src/rules/oas3/spec-components-invalid-map-name.ts +0 -74
  261. package/src/rules/other/stats.ts +0 -73
  262. package/src/rules/utils.ts +0 -191
  263. package/src/types/index.ts +0 -149
  264. package/src/types/oas2.ts +0 -478
  265. package/src/types/oas3.ts +0 -597
  266. package/src/types/oas3_1.ts +0 -258
  267. package/src/types/redocly-yaml.ts +0 -1010
  268. package/src/typings/common.ts +0 -17
  269. package/src/typings/openapi.ts +0 -298
  270. package/src/typings/swagger.ts +0 -236
  271. package/src/utils.ts +0 -276
  272. package/src/visitors.ts +0 -491
  273. package/src/walk.ts +0 -453
  274. package/tsconfig.json +0 -8
  275. package/tsconfig.tsbuildinfo +0 -1
@@ -1,56 +0,0 @@
1
- import { asserts, AssertionFn } from './asserts';
2
- import { buildSubjectVisitor, buildVisitorObject } from './utils';
3
- import { Oas2Visitor, Oas3Visitor } from '../../../visitors';
4
- import { RuleSeverity } from '../../../config';
5
- import { isString } from '../../../utils';
6
-
7
- export type AssertionLocators = {
8
- filterInParentKeys?: (string | number)[];
9
- filterOutParentKeys?: (string | number)[];
10
- matchParentKeys?: string;
11
- };
12
-
13
- export type AssertionDefinition = {
14
- subject: {
15
- type: string;
16
- property?: string | string[];
17
- } & AssertionLocators;
18
- assertions: { [name in keyof typeof asserts]?: AssertionFn };
19
- };
20
-
21
- export type RawAssertion = AssertionDefinition & {
22
- where?: AssertionDefinition[];
23
- message?: string;
24
- suggest?: string[];
25
- severity?: RuleSeverity;
26
- };
27
-
28
- export type Assertion = RawAssertion & { assertionId: string };
29
-
30
- export const Assertions = (opts: Record<string, Assertion>) => {
31
- const visitors: (Oas2Visitor | Oas3Visitor)[] = [];
32
-
33
- // As 'Assertions' has an array of asserts,
34
- // that array spreads into an 'opts' object on init rules phase here
35
- // https://github.com/Redocly/redocly-cli/blob/main/packages/core/src/config/config.ts#L311
36
- // that is why we need to iterate through 'opts' values;
37
- // before - filter only object 'opts' values
38
- const assertions: Assertion[] = Object.values(opts).filter(
39
- (opt: unknown) => typeof opt === 'object' && opt !== null
40
- );
41
-
42
- for (const [index, assertion] of assertions.entries()) {
43
- const assertId =
44
- (assertion.assertionId && `${assertion.assertionId} assertion`) || `assertion #${index + 1}`;
45
-
46
- if (!isString(assertion.subject.type)) {
47
- throw new Error(`${assertId}: 'type' (String) is required`);
48
- }
49
-
50
- const subjectVisitor = buildSubjectVisitor(assertId, assertion);
51
- const visitorObject = buildVisitorObject(assertion, subjectVisitor);
52
- visitors.push(visitorObject);
53
- }
54
-
55
- return visitors;
56
- };
@@ -1,331 +0,0 @@
1
- import { asserts, runOnKeysSet, runOnValuesSet, Asserts } from './asserts';
2
- import { colorize } from '../../../logger';
3
- import { isRef } from '../../../ref-utils';
4
- import { isTruthy, keysOf, isString } from '../../../utils';
5
- import type { AssertionContext, AssertResult } from '../../../config';
6
- import type { Assertion, AssertionDefinition, AssertionLocators } from '.';
7
- import type {
8
- Oas2Visitor,
9
- Oas3Visitor,
10
- SkipFunctionContext,
11
- VisitFunction,
12
- } from '../../../visitors';
13
- import { UserContext } from 'core/src/walk';
14
-
15
- export type OrderDirection = 'asc' | 'desc';
16
-
17
- export type OrderOptions = {
18
- direction: OrderDirection;
19
- property: string;
20
- };
21
-
22
- export type AssertToApply = {
23
- name: keyof Asserts;
24
- conditions: any;
25
- runsOnKeys: boolean;
26
- runsOnValues: boolean;
27
- };
28
-
29
- type RunAssertionParams = {
30
- ctx: AssertionContext;
31
- assert: AssertToApply;
32
- assertionProperty?: string;
33
- };
34
-
35
- const assertionMessageTemplates = {
36
- problems: '{{problems}}',
37
- };
38
-
39
- function getPredicatesFromLocators(
40
- locators: AssertionLocators
41
- ): ((key: string | number) => boolean)[] {
42
- const { filterInParentKeys, filterOutParentKeys, matchParentKeys } = locators;
43
-
44
- const keyMatcher = matchParentKeys && regexFromString(matchParentKeys);
45
- const matchKeysPredicate =
46
- keyMatcher && ((key: string | number) => keyMatcher.test(key.toString()));
47
-
48
- const filterInPredicate =
49
- Array.isArray(filterInParentKeys) &&
50
- ((key: string | number) => filterInParentKeys.includes(key.toString()));
51
-
52
- const filterOutPredicate =
53
- Array.isArray(filterOutParentKeys) &&
54
- ((key: string | number) => !filterOutParentKeys.includes(key.toString()));
55
-
56
- return [matchKeysPredicate, filterInPredicate, filterOutPredicate].filter(isTruthy);
57
- }
58
-
59
- export function getAssertsToApply(assertion: AssertionDefinition): AssertToApply[] {
60
- const assertsToApply = keysOf(asserts)
61
- .filter((assertName) => assertion.assertions[assertName] !== undefined)
62
- .map((assertName) => {
63
- return {
64
- name: assertName,
65
- conditions: assertion.assertions[assertName],
66
- runsOnKeys: runOnKeysSet.has(assertName),
67
- runsOnValues: runOnValuesSet.has(assertName),
68
- };
69
- });
70
-
71
- const shouldRunOnKeys: AssertToApply | undefined = assertsToApply.find(
72
- (assert: AssertToApply) => assert.runsOnKeys && !assert.runsOnValues
73
- );
74
- const shouldRunOnValues: AssertToApply | undefined = assertsToApply.find(
75
- (assert: AssertToApply) => assert.runsOnValues && !assert.runsOnKeys
76
- );
77
-
78
- if (shouldRunOnValues && !assertion.subject.property) {
79
- throw new Error(
80
- `${shouldRunOnValues.name} can't be used on all keys. Please provide a single property`
81
- );
82
- }
83
-
84
- if (shouldRunOnKeys && assertion.subject.property) {
85
- throw new Error(
86
- `${shouldRunOnKeys.name} can't be used on a single property. Please use 'property'.`
87
- );
88
- }
89
-
90
- return assertsToApply;
91
- }
92
-
93
- function getAssertionProperties({ subject }: AssertionDefinition): string[] {
94
- return (Array.isArray(subject.property) ? subject.property : [subject?.property]).filter(
95
- Boolean
96
- ) as string[];
97
- }
98
-
99
- function applyAssertions(
100
- assertionDefinition: AssertionDefinition,
101
- asserts: AssertToApply[],
102
- ctx: AssertionContext
103
- ): AssertResult[] {
104
- const properties = getAssertionProperties(assertionDefinition);
105
- const assertResults: Array<AssertResult[]> = [];
106
-
107
- for (const assert of asserts) {
108
- if (properties.length) {
109
- for (const property of properties) {
110
- assertResults.push(
111
- runAssertion({
112
- assert,
113
- ctx,
114
- assertionProperty: property,
115
- })
116
- );
117
- }
118
- } else {
119
- assertResults.push(
120
- runAssertion({
121
- assert,
122
- ctx,
123
- })
124
- );
125
- }
126
- }
127
-
128
- return assertResults.flat();
129
- }
130
-
131
- export function buildVisitorObject(
132
- assertion: Assertion,
133
- subjectVisitor: VisitFunction<any>
134
- ): Oas2Visitor | Oas3Visitor {
135
- const targetVisitorLocatorPredicates = getPredicatesFromLocators(assertion.subject);
136
- const targetVisitorSkipFunction = targetVisitorLocatorPredicates.length
137
- ? (_: any, key: string | number) =>
138
- !targetVisitorLocatorPredicates.every((predicate) => predicate(key))
139
- : undefined;
140
- const targetVisitor: Oas2Visitor | Oas3Visitor = {
141
- [assertion.subject.type]: {
142
- enter: subjectVisitor,
143
- ...(targetVisitorSkipFunction && { skip: targetVisitorSkipFunction }),
144
- },
145
- };
146
-
147
- if (!Array.isArray(assertion.where)) {
148
- return targetVisitor;
149
- }
150
-
151
- let currentVisitorLevel: Record<string, any> = {};
152
- const visitor: Record<string, any> = currentVisitorLevel;
153
- const context = assertion.where;
154
-
155
- for (let index = 0; index < context.length; index++) {
156
- const assertionDefinitionNode = context[index];
157
-
158
- if (!isString(assertionDefinitionNode.subject?.type)) {
159
- throw new Error(
160
- `${assertion.assertionId} -> where -> [${index}]: 'type' (String) is required`
161
- );
162
- }
163
-
164
- const locatorPredicates = getPredicatesFromLocators(assertionDefinitionNode.subject);
165
- const assertsToApply = getAssertsToApply(assertionDefinitionNode);
166
-
167
- const skipFunction = (node: unknown, key: string | number, ctx: SkipFunctionContext): boolean =>
168
- !locatorPredicates.every((predicate) => predicate(key)) ||
169
- !!applyAssertions(assertionDefinitionNode, assertsToApply, { ...ctx, node }).length;
170
-
171
- const nodeVisitor = {
172
- ...((locatorPredicates.length || assertsToApply.length) && { skip: skipFunction }),
173
- };
174
-
175
- if (
176
- assertionDefinitionNode.subject.type === assertion.subject.type &&
177
- index === context.length - 1
178
- ) {
179
- // We have to merge the visitors if the last node inside the `where` is the same as the subject.
180
- targetVisitor[assertion.subject.type] = {
181
- enter: subjectVisitor,
182
- ...((nodeVisitor.skip && { skip: nodeVisitor.skip }) ||
183
- (targetVisitorSkipFunction && {
184
- skip: (
185
- node,
186
- key,
187
- ctx // We may have locators defined on assertion level and on where level for the same node type
188
- ) => !!(nodeVisitor.skip?.(node, key, ctx) || targetVisitorSkipFunction?.(node, key)),
189
- })),
190
- };
191
- } else {
192
- currentVisitorLevel = currentVisitorLevel[assertionDefinitionNode.subject?.type] =
193
- nodeVisitor;
194
- }
195
- }
196
-
197
- currentVisitorLevel[assertion.subject.type] = targetVisitor[assertion.subject.type];
198
-
199
- return visitor;
200
- }
201
-
202
- export function buildSubjectVisitor(assertId: string, assertion: Assertion): VisitFunction<any> {
203
- return (node: any, ctx: UserContext) => {
204
- const properties = getAssertionProperties(assertion);
205
-
206
- const defaultMessage = `${colorize.blue(assertId)} failed because the ${colorize.blue(
207
- assertion.subject.type
208
- )} ${colorize.blue(properties.join(', '))} didn't meet the assertions: ${
209
- assertionMessageTemplates.problems
210
- }`.replace(/ +/g, ' ');
211
-
212
- const problems = applyAssertions(assertion, getAssertsToApply(assertion), {
213
- ...ctx,
214
- node,
215
- });
216
-
217
- if (problems.length) {
218
- for (const problemGroup of groupProblemsByPointer(problems)) {
219
- const message = assertion.message || defaultMessage;
220
- const problemMessage = getProblemsMessage(problemGroup);
221
- ctx.report({
222
- message: message.replace(assertionMessageTemplates.problems, problemMessage),
223
- location: getProblemsLocation(problemGroup) || ctx.location,
224
- forceSeverity: assertion.severity || 'error',
225
- suggest: assertion.suggest || [],
226
- ruleId: assertId,
227
- });
228
- }
229
- }
230
- };
231
- }
232
-
233
- function groupProblemsByPointer(problems: AssertResult[]): AssertResult[][] {
234
- const groups: Record<string, AssertResult[]> = {};
235
- for (const problem of problems) {
236
- if (!problem.location) continue;
237
- const pointer = problem.location.pointer;
238
- groups[pointer] = groups[pointer] || [];
239
- groups[pointer].push(problem);
240
- }
241
- return Object.values(groups);
242
- }
243
-
244
- function getProblemsLocation(problems: AssertResult[]) {
245
- return problems.length ? problems[0].location : undefined;
246
- }
247
-
248
- function getProblemsMessage(problems: AssertResult[]) {
249
- return problems.length === 1
250
- ? problems[0].message ?? ''
251
- : problems.map((problem) => `\n- ${problem.message ?? ''}`).join('');
252
- }
253
-
254
- export function getIntersectionLength(keys: string[], properties: string[]): number {
255
- const props = new Set(properties);
256
- let count = 0;
257
- for (const key of keys) {
258
- if (props.has(key)) {
259
- count++;
260
- }
261
- }
262
- return count;
263
- }
264
-
265
- export function isOrdered(value: any[], options: OrderOptions | OrderDirection): boolean {
266
- const direction = (options as OrderOptions).direction || (options as OrderDirection);
267
- const property = (options as OrderOptions).property;
268
- for (let i = 1; i < value.length; i++) {
269
- let currValue = value[i];
270
- let prevVal = value[i - 1];
271
-
272
- if (property) {
273
- const currPropValue = value[i][property];
274
- const prevPropValue = value[i - 1][property];
275
-
276
- if (!currPropValue || !prevPropValue) {
277
- return false; // property doesn't exist, so collection is not ordered
278
- }
279
-
280
- currValue = currPropValue;
281
- prevVal = prevPropValue;
282
- }
283
-
284
- if (typeof currValue === 'string' && typeof prevVal === 'string') {
285
- currValue = currValue.toLowerCase();
286
- prevVal = prevVal.toLowerCase();
287
- }
288
-
289
- const result = direction === 'asc' ? currValue >= prevVal : currValue <= prevVal;
290
- if (!result) {
291
- return false;
292
- }
293
- }
294
- return true;
295
- }
296
-
297
- export function runAssertion({
298
- assert,
299
- ctx,
300
- assertionProperty,
301
- }: RunAssertionParams): AssertResult[] {
302
- const currentLocation = assert.name === 'ref' ? ctx.rawLocation : ctx.location;
303
-
304
- if (assertionProperty) {
305
- const values = isRef(ctx.node[assertionProperty])
306
- ? ctx.resolve(ctx.node[assertionProperty])?.node
307
- : ctx.node[assertionProperty];
308
- const rawValues = ctx.rawNode[assertionProperty];
309
-
310
- const location = currentLocation.child(assertionProperty);
311
-
312
- return asserts[assert.name](values, assert.conditions, {
313
- ...ctx,
314
- baseLocation: location,
315
- rawValue: rawValues,
316
- });
317
- } else {
318
- const value = Array.isArray(ctx.node) ? ctx.node : Object.keys(ctx.node);
319
-
320
- return asserts[assert.name](value, assert.conditions, {
321
- ...ctx,
322
- rawValue: ctx.rawNode,
323
- baseLocation: currentLocation,
324
- });
325
- }
326
- }
327
-
328
- export function regexFromString(input: string): RegExp | null {
329
- const matches = input.match(/^\/(.*)\/(.*)|(.*)/);
330
- return matches && new RegExp(matches[1] || matches[3], matches[2]);
331
- }
@@ -1,15 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { missingRequiredField } from '../utils';
3
-
4
- export const InfoContact: Oas3Rule | Oas2Rule = () => {
5
- return {
6
- Info(info, { report, location }) {
7
- if (!info.contact) {
8
- report({
9
- message: missingRequiredField('Info', 'contact'),
10
- location: location.child('contact').key(),
11
- });
12
- }
13
- },
14
- };
15
- };
@@ -1,10 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { validateDefinedAndNonEmpty } from '../utils';
3
-
4
- export const InfoLicenseUrl: Oas3Rule | Oas2Rule = () => {
5
- return {
6
- License(license, ctx) {
7
- validateDefinedAndNonEmpty('url', license, ctx);
8
- },
9
- };
10
- };
@@ -1,15 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { missingRequiredField } from '../utils';
3
-
4
- export const InfoLicense: Oas3Rule | Oas2Rule = () => {
5
- return {
6
- Info(info, { report }) {
7
- if (!info.license) {
8
- report({
9
- message: missingRequiredField('Info', 'license'),
10
- location: { reportOnKey: true },
11
- });
12
- }
13
- },
14
- };
15
- };
@@ -1,50 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { UserContext } from '../../walk';
3
- import { Oas3Paths } from '../../typings/openapi';
4
- import { Oas2Paths } from '../../typings/swagger';
5
-
6
- export const NoAmbiguousPaths: Oas3Rule | Oas2Rule = () => {
7
- return {
8
- Paths(pathMap: Oas3Paths | Oas2Paths, { report, location }: UserContext) {
9
- const seenPaths: string[] = [];
10
-
11
- for (const currentPath of Object.keys(pathMap)) {
12
- const ambiguousPath = seenPaths.find((seenPath) =>
13
- arePathsAmbiguous(seenPath, currentPath)
14
- );
15
- if (ambiguousPath) {
16
- report({
17
- message: `Paths should resolve unambiguously. Found two ambiguous paths: \`${ambiguousPath}\` and \`${currentPath}\`.`,
18
- location: location.child([currentPath]).key(),
19
- });
20
- }
21
- seenPaths.push(currentPath);
22
- }
23
- },
24
- };
25
- };
26
-
27
- function arePathsAmbiguous(a: string, b: string) {
28
- const partsA = a.split('/');
29
- const partsB = b.split('/');
30
-
31
- if (partsA.length !== partsB.length) return false;
32
-
33
- let aVars = 0;
34
- let bVars = 0;
35
- let ambiguous = true;
36
- for (let i = 0; i < partsA.length; i++) {
37
- const aIsVar = partsA[i].match(/^{.+?}$/);
38
- const bIsVar = partsB[i].match(/^{.+?}$/);
39
-
40
- if (aIsVar || bIsVar) {
41
- if (aIsVar) aVars++;
42
- if (bIsVar) bVars++;
43
- continue;
44
- } else if (partsA[i] !== partsB[i]) {
45
- ambiguous = false;
46
- }
47
- }
48
-
49
- return ambiguous && aVars === bVars;
50
- }
@@ -1,52 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { matchesJsonSchemaType, oasTypeOf } from '../utils';
3
- import { Oas2Schema } from '../../typings/swagger';
4
- import { Oas3Schema } from '../../typings/openapi';
5
- import { UserContext } from '../../walk';
6
-
7
- export const NoEnumTypeMismatch: Oas3Rule | Oas2Rule = () => {
8
- return {
9
- Schema(schema: Oas2Schema | Oas3Schema, { report, location }: UserContext) {
10
- if (schema.enum && !Array.isArray(schema.enum)) return;
11
- if (schema.enum && schema.type && !Array.isArray(schema.type)) {
12
- const typeMismatchedValues = schema.enum.filter(
13
- (item) => !matchesJsonSchemaType(item, schema.type as string, schema.nullable as boolean)
14
- );
15
- for (const mismatchedValue of typeMismatchedValues) {
16
- report({
17
- message: `All values of \`enum\` field must be of the same type as the \`type\` field: expected "${
18
- schema.type
19
- }" but received "${oasTypeOf(mismatchedValue)}".`,
20
- location: location.child(['enum', schema.enum.indexOf(mismatchedValue)]),
21
- });
22
- }
23
- }
24
-
25
- if (schema.enum && schema.type && Array.isArray(schema.type)) {
26
- const mismatchedResults: { [key: string]: string[] } = {};
27
- for (const enumValue of schema.enum) {
28
- mismatchedResults[enumValue] = [];
29
-
30
- for (const type of schema.type) {
31
- const valid = matchesJsonSchemaType(
32
- enumValue,
33
- type as string,
34
- schema.nullable as boolean
35
- );
36
- if (!valid) mismatchedResults[enumValue].push(type);
37
- }
38
-
39
- if (mismatchedResults[enumValue].length !== schema.type.length)
40
- delete mismatchedResults[enumValue];
41
- }
42
-
43
- for (const mismatchedKey of Object.keys(mismatchedResults)) {
44
- report({
45
- message: `Enum value \`${mismatchedKey}\` must be of allowed types: \`${schema.type}\`.`,
46
- location: location.child(['enum', schema.enum.indexOf(mismatchedKey)]),
47
- });
48
- }
49
- }
50
- },
51
- };
52
- };
@@ -1,36 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { Oas2PathItem } from '../../typings/swagger';
3
- import { Oas3PathItem } from '../../typings/openapi';
4
- import { UserContext } from '../../walk';
5
- import { isPathParameter, splitCamelCaseIntoWords } from '../../utils';
6
-
7
- const httpMethods = ['get', 'head', 'post', 'put', 'patch', 'delete', 'options', 'trace'];
8
-
9
- export const NoHttpVerbsInPaths: Oas3Rule | Oas2Rule = ({ splitIntoWords }) => {
10
- return {
11
- PathItem(_path: Oas2PathItem | Oas3PathItem, { key, report, location }: UserContext) {
12
- const pathKey = key.toString();
13
- if (!pathKey.startsWith('/')) return;
14
- const pathSegments = pathKey.split('/');
15
-
16
- for (const pathSegment of pathSegments) {
17
- if (!pathSegment || isPathParameter(pathSegment)) continue;
18
-
19
- const isHttpMethodIncluded = (method: string) => {
20
- return splitIntoWords
21
- ? splitCamelCaseIntoWords(pathSegment).has(method)
22
- : pathSegment.toLocaleLowerCase().includes(method);
23
- };
24
-
25
- for (const method of httpMethods) {
26
- if (isHttpMethodIncluded(method)) {
27
- report({
28
- message: `path \`${pathKey}\` should not contain http verb ${method}`,
29
- location: location.key(),
30
- });
31
- }
32
- }
33
- }
34
- },
35
- };
36
- };
@@ -1,24 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { UserContext } from '../../walk';
3
- import { Oas3Paths } from '../../typings/openapi';
4
- import { Oas2Paths } from '../../typings/swagger';
5
-
6
- export const NoIdenticalPaths: Oas3Rule | Oas2Rule = () => {
7
- return {
8
- Paths(pathMap: Oas3Paths | Oas2Paths, { report, location }: UserContext) {
9
- const Paths = new Map<string, string>();
10
- for (const pathName of Object.keys(pathMap)) {
11
- const id = pathName.replace(/{.+?}/g, '{VARIABLE}');
12
- const existingSamePath = Paths.get(id);
13
- if (existingSamePath) {
14
- report({
15
- message: `The path already exists which differs only by path parameter name(s): \`${existingSamePath}\` and \`${pathName}\`.`,
16
- location: location.child([pathName]).key(),
17
- });
18
- } else {
19
- Paths.set(id, pathName);
20
- }
21
- }
22
- },
23
- };
24
- };
@@ -1,36 +0,0 @@
1
- import { UserContext } from '../../walk';
2
- import { Oas3Parameter } from '../../typings/openapi';
3
- import { getAdditionalPropertiesOption, validateExample } from '../utils';
4
-
5
- export const NoInvalidParameterExamples: any = (opts: any) => {
6
- const allowAdditionalProperties = getAdditionalPropertiesOption(opts) ?? false;
7
- return {
8
- Parameter: {
9
- leave(parameter: Oas3Parameter, ctx: UserContext) {
10
- if (parameter.example) {
11
- validateExample(
12
- parameter.example,
13
- parameter.schema!,
14
- ctx.location.child('example'),
15
- ctx,
16
- allowAdditionalProperties
17
- );
18
- }
19
-
20
- if (parameter.examples) {
21
- for (const [key, example] of Object.entries(parameter.examples)) {
22
- if ('value' in example) {
23
- validateExample(
24
- example.value,
25
- parameter.schema!,
26
- ctx.location.child(['examples', key]),
27
- ctx,
28
- true
29
- );
30
- }
31
- }
32
- }
33
- },
34
- },
35
- };
36
- };
@@ -1,27 +0,0 @@
1
- import { UserContext } from '../../walk';
2
- import { Oas3_1Schema } from '../../typings/openapi';
3
- import { getAdditionalPropertiesOption, validateExample } from '../utils';
4
-
5
- export const NoInvalidSchemaExamples: any = (opts: any) => {
6
- const allowAdditionalProperties = getAdditionalPropertiesOption(opts) ?? false;
7
- return {
8
- Schema: {
9
- leave(schema: Oas3_1Schema, ctx: UserContext) {
10
- if (schema.examples) {
11
- for (const example of schema.examples) {
12
- validateExample(
13
- example,
14
- schema,
15
- ctx.location.child(['examples', schema.examples.indexOf(example)]),
16
- ctx,
17
- allowAdditionalProperties
18
- );
19
- }
20
- }
21
- if (schema.example) {
22
- validateExample(schema.example, schema, ctx.location.child('example'), ctx, true);
23
- }
24
- },
25
- },
26
- };
27
- };
@@ -1,15 +0,0 @@
1
- import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { UserContext } from '../../walk';
3
-
4
- export const NoPathTrailingSlash: Oas3Rule | Oas2Rule = () => {
5
- return {
6
- PathItem(_path: any, { report, key, location }: UserContext) {
7
- if ((key as string).endsWith('/') && key !== '/') {
8
- report({
9
- message: `\`${key}\` should not have a trailing slash.`,
10
- location: location.key(),
11
- });
12
- }
13
- },
14
- };
15
- };