Skip to content

Commit fd0ff0a

Browse files
deekshas8cloud-sdk-js
andauthored
chore: Add nullable option for schema properties and persisted Schema (#4996)
* add nullable * Changes from lint:fix * adjust condition * Changes from lint:fix --------- Co-authored-by: cloud-sdk-js <cloud-sdk-js@github.com>
1 parent de75aca commit fd0ff0a

File tree

11 files changed

+119
-7
lines changed

11 files changed

+119
-7
lines changed

packages/openapi-generator/src/file-serializer/__snapshots__/schema-file.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ exports[`schemaFile serializes schema file for schema 1`] = `
2323
* Max Length: 10.
2424
*/
2525
'string-property': string;
26-
};"
26+
} | null;"
2727
`;
2828

2929
exports[`schemaFile serializes schema file for schema including ESM references 1`] = `

packages/openapi-generator/src/file-serializer/schema-file.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import { schemaPropertyDocumentation } from './schema';
1212
const schema = {
1313
schemaName: 'MySchema',
1414
fileName: 'my-schema',
15+
nullable: true,
1516
schema: {
1617
properties: [
1718
{
1819
name: 'string-property',
1920
required: true,
21+
nullable: false,
2022
schema: {
2123
type: 'string'
2224
},
@@ -35,11 +37,13 @@ const schemaWithReferences = {
3537
schemaName: 'MySchema',
3638
fileName: 'my-schema',
3739
schemaProperties: {},
40+
nullable: false,
3841
schema: {
3942
properties: [
4043
{
4144
name: 'otherSchema1',
4245
required: true,
46+
nullable: false,
4347
schema: {
4448
$ref: '#/components/schema/OtherSchema1',
4549
schemaName: 'OtherSchema1',
@@ -51,6 +55,7 @@ const schemaWithReferences = {
5155
name: 'otherSchema2',
5256
description: 'Description other Schema 2',
5357
required: true,
58+
nullable: false,
5459
schema: {
5560
$ref: '#/components/schema/OtherSchema2',
5661
schemaName: 'OtherSchema2',
@@ -65,6 +70,7 @@ const schemaWithReferences = {
6570
const schemaWithNotSchema = {
6671
schemaName: 'MySchema',
6772
fileName: 'my-schema',
73+
nullable: false,
6874
schema: {
6975
items: { not: { type: 'integer' } }
7076
},
@@ -74,11 +80,13 @@ const schemaWithNotSchema = {
7480
const schemaWithoutImportsIncludingOnlySelfReference = {
7581
schemaName: 'MySchema',
7682
fileName: 'my-schema',
83+
nullable: false,
7784
schema: {
7885
properties: [
7986
{
8087
name: 'property',
8188
required: false,
89+
nullable: false,
8290
schema: {
8391
$ref: '#/components/schema/MySchema',
8492
schemaName: 'MySchema',
@@ -94,12 +102,14 @@ const schemaWithoutImportsIncludingOnlySelfReference = {
94102
const schemaWithDescription = {
95103
schemaName: 'MySchema',
96104
fileName: 'my-schema',
105+
nullable: false,
97106
schema: {
98107
properties: [
99108
{
100109
name: 'string-property',
101110
description: 'My description',
102111
required: true,
112+
nullable: false,
103113
schema: {
104114
type: 'string'
105115
},
@@ -110,6 +120,7 @@ const schemaWithDescription = {
110120
{
111121
name: 'string-property-no-description',
112122
required: true,
123+
nullable: false,
113124
schema: {
114125
type: 'string'
115126
},

packages/openapi-generator/src/file-serializer/schema-file.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function schemaFile(
2525
${schemaDocumentation(namedSchema)}
2626
export type ${namedSchema.schemaName} = ${serializeSchema(
2727
namedSchema.schema
28-
)};
28+
)}${namedSchema.nullable ? ' | null' : ''};
2929
`;
3030
}
3131

