mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
backend scripts should not be async because of transaction management
This commit is contained in:
parent
a65eda5e4a
commit
04f249e800
50
package-lock.json
generated
50
package-lock.json
generated
@ -11,9 +11,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
|
||||
"integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
|
||||
"version": "7.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz",
|
||||
"integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/runtime": {
|
||||
@ -1953,12 +1953,12 @@
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"catharsis": {
|
||||
"version": "0.8.11",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
|
||||
"integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
|
||||
"integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.14"
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
@ -2957,9 +2957,9 @@
|
||||
}
|
||||
},
|
||||
"electron": {
|
||||
"version": "13.0.0-beta.24",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-13.0.0-beta.24.tgz",
|
||||
"integrity": "sha512-2zgmhrjdkWrKsBIepF1XkRCn4ODFxd4lgB58BLv3E66yiQJC0ugOnHoqeZcsskQ7bBMGGQwGAzB5nwOJ/83BOg==",
|
||||
"version": "13.0.0-beta.26",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-13.0.0-beta.26.tgz",
|
||||
"integrity": "sha512-glDAQjSzV26JvmB9pbdd1dLkjqUvBv9X0B8FrRvIK0BAhEmMzzZ3gKD6VPsxg2omDYMI35oThQ+92D4RxRcb+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@electron/get": "^1.0.1",
|
||||
@ -2968,9 +2968,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.14.44",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.44.tgz",
|
||||
"integrity": "sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==",
|
||||
"version": "14.14.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.45.tgz",
|
||||
"integrity": "sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -5250,25 +5250,25 @@
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"jsdoc": {
|
||||
"version": "3.6.6",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz",
|
||||
"integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==",
|
||||
"version": "3.6.7",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz",
|
||||
"integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/parser": "^7.9.4",
|
||||
"bluebird": "^3.7.2",
|
||||
"catharsis": "^0.8.11",
|
||||
"catharsis": "^0.9.0",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"js2xmlparser": "^4.0.1",
|
||||
"klaw": "^3.0.0",
|
||||
"markdown-it": "^10.0.0",
|
||||
"markdown-it-anchor": "^5.2.7",
|
||||
"marked": "^0.8.2",
|
||||
"marked": "^2.0.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"requizzle": "^0.2.3",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"taffydb": "2.6.2",
|
||||
"underscore": "~1.10.2"
|
||||
"underscore": "~1.13.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": {
|
||||
@ -5716,9 +5716,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
|
||||
"integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz",
|
||||
"integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA==",
|
||||
"dev": true
|
||||
},
|
||||
"matcher": {
|
||||
@ -8026,9 +8026,9 @@
|
||||
}
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
|
||||
"integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==",
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
|
||||
"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
|
||||
"dev": true
|
||||
},
|
||||
"unescape": {
|
||||
|
@ -80,13 +80,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "7.0.3",
|
||||
"electron": "13.0.0-beta.24",
|
||||
"electron": "13.0.0-beta.26",
|
||||
"electron-builder": "22.11.3",
|
||||
"electron-packager": "15.2.0",
|
||||
"electron-rebuild": "2.3.5",
|
||||
"esm": "3.2.25",
|
||||
"jasmine": "3.7.0",
|
||||
"jsdoc": "3.6.6",
|
||||
"jsdoc": "3.6.7",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"rcedit": "3.0.0",
|
||||
"webpack": "5.37.0",
|
||||
|
@ -5,11 +5,11 @@ const attributeService = require('../../services/attributes');
|
||||
const becca = require('../../services/becca/becca');
|
||||
const syncService = require('../../services/sync');
|
||||
|
||||
async function exec(req) {
|
||||
function exec(req) {
|
||||
try {
|
||||
const {body} = req;
|
||||
|
||||
const result = await scriptService.executeScript(
|
||||
const result = scriptService.executeScript(
|
||||
body.script,
|
||||
body.params,
|
||||
body.startNoteId,
|
||||
@ -29,10 +29,10 @@ async function exec(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function run(req) {
|
||||
function run(req) {
|
||||
const note = becca.getNote(req.params.noteId);
|
||||
|
||||
const result = await scriptService.executeNote(note, { originEntity: note });
|
||||
const result = scriptService.executeNote(note, { originEntity: note });
|
||||
|
||||
return { executionResult: result };
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ async function searchAndExecute(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function searchFromRelation(note, relationName) {
|
||||
function searchFromRelation(note, relationName) {
|
||||
const scriptNote = note.getRelationTarget(relationName);
|
||||
|
||||
if (!scriptNote) {
|
||||
@ -188,7 +188,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.`);
|
||||
|
@ -6,7 +6,7 @@ const cls = require('../services/cls');
|
||||
const sql = require("../services/sql");
|
||||
const becca = require("../services/becca/becca");
|
||||
|
||||
async function handleRequest(req, res) {
|
||||
function handleRequest(req, res) {
|
||||
// express puts content after first slash into 0 index element
|
||||
|
||||
const path = req.params.path + req.params[0];
|
||||
@ -72,7 +72,7 @@ async function handleRequest(req, res) {
|
||||
function register(router) {
|
||||
// explicitly no CSRF middleware since it's meant to allow integration from external services
|
||||
|
||||
router.all('/custom/:path*', async (req, res, next) => {
|
||||
router.all('/custom/:path*', (req, res, next) => {
|
||||
cls.namespace.bindEmitter(req);
|
||||
cls.namespace.bindEmitter(res);
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
const ScriptContext = require('./script_context');
|
||||
const repository = require('./repository');
|
||||
const cls = require('./cls');
|
||||
const log = require('./log');
|
||||
const becca = require("./becca/becca");
|
||||
|
||||
async function executeNote(note, apiParams) {
|
||||
function executeNote(note, apiParams) {
|
||||
if (!note.isJavaScript() || note.getScriptEnv() !== 'backend' || !note.isContentAvailable) {
|
||||
log.info(`Cannot execute note ${note.noteId} "${note.title}", note must be of type "Code: JS frontend"`);
|
||||
|
||||
@ -16,16 +15,16 @@ async function executeNote(note, apiParams) {
|
||||
return executeBundle(bundle, apiParams);
|
||||
}
|
||||
|
||||
async function executeNoteNoException(note, apiParams) {
|
||||
function executeNoteNoException(note, apiParams) {
|
||||
try {
|
||||
await executeNote(note, apiParams);
|
||||
executeNote(note, apiParams);
|
||||
}
|
||||
catch (e) {
|
||||
// just swallow, exception is logged already in executeNote
|
||||
}
|
||||
}
|
||||
|
||||
async function executeBundle(bundle, apiParams = {}) {
|
||||
function executeBundle(bundle, apiParams = {}) {
|
||||
if (!apiParams.startNote) {
|
||||
// this is the default case, the only exception is when we want to preserve frontend startNote
|
||||
apiParams.startNote = bundle.note;
|
||||
@ -34,12 +33,12 @@ async function executeBundle(bundle, apiParams = {}) {
|
||||
cls.set('sourceId', 'script');
|
||||
|
||||
// last \r\n is necessary if script contains line comment on its last line
|
||||
const script = "async function() {\r\n" + bundle.script + "\r\n}";
|
||||
const script = "function() {\r\n" + bundle.script + "\r\n}";
|
||||
|
||||
const ctx = new ScriptContext(bundle.allNotes, apiParams);
|
||||
|
||||
try {
|
||||
return await execute(ctx, script);
|
||||
return execute(ctx, script);
|
||||
}
|
||||
catch (e) {
|
||||
log.error(`Execution of script "${bundle.note.title}" (${bundle.note.noteId}) failed with error: ${e.message}`);
|
||||
@ -49,10 +48,13 @@ async function executeBundle(bundle, apiParams = {}) {
|
||||
}
|
||||
|
||||
/**
|
||||
* THIS METHOD CANT BE ASYNC, OTHERWISE TRANSACTION WRAPPER WON'T BE EFFECTIVE AND WE WILL BE LOSING THE
|
||||
* ENTITY CHANGES IN CLS.
|
||||
*
|
||||
* This method preserves frontend startNode - that's why we start execution from currentNote and override
|
||||
* bundle's startNote.
|
||||
*/
|
||||
async function executeScript(script, params, startNoteId, currentNoteId, originEntityName, originEntityId) {
|
||||
function executeScript(script, params, startNoteId, currentNoteId, originEntityName, originEntityId) {
|
||||
const startNote = becca.getNote(startNoteId);
|
||||
const currentNote = becca.getNote(currentNoteId);
|
||||
const originEntity = becca.getEntityFromName(originEntityName, originEntityId);
|
||||
@ -63,11 +65,11 @@ async function executeScript(script, params, startNoteId, currentNoteId, originE
|
||||
|
||||
const bundle = getScriptBundle(currentNote, true, null, [], backendOverrideContent);
|
||||
|
||||
return await executeBundle(bundle, { startNote, originEntity });
|
||||
return executeBundle(bundle, { startNote, originEntity });
|
||||
}
|
||||
|
||||
async function execute(ctx, script) {
|
||||
return await (function() { return eval(`const apiContext = this;\r\n(${script}\r\n)()`); }.call(ctx));
|
||||
function execute(ctx, script) {
|
||||
return function() { return eval(`const apiContext = this;\r\n(${script}\r\n)()`); }.call(ctx);
|
||||
}
|
||||
|
||||
function getParams(params) {
|
||||
@ -153,10 +155,13 @@ function getScriptBundle(note, root = true, scriptEnv = null, includedNoteIds =
|
||||
|
||||
const moduleNoteIds = modules.map(mod => mod.noteId);
|
||||
|
||||
// only frontend scripts are async. Backend cannot be async because of transaction management.
|
||||
const isFrontend = scriptEnv === 'frontend';
|
||||
|
||||
if (note.isJavaScript()) {
|
||||
bundle.script += `
|
||||
apiContext.modules['${note.noteId}'] = {};
|
||||
${root ? 'return ' : ''}await ((async function(exports, module, require, api` + (modules.length > 0 ? ', ' : '') +
|
||||
${root ? 'return ' : ''}${isFrontend ? 'await' : ''} ((${isFrontend ? 'async' : ''} function(exports, module, require, api` + (modules.length > 0 ? ', ' : '') +
|
||||
modules.map(child => sanitizeVariableName(child.title)).join(', ') + `) {
|
||||
try {
|
||||
${backendOverrideContent || note.getContent()};
|
||||
|
Loading…
x
Reference in New Issue
Block a user