Skip to content

Commit 56b0b09

Browse files
fix(openapi-generator): wrap nullable $ref parameters in an 'allOf' array
OpenAPI spec doesn't allow $ref properties to have siblings, so they're wrapped in an 'allOf' array
1 parent ce392a6 commit 56b0b09

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

packages/openapi-generator/src/openapi.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,14 @@ function schemaToOpenAPI(
7575
if (oneOf.length === 0) {
7676
return undefined;
7777
} else if (oneOf.length === 1) {
78-
return { ...(nullable ? { nullable } : {}), ...oneOf[0] };
78+
if (
79+
Object.keys(
80+
oneOf[0] as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
81+
)[0] === '$ref'
82+
)
83+
// OpenAPI spec doesn't allow $ref properties to have siblings, so they're wrapped in an 'allOf' array
84+
return { ...(nullable ? { nullable } : {}), allOf: oneOf };
85+
else return { ...(nullable ? { nullable } : {}), ...oneOf[0] };
7986
} else {
8087
return { ...(nullable ? { nullable } : {}), oneOf };
8188
}

packages/openapi-generator/test/openapi.test.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,80 @@ testCase('request body double ref', SCHEMA_DOUBLE_REF, {
735735
},
736736
});
737737

738+
const SCHEMA_NULLABLE_REF = `
739+
import * as t from 'io-ts';
740+
import * as h from '@api-ts/io-ts-http';
741+
742+
export const route = h.httpRoute({
743+
path: '/foo',
744+
method: 'GET',
745+
request: t.type({
746+
body: t.union([Foo, t.null]),
747+
}),
748+
response: {
749+
/** foo response */
750+
200: t.string
751+
},
752+
});
753+
754+
const Foo = t.type({ foo: t.string });
755+
`;
756+
757+
testCase('request body nullable ref', SCHEMA_NULLABLE_REF, {
758+
openapi: '3.0.3',
759+
info: {
760+
title: 'Test',
761+
version: '1.0.0',
762+
},
763+
paths: {
764+
'/foo': {
765+
get: {
766+
parameters: [],
767+
requestBody: {
768+
content: {
769+
'application/json': {
770+
schema: {
771+
nullable: true,
772+
allOf: [
773+
{
774+
$ref: '#/components/schemas/Foo',
775+
},
776+
],
777+
},
778+
},
779+
},
780+
},
781+
responses: {
782+
200: {
783+
description: 'foo response',
784+
content: {
785+
'application/json': {
786+
schema: {
787+
type: 'string',
788+
},
789+
},
790+
},
791+
},
792+
},
793+
},
794+
},
795+
},
796+
components: {
797+
schemas: {
798+
Foo: {
799+
title: 'Foo',
800+
type: 'object',
801+
properties: {
802+
foo: {
803+
type: 'string',
804+
},
805+
},
806+
required: ['foo'],
807+
},
808+
},
809+
},
810+
});
811+
738812
const TITLE_TAG = `
739813
import * as t from 'io-ts';
740814
import * as h from '@api-ts/io-ts-http';

0 commit comments

Comments
 (0)