@redocly/openapi-core 1.0.0-beta.98 → 1.0.0-rc.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.
Files changed (380) hide show
  1. package/README.md +6 -6
  2. package/lib/benchmark/benches/lint-with-top-level-rule-report.bench.js +0 -1
  3. package/lib/benchmark/benches/recommended-oas3.bench.js +1 -1
  4. package/lib/benchmark/benches/resolve-with-no-external.bench.js +1 -1
  5. package/lib/benchmark/utils.d.ts +2 -2
  6. package/lib/benchmark/utils.js +2 -2
  7. package/lib/bundle.d.ts +12 -15
  8. package/lib/bundle.js +38 -15
  9. package/lib/config/all.d.ts +2 -2
  10. package/lib/config/all.js +17 -6
  11. package/lib/config/builtIn.d.ts +2 -2
  12. package/lib/config/builtIn.js +2 -2
  13. package/lib/config/config-resolvers.d.ts +5 -5
  14. package/lib/config/config-resolvers.js +121 -66
  15. package/lib/config/config.d.ts +12 -18
  16. package/lib/config/config.js +42 -26
  17. package/lib/config/load.d.ts +16 -3
  18. package/lib/config/load.js +36 -14
  19. package/lib/config/minimal.d.ts +2 -2
  20. package/lib/config/minimal.js +10 -6
  21. package/lib/config/recommended.d.ts +2 -2
  22. package/lib/config/recommended.js +10 -6
  23. package/lib/config/rules.d.ts +7 -4
  24. package/lib/config/rules.js +5 -4
  25. package/lib/config/types.d.ts +72 -23
  26. package/lib/config/types.js +13 -0
  27. package/lib/config/utils.d.ts +6 -5
  28. package/lib/config/utils.js +110 -32
  29. package/lib/decorators/common/filters/filter-helper.d.ts +3 -0
  30. package/lib/decorators/common/filters/filter-helper.js +67 -0
  31. package/lib/decorators/common/filters/filter-in.d.ts +2 -0
  32. package/lib/decorators/common/filters/filter-in.js +17 -0
  33. package/lib/decorators/common/filters/filter-out.d.ts +2 -0
  34. package/lib/decorators/common/filters/filter-out.js +17 -0
  35. package/lib/decorators/common/info-override.d.ts +2 -0
  36. package/lib/decorators/common/info-override.js +28 -0
  37. package/lib/decorators/common/media-type-examples-override.d.ts +2 -0
  38. package/lib/decorators/common/media-type-examples-override.js +53 -0
  39. package/lib/decorators/common/registry-dependencies.js +2 -2
  40. package/lib/decorators/common/remove-x-internal.js +2 -2
  41. package/lib/decorators/oas2/index.d.ts +3 -0
  42. package/lib/decorators/oas2/index.js +7 -1
  43. package/lib/decorators/oas3/index.d.ts +4 -0
  44. package/lib/decorators/oas3/index.js +9 -1
  45. package/lib/env.d.ts +3 -0
  46. package/lib/env.js +8 -0
  47. package/lib/format/codeframes.js +16 -10
  48. package/lib/format/format.d.ts +1 -1
  49. package/lib/format/format.js +64 -32
  50. package/lib/index.d.ts +6 -6
  51. package/lib/index.js +7 -2
  52. package/lib/js-yaml/index.js +2 -6
  53. package/lib/lint.d.ts +4 -2
  54. package/lib/lint.js +36 -11
  55. package/lib/logger.d.ts +10 -0
  56. package/lib/logger.js +31 -0
  57. package/lib/output.d.ts +3 -0
  58. package/lib/output.js +9 -0
  59. package/lib/redocly/index.js +10 -9
  60. package/lib/redocly/registry-api-types.d.ts +28 -28
  61. package/lib/redocly/registry-api.d.ts +3 -3
  62. package/lib/redocly/registry-api.js +10 -2
  63. package/lib/ref-utils.d.ts +1 -0
  64. package/lib/ref-utils.js +8 -2
  65. package/lib/resolve.d.ts +1 -1
  66. package/lib/resolve.js +33 -3
  67. package/lib/rules/ajv.d.ts +2 -2
  68. package/lib/rules/ajv.js +12 -12
  69. package/lib/rules/common/assertions/asserts.d.ts +29 -4
  70. package/lib/rules/common/assertions/asserts.js +227 -97
  71. package/lib/rules/common/assertions/index.d.ts +27 -2
  72. package/lib/rules/common/assertions/index.js +9 -37
  73. package/lib/rules/common/assertions/utils.d.ts +16 -8
  74. package/lib/rules/common/assertions/utils.js +160 -76
  75. package/lib/rules/common/info-license-url.d.ts +1 -1
  76. package/lib/rules/common/info-license-url.js +5 -10
  77. package/lib/rules/common/info-license.d.ts +2 -0
  78. package/lib/rules/common/info-license.js +17 -0
  79. package/lib/rules/common/no-ambiguous-paths.js +1 -1
  80. package/lib/rules/common/no-enum-type-mismatch.js +1 -3
  81. package/lib/rules/common/no-identical-paths.js +4 -4
  82. package/lib/rules/common/no-invalid-parameter-examples.js +3 -3
  83. package/lib/rules/common/no-invalid-schema-examples.js +3 -3
  84. package/lib/rules/common/operation-2xx-response.js +15 -9
  85. package/lib/rules/common/operation-4xx-response.js +15 -9
  86. package/lib/rules/common/operation-operationId.js +2 -2
  87. package/lib/rules/common/operation-tag-defined.js +1 -1
  88. package/lib/rules/common/path-not-include-query.js +2 -2
  89. package/lib/rules/common/path-params-defined.js +7 -2
  90. package/lib/rules/common/paths-kebab-case.js +4 -1
  91. package/lib/rules/common/required-string-property-missing-min-length.d.ts +2 -0
  92. package/lib/rules/common/required-string-property-missing-min-length.js +37 -0
  93. package/lib/rules/common/response-contains-header.d.ts +2 -0
  94. package/lib/rules/common/response-contains-header.js +29 -0
  95. package/lib/rules/common/scalar-property-missing-example.d.ts +2 -0
  96. package/lib/rules/common/scalar-property-missing-example.js +42 -0
  97. package/lib/rules/common/security-defined.d.ts +2 -0
  98. package/lib/rules/common/{operation-security-defined.js → security-defined.js} +25 -6
  99. package/lib/rules/common/spec-strict-refs.d.ts +2 -0
  100. package/lib/rules/common/spec-strict-refs.js +30 -0
  101. package/lib/rules/common/spec.js +41 -18
  102. package/lib/rules/common/tags-alphabetical.js +1 -1
  103. package/lib/rules/oas2/index.d.ts +6 -2
  104. package/lib/rules/oas2/index.js +16 -8
  105. package/lib/rules/oas2/remove-unused-components.js +6 -6
  106. package/lib/rules/oas2/request-mime-type.d.ts +1 -1
  107. package/lib/rules/oas2/request-mime-type.js +1 -1
  108. package/lib/rules/oas2/response-contains-property.d.ts +2 -0
  109. package/lib/rules/oas2/response-contains-property.js +38 -0
  110. package/lib/rules/oas2/response-mime-type.d.ts +1 -1
  111. package/lib/rules/oas2/response-mime-type.js +1 -1
  112. package/lib/rules/oas3/component-name-unique.d.ts +2 -0
  113. package/lib/rules/oas3/component-name-unique.js +124 -0
  114. package/lib/rules/oas3/index.js +24 -10
  115. package/lib/rules/oas3/no-empty-servers.js +2 -2
  116. package/lib/rules/oas3/no-invalid-media-type-examples.js +2 -2
  117. package/lib/rules/oas3/no-server-variables-empty-enum.d.ts +2 -0
  118. package/lib/rules/oas3/{no-servers-empty-enum.js → no-server-variables-empty-enum.js} +5 -5
  119. package/lib/rules/oas3/no-unused-components.js +2 -2
  120. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +5 -0
  121. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +36 -0
  122. package/lib/rules/oas3/remove-unused-components.js +6 -6
  123. package/lib/rules/oas3/request-mime-type.d.ts +1 -1
  124. package/lib/rules/oas3/request-mime-type.js +1 -1
  125. package/lib/rules/oas3/response-contains-property.d.ts +2 -0
  126. package/lib/rules/oas3/response-contains-property.js +40 -0
  127. package/lib/rules/oas3/response-mime-type.d.ts +1 -1
  128. package/lib/rules/oas3/response-mime-type.js +1 -1
  129. package/lib/rules/oas3/spec-components-invalid-map-name.d.ts +2 -0
  130. package/lib/rules/oas3/spec-components-invalid-map-name.js +62 -0
  131. package/lib/rules/other/stats.d.ts +2 -2
  132. package/lib/rules/other/stats.js +45 -16
  133. package/lib/rules/utils.d.ts +5 -2
  134. package/lib/rules/utils.js +54 -6
  135. package/lib/types/config-external-schemas.d.ts +2193 -0
  136. package/lib/types/config-external-schemas.js +805 -0
  137. package/lib/types/index.d.ts +3 -2
  138. package/lib/types/index.js +9 -1
  139. package/lib/types/oas2.js +91 -15
  140. package/lib/types/oas3.js +139 -49
  141. package/lib/types/oas3_1.js +32 -26
  142. package/lib/types/redocly-yaml.js +414 -58
  143. package/lib/typings/openapi.d.ts +3 -2
  144. package/lib/utils.d.ts +15 -3
  145. package/lib/utils.js +73 -7
  146. package/lib/visitors.d.ts +20 -16
  147. package/lib/visitors.js +28 -3
  148. package/lib/walk.d.ts +11 -19
  149. package/lib/walk.js +74 -53
  150. package/package.json +5 -6
  151. package/__tests__/__snapshots__/bundle.test.ts.snap +0 -229
  152. package/__tests__/bundle.test.ts +0 -132
  153. package/__tests__/codeframes.test.ts +0 -531
  154. package/__tests__/fixtures/extension.js +0 -24
  155. package/__tests__/fixtures/refs/definitions.yaml +0 -3
  156. package/__tests__/fixtures/refs/examples.yaml +0 -8
  157. package/__tests__/fixtures/refs/external-request-body.yaml +0 -13
  158. package/__tests__/fixtures/refs/externalref.yaml +0 -35
  159. package/__tests__/fixtures/refs/hosted.yaml +0 -35
  160. package/__tests__/fixtures/refs/openapi-with-external-refs-conflicting-names.yaml +0 -21
  161. package/__tests__/fixtures/refs/openapi-with-external-refs.yaml +0 -33
  162. package/__tests__/fixtures/refs/param-b.yaml +0 -1
  163. package/__tests__/fixtures/refs/param-c.yaml +0 -1
  164. package/__tests__/fixtures/refs/rename.yaml +0 -1
  165. package/__tests__/fixtures/refs/requestBody.yaml +0 -9
  166. package/__tests__/fixtures/refs/schema-a.yaml +0 -1
  167. package/__tests__/fixtures/refs/simple.yaml +0 -1
  168. package/__tests__/fixtures/refs/vendor.schema.yaml +0 -20
  169. package/__tests__/fixtures/resolve/External.yaml +0 -10
  170. package/__tests__/fixtures/resolve/External2.yaml +0 -4
  171. package/__tests__/fixtures/resolve/description.md +0 -3
  172. package/__tests__/fixtures/resolve/externalInfo.yaml +0 -4
  173. package/__tests__/fixtures/resolve/externalLicense.yaml +0 -1
  174. package/__tests__/fixtures/resolve/openapi-with-back.yaml +0 -13
  175. package/__tests__/fixtures/resolve/openapi-with-md-description.yaml +0 -5
  176. package/__tests__/fixtures/resolve/openapi.yaml +0 -28
  177. package/__tests__/fixtures/resolve/schemas/type-a.yaml +0 -10
  178. package/__tests__/fixtures/resolve/schemas/type-b.yaml +0 -6
  179. package/__tests__/fixtures/resolve/transitive/a.yaml +0 -1
  180. package/__tests__/fixtures/resolve/transitive/components.yaml +0 -5
  181. package/__tests__/fixtures/resolve/transitive/schemas.yaml +0 -3
  182. package/__tests__/lint.test.ts +0 -17
  183. package/__tests__/login.test.ts +0 -17
  184. package/__tests__/normalizeVisitors.test.ts +0 -151
  185. package/__tests__/ref-utils.test.ts +0 -120
  186. package/__tests__/resolve-http.test.ts +0 -77
  187. package/__tests__/resolve.test.ts +0 -405
  188. package/__tests__/utils.ts +0 -86
  189. package/__tests__/walk.test.ts +0 -1485
  190. package/lib/rules/common/info-description.d.ts +0 -2
  191. package/lib/rules/common/info-description.js +0 -12
  192. package/lib/rules/common/license-url.d.ts +0 -2
  193. package/lib/rules/common/license-url.js +0 -12
  194. package/lib/rules/common/operation-security-defined.d.ts +0 -2
  195. package/lib/rules/oas3/no-servers-empty-enum.d.ts +0 -2
  196. package/src/__tests__/js-yaml.test.ts +0 -71
  197. package/src/__tests__/lint.test.ts +0 -182
  198. package/src/__tests__/utils.test.ts +0 -74
  199. package/src/benchmark/benches/lint-with-many-rules.bench.ts +0 -35
  200. package/src/benchmark/benches/lint-with-nested-rule.bench.ts +0 -39
  201. package/src/benchmark/benches/lint-with-no-rules.bench.ts +0 -20
  202. package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +0 -36
  203. package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +0 -32
  204. package/src/benchmark/benches/rebilly.yaml +0 -32267
  205. package/src/benchmark/benches/recommended-oas3.bench.ts +0 -22
  206. package/src/benchmark/benches/resolve-with-no-external.bench.ts +0 -23
  207. package/src/benchmark/benchmark.js +0 -307
  208. package/src/benchmark/colors.js +0 -29
  209. package/src/benchmark/fork.js +0 -83
  210. package/src/benchmark/utils.ts +0 -36
  211. package/src/bundle.ts +0 -371
  212. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +0 -157
  213. package/src/config/__tests__/config-resolvers.test.ts +0 -429
  214. package/src/config/__tests__/config.test.ts +0 -244
  215. package/src/config/__tests__/fixtures/plugin-config.yaml +0 -3
  216. package/src/config/__tests__/fixtures/plugin.js +0 -56
  217. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +0 -12
  218. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +0 -67
  219. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +0 -8
  220. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +0 -19
  221. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +0 -10
  222. package/src/config/__tests__/fixtures/resolve-config/plugin.js +0 -66
  223. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +0 -4
  224. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +0 -5
  225. package/src/config/__tests__/load.test.ts +0 -83
  226. package/src/config/__tests__/resolve-plugins.test.ts +0 -27
  227. package/src/config/all.ts +0 -65
  228. package/src/config/builtIn.ts +0 -37
  229. package/src/config/config-resolvers.ts +0 -359
  230. package/src/config/config.ts +0 -312
  231. package/src/config/index.ts +0 -7
  232. package/src/config/load.ts +0 -84
  233. package/src/config/minimal.ts +0 -58
  234. package/src/config/recommended.ts +0 -58
  235. package/src/config/rules.ts +0 -46
  236. package/src/config/types.ts +0 -168
  237. package/src/config/utils.ts +0 -208
  238. package/src/decorators/__tests__/remove-x-internal.test.ts +0 -316
  239. package/src/decorators/common/info-description-override.ts +0 -24
  240. package/src/decorators/common/operation-description-override.ts +0 -30
  241. package/src/decorators/common/registry-dependencies.ts +0 -25
  242. package/src/decorators/common/remove-x-internal.ts +0 -59
  243. package/src/decorators/common/tag-description-override.ts +0 -25
  244. package/src/decorators/oas2/index.ts +0 -14
  245. package/src/decorators/oas3/index.ts +0 -14
  246. package/src/format/codeframes.ts +0 -210
  247. package/src/format/format.ts +0 -339
  248. package/src/index.ts +0 -68
  249. package/src/js-yaml/index.ts +0 -18
  250. package/src/lint.ts +0 -125
  251. package/src/oas-types.ts +0 -62
  252. package/src/redocly/__tests__/redocly-client.test.ts +0 -140
  253. package/src/redocly/index.ts +0 -182
  254. package/src/redocly/redocly-client-types.ts +0 -10
  255. package/src/redocly/registry-api-types.ts +0 -32
  256. package/src/redocly/registry-api.ts +0 -134
  257. package/src/ref-utils.ts +0 -79
  258. package/src/resolve.ts +0 -378
  259. package/src/rules/__tests__/fixtures/invalid-yaml.yaml +0 -1
  260. package/src/rules/__tests__/fixtures/ref.yaml +0 -1
  261. package/src/rules/__tests__/no-unresolved-refs.test.ts +0 -168
  262. package/src/rules/ajv.ts +0 -103
  263. package/src/rules/common/__tests__/info-description.test.ts +0 -102
  264. package/src/rules/common/__tests__/info-license.test.ts +0 -62
  265. package/src/rules/common/__tests__/license-url.test.ts +0 -63
  266. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +0 -96
  267. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +0 -209
  268. package/src/rules/common/__tests__/no-identical-paths.test.ts +0 -58
  269. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +0 -85
  270. package/src/rules/common/__tests__/operation-2xx-response.test.ts +0 -91
  271. package/src/rules/common/__tests__/operation-4xx-response.test.ts +0 -107
  272. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +0 -76
  273. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +0 -45
  274. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +0 -167
  275. package/src/rules/common/__tests__/operation-security-defined.test.ts +0 -69
  276. package/src/rules/common/__tests__/operation-singular-tag.test.ts +0 -72
  277. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +0 -95
  278. package/src/rules/common/__tests__/path-not-include-query.test.ts +0 -64
  279. package/src/rules/common/__tests__/path-params-defined.test.ts +0 -133
  280. package/src/rules/common/__tests__/paths-kebab-case.test.ts +0 -108
  281. package/src/rules/common/__tests__/spec.test.ts +0 -62
  282. package/src/rules/common/__tests__/tag-description.test.ts +0 -65
  283. package/src/rules/common/__tests__/tags-alphabetical.test.ts +0 -64
  284. package/src/rules/common/assertions/__tests__/asserts.test.ts +0 -231
  285. package/src/rules/common/assertions/__tests__/index.test.ts +0 -65
  286. package/src/rules/common/assertions/__tests__/utils.test.ts +0 -89
  287. package/src/rules/common/assertions/asserts.ts +0 -137
  288. package/src/rules/common/assertions/index.ts +0 -75
  289. package/src/rules/common/assertions/utils.ts +0 -167
  290. package/src/rules/common/info-contact.ts +0 -15
  291. package/src/rules/common/info-description.ts +0 -10
  292. package/src/rules/common/info-license-url.ts +0 -15
  293. package/src/rules/common/license-url.ts +0 -10
  294. package/src/rules/common/no-ambiguous-paths.ts +0 -50
  295. package/src/rules/common/no-enum-type-mismatch.ts +0 -49
  296. package/src/rules/common/no-http-verbs-in-paths.ts +0 -36
  297. package/src/rules/common/no-identical-paths.ts +0 -24
  298. package/src/rules/common/no-invalid-parameter-examples.ts +0 -36
  299. package/src/rules/common/no-invalid-schema-examples.ts +0 -27
  300. package/src/rules/common/no-path-trailing-slash.ts +0 -15
  301. package/src/rules/common/operation-2xx-response.ts +0 -16
  302. package/src/rules/common/operation-4xx-response.ts +0 -17
  303. package/src/rules/common/operation-description.ts +0 -13
  304. package/src/rules/common/operation-operationId-unique.ts +0 -21
  305. package/src/rules/common/operation-operationId-url-safe.ts +0 -19
  306. package/src/rules/common/operation-operationId.ts +0 -17
  307. package/src/rules/common/operation-parameters-unique.ts +0 -48
  308. package/src/rules/common/operation-security-defined.ts +0 -45
  309. package/src/rules/common/operation-singular-tag.ts +0 -17
  310. package/src/rules/common/operation-summary.ts +0 -13
  311. package/src/rules/common/operation-tag-defined.ts +0 -26
  312. package/src/rules/common/parameter-description.ts +0 -22
  313. package/src/rules/common/path-declaration-must-exist.ts +0 -15
  314. package/src/rules/common/path-excludes-patterns.ts +0 -23
  315. package/src/rules/common/path-http-verbs-order.ts +0 -30
  316. package/src/rules/common/path-not-include-query.ts +0 -17
  317. package/src/rules/common/path-params-defined.ts +0 -58
  318. package/src/rules/common/path-segment-plural.ts +0 -31
  319. package/src/rules/common/paths-kebab-case.ts +0 -16
  320. package/src/rules/common/spec.ts +0 -143
  321. package/src/rules/common/tag-description.ts +0 -10
  322. package/src/rules/common/tags-alphabetical.ts +0 -20
  323. package/src/rules/no-unresolved-refs.ts +0 -51
  324. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +0 -110
  325. package/src/rules/oas2/__tests__/spec/fixtures/description.md +0 -1
  326. package/src/rules/oas2/__tests__/spec/info.test.ts +0 -355
  327. package/src/rules/oas2/__tests__/spec/operation.test.ts +0 -123
  328. package/src/rules/oas2/__tests__/spec/paths.test.ts +0 -245
  329. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +0 -31
  330. package/src/rules/oas2/__tests__/spec/utils.ts +0 -32
  331. package/src/rules/oas2/boolean-parameter-prefixes.ts +0 -26
  332. package/src/rules/oas2/index.ts +0 -83
  333. package/src/rules/oas2/remove-unused-components.ts +0 -76
  334. package/src/rules/oas2/request-mime-type.ts +0 -17
  335. package/src/rules/oas2/response-mime-type.ts +0 -17
  336. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +0 -111
  337. package/src/rules/oas3/__tests__/fixtures/common.yaml +0 -11
  338. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +0 -205
  339. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +0 -65
  340. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +0 -392
  341. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +0 -60
  342. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +0 -79
  343. package/src/rules/oas3/__tests__/no-unused-components.test.ts +0 -131
  344. package/src/rules/oas3/__tests__/spec/callbacks.test.ts +0 -41
  345. package/src/rules/oas3/__tests__/spec/fixtures/description.md +0 -1
  346. package/src/rules/oas3/__tests__/spec/info.test.ts +0 -391
  347. package/src/rules/oas3/__tests__/spec/operation.test.ts +0 -253
  348. package/src/rules/oas3/__tests__/spec/paths.test.ts +0 -284
  349. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +0 -77
  350. package/src/rules/oas3/__tests__/spec/servers.test.ts +0 -499
  351. package/src/rules/oas3/__tests__/spec/spec.test.ts +0 -288
  352. package/src/rules/oas3/__tests__/spec/utils.ts +0 -32
  353. package/src/rules/oas3/boolean-parameter-prefixes.ts +0 -28
  354. package/src/rules/oas3/index.ts +0 -99
  355. package/src/rules/oas3/no-empty-servers.ts +0 -22
  356. package/src/rules/oas3/no-example-value-and-externalValue.ts +0 -14
  357. package/src/rules/oas3/no-invalid-media-type-examples.ts +0 -41
  358. package/src/rules/oas3/no-server-example.com.ts +0 -14
  359. package/src/rules/oas3/no-server-trailing-slash.ts +0 -15
  360. package/src/rules/oas3/no-servers-empty-enum.ts +0 -67
  361. package/src/rules/oas3/no-undefined-server-variable.ts +0 -30
  362. package/src/rules/oas3/no-unused-components.ts +0 -75
  363. package/src/rules/oas3/remove-unused-components.ts +0 -84
  364. package/src/rules/oas3/request-mime-type.ts +0 -31
  365. package/src/rules/oas3/response-mime-type.ts +0 -31
  366. package/src/rules/other/stats.ts +0 -44
  367. package/src/rules/utils.ts +0 -123
  368. package/src/types/index.ts +0 -138
  369. package/src/types/oas2.ts +0 -397
  370. package/src/types/oas3.ts +0 -506
  371. package/src/types/oas3_1.ts +0 -251
  372. package/src/types/redocly-yaml.ts +0 -637
  373. package/src/typings/common.ts +0 -9
  374. package/src/typings/openapi.ts +0 -297
  375. package/src/typings/swagger.ts +0 -236
  376. package/src/utils.ts +0 -190
  377. package/src/visitors.ts +0 -448
  378. package/src/walk.ts +0 -416
  379. package/tsconfig.json +0 -8
  380. package/tsconfig.tsbuildinfo +0 -1
