@redocly/openapi-core 1.0.0-beta.103 → 1.0.0-beta.106

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 (201) hide show
  1. package/README.md +4 -4
  2. package/__tests__/utils.ts +8 -6
  3. package/lib/benchmark/benches/recommended-oas3.bench.js +1 -1
  4. package/lib/benchmark/utils.d.ts +2 -2
  5. package/lib/benchmark/utils.js +2 -2
  6. package/lib/bundle.d.ts +2 -2
  7. package/lib/bundle.js +2 -2
  8. package/lib/config/all.d.ts +2 -2
  9. package/lib/config/all.js +1 -1
  10. package/lib/config/builtIn.d.ts +2 -2
  11. package/lib/config/builtIn.js +2 -2
  12. package/lib/config/config-resolvers.d.ts +5 -5
  13. package/lib/config/config-resolvers.js +39 -36
  14. package/lib/config/config.d.ts +6 -5
  15. package/lib/config/config.js +27 -20
  16. package/lib/config/load.js +6 -7
  17. package/lib/config/minimal.d.ts +2 -2
  18. package/lib/config/minimal.js +1 -1
  19. package/lib/config/recommended.d.ts +2 -2
  20. package/lib/config/recommended.js +1 -1
  21. package/lib/config/rules.d.ts +2 -2
  22. package/lib/config/rules.js +1 -1
  23. package/lib/config/types.d.ts +23 -19
  24. package/lib/config/utils.d.ts +5 -5
  25. package/lib/config/utils.js +43 -26
  26. package/lib/decorators/common/filters/filter-helper.js +1 -1
  27. package/lib/decorators/common/remove-x-internal.js +2 -2
  28. package/lib/format/format.js +1 -1
  29. package/lib/index.d.ts +2 -2
  30. package/lib/index.js +3 -2
  31. package/lib/js-yaml/index.js +1 -6
  32. package/lib/lint.d.ts +2 -2
  33. package/lib/lint.js +16 -6
  34. package/lib/redocly/registry-api.d.ts +1 -1
  35. package/lib/redocly/registry-api.js +2 -2
  36. package/lib/rules/ajv.d.ts +1 -1
  37. package/lib/rules/ajv.js +1 -1
  38. package/lib/rules/common/info-license-url.d.ts +1 -1
  39. package/lib/rules/common/info-license-url.js +5 -10
  40. package/lib/rules/common/info-license.d.ts +2 -0
  41. package/lib/rules/common/info-license.js +17 -0
  42. package/lib/rules/common/no-enum-type-mismatch.js +1 -3
  43. package/lib/rules/common/operation-operationId.js +1 -1
  44. package/lib/rules/common/path-not-include-query.js +1 -1
  45. package/lib/rules/common/paths-kebab-case.js +4 -1
  46. package/lib/rules/common/spec.js +1 -1
  47. package/lib/rules/oas2/index.js +4 -4
  48. package/lib/rules/oas2/remove-unused-components.js +3 -3
  49. package/lib/rules/oas3/index.js +4 -4
  50. package/lib/rules/oas3/no-empty-servers.js +1 -1
  51. package/lib/rules/oas3/remove-unused-components.js +2 -2
  52. package/lib/rules/other/stats.js +43 -14
  53. package/lib/rules/utils.d.ts +1 -1
  54. package/lib/rules/utils.js +4 -1
  55. package/lib/types/index.d.ts +2 -2
  56. package/lib/types/redocly-yaml.js +9 -7
  57. package/lib/utils.d.ts +3 -2
  58. package/lib/utils.js +11 -2
  59. package/lib/walk.d.ts +2 -14
  60. package/lib/walk.js +19 -19
  61. package/package.json +3 -2
  62. package/src/__tests__/__snapshots__/bundle.test.ts.snap +141 -0
  63. package/src/__tests__/bundle.test.ts +68 -34
  64. package/src/__tests__/codeframes.test.ts +13 -14
  65. package/src/__tests__/fixtures/.redocly.lint-ignore.yaml +5 -0
  66. package/src/__tests__/js-yaml.test.ts +6 -4
  67. package/src/__tests__/lint.test.ts +127 -12
  68. package/src/__tests__/login.test.ts +2 -2
  69. package/src/__tests__/normalizeVisitors.test.ts +4 -4
  70. package/src/__tests__/ref-utils.test.ts +13 -13
  71. package/src/__tests__/resolve-http.test.ts +1 -1
  72. package/src/__tests__/resolve.test.ts +14 -11
  73. package/src/__tests__/utils.test.ts +42 -1
  74. package/src/__tests__/walk.test.ts +48 -56
  75. package/src/benchmark/benches/lint-with-many-rules.bench.ts +1 -1
  76. package/src/benchmark/benches/lint-with-nested-rule.bench.ts +1 -1
  77. package/src/benchmark/benches/lint-with-no-rules.bench.ts +1 -1
  78. package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +1 -1
  79. package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +1 -1
  80. package/src/benchmark/benches/recommended-oas3.bench.ts +3 -3
  81. package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
  82. package/src/benchmark/benchmark.js +9 -5
  83. package/src/benchmark/utils.ts +5 -5
  84. package/src/bundle.ts +18 -17
  85. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -1
  86. package/src/config/__tests__/config-resolvers.test.ts +123 -121
  87. package/src/config/__tests__/config.test.ts +76 -76
  88. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +4 -2
  89. package/src/config/__tests__/fixtures/resolve-config/plugin.js +4 -1
  90. package/src/config/__tests__/load.test.ts +2 -2
  91. package/src/config/__tests__/resolve-plugins.test.ts +3 -3
  92. package/src/config/__tests__/utils.test.ts +83 -0
  93. package/src/config/all.ts +3 -4
  94. package/src/config/builtIn.ts +5 -5
  95. package/src/config/config-resolvers.ts +122 -83
  96. package/src/config/config.ts +36 -32
  97. package/src/config/load.ts +13 -16
  98. package/src/config/minimal.ts +3 -3
  99. package/src/config/recommended.ts +3 -3
  100. package/src/config/rules.ts +6 -6
  101. package/src/config/types.ts +28 -19
  102. package/src/config/utils.ts +70 -50
  103. package/src/decorators/__tests__/filter-out.test.ts +113 -5
  104. package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
  105. package/src/decorators/common/filters/filter-helper.ts +1 -1
  106. package/src/decorators/common/info-description-override.ts +1 -1
  107. package/src/decorators/common/operation-description-override.ts +1 -1
  108. package/src/decorators/common/remove-x-internal.ts +4 -4
  109. package/src/decorators/common/tag-description-override.ts +1 -1
  110. package/src/format/codeframes.ts +4 -4
  111. package/src/format/format.ts +10 -10
  112. package/src/index.ts +3 -4
  113. package/src/js-yaml/index.ts +3 -8
  114. package/src/lint.ts +22 -18
  115. package/src/oas-types.ts +1 -6
  116. package/src/redocly/__tests__/redocly-client.test.ts +25 -19
  117. package/src/redocly/index.ts +6 -4
  118. package/src/redocly/registry-api.ts +6 -6
  119. package/src/ref-utils.ts +2 -2
  120. package/src/resolve.ts +7 -4
  121. package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
  122. package/src/rules/__tests__/utils.test.ts +122 -0
  123. package/src/rules/ajv.ts +7 -8
  124. package/src/rules/common/__tests__/info-description.test.ts +3 -3
  125. package/src/rules/common/__tests__/info-license.test.ts +2 -2
  126. package/src/rules/common/__tests__/license-url.test.ts +2 -2
  127. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
  128. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +8 -8
  129. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
  130. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
  131. package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
  132. package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
  133. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
  134. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
  135. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
  136. package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
  137. package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
  138. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
  139. package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
  140. package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
  141. package/src/rules/common/__tests__/paths-kebab-case.test.ts +15 -15
  142. package/src/rules/common/__tests__/scalar-property-missing-example.test.ts +8 -8
  143. package/src/rules/common/__tests__/spec.test.ts +2 -2
  144. package/src/rules/common/__tests__/tag-description.test.ts +2 -2
  145. package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
  146. package/src/rules/common/assertions/__tests__/asserts.test.ts +513 -130
  147. package/src/rules/common/assertions/index.ts +6 -6
  148. package/src/rules/common/info-license-url.ts +4 -9
  149. package/src/rules/common/info-license.ts +15 -0
  150. package/src/rules/common/no-ambiguous-paths.ts +1 -1
  151. package/src/rules/common/no-enum-type-mismatch.ts +12 -9
  152. package/src/rules/common/no-invalid-parameter-examples.ts +2 -2
  153. package/src/rules/common/no-invalid-schema-examples.ts +1 -1
  154. package/src/rules/common/operation-operationId.ts +1 -1
  155. package/src/rules/common/operation-parameters-unique.ts +2 -2
  156. package/src/rules/common/path-not-include-query.ts +1 -1
  157. package/src/rules/common/path-params-defined.ts +1 -1
  158. package/src/rules/common/paths-kebab-case.ts +4 -1
  159. package/src/rules/common/scalar-property-missing-example.ts +1 -1
  160. package/src/rules/common/spec.ts +10 -7
  161. package/src/rules/no-unresolved-refs.ts +1 -1
  162. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  163. package/src/rules/oas2/__tests__/spec/info.test.ts +12 -12
  164. package/src/rules/oas2/__tests__/spec/operation.test.ts +4 -4
  165. package/src/rules/oas2/__tests__/spec/paths.test.ts +10 -10
  166. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +6 -2
  167. package/src/rules/oas2/__tests__/spec/utils.ts +6 -6
  168. package/src/rules/oas2/index.ts +3 -3
  169. package/src/rules/oas2/remove-unused-components.ts +13 -8
  170. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  171. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
  172. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
  173. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
  174. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
  175. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
  176. package/src/rules/oas3/__tests__/spec/callbacks.test.ts +1 -1
  177. package/src/rules/oas3/__tests__/spec/info.test.ts +12 -12
  178. package/src/rules/oas3/__tests__/spec/operation.test.ts +8 -8
  179. package/src/rules/oas3/__tests__/spec/paths.test.ts +10 -10
  180. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +12 -12
  181. package/src/rules/oas3/__tests__/spec/servers.test.ts +15 -15
  182. package/src/rules/oas3/__tests__/spec/spec.test.ts +6 -6
  183. package/src/rules/oas3/__tests__/spec/utils.ts +6 -6
  184. package/src/rules/oas3/index.ts +3 -3
  185. package/src/rules/oas3/no-empty-servers.ts +1 -1
  186. package/src/rules/oas3/no-invalid-media-type-examples.ts +12 -4
  187. package/src/rules/oas3/no-servers-empty-enum.ts +9 -10
  188. package/src/rules/oas3/remove-unused-components.ts +18 -7
  189. package/src/rules/other/stats.ts +46 -17
  190. package/src/rules/utils.ts +5 -3
  191. package/src/types/index.ts +5 -5
  192. package/src/types/redocly-yaml.ts +9 -7
  193. package/src/typings/common.ts +9 -1
  194. package/src/typings/openapi.ts +1 -1
  195. package/src/utils.ts +18 -8
  196. package/src/visitors.ts +4 -4
  197. package/src/walk.ts +23 -31
  198. package/tsconfig.tsbuildinfo +1 -1
  199. package/lib/rules/common/license-url.d.ts +0 -2
  200. package/lib/rules/common/license-url.js +0 -12
  201. package/src/rules/common/license-url.ts +0 -10
