mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge pull request #48 from TriliumNext/feature/typescript_backend_11
Convert backend to TypeScript (89% -> 92%, final)
This commit is contained in:
commit
a68b75f069
@ -4,7 +4,7 @@ cloc HEAD \
|
|||||||
--git --md \
|
--git --md \
|
||||||
--include-lang=javascript,typescript \
|
--include-lang=javascript,typescript \
|
||||||
--found=filelist.txt \
|
--found=filelist.txt \
|
||||||
--exclude-dir=public,libraries
|
--exclude-dir=public,libraries,views,docs
|
||||||
|
|
||||||
grep -R \.js$ filelist.txt
|
grep -R \.js$ filelist.txt
|
||||||
rm filelist.txt
|
rm filelist.txt
|
70
package-lock.json
generated
70
package-lock.json
generated
@ -91,6 +91,8 @@
|
|||||||
"@types/archiver": "^6.0.2",
|
"@types/archiver": "^6.0.2",
|
||||||
"@types/better-sqlite3": "^7.6.9",
|
"@types/better-sqlite3": "^7.6.9",
|
||||||
"@types/cls-hooked": "^4.3.8",
|
"@types/cls-hooked": "^4.3.8",
|
||||||
|
"@types/compression": "^1.7.5",
|
||||||
|
"@types/cookie-parser": "^1.4.7",
|
||||||
"@types/csurf": "^1.11.5",
|
"@types/csurf": "^1.11.5",
|
||||||
"@types/ejs": "^3.1.5",
|
"@types/ejs": "^3.1.5",
|
||||||
"@types/escape-html": "^1.0.4",
|
"@types/escape-html": "^1.0.4",
|
||||||
@ -105,6 +107,8 @@
|
|||||||
"@types/safe-compare": "^1.1.2",
|
"@types/safe-compare": "^1.1.2",
|
||||||
"@types/sanitize-html": "^2.11.0",
|
"@types/sanitize-html": "^2.11.0",
|
||||||
"@types/sax": "^1.2.7",
|
"@types/sax": "^1.2.7",
|
||||||
|
"@types/semver": "^7.5.8",
|
||||||
|
"@types/serve-favicon": "^2.5.7",
|
||||||
"@types/stream-throttle": "^0.1.4",
|
"@types/stream-throttle": "^0.1.4",
|
||||||
"@types/tmp": "^0.2.6",
|
"@types/tmp": "^0.2.6",
|
||||||
"@types/turndown": "^5.0.4",
|
"@types/turndown": "^5.0.4",
|
||||||
@ -1229,6 +1233,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/compression": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/connect": {
|
"node_modules/@types/connect": {
|
||||||
"version": "3.4.38",
|
"version": "3.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||||
@ -1238,6 +1251,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/cookie-parser": {
|
||||||
|
"version": "1.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz",
|
||||||
|
"integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/csurf": {
|
"node_modules/@types/csurf": {
|
||||||
"version": "1.11.5",
|
"version": "1.11.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
|
||||||
@ -1643,6 +1665,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/semver": {
|
||||||
|
"version": "7.5.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
|
||||||
|
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/send": {
|
"node_modules/@types/send": {
|
||||||
"version": "0.17.4",
|
"version": "0.17.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||||
@ -1653,6 +1681,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/serve-favicon": {
|
||||||
|
"version": "2.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/serve-favicon/-/serve-favicon-2.5.7.tgz",
|
||||||
|
"integrity": "sha512-z9TNUQXdQ+W/OJMP1e3KOYUZ99qJS4+ZfFOIrPGImcayqKoyifbJSEFkVq1MCKBbqjMZpjPj3B5ilrQAR2+TOw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/serve-static": {
|
"node_modules/@types/serve-static": {
|
||||||
"version": "1.15.5",
|
"version": "1.15.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
||||||
@ -14246,6 +14283,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/compression": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/connect": {
|
"@types/connect": {
|
||||||
"version": "3.4.38",
|
"version": "3.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||||
@ -14255,6 +14301,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/cookie-parser": {
|
||||||
|
"version": "1.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz",
|
||||||
|
"integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/csurf": {
|
"@types/csurf": {
|
||||||
"version": "1.11.5",
|
"version": "1.11.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
|
||||||
@ -14630,6 +14685,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/semver": {
|
||||||
|
"version": "7.5.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
|
||||||
|
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/send": {
|
"@types/send": {
|
||||||
"version": "0.17.4",
|
"version": "0.17.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||||
@ -14640,6 +14701,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/serve-favicon": {
|
||||||
|
"version": "2.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/serve-favicon/-/serve-favicon-2.5.7.tgz",
|
||||||
|
"integrity": "sha512-z9TNUQXdQ+W/OJMP1e3KOYUZ99qJS4+ZfFOIrPGImcayqKoyifbJSEFkVq1MCKBbqjMZpjPj3B5ilrQAR2+TOw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/serve-static": {
|
"@types/serve-static": {
|
||||||
"version": "1.15.5",
|
"version": "1.15.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
||||||
|
12
package.json
12
package.json
@ -13,9 +13,9 @@
|
|||||||
"url": "https://github.com/zadam/trilium.git"
|
"url": "https://github.com/zadam/trilium.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start-server": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.js",
|
"start-server": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
|
||||||
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.js",
|
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
|
||||||
"qstart-server": "npm run qswitch-server && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.js",
|
"qstart-server": "npm run qswitch-server && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
|
||||||
"start-electron": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
|
"start-electron": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
|
||||||
"start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
|
"start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
|
||||||
"qstart-electron": "npm run qswitch-electron && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
|
"qstart-electron": "npm run qswitch-electron && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
|
||||||
@ -112,6 +112,8 @@
|
|||||||
"@types/archiver": "^6.0.2",
|
"@types/archiver": "^6.0.2",
|
||||||
"@types/better-sqlite3": "^7.6.9",
|
"@types/better-sqlite3": "^7.6.9",
|
||||||
"@types/cls-hooked": "^4.3.8",
|
"@types/cls-hooked": "^4.3.8",
|
||||||
|
"@types/compression": "^1.7.5",
|
||||||
|
"@types/cookie-parser": "^1.4.7",
|
||||||
"@types/csurf": "^1.11.5",
|
"@types/csurf": "^1.11.5",
|
||||||
"@types/ejs": "^3.1.5",
|
"@types/ejs": "^3.1.5",
|
||||||
"@types/escape-html": "^1.0.4",
|
"@types/escape-html": "^1.0.4",
|
||||||
@ -126,6 +128,8 @@
|
|||||||
"@types/safe-compare": "^1.1.2",
|
"@types/safe-compare": "^1.1.2",
|
||||||
"@types/sanitize-html": "^2.11.0",
|
"@types/sanitize-html": "^2.11.0",
|
||||||
"@types/sax": "^1.2.7",
|
"@types/sax": "^1.2.7",
|
||||||
|
"@types/semver": "^7.5.8",
|
||||||
|
"@types/serve-favicon": "^2.5.7",
|
||||||
"@types/stream-throttle": "^0.1.4",
|
"@types/stream-throttle": "^0.1.4",
|
||||||
"@types/tmp": "^0.2.6",
|
"@types/tmp": "^0.2.6",
|
||||||
"@types/turndown": "^5.0.4",
|
"@types/turndown": "^5.0.4",
|
||||||
@ -151,4 +155,4 @@
|
|||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"electron-installer-debian": "3.2.0"
|
"electron-installer-debian": "3.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
const express = require('express');
|
import express = require('express');
|
||||||
const path = require('path');
|
import path = require('path');
|
||||||
const favicon = require('serve-favicon');
|
import favicon = require('serve-favicon');
|
||||||
const cookieParser = require('cookie-parser');
|
import cookieParser = require('cookie-parser');
|
||||||
const helmet = require('helmet');
|
import helmet = require('helmet');
|
||||||
const compression = require('compression');
|
import compression = require('compression');
|
||||||
const sessionParser = require('./routes/session_parser');
|
import sessionParser = require('./routes/session_parser');
|
||||||
const utils = require('./services/utils');
|
import utils = require('./services/utils');
|
||||||
|
|
||||||
require('./services/handlers');
|
require('./services/handlers');
|
||||||
require('./becca/becca_loader');
|
require('./becca/becca_loader');
|
||||||
@ -20,7 +20,7 @@ if (!utils.isElectron()) {
|
|||||||
app.use(compression()); // HTTP compression
|
app.use(compression()); // HTTP compression
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(helmet({
|
app.use(helmet.default({
|
||||||
hidePoweredBy: false, // errors out in electron
|
hidePoweredBy: false, // errors out in electron
|
||||||
contentSecurityPolicy: false,
|
contentSecurityPolicy: false,
|
||||||
crossOriginEmbedderPolicy: false
|
crossOriginEmbedderPolicy: false
|
||||||
@ -38,7 +38,7 @@ app.use(sessionParser);
|
|||||||
app.use(favicon(`${__dirname}/../images/app-icons/win/icon.ico`));
|
app.use(favicon(`${__dirname}/../images/app-icons/win/icon.ico`));
|
||||||
|
|
||||||
require('./routes/assets').register(app);
|
require('./routes/assets').register(app);
|
||||||
require('./routes/routes.js').register(app);
|
require('./routes/routes').register(app);
|
||||||
require('./routes/custom').register(app);
|
require('./routes/custom').register(app);
|
||||||
require('./routes/error_handlers').register(app);
|
require('./routes/error_handlers').register(app);
|
||||||
|
|
||||||
@ -57,4 +57,4 @@ if (utils.isElectron()) {
|
|||||||
require('@electron/remote/main').initialize();
|
require('@electron/remote/main').initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = app;
|
export = app;
|
@ -103,6 +103,6 @@ function register(router: Router) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
register
|
register
|
||||||
};
|
};
|
||||||
|
@ -229,7 +229,7 @@ function findNotesByUrl(req: Request){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
createNote,
|
createNote,
|
||||||
addClipping,
|
addClipping,
|
||||||
openNote,
|
openNote,
|
||||||
|
@ -55,6 +55,6 @@ function exportBranch(req: Request, res: Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
exportBranch
|
exportBranch
|
||||||
};
|
};
|
||||||
|
@ -124,7 +124,7 @@ function attachmentContentProvider(req: Request) {
|
|||||||
return streamContent(attachment.getContent(), attachment.getFileName(), attachment.mime);
|
return streamContent(attachment.getContent(), attachment.getFileName(), attachment.mime);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamContent(content: string | Buffer, fileName: string, mimeType: string) {
|
async function streamContent(content: string | Buffer, fileName: string, mimeType: string) {
|
||||||
if (typeof content === "string") {
|
if (typeof content === "string") {
|
||||||
content = Buffer.from(content, 'utf8');
|
content = Buffer.from(content, 'utf8');
|
||||||
}
|
}
|
||||||
|
@ -1,87 +1,94 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const utils = require('../services/utils');
|
import utils = require('../services/utils');
|
||||||
const multer = require('multer');
|
import multer = require('multer');
|
||||||
const log = require('../services/log');
|
import log = require('../services/log');
|
||||||
const express = require('express');
|
import express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const auth = require('../services/auth');
|
import auth = require('../services/auth');
|
||||||
const cls = require('../services/cls');
|
import cls = require('../services/cls');
|
||||||
const sql = require('../services/sql');
|
import sql = require('../services/sql');
|
||||||
const entityChangesService = require('../services/entity_changes');
|
import entityChangesService = require('../services/entity_changes');
|
||||||
const csurf = require('csurf');
|
import csurf = require('csurf');
|
||||||
const { createPartialContentHandler } = require("express-partial-content");
|
import { createPartialContentHandler } from "express-partial-content";
|
||||||
const rateLimit = require("express-rate-limit");
|
import rateLimit = require("express-rate-limit");
|
||||||
const AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity');
|
import AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity');
|
||||||
const NotFoundError = require('../errors/not_found_error');
|
import NotFoundError = require('../errors/not_found_error');
|
||||||
const ValidationError = require('../errors/validation_error');
|
import ValidationError = require('../errors/validation_error');
|
||||||
|
|
||||||
// page routes
|
// page routes
|
||||||
const setupRoute = require('./setup');
|
import setupRoute = require('./setup');
|
||||||
const loginRoute = require('./login');
|
import loginRoute = require('./login');
|
||||||
const indexRoute = require('./index');
|
import indexRoute = require('./index');
|
||||||
|
|
||||||
// API routes
|
// API routes
|
||||||
const treeApiRoute = require('./api/tree');
|
import treeApiRoute = require('./api/tree');
|
||||||
const notesApiRoute = require('./api/notes');
|
import notesApiRoute = require('./api/notes');
|
||||||
const branchesApiRoute = require('./api/branches');
|
import branchesApiRoute = require('./api/branches');
|
||||||
const attachmentsApiRoute = require('./api/attachments');
|
import attachmentsApiRoute = require('./api/attachments');
|
||||||
const autocompleteApiRoute = require('./api/autocomplete');
|
import autocompleteApiRoute = require('./api/autocomplete');
|
||||||
const cloningApiRoute = require('./api/cloning');
|
import cloningApiRoute = require('./api/cloning');
|
||||||
const revisionsApiRoute = require('./api/revisions');
|
import revisionsApiRoute = require('./api/revisions');
|
||||||
const recentChangesApiRoute = require('./api/recent_changes');
|
import recentChangesApiRoute = require('./api/recent_changes');
|
||||||
const optionsApiRoute = require('./api/options');
|
import optionsApiRoute = require('./api/options');
|
||||||
const passwordApiRoute = require('./api/password');
|
import passwordApiRoute = require('./api/password');
|
||||||
const syncApiRoute = require('./api/sync');
|
import syncApiRoute = require('./api/sync');
|
||||||
const loginApiRoute = require('./api/login');
|
import loginApiRoute = require('./api/login');
|
||||||
const recentNotesRoute = require('./api/recent_notes');
|
import recentNotesRoute = require('./api/recent_notes');
|
||||||
const appInfoRoute = require('./api/app_info');
|
import appInfoRoute = require('./api/app_info');
|
||||||
const exportRoute = require('./api/export');
|
import exportRoute = require('./api/export');
|
||||||
const importRoute = require('./api/import');
|
import importRoute = require('./api/import');
|
||||||
const setupApiRoute = require('./api/setup');
|
import setupApiRoute = require('./api/setup');
|
||||||
const sqlRoute = require('./api/sql');
|
import sqlRoute = require('./api/sql');
|
||||||
const databaseRoute = require('./api/database');
|
import databaseRoute = require('./api/database');
|
||||||
const imageRoute = require('./api/image');
|
import imageRoute = require('./api/image');
|
||||||
const attributesRoute = require('./api/attributes');
|
import attributesRoute = require('./api/attributes');
|
||||||
const scriptRoute = require('./api/script');
|
import scriptRoute = require('./api/script');
|
||||||
const senderRoute = require('./api/sender');
|
import senderRoute = require('./api/sender');
|
||||||
const filesRoute = require('./api/files');
|
import filesRoute = require('./api/files');
|
||||||
const searchRoute = require('./api/search');
|
import searchRoute = require('./api/search');
|
||||||
const bulkActionRoute = require('./api/bulk_action');
|
import bulkActionRoute = require('./api/bulk_action');
|
||||||
const specialNotesRoute = require('./api/special_notes');
|
import specialNotesRoute = require('./api/special_notes');
|
||||||
const noteMapRoute = require('./api/note_map');
|
import noteMapRoute = require('./api/note_map');
|
||||||
const clipperRoute = require('./api/clipper');
|
import clipperRoute = require('./api/clipper');
|
||||||
const similarNotesRoute = require('./api/similar_notes');
|
import similarNotesRoute = require('./api/similar_notes');
|
||||||
const keysRoute = require('./api/keys');
|
import keysRoute = require('./api/keys');
|
||||||
const backendLogRoute = require('./api/backend_log');
|
import backendLogRoute = require('./api/backend_log');
|
||||||
const statsRoute = require('./api/stats');
|
import statsRoute = require('./api/stats');
|
||||||
const fontsRoute = require('./api/fonts');
|
import fontsRoute = require('./api/fonts');
|
||||||
const etapiTokensApiRoutes = require('./api/etapi_tokens');
|
import etapiTokensApiRoutes = require('./api/etapi_tokens');
|
||||||
const relationMapApiRoute = require('./api/relation-map');
|
import relationMapApiRoute = require('./api/relation-map');
|
||||||
const otherRoute = require('./api/other');
|
import otherRoute = require('./api/other');
|
||||||
const shareRoutes = require('../share/routes');
|
import shareRoutes = require('../share/routes');
|
||||||
|
|
||||||
const etapiAuthRoutes = require('../etapi/auth');
|
import etapiAuthRoutes = require('../etapi/auth');
|
||||||
const etapiAppInfoRoutes = require('../etapi/app_info');
|
import etapiAppInfoRoutes = require('../etapi/app_info');
|
||||||
const etapiAttachmentRoutes = require('../etapi/attachments');
|
import etapiAttachmentRoutes = require('../etapi/attachments');
|
||||||
const etapiAttributeRoutes = require('../etapi/attributes');
|
import etapiAttributeRoutes = require('../etapi/attributes');
|
||||||
const etapiBranchRoutes = require('../etapi/branches');
|
import etapiBranchRoutes = require('../etapi/branches');
|
||||||
const etapiNoteRoutes = require('../etapi/notes');
|
import etapiNoteRoutes = require('../etapi/notes');
|
||||||
const etapiSpecialNoteRoutes = require('../etapi/special_notes');
|
import etapiSpecialNoteRoutes = require('../etapi/special_notes');
|
||||||
const etapiSpecRoute = require('../etapi/spec');
|
import etapiSpecRoute = require('../etapi/spec');
|
||||||
const etapiBackupRoute = require('../etapi/backup');
|
import etapiBackupRoute = require('../etapi/backup');
|
||||||
|
import { AppRequest, AppRequestHandler } from './route-interface';
|
||||||
|
|
||||||
const csrfMiddleware = csurf({
|
const csrfMiddleware = csurf({
|
||||||
cookie: true,
|
cookie: {
|
||||||
path: '' // empty, so cookie is valid only for the current path
|
path: "" // empty, so cookie is valid only for the current path
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const MAX_ALLOWED_FILE_SIZE_MB = 250;
|
const MAX_ALLOWED_FILE_SIZE_MB = 250;
|
||||||
const GET = 'get', PST = 'post', PUT = 'put', PATCH = 'patch', DEL = 'delete';
|
const GET = 'get', PST = 'post', PUT = 'put', PATCH = 'patch', DEL = 'delete';
|
||||||
|
|
||||||
|
type ApiResultHandler = (req: express.Request, res: express.Response, result: unknown) => number;
|
||||||
|
|
||||||
|
// TODO: Deduplicate with etapi_utils.ts afterwards.
|
||||||
|
type HttpMethod = "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head";
|
||||||
|
|
||||||
const uploadMiddleware = createUploadMiddleware();
|
const uploadMiddleware = createUploadMiddleware();
|
||||||
|
|
||||||
const uploadMiddlewareWithErrorHandling = function (req, res, next) {
|
const uploadMiddlewareWithErrorHandling = function (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
uploadMiddleware(req, res, function (err) {
|
uploadMiddleware(req, res, function (err) {
|
||||||
if (err?.code === 'LIMIT_FILE_SIZE') {
|
if (err?.code === 'LIMIT_FILE_SIZE') {
|
||||||
res.setHeader("Content-Type", "text/plain")
|
res.setHeader("Content-Type", "text/plain")
|
||||||
@ -94,12 +101,12 @@ const uploadMiddlewareWithErrorHandling = function (req, res, next) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function register(app) {
|
function register(app: express.Application) {
|
||||||
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
||||||
route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage);
|
route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage);
|
||||||
route(GET, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage);
|
route(GET, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage);
|
||||||
|
|
||||||
const loginRateLimiter = rateLimit({
|
const loginRateLimiter = rateLimit.rateLimit({
|
||||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||||
max: 10, // limit each IP to 10 requests per windowMs
|
max: 10, // limit each IP to 10 requests per windowMs
|
||||||
skipSuccessfulRequests: true // successful auth to rate-limited ETAPI routes isn't counted. However, successful auth to /login is still counted!
|
skipSuccessfulRequests: true // successful auth to rate-limited ETAPI routes isn't counted. However, successful auth to /login is still counted!
|
||||||
@ -353,7 +360,7 @@ function register(app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Handling common patterns. If entity is not caught, serialization to JSON will fail */
|
/** Handling common patterns. If entity is not caught, serialization to JSON will fail */
|
||||||
function convertEntitiesToPojo(result) {
|
function convertEntitiesToPojo(result: unknown) {
|
||||||
if (result instanceof AbstractBeccaEntity) {
|
if (result instanceof AbstractBeccaEntity) {
|
||||||
result = result.getPojo();
|
result = result.getPojo();
|
||||||
}
|
}
|
||||||
@ -364,24 +371,24 @@ function convertEntitiesToPojo(result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (result && typeof result === "object") {
|
||||||
if (result && result.note instanceof AbstractBeccaEntity) {
|
if ("note" in result && result.note instanceof AbstractBeccaEntity) {
|
||||||
result.note = result.note.getPojo();
|
result.note = result.note.getPojo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result && result.branch instanceof AbstractBeccaEntity) {
|
if ("branch" in result && result.branch instanceof AbstractBeccaEntity) {
|
||||||
result.branch = result.branch.getPojo();
|
result.branch = result.branch.getPojo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result && result.executionResult) { // from runOnBackend()
|
if (result && typeof result === "object" && "executionResult" in result) { // from runOnBackend()
|
||||||
result.executionResult = convertEntitiesToPojo(result.executionResult);
|
result.executionResult = convertEntitiesToPojo(result.executionResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function apiResultHandler(req, res, result) {
|
function apiResultHandler(req: express.Request, res: express.Response, result: unknown) {
|
||||||
res.setHeader('trilium-max-entity-change-id', entityChangesService.getMaxEntityChangeId());
|
res.setHeader('trilium-max-entity-change-id', entityChangesService.getMaxEntityChangeId());
|
||||||
|
|
||||||
result = convertEntitiesToPojo(result);
|
result = convertEntitiesToPojo(result);
|
||||||
@ -404,7 +411,7 @@ function apiResultHandler(req, res, result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function send(res, statusCode, response) {
|
function send(res: express.Response, statusCode: number, response: unknown) {
|
||||||
if (typeof response === 'string') {
|
if (typeof response === 'string') {
|
||||||
if (statusCode >= 400) {
|
if (statusCode >= 400) {
|
||||||
res.setHeader("Content-Type", "text/plain");
|
res.setHeader("Content-Type", "text/plain");
|
||||||
@ -424,12 +431,12 @@ function send(res, statusCode, response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function apiRoute(method, path, routeHandler) {
|
function apiRoute(method: HttpMethod, path: string, routeHandler: express.Handler) {
|
||||||
route(method, path, [auth.checkApiAuth, csrfMiddleware], routeHandler, apiResultHandler);
|
route(method, path, [auth.checkApiAuth, csrfMiddleware], routeHandler, apiResultHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
function route(method, path, middleware, routeHandler, resultHandler = null, transactional = true) {
|
function route(method: HttpMethod, path: string, middleware: (express.Handler | AppRequestHandler)[], routeHandler: AppRequestHandler, resultHandler: ApiResultHandler | null = null, transactional = true) {
|
||||||
router[method](path, ...middleware, (req, res, next) => {
|
router[method](path, ...(middleware as express.Handler[]), (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -441,7 +448,7 @@ function route(method, path, middleware, routeHandler, resultHandler = null, tra
|
|||||||
cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']);
|
cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']);
|
||||||
cls.set('hoistedNoteId', req.headers['trilium-hoisted-note-id'] || 'root');
|
cls.set('hoistedNoteId', req.headers['trilium-hoisted-note-id'] || 'root');
|
||||||
|
|
||||||
const cb = () => routeHandler(req, res, next);
|
const cb = () => routeHandler(req as AppRequest, res, next);
|
||||||
|
|
||||||
return transactional ? sql.transactional(cb) : cb();
|
return transactional ? sql.transactional(cb) : cb();
|
||||||
});
|
});
|
||||||
@ -452,8 +459,8 @@ function route(method, path, middleware, routeHandler, resultHandler = null, tra
|
|||||||
|
|
||||||
if (result?.then) { // promise
|
if (result?.then) { // promise
|
||||||
result
|
result
|
||||||
.then(promiseResult => handleResponse(resultHandler, req, res, promiseResult, start))
|
.then((promiseResult: unknown) => handleResponse(resultHandler, req, res, promiseResult, start))
|
||||||
.catch(e => handleException(e, method, path, res));
|
.catch((e: any) => handleException(e, method, path, res));
|
||||||
} else {
|
} else {
|
||||||
handleResponse(resultHandler, req, res, result, start)
|
handleResponse(resultHandler, req, res, result, start)
|
||||||
}
|
}
|
||||||
@ -464,13 +471,13 @@ function route(method, path, middleware, routeHandler, resultHandler = null, tra
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleResponse(resultHandler, req, res, result, start) {
|
function handleResponse(resultHandler: ApiResultHandler, req: express.Request, res: express.Response, result: unknown, start: number) {
|
||||||
const responseLength = resultHandler(req, res, result);
|
const responseLength = resultHandler(req, res, result);
|
||||||
|
|
||||||
log.request(req, res, Date.now() - start, responseLength);
|
log.request(req, res, Date.now() - start, responseLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleException(e, method, path, res) {
|
function handleException(e: any, method: HttpMethod, path: string, res: express.Response) {
|
||||||
log.error(`${method} ${path} threw exception: '${e.message}', stack: ${e.stack}`);
|
log.error(`${method} ${path} threw exception: '${e.message}', stack: ${e.stack}`);
|
||||||
|
|
||||||
if (e instanceof ValidationError) {
|
if (e instanceof ValidationError) {
|
||||||
@ -492,8 +499,8 @@ function handleException(e, method, path, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createUploadMiddleware() {
|
function createUploadMiddleware() {
|
||||||
const multerOptions = {
|
const multerOptions: multer.Options = {
|
||||||
fileFilter: (req, file, cb) => {
|
fileFilter: (req: express.Request, file, cb) => {
|
||||||
// UTF-8 file names are not well decoded by multer/busboy, so we handle the conversion on our side.
|
// UTF-8 file names are not well decoded by multer/busboy, so we handle the conversion on our side.
|
||||||
// See https://github.com/expressjs/multer/pull/1102.
|
// See https://github.com/expressjs/multer/pull/1102.
|
||||||
file.originalname = Buffer.from(file.originalname, "latin1").toString("utf-8");
|
file.originalname = Buffer.from(file.originalname, "latin1").toString("utf-8");
|
||||||
@ -510,6 +517,6 @@ function createUploadMiddleware() {
|
|||||||
return multer(multerOptions).single('upload');
|
return multer(multerOptions).single('upload');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
register
|
register
|
||||||
};
|
};
|
@ -76,7 +76,7 @@ function error(message: string) {
|
|||||||
|
|
||||||
const requestBlacklist = [ "/libraries", "/app", "/images", "/stylesheets", "/api/recent-notes" ];
|
const requestBlacklist = [ "/libraries", "/app", "/images", "/stylesheets", "/api/recent-notes" ];
|
||||||
|
|
||||||
function request(req: Request, res: Response, timeMs: number, responseLength = "?") {
|
function request(req: Request, res: Response, timeMs: number, responseLength: number | string = "?") {
|
||||||
for (const bl of requestBlacklist) {
|
for (const bl of requestBlacklist) {
|
||||||
if (req.url.startsWith(bl)) {
|
if (req.url.startsWith(bl)) {
|
||||||
return;
|
return;
|
||||||
|
@ -81,7 +81,7 @@ async function createMainWindow(app: App) {
|
|||||||
|
|
||||||
app.on('second-instance', () => {
|
app.on('second-instance', () => {
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
// see www.js "requestSingleInstanceLock" for the rest of this logic with explanation
|
// see www.ts "requestSingleInstanceLock" for the rest of this logic with explanation
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
if (mainWindow.isMinimized()) {
|
if (mainWindow.isMinimized()) {
|
||||||
mainWindow.restore();
|
mainWindow.restore();
|
||||||
|
@ -18,19 +18,19 @@ function exit() {
|
|||||||
process.on('SIGINT', exit);
|
process.on('SIGINT', exit);
|
||||||
process.on('SIGTERM', exit);
|
process.on('SIGTERM', exit);
|
||||||
|
|
||||||
const app = require('./app');
|
import app = require('./app');
|
||||||
const sessionParser = require('./routes/session_parser');
|
import sessionParser = require('./routes/session_parser');
|
||||||
const fs = require('fs');
|
import fs = require('fs');
|
||||||
const http = require('http');
|
import http = require('http');
|
||||||
const https = require('https');
|
import https = require('https');
|
||||||
const config = require('./services/config');
|
import config = require('./services/config');
|
||||||
const log = require('./services/log');
|
import log = require('./services/log');
|
||||||
const appInfo = require('./services/app_info');
|
import appInfo = require('./services/app_info');
|
||||||
const ws = require('./services/ws');
|
import ws = require('./services/ws');
|
||||||
const utils = require('./services/utils');
|
import utils = require('./services/utils');
|
||||||
const port = require('./services/port');
|
import port = require('./services/port');
|
||||||
const host = require('./services/host');
|
import host = require('./services/host');
|
||||||
const semver = require('semver');
|
import semver = require('semver');
|
||||||
|
|
||||||
if (!semver.satisfies(process.version, ">=10.5.0")) {
|
if (!semver.satisfies(process.version, ">=10.5.0")) {
|
||||||
console.error("Trilium only supports node.js 10.5 and later");
|
console.error("Trilium only supports node.js 10.5 and later");
|
||||||
@ -66,7 +66,7 @@ function startTrilium() {
|
|||||||
|
|
||||||
const httpServer = startHttpServer();
|
const httpServer = startHttpServer();
|
||||||
|
|
||||||
ws.init(httpServer, sessionParser);
|
ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible.
|
||||||
|
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
const electronRouting = require('./routes/electron');
|
const electronRouting = require('./routes/electron');
|
||||||
@ -126,25 +126,23 @@ function startHttpServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
httpServer.on('error', error => {
|
httpServer.on('error', error => {
|
||||||
if (!listenOnTcp || error.syscall !== 'listen') {
|
if (!listenOnTcp || ("syscall" in error && error.syscall !== 'listen')) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle specific listen errors with friendly messages
|
// handle specific listen errors with friendly messages
|
||||||
switch (error.code) {
|
if ("code" in error) {
|
||||||
case 'EACCES':
|
switch (error.code) {
|
||||||
console.error(`Port ${port} requires elevated privileges. It's recommended to use port above 1024.`);
|
case 'EACCES':
|
||||||
process.exit(1);
|
console.error(`Port ${port} requires elevated privileges. It's recommended to use port above 1024.`);
|
||||||
break;
|
process.exit(1);
|
||||||
|
case 'EADDRINUSE':
|
||||||
case 'EADDRINUSE':
|
console.error(`Port ${port} is already in use. Most likely, another Trilium process is already running. You might try to find it, kill it, and try again.`);
|
||||||
console.error(`Port ${port} is already in use. Most likely, another Trilium process is already running. You might try to find it, kill it, and try again.`);
|
process.exit(1);
|
||||||
process.exit(1);
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user