@redocly/openapi-core 1.0.0-beta.110 → 1.0.0-beta.112

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 (93) hide show
  1. package/lib/config/all.js +0 -1
  2. package/lib/config/config-resolvers.js +42 -34
  3. package/lib/config/load.d.ts +1 -1
  4. package/lib/config/load.js +5 -5
  5. package/lib/config/minimal.js +0 -1
  6. package/lib/config/recommended.js +0 -1
  7. package/lib/rules/common/assertions/asserts.d.ts +22 -5
  8. package/lib/rules/common/assertions/asserts.js +25 -0
  9. package/lib/rules/common/assertions/index.d.ts +27 -2
  10. package/lib/rules/common/assertions/index.js +6 -29
  11. package/lib/rules/common/assertions/utils.d.ts +7 -14
  12. package/lib/rules/common/assertions/utils.js +129 -97
  13. package/lib/rules/common/no-ambiguous-paths.js +1 -1
  14. package/lib/rules/common/no-identical-paths.js +4 -4
  15. package/lib/rules/common/operation-2xx-response.js +2 -2
  16. package/lib/rules/common/operation-4xx-response.js +2 -2
  17. package/lib/rules/common/path-not-include-query.js +1 -1
  18. package/lib/rules/common/path-params-defined.js +7 -2
  19. package/lib/rules/common/response-contains-header.js +2 -2
  20. package/lib/rules/common/security-defined.js +10 -5
  21. package/lib/rules/common/spec.js +14 -12
  22. package/lib/rules/oas2/index.d.ts +0 -1
  23. package/lib/rules/oas2/index.js +0 -2
  24. package/lib/rules/oas3/index.js +0 -2
  25. package/lib/rules/oas3/request-mime-type.js +1 -1
  26. package/lib/rules/oas3/response-mime-type.js +1 -1
  27. package/lib/rules/other/stats.d.ts +1 -1
  28. package/lib/rules/other/stats.js +1 -1
  29. package/lib/rules/utils.d.ts +1 -0
  30. package/lib/rules/utils.js +17 -1
  31. package/lib/types/oas2.js +6 -6
  32. package/lib/types/oas3.js +11 -11
  33. package/lib/types/oas3_1.js +3 -3
  34. package/lib/types/redocly-yaml.js +58 -31
  35. package/lib/utils.d.ts +2 -0
  36. package/lib/utils.js +19 -1
  37. package/lib/visitors.d.ts +9 -7
  38. package/lib/visitors.js +12 -3
  39. package/lib/walk.js +7 -1
  40. package/package.json +1 -1
  41. package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
  42. package/src/__tests__/lint.test.ts +24 -5
  43. package/src/__tests__/utils.test.ts +11 -0
  44. package/src/__tests__/walk.test.ts +2 -2
  45. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -3
  46. package/src/config/__tests__/config-resolvers.test.ts +30 -5
  47. package/src/config/__tests__/fixtures/load-redocly.yaml +4 -0
  48. package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +6 -4
  49. package/src/config/__tests__/load.test.ts +4 -1
  50. package/src/config/all.ts +0 -1
  51. package/src/config/config-resolvers.ts +44 -20
  52. package/src/config/load.ts +8 -5
  53. package/src/config/minimal.ts +0 -1
  54. package/src/config/recommended.ts +0 -1
  55. package/src/rules/common/__tests__/operation-2xx-response.test.ts +37 -0
  56. package/src/rules/common/__tests__/operation-4xx-response.test.ts +37 -0
  57. package/src/rules/common/__tests__/path-params-defined.test.ts +69 -0
  58. package/src/rules/common/__tests__/security-defined.test.ts +6 -6
  59. package/src/rules/common/__tests__/spec.test.ts +125 -0
  60. package/src/rules/common/assertions/__tests__/asserts.test.ts +7 -3
  61. package/src/rules/common/assertions/__tests__/index.test.ts +41 -20
  62. package/src/rules/common/assertions/__tests__/utils.test.ts +44 -18
  63. package/src/rules/common/assertions/asserts.ts +60 -8
  64. package/src/rules/common/assertions/index.ts +36 -46
  65. package/src/rules/common/assertions/utils.ts +204 -127
  66. package/src/rules/common/no-ambiguous-paths.ts +1 -1
  67. package/src/rules/common/no-identical-paths.ts +4 -4
  68. package/src/rules/common/operation-2xx-response.ts +2 -2
  69. package/src/rules/common/operation-4xx-response.ts +2 -2
  70. package/src/rules/common/path-not-include-query.ts +1 -1
  71. package/src/rules/common/path-params-defined.ts +9 -2
  72. package/src/rules/common/response-contains-header.ts +6 -1
  73. package/src/rules/common/security-defined.ts +10 -5
  74. package/src/rules/common/spec.ts +15 -11
  75. package/src/rules/oas2/index.ts +0 -2
  76. package/src/rules/oas3/__tests__/response-contains-header.test.ts +116 -0
  77. package/src/rules/oas3/index.ts +0 -2
  78. package/src/rules/oas3/request-mime-type.ts +1 -1
  79. package/src/rules/oas3/response-mime-type.ts +1 -1
  80. package/src/rules/other/stats.ts +1 -1
  81. package/src/rules/utils.ts +22 -0
  82. package/src/types/oas2.ts +6 -6
  83. package/src/types/oas3.ts +11 -11
  84. package/src/types/oas3_1.ts +3 -3
  85. package/src/types/redocly-yaml.ts +58 -33
  86. package/src/utils.ts +18 -0
  87. package/src/visitors.ts +32 -11
  88. package/src/walk.ts +8 -1
  89. package/tsconfig.tsbuildinfo +1 -1
  90. package/lib/rules/common/info-description.d.ts +0 -2
  91. package/lib/rules/common/info-description.js +0 -12
  92. package/src/rules/common/__tests__/info-description.test.ts +0 -102
  93. package/src/rules/common/info-description.ts +0 -10
