diff --git a/src/routes/api/autocomplete.js b/src/routes/api/autocomplete.js index ef0b13724..28dfaf164 100644 --- a/src/routes/api/autocomplete.js +++ b/src/routes/api/autocomplete.js @@ -1,6 +1,7 @@ "use strict"; -const noteCacheService = require('../../services/note_cache/note_cache.js'); +const noteCacheService = require('../../services/note_cache/note_cache_service'); +const searchService = require('../../services/search/search'); const repository = require('../../services/repository'); const log = require('../../services/log'); const utils = require('../../services/utils'); @@ -18,7 +19,7 @@ async function getAutocomplete(req) { results = await getRecentNotes(activeNoteId); } else { - results = await noteCacheService.findNotesForAutocomplete(query); + results = await searchService.searchNotesForAutocomplete(query); } const msTaken = Date.now() - timestampStarted; diff --git a/src/routes/api/similar_notes.js b/src/routes/api/similar_notes.js index 22ddf427a..c04dc29f1 100644 --- a/src/routes/api/similar_notes.js +++ b/src/routes/api/similar_notes.js @@ -1,6 +1,6 @@ "use strict"; -const noteCacheService = require('../../services/note_cache/note_cache.js'); +const noteCacheService = require('../../services/note_cache/note_cache_service'); const repository = require('../../services/repository'); async function getSimilarNotes(req) { diff --git a/src/services/note_cache/entities/attribute.js b/src/services/note_cache/entities/attribute.js index beb605fbf..116c4b719 100644 --- a/src/services/note_cache/entities/attribute.js +++ b/src/services/note_cache/entities/attribute.js @@ -1,9 +1,9 @@ "use strict"; -const noteCache = require('../note_cache'); - class Attribute { - constructor(row) { + constructor(noteCache, row) { + /** @param {NoteCache} */ + this.noteCache = noteCache; /** @param {string} */ this.attributeId = row.attributeId; /** @param {string} */ @@ -17,11 +17,11 @@ class Attribute { /** @param {boolean} */ this.isInheritable = !!row.isInheritable; - noteCache.notes[this.noteId].ownedAttributes.push(this); + this.noteCache.notes[this.noteId].ownedAttributes.push(this); const key = `${this.type-this.name}`; - noteCache.attributeIndex[key] = noteCache.attributeIndex[key] || []; - noteCache.attributeIndex[key].push(this); + this.noteCache.attributeIndex[key] = this.noteCache.attributeIndex[key] || []; + this.noteCache.attributeIndex[key].push(this); const targetNote = this.targetNote; @@ -36,12 +36,12 @@ class Attribute { } get note() { - return noteCache.notes[this.noteId]; + return this.noteCache.notes[this.noteId]; } get targetNote() { if (this.type === 'relation') { - return noteCache.notes[this.value]; + return this.noteCache.notes[this.value]; } } } diff --git a/src/services/note_cache/entities/branch.js b/src/services/note_cache/entities/branch.js index 07d4221f6..b3a3af904 100644 --- a/src/services/note_cache/entities/branch.js +++ b/src/services/note_cache/entities/branch.js @@ -1,9 +1,9 @@ "use strict"; -const noteCache = require('../note_cache'); - class Branch { - constructor(row) { + constructor(noteCache, row) { + /** @param {NoteCache} */ + this.noteCache = noteCache; /** @param {string} */ this.branchId = row.branchId; /** @param {string} */ @@ -17,7 +17,7 @@ class Branch { return; } - const childNote = noteCache.notes[this.noteId]; + const childNote = this.noteCache.notes[this.noteId]; const parentNote = this.parentNote; if (!childNote) { @@ -30,12 +30,12 @@ class Branch { parentNote.children.push(childNote); - noteCache.childParentToBranch[`${this.noteId}-${this.parentNoteId}`] = this; + this.noteCache.childParentToBranch[`${this.noteId}-${this.parentNoteId}`] = this; } /** @return {Note} */ get parentNote() { - const note = noteCache.notes[this.parentNoteId]; + const note = this.noteCache.notes[this.parentNoteId]; if (!note) { console.log(`Cannot find note ${this.parentNoteId}`); diff --git a/src/services/note_cache/entities/note.js b/src/services/note_cache/entities/note.js index d86508e80..adc120d15 100644 --- a/src/services/note_cache/entities/note.js +++ b/src/services/note_cache/entities/note.js @@ -1,9 +1,12 @@ "use strict"; const noteCache = require('../note_cache'); +const protectedSessionService = require('../../protected_session'); class Note { - constructor(row) { + constructor(noteCache, row) { + /** @param {NoteCache} */ + this.noteCache = noteCache; /** @param {string} */ this.noteId = row.noteId; /** @param {string} */ @@ -33,7 +36,7 @@ class Note { this.flatTextCache = null; if (protectedSessionService.isProtectedSessionAvailable()) { - noteCache.decryptProtectedNote(this); + this.decrypt(); } } @@ -52,7 +55,7 @@ class Note { for (const ownedAttr of parentAttributes) { // parentAttributes so we process also inherited templates if (ownedAttr.type === 'relation' && ownedAttr.name === 'template') { - const templateNote = notes[ownedAttr.value]; + const templateNote = this.noteCache.notes[ownedAttr.value]; if (templateNote) { templateAttributes.push(...templateNote.attributes); diff --git a/src/services/note_cache/note_cache.js b/src/services/note_cache/note_cache.js index 974377dc5..8aaa688bc 100644 --- a/src/services/note_cache/note_cache.js +++ b/src/services/note_cache/note_cache.js @@ -33,15 +33,15 @@ class NoteCache { await sqlInit.dbReady; this.notes = await this.getMappedRows(`SELECT noteId, title, isProtected FROM notes WHERE isDeleted = 0`, - row => new Note(row)); + row => new Note(this, row)); this.branches = await this.getMappedRows(`SELECT branchId, noteId, parentNoteId, prefix FROM branches WHERE isDeleted = 0`, - row => new Branch(row)); + row => new Branch(this, row)); this.attributeIndex = []; this.attributes = await this.getMappedRows(`SELECT attributeId, noteId, type, name, value, isInheritable FROM attributes WHERE isDeleted = 0`, - row => new Attribute(row)); + row => new Attribute(this, row)); this.loaded = true; } @@ -94,13 +94,13 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED note.isDecrypted = !entity.isProtected || !!entity.isContentAvailable; note.flatTextCache = null; - noteCache.decryptProtectedNote(note); + note.decrypt(); } else { const note = new Note(entity); noteCache.notes[noteId] = note; - noteCache.decryptProtectedNote(note); + note.decrypt(); } } else if (entityName === 'branches') { diff --git a/src/services/note_cache/note_cache_service.js b/src/services/note_cache/note_cache_service.js index 3b567c2a9..8007c9cb3 100644 --- a/src/services/note_cache/note_cache_service.js +++ b/src/services/note_cache/note_cache_service.js @@ -2,6 +2,7 @@ const noteCache = require('./note_cache'); const hoistedNoteService = require('../hoisted_note'); +const stringSimilarity = require('string-similarity'); function isNotePathArchived(notePath) { const noteId = notePath[notePath.length - 1]; @@ -69,7 +70,7 @@ function getNoteTitle(childNoteId, parentNoteId) { title = childNote.title; } - const branch = parentNote ? getBranch(childNote.noteId, parentNote.noteId) : null; + const branch = parentNote ? noteCache.getBranch(childNote.noteId, parentNote.noteId) : null; return ((branch && branch.prefix) ? `${branch.prefix} - ` : '') + title; } @@ -199,7 +200,7 @@ async function findSimilarNotes(noteId) { return []; } - for (const note of Object.values(notes)) { + for (const note of Object.values(noteCache.notes)) { if (note.isProtected && !note.isDecrypted) { continue; } @@ -229,7 +230,9 @@ function isAvailable(noteId) { } module.exports = { + getSomePath, getNotePath, + getNoteTitle, getNoteTitleForPath, isAvailable, isArchived, diff --git a/src/services/search/expressions/equals.js b/src/services/search/expressions/equals.js index ab6e69b60..e5e04b3d8 100644 --- a/src/services/search/expressions/equals.js +++ b/src/services/search/expressions/equals.js @@ -1,5 +1,8 @@ "use strict"; +const NoteSet = require('../note_set'); +const noteCache = require('../../note_cache/note_cache'); + class EqualsExp { constructor(attributeType, attributeName, attributeValue) { this.attributeType = attributeType; @@ -8,7 +11,7 @@ class EqualsExp { } execute(noteSet) { - const attrs = findAttributes(this.attributeType, this.attributeName); + const attrs = noteCache.findAttributes(this.attributeType, this.attributeName); const resultNoteSet = new NoteSet(); for (const attr of attrs) { diff --git a/src/services/search/expressions/exists.js b/src/services/search/expressions/exists.js index 781fd0604..25c3a9245 100644 --- a/src/services/search/expressions/exists.js +++ b/src/services/search/expressions/exists.js @@ -1,5 +1,8 @@ "use strict"; +const NoteSet = require('../note_set'); +const noteCache = require('../../note_cache/note_cache'); + class ExistsExp { constructor(attributeType, attributeName) { this.attributeType = attributeType; @@ -7,7 +10,7 @@ class ExistsExp { } execute(noteSet) { - const attrs = findAttributes(this.attributeType, this.attributeName); + const attrs = noteCache.findAttributes(this.attributeType, this.attributeName); const resultNoteSet = new NoteSet(); for (const attr of attrs) { diff --git a/src/services/search/expressions/note_cache_fulltext.js b/src/services/search/expressions/note_cache_fulltext.js index 3d3e1bcff..f09df1e88 100644 --- a/src/services/search/expressions/note_cache_fulltext.js +++ b/src/services/search/expressions/note_cache_fulltext.js @@ -1,5 +1,9 @@ "use strict"; +const NoteSet = require('../note_set'); +const noteCache = require('../../note_cache/note_cache'); +const noteCacheService = require('../../note_cache/note_cache_service'); + class NoteCacheFulltextExp { constructor(tokens) { this.tokens = tokens; @@ -34,7 +38,7 @@ class NoteCacheFulltextExp { } for (const parentNote of note.parents) { - const title = getNoteTitle(note.noteId, parentNote.noteId).toLowerCase(); + const title = noteCacheService.getNoteTitle(note.noteId, parentNote.noteId).toLowerCase(); const foundTokens = foundAttrTokens.slice(); for (const token of this.tokens) { @@ -77,13 +81,13 @@ class NoteCacheFulltextExp { searchDownThePath(note, tokens, path, resultNoteSet, searchContext) { if (tokens.length === 0) { - const retPath = getSomePath(note, path); + const retPath = noteCacheService.getSomePath(note, path); if (retPath) { const noteId = retPath[retPath.length - 1]; searchContext.noteIdToNotePath[noteId] = retPath; - resultNoteSet.add(notes[noteId]); + resultNoteSet.add(noteCache.notes[noteId]); } return; @@ -105,7 +109,7 @@ class NoteCacheFulltextExp { } for (const parentNote of note.parents) { - const title = getNoteTitle(note.noteId, parentNote.noteId).toLowerCase(); + const title = noteCacheService.getNoteTitle(note.noteId, parentNote.noteId).toLowerCase(); const foundTokens = foundAttrTokens.slice(); for (const token of tokens) { diff --git a/src/services/search/expressions/note_content_fulltext.js b/src/services/search/expressions/note_content_fulltext.js index a7a5a4f7a..4d6900802 100644 --- a/src/services/search/expressions/note_content_fulltext.js +++ b/src/services/search/expressions/note_content_fulltext.js @@ -1,5 +1,8 @@ "use strict"; +const NoteSet = require('../note_set'); +const noteCache = require('../../note_cache/note_cache'); + class NoteContentFulltextExp { constructor(tokens) { this.tokens = tokens; @@ -18,8 +21,8 @@ class NoteContentFulltextExp { const results = []; for (const noteId of noteIds) { - if (noteSet.hasNoteId(noteId) && noteId in notes) { - resultNoteSet.add(notes[noteId]); + if (noteSet.hasNoteId(noteId) && noteId in noteCache.notes) { + resultNoteSet.add(noteCache.notes[noteId]); } } diff --git a/src/services/note_cache/note_set.js b/src/services/search/note_set.js similarity index 100% rename from src/services/note_cache/note_set.js rename to src/services/search/note_set.js diff --git a/src/services/search/search.js b/src/services/search/search.js index 09f6f0031..defc4cc7b 100644 --- a/src/services/search/search.js +++ b/src/services/search/search.js @@ -1,13 +1,18 @@ "use strict"; -import NoteCacheFulltextExp from "./expressions/note_cache_fulltext.js"; +const NoteCacheFulltextExp = require("./expressions/note_cache_fulltext"); +const NoteSet = require("./note_set"); +const SearchResult = require("./search_result"); +const noteCache = require('../note_cache/note_cache'); +const hoistedNoteService = require('../hoisted_note'); +const utils = require('../utils'); async function findNotesWithExpression(expression) { - const hoistedNote = notes[hoistedNoteService.getHoistedNoteId()]; + const hoistedNote = noteCache.notes[hoistedNoteService.getHoistedNoteId()]; const allNotes = (hoistedNote && hoistedNote.noteId !== 'root') ? hoistedNote.subtreeNotes - : Object.values(notes); + : Object.values(noteCache.notes); const allNoteSet = new NoteSet(allNotes); @@ -35,7 +40,7 @@ async function findNotesWithExpression(expression) { return searchResults; } -async function findNotesForAutocomplete(query) { +async function searchNotesForAutocomplete(query) { if (!query.trim().length) { return []; } @@ -73,7 +78,7 @@ function highlightSearchResults(searchResults, tokens) { tokens.sort((a, b) => a.length > b.length ? -1 : 1); for (const result of searchResults) { - const note = notes[result.noteId]; + const note = noteCache.notes[result.noteId]; result.highlightedNotePathTitle = result.notePathTitle; @@ -115,3 +120,7 @@ function formatAttribute(attr) { return label; } } + +module.exports = { + searchNotesForAutocomplete +};