diff --git a/docs/backend_api/ApiToken.html b/docs/backend_api/ApiToken.html index f00a999d2..b768600a5 100644 --- a/docs/backend_api/ApiToken.html +++ b/docs/backend_api/ApiToken.html @@ -282,7 +282,7 @@
diff --git a/docs/backend_api/Attribute.html b/docs/backend_api/Attribute.html index 99be20439..85caec79a 100644 --- a/docs/backend_api/Attribute.html +++ b/docs/backend_api/Attribute.html @@ -724,7 +724,7 @@
diff --git a/docs/backend_api/BackendScriptApi.html b/docs/backend_api/BackendScriptApi.html index 2ce1c467d..3f28eedec 100644 --- a/docs/backend_api/BackendScriptApi.html +++ b/docs/backend_api/BackendScriptApi.html @@ -81,7 +81,7 @@
Source:
@@ -221,7 +221,7 @@
Source:
@@ -331,7 +331,70 @@
Source:
+ + + + + + + + + + + + + + + + +

refreshTree

+ + + + +
+ Trigger tree refresh in all connected clients. This is required when some tree change happens in +the backend. +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
@@ -441,7 +504,7 @@
Source:
@@ -695,7 +758,293 @@
Source:
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ object contains newly created entities note and branch +
+ + + +
+
+ Type +
+
+ +Promise.<{note: Note, branch: Branch}> + + +
+
+ + + + + + + + + + + + + +

createNoteAndRefresh(parentNoteId, title, contentopt, extraOptionsopt) → {Promise.<{note: Note, branch: Branch}>}

+ + + + + + +
+ Creates new note according to given params and force all connected clients to refresh their tree. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
parentNoteId + + +string + + + + + + + + + + + + create new note under this parent
title + + +string + + + + + + + + + + + +
content + + +string + + + + + + <optional>
+ + + + + +
+ + "" + +
extraOptions + + +CreateNoteExtraOptions + + + + + + <optional>
+ + + + + +
+ + {} + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
@@ -875,7 +1224,7 @@
Source:
@@ -1074,7 +1423,7 @@
Source:
@@ -1126,6 +1475,113 @@ +

getAppInfo() → {Object|*}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ - object representing basic info about running Trilium version +
+ + + +
+
+ Type +
+
+ +Object +| + +* + + +
+
+ + + + + + + + + + + + +

getAttribute(attributeId) → {Promise.<(Attribute|null)>}

@@ -1223,7 +1679,7 @@
Source:
@@ -1372,7 +1828,7 @@
Source:
@@ -1432,7 +1888,7 @@
- Returns day note for given date (YYYY-MM-DD format). If such note doesn't exist, it is created. + Returns day note for given date. If such note doesn't exist, it is created.
@@ -1484,7 +1940,7 @@ - + in YYYY-MM-DD format @@ -1525,7 +1981,7 @@
Source:
@@ -1697,7 +2153,7 @@
Source:
@@ -1873,7 +2329,7 @@
Source:
@@ -2022,7 +2478,7 @@
Source:
@@ -2127,7 +2583,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2182,6 +2638,159 @@ if some action needs to happen on only one specific instance. +

getMonthNote(date) → {Promise.<(Note|null)>}

+ + + + + + +
+ Returns month note for given date. If such note doesn't exist, it is created. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
date + + +string + + + + in YYYY-MM format
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<(Note|null)> + + +
+
+ + + + + + + + + + + + +

getNote(noteId) → {Promise.<(Note|null)>}

@@ -2279,7 +2888,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2475,7 +3084,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2671,7 +3280,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2775,7 +3384,336 @@ if some action needs to happen on only one specific instance.
Source:
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<(Note|null)> + + +
+
+ + + + + + + + + + + + + +

getWeekNote(date, options) → {Promise.<(Note|null)>}

+ + + + + + +
+ Returns note for the first date of the week of the given date. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
date + + +string + + + + in YYYY-MM-DD format
options + + +object + + + + "startOfTheWeek" - either "monday" (default) or "sunday"
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<(Note|null)> + + +
+
+ + + + + + + + + + + + + +

