oas-toolkit 0.5.2 → 0.6.0

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/components.js CHANGED
@@ -28,14 +28,23 @@ function getReferencedComponents(oas) {
28
28
  if (this.isLeaf && this.key == "$ref") {
29
29
  acc.push(x.replace("#/", "").replace(/\//g, "."));
30
30
  }
31
+
32
+ // Per-operation security schemes
33
+ if (this.node && this.node["operationId"] && this.node["security"]) {
34
+ for (let item of this.node["security"]) {
35
+ for (let key of Object.keys(item)) {
36
+ acc.push(`components.securitySchemes.${key}`);
37
+ }
38
+ }
39
+ }
31
40
  return acc;
32
41
  }, []);
33
42
 
34
- // Add security schemes
35
- if (oas.security){
36
- for (let item of oas.security){
37
- for (let key of Object.keys(item)){
38
- components.push(`components.securitySchemes.${key}`)
43
+ // Add global security schemes
44
+ if (oas.security) {
45
+ for (let item of oas.security) {
46
+ for (let key of Object.keys(item)) {
47
+ components.push(`components.securitySchemes.${key}`);
39
48
  }
40
49
  }
41
50
  }
@@ -258,4 +258,50 @@ describe("#components", () => {
258
258
  },
259
259
  });
260
260
  });
261
+
262
+ it("checks per-operation security schemas in addition to global", () => {
263
+ const securityOas = {
264
+ info: { title: "One" },
265
+ components: {
266
+ securitySchemes: {
267
+ personalAccessToken: {
268
+ type: "http",
269
+ scheme: "bearer",
270
+ },
271
+ systemAccessToken: {
272
+ type: "http",
273
+ scheme: "bearer",
274
+ },
275
+ },
276
+ },
277
+ paths: {
278
+ "/foo": {
279
+ post: {
280
+ operationId: "test-foo",
281
+ security: [{ systemAccessToken: {} }],
282
+ },
283
+ },
284
+ },
285
+ };
286
+
287
+ expect(c.removeUnusedComponents(securityOas)).toEqual({
288
+ info: { title: "One" },
289
+ paths: {
290
+ "/foo": {
291
+ post: {
292
+ operationId: "test-foo",
293
+ security: [{ systemAccessToken: {} }],
294
+ },
295
+ },
296
+ },
297
+ components: {
298
+ securitySchemes: {
299
+ systemAccessToken: {
300
+ type: "http",
301
+ scheme: "bearer",
302
+ },
303
+ },
304
+ },
305
+ });
306
+ });
261
307
  });
package/merger.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const mergician = require("mergician");
2
+ const traverse = require("traverse");
2
3
  const isEqual = require("lodash.isequal");
3
4
  const uniqWith = require("lodash.uniqwith");
4
5
 
@@ -28,6 +29,26 @@ function merge(objects, options) {
28
29
  }
29
30
  }
30
31
 
32
+ // Unique values that are at a non-deterministic path
33
+ combinedSpec = traverse(combinedSpec).map(function () {
34
+ if (["oneOf", "allOf", "anyOf"].includes(this.key)) {
35
+ this.node = uniqWith(this.node, isEqual);
36
+ }
37
+ });
38
+
39
+ // Validate that $ref is the only thing at a specific level
40
+ combinedSpec = traverse(combinedSpec).map(function () {
41
+ if (["oneOf", "allOf", "anyOf", "$ref"].includes(this.key)) {
42
+ if (Object.keys(this.parent.node).length > 1) {
43
+ throw new Error(
44
+ `Cannot have ${
45
+ this.key
46
+ } and other properties at the same level: ${this.path.join(".")}`
47
+ );
48
+ }
49
+ }
50
+ });
51
+
31
52
  return combinedSpec;
32
53
  }
33
54
 
package/merger.test.js CHANGED
@@ -334,4 +334,190 @@ describe("returns unique items for:", () => {
334
334
  security: [{ appKey: [] }],
335
335
  });
336
336
  });
