martmull
2024-11-20 10:06:05 +01:00
committed by GitHub
parent 271af37327
commit a744515303
3 changed files with 235 additions and 99 deletions

View File

@@ -23,7 +23,10 @@ describe('computeSchemaComponents', () => {
fieldPhones: { fieldPhones: {
properties: { properties: {
additionalPhones: { additionalPhones: {
type: 'object', type: 'array',
items: {
type: 'string',
},
}, },
primaryPhoneCountryCode: { primaryPhoneCountryCode: {
type: 'string', type: 'string',
@@ -41,7 +44,11 @@ describe('computeSchemaComponents', () => {
type: 'string', type: 'string',
}, },
additionalEmails: { additionalEmails: {
type: 'object', type: 'array',
items: {
type: 'string',
format: 'email',
},
}, },
}, },
}, },
@@ -85,6 +92,7 @@ describe('computeSchemaComponents', () => {
properties: { properties: {
url: { url: {
type: 'string', type: 'string',
format: 'uri',
}, },
label: { label: {
type: 'string', type: 'string',
@@ -200,7 +208,10 @@ describe('computeSchemaComponents', () => {
fieldPhones: { fieldPhones: {
properties: { properties: {
additionalPhones: { additionalPhones: {
type: 'object', type: 'array',
items: {
type: 'string',
},
}, },
primaryPhoneCountryCode: { primaryPhoneCountryCode: {
type: 'string', type: 'string',
@@ -218,7 +229,11 @@ describe('computeSchemaComponents', () => {
type: 'string', type: 'string',
}, },
additionalEmails: { additionalEmails: {
type: 'object', type: 'array',
items: {
type: 'string',
format: 'email',
},
}, },
}, },
}, },
@@ -262,6 +277,7 @@ describe('computeSchemaComponents', () => {
properties: { properties: {
url: { url: {
type: 'string', type: 'string',
format: 'uri',
}, },
label: { label: {
type: 'string', type: 'string',
@@ -376,7 +392,10 @@ describe('computeSchemaComponents', () => {
fieldPhones: { fieldPhones: {
properties: { properties: {
additionalPhones: { additionalPhones: {
type: 'object', type: 'array',
items: {
type: 'string',
},
}, },
primaryPhoneCountryCode: { primaryPhoneCountryCode: {
type: 'string', type: 'string',
@@ -394,7 +413,11 @@ describe('computeSchemaComponents', () => {
type: 'string', type: 'string',
}, },
additionalEmails: { additionalEmails: {
type: 'object', type: 'array',
items: {
type: 'string',
format: 'email',
},
}, },
}, },
}, },
@@ -438,6 +461,7 @@ describe('computeSchemaComponents', () => {
properties: { properties: {
url: { url: {
type: 'string', type: 'string',
format: 'uri',
}, },
label: { label: {
type: 'string', type: 'string',

View File

@@ -1,7 +1,5 @@
import { OpenAPIV3_1 } from 'openapi-types'; import { OpenAPIV3_1 } from 'openapi-types';
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { import {
computeDepthParameters, computeDepthParameters,
computeEndingBeforeParameters, computeEndingBeforeParameters,
@@ -11,7 +9,6 @@ import {
computeOrderByParameters, computeOrderByParameters,
computeStartingAfterParameters, computeStartingAfterParameters,
} from 'src/engine/core-modules/open-api/utils/parameters.utils'; } from 'src/engine/core-modules/open-api/utils/parameters.utils';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { import {
FieldMetadataEntity, FieldMetadataEntity,
FieldMetadataType, FieldMetadataType,
@@ -41,18 +38,8 @@ const isFieldAvailable = (field: FieldMetadataEntity, forResponse: boolean) => {
} }
}; };
const getFieldProperties = ( const getFieldProperties = (type: FieldMetadataType): Property => {
type: FieldMetadataType,
propertyName?: string,
options?: FieldMetadataOptions,
): Property => {
switch (type) { switch (type) {
case FieldMetadataType.SELECT:
case FieldMetadataType.MULTI_SELECT:
return {
type: 'string',
enum: options?.map((option: { value: string }) => option.value),
};
case FieldMetadataType.UUID: case FieldMetadataType.UUID:
return { type: 'string', format: 'uuid' }; return { type: 'string', format: 'uuid' };
case FieldMetadataType.TEXT: case FieldMetadataType.TEXT:
@@ -64,31 +51,12 @@ const getFieldProperties = (
return { type: 'string', format: 'date' }; return { type: 'string', format: 'date' };
case FieldMetadataType.NUMBER: case FieldMetadataType.NUMBER:
return { type: 'integer' }; return { type: 'integer' };
case FieldMetadataType.RATING:
return {
type: 'string',
enum: options?.map((option: { value: string }) => option.value),
};
case FieldMetadataType.NUMERIC: case FieldMetadataType.NUMERIC:
case FieldMetadataType.POSITION: case FieldMetadataType.POSITION:
return { type: 'number' }; return { type: 'number' };
case FieldMetadataType.BOOLEAN: case FieldMetadataType.BOOLEAN:
return { type: 'boolean' }; return { type: 'boolean' };
case FieldMetadataType.RAW_JSON: case FieldMetadataType.RAW_JSON:
if (propertyName === 'secondaryLinks') {
return {
type: 'array',
items: {
type: 'object',
description: `A secondary link`,
properties: {
url: { type: 'string' },
label: { type: 'string' },
},
},
};
}
return { type: 'object' }; return { type: 'object' };
default: default:
@@ -147,32 +115,155 @@ const getSchemaComponentsProperties = ({
}; };
break; break;
case FieldMetadataType.LINKS: case FieldMetadataType.LINKS:
case FieldMetadataType.CURRENCY:
case FieldMetadataType.FULL_NAME:
case FieldMetadataType.ADDRESS:
case FieldMetadataType.ACTOR:
case FieldMetadataType.EMAILS:
case FieldMetadataType.PHONES:
itemProperty = { itemProperty = {
type: 'object', type: 'object',
properties: compositeTypeDefinitions properties: {
.get(field.type) primaryLinkLabel: {
?.properties?.reduce((properties, property) => { type: 'string',
if ( },
property.hidden === true || primaryLinkUrl: {
(property.hidden === 'input' && !forResponse) || type: 'string',
(property.hidden === 'output' && forResponse) },
) { secondaryLinks: {
return properties; type: 'array',
} items: {
properties[property.name] = getFieldProperties( type: 'object',
property.type, description: 'A secondary link',
property.name, properties: {
property.options, url: {
); type: 'string',
format: 'uri',
return properties; },
}, {} as Properties), label: {
type: 'string',
},
},
},
},
},
};
break;
case FieldMetadataType.CURRENCY:
itemProperty = {
type: 'object',
properties: {
amountMicros: {
type: 'number',
},
currencyCode: {
type: 'string',
},
},
};
break;
case FieldMetadataType.FULL_NAME:
itemProperty = {
type: 'object',
properties: {
firstName: {
type: 'string',
},
lastName: {
type: 'string',
},
},
};
break;
case FieldMetadataType.ADDRESS:
itemProperty = {
type: 'object',
properties: {
addressStreet1: {
type: 'string',
},
addressStreet2: {
type: 'string',
},
addressCity: {
type: 'string',
},
addressPostcode: {
type: 'string',
},
addressState: {
type: 'string',
},
addressCountry: {
type: 'string',
},
addressLat: {
type: 'number',
},
addressLng: {
type: 'number',
},
},
};
break;
case FieldMetadataType.ACTOR:
itemProperty = {
type: 'object',
properties: {
source: {
type: 'string',
enum: [
'EMAIL',
'CALENDAR',
'WORKFLOW',
'API',
'IMPORT',
'MANUAL',
'SYSTEM',
],
},
...(forResponse
? {
workspaceMemberId: {
type: 'string',
format: 'uuid',
},
name: {
type: 'string',
},
}
: {}),
},
};
break;
case FieldMetadataType.EMAILS:
itemProperty = {
type: 'object',
properties: {
primaryEmail: {
type: 'string',
},
additionalEmails: {
type: 'array',
items: {
type: 'string',
format: 'email',
},
},
},
};
break;
case FieldMetadataType.PHONES:
itemProperty = {
properties: {
additionalPhones: {
type: 'array',
items: {
type: 'string',
},
},
primaryPhoneCountryCode: {
type: 'string',
},
primaryPhoneNumber: {
type: 'string',
},
},
type: 'object',
}; };
break; break;
default: default:
@@ -401,22 +492,59 @@ export const computeMetadataSchemaComponents = (
return schemas; return schemas;
} }
case 'field': { case 'field': {
schemas[`${capitalize(item.nameSingular)}`] = { const baseFieldProperties = ({
withImmutableFields,
withRequiredFields,
}: {
withImmutableFields: boolean;
withRequiredFields: boolean;
}): OpenAPIV3_1.SchemaObject => ({
type: 'object', type: 'object',
description: `A field`, description: `A field`,
properties: { properties: {
type: { ...(withImmutableFields
type: 'string', ? {
enum: Object.keys(FieldMetadataType), type: {
}, type: 'string',
enum: Object.keys(FieldMetadataType),
},
objectMetadataId: { type: 'string', format: 'uuid' },
}
: {}),
name: { type: 'string' }, name: { type: 'string' },
label: { type: 'string' }, label: { type: 'string' },
description: { type: 'string' }, description: { type: 'string' },
icon: { type: 'string' }, icon: { type: 'string' },
defaultValue: {},
isNullable: { type: 'boolean' }, isNullable: { type: 'boolean' },
objectMetadataId: { type: 'string', format: 'uuid' }, settings: { type: 'object' },
options: {
type: 'array',
description: 'For enum field types like SELECT or MULTI_SELECT',
items: {
type: 'object',
properties: {
color: { type: 'string' },
label: { type: 'string' },
value: {
type: 'string',
pattern: '^[A-Z0-9]+_[A-Z0-9]+$',
example: 'OPTION_1',
},
position: { type: 'number' },
},
},
},
}, },
}; ...(withRequiredFields
? { required: ['type', 'name', 'label', 'objectMetadataId'] }
: {}),
});
schemas[`${capitalize(item.nameSingular)}`] = baseFieldProperties({
withImmutableFields: true,
withRequiredFields: true,
});
schemas[`${capitalize(item.namePlural)}`] = { schemas[`${capitalize(item.namePlural)}`] = {
type: 'array', type: 'array',
description: `A list of ${item.namePlural}`, description: `A list of ${item.namePlural}`,
@@ -424,38 +552,22 @@ export const computeMetadataSchemaComponents = (
$ref: `#/components/schemas/${capitalize(item.nameSingular)}`, $ref: `#/components/schemas/${capitalize(item.nameSingular)}`,
}, },
}; };
schemas[`${capitalize(item.nameSingular)} for Update`] = { schemas[`${capitalize(item.nameSingular)} for Update`] =
type: 'object', baseFieldProperties({
description: `An object`, withImmutableFields: false,
properties: { withRequiredFields: false,
description: { type: 'string' }, });
icon: { type: 'string' },
isActive: { type: 'boolean' },
isCustom: { type: 'boolean' },
isNullable: { type: 'boolean' },
isSystem: { type: 'boolean' },
label: { type: 'string' },
name: { type: 'string' },
},
};
schemas[`${capitalize(item.nameSingular)} for Response`] = { schemas[`${capitalize(item.nameSingular)} for Response`] = {
...schemas[`${capitalize(item.nameSingular)}`], ...baseFieldProperties({
withImmutableFields: true,
withRequiredFields: false,
}),
properties: { properties: {
type: { ...schemas[`${capitalize(item.nameSingular)}`].properties,
type: 'string',
enum: Object.keys(FieldMetadataType),
},
name: { type: 'string' },
label: { type: 'string' },
description: { type: 'string' },
icon: { type: 'string' },
isNullable: { type: 'boolean' },
id: { type: 'string', format: 'uuid' }, id: { type: 'string', format: 'uuid' },
isCustom: { type: 'boolean' }, isCustom: { type: 'boolean' },
isActive: { type: 'boolean' }, isActive: { type: 'boolean' },
isSystem: { type: 'boolean' }, isSystem: { type: 'boolean' },
defaultValue: { type: 'object' },
options: { type: 'object' },
createdAt: { type: 'string', format: 'date-time' }, createdAt: { type: 'string', format: 'date-time' },
updatedAt: { type: 'string', format: 'date-time' }, updatedAt: { type: 'string', format: 'date-time' },
fromRelationMetadata: { fromRelationMetadata: {

View File

@@ -8,8 +8,8 @@ Queues facilitate async operations to be performed. They can be used for perform
Each use case will have its own queue class extended from `MessageQueueServiceBase`. Each use case will have its own queue class extended from `MessageQueueServiceBase`.
Currently, queue supports two drivers which can be configured by env variable `MESSAGE_QUEUE_TYPE`. Currently, queue supports two drivers which can be configured by env variable `MESSAGE_QUEUE_TYPE`.
1. `pg-boss`: this is the default driver, which uses [pg-boss](https://github.com/timgit/pg-boss) under the hood. 1. `bull-mq`: this is the default driver, which uses [bull-mq](https://bullmq.io/) under the hood.
2. `bull-mq`: this uses [bull-mq](https://bullmq.io/) under the hood. 2. `pg-boss`: this uses [pg-boss](https://github.com/timgit/pg-boss) under the hood.
## Steps to create and use a new queue ## Steps to create and use a new queue
@@ -43,4 +43,4 @@ class CustomWorker {
} }
``` ```
<ArticleEditContent></ArticleEditContent> <ArticleEditContent></ArticleEditContent>