@redocly/openapi-core 1.0.0-beta.77 → 1.0.0-beta.81
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/__tests__/utils.ts +11 -1
- package/lib/bundle.d.ts +3 -1
- package/lib/bundle.js +30 -8
- package/lib/config/builtIn.js +18 -4
- package/lib/config/config.d.ts +2 -9
- package/lib/{rules → decorators}/common/info-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/info-description-override.js +0 -0
- package/lib/{rules → decorators}/common/operation-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/operation-description-override.js +0 -0
- package/lib/{rules → decorators}/common/registry-dependencies.d.ts +0 -0
- package/lib/{rules → decorators}/common/registry-dependencies.js +0 -0
- package/lib/decorators/common/remove-x-internal.d.ts +2 -0
- package/lib/decorators/common/remove-x-internal.js +58 -0
- package/lib/{rules → decorators}/common/tag-description-override.d.ts +0 -0
- package/lib/{rules → decorators}/common/tag-description-override.js +0 -0
- package/lib/decorators/oas2/index.d.ts +8 -0
- package/lib/decorators/oas2/index.js +15 -0
- package/lib/decorators/oas3/index.d.ts +8 -0
- package/lib/decorators/oas3/index.js +15 -0
- package/lib/js-yaml/index.js +1 -1
- package/lib/redocly/registry-api.js +4 -1
- package/lib/resolve.d.ts +1 -0
- package/lib/resolve.js +7 -3
- package/lib/rules/common/operation-security-defined.js +1 -4
- package/lib/rules/common/spec.js +18 -3
- package/lib/rules/oas2/index.d.ts +1 -7
- package/lib/rules/oas2/index.js +1 -11
- package/lib/rules/oas2/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas2/remove-unused-components.js +73 -0
- package/lib/rules/oas3/index.d.ts +0 -7
- package/lib/rules/oas3/index.js +1 -11
- package/lib/rules/oas3/no-invalid-media-type-examples.js +12 -11
- package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas3/remove-unused-components.js +83 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/oas2.js +42 -35
- package/lib/types/oas3.js +68 -139
- package/lib/types/oas3_1.js +52 -49
- package/lib/typings/swagger.d.ts +14 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +10 -2
- package/lib/walk.js +5 -8
- package/package.json +1 -1
- package/src/__tests__/js-yaml.test.ts +29 -5
- package/src/__tests__/lint.test.ts +1 -3
- package/src/bundle.ts +37 -8
- package/src/config/builtIn.ts +20 -7
- package/src/config/config.ts +2 -3
- package/src/decorators/__tests__/remove-x-internal.test.ts +316 -0
- package/src/{rules → decorators}/common/info-description-override.ts +0 -0
- package/src/{rules → decorators}/common/operation-description-override.ts +0 -0
- package/src/{rules → decorators}/common/registry-dependencies.ts +0 -0
- package/src/decorators/common/remove-x-internal.ts +59 -0
- package/src/{rules → decorators}/common/tag-description-override.ts +0 -0
- package/src/decorators/oas2/index.ts +14 -0
- package/src/decorators/oas3/index.ts +14 -0
- package/src/js-yaml/index.ts +1 -2
- package/src/redocly/registry-api.ts +7 -1
- package/src/resolve.ts +6 -6
- package/src/rules/__tests__/no-unresolved-refs.test.ts +1 -4
- package/src/rules/common/__tests__/info-description.test.ts +1 -3
- package/src/rules/common/__tests__/info-license.test.ts +1 -2
- package/src/rules/common/__tests__/license-url.test.ts +1 -2
- package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -2
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -2
- package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -2
- package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +1 -2
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -2
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +1 -2
- package/src/rules/common/__tests__/operation-operationId-unique.test.ts +1 -2
- package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -2
- package/src/rules/common/__tests__/operation-parameters-unique.test.ts +1 -2
- package/src/rules/common/__tests__/operation-security-defined.test.ts +1 -2
- package/src/rules/common/__tests__/operation-singular-tag.test.ts +1 -2
- package/src/rules/common/__tests__/path-http-verbs-order.test.ts +1 -2
- package/src/rules/common/__tests__/path-not-include-query.test.ts +1 -2
- package/src/rules/common/__tests__/path-params-defined.test.ts +1 -2
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +1 -2
- package/src/rules/common/__tests__/tag-description.test.ts +1 -2
- package/src/rules/common/__tests__/tags-alphabetical.test.ts +1 -2
- package/src/rules/common/operation-security-defined.ts +4 -5
- package/src/rules/common/spec.ts +18 -0
- package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +1 -2
- package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -2
- package/src/rules/oas2/index.ts +1 -11
- package/src/rules/oas2/remove-unused-components.ts +76 -0
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +1 -2
- package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -2
- package/src/rules/oas3/index.ts +0 -12
- package/src/rules/oas3/no-invalid-media-type-examples.ts +17 -21
- package/src/rules/oas3/remove-unused-components.ts +84 -0
- package/src/types/index.ts +4 -0
- package/src/types/oas2.ts +42 -43
- package/src/types/oas3.ts +68 -141
- package/src/types/oas3_1.ts +51 -50
- package/src/typings/swagger.ts +7 -0
- package/src/utils.ts +9 -1
- package/src/walk.ts +6 -13
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/builtin.d.ts +0 -20
- package/lib/rules/builtin.js +0 -17
- package/src/rules/__tests__/config.ts +0 -10
- package/src/rules/builtin.ts +0 -18
package/lib/types/oas3_1.js
CHANGED
|
@@ -21,35 +21,19 @@ const DefinitionRoot = {
|
|
|
21
21
|
};
|
|
22
22
|
const License = {
|
|
23
23
|
properties: {
|
|
24
|
-
name: {
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
url: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
},
|
|
30
|
-
identifier: {
|
|
31
|
-
type: 'string',
|
|
32
|
-
},
|
|
24
|
+
name: { type: 'string' },
|
|
25
|
+
url: { type: 'string' },
|
|
26
|
+
identifier: { type: 'string' },
|
|
33
27
|
},
|
|
34
28
|
required: ['name'],
|
|
35
29
|
};
|
|
36
30
|
const Info = {
|
|
37
31
|
properties: {
|
|
38
|
-
title: {
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
description: {
|
|
45
|
-
type: 'string',
|
|
46
|
-
},
|
|
47
|
-
termsOfService: {
|
|
48
|
-
type: 'string',
|
|
49
|
-
},
|
|
50
|
-
summary: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
},
|
|
32
|
+
title: { type: 'string' },
|
|
33
|
+
version: { type: 'string' },
|
|
34
|
+
description: { type: 'string' },
|
|
35
|
+
termsOfService: { type: 'string' },
|
|
36
|
+
summary: { type: 'string' },
|
|
53
37
|
contact: 'Contact',
|
|
54
38
|
license: 'License',
|
|
55
39
|
},
|
|
@@ -84,9 +68,7 @@ const Operation = {
|
|
|
84
68
|
servers: _1.listOf('Server'),
|
|
85
69
|
requestBody: 'RequestBody',
|
|
86
70
|
responses: 'ResponsesMap',
|
|
87
|
-
deprecated: {
|
|
88
|
-
type: 'boolean',
|
|
89
|
-
},
|
|
71
|
+
deprecated: { type: 'boolean' },
|
|
90
72
|
callbacks: _1.mapOf('Callback'),
|
|
91
73
|
'x-codeSamples': _1.listOf('XCodeSample'),
|
|
92
74
|
'x-code-samples': _1.listOf('XCodeSample'), // deprecated
|
|
@@ -137,7 +119,7 @@ const Schema = {
|
|
|
137
119
|
then: 'Schema',
|
|
138
120
|
else: 'Schema',
|
|
139
121
|
dependentSchemas: _1.listOf('Schema'),
|
|
140
|
-
prefixItems:
|
|
122
|
+
prefixItems: _1.listOf('Schema'),
|
|
141
123
|
contains: 'Schema',
|
|
142
124
|
patternProperties: { type: 'object' },
|
|
143
125
|
propertyNames: 'Schema',
|
|
@@ -149,18 +131,16 @@ const Schema = {
|
|
|
149
131
|
if (Array.isArray(value)) {
|
|
150
132
|
return _1.listOf('Schema');
|
|
151
133
|
}
|
|
152
|
-
else {
|
|
153
|
-
return 'Schema';
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
additionalProperties: (value) => {
|
|
157
|
-
if (typeof value === 'boolean') {
|
|
134
|
+
else if (typeof value === 'boolean') {
|
|
158
135
|
return { type: 'boolean' };
|
|
159
136
|
}
|
|
160
137
|
else {
|
|
161
138
|
return 'Schema';
|
|
162
139
|
}
|
|
163
140
|
},
|
|
141
|
+
additionalProperties: (value) => {
|
|
142
|
+
return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
|
|
143
|
+
},
|
|
164
144
|
description: { type: 'string' },
|
|
165
145
|
format: { type: 'string' },
|
|
166
146
|
contentEncoding: { type: 'string' },
|
|
@@ -181,30 +161,53 @@ const SecurityScheme = {
|
|
|
181
161
|
type: { enum: ['apiKey', 'http', 'oauth2', 'openIdConnect', 'mutualTLS'] },
|
|
182
162
|
description: { type: 'string' },
|
|
183
163
|
name: { type: 'string' },
|
|
184
|
-
in: { type: 'string' },
|
|
164
|
+
in: { type: 'string', enum: ['query', 'header', 'cookie'] },
|
|
185
165
|
scheme: { type: 'string' },
|
|
186
166
|
bearerFormat: { type: 'string' },
|
|
187
167
|
flows: 'SecuritySchemeFlows',
|
|
188
168
|
openIdConnectUrl: { type: 'string' },
|
|
189
169
|
},
|
|
190
170
|
required(value) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
171
|
+
switch (value === null || value === void 0 ? void 0 : value.type) {
|
|
172
|
+
case 'apiKey':
|
|
173
|
+
return ['type', 'name', 'in'];
|
|
174
|
+
case 'http':
|
|
175
|
+
return ['type', 'scheme'];
|
|
176
|
+
case 'oauth2':
|
|
177
|
+
return ['type', 'flows'];
|
|
178
|
+
case 'openIdConnect':
|
|
179
|
+
return ['type', 'openIdConnectUrl'];
|
|
180
|
+
default:
|
|
181
|
+
return ['type'];
|
|
196
182
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
183
|
+
},
|
|
184
|
+
allowed(value) {
|
|
185
|
+
switch (value === null || value === void 0 ? void 0 : value.type) {
|
|
186
|
+
case 'apiKey':
|
|
187
|
+
return ['type', 'name', 'in', 'description'];
|
|
188
|
+
case 'http':
|
|
189
|
+
return ['type', 'scheme', 'bearerFormat', 'description'];
|
|
190
|
+
case 'oauth2':
|
|
191
|
+
switch (value === null || value === void 0 ? void 0 : value.flows) {
|
|
192
|
+
case 'implicit':
|
|
193
|
+
return ['type', 'flows', 'authorizationUrl', 'refreshUrl', 'description', 'scopes'];
|
|
194
|
+
case 'password':
|
|
195
|
+
case 'clientCredentials':
|
|
196
|
+
return ['type', 'flows', 'tokenUrl', 'refreshUrl', 'description', 'scopes'];
|
|
197
|
+
case 'authorizationCode':
|
|
198
|
+
return ['type', 'flows', 'authorizationUrl', 'refreshUrl', 'tokenUrl', 'description', 'scopes'];
|
|
199
|
+
default:
|
|
200
|
+
return ['type', 'flows', 'authorizationUrl', 'refreshUrl', 'tokenUrl', 'description', 'scopes'];
|
|
201
|
+
}
|
|
202
|
+
case 'openIdConnect':
|
|
203
|
+
return ['type', 'openIdConnectUrl', 'description'];
|
|
204
|
+
case 'mutualTLS':
|
|
205
|
+
return ['type', 'description'];
|
|
206
|
+
default:
|
|
207
|
+
return ['type', 'description'];
|
|
205
208
|
}
|
|
206
|
-
return ['type'];
|
|
207
209
|
},
|
|
210
|
+
extensionsPrefix: 'x-',
|
|
208
211
|
};
|
|
209
212
|
exports.Oas3_1Types = Object.assign(Object.assign({}, oas3_1.Oas3Types), { Info,
|
|
210
213
|
DefinitionRoot,
|
package/lib/typings/swagger.d.ts
CHANGED
|
@@ -16,6 +16,20 @@ export interface Oas2Definition {
|
|
|
16
16
|
tags?: Oas2Tag[];
|
|
17
17
|
externalDocs?: Oas2ExternalDocs;
|
|
18
18
|
}
|
|
19
|
+
export interface Oas2Components {
|
|
20
|
+
definitions?: {
|
|
21
|
+
[name: string]: Record<string, Oas2Schema>;
|
|
22
|
+
};
|
|
23
|
+
securityDefinitions?: {
|
|
24
|
+
[name: string]: Record<string, Oas2SecurityScheme>;
|
|
25
|
+
};
|
|
26
|
+
responses?: {
|
|
27
|
+
[name: string]: Record<string, Oas2Response>;
|
|
28
|
+
};
|
|
29
|
+
parameters?: {
|
|
30
|
+
[name: string]: Record<string, Oas2Parameter>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
19
33
|
export interface Oas2Info {
|
|
20
34
|
title: string;
|
|
21
35
|
version: string;
|
package/lib/utils.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export declare type BundleOutputFormat = 'json' | 'yml' | 'yaml';
|
|
|
16
16
|
export declare function loadYaml(filename: string): Promise<unknown>;
|
|
17
17
|
export declare function notUndefined<T>(x: T | undefined): x is T;
|
|
18
18
|
export declare function isPlainObject(value: any): value is object;
|
|
19
|
+
export declare function isEmptyObject(value: any): value is object;
|
|
20
|
+
export declare function isEmptyArray(value: any): boolean;
|
|
19
21
|
export declare function readFileFromUrl(url: string, config: HttpResolveConfig): Promise<{
|
|
20
22
|
body: any;
|
|
21
23
|
mimeType: any;
|
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.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
12
|
+
exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
|
|
13
13
|
const fs = require("fs");
|
|
14
14
|
const minimatch = require("minimatch");
|
|
15
15
|
const node_fetch_1 = require("node-fetch");
|
|
@@ -42,6 +42,14 @@ function isPlainObject(value) {
|
|
|
42
42
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
43
43
|
}
|
|
44
44
|
exports.isPlainObject = isPlainObject;
|
|
45
|
+
function isEmptyObject(value) {
|
|
46
|
+
return isPlainObject(value) && Object.keys(value).length === 0;
|
|
47
|
+
}
|
|
48
|
+
exports.isEmptyObject = isEmptyObject;
|
|
49
|
+
function isEmptyArray(value) {
|
|
50
|
+
return Array.isArray(value) && value.length === 0;
|
|
51
|
+
}
|
|
52
|
+
exports.isEmptyArray = isEmptyArray;
|
|
45
53
|
function readFileFromUrl(url, config) {
|
|
46
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47
55
|
const headers = {};
|
|
@@ -130,7 +138,7 @@ function readFileAsStringSync(filePath) {
|
|
|
130
138
|
}
|
|
131
139
|
exports.readFileAsStringSync = readFileAsStringSync;
|
|
132
140
|
function isPathParameter(pathSegment) {
|
|
133
|
-
return pathSegment.startsWith('{') && pathSegment.endsWith('
|
|
141
|
+
return pathSegment.startsWith('{') && pathSegment.endsWith('}');
|
|
134
142
|
}
|
|
135
143
|
exports.isPathParameter = isPathParameter;
|
|
136
144
|
/**
|
package/lib/walk.js
CHANGED
|
@@ -101,10 +101,9 @@ function walkDocument(opts) {
|
|
|
101
101
|
if (!activatedOn.skipped) {
|
|
102
102
|
visitedBySome = true;
|
|
103
103
|
enteredContexts.add(context);
|
|
104
|
-
const ignoreNextVisitorsOnNode = visitWithContext(visit, resolvedNode, context, ruleId, severity);
|
|
105
|
-
if (ignoreNextVisitorsOnNode)
|
|
104
|
+
const { ignoreNextVisitorsOnNode } = visitWithContext(visit, resolvedNode, context, ruleId, severity);
|
|
105
|
+
if (ignoreNextVisitorsOnNode)
|
|
106
106
|
break;
|
|
107
|
-
}
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
}
|
|
@@ -211,17 +210,15 @@ function walkDocument(opts) {
|
|
|
211
210
|
key,
|
|
212
211
|
parentLocations: collectParentsLocations(context),
|
|
213
212
|
oasVersion: ctx.oasVersion,
|
|
214
|
-
ignoreNextVisitorsOnNode: () => {
|
|
215
|
-
ignoreNextVisitorsOnNode = true;
|
|
216
|
-
},
|
|
213
|
+
ignoreNextVisitorsOnNode: () => { ignoreNextVisitorsOnNode = true; },
|
|
217
214
|
getVisitorData: getVisitorDataFn.bind(undefined, ruleId),
|
|
218
215
|
}, collectParents(context), context);
|
|
219
|
-
return ignoreNextVisitorsOnNode;
|
|
216
|
+
return { ignoreNextVisitorsOnNode };
|
|
220
217
|
}
|
|
221
218
|
function resolve(ref, from = currentLocation.source.absoluteRef) {
|
|
222
219
|
if (!ref_utils_1.isRef(ref))
|
|
223
220
|
return { location, node: ref };
|
|
224
|
-
const refId = from
|
|
221
|
+
const refId = resolve_1.makeRefId(from, ref.$ref);
|
|
225
222
|
const resolvedRef = resolvedRefMap.get(refId);
|
|
226
223
|
if (!resolvedRef) {
|
|
227
224
|
return {
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
1
2
|
import { parseYaml, stringifyYaml } from '../js-yaml';
|
|
2
3
|
|
|
3
4
|
const yaml = `
|
|
@@ -7,7 +8,8 @@ const yaml = `
|
|
|
7
8
|
number: 1000
|
|
8
9
|
decimal: 12.34
|
|
9
10
|
boolean: true
|
|
10
|
-
|
|
11
|
+
dateWithoutQuotes: 2020-01-01
|
|
12
|
+
dateWithQuotes: '2020-01-01'
|
|
11
13
|
array:
|
|
12
14
|
- 1
|
|
13
15
|
- 2
|
|
@@ -16,6 +18,16 @@ const yaml = `
|
|
|
16
18
|
key2: 2
|
|
17
19
|
`;
|
|
18
20
|
|
|
21
|
+
const yamlToDump = outdent`
|
|
22
|
+
date: '2022-01-21T11:29:56.694Z'
|
|
23
|
+
dateWithoutQuotes: 2020-01-01
|
|
24
|
+
dateWithQuotes: '2020-01-01'
|
|
25
|
+
dateImplicit: !!str 2020-01-01
|
|
26
|
+
string: test
|
|
27
|
+
stringWithQuotes: 'test'
|
|
28
|
+
stringWithDoubleQuotes: "test"
|
|
29
|
+
`;
|
|
30
|
+
|
|
19
31
|
const jsObject = {
|
|
20
32
|
emptyValue: null,
|
|
21
33
|
'spaces in keys': 'spaces in keys',
|
|
@@ -23,7 +35,8 @@ const jsObject = {
|
|
|
23
35
|
number: 1000,
|
|
24
36
|
decimal: 12.34,
|
|
25
37
|
boolean: true,
|
|
26
|
-
|
|
38
|
+
dateWithoutQuotes: '2020-01-01',
|
|
39
|
+
dateWithQuotes: '2020-01-01',
|
|
27
40
|
array: [1, 2],
|
|
28
41
|
object: { key1: 1, key2: 2 },
|
|
29
42
|
};
|
|
@@ -33,14 +46,25 @@ describe('js-yaml', () => {
|
|
|
33
46
|
expect(parseYaml(yaml)).toEqual(jsObject);
|
|
34
47
|
});
|
|
35
48
|
|
|
49
|
+
test('should correctly dump date and string', () => {
|
|
50
|
+
expect(stringifyYaml(parseYaml(yamlToDump))).toMatchInlineSnapshot(
|
|
51
|
+
`
|
|
52
|
+
"date: '2022-01-21T11:29:56.694Z'
|
|
53
|
+
dateWithoutQuotes: '2020-01-01'
|
|
54
|
+
dateWithQuotes: '2020-01-01'
|
|
55
|
+
dateImplicit: '2020-01-01'
|
|
56
|
+
string: test
|
|
57
|
+
stringWithQuotes: test
|
|
58
|
+
stringWithDoubleQuotes: test
|
|
59
|
+
"
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
|
|
36
63
|
test('parse and stringify', () => {
|
|
37
64
|
expect(parseYaml(stringifyYaml(jsObject))).toEqual(jsObject);
|
|
38
65
|
});
|
|
39
66
|
|
|
40
67
|
test('should throw an error for unsupported types', () => {
|
|
41
|
-
expect(() => stringifyYaml({ date: new Date() }))
|
|
42
|
-
.toThrow('unacceptable kind of an object to dump [object Date]');
|
|
43
|
-
|
|
44
68
|
expect(() => stringifyYaml({ foo: () => {} }))
|
|
45
69
|
.toThrow('unacceptable kind of an object to dump [object Function]');
|
|
46
70
|
});
|
|
@@ -3,9 +3,7 @@ import { outdent } from 'outdent';
|
|
|
3
3
|
import { lintFromString, lintConfig, lintDocument } from '../lint';
|
|
4
4
|
import { BaseResolver } from '../resolve';
|
|
5
5
|
import { loadConfig } from '../config/load';
|
|
6
|
-
import { parseYamlToDocument, replaceSourceWithRef } from '../../__tests__/utils';
|
|
7
|
-
// todo create general utils for tests and move this config.
|
|
8
|
-
import { makeConfig } from '../rules/__tests__/config';
|
|
6
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../__tests__/utils';
|
|
9
7
|
|
|
10
8
|
describe('lint', () => {
|
|
11
9
|
it('lintFromString should work', async () => {
|
package/src/bundle.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isEqual = require('lodash.isequal');
|
|
2
|
-
import { BaseResolver, resolveDocument, Document } from './resolve';
|
|
2
|
+
import { BaseResolver, resolveDocument, Document, ResolvedRefMap, makeRefId } from './resolve';
|
|
3
3
|
import { Oas3Rule, normalizeVisitors, Oas3Visitor, Oas2Visitor } from './visitors';
|
|
4
4
|
import { Oas3Types } from './types/oas3';
|
|
5
5
|
import { Oas2Types } from './types/oas2';
|
|
@@ -14,6 +14,8 @@ import { reportUnresolvedRef } from './rules/no-unresolved-refs';
|
|
|
14
14
|
import { isPlainObject } from './utils';
|
|
15
15
|
import { OasRef } from './typings/openapi';
|
|
16
16
|
import { isRedoclyRegistryURL } from './redocly';
|
|
17
|
+
import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './rules/oas2/remove-unused-components';
|
|
18
|
+
import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './rules/oas3/remove-unused-components';
|
|
17
19
|
|
|
18
20
|
export type Oas3RuleSet = Record<string, Oas3Rule>;
|
|
19
21
|
|
|
@@ -31,6 +33,7 @@ export async function bundle(opts: {
|
|
|
31
33
|
dereference?: boolean;
|
|
32
34
|
base?: string;
|
|
33
35
|
skipRedoclyRegistryRefs?: boolean;
|
|
36
|
+
removeUnusedComponents?: boolean;
|
|
34
37
|
}) {
|
|
35
38
|
const {
|
|
36
39
|
ref,
|
|
@@ -66,6 +69,7 @@ export async function bundleDocument(opts: {
|
|
|
66
69
|
externalRefResolver: BaseResolver;
|
|
67
70
|
dereference?: boolean;
|
|
68
71
|
skipRedoclyRegistryRefs?: boolean;
|
|
72
|
+
removeUnusedComponents?: boolean;
|
|
69
73
|
}) {
|
|
70
74
|
const {
|
|
71
75
|
document,
|
|
@@ -74,6 +78,7 @@ export async function bundleDocument(opts: {
|
|
|
74
78
|
externalRefResolver,
|
|
75
79
|
dereference = false,
|
|
76
80
|
skipRedoclyRegistryRefs = false,
|
|
81
|
+
removeUnusedComponents = false,
|
|
77
82
|
} = opts;
|
|
78
83
|
const oasVersion = detectOpenAPI(document.parsed);
|
|
79
84
|
const oasMajorVersion = openAPIMajor(oasVersion);
|
|
@@ -92,6 +97,7 @@ export async function bundleDocument(opts: {
|
|
|
92
97
|
|
|
93
98
|
const preprocessors = initRules(rules as any, config, 'preprocessors', oasVersion);
|
|
94
99
|
const decorators = initRules(rules as any, config, 'decorators', oasVersion);
|
|
100
|
+
|
|
95
101
|
const ctx: BundleContext = {
|
|
96
102
|
problems: [],
|
|
97
103
|
oasVersion: oasVersion,
|
|
@@ -99,25 +105,35 @@ export async function bundleDocument(opts: {
|
|
|
99
105
|
visitorsData: {},
|
|
100
106
|
};
|
|
101
107
|
|
|
108
|
+
if (removeUnusedComponents) {
|
|
109
|
+
decorators.push({
|
|
110
|
+
severity: 'error',
|
|
111
|
+
ruleId: 'remove-unused-components',
|
|
112
|
+
visitor: oasMajorVersion === OasMajorVersion.Version2
|
|
113
|
+
? RemoveUnusedComponentsOas2({})
|
|
114
|
+
: RemoveUnusedComponentsOas3({})
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const resolvedRefMap = await resolveDocument({
|
|
119
|
+
rootDocument: document,
|
|
120
|
+
rootType: types.DefinitionRoot,
|
|
121
|
+
externalRefResolver,
|
|
122
|
+
});
|
|
123
|
+
|
|
102
124
|
const bundleVisitor = normalizeVisitors(
|
|
103
125
|
[
|
|
104
126
|
...preprocessors,
|
|
105
127
|
{
|
|
106
128
|
severity: 'error',
|
|
107
129
|
ruleId: 'bundler',
|
|
108
|
-
visitor: makeBundleVisitor(oasMajorVersion, dereference, skipRedoclyRegistryRefs, document),
|
|
130
|
+
visitor: makeBundleVisitor(oasMajorVersion, dereference, skipRedoclyRegistryRefs, document, resolvedRefMap),
|
|
109
131
|
},
|
|
110
132
|
...decorators,
|
|
111
133
|
],
|
|
112
134
|
types,
|
|
113
135
|
);
|
|
114
136
|
|
|
115
|
-
const resolvedRefMap = await resolveDocument({
|
|
116
|
-
rootDocument: document,
|
|
117
|
-
rootType: types.DefinitionRoot,
|
|
118
|
-
externalRefResolver,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
137
|
walkDocument({
|
|
122
138
|
document,
|
|
123
139
|
rootType: types.DefinitionRoot as NormalizedNodeType,
|
|
@@ -182,6 +198,7 @@ function makeBundleVisitor(
|
|
|
182
198
|
dereference: boolean,
|
|
183
199
|
skipRedoclyRegistryRefs: boolean,
|
|
184
200
|
rootDocument: Document,
|
|
201
|
+
resolvedRefMap: ResolvedRefMap
|
|
185
202
|
) {
|
|
186
203
|
let components: Record<string, Record<string, any>>;
|
|
187
204
|
|
|
@@ -214,6 +231,7 @@ function makeBundleVisitor(
|
|
|
214
231
|
replaceRef(node, resolved, ctx);
|
|
215
232
|
} else {
|
|
216
233
|
node.$ref = saveComponent(componentType, resolved, ctx);
|
|
234
|
+
resolveBundledComponent(node, resolved, ctx);
|
|
217
235
|
}
|
|
218
236
|
}
|
|
219
237
|
},
|
|
@@ -251,6 +269,17 @@ function makeBundleVisitor(
|
|
|
251
269
|
};
|
|
252
270
|
}
|
|
253
271
|
|
|
272
|
+
function resolveBundledComponent(node: OasRef, resolved: ResolveResult<any>, ctx: UserContext) {
|
|
273
|
+
const newRefId = makeRefId(ctx.location.source.absoluteRef, node.$ref)
|
|
274
|
+
resolvedRefMap.set(newRefId, {
|
|
275
|
+
document: rootDocument,
|
|
276
|
+
isRemote: false,
|
|
277
|
+
node: resolved.node,
|
|
278
|
+
nodePointer: node.$ref,
|
|
279
|
+
resolved: true,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
254
283
|
function replaceRef(ref: OasRef, resolved: ResolveResult<any>, ctx: UserContext) {
|
|
255
284
|
if (!isPlainObject(resolved.node)) {
|
|
256
285
|
ctx.parent[ctx.key] = resolved.node;
|
package/src/config/builtIn.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import recommended from './recommended';
|
|
2
2
|
import all from './all';
|
|
3
3
|
import minimal from './minimal';
|
|
4
|
-
import { LintRawConfig, Plugin } from './config';
|
|
5
|
-
|
|
6
|
-
import
|
|
4
|
+
import { CustomRulesConfig, LintRawConfig, Plugin } from './config';
|
|
5
|
+
import { rules as oas3Rules } from '../rules/oas3';
|
|
6
|
+
import { rules as oas2Rules } from '../rules/oas2';
|
|
7
|
+
import { preprocessors as oas3Preprocessors } from '../rules/oas3';
|
|
8
|
+
import { preprocessors as oas2Preprocessors } from '../rules/oas2';
|
|
9
|
+
import { decorators as oas3Decorators } from '../decorators/oas3';
|
|
10
|
+
import { decorators as oas2Decorators } from '../decorators/oas2';
|
|
7
11
|
|
|
8
12
|
export const builtInConfigs: Record<string, LintRawConfig> = {
|
|
9
13
|
recommended,
|
|
@@ -16,8 +20,17 @@ export const builtInConfigs: Record<string, LintRawConfig> = {
|
|
|
16
20
|
|
|
17
21
|
export const defaultPlugin: Plugin = {
|
|
18
22
|
id: '', // default plugin doesn't have id
|
|
19
|
-
rules:
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
rules: {
|
|
24
|
+
oas3: oas3Rules,
|
|
25
|
+
oas2: oas2Rules,
|
|
26
|
+
} as CustomRulesConfig,
|
|
27
|
+
preprocessors: {
|
|
28
|
+
oas3: oas3Preprocessors,
|
|
29
|
+
oas2: oas2Preprocessors,
|
|
30
|
+
},
|
|
31
|
+
decorators: {
|
|
32
|
+
oas3: oas3Decorators,
|
|
33
|
+
oas2: oas2Decorators,
|
|
34
|
+
},
|
|
22
35
|
configs: builtInConfigs,
|
|
23
|
-
}
|
|
36
|
+
}
|
package/src/config/config.ts
CHANGED