Deprecate inject workspace repo (#6353)

This commit is contained in:
Charles Bochet
2024-07-20 00:43:29 +02:00
committed by GitHub
parent 2e38c3bbc1
commit d8cadad0fa
29 changed files with 441 additions and 359 deletions

View File

@ -4,42 +4,42 @@ import { EntityManager } from 'typeorm';
import { v4 } from 'uuid';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
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 { 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,
CalendarEventsImportJobData,
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
import {
CalendarChannelVisibility,
CalendarChannelWorkspaceEntity,
} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
import {
ConnectedAccountWorkspaceEntity,
ConnectedAccountProvider,
ConnectedAccountWorkspaceEntity,
} from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
import {
MessageChannelWorkspaceEntity,
MessageChannelSyncStatus,
MessageChannelType,
MessageChannelVisibility,
MessageChannelSyncStatus,
MessageChannelWorkspaceEntity,
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import {
MessagingMessageListFetchJob,
MessagingMessageListFetchJobData,
} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator';
import {
CalendarChannelWorkspaceEntity,
CalendarChannelVisibility,
} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import {
CalendarEventsImportJobData,
CalendarEventListFetchJob,
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
@Injectable()
export class GoogleAPIsService {
constructor(
private readonly twentyORMManager: TwentyORMManager,
@InjectWorkspaceDatasource()
private readonly workspaceDataSource: WorkspaceDataSource,
@InjectMessageQueue(MessageQueue.messagingQueue)
@ -51,8 +51,6 @@ export class GoogleAPIsService {
private readonly connectedAccountRepository: ConnectedAccountRepository,
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
private readonly messageChannelRepository: MessageChannelRepository,
@InjectWorkspaceRepository(CalendarChannelWorkspaceEntity)
private readonly calendarChannelRepository: WorkspaceRepository<CalendarChannelWorkspaceEntity>,
) {}
async refreshGoogleRefreshToken(input: {
@ -86,6 +84,11 @@ export class GoogleAPIsService {
const existingAccountId = connectedAccounts?.[0]?.id;
const newOrExistingConnectedAccountId = existingAccountId ?? v4();
const calendarChannelRepository =
await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>(
'calendarChannel',
);
await this.workspaceDataSource.transaction(
async (manager: EntityManager) => {
if (!existingAccountId) {
@ -117,7 +120,7 @@ export class GoogleAPIsService {
);
if (isCalendarEnabled) {
await this.calendarChannelRepository.save(
await calendarChannelRepository.save(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
@ -167,7 +170,7 @@ export class GoogleAPIsService {
}
if (isCalendarEnabled) {
const calendarChannels = await this.calendarChannelRepository.find({
const calendarChannels = await calendarChannelRepository.find({
where: {
connectedAccountId: newOrExistingConnectedAccountId,
},

View File

@ -1,20 +1,22 @@
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import {
AvailableProduct,
BillingWorkspaceService,
} from 'src/engine/core-modules/billing/billing.workspace-service';
import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input';
import { assert } from 'src/utils/assert';
import { ProductPricesEntity } from 'src/engine/core-modules/billing/dto/product-prices.entity';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { User } from 'src/engine/core-modules/user/user.entity';
import { CheckoutSessionInput } from 'src/engine/core-modules/billing/dto/checkout-session.input';
import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity';
import { BillingSessionInput } from 'src/engine/core-modules/billing/dto/billing-session.input';
import { CheckoutSessionInput } from 'src/engine/core-modules/billing/dto/checkout-session.input';
import { ProductPricesEntity } from 'src/engine/core-modules/billing/dto/product-prices.entity';
import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input';
import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity';
import { UpdateBillingEntity } from 'src/engine/core-modules/billing/dto/update-billing.entity';
import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { assert } from 'src/utils/assert';
@Resolver()
export class BillingResolver {
@ -60,6 +62,7 @@ export class BillingResolver {
@Mutation(() => SessionEntity)
@UseGuards(JwtAuthGuard)
async checkoutSession(
@AuthWorkspace() workspace: Workspace,
@AuthUser() user: User,
@Args() { recurringInterval, successUrlPath }: CheckoutSessionInput,
) {
@ -87,6 +90,7 @@ export class BillingResolver {
return {
url: await this.billingWorkspaceService.computeCheckoutSessionURL(
user,
workspace,
stripePriceId,
successUrlPath,
),

View File

@ -4,24 +4,24 @@ import { InjectRepository } from '@nestjs/typeorm';
import Stripe from 'stripe';
import { Not, Repository } from 'typeorm';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
import { BillingService } from 'src/engine/core-modules/billing/billing.service';
import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity';
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
import {
BillingSubscription,
SubscriptionInterval,
SubscriptionStatus,
} from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity';
import { User } from 'src/engine/core-modules/user/user.entity';
import { assert } from 'src/utils/assert';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
import {
FeatureFlagEntity,
FeatureFlagKeys,
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { BillingService } from 'src/engine/core-modules/billing/billing.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { assert } from 'src/utils/assert';
export enum AvailableProduct {
BasePlan = 'base-plan',
@ -219,6 +219,7 @@ export class BillingWorkspaceService {
async computeCheckoutSessionURL(
user: User,
workspace: Workspace,
priceId: string,
successUrlPath?: string,
): Promise<string> {
@ -228,7 +229,7 @@ export class BillingWorkspaceService {
: frontBaseUrl;
const quantity =
(await this.userWorkspaceService.getWorkspaceMemberCount()) || 1;
(await this.userWorkspaceService.getUserCount(workspace.id)) || 1;
const stripeCustomerId = (
await this.billingSubscriptionRepository.findOneBy({

View File

@ -1,11 +1,11 @@
import { Logger, Scope } from '@nestjs/common';
import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
export type UpdateSubscriptionJobData = { workspaceId: string };
@Processor({
@ -23,8 +23,9 @@ export class UpdateSubscriptionJob {
@Process(UpdateSubscriptionJob.name)
async handle(data: UpdateSubscriptionJobData): Promise<void> {
const workspaceMembersCount =
await this.userWorkspaceService.getWorkspaceMemberCount();
const workspaceMembersCount = await this.userWorkspaceService.getUserCount(
data.workspaceId,
);
if (!workspaceMembersCount || workspaceMembersCount <= 0) {
return;

View File

@ -1,20 +1,20 @@
/* eslint-disable @nx/workspace-inject-workspace-repository */
import { Injectable } from '@nestjs/common';
import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service';
import { SubscriptionStatus } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { KeyValuePairService } from 'src/engine/core-modules/key-value-pair/key-value-pair.service';
import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { SubscriptionStatus } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { isDefined } from 'src/utils/is-defined';
import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service';
enum OnboardingStepValues {
SKIPPED = 'SKIPPED',
@ -33,14 +33,13 @@ type OnboardingKeyValueType = {
@Injectable()
export class OnboardingService {
constructor(
private readonly twentyORMManager: TwentyORMManager,
private readonly billingWorkspaceService: BillingWorkspaceService,
private readonly workspaceManagerService: WorkspaceManagerService,
private readonly userWorkspaceService: UserWorkspaceService,
private readonly keyValuePairService: KeyValuePairService<OnboardingKeyValueType>,
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
private readonly connectedAccountRepository: ConnectedAccountRepository,
@InjectWorkspaceRepository(WorkspaceMemberWorkspaceEntity)
private readonly workspaceMemberRepository: WorkspaceRepository<WorkspaceMemberWorkspaceEntity>,
) {}
private async isSubscriptionIncompleteOnboardingStatus(user: User) {
@ -71,7 +70,12 @@ export class OnboardingService {
}
private async isProfileCreationOnboardingStatus(user: User) {
const workspaceMember = await this.workspaceMemberRepository.findOneBy({
const workspaceMemberRepository =
await this.twentyORMManager.getRepository<WorkspaceMemberWorkspaceEntity>(
'workspaceMember',
);
const workspaceMember = await workspaceMemberRepository.findOneBy({
userId: user.id,
});
@ -104,8 +108,9 @@ export class OnboardingService {
});
const isInviteTeamSkipped =
inviteTeamValue === OnboardingStepValues.SKIPPED;
const workspaceMemberCount =
await this.userWorkspaceService.getWorkspaceMemberCount();
const workspaceMemberCount = await this.userWorkspaceService.getUserCount(
workspace.id,
);
return (
!isInviteTeamSkipped &&

View File

@ -11,8 +11,6 @@ import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { assert } from 'src/utils/assert';
@ -22,8 +20,6 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> {
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
@InjectRepository(User, 'core')
private readonly userRepository: Repository<User>,
@InjectWorkspaceRepository(WorkspaceMemberWorkspaceEntity)
private readonly workspaceMemberRepository: WorkspaceRepository<WorkspaceMemberWorkspaceEntity>,
private readonly dataSourceService: DataSourceService,
private readonly typeORMService: TypeORMService,
private eventEmitter: EventEmitter2,
@ -107,13 +103,10 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> {
});
}
public async getWorkspaceMemberCount(): Promise<number | undefined> {
// TODO: to refactor, this could happen today for the first signup since the workspace does not exist yet
if (!this.workspaceMemberRepository) {
return undefined;
}
return await this.workspaceMemberRepository.count();
public async getUserCount(workspaceId): Promise<number | undefined> {
return await this.userWorkspaceRepository.countBy({
workspaceId,
});
}
async checkUserWorkspaceExists(

View File

@ -1,33 +1,33 @@
import { UseGuards } from '@nestjs/common';
import {
Resolver,
Query,
Args,
Mutation,
ResolveField,
Parent,
Query,
ResolveField,
Resolver,
} from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { FileUpload, GraphQLUpload } from 'graphql-upload';
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
import { streamToBuffer } from 'src/utils/stream-to-buffer';
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { assert } from 'src/utils/assert';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input';
import { User } from 'src/engine/core-modules/user/user.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service';
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input';
import { SendInviteLink } from 'src/engine/core-modules/workspace/dtos/send-invite-link.entity';
import { SendInviteLinkInput } from 'src/engine/core-modules/workspace/dtos/send-invite-link.input';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
import { assert } from 'src/utils/assert';
import { streamToBuffer } from 'src/utils/stream-to-buffer';
import { Workspace } from './workspace.entity';
@ -128,8 +128,10 @@ export class WorkspaceResolver {
}
@ResolveField(() => Number)
async workspaceMembersCount(): Promise<number | undefined> {
return await this.userWorkspaceService.getWorkspaceMemberCount();
async workspaceMembersCount(
@Parent() workspace: Workspace,
): Promise<number | undefined> {
return await this.userWorkspaceService.getUserCount(workspace.id);
}
@Mutation(() => SendInviteLink)

View File

@ -36,4 +36,8 @@ export class WorkspaceDataSource extends DataSource {
): WorkspaceEntityManager {
return new WorkspaceEntityManager(this.internalContext, this, queryRunner);
}
getWorkspaceId(): string {
return this.internalContext.workspaceId;
}
}

View File

@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common';
import { EntitySchema } from 'typeorm';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { EntitySchemaColumnFactory } from 'src/engine/twenty-orm/factories/entity-schema-column.factory';
import { EntitySchemaRelationFactory } from 'src/engine/twenty-orm/factories/entity-schema-relation.factory';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage';
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
@ -20,35 +20,7 @@ export class EntitySchemaFactory {
async create(
workspaceId: string,
objectMetadata: ObjectMetadataEntity,
): Promise<EntitySchema>;
async create(
workspaceId: string,
objectMetadataName: string,
): Promise<EntitySchema>;
async create(
workspaceId: string,
objectMetadataOrObjectMetadataName: ObjectMetadataEntity | string,
): Promise<EntitySchema> {
let objectMetadata: ObjectMetadataEntity | null =
typeof objectMetadataOrObjectMetadataName !== 'string'
? objectMetadataOrObjectMetadataName
: null;
if (typeof objectMetadataOrObjectMetadataName === 'string') {
objectMetadata =
(await this.workspaceCacheStorageService.getObjectMetadata(
workspaceId,
(objectMetadata) =>
objectMetadata.nameSingular === objectMetadataOrObjectMetadataName,
)) ?? null;
}
if (!objectMetadata) {
throw new Error('Object metadata not found');
}
const columns = this.entitySchemaColumnFactory.create(
workspaceId,
objectMetadata.fields,

View File

@ -54,9 +54,42 @@ export class TwentyORMManager {
throw new Error('Workspace data source not found');
}
const workspaceId = this.workspaceDataSource.getWorkspaceId();
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 objectMetadata = objectMetadataCollection.find(
(objectMetadata) => objectMetadata.nameSingular === objectMetadataName,
);
if (!objectMetadata) {
throw new Error('Object metadata not found');
}
const entitySchema = await this.entitySchemaFactory.create(
this.workspaceDataSource.internalContext.workspaceId,
objectMetadataName,
workspaceId,
objectMetadata,
);
if (!entitySchema) {
@ -95,38 +128,38 @@ export class TwentyORMManager {
);
}
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 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',
],
});
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(entities, workspaceId);
@ -135,9 +168,17 @@ export class TwentyORMManager {
(dataSource) => dataSource.destroy(),
);
const objectMetadata = objectMetadataCollection.find(
(objectMetadata) => objectMetadata.nameSingular === objectMetadataName,
);
if (!objectMetadata) {
throw new Error('Object metadata not found');
}
const entitySchema = await this.entitySchemaFactory.create(
workspaceId,
objectMetadataName,
objectMetadata,
);
if (!workspaceDataSource) {

View File

@ -6,9 +6,9 @@ import {
TwentyORMOptions,
} from 'src/engine/twenty-orm/interfaces/twenty-orm-options.interface';
import { createTwentyORMProviders } from 'src/engine/twenty-orm/twenty-orm.providers';
import { TwentyORMCoreModule } from 'src/engine/twenty-orm/twenty-orm-core.module';
// Todo: remove this file
@Global()
@Module({})
export class TwentyORMModule {
@ -19,8 +19,8 @@ export class TwentyORMModule {
};
}
static forFeature(objects: EntityClassOrSchema[] = []): DynamicModule {
const providers = createTwentyORMProviders(objects);
static forFeature(_objects: EntityClassOrSchema[] = []): DynamicModule {
const providers = [];
return {
module: TwentyORMModule,

View File

@ -1,44 +0,0 @@
import { Provider, Type } from '@nestjs/common';
import { EntityClassOrSchema } from '@nestjs/typeorm/dist/interfaces/entity-class-or-schema.type';
import { getWorkspaceRepositoryToken } from 'src/engine/twenty-orm/utils/get-workspace-repository-token.util';
import { TWENTY_ORM_WORKSPACE_DATASOURCE } from 'src/engine/twenty-orm/twenty-orm.constants';
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
/**
* Create providers for the given entities.
*/
export function createTwentyORMProviders(
objects?: EntityClassOrSchema[],
): Provider[] {
return (objects || []).map((object) => ({
provide: getWorkspaceRepositoryToken(object),
useFactory: async (
dataSource: WorkspaceDataSource | null,
entitySchemaFactory: EntitySchemaFactory,
) => {
const objectMetadataName = convertClassNameToObjectMetadataName(
(object as Type).name,
);
if (!dataSource) {
// TODO: Throw here when the code is well architected
return null;
}
const entitySchema = await entitySchemaFactory.create(
dataSource.internalContext.workspaceId,
objectMetadataName,
);
if (!entitySchema) {
throw new Error('Entity schema not found');
}
return dataSource.getRepository(entitySchema);
},
inject: [TWENTY_ORM_WORKSPACE_DATASOURCE, EntitySchemaFactory],
}));
}