diff --git a/.changeset/big-trees-hide.md b/.changeset/big-trees-hide.md new file mode 100644 index 00000000..aef5d436 --- /dev/null +++ b/.changeset/big-trees-hide.md @@ -0,0 +1,5 @@ +--- +'@hey-api/openapi-ts': patch +--- + +fix: correctly generate array when items are a oneOf array with length 1 diff --git a/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts b/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts index 5049d481..0fb81cbc 100644 --- a/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts +++ b/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts @@ -81,10 +81,9 @@ const parseArray = ({ if ('$ref' in schema.items) { schemaItems.push(irItemsSchema); } else { - const isComposedSchema = Boolean( - schema.items.allOf || schema.items.anyOf || schema.items.oneOf, - ); - if (isComposedSchema) { + const ofArray = + schema.items.allOf || schema.items.anyOf || schema.items.oneOf; + if (ofArray && ofArray.length > 1 && !schema.items.nullable) { // bring composition up to avoid incorrectly nested arrays irSchema = { ...irSchema, diff --git a/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts b/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts index cdc12491..d42a2bf6 100644 --- a/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts +++ b/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts @@ -120,10 +120,13 @@ const parseArray = ({ ) { schemaItems = Array(schema.maxItems).fill(irItemsSchema); } else { - const isComposedSchema = Boolean( - schema.items.allOf || schema.items.anyOf || schema.items.oneOf, - ); - if (isComposedSchema) { + const ofArray = + schema.items.allOf || schema.items.anyOf || schema.items.oneOf; + if ( + ofArray && + ofArray.length > 1 && + !getSchemaTypes({ schema: schema.items }).includes('null') + ) { // bring composition up to avoid incorrectly nested arrays irSchema = { ...irSchema, diff --git a/packages/openapi-ts/test/3.0.x.spec.ts b/packages/openapi-ts/test/3.0.x.spec.ts index 418a7766..6d758378 100644 --- a/packages/openapi-ts/test/3.0.x.spec.ts +++ b/packages/openapi-ts/test/3.0.x.spec.ts @@ -48,6 +48,14 @@ describe(`OpenAPI ${VERSION}`, () => { }), description: 'allows arbitrary properties on objects', }, + { + config: createConfig({ + input: 'array-items-one-of-length-1.json', + output: 'array-items-one-of-length-1', + }), + description: + 'generates correct array when items are oneOf array with single item', + }, { config: createConfig({ input: 'enum-escape.json', diff --git a/packages/openapi-ts/test/3.1.x.spec.ts b/packages/openapi-ts/test/3.1.x.spec.ts index 0665abd4..ab11ad5f 100644 --- a/packages/openapi-ts/test/3.1.x.spec.ts +++ b/packages/openapi-ts/test/3.1.x.spec.ts @@ -48,6 +48,14 @@ describe(`OpenAPI ${VERSION}`, () => { }), description: 'allows arbitrary properties on objects', }, + { + config: createConfig({ + input: 'array-items-one-of-length-1.json', + output: 'array-items-one-of-length-1', + }), + description: + 'generates correct array when items are oneOf array with single item', + }, { config: createConfig({ input: 'duplicate-null.json', diff --git a/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/index.ts b/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/index.ts new file mode 100644 index 00000000..56bade12 --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/index.ts @@ -0,0 +1,2 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './types.gen'; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/types.gen.ts b/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/types.gen.ts new file mode 100644 index 00000000..d17a3c92 --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.0.x/array-items-one-of-length-1/types.gen.ts @@ -0,0 +1,7 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type Foo = { + foo?: Array; +}; + +export type Bar = string; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/index.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/index.ts new file mode 100644 index 00000000..56bade12 --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/index.ts @@ -0,0 +1,2 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './types.gen'; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/types.gen.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/types.gen.ts new file mode 100644 index 00000000..d17a3c92 --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/array-items-one-of-length-1/types.gen.ts @@ -0,0 +1,7 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type Foo = { + foo?: Array; +}; + +export type Bar = string; \ No newline at end of file diff --git a/packages/openapi-ts/test/sample.cjs b/packages/openapi-ts/test/sample.cjs index 0db06fb5..2b69ea7e 100644 --- a/packages/openapi-ts/test/sample.cjs +++ b/packages/openapi-ts/test/sample.cjs @@ -13,7 +13,7 @@ const main = async () => { input: { // include: // '^(#/components/schemas/import|#/paths/api/v{api-version}/simple/options)$', - path: './test/spec/3.0.x/parameter-explode-false.json', + path: './test/spec/3.1.x/array-items-one-of-length-1.json', // path: 'https://mongodb-mms-prod-build-server.s3.amazonaws.com/openapi/2caffd88277a4e27c95dcefc7e3b6a63a3b03297-v2-2023-11-15.json', }, // name: 'foo', @@ -30,7 +30,7 @@ const main = async () => { { // asClass: true, // include... - name: '@hey-api/services', + // name: '@hey-api/services', // serviceNameBuilder: '^Parameters', }, { diff --git a/packages/openapi-ts/test/spec/3.0.x/array-items-one-of-length-1.json b/packages/openapi-ts/test/spec/3.0.x/array-items-one-of-length-1.json new file mode 100644 index 00000000..d0613678 --- /dev/null +++ b/packages/openapi-ts/test/spec/3.0.x/array-items-one-of-length-1.json @@ -0,0 +1,31 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "OpenAPI 3.0.2 array items oneOf length 1 example", + "version": "1" + }, + "components": { + "schemas": { + "Foo": { + "type": "object", + "properties": { + "foo": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/Bar" + } + ] + }, + "maxItems": 2147483647, + "minItems": 1 + } + } + }, + "Bar": { + "type": "string" + } + } + } +} diff --git a/packages/openapi-ts/test/spec/3.1.x/array-items-one-of-length-1.json b/packages/openapi-ts/test/spec/3.1.x/array-items-one-of-length-1.json new file mode 100644 index 00000000..78a852bc --- /dev/null +++ b/packages/openapi-ts/test/spec/3.1.x/array-items-one-of-length-1.json @@ -0,0 +1,31 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI 3.1.0 array items oneOf length 1 example", + "version": "1" + }, + "components": { + "schemas": { + "Foo": { + "type": "object", + "properties": { + "foo": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/Bar" + } + ] + }, + "maxItems": 2147483647, + "minItems": 1 + } + } + }, + "Bar": { + "type": "string" + } + } + } +}