@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.
Files changed (42) hide show
  1. package/lib/bundle.d.ts +4 -0
  2. package/lib/bundle.js +32 -9
  3. package/lib/config/config.d.ts +2 -9
  4. package/lib/format/format.d.ts +1 -1
  5. package/lib/format/format.js +39 -1
  6. package/lib/index.d.ts +1 -1
  7. package/lib/index.js +2 -1
  8. package/lib/resolve.d.ts +1 -0
  9. package/lib/resolve.js +7 -3
  10. package/lib/rules/builtin.d.ts +2 -0
  11. package/lib/rules/common/remove-x-internal.d.ts +2 -0
  12. package/lib/rules/common/remove-x-internal.js +58 -0
  13. package/lib/rules/oas2/index.d.ts +1 -0
  14. package/lib/rules/oas2/index.js +2 -0
  15. package/lib/rules/oas2/remove-unused-components.d.ts +2 -0
  16. package/lib/rules/oas2/remove-unused-components.js +73 -0
  17. package/lib/rules/oas3/index.d.ts +1 -0
  18. package/lib/rules/oas3/index.js +2 -0
  19. package/lib/rules/oas3/remove-unused-components.d.ts +2 -0
  20. package/lib/rules/oas3/remove-unused-components.js +83 -0
  21. package/lib/typings/swagger.d.ts +14 -0
  22. package/lib/utils.d.ts +2 -0
  23. package/lib/utils.js +9 -1
  24. package/lib/walk.js +5 -8
  25. package/package.json +1 -1
  26. package/src/bundle.ts +38 -9
  27. package/src/config/config.ts +2 -3
  28. package/src/format/format.ts +47 -2
  29. package/src/index.ts +1 -1
  30. package/src/resolve.ts +6 -6
  31. package/src/rules/__tests__/config.ts +5 -4
  32. package/src/rules/__tests__/hide-internals.test.ts +317 -0
  33. package/src/rules/common/remove-x-internal.ts +59 -0
  34. package/src/rules/oas2/index.ts +3 -1
  35. package/src/rules/oas2/remove-unused-components.ts +76 -0
  36. package/src/rules/oas3/index.ts +2 -0
  37. package/src/rules/oas3/remove-unused-components.ts +84 -0
  38. package/src/types/oas2.ts +0 -3
  39. package/src/typings/swagger.ts +7 -0
  40. package/src/utils.ts +8 -0
  41. package/src/walk.ts +6 -13
  42. 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 + '::' + ref.$ref;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.0.0-beta.75",
3
+ "version": "1.0.0-beta.79",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
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;
@@ -38,10 +38,9 @@ export type PreprocessorConfig =
38
38
  | ProblemSeverity
39
39
  | 'off'
40
40
  | 'on'
41
- | {
41
+ | ({
42
42
  severity?: ProblemSeverity;
43
- options?: Record<string, any>;
44
- };
43
+ } & Record<string, any>);
45
44
 
46
45
  export type DecoratorConfig = PreprocessorConfig;
47
46
 
@@ -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 '&lt;';
296
+ case '>':
297
+ return '&gt;';
298
+ case '&':
299
+ return '&amp;';
300
+ case '"':
301
+ return '&quot;';
302
+ case "'":
303
+ return '&apos;';
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 + '::' + ref.$ref;
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 "../../config/config";
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
+ });