@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
|
@@ -16,7 +16,7 @@ function measureAsync() {
|
|
|
16
16
|
return resolve_1.resolveDocument({
|
|
17
17
|
rootDocument: rebillyDocument,
|
|
18
18
|
externalRefResolver,
|
|
19
|
-
rootType: types_1.normalizeTypes(oas3_1.Oas3Types).
|
|
19
|
+
rootType: types_1.normalizeTypes(oas3_1.Oas3Types).Root,
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
exports.measureAsync = measureAsync;
|
package/lib/bundle.d.ts
CHANGED
|
@@ -44,4 +44,4 @@ export declare function bundleDocument(opts: {
|
|
|
44
44
|
refTypes: Map<string, NormalizedNodeType> | undefined;
|
|
45
45
|
visitorsData: Record<string, Record<string, unknown>>;
|
|
46
46
|
}>;
|
|
47
|
-
export declare function mapTypeToComponent(typeName: string, version: OasMajorVersion): "headers" | "definitions" | "parameters" | "examples" | "responses" | "schemas" | "requestBodies" | "
|
|
47
|
+
export declare function mapTypeToComponent(typeName: string, version: OasMajorVersion): "headers" | "definitions" | "parameters" | "examples" | "responses" | "schemas" | "requestBodies" | "links" | "callbacks" | "securitySchemes" | null;
|
package/lib/bundle.js
CHANGED
|
@@ -76,7 +76,7 @@ function bundleDocument(opts) {
|
|
|
76
76
|
}
|
|
77
77
|
const resolvedRefMap = yield resolve_1.resolveDocument({
|
|
78
78
|
rootDocument: document,
|
|
79
|
-
rootType: types.
|
|
79
|
+
rootType: types.Root,
|
|
80
80
|
externalRefResolver,
|
|
81
81
|
});
|
|
82
82
|
const bundleVisitor = visitors_1.normalizeVisitors([
|
|
@@ -90,7 +90,7 @@ function bundleDocument(opts) {
|
|
|
90
90
|
], types);
|
|
91
91
|
walk_1.walkDocument({
|
|
92
92
|
document,
|
|
93
|
-
rootType: types.
|
|
93
|
+
rootType: types.Root,
|
|
94
94
|
normalizedVisitors: bundleVisitor,
|
|
95
95
|
resolvedRefMap,
|
|
96
96
|
ctx,
|
|
@@ -99,7 +99,7 @@ function bundleDocument(opts) {
|
|
|
99
99
|
bundle: document,
|
|
100
100
|
problems: ctx.problems.map((problem) => config.addProblemToIgnore(problem)),
|
|
101
101
|
fileDependencies: externalRefResolver.getFiles(),
|
|
102
|
-
rootType: types.
|
|
102
|
+
rootType: types.Root,
|
|
103
103
|
refTypes: ctx.refTypes,
|
|
104
104
|
visitorsData: ctx.visitorsData,
|
|
105
105
|
};
|
|
@@ -184,7 +184,7 @@ function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDo
|
|
|
184
184
|
}
|
|
185
185
|
},
|
|
186
186
|
},
|
|
187
|
-
|
|
187
|
+
Root: {
|
|
188
188
|
enter(root) {
|
|
189
189
|
if (version === oas_types_1.OasMajorVersion.Version3) {
|
|
190
190
|
components = root.components = root.components || {};
|
package/lib/config/all.js
CHANGED
|
@@ -26,7 +26,7 @@ exports.default = {
|
|
|
26
26
|
'operation-operationId-url-safe': 'error',
|
|
27
27
|
'operation-parameters-unique': 'error',
|
|
28
28
|
'operation-tag-defined': 'error',
|
|
29
|
-
'
|
|
29
|
+
'security-defined': 'error',
|
|
30
30
|
'operation-singular-tag': 'error',
|
|
31
31
|
'no-unresolved-refs': 'error',
|
|
32
32
|
'no-enum-type-mismatch': 'error',
|
|
@@ -52,6 +52,7 @@ exports.default = {
|
|
|
52
52
|
'no-unused-components': 'error',
|
|
53
53
|
'no-undefined-server-variable': 'error',
|
|
54
54
|
'no-server-variables-empty-enum': 'error',
|
|
55
|
+
'operation-4xx-problem-details-rfc7807': 'error',
|
|
55
56
|
},
|
|
56
57
|
oas3_1Rules: {
|
|
57
58
|
'no-server-example.com': 'error',
|
|
@@ -61,5 +62,6 @@ exports.default = {
|
|
|
61
62
|
'no-unused-components': 'error',
|
|
62
63
|
'no-undefined-server-variable': 'error',
|
|
63
64
|
'no-server-variables-empty-enum': 'error',
|
|
65
|
+
'operation-4xx-problem-details-rfc7807': 'error',
|
|
64
66
|
},
|
|
65
67
|
};
|
|
@@ -135,7 +135,7 @@ function resolvePlugins(plugins, configPath = '') {
|
|
|
135
135
|
}
|
|
136
136
|
return plugin;
|
|
137
137
|
})
|
|
138
|
-
.filter(utils_2.
|
|
138
|
+
.filter(utils_2.isDefined);
|
|
139
139
|
}
|
|
140
140
|
exports.resolvePlugins = resolvePlugins;
|
|
141
141
|
function resolveApis({ rawConfig, configPath = '', resolver, }) {
|
package/lib/config/minimal.js
CHANGED
|
@@ -24,7 +24,7 @@ exports.default = {
|
|
|
24
24
|
'operation-operationId-unique': 'warn',
|
|
25
25
|
'operation-parameters-unique': 'warn',
|
|
26
26
|
'operation-tag-defined': 'off',
|
|
27
|
-
'
|
|
27
|
+
'security-defined': 'warn',
|
|
28
28
|
'operation-operationId-url-safe': 'warn',
|
|
29
29
|
'operation-singular-tag': 'off',
|
|
30
30
|
'no-unresolved-refs': 'error',
|
|
@@ -45,6 +45,7 @@ exports.default = {
|
|
|
45
45
|
'no-unused-components': 'warn',
|
|
46
46
|
'no-undefined-server-variable': 'warn',
|
|
47
47
|
'no-server-variables-empty-enum': 'error',
|
|
48
|
+
'spec-components-invalid-map-name': 'warn',
|
|
48
49
|
},
|
|
49
50
|
oas3_1Rules: {
|
|
50
51
|
'no-invalid-media-type-examples': 'warn',
|
|
@@ -55,5 +56,6 @@ exports.default = {
|
|
|
55
56
|
'no-unused-components': 'warn',
|
|
56
57
|
'no-undefined-server-variable': 'warn',
|
|
57
58
|
'no-server-variables-empty-enum': 'error',
|
|
59
|
+
'spec-components-invalid-map-name': 'warn',
|
|
58
60
|
},
|
|
59
61
|
};
|
|
@@ -25,7 +25,7 @@ exports.default = {
|
|
|
25
25
|
'operation-operationId-url-safe': 'error',
|
|
26
26
|
'operation-parameters-unique': 'error',
|
|
27
27
|
'operation-tag-defined': 'off',
|
|
28
|
-
'
|
|
28
|
+
'security-defined': 'error',
|
|
29
29
|
'operation-singular-tag': 'off',
|
|
30
30
|
'no-unresolved-refs': 'error',
|
|
31
31
|
'no-enum-type-mismatch': 'error',
|
|
@@ -45,6 +45,7 @@ exports.default = {
|
|
|
45
45
|
'no-unused-components': 'warn',
|
|
46
46
|
'no-undefined-server-variable': 'error',
|
|
47
47
|
'no-server-variables-empty-enum': 'error',
|
|
48
|
+
'spec-components-invalid-map-name': 'error',
|
|
48
49
|
},
|
|
49
50
|
oas3_1Rules: {
|
|
50
51
|
'no-invalid-media-type-examples': 'warn',
|
|
@@ -55,5 +56,6 @@ exports.default = {
|
|
|
55
56
|
'no-unused-components': 'warn',
|
|
56
57
|
'no-undefined-server-variable': 'error',
|
|
57
58
|
'no-server-variables-empty-enum': 'error',
|
|
59
|
+
'spec-components-invalid-map-name': 'error',
|
|
58
60
|
},
|
|
59
61
|
};
|
package/lib/config/rules.js
CHANGED
package/lib/config/types.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export declare type ResolveHeader = {
|
|
|
72
72
|
};
|
|
73
73
|
export declare type RawResolveConfig = {
|
|
74
74
|
http?: Partial<HttpResolveConfig>;
|
|
75
|
+
doNotResolveExamples?: boolean;
|
|
75
76
|
};
|
|
76
77
|
export declare type HttpResolveConfig = {
|
|
77
78
|
headers: ResolveHeader[];
|
|
@@ -87,6 +88,7 @@ export declare type AccessTokens = {
|
|
|
87
88
|
export declare type DeprecatedInRawConfig = {
|
|
88
89
|
apiDefinitions?: Record<string, string>;
|
|
89
90
|
lint?: StyleguideRawConfig;
|
|
91
|
+
styleguide?: StyleguideRawConfig;
|
|
90
92
|
referenceDocs?: Record<string, any>;
|
|
91
93
|
apis?: Record<string, Api & DeprecatedInApi>;
|
|
92
94
|
};
|
|
@@ -107,6 +109,11 @@ export declare type RawConfig = {
|
|
|
107
109
|
region?: Region;
|
|
108
110
|
organization?: string;
|
|
109
111
|
} & FeaturesConfig;
|
|
112
|
+
export declare type FlatApi = Omit<Api, 'styleguide'> & Omit<ApiStyleguideRawConfig, 'doNotResolveExamples'>;
|
|
113
|
+
export declare type FlatRawConfig = Omit<RawConfig, 'styleguide' | 'resolve' | 'apis'> & Omit<StyleguideRawConfig, 'doNotResolveExamples'> & {
|
|
114
|
+
resolve?: RawResolveConfig;
|
|
115
|
+
apis?: Record<string, FlatApi>;
|
|
116
|
+
};
|
|
110
117
|
export declare type ResolvedConfig = Omit<RawConfig, 'apis' | 'styleguide'> & {
|
|
111
118
|
apis: Record<string, ResolvedApi>;
|
|
112
119
|
styleguide: ResolvedStyleguideConfig;
|
package/lib/config/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config } from './config';
|
|
2
|
-
import type { Api, DeprecatedInRawConfig, Plugin, RawConfig, RawResolveConfig, ResolveConfig, ResolvedStyleguideConfig, RulesFields } from './types';
|
|
2
|
+
import type { Api, DeprecatedInRawConfig, FlatRawConfig, Plugin, RawConfig, RawResolveConfig, ResolveConfig, ResolvedStyleguideConfig, RulesFields } from './types';
|
|
3
3
|
export declare function parsePresetName(presetName: string): {
|
|
4
4
|
pluginId: string;
|
|
5
5
|
configName: string;
|
|
@@ -8,6 +8,6 @@ export declare function transformApiDefinitionsToApis(apiDefinitions?: Deprecate
|
|
|
8
8
|
export declare function prefixRules<T extends Record<string, any>>(rules: T, prefix: string): any;
|
|
9
9
|
export declare function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]): Omit<ResolvedStyleguideConfig, RulesFields> & Required<Pick<ResolvedStyleguideConfig, RulesFields>>;
|
|
10
10
|
export declare function getMergedConfig(config: Config, apiName?: string): Config;
|
|
11
|
-
export declare function transformConfig(rawConfig: DeprecatedInRawConfig & RawConfig): RawConfig;
|
|
11
|
+
export declare function transformConfig(rawConfig: DeprecatedInRawConfig & RawConfig & FlatRawConfig): RawConfig;
|
|
12
12
|
export declare function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig;
|
|
13
13
|
export declare function getUniquePlugins(plugins: Plugin[]): Plugin[];
|
package/lib/config/utils.js
CHANGED
|
@@ -35,13 +35,46 @@ function transformApiDefinitionsToApis(apiDefinitions) {
|
|
|
35
35
|
return apis;
|
|
36
36
|
}
|
|
37
37
|
exports.transformApiDefinitionsToApis = transformApiDefinitionsToApis;
|
|
38
|
+
function extractFlatConfig(_a) {
|
|
39
|
+
var _b;
|
|
40
|
+
var { plugins, extends: _extends, rules, oas2Rules, oas3_0Rules, oas3_1Rules, preprocessors, oas2Preprocessors, oas3_0Preprocessors, oas3_1Preprocessors, decorators, oas2Decorators, oas3_0Decorators, oas3_1Decorators } = _a, rawConfigRest = __rest(_a, ["plugins", "extends", "rules", "oas2Rules", "oas3_0Rules", "oas3_1Rules", "preprocessors", "oas2Preprocessors", "oas3_0Preprocessors", "oas3_1Preprocessors", "decorators", "oas2Decorators", "oas3_0Decorators", "oas3_1Decorators"]);
|
|
41
|
+
const styleguideConfig = {
|
|
42
|
+
plugins,
|
|
43
|
+
extends: _extends,
|
|
44
|
+
rules,
|
|
45
|
+
oas2Rules,
|
|
46
|
+
oas3_0Rules,
|
|
47
|
+
oas3_1Rules,
|
|
48
|
+
preprocessors,
|
|
49
|
+
oas2Preprocessors,
|
|
50
|
+
oas3_0Preprocessors,
|
|
51
|
+
oas3_1Preprocessors,
|
|
52
|
+
decorators,
|
|
53
|
+
oas2Decorators,
|
|
54
|
+
oas3_0Decorators,
|
|
55
|
+
oas3_1Decorators,
|
|
56
|
+
doNotResolveExamples: (_b = rawConfigRest.resolve) === null || _b === void 0 ? void 0 : _b.doNotResolveExamples,
|
|
57
|
+
};
|
|
58
|
+
if ((rawConfigRest.lint && rawConfigRest.styleguide) ||
|
|
59
|
+
(Object.values(styleguideConfig).some(utils_1.isDefined) &&
|
|
60
|
+
(rawConfigRest.lint || rawConfigRest.styleguide))) {
|
|
61
|
+
throw new Error(`Do not use 'lint', 'styleguide' and flat syntax together. \nSee more about the configuration in the docs: https://redocly.com/docs/cli/configuration/ \n`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
styleguideConfig: Object.values(styleguideConfig).some(utils_1.isDefined)
|
|
65
|
+
? styleguideConfig
|
|
66
|
+
: undefined,
|
|
67
|
+
rawConfigRest,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
38
70
|
function transformApis(legacyApis) {
|
|
39
71
|
if (!legacyApis)
|
|
40
72
|
return undefined;
|
|
41
73
|
const apis = {};
|
|
42
74
|
for (let _a of Object.entries(legacyApis)) {
|
|
43
75
|
const [apiName, _b] = _a, { lint } = _b, apiContent = __rest(_b, ["lint"]);
|
|
44
|
-
|
|
76
|
+
const { styleguideConfig, rawConfigRest } = extractFlatConfig(apiContent);
|
|
77
|
+
apis[apiName] = Object.assign({ styleguide: styleguideConfig || lint }, rawConfigRest);
|
|
45
78
|
}
|
|
46
79
|
return apis;
|
|
47
80
|
}
|
|
@@ -130,7 +163,10 @@ exports.getMergedConfig = getMergedConfig;
|
|
|
130
163
|
function checkForDeprecatedFields(deprecatedField, updatedField, rawConfig) {
|
|
131
164
|
const isDeprecatedFieldInApis = rawConfig.apis &&
|
|
132
165
|
Object.values(rawConfig.apis).some((api) => api[deprecatedField]);
|
|
133
|
-
if (rawConfig[deprecatedField] &&
|
|
166
|
+
if (rawConfig[deprecatedField] && updatedField === null) {
|
|
167
|
+
utils_1.showWarningForDeprecatedField(deprecatedField);
|
|
168
|
+
}
|
|
169
|
+
if (rawConfig[deprecatedField] && updatedField && rawConfig[updatedField]) {
|
|
134
170
|
utils_1.showErrorForDeprecatedField(deprecatedField, updatedField);
|
|
135
171
|
}
|
|
136
172
|
if (rawConfig[deprecatedField] || isDeprecatedFieldInApis) {
|
|
@@ -141,13 +177,15 @@ function transformConfig(rawConfig) {
|
|
|
141
177
|
const migratedFields = [
|
|
142
178
|
['apiDefinitions', 'apis'],
|
|
143
179
|
['referenceDocs', 'features.openapi'],
|
|
144
|
-
['lint',
|
|
180
|
+
['lint', undefined],
|
|
181
|
+
['styleguide', undefined],
|
|
145
182
|
];
|
|
146
183
|
for (const [deprecatedField, updatedField] of migratedFields) {
|
|
147
184
|
checkForDeprecatedFields(deprecatedField, updatedField, rawConfig);
|
|
148
185
|
}
|
|
149
186
|
const { apis, apiDefinitions, referenceDocs, lint } = rawConfig, rest = __rest(rawConfig, ["apis", "apiDefinitions", "referenceDocs", "lint"]);
|
|
150
|
-
|
|
187
|
+
const { styleguideConfig, rawConfigRest } = extractFlatConfig(rest);
|
|
188
|
+
return Object.assign({ 'features.openapi': referenceDocs, apis: transformApis(apis) || transformApiDefinitionsToApis(apiDefinitions), styleguide: styleguideConfig || lint }, rawConfigRest);
|
|
151
189
|
}
|
|
152
190
|
exports.transformConfig = transformConfig;
|
|
153
191
|
function getResolveConfig(resolve) {
|
|
@@ -5,7 +5,7 @@ const redocly_1 = require("../../redocly");
|
|
|
5
5
|
const RegistryDependencies = () => {
|
|
6
6
|
const registryDependencies = new Set();
|
|
7
7
|
return {
|
|
8
|
-
|
|
8
|
+
Root: {
|
|
9
9
|
leave(_, ctx) {
|
|
10
10
|
const data = ctx.getVisitorData();
|
|
11
11
|
data.links = Array.from(registryDependencies);
|
package/lib/format/format.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare type Totals = {
|
|
|
4
4
|
warnings: number;
|
|
5
5
|
ignored: number;
|
|
6
6
|
};
|
|
7
|
-
export declare type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle' | 'codeclimate';
|
|
7
|
+
export declare type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle' | 'codeclimate' | 'summary';
|
|
8
8
|
export declare function getTotals(problems: (NormalizedProblem & {
|
|
9
9
|
ignored?: boolean;
|
|
10
10
|
})[]): Totals;
|
package/lib/format/format.js
CHANGED
|
@@ -99,6 +99,9 @@ function formatProblems(problems, opts) {
|
|
|
99
99
|
case 'codeclimate':
|
|
100
100
|
outputForCodeClimate();
|
|
101
101
|
break;
|
|
102
|
+
case 'summary':
|
|
103
|
+
formatSummary(problems);
|
|
104
|
+
break;
|
|
102
105
|
}
|
|
103
106
|
if (totalProblems - ignoredProblems > maxProblems) {
|
|
104
107
|
logger_1.logger.info(`< ... ${totalProblems - maxProblems} more problems hidden > ${logger_1.colorize.gray('increase with `--max-problems N`')}\n`);
|
|
@@ -183,13 +186,31 @@ function formatProblems(problems, opts) {
|
|
|
183
186
|
}
|
|
184
187
|
}
|
|
185
188
|
exports.formatProblems = formatProblems;
|
|
189
|
+
function formatSummary(problems) {
|
|
190
|
+
const counts = {};
|
|
191
|
+
for (const problem of problems) {
|
|
192
|
+
counts[problem.ruleId] = counts[problem.ruleId] || { count: 0, severity: problem.severity };
|
|
193
|
+
counts[problem.ruleId].count++;
|
|
194
|
+
}
|
|
195
|
+
const sorted = Object.entries(counts).sort(([, a], [, b]) => {
|
|
196
|
+
const severityDiff = severityToNumber(a.severity) - severityToNumber(b.severity);
|
|
197
|
+
return severityDiff || b.count - a.count;
|
|
198
|
+
});
|
|
199
|
+
for (const [ruleId, info] of sorted) {
|
|
200
|
+
const color = COLORS[info.severity];
|
|
201
|
+
const severityName = color(SEVERITY_NAMES[info.severity].toLowerCase().padEnd(7));
|
|
202
|
+
logger_1.logger.info(`${severityName} ${ruleId}: ${info.count}\n`);
|
|
203
|
+
}
|
|
204
|
+
logger_1.logger.info('\n');
|
|
205
|
+
}
|
|
186
206
|
function formatFrom(cwd, location) {
|
|
187
207
|
if (!location)
|
|
188
208
|
return '';
|
|
189
209
|
const relativePath = path.relative(cwd, location.source.absoluteRef);
|
|
190
210
|
const loc = codeframes_1.getLineColLocation(location);
|
|
191
211
|
const fileWithLoc = `${relativePath}:${loc.start.line}:${loc.start.col}`;
|
|
192
|
-
|
|
212
|
+
const atPointer = location.pointer ? logger_1.colorize.gray(`at ${location.pointer}`) : '';
|
|
213
|
+
return `referenced from ${logger_1.colorize.blue(fileWithLoc)} ${atPointer} \n\n`;
|
|
193
214
|
}
|
|
194
215
|
function formatDidYouMean(problem) {
|
|
195
216
|
if (problem.suggest.length === 0)
|
package/lib/lint.js
CHANGED
|
@@ -60,12 +60,12 @@ function lintDocument(opts) {
|
|
|
60
60
|
const normalizedVisitors = visitors_1.normalizeVisitors([...preprocessors, ...regularRules], types);
|
|
61
61
|
const resolvedRefMap = yield resolve_1.resolveDocument({
|
|
62
62
|
rootDocument: document,
|
|
63
|
-
rootType: types.
|
|
63
|
+
rootType: types.Root,
|
|
64
64
|
externalRefResolver,
|
|
65
65
|
});
|
|
66
66
|
walk_1.walkDocument({
|
|
67
67
|
document,
|
|
68
|
-
rootType: types.
|
|
68
|
+
rootType: types.Root,
|
|
69
69
|
normalizedVisitors,
|
|
70
70
|
resolvedRefMap,
|
|
71
71
|
ctx,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { PrepareFileuploadOKResponse, PrepareFileuploadParams, PushApiParams } from './registry-api-types';
|
|
2
2
|
import type { AccessTokens, Region } from '../config/types';
|
|
3
|
-
export declare const currentCommand: string;
|
|
4
3
|
export declare class RegistryApi {
|
|
5
4
|
private accessTokens;
|
|
6
5
|
private region;
|
|
@@ -8,14 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var _a;
|
|
12
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.RegistryApi =
|
|
12
|
+
exports.RegistryApi = void 0;
|
|
14
13
|
const node_fetch_1 = require("node-fetch");
|
|
15
14
|
const config_1 = require("../config/config");
|
|
16
15
|
const utils_1 = require("../utils");
|
|
17
16
|
const version = require('../../package.json').version;
|
|
18
|
-
exports.currentCommand = typeof process !== 'undefined' ? ((_a = process.env) === null || _a === void 0 ? void 0 : _a.REDOCLY_CLI_COMMAND) || '' : '';
|
|
19
17
|
class RegistryApi {
|
|
20
18
|
constructor(accessTokens, region) {
|
|
21
19
|
this.accessTokens = accessTokens;
|
|
@@ -32,10 +30,13 @@ class RegistryApi {
|
|
|
32
30
|
return this;
|
|
33
31
|
}
|
|
34
32
|
request(path = '', options = {}, region) {
|
|
33
|
+
var _a, _b;
|
|
35
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
const currentCommand = typeof process !== 'undefined' ? ((_a = process.env) === null || _a === void 0 ? void 0 : _a.REDOCLY_CLI_COMMAND) || '' : '';
|
|
36
|
+
const redoclyEnv = typeof process !== 'undefined' ? ((_b = process.env) === null || _b === void 0 ? void 0 : _b.REDOCLY_ENVIRONMENT) || '' : '';
|
|
36
37
|
const headers = Object.assign({}, options.headers || {}, {
|
|
37
38
|
'x-redocly-cli-version': version,
|
|
38
|
-
'user-agent': `redocly-cli / ${version} ${
|
|
39
|
+
'user-agent': `redocly-cli / ${version} ${currentCommand} ${redoclyEnv}`,
|
|
39
40
|
});
|
|
40
41
|
if (!headers.hasOwnProperty('authorization')) {
|
|
41
42
|
throw new Error('Unauthorized');
|
package/lib/resolve.js
CHANGED
|
@@ -110,7 +110,9 @@ class BaseResolver {
|
|
|
110
110
|
return new Source(absoluteRef, body, mimeType);
|
|
111
111
|
}
|
|
112
112
|
else {
|
|
113
|
-
|
|
113
|
+
const content = yield fs.promises.readFile(absoluteRef, 'utf-8');
|
|
114
|
+
// In some cases file have \r\n line delimeters like on windows, we should skip it.
|
|
115
|
+
return new Source(absoluteRef, content.replace(/\r\n/g, '\n'));
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
catch (error) {
|
|
@@ -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}');
|
|
@@ -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
|
|
3
|
+
exports.SecurityDefined = void 0;
|
|
4
|
+
const SecurityDefined = () => {
|
|
5
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,6 +24,7 @@ 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;
|
|
@@ -31,6 +34,7 @@ const OasSpec = () => {
|
|
|
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
|
}
|
|
@@ -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,
|