package/lib/config/all.js CHANGED
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = {
4
4
  rules: {
5
- 'info-description': 'error',
6
5
  'info-contact': 'error',
7
6
  'info-license': 'error',
8
7
  'info-license-url': 'error',
@@ -23,21 +23,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
23
23
  exports.resolvePreset = exports.resolveStyleguideConfig = exports.resolveApis = exports.resolvePlugins = exports.resolveConfig = void 0;
24
24
  const path = require("path");
25
25
  const ref_utils_1 = require("../ref-utils");
26
+ const utils_1 = require("../utils");
26
27
  const resolve_1 = require("../resolve");
27
28
  const builtIn_1 = require("./builtIn");
28
- const utils_1 = require("./utils");
29
+ const utils_2 = require("./utils");
29
30
  const env_1 = require("../env");
30
- const utils_2 = require("../utils");
31
+ const utils_3 = require("../utils");
31
32
  const config_1 = require("./config");
32
33
  const logger_1 = require("../logger");
33
34
  const asserts_1 = require("../rules/common/assertions/asserts");
34
35
  function resolveConfig(rawConfig, configPath) {
35
36
  var _a, _b, _c, _d, _e;
36
37
  return __awaiter(this, void 0, void 0, function* () {
37
- if ((_b = (_a = rawConfig.styleguide) === null || _a === void 0 ? void 0 : _a.extends) === null || _b === void 0 ? void 0 : _b.some(utils_2.isNotString)) {
38
+ if ((_b = (_a = rawConfig.styleguide) === null || _a === void 0 ? void 0 : _a.extends) === null || _b === void 0 ? void 0 : _b.some(utils_3.isNotString)) {
38
39
  throw new Error(`Error configuration format not detected in extends value must contain strings`);
39
40
  }
40
- const resolver = new resolve_1.BaseResolver(utils_1.getResolveConfig(rawConfig.resolve));
41
+ const resolver = new resolve_1.BaseResolver(utils_2.getResolveConfig(rawConfig.resolve));
41
42
  const configExtends = (_d = (_c = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.styleguide) === null || _c === void 0 ? void 0 : _c.extends) !== null && _d !== void 0 ? _d : ['recommended'];
42
43
  const recommendedFallback = !((_e = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.styleguide) === null || _e === void 0 ? void 0 : _e.extends);
43
44
  const styleguideConfig = Object.assign(Object.assign({}, rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.styleguide), { extends: configExtends, recommendedFallback });
@@ -61,11 +62,11 @@ function resolvePlugins(plugins, configPath = '') {
61
62
  return [];
62
63
  // TODO: implement or reuse Resolver approach so it will work in node and browser envs
63
64
  const requireFunc = (plugin) => {
64
- if (env_1.isBrowser && utils_2.isString(plugin)) {
65
+ if (env_1.isBrowser && utils_3.isString(plugin)) {
65
66
  logger_1.logger.error(`Cannot load ${plugin}. Plugins aren't supported in browser yet.`);
66
67
  return undefined;
67
68
  }
68
- if (utils_2.isString(plugin)) {
69
+ if (utils_3.isString(plugin)) {
69
70
  const absoltePluginPath = path.resolve(path.dirname(configPath), plugin);
70
71
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
71
72
  // @ts-ignore
@@ -80,7 +81,7 @@ function resolvePlugins(plugins, configPath = '') {
80
81
  const seenPluginIds = new Map();
81
82
  return plugins
82
83
  .map((p) => {
83
- if (utils_2.isString(p) && ref_utils_1.isAbsoluteUrl(p)) {
84
+ if (utils_3.isString(p) && ref_utils_1.isAbsoluteUrl(p)) {
84
85
  throw new Error(logger_1.colorize.red(`We don't support remote plugins yet.`));
85
86
  }
86
87
  // TODO: resolve npm packages similar to eslint
@@ -104,10 +105,10 @@ function resolvePlugins(plugins, configPath = '') {
104
105
  }
105
106
  plugin.rules = {};
106
107
  if (pluginModule.rules.oas3) {
107
- plugin.rules.oas3 = utils_1.prefixRules(pluginModule.rules.oas3, id);
108
+ plugin.rules.oas3 = utils_2.prefixRules(pluginModule.rules.oas3, id);
108
109
  }
109
110
  if (pluginModule.rules.oas2) {
110
- plugin.rules.oas2 = utils_1.prefixRules(pluginModule.rules.oas2, id);
111
+ plugin.rules.oas2 = utils_2.prefixRules(pluginModule.rules.oas2, id);
111
112
  }
112
113
  }
113
114
  if (pluginModule.preprocessors) {
@@ -116,10 +117,10 @@ function resolvePlugins(plugins, configPath = '') {
116
117
  }
117
118
  plugin.preprocessors = {};
118
119
  if (pluginModule.preprocessors.oas3) {
119
- plugin.preprocessors.oas3 = utils_1.prefixRules(pluginModule.preprocessors.oas3, id);
120
+ plugin.preprocessors.oas3 = utils_2.prefixRules(pluginModule.preprocessors.oas3, id);
120
121
  }
121
122
  if (pluginModule.preprocessors.oas2) {
122
- plugin.preprocessors.oas2 = utils_1.prefixRules(pluginModule.preprocessors.oas2, id);
123
+ plugin.preprocessors.oas2 = utils_2.prefixRules(pluginModule.preprocessors.oas2, id);
123
124
  }
124
125
  }
125
126
  if (pluginModule.decorators) {
@@ -128,10 +129,10 @@ function resolvePlugins(plugins, configPath = '') {
128
129
  }
129
130
  plugin.decorators = {};
130
131
  if (pluginModule.decorators.oas3) {
131
- plugin.decorators.oas3 = utils_1.prefixRules(pluginModule.decorators.oas3, id);
132
+ plugin.decorators.oas3 = utils_2.prefixRules(pluginModule.decorators.oas3, id);
132
133
  }
133
134
  if (pluginModule.decorators.oas2) {
134
- plugin.decorators.oas2 = utils_1.prefixRules(pluginModule.decorators.oas2, id);
135
+ plugin.decorators.oas2 = utils_2.prefixRules(pluginModule.decorators.oas2, id);
135
136
  }
136
137
  }
137
138
  if (pluginModule.assertions) {
@@ -139,7 +140,7 @@ function resolvePlugins(plugins, configPath = '') {
139
140
  }
140
141
  return plugin;
141
142
  })
142
- .filter(utils_2.isDefined);
143
+ .filter(utils_3.isDefined);
143
144
  }
144
145
  exports.resolvePlugins = resolvePlugins;
145
146
  function resolveApis({ rawConfig, configPath = '', resolver, }) {
@@ -148,7 +149,7 @@ function resolveApis({ rawConfig, configPath = '', resolver, }) {
148
149
  const { apis = {}, styleguide: styleguideConfig = {} } = rawConfig;
149
150
  const resolvedApis = {};
150
151
  for (const [apiName, apiContent] of Object.entries(apis || {})) {
151
- if ((_b = (_a = apiContent.styleguide) === null || _a === void 0 ? void 0 : _a.extends) === null || _b === void 0 ? void 0 : _b.some(utils_2.isNotString)) {
152
+ if ((_b = (_a = apiContent.styleguide) === null || _a === void 0 ? void 0 : _a.extends) === null || _b === void 0 ? void 0 : _b.some(utils_3.isNotString)) {
152
153
  throw new Error(`Error configuration format not detected in extends value must contain strings`);
153
154
  }
154
155
  const rawStyleguideConfig = getMergedRawStyleguideConfig(styleguideConfig, apiContent.styleguide);
@@ -169,8 +170,8 @@ function resolveAndMergeNestedStyleguideConfig({ styleguideConfig, configPath =
169
170
  if (parentConfigPaths.includes(configPath)) {
170
171
  throw new Error(`Circular dependency in config file: "${configPath}"`);
171
172
  }
172
- const plugins = utils_1.getUniquePlugins(resolvePlugins([...((styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.plugins) || []), builtIn_1.defaultPlugin], configPath));
173
- const pluginPaths = (_a = styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.plugins) === null || _a === void 0 ? void 0 : _a.filter(utils_2.isString).map((p) => path.resolve(path.dirname(configPath), p));
173
+ const plugins = utils_2.getUniquePlugins(resolvePlugins([...((styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.plugins) || []), builtIn_1.defaultPlugin], configPath));
174
+ const pluginPaths = (_a = styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.plugins) === null || _a === void 0 ? void 0 : _a.filter(utils_3.isString).map((p) => path.resolve(path.dirname(configPath), p));
174
175
  const resolvedConfigPath = ref_utils_1.isAbsoluteUrl(configPath)
175
176
  ? configPath
176
177
  : configPath && path.resolve(configPath);
@@ -190,11 +191,11 @@ function resolveAndMergeNestedStyleguideConfig({ styleguideConfig, configPath =
190
191
  resolver: resolver,
191
192
  }, [...parentConfigPaths, resolvedConfigPath], extendPaths);
192
193
  }))) || []);
193
- const _d = utils_1.mergeExtends([
194
+ const _d = utils_2.mergeExtends([
194
195
  ...extendConfigs,
195
196
  Object.assign(Object.assign({}, styleguideConfig), { plugins, extends: undefined, extendPaths: [...parentConfigPaths, resolvedConfigPath], pluginPaths }),
196
197
  ]), { plugins: mergedPlugins = [] } = _d, styleguide = __rest(_d, ["plugins"]);
197
- return Object.assign(Object.assign({}, styleguide), { extendPaths: (_c = styleguide.extendPaths) === null || _c === void 0 ? void 0 : _c.filter((path) => path && !ref_utils_1.isAbsoluteUrl(path)), plugins: utils_1.getUniquePlugins(mergedPlugins), recommendedFallback: styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.recommendedFallback, doNotResolveExamples: styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.doNotResolveExamples });
198
+ return Object.assign(Object.assign({}, styleguide), { extendPaths: (_c = styleguide.extendPaths) === null || _c === void 0 ? void 0 : _c.filter((path) => path && !ref_utils_1.isAbsoluteUrl(path)), plugins: utils_2.getUniquePlugins(mergedPlugins), recommendedFallback: styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.recommendedFallback, doNotResolveExamples: styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.doNotResolveExamples });
198
199
  });
199
200
  }
200
201
  function resolveStyleguideConfig(opts, parentConfigPaths = [], extendPaths = []) {
@@ -206,7 +207,7 @@ function resolveStyleguideConfig(opts, parentConfigPaths = [], extendPaths = [])
206
207
  exports.resolveStyleguideConfig = resolveStyleguideConfig;
207
208
  function resolvePreset(presetName, plugins) {
208
209
  var _a;
209
- const { pluginId, configName } = utils_1.parsePresetName(presetName);
210
+ const { pluginId, configName } = utils_2.parsePresetName(presetName);
210
211
  const plugin = plugins.find((p) => p.id === pluginId);
211
212
  if (!plugin) {
212
213
  throw new Error(`Invalid config ${logger_1.colorize.red(presetName)}: plugin ${pluginId} is not included.`);
@@ -224,7 +225,7 @@ function loadExtendStyleguideConfig(filePath, resolver) {
224
225
  return __awaiter(this, void 0, void 0, function* () {
225
226
  try {
226
227
  const fileSource = yield resolver.loadExternalRef(filePath);
227
- const rawConfig = utils_1.transformConfig(utils_2.parseYaml(fileSource.body));
228
+ const rawConfig = utils_2.transformConfig(utils_3.parseYaml(fileSource.body));
228
229
  if (!rawConfig.styleguide) {
229
230
  throw new Error(`Styleguide configuration format not detected: "${filePath}"`);
230
231
  }
@@ -236,7 +237,7 @@ function loadExtendStyleguideConfig(filePath, resolver) {
236
237
  });
237
238
  }
238
239
  function getMergedRawStyleguideConfig(rootStyleguideConfig, apiStyleguideConfig) {
239
- const resultLint = Object.assign(Object.assign(Object.assign({}, rootStyleguideConfig), apiStyleguideConfig), { rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.rules), oas2Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Rules), oas3_0Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Rules), oas3_1Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Rules), preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.preprocessors), oas2Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Preprocessors), oas3_0Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Preprocessors), oas3_1Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Preprocessors), decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.decorators), oas2Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Decorators), oas3_0Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Decorators), oas3_1Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Decorators), recommendedFallback: (apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.extends)
240
+ const resultLint = Object.assign(Object.assign(Object.assign({}, rootStyleguideConfig), utils_1.pickDefined(apiStyleguideConfig)), { rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.rules), oas2Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Rules), oas3_0Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Rules), oas3_1Rules: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Rules), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Rules), preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.preprocessors), oas2Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Preprocessors), oas3_0Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Preprocessors), oas3_1Preprocessors: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Preprocessors), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Preprocessors), decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.decorators), oas2Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas2Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas2Decorators), oas3_0Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_0Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_0Decorators), oas3_1Decorators: Object.assign(Object.assign({}, rootStyleguideConfig === null || rootStyleguideConfig === void 0 ? void 0 : rootStyleguideConfig.oas3_1Decorators), apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.oas3_1Decorators), recommendedFallback: (apiStyleguideConfig === null || apiStyleguideConfig === void 0 ? void 0 : apiStyleguideConfig.extends)
240
241
  ? false