@@ -1,13 +1,13 @@
1
1
  import { outdent } from 'outdent';
2
2
  import { lintDocument } from '../../../../lint';
3
3
  import { parseYamlToDocument, replaceSourceWithRef } from '../../../../../__tests__/utils';
4
- import { LintConfig, defaultPlugin, resolvePlugins, resolvePreset } from '../../../../config';
4
+ import { StyleguideConfig, defaultPlugin, resolvePlugins, resolvePreset } from '../../../../config';
5
5
 
6
6
  import { BaseResolver } from '../../../../resolve';
7
7
 
8
8
  const plugins = resolvePlugins([defaultPlugin]);
9
9
  const pressets = resolvePreset('all', plugins);
10
- const allConfig = new LintConfig({ ...pressets, plugins });
10
+ const allConfig = new StyleguideConfig({ ...pressets, plugins });
11
11
  describe('Oas3 Structural visitor basic', () => {
12
12
  it('should report wrong types', async () => {
13
13
  const document = parseYamlToDocument(
@@ -35,7 +35,7 @@ describe('Oas3 Structural visitor basic', () => {
35
35
  license: invalid
36
36
  paths: {}
37
37
  `,
38
- 'foobar.yaml',
38
+ 'foobar.yaml'
39
39
  );
40
40
 
41
41
  const results = await lintDocument({
@@ -110,7 +110,7 @@ describe('Oas3 Structural visitor basic', () => {
110
110
  "source": "foobar.yaml",
111
111
  },
112
112
  ],
113
- "message": "Expected type \`string\` but got \`number\`.",
113
+ "message": "Expected type \`string\` but got \`integer\`.",
114
114
  "ruleId": "spec",
115
115
  "severity": "error",
116
116
  "suggest": Array [],
@@ -163,7 +163,7 @@ describe('Oas3 Structural visitor basic', () => {
163
163
  x-test: vendor
164
164
  paths: {}
165
165
  `,
166
- 'foobar.yaml',
166
+ 'foobar.yaml'
167
167
  );
168
168
 
169
169
  const results = await lintDocument({
@@ -232,7 +232,7 @@ describe('Oas3 Structural visitor basic', () => {
232
232
  contact:
233
233
  name: string
234
234
  `,
235
- 'foobar.yaml',
235
+ 'foobar.yaml'
236
236
  );
237
237
 
238
238
  const results = await lintDocument({
@@ -1,25 +1,25 @@
1
- import { LintConfig, RuleConfig, resolveLint } from '../../../../config';
1
+ import { StyleguideConfig, RuleConfig, resolveStyleguideConfig } from '../../../../config';
2
2
  import { parseYamlToDocument } from '../../../../../__tests__/utils';
3
3
  import { lintDocument } from '../../../../lint';
4
4
  import { BaseResolver } from '../../../../resolve';
5
5
 
6
6
  export async function validateDoc(
7
7
  source: string,
8
- rules: Record<string, RuleConfig> = { spec: 'error' },
8
+ rules: Record<string, RuleConfig> = { spec: 'error' }
9
9
  ) {
10
10
  const document = parseYamlToDocument(source, 'foobar.yaml');
11
11
 
12
12
  const results = await lintDocument({
13
13
  externalRefResolver: new BaseResolver(),
14
14
  document,
15
- config: new LintConfig(
16
- await resolveLint({
17
- lintConfig: {
15
+ config: new StyleguideConfig(
16
+ await resolveStyleguideConfig({
17
+ styleguideConfig: {
18
18
  plugins: [],
19
19
  extends: [],
20
20
  rules,
21
21
  },
22
- }),
22
+ })
23
23
  ),
24
24
  });
25
25
 
@@ -18,13 +18,13 @@ import { NoServerTrailingSlash } from './no-server-trailing-slash';
18
18
  import { InfoDescription } from '../common/info-description';
19
19
  import { TagDescription } from '../common/tag-description';
20
20
  import { InfoContact } from '../common/info-contact';
21
- import { InfoLicense } from '../common/info-license-url';
21
+ import { InfoLicense } from '../common/info-license';
22
+ import { InfoLicenseUrl } from '../common/info-license-url';
22
23
  import { OperationDescription } from '../common/operation-description';
23
24
  import { NoUnusedComponents } from './no-unused-components';
24
25
  import { PathNotIncludeQuery } from '../common/path-not-include-query';
25
26
  import { ParameterDescription } from '../common/parameter-description';
26
27
  import { OperationSingularTag } from '../common/operation-singular-tag';
27
- import { InfoLicenseUrl } from '../common/license-url';
28
28
  import { OperationSecurityDefined } from '../common/operation-security-defined';
29
29
  import { NoUnresolvedRefs } from '../no-unresolved-refs';
30
30
  import { BooleanParameterPrefixes } from './boolean-parameter-prefixes';
@@ -57,7 +57,7 @@ export const rules = {
57
57
  'info-license-url': InfoLicenseUrl,
58
58
  'operation-2xx-response': Operation2xxResponse,
59
59
  'operation-4xx-response': Operation4xxResponse,
60
- 'assertions': Assertions,
60
+ assertions: Assertions,
61
61
  'operation-operationId-unique': OperationIdUnique,
62
62
  'operation-parameters-unique': OperationParametersUnique,
63
63
  'path-parameters-defined': PathParamsDefined,
@@ -6,7 +6,7 @@ export const NoEmptyServers: Oas3Rule = () => {
6
6
  if (!root.hasOwnProperty('servers')) {
7
7
  report({
8
8
  message: 'Servers must be present.',
9
- location: location.child(['openapi']).key()
9
+ location: location.child(['openapi']).key(),
10
10
  });
11
11
  return;
12
12
  }
@@ -13,14 +13,22 @@ export const ValidContentExamples: Oas3Rule = (opts) => {
13
13
  const { location, resolve } = ctx;
14
14
  if (!mediaType.schema) return;
15
15
  if (mediaType.example) {
16
- resolveAndValidateExample(mediaType.example, location.child('example'));
16
+ resolveAndValidateExample(mediaType.example, location.child('example'));
17
17
  } else if (mediaType.examples) {
18
18
  for (const exampleName of Object.keys(mediaType.examples)) {
19
- resolveAndValidateExample(mediaType.examples[exampleName], location.child(['examples', exampleName, 'value']), true);
19
+ resolveAndValidateExample(
20
+ mediaType.examples[exampleName],
21
+ location.child(['examples', exampleName, 'value']),
22
+ true
23
+ );
20
24
  }
21
25
  }
22
26
 
23
- function resolveAndValidateExample(example: Oas3Example | any, location: Location, isMultiple?: boolean) {
27
+ function resolveAndValidateExample(
28
+ example: Oas3Example | any,
29
+ location: Location,
30
+ isMultiple?: boolean
31
+ ) {
24
32
  if (isRef(example)) {
25
33
  const resolved = resolve<Oas3Example>(example);
26
34
  if (!resolved.location) return;
@@ -32,7 +40,7 @@ export const ValidContentExamples: Oas3Rule = (opts) => {
32
40
  mediaType.schema!,
33
41
  location,
34
42
  ctx,
35
- disallowAdditionalProperties,
43
+ disallowAdditionalProperties
36
44
  );
37
45
  }
38
46
  },
@@ -25,16 +25,17 @@ export const NoEmptyEnumServers: Oas3Rule = () => {
25
25
  invalidVariables.push(...enumErrors);
26
26
  }
27
27
 
28
- for(const invalidVariable of invalidVariables) {
29
- if(invalidVariable === enumError.empty) {
28
+ for (const invalidVariable of invalidVariables) {
29
+ if (invalidVariable === enumError.empty) {
30
30
  report({
31
31
  message: 'Server variable with `enum` must be a non-empty array.',
32
32
  location: location.child(['servers']).key(),
33
33
  });
34
34
  }
35
- if(invalidVariable === enumError.invalidDefaultValue) {
35
+ if (invalidVariable === enumError.invalidDefaultValue) {
36
36
  report({
37
- message: 'Server variable define `enum` and `default`. `enum` must include default value',
37
+ message:
38
+ 'Server variable define `enum` and `default`. `enum` must include default value',
38
39
  location: location.child(['servers']).key(),
39
40
  });
40
41
  }
@@ -43,20 +44,18 @@ export const NoEmptyEnumServers: Oas3Rule = () => {
43
44
  };
44
45
  };
45
46
 
46
- function checkEnumVariables(server: Oas3Server): enumError[] | undefined{
47
- if (server.variables && Object.keys(server.variables).length === 0)
48
- return;
47
+ function checkEnumVariables(server: Oas3Server): enumError[] | undefined {
48
+ if (server.variables && Object.keys(server.variables).length === 0) return;
49
49
 
50
50
  const errors: enumError[] = [];
51
- for(var variable in server.variables) {
51
+ for (var variable in server.variables) {
52
52
  const serverVariable = server.variables[variable];
53
53
  if (!serverVariable.enum) continue;
54
54
 
55
55
  if (Array.isArray(serverVariable.enum) && serverVariable.enum?.length === 0)
56
56
  errors.push(enumError.empty);
57
57
 
58
- if (!serverVariable.default)
59
- continue;
58
+ if (!serverVariable.default) continue;
60
59
 
61
60
  const defaultValue = server.variables[variable].default;
62
61
  if (serverVariable.enum && !serverVariable.enum.includes(defaultValue))
@@ -1,12 +1,19 @@
1
1
  import { Oas3Rule } from '../../visitors';
2
2
  import { Location } from '../../ref-utils';
3
- import { Oas3Components } from '../../typings/openapi'
3
+ import { Oas3Components } from '../../typings/openapi';
4
4
  import { isEmptyObject } from '../../utils';
5
5
 
6
6
  export const RemoveUnusedComponents: Oas3Rule = () => {
7
- let components = new Map<string, { used: boolean; componentType?: keyof Oas3Components; name: string }>();
7
+ let components = new Map<
8
+ string,
9
+ { used: boolean; componentType?: keyof Oas3Components; name: string }
10
+ >();
8
11
 
9
- function registerComponent(location: Location, componentType: keyof Oas3Components, name: string): void {
12
+ function registerComponent(
13
+ location: Location,
14
+ componentType: keyof Oas3Components,
15
+ name: string
16
+ ): void {
10
17
  components.set(location.absolutePointer, {
11
18
  used: components.get(location.absolutePointer)?.used || false,
12
19
  componentType,
@@ -18,7 +25,9 @@ export const RemoveUnusedComponents: Oas3Rule = () => {
18
25
  ref: {
19
26
  leave(ref, { type, resolve, key }) {
20
27
  if (
21
- ['Schema', 'Header', 'Parameter', 'Response', 'Example', 'RequestBody'].includes(type.name)
28
+ ['Schema', 'Header', 'Parameter', 'Response', 'Example', 'RequestBody'].includes(
29
+ type.name
30
+ )
22
31
  ) {
23
32
  const resolvedRef = resolve(ref);
24
33
  if (!resolvedRef.location) return;
@@ -27,14 +36,14 @@ export const RemoveUnusedComponents: Oas3Rule = () => {
27
36
  name: key.toString(),
28
37
  });
29
38
  }
30
- }
39
+ },
31
40
  },
32
41
  DefinitionRoot: {
33
42
  leave(root, ctx) {
34
43
  const data = ctx.getVisitorData() as { removedCount: number };
35
44
  data.removedCount = 0;
36
45
 
37
- components.forEach(usageInfo => {
46
+ components.forEach((usageInfo) => {
38
47
  const { used, componentType, name } = usageInfo;
39
48
  if (!used && componentType) {
40
49
  let componentChild = root.components![componentType];
@@ -45,7 +54,9 @@ export const RemoveUnusedComponents: Oas3Rule = () => {
45
54
  }
46
55
  }
47
56
  });
48
- if (isEmptyObject(root.components)) { delete root.components; }
57
+ if (isEmptyObject(root.components)) {
58
+ delete root.components;
59
+ }
49
60
  },
50
61
  },
51
62
  NamedSchemas: {
@@ -4,10 +4,26 @@ import { StatsAccumulator } from '../../typings/common';
4
4
 
5
5
  export const Stats = (statsAccumulator: StatsAccumulator) => {
6
6
  return {
7
- ExternalDocs: { leave() { statsAccumulator.externalDocs.total++; }},
8
- ref: { enter(ref: OasRef) { statsAccumulator.refs.items!.add(ref['$ref']); }},
9
- Tag: { leave(tag: Oas3Tag) { statsAccumulator.tags.items!.add(tag.name); }},
10
- Link: { leave(link: any) { statsAccumulator.links.items!.add(link.operationId); }},
7
+ ExternalDocs: {
8
+ leave() {
9
+ statsAccumulator.externalDocs.total++;
10
+ },
11
+ },
12
+ ref: {
13
+ enter(ref: OasRef) {
14
+ statsAccumulator.refs.items!.add(ref['$ref']);
15
+ },
16
+ },
17
+ Tag: {
18
+ leave(tag: Oas3Tag) {
19
+ statsAccumulator.tags.items!.add(tag.name);
20
+ },
21
+ },
22
+ Link: {
23
+ leave(link: any) {
24
+ statsAccumulator.links.items!.add(link.operationId);
25
+ },
26
+ },
11
27
  DefinitionRoot: {
12
28
  leave() {
13
29
  statsAccumulator.parameters.total = statsAccumulator.parameters.items!.size;
@@ -19,26 +35,39 @@ export const Stats = (statsAccumulator: StatsAccumulator) => {
19
35
  WebhooksMap: {
20
36
  Operation: {
21
37
  leave(operation: any) {
22
- operation.tags.forEach((tag: string) => { statsAccumulator.tags.items!.add(tag); })
23
- }
24
- }
38
+ operation.tags.forEach((tag: string) => {
39
+ statsAccumulator.tags.items!.add(tag);
40
+ });
41
+ },
42
+ },
25
43
  },
26
44
  PathMap: {
27
45
  PathItem: {
28
- leave() { statsAccumulator.pathItems.total++; },
46
+ leave() {
47
+ statsAccumulator.pathItems.total++;
48
+ },
29
49
  Operation: {
30
50
  leave(operation: any) {
31
51
  statsAccumulator.operations.total++;
32
- operation.tags && operation.tags.forEach((tag: string) => { statsAccumulator.tags.items!.add(tag); })
33
- }
52
+ operation.tags &&
53
+ operation.tags.forEach((tag: string) => {
54
+ statsAccumulator.tags.items!.add(tag);
55
+ });
56
+ },
57
+ },
58
+ Parameter: {
59
+ leave(parameter: Oas2Parameter | Oas3Parameter) {
60
+ statsAccumulator.parameters.items!.add(parameter.name);
61
+ },
34
62
  },
35
- Parameter: { leave(parameter: Oas2Parameter | Oas3Parameter) {
36
- statsAccumulator.parameters.items!.add(parameter.name)
37
- }},
38
63
  },
39
64
  },
40
65
  NamedSchemas: {
41
- Schema: { leave() { statsAccumulator.schemas.total++; }}
42
- }
43
- }
44
- }
66
+ Schema: {
67
+ leave() {
68
+ statsAccumulator.schemas.total++;
69
+ },
70
+ },
71
+ },
72
+ };
73
+ };
@@ -9,6 +9,8 @@ export function oasTypeOf(value: unknown) {
9
9
  return 'array';
10
10
  } else if (value === null) {
11
11
  return 'null';
12
+ } else if (Number.isInteger(value)) {
13
+ return 'integer';
12
14
  } else {
13
15
  return typeof value;
14
16
  }
@@ -23,7 +25,7 @@ export function oasTypeOf(value: unknown) {
23
25
  */
24
26
  export function matchesJsonSchemaType(value: unknown, type: string, nullable: boolean): boolean {
25
27
  if (nullable && value === null) {
26
- return value === null;
28
+ return true;
27
29
  }
28
30
 
29
31
  switch (type) {
@@ -89,7 +91,7 @@ export function validateExample(
89
91
  schema: Referenced<Oas3Schema>,
90
92
  dataLoc: Location,
91
93
  { resolve, location, report }: UserContext,
92
- disallowAdditionalProperties: boolean,
94
+ disallowAdditionalProperties: boolean
93
95
  ) {
94
96
  try {
95
97
  const { valid, errors } = validateJsonSchema(
@@ -98,7 +100,7 @@ export function validateExample(
98
100
  location.child('schema'),
99
101
  dataLoc.pointer,
100
102
  resolve,
101
- disallowAdditionalProperties,
103
+ disallowAdditionalProperties
102
104
  );
103
105
  if (!valid) {
104
106
  for (let error of errors) {
@@ -24,7 +24,7 @@ export type NodeType = {
24
24
  items?: string;
25
25
  required?: string[] | ((value: any, key: string | number | undefined) => string[]);
26
26
  requiredOneOf?: string[];
27
- allowed?: ((value: any) => string[] | undefined);
27
+ allowed?: (value: any) => string[] | undefined;
28
28
  extensionsPrefix?: string;
29
29
  };
30
30
  type PropType = string | NodeType | ScalarSchema | undefined | null;
@@ -37,14 +37,14 @@ export type NormalizedNodeType = {
37
37
  items?: NormalizedNodeType;
38
38
  required?: string[] | ((value: any, key: string | number | undefined) => string[]);
39
39
  requiredOneOf?: string[];
40
- allowed?: ((value: any) => string[] | undefined);
40
+ allowed?: (value: any) => string[] | undefined;
41
41
  extensionsPrefix?: string;
42
42
  };
43
43
 
44
44
  type NormalizedPropType = NormalizedNodeType | NormalizedScalarSchema | undefined | null;
45
45
  type NormalizedResolveTypeFn = (
46
46
  value: any,
47
- key: string,
47
+ key: string
48
48
  ) => NormalizedNodeType | NormalizedScalarSchema | undefined | null;
49
49
 
50
50
  export function listOf(typeName: string) {
@@ -65,7 +65,7 @@ export function mapOf(typeName: string) {
65
65
 
66
66
  export function normalizeTypes(
67
67
  types: Record<string, NodeType>,
68
- options: { doNotResolveExamples?: boolean } = {},
68
+ options: { doNotResolveExamples?: boolean } = {}
69
69
  ): Record<string, NormalizedNodeType> {
70
70
  const normalizedTypes: Record<string, NormalizedNodeType> = {};
71
71
 
@@ -132,7 +132,7 @@ export function normalizeTypes(
132
132
  }
133
133
 
134
134
  export function isNamedType(
135
- t: NormalizedNodeType | NormalizedScalarSchema | null | undefined,
135
+ t: NormalizedNodeType | NormalizedScalarSchema | null | undefined
136
136
  ): t is NormalizedNodeType {
137
137
  return typeof t?.name === 'string';
138
138
  }
@@ -50,6 +50,7 @@ const builtInRulesList = [
50
50
  'no-invalid-parameter-examples',
51
51
  'response-contains-header',
52
52
  'response-contains-property',
53
+ 'scalar-property-missing-example',
53
54
  ];
54
55
  const nodeTypesList = [
55
56
  'DefinitionRoot',
@@ -109,7 +110,8 @@ const ConfigRoot: NodeType = {
109
110
  properties: {},
110
111
  additionalProperties: { properties: { type: 'string' } },
111
112
  }, // deprecated
112
- lint: 'RootConfigLint',
113
+ styleguide: 'RootConfigStyleguide',
114
+ lint: 'RootConfigStyleguide', // deprecated
113
115
  'features.openapi': 'ConfigReferenceDocs',
114
116
  referenceDocs: 'ConfigReferenceDocs', // deprecated
115
117
  'features.mockServer': 'ConfigMockServer',
@@ -136,7 +138,7 @@ const ConfigApisProperties: NodeType = {
136
138
  type: 'string',
137
139
  },
138
140
  },
139
- lint: 'ConfigLint',
141
+ styleguide: 'ConfigStyleguide',
140
142
  'features.openapi': 'ConfigReferenceDocs',
141
143
  'features.mockServer': 'ConfigMockServer',
142
144
  },
@@ -154,7 +156,7 @@ const ConfigHTTP: NodeType = {
154
156
  },
155
157
  };
156
158
 
157
- const ConfigLint: NodeType = {
159
+ const ConfigStyleguide: NodeType = {
158
160
  properties: {
159
161
  extends: {
160
162
  type: 'array',
@@ -178,13 +180,13 @@ const ConfigLint: NodeType = {
178
180
  },
179
181
  };
180
182
 
181
- const RootConfigLint: NodeType = {
183
+ const RootConfigStyleguide: NodeType = {
182
184
  properties: {
183
185
  plugins: {
184
186
  type: 'array',
185
187
  items: { type: 'string' },
186
188
  },
187
- ...ConfigLint.properties,
189
+ ...ConfigStyleguide.properties,
188
190
  },
189
191
  };
190
192
 
@@ -876,8 +878,8 @@ export const ConfigTypes: Record<string, NodeType> = {
876
878
  ConfigRoot,
877
879
  ConfigApis,
878
880
  ConfigApisProperties,
879
- RootConfigLint,
880
- ConfigLint,
881
+ RootConfigStyleguide,
882
+ ConfigStyleguide,
881
883
  ConfigReferenceDocs,
882
884
  ConfigMockServer,
883
885
  ConfigHTTP,
@@ -5,5 +5,13 @@ export interface StatsRow {
5
5
  items?: Set<string>;
6
6
  }
7
7
 
8
- export type StatsName = 'operations' | 'refs' | 'tags' | 'externalDocs' | 'pathItems' | 'links' | 'schemas' | 'parameters';
8
+ export type StatsName =
9
+ | 'operations'
10
+ | 'refs'
11
+ | 'tags'
12
+ | 'externalDocs'
13
+ | 'pathItems'
14
+ | 'links'
15
+ | 'schemas'
16
+ | 'parameters';
9
17
  export type StatsAccumulator = Record<StatsName, StatsRow>;
@@ -156,7 +156,7 @@ export interface Oas3Schema {
156
156
  export type Oas3_1Schema = Oas3Schema & {
157
157
  type?: string | string[];
158
158
  examples?: any[];
159
- }
159
+ };
160
160
 
161
161
  export interface Oas3_1Definition extends Oas3Definition {
162
162
  webhooks?: Oas3_1Webhooks;
package/src/utils.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import * as fs from 'fs';
2
+ import { extname } from 'path';
2
3
  import * as minimatch from 'minimatch';
3
4
  import fetch from 'node-fetch';
4
5
  import * as pluralize from 'pluralize';
5
6
  import { parseYaml } from './js-yaml';
6
7
  import { UserContext } from './walk';
7
- import type { HttpResolveConfig } from './config';
8
+ import { HttpResolveConfig } from './config';
8
9
  import { env } from './config';
9
10
 
10
11
  export { parseYaml, stringifyYaml } from './js-yaml';
@@ -77,16 +78,16 @@ function match(url: string, pattern: string) {
77
78
 
78
79
  export function pickObjectProps<T extends Record<string, unknown>>(
79
80
  object: T,
80
- keys: Array<string>,
81
+ keys: Array<string>
81
82
  ): T {
82
83
  return Object.fromEntries(
83
- keys.filter((key: string) => key in object).map((key: string) => [key, object[key]]),
84
+ keys.filter((key: string) => key in object).map((key: string) => [key, object[key]])
84
85
  ) as T;
85
86
  }
86
87
 
87
88
  export function omitObjectProps<T extends Record<string, unknown>>(
88
89
  object: T,
89
- keys: Array<string>,
90
+ keys: Array<string>
90
91
  ): T {
91
92
  return Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key))) as T;
92
93
  }
@@ -106,7 +107,7 @@ export function splitCamelCaseIntoWords(str: string) {
106
107
  export function validateMimeType(
107
108
  { type, value }: any,
108
109
  { report, location }: UserContext,
109
- allowedValues: string[],
110
+ allowedValues: string[]
110
111
  ) {
111
112
  const ruleType = type === 'consumes' ? 'request' : 'response';
112
113
  if (!allowedValues)
@@ -126,7 +127,7 @@ export function validateMimeType(
126
127
  export function validateMimeTypeOAS3(
127
128
  { type, value }: any,
128
129
  { report, location }: UserContext,
129
- allowedValues: string[],
130
+ allowedValues: string[]
130
131
  ) {
131
132
  const ruleType = type === 'consumes' ? 'request' : 'response';
132
133
  if (!allowedValues)
@@ -188,9 +189,18 @@ export function assignExisting<T>(target: Record<string, T>, obj: Record<string,
188
189
  }
189
190
  }
190
191
 
191
- export const getMatchingStatusCodeRange = (code: number | string): string =>
192
- `${code}`.replace(/^(\d)\d\d$/, (_, firstDigit) => `${firstDigit}XX`);
192
+ export function getMatchingStatusCodeRange(code: number | string): string {
193
+ return `${code}`.replace(/^(\d)\d\d$/, (_, firstDigit) => `${firstDigit}XX`);
194
+ }
193
195
 
194
196
  export function isCustomRuleId(id: string) {
195
197
  return id.includes('/');
196
198
  }
199
+
200
+ export function doesYamlFileExist(filePath: string): boolean {
201
+ return (
202
+ (extname(filePath) === '.yaml' || extname(filePath) === '.yml') &&
203
+ fs.hasOwnProperty('existsSync') &&
204
+ fs.existsSync(filePath)
205
+ );
206
+ }
package/src/visitors.ts CHANGED
@@ -53,7 +53,7 @@ export type VisitFunction<T> = (
53
53
  node: T,
54
54
  ctx: UserContext & { ignoreNextVisitorsOnNode: () => void },
55
55
  parents?: any,
56
- context?: any,
56
+ context?: any
57
57
  ) => void;
58
58
 
59
59
  type VisitRefFunction = (node: OasRef, ctx: UserContext, resolved: ResolveResult<any>) => void;
@@ -264,7 +264,7 @@ export type RuleInstanceConfig = {
264
264
 
265
265
  export function normalizeVisitors<T extends BaseVisitor>(
266
266
  visitorsConfig: (RuleInstanceConfig & { visitor: NestedVisitObject<any, T> })[],
267
- types: Record<keyof T, NormalizedNodeType>,
267
+ types: Record<keyof T, NormalizedNodeType>
268
268
  ): NormalizedOasVisitors<T> {
269
269
  const normalizedVisitors: NormalizedOasVisitors<T> = {} as any;
270
270
 
@@ -301,7 +301,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
301
301
  from: NormalizedNodeType,
302
302
  to: NormalizedNodeType,
303
303
  parentContext: VisitorLevelContext,
304
- stack: NormalizedNodeType[] = [],
304
+ stack: NormalizedNodeType[] = []
305
305
  ) {
306
306
  if (stack.includes(from)) return;
307
307
 
@@ -363,7 +363,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
363
363
  ruleConf: RuleInstanceConfig,
364
364
  visitor: NestedVisitObject<any, T>,
365
365
  parentContext: VisitorLevelContext | null,
366
- depth = 0,
366
+ depth = 0
367
367
  ) {
368
368
  const visitorKeys = Object.keys(types) as Array<keyof T | 'any'>;
369
369