mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-27 00:06:30 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			248 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html lang="en">
 | |
| <head>
 | |
|     <meta charset="utf-8">
 | |
|     <title>JSDoc: Source: becca/entities/note_revision.js</title>
 | |
| 
 | |
|     <script src="scripts/prettify/prettify.js"> </script>
 | |
|     <script src="scripts/prettify/lang-css.js"> </script>
 | |
|     <!--[if lt IE 9]>
 | |
|       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 | |
|     <![endif]-->
 | |
|     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 | |
|     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 | |
| </head>
 | |
| 
 | |
| <body>
 | |
| 
 | |
| <div id="main">
 | |
| 
 | |
|     <h1 class="page-title">Source: becca/entities/note_revision.js</h1>
 | |
| 
 | |
|     
 | |
| 
 | |
| 
 | |
| 
 | |
|     
 | |
|     <section>
 | |
|         <article>
 | |
|             <pre class="prettyprint source linenums"><code>"use strict";
 | |
| 
 | |
| const protectedSessionService = require('../../services/protected_session');
 | |
| const utils = require('../../services/utils');
 | |
| const sql = require('../../services/sql');
 | |
| const dateUtils = require('../../services/date_utils');
 | |
| const becca = require('../becca');
 | |
| const entityChangesService = require('../../services/entity_changes');
 | |
| const AbstractEntity = require("./abstract_entity");
 | |
| 
 | |
| /**
 | |
|  * NoteRevision represents snapshot of note's title and content at some point in the past.
 | |
|  * It's used for seamless note versioning.
 | |
|  *
 | |
|  * @extends AbstractEntity
 | |
|  */
 | |
| class NoteRevision extends AbstractEntity {
 | |
|     static get entityName() { return "note_revisions"; }
 | |
|     static get primaryKeyName() { return "noteRevisionId"; }
 | |
|     static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; }
 | |
| 
 | |
