import { Injectable } from '@nestjs/common'; import { WatcherRepo, WatcherType, } from '@docmost/db/repos/watcher/watcher.repo'; import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; import { KyselyTransaction } from '@docmost/db/types/kysely.types'; import { InsertableWatcher } from '@docmost/db/types/entity.types'; import { SpaceMemberRepo } from '@docmost/db/repos/space/space-member.repo'; @Injectable() export class WatcherService { constructor( private readonly watcherRepo: WatcherRepo, private readonly spaceMemberRepo: SpaceMemberRepo, ) {} async watchPage( userId: string, pageId: string, spaceId: string, workspaceId: string, trx?: KyselyTransaction, ) { const watcher: InsertableWatcher = { userId, pageId, spaceId, workspaceId, type: WatcherType.PAGE, addedById: userId, }; return this.watcherRepo.upsert(watcher, trx); } async addPageWatchers( userIds: string[], pageId: string, spaceId: string, workspaceId: string, trx?: KyselyTransaction, ) { if (userIds.length === 0) return; const watchers: InsertableWatcher[] = userIds.map((userId) => ({ userId, pageId, spaceId, workspaceId, type: WatcherType.PAGE, addedById: userId, })); return this.watcherRepo.insertMany(watchers, trx); } async unwatchPage( userId: string, pageId: string, spaceId: string, workspaceId: string, ) { return this.watcherRepo.mute(userId, pageId, spaceId, workspaceId); } async isWatchingPage(userId: string, pageId: string): Promise { return this.watcherRepo.isWatching(userId, pageId); } async watchSpace( userId: string, spaceId: string, workspaceId: string, trx?: KyselyTransaction, ) { const watcher: InsertableWatcher = { userId, pageId: null, spaceId, workspaceId, type: WatcherType.SPACE, addedById: userId, }; return this.watcherRepo.upsertSpace(watcher, trx); } async unwatchSpace(userId: string, spaceId: string) { return this.watcherRepo.deleteSpaceWatch(userId, spaceId); } async getWatchedSpaceIds(userId: string, workspaceId: string) { const result = await this.watcherRepo.getWatchedSpaceIds(userId, workspaceId); const spaceIds = result.items.map((r) => r.spaceId); if (spaceIds.length === 0) { return { items: spaceIds, meta: result.meta }; } const userSpaceIds = await this.spaceMemberRepo.getUserSpaceIds(userId); const spaceSet = new Set(userSpaceIds); return { items: spaceIds.filter((id) => spaceSet.has(id)), meta: result.meta, }; } async isWatchingSpace(userId: string, spaceId: string): Promise { return this.watcherRepo.isWatchingSpace(userId, spaceId); } async getPageWatchers(pageId: string, pagination: PaginationOptions) { return this.watcherRepo.findPageWatchers(pageId, pagination); } async getPageWatcherIds( pageId: string, trx?: KyselyTransaction, ): Promise { return this.watcherRepo.getPageWatcherIds(pageId, trx); } async countPageWatchers(pageId: string): Promise { return this.watcherRepo.countPageWatchers(pageId); } async cleanupOnSpaceAccessChange( userIds: string[], spaceId: string, opts?: { trx?: KyselyTransaction }, ): Promise { const { trx } = opts; await this.watcherRepo.deleteByUsersWithoutSpaceAccess(userIds, spaceId, { trx, }); } async movePageWatchersToSpace( pageIds: string[], spaceId: string, opts?: { trx?: KyselyTransaction }, ): Promise { await this.watcherRepo.updateSpaceIdByPageIds(spaceId, pageIds, opts); await this.watcherRepo.deleteByPageIdsWithoutSpaceAccess( pageIds, spaceId, opts, ); } }