Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions packages/openapi-generator/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,17 @@ function schemaToOpenAPI(
// If there are two schemas and one of the schemas is undefined, that means the union is a case of `optional` type
const undefinedSchema = schema.schemas.find((s) => s.type === 'undefined');
const nonUndefinedSchema = schema.schemas.find((s) => s.type !== 'undefined');
// If nullSchema exists, that means that the union is also nullable
const nullSchema = schema.schemas.find((s) => s.type === 'null');
// and we can just return the other schema (while attaching the comment to that schema)
const isOptional =
schema.schemas.length == 2 && undefinedSchema && nonUndefinedSchema;
schema.schemas.length >= 2 && undefinedSchema && nonUndefinedSchema;
if (isOptional) {
return schemaToOpenAPI({ ...nonUndefinedSchema, comment: schema.comment });
return schemaToOpenAPI({
...nonUndefinedSchema,
comment: schema.comment,
...(nullSchema ? { nullable: true } : {}),
});
}

for (const s of schema.schemas) {
Expand Down
90 changes: 90 additions & 0 deletions packages/openapi-generator/test/openapi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2736,3 +2736,93 @@ testCase('route with optional array query parameter and documentation', ROUTE_WI
schemas: {}
}
});


const ROUTE_WITH_ARRAY_UNION_NULL_UNDEFINED_QUERY_PARAM = `
import * as t from 'io-ts';
import * as h from '@api-ts/io-ts-http';

/**
* A simple route with type descriptions for references
*
* @operationId api.v1.test
* @tag Test Routes
*/
export const route = h.httpRoute({
path: '/foo',
method: 'GET',
request: h.httpRequest({
query: {
/**
* This is a foo description.
* @example abc
* @pattern ^[a-z]+$
*/
ipRestrict: t.union([t.array(t.string), t.null, t.undefined]),
},
}),
response: {
200: {
test: t.string
}
},
});
`;

testCase('route with array union of null and undefined', ROUTE_WITH_ARRAY_UNION_NULL_UNDEFINED_QUERY_PARAM, {
openapi: '3.0.3',
info: {
title: 'Test',
version: '1.0.0'
},
paths: {
'/foo': {
get: {
summary: 'A simple route with type descriptions for references',
operationId: 'api.v1.test',
tags: [
'Test Routes'
],
parameters: [
{
description: 'This is a foo description.',
in: 'query',
name: 'ipRestrict',
schema: {
items: {
description: 'This is a foo description.',
example: 'abc',
type: 'string',
pattern: '^[a-z]+$'
},
type: 'array'
}
}
],
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
test: {
type: 'string'
}
},
required: [
'test'
]
}
}
}
}
}
}
}
},
components: {
schemas: {}
}
});