From 547731cea6005a5c0b785c8b8791c186acf2b5e6 Mon Sep 17 00:00:00 2001 From: Eric Butler Date: Tue, 23 Jan 2024 16:54:24 -0500 Subject: [PATCH] feat: support for prefixItems --- packages/core/src/getters/array.ts | 45 +++++++++++++++++++++----- tests/configs/default.config.ts | 8 +++++ tests/specifications/example-v3-1.yaml | 30 +++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 tests/specifications/example-v3-1.yaml diff --git a/packages/core/src/getters/array.ts b/packages/core/src/getters/array.ts index e7d576d2f..582f734ed 100644 --- a/packages/core/src/getters/array.ts +++ b/packages/core/src/getters/array.ts @@ -1,4 +1,4 @@ -import { SchemaObject } from 'openapi3-ts/oas30'; +import { ReferenceObject, SchemaObject } from 'openapi3-ts/oas30'; import { SchemaObject as SchemaObject31 } from 'openapi3-ts/oas31'; import { ContextSpecs, ScalarValue } from '../types'; import { resolveObject } from '../resolvers/object'; @@ -18,14 +18,43 @@ export const getArray = ({ name?: string; context: ContextSpecs; }): ScalarValue => { - if (schema.items) { - const schema31 = schema as SchemaObject31; - if (schema31.prefixItems) { - // TODO: https://github.com/anymaniax/orval/issues/890 - throw new Error( - `prefixItems is not supported (name=${name}, schema=${JSON.stringify(schema)})`, - ); + const schema31 = schema as SchemaObject31; + if (schema31.prefixItems) { + const resolvedObjects = schema31.prefixItems.map((item, index) => + resolveObject({ + schema: item as SchemaObject | ReferenceObject, + propName: + name + context.output.override.components.schemas.itemSuffix + index, + context, + }), + ); + if (schema31.items) { + const additional = resolveObject({ + schema: schema31.items as SchemaObject | ReferenceObject, + propName: + name + + context.output.override.components.schemas.itemSuffix + + 'Additional', + context, + }); + resolvedObjects.push({ + ...additional, + value: `...${additional.value}[]`, + }); } + return { + type: 'array', + isEnum: false, + isRef: false, + value: `[${resolvedObjects.map((o) => o.value).join(', ')}]`, + imports: resolvedObjects.flatMap((o) => o.imports), + schemas: resolvedObjects.flatMap((o) => o.schemas), + hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps), + example: schema.example, + examples: resolveExampleRefs(schema.examples, context), + }; + } + if (schema.items) { const resolvedObject = resolveObject({ schema: schema.items, propName: name + context.output.override.components.schemas.itemSuffix, diff --git a/tests/configs/default.config.ts b/tests/configs/default.config.ts index ebc1ad665..a30fb5402 100644 --- a/tests/configs/default.config.ts +++ b/tests/configs/default.config.ts @@ -94,4 +94,12 @@ export default defineConfig({ target: '../generated/default/deeply-nested-refs/endpoints.ts', }, }, + 'example-v3-1': { + input: '../specifications/example-v3-1.yaml', + output: { + mock: true, + schemas: '../generated/default/example-v3-1/model', + target: '../generated/default/example-v3-1/endpoints.ts', + }, + }, }); diff --git a/tests/specifications/example-v3-1.yaml b/tests/specifications/example-v3-1.yaml new file mode 100644 index 000000000..dabe1ddf6 --- /dev/null +++ b/tests/specifications/example-v3-1.yaml @@ -0,0 +1,30 @@ +openapi: 3.1.0 +info: + title: Nullables + description: 'OpenAPI 3.1 examples' + version: 1.0.0 +paths: {} +components: + schemas: + Test: + properties: + example_tuple: + maxItems: 2 + minItems: 2 + prefixItems: + - type: string + - {} + type: array + title: Example tuple + example_tuple_additional: + maxItems: 2 + minItems: 2 + prefixItems: + - type: string + - {} + items: + type: string + type: array + title: Example tuple + title: Test + type: object