aboutsummaryrefslogtreecommitdiffstats
path: root/packages/trpc/models
diff options
context:
space:
mode:
authoromnitrix <gaobowei.ovo@gmail.com>2025-04-16 16:18:04 +0200
committerGitHub <noreply@github.com>2025-04-16 15:18:04 +0100
commit71a474268e6381f8630f6d906471c830342dc50f (patch)
treee7dc62795d4b7aad1daeff78c94c12e63c38f3ef /packages/trpc/models
parentdd990b51f3f85f70298a9b437b16ee7bbb406d24 (diff)
downloadkarakeep-71a474268e6381f8630f6d906471c830342dc50f.tar.zst
feat(web): Add support for merging lists (#1231)
* feat: Support list merging * some fixes * move @hoarder to @karakeep --------- Co-authored-by: Mohamed Bassem <me@mbassem.com>
Diffstat (limited to 'packages/trpc/models')
-rw-r--r--packages/trpc/models/lists.ts46
1 files changed, 46 insertions, 0 deletions
diff --git a/packages/trpc/models/lists.ts b/packages/trpc/models/lists.ts
index a6b1720c..8072060f 100644
--- a/packages/trpc/models/lists.ts
+++ b/packages/trpc/models/lists.ts
@@ -145,6 +145,10 @@ export abstract class List implements PrivacyAware {
abstract getSize(ctx: AuthedContext): Promise<number>;
abstract addBookmark(bookmarkId: string): Promise<void>;
abstract removeBookmark(bookmarkId: string): Promise<void>;
+ abstract mergeInto(
+ targetList: List,
+ deleteSourceAfterMerge: boolean,
+ ): Promise<void>;
}
export class SmartList extends List {
@@ -200,6 +204,16 @@ export class SmartList extends List {
message: "Smart lists cannot be removed from",
});
}
+
+ mergeInto(
+ _targetList: List,
+ _deleteSourceAfterMerge: boolean,
+ ): Promise<void> {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: "Smart lists cannot be merged",
+ });
+ }
}
export class ManualList extends List {
@@ -276,4 +290,36 @@ export class ManualList extends List {
}
return super.update(input);
}
+
+ async mergeInto(
+ targetList: List,
+ deleteSourceAfterMerge: boolean,
+ ): Promise<void> {
+ if (targetList.type !== "manual") {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: "You can only merge into a manual list",
+ });
+ }
+
+ const bookmarkIds = await this.getBookmarkIds();
+
+ await this.ctx.db.transaction(async (tx) => {
+ await tx
+ .insert(bookmarksInLists)
+ .values(
+ bookmarkIds.map((id) => ({
+ bookmarkId: id,
+ listId: targetList.list.id,
+ })),
+ )
+ .onConflictDoNothing();
+
+ if (deleteSourceAfterMerge) {
+ await tx
+ .delete(bookmarkLists)
+ .where(eq(bookmarkLists.id, this.list.id));
+ }
+ });
+ }
}