@redocly/openapi-core 1.0.0-beta.109 → 1.0.0-beta.111
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/README.md +2 -2
- package/lib/config/config-resolvers.js +44 -25
- package/lib/config/config.d.ts +1 -0
- package/lib/config/config.js +1 -0
- package/lib/config/load.d.ts +8 -2
- package/lib/config/load.js +4 -2
- package/lib/config/types.d.ts +10 -0
- package/lib/config/utils.js +2 -2
- package/lib/rules/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +5 -5
- package/lib/rules/common/assertions/asserts.d.ts +3 -5
- package/lib/rules/common/assertions/asserts.js +137 -97
- package/lib/rules/common/assertions/index.js +2 -6
- package/lib/rules/common/assertions/utils.d.ts +12 -6
- package/lib/rules/common/assertions/utils.js +33 -20
- package/lib/rules/common/no-ambiguous-paths.js +1 -1
- package/lib/rules/common/no-identical-paths.js +4 -4
- package/lib/rules/common/operation-2xx-response.js +2 -2
- package/lib/rules/common/operation-4xx-response.js +2 -2
- package/lib/rules/common/path-not-include-query.js +1 -1
- package/lib/rules/common/path-params-defined.js +7 -2
- package/lib/rules/common/response-contains-header.js +2 -2
- package/lib/rules/common/security-defined.js +10 -5
- package/lib/rules/common/spec.js +14 -12
- package/lib/rules/oas3/request-mime-type.js +1 -1
- package/lib/rules/oas3/response-mime-type.js +1 -1
- package/lib/rules/other/stats.d.ts +1 -1
- package/lib/rules/other/stats.js +1 -1
- package/lib/rules/utils.d.ts +1 -0
- package/lib/rules/utils.js +18 -2
- package/lib/types/oas2.js +6 -6
- package/lib/types/oas3.js +11 -11
- package/lib/types/oas3_1.js +3 -3
- package/lib/types/redocly-yaml.js +30 -5
- package/lib/utils.d.ts +1 -0
- package/lib/utils.js +13 -1
- package/lib/visitors.d.ts +7 -6
- package/lib/visitors.js +11 -3
- package/package.json +3 -5
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
- package/src/__tests__/lint.test.ts +88 -0
- package/src/__tests__/utils.test.ts +11 -0
- package/src/__tests__/walk.test.ts +2 -2
- package/src/config/__tests__/config-resolvers.test.ts +62 -1
- package/src/config/__tests__/config.test.ts +5 -0
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +16 -0
- package/src/config/__tests__/fixtures/resolve-config/local-config-with-wrong-custom-function.yaml +16 -0
- package/src/config/__tests__/fixtures/resolve-config/plugin.js +11 -0
- package/src/config/__tests__/load.test.ts +1 -1
- package/src/config/__tests__/resolve-plugins.test.ts +3 -3
- package/src/config/config-resolvers.ts +30 -6
- package/src/config/config.ts +2 -0
- package/src/config/load.ts +10 -4
- package/src/config/types.ts +13 -0
- package/src/config/utils.ts +1 -0
- package/src/rules/ajv.ts +4 -4
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +37 -0
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +37 -0
- package/src/rules/common/__tests__/path-params-defined.test.ts +69 -0
- package/src/rules/common/__tests__/security-defined.test.ts +6 -6
- package/src/rules/common/__tests__/spec.test.ts +125 -0
- package/src/rules/common/assertions/__tests__/asserts.test.ts +491 -428
- package/src/rules/common/assertions/__tests__/utils.test.ts +2 -2
- package/src/rules/common/assertions/asserts.ts +155 -97
- package/src/rules/common/assertions/index.ts +2 -11
- package/src/rules/common/assertions/utils.ts +66 -36
- package/src/rules/common/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-identical-paths.ts +4 -4
- package/src/rules/common/operation-2xx-response.ts +2 -2
- package/src/rules/common/operation-4xx-response.ts +2 -2
- package/src/rules/common/path-not-include-query.ts +1 -1
- package/src/rules/common/path-params-defined.ts +9 -2
- package/src/rules/common/response-contains-header.ts +6 -1
- package/src/rules/common/security-defined.ts +10 -5
- package/src/rules/common/spec.ts +15 -11
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +51 -2
- package/src/rules/oas3/__tests__/response-contains-header.test.ts +116 -0
- package/src/rules/oas3/request-mime-type.ts +1 -1
- package/src/rules/oas3/response-mime-type.ts +1 -1
- package/src/rules/other/stats.ts +1 -1
- package/src/rules/utils.ts +24 -1
- package/src/types/oas2.ts +6 -6
- package/src/types/oas3.ts +11 -11
- package/src/types/oas3_1.ts +3 -3
- package/src/types/redocly-yaml.ts +30 -4
- package/src/utils.ts +13 -0
- package/src/visitors.ts +25 -10
- package/tsconfig.tsbuildinfo +1 -1
package/lib/rules/common/spec.js
CHANGED
|
@@ -8,7 +8,7 @@ const utils_2 = require("../../utils");
|
|
|
8
8
|
const OasSpec = () => {
|
|
9
9
|
return {
|
|
10
10
|
any(node, { report, type, location, rawLocation, key, resolve, ignoreNextVisitorsOnNode }) {
|
|
11
|
-
var _a, _b, _c, _d;
|
|
11
|
+
var _a, _b, _c, _d, _e, _f;
|
|
12
12
|
const nodeType = utils_1.oasTypeOf(node);
|
|
13
13
|
const refLocation = rawLocation !== location ? rawLocation : undefined;
|
|
14
14
|
if (type.items) {
|
|
@@ -99,18 +99,20 @@ const OasSpec = () => {
|
|
|
99
99
|
if (propSchema.resolvable !== false && ref_utils_1.isRef(propValue)) {
|
|
100
100
|
propValue = resolve(propValue).node;
|
|
101
101
|
}
|
|
102
|
-
if (propSchema.enum) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.map((i) => `"${i}"`)
|
|
108
|
-
.join(', ')}.`,
|
|
109
|
-
from: refLocation,
|
|
110
|
-
suggest: utils_1.getSuggest(propValue, propSchema.enum),
|
|
102
|
+
if (propSchema.items && ((_c = propSchema.items) === null || _c === void 0 ? void 0 : _c.enum) && Array.isArray(propValue)) {
|
|
103
|
+
for (let i = 0; i < propValue.length; i++) {
|
|
104
|
+
utils_1.validateSchemaEnumType((_d = propSchema.items) === null || _d === void 0 ? void 0 : _d.enum, propValue[i], propName, refLocation, {
|
|
105
|
+
report,
|
|
106
|
+
location: location.child([propName, i]),
|
|
111
107
|
});
|
|
112
108
|
}
|
|
113
109
|
}
|
|
110
|
+
if (propSchema.enum) {
|
|
111
|
+
utils_1.validateSchemaEnumType(propSchema.enum, propValue, propName, refLocation, {
|
|
112
|
+
report,
|
|
113
|
+
location: location.child([propName]),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
114
116
|
else if (propSchema.type && !utils_1.matchesJsonSchemaType(propValue, propSchema.type, false)) {
|
|
115
117
|
report({
|
|
116
118
|
message: `Expected type \`${propSchema.type}\` but got \`${propValueType}\`.`,
|
|
@@ -118,8 +120,8 @@ const OasSpec = () => {
|
|
|
118
120
|
location: propLocation,
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
|
-
else if (propValueType === 'array' && ((
|
|
122
|
-
const itemsType = (
|
|
123
|
+
else if (propValueType === 'array' && ((_e = propSchema.items) === null || _e === void 0 ? void 0 : _e.type)) {
|
|
124
|
+
const itemsType = (_f = propSchema.items) === null || _f === void 0 ? void 0 : _f.type;
|
|
123
125
|
for (let i = 0; i < propValue.length; i++) {
|
|
124
126
|
const item = propValue[i];
|
|
125
127
|
if (!utils_1.matchesJsonSchemaType(item, itemsType, false)) {
|
|
@@ -4,7 +4,7 @@ exports.RequestMimeType = void 0;
|
|
|
4
4
|
const utils_1 = require("../../utils");
|
|
5
5
|
const RequestMimeType = ({ allowedValues }) => {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
Paths: {
|
|
8
8
|
RequestBody: {
|
|
9
9
|
leave(requestBody, ctx) {
|
|
10
10
|
utils_1.validateMimeTypeOAS3({ type: 'consumes', value: requestBody }, ctx, allowedValues);
|
|
@@ -4,7 +4,7 @@ exports.ResponseMimeType = void 0;
|
|
|
4
4
|
const utils_1 = require("../../utils");
|
|
5
5
|
const ResponseMimeType = ({ allowedValues }) => {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
Paths: {
|
|
8
8
|
Response: {
|
|
9
9
|
leave(response, ctx) {
|
|
10
10
|
utils_1.validateMimeTypeOAS3({ type: 'produces', value: response }, ctx, allowedValues);
|
package/lib/rules/other/stats.js
CHANGED
package/lib/rules/utils.d.ts
CHANGED
|
@@ -16,3 +16,4 @@ export declare function validateDefinedAndNonEmpty(fieldName: string, value: any
|
|
|
16
16
|
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
|
+
export declare function validateSchemaEnumType(schemaEnum: string[], propertyValue: string, propName: string, refLocation: Location | undefined, { report, location }: 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.getAdditionalPropertiesOption = exports.validateExample = exports.getSuggest = exports.validateDefinedAndNonEmpty = exports.fieldNonEmpty = exports.missingRequiredField = exports.matchesJsonSchemaType = exports.oasTypeOf = void 0;
|
|
3
|
+
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");
|
|
@@ -93,7 +93,7 @@ function validateExample(example, schema, dataLoc, { resolve, location, report }
|
|
|
93
93
|
for (const error of errors) {
|
|
94
94
|
report({
|
|
95
95
|
message: `Example value must conform to the schema: ${error.message}.`,
|
|
96
|
-
location: Object.assign(Object.assign({}, new ref_utils_1.Location(dataLoc.source, error.instancePath)), { reportOnKey: error.keyword === 'additionalProperties' }),
|
|
96
|
+
location: Object.assign(Object.assign({}, new ref_utils_1.Location(dataLoc.source, error.instancePath)), { reportOnKey: error.keyword === 'unevaluatedProperties' || error.keyword === 'additionalProperties' }),
|
|
97
97
|
from: location,
|
|
98
98
|
suggest: error.suggest,
|
|
99
99
|
});
|
|
@@ -120,3 +120,19 @@ function getAdditionalPropertiesOption(opts) {
|
|
|
120
120
|
return !opts.disallowAdditionalProperties;
|
|
121
121
|
}
|
|
122
122
|
exports.getAdditionalPropertiesOption = getAdditionalPropertiesOption;
|
|
123
|
+
function validateSchemaEnumType(schemaEnum, propertyValue, propName, refLocation, { report, location }) {
|
|
124
|
+
if (!schemaEnum) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!schemaEnum.includes(propertyValue === null ? 'null' : propertyValue)) {
|
|
128
|
+
report({
|
|
129
|
+
location,
|
|
130
|
+
message: `\`${propName}\` can be one of the following only: ${schemaEnum
|
|
131
|
+
.map((type) => `"${type}"`)
|
|
132
|
+
.join(', ')}.`,
|
|
133
|
+
from: refLocation,
|
|
134
|
+
suggest: getSuggest(propertyValue, schemaEnum),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.validateSchemaEnumType = validateSchemaEnumType;
|
package/lib/types/oas2.js
CHANGED
|
@@ -12,7 +12,7 @@ const Root = {
|
|
|
12
12
|
schemes: { type: 'array', items: { type: 'string' } },
|
|
13
13
|
consumes: { type: 'array', items: { type: 'string' } },
|
|
14
14
|
produces: { type: 'array', items: { type: 'string' } },
|
|
15
|
-
paths: '
|
|
15
|
+
paths: 'Paths',
|
|
16
16
|
definitions: 'NamedSchemas',
|
|
17
17
|
parameters: 'NamedParameters',
|
|
18
18
|
responses: 'NamedResponses',
|
|
@@ -48,7 +48,7 @@ const License = {
|
|
|
48
48
|
},
|
|
49
49
|
required: ['name'],
|
|
50
50
|
};
|
|
51
|
-
const
|
|
51
|
+
const Paths = {
|
|
52
52
|
properties: {},
|
|
53
53
|
additionalProperties: (_value, key) => key.startsWith('/') ? 'PathItem' : undefined,
|
|
54
54
|
};
|
|
@@ -75,7 +75,7 @@ const Operation = {
|
|
|
75
75
|
consumes: { type: 'array', items: { type: 'string' } },
|
|
76
76
|
produces: { type: 'array', items: { type: 'string' } },
|
|
77
77
|
parameters: _1.listOf('Parameter'),
|
|
78
|
-
responses: '
|
|
78
|
+
responses: 'Responses',
|
|
79
79
|
schemes: { type: 'array', items: { type: 'string' } },
|
|
80
80
|
deprecated: { type: 'boolean' },
|
|
81
81
|
security: _1.listOf('SecurityRequirement'),
|
|
@@ -171,7 +171,7 @@ const ParameterItems = {
|
|
|
171
171
|
}
|
|
172
172
|
},
|
|
173
173
|
};
|
|
174
|
-
const
|
|
174
|
+
const Responses = {
|
|
175
175
|
properties: {
|
|
176
176
|
default: 'Response',
|
|
177
177
|
},
|
|
@@ -359,14 +359,14 @@ exports.Oas2Types = {
|
|
|
359
359
|
Info,
|
|
360
360
|
Contact,
|
|
361
361
|
License,
|
|
362
|
-
|
|
362
|
+
Paths,
|
|
363
363
|
PathItem,
|
|
364
364
|
Parameter,
|
|
365
365
|
ParameterItems,
|
|
366
366
|
Operation,
|
|
367
367
|
Examples,
|
|
368
368
|
Header,
|
|
369
|
-
|
|
369
|
+
Responses,
|
|
370
370
|
Response,
|
|
371
371
|
Schema,
|
|
372
372
|
Xml,
|
package/lib/types/oas3.js
CHANGED
|
@@ -12,7 +12,7 @@ const Root = {
|
|
|
12
12
|
security: _1.listOf('SecurityRequirement'),
|
|
13
13
|
tags: _1.listOf('Tag'),
|
|
14
14
|
externalDocs: 'ExternalDocs',
|
|
15
|
-
paths: '
|
|
15
|
+
paths: 'Paths',
|
|
16
16
|
components: 'Components',
|
|
17
17
|
'x-webhooks': 'WebhooksMap',
|
|
18
18
|
},
|
|
@@ -81,7 +81,7 @@ const License = {
|
|
|
81
81
|
},
|
|
82
82
|
required: ['name'],
|
|
83
83
|
};
|
|
84
|
-
const
|
|
84
|
+
const Paths = {
|
|
85
85
|
properties: {},
|
|
86
86
|
additionalProperties: (_value, key) => key.startsWith('/') ? 'PathItem' : undefined,
|
|
87
87
|
};
|
|
@@ -141,7 +141,7 @@ const Operation = {
|
|
|
141
141
|
security: _1.listOf('SecurityRequirement'),
|
|
142
142
|
servers: _1.listOf('Server'),
|
|
143
143
|
requestBody: 'RequestBody',
|
|
144
|
-
responses: '
|
|
144
|
+
responses: 'Responses',
|
|
145
145
|
deprecated: { type: 'boolean' },
|
|
146
146
|
callbacks: 'CallbacksMap',
|
|
147
147
|
'x-codeSamples': _1.listOf('XCodeSample'),
|
|
@@ -174,7 +174,7 @@ const MediaType = {
|
|
|
174
174
|
schema: 'Schema',
|
|
175
175
|
example: { isExample: true },
|
|
176
176
|
examples: 'ExamplesMap',
|
|
177
|
-
encoding: '
|
|
177
|
+
encoding: 'EncodingMap',
|
|
178
178
|
},
|
|
179
179
|
};
|
|
180
180
|
const Example = {
|
|
@@ -214,7 +214,7 @@ const Header = {
|
|
|
214
214
|
},
|
|
215
215
|
requiredOneOf: ['schema', 'content'],
|
|
216
216
|
};
|
|
217
|
-
const
|
|
217
|
+
const Responses = {
|
|
218
218
|
properties: { default: 'Response' },
|
|
219
219
|
additionalProperties: (_v, key) => responseCodeRegexp.test(key) ? 'Response' : undefined,
|
|
220
220
|
};
|
|
@@ -378,7 +378,7 @@ const AuthorizationCode = {
|
|
|
378
378
|
},
|
|
379
379
|
required: ['authorizationUrl', 'tokenUrl', 'scopes'],
|
|
380
380
|
};
|
|
381
|
-
const
|
|
381
|
+
const OAuth2Flows = {
|
|
382
382
|
properties: {
|
|
383
383
|
implicit: 'ImplicitFlow',
|
|
384
384
|
password: 'PasswordFlow',
|
|
@@ -394,7 +394,7 @@ const SecurityScheme = {
|
|
|
394
394
|
in: { type: 'string', enum: ['query', 'header', 'cookie'] },
|
|
395
395
|
scheme: { type: 'string' },
|
|
396
396
|
bearerFormat: { type: 'string' },
|
|
397
|
-
flows: '
|
|
397
|
+
flows: 'OAuth2Flows',
|
|
398
398
|
openIdConnectUrl: { type: 'string' },
|
|
399
399
|
},
|
|
400
400
|
required(value) {
|
|
@@ -438,7 +438,7 @@ exports.Oas3Types = {
|
|
|
438
438
|
Info,
|
|
439
439
|
Contact,
|
|
440
440
|
License,
|
|
441
|
-
|
|
441
|
+
Paths,
|
|
442
442
|
PathItem,
|
|
443
443
|
Parameter,
|
|
444
444
|
Operation,
|
|
@@ -450,10 +450,10 @@ exports.Oas3Types = {
|
|
|
450
450
|
Example,
|
|
451
451
|
ExamplesMap: _1.mapOf('Example'),
|
|
452
452
|
Encoding,
|
|
453
|
-
|
|
453
|
+
EncodingMap: _1.mapOf('Encoding'),
|
|
454
454
|
Header,
|
|
455
455
|
HeadersMap: _1.mapOf('Header'),
|
|
456
|
-
|
|
456
|
+
Responses,
|
|
457
457
|
Response,
|
|
458
458
|
Link,
|
|
459
459
|
Schema,
|
|
@@ -476,7 +476,7 @@ exports.Oas3Types = {
|
|
|
476
476
|
PasswordFlow,
|
|
477
477
|
ClientCredentials,
|
|
478
478
|
AuthorizationCode,
|
|
479
|
-
|
|
479
|
+
OAuth2Flows,
|
|
480
480
|
SecurityScheme,
|
|
481
481
|
XCodeSample,
|
|
482
482
|
WebhooksMap,
|
package/lib/types/oas3_1.js
CHANGED
|
@@ -11,7 +11,7 @@ const Root = {
|
|
|
11
11
|
security: _1.listOf('SecurityRequirement'),
|
|
12
12
|
tags: _1.listOf('Tag'),
|
|
13
13
|
externalDocs: 'ExternalDocs',
|
|
14
|
-
paths: '
|
|
14
|
+
paths: 'Paths',
|
|
15
15
|
webhooks: 'WebhooksMap',
|
|
16
16
|
components: 'Components',
|
|
17
17
|
jsonSchemaDialect: { type: 'string' },
|
|
@@ -67,7 +67,7 @@ const Operation = {
|
|
|
67
67
|
security: _1.listOf('SecurityRequirement'),
|
|
68
68
|
servers: _1.listOf('Server'),
|
|
69
69
|
requestBody: 'RequestBody',
|
|
70
|
-
responses: '
|
|
70
|
+
responses: 'Responses',
|
|
71
71
|
deprecated: { type: 'boolean' },
|
|
72
72
|
callbacks: _1.mapOf('Callback'),
|
|
73
73
|
'x-codeSamples': _1.listOf('XCodeSample'),
|
|
@@ -175,7 +175,7 @@ const SecurityScheme = {
|
|
|
175
175
|
in: { type: 'string', enum: ['query', 'header', 'cookie'] },
|
|
176
176
|
scheme: { type: 'string' },
|
|
177
177
|
bearerFormat: { type: 'string' },
|
|
178
|
-
flows: '
|
|
178
|
+
flows: 'OAuth2Flows',
|
|
179
179
|
openIdConnectUrl: { type: 'string' },
|
|
180
180
|
},
|
|
181
181
|
required(value) {
|
|
@@ -68,7 +68,7 @@ const nodeTypesList = [
|
|
|
68
68
|
'Info',
|
|
69
69
|
'Contact',
|
|
70
70
|
'License',
|
|
71
|
-
'
|
|
71
|
+
'Paths',
|
|
72
72
|
'PathItem',
|
|
73
73
|
'Parameter',
|
|
74
74
|
'Operation',
|
|
@@ -80,10 +80,10 @@ const nodeTypesList = [
|
|
|
80
80
|
'Example',
|
|
81
81
|
'ExamplesMap',
|
|
82
82
|
'Encoding',
|
|
83
|
-
'
|
|
83
|
+
'EncodingMap',
|
|
84
84
|
'Header',
|
|
85
85
|
'HeadersMap',
|
|
86
|
-
'
|
|
86
|
+
'Responses',
|
|
87
87
|
'Response',
|
|
88
88
|
'Link',
|
|
89
89
|
'LinksMap',
|
|
@@ -106,7 +106,7 @@ const nodeTypesList = [
|
|
|
106
106
|
'PasswordFlow',
|
|
107
107
|
'ClientCredentials',
|
|
108
108
|
'AuthorizationCode',
|
|
109
|
-
'
|
|
109
|
+
'OAuth2Flows',
|
|
110
110
|
'SecurityScheme',
|
|
111
111
|
'XCodeSample',
|
|
112
112
|
'WebhooksMap',
|
|
@@ -149,6 +149,11 @@ const ConfigRoot = {
|
|
|
149
149
|
http: 'ConfigHTTP',
|
|
150
150
|
doNotResolveExamples: { type: 'boolean' },
|
|
151
151
|
},
|
|
152
|
+
}, files: {
|
|
153
|
+
type: 'array',
|
|
154
|
+
items: {
|
|
155
|
+
type: 'string',
|
|
156
|
+
},
|
|
152
157
|
} }),
|
|
153
158
|
};
|
|
154
159
|
const ConfigApis = {
|
|
@@ -161,7 +166,12 @@ const ConfigApisProperties = {
|
|
|
161
166
|
items: {
|
|
162
167
|
type: 'string',
|
|
163
168
|
},
|
|
164
|
-
}, lint: 'ConfigStyleguide', styleguide: 'ConfigStyleguide' }, ConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer'
|
|
169
|
+
}, lint: 'ConfigStyleguide', styleguide: 'ConfigStyleguide' }, ConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', files: {
|
|
170
|
+
type: 'array',
|
|
171
|
+
items: {
|
|
172
|
+
type: 'string',
|
|
173
|
+
},
|
|
174
|
+
} }),
|
|
165
175
|
required: ['root'],
|
|
166
176
|
};
|
|
167
177
|
const ConfigHTTP = {
|
|
@@ -249,6 +259,11 @@ const Assert = {
|
|
|
249
259
|
maxLength: { type: 'integer' },
|
|
250
260
|
ref: (value) => typeof value === 'string' ? { type: 'string' } : { type: 'boolean' },
|
|
251
261
|
},
|
|
262
|
+
additionalProperties: (_value, key) => {
|
|
263
|
+
if (/^\w+\/\w+$/.test(key))
|
|
264
|
+
return { type: 'object' };
|
|
265
|
+
return;
|
|
266
|
+
},
|
|
252
267
|
required: ['subject'],
|
|
253
268
|
};
|
|
254
269
|
const Context = {
|
|
@@ -743,6 +758,16 @@ const ConfigReferenceDocs = {
|
|
|
743
758
|
unstable_externalDescription: { type: 'boolean' },
|
|
744
759
|
unstable_ignoreMimeParameters: { type: 'boolean' },
|
|
745
760
|
untrustedDefinition: { type: 'boolean' },
|
|
761
|
+
mockServer: {
|
|
762
|
+
properties: {
|
|
763
|
+
url: { type: 'string' },
|
|
764
|
+
position: { enum: ['first', 'last', 'replace', 'off'] },
|
|
765
|
+
description: { type: 'string' },
|
|
766
|
+
},
|
|
767
|
+
},
|
|
768
|
+
showAccessMode: { type: 'boolean' },
|
|
769
|
+
preserveOriginalExtensionsName: { type: 'boolean' },
|
|
770
|
+
markdownHeadingsAnchorLevel: { type: 'number' },
|
|
746
771
|
},
|
|
747
772
|
additionalProperties: { type: 'string' },
|
|
748
773
|
};
|
package/lib/utils.d.ts
CHANGED
|
@@ -46,3 +46,4 @@ export declare function showErrorForDeprecatedField(deprecatedField: string, upd
|
|
|
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;
|
|
49
|
+
export declare function pickDefined<T extends Record<string, unknown>>(obj?: T): Record<string, unknown> | undefined;
|
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.isDefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
12
|
+
exports.pickDefined = 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");
|
|
@@ -205,3 +205,15 @@ function identity(value) {
|
|
|
205
205
|
return value;
|
|
206
206
|
}
|
|
207
207
|
exports.identity = identity;
|
|
208
|
+
function pickDefined(obj) {
|
|
209
|
+
if (!obj)
|
|
210
|
+
return undefined;
|
|
211
|
+
const res = {};
|
|
212
|
+
for (const key in obj) {
|
|
213
|
+
if (obj[key] !== undefined) {
|
|
214
|
+
res[key] = obj[key];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return res;
|
|
218
|
+
}
|
|
219
|
+
exports.pickDefined = pickDefined;
|
package/lib/visitors.d.ts
CHANGED
|
@@ -70,9 +70,10 @@ declare type Oas3FlatVisitor = {
|
|
|
70
70
|
Info?: VisitFunctionOrObject<Oas3Info>;
|
|
71
71
|
Contact?: VisitFunctionOrObject<Oas3Contact>;
|
|
72
72
|
License?: VisitFunctionOrObject<Oas3License>;
|
|
73
|
-
|
|
73
|
+
Paths?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
|
|
74
74
|
PathItem?: VisitFunctionOrObject<Oas3PathItem>;
|
|
75
|
-
Callback?: VisitFunctionOrObject<
|
|
75
|
+
Callback?: VisitFunctionOrObject<Oas3Callback>;
|
|
76
|
+
CallbacksMap?: VisitFunctionOrObject<Record<string, Oas3Callback>>;
|
|
76
77
|
Parameter?: VisitFunctionOrObject<Oas3Parameter>;
|
|
77
78
|
Operation?: VisitFunctionOrObject<Oas3Operation>;
|
|
78
79
|
RequestBody?: VisitFunctionOrObject<Oas3RequestBody>;
|
|
@@ -81,7 +82,7 @@ declare type Oas3FlatVisitor = {
|
|
|
81
82
|
Example?: VisitFunctionOrObject<Oas3Example>;
|
|
82
83
|
Encoding?: VisitFunctionOrObject<Oas3Encoding>;
|
|
83
84
|
Header?: VisitFunctionOrObject<Oas3Header>;
|
|
84
|
-
|
|
85
|
+
Responses?: VisitFunctionOrObject<Record<string, Oas3Response>>;
|
|
85
86
|
Response?: VisitFunctionOrObject<Oas3Response>;
|
|
86
87
|
Link?: VisitFunctionOrObject<Oas3Link>;
|
|
87
88
|
Schema?: VisitFunctionOrObject<Oas3Schema>;
|
|
@@ -103,7 +104,7 @@ declare type Oas3FlatVisitor = {
|
|
|
103
104
|
PasswordFlow?: VisitFunctionOrObject<Oas3SecurityScheme['flows']['password']>;
|
|
104
105
|
ClientCredentials?: VisitFunctionOrObject<Oas3SecurityScheme['flows']['clientCredentials']>;
|
|
105
106
|
AuthorizationCode?: VisitFunctionOrObject<Oas3SecurityScheme['flows']['authorizationCode']>;
|
|
106
|
-
|
|
107
|
+
OAuth2Flows?: VisitFunctionOrObject<Oas3SecurityScheme['flows']>;
|
|
107
108
|
SecurityScheme?: VisitFunctionOrObject<Oas3SecurityScheme>;
|
|
108
109
|
};
|
|
109
110
|
declare type Oas2FlatVisitor = {
|
|
@@ -114,13 +115,13 @@ declare type Oas2FlatVisitor = {
|
|
|
114
115
|
Info?: VisitFunctionOrObject<Oas2Info>;
|
|
115
116
|
Contact?: VisitFunctionOrObject<Oas2Contact>;
|
|
116
117
|
License?: VisitFunctionOrObject<Oas2License>;
|
|
117
|
-
|
|
118
|
+
Paths?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
|
|
118
119
|
PathItem?: VisitFunctionOrObject<Oas2PathItem>;
|
|
119
120
|
Parameter?: VisitFunctionOrObject<any>;
|
|
120
121
|
Operation?: VisitFunctionOrObject<Oas2Operation>;
|
|
121
122
|
Examples?: VisitFunctionOrObject<Record<string, any>>;
|
|
122
123
|
Header?: VisitFunctionOrObject<Oas2Header>;
|
|
123
|
-
|
|
124
|
+
Responses?: VisitFunctionOrObject<Record<string, Oas2Response>>;
|
|
124
125
|
Response?: VisitFunctionOrObject<Oas2Response>;
|
|
125
126
|
Schema?: VisitFunctionOrObject<Oas2Schema>;
|
|
126
127
|
Xml?: VisitFunctionOrObject<Oas2Xml>;
|
package/lib/visitors.js
CHANGED
|
@@ -4,13 +4,14 @@ exports.normalizeVisitors = void 0;
|
|
|
4
4
|
const legacyTypesMap = {
|
|
5
5
|
Root: 'DefinitionRoot',
|
|
6
6
|
ServerVariablesMap: 'ServerVariableMap',
|
|
7
|
-
|
|
7
|
+
Paths: ['PathMap', 'PathsMap'],
|
|
8
8
|
CallbacksMap: 'CallbackMap',
|
|
9
9
|
MediaTypesMap: 'MediaTypeMap',
|
|
10
10
|
ExamplesMap: 'ExampleMap',
|
|
11
|
-
|
|
11
|
+
EncodingMap: 'EncodingsMap',
|
|
12
12
|
HeadersMap: 'HeaderMap',
|
|
13
13
|
LinksMap: 'LinkMap',
|
|
14
|
+
OAuth2Flows: 'SecuritySchemeFlows',
|
|
14
15
|
};
|
|
15
16
|
function normalizeVisitors(visitorsConfig, types) {
|
|
16
17
|
const normalizedVisitors = {};
|
|
@@ -85,6 +86,13 @@ function normalizeVisitors(visitorsConfig, types) {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
}
|
|
89
|
+
function findLegacyVisitorNode(visitor, typeName) {
|
|
90
|
+
if (Array.isArray(typeName)) {
|
|
91
|
+
const name = typeName.find((name) => visitor[name]) || undefined;
|
|
92
|
+
return name && visitor[name];
|
|
93
|
+
}
|
|
94
|
+
return visitor[typeName];
|
|
95
|
+
}
|
|
88
96
|
function normalizeVisitorLevel(ruleConf, visitor, parentContext, depth = 0) {
|
|
89
97
|
const visitorKeys = Object.keys(types);
|
|
90
98
|
if (depth === 0) {
|
|
@@ -101,7 +109,7 @@ function normalizeVisitors(visitorsConfig, types) {
|
|
|
101
109
|
}
|
|
102
110
|
for (const typeName of visitorKeys) {
|
|
103
111
|
const typeVisitor = (visitor[typeName] ||
|
|
104
|
-
visitor
|
|
112
|
+
findLegacyVisitorNode(visitor, legacyTypesMap[typeName]));
|
|
105
113
|
const normalizedTypeVisitor = normalizedVisitors[typeName];
|
|
106
114
|
if (!typeVisitor)
|
|
107
115
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/openapi-core",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.111",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -29,12 +29,10 @@
|
|
|
29
29
|
"oas"
|
|
30
30
|
],
|
|
31
31
|
"contributors": [
|
|
32
|
-
"
|
|
33
|
-
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)",
|
|
34
|
-
"Andriy Leliv <andriy@redoc.ly> (https://redoc.ly/)"
|
|
32
|
+
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
35
33
|
],
|
|
36
34
|
"dependencies": {
|
|
37
|
-
"@redocly/ajv": "^8.
|
|
35
|
+
"@redocly/ajv": "^8.11.0",
|
|
38
36
|
"@types/node": "^14.11.8",
|
|
39
37
|
"colorette": "^1.2.0",
|
|
40
38
|
"js-levenshtein": "^1.1.6",
|
|
@@ -60,6 +60,22 @@ describe('lint', () => {
|
|
|
60
60
|
no-invalid-media-type-examples: error
|
|
61
61
|
path-http-verbs-order: error
|
|
62
62
|
boolean-parameter-prefixes: off
|
|
63
|
+
assert/operation-summary-length:
|
|
64
|
+
subject: Operation
|
|
65
|
+
property: summary
|
|
66
|
+
message: Operation summary should start with an active verb
|
|
67
|
+
local/checkWordsCount:
|
|
68
|
+
min: 3
|
|
69
|
+
features.openapi:
|
|
70
|
+
showConsole: true
|
|
71
|
+
layout:
|
|
72
|
+
scope: section
|
|
73
|
+
routingStrategy: browser
|
|
74
|
+
theme:
|
|
75
|
+
rightPanel:
|
|
76
|
+
backgroundColor: '#263238'
|
|
77
|
+
links:
|
|
78
|
+
color: '#6CC496'
|
|
63
79
|
features.openapi:
|
|
64
80
|
showConsole: true
|
|
65
81
|
layout:
|
|
@@ -77,6 +93,78 @@ describe('lint', () => {
|
|
|
77
93
|
|
|
78
94
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
79
95
|
Array [
|
|
96
|
+
Object {
|
|
97
|
+
"from": undefined,
|
|
98
|
+
"location": Array [
|
|
99
|
+
Object {
|
|
100
|
+
"pointer": "#/atures.openapi",
|
|
101
|
+
"reportOnKey": true,
|
|
102
|
+
"source": "",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
"message": "Property \`atures.openapi\` is not expected here.",
|
|
106
|
+
"ruleId": "configuration spec",
|
|
107
|
+
"severity": "error",
|
|
108
|
+
"suggest": Array [
|
|
109
|
+
"features.openapi",
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
Object {
|
|
113
|
+
"from": undefined,
|
|
114
|
+
"location": Array [
|
|
115
|
+
Object {
|
|
116
|
+
"pointer": "#/showConsole",
|
|
117
|
+
"reportOnKey": true,
|
|
118
|
+
"source": "",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
"message": "Property \`showConsole\` is not expected here.",
|
|
122
|
+
"ruleId": "configuration spec",
|
|
123
|
+
"severity": "error",
|
|
124
|
+
"suggest": Array [],
|
|
125
|
+
},
|
|
126
|
+
Object {
|
|
127
|
+
"from": undefined,
|
|
128
|
+
"location": Array [
|
|
129
|
+
Object {
|
|
130
|
+
"pointer": "#/layout",
|
|
131
|
+
"reportOnKey": true,
|
|
132
|
+
"source": "",
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
"message": "Property \`layout\` is not expected here.",
|
|
136
|
+
"ruleId": "configuration spec",
|
|
137
|
+
"severity": "error",
|
|
138
|
+
"suggest": Array [],
|
|
139
|
+
},
|
|
140
|
+
Object {
|
|
141
|
+
"from": undefined,
|
|
142
|
+
"location": Array [
|
|
143
|
+
Object {
|
|
144
|
+
"pointer": "#/routingStrategy",
|
|
145
|
+
"reportOnKey": true,
|
|
146
|
+
"source": "",
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
"message": "Property \`routingStrategy\` is not expected here.",
|
|
150
|
+
"ruleId": "configuration spec",
|
|
151
|
+
"severity": "error",
|
|
152
|
+
"suggest": Array [],
|
|
153
|
+
},
|
|
154
|
+
Object {
|
|
155
|
+
"from": undefined,
|
|
156
|
+
"location": Array [
|
|
157
|
+
Object {
|
|
158
|
+
"pointer": "#/theme",
|
|
159
|
+
"reportOnKey": true,
|
|
160
|
+
"source": "",
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
"message": "Property \`theme\` is not expected here.",
|
|
164
|
+
"ruleId": "configuration spec",
|
|
165
|
+
"severity": "error",
|
|
166
|
+
"suggest": Array [],
|
|
167
|
+
},
|
|
80
168
|
Object {
|
|
81
169
|
"from": undefined,
|
|
82
170
|
"location": Array [
|