@redocly/openapi-core 1.0.0-beta.75 → 1.0.0-beta.79
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/bundle.d.ts +4 -0
- package/lib/bundle.js +32 -9
- package/lib/config/config.d.ts +2 -9
- package/lib/format/format.d.ts +1 -1
- package/lib/format/format.js +39 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -1
- package/lib/resolve.d.ts +1 -0
- package/lib/resolve.js +7 -3
- package/lib/rules/builtin.d.ts +2 -0
- package/lib/rules/common/remove-x-internal.d.ts +2 -0
- package/lib/rules/common/remove-x-internal.js +58 -0
- package/lib/rules/oas2/index.d.ts +1 -0
- package/lib/rules/oas2/index.js +2 -0
- 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 +1 -0
- package/lib/rules/oas3/index.js +2 -0
- package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
- package/lib/rules/oas3/remove-unused-components.js +83 -0
- package/lib/typings/swagger.d.ts +14 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +9 -1
- package/lib/walk.js +5 -8
- package/package.json +1 -1
- package/src/bundle.ts +38 -9
- package/src/config/config.ts +2 -3
- package/src/format/format.ts +47 -2
- package/src/index.ts +1 -1
- package/src/resolve.ts +6 -6
- package/src/rules/__tests__/config.ts +5 -4
- package/src/rules/__tests__/hide-internals.test.ts +317 -0
- package/src/rules/common/remove-x-internal.ts +59 -0
- package/src/rules/oas2/index.ts +3 -1
- package/src/rules/oas2/remove-unused-components.ts +76 -0
- package/src/rules/oas3/index.ts +2 -0
- package/src/rules/oas3/remove-unused-components.ts +84 -0
- package/src/types/oas2.ts +0 -3
- package/src/typings/swagger.ts +7 -0
- package/src/utils.ts +8 -0
- package/src/walk.ts +6 -13
- package/tsconfig.tsbuildinfo +1 -1
package/lib/bundle.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseResolver, Document } from './resolve';
|
|
2
2
|
import { Oas3Rule } from './visitors';
|
|
3
3
|
import { NormalizedNodeType, NodeType } from './types';
|
|
4
|
+
import { OasMajorVersion } from './oas-types';
|
|
4
5
|
import type { Config, LintConfig } from './config/config';
|
|
5
6
|
export declare type Oas3RuleSet = Record<string, Oas3Rule>;
|
|
6
7
|
export declare enum OasVersion {
|
|
@@ -16,6 +17,7 @@ export declare function bundle(opts: {
|
|
|
16
17
|
dereference?: boolean;
|
|
17
18
|
base?: string;
|
|
18
19
|
skipRedoclyRegistryRefs?: boolean;
|
|
20
|
+
removeUnusedComponents?: boolean;
|
|
19
21
|
}): Promise<{
|
|
20
22
|
bundle: Document;
|
|
21
23
|
problems: import("./walk").NormalizedProblem[];
|
|
@@ -31,6 +33,7 @@ export declare function bundleDocument(opts: {
|
|
|
31
33
|
externalRefResolver: BaseResolver;
|
|
32
34
|
dereference?: boolean;
|
|
33
35
|
skipRedoclyRegistryRefs?: boolean;
|
|
36
|
+
removeUnusedComponents?: boolean;
|
|
34
37
|
}): Promise<{
|
|
35
38
|
bundle: Document;
|
|
36
39
|
problems: import("./walk").NormalizedProblem[];
|
|
@@ -39,3 +42,4 @@ export declare function bundleDocument(opts: {
|
|
|
39
42
|
refTypes: Map<string, NormalizedNodeType> | undefined;
|
|
40
43
|
visitorsData: Record<string, Record<string, unknown>>;
|
|
41
44
|
}>;
|
|
45
|
+
export declare function mapTypeToComponent(typeName: string, version: OasMajorVersion): "headers" | "responses" | "definitions" | "parameters" | "schemas" | "examples" | "requestBodies" | "securitySchemes" | "links" | "callbacks" | null;
|
package/lib/bundle.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.bundleDocument = exports.bundle = exports.OasVersion = void 0;
|
|
12
|
+
exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = exports.OasVersion = void 0;
|
|
13
13
|
const isEqual = require("lodash.isequal");
|
|
14
14
|
const resolve_1 = require("./resolve");
|
|
15
15
|
const visitors_1 = require("./visitors");
|
|
@@ -24,6 +24,8 @@ const rules_1 = require("./config/rules");
|
|
|
24
24
|
const no_unresolved_refs_1 = require("./rules/no-unresolved-refs");
|
|
25
25
|
const utils_1 = require("./utils");
|
|
26
26
|
const redocly_1 = require("./redocly");
|
|
27
|
+
const remove_unused_components_1 = require("./rules/oas2/remove-unused-components");
|
|
28
|
+
const remove_unused_components_2 = require("./rules/oas3/remove-unused-components");
|
|
27
29
|
var OasVersion;
|
|
28
30
|
(function (OasVersion) {
|
|
29
31
|
OasVersion["Version2"] = "oas2";
|
|
@@ -46,7 +48,7 @@ function bundle(opts) {
|
|
|
46
48
|
exports.bundle = bundle;
|
|
47
49
|
function bundleDocument(opts) {
|
|
48
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, } = opts;
|
|
51
|
+
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, removeUnusedComponents = false, } = opts;
|
|
50
52
|
const oasVersion = oas_types_1.detectOpenAPI(document.parsed);
|
|
51
53
|
const oasMajorVersion = oas_types_1.openAPIMajor(oasVersion);
|
|
52
54
|
const rules = config.getRulesForOasVersion(oasMajorVersion);
|
|
@@ -63,20 +65,29 @@ function bundleDocument(opts) {
|
|
|
63
65
|
refTypes: new Map(),
|
|
64
66
|
visitorsData: {},
|
|
65
67
|
};
|
|
68
|
+
if (removeUnusedComponents) {
|
|
69
|
+
decorators.push({
|
|
70
|
+
severity: 'error',
|
|
71
|
+
ruleId: 'remove-unused-components',
|
|
72
|
+
visitor: oasMajorVersion === oas_types_1.OasMajorVersion.Version2
|
|
73
|
+
? remove_unused_components_1.RemoveUnusedComponents({})
|
|
74
|
+
: remove_unused_components_2.RemoveUnusedComponents({})
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const resolvedRefMap = yield resolve_1.resolveDocument({
|
|
78
|
+
rootDocument: document,
|
|
79
|
+
rootType: types.DefinitionRoot,
|
|
80
|
+
externalRefResolver,
|
|
81
|
+
});
|
|
66
82
|
const bundleVisitor = visitors_1.normalizeVisitors([
|
|
67
83
|
...preprocessors,
|
|
68
84
|
{
|
|
69
85
|
severity: 'error',
|
|
70
86
|
ruleId: 'bundler',
|
|
71
|
-
visitor: makeBundleVisitor(oasMajorVersion, dereference, skipRedoclyRegistryRefs, document),
|
|
87
|
+
visitor: makeBundleVisitor(oasMajorVersion, dereference, skipRedoclyRegistryRefs, document, resolvedRefMap),
|
|
72
88
|
},
|
|
73
89
|
...decorators,
|
|
74
90
|
], types);
|
|
75
|
-
const resolvedRefMap = yield resolve_1.resolveDocument({
|
|
76
|
-
rootDocument: document,
|
|
77
|
-
rootType: types.DefinitionRoot,
|
|
78
|
-
externalRefResolver,
|
|
79
|
-
});
|
|
80
91
|
walk_1.walkDocument({
|
|
81
92
|
document,
|
|
82
93
|
rootType: types.DefinitionRoot,
|
|
@@ -133,8 +144,9 @@ function mapTypeToComponent(typeName, version) {
|
|
|
133
144
|
}
|
|
134
145
|
}
|
|
135
146
|
}
|
|
147
|
+
exports.mapTypeToComponent = mapTypeToComponent;
|
|
136
148
|
// function oas3Move
|
|
137
|
-
function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDocument) {
|
|
149
|
+
function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDocument, resolvedRefMap) {
|
|
138
150
|
let components;
|
|
139
151
|
const visitor = {
|
|
140
152
|
ref: {
|
|
@@ -163,6 +175,7 @@ function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDo
|
|
|
163
175
|
}
|
|
164
176
|
else {
|
|
165
177
|
node.$ref = saveComponent(componentType, resolved, ctx);
|
|
178
|
+
resolveBundledComponent(node, resolved, ctx);
|
|
166
179
|
}
|
|
167
180
|
}
|
|
168
181
|
},
|
|
@@ -199,6 +212,16 @@ function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDo
|
|
|
199
212
|
},
|
|
200
213
|
};
|
|
201
214
|
}
|
|
215
|
+
function resolveBundledComponent(node, resolved, ctx) {
|
|
216
|
+
const newRefId = resolve_1.makeRefId(ctx.location.source.absoluteRef, node.$ref);
|
|
217
|
+
resolvedRefMap.set(newRefId, {
|
|
218
|
+
document: rootDocument,
|
|
219
|
+
isRemote: false,
|
|
220
|
+
node: resolved.node,
|
|
221
|
+
nodePointer: node.$ref,
|
|
222
|
+
resolved: true,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
202
225
|
function replaceRef(ref, resolved, ctx) {
|
|
203
226
|
if (!utils_1.isPlainObject(resolved.node)) {
|
|
204
227
|
ctx.parent[ctx.key] = resolved.node;
|
package/lib/config/config.d.ts
CHANGED
|
@@ -5,10 +5,9 @@ export declare const IGNORE_FILE = ".redocly.lint-ignore.yaml";
|
|
|
5
5
|
export declare type RuleConfig = ProblemSeverity | 'off' | ({
|
|
6
6
|
severity?: ProblemSeverity;
|
|
7
7
|
} & Record<string, any>);
|
|
8
|
-
export declare type PreprocessorConfig = ProblemSeverity | 'off' | 'on' | {
|
|
8
|
+
export declare type PreprocessorConfig = ProblemSeverity | 'off' | 'on' | ({
|
|
9
9
|
severity?: ProblemSeverity;
|
|
10
|
-
|
|
11
|
-
};
|
|
10
|
+
} & Record<string, any>);
|
|
12
11
|
export declare type DecoratorConfig = PreprocessorConfig;
|
|
13
12
|
export declare type LintRawConfig = {
|
|
14
13
|
plugins?: (string | Plugin)[];
|
|
@@ -107,15 +106,9 @@ export declare class LintConfig {
|
|
|
107
106
|
};
|
|
108
107
|
getPreprocessorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
109
108
|
severity: ProblemSeverity | "off";
|
|
110
|
-
} | {
|
|
111
|
-
severity: ProblemSeverity;
|
|
112
|
-
options?: Record<string, any> | undefined;
|
|
113
109
|
};
|
|
114
110
|
getDecoratorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
115
111
|
severity: ProblemSeverity | "off";
|
|
116
|
-
} | {
|
|
117
|
-
severity: ProblemSeverity;
|
|
118
|
-
options?: Record<string, any> | undefined;
|
|
119
112
|
};
|
|
120
113
|
getUnusedRules(): {
|
|
121
114
|
rules: string[];
|
package/lib/format/format.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare type Totals = {
|
|
|
4
4
|
warnings: number;
|
|
5
5
|
ignored: number;
|
|
6
6
|
};
|
|
7
|
-
export declare type OutputFormat = 'codeframe' | 'stylish' | 'json';
|
|
7
|
+
export declare type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle';
|
|
8
8
|
export declare function getTotals(problems: (NormalizedProblem & {
|
|
9
9
|
ignored?: boolean;
|
|
10
10
|
})[]): Totals;
|
package/lib/format/format.js
CHANGED
|
@@ -66,7 +66,7 @@ function formatProblems(problems, opts) {
|
|
|
66
66
|
process.stderr.write(`${formatCodeframe(problem, i)}\n`);
|
|
67
67
|
}
|
|
68
68
|
break;
|
|
69
|
-
case 'stylish':
|
|
69
|
+
case 'stylish': {
|
|
70
70
|
const groupedByFile = groupByFiles(problems);
|
|
71
71
|
for (const [file, { ruleIdPad, locationPad: positionPad, fileProblems }] of Object.entries(groupedByFile)) {
|
|
72
72
|
process.stderr.write(`${colorette_1.blue(path.relative(cwd, file))}:\n`);
|
|
@@ -77,6 +77,19 @@ function formatProblems(problems, opts) {
|
|
|
77
77
|
process.stderr.write('\n');
|
|
78
78
|
}
|
|
79
79
|
break;
|
|
80
|
+
}
|
|
81
|
+
case 'checkstyle': {
|
|
82
|
+
const groupedByFile = groupByFiles(problems);
|
|
83
|
+
process.stdout.write('<?xml version="1.0" encoding="UTF-8"?>\n');
|
|
84
|
+
process.stdout.write('<checkstyle version="4.3">\n');
|
|
85
|
+
for (const [file, { fileProblems }] of Object.entries(groupedByFile)) {
|
|
86
|
+
process.stdout.write(`<file name="${xmlEscape(path.relative(cwd, file))}">\n`);
|
|
87
|
+
fileProblems.forEach(formatCheckstyle);
|
|
88
|
+
process.stdout.write(`</file>\n`);
|
|
89
|
+
}
|
|
90
|
+
process.stdout.write(`</checkstyle>\n`);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
80
93
|
}
|
|
81
94
|
if (totalProblems - ignoredProblems > maxProblems) {
|
|
82
95
|
process.stderr.write(`< ... ${totalProblems - maxProblems} more problems hidden > ${colorette_1.gray('increase with `--max-problems N`')}\n`);
|
|
@@ -131,6 +144,13 @@ function formatProblems(problems, opts) {
|
|
|
131
144
|
const { start } = problem.location[0];
|
|
132
145
|
return ` ${`${start.line}:${start.col}`.padEnd(locationPad)} ${severityName} ${problem.ruleId.padEnd(ruleIdPad)} ${problem.message}`;
|
|
133
146
|
}
|
|
147
|
+
function formatCheckstyle(problem) {
|
|
148
|
+
const { line, col } = problem.location[0].start;
|
|
149
|
+
const severity = problem.severity == 'warn' ? 'warning' : 'error';
|
|
150
|
+
const message = xmlEscape(problem.message);
|
|
151
|
+
const source = xmlEscape(problem.ruleId);
|
|
152
|
+
process.stdout.write(`<error line="${line}" column="${col}" severity="${severity}" message="${message}" source="${source}" />\n`);
|
|
153
|
+
}
|
|
134
154
|
}
|
|
135
155
|
exports.formatProblems = formatProblems;
|
|
136
156
|
function formatFrom(cwd, location) {
|
|
@@ -167,3 +187,21 @@ const groupByFiles = (problems) => {
|
|
|
167
187
|
}
|
|
168
188
|
return fileGroups;
|
|
169
189
|
};
|
|
190
|
+
function xmlEscape(s) {
|
|
191
|
+
return s.replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, (char) => {
|
|
192
|
+
switch (char) {
|
|
193
|
+
case '<':
|
|
194
|
+
return '<';
|
|
195
|
+
case '>':
|
|
196
|
+
return '>';
|
|
197
|
+
case '&':
|
|
198
|
+
return '&';
|
|
199
|
+
case '"':
|
|
200
|
+
return '"';
|
|
201
|
+
case "'":
|
|
202
|
+
return ''';
|
|
203
|
+
default:
|
|
204
|
+
return `&#${char.charCodeAt(0)};`;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -20,4 +20,4 @@ export { WalkContext, walkDocument, NormalizedProblem, ProblemSeverity, LineColL
|
|
|
20
20
|
export { getAstNodeByPointer, getLineColLocation } from './format/codeframes';
|
|
21
21
|
export { formatProblems, OutputFormat, getTotals, Totals } from './format/format';
|
|
22
22
|
export { lint, lint as validate, lintDocument, lintFromString, lintConfig } from './lint';
|
|
23
|
-
export { bundle, bundleDocument } from './bundle';
|
|
23
|
+
export { bundle, bundleDocument, mapTypeToComponent } from './bundle';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bundleDocument = exports.bundle = exports.lintConfig = exports.lintFromString = exports.lintDocument = exports.validate = exports.lint = exports.getTotals = exports.formatProblems = exports.getLineColLocation = exports.getAstNodeByPointer = exports.walkDocument = exports.normalizeVisitors = exports.OasVersion = exports.openAPIMajor = exports.OasMajorVersion = exports.detectOpenAPI = exports.unescapePointer = exports.stringifyYaml = exports.parseYaml = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.resolveDocument = exports.BaseResolver = exports.Source = exports.RedoclyClient = exports.loadConfig = exports.IGNORE_FILE = exports.LintConfig = exports.Config = exports.Stats = exports.normalizeTypes = exports.ConfigTypes = exports.Oas2Types = exports.Oas3Types = exports.Oas3_1Types = exports.slash = exports.readFileFromUrl = void 0;
|
|
3
|
+
exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = exports.lintConfig = exports.lintFromString = exports.lintDocument = exports.validate = exports.lint = exports.getTotals = exports.formatProblems = exports.getLineColLocation = exports.getAstNodeByPointer = exports.walkDocument = exports.normalizeVisitors = exports.OasVersion = exports.openAPIMajor = exports.OasMajorVersion = exports.detectOpenAPI = exports.unescapePointer = exports.stringifyYaml = exports.parseYaml = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.resolveDocument = exports.BaseResolver = exports.Source = exports.RedoclyClient = exports.loadConfig = exports.IGNORE_FILE = exports.LintConfig = exports.Config = exports.Stats = exports.normalizeTypes = exports.ConfigTypes = exports.Oas2Types = exports.Oas3Types = exports.Oas3_1Types = exports.slash = exports.readFileFromUrl = void 0;
|
|
4
4
|
var utils_1 = require("./utils");
|
|
5
5
|
Object.defineProperty(exports, "readFileFromUrl", { enumerable: true, get: function () { return utils_1.readFileFromUrl; } });
|
|
6
6
|
Object.defineProperty(exports, "slash", { enumerable: true, get: function () { return utils_1.slash; } });
|
|
@@ -60,3 +60,4 @@ Object.defineProperty(exports, "lintConfig", { enumerable: true, get: function (
|
|
|
60
60
|
var bundle_1 = require("./bundle");
|
|
61
61
|
Object.defineProperty(exports, "bundle", { enumerable: true, get: function () { return bundle_1.bundle; } });
|
|
62
62
|
Object.defineProperty(exports, "bundleDocument", { enumerable: true, get: function () { return bundle_1.bundleDocument; } });
|
|
63
|
+
Object.defineProperty(exports, "mapTypeToComponent", { enumerable: true, get: function () { return bundle_1.mapTypeToComponent; } });
|
package/lib/resolve.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare type Document = {
|
|
|
27
27
|
source: Source;
|
|
28
28
|
parsed: any;
|
|
29
29
|
};
|
|
30
|
+
export declare function makeRefId(absoluteRef: string, pointer: string): string;
|
|
30
31
|
export declare function makeDocumentFromString(sourceString: string, absoluteRef: string): {
|
|
31
32
|
source: Source;
|
|
32
33
|
parsed: unknown;
|
package/lib/resolve.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.resolveDocument = exports.BaseResolver = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.Source = void 0;
|
|
12
|
+
exports.resolveDocument = exports.BaseResolver = exports.makeDocumentFromString = exports.makeRefId = exports.YamlParseError = exports.ResolveError = exports.Source = void 0;
|
|
13
13
|
const fs = require("fs");
|
|
14
14
|
const path = require("path");
|
|
15
15
|
const url = require("url");
|
|
@@ -69,6 +69,10 @@ class YamlParseError extends Error {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
exports.YamlParseError = YamlParseError;
|
|
72
|
+
function makeRefId(absoluteRef, pointer) {
|
|
73
|
+
return absoluteRef + '::' + pointer;
|
|
74
|
+
}
|
|
75
|
+
exports.makeRefId = makeRefId;
|
|
72
76
|
function makeDocumentFromString(sourceString, absoluteRef) {
|
|
73
77
|
const source = new Source(absoluteRef, sourceString);
|
|
74
78
|
try {
|
|
@@ -255,7 +259,7 @@ function resolveDocument(opts) {
|
|
|
255
259
|
document: undefined,
|
|
256
260
|
error: error,
|
|
257
261
|
};
|
|
258
|
-
const refId = document.source.absoluteRef
|
|
262
|
+
const refId = makeRefId(document.source.absoluteRef, ref.$ref);
|
|
259
263
|
resolvedRefMap.set(refId, resolvedRef);
|
|
260
264
|
return resolvedRef;
|
|
261
265
|
}
|
|
@@ -294,7 +298,7 @@ function resolveDocument(opts) {
|
|
|
294
298
|
}
|
|
295
299
|
resolvedRef.node = target;
|
|
296
300
|
resolvedRef.document = targetDoc;
|
|
297
|
-
const refId = document.source.absoluteRef
|
|
301
|
+
const refId = makeRefId(document.source.absoluteRef, ref.$ref);
|
|
298
302
|
if (resolvedRef.document && ref_utils_1.isRef(target)) {
|
|
299
303
|
resolvedRef = yield followRef(resolvedRef.document, target, pushRef(refStack, target));
|
|
300
304
|
}
|
package/lib/rules/builtin.d.ts
CHANGED
|
@@ -10,11 +10,13 @@ export declare const decorators: {
|
|
|
10
10
|
'operation-description-override': import("../visitors").Oas3Decorator;
|
|
11
11
|
'tag-description-override': import("../visitors").Oas3Decorator;
|
|
12
12
|
'info-description-override': import("../visitors").Oas3Decorator;
|
|
13
|
+
'remove-x-internal': import("../visitors").Oas3Decorator;
|
|
13
14
|
};
|
|
14
15
|
oas2: {
|
|
15
16
|
'registry-dependencies': import("../visitors").Oas2Decorator;
|
|
16
17
|
'operation-description-override': import("../visitors").Oas2Decorator;
|
|
17
18
|
'tag-description-override': import("../visitors").Oas2Decorator;
|
|
18
19
|
'info-description-override': import("../visitors").Oas2Decorator;
|
|
20
|
+
'remove-x-internal': import("../visitors").Oas2Decorator;
|
|
19
21
|
};
|
|
20
22
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveXInternal = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const ref_utils_1 = require("../../ref-utils");
|
|
6
|
+
const DEFAULT_INTERNAL_PROPERTY_NAME = 'x-internal';
|
|
7
|
+
const RemoveXInternal = ({ internalFlagProperty }) => {
|
|
8
|
+
const hiddenTag = internalFlagProperty || DEFAULT_INTERNAL_PROPERTY_NAME;
|
|
9
|
+
function removeInternal(node, ctx) {
|
|
10
|
+
var _a, _b, _c, _d;
|
|
11
|
+
const { parent, key } = ctx;
|
|
12
|
+
let didDelete = false;
|
|
13
|
+
if (Array.isArray(node)) {
|
|
14
|
+
for (let i = 0; i < node.length; i++) {
|
|
15
|
+
if (ref_utils_1.isRef(node[i])) {
|
|
16
|
+
const resolved = ctx.resolve(node[i]);
|
|
17
|
+
if ((_a = resolved.node) === null || _a === void 0 ? void 0 : _a[hiddenTag]) {
|
|
18
|
+
node.splice(i, 1);
|
|
19
|
+
didDelete = true;
|
|
20
|
+
i--;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if ((_b = node[i]) === null || _b === void 0 ? void 0 : _b[hiddenTag]) {
|
|
24
|
+
node.splice(i, 1);
|
|
25
|
+
didDelete = true;
|
|
26
|
+
i--;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (utils_1.isPlainObject(node)) {
|
|
31
|
+
for (const key of Object.keys(node)) {
|
|
32
|
+
node = node;
|
|
33
|
+
if (ref_utils_1.isRef(node[key])) {
|
|
34
|
+
const resolved = ctx.resolve(node[key]);
|
|
35
|
+
if ((_c = resolved.node) === null || _c === void 0 ? void 0 : _c[hiddenTag]) {
|
|
36
|
+
delete node[key];
|
|
37
|
+
didDelete = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if ((_d = node[key]) === null || _d === void 0 ? void 0 : _d[hiddenTag]) {
|
|
41
|
+
delete node[key];
|
|
42
|
+
didDelete = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (didDelete && (utils_1.isEmptyObject(node) || utils_1.isEmptyArray(node))) {
|
|
47
|
+
delete parent[key];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
any: {
|
|
52
|
+
enter: (node, ctx) => {
|
|
53
|
+
removeInternal(node, ctx);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
exports.RemoveXInternal = RemoveXInternal;
|
package/lib/rules/oas2/index.js
CHANGED
|
@@ -42,6 +42,7 @@ const path_segment_plural_1 = require("../common/path-segment-plural");
|
|
|
42
42
|
const operation_description_override_1 = require("../common/operation-description-override");
|
|
43
43
|
const tag_description_override_1 = require("../common/tag-description-override");
|
|
44
44
|
const info_description_override_1 = require("../common/info-description-override");
|
|
45
|
+
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
45
46
|
exports.rules = {
|
|
46
47
|
spec: spec_1.OasSpec,
|
|
47
48
|
'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
|
|
@@ -88,4 +89,5 @@ exports.decorators = {
|
|
|
88
89
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
89
90
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
90
91
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
92
|
+
'remove-x-internal': remove_x_internal_1.RemoveXInternal
|
|
91
93
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveUnusedComponents = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const RemoveUnusedComponents = () => {
|
|
6
|
+
let components = new Map();
|
|
7
|
+
function registerComponent(location, componentType, name) {
|
|
8
|
+
var _a;
|
|
9
|
+
components.set(location.absolutePointer, {
|
|
10
|
+
used: ((_a = components.get(location.absolutePointer)) === null || _a === void 0 ? void 0 : _a.used) || false,
|
|
11
|
+
componentType,
|
|
12
|
+
name,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
ref: {
|
|
17
|
+
leave(ref, { type, resolve, key }) {
|
|
18
|
+
if (['Schema', 'Parameter', 'Response', 'SecurityScheme'].includes(type.name)) {
|
|
19
|
+
const resolvedRef = resolve(ref);
|
|
20
|
+
if (!resolvedRef.location)
|
|
21
|
+
return;
|
|
22
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
23
|
+
used: true,
|
|
24
|
+
name: key.toString(),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
DefinitionRoot: {
|
|
30
|
+
leave(root, ctx) {
|
|
31
|
+
const data = ctx.getVisitorData();
|
|
32
|
+
data.removedCount = 0;
|
|
33
|
+
let rootComponents = new Set();
|
|
34
|
+
components.forEach(usageInfo => {
|
|
35
|
+
const { used, name, componentType } = usageInfo;
|
|
36
|
+
if (!used && componentType) {
|
|
37
|
+
rootComponents.add(componentType);
|
|
38
|
+
delete root[componentType][name];
|
|
39
|
+
data.removedCount++;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
for (const component of rootComponents) {
|
|
43
|
+
if (utils_1.isEmptyObject(root[component])) {
|
|
44
|
+
delete root[component];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
NamedSchemas: {
|
|
50
|
+
Schema(schema, { location, key }) {
|
|
51
|
+
if (!schema.allOf) {
|
|
52
|
+
registerComponent(location, 'definitions', key.toString());
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
NamedParameters: {
|
|
57
|
+
Parameter(_parameter, { location, key }) {
|
|
58
|
+
registerComponent(location, 'parameters', key.toString());
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
NamedResponses: {
|
|
62
|
+
Response(_response, { location, key }) {
|
|
63
|
+
registerComponent(location, 'responses', key.toString());
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
NamedSecuritySchemes: {
|
|
67
|
+
SecurityScheme(_securityScheme, { location, key }) {
|
|
68
|
+
registerComponent(location, 'securityDefinitions', key.toString());
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
exports.RemoveUnusedComponents = RemoveUnusedComponents;
|
package/lib/rules/oas3/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const info_description_override_1 = require("../common/info-description-override
|
|
|
50
50
|
const path_excludes_patterns_1 = require("../common/path-excludes-patterns");
|
|
51
51
|
const no_invalid_schema_examples_1 = require("../common/no-invalid-schema-examples");
|
|
52
52
|
const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-examples");
|
|
53
|
+
const remove_x_internal_1 = require("../common/remove-x-internal");
|
|
53
54
|
exports.rules = {
|
|
54
55
|
spec: spec_1.OasSpec,
|
|
55
56
|
'info-description': info_description_1.InfoDescription,
|
|
@@ -104,4 +105,5 @@ exports.decorators = {
|
|
|
104
105
|
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
105
106
|
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
106
107
|
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
108
|
+
'remove-x-internal': remove_x_internal_1.RemoveXInternal
|
|
107
109
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoveUnusedComponents = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const RemoveUnusedComponents = () => {
|
|
6
|
+
let components = new Map();
|
|
7
|
+
function registerComponent(location, componentType, name) {
|
|
8
|
+
var _a;
|
|
9
|
+
components.set(location.absolutePointer, {
|
|
10
|
+
used: ((_a = components.get(location.absolutePointer)) === null || _a === void 0 ? void 0 : _a.used) || false,
|
|
11
|
+
componentType,
|
|
12
|
+
name,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
ref: {
|
|
17
|
+
leave(ref, { type, resolve, key }) {
|
|
18
|
+
if (['Schema', 'Header', 'Parameter', 'Response', 'Example', 'RequestBody'].includes(type.name)) {
|
|
19
|
+
const resolvedRef = resolve(ref);
|
|
20
|
+
if (!resolvedRef.location)
|
|
21
|
+
return;
|
|
22
|
+
components.set(resolvedRef.location.absolutePointer, {
|
|
23
|
+
used: true,
|
|
24
|
+
name: key.toString(),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
DefinitionRoot: {
|
|
30
|
+
leave(root, ctx) {
|
|
31
|
+
const data = ctx.getVisitorData();
|
|
32
|
+
data.removedCount = 0;
|
|
33
|
+
components.forEach(usageInfo => {
|
|
34
|
+
const { used, componentType, name } = usageInfo;
|
|
35
|
+
if (!used && componentType) {
|
|
36
|
+
let componentChild = root.components[componentType];
|
|
37
|
+
delete componentChild[name];
|
|
38
|
+
data.removedCount++;
|
|
39
|
+
if (utils_1.isEmptyObject(componentChild)) {
|
|
40
|
+
delete root.components[componentType];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
if (utils_1.isEmptyObject(root.components)) {
|
|
45
|
+
delete root.components;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
NamedSchemas: {
|
|
50
|
+
Schema(schema, { location, key }) {
|
|
51
|
+
if (!schema.allOf) {
|
|
52
|
+
registerComponent(location, 'schemas', key.toString());
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
NamedParameters: {
|
|
57
|
+
Parameter(_parameter, { location, key }) {
|
|
58
|
+
registerComponent(location, 'parameters', key.toString());
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
NamedResponses: {
|
|
62
|
+
Response(_response, { location, key }) {
|
|
63
|
+
registerComponent(location, 'responses', key.toString());
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
NamedExamples: {
|
|
67
|
+
Example(_example, { location, key }) {
|
|
68
|
+
registerComponent(location, 'examples', key.toString());
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
NamedRequestBodies: {
|
|
72
|
+
RequestBody(_requestBody, { location, key }) {
|
|
73
|
+
registerComponent(location, 'requestBodies', key.toString());
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
NamedHeaders: {
|
|
77
|
+
Header(_header, { location, key }) {
|
|
78
|
+
registerComponent(location, 'headers', key.toString());
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
exports.RemoveUnusedComponents = RemoveUnusedComponents;
|
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 = {};
|