Make colloboration module not dependant on page module

* add unloadImmediately to collab
This commit is contained in:
Philipinho
2024-04-22 23:40:50 +01:00
parent f65e5c872b
commit 6a57e3edb2
7 changed files with 41 additions and 55 deletions

View File

@ -17,6 +17,7 @@ export class CollaborationGateway {
private hocuspocus = HocuspocusServer.configure({ private hocuspocus = HocuspocusServer.configure({
debounce: 5000, debounce: 5000,
maxDebounce: 10000, maxDebounce: 10000,
unloadImmediately: false,
extensions: [ extensions: [
this.authenticationExtension, this.authenticationExtension,
this.persistenceExtension, this.persistenceExtension,

View File

@ -2,7 +2,6 @@ import { Module, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { AuthModule } from '../core/auth/auth.module'; import { AuthModule } from '../core/auth/auth.module';
import { AuthenticationExtension } from './extensions/authentication.extension'; import { AuthenticationExtension } from './extensions/authentication.extension';
import { PersistenceExtension } from './extensions/persistence.extension'; import { PersistenceExtension } from './extensions/persistence.extension';
import { PageModule } from '../core/page/page.module';
import { CollaborationGateway } from './collaboration.gateway'; import { CollaborationGateway } from './collaboration.gateway';
import { HttpAdapterHost } from '@nestjs/core'; import { HttpAdapterHost } from '@nestjs/core';
import { CollabWsAdapter } from './adapter/collab-ws.adapter'; import { CollabWsAdapter } from './adapter/collab-ws.adapter';
@ -17,7 +16,7 @@ import { HistoryExtension } from './extensions/history.extension';
PersistenceExtension, PersistenceExtension,
HistoryExtension, HistoryExtension,
], ],
imports: [AuthModule, PageModule], imports: [AuthModule],
}) })
export class CollaborationModule implements OnModuleInit, OnModuleDestroy { export class CollaborationModule implements OnModuleInit, OnModuleDestroy {
private collabWsAdapter: CollabWsAdapter; private collabWsAdapter: CollabWsAdapter;

View File

@ -4,8 +4,8 @@ import {
onDisconnectPayload, onDisconnectPayload,
} from '@hocuspocus/server'; } from '@hocuspocus/server';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { PageService } from '../../core/page/services/page.service'; import { PageRepo } from '@docmost/db/repos/page/page.repo';
import { PageHistoryService } from '../../core/page/services/page-history.service'; import { PageHistoryRepo } from '@docmost/db/repos/page/page-history.repo';
@Injectable() @Injectable()
export class HistoryExtension implements Extension { export class HistoryExtension implements Extension {
@ -14,8 +14,8 @@ export class HistoryExtension implements Extension {
lastEditTimeMap = new Map<string, number>(); lastEditTimeMap = new Map<string, number>();
constructor( constructor(
private readonly pageService: PageService, private readonly pageRepo: PageRepo,
private readonly pageHistoryService: PageHistoryService, private readonly pageHistoryRepo: PageHistoryRepo,
) {} ) {}
async onChange(data: onChangePayload): Promise<void> { async onChange(data: onChangePayload): Promise<void> {
@ -53,10 +53,11 @@ export class HistoryExtension implements Extension {
async recordHistory(pageId: string) { async recordHistory(pageId: string) {
try { try {
const includeContent = true; const page = await this.pageRepo.findById(pageId, {
const page = await this.pageService.findById(pageId, includeContent); includeContent: true,
});
// Todo: compare if data is the same as the previous version // Todo: compare if data is the same as the previous version
await this.pageHistoryService.saveHistory(page); await this.pageHistoryRepo.saveHistory(page);
console.log(`New history created for: ${pageId}`); console.log(`New history created for: ${pageId}`);
} catch (err) { } catch (err) {
console.error('An error occurred saving page history', err); console.error('An error occurred saving page history', err);

View File

@ -4,14 +4,14 @@ import {
onStoreDocumentPayload, onStoreDocumentPayload,
} from '@hocuspocus/server'; } from '@hocuspocus/server';
import * as Y from 'yjs'; import * as Y from 'yjs';
import { PageService } from '../../core/page/services/page.service';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { TiptapTransformer } from '@hocuspocus/transformer'; import { TiptapTransformer } from '@hocuspocus/transformer';
import { jsonToText, tiptapExtensions } from '../collaboration.util'; import { jsonToText, tiptapExtensions } from '../collaboration.util';
import { PageRepo } from '@docmost/db/repos/page/page.repo';
@Injectable() @Injectable()
export class PersistenceExtension implements Extension { export class PersistenceExtension implements Extension {
constructor(private readonly pageService: PageService) {} constructor(private readonly pageRepo: PageRepo) {}
async onLoadDocument(data: onLoadDocumentPayload) { async onLoadDocument(data: onLoadDocumentPayload) {
const { documentName, document } = data; const { documentName, document } = data;
@ -21,7 +21,10 @@ export class PersistenceExtension implements Extension {
return; return;
} }
const page = await this.pageService.findById(pageId, true, true); const page = await this.pageRepo.findById(pageId, {
includeContent: true,
includeYdoc: true,
});
if (!page) { if (!page) {
console.log('page does not exist.'); console.log('page does not exist.');
@ -68,11 +71,14 @@ export class PersistenceExtension implements Extension {
const textContent = jsonToText(tiptapJson); const textContent = jsonToText(tiptapJson);
try { try {
await this.pageService.updateState( await this.pageRepo.updatePage(
{
content: tiptapJson,
textContent: textContent,
ydoc: ydocState,
lastUpdatedById: context.user.id,
},
pageId, pageId,
tiptapJson,
textContent,
ydocState,
); );
} catch (err) { } catch (err) {
console.error(`Failed to update page ${documentName}`); console.error(`Failed to update page ${documentName}`);

View File

@ -1,4 +1,4 @@
import { BadRequestException, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { PageHistoryRepo } from '@docmost/db/repos/page/page-history.repo'; import { PageHistoryRepo } from '@docmost/db/repos/page/page-history.repo';
import { Page, PageHistory } from '@docmost/db/types/entity.types'; import { Page, PageHistory } from '@docmost/db/types/entity.types';
import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; import { PaginationOptions } from '@docmost/db/pagination/pagination-options';
@ -9,26 +9,7 @@ export class PageHistoryService {
constructor(private pageHistoryRepo: PageHistoryRepo) {} constructor(private pageHistoryRepo: PageHistoryRepo) {}
async findById(historyId: string): Promise<PageHistory> { async findById(historyId: string): Promise<PageHistory> {
const history = await this.pageHistoryRepo.findById(historyId); return await this.pageHistoryRepo.findById(historyId);
if (!history) {
throw new BadRequestException('History not found');
}
return history;
}
async saveHistory(page: Page): Promise<void> {
await this.pageHistoryRepo.insertPageHistory({
pageId: page.id,
title: page.title,
content: page.content,
slug: page.slug,
icon: page.icon,
version: 1, // TODO: make incremental
coverPhoto: page.coverPhoto,
lastUpdatedById: page.lastUpdatedById ?? page.creatorId,
spaceId: page.spaceId,
workspaceId: page.workspaceId,
});
} }
async findHistoryByPageId( async findHistoryByPageId(

View File

@ -117,24 +117,6 @@ export class PageService {
return await this.pageRepo.findById(pageId); return await this.pageRepo.findById(pageId);
} }
async updateState(
pageId: string,
content: any,
textContent: string,
ydoc: any,
userId?: string, // TODO: fix this
): Promise<void> {
await this.pageRepo.updatePage(
{
content: content,
textContent: textContent,
ydoc: ydoc,
...(userId && { lastUpdatedById: userId }),
},
pageId,
);
}
withHasChildren(eb: ExpressionBuilder<DB, 'pages'>) { withHasChildren(eb: ExpressionBuilder<DB, 'pages'>) {
return eb return eb
.selectFrom('pages as child') .selectFrom('pages as child')

View File

@ -4,6 +4,7 @@ import { KyselyDB, KyselyTransaction } from '../../types/kysely.types';
import { dbOrTx } from '../../utils'; import { dbOrTx } from '../../utils';
import { import {
InsertablePageHistory, InsertablePageHistory,
Page,
PageHistory, PageHistory,
UpdatablePageHistory, UpdatablePageHistory,
} from '@docmost/db/types/entity.types'; } from '@docmost/db/types/entity.types';
@ -64,6 +65,21 @@ export class PageHistoryRepo {
.executeTakeFirst(); .executeTakeFirst();
} }
async saveHistory(page: Page): Promise<void> {
await this.insertPageHistory({
pageId: page.id,
title: page.title,
content: page.content,
slug: page.slug,
icon: page.icon,
version: 1, // TODO: make incremental
coverPhoto: page.coverPhoto,
lastUpdatedById: page.lastUpdatedById ?? page.creatorId,
spaceId: page.spaceId,
workspaceId: page.workspaceId,
});
}
async findPageHistoryByPageId(pageId: string, pagination: PaginationOptions) { async findPageHistoryByPageId(pageId: string, pagination: PaginationOptions) {
const query = this.db const query = this.db
.selectFrom('pageHistory') .selectFrom('pageHistory')