[backend] rename repository services and replace repository modules by dynamicModule (#4536)
* rename database services to repository * refactor more repositories * more refactoring * followup * remove unused imports * fix * fix * Fix calendar listener being called when flag is off * remove folders
This commit is contained in:
@ -11,18 +11,14 @@ import { ObjectMetadataModule } from 'src/engine-metadata/object-metadata/object
|
|||||||
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
||||||
import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job';
|
import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job';
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||||
import { MessagingModule } from 'src/modules/messaging/messaging.module';
|
|
||||||
import { GmailPartialSyncJob } from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
import { GmailPartialSyncJob } from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
||||||
import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job';
|
import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job';
|
||||||
import { UserModule } from 'src/engine/modules/user/user.module';
|
import { UserModule } from 'src/engine/modules/user/user.module';
|
||||||
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
|
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
|
||||||
import { FetchAllWorkspacesMessagesJob } from 'src/modules/messaging/commands/crons/fetch-all-workspaces-messages.job';
|
import { FetchAllWorkspacesMessagesJob } from 'src/modules/messaging/commands/crons/fetch-all-workspaces-messages.job';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
|
||||||
import { MatchMessageParticipantJob } from 'src/modules/messaging/jobs/match-message-participant.job';
|
import { MatchMessageParticipantJob } from 'src/modules/messaging/jobs/match-message-participant.job';
|
||||||
import { CreateCompaniesAndContactsAfterSyncJob } from 'src/modules/messaging/jobs/create-companies-and-contacts-after-sync.job';
|
import { CreateCompaniesAndContactsAfterSyncJob } from 'src/modules/messaging/jobs/create-companies-and-contacts-after-sync.job';
|
||||||
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
||||||
import { MessageChannelModule } from 'src/modules/messaging/repositories/message-channel/message-channel.module';
|
|
||||||
import { MessageParticipantModule } from 'src/modules/messaging/repositories/message-participant/message-participant.module';
|
|
||||||
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
|
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
|
||||||
import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job';
|
import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job';
|
||||||
import { DeleteConnectedAccountAssociatedMessagingDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job';
|
import { DeleteConnectedAccountAssociatedMessagingDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job';
|
||||||
@ -33,27 +29,31 @@ import { UserWorkspaceModule } from 'src/engine/modules/user-workspace/user-work
|
|||||||
import { StripeModule } from 'src/engine/modules/billing/stripe/stripe.module';
|
import { StripeModule } from 'src/engine/modules/billing/stripe/stripe.module';
|
||||||
import { Workspace } from 'src/engine/modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/modules/workspace/workspace.entity';
|
||||||
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
import { CalendarModule } from 'src/modules/calendar/calendar.module';
|
|
||||||
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
||||||
import { GoogleCalendarFullSyncJob } from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
import { GoogleCalendarFullSyncJob } from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
||||||
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
||||||
import { RecordPositionBackfillJob } from 'src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job';
|
import { RecordPositionBackfillJob } from 'src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job';
|
||||||
import { RecordPositionBackfillModule } from 'src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-module';
|
import { RecordPositionBackfillModule } from 'src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-module';
|
||||||
import { DeleteConnectedAccountAssociatedCalendarDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-calendar-data.job';
|
import { DeleteConnectedAccountAssociatedCalendarDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-calendar-data.job';
|
||||||
|
import { GoogleCalendarFullSyncModule } from 'src/modules/calendar/services/google-calendar-full-sync.module';
|
||||||
|
import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module';
|
||||||
|
import { GmailFullSyncModule } from 'src/modules/messaging/services/gmail-full-sync/gmail-full-sync.module';
|
||||||
|
import { GmailPartialSyncModule } from 'src/modules/messaging/services/gmail-partial-sync/gmail-partial-sync.module';
|
||||||
|
import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
BillingModule,
|
BillingModule,
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
ConnectedAccountModule,
|
|
||||||
CreateCompaniesAndContactsModule,
|
CreateCompaniesAndContactsModule,
|
||||||
DataSeedDemoWorkspaceModule,
|
DataSeedDemoWorkspaceModule,
|
||||||
EnvironmentModule,
|
EnvironmentModule,
|
||||||
HttpModule,
|
HttpModule,
|
||||||
MessagingModule,
|
GoogleCalendarFullSyncModule,
|
||||||
MessageParticipantModule,
|
|
||||||
MessageChannelModule,
|
|
||||||
CalendarModule,
|
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
StripeModule,
|
StripeModule,
|
||||||
ThreadCleanerModule,
|
ThreadCleanerModule,
|
||||||
@ -65,6 +65,15 @@ import { DeleteConnectedAccountAssociatedCalendarDataJob } from 'src/modules/mes
|
|||||||
UserWorkspaceModule,
|
UserWorkspaceModule,
|
||||||
WorkspaceDataSourceModule,
|
WorkspaceDataSourceModule,
|
||||||
RecordPositionBackfillModule,
|
RecordPositionBackfillModule,
|
||||||
|
GoogleAPIRefreshAccessTokenModule,
|
||||||
|
GmailFullSyncModule,
|
||||||
|
GmailPartialSyncModule,
|
||||||
|
MessageParticipantModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
ConnectedAccountObjectMetadata,
|
||||||
|
MessageParticipantObjectMetadata,
|
||||||
|
MessageChannelObjectMetadata,
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
import { CalendarChannelEventAssociationRepository } from 'src/modules/calendar/repositories/calendar-channel-event-association.repository';
|
||||||
|
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
|
||||||
|
import { CalendarEventAttendeeRepository } from 'src/modules/calendar/repositories/calendar-event-attendee.repository';
|
||||||
|
import { CalendarEventRepository } from 'src/modules/calendar/repositories/calendar-event.repository';
|
||||||
|
import { CompanyRepository } from 'src/modules/company/repositories/company.repository';
|
||||||
|
import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository';
|
||||||
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
|
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository';
|
||||||
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
|
import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository';
|
||||||
|
import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository';
|
||||||
|
import { MessageRepository } from 'src/modules/messaging/repositories/message.repository';
|
||||||
|
import { PersonRepository } from 'src/modules/person/repositories/person.repository';
|
||||||
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
|
|
||||||
|
export const metadataToRepositoryMapping = {
|
||||||
|
BlocklistObjectMetadata: BlocklistRepository,
|
||||||
|
CalendarChannelEventAssociationObjectMetadata:
|
||||||
|
CalendarChannelEventAssociationRepository,
|
||||||
|
CalendarChannelObjectMetadata: CalendarChannelRepository,
|
||||||
|
CalendarEventAttendeeObjectMetadata: CalendarEventAttendeeRepository,
|
||||||
|
CalendarEventObjectMetadata: CalendarEventRepository,
|
||||||
|
CompanyObjectMetadata: CompanyRepository,
|
||||||
|
ConnectedAccountObjectMetadata: ConnectedAccountRepository,
|
||||||
|
MessageChannelMessageAssociationObjectMetadata:
|
||||||
|
MessageChannelMessageAssociationRepository,
|
||||||
|
MessageChannelObjectMetadata: MessageChannelRepository,
|
||||||
|
MessageObjectMetadata: MessageRepository,
|
||||||
|
MessageParticipantObjectMetadata: MessageParticipantRepository,
|
||||||
|
MessageThreadObjectMetadata: MessageThreadRepository,
|
||||||
|
PersonObjectMetadata: PersonRepository,
|
||||||
|
WorkspaceMemberObjectMetadata: WorkspaceMemberRepository,
|
||||||
|
};
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||||
|
import { capitalize } from 'src/utils/capitalize';
|
||||||
|
|
||||||
|
export const InjectObjectMetadataRepository = (objectMetadata: any) => {
|
||||||
|
const token = `${capitalize(
|
||||||
|
convertClassNameToObjectMetadataName(objectMetadata.name),
|
||||||
|
)}Repository`;
|
||||||
|
|
||||||
|
return Inject(token);
|
||||||
|
};
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { Global, Module, DynamicModule, Provider } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { metadataToRepositoryMapping } from 'src/engine/object-metadata-repository/metadata-to-repository.mapping';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||||
|
import { capitalize } from 'src/utils/capitalize';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({})
|
||||||
|
export class ObjectMetadataRepositoryModule {
|
||||||
|
static forFeature(objectMetadatas): DynamicModule {
|
||||||
|
const providers: Provider[] = objectMetadatas.map((objectMetadata) => {
|
||||||
|
const repositoryClass = metadataToRepositoryMapping[objectMetadata.name];
|
||||||
|
|
||||||
|
if (!repositoryClass) {
|
||||||
|
throw new Error(`No repository found for ${objectMetadata.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
provide: `${capitalize(
|
||||||
|
convertClassNameToObjectMetadataName(objectMetadata.name),
|
||||||
|
)}Repository`,
|
||||||
|
useFactory: (
|
||||||
|
workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
|
) => {
|
||||||
|
return new repositoryClass(workspaceDataSourceService);
|
||||||
|
},
|
||||||
|
inject: [WorkspaceDataSourceService],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
module: ObjectMetadataRepositoryModule,
|
||||||
|
imports: [WorkspaceDataSourceModule],
|
||||||
|
providers: [...providers],
|
||||||
|
exports: providers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,41 +1,8 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
|
||||||
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
|
|
||||||
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
|
||||||
import { BlocklistModule } from 'src/modules/connected-account/repositories/blocklist/blocklist.module';
|
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
|
||||||
import { CalendarChannelEventAssociationModule } from 'src/modules/calendar/repositories/calendar-channel-event-association/calendar-channel-event-assocation.module';
|
|
||||||
import { CalendarChannelModule } from 'src/modules/calendar/repositories/calendar-channel/calendar-channel.module';
|
|
||||||
import { CalendarEventAttendeeModule } from 'src/modules/calendar/repositories/calendar-event-attendee/calendar-event-attendee.module';
|
|
||||||
import { CalendarEventModule } from 'src/modules/calendar/repositories/calendar-event/calendar-event.module';
|
|
||||||
import { CalendarEventCleanerModule } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.module';
|
|
||||||
import { GoogleCalendarFullSyncService } from 'src/modules/calendar/services/google-calendar-full-sync.service';
|
|
||||||
import { GoogleCalendarClientProvider } from 'src/modules/calendar/services/providers/google-calendar/google-calendar.provider';
|
|
||||||
import { CompanyModule } from 'src/modules/messaging/repositories/company/company.module';
|
|
||||||
import { PersonModule } from 'src/modules/person/repositories/person/person.module';
|
|
||||||
import { WorkspaceMemberModule } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.module';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [],
|
||||||
EnvironmentModule,
|
providers: [],
|
||||||
WorkspaceDataSourceModule,
|
exports: [],
|
||||||
ConnectedAccountModule,
|
|
||||||
CalendarChannelModule,
|
|
||||||
CalendarChannelEventAssociationModule,
|
|
||||||
CalendarEventModule,
|
|
||||||
CalendarEventAttendeeModule,
|
|
||||||
CreateCompaniesAndContactsModule,
|
|
||||||
WorkspaceMemberModule,
|
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
|
||||||
CompanyModule,
|
|
||||||
PersonModule,
|
|
||||||
BlocklistModule,
|
|
||||||
CalendarEventCleanerModule,
|
|
||||||
],
|
|
||||||
providers: [GoogleCalendarFullSyncService, GoogleCalendarClientProvider],
|
|
||||||
exports: [GoogleCalendarFullSyncService],
|
|
||||||
})
|
})
|
||||||
export class CalendarModule {}
|
export class CalendarModule {}
|
||||||
|
|||||||
@ -4,11 +4,13 @@ import { Command, CommandRunner, Option } from 'nest-commander';
|
|||||||
|
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import {
|
import {
|
||||||
GoogleCalendarFullSyncJobData,
|
GoogleCalendarFullSyncJobData,
|
||||||
GoogleCalendarFullSyncJob,
|
GoogleCalendarFullSyncJob,
|
||||||
} from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
} from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
interface GoogleCalendarFullSyncOptions {
|
interface GoogleCalendarFullSyncOptions {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -23,7 +25,8 @@ export class GoogleCalendarFullSyncCommand extends CommandRunner {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -48,7 +51,7 @@ export class GoogleCalendarFullSyncCommand extends CommandRunner {
|
|||||||
|
|
||||||
private async fetchWorkspaceCalendars(workspaceId: string): Promise<void> {
|
private async fetchWorkspaceCalendars(workspaceId: string): Promise<void> {
|
||||||
const connectedAccounts =
|
const connectedAccounts =
|
||||||
await this.connectedAccountService.getAll(workspaceId);
|
await this.connectedAccountRepository.getAll(workspaceId);
|
||||||
|
|
||||||
for (const connectedAccount of connectedAccounts) {
|
for (const connectedAccount of connectedAccounts) {
|
||||||
await this.messageQueueService.add<GoogleCalendarFullSyncJobData>(
|
await this.messageQueueService.add<GoogleCalendarFullSyncJobData>(
|
||||||
|
|||||||
@ -1,18 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
|
||||||
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
|
||||||
import { GoogleCalendarFullSyncCommand } from 'src/modules/calendar/commands/google-calendar-full-sync.command';
|
import { GoogleCalendarFullSyncCommand } from 'src/modules/calendar/commands/google-calendar-full-sync.command';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
DataSourceModule,
|
ObjectMetadataRepositoryModule.forFeature([ConnectedAccountObjectMetadata]),
|
||||||
TypeORMModule,
|
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
|
||||||
ConnectedAccountModule,
|
|
||||||
],
|
],
|
||||||
providers: [GoogleCalendarFullSyncCommand],
|
providers: [GoogleCalendarFullSyncCommand],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { GoogleAPIsRefreshAccessTokenService } from 'src/modules/connected-account/services/google-apis-refresh-access-token.service';
|
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
||||||
import { GoogleCalendarFullSyncService } from 'src/modules/calendar/services/google-calendar-full-sync.service';
|
import { GoogleCalendarFullSyncService } from 'src/modules/calendar/services/google-calendar-full-sync.service';
|
||||||
|
|
||||||
export type GoogleCalendarFullSyncJobData = {
|
export type GoogleCalendarFullSyncJobData = {
|
||||||
@ -18,7 +18,7 @@ export class GoogleCalendarFullSyncJob
|
|||||||
private readonly logger = new Logger(GoogleCalendarFullSyncJob.name);
|
private readonly logger = new Logger(GoogleCalendarFullSyncJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIsRefreshAccessTokenService,
|
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService,
|
||||||
private readonly googleCalendarFullSyncService: GoogleCalendarFullSyncService,
|
private readonly googleCalendarFullSyncService: GoogleCalendarFullSyncService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calen
|
|||||||
import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/utils/getFlattenedValuesAndValuesStringForBatchRawQuery.util';
|
import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/utils/getFlattenedValuesAndValuesStringForBatchRawQuery.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CalendarChannelEventAssociationService {
|
export class CalendarChannelEventAssociationRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { CalendarChannelEventAssociationService } from 'src/modules/calendar/repositories/calendar-channel-event-association/calendar-channel-event-association.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [CalendarChannelEventAssociationService],
|
|
||||||
exports: [CalendarChannelEventAssociationService],
|
|
||||||
})
|
|
||||||
export class CalendarChannelEventAssociationModule {}
|
|
||||||
@ -7,7 +7,7 @@ import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-obj
|
|||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CalendarChannelService {
|
export class CalendarChannelRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { CalendarChannelService } from 'src/modules/calendar/repositories/calendar-channel/calendar-channel.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [CalendarChannelService],
|
|
||||||
exports: [CalendarChannelService],
|
|
||||||
})
|
|
||||||
export class CalendarChannelModule {}
|
|
||||||
@ -9,7 +9,7 @@ import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/c
|
|||||||
import { CalendarEventAttendee } from 'src/modules/calendar/types/calendar-event';
|
import { CalendarEventAttendee } from 'src/modules/calendar/types/calendar-event';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CalendarEventAttendeeService {
|
export class CalendarEventAttendeeRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { CalendarEventAttendeeService } from 'src/modules/calendar/repositories/calendar-event-attendee/calendar-event-attendee.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [CalendarEventAttendeeService],
|
|
||||||
exports: [CalendarEventAttendeeService],
|
|
||||||
})
|
|
||||||
export class CalendarEventAttendeeModule {}
|
|
||||||
@ -10,7 +10,7 @@ import { CalendarEvent } from 'src/modules/calendar/types/calendar-event';
|
|||||||
import { CalendarEventAttendeeObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-attendee.object-metadata';
|
import { CalendarEventAttendeeObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-attendee.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CalendarEventService {
|
export class CalendarEventRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { CalendarEventService } from 'src/modules/calendar/repositories/calendar-event/calendar-event.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [CalendarEventService],
|
|
||||||
exports: [CalendarEventService],
|
|
||||||
})
|
|
||||||
export class CalendarEventModule {}
|
|
||||||
@ -1,12 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
|
||||||
import { CalendarEventModule } from 'src/modules/calendar/repositories/calendar-event/calendar-event.module';
|
|
||||||
import { CalendarEventCleanerService } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service';
|
import { CalendarEventCleanerService } from 'src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service';
|
||||||
|
import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DataSourceModule, TypeORMModule, CalendarEventModule],
|
imports: [
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([CalendarEventObjectMetadata]),
|
||||||
|
],
|
||||||
providers: [CalendarEventCleanerService],
|
providers: [CalendarEventCleanerService],
|
||||||
exports: [CalendarEventCleanerService],
|
exports: [CalendarEventCleanerService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,20 +1,27 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { CalendarEventService } from 'src/modules/calendar/repositories/calendar-event/calendar-event.service';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { CalendarEventRepository } from 'src/modules/calendar/repositories/calendar-event.repository';
|
||||||
|
import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata';
|
||||||
import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util';
|
import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CalendarEventCleanerService {
|
export class CalendarEventCleanerService {
|
||||||
constructor(private readonly calendarEventService: CalendarEventService) {}
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(CalendarEventObjectMetadata)
|
||||||
|
private readonly calendarEventRepository: CalendarEventRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
public async cleanWorkspaceCalendarEvents(workspaceId: string) {
|
public async cleanWorkspaceCalendarEvents(workspaceId: string) {
|
||||||
await deleteUsingPagination(
|
await deleteUsingPagination(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
500,
|
500,
|
||||||
this.calendarEventService.getNonAssociatedCalendarEventIdsPaginated.bind(
|
this.calendarEventRepository.getNonAssociatedCalendarEventIdsPaginated.bind(
|
||||||
this.calendarEventService,
|
this.calendarEventRepository,
|
||||||
|
),
|
||||||
|
this.calendarEventRepository.deleteByIds.bind(
|
||||||
|
this.calendarEventRepository,
|
||||||
),
|
),
|
||||||
this.calendarEventService.deleteByIds.bind(this.calendarEventService),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { GoogleCalendarFullSyncService } from 'src/modules/calendar/services/google-calendar-full-sync.service';
|
||||||
|
import { CalendarProvidersModule } from 'src/modules/calendar/services/providers/calendar-providers.module';
|
||||||
|
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata';
|
||||||
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
|
import { CalendarEventAttendeeObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-attendee.object-metadata';
|
||||||
|
import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
CalendarProvidersModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
ConnectedAccountObjectMetadata,
|
||||||
|
CalendarEventObjectMetadata,
|
||||||
|
CalendarChannelObjectMetadata,
|
||||||
|
CalendarChannelEventAssociationObjectMetadata,
|
||||||
|
CalendarEventAttendeeObjectMetadata,
|
||||||
|
BlocklistObjectMetadata,
|
||||||
|
PersonObjectMetadata,
|
||||||
|
WorkspaceMemberObjectMetadata,
|
||||||
|
]),
|
||||||
|
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||||
|
WorkspaceDataSourceModule,
|
||||||
|
],
|
||||||
|
providers: [GoogleCalendarFullSyncService],
|
||||||
|
exports: [GoogleCalendarFullSyncService],
|
||||||
|
})
|
||||||
|
export class GoogleCalendarFullSyncModule {}
|
||||||
@ -3,23 +3,30 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
|
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { BlocklistService } from 'src/modules/connected-account/repositories/blocklist/blocklist.service';
|
import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository';
|
||||||
import {
|
import {
|
||||||
FeatureFlagEntity,
|
FeatureFlagEntity,
|
||||||
FeatureFlagKeys,
|
FeatureFlagKeys,
|
||||||
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
import { GoogleCalendarClientProvider } from 'src/modules/calendar/services/providers/google-calendar/google-calendar.provider';
|
import { GoogleCalendarClientProvider } from 'src/modules/calendar/services/providers/google-calendar/google-calendar.provider';
|
||||||
import { googleCalendarSearchFilterExcludeEmails } from 'src/modules/calendar/utils/google-calendar-search-filter.util';
|
import { googleCalendarSearchFilterExcludeEmails } from 'src/modules/calendar/utils/google-calendar-search-filter.util';
|
||||||
import { CalendarChannelEventAssociationService } from 'src/modules/calendar/repositories/calendar-channel-event-association/calendar-channel-event-association.service';
|
import { CalendarChannelEventAssociationRepository } from 'src/modules/calendar/repositories/calendar-channel-event-association.repository';
|
||||||
import { CalendarChannelService } from 'src/modules/calendar/repositories/calendar-channel/calendar-channel.service';
|
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
import { CalendarEventService } from 'src/modules/calendar/repositories/calendar-event/calendar-event.service';
|
import { CalendarEventRepository } from 'src/modules/calendar/repositories/calendar-event.repository';
|
||||||
import { formatGoogleCalendarEvent } from 'src/modules/calendar/utils/format-google-calendar-event.util';
|
import { formatGoogleCalendarEvent } from 'src/modules/calendar/utils/format-google-calendar-event.util';
|
||||||
import { GoogleCalendarFullSyncJobData } from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
import { GoogleCalendarFullSyncJobData } from 'src/modules/calendar/jobs/google-calendar-full-sync.job';
|
||||||
import { CalendarEventAttendeeService } from 'src/modules/calendar/repositories/calendar-event-attendee/calendar-event-attendee.service';
|
import { CalendarEventAttendeeRepository } from 'src/modules/calendar/repositories/calendar-event-attendee.repository';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata';
|
||||||
|
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
|
||||||
|
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata';
|
||||||
|
import { CalendarEventAttendeeObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-attendee.object-metadata';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleCalendarFullSyncService {
|
export class GoogleCalendarFullSyncService {
|
||||||
@ -29,12 +36,20 @@ export class GoogleCalendarFullSyncService {
|
|||||||
private readonly googleCalendarClientProvider: GoogleCalendarClientProvider,
|
private readonly googleCalendarClientProvider: GoogleCalendarClientProvider,
|
||||||
@Inject(MessageQueue.calendarQueue)
|
@Inject(MessageQueue.calendarQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
private readonly calendarEventService: CalendarEventService,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
private readonly calendarChannelService: CalendarChannelService,
|
@InjectObjectMetadataRepository(CalendarEventObjectMetadata)
|
||||||
private readonly calendarChannelEventAssociationService: CalendarChannelEventAssociationService,
|
private readonly calendarEventRepository: CalendarEventRepository,
|
||||||
private readonly calendarEventAttendeesService: CalendarEventAttendeeService,
|
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata)
|
||||||
private readonly blocklistService: BlocklistService,
|
private readonly calendarChannelRepository: CalendarChannelRepository,
|
||||||
|
@InjectObjectMetadataRepository(
|
||||||
|
CalendarChannelEventAssociationObjectMetadata,
|
||||||
|
)
|
||||||
|
private readonly calendarChannelEventAssociationRepository: CalendarChannelEventAssociationRepository,
|
||||||
|
@InjectObjectMetadataRepository(CalendarEventAttendeeObjectMetadata)
|
||||||
|
private readonly calendarEventAttendeesRepository: CalendarEventAttendeeRepository,
|
||||||
|
@InjectObjectMetadataRepository(BlocklistObjectMetadata)
|
||||||
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
@InjectRepository(FeatureFlagEntity, 'core')
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
@ -45,7 +60,7 @@ export class GoogleCalendarFullSyncService {
|
|||||||
connectedAccountId: string,
|
connectedAccountId: string,
|
||||||
pageToken?: string,
|
pageToken?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const connectedAccount = await this.connectedAccountService.getById(
|
const connectedAccount = await this.connectedAccountRepository.getById(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -64,7 +79,7 @@ export class GoogleCalendarFullSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const calendarChannel =
|
const calendarChannel =
|
||||||
await this.calendarChannelService.getFirstByConnectedAccountIdOrFail(
|
await this.calendarChannelRepository.getFirstByConnectedAccountIdOrFail(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -87,7 +102,7 @@ export class GoogleCalendarFullSyncService {
|
|||||||
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
||||||
|
|
||||||
const blocklist = isBlocklistEnabled
|
const blocklist = isBlocklistEnabled
|
||||||
? await this.blocklistService.getByWorkspaceMemberId(
|
? await this.blocklistRepository.getByWorkspaceMemberId(
|
||||||
workspaceMemberId,
|
workspaceMemberId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
)
|
)
|
||||||
@ -130,7 +145,7 @@ export class GoogleCalendarFullSyncService {
|
|||||||
startTime = Date.now();
|
startTime = Date.now();
|
||||||
|
|
||||||
const existingCalendarChannelEventAssociations =
|
const existingCalendarChannelEventAssociations =
|
||||||
await this.calendarChannelEventAssociationService.getByEventExternalIdsAndCalendarChannelId(
|
await this.calendarChannelEventAssociationRepository.getByEventExternalIdsAndCalendarChannelId(
|
||||||
eventExternalIds,
|
eventExternalIds,
|
||||||
calendarChannelId,
|
calendarChannelId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -180,7 +195,7 @@ export class GoogleCalendarFullSyncService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const iCalUIDCalendarEventIdMap =
|
const iCalUIDCalendarEventIdMap =
|
||||||
await this.calendarEventService.getICalUIDCalendarEventIdMap(
|
await this.calendarEventRepository.getICalUIDCalendarEventIdMap(
|
||||||
eventsToUpdate.map((event) => event.iCalUID),
|
eventsToUpdate.map((event) => event.iCalUID),
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -192,31 +207,31 @@ export class GoogleCalendarFullSyncService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
dataSourceMetadata?.transaction(async (transactionManager) => {
|
dataSourceMetadata?.transaction(async (transactionManager) => {
|
||||||
this.calendarEventService.saveCalendarEvents(
|
this.calendarEventRepository.saveCalendarEvents(
|
||||||
eventsToSave,
|
eventsToSave,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.calendarEventService.updateCalendarEvents(
|
this.calendarEventRepository.updateCalendarEvents(
|
||||||
eventsToUpdate,
|
eventsToUpdate,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.calendarChannelEventAssociationService.saveCalendarChannelEventAssociations(
|
this.calendarChannelEventAssociationRepository.saveCalendarChannelEventAssociations(
|
||||||
calendarChannelEventAssociationsToSave,
|
calendarChannelEventAssociationsToSave,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.calendarEventAttendeesService.saveCalendarEventAttendees(
|
this.calendarEventAttendeesRepository.saveCalendarEventAttendees(
|
||||||
attendeesToSave,
|
attendeesToSave,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.calendarEventAttendeesService.updateCalendarEventAttendees(
|
this.calendarEventAttendeesRepository.updateCalendarEventAttendees(
|
||||||
attendeesToUpdate,
|
attendeesToUpdate,
|
||||||
iCalUIDCalendarEventIdMap,
|
iCalUIDCalendarEventIdMap,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
|||||||
@ -11,9 +11,8 @@ export type CompanyToCreate = {
|
|||||||
city?: string;
|
city?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Move outside of the messaging module
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CompanyService {
|
export class CompanyRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,19 +1,20 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { PersonModule } from 'src/modules/person/repositories/person/person.module';
|
|
||||||
import { WorkspaceMemberModule } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.module';
|
|
||||||
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
||||||
import { CreateCompanyModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.module';
|
import { CreateCompanyModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.module';
|
||||||
import { CreateContactModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.module';
|
import { CreateContactModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
WorkspaceDataSourceModule,
|
|
||||||
CreateContactModule,
|
CreateContactModule,
|
||||||
CreateCompanyModule,
|
CreateCompanyModule,
|
||||||
WorkspaceMemberModule,
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
PersonModule,
|
PersonObjectMetadata,
|
||||||
|
WorkspaceMemberObjectMetadata,
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
providers: [CreateCompanyAndContactService],
|
providers: [CreateCompanyAndContactService],
|
||||||
exports: [CreateCompanyAndContactService],
|
exports: [CreateCompanyAndContactService],
|
||||||
|
|||||||
@ -7,19 +7,24 @@ import { Participant } from 'src/modules/messaging/types/gmail-message';
|
|||||||
import { getDomainNameFromHandle } from 'src/modules/messaging/utils/get-domain-name-from-handle.util';
|
import { getDomainNameFromHandle } from 'src/modules/messaging/utils/get-domain-name-from-handle.util';
|
||||||
import { CreateCompanyService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.service';
|
import { CreateCompanyService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.service';
|
||||||
import { CreateContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service';
|
import { CreateContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service';
|
||||||
import { PersonService } from 'src/modules/person/repositories/person/person.service';
|
import { PersonRepository } from 'src/modules/person/repositories/person.repository';
|
||||||
import { WorkspaceMemberService } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.service';
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
import { getUniqueParticipantsAndHandles } from 'src/modules/messaging/utils/get-unique-participants-and-handles.util';
|
import { getUniqueParticipantsAndHandles } from 'src/modules/messaging/utils/get-unique-participants-and-handles.util';
|
||||||
import { filterOutParticipantsFromCompanyOrWorkspace } from 'src/modules/messaging/utils/filter-out-participants-from-company-or-workspace.util';
|
import { filterOutParticipantsFromCompanyOrWorkspace } from 'src/modules/messaging/utils/filter-out-participants-from-company-or-workspace.util';
|
||||||
import { isWorkEmail } from 'src/utils/is-work-email';
|
import { isWorkEmail } from 'src/utils/is-work-email';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateCompanyAndContactService {
|
export class CreateCompanyAndContactService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly personService: PersonService,
|
|
||||||
private readonly createContactService: CreateContactService,
|
private readonly createContactService: CreateContactService,
|
||||||
private readonly createCompaniesService: CreateCompanyService,
|
private readonly createCompaniesService: CreateCompanyService,
|
||||||
private readonly workspaceMemberService: WorkspaceMemberService,
|
@InjectObjectMetadataRepository(PersonObjectMetadata)
|
||||||
|
private readonly personRepository: PersonRepository,
|
||||||
|
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata)
|
||||||
|
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createCompaniesAndContacts(
|
async createCompaniesAndContacts(
|
||||||
@ -36,7 +41,7 @@ export class CreateCompanyAndContactService {
|
|||||||
const isContactAutoCreationForNonWorkEmailsEnabled = false;
|
const isContactAutoCreationForNonWorkEmailsEnabled = false;
|
||||||
|
|
||||||
const workspaceMembers =
|
const workspaceMembers =
|
||||||
await this.workspaceMemberService.getAllByWorkspaceId(
|
await this.workspaceMemberRepository.getAllByWorkspaceId(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
@ -55,7 +60,7 @@ export class CreateCompanyAndContactService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const alreadyCreatedContacts = await this.personService.getByEmails(
|
const alreadyCreatedContacts = await this.personRepository.getByEmails(
|
||||||
uniqueHandles,
|
uniqueHandles,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata';
|
||||||
import { CreateCompanyService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.service';
|
import { CreateCompanyService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.service';
|
||||||
import { CompanyModule } from 'src/modules/messaging/repositories/company/company.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [WorkspaceDataSourceModule, CompanyModule],
|
imports: [ObjectMetadataRepositoryModule.forFeature([CompanyObjectMetadata])],
|
||||||
providers: [CreateCompanyService],
|
providers: [CreateCompanyService],
|
||||||
exports: [CreateCompanyService],
|
exports: [CreateCompanyService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -4,13 +4,18 @@ import { EntityManager } from 'typeorm';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import axios, { AxiosInstance } from 'axios';
|
import axios, { AxiosInstance } from 'axios';
|
||||||
|
|
||||||
import { CompanyService } from 'src/modules/messaging/repositories/company/company.service';
|
import { CompanyRepository } from 'src/modules/company/repositories/company.repository';
|
||||||
import { getCompanyNameFromDomainName } from 'src/modules/messaging/utils/get-company-name-from-domain-name.util';
|
import { getCompanyNameFromDomainName } from 'src/modules/messaging/utils/get-company-name-from-domain-name.util';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateCompanyService {
|
export class CreateCompanyService {
|
||||||
private readonly httpService: AxiosInstance;
|
private readonly httpService: AxiosInstance;
|
||||||
|
|
||||||
constructor(private readonly companyService: CompanyService) {
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(CompanyObjectMetadata)
|
||||||
|
private readonly companyRepository: CompanyRepository,
|
||||||
|
) {
|
||||||
this.httpService = axios.create({
|
this.httpService = axios.create({
|
||||||
baseURL: 'https://companies.twenty.com',
|
baseURL: 'https://companies.twenty.com',
|
||||||
});
|
});
|
||||||
@ -30,7 +35,7 @@ export class CreateCompanyService {
|
|||||||
const uniqueDomainNames = [...new Set(domainNames)];
|
const uniqueDomainNames = [...new Set(domainNames)];
|
||||||
|
|
||||||
const existingCompanies =
|
const existingCompanies =
|
||||||
await this.companyService.getExistingCompaniesByDomainNames(
|
await this.companyRepository.getExistingCompaniesByDomainNames(
|
||||||
uniqueDomainNames,
|
uniqueDomainNames,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
@ -80,7 +85,7 @@ export class CreateCompanyService {
|
|||||||
|
|
||||||
const { name, city } = await this.getCompanyInfoFromDomainName(domainName);
|
const { name, city } = await this.getCompanyInfoFromDomainName(domainName);
|
||||||
|
|
||||||
this.companyService.createCompany(
|
this.companyRepository.createCompany(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
{
|
{
|
||||||
id: companyId,
|
id: companyId,
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { CreateContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service';
|
import { CreateContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service';
|
||||||
import { PersonModule } from 'src/modules/person/repositories/person/person.module';
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [WorkspaceDataSourceModule, PersonModule],
|
imports: [ObjectMetadataRepositoryModule.forFeature([PersonObjectMetadata])],
|
||||||
providers: [CreateContactService],
|
providers: [CreateContactService],
|
||||||
exports: [CreateContactService],
|
exports: [CreateContactService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -3,8 +3,10 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { EntityManager } from 'typeorm';
|
import { EntityManager } from 'typeorm';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { PersonService } from 'src/modules/person/repositories/person/person.service';
|
import { PersonRepository } from 'src/modules/person/repositories/person.repository';
|
||||||
import { getFirstNameAndLastNameFromHandleAndDisplayName } from 'src/modules/messaging/utils/get-first-name-and-last-name-from-handle-and-display-name.util';
|
import { getFirstNameAndLastNameFromHandleAndDisplayName } from 'src/modules/messaging/utils/get-first-name-and-last-name-from-handle-and-display-name.util';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
|
||||||
type ContactToCreate = {
|
type ContactToCreate = {
|
||||||
handle: string;
|
handle: string;
|
||||||
@ -22,7 +24,10 @@ type FormattedContactToCreate = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateContactService {
|
export class CreateContactService {
|
||||||
constructor(private readonly personService: PersonService) {}
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(PersonObjectMetadata)
|
||||||
|
private readonly personRepository: PersonRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
public formatContacts(
|
public formatContacts(
|
||||||
contactsToCreate: ContactToCreate[],
|
contactsToCreate: ContactToCreate[],
|
||||||
@ -54,7 +59,7 @@ export class CreateContactService {
|
|||||||
|
|
||||||
const formattedContacts = this.formatContacts(contactsToCreate);
|
const formattedContacts = this.formatContacts(contactsToCreate);
|
||||||
|
|
||||||
await this.personService.createPeople(
|
await this.personRepository.createPeople(
|
||||||
formattedContacts,
|
formattedContacts,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metada
|
|||||||
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BlocklistService {
|
export class BlocklistRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { BlocklistService } from 'src/modules/connected-account/repositories/blocklist/blocklist.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [BlocklistService],
|
|
||||||
exports: [BlocklistService],
|
|
||||||
})
|
|
||||||
export class BlocklistModule {}
|
|
||||||
@ -7,7 +7,7 @@ import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/st
|
|||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConnectedAccountService {
|
export class ConnectedAccountRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [ConnectedAccountService],
|
|
||||||
exports: [ConnectedAccountService],
|
|
||||||
})
|
|
||||||
export class ConnectedAccountModule {}
|
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([ConnectedAccountObjectMetadata]),
|
||||||
|
],
|
||||||
|
providers: [GoogleAPIRefreshAccessTokenService],
|
||||||
|
exports: [GoogleAPIRefreshAccessTokenService],
|
||||||
|
})
|
||||||
|
export class GoogleAPIRefreshAccessTokenModule {}
|
||||||
@ -3,20 +3,23 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleAPIsRefreshAccessTokenService {
|
export class GoogleAPIRefreshAccessTokenService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async refreshAndSaveAccessToken(
|
async refreshAndSaveAccessToken(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
connectedAccountId: string,
|
connectedAccountId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const connectedAccount = await this.connectedAccountService.getById(
|
const connectedAccount = await this.connectedAccountRepository.getById(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -37,7 +40,7 @@ export class GoogleAPIsRefreshAccessTokenService {
|
|||||||
|
|
||||||
const accessToken = await this.refreshAccessToken(refreshToken);
|
const accessToken = await this.refreshAccessToken(refreshToken);
|
||||||
|
|
||||||
await this.connectedAccountService.updateAccessToken(
|
await this.connectedAccountRepository.updateAccessToken(
|
||||||
accessToken,
|
accessToken,
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -7,13 +7,15 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface
|
|||||||
|
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { Workspace } from 'src/engine/modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/modules/workspace/workspace.entity';
|
||||||
import {
|
import {
|
||||||
GmailPartialSyncJobData,
|
GmailPartialSyncJobData,
|
||||||
GmailPartialSyncJob,
|
GmailPartialSyncJob,
|
||||||
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
||||||
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FetchAllWorkspacesMessagesJob
|
export class FetchAllWorkspacesMessagesJob
|
||||||
@ -28,7 +30,8 @@ export class FetchAllWorkspacesMessagesJob
|
|||||||
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
@ -59,7 +62,7 @@ export class FetchAllWorkspacesMessagesJob
|
|||||||
private async fetchWorkspaceMessages(workspaceId: string): Promise<void> {
|
private async fetchWorkspaceMessages(workspaceId: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const connectedAccounts =
|
const connectedAccounts =
|
||||||
await this.connectedAccountService.getAll(workspaceId);
|
await this.connectedAccountRepository.getAll(workspaceId);
|
||||||
|
|
||||||
for (const connectedAccount of connectedAccounts) {
|
for (const connectedAccount of connectedAccounts) {
|
||||||
await this.messageQueueService.add<GmailPartialSyncJobData>(
|
await this.messageQueueService.add<GmailPartialSyncJobData>(
|
||||||
|
|||||||
@ -1,21 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
|
||||||
import { GmailFullSyncCommand } from 'src/modules/messaging/commands/gmail-full-sync.command';
|
import { GmailFullSyncCommand } from 'src/modules/messaging/commands/gmail-full-sync.command';
|
||||||
import { GmailPartialSyncCommand } from 'src/modules/messaging/commands/gmail-partial-sync.command';
|
import { GmailPartialSyncCommand } from 'src/modules/messaging/commands/gmail-partial-sync.command';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
|
||||||
import { StartFetchAllWorkspacesMessagesCronCommand } from 'src/modules/messaging/commands/start-fetch-all-workspaces-messages.cron.command';
|
import { StartFetchAllWorkspacesMessagesCronCommand } from 'src/modules/messaging/commands/start-fetch-all-workspaces-messages.cron.command';
|
||||||
import { StopFetchAllWorkspacesMessagesCronCommand } from 'src/modules/messaging/commands/stop-fetch-all-workspaces-messages.cron.command';
|
import { StopFetchAllWorkspacesMessagesCronCommand } from 'src/modules/messaging/commands/stop-fetch-all-workspaces-messages.cron.command';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
DataSourceModule,
|
ObjectMetadataRepositoryModule.forFeature([ConnectedAccountObjectMetadata]),
|
||||||
TypeORMModule,
|
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
|
||||||
ConnectedAccountModule,
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
GmailFullSyncCommand,
|
GmailFullSyncCommand,
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import {
|
|||||||
GmailFullSyncJobData,
|
GmailFullSyncJobData,
|
||||||
GmailFullSyncJob,
|
GmailFullSyncJob,
|
||||||
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
|
||||||
interface GmailFullSyncOptions {
|
interface GmailFullSyncOptions {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -22,7 +24,8 @@ export class GmailFullSyncCommand extends CommandRunner {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -47,7 +50,7 @@ export class GmailFullSyncCommand extends CommandRunner {
|
|||||||
|
|
||||||
private async fetchWorkspaceMessages(workspaceId: string): Promise<void> {
|
private async fetchWorkspaceMessages(workspaceId: string): Promise<void> {
|
||||||
const connectedAccounts =
|
const connectedAccounts =
|
||||||
await this.connectedAccountService.getAll(workspaceId);
|
await this.connectedAccountRepository.getAll(workspaceId);
|
||||||
|
|
||||||
for (const connectedAccount of connectedAccounts) {
|
for (const connectedAccount of connectedAccounts) {
|
||||||
await this.messageQueueService.add<GmailFullSyncJobData>(
|
await this.messageQueueService.add<GmailFullSyncJobData>(
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import {
|
|||||||
GmailPartialSyncJob,
|
GmailPartialSyncJob,
|
||||||
GmailPartialSyncJobData,
|
GmailPartialSyncJobData,
|
||||||
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-partial-sync.job';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
|
|
||||||
interface GmailPartialSyncOptions {
|
interface GmailPartialSyncOptions {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -22,7 +24,8 @@ export class GmailPartialSyncCommand extends CommandRunner {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountService: ConnectedAccountRepository,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,13 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
import { MessageParticipantService } from 'src/modules/messaging/repositories/message-participant/message-participant.service';
|
import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository';
|
||||||
|
import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata';
|
||||||
|
|
||||||
export type CreateCompaniesAndContactsAfterSyncJobData = {
|
export type CreateCompaniesAndContactsAfterSyncJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -20,8 +24,11 @@ export class CreateCompaniesAndContactsAfterSyncJob
|
|||||||
);
|
);
|
||||||
constructor(
|
constructor(
|
||||||
private readonly createCompaniesAndContactsService: CreateCompanyAndContactService,
|
private readonly createCompaniesAndContactsService: CreateCompanyAndContactService,
|
||||||
private readonly messageChannelService: MessageChannelService,
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
|
private readonly messageChannelService: MessageChannelRepository,
|
||||||
private readonly messageParticipantService: MessageParticipantService,
|
private readonly messageParticipantService: MessageParticipantService,
|
||||||
|
@InjectObjectMetadataRepository(MessageParticipantObjectMetadata)
|
||||||
|
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(
|
async handle(
|
||||||
@ -44,7 +51,7 @@ export class CreateCompaniesAndContactsAfterSyncJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
const messageParticipantsWithoutPersonIdAndWorkspaceMemberId =
|
const messageParticipantsWithoutPersonIdAndWorkspaceMemberId =
|
||||||
await this.messageParticipantService.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
||||||
messageChannelId,
|
messageChannelId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { GoogleAPIsRefreshAccessTokenService } from 'src/modules/connected-account/services/google-apis-refresh-access-token.service';
|
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
||||||
import { GmailFullSyncService } from 'src/modules/messaging/services/gmail-full-sync.service';
|
import { GmailFullSyncService } from 'src/modules/messaging/services/gmail-full-sync/gmail-full-sync.service';
|
||||||
|
|
||||||
export type GmailFullSyncJobData = {
|
export type GmailFullSyncJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -16,7 +16,7 @@ export class GmailFullSyncJob implements MessageQueueJob<GmailFullSyncJobData> {
|
|||||||
private readonly logger = new Logger(GmailFullSyncJob.name);
|
private readonly logger = new Logger(GmailFullSyncJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIsRefreshAccessTokenService,
|
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService,
|
||||||
private readonly gmailFullSyncService: GmailFullSyncService,
|
private readonly gmailFullSyncService: GmailFullSyncService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { GoogleAPIsRefreshAccessTokenService } from 'src/modules/connected-account/services/google-apis-refresh-access-token.service';
|
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service';
|
||||||
import { GmailPartialSyncService } from 'src/modules/messaging/services/gmail-partial-sync.service';
|
import { GmailPartialSyncService } from 'src/modules/messaging/services/gmail-partial-sync/gmail-partial-sync.service';
|
||||||
|
|
||||||
export type GmailPartialSyncJobData = {
|
export type GmailPartialSyncJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -17,7 +17,7 @@ export class GmailPartialSyncJob
|
|||||||
private readonly logger = new Logger(GmailPartialSyncJob.name);
|
private readonly logger = new Logger(GmailPartialSyncJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIsRefreshAccessTokenService,
|
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService,
|
||||||
private readonly gmailPartialSyncService: GmailPartialSyncService,
|
private readonly gmailPartialSyncService: GmailPartialSyncService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,9 @@ import { Injectable } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { MessageParticipantService } from 'src/modules/messaging/repositories/message-participant/message-participant.service';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository';
|
||||||
|
import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata';
|
||||||
|
|
||||||
export type MatchMessageParticipantsJobData = {
|
export type MatchMessageParticipantsJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -16,28 +18,32 @@ export class MatchMessageParticipantJob
|
|||||||
implements MessageQueueJob<MatchMessageParticipantsJobData>
|
implements MessageQueueJob<MatchMessageParticipantsJobData>
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
private readonly messageParticipantService: MessageParticipantService,
|
@InjectObjectMetadataRepository(MessageParticipantObjectMetadata)
|
||||||
|
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(data: MatchMessageParticipantsJobData): Promise<void> {
|
async handle(data: MatchMessageParticipantsJobData): Promise<void> {
|
||||||
const { workspaceId, personId, workspaceMemberId, email } = data;
|
const { workspaceId, personId, workspaceMemberId, email } = data;
|
||||||
|
|
||||||
const messageParticipantsToUpdate =
|
const messageParticipantsToUpdate =
|
||||||
await this.messageParticipantService.getByHandles([email], workspaceId);
|
await this.messageParticipantRepository.getByHandles(
|
||||||
|
[email],
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
const messageParticipantIdsToUpdate = messageParticipantsToUpdate.map(
|
const messageParticipantIdsToUpdate = messageParticipantsToUpdate.map(
|
||||||
(participant) => participant.id,
|
(participant) => participant.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (personId) {
|
if (personId) {
|
||||||
await this.messageParticipantService.updateParticipantsPersonId(
|
await this.messageParticipantRepository.updateParticipantsPersonId(
|
||||||
messageParticipantIdsToUpdate,
|
messageParticipantIdsToUpdate,
|
||||||
personId,
|
personId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (workspaceMemberId) {
|
if (workspaceMemberId) {
|
||||||
await this.messageParticipantService.updateParticipantsWorkspaceMemberId(
|
await this.messageParticipantRepository.updateParticipantsWorkspaceMemberId(
|
||||||
messageParticipantIdsToUpdate,
|
messageParticipantIdsToUpdate,
|
||||||
workspaceMemberId,
|
workspaceMemberId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { OnEvent } from '@nestjs/event-emitter';
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event';
|
import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
@ -13,6 +16,10 @@ import {
|
|||||||
DeleteConnectedAccountAssociatedMessagingDataJob,
|
DeleteConnectedAccountAssociatedMessagingDataJob,
|
||||||
} from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job';
|
} from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job';
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import {
|
||||||
|
FeatureFlagEntity,
|
||||||
|
FeatureFlagKeys,
|
||||||
|
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessagingConnectedAccountListener {
|
export class MessagingConnectedAccountListener {
|
||||||
@ -21,12 +28,20 @@ export class MessagingConnectedAccountListener {
|
|||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
@Inject(MessageQueue.calendarQueue)
|
@Inject(MessageQueue.calendarQueue)
|
||||||
private readonly calendarQueueService: MessageQueueService,
|
private readonly calendarQueueService: MessageQueueService,
|
||||||
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('connectedAccount.deleted')
|
@OnEvent('connectedAccount.deleted')
|
||||||
handleDeletedEvent(
|
async handleDeletedEvent(
|
||||||
payload: ObjectRecordDeleteEvent<ConnectedAccountObjectMetadata>,
|
payload: ObjectRecordDeleteEvent<ConnectedAccountObjectMetadata>,
|
||||||
) {
|
) {
|
||||||
|
const isCalendarEnabled = await this.featureFlagRepository.findOneBy({
|
||||||
|
workspaceId: payload.workspaceId,
|
||||||
|
key: FeatureFlagKeys.IsCalendarEnabled,
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
|
||||||
this.messageQueueService.add<DeleteConnectedAccountAssociatedMessagingDataJobData>(
|
this.messageQueueService.add<DeleteConnectedAccountAssociatedMessagingDataJobData>(
|
||||||
DeleteConnectedAccountAssociatedMessagingDataJob.name,
|
DeleteConnectedAccountAssociatedMessagingDataJob.name,
|
||||||
{
|
{
|
||||||
@ -35,12 +50,14 @@ export class MessagingConnectedAccountListener {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.calendarQueueService.add<DeleteConnectedAccountAssociatedCalendarDataJobData>(
|
if (isCalendarEnabled) {
|
||||||
DeleteConnectedAccountAssociatedCalendarDataJob.name,
|
this.calendarQueueService.add<DeleteConnectedAccountAssociatedCalendarDataJobData>(
|
||||||
{
|
DeleteConnectedAccountAssociatedCalendarDataJob.name,
|
||||||
workspaceId: payload.workspaceId,
|
{
|
||||||
connectedAccountId: payload.deletedRecord.id,
|
workspaceId: payload.workspaceId,
|
||||||
},
|
connectedAccountId: payload.deletedRecord.id,
|
||||||
);
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,76 +1,19 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { HttpModule } from '@nestjs/axios';
|
|
||||||
|
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
|
||||||
import { MessageChannelMessageAssociationModule } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module';
|
|
||||||
import { MessageChannelModule } from 'src/modules/messaging/repositories/message-channel/message-channel.module';
|
|
||||||
import { MessageThreadModule } from 'src/modules/messaging/repositories/message-thread/message-thread.module';
|
|
||||||
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
|
|
||||||
import { MessagingPersonListener } from 'src/modules/messaging/listeners/messaging-person.listener';
|
import { MessagingPersonListener } from 'src/modules/messaging/listeners/messaging-person.listener';
|
||||||
import { MessageModule } from 'src/modules/messaging/repositories/message/message.module';
|
|
||||||
import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider';
|
|
||||||
import { CreateContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service';
|
|
||||||
import { CreateCompanyService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company/create-company.service';
|
|
||||||
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches.service';
|
|
||||||
import { GmailFullSyncService } from 'src/modules/messaging/services/gmail-full-sync.service';
|
|
||||||
import { GmailPartialSyncService } from 'src/modules/messaging/services/gmail-partial-sync.service';
|
|
||||||
import { GoogleAPIsRefreshAccessTokenService } from 'src/modules/connected-account/services/google-apis-refresh-access-token.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
import { MessageParticipantModule } from 'src/modules/messaging/repositories/message-participant/message-participant.module';
|
|
||||||
import { MessagingWorkspaceMemberListener } from 'src/modules/messaging/listeners/messaging-workspace-member.listener';
|
import { MessagingWorkspaceMemberListener } from 'src/modules/messaging/listeners/messaging-workspace-member.listener';
|
||||||
import { MessagingMessageChannelListener } from 'src/modules/messaging/listeners/messaging-message-channel.listener';
|
import { MessagingMessageChannelListener } from 'src/modules/messaging/listeners/messaging-message-channel.listener';
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
import { WorkspaceMemberModule } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.module';
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
|
||||||
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
|
||||||
import { CompanyModule } from 'src/modules/messaging/repositories/company/company.module';
|
|
||||||
import { PersonModule } from 'src/modules/person/repositories/person/person.module';
|
|
||||||
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-messages-and-create-contacts.service';
|
|
||||||
import { MessagingConnectedAccountListener } from 'src/modules/messaging/listeners/messaging-connected-account.listener';
|
import { MessagingConnectedAccountListener } from 'src/modules/messaging/listeners/messaging-connected-account.listener';
|
||||||
import { BlocklistModule } from 'src/modules/connected-account/repositories/blocklist/blocklist.module';
|
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch.service';
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [TypeOrmModule.forFeature([FeatureFlagEntity], 'core')],
|
||||||
EnvironmentModule,
|
|
||||||
WorkspaceDataSourceModule,
|
|
||||||
ConnectedAccountModule,
|
|
||||||
MessageChannelModule,
|
|
||||||
MessageChannelMessageAssociationModule,
|
|
||||||
MessageModule,
|
|
||||||
MessageThreadModule,
|
|
||||||
MessageParticipantModule,
|
|
||||||
CreateCompaniesAndContactsModule,
|
|
||||||
WorkspaceMemberModule,
|
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
|
||||||
CompanyModule,
|
|
||||||
PersonModule,
|
|
||||||
BlocklistModule,
|
|
||||||
HttpModule.register({
|
|
||||||
baseURL: 'https://www.googleapis.com/batch/gmail/v1',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
providers: [
|
providers: [
|
||||||
GmailFullSyncService,
|
|
||||||
GmailPartialSyncService,
|
|
||||||
FetchMessagesByBatchesService,
|
|
||||||
GoogleAPIsRefreshAccessTokenService,
|
|
||||||
GmailClientProvider,
|
|
||||||
CreateContactService,
|
|
||||||
CreateCompanyService,
|
|
||||||
MessagingPersonListener,
|
MessagingPersonListener,
|
||||||
MessagingWorkspaceMemberListener,
|
MessagingWorkspaceMemberListener,
|
||||||
MessagingMessageChannelListener,
|
MessagingMessageChannelListener,
|
||||||
MessageService,
|
|
||||||
SaveMessagesAndCreateContactsService,
|
|
||||||
MessagingConnectedAccountListener,
|
MessagingConnectedAccountListener,
|
||||||
FetchByBatchesService,
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
GmailPartialSyncService,
|
|
||||||
GmailFullSyncService,
|
|
||||||
GoogleAPIsRefreshAccessTokenService,
|
|
||||||
FetchByBatchesService,
|
|
||||||
],
|
],
|
||||||
|
exports: [],
|
||||||
})
|
})
|
||||||
export class MessagingModule {}
|
export class MessagingModule {}
|
||||||
|
|||||||
@ -10,18 +10,29 @@ import { groupBy } from 'lodash';
|
|||||||
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
||||||
import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { MessageChannelMessageAssociationService } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository';
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { WorkspaceMemberService } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.service';
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
|
export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationService,
|
@InjectObjectMetadataRepository(
|
||||||
private readonly messageChannelService: MessageChannelService,
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
)
|
||||||
private readonly workspaceMemberService: WorkspaceMemberService,
|
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
|
private readonly messageChannelService: MessageChannelRepository,
|
||||||
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
|
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata)
|
||||||
|
private readonly workspaceMemberService: WorkspaceMemberRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
@ -75,7 +86,7 @@ export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
|
|||||||
await this.workspaceMemberService.getByIdOrFail(userId, workspaceId);
|
await this.workspaceMemberService.getByIdOrFail(userId, workspaceId);
|
||||||
|
|
||||||
const messageChannelsConnectedAccounts =
|
const messageChannelsConnectedAccounts =
|
||||||
await this.connectedAccountService.getByIds(
|
await this.connectedAccountRepository.getByIds(
|
||||||
messageChannels.map((channel) => channel.connectedAccountId),
|
messageChannels.map((channel) => channel.connectedAccountId),
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,17 +2,20 @@ import { Module } from '@nestjs/common';
|
|||||||
|
|
||||||
import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook';
|
import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook';
|
||||||
import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook';
|
import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/repositories/connected-account/connected-account.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { MessageChannelMessageAssociationModule } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module';
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
import { MessageChannelModule } from 'src/modules/messaging/repositories/message-channel/message-channel.module';
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
import { WorkspaceMemberModule } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.module';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
MessageChannelMessageAssociationModule,
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
MessageChannelModule,
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
ConnectedAccountModule,
|
MessageChannelObjectMetadata,
|
||||||
WorkspaceMemberModule,
|
ConnectedAccountObjectMetadata,
|
||||||
|
WorkspaceMemberObjectMetadata,
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { CompanyService } from 'src/modules/messaging/repositories/company/company.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
// TODO: Move outside of the messaging module
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [CompanyService],
|
|
||||||
exports: [CompanyService],
|
|
||||||
})
|
|
||||||
export class CompanyModule {}
|
|
||||||
@ -7,7 +7,7 @@ import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/mess
|
|||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessageChannelMessageAssociationService {
|
export class MessageChannelMessageAssociationRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -192,4 +192,30 @@ export class MessageChannelMessageAssociationService {
|
|||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async insert(
|
||||||
|
messageChannelId: string,
|
||||||
|
messageId: string,
|
||||||
|
messageExternalId: string,
|
||||||
|
messageThreadId: string,
|
||||||
|
messageThreadExternalId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`INSERT INTO ${dataSourceSchema}."messageChannelMessageAssociation" ("messageChannelId", "messageId", "messageExternalId", "messageThreadId", "messageThreadExternalId") VALUES ($1, $2, $3, $4, $5)`,
|
||||||
|
[
|
||||||
|
messageChannelId,
|
||||||
|
messageId,
|
||||||
|
messageExternalId,
|
||||||
|
messageThreadId,
|
||||||
|
messageThreadExternalId,
|
||||||
|
],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { MessageChannelMessageAssociationService } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [MessageChannelMessageAssociationService],
|
|
||||||
exports: [MessageChannelMessageAssociationService],
|
|
||||||
})
|
|
||||||
export class MessageChannelMessageAssociationModule {}
|
|
||||||
@ -7,7 +7,7 @@ import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-obj
|
|||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessageChannelService {
|
export class MessageChannelRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [MessageChannelService],
|
|
||||||
exports: [MessageChannelService],
|
|
||||||
})
|
|
||||||
export class MessageChannelModule {}
|
|
||||||
@ -9,13 +9,11 @@ import {
|
|||||||
ParticipantWithId,
|
ParticipantWithId,
|
||||||
ParticipantWithMessageId,
|
ParticipantWithMessageId,
|
||||||
} from 'src/modules/messaging/types/gmail-message';
|
} from 'src/modules/messaging/types/gmail-message';
|
||||||
import { PersonService } from 'src/modules/person/repositories/person/person.service';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessageParticipantService {
|
export class MessageParticipantRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
private readonly personService: PersonService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getByHandles(
|
public async getByHandles(
|
||||||
@ -195,45 +193,4 @@ export class MessageParticipantService {
|
|||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateMessageParticipantsAfterPeopleCreation(
|
|
||||||
participants: ParticipantWithId[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
if (!participants) return;
|
|
||||||
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const handles = participants.map((participant) => participant.handle);
|
|
||||||
|
|
||||||
const participantPersonIds = await this.personService.getByEmails(
|
|
||||||
handles,
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
const messageParticipantsToUpdate = participants.map((participant) => [
|
|
||||||
participant.id,
|
|
||||||
participantPersonIds.find(
|
|
||||||
(e: { id: string; email: string }) => e.email === participant.handle,
|
|
||||||
)?.id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (messageParticipantsToUpdate.length === 0) return;
|
|
||||||
|
|
||||||
const valuesString = messageParticipantsToUpdate
|
|
||||||
.map((_, index) => `($${index * 2 + 1}::uuid, $${index * 2 + 2}::uuid)`)
|
|
||||||
.join(', ');
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" AS "messageParticipant" SET "personId" = "data"."personId"
|
|
||||||
FROM (VALUES ${valuesString}) AS "data"("id", "personId")
|
|
||||||
WHERE "messageParticipant"."id" = "data"."id"`,
|
|
||||||
messageParticipantsToUpdate.flat(),
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { MessageParticipantService } from 'src/modules/messaging/repositories/message-participant/message-participant.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
import { PersonModule } from 'src/modules/person/repositories/person/person.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule, PersonModule],
|
|
||||||
providers: [MessageParticipantService],
|
|
||||||
exports: [MessageParticipantService],
|
|
||||||
})
|
|
||||||
export class MessageParticipantModule {}
|
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MessageThreadRepository {
|
||||||
|
constructor(
|
||||||
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async getOrphanThreadIdsPaginated(
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<string[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
const orphanThreads = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT mt.id
|
||||||
|
FROM ${dataSourceSchema}."messageThread" mt
|
||||||
|
LEFT JOIN ${dataSourceSchema}."message" m ON mt.id = m."messageThreadId"
|
||||||
|
WHERE m."messageThreadId" IS NULL
|
||||||
|
LIMIT $1 OFFSET $2`,
|
||||||
|
[limit, offset],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
return orphanThreads.map(({ id }) => id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteByIds(
|
||||||
|
messageThreadIds: string[],
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`DELETE FROM ${dataSourceSchema}."messageThread" WHERE id = ANY($1)`,
|
||||||
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async insert(
|
||||||
|
messageThreadId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`INSERT INTO ${dataSourceSchema}."messageThread" (id) VALUES ($1)`,
|
||||||
|
[messageThreadId],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +0,0 @@
|
|||||||
import { Module, forwardRef } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { MessageChannelMessageAssociationModule } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module';
|
|
||||||
import { MessageThreadService } from 'src/modules/messaging/repositories/message-thread/message-thread.service';
|
|
||||||
import { MessageModule } from 'src/modules/messaging/repositories/message/message.module';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [
|
|
||||||
WorkspaceDataSourceModule,
|
|
||||||
MessageChannelMessageAssociationModule,
|
|
||||||
forwardRef(() => MessageModule),
|
|
||||||
],
|
|
||||||
providers: [MessageThreadService],
|
|
||||||
exports: [MessageThreadService],
|
|
||||||
})
|
|
||||||
export class MessageThreadModule {}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
import { Inject, Injectable, forwardRef } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
|
||||||
import { MessageChannelMessageAssociationService } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageThreadService {
|
|
||||||
constructor(
|
|
||||||
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationService,
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
@Inject(forwardRef(() => MessageService))
|
|
||||||
private readonly messageService: MessageService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async getOrphanThreadIdsPaginated(
|
|
||||||
limit: number,
|
|
||||||
offset: number,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<string[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const orphanThreads = await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT mt.id
|
|
||||||
FROM ${dataSourceSchema}."messageThread" mt
|
|
||||||
LEFT JOIN ${dataSourceSchema}."message" m ON mt.id = m."messageThreadId"
|
|
||||||
WHERE m."messageThreadId" IS NULL
|
|
||||||
LIMIT $1 OFFSET $2`,
|
|
||||||
[limit, offset],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return orphanThreads.map(({ id }) => id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deleteByIds(
|
|
||||||
messageThreadIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`DELETE FROM ${dataSourceSchema}."messageThread" WHERE id = ANY($1)`,
|
|
||||||
[messageThreadIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async saveMessageThreadOrReturnExistingMessageThread(
|
|
||||||
headerMessageId: string,
|
|
||||||
messageThreadExternalId: string,
|
|
||||||
dataSourceMetadata: DataSourceEntity,
|
|
||||||
workspaceId: string,
|
|
||||||
manager: EntityManager,
|
|
||||||
) {
|
|
||||||
// Check if message thread already exists via threadExternalId
|
|
||||||
const existingMessageChannelMessageAssociationByMessageThreadExternalId =
|
|
||||||
await this.messageChannelMessageAssociationService.getFirstByMessageThreadExternalId(
|
|
||||||
messageThreadExternalId,
|
|
||||||
workspaceId,
|
|
||||||
manager,
|
|
||||||
);
|
|
||||||
|
|
||||||
const existingMessageThread =
|
|
||||||
existingMessageChannelMessageAssociationByMessageThreadExternalId?.messageThreadId;
|
|
||||||
|
|
||||||
if (existingMessageThread) {
|
|
||||||
return Promise.resolve(existingMessageThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if message thread already exists via existing message headerMessageId
|
|
||||||
const existingMessageWithSameHeaderMessageId =
|
|
||||||
await this.messageService.getFirstOrNullByHeaderMessageId(
|
|
||||||
headerMessageId,
|
|
||||||
workspaceId,
|
|
||||||
manager,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingMessageWithSameHeaderMessageId) {
|
|
||||||
return Promise.resolve(
|
|
||||||
existingMessageWithSameHeaderMessageId.messageThreadId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If message thread does not exist, create new message thread
|
|
||||||
const newMessageThreadId = v4();
|
|
||||||
|
|
||||||
await manager.query(
|
|
||||||
`INSERT INTO ${dataSourceMetadata.schema}."messageThread" ("id") VALUES ($1)`,
|
|
||||||
[newMessageThreadId],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Promise.resolve(newMessageThreadId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MessageRepository {
|
||||||
|
constructor(
|
||||||
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async getNonAssociatedMessageIdsPaginated(
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<string[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
const nonAssociatedMessages =
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT m.id FROM ${dataSourceSchema}."message" m
|
||||||
|
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" mcma
|
||||||
|
ON m.id = mcma."messageId"
|
||||||
|
WHERE mcma.id IS NULL
|
||||||
|
LIMIT $1 OFFSET $2`,
|
||||||
|
[limit, offset],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
return nonAssociatedMessages.map(({ id }) => id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFirstOrNullByHeaderMessageId(
|
||||||
|
headerMessageId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<ObjectRecord<MessageObjectMetadata> | null> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
const messages = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT * FROM ${dataSourceSchema}."message" WHERE "headerMessageId" = $1 LIMIT 1`,
|
||||||
|
[headerMessageId],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!messages || messages.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getByIds(
|
||||||
|
messageIds: string[],
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<ObjectRecord<MessageObjectMetadata>[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
return await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT * FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
||||||
|
[messageIds],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteByIds(
|
||||||
|
messageIds: string[],
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`DELETE FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
||||||
|
[messageIds],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getByMessageThreadIds(
|
||||||
|
messageThreadIds: string[],
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<ObjectRecord<MessageObjectMetadata>[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
return await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT * FROM ${dataSourceSchema}."message" WHERE "messageThreadId" = ANY($1)`,
|
||||||
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async insert(
|
||||||
|
id: string,
|
||||||
|
headerMessageId: string,
|
||||||
|
subject: string,
|
||||||
|
receivedAt: Date,
|
||||||
|
messageDirection: string,
|
||||||
|
messageThreadId: string,
|
||||||
|
text: string,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`INSERT INTO ${dataSourceSchema}."message" ("id", "headerMessageId", "subject", "receivedAt", "direction", "messageThreadId", "text") VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
||||||
|
[
|
||||||
|
id,
|
||||||
|
headerMessageId,
|
||||||
|
subject,
|
||||||
|
receivedAt,
|
||||||
|
messageDirection,
|
||||||
|
messageThreadId,
|
||||||
|
text,
|
||||||
|
],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import { Module, forwardRef } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { MessageChannelModule } from 'src/modules/messaging/repositories/message-channel/message-channel.module';
|
|
||||||
import { MessageChannelMessageAssociationModule } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module';
|
|
||||||
import { MessageParticipantModule } from 'src/modules/messaging/repositories/message-participant/message-participant.module';
|
|
||||||
import { MessageThreadModule } from 'src/modules/messaging/repositories/message-thread/message-thread.module';
|
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [
|
|
||||||
WorkspaceDataSourceModule,
|
|
||||||
forwardRef(() => MessageThreadModule),
|
|
||||||
MessageParticipantModule,
|
|
||||||
MessageChannelMessageAssociationModule,
|
|
||||||
MessageChannelModule,
|
|
||||||
CreateCompaniesAndContactsModule,
|
|
||||||
],
|
|
||||||
providers: [MessageService],
|
|
||||||
exports: [MessageService],
|
|
||||||
})
|
|
||||||
export class MessageModule {}
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { HttpModule } from '@nestjs/axios';
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
HttpModule.register({
|
||||||
|
baseURL: 'https://www.googleapis.com/batch/gmail/v1',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
providers: [FetchByBatchesService],
|
||||||
|
exports: [FetchByBatchesService],
|
||||||
|
})
|
||||||
|
export class FetchByBatchModule {}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { FetchByBatchModule } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module';
|
||||||
|
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [FetchByBatchModule],
|
||||||
|
providers: [FetchMessagesByBatchesService],
|
||||||
|
exports: [FetchMessagesByBatchesService],
|
||||||
|
})
|
||||||
|
export class FetchMessagesByBatchesModule {}
|
||||||
@ -7,7 +7,7 @@ import planer from 'planer';
|
|||||||
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
||||||
import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query';
|
import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query';
|
||||||
import { GmailMessageParsedResponse } from 'src/modules/messaging/types/gmail-message-parsed-response';
|
import { GmailMessageParsedResponse } from 'src/modules/messaging/types/gmail-message-parsed-response';
|
||||||
import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch.service';
|
import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service';
|
||||||
import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util';
|
import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module';
|
||||||
|
import { GmailFullSyncService } from 'src/modules/messaging/services/gmail-full-sync/gmail-full-sync.service';
|
||||||
|
import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module';
|
||||||
|
import { SaveMessagesAndCreateContactsModule } from 'src/modules/messaging/services/save-message-and-create-contact/save-message-and-create-contacts.module';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
MessagingProvidersModule,
|
||||||
|
FetchMessagesByBatchesModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
ConnectedAccountObjectMetadata,
|
||||||
|
MessageChannelObjectMetadata,
|
||||||
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
BlocklistObjectMetadata,
|
||||||
|
]),
|
||||||
|
SaveMessagesAndCreateContactsModule,
|
||||||
|
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||||
|
],
|
||||||
|
providers: [GmailFullSyncService],
|
||||||
|
exports: [GmailFullSyncService],
|
||||||
|
})
|
||||||
|
export class GmailFullSyncModule {}
|
||||||
@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
|
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches.service';
|
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service';
|
||||||
import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider';
|
import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
@ -11,17 +11,22 @@ import {
|
|||||||
GmailFullSyncJobData,
|
GmailFullSyncJobData,
|
||||||
GmailFullSyncJob,
|
GmailFullSyncJob,
|
||||||
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
import { MessageChannelMessageAssociationService } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository';
|
||||||
import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util';
|
import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util';
|
||||||
import { gmailSearchFilterExcludeEmails } from 'src/modules/messaging/utils/gmail-search-filter.util';
|
import { gmailSearchFilterExcludeEmails } from 'src/modules/messaging/utils/gmail-search-filter.util';
|
||||||
import { BlocklistService } from 'src/modules/connected-account/repositories/blocklist/blocklist.service';
|
import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository';
|
||||||
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-messages-and-create-contacts.service';
|
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-message-and-create-contact/save-messages-and-create-contacts.service';
|
||||||
import {
|
import {
|
||||||
FeatureFlagEntity,
|
FeatureFlagEntity,
|
||||||
FeatureFlagKeys,
|
FeatureFlagKeys,
|
||||||
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GmailFullSyncService {
|
export class GmailFullSyncService {
|
||||||
@ -32,10 +37,16 @@ export class GmailFullSyncService {
|
|||||||
private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService,
|
private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService,
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
private readonly messageChannelService: MessageChannelService,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationService,
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
private readonly blocklistService: BlocklistService,
|
private readonly messageChannelRepository: MessageChannelRepository,
|
||||||
|
@InjectObjectMetadataRepository(
|
||||||
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
)
|
||||||
|
private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository,
|
||||||
|
@InjectObjectMetadataRepository(BlocklistObjectMetadata)
|
||||||
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
private readonly saveMessagesAndCreateContactsService: SaveMessagesAndCreateContactsService,
|
private readonly saveMessagesAndCreateContactsService: SaveMessagesAndCreateContactsService,
|
||||||
@InjectRepository(FeatureFlagEntity, 'core')
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
@ -46,7 +57,7 @@ export class GmailFullSyncService {
|
|||||||
connectedAccountId: string,
|
connectedAccountId: string,
|
||||||
nextPageToken?: string,
|
nextPageToken?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const connectedAccount = await this.connectedAccountService.getById(
|
const connectedAccount = await this.connectedAccountRepository.getById(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -70,7 +81,7 @@ export class GmailFullSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gmailMessageChannel =
|
const gmailMessageChannel =
|
||||||
await this.messageChannelService.getFirstByConnectedAccountId(
|
await this.messageChannelRepository.getFirstByConnectedAccountId(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -99,7 +110,7 @@ export class GmailFullSyncService {
|
|||||||
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
||||||
|
|
||||||
const blocklist = isBlocklistEnabled
|
const blocklist = isBlocklistEnabled
|
||||||
? await this.blocklistService.getByWorkspaceMemberId(
|
? await this.blocklistRepository.getByWorkspaceMemberId(
|
||||||
workspaceMemberId,
|
workspaceMemberId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
)
|
)
|
||||||
@ -140,7 +151,7 @@ export class GmailFullSyncService {
|
|||||||
startTime = Date.now();
|
startTime = Date.now();
|
||||||
|
|
||||||
const existingMessageChannelMessageAssociations =
|
const existingMessageChannelMessageAssociations =
|
||||||
await this.messageChannelMessageAssociationService.getByMessageExternalIdsAndMessageChannelId(
|
await this.messageChannelMessageAssociationRepository.getByMessageExternalIdsAndMessageChannelId(
|
||||||
messageExternalIds,
|
messageExternalIds,
|
||||||
gmailMessageChannelId,
|
gmailMessageChannelId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -221,7 +232,7 @@ export class GmailFullSyncService {
|
|||||||
|
|
||||||
startTime = Date.now();
|
startTime = Date.now();
|
||||||
|
|
||||||
await this.connectedAccountService.updateLastSyncHistoryIdIfHigher(
|
await this.connectedAccountRepository.updateLastSyncHistoryIdIfHigher(
|
||||||
historyId,
|
historyId,
|
||||||
connectedAccount.id,
|
connectedAccount.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { FeatureFlagEntity } from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module';
|
||||||
|
import { GmailPartialSyncService } from 'src/modules/messaging/services/gmail-partial-sync/gmail-partial-sync.service';
|
||||||
|
import { MessageModule } from 'src/modules/messaging/services/message/message.module';
|
||||||
|
import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module';
|
||||||
|
import { SaveMessagesAndCreateContactsModule } from 'src/modules/messaging/services/save-message-and-create-contact/save-message-and-create-contacts.module';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
MessagingProvidersModule,
|
||||||
|
FetchMessagesByBatchesModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
ConnectedAccountObjectMetadata,
|
||||||
|
MessageChannelObjectMetadata,
|
||||||
|
BlocklistObjectMetadata,
|
||||||
|
]),
|
||||||
|
MessageModule,
|
||||||
|
SaveMessagesAndCreateContactsModule,
|
||||||
|
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||||
|
],
|
||||||
|
providers: [GmailPartialSyncService],
|
||||||
|
exports: [GmailPartialSyncService],
|
||||||
|
})
|
||||||
|
export class GmailPartialSyncModule {}
|
||||||
@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { gmail_v1 } from 'googleapis';
|
import { gmail_v1 } from 'googleapis';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches.service';
|
import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service';
|
||||||
import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider';
|
import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
@ -12,18 +12,22 @@ import {
|
|||||||
GmailFullSyncJob,
|
GmailFullSyncJob,
|
||||||
GmailFullSyncJobData,
|
GmailFullSyncJobData,
|
||||||
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
} from 'src/modules/messaging/jobs/gmail-full-sync.job';
|
||||||
import { ConnectedAccountService } from 'src/modules/connected-account/repositories/connected-account/connected-account.service';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util';
|
import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util';
|
||||||
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
||||||
import { isPersonEmail } from 'src/modules/messaging/utils/is-person-email.util';
|
import { isPersonEmail } from 'src/modules/messaging/utils/is-person-email.util';
|
||||||
import { BlocklistService } from 'src/modules/connected-account/repositories/blocklist/blocklist.service';
|
import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository';
|
||||||
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-messages-and-create-contacts.service';
|
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-message-and-create-contact/save-messages-and-create-contacts.service';
|
||||||
import {
|
import {
|
||||||
FeatureFlagEntity,
|
FeatureFlagEntity,
|
||||||
FeatureFlagKeys,
|
FeatureFlagKeys,
|
||||||
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
} from 'src/engine/modules/feature-flag/feature-flag.entity';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { MessageService } from 'src/modules/messaging/services/message/message.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GmailPartialSyncService {
|
export class GmailPartialSyncService {
|
||||||
@ -34,10 +38,13 @@ export class GmailPartialSyncService {
|
|||||||
private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService,
|
private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService,
|
||||||
@Inject(MessageQueue.messagingQueue)
|
@Inject(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
private readonly connectedAccountService: ConnectedAccountService,
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
private readonly messageChannelService: MessageChannelService,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
|
private readonly messageChannelRepository: MessageChannelRepository,
|
||||||
private readonly messageService: MessageService,
|
private readonly messageService: MessageService,
|
||||||
private readonly blocklistService: BlocklistService,
|
@InjectObjectMetadataRepository(BlocklistObjectMetadata)
|
||||||
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
private readonly saveMessagesAndCreateContactsService: SaveMessagesAndCreateContactsService,
|
private readonly saveMessagesAndCreateContactsService: SaveMessagesAndCreateContactsService,
|
||||||
@InjectRepository(FeatureFlagEntity, 'core')
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
@ -48,7 +55,7 @@ export class GmailPartialSyncService {
|
|||||||
connectedAccountId: string,
|
connectedAccountId: string,
|
||||||
maxResults = 500,
|
maxResults = 500,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const connectedAccount = await this.connectedAccountService.getById(
|
const connectedAccount = await this.connectedAccountRepository.getById(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -103,7 +110,7 @@ export class GmailPartialSyncService {
|
|||||||
`gmail partial-sync for workspace ${workspaceId} and account ${connectedAccountId}: invalid lastSyncHistoryId, falling back to full sync.`,
|
`gmail partial-sync for workspace ${workspaceId} and account ${connectedAccountId}: invalid lastSyncHistoryId, falling back to full sync.`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.connectedAccountService.deleteHistoryId(
|
await this.connectedAccountRepository.deleteHistoryId(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -143,7 +150,7 @@ export class GmailPartialSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gmailMessageChannel =
|
const gmailMessageChannel =
|
||||||
await this.messageChannelService.getFirstByConnectedAccountId(
|
await this.messageChannelRepository.getFirstByConnectedAccountId(
|
||||||
connectedAccountId,
|
connectedAccountId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -183,7 +190,7 @@ export class GmailPartialSyncService {
|
|||||||
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value;
|
||||||
|
|
||||||
const blocklist = isBlocklistEnabled
|
const blocklist = isBlocklistEnabled
|
||||||
? await this.blocklistService.getByWorkspaceMemberId(
|
? await this.blocklistRepository.getByWorkspaceMemberId(
|
||||||
connectedAccount.accountOwnerId,
|
connectedAccount.accountOwnerId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
)
|
)
|
||||||
@ -251,7 +258,7 @@ export class GmailPartialSyncService {
|
|||||||
}
|
}
|
||||||
startTime = Date.now();
|
startTime = Date.now();
|
||||||
|
|
||||||
await this.connectedAccountService.updateLastSyncHistoryId(
|
await this.connectedAccountRepository.updateLastSyncHistoryId(
|
||||||
historyId,
|
historyId,
|
||||||
connectedAccount.id,
|
connectedAccount.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
WorkspaceDataSourceModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([PersonObjectMetadata]),
|
||||||
|
],
|
||||||
|
providers: [MessageParticipantService],
|
||||||
|
exports: [MessageParticipantService],
|
||||||
|
})
|
||||||
|
export class MessageParticipantModule {}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ParticipantWithId } from 'src/modules/messaging/types/gmail-message';
|
||||||
|
import { PersonRepository } from 'src/modules/person/repositories/person.repository';
|
||||||
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MessageParticipantService {
|
||||||
|
constructor(
|
||||||
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
|
@InjectObjectMetadataRepository(PersonObjectMetadata)
|
||||||
|
private readonly personRepository: PersonRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async updateMessageParticipantsAfterPeopleCreation(
|
||||||
|
participants: ParticipantWithId[],
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
if (!participants) return;
|
||||||
|
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
const handles = participants.map((participant) => participant.handle);
|
||||||
|
|
||||||
|
const participantPersonIds = await this.personRepository.getByEmails(
|
||||||
|
handles,
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageParticipantsToUpdate = participants.map((participant) => [
|
||||||
|
participant.id,
|
||||||
|
participantPersonIds.find(
|
||||||
|
(e: { id: string; email: string }) => e.email === participant.handle,
|
||||||
|
)?.id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (messageParticipantsToUpdate.length === 0) return;
|
||||||
|
|
||||||
|
const valuesString = messageParticipantsToUpdate
|
||||||
|
.map((_, index) => `($${index * 2 + 1}::uuid, $${index * 2 + 2}::uuid)`)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`UPDATE ${dataSourceSchema}."messageParticipant" AS "messageParticipant" SET "personId" = "data"."personId"
|
||||||
|
FROM (VALUES ${valuesString}) AS "data"("id", "personId")
|
||||||
|
WHERE "messageParticipant"."id" = "data"."id"`,
|
||||||
|
messageParticipantsToUpdate.flat(),
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
MessageObjectMetadata,
|
||||||
|
MessageThreadObjectMetadata,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
providers: [MessageThreadService],
|
||||||
|
exports: [MessageThreadService],
|
||||||
|
})
|
||||||
|
export class MessageThreadModule {}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository';
|
||||||
|
import { MessageRepository } from 'src/modules/messaging/repositories/message.repository';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MessageThreadService {
|
||||||
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(
|
||||||
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
)
|
||||||
|
private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageObjectMetadata)
|
||||||
|
private readonly messageRepository: MessageRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageThreadObjectMetadata)
|
||||||
|
private readonly messageThreadRepository: MessageThreadRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async saveMessageThreadOrReturnExistingMessageThread(
|
||||||
|
headerMessageId: string,
|
||||||
|
messageThreadExternalId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
manager: EntityManager,
|
||||||
|
) {
|
||||||
|
// Check if message thread already exists via threadExternalId
|
||||||
|
const existingMessageChannelMessageAssociationByMessageThreadExternalId =
|
||||||
|
await this.messageChannelMessageAssociationRepository.getFirstByMessageThreadExternalId(
|
||||||
|
messageThreadExternalId,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
|
const existingMessageThread =
|
||||||
|
existingMessageChannelMessageAssociationByMessageThreadExternalId?.messageThreadId;
|
||||||
|
|
||||||
|
if (existingMessageThread) {
|
||||||
|
return Promise.resolve(existingMessageThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if message thread already exists via existing message headerMessageId
|
||||||
|
const existingMessageWithSameHeaderMessageId =
|
||||||
|
await this.messageRepository.getFirstOrNullByHeaderMessageId(
|
||||||
|
headerMessageId,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingMessageWithSameHeaderMessageId) {
|
||||||
|
return Promise.resolve(
|
||||||
|
existingMessageWithSameHeaderMessageId.messageThreadId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If message thread does not exist, create new message thread
|
||||||
|
const newMessageThreadId = v4();
|
||||||
|
|
||||||
|
await this.messageThreadRepository.insert(
|
||||||
|
newMessageThreadId,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.resolve(newMessageThreadId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { MessageThreadModule } from 'src/modules/messaging/services/message-thread/message-thread.module';
|
||||||
|
import { MessageService } from 'src/modules/messaging/services/message/message.service';
|
||||||
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
WorkspaceDataSourceModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
MessageObjectMetadata,
|
||||||
|
MessageChannelObjectMetadata,
|
||||||
|
MessageThreadObjectMetadata,
|
||||||
|
]),
|
||||||
|
MessageThreadModule,
|
||||||
|
],
|
||||||
|
providers: [MessageService],
|
||||||
|
exports: [MessageService],
|
||||||
|
})
|
||||||
|
export class MessageModule {}
|
||||||
@ -1,17 +1,23 @@
|
|||||||
import { Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { DataSource, EntityManager } from 'typeorm';
|
import { DataSource, EntityManager } from 'typeorm';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
|
||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
|
||||||
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
import { DataSourceEntity } from 'src/engine-metadata/data-source/data-source.entity';
|
||||||
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
import { MessageChannelMessageAssociationService } from 'src/modules/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository';
|
||||||
import { MessageThreadService } from 'src/modules/messaging/repositories/message-thread/message-thread.service';
|
import { MessageRepository } from 'src/modules/messaging/repositories/message.repository';
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
import { GmailMessage } from 'src/modules/messaging/types/gmail-message';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
|
import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository';
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessageService {
|
export class MessageService {
|
||||||
@ -19,106 +25,19 @@ export class MessageService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationService,
|
@InjectObjectMetadataRepository(
|
||||||
@Inject(forwardRef(() => MessageThreadService))
|
MessageChannelMessageAssociationObjectMetadata,
|
||||||
|
)
|
||||||
|
private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageObjectMetadata)
|
||||||
|
private readonly messageRepository: MessageRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
|
private readonly messageChannelRepository: MessageChannelRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageThreadObjectMetadata)
|
||||||
|
private readonly messageThreadRepository: MessageThreadRepository,
|
||||||
private readonly messageThreadService: MessageThreadService,
|
private readonly messageThreadService: MessageThreadService,
|
||||||
private readonly messageChannelService: MessageChannelService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getNonAssociatedMessageIdsPaginated(
|
|
||||||
limit: number,
|
|
||||||
offset: number,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<string[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const nonAssociatedMessages =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT m.id FROM ${dataSourceSchema}."message" m
|
|
||||||
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" mcma
|
|
||||||
ON m.id = mcma."messageId"
|
|
||||||
WHERE mcma.id IS NULL
|
|
||||||
LIMIT $1 OFFSET $2`,
|
|
||||||
[limit, offset],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return nonAssociatedMessages.map(({ id }) => id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getFirstOrNullByHeaderMessageId(
|
|
||||||
headerMessageId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ObjectRecord<MessageObjectMetadata> | null> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messages = await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "headerMessageId" = $1 LIMIT 1`,
|
|
||||||
[headerMessageId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!messages || messages.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByIds(
|
|
||||||
messageIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ObjectRecord<MessageObjectMetadata>[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
|
||||||
[messageIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deleteByIds(
|
|
||||||
messageIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`DELETE FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
|
||||||
[messageIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByMessageThreadIds(
|
|
||||||
messageThreadIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ObjectRecord<MessageObjectMetadata>[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "messageThreadId" = ANY($1)`,
|
|
||||||
[messageThreadIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async saveMessages(
|
public async saveMessages(
|
||||||
messages: GmailMessage[],
|
messages: GmailMessage[],
|
||||||
dataSourceMetadata: DataSourceEntity,
|
dataSourceMetadata: DataSourceEntity,
|
||||||
@ -140,7 +59,7 @@ export class MessageService {
|
|||||||
await workspaceDataSource?.transaction(
|
await workspaceDataSource?.transaction(
|
||||||
async (manager: EntityManager) => {
|
async (manager: EntityManager) => {
|
||||||
const gmailMessageChannel =
|
const gmailMessageChannel =
|
||||||
await this.messageChannelService.getByIds(
|
await this.messageChannelRepository.getByIds(
|
||||||
[gmailMessageChannelId],
|
[gmailMessageChannelId],
|
||||||
workspaceId,
|
workspaceId,
|
||||||
manager,
|
manager,
|
||||||
@ -157,7 +76,7 @@ export class MessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const existingMessageChannelMessageAssociationsCount =
|
const existingMessageChannelMessageAssociationsCount =
|
||||||
await this.messageChannelMessageAssociationService.countByMessageExternalIdsAndMessageChannelId(
|
await this.messageChannelMessageAssociationRepository.countByMessageExternalIdsAndMessageChannelId(
|
||||||
[message.externalId],
|
[message.externalId],
|
||||||
gmailMessageChannelId,
|
gmailMessageChannelId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -173,7 +92,6 @@ export class MessageService {
|
|||||||
await this.messageThreadService.saveMessageThreadOrReturnExistingMessageThread(
|
await this.messageThreadService.saveMessageThreadOrReturnExistingMessageThread(
|
||||||
message.headerMessageId,
|
message.headerMessageId,
|
||||||
message.messageThreadExternalId,
|
message.messageThreadExternalId,
|
||||||
dataSourceMetadata,
|
|
||||||
workspaceId,
|
workspaceId,
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
@ -193,15 +111,14 @@ export class MessageService {
|
|||||||
savedOrExistingMessageId,
|
savedOrExistingMessageId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await manager.query(
|
await this.messageChannelMessageAssociationRepository.insert(
|
||||||
`INSERT INTO ${dataSourceMetadata.schema}."messageChannelMessageAssociation" ("messageChannelId", "messageId", "messageExternalId", "messageThreadId", "messageThreadExternalId") VALUES ($1, $2, $3, $4, $5)`,
|
gmailMessageChannelId,
|
||||||
[
|
savedOrExistingMessageId,
|
||||||
gmailMessageChannelId,
|
message.externalId,
|
||||||
savedOrExistingMessageId,
|
savedOrExistingMessageThreadId,
|
||||||
message.externalId,
|
message.messageThreadExternalId,
|
||||||
savedOrExistingMessageThreadId,
|
workspaceId,
|
||||||
message.messageThreadExternalId,
|
manager,
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -223,10 +140,11 @@ export class MessageService {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
manager: EntityManager,
|
manager: EntityManager,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const existingMessage = await this.getFirstOrNullByHeaderMessageId(
|
const existingMessage =
|
||||||
message.headerMessageId,
|
await this.messageRepository.getFirstOrNullByHeaderMessageId(
|
||||||
workspaceId,
|
message.headerMessageId,
|
||||||
);
|
workspaceId,
|
||||||
|
);
|
||||||
const existingMessageId = existingMessage?.id;
|
const existingMessageId = existingMessage?.id;
|
||||||
|
|
||||||
if (existingMessageId) {
|
if (existingMessageId) {
|
||||||
@ -240,17 +158,16 @@ export class MessageService {
|
|||||||
|
|
||||||
const receivedAt = new Date(parseInt(message.internalDate));
|
const receivedAt = new Date(parseInt(message.internalDate));
|
||||||
|
|
||||||
await manager.query(
|
await this.messageRepository.insert(
|
||||||
`INSERT INTO ${dataSourceMetadata.schema}."message" ("id", "headerMessageId", "subject", "receivedAt", "direction", "messageThreadId", "text") VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
newMessageId,
|
||||||
[
|
message.headerMessageId,
|
||||||
newMessageId,
|
message.subject,
|
||||||
message.headerMessageId,
|
receivedAt,
|
||||||
message.subject,
|
messageDirection,
|
||||||
receivedAt,
|
messageThreadId,
|
||||||
messageDirection,
|
message.text,
|
||||||
messageThreadId,
|
workspaceId,
|
||||||
message.text,
|
manager,
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return Promise.resolve(newMessageId);
|
return Promise.resolve(newMessageId);
|
||||||
@ -268,7 +185,7 @@ export class MessageService {
|
|||||||
|
|
||||||
await workspaceDataSource?.transaction(async (manager: EntityManager) => {
|
await workspaceDataSource?.transaction(async (manager: EntityManager) => {
|
||||||
const messageChannelMessageAssociationsToDelete =
|
const messageChannelMessageAssociationsToDelete =
|
||||||
await this.messageChannelMessageAssociationService.getByMessageExternalIdsAndMessageChannelId(
|
await this.messageChannelMessageAssociationRepository.getByMessageExternalIdsAndMessageChannelId(
|
||||||
messagesDeletedMessageExternalIds,
|
messagesDeletedMessageExternalIds,
|
||||||
gmailMessageChannelId,
|
gmailMessageChannelId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -281,7 +198,7 @@ export class MessageService {
|
|||||||
messageChannelMessageAssociationToDelete.id,
|
messageChannelMessageAssociationToDelete.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelMessageAssociationService.deleteByIds(
|
await this.messageChannelMessageAssociationRepository.deleteByIds(
|
||||||
messageChannelMessageAssociationIdsToDeleteIds,
|
messageChannelMessageAssociationIdsToDeleteIds,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
manager,
|
manager,
|
||||||
@ -294,7 +211,7 @@ export class MessageService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const messageChannelMessageAssociationByMessageIds =
|
const messageChannelMessageAssociationByMessageIds =
|
||||||
await this.messageChannelMessageAssociationService.getByMessageIds(
|
await this.messageChannelMessageAssociationRepository.getByMessageIds(
|
||||||
messageIdsFromMessageChannelMessageAssociationsToDelete,
|
messageIdsFromMessageChannelMessageAssociationsToDelete,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
manager,
|
manager,
|
||||||
@ -314,7 +231,11 @@ export class MessageService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.deleteByIds(messageIdsToDelete, workspaceId, manager);
|
await this.messageRepository.deleteByIds(
|
||||||
|
messageIdsToDelete,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
const messageThreadIdsFromMessageChannelMessageAssociationsToDelete =
|
const messageThreadIdsFromMessageChannelMessageAssociationsToDelete =
|
||||||
messageChannelMessageAssociationsToDelete.map(
|
messageChannelMessageAssociationsToDelete.map(
|
||||||
@ -322,11 +243,12 @@ export class MessageService {
|
|||||||
messageChannelMessageAssociationToDelete.messageThreadId,
|
messageChannelMessageAssociationToDelete.messageThreadId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const messagesByThreadIds = await this.getByMessageThreadIds(
|
const messagesByThreadIds =
|
||||||
messageThreadIdsFromMessageChannelMessageAssociationsToDelete,
|
await this.messageRepository.getByMessageThreadIds(
|
||||||
workspaceId,
|
messageThreadIdsFromMessageChannelMessageAssociationsToDelete,
|
||||||
manager,
|
workspaceId,
|
||||||
);
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
const threadIdsToDelete =
|
const threadIdsToDelete =
|
||||||
messageThreadIdsFromMessageChannelMessageAssociationsToDelete.filter(
|
messageThreadIdsFromMessageChannelMessageAssociationsToDelete.filter(
|
||||||
@ -336,7 +258,7 @@ export class MessageService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageThreadService.deleteByIds(
|
await this.messageThreadRepository.deleteByIds(
|
||||||
threadIdsToDelete,
|
threadIdsToDelete,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
manager,
|
manager,
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { CreateCompaniesAndContactsModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.module';
|
||||||
|
import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module';
|
||||||
|
import { MessageModule } from 'src/modules/messaging/services/message/message.module';
|
||||||
|
import { SaveMessagesAndCreateContactsService } from 'src/modules/messaging/services/save-message-and-create-contact/save-messages-and-create-contacts.service';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
MessageModule,
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
MessageChannelObjectMetadata,
|
||||||
|
MessageParticipantObjectMetadata,
|
||||||
|
]),
|
||||||
|
CreateCompaniesAndContactsModule,
|
||||||
|
MessageParticipantModule,
|
||||||
|
WorkspaceDataSourceModule,
|
||||||
|
],
|
||||||
|
providers: [SaveMessagesAndCreateContactsService],
|
||||||
|
exports: [SaveMessagesAndCreateContactsService],
|
||||||
|
})
|
||||||
|
export class SaveMessagesAndCreateContactsModule {}
|
||||||
@ -2,9 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
import { MessageChannelService } from 'src/modules/messaging/repositories/message-channel/message-channel.service';
|
import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository';
|
||||||
import { MessageParticipantService } from 'src/modules/messaging/repositories/message-participant/message-participant.service';
|
import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository';
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/create-company-and-contact/create-company-and-contact.service';
|
||||||
import {
|
import {
|
||||||
GmailMessage,
|
GmailMessage,
|
||||||
@ -13,6 +12,11 @@ import {
|
|||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata';
|
||||||
|
import { MessageService } from 'src/modules/messaging/services/message/message.service';
|
||||||
|
import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata';
|
||||||
|
import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SaveMessagesAndCreateContactsService {
|
export class SaveMessagesAndCreateContactsService {
|
||||||
@ -22,7 +26,10 @@ export class SaveMessagesAndCreateContactsService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly messageService: MessageService,
|
private readonly messageService: MessageService,
|
||||||
private readonly messageChannelService: MessageChannelService,
|
@InjectObjectMetadataRepository(MessageChannelObjectMetadata)
|
||||||
|
private readonly messageChannelRepository: MessageChannelRepository,
|
||||||
|
@InjectObjectMetadataRepository(MessageParticipantObjectMetadata)
|
||||||
|
private readonly messageParticipantRepository: MessageParticipantRepository,
|
||||||
private readonly createCompaniesAndContactsService: CreateCompanyAndContactService,
|
private readonly createCompaniesAndContactsService: CreateCompanyAndContactService,
|
||||||
private readonly messageParticipantService: MessageParticipantService,
|
private readonly messageParticipantService: MessageParticipantService,
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
@ -60,7 +67,7 @@ export class SaveMessagesAndCreateContactsService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const gmailMessageChannel =
|
const gmailMessageChannel =
|
||||||
await this.messageChannelService.getFirstByConnectedAccountId(
|
await this.messageChannelRepository.getFirstByConnectedAccountId(
|
||||||
connectedAccount.id,
|
connectedAccount.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -111,7 +118,7 @@ export class SaveMessagesAndCreateContactsService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const messageParticipantsWithoutPersonIdAndWorkspaceMemberId =
|
const messageParticipantsWithoutPersonIdAndWorkspaceMemberId =
|
||||||
await this.messageParticipantService.getByHandlesWithoutPersonIdAndWorkspaceMemberId(
|
await this.messageParticipantRepository.getByHandlesWithoutPersonIdAndWorkspaceMemberId(
|
||||||
handles,
|
handles,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -157,7 +164,7 @@ export class SaveMessagesAndCreateContactsService {
|
|||||||
jobName?: string,
|
jobName?: string,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await this.messageParticipantService.saveMessageParticipants(
|
await this.messageParticipantRepository.saveMessageParticipants(
|
||||||
participantsWithMessageId,
|
participantsWithMessageId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -1,17 +1,16 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { DataSourceModule } from 'src/engine-metadata/data-source/data-source.module';
|
|
||||||
import { MessageThreadModule } from 'src/modules/messaging/repositories/message-thread/message-thread.module';
|
|
||||||
import { MessageModule } from 'src/modules/messaging/repositories/message/message.module';
|
|
||||||
import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service';
|
import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
DataSourceModule,
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
TypeORMModule,
|
MessageObjectMetadata,
|
||||||
MessageThreadModule,
|
MessageThreadObjectMetadata,
|
||||||
MessageModule,
|
]),
|
||||||
],
|
],
|
||||||
providers: [ThreadCleanerService],
|
providers: [ThreadCleanerService],
|
||||||
exports: [ThreadCleanerService],
|
exports: [ThreadCleanerService],
|
||||||
|
|||||||
@ -1,37 +1,40 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
import { DataSourceService } from 'src/engine-metadata/data-source/data-source.service';
|
import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository';
|
||||||
import { MessageThreadService } from 'src/modules/messaging/repositories/message-thread/message-thread.service';
|
import { MessageRepository } from 'src/modules/messaging/repositories/message.repository';
|
||||||
import { MessageService } from 'src/modules/messaging/repositories/message/message.service';
|
|
||||||
import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util';
|
import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util';
|
||||||
|
import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata';
|
||||||
|
import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ThreadCleanerService {
|
export class ThreadCleanerService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly dataSourceService: DataSourceService,
|
@InjectObjectMetadataRepository(MessageObjectMetadata)
|
||||||
private readonly typeORMService: TypeORMService,
|
private readonly messageRepository: MessageRepository,
|
||||||
private readonly messageService: MessageService,
|
@InjectObjectMetadataRepository(MessageThreadObjectMetadata)
|
||||||
private readonly messageThreadService: MessageThreadService,
|
private readonly messageThreadRepository: MessageThreadRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async cleanWorkspaceThreads(workspaceId: string) {
|
public async cleanWorkspaceThreads(workspaceId: string) {
|
||||||
await deleteUsingPagination(
|
await deleteUsingPagination(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
500,
|
500,
|
||||||
this.messageService.getNonAssociatedMessageIdsPaginated.bind(
|
this.messageRepository.getNonAssociatedMessageIdsPaginated.bind(
|
||||||
this.messageService,
|
this.messageRepository,
|
||||||
),
|
),
|
||||||
this.messageService.deleteByIds.bind(this.messageService),
|
this.messageRepository.deleteByIds.bind(this.messageRepository),
|
||||||
);
|
);
|
||||||
|
|
||||||
await deleteUsingPagination(
|
await deleteUsingPagination(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
500,
|
500,
|
||||||
this.messageThreadService.getOrphanThreadIdsPaginated.bind(
|
this.messageThreadRepository.getOrphanThreadIdsPaginated.bind(
|
||||||
this.messageThreadService,
|
this.messageThreadRepository,
|
||||||
|
),
|
||||||
|
this.messageThreadRepository.deleteByIds.bind(
|
||||||
|
this.messageThreadRepository,
|
||||||
),
|
),
|
||||||
this.messageThreadService.deleteByIds.bind(this.messageThreadService),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,8 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work
|
|||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata';
|
||||||
|
|
||||||
// TODO: Move outside of the messaging module
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PersonService {
|
export class PersonRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { PersonService } from 'src/modules/person/repositories/person/person.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [PersonService],
|
|
||||||
exports: [PersonService],
|
|
||||||
})
|
|
||||||
export class PersonModule {}
|
|
||||||
@ -6,9 +6,8 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work
|
|||||||
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record';
|
||||||
|
|
||||||
// TODO: Move outside of the messaging module
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceMemberService {
|
export class WorkspaceMemberRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { WorkspaceMemberService } from 'src/modules/workspace-member/repositories/workspace-member/workspace-member.service';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [WorkspaceDataSourceModule],
|
|
||||||
providers: [WorkspaceMemberService],
|
|
||||||
exports: [WorkspaceMemberService],
|
|
||||||
})
|
|
||||||
export class WorkspaceMemberModule {}
|
|
||||||
Reference in New Issue
Block a user