Files
docmost/apps/server/src/integrations/queue/tasks/backlinks.task.ts
T
Philip Okugbe 895c1817ae feat: bug fixes (#2084)
* 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
2026-04-05 13:45:36 +01:00

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}.`,
);
}
});
}