From 414964e791aff08ae0b1a7a62a1edf9d574d762d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 18 Feb 2024 01:01:17 +0200 Subject: [PATCH] server-ts: Port services/search/expressions/note_content_fulltext --- src/becca/entities/rows.ts | 1 + ...t_fulltext.js => note_content_fulltext.ts} | 57 ++++++++++++------- src/services/search/services/parse.js | 2 +- src/services/sql.ts | 4 +- 4 files changed, 41 insertions(+), 23 deletions(-) rename src/services/search/expressions/{note_content_fulltext.js => note_content_fulltext.ts} (70%) diff --git a/src/becca/entities/rows.ts b/src/becca/entities/rows.ts index 331f150df..cf7dae4ac 100644 --- a/src/becca/entities/rows.ts +++ b/src/becca/entities/rows.ts @@ -106,6 +106,7 @@ export interface NoteRow { dateModified: string; utcDateCreated: string; utcDateModified: string; + content?: string; } export interface AttributeRow { diff --git a/src/services/search/expressions/note_content_fulltext.js b/src/services/search/expressions/note_content_fulltext.ts similarity index 70% rename from src/services/search/expressions/note_content_fulltext.js rename to src/services/search/expressions/note_content_fulltext.ts index f8a937f6a..ab80e21eb 100644 --- a/src/services/search/expressions/note_content_fulltext.js +++ b/src/services/search/expressions/note_content_fulltext.ts @@ -1,18 +1,22 @@ "use strict"; -const Expression = require('./expression'); -const NoteSet = require('../note_set'); -const log = require('../../log'); -const becca = require('../../../becca/becca'); -const protectedSessionService = require('../../protected_session'); -const striptags = require('striptags'); -const utils = require('../../utils'); +import { NoteRow } from "../../../becca/entities/rows"; +import SearchContext = require("../search_context"); + +import Expression = require('./expression'); +import NoteSet = require('../note_set'); +import log = require('../../log'); +import becca = require('../../../becca/becca'); +import protectedSessionService = require('../../protected_session'); +import striptags = require('striptags'); +import utils = require('../../utils'); +import sql = require("../../sql"); const ALLOWED_OPERATORS = ['=', '!=', '*=*', '*=', '=*', '%=']; -const cachedRegexes = {}; +const cachedRegexes: Record = {}; -function getRegex(str) { +function getRegex(str: string): RegExp { if (!(str in cachedRegexes)) { cachedRegexes[str] = new RegExp(str, 'ms'); // multiline, dot-all } @@ -20,8 +24,22 @@ function getRegex(str) { return cachedRegexes[str]; } +interface ConstructorOpts { + tokens: string[]; + raw: boolean; + flatText: boolean; +} + +type SearchRow = Pick; + class NoteContentFulltextExp extends Expression { - constructor(operator, {tokens, raw, flatText}) { + + private operator: string; + private tokens: string[]; + private raw: boolean; + private flatText: boolean; + + constructor(operator: string, {tokens, raw, flatText}: ConstructorOpts) { super(); this.operator = operator; @@ -30,7 +48,7 @@ class NoteContentFulltextExp extends Expression { this.flatText = !!flatText; } - execute(inputNoteSet, executionContext, searchContext) { + execute(inputNoteSet: NoteSet, executionContext: {}, searchContext: SearchContext) { if (!ALLOWED_OPERATORS.includes(this.operator)) { searchContext.addError(`Note content can be searched only with operators: ${ALLOWED_OPERATORS.join(", ")}, operator ${this.operator} given.`); @@ -38,9 +56,8 @@ class NoteContentFulltextExp extends Expression { } const resultNoteSet = new NoteSet(); - const sql = require('../../sql'); - - for (const row of sql.iterateRows(` + + for (const row of sql.iterateRows(` SELECT noteId, type, mime, content, isProtected FROM notes JOIN blobs USING (blobId) WHERE type IN ('text', 'code', 'mermaid') AND isDeleted = 0`)) { @@ -51,18 +68,18 @@ class NoteContentFulltextExp extends Expression { return resultNoteSet; } - findInText({noteId, isProtected, content, type, mime}, inputNoteSet, resultNoteSet) { + findInText({noteId, isProtected, content, type, mime}: SearchRow, inputNoteSet: NoteSet, resultNoteSet: NoteSet) { if (!inputNoteSet.hasNoteId(noteId) || !(noteId in becca.notes)) { return; } if (isProtected) { - if (!protectedSessionService.isProtectedSessionAvailable()) { + if (!protectedSessionService.isProtectedSessionAvailable() || !content) { return; } try { - content = protectedSessionService.decryptString(content); + content = protectedSessionService.decryptString(content) || undefined; } catch (e) { log.info(`Cannot decrypt content of note ${noteId}`); return; @@ -89,7 +106,7 @@ class NoteContentFulltextExp extends Expression { } } else { const nonMatchingToken = this.tokens.find(token => - !content.includes(token) && + !content?.includes(token) && ( // in case of default fulltext search, we should consider both title, attrs and content // so e.g. "hello world" should match when "hello" is in title and "world" in content @@ -106,7 +123,7 @@ class NoteContentFulltextExp extends Expression { return content; } - preprocessContent(content, type, mime) { + preprocessContent(content: string, type: string, mime: string) { content = utils.normalize(content.toString()); if (type === 'text' && mime === 'text/html') { @@ -125,4 +142,4 @@ class NoteContentFulltextExp extends Expression { } } -module.exports = NoteContentFulltextExp; +export = NoteContentFulltextExp; diff --git a/src/services/search/services/parse.js b/src/services/search/services/parse.js index 38a022a21..97e1632f1 100644 --- a/src/services/search/services/parse.js +++ b/src/services/search/services/parse.js @@ -12,7 +12,7 @@ const PropertyComparisonExp = require('../expressions/property_comparison.js'); const AttributeExistsExp = require('../expressions/attribute_exists'); const LabelComparisonExp = require('../expressions/label_comparison'); const NoteFlatTextExp = require('../expressions/note_flat_text.js'); -const NoteContentFulltextExp = require('../expressions/note_content_fulltext.js'); +const NoteContentFulltextExp = require('../expressions/note_content_fulltext'); const OrderByAndLimitExp = require('../expressions/order_by_and_limit.js'); const AncestorExp = require('../expressions/ancestor'); const buildComparator = require('./build_comparator.js'); diff --git a/src/services/sql.ts b/src/services/sql.ts index 1945efa92..3110e1b30 100644 --- a/src/services/sql.ts +++ b/src/services/sql.ts @@ -147,12 +147,12 @@ function getRawRows(query: string, params: Params = [] return (wrap(query, s => s.raw().all(params)) as T[] | null) || []; } -function iterateRows(query: string, params: Params = []) { +function iterateRows(query: string, params: Params = []): IterableIterator { if (LOG_ALL_QUERIES) { console.log(query); } - return stmt(query).iterate(params); + return stmt(query).iterate(params) as IterableIterator; } function getMap(query: string, params: Params = []) {