@redocly/openapi-core 1.0.0-beta.106 → 1.0.0-beta.109
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/benchmark/benches/lint-with-top-level-rule-report.bench.js +0 -1
- package/lib/benchmark/benches/resolve-with-no-external.bench.js +1 -1
- package/lib/bundle.d.ts +1 -1
- package/lib/bundle.js +9 -6
- package/lib/config/all.js +5 -3
- package/lib/config/config-resolvers.js +32 -14
- package/lib/config/config.d.ts +3 -5
- package/lib/config/config.js +7 -4
- package/lib/config/load.d.ts +7 -0
- package/lib/config/load.js +14 -6
- package/lib/config/minimal.js +7 -4
- package/lib/config/recommended.js +7 -4
- package/lib/config/rules.d.ts +1 -1
- package/lib/config/rules.js +1 -1
- package/lib/config/types.d.ts +7 -0
- package/lib/config/utils.d.ts +2 -2
- package/lib/config/utils.js +49 -11
- package/lib/decorators/common/registry-dependencies.js +2 -2
- package/lib/env.d.ts +3 -0
- package/lib/env.js +8 -0
- package/lib/format/codeframes.js +16 -10
- package/lib/format/format.d.ts +1 -1
- package/lib/format/format.js +49 -26
- package/lib/index.d.ts +5 -5
- package/lib/index.js +3 -1
- package/lib/js-yaml/index.js +1 -0
- package/lib/lint.js +2 -2
- package/lib/logger.d.ts +10 -0
- package/lib/logger.js +31 -0
- package/lib/output.d.ts +3 -0
- package/lib/output.js +9 -0
- package/lib/redocly/index.js +10 -9
- package/lib/redocly/registry-api-types.d.ts +28 -30
- package/lib/redocly/registry-api.d.ts +3 -3
- package/lib/redocly/registry-api.js +7 -1
- package/lib/ref-utils.js +2 -1
- package/lib/resolve.d.ts +1 -1
- package/lib/resolve.js +4 -2
- package/lib/rules/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +7 -7
- package/lib/rules/common/assertions/asserts.js +4 -4
- package/lib/rules/common/assertions/index.js +1 -1
- package/lib/rules/common/no-ambiguous-paths.js +1 -1
- package/lib/rules/common/no-identical-paths.js +1 -1
- package/lib/rules/common/no-invalid-parameter-examples.js +3 -3
- package/lib/rules/common/no-invalid-schema-examples.js +3 -3
- package/lib/rules/common/operation-2xx-response.js +1 -1
- package/lib/rules/common/operation-4xx-response.js +1 -1
- package/lib/rules/common/operation-operationId.js +1 -1
- package/lib/rules/common/operation-tag-defined.js +1 -1
- package/lib/rules/common/path-not-include-query.js +1 -1
- package/lib/rules/common/security-defined.d.ts +2 -0
- package/lib/rules/common/{operation-security-defined.js → security-defined.js} +19 -5
- package/lib/rules/common/spec.js +14 -3
- package/lib/rules/common/tags-alphabetical.js +1 -1
- package/lib/rules/oas2/index.d.ts +1 -1
- package/lib/rules/oas2/index.js +2 -2
- package/lib/rules/oas2/remove-unused-components.js +3 -3
- package/lib/rules/oas2/request-mime-type.js +1 -1
- package/lib/rules/oas2/response-mime-type.js +1 -1
- package/lib/rules/oas3/index.js +8 -4
- package/lib/rules/oas3/no-empty-servers.js +1 -1
- package/lib/rules/oas3/no-invalid-media-type-examples.js +2 -2
- package/lib/rules/oas3/no-server-variables-empty-enum.d.ts +2 -0
- package/lib/rules/oas3/{no-servers-empty-enum.js → no-server-variables-empty-enum.js} +5 -5
- package/lib/rules/oas3/no-unused-components.js +2 -2
- package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +5 -0
- package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +36 -0
- package/lib/rules/oas3/remove-unused-components.js +4 -4
- package/lib/rules/oas3/request-mime-type.js +1 -1
- package/lib/rules/oas3/response-mime-type.js +1 -1
- package/lib/rules/oas3/spec-components-invalid-map-name.d.ts +2 -0
- package/lib/rules/oas3/spec-components-invalid-map-name.js +46 -0
- package/lib/rules/other/stats.d.ts +2 -2
- package/lib/rules/other/stats.js +2 -2
- package/lib/rules/utils.d.ts +3 -2
- package/lib/rules/utils.js +16 -4
- package/lib/types/oas2.js +5 -5
- package/lib/types/oas3.js +27 -20
- package/lib/types/oas3_1.js +3 -3
- package/lib/types/redocly-yaml.js +47 -56
- package/lib/utils.d.ts +6 -1
- package/lib/utils.js +24 -7
- package/lib/visitors.d.ts +12 -12
- package/lib/visitors.js +15 -3
- package/lib/walk.d.ts +2 -1
- package/lib/walk.js +6 -3
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +3 -3
- package/src/__tests__/fixtures/extension.js +3 -3
- package/src/__tests__/format.test.ts +76 -0
- package/src/__tests__/lint.test.ts +106 -131
- package/src/__tests__/logger-browser.test.ts +53 -0
- package/src/__tests__/logger.test.ts +47 -0
- package/src/__tests__/output-browser.test.ts +18 -0
- package/src/__tests__/output.test.ts +15 -0
- package/src/__tests__/resolve-http.test.ts +1 -1
- package/src/__tests__/resolve.test.ts +9 -9
- package/src/__tests__/utils-browser.test.ts +11 -0
- package/src/__tests__/utils.test.ts +7 -0
- package/src/__tests__/walk.test.ts +78 -10
- package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +0 -1
- package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
- package/src/bundle.ts +10 -7
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +12 -6
- package/src/config/__tests__/config.test.ts +35 -0
- package/src/config/__tests__/fixtures/plugin-config.yaml +2 -3
- package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +11 -12
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +7 -8
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +18 -19
- package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +9 -10
- package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +3 -4
- package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +4 -5
- package/src/config/__tests__/load.test.ts +76 -1
- package/src/config/__tests__/utils.test.ts +64 -4
- package/src/config/all.ts +5 -3
- package/src/config/config-resolvers.ts +45 -19
- package/src/config/config.ts +10 -8
- package/src/config/load.ts +31 -7
- package/src/config/minimal.ts +7 -4
- package/src/config/recommended.ts +7 -4
- package/src/config/rules.ts +2 -2
- package/src/config/types.ts +11 -0
- package/src/config/utils.ts +115 -25
- package/src/decorators/common/registry-dependencies.ts +2 -2
- package/src/env.ts +5 -0
- package/src/format/codeframes.ts +15 -9
- package/src/format/format.ts +59 -34
- package/src/index.ts +6 -4
- package/src/js-yaml/index.ts +1 -0
- package/src/lint.ts +2 -2
- package/src/logger.ts +34 -0
- package/src/output.ts +7 -0
- package/src/redocly/index.ts +7 -4
- package/src/redocly/registry-api-types.ts +27 -29
- package/src/redocly/registry-api.ts +18 -7
- package/src/ref-utils.ts +2 -1
- package/src/resolve.ts +7 -5
- package/src/rules/__tests__/utils.test.ts +39 -1
- package/src/rules/ajv.ts +7 -7
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -0
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -1
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +26 -3
- package/src/rules/common/__tests__/security-defined.test.ts +175 -0
- package/src/rules/common/__tests__/spec.test.ts +79 -0
- package/src/rules/common/assertions/__tests__/utils.test.ts +2 -2
- package/src/rules/common/assertions/asserts.ts +4 -4
- package/src/rules/common/assertions/index.ts +1 -1
- package/src/rules/common/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-identical-paths.ts +1 -1
- package/src/rules/common/no-invalid-parameter-examples.ts +4 -4
- package/src/rules/common/no-invalid-schema-examples.ts +4 -4
- package/src/rules/common/operation-2xx-response.ts +1 -1
- package/src/rules/common/operation-4xx-response.ts +1 -1
- package/src/rules/common/operation-operationId.ts +1 -1
- package/src/rules/common/operation-tag-defined.ts +1 -1
- package/src/rules/common/path-not-include-query.ts +1 -1
- package/src/rules/common/{operation-security-defined.ts → security-defined.ts} +20 -5
- package/src/rules/common/spec.ts +17 -3
- package/src/rules/common/tags-alphabetical.ts +1 -1
- package/src/rules/oas2/index.ts +2 -2
- package/src/rules/oas2/remove-unused-components.ts +3 -3
- package/src/rules/oas2/request-mime-type.ts +1 -1
- package/src/rules/oas2/response-mime-type.ts +1 -1
- package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +16 -16
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +5 -5
- package/src/rules/oas3/__tests__/operation-4xx-problem-details-rfc7807.test.ts +145 -0
- package/src/rules/oas3/__tests__/spec/spec.test.ts +10 -0
- package/src/rules/oas3/__tests__/spec-components-invalid-map-name.test.ts +217 -0
- package/src/rules/oas3/index.ts +8 -4
- package/src/rules/oas3/no-empty-servers.ts +1 -1
- package/src/rules/oas3/no-invalid-media-type-examples.ts +3 -3
- package/src/rules/oas3/{no-servers-empty-enum.ts → no-server-variables-empty-enum.ts} +3 -3
- package/src/rules/oas3/no-unused-components.ts +2 -2
- package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +36 -0
- package/src/rules/oas3/remove-unused-components.ts +5 -5
- package/src/rules/oas3/request-mime-type.ts +1 -1
- package/src/rules/oas3/response-mime-type.ts +1 -1
- package/src/rules/oas3/spec-components-invalid-map-name.ts +53 -0
- package/src/rules/other/stats.ts +2 -2
- package/src/rules/utils.ts +17 -3
- package/src/types/index.ts +2 -2
- package/src/types/oas2.ts +5 -5
- package/src/types/oas3.ts +27 -20
- package/src/types/oas3_1.ts +3 -3
- package/src/types/redocly-yaml.ts +53 -41
- package/src/utils.ts +31 -4
- package/src/visitors.ts +34 -18
- package/src/walk.ts +15 -11
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/common/operation-security-defined.d.ts +0 -2
- package/lib/rules/oas3/no-servers-empty-enum.d.ts +0 -2
- package/src/rules/common/__tests__/operation-security-defined.test.ts +0 -69
package/lib/rules/ajv.js
CHANGED
|
@@ -8,7 +8,7 @@ function releaseAjvInstance() {
|
|
|
8
8
|
ajvInstance = null;
|
|
9
9
|
}
|
|
10
10
|
exports.releaseAjvInstance = releaseAjvInstance;
|
|
11
|
-
function getAjv(resolve,
|
|
11
|
+
function getAjv(resolve, allowAdditionalProperties) {
|
|
12
12
|
if (!ajvInstance) {
|
|
13
13
|
ajvInstance = new ajv_1.default({
|
|
14
14
|
schemaId: '$id',
|
|
@@ -20,7 +20,7 @@ function getAjv(resolve, disallowAdditionalProperties) {
|
|
|
20
20
|
discriminator: true,
|
|
21
21
|
allowUnionTypes: true,
|
|
22
22
|
validateFormats: false,
|
|
23
|
-
defaultAdditionalProperties:
|
|
23
|
+
defaultAdditionalProperties: allowAdditionalProperties,
|
|
24
24
|
loadSchemaSync(base, $ref) {
|
|
25
25
|
const resolvedRef = resolve({ $ref }, base.split('#')[0]);
|
|
26
26
|
if (!resolvedRef || !resolvedRef.location)
|
|
@@ -32,15 +32,15 @@ function getAjv(resolve, disallowAdditionalProperties) {
|
|
|
32
32
|
}
|
|
33
33
|
return ajvInstance;
|
|
34
34
|
}
|
|
35
|
-
function getAjvValidator(schema, loc, resolve,
|
|
36
|
-
const ajv = getAjv(resolve,
|
|
35
|
+
function getAjvValidator(schema, loc, resolve, allowAdditionalProperties) {
|
|
36
|
+
const ajv = getAjv(resolve, allowAdditionalProperties);
|
|
37
37
|
if (!ajv.getSchema(loc.absolutePointer)) {
|
|
38
38
|
ajv.addSchema(Object.assign({ $id: loc.absolutePointer }, schema), loc.absolutePointer);
|
|
39
39
|
}
|
|
40
40
|
return ajv.getSchema(loc.absolutePointer);
|
|
41
41
|
}
|
|
42
|
-
function validateJsonSchema(data, schema, schemaLoc, instancePath, resolve,
|
|
43
|
-
const validate = getAjvValidator(schema, schemaLoc, resolve,
|
|
42
|
+
function validateJsonSchema(data, schema, schemaLoc, instancePath, resolve, allowAdditionalProperties) {
|
|
43
|
+
const validate = getAjvValidator(schema, schemaLoc, resolve, allowAdditionalProperties);
|
|
44
44
|
if (!validate)
|
|
45
45
|
return { valid: true, errors: [] }; // unresolved refs are reported
|
|
46
46
|
const valid = validate(data, {
|
|
@@ -56,7 +56,7 @@ function validateJsonSchema(data, schema, schemaLoc, instancePath, resolve, disa
|
|
|
56
56
|
};
|
|
57
57
|
function beatifyErrorMessage(error) {
|
|
58
58
|
let message = error.message;
|
|
59
|
-
|
|
59
|
+
const suggest = error.keyword === 'enum' ? error.params.allowedValues : undefined;
|
|
60
60
|
if (suggest) {
|
|
61
61
|
message += ` ${suggest.map((e) => `"${e}"`).join(', ')}`;
|
|
62
62
|
}
|
|
@@ -35,7 +35,7 @@ exports.asserts = {
|
|
|
35
35
|
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
36
36
|
const values = utils_1.isString(value) ? [value] : value;
|
|
37
37
|
const regx = utils_2.regexFromString(condition);
|
|
38
|
-
for (
|
|
38
|
+
for (const _val of values) {
|
|
39
39
|
if (!(regx === null || regx === void 0 ? void 0 : regx.test(_val))) {
|
|
40
40
|
return { isValid: false, location: utils_1.isString(value) ? baseLocation : baseLocation.key() };
|
|
41
41
|
}
|
|
@@ -46,7 +46,7 @@ exports.asserts = {
|
|
|
46
46
|
if (typeof value === 'undefined')
|
|
47
47
|
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
48
48
|
const values = utils_1.isString(value) ? [value] : value;
|
|
49
|
-
for (
|
|
49
|
+
for (const _val of values) {
|
|
50
50
|
if (!condition.includes(_val)) {
|
|
51
51
|
return {
|
|
52
52
|
isValid: false,
|
|
@@ -72,7 +72,7 @@ exports.asserts = {
|
|
|
72
72
|
if (typeof value === 'undefined')
|
|
73
73
|
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
74
74
|
const values = utils_1.isString(value) ? [value] : value;
|
|
75
|
-
for (
|
|
75
|
+
for (const _val of values) {
|
|
76
76
|
if (condition.includes(_val)) {
|
|
77
77
|
return {
|
|
78
78
|
isValid: false,
|
|
@@ -104,7 +104,7 @@ exports.asserts = {
|
|
|
104
104
|
if (typeof value === 'undefined')
|
|
105
105
|
return { isValid: true }; // property doesn't exist, no need to lint it with this assert
|
|
106
106
|
const values = utils_1.isString(value) ? [value] : value;
|
|
107
|
-
for (
|
|
107
|
+
for (const _val of values) {
|
|
108
108
|
let matchCase = false;
|
|
109
109
|
switch (condition) {
|
|
110
110
|
case 'camelCase':
|
|
@@ -4,7 +4,7 @@ exports.Assertions = void 0;
|
|
|
4
4
|
const asserts_1 = require("./asserts");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const Assertions = (opts) => {
|
|
7
|
-
|
|
7
|
+
const visitors = [];
|
|
8
8
|
// As 'Assertions' has an array of asserts,
|
|
9
9
|
// that array spreads into an 'opts' object on init rules phase here
|
|
10
10
|
// https://github.com/Redocly/redocly-cli/blob/master/packages/core/src/config/config.ts#L311
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NoAmbiguousPaths = void 0;
|
|
4
4
|
const NoAmbiguousPaths = () => {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
PathsMap(pathMap, { report, location }) {
|
|
7
7
|
const seenPaths = [];
|
|
8
8
|
for (const currentPath of Object.keys(pathMap)) {
|
|
9
9
|
const ambiguousPath = seenPaths.find((seenPath) => arePathsAmbiguous(seenPath, currentPath));
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NoIdenticalPaths = void 0;
|
|
4
4
|
const NoIdenticalPaths = () => {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
PathsMap(pathMap, { report, location }) {
|
|
7
7
|
const pathsMap = new Map();
|
|
8
8
|
for (const pathName of Object.keys(pathMap)) {
|
|
9
9
|
const id = pathName.replace(/{.+?}/g, '{VARIABLE}');
|
|
@@ -4,17 +4,17 @@ exports.NoInvalidParameterExamples = void 0;
|
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const NoInvalidParameterExamples = (opts) => {
|
|
6
6
|
var _a;
|
|
7
|
-
const
|
|
7
|
+
const allowAdditionalProperties = (_a = utils_1.getAdditionalPropertiesOption(opts)) !== null && _a !== void 0 ? _a : false;
|
|
8
8
|
return {
|
|
9
9
|
Parameter: {
|
|
10
10
|
leave(parameter, ctx) {
|
|
11
11
|
if (parameter.example) {
|
|
12
|
-
utils_1.validateExample(parameter.example, parameter.schema, ctx.location.child('example'), ctx,
|
|
12
|
+
utils_1.validateExample(parameter.example, parameter.schema, ctx.location.child('example'), ctx, allowAdditionalProperties);
|
|
13
13
|
}
|
|
14
14
|
if (parameter.examples) {
|
|
15
15
|
for (const [key, example] of Object.entries(parameter.examples)) {
|
|
16
16
|
if ('value' in example) {
|
|
17
|
-
utils_1.validateExample(example.value, parameter.schema, ctx.location.child(['examples', key]), ctx,
|
|
17
|
+
utils_1.validateExample(example.value, parameter.schema, ctx.location.child(['examples', key]), ctx, true);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -4,17 +4,17 @@ exports.NoInvalidSchemaExamples = void 0;
|
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const NoInvalidSchemaExamples = (opts) => {
|
|
6
6
|
var _a;
|
|
7
|
-
const
|
|
7
|
+
const allowAdditionalProperties = (_a = utils_1.getAdditionalPropertiesOption(opts)) !== null && _a !== void 0 ? _a : false;
|
|
8
8
|
return {
|
|
9
9
|
Schema: {
|
|
10
10
|
leave(schema, ctx) {
|
|
11
11
|
if (schema.examples) {
|
|
12
12
|
for (const example of schema.examples) {
|
|
13
|
-
utils_1.validateExample(example, schema, ctx.location.child(['examples', schema.examples.indexOf(example)]), ctx,
|
|
13
|
+
utils_1.validateExample(example, schema, ctx.location.child(['examples', schema.examples.indexOf(example)]), ctx, allowAdditionalProperties);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
if (schema.example) {
|
|
17
|
-
utils_1.validateExample(schema.example, schema, ctx.location.child('example'), ctx,
|
|
17
|
+
utils_1.validateExample(schema.example, schema, ctx.location.child('example'), ctx, true);
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
},
|
|
@@ -7,7 +7,7 @@ const Operation2xxResponse = () => {
|
|
|
7
7
|
const codes = Object.keys(responses);
|
|
8
8
|
if (!codes.some((code) => code === 'default' || /2[Xx0-9]{2}/.test(code))) {
|
|
9
9
|
report({
|
|
10
|
-
message: 'Operation must have at least one `
|
|
10
|
+
message: 'Operation must have at least one `2XX` response.',
|
|
11
11
|
location: { reportOnKey: true },
|
|
12
12
|
});
|
|
13
13
|
}
|
|
@@ -7,7 +7,7 @@ const Operation4xxResponse = () => {
|
|
|
7
7
|
const codes = Object.keys(responses);
|
|
8
8
|
if (!codes.some((code) => /4[Xx0-9]{2}/.test(code))) {
|
|
9
9
|
report({
|
|
10
|
-
message: 'Operation must have at least one `
|
|
10
|
+
message: 'Operation must have at least one `4XX` response.',
|
|
11
11
|
location: { reportOnKey: true },
|
|
12
12
|
});
|
|
13
13
|
}
|
|
@@ -4,7 +4,7 @@ exports.OperationOperationId = void 0;
|
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const OperationOperationId = () => {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
Root: {
|
|
8
8
|
PathItem: {
|
|
9
9
|
Operation(operation, ctx) {
|
|
10
10
|
utils_1.validateDefinedAndNonEmpty('operationId', operation, ctx);
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PathNotIncludeQuery = void 0;
|
|
4
4
|
const PathNotIncludeQuery = () => {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
PathsMap: {
|
|
7
7
|
PathItem(_operation, { report, key }) {
|
|
8
8
|
if (key.toString().includes('?')) {
|
|
9
9
|
report({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
exports.SecurityDefined = void 0;
|
|
4
|
+
const SecurityDefined = () => {
|
|
5
|
+
const referencedSchemes = new Map();
|
|
6
|
+
let eachOperationHasSecurity = true;
|
|
6
7
|
return {
|
|
7
8
|
DefinitionRoot: {
|
|
8
|
-
leave(
|
|
9
|
+
leave(root, { report }) {
|
|
9
10
|
for (const [name, scheme] of referencedSchemes.entries()) {
|
|
10
11
|
if (scheme.defined)
|
|
11
12
|
continue;
|
|
@@ -16,6 +17,14 @@ const OperationSecurityDefined = () => {
|
|
|
16
17
|
});
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
if (root.security || eachOperationHasSecurity) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
report({
|
|
25
|
+
message: `Every API should have security defined on the root level or for each operation.`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
19
28
|
},
|
|
20
29
|
},
|
|
21
30
|
SecurityScheme(_securityScheme, { key }) {
|
|
@@ -33,6 +42,11 @@ const OperationSecurityDefined = () => {
|
|
|
33
42
|
}
|
|
34
43
|
}
|
|
35
44
|
},
|
|
45
|
+
Operation(operation) {
|
|
46
|
+
if (!(operation === null || operation === void 0 ? void 0 : operation.security)) {
|
|
47
|
+
eachOperationHasSecurity = false;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
36
50
|
};
|
|
37
51
|
};
|
|
38
|
-
exports.
|
|
52
|
+
exports.SecurityDefined = SecurityDefined;
|
package/lib/rules/common/spec.js
CHANGED
|
@@ -7,13 +7,15 @@ const ref_utils_1 = require("../../ref-utils");
|
|
|
7
7
|
const utils_2 = require("../../utils");
|
|
8
8
|
const OasSpec = () => {
|
|
9
9
|
return {
|
|
10
|
-
any(node, { report, type, location, key, resolve, ignoreNextVisitorsOnNode }) {
|
|
10
|
+
any(node, { report, type, location, rawLocation, key, resolve, ignoreNextVisitorsOnNode }) {
|
|
11
11
|
var _a, _b, _c, _d;
|
|
12
12
|
const nodeType = utils_1.oasTypeOf(node);
|
|
13
|
+
const refLocation = rawLocation !== location ? rawLocation : undefined;
|
|
13
14
|
if (type.items) {
|
|
14
15
|
if (nodeType !== 'array') {
|
|
15
16
|
report({
|
|
16
17
|
message: `Expected type \`${type.name}\` (array) but got \`${nodeType}\``,
|
|
18
|
+
from: refLocation,
|
|
17
19
|
});
|
|
18
20
|
ignoreNextVisitorsOnNode();
|
|
19
21
|
}
|
|
@@ -22,15 +24,17 @@ const OasSpec = () => {
|
|
|
22
24
|
else if (nodeType !== 'object') {
|
|
23
25
|
report({
|
|
24
26
|
message: `Expected type \`${type.name}\` (object) but got \`${nodeType}\``,
|
|
27
|
+
from: refLocation,
|
|
25
28
|
});
|
|
26
29
|
ignoreNextVisitorsOnNode();
|
|
27
30
|
return;
|
|
28
31
|
}
|
|
29
32
|
const required = typeof type.required === 'function' ? type.required(node, key) : type.required;
|
|
30
|
-
for (
|
|
33
|
+
for (const propName of required || []) {
|
|
31
34
|
if (!node.hasOwnProperty(propName)) {
|
|
32
35
|
report({
|
|
33
36
|
message: `The field \`${propName}\` must be present on this level.`,
|
|
37
|
+
from: refLocation,
|
|
34
38
|
location: [{ reportOnKey: true }],
|
|
35
39
|
});
|
|
36
40
|
}
|
|
@@ -45,6 +49,7 @@ const OasSpec = () => {
|
|
|
45
49
|
}
|
|
46
50
|
report({
|
|
47
51
|
message: `The field \`${propName}\` is not allowed here.`,
|
|
52
|
+
from: refLocation,
|
|
48
53
|
location: location.child([propName]).key(),
|
|
49
54
|
});
|
|
50
55
|
}
|
|
@@ -52,7 +57,7 @@ const OasSpec = () => {
|
|
|
52
57
|
const requiredOneOf = type.requiredOneOf || null;
|
|
53
58
|
if (requiredOneOf) {
|
|
54
59
|
let hasProperty = false;
|
|
55
|
-
for (
|
|
60
|
+
for (const propName of requiredOneOf || []) {
|
|
56
61
|
if (node.hasOwnProperty(propName)) {
|
|
57
62
|
hasProperty = true;
|
|
58
63
|
}
|
|
@@ -60,6 +65,7 @@ const OasSpec = () => {
|
|
|
60
65
|
if (!hasProperty)
|
|
61
66
|
report({
|
|
62
67
|
message: `Must contain at least one of the following fields: ${(_b = type.requiredOneOf) === null || _b === void 0 ? void 0 : _b.join(', ')}.`,
|
|
68
|
+
from: refLocation,
|
|
63
69
|
location: [{ reportOnKey: true }],
|
|
64
70
|
});
|
|
65
71
|
}
|
|
@@ -82,6 +88,7 @@ const OasSpec = () => {
|
|
|
82
88
|
report({
|
|
83
89
|
message: `Property \`${propName}\` is not expected here.`,
|
|
84
90
|
suggest: utils_1.getSuggest(propName, Object.keys(type.properties)),
|
|
91
|
+
from: refLocation,
|
|
85
92
|
location: propLocation.key(),
|
|
86
93
|
});
|
|
87
94
|
continue;
|
|
@@ -99,6 +106,7 @@ const OasSpec = () => {
|
|
|
99
106
|
message: `\`${propName}\` can be one of the following only: ${propSchema.enum
|
|
100
107
|
.map((i) => `"${i}"`)
|
|
101
108
|
.join(', ')}.`,
|
|
109
|
+
from: refLocation,
|
|
102
110
|
suggest: utils_1.getSuggest(propValue, propSchema.enum),
|
|
103
111
|
});
|
|
104
112
|
}
|
|
@@ -106,6 +114,7 @@ const OasSpec = () => {
|
|
|
106
114
|
else if (propSchema.type && !utils_1.matchesJsonSchemaType(propValue, propSchema.type, false)) {
|
|
107
115
|
report({
|
|
108
116
|
message: `Expected type \`${propSchema.type}\` but got \`${propValueType}\`.`,
|
|
117
|
+
from: refLocation,
|
|
109
118
|
location: propLocation,
|
|
110
119
|
});
|
|
111
120
|
}
|
|
@@ -116,6 +125,7 @@ const OasSpec = () => {
|
|
|
116
125
|
if (!utils_1.matchesJsonSchemaType(item, itemsType, false)) {
|
|
117
126
|
report({
|
|
118
127
|
message: `Expected type \`${itemsType}\` but got \`${utils_1.oasTypeOf(item)}\`.`,
|
|
128
|
+
from: refLocation,
|
|
119
129
|
location: propLocation.child([i]),
|
|
120
130
|
});
|
|
121
131
|
}
|
|
@@ -125,6 +135,7 @@ const OasSpec = () => {
|
|
|
125
135
|
if (propSchema.minimum > node[propName]) {
|
|
126
136
|
report({
|
|
127
137
|
message: `The value of the ${propName} field must be greater than or equal to ${propSchema.minimum}`,
|
|
138
|
+
from: refLocation,
|
|
128
139
|
location: location.child([propName]),
|
|
129
140
|
});
|
|
130
141
|
}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TagsAlphabetical = void 0;
|
|
4
4
|
const TagsAlphabetical = () => {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
Root(root, { report, location }) {
|
|
7
7
|
if (!root.tags)
|
|
8
8
|
return;
|
|
9
9
|
for (let i = 0; i < root.tags.length - 1; i++) {
|
|
@@ -29,7 +29,7 @@ export declare const rules: {
|
|
|
29
29
|
'path-params-defined': Oas2Rule;
|
|
30
30
|
'parameter-description': Oas2Rule;
|
|
31
31
|
'operation-singular-tag': Oas2Rule;
|
|
32
|
-
'
|
|
32
|
+
'security-defined': Oas2Rule;
|
|
33
33
|
'no-unresolved-refs': Oas2Rule;
|
|
34
34
|
'no-identical-paths': Oas2Rule;
|
|
35
35
|
'no-ambiguous-paths': Oas2Rule;
|
package/lib/rules/oas2/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const operation_description_1 = require("../common/operation-description");
|
|
|
27
27
|
const path_not_include_query_1 = require("../common/path-not-include-query");
|
|
28
28
|
const parameter_description_1 = require("../common/parameter-description");
|
|
29
29
|
const operation_singular_tag_1 = require("../common/operation-singular-tag");
|
|
30
|
-
const
|
|
30
|
+
const security_defined_1 = require("../common/security-defined");
|
|
31
31
|
const no_unresolved_refs_1 = require("../no-unresolved-refs");
|
|
32
32
|
const path_http_verbs_order_1 = require("../common/path-http-verbs-order");
|
|
33
33
|
const no_identical_paths_1 = require("../common/no-identical-paths");
|
|
@@ -72,7 +72,7 @@ exports.rules = {
|
|
|
72
72
|
'path-params-defined': path_params_defined_1.PathParamsDefined,
|
|
73
73
|
'parameter-description': parameter_description_1.ParameterDescription,
|
|
74
74
|
'operation-singular-tag': operation_singular_tag_1.OperationSingularTag,
|
|
75
|
-
'
|
|
75
|
+
'security-defined': security_defined_1.SecurityDefined,
|
|
76
76
|
'no-unresolved-refs': no_unresolved_refs_1.NoUnresolvedRefs,
|
|
77
77
|
'no-identical-paths': no_identical_paths_1.NoIdenticalPaths,
|
|
78
78
|
'no-ambiguous-paths': no_ambiguous_paths_1.NoAmbiguousPaths,
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RemoveUnusedComponents = void 0;
|
|
4
4
|
const utils_1 = require("../../utils");
|
|
5
5
|
const RemoveUnusedComponents = () => {
|
|
6
|
-
|
|
6
|
+
const components = new Map();
|
|
7
7
|
function registerComponent(location, componentType, name) {
|
|
8
8
|
var _a;
|
|
9
9
|
components.set(location.absolutePointer, {
|
|
@@ -26,11 +26,11 @@ const RemoveUnusedComponents = () => {
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
Root: {
|
|
30
30
|
leave(root, ctx) {
|
|
31
31
|
const data = ctx.getVisitorData();
|
|
32
32
|
data.removedCount = 0;
|
|
33
|
-
|
|
33
|
+
const rootComponents = new Set();
|
|
34
34
|
components.forEach((usageInfo) => {
|
|
35
35
|
const { used, name, componentType } = usageInfo;
|
|
36
36
|
if (!used && componentType) {
|
|
@@ -4,7 +4,7 @@ exports.RequestMimeType = void 0;
|
|
|
4
4
|
const utils_1 = require("../../utils");
|
|
5
5
|
const RequestMimeType = ({ allowedValues }) => {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
Root(root, ctx) {
|
|
8
8
|
utils_1.validateMimeType({ type: 'consumes', value: root }, ctx, allowedValues);
|
|
9
9
|
},
|
|
10
10
|
Operation: {
|
|
@@ -4,7 +4,7 @@ exports.ResponseMimeType = void 0;
|
|
|
4
4
|
const utils_1 = require("../../utils");
|
|
5
5
|
const ResponseMimeType = ({ allowedValues }) => {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
Root(root, ctx) {
|
|
8
8
|
utils_1.validateMimeType({ type: 'produces', value: root }, ctx, allowedValues);
|
|
9
9
|
},
|
|
10
10
|
Operation: {
|
package/lib/rules/oas3/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const no_unused_components_1 = require("./no-unused-components");
|
|
|
27
27
|
const path_not_include_query_1 = require("../common/path-not-include-query");
|
|
28
28
|
const parameter_description_1 = require("../common/parameter-description");
|
|
29
29
|
const operation_singular_tag_1 = require("../common/operation-singular-tag");
|
|
30
|
-
const
|
|
30
|
+
const security_defined_1 = require("../common/security-defined");
|
|
31
31
|
const no_unresolved_refs_1 = require("../no-unresolved-refs");
|
|
32
32
|
const boolean_parameter_prefixes_1 = require("./boolean-parameter-prefixes");
|
|
33
33
|
const paths_kebab_case_1 = require("../common/paths-kebab-case");
|
|
@@ -39,7 +39,7 @@ const no_undefined_server_variable_1 = require("./no-undefined-server-variable")
|
|
|
39
39
|
const operation_operationId_1 = require("../common/operation-operationId");
|
|
40
40
|
const operation_summary_1 = require("../common/operation-summary");
|
|
41
41
|
const no_ambiguous_paths_1 = require("../common/no-ambiguous-paths");
|
|
42
|
-
const
|
|
42
|
+
const no_server_variables_empty_enum_1 = require("./no-server-variables-empty-enum");
|
|
43
43
|
const no_http_verbs_in_paths_1 = require("../common/no-http-verbs-in-paths");
|
|
44
44
|
const request_mime_type_1 = require("./request-mime-type");
|
|
45
45
|
const response_mime_type_1 = require("./response-mime-type");
|
|
@@ -50,6 +50,8 @@ const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-
|
|
|
50
50
|
const response_contains_header_1 = require("../common/response-contains-header");
|
|
51
51
|
const response_contains_property_1 = require("./response-contains-property");
|
|
52
52
|
const scalar_property_missing_example_1 = require("../common/scalar-property-missing-example");
|
|
53
|
+
const spec_components_invalid_map_name_1 = require("./spec-components-invalid-map-name");
|
|
54
|
+
const operation_4xx_problem_details_rfc7807_1 = require("./operation-4xx-problem-details-rfc7807");
|
|
53
55
|
exports.rules = {
|
|
54
56
|
spec: spec_1.OasSpec,
|
|
55
57
|
'info-description': info_description_1.InfoDescription,
|
|
@@ -58,6 +60,7 @@ exports.rules = {
|
|
|
58
60
|
'info-license-url': info_license_url_1.InfoLicenseUrl,
|
|
59
61
|
'operation-2xx-response': operation_2xx_response_1.Operation2xxResponse,
|
|
60
62
|
'operation-4xx-response': operation_4xx_response_1.Operation4xxResponse,
|
|
63
|
+
'operation-4xx-problem-details-rfc7807': operation_4xx_problem_details_rfc7807_1.Operation4xxProblemDetailsRfc7807,
|
|
61
64
|
assertions: assertions_1.Assertions,
|
|
62
65
|
'operation-operationId-unique': operation_operationId_unique_1.OperationIdUnique,
|
|
63
66
|
'operation-parameters-unique': operation_parameters_unique_1.OperationParametersUnique,
|
|
@@ -81,7 +84,7 @@ exports.rules = {
|
|
|
81
84
|
'path-params-defined': path_params_defined_1.PathParamsDefined,
|
|
82
85
|
'parameter-description': parameter_description_1.ParameterDescription,
|
|
83
86
|
'operation-singular-tag': operation_singular_tag_1.OperationSingularTag,
|
|
84
|
-
'
|
|
87
|
+
'security-defined': security_defined_1.SecurityDefined,
|
|
85
88
|
'no-unresolved-refs': no_unresolved_refs_1.NoUnresolvedRefs,
|
|
86
89
|
'paths-kebab-case': paths_kebab_case_1.PathsKebabCase,
|
|
87
90
|
'boolean-parameter-prefixes': boolean_parameter_prefixes_1.BooleanParameterPrefixes,
|
|
@@ -90,7 +93,7 @@ exports.rules = {
|
|
|
90
93
|
'no-identical-paths': no_identical_paths_1.NoIdenticalPaths,
|
|
91
94
|
'no-ambiguous-paths': no_ambiguous_paths_1.NoAmbiguousPaths,
|
|
92
95
|
'no-undefined-server-variable': no_undefined_server_variable_1.NoUndefinedServerVariable,
|
|
93
|
-
'no-
|
|
96
|
+
'no-server-variables-empty-enum': no_server_variables_empty_enum_1.NoServerVariablesEmptyEnum,
|
|
94
97
|
'no-http-verbs-in-paths': no_http_verbs_in_paths_1.NoHttpVerbsInPaths,
|
|
95
98
|
'path-excludes-patterns': path_excludes_patterns_1.PathExcludesPatterns,
|
|
96
99
|
'request-mime-type': request_mime_type_1.RequestMimeType,
|
|
@@ -101,5 +104,6 @@ exports.rules = {
|
|
|
101
104
|
'response-contains-header': response_contains_header_1.ResponseContainsHeader,
|
|
102
105
|
'response-contains-property': response_contains_property_1.ResponseContainsProperty,
|
|
103
106
|
'scalar-property-missing-example': scalar_property_missing_example_1.ScalarPropertyMissingExample,
|
|
107
|
+
'spec-components-invalid-map-name': spec_components_invalid_map_name_1.SpecComponentsInvalidMapName,
|
|
104
108
|
};
|
|
105
109
|
exports.preprocessors = {};
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NoEmptyServers = void 0;
|
|
4
4
|
const NoEmptyServers = () => {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
Root(root, { report, location }) {
|
|
7
7
|
if (!root.hasOwnProperty('servers')) {
|
|
8
8
|
report({
|
|
9
9
|
message: 'Servers must be present.',
|
|
@@ -5,7 +5,7 @@ const ref_utils_1 = require("../../ref-utils");
|
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const ValidContentExamples = (opts) => {
|
|
7
7
|
var _a;
|
|
8
|
-
const
|
|
8
|
+
const allowAdditionalProperties = (_a = utils_1.getAdditionalPropertiesOption(opts)) !== null && _a !== void 0 ? _a : false;
|
|
9
9
|
return {
|
|
10
10
|
MediaType: {
|
|
11
11
|
leave(mediaType, ctx) {
|
|
@@ -28,7 +28,7 @@ const ValidContentExamples = (opts) => {
|
|
|
28
28
|
location = isMultiple ? resolved.location.child('value') : resolved.location;
|
|
29
29
|
example = resolved.node;
|
|
30
30
|
}
|
|
31
|
-
utils_1.validateExample(isMultiple ? example.value : example, mediaType.schema, location, ctx,
|
|
31
|
+
utils_1.validateExample(isMultiple ? example.value : example, mediaType.schema, location, ctx, allowAdditionalProperties);
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
},
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.NoServerVariablesEmptyEnum = void 0;
|
|
4
4
|
var enumError;
|
|
5
5
|
(function (enumError) {
|
|
6
6
|
enumError["empty"] = "empty";
|
|
7
7
|
enumError["invalidDefaultValue"] = "invalidDefaultValue";
|
|
8
8
|
})(enumError || (enumError = {}));
|
|
9
|
-
const
|
|
9
|
+
const NoServerVariablesEmptyEnum = () => {
|
|
10
10
|
return {
|
|
11
|
-
|
|
11
|
+
Root(root, { report, location }) {
|
|
12
12
|
if (!root.servers || root.servers.length === 0)
|
|
13
13
|
return;
|
|
14
14
|
const invalidVariables = [];
|
|
@@ -43,13 +43,13 @@ const NoEmptyEnumServers = () => {
|
|
|
43
43
|
},
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
|
-
exports.
|
|
46
|
+
exports.NoServerVariablesEmptyEnum = NoServerVariablesEmptyEnum;
|
|
47
47
|
function checkEnumVariables(server) {
|
|
48
48
|
var _a;
|
|
49
49
|
if (server.variables && Object.keys(server.variables).length === 0)
|
|
50
50
|
return;
|
|
51
51
|
const errors = [];
|
|
52
|
-
for (
|
|
52
|
+
for (const variable in server.variables) {
|
|
53
53
|
const serverVariable = server.variables[variable];
|
|
54
54
|
if (!serverVariable.enum)
|
|
55
55
|
continue;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NoUnusedComponents = void 0;
|
|
4
4
|
const NoUnusedComponents = () => {
|
|
5
|
-
|
|
5
|
+
const components = new Map();
|
|
6
6
|
function registerComponent(location, name) {
|
|
7
7
|
var _a;
|
|
8
8
|
components.set(location.absolutePointer, {
|
|
@@ -24,7 +24,7 @@ const NoUnusedComponents = () => {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
-
|
|
27
|
+
Root: {
|
|
28
28
|
leave(_, { report }) {
|
|
29
29
|
components.forEach((usageInfo) => {
|
|
30
30
|
if (!usageInfo.used) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Operation4xxProblemDetailsRfc7807 = void 0;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
/**
|
|
6
|
+
* Validation according rfc7807 - https://datatracker.ietf.org/doc/html/rfc7807
|
|
7
|
+
*/
|
|
8
|
+
const Operation4xxProblemDetailsRfc7807 = () => {
|
|
9
|
+
return {
|
|
10
|
+
Response: {
|
|
11
|
+
skip(_response, key) {
|
|
12
|
+
return !/4[Xx0-9]{2}/.test(`${key}`);
|
|
13
|
+
},
|
|
14
|
+
enter(response, { report, location }) {
|
|
15
|
+
if (!response.content || !response.content['application/problem+json'])
|
|
16
|
+
report({
|
|
17
|
+
message: 'Response `4xx` must have content-type `application/problem+json`.',
|
|
18
|
+
location: location.key(),
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
MediaType: {
|
|
22
|
+
skip(_response, key) {
|
|
23
|
+
return key !== 'application/problem+json';
|
|
24
|
+
},
|
|
25
|
+
enter(media, ctx) {
|
|
26
|
+
utils_1.validateDefinedAndNonEmpty('schema', media, ctx);
|
|
27
|
+
},
|
|
28
|
+
SchemaProperties(schema, ctx) {
|
|
29
|
+
utils_1.validateDefinedAndNonEmpty('type', schema, ctx);
|
|
30
|
+
utils_1.validateDefinedAndNonEmpty('title', schema, ctx);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.Operation4xxProblemDetailsRfc7807 = Operation4xxProblemDetailsRfc7807;
|