Skip to content

Commit 43bb599

Browse files
authored
Merge pull request ferdikoomen#381 from budde377/master
feat: Support x-nullable vendor extension
2 parents b79618f + 9184b2e commit 43bb599

File tree

9 files changed

+105
-12
lines changed

9 files changed

+105
-12
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,42 @@ enum EnumWithStrings {
329329
```
330330

331331

332+
### Nullable in OpenAPI v2
333+
In the OpenAPI v3 spec you can create properties that can be NULL, by providing a `nullable: true` in your schema.
334+
However, the v2 spec does not allow you to do this. You can use the unofficial `x-nullable` in your specification
335+
to generate nullable properties in OpenApi v2.
336+
337+
```json
338+
{
339+
"ModelWithNullableString": {
340+
"required": ["requiredProp"],
341+
"description": "This is a model with one string property",
342+
"type": "object",
343+
"properties": {
344+
"prop": {
345+
"description": "This is a simple string property",
346+
"type": "string",
347+
"x-nullable": true
348+
},
349+
"requiredProp": {
350+
"description": "This is a simple string property",
351+
"type": "string",
352+
"x-nullable": true
353+
}
354+
}
355+
}
356+
}
357+
```
358+
359+
Generated code:
360+
```typescript
361+
interface ModelWithNullableString {
362+
prop?: string | null,
363+
requiredProp: string | null,
364+
}
365+
```
366+
367+
332368
### Authorization
333369
The OpenAPI generator supports Bearer Token authorization. In order to enable the sending
334370
of tokens in each request you can set the token using the global OpenAPI configuration:

src/index.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import * as OpenAPI from './index';
33
describe('index', () => {
44
it('parses v2 without issues', async () => {
55
await OpenAPI.generate({
6-
input: './test/spec/v3.json',
7-
output: './generated/v3/',
6+
input: './test/spec/v2.json',
7+
output: './generated/v2/',
88
write: false,
99
});
1010
});

src/openApi/v2/interfaces/Extensions/WithEnumExtension.d.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
/**
2-
* Supported extension for enums
3-
*/
41
export interface WithEnumExtension {
52
'x-enum-varnames'?: string[];
63
'x-enum-descriptions'?: string[];
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface WithNullableExtension {
2+
'x-nullable'?: boolean;
3+
}

src/openApi/v2/interfaces/OpenApiSchema.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import type { Dictionary } from '../../../utils/types';
22
import type { WithEnumExtension } from './Extensions/WithEnumExtension';
3+
import type { WithNullableExtension } from './Extensions/WithNullableExtension';
34
import type { OpenApiExternalDocs } from './OpenApiExternalDocs';
45
import type { OpenApiReference } from './OpenApiReference';
56
import type { OpenApiXml } from './OpenApiXml';
67

78
/**
89
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject
910
*/
10-
export interface OpenApiSchema extends OpenApiReference, WithEnumExtension {
11+
export interface OpenApiSchema extends OpenApiReference, WithEnumExtension, WithNullableExtension {
1112
title?: string;
1213
description?: string;
1314
default?: any;

src/openApi/v2/parser/getModelProperties.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema,
2626
isDefinition: false,
2727
isReadOnly: property.readOnly === true,
2828
isRequired: propertyRequired === true,
29-
isNullable: false,
29+
isNullable: property['x-nullable'] === true,
3030
format: property.format,
3131
maximum: property.maximum,
3232
exclusiveMaximum: property.exclusiveMaximum,
@@ -60,7 +60,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema,
6060
isDefinition: false,
6161
isReadOnly: property.readOnly === true,
6262
isRequired: propertyRequired === true,
63-
isNullable: false,
63+
isNullable: property['x-nullable'] === true,
6464
format: property.format,
6565
maximum: property.maximum,
6666
exclusiveMaximum: property.exclusiveMaximum,
@@ -84,6 +84,5 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema,
8484
}
8585
}
8686
}
87-
8887
return models;
8988
}

src/openApi/v3/interfaces/Extensions/WithEnumExtension.d.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
/**
2-
* Supported extension for enums
3-
*/
41
export interface WithEnumExtension {
52
'x-enum-varnames'?: string[];
63
'x-enum-descriptions'?: string[];

test/__snapshots__/index.spec.js.snap

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ export type { ModelWithInteger } from './models/ModelWithInteger';
301301
export type { ModelWithLink } from './models/ModelWithLink';
302302
export type { ModelWithNestedEnums } from './models/ModelWithNestedEnums';
303303
export type { ModelWithNestedProperties } from './models/ModelWithNestedProperties';
304+
export type { ModelWithNullableString } from './models/ModelWithNullableString';
304305
export type { ModelWithOrderedProperties } from './models/ModelWithOrderedProperties';
305306
export type { ModelWithPattern } from './models/ModelWithPattern';
306307
export type { ModelWithProperties } from './models/ModelWithProperties';
@@ -343,6 +344,7 @@ export { $ModelWithInteger } from './schemas/$ModelWithInteger';
343344
export { $ModelWithLink } from './schemas/$ModelWithLink';
344345
export { $ModelWithNestedEnums } from './schemas/$ModelWithNestedEnums';
345346
export { $ModelWithNestedProperties } from './schemas/$ModelWithNestedProperties';
347+
export { $ModelWithNullableString } from './schemas/$ModelWithNullableString';
346348
export { $ModelWithOrderedProperties } from './schemas/$ModelWithOrderedProperties';
347349
export { $ModelWithPattern } from './schemas/$ModelWithPattern';
348350
export { $ModelWithProperties } from './schemas/$ModelWithProperties';
@@ -833,6 +835,26 @@ export interface ModelWithNestedProperties {
833835
"
834836
`;
835837

838+
exports[`v2 should generate: ./test/generated/v2/models/ModelWithNullableString.ts 1`] = `
839+
"/* istanbul ignore file */
840+
/* tslint:disable */
841+
/* eslint-disable */
842+
/**
843+
* This is a model with one string property
844+
*/
845+
export interface ModelWithNullableString {
846+
/**
847+
* This is a simple string property
848+
*/
849+
nullableProp?: string | null;
850+
/**
851+
* This is a simple string property
852+
*/
853+
nullableRequiredProp: string | null;
854+
}
855+
"
856+
`;
857+
836858
exports[`v2 should generate: ./test/generated/v2/models/ModelWithOrderedProperties.ts 1`] = `
837859
"/* istanbul ignore file */
838860
/* tslint:disable */
@@ -1362,6 +1384,25 @@ export const $ModelWithNestedProperties = {
13621384
};"
13631385
`;
13641386

1387+
exports[`v2 should generate: ./test/generated/v2/schemas/$ModelWithNullableString.ts 1`] = `
1388+
"/* istanbul ignore file */
1389+
/* tslint:disable */
1390+
/* eslint-disable */
1391+
export const $ModelWithNullableString = {
1392+
properties: {
1393+
nullableProp: {
1394+
type: 'string',
1395+
isNullable: true,
1396+
},
1397+
nullableRequiredProp: {
1398+
type: 'string',
1399+
isRequired: true,
1400+
isNullable: true,
1401+
},
1402+
},
1403+
};"
1404+
`;
1405+
13651406
exports[`v2 should generate: ./test/generated/v2/schemas/$ModelWithOrderedProperties.ts 1`] = `
13661407
"/* istanbul ignore file */
13671408
/* tslint:disable */

test/spec/v2.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,25 @@
858858
}
859859
}
860860
},
861+
"ModelWithNullableString": {
862+
"description": "This is a model with one string property",
863+
"type": "object",
864+
"required": [
865+
"nullableRequiredProp"
866+
],
867+
"properties": {
868+
"nullableProp": {
869+
"description": "This is a simple string property",
870+
"type": "string",
871+
"x-nullable": true
872+
},
873+
"nullableRequiredProp": {
874+
"description": "This is a simple string property",
875+
"type": "string",
876+
"x-nullable": true
877+
}
878+
}
879+
},
861880
"ModelWithEnum": {
862881
"description": "This is a model with one enum",
863882
"type": "object",

0 commit comments

Comments
 (0)