@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.
- package/lib/config/all.js +0 -1
- package/lib/config/config-resolvers.js +42 -34
- package/lib/config/load.d.ts +1 -1
- package/lib/config/load.js +5 -5
- package/lib/config/minimal.js +0 -1
- package/lib/config/recommended.js +0 -1
- package/lib/rules/common/assertions/asserts.d.ts +22 -5
- package/lib/rules/common/assertions/asserts.js +25 -0
- package/lib/rules/common/assertions/index.d.ts +27 -2
- package/lib/rules/common/assertions/index.js +6 -29
- package/lib/rules/common/assertions/utils.d.ts +7 -14
- package/lib/rules/common/assertions/utils.js +129 -97
- package/lib/rules/common/no-ambiguous-paths.js +1 -1
- package/lib/rules/common/no-identical-paths.js +4 -4
- package/lib/rules/common/operation-2xx-response.js +2 -2
- package/lib/rules/common/operation-4xx-response.js +2 -2
- package/lib/rules/common/path-not-include-query.js +1 -1
- package/lib/rules/common/path-params-defined.js +7 -2
- package/lib/rules/common/response-contains-header.js +2 -2
- package/lib/rules/common/security-defined.js +10 -5
- package/lib/rules/common/spec.js +14 -12
- package/lib/rules/oas2/index.d.ts +0 -1
- package/lib/rules/oas2/index.js +0 -2
- package/lib/rules/oas3/index.js +0 -2
- package/lib/rules/oas3/request-mime-type.js +1 -1
- package/lib/rules/oas3/response-mime-type.js +1 -1
- package/lib/rules/other/stats.d.ts +1 -1
- package/lib/rules/other/stats.js +1 -1
- package/lib/rules/utils.d.ts +1 -0
- package/lib/rules/utils.js +17 -1
- package/lib/types/oas2.js +6 -6
- package/lib/types/oas3.js +11 -11
- package/lib/types/oas3_1.js +3 -3
- package/lib/types/redocly-yaml.js +58 -31
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +19 -1
- package/lib/visitors.d.ts +9 -7
- package/lib/visitors.js +12 -3
- package/lib/walk.js +7 -1
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
- package/src/__tests__/lint.test.ts +24 -5
- package/src/__tests__/utils.test.ts +11 -0
- package/src/__tests__/walk.test.ts +2 -2
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -3
- package/src/config/__tests__/config-resolvers.test.ts +30 -5
- package/src/config/__tests__/fixtures/load-redocly.yaml +4 -0
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +6 -4
- package/src/config/__tests__/load.test.ts +4 -1
- package/src/config/all.ts +0 -1
- package/src/config/config-resolvers.ts +44 -20
- package/src/config/load.ts +8 -5
- package/src/config/minimal.ts +0 -1
- package/src/config/recommended.ts +0 -1
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +37 -0
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +37 -0
- package/src/rules/common/__tests__/path-params-defined.test.ts +69 -0
- package/src/rules/common/__tests__/security-defined.test.ts +6 -6
- package/src/rules/common/__tests__/spec.test.ts +125 -0
- package/src/rules/common/assertions/__tests__/asserts.test.ts +7 -3
- package/src/rules/common/assertions/__tests__/index.test.ts +41 -20
- package/src/rules/common/assertions/__tests__/utils.test.ts +44 -18
- package/src/rules/common/assertions/asserts.ts +60 -8
- package/src/rules/common/assertions/index.ts +36 -46
- package/src/rules/common/assertions/utils.ts +204 -127
- package/src/rules/common/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-identical-paths.ts +4 -4
- package/src/rules/common/operation-2xx-response.ts +2 -2
- package/src/rules/common/operation-4xx-response.ts +2 -2
- package/src/rules/common/path-not-include-query.ts +1 -1
- package/src/rules/common/path-params-defined.ts +9 -2
- package/src/rules/common/response-contains-header.ts +6 -1
- package/src/rules/common/security-defined.ts +10 -5
- package/src/rules/common/spec.ts +15 -11
- package/src/rules/oas2/index.ts +0 -2
- package/src/rules/oas3/__tests__/response-contains-header.test.ts +116 -0
- package/src/rules/oas3/index.ts +0 -2
- package/src/rules/oas3/request-mime-type.ts +1 -1
- package/src/rules/oas3/response-mime-type.ts +1 -1
- package/src/rules/other/stats.ts +1 -1
- package/src/rules/utils.ts +22 -0
- package/src/types/oas2.ts +6 -6
- package/src/types/oas3.ts +11 -11
- package/src/types/oas3_1.ts +3 -3
- package/src/types/redocly-yaml.ts +58 -33
- package/src/utils.ts +18 -0
- package/src/visitors.ts +32 -11
- package/src/walk.ts +8 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/common/info-description.d.ts +0 -2
- package/lib/rules/common/info-description.js +0 -12
- package/src/rules/common/__tests__/info-description.test.ts +0 -102
- package/src/rules/common/info-description.ts +0 -10
package/lib/config/all.js
CHANGED
|
@@ -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
|
|
29
|
+
const utils_2 = require("./utils");
|
|
29
30
|
const env_1 = require("../env");
|
|
30
|
-
const
|
|
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(
|
|
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(
|
|
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 &&
|
|
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 (
|
|
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 (
|
|
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 =
|
|
108
|
+
plugin.rules.oas3 = utils_2.prefixRules(pluginModule.rules.oas3, id);
|
|
108
109
|
}
|
|
109
110
|
if (pluginModule.rules.oas2) {
|
|
110
|
-
plugin.rules.oas2 =
|
|
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 =
|
|
120
|
+
plugin.preprocessors.oas3 = utils_2.prefixRules(pluginModule.preprocessors.oas3, id);
|
|
120
121
|
}
|
|
121
122
|
if (pluginModule.preprocessors.oas2) {
|
|
122
|
-
plugin.preprocessors.oas2 =
|
|
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 =
|
|
132
|
+
plugin.decorators.oas3 = utils_2.prefixRules(pluginModule.decorators.oas3, id);
|
|
132
133
|
}
|
|
133
134
|
if (pluginModule.decorators.oas2) {
|
|
134
|
-
plugin.decorators.oas2 =
|
|
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(
|
|
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(
|
|
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 =
|
|
173
|
-
const pluginPaths = (_a = styleguideConfig === null || styleguideConfig === void 0 ? void 0 : styleguideConfig.plugins) === null || _a === void 0 ? void 0 : _a.filter(
|
|
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 =
|
|
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:
|
|
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 } =
|
|
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 =
|
|
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
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
+
}
|
package/lib/config/load.d.ts
CHANGED
|
@@ -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[];
|
package/lib/config/load.js
CHANGED
|
@@ -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) {
|
package/lib/config/minimal.js
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import { AssertResult, CustomFunction } from 'core/src/config/types';
|
|
2
2
|
import { Location } from '../../../ref-utils';
|
|
3
|
-
declare type
|
|
4
|
-
export declare
|
|
5
|
-
|
|
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):
|
|
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 {
|
|
2
|
-
|
|
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}: '
|
|
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
|
|
2
|
-
import {
|
|
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:
|
|
10
|
+
name: keyof Asserts;
|
|
18
11
|
conditions: any;
|
|
19
12
|
runsOnKeys: boolean;
|
|
20
13
|
runsOnValues: boolean;
|
|
21
14
|
};
|
|
22
|
-
export declare function
|
|
23
|
-
export declare function
|
|
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 {};
|