@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
@@ -12,28 +12,30 @@ import {
12
12
  transformConfig,
13
13
  } from './utils';
14
14
  import type {
15
- LintRawConfig,
15
+ StyleguideRawConfig,
16
+ ApiStyleguideRawConfig,
16
17
  Plugin,
17
18
  RawConfig,
18
19
  ResolvedApi,
19
- ResolvedLintConfig,
20
+ ResolvedStyleguideConfig,
20
21
  RuleConfig,
22
+ DeprecatedInRawConfig,
21
23
  } from './types';
22
24
  import { isNotString, isString, notUndefined, parseYaml } from '../utils';
23
25
  import { Config } from './config';
24
26
 
25
- export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
26
- if (rawConfig.lint?.extends?.some(isNotString)) {
27
+ export async function resolveConfig(rawConfig: RawConfig, configPath?: string): Promise<Config> {
28
+ if (rawConfig.styleguide?.extends?.some(isNotString)) {
27
29
  throw new Error(
28
- `Error configuration format not detected in extends value must contain strings`,
30
+ `Error configuration format not detected in extends value must contain strings`
29
31
  );
30
32
  }
31
33
 
32
34
  const resolver = new BaseResolver(getResolveConfig(rawConfig.resolve));
33
- const configExtends = rawConfig?.lint?.extends ?? ['recommended'];
34
- const recommendedFallback = !rawConfig?.lint?.extends;
35
- const lintConfig = {
36
- ...rawConfig?.lint,
35
+ const configExtends = rawConfig?.styleguide?.extends ?? ['recommended'];
36
+ const recommendedFallback = !rawConfig?.styleguide?.extends;
37
+ const styleguideConfig = {
38
+ ...rawConfig?.styleguide,
37
39
  extends: configExtends,
38
40
  recommendedFallback,
39
41
  };
@@ -41,14 +43,14 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
41
43
  const apis = await resolveApis({
42
44
  rawConfig: {
43
45
  ...rawConfig,
44
- lint: lintConfig,
46
+ styleguide: styleguideConfig,
45
47
  },
46
48
  configPath,
47
49
  resolver,
48
50
  });
49
51
 
50
- const lint = await resolveLint({
51
- lintConfig,
52
+ const styleguide = await resolveStyleguideConfig({
53
+ styleguideConfig,
52
54
  configPath,
53
55
  resolver,
54
56
  });
@@ -57,15 +59,15 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
57
59
  {
58
60
  ...rawConfig,
59
61
  apis,
60
- lint,
62
+ styleguide,
61
63
  },
62
- configPath,
64
+ configPath
63
65
  );
64
66
  }
65
67
 
66
68
  export function resolvePlugins(
67
69
  plugins: (string | Plugin)[] | null,
68
- configPath: string = '',
70
+ configPath: string = ''
69
71
  ): Plugin[] {
70
72
  if (!plugins) return [];
71
73
 
@@ -95,9 +97,9 @@ export function resolvePlugins(
95
97
  throw new Error(
96
98
  red(
97
99
  `Plugin "id" must be unique. Plugin ${blue(p.toString())} uses id "${blue(
98
- id,
99
- )}" already seen in ${blue(pluginPath)}`,
100
- ),
100
+ id
101
+ )}" already seen in ${blue(pluginPath)}`
102
+ )
101
103
  );
102
104
  }
103
105
 
@@ -124,7 +126,7 @@ export function resolvePlugins(
124
126
  if (pluginModule.preprocessors) {
125
127
  if (!pluginModule.preprocessors.oas3 && !pluginModule.preprocessors.oas2) {
126
128
  throw new Error(
127
- `Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}.`,
129
+ `Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}.`
128
130
  );
129
131
  }
130
132
  plugin.preprocessors = {};
@@ -163,45 +165,48 @@ export async function resolveApis({
163
165
  configPath?: string;
164
166
  resolver?: BaseResolver;
165
167
  }): Promise<Record<string, ResolvedApi>> {
166
- const { apis = {}, lint: lintConfig = {} } = rawConfig;
168
+ const { apis = {}, styleguide: styleguideConfig = {} } = rawConfig;
167
169
  let resolvedApis: Record<string, ResolvedApi> = {};
168
170
  for (const [apiName, apiContent] of Object.entries(apis || {})) {
169
- if (apiContent.lint?.extends?.some(isNotString)) {
171
+ if (apiContent.styleguide?.extends?.some(isNotString)) {
170
172
  throw new Error(
171
- `Error configuration format not detected in extends value must contain strings`,
173
+ `Error configuration format not detected in extends value must contain strings`
172
174
  );
173
175
  }
174
- const rawLintConfig = getMergedLintRawConfig(lintConfig, apiContent.lint);
175
- const apiLint = await resolveLint({
176
- lintConfig: rawLintConfig,
176
+ const rawStyleguideConfig = getMergedRawStyleguideConfig(
177
+ styleguideConfig,
178
+ apiContent.styleguide
179
+ );
180
+ const resolvedApiConfig = await resolveStyleguideConfig({
181
+ styleguideConfig: rawStyleguideConfig,
177
182
  configPath,
178
183
  resolver,
179
184
  });
180
- resolvedApis[apiName] = { ...apiContent, lint: apiLint };
185
+ resolvedApis[apiName] = { ...apiContent, styleguide: resolvedApiConfig };
181
186
  }
182
187
  return resolvedApis;
183
188
  }
184
189
 
185
- async function resolveAndMergeNestedLint(
190
+ async function resolveAndMergeNestedStyleguideConfig(
186
191
  {
187
- lintConfig,
192
+ styleguideConfig,
188
193
  configPath = '',
189
194
  resolver = new BaseResolver(),
190
195
  }: {
191
- lintConfig?: LintRawConfig;
196
+ styleguideConfig?: StyleguideRawConfig;
192
197
  configPath?: string;
193
198
  resolver?: BaseResolver;
194
199
  },
195
200
  parentConfigPaths: string[] = [],
196
- extendPaths: string[] = [],
197
- ): Promise<ResolvedLintConfig> {
201
+ extendPaths: string[] = []
202
+ ): Promise<ResolvedStyleguideConfig> {
198
203
  if (parentConfigPaths.includes(configPath)) {
199
204
  throw new Error(`Circular dependency in config file: "${configPath}"`);
200
205
  }
201
206
  const plugins = getUniquePlugins(
202
- resolvePlugins([...(lintConfig?.plugins || []), defaultPlugin], configPath),
207
+ resolvePlugins([...(styleguideConfig?.plugins || []), defaultPlugin], configPath)
203
208
  );
204
- const pluginPaths = lintConfig?.plugins
209
+ const pluginPaths = styleguideConfig?.plugins
205
210
  ?.filter(isString)
206
211
  .map((p) => path.resolve(path.dirname(configPath), p));
207
212
 
@@ -209,8 +214,8 @@ async function resolveAndMergeNestedLint(
209
214
  ? configPath
210
215
  : configPath && path.resolve(configPath);
211
216
 
212
- const extendConfigs: ResolvedLintConfig[] = await Promise.all(
213
- lintConfig?.extends?.map(async (presetItem) => {
217
+ const extendConfigs: ResolvedStyleguideConfig[] = await Promise.all(
218
+ styleguideConfig?.extends?.map(async (presetItem) => {
214
219
  if (!isAbsoluteUrl(presetItem) && !path.extname(presetItem)) {
215
220
  return resolvePreset(presetItem, plugins);
216
221
  }
@@ -219,23 +224,23 @@ async function resolveAndMergeNestedLint(
219
224
  : isAbsoluteUrl(configPath)
220
225
  ? new URL(presetItem, configPath).href
221
226
  : path.resolve(path.dirname(configPath), presetItem);
222
- const extendedLintConfig = await loadExtendLintConfig(pathItem, resolver);
223
- return await resolveAndMergeNestedLint(
227
+ const extendedStyleguideConfig = await loadExtendStyleguideConfig(pathItem, resolver);
228
+ return await resolveAndMergeNestedStyleguideConfig(
224
229
  {
225
- lintConfig: extendedLintConfig,
230
+ styleguideConfig: extendedStyleguideConfig,
226
231
  configPath: pathItem,
227
232
  resolver: resolver,
228
233
  },
229
234
  [...parentConfigPaths, resolvedConfigPath],
230
- extendPaths,
235
+ extendPaths
231
236
  );
232
- }) || [],
237
+ }) || []
233
238
  );
234
239
 
235
- const { plugins: mergedPlugins = [], ...lint } = mergeExtends([
240
+ const { plugins: mergedPlugins = [], ...styleguide } = mergeExtends([
236
241
  ...extendConfigs,
237
242
  {
238
- ...lintConfig,
243
+ ...styleguideConfig,
239
244
  plugins,
240
245
  extends: undefined,
241
246
  extendPaths: [...parentConfigPaths, resolvedConfigPath],
@@ -244,91 +249,125 @@ async function resolveAndMergeNestedLint(
244
249
  ]);
245
250
 
246
251
  return {
247
- ...lint,
248
- extendPaths: lint.extendPaths?.filter((path) => path && !isAbsoluteUrl(path)),
252
+ ...styleguide,
253
+ extendPaths: styleguide.extendPaths?.filter((path) => path && !isAbsoluteUrl(path)),
249
254
  plugins: getUniquePlugins(mergedPlugins),
250
- recommendedFallback: lintConfig?.recommendedFallback,
251
- doNotResolveExamples: lintConfig?.doNotResolveExamples,
255
+ recommendedFallback: styleguideConfig?.recommendedFallback,
256
+ doNotResolveExamples: styleguideConfig?.doNotResolveExamples,
252
257
  };
253
258
  }
254
259
 
255
- export async function resolveLint(
256
- lintOpts: {
257
- lintConfig?: LintRawConfig;
260
+ export async function resolveStyleguideConfig(
261
+ opts: {
262
+ styleguideConfig?: StyleguideRawConfig;
258
263
  configPath?: string;
259
264
  resolver?: BaseResolver;
260
265
  },
261
266
  parentConfigPaths: string[] = [],
262
- extendPaths: string[] = [],
263
- ): Promise<ResolvedLintConfig> {
264
- const resolvedLint = await resolveAndMergeNestedLint(lintOpts, parentConfigPaths, extendPaths);
267
+ extendPaths: string[] = []
268
+ ): Promise<ResolvedStyleguideConfig> {
269
+ const resolvedStyleguideConfig = await resolveAndMergeNestedStyleguideConfig(
270
+ opts,
271
+ parentConfigPaths,
272
+ extendPaths
273
+ );
265
274
 
266
275
  return {
267
- ...resolvedLint,
268
- rules: resolvedLint.rules && groupLintAssertionRules(resolvedLint.rules),
276
+ ...resolvedStyleguideConfig,
277
+ rules:
278
+ resolvedStyleguideConfig.rules &&
279
+ groupStyleguideAssertionRules(resolvedStyleguideConfig.rules),
269
280
  };
270
281
  }
271
282
 
272
- export function resolvePreset(presetName: string, plugins: Plugin[]): ResolvedLintConfig {
283
+ export function resolvePreset(presetName: string, plugins: Plugin[]): ResolvedStyleguideConfig {
273
284
  const { pluginId, configName } = parsePresetName(presetName);
274
285
  const plugin = plugins.find((p) => p.id === pluginId);
275
286
  if (!plugin) {
276
287
  throw new Error(`Invalid config ${red(presetName)}: plugin ${pluginId} is not included.`);
277
288
  }
278
289
 
279
- const preset = plugin.configs?.[configName]! as ResolvedLintConfig;
290
+ const preset = plugin.configs?.[configName]! as ResolvedStyleguideConfig;
280
291
  if (!preset) {
281
292
  throw new Error(
282
293
  pluginId
283
294
  ? `Invalid config ${red(
284
- presetName,
295
+ presetName
285
296
  )}: plugin ${pluginId} doesn't export config with name ${configName}.`
286
- : `Invalid config ${red(presetName)}: there is no such built-in config.`,
297
+ : `Invalid config ${red(presetName)}: there is no such built-in config.`
287
298
  );
288
299
  }
289
300
  return preset;
290
301
  }
291
302
 
292
- async function loadExtendLintConfig(
303
+ async function loadExtendStyleguideConfig(
293
304
  filePath: string,
294
- resolver: BaseResolver,
295
- ): Promise<LintRawConfig> {
305
+ resolver: BaseResolver
306
+ ): Promise<StyleguideRawConfig> {
296
307
  try {
297
308
  const fileSource = await resolver.loadExternalRef(filePath);
298
- const rawConfig = transformConfig(parseYaml(fileSource.body) as RawConfig);
299
- if (!rawConfig.lint) {
300
- throw new Error(`Lint configuration format not detected: "${filePath}"`);
309
+ const rawConfig = transformConfig(
310
+ parseYaml(fileSource.body) as RawConfig & DeprecatedInRawConfig
311
+ );
312
+ if (!rawConfig.styleguide) {
313
+ throw new Error(`Styleguide configuration format not detected: "${filePath}"`);
301
314
  }
302
315
 
303
- return rawConfig.lint;
316
+ return rawConfig.styleguide;
304
317
  } catch (error) {
305
318
  throw new Error(`Failed to load "${filePath}": ${error.message}`);
306
319
  }
307
320
  }
308
321
 
309
- function getMergedLintRawConfig(configLint: LintRawConfig, apiLint?: LintRawConfig) {
322
+ function getMergedRawStyleguideConfig(
323
+ rootStyleguideConfig: StyleguideRawConfig,
324
+ apiStyleguideConfig?: ApiStyleguideRawConfig
325
+ ) {
310
326
  const resultLint = {
311
- ...configLint,
312
- ...apiLint,
313
- rules: { ...configLint?.rules, ...apiLint?.rules },
314
- oas2Rules: { ...configLint?.oas2Rules, ...apiLint?.oas2Rules },
315
- oas3_0Rules: { ...configLint?.oas3_0Rules, ...apiLint?.oas3_0Rules },
316
- oas3_1Rules: { ...configLint?.oas3_1Rules, ...apiLint?.oas3_1Rules },
317
- preprocessors: { ...configLint?.preprocessors, ...apiLint?.preprocessors },
318
- oas2Preprocessors: { ...configLint?.oas2Preprocessors, ...apiLint?.oas2Preprocessors },
319
- oas3_0Preprocessors: { ...configLint?.oas3_0Preprocessors, ...apiLint?.oas3_0Preprocessors },
320
- oas3_1Preprocessors: { ...configLint?.oas3_1Preprocessors, ...apiLint?.oas3_1Preprocessors },
321
- decorators: { ...configLint?.decorators, ...apiLint?.decorators },
322
- oas2Decorators: { ...configLint?.oas2Decorators, ...apiLint?.oas2Decorators },
323
- oas3_0Decorators: { ...configLint?.oas3_0Decorators, ...apiLint?.oas3_0Decorators },
324
- oas3_1Decorators: { ...configLint?.oas3_1Decorators, ...apiLint?.oas3_1Decorators },
325
- recommendedFallback: apiLint?.extends ? false : configLint.recommendedFallback,
327
+ ...rootStyleguideConfig,
328
+ ...apiStyleguideConfig,
329
+ rules: { ...rootStyleguideConfig?.rules, ...apiStyleguideConfig?.rules },
330
+ oas2Rules: { ...rootStyleguideConfig?.oas2Rules, ...apiStyleguideConfig?.oas2Rules },
331
+ oas3_0Rules: { ...rootStyleguideConfig?.oas3_0Rules, ...apiStyleguideConfig?.oas3_0Rules },
332
+ oas3_1Rules: { ...rootStyleguideConfig?.oas3_1Rules, ...apiStyleguideConfig?.oas3_1Rules },
333
+ preprocessors: {
334
+ ...rootStyleguideConfig?.preprocessors,
335
+ ...apiStyleguideConfig?.preprocessors,
336
+ },
337
+ oas2Preprocessors: {
338
+ ...rootStyleguideConfig?.oas2Preprocessors,
339
+ ...apiStyleguideConfig?.oas2Preprocessors,
340
+ },
341
+ oas3_0Preprocessors: {
342
+ ...rootStyleguideConfig?.oas3_0Preprocessors,
343
+ ...apiStyleguideConfig?.oas3_0Preprocessors,
344
+ },
345
+ oas3_1Preprocessors: {
346
+ ...rootStyleguideConfig?.oas3_1Preprocessors,
347
+ ...apiStyleguideConfig?.oas3_1Preprocessors,
348
+ },
349
+ decorators: { ...rootStyleguideConfig?.decorators, ...apiStyleguideConfig?.decorators },
350
+ oas2Decorators: {
351
+ ...rootStyleguideConfig?.oas2Decorators,
352
+ ...apiStyleguideConfig?.oas2Decorators,
353
+ },
354
+ oas3_0Decorators: {
355
+ ...rootStyleguideConfig?.oas3_0Decorators,
356
+ ...apiStyleguideConfig?.oas3_0Decorators,
357
+ },
358
+ oas3_1Decorators: {
359
+ ...rootStyleguideConfig?.oas3_1Decorators,
360
+ ...apiStyleguideConfig?.oas3_1Decorators,
361
+ },
362
+ recommendedFallback: apiStyleguideConfig?.extends
363
+ ? false
364
+ : rootStyleguideConfig.recommendedFallback,
326
365
  };
327
366
  return resultLint;
328
367
  }
329
368
 
330
- function groupLintAssertionRules(
331
- rules: Record<string, RuleConfig> | undefined,
369
+ function groupStyleguideAssertionRules(
370
+ rules: Record<string, RuleConfig> | undefined
332
371
  ): Record<string, RuleConfig> | undefined {
333
372
  if (!rules) {
334
373
  return rules;
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { parseYaml, stringifyYaml } from '../js-yaml';
4
- import { slash } from '../utils';
4
+ import { slash, doesYamlFileExist } from '../utils';
5
5
  import { NormalizedProblem } from '../walk';
6
6
  import { OasVersion, OasMajorVersion, Oas2RuleSet, Oas3RuleSet } from '../oas-types';
7
7
 
@@ -14,7 +14,7 @@ import type {
14
14
  ResolveConfig,
15
15
  ResolvedApi,
16
16
  ResolvedConfig,
17
- ResolvedLintConfig,
17
+ ResolvedStyleguideConfig,
18
18
  RuleConfig,
19
19
  } from './types';
20
20
  import { getResolveConfig } from './utils';
@@ -46,10 +46,20 @@ function getDomains() {
46
46
  return domains;
47
47
  }
48
48
 
49
+ function getIgnoreFilePath(configFile?: string): string | undefined {
50
+ if (configFile) {
51
+ return doesYamlFileExist(configFile)
52
+ ? path.join(path.dirname(configFile), IGNORE_FILE)
53
+ : path.join(configFile, IGNORE_FILE);
54
+ } else {
55
+ return typeof process === 'undefined' ? undefined : path.join(process.cwd(), IGNORE_FILE);
56
+ }
57
+ }
58
+
49
59
  export const DOMAINS = getDomains();
50
60
  export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
51
61
 
52
- export class LintConfig {
62
+ export class StyleguideConfig {
53
63
  plugins: Plugin[];
54
64
  ignore: Record<string, Record<string, Set<string>>> = {};
55
65
  doNotResolveExamples: boolean;
@@ -65,11 +75,11 @@ export class LintConfig {
65
75
  extendPaths: string[];
66
76
  pluginPaths: string[];
67
77
 
68
- constructor(public rawConfig: ResolvedLintConfig, public configFile?: string) {
78
+ constructor(public rawConfig: ResolvedStyleguideConfig, public configFile?: string) {
69
79
  this.plugins = rawConfig.plugins || [];
70
80
  this.doNotResolveExamples = !!rawConfig.doNotResolveExamples;
71
81
 
72
- this.recommendedFallback = rawConfig.recommendedFallback || false
82
+ this.recommendedFallback = rawConfig.recommendedFallback || false;
73
83
 
74
84
  this.rules = {
75
85
  [OasVersion.Version2]: { ...rawConfig.rules, ...rawConfig.oas2Rules },
@@ -91,29 +101,25 @@ export class LintConfig {
91
101
 
92
102
  this.extendPaths = rawConfig.extendPaths || [];
93
103
  this.pluginPaths = rawConfig.pluginPaths || [];
104
+ this.resolveIgnore(getIgnoreFilePath(configFile));
105
+ }
94
106
 
95
- const dir = this.configFile
96
- ? path.dirname(this.configFile)
97
- : (typeof process !== 'undefined' && process.cwd()) || '';
98
- const ignoreFile = path.join(dir, IGNORE_FILE);
107
+ resolveIgnore(ignoreFile?: string) {
108
+ if (!ignoreFile || !doesYamlFileExist(ignoreFile)) return;
99
109
 
100
- /* no crash when using it on the client */
101
- if (fs.hasOwnProperty('existsSync') && fs.existsSync(ignoreFile)) {
102
- // TODO: parse errors
103
- this.ignore =
104
- (parseYaml(fs.readFileSync(ignoreFile, 'utf-8')) as Record<
105
- string,
106
- Record<string, Set<string>>
107
- >) || {};
108
-
109
- // resolve ignore paths
110
- for (const fileName of Object.keys(this.ignore)) {
111
- this.ignore[path.resolve(path.dirname(ignoreFile), fileName)] = this.ignore[fileName];
112
- for (const ruleId of Object.keys(this.ignore[fileName])) {
113
- this.ignore[fileName][ruleId] = new Set(this.ignore[fileName][ruleId]);
114
- }
115
- delete this.ignore[fileName];
110
+ this.ignore =
111
+ (parseYaml(fs.readFileSync(ignoreFile, 'utf-8')) as Record<
112
+ string,
113
+ Record<string, Set<string>>
114
+ >) || {};
115
+
116
+ // resolve ignore paths
117
+ for (const fileName of Object.keys(this.ignore)) {
118
+ this.ignore[path.resolve(path.dirname(ignoreFile), fileName)] = this.ignore[fileName];
119
+ for (const ruleId of Object.keys(this.ignore[fileName])) {
120
+ this.ignore[fileName][ruleId] = new Set(this.ignore[fileName][ruleId]);
116
121
  }
122
+ delete this.ignore[fileName];
117
123
  }
118
124
  }
119
125
 
@@ -224,15 +230,13 @@ export class LintConfig {
224
230
 
225
231
  for (const usedVersion of Array.from(this._usedVersions)) {
226
232
  rules.push(
227
- ...Object.keys(this.rules[usedVersion]).filter((name) => !this._usedRules.has(name)),
233
+ ...Object.keys(this.rules[usedVersion]).filter((name) => !this._usedRules.has(name))
228
234
  );
229
235
  decorators.push(
230
- ...Object.keys(this.decorators[usedVersion]).filter((name) => !this._usedRules.has(name)),
236
+ ...Object.keys(this.decorators[usedVersion]).filter((name) => !this._usedRules.has(name))
231
237
  );
232
238
  preprocessors.push(
233
- ...Object.keys(this.preprocessors[usedVersion]).filter(
234
- (name) => !this._usedRules.has(name),
235
- ),
239
+ ...Object.keys(this.preprocessors[usedVersion]).filter((name) => !this._usedRules.has(name))
236
240
  );
237
241
  }
238
242
 
@@ -293,7 +297,7 @@ export class LintConfig {
293
297
 
294
298
  export class Config {
295
299
  apis: Record<string, ResolvedApi>;
296
- lint: LintConfig;
300
+ styleguide: StyleguideConfig;
297
301
  resolve: ResolveConfig;
298
302
  licenseKey?: string;
299
303
  region?: Region;
@@ -302,7 +306,7 @@ export class Config {
302
306
  organization?: string;
303
307
  constructor(public rawConfig: ResolvedConfig, public configFile?: string) {
304
308
  this.apis = rawConfig.apis || {};
305
- this.lint = new LintConfig(rawConfig.lint || {}, configFile);
309
+ this.styleguide = new StyleguideConfig(rawConfig.styleguide || {}, configFile);
306
310
  this['features.openapi'] = rawConfig['features.openapi'] || {};
307
311
  this['features.mockServer'] = rawConfig['features.mockServer'] || {};
308
312
  this.resolve = getResolveConfig(rawConfig?.resolve);
@@ -1,29 +1,28 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { RedoclyClient } from '../redocly';
4
- import { isEmptyObject, loadYaml } from '../utils';
4
+ import { isEmptyObject, loadYaml, doesYamlFileExist } from '../utils';
5
5
  import { Config, DOMAINS } from './config';
6
6
  import { transformConfig } from './utils';
7
7
  import { resolveConfig } from './config-resolvers';
8
8
 
9
- import type { RawConfig, Region } from './types';
9
+ import type { DeprecatedInRawConfig, RawConfig, Region } from './types';
10
10
 
11
11
  async function addConfigMetadata({
12
12
  rawConfig,
13
13
  customExtends,
14
- configPath
14
+ configPath,
15
15
  }: {
16
16
  rawConfig: RawConfig;
17
17
  customExtends?: string[];
18
18
  configPath?: string;
19
-
20
19
  }): Promise<Config> {
21
20
  if (customExtends !== undefined) {
22
- rawConfig.lint = rawConfig.lint || {};
23
- rawConfig.lint.extends = customExtends;
21
+ rawConfig.styleguide = rawConfig.styleguide || {};
22
+ rawConfig.styleguide.extends = customExtends;
24
23
  } else if (isEmptyObject(rawConfig)) {
25
24
  // TODO: check if we can add recommended here. add message here?
26
- // rawConfig.lint = { extends: ['recommended'], recommendedFallback: true };
25
+ // rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
27
26
  }
28
27
 
29
28
  const redoclyClient = new RedoclyClient();
@@ -53,7 +52,7 @@ async function addConfigMetadata({
53
52
  value: item.token,
54
53
  },
55
54
  ]
56
- : []),
55
+ : [])
57
56
  );
58
57
  }
59
58
  }
@@ -64,27 +63,25 @@ async function addConfigMetadata({
64
63
  export async function loadConfig(
65
64
  configPath: string | undefined = findConfig(),
66
65
  customExtends?: string[],
67
- processRawConfig?: (rawConfig: RawConfig) => void | Promise<void>,
66
+ processRawConfig?: (rawConfig: RawConfig) => void | Promise<void>
68
67
  ): Promise<Config> {
69
68
  const rawConfig = await getConfig(configPath);
70
-
71
69
  if (typeof processRawConfig === 'function') {
72
70
  await processRawConfig(rawConfig);
73
71
  }
74
-
75
72
  return await addConfigMetadata({
76
73
  rawConfig,
77
74
  customExtends,
78
75
  configPath,
79
76
  });
80
- };
77
+ }
81
78
 
82
79
  export const CONFIG_FILE_NAMES = ['redocly.yaml', 'redocly.yml', '.redocly.yaml', '.redocly.yml'];
83
80
 
84
81
  export function findConfig(dir?: string): string | undefined {
85
82
  if (!fs.hasOwnProperty('existsSync')) return;
86
83
  const existingConfigFiles = CONFIG_FILE_NAMES.map((name) =>
87
- dir ? path.resolve(dir, name) : name,
84
+ dir ? path.resolve(dir, name) : name
88
85
  ).filter(fs.existsSync);
89
86
  if (existingConfigFiles.length > 1) {
90
87
  throw new Error(`
@@ -96,10 +93,10 @@ export function findConfig(dir?: string): string | undefined {
96
93
  return existingConfigFiles[0];
97
94
  }
98
95
 
99
- export async function getConfig(configPath: string | undefined = findConfig()) {
100
- if (!configPath) return {};
96
+ export async function getConfig(configPath: string | undefined = findConfig()): Promise<RawConfig> {
97
+ if (!configPath || !doesYamlFileExist(configPath)) return {};
101
98
  try {
102
- const rawConfig = ((await loadYaml(configPath)) || {}) as RawConfig;
99
+ const rawConfig = (await loadYaml<RawConfig & DeprecatedInRawConfig>(configPath)) || {};
103
100
  return transformConfig(rawConfig);
104
101
  } catch (e) {
105
102
  throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
@@ -1,4 +1,4 @@
1
- import type { PluginLintConfig } from './types';
1
+ import type { PluginStyleguideConfig } from './types';
2
2
 
3
3
  export default {
4
4
  rules: {
@@ -18,7 +18,7 @@ export default {
18
18
  'operation-description': 'off',
19
19
  'operation-2xx-response': 'warn',
20
20
  'operation-4xx-response': 'off',
21
- 'assertions': 'warn',
21
+ assertions: 'warn',
22
22
  'operation-operationId': 'warn',
23
23
  'operation-summary': 'warn',
24
24
  'operation-operationId-unique': 'warn',
@@ -55,4 +55,4 @@ export default {
55
55
  'no-undefined-server-variable': 'warn',
56
56
  'no-servers-empty-enum': 'error',
57
57
  },
58
- } as PluginLintConfig;
58
+ } as PluginStyleguideConfig;
@@ -1,4 +1,4 @@
1
- import type { PluginLintConfig } from './types';
1
+ import type { PluginStyleguideConfig } from './types';
2
2
 
3
3
  export default {
4
4
  rules: {
@@ -17,7 +17,7 @@ export default {
17
17
  'path-parameters-defined': 'error',
18
18
  'operation-description': 'off',
19
19
  'operation-2xx-response': 'warn',
20
- 'assertions': 'warn',
20
+ assertions: 'warn',
21
21
  'operation-4xx-response': 'warn',
22
22
  'operation-operationId': 'warn',
23
23
  'operation-summary': 'error',
@@ -55,4 +55,4 @@ export default {
55
55
  'no-undefined-server-variable': 'error',
56
56
  'no-servers-empty-enum': 'error',
57
57
  },
58
- } as PluginLintConfig;
58
+ } as PluginStyleguideConfig;
@@ -1,12 +1,12 @@
1
1
  import { RuleSet, OasVersion } from '../oas-types';
2
- import { LintConfig } from './config';
2
+ import { StyleguideConfig } from './config';
3
3
  import { notUndefined } from '../utils';
4
4
 
5
5
  export function initRules<T extends Function, P extends RuleSet<T>>(
6
6
  rules: P[],
7
- config: LintConfig,
7
+ config: StyleguideConfig,
8
8
  type: 'rules' | 'preprocessors' | 'decorators',
9
- oasVersion: OasVersion,
9
+ oasVersion: OasVersion
10
10
  ) {
11
11
  return rules
12
12
  .flatMap((ruleset) =>
@@ -31,7 +31,7 @@ export function initRules<T extends Function, P extends RuleSet<T>>(
31
31
  severity: ruleSettings.severity,
32
32
  ruleId,
33
33
  visitor: visitor,
34
- }))
34
+ }));
35
35
  }
36
36
 
37
37
  return {
@@ -39,8 +39,8 @@ export function initRules<T extends Function, P extends RuleSet<T>>(
39
39
  ruleId,
40
40
  visitor: visitors, // note: actually it is only one visitor object
41
41
  };
42
- }),
42
+ })
43
43
  )
44
- .flatMap(visitor => visitor)
44
+ .flatMap((visitor) => visitor)
45
45
  .filter(notUndefined);
46
46
  }