Merge pull request #44 from TriliumNext/feature/typescript_backend_8

Convert backend to TypeScript (80% -> 81%)
This commit is contained in:
Elian Doran 2024-04-16 21:01:20 +03:00 committed by GitHub
commit 625d935f08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 213 additions and 109 deletions

57
package-lock.json generated
View File

@ -91,12 +91,15 @@
"@types/archiver": "^6.0.2",
"@types/better-sqlite3": "^7.6.9",
"@types/cls-hooked": "^4.3.8",
"@types/csurf": "^1.11.5",
"@types/escape-html": "^1.0.4",
"@types/express": "^4.17.21",
"@types/express-session": "^1.18.0",
"@types/html": "^1.0.4",
"@types/ini": "^4.1.0",
"@types/jsdom": "^21.1.6",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.11",
"@types/node": "^20.11.19",
"@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7",
@ -1233,6 +1236,15 @@
"@types/node": "*"
}
},
"node_modules/@types/csurf": {
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
"integrity": "sha512-5rw87+5YGixyL2W8wblSUl5DSZi5YOlXE6Awwn2ofLvqKr/1LruKffrQipeJKUX44VaxKj8m5es3vfhltJTOoA==",
"dev": true,
"dependencies": {
"@types/express-serve-static-core": "*"
}
},
"node_modules/@types/d3-scale": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
@ -1315,6 +1327,15 @@
"@types/send": "*"
}
},
"node_modules/@types/express-session": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz",
"integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==",
"dev": true,
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
@ -1459,6 +1480,15 @@
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz",
"integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g=="
},
"node_modules/@types/multer": {
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz",
"integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==",
"dev": true,
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/node": {
"version": "20.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
@ -14211,6 +14241,15 @@
"@types/node": "*"
}
},
"@types/csurf": {
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.11.5.tgz",
"integrity": "sha512-5rw87+5YGixyL2W8wblSUl5DSZi5YOlXE6Awwn2ofLvqKr/1LruKffrQipeJKUX44VaxKj8m5es3vfhltJTOoA==",
"dev": true,
"requires": {
"@types/express-serve-static-core": "*"
}
},
"@types/d3-scale": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
@ -14293,6 +14332,15 @@
"@types/send": "*"
}
},
"@types/express-session": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz",
"integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/fs-extra": {
"version": "9.0.13",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
@ -14430,6 +14478,15 @@
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz",
"integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g=="
},
"@types/multer": {
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz",
"integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/node": {
"version": "20.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",

View File

@ -112,12 +112,15 @@
"@types/archiver": "^6.0.2",
"@types/better-sqlite3": "^7.6.9",
"@types/cls-hooked": "^4.3.8",
"@types/csurf": "^1.11.5",
"@types/escape-html": "^1.0.4",
"@types/express": "^4.17.21",
"@types/express-session": "^1.18.0",
"@types/html": "^1.0.4",
"@types/ini": "^4.1.0",
"@types/jsdom": "^21.1.6",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.11",
"@types/node": "^20.11.19",
"@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7",

View File

@ -4,7 +4,7 @@ const favicon = require('serve-favicon');
const cookieParser = require('cookie-parser');
const helmet = require('helmet');
const compression = require('compression');
const sessionParser = require('./routes/session_parser.js');
const sessionParser = require('./routes/session_parser');
const utils = require('./services/utils');
require('./services/handlers');
@ -37,10 +37,10 @@ app.use(`/robots.txt`, express.static(path.join(__dirname, 'public/robots.txt'))
app.use(sessionParser);
app.use(favicon(`${__dirname}/../images/app-icons/win/icon.ico`));
require('./routes/assets.js').register(app);
require('./routes/assets').register(app);
require('./routes/routes.js').register(app);
require('./routes/custom.js').register(app);
require('./routes/error_handlers.js').register(app);
require('./routes/custom').register(app);
require('./routes/error_handlers').register(app);
// triggers sync timer
require('./services/sync');

View File

@ -14,11 +14,12 @@ import ValidationError = require('../../errors/validation_error');
import { Request, Response } from 'express';
import BNote = require('../../becca/entities/bnote');
import BAttachment = require('../../becca/entities/battachment');
import { AppRequest } from '../route-interface';
function updateFile(req: Request) {
function updateFile(req: AppRequest) {
const note = becca.getNoteOrThrow(req.params.noteId);
const file = (req as any).file;
const file = req.file;
note.saveRevision();
note.mime = file.mimetype.toLowerCase();
@ -35,9 +36,9 @@ function updateFile(req: Request) {
};
}
function updateAttachment(req: Request) {
function updateAttachment(req: AppRequest) {
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
const file = (req as any).file;
const file = req.file;
attachment.getNote().saveRevision();

View File

@ -7,6 +7,7 @@ import fs = require('fs');
import { Request, Response } from 'express';
import BNote = require('../../becca/entities/bnote');
import BRevision = require('../../becca/entities/brevision');
import { AppRequest } from '../route-interface';
function returnImageFromNote(req: Request, res: Response) {
const image = becca.getNote(req.params.noteId);
@ -81,9 +82,9 @@ function returnAttachedImage(req: Request, res: Response) {
res.send(attachment.getContent());
}
function updateImage(req: Request) {
function updateImage(req: AppRequest) {
const {noteId} = req.params;
const {file} = (req as any);
const {file} = req;
const note = becca.getNoteOrThrow(noteId);
@ -94,6 +95,13 @@ function updateImage(req: Request) {
};
}
if (typeof file.buffer === "string") {
return {
uploaded: false,
message: "Invalid image content."
};
}
imageService.updateImage(noteId, file.buffer, file.originalname);
return { uploaded: true };

View File

@ -13,8 +13,9 @@ import TaskContext = require('../../services/task_context');
import ValidationError = require('../../errors/validation_error');
import { Request } from 'express';
import BNote = require('../../becca/entities/bnote');
import { AppRequest } from '../route-interface';
async function importNotesToBranch(req: Request) {
async function importNotesToBranch(req: AppRequest) {
const { parentNoteId } = req.params;
const { taskId, last } = req.body;
@ -27,7 +28,7 @@ async function importNotesToBranch(req: Request) {
replaceUnderscoresWithSpaces: req.body.replaceUnderscoresWithSpaces !== 'false'
};
const file = (req as any).file;
const file = req.file;
if (!file) {
throw new ValidationError("No file has been uploaded");
@ -49,7 +50,7 @@ async function importNotesToBranch(req: Request) {
const taskContext = TaskContext.getInstance(taskId, 'importNotes', options);
try {
if (extension === '.zip' && options.explodeArchives) {
if (extension === '.zip' && options.explodeArchives && typeof file.buffer !== "string") {
note = await zipImportService.importZip(taskContext, file.buffer, parentNote);
} else if (extension === '.opml' && options.explodeArchives) {
const importResult = await opmlImportService.importOpml(taskContext, file.buffer, parentNote);
@ -96,7 +97,7 @@ async function importNotesToBranch(req: Request) {
return note.getPojo();
}
async function importAttachmentsToNote(req: Request) {
async function importAttachmentsToNote(req: AppRequest) {
const { parentNoteId } = req.params;
const { taskId, last } = req.body;
@ -104,7 +105,7 @@ async function importAttachmentsToNote(req: Request) {
shrinkImages: req.body.shrinkImages !== 'false',
};
const file = (req as any).file;
const file = req.file;
if (!file) {
throw new ValidationError("No file has been uploaded");

View File

@ -13,8 +13,9 @@ import sql = require('../../services/sql');
import ws = require('../../services/ws');
import etapiTokenService = require('../../services/etapi_tokens');
import { Request } from 'express';
import { AppRequest } from '../route-interface';
function loginSync(req: Request) {
function loginSync(req: AppRequest) {
if (!sqlInit.schemaExists()) {
return [500, { message: "DB schema does not exist, can't sync." }];
}
@ -45,7 +46,7 @@ function loginSync(req: Request) {
return [400, { message: "Sync login credentials are incorrect. It looks like you're trying to sync two different initialized documents which is not possible." }];
}
(req as any).session.loggedIn = true;
req.session.loggedIn = true;
return {
instanceId: instanceId,

View File

@ -6,13 +6,17 @@ import noteService = require('../../services/notes');
import sanitize_attribute_name = require('../../services/sanitize_attribute_name');
import specialNotesService = require('../../services/special_notes');
import { Request } from 'express';
import { AppRequest } from '../route-interface';
function uploadImage(req: Request) {
const file = (req as any).file;
function uploadImage(req: AppRequest) {
const file = req.file;
if (!["image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"].includes(file.mimetype)) {
return [400, `Unknown image type: ${file.mimetype}`];
}
if (typeof file.buffer === "string") {
return [400, "Invalid image content type."];
}
const uploadedImageType = imageType(file.buffer);
if (!uploadedImageType) {
@ -20,14 +24,10 @@ function uploadImage(req: Request) {
}
const originalName = `Sender image.${uploadedImageType.ext}`;
if (!req.headers["x-local-date"] || Array.isArray(req.headers["x-local-date"])) {
if (!req.headers["x-local-date"]) {
return [400, "Invalid local date"];
}
if (Array.isArray(req.headers["x-labels"])) {
return [400, "Invalid value type."];
}
const parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']);
const { note, noteId } = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);

View File

@ -1,9 +1,10 @@
const assetPath = require('../services/asset_path');
const path = require("path");
const express = require("express");
const env = require('../services/env');
import assetPath = require('../services/asset_path');
import path = require("path");
import express = require("express");
import env = require('../services/env');
import serveStatic = require('serve-static');
const persistentCacheStatic = (root, options) => {
const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOptions<express.Response<any, Record<string, any>>>) => {
if (!env.isDev()) {
options = {
maxAge: '1y',
@ -13,7 +14,7 @@ const persistentCacheStatic = (root, options) => {
return express.static(root, options);
};
function register(app) {
function register(app: express.Application) {
const srcRoot = path.join(__dirname, '..');
app.use(`/${assetPath}/app`, persistentCacheStatic(path.join(srcRoot, 'public/app')));
app.use(`/${assetPath}/app-dist`, persistentCacheStatic(path.join(srcRoot, 'public/app-dist')));
@ -70,6 +71,6 @@ function register(app) {
app.use(`/${assetPath}/node_modules/panzoom/dist/`, persistentCacheStatic(path.join(srcRoot, '..', 'node_modules/panzoom/dist/')));
}
module.exports = {
export = {
register
};

View File

@ -1,21 +1,22 @@
const log = require('../services/log');
const fileService = require('./api/files');
const scriptService = require('../services/script');
const cls = require('../services/cls');
const sql = require('../services/sql');
const becca = require('../becca/becca');
import log = require('../services/log');
import fileService = require('./api/files');
import scriptService = require('../services/script');
import cls = require('../services/cls');
import sql = require('../services/sql');
import becca = require('../becca/becca');
import { Request, Response, Router } from 'express';
function handleRequest(req, res) {
function handleRequest(req: Request, res: Response) {
// express puts content after first slash into 0 index element
const path = req.params.path + req.params[0];
const attributeIds = sql.getColumn("SELECT attributeId FROM attributes WHERE isDeleted = 0 AND type = 'label' AND name IN ('customRequestHandler', 'customResourceProvider')");
const attributeIds = sql.getColumn<string>("SELECT attributeId FROM attributes WHERE isDeleted = 0 AND type = 'label' AND name IN ('customRequestHandler', 'customResourceProvider')");
const attrs = attributeIds.map(attrId => becca.getAttribute(attrId));
for (const attr of attrs) {
if (!attr.value.trim()) {
if (!attr?.value.trim()) {
continue;
}
@ -25,7 +26,7 @@ function handleRequest(req, res) {
try {
match = path.match(regex);
}
catch (e) {
catch (e: any) {
log.error(`Testing path for label '${attr.attributeId}', regex '${attr.value}' failed with error: ${e.message}, stack: ${e.stack}`);
continue;
}
@ -46,7 +47,7 @@ function handleRequest(req, res) {
res
});
}
catch (e) {
catch (e: any) {
log.error(`Custom handler '${note.noteId}' failed with: ${e.message}, ${e.stack}`);
res.setHeader("Content-Type", "text/plain")
@ -72,10 +73,10 @@ function handleRequest(req, res) {
.send(message);
}
function register(router) {
function register(router: Router) {
// explicitly no CSRF middleware since it's meant to allow integration from external services
router.all('/custom/:path*', (req, res, next) => {
router.all('/custom/:path*', (req: Request, res: Response, next) => {
cls.namespace.bindEmitter(req);
cls.namespace.bindEmitter(res);
@ -83,6 +84,6 @@ function register(router) {
});
}
module.exports = {
export = {
register
};

View File

@ -1,6 +1,17 @@
import { Application } from "express";
const ipcMain = require('electron').ipcMain;
function init(app) {
interface Response {
statusCode: number;
getHeader: (name: string) => string;
setHeader: (name: string, value: string) => Response;
header: (name: string, value: string) => Response;
status: (statusCode: number) => Response;
send: (obj: {}) => void;
}
function init(app: Application) {
ipcMain.on('server-request', (event, arg) => {
const req = {
url: arg.url,
@ -12,9 +23,9 @@ function init(app) {
}
};
const respHeaders = {};
const respHeaders: Record<string, string> = {};
const res = {
const res: Response = {
statusCode: 200,
getHeader: name => respHeaders[name],
setHeader: (name, value) => {
@ -45,4 +56,4 @@ function init(app) {
});
}
module.exports = init;
export = init;

View File

@ -1,7 +1,8 @@
const log = require('../services/log');
import { Application, NextFunction, Request, Response } from 'express';
import log = require('../services/log');
function register(app) {
app.use((err, req, res, next) => {
function register(app: Application) {
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
if (err.code !== 'EBADCSRFTOKEN') {
return next(err);
}
@ -16,12 +17,12 @@ function register(app) {
// catch 404 and forward to error handler
app.use((req, res, next) => {
const err = new Error(`Router not found for request ${req.method} ${req.url}`);
err.status = 404;
(err as any).status = 404;
next(err);
});
// error handler
app.use((err, req, res, next) => {
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
if (err && err.message && (
(err.message.includes("Router not found for request") && err.message.includes(".js.map"))
|| (err.message.includes("Router not found for request") && err.message.includes(".css.map"))
@ -38,6 +39,6 @@ function register(app) {
});
}
module.exports = {
export = {
register
};

View File

@ -1,18 +1,19 @@
"use strict";
const sql = require('../services/sql');
const attributeService = require('../services/attributes');
const config = require('../services/config');
const optionService = require('../services/options');
const log = require('../services/log');
const env = require('../services/env');
const utils = require('../services/utils');
const protectedSessionService = require('../services/protected_session');
const packageJson = require('../../package.json');
const assetPath = require('../services/asset_path');
const appPath = require('../services/app_path');
import sql = require('../services/sql');
import attributeService = require('../services/attributes');
import config = require('../services/config');
import optionService = require('../services/options');
import log = require('../services/log');
import env = require('../services/env');
import utils = require('../services/utils');
import protectedSessionService = require('../services/protected_session');
import packageJson = require('../../package.json');
import assetPath = require('../services/asset_path');
import appPath = require('../services/app_path');
import { Request, Response } from 'express';
function index(req, res) {
function index(req: Request, res: Response) {
const options = optionService.getOptionMap();
const view = (!utils.isElectron() && req.cookies['trilium-device'] === 'mobile')
@ -43,7 +44,7 @@ function index(req, res) {
});
}
function getThemeCssUrl(theme) {
function getThemeCssUrl(theme: string) {
if (theme === 'light') {
return false; // light theme is always loaded as baseline
} else if (theme === 'dark') {
@ -63,6 +64,6 @@ function getAppCssNoteIds() {
return attributeService.getNotesWithLabel('appCss').map(note => note.noteId);
}
module.exports = {
export = {
index
};

View File

@ -1,15 +1,17 @@
"use strict";
const utils = require('../services/utils');
const optionService = require('../services/options');
const myScryptService = require('../services/encryption/my_scrypt');
const log = require('../services/log');
const passwordService = require('../services/encryption/password');
const assetPath = require('../services/asset_path');
const appPath = require('../services/app_path');
const ValidationError = require('../errors/validation_error');
import utils = require('../services/utils');
import optionService = require('../services/options');
import myScryptService = require('../services/encryption/my_scrypt');
import log = require('../services/log');
import passwordService = require('../services/encryption/password');
import assetPath = require('../services/asset_path');
import appPath = require('../services/app_path');
import ValidationError = require('../errors/validation_error');
import { Request, Response } from 'express';
import { AppRequest } from './route-interface';
function loginPage(req, res) {
function loginPage(req: Request, res: Response) {
res.render('login', {
failedAuth: false,
assetPath: assetPath,
@ -17,7 +19,7 @@ function loginPage(req, res) {
});
}
function setPasswordPage(req, res) {
function setPasswordPage(req: Request, res: Response) {
res.render('set_password', {
error: false,
assetPath: assetPath,
@ -25,7 +27,7 @@ function setPasswordPage(req, res) {
});
}
function setPassword(req, res) {
function setPassword(req: Request, res: Response) {
if (passwordService.isPasswordSet()) {
throw new ValidationError("Password has been already set");
}
@ -55,7 +57,7 @@ function setPassword(req, res) {
res.redirect('login');
}
function login(req, res) {
function login(req: AppRequest, res: Response) {
const guessedPassword = req.body.password;
if (verifyPassword(guessedPassword)) {
@ -83,7 +85,7 @@ function login(req, res) {
}
}
function verifyPassword(guessedPassword) {
function verifyPassword(guessedPassword: string) {
const hashed_password = utils.fromBase64(optionService.getOption('passwordVerificationHash'));
const guess_hashed = myScryptService.getVerificationHash(guessedPassword);
@ -91,7 +93,7 @@ function verifyPassword(guessedPassword) {
return guess_hashed.equals(hashed_password);
}
function logout(req, res) {
function logout(req: AppRequest, res: Response) {
req.session.regenerate(() => {
req.session.loggedIn = false;
@ -100,7 +102,7 @@ function logout(req, res) {
}
module.exports = {
export = {
loginPage,
setPasswordPage,
setPassword,

View File

@ -0,0 +1,20 @@
import { Request } from "express";
import { File } from "../services/import/common";
export interface AppRequest extends Request {
headers: {
authorization?: string;
"trilium-cred"?: string;
"x-local-date"?: string;
"x-labels"?: string;
}
session: {
loggedIn: boolean;
cookie: {
maxAge: number;
expires: boolean
};
regenerate: (callback: () => void) => void;
}
file: File;
}

View File

@ -18,8 +18,8 @@ const ValidationError = require('../errors/validation_error');
// page routes
const setupRoute = require('./setup');
const loginRoute = require('./login.js');
const indexRoute = require('./index.js');
const loginRoute = require('./login');
const indexRoute = require('./index');
// API routes
const treeApiRoute = require('./api/tree');

View File

@ -1,6 +1,6 @@
const session = require("express-session");
const sessionSecret = require('../services/session_secret');
const dataDir = require('../services/data_dir');
import session = require("express-session");
import sessionSecret = require('../services/session_secret');
import dataDir = require('../services/data_dir');
const FileStore = require('session-file-store')(session);
const sessionParser = session({
@ -19,4 +19,4 @@ const sessionParser = session({
})
});
module.exports = sessionParser;
export = sessionParser;

View File

@ -1,12 +1,13 @@
"use strict";
const sqlInit = require('../services/sql_init');
const setupService = require('../services/setup');
const utils = require('../services/utils');
const assetPath = require('../services/asset_path');
const appPath = require('../services/app_path');
import sqlInit = require('../services/sql_init');
import setupService = require('../services/setup');
import utils = require('../services/utils');
import assetPath = require('../services/asset_path');
import appPath = require('../services/app_path');
import { Request, Response } from 'express';
function setupPage(req, res) {
function setupPage(req: Request, res: Response) {
if (sqlInit.isDbInitialized()) {
if (utils.isElectron()) {
const windowService = require('../services/window');
@ -37,6 +38,6 @@ function setupPage(req, res) {
});
}
module.exports = {
export = {
setupPage
};

View File

@ -8,19 +8,10 @@ import passwordEncryptionService = require('./encryption/password_encryption');
import config = require('./config');
import passwordService = require('./encryption/password');
import type { NextFunction, Request, Response } from 'express';
import { AppRequest } from '../routes/route-interface';
const noAuthentication = config.General && config.General.noAuthentication === true;
interface AppRequest extends Request {
headers: {
authorization?: string;
"trilium-cred"?: string;
}
session: {
loggedIn: boolean;
}
}
function checkAuth(req: AppRequest, res: Response, next: NextFunction) {
if (!sqlInit.isDbInitialized()) {
res.redirect("setup");

View File

@ -1,7 +1,11 @@
import { Request, Response } from "express";
import AbstractBeccaEntity = require("../becca/entities/abstract_becca_entity");
import BNote = require("../becca/entities/bnote");
export interface ApiParams {
startNote?: BNote;
originEntity?: AbstractBeccaEntity<any>;
pathParams?: string[],
req?: Request,
res?: Response
}

View File

@ -28,7 +28,7 @@ interface OpmlOutline {
outline: OpmlOutline[];
}
async function importOpml(taskContext: TaskContext, fileBuffer: Buffer, parentNote: BNote) {
async function importOpml(taskContext: TaskContext, fileBuffer: string | Buffer, parentNote: BNote) {
const xml = await new Promise<OpmlXml>(function(resolve, reject)
{
parseString(fileBuffer, function (err: any, result: OpmlXml) {

View File

@ -7,7 +7,7 @@ import log = require('./log');
const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`;
let sessionSecret;
let sessionSecret: string;
const ENCODING = "ascii";