From 661a6ada377429b0663e2d463cef91c0dd569dee Mon Sep 17 00:00:00 2001 From: Alfred Jonsson Date: Fri, 29 Mar 2024 14:35:40 +0100 Subject: [PATCH] fix: request bodies should take required property into account (#1277) * fix: request bodies should be optional by default * fix: request body is required by default --------- Co-authored-by: Alfred Jonsson --- packages/core/src/getters/body.ts | 16 ++++- packages/core/src/getters/props.ts | 6 +- packages/core/src/types.ts | 1 + tests/configs/swr.config.ts | 11 ++++ .../specifications/optional-request-body.yaml | 60 +++++++++++++++++++ 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 tests/specifications/optional-request-body.yaml diff --git a/packages/core/src/getters/body.ts b/packages/core/src/getters/body.ts index 5a199f754..844ce53ba 100644 --- a/packages/core/src/getters/body.ts +++ b/packages/core/src/getters/body.ts @@ -1,7 +1,8 @@ import { ReferenceObject, RequestBodyObject } from 'openapi3-ts/oas30'; import { generalJSTypesWithArray } from '../constants'; +import { resolveRef } from '../resolvers'; import { ContextSpecs, GetterBody, OverrideOutputContentType } from '../types'; -import { camel, sanitize } from '../utils'; +import { camel, isReference, sanitize } from '../utils'; import { getResReqTypes } from './res-req-types'; export const getBody = ({ @@ -53,6 +54,7 @@ export const getBody = ({ context.output.override.components.requestBodies.suffix : camel(definition); + let isOptional = false; if (implementation) { implementation = sanitize(implementation, { underscore: '_', @@ -61,6 +63,17 @@ export const getBody = ({ es5keyword: true, es5IdentifierName: true, }); + if (isReference(requestBody)) { + const { schema: bodySchema } = resolveRef( + requestBody, + context, + ); + if (bodySchema.required !== undefined) { + isOptional = !bodySchema.required; + } + } else if (requestBody.required !== undefined) { + isOptional = !requestBody.required; + } } return { @@ -69,6 +82,7 @@ export const getBody = ({ implementation, imports, schemas, + isOptional, ...(filteredBodyTypes.length === 1 ? { formData: filteredBodyTypes[0].formData, diff --git a/packages/core/src/getters/props.ts b/packages/core/src/getters/props.ts index 8ab382c94..6060952e1 100644 --- a/packages/core/src/getters/props.ts +++ b/packages/core/src/getters/props.ts @@ -25,10 +25,10 @@ export const getProps = ({ }): GetterProps => { const bodyProp = { name: body.implementation, - definition: `${body.implementation}: ${body.definition}`, - implementation: `${body.implementation}: ${body.definition}`, + definition: `${body.implementation}${body.isOptional ? '?' : ''}: ${body.definition}`, + implementation: `${body.implementation}${body.isOptional ? '?' : ''}: ${body.definition}`, default: false, - required: true, + required: !body.isOptional, type: GetterPropType.BODY, }; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 8fbb35605..e4e087018 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -749,6 +749,7 @@ export type GetterBody = { formData?: string; formUrlEncoded?: string; contentType: string; + isOptional: boolean; }; export type GetterParameters = { diff --git a/tests/configs/swr.config.ts b/tests/configs/swr.config.ts index 20de0fa69..1f667a563 100644 --- a/tests/configs/swr.config.ts +++ b/tests/configs/swr.config.ts @@ -178,4 +178,15 @@ export default defineConfig({ target: '../specifications/errors.yaml', }, }, + optionalRequestBody: { + output: { + target: '../generated/swr/optional-request-body/endpoints.ts', + schemas: '../generated/swr/optional-request-body/model', + client: 'swr', + mock: true, + }, + input: { + target: '../specifications/optional-request-body.yaml', + }, + }, }); diff --git a/tests/specifications/optional-request-body.yaml b/tests/specifications/optional-request-body.yaml new file mode 100644 index 000000000..1becd3c97 --- /dev/null +++ b/tests/specifications/optional-request-body.yaml @@ -0,0 +1,60 @@ +openapi: '3.0.0' +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + post: + operationId: createPets + requestBody: + $ref: '#/components/requestBodies/RequiredPetBody' + responses: + '204': + description: Ok + put: + operationId: updatePets + requestBody: + $ref: '#/components/requestBodies/OptionalPetBody' + responses: + '204': + description: Ok + /cookies: + post: + operationId: createCookies + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Cookie' + responses: + '204': + description: Ok + put: + operationId: updateCookies + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/Cookie' + responses: + '204': + description: Ok +components: + requestBodies: + OptionalPetBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + RequiredPetBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + schemas: + Pet: + type: object + Cookie: + type: object