@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/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
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,
|
|
@@ -136,7 +152,7 @@ export async function bundleDocument(opts: {
|
|
|
136
152
|
};
|
|
137
153
|
}
|
|
138
154
|
|
|
139
|
-
function mapTypeToComponent(typeName: string, version: OasMajorVersion) {
|
|
155
|
+
export function mapTypeToComponent(typeName: string, version: OasMajorVersion) {
|
|
140
156
|
switch (version) {
|
|
141
157
|
case OasMajorVersion.Version3:
|
|
142
158
|
switch (typeName) {
|
|
@@ -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/config.ts
CHANGED
package/src/format/format.ts
CHANGED
|
@@ -46,7 +46,7 @@ function severityToNumber(severity: ProblemSeverity) {
|
|
|
46
46
|
return severity === 'error' ? 1 : 2;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export type OutputFormat = 'codeframe' | 'stylish' | 'json';
|
|
49
|
+
export type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle';
|
|
50
50
|
|
|
51
51
|
export function getTotals(problems: (NormalizedProblem & { ignored?: boolean })[]): Totals {
|
|
52
52
|
let errors = 0;
|
|
@@ -111,7 +111,7 @@ export function formatProblems(
|
|
|
111
111
|
process.stderr.write(`${formatCodeframe(problem, i)}\n`);
|
|
112
112
|
}
|
|
113
113
|
break;
|
|
114
|
-
case 'stylish':
|
|
114
|
+
case 'stylish': {
|
|
115
115
|
const groupedByFile = groupByFiles(problems);
|
|
116
116
|
for (const [file, { ruleIdPad, locationPad: positionPad, fileProblems }] of Object.entries(
|
|
117
117
|
groupedByFile,
|
|
@@ -126,6 +126,22 @@ export function formatProblems(
|
|
|
126
126
|
process.stderr.write('\n');
|
|
127
127
|
}
|
|
128
128
|
break;
|
|
129
|
+
}
|
|
130
|
+
case 'checkstyle': {
|
|
131
|
+
const groupedByFile = groupByFiles(problems);
|
|
132
|
+
|
|
133
|
+
process.stdout.write('<?xml version="1.0" encoding="UTF-8"?>\n');
|
|
134
|
+
process.stdout.write('<checkstyle version="4.3">\n');
|
|
135
|
+
|
|
136
|
+
for (const [file, { fileProblems }] of Object.entries(groupedByFile)) {
|
|
137
|
+
process.stdout.write(`<file name="${xmlEscape(path.relative(cwd, file))}">\n`);
|
|
138
|
+
fileProblems.forEach(formatCheckstyle);
|
|
139
|
+
process.stdout.write(`</file>\n`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
process.stdout.write(`</checkstyle>\n`);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
129
145
|
}
|
|
130
146
|
|
|
131
147
|
if (totalProblems - ignoredProblems > maxProblems) {
|
|
@@ -204,6 +220,16 @@ export function formatProblems(
|
|
|
204
220
|
locationPad,
|
|
205
221
|
)} ${severityName} ${problem.ruleId.padEnd(ruleIdPad)} ${problem.message}`;
|
|
206
222
|
}
|
|
223
|
+
|
|
224
|
+
function formatCheckstyle(problem: OnlyLineColProblem) {
|
|
225
|
+
const { line, col } = problem.location[0].start;
|
|
226
|
+
const severity = problem.severity == 'warn' ? 'warning' : 'error';
|
|
227
|
+
const message = xmlEscape(problem.message);
|
|
228
|
+
const source = xmlEscape(problem.ruleId);
|
|
229
|
+
process.stdout.write(
|
|
230
|
+
`<error line="${line}" column="${col}" severity="${severity}" message="${message}" source="${source}" />\n`,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
207
233
|
}
|
|
208
234
|
|
|
209
235
|
function formatFrom(cwd: string, location?: LocationObject) {
|
|
@@ -261,3 +287,22 @@ const groupByFiles = (problems: NormalizedProblem[]) => {
|
|
|
261
287
|
|
|
262
288
|
return fileGroups;
|
|
263
289
|
};
|
|
290
|
+
|
|
291
|
+
function xmlEscape(s: string): string {
|
|
292
|
+
return s.replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, (char) => {
|
|
293
|
+
switch (char) {
|
|
294
|
+
case '<':
|
|
295
|
+
return '<';
|
|
296
|
+
case '>':
|
|
297
|
+
return '>';
|
|
298
|
+
case '&':
|
|
299
|
+
return '&';
|
|
300
|
+
case '"':
|
|
301
|
+
return '"';
|
|
302
|
+
case "'":
|
|
303
|
+
return ''';
|
|
304
|
+
default:
|
|
305
|
+
return `&#${char.charCodeAt(0)};`;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -47,4 +47,4 @@ export {
|
|
|
47
47
|
export { getAstNodeByPointer, getLineColLocation } from './format/codeframes';
|
|
48
48
|
export { formatProblems, OutputFormat, getTotals, Totals } from './format/format';
|
|
49
49
|
export { lint, lint as validate, lintDocument, lintFromString, lintConfig } from './lint';
|
|
50
|
-
export { bundle, bundleDocument } from './bundle';
|
|
50
|
+
export { bundle, bundleDocument, mapTypeToComponent } from './bundle';
|
package/src/resolve.ts
CHANGED
|
@@ -74,6 +74,10 @@ export type Document = {
|
|
|
74
74
|
parsed: any;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
+
export function makeRefId(absoluteRef: string, pointer: string) {
|
|
78
|
+
return absoluteRef + '::' + pointer;
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
export function makeDocumentFromString(sourceString: string, absoluteRef: string) {
|
|
78
82
|
const source = new Source(absoluteRef, sourceString);
|
|
79
83
|
try {
|
|
@@ -323,10 +327,8 @@ export async function resolveDocument(opts: {
|
|
|
323
327
|
document: undefined,
|
|
324
328
|
error: error,
|
|
325
329
|
};
|
|
326
|
-
|
|
327
|
-
const refId = document.source.absoluteRef + '::' + ref.$ref;
|
|
330
|
+
const refId = makeRefId(document.source.absoluteRef, ref.$ref);
|
|
328
331
|
resolvedRefMap.set(refId, resolvedRef);
|
|
329
|
-
|
|
330
332
|
return resolvedRef;
|
|
331
333
|
}
|
|
332
334
|
|
|
@@ -367,13 +369,11 @@ export async function resolveDocument(opts: {
|
|
|
367
369
|
|
|
368
370
|
resolvedRef.node = target;
|
|
369
371
|
resolvedRef.document = targetDoc;
|
|
370
|
-
const refId = document.source.absoluteRef
|
|
371
|
-
|
|
372
|
+
const refId = makeRefId(document.source.absoluteRef, ref.$ref);
|
|
372
373
|
if (resolvedRef.document && isRef(target)) {
|
|
373
374
|
resolvedRef = await followRef(resolvedRef.document, target, pushRef(refStack, target));
|
|
374
375
|
}
|
|
375
376
|
resolvedRefMap.set(refId, resolvedRef);
|
|
376
|
-
|
|
377
377
|
return { ...resolvedRef };
|
|
378
378
|
}
|
|
379
379
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { LintConfig, RuleConfig } from
|
|
1
|
+
import { DecoratorConfig, LintConfig, RuleConfig } from '../../config/config';
|
|
2
2
|
import { defaultPlugin } from '../../config/builtIn';
|
|
3
3
|
|
|
4
|
-
export function makeConfig(rules: Record<string, RuleConfig>) {
|
|
4
|
+
export function makeConfig(rules: Record<string, RuleConfig>, decorators?: Record<string, DecoratorConfig>) {
|
|
5
5
|
return new LintConfig({
|
|
6
6
|
plugins: [defaultPlugin],
|
|
7
7
|
extends: [],
|
|
8
|
-
rules
|
|
8
|
+
rules,
|
|
9
|
+
decorators,
|
|
9
10
|
});
|
|
10
|
-
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
import { bundleDocument } from '../../bundle';
|
|
3
|
+
import { BaseResolver } from '../../resolve';
|
|
4
|
+
import { parseYamlToDocument, yamlSerializer } from '../../../__tests__/utils';
|
|
5
|
+
import { makeConfig } from './config';
|
|
6
|
+
|
|
7
|
+
describe('oas3 remove-x-internal', () => {
|
|
8
|
+
expect.addSnapshotSerializer(yamlSerializer);
|
|
9
|
+
const testDocument = parseYamlToDocument(
|
|
10
|
+
outdent`
|
|
11
|
+
openapi: 3.0.0
|
|
12
|
+
paths:
|
|
13
|
+
/pet:
|
|
14
|
+
removeit: true
|
|
15
|
+
get:
|
|
16
|
+
parameters:
|
|
17
|
+
- $ref: '#/components/parameters/x'
|
|
18
|
+
components:
|
|
19
|
+
parameters:
|
|
20
|
+
x:
|
|
21
|
+
name: x
|
|
22
|
+
`,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
it('should use `internalFlagProperty` option to remove internal paths', async () => {
|
|
26
|
+
const { bundle: res } = await bundleDocument({
|
|
27
|
+
document: testDocument,
|
|
28
|
+
externalRefResolver: new BaseResolver(),
|
|
29
|
+
config: makeConfig({}, { 'remove-x-internal': { internalFlagProperty: 'removeit' } }),
|
|
30
|
+
});
|
|
31
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
32
|
+
openapi: 3.0.0
|
|
33
|
+
components:
|
|
34
|
+
parameters:
|
|
35
|
+
x:
|
|
36
|
+
name: x
|
|
37
|
+
|
|
38
|
+
`);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should clean types: Server, Operation, Parameter, PathItem, Example', async () => {
|
|
42
|
+
const testDoc = parseYamlToDocument(
|
|
43
|
+
outdent`
|
|
44
|
+
openapi: 3.1.0
|
|
45
|
+
servers:
|
|
46
|
+
- url: //petstore.swagger.io/v2
|
|
47
|
+
description: Default server
|
|
48
|
+
x-internal: true
|
|
49
|
+
paths:
|
|
50
|
+
/pet:
|
|
51
|
+
get:
|
|
52
|
+
x-internal: true
|
|
53
|
+
operationId: getPet
|
|
54
|
+
parameters:
|
|
55
|
+
- $ref: '#/components/parameters/x'
|
|
56
|
+
put:
|
|
57
|
+
parameters:
|
|
58
|
+
- name: Accept-Language
|
|
59
|
+
x-internal: true
|
|
60
|
+
in: header
|
|
61
|
+
example: en-US
|
|
62
|
+
required: false
|
|
63
|
+
- name: cookieParam
|
|
64
|
+
x-internal: true
|
|
65
|
+
in: cookie
|
|
66
|
+
description: Some cookie
|
|
67
|
+
required: true
|
|
68
|
+
/admin:
|
|
69
|
+
x-internal: true
|
|
70
|
+
post:
|
|
71
|
+
parameters:
|
|
72
|
+
- $ref: '#/components/parameters/y'
|
|
73
|
+
/store/order:
|
|
74
|
+
post:
|
|
75
|
+
operationId: placeOrder
|
|
76
|
+
responses:
|
|
77
|
+
'200':
|
|
78
|
+
description: successful operation
|
|
79
|
+
content:
|
|
80
|
+
application/json:
|
|
81
|
+
examples:
|
|
82
|
+
response:
|
|
83
|
+
x-internal: true
|
|
84
|
+
value: OK
|
|
85
|
+
components:
|
|
86
|
+
parameters:
|
|
87
|
+
x:
|
|
88
|
+
name: x
|
|
89
|
+
y:
|
|
90
|
+
name: y
|
|
91
|
+
`,
|
|
92
|
+
);
|
|
93
|
+
const { bundle: res } = await bundleDocument({
|
|
94
|
+
document: testDoc,
|
|
95
|
+
externalRefResolver: new BaseResolver(),
|
|
96
|
+
config: makeConfig({}, { 'remove-x-internal': 'on' }),
|
|
97
|
+
});
|
|
98
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
99
|
+
openapi: 3.1.0
|
|
100
|
+
paths:
|
|
101
|
+
/pet:
|
|
102
|
+
put: {}
|
|
103
|
+
/store/order:
|
|
104
|
+
post:
|
|
105
|
+
operationId: placeOrder
|
|
106
|
+
responses:
|
|
107
|
+
'200':
|
|
108
|
+
description: successful operation
|
|
109
|
+
content:
|
|
110
|
+
application/json: {}
|
|
111
|
+
components:
|
|
112
|
+
parameters:
|
|
113
|
+
x:
|
|
114
|
+
name: x
|
|
115
|
+
'y':
|
|
116
|
+
name: 'y'
|
|
117
|
+
|
|
118
|
+
`);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should clean types: Schema, Response, RequestBody, MediaType, Callback', async () => {
|
|
122
|
+
const testDoc = parseYamlToDocument(
|
|
123
|
+
outdent`
|
|
124
|
+
openapi: 3.1.0
|
|
125
|
+
paths:
|
|
126
|
+
/pet:
|
|
127
|
+
post:
|
|
128
|
+
summary: test
|
|
129
|
+
requestBody:
|
|
130
|
+
x-internal: true
|
|
131
|
+
content:
|
|
132
|
+
application/x-www-form-urlencoded:
|
|
133
|
+
schema:
|
|
134
|
+
type: object
|
|
135
|
+
/store/order:
|
|
136
|
+
post:
|
|
137
|
+
operationId: storeOrder
|
|
138
|
+
parameters:
|
|
139
|
+
- name: api_key
|
|
140
|
+
schema:
|
|
141
|
+
x-internal: true
|
|
142
|
+
type: string
|
|
143
|
+
responses:
|
|
144
|
+
'200':
|
|
145
|
+
x-internal: true
|
|
146
|
+
content:
|
|
147
|
+
application/json:
|
|
148
|
+
examples:
|
|
149
|
+
response:
|
|
150
|
+
value: OK
|
|
151
|
+
requestBody:
|
|
152
|
+
content:
|
|
153
|
+
application/x-www-form-urlencoded:
|
|
154
|
+
x-internal: true
|
|
155
|
+
schema:
|
|
156
|
+
type: object
|
|
157
|
+
callbacks:
|
|
158
|
+
orderInProgress:
|
|
159
|
+
x-internal: true
|
|
160
|
+
'{$request.body#/callbackUrl}?event={$request.body#/eventName}':
|
|
161
|
+
servers:
|
|
162
|
+
- url: //callback-url.path-level/v1
|
|
163
|
+
description: Path level server
|
|
164
|
+
`,
|
|
165
|
+
);
|
|
166
|
+
const { bundle: res } = await bundleDocument({
|
|
167
|
+
document: testDoc,
|
|
168
|
+
externalRefResolver: new BaseResolver(),
|
|
169
|
+
config: makeConfig({}, { 'remove-x-internal': 'on' }),
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
173
|
+
openapi: 3.1.0
|
|
174
|
+
paths:
|
|
175
|
+
/pet:
|
|
176
|
+
post:
|
|
177
|
+
summary: test
|
|
178
|
+
/store/order:
|
|
179
|
+
post:
|
|
180
|
+
operationId: storeOrder
|
|
181
|
+
parameters:
|
|
182
|
+
- name: api_key
|
|
183
|
+
requestBody: {}
|
|
184
|
+
components: {}
|
|
185
|
+
|
|
186
|
+
`);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should remove refs', async () => {
|
|
190
|
+
const testDoc = parseYamlToDocument(
|
|
191
|
+
outdent`
|
|
192
|
+
openapi: 3.0.1
|
|
193
|
+
info:
|
|
194
|
+
version: 1.0.0
|
|
195
|
+
title: Test API
|
|
196
|
+
paths:
|
|
197
|
+
/test1:
|
|
198
|
+
get:
|
|
199
|
+
parameters:
|
|
200
|
+
- $ref: '#/components/parameters/Internal'
|
|
201
|
+
- in: query
|
|
202
|
+
name: inline
|
|
203
|
+
schema:
|
|
204
|
+
type: string
|
|
205
|
+
- in: query
|
|
206
|
+
name: inline-internal
|
|
207
|
+
schema:
|
|
208
|
+
type: string
|
|
209
|
+
x-internal: true
|
|
210
|
+
/test2:
|
|
211
|
+
get:
|
|
212
|
+
parameters:
|
|
213
|
+
- $ref: '#/components/parameters/Public'
|
|
214
|
+
- $ref: '#/components/parameters/Internal'
|
|
215
|
+
requestBody:
|
|
216
|
+
$ref: '#/components/requestBodies/Public'
|
|
217
|
+
components:
|
|
218
|
+
requestBodies:
|
|
219
|
+
Public:
|
|
220
|
+
content:
|
|
221
|
+
application/json:
|
|
222
|
+
schema:
|
|
223
|
+
type: string
|
|
224
|
+
required: true
|
|
225
|
+
x-internal: true
|
|
226
|
+
parameters:
|
|
227
|
+
Public:
|
|
228
|
+
in: path
|
|
229
|
+
name: product_id
|
|
230
|
+
schema:
|
|
231
|
+
type: string
|
|
232
|
+
Internal:
|
|
233
|
+
in: header
|
|
234
|
+
name: X-Vendor
|
|
235
|
+
schema:
|
|
236
|
+
type: string
|
|
237
|
+
x-internal: true
|
|
238
|
+
`,
|
|
239
|
+
);
|
|
240
|
+
const { bundle: res } = await bundleDocument({
|
|
241
|
+
document: testDoc,
|
|
242
|
+
externalRefResolver: new BaseResolver(),
|
|
243
|
+
config: makeConfig({}, { 'remove-x-internal': 'on' }),
|
|
244
|
+
});
|
|
245
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
246
|
+
openapi: 3.0.1
|
|
247
|
+
info:
|
|
248
|
+
version: 1.0.0
|
|
249
|
+
title: Test API
|
|
250
|
+
paths:
|
|
251
|
+
/test1:
|
|
252
|
+
get:
|
|
253
|
+
parameters:
|
|
254
|
+
- in: query
|
|
255
|
+
name: inline
|
|
256
|
+
schema:
|
|
257
|
+
type: string
|
|
258
|
+
/test2:
|
|
259
|
+
get:
|
|
260
|
+
parameters:
|
|
261
|
+
- $ref: '#/components/parameters/Public'
|
|
262
|
+
components:
|
|
263
|
+
parameters:
|
|
264
|
+
Public:
|
|
265
|
+
in: path
|
|
266
|
+
name: product_id
|
|
267
|
+
schema:
|
|
268
|
+
type: string
|
|
269
|
+
|
|
270
|
+
`);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe('oas2 remove-x-internal', () => {
|
|
275
|
+
it('should clean types - base test', async () => {
|
|
276
|
+
const testDoc = parseYamlToDocument(
|
|
277
|
+
outdent`
|
|
278
|
+
swagger: '2.0'
|
|
279
|
+
host: api.instagram.com
|
|
280
|
+
paths:
|
|
281
|
+
'/geographies/{geo-id}/media/recent':
|
|
282
|
+
get:
|
|
283
|
+
parameters:
|
|
284
|
+
- description: The geography ID.
|
|
285
|
+
x-internal: true
|
|
286
|
+
in: path
|
|
287
|
+
name: geo-id
|
|
288
|
+
required: true
|
|
289
|
+
type: string
|
|
290
|
+
- description: Max number of media to return.
|
|
291
|
+
x-internal: true
|
|
292
|
+
format: int32
|
|
293
|
+
in: query
|
|
294
|
+
name: count
|
|
295
|
+
required: false
|
|
296
|
+
type: integer
|
|
297
|
+
responses:
|
|
298
|
+
'200':
|
|
299
|
+
x-internal: true
|
|
300
|
+
description: List of recent media entries.
|
|
301
|
+
`,
|
|
302
|
+
);
|
|
303
|
+
const { bundle: res } = await bundleDocument({
|
|
304
|
+
document: testDoc,
|
|
305
|
+
externalRefResolver: new BaseResolver(),
|
|
306
|
+
config: makeConfig({}, { 'remove-x-internal': 'on' }),
|
|
307
|
+
});
|
|
308
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
309
|
+
swagger: '2.0'
|
|
310
|
+
host: api.instagram.com
|
|
311
|
+
paths:
|
|
312
|
+
/geographies/{geo-id}/media/recent:
|
|
313
|
+
get: {}
|
|
314
|
+
|
|
315
|
+
`);
|
|
316
|
+
});
|
|
317
|
+
});
|