Merge pull request #42 from TriliumNext/feature/typescript_backend_6

Convert backend to TypeScript (67% -> 71%)
This commit is contained in:
Elian Doran 2024-04-15 21:12:55 +03:00 committed by GitHub
commit a072016fc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 282 additions and 208 deletions

13
package-lock.json generated
View File

@ -101,6 +101,7 @@
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7", "@types/sax": "^1.2.7",
"@types/stream-throttle": "^0.1.4", "@types/stream-throttle": "^0.1.4",
"@types/tmp": "^0.2.6",
"@types/turndown": "^5.0.4", "@types/turndown": "^5.0.4",
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
"@types/xml2js": "^0.4.14", "@types/xml2js": "^0.4.14",
@ -1628,6 +1629,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/tmp": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz",
"integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==",
"dev": true
},
"node_modules/@types/tough-cookie": { "node_modules/@types/tough-cookie": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
@ -14570,6 +14577,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/tmp": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz",
"integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==",
"dev": true
},
"@types/tough-cookie": { "@types/tough-cookie": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",

View File

@ -122,6 +122,7 @@
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7", "@types/sax": "^1.2.7",
"@types/stream-throttle": "^0.1.4", "@types/stream-throttle": "^0.1.4",
"@types/tmp": "^0.2.6",
"@types/turndown": "^5.0.4", "@types/turndown": "^5.0.4",
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
"@types/xml2js": "^0.4.14", "@types/xml2js": "^0.4.14",

View File

@ -129,7 +129,7 @@ export default class Becca {
return this.branches[branchId]; return this.branches[branchId];
} }
getBranchOrThrow(branchId: string): BBranch | null { getBranchOrThrow(branchId: string): BBranch {
const branch = this.getBranch(branchId); const branch = this.getBranch(branchId);
if (!branch) { if (!branch) {
throw new NotFoundError(`Branch '${branchId}' was not found in becca.`); throw new NotFoundError(`Branch '${branchId}' was not found in becca.`);
@ -239,7 +239,7 @@ export default class Becca {
return (this as any)[camelCaseEntityName][entityId]; return (this as any)[camelCaseEntityName][entityId];
} }
getRecentNotesFromQuery(query: string, params = []): BRecentNote[] { getRecentNotesFromQuery(query: string, params: string[] = []): BRecentNote[] {
const rows = sql.getRows(query, params); const rows = sql.getRows(query, params);
const BRecentNote = require('./entities/brecent_note'); // avoiding circular dependency problems const BRecentNote = require('./entities/brecent_note'); // avoiding circular dependency problems

View File

@ -134,7 +134,7 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
return this._getContent() as Buffer; return this._getContent() as Buffer;
} }
setContent(content: string | Buffer, opts: ContentOpts) { setContent(content: string | Buffer, opts?: ContentOpts) {
this._setContent(content, opts); this._setContent(content, opts);
} }

View File

@ -203,9 +203,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
return this.children && this.children.length > 0; return this.children && this.children.length > 0;
} }
getChildBranches(): (BBranch | null)[] { getChildBranches(): BBranch[] {
return this.children return this.children
.map(childNote => this.becca.getBranchFromChildAndParent(childNote.noteId, this.noteId)); .map(childNote => this.becca.getBranchFromChildAndParent(childNote.noteId, this.noteId)) as BBranch[];
} }
/* /*
@ -1434,7 +1434,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
searchNotesInSubtree(searchString: string) { searchNotesInSubtree(searchString: string) {
const searchService = require('../../services/search/services/search'); const searchService = require('../../services/search/services/search');
return searchService.searchNotes(searchString); return searchService.searchNotes(searchString) as BNote[];
} }
searchNoteInSubtree(searchString: string) { searchNoteInSubtree(searchString: string) {

View File

@ -1,11 +1,11 @@
"use strict"; "use strict";
const appInfo = require('../../services/app_info'); import appInfo = require('../../services/app_info');
function getAppInfo() { function getAppInfo() {
return appInfo; return appInfo;
} }
module.exports = { export = {
getAppInfo getAppInfo
}; };

View File

@ -1,27 +1,28 @@
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
const blobService = require('../../services/blob'); import blobService = require('../../services/blob');
const ValidationError = require('../../errors/validation_error'); import ValidationError = require('../../errors/validation_error');
const imageService = require("../../services/image"); import imageService = require("../../services/image");
import { Request } from 'express';
function getAttachmentBlob(req) { function getAttachmentBlob(req: Request) {
const preview = req.query.preview === 'true'; const preview = req.query.preview === 'true';
return blobService.getBlobPojo('attachments', req.params.attachmentId, { preview }); return blobService.getBlobPojo('attachments', req.params.attachmentId, { preview });
} }
function getAttachments(req) { function getAttachments(req: Request) {
const note = becca.getNoteOrThrow(req.params.noteId); const note = becca.getNoteOrThrow(req.params.noteId);
return note.getAttachments({includeContentLength: true}); return note.getAttachments({includeContentLength: true});
} }
function getAttachment(req) { function getAttachment(req: Request) {
const {attachmentId} = req.params; const {attachmentId} = req.params;
return becca.getAttachmentOrThrow(attachmentId, {includeContentLength: true}); return becca.getAttachmentOrThrow(attachmentId, {includeContentLength: true});
} }
function getAllAttachments(req) { function getAllAttachments(req: Request) {
const {attachmentId} = req.params; const {attachmentId} = req.params;
// one particular attachment is requested, but return all note's attachments // one particular attachment is requested, but return all note's attachments
@ -29,18 +30,18 @@ function getAllAttachments(req) {
return attachment.getNote()?.getAttachments({includeContentLength: true}) || []; return attachment.getNote()?.getAttachments({includeContentLength: true}) || [];
} }
function saveAttachment(req) { function saveAttachment(req: Request) {
const {noteId} = req.params; const {noteId} = req.params;
const {attachmentId, role, mime, title, content} = req.body; const {attachmentId, role, mime, title, content} = req.body;
const {matchBy} = req.query; const {matchBy} = req.query as any;
const note = becca.getNoteOrThrow(noteId); const note = becca.getNoteOrThrow(noteId);
note.saveAttachment({attachmentId, role, mime, title, content}, matchBy); note.saveAttachment({attachmentId, role, mime, title, content}, matchBy);
} }
function uploadAttachment(req) { function uploadAttachment(req: Request) {
const {noteId} = req.params; const {noteId} = req.params;
const {file} = req; const {file} = req as any;
const note = becca.getNoteOrThrow(noteId); const note = becca.getNoteOrThrow(noteId);
let url; let url;
@ -65,7 +66,7 @@ function uploadAttachment(req) {
}; };
} }
function renameAttachment(req) { function renameAttachment(req: Request) {
const {title} = req.body; const {title} = req.body;
const {attachmentId} = req.params; const {attachmentId} = req.params;
@ -79,7 +80,7 @@ function renameAttachment(req) {
attachment.save(); attachment.save();
} }
function deleteAttachment(req) { function deleteAttachment(req: Request) {
const {attachmentId} = req.params; const {attachmentId} = req.params;
const attachment = becca.getAttachment(attachmentId); const attachment = becca.getAttachment(attachmentId);
@ -89,14 +90,14 @@ function deleteAttachment(req) {
} }
} }
function convertAttachmentToNote(req) { function convertAttachmentToNote(req: Request) {
const {attachmentId} = req.params; const {attachmentId} = req.params;
const attachment = becca.getAttachmentOrThrow(attachmentId); const attachment = becca.getAttachmentOrThrow(attachmentId);
return attachment.convertToNote(); return attachment.convertToNote();
} }
module.exports = { export = {
getAttachmentBlob, getAttachmentBlob,
getAttachments, getAttachments,
getAttachment, getAttachment,

View File

@ -1,19 +1,20 @@
"use strict"; "use strict";
const sql = require('../../services/sql'); import sql = require('../../services/sql');
const log = require('../../services/log'); import log = require('../../services/log');
const attributeService = require('../../services/attributes'); import attributeService = require('../../services/attributes');
const BAttribute = require('../../becca/entities/battribute'); import BAttribute = require('../../becca/entities/battribute');
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
const ValidationError = require('../../errors/validation_error'); import ValidationError = require('../../errors/validation_error');
import { Request } from 'express';
function getEffectiveNoteAttributes(req) { function getEffectiveNoteAttributes(req: Request) {
const note = becca.getNote(req.params.noteId); const note = becca.getNote(req.params.noteId);
return note.getAttributes(); return note?.getAttributes();
} }
function updateNoteAttribute(req) { function updateNoteAttribute(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const body = req.body; const body = req.body;
@ -70,14 +71,17 @@ function updateNoteAttribute(req) {
}; };
} }
function setNoteAttribute(req) { function setNoteAttribute(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const body = req.body; const body = req.body;
const attributeId = sql.getValue(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = ? AND name = ?`, [noteId, body.type, body.name]); const attributeId = sql.getValue<string | null>(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = ? AND name = ?`, [noteId, body.type, body.name]);
if (attributeId) { if (attributeId) {
const attr = becca.getAttribute(attributeId); const attr = becca.getAttribute(attributeId);
if (!attr) {
throw new ValidationError(`Missing attribute with ID ${attributeId}.`);
}
attr.value = body.value; attr.value = body.value;
attr.save(); attr.save();
} else { } else {
@ -88,14 +92,14 @@ function setNoteAttribute(req) {
} }
} }
function addNoteAttribute(req) { function addNoteAttribute(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const body = req.body; const body = req.body;
new BAttribute({...body, noteId}).save(); new BAttribute({...body, noteId}).save();
} }
function deleteNoteAttribute(req) { function deleteNoteAttribute(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const attributeId = req.params.attributeId; const attributeId = req.params.attributeId;
@ -110,11 +114,14 @@ function deleteNoteAttribute(req) {
} }
} }
function updateNoteAttributes(req) { function updateNoteAttributes(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const incomingAttributes = req.body; const incomingAttributes = req.body;
const note = becca.getNote(noteId); const note = becca.getNote(noteId);
if (!note) {
throw new ValidationError(`Cannot find note with ID ${noteId}.`);
}
let existingAttrs = note.getOwnedAttributes().slice(); let existingAttrs = note.getOwnedAttributes().slice();
@ -179,25 +186,29 @@ function updateNoteAttributes(req) {
} }
} }
function getAttributeNames(req) { function getAttributeNames(req: Request) {
const type = req.query.type; const type = req.query.type;
const query = req.query.query; const query = req.query.query;
if (typeof type !== "string" || typeof query !== "string") {
throw new ValidationError("Invalid data type.");
}
return attributeService.getAttributeNames(type, query); return attributeService.getAttributeNames(type, query);
} }
function getValuesForAttribute(req) { function getValuesForAttribute(req: Request) {
const attributeName = req.params.attributeName; const attributeName = req.params.attributeName;
return sql.getColumn("SELECT DISTINCT value FROM attributes WHERE isDeleted = 0 AND name = ? AND type = 'label' AND value != '' ORDER BY value", [attributeName]); return sql.getColumn("SELECT DISTINCT value FROM attributes WHERE isDeleted = 0 AND name = ? AND type = 'label' AND value != '' ORDER BY value", [attributeName]);
} }
function createRelation(req) { function createRelation(req: Request) {
const sourceNoteId = req.params.noteId; const sourceNoteId = req.params.noteId;
const targetNoteId = req.params.targetNoteId; const targetNoteId = req.params.targetNoteId;
const name = req.params.name; const name = req.params.name;
const attributeId = sql.getValue(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]); const attributeId = sql.getValue<string>(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
let attribute = becca.getAttribute(attributeId); let attribute = becca.getAttribute(attributeId);
if (!attribute) { if (!attribute) {
@ -212,20 +223,22 @@ function createRelation(req) {
return attribute; return attribute;
} }
function deleteRelation(req) { function deleteRelation(req: Request) {
const sourceNoteId = req.params.noteId; const sourceNoteId = req.params.noteId;
const targetNoteId = req.params.targetNoteId; const targetNoteId = req.params.targetNoteId;
const name = req.params.name; const name = req.params.name;
const attributeId = sql.getValue(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]); const attributeId = sql.getValue<string | null>(`SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
if (attributeId) { if (attributeId) {
const attribute = becca.getAttribute(attributeId); const attribute = becca.getAttribute(attributeId);
if (attribute) {
attribute.markAsDeleted(); attribute.markAsDeleted();
} }
}
} }
module.exports = { export = {
updateNoteAttributes, updateNoteAttributes,
updateNoteAttribute, updateNoteAttribute,
setNoteAttribute, setNoteAttribute,

View File

@ -1,21 +1,26 @@
"use strict"; "use strict";
const beccaService = require('../../becca/becca_service'); import beccaService = require('../../becca/becca_service');
const searchService = require('../../services/search/services/search'); import searchService = require('../../services/search/services/search');
const log = require('../../services/log'); import log = require('../../services/log');
const utils = require('../../services/utils'); import utils = require('../../services/utils');
const cls = require('../../services/cls'); import cls = require('../../services/cls');
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
import { Request } from 'express';
import ValidationError = require('../../errors/validation_error');
function getAutocomplete(req) { function getAutocomplete(req: Request) {
const query = req.query.query.trim(); if (typeof req.query.query !== "string") {
throw new ValidationError("Invalid query data type.");
}
const query = (req.query.query || "").trim();
const activeNoteId = req.query.activeNoteId || 'none'; const activeNoteId = req.query.activeNoteId || 'none';
let results; let results;
const timestampStarted = Date.now(); const timestampStarted = Date.now();
if (query.length === 0) { if (query.length === 0 && typeof activeNoteId === "string") {
results = getRecentNotes(activeNoteId); results = getRecentNotes(activeNoteId);
} }
else { else {
@ -31,7 +36,7 @@ function getAutocomplete(req) {
return results; return results;
} }
function getRecentNotes(activeNoteId) { function getRecentNotes(activeNoteId: string) {
let extraCondition = ''; let extraCondition = '';
const params = [activeNoteId]; const params = [activeNoteId];
@ -70,6 +75,6 @@ function getRecentNotes(activeNoteId) {
}); });
} }
module.exports = { export = {
getAutocomplete getAutocomplete
}; };

View File

@ -1,8 +1,9 @@
"use strict"; "use strict";
const fs = require('fs'); import fs = require('fs');
const dateUtils = require('../../services/date_utils'); import dateUtils = require('../../services/date_utils');
const {LOG_DIR} = require('../../services/data_dir'); import dataDir = require('../../services/data_dir');
const { LOG_DIR } = dataDir;
function getBackendLog() { function getBackendLog() {
const file = `${LOG_DIR}/trilium-${dateUtils.localNowDate()}.log`; const file = `${LOG_DIR}/trilium-${dateUtils.localNowDate()}.log`;
@ -16,6 +17,6 @@ function getBackendLog() {
} }
} }
module.exports = { export = {
getBackendLog getBackendLog
}; };

View File

@ -1,23 +1,24 @@
"use strict"; "use strict";
const sql = require('../../services/sql'); import sql = require('../../services/sql');
const utils = require('../../services/utils'); import utils = require('../../services/utils');
const entityChangesService = require('../../services/entity_changes'); import entityChangesService = require('../../services/entity_changes');
const treeService = require('../../services/tree'); import treeService = require('../../services/tree');
const eraseService = require('../../services/erase'); import eraseService = require('../../services/erase');
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
const TaskContext = require('../../services/task_context'); import TaskContext = require('../../services/task_context');
const branchService = require('../../services/branches'); import branchService = require('../../services/branches');
const log = require('../../services/log'); import log = require('../../services/log');
const ValidationError = require('../../errors/validation_error'); import ValidationError = require('../../errors/validation_error');
const eventService = require("../../services/events"); import eventService = require("../../services/events");
import { Request } from 'express';
/** /**
* Code in this file deals with moving and cloning branches. The relationship between note and parent note is unique * Code in this file deals with moving and cloning branches. The relationship between note and parent note is unique
* for not deleted branches. There may be multiple deleted note-parent note relationships. * for not deleted branches. There may be multiple deleted note-parent note relationships.
*/ */
function moveBranchToParent(req) { function moveBranchToParent(req: Request) {
const {branchId, parentBranchId} = req.params; const {branchId, parentBranchId} = req.params;
const branchToMove = becca.getBranch(branchId); const branchToMove = becca.getBranch(branchId);
@ -30,7 +31,7 @@ function moveBranchToParent(req) {
return branchService.moveBranchToBranch(branchToMove, targetParentBranch, branchId); return branchService.moveBranchToBranch(branchToMove, targetParentBranch, branchId);
} }
function moveBranchBeforeNote(req) { function moveBranchBeforeNote(req: Request) {
const {branchId, beforeBranchId} = req.params; const {branchId, beforeBranchId} = req.params;
const branchToMove = becca.getBranchOrThrow(branchId); const branchToMove = becca.getBranchOrThrow(branchId);
@ -51,7 +52,7 @@ function moveBranchBeforeNote(req) {
[beforeBranch.parentNoteId, originalBeforeNotePosition]); [beforeBranch.parentNoteId, originalBeforeNotePosition]);
// also need to update becca positions // also need to update becca positions
const parentNote = becca.getNote(beforeBranch.parentNoteId); const parentNote = becca.getNoteOrThrow(beforeBranch.parentNoteId);
for (const childBranch of parentNote.getChildBranches()) { for (const childBranch of parentNote.getChildBranches()) {
if (childBranch.notePosition >= originalBeforeNotePosition) { if (childBranch.notePosition >= originalBeforeNotePosition) {
@ -80,11 +81,11 @@ function moveBranchBeforeNote(req) {
return { success: true }; return { success: true };
} }
function moveBranchAfterNote(req) { function moveBranchAfterNote(req: Request) {
const {branchId, afterBranchId} = req.params; const {branchId, afterBranchId} = req.params;
const branchToMove = becca.getBranch(branchId); const branchToMove = becca.getBranchOrThrow(branchId);
const afterNote = becca.getBranch(afterBranchId); const afterNote = becca.getBranchOrThrow(afterBranchId);
const validationResult = treeService.validateParentChild(afterNote.parentNoteId, branchToMove.noteId, branchId); const validationResult = treeService.validateParentChild(afterNote.parentNoteId, branchToMove.noteId, branchId);
@ -100,7 +101,7 @@ function moveBranchAfterNote(req) {
[afterNote.parentNoteId, originalAfterNotePosition]); [afterNote.parentNoteId, originalAfterNotePosition]);
// also need to update becca positions // also need to update becca positions
const parentNote = becca.getNote(afterNote.parentNoteId); const parentNote = becca.getNoteOrThrow(afterNote.parentNoteId);
for (const childBranch of parentNote.getChildBranches()) { for (const childBranch of parentNote.getChildBranches()) {
if (childBranch.notePosition > originalAfterNotePosition) { if (childBranch.notePosition > originalAfterNotePosition) {
@ -131,7 +132,7 @@ function moveBranchAfterNote(req) {
return { success: true }; return { success: true };
} }
function setExpanded(req) { function setExpanded(req: Request) {
const {branchId} = req.params; const {branchId} = req.params;
const expanded = parseInt(req.params.expanded); const expanded = parseInt(req.params.expanded);
@ -153,11 +154,11 @@ function setExpanded(req) {
} }
} }
function setExpandedForSubtree(req) { function setExpandedForSubtree(req: Request) {
const {branchId} = req.params; const {branchId} = req.params;
const expanded = parseInt(req.params.expanded); const expanded = parseInt(req.params.expanded);
let branchIds = sql.getColumn(` let branchIds = sql.getColumn<string>(`
WITH RECURSIVE WITH RECURSIVE
tree(branchId, noteId) AS ( tree(branchId, noteId) AS (
SELECT branchId, noteId FROM branches WHERE branchId = ? SELECT branchId, noteId FROM branches WHERE branchId = ?
@ -186,12 +187,12 @@ function setExpandedForSubtree(req) {
}; };
} }
function deleteBranch(req) { function deleteBranch(req: Request) {
const last = req.query.last === 'true'; const last = req.query.last === 'true';
const eraseNotes = req.query.eraseNotes === 'true'; const eraseNotes = req.query.eraseNotes === 'true';
const branch = becca.getBranchOrThrow(req.params.branchId); const branch = becca.getBranchOrThrow(req.params.branchId);
const taskContext = TaskContext.getInstance(req.query.taskId, 'deleteNotes'); const taskContext = TaskContext.getInstance(req.query.taskId as string, 'deleteNotes');
const deleteId = utils.randomString(10); const deleteId = utils.randomString(10);
let noteDeleted; let noteDeleted;
@ -214,16 +215,16 @@ function deleteBranch(req) {
}; };
} }
function setPrefix(req) { function setPrefix(req: Request) {
const branchId = req.params.branchId; const branchId = req.params.branchId;
const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix; const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix;
const branch = becca.getBranch(branchId); const branch = becca.getBranchOrThrow(branchId);
branch.prefix = prefix; branch.prefix = prefix;
branch.save(); branch.save();
} }
module.exports = { export = {
moveBranchToParent, moveBranchToParent,
moveBranchBeforeNote, moveBranchBeforeNote,
moveBranchAfterNote, moveBranchAfterNote,

View File

@ -1,17 +1,18 @@
const becca = require('../../becca/becca'); import { Request } from 'express';
const bulkActionService = require('../../services/bulk_actions'); import becca = require('../../becca/becca');
import bulkActionService = require('../../services/bulk_actions');
function execute(req) { function execute(req: Request) {
const {noteIds, includeDescendants} = req.body; const {noteIds, includeDescendants} = req.body;
const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants); const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants);
const bulkActionNote = becca.getNote('_bulkAction'); const bulkActionNote = becca.getNoteOrThrow('_bulkAction');
bulkActionService.executeActions(bulkActionNote, affectedNoteIds); bulkActionService.executeActions(bulkActionNote, affectedNoteIds);
} }
function getAffectedNoteCount(req) { function getAffectedNoteCount(req: Request) {
const {noteIds, includeDescendants} = req.body; const {noteIds, includeDescendants} = req.body;
const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants); const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants);
@ -21,8 +22,8 @@ function getAffectedNoteCount(req) {
}; };
} }
function getAffectedNoteIds(noteIds, includeDescendants) { function getAffectedNoteIds(noteIds: string[], includeDescendants: boolean) {
const affectedNoteIds = new Set(); const affectedNoteIds = new Set<string>();
for (const noteId of noteIds) { for (const noteId of noteIds) {
const note = becca.getNote(noteId); const note = becca.getNote(noteId);
@ -42,7 +43,7 @@ function getAffectedNoteIds(noteIds, includeDescendants) {
return affectedNoteIds; return affectedNoteIds;
} }
module.exports = { export = {
execute, execute,
getAffectedNoteCount getAffectedNoteCount
}; };

View File

@ -1,22 +1,32 @@
"use strict"; "use strict";
const attributeService = require('../../services/attributes'); import { Request } from "express";
const cloneService = require('../../services/cloning');
const noteService = require('../../services/notes'); import attributeService = require('../../services/attributes');
const dateNoteService = require('../../services/date_notes'); import cloneService = require('../../services/cloning');
const dateUtils = require('../../services/date_utils'); import noteService = require('../../services/notes');
const imageService = require('../../services/image'); import dateNoteService = require('../../services/date_notes');
const appInfo = require('../../services/app_info'); import dateUtils = require('../../services/date_utils');
const ws = require('../../services/ws'); import imageService = require('../../services/image');
const log = require('../../services/log'); import appInfo = require('../../services/app_info');
const utils = require('../../services/utils'); import ws = require('../../services/ws');
const path = require('path'); import log = require('../../services/log');
const htmlSanitizer = require('../../services/html_sanitizer'); import utils = require('../../services/utils');
const {formatAttrForSearch} = require('../../services/attribute_formatter'); import path = require('path');
const jsdom = require("jsdom"); import htmlSanitizer = require('../../services/html_sanitizer');
import attributeFormatter = require('../../services/attribute_formatter');
import jsdom = require("jsdom");
import BNote = require("../../becca/entities/bnote");
import ValidationError = require("../../errors/validation_error");
const { JSDOM } = jsdom; const { JSDOM } = jsdom;
function addClipping(req) { interface Image {
src: string;
dataUrl: string;
imageId: string;
}
function addClipping(req: Request) {
// if a note under the clipperInbox has the same 'pageUrl' attribute, // if a note under the clipperInbox has the same 'pageUrl' attribute,
// add the content to that note and clone it under today's inbox // add the content to that note and clone it under today's inbox
// otherwise just create a new note under today's inbox // otherwise just create a new note under today's inbox
@ -44,10 +54,14 @@ function addClipping(req) {
const rewrittenContent = processContent(images, clippingNote, content); const rewrittenContent = processContent(images, clippingNote, content);
const existingContent = clippingNote.getContent(); const existingContent = clippingNote.getContent();
if (typeof existingContent !== "string") {
throw new ValidationError("Invalid note content type.");
}
clippingNote.setContent(`${existingContent}${existingContent.trim() ? "<br>" : ""}${rewrittenContent}`); clippingNote.setContent(`${existingContent}${existingContent.trim() ? "<br>" : ""}${rewrittenContent}`);
if (clippingNote.parentNoteId !== clipperInbox.noteId) { // TODO: Is parentNoteId ever defined?
if ((clippingNote as any).parentNoteId !== clipperInbox.noteId) {
cloneService.cloneNoteToParentNote(clippingNote.noteId, clipperInbox.noteId); cloneService.cloneNoteToParentNote(clippingNote.noteId, clipperInbox.noteId);
} }
@ -56,13 +70,13 @@ function addClipping(req) {
}; };
} }
function findClippingNote(clipperInboxNote, pageUrl, clipType) { function findClippingNote(clipperInboxNote: BNote, pageUrl: string, clipType: string | null) {
if (!pageUrl) { if (!pageUrl) {
return null; return null;
} }
const notes = clipperInboxNote.searchNotesInSubtree( const notes = clipperInboxNote.searchNotesInSubtree(
formatAttrForSearch({ attributeFormatter.formatAttrForSearch({
type: 'label', type: 'label',
name: "pageUrl", name: "pageUrl",
value: pageUrl value: pageUrl
@ -84,7 +98,7 @@ function getClipperInboxNote() {
return clipperInbox; return clipperInbox;
} }
function createNote(req) { function createNote(req: Request) {
let {title, content, pageUrl, images, clipType, labels} = req.body; let {title, content, pageUrl, images, clipType, labels} = req.body;
if (!title || !title.trim()) { if (!title || !title.trim()) {
@ -123,6 +137,9 @@ function createNote(req) {
} }
const existingContent = note.getContent(); const existingContent = note.getContent();
if (typeof existingContent !== "string") {
throw new ValidationError("Invalid note content tpye.");
}
const rewrittenContent = processContent(images, note, content); const rewrittenContent = processContent(images, note, content);
const newContent = `${existingContent}${existingContent.trim() ? "<br/>" : ""}${rewrittenContent}`; const newContent = `${existingContent}${existingContent.trim() ? "<br/>" : ""}${rewrittenContent}`;
note.setContent(newContent); note.setContent(newContent);
@ -134,7 +151,7 @@ function createNote(req) {
}; };
} }
function processContent(images, note, content) { function processContent(images: Image[], note: BNote, content: string) {
let rewrittenContent = htmlSanitizer.sanitize(content); let rewrittenContent = htmlSanitizer.sanitize(content);
if (images) { if (images) {
@ -178,7 +195,7 @@ function processContent(images, note, content) {
return rewrittenContent; return rewrittenContent;
} }
function openNote(req) { function openNote(req: Request) {
if (utils.isElectron()) { if (utils.isElectron()) {
ws.sendMessageToAllClients({ ws.sendMessageToAllClients({
type: 'openNote', type: 'openNote',
@ -203,7 +220,7 @@ function handshake() {
} }
} }
function findNotesByUrl(req){ function findNotesByUrl(req: Request){
let pageUrl = req.params.noteUrl; let pageUrl = req.params.noteUrl;
const clipperInbox = getClipperInboxNote(); const clipperInbox = getClipperInboxNote();
let foundPage = findClippingNote(clipperInbox, pageUrl, null); let foundPage = findClippingNote(clipperInbox, pageUrl, null);

View File

@ -1,34 +1,35 @@
"use strict"; "use strict";
const cloningService = require('../../services/cloning'); import { Request } from 'express';
import cloningService = require('../../services/cloning');
function cloneNoteToBranch(req) { function cloneNoteToBranch(req: Request) {
const {noteId, parentBranchId} = req.params; const {noteId, parentBranchId} = req.params;
const {prefix} = req.body; const {prefix} = req.body;
return cloningService.cloneNoteToBranch(noteId, parentBranchId, prefix); return cloningService.cloneNoteToBranch(noteId, parentBranchId, prefix);
} }
function cloneNoteToParentNote(req) { function cloneNoteToParentNote(req: Request) {
const {noteId, parentNoteId} = req.params; const {noteId, parentNoteId} = req.params;
const {prefix} = req.body; const {prefix} = req.body;
return cloningService.cloneNoteToParentNote(noteId, parentNoteId, prefix); return cloningService.cloneNoteToParentNote(noteId, parentNoteId, prefix);
} }
function cloneNoteAfter(req) { function cloneNoteAfter(req: Request) {
const {noteId, afterBranchId} = req.params; const {noteId, afterBranchId} = req.params;
return cloningService.cloneNoteAfter(noteId, afterBranchId); return cloningService.cloneNoteAfter(noteId, afterBranchId);
} }
function toggleNoteInParent(req) { function toggleNoteInParent(req: Request) {
const {noteId, parentNoteId, present} = req.params; const {noteId, parentNoteId, present} = req.params;
return cloningService.toggleNoteInParent(present === 'true', noteId, parentNoteId); return cloningService.toggleNoteInParent(present === 'true', noteId, parentNoteId);
} }
module.exports = { export = {
cloneNoteToBranch, cloneNoteToBranch,
cloneNoteToParentNote, cloneNoteToParentNote,
cloneNoteAfter, cloneNoteAfter,

View File

@ -1,10 +1,12 @@
"use strict"; "use strict";
const sql = require('../../services/sql'); import sql = require('../../services/sql');
const log = require('../../services/log'); import log = require('../../services/log');
const backupService = require('../../services/backup'); import backupService = require('../../services/backup');
const anonymizationService = require('../../services/anonymization'); import anonymizationService = require('../../services/anonymization');
const consistencyChecksService = require('../../services/consistency_checks'); import consistencyChecksService = require('../../services/consistency_checks');
import { Request } from 'express';
import ValidationError = require('../../errors/validation_error');
function getExistingBackups() { function getExistingBackups() {
return backupService.getExistingBackups(); return backupService.getExistingBackups();
@ -30,7 +32,10 @@ function getExistingAnonymizedDatabases() {
return anonymizationService.getExistingAnonymizedDatabases(); return anonymizationService.getExistingAnonymizedDatabases();
} }
async function anonymize(req) { async function anonymize(req: Request) {
if (req.params.type !== "full" && req.params.type !== "light") {
throw new ValidationError("Invalid type provided.");
}
return await anonymizationService.createAnonymizedCopy(req.params.type); return await anonymizationService.createAnonymizedCopy(req.params.type);
} }
@ -44,7 +49,7 @@ function checkIntegrity() {
}; };
} }
module.exports = { export = {
getExistingBackups, getExistingBackups,
backupDatabase, backupDatabase,
vacuumDatabase, vacuumDatabase,

View File

@ -1,4 +1,5 @@
const etapiTokenService = require('../../services/etapi_tokens'); import { Request } from 'express';
import etapiTokenService = require('../../services/etapi_tokens');
function getTokens() { function getTokens() {
const tokens = etapiTokenService.getTokens(); const tokens = etapiTokenService.getTokens();
@ -8,19 +9,19 @@ function getTokens() {
return tokens; return tokens;
} }
function createToken(req) { function createToken(req: Request) {
return etapiTokenService.createToken(req.body.tokenName); return etapiTokenService.createToken(req.body.tokenName);
} }
function patchToken(req) { function patchToken(req: Request) {
etapiTokenService.renameToken(req.params.etapiTokenId, req.body.name); etapiTokenService.renameToken(req.params.etapiTokenId, req.body.name);
} }
function deleteToken(req) { function deleteToken(req: Request) {
etapiTokenService.deleteToken(req.params.etapiTokenId); etapiTokenService.deleteToken(req.params.etapiTokenId);
} }
module.exports = { export = {
getTokens, getTokens,
createToken, createToken,
patchToken, patchToken,

View File

@ -1,14 +1,16 @@
"use strict"; "use strict";
const zipExportService = require('../../services/export/zip'); import zipExportService = require('../../services/export/zip');
const singleExportService = require('../../services/export/single'); import singleExportService = require('../../services/export/single');
const opmlExportService = require('../../services/export/opml'); import opmlExportService = require('../../services/export/opml');
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
const TaskContext = require('../../services/task_context'); import TaskContext = require('../../services/task_context');
const log = require('../../services/log'); import log = require('../../services/log');
const NotFoundError = require('../../errors/not_found_error'); import NotFoundError = require('../../errors/not_found_error');
import { Request, Response } from 'express';
import ValidationError = require('../../errors/validation_error');
function exportBranch(req, res) { function exportBranch(req: Request, res: Response) {
const {branchId, type, format, version, taskId} = req.params; const {branchId, type, format, version, taskId} = req.params;
const branch = becca.getBranch(branchId); const branch = becca.getBranch(branchId);
@ -29,6 +31,9 @@ function exportBranch(req, res) {
zipExportService.exportToZip(taskContext, branch, format, res); zipExportService.exportToZip(taskContext, branch, format, res);
} }
else if (type === 'single') { else if (type === 'single') {
if (format !== "html" && format !== "markdown") {
throw new ValidationError("Invalid export type.");
}
singleExportService.exportSingleNote(taskContext, branch, format, res); singleExportService.exportSingleNote(taskContext, branch, format, res);
} }
else if (format === 'opml') { else if (format === 'opml') {
@ -38,7 +43,7 @@ function exportBranch(req, res) {
throw new NotFoundError(`Unrecognized export format '${format}'`); throw new NotFoundError(`Unrecognized export format '${format}'`);
} }
} }
catch (e) { catch (e: any) {
const message = `Export failed with following error: '${e.message}'. More details might be in the logs.`; const message = `Export failed with following error: '${e.message}'. More details might be in the logs.`;
taskContext.reportError(message); taskContext.reportError(message);

View File

@ -1,21 +1,24 @@
"use strict"; "use strict";
const protectedSessionService = require('../../services/protected_session'); import protectedSessionService = require('../../services/protected_session');
const utils = require('../../services/utils'); import utils = require('../../services/utils');
const log = require('../../services/log'); import log = require('../../services/log');
const noteService = require('../../services/notes'); import noteService = require('../../services/notes');
const tmp = require('tmp'); import tmp = require('tmp');
const fs = require('fs'); import fs = require('fs');
const { Readable } = require('stream'); import { Readable } from 'stream';
const chokidar = require('chokidar'); import chokidar = require('chokidar');
const ws = require('../../services/ws'); import ws = require('../../services/ws');
const becca = require('../../becca/becca'); import becca = require('../../becca/becca');
const ValidationError = require('../../errors/validation_error'); import ValidationError = require('../../errors/validation_error');
import { Request, Response } from 'express';
import BNote = require('../../becca/entities/bnote');
import BAttachment = require('../../becca/entities/battachment');
function updateFile(req) { function updateFile(req: Request) {
const note = becca.getNoteOrThrow(req.params.noteId); const note = becca.getNoteOrThrow(req.params.noteId);
const file = req.file; const file = (req as any).file;
note.saveRevision(); note.saveRevision();
note.mime = file.mimetype.toLowerCase(); note.mime = file.mimetype.toLowerCase();
@ -32,9 +35,9 @@ function updateFile(req) {
}; };
} }
function updateAttachment(req) { function updateAttachment(req: Request) {
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId); const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
const file = req.file; const file = (req as any).file;
attachment.getNote().saveRevision(); attachment.getNote().saveRevision();
@ -46,12 +49,7 @@ function updateAttachment(req) {
}; };
} }
/** function downloadData(noteOrAttachment: BNote | BAttachment, res: Response, contentDisposition: boolean) {
* @param {BNote|BAttachment} noteOrAttachment
* @param res
* @param {boolean} contentDisposition
*/
function downloadData(noteOrAttachment, res, contentDisposition) {
if (noteOrAttachment.isProtected && !protectedSessionService.isProtectedSessionAvailable()) { if (noteOrAttachment.isProtected && !protectedSessionService.isProtectedSessionAvailable()) {
return res.status(401).send("Protected session not available"); return res.status(401).send("Protected session not available");
} }
@ -68,7 +66,7 @@ function downloadData(noteOrAttachment, res, contentDisposition) {
res.send(noteOrAttachment.getContent()); res.send(noteOrAttachment.getContent());
} }
function downloadNoteInt(noteId, res, contentDisposition = true) { function downloadNoteInt(noteId: string, res: Response, contentDisposition = true) {
const note = becca.getNote(noteId); const note = becca.getNote(noteId);
if (!note) { if (!note) {
@ -80,7 +78,7 @@ function downloadNoteInt(noteId, res, contentDisposition = true) {
return downloadData(note, res, contentDisposition); return downloadData(note, res, contentDisposition);
} }
function downloadAttachmentInt(attachmentId, res, contentDisposition = true) { function downloadAttachmentInt(attachmentId: string, res: Response, contentDisposition = true) {
const attachment = becca.getAttachment(attachmentId); const attachment = becca.getAttachment(attachmentId);
if (!attachment) { if (!attachment) {
@ -92,34 +90,34 @@ function downloadAttachmentInt(attachmentId, res, contentDisposition = true) {
return downloadData(attachment, res, contentDisposition); return downloadData(attachment, res, contentDisposition);
} }
const downloadFile = (req, res) => downloadNoteInt(req.params.noteId, res, true); const downloadFile = (req: Request, res: Response) => downloadNoteInt(req.params.noteId, res, true);
const openFile = (req, res) => downloadNoteInt(req.params.noteId, res, false); const openFile = (req: Request, res: Response) => downloadNoteInt(req.params.noteId, res, false);
const downloadAttachment = (req, res) => downloadAttachmentInt(req.params.attachmentId, res, true); const downloadAttachment = (req: Request, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, true);
const openAttachment = (req, res) => downloadAttachmentInt(req.params.attachmentId, res, false); const openAttachment = (req: Request, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, false);
function fileContentProvider(req) { function fileContentProvider(req: Request) {
// Read the file name from route params. // Read the file name from route params.
const note = becca.getNoteOrThrow(req.params.noteId); const note = becca.getNoteOrThrow(req.params.noteId);
return streamContent(note.getContent(), note.getFileName(), note.mime); return streamContent(note.getContent(), note.getFileName(), note.mime);
} }
function attachmentContentProvider(req) { function attachmentContentProvider(req: Request) {
// Read the file name from route params. // Read the file name from route params.
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId); const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
return streamContent(attachment.getContent(), attachment.getFileName(), attachment.mime); return streamContent(attachment.getContent(), attachment.getFileName(), attachment.mime);
} }
function streamContent(content, fileName, mimeType) { function streamContent(content: string | Buffer, fileName: string, mimeType: string) {
if (typeof content === "string") { if (typeof content === "string") {
content = Buffer.from(content, 'utf8'); content = Buffer.from(content, 'utf8');
} }
const totalSize = content.byteLength; const totalSize = content.byteLength;
const getStream = range => { const getStream = (range: { start: number, end: number }) => {
if (!range) { if (!range) {
// Request if for complete content. // Request if for complete content.
return Readable.from(content); return Readable.from(content);
@ -138,7 +136,7 @@ function streamContent(content, fileName, mimeType) {
}; };
} }
function saveNoteToTmpDir(req) { function saveNoteToTmpDir(req: Request) {
const note = becca.getNoteOrThrow(req.params.noteId); const note = becca.getNoteOrThrow(req.params.noteId);
const fileName = note.getFileName(); const fileName = note.getFileName();
const content = note.getContent(); const content = note.getContent();
@ -146,18 +144,26 @@ function saveNoteToTmpDir(req) {
return saveToTmpDir(fileName, content, 'notes', note.noteId); return saveToTmpDir(fileName, content, 'notes', note.noteId);
} }
function saveAttachmentToTmpDir(req) { function saveAttachmentToTmpDir(req: Request) {
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId); const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
const fileName = attachment.getFileName(); const fileName = attachment.getFileName();
const content = attachment.getContent(); const content = attachment.getContent();
if (!attachment.attachmentId) {
throw new ValidationError("Missing attachment ID.");
}
return saveToTmpDir(fileName, content, 'attachments', attachment.attachmentId); return saveToTmpDir(fileName, content, 'attachments', attachment.attachmentId);
} }
function saveToTmpDir(fileName, content, entityType, entityId) { function saveToTmpDir(fileName: string, content: string | Buffer, entityType: string, entityId: string) {
const tmpObj = tmp.fileSync({ postfix: fileName }); const tmpObj = tmp.fileSync({ postfix: fileName });
if (typeof content === "string") {
fs.writeSync(tmpObj.fd, content); fs.writeSync(tmpObj.fd, content);
} else {
fs.writeSync(tmpObj.fd, content);
}
fs.closeSync(tmpObj.fd); fs.closeSync(tmpObj.fd);
log.info(`Saved temporary file ${tmpObj.name}`); log.info(`Saved temporary file ${tmpObj.name}`);
@ -168,7 +174,7 @@ function saveToTmpDir(fileName, content, entityType, entityId) {
type: 'openedFileUpdated', type: 'openedFileUpdated',
entityType: entityType, entityType: entityType,
entityId: entityId, entityId: entityId,
lastModifiedMs: stats.atimeMs, lastModifiedMs: stats?.atimeMs,
filePath: tmpObj.name filePath: tmpObj.name
}); });
}); });
@ -179,7 +185,7 @@ function saveToTmpDir(fileName, content, entityType, entityId) {
}; };
} }
function uploadModifiedFileToNote(req) { function uploadModifiedFileToNote(req: Request) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const {filePath} = req.body; const {filePath} = req.body;
@ -198,7 +204,7 @@ function uploadModifiedFileToNote(req) {
note.setContent(fileContent); note.setContent(fileContent);
} }
function uploadModifiedFileToAttachment(req) { function uploadModifiedFileToAttachment(req: Request) {
const {attachmentId} = req.params; const {attachmentId} = req.params;
const {filePath} = req.body; const {filePath} = req.body;
@ -217,7 +223,7 @@ function uploadModifiedFileToAttachment(req) {
attachment.setContent(fileContent); attachment.setContent(fileContent);
} }
module.exports = { export = {
updateFile, updateFile,
updateAttachment, updateAttachment,
openFile, openFile,

View File

@ -1,6 +1,7 @@
const optionService = require('../../services/options'); import { Request, Response } from 'express';
import optionService = require('../../services/options');
function getFontCss(req, res) { function getFontCss(req: Request, res: Response) {
res.setHeader('Content-Type', 'text/css'); res.setHeader('Content-Type', 'text/css');
if (!optionService.getOptionBool('overrideThemeFonts')) { if (!optionService.getOptionBool('overrideThemeFonts')) {
@ -34,6 +35,6 @@ function getFontCss(req, res) {
res.send(style); res.send(style);
} }
module.exports = { export = {
getFontCss getFontCss
}; };

View File

@ -1,5 +1,5 @@
const log = require('../services/log'); const log = require('../services/log');
const fileService = require('./api/files.js'); const fileService = require('./api/files');
const scriptService = require('../services/script'); const scriptService = require('../services/script');
const cls = require('../services/cls'); const cls = require('../services/cls');
const sql = require('../services/sql'); const sql = require('../services/sql');

View File

@ -24,9 +24,9 @@ const indexRoute = require('./index.js');
// API routes // API routes
const treeApiRoute = require('./api/tree.js'); const treeApiRoute = require('./api/tree.js');
const notesApiRoute = require('./api/notes.js'); const notesApiRoute = require('./api/notes.js');
const branchesApiRoute = require('./api/branches.js'); const branchesApiRoute = require('./api/branches');
const attachmentsApiRoute = require('./api/attachments.js'); const attachmentsApiRoute = require('./api/attachments');
const autocompleteApiRoute = require('./api/autocomplete.js'); const autocompleteApiRoute = require('./api/autocomplete');
const cloningApiRoute = require('./api/cloning'); const cloningApiRoute = require('./api/cloning');
const revisionsApiRoute = require('./api/revisions'); const revisionsApiRoute = require('./api/revisions');
const recentChangesApiRoute = require('./api/recent_changes.js'); const recentChangesApiRoute = require('./api/recent_changes.js');
@ -36,26 +36,26 @@ const syncApiRoute = require('./api/sync');
const loginApiRoute = require('./api/login.js'); const loginApiRoute = require('./api/login.js');
const recentNotesRoute = require('./api/recent_notes.js'); const recentNotesRoute = require('./api/recent_notes.js');
const appInfoRoute = require('./api/app_info'); const appInfoRoute = require('./api/app_info');
const exportRoute = require('./api/export.js'); const exportRoute = require('./api/export');
const importRoute = require('./api/import.js'); const importRoute = require('./api/import.js');
const setupApiRoute = require('./api/setup.js'); const setupApiRoute = require('./api/setup.js');
const sqlRoute = require('./api/sql'); const sqlRoute = require('./api/sql');
const databaseRoute = require('./api/database.js'); const databaseRoute = require('./api/database');
const imageRoute = require('./api/image'); const imageRoute = require('./api/image');
const attributesRoute = require('./api/attributes'); const attributesRoute = require('./api/attributes');
const scriptRoute = require('./api/script.js'); const scriptRoute = require('./api/script.js');
const senderRoute = require('./api/sender.js'); const senderRoute = require('./api/sender.js');
const filesRoute = require('./api/files.js'); const filesRoute = require('./api/files');
const searchRoute = require('./api/search'); const searchRoute = require('./api/search');
const bulkActionRoute = require('./api/bulk_action.js'); const bulkActionRoute = require('./api/bulk_action');
const specialNotesRoute = require('./api/special_notes'); const specialNotesRoute = require('./api/special_notes');
const noteMapRoute = require('./api/note_map.js'); const noteMapRoute = require('./api/note_map.js');
const clipperRoute = require('./api/clipper.js'); const clipperRoute = require('./api/clipper');
const similarNotesRoute = require('./api/similar_notes.js'); const similarNotesRoute = require('./api/similar_notes.js');
const keysRoute = require('./api/keys.js'); const keysRoute = require('./api/keys.js');
const backendLogRoute = require('./api/backend_log.js'); const backendLogRoute = require('./api/backend_log');
const statsRoute = require('./api/stats.js'); const statsRoute = require('./api/stats.js');
const fontsRoute = require('./api/fonts.js'); const fontsRoute = require('./api/fonts');
const etapiTokensApiRoutes = require('./api/etapi_tokens'); const etapiTokensApiRoutes = require('./api/etapi_tokens');
const relationMapApiRoute = require('./api/relation-map'); const relationMapApiRoute = require('./api/relation-map');
const otherRoute = require('./api/other.js'); const otherRoute = require('./api/other.js');

View File

@ -80,7 +80,6 @@ interface Api {
/** /**
* Axios library for HTTP requests. See {@link https://axios-http.com} for documentation * Axios library for HTTP requests. See {@link https://axios-http.com} for documentation
* @type {axios}
* @deprecated use native (browser compatible) fetch() instead * @deprecated use native (browser compatible) fetch() instead
*/ */
axios: typeof axios; axios: typeof axios;
@ -122,9 +121,6 @@ interface Api {
/** /**
* This is a powerful search method - you can search by attributes and their values, e.g.: * This is a powerful search method - you can search by attributes and their values, e.g.:
* "#dateModified =* MONTH AND #log". See {@link https://github.com/zadam/trilium/wiki/Search} for full documentation for all options * "#dateModified =* MONTH AND #log". See {@link https://github.com/zadam/trilium/wiki/Search} for full documentation for all options
*
* @param {string} query
* @param {Object} [searchParams]
*/ */
searchForNote(query: string, searchParams: SearchParams): BNote | null; searchForNote(query: string, searchParams: SearchParams): BNote | null;

View File

@ -4,7 +4,8 @@ import protectedSessionService = require('./protected_session');
import utils = require('./utils'); import utils = require('./utils');
import type { Blob } from "./blob-interface"; import type { Blob } from "./blob-interface";
function getBlobPojo(entityName: string, entityId: string) { function getBlobPojo(entityName: string, entityId: string, opts?: { preview: boolean }) {
// TODO: Unused opts.
const entity = becca.getEntity(entityName, entityId); const entity = becca.getEntity(entityName, entityId);
if (!entity) { if (!entity) {
throw new NotFoundError(`Entity ${entityName} '${entityId}' was not found.`); throw new NotFoundError(`Entity ${entityName} '${entityId}' was not found.`);

View File

@ -27,7 +27,8 @@ function moveBranchToNote(branchToMove: BBranch, targetParentNoteId: string) {
}; };
} }
function moveBranchToBranch(branchToMove: BBranch, targetParentBranch: BBranch) { function moveBranchToBranch(branchToMove: BBranch, targetParentBranch: BBranch, branchId: string) {
// TODO: Unused branch ID argument.
const res = moveBranchToNote(branchToMove, targetParentBranch.noteId); const res = moveBranchToNote(branchToMove, targetParentBranch.noteId);
if (!("success" in res) || !res.success) { if (!("success" in res) || !res.success) {

View File

@ -150,7 +150,7 @@ function getActions(note: BNote) {
.filter(a => !!a); .filter(a => !!a);
} }
function executeActions(note: BNote, searchResultNoteIds: string[]) { function executeActions(note: BNote, searchResultNoteIds: string[] | Set<string>) {
const actions = getActions(note); const actions = getActions(note);
for (const resultNoteId of searchResultNoteIds) { for (const resultNoteId of searchResultNoteIds) {

View File

@ -58,7 +58,7 @@ function cloneNoteToBranch(noteId: string, parentBranchId: string, prefix: strin
return ret; return ret;
} }
function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefix: string) { function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefix?: string) {
if (!(noteId in becca.notes)) { if (!(noteId in becca.notes)) {
return { branch: null, success: false, message: `Note '${noteId}' is deleted.` }; return { branch: null, success: false, message: `Note '${noteId}' is deleted.` };
} else if (!(parentNoteId in becca.notes)) { } else if (!(parentNoteId in becca.notes)) {
@ -109,7 +109,7 @@ function ensureNoteIsAbsentFromParent(noteId: string, parentNoteId: string) {
} }
} }
function toggleNoteInParent(present: boolean, noteId: string, parentNoteId: string, prefix: string) { function toggleNoteInParent(present: boolean, noteId: string, parentNoteId: string, prefix?: string) {
if (present) { if (present) {
return ensureNoteIsPresentInParent(noteId, parentNoteId, prefix); return ensureNoteIsPresentInParent(noteId, parentNoteId, prefix);
} }

View File

@ -913,7 +913,7 @@ sqlInit.dbReady.then(() => {
setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000); setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000);
}); });
module.exports = { export = {
runOnDemandChecks, runOnDemandChecks,
runEntityChangesChecks runEntityChangesChecks
}; };

View File

@ -49,8 +49,12 @@ interface Message {
messages?: string[]; messages?: string[];
startNoteId?: string; startNoteId?: string;
currentNoteId?: string; currentNoteId?: string;
entityType?: string;
entityId?: string;
originEntityName?: "notes"; originEntityName?: "notes";
originEntityId?: string | null; originEntityId?: string | null;
lastModifiedMs?: number;
filePath?: string;
} }
type SessionParser = (req: IncomingMessage, params: {}, cb: () => void) => void; type SessionParser = (req: IncomingMessage, params: {}, cb: () => void) => void;