Remove sync-metadata and IS_WORKSPACE_CREATION_V2_ENABLED feature flag (#16997)
# Introduction Followup of https://github.com/twentyhq/twenty/pull/17001#pullrequestreview-3638508738 close https://github.com/twentyhq/core-team-issues/issues/1910 We've completely decom the `sync-metadata` in production. We're now then removing its implementation in favor of the v2. ## TODO: - [x] Remove sync-metadata implem and commands - [x] Remove workspace decorators - [x] Type each deprecated field to deprecated on their workspaceEntity - [x] Remove the `workspace-sync-metadata` folder entirely - [x] remove workspace migration - [x] workspace migration removal migration - [x] remove the `v2` references from workspace manager file names - [x] remove the `v2` references from workspace manager modules - [ ] Double check impact on translation file path updates ## Note - Removed the gate logic - Remains some service v2 naming, serverless needs to be migrated on v2 fully - Removed workspaceMigration service app health consumption, making it always returning up ( no more down ) cc @FelixMalfait ( quite obsolete health check now, will require complete refactor once we introduce inter app dependency etc )
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
export const DEFAULT_FEATURE_FLAGS = [
|
||||
FeatureFlagKey.IS_TIMELINE_ACTIVITY_MIGRATED,
|
||||
] as const satisfies FeatureFlagKey[];
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { getMetadataEmptyWorkspaceMigrationActionRecord } from 'src/engine/workspace-manager/workspace-migration/utils/get-metadata-empty-workspace-migration-action-record.util';
|
||||
|
||||
export const createEmptyOrchestratorActionsReport =
|
||||
(): OrchestratorActionsReport =>
|
||||
(
|
||||
Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[]
|
||||
).reduce(
|
||||
(orchestratorReport, metadataName) => ({
|
||||
...orchestratorReport,
|
||||
[metadataName]:
|
||||
getMetadataEmptyWorkspaceMigrationActionRecord(metadataName),
|
||||
}),
|
||||
{} as OrchestratorActionsReport,
|
||||
);
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { type OrchestratorFailureReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
|
||||
export const EMPTY_ORCHESTRATOR_FAILURE_REPORT =
|
||||
(): OrchestratorFailureReport =>
|
||||
(
|
||||
Object.keys(ALL_METADATA_NAME) as (keyof typeof ALL_METADATA_NAME)[]
|
||||
).reduce(
|
||||
(orchestratorReport, metadataName) => ({
|
||||
...orchestratorReport,
|
||||
[metadataName]: [],
|
||||
}),
|
||||
{} as OrchestratorFailureReport,
|
||||
);
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export const HELPER_AGENT = {
|
||||
standardId: '20202020-0002-0001-0001-000000000004',
|
||||
} as const;
|
||||
+588
@@ -0,0 +1,588 @@
|
||||
/**
|
||||
* /!\ DO NOT EDIT THE IDS OF THIS FILE /!\
|
||||
* This file contains static ids for standard objects.
|
||||
* These ids are used to identify standard objects in the database and compare them even when renamed.
|
||||
* For readability keys can be edited but the values should not be changed.
|
||||
*/
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const ACTIVITY_TARGET_STANDARD_FIELD_IDS = {
|
||||
activity: '20202020-ca58-478c-a4f5-ae825671c30e',
|
||||
person: '20202020-4afd-4ae7-99c2-de57d795a93f',
|
||||
company: '20202020-7cc0-44a1-8068-f11171fdd02e',
|
||||
opportunity: '20202020-1fc2-4af1-8c91-7901ee0fd38b',
|
||||
custom: '20202020-7f21-442f-94be-32462281b1ca',
|
||||
} as const;
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const ACTIVITY_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-24a1-4d94-a071-617f3eeed7b0',
|
||||
body: '20202020-209b-440a-b2a8-043fa36a7d37',
|
||||
type: '20202020-0f2b-4aab-8827-ee5d3f07d993',
|
||||
reminderAt: '20202020-eb06-43e2-ba06-336be0e665a3',
|
||||
dueAt: '20202020-0336-4511-ba79-565b12801bd9',
|
||||
completedAt: '20202020-0f4d-4fca-9f2f-6309d9ecb85f',
|
||||
activityTargets: '20202020-7253-42cb-8586-8cf950e70b79',
|
||||
attachments: '20202020-5547-4197-bc2e-a07dfc4559ca',
|
||||
comments: '20202020-6b2e-4d29-bbd1-ecddb330e71a',
|
||||
author: '20202020-455f-44f2-8e89-1b0ef01cb7fb',
|
||||
assignee: '20202020-4259-48e4-9e77-6b92991906d5',
|
||||
} as const;
|
||||
|
||||
export const ATTACHMENT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-87a5-48f8-bbf7-ade388825a57',
|
||||
fullPath: '20202020-0d19-453d-8e8d-fbcda8ca3747',
|
||||
type: '20202020-a417-49b8-a40b-f6a7874caa0d',
|
||||
fileCategory: '20202020-8c3f-4d9e-9a1b-2e5f7a8c9d0e',
|
||||
createdBy: '395be3bd-a5c9-463d-aafe-9bc3bbec3f15',
|
||||
updatedBy: '376239d1-3e65-4cb6-b5d8-e0917d43cc93',
|
||||
author: '20202020-6501-4ac5-a4ef-b2f8522ef6cd',
|
||||
activity: '20202020-b569-481b-a13f-9b94e47e54fe',
|
||||
task: '20202020-51e5-4621-9cf8-215487951c4b',
|
||||
note: '20202020-4f4b-4503-a6fc-6b982f3dffb5',
|
||||
person: '20202020-0158-4aa2-965c-5cdafe21ffa2',
|
||||
company: '20202020-ceab-4a28-b546-73b06b4c08d5',
|
||||
opportunity: '20202020-7374-499d-bea3-9354890755b5',
|
||||
dashboard: '20202020-5324-43f3-9dbf-1a33e7de0ce6',
|
||||
workflow: '20202020-f1e8-4c9d-8a7b-3f5e1d2c9a8b',
|
||||
custom: '20202020-302d-43b3-9aea-aa4f89282a9f',
|
||||
} as const;
|
||||
|
||||
export const BASE_OBJECT_STANDARD_FIELD_IDS = {
|
||||
id: '20202020-eda0-4cee-9577-3eb357e3c22b',
|
||||
createdAt: '20202020-66ac-4502-9975-e4d959c50311',
|
||||
updatedAt: '20202020-d767-4622-bdcf-d8a084834d86',
|
||||
deletedAt: '20202020-b9a7-48d8-8387-b9a3090a50ec',
|
||||
} as const;
|
||||
|
||||
export const BLOCKLIST_STANDARD_FIELD_IDS = {
|
||||
handle: '20202020-eef3-44ed-aa32-4641d7fd4a3e',
|
||||
workspaceMember: '20202020-548d-4084-a947-fa20a39f7c06',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS = {
|
||||
calendarChannel: '20202020-93ee-4da4-8d58-0282c4a9cb7d',
|
||||
calendarEvent: '20202020-5aa5-437e-bb86-f42d457783e3',
|
||||
eventExternalId: '20202020-9ec8-48bb-b279-21d0734a75a1',
|
||||
recurringEventExternalId: '20202020-c58f-4c69-9bf8-9518fa31aa50',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_CHANNEL_STANDARD_FIELD_IDS = {
|
||||
connectedAccount: '20202020-95b1-4f44-82dc-61b042ae2414',
|
||||
handle: '20202020-1d08-420a-9aa7-22e0f298232d',
|
||||
visibility: '20202020-1b07-4796-9f01-d626bab7ca4d',
|
||||
isContactAutoCreationEnabled: '20202020-50fb-404b-ba28-369911a3793a',
|
||||
contactAutoCreationPolicy: '20202020-b55d-447d-b4df-226319058775',
|
||||
isSyncEnabled: '20202020-fe19-4818-8854-21f7b1b43395',
|
||||
syncCursor: '20202020-bac2-4852-a5cb-7a7898992b70',
|
||||
calendarChannelEventAssociations: '20202020-afb0-4a9f-979f-2d5087d71d09',
|
||||
throttleFailureCount: '20202020-525c-4b76-b9bd-0dd57fd11d61',
|
||||
syncStatus: '20202020-7116-41da-8b4b-035975c4eb6a',
|
||||
syncStage: '20202020-6246-42e6-b5cd-003bd921782c',
|
||||
syncStageStartedAt: '20202020-a934-46f1-a8e7-9568b1e3a53e',
|
||||
syncedAt: '20202020-2ff5-4f70-953a-3d0d36357576',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS = {
|
||||
calendarEvent: '20202020-fe3a-401c-b889-af4f4657a861',
|
||||
handle: '20202020-8692-4580-8210-9e09cbd031a7',
|
||||
displayName: '20202020-ee1e-4f9f-8ac1-5c0b2f69691e',
|
||||
isOrganizer: '20202020-66e7-4e00-9e06-d06c92650580',
|
||||
responseStatus: '20202020-cec0-4be8-8fba-c366abc23147',
|
||||
person: '20202020-5761-4842-8186-e1898ef93966',
|
||||
workspaceMember: '20202020-20e4-4591-93ed-aeb17a4dcbd2',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_EVENT_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-080e-49d1-b21d-9702a7e2525c',
|
||||
isCanceled: '20202020-335b-4e04-b470-43b84b64863c',
|
||||
isFullDay: '20202020-551c-402c-bb6d-dfe9efe86bcb',
|
||||
startsAt: '20202020-2c57-4c75-93c5-2ac950a6ed67',
|
||||
endsAt: '20202020-2554-4ee1-a617-17907f6bab21',
|
||||
externalCreatedAt: '20202020-9f03-4058-a898-346c62181599',
|
||||
externalUpdatedAt: '20202020-b355-4c18-8825-ef42c8a5a755',
|
||||
description: '20202020-52c4-4266-a98f-e90af0b4d271',
|
||||
location: '20202020-641a-4ffe-960d-c3c186d95b17',
|
||||
iCalUid: '20202020-f24b-45f4-b6a3-d2f9fcb98714',
|
||||
conferenceSolution: '20202020-1c3f-4b5a-b526-5411a82179eb',
|
||||
conferenceLink: '20202020-35da-43ef-9ca0-e936e9dc237b',
|
||||
calendarChannelEventAssociations: '20202020-bdf8-4572-a2cc-ecbb6bcc3a02',
|
||||
calendarEventParticipants: '20202020-e07e-4ccb-88f5-6f3d00458eec',
|
||||
} as const;
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const COMMENT_STANDARD_FIELD_IDS = {
|
||||
body: '20202020-d5eb-49d2-b3e0-1ed04145ebb7',
|
||||
author: '20202020-2ab1-427e-a981-cf089de3a9bd',
|
||||
activity: '20202020-c8d9-4c30-a35e-dc7f44388070',
|
||||
} as const;
|
||||
|
||||
export const COMPANY_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-4d99-4e2e-a84c-4a27837b1ece',
|
||||
domainName: '20202020-0c28-43d8-8ba5-3659924d3489',
|
||||
address_deprecated: '20202020-a82a-4ee2-96cc-a18a3259d953',
|
||||
address: '20202020-c5ce-4adc-b7b6-9c0979fc55e7',
|
||||
employees: '20202020-8965-464a-8a75-74bafc152a0b',
|
||||
linkedinLink: '20202020-ebeb-4beb-b9ad-6848036fb451',
|
||||
xLink: '20202020-6f64-4fd9-9580-9c1991c7d8c3',
|
||||
annualRecurringRevenue: '20202020-602a-495c-9776-f5d5b11d227b',
|
||||
idealCustomerProfile: '20202020-ba6b-438a-8213-2c5ba28d76a2',
|
||||
position: '20202020-9b4e-462b-991d-a0ee33326454',
|
||||
createdBy: '20202020-fabc-451d-ab7d-412170916baa',
|
||||
updatedBy: '7444022e-b38f-4d4f-801b-cd664abc4834',
|
||||
people: '20202020-3213-4ddf-9494-6422bcff8d7c',
|
||||
accountOwner: '20202020-95b8-4e10-9881-edb5d4765f9d',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-c2a5-4c9b-9d9a-582bcd57fbc8',
|
||||
taskTargets: '20202020-cb17-4a61-8f8f-3be6730480de',
|
||||
noteTargets: '20202020-bae0-4556-a74a-a9c686f77a88',
|
||||
opportunities: '20202020-add3-4658-8e23-d70dccb6d0ec',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d55',
|
||||
attachments: '20202020-c1b5-4120-b0f0-987ca401ed53',
|
||||
timelineActivities: '20202020-0414-4daf-9c0d-64fe7b27f89f',
|
||||
searchVector: '85c71601-72f9-4b7b-b343-d46100b2c74d',
|
||||
} as const;
|
||||
|
||||
export const CONNECTED_ACCOUNT_STANDARD_FIELD_IDS = {
|
||||
handle: '20202020-c804-4a50-bb05-b3a9e24f1dec',
|
||||
provider: '20202020-ebb0-4516-befc-a9e95935efd5',
|
||||
accessToken: '20202020-707b-4a0a-8753-2ad42efe1e29',
|
||||
refreshToken: '20202020-532d-48bd-80a5-c4be6e7f6e49',
|
||||
accountOwner: '20202020-3517-4896-afac-b1d0aa362af6',
|
||||
lastSyncHistoryId: '20202020-115c-4a87-b50f-ac4367a971b9',
|
||||
authFailedAt: '20202020-d268-4c6b-baff-400d402b430a',
|
||||
lastCredentialsRefreshedAt: '20202020-aa5e-4e85-903b-fdf90a941941',
|
||||
messageChannels: '20202020-24f7-4362-8468-042204d1e445',
|
||||
calendarChannels: '20202020-af4a-47bb-99ec-51911c1d3977',
|
||||
handleAliases: '20202020-8a3d-46be-814f-6228af16c47b',
|
||||
scopes: '20202020-8a3d-46be-814f-6228af16c47c',
|
||||
connectionParameters: '20202020-a1b2-46be-814f-6228af16c481',
|
||||
} as const;
|
||||
|
||||
export const TIMELINE_ACTIVITY_STANDARD_FIELD_IDS = {
|
||||
happensAt: '20202020-9526-4993-b339-c4318c4d39f0',
|
||||
type: '20202020-5e7b-4ccd-8b8a-86b94b474134',
|
||||
name: '20202020-7207-46e8-9dab-849505ae8497',
|
||||
properties: '20202020-f142-4b04-b91b-6a2b4af3bf11',
|
||||
workspaceMember: '20202020-af23-4479-9a30-868edc474b36',
|
||||
targetPerson: '20202020-c414-45b9-a60a-ac27aa96229f',
|
||||
targetCompany: '20202020-04ad-4221-a744-7a8278a5ce21',
|
||||
targetOpportunity: '20202020-7664-4a35-a3df-580d389fd527',
|
||||
targetTask: '20202020-b2f5-415c-9135-a31dfe49501b',
|
||||
targetNote: '20202020-ec55-4135-8da5-3a20badc0156',
|
||||
targetWorkflow: '20202020-616c-4ad3-a2e9-c477c341e295',
|
||||
targetWorkflowVersion: '20202020-74f1-4711-a129-e14ca0ecd744',
|
||||
targetWorkflowRun: '20202020-96f0-401b-9186-a3a0759225ac',
|
||||
targetDashboard: '20202020-7864-48f5-af7c-9e4b60140948',
|
||||
targetCustom: '20202020-4a71-41b0-9f83-9cdcca3f8b14',
|
||||
linkedRecordCachedName: '20202020-cfdb-4bef-bbce-a29f41230934',
|
||||
linkedRecordId: '20202020-2e0e-48c0-b445-ee6c1e61687d',
|
||||
linkedObjectMetadataId: '20202020-c595-449d-9f89-562758c9ee69',
|
||||
targetMorphId: '20202020-9a2b-4c3d-a4e5-f6a7b8c9d0e1',
|
||||
} as const;
|
||||
|
||||
export const FAVORITE_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-dd26-42c6-8c3c-2a7598c204f6',
|
||||
forWorkspaceMember: '20202020-ce63-49cb-9676-fdc0c45892cd',
|
||||
person: '20202020-c428-4f40-b6f3-86091511c41c',
|
||||
company: '20202020-cff5-4682-8bf9-069169e08279',
|
||||
opportunity: '20202020-dabc-48e1-8318-2781a2b32aa2',
|
||||
workflow: '20202020-b11b-4dc8-999a-6bd0a947b463',
|
||||
workflowVersion: '20202020-e1b8-4caf-b55a-3ab4d4cbcd21',
|
||||
workflowRun: '20202020-db5a-4fe4-9a13-9afa22b1e762',
|
||||
task: '20202020-1b1b-4b3b-8b1b-7f8d6a1d7d5c',
|
||||
note: '20202020-1f25-43fe-8b00-af212fdde824',
|
||||
view: '20202020-5a93-4fa9-acce-e73481a0bbdf',
|
||||
custom: '20202020-855a-4bc8-9861-79deef37011f',
|
||||
favoriteFolder: '20202020-f658-4d12-8b4d-248356aa4bd9',
|
||||
dashboard: '20202020-6ef9-45e4-b440-cc986f687c91',
|
||||
} as const;
|
||||
|
||||
export const FAVORITE_FOLDER_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-5278-4bde-8909-2cec74d43744',
|
||||
name: '20202020-82a3-4537-8ff0-dbce7eec35d6',
|
||||
favorites: '20202020-b5e3-4b42-8af2-03cd4fd2e4d2',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS = {
|
||||
messageChannel: '20202020-b658-408f-bd46-3bd2d15d7e52',
|
||||
message: '20202020-da5d-4ac5-8743-342ab0a0336b',
|
||||
messageExternalId: '20202020-37d6-438f-b6fd-6503596c8f34',
|
||||
messageThread: '20202020-fac8-42a8-94dd-44dbc920ae16',
|
||||
messageThreadExternalId: '20202020-35fb-421e-afa0-0b8e8f7f9018',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_CHANNEL_STANDARD_FIELD_IDS = {
|
||||
visibility: '20202020-6a6b-4532-9767-cbc61b469453',
|
||||
handle: '20202020-2c96-43c3-93e3-ed6b1acb69bc',
|
||||
connectedAccount: '20202020-49a2-44a4-b470-282c0440d15d',
|
||||
type: '20202020-ae95-42d9-a3f1-797a2ea22122',
|
||||
isContactAutoCreationEnabled: '20202020-fabd-4f14-b7c6-3310f6d132c6',
|
||||
contactAutoCreationPolicy: '20202020-fc0e-4ba6-b259-a66ca89cfa38',
|
||||
excludeNonProfessionalEmails: '20202020-1df5-445d-b4f3-2413ad178431',
|
||||
excludeGroupEmails: '20202020-45a0-4be4-9164-5820a6a109fb',
|
||||
messageChannelMessageAssociations: '20202020-49b8-4766-88fd-75f1e21b3d5f',
|
||||
messageFolders: '20202020-cc39-4432-9fe8-ec8ab8bbed94',
|
||||
messageFolderImportPolicy: '20202020-cc39-4432-9fe8-ec8ab8bbed95',
|
||||
pendingGroupEmailsAction: '20202020-17c5-4e9f-bc50-af46a89fdd42',
|
||||
isSyncEnabled: '20202020-d9a6-48e9-990b-b97fdf22e8dd',
|
||||
syncCursor: '20202020-79d1-41cf-b738-bcf5ed61e256',
|
||||
syncedAt: '20202020-263d-4c6b-ad51-137ada56f7d4',
|
||||
syncStatus: '20202020-56a1-4f7e-9880-a8493bb899cc',
|
||||
syncStage: '20202020-7979-4b08-89fe-99cb5e698767',
|
||||
syncStageStartedAt: '20202020-8c61-4a42-ae63-73c1c3c52e06',
|
||||
throttleFailureCount: '20202020-0291-42be-9ad0-d578a51684ab',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_FOLDER_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-7cf8-40bc-a681-b80b771449b7',
|
||||
parentFolderId: '20202020-e45d-49de-a4aa-587bbf9601f3',
|
||||
messageChannel: '20202020-b658-408f-bd46-3bd2d15d7e52',
|
||||
syncCursor: '20202020-98cd-49ed-8dfc-cb5796400e64',
|
||||
isSentFolder: '20202020-2af5-4a25-b2de-3c9386da941b',
|
||||
isSynced: '20202020-764f-4e09-8f95-cd46b6bfe3c4',
|
||||
externalId: '20202020-f3a8-4d2b-9c7e-1b5f9a8e4c6d',
|
||||
pendingSyncAction: '20202020-4f97-4c79-9517-16387fe237f7',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS = {
|
||||
message: '20202020-985b-429a-9db9-9e55f4898a2a',
|
||||
role: '20202020-65d1-42f4-8729-c9ec1f52aecd',
|
||||
handle: '20202020-2456-464e-b422-b965a4db4a0b',
|
||||
displayName: '20202020-36dd-4a4f-ac02-228425be9fac',
|
||||
person: '20202020-249d-4e0f-82cd-1b9df5cd3da2',
|
||||
workspaceMember: '20202020-77a7-4845-99ed-1bcbb478be6f',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_THREAD_STANDARD_FIELD_IDS = {
|
||||
messages: '20202020-3115-404f-aade-e1154b28e35a',
|
||||
messageChannelMessageAssociations: '20202020-314e-40a4-906d-a5d5d6c285f6',
|
||||
messageThreadSubscribers: '20202020-3b3b-4b3b-8b3b-7f8d6a1d7d5b',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS = {
|
||||
messageThread: '20202020-2c8f-4f3e-8b9a-7f8d6a1c7d5b',
|
||||
workspaceMember: '20202020-7f7b-4b3b-8b3b-7f8d6a1d7d5a',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_STANDARD_FIELD_IDS = {
|
||||
headerMessageId: '20202020-72b5-416d-aed8-b55609067d01',
|
||||
messageThread: '20202020-30f2-4ccd-9f5c-e41bb9d26214',
|
||||
direction: '20202020-0203-4118-8e2a-05b9bdae6dab',
|
||||
subject: '20202020-52d1-4036-b9ae-84bd722bb37a',
|
||||
text: '20202020-d2ee-4e7e-89de-9a0a9044a143',
|
||||
receivedAt: '20202020-140a-4a2a-9f86-f13b6a979afc',
|
||||
messageParticipants: '20202020-7cff-4a74-b63c-73228448cbd9',
|
||||
messageChannelMessageAssociations: '20202020-3cef-43a3-82c6-50e7cfbc9ae4',
|
||||
} as const;
|
||||
|
||||
export const NOTE_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-368d-4dc2-943f-ed8a49c7fdfb',
|
||||
title: '20202020-faeb-4c76-8ba6-ccbb0b4a965f',
|
||||
body: '20202020-e63d-4e70-95be-a78cd9abe7ef',
|
||||
bodyV2: '20202020-a7bb-4d94-be51-8f25181502c8',
|
||||
createdBy: '20202020-0d79-4e21-ab77-5a394eff97be',
|
||||
updatedBy: '9b446e89-2484-4044-a3b5-420f6b578c0c',
|
||||
noteTargets: '20202020-1f25-43fe-8b00-af212fdde823',
|
||||
attachments: '20202020-4986-4c92-bf19-39934b149b16',
|
||||
timelineActivities: '20202020-7030-42f8-929c-1a57b25d6bce',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d67',
|
||||
searchVector: '20202020-7ea8-44d4-9d4c-51dd2a757950',
|
||||
} as const;
|
||||
|
||||
export const NOTE_TARGET_STANDARD_FIELD_IDS = {
|
||||
note: '20202020-57f3-4f50-9599-fc0f671df003',
|
||||
person: '20202020-38ca-4aab-92f5-8a605ca2e4c5',
|
||||
company: 'c500fbc0-d6f2-4982-a959-5a755431696c',
|
||||
opportunity: '20202020-4e42-417a-a705-76581c9ade79',
|
||||
custom: '20202020-3d12-4579-94ee-7117c1bad492',
|
||||
} as const;
|
||||
|
||||
export const OPPORTUNITY_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-8609-4f65-a2d9-44009eb422b5',
|
||||
amount: '20202020-583e-4642-8533-db761d5fa82f',
|
||||
closeDate: '20202020-527e-44d6-b1ac-c4158d307b97',
|
||||
probabilityDeprecated: '20202020-69d4-45f3-9703-690b09fafcf0',
|
||||
stage: '20202020-6f76-477d-8551-28cd65b2b4b9',
|
||||
position: '20202020-806d-493a-bbc6-6313e62958e2',
|
||||
createdBy: '20202020-a63e-4a62-8e63-42a51828f831',
|
||||
updatedBy: '3c8a6095-3f64-4e81-a59e-66c2bd181e11',
|
||||
pointOfContact: '20202020-8dfb-42fc-92b6-01afb759ed16',
|
||||
company: '20202020-cbac-457e-b565-adece5fc815f',
|
||||
favorites: '20202020-a1c2-4500-aaae-83ba8a0e827a',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-220a-42d6-8261-b2102d6eab35',
|
||||
taskTargets: '20202020-59c0-4179-a208-4a255f04a5be',
|
||||
noteTargets: '20202020-dd3f-42d5-a382-db58aabf43d3',
|
||||
attachments: '20202020-87c7-4118-83d6-2f4031005209',
|
||||
timelineActivities: '20202020-30e2-421f-96c7-19c69d1cf631',
|
||||
searchVector: '428a0da5-4b2e-4ce3-b695-89a8b384e6e3',
|
||||
} as const;
|
||||
|
||||
export const PERSON_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-3875-44d5-8c33-a6239011cab8',
|
||||
email: '20202020-a740-42bb-8849-8980fb3f12e1',
|
||||
emails: '20202020-3c51-43fa-8b6e-af39e29368ab',
|
||||
linkedinLink: '20202020-f1af-48f7-893b-2007a73dd508',
|
||||
xLink: '20202020-8fc2-487c-b84a-55a99b145cfd',
|
||||
jobTitle: '20202020-b0d0-415a-bef9-640a26dacd9b',
|
||||
phone: '20202020-4564-4b8b-a09f-05445f2e0bce',
|
||||
phones: '20202020-0638-448e-8825-439134618022',
|
||||
city: '20202020-5243-4ffb-afc5-2c675da41346',
|
||||
avatarUrl: '20202020-b8a6-40df-961c-373dc5d2ec21',
|
||||
position: '20202020-fcd5-4231-aff5-fff583eaa0b1',
|
||||
createdBy: '20202020-f6ab-4d98-af24-a3d5b664148a',
|
||||
updatedBy: 'e9e0dd35-184c-4742-84da-afadf45ce59a',
|
||||
company: '20202020-e2f3-448e-b34c-2d625f0025fd',
|
||||
pointOfContactForOpportunities: '20202020-911b-4a7d-b67b-918aa9a5b33a',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-dee7-4b7f-b50a-1f50bd3be452',
|
||||
taskTargets: '20202020-584b-4d3e-88b6-53ab1fa03c3a',
|
||||
noteTargets: '20202020-c8fc-4258-8250-15905d3fcfec',
|
||||
favorites: '20202020-4073-4117-9cf1-203bcdc91cbd',
|
||||
attachments: '20202020-cd97-451f-87fa-bcb789bdbf3a',
|
||||
messageParticipants: '20202020-498e-4c61-8158-fa04f0638334',
|
||||
calendarEventParticipants: '20202020-52ee-45e9-a702-b64b3753e3a9',
|
||||
timelineActivities: '20202020-a43e-4873-9c23-e522de906ce5',
|
||||
searchVector: '57d1d7ad-fa10-44fc-82f3-ad0959ec2534',
|
||||
} as const;
|
||||
|
||||
export const TASK_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-7d47-4690-8a98-98b9a0c05dd8',
|
||||
title: '20202020-b386-4cb7-aa5a-08d4a4d92680',
|
||||
body: '20202020-ce13-43f4-8821-69388fe1fd26',
|
||||
bodyV2: '20202020-4aa0-4ae8-898d-7df0afd47ab1',
|
||||
dueAt: '20202020-fd99-40da-951b-4cb9a352fce3',
|
||||
status: '20202020-70bc-48f9-89c5-6aa730b151e0',
|
||||
createdBy: '20202020-1a04-48ab-a567-576965ae5387',
|
||||
updatedBy: '9e8bf518-f4ab-433e-9674-efb75fba2802',
|
||||
taskTargets: '20202020-de9c-4d0e-a452-713d4a3e5fc7',
|
||||
attachments: '20202020-794d-4783-a8ff-cecdb15be139',
|
||||
assignee: '20202020-065a-4f42-a906-e20422c1753f',
|
||||
timelineActivities: '20202020-c778-4278-99ee-23a2837aee64',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d65',
|
||||
searchVector: '20202020-4746-4e2f-870c-52b02c67c90d',
|
||||
} as const;
|
||||
|
||||
export const TASK_TARGET_STANDARD_FIELD_IDS = {
|
||||
task: '20202020-e881-457a-8758-74aaef4ae78a',
|
||||
person: '20202020-c8a0-4e85-a016-87e2349cfbec',
|
||||
company: '20202020-4703-4a4e-948c-487b0c60a92c',
|
||||
opportunity: '20202020-6cb2-4c01-a9a5-aca3dbc11d41',
|
||||
custom: '20202020-41c1-4c9a-8c75-be0971ef89af',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FIELD_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-135f-4c5b-b361-15f24870473c',
|
||||
isVisible: '20202020-e966-473c-9c18-f00d3347e0ba',
|
||||
size: '20202020-6fab-4bd0-ae72-20f3ee39d581',
|
||||
position: '20202020-19e5-4e4c-8c15-3a96d1fd0650',
|
||||
view: '20202020-e8da-4521-afab-d6d231f9fa18',
|
||||
aggregateOperation: '20202020-2cd7-4f94-ae83-4a14f5731a04',
|
||||
} as const;
|
||||
|
||||
export const VIEW_GROUP_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-8f26-46ae-afed-fdacd7778682',
|
||||
fieldValue: '20202020-175e-4596-b7a4-1cd9d14e5a30',
|
||||
isVisible: '20202020-0fed-4b44-88fd-a064c4fcfce4',
|
||||
position: '20202020-748e-4645-8f32-84aae7726c04',
|
||||
view: '20202020-5bc7-4110-b23f-fb851fb133b4',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FILTER_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-c9aa-4c94-8d0e-9592f5008fb0',
|
||||
operand: '20202020-bd23-48c4-9fab-29d1ffb80310',
|
||||
value: '20202020-1e55-4a1e-a1d2-fefb86a5fce5',
|
||||
displayValue: '20202020-1270-4ebf-9018-c0ec10d5038e',
|
||||
view: '20202020-4f5b-487e-829c-3d881c163611',
|
||||
viewFilterGroupId: '20202020-2580-420a-8328-cab1635c0296',
|
||||
positionInViewFilterGroup: '20202020-3bb0-4f66-a537-a46fe0dc468f',
|
||||
subFieldName: '20202020-3bb0-4f66-a537-a46fe0dc469a',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FILTER_GROUP_STANDARD_FIELD_IDS = {
|
||||
view: '20202020-ff7a-4b54-8be5-aa0249047b74',
|
||||
parentViewFilterGroupId: '20202020-edbf-4929-8ede-64f48d6bf2a7',
|
||||
logicalOperator: '20202020-64d9-4bc5-85ba-c250796ce9aa',
|
||||
positionInViewFilterGroup: '20202020-90d6-4299-ad87-d05ddd3a0a3f',
|
||||
} as const;
|
||||
|
||||
export const VIEW_SORT_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-8240-4657-aee4-7f0df8e94eca',
|
||||
direction: '20202020-b06e-4eb3-9b58-0a62e5d79836',
|
||||
view: '20202020-bd6c-422b-9167-5c105f2d02c8',
|
||||
} as const;
|
||||
|
||||
export const VIEW_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-12c6-4f37-b588-c9b9bf57328d',
|
||||
objectMetadataId: '20202020-d6de-4fd5-84dd-47f9e730368b',
|
||||
type: '20202020-dd11-4607-9ec7-c57217262a7f',
|
||||
key: '20202020-298e-49fa-9f4a-7b416b110443',
|
||||
icon: '20202020-1f08-4fd9-929b-cbc07f317166',
|
||||
kanbanFieldMetadataId: '20202020-d09b-4f65-ac42-06a2f20ba0e8',
|
||||
kanbanAggregateOperation: '20202020-8da2-45de-a731-61bed84b17a8',
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
'20202020-b1b3-4bf3-85e4-dc7d58aa9b02',
|
||||
mainGroupByFieldMetadataId: '20202020-f782-4f89-96eb-083a02cca887',
|
||||
position: '20202020-e9db-4303-b271-e8250c450172',
|
||||
isCompact: '20202020-674e-4314-994d-05754ea7b22b',
|
||||
openRecordIn: '20202020-086d-4eef-9f03-56c6392eacb8',
|
||||
viewFields: '20202020-542b-4bdc-b177-b63175d48edf',
|
||||
viewGroups: '20202020-e1a1-419f-ac81-1986a5ea59a8',
|
||||
viewFilters: '20202020-ff23-4154-b63c-21fb36cd0967',
|
||||
viewFilterGroups: '20202020-0318-474a-84a1-bac895ceaa5a',
|
||||
viewSorts: '20202020-891b-45c3-9fe1-80a75b4aa043',
|
||||
favorites: '20202020-c818-4a86-8284-9ec0ef0a59a5',
|
||||
anyFieldFilterValue: '20202020-3143-46c0-bb05-034063ce0703',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS = {
|
||||
type: '20202020-3319-4234-a34c-3f92c1ab56e7',
|
||||
settings: '20202020-3319-4234-a34c-bac8f903de12',
|
||||
workflow: '20202020-3319-4234-a34c-8e1a4d2f7c03',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-b3d3-478f-acc0-5d901e725b20',
|
||||
lastPublishedVersionId: '20202020-326a-4fba-8639-3456c0a169e8',
|
||||
statuses: '20202020-357c-4432-8c50-8c31b4a552d9',
|
||||
position: '20202020-39b0-4d8c-8c5f-33c2326deb5f',
|
||||
versions: '20202020-9432-416e-8f3c-27ee3153d099',
|
||||
runs: '20202020-759b-4340-b58b-e73595c4df4f',
|
||||
eventListeners: '20202020-0229-4c66-832e-035c67579a38',
|
||||
automatedTriggers: '20202020-3319-4234-a34c-117ecad2b8a9',
|
||||
favorites: '20202020-c554-4c41-be7a-cf9cd4b0d512',
|
||||
timelineActivities: '20202020-906e-486a-a798-131a5f081faf',
|
||||
attachments: '20202020-4a8c-4e2d-9b1c-7e5f3a2b4c6d',
|
||||
createdBy: '20202020-6007-401a-8aa5-e6f48581a6f3',
|
||||
updatedBy: '3559831e-caf2-4eb5-9db1-b47bf968c774',
|
||||
searchVector: '20202020-535d-4ffa-b7f3-4fa0d5da1b7a',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_RUN_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-b840-4253-aef9-4e5013694587',
|
||||
workflowVersion: '20202020-2f52-4ba8-8dc4-d0d6adb9578d',
|
||||
workflow: '20202020-8c57-4e7f-84f5-f373f68e1b82',
|
||||
enqueuedAt: '20202020-f1e3-4de1-a461-b5c4fdbc861d',
|
||||
startedAt: '20202020-a234-4e2d-bd15-85bcea6bb183',
|
||||
endedAt: '20202020-e1c1-4b6b-bbbd-b2beaf2e159e',
|
||||
status: '20202020-6b3e-4f9c-8c2b-2e5b8e6d6f3b',
|
||||
position: '20202020-7802-4c40-ae89-1f506fe3365c',
|
||||
createdBy: '20202020-6007-401a-8aa5-e6f38581a6f3',
|
||||
updatedBy: '730dc1c9-34f5-4c22-84a6-bcb55b7604e2',
|
||||
output: '20202020-7be4-4db2-8ac6-3ff0d740843d',
|
||||
context: '20202020-189c-478a-b867-d72feaf5926a',
|
||||
state: '20202020-611f-45f3-9cde-d64927e8ec57',
|
||||
favorites: '20202020-4baf-4604-b899-2f7fcfbbf90d',
|
||||
timelineActivities: '20202020-af4d-4eb0-babc-eb960a45b356',
|
||||
searchVector: '20202020-0b91-4ded-b1ac-cbd5efa58cb9',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_VERSION_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-a12f-4cca-9937-a2e40cc65509',
|
||||
workflow: '20202020-afa3-46c3-91b0-0631ca6aa1c8',
|
||||
trigger: '20202020-4eae-43e7-86e0-212b41a30b48',
|
||||
status: '20202020-5a34-440e-8a25-39d8c3d1d4cf',
|
||||
position: '20202020-791d-4950-ab28-0e704767ae1c',
|
||||
runs: '20202020-1d08-46df-901a-85045f18099a',
|
||||
steps: '20202020-5988-4a64-b94a-1f9b7b989039',
|
||||
favorites: '20202020-b8e0-4e57-928d-b51671cc71f2',
|
||||
timelineActivities: '20202020-fcb0-4695-b17e-3b43a421c633',
|
||||
searchVector: '20202020-3f17-44ef-b8c1-b282ae8469b2',
|
||||
} as const;
|
||||
|
||||
export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-1810-4591-a93c-d0df97dca843',
|
||||
name: '20202020-e914-43a6-9c26-3603c59065f4',
|
||||
colorScheme: '20202020-66bc-47f2-adac-f2ef7c598b63',
|
||||
locale: '20202020-402e-4695-b169-794fa015afbe',
|
||||
avatarUrl: '20202020-0ced-4c4f-a376-c98a966af3f6',
|
||||
userEmail: '20202020-4c5f-4e09-bebc-9e624e21ecf4',
|
||||
userId: '20202020-75a9-4dfc-bf25-2e4b43e89820',
|
||||
authoredActivities: '20202020-f139-4f13-a82f-a65a8d290a74',
|
||||
assignedActivities: '20202020-5c97-42b6-8ca9-c07622cbb33f',
|
||||
assignedTasks: '20202020-61dc-4a1c-99e8-38ebf8d2bbeb',
|
||||
favorites: '20202020-f3c1-4faf-b343-cf7681038757',
|
||||
accountOwnerForCompanies: '20202020-dc29-4bd4-a3c1-29eafa324bee',
|
||||
authoredAttachments: '20202020-000f-4947-917f-1b09851024fe',
|
||||
authoredComments: '20202020-5536-4f59-b837-51c45ef43b05',
|
||||
connectedAccounts: '20202020-e322-4bde-a525-727079b4a100',
|
||||
messageParticipants: '20202020-8f99-48bc-a5eb-edd33dd54188',
|
||||
blocklist: '20202020-6cb2-4161-9f29-a4b7f1283859',
|
||||
calendarEventParticipants: '20202020-0dbc-4841-9ce1-3e793b5b3512',
|
||||
timelineActivities: '20202020-e15b-47b8-94fe-8200e3c66615',
|
||||
auditLogs: '20202020-2f54-4739-a5e2-99563385e83d',
|
||||
messageThreadSubscribers: '20202020-4b3b-4b3b-9b3b-3b3b3b3b3b3b',
|
||||
timeZone: '20202020-2d33-4c21-a86e-5943b050dd54',
|
||||
dateFormat: '20202020-af13-4e11-b1e7-b8cf5ea13dc0',
|
||||
timeFormat: '20202020-8acb-4cf8-a851-a6ed443c8d81',
|
||||
searchVector: '20202020-46d0-4e7f-bc26-74c0edaeb619',
|
||||
calendarStartDay: '20202020-92d0-1d7f-a126-25ededa6b142',
|
||||
numberFormat: '20202020-7f40-4e7f-b126-11c0eda6b141',
|
||||
} as const;
|
||||
export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-ba07-4ffd-ba63-009491f5749c',
|
||||
position: '20202020-c2bd-4e16-bb9a-c8b0411bf49d',
|
||||
createdBy: '20202020-be0e-4971-865b-32ca87cbb315',
|
||||
updatedBy: 'd047ccb4-9469-4514-a982-29c4ae49317d',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-7f42-40ae-b96c-c8a61acc83bf',
|
||||
noteTargets: '20202020-01fd-4f37-99dc-9427a444018a',
|
||||
taskTargets: '20202020-0860-4566-b865-bff3c626c303',
|
||||
favorites: '20202020-a4a7-4686-b296-1c6c3482ee21',
|
||||
attachments: '20202020-8d59-46ca-b7b2-73d167712134',
|
||||
timelineActivities: '20202020-f1ef-4ba4-8f33-1a4577afa477',
|
||||
searchVector: '70e56537-18ef-4811-b1c7-0a444006b815',
|
||||
} as const;
|
||||
|
||||
export const DASHBOARD_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-20ee-4091-95dc-44b57eda3a89',
|
||||
position: '20202020-38af-409b-95f0-7f08aa5f420f',
|
||||
pageLayoutId: '20202020-bb53-4648-aa36-1d9d54e6f7f2',
|
||||
createdBy: '20202020-ff32-4fa1-b7ad-407cc6aa0734',
|
||||
updatedBy: '53ee42e7-f157-42b5-b278-a5fa9b378307',
|
||||
timelineActivities: '20202020-9b0c-5d6e-7f8a-9b0c1d2e3f4a',
|
||||
favorites: '20202020-f032-478f-88fa-6426ff6f1e4c',
|
||||
attachments: '20202020-bf6f-4220-8c55-2764f1175870',
|
||||
searchVector: '20202020-0bcc-47a4-8360-2e35a7133f7a',
|
||||
} as const;
|
||||
|
||||
export const STANDARD_OBJECT_FIELD_IDS = {
|
||||
activityTarget: ACTIVITY_TARGET_STANDARD_FIELD_IDS,
|
||||
activity: ACTIVITY_STANDARD_FIELD_IDS,
|
||||
attachment: ATTACHMENT_STANDARD_FIELD_IDS,
|
||||
blocklist: BLOCKLIST_STANDARD_FIELD_IDS,
|
||||
calendarChannelEventAssociation:
|
||||
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS,
|
||||
calendarChannel: CALENDAR_CHANNEL_STANDARD_FIELD_IDS,
|
||||
calendarEventParticipant: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS,
|
||||
calendarEvent: CALENDAR_EVENT_STANDARD_FIELD_IDS,
|
||||
comment: COMMENT_STANDARD_FIELD_IDS,
|
||||
company: COMPANY_STANDARD_FIELD_IDS,
|
||||
connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS,
|
||||
dashboard: DASHBOARD_STANDARD_FIELD_IDS,
|
||||
favorite: FAVORITE_STANDARD_FIELD_IDS,
|
||||
messageChannelMessageAssociation:
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS,
|
||||
messageChannel: MESSAGE_CHANNEL_STANDARD_FIELD_IDS,
|
||||
messageParticipant: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS,
|
||||
messageThread: MESSAGE_THREAD_STANDARD_FIELD_IDS,
|
||||
messageThreadSubscriber: MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS,
|
||||
message: MESSAGE_STANDARD_FIELD_IDS,
|
||||
note: NOTE_STANDARD_FIELD_IDS,
|
||||
noteTarget: NOTE_TARGET_STANDARD_FIELD_IDS,
|
||||
opportunity: OPPORTUNITY_STANDARD_FIELD_IDS,
|
||||
person: PERSON_STANDARD_FIELD_IDS,
|
||||
task: TASK_STANDARD_FIELD_IDS,
|
||||
taskTarget: TASK_TARGET_STANDARD_FIELD_IDS,
|
||||
timelineActivity: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS,
|
||||
viewField: VIEW_FIELD_STANDARD_FIELD_IDS,
|
||||
viewGroup: VIEW_GROUP_STANDARD_FIELD_IDS,
|
||||
viewFilter: VIEW_FILTER_STANDARD_FIELD_IDS,
|
||||
viewSort: VIEW_SORT_STANDARD_FIELD_IDS,
|
||||
view: VIEW_STANDARD_FIELD_IDS,
|
||||
workflow: WORKFLOW_STANDARD_FIELD_IDS,
|
||||
workflowRun: WORKFLOW_RUN_STANDARD_FIELD_IDS,
|
||||
workflowVersion: WORKFLOW_VERSION_STANDARD_FIELD_IDS,
|
||||
workspaceMember: WORKSPACE_MEMBER_STANDARD_FIELD_IDS,
|
||||
} as const;
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
export const STANDARD_OBJECT_ICONS = {
|
||||
activityTarget: 'IconCheckbox',
|
||||
activity: 'IconCheckbox',
|
||||
apiKey: 'IconRobot',
|
||||
attachment: 'IconFileImport',
|
||||
blocklist: 'IconForbid2',
|
||||
behavioralEvent: 'IconTimelineEvent',
|
||||
calendarChannelEventAssociation: 'IconCalendar',
|
||||
calendarChannel: 'IconCalendar',
|
||||
calendarEventParticipant: 'IconCalendar',
|
||||
calendarEvent: 'IconCalendar',
|
||||
comment: 'IconMessageCircle',
|
||||
company: 'IconBuildingSkyscraper',
|
||||
connectedAccount: 'IconAt',
|
||||
dashboard: 'IconLayoutDashboard',
|
||||
favorite: 'IconHeart',
|
||||
auditLog: 'IconTimelineEvent',
|
||||
messageChannelMessageAssociation: 'IconMessage',
|
||||
messageChannel: 'IconMessage',
|
||||
messageFolder: 'IconFolder',
|
||||
messageParticipant: 'IconUserCircle',
|
||||
messageThread: 'IconMessage',
|
||||
messageThreadSubscriber: 'IconPerson',
|
||||
message: 'IconMessage',
|
||||
note: 'IconNotes',
|
||||
noteTarget: 'IconCheckbox',
|
||||
opportunity: 'IconTargetArrow',
|
||||
person: 'IconUser',
|
||||
task: 'IconCheckbox',
|
||||
taskTarget: 'IconCheckbox',
|
||||
timelineActivity: 'IconTimelineEvent',
|
||||
viewField: 'IconTag',
|
||||
viewGroup: 'IconTag',
|
||||
viewFilter: 'IconFilterBolt',
|
||||
viewSort: 'IconArrowsSort',
|
||||
view: 'IconLayoutCollage',
|
||||
webhook: 'IconRobot',
|
||||
workflow: 'IconSettingsAutomation',
|
||||
workflowEventListener: 'IconSettingsAutomation',
|
||||
workflowRun: 'IconHistoryToggle',
|
||||
workflowVersion: 'IconVersions',
|
||||
workflowAutomatedTrigger: 'IconSettingsAutomation',
|
||||
workspaceMember: 'IconUserCircle',
|
||||
} as const;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type AdditionalCacheDataMaps } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
|
||||
export const WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY = [
|
||||
'featureFlagsMap',
|
||||
] as const satisfies (keyof AdditionalCacheDataMaps)[];
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type WorkspaceMigrationOrchestratorFailedResult } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
|
||||
export class WorkspaceMigrationBuilderException extends Error {
|
||||
constructor(
|
||||
public readonly failedWorkspaceMigrationBuildResult: WorkspaceMigrationOrchestratorFailedResult,
|
||||
message = 'Workspace migration builder failed',
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'WorkspaceMigrationBuilderException';
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { type I18n } from '@lingui/core';
|
||||
import { type MetadataValidationErrorResponse } from 'twenty-shared/metadata';
|
||||
|
||||
import { type WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
import { translateOrchestratorFailureReportErrors } from 'src/engine/workspace-manager/workspace-migration/interceptors/utils/translate-orchestrator-failure-report-errors.util';
|
||||
|
||||
export const fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseError =
|
||||
(
|
||||
workspaceMigrationBuilderException: WorkspaceMigrationBuilderException,
|
||||
i18n: I18n,
|
||||
): MetadataValidationErrorResponse => {
|
||||
const translatedReport = translateOrchestratorFailureReportErrors(
|
||||
workspaceMigrationBuilderException.failedWorkspaceMigrationBuildResult
|
||||
.report,
|
||||
i18n,
|
||||
);
|
||||
|
||||
const initialAccumulator: MetadataValidationErrorResponse = {
|
||||
errors: {},
|
||||
summary: {
|
||||
totalErrors: 0,
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
Object.keys(translatedReport) as (keyof typeof translatedReport)[]
|
||||
).reduce((acc, metadataName) => {
|
||||
const failedMetadataValidation = translatedReport[metadataName];
|
||||
|
||||
if (failedMetadataValidation.length === 0) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return {
|
||||
errors: {
|
||||
...acc.errors,
|
||||
[metadataName]: failedMetadataValidation,
|
||||
},
|
||||
summary: {
|
||||
...acc.summary,
|
||||
totalErrors:
|
||||
acc.summary.totalErrors + failedMetadataValidation.length,
|
||||
[metadataName]: failedMetadataValidation.length,
|
||||
},
|
||||
} satisfies MetadataValidationErrorResponse;
|
||||
}, initialAccumulator);
|
||||
};
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import { type I18n, type MessageDescriptor } from '@lingui/core';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type OrchestratorFailureReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type FlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
const isMessageDescriptor = (obj: unknown): obj is MessageDescriptor =>
|
||||
isDefined(obj) &&
|
||||
typeof obj === 'object' &&
|
||||
Object.prototype.hasOwnProperty.call(obj, 'id') &&
|
||||
Object.prototype.hasOwnProperty.call(obj, 'message') &&
|
||||
typeof (obj as MessageDescriptor).id === 'string';
|
||||
|
||||
const translateUserFriendlyMessageInFlatEntityValidationError = <T>(
|
||||
obj: T,
|
||||
i18n: I18n,
|
||||
parentKey?: string,
|
||||
): T => {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (
|
||||
isMessageDescriptor(obj) &&
|
||||
isDefined(parentKey) &&
|
||||
parentKey ===
|
||||
('userFriendlyMessage' as const satisfies keyof FlatEntityValidationError)
|
||||
) {
|
||||
return i18n._(obj) as T;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) =>
|
||||
translateUserFriendlyMessageInFlatEntityValidationError(
|
||||
item,
|
||||
i18n,
|
||||
parentKey,
|
||||
),
|
||||
) as T;
|
||||
}
|
||||
|
||||
const result = {} as T;
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
(result as Record<string, unknown>)[key] =
|
||||
translateUserFriendlyMessageInFlatEntityValidationError(value, i18n, key);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const translateOrchestratorFailureReportErrors = (
|
||||
report: OrchestratorFailureReport,
|
||||
i18n: I18n,
|
||||
) => {
|
||||
return translateUserFriendlyMessageInFlatEntityValidationError(report, i18n);
|
||||
};
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { type I18n } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
BaseGraphQLError,
|
||||
ErrorCode,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { type WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
import { fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseError } from 'src/engine/workspace-manager/workspace-migration/interceptors/utils/from-workspace-migration-builder-exception-to-metadata-validation-response-error.util';
|
||||
|
||||
export const workspaceMigrationBuilderExceptionFormatter = (
|
||||
error: WorkspaceMigrationBuilderException,
|
||||
i18n: I18n,
|
||||
) => {
|
||||
const { errors, summary } =
|
||||
fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseError(
|
||||
error,
|
||||
i18n,
|
||||
);
|
||||
|
||||
const message = `Validation failed for ${Object.values(ALL_METADATA_NAME)
|
||||
.flatMap((metadataName) => {
|
||||
const count = summary[metadataName];
|
||||
|
||||
if (!isDefined(count) || count === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [`${count} ${metadataName}${count > 1 ? 's' : ''}`];
|
||||
})
|
||||
.join(', ')}`;
|
||||
|
||||
throw new BaseGraphQLError(
|
||||
error.message,
|
||||
ErrorCode.METADATA_VALIDATION_FAILED,
|
||||
{
|
||||
code: 'METADATA_VALIDATION_ERROR',
|
||||
errors,
|
||||
summary,
|
||||
message,
|
||||
userFriendlyMessage: msg`Metadata validation failed`,
|
||||
},
|
||||
);
|
||||
};
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
type CallHandler,
|
||||
type ExecutionContext,
|
||||
Injectable,
|
||||
type NestInterceptor,
|
||||
} from '@nestjs/common';
|
||||
import { GqlExecutionContext } from '@nestjs/graphql';
|
||||
|
||||
import { type Observable, catchError } from 'rxjs';
|
||||
import { SOURCE_LOCALE } from 'twenty-shared/translations';
|
||||
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
import { workspaceMigrationBuilderExceptionFormatter } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-builder-exception-formatter';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor
|
||||
implements NestInterceptor
|
||||
{
|
||||
constructor(private readonly i18nService: I18nService) {}
|
||||
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
|
||||
const gqlContext = GqlExecutionContext.create(context);
|
||||
const ctx = gqlContext.getContext();
|
||||
const locale = ctx.req?.locale ?? SOURCE_LOCALE;
|
||||
const i18n = this.i18nService.getI18nInstance(locale);
|
||||
|
||||
return next.handle().pipe(
|
||||
catchError((error) => {
|
||||
if (error instanceof WorkspaceMigrationBuilderException) {
|
||||
workspaceMigrationBuilderExceptionFormatter(error, i18n);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
+1075
File diff suppressed because it is too large
Load Diff
+238
@@ -0,0 +1,238 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
AllMetadataName,
|
||||
WorkspaceMigrationV2ExceptionCode,
|
||||
} from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-required-metadata-for-validation.constant';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { FlatEntityToCreateDeleteUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-to-create-delete-update.type';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { WorkspaceMigrationV2Exception } from 'src/engine/workspace-manager/workspace-migration.exception';
|
||||
import { WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY } from 'src/engine/workspace-manager/workspace-migration/constant/workspace-migration-additional-cache-data-maps-key.constant';
|
||||
import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-build-orchestrator.service';
|
||||
import { WorkspaceMigrationBuilderAdditionalCacheDataMaps } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-builder-additional-cache-data-maps.type';
|
||||
import {
|
||||
FromToAllFlatEntityMaps,
|
||||
WorkspaceMigrationOrchestratorBuildArgs,
|
||||
WorkspaceMigrationOrchestratorFailedResult,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { InferDeletionFromMissingEntities } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/infer-deletion-from-missing-entities.type';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
type ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs = {
|
||||
workspaceId: string;
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
[P in AllMetadataName]?: FlatEntityToCreateDeleteUpdate<P>;
|
||||
};
|
||||
isSystemBuild?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationValidateBuildAndRunService {
|
||||
private readonly logger = new Logger(
|
||||
WorkspaceMigrationValidateBuildAndRunService.name,
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceMigrationBuildOrchestratorService: WorkspaceMigrationBuildOrchestratorService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {}
|
||||
|
||||
private async computeAllRelatedFlatEntityMaps({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
workspaceId,
|
||||
}: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs) {
|
||||
const allMetadataNameToCompare = Object.keys(
|
||||
allFlatEntityOperationByMetadataName,
|
||||
) as AllMetadataName[];
|
||||
const allDependencyMetadataName = allMetadataNameToCompare.flatMap(
|
||||
(metadataName) =>
|
||||
Object.keys(
|
||||
ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION[metadataName],
|
||||
) as AllMetadataName[],
|
||||
);
|
||||
const allMetadataNameCacheToCompute = [
|
||||
...new Set([...allMetadataNameToCompare, ...allDependencyMetadataName]),
|
||||
];
|
||||
const allFlatEntityMapsCacheKeysToCompute =
|
||||
allMetadataNameCacheToCompute.map(getMetadataFlatEntityMapsKey);
|
||||
|
||||
const allRelatedFlatEntityMaps =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
...allFlatEntityMapsCacheKeysToCompute,
|
||||
...WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY,
|
||||
]);
|
||||
|
||||
const initialAccumulator = allDependencyMetadataName.reduce<
|
||||
Partial<AllFlatEntityMaps>
|
||||
>(
|
||||
(allFlatEntityMaps, metadataName) => ({
|
||||
...allFlatEntityMaps,
|
||||
[getMetadataFlatEntityMapsKey(metadataName)]:
|
||||
createEmptyFlatEntityMaps(),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
const dependencyAllFlatEntityMaps = allDependencyMetadataName.reduce(
|
||||
(allFlatEntityMaps, metadataName) => {
|
||||
const metadataFlatEntityMapsKey =
|
||||
getMetadataFlatEntityMapsKey(metadataName);
|
||||
|
||||
return {
|
||||
...allFlatEntityMaps,
|
||||
[metadataFlatEntityMapsKey]:
|
||||
allRelatedFlatEntityMaps[metadataFlatEntityMapsKey],
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
const additionalCacheDataMaps =
|
||||
WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY.reduce<WorkspaceMigrationBuilderAdditionalCacheDataMaps>(
|
||||
(acc, additionalCacheDataMapsKey) => {
|
||||
return {
|
||||
...acc,
|
||||
[additionalCacheDataMapsKey]:
|
||||
allRelatedFlatEntityMaps[additionalCacheDataMapsKey],
|
||||
};
|
||||
},
|
||||
{} as WorkspaceMigrationBuilderAdditionalCacheDataMaps,
|
||||
);
|
||||
|
||||
return {
|
||||
allRelatedFlatEntityMaps,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
};
|
||||
}
|
||||
|
||||
private async computeFromToAllFlatEntityMapsAndBuildOptions({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
workspaceId,
|
||||
}: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs): Promise<{
|
||||
fromToAllFlatEntityMaps: FromToAllFlatEntityMaps;
|
||||
inferDeletionFromMissingEntities: InferDeletionFromMissingEntities;
|
||||
dependencyAllFlatEntityMaps: Partial<AllFlatEntityMaps>;
|
||||
additionalCacheDataMaps: WorkspaceMigrationBuilderAdditionalCacheDataMaps;
|
||||
}> {
|
||||
const {
|
||||
allRelatedFlatEntityMaps,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
} = await this.computeAllRelatedFlatEntityMaps({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const fromToAllFlatEntityMaps: FromToAllFlatEntityMaps = {};
|
||||
const inferDeletionFromMissingEntities: InferDeletionFromMissingEntities =
|
||||
{};
|
||||
const allMetadataNameToCompare = Object.keys(
|
||||
allFlatEntityOperationByMetadataName,
|
||||
) as AllMetadataName[];
|
||||
|
||||
for (const metadataName of allMetadataNameToCompare) {
|
||||
const flatEntityOperations =
|
||||
allFlatEntityOperationByMetadataName[metadataName];
|
||||
|
||||
if (!isDefined(flatEntityOperations)) {
|
||||
throw new Error('Should never occurs');
|
||||
}
|
||||
const { flatEntityToCreate, flatEntityToDelete, flatEntityToUpdate } =
|
||||
flatEntityOperations;
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
const flatEntityMaps = allRelatedFlatEntityMaps[flatEntityMapsKey];
|
||||
|
||||
// @ts-expect-error Metadata flat entity maps cache key and metadataName colliding
|
||||
fromToAllFlatEntityMaps[flatEntityMapsKey] = computeFlatEntityMapsFromTo({
|
||||
flatEntityMaps,
|
||||
flatEntityToCreate,
|
||||
flatEntityToDelete,
|
||||
flatEntityToUpdate,
|
||||
});
|
||||
|
||||
if (flatEntityToDelete.length > 0) {
|
||||
inferDeletionFromMissingEntities[metadataName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fromToAllFlatEntityMaps,
|
||||
inferDeletionFromMissingEntities,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
};
|
||||
}
|
||||
|
||||
public async validateBuildAndRunWorkspaceMigrationFromTo(
|
||||
args: WorkspaceMigrationOrchestratorBuildArgs,
|
||||
) {
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationBuildOrchestratorService
|
||||
.buildWorkspaceMigration(args)
|
||||
.catch((error) => {
|
||||
this.logger.error(error);
|
||||
throw new WorkspaceMigrationV2Exception(
|
||||
WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR,
|
||||
error.message,
|
||||
);
|
||||
});
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
return validateAndBuildResult;
|
||||
}
|
||||
|
||||
// Note: This should be removed once we've refactored the runner optimistic rendering
|
||||
// As with the current implementation passing an empty workspace migration might result
|
||||
// in dependency flat entity maps invalidation
|
||||
if (validateAndBuildResult.workspaceMigration.actions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.workspaceMigrationRunnerService
|
||||
.run(validateAndBuildResult.workspaceMigration)
|
||||
.catch((error) => {
|
||||
this.logger.error(error);
|
||||
throw new WorkspaceMigrationV2Exception(
|
||||
WorkspaceMigrationV2ExceptionCode.RUNNER_INTERNAL_SERVER_ERROR,
|
||||
error.message,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public async validateBuildAndRunWorkspaceMigration({
|
||||
allFlatEntityOperationByMetadataName: allFlatEntities,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
}: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs): Promise<
|
||||
WorkspaceMigrationOrchestratorFailedResult | undefined
|
||||
> {
|
||||
const {
|
||||
fromToAllFlatEntityMaps,
|
||||
inferDeletionFromMissingEntities,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
} = await this.computeFromToAllFlatEntityMapsAndBuildOptions({
|
||||
allFlatEntityOperationByMetadataName: allFlatEntities,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return await this.validateBuildAndRunWorkspaceMigrationFromTo({
|
||||
buildOptions: {
|
||||
isSystemBuild,
|
||||
inferDeletionFromMissingEntities,
|
||||
},
|
||||
fromToAllFlatEntityMaps,
|
||||
workspaceId,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
});
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Wrapper type used to circumvent ESM modules circular dependency issue
|
||||
* caused by reflection metadata saving the type of the property.
|
||||
*/
|
||||
export type EntityRelation<T> = T;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
export type PropertyUpdate<T, P extends keyof T> = {
|
||||
property: P;
|
||||
} & FromTo<T[P]>;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
|
||||
export type AggregateOrchestratorActionsReportArgs = {
|
||||
orchestratorActionsReport: OrchestratorActionsReport;
|
||||
flatFieldMetadataMaps?: FlatEntityMaps<FlatFieldMetadata>;
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { type AdditionalCacheDataMaps } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
import { type WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY } from 'src/engine/workspace-manager/workspace-migration/constant/workspace-migration-additional-cache-data-maps-key.constant';
|
||||
|
||||
export type WorkspaceMigrationBuilderAdditionalCacheDataMaps = Pick<
|
||||
AdditionalCacheDataMaps,
|
||||
(typeof WORKSPACE_MIGRATION_ADDITIONAL_CACHE_DATA_MAPS_KEY)[number]
|
||||
>;
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import {
|
||||
type MetadataWorkspaceMigrationActionsRecord,
|
||||
type WorkspaceMigrationActionType,
|
||||
} from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type WorkspaceMigrationBuilderAdditionalCacheDataMaps } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-builder-additional-cache-data-maps.type';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
import { type WorkspaceMigration } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration';
|
||||
|
||||
export type FromToAllFlatEntityMaps = {
|
||||
[P in keyof AllFlatEntityMaps]?: FromTo<AllFlatEntityMaps[P]>;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationOrchestratorBuildArgs = {
|
||||
workspaceId: string;
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
fromToAllFlatEntityMaps: FromToAllFlatEntityMaps;
|
||||
dependencyAllFlatEntityMaps?: Partial<AllFlatEntityMaps>;
|
||||
additionalCacheDataMaps: WorkspaceMigrationBuilderAdditionalCacheDataMaps;
|
||||
};
|
||||
|
||||
export type OrchestratorFailureReport = {
|
||||
[P in AllMetadataName]: FailedFlatEntityValidation<
|
||||
P,
|
||||
WorkspaceMigrationActionType
|
||||
>[];
|
||||
};
|
||||
|
||||
export type OrchestratorActionsReport = {
|
||||
[P in AllMetadataName]: MetadataWorkspaceMigrationActionsRecord<P>;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationOrchestratorFailedResult = {
|
||||
status: 'fail';
|
||||
report: OrchestratorFailureReport;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationOrchestratorSuccessfulResult = {
|
||||
status: 'success';
|
||||
workspaceMigration: WorkspaceMigration;
|
||||
};
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a created entity 1`] = `
|
||||
{
|
||||
"createdFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"applicationId": "application-id-1",
|
||||
"calendarViewIds": [],
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"icon": "icon",
|
||||
"id": "field-id-1",
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "flat field metadata label",
|
||||
"mainGroupByFieldMetadataViewIds": [],
|
||||
"morphId": null,
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": "object-metadata-id-1",
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
"universalIdentifier": "universal-identifier-1",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"viewFieldIds": [],
|
||||
"viewFilterIds": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
"idByUniversalIdentifier": {
|
||||
"universal-identifier-1": "field-id-1",
|
||||
},
|
||||
"universalIdentifiersByApplicationId": {
|
||||
"application-id-1": [
|
||||
"universal-identifier-1",
|
||||
],
|
||||
},
|
||||
},
|
||||
"deletedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"updatedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a deleted entity 1`] = `
|
||||
{
|
||||
"createdFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"deletedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"applicationId": "application-id-1",
|
||||
"calendarViewIds": [],
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"icon": "icon",
|
||||
"id": "field-id-1",
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "flat field metadata label",
|
||||
"mainGroupByFieldMetadataViewIds": [],
|
||||
"morphId": null,
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": "object-metadata-id-1",
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
"universalIdentifier": "universal-identifier-1",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"viewFieldIds": [],
|
||||
"viewFilterIds": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
"idByUniversalIdentifier": {
|
||||
"universal-identifier-1": "field-id-1",
|
||||
},
|
||||
"universalIdentifiersByApplicationId": {
|
||||
"application-id-1": [
|
||||
"universal-identifier-1",
|
||||
],
|
||||
},
|
||||
},
|
||||
"updatedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect an updated entity 1`] = `
|
||||
{
|
||||
"createdFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"deletedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"updatedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"updates": [
|
||||
{
|
||||
"from": false,
|
||||
"property": "isActive",
|
||||
"to": true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect created, deleted and updated entities 1`] = `
|
||||
{
|
||||
"createdFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-3": {
|
||||
"applicationId": "application-id-1",
|
||||
"calendarViewIds": [],
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"icon": "icon",
|
||||
"id": "field-id-3",
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "flat field metadata label",
|
||||
"mainGroupByFieldMetadataViewIds": [],
|
||||
"morphId": null,
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": "object-metadata-id-1",
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
"universalIdentifier": "universal-identifier-3",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"viewFieldIds": [],
|
||||
"viewFilterIds": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
"idByUniversalIdentifier": {
|
||||
"universal-identifier-3": "field-id-3",
|
||||
},
|
||||
"universalIdentifiersByApplicationId": {
|
||||
"application-id-1": [
|
||||
"universal-identifier-3",
|
||||
],
|
||||
},
|
||||
},
|
||||
"deletedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-2": {
|
||||
"applicationId": "application-id-1",
|
||||
"calendarViewIds": [],
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"icon": "icon",
|
||||
"id": "field-id-2",
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "flat field metadata label",
|
||||
"mainGroupByFieldMetadataViewIds": [],
|
||||
"morphId": null,
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": "object-metadata-id-1",
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
"universalIdentifier": "universal-identifier-2",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"viewFieldIds": [],
|
||||
"viewFilterIds": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
"idByUniversalIdentifier": {
|
||||
"universal-identifier-2": "field-id-2",
|
||||
},
|
||||
"universalIdentifiersByApplicationId": {
|
||||
"application-id-1": [
|
||||
"universal-identifier-2",
|
||||
],
|
||||
},
|
||||
},
|
||||
"updatedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"updates": [
|
||||
{
|
||||
"from": true,
|
||||
"property": "isActive",
|
||||
"to": false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should not detect deleted entities when inferDeletionFromMissingEntities is false 1`] = `
|
||||
{
|
||||
"createdFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"deletedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
"idByUniversalIdentifier": {},
|
||||
"universalIdentifiersByApplicationId": {},
|
||||
},
|
||||
"updatedFlatEntityMaps": {
|
||||
"byId": {},
|
||||
},
|
||||
}
|
||||
`;
|
||||
+491
@@ -0,0 +1,491 @@
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util';
|
||||
import { type CreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type CreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type CreateAggregationTestCase = EachTestingContext<{
|
||||
input: OrchestratorActionsReport;
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: Record<string, number>;
|
||||
expectCreateObjectActionPerObjectMetadataId: Record<string, number>;
|
||||
};
|
||||
}>;
|
||||
describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', () => {
|
||||
const testCases: CreateAggregationTestCase[] = [
|
||||
{
|
||||
title:
|
||||
'should aggregate single object with multiple fields into one object action',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should keep separate field actions when no matching object action exists',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'secondName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle multiple objects with their respective fields',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-2',
|
||||
id: 'object-2',
|
||||
nameSingular: 'company',
|
||||
namePlural: 'companies',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-2',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'name',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'industry',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
'object-2': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should handle mixed scenario with some fields merged and some kept separate',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-2',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'orphanField',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-2': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should aggregate multiple field actions for the same object when no create object action exists',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'email',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle empty actions report',
|
||||
context: {
|
||||
input: createEmptyOrchestratorActionsReport(),
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should not merge create_field actions containing relation fields into create_object',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'attachment',
|
||||
namePlural: 'attachments',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.RELATION,
|
||||
id: 'field-1',
|
||||
name: 'author',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { input, expected } }) => {
|
||||
const result =
|
||||
aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
const fieldActions = result.fieldMetadata.create as CreateFieldAction[];
|
||||
const fieldActionCounts = fieldActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.objectMetadataId] =
|
||||
(acc[action.objectMetadataId] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
const objectActions = result.objectMetadata
|
||||
.create as CreateObjectAction[];
|
||||
const objectActionCounts = objectActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.flatEntity.id] = (acc[action.flatEntity.id] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
Object.entries(
|
||||
expected.expectCreateFieldActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(fieldActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
Object.entries(
|
||||
expected.expectCreateObjectActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(objectActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
// Check total counts
|
||||
const expectedTotalFieldActions = Object.values(
|
||||
expected.expectCreateFieldActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
const expectedTotalObjectActions = Object.values(
|
||||
expected.expectCreateObjectActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
|
||||
expect(fieldActions).toHaveLength(expectedTotalFieldActions);
|
||||
expect(objectActions).toHaveLength(expectedTotalObjectActions);
|
||||
},
|
||||
);
|
||||
});
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-delete-object-and-delete-field.util';
|
||||
import { type DeleteFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type DeleteObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type DeleteAggregationTestCase = EachTestingContext<{
|
||||
input: OrchestratorActionsReport;
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: Record<string, number>;
|
||||
expectDeleteObjectActionPerObjectMetadataId: Record<string, number>;
|
||||
};
|
||||
}>;
|
||||
|
||||
describe('aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions', () => {
|
||||
const testCases: DeleteAggregationTestCase[] = [
|
||||
{
|
||||
title: 'should remove field actions when parent object is being deleted',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: 'object-1',
|
||||
} satisfies DeleteObjectAction,
|
||||
],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
} satisfies DeleteFieldAction,
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
} satisfies DeleteFieldAction,
|
||||
],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: {},
|
||||
expectDeleteObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should keep field actions when no parent object is being deleted',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
} satisfies DeleteFieldAction,
|
||||
],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectDeleteObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should handle mixed scenario with some fields removed and some kept',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: 'object-1',
|
||||
} satisfies DeleteObjectAction,
|
||||
],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
} satisfies DeleteFieldAction,
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
} satisfies DeleteFieldAction,
|
||||
],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: {
|
||||
'object-2': 1,
|
||||
},
|
||||
expectDeleteObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle multiple objects with mixed field deletions',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: 'object-1',
|
||||
} satisfies DeleteObjectAction,
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: 'object-2',
|
||||
} satisfies DeleteObjectAction,
|
||||
],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
} satisfies DeleteFieldAction,
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
} satisfies DeleteFieldAction,
|
||||
{
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'field-3',
|
||||
objectMetadataId: 'object-3',
|
||||
} satisfies DeleteFieldAction,
|
||||
],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: {
|
||||
'object-3': 1,
|
||||
},
|
||||
expectDeleteObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
'object-2': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle empty actions report',
|
||||
context: {
|
||||
input: createEmptyOrchestratorActionsReport(),
|
||||
expected: {
|
||||
expectDeleteFieldActionPerObjectMetadataId: {},
|
||||
expectDeleteObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { input, expected } }) => {
|
||||
const result =
|
||||
aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
const fieldActions = result.fieldMetadata.delete as DeleteFieldAction[];
|
||||
const fieldActionCounts = fieldActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.objectMetadataId] =
|
||||
(acc[action.objectMetadataId] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
const objectActions = result.objectMetadata
|
||||
.delete as DeleteObjectAction[];
|
||||
const objectActionCounts = objectActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.entityId] = (acc[action.entityId] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
Object.entries(
|
||||
expected.expectDeleteFieldActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(fieldActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
Object.entries(
|
||||
expected.expectDeleteObjectActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(objectActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
// Check total counts
|
||||
const expectedTotalFieldActions = Object.values(
|
||||
expected.expectDeleteFieldActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
const expectedTotalObjectActions = Object.values(
|
||||
expected.expectDeleteObjectActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
|
||||
expect(fieldActions).toHaveLength(expectedTotalFieldActions);
|
||||
expect(objectActions).toHaveLength(expectedTotalObjectActions);
|
||||
},
|
||||
);
|
||||
});
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-deprioritize-search-vector-update-field-actions.util';
|
||||
import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions', () => {
|
||||
it('should move searchVector update actions to the end of the update list', () => {
|
||||
const orchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
fieldMetadata: {
|
||||
create: [],
|
||||
update: [
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'search-vector-field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'Search Vector',
|
||||
to: 'Updated Search Vector',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'regular-field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'First Name',
|
||||
to: 'Updated First Name',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'regular-field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'Last Name',
|
||||
to: 'Updated Last Name',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const flatFieldMetadataMaps = [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'search-vector-field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
id: 'search-vector-field-1',
|
||||
name: SEARCH_VECTOR_FIELD.name,
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'regular-field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'regular-field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'regular-field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'regular-field-2',
|
||||
name: 'lastName',
|
||||
}),
|
||||
].reduce<FlatEntityMaps<FlatFieldMetadata>>(
|
||||
(flatEntityMaps, field) =>
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: field,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
createEmptyFlatEntityMaps() as FlatEntityMaps<FlatFieldMetadata>,
|
||||
);
|
||||
|
||||
const result =
|
||||
aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions(
|
||||
{
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
},
|
||||
);
|
||||
|
||||
const updateFieldActions = result.fieldMetadata
|
||||
.update as UpdateFieldAction[];
|
||||
|
||||
const actualEntityIds = updateFieldActions.map((action) => action.entityId);
|
||||
|
||||
expect(actualEntityIds).toEqual([
|
||||
'regular-field-1',
|
||||
'regular-field-2',
|
||||
'search-vector-field-1',
|
||||
]);
|
||||
|
||||
expect(result.fieldMetadata.create).toEqual(
|
||||
orchestratorActionsReport.fieldMetadata.create,
|
||||
);
|
||||
expect(result.fieldMetadata.delete).toEqual(
|
||||
orchestratorActionsReport.fieldMetadata.delete,
|
||||
);
|
||||
expect(result.objectMetadata).toEqual(
|
||||
orchestratorActionsReport.objectMetadata,
|
||||
);
|
||||
});
|
||||
});
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { flatEntityDeletedCreatedUpdatedMatrixDispatcher } from 'src/engine/workspace-manager/workspace-migration/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
|
||||
type TestContext = FromTo<MetadataFlatEntity<'fieldMetadata'>[]> & {
|
||||
metadataName: 'fieldMetadata';
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
};
|
||||
|
||||
describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
|
||||
const testCases = [
|
||||
{
|
||||
title: 'It should detect a created entity',
|
||||
context: {
|
||||
from: [],
|
||||
to: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
}),
|
||||
],
|
||||
metadataName: 'fieldMetadata',
|
||||
buildOptions: {
|
||||
inferDeletionFromMissingEntities: { fieldMetadata: false },
|
||||
isSystemBuild: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'It should detect a deleted entity',
|
||||
context: {
|
||||
from: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
}),
|
||||
],
|
||||
to: [],
|
||||
metadataName: 'fieldMetadata',
|
||||
buildOptions: {
|
||||
inferDeletionFromMissingEntities: { fieldMetadata: true },
|
||||
isSystemBuild: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'It should detect an updated entity',
|
||||
context: {
|
||||
from: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
isActive: false,
|
||||
}),
|
||||
],
|
||||
to: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
}),
|
||||
],
|
||||
metadataName: 'fieldMetadata',
|
||||
buildOptions: {
|
||||
inferDeletionFromMissingEntities: { fieldMetadata: false },
|
||||
isSystemBuild: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'It should detect created, deleted and updated entities',
|
||||
context: {
|
||||
from: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-2',
|
||||
id: 'field-id-2',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
}),
|
||||
],
|
||||
to: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
isActive: false,
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-3',
|
||||
id: 'field-id-3',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
}),
|
||||
],
|
||||
metadataName: 'fieldMetadata',
|
||||
buildOptions: {
|
||||
inferDeletionFromMissingEntities: { fieldMetadata: true },
|
||||
isSystemBuild: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'It should not detect deleted entities when inferDeletionFromMissingEntities is false',
|
||||
context: {
|
||||
from: [
|
||||
getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'object-metadata-id-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
universalIdentifier: 'universal-identifier-1',
|
||||
id: 'field-id-1',
|
||||
workspaceId: 'workspace-id-1',
|
||||
applicationId: 'application-id-1',
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
}),
|
||||
],
|
||||
to: [],
|
||||
metadataName: 'fieldMetadata',
|
||||
buildOptions: {
|
||||
inferDeletionFromMissingEntities: { fieldMetadata: false },
|
||||
isSystemBuild: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
] as EachTestingContext<TestContext>[];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { from, to, metadataName, buildOptions } }) => {
|
||||
const result = flatEntityDeletedCreatedUpdatedMatrixDispatcher({
|
||||
from: from as any,
|
||||
to: to as any,
|
||||
metadataName,
|
||||
buildOptions,
|
||||
});
|
||||
|
||||
expect(result).toMatchSnapshot();
|
||||
},
|
||||
);
|
||||
});
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import {
|
||||
type CircularDependencyValidationResult,
|
||||
validateFlatEntityCircularDependency,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/utils/validate-flat-entity-circular-dependency.util';
|
||||
|
||||
type TestFlatEntity = SyncableFlatEntity & {
|
||||
parentId: string | null;
|
||||
};
|
||||
|
||||
const createFlatEntityMaps = (
|
||||
entities: TestFlatEntity[],
|
||||
): FlatEntityMaps<TestFlatEntity> => ({
|
||||
byId: Object.fromEntries(entities.map((entity) => [entity.id, entity])),
|
||||
idByUniversalIdentifier: Object.fromEntries(
|
||||
entities.map((entity) => [entity.universalIdentifier, entity.id]),
|
||||
),
|
||||
universalIdentifiersByApplicationId: {},
|
||||
});
|
||||
|
||||
const createTestEntity = (
|
||||
id: string,
|
||||
parentId: string | null = null,
|
||||
): TestFlatEntity => ({
|
||||
id,
|
||||
parentId,
|
||||
universalIdentifier: id,
|
||||
applicationId: 'test-app',
|
||||
workspaceId: 'test-workspace',
|
||||
});
|
||||
|
||||
type TestContext = {
|
||||
flatEntityId: string;
|
||||
flatEntityParentId: string;
|
||||
maxDepth?: number;
|
||||
entities: TestFlatEntity[];
|
||||
expected: CircularDependencyValidationResult;
|
||||
};
|
||||
|
||||
type ValidateCircularDependencyTestCase = EachTestingContext<TestContext>;
|
||||
|
||||
const testCases: ValidateCircularDependencyTestCase[] = [
|
||||
{
|
||||
title: 'should fail with self_reference when entity is its own parent',
|
||||
context: {
|
||||
flatEntityId: 'entity-1',
|
||||
flatEntityParentId: 'entity-1',
|
||||
entities: [],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'self_reference',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should succeed with depth 2 when parent has no parent',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'entity-parent',
|
||||
entities: [createTestEntity('entity-parent', null)],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should succeed with depth 3 when parent has a grandparent',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'entity-parent',
|
||||
entities: [
|
||||
createTestEntity('entity-grandparent', null),
|
||||
createTestEntity('entity-parent', 'entity-grandparent'),
|
||||
],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should fail with circular_dependency when parent points back to entity',
|
||||
context: {
|
||||
flatEntityId: 'entity-a',
|
||||
flatEntityParentId: 'entity-b',
|
||||
entities: [createTestEntity('entity-b', 'entity-a')],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'circular_dependency',
|
||||
depth: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should fail with circular_dependency when chain creates a cycle (A -> B -> C -> A)',
|
||||
context: {
|
||||
flatEntityId: 'entity-a',
|
||||
flatEntityParentId: 'entity-b',
|
||||
entities: [
|
||||
createTestEntity('entity-b', 'entity-c'),
|
||||
createTestEntity('entity-c', 'entity-a'),
|
||||
],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'circular_dependency',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should fail with circular_dependency when ancestors form a cycle among themselves',
|
||||
context: {
|
||||
flatEntityId: 'entity-new',
|
||||
flatEntityParentId: 'entity-a',
|
||||
entities: [
|
||||
createTestEntity('entity-a', 'entity-b'),
|
||||
createTestEntity('entity-b', 'entity-a'),
|
||||
],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'circular_dependency',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should succeed when parent does not exist in maps',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'non-existent-parent',
|
||||
entities: [],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should fail with max_depth_exceeded when depth exceeds maxDepth',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'entity-parent',
|
||||
maxDepth: 2,
|
||||
entities: [
|
||||
createTestEntity('entity-grandparent', null),
|
||||
createTestEntity('entity-parent', 'entity-grandparent'),
|
||||
],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'max_depth_exceeded',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should succeed when depth equals maxDepth',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'entity-parent',
|
||||
maxDepth: 3,
|
||||
entities: [
|
||||
createTestEntity('entity-grandparent', null),
|
||||
createTestEntity('entity-parent', 'entity-grandparent'),
|
||||
],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should succeed with depth 2 when maxDepth is 2 and parent is root',
|
||||
context: {
|
||||
flatEntityId: 'entity-child',
|
||||
flatEntityParentId: 'entity-parent',
|
||||
maxDepth: 2,
|
||||
entities: [createTestEntity('entity-parent', null)],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should check max depth before circular dependency to prevent infinite loop',
|
||||
context: {
|
||||
flatEntityId: 'entity-new',
|
||||
flatEntityParentId: 'entity-a',
|
||||
maxDepth: 2,
|
||||
entities: [
|
||||
createTestEntity('entity-a', 'entity-b'),
|
||||
createTestEntity('entity-b', 'entity-c'),
|
||||
createTestEntity('entity-c', 'entity-d'),
|
||||
createTestEntity('entity-d', 'entity-a'),
|
||||
],
|
||||
expected: {
|
||||
status: 'fail',
|
||||
reason: 'max_depth_exceeded',
|
||||
depth: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle deep valid hierarchy without maxDepth',
|
||||
context: {
|
||||
flatEntityId: 'entity-new',
|
||||
flatEntityParentId: 'entity-1',
|
||||
entities: [
|
||||
createTestEntity('entity-5', null),
|
||||
createTestEntity('entity-4', 'entity-5'),
|
||||
createTestEntity('entity-3', 'entity-4'),
|
||||
createTestEntity('entity-2', 'entity-3'),
|
||||
createTestEntity('entity-1', 'entity-2'),
|
||||
],
|
||||
expected: {
|
||||
status: 'success',
|
||||
depth: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
describe('validateFlatEntityCircularDependency', () => {
|
||||
test.each(testCases)('$title', ({ context }) => {
|
||||
const flatEntityMaps = createFlatEntityMaps(context.entities);
|
||||
|
||||
const result = validateFlatEntityCircularDependency({
|
||||
flatEntityId: context.flatEntityId,
|
||||
flatEntityParentId: context.flatEntityParentId,
|
||||
maxDepth: context.maxDepth,
|
||||
parentIdKey: 'parentId',
|
||||
flatEntityMaps,
|
||||
});
|
||||
|
||||
expect(result).toEqual(context.expected);
|
||||
});
|
||||
});
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
|
||||
type AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
> = {
|
||||
flatEntity: T;
|
||||
flatEntityMapsToMutate: FlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const addFlatEntityToFlatEntityMapsThroughMutationOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
>({
|
||||
flatEntity,
|
||||
flatEntityMapsToMutate,
|
||||
}: AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs<T>): void => {
|
||||
if (isDefined(flatEntityMapsToMutate.byId[flatEntity.id])) {
|
||||
throw new FlatEntityMapsException(
|
||||
'addFlatEntityToFlatEntityMapsThroughMutationOrThrow: flat entity to add already exists',
|
||||
FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
|
||||
flatEntityMapsToMutate.byId[flatEntity.id] = flatEntity;
|
||||
|
||||
flatEntityMapsToMutate.idByUniversalIdentifier[
|
||||
flatEntity.universalIdentifier
|
||||
] = flatEntity.id;
|
||||
|
||||
if (isDefined(flatEntity.applicationId)) {
|
||||
const existingUniversalIdentifiers =
|
||||
flatEntityMapsToMutate.universalIdentifiersByApplicationId[
|
||||
flatEntity.applicationId
|
||||
];
|
||||
|
||||
if (isDefined(existingUniversalIdentifiers)) {
|
||||
if (
|
||||
!existingUniversalIdentifiers.includes(flatEntity.universalIdentifier)
|
||||
) {
|
||||
existingUniversalIdentifiers.push(flatEntity.universalIdentifier);
|
||||
}
|
||||
} else {
|
||||
flatEntityMapsToMutate.universalIdentifiersByApplicationId[
|
||||
flatEntity.applicationId
|
||||
] = [flatEntity.universalIdentifier];
|
||||
}
|
||||
}
|
||||
};
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type CreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type CreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type AggregatedActions = {
|
||||
createdFieldActionByObjectMetadataId: Record<string, CreateFieldAction>;
|
||||
createdObjectActionByObjectMetadataId: Record<string, CreateObjectAction>;
|
||||
};
|
||||
|
||||
export const aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions =
|
||||
({
|
||||
orchestratorActionsReport,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
const initialCreatedObjectActionByObjectMetadataId = (
|
||||
orchestratorActionsReport.objectMetadata.create as CreateObjectAction[]
|
||||
).reduce(
|
||||
(acc, createObjectAction) => ({
|
||||
...acc,
|
||||
[createObjectAction.flatEntity.id]: createObjectAction,
|
||||
}),
|
||||
{} as Record<string, CreateObjectAction>,
|
||||
);
|
||||
const initialAccumulator: AggregatedActions = {
|
||||
createdFieldActionByObjectMetadataId: {},
|
||||
createdObjectActionByObjectMetadataId:
|
||||
initialCreatedObjectActionByObjectMetadataId,
|
||||
};
|
||||
|
||||
const {
|
||||
createdFieldActionByObjectMetadataId,
|
||||
createdObjectActionByObjectMetadataId,
|
||||
} = (
|
||||
orchestratorActionsReport.fieldMetadata.create as CreateFieldAction[]
|
||||
).reduce<AggregatedActions>(
|
||||
(
|
||||
{
|
||||
createdObjectActionByObjectMetadataId,
|
||||
createdFieldActionByObjectMetadataId,
|
||||
},
|
||||
createFieldAction,
|
||||
) => {
|
||||
const existingCreateObjectAction =
|
||||
createdObjectActionByObjectMetadataId[
|
||||
createFieldAction.objectMetadataId
|
||||
];
|
||||
|
||||
const existingCreateFieldAction =
|
||||
createdFieldActionByObjectMetadataId[
|
||||
createFieldAction.objectMetadataId
|
||||
];
|
||||
|
||||
const initialAccumulator: {
|
||||
morphOrRelationFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
otherFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
} = {
|
||||
morphOrRelationFlatFieldMetadatas: [],
|
||||
otherFlatFieldMetadatas: [],
|
||||
};
|
||||
const { morphOrRelationFlatFieldMetadatas, otherFlatFieldMetadatas } =
|
||||
createFieldAction.flatFieldMetadatas.reduce(
|
||||
(acc, flatFieldMetadata) => {
|
||||
if (isMorphOrRelationFlatFieldMetadata(flatFieldMetadata)) {
|
||||
return {
|
||||
...acc,
|
||||
morphOrRelationFlatFieldMetadatas: [
|
||||
...acc.morphOrRelationFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
otherFlatFieldMetadatas: [
|
||||
...acc.otherFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
if (isDefined(existingCreateObjectAction)) {
|
||||
if (isDefined(existingCreateFieldAction)) {
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateFieldAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateFieldAction.flatFieldMetadatas,
|
||||
...morphOrRelationFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (morphOrRelationFlatFieldMetadatas.length > 0) {
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...createFieldAction,
|
||||
flatFieldMetadatas: morphOrRelationFlatFieldMetadatas,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId,
|
||||
};
|
||||
}
|
||||
|
||||
if (isDefined(existingCreateFieldAction)) {
|
||||
return {
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateFieldAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateFieldAction.flatFieldMetadatas,
|
||||
...createFieldAction.flatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdObjectActionByObjectMetadataId,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: createFieldAction,
|
||||
},
|
||||
createdObjectActionByObjectMetadataId,
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
create: Object.values(createdFieldActionByObjectMetadataId),
|
||||
},
|
||||
objectMetadata: {
|
||||
...orchestratorActionsReport.objectMetadata,
|
||||
create: Object.values(createdObjectActionByObjectMetadataId),
|
||||
},
|
||||
};
|
||||
};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type DeleteFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type DeleteObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type AggregatedActions = {
|
||||
deleteFieldActionByFieldMetadataId: Record<string, DeleteFieldAction>;
|
||||
};
|
||||
export const aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions =
|
||||
({
|
||||
orchestratorActionsReport,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
const deleteObjectActionByObjectMetadataId = (
|
||||
orchestratorActionsReport.objectMetadata.delete as DeleteObjectAction[]
|
||||
).reduce<Record<string, DeleteObjectAction>>(
|
||||
(acc, deleteObjectAction) => ({
|
||||
...acc,
|
||||
[deleteObjectAction.entityId]: deleteObjectAction,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
const initialAccumulator: AggregatedActions = {
|
||||
deleteFieldActionByFieldMetadataId: {},
|
||||
};
|
||||
|
||||
const { deleteFieldActionByFieldMetadataId } = (
|
||||
orchestratorActionsReport.fieldMetadata.delete as DeleteFieldAction[]
|
||||
).reduce<AggregatedActions>(
|
||||
({ deleteFieldActionByFieldMetadataId }, deleteFieldAction) => {
|
||||
const fieldParentObjectDeleteObjectAction =
|
||||
deleteObjectActionByObjectMetadataId[
|
||||
deleteFieldAction.objectMetadataId
|
||||
];
|
||||
|
||||
if (isDefined(fieldParentObjectDeleteObjectAction)) {
|
||||
return {
|
||||
deleteFieldActionByFieldMetadataId,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
deleteFieldActionByFieldMetadataId: {
|
||||
...deleteFieldActionByFieldMetadataId,
|
||||
[deleteFieldAction.entityId]: deleteFieldAction,
|
||||
},
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
delete: Object.values(deleteFieldActionByFieldMetadataId),
|
||||
},
|
||||
};
|
||||
};
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions =
|
||||
({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
assertIsDefinedOrThrow(flatFieldMetadataMaps);
|
||||
|
||||
const updateFieldActions = orchestratorActionsReport.fieldMetadata
|
||||
.update as UpdateFieldAction[];
|
||||
|
||||
const { searchVectorUpdateFieldActions, otherUpdateFieldActions } =
|
||||
updateFieldActions.reduce<{
|
||||
searchVectorUpdateFieldActions: UpdateFieldAction[];
|
||||
otherUpdateFieldActions: UpdateFieldAction[];
|
||||
}>(
|
||||
(acc, updateFieldAction) => {
|
||||
const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityId: updateFieldAction.entityId,
|
||||
});
|
||||
|
||||
const isSearchVectorUpdateFieldAction =
|
||||
flatFieldMetadata?.name === SEARCH_VECTOR_FIELD.name;
|
||||
|
||||
if (isSearchVectorUpdateFieldAction) {
|
||||
return {
|
||||
...acc,
|
||||
searchVectorUpdateFieldActions: [
|
||||
...acc.searchVectorUpdateFieldActions,
|
||||
updateFieldAction,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
otherUpdateFieldActions: [
|
||||
...acc.otherUpdateFieldActions,
|
||||
updateFieldAction,
|
||||
],
|
||||
};
|
||||
},
|
||||
{
|
||||
searchVectorUpdateFieldActions: [],
|
||||
otherUpdateFieldActions: [],
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
update: [...otherUpdateFieldActions, ...searchVectorUpdateFieldActions],
|
||||
},
|
||||
};
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util';
|
||||
import { aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-delete-object-and-delete-field.util';
|
||||
import { aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-deprioritize-search-vector-update-field-actions.util';
|
||||
|
||||
export const aggregateOrchestratorActionsReport = ({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
}: AggregateOrchestratorActionsReportArgs) => {
|
||||
const aggregatedOrchestratorActionsReport = [
|
||||
aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions,
|
||||
aggregateOrchestratorActionsReportDeleteObjectAndDeleteFieldActions,
|
||||
aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions,
|
||||
].reduce(
|
||||
(currentOrchestratorActionsReport, aggregator) =>
|
||||
aggregator({
|
||||
orchestratorActionsReport: currentOrchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
}),
|
||||
orchestratorActionsReport,
|
||||
);
|
||||
|
||||
return { aggregatedOrchestratorActionsReport };
|
||||
};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { removeSqlDDLInjection } from 'src/engine/workspace-manager/workspace-migration/utils/remove-sql-injection.util';
|
||||
|
||||
type ComputePostgresEnumNameParams = {
|
||||
tableName: string;
|
||||
columnName: string;
|
||||
};
|
||||
|
||||
export const computePostgresEnumName = ({
|
||||
tableName,
|
||||
columnName,
|
||||
}: ComputePostgresEnumNameParams): string => {
|
||||
return removeSqlDDLInjection(`${tableName}_${columnName}_enum`);
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
export const convertOnDeleteActionToOnDelete = (
|
||||
onDeleteAction: RelationOnDeleteAction | undefined,
|
||||
): 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION' | undefined => {
|
||||
if (!onDeleteAction) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
switch (onDeleteAction) {
|
||||
case 'CASCADE':
|
||||
return 'CASCADE';
|
||||
case 'SET_NULL':
|
||||
return 'SET NULL';
|
||||
case 'RESTRICT':
|
||||
return 'RESTRICT';
|
||||
case 'NO_ACTION':
|
||||
return 'NO ACTION';
|
||||
default:
|
||||
throw new Error('Invalid onDeleteAction');
|
||||
}
|
||||
};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
|
||||
export type DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
> = {
|
||||
entityToDeleteId: string;
|
||||
flatEntityMapsToMutate: FlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
>({
|
||||
flatEntityMapsToMutate,
|
||||
entityToDeleteId,
|
||||
}: DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs<T>): void => {
|
||||
const entityToDelete = flatEntityMapsToMutate.byId[entityToDeleteId];
|
||||
|
||||
if (!isDefined(entityToDelete)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow: entity to delete not found',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
delete flatEntityMapsToMutate.byId[entityToDeleteId];
|
||||
|
||||
delete flatEntityMapsToMutate.idByUniversalIdentifier[
|
||||
entityToDelete.universalIdentifier
|
||||
];
|
||||
|
||||
if (isDefined(entityToDelete.applicationId)) {
|
||||
const universalIdentifiers =
|
||||
flatEntityMapsToMutate.universalIdentifiersByApplicationId[
|
||||
entityToDelete.applicationId
|
||||
];
|
||||
|
||||
if (isDefined(universalIdentifiers)) {
|
||||
const index = universalIdentifiers.indexOf(
|
||||
entityToDelete.universalIdentifier,
|
||||
);
|
||||
|
||||
if (index !== -1) {
|
||||
universalIdentifiers.splice(index, 1);
|
||||
}
|
||||
|
||||
if (universalIdentifiers.length === 0) {
|
||||
delete flatEntityMapsToMutate.universalIdentifiersByApplicationId[
|
||||
entityToDelete.applicationId
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatEntityPropertyUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-property-update.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { isPropertyUpdate } from 'src/engine/workspace-manager/workspace-migration/utils/is-property-update.util';
|
||||
|
||||
export const findFlatEntityPropertyUpdate = <
|
||||
T extends AllMetadataName,
|
||||
P extends Extract<
|
||||
FlatEntityPropertiesToCompare<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>,
|
||||
>({
|
||||
property,
|
||||
flatEntityUpdates,
|
||||
}: {
|
||||
flatEntityUpdates: FlatEntityPropertiesUpdates<T>;
|
||||
property: P;
|
||||
}) =>
|
||||
flatEntityUpdates.find((update): update is FlatEntityPropertyUpdate<T, P> =>
|
||||
isPropertyUpdate(update, property),
|
||||
);
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityPropertiesToStringify } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-stringify.type';
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { shouldInferDeletionFromMissingEntities } from 'src/engine/workspace-manager/workspace-migration/utils/should-infer-deletion-from-missing-entities.util';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
|
||||
export type DeletedCreatedUpdatedMatrix<T extends AllMetadataName> = {
|
||||
createdFlatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
deletedFlatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
updatedFlatEntityMaps: {
|
||||
byId: Record<
|
||||
string,
|
||||
{
|
||||
updates: FlatEntityPropertiesUpdates<T>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
export type UniversalIdentifierItem = {
|
||||
universalIdentifier: string;
|
||||
};
|
||||
|
||||
type FlatEntityDeletedCreatedUpdatedMatrixDispatcherArgs<
|
||||
T extends AllMetadataName,
|
||||
> = FromTo<MetadataFlatEntity<T>[]> & {
|
||||
metadataName: T;
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
};
|
||||
|
||||
export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
from,
|
||||
to,
|
||||
metadataName,
|
||||
buildOptions,
|
||||
}: FlatEntityDeletedCreatedUpdatedMatrixDispatcherArgs<T>): DeletedCreatedUpdatedMatrix<T> => {
|
||||
const initialDispatcher: DeletedCreatedUpdatedMatrix<T> = {
|
||||
createdFlatEntityMaps: createEmptyFlatEntityMaps(),
|
||||
deletedFlatEntityMaps: createEmptyFlatEntityMaps(),
|
||||
updatedFlatEntityMaps: { byId: {} },
|
||||
};
|
||||
|
||||
const fromMap = new Map(from.map((obj) => [obj.universalIdentifier, obj]));
|
||||
const toMap = new Map(to.map((obj) => [obj.universalIdentifier, obj]));
|
||||
|
||||
if (shouldInferDeletionFromMissingEntities({ buildOptions, metadataName })) {
|
||||
for (const [universalIdentifier, fromEntity] of fromMap) {
|
||||
if (toMap.has(universalIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: fromEntity,
|
||||
flatEntityMapsToMutate: initialDispatcher.deletedFlatEntityMaps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const [universalIdentifier, toFlatEntity] of toMap) {
|
||||
if (fromMap.has(universalIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: toFlatEntity,
|
||||
flatEntityMapsToMutate: initialDispatcher.createdFlatEntityMaps,
|
||||
});
|
||||
}
|
||||
|
||||
const { propertiesToCompare, propertiesToStringify } =
|
||||
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName];
|
||||
|
||||
for (const [universalIdentifier, fromFlatEntity] of fromMap) {
|
||||
const toFlatEntity = toMap.get(universalIdentifier);
|
||||
|
||||
if (!isDefined(toFlatEntity)) {
|
||||
continue;
|
||||
}
|
||||
const updates = compareTwoFlatEntity({
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
propertiesToCompare: propertiesToCompare as unknown as Extract<
|
||||
FlatEntityPropertiesToCompare<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>[],
|
||||
propertiesToStringify: propertiesToStringify as unknown as Extract<
|
||||
FlatEntityPropertiesToStringify<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>[],
|
||||
});
|
||||
|
||||
if (updates.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
initialDispatcher.updatedFlatEntityMaps.byId[toFlatEntity.id] = {
|
||||
updates,
|
||||
};
|
||||
}
|
||||
|
||||
return initialDispatcher;
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataWorkspaceMigrationActionsRecord } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
|
||||
export const getMetadataEmptyWorkspaceMigrationActionRecord = <
|
||||
T extends AllMetadataName,
|
||||
>(
|
||||
_metadataName: T,
|
||||
) =>
|
||||
({
|
||||
create: [],
|
||||
delete: [],
|
||||
update: [],
|
||||
}) as MetadataWorkspaceMigrationActionsRecord<T>;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration/types/property-update.type';
|
||||
|
||||
export const isPropertyUpdate = <T, P extends keyof T>(
|
||||
update: PropertyUpdate<T, keyof T>,
|
||||
property: P,
|
||||
): update is PropertyUpdate<T, P> => {
|
||||
return update.property === property;
|
||||
};
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export const removeSqlDDLInjection = (value: string): string => {
|
||||
return value.replace(/[^a-zA-Z0-9_]/g, '');
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
export type ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
> = {
|
||||
flatEntity: T;
|
||||
flatEntityMapsToMutate: FlatEntityMaps<T>;
|
||||
};
|
||||
|
||||
export const replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
>({
|
||||
flatEntity,
|
||||
flatEntityMapsToMutate,
|
||||
}: ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs<T>): void => {
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntityMapsToMutate,
|
||||
entityToDeleteId: flatEntity.id,
|
||||
});
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity,
|
||||
flatEntityMapsToMutate,
|
||||
});
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
|
||||
export const shouldInferDeletionFromMissingEntities = ({
|
||||
buildOptions,
|
||||
metadataName,
|
||||
}: {
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
metadataName: AllMetadataName;
|
||||
}): boolean => {
|
||||
return (
|
||||
buildOptions.inferDeletionFromMissingEntities === true ||
|
||||
buildOptions.inferDeletionFromMissingEntities?.[metadataName] === true
|
||||
);
|
||||
};
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
|
||||
export type CircularDependencyValidationSuccess = {
|
||||
status: 'success';
|
||||
depth: number;
|
||||
};
|
||||
|
||||
export type CircularDependencyValidationFailure = {
|
||||
status: 'fail';
|
||||
reason: 'self_reference' | 'circular_dependency' | 'max_depth_exceeded';
|
||||
depth?: number;
|
||||
};
|
||||
|
||||
export type CircularDependencyValidationResult =
|
||||
| CircularDependencyValidationSuccess
|
||||
| CircularDependencyValidationFailure;
|
||||
|
||||
export const validateFlatEntityCircularDependency = <
|
||||
T extends SyncableFlatEntity,
|
||||
K extends keyof T,
|
||||
>({
|
||||
flatEntityId,
|
||||
flatEntityParentId,
|
||||
maxDepth,
|
||||
parentIdKey,
|
||||
flatEntityMaps,
|
||||
}: {
|
||||
flatEntityId: string;
|
||||
flatEntityParentId: string;
|
||||
maxDepth?: number;
|
||||
parentIdKey: K;
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
}): CircularDependencyValidationResult => {
|
||||
// Direct self-reference check
|
||||
if (flatEntityId === flatEntityParentId) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'self_reference',
|
||||
};
|
||||
}
|
||||
|
||||
// Traverse ancestor chain to detect cycles and measure depth
|
||||
const visited = new Set<string>();
|
||||
let currentParentId: string | null | undefined = flatEntityParentId;
|
||||
let depth = 1;
|
||||
|
||||
while (isDefined(currentParentId)) {
|
||||
if (isDefined(maxDepth) && depth > maxDepth) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'max_depth_exceeded',
|
||||
depth,
|
||||
};
|
||||
}
|
||||
|
||||
// Check for circular dependency
|
||||
if (currentParentId === flatEntityId) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'circular_dependency',
|
||||
depth,
|
||||
};
|
||||
}
|
||||
|
||||
// Check for cycle in ancestors (already visited node)
|
||||
if (visited.has(currentParentId)) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'circular_dependency',
|
||||
depth,
|
||||
};
|
||||
}
|
||||
|
||||
visited.add(currentParentId);
|
||||
|
||||
const parentEntity: T | undefined = flatEntityMaps.byId[currentParentId];
|
||||
|
||||
if (!isDefined(parentEntity)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const nextParentId: T[K] = parentEntity[parentIdKey];
|
||||
|
||||
currentParentId =
|
||||
isDefined(nextParentId) && typeof nextParentId === 'string'
|
||||
? nextParentId
|
||||
: undefined;
|
||||
depth++;
|
||||
}
|
||||
|
||||
// Check max depth for the final depth value
|
||||
if (isDefined(maxDepth) && depth > maxDepth) {
|
||||
return {
|
||||
status: 'fail',
|
||||
reason: 'max_depth_exceeded',
|
||||
depth,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
depth,
|
||||
};
|
||||
};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateAgentAction = BaseCreateWorkspaceMigrationAction<'agent'>;
|
||||
|
||||
export type UpdateAgentAction = BaseUpdateWorkspaceMigrationAction<'agent'>;
|
||||
|
||||
export type DeleteAgentAction = BaseDeleteWorkspaceMigrationAction<'agent'>;
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateAgentAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/types/workspace-migration-agent-action-builder.service';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatAgentValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-agent-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationAgentActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.agent
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatAgentValidatorService: FlatAgentValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.agent);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.agent>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.agent, 'create'> {
|
||||
const validationResult =
|
||||
this.flatAgentValidatorService.validateFlatAgentCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatAgentToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'agent',
|
||||
flatEntity: flatAgentToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.agent>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.agent, 'delete'> {
|
||||
const validationResult =
|
||||
this.flatAgentValidatorService.validateFlatAgentDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatAgentToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'agent',
|
||||
entityId: flatAgentToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.agent>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.agent, 'update'> {
|
||||
const validationResult =
|
||||
this.flatAgentValidatorService.validateFlatAgentUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAgentAction: UpdateAgentAction = {
|
||||
type: 'update',
|
||||
metadataName: 'agent',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateAgentAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateCronTriggerAction =
|
||||
BaseCreateWorkspaceMigrationAction<'cronTrigger'>;
|
||||
|
||||
export type UpdateCronTriggerAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'cronTrigger'>;
|
||||
|
||||
export type DeleteCronTriggerAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'cronTrigger'>;
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/cron-trigger/types/workspace-migration-cron-trigger-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatCronTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-cron-trigger-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationCronTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.cronTrigger
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatCronTriggerValidatorService: FlatCronTriggerValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.cronTrigger);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.cronTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.cronTrigger,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatCronTriggerValidatorService.validateFlatCronTriggerCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatCronTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'cronTrigger',
|
||||
flatEntity: flatCronTriggerToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.cronTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.cronTrigger,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatCronTriggerValidatorService.validateFlatCronTriggerDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatCronTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'cronTrigger',
|
||||
entityId: flatCronTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.cronTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.cronTrigger,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatCronTriggerValidatorService.validateFlatCronTriggerUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateCronTriggerAction: UpdateCronTriggerAction = {
|
||||
type: 'update',
|
||||
metadataName: 'cronTrigger',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateCronTriggerAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateDatabaseEventTriggerAction =
|
||||
BaseCreateWorkspaceMigrationAction<'databaseEventTrigger'>;
|
||||
|
||||
export type UpdateDatabaseEventTriggerAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'databaseEventTrigger'>;
|
||||
|
||||
export type DeleteDatabaseEventTriggerAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'databaseEventTrigger'>;
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/database-event-trigger/types/workspace-migration-database-event-trigger-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatDatabaseEventTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-database-event-trigger-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationDatabaseEventTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatDatabaseEventTriggerValidatorService: FlatDatabaseEventTriggerValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.databaseEventTrigger);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatDatabaseEventTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'databaseEventTrigger',
|
||||
flatEntity: flatDatabaseEventTriggerToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatDatabaseEventTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'databaseEventTrigger',
|
||||
entityId: flatDatabaseEventTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.databaseEventTrigger,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateDatabaseEventTriggerAction: UpdateDatabaseEventTriggerAction = {
|
||||
type: 'update',
|
||||
metadataName: 'databaseEventTrigger',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateDatabaseEventTriggerAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateFieldAction = Omit<
|
||||
BaseCreateWorkspaceMigrationAction<'fieldMetadata'>,
|
||||
'flatEntity'
|
||||
> & {
|
||||
objectMetadataId: string;
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
};
|
||||
|
||||
export type UpdateFieldAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'fieldMetadata'> & {
|
||||
objectMetadataId: string;
|
||||
};
|
||||
|
||||
export type DeleteFieldAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'fieldMetadata'> & {
|
||||
objectMetadataId: string;
|
||||
};
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatFieldMetadataValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-field-metadata-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationFieldActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.fieldMetadata
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatFieldValidatorService: FlatFieldMetadataValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.fieldMetadata);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.fieldMetadata>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.fieldMetadata,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatFieldValidatorService.validateFlatFieldMetadataCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatFieldMetadataToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: flatFieldMetadataToValidate.objectMetadataId,
|
||||
flatFieldMetadatas: [flatFieldMetadataToValidate],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.fieldMetadata>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.fieldMetadata,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatFieldValidatorService.validateFlatFieldMetadataDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatFieldMetadataToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: flatFieldMetadataToValidate.id,
|
||||
objectMetadataId: flatFieldMetadataToValidate.objectMetadataId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.fieldMetadata
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.fieldMetadata,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatFieldValidatorService.validateFlatFieldMetadataUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
flatEntityId,
|
||||
flatEntityUpdates,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
} = args;
|
||||
|
||||
const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatEntityId,
|
||||
flatEntityMaps:
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
const updateFieldAction: UpdateFieldAction = {
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: flatEntityId,
|
||||
objectMetadataId: flatFieldMetadata.objectMetadataId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateFieldAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
|
||||
export type CreateIndexAction = BaseCreateWorkspaceMigrationAction<'index'>;
|
||||
|
||||
export type DeleteIndexAction = BaseDeleteWorkspaceMigrationAction<'index'>;
|
||||
|
||||
export type UpdateIndexAction = {
|
||||
type: 'update';
|
||||
metadataName: 'index';
|
||||
entityId: string;
|
||||
updatedFlatEntity: FlatIndexMetadata;
|
||||
};
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { FlatEntityMapsExceptionCode } from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatIndexValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-index-metadata-validator.service';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationIndexActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.index
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatIndexValidatorService: FlatIndexValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.index);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.index>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.index, 'create'> {
|
||||
const validationResult =
|
||||
this.flatIndexValidatorService.validateFlatIndexCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatIndexToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'index',
|
||||
flatEntity: flatIndexToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.index>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.index, 'delete'> {
|
||||
const validationResult =
|
||||
this.flatIndexValidatorService.validateFlatIndexDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatIndexToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'index',
|
||||
entityId: flatIndexToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate({
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
flatEntityId,
|
||||
flatEntityUpdates,
|
||||
buildOptions,
|
||||
workspaceId,
|
||||
additionalCacheDataMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.index
|
||||
>): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.index, 'update'> {
|
||||
const flatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId,
|
||||
flatEntityMaps:
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatIndexMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatEntity)) {
|
||||
return {
|
||||
status: 'fail',
|
||||
metadataName: 'index',
|
||||
type: 'update',
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatEntityId,
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
code: FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
message: t`Index to delete not found`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
const deletionValidationResult =
|
||||
this.flatIndexValidatorService.validateFlatIndexDeletion({
|
||||
buildOptions,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
workspaceId,
|
||||
flatEntityToValidate: flatEntity,
|
||||
remainingFlatEntityMapsToValidate: createEmptyFlatEntityMaps(),
|
||||
additionalCacheDataMaps,
|
||||
});
|
||||
|
||||
if (deletionValidationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
type: 'update',
|
||||
errors: deletionValidationResult.errors,
|
||||
flatEntityMinimalInformation:
|
||||
deletionValidationResult.flatEntityMinimalInformation,
|
||||
metadataName: deletionValidationResult.metadataName,
|
||||
};
|
||||
}
|
||||
|
||||
const updatedFlatIndex = {
|
||||
...flatEntity,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
|
||||
updates: flatEntityUpdates,
|
||||
}),
|
||||
};
|
||||
|
||||
const tempOptimisticFlatIndexMaps = structuredClone(
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatIndexMaps,
|
||||
);
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
|
||||
entityToDeleteId: flatEntity.id,
|
||||
flatEntityMapsToMutate: tempOptimisticFlatIndexMaps,
|
||||
});
|
||||
|
||||
const creationValidationResult =
|
||||
this.flatIndexValidatorService.validateFlatIndexCreation({
|
||||
buildOptions,
|
||||
workspaceId,
|
||||
flatEntityToValidate: updatedFlatIndex,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
...optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
flatIndexMaps: tempOptimisticFlatIndexMaps,
|
||||
},
|
||||
remainingFlatEntityMapsToValidate: createEmptyFlatEntityMaps(),
|
||||
additionalCacheDataMaps,
|
||||
});
|
||||
|
||||
if (creationValidationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
type: 'update',
|
||||
errors: creationValidationResult.errors,
|
||||
flatEntityMinimalInformation:
|
||||
creationValidationResult.flatEntityMinimalInformation,
|
||||
metadataName: creationValidationResult.metadataName,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'update',
|
||||
metadataName: 'index',
|
||||
entityId: flatEntity.id,
|
||||
updatedFlatEntity: updatedFlatIndex,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateObjectAction =
|
||||
BaseCreateWorkspaceMigrationAction<'objectMetadata'> & {
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
};
|
||||
|
||||
export type UpdateObjectAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'objectMetadata'>;
|
||||
|
||||
export type DeleteObjectAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'objectMetadata'>;
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatObjectMetadataValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-object-metadata-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationObjectActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.objectMetadata
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatObjectValidatorService: FlatObjectMetadataValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.objectMetadata);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.objectMetadata>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.objectMetadata,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatObjectValidatorService.validateFlatObjectMetadataCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatObjectMetadataToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatFieldMetadatas: [],
|
||||
flatEntity: flatObjectMetadataToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.objectMetadata>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.objectMetadata,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatObjectValidatorService.validateFlatObjectMetadataDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatObjectMetadataToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: flatObjectMetadataToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.objectMetadata
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.objectMetadata,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatObjectValidatorService.validateFlatObjectMetadataUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateObjectAction: UpdateObjectAction = {
|
||||
type: 'update',
|
||||
metadataName: 'objectMetadata',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateObjectAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreatePageLayoutTabAction =
|
||||
BaseCreateWorkspaceMigrationAction<'pageLayoutTab'>;
|
||||
|
||||
export type UpdatePageLayoutTabAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'pageLayoutTab'>;
|
||||
|
||||
export type DeletePageLayoutTabAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'pageLayoutTab'>;
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdatePageLayoutTabAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatPageLayoutTabValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-page-layout-tab-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationPageLayoutTabActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.pageLayoutTab
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatPageLayoutTabValidatorService: FlatPageLayoutTabValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.pageLayoutTab);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutTab>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutTab,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatPageLayoutTabToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'pageLayoutTab',
|
||||
flatEntity: flatPageLayoutTabToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutTab>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutTab,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatPageLayoutTabToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'pageLayoutTab',
|
||||
entityId: flatPageLayoutTabToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.pageLayoutTab
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutTab,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updatePageLayoutTabAction: UpdatePageLayoutTabAction = {
|
||||
type: 'update',
|
||||
metadataName: 'pageLayoutTab',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updatePageLayoutTabAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreatePageLayoutWidgetAction =
|
||||
BaseCreateWorkspaceMigrationAction<'pageLayoutWidget'>;
|
||||
|
||||
export type UpdatePageLayoutWidgetAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'pageLayoutWidget'>;
|
||||
|
||||
export type DeletePageLayoutWidgetAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'pageLayoutWidget'>;
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdatePageLayoutWidgetAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatPageLayoutWidgetValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-page-layout-widget-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationPageLayoutWidgetActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatPageLayoutWidgetValidatorService: FlatPageLayoutWidgetValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.pageLayoutWidget);
|
||||
}
|
||||
|
||||
protected async validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutWidget>,
|
||||
): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget,
|
||||
'create'
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
await this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'pageLayoutWidget',
|
||||
flatEntity: args.flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutWidget>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatPageLayoutWidgetToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'pageLayoutWidget',
|
||||
entityId: flatPageLayoutWidgetToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget
|
||||
>,
|
||||
): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayoutWidget,
|
||||
'update'
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
await this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updatePageLayoutWidgetAction: UpdatePageLayoutWidgetAction = {
|
||||
type: 'update',
|
||||
metadataName: 'pageLayoutWidget',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updatePageLayoutWidgetAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreatePageLayoutAction =
|
||||
BaseCreateWorkspaceMigrationAction<'pageLayout'>;
|
||||
|
||||
export type UpdatePageLayoutAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'pageLayout'>;
|
||||
|
||||
export type DeletePageLayoutAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'pageLayout'>;
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdatePageLayoutAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout/types/workspace-migration-page-layout-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatPageLayoutValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-page-layout-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationPageLayoutActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.pageLayout
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatPageLayoutValidatorService: FlatPageLayoutValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.pageLayout);
|
||||
}
|
||||
|
||||
protected async validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayout>,
|
||||
): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayout,
|
||||
'create'
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutValidatorService.validateFlatPageLayoutCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatPageLayoutToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'pageLayout',
|
||||
flatEntity: flatPageLayoutToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayout>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayout,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutValidatorService.validateFlatPageLayoutDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatPageLayoutToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'pageLayout',
|
||||
entityId: flatPageLayoutToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.pageLayout>,
|
||||
): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.pageLayout,
|
||||
'update'
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatPageLayoutValidatorService.validateFlatPageLayoutUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updatePageLayoutAction: UpdatePageLayoutAction = {
|
||||
type: 'update',
|
||||
metadataName: 'pageLayout',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updatePageLayoutAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateRoleTargetAction =
|
||||
BaseCreateWorkspaceMigrationAction<'roleTarget'>;
|
||||
|
||||
export type UpdateRoleTargetAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'roleTarget'>;
|
||||
|
||||
export type DeleteRoleTargetAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'roleTarget'>;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRoleTargetAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-target/types/workspace-migration-role-target-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatRoleTargetValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-role-target-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRoleTargetActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.roleTarget
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRoleTargetValidatorService: FlatRoleTargetValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.roleTarget);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.roleTarget>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.roleTarget,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRoleTargetValidatorService.validateFlatRoleTargetCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRoleTargetToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'roleTarget',
|
||||
flatEntity: flatRoleTargetToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.roleTarget>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.roleTarget,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRoleTargetValidatorService.validateFlatRoleTargetDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRoleTargetToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'roleTarget',
|
||||
entityId: flatRoleTargetToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.roleTarget>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.roleTarget,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRoleTargetValidatorService.validateFlatRoleTargetUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateRoleTargetAction: UpdateRoleTargetAction = {
|
||||
type: 'update',
|
||||
metadataName: 'roleTarget',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateRoleTargetAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateRoleAction = BaseCreateWorkspaceMigrationAction<'role'>;
|
||||
|
||||
export type UpdateRoleAction = BaseUpdateWorkspaceMigrationAction<'role'>;
|
||||
|
||||
export type DeleteRoleAction = BaseDeleteWorkspaceMigrationAction<'role'>;
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRoleAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role/types/workspace-migration-role-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatRoleValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-role-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRoleActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.role
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRoleValidatorService: FlatRoleValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.role);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.role>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.role, 'create'> {
|
||||
const validationResult =
|
||||
this.flatRoleValidatorService.validateFlatRoleCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRoleToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'role',
|
||||
flatEntity: flatRoleToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.role>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.role, 'delete'> {
|
||||
const validationResult =
|
||||
this.flatRoleValidatorService.validateFlatRoleDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRoleToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'role',
|
||||
entityId: flatRoleToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.role>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.role, 'update'> {
|
||||
const validationResult =
|
||||
this.flatRoleValidatorService.validateFlatRoleUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateRoleAction: UpdateRoleAction = {
|
||||
type: 'update',
|
||||
metadataName: 'role',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateRoleAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateRouteTriggerAction =
|
||||
BaseCreateWorkspaceMigrationAction<'routeTrigger'>;
|
||||
|
||||
export type UpdateRouteTriggerAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'routeTrigger'>;
|
||||
|
||||
export type DeleteRouteTriggerAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'routeTrigger'>;
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRouteTriggerAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/route-trigger/types/workspace-migration-route-trigger-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatRouteTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-route-trigger-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRouteTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.routeTrigger
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRouteTriggerValidatorService: FlatRouteTriggerValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.routeTrigger);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.routeTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.routeTrigger,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRouteTriggerValidatorService.validateFlatRouteTriggerCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRouteTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'routeTrigger',
|
||||
flatEntity: flatRouteTriggerToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.routeTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.routeTrigger,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRouteTriggerValidatorService.validateFlatRouteTriggerDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatRouteTriggerToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'routeTrigger',
|
||||
entityId: flatRouteTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.routeTrigger>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.routeTrigger,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRouteTriggerValidatorService.validateFlatRouteTriggerUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateRouteTriggerAction: UpdateRouteTriggerAction = {
|
||||
type: 'update',
|
||||
metadataName: 'routeTrigger',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateRouteTriggerAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateRowLevelPermissionPredicateGroupAction =
|
||||
BaseCreateWorkspaceMigrationAction<'rowLevelPermissionPredicateGroup'>;
|
||||
|
||||
export type UpdateRowLevelPermissionPredicateGroupAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'rowLevelPermissionPredicateGroup'>;
|
||||
|
||||
export type DeleteRowLevelPermissionPredicateGroupAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'rowLevelPermissionPredicateGroup'>;
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRowLevelPermissionPredicateGroupAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatRowLevelPermissionPredicateGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-row-level-permission-predicate-group-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRowLevelPermissionPredicateGroupActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRowLevelPermissionPredicateGroupValidatorService: FlatRowLevelPermissionPredicateGroupValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.rowLevelPermissionPredicateGroup);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
flatEntity: flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
flatEntityToValidate: { id: predicateGroupId },
|
||||
} = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
entityId: predicateGroupId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAction: UpdateRowLevelPermissionPredicateGroupAction = {
|
||||
type: 'update',
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateRowLevelPermissionPredicateAction =
|
||||
BaseCreateWorkspaceMigrationAction<'rowLevelPermissionPredicate'>;
|
||||
|
||||
export type UpdateRowLevelPermissionPredicateAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'rowLevelPermissionPredicate'>;
|
||||
|
||||
export type DeleteRowLevelPermissionPredicateAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'rowLevelPermissionPredicate'>;
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRowLevelPermissionPredicateAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatRowLevelPermissionPredicateValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-row-level-permission-predicate-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRowLevelPermissionPredicateActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRowLevelPermissionPredicateValidatorService: FlatRowLevelPermissionPredicateValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.rowLevelPermissionPredicate);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
flatEntity: flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
flatEntityToValidate: { id: predicateId },
|
||||
} = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
entityId: predicateId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAction: UpdateRowLevelPermissionPredicateAction = {
|
||||
type: 'update',
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { type Sources } from 'twenty-shared/types';
|
||||
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateServerlessFunctionAction =
|
||||
BaseCreateWorkspaceMigrationAction<'serverlessFunction'>;
|
||||
|
||||
export type UpdateServerlessFunctionAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'serverlessFunction'> & {
|
||||
code?: Sources;
|
||||
};
|
||||
|
||||
export type DeleteServerlessFunctionAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'serverlessFunction'>;
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { UpdateServerlessFunctionAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/serverless-function/types/workspace-migration-serverless-function-action.type';
|
||||
import {
|
||||
ValidateAndBuildArgs,
|
||||
ValidateAndBuildReturnType,
|
||||
WorkspaceEntityMigrationBuilderService,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-serverless-function-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationServerlessFunctionActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.serverlessFunction
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatServerlessFunctionValidatorService: FlatServerlessFunctionValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.serverlessFunction);
|
||||
}
|
||||
|
||||
public async validateAndBuild(
|
||||
args: ValidateAndBuildArgs<typeof ALL_METADATA_NAME.serverlessFunction>,
|
||||
): ValidateAndBuildReturnType<typeof ALL_METADATA_NAME.serverlessFunction> {
|
||||
const { to: toFlatEntityMaps } = args;
|
||||
const baseResult = await super.validateAndBuild(args);
|
||||
|
||||
if (baseResult.status === 'fail') {
|
||||
return baseResult;
|
||||
}
|
||||
|
||||
const updatedActions = baseResult.actions.update.map((action) => {
|
||||
if (action.type !== 'update') {
|
||||
return action;
|
||||
}
|
||||
|
||||
const toServerlessFunction = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: action.entityId,
|
||||
flatEntityMaps: toFlatEntityMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...action,
|
||||
code: toServerlessFunction?.code,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
...baseResult,
|
||||
actions: {
|
||||
...baseResult.actions,
|
||||
update: updatedActions,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.serverlessFunction>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.serverlessFunction,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatServerlessFunctionToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'serverlessFunction',
|
||||
flatEntity: flatServerlessFunctionToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.serverlessFunction>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.serverlessFunction,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatServerlessFunctionToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'serverlessFunction',
|
||||
entityId: flatServerlessFunctionToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.serverlessFunction
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.serverlessFunction,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateServerlessFunctionAction: UpdateServerlessFunctionAction = {
|
||||
type: 'update',
|
||||
metadataName: 'serverlessFunction',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateServerlessFunctionAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateSkillAction = BaseCreateWorkspaceMigrationAction<'skill'>;
|
||||
|
||||
export type UpdateSkillAction = BaseUpdateWorkspaceMigrationAction<'skill'>;
|
||||
|
||||
export type DeleteSkillAction = BaseDeleteWorkspaceMigrationAction<'skill'>;
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateSkillAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/skill/types/workspace-migration-skill-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatSkillValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-skill-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationSkillActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.skill
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatSkillValidatorService: FlatSkillValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.skill);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.skill>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.skill, 'create'> {
|
||||
const validationResult =
|
||||
this.flatSkillValidatorService.validateFlatSkillCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatSkillToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'skill',
|
||||
flatEntity: flatSkillToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.skill>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.skill, 'delete'> {
|
||||
const validationResult =
|
||||
this.flatSkillValidatorService.validateFlatSkillDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatSkillToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'skill',
|
||||
entityId: flatSkillToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.skill>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.skill, 'update'> {
|
||||
const validationResult =
|
||||
this.flatSkillValidatorService.validateFlatSkillUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateSkillAction: UpdateSkillAction = {
|
||||
type: 'update',
|
||||
metadataName: 'skill',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateSkillAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { type WorkspaceMigrationActionType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
|
||||
|
||||
export type FlatEntityValidationError<TCode extends string = string> = {
|
||||
code: TCode;
|
||||
message: string;
|
||||
userFriendlyMessage?: MessageDescriptor;
|
||||
value?: unknown;
|
||||
};
|
||||
|
||||
export type FailedFlatEntityValidation<
|
||||
TMetadataName extends AllMetadataName,
|
||||
TAcionType extends WorkspaceMigrationActionType,
|
||||
> = {
|
||||
type: TAcionType;
|
||||
metadataName: TMetadataName;
|
||||
errors: FlatEntityValidationError[];
|
||||
flatEntityMinimalInformation: Pick<MetadataFlatEntity<TMetadataName>, 'id'> &
|
||||
Partial<Omit<MetadataFlatEntity<TMetadataName>, 'id'>>;
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type WorkspaceMigrationActionType } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
export const getEmptyFlatEntityValidationError = <
|
||||
TMetadataName extends AllMetadataName,
|
||||
TActionType extends WorkspaceMigrationActionType,
|
||||
>({
|
||||
metadataName,
|
||||
flatEntityMinimalInformation,
|
||||
type,
|
||||
}: Pick<
|
||||
FailedFlatEntityValidation<TMetadataName, TActionType>,
|
||||
'metadataName' | 'flatEntityMinimalInformation' | 'type'
|
||||
>): FailedFlatEntityValidation<TMetadataName, TActionType> => {
|
||||
return {
|
||||
errors: [],
|
||||
flatEntityMinimalInformation,
|
||||
metadataName,
|
||||
type,
|
||||
};
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateViewFieldAction =
|
||||
BaseCreateWorkspaceMigrationAction<'viewField'>;
|
||||
|
||||
export type UpdateViewFieldAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'viewField'>;
|
||||
|
||||
export type DeleteViewFieldAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'viewField'>;
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateViewFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-field/types/workspace-migration-view-field-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-field-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewFieldActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.viewField
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewFieldValidatorService: FlatViewFieldValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.viewField);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewField>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewField,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFieldValidatorService.validateFlatViewFieldCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'viewField',
|
||||
flatEntity: args.flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewField>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewField,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFieldValidatorService.validateFlatViewFieldDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewFieldToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'viewField',
|
||||
entityId: flatViewFieldToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.viewField>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewField,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFieldValidatorService.validateFlatViewFieldUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateViewFieldAction: UpdateViewFieldAction = {
|
||||
type: 'update',
|
||||
metadataName: 'viewField',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewFieldAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateViewFilterGroupAction =
|
||||
BaseCreateWorkspaceMigrationAction<'viewFilterGroup'>;
|
||||
|
||||
export type UpdateViewFilterGroupAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'viewFilterGroup'>;
|
||||
|
||||
export type DeleteViewFilterGroupAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'viewFilterGroup'>;
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { type UpdateViewFilterGroupAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter-group/types/workspace-migration-view-filter-group-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { type FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { type FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { type FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatViewFilterGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-filter-group-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewFilterGroupActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.viewFilterGroup
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewFilterGroupValidatorService: FlatViewFilterGroupValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.viewFilterGroup);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewFilterGroup>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilterGroup,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterGroupValidatorService.validateFlatViewFilterGroupCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewFilterGroupToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'viewFilterGroup',
|
||||
flatEntity: flatViewFilterGroupToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewFilterGroup>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilterGroup,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterGroupValidatorService.validateFlatViewFilterGroupDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewFilterGroupToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'viewFilterGroup',
|
||||
entityId: flatViewFilterGroupToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.viewFilterGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilterGroup,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterGroupValidatorService.validateFlatViewFilterGroupUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateViewFilterGroupAction: UpdateViewFilterGroupAction = {
|
||||
type: 'update',
|
||||
metadataName: 'viewFilterGroup',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewFilterGroupAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateViewFilterAction =
|
||||
BaseCreateWorkspaceMigrationAction<'viewFilter'>;
|
||||
|
||||
export type UpdateViewFilterAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'viewFilter'>;
|
||||
|
||||
export type DeleteViewFilterAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'viewFilter'>;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter/types/workspace-migration-view-filter-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-filter-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewFilterActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.viewFilter
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewFilterValidatorService: FlatViewFilterValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.viewFilter);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewFilter>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilter,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewFilterToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'viewFilter',
|
||||
flatEntity: flatViewFilterToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewFilter>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilter,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewFilterToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'viewFilter',
|
||||
entityId: flatViewFilterToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.viewFilter>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewFilter,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewFilterValidatorService.validateFlatViewFilterUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateViewFilterAction: UpdateViewFilterAction = {
|
||||
type: 'update',
|
||||
metadataName: 'viewFilter',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewFilterAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateViewGroupAction =
|
||||
BaseCreateWorkspaceMigrationAction<'viewGroup'>;
|
||||
|
||||
export type UpdateViewGroupAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'viewGroup'>;
|
||||
|
||||
export type DeleteViewGroupAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'viewGroup'>;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateViewGroupAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-group/types/workspace-migration-view-group-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatViewGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-group-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewGroupActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.viewGroup
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewGroupValidatorService: FlatViewGroupValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.viewGroup);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewGroup>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewGroup,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewGroupValidatorService.validateFlatViewGroupCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewGroupToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'viewGroup',
|
||||
flatEntity: flatViewGroupToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewGroup>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewGroup,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewGroupValidatorService.validateFlatViewGroupDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewGroupToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'viewGroup',
|
||||
entityId: flatViewGroupToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.viewGroup>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewGroup,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewGroupValidatorService.validateFlatViewGroupUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateViewGroupAction: UpdateViewGroupAction = {
|
||||
type: 'update',
|
||||
metadataName: 'viewGroup',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewGroupAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateViewAction = BaseCreateWorkspaceMigrationAction<'view'>;
|
||||
|
||||
export type UpdateViewAction = BaseUpdateWorkspaceMigrationAction<'view'>;
|
||||
|
||||
export type DeleteViewAction = BaseDeleteWorkspaceMigrationAction<'view'>;
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateViewAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view/types/workspace-migration-view-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.view
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewValidatorService: FlatViewValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.view);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.view>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.view, 'create'> {
|
||||
const validationResult =
|
||||
this.flatViewValidatorService.validateFlatViewCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'view',
|
||||
flatEntity: flatViewToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.view>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.view, 'delete'> {
|
||||
const validationResult =
|
||||
this.flatViewValidatorService.validateFlatViewDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'view',
|
||||
entityId: flatViewToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.view>,
|
||||
): FlatEntityValidationReturnType<typeof ALL_METADATA_NAME.view, 'update'> {
|
||||
const validationResult =
|
||||
this.flatViewValidatorService.validateFlatViewUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateViewAction: UpdateViewAction = {
|
||||
type: 'update',
|
||||
metadataName: 'view',
|
||||
entityId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
import { Inject } from '@nestjs/common';
|
||||
|
||||
import { AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { LoggerService } from 'src/engine/core-modules/logger/logger.service';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { MetadataFlatEntityAndRelatedFlatEntityMapsForValidation } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-and-related-flat-entity-maps-for-validation.type';
|
||||
import { MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { MetadataValidationRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { WorkspaceMigrationBuilderAdditionalCacheDataMaps } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-builder-additional-cache-data-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { flatEntityDeletedCreatedUpdatedMatrixDispatcher } from 'src/engine/workspace-manager/workspace-migration/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util';
|
||||
import { getMetadataEmptyWorkspaceMigrationActionRecord } from 'src/engine/workspace-manager/workspace-migration/utils/get-metadata-empty-workspace-migration-action-record.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { shouldInferDeletionFromMissingEntities } from 'src/engine/workspace-manager/workspace-migration/utils/should-infer-deletion-from-missing-entities.util';
|
||||
import { FailedFlatEntityValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/failed-flat-entity-validate-and-build.type';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-result.type';
|
||||
import { SuccessfulFlatEntityValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/successful-flat-entity-validate-and-build.type';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
export type ValidateAndBuildArgs<T extends AllMetadataName> = {
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
dependencyOptimisticFlatEntityMaps: MetadataValidationRelatedFlatEntityMaps<T>;
|
||||
workspaceId: string;
|
||||
additionalCacheDataMaps: WorkspaceMigrationBuilderAdditionalCacheDataMaps;
|
||||
} & FromTo<MetadataFlatEntityMaps<T>>;
|
||||
|
||||
export type ValidateAndBuildReturnType<T extends AllMetadataName> = Promise<
|
||||
SuccessfulFlatEntityValidateAndBuild<T> | FailedFlatEntityValidateAndBuild<T>
|
||||
>;
|
||||
|
||||
export abstract class WorkspaceEntityMigrationBuilderService<
|
||||
T extends AllMetadataName,
|
||||
> {
|
||||
@Inject(LoggerService)
|
||||
protected readonly logger: LoggerService;
|
||||
private metadataName: T;
|
||||
|
||||
constructor(metadataName: T) {
|
||||
this.metadataName = metadataName;
|
||||
}
|
||||
|
||||
public async validateAndBuild({
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: inputDependencyOptimisticFlatEntityMaps,
|
||||
from: fromFlatEntityMaps,
|
||||
to: toFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
workspaceId,
|
||||
}: ValidateAndBuildArgs<T>): ValidateAndBuildReturnType<T> {
|
||||
this.logger.time(`EntityBuilder ${this.metadataName}`, 'validateAndBuild');
|
||||
this.logger.time(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'matrix computation',
|
||||
);
|
||||
|
||||
const fromFlatEntities = Object.values(fromFlatEntityMaps.byId).filter(
|
||||
isDefined,
|
||||
);
|
||||
const toFlatEntities = Object.values(toFlatEntityMaps.byId).filter(
|
||||
isDefined,
|
||||
);
|
||||
|
||||
const {
|
||||
createdFlatEntityMaps,
|
||||
deletedFlatEntityMaps,
|
||||
updatedFlatEntityMaps,
|
||||
} = flatEntityDeletedCreatedUpdatedMatrixDispatcher<T>({
|
||||
from: fromFlatEntities,
|
||||
to: toFlatEntities,
|
||||
metadataName: this.metadataName,
|
||||
buildOptions,
|
||||
});
|
||||
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'matrix computation',
|
||||
);
|
||||
this.logger.time(`EntityBuilder ${this.metadataName}`, 'entity processing');
|
||||
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(this.metadataName);
|
||||
const optimisticFlatEntityMapsAndRelatedFlatEntityMaps = {
|
||||
[flatEntityMapsKey]: structuredClone(fromFlatEntityMaps),
|
||||
...structuredClone(inputDependencyOptimisticFlatEntityMaps),
|
||||
} as MetadataFlatEntityAndRelatedFlatEntityMapsForValidation<T>;
|
||||
|
||||
const actionsResult = getMetadataEmptyWorkspaceMigrationActionRecord(
|
||||
this.metadataName,
|
||||
);
|
||||
const allValidationResult: FailedFlatEntityValidateAndBuild<T>['errors'] =
|
||||
[];
|
||||
const remainingFlatEntityMapsToCreate = structuredClone(
|
||||
createdFlatEntityMaps,
|
||||
);
|
||||
|
||||
this.logger.time(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'creation validation',
|
||||
);
|
||||
for (const flatEntityToCreateId in createdFlatEntityMaps.byId) {
|
||||
const flatEntityToCreate =
|
||||
createdFlatEntityMaps.byId[flatEntityToCreateId];
|
||||
|
||||
if (!isDefined(flatEntityToCreate)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Could not find flat entity to create in maps should never occur',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
|
||||
entityToDeleteId: flatEntityToCreateId,
|
||||
flatEntityMapsToMutate: remainingFlatEntityMapsToCreate,
|
||||
});
|
||||
|
||||
const validationResult = await this.validateFlatEntityCreation({
|
||||
additionalCacheDataMaps,
|
||||
flatEntityToValidate: flatEntityToCreate,
|
||||
workspaceId,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
remainingFlatEntityMapsToValidate: remainingFlatEntityMapsToCreate,
|
||||
buildOptions,
|
||||
});
|
||||
|
||||
if (validationResult.status === 'fail') {
|
||||
allValidationResult.push(validationResult);
|
||||
continue;
|
||||
}
|
||||
|
||||
addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatEntityToCreate,
|
||||
flatEntityAndRelatedMapsToMutate:
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
metadataName: this.metadataName,
|
||||
});
|
||||
|
||||
actionsResult.create.push(
|
||||
...(Array.isArray(validationResult.action)
|
||||
? validationResult.action
|
||||
: [validationResult.action]),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'creation validation',
|
||||
);
|
||||
this.logger.time(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'deletion validation',
|
||||
);
|
||||
|
||||
const remainingFlatEntityMapsToDelete = structuredClone(
|
||||
deletedFlatEntityMaps,
|
||||
);
|
||||
|
||||
const flatEntityToDeleteIds = shouldInferDeletionFromMissingEntities({
|
||||
buildOptions,
|
||||
metadataName: this.metadataName,
|
||||
})
|
||||
? Object.keys(deletedFlatEntityMaps.byId)
|
||||
: [];
|
||||
|
||||
for (const flatEntityToDeleteId of flatEntityToDeleteIds) {
|
||||
const flatEntityToDelete =
|
||||
deletedFlatEntityMaps.byId[flatEntityToDeleteId];
|
||||
|
||||
if (!isDefined(flatEntityToDelete)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Could not find flat entity to delete in maps should never occur',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
|
||||
entityToDeleteId: flatEntityToDeleteId,
|
||||
flatEntityMapsToMutate: remainingFlatEntityMapsToDelete,
|
||||
});
|
||||
|
||||
const validationResult = await this.validateFlatEntityDeletion({
|
||||
flatEntityToValidate: flatEntityToDelete,
|
||||
workspaceId,
|
||||
remainingFlatEntityMapsToValidate: remainingFlatEntityMapsToDelete,
|
||||
buildOptions,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
});
|
||||
|
||||
if (validationResult.status === 'fail') {
|
||||
allValidationResult.push(validationResult);
|
||||
continue;
|
||||
}
|
||||
|
||||
deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatEntityToDelete,
|
||||
flatEntityAndRelatedMapsToMutate:
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
metadataName: this.metadataName,
|
||||
});
|
||||
|
||||
actionsResult.delete.push(
|
||||
...(Array.isArray(validationResult.action)
|
||||
? validationResult.action
|
||||
: [validationResult.action]),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'deletion validation',
|
||||
);
|
||||
this.logger.time(`EntityBuilder ${this.metadataName}`, 'update validation');
|
||||
|
||||
for (const flatEntityToUpdateId in updatedFlatEntityMaps.byId) {
|
||||
const flatEntityToUpdate =
|
||||
updatedFlatEntityMaps.byId[flatEntityToUpdateId];
|
||||
|
||||
if (!isDefined(flatEntityToUpdate)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Could not find flat entity updates in maps dispatcher should never occur',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const validationResult = await this.validateFlatEntityUpdate({
|
||||
flatEntityUpdates: flatEntityToUpdate.updates,
|
||||
flatEntityId: flatEntityToUpdateId,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
workspaceId,
|
||||
buildOptions,
|
||||
additionalCacheDataMaps,
|
||||
});
|
||||
|
||||
if (validationResult.status === 'fail') {
|
||||
allValidationResult.push(validationResult);
|
||||
continue;
|
||||
}
|
||||
|
||||
const existingFlatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatEntityToUpdateId,
|
||||
flatEntityMaps: optimisticFlatEntityMapsAndRelatedFlatEntityMaps[
|
||||
flatEntityMapsKey
|
||||
] as MetadataFlatEntityMaps<T>,
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatEntity)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Existing flat entity to update post successful validation is not defined, should never occur',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedFlatEntity = {
|
||||
...existingFlatEntity,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
|
||||
updates: flatEntityToUpdate.updates,
|
||||
}),
|
||||
};
|
||||
|
||||
replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: updatedFlatEntity,
|
||||
flatEntityMapsToMutate:
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps[flatEntityMapsKey],
|
||||
});
|
||||
|
||||
actionsResult.update.push(
|
||||
...(Array.isArray(validationResult.action)
|
||||
? validationResult.action
|
||||
: [validationResult.action]),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'update validation',
|
||||
);
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'entity processing',
|
||||
);
|
||||
|
||||
if (allValidationResult.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
errors: allValidationResult,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
};
|
||||
}
|
||||
|
||||
this.logger.timeEnd(
|
||||
`EntityBuilder ${this.metadataName}`,
|
||||
'validateAndBuild',
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
actions: actionsResult,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<T>,
|
||||
):
|
||||
| FlatEntityValidationReturnType<T, 'create'>
|
||||
| Promise<FlatEntityValidationReturnType<T, 'create'>>;
|
||||
|
||||
protected abstract validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<T>,
|
||||
):
|
||||
| FlatEntityValidationReturnType<T, 'delete'>
|
||||
| Promise<FlatEntityValidationReturnType<T, 'delete'>>;
|
||||
|
||||
protected abstract validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<T>,
|
||||
):
|
||||
| FlatEntityValidationReturnType<T, 'update'>
|
||||
| Promise<FlatEntityValidationReturnType<T, 'update'>>;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
|
||||
export type BaseCreateWorkspaceMigrationAction<T extends AllMetadataName> = {
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
type: 'create';
|
||||
metadataName: T;
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
export type BaseDeleteWorkspaceMigrationAction<T extends AllMetadataName> = {
|
||||
entityId: string;
|
||||
type: 'delete';
|
||||
metadataName: T;
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
|
||||
export type BaseUpdateWorkspaceMigrationAction<T extends AllMetadataName> = {
|
||||
type: 'update';
|
||||
metadataName: T;
|
||||
entityId: string;
|
||||
updates: FlatEntityPropertiesUpdates<T>;
|
||||
};
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export type ConvertActionTypeToCamelCase<T extends string> =
|
||||
T extends `${infer Before}_${infer After}`
|
||||
? `${Before}${Capitalize<After>}`
|
||||
: T;
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { type WorkspaceMigrationActionType } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
export type FailedFlatEntityValidateAndBuild<T extends AllMetadataName> = {
|
||||
status: 'fail';
|
||||
errors: FailedFlatEntityValidation<T, WorkspaceMigrationActionType>[];
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
|
||||
export type FlatEntityUpdateValidationArgs<T extends AllMetadataName> = Omit<
|
||||
FlatEntityValidationArgs<T>,
|
||||
'flatEntityToValidate' | 'remainingFlatEntityMapsToValidate'
|
||||
> & {
|
||||
flatEntityId: string;
|
||||
flatEntityUpdates: FlatEntityPropertiesUpdates<T>;
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMapsForValidation } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-and-related-flat-entity-maps-for-validation.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { type WorkspaceMigrationBuilderAdditionalCacheDataMaps } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-builder-additional-cache-data-maps.type';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
|
||||
export type FlatEntityValidationArgs<T extends AllMetadataName> = {
|
||||
additionalCacheDataMaps: WorkspaceMigrationBuilderAdditionalCacheDataMaps;
|
||||
flatEntityToValidate: MetadataFlatEntity<T>;
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: MetadataFlatEntityAndRelatedFlatEntityMapsForValidation<T>;
|
||||
workspaceId: string;
|
||||
remainingFlatEntityMapsToValidate: MetadataFlatEntityMaps<T>;
|
||||
buildOptions: WorkspaceMigrationBuilderOptions;
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import {
|
||||
type MetadataWorkspaceMigrationAction,
|
||||
type WorkspaceMigrationActionType,
|
||||
} from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
export type FlatEntityValidationReturnType<
|
||||
TMetadataName extends AllMetadataName,
|
||||
TACtionType extends WorkspaceMigrationActionType,
|
||||
> =
|
||||
| {
|
||||
status: 'success';
|
||||
action:
|
||||
| MetadataWorkspaceMigrationAction<TMetadataName, TACtionType>
|
||||
| MetadataWorkspaceMigrationAction<TMetadataName, TACtionType>[];
|
||||
}
|
||||
| ({
|
||||
status: 'fail';
|
||||
} & FailedFlatEntityValidation<TMetadataName, TACtionType>);
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
export type InferDeletionFromMissingEntities =
|
||||
| true
|
||||
| Partial<Record<AllMetadataName, boolean>>
|
||||
| undefined;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export type RemoveSuffix<
|
||||
T extends string,
|
||||
P extends string,
|
||||
> = T extends `${infer Prefix}${P}` ? Prefix : T;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { type MetadataWorkspaceMigrationActionsRecord } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
|
||||
export type SuccessfulFlatEntityValidateAndBuild<T extends AllMetadataName> = {
|
||||
status: 'success';
|
||||
actions: MetadataWorkspaceMigrationActionsRecord<T>;
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import {
|
||||
type MetadataWorkspaceMigrationAction,
|
||||
type WorkspaceMigrationActionType,
|
||||
} from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
|
||||
export type WorkspaceMigrationAction = MetadataWorkspaceMigrationAction<
|
||||
AllMetadataName,
|
||||
WorkspaceMigrationActionType
|
||||
>;
|
||||
|
||||
export { WorkspaceMigrationActionType };
|
||||
|
||||
export type WorkspaceMigrationActionHandlerKey =
|
||||
`${WorkspaceMigrationActionType}_${AllMetadataName}`;
|
||||
|
||||
export const buildActionHandlerKey = (
|
||||
actionType: WorkspaceMigrationActionType,
|
||||
metadataName: AllMetadataName,
|
||||
): WorkspaceMigrationActionHandlerKey => `${actionType}_${metadataName}`;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { type InferDeletionFromMissingEntities } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/infer-deletion-from-missing-entities.type';
|
||||
|
||||
export type WorkspaceMigrationBuilderOptions = {
|
||||
inferDeletionFromMissingEntities?: InferDeletionFromMissingEntities;
|
||||
isSystemBuild: boolean;
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type WorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
|
||||
|
||||
export type WorkspaceMigration<
|
||||
TActions extends WorkspaceMigrationAction = WorkspaceMigrationAction,
|
||||
> = {
|
||||
actions: TActions[];
|
||||
workspaceId: string;
|
||||
// TODO remove from workspaceMigration once we've refactored the actions to have metadata and action type grain
|
||||
relatedFlatEntityMapsKeys?: (keyof AllFlatEntityMaps)[];
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user