@redocly/openapi-core 1.0.0-beta.119 → 1.0.0-beta.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config/config.d.ts +2 -3
- package/lib/config/config.js +1 -2
- package/lib/config/types.d.ts +13 -6
- package/lib/config/utils.d.ts +1 -0
- package/lib/config/utils.js +21 -12
- package/lib/decorators/common/info-override.d.ts +2 -0
- package/lib/decorators/common/info-override.js +28 -0
- package/lib/decorators/oas2/index.d.ts +1 -0
- package/lib/decorators/oas2/index.js +2 -0
- package/lib/decorators/oas3/index.d.ts +1 -0
- package/lib/decorators/oas3/index.js +2 -0
- package/lib/resolve.js +3 -1
- package/lib/rules/common/operation-2xx-response.js +15 -9
- package/lib/rules/common/operation-4xx-response.js +15 -9
- package/lib/rules/utils.d.ts +1 -0
- package/lib/rules/utils.js +14 -2
- package/lib/types/index.js +1 -1
- package/lib/types/redocly-yaml.js +9 -2
- package/lib/utils.d.ts +2 -2
- package/lib/utils.js +9 -4
- package/package.json +1 -1
- package/src/__tests__/lint.test.ts +19 -73
- package/src/config/__tests__/config.test.ts +8 -10
- package/src/config/__tests__/utils.test.ts +67 -6
- package/src/config/config.ts +3 -4
- package/src/config/types.ts +15 -6
- package/src/config/utils.ts +32 -18
- package/src/decorators/common/info-override.ts +15 -0
- package/src/decorators/oas2/index.ts +2 -0
- package/src/decorators/oas3/index.ts +2 -0
- package/src/resolve.ts +5 -1
- package/src/rules/__tests__/fixtures/code-sample.php +9 -0
- package/src/rules/__tests__/no-unresolved-refs.test.ts +89 -0
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +64 -0
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +64 -0
- package/src/rules/common/operation-2xx-response.ts +17 -9
- package/src/rules/common/operation-4xx-response.ts +16 -9
- package/src/rules/utils.ts +26 -1
- package/src/types/index.ts +1 -1
- package/src/types/redocly-yaml.ts +14 -4
- package/src/utils.ts +18 -4
- package/tsconfig.tsbuildinfo +1 -1
package/lib/config/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NormalizedProblem } from '../walk';
|
|
2
2
|
import { OasVersion, OasMajorVersion, Oas2RuleSet, Oas3RuleSet } from '../oas-types';
|
|
3
3
|
import type { NodeType } from '../types';
|
|
4
|
-
import type { DecoratorConfig, Plugin, PreprocessorConfig, Region, ResolveConfig, ResolvedApi, ResolvedConfig, ResolvedStyleguideConfig, RuleConfig, RuleSettings } from './types';
|
|
4
|
+
import type { DecoratorConfig, Plugin, PreprocessorConfig, Region, ResolveConfig, ResolvedApi, ResolvedConfig, ResolvedStyleguideConfig, RuleConfig, RuleSettings, ThemeRawConfig } from './types';
|
|
5
5
|
export declare const IGNORE_FILE = ".redocly.lint-ignore.yaml";
|
|
6
6
|
export declare const DEFAULT_REGION = "us";
|
|
7
7
|
export declare const DOMAINS: {
|
|
@@ -50,8 +50,7 @@ export declare class Config {
|
|
|
50
50
|
resolve: ResolveConfig;
|
|
51
51
|
licenseKey?: string;
|
|
52
52
|
region?: Region;
|
|
53
|
-
|
|
54
|
-
'features.mockServer'?: Record<string, any>;
|
|
53
|
+
theme: ThemeRawConfig;
|
|
55
54
|
organization?: string;
|
|
56
55
|
files: string[];
|
|
57
56
|
constructor(rawConfig: ResolvedConfig, configFile?: string | undefined);
|
package/lib/config/config.js
CHANGED
|
@@ -244,8 +244,7 @@ class Config {
|
|
|
244
244
|
this.configFile = configFile;
|
|
245
245
|
this.apis = rawConfig.apis || {};
|
|
246
246
|
this.styleguide = new StyleguideConfig(rawConfig.styleguide || {}, configFile);
|
|
247
|
-
this
|
|
248
|
-
this['features.mockServer'] = rawConfig['features.mockServer'] || {};
|
|
247
|
+
this.theme = rawConfig.theme || {};
|
|
249
248
|
this.resolve = utils_2.getResolveConfig(rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.resolve);
|
|
250
249
|
this.region = rawConfig.region;
|
|
251
250
|
this.organization = rawConfig.organization;
|
package/lib/config/types.d.ts
CHANGED
|
@@ -102,14 +102,14 @@ export declare type DeprecatedInRawConfig = {
|
|
|
102
102
|
styleguide?: StyleguideRawConfig;
|
|
103
103
|
referenceDocs?: Record<string, any>;
|
|
104
104
|
apis?: Record<string, Api & DeprecatedInApi>;
|
|
105
|
-
};
|
|
105
|
+
} & DeprecatedFeaturesConfig;
|
|
106
106
|
export declare type Api = {
|
|
107
107
|
root: string;
|
|
108
108
|
styleguide?: ApiStyleguideRawConfig;
|
|
109
|
-
} &
|
|
109
|
+
} & ThemeConfig;
|
|
110
110
|
export declare type DeprecatedInApi = {
|
|
111
111
|
lint?: ApiStyleguideRawConfig;
|
|
112
|
-
};
|
|
112
|
+
} & DeprecatedFeaturesConfig;
|
|
113
113
|
export declare type ResolvedApi = Omit<Api, 'styleguide'> & {
|
|
114
114
|
styleguide: ResolvedStyleguideConfig;
|
|
115
115
|
files?: string[];
|
|
@@ -121,19 +121,26 @@ export declare type RawConfig = {
|
|
|
121
121
|
region?: Region;
|
|
122
122
|
organization?: string;
|
|
123
123
|
files?: string[];
|
|
124
|
-
} &
|
|
124
|
+
} & ThemeConfig;
|
|
125
125
|
export declare type FlatApi = Omit<Api, 'styleguide'> & Omit<ApiStyleguideRawConfig, 'doNotResolveExamples'>;
|
|
126
126
|
export declare type FlatRawConfig = Omit<RawConfig, 'styleguide' | 'resolve' | 'apis'> & Omit<StyleguideRawConfig, 'doNotResolveExamples'> & {
|
|
127
127
|
resolve?: RawResolveConfig;
|
|
128
128
|
apis?: Record<string, FlatApi>;
|
|
129
|
-
};
|
|
129
|
+
} & ThemeRawConfig;
|
|
130
130
|
export declare type ResolvedConfig = Omit<RawConfig, 'apis' | 'styleguide'> & {
|
|
131
131
|
apis: Record<string, ResolvedApi>;
|
|
132
132
|
styleguide: ResolvedStyleguideConfig;
|
|
133
133
|
};
|
|
134
|
-
declare type
|
|
134
|
+
declare type DeprecatedFeaturesConfig = {
|
|
135
135
|
'features.openapi'?: Record<string, any>;
|
|
136
136
|
'features.mockServer'?: Record<string, any>;
|
|
137
137
|
};
|
|
138
|
+
export declare type ThemeConfig = {
|
|
139
|
+
theme?: ThemeRawConfig;
|
|
140
|
+
};
|
|
141
|
+
export declare type ThemeRawConfig = {
|
|
142
|
+
openapi?: Record<string, any>;
|
|
143
|
+
mockServer?: Record<string, any>;
|
|
144
|
+
};
|
|
138
145
|
export declare type RulesFields = 'rules' | 'oas2Rules' | 'oas3_0Rules' | 'oas3_1Rules' | 'preprocessors' | 'oas2Preprocessors' | 'oas3_0Preprocessors' | 'oas3_1Preprocessors' | 'decorators' | 'oas2Decorators' | 'oas3_0Decorators' | 'oas3_1Decorators';
|
|
139
146
|
export {};
|
package/lib/config/utils.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ 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 checkForDeprecatedFields(deprecatedField: keyof (DeprecatedInRawConfig & RawConfig), updatedField: keyof FlatRawConfig | undefined, rawConfig: DeprecatedInRawConfig & RawConfig & FlatRawConfig, updatedObject: keyof FlatRawConfig | undefined): void;
|
|
11
12
|
export declare function transformConfig(rawConfig: DeprecatedInRawConfig & RawConfig & FlatRawConfig): RawConfig;
|
|
12
13
|
export declare function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig;
|
|
13
14
|
export declare function getUniquePlugins(plugins: Plugin[]): Plugin[];
|
package/lib/config/utils.js
CHANGED
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.getUniquePlugins = exports.getResolveConfig = exports.transformConfig = exports.getMergedConfig = exports.mergeExtends = exports.prefixRules = exports.transformApiDefinitionsToApis = exports.parsePresetName = void 0;
|
|
14
|
+
exports.getUniquePlugins = exports.getResolveConfig = exports.transformConfig = exports.checkForDeprecatedFields = exports.getMergedConfig = exports.mergeExtends = exports.prefixRules = exports.transformApiDefinitionsToApis = exports.parsePresetName = void 0;
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
const config_1 = require("./config");
|
|
17
17
|
const logger_1 = require("../logger");
|
|
@@ -139,7 +139,7 @@ function mergeExtends(rulesConfList) {
|
|
|
139
139
|
}
|
|
140
140
|
exports.mergeExtends = mergeExtends;
|
|
141
141
|
function getMergedConfig(config, apiName) {
|
|
142
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
142
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
143
143
|
const extendPaths = [
|
|
144
144
|
...Object.values(config.apis).map((api) => { var _a; return (_a = api === null || api === void 0 ? void 0 : api.styleguide) === null || _a === void 0 ? void 0 : _a.extendPaths; }),
|
|
145
145
|
(_b = (_a = config.rawConfig) === null || _a === void 0 ? void 0 : _a.styleguide) === null || _b === void 0 ? void 0 : _b.extendPaths,
|
|
@@ -156,11 +156,11 @@ function getMergedConfig(config, apiName) {
|
|
|
156
156
|
? new config_1.Config(Object.assign(Object.assign({}, config.rawConfig), { styleguide: Object.assign(Object.assign({}, (config.apis[apiName]
|
|
157
157
|
? config.apis[apiName].styleguide
|
|
158
158
|
: config.rawConfig.styleguide)), { extendPaths,
|
|
159
|
-
pluginPaths }),
|
|
159
|
+
pluginPaths }), theme: Object.assign(Object.assign({}, config.rawConfig.theme), (_e = config.apis[apiName]) === null || _e === void 0 ? void 0 : _e.theme), files: [...config.files, ...((_h = (_g = (_f = config.apis) === null || _f === void 0 ? void 0 : _f[apiName]) === null || _g === void 0 ? void 0 : _g.files) !== null && _h !== void 0 ? _h : [])] }), config.configFile)
|
|
160
160
|
: config;
|
|
161
161
|
}
|
|
162
162
|
exports.getMergedConfig = getMergedConfig;
|
|
163
|
-
function checkForDeprecatedFields(deprecatedField, updatedField, rawConfig) {
|
|
163
|
+
function checkForDeprecatedFields(deprecatedField, updatedField, rawConfig, updatedObject) {
|
|
164
164
|
const isDeprecatedFieldInApis = rawConfig.apis &&
|
|
165
165
|
Object.values(rawConfig.apis).some((api) => api[deprecatedField]);
|
|
166
166
|
if (rawConfig[deprecatedField] && updatedField === null) {
|
|
@@ -169,23 +169,32 @@ function checkForDeprecatedFields(deprecatedField, updatedField, rawConfig) {
|
|
|
169
169
|
if (rawConfig[deprecatedField] && updatedField && rawConfig[updatedField]) {
|
|
170
170
|
utils_1.showErrorForDeprecatedField(deprecatedField, updatedField);
|
|
171
171
|
}
|
|
172
|
+
if (rawConfig[deprecatedField] && updatedObject && rawConfig[updatedObject]) {
|
|
173
|
+
utils_1.showErrorForDeprecatedField(deprecatedField, updatedField, updatedObject);
|
|
174
|
+
}
|
|
172
175
|
if (rawConfig[deprecatedField] || isDeprecatedFieldInApis) {
|
|
173
|
-
utils_1.showWarningForDeprecatedField(deprecatedField, updatedField);
|
|
176
|
+
utils_1.showWarningForDeprecatedField(deprecatedField, updatedField, updatedObject);
|
|
174
177
|
}
|
|
175
178
|
}
|
|
179
|
+
exports.checkForDeprecatedFields = checkForDeprecatedFields;
|
|
176
180
|
function transformConfig(rawConfig) {
|
|
181
|
+
var _a, _b;
|
|
177
182
|
const migratedFields = [
|
|
178
|
-
['apiDefinitions', 'apis'],
|
|
179
|
-
['referenceDocs', '
|
|
180
|
-
['lint', undefined],
|
|
181
|
-
['styleguide', undefined],
|
|
183
|
+
['apiDefinitions', 'apis', undefined],
|
|
184
|
+
['referenceDocs', 'openapi', 'theme'],
|
|
185
|
+
['lint', undefined, undefined],
|
|
186
|
+
['styleguide', undefined, undefined],
|
|
187
|
+
['features.openapi', 'openapi', 'theme'],
|
|
182
188
|
];
|
|
183
|
-
for (const [deprecatedField, updatedField] of migratedFields) {
|
|
184
|
-
checkForDeprecatedFields(deprecatedField, updatedField, rawConfig);
|
|
189
|
+
for (const [deprecatedField, updatedField, updatedObject] of migratedFields) {
|
|
190
|
+
checkForDeprecatedFields(deprecatedField, updatedField, rawConfig, updatedObject);
|
|
185
191
|
}
|
|
186
192
|
const { apis, apiDefinitions, referenceDocs, lint } = rawConfig, rest = __rest(rawConfig, ["apis", "apiDefinitions", "referenceDocs", "lint"]);
|
|
187
193
|
const { styleguideConfig, rawConfigRest } = extractFlatConfig(rest);
|
|
188
|
-
return Object.assign({
|
|
194
|
+
return Object.assign({ theme: {
|
|
195
|
+
openapi: Object.assign(Object.assign(Object.assign({}, referenceDocs), rawConfig['features.openapi']), (_a = rawConfig.theme) === null || _a === void 0 ? void 0 : _a.openapi),
|
|
196
|
+
mockServer: Object.assign(Object.assign({}, rawConfig['features.mockServer']), (_b = rawConfig.theme) === null || _b === void 0 ? void 0 : _b.mockServer),
|
|
197
|
+
}, apis: transformApis(apis) || transformApiDefinitionsToApis(apiDefinitions), styleguide: styleguideConfig || lint }, rawConfigRest);
|
|
189
198
|
}
|
|
190
199
|
exports.transformConfig = transformConfig;
|
|
191
200
|
function getResolveConfig(resolve) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.InfoOverride = void 0;
|
|
15
|
+
const InfoOverride = (newInfo) => {
|
|
16
|
+
return {
|
|
17
|
+
Info: {
|
|
18
|
+
leave(info) {
|
|
19
|
+
if (typeof newInfo !== 'object' || Array.isArray(newInfo) || newInfo === null) {
|
|
20
|
+
throw new Error(`"info-override" decorator should be called with an object`);
|
|
21
|
+
}
|
|
22
|
+
const { severity: _ } = newInfo, rest = __rest(newInfo, ["severity"]);
|
|
23
|
+
Object.assign(info, rest);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
exports.InfoOverride = InfoOverride;
|
|
@@ -4,6 +4,7 @@ export declare const decorators: {
|
|
|
4
4
|
'operation-description-override': Oas2Decorator;
|
|
5
5
|
'tag-description-override': Oas2Decorator;
|
|
6
6
|
'info-description-override': Oas2Decorator;
|
|
7
|
+
'info-override': Oas2Decorator;
|
|
7
8
|
'remove-x-internal': Oas2Decorator;
|
|
8
9
|
'filter-in': Oas2Decorator;
|
|
9
10
|
'filter-out': Oas2Decorator;
|
|
@@ -5,6 +5,7 @@ const registry_dependencies_1 = require("../common/registry-dependencies");
|
|
|
5
5
|
const operation_description_override_1 = require("../common/operation-description-override");
|
|
6
6
|
const tag_description_override_1 = require("../common/tag-description-override");
|
|
7
7
|
const info_description_override_1 = require("../common/info-description-override");
|
|
8
|
+
const info_override_1 = require("../common/info-override");
|
|
8
9
|
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
9
10
|
const filter_in_1 = require("../common/filters/filter-in");
|
|
10
11
|
const filter_out_1 = require("../common/filters/filter-out");
|
|
@@ -13,6 +14,7 @@ exports.decorators = {
|
|
|
13
14
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
14
15
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
15
16
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
17
|
+
'info-override': info_override_1.InfoOverride,
|
|
16
18
|
'remove-x-internal': remove_x_internal_1.RemoveXInternal,
|
|
17
19
|
'filter-in': filter_in_1.FilterIn,
|
|
18
20
|
'filter-out': filter_out_1.FilterOut,
|
|
@@ -4,6 +4,7 @@ export declare const decorators: {
|
|
|
4
4
|
'operation-description-override': Oas3Decorator;
|
|
5
5
|
'tag-description-override': Oas3Decorator;
|
|
6
6
|
'info-description-override': Oas3Decorator;
|
|
7
|
+
'info-override': Oas3Decorator;
|
|
7
8
|
'remove-x-internal': Oas3Decorator;
|
|
8
9
|
'filter-in': Oas3Decorator;
|
|
9
10
|
'filter-out': Oas3Decorator;
|
|
@@ -5,6 +5,7 @@ const registry_dependencies_1 = require("../common/registry-dependencies");
|
|
|
5
5
|
const operation_description_override_1 = require("../common/operation-description-override");
|
|
6
6
|
const tag_description_override_1 = require("../common/tag-description-override");
|
|
7
7
|
const info_description_override_1 = require("../common/info-description-override");
|
|
8
|
+
const info_override_1 = require("../common/info-override");
|
|
8
9
|
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
9
10
|
const filter_in_1 = require("../common/filters/filter-in");
|
|
10
11
|
const filter_out_1 = require("../common/filters/filter-out");
|
|
@@ -14,6 +15,7 @@ exports.decorators = {
|
|
|
14
15
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
15
16
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
16
17
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
18
|
+
'info-override': info_override_1.InfoOverride,
|
|
17
19
|
'remove-x-internal': remove_x_internal_1.RemoveXInternal,
|
|
18
20
|
'filter-in': filter_in_1.FilterIn,
|
|
19
21
|
'filter-out': filter_out_1.FilterOut,
|
package/lib/resolve.js
CHANGED
|
@@ -221,7 +221,9 @@ function resolveDocument(opts) {
|
|
|
221
221
|
propType = propType(propValue, propName);
|
|
222
222
|
if (propType === undefined)
|
|
223
223
|
propType = unknownType;
|
|
224
|
-
if (type.extensionsPrefix &&
|
|
224
|
+
if (type.extensionsPrefix &&
|
|
225
|
+
propName.startsWith(type.extensionsPrefix) &&
|
|
226
|
+
propType === unknownType) {
|
|
225
227
|
propType = types_1.SpecExtension;
|
|
226
228
|
}
|
|
227
229
|
if (!types_1.isNamedType(propType) && (propType === null || propType === void 0 ? void 0 : propType.directResolveAs)) {
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Operation2xxResponse = void 0;
|
|
4
|
-
const
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const Operation2xxResponse = ({ validateWebhooks }) => {
|
|
5
6
|
return {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
7
|
+
Paths: {
|
|
8
|
+
Responses(responses, { report }) {
|
|
9
|
+
const codes = Object.keys(responses || {});
|
|
10
|
+
utils_1.validateResponseCodes(codes, '2XX', { report });
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
WebhooksMap: {
|
|
14
|
+
Responses(responses, { report }) {
|
|
15
|
+
if (!validateWebhooks)
|
|
16
|
+
return;
|
|
17
|
+
const codes = Object.keys(responses || {});
|
|
18
|
+
utils_1.validateResponseCodes(codes, '2XX', { report });
|
|
19
|
+
},
|
|
14
20
|
},
|
|
15
21
|
};
|
|
16
22
|
};
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Operation4xxResponse = void 0;
|
|
4
|
-
const
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const Operation4xxResponse = ({ validateWebhooks }) => {
|
|
5
6
|
return {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
7
|
+
Paths: {
|
|
8
|
+
Responses(responses, { report }) {
|
|
9
|
+
const codes = Object.keys(responses || {});
|
|
10
|
+
utils_1.validateResponseCodes(codes, '4XX', { report });
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
WebhooksMap: {
|
|
14
|
+
Responses(responses, { report }) {
|
|
15
|
+
if (!validateWebhooks)
|
|
16
|
+
return;
|
|
17
|
+
const codes = Object.keys(responses || {});
|
|
18
|
+
utils_1.validateResponseCodes(codes, '4XX', { report });
|
|
19
|
+
},
|
|
14
20
|
},
|
|
15
21
|
};
|
|
16
22
|
};
|
package/lib/rules/utils.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export declare function getSuggest(given: string, variants: string[]): string[];
|
|
|
17
17
|
export declare function validateExample(example: any, schema: Referenced<Oas3Schema>, dataLoc: Location, { resolve, location, report }: UserContext, allowAdditionalProperties: boolean): void;
|
|
18
18
|
export declare function getAdditionalPropertiesOption(opts: Record<string, any>): boolean;
|
|
19
19
|
export declare function validateSchemaEnumType(schemaEnum: string[], propertyValue: string, propName: string, refLocation: Location | undefined, { report, location }: UserContext): void;
|
|
20
|
+
export declare function validateResponseCodes(responseCodes: string[], codeRange: string, { report }: UserContext): void;
|
package/lib/rules/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateSchemaEnumType = exports.getAdditionalPropertiesOption = exports.validateExample = exports.getSuggest = exports.validateDefinedAndNonEmpty = exports.fieldNonEmpty = exports.missingRequiredField = exports.matchesJsonSchemaType = exports.oasTypeOf = void 0;
|
|
3
|
+
exports.validateResponseCodes = exports.validateSchemaEnumType = exports.getAdditionalPropertiesOption = exports.validateExample = exports.getSuggest = exports.validateDefinedAndNonEmpty = exports.fieldNonEmpty = exports.missingRequiredField = exports.matchesJsonSchemaType = exports.oasTypeOf = void 0;
|
|
4
4
|
const levenshtein = require("js-levenshtein");
|
|
5
5
|
const ref_utils_1 = require("../ref-utils");
|
|
6
6
|
const ajv_1 = require("./ajv");
|
|
@@ -117,7 +117,7 @@ function getAdditionalPropertiesOption(opts) {
|
|
|
117
117
|
return opts.allowAdditionalProperties;
|
|
118
118
|
}
|
|
119
119
|
if (opts.allowAdditionalProperties !== undefined) {
|
|
120
|
-
utils_1.showErrorForDeprecatedField('disallowAdditionalProperties', 'allowAdditionalProperties');
|
|
120
|
+
utils_1.showErrorForDeprecatedField('disallowAdditionalProperties', 'allowAdditionalProperties', undefined);
|
|
121
121
|
}
|
|
122
122
|
utils_1.showWarningForDeprecatedField('disallowAdditionalProperties', 'allowAdditionalProperties');
|
|
123
123
|
return !opts.disallowAdditionalProperties;
|
|
@@ -139,3 +139,15 @@ function validateSchemaEnumType(schemaEnum, propertyValue, propName, refLocation
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
exports.validateSchemaEnumType = validateSchemaEnumType;
|
|
142
|
+
function validateResponseCodes(responseCodes, codeRange, { report }) {
|
|
143
|
+
const responseCodeRegexp = new RegExp(`^${codeRange[0]}[0-9Xx]{2}$`);
|
|
144
|
+
const containsNeededCode = responseCodes.some((code) => (codeRange === '2XX' && code === 'default') || // It's OK to replace 2xx codes with the default
|
|
145
|
+
responseCodeRegexp.test(code));
|
|
146
|
+
if (!containsNeededCode) {
|
|
147
|
+
report({
|
|
148
|
+
message: `Operation must have at least one \`${codeRange}\` response.`,
|
|
149
|
+
location: { reportOnKey: true },
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.validateResponseCodes = validateResponseCodes;
|
package/lib/types/index.js
CHANGED
|
@@ -21,7 +21,7 @@ exports.SpecExtension = {
|
|
|
21
21
|
name: 'SpecExtension',
|
|
22
22
|
properties: {},
|
|
23
23
|
// skip validation of additional properties for unknown extensions
|
|
24
|
-
additionalProperties:
|
|
24
|
+
additionalProperties: { resolvable: true },
|
|
25
25
|
};
|
|
26
26
|
function normalizeTypes(types, options = {}) {
|
|
27
27
|
const normalizedTypes = {};
|
|
@@ -146,7 +146,7 @@ const RootConfigStyleguide = {
|
|
|
146
146
|
} }, ConfigStyleguide.properties),
|
|
147
147
|
};
|
|
148
148
|
const ConfigRoot = {
|
|
149
|
-
properties: Object.assign(Object.assign({ organization: { type: 'string' }, apis: 'ConfigApis' }, RootConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', region: { enum: ['us', 'eu'] }, resolve: {
|
|
149
|
+
properties: Object.assign(Object.assign({ organization: { type: 'string' }, apis: 'ConfigApis' }, RootConfigStyleguide.properties), { theme: 'ConfigRootTheme', 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', region: { enum: ['us', 'eu'] }, resolve: {
|
|
150
150
|
properties: {
|
|
151
151
|
http: 'ConfigHTTP',
|
|
152
152
|
doNotResolveExamples: { type: 'boolean' },
|
|
@@ -168,7 +168,7 @@ const ConfigApisProperties = {
|
|
|
168
168
|
items: {
|
|
169
169
|
type: 'string',
|
|
170
170
|
},
|
|
171
|
-
}, lint: 'ConfigStyleguide', styleguide: 'ConfigStyleguide' }, ConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', files: {
|
|
171
|
+
}, lint: 'ConfigStyleguide', styleguide: 'ConfigStyleguide' }, ConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', theme: 'ConfigRootTheme', files: {
|
|
172
172
|
type: 'array',
|
|
173
173
|
items: {
|
|
174
174
|
type: 'string',
|
|
@@ -186,6 +186,12 @@ const ConfigHTTP = {
|
|
|
186
186
|
},
|
|
187
187
|
},
|
|
188
188
|
};
|
|
189
|
+
const ConfigRootTheme = {
|
|
190
|
+
properties: {
|
|
191
|
+
openapi: 'ConfigReferenceDocs',
|
|
192
|
+
mockServer: 'ConfigMockServer',
|
|
193
|
+
},
|
|
194
|
+
};
|
|
189
195
|
const Rules = {
|
|
190
196
|
properties: {},
|
|
191
197
|
additionalProperties: (value, key) => {
|
|
@@ -815,6 +821,7 @@ exports.ConfigTypes = {
|
|
|
815
821
|
ConfigSidebarLinks,
|
|
816
822
|
CommonConfigSidebarLinks,
|
|
817
823
|
ConfigTheme,
|
|
824
|
+
ConfigRootTheme,
|
|
818
825
|
AssertDefinition,
|
|
819
826
|
ThemeColors,
|
|
820
827
|
CommonThemeColors,
|
package/lib/utils.d.ts
CHANGED
|
@@ -42,8 +42,8 @@ export declare function assignExisting<T>(target: Record<string, T>, obj: Record
|
|
|
42
42
|
export declare function getMatchingStatusCodeRange(code: number | string): string;
|
|
43
43
|
export declare function isCustomRuleId(id: string): boolean;
|
|
44
44
|
export declare function doesYamlFileExist(filePath: string): boolean;
|
|
45
|
-
export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField?: string): void;
|
|
46
|
-
export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField?: string): void;
|
|
45
|
+
export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField?: string, updatedObject?: string): void;
|
|
46
|
+
export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField?: string, updatedObject?: string): void;
|
|
47
47
|
export declare type Falsy = undefined | null | false | '' | 0;
|
|
48
48
|
export declare function isTruthy<Truthy>(value: Truthy | Falsy): value is Truthy;
|
|
49
49
|
export declare function identity<T>(value: T): T;
|
package/lib/utils.js
CHANGED
|
@@ -194,12 +194,14 @@ function doesYamlFileExist(filePath) {
|
|
|
194
194
|
fs.existsSync(filePath));
|
|
195
195
|
}
|
|
196
196
|
exports.doesYamlFileExist = doesYamlFileExist;
|
|
197
|
-
function showWarningForDeprecatedField(deprecatedField, updatedField) {
|
|
198
|
-
logger_1.logger.warn(`The '${logger_1.colorize.red(deprecatedField)}' field is deprecated. ${updatedField
|
|
197
|
+
function showWarningForDeprecatedField(deprecatedField, updatedField, updatedObject) {
|
|
198
|
+
logger_1.logger.warn(`The '${logger_1.colorize.red(deprecatedField)}' field is deprecated. ${updatedField
|
|
199
|
+
? `Use ${logger_1.colorize.green(getUpdatedFieldName(updatedField, updatedObject))} instead. `
|
|
200
|
+
: ''}Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
|
|
199
201
|
}
|
|
200
202
|
exports.showWarningForDeprecatedField = showWarningForDeprecatedField;
|
|
201
|
-
function showErrorForDeprecatedField(deprecatedField, updatedField) {
|
|
202
|
-
throw new Error(`Do not use '${deprecatedField}' field. ${updatedField ? `Use '${updatedField}' instead. ` : ''}\n`);
|
|
203
|
+
function showErrorForDeprecatedField(deprecatedField, updatedField, updatedObject) {
|
|
204
|
+
throw new Error(`Do not use '${deprecatedField}' field. ${updatedField ? `Use '${getUpdatedFieldName(updatedField, updatedObject)}' instead. ` : ''}\n`);
|
|
203
205
|
}
|
|
204
206
|
exports.showErrorForDeprecatedField = showErrorForDeprecatedField;
|
|
205
207
|
function isTruthy(value) {
|
|
@@ -234,3 +236,6 @@ function nextTick() {
|
|
|
234
236
|
});
|
|
235
237
|
}
|
|
236
238
|
exports.nextTick = nextTick;
|
|
239
|
+
function getUpdatedFieldName(updatedField, updatedObject) {
|
|
240
|
+
return `${typeof updatedObject !== 'undefined' ? `${updatedObject}.` : ''}${updatedField}`;
|
|
241
|
+
}
|
package/package.json
CHANGED
|
@@ -68,17 +68,8 @@ describe('lint', () => {
|
|
|
68
68
|
assertions:
|
|
69
69
|
local/checkWordsCount:
|
|
70
70
|
min: 3
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
layout:
|
|
74
|
-
scope: section
|
|
75
|
-
routingStrategy: browser
|
|
76
|
-
theme:
|
|
77
|
-
rightPanel:
|
|
78
|
-
backgroundColor: '#263238'
|
|
79
|
-
links:
|
|
80
|
-
color: '#6CC496'
|
|
81
|
-
features.openapi:
|
|
71
|
+
theme:
|
|
72
|
+
openapi:
|
|
82
73
|
showConsole: true
|
|
83
74
|
layout:
|
|
84
75
|
scope: section
|
|
@@ -88,6 +79,17 @@ describe('lint', () => {
|
|
|
88
79
|
backgroundColor: '#263238'
|
|
89
80
|
links:
|
|
90
81
|
color: '#6CC496'
|
|
82
|
+
theme:
|
|
83
|
+
openapi:
|
|
84
|
+
showConsole: true
|
|
85
|
+
layout:
|
|
86
|
+
scope: section
|
|
87
|
+
routingStrategy: browser
|
|
88
|
+
theme:
|
|
89
|
+
rightPanel:
|
|
90
|
+
backgroundColor: '#263238'
|
|
91
|
+
links:
|
|
92
|
+
color: '#6CC496'
|
|
91
93
|
`,
|
|
92
94
|
''
|
|
93
95
|
);
|
|
@@ -99,70 +101,28 @@ describe('lint', () => {
|
|
|
99
101
|
"from": undefined,
|
|
100
102
|
"location": Array [
|
|
101
103
|
Object {
|
|
102
|
-
"pointer": "#/
|
|
104
|
+
"pointer": "#/eme",
|
|
103
105
|
"reportOnKey": true,
|
|
104
106
|
"source": "",
|
|
105
107
|
},
|
|
106
108
|
],
|
|
107
|
-
"message": "Property \`
|
|
109
|
+
"message": "Property \`eme\` is not expected here.",
|
|
108
110
|
"ruleId": "configuration spec",
|
|
109
111
|
"severity": "error",
|
|
110
112
|
"suggest": Array [
|
|
111
|
-
"
|
|
113
|
+
"theme",
|
|
112
114
|
],
|
|
113
115
|
},
|
|
114
116
|
Object {
|
|
115
117
|
"from": undefined,
|
|
116
118
|
"location": Array [
|
|
117
119
|
Object {
|
|
118
|
-
"pointer": "#/
|
|
120
|
+
"pointer": "#/openapi",
|
|
119
121
|
"reportOnKey": true,
|
|
120
122
|
"source": "",
|
|
121
123
|
},
|
|
122
124
|
],
|
|
123
|
-
"message": "Property \`
|
|
124
|
-
"ruleId": "configuration spec",
|
|
125
|
-
"severity": "error",
|
|
126
|
-
"suggest": Array [],
|
|
127
|
-
},
|
|
128
|
-
Object {
|
|
129
|
-
"from": undefined,
|
|
130
|
-
"location": Array [
|
|
131
|
-
Object {
|
|
132
|
-
"pointer": "#/layout",
|
|
133
|
-
"reportOnKey": true,
|
|
134
|
-
"source": "",
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
"message": "Property \`layout\` is not expected here.",
|
|
138
|
-
"ruleId": "configuration spec",
|
|
139
|
-
"severity": "error",
|
|
140
|
-
"suggest": Array [],
|
|
141
|
-
},
|
|
142
|
-
Object {
|
|
143
|
-
"from": undefined,
|
|
144
|
-
"location": Array [
|
|
145
|
-
Object {
|
|
146
|
-
"pointer": "#/routingStrategy",
|
|
147
|
-
"reportOnKey": true,
|
|
148
|
-
"source": "",
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
"message": "Property \`routingStrategy\` is not expected here.",
|
|
152
|
-
"ruleId": "configuration spec",
|
|
153
|
-
"severity": "error",
|
|
154
|
-
"suggest": Array [],
|
|
155
|
-
},
|
|
156
|
-
Object {
|
|
157
|
-
"from": undefined,
|
|
158
|
-
"location": Array [
|
|
159
|
-
Object {
|
|
160
|
-
"pointer": "#/theme",
|
|
161
|
-
"reportOnKey": true,
|
|
162
|
-
"source": "",
|
|
163
|
-
},
|
|
164
|
-
],
|
|
165
|
-
"message": "Property \`theme\` is not expected here.",
|
|
125
|
+
"message": "Property \`openapi\` is not expected here.",
|
|
166
126
|
"ruleId": "configuration spec",
|
|
167
127
|
"severity": "error",
|
|
168
128
|
"suggest": Array [],
|
|
@@ -181,20 +141,6 @@ describe('lint', () => {
|
|
|
181
141
|
"severity": "error",
|
|
182
142
|
"suggest": Array [],
|
|
183
143
|
},
|
|
184
|
-
Object {
|
|
185
|
-
"from": undefined,
|
|
186
|
-
"location": Array [
|
|
187
|
-
Object {
|
|
188
|
-
"pointer": "#/features.openapi/layout",
|
|
189
|
-
"reportOnKey": false,
|
|
190
|
-
"source": "",
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
"message": "\`layout\` can be one of the following only: \\"stacked\\", \\"three-panel\\".",
|
|
194
|
-
"ruleId": "configuration spec",
|
|
195
|
-
"severity": "error",
|
|
196
|
-
"suggest": Array [],
|
|
197
|
-
},
|
|
198
144
|
]
|
|
199
145
|
`);
|
|
200
146
|
});
|
|
@@ -234,7 +180,7 @@ describe('lint', () => {
|
|
|
234
180
|
`);
|
|
235
181
|
});
|
|
236
182
|
|
|
237
|
-
it('lintConfig should work with legacy fields', async () => {
|
|
183
|
+
it('lintConfig should work with legacy fields - referenceDocs', async () => {
|
|
238
184
|
const document = parseYamlToDocument(
|
|
239
185
|
outdent`
|
|
240
186
|
apis:
|