Refactor ORM

This commit is contained in:
Charles Bochet 2024-07-22 18:28:38 +02:00
parent 303a142b63
commit 612a8bcd61
9 changed files with 229 additions and 345 deletions

4
.vscode/launch.json vendored
View File

@ -44,8 +44,8 @@
"nx",
"run",
"twenty-server:command",
"my-command",
"--my-parameter value",
"migrate-0.23:migrate-link-fields-to-links",
"-w 20202020-1c25-4d02-bf25-6aeccf7ea419",
],
"outputCapture": "std",
"internalConsoleOptions": "openOnSessionStart",

View File

@ -19,8 +19,6 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service';
import { ViewService } from 'src/modules/view/services/view.service';
import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity';
interface MigrateLinkFieldsToLinksCommandOptions {
workspaceId?: string;
@ -42,7 +40,7 @@ export class MigrateLinkFieldsToLinksCommand extends CommandRunner {
private readonly typeORMService: TypeORMService,
private readonly dataSourceService: DataSourceService,
private readonly workspaceStatusService: WorkspaceStatusService,
private readonly viewService: ViewService,
// private readonly viewService: ViewService,
) {
super();
}
@ -177,33 +175,34 @@ export class MigrateLinkFieldsToLinksCommand extends CommandRunner {
});
// Duplicate link field's views behaviour for new links field
await this.viewService.removeFieldFromViews({
workspaceId: workspaceId,
fieldId: tmpNewLinksField.id,
});
// await this.viewService.removeFieldFromViews({
// workspaceId: workspaceId,
// fieldId: tmpNewLinksField.id,
// });
const viewFieldRepository =
await this.twentyORMManager.getRepositoryForWorkspace(
workspaceId,
ViewFieldWorkspaceEntity,
);
const viewsWithDeprecatedField = await viewFieldRepository.find({
where: {
fieldMetadataId: fieldWithLinkType.id,
isVisible: true,
},
});
// const viewFieldRepository =
// await this.twentyORMManager.getRepositoryForWorkspace(
// workspaceId,
// ViewFieldWorkspaceEntity,
// );
// const viewsWithDeprecatedField = await viewFieldRepository.find({
// where: {
// fieldMetadataId: fieldWithLinkType.id,
// isVisible: true,
// },
// });
const viewsWithDeprecatedField = [] as any[];
await this.viewService.addFieldToViews({
workspaceId: workspaceId,
fieldId: tmpNewLinksField.id,
viewsIds: viewsWithDeprecatedField.map((view) => view.id),
positions: viewsWithDeprecatedField.reduce((acc, view) => {
acc[view.id] = view.position;
// await this.viewService.addFieldToViews({
// workspaceId: workspaceId,
// fieldId: tmpNewLinksField.id,
// viewsIds: viewsWithDeprecatedField.map((view) => view.id),
// positions: viewsWithDeprecatedField.reduce((acc, view) => {
// acc[view.id] = view.position;
return acc;
}, []),
});
// return acc;
// }, []),
// });
// Delete link field
await this.fieldMetadataService.deleteOneField(

View File

@ -8,8 +8,6 @@ import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decora
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import {
CalendarEventListFetchJob,
@ -40,8 +38,6 @@ import {
export class GoogleAPIsService {
constructor(
private readonly twentyORMManager: TwentyORMManager,
@InjectWorkspaceDatasource()
private readonly workspaceDataSource: WorkspaceDataSource,
@InjectMessageQueue(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
@InjectMessageQueue(MessageQueue.calendarQueue)
@ -89,67 +85,67 @@ export class GoogleAPIsService {
'calendarChannel',
);
await this.workspaceDataSource.transaction(
async (manager: EntityManager) => {
if (!existingAccountId) {
await this.connectedAccountRepository.create(
{
id: newOrExistingConnectedAccountId,
handle,
provider: ConnectedAccountProvider.GOOGLE,
accessToken: input.accessToken,
refreshToken: input.refreshToken,
accountOwnerId: workspaceMemberId,
},
workspaceId,
manager,
);
await (
await this.twentyORMManager.getWorkspaceDatasource()
)?.transaction(async (manager: EntityManager) => {
if (!existingAccountId) {
await this.connectedAccountRepository.create(
{
id: newOrExistingConnectedAccountId,
handle,
provider: ConnectedAccountProvider.GOOGLE,
accessToken: input.accessToken,
refreshToken: input.refreshToken,
accountOwnerId: workspaceMemberId,
},
workspaceId,
manager,
);
await this.messageChannelRepository.create(
await this.messageChannelRepository.create(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
type: MessageChannelType.EMAIL,
handle,
visibility:
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
syncStatus: MessageChannelSyncStatus.ONGOING,
},
workspaceId,
manager,
);
if (isCalendarEnabled) {
await calendarChannelRepository.save(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
type: MessageChannelType.EMAIL,
handle,
visibility:
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
syncStatus: MessageChannelSyncStatus.ONGOING,
calendarVisibility ||
CalendarChannelVisibility.SHARE_EVERYTHING,
},
workspaceId,
manager,
);
if (isCalendarEnabled) {
await calendarChannelRepository.save(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
handle,
visibility:
calendarVisibility ||
CalendarChannelVisibility.SHARE_EVERYTHING,
},
{},
manager,
);
}
} else {
await this.connectedAccountRepository.updateAccessTokenAndRefreshToken(
input.accessToken,
input.refreshToken,
newOrExistingConnectedAccountId,
workspaceId,
manager,
);
await this.messageChannelRepository.resetSync(
newOrExistingConnectedAccountId,
workspaceId,
{},
manager,
);
}
},
);
} else {
await this.connectedAccountRepository.updateAccessTokenAndRefreshToken(
input.accessToken,
input.refreshToken,
newOrExistingConnectedAccountId,
workspaceId,
manager,
);
await this.messageChannelRepository.resetSync(
newOrExistingConnectedAccountId,
workspaceId,
manager,
);
}
});
if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
const messageChannels =

View File

@ -1,22 +1,30 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { EntitySchema } from 'typeorm';
import { Repository } from 'typeorm';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
import { workspaceDataSourceCacheInstance } from 'src/engine/twenty-orm/twenty-orm-core.module';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
@Injectable()
export class WorkspaceDatasourceFactory {
constructor(
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly dataSourceService: DataSourceService,
private readonly environmentService: EnvironmentService,
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
private readonly entitySchemaFactory: EntitySchemaFactory,
) {}
public async create(
entities: EntitySchema[],
workspaceId: string,
): Promise<WorkspaceDataSource | null> {
const dataSourceMetadata =
@ -28,31 +36,73 @@ export class WorkspaceDatasourceFactory {
return null;
}
const workspaceDataSource = new WorkspaceDataSource(
{
workspaceId,
workspaceCacheStorage: this.workspaceCacheStorageService,
},
{
url:
dataSourceMetadata.url ??
this.environmentService.get('PG_DATABASE_URL'),
type: 'postgres',
logging: this.environmentService.get('DEBUG_MODE')
? ['query', 'error']
: ['error'],
schema: dataSourceMetadata.schema,
entities,
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')
? {
rejectUnauthorized: false,
}
: undefined,
const cacheVersion =
await this.workspaceCacheVersionService.getVersion(workspaceId);
return await workspaceDataSourceCacheInstance.execute(
`${workspaceId}-${cacheVersion}`,
async () => {
let objectMetadataCollection =
await this.workspaceCacheStorageService.getObjectMetadataCollection(
workspaceId,
);
if (!objectMetadataCollection) {
objectMetadataCollection = await this.objectMetadataRepository.find({
where: { workspaceId },
relations: [
'fields.object',
'fields',
'fields.fromRelationMetadata',
'fields.toRelationMetadata',
'fields.fromRelationMetadata.toObjectMetadata',
],
});
if (!objectMetadataCollection) {
throw new Error('No object metadata found');
}
await this.workspaceCacheStorageService.setObjectMetadataCollection(
workspaceId,
objectMetadataCollection,
);
}
const entities = await Promise.all(
objectMetadataCollection.map((objectMetadata) =>
this.entitySchemaFactory.create(workspaceId, objectMetadata),
),
);
const workspaceDataSource = new WorkspaceDataSource(
{
workspaceId,
workspaceCacheStorage: this.workspaceCacheStorageService,
},
{
url:
dataSourceMetadata.url ??
this.environmentService.get('PG_DATABASE_URL'),
type: 'postgres',
logging: this.environmentService.get('DEBUG_MODE')
? ['query', 'error']
: ['error'],
schema: dataSourceMetadata.schema,
entities,
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')
? {
rejectUnauthorized: false,
}
: undefined,
},
);
await workspaceDataSource.initialize();
return workspaceDataSource;
},
(dataSource) => dataSource.destroy(),
);
await workspaceDataSource.initialize();
return workspaceDataSource;
}
}

View File

@ -4,11 +4,8 @@ import {
Logger,
Module,
OnApplicationShutdown,
Provider,
} from '@nestjs/common';
import { TypeOrmModule, getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TypeOrmModule } from '@nestjs/typeorm';
import {
TwentyORMModuleAsyncOptions,
@ -22,17 +19,11 @@ import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/l
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
import { CacheManager } from 'src/engine/twenty-orm/storage/cache-manager.storage';
import { TWENTY_ORM_WORKSPACE_DATASOURCE } from 'src/engine/twenty-orm/twenty-orm.constants';
import { TwentyORMUnscopedManager } from 'src/engine/twenty-orm/twenty-orm-unscoped.manager';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import {
ConfigurableModuleClass,
MODULE_OPTIONS_TOKEN,
} from 'src/engine/twenty-orm/twenty-orm.module-definition';
import { ConfigurableModuleClass } from 'src/engine/twenty-orm/twenty-orm.module-definition';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
export const workspaceDataSourceCacheInstance =
new CacheManager<WorkspaceDataSource>();
@ -48,6 +39,7 @@ export const workspaceDataSourceCacheInstance =
providers: [
...entitySchemaFactories,
TwentyORMManager,
TwentyORMUnscopedManager,
LoadServiceWithWorkspaceContext,
],
exports: [
@ -65,28 +57,10 @@ export class TwentyORMCoreModule
static register(options: TwentyORMOptions): DynamicModule {
const dynamicModule = super.register(options);
// TODO: Avoid code duplication here
const providers: Provider[] = [
{
provide: TWENTY_ORM_WORKSPACE_DATASOURCE,
useFactory: this.createWorkspaceDataSource,
inject: [
WorkspaceCacheStorageService,
getRepositoryToken(ObjectMetadataEntity, 'metadata'),
EntitySchemaFactory,
ScopedWorkspaceContextFactory,
WorkspaceDatasourceFactory,
],
},
];
return {
...dynamicModule,
providers: [...(dynamicModule.providers ?? []), ...providers],
exports: [
...(dynamicModule.exports ?? []),
TWENTY_ORM_WORKSPACE_DATASOURCE,
],
providers: [...(dynamicModule.providers ?? [])],
exports: [...(dynamicModule.exports ?? [])],
};
}
@ -94,89 +68,14 @@ export class TwentyORMCoreModule
asyncOptions: TwentyORMModuleAsyncOptions,
): DynamicModule {
const dynamicModule = super.registerAsync(asyncOptions);
const providers: Provider[] = [
{
provide: TWENTY_ORM_WORKSPACE_DATASOURCE,
useFactory: this.createWorkspaceDataSource,
inject: [
WorkspaceCacheStorageService,
getRepositoryToken(ObjectMetadataEntity, 'metadata'),
EntitySchemaFactory,
ScopedWorkspaceContextFactory,
WorkspaceDatasourceFactory,
MODULE_OPTIONS_TOKEN,
],
},
];
return {
...dynamicModule,
providers: [...(dynamicModule.providers ?? []), ...providers],
exports: [
...(dynamicModule.exports ?? []),
TWENTY_ORM_WORKSPACE_DATASOURCE,
],
providers: [...(dynamicModule.providers ?? [])],
exports: [...(dynamicModule.exports ?? [])],
};
}
static async createWorkspaceDataSource(
workspaceCacheStorageService: WorkspaceCacheStorageService,
objectMetadataRepository: Repository<ObjectMetadataEntity>,
entitySchemaFactory: EntitySchemaFactory,
scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory,
workspaceDataSourceFactory: WorkspaceDatasourceFactory,
_options?: TwentyORMOptions,
) {
const { workspaceId, cacheVersion } =
scopedWorkspaceContextFactory.create();
if (!workspaceId) {
return null;
}
return workspaceDataSourceCacheInstance.execute(
`${workspaceId}-${cacheVersion}`,
async () => {
let objectMetadataCollection =
await workspaceCacheStorageService.getObjectMetadataCollection(
workspaceId,
);
if (!objectMetadataCollection) {
objectMetadataCollection = await objectMetadataRepository.find({
where: { workspaceId },
relations: [
'fields.object',
'fields',
'fields.fromRelationMetadata',
'fields.toRelationMetadata',
'fields.fromRelationMetadata.toObjectMetadata',
],
});
await workspaceCacheStorageService.setObjectMetadataCollection(
workspaceId,
objectMetadataCollection,
);
}
const entities = await Promise.all(
objectMetadataCollection.map((objectMetadata) =>
entitySchemaFactory.create(workspaceId, objectMetadata),
),
);
const workspaceDataSource = await workspaceDataSourceFactory.create(
entities,
workspaceId,
);
return workspaceDataSource;
},
(dataSource) => dataSource.destroy(),
);
}
/**
* Destroys all data sources on application shutdown
*/

View File

@ -0,0 +1,51 @@
import { Injectable, Type } from '@nestjs/common';
import { ObjectLiteral } from 'typeorm';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
@Injectable()
export class TwentyORMUnscopedManager {
constructor(
private readonly workspaceDataSourceFactory: WorkspaceDatasourceFactory,
) {}
async getRepositoryForWorkspace<T extends ObjectLiteral>(
workspaceId: string,
entityClass: Type<T>,
): Promise<WorkspaceRepository<T>>;
async getRepositoryForWorkspace(
workspaceId: string,
objectMetadataName: string,
): Promise<WorkspaceRepository<CustomWorkspaceEntity>>;
async getRepositoryForWorkspace<T extends ObjectLiteral>(
workspaceId: string,
entityClassOrobjectMetadataName: Type<T> | string,
): Promise<
WorkspaceRepository<T> | WorkspaceRepository<CustomWorkspaceEntity>
> {
let objectMetadataName: string;
if (typeof entityClassOrobjectMetadataName === 'string') {
objectMetadataName = entityClassOrobjectMetadataName;
} else {
objectMetadataName = convertClassNameToObjectMetadataName(
entityClassOrobjectMetadataName.name,
);
}
const workspaceDataSource =
await this.workspaceDataSourceFactory.create(workspaceId);
if (!workspaceDataSource) {
throw new Error('Workspace data source not found');
}
return workspaceDataSource.getRepository<T>(objectMetadataName);
}
}

View File

@ -1,32 +1,15 @@
import { Injectable, Optional, Type } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Injectable, Type } from '@nestjs/common';
import { ObjectLiteral, Repository } from 'typeorm';
import { ObjectLiteral } from 'typeorm';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator';
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { workspaceDataSourceCacheInstance } from 'src/engine/twenty-orm/twenty-orm-core.module';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
@Injectable()
export class TwentyORMManager {
constructor(
@Optional()
@InjectWorkspaceDatasource()
private readonly workspaceDataSource: WorkspaceDataSource | null,
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
private readonly workspaceDataSourceFactory: WorkspaceDatasourceFactory,
private readonly entitySchemaFactory: EntitySchemaFactory,
) {}
async getRepository<T extends ObjectLiteral>(
@ -50,110 +33,20 @@ export class TwentyORMManager {
);
}
if (!this.workspaceDataSource) {
throw new Error('Workspace data source not found');
}
const workspaceId = this.workspaceDataSource.getWorkspaceId();
return this.buildRepositoryForWorkspace<T>(workspaceId, objectMetadataName);
}
async getRepositoryForWorkspace<T extends ObjectLiteral>(
workspaceId: string,
entityClass: Type<T>,
): Promise<WorkspaceRepository<T>>;
async getRepositoryForWorkspace(
workspaceId: string,
objectMetadataName: string,
): Promise<WorkspaceRepository<CustomWorkspaceEntity>>;
async getRepositoryForWorkspace<T extends ObjectLiteral>(
workspaceId: string,
entityClassOrobjectMetadataName: Type<T> | string,
): Promise<
WorkspaceRepository<T> | WorkspaceRepository<CustomWorkspaceEntity>
> {
let objectMetadataName: string;
if (typeof entityClassOrobjectMetadataName === 'string') {
objectMetadataName = entityClassOrobjectMetadataName;
} else {
objectMetadataName = convertClassNameToObjectMetadataName(
entityClassOrobjectMetadataName.name,
);
}
return this.buildRepositoryForWorkspace<T>(workspaceId, objectMetadataName);
}
async getWorkspaceDatasource() {
if (!this.workspaceDataSource) {
throw new Error('Workspace data source not found');
}
const workspaceId = this.workspaceDataSource.getWorkspaceId();
return this.buildDatasourceForWorkspace(workspaceId);
}
async buildDatasourceForWorkspace(workspaceId: string) {
const cacheVersion =
await this.workspaceCacheVersionService.getVersion(workspaceId);
let objectMetadataCollection =
await this.workspaceCacheStorageService.getObjectMetadataCollection(
workspaceId,
);
if (!objectMetadataCollection) {
objectMetadataCollection = await this.objectMetadataRepository.find({
where: { workspaceId },
relations: [
'fields.object',
'fields',
'fields.fromRelationMetadata',
'fields.toRelationMetadata',
'fields.fromRelationMetadata.toObjectMetadata',
],
});
await this.workspaceCacheStorageService.setObjectMetadataCollection(
workspaceId,
objectMetadataCollection,
);
}
const entities = await Promise.all(
objectMetadataCollection.map((objectMetadata) =>
this.entitySchemaFactory.create(workspaceId, objectMetadata),
),
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
'20202020-1c25-4d02-bf25-6aeccf7ea419',
);
return await workspaceDataSourceCacheInstance.execute(
`${workspaceId}-${cacheVersion}`,
async () => {
const workspaceDataSource =
await this.workspaceDataSourceFactory.create(entities, workspaceId);
return workspaceDataSource;
},
(dataSource) => dataSource.destroy(),
);
}
async buildRepositoryForWorkspace<T extends ObjectLiteral>(
workspaceId: string,
objectMetadataName: string,
) {
const workspaceDataSource =
await this.buildDatasourceForWorkspace(workspaceId);
if (!workspaceDataSource) {
throw new Error('Workspace data source not found');
}
return workspaceDataSource.getRepository<T>(objectMetadataName);
}
async getWorkspaceDatasource() {
const workspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419';
return this.workspaceDataSourceFactory.create(workspaceId);
}
}

View File

@ -1,20 +1,20 @@
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import * as Sentry from '@sentry/node';
import { graphqlUploadExpress } from 'graphql-upload';
import '@sentry/tracing';
import bytes from 'bytes';
import { useContainer } from 'class-validator';
import '@sentry/tracing';
import { graphqlUploadExpress } from 'graphql-upload';
import { ApplyCorsToExceptions } from 'src/utils/apply-cors-to-exceptions';
import { AppModule } from './app.module';
import { generateFrontConfig } from './utils/generate-front-config';
import { settings } from './engine/constants/settings';
import { LoggerService } from './engine/integrations/logger/logger.service';
import { generateFrontConfig } from './utils/generate-front-config';
const bootstrap = async () => {
const app = await NestFactory.create<NestExpressApplication>(AppModule, {

View File

@ -6,8 +6,6 @@ import { Any } from 'typeorm';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { injectIdsInCalendarEvents } from 'src/modules/calendar/calendar-event-import-manager/utils/inject-ids-in-calendar-events.util';
import { CalendarEventParticipantService } from 'src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service';
@ -26,8 +24,6 @@ import {
export class CalendarSaveEventsService {
constructor(
private readonly twentyORMManager: TwentyORMManager,
@InjectWorkspaceDatasource()
private readonly workspaceDataSource: WorkspaceDataSource,
private readonly calendarEventParticipantService: CalendarEventParticipantService,
@InjectMessageQueue(MessageQueue.contactCreationQueue)
private readonly messageQueueService: MessageQueueService,