mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	changes in backend script running
This commit is contained in:
		| @@ -32,6 +32,17 @@ class Note extends Entity { | |||||||
|         return this.repository.getEntities("SELECT * FROM attributes WHERE noteId = ? AND isDeleted = 0", [this.noteId]); |         return this.repository.getEntities("SELECT * FROM attributes WHERE noteId = ? AND isDeleted = 0", [this.noteId]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // WARNING: this doesn't take into account the possibility to have multi-valued attributes! | ||||||
|  |     async getAttributeMap() { | ||||||
|  |         const map = {}; | ||||||
|  |  | ||||||
|  |         for (const attr of await this.getAttributes()) { | ||||||
|  |             map[attr.name] = attr.value; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return map; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async getAttribute(name) { |     async getAttribute(name) { | ||||||
|         return this.repository.getEntity("SELECT * FROM attributes WHERE noteId = ? AND name = ?", [this.noteId, name]); |         return this.repository.getEntity("SELECT * FROM attributes WHERE noteId = ? AND name = ?", [this.noteId, name]); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ const express = require('express'); | |||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| const auth = require('../../services/auth'); | const auth = require('../../services/auth'); | ||||||
| const wrap = require('express-promise-wrap').wrap; | const wrap = require('express-promise-wrap').wrap; | ||||||
| const notes = require('../../services/notes'); |  | ||||||
| const attributes = require('../../services/attributes'); | const attributes = require('../../services/attributes'); | ||||||
| const script = require('../../services/script'); | const script = require('../../services/script'); | ||||||
| const Repository = require('../../services/repository'); | const Repository = require('../../services/repository'); | ||||||
| @@ -24,13 +23,15 @@ router.post('/job', auth.checkApiAuth, wrap(async (req, res, next) => { | |||||||
| })); | })); | ||||||
|  |  | ||||||
| router.get('/startup', auth.checkApiAuth, wrap(async (req, res, next) => { | router.get('/startup', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||||
|     const noteIds = await attributes.getNoteIdsWithAttribute("run_on_startup"); |     const noteIds = await attributes.getNoteIdsWithAttribute("run", "frontend_startup"); | ||||||
|     const repository = new Repository(req); |     const repository = new Repository(req); | ||||||
|  |  | ||||||
|     const scripts = []; |     const scripts = []; | ||||||
|  |  | ||||||
|     for (const noteId of noteIds) { |     for (const noteId of noteIds) { | ||||||
|         scripts.push(await getNoteWithSubtreeScript(noteId, repository)); |         const note = await repository.getNote(noteId); | ||||||
|  |  | ||||||
|  |         scripts.push(await script.getNoteScript(note)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     res.send(scripts); |     res.send(scripts); | ||||||
| @@ -38,55 +39,9 @@ router.get('/startup', auth.checkApiAuth, wrap(async (req, res, next) => { | |||||||
|  |  | ||||||
| router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | router.get('/subtree/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||||
|     const repository = new Repository(req); |     const repository = new Repository(req); | ||||||
|     const noteId = req.params.noteId; |     const note = await repository.getNote(req.params.noteId); | ||||||
|  |  | ||||||
|     res.send(await getNoteWithSubtreeScript(noteId, repository)); |     res.send(await script.getNoteScript(note, repository)); | ||||||
| })); | })); | ||||||
|  |  | ||||||
| async function getNoteWithSubtreeScript(noteId, repository) { |  | ||||||
|     const note = await repository.getNote(noteId); |  | ||||||
|  |  | ||||||
|     let noteScript = note.content; |  | ||||||
|  |  | ||||||
|     if (note.isJavaScript()) { |  | ||||||
|         // last \r\n is necessary if script contains line comment on its last line |  | ||||||
|         noteScript = "(async function() {" + noteScript + "\r\n})()"; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const subTreeScripts = await getSubTreeScripts(noteId, [noteId], repository, note.isJavaScript()); |  | ||||||
|  |  | ||||||
|     return subTreeScripts + noteScript; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function getSubTreeScripts(parentId, includedNoteIds, repository, isJavaScript) { |  | ||||||
|     const children = await repository.getEntities(` |  | ||||||
|                                       SELECT notes.*  |  | ||||||
|                                       FROM notes JOIN note_tree USING(noteId) |  | ||||||
|                                       WHERE note_tree.isDeleted = 0 AND notes.isDeleted = 0 |  | ||||||
|                                            AND note_tree.parentNoteId = ? AND (notes.type = 'code' OR notes.type = 'file') |  | ||||||
|                                            AND (notes.mime = 'application/javascript'  |  | ||||||
|                                                 OR notes.mime = 'application/x-javascript'  |  | ||||||
|                                                 OR notes.mime = 'text/html')`, [parentId]); |  | ||||||
|  |  | ||||||
|     let script = "\r\n"; |  | ||||||
|  |  | ||||||
|     for (const child of children) { |  | ||||||
|         if (includedNoteIds.includes(child.noteId)) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         includedNoteIds.push(child.noteId); |  | ||||||
|  |  | ||||||
|         script += await getSubTreeScripts(child.noteId, includedNoteIds, repository); |  | ||||||
|  |  | ||||||
|         if (!isJavaScript && child.isJavaScript()) { |  | ||||||
|             child.content = '<script>' + child.content + '</script>'; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         script += child.content + "\r\n"; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return script; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = router; | module.exports = router; | ||||||
| @@ -11,7 +11,8 @@ const BUILTIN_ATTRIBUTES = [ | |||||||
|     'calendar_root', |     'calendar_root', | ||||||
|     'hide_in_autocomplete', |     'hide_in_autocomplete', | ||||||
|     'exclude_from_export', |     'exclude_from_export', | ||||||
|     'run' |     'run', | ||||||
|  |     'manual_transaction_handling' | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| async function getNoteAttributeMap(noteId) { | async function getNoteAttributeMap(noteId) { | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ async function runNotesWithAttribute(runAttrValue) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| setTimeout(() => runNotesWithAttribute('on_startup'), 10 * 1000); | setTimeout(() => runNotesWithAttribute('backend_startup'), 10 * 1000); | ||||||
|  |  | ||||||
| setInterval(() => runNotesWithAttribute('hourly'), 3600 * 1000); | setInterval(() => runNotesWithAttribute('hourly'), 3600 * 1000); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,11 +6,10 @@ async function executeNote(note) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const ctx = new ScriptContext(); |     const manualTransactionHandling = (await note.getAttributeMap()).manual_transaction_handling !== undefined; | ||||||
|  |     const noteScript = await getNoteScript(note); | ||||||
|  |  | ||||||
|     return await sql.doInTransaction(async () => { |     return await executeJob(noteScript, [], manualTransactionHandling); | ||||||
|         return await (function() { return eval(`const api = this; (async function() {${note.content}\n\r})()`); }.call(ctx)); |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| async function executeScript(dataKey, script, params) { | async function executeScript(dataKey, script, params) { | ||||||
| @@ -84,8 +83,38 @@ function getParams(params) { | |||||||
|     }).join(","); |     }).join(","); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function getNoteScript(note) { | ||||||
|  |     const subTreeScripts = await getSubTreeScripts(note, [note.noteId]); | ||||||
|  |  | ||||||
|  |     // last \r\n is necessary if script contains line comment on its last line | ||||||
|  |     return "async function() {" + subTreeScripts + note.content + "\r\n}"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @param includedNoteIds - if multiple child note scripts reference same dependency (child note), | ||||||
|  |  *                          it will be included just once | ||||||
|  |  */ | ||||||
|  | async function getSubTreeScripts(parent, includedNoteIds) { | ||||||
|  |     let script = "\r\n"; | ||||||
|  |  | ||||||
|  |     for (const child of await parent.getChildren()) { | ||||||
|  |         if (!child.isJavaScript() || includedNoteIds.includes(child.noteId)) { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         includedNoteIds.push(child.noteId); | ||||||
|  |  | ||||||
|  |         script += await getSubTreeScripts(child.noteId, includedNoteIds); | ||||||
|  |  | ||||||
|  |         script += child.content + "\r\n"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return script; | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     executeNote, |     executeNote, | ||||||
|     executeScript, |     executeScript, | ||||||
|     setJob |     setJob, | ||||||
|  |     getNoteScript | ||||||
| }; | }; | ||||||
		Reference in New Issue
	
	Block a user