From 188d66909d5ab9d542c27477572256533e3e09f1 Mon Sep 17 00:00:00 2001 From: Weiko Date: Thu, 25 Sep 2025 14:05:01 +0200 Subject: [PATCH] Add ServerlessFunction to migration v2 (#14698) --- ...UniversalIdentifierToServerlessFunction.ts | 31 ++ ...ll-flat-entity-maps-properties.constant.ts | 1 + .../empty-all-flat-entity-maps.constant.ts | 1 + ...t-entities-by-metadata-engine-name.type.ts | 2 + .../serverless/drivers/lambda.driver.ts | 2 +- .../serverless/drivers/local.driver.ts | 6 +- .../utils/serverless-get-folder.utils.ts | 3 +- ...n-field-input-transpilations-error.util.ts | 1 + ...s-function-editable-properties.constant.ts | 7 + ...function-properties-to-compare.constant.ts | 6 + .../serverless-function.entity.ts | 39 +- .../serverless-function.module.ts | 10 +- .../serverless-function.service.ts | 2 +- .../serverless-function-v2.service.ts | 369 ++++++++++++++++++ ...t-serverless-function-map-cache.service.ts | 71 ++++ ...ess-function-properties-to-compare.type.ts | 4 + .../types/flat-serverless-function.type.ts | 19 + ...mpare-two-flat-serverless-function.util.ts | 59 +++ ...-input-to-flat-serverless-function.util.ts | 36 ++ ...erless-function-to-update-or-throw.util.ts | 51 +++ ...ty-orchestrator-actions-report.constant.ts | 1 + ...ption-to-validation-response-error.util.ts | 2 + ...ce-migration-build-orchestrator.service.ts | 41 +- ...ration-v2-index-actions-builder.service.ts | 24 +- ...erless-function-actions-builder.service.ts | 162 ++++++++ ...n-v2-view-field-actions-builder.service.ts | 18 +- ...gration-v2-view-actions-builder.service.ts | 14 +- .../workspace-migration-action-common-v2.ts | 4 +- ...tion-serverless-function-action-v2.type.ts | 39 ++ ...et-workspace-migration-v2-index-actions.ts | 19 - .../get-workspace-migration-v2-view-action.ts | 19 - ...orkspace-migration-v2-view-field-action.ts | 19 - ...t-serverless-function-validator.service.ts | 110 ++++++ .../workspace-migration-builder-v2.module.ts | 7 +- ...verless-function-action-handler.service.ts | 62 +++ ...verless-function-action-handler.service.ts | 62 +++ ...verless-function-action-handler.service.ts | 75 ++++ ...migration-runner-action-handlers.module.ts | 7 + ...-to-partial-field-or-object-entity.util.ts | 11 +- .../jobs/workflow-statuses-update.job.ts | 11 + ...ate-view-field-v2.integration-spec.ts.snap | 4 + ...-metadata-enum-v2.integration-spec.ts.snap | 140 +++++++ ...field-metadata-v2.integration-spec.ts.snap | 136 +++++++ ...morph-relation-v2.integration-spec.ts.snap | 34 ++ ...bject-metadata-v2.integration-spec.ts.snap | 42 ++ 45 files changed, 1671 insertions(+), 112 deletions(-) create mode 100644 packages/twenty-server/src/database/typeorm/core/migrations/common/1758793689363-addUniversalIdentifierToServerlessFunction.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/compare-two-flat-serverless-function.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-create-serverless-function-input-to-flat-serverless-function.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-update-serverless-function-input-to-flat-serverless-function-to-update-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-action.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-field-action.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service.ts diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/common/1758793689363-addUniversalIdentifierToServerlessFunction.ts b/packages/twenty-server/src/database/typeorm/core/migrations/common/1758793689363-addUniversalIdentifierToServerlessFunction.ts new file mode 100644 index 0000000000..bae2d4d214 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/common/1758793689363-addUniversalIdentifierToServerlessFunction.ts @@ -0,0 +1,31 @@ +import { type MigrationInterface, type QueryRunner } from 'typeorm'; + +export class AddUniversalIdentifierToServerlessFunction1758793689363 + implements MigrationInterface +{ + name = 'AddUniversalIdentifierToServerlessFunction1758793689363'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunction" ADD "universalIdentifier" uuid`, + ); + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunction" ADD "applicationId" uuid`, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_5b43e65e322d516c9307bed97a" ON "core"."serverlessFunction" ("workspaceId", "universalIdentifier") `, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DROP INDEX "core"."IDX_5b43e65e322d516c9307bed97a"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunction" DROP COLUMN "applicationId"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunction" DROP COLUMN "universalIdentifier"`, + ); + } +} diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts index 1da000e96e..61f50bf24e 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts @@ -5,4 +5,5 @@ export const ALL_FLAT_ENTITY_MAPS_PROPERTIES = [ 'flatViewFieldMaps', 'flatViewMaps', 'flatIndexMaps', + 'flatServerlessFunctionMaps', ] as const satisfies (keyof AllFlatEntityMaps)[]; diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts index ff2980f589..933206acbc 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts @@ -9,4 +9,5 @@ export const EMPTY_ALL_FLAT_ENTITY_MAPS = { flatIndexMaps: EMPTY_FLAT_ENTITY_MAPS, flatViewFieldMaps: EMPTY_FLAT_ENTITY_MAPS, flatViewMaps: EMPTY_FLAT_ENTITY_MAPS, + flatServerlessFunctionMaps: EMPTY_FLAT_ENTITY_MAPS, } as const satisfies AllFlatEntityMaps; diff --git a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts index 0cf3957f7c..a7e327f38a 100644 --- a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts +++ b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts @@ -2,6 +2,7 @@ import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.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'; export type AllFlatEntitiesByMetadataEngineName = { // flatFieldMetadata: FlatFieldMetadata; @@ -9,4 +10,5 @@ export type AllFlatEntitiesByMetadataEngineName = { view: FlatView; viewField: FlatViewField; index: FlatIndexMetadata; + serverlessFunction: FlatServerlessFunction; }; diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts index 973f91edfd..36f540d898 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts @@ -234,7 +234,7 @@ export class LambdaDriver implements ServerlessDriver { } const layerArn = await this.createLayerIfNotExists( - serverlessFunction.layerVersion, + serverlessFunction.layerVersion ?? 0, ); const lambdaBuildDirectoryManager = new LambdaBuildDirectoryManager(); diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts index 49507efa18..2710588d20 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts @@ -49,7 +49,7 @@ export class LocalDriver implements ServerlessDriver { async delete() {} private async build(serverlessFunction: ServerlessFunctionEntity) { - await this.createLayerIfNotExists(serverlessFunction.layerVersion); + await this.createLayerIfNotExists(serverlessFunction.layerVersion ?? 0); } private async executeWithTimeout( @@ -113,6 +113,10 @@ export class LocalDriver implements ServerlessDriver { await fs.writeFile(compiledCodeFilePath, compiledCode, 'utf8'); try { + if (!serverlessFunction.layerVersion) { + throw new Error('Layer version is not set'); + } + await fs.symlink( join( this.getInMemoryLayerFolderPath(serverlessFunction.layerVersion), diff --git a/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts b/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts index dc94d21179..3915a96295 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts @@ -9,12 +9,13 @@ import { ServerlessFunctionException, ServerlessFunctionExceptionCode, } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; export const getServerlessFolder = ({ serverlessFunction, version, }: { - serverlessFunction: ServerlessFunctionEntity; + serverlessFunction: ServerlessFunctionEntity | FlatServerlessFunction; version?: 'draft' | 'latest' | (string & NonNullable); }) => { if (version === 'latest' && !isDefined(serverlessFunction.latestVersion)) { diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts index 5ad7083209..0a2fd8cec8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts @@ -34,6 +34,7 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio flatEntityMinimalInformation: {}, }, ], + serverlessFunction: [], }, status: 'fail', }, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant.ts new file mode 100644 index 0000000000..21110f6bd1 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant.ts @@ -0,0 +1,7 @@ +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; + +export const FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES = [ + 'name', + 'description', + 'timeoutSeconds', +] as const satisfies (keyof FlatServerlessFunction)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant.ts new file mode 100644 index 0000000000..7304492653 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant.ts @@ -0,0 +1,6 @@ +import { FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; + +export const FLAT_SERVERLESS_FUNCTION_PROPERTIES_TO_COMPARE = [ + ...FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES, +] as const satisfies (keyof FlatServerlessFunction)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts index 76f1b6fc3c..472d4b83c7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts @@ -5,15 +5,18 @@ import { DeleteDateColumn, Entity, Index, + OneToMany, PrimaryGeneratedColumn, UpdateDateColumn, - OneToMany, } from 'typeorm'; -import { InputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/input-schema.type'; +import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface'; + +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 { Route } from 'src/engine/metadata-modules/route/route.entity'; +import { InputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/input-schema.type'; const DEFAULT_SERVERLESS_TIMEOUT_SECONDS = 300; // 5 minutes @@ -22,26 +25,35 @@ export enum ServerlessFunctionRuntime { NODE22 = 'nodejs22.x', } +export const SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES = [ + 'cronTriggers', + 'databaseEventTriggers', + 'routes', +] as const satisfies readonly ServerlessFunctionEntityRelationProperties[]; + @Entity('serverlessFunction') @Index('IDX_SERVERLESS_FUNCTION_ID_DELETED_AT', ['id', 'deletedAt']) -export class ServerlessFunctionEntity { +export class ServerlessFunctionEntity + extends SyncableEntity + implements Required +{ @PrimaryGeneratedColumn('uuid') id: string; @Column({ nullable: false }) name: string; - @Column({ nullable: true }) - description: string; + @Column({ nullable: true, type: 'varchar' }) + description: string | null; - @Column({ nullable: true }) - latestVersion: string; + @Column({ nullable: true, type: 'varchar' }) + latestVersion: string | null; @Column({ nullable: false, type: 'jsonb', default: [] }) publishedVersions: string[]; @Column({ nullable: true, type: 'jsonb' }) - latestVersionInputSchema: InputSchema; + latestVersionInputSchema: InputSchema | null; @Column({ nullable: false, default: ServerlessFunctionRuntime.NODE22 }) runtime: ServerlessFunctionRuntime; @@ -50,12 +62,15 @@ export class ServerlessFunctionEntity { @Check(`"timeoutSeconds" >= 1 AND "timeoutSeconds" <= 900`) timeoutSeconds: number; - @Column({ nullable: true }) - layerVersion: number; + @Column({ nullable: true, type: 'integer' }) + layerVersion: number | null; @Column({ nullable: false, type: 'uuid' }) workspaceId: string; + @Column({ nullable: true, type: 'uuid' }) + applicationId: string | null; + @OneToMany( () => CronTrigger, (cronTrigger) => cronTrigger.serverlessFunction, @@ -86,5 +101,5 @@ export class ServerlessFunctionEntity { updatedAt: Date; @DeleteDateColumn({ type: 'timestamptz' }) - deletedAt?: Date; + deletedAt: Date | null; } diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts index 11b25e1a68..e376ec4798 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts @@ -4,15 +4,19 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { AuditModule } from 'src/engine/core-modules/audit/audit.module'; +import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.module'; +import { ServerlessFunctionTriggerJob } from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; import { ServerlessFunctionResolver } from 'src/engine/metadata-modules/serverless-function/serverless-function.resolver'; import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service'; -import { ServerlessFunctionTriggerJob } from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job'; +import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service'; +import { WorkspaceFlatServerlessFunctionMapCacheService } from 'src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service'; +import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module'; @Module({ imports: [ @@ -23,11 +27,15 @@ import { ServerlessFunctionTriggerJob } from 'src/engine/metadata-modules/server ThrottlerModule, AuditModule, FeatureFlagModule, + WorkspaceManyOrAllFlatEntityMapsCacheModule, + WorkspaceMigrationV2Module, ], providers: [ ServerlessFunctionService, + ServerlessFunctionV2Service, ServerlessFunctionTriggerJob, ServerlessFunctionResolver, + WorkspaceFlatServerlessFunctionMapCacheService, ], exports: [ServerlessFunctionService], }) diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts index 266dd57d84..a8cea23baa 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts @@ -420,7 +420,7 @@ export class ServerlessFunctionService { const newServerlessFunction = await this.createOneServerlessFunction( { name: serverlessFunctionToDuplicate.name, - description: serverlessFunctionToDuplicate.description, + description: serverlessFunctionToDuplicate.description ?? undefined, timeoutSeconds: serverlessFunctionToDuplicate.timeoutSeconds, }, workspaceId, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service.ts new file mode 100644 index 0000000000..f10d3faeba --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service.ts @@ -0,0 +1,369 @@ +import { Injectable } from '@nestjs/common'; + +import { basename, dirname, join } from 'path'; + +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 { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { getBaseTypescriptProjectFiles } from 'src/engine/core-modules/serverless/drivers/utils/get-base-typescript-project-files'; +import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service'; +import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; +import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input'; +import { ServerlessFunctionIdInput } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function-id.input'; +import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; +import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { + ServerlessFunctionException, + ServerlessFunctionExceptionCode, +} from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; +import { fromCreateServerlessFunctionInputToFlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/utils/from-create-serverless-function-input-to-flat-serverless-function.util'; +import { fromUpdateServerlessFunctionInputToFlatServerlessFunctionToUpdateOrThrow } from 'src/engine/metadata-modules/serverless-function/utils/from-update-serverless-function-input-to-flat-serverless-function-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 ServerlessFunctionV2Service { + constructor( + private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, + private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, + private readonly fileStorageService: FileStorageService, + private readonly serverlessService: ServerlessService, + ) {} + + async createOne( + serverlessFunctionInput: CreateServerlessFunctionInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const existingFlatServerlessFunctionMaps = + flatEntityMaps.flatServerlessFunctionMaps; + + const flatServerlessFunctionToCreate = + fromCreateServerlessFunctionInputToFlatServerlessFunction({ + createServerlessFunctionInput: serverlessFunctionInput, + workspaceId, + }); + + const toFlatServerlessFunctionMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatServerlessFunctionToCreate, + flatEntityMaps: existingFlatServerlessFunctionMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatServerlessFunctionMaps: { + from: existingFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while creating serverless function', + ); + } + + const updatedFlatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const createdServerlessFunction = + updatedFlatEntityMaps.flatServerlessFunctionMaps.byId[ + flatServerlessFunctionToCreate.id + ]; + + if (!isDefined(createdServerlessFunction)) { + throw new ServerlessFunctionException( + 'Created serverless function not found in recomputed cache', + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + + const draftFileFolder = getServerlessFolder({ + serverlessFunction: createdServerlessFunction, + version: 'draft', + }); + + for (const file of await getBaseTypescriptProjectFiles) { + await this.fileStorageService.write({ + file: file.content, + name: file.name, + mimeType: undefined, + folder: join(draftFileFolder, file.path), + }); + } + + return createdServerlessFunction; + } + + async updateOne( + serverlessFunctionInput: UpdateServerlessFunctionInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const existingFlatServerlessFunctionMaps = + flatEntityMaps.flatServerlessFunctionMaps; + + const optimisticallyUpdatedFlatServerlessFunction = + fromUpdateServerlessFunctionInputToFlatServerlessFunctionToUpdateOrThrow({ + flatServerlessFunctionMaps: existingFlatServerlessFunctionMaps, + updateServerlessFunctionInput: serverlessFunctionInput, + }); + + const fromFlatServerlessFunctionMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [optimisticallyUpdatedFlatServerlessFunction.id], + flatEntityMaps: existingFlatServerlessFunctionMaps, + }); + const toFlatServerlessFunctionMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatServerlessFunction, + flatEntityMaps: fromFlatServerlessFunctionMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatServerlessFunctionMaps: { + from: existingFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while updating serverless function', + ); + } + + const updatedFlatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const updatedFlatServerlessFunction = + updatedFlatEntityMaps.flatServerlessFunctionMaps.byId[ + optimisticallyUpdatedFlatServerlessFunction.id + ]; + + if (!isDefined(updatedFlatServerlessFunction)) { + throw new ServerlessFunctionException( + 'Updated serverless function not found in recomputed cache', + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + + const fileFolder = getServerlessFolder({ + serverlessFunction: updatedFlatServerlessFunction, + version: 'draft', + }); + + for (const key of Object.keys(serverlessFunctionInput.code)) { + await this.fileStorageService.write({ + // @ts-expect-error legacy noImplicitAny + file: serverlessFunctionInput.code[key], + name: basename(key), + mimeType: undefined, + folder: join(fileFolder, dirname(key)), + }); + } + + return updatedFlatServerlessFunction; + } + + async deleteOne({ + deleteServerlessFunctionInput, + workspaceId, + }: { + deleteServerlessFunctionInput: ServerlessFunctionIdInput; + workspaceId: string; + }): Promise { + const { flatServerlessFunctionMaps: existingFlatServerlessFunctionMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const existingFlatServerlessFunction = + existingFlatServerlessFunctionMaps.byId[deleteServerlessFunctionInput.id]; + + if (!isDefined(existingFlatServerlessFunction)) { + throw new ServerlessFunctionException( + 'Serverless function to delete not found', + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + + const optimisticallyUpdatedFlatServerlessFunctionWithDeletedAt = { + ...existingFlatServerlessFunction, + deletedAt: new Date(), + }; + + const toFlatServerlessFunctionMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatServerlessFunctionWithDeletedAt, + flatEntityMaps: existingFlatServerlessFunctionMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatServerlessFunctionMaps: { + from: existingFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while deleting serverless function', + ); + } + + const { + flatServerlessFunctionMaps: recomputedExistingFlatServerlessFunctionMaps, + } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + this.serverlessService.delete( + existingFlatServerlessFunction as ServerlessFunctionEntity, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: optimisticallyUpdatedFlatServerlessFunctionWithDeletedAt.id, + flatEntityMaps: recomputedExistingFlatServerlessFunctionMaps, + }); + } + + async destroyOne({ + destroyServerlessFunctionInput, + workspaceId, + }: { + destroyServerlessFunctionInput: ServerlessFunctionIdInput; + workspaceId: string; + }): Promise { + const { flatServerlessFunctionMaps: existingFlatServerlessFunctionMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatServerlessFunctionMaps'], + }, + ); + + const existingFlatServerlessFunction = + existingFlatServerlessFunctionMaps.byId[ + destroyServerlessFunctionInput.id + ]; + + if (!isDefined(existingFlatServerlessFunction)) { + throw new ServerlessFunctionException( + 'Serverless function to destroy not found', + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + + const fromFlatServerlessFunctionMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [existingFlatServerlessFunction.id], + flatEntityMaps: existingFlatServerlessFunctionMaps, + }); + const toFlatServerlessFunctionMaps = + deleteFlatEntityFromFlatEntityMapsOrThrow({ + flatEntityMaps: fromFlatServerlessFunctionMaps, + entityToDeleteId: existingFlatServerlessFunction.id, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatServerlessFunctionMaps: { + from: fromFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: true, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while destroying serverless function', + ); + } + + this.fileStorageService.delete({ + folderPath: getServerlessFolder({ + serverlessFunction: existingFlatServerlessFunction, + }), + }); + + return existingFlatServerlessFunction; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts new file mode 100644 index 0000000000..b6dc5fbd0b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/services/workspace-flat-serverless-function-map-cache.service.ts @@ -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 { + SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES, + ServerlessFunctionEntity, +} from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.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('flatServerlessFunctionMaps') +export class WorkspaceFlatServerlessFunctionMapCacheService extends WorkspaceFlatMapCacheService< + FlatEntityMaps +> { + constructor( + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + cacheStorageService: CacheStorageService, + @InjectRepository(ServerlessFunctionEntity) + private readonly serverlessFunctionRepository: Repository, + ) { + super(cacheStorageService); + } + + protected async computeFlatMap({ + workspaceId, + }: { + workspaceId: string; + }): Promise> { + const serverlessFunctions = await this.serverlessFunctionRepository.find({ + where: { + workspaceId, + }, + withDeleted: true, + }); + + const flatServerlessFunctionMaps = serverlessFunctions.reduce< + FlatEntityMaps + >((flatEntityMaps, serverlessFunction) => { + const flatServerlessFunction = { + ...removePropertiesFromRecord(serverlessFunction, [ + ...SERVERLESS_FUNCTION_ENTITY_RELATION_PROPERTIES, + ]), + universalIdentifier: serverlessFunction.universalIdentifier ?? '', + } satisfies FlatServerlessFunction; + + return { + byId: { + ...flatEntityMaps.byId, + [flatServerlessFunction.id]: flatServerlessFunction, + }, + idByUniversalIdentifier: { + ...flatEntityMaps.idByUniversalIdentifier, + [flatServerlessFunction.universalIdentifier]: + flatServerlessFunction.id, + }, + }; + }, EMPTY_FLAT_ENTITY_MAPS); + + return flatServerlessFunctionMaps; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type.ts new file mode 100644 index 0000000000..b13e090692 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type.ts @@ -0,0 +1,4 @@ +import { type FLAT_SERVERLESS_FUNCTION_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant'; + +export type FlatServerlessFunctionPropertiesToCompare = + (typeof FLAT_SERVERLESS_FUNCTION_PROPERTIES_TO_COMPARE)[number]; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts new file mode 100644 index 0000000000..43668d3b7a --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts @@ -0,0 +1,19 @@ +import { type Workspace } from 'src/engine/core-modules/workspace/workspace.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 = + ExtractRecordTypeOrmRelationProperties< + ServerlessFunctionEntity, + CronTrigger | DatabaseEventTrigger | Route | Workspace + >; + +export type FlatServerlessFunction = Omit< + ServerlessFunctionEntity, + ServerlessFunctionEntityRelationProperties +> & { + universalIdentifier: string; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/compare-two-flat-serverless-function.util.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/compare-two-flat-serverless-function.util.ts new file mode 100644 index 0000000000..08a63db136 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/compare-two-flat-serverless-function.util.ts @@ -0,0 +1,59 @@ +import diff from 'microdiff'; +import { type FromTo } from 'twenty-shared/types'; + +import { FLAT_SERVERLESS_FUNCTION_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-properties-to-compare.constant'; +import { type FlatServerlessFunctionPropertiesToCompare } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; +import { type UpdateServerlessFunctionAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type'; +import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; + +type GetWorkspaceMigrationUpdateServerlessFunctionActionArgs = FromTo< + FlatServerlessFunction, + 'FlatServerlessFunction' +>; + +export const compareTwoFlatServerlessFunction = ({ + fromFlatServerlessFunction, + toFlatServerlessFunction, +}: GetWorkspaceMigrationUpdateServerlessFunctionActionArgs) => { + const transformMetadataForComparisonParameters = { + shouldIgnoreProperty: (property: string) => + !FLAT_SERVERLESS_FUNCTION_PROPERTIES_TO_COMPARE.includes( + property as FlatServerlessFunctionPropertiesToCompare, + ), + propertiesToStringify: [], + }; + const fromCompare = transformMetadataForComparison( + fromFlatServerlessFunction, + transformMetadataForComparisonParameters, + ); + const toCompare = transformMetadataForComparison( + toFlatServerlessFunction, + transformMetadataForComparisonParameters, + ); + + const flatServerlessFunctionDifferences = diff(fromCompare, toCompare); + + return flatServerlessFunctionDifferences.flatMap< + UpdateServerlessFunctionAction['updates'][number] + >((difference) => { + switch (difference.type) { + case 'CHANGE': { + const { oldValue, path, value } = difference; + const property = path[0] as FlatServerlessFunctionPropertiesToCompare; + + 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 []; + } + } + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-create-serverless-function-input-to-flat-serverless-function.util.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-create-serverless-function-input-to-flat-serverless-function.util.ts new file mode 100644 index 0000000000..112e04303b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-create-serverless-function-input-to-flat-serverless-function.util.ts @@ -0,0 +1,36 @@ +import { v4 } from 'uuid'; + +import { LAST_LAYER_VERSION } from 'src/engine/core-modules/serverless/drivers/layers/last-layer-version'; +import { type CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input'; +import { ServerlessFunctionRuntime } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; + +export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({ + createServerlessFunctionInput, + workspaceId, +}: { + createServerlessFunctionInput: CreateServerlessFunctionInput; + workspaceId: string; +}): FlatServerlessFunction => { + const id = v4(); + const universalIdentifier = v4(); + const currentDate = new Date(); + + return { + id, + name: createServerlessFunctionInput.name, + description: createServerlessFunctionInput.description ?? null, + universalIdentifier, + createdAt: currentDate, + updatedAt: currentDate, + deletedAt: null, + latestVersion: null, + publishedVersions: [], + applicationId: null, + latestVersionInputSchema: null, + runtime: ServerlessFunctionRuntime.NODE22, + timeoutSeconds: createServerlessFunctionInput.timeoutSeconds ?? 300, + layerVersion: LAST_LAYER_VERSION, + workspaceId, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-update-serverless-function-input-to-flat-serverless-function-to-update-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-update-serverless-function-input-to-flat-serverless-function-to-update-or-throw.util.ts new file mode 100644 index 0000000000..cbd8438a90 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/utils/from-update-serverless-function-input-to-flat-serverless-function-to-update-or-throw.util.ts @@ -0,0 +1,51 @@ +import { t } from '@lingui/core/macro'; +import { + extractAndSanitizeObjectStringFields, + isDefined, + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, +} from 'twenty-shared/utils'; + +import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant'; +import { type UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; +import { + ServerlessFunctionException, + ServerlessFunctionExceptionCode, +} from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; +import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util'; + +export const fromUpdateServerlessFunctionInputToFlatServerlessFunctionToUpdateOrThrow = + ({ + updateServerlessFunctionInput: rawUpdateServerlessFunctionInput, + flatServerlessFunctionMaps, + }: { + updateServerlessFunctionInput: UpdateServerlessFunctionInput; + flatServerlessFunctionMaps: FlatEntityMaps; + }): FlatServerlessFunction => { + const { id: serverlessFunctionToUpdateId } = + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( + rawUpdateServerlessFunctionInput, + ['id'], + ); + + const existingFlatServerlessFunctionToUpdate = + flatServerlessFunctionMaps.byId[serverlessFunctionToUpdateId]; + + if (!isDefined(existingFlatServerlessFunctionToUpdate)) { + throw new ServerlessFunctionException( + t`Serverless function to update not found`, + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields( + rawUpdateServerlessFunctionInput, + FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES, + ); + + return mergeUpdateInExistingRecord({ + existing: existingFlatServerlessFunctionToUpdate, + properties: FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES, + update: updatedEditableFieldProperties, + }); + }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts index 7522c194f8..11cfc3456d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts @@ -15,4 +15,5 @@ export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = { view: emptyCreatedDeletedUpdated, viewField: emptyCreatedDeletedUpdated, fieldMetadata: emptyCreatedDeletedUpdated, + serverlessFunction: emptyCreatedDeletedUpdated, } as const satisfies OrchestratorActionsReport; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts index 285bca5ae9..881e66dab0 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts @@ -10,6 +10,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( invalidView: 0, invalidViewField: 0, invalidIndex: 0, + invalidServerlessFunction: 0, totalErrors: 0, }, errors: { @@ -17,6 +18,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( objectMetadata: [], view: [], viewField: [], + serverlessFunction: [], }, }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts index 451dfd204d..c9e670cc06 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts @@ -12,6 +12,7 @@ import { WorkspaceMigrationOrchestratorSuccessfulResult, } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; 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'; 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'; @@ -27,6 +28,7 @@ export class WorkspaceMigrationBuildOrchestratorService { private readonly workspaceMigrationV2IndexActionsBuilderService: WorkspaceMigrationV2IndexActionsBuilderService, private readonly workspaceMigrationV2ViewActionsBuilderService: WorkspaceMigrationV2ViewActionsBuilderService, private readonly workspaceMigrationV2ViewFieldActionsBuilderService: WorkspaceMigrationV2ViewFieldActionsBuilderService, + private readonly workspaceMigrationV2ServerlessFunctionActionsBuilderService: WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, ) {} private setupOptimisticCache({ @@ -77,6 +79,7 @@ export class WorkspaceMigrationBuildOrchestratorService { view: [], viewField: [], index: [], + serverlessFunction: [], }; const optimisticAllFlatEntityMaps = this.setupOptimisticCache({ @@ -88,6 +91,7 @@ export class WorkspaceMigrationBuildOrchestratorService { flatViewFieldMaps, flatViewMaps, flatIndexMaps, + flatServerlessFunctionMaps, } = fromToAllFlatEntityMaps; if (isDefined(flatObjectMetadataMaps)) { @@ -189,6 +193,35 @@ export class WorkspaceMigrationBuildOrchestratorService { } } + if (isDefined(flatServerlessFunctionMaps)) { + const { + from: fromFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + } = flatServerlessFunctionMaps; + + const serverlessFunctionResult = + await this.workspaceMigrationV2ServerlessFunctionActionsBuilderService.validateAndBuild( + { + from: fromFlatServerlessFunctionMaps, + to: toFlatServerlessFunctionMaps, + buildOptions, + dependencyOptimisticFlatEntityMaps: {} as AllFlatEntityMaps, + }, + ); + + optimisticAllFlatEntityMaps.flatServerlessFunctionMaps = + serverlessFunctionResult.optimisticFlatEntityMaps; + + if (serverlessFunctionResult.status === 'fail') { + orchestratorFailureReport.serverlessFunction.push( + ...serverlessFunctionResult.errors, + ); + } else { + orchestratorActionsReport.serverlessFunction = + serverlessFunctionResult.actions; + } + } + const allErrors = Object.values(orchestratorFailureReport); if (allErrors.some((report) => report.length > 0)) { @@ -207,7 +240,7 @@ export class WorkspaceMigrationBuildOrchestratorService { workspaceMigration: { relatedFlatEntityMapsKeys, actions: [ - // Object and fields + // Object and fields and indexes ...orchestratorActionsReport.index.deleted, ...orchestratorActionsReport.fieldMetadata.deleted, ...orchestratorActionsReport.objectMetadata.deleted, @@ -227,6 +260,12 @@ export class WorkspaceMigrationBuildOrchestratorService { ...orchestratorActionsReport.viewField.created, ...orchestratorActionsReport.viewField.updated, /// + + // Serverless functions + ...orchestratorActionsReport.serverlessFunction.deleted, + ...orchestratorActionsReport.serverlessFunction.created, + ...orchestratorActionsReport.serverlessFunction.updated, + /// ], workspaceId, }, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts index fe677a7e21..37573b2aa3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service.ts @@ -11,10 +11,6 @@ import { WorkspaceEntityMigrationBuilderV2Service, } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; import { WorkspaceMigrationIndexActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2'; -import { - getWorkspaceMigrationV2CreateIndexAction, - getWorkspaceMigrationV2DeleteIndexAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions'; import { FlatIndexValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service'; export type IndexRelatedFlatEntityMaps = Pick< @@ -62,7 +58,10 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt return { status: 'success', - action: getWorkspaceMigrationV2CreateIndexAction(flatIndexToValidate), + action: { + type: 'create_index', + flatIndexMetadata: flatIndexToValidate, + }, }; } @@ -95,7 +94,10 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt return { status: 'success', - action: getWorkspaceMigrationV2DeleteIndexAction(flatIndexToValidate), + action: { + type: 'delete_index', + flatIndexMetadataId: flatIndexToValidate.id, + }, }; } @@ -156,8 +158,14 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt return { status: 'success', action: [ - getWorkspaceMigrationV2DeleteIndexAction(fromFlatIndex), - getWorkspaceMigrationV2CreateIndexAction(toFlatIndex), + { + type: 'delete_index', + flatIndexMetadataId: fromFlatIndex.id, + }, + { + type: 'create_index', + flatIndexMetadata: toFlatIndex, + }, ], }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts new file mode 100644 index 0000000000..8d85165af1 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service.ts @@ -0,0 +1,162 @@ +import { Injectable } from '@nestjs/common'; + +import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; +import { compareTwoFlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/utils/compare-two-flat-serverless-function.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 { + UpdateServerlessFunctionAction, + WorkspaceMigrationServerlessFunctionActionV2, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type'; +import { + FlatServerlessFunctionValidatorService, + ServerlessFunctionRelatedFlatEntityMaps, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service'; + +@Injectable() +export class WorkspaceMigrationV2ServerlessFunctionActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service< + FlatServerlessFunction, + WorkspaceMigrationServerlessFunctionActionV2, + ServerlessFunctionRelatedFlatEntityMaps +> { + constructor( + private readonly flatServerlessFunctionValidatorService: FlatServerlessFunctionValidatorService, + ) { + super(); + } + + protected async validateFlatEntityCreation({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatServerlessFunctionToValidate, + optimisticFlatEntityMaps: optimisticFlatServerlessFunctionMaps, + }: FlatEntityValidationArgs< + FlatServerlessFunction, + ServerlessFunctionRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationServerlessFunctionActionV2, + FlatServerlessFunction + > + > { + const validationResult = + await this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionCreation( + { + dependencyOptimisticFlatEntityMaps, + flatServerlessFunctionToValidate, + optimisticFlatServerlessFunctionMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'create_serverless_function', + serverlessFunction: flatServerlessFunctionToValidate, + }, + }; + } + + protected async validateFlatEntityDeletion({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatServerlessFunctionToValidate, + optimisticFlatEntityMaps: optimisticFlatServerlessFunctionMaps, + }: FlatEntityValidationArgs< + FlatServerlessFunction, + ServerlessFunctionRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationServerlessFunctionActionV2, + FlatServerlessFunction + > + > { + const validationResult = + this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionDeletion( + { + dependencyOptimisticFlatEntityMaps, + flatServerlessFunctionToValidate, + optimisticFlatServerlessFunctionMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'delete_serverless_function', + serverlessFunctionId: flatServerlessFunctionToValidate.id, + }, + }; + } + + protected async validateFlatEntityUpdate({ + dependencyOptimisticFlatEntityMaps, + flatEntityUpdate: { + from: fromFlatServerlessFunction, + to: toFlatServerlessFunction, + }, + optimisticFlatEntityMaps: optimisticFlatServerlessFunctionMaps, + }: FlatEntityUpdateValidationArgs< + FlatServerlessFunction, + ServerlessFunctionRelatedFlatEntityMaps + >): Promise< + | FlatEntityValidationReturnType< + WorkspaceMigrationServerlessFunctionActionV2, + FlatServerlessFunction + > + | undefined + > { + const serverlessFunctionUpdatedProperties = + compareTwoFlatServerlessFunction({ + fromFlatServerlessFunction, + toFlatServerlessFunction, + }); + + if (serverlessFunctionUpdatedProperties.length === 0) { + return undefined; + } + + const validationResult = + this.flatServerlessFunctionValidatorService.validateFlatServerlessFunctionUpdate( + { + dependencyOptimisticFlatEntityMaps, + flatServerlessFunctionToValidate: toFlatServerlessFunction, + optimisticFlatServerlessFunctionMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const updateServerlessFunctionAction: UpdateServerlessFunctionAction = { + type: 'update_serverless_function', + serverlessFunctionId: toFlatServerlessFunction.id, + updates: serverlessFunctionUpdatedProperties, + }; + + return { + status: 'success', + action: updateServerlessFunctionAction, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts index c2637063a6..3714f633c7 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts @@ -13,10 +13,6 @@ import { UpdateViewFieldAction, WorkspaceMigrationViewFieldActionV2, } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; -import { - getWorkspaceMigrationV2ViewFieldCreateAction, - getWorkspaceMigrationV2ViewFieldDeleteAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-field-action'; import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service'; @Injectable() @@ -60,9 +56,10 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac return { status: 'success', - action: getWorkspaceMigrationV2ViewFieldCreateAction( - flatViewFieldToValidate, - ), + action: { + type: 'create_view_field', + viewField: flatViewFieldToValidate, + }, }; } @@ -95,9 +92,10 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac return { status: 'success', - action: getWorkspaceMigrationV2ViewFieldDeleteAction( - flatViewFieldToValidate, - ), + action: { + type: 'delete_view_field', + viewFieldId: flatViewFieldToValidate.id, + }, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts index 7ae45ec2b4..84f8b196c8 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts @@ -13,10 +13,6 @@ import { UpdateViewAction, WorkspaceMigrationViewActionV2, } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; -import { - getWorkspaceMigrationV2ViewCreateAction, - getWorkspaceMigrationV2ViewDeleteAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-action'; import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service'; export type ViewRelatedFlatEntityMaps = Pick< @@ -59,7 +55,10 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti return { status: 'success', - action: getWorkspaceMigrationV2ViewCreateAction(flatViewToValidate), + action: { + type: 'create_view', + view: flatViewToValidate, + }, }; } @@ -86,7 +85,10 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti return { status: 'success', - action: getWorkspaceMigrationV2ViewDeleteAction(flatViewToValidate), + action: { + type: 'delete_view', + viewId: flatViewToValidate.id, + }, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts index b3cd6933e7..4ec9516e99 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts @@ -1,6 +1,7 @@ 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'; +import { type WorkspaceMigrationServerlessFunctionActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type'; import { type WorkspaceMigrationViewActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; import { type WorkspaceMigrationViewFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; @@ -9,7 +10,8 @@ export type WorkspaceMigrationActionV2 = | WorkspaceMigrationFieldActionV2 | WorkspaceMigrationIndexActionV2 | WorkspaceMigrationViewActionV2 - | WorkspaceMigrationViewFieldActionV2; + | WorkspaceMigrationViewFieldActionV2 + | WorkspaceMigrationServerlessFunctionActionV2; export type WorkspaceMigrationActionTypeV2 = WorkspaceMigrationActionV2['type']; export type ExtractAction = Extract< diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type.ts new file mode 100644 index 0000000000..ebeee27f92 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type.ts @@ -0,0 +1,39 @@ +import { type FromTo } from 'twenty-shared/types'; + +import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { type FlatServerlessFunctionPropertiesToCompare } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function-properties-to-compare.type'; +import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; + +export type FlatServerlessFunctionPropertyUpdate< + P extends FlatServerlessFunctionPropertiesToCompare, +> = { + property: P; +} & FromTo; + +export type CreateServerlessFunctionAction = { + type: 'create_serverless_function'; + serverlessFunction: FlatServerlessFunction; +}; + +export type UpdateServerlessFunctionAction = { + type: 'update_serverless_function'; + serverlessFunctionId: string; + updates: Array< + { + [P in FlatServerlessFunctionPropertiesToCompare]: FlatServerlessFunctionPropertyUpdate

; + }[FlatServerlessFunctionPropertiesToCompare] + >; +}; + +export type DeleteServerlessFunctionAction = { + type: 'delete_serverless_function'; + serverlessFunctionId: string; +}; + +export type WorkspaceMigrationServerlessFunctionActionV2 = + | CreateServerlessFunctionAction + | UpdateServerlessFunctionAction + | DeleteServerlessFunctionAction; + +export type WorkspaceMigrationServerlessFunctionActionTypeV2 = + WorkspaceMigrationServerlessFunctionActionV2['type']; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions.ts deleted file mode 100644 index ee1b508da5..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; -import { - type CreateIndexAction, - type DeleteIndexAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2'; - -export const getWorkspaceMigrationV2CreateIndexAction = ( - flatIndexMetadata: FlatIndexMetadata, -): CreateIndexAction => ({ - type: 'create_index', - flatIndexMetadata, -}); - -export const getWorkspaceMigrationV2DeleteIndexAction = ( - flatIndexMetadata: FlatIndexMetadata, -): DeleteIndexAction => ({ - type: 'delete_index', - flatIndexMetadataId: flatIndexMetadata.id, -}); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-action.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-action.ts deleted file mode 100644 index 7b3cc1f8a1..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-action.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type'; -import { - type CreateViewAction, - type DeleteViewAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; - -export const getWorkspaceMigrationV2ViewCreateAction = ( - flatView: FlatView, -): CreateViewAction => ({ - type: 'create_view', - view: flatView, -}); - -export const getWorkspaceMigrationV2ViewDeleteAction = ( - flatView: FlatView, -): DeleteViewAction => ({ - type: 'delete_view', - viewId: flatView.id, -}); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-field-action.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-field-action.ts deleted file mode 100644 index 3011fd99d1..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-view-field-action.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; -import { - type CreateViewFieldAction, - type DeleteViewFieldAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; - -export const getWorkspaceMigrationV2ViewFieldCreateAction = ( - flatViewField: FlatViewField, -): CreateViewFieldAction => ({ - type: 'create_view_field', - viewField: flatViewField, -}); - -export const getWorkspaceMigrationV2ViewFieldDeleteAction = ( - flatViewField: FlatViewField, -): DeleteViewFieldAction => ({ - type: 'delete_view_field', - viewFieldId: flatViewField.id, -}); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service.ts new file mode 100644 index 0000000000..26ec68c49d --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service.ts @@ -0,0 +1,110 @@ +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 { ServerlessFunctionExceptionCode } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; +import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; + +export type ServerlessFunctionRelatedFlatEntityMaps = Pick< + AllFlatEntityMaps, + 'flatServerlessFunctionMaps' +>; + +type ServerlessFunctionValidationArgs = { + flatServerlessFunctionToValidate: FlatServerlessFunction; + optimisticFlatServerlessFunctionMaps: FlatEntityMaps; + dependencyOptimisticFlatEntityMaps: ServerlessFunctionRelatedFlatEntityMaps; +}; +@Injectable() +export class FlatServerlessFunctionValidatorService { + constructor() {} + + public validateFlatServerlessFunctionUpdate({ + flatServerlessFunctionToValidate: updatedFlatServerlessFunction, + optimisticFlatServerlessFunctionMaps, + }: ServerlessFunctionValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatServerlessFunction = + optimisticFlatServerlessFunctionMaps.byId[ + updatedFlatServerlessFunction.id + ]; + + if (!isDefined(existingFlatServerlessFunction)) { + errors.push({ + code: ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + message: t`Serverless function not found`, + userFriendlyMessage: t`Serverless function not found`, + }); + } + + return { + type: 'update_serverless_function', + errors, + flatEntityMinimalInformation: { + id: updatedFlatServerlessFunction.id, + }, + }; + } + + public validateFlatServerlessFunctionDeletion({ + flatServerlessFunctionToValidate: { id: serverlessFunctionIdToDelete }, + optimisticFlatServerlessFunctionMaps, + }: ServerlessFunctionValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatServerlessFunction = + optimisticFlatServerlessFunctionMaps.byId[serverlessFunctionIdToDelete]; + + if (!isDefined(existingFlatServerlessFunction)) { + errors.push({ + code: ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + message: t`Serverless function not found`, + userFriendlyMessage: t`Serverless function not found`, + }); + } + + return { + type: 'delete_serverless_function', + errors, + flatEntityMinimalInformation: { + id: serverlessFunctionIdToDelete, + }, + }; + } + + public async validateFlatServerlessFunctionCreation({ + flatServerlessFunctionToValidate, + optimisticFlatServerlessFunctionMaps, + }: ServerlessFunctionValidationArgs): Promise< + FailedFlatEntityValidation + > { + const errors = []; + + if ( + isDefined( + optimisticFlatServerlessFunctionMaps.byId[ + flatServerlessFunctionToValidate.id + ], + ) + ) { + errors.push({ + code: ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_ALREADY_EXIST, + message: t`Serverless function with same id already exists`, + userFriendlyMessage: t`Serverless function already exists`, + }); + } + + return { + type: 'create_serverless_function', + errors, + flatEntityMinimalInformation: { + id: flatServerlessFunctionToValidate.id, + }, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts index 5a0f1d7700..13edd2f5e1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts @@ -7,9 +7,11 @@ import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/ 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'; +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'; 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 { 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'; import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module'; @@ -26,16 +28,17 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace- WorkspaceMigrationV2ViewActionsBuilderService, WorkspaceMigrationV2ViewFieldActionsBuilderService, WorkspaceMigrationV2IndexActionsBuilderService, + WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, FlatViewValidatorService, FlatViewFieldValidatorService, + FlatServerlessFunctionValidatorService, ], exports: [ WorkspaceMigrationBuilderV2Service, WorkspaceMigrationV2ViewActionsBuilderService, WorkspaceMigrationV2IndexActionsBuilderService, - FlatViewValidatorService, WorkspaceMigrationV2ViewFieldActionsBuilderService, - FlatViewFieldValidatorService, + WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, ], }) export class WorkspaceMigrationBuilderV2Module {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service.ts new file mode 100644 index 0000000000..3a64add6fd --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service.ts @@ -0,0 +1,62 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { CreateServerlessFunctionAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-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 CreateServerlessFunctionActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'create_serverless_function', +) { + constructor() { + super(); + } + + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatServerlessFunctionMaps } = allFlatEntityMaps; + const { serverlessFunction } = action; + + const updatedFlatServerlessFunctionMaps = + addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: serverlessFunction, + flatEntityMaps: flatServerlessFunctionMaps, + }); + + return { + flatServerlessFunctionMaps: updatedFlatServerlessFunctionMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { serverlessFunction } = action; + + const serverlessFunctionRepository = + queryRunner.manager.getRepository( + ServerlessFunctionEntity, + ); + + await serverlessFunctionRepository.insert({ + ...serverlessFunction, + workspaceId, + }); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service.ts new file mode 100644 index 0000000000..806a6d7d30 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service.ts @@ -0,0 +1,62 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { DeleteServerlessFunctionAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-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 DeleteServerlessFunctionActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'delete_serverless_function', +) { + constructor() { + super(); + } + + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatServerlessFunctionMaps } = allFlatEntityMaps; + const { serverlessFunctionId } = action; + + const updatedFlatServerlessFunctionMaps = + deleteFlatEntityFromFlatEntityMapsOrThrow({ + entityToDeleteId: serverlessFunctionId, + flatEntityMaps: flatServerlessFunctionMaps, + }); + + return { + flatServerlessFunctionMaps: updatedFlatServerlessFunctionMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { serverlessFunctionId } = action; + + const serverlessFunctionRepository = + queryRunner.manager.getRepository( + ServerlessFunctionEntity, + ); + + await serverlessFunctionRepository.delete({ + id: serverlessFunctionId, + workspaceId, + }); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service.ts new file mode 100644 index 0000000000..352187258e --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service.ts @@ -0,0 +1,75 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-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 { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { UpdateServerlessFunctionAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-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 UpdateServerlessFunctionActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'update_serverless_function', +) { + constructor() { + super(); + } + + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatServerlessFunctionMaps } = allFlatEntityMaps; + const { serverlessFunctionId } = action; + + const existingServerlessFunction = + findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: serverlessFunctionId, + flatEntityMaps: flatServerlessFunctionMaps, + }); + + const updatedServerlessFunction = { + ...existingServerlessFunction, + ...fromWorkspaceMigrationUpdateActionToPartialEntity(action), + }; + + const updatedFlatServerlessFunctionMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: updatedServerlessFunction, + flatEntityMaps: flatServerlessFunctionMaps, + }); + + return { + flatServerlessFunctionMaps: updatedFlatServerlessFunctionMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner } = context; + const { serverlessFunctionId } = action; + + const serverlessFunctionRepository = + queryRunner.manager.getRepository( + ServerlessFunctionEntity, + ); + + await serverlessFunctionRepository.update( + serverlessFunctionId, + fromWorkspaceMigrationUpdateActionToPartialEntity(action), + ); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts index 35c2e543f5..03124d77c8 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts @@ -9,6 +9,9 @@ import { DeleteIndexActionHandlerService } from 'src/engine/workspace-manager/wo import { CreateObjectActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/create-object-action-handler.service'; import { DeleteObjectActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/delete-object-action-handler.service'; import { UpdateObjectActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/update-object-action-handler.service'; +import { CreateServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service'; +import { DeleteServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service'; +import { UpdateServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service'; import { CreateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/create-view-field-action-handler.service'; import { DeleteViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/delete-view-field-action-handler.service'; import { UpdateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/update-view-field-action-handler.service'; @@ -37,6 +40,10 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor CreateViewFieldActionHandlerService, UpdateViewFieldActionHandlerService, DeleteViewFieldActionHandlerService, + + CreateServerlessFunctionActionHandlerService, + DeleteServerlessFunctionActionHandlerService, + UpdateServerlessFunctionActionHandlerService, ], }) export class WorkspaceSchemaMigrationRunnerActionHandlersModule {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util.ts index ecd12a70bf..47a5464bdf 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util.ts @@ -1,14 +1,5 @@ -import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2'; -import { type UpdateObjectAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2'; -import { type UpdateViewAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; -import { type UpdateViewFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; - export const fromWorkspaceMigrationUpdateActionToPartialEntity = < - T extends - | UpdateFieldAction - | UpdateObjectAction - | UpdateViewAction - | UpdateViewFieldAction, + T extends { updates: Array<{ property: string; to: unknown }> }, >( action: T, ) => { diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts index 07a05a42e1..1db714fcb6 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts @@ -10,6 +10,10 @@ import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queu import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service'; import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { + WorkflowVersionStepException, + WorkflowVersionStepExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-version-step.exception'; import { WorkflowVersionStatus, type WorkflowVersionWorkspaceEntity, @@ -178,6 +182,13 @@ export class WorkflowStatusesUpdateJob { const newStepSettings = { ...step.settings }; + if (!isDefined(serverlessFunction.latestVersion)) { + throw new WorkflowVersionStepException( + `Fail to publish serverless function ${serverlessFunction.id}. Latest version is null`, + WorkflowVersionStepExceptionCode.CODE_STEP_FAILURE, + ); + } + newStepSettings.input.serverlessFunctionVersion = serverlessFunction.latestVersion; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap index e489889d72..f2d279f14c 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap @@ -7,6 +7,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "errors": { "index": [], "objectMetadata": [], + "serverlessFunction": [], "view": [], "viewField": [ { @@ -31,6 +32,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -49,6 +51,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "errors": { "index": [], "objectMetadata": [], + "serverlessFunction": [], "view": [], "viewField": [ { @@ -73,6 +76,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap index 4f7ea31447..e3d0e38bbb 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap @@ -25,6 +25,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -32,6 +33,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -69,6 +71,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -76,6 +79,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -112,6 +116,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -119,6 +124,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -170,6 +176,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -177,6 +184,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -228,6 +236,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -235,6 +244,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -286,6 +296,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -293,6 +304,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -344,6 +356,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -351,6 +364,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -387,6 +401,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -394,6 +409,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -431,6 +447,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -438,6 +455,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -479,6 +497,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -486,6 +505,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -522,6 +542,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -529,6 +550,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -566,6 +588,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -573,6 +596,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -609,6 +633,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -616,6 +641,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -667,6 +693,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -674,6 +701,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -710,6 +738,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -717,6 +746,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -753,6 +783,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -760,6 +791,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -797,6 +829,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -804,6 +837,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -841,6 +875,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -848,6 +883,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -884,6 +920,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -891,6 +928,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -928,6 +966,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -935,6 +974,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -971,6 +1011,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -978,6 +1019,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1019,6 +1061,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1026,6 +1069,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1062,6 +1106,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1069,6 +1114,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1106,6 +1152,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1113,6 +1160,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1149,6 +1197,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1156,6 +1205,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1197,6 +1247,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1204,6 +1255,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1240,6 +1292,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1247,6 +1300,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1284,6 +1338,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1291,6 +1346,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1327,6 +1383,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1334,6 +1391,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1375,6 +1433,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1382,6 +1441,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1418,6 +1478,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1425,6 +1486,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1461,6 +1523,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1468,6 +1531,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1509,6 +1573,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1516,6 +1581,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1552,6 +1618,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1559,6 +1626,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1595,6 +1663,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1602,6 +1671,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1639,6 +1709,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1646,6 +1717,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1682,6 +1754,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1689,6 +1762,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1730,6 +1804,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1737,6 +1812,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1773,6 +1849,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1780,6 +1857,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1816,6 +1894,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1823,6 +1902,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1874,6 +1954,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1881,6 +1962,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1932,6 +2014,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1939,6 +2022,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1990,6 +2074,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1997,6 +2082,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2048,6 +2134,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2055,6 +2142,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2092,6 +2180,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2099,6 +2188,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2140,6 +2230,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2147,6 +2238,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2183,6 +2275,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2190,6 +2283,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2227,6 +2321,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2234,6 +2329,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2270,6 +2366,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2277,6 +2374,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2313,6 +2411,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2320,6 +2419,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2356,6 +2456,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2363,6 +2464,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2400,6 +2502,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2407,6 +2510,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2443,6 +2547,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2450,6 +2555,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2487,6 +2593,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2494,6 +2601,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2530,6 +2638,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2537,6 +2646,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2578,6 +2688,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2585,6 +2696,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2621,6 +2733,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2628,6 +2741,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2665,6 +2779,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2672,6 +2787,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2708,6 +2824,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2715,6 +2832,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2756,6 +2874,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2763,6 +2882,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2799,6 +2919,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2806,6 +2927,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2843,6 +2965,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2850,6 +2973,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2886,6 +3010,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2893,6 +3018,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2934,6 +3060,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2941,6 +3068,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2977,6 +3105,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2984,6 +3113,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3020,6 +3150,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3027,6 +3158,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3068,6 +3200,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3075,6 +3208,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3111,6 +3245,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3118,6 +3253,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3154,6 +3290,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3161,6 +3298,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3198,6 +3336,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3205,6 +3344,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap index a319ee1ebc..186f686404 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap @@ -25,6 +25,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -32,6 +33,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -69,6 +71,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -76,6 +79,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -112,6 +116,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -119,6 +124,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -170,6 +176,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -177,6 +184,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -228,6 +236,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -235,6 +244,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -286,6 +296,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -293,6 +304,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -344,6 +356,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -351,6 +364,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -387,6 +401,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -394,6 +409,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -431,6 +447,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -438,6 +455,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -479,6 +497,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -486,6 +505,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -522,6 +542,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -529,6 +550,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -566,6 +588,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -573,6 +596,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -609,6 +633,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -616,6 +641,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -667,6 +693,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -674,6 +701,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -710,6 +738,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -717,6 +746,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -753,6 +783,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -760,6 +791,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -797,6 +829,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -804,6 +837,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -841,6 +875,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -848,6 +883,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -884,6 +920,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -891,6 +928,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -928,6 +966,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -935,6 +974,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -971,6 +1011,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -978,6 +1019,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1019,6 +1061,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1026,6 +1069,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1062,6 +1106,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1069,6 +1114,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1105,6 +1151,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1112,6 +1159,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1153,6 +1201,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1160,6 +1209,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1196,6 +1246,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1203,6 +1254,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1240,6 +1292,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1247,6 +1300,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1283,6 +1337,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1290,6 +1345,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1331,6 +1387,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1338,6 +1395,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1374,6 +1432,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1381,6 +1440,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1417,6 +1477,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1424,6 +1485,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1465,6 +1527,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1472,6 +1535,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1508,6 +1572,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1515,6 +1580,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1551,6 +1617,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1558,6 +1625,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1594,6 +1662,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1601,6 +1670,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1637,6 +1707,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1644,6 +1715,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1685,6 +1757,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1692,6 +1765,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1728,6 +1802,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1735,6 +1810,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1771,6 +1847,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1778,6 +1855,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1829,6 +1907,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1836,6 +1915,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1887,6 +1967,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1894,6 +1975,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1945,6 +2027,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -1952,6 +2035,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2003,6 +2087,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2010,6 +2095,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2047,6 +2133,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2054,6 +2141,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2095,6 +2183,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2102,6 +2191,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2138,6 +2228,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2145,6 +2236,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2182,6 +2274,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2189,6 +2282,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2225,6 +2319,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2232,6 +2327,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2268,6 +2364,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2275,6 +2372,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2311,6 +2409,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2318,6 +2417,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2355,6 +2455,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2362,6 +2463,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2398,6 +2500,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2405,6 +2508,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2442,6 +2546,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2449,6 +2554,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2485,6 +2591,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2492,6 +2599,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2533,6 +2641,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2540,6 +2649,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2576,6 +2686,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2583,6 +2694,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2619,6 +2731,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2626,6 +2739,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2667,6 +2781,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2674,6 +2789,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2710,6 +2826,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2717,6 +2834,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2754,6 +2872,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2761,6 +2880,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2797,6 +2917,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2804,6 +2925,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2845,6 +2967,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2852,6 +2975,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2888,6 +3012,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2895,6 +3020,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2931,6 +3057,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2938,6 +3065,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2979,6 +3107,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -2986,6 +3115,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3022,6 +3152,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3029,6 +3160,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3065,6 +3197,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3072,6 +3205,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3108,6 +3242,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "type": "update_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -3115,6 +3250,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap index dd37a07464..467ada0cad 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap @@ -71,6 +71,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -78,6 +79,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -113,6 +115,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -120,6 +123,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -150,6 +154,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -157,6 +162,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -187,6 +193,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -194,6 +201,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -251,6 +259,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -258,6 +267,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -309,6 +319,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -316,6 +327,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -367,6 +379,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -374,6 +387,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -431,6 +445,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -438,6 +453,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -476,6 +492,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -483,6 +500,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -521,6 +539,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -528,6 +547,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -565,6 +585,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -572,6 +593,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -602,6 +624,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -609,6 +632,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -639,6 +663,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -646,6 +671,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -676,6 +702,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -683,6 +710,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -716,6 +744,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -723,6 +752,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -754,6 +784,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -761,6 +792,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -791,6 +823,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "type": "create_field", }, ], + "serverlessFunction": [], "view": [], "viewField": [], }, @@ -798,6 +831,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap index 0a33ced73b..96e7c153b1 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap @@ -44,6 +44,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -298,6 +299,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -353,6 +355,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -607,6 +610,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -662,6 +666,7 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -916,6 +921,7 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -971,6 +977,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -1225,6 +1232,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1280,6 +1288,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -1534,6 +1543,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1589,6 +1599,7 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -1843,6 +1854,7 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -1899,6 +1911,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -2153,6 +2166,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2209,6 +2223,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -2463,6 +2478,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2598,6 +2614,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -2852,6 +2869,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -2907,6 +2925,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -3161,6 +3180,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3216,6 +3236,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -3470,6 +3491,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3530,6 +3552,7 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -3784,6 +3807,7 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -3844,6 +3868,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -4098,6 +4123,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -4268,6 +4294,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -4522,6 +4549,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -4692,6 +4720,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -4946,6 +4975,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -5081,6 +5111,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -5335,6 +5366,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -5470,6 +5502,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -5724,6 +5757,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -5894,6 +5928,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -6148,6 +6183,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -6318,6 +6354,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "type": "create_field", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -6572,6 +6609,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -6628,6 +6666,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -6882,6 +6921,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0, @@ -6938,6 +6978,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "type": "create_object", }, ], + "serverlessFunction": [], "view": [ { "errors": [ @@ -7192,6 +7233,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "summary": { "invalidIndex": 0, "invalidObjectMetadata": 0, + "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, "totalErrors": 0,