@redocly/openapi-core 1.0.0-beta.111 → 1.0.0-beta.113
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 +22 -18
- package/lib/config/config.d.ts +4 -10
- package/lib/config/config.js +1 -1
- package/lib/config/load.d.ts +1 -1
- package/lib/config/load.js +10 -10
- package/lib/config/minimal.js +0 -1
- package/lib/config/recommended.js +0 -1
- package/lib/config/rules.d.ts +6 -3
- package/lib/config/rules.js +3 -2
- package/lib/config/types.d.ts +3 -0
- package/lib/ref-utils.d.ts +1 -0
- package/lib/ref-utils.js +5 -1
- package/lib/resolve.js +19 -0
- 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/spec.js +6 -0
- 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/utils.js +3 -0
- package/lib/types/oas2.js +11 -7
- package/lib/types/oas3.js +15 -10
- package/lib/types/oas3_1.js +1 -0
- package/lib/types/redocly-yaml.js +49 -27
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +13 -1
- package/lib/visitors.d.ts +2 -1
- package/lib/visitors.js +1 -0
- package/lib/walk.js +7 -1
- package/package.json +1 -1
- package/src/__tests__/bundle.test.ts +46 -0
- package/src/__tests__/lint.test.ts +24 -5
- package/src/benchmark/benches/rebilly.yaml +36 -28
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -3
- package/src/config/__tests__/config-resolvers.test.ts +6 -7
- package/src/config/__tests__/fixtures/load-redocly.yaml +2 -0
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +6 -5
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-wrong-custom-function.yaml +0 -1
- package/src/config/__tests__/load.test.ts +4 -1
- package/src/config/all.ts +0 -1
- package/src/config/config-resolvers.ts +44 -31
- package/src/config/config.ts +6 -5
- package/src/config/load.ts +19 -9
- package/src/config/minimal.ts +0 -1
- package/src/config/recommended.ts +0 -1
- package/src/config/rules.ts +11 -3
- package/src/config/types.ts +2 -0
- package/src/ref-utils.ts +4 -0
- package/src/resolve.ts +25 -3
- package/src/rules/common/__tests__/spec.test.ts +170 -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 +43 -17
- 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/spec.ts +7 -0
- package/src/rules/oas2/index.ts +0 -2
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +32 -0
- package/src/rules/oas3/index.ts +0 -2
- package/src/rules/utils.ts +4 -0
- package/src/types/oas2.ts +11 -7
- package/src/types/oas3.ts +15 -10
- package/src/types/oas3_1.ts +1 -0
- package/src/types/redocly-yaml.ts +49 -29
- package/src/utils.ts +11 -0
- package/src/visitors.ts +7 -1
- 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
|
@@ -33,22 +33,19 @@ const config_1 = require("./config");
|
|
|
33
33
|
const logger_1 = require("../logger");
|
|
34
34
|
const asserts_1 = require("../rules/common/assertions/asserts");
|
|
35
35
|
function resolveConfig(rawConfig, configPath) {
|
|
36
|
-
var _a, _b
|
|
36
|
+
var _a, _b;
|
|
37
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
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)) {
|
|
39
39
|
throw new Error(`Error configuration format not detected in extends value must contain strings`);
|
|
40
40
|
}
|
|
41
41
|
const resolver = new resolve_1.BaseResolver(utils_2.getResolveConfig(rawConfig.resolve));
|
|
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'];
|
|
43
|
-
const recommendedFallback = !((_e = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.styleguide) === null || _e === void 0 ? void 0 : _e.extends);
|
|
44
|
-
const styleguideConfig = Object.assign(Object.assign({}, rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.styleguide), { extends: configExtends, recommendedFallback });
|
|
45
42
|
const apis = yield resolveApis({
|
|
46
|
-
rawConfig
|
|
43
|
+
rawConfig,
|
|
47
44
|
configPath,
|
|
48
45
|
resolver,
|
|
49
46
|
});
|
|
50
47
|
const styleguide = yield resolveStyleguideConfig({
|
|
51
|
-
styleguideConfig,
|
|
48
|
+
styleguideConfig: rawConfig.styleguide,
|
|
52
49
|
configPath,
|
|
53
50
|
resolver,
|
|
54
51
|
});
|
|
@@ -254,18 +251,10 @@ function groupStyleguideAssertionRules({ rules, plugins, }) {
|
|
|
254
251
|
if (ruleKey.startsWith('assert/') && typeof rule === 'object' && rule !== null) {
|
|
255
252
|
const assertion = rule;
|
|
256
253
|
if (plugins) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const plugin = plugins.find((plugin) => plugin.id === pluginId);
|
|
262
|
-
if (!plugin) {
|
|
263
|
-
throw Error(logger_1.colorize.red(`Plugin ${logger_1.colorize.blue(pluginId)} isn't found.`));
|
|
264
|
-
}
|
|
265
|
-
if (!plugin.assertions || !plugin.assertions[fn]) {
|
|
266
|
-
throw Error(`Plugin ${logger_1.colorize.red(pluginId)} doesn't export assertions function with name ${logger_1.colorize.red(fn)}.`);
|
|
267
|
-
}
|
|
268
|
-
asserts_1.asserts[field] = asserts_1.buildAssertCustomFunction(plugin.assertions[fn]);
|
|
254
|
+
registerCustomAssertions(plugins, assertion);
|
|
255
|
+
// We may have custom assertion inside where block
|
|
256
|
+
for (const context of assertion.where || []) {
|
|
257
|
+
registerCustomAssertions(plugins, context);
|
|
269
258
|
}
|
|
270
259
|
}
|
|
271
260
|
assertions.push(Object.assign(Object.assign({}, assertion), { assertionId: ruleKey.replace('assert/', '') }));
|
|
@@ -280,3 +269,18 @@ function groupStyleguideAssertionRules({ rules, plugins, }) {
|
|
|
280
269
|
}
|
|
281
270
|
return transformedRules;
|
|
282
271
|
}
|
|
272
|
+
function registerCustomAssertions(plugins, assertion) {
|
|
273
|
+
for (const field of utils_3.keysOf(assertion.assertions)) {
|
|
274
|
+
const [pluginId, fn] = field.split('/');
|
|
275
|
+
if (!pluginId || !fn)
|
|
276
|
+
continue;
|
|
277
|
+
const plugin = plugins.find((plugin) => plugin.id === pluginId);
|
|
278
|
+
if (!plugin) {
|
|
279
|
+
throw Error(logger_1.colorize.red(`Plugin ${logger_1.colorize.blue(pluginId)} isn't found.`));
|
|
280
|
+
}
|
|
281
|
+
if (!plugin.assertions || !plugin.assertions[fn]) {
|
|
282
|
+
throw Error(`Plugin ${logger_1.colorize.red(pluginId)} doesn't export assertions function with name ${logger_1.colorize.red(fn)}.`);
|
|
283
|
+
}
|
|
284
|
+
asserts_1.asserts[field] = asserts_1.buildAssertCustomFunction(plugin.assertions[fn]);
|
|
285
|
+
}
|
|
286
|
+
}
|
package/lib/config/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NormalizedProblem } from '../walk';
|
|
2
2
|
import { OasVersion, OasMajorVersion, Oas2RuleSet, Oas3RuleSet } from '../oas-types';
|
|
3
3
|
import type { NodeType } from '../types';
|
|
4
|
-
import type { DecoratorConfig, Plugin, PreprocessorConfig, Region, ResolveConfig, ResolvedApi, ResolvedConfig, ResolvedStyleguideConfig, RuleConfig } from './types';
|
|
4
|
+
import type { DecoratorConfig, Plugin, PreprocessorConfig, Region, ResolveConfig, ResolvedApi, ResolvedConfig, ResolvedStyleguideConfig, RuleConfig, RuleSettings } from './types';
|
|
5
5
|
export declare const IGNORE_FILE = ".redocly.lint-ignore.yaml";
|
|
6
6
|
export declare const DEFAULT_REGION = "us";
|
|
7
7
|
export declare const DOMAINS: {
|
|
@@ -29,15 +29,9 @@ export declare class StyleguideConfig {
|
|
|
29
29
|
addIgnore(problem: NormalizedProblem): void;
|
|
30
30
|
addProblemToIgnore(problem: NormalizedProblem): NormalizedProblem;
|
|
31
31
|
extendTypes(types: Record<string, NodeType>, version: OasVersion): Record<string, NodeType>;
|
|
32
|
-
getRuleSettings(ruleId: string, oasVersion: OasVersion):
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
getPreprocessorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
36
|
-
severity: string;
|
|
37
|
-
};
|
|
38
|
-
getDecoratorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
39
|
-
severity: string;
|
|
40
|
-
};
|
|
32
|
+
getRuleSettings(ruleId: string, oasVersion: OasVersion): RuleSettings;
|
|
33
|
+
getPreprocessorSettings(ruleId: string, oasVersion: OasVersion): RuleSettings;
|
|
34
|
+
getDecoratorSettings(ruleId: string, oasVersion: OasVersion): RuleSettings;
|
|
41
35
|
getUnusedRules(): {
|
|
42
36
|
rules: string[];
|
|
43
37
|
preprocessors: string[];
|
package/lib/config/config.js
CHANGED
|
@@ -34,7 +34,7 @@ function getIgnoreFilePath(configFile) {
|
|
|
34
34
|
: path.join(configFile, exports.IGNORE_FILE);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
return
|
|
37
|
+
return env_1.isBrowser ? undefined : path.join(process.cwd(), exports.IGNORE_FILE);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
exports.DOMAINS = getDomains();
|
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
|
@@ -18,7 +18,7 @@ const js_yaml_1 = require("../js-yaml");
|
|
|
18
18
|
const config_1 = require("./config");
|
|
19
19
|
const utils_2 = require("./utils");
|
|
20
20
|
const config_resolvers_1 = require("./config-resolvers");
|
|
21
|
-
function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, }) {
|
|
21
|
+
function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, files, region, }) {
|
|
22
22
|
var _a;
|
|
23
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
24
|
if (customExtends !== undefined) {
|
|
@@ -26,8 +26,7 @@ function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, }) {
|
|
|
26
26
|
rawConfig.styleguide.extends = customExtends;
|
|
27
27
|
}
|
|
28
28
|
else if (utils_1.isEmptyObject(rawConfig)) {
|
|
29
|
-
|
|
30
|
-
// rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
|
|
29
|
+
rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
|
|
31
30
|
}
|
|
32
31
|
if (tokens === null || tokens === void 0 ? void 0 : tokens.length) {
|
|
33
32
|
if (!rawConfig.resolve)
|
|
@@ -56,17 +55,13 @@ function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, }) {
|
|
|
56
55
|
: []));
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
|
-
return config_resolvers_1.resolveConfig(rawConfig, configPath);
|
|
58
|
+
return config_resolvers_1.resolveConfig(Object.assign(Object.assign({}, rawConfig), { files: files !== null && files !== void 0 ? files : rawConfig.files, region: region !== null && region !== void 0 ? region : rawConfig.region }), configPath);
|
|
60
59
|
});
|
|
61
60
|
}
|
|
62
61
|
function loadConfig(options = {}) {
|
|
63
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
63
|
const { configPath = findConfig(), customExtends, processRawConfig, files, region } = options;
|
|
65
|
-
const
|
|
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
|
-
}
|
|
64
|
+
const rawConfig = yield getConfig(configPath, processRawConfig);
|
|
70
65
|
const redoclyClient = new redocly_1.RedoclyClient();
|
|
71
66
|
const tokens = yield redoclyClient.getTokens();
|
|
72
67
|
return addConfigMetadata({
|
|
@@ -74,6 +69,8 @@ function loadConfig(options = {}) {
|
|
|
74
69
|
customExtends,
|
|
75
70
|
configPath,
|
|
76
71
|
tokens,
|
|
72
|
+
files,
|
|
73
|
+
region,
|
|
77
74
|
});
|
|
78
75
|
});
|
|
79
76
|
}
|
|
@@ -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
package/lib/config/rules.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { RuleSet, OasVersion } from '../oas-types';
|
|
2
2
|
import { StyleguideConfig } from './config';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import type { ProblemSeverity } from '../walk';
|
|
4
|
+
declare type InitializedRule = {
|
|
5
|
+
severity: ProblemSeverity;
|
|
5
6
|
ruleId: string;
|
|
6
7
|
visitor: any;
|
|
7
|
-
}
|
|
8
|
+
};
|
|
9
|
+
export declare function initRules<T extends Function, P extends RuleSet<T>>(rules: P[], config: StyleguideConfig, type: 'rules' | 'preprocessors' | 'decorators', oasVersion: OasVersion): InitializedRule[];
|
|
10
|
+
export {};
|
package/lib/config/rules.js
CHANGED
|
@@ -14,16 +14,17 @@ function initRules(rules, config, type, oasVersion) {
|
|
|
14
14
|
if (ruleSettings.severity === 'off') {
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
|
+
const severity = ruleSettings.severity;
|
|
17
18
|
const visitors = rule(ruleSettings);
|
|
18
19
|
if (Array.isArray(visitors)) {
|
|
19
20
|
return visitors.map((visitor) => ({
|
|
20
|
-
severity
|
|
21
|
+
severity,
|
|
21
22
|
ruleId,
|
|
22
23
|
visitor: visitor,
|
|
23
24
|
}));
|
|
24
25
|
}
|
|
25
26
|
return {
|
|
26
|
-
severity
|
|
27
|
+
severity,
|
|
27
28
|
ruleId,
|
|
28
29
|
visitor: visitors, // note: actually it is only one visitor object
|
|
29
30
|
};
|
package/lib/config/types.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type { Oas3PreprocessorsSet, OasMajorVersion, Oas3DecoratorsSet, Oas2Rule
|
|
|
3
3
|
import type { NodeType } from '../types';
|
|
4
4
|
import { Location } from '../ref-utils';
|
|
5
5
|
export declare type RuleSeverity = ProblemSeverity | 'off';
|
|
6
|
+
export declare type RuleSettings = {
|
|
7
|
+
severity: RuleSeverity;
|
|
8
|
+
};
|
|
6
9
|
export declare type PreprocessorSeverity = RuleSeverity | 'on';
|
|
7
10
|
export declare type RuleConfig = RuleSeverity | ({
|
|
8
11
|
severity?: ProblemSeverity;
|
package/lib/ref-utils.d.ts
CHANGED
|
@@ -23,3 +23,4 @@ export declare function pointerBaseName(pointer: string): string;
|
|
|
23
23
|
export declare function refBaseName(ref: string): string;
|
|
24
24
|
export declare function isAbsoluteUrl(ref: string): boolean;
|
|
25
25
|
export declare function isMappingRef(mapping: string): boolean;
|
|
26
|
+
export declare function isAnchor(ref: string): boolean;
|
package/lib/ref-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isMappingRef = exports.isAbsoluteUrl = exports.refBaseName = exports.pointerBaseName = exports.parsePointer = exports.parseRef = exports.escapePointer = exports.unescapePointer = exports.Location = exports.isRef = exports.joinPointer = void 0;
|
|
3
|
+
exports.isAnchor = exports.isMappingRef = exports.isAbsoluteUrl = exports.refBaseName = exports.pointerBaseName = exports.parsePointer = exports.parseRef = exports.escapePointer = exports.unescapePointer = exports.Location = exports.isRef = exports.joinPointer = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
function joinPointer(base, key) {
|
|
6
6
|
if (base === '')
|
|
@@ -74,3 +74,7 @@ function isMappingRef(mapping) {
|
|
|
74
74
|
mapping.indexOf('/') > -1);
|
|
75
75
|
}
|
|
76
76
|
exports.isMappingRef = isMappingRef;
|
|
77
|
+
function isAnchor(ref) {
|
|
78
|
+
return /^#[A-Za-z][A-Za-z0-9\-_:.]*$/.test(ref);
|
|
79
|
+
}
|
|
80
|
+
exports.isAnchor = isAnchor;
|
package/lib/resolve.js
CHANGED
|
@@ -186,6 +186,7 @@ function resolveDocument(opts) {
|
|
|
186
186
|
return resolvedRefMap;
|
|
187
187
|
function resolveRefsInParallel(rootNode, rootNodeDocument, rootNodePointer, type) {
|
|
188
188
|
const rootNodeDocAbsoluteRef = rootNodeDocument.source.absoluteRef;
|
|
189
|
+
const anchorRefsMap = new Map();
|
|
189
190
|
walk(rootNode, type, rootNodeDocAbsoluteRef + rootNodePointer);
|
|
190
191
|
function walk(node, type, nodeAbsoluteRef) {
|
|
191
192
|
if (typeof node !== 'object' || node === null) {
|
|
@@ -196,6 +197,10 @@ function resolveDocument(opts) {
|
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
198
199
|
seedNodes.add(nodeId);
|
|
200
|
+
const [_, anchor] = Object.entries(node).find(([key]) => key === '$anchor') || [];
|
|
201
|
+
if (anchor) {
|
|
202
|
+
anchorRefsMap.set(`#${anchor}`, node);
|
|
203
|
+
}
|
|
199
204
|
if (Array.isArray(node)) {
|
|
200
205
|
const itemsType = type.items;
|
|
201
206
|
// we continue resolving unknown types, but stop early on known scalars
|
|
@@ -245,6 +250,20 @@ function resolveDocument(opts) {
|
|
|
245
250
|
if (hasRef(refStack.prev, ref)) {
|
|
246
251
|
throw new Error('Self-referencing circular pointer');
|
|
247
252
|
}
|
|
253
|
+
if (ref_utils_1.isAnchor(ref.$ref)) {
|
|
254
|
+
// Wait for all anchors in the document to be collected firstly.
|
|
255
|
+
yield utils_1.nextTick();
|
|
256
|
+
const resolvedRef = {
|
|
257
|
+
resolved: true,
|
|
258
|
+
isRemote: false,
|
|
259
|
+
node: anchorRefsMap.get(ref.$ref),
|
|
260
|
+
document,
|
|
261
|
+
nodePointer: ref.$ref,
|
|
262
|
+
};
|
|
263
|
+
const refId = makeRefId(document.source.absoluteRef, ref.$ref);
|
|
264
|
+
resolvedRefMap.set(refId, resolvedRef);
|
|
265
|
+
return resolvedRef;
|
|
266
|
+
}
|
|
248
267
|
const { uri, pointer } = ref_utils_1.parseRef(ref.$ref);
|
|
249
268
|
const isRemote = uri !== null;
|
|
250
269
|
let targetDoc;
|
|
@@ -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 {};
|