mirror of
https://github.com/docmost/docmost.git
synced 2026-05-17 23:14:07 +08:00
895c1817ae
* handle enter in inline code * fix: duplicate comment cache * track link nodes (backlinks) * fix en-US translation * fix internal a-links * overrides * 0.71.1
98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import { Logger } from '@nestjs/common';
|
|
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
|
import { BacklinkRepo } from '@docmost/db/repos/backlink/backlink.repo';
|
|
import { IPageBacklinkJob } from '../constants/queue.interface';
|
|
import { executeTx } from '@docmost/db/utils';
|
|
|
|
const logger = new Logger('BacklinksTask');
|
|
|
|
export async function processBacklinks(
|
|
db: KyselyDB,
|
|
backlinkRepo: BacklinkRepo,
|
|
data: IPageBacklinkJob,
|
|
): Promise<void> {
|
|
const { pageId, mentions, workspaceId, internalLinkSlugIds = [] } = data;
|
|
|
|
await executeTx(db, async (trx) => {
|
|
const existingBacklinks = await trx
|
|
.selectFrom('backlinks')
|
|
.select('targetPageId')
|
|
.where('sourcePageId', '=', pageId)
|
|
.execute();
|
|
|
|
const mentionTargetPageIds = mentions
|
|
.filter((mention) => mention.entityId !== pageId)
|
|
.map((mention) => mention.entityId);
|
|
|
|
let resolvedLinkPageIds: string[] = [];
|
|
if (internalLinkSlugIds.length > 0) {
|
|
const resolvedPages = await trx
|
|
.selectFrom('pages')
|
|
.select('id')
|
|
.where('slugId', 'in', internalLinkSlugIds)
|
|
.where('workspaceId', '=', workspaceId)
|
|
.execute();
|
|
resolvedLinkPageIds = resolvedPages
|
|
.map((p) => p.id)
|
|
.filter((id) => id !== pageId);
|
|
}
|
|
|
|
const allTargetPageIds = [
|
|
...new Set([...mentionTargetPageIds, ...resolvedLinkPageIds]),
|
|
];
|
|
|
|
if (existingBacklinks.length === 0 && allTargetPageIds.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const existingTargetPageIds = existingBacklinks.map(
|
|
(backlink) => backlink.targetPageId,
|
|
);
|
|
|
|
let validTargetPages = [];
|
|
if (allTargetPageIds.length > 0) {
|
|
validTargetPages = await trx
|
|
.selectFrom('pages')
|
|
.select('id')
|
|
.where('id', 'in', allTargetPageIds)
|
|
.where('workspaceId', '=', workspaceId)
|
|
.execute();
|
|
}
|
|
|
|
const validTargetPageIds = validTargetPages.map((page) => page.id);
|
|
|
|
const backlinksToAdd = validTargetPageIds.filter(
|
|
(id) => !existingTargetPageIds.includes(id),
|
|
);
|
|
|
|
const backlinksToRemove = existingTargetPageIds.filter(
|
|
(existingId) => !validTargetPageIds.includes(existingId),
|
|
);
|
|
|
|
if (backlinksToAdd.length > 0) {
|
|
const newBacklinks = backlinksToAdd.map((targetPageId) => ({
|
|
sourcePageId: pageId,
|
|
targetPageId: targetPageId,
|
|
workspaceId: workspaceId,
|
|
}));
|
|
|
|
await backlinkRepo.insertBacklink(newBacklinks, trx);
|
|
logger.debug(
|
|
`Added ${newBacklinks.length} new backlinks to ${pageId}`,
|
|
);
|
|
}
|
|
|
|
if (backlinksToRemove.length > 0) {
|
|
await db
|
|
.deleteFrom('backlinks')
|
|
.where('sourcePageId', '=', pageId)
|
|
.where('targetPageId', 'in', backlinksToRemove)
|
|
.execute();
|
|
|
|
logger.debug(
|
|
`Removed ${backlinksToRemove.length} outdated backlinks from ${pageId}.`,
|
|
);
|
|
}
|
|
});
|
|
}
|