@@ -1,1485 +0,0 @@
1
- import outdent from 'outdent';
2
- import each from 'jest-each';
3
- import * as path from 'path';
4
-
5
- import { lintDocument } from '../src/lint';
6
-
7
- import { parseYamlToDocument, replaceSourceWithRef, makeConfigForRuleset } from './utils';
8
- import { BaseResolver, Document } from '../src/resolve';
9
- import { listOf } from '../src/types';
10
- import { Oas3RuleSet } from '../src/oas-types';
11
-
12
- describe('walk order', () => {
13
- it('should run visitors', async () => {
14
- const visitors = {
15
- DefinitionRoot: {
16
- enter: jest.fn(),
17
- leave: jest.fn(),
18
- },
19
- Info: {
20
- enter: jest.fn(),
21
- leave: jest.fn(),
22
- },
23
- Contact: {
24
- enter: jest.fn(),
25
- leave: jest.fn(),
26
- },
27
- License: {
28
- enter: jest.fn(),
29
- leave: jest.fn(),
30
- },
31
- };
32
-
33
- const testRuleSet: Oas3RuleSet = {
34
- test: jest.fn(() => {
35
- return visitors;
36
- }),
37
- };
38
-
39
- const document = parseYamlToDocument(
40
- outdent`
41
- openapi: 3.0.0
42
- info:
43
- contact: {}
44
- license: {}
45
- `,
46
- '',
47
- );
48
-
49
- await lintDocument({
50
- externalRefResolver: new BaseResolver(),
51
- document,
52
- config: makeConfigForRuleset(testRuleSet),
53
- });
54
-
55
- expect(testRuleSet.test).toBeCalledTimes(1);
56
- for (const fns of Object.values(visitors)) {
57
- expect(fns.enter).toBeCalled();
58
- expect(fns.leave).toBeCalled();
59
- }
60
- });
61
-
62
- it('should run nested visitors correctly', async () => {
63
- const calls: string[] = [];
64
-
65
- const testRuleSet: Oas3RuleSet = {
66
- test: jest.fn(() => {
67
- return {
68
- Operation: {
69
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
70
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
71
- Parameter: {
72
- enter: jest.fn((param, _ctx, parents) =>
73
- calls.push(
74
- `enter operation ${parents.Operation.operationId} > param ${param.name}`,
75
- ),
76
- ),
77
- leave: jest.fn((param, _ctx, parents) =>
78
- calls.push(
79
- `leave operation ${parents.Operation.operationId} > param ${param.name}`,
80
- ),
81
- ),
82
- },
83
- },
84
- Parameter: {
85
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
86
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
87
- },
88
- };
89
- }),
90
- };
91
-
92
- const document = parseYamlToDocument(
93
- outdent`
94
- openapi: 3.0.0
95
- info:
96
- contact: {}
97
- license: {}
98
- paths:
99
- /pet:
100
- parameters:
101
- - name: path-param
102
- get:
103
- operationId: get
104
- parameters:
105
- - name: get_a
106
- - name: get_b
107
- post:
108
- operationId: post
109
- parameters:
110
- - name: post_a
111
-
112
- `,
113
- '',
114
- );
115
-
116
- await lintDocument({
117
- externalRefResolver: new BaseResolver(),
118
- document,
119
- config: makeConfigForRuleset(testRuleSet),
120
- });
121
-
122
- expect(calls).toMatchInlineSnapshot(`
123
- Array [
124
- "enter param path-param",
125
- "leave param path-param",
126
- "enter operation: get",
127
- "enter operation get > param get_a",
128
- "enter param get_a",
129
- "leave param get_a",
130
- "leave operation get > param get_a",
131
- "enter operation get > param get_b",
132
- "enter param get_b",
133
- "leave param get_b",
134
- "leave operation get > param get_b",
135
- "leave operation: get",
136
- "enter operation: post",
137
- "enter operation post > param post_a",
138
- "enter param post_a",
139
- "leave param post_a",
140
- "leave operation post > param post_a",
141
- "leave operation: post",
142
- ]
143
- `);
144
- });
145
-
146
- it('should run nested visitors correctly oas2', async () => {
147
- const calls: string[] = [];
148
-
149
- const testRuleSet: Oas3RuleSet = {
150
- test: jest.fn(() => {
151
- return {
152
- Operation: {
153
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
154
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
155
- Parameter: {
156
- enter: jest.fn((param, _ctx, parents) =>
157
- calls.push(
158
- `enter operation ${parents.Operation.operationId} > param ${param.name}`,
159
- ),
160
- ),
161
- leave: jest.fn((param, _ctx, parents) =>
162
- calls.push(
163
- `leave operation ${parents.Operation.operationId} > param ${param.name}`,
164
- ),
165
- ),
166
- },
167
- },
168
- Parameter: {
169
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
170
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
171
- },
172
- };
173
- }),
174
- };
175
-
176
- const document = parseYamlToDocument(
177
- outdent`
178
- swagger: "2.0"
179
- info:
180
- contact: {}
181
- license: {}
182
- paths:
183
- /pet:
184
- parameters:
185
- - name: path-param
186
- get:
187
- operationId: get
188
- parameters:
189
- - name: get_a
190
- - name: get_b
191
- post:
192
- operationId: post
193
- parameters:
194
- - name: post_a
195
-
196
- `,
197
- '',
198
- );
199
-
200
- await lintDocument({
201
- externalRefResolver: new BaseResolver(),
202
- document,
203
- config: makeConfigForRuleset(testRuleSet, undefined, 'oas2'),
204
- });
205
-
206
- expect(calls).toMatchInlineSnapshot(`
207
- Array [
208
- "enter param path-param",
209
- "leave param path-param",
210
- "enter operation: get",
211
- "enter operation get > param get_a",
212
- "enter param get_a",
213
- "leave param get_a",
214
- "leave operation get > param get_a",
215
- "enter operation get > param get_b",
216
- "enter param get_b",
217
- "leave param get_b",
218
- "leave operation get > param get_b",
219
- "leave operation: get",
220
- "enter operation: post",
221
- "enter operation post > param post_a",
222
- "enter param post_a",
223
- "leave param post_a",
224
- "leave operation post > param post_a",
225
- "leave operation: post",
226
- ]
227
- `);
228
- });
229
-
230
- it('should resolve refs', async () => {
231
- const calls: string[] = [];
232
-
233
- const testRuleSet: Oas3RuleSet = {
234
- test: jest.fn(() => {
235
- return {
236
- Operation: {
237
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
238
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
239
- Parameter: {
240
- enter: jest.fn((param, _ctx, parents) =>
241
- calls.push(
242
- `enter operation ${parents.Operation.operationId} > param ${param.name}`,
243
- ),
244
- ),
245
- leave: jest.fn((param, _ctx, parents) =>
246
- calls.push(
247
- `leave operation ${parents.Operation.operationId} > param ${param.name}`,
248
- ),
249
- ),
250
- },
251
- },
252
- Parameter: {
253
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
254
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
255
- },
256
- };
257
- }),
258
- };
259
-
260
- const document = parseYamlToDocument(
261
- outdent`
262
- openapi: 3.0.0
263
- info:
264
- contact: {}
265
- license: {}
266
- paths:
267
- /pet:
268
- get:
269
- operationId: get
270
- parameters:
271
- - $ref: '#/components/parameters/shared_a'
272
- - name: get_b
273
- post:
274
- operationId: post
275
- parameters:
276
- - $ref: '#/components/parameters/shared_a'
277
- components:
278
- parameters:
279
- shared_a:
280
- name: shared-a
281
- `,
282
- '',
283
- );
284
-
285
- await lintDocument({
286
- externalRefResolver: new BaseResolver(),
287
- document,
288
- config: makeConfigForRuleset(testRuleSet),
289
- });
290
-
291
- expect(calls).toMatchInlineSnapshot(`
292
- Array [
293
- "enter operation: get",
294
- "enter operation get > param shared-a",
295
- "enter param shared-a",
296
- "leave param shared-a",
297
- "leave operation get > param shared-a",
298
- "enter operation get > param get_b",
299
- "enter param get_b",
300
- "leave param get_b",
301
- "leave operation get > param get_b",
302
- "leave operation: get",
303
- "enter operation: post",
304
- "enter operation post > param shared-a",
305
- "leave operation post > param shared-a",
306
- "leave operation: post",
307
- ]
308
- `);
309
- });
310
-
311
- it('should visit with context same refs with gaps in visitor simple', async () => {
312
- const calls: string[] = [];
313
-
314
- const testRuleSet: Oas3RuleSet = {
315
- test: jest.fn(() => {
316
- return {
317
- PathItem: {
318
- Parameter: {
319
- enter: jest.fn((param, _ctx, parents) =>
320
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`),
321
- ),
322
- },
323
- },
324
- };
325
- }),
326
- };
327
-
328
- const document = parseYamlToDocument(
329
- outdent`
330
- openapi: 3.0.0
331
- paths:
332
- /pet:
333
- id: pet
334
- parameters:
335
- $ref: '#/components/fake_parameters_list'
336
- get:
337
- operationId: get
338
- parameters:
339
- - $ref: '#/components/parameters/shared_a'
340
- - name: get_b
341
- /dog:
342
- id: dog
343
- post:
344
- operationId: post
345
- parameters:
346
- - $ref: '#/components/parameters/shared_a'
347
- components:
348
- fake_parameters_list:
349
- - name: path-param
350
- parameters:
351
- shared_a:
352
- name: shared-a
353
- `,
354
- '',
355
- );
356
-
357
- await lintDocument({
358
- externalRefResolver: new BaseResolver(),
359
- document,
360
- config: makeConfigForRuleset(testRuleSet),
361
- });
362
-
363
- expect(calls).toMatchInlineSnapshot(`
364
- Array [
365
- "enter path pet > param path-param",
366
- "enter path pet > param shared-a",
367
- "enter path pet > param get_b",
368
- "enter path dog > param shared-a",
369
- ]
370
- `);
371
- });
372
-
373
- it('should correctly visit more specific visitor', async () => {
374
- const calls: string[] = [];
375
-
376
- const testRuleSet: Oas3RuleSet = {
377
- test: jest.fn(() => {
378
- return {
379
- PathItem: {
380
- Parameter: {
381
- enter: jest.fn((param, _ctx, parents) =>
382
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`),
383
- ),
384
- },
385
- Operation: {
386
- Parameter: {
387
- enter: jest.fn((param, _ctx, parents) =>
388
- calls.push(
389
- `enter operation ${parents.Operation.operationId} > param ${param.name}`,
390
- ),
391
- ),
392
- },
393
- },
394
- },
395
- };
396
- }),
397
- };
398
-
399
- const document = parseYamlToDocument(
400
- outdent`
401
- openapi: 3.0.0
402
- paths:
403
- /pet:
404
- id: pet
405
- parameters:
406
- - name: path-param
407
- get:
408
- operationId: get
409
- parameters:
410
- - $ref: '#/components/parameters/shared_a'
411
- - name: get_b
412
- - name: get_c
413
- /dog:
414
- id: dog
415
- post:
416
- operationId: post
417
- parameters:
418
- - $ref: '#/components/parameters/shared_b'
419
- components:
420
- parameters:
421
- shared_a:
422
- name: shared-a
423
- shared_b:
424
- name: shared-b
425
- `,
426
- '',
427
- );
428
-
429
- await lintDocument({
430
- externalRefResolver: new BaseResolver(),
431
- document,
432
- config: makeConfigForRuleset(testRuleSet),
433
- });
434
-
435
- expect(calls).toMatchInlineSnapshot(`
436
- Array [
437
- "enter path pet > param path-param",
438
- "enter operation get > param shared-a",
439
- "enter operation get > param get_b",
440
- "enter operation get > param get_c",
441
- "enter operation post > param shared-b",
442
- ]
443
- `);
444
- });
445
-
446
- it('should visit with context same refs with gaps in visitor and nested rule', async () => {
447
- const calls: string[] = [];
448
-
449
- const testRuleSet: Oas3RuleSet = {
450
- test: jest.fn(() => {
451
- return {
452
- PathItem: {
453
- Parameter: {
454
- enter: jest.fn((param, _ctx, parents) =>
455
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`),
456
- ),
457
- leave: jest.fn((param, _ctx, parents) =>
458
- calls.push(`leave path ${parents.PathItem.id} > param ${param.name}`),
459
- ),
460
- },
461
- Operation(op, _ctx, parents) {
462
- calls.push(`enter path ${parents.PathItem.id} > op ${op.operationId}`);
463
- },
464
- },
465
- };
466
- }),
467
- };
468
-
469
- const document = parseYamlToDocument(
470
- outdent`
471
- openapi: 3.0.0
472
- paths:
473
- /pet:
474
- id: pet
475
- parameters:
476
- - name: path-param
477
- get:
478
- operationId: get
479
- parameters:
480
- - $ref: '#/components/parameters/shared_a'
481
- - name: get_b
482
- /dog:
483
- id: dog
484
- post:
485
- operationId: post
486
- parameters:
487
- - $ref: '#/components/parameters/shared_a'
488
- components:
489
- parameters:
490
- shared_a:
491
- name: shared-a
492
- `,
493
- '',
494
- );
495
-
496
- await lintDocument({
497
- externalRefResolver: new BaseResolver(),
498
- document,
499
- config: makeConfigForRuleset(testRuleSet),
500
- });
501
-
502
- expect(calls).toMatchInlineSnapshot(`
503
- Array [
504
- "enter path pet > param path-param",
505
- "leave path pet > param path-param",
506
- "enter path pet > op get",
507
- "enter path pet > param shared-a",
508
- "leave path pet > param shared-a",
509
- "enter path pet > param get_b",
510
- "leave path pet > param get_b",
511
- "enter path dog > op post",
512
- "enter path dog > param shared-a",
513
- "leave path dog > param shared-a",
514
- ]
515
- `);
516
- });
517
-
518
- it('should visit and do not recurse for circular refs top-level', async () => {
519
- const calls: string[] = [];
520
-
521
- const testRuleSet: Oas3RuleSet = {
522
- test: jest.fn(() => {
523
- return {
524
- Schema: jest.fn((schema: any) => calls.push(`enter schema ${schema.id}`)),
525
- };
526
- }),
527
- };
528
-
529
- const document = parseYamlToDocument(
530
- outdent`
531
- openapi: 3.0.0
532
- paths:
533
- /pet:
534
- id: pet
535
- parameters:
536
- - name: path-param
537
- schema:
538
- $ref: "#/components/parameters/shared_a"
539
- components:
540
- parameters:
541
- shared_a:
542
- id: 'shared_a'
543
- allOf:
544
- - $ref: "#/components/parameters/shared_a"
545
- - id: 'nested'
546
- `,
547
- '',
548
- );
549
-
550
- await lintDocument({
551
- externalRefResolver: new BaseResolver(),
552
- document,
553
- config: makeConfigForRuleset(testRuleSet),
554
- });
555
-
556
- expect(calls).toMatchInlineSnapshot(`
557
- Array [
558
- "enter schema shared_a",
559
- "enter schema nested",
560
- ]
561
- `);
562
- });
563
-
564
- it('should visit and do not recurse for circular refs with context', async () => {
565
- const calls: string[] = [];
566
-
567
- const testRuleSet: Oas3RuleSet = {
568
- test: jest.fn(() => {
569
- return {
570
- Parameter: {
571
- Schema: jest.fn((schema: any, _ctx, parents) =>
572
- calls.push(`enter param ${parents.Parameter.name} > schema ${schema.id}`),
573
- ),
574
- },
575
- };
576
- }),
577
- };
578
-
579
- const document = parseYamlToDocument(
580
- outdent`
581
- openapi: 3.0.0
582
- paths:
583
- /pet:
584
- id: pet
585
- parameters:
586
- - name: a
587
- schema:
588
- $ref: "#/components/parameters/shared_a"
589
- - name: b
590
- schema:
591
- $ref: "#/components/parameters/shared_a"
592
- components:
593
- parameters:
594
- shared_a:
595
- id: 'shared_a'
596
- properties:
597
- a:
598
- id: a
599
- allOf:
600
- - $ref: "#/components/parameters/shared_a"
601
- - id: 'nested'
602
- `,
603
- '',
604
- );
605
-
606
- await lintDocument({
607
- externalRefResolver: new BaseResolver(),
608
- document,
609
- config: makeConfigForRuleset(testRuleSet),
610
- });
611
-
612
- expect(calls).toMatchInlineSnapshot(`
613
- Array [
614
- "enter param a > schema shared_a",
615
- "enter param b > schema shared_a",
616
- ]
617
- `);
618
- });
619
-
620
- it('should correctly skip top level', async () => {
621
- const calls: string[] = [];
622
-
623
- const testRuleSet: Oas3RuleSet = {
624
- test: jest.fn(() => {
625
- return {
626
- Operation: {
627
- skip: (op) => op.operationId === 'put',
628
- enter: jest.fn((op) => calls.push(`enter operation ${op.operationId}`)),
629
- leave: jest.fn((op) => calls.push(`leave operation ${op.operationId}`)),
630
- },
631
- };
632
- }),
633
- };
634
-
635
- const document = parseYamlToDocument(
636
- outdent`
637
- openapi: 3.0.0
638
- paths:
639
- /pet:
640
- get:
641
- operationId: get
642
- put:
643
- operationId: put
644
- `,
645
- '',
646
- );
647
-
648
- await lintDocument({
649
- externalRefResolver: new BaseResolver(),
650
- document,
651
- config: makeConfigForRuleset(testRuleSet),
652
- });
653
-
654
- expect(calls).toMatchInlineSnapshot(`
655
- Array [
656
- "enter operation get",
657
- "leave operation get",
658
- ]
659
- `);
660
- });
661
-
662
- it('should correctly skip nested levels', async () => {
663
- const calls: string[] = [];
664
-
665
- const testRuleSet: Oas3RuleSet = {
666
- test: jest.fn(() => {
667
- return {
668
- Operation: {
669
- skip: (op) => op.operationId === 'put',
670
- Parameter: jest.fn((param, _ctx, parents) =>
671
- calls.push(`enter operation ${parents.Operation.operationId} > param ${param.name}`),
672
- ),
673
- },
674
- };
675
- }),
676
- };
677
-
678
- const document = parseYamlToDocument(
679
- outdent`
680
- openapi: 3.0.0
681
- paths:
682
- /pet:
683
- get:
684
- operationId: get
685
- parameters:
686
- - $ref: '#/components/parameters/shared_a'
687
- - name: get_b
688
- - name: get_c
689
- put:
690
- operationId: put
691
- parameters:
692
- - $ref: '#/components/parameters/shared_a'
693
- - name: get_b
694
- - name: get_c
695
- components:
696
- parameters:
697
- shared_a:
698
- name: shared-a
699
- `,
700
- '',
701
- );
702
-
703
- await lintDocument({
704
- externalRefResolver: new BaseResolver(),
705
- document,
706
- config: makeConfigForRuleset(testRuleSet),
707
- });
708
-
709
- expect(calls).toMatchInlineSnapshot(`
710
- Array [
711
- "enter operation get > param shared-a",
712
- "enter operation get > param get_b",
713
- "enter operation get > param get_c",
714
- ]
715
- `);
716
- });
717
-
718
- it('should correctly visit more specific visitor with skips', async () => {
719
- const calls: string[] = [];
720
-
721
- const testRuleSet: Oas3RuleSet = {
722
- test: jest.fn(() => {
723
- return {
724
- PathItem: {
725
- Parameter: {
726
- enter: jest.fn((param, _ctx, parents) =>
727
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`),
728
- ),
729
- leave: jest.fn((param, _ctx, parents) =>
730
- calls.push(`leave path ${parents.PathItem.id} > param ${param.name}`),
731
- ),
732
- },
733
- Operation: {
734
- skip: (op) => op.operationId === 'put',
735
- Parameter: {
736
- enter: jest.fn((param, _ctx, parents) =>
737
- calls.push(
738
- `enter operation ${parents.Operation.operationId} > param ${param.name}`,
739
- ),
740
- ),
741
- leave: jest.fn((param, _ctx, parents) =>
742
- calls.push(
743
- `leave operation ${parents.Operation.operationId} > param ${param.name}`,
744
- ),
745
- ),
746
- },
747
- },
748
- },
749
- };
750
- }),
751
- };
752
-
753
- const document = parseYamlToDocument(
754
- outdent`
755
- openapi: 3.0.0
756
- paths:
757
- /pet:
758
- id: pet
759
- parameters:
760
- - name: path-param
761
- get:
762
- operationId: get
763
- parameters:
764
- - $ref: '#/components/parameters/shared_a'
765
- - name: get_b
766
- - name: get_c
767
- put:
768
- operationId: put
769
- parameters:
770
- - $ref: '#/components/parameters/shared_a'
771
- - name: get_b
772
- - name: get_c
773
- /dog:
774
- id: dog
775
- post:
776
- operationId: post
777
- parameters:
778
- - $ref: '#/components/parameters/shared_b'
779
- components:
780
- parameters:
781
- shared_a:
782
- name: shared-a
783
- shared_b:
784
- name: shared-b
785
- `,
786
- '',
787
- );
788
-
789
- await lintDocument({
790
- externalRefResolver: new BaseResolver(),
791
- document,
792
- config: makeConfigForRuleset(testRuleSet),
793
- });
794
-
795
- expect(calls).toMatchInlineSnapshot(`
796
- Array [
797
- "enter path pet > param path-param",
798
- "leave path pet > param path-param",
799
- "enter operation get > param shared-a",
800
- "leave operation get > param shared-a",
801
- "enter operation get > param get_b",
802
- "leave operation get > param get_b",
803
- "enter operation get > param get_c",
804
- "leave operation get > param get_c",
805
- "enter operation post > param shared-b",
806
- "leave operation post > param shared-b",
807
- ]
808
- `);
809
- });
810
-
811
- it('should correctly visit with nested rules', async () => {
812
- const calls: string[] = [];
813
-
814
- const testRuleSet: Oas3RuleSet = {
815
- test: jest.fn(() => {
816
- return {
817
- Schema: {
818
- Schema: {
819
- enter: jest.fn((schema: any, _ctx, parents) =>
820
- calls.push(`enter nested schema ${parents.Schema.id} > ${schema.id}`),
821
- ),
822
- leave: jest.fn((schema: any, _ctx, parents) =>
823
- calls.push(`leave nested schema ${parents.Schema.id} > ${schema.id}`),
824
- ),
825
- },
826
- },
827
- };
828
- }),
829
- };
830
-
831
- const document = parseYamlToDocument(
832
- outdent`
833
- openapi: 3.0.0
834
- paths:
835
- /pet:
836
- get:
837
- requestBody:
838
- content:
839
- application/json:
840
- schema:
841
- id: inline-top
842
- type: object
843
- properties:
844
- b:
845
- $ref: "#/components/schemas/b"
846
- a:
847
- type: object
848
- id: inline-nested-2
849
- properties:
850
- a:
851
- id: inline-nested-nested-2
852
- components:
853
- schemas:
854
- b:
855
- id: inline-top
856
- type: object
857
- properties:
858
- a:
859
- type: object
860
- id: inline-nested
861
- properties:
862
- a:
863
- id: inline-nested-nested
864
- `,
865
- 'foobar.yaml',
866
- );
867
-
868
- await lintDocument({
869
- externalRefResolver: new BaseResolver(),
870
- document,
871
- config: makeConfigForRuleset(testRuleSet),
872
- });
873
-
874
- expect(calls).toMatchInlineSnapshot(`
875
- Array [
876
- "enter nested schema inline-top > inline-top",
877
- "enter nested schema inline-top > inline-nested",
878
- "enter nested schema inline-nested > inline-nested-nested",
879
- "leave nested schema inline-nested > inline-nested-nested",
880
- "leave nested schema inline-top > inline-nested",
881
- "leave nested schema inline-top > inline-top",
882
- "enter nested schema inline-top > inline-nested-2",
883
- "enter nested schema inline-nested-2 > inline-nested-nested-2",
884
- "leave nested schema inline-nested-2 > inline-nested-nested-2",
885
- "leave nested schema inline-top > inline-nested-2",
886
- ]
887
- `);
888
- });
889
-
890
- it('should correctly visit refs', async () => {
891
- const calls: string[] = [];
892
-
893
- const testRuleSet: Oas3RuleSet = {
894
- test: jest.fn(() => {
895
- return {
896
- ref(node, _, { node: target }) {
897
- calls.push(`enter $ref ${node.$ref} with target ${target?.name}`);
898
- },
899
- };
900
- }),
901
- };
902
-
903
- const document = parseYamlToDocument(
904
- outdent`
905
- openapi: 3.0.0
906
- paths:
907
- /pet:
908
- id: pet
909
- parameters:
910
- - name: path-param
911
- get:
912
- operationId: get
913
- parameters:
914
- - $ref: '#/components/parameters/shared_b'
915
- put:
916
- operationId: put
917
- parameters:
918
- - $ref: '#/components/parameters/shared_a'
919
- /dog:
920
- id: dog
921
- post:
922
- operationId: post
923
- schema:
924
- example:
925
- $ref: 123
926
- parameters:
927
- - $ref: '#/components/parameters/shared_a'
928
- components:
929
- parameters:
930
- shared_a:
931
- name: shared-a
932
- shared_b:
933
- name: shared-b
934
- schema:
935
- $ref: '#/components/parameters/shared_b'
936
- `,
937
- 'foobar.yaml',
938
- );
939
-
940
- await lintDocument({
941
- externalRefResolver: new BaseResolver(),
942
- document,
943
- config: makeConfigForRuleset(testRuleSet),
944
- });
945
-
946
- expect(calls).toMatchInlineSnapshot(`
947
- Array [
948
- "enter $ref #/components/parameters/shared_b with target shared-b",
949
- "enter $ref #/components/parameters/shared_b with target shared-b",
950
- "enter $ref #/components/parameters/shared_a with target shared-a",
951
- "enter $ref #/components/parameters/shared_a with target shared-a",
952
- ]
953
- `);
954
- });
955
-
956
- it('should correctly visit refs', async () => {
957
- const calls: string[] = [];
958
-
959
- const testRuleSet: Oas3RuleSet = {
960
- test: jest.fn(() => {
961
- return {
962
- NamedSchemas: {
963
- Schema(node, { key }) {
964
- calls.push(`enter schema ${key}: ${node.type}`);
965
- },
966
- },
967
- };
968
- }),
969
- };
970
-
971
- const document = parseYamlToDocument(
972
- outdent`
973
- openapi: 3.0.0
974
- components:
975
- schemas:
976
- a:
977
- type: string
978
- b:
979
- type: number
980
- `,
981
- 'foobar.yaml',
982
- );
983
-
984
- await lintDocument({
985
- externalRefResolver: new BaseResolver(),
986
- document,
987
- config: makeConfigForRuleset(testRuleSet),
988
- });
989
-
990
- expect(calls).toMatchInlineSnapshot(`
991
- Array [
992
- "enter schema a: string",
993
- "enter schema b: number",
994
- ]
995
- `);
996
- });
997
-
998
- it('should correctly visit any visitor', async () => {
999
- const calls: string[] = [];
1000
-
1001
- const testRuleSet: Oas3RuleSet = {
1002
- test: jest.fn(() => {
1003
- return {
1004
- ref: {
1005
- enter(ref: any) {
1006
- calls.push(`enter ref ${ref.$ref}`);
1007
- },
1008
- leave(ref) {
1009
- calls.push(`leave ref ${ref.$ref}`);
1010
- },
1011
- },
1012
- any: {
1013
- enter(_node: any, { type }) {
1014
- calls.push(`enter ${type.name}`);
1015
- },
1016
- leave(_node, { type }) {
1017
- calls.push(`leave ${type.name}`);
1018
- },
1019
- },
1020
- };
1021
- }),
1022
- };
1023
-
1024
- const document = parseYamlToDocument(
1025
- outdent`
1026
- openapi: 3.0.0
1027
- paths:
1028
- /pet:
1029
- id: pet
1030
- parameters:
1031
- - name: path-param
1032
- get:
1033
- operationId: get
1034
- parameters:
1035
- - $ref: '#/components/parameters/shared_a'
1036
- - name: get_b
1037
- - name: get_c
1038
- components:
1039
- parameters:
1040
- shared_a:
1041
- name: shared-a
1042
- schemas:
1043
- a:
1044
- type: object
1045
- `,
1046
- '',
1047
- );
1048
-
1049
- await lintDocument({
1050
- externalRefResolver: new BaseResolver(),
1051
- document,
1052
- config: makeConfigForRuleset(testRuleSet),
1053
- });
1054
-
1055
- expect(calls).toMatchInlineSnapshot(`
1056
- Array [
1057
- "enter DefinitionRoot",
1058
- "enter PathMap",
1059
- "enter PathItem",
1060
- "enter ParameterList",
1061
- "enter Parameter",
1062
- "leave Parameter",
1063
- "leave ParameterList",
1064
- "enter Operation",
1065
- "enter ParameterList",
1066
- "enter ref #/components/parameters/shared_a",
1067
- "enter Parameter",
1068
- "leave Parameter",
1069
- "leave ref #/components/parameters/shared_a",
1070
- "enter Parameter",
1071
- "leave Parameter",
1072
- "enter Parameter",
1073
- "leave Parameter",
1074
- "leave ParameterList",
1075
- "leave Operation",
1076
- "leave PathItem",
1077
- "leave PathMap",
1078
- "enter Components",
1079
- "enter NamedParameters",
1080
- "leave NamedParameters",
1081
- "enter NamedSchemas",
1082
- "enter Schema",
1083
- "leave Schema",
1084
- "leave NamedSchemas",
1085
- "leave Components",
1086
- "leave DefinitionRoot",
1087
- ]
1088
- `);
1089
- });
1090
- });
1091
-
1092
- describe('context.report', () => {
1093
- it('should report errors correctly', async () => {
1094
- const testRuleSet: Oas3RuleSet = {
1095
- test: jest.fn(() => {
1096
- return {
1097
- Parameter: {
1098
- enter: jest.fn((param, ctx) => {
1099
- if (param.name.indexOf('_') > -1) {
1100
- ctx.report({
1101
- message: `Parameter name shouldn't contain '_: ${param.name}`,
1102
- });
1103
- }
1104
- }),
1105
- },
1106
- };
1107
- }),
1108
- };
1109
-
1110
- const document = parseYamlToDocument(
1111
- outdent`
1112
- openapi: 3.0.0
1113
- info:
1114
- contact: {}
1115
- license: {}
1116
- paths:
1117
- /pet:
1118
- parameters:
1119
- - name: path-param
1120
- get:
1121
- operationId: get
1122
- parameters:
1123
- - name: get_a
1124
- - name: get_b
1125
- post:
1126
- operationId: post
1127
- parameters:
1128
- - $ref: '#/components/parameters/shared_a'
1129
- components:
1130
- parameters:
1131
- shared_a:
1132
- name: shared_a
1133
- `,
1134
- 'foobar.yaml',
1135
- );
1136
-
1137
- const results = await lintDocument({
1138
- externalRefResolver: new BaseResolver(),
1139
- document,
1140
- config: makeConfigForRuleset(testRuleSet),
1141
- });
1142
-
1143
- expect(results).toHaveLength(3);
1144
- expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
1145
- Array [
1146
- Object {
1147
- "location": Array [
1148
- Object {
1149
- "pointer": "#/paths/~1pet/get/parameters/0",
1150
- "reportOnKey": false,
1151
- "source": "foobar.yaml",
1152
- },
1153
- ],
1154
- "message": "Parameter name shouldn't contain '_: get_a",
1155
- "ruleId": "test/test",
1156
- "severity": "error",
1157
- "suggest": Array [],
1158
- },
1159
- Object {
1160
- "location": Array [
1161
- Object {
1162
- "pointer": "#/paths/~1pet/get/parameters/1",
1163
- "reportOnKey": false,
1164
- "source": "foobar.yaml",
1165
- },
1166
- ],
1167
- "message": "Parameter name shouldn't contain '_: get_b",
1168
- "ruleId": "test/test",
1169
- "severity": "error",
1170
- "suggest": Array [],
1171
- },
1172
- Object {
1173
- "location": Array [
1174
- Object {
1175
- "pointer": "#/components/parameters/shared_a",
1176
- "reportOnKey": false,
1177
- "source": "foobar.yaml",
1178
- },
1179
- ],
1180
- "message": "Parameter name shouldn't contain '_: shared_a",
1181
- "ruleId": "test/test",
1182
- "severity": "error",
1183
- "suggest": Array [],
1184
- },
1185
- ]
1186
- `);
1187
- });
1188
-
1189
- it('should report errors correctly', async () => {
1190
- const testRuleSet: Oas3RuleSet = {
1191
- test: jest.fn(() => {
1192
- return {
1193
- Parameter: {
1194
- enter: jest.fn((param, ctx) => {
1195
- if (param.name.indexOf('_') > -1) {
1196
- ctx.report({
1197
- message: `Parameter name shouldn't contain '_: ${param.name}`,
1198
- });
1199
- }
1200
- }),
1201
- },
1202
- };
1203
- }),
1204
- };
1205
-
1206
- const cwd = path.join(__dirname, 'fixtures/refs');
1207
- const externalRefResolver = new BaseResolver();
1208
- const document = (await externalRefResolver.resolveDocument(
1209
- null,
1210
- `${cwd}/openapi-with-external-refs.yaml`,
1211
- )) as Document;
1212
-
1213
- if (document === null) {
1214
- throw 'Should never happen';
1215
- }
1216
-
1217
- const results = await lintDocument({
1218
- externalRefResolver: new BaseResolver(),
1219
- document,
1220
- config: makeConfigForRuleset(testRuleSet),
1221
- });
1222
-
1223
- expect(results).toHaveLength(4);
1224
- expect(replaceSourceWithRef(results, cwd)).toMatchInlineSnapshot(`
1225
- Array [
1226
- Object {
1227
- "location": Array [
1228
- Object {
1229
- "pointer": "#/components/parameters/path-param",
1230
- "reportOnKey": false,
1231
- "source": "openapi-with-external-refs.yaml",
1232
- },
1233
- ],
1234
- "message": "Parameter name shouldn't contain '_: path_param",
1235
- "ruleId": "test/test",
1236
- "severity": "error",
1237
- "suggest": Array [],
1238
- },
1239
- Object {
1240
- "location": Array [
1241
- Object {
1242
- "pointer": "#/components/parameters/param-a",
1243
- "reportOnKey": false,
1244
- "source": "openapi-with-external-refs.yaml",
1245
- },
1246
- ],
1247
- "message": "Parameter name shouldn't contain '_: param_a",
1248
- "ruleId": "test/test",
1249
- "severity": "error",
1250
- "suggest": Array [],
1251
- },
1252
- Object {
1253
- "location": Array [
1254
- Object {
1255
- "pointer": "#/",
1256
- "reportOnKey": false,
1257
- "source": "param-c.yaml",
1258
- },
1259
- ],
1260
- "message": "Parameter name shouldn't contain '_: param_c",
1261
- "ruleId": "test/test",
1262
- "severity": "error",
1263
- "suggest": Array [],
1264
- },
1265
- Object {
1266
- "location": Array [
1267
- Object {
1268
- "pointer": "#/",
1269
- "reportOnKey": false,
1270
- "source": "param-b.yaml",
1271
- },
1272
- ],
1273
- "message": "Parameter name shouldn't contain '_: param_b",
1274
- "ruleId": "test/test",
1275
- "severity": "error",
1276
- "suggest": Array [],
1277
- },
1278
- ]
1279
- `);
1280
- });
1281
- });
1282
-
1283
- describe('context.resolve', () => {
1284
- it('should resolve refs correctly', async () => {
1285
- const testRuleSet: Oas3RuleSet = {
1286
- test: jest.fn(() => {
1287
- return {
1288
- Schema: jest.fn((schema, { resolve }) => {
1289
- if (schema.properties) {
1290
- expect(schema.properties.a.$ref).toBeDefined();
1291
- const { location, node } = resolve(schema.properties.a);
1292
- expect(node).toMatchInlineSnapshot(`
1293
- Object {
1294
- "type": "string",
1295
- }
1296
- `);
1297
- expect(location?.pointer).toEqual('#/components/schemas/b');
1298
- expect(location?.source).toStrictEqual(document.source);
1299
- }
1300
- }),
1301
- };
1302
- }),
1303
- };
1304
-
1305
- const document = parseYamlToDocument(
1306
- outdent`
1307
- openapi: 3.0.0
1308
- info:
1309
- contact: {}
1310
- license: {}
1311
- paths: {}
1312
- components:
1313
- schemas:
1314
- b:
1315
- type: string
1316
- a:
1317
- type: object
1318
- properties:
1319
- a:
1320
- $ref: '#/components/schemas/b'
1321
- `,
1322
- 'foobar.yaml',
1323
- );
1324
-
1325
- await lintDocument({
1326
- externalRefResolver: new BaseResolver(),
1327
- document,
1328
- config: makeConfigForRuleset(testRuleSet),
1329
- });
1330
- });
1331
- });
1332
-
1333
- describe('type extensions', () => {
1334
- each([
1335
- ['3.0.0', 'oas3_0'],
1336
- ['3.1.0', 'oas3_1'],
1337
- ]).it('should correctly visit OpenAPI %s extended types', async (openapi, oas) => {
1338
- const calls: string[] = [];
1339
-
1340
- const testRuleSet: Oas3RuleSet = {
1341
- test: jest.fn(() => {
1342
- return {
1343
- any: {
1344
- enter(_node: any, { type }) {
1345
- calls.push(`enter ${type.name}`);
1346
- },
1347
- leave(_node, { type }) {
1348
- calls.push(`leave ${type.name}`);
1349
- },
1350
- },
1351
- XWebHooks: {
1352
- enter(hook: any) {
1353
- calls.push(`enter hook ${hook.name}`);
1354
- },
1355
- leave(hook) {
1356
- calls.push(`leave hook ${hook.name}`);
1357
- },
1358
- },
1359
- };
1360
- }),
1361
- };
1362
-
1363
- const document = parseYamlToDocument(
1364
- outdent`
1365
- openapi: ${openapi}
1366
- x-webhooks:
1367
- name: test
1368
- parameters:
1369
- - name: a
1370
- `,
1371
- 'foobar.yaml',
1372
- );
1373
-
1374
- await lintDocument({
1375
- externalRefResolver: new BaseResolver(),
1376
- document,
1377
- config: makeConfigForRuleset(testRuleSet, {
1378
- typeExtension: {
1379
- oas3(types, version) {
1380
- expect(version).toEqual(oas);
1381
-
1382
- return {
1383
- ...types,
1384
- XWebHooks: {
1385
- properties: {
1386
- parameters: listOf('Parameter'),
1387
- },
1388
- },
1389
- DefinitionRoot: {
1390
- ...types.DefinitionRoot,
1391
- properties: {
1392
- ...types.DefinitionRoot.properties,
1393
- 'x-webhooks': 'XWebHooks',
1394
- },
1395
- },
1396
- };
1397
- },
1398
- },
1399
- }),
1400
- });
1401
-
1402
- expect(calls).toMatchInlineSnapshot(`
1403
- Array [
1404
- "enter DefinitionRoot",
1405
- "enter XWebHooks",
1406
- "enter hook test",
1407
- "enter ParameterList",
1408
- "enter Parameter",
1409
- "leave Parameter",
1410
- "leave ParameterList",
1411
- "leave hook test",
1412
- "leave XWebHooks",
1413
- "leave DefinitionRoot",
1414
- ]
1415
- `);
1416
- });
1417
- });
1418
-
1419
- describe('ignoreNextRules', () => {
1420
- it('should correctly skip top level', async () => {
1421
- const calls: string[] = [];
1422
-
1423
- const testRuleSet: Oas3RuleSet = {
1424
- skip: jest.fn(() => {
1425
- return {
1426
- Operation: {
1427
- enter: jest.fn((op, ctx) => {
1428
- if (op.operationId === 'get') {
1429
- ctx.ignoreNextVisitorsOnNode();
1430
- calls.push(`enter and skip operation ${op.operationId}`);
1431
- } else {
1432
- calls.push(`enter and not skip operation ${op.operationId}`);
1433
- }
1434
- }),
1435
- leave: jest.fn((op) => {
1436
- if (op.operationId === 'get') {
1437
- calls.push(`leave skipped operation ${op.operationId}`);
1438
- } else {
1439
- calls.push(`leave not skipped operation ${op.operationId}`);
1440
- }
1441
- }),
1442
- },
1443
- };
1444
- }),
1445
- test: jest.fn(() => {
1446
- return {
1447
- Operation: {
1448
- enter: jest.fn((op) => calls.push(`enter operation ${op.operationId}`)),
1449
- leave: jest.fn((op) => calls.push(`leave operation ${op.operationId}`)),
1450
- },
1451
- };
1452
- }),
1453
- };
1454
-
1455
- const document = parseYamlToDocument(
1456
- outdent`
1457
- openapi: 3.0.0
1458
- paths:
1459
- /pet:
1460
- get:
1461
- operationId: get
1462
- put:
1463
- operationId: put
1464
- `,
1465
- '',
1466
- );
1467
-
1468
- await lintDocument({
1469
- externalRefResolver: new BaseResolver(),
1470
- document,
1471
- config: makeConfigForRuleset(testRuleSet),
1472
- });
1473
-
1474
- expect(calls).toMatchInlineSnapshot(`
1475
- Array [
1476
- "enter and skip operation get",
1477
- "leave skipped operation get",
1478
- "enter and not skip operation put",
1479
- "enter operation put",
1480
- "leave not skipped operation put",
1481
- "leave operation put",
1482
- ]
1483
- `);
1484
- });
1485
- });