mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-22 03:17:40 +03:00
Refactor ORM
This commit is contained in:
parent
303a142b63
commit
612a8bcd61
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -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",
|
||||
|
@ -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(
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, {
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user