packages/openapi-generator/src/file-serializer/schema.spec.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe('serializeSchema for object schemas', () => {
1818
{
1919
name: 'simpleProperty',
2020
required: true,
21+
nullable: true,
2122
schema: { type: 'integer' },
2223
schemaProperties: {
2324
minimum: 8
@@ -27,11 +28,13 @@ describe('serializeSchema for object schemas', () => {
2728
{
2829
name: 'nested-property',
2930
required: false,
31+
nullable: false,
3032
schema: {
3133
properties: [
3234
{
3335
name: 'stringProperty',
3436
required: false,
37+
nullable: false,
3538
schema: { type: 'string' },
3639
schemaProperties: {
3740
pattern: '^[p{L}-.^_|~d]+$'
@@ -49,7 +52,7 @@ describe('serializeSchema for object schemas', () => {
4952
/**
5053
* Minimum: 8.
5154
*/
52-
'simpleProperty': number;
55+
'simpleProperty': number | null;
5356
'nested-property'?: {
5457
/**
5558
* Pattern: "^[p{L}-.^_|~d]+$".
@@ -93,6 +96,7 @@ describe('serializeSchema for object schemas', () => {
9396
{
9497
name: 'simpleProperty',
9598
required: true,
99+
nullable: false,
96100
schema: { type: 'integer' },
97101
schemaProperties: {}
98102
}
@@ -112,6 +116,7 @@ describe('serializeSchema for object schemas', () => {
112116
properties: [
113117
{
114118
name: 'objectArrayProp',
119+
nullable: false,
115120
required: true,
116121
schema: {
117122
uniqueItems: false,
@@ -120,6 +125,7 @@ describe('serializeSchema for object schemas', () => {
120125
{
121126
name: 'name',
122127
required: true,
128+
nullable: false,
123129
schema: { type: 'string' },
124130
schemaProperties: {}
125131
}

packages/openapi-generator/src/file-serializer/schema.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,13 @@ function serializeObjectSchemaForProperties(
9696
}`;
9797
}
9898

99-
function serializeProperty(name: string, required: boolean, type: string) {
100-
return `'${name}'${required ? '' : '?'}: ${type};`;
99+
function serializeProperty(
100+
name: string,
101+
required: boolean,
102+
nullable: boolean,
103+
type: string
104+
) {
105+
return `'${name}'${required ? '' : '?'}: ${type}${nullable ? ' | null' : ''};`;
101106
}
102107

103108
function serializePropertyWithDocumentation(
@@ -107,6 +112,7 @@ function serializePropertyWithDocumentation(
107112
const serialized = serializeProperty(
108113
property.name,
109114
property.required,
115+
property.nullable,
110116
serializeSchema(property.schema)
111117
);
112118
if (documentation) {

packages/openapi-generator/src/openapi-types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ export interface OpenApiPersistedSchema extends SchemaNaming {
218218
* Denotes the schema properties.
219219
*/
220220
schemaProperties: OpenApiSchemaProperties;
221+
222+
/**
223+
* Denotes whether the schema is nullable.
224+
*/
225+
nullable: boolean;
221226
}
222227

223228
/**
@@ -337,6 +342,10 @@ export interface OpenApiObjectSchemaProperty extends OpenApiNamedSchema {
337342
* Denotes whether the parameter is required for the according object.
338343
*/
339344
required: boolean;
345+
/**
346+
* Denotes whether the parameter is nullable.
347+
*/
348+
nullable: boolean;
340349
}
341350

342351
/**

packages/openapi-generator/src/parser/document.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ describe('parseOpenApiDocument', () => {
9494
description: 'Schema Description',
9595
schemaName: 'SimpleSchema',
9696
fileName: 'simple-schema',
97+
nullable: false,
9798
schema: {
9899
type: 'string'
99100
},
@@ -102,6 +103,58 @@ describe('parseOpenApiDocument', () => {
102103
]);
103104
});
104105

106+
it('parses simple object persisted schema with nullable', async () => {
107+
const components: OpenAPIV3.ComponentsObject = {
108+
schemas: {
109+
SimpleSchema: {
110+
description: 'Schema Description',
111+
type: 'object',
112+
nullable: true,
113+
properties: {
114+
prop1: { type: 'string' }
115+
}
116+
}
117+
}
118+
};
119+
120+
const document: OpenAPIV3.Document = getDocument(
121+
getResponse('SimpleSchema'),
122+
components
123+
);
124+
125+
const parsed = await parseOpenApiDocument(
126+
document,
127+
{ directoryName: 'myService' } as ServiceOptions,
128+
options
129+
);
130+
expect(parsed.schemas).toStrictEqual([
131+
{
132+
description: 'Schema Description',
133+
schemaName: 'SimpleSchema',
134+
fileName: 'simple-schema',
135+
schema: {
136+
additionalProperties: {
137+
type: 'any'
138+
},
139+
properties: [
140+
{
141+
description: undefined,
142+
name: 'prop1',
143+
nullable: false,
144+
required: false,
145+
schema: {
146+
type: 'string'
147+
},
148+
schemaProperties: {}
149+
}
150+
]
151+
},
152+
nullable: true,
153+
schemaProperties: {}
154+
}
155+
]);
156+
});
157+
105158
it("escapes 'index' as file name, but not as schema name", async () => {
106159
const input: OpenAPIV3.Document = {
107160
...emptyDocument,

packages/openapi-generator/src/parser/document.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export function parseSchemas(
4646
...refs.getSchemaNaming(`#/components/schemas/${name}`),
4747
schema: parseSchema(schema, refs, options),
4848
description: refs.resolveObject(schema).description,
49-
schemaProperties: parseSchemaProperties(schema)
49+
schemaProperties: parseSchemaProperties(schema),
50+
nullable: 'nullable' in schema && schema.nullable ? true : false
5051
})
5152
);
5253
}

packages/openapi-generator/src/parser/schema.spec.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ describe('parseSchema', () => {
4545
).toBe('My Description');
4646
});
4747

48+
it('parses simple schema with nullable property', async () => {
49+
const schema: OpenAPIV3.SchemaObject = {
50+
type: 'object',
51+
properties: {
52+
prop1: { description: 'My Description', type: 'string', nullable: true }
53+
}
54+
};
55+
expect(
56+
(
57+
parseSchema(
58+
schema,
59+
await createTestRefs(),
60+
defaultOptions
61+
) as OpenApiObjectSchema
62+
).properties[0].nullable
63+
).toBe(true);
64+
});
65+
4866
it('parses array schema', async () => {
4967
const schema: OpenAPIV3.SchemaObject = {
5068
type: 'array',
@@ -107,6 +125,7 @@ describe('parseSchema', () => {
107125
name: 'simpleProperty',
108126
description: undefined,
109127
required: true,
128+
nullable: false,
110129
schema: {
111130
type: 'string'
112131
},
@@ -116,6 +135,7 @@ describe('parseSchema', () => {
116135
name: 'nestedObjectProperty',
117136
required: false,
118137
description: undefined,
138+
nullable: false,
119139
schema: {
120140
additionalProperties: {
121141
additionalProperties: { type: 'any' },
@@ -124,6 +144,7 @@ describe('parseSchema', () => {
124144
name: 'simpleProperty',
125145
description: undefined,
126146
required: false,
147+
nullable: false,
127148
schema: {
128149
type: 'string'
129150
},
@@ -150,7 +171,8 @@ describe('parseSchema', () => {
150171
deprecated: true,
151172
example: 'test',
152173
maxLength: 10,
153-
default: 'testString'
174+
default: 'testString',
175+
nullable: false
154176
}
155177
}
156178
};
@@ -161,6 +183,7 @@ describe('parseSchema', () => {
161183
name: 'simpleProperty',
162184
description: undefined,
163185
required: true,
186+
nullable: false,
164187
schema: {
165188
type: 'string'
166189
},

packages/openapi-generator/src/parser/schema.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ function parseObjectSchemaProperties(
161161
description: isReferenceObject(propSchema)
162162
? undefined
163163
: propSchema.description,
164+
nullable:
165+
(!isReferenceObject(propSchema) && propSchema.nullable) ?? false,
164166
name: propName,
165167
required: schema.required?.includes(propName) || false,
166168
schemaProperties: { ...parseSchemaProperties(propSchema) }

0 commit comments

Comments
 (0)