Add relations in database event trigger output data (#11820)
## Done - add relations in dropdown variables - add relations in worklfow run inputs - use objectMetadataMaps in workflow folder ## To do - does not work with rest api calls, will be fixed after https://github.com/twentyhq/twenty/pull/11349 is merged - waiting for crud action relation fields https://github.com/twentyhq/core-team-issues/issues/509
This commit is contained in:
@ -321,8 +321,8 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents({
|
||||
existingRecords: [existingRecord],
|
||||
records: [record],
|
||||
existingRecords: structuredClone([existingRecord]),
|
||||
records: structuredClone([record]),
|
||||
updatedFields: Object.keys(formattedPartialRecordToUpdate),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
@ -366,7 +366,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
}
|
||||
|
||||
this.apiEventEmitterService.emitCreateEvents({
|
||||
records: formattedInsertedRecords,
|
||||
records: structuredClone(formattedInsertedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -54,7 +54,7 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitCreateEvents({
|
||||
records: upsertedRecords,
|
||||
records: structuredClone(upsertedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -56,7 +56,7 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDeletedEvents({
|
||||
records: formattedDeletedRecords,
|
||||
records: structuredClone(formattedDeletedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -48,12 +48,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
|
||||
objectMetadataMaps,
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDeletedEvents({
|
||||
records: formattedDeletedRecords,
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (formattedDeletedRecords.length === 0) {
|
||||
throw new GraphqlQueryRunnerException(
|
||||
'Record not found',
|
||||
@ -63,6 +57,12 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
|
||||
|
||||
const deletedRecord = formattedDeletedRecords[0];
|
||||
|
||||
this.apiEventEmitterService.emitDeletedEvents({
|
||||
records: structuredClone(formattedDeletedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (executionArgs.graphqlQuerySelectedFieldsResult.relations) {
|
||||
await this.processNestedRelationsHelper.processNestedRelations({
|
||||
objectMetadataMaps,
|
||||
|
||||
@ -54,7 +54,7 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDestroyEvents({
|
||||
records: deletedRecords,
|
||||
records: structuredClone(deletedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -54,7 +54,7 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDestroyEvents({
|
||||
records: deletedRecords,
|
||||
records: structuredClone(deletedRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -56,7 +56,7 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitRestoreEvents({
|
||||
records: formattedRestoredRecords,
|
||||
records: structuredClone(formattedRestoredRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
@ -48,12 +48,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
|
||||
objectMetadataMaps,
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitRestoreEvents({
|
||||
records: formattedRestoredRecords,
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (formattedRestoredRecords.length === 0) {
|
||||
throw new GraphqlQueryRunnerException(
|
||||
'Record not found',
|
||||
@ -63,6 +57,12 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
|
||||
|
||||
const restoredRecord = formattedRestoredRecords[0];
|
||||
|
||||
this.apiEventEmitterService.emitRestoreEvents({
|
||||
records: structuredClone(formattedRestoredRecords),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (executionArgs.graphqlQuerySelectedFieldsResult.relations) {
|
||||
await this.processNestedRelationsHelper.processNestedRelations({
|
||||
objectMetadataMaps,
|
||||
|
||||
@ -90,8 +90,8 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents({
|
||||
existingRecords: formattedExistingRecords,
|
||||
records: formattedUpdatedRecords,
|
||||
existingRecords: structuredClone(formattedExistingRecords),
|
||||
records: structuredClone(formattedUpdatedRecords),
|
||||
updatedFields: Object.keys(executionArgs.args.data),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
@ -101,7 +101,10 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
await this.processNestedRelationsHelper.processNestedRelations({
|
||||
objectMetadataMaps,
|
||||
parentObjectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
parentObjectRecords: formattedUpdatedRecords,
|
||||
parentObjectRecords: [
|
||||
...formattedExistingRecords,
|
||||
...formattedUpdatedRecords,
|
||||
],
|
||||
relations: executionArgs.graphqlQuerySelectedFieldsResult.relations,
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
|
||||
@ -74,14 +74,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
objectMetadataMaps,
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents({
|
||||
existingRecords: formattedExistingRecords,
|
||||
records: formattedUpdatedRecords,
|
||||
updatedFields: Object.keys(executionArgs.args.data),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (formattedUpdatedRecords.length === 0) {
|
||||
throw new GraphqlQueryRunnerException(
|
||||
'Record not found',
|
||||
@ -90,12 +82,21 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
}
|
||||
|
||||
const updatedRecord = formattedUpdatedRecords[0];
|
||||
const existingRecord = formattedExistingRecords[0];
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents({
|
||||
existingRecords: structuredClone(formattedExistingRecords),
|
||||
records: structuredClone(formattedUpdatedRecords),
|
||||
updatedFields: Object.keys(executionArgs.args.data),
|
||||
authContext,
|
||||
objectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
});
|
||||
|
||||
if (executionArgs.graphqlQuerySelectedFieldsResult.relations) {
|
||||
await this.processNestedRelationsHelper.processNestedRelations({
|
||||
objectMetadataMaps,
|
||||
parentObjectMetadataItem: objectMetadataItemWithFieldMaps,
|
||||
parentObjectRecords: [updatedRecord],
|
||||
parentObjectRecords: [existingRecord, updatedRecord],
|
||||
relations: executionArgs.graphqlQuerySelectedFieldsResult.relations,
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
|
||||
@ -12,6 +12,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelSingular: 'Person',
|
||||
labelPlural: 'People',
|
||||
description: 'A person',
|
||||
icon: 'test-person-icon',
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
@ -24,13 +25,32 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
|
||||
imageIdentifierFieldMetadataId: '',
|
||||
workspaceId: '',
|
||||
fields: [],
|
||||
fields: [
|
||||
{
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
lastName: "''",
|
||||
firstName: "''",
|
||||
},
|
||||
description: 'Contact’s name',
|
||||
isCustom: false,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
workspaceId: '',
|
||||
},
|
||||
],
|
||||
indexMetadatas: [],
|
||||
fieldsById: {
|
||||
nameFieldMetadataId: {
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
@ -49,6 +69,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
@ -72,6 +93,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelSingular: 'Company',
|
||||
labelPlural: 'Companies',
|
||||
description: 'A company',
|
||||
icon: 'test-company-icon',
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
@ -84,13 +106,41 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
|
||||
imageIdentifierFieldMetadataId: '',
|
||||
workspaceId: '',
|
||||
fields: [],
|
||||
fields: [
|
||||
{
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: '',
|
||||
isCustom: false,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
workspaceId: '',
|
||||
},
|
||||
{
|
||||
id: 'domainNameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.LINKS,
|
||||
icon: 'test-field-icon',
|
||||
name: 'domainName',
|
||||
label: 'Domain Name',
|
||||
defaultValue: '',
|
||||
isCustom: false,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
workspaceId: '',
|
||||
},
|
||||
],
|
||||
indexMetadatas: [],
|
||||
fieldsById: {
|
||||
nameFieldMetadataId: {
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: '',
|
||||
@ -103,6 +153,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'domainNameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.LINKS,
|
||||
icon: 'test-field-icon',
|
||||
name: 'domainName',
|
||||
label: 'Domain Name',
|
||||
defaultValue: '',
|
||||
@ -117,6 +168,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
@ -132,6 +184,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'domainNameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.LINKS,
|
||||
icon: 'test-field-icon',
|
||||
name: 'domainName',
|
||||
label: 'Domain Name',
|
||||
defaultValue: '',
|
||||
@ -151,6 +204,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelSingular: 'Regular Custom Object',
|
||||
labelPlural: 'Regular Custom Objects',
|
||||
description: 'A regular custom object',
|
||||
icon: 'test-regular-custom-object-icon',
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: true,
|
||||
isRemote: false,
|
||||
@ -163,13 +217,41 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
|
||||
imageIdentifierFieldMetadataId: 'imageIdentifierFieldMetadataId',
|
||||
workspaceId: '',
|
||||
fields: [],
|
||||
fields: [
|
||||
{
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: '',
|
||||
isCustom: false,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
workspaceId: '',
|
||||
},
|
||||
{
|
||||
id: 'imageIdentifierFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'imageIdentifierFieldName',
|
||||
label: 'Image Identifier Field Name',
|
||||
defaultValue: '',
|
||||
isCustom: false,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
workspaceId: '',
|
||||
},
|
||||
],
|
||||
indexMetadatas: [],
|
||||
fieldsById: {
|
||||
nameFieldMetadataId: {
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: '',
|
||||
@ -182,6 +264,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'imageIdentifierFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'imageIdentifierFieldName',
|
||||
label: 'Image Identifier Field Name',
|
||||
defaultValue: '',
|
||||
@ -196,6 +279,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'nameFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
@ -211,6 +295,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
id: 'imageIdentifierFieldMetadataId',
|
||||
objectMetadataId: '',
|
||||
type: FieldMetadataType.TEXT,
|
||||
icon: 'test-field-icon',
|
||||
name: 'imageIdentifierFieldName',
|
||||
label: 'Image Identifier Field Name',
|
||||
defaultValue: '',
|
||||
@ -230,6 +315,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
labelSingular: '',
|
||||
labelPlural: '',
|
||||
description: '',
|
||||
icon: 'test-non-searchable-object-icon',
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||
import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/search/__mocks__/mockObjectMetadataItemsWithFieldMaps';
|
||||
import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps';
|
||||
import { SearchService } from 'src/engine/core-modules/search/services/search.service';
|
||||
import { encodeCursorData } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
@ -3,10 +3,8 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
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 { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
import { RelationMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-metadata.interface';
|
||||
|
||||
export interface FieldMetadataInterface<
|
||||
T extends FieldMetadataType = FieldMetadataType,
|
||||
@ -21,14 +19,15 @@ export interface FieldMetadataInterface<
|
||||
objectMetadataId: string;
|
||||
workspaceId?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
isNullable?: boolean;
|
||||
isUnique?: boolean;
|
||||
fromRelationMetadata?: RelationMetadataEntity;
|
||||
toRelationMetadata?: RelationMetadataEntity;
|
||||
fromRelationMetadata?: RelationMetadataInterface;
|
||||
toRelationMetadata?: RelationMetadataInterface;
|
||||
relationTargetFieldMetadataId?: string;
|
||||
relationTargetFieldMetadata?: FieldMetadataEntity;
|
||||
relationTargetFieldMetadata?: FieldMetadataInterface;
|
||||
relationTargetObjectMetadataId?: string;
|
||||
relationTargetObjectMetadata?: ObjectMetadataEntity;
|
||||
relationTargetObjectMetadata?: ObjectMetadataInterface;
|
||||
isCustom?: boolean;
|
||||
isSystem?: boolean;
|
||||
isActive?: boolean;
|
||||
|
||||
@ -14,6 +14,7 @@ export interface ObjectMetadataInterface {
|
||||
labelSingular: string;
|
||||
labelPlural: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
targetTableName: string;
|
||||
fromRelations: RelationMetadataInterface[];
|
||||
toRelations: RelationMetadataInterface[];
|
||||
|
||||
@ -7,4 +7,8 @@ import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/typ
|
||||
export const removeFieldMapsFromObjectMetadata = (
|
||||
objectMetadata: ObjectMetadataItemWithFieldMaps,
|
||||
): ObjectMetadataInterface =>
|
||||
omit(objectMetadata, ['fieldsById', 'fieldsByName']);
|
||||
omit(objectMetadata, [
|
||||
'fieldsById',
|
||||
'fieldsByName',
|
||||
'fieldsByJoinColumnName',
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user