Skip to content

Commit ade6d2f

Browse files
authored
fix: change parsing of type: null to add nullable: true to oneOf/anyOf (#43)
1 parent e5e74e7 commit ade6d2f

File tree

5 files changed

+739
-395
lines changed

5 files changed

+739
-395
lines changed

Diff for: package.json

+9-9
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,22 @@
3636
"dependencies": {
3737
"@apidevtools/json-schema-ref-parser": "^9.0.9",
3838
"json-schema-walker": "^1.1.0",
39-
"openapi-types": "^12.0.2",
39+
"openapi-types": "^12.1.0",
4040
"yargs": "^17.6.2"
4141
},
4242
"devDependencies": {
4343
"@types/json-schema": "^7.0.11",
44-
"@typescript-eslint/eslint-plugin": "^5.42.0",
45-
"@typescript-eslint/parser": "^5.42.0",
44+
"@typescript-eslint/eslint-plugin": "^5.49.0",
45+
"@typescript-eslint/parser": "^5.49.0",
4646
"c8": "^7.12.0",
47-
"eslint": "^8.27.0",
48-
"eslint-config-prettier": "^8.5.0",
47+
"eslint": "^8.32.0",
48+
"eslint-config-prettier": "^8.6.0",
4949
"eslint-plugin-prettier": "^4.2.1",
5050
"eslint-plugin-unused-imports": "^2.0.0",
51-
"nock": "^13.2.9",
52-
"prettier": "^2.7.1",
53-
"typescript": "^4.8.4",
54-
"vitest": "^0.24.5"
51+
"nock": "^13.3.0",
52+
"prettier": "^2.8.3",
53+
"typescript": "^4.9.4",
54+
"vitest": "^0.28.1"
5555
},
5656
"prettier": {
5757
"singleQuote": true,

Diff for: src/index.ts

+31-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class InvalidTypeError extends Error {
1919

2020
const oasExtensionPrefix = 'x-';
2121

22-
const handleDefinition = async <T extends JSONSchema = JSONSchema>(
22+
const handleDefinition = async <T extends JSONSchema4 = JSONSchema4>(
2323
def: JSONSchema7Definition | JSONSchema6Definition | JSONSchema4,
2424
schema: T
2525
) => {
@@ -52,7 +52,8 @@ const handleDefinition = async <T extends JSONSchema = JSONSchema>(
5252
delete (<any>walker.rootSchema).definitions;
5353
}
5454
return walker.rootSchema;
55-
} else if (Array.isArray(def)) {
55+
}
56+
if (Array.isArray(def)) {
5657
// if it's an array, we might want to reconstruct the type;
5758
const typeArr = def;
5859
const hasNull = typeArr.includes('null');
@@ -69,7 +70,7 @@ const handleDefinition = async <T extends JSONSchema = JSONSchema>(
6970
return def;
7071
};
7172

72-
const convert = async <T extends JSONSchema = JSONSchema>(
73+
const convert = async <T extends object = JSONSchema4>(
7374
schema: T,
7475
options?: Options
7576
): Promise<OpenAPIV3.Document> => {
@@ -108,6 +109,7 @@ function convertSchema(schema: SchemaType | undefined) {
108109
schema = convertTypes(schema);
109110
schema = rewriteConst(schema);
110111
schema = convertDependencies(schema);
112+
schema = convertNullable(schema);
111113
schema = rewriteIfThenElse(schema);
112114
schema = rewriteExclusiveMinMax(schema);
113115
schema = convertExamples(schema);
@@ -196,6 +198,30 @@ function convertDependencies(schema: SchemaType) {
196198
return schema;
197199
}
198200

201+
function convertNullable(schema: SchemaType) {
202+
for (const key of ['oneOf', 'anyOf'] as const) {
203+
const schemas = schema[key] as JSONSchema4[];
204+
if (!Array.isArray(schemas)) {
205+
return schema;
206+
}
207+
208+
const hasNullable = schemas.some((item) => item.type === 'null');
209+
210+
if (!hasNullable) {
211+
return schema;
212+
}
213+
214+
const filtered = schemas.filter((l) => l.type !== 'null');
215+
for (const schemaEntry of filtered) {
216+
schemaEntry.nullable = true;
217+
}
218+
219+
schema[key] = filtered;
220+
}
221+
222+
return schema;
223+
}
224+
199225
function convertTypes(schema: SchemaType) {
200226
if (typeof schema !== 'object') {
201227
return schema;
@@ -300,11 +326,11 @@ function rewriteIfThenElse(schema: SchemaType) {
300326
function rewriteExclusiveMinMax(schema: SchemaType) {
301327
if (typeof schema.exclusiveMaximum === 'number') {
302328
schema.maximum = schema.exclusiveMaximum;
303-
schema.exclusiveMaximum = true;
329+
(schema as JSONSchema4).exclusiveMaximum = true;
304330
}
305331
if (typeof schema.exclusiveMinimum === 'number') {
306332
schema.minimum = schema.exclusiveMinimum;
307-
schema.exclusiveMinimum = true;
333+
(schema as JSONSchema4).exclusiveMinimum = true;
308334
}
309335
return schema;
310336
}

Diff for: test/default-null.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ it('supports default values of null', async ({ expect }) => {
88
nullableStringWithDefault: {
99
default: null,
1010
oneOf: [{ type: 'string' }, { type: 'null' }],
11-
}
12-
}
11+
},
12+
},
1313
};
1414

1515
const result = await convert(schema);
@@ -19,9 +19,9 @@ it('supports default values of null', async ({ expect }) => {
1919
properties: {
2020
nullableStringWithDefault: {
2121
default: null,
22-
oneOf: [{ type: 'string' }, { nullable: true }],
23-
}
24-
}
22+
oneOf: [{ type: 'string', nullable: true }],
23+
},
24+
},
2525
};
2626

2727
expect(result).toEqual(expected);

0 commit comments

Comments
 (0)