getYearNote(year) → {Promise.<(Note|null)>}

+ + + + + + +
+ Returns year note for given year. If such note doesn't exist, it is created. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
year + + +string + + + + in YYYY format
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
@@ -2923,7 +3861,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2953,111 +3891,6 @@ if some action needs to happen on only one specific instance. - - - - -

refreshTree() → {Promise.<void>}

- - - - - - -
- Trigger tree refresh in all connected clients. This is required when some tree change happens in -the backend. -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Promise.<void> - - -
-
- - - - - - - - - @@ -3240,7 +4073,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
Source:
@@ -3371,7 +4204,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
Source:
@@ -3585,7 +4418,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
Source:
@@ -3742,7 +4575,7 @@ transactional by default.
Source:
@@ -3808,7 +4641,7 @@ transactional by default.
diff --git a/docs/backend_api/Branch.html b/docs/backend_api/Branch.html index 5424adf8b..cad699e14 100644 --- a/docs/backend_api/Branch.html +++ b/docs/backend_api/Branch.html @@ -505,7 +505,7 @@ Each note can have multiple (at least one) branches, meaning it can be placed in
diff --git a/docs/backend_api/Entity.html b/docs/backend_api/Entity.html index 4259b6dfd..859b391e6 100644 --- a/docs/backend_api/Entity.html +++ b/docs/backend_api/Entity.html @@ -210,7 +210,7 @@
diff --git a/docs/backend_api/Link.html b/docs/backend_api/Link.html index 906071993..e9abe5627 100644 --- a/docs/backend_api/Link.html +++ b/docs/backend_api/Link.html @@ -352,7 +352,7 @@ this is different concept than attribute/relation.
diff --git a/docs/backend_api/Note.html b/docs/backend_api/Note.html index bf222ab85..9f35c02f9 100644 --- a/docs/backend_api/Note.html +++ b/docs/backend_api/Note.html @@ -224,29 +224,6 @@ - - - content - - - - - -string - - - - - - - - - - note content - e.g. HTML text for text notes, file payload for files - - - - isProtected @@ -558,7 +535,7 @@
Source:
@@ -723,7 +700,7 @@
Source:
@@ -899,7 +876,7 @@
Source:
@@ -1003,7 +980,7 @@
Source:
@@ -1103,7 +1080,7 @@
Source:
@@ -1207,7 +1184,7 @@
Source:
@@ -1263,6 +1240,106 @@ +