241
242
  : rootStyleguideConfig.recommendedFallback });
242
243
  return resultLint;
@@ -253,18 +254,10 @@ function groupStyleguideAssertionRules({ rules, plugins, }) {
253
254
  if (ruleKey.startsWith('assert/') && typeof rule === 'object' && rule !== null) {
254
255
  const assertion = rule;
255
256
  if (plugins) {
256
- for (const field of Object.keys(assertion)) {
257
- const [pluginId, fn] = field.split('/');
258
- if (!pluginId || !fn)
259
- continue;
260
- const plugin = plugins.find((plugin) => plugin.id === pluginId);
261
- if (!plugin) {
262
- throw Error(logger_1.colorize.red(`Plugin ${logger_1.colorize.blue(pluginId)} isn't found.`));
263
- }
264
- if (!plugin.assertions || !plugin.assertions[fn]) {
265
- throw Error(`Plugin ${logger_1.colorize.red(pluginId)} doesn't export assertions function with name ${logger_1.colorize.red(fn)}.`);
266
- }
267
- asserts_1.asserts[field] = asserts_1.buildAssertCustomFunction(plugin.assertions[fn]);
257
+ registerCustomAssertions(plugins, assertion);
258
+ // We may have custom assertion inside where block
259
+ for (const context of assertion.where || []) {
260
+ registerCustomAssertions(plugins, context);
268
261
  }
269
262
  }
270
263
  assertions.push(Object.assign(Object.assign({}, assertion), { assertionId: ruleKey.replace('assert/', '') }));
@@ -279,3 +272,18 @@ function groupStyleguideAssertionRules({ rules, plugins, }) {
279
272
  }
280
273
  return transformedRules;
281
274
  }
275
+ function registerCustomAssertions(plugins, assertion) {
276
+ for (const field of utils_3.keysOf(assertion.assertions)) {
277
+ const [pluginId, fn] = field.split('/');
278
+ if (!pluginId || !fn)
279
+ continue;
280
+ const plugin = plugins.find((plugin) => plugin.id === pluginId);
281
+ if (!plugin) {
282
+ throw Error(logger_1.colorize.red(`Plugin ${logger_1.colorize.blue(pluginId)} isn't found.`));
283
+ }
284
+ if (!plugin.assertions || !plugin.assertions[fn]) {
285
+ throw Error(`Plugin ${logger_1.colorize.red(pluginId)} doesn't export assertions function with name ${logger_1.colorize.red(fn)}.`);
286
+ }
287
+ asserts_1.asserts[field] = asserts_1.buildAssertCustomFunction(plugin.assertions[fn]);
288
+ }
289
+ }
@@ -10,7 +10,7 @@ export declare function loadConfig(options?: {
10
10
  }): Promise<Config>;
11
11
  export declare const CONFIG_FILE_NAMES: string[];
12
12
  export declare function findConfig(dir?: string): string | undefined;
13
- export declare function getConfig(configPath?: string | undefined): Promise<RawConfig>;
13
+ export declare function getConfig(configPath?: string | undefined, processRawConfig?: (rawConfig: RawConfig) => void | Promise<void>): Promise<RawConfig>;
14
14
  declare type CreateConfigOptions = {
15
15
  extends?: string[];
16
16
  tokens?: RegionalTokenWithValidity[];
@@ -62,11 +62,8 @@ function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, }) {
62
62
  function loadConfig(options = {}) {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
64
  const { configPath = findConfig(), customExtends, processRawConfig, files, region } = options;
65
- const config = yield getConfig(configPath);
65
+ const config = yield getConfig(configPath, processRawConfig);
66
66
  const rawConfig = Object.assign(Object.assign({}, config), { files: files !== null && files !== void 0 ? files : config.files, region: region !== null && region !== void 0 ? region : config.region });
67
- if (typeof processRawConfig === 'function') {
68
- yield processRawConfig(rawConfig);
69
- }
70
67
  const redoclyClient = new redocly_1.RedoclyClient();
71
68
  const tokens = yield redoclyClient.getTokens();
72
69
  return addConfigMetadata({
@@ -93,12 +90,15 @@ function findConfig(dir) {
93
90
  return existingConfigFiles[0];
94
91
  }
95
92
  exports.findConfig = findConfig;
96
- function getConfig(configPath = findConfig()) {
93
+ function getConfig(configPath = findConfig(), processRawConfig) {
97
94
  return __awaiter(this, void 0, void 0, function* () {
98
95
  if (!configPath || !utils_1.doesYamlFileExist(configPath))
99
96
  return {};
100
97
  try {
101
98
  const rawConfig = (yield utils_1.loadYaml(configPath)) || {};
99
+ if (typeof processRawConfig === 'function') {
100
+ yield processRawConfig(rawConfig);
101
+ }
102
102
  return utils_2.transformConfig(rawConfig);
103
103
  }
104
104
  catch (e) {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = {
4
4
  rules: {
5
- 'info-description': 'warn',
6
5
  'info-contact': 'off',
7
6
  'info-license': 'off',
8
7
  'info-license-url': 'off',
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = {
4
4
  rules: {
5
- 'info-description': 'warn',
6
5
  'info-contact': 'off',
7
6
  'info-license': 'warn',
8
7
  'info-license-url': 'warn',
@@ -1,8 +1,25 @@
1
1
  import { AssertResult, CustomFunction } from 'core/src/config/types';
2
2
  import { Location } from '../../../ref-utils';
3
- declare type Asserts = Record<string, (value: any, condition: any, baseLocation: Location, rawValue?: any) => AssertResult[]>;
4
- export declare const runOnKeysSet: Set<string>;
5
- export declare const runOnValuesSet: Set<string>;
3
+ export declare type AssertionFn = (value: any, condition: any, baseLocation: Location, rawValue?: any) => AssertResult[];
4
+ export declare type Asserts = {
5
+ pattern: AssertionFn;
6
+ enum: AssertionFn;
7
+ defined: AssertionFn;
8
+ required: AssertionFn;
9
+ disallowed: AssertionFn;
10
+ undefined: AssertionFn;
11
+ nonEmpty: AssertionFn;
12
+ minLength: AssertionFn;
13
+ maxLength: AssertionFn;
14
+ casing: AssertionFn;
15
+ sortOrder: AssertionFn;
16
+ mutuallyExclusive: AssertionFn;
17
+ mutuallyRequired: AssertionFn;
18
+ requireAny: AssertionFn;
19
+ ref: AssertionFn;
20
+ const: AssertionFn;
21
+ };
22
+ export declare const runOnKeysSet: Set<keyof Asserts>;
23
+ export declare const runOnValuesSet: Set<keyof Asserts>;
6
24
  export declare const asserts: Asserts;
7
- export declare function buildAssertCustomFunction(fn: CustomFunction): (value: string[], options: any, baseLocation: Location) => any;
8
- export {};
25
+ export declare function buildAssertCustomFunction(fn: CustomFunction): AssertionFn;
@@ -16,6 +16,8 @@ exports.runOnKeysSet = new Set([
16
16
  'required',
17
17
  'requireAny',
18
18
  'ref',
19
+ 'const',
20
+ 'defined', // In case if `property` for assertions is not added
19
21
  ]);
20
22
  exports.runOnValuesSet = new Set([
21
23
  'pattern',
@@ -28,6 +30,7 @@ exports.runOnValuesSet = new Set([
28
30
  'casing',
29
31
  'sortOrder',
30
32
  'ref',
33
+ 'const',
31
34
  ]);
32
35
  exports.asserts = {
33
36
  pattern: (value, condition, baseLocation) => {
@@ -84,6 +87,28 @@ exports.asserts = {
84
87
  })
85
88
  .filter(utils_1.isTruthy);
86
89
  },
90
+ const: (value, condition, baseLocation) => {
91
+ if (typeof value === 'undefined')
92
+ return [];
93
+ if (Array.isArray(value)) {
94
+ return value
95
+ .map((_val) => condition !== _val && {
96
+ message: `"${_val}" should be equal ${condition} `,
97
+ location: utils_1.isString(value) ? baseLocation : baseLocation.child(_val).key(),
98
+ })
99
+ .filter(utils_1.isTruthy);
100
+ }
101
+ else {
102
+ return value !== condition
103
+ ? [
104
+ {
105
+ message: `${value} should be equal ${condition}`,
106
+ location: baseLocation,
107
+ },
108
+ ]
109
+ : [];
110
+ }
111
+ },
87
112
  undefined: (value, condition = true, baseLocation) => {
88
113
  const isUndefined = typeof value === 'undefined';
89
114
  const isValid = condition ? isUndefined : !isUndefined;
@@ -1,2 +1,27 @@
1
- import { Oas2Rule, Oas3Rule } from '../../../visitors';
2
- export declare const Assertions: Oas3Rule | Oas2Rule;
1
+ import { asserts, AssertionFn } from './asserts';
2
+ import { Oas2Visitor, Oas3Visitor } from '../../../visitors';
3
+ import { RuleSeverity } from '../../../config';
4
+ export declare type AssertionLocators = {
5
+ filterInParentKeys?: (string | number)[];
6
+ filterOutParentKeys?: (string | number)[];
7
+ matchParentKeys?: string;
8
+ };
9
+ export declare type AssertionDefinition = {
10
+ subject: {
11
+ type: string;
12
+ property?: string | string[];
13
+ } & AssertionLocators;
14
+ assertions: {
15
+ [name in keyof typeof asserts]?: AssertionFn;
16
+ };
17
+ };
18
+ export declare type RawAssertion = AssertionDefinition & {
19
+ where?: AssertionDefinition[];
20
+ message?: string;
21
+ suggest?: string[];
22
+ severity?: RuleSeverity;
23
+ };
24
+ export declare type Assertion = RawAssertion & {
25
+ assertionId: string;
26
+ };
27
+ export declare const Assertions: (opts: Record<string, Assertion>) => (Oas3Visitor | Oas2Visitor)[];
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Assertions = void 0;
4
- const asserts_1 = require("./asserts");
5
4
  const utils_1 = require("./utils");
5
+ const utils_2 = require("../../../utils");
6
6
  const Assertions = (opts) => {
7
7
  const visitors = [];
8
8
  // As 'Assertions' has an array of asserts,
@@ -13,35 +13,12 @@ const Assertions = (opts) => {
13
13
  const assertions = Object.values(opts).filter((opt) => typeof opt === 'object' && opt !== null);
14
14
  for (const [index, assertion] of assertions.entries()) {
15
15
  const assertId = (assertion.assertionId && `${assertion.assertionId} assertion`) || `assertion #${index + 1}`;
16
- if (!assertion.subject) {
17
- throw new Error(`${assertId}: 'subject' is required`);
18
- }
19
- const subjects = Array.isArray(assertion.subject)
20
- ? assertion.subject
21
- : [assertion.subject];
22
- const assertsToApply = Object.keys(asserts_1.asserts)
23
- .filter((assertName) => assertion[assertName] !== undefined)
24
- .map((assertName) => {
25
- return {
26
- name: assertName,
27
- conditions: assertion[assertName],
28
- runsOnKeys: asserts_1.runOnKeysSet.has(assertName),
29
- runsOnValues: asserts_1.runOnValuesSet.has(assertName),
30
- };
31
- });
32
- const shouldRunOnKeys = assertsToApply.find((assert) => assert.runsOnKeys && !assert.runsOnValues);
33
- const shouldRunOnValues = assertsToApply.find((assert) => assert.runsOnValues && !assert.runsOnKeys);
34
- if (shouldRunOnValues && !assertion.property) {
35
- throw new Error(`${shouldRunOnValues.name} can't be used on all keys. Please provide a single property.`);
36
- }
37
- if (shouldRunOnKeys && assertion.property) {
38
- throw new Error(`${shouldRunOnKeys.name} can't be used on a single property. Please use 'property'.`);
39
- }
40
- for (const subject of subjects) {
41
- const subjectVisitor = utils_1.buildSubjectVisitor(assertId, assertion, assertsToApply);
42
- const visitorObject = utils_1.buildVisitorObject(subject, assertion.context, subjectVisitor);
43
- visitors.push(visitorObject);
16
+ if (!utils_2.isString(assertion.subject.type)) {
17
+ throw new Error(`${assertId}: 'type' (String) is required`);
44
18
  }
19
+ const subjectVisitor = utils_1.buildSubjectVisitor(assertId, assertion);
20
+ const visitorObject = utils_1.buildVisitorObject(assertion, subjectVisitor);
21
+ visitors.push(visitorObject);
45
22
  }
46
23
  return visitors;
47
24
  };
@@ -1,27 +1,20 @@
1
- import type { RuleSeverity } from '../../../config';
2
- import { UserContext } from '../../../walk';
1
+ import { Asserts } from './asserts';
2
+ import type { Assertion, AssertionDefinition } from '.';
3
+ import type { Oas2Visitor, Oas3Visitor, VisitFunction } from '../../../visitors';
3
4
  export declare type OrderDirection = 'asc' | 'desc';
4
5
  export declare type OrderOptions = {
5
6
  direction: OrderDirection;
6
7
  property: string;
7
8
  };
8
- declare type Assertion = {
9
- property: string | string[];
10
- context?: Record<string, any>[];
11
- severity?: RuleSeverity;
12
- suggest?: any[];
13
- message?: string;
14
- subject: string;
15
- };
16
9
  export declare type AssertToApply = {
17
- name: string;
10
+ name: keyof Asserts;
18
11
  conditions: any;
19
12
  runsOnKeys: boolean;
20
13
  runsOnValues: boolean;
21
14
  };
22
- export declare function buildVisitorObject(subject: string, context: Record<string, any>[], subjectVisitor: any): Record<string, any>;
23
- export declare function buildSubjectVisitor(assertId: string, assertion: Assertion, asserts: AssertToApply[]): (node: any, { report, location, rawLocation, key, type, resolve, rawNode }: UserContext) => void;
15
+ export declare function getAssertsToApply(assertion: AssertionDefinition): AssertToApply[];
16
+ export declare function buildVisitorObject(assertion: Assertion, subjectVisitor: VisitFunction<any>): Oas2Visitor | Oas3Visitor;
17
+ export declare function buildSubjectVisitor(assertId: string, assertion: Assertion): VisitFunction<any>;
24
18
  export declare function getIntersectionLength(keys: string[], properties: string[]): number;
25
19
  export declare function isOrdered(value: any[], options: OrderOptions | OrderDirection): boolean;
26
20
  export declare function regexFromString(input: string): RegExp | null;
27
- export {};