feat: migrate ConnectedAccount infrastructure entities to metadata schema (#18784)
## Summary - Migrates 4 entities (`connectedAccount`, `messageChannel`, `calendarChannel`, `messageFolder`) from per-workspace schemas to the shared `core` metadata schema - Introduces a `IS_CONNECTED_ACCOUNT_MIGRATED` feature flag to control the migration: when enabled, reads come from core metadata and all writes are dual-written to both workspace and core - Extracts 12 enums from workspace entity files to `twenty-shared` for reuse across frontend and backend - Creates new TypeORM entities, metadata services, GraphQL resolvers/DTOs, and exception interceptors per entity - Each entity owns its own data access module (`ConnectedAccountDataAccessModule`, `MessageChannelDataAccessModule`, `CalendarChannelDataAccessModule`, `MessageFolderDataAccessModule`) — no umbrella infrastructure module - Adds a 1.20 upgrade command that backfills data from workspace schemas to core (preserving UUIDs) and enables the feature flag - Replaces direct repository access with data access service calls across ~50 files in messaging, calendar, and connected-account modules - Adds `lastSignedInAt` and `oidcTokenClaims` fields to the new `ConnectedAccountEntity` - Drops unused `lastSyncHistoryId` field from the migrated connected account entity ## Test plan - [x] Lint passes (`npx nx lint:diff-with-main twenty-server`) - [x] Typecheck passes (`npx nx typecheck twenty-server`) - [x] All unit tests pass (477 suites, 4267 tests, 0 failures) - [ ] Manual test: verify messaging sync works with feature flag disabled (existing behavior) - [ ] Manual test: run upgrade command on a workspace, verify data backfilled to core tables - [ ] Manual test: verify messaging/calendar sync works with feature flag enabled (dual-write path) - [ ] Manual test: verify GraphQL metadata resolvers return correct data when flag enabled
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
export enum CalendarChannelContactAutoCreationPolicy {
|
||||
AS_PARTICIPANT_AND_ORGANIZER = 'AS_PARTICIPANT_AND_ORGANIZER',
|
||||
AS_PARTICIPANT = 'AS_PARTICIPANT',
|
||||
AS_ORGANIZER = 'AS_ORGANIZER',
|
||||
NONE = 'NONE',
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export enum CalendarChannelSyncStage {
|
||||
PENDING_CONFIGURATION = 'PENDING_CONFIGURATION',
|
||||
CALENDAR_EVENT_LIST_FETCH_PENDING = 'CALENDAR_EVENT_LIST_FETCH_PENDING',
|
||||
CALENDAR_EVENT_LIST_FETCH_SCHEDULED = 'CALENDAR_EVENT_LIST_FETCH_SCHEDULED',
|
||||
CALENDAR_EVENT_LIST_FETCH_ONGOING = 'CALENDAR_EVENT_LIST_FETCH_ONGOING',
|
||||
CALENDAR_EVENTS_IMPORT_PENDING = 'CALENDAR_EVENTS_IMPORT_PENDING',
|
||||
CALENDAR_EVENTS_IMPORT_SCHEDULED = 'CALENDAR_EVENTS_IMPORT_SCHEDULED',
|
||||
CALENDAR_EVENTS_IMPORT_ONGOING = 'CALENDAR_EVENTS_IMPORT_ONGOING',
|
||||
FAILED = 'FAILED',
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export enum CalendarChannelSyncStatus {
|
||||
NOT_SYNCED = 'NOT_SYNCED',
|
||||
ONGOING = 'ONGOING',
|
||||
ACTIVE = 'ACTIVE',
|
||||
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
|
||||
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum CalendarChannelVisibility {
|
||||
METADATA = 'METADATA',
|
||||
SHARE_EVERYTHING = 'SHARE_EVERYTHING',
|
||||
}
|
||||
@@ -20,4 +20,5 @@ export enum FeatureFlagKey {
|
||||
IS_DRAFT_EMAIL_ENABLED = 'IS_DRAFT_EMAIL_ENABLED',
|
||||
IS_RICH_TEXT_V1_MIGRATED = 'IS_RICH_TEXT_V1_MIGRATED',
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED = 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED',
|
||||
IS_CONNECTED_ACCOUNT_MIGRATED = 'IS_CONNECTED_ACCOUNT_MIGRATED',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum MessageChannelContactAutoCreationPolicy {
|
||||
SENT_AND_RECEIVED = 'SENT_AND_RECEIVED',
|
||||
SENT = 'SENT',
|
||||
NONE = 'NONE',
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum MessageChannelPendingGroupEmailsAction {
|
||||
GROUP_EMAILS_DELETION = 'GROUP_EMAILS_DELETION',
|
||||
GROUP_EMAILS_IMPORT = 'GROUP_EMAILS_IMPORT',
|
||||
NONE = 'NONE',
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export enum MessageChannelSyncStage {
|
||||
PENDING_CONFIGURATION = 'PENDING_CONFIGURATION',
|
||||
MESSAGE_LIST_FETCH_PENDING = 'MESSAGE_LIST_FETCH_PENDING',
|
||||
MESSAGE_LIST_FETCH_SCHEDULED = 'MESSAGE_LIST_FETCH_SCHEDULED',
|
||||
MESSAGE_LIST_FETCH_ONGOING = 'MESSAGE_LIST_FETCH_ONGOING',
|
||||
MESSAGES_IMPORT_PENDING = 'MESSAGES_IMPORT_PENDING',
|
||||
MESSAGES_IMPORT_SCHEDULED = 'MESSAGES_IMPORT_SCHEDULED',
|
||||
MESSAGES_IMPORT_ONGOING = 'MESSAGES_IMPORT_ONGOING',
|
||||
FAILED = 'FAILED',
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export enum MessageChannelSyncStatus {
|
||||
NOT_SYNCED = 'NOT_SYNCED',
|
||||
ONGOING = 'ONGOING',
|
||||
ACTIVE = 'ACTIVE',
|
||||
FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS',
|
||||
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum MessageChannelType {
|
||||
EMAIL = 'EMAIL',
|
||||
SMS = 'SMS',
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum MessageChannelVisibility {
|
||||
METADATA = 'METADATA',
|
||||
SUBJECT = 'SUBJECT',
|
||||
SHARE_EVERYTHING = 'SHARE_EVERYTHING',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum MessageFolderImportPolicy {
|
||||
ALL_FOLDERS = 'ALL_FOLDERS',
|
||||
SELECTED_FOLDERS = 'SELECTED_FOLDERS',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum MessageFolderPendingSyncAction {
|
||||
FOLDER_DELETION = 'FOLDER_DELETION',
|
||||
NONE = 'NONE',
|
||||
}
|
||||
@@ -14,6 +14,10 @@ export { AppBasePath } from './AppBasePath';
|
||||
export { AppPath } from './AppPath';
|
||||
export type { Arrayable } from './Arrayable';
|
||||
export type { ArraySortDirection } from './ArraySortDirection';
|
||||
export { CalendarChannelContactAutoCreationPolicy } from './CalendarChannelContactAutoCreationPolicy';
|
||||
export { CalendarChannelSyncStage } from './CalendarChannelSyncStage';
|
||||
export { CalendarChannelSyncStatus } from './CalendarChannelSyncStatus';
|
||||
export { CalendarChannelVisibility } from './CalendarChannelVisibility';
|
||||
export type { CommandMenuContextApi } from './CommandMenuContextApi';
|
||||
export { CommandMenuContextApiPageType } from './CommandMenuContextApiPageType';
|
||||
export { CommandMenuItemViewType } from './CommandMenuItemViewType';
|
||||
@@ -125,6 +129,14 @@ export type { IsExactly } from './IsExactly';
|
||||
export type { IsNever } from './IsNever.type';
|
||||
export type { IsSerializedRelation } from './IsSerializedRelation.type';
|
||||
export type { LogicFunctionEvent } from './LogicFunctionEvent';
|
||||
export { MessageChannelContactAutoCreationPolicy } from './MessageChannelContactAutoCreationPolicy';
|
||||
export { MessageChannelPendingGroupEmailsAction } from './MessageChannelPendingGroupEmailsAction';
|
||||
export { MessageChannelSyncStage } from './MessageChannelSyncStage';
|
||||
export { MessageChannelSyncStatus } from './MessageChannelSyncStatus';
|
||||
export { MessageChannelType } from './MessageChannelType';
|
||||
export { MessageChannelVisibility } from './MessageChannelVisibility';
|
||||
export { MessageFolderImportPolicy } from './MessageFolderImportPolicy';
|
||||
export { MessageFolderPendingSyncAction } from './MessageFolderPendingSyncAction';
|
||||
export { MessageParticipantRole } from './MessageParticipantRole';
|
||||
export type { MetadataGqlOperationSignature } from './MetadataGqlOperationSignature';
|
||||
export type { ModifiedProperties } from './ModifiedProperties';
|
||||
|
||||
Reference in New Issue
Block a user