@redocly/openapi-core 1.0.0-beta.101 → 1.0.0-beta.104
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/config/config.d.ts +3 -3
- package/lib/config/load.d.ts +1 -1
- package/lib/config/load.js +15 -2
- package/lib/config/rules.d.ts +1 -1
- package/lib/config/types.d.ts +4 -2
- package/lib/decorators/common/filters/filter-helper.d.ts +3 -0
- package/lib/decorators/common/filters/filter-helper.js +67 -0
- package/lib/decorators/common/filters/filter-in.d.ts +2 -0
- package/lib/decorators/common/filters/filter-in.js +17 -0
- package/lib/decorators/common/filters/filter-out.d.ts +2 -0
- package/lib/decorators/common/filters/filter-out.js +17 -0
- package/lib/decorators/oas2/index.d.ts +2 -0
- package/lib/decorators/oas2/index.js +5 -1
- package/lib/decorators/oas3/index.d.ts +2 -0
- package/lib/decorators/oas3/index.js +5 -1
- package/lib/index.d.ts +1 -1
- package/lib/lint.d.ts +2 -0
- package/lib/lint.js +2 -2
- package/lib/redocly/registry-api-types.d.ts +2 -0
- package/lib/redocly/registry-api.d.ts +1 -1
- package/lib/redocly/registry-api.js +3 -1
- package/lib/rules/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +1 -1
- package/lib/rules/common/assertions/asserts.d.ts +6 -1
- package/lib/rules/common/assertions/asserts.js +81 -51
- package/lib/rules/common/assertions/utils.d.ts +2 -1
- package/lib/rules/common/assertions/utils.js +27 -8
- package/lib/types/redocly-yaml.js +317 -27
- package/lib/utils.d.ts +2 -1
- package/lib/utils.js +5 -1
- package/lib/walk.d.ts +4 -14
- package/lib/walk.js +35 -26
- package/package.json +3 -2
- package/src/__tests__/lint.test.ts +17 -4
- package/src/config/__tests__/load.test.ts +6 -0
- package/src/config/load.ts +28 -5
- package/src/config/types.ts +6 -5
- package/src/decorators/__tests__/filter-in.test.ts +310 -0
- package/src/decorators/__tests__/filter-out.test.ts +331 -0
- package/src/decorators/common/filters/filter-helper.ts +72 -0
- package/src/decorators/common/filters/filter-in.ts +18 -0
- package/src/decorators/common/filters/filter-out.ts +18 -0
- package/src/decorators/oas2/index.ts +5 -1
- package/src/decorators/oas3/index.ts +5 -1
- package/src/index.ts +1 -0
- package/src/lint.ts +4 -3
- package/src/redocly/registry-api-types.ts +2 -0
- package/src/redocly/registry-api.ts +4 -0
- package/src/rules/ajv.ts +4 -4
- package/src/rules/common/assertions/__tests__/asserts.test.ts +149 -146
- package/src/rules/common/assertions/asserts.ts +97 -52
- package/src/rules/common/assertions/utils.ts +41 -16
- package/src/types/redocly-yaml.ts +322 -34
- package/src/utils.ts +10 -7
- package/src/walk.ts +59 -47
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
import { bundleDocument } from '../../bundle';
|
|
3
|
+
import { BaseResolver } from '../../resolve';
|
|
4
|
+
import { makeConfig, parseYamlToDocument, yamlSerializer } from '../../../__tests__/utils';
|
|
5
|
+
|
|
6
|
+
describe('oas3 filter-out', () => {
|
|
7
|
+
expect.addSnapshotSerializer(yamlSerializer);
|
|
8
|
+
|
|
9
|
+
const inputDoc = parseYamlToDocument(
|
|
10
|
+
outdent`
|
|
11
|
+
openapi: 3.0.0
|
|
12
|
+
paths:
|
|
13
|
+
/pet:
|
|
14
|
+
x-audience: Private
|
|
15
|
+
post:
|
|
16
|
+
summary: test
|
|
17
|
+
/user:
|
|
18
|
+
x-audience: Protected
|
|
19
|
+
post:
|
|
20
|
+
summary: test
|
|
21
|
+
/order:
|
|
22
|
+
x-audience: [Private, Protected]
|
|
23
|
+
post:
|
|
24
|
+
operationId: storeOrder
|
|
25
|
+
parameters:
|
|
26
|
+
- name: api_key
|
|
27
|
+
callbacks:
|
|
28
|
+
x-access: protected
|
|
29
|
+
orderInProgress:
|
|
30
|
+
x-internal: true`);
|
|
31
|
+
|
|
32
|
+
it('should remove /pet path and y parameter', async () => {
|
|
33
|
+
const testDocument = parseYamlToDocument(
|
|
34
|
+
outdent`
|
|
35
|
+
openapi: 3.0.0
|
|
36
|
+
paths:
|
|
37
|
+
/pet:
|
|
38
|
+
x-access: private
|
|
39
|
+
get:
|
|
40
|
+
parameters:
|
|
41
|
+
- $ref: '#/components/parameters/y'
|
|
42
|
+
components:
|
|
43
|
+
parameters:
|
|
44
|
+
x:
|
|
45
|
+
name: x
|
|
46
|
+
y:
|
|
47
|
+
x-access: private
|
|
48
|
+
name: y
|
|
49
|
+
`
|
|
50
|
+
);
|
|
51
|
+
const { bundle: res } = await bundleDocument({
|
|
52
|
+
document: testDocument,
|
|
53
|
+
externalRefResolver: new BaseResolver(),
|
|
54
|
+
config: await makeConfig({}, { 'filter-out': { property: 'x-access', value: 'private' } }),
|
|
55
|
+
});
|
|
56
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
57
|
+
openapi: 3.0.0
|
|
58
|
+
components:
|
|
59
|
+
parameters:
|
|
60
|
+
x:
|
|
61
|
+
name: x
|
|
62
|
+
|
|
63
|
+
`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should remove only /order path', async () => {
|
|
67
|
+
const { bundle: res } = await bundleDocument({
|
|
68
|
+
document: inputDoc,
|
|
69
|
+
externalRefResolver: new BaseResolver(),
|
|
70
|
+
config: await makeConfig(
|
|
71
|
+
{},
|
|
72
|
+
{
|
|
73
|
+
'filter-out': {
|
|
74
|
+
property: 'x-audience',
|
|
75
|
+
value: ['Private', 'Protected'],
|
|
76
|
+
matchStrategy: 'all',
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
});
|
|
81
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
82
|
+
openapi: 3.0.0
|
|
83
|
+
paths:
|
|
84
|
+
/pet:
|
|
85
|
+
x-audience: Private
|
|
86
|
+
post:
|
|
87
|
+
summary: test
|
|
88
|
+
/user:
|
|
89
|
+
x-audience: Protected
|
|
90
|
+
post:
|
|
91
|
+
summary: test
|
|
92
|
+
components: {}
|
|
93
|
+
|
|
94
|
+
`);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should remove all paths', async () => {
|
|
98
|
+
const { bundle: res } = await bundleDocument({
|
|
99
|
+
document: inputDoc,
|
|
100
|
+
externalRefResolver: new BaseResolver(),
|
|
101
|
+
config: await makeConfig(
|
|
102
|
+
{},
|
|
103
|
+
{
|
|
104
|
+
'filter-out': {
|
|
105
|
+
property: 'x-audience',
|
|
106
|
+
value: ['Private', 'Protected'],
|
|
107
|
+
matchStrategy: 'any',
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
});
|
|
112
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
113
|
+
openapi: 3.0.0
|
|
114
|
+
components: {}
|
|
115
|
+
|
|
116
|
+
`);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should remove requestBody', async () => {
|
|
120
|
+
const testDoc = parseYamlToDocument(
|
|
121
|
+
outdent`
|
|
122
|
+
openapi: 3.0.0
|
|
123
|
+
paths:
|
|
124
|
+
/pet:
|
|
125
|
+
post:
|
|
126
|
+
summary: test
|
|
127
|
+
requestBody:
|
|
128
|
+
content:
|
|
129
|
+
x-access: private
|
|
130
|
+
application/x-www-form-urlencoded:
|
|
131
|
+
schema:
|
|
132
|
+
type: object
|
|
133
|
+
components: {}
|
|
134
|
+
|
|
135
|
+
`);
|
|
136
|
+
const { bundle: res } = await bundleDocument({
|
|
137
|
+
document: testDoc,
|
|
138
|
+
externalRefResolver: new BaseResolver(),
|
|
139
|
+
config: await makeConfig(
|
|
140
|
+
{},
|
|
141
|
+
{
|
|
142
|
+
'filter-out': {
|
|
143
|
+
property: 'x-access',
|
|
144
|
+
value: 'private',
|
|
145
|
+
matchStrategy: 'any',
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
),
|
|
149
|
+
});
|
|
150
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
151
|
+
openapi: 3.0.0
|
|
152
|
+
paths:
|
|
153
|
+
/pet:
|
|
154
|
+
post:
|
|
155
|
+
summary: test
|
|
156
|
+
components: {}
|
|
157
|
+
|
|
158
|
+
`);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should remove /pet path and /my/path/false path', async () => {
|
|
162
|
+
const testDocument = parseYamlToDocument(
|
|
163
|
+
outdent`
|
|
164
|
+
openapi: 3.0.0
|
|
165
|
+
paths:
|
|
166
|
+
/pet:
|
|
167
|
+
get:
|
|
168
|
+
x-prop: false
|
|
169
|
+
parameters:
|
|
170
|
+
- $ref: '#/components/parameters/x'
|
|
171
|
+
/my/path/false:
|
|
172
|
+
x-access: private
|
|
173
|
+
x-prop: false
|
|
174
|
+
get:
|
|
175
|
+
parameters:
|
|
176
|
+
- $ref: '#/components/parameters/x'
|
|
177
|
+
/my/path/null:
|
|
178
|
+
x-access: private
|
|
179
|
+
x-prop: null
|
|
180
|
+
get:
|
|
181
|
+
parameters:
|
|
182
|
+
- $ref: '#/components/parameters/x'
|
|
183
|
+
components:
|
|
184
|
+
parameters:
|
|
185
|
+
x:
|
|
186
|
+
name: x
|
|
187
|
+
|
|
188
|
+
`);
|
|
189
|
+
const { bundle: res } = await bundleDocument({
|
|
190
|
+
document: testDocument,
|
|
191
|
+
externalRefResolver: new BaseResolver(),
|
|
192
|
+
config: await makeConfig({}, { 'filter-out': { property: 'x-prop', value: false } }),
|
|
193
|
+
});
|
|
194
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
195
|
+
openapi: 3.0.0
|
|
196
|
+
paths:
|
|
197
|
+
/my/path/null:
|
|
198
|
+
x-access: private
|
|
199
|
+
x-prop: null
|
|
200
|
+
get:
|
|
201
|
+
parameters:
|
|
202
|
+
- $ref: '#/components/parameters/x'
|
|
203
|
+
components:
|
|
204
|
+
parameters:
|
|
205
|
+
x:
|
|
206
|
+
name: x
|
|
207
|
+
|
|
208
|
+
`);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should remove /my/path/null path ', async () => {
|
|
212
|
+
const testDocument = parseYamlToDocument(
|
|
213
|
+
outdent`
|
|
214
|
+
openapi: 3.0.0
|
|
215
|
+
paths:
|
|
216
|
+
/pet:
|
|
217
|
+
x-access: private
|
|
218
|
+
get:
|
|
219
|
+
x-prop: false
|
|
220
|
+
parameters:
|
|
221
|
+
- $ref: '#/components/parameters/y'
|
|
222
|
+
/my/path/false:
|
|
223
|
+
x-access: private
|
|
224
|
+
x-prop: false
|
|
225
|
+
get:
|
|
226
|
+
parameters:
|
|
227
|
+
- $ref: '#/components/parameters/y'
|
|
228
|
+
/my/path/null:
|
|
229
|
+
x-access: private
|
|
230
|
+
x-prop: null
|
|
231
|
+
get:
|
|
232
|
+
parameters:
|
|
233
|
+
- $ref: '#/components/parameters/y'
|
|
234
|
+
components:
|
|
235
|
+
parameters:
|
|
236
|
+
x:
|
|
237
|
+
name: x
|
|
238
|
+
|
|
239
|
+
`);
|
|
240
|
+
const { bundle: res } = await bundleDocument({
|
|
241
|
+
document: testDocument,
|
|
242
|
+
externalRefResolver: new BaseResolver(),
|
|
243
|
+
config: await makeConfig({}, { 'filter-out': { property: 'x-prop', value: null } }),
|
|
244
|
+
});
|
|
245
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
246
|
+
openapi: 3.0.0
|
|
247
|
+
paths:
|
|
248
|
+
/pet:
|
|
249
|
+
x-access: private
|
|
250
|
+
get:
|
|
251
|
+
x-prop: false
|
|
252
|
+
parameters:
|
|
253
|
+
- $ref: '#/components/parameters/y'
|
|
254
|
+
/my/path/false:
|
|
255
|
+
x-access: private
|
|
256
|
+
x-prop: false
|
|
257
|
+
get:
|
|
258
|
+
parameters:
|
|
259
|
+
- $ref: '#/components/parameters/y'
|
|
260
|
+
components:
|
|
261
|
+
parameters:
|
|
262
|
+
x:
|
|
263
|
+
name: x
|
|
264
|
+
|
|
265
|
+
`);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('oas2 filter-out', () => {
|
|
270
|
+
it('should clean all parameters and responses ', async () => {
|
|
271
|
+
const testDoc = parseYamlToDocument(
|
|
272
|
+
outdent`
|
|
273
|
+
swagger: '2.0'
|
|
274
|
+
host: api.instagram.com
|
|
275
|
+
paths:
|
|
276
|
+
'/geographies/{geo-id}/media/recent':
|
|
277
|
+
get:
|
|
278
|
+
parameters:
|
|
279
|
+
- description: The geography ID.
|
|
280
|
+
x-access: private
|
|
281
|
+
in: path
|
|
282
|
+
name: geo-id
|
|
283
|
+
required: true
|
|
284
|
+
type: string
|
|
285
|
+
- description: Max number of media to return.
|
|
286
|
+
x-access: protected
|
|
287
|
+
format: int32
|
|
288
|
+
in: query
|
|
289
|
+
name: count
|
|
290
|
+
required: false
|
|
291
|
+
type: integer
|
|
292
|
+
responses:
|
|
293
|
+
$ref: '#/components/response/200'
|
|
294
|
+
components:
|
|
295
|
+
response:
|
|
296
|
+
'200':
|
|
297
|
+
description: List of recent media entries.
|
|
298
|
+
x-access: [protected, public]
|
|
299
|
+
`
|
|
300
|
+
);
|
|
301
|
+
const { bundle: res } = await bundleDocument({
|
|
302
|
+
document: testDoc,
|
|
303
|
+
externalRefResolver: new BaseResolver(),
|
|
304
|
+
config: await makeConfig(
|
|
305
|
+
{},
|
|
306
|
+
{
|
|
307
|
+
'filter-out': {
|
|
308
|
+
property: 'x-access',
|
|
309
|
+
value: ['private', 'protected'],
|
|
310
|
+
matchStrategy: 'any',
|
|
311
|
+
},
|
|
312
|
+
}
|
|
313
|
+
),
|
|
314
|
+
});
|
|
315
|
+
expect(res.parsed).toMatchInlineSnapshot(`
|
|
316
|
+
swagger: '2.0'
|
|
317
|
+
host: api.instagram.com
|
|
318
|
+
paths:
|
|
319
|
+
/geographies/{geo-id}/media/recent:
|
|
320
|
+
get: {}
|
|
321
|
+
components:
|
|
322
|
+
response:
|
|
323
|
+
'200':
|
|
324
|
+
description: List of recent media entries.
|
|
325
|
+
x-access:
|
|
326
|
+
- protected
|
|
327
|
+
- public
|
|
328
|
+
|
|
329
|
+
`);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { UserContext } from '../../../walk';
|
|
2
|
+
import { isRef } from '../../../ref-utils';
|
|
3
|
+
import { isEmptyArray, isEmptyObject, isPlainObject } from '../../../utils';
|
|
4
|
+
|
|
5
|
+
export function filter(node: any, ctx: UserContext, criteria: (item: any) => boolean) {
|
|
6
|
+
const { parent, key } = ctx;
|
|
7
|
+
let didDelete = false;
|
|
8
|
+
if (Array.isArray(node)) {
|
|
9
|
+
for (let i = 0; i < node.length; i++) {
|
|
10
|
+
if (isRef(node[i])) {
|
|
11
|
+
const resolved = ctx.resolve(node[i]);
|
|
12
|
+
if (criteria(resolved.node)) {
|
|
13
|
+
node.splice(i, 1);
|
|
14
|
+
didDelete = true;
|
|
15
|
+
i--;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (criteria(node[i])) {
|
|
19
|
+
node.splice(i, 1);
|
|
20
|
+
didDelete = true;
|
|
21
|
+
i--;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
} else if (isPlainObject(node)) {
|
|
25
|
+
for (const key of Object.keys(node)) {
|
|
26
|
+
node = node as any;
|
|
27
|
+
if (isRef(node[key])) {
|
|
28
|
+
const resolved = ctx.resolve(node[key]);
|
|
29
|
+
if (criteria(resolved.node)) {
|
|
30
|
+
delete node[key];
|
|
31
|
+
didDelete = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (criteria(node[key])) {
|
|
35
|
+
delete node[key];
|
|
36
|
+
didDelete = true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (didDelete && (isEmptyObject(node) || isEmptyArray(node))) {
|
|
41
|
+
delete parent[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function checkIfMatchByStrategy(
|
|
46
|
+
nodeValue: any,
|
|
47
|
+
decoratorValue: any,
|
|
48
|
+
strategy: 'all' | 'any'
|
|
49
|
+
): boolean {
|
|
50
|
+
if (nodeValue===undefined || decoratorValue===undefined) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!Array.isArray(decoratorValue) && !Array.isArray(nodeValue)) {
|
|
55
|
+
return nodeValue === decoratorValue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
decoratorValue = toArrayIfNeeded<string>(decoratorValue);
|
|
59
|
+
nodeValue = toArrayIfNeeded<string>(nodeValue);
|
|
60
|
+
|
|
61
|
+
if (strategy === 'any') {
|
|
62
|
+
return decoratorValue.some((item: string) => nodeValue.includes(item));
|
|
63
|
+
}
|
|
64
|
+
if (strategy === 'all') {
|
|
65
|
+
return decoratorValue.every((item: string) => nodeValue.includes(item));
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function toArrayIfNeeded<T>(value: T | T[]): T[] {
|
|
71
|
+
return Array.isArray(value) ? value : [value];
|
|
72
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Oas2Decorator, Oas3Decorator } from '../../../visitors';
|
|
2
|
+
import { checkIfMatchByStrategy, filter } from './filter-helper';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_STRATEGY = 'any';
|
|
5
|
+
|
|
6
|
+
export const FilterIn: Oas3Decorator | Oas2Decorator = ({ property, value, matchStrategy }) => {
|
|
7
|
+
const strategy = matchStrategy || DEFAULT_STRATEGY;
|
|
8
|
+
const filterInCriteria = (item: any) =>
|
|
9
|
+
item?.[property] && !checkIfMatchByStrategy(item?.[property], value, strategy);
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
any: {
|
|
13
|
+
enter: (node, ctx) => {
|
|
14
|
+
filter(node, ctx, filterInCriteria);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Oas2Decorator, Oas3Decorator } from '../../../visitors';
|
|
2
|
+
import { checkIfMatchByStrategy, filter } from './filter-helper';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_STRATEGY = 'any';
|
|
5
|
+
|
|
6
|
+
export const FilterOut: Oas3Decorator | Oas2Decorator = ({ property, value, matchStrategy }) => {
|
|
7
|
+
const strategy = matchStrategy || DEFAULT_STRATEGY;
|
|
8
|
+
const filterOutCriteria = (item: any) =>
|
|
9
|
+
checkIfMatchByStrategy(item?.[property], value, strategy);
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
any: {
|
|
13
|
+
enter: (node, ctx) => {
|
|
14
|
+
filter(node, ctx, filterOutCriteria);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -4,11 +4,15 @@ import { OperationDescriptionOverride } from '../common/operation-description-ov
|
|
|
4
4
|
import { TagDescriptionOverride } from '../common/tag-description-override';
|
|
5
5
|
import { InfoDescriptionOverride } from '../common/info-description-override';
|
|
6
6
|
import { RemoveXInternal } from '../common/remove-x-internal';
|
|
7
|
+
import { FilterIn } from '../common/filters/filter-in';
|
|
8
|
+
import { FilterOut } from '../common/filters/filter-out';
|
|
7
9
|
|
|
8
10
|
export const decorators = {
|
|
9
11
|
'registry-dependencies': RegistryDependencies as Oas2Decorator,
|
|
10
12
|
'operation-description-override': OperationDescriptionOverride as Oas2Decorator,
|
|
11
13
|
'tag-description-override': TagDescriptionOverride as Oas2Decorator,
|
|
12
14
|
'info-description-override': InfoDescriptionOverride as Oas2Decorator,
|
|
13
|
-
'remove-x-internal': RemoveXInternal as Oas2Decorator
|
|
15
|
+
'remove-x-internal': RemoveXInternal as Oas2Decorator,
|
|
16
|
+
'filter-in': FilterIn as Oas2Decorator,
|
|
17
|
+
'filter-out': FilterOut as Oas2Decorator,
|
|
14
18
|
};
|
|
@@ -4,11 +4,15 @@ import { OperationDescriptionOverride } from '../common/operation-description-ov
|
|
|
4
4
|
import { TagDescriptionOverride } from '../common/tag-description-override';
|
|
5
5
|
import { InfoDescriptionOverride } from '../common/info-description-override';
|
|
6
6
|
import { RemoveXInternal } from '../common/remove-x-internal';
|
|
7
|
+
import { FilterIn } from '../common/filters/filter-in';
|
|
8
|
+
import { FilterOut } from '../common/filters/filter-out';
|
|
7
9
|
|
|
8
10
|
export const decorators = {
|
|
9
11
|
'registry-dependencies': RegistryDependencies as Oas3Decorator,
|
|
10
12
|
'operation-description-override': OperationDescriptionOverride as Oas3Decorator,
|
|
11
13
|
'tag-description-override': TagDescriptionOverride as Oas3Decorator,
|
|
12
14
|
'info-description-override': InfoDescriptionOverride as Oas3Decorator,
|
|
13
|
-
'remove-x-internal': RemoveXInternal as Oas3Decorator
|
|
15
|
+
'remove-x-internal': RemoveXInternal as Oas3Decorator,
|
|
16
|
+
'filter-in': FilterIn as Oas3Decorator,
|
|
17
|
+
'filter-out': FilterOut as Oas3Decorator,
|
|
14
18
|
};
|
package/src/index.ts
CHANGED
package/src/lint.ts
CHANGED
|
@@ -94,9 +94,10 @@ export async function lintDocument(opts: {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
export async function lintConfig(opts: {
|
|
97
|
-
document: Document
|
|
97
|
+
document: Document
|
|
98
|
+
severity?: ProblemSeverity
|
|
98
99
|
}) {
|
|
99
|
-
const { document } = opts;
|
|
100
|
+
const { document, severity } = opts;
|
|
100
101
|
|
|
101
102
|
const ctx: WalkContext = {
|
|
102
103
|
problems: [],
|
|
@@ -110,7 +111,7 @@ export async function lintConfig(opts: {
|
|
|
110
111
|
});
|
|
111
112
|
|
|
112
113
|
const types = normalizeTypes(ConfigTypes, config);
|
|
113
|
-
const rules = [{ severity: 'error'
|
|
114
|
+
const rules = [{ severity: severity || 'error', ruleId: 'configuration spec', visitor: OasSpec({ severity: 'error' }) }];
|
|
114
115
|
const normalizedVisitors = normalizeVisitors(rules, types);
|
|
115
116
|
|
|
116
117
|
walkDocument({
|
|
@@ -105,6 +105,8 @@ export class RegistryApi {
|
|
|
105
105
|
branch,
|
|
106
106
|
isUpsert,
|
|
107
107
|
isPublic,
|
|
108
|
+
batchId,
|
|
109
|
+
batchSize
|
|
108
110
|
}: RegistryApiTypes.PushApiParams) {
|
|
109
111
|
const response = await this.request(
|
|
110
112
|
`/${organizationId}/${name}/${version}`,
|
|
@@ -120,6 +122,8 @@ export class RegistryApi {
|
|
|
120
122
|
branch,
|
|
121
123
|
isUpsert,
|
|
122
124
|
isPublic,
|
|
125
|
+
batchId,
|
|
126
|
+
batchSize
|
|
123
127
|
}),
|
|
124
128
|
},
|
|
125
129
|
this.region,
|
package/src/rules/ajv.ts
CHANGED
|
@@ -8,7 +8,7 @@ export function releaseAjvInstance() {
|
|
|
8
8
|
ajvInstance = null;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
function getAjv(resolve: ResolveFn
|
|
11
|
+
function getAjv(resolve: ResolveFn, disallowAdditionalProperties: boolean) {
|
|
12
12
|
if (!ajvInstance) {
|
|
13
13
|
ajvInstance = new Ajv({
|
|
14
14
|
schemaId: '$id',
|
|
@@ -23,7 +23,7 @@ function getAjv(resolve: ResolveFn<any>, disallowAdditionalProperties: boolean)
|
|
|
23
23
|
defaultAdditionalProperties: !disallowAdditionalProperties,
|
|
24
24
|
loadSchemaSync(base: string, $ref: string) {
|
|
25
25
|
const resolvedRef = resolve({ $ref }, base.split('#')[0]);
|
|
26
|
-
if (!resolvedRef || !resolvedRef.location) return
|
|
26
|
+
if (!resolvedRef || !resolvedRef.location) return false;
|
|
27
27
|
return { $id: resolvedRef.location.absolutePointer, ...resolvedRef.node };
|
|
28
28
|
},
|
|
29
29
|
logger: false,
|
|
@@ -35,7 +35,7 @@ function getAjv(resolve: ResolveFn<any>, disallowAdditionalProperties: boolean)
|
|
|
35
35
|
function getAjvValidator(
|
|
36
36
|
schema: any,
|
|
37
37
|
loc: Location,
|
|
38
|
-
resolve: ResolveFn
|
|
38
|
+
resolve: ResolveFn,
|
|
39
39
|
disallowAdditionalProperties: boolean,
|
|
40
40
|
): ValidateFunction | undefined {
|
|
41
41
|
const ajv = getAjv(resolve, disallowAdditionalProperties);
|
|
@@ -52,7 +52,7 @@ export function validateJsonSchema(
|
|
|
52
52
|
schema: any,
|
|
53
53
|
schemaLoc: Location,
|
|
54
54
|
instancePath: string,
|
|
55
|
-
resolve: ResolveFn
|
|
55
|
+
resolve: ResolveFn,
|
|
56
56
|
disallowAdditionalProperties: boolean,
|
|
57
57
|
): { valid: boolean; errors: (ErrorObject & { suggest?: string[] })[] } {
|
|
58
58
|
const validate = getAjvValidator(schema, schemaLoc, resolve, disallowAdditionalProperties);
|