Skip to content

Commit 69ca7d5

Browse files
authored
fix: Multiple fixes for 3.0 -> 3.1 conversion (#173)
* fix: convert nullable for anyOf oneOf to 3.1 * fix: convert 0 correctly for exclusiveMinimum and exclusiveMaximum
1 parent a4d4244 commit 69ca7d5

File tree

6 files changed

+193
-15
lines changed

6 files changed

+193
-15
lines changed

openapi-format.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,10 +1120,10 @@ async function openapiConvertVersion(oaObj, options) {
11201120
traverse(jsonObj).forEach(function (node) {
11211121
if (typeof node === 'object' && node !== null) {
11221122
// Change components/schemas - properties
1123-
if (node.type) {
1124-
// Change type > nullable
1125-
node = convertNullable(node);
11261123

1124+
// Change anyOf/oneOf/type > nullable
1125+
node = convertNullable(node);
1126+
if (node.type) {
11271127
// Change type > example
11281128
node = convertExample(node);
11291129

@@ -1135,9 +1135,8 @@ async function openapiConvertVersion(oaObj, options) {
11351135

11361136
// Change type > single enum
11371137
node = convertConst(node);
1138-
1139-
this.update(node);
11401138
}
1139+
this.update(node);
11411140

11421141
// Change components/schemas - schema
11431142
if (node.schema) {

test/converting.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const testUtils = require('./__utils__/test-utils');
4-
const of = require('./../openapi-format');
54
const {
65
convertNullable,
76
convertExclusiveMinimum,

test/json-convert-3.1/input.json

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,58 @@
30793079
}
30803080
}
30813081
}
3082+
},
3083+
"/one-of-nullable": {
3084+
"patch": {
3085+
"requestBody": {
3086+
"content": {
3087+
"application/json": {
3088+
"schema": {
3089+
"oneOf": [
3090+
{
3091+
"$ref": "#/components/schemas/User"
3092+
},
3093+
{
3094+
"$ref": "#/components/schemas/Customer"
3095+
}
3096+
],
3097+
"nullable": true
3098+
}
3099+
}
3100+
}
3101+
},
3102+
"responses": {
3103+
"200": {
3104+
"description": "Updated"
3105+
}
3106+
}
3107+
}
3108+
},
3109+
"/any-of-nullable": {
3110+
"patch": {
3111+
"requestBody": {
3112+
"content": {
3113+
"application/json": {
3114+
"schema": {
3115+
"anyOf": [
3116+
{
3117+
"$ref": "#/components/schemas/User"
3118+
},
3119+
{
3120+
"$ref": "#/components/schemas/Customer"
3121+
}
3122+
],
3123+
"nullable": true
3124+
}
3125+
}
3126+
}
3127+
},
3128+
"responses": {
3129+
"200": {
3130+
"description": "Updated"
3131+
}
3132+
}
3133+
}
30823134
}
30833135
},
30843136
"externalDocs": {
@@ -3384,6 +3436,39 @@
33843436
"name": "##default"
33853437
},
33863438
"type": "object"
3439+
},
3440+
"FalseyExclusiveMinMax": {
3441+
"properties": {
3442+
"minIsZero": {
3443+
"type": "integer",
3444+
"maximum": 1,
3445+
"minimum": 0,
3446+
"exclusiveMaximum": true,
3447+
"exclusiveMinimum": true
3448+
},
3449+
"maxIsZero": {
3450+
"type": "integer",
3451+
"maximum": 0,
3452+
"minimum": 1,
3453+
"exclusiveMaximum": true,
3454+
"exclusiveMinimum": true
3455+
},
3456+
"bothAreZero": {
3457+
"type": "integer",
3458+
"maximum": 0,
3459+
"minimum": 0,
3460+
"exclusiveMaximum": true,
3461+
"exclusiveMinimum": true
3462+
},
3463+
"nonExclusive": {
3464+
"type": "integer",
3465+
"maximum": 0,
3466+
"minimum": 0,
3467+
"exclusiveMinimum": false,
3468+
"exclusiveMaximum": false
3469+
}
3470+
},
3471+
"type": "object"
33873472
}
33883473
},
33893474
"requestBodies": {

test/json-convert-3.1/output.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,6 +3496,62 @@
34963496
}
34973497
}
34983498
}
3499+
},
3500+
"/one-of-nullable": {
3501+
"patch": {
3502+
"requestBody": {
3503+
"content": {
3504+
"application/json": {
3505+
"schema": {
3506+
"oneOf": [
3507+
{
3508+
"$ref": "#/components/schemas/User"
3509+
},
3510+
{
3511+
"$ref": "#/components/schemas/Customer"
3512+
},
3513+
{
3514+
"type": "null"
3515+
}
3516+
]
3517+
}
3518+
}
3519+
}
3520+
},
3521+
"responses": {
3522+
"200": {
3523+
"description": "Updated"
3524+
}
3525+
}
3526+
}
3527+
},
3528+
"/any-of-nullable": {
3529+
"patch": {
3530+
"requestBody": {
3531+
"content": {
3532+
"application/json": {
3533+
"schema": {
3534+
"anyOf": [
3535+
{
3536+
"$ref": "#/components/schemas/User"
3537+
},
3538+
{
3539+
"$ref": "#/components/schemas/Customer"
3540+
},
3541+
{
3542+
"type": "null"
3543+
}
3544+
]
3545+
}
3546+
}
3547+
}
3548+
},
3549+
"responses": {
3550+
"200": {
3551+
"description": "Updated"
3552+
}
3553+
}
3554+
}
34993555
}
35003556
},
35013557
"externalDocs": {
@@ -3859,6 +3915,31 @@
38593915
"name": "##default"
38603916
},
38613917
"type": "object"
3918+
},
3919+
"FalseyExclusiveMinMax": {
3920+
"properties": {
3921+
"minIsZero": {
3922+
"type": "integer",
3923+
"exclusiveMaximum": 1,
3924+
"exclusiveMinimum": 0
3925+
},
3926+
"maxIsZero": {
3927+
"type": "integer",
3928+
"exclusiveMaximum": 0,
3929+
"exclusiveMinimum": 1
3930+
},
3931+
"bothAreZero": {
3932+
"type": "integer",
3933+
"exclusiveMaximum": 0,
3934+
"exclusiveMinimum": 0
3935+
},
3936+
"nonExclusive": {
3937+
"type": "integer",
3938+
"maximum": 0,
3939+
"minimum": 0
3940+
}
3941+
},
3942+
"type": "object"
38623943
}
38633944
},
38643945
"requestBodies": {

utils/convert.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {isObject, isArray, isNumber, isString} = require('./types');
1+
const {isObject, isArray, isNumber, isString, isUndefined} = require('./types');
22

33
/**
44
* Add property to object at certain position
@@ -18,14 +18,14 @@ function setInObject(obj, key, value, index) {
1818
for (let prop in obj) {
1919
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
2020
// If the indexes match, add the new item
21-
if (i === index && isNumber(index) && key && value) {
21+
if (i === index && isNumber(index) && key && !isUndefined(value)) {
2222
dto[key] = value;
2323
}
2424
// Add the current item in the loop to the temp obj
2525
dto[prop] = obj[prop];
2626

2727
// Add/overwrite item
28-
if (isString(index) && i === ordering.indexOf(index) && key && value) {
28+
if (isString(index) && i === ordering.indexOf(index) && key && !isUndefined(value)) {
2929
dto[key] = value;
3030
}
3131
// Increase the count
@@ -40,7 +40,12 @@ function setInObject(obj, key, value, index) {
4040
}
4141

4242
/**
43-
* Convert nullable property to type
43+
* converts:
44+
* `type: 'thing'` -> `type: ['thing']`
45+
* `type: 'thing', nullable: true` -> `type: ['thing', 'null']`
46+
* `anyOf: ['thing'], nullable: true` -> `anyOf: ['thing', {type: 'null'}]`
47+
* `oneOf: ['thing'], nullable: true` -> `oneOf: ['thing', {type: 'null'}]`
48+
*
4449
* @param {object} obj
4550
* @returns {*}
4651
*/
@@ -49,12 +54,20 @@ function convertNullable(obj) {
4954
if (obj.nullable === undefined) return obj;
5055

5156
let dto = JSON.parse(JSON.stringify(obj)); // Deep copy of the object
52-
const types = [dto.type.toString()];
53-
if (dto.nullable === true) {
54-
types.push('null');
57+
// Update for 3.1
58+
if (obj.type) {
59+
const types = [dto.type.toString()];
60+
if (dto.nullable === true) {
61+
types.push('null');
62+
}
63+
dto = setInObject(dto, 'type', types, 'type');
64+
} else if (dto.nullable === true && Array.isArray(dto.oneOf)) {
65+
const withNullType = dto.oneOf.concat({type: 'null'});
66+
dto = setInObject(dto, 'oneOf', withNullType, 'oneOf');
67+
} else if (dto.nullable === true && Array.isArray(dto.anyOf)) {
68+
const withNullType = dto.anyOf.concat({type: 'null'});
69+
dto = setInObject(dto, 'anyOf', withNullType, 'anyOf');
5570
}
56-
// Update 3.1 type
57-
dto = setInObject(dto, 'type', types, 'type');
5871
// Remove 3.0 prop
5972
delete dto.nullable;
6073
return dto;

utils/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@ module.exports = {
6060
isFunction: isFunction,
6161
isArray: isArray,
6262
isElement: isElement,
63+
isUndefined: isUndefined,
6364
isset: isset
6465
};

0 commit comments

Comments
 (0)