diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts index db004bbcd896..8a953bc4540f 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts @@ -102,12 +102,6 @@ describe('computeSchemaComponents', () => { type: 'string', enum: ['OPTION_1', 'OPTION_2'], }, - fieldRelation: { - type: 'array', - items: { - $ref: '#/components/schemas/ToObjectMetadataName', - }, - }, fieldPosition: { type: 'number', }, @@ -145,16 +139,28 @@ describe('computeSchemaComponents', () => { }, }, }, - ObjectsName: { - description: 'A list of objectsName', + 'ObjectName with Relations': { + allOf: [ + { + $ref: '#/components/schemas/ObjectName', + }, + { + properties: { + fieldRelation: { + type: 'array', + items: { + $ref: '#/components/schemas/ToObjectMetadataName', + }, + }, + }, + type: 'object', + }, + ], + description: undefined, example: { fieldNumber: '', }, - items: { - $ref: '#/components/schemas/ObjectName', - }, required: ['fieldNumber'], - type: 'array', }, }); }); diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts index eb5bf7cbb28a..37ebb6d13668 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts @@ -51,6 +51,10 @@ const getSchemaComponentsProperties = ( item: ObjectMetadataEntity, ): Properties => { return item.fields.reduce((node, field) => { + if (field.type == FieldMetadataType.RELATION) { + return node; + } + let itemProperty = {} as Property; switch (field.type) { @@ -61,18 +65,6 @@ const getSchemaComponentsProperties = ( enum: field.options.map((option: { value: string }) => option.value), }; break; - case FieldMetadataType.RELATION: - if (field.fromRelationMetadata?.toObjectMetadata.nameSingular) { - itemProperty = { - type: 'array', - items: { - $ref: `#/components/schemas/${capitalize( - field.fromRelationMetadata?.toObjectMetadata.nameSingular || '', - )}`, - }, - }; - } - break; case FieldMetadataType.LINK: case FieldMetadataType.LINKS: case FieldMetadataType.CURRENCY: @@ -106,6 +98,37 @@ const getSchemaComponentsProperties = ( }, {} as Properties); }; +const getSchemaComponentsRelationProperties = ( + item: ObjectMetadataEntity, +): Properties => { + return item.fields.reduce((node, field) => { + let itemProperty = {} as Property; + + if (field.type == FieldMetadataType.RELATION) { + if (field.fromRelationMetadata?.toObjectMetadata.nameSingular) { + itemProperty = { + type: 'array', + items: { + $ref: `#/components/schemas/${capitalize( + field.fromRelationMetadata?.toObjectMetadata.nameSingular || '', + )}`, + }, + }; + } + } + + if (field.description) { + itemProperty.description = field.description; + } + + if (Object.keys(itemProperty).length) { + node[field.name] = itemProperty; + } + + return node; + }, {} as Properties); +}; + const getRequiredFields = (item: ObjectMetadataEntity): string[] => { return item.fields.reduce((required, field) => { if (!field.isNullable && field.defaultValue === null) { @@ -118,14 +141,14 @@ const getRequiredFields = (item: ObjectMetadataEntity): string[] => { }, [] as string[]); }; -const computeBatchSchemaComponent = ( +const computeSchemaComponent = ( item: ObjectMetadataEntity, ): OpenAPIV3_1.SchemaObject => { const result = { - type: 'array', - description: `A list of ${item.namePlural}`, - items: { $ref: `#/components/schemas/${capitalize(item.nameSingular)}` }, - example: [{}], + type: 'object', + description: item.description, + properties: getSchemaComponentsProperties(item), + example: {}, } as OpenAPIV3_1.SchemaObject; const requiredFields = getRequiredFields(item); @@ -145,13 +168,20 @@ const computeBatchSchemaComponent = ( return result; }; -const computeSchemaComponent = ( +const computeRelationSchemaComponent = ( item: ObjectMetadataEntity, ): OpenAPIV3_1.SchemaObject => { const result = { - type: 'object', description: item.description, - properties: getSchemaComponentsProperties(item), + allOf: [ + { + $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + }, + { + type: 'object', + properties: getSchemaComponentsRelationProperties(item), + }, + ], example: {}, } as OpenAPIV3_1.SchemaObject; @@ -178,7 +208,8 @@ export const computeSchemaComponents = ( return objectMetadataItems.reduce( (schemas, item) => { schemas[capitalize(item.nameSingular)] = computeSchemaComponent(item); - schemas[capitalize(item.namePlural)] = computeBatchSchemaComponent(item); + schemas[capitalize(item.nameSingular) + ' with Relations'] = + computeRelationSchemaComponent(item); return schemas; }, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts index 083c57a4ce00..cb15a47afde1 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts @@ -11,7 +11,10 @@ import { getFindOneResponse200, getUpdateOneResponse200, } from 'src/engine/core-modules/open-api/utils/responses.utils'; -import { getRequestBody } from 'src/engine/core-modules/open-api/utils/request-body.utils'; +import { + getArrayRequestBody, + getRequestBody, +} from 'src/engine/core-modules/open-api/utils/request-body.utils'; export const computeBatchPath = ( item: ObjectMetadataEntity, @@ -22,7 +25,7 @@ export const computeBatchPath = ( summary: `Create Many ${item.namePlural}`, operationId: `createMany${capitalize(item.namePlural)}`, parameters: [{ $ref: '#/components/parameters/depth' }], - requestBody: getRequestBody(capitalize(item.namePlural)), + requestBody: getArrayRequestBody(capitalize(item.nameSingular)), responses: { '201': getCreateManyResponse201(item), '400': { $ref: '#/components/responses/400' }, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts index 904a18fb7340..6965d8fc0f8e 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts @@ -11,3 +11,19 @@ export const getRequestBody = (name: string) => { }, }; }; + +export const getArrayRequestBody = (name: string) => { + return { + required: true, + content: { + 'application/json': { + schema: { + type: 'array', + items: { + $ref: `#/components/schemas/${name}`, + }, + }, + }, + }, + }; +}; diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts index 7baae995ef96..25438d3da451 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts @@ -19,7 +19,7 @@ export const getFindManyResponse200 = ( items: { $ref: `#/components/schemas/${capitalize( item.nameSingular, - )}`, + )} with Relations`, }, }, }, @@ -54,7 +54,9 @@ export const getFindOneResponse200 = ( type: 'object', properties: { [item.nameSingular]: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: `#/components/schemas/${capitalize( + item.nameSingular, + )} with Relations`, }, }, },