@redocly/openapi-core 1.0.0-beta.108 → 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/resolve-with-no-external.bench.js +1 -1
- package/lib/bundle.d.ts +1 -1
- package/lib/bundle.js +4 -4
- package/lib/config/all.js +3 -1
- package/lib/config/config-resolvers.js +1 -1
- package/lib/config/minimal.js +3 -1
- package/lib/config/recommended.js +3 -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 +42 -4
- package/lib/decorators/common/registry-dependencies.js +1 -1
- package/lib/format/format.d.ts +1 -1
- package/lib/format/format.js +22 -1
- package/lib/lint.js +2 -2
- package/lib/redocly/registry-api.d.ts +0 -1
- package/lib/redocly/registry-api.js +5 -4
- package/lib/resolve.js +3 -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/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} +18 -4
- package/lib/rules/common/spec.js +12 -1
- 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 +1 -1
- 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 +6 -2
- package/lib/rules/oas3/no-empty-servers.js +1 -1
- package/lib/rules/oas3/no-server-variables-empty-enum.js +1 -1
- package/lib/rules/oas3/no-unused-components.js +1 -1
- 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 +1 -1
- 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/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 +46 -55
- package/lib/utils.d.ts +3 -3
- package/lib/utils.js +5 -5
- package/lib/visitors.d.ts +11 -11
- package/lib/visitors.js +13 -1
- package/package.json +1 -1
- 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__/resolve-http.test.ts +1 -1
- package/src/__tests__/resolve.test.ts +9 -9
- package/src/__tests__/walk.test.ts +78 -10
- package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
- package/src/bundle.ts +4 -4
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +6 -2
- 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 +12 -15
- package/src/config/__tests__/utils.test.ts +64 -4
- package/src/config/all.ts +3 -1
- package/src/config/config-resolvers.ts +2 -2
- package/src/config/load.ts +3 -2
- package/src/config/minimal.ts +3 -1
- package/src/config/recommended.ts +3 -1
- package/src/config/rules.ts +2 -2
- package/src/config/types.ts +11 -0
- package/src/config/utils.ts +102 -13
- package/src/decorators/common/registry-dependencies.ts +1 -1
- package/src/format/format.ts +32 -2
- package/src/lint.ts +2 -2
- package/src/redocly/registry-api.ts +5 -4
- package/src/resolve.ts +3 -1
- package/src/rules/__tests__/utils.test.ts +1 -1
- 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/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-identical-paths.ts +1 -1
- 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} +19 -4
- package/src/rules/common/spec.ts +15 -1
- 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 +1 -1
- 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__/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 +6 -2
- package/src/rules/oas3/no-empty-servers.ts +1 -1
- package/src/rules/oas3/no-server-variables-empty-enum.ts +1 -1
- package/src/rules/oas3/no-unused-components.ts +1 -1
- package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +36 -0
- package/src/rules/oas3/remove-unused-components.ts +1 -1
- 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/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 +52 -40
- package/src/utils.ts +11 -7
- package/src/visitors.ts +29 -13
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/common/operation-security-defined.d.ts +0 -2
- package/src/rules/common/__tests__/operation-security-defined.test.ts +0 -69
package/lib/utils.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare function pushStack<T, P extends Stack<T> = Stack<T>>(head: P, val
|
|
|
14
14
|
export declare function popStack<T, P extends Stack<T>>(head: P): StackFrame<T> | null;
|
|
15
15
|
export declare type BundleOutputFormat = 'json' | 'yml' | 'yaml';
|
|
16
16
|
export declare function loadYaml<T>(filename: string): Promise<T>;
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function isDefined<T>(x: T | undefined): x is T;
|
|
18
18
|
export declare function isPlainObject(value: any): value is object;
|
|
19
19
|
export declare function isEmptyObject(value: any): value is object;
|
|
20
20
|
export declare function isEmptyArray(value: any): boolean;
|
|
@@ -41,8 +41,8 @@ export declare function assignExisting<T>(target: Record<string, T>, obj: Record
|
|
|
41
41
|
export declare function getMatchingStatusCodeRange(code: number | string): string;
|
|
42
42
|
export declare function isCustomRuleId(id: string): boolean;
|
|
43
43
|
export declare function doesYamlFileExist(filePath: string): boolean;
|
|
44
|
-
export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField
|
|
45
|
-
export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField
|
|
44
|
+
export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField?: string): void;
|
|
45
|
+
export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField?: string): void;
|
|
46
46
|
export declare type Falsy = undefined | null | false | '' | 0;
|
|
47
47
|
export declare function isTruthy<Truthy>(value: Truthy | Falsy): value is Truthy;
|
|
48
48
|
export declare function identity<T>(value: T): T;
|
package/lib/utils.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.identity = exports.isTruthy = exports.showErrorForDeprecatedField = exports.showWarningForDeprecatedField = exports.doesYamlFileExist = exports.isCustomRuleId = exports.getMatchingStatusCodeRange = exports.assignExisting = exports.isNotString = exports.isString = exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.
|
|
12
|
+
exports.identity = exports.isTruthy = exports.showErrorForDeprecatedField = exports.showWarningForDeprecatedField = exports.doesYamlFileExist = exports.isCustomRuleId = exports.getMatchingStatusCodeRange = exports.assignExisting = exports.isNotString = exports.isString = exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.isDefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
13
13
|
const fs = require("fs");
|
|
14
14
|
const path_1 = require("path");
|
|
15
15
|
const minimatch = require("minimatch");
|
|
@@ -37,10 +37,10 @@ function loadYaml(filename) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
exports.loadYaml = loadYaml;
|
|
40
|
-
function
|
|
40
|
+
function isDefined(x) {
|
|
41
41
|
return x !== undefined;
|
|
42
42
|
}
|
|
43
|
-
exports.
|
|
43
|
+
exports.isDefined = isDefined;
|
|
44
44
|
function isPlainObject(value) {
|
|
45
45
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
46
46
|
}
|
|
@@ -190,11 +190,11 @@ function doesYamlFileExist(filePath) {
|
|
|
190
190
|
}
|
|
191
191
|
exports.doesYamlFileExist = doesYamlFileExist;
|
|
192
192
|
function showWarningForDeprecatedField(deprecatedField, updatedField) {
|
|
193
|
-
logger_1.logger.warn(`The ${logger_1.colorize.red(deprecatedField)} field is deprecated. Use ${logger_1.colorize.green(updatedField)} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
|
|
193
|
+
logger_1.logger.warn(`The '${logger_1.colorize.red(deprecatedField)}' field is deprecated. ${updatedField ? `Use ${logger_1.colorize.green(updatedField)} instead. ` : ''}Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
|
|
194
194
|
}
|
|
195
195
|
exports.showWarningForDeprecatedField = showWarningForDeprecatedField;
|
|
196
196
|
function showErrorForDeprecatedField(deprecatedField, updatedField) {
|
|
197
|
-
throw new Error(`Do not use '${deprecatedField}' field. Use '${updatedField}' instead
|
|
197
|
+
throw new Error(`Do not use '${deprecatedField}' field. ${updatedField ? `Use '${updatedField}' instead. ` : ''}\n`);
|
|
198
198
|
}
|
|
199
199
|
exports.showErrorForDeprecatedField = showErrorForDeprecatedField;
|
|
200
200
|
function isTruthy(value) {
|
package/lib/visitors.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Oas3Definition, Oas3ExternalDocs, Oas3Info, Oas3Contact, Oas3Components, Oas3License, Oas3Schema, Oas3Header, Oas3Parameter, Oas3Operation, Oas3PathItem, Oas3ServerVariable, Oas3Server, Oas3MediaType, Oas3Response, Oas3Example, Oas3RequestBody, Oas3Tag, OasRef, Oas3SecurityScheme, Oas3SecurityRequirement, Oas3Encoding, Oas3Link, Oas3Xml, Oas3Discriminator, Oas3Callback } from './typings/openapi';
|
|
2
|
-
import { Oas2Definition, Oas2Tag, Oas2ExternalDocs, Oas2SecurityRequirement, Oas2Info, Oas2Contact, Oas2License, Oas2PathItem, Oas2Operation, Oas2Header, Oas2Response, Oas2Schema, Oas2Xml, Oas2Parameter, Oas2SecurityScheme } from './typings/swagger';
|
|
3
|
-
import { NormalizedNodeType } from './types';
|
|
4
|
-
import { Stack } from './utils';
|
|
5
|
-
import { UserContext, ResolveResult, ProblemSeverity } from './walk';
|
|
6
|
-
import { Location } from './ref-utils';
|
|
2
|
+
import type { Oas2Definition, Oas2Tag, Oas2ExternalDocs, Oas2SecurityRequirement, Oas2Info, Oas2Contact, Oas2License, Oas2PathItem, Oas2Operation, Oas2Header, Oas2Response, Oas2Schema, Oas2Xml, Oas2Parameter, Oas2SecurityScheme } from './typings/swagger';
|
|
3
|
+
import type { NormalizedNodeType } from './types';
|
|
4
|
+
import type { Stack } from './utils';
|
|
5
|
+
import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
|
|
6
|
+
import type { Location } from './ref-utils';
|
|
7
7
|
export declare type VisitFunction<T> = (node: T, ctx: UserContext & {
|
|
8
8
|
ignoreNextVisitorsOnNode: () => void;
|
|
9
9
|
}, parents?: any, context?: any) => void;
|
|
@@ -61,7 +61,7 @@ export declare type BaseVisitor = {
|
|
|
61
61
|
} | VisitRefFunction;
|
|
62
62
|
};
|
|
63
63
|
declare type Oas3FlatVisitor = {
|
|
64
|
-
|
|
64
|
+
Root?: VisitFunctionOrObject<Oas3Definition>;
|
|
65
65
|
Tag?: VisitFunctionOrObject<Oas3Tag>;
|
|
66
66
|
ExternalDocs?: VisitFunctionOrObject<Oas3ExternalDocs>;
|
|
67
67
|
Server?: VisitFunctionOrObject<Oas3Server>;
|
|
@@ -70,13 +70,13 @@ declare type Oas3FlatVisitor = {
|
|
|
70
70
|
Info?: VisitFunctionOrObject<Oas3Info>;
|
|
71
71
|
Contact?: VisitFunctionOrObject<Oas3Contact>;
|
|
72
72
|
License?: VisitFunctionOrObject<Oas3License>;
|
|
73
|
-
|
|
73
|
+
PathsMap?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
|
|
74
74
|
PathItem?: VisitFunctionOrObject<Oas3PathItem>;
|
|
75
75
|
Callback?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
|
|
76
76
|
Parameter?: VisitFunctionOrObject<Oas3Parameter>;
|
|
77
77
|
Operation?: VisitFunctionOrObject<Oas3Operation>;
|
|
78
78
|
RequestBody?: VisitFunctionOrObject<Oas3RequestBody>;
|
|
79
|
-
|
|
79
|
+
MediaTypesMap?: VisitFunctionOrObject<Record<string, Oas3MediaType>>;
|
|
80
80
|
MediaType?: VisitFunctionOrObject<Oas3MediaType>;
|
|
81
81
|
Example?: VisitFunctionOrObject<Oas3Example>;
|
|
82
82
|
Encoding?: VisitFunctionOrObject<Oas3Encoding>;
|
|
@@ -107,14 +107,14 @@ declare type Oas3FlatVisitor = {
|
|
|
107
107
|
SecurityScheme?: VisitFunctionOrObject<Oas3SecurityScheme>;
|
|
108
108
|
};
|
|
109
109
|
declare type Oas2FlatVisitor = {
|
|
110
|
-
|
|
110
|
+
Root?: VisitFunctionOrObject<Oas2Definition>;
|
|
111
111
|
Tag?: VisitFunctionOrObject<Oas2Tag>;
|
|
112
112
|
ExternalDocs?: VisitFunctionOrObject<Oas2ExternalDocs>;
|
|
113
113
|
SecurityRequirement?: VisitFunctionOrObject<Oas2SecurityRequirement>;
|
|
114
114
|
Info?: VisitFunctionOrObject<Oas2Info>;
|
|
115
115
|
Contact?: VisitFunctionOrObject<Oas2Contact>;
|
|
116
116
|
License?: VisitFunctionOrObject<Oas2License>;
|
|
117
|
-
|
|
117
|
+
PathsMap?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
|
|
118
118
|
PathItem?: VisitFunctionOrObject<Oas2PathItem>;
|
|
119
119
|
Parameter?: VisitFunctionOrObject<any>;
|
|
120
120
|
Operation?: VisitFunctionOrObject<Oas2Operation>;
|
|
@@ -140,7 +140,7 @@ export declare type Oas3Visitor = BaseVisitor & Oas3NestedVisitor & Record<strin
|
|
|
140
140
|
export declare type Oas2Visitor = BaseVisitor & Oas2NestedVisitor & Record<string, VisitFunction<any> | NestedVisitObject<any, Oas2NestedVisitor>>;
|
|
141
141
|
export declare type Oas3TransformVisitor = BaseVisitor & Oas3FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
|
|
142
142
|
export declare type Oas2TransformVisitor = BaseVisitor & Oas2FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
|
|
143
|
-
export declare type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | '
|
|
143
|
+
export declare type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'Root'>;
|
|
144
144
|
export declare type NormalizedOasVisitors<T extends BaseVisitor> = {
|
|
145
145
|
[V in keyof T]-?: {
|
|
146
146
|
enter: Array<NormalizeVisitor<T[V]>>;
|
package/lib/visitors.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeVisitors = void 0;
|
|
4
|
+
const legacyTypesMap = {
|
|
5
|
+
Root: 'DefinitionRoot',
|
|
6
|
+
ServerVariablesMap: 'ServerVariableMap',
|
|
7
|
+
PathsMap: 'PathMap',
|
|
8
|
+
CallbacksMap: 'CallbackMap',
|
|
9
|
+
MediaTypesMap: 'MediaTypeMap',
|
|
10
|
+
ExamplesMap: 'ExampleMap',
|
|
11
|
+
EncodingsMap: 'EncodingMap',
|
|
12
|
+
HeadersMap: 'HeaderMap',
|
|
13
|
+
LinksMap: 'LinkMap',
|
|
14
|
+
};
|
|
4
15
|
function normalizeVisitors(visitorsConfig, types) {
|
|
5
16
|
const normalizedVisitors = {};
|
|
6
17
|
normalizedVisitors.any = {
|
|
@@ -89,7 +100,8 @@ function normalizeVisitors(visitorsConfig, types) {
|
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
102
|
for (const typeName of visitorKeys) {
|
|
92
|
-
const typeVisitor = visitor[typeName]
|
|
103
|
+
const typeVisitor = (visitor[typeName] ||
|
|
104
|
+
visitor[legacyTypesMap[typeName]]);
|
|
93
105
|
const normalizedTypeVisitor = normalizedVisitors[typeName];
|
|
94
106
|
if (!typeVisitor)
|
|
95
107
|
continue;
|
package/package.json
CHANGED
|
@@ -47,7 +47,7 @@ rootType:
|
|
|
47
47
|
description:
|
|
48
48
|
type: string
|
|
49
49
|
variables:
|
|
50
|
-
name:
|
|
50
|
+
name: ServerVariablesMap
|
|
51
51
|
properties: {}
|
|
52
52
|
required:
|
|
53
53
|
- url
|
|
@@ -94,7 +94,7 @@ rootType:
|
|
|
94
94
|
name: ExternalDocs
|
|
95
95
|
paths:
|
|
96
96
|
properties: {}
|
|
97
|
-
name:
|
|
97
|
+
name: PathsMap
|
|
98
98
|
components:
|
|
99
99
|
properties:
|
|
100
100
|
parameters:
|
|
@@ -132,7 +132,7 @@ rootType:
|
|
|
132
132
|
- openapi
|
|
133
133
|
- paths
|
|
134
134
|
- info
|
|
135
|
-
name:
|
|
135
|
+
name: Root
|
|
136
136
|
refTypes: {}
|
|
137
137
|
visitorsData:
|
|
138
138
|
registry-dependencies:
|
|
@@ -9,10 +9,10 @@ function oas3_0(types) {
|
|
|
9
9
|
parameters: listOf('Parameter'),
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
|
-
|
|
13
|
-
...types.
|
|
12
|
+
Root: {
|
|
13
|
+
...types.Root,
|
|
14
14
|
properties: {
|
|
15
|
-
...types.
|
|
15
|
+
...types.Root.properties,
|
|
16
16
|
'x-webhooks': 'XWebHooks',
|
|
17
17
|
},
|
|
18
18
|
},
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
|
|
3
|
+
import { formatProblems, getTotals } from '../format/format';
|
|
4
|
+
|
|
5
|
+
describe('format', () => {
|
|
6
|
+
function replaceColors(log: string) {
|
|
7
|
+
return log
|
|
8
|
+
.replace(/\x1b\[33m(.*?)\x1b\[39m/g, '<o>$1</o>') // orange
|
|
9
|
+
.replace(/\x1b\[31m(.*?)\x1b\[39m/g, '<r>$1</r>'); // red
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const problems = [
|
|
13
|
+
{
|
|
14
|
+
ruleId: 'spec',
|
|
15
|
+
location: [],
|
|
16
|
+
severity: 'error' as const,
|
|
17
|
+
message: 'message',
|
|
18
|
+
suggest: [],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
ruleId: 'spec',
|
|
22
|
+
location: [],
|
|
23
|
+
severity: 'error' as const,
|
|
24
|
+
message: 'message 2',
|
|
25
|
+
suggest: [],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
ruleId: 'other-rule',
|
|
29
|
+
location: [],
|
|
30
|
+
severity: 'warn' as const,
|
|
31
|
+
message: 'message',
|
|
32
|
+
suggest: [],
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
let output = '';
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
output = '';
|
|
39
|
+
jest.spyOn(process.stderr, 'write').mockImplementation((str: string | Uint8Array) => {
|
|
40
|
+
output += str;
|
|
41
|
+
return true;
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should correctly format summary output', () => {
|
|
46
|
+
formatProblems(problems, {
|
|
47
|
+
format: 'summary',
|
|
48
|
+
version: '1.0.0',
|
|
49
|
+
totals: getTotals(problems),
|
|
50
|
+
color: false,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(output).toMatchInlineSnapshot(`
|
|
54
|
+
"error spec: 2
|
|
55
|
+
warning other-rule: 1
|
|
56
|
+
|
|
57
|
+
"
|
|
58
|
+
`);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should correctly format summary output in color mode', () => {
|
|
62
|
+
formatProblems(problems, {
|
|
63
|
+
format: 'summary',
|
|
64
|
+
version: '1.0.0',
|
|
65
|
+
totals: getTotals(problems),
|
|
66
|
+
color: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(replaceColors(output)).toMatchInlineSnapshot(`
|
|
70
|
+
"<r>error </r> spec: 2
|
|
71
|
+
<o>warning</o> other-rule: 1
|
|
72
|
+
|
|
73
|
+
"
|
|
74
|
+
`);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -12,16 +12,16 @@ describe('lint', () => {
|
|
|
12
12
|
const results = await lintFromString({
|
|
13
13
|
absoluteRef: '/test/spec.yaml',
|
|
14
14
|
source: outdent`
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
openapi: 3.0.0
|
|
16
|
+
info:
|
|
17
|
+
title: Test API
|
|
18
|
+
version: "1.0"
|
|
19
|
+
description: Test
|
|
20
|
+
license: Fail
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
servers:
|
|
23
|
+
- url: http://example.com
|
|
24
|
+
paths: {}
|
|
25
25
|
`,
|
|
26
26
|
config: await loadConfig(),
|
|
27
27
|
});
|
|
@@ -29,6 +29,7 @@ describe('lint', () => {
|
|
|
29
29
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
30
30
|
Array [
|
|
31
31
|
Object {
|
|
32
|
+
"from": undefined,
|
|
32
33
|
"location": Array [
|
|
33
34
|
Object {
|
|
34
35
|
"pointer": "#/info/license",
|
|
@@ -48,8 +49,7 @@ describe('lint', () => {
|
|
|
48
49
|
it('lintConfig should work', async () => {
|
|
49
50
|
const document = parseYamlToDocument(
|
|
50
51
|
outdent`
|
|
51
|
-
|
|
52
|
-
styleguide:
|
|
52
|
+
apis: error string
|
|
53
53
|
plugins:
|
|
54
54
|
- './local-plugin.js'
|
|
55
55
|
extends:
|
|
@@ -60,16 +60,16 @@ describe('lint', () => {
|
|
|
60
60
|
no-invalid-media-type-examples: error
|
|
61
61
|
path-http-verbs-order: error
|
|
62
62
|
boolean-parameter-prefixes: off
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
features.openapi:
|
|
64
|
+
showConsole: true
|
|
65
|
+
layout:
|
|
66
|
+
scope: section
|
|
67
|
+
routingStrategy: browser
|
|
68
|
+
theme:
|
|
69
|
+
rightPanel:
|
|
70
|
+
backgroundColor: '#263238'
|
|
71
|
+
links:
|
|
72
|
+
color: '#6CC496'
|
|
73
73
|
`,
|
|
74
74
|
''
|
|
75
75
|
);
|
|
@@ -78,6 +78,7 @@ describe('lint', () => {
|
|
|
78
78
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
79
79
|
Array [
|
|
80
80
|
Object {
|
|
81
|
+
"from": undefined,
|
|
81
82
|
"location": Array [
|
|
82
83
|
Object {
|
|
83
84
|
"pointer": "#/apis",
|
|
@@ -91,6 +92,7 @@ describe('lint', () => {
|
|
|
91
92
|
"suggest": Array [],
|
|
92
93
|
},
|
|
93
94
|
Object {
|
|
95
|
+
"from": undefined,
|
|
94
96
|
"location": Array [
|
|
95
97
|
Object {
|
|
96
98
|
"pointer": "#/features.openapi/layout",
|
|
@@ -110,10 +112,9 @@ describe('lint', () => {
|
|
|
110
112
|
it('lintConfig should detect wrong fields and suggest correct ones', async () => {
|
|
111
113
|
const document = parseYamlToDocument(
|
|
112
114
|
outdent`
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
syleguide:
|
|
115
|
+
api:
|
|
116
|
+
name@version:
|
|
117
|
+
root: ./file.yaml
|
|
117
118
|
rules:
|
|
118
119
|
operation-2xx-response: warn
|
|
119
120
|
`,
|
|
@@ -124,6 +125,7 @@ describe('lint', () => {
|
|
|
124
125
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
125
126
|
Array [
|
|
126
127
|
Object {
|
|
128
|
+
"from": undefined,
|
|
127
129
|
"location": Array [
|
|
128
130
|
Object {
|
|
129
131
|
"pointer": "#/api",
|
|
@@ -138,21 +140,6 @@ describe('lint', () => {
|
|
|
138
140
|
"apis",
|
|
139
141
|
],
|
|
140
142
|
},
|
|
141
|
-
Object {
|
|
142
|
-
"location": Array [
|
|
143
|
-
Object {
|
|
144
|
-
"pointer": "#/syleguide",
|
|
145
|
-
"reportOnKey": true,
|
|
146
|
-
"source": "",
|
|
147
|
-
},
|
|
148
|
-
],
|
|
149
|
-
"message": "Property \`syleguide\` is not expected here.",
|
|
150
|
-
"ruleId": "configuration spec",
|
|
151
|
-
"severity": "error",
|
|
152
|
-
"suggest": Array [
|
|
153
|
-
"styleguide",
|
|
154
|
-
],
|
|
155
|
-
},
|
|
156
143
|
]
|
|
157
144
|
`);
|
|
158
145
|
});
|
|
@@ -160,13 +147,13 @@ describe('lint', () => {
|
|
|
160
147
|
it('lintConfig should work with legacy fields', async () => {
|
|
161
148
|
const document = parseYamlToDocument(
|
|
162
149
|
outdent`
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
150
|
+
apis:
|
|
151
|
+
entry:
|
|
152
|
+
root: ./file.yaml
|
|
166
153
|
rules:
|
|
167
154
|
operation-2xx-response: warn
|
|
168
|
-
|
|
169
|
-
|
|
155
|
+
referenceDocs:
|
|
156
|
+
showConsole: true
|
|
170
157
|
`,
|
|
171
158
|
''
|
|
172
159
|
);
|
|
@@ -175,16 +162,16 @@ describe('lint', () => {
|
|
|
175
162
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
|
|
176
163
|
});
|
|
177
164
|
|
|
178
|
-
it("'plugins' shouldn't be allowed in 'apis'
|
|
165
|
+
it("'plugins' shouldn't be allowed in 'apis'", async () => {
|
|
179
166
|
const document = parseYamlToDocument(
|
|
180
167
|
outdent`
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
168
|
+
apis:
|
|
169
|
+
main:
|
|
170
|
+
root: ./main.yaml
|
|
171
|
+
plugins:
|
|
184
172
|
- './local-plugin.js'
|
|
185
|
-
styleguide:
|
|
186
173
|
plugins:
|
|
187
|
-
|
|
174
|
+
- './local-plugin.js'
|
|
188
175
|
`,
|
|
189
176
|
''
|
|
190
177
|
);
|
|
@@ -193,22 +180,10 @@ describe('lint', () => {
|
|
|
193
180
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
194
181
|
Array [
|
|
195
182
|
Object {
|
|
183
|
+
"from": undefined,
|
|
196
184
|
"location": Array [
|
|
197
185
|
Object {
|
|
198
|
-
"pointer": "#/apis/
|
|
199
|
-
"reportOnKey": true,
|
|
200
|
-
"source": "",
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
"message": "The field \`root\` must be present on this level.",
|
|
204
|
-
"ruleId": "configuration spec",
|
|
205
|
-
"severity": "error",
|
|
206
|
-
"suggest": Array [],
|
|
207
|
-
},
|
|
208
|
-
Object {
|
|
209
|
-
"location": Array [
|
|
210
|
-
Object {
|
|
211
|
-
"pointer": "#/apis/styleguide/plugins",
|
|
186
|
+
"pointer": "#/apis/main/plugins",
|
|
212
187
|
"reportOnKey": true,
|
|
213
188
|
"source": "",
|
|
214
189
|
},
|
|
@@ -225,31 +200,31 @@ describe('lint', () => {
|
|
|
225
200
|
it("'const' can have any type", async () => {
|
|
226
201
|
const document = parseYamlToDocument(
|
|
227
202
|
outdent`
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
203
|
+
openapi: "3.1.0"
|
|
204
|
+
info:
|
|
205
|
+
version: 1.0.0
|
|
206
|
+
title: Swagger Petstore
|
|
207
|
+
description: Information about Petstore
|
|
208
|
+
license:
|
|
209
|
+
name: MIT
|
|
210
|
+
url: https://opensource.org/licenses/MIT
|
|
211
|
+
servers:
|
|
212
|
+
- url: http://petstore.swagger.io/v1
|
|
213
|
+
paths:
|
|
214
|
+
/pets:
|
|
215
|
+
get:
|
|
216
|
+
summary: List all pets
|
|
217
|
+
operationId: listPets
|
|
218
|
+
tags:
|
|
219
|
+
- pets
|
|
220
|
+
responses:
|
|
221
|
+
200:
|
|
222
|
+
description: An paged array of pets
|
|
223
|
+
content:
|
|
224
|
+
application/json:
|
|
225
|
+
schema:
|
|
226
|
+
type: string
|
|
227
|
+
const: ABC
|
|
253
228
|
`,
|
|
254
229
|
'foobar.yaml'
|
|
255
230
|
);
|
|
@@ -266,8 +241,8 @@ describe('lint', () => {
|
|
|
266
241
|
it('detect OpenAPI should throw an error when version is not string', () => {
|
|
267
242
|
const testDocument = parseYamlToDocument(
|
|
268
243
|
outdent`
|
|
269
|
-
|
|
270
|
-
|
|
244
|
+
openapi: 3.0
|
|
245
|
+
`,
|
|
271
246
|
''
|
|
272
247
|
);
|
|
273
248
|
expect(() => detectOpenAPI(testDocument.parsed)).toThrow(
|
|
@@ -278,28 +253,28 @@ describe('lint', () => {
|
|
|
278
253
|
it("spec rule shouldn't throw an error for named callback", async () => {
|
|
279
254
|
const document = parseYamlToDocument(
|
|
280
255
|
outdent`
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
256
|
+
openapi: 3.1.0
|
|
257
|
+
info:
|
|
258
|
+
title: Callback test
|
|
259
|
+
version: 'alpha'
|
|
260
|
+
components:
|
|
261
|
+
callbacks:
|
|
262
|
+
resultCallback:
|
|
263
|
+
'{$url}':
|
|
264
|
+
post:
|
|
265
|
+
requestBody:
|
|
266
|
+
description: Callback payload
|
|
267
|
+
content:
|
|
268
|
+
'application/json':
|
|
269
|
+
schema:
|
|
270
|
+
type: object
|
|
271
|
+
properties:
|
|
272
|
+
test:
|
|
273
|
+
type: string
|
|
274
|
+
responses:
|
|
275
|
+
'200':
|
|
276
|
+
description: callback successfully processed
|
|
277
|
+
`,
|
|
303
278
|
'foobar.yaml'
|
|
304
279
|
);
|
|
305
280
|
|
|
@@ -316,23 +291,23 @@ describe('lint', () => {
|
|
|
316
291
|
const absoluteRef = path.join(__dirname, 'fixtures/openapi.yaml');
|
|
317
292
|
const document = parseYamlToDocument(
|
|
318
293
|
outdent`
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
294
|
+
openapi: 3.0.0
|
|
295
|
+
info:
|
|
296
|
+
version: 1.0.0
|
|
297
|
+
title: Example OpenAPI 3 definition.
|
|
298
|
+
description: Information about API
|
|
299
|
+
license:
|
|
300
|
+
name: MIT
|
|
301
|
+
url: 'https://opensource.org/licenses/MIT'
|
|
302
|
+
servers:
|
|
303
|
+
- url: 'https://redocly.com/v1'
|
|
304
|
+
paths:
|
|
305
|
+
'/pets/{petId}':
|
|
306
|
+
post:
|
|
307
|
+
responses:
|
|
308
|
+
'201':
|
|
309
|
+
summary: Exist
|
|
310
|
+
description: example description
|
|
336
311
|
`,
|
|
337
312
|
absoluteRef
|
|
338
313
|
);
|