diff --git a/packages/core/src/collections/notes.ts b/packages/core/src/collections/notes.ts index fc0abcb28..8e84b75ba 100644 --- a/packages/core/src/collections/notes.ts +++ b/packages/core/src/collections/notes.ts @@ -318,17 +318,9 @@ export class Notes implements ICollection { const content = note.contentId ? await this.db.content.get(note.contentId) : undefined; - if (content && (isDeleted(content) || content.locked)) - throw new Error("Cannot duplicate a locked or deleted note."); const duplicateId = await this.db.notes.add({ ...clone(note), id: undefined, - content: content - ? { - type: content.type, - data: content.data - } - : undefined, readonly: false, favorite: false, pinned: false, @@ -338,19 +330,38 @@ export class Notes implements ICollection { dateCreated: undefined, dateModified: undefined }); - if (!duplicateId) continue; - for (const relation of await this.db.relations - .to(note, "notebook") - .get()) { + const contentId = await this.db.content.add({ + ...clone(content), + id: undefined, + noteId: duplicateId, + dateResolved: undefined, + dateEdited: undefined, + dateCreated: undefined, + dateModified: undefined + }); + + await this.db.notes.add({ id: duplicateId, contentId }); + + for (const relation of await this.db.relations.to(note).get()) { await this.db.relations.add( - { type: "notebook", id: relation.fromId }, + { type: relation.fromType, id: relation.fromId }, { id: duplicateId, type: "note" } ); } + + for (const relation of await this.db.relations.from(note).get()) { + await this.db.relations.add( + { + id: duplicateId, + type: "note" + }, + { type: relation.toType, id: relation.toId } + ); + } } } diff --git a/packages/core/src/collections/relations.ts b/packages/core/src/collections/relations.ts index ad233eabe..a6a6a1111 100644 --- a/packages/core/src/collections/relations.ts +++ b/packages/core/src/collections/relations.ts @@ -63,6 +63,9 @@ export class Relations implements ICollection { }); } + from( + reference: ItemReference | ItemReferences + ): RelationsArray; from( reference: ItemReference | ItemReferences, types: (keyof RelatableTable)[] @@ -73,16 +76,19 @@ export class Relations implements ICollection { ): RelationsArray; from( reference: ItemReference | ItemReferences, - type: TType | keyof RelatableTable[] + type?: TType | keyof RelatableTable[] ) { return new RelationsArray( this.db, reference, - Array.isArray(type) ? type : [type], + type ? (Array.isArray(type) ? type : ([type] as TType[])) : undefined, "from" ); } + to( + reference: ItemReference | ItemReferences + ): RelationsArray; to( reference: ItemReference | ItemReferences, types: (keyof RelatableTable)[] @@ -93,12 +99,12 @@ export class Relations implements ICollection { ): RelationsArray; to( reference: ItemReference | ItemReferences, - type: TType | keyof RelatableTable[] + type?: TType | keyof RelatableTable[] ) { return new RelationsArray( this.db, reference, - Array.isArray(type) ? type : [type], + type ? (Array.isArray(type) ? type : ([type] as TType[])) : undefined, "to" ); } @@ -224,21 +230,26 @@ const TABLE_MAP = { type RelatableTable = typeof TABLE_MAP; class RelationsArray { - private table: ValueOf = TABLE_MAP[this.types[0]]; - constructor( private readonly db: Database, private readonly reference: ItemReference | ItemReferences, - private readonly types: TType[], + private readonly types: TType[] | undefined, private readonly direction: "from" | "to" ) {} get selector() { + if (!this.types) + throw new Error("Cannot use selector when no tables are specified."); + if (this.types.length > 1) + throw new Error( + "Cannot use selector when more than 1 tables are specified." + ); + const table: ValueOf = TABLE_MAP[this.types[0]]; return new FilteredSelector( - this.table, + table, this.db .sql() - .selectFrom(this.table) + .selectFrom(table) .where("id", "in", (b) => b .selectFrom("relations") @@ -356,10 +367,12 @@ class RelationsArray { ) => { if (this.direction === "to") { return builder - .where( - "fromType", - this.types.length > 1 ? "in" : "==", - this.types.length > 1 ? this.types : this.types[0] + .$if(!!this.types, (eb) => + eb.where( + "fromType", + this.types!.length > 1 ? "in" : "==", + this.types!.length > 1 ? this.types : this.types![0] + ) ) .where("toType", "==", this.reference.type) .where( @@ -370,12 +383,12 @@ class RelationsArray { : this.reference.id ) .$if( - this.types.includes("note" as TType) && + !!this.types?.includes("note" as TType) && this.db.trash.cache.notes.length > 0, (b) => b.where("fromId", "not in", this.db.trash.cache.notes) ) .$if( - this.types.includes("notebook" as TType) && + !!this.types?.includes("notebook" as TType) && this.db.trash.cache.notebooks.length > 0, (b) => b.where("fromId", "not in", this.db.trash.cache.notebooks) ) @@ -383,10 +396,12 @@ class RelationsArray { .$narrowType<{ id: string }>(); } else { return builder - .where( - "toType", - this.types.length > 1 ? "in" : "==", - this.types.length > 1 ? this.types : this.types[0] + .$if(!!this.types, (eb) => + eb.where( + "toType", + this.types!.length > 1 ? "in" : "==", + this.types!.length > 1 ? this.types : this.types![0] + ) ) .where("fromType", "==", this.reference.type) .where( @@ -397,12 +412,12 @@ class RelationsArray { : this.reference.id ) .$if( - this.types.includes("note" as TType) && + !!this.types?.includes("note" as TType) && this.db.trash.cache.notes.length > 0, (b) => b.where("toId", "not in", this.db.trash.cache.notes) ) .$if( - this.types.includes("notebook" as TType) && + !!this.types?.includes("notebook" as TType) && this.db.trash.cache.notebooks.length > 0, (b) => b.where("toId", "not in", this.db.trash.cache.notebooks) )