12660 bugapi create one person post api request example is returning 400 in playground (#12787)
Use faker to provide simple working examples for REST API create one, create many, update one and find duplicates Eg: <img width="1505" alt="image" src="https://github.com/user-attachments/assets/99be990f-efd6-4ad7-8c29-f9dcecac112f" />
This commit is contained in:
@ -4,6 +4,9 @@ exports[`computeSchemaComponents Float without decimals 1`] = `
|
|||||||
{
|
{
|
||||||
"ObjectName": {
|
"ObjectName": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number2": 692.1852368365229,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number2": {
|
"number2": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -25,6 +28,9 @@ exports[`computeSchemaComponents Float without decimals 1`] = `
|
|||||||
},
|
},
|
||||||
"ObjectNameForUpdate": {
|
"ObjectNameForUpdate": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number2": 316.2001153750569,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number2": {
|
"number2": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -39,6 +45,9 @@ exports[`computeSchemaComponents Integer dataType with decimals 1`] = `
|
|||||||
{
|
{
|
||||||
"ObjectName": {
|
"ObjectName": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number1": 957.9316406203515,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number1": {
|
"number1": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -60,6 +69,9 @@ exports[`computeSchemaComponents Integer dataType with decimals 1`] = `
|
|||||||
},
|
},
|
||||||
"ObjectNameForUpdate": {
|
"ObjectNameForUpdate": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number1": 533.6321196880441,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number1": {
|
"number1": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -74,6 +86,9 @@ exports[`computeSchemaComponents Integer with a 0 decimals 1`] = `
|
|||||||
{
|
{
|
||||||
"ObjectName": {
|
"ObjectName": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number3": 686.8144267539021,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number3": {
|
"number3": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -95,6 +110,9 @@ exports[`computeSchemaComponents Integer with a 0 decimals 1`] = `
|
|||||||
},
|
},
|
||||||
"ObjectNameForUpdate": {
|
"ObjectNameForUpdate": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"number3": 834.7910462254755,
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"number3": {
|
"number3": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { EachTestingContext } from 'twenty-shared/testing';
|
import { EachTestingContext } from 'twenty-shared/testing';
|
||||||
import { FieldMetadataType } from 'twenty-shared/types';
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
|
|
||||||
describe('computeSchemaComponents', () => {
|
describe('computeSchemaComponents', () => {
|
||||||
|
faker.seed(1);
|
||||||
it('should compute schema components', () => {
|
it('should compute schema components', () => {
|
||||||
expect(
|
expect(
|
||||||
computeSchemaComponents([
|
computeSchemaComponents([
|
||||||
@ -18,6 +20,36 @@ describe('computeSchemaComponents', () => {
|
|||||||
{
|
{
|
||||||
"ObjectName": {
|
"ObjectName": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"fieldCurrency": {
|
||||||
|
"amountMicros": 284000000,
|
||||||
|
"currencyCode": "EUR",
|
||||||
|
},
|
||||||
|
"fieldEmails": {
|
||||||
|
"additionalEmails": null,
|
||||||
|
"primaryEmail": "mina.gutmann9@hotmail.com",
|
||||||
|
},
|
||||||
|
"fieldFullName": {
|
||||||
|
"firstName": "Shad",
|
||||||
|
"lastName": "Osinski",
|
||||||
|
},
|
||||||
|
"fieldLinks": {
|
||||||
|
"additionalLinks": [],
|
||||||
|
"primaryLinkLabel": "",
|
||||||
|
"primaryLinkUrl": "https://narrow-help.net/",
|
||||||
|
},
|
||||||
|
"fieldMultiSelect": [
|
||||||
|
"OPTION_1",
|
||||||
|
],
|
||||||
|
"fieldNumber": 346.2151663160047,
|
||||||
|
"fieldPhones": {
|
||||||
|
"additionalPhones": [],
|
||||||
|
"primaryPhoneCallingCode": "+33",
|
||||||
|
"primaryPhoneCountryCode": "FR",
|
||||||
|
"primaryPhoneNumber": "06 10 20 30 40",
|
||||||
|
},
|
||||||
|
"fieldSelect": "OPTION_1",
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"fieldActor": {
|
"fieldActor": {
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -444,6 +476,36 @@ describe('computeSchemaComponents', () => {
|
|||||||
},
|
},
|
||||||
"ObjectNameForUpdate": {
|
"ObjectNameForUpdate": {
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
|
"example": {
|
||||||
|
"fieldCurrency": {
|
||||||
|
"amountMicros": 253000000,
|
||||||
|
"currencyCode": "EUR",
|
||||||
|
},
|
||||||
|
"fieldEmails": {
|
||||||
|
"additionalEmails": null,
|
||||||
|
"primaryEmail": "keegan_donnelly96@hotmail.com",
|
||||||
|
},
|
||||||
|
"fieldFullName": {
|
||||||
|
"firstName": "Shad",
|
||||||
|
"lastName": "Jones",
|
||||||
|
},
|
||||||
|
"fieldLinks": {
|
||||||
|
"additionalLinks": [],
|
||||||
|
"primaryLinkLabel": "",
|
||||||
|
"primaryLinkUrl": "https://unlawful-blowgun.biz",
|
||||||
|
},
|
||||||
|
"fieldMultiSelect": [
|
||||||
|
"OPTION_1",
|
||||||
|
],
|
||||||
|
"fieldNumber": 692.6302930536448,
|
||||||
|
"fieldPhones": {
|
||||||
|
"additionalPhones": [],
|
||||||
|
"primaryPhoneCallingCode": "+33",
|
||||||
|
"primaryPhoneCountryCode": "FR",
|
||||||
|
"primaryPhoneNumber": "06 10 20 30 40",
|
||||||
|
},
|
||||||
|
"fieldSelect": "OPTION_1",
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"fieldActor": {
|
"fieldActor": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
NumberDataType,
|
NumberDataType,
|
||||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||||
|
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
computeDepthParameters,
|
computeDepthParameters,
|
||||||
@ -20,6 +21,8 @@ import {
|
|||||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||||
|
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
|
||||||
|
import { generateRandomFieldValue } from 'src/engine/core-modules/open-api/utils/generate-random-field-value.utils';
|
||||||
|
|
||||||
type Property = OpenAPIV3_1.SchemaObject;
|
type Property = OpenAPIV3_1.SchemaObject;
|
||||||
|
|
||||||
@ -27,6 +30,8 @@ type Properties = {
|
|||||||
[name: string]: Property;
|
[name: string]: Property;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type OpenApiExample = Record<string, FieldMetadataDefaultValue>;
|
||||||
|
|
||||||
const isFieldAvailable = (field: FieldMetadataEntity, forResponse: boolean) => {
|
const isFieldAvailable = (field: FieldMetadataEntity, forResponse: boolean) => {
|
||||||
if (forResponse) {
|
if (forResponse) {
|
||||||
return true;
|
return true;
|
||||||
@ -86,6 +91,47 @@ const getFieldProperties = (field: FieldMetadataEntity): Property => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSchemaComponentsExample = (
|
||||||
|
item: ObjectMetadataEntity,
|
||||||
|
): OpenApiExample => {
|
||||||
|
return item.fields.reduce((node, field) => {
|
||||||
|
// If field is required
|
||||||
|
if (!field.isNullable && field.defaultValue === null) {
|
||||||
|
return { ...node, [field.name]: generateRandomFieldValue({ field }) };
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (field.type) {
|
||||||
|
case FieldMetadataType.TEXT: {
|
||||||
|
if (field.name !== 'name') {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
[field.name]: `${camelToTitleCase(item.nameSingular)} name`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.EMAILS:
|
||||||
|
case FieldMetadataType.LINKS:
|
||||||
|
case FieldMetadataType.CURRENCY:
|
||||||
|
case FieldMetadataType.FULL_NAME:
|
||||||
|
case FieldMetadataType.SELECT:
|
||||||
|
case FieldMetadataType.MULTI_SELECT:
|
||||||
|
case FieldMetadataType.PHONES: {
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
[field.name]: generateRandomFieldValue({ field }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
const getSchemaComponentsProperties = ({
|
const getSchemaComponentsProperties = ({
|
||||||
item,
|
item,
|
||||||
forResponse,
|
forResponse,
|
||||||
@ -105,12 +151,13 @@ const getSchemaComponentsProperties = ({
|
|||||||
isFieldMetadataEntityOfType(field, FieldMetadataType.RELATION) &&
|
isFieldMetadataEntityOfType(field, FieldMetadataType.RELATION) &&
|
||||||
field.settings?.relationType === RelationType.MANY_TO_ONE
|
field.settings?.relationType === RelationType.MANY_TO_ONE
|
||||||
) {
|
) {
|
||||||
node[`${field.name}Id`] = {
|
return {
|
||||||
type: 'string',
|
...node,
|
||||||
format: 'uuid',
|
[`${field.name}Id`]: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -333,7 +380,7 @@ const getSchemaComponentsProperties = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(itemProperty).length) {
|
if (Object.keys(itemProperty).length) {
|
||||||
node[field.name] = itemProperty;
|
return { ...node, [field.name]: itemProperty };
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -379,7 +426,7 @@ const getSchemaComponentsRelationProperties = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(itemProperty).length) {
|
if (Object.keys(itemProperty).length) {
|
||||||
node[field.name] = itemProperty;
|
return { ...node, [field.name]: itemProperty };
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -400,20 +447,23 @@ const getRequiredFields = (item: ObjectMetadataEntity): string[] => {
|
|||||||
|
|
||||||
const computeSchemaComponent = ({
|
const computeSchemaComponent = ({
|
||||||
item,
|
item,
|
||||||
withRequiredFields,
|
|
||||||
forResponse,
|
forResponse,
|
||||||
withRelations,
|
forUpdate,
|
||||||
}: {
|
}: {
|
||||||
item: ObjectMetadataEntity;
|
item: ObjectMetadataEntity;
|
||||||
withRequiredFields: boolean;
|
|
||||||
forResponse: boolean;
|
forResponse: boolean;
|
||||||
withRelations: boolean;
|
forUpdate: boolean;
|
||||||
}): OpenAPIV3_1.SchemaObject => {
|
}): OpenAPIV3_1.SchemaObject => {
|
||||||
const result = {
|
const withRelations = forResponse && !forUpdate;
|
||||||
|
|
||||||
|
const withRequiredFields = !forResponse && !forUpdate;
|
||||||
|
|
||||||
|
const result: OpenAPIV3_1.SchemaObject = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: item.description,
|
description: item.description,
|
||||||
properties: getSchemaComponentsProperties({ item, forResponse }),
|
properties: getSchemaComponentsProperties({ item, forResponse }),
|
||||||
} as OpenAPIV3_1.SchemaObject;
|
...(!forResponse ? { example: getSchemaComponentsExample(item) } : {}),
|
||||||
|
};
|
||||||
|
|
||||||
if (withRelations) {
|
if (withRelations) {
|
||||||
result.properties = {
|
result.properties = {
|
||||||
@ -442,23 +492,20 @@ export const computeSchemaComponents = (
|
|||||||
(schemas, item) => {
|
(schemas, item) => {
|
||||||
schemas[capitalize(item.nameSingular)] = computeSchemaComponent({
|
schemas[capitalize(item.nameSingular)] = computeSchemaComponent({
|
||||||
item,
|
item,
|
||||||
withRequiredFields: true,
|
|
||||||
forResponse: false,
|
forResponse: false,
|
||||||
withRelations: false,
|
forUpdate: false,
|
||||||
});
|
});
|
||||||
schemas[capitalize(item.nameSingular) + 'ForUpdate'] =
|
schemas[capitalize(item.nameSingular) + 'ForUpdate'] =
|
||||||
computeSchemaComponent({
|
computeSchemaComponent({
|
||||||
item,
|
item,
|
||||||
withRequiredFields: false,
|
|
||||||
forResponse: false,
|
forResponse: false,
|
||||||
withRelations: false,
|
forUpdate: true,
|
||||||
});
|
});
|
||||||
schemas[capitalize(item.nameSingular) + 'ForResponse'] =
|
schemas[capitalize(item.nameSingular) + 'ForResponse'] =
|
||||||
computeSchemaComponent({
|
computeSchemaComponent({
|
||||||
item,
|
item,
|
||||||
withRequiredFields: false,
|
|
||||||
forResponse: true,
|
forResponse: true,
|
||||||
withRelations: true,
|
forUpdate: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return schemas;
|
return schemas;
|
||||||
|
|||||||
@ -0,0 +1,144 @@
|
|||||||
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||||
|
|
||||||
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
|
|
||||||
|
export const generateRandomFieldValue = ({
|
||||||
|
field,
|
||||||
|
}: {
|
||||||
|
field: FieldMetadataEntity;
|
||||||
|
}): FieldMetadataDefaultValue => {
|
||||||
|
switch (field.type) {
|
||||||
|
case FieldMetadataType.UUID: {
|
||||||
|
return v4();
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.TEXT: {
|
||||||
|
return faker.string.fromCharacters(field.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.PHONES: {
|
||||||
|
return {
|
||||||
|
primaryPhoneNumber: '06 10 20 30 40',
|
||||||
|
primaryPhoneCallingCode: '+33',
|
||||||
|
primaryPhoneCountryCode: 'FR',
|
||||||
|
additionalPhones: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.EMAILS: {
|
||||||
|
return {
|
||||||
|
primaryEmail: faker.internet.email().toLowerCase(),
|
||||||
|
additionalEmails: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.DATE:
|
||||||
|
case FieldMetadataType.DATE_TIME: {
|
||||||
|
return faker.date.soon();
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.BOOLEAN: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.NUMBER: {
|
||||||
|
return faker.number.float({ min: 1, max: 1_000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.NUMERIC: {
|
||||||
|
return faker.number.int({ min: 1, max: 1_000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.LINKS: {
|
||||||
|
return {
|
||||||
|
primaryLinkLabel: '',
|
||||||
|
primaryLinkUrl: faker.internet.url(),
|
||||||
|
additionalLinks: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.CURRENCY: {
|
||||||
|
return {
|
||||||
|
amountMicros: faker.number.int({ min: 100, max: 1_000 }) * 1_000_000,
|
||||||
|
currencyCode: 'EUR',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.FULL_NAME: {
|
||||||
|
return {
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.RATING: {
|
||||||
|
return 'RATING_5';
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.SELECT: {
|
||||||
|
return isDefined(field.options[0].value) ? field.options[0].value : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.MULTI_SELECT: {
|
||||||
|
return isDefined(field.options[0].value) ? [field.options[0].value] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.RELATION: {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.POSITION: {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.ADDRESS: {
|
||||||
|
return {
|
||||||
|
addressStreet1: faker.location.streetAddress(),
|
||||||
|
addressStreet2: faker.location.secondaryAddress(),
|
||||||
|
addressCity: faker.location.city(),
|
||||||
|
addressState: faker.location.state(),
|
||||||
|
addressCountry: faker.location.country(),
|
||||||
|
addressPostcode: faker.location.zipCode(),
|
||||||
|
addressLat: faker.location.latitude(),
|
||||||
|
addressLng: faker.location.longitude(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.RAW_JSON: {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.RICH_TEXT:
|
||||||
|
case FieldMetadataType.RICH_TEXT_V2: {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.ACTOR: {
|
||||||
|
return {
|
||||||
|
source: 'MANUAL',
|
||||||
|
context: {},
|
||||||
|
name: faker.person.fullName(),
|
||||||
|
workspaceMemberId: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.ARRAY: {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
case FieldMetadataType.TS_VECTOR: {
|
||||||
|
throw new Error(
|
||||||
|
`We should not generate fake version for ${field.type} field`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
assertUnreachable(field.type, `Unsupported field type '${field.type}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
export const getRequestBody = (name: string) => {
|
export const getRequestBody = (name: string) => {
|
||||||
return {
|
return {
|
||||||
description: 'body',
|
description: 'body',
|
||||||
@ -59,8 +61,13 @@ export const getFindDuplicatesRequestBody = (name: string) => {
|
|||||||
},
|
},
|
||||||
ids: {
|
ids: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
example: { ids: [v4()] },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { capitalize } from 'twenty-shared/utils';
|
import { capitalize } from 'twenty-shared/utils';
|
||||||
export const camelToTitleCase = (camelCaseText: string) =>
|
export const camelToTitleCase = (camelCaseText: string) =>
|
||||||
capitalize(camelCaseText)
|
capitalize(
|
||||||
.replace(/([A-Z])/g, ' $1')
|
camelCaseText
|
||||||
.replace(/^./, (str) => str.toUpperCase());
|
.replace(/([A-Z])/g, ' $1')
|
||||||
|
.replace(/^./, (str) => str.toUpperCase()),
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user