Metadata api create entity in workspace custom app (#15911)
# Introduction Cleaner and fewer scope version of https://github.com/twentyhq/twenty/pull/15745 ( removed sync-metadata hack through, too ambitious migration and upgrade ) Please note that this PR won't have any interaction with the existing sync-metadata Which mean that the sync metadata does not update the standard entities applicationId and universalIdentifier, and it won't we will deprecate it on favor of a workspace migration aka twenty-standard app installation ## API Metadata Any operation going through the api metadata nows automatically scope the related entity to the workspace custom application instance. ( optionally passing an applicationId to allow current hacky implem of app sync service ) We need to either ignore the tests or remove the cli status check from the blocking status badges for a PR to be merged ## New workspace Already handled in previous https://github.com/twentyhq/twenty/pull/15625, when a workspace is created it gets created a twenty standard and custom workspace instance All his views and permissions will be prefilled to the its twenty standard app instance with a specific universalIdentifier ## New universalIdentifier At the contrary as before with standardIds, universalIdentifier are unique for a given workspace This means that createdAt field of both object company and opportunity will have a unique universalIdentifier whereas they share the same standardId ## FlatApplication Introduced the flatApplication and cache. Will migrate existing `MetadataName` to be `SyncableMetadataName` in a following PR ## What's next Next we will describe a twenty standard app configuration as json that will be used to generate a workspace migration that will be run instead of the sync metadata, in a nutshell we aim to deprecated the sync metadata So we can standardize any entity to have a non nullable applicationId and universalIdentifier ## Upgrade command Introduced an upgrade command that will create a custom workspace instance for any workspace that do not have one in order to align with the new behavior when creating a new workspace
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
@@ -15,6 +16,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity, CronTriggerEntity]),
|
||||
ApplicationModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
|
||||
import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input';
|
||||
import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input';
|
||||
@@ -23,12 +24,25 @@ export class CronTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
cronTriggerInput: CreateCronTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -43,6 +57,8 @@ export class CronTriggerV2Service {
|
||||
{
|
||||
createCronTriggerInput: cronTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
+6
-3
@@ -6,18 +6,21 @@ import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/t
|
||||
export const fromCreateCronTriggerInputToFlatCronTrigger = ({
|
||||
createCronTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createCronTriggerInput: CreateCronTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatCronTrigger => {
|
||||
const now = new Date();
|
||||
const id = v4();
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: createCronTriggerInput.universalIdentifier ?? v4(),
|
||||
id,
|
||||
universalIdentifier: createCronTriggerInput.universalIdentifier ?? id,
|
||||
settings: createCronTriggerInput.settings,
|
||||
serverlessFunctionId: createCronTriggerInput.serverlessFunctionId,
|
||||
applicationId: createCronTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
||||
+2
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DatabaseEventTriggerEntity } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
@@ -14,6 +15,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity, DatabaseEventTriggerEntity]),
|
||||
ApplicationModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
|
||||
import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input';
|
||||
import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input';
|
||||
@@ -23,12 +24,25 @@ export class DatabaseEventTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
databaseEventTriggerInput: CreateDatabaseEventTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -47,6 +61,8 @@ export class DatabaseEventTriggerV2Service {
|
||||
fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger({
|
||||
createDatabaseEventTriggerInput: databaseEventTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+6
-3
@@ -6,21 +6,24 @@ import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/datab
|
||||
export const fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger = ({
|
||||
createDatabaseEventTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createDatabaseEventTriggerInput: CreateDatabaseEventTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatDatabaseEventTrigger => {
|
||||
const now = new Date();
|
||||
const id = uuidV4();
|
||||
|
||||
return {
|
||||
id: uuidV4(),
|
||||
id,
|
||||
universalIdentifier:
|
||||
createDatabaseEventTriggerInput.universalIdentifier ?? uuidV4(),
|
||||
createDatabaseEventTriggerInput.universalIdentifier ?? id,
|
||||
settings: createDatabaseEventTriggerInput.settings,
|
||||
serverlessFunctionId: createDatabaseEventTriggerInput.serverlessFunctionId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
applicationId: createDatabaseEventTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { ActorModule } from 'src/engine/core-modules/actor/actor.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
@@ -60,6 +61,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
|
||||
DataSourceModule,
|
||||
TypeORMModule,
|
||||
ActorModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
ViewModule,
|
||||
ViewFieldModule,
|
||||
|
||||
+24
@@ -5,6 +5,7 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FindOneOptions, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input';
|
||||
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
|
||||
@@ -32,6 +33,7 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(fieldMetadataRepository);
|
||||
}
|
||||
@@ -39,13 +41,20 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
async createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatFieldMetadata> {
|
||||
const [createdFieldMetadata] = await this.createManyFields({
|
||||
workspaceId,
|
||||
createFieldInputs: [createFieldInput],
|
||||
applicationId,
|
||||
});
|
||||
|
||||
if (!isDefined(createdFieldMetadata)) {
|
||||
@@ -283,14 +292,27 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
async createManyFields({
|
||||
createFieldInputs,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createFieldInputs: Omit<CreateFieldInput, 'workspaceId'>[];
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatFieldMetadata[]> {
|
||||
if (createFieldInputs.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
@@ -316,6 +338,8 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
+6
-6
@@ -104,7 +104,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"result": {
|
||||
"flatFieldMetadatas": [
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -140,7 +140,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -178,7 +178,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -214,7 +214,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -254,7 +254,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
],
|
||||
"indexMetadatas": [
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<ClockDate>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
@@ -278,7 +278,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<ClockDate>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
|
||||
+14
@@ -42,6 +42,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should create morph relation field metadata with valid input on rocket object to pet object',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -100,6 +102,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when morphRelationsCreationPayload is missing',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -118,6 +122,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when morphRelationsCreationPayload is empty array',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -137,6 +143,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has different relation types',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -169,6 +177,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has several references to same object metadata',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -201,6 +211,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has invalid relation payload',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -225,6 +237,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when target object metadata is not found',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
|
||||
+5
@@ -25,12 +25,14 @@ import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-m
|
||||
export type FromCreateFieldInputToFlatObjectMetadataArgs = {
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
|
||||
|
||||
export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
createFieldInput: rawCreateFieldInput,
|
||||
workspaceId,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateFieldInputToFlatObjectMetadataArgs): Promise<
|
||||
FieldInputTranspilationResult<{
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
@@ -71,6 +73,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
switch (createFieldInput.type) {
|
||||
@@ -83,6 +86,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata: parentFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
}
|
||||
case FieldMetadataType.RELATION: {
|
||||
@@ -94,6 +98,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
type: createFieldInput.type,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
}
|
||||
case FieldMetadataType.RATING: {
|
||||
|
||||
+3
@@ -21,12 +21,14 @@ type FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs = {
|
||||
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
sourceFlatObjectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
createFieldInput,
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs): Promise<
|
||||
FieldInputTranspilationResult<{
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
@@ -90,6 +92,7 @@ export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
morphId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+3
@@ -21,12 +21,14 @@ type FromRelationCreateFieldInputToFlatFieldMetadataArgs = {
|
||||
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
sourceFlatObjectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata,
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromRelationCreateFieldInputToFlatFieldMetadataArgs): Promise<
|
||||
FieldInputTranspilationResult<SourceTargetMorphOrRelationFlatFieldAndFlatIndex>
|
||||
> => {
|
||||
@@ -67,6 +69,7 @@ export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
sourceFlatObjectMetadata,
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ export const generateIndexForFlatFieldMetadata = ({
|
||||
universalIdentifier: indexId,
|
||||
updatedAt: createdAt,
|
||||
workspaceId,
|
||||
applicationId: null,
|
||||
applicationId: flatFieldMetadata.applicationId,
|
||||
},
|
||||
flatObjectMetadata,
|
||||
},
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationType,
|
||||
RelationOnDeleteAction,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@@ -46,6 +46,7 @@ type GenerateMorphOrRelationFlatFieldMetadataPairArgs = {
|
||||
> & { type: MorphOrRelationFieldMetadataType };
|
||||
workspaceId: string;
|
||||
morphId?: string | null;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export type SourceTargetMorphOrRelationFlatFieldAndFlatIndex = {
|
||||
@@ -58,6 +59,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
sourceFlatObjectMetadata,
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
sourceFlatObjectMetadataJoinColumnName,
|
||||
morphId = null,
|
||||
}: GenerateMorphOrRelationFlatFieldMetadataPairArgs): SourceTargetMorphOrRelationFlatFieldAndFlatIndex => {
|
||||
@@ -78,6 +80,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId: sourceRelationTargetFieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
}),
|
||||
morphId,
|
||||
objectMetadataId: sourceFlatObjectMetadata.id,
|
||||
@@ -116,6 +119,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
createFieldInput: targetCreateFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId: targetRelationTargetFieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
}),
|
||||
type: FieldMetadataType.RELATION,
|
||||
defaultValue: null,
|
||||
|
||||
+3
-1
@@ -9,11 +9,13 @@ type GetDefaultFlatFieldMetadataArgs = {
|
||||
fieldMetadataId: string;
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const getDefaultFlatFieldMetadata = ({
|
||||
createFieldInput,
|
||||
fieldMetadataId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: GetDefaultFlatFieldMetadataArgs) => {
|
||||
const { defaultValue, settings } = extractAndSanitizeObjectStringFields(
|
||||
createFieldInput,
|
||||
@@ -56,7 +58,7 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
updatedAt: createdAt,
|
||||
isUIReadOnly: createFieldInput.isUIReadOnly ?? false,
|
||||
morphId: null,
|
||||
applicationId: createFieldInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
|
||||
+4
-2
@@ -17,11 +17,13 @@ type FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs
|
||||
{
|
||||
createObjectInput: CreateObjectInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
|
||||
export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate =
|
||||
({
|
||||
createObjectInput: rawCreateObjectInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
}: FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs): {
|
||||
flatObjectMetadataToCreate: FlatObjectMetadata;
|
||||
@@ -48,7 +50,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
|
||||
buildDefaultFlatFieldMetadatasForCustomObject({
|
||||
flatObjectMetadata: {
|
||||
id: objectMetadataId,
|
||||
applicationId: createObjectInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
},
|
||||
workspaceId,
|
||||
});
|
||||
@@ -81,7 +83,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
|
||||
shortcut: createObjectInput.shortcut ?? null,
|
||||
standardId: createObjectInput.standardId ?? null,
|
||||
standardOverrides: null,
|
||||
applicationId: createObjectInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
universalIdentifier: objectMetadataId,
|
||||
targetTableName: 'DEPRECATED',
|
||||
workspaceId,
|
||||
|
||||
+3
-1
@@ -8,11 +8,13 @@ import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-o
|
||||
export type FromCreateViewFieldInputToFlatViewFieldToCreateArgs = {
|
||||
createViewFieldInput: CreateViewFieldInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
createViewFieldInput: rawCreateViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateViewFieldInputToFlatViewFieldToCreateArgs): FlatViewField => {
|
||||
const { fieldMetadataId, viewId, ...createViewFieldInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -37,6 +39,6 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
size: createViewFieldInput.size ?? DEFAULT_VIEW_FIELD_SIZE,
|
||||
position: createViewFieldInput.position ?? 0,
|
||||
aggregateOperation: createViewFieldInput.aggregateOperation ?? null,
|
||||
applicationId: createViewFieldInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -8,9 +8,11 @@ import { type CreateViewFilterInput } from 'src/engine/metadata-modules/view-fil
|
||||
export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
createViewFilterInput: rawCreateViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewFilterInput: CreateViewFilterInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewFilter => {
|
||||
const { fieldMetadataId, viewId, value, ...createViewFilterInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -44,6 +46,6 @@ export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
positionInViewFilterGroup:
|
||||
createViewFilterInput.positionInViewFilterGroup ?? null,
|
||||
subFieldName: createViewFilterInput.subFieldName ?? null,
|
||||
applicationId: createViewFilterInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -7,9 +7,11 @@ import { type CreateViewGroupInput } from 'src/engine/metadata-modules/view-grou
|
||||
export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
createViewGroupInput: rawCreateViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewGroupInput: CreateViewGroupInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewGroup => {
|
||||
const { fieldMetadataId, viewId, ...createViewGroupInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -33,6 +35,6 @@ export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
isVisible: createViewGroupInput.isVisible ?? true,
|
||||
fieldValue: createViewGroupInput.fieldValue,
|
||||
position: createViewGroupInput.position ?? 0,
|
||||
applicationId: createViewGroupInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -11,10 +11,12 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
createViewInput: rawCreateViewInput,
|
||||
workspaceId,
|
||||
createdByUserWorkspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewInput: CreateViewInput;
|
||||
workspaceId: string;
|
||||
createdByUserWorkspaceId?: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatView => {
|
||||
const { objectMetadataId, ...createViewInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -52,6 +54,6 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
applicationId: createViewInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+28
-4
@@ -5,6 +5,7 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { fromArrayToUniqueKeyRecord, isDefined } from 'twenty-shared/utils';
|
||||
import { FindManyOptions, FindOneOptions, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -43,6 +44,7 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(objectMetadataRepository);
|
||||
}
|
||||
@@ -323,10 +325,22 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
async createOneObject({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createObjectInput: CreateObjectInput;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatObjectMetadata> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
@@ -354,6 +368,8 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
} = fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
@@ -367,13 +383,15 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
flatEntityToUpdate: [],
|
||||
});
|
||||
|
||||
const flatDefaultViewToCreate = await this.createDefaultFlatView({
|
||||
const flatDefaultViewToCreate = await this.computeFlatViewToCreate({
|
||||
objectMetadata: flatObjectMetadataToCreate,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const flatDefaultViewFieldsToCreate =
|
||||
await this.createDefaultFlatViewFields({
|
||||
await this.computeFlatViewFieldsToCreate({
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
objectFlatFieldMetadatas: findManyFlatEntityByIdInFlatEntityMapsOrThrow(
|
||||
{
|
||||
flatEntityMaps: flatFieldMetadataMapsFromTo.to,
|
||||
@@ -456,10 +474,12 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
return createdFlatObjectMetadata;
|
||||
}
|
||||
|
||||
private async createDefaultFlatView({
|
||||
private async computeFlatViewToCreate({
|
||||
objectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
@@ -475,16 +495,19 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
const flatViewFromCreateInput = fromCreateViewInputToFlatViewToCreate({
|
||||
createViewInput: defaultViewInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return flatViewFromCreateInput;
|
||||
}
|
||||
|
||||
private async createDefaultFlatViewFields({
|
||||
private async computeFlatViewFieldsToCreate({
|
||||
objectFlatFieldMetadatas,
|
||||
viewId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
objectFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
viewId: string;
|
||||
workspaceId: string;
|
||||
@@ -500,6 +523,7 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
viewId: viewId,
|
||||
},
|
||||
workspaceCustomApplicationId,
|
||||
workspaceId: workspaceId,
|
||||
}),
|
||||
);
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ import {
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
@@ -50,6 +51,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
FieldMetadataEntity,
|
||||
]),
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity, ViewEntity]),
|
||||
ApplicationModule,
|
||||
DataSourceModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const buildDefaultFieldsForCustomObject = (
|
||||
workspaceId: string,
|
||||
): Array<Partial<FieldMetadataEntity> & { id: string }> => [
|
||||
{
|
||||
id: v4(),
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id,
|
||||
type: FieldMetadataType.UUID,
|
||||
name: 'id',
|
||||
label: 'Id',
|
||||
icon: 'Icon123',
|
||||
description: 'Id',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: true,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: 'uuid',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
icon: 'IconAbc',
|
||||
description: 'Name',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: "''",
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
name: 'createdAt',
|
||||
label: 'Creation date',
|
||||
icon: 'IconCalendar',
|
||||
description: 'Creation date',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 'now',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
name: 'updatedAt',
|
||||
label: 'Last update',
|
||||
icon: 'IconCalendarClock',
|
||||
description: 'Last time the record was changed',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: false,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 'now',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt,
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
name: 'deletedAt',
|
||||
label: 'Deleted at',
|
||||
icon: 'IconCalendarClock',
|
||||
description: 'Deletion date',
|
||||
isNullable: true,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: false,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
type: FieldMetadataType.ACTOR,
|
||||
name: 'createdBy',
|
||||
label: 'Created by',
|
||||
icon: 'IconCreativeCommonsSa',
|
||||
description: 'The creator of the record',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: false,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: { name: "''", source: "'MANUAL'" },
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
type: FieldMetadataType.POSITION,
|
||||
name: 'position',
|
||||
label: 'Position',
|
||||
icon: 'IconHierarchy2',
|
||||
description: 'Position',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: true,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 0,
|
||||
},
|
||||
];
|
||||
+24
-41
@@ -7,7 +7,6 @@ import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
|
||||
|
||||
type BuildDefaultFlatFieldMetadataForCustomObjectArgs = {
|
||||
@@ -24,9 +23,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
flatObjectMetadata: { id: objectMetadataId, applicationId },
|
||||
}: BuildDefaultFlatFieldMetadataForCustomObjectArgs) => {
|
||||
const createdAt = new Date();
|
||||
const idFieldId = v4();
|
||||
const idField: FlatFieldMetadata<FieldMetadataType.UUID> = {
|
||||
type: FieldMetadataType.UUID,
|
||||
id: v4(),
|
||||
id: idFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -34,10 +34,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: true,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.id,
|
||||
]),
|
||||
universalIdentifier: idFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id,
|
||||
name: 'id',
|
||||
@@ -63,9 +60,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const nameFieldId = v4();
|
||||
const nameField: FlatFieldMetadata<FieldMetadataType.TEXT> = {
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: v4(),
|
||||
id: nameFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -73,10 +71,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
]),
|
||||
universalIdentifier: nameFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
name: 'name',
|
||||
@@ -102,9 +97,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const createdAtFieldId = v4();
|
||||
const createdAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: createdAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -112,10 +108,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
]),
|
||||
universalIdentifier: createdAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
name: 'createdAt',
|
||||
@@ -141,9 +134,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const updatedAtFieldId = v4();
|
||||
const updatedAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: updatedAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -151,10 +145,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
]),
|
||||
universalIdentifier: updatedAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
name: 'updatedAt',
|
||||
@@ -180,9 +171,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const deletedAtFieldId = v4();
|
||||
const deletedAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: deletedAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -190,10 +182,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt,
|
||||
]),
|
||||
universalIdentifier: deletedAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt,
|
||||
name: 'deletedAt',
|
||||
@@ -219,9 +208,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const createdByFieldId = v4();
|
||||
const createdByField: FlatFieldMetadata<FieldMetadataType.ACTOR> = {
|
||||
type: FieldMetadataType.ACTOR,
|
||||
id: v4(),
|
||||
id: createdByFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -229,10 +219,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
]),
|
||||
universalIdentifier: createdByFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
name: 'createdBy',
|
||||
@@ -257,9 +244,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const positionFieldId = v4();
|
||||
const positionField: FlatFieldMetadata<FieldMetadataType.POSITION> = {
|
||||
type: FieldMetadataType.POSITION,
|
||||
id: v4(),
|
||||
id: positionFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -267,10 +255,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
]),
|
||||
universalIdentifier: positionFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
name: 'position',
|
||||
@@ -296,20 +281,18 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const searchVectorFieldId = v4();
|
||||
const searchVectorField: FlatFieldMetadata<FieldMetadataType.TS_VECTOR> = {
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
id: v4(),
|
||||
id: searchVectorFieldId,
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.searchVector,
|
||||
]),
|
||||
universalIdentifier: searchVectorFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.searchVector,
|
||||
name: 'searchVector',
|
||||
|
||||
+8
-31
@@ -1,7 +1,7 @@
|
||||
import { type STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { type STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -16,15 +16,9 @@ import {
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
|
||||
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
|
||||
import {
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
STANDARD_OBJECT_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
|
||||
import {
|
||||
createDeterministicUuid,
|
||||
createRelationDeterministicUuid,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { createRelationDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
|
||||
const generateSourceFlatFieldMetadata = ({
|
||||
workspaceId,
|
||||
@@ -49,17 +43,6 @@ const generateSourceFlatFieldMetadata = ({
|
||||
STANDARD_OBJECT_ICONS[
|
||||
targetFlatObjectMetadata.nameSingular as keyof typeof STANDARD_OBJECT_ICONS
|
||||
] || 'IconBuildingSkyscraper';
|
||||
const standardId =
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS[
|
||||
targetFlatObjectMetadata.namePlural as keyof typeof CUSTOM_OBJECT_STANDARD_FIELD_IDS
|
||||
];
|
||||
|
||||
if (!isDefined(standardId)) {
|
||||
throw new ObjectMetadataException(
|
||||
`Standard field ID not found for target object ${targetFlatObjectMetadata.namePlural}`,
|
||||
ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
@@ -89,16 +72,13 @@ const generateSourceFlatFieldMetadata = ({
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
standardId,
|
||||
standardId: null,
|
||||
standardOverrides: null,
|
||||
type: FieldMetadataType.RELATION,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
sourceFlatObjectMetadata.id,
|
||||
standardId,
|
||||
]),
|
||||
universalIdentifier: sourceFieldMetadataId,
|
||||
workspaceId,
|
||||
morphId: null,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId ?? null,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -165,11 +145,8 @@ const generateTargetFlatFieldMetadata = ({
|
||||
relationTargetFieldMetadataId: sourceFlatFieldMetadata.id,
|
||||
relationTargetObjectMetadataId: sourceFlatObjectMetadata.id,
|
||||
standardOverrides: null,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
targetFlatObjectMetadata.id,
|
||||
standardId,
|
||||
]),
|
||||
applicationId: sourceFlatObjectMetadata.applicationId ?? null,
|
||||
universalIdentifier: sourceFlatFieldMetadata.relationTargetFieldMetadataId,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
|
||||
@@ -30,6 +31,7 @@ import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/wor
|
||||
PermissionFlagModule,
|
||||
WorkspacePermissionsCacheModule,
|
||||
FileModule,
|
||||
ApplicationModule,
|
||||
],
|
||||
providers: [RoleService, RoleResolver],
|
||||
exports: [RoleService],
|
||||
|
||||
@@ -3,7 +3,9 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { MEMBER_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/member-role-label.constants';
|
||||
import {
|
||||
@@ -29,6 +31,7 @@ export class RoleService {
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
public async getWorkspaceRoles(workspaceId: string): Promise<RoleEntity[]> {
|
||||
@@ -70,10 +73,18 @@ export class RoleService {
|
||||
input: CreateRoleInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.validateRoleInputOrThrow({ input, workspaceId });
|
||||
|
||||
const id = input.id ?? v4();
|
||||
const role = await this.roleRepository.save({
|
||||
id: input.id,
|
||||
id,
|
||||
label: input.label,
|
||||
description: input.description,
|
||||
icon: input.icon,
|
||||
@@ -88,6 +99,8 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: input.canBeAssignedToApiKeys,
|
||||
isEditable: true,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
|
||||
await this.workspacePermissionsCacheService.recomputeRolesPermissionsCache({
|
||||
@@ -198,9 +211,13 @@ export class RoleService {
|
||||
|
||||
public async createMemberRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
applicationId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const id = v4();
|
||||
|
||||
return this.roleRepository.save({
|
||||
label: MEMBER_ROLE_LABEL,
|
||||
description: 'Member role',
|
||||
@@ -216,15 +233,22 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: false,
|
||||
isEditable: true,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
}
|
||||
|
||||
// Only used for dev seeding and testing
|
||||
public async createGuestRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const id = v4();
|
||||
|
||||
return this.roleRepository.save({
|
||||
label: 'Guest',
|
||||
description: 'Guest role',
|
||||
@@ -240,6 +264,9 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: false,
|
||||
isEditable: false,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { TokenModule } from 'src/engine/core-modules/auth/token/token.module';
|
||||
import { WorkspaceDomainsModule } from 'src/engine/core-modules/domain/workspace-domains/workspace-domains.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
@@ -17,6 +18,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([RouteTriggerEntity]),
|
||||
ApplicationModule,
|
||||
TokenModule,
|
||||
WorkspaceDomainsModule,
|
||||
ServerlessFunctionModule,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -23,12 +24,25 @@ export class RouteTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
routeTriggerInput: CreateRouteTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -43,6 +57,8 @@ export class RouteTriggerV2Service {
|
||||
fromCreateRouteTriggerInputToFlatRouteTrigger({
|
||||
createRouteTriggerInput: routeTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+6
-4
@@ -6,16 +6,18 @@ import { type FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger
|
||||
export const fromCreateRouteTriggerInputToFlatRouteTrigger = ({
|
||||
createRouteTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createRouteTriggerInput: CreateRouteTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatRouteTrigger => {
|
||||
const now = new Date();
|
||||
const id = uuidV4();
|
||||
|
||||
return {
|
||||
id: uuidV4(),
|
||||
universalIdentifier:
|
||||
createRouteTriggerInput.universalIdentifier ?? uuidV4(),
|
||||
id,
|
||||
universalIdentifier: createRouteTriggerInput.universalIdentifier ?? id,
|
||||
path: createRouteTriggerInput.path,
|
||||
isAuthRequired: createRouteTriggerInput.isAuthRequired,
|
||||
httpMethod: createRouteTriggerInput.httpMethod,
|
||||
@@ -23,6 +25,6 @@ export const fromCreateRouteTriggerInputToFlatRouteTrigger = ({
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
applicationId: createRouteTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { AuditModule } from 'src/engine/core-modules/audit/audit.module';
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
@@ -35,6 +36,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
]),
|
||||
FileModule,
|
||||
ThrottlerModule,
|
||||
ApplicationModule,
|
||||
AuditModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -23,6 +24,7 @@ export class ServerlessFunctionV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -34,6 +36,13 @@ export class ServerlessFunctionV2Service {
|
||||
};
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -49,6 +58,7 @@ export class ServerlessFunctionV2Service {
|
||||
fromCreateServerlessFunctionInputToFlatServerlessFunction({
|
||||
createServerlessFunctionInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+4
-2
@@ -14,11 +14,13 @@ export type FromCreateServerlessFunctionInputToFlatServerlessFunctionArgs = {
|
||||
serverlessFunctionLayerId: string;
|
||||
};
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({
|
||||
createServerlessFunctionInput: rawCreateServerlessFunctionInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateServerlessFunctionInputToFlatServerlessFunctionArgs): FlatServerlessFunction => {
|
||||
const id = v4();
|
||||
const currentDate = new Date();
|
||||
@@ -35,13 +37,13 @@ export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({
|
||||
handlerName:
|
||||
rawCreateServerlessFunctionInput.handlerName ?? DEFAULT_HANDLER_NAME,
|
||||
universalIdentifier:
|
||||
rawCreateServerlessFunctionInput.universalIdentifier ?? v4(),
|
||||
rawCreateServerlessFunctionInput.universalIdentifier ?? id,
|
||||
createdAt: currentDate,
|
||||
updatedAt: currentDate,
|
||||
deletedAt: null,
|
||||
latestVersion: null,
|
||||
publishedVersions: [],
|
||||
applicationId: rawCreateServerlessFunctionInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
runtime: ServerlessFunctionRuntime.NODE22,
|
||||
timeoutSeconds: rawCreateServerlessFunctionInput.timeoutSeconds ?? 300,
|
||||
serverlessFunctionLayerId:
|
||||
|
||||
+10
@@ -4,6 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -32,6 +33,7 @@ export class ViewFieldV2Service {
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
@InjectRepository(ViewFieldEntity)
|
||||
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -67,6 +69,13 @@ export class ViewFieldV2Service {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatViewMaps,
|
||||
@@ -89,6 +98,7 @@ export class ViewFieldV2Service {
|
||||
fromCreateViewFieldInputToFlatViewFieldToCreate({
|
||||
createViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { ViewFieldController } from 'src/engine/metadata-modules/view-field/controllers/view-field.controller';
|
||||
@@ -16,6 +17,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewFieldEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ export class ViewFilterV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -31,6 +33,13 @@ export class ViewFilterV2Service {
|
||||
createViewFilterInput: CreateViewFilterInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatViewMaps,
|
||||
@@ -52,6 +61,7 @@ export class ViewFilterV2Service {
|
||||
fromCreateViewFilterInputToFlatViewFilterToCreate({
|
||||
createViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
@@ -18,6 +19,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewFilterEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -27,6 +28,7 @@ export class ViewGroupV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -62,6 +64,13 @@ export class ViewGroupV2Service {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
@@ -82,6 +91,7 @@ export class ViewGroupV2Service {
|
||||
fromCreateViewGroupInputToFlatViewGroupToCreate({
|
||||
createViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
@@ -18,6 +19,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewGroupEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ export class ViewV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -33,6 +35,13 @@ export class ViewV2Service {
|
||||
workspaceId: string;
|
||||
createdByUserWorkspaceId?: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
@@ -52,6 +61,7 @@ export class ViewV2Service {
|
||||
createViewInput,
|
||||
workspaceId,
|
||||
createdByUserWorkspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { I18nModule } from 'src/engine/core-modules/i18n/i18n.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
@@ -32,6 +33,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
ViewGroupModule,
|
||||
ViewSortModule,
|
||||
I18nModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
UserRoleModule,
|
||||
|
||||
Reference in New Issue
Block a user