337
+
338
+ it("oneOf", () => {
339
+ expect(
340
+ merger([
341
+ {
342
+ components: {
343
+ schemas: {
344
+ DemoError: {
345
+ oneOf: [
346
+ { $ref: "#/components/schemas/One" },
347
+ { $ref: "#/components/schemas/Two" },
348
+ { $ref: "#/components/schemas/Three" },
349
+ ],
350
+ },
351
+ },
352
+ },
353
+ },
354
+ {
355
+ components: {
356
+ schemas: {
357
+ DemoError: {
358
+ oneOf: [
359
+ { $ref: "#/components/schemas/One" },
360
+ { $ref: "#/components/schemas/Two" },
361
+ { $ref: "#/components/schemas/Four" },
362
+ ],
363
+ },
364
+ AnotherError: {
365
+ $ref: "#/components/schemas/One",
366
+ },
367
+ },
368
+ },
369
+ },
370
+ ])
371
+ ).toEqual({
372
+ components: {
373
+ schemas: {
374
+ DemoError: {
375
+ oneOf: [
376
+ { $ref: "#/components/schemas/One" },
377
+ { $ref: "#/components/schemas/Two" },
378
+ { $ref: "#/components/schemas/Three" },
379
+ { $ref: "#/components/schemas/Four" },
380
+ ],
381
+ },
382
+ AnotherError: {
383
+ $ref: "#/components/schemas/One",
384
+ },
385
+ },
386
+ },
387
+ });
388
+ });
389
+
390
+ it("allOf", () => {
391
+ expect(
392
+ merger([
393
+ {
394
+ components: {
395
+ schemas: {
396
+ DemoError: {
397
+ allOf: [{ $ref: "#/components/schemas/One" }],
398
+ },
399
+ },
400
+ },
401
+ },
402
+ {
403
+ components: {
404
+ schemas: {
405
+ DemoError: {
406
+ allOf: [{ $ref: "#/components/schemas/One" }],
407
+ },
408
+ },
409
+ },
410
+ },
411
+ ])
412
+ ).toEqual({
413
+ components: {
414
+ schemas: {
415
+ DemoError: {
416
+ allOf: [{ $ref: "#/components/schemas/One" }],
417
+ },
418
+ },
419
+ },
420
+ });
421
+ });
422
+
423
+ it("anyOf", () => {
424
+ expect(
425
+ merger([
426
+ {
427
+ components: {
428
+ schemas: {
429
+ DemoError: {
430
+ allOf: [{ $ref: "#/components/schemas/One" }],
431
+ },
432
+ },
433
+ },
434
+ },
435
+ {
436
+ components: {
437
+ schemas: {
438
+ DemoError: {
439
+ allOf: [{ $ref: "#/components/schemas/One" }],
440
+ },
441
+ },
442
+ },
443
+ },
444
+ ])
445
+ ).toEqual({
446
+ components: {
447
+ schemas: {
448
+ DemoError: {
449
+ allOf: [{ $ref: "#/components/schemas/One" }],
450
+ },
451
+ },
452
+ },
453
+ });
454
+ });
455
+ });
456
+
457
+ describe("validates the final output", () => {
458
+ it("throws when $ref is detected alongside other values", () => {
459
+ expect(() => {
460
+ merger([
461
+ {
462
+ components: {
463
+ schemas: {
464
+ DemoError: {
465
+ type: "object",
466
+ properties: {
467
+ code: {
468
+ type: "string",
469
+ example: "ERROR_ABC",
470
+ },
471
+ },
472
+ },
473
+ },
474
+ },
475
+ },
476
+ {
477
+ components: {
478
+ schemas: {
479
+ DemoError: {
480
+ $ref: "#/components/schemas/AnotherError",
481
+ },
482
+ },
483
+ },
484
+ },
485
+ ]);
486
+ }).toThrow(
487
+ "Cannot have $ref and other properties at the same level: components.schemas.DemoError.$ref"
488
+ );
489
+ });
490
+
491
+ it("throws when $ref is detected alongside other values", () => {
492
+ expect(() => {
493
+ merger([
494
+ {
495
+ components: {
496
+ schemas: {
497
+ DemoError: {
498
+ type: "object",
499
+ properties: {
500
+ code: {
501
+ type: "string",
502
+ example: "ERROR_ABC",
503
+ },
504
+ },
505
+ },
506
+ },
507
+ },
508
+ },
509
+ {
510
+ components: {
511
+ schemas: {
512
+ DemoError: {
513
+ oneOf: ["#/components/schemas/AnotherError"],
514
+ },
515
+ },
516
+ },
517
+ },
518
+ ]);
519
+ }).toThrow(
520
+ "Cannot have oneOf and other properties at the same level: components.schemas.DemoError.oneOf"
521
+ );
522
+ });
337
523
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oas-toolkit",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {