mirror of
https://github.com/zadam/trilium.git
synced 2025-11-17 18:50:41 +01:00
syncification
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
|
||||
const appInfo = require('../../services/app_info');
|
||||
|
||||
async function getAppInfo() {
|
||||
function getAppInfo() {
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAppInfo
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,19 +6,19 @@ const attributeService = require('../../services/attributes');
|
||||
const repository = require('../../services/repository');
|
||||
const Attribute = require('../../entities/attribute');
|
||||
|
||||
async function getEffectiveNoteAttributes(req) {
|
||||
const note = await repository.getNote(req.params.noteId);
|
||||
function getEffectiveNoteAttributes(req) {
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
return await note.getAttributes();
|
||||
return note.getAttributes();
|
||||
}
|
||||
|
||||
async function updateNoteAttribute(req) {
|
||||
function updateNoteAttribute(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const body = req.body;
|
||||
|
||||
let attribute;
|
||||
if (body.attributeId) {
|
||||
attribute = await repository.getAttribute(body.attributeId);
|
||||
attribute = repository.getAttribute(body.attributeId);
|
||||
|
||||
if (attribute.noteId !== noteId) {
|
||||
return [400, `Attribute ${body.attributeId} is not owned by ${noteId}`];
|
||||
@@ -30,11 +30,11 @@ async function updateNoteAttribute(req) {
|
||||
|
||||
if (body.type !== 'relation' || !!body.value.trim()) {
|
||||
const newAttribute = attribute.createClone(body.type, body.name, body.value);
|
||||
await newAttribute.save();
|
||||
newAttribute.save();
|
||||
}
|
||||
|
||||
attribute.isDeleted = true;
|
||||
await attribute.save();
|
||||
attribute.save();
|
||||
|
||||
return {
|
||||
attributeId: attribute.attributeId
|
||||
@@ -60,18 +60,18 @@ async function updateNoteAttribute(req) {
|
||||
attribute.isDeleted = true;
|
||||
}
|
||||
|
||||
await attribute.save();
|
||||
attribute.save();
|
||||
|
||||
return {
|
||||
attributeId: attribute.attributeId
|
||||
};
|
||||
}
|
||||
|
||||
async function deleteNoteAttribute(req) {
|
||||
function deleteNoteAttribute(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const attributeId = req.params.attributeId;
|
||||
|
||||
const attribute = await repository.getAttribute(attributeId);
|
||||
const attribute = repository.getAttribute(attributeId);
|
||||
|
||||
if (attribute) {
|
||||
if (attribute.noteId !== noteId) {
|
||||
@@ -79,17 +79,17 @@ async function deleteNoteAttribute(req) {
|
||||
}
|
||||
|
||||
attribute.isDeleted = true;
|
||||
await attribute.save();
|
||||
attribute.save();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateNoteAttributes2(req) {
|
||||
function updateNoteAttributes2(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const incomingAttributes = req.body;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
let existingAttrs = await note.getAttributes();
|
||||
let existingAttrs = note.getAttributes();
|
||||
|
||||
let position = 0;
|
||||
|
||||
@@ -107,14 +107,14 @@ async function updateNoteAttributes2(req) {
|
||||
|
||||
if (perfectMatchAttr.position !== position) {
|
||||
perfectMatchAttr.position = position;
|
||||
await perfectMatchAttr.save();
|
||||
perfectMatchAttr.save();
|
||||
}
|
||||
|
||||
continue; // nothing to update
|
||||
}
|
||||
|
||||
if (incAttr.type === 'relation') {
|
||||
const targetNote = await repository.getNote(incAttr.value);
|
||||
const targetNote = repository.getNote(incAttr.value);
|
||||
|
||||
if (!targetNote || targetNote.isDeleted) {
|
||||
log.error(`Target note of relation ${JSON.stringify(incAttr)} does not exist or is deleted`);
|
||||
@@ -130,7 +130,7 @@ async function updateNoteAttributes2(req) {
|
||||
if (matchedAttr) {
|
||||
matchedAttr.value = incAttr.value;
|
||||
matchedAttr.position = position;
|
||||
await matchedAttr.save();
|
||||
matchedAttr.save();
|
||||
|
||||
existingAttrs = existingAttrs.filter(attr => attr.attributeId !== matchedAttr.attributeId);
|
||||
continue;
|
||||
@@ -139,17 +139,17 @@ async function updateNoteAttributes2(req) {
|
||||
// no existing attribute has been matched so we need to create a new one
|
||||
// type, name and isInheritable are immutable so even if there is an attribute with matching type & name, we need to create a new one and delete the former one
|
||||
|
||||
await note.addAttribute(incAttr.type, incAttr.name, incAttr.value, incAttr.isInheritable, position);
|
||||
note.addAttribute(incAttr.type, incAttr.name, incAttr.value, incAttr.isInheritable, position);
|
||||
}
|
||||
|
||||
// all the remaining existing attributes are not defined anymore and should be deleted
|
||||
for (const toDeleteAttr of existingAttrs) {
|
||||
toDeleteAttr.isDeleted = true;
|
||||
await toDeleteAttr.save();
|
||||
toDeleteAttr.save();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateNoteAttributes(req) {
|
||||
function updateNoteAttributes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const attributes = req.body;
|
||||
|
||||
@@ -157,7 +157,7 @@ async function updateNoteAttributes(req) {
|
||||
let attributeEntity;
|
||||
|
||||
if (attribute.attributeId) {
|
||||
attributeEntity = await repository.getAttribute(attribute.attributeId);
|
||||
attributeEntity = repository.getAttribute(attribute.attributeId);
|
||||
|
||||
if (attributeEntity.noteId !== noteId) {
|
||||
return [400, `Attribute ${attributeEntity.noteId} is not owned by ${noteId}`];
|
||||
@@ -170,11 +170,11 @@ async function updateNoteAttributes(req) {
|
||||
|
||||
if (attribute.type !== 'relation' || !!attribute.value.trim()) {
|
||||
const newAttribute = attributeEntity.createClone(attribute.type, attribute.name, attribute.value, attribute.isInheritable);
|
||||
await newAttribute.save();
|
||||
newAttribute.save();
|
||||
}
|
||||
|
||||
attributeEntity.isDeleted = true;
|
||||
await attributeEntity.save();
|
||||
attributeEntity.save();
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -203,34 +203,34 @@ async function updateNoteAttributes(req) {
|
||||
attributeEntity.value = attribute.value;
|
||||
}
|
||||
|
||||
await attributeEntity.save();
|
||||
attributeEntity.save();
|
||||
}
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
note.invalidateAttributeCache();
|
||||
|
||||
return await note.getAttributes();
|
||||
return note.getAttributes();
|
||||
}
|
||||
|
||||
async function getAttributeNames(req) {
|
||||
function getAttributeNames(req) {
|
||||
const type = req.query.type;
|
||||
const query = req.query.query;
|
||||
|
||||
return attributeService.getAttributeNames(type, query);
|
||||
}
|
||||
|
||||
async function getValuesForAttribute(req) {
|
||||
function getValuesForAttribute(req) {
|
||||
const attributeName = req.params.attributeName;
|
||||
|
||||
return await 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]);
|
||||
}
|
||||
|
||||
async function createRelation(req) {
|
||||
function createRelation(req) {
|
||||
const sourceNoteId = req.params.noteId;
|
||||
const targetNoteId = req.params.targetNoteId;
|
||||
const name = req.params.name;
|
||||
|
||||
let attribute = await repository.getEntity(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
|
||||
let attribute = repository.getEntity(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
|
||||
|
||||
if (!attribute) {
|
||||
attribute = new Attribute();
|
||||
@@ -239,22 +239,22 @@ async function createRelation(req) {
|
||||
attribute.type = 'relation';
|
||||
attribute.value = targetNoteId;
|
||||
|
||||
await attribute.save();
|
||||
attribute.save();
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
async function deleteRelation(req) {
|
||||
function deleteRelation(req) {
|
||||
const sourceNoteId = req.params.noteId;
|
||||
const targetNoteId = req.params.targetNoteId;
|
||||
const name = req.params.name;
|
||||
|
||||
let attribute = await repository.getEntity(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
|
||||
let attribute = repository.getEntity(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ?`, [sourceNoteId, name, targetNoteId]);
|
||||
|
||||
if (attribute) {
|
||||
attribute.isDeleted = true;
|
||||
await attribute.save();
|
||||
attribute.save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ const log = require('../../services/log');
|
||||
const utils = require('../../services/utils');
|
||||
const optionService = require('../../services/options');
|
||||
|
||||
async function getAutocomplete(req) {
|
||||
function getAutocomplete(req) {
|
||||
const query = req.query.query.trim();
|
||||
const activeNoteId = req.query.activeNoteId || 'none';
|
||||
|
||||
@@ -16,10 +16,10 @@ async function getAutocomplete(req) {
|
||||
const timestampStarted = Date.now();
|
||||
|
||||
if (query.length === 0) {
|
||||
results = await getRecentNotes(activeNoteId);
|
||||
results = getRecentNotes(activeNoteId);
|
||||
}
|
||||
else {
|
||||
results = await searchService.searchNotesForAutocomplete(query);
|
||||
results = searchService.searchNotesForAutocomplete(query);
|
||||
}
|
||||
|
||||
const msTaken = Date.now() - timestampStarted;
|
||||
@@ -31,15 +31,15 @@ async function getAutocomplete(req) {
|
||||
return results;
|
||||
}
|
||||
|
||||
async function getRecentNotes(activeNoteId) {
|
||||
function getRecentNotes(activeNoteId) {
|
||||
let extraCondition = '';
|
||||
|
||||
const hoistedNoteId = await optionService.getOption('hoistedNoteId');
|
||||
const hoistedNoteId = optionService.getOption('hoistedNoteId');
|
||||
if (hoistedNoteId !== 'root') {
|
||||
extraCondition = `AND recent_notes.notePath LIKE '%${utils.sanitizeSql(hoistedNoteId)}%'`;
|
||||
}
|
||||
|
||||
const recentNotes = await repository.getEntities(`
|
||||
const recentNotes = repository.getEntities(`
|
||||
SELECT
|
||||
recent_notes.*
|
||||
FROM
|
||||
|
||||
@@ -4,7 +4,7 @@ const fs = require('fs');
|
||||
const dateUtils = require('../../services/date_utils');
|
||||
const {LOG_DIR} = require('../../services/data_dir.js');
|
||||
|
||||
async function getBackendLog() {
|
||||
function getBackendLog() {
|
||||
const file = `${LOG_DIR}/trilium-${dateUtils.localNowDate()}.log`;
|
||||
|
||||
return fs.readFileSync(file, 'utf8');
|
||||
@@ -12,4 +12,4 @@ async function getBackendLog() {
|
||||
|
||||
module.exports = {
|
||||
getBackendLog
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,11 +13,11 @@ const TaskContext = require('../../services/task_context');
|
||||
* for not deleted branches. There may be multiple deleted note-parent note relationships.
|
||||
*/
|
||||
|
||||
async function moveBranchToParent(req) {
|
||||
function moveBranchToParent(req) {
|
||||
const {branchId, parentBranchId} = req.params;
|
||||
|
||||
const parentBranch = await repository.getBranch(parentBranchId);
|
||||
const branchToMove = await repository.getBranch(branchId);
|
||||
const parentBranch = repository.getBranch(parentBranchId);
|
||||
const branchToMove = repository.getBranch(branchId);
|
||||
|
||||
if (!parentBranch || !branchToMove) {
|
||||
return [400, `One or both branches ${branchId}, ${parentBranchId} have not been found`];
|
||||
@@ -27,35 +27,35 @@ async function moveBranchToParent(req) {
|
||||
return { success: true }; // no-op
|
||||
}
|
||||
|
||||
const validationResult = await treeService.validateParentChild(parentBranch.noteId, branchToMove.noteId, branchId);
|
||||
const validationResult = treeService.validateParentChild(parentBranch.noteId, branchToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [200, validationResult];
|
||||
}
|
||||
|
||||
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentBranch.noteId]);
|
||||
const maxNotePos = sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentBranch.noteId]);
|
||||
const newNotePos = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||
|
||||
// expanding so that the new placement of the branch is immediately visible
|
||||
parentBranch.isExpanded = true;
|
||||
await parentBranch.save();
|
||||
parentBranch.save();
|
||||
|
||||
const newBranch = branchToMove.createClone(parentBranch.noteId, newNotePos);
|
||||
await newBranch.save();
|
||||
newBranch.save();
|
||||
|
||||
branchToMove.isDeleted = true;
|
||||
await branchToMove.save();
|
||||
branchToMove.save();
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async function moveBranchBeforeNote(req) {
|
||||
function moveBranchBeforeNote(req) {
|
||||
const {branchId, beforeBranchId} = req.params;
|
||||
|
||||
const branchToMove = await repository.getBranch(branchId);
|
||||
const beforeNote = await repository.getBranch(beforeBranchId);
|
||||
const branchToMove = repository.getBranch(branchId);
|
||||
const beforeNote = repository.getBranch(beforeBranchId);
|
||||
|
||||
const validationResult = await treeService.validateParentChild(beforeNote.parentNoteId, branchToMove.noteId, branchId);
|
||||
const validationResult = treeService.validateParentChild(beforeNote.parentNoteId, branchToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [200, validationResult];
|
||||
@@ -63,33 +63,33 @@ async function moveBranchBeforeNote(req) {
|
||||
|
||||
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
||||
// also we would have to sync all those modified branches otherwise hash checks would fail
|
||||
await sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
|
||||
sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
|
||||
[beforeNote.parentNoteId, beforeNote.notePosition]);
|
||||
|
||||
await syncTableService.addNoteReorderingSync(beforeNote.parentNoteId);
|
||||
syncTableService.addNoteReorderingSync(beforeNote.parentNoteId);
|
||||
|
||||
if (branchToMove.parentNoteId === beforeNote.parentNoteId) {
|
||||
branchToMove.notePosition = beforeNote.notePosition;
|
||||
await branchToMove.save();
|
||||
branchToMove.save();
|
||||
}
|
||||
else {
|
||||
const newBranch = branchToMove.createClone(beforeNote.parentNoteId, beforeNote.notePosition);
|
||||
await newBranch.save();
|
||||
newBranch.save();
|
||||
|
||||
branchToMove.isDeleted = true;
|
||||
await branchToMove.save();
|
||||
branchToMove.save();
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async function moveBranchAfterNote(req) {
|
||||
function moveBranchAfterNote(req) {
|
||||
const {branchId, afterBranchId} = req.params;
|
||||
|
||||
const branchToMove = await repository.getBranch(branchId);
|
||||
const afterNote = await repository.getBranch(afterBranchId);
|
||||
const branchToMove = repository.getBranch(branchId);
|
||||
const afterNote = repository.getBranch(afterBranchId);
|
||||
|
||||
const validationResult = await treeService.validateParentChild(afterNote.parentNoteId, branchToMove.noteId, branchId);
|
||||
const validationResult = treeService.validateParentChild(afterNote.parentNoteId, branchToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [200, validationResult];
|
||||
@@ -97,42 +97,42 @@ async function moveBranchAfterNote(req) {
|
||||
|
||||
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
||||
// also we would have to sync all those modified branches otherwise hash checks would fail
|
||||
await sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
||||
sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
||||
[afterNote.parentNoteId, afterNote.notePosition]);
|
||||
|
||||
await syncTableService.addNoteReorderingSync(afterNote.parentNoteId);
|
||||
syncTableService.addNoteReorderingSync(afterNote.parentNoteId);
|
||||
|
||||
const movedNotePosition = afterNote.notePosition + 10;
|
||||
|
||||
if (branchToMove.parentNoteId === afterNote.parentNoteId) {
|
||||
branchToMove.notePosition = movedNotePosition;
|
||||
await branchToMove.save();
|
||||
branchToMove.save();
|
||||
}
|
||||
else {
|
||||
const newBranch = branchToMove.createClone(afterNote.parentNoteId, movedNotePosition);
|
||||
await newBranch.save();
|
||||
newBranch.save();
|
||||
|
||||
branchToMove.isDeleted = true;
|
||||
await branchToMove.save();
|
||||
branchToMove.save();
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async function setExpanded(req) {
|
||||
function setExpanded(req) {
|
||||
const {branchId, expanded} = req.params;
|
||||
|
||||
if (branchId !== 'root') {
|
||||
await sql.execute("UPDATE branches SET isExpanded = ? WHERE branchId = ?", [expanded, branchId]);
|
||||
sql.execute("UPDATE branches SET isExpanded = ? WHERE branchId = ?", [expanded, branchId]);
|
||||
// we don't sync expanded label
|
||||
// also this does not trigger updates to the frontend, this would trigger too many reloads
|
||||
}
|
||||
}
|
||||
|
||||
async function setExpandedForSubtree(req) {
|
||||
function setExpandedForSubtree(req) {
|
||||
const {branchId, expanded} = req.params;
|
||||
|
||||
let branchIds = await sql.getColumn(`
|
||||
let branchIds = sql.getColumn(`
|
||||
WITH RECURSIVE
|
||||
tree(branchId, noteId) AS (
|
||||
SELECT branchId, noteId FROM branches WHERE branchId = ?
|
||||
@@ -146,20 +146,20 @@ async function setExpandedForSubtree(req) {
|
||||
// root is always expanded
|
||||
branchIds = branchIds.filter(branchId => branchId !== 'root');
|
||||
|
||||
await sql.executeMany(`UPDATE branches SET isExpanded = ${expanded} WHERE branchId IN (???)`, branchIds);
|
||||
sql.executeMany(`UPDATE branches SET isExpanded = ${expanded} WHERE branchId IN (???)`, branchIds);
|
||||
|
||||
return {
|
||||
branchIds
|
||||
};
|
||||
}
|
||||
|
||||
async function deleteBranch(req) {
|
||||
function deleteBranch(req) {
|
||||
const last = req.query.last === 'true';
|
||||
const branch = await repository.getBranch(req.params.branchId);
|
||||
const branch = repository.getBranch(req.params.branchId);
|
||||
const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes');
|
||||
|
||||
const deleteId = utils.randomString(10);
|
||||
const noteDeleted = await noteService.deleteBranch(branch, deleteId, taskContext);
|
||||
const noteDeleted = noteService.deleteBranch(branch, deleteId, taskContext);
|
||||
|
||||
if (last) {
|
||||
taskContext.taskSucceeded();
|
||||
@@ -170,13 +170,13 @@ async function deleteBranch(req) {
|
||||
};
|
||||
}
|
||||
|
||||
async function setPrefix(req) {
|
||||
function setPrefix(req) {
|
||||
const branchId = req.params.branchId;
|
||||
const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix;
|
||||
|
||||
const branch = await repository.getBranch(branchId);
|
||||
const branch = repository.getBranch(branchId);
|
||||
branch.prefix = prefix;
|
||||
await branch.save();
|
||||
branch.save();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -12,11 +12,11 @@ const utils = require('../../services/utils');
|
||||
const path = require('path');
|
||||
const Attribute = require('../../entities/attribute');
|
||||
|
||||
async function findClippingNote(todayNote, pageUrl) {
|
||||
const notes = await todayNote.getDescendantNotesWithLabel('pageUrl', pageUrl);
|
||||
function findClippingNote(todayNote, pageUrl) {
|
||||
const notes = todayNote.getDescendantNotesWithLabel('pageUrl', pageUrl);
|
||||
|
||||
for (const note of notes) {
|
||||
if (await note.getOwnedLabelValue('clipType') === 'clippings') {
|
||||
if (note.getOwnedLabelValue('clipType') === 'clippings') {
|
||||
return note;
|
||||
}
|
||||
}
|
||||
@@ -24,76 +24,76 @@ async function findClippingNote(todayNote, pageUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getClipperInboxNote() {
|
||||
let clipperInbox = await attributeService.getNoteWithLabel('clipperInbox');
|
||||
function getClipperInboxNote() {
|
||||
let clipperInbox = attributeService.getNoteWithLabel('clipperInbox');
|
||||
|
||||
if (!clipperInbox) {
|
||||
clipperInbox = await dateNoteService.getDateNote(dateUtils.localNowDate());
|
||||
clipperInbox = dateNoteService.getDateNote(dateUtils.localNowDate());
|
||||
}
|
||||
|
||||
return clipperInbox;
|
||||
}
|
||||
|
||||
async function addClipping(req) {
|
||||
function addClipping(req) {
|
||||
const {title, content, pageUrl, images} = req.body;
|
||||
|
||||
const clipperInbox = await getClipperInboxNote();
|
||||
const clipperInbox = getClipperInboxNote();
|
||||
|
||||
let clippingNote = await findClippingNote(clipperInbox, pageUrl);
|
||||
let clippingNote = findClippingNote(clipperInbox, pageUrl);
|
||||
|
||||
if (!clippingNote) {
|
||||
clippingNote = (await noteService.createNewNote({
|
||||
clippingNote = (noteService.createNewNote({
|
||||
parentNoteId: clipperInbox.noteId,
|
||||
title: title,
|
||||
content: '',
|
||||
type: 'text'
|
||||
})).note;
|
||||
|
||||
await clippingNote.setLabel('clipType', 'clippings');
|
||||
await clippingNote.setLabel('pageUrl', pageUrl);
|
||||
clippingNote.setLabel('clipType', 'clippings');
|
||||
clippingNote.setLabel('pageUrl', pageUrl);
|
||||
}
|
||||
|
||||
const rewrittenContent = await addImagesToNote(images, clippingNote, content);
|
||||
const rewrittenContent = addImagesToNote(images, clippingNote, content);
|
||||
|
||||
const existingContent = await clippingNote.getContent();
|
||||
const existingContent = clippingNote.getContent();
|
||||
|
||||
await clippingNote.setContent(existingContent + (existingContent.trim() ? "<br/>" : "") + rewrittenContent);
|
||||
clippingNote.setContent(existingContent + (existingContent.trim() ? "<br/>" : "") + rewrittenContent);
|
||||
|
||||
return {
|
||||
noteId: clippingNote.noteId
|
||||
};
|
||||
}
|
||||
|
||||
async function createNote(req) {
|
||||
function createNote(req) {
|
||||
const {title, content, pageUrl, images, clipType} = req.body;
|
||||
|
||||
log.info(`Creating clipped note from ${pageUrl}`);
|
||||
|
||||
const clipperInbox = await getClipperInboxNote();
|
||||
const clipperInbox = getClipperInboxNote();
|
||||
|
||||
const {note} = await noteService.createNewNote({
|
||||
const {note} = noteService.createNewNote({
|
||||
parentNoteId: clipperInbox.noteId,
|
||||
title,
|
||||
content,
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
await note.setLabel('clipType', clipType);
|
||||
note.setLabel('clipType', clipType);
|
||||
|
||||
if (pageUrl) {
|
||||
await note.setLabel('pageUrl', pageUrl);
|
||||
note.setLabel('pageUrl', pageUrl);
|
||||
}
|
||||
|
||||
const rewrittenContent = await addImagesToNote(images, note, content);
|
||||
const rewrittenContent = addImagesToNote(images, note, content);
|
||||
|
||||
await note.setContent(rewrittenContent);
|
||||
note.setContent(rewrittenContent);
|
||||
|
||||
return {
|
||||
noteId: note.noteId
|
||||
};
|
||||
}
|
||||
|
||||
async function addImagesToNote(images, note, content) {
|
||||
function addImagesToNote(images, note, content) {
|
||||
let rewrittenContent = content;
|
||||
|
||||
if (images) {
|
||||
@@ -107,15 +107,15 @@ async function addImagesToNote(images, note, content) {
|
||||
|
||||
const buffer = Buffer.from(dataUrl.split(",")[1], 'base64');
|
||||
|
||||
const {note: imageNote, url} = await imageService.saveImage(note.noteId, buffer, filename, true);
|
||||
const {note: imageNote, url} = imageService.saveImage(note.noteId, buffer, filename, true);
|
||||
|
||||
await new Attribute({
|
||||
new Attribute({
|
||||
noteId: imageNote.noteId,
|
||||
type: 'label',
|
||||
name: 'hideInAutocomplete'
|
||||
}).save();
|
||||
|
||||
await new Attribute({
|
||||
new Attribute({
|
||||
noteId: note.noteId,
|
||||
type: 'relation',
|
||||
name: 'imageLink',
|
||||
@@ -131,7 +131,7 @@ async function addImagesToNote(images, note, content) {
|
||||
return rewrittenContent;
|
||||
}
|
||||
|
||||
async function openNote(req) {
|
||||
function openNote(req) {
|
||||
if (utils.isElectron()) {
|
||||
ws.sendMessageToAllClients({
|
||||
type: 'open-note',
|
||||
@@ -149,7 +149,7 @@ async function openNote(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handshake() {
|
||||
function handshake() {
|
||||
return {
|
||||
appName: "trilium",
|
||||
protocolVersion: appInfo.clipperProtocolVersion
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
const cloningService = require('../../services/cloning');
|
||||
|
||||
async function cloneNoteToParent(req) {
|
||||
function cloneNoteToParent(req) {
|
||||
const {noteId, parentBranchId} = req.params;
|
||||
const {prefix} = req.body;
|
||||
|
||||
return await cloningService.cloneNoteToParent(noteId, parentBranchId, prefix);
|
||||
return cloningService.cloneNoteToParent(noteId, parentBranchId, prefix);
|
||||
}
|
||||
|
||||
async function cloneNoteAfter(req) {
|
||||
function cloneNoteAfter(req) {
|
||||
const {noteId, afterBranchId} = req.params;
|
||||
|
||||
return await cloningService.cloneNoteAfter(noteId, afterBranchId);
|
||||
return cloningService.cloneNoteAfter(noteId, afterBranchId);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -5,24 +5,24 @@ const log = require('../../services/log');
|
||||
const backupService = require('../../services/backup');
|
||||
const consistencyChecksService = require('../../services/consistency_checks');
|
||||
|
||||
async function anonymize() {
|
||||
return await backupService.anonymize();
|
||||
function anonymize() {
|
||||
return backupService.anonymize();
|
||||
}
|
||||
|
||||
async function backupDatabase() {
|
||||
function backupDatabase() {
|
||||
return {
|
||||
backupFile: await backupService.backupNow("now")
|
||||
backupFile: backupService.backupNow("now")
|
||||
};
|
||||
}
|
||||
|
||||
async function vacuumDatabase() {
|
||||
await sql.execute("VACUUM");
|
||||
function vacuumDatabase() {
|
||||
sql.execute("VACUUM");
|
||||
|
||||
log.info("Database has been vacuumed.");
|
||||
}
|
||||
|
||||
async function findAndFixConsistencyIssues() {
|
||||
await consistencyChecksService.runOnDemandChecks(true);
|
||||
function findAndFixConsistencyIssues() {
|
||||
consistencyChecksService.runOnDemandChecks(true);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -5,19 +5,19 @@ const sql = require('../../services/sql');
|
||||
const dateUtils = require('../../services/date_utils');
|
||||
const noteService = require('../../services/notes');
|
||||
|
||||
async function getDateNote(req) {
|
||||
return await dateNoteService.getDateNote(req.params.date);
|
||||
function getDateNote(req) {
|
||||
return dateNoteService.getDateNote(req.params.date);
|
||||
}
|
||||
|
||||
async function getMonthNote(req) {
|
||||
return await dateNoteService.getMonthNote(req.params.month);
|
||||
function getMonthNote(req) {
|
||||
return dateNoteService.getMonthNote(req.params.month);
|
||||
}
|
||||
|
||||
async function getYearNote(req) {
|
||||
return await dateNoteService.getYearNote(req.params.year);
|
||||
function getYearNote(req) {
|
||||
return dateNoteService.getYearNote(req.params.year);
|
||||
}
|
||||
|
||||
async function getDateNotesForMonth(req) {
|
||||
function getDateNotesForMonth(req) {
|
||||
const month = req.params.month;
|
||||
|
||||
return sql.getMap(`
|
||||
@@ -33,12 +33,12 @@ async function getDateNotesForMonth(req) {
|
||||
AND attr.value LIKE '${month}%'`);
|
||||
}
|
||||
|
||||
async function createSqlConsole() {
|
||||
function createSqlConsole() {
|
||||
const today = dateUtils.localNowDate();
|
||||
|
||||
const todayNote = await dateNoteService.getDateNote(today);
|
||||
const todayNote = dateNoteService.getDateNote(today);
|
||||
|
||||
const {note} = await noteService.createNewNote({
|
||||
const {note} = noteService.createNewNote({
|
||||
parentNoteId: todayNote.noteId,
|
||||
title: 'SQL Console',
|
||||
content: "SELECT title, isDeleted, isProtected FROM notes WHERE noteId = ''\n\n\n\n",
|
||||
@@ -46,7 +46,7 @@ async function createSqlConsole() {
|
||||
mime: 'text/x-sqlite;schema=trilium'
|
||||
});
|
||||
|
||||
await note.setLabel("sqlConsole", today);
|
||||
note.setLabel("sqlConsole", today);
|
||||
|
||||
return note;
|
||||
}
|
||||
@@ -57,4 +57,4 @@ module.exports = {
|
||||
getYearNote,
|
||||
getDateNotesForMonth,
|
||||
createSqlConsole
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,9 +7,9 @@ const repository = require("../../services/repository");
|
||||
const TaskContext = require("../../services/task_context");
|
||||
const log = require("../../services/log");
|
||||
|
||||
async function exportBranch(req, res) {
|
||||
function exportBranch(req, res) {
|
||||
const {branchId, type, format, version, taskId} = req.params;
|
||||
const branch = await repository.getBranch(branchId);
|
||||
const branch = repository.getBranch(branchId);
|
||||
|
||||
if (!branch) {
|
||||
const message = `Cannot export branch ${branchId} since it does not exist.`;
|
||||
@@ -25,15 +25,15 @@ async function exportBranch(req, res) {
|
||||
if (type === 'subtree' && (format === 'html' || format === 'markdown')) {
|
||||
const start = Date.now();
|
||||
|
||||
await zipExportService.exportToZip(taskContext, branch, format, res);
|
||||
zipExportService.exportToZip(taskContext, branch, format, res);
|
||||
|
||||
console.log("Export took", Date.now() - start, "ms");
|
||||
}
|
||||
else if (type === 'single') {
|
||||
await singleExportService.exportSingleNote(taskContext, branch, format, res);
|
||||
singleExportService.exportSingleNote(taskContext, branch, format, res);
|
||||
}
|
||||
else if (format === 'opml') {
|
||||
await opmlExportService.exportToOpml(taskContext, branch, version, res);
|
||||
opmlExportService.exportToOpml(taskContext, branch, version, res);
|
||||
}
|
||||
else {
|
||||
return [404, "Unrecognized export format " + format];
|
||||
|
||||
@@ -5,33 +5,33 @@ const repository = require('../../services/repository');
|
||||
const utils = require('../../services/utils');
|
||||
const noteRevisionService = require('../../services/note_revisions');
|
||||
|
||||
async function updateFile(req) {
|
||||
function updateFile(req) {
|
||||
const {noteId} = req.params;
|
||||
const file = req.file;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${noteId} doesn't exist.`];
|
||||
}
|
||||
|
||||
await noteRevisionService.createNoteRevision(note);
|
||||
noteRevisionService.createNoteRevision(note);
|
||||
|
||||
note.mime = file.mimetype.toLowerCase();
|
||||
|
||||
await note.setContent(file.buffer);
|
||||
note.setContent(file.buffer);
|
||||
|
||||
await note.setLabel('originalFileName', file.originalname);
|
||||
note.setLabel('originalFileName', file.originalname);
|
||||
|
||||
await noteRevisionService.protectNoteRevisions(note);
|
||||
noteRevisionService.protectNoteRevisions(note);
|
||||
|
||||
return {
|
||||
uploaded: true
|
||||
};
|
||||
}
|
||||
|
||||
async function downloadNoteFile(noteId, res, contentDisposition = true) {
|
||||
const note = await repository.getNote(noteId);
|
||||
function downloadNoteFile(noteId, res, contentDisposition = true) {
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return res.status(404).send(`Note ${noteId} doesn't exist.`);
|
||||
@@ -51,19 +51,19 @@ async function downloadNoteFile(noteId, res, contentDisposition = true) {
|
||||
|
||||
res.setHeader('Content-Type', note.mime);
|
||||
|
||||
res.send(await note.getContent());
|
||||
res.send(note.getContent());
|
||||
}
|
||||
|
||||
async function downloadFile(req, res) {
|
||||
function downloadFile(req, res) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
return await downloadNoteFile(noteId, res);
|
||||
return downloadNoteFile(noteId, res);
|
||||
}
|
||||
|
||||
async function openFile(req, res) {
|
||||
function openFile(req, res) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
return await downloadNoteFile(noteId, res, false);
|
||||
return downloadNoteFile(noteId, res, false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -5,8 +5,8 @@ const repository = require('../../services/repository');
|
||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
|
||||
const fs = require('fs');
|
||||
|
||||
async function returnImage(req, res) {
|
||||
const image = await repository.getNote(req.params.noteId);
|
||||
function returnImage(req, res) {
|
||||
const image = repository.getNote(req.params.noteId);
|
||||
|
||||
if (!image) {
|
||||
return res.sendStatus(404);
|
||||
@@ -21,14 +21,14 @@ async function returnImage(req, res) {
|
||||
|
||||
res.set('Content-Type', image.mime);
|
||||
|
||||
res.send(await image.getContent());
|
||||
res.send(image.getContent());
|
||||
}
|
||||
|
||||
async function uploadImage(req) {
|
||||
function uploadImage(req) {
|
||||
const {noteId} = req.query;
|
||||
const {file} = req;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${noteId} doesn't exist.`];
|
||||
@@ -38,7 +38,7 @@ async function uploadImage(req) {
|
||||
return [400, "Unknown image type: " + file.mimetype];
|
||||
}
|
||||
|
||||
const {url} = await imageService.saveImage(noteId, file.buffer, file.originalname, true);
|
||||
const {url} = imageService.saveImage(noteId, file.buffer, file.originalname, true);
|
||||
|
||||
return {
|
||||
uploaded: true,
|
||||
@@ -46,11 +46,11 @@ async function uploadImage(req) {
|
||||
};
|
||||
}
|
||||
|
||||
async function updateImage(req) {
|
||||
function updateImage(req) {
|
||||
const {noteId} = req.params;
|
||||
const {file} = req;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${noteId} doesn't exist.`];
|
||||
@@ -63,7 +63,7 @@ async function updateImage(req) {
|
||||
};
|
||||
}
|
||||
|
||||
await imageService.updateImage(noteId, file.buffer, file.originalname);
|
||||
imageService.updateImage(noteId, file.buffer, file.originalname);
|
||||
|
||||
return { uploaded: true };
|
||||
}
|
||||
@@ -72,4 +72,4 @@ module.exports = {
|
||||
returnImage,
|
||||
uploadImage,
|
||||
updateImage
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ const noteCacheService = require('../../services/note_cache/note_cache.js');
|
||||
const log = require('../../services/log');
|
||||
const TaskContext = require('../../services/task_context.js');
|
||||
|
||||
async function importToBranch(req) {
|
||||
function importToBranch(req) {
|
||||
const {parentNoteId} = req.params;
|
||||
const {taskId, last} = req.body;
|
||||
|
||||
@@ -31,7 +31,7 @@ async function importToBranch(req) {
|
||||
return [400, "No file has been uploaded"];
|
||||
}
|
||||
|
||||
const parentNote = await repository.getNote(parentNoteId);
|
||||
const parentNote = repository.getNote(parentNoteId);
|
||||
|
||||
if (!parentNote) {
|
||||
return [404, `Note ${parentNoteId} doesn't exist.`];
|
||||
@@ -49,19 +49,19 @@ async function importToBranch(req) {
|
||||
|
||||
try {
|
||||
if (extension === '.tar' && options.explodeArchives) {
|
||||
note = await tarImportService.importTar(taskContext, file.buffer, parentNote);
|
||||
note = tarImportService.importTar(taskContext, file.buffer, parentNote);
|
||||
} else if (extension === '.zip' && options.explodeArchives) {
|
||||
const start = Date.now();
|
||||
|
||||
note = await zipImportService.importZip(taskContext, file.buffer, parentNote);
|
||||
note = zipImportService.importZip(taskContext, file.buffer, parentNote);
|
||||
|
||||
console.log("Import took", Date.now() - start, "ms");
|
||||
} else if (extension === '.opml' && options.explodeArchives) {
|
||||
note = await opmlImportService.importOpml(taskContext, file.buffer, parentNote);
|
||||
note = opmlImportService.importOpml(taskContext, file.buffer, parentNote);
|
||||
} else if (extension === '.enex' && options.explodeArchives) {
|
||||
note = await enexImportService.importEnex(taskContext, file, parentNote);
|
||||
note = enexImportService.importEnex(taskContext, file, parentNote);
|
||||
} else {
|
||||
note = await singleImportService.importSingleFile(taskContext, file, parentNote);
|
||||
note = singleImportService.importSingleFile(taskContext, file, parentNote);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
const keyboardActions = require('../../services/keyboard_actions');
|
||||
const sql = require('../../services/sql');
|
||||
|
||||
async function getKeyboardActions() {
|
||||
return await keyboardActions.getKeyboardActions();
|
||||
function getKeyboardActions() {
|
||||
return keyboardActions.getKeyboardActions();
|
||||
}
|
||||
|
||||
async function getShortcutsForNotes() {
|
||||
return await sql.getMap(`
|
||||
function getShortcutsForNotes() {
|
||||
return sql.getMap(`
|
||||
SELECT value, noteId
|
||||
FROM attributes
|
||||
WHERE isDeleted = 0
|
||||
@@ -19,4 +19,4 @@ async function getShortcutsForNotes() {
|
||||
module.exports = {
|
||||
getKeyboardActions,
|
||||
getShortcutsForNotes
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const sql = require('../../services/sql');
|
||||
|
||||
async function getRelations(noteIds) {
|
||||
return (await sql.getManyRows(`
|
||||
function getRelations(noteIds) {
|
||||
return (sql.getManyRows(`
|
||||
SELECT noteId, name, value AS targetNoteId
|
||||
FROM attributes
|
||||
WHERE (noteId IN (???) OR value IN (???))
|
||||
@@ -14,7 +14,7 @@ async function getRelations(noteIds) {
|
||||
`, Array.from(noteIds)));
|
||||
}
|
||||
|
||||
async function getLinkMap(req) {
|
||||
function getLinkMap(req) {
|
||||
const {noteId} = req.params;
|
||||
const {maxNotes, maxDepth} = req.body;
|
||||
|
||||
@@ -24,7 +24,7 @@ async function getLinkMap(req) {
|
||||
let depth = 0;
|
||||
|
||||
while (noteIds.size < maxNotes) {
|
||||
relations = await getRelations(noteIds);
|
||||
relations = getRelations(noteIds);
|
||||
|
||||
if (depth === maxDepth) {
|
||||
break;
|
||||
@@ -58,4 +58,4 @@ async function getLinkMap(req) {
|
||||
|
||||
module.exports = {
|
||||
getLinkMap
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,8 +14,8 @@ const sql = require('../../services/sql');
|
||||
const optionService = require('../../services/options');
|
||||
const ApiToken = require('../../entities/api_token');
|
||||
|
||||
async function loginSync(req) {
|
||||
if (!await sqlInit.schemaExists()) {
|
||||
function loginSync(req) {
|
||||
if (!sqlInit.schemaExists()) {
|
||||
return [500, { message: "DB schema does not exist, can't sync." }];
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ async function loginSync(req) {
|
||||
return [400, { message: `Non-matching sync versions, local is version ${appInfo.syncVersion}, remote is ${syncVersion}. It is recommended to run same version of Trilium on both sides of sync.` }];
|
||||
}
|
||||
|
||||
const documentSecret = await options.getOption('documentSecret');
|
||||
const documentSecret = options.getOption('documentSecret');
|
||||
const expectedHash = utils.hmac(documentSecret, timestampStr);
|
||||
|
||||
const givenHash = req.body.hash;
|
||||
@@ -49,28 +49,28 @@ async function loginSync(req) {
|
||||
|
||||
return {
|
||||
sourceId: sourceIdService.getCurrentSourceId(),
|
||||
maxSyncId: await sql.getValue("SELECT MAX(id) FROM sync WHERE isSynced = 1")
|
||||
maxSyncId: sql.getValue("SELECT MAX(id) FROM sync WHERE isSynced = 1")
|
||||
};
|
||||
}
|
||||
|
||||
async function loginToProtectedSession(req) {
|
||||
function loginToProtectedSession(req) {
|
||||
const password = req.body.password;
|
||||
|
||||
if (!await passwordEncryptionService.verifyPassword(password)) {
|
||||
if (!passwordEncryptionService.verifyPassword(password)) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Given current password doesn't match hash"
|
||||
};
|
||||
}
|
||||
|
||||
const decryptedDataKey = await passwordEncryptionService.getDataKey(password);
|
||||
const decryptedDataKey = passwordEncryptionService.getDataKey(password);
|
||||
|
||||
const protectedSessionId = protectedSessionService.setDataKey(decryptedDataKey);
|
||||
|
||||
// this is set here so that event handlers have access to the protected session
|
||||
cls.set('protectedSessionId', protectedSessionId);
|
||||
|
||||
await eventService.emit(eventService.ENTER_PROTECTED_SESSION);
|
||||
eventService.emit(eventService.ENTER_PROTECTED_SESSION);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -78,18 +78,18 @@ async function loginToProtectedSession(req) {
|
||||
};
|
||||
}
|
||||
|
||||
async function token(req) {
|
||||
function token(req) {
|
||||
const username = req.body.username;
|
||||
const password = req.body.password;
|
||||
|
||||
const isUsernameValid = username === await optionService.getOption('username');
|
||||
const isPasswordValid = await passwordEncryptionService.verifyPassword(password);
|
||||
const isUsernameValid = username === optionService.getOption('username');
|
||||
const isPasswordValid = passwordEncryptionService.verifyPassword(password);
|
||||
|
||||
if (!isUsernameValid || !isPasswordValid) {
|
||||
return [401, "Incorrect username/password"];
|
||||
}
|
||||
|
||||
const apiToken = await new ApiToken({
|
||||
const apiToken = new ApiToken({
|
||||
token: utils.randomSecureToken()
|
||||
}).save();
|
||||
|
||||
|
||||
@@ -7,23 +7,23 @@ const noteRevisionService = require('../../services/note_revisions');
|
||||
const utils = require('../../services/utils');
|
||||
const path = require('path');
|
||||
|
||||
async function getNoteRevisions(req) {
|
||||
return await repository.getEntities(`
|
||||
function getNoteRevisions(req) {
|
||||
return repository.getEntities(`
|
||||
SELECT * FROM note_revisions
|
||||
WHERE noteId = ? AND isErased = 0
|
||||
ORDER BY utcDateCreated DESC`, [req.params.noteId]);
|
||||
}
|
||||
|
||||
async function getNoteRevision(req) {
|
||||
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
|
||||
function getNoteRevision(req) {
|
||||
const noteRevision = repository.getNoteRevision(req.params.noteRevisionId);
|
||||
|
||||
if (noteRevision.type === 'file') {
|
||||
if (noteRevision.isStringNote()) {
|
||||
noteRevision.content = (await noteRevision.getContent()).substr(0, 10000);
|
||||
noteRevision.content = (noteRevision.getContent()).substr(0, 10000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
noteRevision.content = await noteRevision.getContent();
|
||||
noteRevision.content = noteRevision.getContent();
|
||||
|
||||
if (noteRevision.content && noteRevision.type === 'image') {
|
||||
noteRevision.content = noteRevision.content.toString('base64');
|
||||
@@ -57,8 +57,8 @@ function getRevisionFilename(noteRevision) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
async function downloadNoteRevision(req, res) {
|
||||
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
|
||||
function downloadNoteRevision(req, res) {
|
||||
const noteRevision = repository.getNoteRevision(req.params.noteRevisionId);
|
||||
|
||||
if (noteRevision.noteId !== req.params.noteId) {
|
||||
return res.status(400).send(`Note revision ${req.params.noteRevisionId} does not belong to note ${req.params.noteId}`);
|
||||
@@ -73,55 +73,55 @@ async function downloadNoteRevision(req, res) {
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||
res.setHeader('Content-Type', noteRevision.mime);
|
||||
|
||||
res.send(await noteRevision.getContent());
|
||||
res.send(noteRevision.getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NoteRevision} noteRevision
|
||||
*/
|
||||
async function eraseOneNoteRevision(noteRevision) {
|
||||
function eraseOneNoteRevision(noteRevision) {
|
||||
noteRevision.isErased = true;
|
||||
noteRevision.title = null;
|
||||
await noteRevision.setContent(null);
|
||||
await noteRevision.save();
|
||||
noteRevision.setContent(null);
|
||||
noteRevision.save();
|
||||
}
|
||||
|
||||
async function eraseAllNoteRevisions(req) {
|
||||
const noteRevisionsToErase = await repository.getEntities(
|
||||
function eraseAllNoteRevisions(req) {
|
||||
const noteRevisionsToErase = repository.getEntities(
|
||||
'SELECT * FROM note_revisions WHERE isErased = 0 AND noteId = ?',
|
||||
[req.params.noteId]);
|
||||
|
||||
for (const noteRevision of noteRevisionsToErase) {
|
||||
await eraseOneNoteRevision(noteRevision);
|
||||
eraseOneNoteRevision(noteRevision);
|
||||
}
|
||||
}
|
||||
|
||||
async function eraseNoteRevision(req) {
|
||||
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
|
||||
function eraseNoteRevision(req) {
|
||||
const noteRevision = repository.getNoteRevision(req.params.noteRevisionId);
|
||||
|
||||
if (noteRevision && !noteRevision.isErased) {
|
||||
await eraseOneNoteRevision(noteRevision);
|
||||
eraseOneNoteRevision(noteRevision);
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreNoteRevision(req) {
|
||||
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
|
||||
function restoreNoteRevision(req) {
|
||||
const noteRevision = repository.getNoteRevision(req.params.noteRevisionId);
|
||||
|
||||
if (noteRevision && !noteRevision.isErased) {
|
||||
const note = await noteRevision.getNote();
|
||||
const note = noteRevision.getNote();
|
||||
|
||||
await noteRevisionService.createNoteRevision(note);
|
||||
noteRevisionService.createNoteRevision(note);
|
||||
|
||||
note.title = noteRevision.title;
|
||||
await note.setContent(await noteRevision.getContent());
|
||||
await note.save();
|
||||
note.setContent(noteRevision.getContent());
|
||||
note.save();
|
||||
}
|
||||
}
|
||||
|
||||
async function getEditedNotesOnDate(req) {
|
||||
function getEditedNotesOnDate(req) {
|
||||
const date = utils.sanitizeSql(req.params.date);
|
||||
|
||||
const notes = await repository.getEntities(`
|
||||
const notes = repository.getEntities(`
|
||||
SELECT notes.*
|
||||
FROM notes
|
||||
WHERE noteId IN (
|
||||
|
||||
@@ -6,16 +6,16 @@ const repository = require('../../services/repository');
|
||||
const utils = require('../../services/utils');
|
||||
const TaskContext = require('../../services/task_context');
|
||||
|
||||
async function getNote(req) {
|
||||
function getNote(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, "Note " + noteId + " has not been found."];
|
||||
}
|
||||
|
||||
if (note.isStringNote()) {
|
||||
note.content = await note.getContent();
|
||||
note.content = note.getContent();
|
||||
|
||||
if (note.type === 'file') {
|
||||
note.content = note.content.substr(0, 10000);
|
||||
@@ -25,13 +25,13 @@ async function getNote(req) {
|
||||
return note;
|
||||
}
|
||||
|
||||
async function createNote(req) {
|
||||
function createNote(req) {
|
||||
const params = Object.assign({}, req.body); // clone
|
||||
params.parentNoteId = req.params.parentNoteId;
|
||||
|
||||
const { target, targetBranchId } = req.query;
|
||||
|
||||
const { note, branch } = await noteService.createNewNoteWithTarget(target, targetBranchId, params);
|
||||
const { note, branch } = noteService.createNewNoteWithTarget(target, targetBranchId, params);
|
||||
|
||||
return {
|
||||
note,
|
||||
@@ -39,14 +39,14 @@ async function createNote(req) {
|
||||
};
|
||||
}
|
||||
|
||||
async function updateNote(req) {
|
||||
function updateNote(req) {
|
||||
const note = req.body;
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
return await noteService.updateNote(noteId, note);
|
||||
return noteService.updateNote(noteId, note);
|
||||
}
|
||||
|
||||
async function deleteNote(req) {
|
||||
function deleteNote(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const taskId = req.query.taskId;
|
||||
const last = req.query.last === 'true';
|
||||
@@ -54,61 +54,61 @@ async function deleteNote(req) {
|
||||
// note how deleteId is separate from taskId - single taskId produces separate deleteId for each "top level" deleted note
|
||||
const deleteId = utils.randomString(10);
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
const taskContext = TaskContext.getInstance(taskId, 'delete-notes');
|
||||
|
||||
for (const branch of await note.getBranches()) {
|
||||
await noteService.deleteBranch(branch, deleteId, taskContext);
|
||||
for (const branch of note.getBranches()) {
|
||||
noteService.deleteBranch(branch, deleteId, taskContext);
|
||||
}
|
||||
|
||||
if (last) {
|
||||
await taskContext.taskSucceeded();
|
||||
taskContext.taskSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
async function undeleteNote(req) {
|
||||
const note = await repository.getNote(req.params.noteId);
|
||||
function undeleteNote(req) {
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
const taskContext = TaskContext.getInstance(utils.randomString(10), 'undelete-notes');
|
||||
|
||||
await noteService.undeleteNote(note, note.deleteId, taskContext);
|
||||
noteService.undeleteNote(note, note.deleteId, taskContext);
|
||||
|
||||
await taskContext.taskSucceeded();
|
||||
taskContext.taskSucceeded();
|
||||
}
|
||||
|
||||
async function sortNotes(req) {
|
||||
function sortNotes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
await treeService.sortNotesAlphabetically(noteId);
|
||||
treeService.sortNotesAlphabetically(noteId);
|
||||
}
|
||||
|
||||
async function protectNote(req) {
|
||||
function protectNote(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
const protect = !!parseInt(req.params.isProtected);
|
||||
const includingSubTree = !!parseInt(req.query.subtree);
|
||||
|
||||
const taskContext = new TaskContext(utils.randomString(10), 'protect-notes', {protect});
|
||||
|
||||
await noteService.protectNoteRecursively(note, protect, includingSubTree, taskContext);
|
||||
noteService.protectNoteRecursively(note, protect, includingSubTree, taskContext);
|
||||
|
||||
taskContext.taskSucceeded();
|
||||
}
|
||||
|
||||
async function setNoteTypeMime(req) {
|
||||
function setNoteTypeMime(req) {
|
||||
// can't use [] destructuring because req.params is not iterable
|
||||
const noteId = req.params[0];
|
||||
const type = req.params[1];
|
||||
const mime = req.params[2];
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
note.type = type;
|
||||
note.mime = mime;
|
||||
await note.save();
|
||||
note.save();
|
||||
}
|
||||
|
||||
async function getRelationMap(req) {
|
||||
function getRelationMap(req) {
|
||||
const noteIds = req.body.noteIds;
|
||||
const resp = {
|
||||
// noteId => title
|
||||
@@ -126,12 +126,12 @@ async function getRelationMap(req) {
|
||||
|
||||
const questionMarks = noteIds.map(noteId => '?').join(',');
|
||||
|
||||
const notes = await repository.getEntities(`SELECT * FROM notes WHERE isDeleted = 0 AND noteId IN (${questionMarks})`, noteIds);
|
||||
const notes = repository.getEntities(`SELECT * FROM notes WHERE isDeleted = 0 AND noteId IN (${questionMarks})`, noteIds);
|
||||
|
||||
for (const note of notes) {
|
||||
resp.noteTitles[note.noteId] = note.title;
|
||||
|
||||
resp.relations = resp.relations.concat((await note.getRelations())
|
||||
resp.relations = resp.relations.concat((note.getRelations())
|
||||
.filter(relation => noteIds.includes(relation.value))
|
||||
.map(relation => ({
|
||||
attributeId: relation.attributeId,
|
||||
@@ -140,7 +140,7 @@ async function getRelationMap(req) {
|
||||
name: relation.name
|
||||
})));
|
||||
|
||||
for (const relationDefinition of await note.getRelationDefinitions()) {
|
||||
for (const relationDefinition of note.getRelationDefinitions()) {
|
||||
if (relationDefinition.value.inverseRelation) {
|
||||
resp.inverseRelations[relationDefinition.name] = relationDefinition.value.inverseRelation;
|
||||
}
|
||||
@@ -150,11 +150,11 @@ async function getRelationMap(req) {
|
||||
return resp;
|
||||
}
|
||||
|
||||
async function changeTitle(req) {
|
||||
function changeTitle(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const title = req.body.title;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${noteId} has not been found`];
|
||||
@@ -166,15 +166,15 @@ async function changeTitle(req) {
|
||||
|
||||
note.title = title;
|
||||
|
||||
await note.save();
|
||||
note.save();
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
async function duplicateNote(req) {
|
||||
function duplicateNote(req) {
|
||||
const {noteId, parentNoteId} = req.params;
|
||||
|
||||
return await noteService.duplicateNote(noteId, parentNoteId);
|
||||
return noteService.duplicateNote(noteId, parentNoteId);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -189,4 +189,4 @@ module.exports = {
|
||||
getRelationMap,
|
||||
changeTitle,
|
||||
duplicateNote
|
||||
};
|
||||
};
|
||||
|
||||
@@ -40,8 +40,8 @@ const ALLOWED_OPTIONS = new Set([
|
||||
'nativeTitleBarVisible'
|
||||
]);
|
||||
|
||||
async function getOptions() {
|
||||
const optionMap = await optionService.getOptionsMap();
|
||||
function getOptions() {
|
||||
const optionMap = optionService.getOptionsMap();
|
||||
const resultMap = {};
|
||||
|
||||
for (const optionName in optionMap) {
|
||||
@@ -53,17 +53,17 @@ async function getOptions() {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
async function updateOption(req) {
|
||||
function updateOption(req) {
|
||||
const {name, value} = req.params;
|
||||
|
||||
if (!await update(name, value)) {
|
||||
if (!update(name, value)) {
|
||||
return [400, "not allowed option to change"];
|
||||
}
|
||||
}
|
||||
|
||||
async function updateOptions(req) {
|
||||
function updateOptions(req) {
|
||||
for (const optionName in req.body) {
|
||||
if (!await update(optionName, req.body[optionName])) {
|
||||
if (!update(optionName, req.body[optionName])) {
|
||||
// this should be improved
|
||||
// it should return 400 instead of current 500, but at least it now rollbacks transaction
|
||||
throw new Error(`${optionName} is not allowed to change`);
|
||||
@@ -71,7 +71,7 @@ async function updateOptions(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function update(name, value) {
|
||||
function update(name, value) {
|
||||
if (!isAllowed(name)) {
|
||||
return false;
|
||||
}
|
||||
@@ -80,18 +80,18 @@ async function update(name, value) {
|
||||
log.info(`Updating option ${name} to ${value}`);
|
||||
}
|
||||
|
||||
await optionService.setOption(name, value);
|
||||
optionService.setOption(name, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function getUserThemes() {
|
||||
const notes = await attributes.getNotesWithLabel('appTheme');
|
||||
function getUserThemes() {
|
||||
const notes = attributes.getNotesWithLabel('appTheme');
|
||||
|
||||
const ret = [];
|
||||
|
||||
for (const note of notes) {
|
||||
let value = await note.getOwnedLabelValue('appTheme');
|
||||
let value = note.getOwnedLabelValue('appTheme');
|
||||
|
||||
if (!value) {
|
||||
value = note.title.toLowerCase().replace(/[^a-z0-9]/gi, '-');
|
||||
@@ -120,4 +120,4 @@ module.exports = {
|
||||
updateOption,
|
||||
updateOptions,
|
||||
getUserThemes
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
const changePasswordService = require('../../services/change_password');
|
||||
|
||||
async function changePassword(req) {
|
||||
return await changePasswordService.changePassword(req.body.current_password, req.body.new_password);
|
||||
function changePassword(req) {
|
||||
return changePasswordService.changePassword(req.body.current_password, req.body.new_password);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
changePassword
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,12 +5,12 @@ const protectedSessionService = require('../../services/protected_session');
|
||||
const noteService = require('../../services/notes');
|
||||
const noteCacheService = require('../../services/note_cache/note_cache.js');
|
||||
|
||||
async function getRecentChanges(req) {
|
||||
function getRecentChanges(req) {
|
||||
const {ancestorNoteId} = req.params;
|
||||
|
||||
let recentChanges = [];
|
||||
|
||||
const noteRevisions = await sql.getRows(`
|
||||
const noteRevisions = sql.getRows(`
|
||||
SELECT
|
||||
notes.noteId,
|
||||
notes.isDeleted AS current_isDeleted,
|
||||
@@ -31,7 +31,7 @@ async function getRecentChanges(req) {
|
||||
}
|
||||
}
|
||||
|
||||
const notes = await sql.getRows(`
|
||||
const notes = sql.getRows(`
|
||||
SELECT
|
||||
notes.noteId,
|
||||
notes.isDeleted AS current_isDeleted,
|
||||
@@ -75,7 +75,7 @@ async function getRecentChanges(req) {
|
||||
else {
|
||||
const deleteId = change.current_deleteId;
|
||||
|
||||
const undeletedParentBranches = await noteService.getUndeletedParentBranches(change.noteId, deleteId);
|
||||
const undeletedParentBranches = noteService.getUndeletedParentBranches(change.noteId, deleteId);
|
||||
|
||||
// note (and the subtree) can be undeleted if there's at least one undeleted parent (whose branch would be undeleted by this op)
|
||||
change.canBeUndeleted = undeletedParentBranches.length > 0;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const RecentNote = require('../../entities/recent_note');
|
||||
|
||||
async function addRecentNote(req) {
|
||||
await new RecentNote({
|
||||
function addRecentNote(req) {
|
||||
new RecentNote({
|
||||
noteId: req.body.noteId,
|
||||
notePath: req.body.notePath
|
||||
}).save();
|
||||
@@ -11,4 +11,4 @@ async function addRecentNote(req) {
|
||||
|
||||
module.exports = {
|
||||
addRecentNote
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,15 +5,15 @@ const attributeService = require('../../services/attributes');
|
||||
const repository = require('../../services/repository');
|
||||
const syncService = require('../../services/sync');
|
||||
|
||||
async function exec(req) {
|
||||
function exec(req) {
|
||||
try {
|
||||
const result = await scriptService.executeScript(req.body.script, req.body.params, req.body.startNoteId,
|
||||
const result = scriptService.executeScript(req.body.script, req.body.params, req.body.startNoteId,
|
||||
req.body.currentNoteId, req.body.originEntityName, req.body.originEntityId);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
executionResult: result,
|
||||
maxSyncId: await syncService.getMaxSyncId()
|
||||
maxSyncId: syncService.getMaxSyncId()
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
@@ -21,21 +21,21 @@ async function exec(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function run(req) {
|
||||
const note = await repository.getNote(req.params.noteId);
|
||||
function run(req) {
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
const result = await scriptService.executeNote(note, { originEntity: note });
|
||||
const result = scriptService.executeNote(note, { originEntity: note });
|
||||
|
||||
return { executionResult: result };
|
||||
}
|
||||
|
||||
async function getBundlesWithLabel(label, value) {
|
||||
const notes = await attributeService.getNotesWithLabel(label, value);
|
||||
function getBundlesWithLabel(label, value) {
|
||||
const notes = attributeService.getNotesWithLabel(label, value);
|
||||
|
||||
const bundles = [];
|
||||
|
||||
for (const note of notes) {
|
||||
const bundle = await scriptService.getScriptBundleForFrontend(note);
|
||||
const bundle = scriptService.getScriptBundleForFrontend(note);
|
||||
|
||||
if (bundle) {
|
||||
bundles.push(bundle);
|
||||
@@ -45,20 +45,20 @@ async function getBundlesWithLabel(label, value) {
|
||||
return bundles;
|
||||
}
|
||||
|
||||
async function getStartupBundles() {
|
||||
return await getBundlesWithLabel("run", "frontendStartup");
|
||||
function getStartupBundles() {
|
||||
return getBundlesWithLabel("run", "frontendStartup");
|
||||
}
|
||||
|
||||
async function getWidgetBundles() {
|
||||
return await getBundlesWithLabel("widget");
|
||||
function getWidgetBundles() {
|
||||
return getBundlesWithLabel("widget");
|
||||
}
|
||||
|
||||
async function getRelationBundles(req) {
|
||||
function getRelationBundles(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
const relationName = req.params.relationName;
|
||||
|
||||
const attributes = await note.getAttributes();
|
||||
const attributes = note.getAttributes();
|
||||
const filtered = attributes.filter(attr => attr.type === 'relation' && attr.name === relationName);
|
||||
const targetNoteIds = filtered.map(relation => relation.value);
|
||||
const uniqueNoteIds = Array.from(new Set(targetNoteIds));
|
||||
@@ -66,13 +66,13 @@ async function getRelationBundles(req) {
|
||||
const bundles = [];
|
||||
|
||||
for (const noteId of uniqueNoteIds) {
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note.isJavaScript() || note.getScriptEnv() !== 'frontend') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bundle = await scriptService.getScriptBundleForFrontend(note);
|
||||
const bundle = scriptService.getScriptBundleForFrontend(note);
|
||||
|
||||
if (bundle) {
|
||||
bundles.push(bundle);
|
||||
@@ -82,10 +82,10 @@ async function getRelationBundles(req) {
|
||||
return bundles;
|
||||
}
|
||||
|
||||
async function getBundle(req) {
|
||||
const note = await repository.getNote(req.params.noteId);
|
||||
function getBundle(req) {
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
return await scriptService.getScriptBundleForFrontend(note);
|
||||
return scriptService.getScriptBundleForFrontend(note);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -95,4 +95,4 @@ module.exports = {
|
||||
getWidgetBundles,
|
||||
getRelationBundles,
|
||||
getBundle
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@ const log = require('../../services/log');
|
||||
const scriptService = require('../../services/script');
|
||||
const searchService = require('../../services/search/search');
|
||||
|
||||
async function searchNotes(req) {
|
||||
const {count, results} = await searchService.searchNotes(req.params.searchString);
|
||||
function searchNotes(req) {
|
||||
const {count, results} = searchService.searchNotes(req.params.searchString);
|
||||
|
||||
try {
|
||||
return {
|
||||
@@ -23,8 +23,8 @@ async function searchNotes(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function searchFromNote(req) {
|
||||
const note = await repository.getNote(req.params.noteId);
|
||||
function searchFromNote(req) {
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${req.params.noteId} has not been found.`];
|
||||
@@ -38,7 +38,7 @@ async function searchFromNote(req) {
|
||||
return [400, `Note ${req.params.noteId} is not search note.`]
|
||||
}
|
||||
|
||||
const json = await note.getJsonContent();
|
||||
const json = note.getJsonContent();
|
||||
|
||||
if (!json || !json.searchString) {
|
||||
return [];
|
||||
@@ -50,9 +50,9 @@ async function searchFromNote(req) {
|
||||
if (json.searchString.startsWith('=')) {
|
||||
const relationName = json.searchString.substr(1).trim();
|
||||
|
||||
noteIds = await searchFromRelation(note, relationName);
|
||||
noteIds = searchFromRelation(note, relationName);
|
||||
} else {
|
||||
noteIds = await searchService.searchForNoteIds(json.searchString);
|
||||
noteIds = searchService.searchForNoteIds(json.searchString);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
@@ -71,8 +71,8 @@ async function searchFromNote(req) {
|
||||
return noteIds.map(noteCacheService.getNotePath).filter(res => !!res);
|
||||
}
|
||||
|
||||
async function searchFromRelation(note, relationName) {
|
||||
const scriptNote = await note.getRelationTarget(relationName);
|
||||
function searchFromRelation(note, relationName) {
|
||||
const scriptNote = note.getRelationTarget(relationName);
|
||||
|
||||
if (!scriptNote) {
|
||||
log.info(`Search note's relation ${relationName} has not been found.`);
|
||||
@@ -92,7 +92,7 @@ async function searchFromRelation(note, relationName) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result = await scriptService.executeNote(scriptNote, { originEntity: note });
|
||||
const result = scriptService.executeNote(scriptNote, { originEntity: note });
|
||||
|
||||
if (!Array.isArray(result)) {
|
||||
log.info(`Result from ${scriptNote.noteId} is not an array.`);
|
||||
|
||||
@@ -5,7 +5,7 @@ const imageService = require('../../services/image');
|
||||
const dateNoteService = require('../../services/date_notes');
|
||||
const noteService = require('../../services/notes');
|
||||
|
||||
async function uploadImage(req) {
|
||||
function uploadImage(req) {
|
||||
const file = req.file;
|
||||
|
||||
if (!["image/png", "image/jpeg", "image/gif"].includes(file.mimetype)) {
|
||||
@@ -14,19 +14,19 @@ async function uploadImage(req) {
|
||||
|
||||
const originalName = "Sender image." + imageType(file.buffer).ext;
|
||||
|
||||
const parentNote = await dateNoteService.getDateNote(req.headers['x-local-date']);
|
||||
const parentNote = dateNoteService.getDateNote(req.headers['x-local-date']);
|
||||
|
||||
const {noteId} = await imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
|
||||
const {noteId} = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
|
||||
|
||||
return {
|
||||
noteId: noteId
|
||||
};
|
||||
}
|
||||
|
||||
async function saveNote(req) {
|
||||
const parentNote = await dateNoteService.getDateNote(req.headers['x-local-date']);
|
||||
function saveNote(req) {
|
||||
const parentNote = dateNoteService.getDateNote(req.headers['x-local-date']);
|
||||
|
||||
const {note, branch} = await noteService.createNewNote({
|
||||
const {note, branch} = noteService.createNewNote({
|
||||
parentNoteId: parentNote.noteId,
|
||||
title: req.body.title,
|
||||
content: req.body.content,
|
||||
@@ -44,4 +44,4 @@ async function saveNote(req) {
|
||||
module.exports = {
|
||||
uploadImage,
|
||||
saveNote
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,27 +5,27 @@ const setupService = require('../../services/setup');
|
||||
const log = require('../../services/log');
|
||||
const appInfo = require('../../services/app_info');
|
||||
|
||||
async function getStatus() {
|
||||
function getStatus() {
|
||||
return {
|
||||
isInitialized: await sqlInit.isDbInitialized(),
|
||||
schemaExists: await sqlInit.schemaExists(),
|
||||
isInitialized: sqlInit.isDbInitialized(),
|
||||
schemaExists: sqlInit.schemaExists(),
|
||||
syncVersion: appInfo.syncVersion
|
||||
};
|
||||
}
|
||||
|
||||
async function setupNewDocument(req) {
|
||||
function setupNewDocument(req) {
|
||||
const { username, password, theme } = req.body;
|
||||
|
||||
await sqlInit.createInitialDatabase(username, password, theme);
|
||||
sqlInit.createInitialDatabase(username, password, theme);
|
||||
}
|
||||
|
||||
async function setupSyncFromServer(req) {
|
||||
function setupSyncFromServer(req) {
|
||||
const { syncServerHost, syncProxy, username, password } = req.body;
|
||||
|
||||
return await setupService.setupSyncFromSyncServer(syncServerHost, syncProxy, username, password);
|
||||
return setupService.setupSyncFromSyncServer(syncServerHost, syncProxy, username, password);
|
||||
}
|
||||
|
||||
async function saveSyncSeed(req) {
|
||||
function saveSyncSeed(req) {
|
||||
const {options, syncVersion} = req.body;
|
||||
|
||||
if (appInfo.syncVersion !== syncVersion) {
|
||||
@@ -38,14 +38,14 @@ async function saveSyncSeed(req) {
|
||||
}]
|
||||
}
|
||||
|
||||
await sqlInit.createDatabaseForSync(options);
|
||||
sqlInit.createDatabaseForSync(options);
|
||||
}
|
||||
|
||||
async function getSyncSeed() {
|
||||
function getSyncSeed() {
|
||||
log.info("Serving sync seed.");
|
||||
|
||||
return {
|
||||
options: await setupService.getSyncSeedOptions(),
|
||||
options: setupService.getSyncSeedOptions(),
|
||||
syncVersion: appInfo.syncVersion
|
||||
};
|
||||
}
|
||||
@@ -56,4 +56,4 @@ module.exports = {
|
||||
setupSyncFromServer,
|
||||
getSyncSeed,
|
||||
saveSyncSeed
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
const noteCacheService = require('../../services/note_cache/note_cache_service');
|
||||
const repository = require('../../services/repository');
|
||||
|
||||
async function getSimilarNotes(req) {
|
||||
function getSimilarNotes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
const note = repository.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${noteId} not found.`];
|
||||
}
|
||||
|
||||
const results = await noteCacheService.findSimilarNotes(noteId);
|
||||
const results = noteCacheService.findSimilarNotes(noteId);
|
||||
|
||||
return results
|
||||
.filter(note => note.noteId !== noteId);
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
|
||||
const sql = require('../../services/sql');
|
||||
|
||||
async function getSchema() {
|
||||
const tableNames = await sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
|
||||
function getSchema() {
|
||||
const tableNames = sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
|
||||
const tables = [];
|
||||
|
||||
for (const tableName of tableNames) {
|
||||
tables.push({
|
||||
name: tableName,
|
||||
columns: await sql.getRows(`PRAGMA table_info(${tableName})`)
|
||||
columns: sql.getRows(`PRAGMA table_info(${tableName})`)
|
||||
});
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
async function execute(req) {
|
||||
function execute(req) {
|
||||
const queries = req.body.query.split("\n---");
|
||||
|
||||
try {
|
||||
@@ -27,7 +27,7 @@ async function execute(req) {
|
||||
continue;
|
||||
}
|
||||
|
||||
results.push(await sql.getRows(query));
|
||||
results.push(sql.getRows(query));
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -46,4 +46,4 @@ async function execute(req) {
|
||||
module.exports = {
|
||||
getSchema,
|
||||
execute
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,13 +13,13 @@ const dateUtils = require('../../services/date_utils');
|
||||
const entityConstructor = require('../../entities/entity_constructor');
|
||||
const utils = require('../../services/utils');
|
||||
|
||||
async function testSync() {
|
||||
function testSync() {
|
||||
try {
|
||||
if (!await syncOptions.isSyncSetup()) {
|
||||
if (!syncOptions.isSyncSetup()) {
|
||||
return { success: false, message: "Sync server host is not configured. Please configure sync first." };
|
||||
}
|
||||
|
||||
await syncService.login();
|
||||
syncService.login();
|
||||
|
||||
// login was successful so we'll kick off sync now
|
||||
// this is important in case when sync server has been just initialized
|
||||
@@ -35,40 +35,40 @@ async function testSync() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getStats() {
|
||||
if (!await sqlInit.schemaExists()) {
|
||||
function getStats() {
|
||||
if (!sqlInit.schemaExists()) {
|
||||
// fail silently but prevent errors from not existing options table
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
initialized: await optionService.getOption('initialized') === 'true',
|
||||
initialized: optionService.getOption('initialized') === 'true',
|
||||
stats: syncService.stats
|
||||
};
|
||||
}
|
||||
|
||||
async function checkSync() {
|
||||
function checkSync() {
|
||||
return {
|
||||
entityHashes: await contentHashService.getEntityHashes(),
|
||||
maxSyncId: await sql.getValue('SELECT MAX(id) FROM sync WHERE isSynced = 1')
|
||||
entityHashes: contentHashService.getEntityHashes(),
|
||||
maxSyncId: sql.getValue('SELECT MAX(id) FROM sync WHERE isSynced = 1')
|
||||
};
|
||||
}
|
||||
|
||||
async function syncNow() {
|
||||
function syncNow() {
|
||||
log.info("Received request to trigger sync now.");
|
||||
|
||||
return await syncService.sync();
|
||||
return syncService.sync();
|
||||
}
|
||||
|
||||
async function fillSyncRows() {
|
||||
await syncTableService.fillAllSyncRows();
|
||||
function fillSyncRows() {
|
||||
syncTableService.fillAllSyncRows();
|
||||
|
||||
log.info("Sync rows have been filled.");
|
||||
}
|
||||
|
||||
async function forceFullSync() {
|
||||
await optionService.setOption('lastSyncedPull', 0);
|
||||
await optionService.setOption('lastSyncedPush', 0);
|
||||
function forceFullSync() {
|
||||
optionService.setOption('lastSyncedPull', 0);
|
||||
optionService.setOption('lastSyncedPush', 0);
|
||||
|
||||
log.info("Forcing full sync.");
|
||||
|
||||
@@ -76,38 +76,38 @@ async function forceFullSync() {
|
||||
syncService.sync();
|
||||
}
|
||||
|
||||
async function forceNoteSync(req) {
|
||||
function forceNoteSync(req) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
const now = dateUtils.utcNowDateTime();
|
||||
|
||||
await sql.execute(`UPDATE notes SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
||||
await syncTableService.addNoteSync(noteId);
|
||||
sql.execute(`UPDATE notes SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
||||
syncTableService.addNoteSync(noteId);
|
||||
|
||||
await sql.execute(`UPDATE note_contents SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
||||
await syncTableService.addNoteContentSync(noteId);
|
||||
sql.execute(`UPDATE note_contents SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
||||
syncTableService.addNoteContentSync(noteId);
|
||||
|
||||
for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE noteId = ?", [noteId])) {
|
||||
await sql.execute(`UPDATE branches SET utcDateModified = ? WHERE branchId = ?`, [now, branchId]);
|
||||
for (const branchId of sql.getColumn("SELECT branchId FROM branches WHERE noteId = ?", [noteId])) {
|
||||
sql.execute(`UPDATE branches SET utcDateModified = ? WHERE branchId = ?`, [now, branchId]);
|
||||
|
||||
await syncTableService.addBranchSync(branchId);
|
||||
syncTableService.addBranchSync(branchId);
|
||||
}
|
||||
|
||||
for (const attributeId of await sql.getColumn("SELECT attributeId FROM attributes WHERE noteId = ?", [noteId])) {
|
||||
await sql.execute(`UPDATE attributes SET utcDateModified = ? WHERE attributeId = ?`, [now, attributeId]);
|
||||
for (const attributeId of sql.getColumn("SELECT attributeId FROM attributes WHERE noteId = ?", [noteId])) {
|
||||
sql.execute(`UPDATE attributes SET utcDateModified = ? WHERE attributeId = ?`, [now, attributeId]);
|
||||
|
||||
await syncTableService.addAttributeSync(attributeId);
|
||||
syncTableService.addAttributeSync(attributeId);
|
||||
}
|
||||
|
||||
for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) {
|
||||
await sql.execute(`UPDATE note_revisions SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
||||
await syncTableService.addNoteRevisionSync(noteRevisionId);
|
||||
for (const noteRevisionId of sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) {
|
||||
sql.execute(`UPDATE note_revisions SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
||||
syncTableService.addNoteRevisionSync(noteRevisionId);
|
||||
|
||||
await sql.execute(`UPDATE note_revision_contents SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
||||
await syncTableService.addNoteRevisionContentSync(noteRevisionId);
|
||||
sql.execute(`UPDATE note_revision_contents SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
||||
syncTableService.addNoteRevisionContentSync(noteRevisionId);
|
||||
}
|
||||
|
||||
await syncTableService.addRecentNoteSync(noteId);
|
||||
syncTableService.addRecentNoteSync(noteId);
|
||||
|
||||
log.info("Forcing note sync for " + noteId);
|
||||
|
||||
@@ -115,16 +115,16 @@ async function forceNoteSync(req) {
|
||||
syncService.sync();
|
||||
}
|
||||
|
||||
async function getChanged(req) {
|
||||
function getChanged(req) {
|
||||
const startTime = Date.now();
|
||||
|
||||
const lastSyncId = parseInt(req.query.lastSyncId);
|
||||
|
||||
const syncs = await sql.getRows("SELECT * FROM sync WHERE isSynced = 1 AND id > ? LIMIT 1000", [lastSyncId]);
|
||||
const syncs = sql.getRows("SELECT * FROM sync WHERE isSynced = 1 AND id > ? LIMIT 1000", [lastSyncId]);
|
||||
|
||||
const ret = {
|
||||
syncs: await syncService.getSyncRecords(syncs),
|
||||
maxSyncId: await sql.getValue('SELECT MAX(id) FROM sync WHERE isSynced = 1')
|
||||
syncs: syncService.getSyncRecords(syncs),
|
||||
maxSyncId: sql.getValue('SELECT MAX(id) FROM sync WHERE isSynced = 1')
|
||||
};
|
||||
|
||||
if (ret.syncs.length > 0) {
|
||||
@@ -134,28 +134,28 @@ async function getChanged(req) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function update(req) {
|
||||
function update(req) {
|
||||
const sourceId = req.body.sourceId;
|
||||
const entities = req.body.entities;
|
||||
|
||||
for (const {sync, entity} of entities) {
|
||||
await syncUpdateService.updateEntity(sync, entity, sourceId);
|
||||
syncUpdateService.updateEntity(sync, entity, sourceId);
|
||||
}
|
||||
}
|
||||
|
||||
async function syncFinished() {
|
||||
function syncFinished() {
|
||||
// after first sync finishes, the application is ready to be used
|
||||
// this is meaningless but at the same time harmless (idempotent) for further syncs
|
||||
await sqlInit.dbInitialized();
|
||||
sqlInit.dbInitialized();
|
||||
}
|
||||
|
||||
async function queueSector(req) {
|
||||
function queueSector(req) {
|
||||
const entityName = utils.sanitizeSqlIdentifier(req.params.entityName);
|
||||
const sector = utils.sanitizeSqlIdentifier(req.params.sector);
|
||||
|
||||
const entityPrimaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
|
||||
|
||||
await syncTableService.addEntitySyncsForSector(entityName, entityPrimaryKey, sector);
|
||||
syncTableService.addEntitySyncsForSector(entityName, entityPrimaryKey, sector);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -4,15 +4,15 @@ const sql = require('../../services/sql');
|
||||
const optionService = require('../../services/options');
|
||||
const treeService = require('../../services/tree');
|
||||
|
||||
async function getNotesAndBranchesAndAttributes(noteIds) {
|
||||
function getNotesAndBranchesAndAttributes(noteIds) {
|
||||
noteIds = Array.from(new Set(noteIds));
|
||||
const notes = await treeService.getNotes(noteIds);
|
||||
const notes = treeService.getNotes(noteIds);
|
||||
|
||||
noteIds = notes.map(note => note.noteId);
|
||||
|
||||
// joining child note to filter out not completely synchronised notes which would then cause errors later
|
||||
// cannot do that with parent because of root note's 'none' parent
|
||||
const branches = await sql.getManyRows(`
|
||||
const branches = sql.getManyRows(`
|
||||
SELECT
|
||||
branches.branchId,
|
||||
branches.noteId,
|
||||
@@ -28,7 +28,7 @@ async function getNotesAndBranchesAndAttributes(noteIds) {
|
||||
// sorting in memory is faster
|
||||
branches.sort((a, b) => a.notePosition - b.notePosition < 0 ? -1 : 1);
|
||||
|
||||
const attributes = await sql.getManyRows(`
|
||||
const attributes = sql.getManyRows(`
|
||||
SELECT
|
||||
attributeId,
|
||||
noteId,
|
||||
@@ -50,12 +50,12 @@ async function getNotesAndBranchesAndAttributes(noteIds) {
|
||||
};
|
||||
}
|
||||
|
||||
async function getTree() {
|
||||
const hoistedNoteId = await optionService.getOption('hoistedNoteId');
|
||||
function getTree() {
|
||||
const hoistedNoteId = optionService.getOption('hoistedNoteId');
|
||||
|
||||
// we fetch all branches of notes, even if that particular branch isn't visible
|
||||
// this allows us to e.g. detect and properly display clones
|
||||
const noteIds = await sql.getColumn(`
|
||||
const noteIds = sql.getColumn(`
|
||||
WITH RECURSIVE
|
||||
tree(branchId, noteId, isExpanded) AS (
|
||||
SELECT branchId, noteId, isExpanded FROM branches WHERE noteId = ?
|
||||
@@ -68,11 +68,11 @@ async function getTree() {
|
||||
|
||||
noteIds.push('root');
|
||||
|
||||
return await getNotesAndBranchesAndAttributes(noteIds);
|
||||
return getNotesAndBranchesAndAttributes(noteIds);
|
||||
}
|
||||
|
||||
async function load(req) {
|
||||
return await getNotesAndBranchesAndAttributes(req.body.noteIds);
|
||||
function load(req) {
|
||||
return getNotesAndBranchesAndAttributes(req.body.noteIds);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user