|     constructor(row) {
 | |
|         super();
 | |
| 
 | |
|         /** @type {string} */
 | |
|         this.noteRevisionId = row.noteRevisionId;
 | |
|         /** @type {string} */
 | |
|         this.noteId = row.noteId;
 | |
|         /** @type {string} */
 | |
|         this.type = row.type;
 | |
|         /** @type {string} */
 | |
|         this.mime = row.mime;
 | |
|         /** @type {boolean} */
 | |
|         this.isProtected = !!row.isProtected;
 | |
|         /** @type {string} */
 | |
|         this.title = row.title;
 | |
|         /** @type {string} */
 | |
|         this.dateLastEdited = row.dateLastEdited;
 | |
|         /** @type {string} */
 | |
|         this.dateCreated = row.dateCreated;
 | |
|         /** @type {string} */
 | |
|         this.utcDateLastEdited = row.utcDateLastEdited;
 | |
|         /** @type {string} */
 | |
|         this.utcDateCreated = row.utcDateCreated;
 | |
|         /** @type {string} */
 | |
|         this.utcDateModified = row.utcDateModified;
 | |
|         /** @type {number} */
 | |
|         this.contentLength = row.contentLength;
 | |
| 
 | |
|         if (this.isProtected) {
 | |
|             if (protectedSessionService.isProtectedSessionAvailable()) {
 | |
|                 this.title = protectedSessionService.decryptString(this.title);
 | |
|             }
 | |
|             else {
 | |
|                 this.title = "[protected]";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     getNote() {
 | |
|         return becca.notes[this.noteId];
 | |
|     }
 | |
| 
 | |
|     /** @returns {boolean} true if the note has string content (not binary) */
 | |
|     isStringNote() {
 | |
|         return utils.isStringNote(this.type, this.mime);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Note revision content has quite special handling - it's not a separate entity, but a lazily loaded
 | |
|      * part of NoteRevision entity with it's own sync. Reason behind this hybrid design is that
 | |
|      * content can be quite large and it's not necessary to load it / fill memory for any note access even
 | |
|      * if we don't need a content, especially for bulk operations like search.
 | |
|      *
 | |
|      * This is the same approach as is used for Note's content.
 | |
|      */
 | |
| 
 | |
|     /** @returns {*} */
 | |
|     getContent(silentNotFoundError = false) {
 | |
|         const res = sql.getRow(`SELECT content FROM note_revision_contents WHERE noteRevisionId = ?`, [this.noteRevisionId]);
 | |
| 
 | |
|         if (!res) {
 | |
|             if (silentNotFoundError) {
 | |
|                 return undefined;
 | |
|             }
 | |
|             else {
 | |
|                 throw new Error("Cannot find note revision content for noteRevisionId=" + this.noteRevisionId);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         let content = res.content;
 | |
| 
 | |
|         if (this.isProtected) {
 | |
|             if (protectedSessionService.isProtectedSessionAvailable()) {
 | |
|                 content = protectedSessionService.decrypt(content);
 | |
|             }
 | |
|             else {
 | |
|                 content = "";
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (this.isStringNote()) {
 | |
|             return content === null
 | |
|                 ? ""
 | |
|                 : content.toString("UTF-8");
 | |
|         }
 | |
|         else {
 | |
|             return content;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     setContent(content, ignoreMissingProtectedSession = false) {
 | |
|         const pojo = {
 | |
|             noteRevisionId: this.noteRevisionId,
 | |
|             content: content,
 | |
|             utcDateModified: dateUtils.utcNowDateTime()
 | |
|         };
 | |
| 
 | |
|         if (this.isProtected) {
 | |
|             if (protectedSessionService.isProtectedSessionAvailable()) {
 | |
|                 pojo.content = protectedSessionService.encrypt(pojo.content);
 | |
|             }
 | |
|             else if (!ignoreMissingProtectedSession) {
 | |
|                 throw new Error(`Cannot update content of noteRevisionId=${this.noteRevisionId} since we're out of protected session.`);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         sql.upsert("note_revision_contents", "noteRevisionId", pojo);
 | |
| 
 | |
|         const hash = utils.hash(this.noteRevisionId + "|" + pojo.content.toString());
 | |
| 
 | |
|         entityChangesService.addEntityChange({
 | |
|             entityName: 'note_revision_contents',
 | |
|             entityId: this.noteRevisionId,
 | |
|             hash: hash,
 | |
|             isErased: false,
 | |
|             utcDateChanged: this.getUtcDateChanged(),
 | |
|             isSynced: true
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /** @returns {{contentLength, dateModified, utcDateModified}} */
 | |
|     getContentMetadata() {
 | |
|         return sql.getRow(`
 | |
|             SELECT 
 | |
|                 LENGTH(content) AS contentLength, 
 | |
|                 dateModified,
 | |
|                 utcDateModified 
 | |
|             FROM note_revision_contents 
 | |
|             WHERE noteRevisionId = ?`, [this.noteRevisionId]);
 | |
|     }
 | |
| 
 | |
|     beforeSaving() {
 | |
|         super.beforeSaving();
 | |
| 
 | |
|         this.utcDateModified = dateUtils.utcNowDateTime();
 | |
|     }
 | |
| 
 | |
|     getPojo() {
 | |
|         return {
 | |
|             noteRevisionId: this.noteRevisionId,
 | |
|             noteId: this.noteId,
 | |
|             type: this.type,
 | |
|             mime: this.mime,
 | |
|             isProtected: this.isProtected,
 | |
|             title: this.title,
 | |
|             dateLastEdited: this.dateLastEdited,
 | |
|             dateCreated: this.dateCreated,
 | |
|             utcDateLastEdited: this.utcDateLastEdited,
 | |
|             utcDateCreated: this.utcDateCreated,
 | |
|             utcDateModified: this.utcDateModified,
 | |
|             content: this.content,
 | |
|             contentLength: this.contentLength
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     getPojoToSave() {
 | |
|         const pojo = this.getPojo();
 | |
|         delete pojo.content; // not getting persisted
 | |
|         delete pojo.contentLength; // not getting persisted
 | |
| 
 | |
|         if (pojo.isProtected) {
 | |
|             if (protectedSessionService.isProtectedSessionAvailable()) {
 | |
|                 pojo.title = protectedSessionService.encrypt(this.title);
 | |
|             }
 | |
|             else {
 | |
|                 // updating protected note outside of protected session means we will keep original ciphertexts
 | |
|                 delete pojo.title;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return pojo;
 | |
|     }
 | |
| }
 | |
| 
 | |
| module.exports = NoteRevision;
 | |
| </code></pre>
 | |
|         </article>
 | |
|     </section>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| </div>
 | |
| 
 | |
| <nav>
 | |
|     <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-sql.html">sql</a></li></ul><h3>Classes</h3><ul><li><a href="AbstractEntity.html">AbstractEntity</a></li><li><a href="Attribute.html">Attribute</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li><li><a href="Branch.html">Branch</a></li><li><a href="EtapiToken.html">EtapiToken</a></li><li><a href="Note.html">Note</a></li><li><a href="NoteRevision.html">NoteRevision</a></li><li><a href="Option.html">Option</a></li><li><a href="RecentNote.html">RecentNote</a></li></ul><h3><a href="global.html">Global</a></h3>
 | |
| </nav>
 | |
| 
 | |
| <br class="clear">
 | |
| 
 | |
| <footer>
 | |
|     Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.10</a>
 | |
| </footer>
 | |
| 
 | |
| <script> prettyPrint(); </script>
 | |
| <script src="scripts/linenumber.js"> </script>
 | |
| </body>
 | |
| </html>
 |