mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-24 20:20:21 +01:00
188 lines
4.3 KiB
JavaScript
188 lines
4.3 KiB
JavaScript
/*
|
|
This file is part of the Notesnook project (https://notesnook.com/)
|
|
|
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import { makeId } from "../utils/id";
|
|
import Collection from "./collection";
|
|
|
|
/**
|
|
* @typedef {{
|
|
* id: string;
|
|
* type: string;
|
|
* }} ItemReference
|
|
*
|
|
* @typedef {{
|
|
* id: string;
|
|
* type: string;
|
|
* from: ItemReference;
|
|
* to: ItemReference;
|
|
* dateCreated: number;
|
|
* dateModified: number;
|
|
* }} Relation
|
|
*/
|
|
|
|
export default class Relations extends Collection {
|
|
async merge(relation) {
|
|
if (!relation) return;
|
|
await this._collection.addItem(relation);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {ItemReference} from
|
|
* @param {ItemReference} to
|
|
*/
|
|
async add(from, to) {
|
|
if (
|
|
this.all.find(
|
|
(a) =>
|
|
compareItemReference(a.from, from) && compareItemReference(a.to, to)
|
|
)
|
|
)
|
|
return;
|
|
|
|
const relation = {
|
|
id: generateId(from, to),
|
|
type: "relation",
|
|
dateCreated: Date.now(),
|
|
dateModified: Date.now(),
|
|
from: { id: from.id, type: from.type },
|
|
to: { id: to.id, type: to.type }
|
|
};
|
|
|
|
await this._collection.addItem(relation);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {ItemReference} reference
|
|
* @param {string} type
|
|
*/
|
|
from(reference, type) {
|
|
const relations = this.all.filter(
|
|
(a) => compareItemReference(a.from, reference) && a.to.type === type
|
|
);
|
|
return this.resolve(relations, "to");
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {ItemReference} reference
|
|
* @param {string} type
|
|
*/
|
|
to(reference, type) {
|
|
const relations = this.all.filter(
|
|
(a) => compareItemReference(a.to, reference) && a.from.type === type
|
|
);
|
|
return this.resolve(relations, "from");
|
|
}
|
|
|
|
get raw() {
|
|
return this._collection.getRaw();
|
|
}
|
|
|
|
/**
|
|
* @return {Relation[]}
|
|
*/
|
|
get all() {
|
|
return this._collection.getItems();
|
|
}
|
|
|
|
/**
|
|
* @return {Relation}
|
|
*/
|
|
relation(id) {
|
|
return this._collection.getItem(id);
|
|
}
|
|
|
|
async remove(...ids) {
|
|
for (const id of ids) {
|
|
await this._collection.removeItem(id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Relation[]} relations
|
|
* @param {"from" | "to"} resolveType
|
|
* @private
|
|
*
|
|
* @returns {Relation[]}
|
|
*/
|
|
resolve(relations, resolveType) {
|
|
const items = [];
|
|
for (const relation of relations) {
|
|
const reference = resolveType === "from" ? relation.from : relation.to;
|
|
|
|
let item = null;
|
|
switch (reference.type) {
|
|
case "reminder":
|
|
item = this._db.reminders.reminder(reference.id);
|
|
break;
|
|
case "note": {
|
|
const note = this._db.notes.note(reference.id);
|
|
if (!note) continue;
|
|
item = note.data;
|
|
break;
|
|
}
|
|
}
|
|
if (item) items.push(item);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
async cleanup() {
|
|
const relations = this._collection.getItems();
|
|
for (const relation of relations) {
|
|
const references = [relation.to, relation.from];
|
|
for (let reference of references) {
|
|
let exists = false;
|
|
switch (reference.type) {
|
|
case "reminder":
|
|
exists = this._db.reminders.exists(reference.id);
|
|
break;
|
|
case "note":
|
|
exists =
|
|
this._db.notes.exists(reference.id) ||
|
|
this._db.trash.exists(reference.id);
|
|
break;
|
|
}
|
|
if (!exists) await this.remove(relation.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {ItemReference} a
|
|
* @param {ItemReference} b
|
|
*/
|
|
function compareItemReference(a, b) {
|
|
return a.id === b.id && a.type === b.type;
|
|
}
|
|
|
|
/**
|
|
* Generate deterministic constant id from `a` & `b` item reference.
|
|
* @param {ItemReference} a
|
|
* @param {ItemReference} b
|
|
*/
|
|
function generateId(a, b) {
|
|
const str = `${a.id}${b.id}${a.type}${b.type}`;
|
|
return makeId(str);
|
|
}
|