diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index e607657d0a1..4ce18bc75d9 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1596,7 +1596,7 @@ export enum EventLogTable { export type EventSubscription = { __typename?: 'EventSubscription'; eventStreamId: Scalars['String']; - metadataEventsWithQueryIds: Array; + metadataEvents: Array; objectRecordEventsWithQueryIds: Array; }; @@ -2304,12 +2304,6 @@ export enum MetadataEventAction { UPDATED = 'UPDATED' } -export type MetadataEventWithQueryIds = { - __typename?: 'MetadataEventWithQueryIds'; - metadataEvent: MetadataEvent; - queryIds: Array; -}; - export type MinimalMetadata = { __typename?: 'MinimalMetadata'; collectionHashes: Array; @@ -6494,14 +6488,14 @@ export type CreateOneObjectMetadataItemMutationVariables = Exact<{ }>; -export type CreateOneObjectMetadataItemMutation = { __typename?: 'Mutation', createOneObject: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, color?: string | null, isCustom: boolean, isActive: boolean, isSearchable: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, isLabelSyncedWithName: boolean } }; +export type CreateOneObjectMetadataItemMutation = { __typename?: 'Mutation', createOneObject: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, color?: string | null, isCustom: boolean, isActive: boolean, isSearchable: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, isLabelSyncedWithName: boolean, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> } }; export type CreateOneFieldMetadataItemMutationVariables = Exact<{ input: CreateOneFieldMetadataInput; }>; -export type CreateOneFieldMetadataItemMutation = { __typename?: 'Mutation', createOneField: { __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isUnique?: boolean | null, isNullable?: boolean | null, createdAt: string, updatedAt: string, settings?: any | null, defaultValue?: any | null, options?: any | null, isLabelSyncedWithName?: boolean | null, applicationId: string, object?: { __typename?: 'Object', id: string } | null } }; +export type CreateOneFieldMetadataItemMutation = { __typename?: 'Mutation', createOneField: { __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isUnique?: boolean | null, isNullable?: boolean | null, createdAt: string, updatedAt: string, settings?: any | null, defaultValue?: any | null, options?: any | null, isLabelSyncedWithName?: boolean | null, applicationId: string, object?: { __typename?: 'Object', id: string } | null, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null } }; export type UpdateOneFieldMetadataItemMutationVariables = Exact<{ idToUpdate: Scalars['UUID']; @@ -7709,8 +7703,8 @@ export const DeleteNavigationMenuItemDocument = {"kind":"Document","definitions" export const UpdateNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateOneNavigationMenuItemInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const FindManyNavigationMenuItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyNavigationMenuItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"navigationMenuItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; export const FindOneNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"navigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; -export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}}]}}]}}]} as unknown as DocumentNode; -export const CreateOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneFieldMetadataInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"object"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"fieldsList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isUIReadOnly"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"morphId"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"relation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"morphRelations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneFieldMetadataInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"object"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"relation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"morphRelations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const UpdateOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateFieldInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"object"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; export const UpdateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateObjectPayload"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}}]}}]}}]} as unknown as DocumentNode; export const DeleteOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/metadata-store/effect-components/MetadataStoreSSEEffect.tsx b/packages/twenty-front/src/modules/metadata-store/effect-components/MetadataStoreSSEEffect.tsx index 8b9f9b9ca22..5cdf513fc5b 100644 --- a/packages/twenty-front/src/modules/metadata-store/effect-components/MetadataStoreSSEEffect.tsx +++ b/packages/twenty-front/src/modules/metadata-store/effect-components/MetadataStoreSSEEffect.tsx @@ -1,11 +1,14 @@ import { useListenToMetadataOperationBrowserEvent } from '@/browser-event/hooks/useListenToMetadataOperationBrowserEvent'; -import { patchMetadataStoreFromSSEEvent } from '@/metadata-store/utils/patchMetadataStoreFromSSEEvent'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; +import { type MetadataEntityKey } from '@/metadata-store/states/metadataStoreState'; +import { type MetadataEntityTypeMap } from '@/metadata-store/types/MetadataEntityTypeMap'; import { mapAllMetadataNameToEntityKey } from '@/metadata-store/utils/mapAllMetadataNameToEntityKey'; -import { useStore } from 'jotai'; import { isDefined } from 'twenty-shared/utils'; +type AnyMetadataEntity = MetadataEntityTypeMap[MetadataEntityKey]; + export const MetadataStoreSSEEffect = () => { - const store = useStore(); + const { addToDraft, removeFromDraft, applyChanges } = useMetadataStore(); useListenToMetadataOperationBrowserEvent({ onMetadataOperationBrowserEvent: (eventDetail) => { @@ -15,12 +18,42 @@ export const MetadataStoreSSEEffect = () => { return; } - patchMetadataStoreFromSSEEvent({ - store, - entityKey, - operation: eventDetail.operation, - updatedCollectionHash: eventDetail.updatedCollectionHash, - }); + const collectionHash = eventDetail.updatedCollectionHash; + + switch (eventDetail.operation.type) { + case 'create': { + addToDraft({ + key: entityKey, + items: [ + eventDetail.operation + .createdRecord as unknown as AnyMetadataEntity, + ], + collectionHash, + }); + break; + } + case 'update': { + addToDraft({ + key: entityKey, + items: [ + eventDetail.operation + .updatedRecord as unknown as AnyMetadataEntity, + ], + collectionHash, + }); + break; + } + case 'delete': { + removeFromDraft({ + key: entityKey, + itemIds: [eventDetail.operation.deletedRecordId], + collectionHash, + }); + break; + } + } + + applyChanges(); }, }); diff --git a/packages/twenty-front/src/modules/metadata-store/hooks/useLoadMockedMinimalMetadata.ts b/packages/twenty-front/src/modules/metadata-store/hooks/useLoadMockedMinimalMetadata.ts index f07c0414034..d3cc2468a64 100644 --- a/packages/twenty-front/src/modules/metadata-store/hooks/useLoadMockedMinimalMetadata.ts +++ b/packages/twenty-front/src/modules/metadata-store/hooks/useLoadMockedMinimalMetadata.ts @@ -6,7 +6,7 @@ import { useCallback } from 'react'; const MOCKED_COLLECTION_HASH = 'mocked'; export const useLoadMockedMinimalMetadata = () => { - const { updateDraft, applyChanges, resetMetadataStore } = useMetadataStore(); + const { replaceDraft, applyChanges, resetMetadataStore } = useMetadataStore(); const loadMockedMinimalMetadata = useCallback(async () => { resetMetadataStore(); @@ -25,9 +25,9 @@ export const useLoadMockedMinimalMetadata = () => { const { flatObjects, flatFields, flatIndexes } = splitObjectMetadataItemWithRelated(generatedMockObjectMetadataItems); - updateDraft('objectMetadataItems', flatObjects, MOCKED_COLLECTION_HASH); - updateDraft('fieldMetadataItems', flatFields, MOCKED_COLLECTION_HASH); - updateDraft('indexMetadataItems', flatIndexes, MOCKED_COLLECTION_HASH); + replaceDraft('objectMetadataItems', flatObjects, MOCKED_COLLECTION_HASH); + replaceDraft('fieldMetadataItems', flatFields, MOCKED_COLLECTION_HASH); + replaceDraft('indexMetadataItems', flatIndexes, MOCKED_COLLECTION_HASH); const { flatViews, @@ -39,26 +39,30 @@ export const useLoadMockedMinimalMetadata = () => { flatViewFieldGroups, } = splitViewWithRelated(mockedViews); - updateDraft('views', flatViews, MOCKED_COLLECTION_HASH); - updateDraft('viewFields', flatViewFields, MOCKED_COLLECTION_HASH); - updateDraft('viewFilters', flatViewFilters, MOCKED_COLLECTION_HASH); - updateDraft('viewSorts', flatViewSorts, MOCKED_COLLECTION_HASH); - updateDraft('viewGroups', flatViewGroups, MOCKED_COLLECTION_HASH); - updateDraft( + replaceDraft('views', flatViews, MOCKED_COLLECTION_HASH); + replaceDraft('viewFields', flatViewFields, MOCKED_COLLECTION_HASH); + replaceDraft('viewFilters', flatViewFilters, MOCKED_COLLECTION_HASH); + replaceDraft('viewSorts', flatViewSorts, MOCKED_COLLECTION_HASH); + replaceDraft('viewGroups', flatViewGroups, MOCKED_COLLECTION_HASH); + replaceDraft( 'viewFilterGroups', flatViewFilterGroups, MOCKED_COLLECTION_HASH, ); - updateDraft('viewFieldGroups', flatViewFieldGroups, MOCKED_COLLECTION_HASH); + replaceDraft( + 'viewFieldGroups', + flatViewFieldGroups, + MOCKED_COLLECTION_HASH, + ); - updateDraft( + replaceDraft( 'navigationMenuItems', mockedNavigationMenuItems, MOCKED_COLLECTION_HASH, ); applyChanges(); - }, [updateDraft, applyChanges, resetMetadataStore]); + }, [replaceDraft, applyChanges, resetMetadataStore]); return { loadMockedMinimalMetadata }; }; diff --git a/packages/twenty-front/src/modules/metadata-store/hooks/useLoadStaleMetadataEntities.ts b/packages/twenty-front/src/modules/metadata-store/hooks/useLoadStaleMetadataEntities.ts index 7eed79f3e67..046ec790578 100644 --- a/packages/twenty-front/src/modules/metadata-store/hooks/useLoadStaleMetadataEntities.ts +++ b/packages/twenty-front/src/modules/metadata-store/hooks/useLoadStaleMetadataEntities.ts @@ -54,7 +54,7 @@ const hasOverlap = ( export const useLoadStaleMetadataEntities = () => { const client = useApolloClient(); const store = useStore(); - const { updateDraft, applyChanges } = useMetadataStore(); + const { replaceDraft, applyChanges } = useMetadataStore(); const loadStaleMetadataEntities = useCallback( async (staleEntityKeys: MetadataEntityKey[]) => { @@ -80,9 +80,9 @@ export const useLoadStaleMetadataEntities = () => { const { flatObjects, flatFields, flatIndexes } = splitObjectMetadataItemWithRelated(compositeObjects); - updateDraft('objectMetadataItems', flatObjects); - updateDraft('fieldMetadataItems', flatFields); - updateDraft('indexMetadataItems', flatIndexes); + replaceDraft('objectMetadataItems', flatObjects); + replaceDraft('fieldMetadataItems', flatFields); + replaceDraft('indexMetadataItems', flatIndexes); }), ); } @@ -116,13 +116,13 @@ export const useLoadStaleMetadataEntities = () => { flatViewFieldGroups, } = splitViewWithRelated(allViews); - updateDraft('views', flatViews); - updateDraft('viewFields', flatViewFields); - updateDraft('viewFilters', flatViewFilters); - updateDraft('viewSorts', flatViewSorts); - updateDraft('viewGroups', flatViewGroups); - updateDraft('viewFilterGroups', flatViewFilterGroups); - updateDraft('viewFieldGroups', flatViewFieldGroups); + replaceDraft('views', flatViews); + replaceDraft('viewFields', flatViewFields); + replaceDraft('viewFilters', flatViewFilters); + replaceDraft('viewSorts', flatViewSorts); + replaceDraft('viewGroups', flatViewGroups); + replaceDraft('viewFilterGroups', flatViewFilterGroups); + replaceDraft('viewFieldGroups', flatViewFieldGroups); }), ); } @@ -148,9 +148,9 @@ export const useLoadStaleMetadataEntities = () => { flatPageLayoutWidgets, } = splitPageLayoutWithRelated(transformed); - updateDraft('pageLayouts', flatPageLayouts); - updateDraft('pageLayoutTabs', flatPageLayoutTabs); - updateDraft('pageLayoutWidgets', flatPageLayoutWidgets); + replaceDraft('pageLayouts', flatPageLayouts); + replaceDraft('pageLayoutTabs', flatPageLayoutTabs); + replaceDraft('pageLayoutWidgets', flatPageLayoutWidgets); }), ); } @@ -171,7 +171,10 @@ export const useLoadStaleMetadataEntities = () => { logicFunctionsState.atom, result.data.findManyLogicFunctions, ); - updateDraft('logicFunctions', result.data.findManyLogicFunctions); + replaceDraft( + 'logicFunctions', + result.data.findManyLogicFunctions, + ); }), ); } @@ -188,7 +191,7 @@ export const useLoadStaleMetadataEntities = () => { return; } - updateDraft( + replaceDraft( 'navigationMenuItems', result.data.navigationMenuItems, ); @@ -199,7 +202,7 @@ export const useLoadStaleMetadataEntities = () => { await Promise.all(fetchPromises); applyChanges(); }, - [client, store, updateDraft, applyChanges], + [client, store, replaceDraft, applyChanges], ); return { loadStaleMetadataEntities }; diff --git a/packages/twenty-front/src/modules/metadata-store/hooks/useMetadataStore.ts b/packages/twenty-front/src/modules/metadata-store/hooks/useMetadataStore.ts index f3d3f9e5b22..7b1059a2728 100644 --- a/packages/twenty-front/src/modules/metadata-store/hooks/useMetadataStore.ts +++ b/packages/twenty-front/src/modules/metadata-store/hooks/useMetadataStore.ts @@ -8,6 +8,7 @@ import { import { type MetadataEntityTypeMap } from '@/metadata-store/types/MetadataEntityTypeMap'; import { useStore, type createStore } from 'jotai'; import { useCallback } from 'react'; +import { isDefined } from 'twenty-shared/utils'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; type JotaiStore = ReturnType; @@ -58,7 +59,7 @@ const changeMetadataEntityAsUpToDate = ( export const useMetadataStore = () => { const store = useStore(); - const updateDraft = useCallback( + const replaceDraft = useCallback( ( key: K, data: MetadataEntityTypeMap[K][], @@ -123,9 +124,159 @@ export const useMetadataStore = () => { return { hasPersistedAnyMetadataEntity }; }, [store]); + const addToDraft = useCallback( + ({ + key, + items, + collectionHash, + }: { + key: K; + items: MetadataEntityTypeMap[K][]; + collectionHash?: string; + }) => { + if (items.length === 0) { + return; + } + + const entry = store.get(metadataStoreState.atomFamily(key)); + const baseItems = ( + entry.status === 'draft-pending' ? entry.draft : entry.current + ) as Array<{ id: string }>; + + let newItems = [...baseItems]; + + for (const item of items) { + const newItem = item as unknown as { id: string }; + const existingIndex = newItems.findIndex( + (existing) => existing.id === newItem.id, + ); + + if (existingIndex >= 0) { + if (!isDeeplyEqual(newItems[existingIndex], newItem)) { + newItems[existingIndex] = newItem; + } + } else { + newItems = [...newItems, newItem]; + } + } + + store.set(metadataStoreState.atomFamily(key), { + ...entry, + draft: newItems, + status: 'draft-pending' as const, + ...(collectionHash !== undefined + ? { draftCollectionHash: collectionHash } + : {}), + }); + }, + [store], + ); + + const updateInDraft = useCallback( + ( + key: K, + items: MetadataEntityTypeMap[K][], + collectionHash?: string, + ) => { + if (items.length === 0) { + return; + } + + const entry = store.get(metadataStoreState.atomFamily(key)); + const baseItems = ( + entry.status === 'draft-pending' ? entry.draft : entry.current + ) as Array<{ id: string }>; + + let hasChanged = false; + const newItems = baseItems.map((existing) => { + const updatedItem = (items as unknown as Array<{ id: string }>).find( + (item) => item.id === existing.id, + ); + + if (!isDefined(updatedItem)) { + return existing; + } + + const merged = { ...existing, ...updatedItem }; + + if (isDeeplyEqual(existing, merged)) { + return existing; + } + + hasChanged = true; + + return merged; + }); + + if (!hasChanged && collectionHash === undefined) { + return; + } + + store.set(metadataStoreState.atomFamily(key), { + ...entry, + draft: hasChanged ? newItems : baseItems, + status: 'draft-pending' as const, + ...(collectionHash !== undefined + ? { draftCollectionHash: collectionHash } + : {}), + }); + }, + [store], + ); + + const removeFromDraft = useCallback( + ({ + key, + itemIds, + collectionHash, + }: { + key: K; + itemIds: string[]; + collectionHash?: string; + }) => { + if (itemIds.length === 0) { + return; + } + + const entry = store.get(metadataStoreState.atomFamily(key)); + const baseItems = ( + entry.status === 'draft-pending' ? entry.draft : entry.current + ) as Array<{ id: string }>; + + const idsToDelete = new Set(itemIds); + const newItems = baseItems.filter( + (existing) => !idsToDelete.has(existing.id), + ); + + if ( + newItems.length === baseItems.length && + collectionHash === undefined + ) { + return; + } + + store.set(metadataStoreState.atomFamily(key), { + ...entry, + draft: newItems, + status: 'draft-pending' as const, + ...(collectionHash !== undefined + ? { draftCollectionHash: collectionHash } + : {}), + }); + }, + [store], + ); + const reset = useCallback(() => { resetMetadataStore(store); }, [store]); - return { updateDraft, applyChanges, resetMetadataStore: reset }; + return { + replaceDraft, + applyChanges, + addToDraft, + updateInDraft, + removeFromDraft, + resetMetadataStore: reset, + }; }; diff --git a/packages/twenty-front/src/modules/metadata-store/utils/patchMetadataStoreFromSSEEvent.ts b/packages/twenty-front/src/modules/metadata-store/utils/patchMetadataStoreFromSSEEvent.ts deleted file mode 100644 index a97e21bbd26..00000000000 --- a/packages/twenty-front/src/modules/metadata-store/utils/patchMetadataStoreFromSSEEvent.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - metadataStoreState, - type MetadataEntityKey, -} from '@/metadata-store/states/metadataStoreState'; -import { type createStore } from 'jotai'; -import { isDefined } from 'twenty-shared/utils'; - -type JotaiStore = ReturnType; - -type SSEEventOperation = - | { - type: 'create'; - createdRecord: Record; - } - | { - type: 'update'; - updatedRecord: Record; - } - | { - type: 'delete'; - deletedRecordId: string; - }; - -export const patchMetadataStoreFromSSEEvent = ({ - store, - entityKey, - operation, - updatedCollectionHash, -}: { - store: JotaiStore; - entityKey: MetadataEntityKey; - operation: SSEEventOperation; - updatedCollectionHash?: string; -}) => { - const entry = store.get(metadataStoreState.atomFamily(entityKey)); - const currentItems = entry.current as Array<{ id: string }>; - - const hashUpdate = isDefined(updatedCollectionHash) - ? { currentCollectionHash: updatedCollectionHash } - : {}; - - switch (operation.type) { - case 'create': { - store.set(metadataStoreState.atomFamily(entityKey), { - ...entry, - ...hashUpdate, - current: [...currentItems, operation.createdRecord], - }); - break; - } - case 'update': { - store.set(metadataStoreState.atomFamily(entityKey), { - ...entry, - ...hashUpdate, - current: currentItems.map((item) => - item.id === (operation.updatedRecord as { id: string }).id - ? { ...item, ...operation.updatedRecord } - : item, - ), - }); - break; - } - case 'delete': { - store.set(metadataStoreState.atomFamily(entityKey), { - ...entry, - ...hashUpdate, - current: currentItems.filter( - (item) => item.id !== operation.deletedRecordId, - ), - }); - break; - } - } -}; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts index b44d9014453..c81d04e1b6c 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts @@ -1,12 +1,12 @@ +import { useMutation } from '@apollo/client/react'; import { NavigationMenuItemType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { useMutation } from '@apollo/client/react'; import { CreateNavigationMenuItemDocument } from '~/generated-metadata/graphql'; import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData'; import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector'; -import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; export const useCreateNavigationMenuItem = () => { const { navigationMenuItems, currentWorkspaceMemberId } = diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useRemoveNavigationMenuItemByTargetRecordId.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useRemoveNavigationMenuItemByTargetRecordId.ts index 91059ccae56..e3ad891dbff 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useRemoveNavigationMenuItemByTargetRecordId.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useRemoveNavigationMenuItemByTargetRecordId.ts @@ -14,7 +14,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => { const store = useStore(); const apolloCoreClient = useApolloCoreClient(); const cache = apolloCoreClient.cache; - const { updateDraft, applyChanges } = useMetadataStore(); + const { replaceDraft, applyChanges } = useMetadataStore(); const removeNavigationMenuItemsByTargetRecordIds = useCallback( (targetRecordIds: string[]) => { @@ -31,7 +31,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => { !targetRecordIdsSet.has(item.targetRecordId), ); - updateDraft('navigationMenuItems', updatedNavigationMenuItems); + replaceDraft('navigationMenuItems', updatedNavigationMenuItems); applyChanges(); cache.updateQuery( @@ -48,7 +48,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => { }, ); }, - [cache, store, updateDraft, applyChanges], + [cache, store, replaceDraft, applyChanges], ); return { diff --git a/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts b/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts index 2d84a94d89c..13ea6e39701 100644 --- a/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts +++ b/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts @@ -19,6 +19,71 @@ export const CREATE_ONE_OBJECT_METADATA_ITEM = gql` labelIdentifierFieldMetadataId imageIdentifierFieldMetadataId isLabelSyncedWithName + fieldsList { + id + universalIdentifier + type + name + label + description + icon + isCustom + isActive + isSystem + isUIReadOnly + isNullable + isUnique + createdAt + updatedAt + defaultValue + options + settings + isLabelSyncedWithName + morphId + applicationId + relation { + type + sourceObjectMetadata { + id + nameSingular + namePlural + } + targetObjectMetadata { + id + nameSingular + namePlural + } + sourceFieldMetadata { + id + name + } + targetFieldMetadata { + id + name + } + } + morphRelations { + type + sourceObjectMetadata { + id + nameSingular + namePlural + } + targetObjectMetadata { + id + nameSingular + namePlural + } + sourceFieldMetadata { + id + name + } + targetFieldMetadata { + id + name + } + } + } } } `; @@ -46,6 +111,48 @@ export const CREATE_ONE_FIELD_METADATA_ITEM = gql` object { id } + relation { + type + sourceObjectMetadata { + id + nameSingular + namePlural + } + targetObjectMetadata { + id + nameSingular + namePlural + } + sourceFieldMetadata { + id + name + } + targetFieldMetadata { + id + name + } + } + morphRelations { + type + sourceObjectMetadata { + id + nameSingular + namePlural + } + targetObjectMetadata { + id + nameSingular + namePlural + } + sourceFieldMetadata { + id + name + } + targetFieldMetadata { + id + name + } + } } } `; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useCreateOneObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useCreateOneObjectMetadataItem.ts index 5f2bded309a..72fe17ca8c4 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useCreateOneObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useCreateOneObjectMetadataItem.ts @@ -1,5 +1,6 @@ import { CreateOneObjectMetadataItemDocument, + FindManyNavigationMenuItemsDocument, FindManyViewsDocument, } from '~/generated-metadata/graphql'; @@ -7,6 +8,9 @@ export const query = CreateOneObjectMetadataItemDocument; export const findManyViewsQuery = FindManyViewsDocument; +export const findManyNavigationMenuItemsQuery = + FindManyNavigationMenuItemsDocument; + export const variables = { input: { object: { @@ -35,4 +39,6 @@ export const responseData = { updatedAt: '', labelIdentifierFieldMetadataId: '20202020-72ba-4e11-a36d-e17b544541e1', imageIdentifierFieldMetadataId: '', + isLabelSyncedWithName: false, + fieldsList: [], }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneObjectMetadataItem.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneObjectMetadataItem.test.tsx index faa2860e72e..860f9a90416 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneObjectMetadataItem.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneObjectMetadataItem.test.tsx @@ -4,6 +4,7 @@ import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreat import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; import { + findManyNavigationMenuItemsQuery, findManyViewsQuery, query, responseData, @@ -63,6 +64,17 @@ const mocks = [ }, })), }, + { + request: { + query: findManyNavigationMenuItemsQuery, + variables: {}, + }, + result: jest.fn(() => ({ + data: { + navigationMenuItems: [], + }, + })), + }, ]; const Wrapper = getJestMetadataAndApolloMocksWrapper({ diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneFieldMetadataItem.ts index 79a93a05f91..e305a25b381 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneFieldMetadataItem.ts @@ -5,10 +5,13 @@ import { } from '~/generated-metadata/graphql'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; +import { type FlatFieldMetadataItem } from '@/metadata-store/types/FlatFieldMetadataItem'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; import { CrudOperationType } from 'twenty-shared/types'; export const useCreateOneFieldMetadataItem = () => { @@ -18,6 +21,7 @@ export const useCreateOneFieldMetadataItem = () => { const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { addToDraft, applyChanges } = useMetadataStore(); const createOneFieldMetadataItem = async ( input: CreateFieldInput, @@ -35,6 +39,23 @@ export const useCreateOneFieldMetadataItem = () => { }, }); + const createdField = response.data?.createOneField; + + if (isDefined(createdField)) { + const { __typename, object, ...fieldData } = createdField; + + addToDraft({ + key: 'fieldMetadataItems', + items: [ + { + ...fieldData, + objectMetadataId: object?.id ?? input.objectMetadataId, + } as FlatFieldMetadataItem, + ], + }); + applyChanges(); + } + return { status: 'successful', response, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts index 1784e12ed45..5516f8de798 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useCreateOneObjectMetadataItem.ts @@ -1,22 +1,32 @@ -import { useMutation } from '@apollo/client/react'; +import { useApolloClient, useMutation } from '@apollo/client/react'; import { type CreateObjectInput, CreateOneObjectMetadataItemDocument, + FindManyNavigationMenuItemsDocument, + FindManyViewsDocument, } from '~/generated-metadata/graphql'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; +import { type FlatFieldMetadataItem } from '@/metadata-store/types/FlatFieldMetadataItem'; +import { type FlatObjectMetadataItem } from '@/metadata-store/types/FlatObjectMetadataItem'; +import { splitViewWithRelated } from '@/metadata-store/utils/splitViewWithRelated'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { t } from '@lingui/core/macro'; import { CrudOperationType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + export const useCreateOneObjectMetadataItem = () => { const [createOneObjectMetadataItemMutation] = useMutation( CreateOneObjectMetadataItemDocument, ); + const client = useApolloClient(); const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { addToDraft, replaceDraft, applyChanges } = useMetadataStore(); const createOneObjectMetadataItem = async ( input: CreateObjectInput, @@ -32,6 +42,73 @@ export const useCreateOneObjectMetadataItem = () => { }, }); + const createdObject = createdObjectMetadata.data?.createOneObject; + + if (isDefined(createdObject)) { + const { + __typename: _objectTypename, + fieldsList, + ...objectData + } = createdObject; + + addToDraft({ + key: 'objectMetadataItems', + items: [objectData as FlatObjectMetadataItem], + }); + + const flatFields = fieldsList.map((field) => { + const { __typename: _fieldTypename, ...fieldData } = field; + + return { + ...fieldData, + objectMetadataId: createdObject.id, + } as FlatFieldMetadataItem; + }); + + addToDraft({ key: 'fieldMetadataItems', items: flatFields }); + + applyChanges(); + + const [viewsResult, navItemsResult] = await Promise.all([ + client.query({ + query: FindManyViewsDocument, + variables: { objectMetadataId: createdObject.id }, + fetchPolicy: 'network-only', + }), + client.query({ + query: FindManyNavigationMenuItemsDocument, + fetchPolicy: 'network-only', + }), + ]); + + const fetchedViews = viewsResult.data?.getViews ?? []; + + const { + flatViews, + flatViewFields, + flatViewFilters, + flatViewSorts, + flatViewGroups, + flatViewFilterGroups, + flatViewFieldGroups, + } = splitViewWithRelated(fetchedViews); + + addToDraft({ key: 'views', items: flatViews }); + addToDraft({ key: 'viewFields', items: flatViewFields }); + addToDraft({ key: 'viewFilters', items: flatViewFilters }); + addToDraft({ key: 'viewSorts', items: flatViewSorts }); + addToDraft({ key: 'viewGroups', items: flatViewGroups }); + addToDraft({ key: 'viewFilterGroups', items: flatViewFilterGroups }); + addToDraft({ key: 'viewFieldGroups', items: flatViewFieldGroups }); + + replaceDraft( + 'navigationMenuItems', + navItemsResult.data?.navigationMenuItems ?? [], + ); + + applyChanges(); + } + return { status: 'successful', response: createdObjectMetadata, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneFieldMetadataItem.ts index a9f2982d63f..f931714844e 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneFieldMetadataItem.ts @@ -3,6 +3,7 @@ import { DeleteOneFieldMetadataItemDocument } from '~/generated-metadata/graphql import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { recordIndexGroupAggregateFieldMetadataItemComponentState } from '@/object-record/record-index/states/recordIndexGroupAggregateFieldMetadataItemComponentState'; import { recordIndexGroupAggregateOperationComponentState } from '@/object-record/record-index/states/recordIndexGroupAggregateOperationComponentState'; @@ -21,6 +22,7 @@ export const useDeleteOneFieldMetadataItem = () => { const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { removeFromDraft, applyChanges } = useMetadataStore(); const setRecordIndexGroupAggregateOperation = useSetAtomComponentState( recordIndexGroupAggregateOperationComponentState, @@ -63,7 +65,10 @@ export const useDeleteOneFieldMetadataItem = () => { }, }); - // TODO: see if we can remove this lin altogether + removeFromDraft({ key: 'fieldMetadataItems', itemIds: [idToDelete] }); + applyChanges(); + + // TODO: see if we can remove this line altogether await resetRecordIndexKanbanAggregateOperation(idToDelete); return { diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts index 1d3a3926ae8..aa94d7ecb13 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts @@ -2,6 +2,7 @@ import { useMutation } from '@apollo/client/react'; import { DeleteOneObjectMetadataItemDocument } from '~/generated-metadata/graphql'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; @@ -15,6 +16,7 @@ export const useDeleteOneObjectMetadataItem = () => { const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { removeFromDraft, applyChanges } = useMetadataStore(); const deleteOneObjectMetadataItem = async ( idToDelete: string, @@ -30,6 +32,9 @@ export const useDeleteOneObjectMetadataItem = () => { }, }); + removeFromDraft({ key: 'objectMetadataItems', itemIds: [idToDelete] }); + applyChanges(); + return { status: 'successful', response, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useLoadMockedObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useLoadMockedObjectMetadataItems.ts index 31481e3749e..9fe370a6d77 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useLoadMockedObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useLoadMockedObjectMetadataItems.ts @@ -3,7 +3,7 @@ import { splitObjectMetadataItemWithRelated } from '@/metadata-store/utils/split import { useCallback } from 'react'; export const useLoadMockedObjectMetadataItems = () => { - const { updateDraft, applyChanges } = useMetadataStore(); + const { replaceDraft, applyChanges } = useMetadataStore(); const loadMockedObjectMetadataItems = useCallback(async () => { const { generatedMockObjectMetadataItems } = await import( @@ -13,11 +13,11 @@ export const useLoadMockedObjectMetadataItems = () => { const { flatObjects, flatFields, flatIndexes } = splitObjectMetadataItemWithRelated(generatedMockObjectMetadataItems); - updateDraft('objectMetadataItems', flatObjects); - updateDraft('fieldMetadataItems', flatFields); - updateDraft('indexMetadataItems', flatIndexes); + replaceDraft('objectMetadataItems', flatObjects); + replaceDraft('fieldMetadataItems', flatFields); + replaceDraft('indexMetadataItems', flatIndexes); applyChanges(); - }, [updateDraft, applyChanges]); + }, [replaceDraft, applyChanges]); return { loadMockedObjectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts index 695eb898ef9..fccf6a91e72 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts @@ -5,12 +5,15 @@ import { } from '~/generated-metadata/graphql'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; +import { type FlatFieldMetadataItem } from '@/metadata-store/types/FlatFieldMetadataItem'; import { lastFieldMetadataItemUpdateState } from '@/object-metadata/states/lastFieldMetadataItemUpdateState'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; import { CrudOperationType } from 'twenty-shared/types'; import { v4 as uuidv4 } from 'uuid'; @@ -22,6 +25,7 @@ export const useUpdateOneFieldMetadataItem = () => { const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { updateInDraft, applyChanges } = useMetadataStore(); const setLastFieldMetadataItemUpdate = useSetAtomState( lastFieldMetadataItemUpdateState, @@ -58,6 +62,20 @@ export const useUpdateOneFieldMetadataItem = () => { }, }); + const updatedField = response.data?.updateOneField; + + if (isDefined(updatedField)) { + const { __typename, object, ...fieldData } = updatedField; + + updateInDraft('fieldMetadataItems', [ + { + ...fieldData, + objectMetadataId: object?.id ?? objectMetadataId, + } as FlatFieldMetadataItem, + ]); + applyChanges(); + } + setLastFieldMetadataItemUpdate({ fieldMetadataItemId: fieldMetadataIdToUpdate, objectMetadataId, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts index 4cd8c26f972..e9ac7039b5a 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts @@ -5,10 +5,13 @@ import { } from '~/generated-metadata/graphql'; import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; +import { type FlatObjectMetadataItem } from '@/metadata-store/types/FlatObjectMetadataItem'; import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; import { CrudOperationType } from 'twenty-shared/types'; // TODO: Slice the Apollo store synchronously in the update function instead of subscribing, so we can use update after read in the same function call @@ -19,6 +22,7 @@ export const useUpdateOneObjectMetadataItem = () => { const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); + const { updateInDraft, applyChanges } = useMetadataStore(); const updateOneObjectMetadataItem = async ({ idToUpdate, @@ -39,6 +43,17 @@ export const useUpdateOneObjectMetadataItem = () => { }, }); + const updatedObject = response.data?.updateOneObject; + + if (isDefined(updatedObject)) { + const { __typename, ...objectData } = updatedObject; + + updateInDraft('objectMetadataItems', [ + objectData as FlatObjectMetadataItem, + ]); + applyChanges(); + } + return { status: 'successful', response, diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx index ddd2f29fa08..eca14501e57 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx @@ -53,7 +53,7 @@ const RelationFieldValueSetterEffect = () => { 'recordTableId', ); - const { updateDraft, applyChanges } = useMetadataStore(); + const { replaceDraft, applyChanges } = useMetadataStore(); useEffect(() => { setRecordStore(mockPerformance.entityValue); @@ -74,14 +74,14 @@ const RelationFieldValueSetterEffect = () => { const { flatObjects, flatFields, flatIndexes } = splitObjectMetadataItemWithRelated(generatedMockObjectMetadataItems); - updateDraft('objectMetadataItems', flatObjects); - updateDraft('fieldMetadataItems', flatFields); - updateDraft('indexMetadataItems', flatIndexes); + replaceDraft('objectMetadataItems', flatObjects); + replaceDraft('fieldMetadataItems', flatFields); + replaceDraft('indexMetadataItems', flatIndexes); applyChanges(); }, [ setRecordStore, setRelationRecordStore, - updateDraft, + replaceDraft, applyChanges, setCurrentRecordFields, ]); diff --git a/packages/twenty-front/src/modules/sse-db-event/graphql/subscriptions/OnEventSubscription.ts b/packages/twenty-front/src/modules/sse-db-event/graphql/subscriptions/OnEventSubscription.ts index 65ad4eed666..85b2af8cd24 100644 --- a/packages/twenty-front/src/modules/sse-db-event/graphql/subscriptions/OnEventSubscription.ts +++ b/packages/twenty-front/src/modules/sse-db-event/graphql/subscriptions/OnEventSubscription.ts @@ -20,19 +20,17 @@ export const ON_EVENT_SUBSCRIPTION = gql` } queryIds } - metadataEventsWithQueryIds { - metadataEvent { - type - metadataName - recordId - properties { - updatedFields - before - after - diff - } + metadataEvents { + type + metadataName + recordId + updatedCollectionHash + properties { + updatedFields + before + after + diff } - queryIds } } } diff --git a/packages/twenty-front/src/modules/sse-db-event/hooks/useDispatchMetadataEventsFromSseToBrowserEvents.ts b/packages/twenty-front/src/modules/sse-db-event/hooks/useDispatchMetadataEventsFromSseToBrowserEvents.ts index e50481eef3b..b74b1f126d1 100644 --- a/packages/twenty-front/src/modules/sse-db-event/hooks/useDispatchMetadataEventsFromSseToBrowserEvents.ts +++ b/packages/twenty-front/src/modules/sse-db-event/hooks/useDispatchMetadataEventsFromSseToBrowserEvents.ts @@ -4,7 +4,6 @@ import { useCallback } from 'react'; import { type AllMetadataName, type MetadataEvent, - type MetadataEventWithQueryIds, } from '~/generated-metadata/graphql'; const groupSseMetadataEventsByMetadataName = ( @@ -27,13 +26,9 @@ export const useDispatchMetadataEventsFromSseToBrowserEvents = < T extends Record, >() => { const dispatchMetadataEventsFromSseToBrowserEvents = useCallback( - (metadataEventsWithQueryIds: MetadataEventWithQueryIds[]) => { - const sseMetadataEvents = metadataEventsWithQueryIds.map( - (item) => item.metadataEvent, - ); - + (metadataEvents: MetadataEvent[]) => { const eventsByMetadataName = - groupSseMetadataEventsByMetadataName(sseMetadataEvents); + groupSseMetadataEventsByMetadataName(metadataEvents); for (const [metadataName, events] of eventsByMetadataName) { const metadataOperationBrowserEvents = diff --git a/packages/twenty-front/src/modules/sse-db-event/hooks/useTriggerEventStreamCreation.ts b/packages/twenty-front/src/modules/sse-db-event/hooks/useTriggerEventStreamCreation.ts index 9e482072aea..697d20ef92b 100644 --- a/packages/twenty-front/src/modules/sse-db-event/hooks/useTriggerEventStreamCreation.ts +++ b/packages/twenty-front/src/modules/sse-db-event/hooks/useTriggerEventStreamCreation.ts @@ -98,8 +98,7 @@ export const useTriggerEventStreamCreation = () => { const objectRecordEventsWithQueryIds = eventSubscription?.objectRecordEventsWithQueryIds ?? []; - const metadataEventsWithQueryIds = - eventSubscription?.metadataEventsWithQueryIds ?? []; + const metadataEvents = eventSubscription?.metadataEvents ?? []; const objectRecordEvents = objectRecordEventsWithQueryIds.map( (item) => item.objectRecordEvent, @@ -113,9 +112,7 @@ export const useTriggerEventStreamCreation = () => { objectRecordEventsWithQueryIds, ); - dispatchMetadataEventsFromSseToBrowserEvents( - metadataEventsWithQueryIds, - ); + dispatchMetadataEventsFromSseToBrowserEvents(metadataEvents); }, error: (error) => { captureException(error); @@ -169,6 +166,11 @@ export const useTriggerEventStreamCreation = () => { dispatchObjectRecordEventsFromSseToBrowserEvents( objectRecordEventsWithQueryIds, ); + + const metadataEvents = + result?.data?.onEventSubscription?.metadataEvents ?? []; + + dispatchMetadataEventsFromSseToBrowserEvents(metadataEvents); } } } catch (error) { diff --git a/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx b/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx index 9c351e924a7..9d5c8a4c3eb 100644 --- a/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx +++ b/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx @@ -12,7 +12,7 @@ export const JestObjectMetadataItemSetter = ({ children: ReactNode; objectMetadataItems?: ObjectMetadataItem[]; }) => { - const { updateDraft, applyChanges } = useMetadataStore(); + const { replaceDraft, applyChanges } = useMetadataStore(); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { @@ -20,12 +20,12 @@ export const JestObjectMetadataItemSetter = ({ const { flatObjects, flatFields, flatIndexes } = splitObjectMetadataItemWithRelated(items); - updateDraft('objectMetadataItems', flatObjects); - updateDraft('fieldMetadataItems', flatFields); - updateDraft('indexMetadataItems', flatIndexes); + replaceDraft('objectMetadataItems', flatObjects); + replaceDraft('fieldMetadataItems', flatFields); + replaceDraft('indexMetadataItems', flatIndexes); applyChanges(); setIsLoaded(true); - }, [objectMetadataItems, updateDraft, applyChanges]); + }, [objectMetadataItems, replaceDraft, applyChanges]); return isLoaded ? <>{children} : null; }; diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql index a8914e77931..e44873e0ec3 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql @@ -1282,15 +1282,10 @@ type ObjectRecordEventWithQueryIds { objectRecordEvent: ObjectRecordEvent! } -type MetadataEventWithQueryIds { - queryIds: [String!]! - metadataEvent: MetadataEvent! -} - type EventSubscription { eventStreamId: String! objectRecordEventsWithQueryIds: [ObjectRecordEventWithQueryIds!]! - metadataEventsWithQueryIds: [MetadataEventWithQueryIds!]! + metadataEvents: [MetadataEvent!]! } type OnDbEvent { diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts index cdfe7481ea8..ffcfb748d20 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts @@ -1004,16 +1004,10 @@ export interface ObjectRecordEventWithQueryIds { __typename: 'ObjectRecordEventWithQueryIds' } -export interface MetadataEventWithQueryIds { - queryIds: Scalars['String'][] - metadataEvent: MetadataEvent - __typename: 'MetadataEventWithQueryIds' -} - export interface EventSubscription { eventStreamId: Scalars['String'] objectRecordEventsWithQueryIds: ObjectRecordEventWithQueryIds[] - metadataEventsWithQueryIds: MetadataEventWithQueryIds[] + metadataEvents: MetadataEvent[] __typename: 'EventSubscription' } @@ -3941,17 +3935,10 @@ export interface ObjectRecordEventWithQueryIdsGenqlSelection{ __scalar?: boolean | number } -export interface MetadataEventWithQueryIdsGenqlSelection{ - queryIds?: boolean | number - metadataEvent?: MetadataEventGenqlSelection - __typename?: boolean | number - __scalar?: boolean | number -} - export interface EventSubscriptionGenqlSelection{ eventStreamId?: boolean | number objectRecordEventsWithQueryIds?: ObjectRecordEventWithQueryIdsGenqlSelection - metadataEventsWithQueryIds?: MetadataEventWithQueryIdsGenqlSelection + metadataEvents?: MetadataEventGenqlSelection __typename?: boolean | number __scalar?: boolean | number } @@ -6869,14 +6856,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null - const MetadataEventWithQueryIds_possibleTypes: string[] = ['MetadataEventWithQueryIds'] - export const isMetadataEventWithQueryIds = (obj?: { __typename?: any } | null): obj is MetadataEventWithQueryIds => { - if (!obj?.__typename) throw new Error('__typename is missing in "isMetadataEventWithQueryIds"') - return MetadataEventWithQueryIds_possibleTypes.includes(obj.__typename) - } - - - const EventSubscription_possibleTypes: string[] = ['EventSubscription'] export const isEventSubscription = (obj?: { __typename?: any } | null): obj is EventSubscription => { if (!obj?.__typename) throw new Error('__typename is missing in "isEventSubscription"') diff --git a/packages/twenty-sdk/src/clients/generated/metadata/types.ts b/packages/twenty-sdk/src/clients/generated/metadata/types.ts index ac4bf49b5d0..5125e822aad 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/types.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/types.ts @@ -40,43 +40,43 @@ export default { 112, 115, 117, + 125, 126, 127, - 128, - 130, - 138, + 129, + 137, + 153, 154, - 155, - 160, - 164, - 188, - 217, - 219, + 159, + 163, + 187, + 216, + 218, + 226, 227, - 228, - 238, + 237, + 245, 246, - 247, - 252, - 255, + 251, + 254, + 260, 261, - 262, - 264, - 269, + 263, + 268, + 273, 274, - 275, - 287, + 286, + 302, 303, - 304, - 327, + 326, + 333, 334, 335, - 336, - 338, - 347, - 394, - 457, - 458 + 337, + 346, + 393, + 456, + 457 ], "types": { "BillingProductDTO": { @@ -90,13 +90,13 @@ export default { 1 ], "metadata": [ - 125 + 124 ], "on_BillingLicensedProduct": [ - 134 + 133 ], "on_BillingMeteredProduct": [ - 135 + 134 ], "__typename": [ 1 @@ -780,10 +780,10 @@ export default { 3 ], "relation": [ - 187 + 186 ], "morphRelations": [ - 187 + 186 ], "object": [ 46 @@ -842,7 +842,7 @@ export default { 36 ], "objectMetadata": [ - 175, + 174, { "paging": [ 39, @@ -855,7 +855,7 @@ export default { } ], "indexFieldMetadatas": [ - 173, + 172, { "paging": [ 39, @@ -1100,7 +1100,7 @@ export default { 37 ], "fields": [ - 180, + 179, { "paging": [ 39, @@ -1113,7 +1113,7 @@ export default { } ], "indexMetadatas": [ - 178, + 177, { "paging": [ 39, @@ -1691,16 +1691,16 @@ export default { 49 ], "featureFlags": [ - 163 + 162 ], "billingSubscriptions": [ - 137 + 136 ], "currentBillingSubscription": [ - 137 + 136 ], "billingEntitlements": [ - 159 + 158 ], "hasValidEnterpriseKey": [ 6 @@ -1712,7 +1712,7 @@ export default { 6 ], "workspaceUrls": [ - 152 + 151 ], "workspaceCustomApplicationId": [ 1 @@ -1804,7 +1804,7 @@ export default { 20 ], "deletedWorkspaceMembers": [ - 158 + 157 ], "hasPassword": [ 6 @@ -1816,7 +1816,7 @@ export default { 17 ], "availableWorkspaces": [ - 157 + 156 ], "__typename": [ 1 @@ -2639,17 +2639,6 @@ export default { 1 ] }, - "MetadataEventWithQueryIds": { - "queryIds": [ - 1 - ], - "metadataEvent": [ - 114 - ], - "__typename": [ - 1 - ] - }, "EventSubscription": { "eventStreamId": [ 1 @@ -2657,8 +2646,8 @@ export default { "objectRecordEventsWithQueryIds": [ 118 ], - "metadataEventsWithQueryIds": [ - 119 + "metadataEvents": [ + 114 ], "__typename": [ 1 @@ -2711,7 +2700,7 @@ export default { 11 ], "items": [ - 123 + 122 ], "__typename": [ 1 @@ -2719,13 +2708,13 @@ export default { }, "BillingProductMetadata": { "planKey": [ - 126 + 125 ], "priceUsageBased": [ - 127 + 126 ], "productKey": [ - 128 + 127 ], "__typename": [ 1 @@ -2736,7 +2725,7 @@ export default { "BillingProductKey": {}, "BillingPriceLicensed": { "recurringInterval": [ - 130 + 129 ], "unitAmount": [ 11 @@ -2745,7 +2734,7 @@ export default { 1 ], "priceUsageType": [ - 127 + 126 ], "__typename": [ 1 @@ -2768,16 +2757,16 @@ export default { }, "BillingPriceMetered": { "tiers": [ - 131 + 130 ], "recurringInterval": [ - 130 + 129 ], "stripePriceId": [ 1 ], "priceUsageType": [ - 127 + 126 ], "__typename": [ 1 @@ -2794,7 +2783,7 @@ export default { 1 ], "metadata": [ - 125 + 124 ], "__typename": [ 1 @@ -2811,10 +2800,10 @@ export default { 1 ], "metadata": [ - 125 + 124 ], "prices": [ - 129 + 128 ], "__typename": [ 1 @@ -2831,10 +2820,10 @@ export default { 1 ], "metadata": [ - 125 + 124 ], "prices": [ - 132 + 131 ], "__typename": [ 1 @@ -2865,13 +2854,13 @@ export default { 3 ], "status": [ - 138 + 137 ], "interval": [ - 130 + 129 ], "billingSubscriptionItems": [ - 136 + 135 ], "currentPeriodEnd": [ 4 @@ -2880,7 +2869,7 @@ export default { 15 ], "phases": [ - 124 + 123 ], "__typename": [ 1 @@ -2889,7 +2878,7 @@ export default { "SubscriptionStatus": {}, "BillingEndTrialPeriod": { "status": [ - 138 + 137 ], "hasPaymentMethod": [ 6 @@ -2903,7 +2892,7 @@ export default { }, "BillingMeteredProductUsage": { "productKey": [ - 128 + 127 ], "periodStart": [ 4 @@ -2932,13 +2921,13 @@ export default { }, "BillingPlan": { "planKey": [ - 126 + 125 ], "licensedProducts": [ - 134 + 133 ], "meteredProducts": [ - 135 + 134 ], "__typename": [ 1 @@ -2954,10 +2943,10 @@ export default { }, "BillingUpdate": { "currentBillingSubscription": [ - 137 + 136 ], "billingSubscriptions": [ - 137 + 136 ], "__typename": [ 1 @@ -3073,7 +3062,7 @@ export default { 1 ], "result": [ - 149 + 148 ], "__typename": [ 1 @@ -3100,7 +3089,7 @@ export default { }, "SSOConnection": { "type": [ - 154 + 153 ], "id": [ 3 @@ -3112,7 +3101,7 @@ export default { 1 ], "status": [ - 155 + 154 ], "__typename": [ 1 @@ -3137,13 +3126,13 @@ export default { 1 ], "workspaceUrls": [ - 152 + 151 ], "logo": [ 1 ], "sso": [ - 153 + 152 ], "__typename": [ 1 @@ -3151,10 +3140,10 @@ export default { }, "AvailableWorkspaces": { "availableWorkspacesForSignIn": [ - 156 + 155 ], "availableWorkspacesForSignUp": [ - 156 + 155 ], "__typename": [ 1 @@ -3182,7 +3171,7 @@ export default { }, "BillingEntitlement": { "key": [ - 160 + 159 ], "value": [ 6 @@ -3220,7 +3209,7 @@ export default { 1 ], "records": [ - 161 + 160 ], "__typename": [ 1 @@ -3228,7 +3217,7 @@ export default { }, "FeatureFlag": { "key": [ - 164 + 163 ], "value": [ 6 @@ -3246,10 +3235,10 @@ export default { 1 ], "type": [ - 154 + 153 ], "status": [ - 155 + 154 ], "issuer": [ 1 @@ -3260,7 +3249,7 @@ export default { }, "AuthProviders": { "sso": [ - 165 + 164 ], "google": [ 6 @@ -3297,10 +3286,10 @@ export default { 3 ], "authProviders": [ - 166 + 165 ], "authBypassProviders": [ - 167 + 166 ], "logo": [ 1 @@ -3309,7 +3298,7 @@ export default { 1 ], "workspaceUrls": [ - 152 + 151 ], "__typename": [ 1 @@ -3345,10 +3334,10 @@ export default { }, "IndexConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 169 + 168 ], "__typename": [ 1 @@ -3367,10 +3356,10 @@ export default { }, "IndexIndexFieldMetadatasConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 172 + 171 ], "__typename": [ 1 @@ -3389,10 +3378,10 @@ export default { }, "IndexObjectMetadataConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 174 + 173 ], "__typename": [ 1 @@ -3411,10 +3400,10 @@ export default { }, "ObjectConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 174 + 173 ], "__typename": [ 1 @@ -3422,10 +3411,10 @@ export default { }, "ObjectIndexMetadatasConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 169 + 168 ], "__typename": [ 1 @@ -3444,10 +3433,10 @@ export default { }, "ObjectFieldsConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 179 + 178 ], "__typename": [ 1 @@ -3483,7 +3472,7 @@ export default { 1 ], "versionDistribution": [ - 182 + 181 ], "__typename": [ 1 @@ -3530,7 +3519,7 @@ export default { }, "Relation": { "type": [ - 188 + 187 ], "sourceObjectMetadata": [ 46 @@ -3551,10 +3540,10 @@ export default { "RelationType": {}, "FieldConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 179 + 178 ], "__typename": [ 1 @@ -3573,7 +3562,7 @@ export default { 3 ], "type": [ - 154 + 153 ], "issuer": [ 1 @@ -3582,7 +3571,7 @@ export default { 1 ], "status": [ - 155 + 154 ], "__typename": [ 1 @@ -3601,7 +3590,7 @@ export default { }, "FindAvailableSSOIDP": { "type": [ - 154 + 153 ], "id": [ 3 @@ -3613,10 +3602,10 @@ export default { 1 ], "status": [ - 155 + 154 ], "workspace": [ - 192 + 191 ], "__typename": [ 1 @@ -3627,7 +3616,7 @@ export default { 3 ], "type": [ - 154 + 153 ], "issuer": [ 1 @@ -3636,7 +3625,7 @@ export default { 1 ], "status": [ - 155 + 154 ], "__typename": [ 1 @@ -3687,10 +3676,10 @@ export default { }, "AuthTokenPair": { "accessOrWorkspaceAgnosticToken": [ - 199 + 198 ], "refreshToken": [ - 199 + 198 ], "__typename": [ 1 @@ -3698,10 +3687,10 @@ export default { }, "AvailableWorkspacesAndAccessTokens": { "tokens": [ - 200 + 199 ], "availableWorkspaces": [ - 157 + 156 ], "__typename": [ 1 @@ -3739,7 +3728,7 @@ export default { }, "WorkspaceUrlsAndId": { "workspaceUrls": [ - 152 + 151 ], "id": [ 3 @@ -3750,10 +3739,10 @@ export default { }, "SignUp": { "loginToken": [ - 199 + 198 ], "workspace": [ - 205 + 204 ], "__typename": [ 1 @@ -3761,7 +3750,7 @@ export default { }, "TransientToken": { "transientToken": [ - 199 + 198 ], "__typename": [ 1 @@ -3783,10 +3772,10 @@ export default { }, "VerifyEmailAndGetLoginToken": { "loginToken": [ - 199 + 198 ], "workspaceUrls": [ - 152 + 151 ], "__typename": [ 1 @@ -3802,7 +3791,7 @@ export default { }, "AuthTokens": { "tokens": [ - 200 + 199 ], "__typename": [ 1 @@ -3810,7 +3799,7 @@ export default { }, "LoginToken": { "loginToken": [ - 199 + 198 ], "__typename": [ 1 @@ -3869,7 +3858,7 @@ export default { 3 ], "type": [ - 217 + 216 ], "name": [ 1 @@ -3899,7 +3888,7 @@ export default { 4 ], "targetRecordIdentifier": [ - 215 + 214 ], "__typename": [ 1 @@ -3917,7 +3906,7 @@ export default { 11 ], "status": [ - 219 + 218 ], "error": [ 15 @@ -4078,10 +4067,10 @@ export default { }, "ApplicationTokenPair": { "applicationAccessToken": [ - 199 + 198 ], "applicationRefreshToken": [ - 199 + 198 ], "__typename": [ 1 @@ -4125,7 +4114,7 @@ export default { 6 ], "applicationTokenPair": [ - 224 + 223 ], "__typename": [ 1 @@ -4142,10 +4131,10 @@ export default { 3 ], "frontComponent": [ - 225 + 224 ], "engineComponentKey": [ - 227 + 226 ], "label": [ 1 @@ -4163,7 +4152,7 @@ export default { 6 ], "availabilityType": [ - 228 + 227 ], "hotKeys": [ 1 @@ -4241,7 +4230,7 @@ export default { 1 ], "parts": [ - 222 + 221 ], "createdAt": [ 4 @@ -4266,7 +4255,7 @@ export default { }, "AISystemPromptPreview": { "sections": [ - 231 + 230 ], "estimatedTokenCount": [ 21 @@ -4277,7 +4266,7 @@ export default { }, "AgentChatThreadEdge": { "node": [ - 229 + 228 ], "cursor": [ 40 @@ -4288,10 +4277,10 @@ export default { }, "AgentChatThreadConnection": { "pageInfo": [ - 170 + 169 ], "edges": [ - 233 + 232 ], "__typename": [ 1 @@ -4328,10 +4317,10 @@ export default { 3 ], "evaluations": [ - 235 + 234 ], "messages": [ - 230 + 229 ], "createdAt": [ 4 @@ -4342,7 +4331,7 @@ export default { }, "CollectionHash": { "collectionName": [ - 238 + 237 ], "hash": [ 1 @@ -4409,13 +4398,13 @@ export default { }, "MinimalMetadata": { "objectMetadataItems": [ - 239 + 238 ], "views": [ - 240 + 239 ], "collectionHashes": [ - 237 + 236 ], "__typename": [ 1 @@ -4483,10 +4472,10 @@ export default { 1 ], "modelFamily": [ - 246 + 245 ], "inferenceProvider": [ - 247 + 246 ], "inputCostPerMillionTokensInCredits": [ 11 @@ -4495,7 +4484,7 @@ export default { 11 ], "nativeCapabilities": [ - 244 + 243 ], "deprecated": [ 6 @@ -4517,10 +4506,10 @@ export default { 1 ], "modelFamily": [ - 246 + 245 ], "inferenceProvider": [ - 247 + 246 ], "isAvailable": [ 6 @@ -4543,7 +4532,7 @@ export default { 6 ], "models": [ - 248 + 247 ], "__typename": [ 1 @@ -4557,7 +4546,7 @@ export default { 1 ], "trialPeriods": [ - 243 + 242 ], "__typename": [ 1 @@ -4565,7 +4554,7 @@ export default { }, "Support": { "supportDriver": [ - 252 + 251 ], "supportFrontChatId": [ 1 @@ -4591,7 +4580,7 @@ export default { }, "Captcha": { "provider": [ - 255 + 254 ], "siteKey": [ 1 @@ -4625,10 +4614,10 @@ export default { }, "PublicFeatureFlag": { "key": [ - 164 + 163 ], "metadata": [ - 257 + 256 ], "__typename": [ 1 @@ -4639,13 +4628,13 @@ export default { 1 ], "authProviders": [ - 166 + 165 ], "billing": [ - 250 + 249 ], "aiModels": [ - 245 + 244 ], "signInPrefilled": [ 6 @@ -4666,28 +4655,28 @@ export default { 6 ], "support": [ - 251 + 250 ], "isAttachmentPreviewEnabled": [ 6 ], "sentry": [ - 253 + 252 ], "captcha": [ - 254 + 253 ], "chromeExtensionId": [ 1 ], "api": [ - 256 + 255 ], "canManageFeatureFlags": [ 6 ], "publicFeatureFlags": [ - 258 + 257 ], "isMicrosoftMessagingEnabled": [ 6 @@ -4737,13 +4726,13 @@ export default { 6 ], "source": [ - 261 + 260 ], "isEnvOnly": [ 6 ], "type": [ - 262 + 261 ], "options": [ 15 @@ -4756,10 +4745,10 @@ export default { "ConfigVariableType": {}, "ConfigVariablesGroupData": { "variables": [ - 260 + 259 ], "name": [ - 264 + 263 ], "description": [ 1 @@ -4774,7 +4763,7 @@ export default { "ConfigVariablesGroup": {}, "ConfigVariables": { "groups": [ - 263 + 262 ], "__typename": [ 1 @@ -4799,7 +4788,7 @@ export default { 21 ], "results": [ - 266 + 265 ], "__typename": [ 1 @@ -4816,7 +4805,7 @@ export default { 15 ], "state": [ - 269 + 268 ], "timestamp": [ 11 @@ -4866,7 +4855,7 @@ export default { }, "QueueJobsResponse": { "jobs": [ - 268 + 267 ], "count": [ 11 @@ -4878,7 +4867,7 @@ export default { 6 ], "retentionConfig": [ - 270 + 269 ], "__typename": [ 1 @@ -4889,7 +4878,7 @@ export default { 21 ], "results": [ - 266 + 265 ], "__typename": [ 1 @@ -4897,13 +4886,13 @@ export default { }, "SystemHealthService": { "id": [ - 274 + 273 ], "label": [ 1 ], "status": [ - 275 + 274 ], "__typename": [ 1 @@ -4913,7 +4902,7 @@ export default { "AdminPanelHealthServiceStatus": {}, "SystemHealth": { "services": [ - 273 + 272 ], "__typename": [ 1 @@ -4953,13 +4942,13 @@ export default { 11 ], "workspaceUrls": [ - 152 + 151 ], "users": [ - 277 + 276 ], "featureFlags": [ - 163 + 162 ], "__typename": [ 1 @@ -4967,10 +4956,10 @@ export default { }, "UserLookup": { "user": [ - 277 + 276 ], "workspaces": [ - 278 + 277 ], "__typename": [ 1 @@ -4995,7 +4984,7 @@ export default { 1 ], "status": [ - 275 + 274 ], "__typename": [ 1 @@ -5003,7 +4992,7 @@ export default { }, "AdminPanelHealthServiceData": { "id": [ - 274 + 273 ], "label": [ 1 @@ -5012,7 +5001,7 @@ export default { 1 ], "status": [ - 275 + 274 ], "errorMessage": [ 1 @@ -5021,7 +5010,7 @@ export default { 1 ], "queues": [ - 281 + 280 ], "__typename": [ 1 @@ -5043,7 +5032,7 @@ export default { 1 ], "data": [ - 283 + 282 ], "__typename": [ 1 @@ -5086,13 +5075,13 @@ export default { 11 ], "timeRange": [ - 287 + 286 ], "details": [ - 285 + 284 ], "data": [ - 284 + 283 ], "__typename": [ 1 @@ -5101,10 +5090,10 @@ export default { "QueueMetricsTimeRange": {}, "Impersonate": { "loginToken": [ - 199 + 198 ], "workspace": [ - 205 + 204 ], "__typename": [ 1 @@ -5198,7 +5187,7 @@ export default { 1 ], "fields": [ - 292 + 291 ], "__typename": [ 1 @@ -5295,10 +5284,10 @@ export default { 6 ], "objectPermissions": [ - 296 + 295 ], "fieldPermissions": [ - 297 + 296 ], "permissionFlags": [ 1 @@ -5348,19 +5337,19 @@ export default { 1 ], "objects": [ - 293 - ], - "fields": [ 292 ], + "fields": [ + 291 + ], "logicFunctions": [ - 294 + 293 ], "frontComponents": [ - 295 + 294 ], "defaultRole": [ - 298 + 297 ], "sourcePackage": [ 1 @@ -5420,13 +5409,13 @@ export default { 1 ], "driver": [ - 303 + 302 ], "status": [ - 304 + 303 ], "verificationRecords": [ - 301 + 300 ], "verifiedAt": [ 4 @@ -5473,7 +5462,7 @@ export default { 1 ], "location": [ - 306 + 305 ], "__typename": [ 1 @@ -5501,13 +5490,13 @@ export default { }, "ImapSmtpCaldavConnectionParameters": { "IMAP": [ - 308 + 307 ], "SMTP": [ - 308 + 307 ], "CALDAV": [ - 308 + 307 ], "__typename": [ 1 @@ -5527,7 +5516,7 @@ export default { 3 ], "connectionParameters": [ - 309 + 308 ], "__typename": [ 1 @@ -5591,7 +5580,7 @@ export default { 1 ], "series": [ - 314 + 313 ], "xAxisLabel": [ 1 @@ -5640,7 +5629,7 @@ export default { 1 ], "data": [ - 316 + 315 ], "__typename": [ 1 @@ -5648,7 +5637,7 @@ export default { }, "LineChartData": { "series": [ - 317 + 316 ], "xAxisLabel": [ 1 @@ -5685,7 +5674,7 @@ export default { }, "PieChartData": { "data": [ - 319 + 318 ], "showLegend": [ 6 @@ -5768,13 +5757,13 @@ export default { }, "EventLogQueryResult": { "records": [ - 322 + 321 ], "totalCount": [ 21 ], "pageInfo": [ - 323 + 322 ], "__typename": [ 1 @@ -5841,7 +5830,7 @@ export default { 32, { "input": [ - 326, + 325, "LogicFunctionIdInput!" ] } @@ -5853,7 +5842,7 @@ export default { 15, { "input": [ - 326, + 325, "LogicFunctionIdInput!" ] } @@ -5862,13 +5851,13 @@ export default { 1, { "input": [ - 326, + 325, "LogicFunctionIdInput!" ] } ], "objectRecordCounts": [ - 176 + 175 ], "object": [ 46, @@ -5880,7 +5869,7 @@ export default { } ], "objects": [ - 177, + 176, { "paging": [ 39, @@ -5976,7 +5965,7 @@ export default { } ], "indexMetadatas": [ - 171, + 170, { "paging": [ 39, @@ -5989,10 +5978,10 @@ export default { } ], "commandMenuItems": [ - 226 + 225 ], "commandMenuItem": [ - 226, + 225, { "id": [ 3, @@ -6001,10 +5990,10 @@ export default { } ], "frontComponents": [ - 225 + 224 ], "frontComponent": [ - 225, + 224, { "id": [ 3, @@ -6019,13 +6008,13 @@ export default { 25, { "input": [ - 328, + 327, "AgentIdInput!" ] } ], "billingPortalSession": [ - 142, + 141, { "returnUrlPath": [ 1 @@ -6033,10 +6022,10 @@ export default { } ], "listPlans": [ - 141 + 140 ], "getMeteredProductsUsage": [ - 140 + 139 ], "enterprisePortalSession": [ 1, @@ -6055,13 +6044,13 @@ export default { } ], "enterpriseSubscriptionStatus": [ - 145 + 144 ], "navigationMenuItems": [ - 216 + 215 ], "navigationMenuItem": [ - 216, + 215, { "id": [ 3, @@ -6076,7 +6065,7 @@ export default { 2, { "input": [ - 329, + 328, "GetApiKeyInput!" ] } @@ -6085,13 +6074,13 @@ export default { 29 ], "findWorkspaceInvitations": [ - 149 + 148 ], "getApprovedAccessDomains": [ - 147 + 146 ], "getToolIndex": [ - 221 + 220 ], "getToolInputSchema": [ 15, @@ -6112,7 +6101,7 @@ export default { } ], "fields": [ - 189, + 188, { "paging": [ 39, @@ -6182,7 +6171,7 @@ export default { 66 ], "getPublicWorkspaceDataByDomain": [ - 168, + 167, { "origin": [ 1 @@ -6190,7 +6179,7 @@ export default { } ], "findApplicationRegistrationByClientId": [ - 185, + 184, { "clientId": [ 1, @@ -6220,7 +6209,7 @@ export default { } ], "findApplicationRegistrationStats": [ - 183, + 182, { "id": [ 1, @@ -6247,7 +6236,7 @@ export default { } ], "checkUserExists": [ - 213, + 212, { "email": [ 1, @@ -6259,7 +6248,7 @@ export default { } ], "checkWorkspaceInviteHashIsValid": [ - 214, + 213, { "inviteHash": [ 1, @@ -6277,7 +6266,7 @@ export default { } ], "validatePasswordResetToken": [ - 208, + 207, { "passwordResetToken": [ 1, @@ -6286,13 +6275,13 @@ export default { } ], "getSSOIdentityProviders": [ - 193 + 192 ], "webhooks": [ - 242 + 241 ], "webhook": [ - 242, + 241, { "id": [ 3, @@ -6301,10 +6290,10 @@ export default { } ], "minimalMetadata": [ - 241 + 240 ], "chatThread": [ - 229, + 228, { "id": [ 3, @@ -6313,7 +6302,7 @@ export default { } ], "chatMessages": [ - 230, + 229, { "threadId": [ 3, @@ -6322,13 +6311,13 @@ export default { } ], "getAISystemPromptPreview": [ - 232 + 231 ], "skills": [ - 223 + 222 ], "skill": [ - 223, + 222, { "id": [ 3, @@ -6337,24 +6326,24 @@ export default { } ], "chatThreads": [ - 234, + 233, { "paging": [ 39, "CursorPaging!" ], "filter": [ - 330, + 329, "AgentChatThreadFilter!" ], "sorting": [ - 333, + 332, "[AgentChatThreadSort!]!" ] } ], "agentTurns": [ - 236, + 235, { "agentId": [ 3, @@ -6363,43 +6352,43 @@ export default { } ], "eventLogs": [ - 324, + 323, { "input": [ - 337, + 336, "EventLogQueryInput!" ] } ], "pieChartData": [ - 320, + 319, { "input": [ - 341, + 340, "PieChartDataInput!" ] } ], "lineChartData": [ - 318, + 317, { "input": [ - 342, + 341, "LineChartDataInput!" ] } ], "barChartData": [ - 315, + 314, { "input": [ - 343, + 342, "BarChartDataInput!" ] } ], "getConnectedImapSmtpCaldavAccount": [ - 310, + 309, { "id": [ 3, @@ -6408,7 +6397,7 @@ export default { } ], "getAutoCompleteAddress": [ - 305, + 304, { "address": [ 1, @@ -6427,7 +6416,7 @@ export default { } ], "getAddressDetails": [ - 307, + 306, { "placeId": [ 1, @@ -6440,40 +6429,40 @@ export default { } ], "getConfigVariablesGrouped": [ - 265 + 264 ], "getSystemHealthStatus": [ - 276 + 275 ], "getIndicatorHealthStatus": [ - 282, + 281, { "indicatorId": [ - 274, + 273, "HealthIndicatorId!" ] } ], "getQueueMetrics": [ - 286, + 285, { "queueName": [ 1, "String!" ], "timeRange": [ - 287 + 286 ] } ], "versionInfo": [ - 280 + 279 ], "getAdminAiModels": [ - 249 + 248 ], "getDatabaseConfigVariable": [ - 260, + 259, { "key": [ 1, @@ -6482,14 +6471,14 @@ export default { } ], "getQueueJobs": [ - 271, + 270, { "queueName": [ 1, "String!" ], "state": [ - 269, + 268, "JobState!" ], "limit": [ @@ -6504,19 +6493,19 @@ export default { 7 ], "getPostgresCredentials": [ - 312 + 311 ], "findManyPublicDomains": [ - 300 - ], - "getEmailingDomains": [ - 302 - ], - "findManyMarketplaceApps": [ 299 ], + "getEmailingDomains": [ + 301 + ], + "findManyMarketplaceApps": [ + 298 + ], "findOneMarketplaceApp": [ - 299, + 298, { "universalIdentifier": [ 1, @@ -6544,7 +6533,7 @@ export default { }, "LogicFunctionIdInput": { "id": [ - 327 + 326 ], "__typename": [ 1 @@ -6569,16 +6558,16 @@ export default { }, "AgentChatThreadFilter": { "and": [ - 330 + 329 ], "or": [ - 330 + 329 ], "id": [ 42 ], "updatedAt": [ - 331 + 330 ], "__typename": [ 1 @@ -6616,10 +6605,10 @@ export default { 4 ], "between": [ - 332 + 331 ], "notBetween": [ - 332 + 331 ], "__typename": [ 1 @@ -6638,13 +6627,13 @@ export default { }, "AgentChatThreadSort": { "field": [ - 334 + 333 ], "direction": [ - 335 + 334 ], "nulls": [ - 336 + 335 ], "__typename": [ 1 @@ -6655,10 +6644,10 @@ export default { "SortNulls": {}, "EventLogQueryInput": { "table": [ - 338 + 337 ], "filters": [ - 339 + 338 ], "first": [ 21 @@ -6679,7 +6668,7 @@ export default { 1 ], "dateRange": [ - 340 + 339 ], "recordId": [ 1 @@ -6740,7 +6729,7 @@ export default { 6, { "input": [ - 345, + 344, "AddQuerySubscriptionInput!" ] } @@ -6749,13 +6738,13 @@ export default { 6, { "input": [ - 346, + 345, "RemoveQueryFromEventStreamInput!" ] } ], "createObjectEvent": [ - 122, + 121, { "event": [ 1, @@ -6775,10 +6764,10 @@ export default { } ], "trackAnalytics": [ - 122, + 121, { "type": [ - 347, + 346, "AnalyticsType!" ], "name": [ @@ -6796,7 +6785,7 @@ export default { 75, { "input": [ - 348, + 347, "CreatePageLayoutWidgetInput!" ] } @@ -6809,7 +6798,7 @@ export default { "String!" ], "input": [ - 350, + 349, "UpdatePageLayoutWidgetInput!" ] } @@ -6827,7 +6816,7 @@ export default { 110, { "input": [ - 351, + 350, "CreatePageLayoutTabInput!" ] } @@ -6840,7 +6829,7 @@ export default { "String!" ], "input": [ - 352, + 351, "UpdatePageLayoutTabInput!" ] } @@ -6858,7 +6847,7 @@ export default { 111, { "input": [ - 353, + 352, "CreatePageLayoutInput!" ] } @@ -6871,7 +6860,7 @@ export default { "String!" ], "input": [ - 354, + 353, "UpdatePageLayoutInput!" ] } @@ -6893,7 +6882,7 @@ export default { "String!" ], "input": [ - 355, + 354, "UpdatePageLayoutWithTabsInput!" ] } @@ -6902,7 +6891,7 @@ export default { 32, { "input": [ - 326, + 325, "LogicFunctionIdInput!" ] } @@ -6911,16 +6900,16 @@ export default { 32, { "input": [ - 358, + 357, "CreateLogicFunctionFromSourceInput!" ] } ], "executeOneLogicFunction": [ - 218, + 217, { "input": [ - 359, + 358, "ExecuteOneLogicFunctionInput!" ] } @@ -6929,7 +6918,7 @@ export default { 6, { "input": [ - 360, + 359, "UpdateLogicFunctionFromSourceInput!" ] } @@ -6938,7 +6927,7 @@ export default { 46, { "input": [ - 362, + 361, "CreateOneObjectInput!" ] } @@ -6947,7 +6936,7 @@ export default { 46, { "input": [ - 364, + 363, "DeleteOneObjectInput!" ] } @@ -6956,7 +6945,7 @@ export default { 46, { "input": [ - 365, + 364, "UpdateOneObjectInput!" ] } @@ -6965,7 +6954,7 @@ export default { 50, { "input": [ - 367, + 366, "UpdateViewFieldInput!" ] } @@ -6974,7 +6963,7 @@ export default { 50, { "input": [ - 369, + 368, "CreateViewFieldInput!" ] } @@ -6983,7 +6972,7 @@ export default { 50, { "inputs": [ - 369, + 368, "[CreateViewFieldInput!]!" ] } @@ -6992,7 +6981,7 @@ export default { 50, { "input": [ - 370, + 369, "DeleteViewFieldInput!" ] } @@ -7001,7 +6990,7 @@ export default { 50, { "input": [ - 371, + 370, "DestroyViewFieldInput!" ] } @@ -7010,7 +6999,7 @@ export default { 60, { "input": [ - 372, + 371, "CreateViewInput!" ] } @@ -7023,7 +7012,7 @@ export default { "String!" ], "input": [ - 373, + 372, "UpdateViewInput!" ] } @@ -7050,7 +7039,7 @@ export default { 57, { "input": [ - 374, + 373, "CreateViewSortInput!" ] } @@ -7059,7 +7048,7 @@ export default { 57, { "input": [ - 375, + 374, "UpdateViewSortInput!" ] } @@ -7068,7 +7057,7 @@ export default { 6, { "input": [ - 377, + 376, "DeleteViewSortInput!" ] } @@ -7077,7 +7066,7 @@ export default { 6, { "input": [ - 378, + 377, "DestroyViewSortInput!" ] } @@ -7086,7 +7075,7 @@ export default { 59, { "input": [ - 379, + 378, "UpdateViewFieldGroupInput!" ] } @@ -7095,7 +7084,7 @@ export default { 59, { "input": [ - 381, + 380, "CreateViewFieldGroupInput!" ] } @@ -7104,7 +7093,7 @@ export default { 59, { "inputs": [ - 381, + 380, "[CreateViewFieldGroupInput!]!" ] } @@ -7113,7 +7102,7 @@ export default { 59, { "input": [ - 382, + 381, "DeleteViewFieldGroupInput!" ] } @@ -7122,7 +7111,7 @@ export default { 59, { "input": [ - 383, + 382, "DestroyViewFieldGroupInput!" ] } @@ -7131,31 +7120,31 @@ export default { 60, { "input": [ - 384, + 383, "UpsertFieldsWidgetInput!" ] } ], "createCommandMenuItem": [ - 226, + 225, { "input": [ - 387, + 386, "CreateCommandMenuItemInput!" ] } ], "updateCommandMenuItem": [ - 226, + 225, { "input": [ - 388, + 387, "UpdateCommandMenuItemInput!" ] } ], "deleteCommandMenuItem": [ - 226, + 225, { "id": [ 3, @@ -7164,25 +7153,25 @@ export default { } ], "createFrontComponent": [ - 225, + 224, { "input": [ - 389, + 388, "CreateFrontComponentInput!" ] } ], "updateFrontComponent": [ - 225, + 224, { "input": [ - 390, + 389, "UpdateFrontComponentInput!" ] } ], "deleteFrontComponent": [ - 225, + 224, { "id": [ 3, @@ -7194,7 +7183,7 @@ export default { 25, { "input": [ - 392, + 391, "CreateAgentInput!" ] } @@ -7203,7 +7192,7 @@ export default { 25, { "input": [ - 393, + 392, "UpdateAgentInput!" ] } @@ -7212,52 +7201,52 @@ export default { 25, { "input": [ - 328, + 327, "AgentIdInput!" ] } ], "uploadAIChatFile": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ] } ], "uploadWorkflowFile": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ] } ], "uploadWorkspaceLogo": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ] } ], "uploadWorkspaceMemberProfilePicture": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ] } ], "uploadFilesFieldFile": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ], "fieldMetadataId": [ @@ -7267,10 +7256,10 @@ export default { } ], "uploadFilesFieldFileByUniversalIdentifier": [ - 148, + 147, { "file": [ - 394, + 393, "Upload!" ], "fieldMetadataUniversalIdentifier": [ @@ -7280,14 +7269,14 @@ export default { } ], "checkoutSession": [ - 142, + 141, { "recurringInterval": [ - 130, + 129, "SubscriptionInterval!" ], "plan": [ - 126, + 125, "BillingPlanKey!" ], "requirePaymentMethod": [ @@ -7300,19 +7289,19 @@ export default { } ], "switchSubscriptionInterval": [ - 143 + 142 ], "switchBillingPlan": [ - 143 + 142 ], "cancelSwitchBillingPlan": [ - 143 + 142 ], "cancelSwitchBillingInterval": [ - 143 + 142 ], "setMeteredSubscriptionPrice": [ - 143, + 142, { "priceId": [ 1, @@ -7321,16 +7310,16 @@ export default { } ], "endSubscriptionTrialPeriod": [ - 139 + 138 ], "cancelSwitchMeteredPrice": [ - 143 + 142 ], "refreshEnterpriseValidityToken": [ 6 ], "setEnterpriseKey": [ - 144, + 143, { "enterpriseKey": [ 1, @@ -7339,25 +7328,25 @@ export default { } ], "createNavigationMenuItem": [ - 216, + 215, { "input": [ - 395, + 394, "CreateNavigationMenuItemInput!" ] } ], "updateNavigationMenuItem": [ - 216, + 215, { "input": [ - 396, + 395, "UpdateOneNavigationMenuItemInput!" ] } ], "deleteNavigationMenuItem": [ - 216, + 215, { "id": [ 3, @@ -7369,7 +7358,7 @@ export default { 2, { "input": [ - 398, + 397, "CreateApiKeyInput!" ] } @@ -7378,7 +7367,7 @@ export default { 2, { "input": [ - 399, + 398, "UpdateApiKeyInput!" ] } @@ -7387,7 +7376,7 @@ export default { 2, { "input": [ - 400, + 399, "RevokeApiKeyInput!" ] } @@ -7422,7 +7411,7 @@ export default { 29, { "createRoleInput": [ - 401, + 400, "CreateRoleInput!" ] } @@ -7431,7 +7420,7 @@ export default { 29, { "updateRoleInput": [ - 402, + 401, "UpdateRoleInput!" ] } @@ -7449,7 +7438,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 404, + 403, "UpsertObjectPermissionsInput!" ] } @@ -7458,7 +7447,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 406, + 405, "UpsertPermissionFlagsInput!" ] } @@ -7467,16 +7456,16 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 407, + 406, "UpsertFieldPermissionsInput!" ] } ], "upsertRowLevelPermissionPredicates": [ - 181, + 180, { "input": [ - 409, + 408, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -7504,10 +7493,10 @@ export default { } ], "skipSyncEmailOnboardingStep": [ - 146 + 145 ], "skipBookOnboardingStep": [ - 146 + 145 ], "deleteWorkspaceInvitation": [ 1, @@ -7519,7 +7508,7 @@ export default { } ], "resendWorkspaceInvitation": [ - 150, + 149, { "appTokenId": [ 1, @@ -7528,7 +7517,7 @@ export default { } ], "sendInvitations": [ - 150, + 149, { "emails": [ 1, @@ -7540,10 +7529,10 @@ export default { } ], "createApprovedAccessDomain": [ - 147, + 146, { "input": [ - 412, + 411, "CreateApprovedAccessDomainInput!" ] } @@ -7552,16 +7541,16 @@ export default { 6, { "input": [ - 413, + 412, "DeleteApprovedAccessDomainInput!" ] } ], "validateApprovedAccessDomain": [ - 147, + 146, { "input": [ - 414, + 413, "ValidateApprovedAccessDomainInput!" ] } @@ -7570,7 +7559,7 @@ export default { 34, { "input": [ - 415, + 414, "CreateOneFieldMetadataInput!" ] } @@ -7579,7 +7568,7 @@ export default { 34, { "input": [ - 417, + 416, "UpdateOneFieldMetadataInput!" ] } @@ -7588,7 +7577,7 @@ export default { 34, { "input": [ - 419, + 418, "DeleteOneFieldInput!" ] } @@ -7597,7 +7586,7 @@ export default { 56, { "input": [ - 420, + 419, "CreateViewGroupInput!" ] } @@ -7606,7 +7595,7 @@ export default { 56, { "inputs": [ - 420, + 419, "[CreateViewGroupInput!]!" ] } @@ -7615,7 +7604,7 @@ export default { 56, { "input": [ - 421, + 420, "UpdateViewGroupInput!" ] } @@ -7624,7 +7613,7 @@ export default { 56, { "input": [ - 423, + 422, "DeleteViewGroupInput!" ] } @@ -7633,7 +7622,7 @@ export default { 56, { "input": [ - 424, + 423, "DestroyViewGroupInput!" ] } @@ -7642,7 +7631,7 @@ export default { 54, { "input": [ - 425, + 424, "CreateViewFilterInput!" ] } @@ -7651,7 +7640,7 @@ export default { 54, { "input": [ - 426, + 425, "UpdateViewFilterInput!" ] } @@ -7660,7 +7649,7 @@ export default { 54, { "input": [ - 428, + 427, "DeleteViewFilterInput!" ] } @@ -7669,7 +7658,7 @@ export default { 54, { "input": [ - 429, + 428, "DestroyViewFilterInput!" ] } @@ -7678,7 +7667,7 @@ export default { 52, { "input": [ - 430, + 429, "CreateViewFilterGroupInput!" ] } @@ -7691,7 +7680,7 @@ export default { "String!" ], "input": [ - 431, + 430, "UpdateViewFilterGroupInput!" ] } @@ -7739,7 +7728,7 @@ export default { } ], "resendEmailVerificationToken": [ - 151, + 150, { "email": [ 1, @@ -7755,7 +7744,7 @@ export default { 66, { "data": [ - 432, + 431, "ActivateWorkspaceInput!" ] } @@ -7764,7 +7753,7 @@ export default { 66, { "data": [ - 433, + 432, "UpdateWorkspaceInput!" ] } @@ -7773,13 +7762,13 @@ export default { 66 ], "checkCustomDomainValidRecords": [ - 162 + 161 ], "createApplicationRegistration": [ - 184, + 183, { "input": [ - 434, + 433, "CreateApplicationRegistrationInput!" ] } @@ -7788,7 +7777,7 @@ export default { 7, { "input": [ - 435, + 434, "UpdateApplicationRegistrationInput!" ] } @@ -7803,7 +7792,7 @@ export default { } ], "rotateApplicationRegistrationClientSecret": [ - 186, + 185, { "id": [ 1, @@ -7815,7 +7804,7 @@ export default { 5, { "input": [ - 437, + 436, "CreateApplicationRegistrationVariableInput!" ] } @@ -7824,7 +7813,7 @@ export default { 5, { "input": [ - 438, + 437, "UpdateApplicationRegistrationVariableInput!" ] } @@ -7842,7 +7831,7 @@ export default { 7, { "file": [ - 394, + 393, "Upload!" ], "universalIdentifier": [ @@ -7864,16 +7853,16 @@ export default { } ], "getAuthorizationUrlForSSO": [ - 203, + 202, { "input": [ - 440, + 439, "GetAuthorizationUrlForSSOInput!" ] } ], "getLoginTokenFromCredentials": [ - 212, + 211, { "email": [ 1, @@ -7899,7 +7888,7 @@ export default { } ], "signIn": [ - 201, + 200, { "email": [ 1, @@ -7921,7 +7910,7 @@ export default { } ], "verifyEmailAndGetLoginToken": [ - 209, + 208, { "emailVerificationToken": [ 1, @@ -7941,7 +7930,7 @@ export default { } ], "verifyEmailAndGetWorkspaceAgnosticToken": [ - 201, + 200, { "emailVerificationToken": [ 1, @@ -7957,7 +7946,7 @@ export default { } ], "getAuthTokensFromOTP": [ - 211, + 210, { "otp": [ 1, @@ -7977,7 +7966,7 @@ export default { } ], "signUp": [ - 201, + 200, { "email": [ 1, @@ -7999,7 +7988,7 @@ export default { } ], "signUpInWorkspace": [ - 206, + 205, { "email": [ 1, @@ -8030,13 +8019,13 @@ export default { } ], "signUpInNewWorkspace": [ - 206 + 205 ], "generateTransientToken": [ - 207 + 206 ], "getAuthTokensFromLoginToken": [ - 211, + 210, { "loginToken": [ 1, @@ -8049,7 +8038,7 @@ export default { } ], "authorizeApp": [ - 198, + 197, { "clientId": [ 1, @@ -8071,7 +8060,7 @@ export default { } ], "renewToken": [ - 211, + 210, { "appToken": [ 1, @@ -8080,7 +8069,7 @@ export default { } ], "generateApiKeyToken": [ - 210, + 209, { "apiKeyId": [ 3, @@ -8093,7 +8082,7 @@ export default { } ], "emailPasswordResetLink": [ - 202, + 201, { "email": [ 1, @@ -8105,7 +8094,7 @@ export default { } ], "updatePasswordViaResetToken": [ - 204, + 203, { "passwordResetToken": [ 1, @@ -8118,7 +8107,7 @@ export default { } ], "initiateOTPProvisioning": [ - 196, + 195, { "loginToken": [ 1, @@ -8131,10 +8120,10 @@ export default { } ], "initiateOTPProvisioningForAuthenticatedUser": [ - 196 + 195 ], "deleteTwoFactorAuthenticationMethod": [ - 195, + 194, { "twoFactorAuthenticationMethodId": [ 3, @@ -8143,7 +8132,7 @@ export default { } ], "verifyTwoFactorAuthenticationMethodForAuthenticatedUser": [ - 197, + 196, { "otp": [ 1, @@ -8152,61 +8141,61 @@ export default { } ], "createOIDCIdentityProvider": [ - 194, + 193, { "input": [ - 441, + 440, "SetupOIDCSsoInput!" ] } ], "createSAMLIdentityProvider": [ - 194, + 193, { "input": [ - 442, + 441, "SetupSAMLSsoInput!" ] } ], "deleteSSOIdentityProvider": [ - 190, + 189, { "input": [ - 443, + 442, "DeleteSsoInput!" ] } ], "editSSOIdentityProvider": [ - 191, + 190, { "input": [ - 444, + 443, "EditSsoInput!" ] } ], "createWebhook": [ - 242, + 241, { "input": [ - 445, + 444, "CreateWebhookInput!" ] } ], "updateWebhook": [ - 242, + 241, { "input": [ - 446, + 445, "UpdateWebhookInput!" ] } ], "deleteWebhook": [ - 242, + 241, { "id": [ 3, @@ -8215,28 +8204,28 @@ export default { } ], "createChatThread": [ - 229 + 228 ], "createSkill": [ - 223, + 222, { "input": [ - 448, + 447, "CreateSkillInput!" ] } ], "updateSkill": [ - 223, + 222, { "input": [ - 449, + 448, "UpdateSkillInput!" ] } ], "deleteSkill": [ - 223, + 222, { "id": [ 3, @@ -8245,7 +8234,7 @@ export default { } ], "activateSkill": [ - 223, + 222, { "id": [ 3, @@ -8254,7 +8243,7 @@ export default { } ], "deactivateSkill": [ - 223, + 222, { "id": [ 3, @@ -8263,7 +8252,7 @@ export default { } ], "evaluateAgentTurn": [ - 235, + 234, { "turnId": [ 3, @@ -8272,7 +8261,7 @@ export default { } ], "runEvaluationInput": [ - 236, + 235, { "agentId": [ 3, @@ -8285,7 +8274,7 @@ export default { } ], "duplicateDashboard": [ - 321, + 320, { "id": [ 3, @@ -8294,7 +8283,7 @@ export default { } ], "impersonate": [ - 288, + 287, { "userId": [ 3, @@ -8307,7 +8296,7 @@ export default { } ], "startChannelSync": [ - 313, + 312, { "connectedAccountId": [ 3, @@ -8316,7 +8305,7 @@ export default { } ], "saveImapSmtpCaldavAccount": [ - 311, + 310, { "accountOwnerId": [ 3, @@ -8327,7 +8316,7 @@ export default { "String!" ], "connectionParameters": [ - 450, + 449, "EmailAccountConnectionParameters!" ], "id": [ @@ -8336,16 +8325,16 @@ export default { } ], "updateLabPublicFeatureFlag": [ - 163, + 162, { "input": [ - 452, + 451, "UpdateLabPublicFeatureFlagInput!" ] } ], "userLookupAdminPanel": [ - 279, + 278, { "userIdentifier": [ 1, @@ -8419,7 +8408,7 @@ export default { } ], "retryJobs": [ - 272, + 271, { "queueName": [ 1, @@ -8432,7 +8421,7 @@ export default { } ], "deleteJobs": [ - 267, + 266, { "queueName": [ 1, @@ -8445,13 +8434,13 @@ export default { } ], "enablePostgresProxy": [ - 312 + 311 ], "disablePostgresProxy": [ - 312 + 311 ], "createPublicDomain": [ - 300, + 299, { "domain": [ 1, @@ -8469,7 +8458,7 @@ export default { } ], "checkPublicDomainValidRecords": [ - 162, + 161, { "domain": [ 1, @@ -8478,14 +8467,14 @@ export default { } ], "createEmailingDomain": [ - 302, + 301, { "domain": [ 1, "String!" ], "driver": [ - 303, + 302, "EmailingDomainDriver!" ] } @@ -8500,7 +8489,7 @@ export default { } ], "verifyEmailingDomain": [ - 302, + 301, { "id": [ 1, @@ -8512,7 +8501,7 @@ export default { 68, { "input": [ - 453, + 452, "CreateOneAppTokenInput!" ] } @@ -8545,7 +8534,7 @@ export default { 6, { "workspaceMigration": [ - 455, + 454, "WorkspaceMigrationInput!" ] } @@ -8577,7 +8566,7 @@ export default { } ], "createDevelopmentApplication": [ - 289, + 288, { "universalIdentifier": [ 1, @@ -8590,7 +8579,7 @@ export default { } ], "generateApplicationToken": [ - 224, + 223, { "applicationId": [ 3, @@ -8599,7 +8588,7 @@ export default { } ], "syncApplication": [ - 290, + 289, { "manifest": [ 15, @@ -8608,10 +8597,10 @@ export default { } ], "uploadApplicationFile": [ - 291, + 290, { "file": [ - 394, + 393, "Upload!" ], "applicationUniversalIdentifier": [ @@ -8619,7 +8608,7 @@ export default { "String!" ], "fileFolder": [ - 458, + 457, "FileFolder!" ], "filePath": [ @@ -8642,7 +8631,7 @@ export default { } ], "renewApplicationToken": [ - 224, + 223, { "applicationRefreshToken": [ 1, @@ -8694,7 +8683,7 @@ export default { 3 ], "gridPosition": [ - 349 + 348 ], "position": [ 15 @@ -8734,7 +8723,7 @@ export default { 3 ], "gridPosition": [ - 349 + 348 ], "position": [ 15 @@ -8816,7 +8805,7 @@ export default { 3 ], "tabs": [ - 356 + 355 ], "__typename": [ 1 @@ -8836,7 +8825,7 @@ export default { 1 ], "widgets": [ - 357 + 356 ], "__typename": [ 1 @@ -8859,7 +8848,7 @@ export default { 3 ], "gridPosition": [ - 349 + 348 ], "position": [ 15 @@ -8928,7 +8917,7 @@ export default { 3 ], "update": [ - 361 + 360 ], "__typename": [ 1 @@ -8974,7 +8963,7 @@ export default { }, "CreateOneObjectInput": { "object": [ - 363 + 362 ], "__typename": [ 1 @@ -9034,7 +9023,7 @@ export default { }, "UpdateOneObjectInput": { "update": [ - 366 + 365 ], "id": [ 3 @@ -9089,7 +9078,7 @@ export default { 3 ], "update": [ - 368 + 367 ], "__typename": [ 1 @@ -9288,7 +9277,7 @@ export default { 3 ], "update": [ - 376 + 375 ], "__typename": [ 1 @@ -9323,7 +9312,7 @@ export default { 3 ], "update": [ - 380 + 379 ], "__typename": [ 1 @@ -9387,10 +9376,10 @@ export default { 3 ], "groups": [ - 385 + 384 ], "fields": [ - 386 + 385 ], "__typename": [ 1 @@ -9410,7 +9399,7 @@ export default { 6 ], "fields": [ - 386 + 385 ], "__typename": [ 1 @@ -9438,7 +9427,7 @@ export default { 3 ], "engineComponentKey": [ - 227 + 226 ], "label": [ 1 @@ -9456,7 +9445,7 @@ export default { 6 ], "availabilityType": [ - 228 + 227 ], "hotKeys": [ 1 @@ -9491,13 +9480,13 @@ export default { 6 ], "availabilityType": [ - 228 + 227 ], "availabilityObjectMetadataId": [ 3 ], "engineComponentKey": [ - 227 + 226 ], "hotKeys": [ 1 @@ -9537,7 +9526,7 @@ export default { 3 ], "update": [ - 391 + 390 ], "__typename": [ 1 @@ -9642,7 +9631,7 @@ export default { 3 ], "type": [ - 217 + 216 ], "name": [ 1 @@ -9671,7 +9660,7 @@ export default { 3 ], "update": [ - 397 + 396 ], "__typename": [ 1 @@ -9788,7 +9777,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 403 + 402 ], "id": [ 3 @@ -9843,7 +9832,7 @@ export default { 3 ], "objectPermissions": [ - 405 + 404 ], "__typename": [ 1 @@ -9885,7 +9874,7 @@ export default { 3 ], "fieldPermissions": [ - 408 + 407 ], "__typename": [ 1 @@ -9916,10 +9905,10 @@ export default { 3 ], "predicates": [ - 410 + 409 ], "predicateGroups": [ - 411 + 410 ], "__typename": [ 1 @@ -10009,7 +9998,7 @@ export default { }, "CreateOneFieldMetadataInput": { "field": [ - 416 + 415 ], "__typename": [ 1 @@ -10082,7 +10071,7 @@ export default { 3 ], "update": [ - 418 + 417 ], "__typename": [ 1 @@ -10171,7 +10160,7 @@ export default { 3 ], "update": [ - 422 + 421 ], "__typename": [ 1 @@ -10244,7 +10233,7 @@ export default { 3 ], "update": [ - 427 + 426 ], "__typename": [ 1 @@ -10454,7 +10443,7 @@ export default { 1 ], "update": [ - 436 + 435 ], "__typename": [ 1 @@ -10517,7 +10506,7 @@ export default { 1 ], "update": [ - 439 + 438 ], "__typename": [ 1 @@ -10598,7 +10587,7 @@ export default { 3 ], "status": [ - 155 + 154 ], "__typename": [ 1 @@ -10629,7 +10618,7 @@ export default { 3 ], "update": [ - 447 + 446 ], "__typename": [ 1 @@ -10703,13 +10692,13 @@ export default { }, "EmailAccountConnectionParameters": { "IMAP": [ - 451 + 450 ], "SMTP": [ - 451 + 450 ], "CALDAV": [ - 451 + 450 ], "__typename": [ 1 @@ -10748,7 +10737,7 @@ export default { }, "CreateOneAppTokenInput": { "appToken": [ - 454 + 453 ], "__typename": [ 1 @@ -10764,7 +10753,7 @@ export default { }, "WorkspaceMigrationInput": { "actions": [ - 456 + 455 ], "__typename": [ 1 @@ -10772,10 +10761,10 @@ export default { }, "WorkspaceMigrationDeleteActionInput": { "type": [ - 457 + 456 ], "metadataName": [ - 238 + 237 ], "universalIdentifier": [ 1 @@ -10788,16 +10777,16 @@ export default { "FileFolder": {}, "Subscription": { "onDbEvent": [ - 121, + 120, { "input": [ - 460, + 459, "OnDbEventInput!" ] } ], "onEventSubscription": [ - 120, + 119, { "eventStreamId": [ 1, @@ -10806,10 +10795,10 @@ export default { } ], "logicFunctionLogs": [ - 220, + 219, { "input": [ - 461, + 460, "LogicFunctionLogsInput!" ] } diff --git a/packages/twenty-server/project.json b/packages/twenty-server/project.json index f4a5fc74e43..4cef79ce2e2 100644 --- a/packages/twenty-server/project.json +++ b/packages/twenty-server/project.json @@ -171,6 +171,18 @@ } } }, + "lint:diff-with-main": { + "executor": "nx:run-commands", + "options": { + "cwd": "{projectRoot}", + "command": "FILES=$(git diff --name-only --relative --diff-filter=d main...HEAD -- src/ | grep -E '\\.(ts|tsx)$'); [ -z \"$FILES\" ] && echo 'No changed files.' || (npx oxlint --type-aware -c .oxlintrc.json $FILES && (prettier --check $FILES || (echo 'ERROR: Prettier formatting check failed! Fix with: npx nx lint:diff-with-main twenty-server --configuration=fix' && false)))" + }, + "configurations": { + "fix": { + "command": "FILES=$(git diff --name-only --relative --diff-filter=d main...HEAD -- src/ | grep -E '\\.(ts|tsx)$'); [ -z \"$FILES\" ] && echo 'No changed files.' || (npx oxlint --type-aware --fix -c .oxlintrc.json $FILES && prettier --write $FILES)" + } + } + }, "test": {}, "test:debug": { "executor": "nx:run-commands", diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts index 12c6c02438e..79a1399aec7 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts @@ -10,7 +10,6 @@ import { type IndexMetadataInterface } from 'src/engine/metadata-modules/index-m import { I18nService } from 'src/engine/core-modules/i18n/i18n.service'; import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface'; import { filterMorphRelationDuplicateFields } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util'; -import { pickMorphGroupSurvivor } from 'src/engine/dataloaders/utils/pick-morph-group-survivor.util'; import { FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/field-metadata/constants/field-metadata-standard-overrides-properties.constant'; import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; import { RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto'; @@ -21,11 +20,10 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/ import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findManyFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps.util'; import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; -import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util'; import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util'; -import { fromMorphOrRelationFlatFieldMetadataToRelationDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-or-relation-flat-field-metadata-to-relation-dto.util'; import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; -import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util'; +import { resolveMorphRelationsFromFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/resolve-morph-relations-from-flat-field-metadata.util'; +import { resolveRelationFromFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util'; import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util'; import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util'; import { fromFlatViewFieldGroupToViewFieldGroupDto } from 'src/engine/metadata-modules/view-field-group/utils/from-flat-view-field-group-to-view-field-group-dto.util'; @@ -158,7 +156,6 @@ export class DataloaderService { private createRelationLoader() { return new DataLoader( async (dataLoaderParams: RelationLoaderPayload[]) => { - const relationDtos: Array = []; const workspaceId = dataLoaderParams[0].workspaceId; const { flatFieldMetadataMaps, flatObjectMetadataMaps } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( @@ -168,7 +165,7 @@ export class DataloaderService { }, ); - for (const { fieldMetadataId } of dataLoaderParams) { + return dataLoaderParams.map(({ fieldMetadataId }) => { const sourceFlatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: fieldMetadataId, @@ -181,85 +178,15 @@ export class DataloaderService { FieldMetadataType.RELATION, ) ) { - relationDtos.push(null); - continue; + return null; } - const sourceFlatObjectMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityId: sourceFlatFieldMetadata.objectMetadataId, - flatEntityMaps: flatObjectMetadataMaps, - }); - - const targetFlatFieldMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityId: - sourceFlatFieldMetadata.relationTargetFieldMetadataId, - flatEntityMaps: flatFieldMetadataMaps, - }); - - if (!isMorphOrRelationFlatFieldMetadata(targetFlatFieldMetadata)) { - relationDtos.push(null); - continue; - } - - const targetFlatObjectMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityId: targetFlatFieldMetadata.objectMetadataId, - flatEntityMaps: flatObjectMetadataMaps, - }); - - if ( - isFlatFieldMetadataOfType( - targetFlatFieldMetadata, - FieldMetadataType.MORPH_RELATION, - ) - ) { - const morphNameFromMorphFieldMetadataName = - getMorphNameFromMorphFieldMetadataName({ - morphRelationFlatFieldMetadata: targetFlatFieldMetadata, - nameSingular: sourceFlatObjectMetadata.nameSingular, - namePlural: sourceFlatObjectMetadata.namePlural, - }); - - const allMorphFlatFieldMetadatas = [ - targetFlatFieldMetadata, - ...findAllOthersMorphRelationFlatFieldMetadatasOrThrow({ - flatFieldMetadata: targetFlatFieldMetadata, - flatFieldMetadataMaps, - flatObjectMetadata: targetFlatObjectMetadata, - }), - ]; - - const survivorMorphField = pickMorphGroupSurvivor( - allMorphFlatFieldMetadatas, - ); - - relationDtos.push( - fromMorphOrRelationFlatFieldMetadataToRelationDto({ - sourceFlatFieldMetadata, - sourceFlatObjectMetadata, - targetFlatFieldMetadata: { - ...survivorMorphField, - name: morphNameFromMorphFieldMetadataName, - }, - targetFlatObjectMetadata, - }), - ); - continue; - } - - relationDtos.push( - fromMorphOrRelationFlatFieldMetadataToRelationDto({ - sourceFlatFieldMetadata, - targetFlatFieldMetadata, - targetFlatObjectMetadata, - sourceFlatObjectMetadata, - }), - ); - } - - return relationDtos; + return resolveRelationFromFlatFieldMetadata({ + sourceFlatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadataMaps, + }); + }); }, ); } @@ -275,9 +202,8 @@ export class DataloaderService { flatMapsKeys: ['flatFieldMetadataMaps', 'flatObjectMetadataMaps'], }, ); - const relationDtos: Array = []; - for (const { fieldMetadataId } of dataLoaderParams) { + return dataLoaderParams.map(({ fieldMetadataId }) => { const morphFlatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: fieldMetadataId, @@ -290,70 +216,15 @@ export class DataloaderService { FieldMetadataType.MORPH_RELATION, ) ) { - relationDtos.push(null); - continue; + return null; } - const sourceFlatObjectMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityMaps: flatObjectMetadataMaps, - flatEntityId: morphFlatFieldMetadata.objectMetadataId, - }); - - const relatedMorphFlatFieldMetadatas = - findAllOthersMorphRelationFlatFieldMetadatasOrThrow({ - flatFieldMetadata: morphFlatFieldMetadata, - flatFieldMetadataMaps, - flatObjectMetadata: sourceFlatObjectMetadata, - }); - const allMorphFlatFieldMetadatas = [ + return resolveMorphRelationsFromFlatFieldMetadata({ morphFlatFieldMetadata, - ...relatedMorphFlatFieldMetadatas, - ]; - - relationDtos.push( - allMorphFlatFieldMetadatas.flatMap((sourceFlatFieldMetadata) => { - const targetFlatFieldMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityId: - sourceFlatFieldMetadata.relationTargetFieldMetadataId, - flatEntityMaps: flatFieldMetadataMaps, - }); - - if ( - !isMorphOrRelationFlatFieldMetadata(targetFlatFieldMetadata) - ) { - return []; - } - - const targetFlatObjectMetadata = - findFlatEntityByIdInFlatEntityMapsOrThrow({ - flatEntityId: - sourceFlatFieldMetadata.relationTargetObjectMetadataId, - flatEntityMaps: flatObjectMetadataMaps, - }); - - const morphNameFromMorphFieldMetadataName = - getMorphNameFromMorphFieldMetadataName({ - morphRelationFlatFieldMetadata: sourceFlatFieldMetadata, - nameSingular: targetFlatObjectMetadata.nameSingular, - namePlural: targetFlatObjectMetadata.namePlural, - }); - - return fromMorphOrRelationFlatFieldMetadataToRelationDto({ - sourceFlatFieldMetadata: { - ...sourceFlatFieldMetadata, - name: morphNameFromMorphFieldMetadataName, - }, - targetFlatFieldMetadata, - targetFlatObjectMetadata, - sourceFlatObjectMetadata, - }); - }), - ); - } - - return relationDtos; + flatFieldMetadataMaps, + flatObjectMetadataMaps, + }); + }); }, ); } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-morph-relations-from-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-morph-relations-from-flat-field-metadata.util.ts new file mode 100644 index 00000000000..72e010a6899 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-morph-relations-from-flat-field-metadata.util.ts @@ -0,0 +1,73 @@ +import { FieldMetadataType } from 'twenty-shared/types'; + +import { RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto'; +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util'; +import { fromMorphOrRelationFlatFieldMetadataToRelationDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-or-relation-flat-field-metadata-to-relation-dto.util'; +import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util'; + +type ResolveMorphRelationsFromFlatFieldMetadataArgs = { + morphFlatFieldMetadata: FlatFieldMetadata; + flatFieldMetadataMaps: FlatEntityMaps; + flatObjectMetadataMaps: FlatEntityMaps; +}; + +export const resolveMorphRelationsFromFlatFieldMetadata = ({ + morphFlatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadataMaps, +}: ResolveMorphRelationsFromFlatFieldMetadataArgs): RelationDTO[] => { + const sourceFlatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatObjectMetadataMaps, + flatEntityId: morphFlatFieldMetadata.objectMetadataId, + }); + + const relatedMorphFlatFieldMetadatas = + findAllOthersMorphRelationFlatFieldMetadatasOrThrow({ + flatFieldMetadata: morphFlatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadata: sourceFlatObjectMetadata, + }); + + const allMorphFlatFieldMetadatas = [ + morphFlatFieldMetadata, + ...relatedMorphFlatFieldMetadatas, + ]; + + return allMorphFlatFieldMetadatas.flatMap((sourceFlatFieldMetadata) => { + const targetFlatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: sourceFlatFieldMetadata.relationTargetFieldMetadataId, + flatEntityMaps: flatFieldMetadataMaps, + }); + + if (!isMorphOrRelationFlatFieldMetadata(targetFlatFieldMetadata)) { + return []; + } + + const targetFlatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: sourceFlatFieldMetadata.relationTargetObjectMetadataId, + flatEntityMaps: flatObjectMetadataMaps, + }); + + const morphNameFromMorphFieldMetadataName = + getMorphNameFromMorphFieldMetadataName({ + morphRelationFlatFieldMetadata: sourceFlatFieldMetadata, + nameSingular: targetFlatObjectMetadata.nameSingular, + namePlural: targetFlatObjectMetadata.namePlural, + }); + + return fromMorphOrRelationFlatFieldMetadataToRelationDto({ + sourceFlatFieldMetadata: { + ...sourceFlatFieldMetadata, + name: morphNameFromMorphFieldMetadataName, + }, + targetFlatFieldMetadata, + targetFlatObjectMetadata, + sourceFlatObjectMetadata, + }); + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util.ts new file mode 100644 index 00000000000..d3304c5e869 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util.ts @@ -0,0 +1,88 @@ +import { FieldMetadataType } from 'twenty-shared/types'; + +import { pickMorphGroupSurvivor } from 'src/engine/dataloaders/utils/pick-morph-group-survivor.util'; +import { RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto'; +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util'; +import { fromMorphOrRelationFlatFieldMetadataToRelationDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-or-relation-flat-field-metadata-to-relation-dto.util'; +import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; +import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util'; + +type ResolveRelationFromFlatFieldMetadataArgs = { + sourceFlatFieldMetadata: FlatFieldMetadata; + flatFieldMetadataMaps: FlatEntityMaps; + flatObjectMetadataMaps: FlatEntityMaps; +}; + +export const resolveRelationFromFlatFieldMetadata = ({ + sourceFlatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadataMaps, +}: ResolveRelationFromFlatFieldMetadataArgs): RelationDTO | null => { + const sourceFlatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: sourceFlatFieldMetadata.objectMetadataId, + flatEntityMaps: flatObjectMetadataMaps, + }); + + const targetFlatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: sourceFlatFieldMetadata.relationTargetFieldMetadataId, + flatEntityMaps: flatFieldMetadataMaps, + }); + + if (!isMorphOrRelationFlatFieldMetadata(targetFlatFieldMetadata)) { + return null; + } + + const targetFlatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: targetFlatFieldMetadata.objectMetadataId, + flatEntityMaps: flatObjectMetadataMaps, + }); + + if ( + isFlatFieldMetadataOfType( + targetFlatFieldMetadata, + FieldMetadataType.MORPH_RELATION, + ) + ) { + const morphNameFromMorphFieldMetadataName = + getMorphNameFromMorphFieldMetadataName({ + morphRelationFlatFieldMetadata: targetFlatFieldMetadata, + nameSingular: sourceFlatObjectMetadata.nameSingular, + namePlural: sourceFlatObjectMetadata.namePlural, + }); + + const allMorphFlatFieldMetadatas = [ + targetFlatFieldMetadata, + ...findAllOthersMorphRelationFlatFieldMetadatasOrThrow({ + flatFieldMetadata: targetFlatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadata: targetFlatObjectMetadata, + }), + ]; + + const survivorMorphField = pickMorphGroupSurvivor( + allMorphFlatFieldMetadatas, + ); + + return fromMorphOrRelationFlatFieldMetadataToRelationDto({ + sourceFlatFieldMetadata, + sourceFlatObjectMetadata, + targetFlatFieldMetadata: { + ...survivorMorphField, + name: morphNameFromMorphFieldMetadataName, + }, + targetFlatObjectMetadata, + }); + } + + return fromMorphOrRelationFlatFieldMetadataToRelationDto({ + sourceFlatFieldMetadata, + targetFlatFieldMetadata, + targetFlatObjectMetadata, + sourceFlatObjectMetadata, + }); +}; diff --git a/packages/twenty-server/src/engine/subscriptions/dtos/event-subscription.dto.ts b/packages/twenty-server/src/engine/subscriptions/dtos/event-subscription.dto.ts index d04b0cdb109..ff4fc0760bd 100644 --- a/packages/twenty-server/src/engine/subscriptions/dtos/event-subscription.dto.ts +++ b/packages/twenty-server/src/engine/subscriptions/dtos/event-subscription.dto.ts @@ -12,15 +12,6 @@ export class ObjectRecordEventWithQueryIdsDTO { objectRecordEvent: ObjectRecordEventDTO; } -@ObjectType('MetadataEventWithQueryIds') -export class MetadataEventWithQueryIdsDTO { - @Field(() => [String]) - queryIds: string[]; - - @Field(() => MetadataEventDTO) - metadataEvent: MetadataEventDTO; -} - @ObjectType('EventSubscription') export class EventSubscriptionDTO { @Field(() => String) @@ -29,6 +20,6 @@ export class EventSubscriptionDTO { @Field(() => [ObjectRecordEventWithQueryIdsDTO]) objectRecordEventsWithQueryIds: ObjectRecordEventWithQueryIdsDTO[]; - @Field(() => [MetadataEventWithQueryIdsDTO]) - metadataEventsWithQueryIds: MetadataEventWithQueryIdsDTO[]; + @Field(() => [MetadataEventDTO]) + metadataEvents: MetadataEventDTO[]; } diff --git a/packages/twenty-server/src/engine/subscriptions/types/event-stream-payload.type.ts b/packages/twenty-server/src/engine/subscriptions/types/event-stream-payload.type.ts index 33e9c89029f..b748dfadc92 100644 --- a/packages/twenty-server/src/engine/subscriptions/types/event-stream-payload.type.ts +++ b/packages/twenty-server/src/engine/subscriptions/types/event-stream-payload.type.ts @@ -6,8 +6,5 @@ export type EventStreamPayload = { queryIds: string[]; objectRecordEvent: ObjectRecordSubscriptionEvent; }[]; - metadataEventsWithQueryIds: { - queryIds: string[]; - metadataEvent: MetadataEvent; - }[]; + metadataEvents: MetadataEvent[]; }; diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/utils/enrich-field-metadata-event-with-relations.util.ts b/packages/twenty-server/src/engine/workspace-event-emitter/utils/enrich-field-metadata-event-with-relations.util.ts new file mode 100644 index 00000000000..631fdc93589 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-event-emitter/utils/enrich-field-metadata-event-with-relations.util.ts @@ -0,0 +1,64 @@ +import { FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; +import { resolveMorphRelationsFromFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/resolve-morph-relations-from-flat-field-metadata.util'; +import { resolveRelationFromFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; + +type EnrichFieldMetadataEventArgs = { + record: Record; + flatFieldMetadataMaps: FlatEntityMaps; + flatObjectMetadataMaps: FlatEntityMaps; +}; + +export const enrichFieldMetadataEventWithRelations = ({ + record, + flatFieldMetadataMaps, + flatObjectMetadataMaps, +}: EnrichFieldMetadataEventArgs): Record => { + const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: record.id as string, + flatEntityMaps: flatFieldMetadataMaps, + }); + + if (!isDefined(flatFieldMetadata)) { + return record; + } + + try { + if ( + isFlatFieldMetadataOfType(flatFieldMetadata, FieldMetadataType.RELATION) + ) { + const relation = resolveRelationFromFlatFieldMetadata({ + sourceFlatFieldMetadata: flatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadataMaps, + }); + + return isDefined(relation) ? { ...record, relation } : record; + } + + if ( + isFlatFieldMetadataOfType( + flatFieldMetadata, + FieldMetadataType.MORPH_RELATION, + ) + ) { + const morphRelations = resolveMorphRelationsFromFlatFieldMetadata({ + morphFlatFieldMetadata: flatFieldMetadata, + flatFieldMetadataMaps, + flatObjectMetadataMaps, + }); + + return { ...record, morphRelations }; + } + } catch { + return record; + } + + return record; +}; diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.resolver.ts b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.resolver.ts index fa14772e1fb..119607040b6 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.resolver.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.resolver.ts @@ -90,7 +90,7 @@ export class WorkspaceEventEmitterResolver { return { eventStreamId: variables.eventStreamId, objectRecordEventsWithQueryIds: payload.objectRecordEventsWithQueryIds, - metadataEventsWithQueryIds: payload.metadataEventsWithQueryIds, + metadataEvents: payload.metadataEvents, }; }, }) @@ -143,7 +143,7 @@ export class WorkspaceEventEmitterResolver { return wrapAsyncIteratorWithLifecycle(iterator, { initialValue: { objectRecordEventsWithQueryIds: [], - metadataEventsWithQueryIds: [], + metadataEvents: [], }, onHeartbeat: () => this.eventStreamService.refreshEventStreamTTL({ diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts index 81ac8231362..7e80f1f7ff3 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts @@ -31,6 +31,7 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { enrichFieldMetadataEventWithRelations } from 'src/engine/workspace-event-emitter/utils/enrich-field-metadata-event-with-relations.util'; import { UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/types/user-workspace-role-map'; import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type'; import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type'; @@ -130,23 +131,29 @@ export class WorkspaceEventEmitterService { ? await this.fetchObjectRecordStreamContext(workspaceId) : undefined; + const enrichedMetadataEventBatch = isMetadata + ? await this.enrichFieldMetadataEventsWithRelations( + eventBatch as MetadataEventBatch, + ) + : undefined; + for (const [streamChannelId, streamData] of streamsData) { if (!isDefined(streamData)) { streamIdsToRemove.push(streamChannelId); continue; } - if (Object.keys(streamData.queries).length === 0) { - continue; - } - - if (isMetadata) { + if (isMetadata && isDefined(enrichedMetadataEventBatch)) { await this.processMetadataStreamEvents( streamChannelId, streamData, - eventBatch as MetadataEventBatch, + enrichedMetadataEventBatch, ); - } else { + } else if (!isMetadata) { + if (Object.keys(streamData.queries).length === 0) { + continue; + } + if (!isDefined(objectRecordStreamContext)) { continue; } @@ -186,19 +193,14 @@ export class WorkspaceEventEmitterService { return; } - const metadataEventsWithQueryIds = metadataEventBatch.events.map( - (metadataEvent) => ({ - queryIds: [] as string[], - metadataEvent: { - ...metadataEvent, - updatedCollectionHash: metadataEventBatch.updatedCollectionHash, - }, - }), - ); + const metadataEvents = metadataEventBatch.events.map((metadataEvent) => ({ + ...metadataEvent, + updatedCollectionHash: metadataEventBatch.updatedCollectionHash, + })); const payload: EventStreamPayload = { objectRecordEventsWithQueryIds: [], - metadataEventsWithQueryIds, + metadataEvents, }; await this.subscriptionService.publishToEventStream({ @@ -208,6 +210,47 @@ export class WorkspaceEventEmitterService { }); } + private async enrichFieldMetadataEventsWithRelations( + metadataEventBatch: MetadataEventBatch, + ): Promise { + if (metadataEventBatch.metadataName !== 'fieldMetadata') { + return metadataEventBatch; + } + + const { flatFieldMetadataMaps, flatObjectMetadataMaps } = + await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId: metadataEventBatch.workspaceId, + flatMapsKeys: ['flatFieldMetadataMaps', 'flatObjectMetadataMaps'], + }, + ); + + const enrichedEvents = metadataEventBatch.events.map((event) => { + if ( + !('after' in event.properties) || + !isDefined(event.properties.after) + ) { + return event; + } + + const enrichedAfter = enrichFieldMetadataEventWithRelations({ + record: event.properties.after as Record, + flatFieldMetadataMaps, + flatObjectMetadataMaps, + }); + + return { + ...event, + properties: { + ...event.properties, + after: enrichedAfter, + }, + } as typeof event; + }); + + return { ...metadataEventBatch, events: enrichedEvents }; + } + private async processObjectRecordStreamEvents( streamChannelId: string, streamData: EventStreamData, @@ -315,7 +358,7 @@ export class WorkspaceEventEmitterService { const payload: EventStreamPayload = { objectRecordEventsWithQueryIds: matchedEvents, - metadataEventsWithQueryIds: [], + metadataEvents: [], }; await this.subscriptionService.publishToEventStream({