@redocly/openapi-core 1.0.0-beta.102 → 1.0.0-beta.105
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/__tests__/utils.ts +3 -1
- package/lib/config/config.d.ts +4 -3
- package/lib/config/config.js +23 -16
- package/lib/config/load.d.ts +1 -1
- package/lib/config/load.js +15 -3
- package/lib/config/rules.d.ts +1 -1
- package/lib/config/types.d.ts +4 -2
- package/lib/decorators/common/filters/filter-helper.d.ts +3 -0
- package/lib/decorators/common/filters/filter-helper.js +67 -0
- package/lib/decorators/common/filters/filter-in.d.ts +2 -0
- package/lib/decorators/common/filters/filter-in.js +17 -0
- package/lib/decorators/common/filters/filter-out.d.ts +2 -0
- package/lib/decorators/common/filters/filter-out.js +17 -0
- package/lib/decorators/oas2/index.d.ts +2 -0
- package/lib/decorators/oas2/index.js +5 -1
- package/lib/decorators/oas3/index.d.ts +2 -0
- package/lib/decorators/oas3/index.js +5 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -1
- package/lib/lint.d.ts +2 -0
- package/lib/lint.js +2 -2
- package/lib/redocly/registry-api-types.d.ts +2 -0
- package/lib/redocly/registry-api.d.ts +1 -1
- package/lib/redocly/registry-api.js +3 -1
- package/lib/rules/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +1 -1
- package/lib/rules/common/assertions/asserts.d.ts +6 -1
- package/lib/rules/common/assertions/asserts.js +81 -51
- package/lib/rules/common/assertions/utils.d.ts +2 -1
- package/lib/rules/common/assertions/utils.js +27 -8
- package/lib/types/redocly-yaml.js +317 -27
- package/lib/utils.d.ts +5 -3
- package/lib/utils.js +15 -2
- package/lib/walk.d.ts +4 -14
- package/lib/walk.js +35 -26
- package/package.json +3 -2
- package/src/__tests__/fixtures/.redocly.lint-ignore.yaml +5 -0
- package/src/__tests__/lint.test.ts +70 -10
- package/src/__tests__/utils.test.ts +42 -1
- package/src/config/__tests__/load.test.ts +8 -2
- package/src/config/config.ts +31 -27
- package/src/config/load.ts +29 -9
- package/src/config/types.ts +6 -5
- package/src/decorators/__tests__/filter-in.test.ts +310 -0
- package/src/decorators/__tests__/filter-out.test.ts +331 -0
- package/src/decorators/common/filters/filter-helper.ts +72 -0
- package/src/decorators/common/filters/filter-in.ts +18 -0
- package/src/decorators/common/filters/filter-out.ts +18 -0
- package/src/decorators/oas2/index.ts +5 -1
- package/src/decorators/oas3/index.ts +5 -1
- package/src/index.ts +2 -1
- package/src/lint.ts +4 -3
- package/src/redocly/registry-api-types.ts +2 -0
- package/src/redocly/registry-api.ts +4 -0
- package/src/rules/ajv.ts +4 -4
- package/src/rules/common/assertions/__tests__/asserts.test.ts +149 -146
- package/src/rules/common/assertions/asserts.ts +97 -52
- package/src/rules/common/assertions/utils.ts +41 -16
- package/src/types/redocly-yaml.ts +322 -34
- package/src/utils.ts +28 -15
- package/src/walk.ts +59 -47
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.asserts = exports.runOnValuesSet = exports.runOnKeysSet = void 0;
|
|
4
|
-
const utils_1 = require("
|
|
4
|
+
const utils_1 = require("../../../utils");
|
|
5
|
+
const utils_2 = require("./utils");
|
|
5
6
|
exports.runOnKeysSet = new Set([
|
|
6
7
|
'mutuallyExclusive',
|
|
7
8
|
'mutuallyRequired',
|
|
@@ -13,6 +14,8 @@ exports.runOnKeysSet = new Set([
|
|
|
13
14
|
'sortOrder',
|
|
14
15
|
'disallowed',
|
|
15
16
|
'required',
|
|
17
|
+
'requireAny',
|
|
18
|
+
'ref',
|
|
16
19
|
]);
|
|
17
20
|
exports.runOnValuesSet = new Set([
|
|
18
21
|
'pattern',
|
|
@@ -24,78 +27,83 @@ exports.runOnValuesSet = new Set([
|
|
|
24
27
|
'maxLength',
|
|
25
28
|
'casing',
|
|
26
29
|
'sortOrder',
|
|
30
|
+
'ref',
|
|
27
31
|
]);
|
|
28
32
|
exports.asserts = {
|
|
29
|
-
pattern: (value, condition) => {
|
|
33
|
+
pattern: (value, condition, baseLocation) => {
|
|
30
34
|
if (typeof value === 'undefined')
|
|
31
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
32
|
-
const values =
|
|
33
|
-
const
|
|
34
|
-
condition = condition.slice(1).replace(regexOptions[0], '');
|
|
35
|
-
const regx = new RegExp(condition, regexOptions[0].slice(1));
|
|
35
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
36
|
+
const values = utils_1.isString(value) ? [value] : value;
|
|
37
|
+
const regx = utils_2.regexFromString(condition);
|
|
36
38
|
for (let _val of values) {
|
|
37
|
-
if (!
|
|
38
|
-
return false;
|
|
39
|
+
if (!(regx === null || regx === void 0 ? void 0 : regx.test(_val))) {
|
|
40
|
+
return { isValid: false, location: utils_1.isString(value) ? baseLocation : baseLocation.key() };
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
return true;
|
|
43
|
+
return { isValid: true };
|
|
42
44
|
},
|
|
43
|
-
enum: (value, condition) => {
|
|
45
|
+
enum: (value, condition, baseLocation) => {
|
|
44
46
|
if (typeof value === 'undefined')
|
|
45
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
46
|
-
const values =
|
|
47
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
48
|
+
const values = utils_1.isString(value) ? [value] : value;
|
|
47
49
|
for (let _val of values) {
|
|
48
50
|
if (!condition.includes(_val)) {
|
|
49
|
-
return
|
|
51
|
+
return {
|
|
52
|
+
isValid: false,
|
|
53
|
+
location: utils_1.isString(value) ? baseLocation : baseLocation.child(_val).key(),
|
|
54
|
+
};
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
|
-
return true;
|
|
57
|
+
return { isValid: true };
|
|
53
58
|
},
|
|
54
|
-
defined: (value, condition = true) => {
|
|
59
|
+
defined: (value, condition = true, baseLocation) => {
|
|
55
60
|
const isDefined = typeof value !== 'undefined';
|
|
56
|
-
return condition ? isDefined : !isDefined;
|
|
61
|
+
return { isValid: condition ? isDefined : !isDefined, location: baseLocation };
|
|
57
62
|
},
|
|
58
|
-
required: (value, keys) => {
|
|
63
|
+
required: (value, keys, baseLocation) => {
|
|
59
64
|
for (const requiredKey of keys) {
|
|
60
65
|
if (!value.includes(requiredKey)) {
|
|
61
|
-
return false;
|
|
66
|
+
return { isValid: false, location: baseLocation.key() };
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
|
-
return true;
|
|
69
|
+
return { isValid: true };
|
|
65
70
|
},
|
|
66
|
-
disallowed: (value, condition) => {
|
|
71
|
+
disallowed: (value, condition, baseLocation) => {
|
|
67
72
|
if (typeof value === 'undefined')
|
|
68
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
69
|
-
const values =
|
|
73
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
74
|
+
const values = utils_1.isString(value) ? [value] : value;
|
|
70
75
|
for (let _val of values) {
|
|
71
76
|
if (condition.includes(_val)) {
|
|
72
|
-
return
|
|
77
|
+
return {
|
|
78
|
+
isValid: false,
|
|
79
|
+
location: utils_1.isString(value) ? baseLocation : baseLocation.child(_val).key(),
|
|
80
|
+
};
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
|
-
return true;
|
|
83
|
+
return { isValid: true };
|
|
76
84
|
},
|
|
77
|
-
undefined: (value, condition = true) => {
|
|
85
|
+
undefined: (value, condition = true, baseLocation) => {
|
|
78
86
|
const isUndefined = typeof value === 'undefined';
|
|
79
|
-
return condition ? isUndefined : !isUndefined;
|
|
87
|
+
return { isValid: condition ? isUndefined : !isUndefined, location: baseLocation };
|
|
80
88
|
},
|
|
81
|
-
nonEmpty: (value, condition = true) => {
|
|
89
|
+
nonEmpty: (value, condition = true, baseLocation) => {
|
|
82
90
|
const isEmpty = typeof value === 'undefined' || value === null || value === '';
|
|
83
|
-
return condition ? !isEmpty : isEmpty;
|
|
91
|
+
return { isValid: condition ? !isEmpty : isEmpty, location: baseLocation };
|
|
84
92
|
},
|
|
85
|
-
minLength: (value, condition) => {
|
|
93
|
+
minLength: (value, condition, baseLocation) => {
|
|
86
94
|
if (typeof value === 'undefined')
|
|
87
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
88
|
-
return value.length >= condition;
|
|
95
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
96
|
+
return { isValid: value.length >= condition, location: baseLocation };
|
|
89
97
|
},
|
|
90
|
-
maxLength: (value, condition) => {
|
|
98
|
+
maxLength: (value, condition, baseLocation) => {
|
|
91
99
|
if (typeof value === 'undefined')
|
|
92
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
93
|
-
return value.length <= condition;
|
|
100
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
101
|
+
return { isValid: value.length <= condition, location: baseLocation };
|
|
94
102
|
},
|
|
95
|
-
casing: (value, condition) => {
|
|
103
|
+
casing: (value, condition, baseLocation) => {
|
|
96
104
|
if (typeof value === 'undefined')
|
|
97
|
-
return true; // property doesn't exist, no need to lint it with this assert
|
|
98
|
-
const values =
|
|
105
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
106
|
+
const values = utils_1.isString(value) ? [value] : value;
|
|
99
107
|
for (let _val of values) {
|
|
100
108
|
let matchCase = false;
|
|
101
109
|
switch (condition) {
|
|
@@ -122,25 +130,47 @@ exports.asserts = {
|
|
|
122
130
|
break;
|
|
123
131
|
}
|
|
124
132
|
if (!matchCase) {
|
|
125
|
-
return
|
|
133
|
+
return {
|
|
134
|
+
isValid: false,
|
|
135
|
+
location: utils_1.isString(value) ? baseLocation : baseLocation.child(_val).key(),
|
|
136
|
+
};
|
|
126
137
|
}
|
|
127
138
|
}
|
|
128
|
-
return true;
|
|
139
|
+
return { isValid: true };
|
|
129
140
|
},
|
|
130
|
-
sortOrder: (value, condition) => {
|
|
141
|
+
sortOrder: (value, condition, baseLocation) => {
|
|
131
142
|
if (typeof value === 'undefined')
|
|
132
|
-
return true;
|
|
133
|
-
return
|
|
143
|
+
return { isValid: true };
|
|
144
|
+
return { isValid: utils_2.isOrdered(value, condition), location: baseLocation };
|
|
134
145
|
},
|
|
135
|
-
mutuallyExclusive: (value, condition) => {
|
|
136
|
-
return
|
|
146
|
+
mutuallyExclusive: (value, condition, baseLocation) => {
|
|
147
|
+
return { isValid: utils_2.getIntersectionLength(value, condition) < 2, location: baseLocation.key() };
|
|
137
148
|
},
|
|
138
|
-
mutuallyRequired: (value, condition) => {
|
|
139
|
-
return
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
mutuallyRequired: (value, condition, baseLocation) => {
|
|
150
|
+
return {
|
|
151
|
+
isValid: utils_2.getIntersectionLength(value, condition) > 0
|
|
152
|
+
? utils_2.getIntersectionLength(value, condition) === condition.length
|
|
153
|
+
: true,
|
|
154
|
+
location: baseLocation.key(),
|
|
155
|
+
};
|
|
142
156
|
},
|
|
143
|
-
requireAny: (value, condition) => {
|
|
144
|
-
return
|
|
157
|
+
requireAny: (value, condition, baseLocation) => {
|
|
158
|
+
return { isValid: utils_2.getIntersectionLength(value, condition) >= 1, location: baseLocation.key() };
|
|
159
|
+
},
|
|
160
|
+
ref: (_value, condition, baseLocation, rawValue) => {
|
|
161
|
+
if (typeof rawValue === 'undefined')
|
|
162
|
+
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
163
|
+
const hasRef = rawValue.hasOwnProperty('$ref');
|
|
164
|
+
if (typeof condition === 'boolean') {
|
|
165
|
+
return {
|
|
166
|
+
isValid: condition ? hasRef : !hasRef,
|
|
167
|
+
location: hasRef ? baseLocation : baseLocation.key(),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const regex = utils_2.regexFromString(condition);
|
|
171
|
+
return {
|
|
172
|
+
isValid: hasRef && (regex === null || regex === void 0 ? void 0 : regex.test(rawValue['$ref'])),
|
|
173
|
+
location: hasRef ? baseLocation : baseLocation.key(),
|
|
174
|
+
};
|
|
145
175
|
},
|
|
146
176
|
};
|
|
@@ -15,6 +15,7 @@ export declare type AssertToApply = {
|
|
|
15
15
|
runsOnValues: boolean;
|
|
16
16
|
};
|
|
17
17
|
export declare function buildVisitorObject(subject: string, context: Record<string, any>[], subjectVisitor: any): Record<string, any>;
|
|
18
|
-
export declare function buildSubjectVisitor(properties: string | string[], asserts: AssertToApply[], context?: Record<string, any>[]): (node: any, { report, location, key, type, resolve }: UserContext) => void;
|
|
18
|
+
export declare function buildSubjectVisitor(properties: string | string[], asserts: AssertToApply[], context?: Record<string, any>[]): (node: any, { report, location, rawLocation, key, type, resolve, rawNode }: UserContext) => void;
|
|
19
19
|
export declare function getIntersectionLength(keys: string[], properties: string[]): number;
|
|
20
20
|
export declare function isOrdered(value: any[], options: OrderOptions | OrderDirection): boolean;
|
|
21
|
+
export declare function regexFromString(input: string): RegExp | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isOrdered = exports.getIntersectionLength = exports.buildSubjectVisitor = exports.buildVisitorObject = void 0;
|
|
3
|
+
exports.regexFromString = exports.isOrdered = exports.getIntersectionLength = exports.buildSubjectVisitor = exports.buildVisitorObject = void 0;
|
|
4
4
|
const ref_utils_1 = require("../../../ref-utils");
|
|
5
5
|
const asserts_1 = require("./asserts");
|
|
6
6
|
function buildVisitorObject(subject, context, subjectVisitor) {
|
|
@@ -45,7 +45,7 @@ function buildVisitorObject(subject, context, subjectVisitor) {
|
|
|
45
45
|
}
|
|
46
46
|
exports.buildVisitorObject = buildVisitorObject;
|
|
47
47
|
function buildSubjectVisitor(properties, asserts, context) {
|
|
48
|
-
return
|
|
48
|
+
return (node, { report, location, rawLocation, key, type, resolve, rawNode }) => {
|
|
49
49
|
var _a;
|
|
50
50
|
// We need to check context's last node if it has the same type as subject node;
|
|
51
51
|
// if yes - that means we didn't create context's last node visitor,
|
|
@@ -67,15 +67,29 @@ function buildSubjectVisitor(properties, asserts, context) {
|
|
|
67
67
|
properties = Array.isArray(properties) ? properties : [properties];
|
|
68
68
|
}
|
|
69
69
|
for (const assert of asserts) {
|
|
70
|
+
const currentLocation = assert.name === 'ref' ? rawLocation : location;
|
|
70
71
|
if (properties) {
|
|
71
72
|
for (const property of properties) {
|
|
72
73
|
// we can have resolvable scalar so need to resolve value here.
|
|
73
74
|
const value = ref_utils_1.isRef(node[property]) ? (_a = resolve(node[property])) === null || _a === void 0 ? void 0 : _a.node : node[property];
|
|
74
|
-
runAssertion(
|
|
75
|
+
runAssertion({
|
|
76
|
+
values: value,
|
|
77
|
+
rawValues: rawNode[property],
|
|
78
|
+
assert,
|
|
79
|
+
location: currentLocation.child(property),
|
|
80
|
+
report,
|
|
81
|
+
});
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
else {
|
|
78
|
-
|
|
85
|
+
const value = assert.name === 'ref' ? rawNode : Object.keys(node);
|
|
86
|
+
runAssertion({
|
|
87
|
+
values: Object.keys(node),
|
|
88
|
+
rawValues: value,
|
|
89
|
+
assert,
|
|
90
|
+
location: currentLocation,
|
|
91
|
+
report,
|
|
92
|
+
});
|
|
79
93
|
}
|
|
80
94
|
}
|
|
81
95
|
};
|
|
@@ -113,15 +127,20 @@ function isOrdered(value, options) {
|
|
|
113
127
|
return true;
|
|
114
128
|
}
|
|
115
129
|
exports.isOrdered = isOrdered;
|
|
116
|
-
function runAssertion(values, assert, location, report) {
|
|
117
|
-
const lintResult = asserts_1.asserts[assert.name](values, assert.conditions);
|
|
118
|
-
if (!lintResult) {
|
|
130
|
+
function runAssertion({ values, rawValues, assert, location, report }) {
|
|
131
|
+
const lintResult = asserts_1.asserts[assert.name](values, assert.conditions, location, rawValues);
|
|
132
|
+
if (!lintResult.isValid) {
|
|
119
133
|
report({
|
|
120
134
|
message: assert.message || `The ${assert.assertId} doesn't meet required conditions`,
|
|
121
|
-
location,
|
|
135
|
+
location: lintResult.location || location,
|
|
122
136
|
forceSeverity: assert.severity,
|
|
123
137
|
suggest: assert.suggest,
|
|
124
138
|
ruleId: assert.assertId,
|
|
125
139
|
});
|
|
126
140
|
}
|
|
127
141
|
}
|
|
142
|
+
function regexFromString(input) {
|
|
143
|
+
const matches = input.match(/^\/(.*)\/(.*)|(.*)/);
|
|
144
|
+
return matches && new RegExp(matches[1] || matches[3], matches[2]);
|
|
145
|
+
}
|
|
146
|
+
exports.regexFromString = regexFromString;
|