@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
|
@@ -24,7 +24,7 @@ describe('collect refs', () => {
|
|
|
24
24
|
const resolvedRefs = await resolveDocument({
|
|
25
25
|
rootDocument,
|
|
26
26
|
externalRefResolver: new BaseResolver(),
|
|
27
|
-
rootType: normalizeTypes(Oas3Types).
|
|
27
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -63,7 +63,7 @@ describe('collect refs', () => {
|
|
|
63
63
|
await resolveDocument({
|
|
64
64
|
rootDocument,
|
|
65
65
|
externalRefResolver: new BaseResolver(),
|
|
66
|
-
rootType: normalizeTypes(Oas3Types).
|
|
66
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
67
67
|
});
|
|
68
68
|
} catch (e) {
|
|
69
69
|
expect(e.message).toEqual('Self-referencing circular pointer');
|
|
@@ -95,7 +95,7 @@ describe('collect refs', () => {
|
|
|
95
95
|
const resolvedRefs = await resolveDocument({
|
|
96
96
|
rootDocument,
|
|
97
97
|
externalRefResolver: new BaseResolver(),
|
|
98
|
-
rootType: normalizeTypes(Oas3Types).
|
|
98
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -132,7 +132,7 @@ describe('collect refs', () => {
|
|
|
132
132
|
await resolveDocument({
|
|
133
133
|
rootDocument,
|
|
134
134
|
externalRefResolver: new BaseResolver(),
|
|
135
|
-
rootType: normalizeTypes(Oas3Types).
|
|
135
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
136
136
|
});
|
|
137
137
|
} catch (e) {
|
|
138
138
|
expect(e.message).toEqual('Self-referencing circular pointer');
|
|
@@ -153,7 +153,7 @@ describe('collect refs', () => {
|
|
|
153
153
|
const resolvedRefs = await resolveDocument({
|
|
154
154
|
rootDocument,
|
|
155
155
|
externalRefResolver: new BaseResolver(),
|
|
156
|
-
rootType: normalizeTypes(Oas3Types).
|
|
156
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -187,7 +187,7 @@ describe('collect refs', () => {
|
|
|
187
187
|
const resolvedRefs = await resolveDocument({
|
|
188
188
|
rootDocument: rootDocument as Document,
|
|
189
189
|
externalRefResolver: externalRefResolver,
|
|
190
|
-
rootType: normalizeTypes(Oas3Types).
|
|
190
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
191
191
|
});
|
|
192
192
|
|
|
193
193
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -263,7 +263,7 @@ describe('collect refs', () => {
|
|
|
263
263
|
const resolvedRefs = await resolveDocument({
|
|
264
264
|
rootDocument: rootDocument as Document,
|
|
265
265
|
externalRefResolver: externalRefResolver,
|
|
266
|
-
rootType: normalizeTypes(Oas3Types).
|
|
266
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
267
267
|
});
|
|
268
268
|
|
|
269
269
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -358,7 +358,7 @@ describe('collect refs', () => {
|
|
|
358
358
|
const resolvedRefs = await resolveDocument({
|
|
359
359
|
rootDocument: rootDocument as Document,
|
|
360
360
|
externalRefResolver: externalRefResolver,
|
|
361
|
-
rootType: normalizeTypes(Oas3Types).
|
|
361
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
362
362
|
});
|
|
363
363
|
|
|
364
364
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -392,7 +392,7 @@ describe('collect refs', () => {
|
|
|
392
392
|
const resolvedRefs = await resolveDocument({
|
|
393
393
|
rootDocument,
|
|
394
394
|
externalRefResolver: new BaseResolver(),
|
|
395
|
-
rootType: normalizeTypes(Oas3Types).
|
|
395
|
+
rootType: normalizeTypes(Oas3Types).Root,
|
|
396
396
|
});
|
|
397
397
|
|
|
398
398
|
expect(resolvedRefs).toBeDefined();
|
|
@@ -16,7 +16,7 @@ import { Oas3RuleSet } from '../oas-types';
|
|
|
16
16
|
describe('walk order', () => {
|
|
17
17
|
it('should run visitors', async () => {
|
|
18
18
|
const visitors = {
|
|
19
|
-
|
|
19
|
+
Root: {
|
|
20
20
|
enter: jest.fn(),
|
|
21
21
|
leave: jest.fn(),
|
|
22
22
|
},
|
|
@@ -63,6 +63,74 @@ describe('walk order', () => {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
it('should run legacy visitors', async () => {
|
|
67
|
+
const visitors = {
|
|
68
|
+
DefinitionRoot: {
|
|
69
|
+
enter: jest.fn(),
|
|
70
|
+
leave: jest.fn(),
|
|
71
|
+
},
|
|
72
|
+
PathMap: {
|
|
73
|
+
enter: jest.fn(),
|
|
74
|
+
leave: jest.fn(),
|
|
75
|
+
},
|
|
76
|
+
ServerVariableMap: {
|
|
77
|
+
enter: jest.fn(),
|
|
78
|
+
leave: jest.fn(),
|
|
79
|
+
},
|
|
80
|
+
MediaTypeMap: {
|
|
81
|
+
enter: jest.fn(),
|
|
82
|
+
leave: jest.fn(),
|
|
83
|
+
},
|
|
84
|
+
ExampleMap: {
|
|
85
|
+
enter: jest.fn(),
|
|
86
|
+
leave: jest.fn(),
|
|
87
|
+
},
|
|
88
|
+
HeaderMap: {
|
|
89
|
+
enter: jest.fn(),
|
|
90
|
+
leave: jest.fn(),
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const testRuleSet: Oas3RuleSet = {
|
|
95
|
+
test: jest.fn(() => {
|
|
96
|
+
return visitors;
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const document = parseYamlToDocument(
|
|
101
|
+
outdent`
|
|
102
|
+
openapi: 3.0.0
|
|
103
|
+
servers:
|
|
104
|
+
- url: http://{test}.url
|
|
105
|
+
variables:
|
|
106
|
+
test: test
|
|
107
|
+
paths:
|
|
108
|
+
/test-path:
|
|
109
|
+
get:
|
|
110
|
+
responses:
|
|
111
|
+
200:
|
|
112
|
+
headers: {}
|
|
113
|
+
content:
|
|
114
|
+
application/json:
|
|
115
|
+
schema: {}
|
|
116
|
+
examples: {}
|
|
117
|
+
`,
|
|
118
|
+
''
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
await lintDocument({
|
|
122
|
+
externalRefResolver: new BaseResolver(),
|
|
123
|
+
document,
|
|
124
|
+
config: makeConfigForRuleset(testRuleSet),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(testRuleSet.test).toBeCalledTimes(1);
|
|
128
|
+
for (const fns of Object.values(visitors)) {
|
|
129
|
+
expect(fns.enter).toBeCalled();
|
|
130
|
+
expect(fns.leave).toBeCalled();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
66
134
|
it('should run nested visitors correctly', async () => {
|
|
67
135
|
const calls: string[] = [];
|
|
68
136
|
|
|
@@ -1046,8 +1114,8 @@ describe('walk order', () => {
|
|
|
1046
1114
|
|
|
1047
1115
|
expect(calls).toMatchInlineSnapshot(`
|
|
1048
1116
|
Array [
|
|
1049
|
-
"enter
|
|
1050
|
-
"enter
|
|
1117
|
+
"enter Root",
|
|
1118
|
+
"enter PathsMap",
|
|
1051
1119
|
"enter PathItem",
|
|
1052
1120
|
"enter ParameterList",
|
|
1053
1121
|
"enter Parameter",
|
|
@@ -1066,7 +1134,7 @@ describe('walk order', () => {
|
|
|
1066
1134
|
"leave ParameterList",
|
|
1067
1135
|
"leave Operation",
|
|
1068
1136
|
"leave PathItem",
|
|
1069
|
-
"leave
|
|
1137
|
+
"leave PathsMap",
|
|
1070
1138
|
"enter Components",
|
|
1071
1139
|
"enter NamedParameters",
|
|
1072
1140
|
"leave NamedParameters",
|
|
@@ -1075,7 +1143,7 @@ describe('walk order', () => {
|
|
|
1075
1143
|
"leave Schema",
|
|
1076
1144
|
"leave NamedSchemas",
|
|
1077
1145
|
"leave Components",
|
|
1078
|
-
"leave
|
|
1146
|
+
"leave Root",
|
|
1079
1147
|
]
|
|
1080
1148
|
`);
|
|
1081
1149
|
});
|
|
@@ -1378,10 +1446,10 @@ describe('type extensions', () => {
|
|
|
1378
1446
|
parameters: listOf('Parameter'),
|
|
1379
1447
|
},
|
|
1380
1448
|
},
|
|
1381
|
-
|
|
1382
|
-
...types.
|
|
1449
|
+
Root: {
|
|
1450
|
+
...types.Root,
|
|
1383
1451
|
properties: {
|
|
1384
|
-
...types.
|
|
1452
|
+
...types.Root.properties,
|
|
1385
1453
|
'x-webhooks': 'XWebHooks',
|
|
1386
1454
|
},
|
|
1387
1455
|
},
|
|
@@ -1393,7 +1461,7 @@ describe('type extensions', () => {
|
|
|
1393
1461
|
|
|
1394
1462
|
expect(calls).toMatchInlineSnapshot(`
|
|
1395
1463
|
Array [
|
|
1396
|
-
"enter
|
|
1464
|
+
"enter Root",
|
|
1397
1465
|
"enter XWebHooks",
|
|
1398
1466
|
"enter hook test",
|
|
1399
1467
|
"enter ParameterList",
|
|
@@ -1402,7 +1470,7 @@ describe('type extensions', () => {
|
|
|
1402
1470
|
"leave ParameterList",
|
|
1403
1471
|
"leave hook test",
|
|
1404
1472
|
"leave XWebHooks",
|
|
1405
|
-
"leave
|
|
1473
|
+
"leave Root",
|
|
1406
1474
|
]
|
|
1407
1475
|
`);
|
|
1408
1476
|
});
|
package/src/bundle.ts
CHANGED
|
@@ -122,7 +122,7 @@ export async function bundleDocument(opts: {
|
|
|
122
122
|
|
|
123
123
|
const resolvedRefMap = await resolveDocument({
|
|
124
124
|
rootDocument: document,
|
|
125
|
-
rootType: types.
|
|
125
|
+
rootType: types.Root,
|
|
126
126
|
externalRefResolver,
|
|
127
127
|
});
|
|
128
128
|
|
|
@@ -148,7 +148,7 @@ export async function bundleDocument(opts: {
|
|
|
148
148
|
|
|
149
149
|
walkDocument({
|
|
150
150
|
document,
|
|
151
|
-
rootType: types.
|
|
151
|
+
rootType: types.Root as NormalizedNodeType,
|
|
152
152
|
normalizedVisitors: bundleVisitor,
|
|
153
153
|
resolvedRefMap,
|
|
154
154
|
ctx,
|
|
@@ -158,7 +158,7 @@ export async function bundleDocument(opts: {
|
|
|
158
158
|
bundle: document,
|
|
159
159
|
problems: ctx.problems.map((problem) => config.addProblemToIgnore(problem)),
|
|
160
160
|
fileDependencies: externalRefResolver.getFiles(),
|
|
161
|
-
rootType: types.
|
|
161
|
+
rootType: types.Root,
|
|
162
162
|
refTypes: ctx.refTypes,
|
|
163
163
|
visitorsData: ctx.visitorsData,
|
|
164
164
|
};
|
|
@@ -254,7 +254,7 @@ function makeBundleVisitor(
|
|
|
254
254
|
}
|
|
255
255
|
},
|
|
256
256
|
},
|
|
257
|
-
|
|
257
|
+
Root: {
|
|
258
258
|
enter(root: any) {
|
|
259
259
|
if (version === OasMajorVersion.Version3) {
|
|
260
260
|
components = root.components = root.components || {};
|
|
@@ -18,6 +18,7 @@ Object {
|
|
|
18
18
|
"no-server-variables-empty-enum": "error",
|
|
19
19
|
"no-undefined-server-variable": "error",
|
|
20
20
|
"no-unused-components": "warn",
|
|
21
|
+
"spec-components-invalid-map-name": "error",
|
|
21
22
|
},
|
|
22
23
|
"oas3_1Decorators": Object {},
|
|
23
24
|
"oas3_1Preprocessors": Object {},
|
|
@@ -30,6 +31,7 @@ Object {
|
|
|
30
31
|
"no-server-variables-empty-enum": "error",
|
|
31
32
|
"no-undefined-server-variable": "error",
|
|
32
33
|
"no-unused-components": "warn",
|
|
34
|
+
"spec-components-invalid-map-name": "error",
|
|
33
35
|
},
|
|
34
36
|
"preprocessors": Object {},
|
|
35
37
|
"recommendedFallback": false,
|
|
@@ -54,7 +56,6 @@ Object {
|
|
|
54
56
|
"operation-operationId-unique": "error",
|
|
55
57
|
"operation-operationId-url-safe": "error",
|
|
56
58
|
"operation-parameters-unique": "error",
|
|
57
|
-
"operation-security-defined": "error",
|
|
58
59
|
"operation-singular-tag": "off",
|
|
59
60
|
"operation-summary": "error",
|
|
60
61
|
"operation-tag-defined": "off",
|
|
@@ -64,6 +65,7 @@ Object {
|
|
|
64
65
|
"path-not-include-query": "error",
|
|
65
66
|
"path-parameters-defined": "error",
|
|
66
67
|
"paths-kebab-case": "off",
|
|
68
|
+
"security-defined": "error",
|
|
67
69
|
"spec": "error",
|
|
68
70
|
"tag-description": "warn",
|
|
69
71
|
"tags-alphabetical": "off",
|
|
@@ -89,6 +91,7 @@ Object {
|
|
|
89
91
|
"no-server-variables-empty-enum": "error",
|
|
90
92
|
"no-undefined-server-variable": "error",
|
|
91
93
|
"no-unused-components": "warn",
|
|
94
|
+
"spec-components-invalid-map-name": "error",
|
|
92
95
|
},
|
|
93
96
|
"oas3_1Decorators": Object {},
|
|
94
97
|
"oas3_1Preprocessors": Object {},
|
|
@@ -101,6 +104,7 @@ Object {
|
|
|
101
104
|
"no-server-variables-empty-enum": "error",
|
|
102
105
|
"no-undefined-server-variable": "error",
|
|
103
106
|
"no-unused-components": "warn",
|
|
107
|
+
"spec-components-invalid-map-name": "error",
|
|
104
108
|
},
|
|
105
109
|
"preprocessors": Object {},
|
|
106
110
|
"recommendedFallback": undefined,
|
|
@@ -142,7 +146,6 @@ Object {
|
|
|
142
146
|
"operation-operationId-unique": "error",
|
|
143
147
|
"operation-operationId-url-safe": "error",
|
|
144
148
|
"operation-parameters-unique": "error",
|
|
145
|
-
"operation-security-defined": "error",
|
|
146
149
|
"operation-singular-tag": "off",
|
|
147
150
|
"operation-summary": "error",
|
|
148
151
|
"operation-tag-defined": "off",
|
|
@@ -151,6 +154,7 @@ Object {
|
|
|
151
154
|
"path-not-include-query": "error",
|
|
152
155
|
"path-parameters-defined": "error",
|
|
153
156
|
"paths-kebab-case": "off",
|
|
157
|
+
"security-defined": "error",
|
|
154
158
|
"spec": "error",
|
|
155
159
|
"tag-description": "warn",
|
|
156
160
|
"tags-alphabetical": "off",
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
- './plugin.js'
|
|
1
|
+
plugins:
|
|
2
|
+
- './plugin.js'
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- test-plugin-nested/all
|
|
1
|
+
plugins:
|
|
2
|
+
- plugin.js
|
|
3
|
+
rules:
|
|
4
|
+
operation-2xx-response: error
|
|
5
|
+
assert/path-item-get-defined:
|
|
6
|
+
subject: PathItem
|
|
7
|
+
property: get
|
|
8
|
+
message: Every path item must have a GET operation.
|
|
9
|
+
defined: true
|
|
10
|
+
extends:
|
|
11
|
+
- test-plugin-nested/all
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
operation-2xx-response: off
|
|
1
|
+
extends:
|
|
2
|
+
- local-config-with-circular.yaml
|
|
3
|
+
rules:
|
|
4
|
+
no-invalid-media-type-examples: error
|
|
5
|
+
operation-description: error
|
|
6
|
+
path-http-verbs-order: error
|
|
7
|
+
operation-2xx-response: off
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- test-plugin/all
|
|
1
|
+
rules:
|
|
2
|
+
no-invalid-media-type-examples: warn
|
|
3
|
+
operation-4xx-response: off
|
|
4
|
+
assert/tag-description:
|
|
5
|
+
subject: Tag
|
|
6
|
+
property: description
|
|
7
|
+
message: Tag description must be at least 13 characters and end with a full stop.
|
|
8
|
+
severity: error
|
|
9
|
+
minLength: 13
|
|
10
|
+
pattern: /\.$/
|
|
11
|
+
plugins:
|
|
12
|
+
- plugin.js
|
|
13
|
+
- api/plugin.js
|
|
14
|
+
extends:
|
|
15
|
+
- recommended
|
|
16
|
+
- api/nested-config.yaml
|
|
17
|
+
- test-plugin-nested/all
|
|
18
|
+
- test-plugin/all
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
operation-2xx-response: off
|
|
1
|
+
plugins:
|
|
2
|
+
- plugin.js
|
|
3
|
+
extends:
|
|
4
|
+
- test-plugin/all
|
|
5
|
+
rules:
|
|
6
|
+
no-invalid-media-type-examples: error
|
|
7
|
+
operation-description: error
|
|
8
|
+
path-http-verbs-order: error
|
|
9
|
+
operation-2xx-response: off
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
operation-4xx-response: error
|
|
1
|
+
rules:
|
|
2
|
+
operation-2xx-response: off
|
|
3
|
+
operation-4xx-response: error
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
operation-2xx-response: error
|
|
1
|
+
extends:
|
|
2
|
+
- nested-remote-config.yaml
|
|
3
|
+
rules:
|
|
4
|
+
operation-2xx-response: error
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadConfig, findConfig, getConfig, createConfig } from '../load';
|
|
2
2
|
import { RedoclyClient } from '../../redocly';
|
|
3
|
-
import { RuleConfig,
|
|
3
|
+
import { RuleConfig, FlatRawConfig } from './../types';
|
|
4
4
|
import { Config } from '../config';
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -93,11 +93,10 @@ describe('getConfig', () => {
|
|
|
93
93
|
describe('createConfig', () => {
|
|
94
94
|
it('should create config from string', async () => {
|
|
95
95
|
const config = await createConfig(`
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
info-license: off
|
|
96
|
+
extends:
|
|
97
|
+
- recommended
|
|
98
|
+
rules:
|
|
99
|
+
info-license: off
|
|
101
100
|
`);
|
|
102
101
|
|
|
103
102
|
verifyExtendedConfig(config, {
|
|
@@ -107,21 +106,19 @@ describe('createConfig', () => {
|
|
|
107
106
|
});
|
|
108
107
|
|
|
109
108
|
it('should create config from object', async () => {
|
|
110
|
-
const rawConfig:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'operation-2xx-response': 'off',
|
|
117
|
-
},
|
|
109
|
+
const rawConfig: FlatRawConfig = {
|
|
110
|
+
extends: ['minimal'],
|
|
111
|
+
rules: {
|
|
112
|
+
'info-license': 'off',
|
|
113
|
+
'tag-description': 'off',
|
|
114
|
+
'operation-2xx-response': 'off',
|
|
118
115
|
},
|
|
119
116
|
};
|
|
120
117
|
const config = await createConfig(rawConfig);
|
|
121
118
|
|
|
122
119
|
verifyExtendedConfig(config, {
|
|
123
120
|
extendsRuleSet: 'minimal',
|
|
124
|
-
overridesRules: rawConfig.
|
|
121
|
+
overridesRules: rawConfig.rules as Record<string, RuleConfig>,
|
|
125
122
|
});
|
|
126
123
|
});
|
|
127
124
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeprecatedInRawConfig, RawConfig } from '../types';
|
|
1
|
+
import { DeprecatedInRawConfig, RawConfig, FlatRawConfig } from '../types';
|
|
2
2
|
import * as utils from '../utils';
|
|
3
3
|
|
|
4
4
|
const makeTestRawConfig = (
|
|
@@ -22,8 +22,54 @@ const makeTestRawConfig = (
|
|
|
22
22
|
},
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
const rawTestConfig: RawConfig = {
|
|
26
|
+
apis: {
|
|
27
|
+
'test@v1': {
|
|
28
|
+
root: 'root.yaml',
|
|
29
|
+
styleguide: {
|
|
30
|
+
extends: ['recommended'],
|
|
31
|
+
rules: { 'operation-2xx-response': 'error' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
styleguide: {
|
|
36
|
+
plugins: ['test-plugin'],
|
|
37
|
+
extends: ['minimal'],
|
|
38
|
+
rules: { 'operation-4xx-response': 'warn' },
|
|
39
|
+
doNotResolveExamples: true,
|
|
40
|
+
},
|
|
41
|
+
resolve: {
|
|
42
|
+
http: { headers: [{ matches: '*', name: 'all', envVariable: 'all' }] },
|
|
43
|
+
},
|
|
44
|
+
'features.openapi': {
|
|
45
|
+
disableSidebar: true,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const flatTestConfig: FlatRawConfig = {
|
|
50
|
+
apis: {
|
|
51
|
+
'test@v1': {
|
|
52
|
+
root: 'root.yaml',
|
|
53
|
+
extends: ['recommended'],
|
|
54
|
+
rules: { 'operation-2xx-response': 'error' },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
plugins: ['test-plugin'],
|
|
58
|
+
extends: ['minimal'],
|
|
59
|
+
rules: {
|
|
60
|
+
'operation-4xx-response': 'warn',
|
|
61
|
+
},
|
|
62
|
+
resolve: {
|
|
63
|
+
http: { headers: [{ matches: '*', name: 'all', envVariable: 'all' }] },
|
|
64
|
+
doNotResolveExamples: true,
|
|
65
|
+
},
|
|
66
|
+
'features.openapi': {
|
|
67
|
+
disableSidebar: true,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
25
71
|
describe('transformConfig', () => {
|
|
26
|
-
it('should work for
|
|
72
|
+
it('should work for the `styleguide` syntax', () => {
|
|
27
73
|
const transformedRawConfig: RawConfig = utils.transformConfig(
|
|
28
74
|
makeTestRawConfig('styleguide', 'styleguide')
|
|
29
75
|
);
|
|
@@ -73,11 +119,25 @@ describe('transformConfig', () => {
|
|
|
73
119
|
}
|
|
74
120
|
`);
|
|
75
121
|
});
|
|
76
|
-
it('should throw an error if both
|
|
122
|
+
it('should throw an error if both `styleguide` and `lint` syntaxes used together', () => {
|
|
77
123
|
const testRawConfig = makeTestRawConfig('styleguide', 'lint');
|
|
78
124
|
testRawConfig.apiDefinitions = { legacyApiDefinition: 'file.yaml' };
|
|
79
125
|
expect(() => utils.transformConfig(testRawConfig)).toThrowError(
|
|
80
|
-
`Do not use 'apiDefinitions' field. Use 'apis' instead
|
|
126
|
+
`Do not use 'apiDefinitions' field. Use 'apis' instead. `
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
it('should transform flatten config into styleguide', () => {
|
|
130
|
+
expect(utils.transformConfig(flatTestConfig)).toEqual({
|
|
131
|
+
...rawTestConfig,
|
|
132
|
+
resolve: { ...rawTestConfig.resolve, doNotResolveExamples: true },
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
it('should transform styleguide config into styleguide identically', () => {
|
|
136
|
+
expect(utils.transformConfig(rawTestConfig)).toEqual(rawTestConfig);
|
|
137
|
+
});
|
|
138
|
+
it('should fail when there is a mixed config', () => {
|
|
139
|
+
expect(() => utils.transformConfig({ ...rawTestConfig, extends: ['recommended'] })).toThrow(
|
|
140
|
+
`Do not use 'lint', 'styleguide' and flat syntax together. \nSee more about the configuration in the docs: https://redocly.com/docs/cli/configuration/ \n`
|
|
81
141
|
);
|
|
82
142
|
});
|
|
83
143
|
});
|
package/src/config/all.ts
CHANGED
|
@@ -26,7 +26,7 @@ export 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 @@ export 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 @@ export 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
|
} as PluginStyleguideConfig;
|
|
@@ -21,7 +21,7 @@ import type {
|
|
|
21
21
|
DeprecatedInRawConfig,
|
|
22
22
|
} from './types';
|
|
23
23
|
import { isBrowser } from '../env';
|
|
24
|
-
import { isNotString, isString,
|
|
24
|
+
import { isNotString, isString, isDefined, parseYaml } from '../utils';
|
|
25
25
|
import { Config } from './config';
|
|
26
26
|
import { colorize, logger } from '../logger';
|
|
27
27
|
|
|
@@ -177,7 +177,7 @@ export function resolvePlugins(
|
|
|
177
177
|
|
|
178
178
|
return plugin;
|
|
179
179
|
})
|
|
180
|
-
.filter(
|
|
180
|
+
.filter(isDefined);
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
export async function resolveApis({
|
package/src/config/load.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Config, DOMAINS } from './config';
|
|
|
7
7
|
import { transformConfig } from './utils';
|
|
8
8
|
import { resolveConfig } from './config-resolvers';
|
|
9
9
|
|
|
10
|
-
import type { DeprecatedInRawConfig, RawConfig, Region } from './types';
|
|
10
|
+
import type { DeprecatedInRawConfig, FlatRawConfig, RawConfig, Region } from './types';
|
|
11
11
|
import { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
12
12
|
|
|
13
13
|
async function addConfigMetadata({
|
|
@@ -102,7 +102,8 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
102
102
|
export async function getConfig(configPath: string | undefined = findConfig()): Promise<RawConfig> {
|
|
103
103
|
if (!configPath || !doesYamlFileExist(configPath)) return {};
|
|
104
104
|
try {
|
|
105
|
-
const rawConfig =
|
|
105
|
+
const rawConfig =
|
|
106
|
+
(await loadYaml<RawConfig & DeprecatedInRawConfig & FlatRawConfig>(configPath)) || {};
|
|
106
107
|
return transformConfig(rawConfig);
|
|
107
108
|
} catch (e) {
|
|
108
109
|
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|