(async) getContent() → {Promise.<*>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<*> + + +
+
+ + + + + + + + + + + + +

(async) getDescendantNoteIds() → {Promise.<Array.<string>>}

@@ -1311,7 +1388,7 @@
Source:
@@ -1542,7 +1619,7 @@
Source:
@@ -1738,7 +1815,7 @@
Source:
@@ -1934,7 +2011,7 @@
Source:
@@ -1986,6 +2063,106 @@ +

(async) getJsonContent() → {Promise.<*>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<*> + + +
+
+ + + + + + + + + + + + +

(async) getLabel(name) → {Promise.<Attribute>}

@@ -2083,7 +2260,7 @@
Source:
@@ -2248,7 +2425,7 @@
Source:
@@ -2413,7 +2590,7 @@
Source:
@@ -2566,7 +2743,7 @@
Source:
@@ -2674,7 +2851,7 @@
Source:
@@ -2778,7 +2955,7 @@
Source:
@@ -2830,6 +3007,106 @@ +

(async) getNoteContent() → {Promise.<NoteContent>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<NoteContent> + + +
+
+ + + + + + + + + + + + +

(async) getOwnedAttributes() → {Promise.<Array.<Attribute>>}

@@ -2878,7 +3155,7 @@
Source:
@@ -2982,7 +3259,7 @@
Source:
@@ -3135,7 +3412,7 @@
Source:
@@ -3300,7 +3577,7 @@
Source:
@@ -3465,7 +3742,7 @@
Source:
@@ -3618,7 +3895,7 @@
Source:
@@ -3774,7 +4051,7 @@
Source:
@@ -3882,7 +4159,7 @@
Source:
@@ -3982,7 +4259,7 @@
Source:
@@ -4090,7 +4367,7 @@
Source:
@@ -4190,7 +4467,7 @@
Source:
@@ -4366,7 +4643,7 @@
Source:
@@ -4470,7 +4747,7 @@
Source:
@@ -4623,7 +4900,7 @@
Source:
@@ -4776,7 +5053,7 @@
Source:
@@ -4885,7 +5162,7 @@ Cache is note instance scoped.
Source:
@@ -4967,7 +5244,7 @@ Cache is note instance scoped.
Source:
@@ -5071,7 +5348,7 @@ Cache is note instance scoped.
Source:
@@ -5175,7 +5452,7 @@ Cache is note instance scoped.
Source:
@@ -5279,7 +5556,7 @@ Cache is note instance scoped.
Source:
@@ -5335,6 +5612,110 @@ Cache is note instance scoped. +

isStringNote() → {boolean}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if the note has string content (not binary) +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + +

(async) loadAttributesToCache() → {Promise.<void>}

@@ -5383,7 +5764,7 @@ Cache is note instance scoped.
Source:
@@ -5610,7 +5991,7 @@ Cache is note instance scoped.
Source:
@@ -5806,7 +6187,7 @@ Cache is note instance scoped.
Source:
@@ -6002,7 +6383,7 @@ Cache is note instance scoped.
Source:
@@ -6229,7 +6610,7 @@ Cache is note instance scoped.
Source:
@@ -6281,6 +6662,206 @@ Cache is note instance scoped. +

(async) setContent() → {Promise}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise + + +
+
+ + + + + + + + + + + + + +

(async) setJsonContent() → {Promise}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise + + +
+
+ + + + + + + + + + + + +

(async) setLabel(name, valueopt) → {Promise.<void>}

@@ -6425,7 +7006,7 @@ Cache is note instance scoped.
Source:
@@ -6621,7 +7202,7 @@ Cache is note instance scoped.
Source:
@@ -6879,7 +7460,7 @@ Cache is note instance scoped.
Source:
@@ -7106,7 +7687,7 @@ Cache is note instance scoped.
Source:
@@ -7333,7 +7914,7 @@ Cache is note instance scoped.
Source:
@@ -7395,7 +7976,7 @@ Cache is note instance scoped.
diff --git a/docs/backend_api/NoteContent.html b/docs/backend_api/NoteContent.html new file mode 100644 index 000000000..96ccf9d4a --- /dev/null +++ b/docs/backend_api/NoteContent.html @@ -0,0 +1,494 @@ + + + + + JSDoc: Class: NoteContent + + + + + + + + + + +
+ +

Class: NoteContent

+ + + + + + +
+ +
+ +

NoteContent(row)

+ +
This represents a Note which is a central object in the Trilium Notes project.
+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new NoteContent(row)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
row + + object containing database row from "note_contents" table
+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
noteContentId + + +string + + + + primary key
noteId + + +string + + + + reference to owning note
isProtected + + +boolean + + + + true if note content is protected
content + + +blob + + + + note content - e.g. HTML text for text notes, file payload for files
dateCreated + + +string + + + +
dateModified + + +string + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(async) getNote() → {Promise.<Note>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<Note> + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/backend_api/NoteRevision.html b/docs/backend_api/NoteRevision.html index 79796df3b..6de063504 100644 --- a/docs/backend_api/NoteRevision.html +++ b/docs/backend_api/NoteRevision.html @@ -397,7 +397,7 @@
diff --git a/docs/backend_api/Option.html b/docs/backend_api/Option.html index da6d88ae5..ed172ed86 100644 --- a/docs/backend_api/Option.html +++ b/docs/backend_api/Option.html @@ -305,7 +305,7 @@
diff --git a/docs/backend_api/RecentNote.html b/docs/backend_api/RecentNote.html index e41c49e69..000826df3 100644 --- a/docs/backend_api/RecentNote.html +++ b/docs/backend_api/RecentNote.html @@ -282,7 +282,7 @@
diff --git a/docs/backend_api/entities_api_token.js.html b/docs/backend_api/entities_api_token.js.html index 160f0ebdc..20ce1ff98 100644 --- a/docs/backend_api/entities_api_token.js.html +++ b/docs/backend_api/entities_api_token.js.html @@ -69,7 +69,7 @@ module.exports = ApiToken;
diff --git a/docs/backend_api/entities_attribute.js.html b/docs/backend_api/entities_attribute.js.html index 646b5a067..b65bf2f81 100644 --- a/docs/backend_api/entities_attribute.js.html +++ b/docs/backend_api/entities_attribute.js.html @@ -150,7 +150,7 @@ module.exports = Attribute;
diff --git a/docs/backend_api/entities_branch.js.html b/docs/backend_api/entities_branch.js.html index 1f0ab47fb..e0bcf59dc 100644 --- a/docs/backend_api/entities_branch.js.html +++ b/docs/backend_api/entities_branch.js.html @@ -104,7 +104,7 @@ module.exports = Branch;
diff --git a/docs/backend_api/entities_entity.js.html b/docs/backend_api/entities_entity.js.html index 56ddd0a17..23564c26d 100644 --- a/docs/backend_api/entities_entity.js.html +++ b/docs/backend_api/entities_entity.js.html @@ -36,7 +36,10 @@ class Entity { */ constructor(row = {}) { for (const key in row) { - this[key] = row[key]; + // ! is used when joint-fetching notes and note_contents objects for performance + if (!key.startsWith('!')) { + this[key] = row[key]; + } } if ('isDeleted' in this) { @@ -87,7 +90,7 @@ module.exports = Entity;
diff --git a/docs/backend_api/entities_link.js.html b/docs/backend_api/entities_link.js.html index f4c05cbeb..3a3a3d089 100644 --- a/docs/backend_api/entities_link.js.html +++ b/docs/backend_api/entities_link.js.html @@ -86,7 +86,7 @@ module.exports = Link;
diff --git a/docs/backend_api/entities_note.js.html b/docs/backend_api/entities_note.js.html index 07e582d58..c0fe2f8cf 100644 --- a/docs/backend_api/entities_note.js.html +++ b/docs/backend_api/entities_note.js.html @@ -30,6 +30,7 @@ const Entity = require('./entity'); const Attribute = require('./attribute'); +const NoteContent = require('./note_content'); const protectedSessionService = require('../services/protected_session'); const repository = require('../services/repository'); const sql = require('../services/sql'); @@ -47,7 +48,6 @@ const RELATION_DEFINITION = 'relation-definition'; * @property {string} type - one of "text", "code", "file" or "render" * @property {string} mime - MIME type, e.g. "text/html" * @property {string} title - note title - * @property {string} content - note content - e.g. HTML text for text notes, file payload for files * @property {boolean} isProtected - true if note is protected * @property {boolean} isDeleted - true if note is deleted * @property {string} dateCreated @@ -58,7 +58,7 @@ const RELATION_DEFINITION = 'relation-definition'; class Note extends Entity { static get entityName() { return "notes"; } static get primaryKeyName() { return "noteId"; } - static get hashedProperties() { return ["noteId", "title", "content", "type", "isProtected", "isDeleted"]; } + static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; } /** * @param row - object containing database row from "notes" table @@ -75,19 +75,64 @@ class Note extends Entity { if (this.isProtected && this.noteId) { this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable(); - protectedSessionService.decryptNote(this); + if (this.isContentAvailable) { + protectedSessionService.decryptNote(this); + } + else { + // saving ciphertexts in case we do want to update protected note outside of protected session + // (which is allowed) + this.titleCipherText = this.title; + this.title = "[protected]"; + } } - - this.setContent(this.content); } - setContent(content) { - this.content = content; + /** @returns {Promise<NoteContent>} */ + async getNoteContent() { + if (!this.noteContent) { + this.noteContent = await repository.getEntity(`SELECT * FROM note_contents WHERE noteId = ?`, [this.noteId]); - try { - this.jsonContent = JSON.parse(this.content); + if (!this.noteContent) { + throw new Error("Note content not found for noteId=" + this.noteId); + } + + if (this.isStringNote()) { + this.noteContent.content = this.noteContent.content.toString("UTF-8"); + } } - catch(e) {} + + return this.noteContent; + } + + /** @returns {Promise<*>} */ + async getContent() { + const noteContent = await this.getNoteContent(); + + return noteContent.content; + } + + /** @returns {Promise<*>} */ + async getJsonContent() { + const content = await this.getContent(); + + return JSON.parse(content); + } + + /** @returns {Promise} */ + async setContent(content) { + if (!this.noteContent) { + // make sure it is loaded + await this.getNoteContent(); + } + + this.noteContent.content = content; + + await this.noteContent.save(); + } + + /** @returns {Promise} */ + async setJsonContent(content) { + await this.setContent(JSON.stringify(content)); } /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ @@ -113,6 +158,11 @@ class Note extends Entity { return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html"; } + /** @returns {boolean} true if the note has string content (not binary) */ + isStringNote() { + return ["text", "code", "relation-map", "search"].includes(this.type) || this.mime.startsWith('text/'); + } + /** @returns {string} JS script environment - either "frontend" or "backend" */ getScriptEnv() { if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith('env=frontend'))) { @@ -629,13 +679,6 @@ class Note extends Entity { } beforeSaving() { - if (this.isJson() && this.jsonContent) { - this.content = JSON.stringify(this.jsonContent, null, '\t'); - } - - // we do this here because encryption needs the note ID for the IV - this.generateIdIfNecessary(); - if (!this.isDeleted) { this.isDeleted = false; } @@ -654,12 +697,18 @@ class Note extends Entity { // cannot be static! updatePojo(pojo) { if (pojo.isProtected) { - protectedSessionService.encryptNote(pojo); + if (this.isContentAvailable) { + protectedSessionService.encryptNote(pojo); + } + else { + // updating protected note outside of protected session means we will keep original ciphertexts + pojo.title = pojo.titleCipherText; + } } - delete pojo.jsonContent; delete pojo.isContentAvailable; delete pojo.__attributeCache; + delete pojo.titleCipherText; } } @@ -673,7 +722,7 @@ module.exports = Note;
diff --git a/docs/backend_api/entities_note_content.js.html b/docs/backend_api/entities_note_content.js.html new file mode 100644 index 000000000..4aa2ac78d --- /dev/null +++ b/docs/backend_api/entities_note_content.js.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: entities/note_content.js + + + + + + + + + + +
+ +

Source: entities/note_content.js

+ + + + + + +
+
+
"use strict";
+
+const Entity = require('./entity');
+const protectedSessionService = require('../services/protected_session');
+const repository = require('../services/repository');
+const dateUtils = require('../services/date_utils');
+
+/**
+ * This represents a Note which is a central object in the Trilium Notes project.
+ *
+ * @property {string} noteContentId - primary key
+ * @property {string} noteId - reference to owning note
+ * @property {boolean} isProtected - true if note content is protected
+ * @property {blob} content - note content - e.g. HTML text for text notes, file payload for files
+ * @property {string} dateCreated
+ * @property {string} dateModified
+ *
+ * @extends Entity
+ */
+class NoteContent extends Entity {
+    static get entityName() {
+        return "note_contents";
+    }
+
+    static get primaryKeyName() {
+        return "noteContentId";
+    }
+
+    static get hashedProperties() {
+        return ["noteContentId", "noteId", "isProtected", "content"];
+    }
+
+    /**
+     * @param row - object containing database row from "note_contents" table
+     */
+    constructor(row) {
+        super(row);
+
+        this.isProtected = !!this.isProtected;
+        /* true if content (meaning any kind of potentially encrypted content) is either not encrypted
+         * or encrypted, but with available protected session (so effectively decrypted) */
+        this.isContentAvailable = true;
+
+        // check if there's noteContentId, otherwise this is a new entity which wasn't encrypted yet
+        if (this.isProtected && this.noteContentId) {
+            this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
+
+            if (this.isContentAvailable) {
+                protectedSessionService.decryptNoteContent(this);
+            }
+            else {
+                // saving ciphertexts in case we do want to update protected note outside of protected session
+                // (which is allowed)
+                this.contentCipherText = this.content;
+                this.content = "";
+            }
+        }
+    }
+
+    /**
+     * @returns {Promise<Note>}
+     */
+    async getNote() {
+        return await repository.getNote(this.noteId);
+    }
+
+    beforeSaving() {
+        if (!this.dateCreated) {
+            this.dateCreated = dateUtils.nowDate();
+        }
+
+        super.beforeSaving();
+
+        if (this.isChanged) {
+            this.dateModified = dateUtils.nowDate();
+        }
+    }
+
+    // cannot be static!
+    updatePojo(pojo) {
+        if (pojo.isProtected) {
+            if (this.isContentAvailable) {
+                protectedSessionService.encryptNoteContent(pojo);
+            }
+            else {
+                // updating protected note outside of protected session means we will keep original ciphertext
+                pojo.content = pojo.contentCipherText;
+            }
+        }
+
+        delete pojo.isContentAvailable;
+        delete pojo.contentCipherText;
+    }
+}
+
+module.exports = NoteContent;
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/backend_api/entities_note_revision.js.html b/docs/backend_api/entities_note_revision.js.html index 481d94f06..70c4f281c 100644 --- a/docs/backend_api/entities_note_revision.js.html +++ b/docs/backend_api/entities_note_revision.js.html @@ -85,7 +85,7 @@ module.exports = NoteRevision;
diff --git a/docs/backend_api/entities_option.js.html b/docs/backend_api/entities_option.js.html index 213852a21..2fa04309b 100644 --- a/docs/backend_api/entities_option.js.html +++ b/docs/backend_api/entities_option.js.html @@ -72,7 +72,7 @@ module.exports = Option;
diff --git a/docs/backend_api/entities_recent_note.js.html b/docs/backend_api/entities_recent_note.js.html index 9a0fc684d..f32e3233b 100644 --- a/docs/backend_api/entities_recent_note.js.html +++ b/docs/backend_api/entities_recent_note.js.html @@ -69,7 +69,7 @@ module.exports = RecentNote;
diff --git a/docs/backend_api/global.html b/docs/backend_api/global.html index 96dbf091e..099e4d910 100644 --- a/docs/backend_api/global.html +++ b/docs/backend_api/global.html @@ -272,7 +272,7 @@
Source:
@@ -558,7 +558,7 @@
Source:
@@ -588,7 +588,7 @@
diff --git a/docs/backend_api/index.html b/docs/backend_api/index.html index 263759f06..49f2ec3e4 100644 --- a/docs/backend_api/index.html +++ b/docs/backend_api/index.html @@ -50,7 +50,7 @@
diff --git a/docs/backend_api/services_backend_script_api.js.html b/docs/backend_api/services_backend_script_api.js.html index 5cc8cc393..3f03e361f 100644 --- a/docs/backend_api/services_backend_script_api.js.html +++ b/docs/backend_api/services_backend_script_api.js.html @@ -39,6 +39,7 @@ const repository = require('./repository'); const axios = require('axios'); const cloningService = require('./cloning'); const messagingService = require('./messaging'); +const appInfo = require('./app_info'); /** * This is the main backend API interface for scripts. It's published in the local "api" object. @@ -46,13 +47,17 @@ const messagingService = require('./messaging'); * @constructor * @hideconstructor */ -function BackendScriptApi(startNote, currentNote, originEntity) { +function BackendScriptApi(currentNote, apiParams) { /** @property {Note} note where script started executing */ - this.startNote = startNote; + this.startNote = apiParams.startNote; /** @property {Note} note where script is currently executing */ this.currentNote = currentNote; /** @property {Entity} entity whose event triggered this executions */ - this.originEntity = originEntity; + this.originEntity = apiParams.originEntity; + + for (const key in apiParams) { + this[key] = apiParams[key]; + } this.axios = axios; @@ -196,6 +201,23 @@ function BackendScriptApi(startNote, currentNote, originEntity) { */ this.createNote = noteService.createNote; + /** + * Creates new note according to given params and force all connected clients to refresh their tree. + * + * @method + * + * @param {string} parentNoteId - create new note under this parent + * @param {string} title + * @param {string} [content=""] + * @param {CreateNoteExtraOptions} [extraOptions={}] + * @returns {Promise<{note: Note, branch: Branch}>} object contains newly created entities note and branch + */ + this.createNoteAndRefresh = async function(parentNoteId, title, content, extraOptions) { + await noteService.createNote(parentNoteId, title, content, extraOptions); + + messagingService.refreshTree(); + }; + /** * Log given message to trilium logs. * @@ -212,14 +234,42 @@ function BackendScriptApi(startNote, currentNote, originEntity) { this.getRootCalendarNote = dateNoteService.getRootCalendarNote; /** - * Returns day note for given date (YYYY-MM-DD format). If such note doesn't exist, it is created. + * Returns day note for given date. If such note doesn't exist, it is created. * * @method - * @param {string} date + * @param {string} date in YYYY-MM-DD format * @returns {Promise<Note|null>} */ this.getDateNote = dateNoteService.getDateNote; + /** + * Returns note for the first date of the week of the given date. + * + * @method + * @param {string} date in YYYY-MM-DD format + * @param {object} options - "startOfTheWeek" - either "monday" (default) or "sunday" + * @returns {Promise<Note|null>} + */ + this.getWeekNote = dateNoteService.getWeekNote; + + /** + * Returns month note for given date. If such note doesn't exist, it is created. + * + * @method + * @param {string} date in YYYY-MM format + * @returns {Promise<Note|null>} + */ + this.getMonthNote = dateNoteService.getMonthNote; + + /** + * Returns year note for given year. If such note doesn't exist, it is created. + * + * @method + * @param {string} year in YYYY format + * @returns {Promise<Note|null>} + */ + this.getYearNote = dateNoteService.getYearNote; + /** * @method * @param {string} parentNoteId - this note's child notes will be sorted @@ -261,7 +311,12 @@ function BackendScriptApi(startNote, currentNote, originEntity) { * * @returns {Promise<void>} */ - this.refreshTree = () => messagingService.sendMessageToAllClients({ type: 'refresh-tree' }); + this.refreshTree = messagingService.refreshTree; + + /** + * @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version + */ + this.getAppInfo = () => appInfo } module.exports = BackendScriptApi; @@ -274,7 +329,7 @@ module.exports = BackendScriptApi;
diff --git a/docs/frontend_api/FrontendScriptApi.html b/docs/frontend_api/FrontendScriptApi.html index 1cbea7dd9..2782ec98d 100644 --- a/docs/frontend_api/FrontendScriptApi.html +++ b/docs/frontend_api/FrontendScriptApi.html @@ -81,7 +81,7 @@
Source:
@@ -221,7 +221,7 @@
Source:
@@ -334,7 +334,7 @@
Source:
@@ -444,7 +444,7 @@
Source:
@@ -573,7 +573,7 @@
Source:
@@ -726,7 +726,7 @@
Source:
@@ -879,7 +879,7 @@
Source:
@@ -1057,7 +1057,7 @@
Source:
@@ -1188,7 +1188,7 @@
Source:
@@ -1292,7 +1292,7 @@
Source:
@@ -1396,7 +1396,7 @@
Source:
@@ -1500,7 +1500,7 @@
Source:
@@ -1609,7 +1609,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -1808,7 +1808,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -1860,6 +1860,117 @@ otherwise (by e.g. createNoteLink()) +

isNoteStillLoaded() → {boolean}

+ + + + + + +
+ This method checks whether user navigated away from the note from which the scripts has been started. +This is necessary because script execution is async and by the time it is finished, the user might have +already navigated away from this page - the end result would be that script might return data for the wrong +note. +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ returns true if the original note is still loaded, false if user switched to another +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + +

onNoteChange(func)

@@ -1957,7 +2068,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -2088,7 +2199,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -2140,6 +2251,88 @@ otherwise (by e.g. createNoteLink()) + + + + +

protectCurrentNote()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + @@ -2196,7 +2389,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -2373,7 +2566,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -2526,7 +2719,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -2657,7 +2850,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -2792,7 +2985,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -2927,7 +3120,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
diff --git a/docs/frontend_api/NoteFull.html b/docs/frontend_api/NoteFull.html index 52dd3a82e..a347542f1 100644 --- a/docs/frontend_api/NoteFull.html +++ b/docs/frontend_api/NoteFull.html @@ -141,7 +141,123 @@ -

content

+

dateCreated

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

dateModified

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

noteContent

@@ -198,64 +314,6 @@ - -

jsonContent

- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - diff --git a/docs/frontend_api/entities_attribute.js.html b/docs/frontend_api/entities_attribute.js.html index bdba252b1..1a6ed291d 100644 --- a/docs/frontend_api/entities_attribute.js.html +++ b/docs/frontend_api/entities_attribute.js.html @@ -59,7 +59,9 @@ get toString() { return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name})`; } -} +} + +export default Attribute; diff --git a/docs/frontend_api/entities_note_full.js.html b/docs/frontend_api/entities_note_full.js.html index e24275b4a..deeeab5f2 100644 --- a/docs/frontend_api/entities_note_full.js.html +++ b/docs/frontend_api/entities_note_full.js.html @@ -36,15 +36,13 @@ class NoteFull extends NoteShort { super(treeCache, row); /** @param {string} */ - this.content = row.content; + this.noteContent = row.noteContent; - if (this.content !== "" && this.isJson()) { - try { - /** @param {object} */ - this.jsonContent = JSON.parse(this.content); - } - catch(e) {} - } + /** @param {string} */ + this.dateCreated = row.dateCreated; + + /** @param {string} */ + this.dateModified = row.dateModified; } } diff --git a/docs/frontend_api/global.html b/docs/frontend_api/global.html index a73e78e1b..643d96edf 100644 --- a/docs/frontend_api/global.html +++ b/docs/frontend_api/global.html @@ -303,7 +303,7 @@
Source:
diff --git a/docs/frontend_api/services_frontend_script_api.js.html b/docs/frontend_api/services_frontend_script_api.js.html index 9ce981b93..23aa73166 100644 --- a/docs/frontend_api/services_frontend_script_api.js.html +++ b/docs/frontend_api/services_frontend_script_api.js.html @@ -35,6 +35,7 @@ import treeCache from './tree_cache.js'; import noteDetailService from './note_detail.js'; import noteTypeService from './note_type.js'; import noteTooltipService from './note_tooltip.js'; +import protectedSessionService from'./protected_session.js'; /** * This is the main frontend API interface for scripts. It's published in the local "api" object. @@ -70,7 +71,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { this.activateNewNote = async notePath => { await treeService.reload(); - await treeService.activateNote(notePath, true); + await treeService.activateNote(notePath, noteDetailService.focusAndSelectTitle); }; /** @@ -231,6 +232,19 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { */ this.getCurrentNoteContent = noteDetailService.getCurrentNoteContent; + /** + * This method checks whether user navigated away from the note from which the scripts has been started. + * This is necessary because script execution is async and by the time it is finished, the user might have + * already navigated away from this page - the end result would be that script might return data for the wrong + * note. + * + * @method + * @return {boolean} returns true if the original note is still loaded, false if user switched to another + */ + this.isNoteStillLoaded = () => { + return this.originEntity.noteId === noteDetailService.getCurrentNoteId(); + }; + /** * @method * @param {function} func - callback called on note change as user is typing (not necessarily tied to save event) @@ -259,7 +273,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { * @method * @param {object} $el - jquery object on which to setup the tooltip */ - this.setupElementTooltip = noteTooltipService.setupElementTooltip + this.setupElementTooltip = noteTooltipService.setupElementTooltip; + + /** + * @method + */ + this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer; } export default FrontendScriptApi;