diff --git a/packages/core/__tests__/notes.test.js b/packages/core/__tests__/notes.test.js index 080dd995e..6d91c4cb3 100644 --- a/packages/core/__tests__/notes.test.js +++ b/packages/core/__tests__/notes.test.js @@ -64,7 +64,22 @@ test("add note", () => expect(id).toBeDefined(); let note = db.notes.get(id); expect(note).toBeDefined(); - expect(note.content).toStrictEqual(TEST_NOTE.content); + expect(note.content.text).toStrictEqual(TEST_NOTE.content.text); + })); + +test("get delta of note", () => + noteTest().then(async ({ db, id }) => { + expect(id).toBeDefined(); + let delta = await db.notes.delta(id); + expect(delta).toStrictEqual(TEST_NOTE.content.delta); + })); + +test("delete note", () => + noteTest().then(async ({ db, id }) => { + expect(id).toBeDefined(); + await db.notes.delete(id); + let note = db.notes.get(id); + expect(note).toBeUndefined(); })); test("get all notes", () => @@ -102,7 +117,7 @@ test("update note", () => id = await db.notes.add(noteData); let note = db.notes.get(id); expect(note.title).toBe(noteData.title); - expect(note.content).toStrictEqual(noteData.content); + expect(note.content.text).toStrictEqual(noteData.content.text); expect(note.pinned).toBe(true); expect(note.favorite).toBe(true); })); @@ -226,7 +241,7 @@ test("lock and unlock note", () => expect(note.locked).toBe(true); expect(note.content.iv).toBeDefined(); note = await db.notes.unlock(id, "password123"); - expect(note.dateCreated).toBe(id); + expect(note.id).toBe(id); expect(note.content.text).toBe(TEST_NOTE.content.text); await db.notes.unlock(id, "password123", true); note = db.notes.get(id); diff --git a/packages/core/collections/notes.js b/packages/core/collections/notes.js index e2ff1aa99..22aa06c4c 100644 --- a/packages/core/collections/notes.js +++ b/packages/core/collections/notes.js @@ -1,12 +1,14 @@ -import Collection from "../database/collection"; +import CachedCollection from "../database/cached-collection"; import fuzzysearch from "fuzzysearch"; import Tags from "./tags"; import { groupBy } from "../utils"; +import sort from "fast-sort"; import { getWeekGroupFromTimestamp, months, getLastWeekTimestamp } from "../utils/date"; +import Storage from "../database/storage"; var tfun = require("transfun/transfun.js").tfun; if (!tfun) { tfun = global.tfun; @@ -14,7 +16,8 @@ if (!tfun) { export default class Notes { constructor(context) { - this.collection = new Collection(context, "notes"); + this.collection = new CachedCollection(context, "notes"); + this.deltaStorage = new Storage(context); this.tagsCollection = new Tags(context); } @@ -25,7 +28,7 @@ export default class Notes { async add(noteArg) { if (!noteArg) return; - let id = noteArg.id || Date.now(); + let id = noteArg.id || Date.now().toString() + "_note"; let oldNote = this.get(id); let note = { ...oldNote, @@ -37,11 +40,13 @@ export default class Notes { return; } + await this.deltaStorage.write(id + "_delta", note.content.delta); + note = { id, type: "note", title: getNoteTitle(note), - content: getNoteContent(note), + content: getNoteContent(note, id), pinned: !!note.pinned, locked: !!note.locked, notebook: note.notebook || {}, @@ -50,7 +55,7 @@ export default class Notes { favorite: !!note.favorite, headline: getNoteHeadline(note), dateEdited: Date.now(), - dateCreated: id + dateCreated: note.dateCreated || Date.now() }; if (oldNote) { @@ -62,7 +67,11 @@ export default class Notes { } await this.collection.addItem(note); - return id; + return note.id; + } + + async delta(id) { + return await this.deltaStorage.read(id + "_delta"); } get(id) { @@ -103,7 +112,8 @@ export default class Notes { switch (by) { case "abc": return groupBy( - notes.sort((a, b) => a.title.localeCompare(b.title)), + //notes.sort((a, b) => a.title.localeCompare(b.title)), + sort(notes).asc(t => t.title), note => note.title[0].toUpperCase(), special ); @@ -266,12 +276,13 @@ function getNoteTitle(note) { .trim(); } -function getNoteContent(note) { +function getNoteContent(note, id) { if (note.locked) { return note.content; } + return { text: note.content.text.trim(), - delta: note.content.delta + delta: id + "_delta" }; } diff --git a/packages/core/collections/tags.js b/packages/core/collections/tags.js index 2cde46643..b3f02df31 100644 --- a/packages/core/collections/tags.js +++ b/packages/core/collections/tags.js @@ -1,8 +1,8 @@ -import Collection from "../database/collection"; +import CachedCollection from "../database/cached-collection"; export default class Tags { constructor(context) { - this.collection = new Collection(context, "tags"); + this.collection = new CachedCollection(context, "tags"); } async add(id) { diff --git a/packages/core/database/collection.js b/packages/core/database/cached-collection.js similarity index 82% rename from packages/core/database/collection.js rename to packages/core/database/cached-collection.js index 8a6f8e49d..e6654d5a4 100644 --- a/packages/core/database/collection.js +++ b/packages/core/database/cached-collection.js @@ -1,6 +1,6 @@ import Indexer from "./indexer"; -export default class Collection { +export default class CachedCollection { constructor(context, type) { this.map = new Map(); this.indexer = new Indexer(context, type); @@ -14,6 +14,8 @@ export default class Collection { } async addItem(item) { + if (!item.id) throw new Error("The item must contain the id field."); + let exists = this.map.has(item.id); await this.updateItem(item); if (!exists) { @@ -22,6 +24,8 @@ export default class Collection { } async updateItem(item) { + if (!item.id) throw new Error("The item must contain the id field."); + this.map.set(item.id, item); await this.indexer.write(item.id, item); } diff --git a/packages/core/database/indexer.js b/packages/core/database/indexer.js index 73469b56f..f71e8af60 100644 --- a/packages/core/database/indexer.js +++ b/packages/core/database/indexer.js @@ -11,18 +11,16 @@ export default class Indexer extends Storage { this.indices = (await this.read(this.type)) || []; } + async exists(key) { + return this.indices.includes(key); + } + async index(key) { - if (this.indices.length <= 0) { - this.indices = (await this.read(this.type)) || []; - } this.indices[this.indices.length] = key; await this.write(this.type, this.indices); } async getIndices() { - if (this.indices.length <= 0) { - this.indices = (await this.read(this.type)) || []; - } return this.indices; } diff --git a/packages/core/database/storage.js b/packages/core/database/storage.js index ce107ca16..f8bbe1ac4 100644 --- a/packages/core/database/storage.js +++ b/packages/core/database/storage.js @@ -1,15 +1,13 @@ -import Convert from "../utils/convert"; - export default class Storage { constructor(context) { this.storage = context; } async write(key, data) { - await this.storage.write(key, Convert.toString(data)); + await this.storage.write(key, data); } async read(key) { let data = await this.storage.read(key); - return Convert.fromString(data); + return data; } clear() { this.storage.clear(); diff --git a/packages/core/package.json b/packages/core/package.json index e6e8acb33..00d748bfe 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -16,8 +16,9 @@ "test": "jest" }, "dependencies": { + "fast-sort": "^2.0.1", "fuzzysearch": "^1.0.3", - "transfun": "^1.0.2", - "node-fetch": "^2.6.0" + "node-fetch": "^2.6.0", + "transfun": "^1.0.2" } } diff --git a/packages/core/yarn.lock b/packages/core/yarn.lock index 63125eb3a..b709782fe 100644 --- a/packages/core/yarn.lock +++ b/packages/core/yarn.lock @@ -2171,6 +2171,11 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-sort@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-sort/-/fast-sort-2.0.1.tgz#71d932d2de380d0d6ca449fdc5dbdefdc437e84a" + integrity sha512-61gSQXW5KavRau+RBlQbpD3q+tUyrHSKiU/wob4RP58s99uIpydII6MaRpA+t6Td6/WhvU0lgL8UoMPKKv4xYg== + fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"