Add db event trigger and cron trigger to migration v2 (#14772)
## Context Add DB events triggers and Cron triggers to migration v2 builder/runner (and adding corresponding services/resolvers)
This commit is contained in:
+5
-5
@@ -10,17 +10,17 @@ import { type ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/ty
|
||||
import { type ObjectRecordNonDestructiveEvent } from 'src/engine/core-modules/event-emitter/types/object-record-non-destructive-event';
|
||||
import { type ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event';
|
||||
import { type ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
|
||||
import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job';
|
||||
import { CallWebhookJobsJob } from 'src/engine/core-modules/webhook/jobs/call-webhook-jobs.job';
|
||||
import { type ObjectRecordEventForWebhook } from 'src/engine/core-modules/webhook/types/object-record-event-for-webhook.type';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
import { SubscriptionsService } from 'src/engine/subscriptions/subscriptions.service';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
|
||||
import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job';
|
||||
|
||||
@Injectable()
|
||||
export class EntityEventsToDbListener {
|
||||
|
||||
+2
@@ -6,4 +6,6 @@ export const ALL_FLAT_ENTITY_MAPS_PROPERTIES = [
|
||||
'flatViewMaps',
|
||||
'flatIndexMaps',
|
||||
'flatServerlessFunctionMaps',
|
||||
'flatDatabaseEventTriggerMaps',
|
||||
'flatCronTriggerMaps',
|
||||
] as const satisfies (keyof AllFlatEntityMaps)[];
|
||||
|
||||
+2
@@ -10,4 +10,6 @@ export const EMPTY_ALL_FLAT_ENTITY_MAPS = {
|
||||
flatViewFieldMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatViewMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatServerlessFunctionMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatCronTriggerMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatDatabaseEventTriggerMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
} as const satisfies AllFlatEntityMaps;
|
||||
|
||||
+4
@@ -1,5 +1,7 @@
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
|
||||
@@ -11,4 +13,6 @@ export type AllFlatEntitiesByMetadataEngineName = {
|
||||
viewField: FlatViewField;
|
||||
index: FlatIndexMetadata;
|
||||
serverlessFunction: FlatServerlessFunction;
|
||||
cronTrigger: FlatCronTrigger;
|
||||
databaseEventTrigger: FlatDatabaseEventTrigger;
|
||||
};
|
||||
|
||||
@@ -14,11 +14,15 @@ import { EmailModule } from 'src/engine/core-modules/email/email.module';
|
||||
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
|
||||
import { UserVarsModule } from 'src/engine/core-modules/user/user-vars/user-vars.module';
|
||||
import { UserModule } from 'src/engine/core-modules/user/user.module';
|
||||
import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module';
|
||||
import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
|
||||
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { SubscriptionsModule } from 'src/engine/subscriptions/subscriptions.module';
|
||||
import { CleanOnboardingWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-onboarding-workspaces.job';
|
||||
import { CleanSuspendedWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-suspended-workspaces.job';
|
||||
@@ -31,10 +35,7 @@ import { FavoriteModule } from 'src/modules/favorite/favorite.module';
|
||||
import { MessagingModule } from 'src/modules/messaging/messaging.module';
|
||||
import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module';
|
||||
import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module';
|
||||
import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module';
|
||||
import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
||||
import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -62,7 +63,8 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless
|
||||
WorkspaceCleanerModule,
|
||||
SubscriptionsModule,
|
||||
AuditJobModule,
|
||||
TriggerModule,
|
||||
CronTriggerModule,
|
||||
DatabaseEventTriggerModule,
|
||||
ServerlessFunctionModule,
|
||||
],
|
||||
providers: [
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
|
||||
export const FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES = [
|
||||
'settings',
|
||||
] as const satisfies (keyof FlatCronTrigger)[];
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
|
||||
export const FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE = [
|
||||
...FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES,
|
||||
] as const satisfies (keyof FlatCronTrigger)[];
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { CronTriggerResolver } from 'src/engine/metadata-modules/cron-trigger/resolvers/cron-trigger.resolver';
|
||||
import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service';
|
||||
import { WorkspaceFlatCronTriggerMapCacheService } from 'src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, CronTrigger]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
],
|
||||
providers: [
|
||||
CronTriggerCronJob,
|
||||
CronTriggerCronCommand,
|
||||
CronTriggerResolver,
|
||||
CronTriggerV2Service,
|
||||
WorkspaceFlatCronTriggerMapCacheService,
|
||||
],
|
||||
exports: [
|
||||
CronTriggerCronCommand,
|
||||
CronTriggerV2Service,
|
||||
WorkspaceFlatCronTriggerMapCacheService,
|
||||
],
|
||||
})
|
||||
export class CronTriggerModule {}
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { MessageQueueService } from 'src/engine/core-modules/message-queue/servi
|
||||
import {
|
||||
CRON_TRIGGER_CRON_PATTERN,
|
||||
CronTriggerCronJob,
|
||||
} from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job';
|
||||
} from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
@Command({
|
||||
name: 'cron:trigger:start-cron-trigger',
|
||||
description:
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { Process } from 'src/engine/core-modules/message-queue/decorators/proces
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import {
|
||||
ServerlessFunctionTriggerJob,
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
|
||||
@InputType()
|
||||
export class CreateCronTriggerInput {
|
||||
@IsObject()
|
||||
@IsNotEmpty()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: CronTriggerSettings;
|
||||
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
serverlessFunctionId: string;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class CronTriggerIdInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsDateString, IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
|
||||
@ObjectType('CronTrigger')
|
||||
export class CronTriggerDTO {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@IDField(() => UUIDScalarType)
|
||||
id: string;
|
||||
|
||||
@IsObject()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: CronTriggerSettings;
|
||||
|
||||
@HideField()
|
||||
workspaceId: string;
|
||||
|
||||
@IsUUID()
|
||||
@Field()
|
||||
serverlessFunctionId: string;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
createdAt: Date;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
|
||||
@InputType()
|
||||
export class UpdateCronTriggerInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
|
||||
@IsObject()
|
||||
@IsNotEmpty()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: CronTriggerSettings;
|
||||
}
|
||||
+10
-2
@@ -2,22 +2,27 @@ import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
Relation,
|
||||
Index,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
|
||||
|
||||
import { CronTriggerEntityRelationProperties } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
|
||||
export type CronTriggerSettings = {
|
||||
pattern: string;
|
||||
};
|
||||
|
||||
export const CRON_TRIGGER_ENTITY_RELATION_PROPERTIES = [
|
||||
'serverlessFunction',
|
||||
] as const satisfies readonly CronTriggerEntityRelationProperties[];
|
||||
|
||||
@Entity({ name: 'cronTrigger', schema: 'core' })
|
||||
@Index('IDX_CRON_TRIGGER_WORKSPACE_ID', ['workspaceId'])
|
||||
export class CronTrigger extends SyncableEntity {
|
||||
@@ -35,6 +40,9 @@ export class CronTrigger extends SyncableEntity {
|
||||
@JoinColumn({ name: 'serverlessFunctionId' })
|
||||
serverlessFunction: Relation<ServerlessFunctionEntity>;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
serverlessFunctionId: string | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class CronTriggerException extends CustomException {
|
||||
constructor(message: string, code: CronTriggerExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum CronTriggerExceptionCode {
|
||||
CRON_TRIGGER_NOT_FOUND = 'CRON_TRIGGER_NOT_FOUND',
|
||||
CRON_TRIGGER_ALREADY_EXIST = 'CRON_TRIGGER_ALREADY_EXIST',
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
|
||||
import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input';
|
||||
import { CronTriggerDTO } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto';
|
||||
import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service';
|
||||
import { cronTriggerGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.util';
|
||||
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
@Resolver()
|
||||
@UsePipes(ResolverValidationPipe)
|
||||
@UseFilters(PreventNestToAutoLogGraphqlErrorsFilter)
|
||||
export class CronTriggerResolver {
|
||||
constructor(
|
||||
private readonly cronTriggerV2Service: CronTriggerV2Service,
|
||||
@InjectRepository(CronTrigger)
|
||||
private readonly cronTriggerRepository: Repository<CronTrigger>,
|
||||
) {}
|
||||
|
||||
@Query(() => CronTriggerDTO)
|
||||
async findOneCronTrigger(
|
||||
@Args('input') { id }: CronTriggerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.cronTriggerRepository.findOneOrFail({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
cronTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => [CronTriggerDTO])
|
||||
async findManyCronTriggers(@AuthWorkspace() { id: workspaceId }: Workspace) {
|
||||
try {
|
||||
return await this.cronTriggerRepository.find({
|
||||
where: { workspaceId },
|
||||
});
|
||||
} catch (error) {
|
||||
cronTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => CronTriggerDTO)
|
||||
async deleteOneCronTrigger(
|
||||
@Args('input') input: CronTriggerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.cronTriggerV2Service.destroyOne({
|
||||
destroyCronTriggerInput: input,
|
||||
workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
cronTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => CronTriggerDTO)
|
||||
async updateOneCronTrigger(
|
||||
@Args('input')
|
||||
input: UpdateCronTriggerInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.cronTriggerV2Service.updateOne(input, workspaceId);
|
||||
} catch (error) {
|
||||
cronTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => CronTriggerDTO)
|
||||
async createOneCronTrigger(
|
||||
@Args('input')
|
||||
input: CreateCronTriggerInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.cronTriggerV2Service.createOne(input, workspaceId);
|
||||
} catch (error) {
|
||||
cronTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service.';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
|
||||
import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input';
|
||||
import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input';
|
||||
import {
|
||||
CronTriggerException,
|
||||
CronTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception';
|
||||
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { fromCreateCronTriggerInputToFlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/utils/from-create-cron-trigger-input-to-flat-cron-trigger.util';
|
||||
import { fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow } from 'src/engine/metadata-modules/cron-trigger/utils/from-update-cron-trigger-input-to-flat-cron-trigger-to-update-or-throw.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
@Injectable()
|
||||
export class CronTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
cronTriggerInput: CreateCronTriggerInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatCronTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatCronTriggerMaps = flatEntityMaps.flatCronTriggerMaps;
|
||||
|
||||
const flatCronTriggerToCreate = fromCreateCronTriggerInputToFlatCronTrigger(
|
||||
{
|
||||
createCronTriggerInput: cronTriggerInput,
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const toFlatCronTriggerMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatCronTriggerToCreate,
|
||||
flatEntityMaps: existingFlatCronTriggerMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
workspaceId,
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatCronTriggerMaps: {
|
||||
from: existingFlatCronTriggerMaps,
|
||||
to: toFlatCronTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while creating cron trigger',
|
||||
);
|
||||
}
|
||||
|
||||
const { flatCronTriggerMaps: recomputedExistingFlatCronTriggerMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatCronTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatCronTriggerToCreate.id,
|
||||
flatEntityMaps: recomputedExistingFlatCronTriggerMaps,
|
||||
});
|
||||
}
|
||||
|
||||
async updateOne(
|
||||
cronTriggerInput: UpdateCronTriggerInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatCronTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatCronTriggerMaps = flatEntityMaps.flatCronTriggerMaps;
|
||||
|
||||
const optimisticallyUpdatedFlatCronTrigger =
|
||||
fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow({
|
||||
flatCronTriggerMaps: existingFlatCronTriggerMaps,
|
||||
updateCronTriggerInput: cronTriggerInput,
|
||||
});
|
||||
|
||||
const fromFlatCronTriggerMaps = getSubFlatEntityMapsOrThrow({
|
||||
flatEntityIds: [optimisticallyUpdatedFlatCronTrigger.id],
|
||||
flatEntityMaps: existingFlatCronTriggerMaps,
|
||||
});
|
||||
const toFlatCronTriggerMaps = replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: optimisticallyUpdatedFlatCronTrigger,
|
||||
flatEntityMaps: fromFlatCronTriggerMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
workspaceId,
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatCronTriggerMaps: {
|
||||
from: existingFlatCronTriggerMaps,
|
||||
to: toFlatCronTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while updating cron trigger',
|
||||
);
|
||||
}
|
||||
|
||||
const { flatCronTriggerMaps: recomputedExistingFlatCronTriggerMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatCronTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: optimisticallyUpdatedFlatCronTrigger.id,
|
||||
flatEntityMaps: recomputedExistingFlatCronTriggerMaps,
|
||||
});
|
||||
}
|
||||
|
||||
async destroyOne({
|
||||
destroyCronTriggerInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
destroyCronTriggerInput: CronTriggerIdInput;
|
||||
workspaceId: string;
|
||||
}): Promise<FlatCronTrigger> {
|
||||
const { flatCronTriggerMaps: existingFlatCronTriggerMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatCronTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatCronTrigger =
|
||||
existingFlatCronTriggerMaps.byId[destroyCronTriggerInput.id];
|
||||
|
||||
if (!isDefined(existingFlatCronTrigger)) {
|
||||
throw new CronTriggerException(
|
||||
'Cron trigger to destroy not found',
|
||||
CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fromFlatCronTriggerMaps = getSubFlatEntityMapsOrThrow({
|
||||
flatEntityIds: [existingFlatCronTrigger.id],
|
||||
flatEntityMaps: existingFlatCronTriggerMaps,
|
||||
});
|
||||
const toFlatCronTriggerMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: fromFlatCronTriggerMaps,
|
||||
entityToDeleteId: existingFlatCronTrigger.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatCronTriggerMaps: {
|
||||
from: fromFlatCronTriggerMaps,
|
||||
to: toFlatCronTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: true,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while destroying cron trigger',
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatCronTrigger;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant';
|
||||
import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import {
|
||||
CRON_TRIGGER_ENTITY_RELATION_PROPERTIES,
|
||||
CronTrigger,
|
||||
} from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
|
||||
import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceFlatMapCache('flatCronTriggerMaps')
|
||||
export class WorkspaceFlatCronTriggerMapCacheService extends WorkspaceFlatMapCacheService<
|
||||
FlatEntityMaps<FlatCronTrigger>
|
||||
> {
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
cacheStorageService: CacheStorageService,
|
||||
@InjectRepository(CronTrigger)
|
||||
private readonly cronTriggerRepository: Repository<CronTrigger>,
|
||||
) {
|
||||
super(cacheStorageService);
|
||||
}
|
||||
|
||||
protected async computeFlatMap({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<FlatEntityMaps<FlatCronTrigger>> {
|
||||
const cronTriggers = await this.cronTriggerRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const flatCronTriggerMaps = cronTriggers.reduce<
|
||||
FlatEntityMaps<FlatCronTrigger>
|
||||
>((flatEntityMaps, cronTrigger) => {
|
||||
const flatCronTrigger = {
|
||||
...removePropertiesFromRecord(cronTrigger, [
|
||||
...CRON_TRIGGER_ENTITY_RELATION_PROPERTIES,
|
||||
]),
|
||||
universalIdentifier: cronTrigger.universalIdentifier ?? cronTrigger.id,
|
||||
} satisfies FlatCronTrigger;
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatEntityMaps.byId,
|
||||
[flatCronTrigger.id]: flatCronTrigger,
|
||||
},
|
||||
idByUniversalIdentifier: {
|
||||
...flatEntityMaps.idByUniversalIdentifier,
|
||||
[flatCronTrigger.universalIdentifier]: flatCronTrigger.id,
|
||||
},
|
||||
};
|
||||
}, EMPTY_FLAT_ENTITY_MAPS);
|
||||
|
||||
return flatCronTriggerMaps;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
|
||||
export type FlatCronTriggerPropertiesToCompare = keyof Pick<
|
||||
FlatCronTrigger,
|
||||
'settings'
|
||||
>;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type CronTriggerEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
CronTrigger,
|
||||
ServerlessFunctionEntity | Workspace
|
||||
>;
|
||||
|
||||
export type FlatCronTrigger = Omit<
|
||||
CronTrigger,
|
||||
CronTriggerEntityRelationProperties
|
||||
> & {
|
||||
universalIdentifier: string;
|
||||
};
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import diff from 'microdiff';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { parseJson } from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-properties-to-compare.constant';
|
||||
import { type CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { type FlatCronTriggerPropertiesToCompare } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { type UpdateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
type GetWorkspaceMigrationUpdateCronTriggerActionArgs = FromTo<
|
||||
FlatCronTrigger,
|
||||
'FlatCronTrigger'
|
||||
>;
|
||||
|
||||
export const compareTwoFlatCronTrigger = ({
|
||||
fromFlatCronTrigger,
|
||||
toFlatCronTrigger,
|
||||
}: GetWorkspaceMigrationUpdateCronTriggerActionArgs) => {
|
||||
const transformMetadataForComparisonParameters = {
|
||||
shouldIgnoreProperty: (property: string) =>
|
||||
!FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE.includes(
|
||||
property as FlatCronTriggerPropertiesToCompare,
|
||||
),
|
||||
propertiesToStringify: ['settings'] as const,
|
||||
};
|
||||
const fromCompare = transformMetadataForComparison(
|
||||
fromFlatCronTrigger,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
const toCompare = transformMetadataForComparison(
|
||||
toFlatCronTrigger,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
|
||||
const flatCronTriggerDifferences = diff(fromCompare, toCompare);
|
||||
|
||||
return flatCronTriggerDifferences.flatMap<
|
||||
UpdateCronTriggerAction['updates'][number]
|
||||
>((difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { oldValue, path, value } = difference;
|
||||
const property = path[0] as FlatCronTriggerPropertiesToCompare;
|
||||
|
||||
if (property === 'settings') {
|
||||
return {
|
||||
from: parseJson(oldValue) as CronTriggerSettings,
|
||||
to: parseJson(value) as CronTriggerSettings,
|
||||
property,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
from: oldValue,
|
||||
to: value,
|
||||
property,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occurs, we should only provide null never undefined and so on
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import {
|
||||
ConflictError,
|
||||
NotFoundError,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import {
|
||||
CronTriggerException,
|
||||
CronTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception';
|
||||
|
||||
export const cronTriggerGraphQLApiExceptionHandler = (error: Error): void => {
|
||||
if (error instanceof CronTriggerException) {
|
||||
switch (error.code) {
|
||||
case CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND:
|
||||
throw new NotFoundError('Cron trigger not found');
|
||||
case CronTriggerExceptionCode.CRON_TRIGGER_ALREADY_EXIST:
|
||||
throw new ConflictError('Cron trigger already exists');
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { CronTriggerException } from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception';
|
||||
|
||||
export const cronTriggerGraphqlApiExceptionHandler = (error: Error) => {
|
||||
if (error instanceof CronTriggerException) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { type CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
|
||||
export const fromCreateCronTriggerInputToFlatCronTrigger = ({
|
||||
createCronTriggerInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createCronTriggerInput: CreateCronTriggerInput;
|
||||
workspaceId: string;
|
||||
}): FlatCronTrigger => {
|
||||
const now = new Date();
|
||||
|
||||
return {
|
||||
id: uuidv4(),
|
||||
universalIdentifier: uuidv4(),
|
||||
settings: createCronTriggerInput.settings,
|
||||
serverlessFunctionId: createCronTriggerInput.serverlessFunctionId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { type UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input';
|
||||
import {
|
||||
CronTriggerException,
|
||||
CronTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
|
||||
export const fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow = ({
|
||||
flatCronTriggerMaps,
|
||||
updateCronTriggerInput,
|
||||
}: {
|
||||
flatCronTriggerMaps: FlatEntityMaps<FlatCronTrigger>;
|
||||
updateCronTriggerInput: UpdateCronTriggerInput;
|
||||
}): FlatCronTrigger => {
|
||||
const existingFlatCronTrigger =
|
||||
flatCronTriggerMaps.byId[updateCronTriggerInput.id];
|
||||
|
||||
if (!existingFlatCronTrigger) {
|
||||
throw new CronTriggerException(
|
||||
'Cron trigger not found',
|
||||
CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatCronTrigger,
|
||||
settings: updateCronTriggerInput.settings,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
};
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
|
||||
export const FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES = [
|
||||
'settings',
|
||||
] as const satisfies (keyof FlatDatabaseEventTrigger)[];
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
|
||||
export const FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE = [
|
||||
...FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES,
|
||||
] as const satisfies (keyof FlatDatabaseEventTrigger)[];
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
import { DatabaseEventTriggerResolver } from 'src/engine/metadata-modules/database-event-trigger/resolvers/database-event-trigger.resolver';
|
||||
import { DatabaseEventTriggerV2Service } from 'src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service';
|
||||
import { WorkspaceFlatDatabaseEventTriggerMapCacheService } from 'src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, DatabaseEventTrigger]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
],
|
||||
providers: [
|
||||
CallDatabaseEventTriggerJobsJob,
|
||||
DatabaseEventTriggerV2Service,
|
||||
DatabaseEventTriggerResolver,
|
||||
WorkspaceFlatDatabaseEventTriggerMapCacheService,
|
||||
],
|
||||
exports: [DatabaseEventTriggerV2Service],
|
||||
})
|
||||
export class DatabaseEventTriggerModule {}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
|
||||
@InputType()
|
||||
export class CreateDatabaseEventTriggerInput {
|
||||
@IsObject()
|
||||
@IsNotEmpty()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: DatabaseEventTriggerSettings;
|
||||
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
serverlessFunctionId: string;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class DatabaseEventTriggerIdInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
id: string;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsDateString, IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
|
||||
@ObjectType('DatabaseEventTrigger')
|
||||
export class DatabaseEventTriggerDTO {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@IDField(() => UUIDScalarType)
|
||||
id: string;
|
||||
|
||||
@IsObject()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: DatabaseEventTriggerSettings;
|
||||
|
||||
@HideField()
|
||||
workspaceId: string;
|
||||
|
||||
@IsUUID()
|
||||
@Field()
|
||||
serverlessFunctionId: string;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
createdAt: Date;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsObject, IsUUID } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
|
||||
@InputType()
|
||||
export class UpdateDatabaseEventTriggerInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
id: string;
|
||||
|
||||
@IsObject()
|
||||
@IsNotEmpty()
|
||||
@Field(() => GraphQLJSON)
|
||||
settings: DatabaseEventTriggerSettings;
|
||||
}
|
||||
+15
-4
@@ -2,25 +2,33 @@ import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
Relation,
|
||||
Index,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
|
||||
|
||||
import { DatabaseEventTriggerEntityRelationProperties } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
|
||||
export type DatabaseEventTriggerSettings = {
|
||||
eventName: string;
|
||||
};
|
||||
|
||||
@Entity({ name: 'databaseEventTrigger', schema: 'core' })
|
||||
export const DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES = [
|
||||
'serverlessFunction',
|
||||
] as const satisfies readonly DatabaseEventTriggerEntityRelationProperties[];
|
||||
|
||||
@Entity('databaseEventTrigger')
|
||||
@Index('IDX_DATABASE_EVENT_TRIGGER_WORKSPACE_ID', ['workspaceId'])
|
||||
export class DatabaseEventTrigger extends SyncableEntity {
|
||||
export class DatabaseEventTrigger
|
||||
extends SyncableEntity
|
||||
implements Required<DatabaseEventTrigger>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@@ -35,6 +43,9 @@ export class DatabaseEventTrigger extends SyncableEntity {
|
||||
@JoinColumn({ name: 'serverlessFunctionId' })
|
||||
serverlessFunction: Relation<ServerlessFunctionEntity>;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
serverlessFunctionId: string | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class DatabaseEventTriggerException extends CustomException {
|
||||
constructor(message: string, code: DatabaseEventTriggerExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum DatabaseEventTriggerExceptionCode {
|
||||
DATABASE_EVENT_TRIGGER_NOT_FOUND = 'DATABASE_EVENT_TRIGGER_NOT_FOUND',
|
||||
DATABASE_EVENT_TRIGGER_ALREADY_EXIST = 'DATABASE_EVENT_TRIGGER_ALREADY_EXIST',
|
||||
}
|
||||
+5
-5
@@ -2,18 +2,18 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import type { ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/types/object-record-event.event';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
|
||||
import type { ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/types/object-record-event.event';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import {
|
||||
ServerlessFunctionTriggerJob,
|
||||
ServerlessFunctionTriggerJobData,
|
||||
} from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
|
||||
|
||||
@Processor(MessageQueue.triggerQueue)
|
||||
export class CallDatabaseEventTriggerJobsJob {
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
|
||||
import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input';
|
||||
import { DatabaseEventTriggerDTO } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto';
|
||||
import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { DatabaseEventTriggerV2Service } from 'src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service';
|
||||
import { databaseEventTriggerGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/database-event-trigger/utils/database-event-trigger-graphql-api-exception-handler.utils';
|
||||
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
@Resolver()
|
||||
@UsePipes(ResolverValidationPipe)
|
||||
@UseFilters(PreventNestToAutoLogGraphqlErrorsFilter)
|
||||
export class DatabaseEventTriggerResolver {
|
||||
constructor(
|
||||
private readonly databaseEventTriggerV2Service: DatabaseEventTriggerV2Service,
|
||||
@InjectRepository(DatabaseEventTrigger)
|
||||
private readonly databaseEventTriggerRepository: Repository<DatabaseEventTrigger>,
|
||||
) {}
|
||||
|
||||
@Query(() => DatabaseEventTriggerDTO)
|
||||
async findOneDatabaseEventTrigger(
|
||||
@Args('input') { id }: DatabaseEventTriggerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.databaseEventTriggerRepository.findOneOrFail({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
databaseEventTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => [DatabaseEventTriggerDTO])
|
||||
async findManyDatabaseEventTriggers(
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.databaseEventTriggerRepository.find({
|
||||
where: { workspaceId },
|
||||
});
|
||||
} catch (error) {
|
||||
databaseEventTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => DatabaseEventTriggerDTO)
|
||||
async deleteOneDatabaseEventTrigger(
|
||||
@Args('input') input: DatabaseEventTriggerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.databaseEventTriggerV2Service.destroyOne({
|
||||
destroyDatabaseEventTriggerInput: input,
|
||||
workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
databaseEventTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => DatabaseEventTriggerDTO)
|
||||
async updateOneDatabaseEventTrigger(
|
||||
@Args('input')
|
||||
input: UpdateDatabaseEventTriggerInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.databaseEventTriggerV2Service.updateOne(
|
||||
input,
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
databaseEventTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => DatabaseEventTriggerDTO)
|
||||
async createOneDatabaseEventTrigger(
|
||||
@Args('input')
|
||||
input: CreateDatabaseEventTriggerInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
try {
|
||||
return await this.databaseEventTriggerV2Service.createOne(
|
||||
input,
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
databaseEventTriggerGraphQLApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service.';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
|
||||
import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input';
|
||||
import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input';
|
||||
import {
|
||||
DatabaseEventTriggerException,
|
||||
DatabaseEventTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception';
|
||||
import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/utils/from-create-database-event-trigger-input-to-flat-database-event-trigger.util';
|
||||
import { fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow } from 'src/engine/metadata-modules/database-event-trigger/utils/from-update-database-event-trigger-input-to-flat-database-event-trigger-to-update-or-throw.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
@Injectable()
|
||||
export class DatabaseEventTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
databaseEventTriggerInput: CreateDatabaseEventTriggerInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatDatabaseEventTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatDatabaseEventTriggerMaps =
|
||||
flatEntityMaps.flatDatabaseEventTriggerMaps;
|
||||
|
||||
const flatDatabaseEventTriggerToCreate =
|
||||
fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger({
|
||||
createDatabaseEventTriggerInput: databaseEventTriggerInput,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const toFlatDatabaseEventTriggerMaps = addFlatEntityToFlatEntityMapsOrThrow(
|
||||
{
|
||||
flatEntity: flatDatabaseEventTriggerToCreate,
|
||||
flatEntityMaps: existingFlatDatabaseEventTriggerMaps,
|
||||
},
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
workspaceId,
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatDatabaseEventTriggerMaps: {
|
||||
from: existingFlatDatabaseEventTriggerMaps,
|
||||
to: toFlatDatabaseEventTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while creating database event trigger',
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
flatDatabaseEventTriggerMaps:
|
||||
recomputedExistingFlatDatabaseEventTriggerMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatDatabaseEventTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatDatabaseEventTriggerToCreate.id,
|
||||
flatEntityMaps: recomputedExistingFlatDatabaseEventTriggerMaps,
|
||||
});
|
||||
}
|
||||
|
||||
async updateOne(
|
||||
databaseEventTriggerInput: UpdateDatabaseEventTriggerInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatDatabaseEventTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatDatabaseEventTriggerMaps =
|
||||
flatEntityMaps.flatDatabaseEventTriggerMaps;
|
||||
|
||||
const optimisticallyUpdatedFlatDatabaseEventTrigger =
|
||||
fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow(
|
||||
{
|
||||
flatDatabaseEventTriggerMaps: existingFlatDatabaseEventTriggerMaps,
|
||||
updateDatabaseEventTriggerInput: databaseEventTriggerInput,
|
||||
},
|
||||
);
|
||||
|
||||
const fromFlatDatabaseEventTriggerMaps = getSubFlatEntityMapsOrThrow({
|
||||
flatEntityIds: [optimisticallyUpdatedFlatDatabaseEventTrigger.id],
|
||||
flatEntityMaps: existingFlatDatabaseEventTriggerMaps,
|
||||
});
|
||||
const toFlatDatabaseEventTriggerMaps =
|
||||
replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: optimisticallyUpdatedFlatDatabaseEventTrigger,
|
||||
flatEntityMaps: fromFlatDatabaseEventTriggerMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
workspaceId,
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatDatabaseEventTriggerMaps: {
|
||||
from: existingFlatDatabaseEventTriggerMaps,
|
||||
to: toFlatDatabaseEventTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while updating database event trigger',
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
flatDatabaseEventTriggerMaps:
|
||||
recomputedExistingFlatDatabaseEventTriggerMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatDatabaseEventTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: optimisticallyUpdatedFlatDatabaseEventTrigger.id,
|
||||
flatEntityMaps: recomputedExistingFlatDatabaseEventTriggerMaps,
|
||||
});
|
||||
}
|
||||
|
||||
async destroyOne({
|
||||
destroyDatabaseEventTriggerInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
destroyDatabaseEventTriggerInput: DatabaseEventTriggerIdInput;
|
||||
workspaceId: string;
|
||||
}): Promise<FlatDatabaseEventTrigger> {
|
||||
const {
|
||||
flatDatabaseEventTriggerMaps: existingFlatDatabaseEventTriggerMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatDatabaseEventTriggerMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFlatDatabaseEventTrigger =
|
||||
existingFlatDatabaseEventTriggerMaps.byId[
|
||||
destroyDatabaseEventTriggerInput.id
|
||||
];
|
||||
|
||||
if (!isDefined(existingFlatDatabaseEventTrigger)) {
|
||||
throw new DatabaseEventTriggerException(
|
||||
'Database event trigger to destroy not found',
|
||||
DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fromFlatDatabaseEventTriggerMaps = getSubFlatEntityMapsOrThrow({
|
||||
flatEntityIds: [existingFlatDatabaseEventTrigger.id],
|
||||
flatEntityMaps: existingFlatDatabaseEventTriggerMaps,
|
||||
});
|
||||
const toFlatDatabaseEventTriggerMaps =
|
||||
deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: fromFlatDatabaseEventTriggerMaps,
|
||||
entityToDeleteId: existingFlatDatabaseEventTrigger.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatDatabaseEventTriggerMaps: {
|
||||
from: fromFlatDatabaseEventTriggerMaps,
|
||||
to: toFlatDatabaseEventTriggerMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: true,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while destroying database event trigger',
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatDatabaseEventTrigger;
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant';
|
||||
import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import {
|
||||
DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES,
|
||||
DatabaseEventTrigger,
|
||||
} from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
|
||||
import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceFlatMapCache('flatDatabaseEventTriggerMaps')
|
||||
export class WorkspaceFlatDatabaseEventTriggerMapCacheService extends WorkspaceFlatMapCacheService<
|
||||
FlatEntityMaps<FlatDatabaseEventTrigger>
|
||||
> {
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
cacheStorageService: CacheStorageService,
|
||||
@InjectRepository(DatabaseEventTrigger)
|
||||
private readonly databaseEventTriggerRepository: Repository<DatabaseEventTrigger>,
|
||||
) {
|
||||
super(cacheStorageService);
|
||||
}
|
||||
|
||||
protected async computeFlatMap({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<FlatEntityMaps<FlatDatabaseEventTrigger>> {
|
||||
const databaseEventTriggers =
|
||||
await this.databaseEventTriggerRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const flatDatabaseEventTriggerMaps = databaseEventTriggers.reduce<
|
||||
FlatEntityMaps<FlatDatabaseEventTrigger>
|
||||
>((flatEntityMaps, databaseEventTrigger) => {
|
||||
const flatDatabaseEventTrigger = {
|
||||
...removePropertiesFromRecord(databaseEventTrigger, [
|
||||
...DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES,
|
||||
]),
|
||||
universalIdentifier: databaseEventTrigger.universalIdentifier ?? '',
|
||||
} satisfies FlatDatabaseEventTrigger;
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatEntityMaps.byId,
|
||||
[flatDatabaseEventTrigger.id]: flatDatabaseEventTrigger,
|
||||
},
|
||||
idByUniversalIdentifier: {
|
||||
...flatEntityMaps.idByUniversalIdentifier,
|
||||
[flatDatabaseEventTrigger.universalIdentifier]:
|
||||
flatDatabaseEventTrigger.id,
|
||||
},
|
||||
};
|
||||
}, EMPTY_FLAT_ENTITY_MAPS);
|
||||
|
||||
return flatDatabaseEventTriggerMaps;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant';
|
||||
|
||||
export type FlatDatabaseEventTriggerPropertiesToCompare =
|
||||
(typeof FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE)[number];
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type DatabaseEventTriggerEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
DatabaseEventTrigger,
|
||||
ServerlessFunctionEntity | Workspace
|
||||
>;
|
||||
|
||||
export type FlatDatabaseEventTrigger = Omit<
|
||||
DatabaseEventTrigger,
|
||||
DatabaseEventTriggerEntityRelationProperties
|
||||
> & {
|
||||
universalIdentifier: string;
|
||||
};
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import diff from 'microdiff';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { parseJson } from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant';
|
||||
import { type DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { type FlatDatabaseEventTriggerPropertiesToCompare } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { type UpdateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
type GetWorkspaceMigrationUpdateDatabaseEventTriggerActionArgs = FromTo<
|
||||
FlatDatabaseEventTrigger,
|
||||
'FlatDatabaseEventTrigger'
|
||||
>;
|
||||
|
||||
export const compareTwoFlatDatabaseEventTrigger = ({
|
||||
fromFlatDatabaseEventTrigger,
|
||||
toFlatDatabaseEventTrigger,
|
||||
}: GetWorkspaceMigrationUpdateDatabaseEventTriggerActionArgs) => {
|
||||
const transformMetadataForComparisonParameters = {
|
||||
shouldIgnoreProperty: (property: string) =>
|
||||
!FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE.includes(
|
||||
property as FlatDatabaseEventTriggerPropertiesToCompare,
|
||||
),
|
||||
propertiesToStringify: ['settings'] as const,
|
||||
};
|
||||
const fromCompare = transformMetadataForComparison(
|
||||
fromFlatDatabaseEventTrigger,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
const toCompare = transformMetadataForComparison(
|
||||
toFlatDatabaseEventTrigger,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
|
||||
const flatDatabaseEventTriggerDifferences = diff(fromCompare, toCompare);
|
||||
|
||||
return flatDatabaseEventTriggerDifferences.flatMap<
|
||||
UpdateDatabaseEventTriggerAction['updates'][number]
|
||||
>((difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { oldValue, path, value } = difference;
|
||||
const property = path[0] as FlatDatabaseEventTriggerPropertiesToCompare;
|
||||
|
||||
if (property === 'settings') {
|
||||
return {
|
||||
from: parseJson(oldValue) as DatabaseEventTriggerSettings,
|
||||
to: parseJson(value) as DatabaseEventTriggerSettings,
|
||||
property,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
from: oldValue,
|
||||
to: value,
|
||||
property,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occurs, we should only provide null never undefined and so on
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
ConflictError,
|
||||
NotFoundError,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import {
|
||||
DatabaseEventTriggerException,
|
||||
DatabaseEventTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception';
|
||||
|
||||
export const databaseEventTriggerGraphQLApiExceptionHandler = (
|
||||
error: Error,
|
||||
): void => {
|
||||
if (error instanceof DatabaseEventTriggerException) {
|
||||
switch (error.code) {
|
||||
case DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND:
|
||||
throw new NotFoundError('Database event trigger not found');
|
||||
case DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_ALREADY_EXIST:
|
||||
throw new ConflictError('Database event trigger already exists');
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
|
||||
import { type CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
|
||||
export const fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger = ({
|
||||
createDatabaseEventTriggerInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createDatabaseEventTriggerInput: CreateDatabaseEventTriggerInput;
|
||||
workspaceId: string;
|
||||
}): FlatDatabaseEventTrigger => {
|
||||
const now = new Date();
|
||||
|
||||
return {
|
||||
id: uuidV4(),
|
||||
universalIdentifier: uuidV4(),
|
||||
settings: createDatabaseEventTriggerInput.settings,
|
||||
serverlessFunctionId: createDatabaseEventTriggerInput.serverlessFunctionId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { type UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input';
|
||||
import {
|
||||
DatabaseEventTriggerException,
|
||||
DatabaseEventTriggerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
|
||||
export const fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow =
|
||||
({
|
||||
flatDatabaseEventTriggerMaps,
|
||||
updateDatabaseEventTriggerInput,
|
||||
}: {
|
||||
flatDatabaseEventTriggerMaps: FlatEntityMaps<FlatDatabaseEventTrigger>;
|
||||
updateDatabaseEventTriggerInput: UpdateDatabaseEventTriggerInput;
|
||||
}): FlatDatabaseEventTrigger => {
|
||||
const existingFlatDatabaseEventTrigger =
|
||||
flatDatabaseEventTriggerMaps.byId[updateDatabaseEventTriggerInput.id];
|
||||
|
||||
if (!existingFlatDatabaseEventTrigger) {
|
||||
throw new DatabaseEventTriggerException(
|
||||
'Database event trigger not found',
|
||||
DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatDatabaseEventTrigger,
|
||||
settings: updateDatabaseEventTriggerInput.settings,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
};
|
||||
+2
@@ -35,6 +35,8 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio
|
||||
},
|
||||
],
|
||||
serverlessFunction: [],
|
||||
databaseEventTrigger: [],
|
||||
cronTrigger: [],
|
||||
},
|
||||
status: 'fail',
|
||||
},
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { AgentModule } from 'src/engine/metadata-modules/agent/agent.module';
|
||||
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { RouteModule } from 'src/engine/metadata-modules/route/route.module';
|
||||
import { SearchFieldMetadataModule } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { RouteModule } from 'src/engine/metadata-modules/route/route.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -27,6 +29,8 @@ import { RouteModule } from 'src/engine/metadata-modules/route/route.module';
|
||||
RoleModule,
|
||||
PermissionsModule,
|
||||
RouteModule,
|
||||
CronTriggerModule,
|
||||
DatabaseEventTriggerModule,
|
||||
],
|
||||
providers: [],
|
||||
exports: [
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@ import {
|
||||
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
|
||||
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { Route } from 'src/engine/metadata-modules/route/route.entity';
|
||||
import { ServerlessFunctionEntityRelationProperties } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity';
|
||||
import { InputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/input-schema.type';
|
||||
|
||||
const DEFAULT_SERVERLESS_TIMEOUT_SECONDS = 300; // 5 minutes
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { type Route } from 'src/engine/metadata-modules/route/route.entity';
|
||||
import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { type CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type ServerlessFunctionEntityRelationProperties =
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, CronTrigger, DatabaseEventTrigger]),
|
||||
],
|
||||
providers: [
|
||||
CronTriggerCronJob,
|
||||
CronTriggerCronCommand,
|
||||
CallDatabaseEventTriggerJobsJob,
|
||||
],
|
||||
exports: [CronTriggerCronCommand],
|
||||
})
|
||||
export class TriggerModule {}
|
||||
+2
@@ -16,4 +16,6 @@ export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = {
|
||||
viewField: emptyCreatedDeletedUpdated,
|
||||
fieldMetadata: emptyCreatedDeletedUpdated,
|
||||
serverlessFunction: emptyCreatedDeletedUpdated,
|
||||
databaseEventTrigger: emptyCreatedDeletedUpdated,
|
||||
cronTrigger: emptyCreatedDeletedUpdated,
|
||||
} as const satisfies OrchestratorActionsReport;
|
||||
|
||||
+4
@@ -11,6 +11,8 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = (
|
||||
invalidViewField: 0,
|
||||
invalidIndex: 0,
|
||||
invalidServerlessFunction: 0,
|
||||
invalidDatabaseEventTrigger: 0,
|
||||
invalidCronTrigger: 0,
|
||||
totalErrors: 0,
|
||||
},
|
||||
errors: {
|
||||
@@ -19,6 +21,8 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = (
|
||||
view: [],
|
||||
viewField: [],
|
||||
serverlessFunction: [],
|
||||
databaseEventTrigger: [],
|
||||
cronTrigger: [],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+73
@@ -11,6 +11,8 @@ import {
|
||||
WorkspaceMigrationOrchestratorFailedResult,
|
||||
WorkspaceMigrationOrchestratorSuccessfulResult,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type';
|
||||
import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service';
|
||||
import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
@@ -29,6 +31,8 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
private readonly workspaceMigrationV2ViewActionsBuilderService: WorkspaceMigrationV2ViewActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ViewFieldActionsBuilderService: WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
private readonly workspaceMigrationV2ServerlessFunctionActionsBuilderService: WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
private readonly workspaceMigrationV2DatabaseEventTriggerActionsBuilderService: WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
private readonly workspaceMigrationV2CronTriggerActionsBuilderService: WorkspaceMigrationV2CronTriggerActionsBuilderService,
|
||||
) {}
|
||||
|
||||
private setupOptimisticCache({
|
||||
@@ -80,6 +84,8 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
viewField: [],
|
||||
index: [],
|
||||
serverlessFunction: [],
|
||||
databaseEventTrigger: [],
|
||||
cronTrigger: [],
|
||||
};
|
||||
|
||||
const optimisticAllFlatEntityMaps = this.setupOptimisticCache({
|
||||
@@ -92,6 +98,8 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
flatViewMaps,
|
||||
flatIndexMaps,
|
||||
flatServerlessFunctionMaps,
|
||||
flatDatabaseEventTriggerMaps,
|
||||
flatCronTriggerMaps,
|
||||
} = fromToAllFlatEntityMaps;
|
||||
|
||||
if (isDefined(flatObjectMetadataMaps)) {
|
||||
@@ -222,6 +230,59 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatDatabaseEventTriggerMaps)) {
|
||||
const {
|
||||
from: fromFlatDatabaseEventTriggerMaps,
|
||||
to: toFlatDatabaseEventTriggerMaps,
|
||||
} = flatDatabaseEventTriggerMaps;
|
||||
|
||||
const databaseEventTriggerResult =
|
||||
await this.workspaceMigrationV2DatabaseEventTriggerActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
from: fromFlatDatabaseEventTriggerMaps,
|
||||
to: toFlatDatabaseEventTriggerMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: {} as AllFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
optimisticAllFlatEntityMaps.flatDatabaseEventTriggerMaps =
|
||||
databaseEventTriggerResult.optimisticFlatEntityMaps;
|
||||
|
||||
if (databaseEventTriggerResult.status === 'fail') {
|
||||
orchestratorFailureReport.databaseEventTrigger.push(
|
||||
...databaseEventTriggerResult.errors,
|
||||
);
|
||||
} else {
|
||||
orchestratorActionsReport.databaseEventTrigger =
|
||||
databaseEventTriggerResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatCronTriggerMaps)) {
|
||||
const { from: fromFlatCronTriggerMaps, to: toFlatCronTriggerMaps } =
|
||||
flatCronTriggerMaps;
|
||||
|
||||
const cronTriggerResult =
|
||||
await this.workspaceMigrationV2CronTriggerActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
from: fromFlatCronTriggerMaps,
|
||||
to: toFlatCronTriggerMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: {} as AllFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
optimisticAllFlatEntityMaps.flatCronTriggerMaps =
|
||||
cronTriggerResult.optimisticFlatEntityMaps;
|
||||
|
||||
if (cronTriggerResult.status === 'fail') {
|
||||
orchestratorFailureReport.cronTrigger.push(...cronTriggerResult.errors);
|
||||
} else {
|
||||
orchestratorActionsReport.cronTrigger = cronTriggerResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
const allErrors = Object.values(orchestratorFailureReport);
|
||||
|
||||
if (allErrors.some((report) => report.length > 0)) {
|
||||
@@ -266,6 +327,18 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
...orchestratorActionsReport.serverlessFunction.created,
|
||||
...orchestratorActionsReport.serverlessFunction.updated,
|
||||
///
|
||||
|
||||
// Database event triggers
|
||||
...orchestratorActionsReport.databaseEventTrigger.deleted,
|
||||
...orchestratorActionsReport.databaseEventTrigger.created,
|
||||
...orchestratorActionsReport.databaseEventTrigger.updated,
|
||||
///
|
||||
|
||||
// Cron triggers
|
||||
...orchestratorActionsReport.cronTrigger.deleted,
|
||||
...orchestratorActionsReport.cronTrigger.created,
|
||||
...orchestratorActionsReport.cronTrigger.updated,
|
||||
///
|
||||
],
|
||||
workspaceId,
|
||||
},
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { compareTwoFlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/utils/compare-two-flat-cron-trigger.util';
|
||||
import {
|
||||
FlatEntityUpdateValidationArgs,
|
||||
FlatEntityValidationArgs,
|
||||
FlatEntityValidationReturnType,
|
||||
WorkspaceEntityMigrationBuilderV2Service,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
|
||||
import {
|
||||
UpdateCronTriggerAction,
|
||||
WorkspaceMigrationCronTriggerActionV2,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import {
|
||||
CronTriggerRelatedFlatEntityMaps,
|
||||
FlatCronTriggerValidatorService,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
|
||||
FlatCronTrigger,
|
||||
WorkspaceMigrationCronTriggerActionV2,
|
||||
CronTriggerRelatedFlatEntityMaps
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatCronTriggerValidatorService: FlatCronTriggerValidatorService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async validateFlatEntityCreation({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatCronTriggerToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatCronTrigger,
|
||||
CronTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationCronTriggerActionV2,
|
||||
FlatCronTrigger
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
await this.flatCronTriggerValidatorService.validateFlatCronTriggerCreation(
|
||||
{
|
||||
flatCronTriggerToValidate,
|
||||
optimisticFlatCronTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create_cron_trigger',
|
||||
cronTrigger: flatCronTriggerToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityDeletion({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatCronTriggerToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatCronTrigger,
|
||||
CronTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationCronTriggerActionV2,
|
||||
FlatCronTrigger
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatCronTriggerValidatorService.validateFlatCronTriggerDeletion({
|
||||
flatCronTriggerToValidate,
|
||||
optimisticFlatCronTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
});
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete_cron_trigger',
|
||||
cronTriggerId: flatCronTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityUpdate({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityUpdate: { from: fromFlatCronTrigger, to: toFlatCronTrigger },
|
||||
optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
FlatCronTrigger,
|
||||
CronTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
| FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationCronTriggerActionV2,
|
||||
FlatCronTrigger
|
||||
>
|
||||
| undefined
|
||||
> {
|
||||
const cronTriggerUpdatedProperties = compareTwoFlatCronTrigger({
|
||||
fromFlatCronTrigger,
|
||||
toFlatCronTrigger,
|
||||
});
|
||||
|
||||
if (cronTriggerUpdatedProperties.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const validationResult =
|
||||
this.flatCronTriggerValidatorService.validateFlatCronTriggerUpdate({
|
||||
flatCronTriggerToValidate: toFlatCronTrigger,
|
||||
optimisticFlatCronTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
});
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const updateCronTriggerAction: UpdateCronTriggerAction = {
|
||||
type: 'update_cron_trigger',
|
||||
cronTriggerId: toFlatCronTrigger.id,
|
||||
updates: cronTriggerUpdatedProperties,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateCronTriggerAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { compareTwoFlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/utils/compare-two-flat-database-event-trigger.util';
|
||||
import {
|
||||
FlatEntityUpdateValidationArgs,
|
||||
FlatEntityValidationArgs,
|
||||
FlatEntityValidationReturnType,
|
||||
WorkspaceEntityMigrationBuilderV2Service,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
|
||||
import {
|
||||
UpdateDatabaseEventTriggerAction,
|
||||
WorkspaceMigrationDatabaseEventTriggerActionV2,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import {
|
||||
DatabaseEventTriggerRelatedFlatEntityMaps,
|
||||
FlatDatabaseEventTriggerValidatorService,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
|
||||
FlatDatabaseEventTrigger,
|
||||
WorkspaceMigrationDatabaseEventTriggerActionV2,
|
||||
DatabaseEventTriggerRelatedFlatEntityMaps
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatDatabaseEventTriggerValidatorService: FlatDatabaseEventTriggerValidatorService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async validateFlatEntityCreation({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatDatabaseEventTriggerToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatDatabaseEventTrigger,
|
||||
DatabaseEventTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationDatabaseEventTriggerActionV2,
|
||||
FlatDatabaseEventTrigger
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
await this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerCreation(
|
||||
{
|
||||
flatDatabaseEventTriggerToValidate,
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create_database_event_trigger',
|
||||
databaseEventTrigger: flatDatabaseEventTriggerToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityDeletion({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityToValidate: flatDatabaseEventTriggerToValidate,
|
||||
optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
FlatDatabaseEventTrigger,
|
||||
DatabaseEventTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationDatabaseEventTriggerActionV2,
|
||||
FlatDatabaseEventTrigger
|
||||
>
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerDeletion(
|
||||
{
|
||||
flatDatabaseEventTriggerToValidate,
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete_database_event_trigger',
|
||||
databaseEventTriggerId: flatDatabaseEventTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async validateFlatEntityUpdate({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatEntityUpdate: {
|
||||
from: fromFlatDatabaseEventTrigger,
|
||||
to: toFlatDatabaseEventTrigger,
|
||||
},
|
||||
optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
FlatDatabaseEventTrigger,
|
||||
DatabaseEventTriggerRelatedFlatEntityMaps
|
||||
>): Promise<
|
||||
| FlatEntityValidationReturnType<
|
||||
WorkspaceMigrationDatabaseEventTriggerActionV2,
|
||||
FlatDatabaseEventTrigger
|
||||
>
|
||||
| undefined
|
||||
> {
|
||||
const databaseEventTriggerUpdatedProperties =
|
||||
compareTwoFlatDatabaseEventTrigger({
|
||||
fromFlatDatabaseEventTrigger,
|
||||
toFlatDatabaseEventTrigger,
|
||||
});
|
||||
|
||||
if (databaseEventTriggerUpdatedProperties.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const validationResult =
|
||||
this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerUpdate(
|
||||
{
|
||||
flatDatabaseEventTriggerToValidate: toFlatDatabaseEventTrigger,
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const updateDatabaseEventTriggerAction: UpdateDatabaseEventTriggerAction = {
|
||||
type: 'update_database_event_trigger',
|
||||
databaseEventTriggerId: toFlatDatabaseEventTrigger.id,
|
||||
updates: databaseEventTriggerUpdatedProperties,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateDatabaseEventTriggerAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -1,3 +1,5 @@
|
||||
import { type WorkspaceMigrationCronTriggerActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import { type WorkspaceMigrationDatabaseEventTriggerActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import { type WorkspaceMigrationFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2';
|
||||
import { type WorkspaceMigrationIndexActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2';
|
||||
import { type WorkspaceMigrationObjectActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2';
|
||||
@@ -11,7 +13,9 @@ export type WorkspaceMigrationActionV2 =
|
||||
| WorkspaceMigrationIndexActionV2
|
||||
| WorkspaceMigrationViewActionV2
|
||||
| WorkspaceMigrationViewFieldActionV2
|
||||
| WorkspaceMigrationServerlessFunctionActionV2;
|
||||
| WorkspaceMigrationServerlessFunctionActionV2
|
||||
| WorkspaceMigrationDatabaseEventTriggerActionV2
|
||||
| WorkspaceMigrationCronTriggerActionV2;
|
||||
export type WorkspaceMigrationActionTypeV2 = WorkspaceMigrationActionV2['type'];
|
||||
|
||||
export type ExtractAction<T extends WorkspaceMigrationActionTypeV2> = Extract<
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { type FlatCronTriggerPropertiesToCompare } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type';
|
||||
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type';
|
||||
|
||||
export type CreateCronTriggerAction = {
|
||||
type: 'create_cron_trigger';
|
||||
cronTrigger: FlatCronTrigger;
|
||||
};
|
||||
|
||||
export type UpdateCronTriggerAction = {
|
||||
type: 'update_cron_trigger';
|
||||
cronTriggerId: string;
|
||||
updates: Array<
|
||||
{
|
||||
[P in FlatCronTriggerPropertiesToCompare]: PropertyUpdate<
|
||||
FlatCronTrigger,
|
||||
P
|
||||
>;
|
||||
}[FlatCronTriggerPropertiesToCompare]
|
||||
>;
|
||||
};
|
||||
|
||||
export type DeleteCronTriggerAction = {
|
||||
type: 'delete_cron_trigger';
|
||||
cronTriggerId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationCronTriggerActionV2 =
|
||||
| CreateCronTriggerAction
|
||||
| UpdateCronTriggerAction
|
||||
| DeleteCronTriggerAction;
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { type FlatDatabaseEventTriggerPropertiesToCompare } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type';
|
||||
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type';
|
||||
|
||||
export type CreateDatabaseEventTriggerAction = {
|
||||
type: 'create_database_event_trigger';
|
||||
databaseEventTrigger: FlatDatabaseEventTrigger;
|
||||
};
|
||||
|
||||
export type UpdateDatabaseEventTriggerAction = {
|
||||
type: 'update_database_event_trigger';
|
||||
databaseEventTriggerId: string;
|
||||
updates: Array<
|
||||
{
|
||||
[P in FlatDatabaseEventTriggerPropertiesToCompare]: PropertyUpdate<
|
||||
FlatDatabaseEventTrigger,
|
||||
P
|
||||
>;
|
||||
}[FlatDatabaseEventTriggerPropertiesToCompare]
|
||||
>;
|
||||
};
|
||||
|
||||
export type DeleteDatabaseEventTriggerAction = {
|
||||
type: 'delete_database_event_trigger';
|
||||
databaseEventTriggerId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationDatabaseEventTriggerActionV2 =
|
||||
| CreateDatabaseEventTriggerAction
|
||||
| UpdateDatabaseEventTriggerAction
|
||||
| DeleteDatabaseEventTriggerAction;
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { CronTriggerExceptionCode } from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception';
|
||||
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
export type CronTriggerRelatedFlatEntityMaps = Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatCronTriggerMaps'
|
||||
>;
|
||||
|
||||
type CronTriggerValidationArgs = {
|
||||
flatCronTriggerToValidate: FlatCronTrigger;
|
||||
optimisticFlatCronTriggerMaps: FlatEntityMaps<FlatCronTrigger>;
|
||||
dependencyOptimisticFlatEntityMaps: CronTriggerRelatedFlatEntityMaps;
|
||||
};
|
||||
// TODO: validate settings integrity
|
||||
@Injectable()
|
||||
export class FlatCronTriggerValidatorService {
|
||||
constructor() {}
|
||||
|
||||
public validateFlatCronTriggerUpdate({
|
||||
flatCronTriggerToValidate: updatedFlatCronTrigger,
|
||||
optimisticFlatCronTriggerMaps,
|
||||
}: CronTriggerValidationArgs): FailedFlatEntityValidation<FlatCronTrigger> {
|
||||
const errors = [];
|
||||
|
||||
const existingFlatCronTrigger =
|
||||
optimisticFlatCronTriggerMaps.byId[updatedFlatCronTrigger.id];
|
||||
|
||||
if (!isDefined(existingFlatCronTrigger)) {
|
||||
errors.push({
|
||||
code: CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND,
|
||||
message: t`Cron trigger not found`,
|
||||
userFriendlyMessage: t`Cron trigger not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'update_cron_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: updatedFlatCronTrigger.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public validateFlatCronTriggerDeletion({
|
||||
flatCronTriggerToValidate: { id: cronTriggerIdToDelete },
|
||||
optimisticFlatCronTriggerMaps,
|
||||
}: CronTriggerValidationArgs): FailedFlatEntityValidation<FlatCronTrigger> {
|
||||
const errors = [];
|
||||
|
||||
const existingFlatCronTrigger =
|
||||
optimisticFlatCronTriggerMaps.byId[cronTriggerIdToDelete];
|
||||
|
||||
if (!isDefined(existingFlatCronTrigger)) {
|
||||
errors.push({
|
||||
code: CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND,
|
||||
message: t`Cron trigger not found`,
|
||||
userFriendlyMessage: t`Cron trigger not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'delete_cron_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: cronTriggerIdToDelete,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public async validateFlatCronTriggerCreation({
|
||||
flatCronTriggerToValidate,
|
||||
optimisticFlatCronTriggerMaps,
|
||||
}: CronTriggerValidationArgs): Promise<
|
||||
FailedFlatEntityValidation<FlatCronTrigger>
|
||||
> {
|
||||
const errors = [];
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
optimisticFlatCronTriggerMaps.byId[flatCronTriggerToValidate.id],
|
||||
)
|
||||
) {
|
||||
errors.push({
|
||||
code: CronTriggerExceptionCode.CRON_TRIGGER_ALREADY_EXIST,
|
||||
message: t`Cron trigger with same id already exists`,
|
||||
userFriendlyMessage: t`Cron trigger already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'create_cron_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatCronTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { DatabaseEventTriggerExceptionCode } from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception';
|
||||
import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
|
||||
|
||||
export type DatabaseEventTriggerRelatedFlatEntityMaps = Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatDatabaseEventTriggerMaps'
|
||||
>;
|
||||
|
||||
type DatabaseEventTriggerValidationArgs = {
|
||||
flatDatabaseEventTriggerToValidate: FlatDatabaseEventTrigger;
|
||||
optimisticFlatDatabaseEventTriggerMaps: FlatEntityMaps<FlatDatabaseEventTrigger>;
|
||||
dependencyOptimisticFlatEntityMaps: DatabaseEventTriggerRelatedFlatEntityMaps;
|
||||
};
|
||||
// TODO: validate settings integrity
|
||||
@Injectable()
|
||||
export class FlatDatabaseEventTriggerValidatorService {
|
||||
constructor() {}
|
||||
|
||||
public validateFlatDatabaseEventTriggerUpdate({
|
||||
flatDatabaseEventTriggerToValidate: updatedFlatDatabaseEventTrigger,
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: DatabaseEventTriggerValidationArgs): FailedFlatEntityValidation<FlatDatabaseEventTrigger> {
|
||||
const errors = [];
|
||||
|
||||
const existingFlatDatabaseEventTrigger =
|
||||
optimisticFlatDatabaseEventTriggerMaps.byId[
|
||||
updatedFlatDatabaseEventTrigger.id
|
||||
];
|
||||
|
||||
if (!isDefined(existingFlatDatabaseEventTrigger)) {
|
||||
errors.push({
|
||||
code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND,
|
||||
message: t`Database event trigger not found`,
|
||||
userFriendlyMessage: t`Database event trigger not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'update_database_event_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: updatedFlatDatabaseEventTrigger.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public validateFlatDatabaseEventTriggerDeletion({
|
||||
flatDatabaseEventTriggerToValidate: { id: databaseEventTriggerIdToDelete },
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: DatabaseEventTriggerValidationArgs): FailedFlatEntityValidation<FlatDatabaseEventTrigger> {
|
||||
const errors = [];
|
||||
|
||||
const existingFlatDatabaseEventTrigger =
|
||||
optimisticFlatDatabaseEventTriggerMaps.byId[
|
||||
databaseEventTriggerIdToDelete
|
||||
];
|
||||
|
||||
if (!isDefined(existingFlatDatabaseEventTrigger)) {
|
||||
errors.push({
|
||||
code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND,
|
||||
message: t`Database event trigger not found`,
|
||||
userFriendlyMessage: t`Database event trigger not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'delete_database_event_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: databaseEventTriggerIdToDelete,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public async validateFlatDatabaseEventTriggerCreation({
|
||||
flatDatabaseEventTriggerToValidate,
|
||||
optimisticFlatDatabaseEventTriggerMaps,
|
||||
}: DatabaseEventTriggerValidationArgs): Promise<
|
||||
FailedFlatEntityValidation<FlatDatabaseEventTrigger>
|
||||
> {
|
||||
const errors = [];
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
optimisticFlatDatabaseEventTriggerMaps.byId[
|
||||
flatDatabaseEventTriggerToValidate.id
|
||||
],
|
||||
)
|
||||
) {
|
||||
errors.push({
|
||||
code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_ALREADY_EXIST,
|
||||
message: t`Database event trigger with same id already exists`,
|
||||
userFriendlyMessage: t`Database event trigger already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'create_database_event_trigger',
|
||||
errors,
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatDatabaseEventTriggerToValidate.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
+10
@@ -4,6 +4,8 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-
|
||||
import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service';
|
||||
import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service';
|
||||
import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service';
|
||||
import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service';
|
||||
import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service';
|
||||
@@ -11,6 +13,8 @@ import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service';
|
||||
import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service';
|
||||
import { FlatCronTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service';
|
||||
import { FlatDatabaseEventTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service';
|
||||
import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service';
|
||||
import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service';
|
||||
import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service';
|
||||
@@ -29,9 +33,13 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
WorkspaceMigrationV2IndexActionsBuilderService,
|
||||
WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
WorkspaceMigrationV2CronTriggerActionsBuilderService,
|
||||
FlatViewValidatorService,
|
||||
FlatViewFieldValidatorService,
|
||||
FlatServerlessFunctionValidatorService,
|
||||
FlatDatabaseEventTriggerValidatorService,
|
||||
FlatCronTriggerValidatorService,
|
||||
],
|
||||
exports: [
|
||||
WorkspaceMigrationBuilderV2Service,
|
||||
@@ -39,6 +47,8 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2IndexActionsBuilderService,
|
||||
WorkspaceMigrationV2ViewFieldActionsBuilderService,
|
||||
WorkspaceMigrationV2ServerlessFunctionActionsBuilderService,
|
||||
WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService,
|
||||
WorkspaceMigrationV2CronTriggerActionsBuilderService,
|
||||
],
|
||||
})
|
||||
export class WorkspaceMigrationBuilderV2Module {}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { CreateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create_cron_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<CreateCronTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { cronTrigger } = action;
|
||||
|
||||
const cronTriggerRepository =
|
||||
queryRunner.manager.getRepository<CronTrigger>(CronTrigger);
|
||||
|
||||
await cronTriggerRepository.insert({
|
||||
...cronTrigger,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { DeleteCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_cron_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<DeleteCronTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { cronTriggerId } = action;
|
||||
|
||||
const cronTriggerRepository =
|
||||
queryRunner.manager.getRepository<CronTrigger>(CronTrigger);
|
||||
|
||||
await cronTriggerRepository.delete({
|
||||
id: cronTriggerId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { UpdateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update_cron_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UpdateCronTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner } = context;
|
||||
const { cronTriggerId } = action;
|
||||
|
||||
const cronTriggerRepository =
|
||||
queryRunner.manager.getRepository<CronTrigger>(CronTrigger);
|
||||
|
||||
await cronTriggerRepository.update(
|
||||
cronTriggerId,
|
||||
fromWorkspaceMigrationUpdateActionToPartialEntity(action),
|
||||
);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { CreateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class CreateDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create_database_event_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<CreateDatabaseEventTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { databaseEventTrigger } = action;
|
||||
|
||||
const databaseEventTriggerRepository =
|
||||
queryRunner.manager.getRepository<DatabaseEventTrigger>(
|
||||
DatabaseEventTrigger,
|
||||
);
|
||||
|
||||
await databaseEventTriggerRepository.insert({
|
||||
...databaseEventTrigger,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { DeleteDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_database_event_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<DeleteDatabaseEventTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { databaseEventTriggerId } = action;
|
||||
|
||||
const databaseEventTriggerRepository =
|
||||
queryRunner.manager.getRepository<DatabaseEventTrigger>(
|
||||
DatabaseEventTrigger,
|
||||
);
|
||||
|
||||
await databaseEventTriggerRepository.delete({
|
||||
id: databaseEventTriggerId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { UpdateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update_database_event_trigger',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UpdateDatabaseEventTriggerAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner } = context;
|
||||
const { databaseEventTriggerId } = action;
|
||||
|
||||
const databaseEventTriggerRepository =
|
||||
queryRunner.manager.getRepository<DatabaseEventTrigger>(
|
||||
DatabaseEventTrigger,
|
||||
);
|
||||
|
||||
await databaseEventTriggerRepository.update(
|
||||
databaseEventTriggerId,
|
||||
fromWorkspaceMigrationUpdateActionToPartialEntity(action),
|
||||
);
|
||||
}
|
||||
}
|
||||
+14
@@ -1,6 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.module';
|
||||
import { CreateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service';
|
||||
import { DeleteCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service';
|
||||
import { UpdateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service';
|
||||
import { CreateDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/create-database-event-trigger-action-handler.service';
|
||||
import { DeleteDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/delete-database-event-trigger-action-handler.service';
|
||||
import { UpdateDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/update-database-event-trigger-action-handler.service';
|
||||
import { CreateFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/create-field-action-handler.service';
|
||||
import { DeleteFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/delete-field-action-handler.service';
|
||||
import { UpdateFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service';
|
||||
@@ -44,6 +50,14 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor
|
||||
CreateServerlessFunctionActionHandlerService,
|
||||
DeleteServerlessFunctionActionHandlerService,
|
||||
UpdateServerlessFunctionActionHandlerService,
|
||||
|
||||
CreateDatabaseEventTriggerActionHandlerService,
|
||||
DeleteDatabaseEventTriggerActionHandlerService,
|
||||
UpdateDatabaseEventTriggerActionHandlerService,
|
||||
|
||||
CreateCronTriggerActionHandlerService,
|
||||
DeleteCronTriggerActionHandlerService,
|
||||
UpdateCronTriggerActionHandlerService,
|
||||
],
|
||||
})
|
||||
export class WorkspaceSchemaMigrationRunnerActionHandlersModule {}
|
||||
|
||||
Reference in New Issue
Block a user