From 8b70214d15b9e9c9a769e316c6b58cf4d8047410 Mon Sep 17 00:00:00 2001 From: hugo Date: Sun, 15 Feb 2026 21:08:41 +0100 Subject: [PATCH] fix: merge tags did not update disc --- src/main/engine/PostEngine.ts | 32 ++++++++++++++++++++++++++++++++ src/main/engine/TagEngine.ts | 10 ++++++++++ tests/engine/TagEngine.test.ts | 7 +++++++ 3 files changed, 49 insertions(+) diff --git a/src/main/engine/PostEngine.ts b/src/main/engine/PostEngine.ts index a389b6c..4e6d430 100644 --- a/src/main/engine/PostEngine.ts +++ b/src/main/engine/PostEngine.ts @@ -519,6 +519,38 @@ export class PostEngine extends EventEmitter { return this.dbRowToPostData(dbPost, ''); } + /** + * Sync a published post's file with current database metadata (e.g., tags). + * This is needed when metadata changes outside of normal post editing flow, + * such as tag merge or rename operations. + * + * @param postId - The post ID to sync + * @returns true if file was updated, false if post is not published or doesn't exist + */ + async syncPublishedPostFile(postId: string): Promise { + const db = getDatabase().getLocal(); + const dbPost = await db.select().from(posts).where(eq(posts.id, postId)).get(); + + if (!dbPost || !dbPost.filePath) { + // Not a published post or doesn't exist + return false; + } + + // Read content from the existing file + const fileData = await this.readPostFile(dbPost.filePath); + if (!fileData) { + return false; + } + + // Build the full post data with DB metadata (tags) and file content + const postData = this.dbRowToPostData(dbPost, fileData.content); + + // Re-write the file with updated metadata + await this.writePostFile(postData); + + return true; + } + async getAllPosts(options?: PaginationOptions): Promise> { const db = getDatabase().getLocal(); const limit = options?.limit ?? 500; diff --git a/src/main/engine/TagEngine.ts b/src/main/engine/TagEngine.ts index 678c339..aeb35ac 100644 --- a/src/main/engine/TagEngine.ts +++ b/src/main/engine/TagEngine.ts @@ -7,6 +7,7 @@ import { eq, and, asc, sql, like } from 'drizzle-orm'; import { getDatabase } from '../database'; import { tags, posts } from '../database/schema'; import { taskManager } from './TaskManager'; +import { getPostEngine } from './PostEngine'; /** * Tag data stored in the database @@ -379,6 +380,9 @@ export class TagEngine extends EventEmitter { }) .where(eq(posts.id, postId)); + // Sync published post's file with updated tags + await getPostEngine().syncPublishedPostFile(postId); + updated++; onProgress((updated / total) * 80, `Updated ${updated}/${total} posts...`); } @@ -486,6 +490,9 @@ export class TagEngine extends EventEmitter { }) .where(eq(posts.id, postId)); + // Sync published post's file with updated tags + await getPostEngine().syncPublishedPostFile(postId); + totalPostsUpdated++; } } @@ -601,6 +608,9 @@ export class TagEngine extends EventEmitter { }) .where(eq(posts.id, postId)); + // Sync published post's file with updated tags + await getPostEngine().syncPublishedPostFile(postId); + updated++; onProgress((updated / total) * 80, `Updated ${updated}/${total} posts...`); } diff --git a/tests/engine/TagEngine.test.ts b/tests/engine/TagEngine.test.ts index 0f0e1e4..8b148ab 100644 --- a/tests/engine/TagEngine.test.ts +++ b/tests/engine/TagEngine.test.ts @@ -123,6 +123,13 @@ vi.mock('../../src/main/engine/TaskManager', () => ({ }, })); +// Mock PostEngine - only mock the syncPublishedPostFile method used by TagEngine +vi.mock('../../src/main/engine/PostEngine', () => ({ + getPostEngine: vi.fn(() => ({ + syncPublishedPostFile: vi.fn(async () => true), + })), +})); + describe('TagEngine', () => { let tagEngine: TagEngine;