mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Merge pull request #44 from TriliumNext/feature/typescript_backend_8
Convert backend to TypeScript (80% -> 81%)
This commit is contained in:
		
							
								
								
									
										57
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										57
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -91,12 +91,15 @@ | |||||||
|         "@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/csurf": "^1.11.5", | ||||||
|         "@types/escape-html": "^1.0.4", |         "@types/escape-html": "^1.0.4", | ||||||
|         "@types/express": "^4.17.21", |         "@types/express": "^4.17.21", | ||||||
|  |         "@types/express-session": "^1.18.0", | ||||||
|         "@types/html": "^1.0.4", |         "@types/html": "^1.0.4", | ||||||
|         "@types/ini": "^4.1.0", |         "@types/ini": "^4.1.0", | ||||||
|         "@types/jsdom": "^21.1.6", |         "@types/jsdom": "^21.1.6", | ||||||
|         "@types/mime-types": "^2.1.4", |         "@types/mime-types": "^2.1.4", | ||||||
|  |         "@types/multer": "^1.4.11", | ||||||
|         "@types/node": "^20.11.19", |         "@types/node": "^20.11.19", | ||||||
|         "@types/sanitize-html": "^2.11.0", |         "@types/sanitize-html": "^2.11.0", | ||||||
|         "@types/sax": "^1.2.7", |         "@types/sax": "^1.2.7", | ||||||
| @@ -1233,6 +1236,15 @@ | |||||||
|         "@types/node": "*" |         "@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": { |     "node_modules/@types/d3-scale": { | ||||||
|       "version": "4.0.8", |       "version": "4.0.8", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", |       "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", | ||||||
| @@ -1315,6 +1327,15 @@ | |||||||
|         "@types/send": "*" |         "@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": { |     "node_modules/@types/fs-extra": { | ||||||
|       "version": "9.0.13", |       "version": "9.0.13", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", |       "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", |       "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", | ||||||
|       "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" |       "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": { |     "node_modules/@types/node": { | ||||||
|       "version": "20.11.19", |       "version": "20.11.19", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", |       "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", | ||||||
| @@ -14211,6 +14241,15 @@ | |||||||
|         "@types/node": "*" |         "@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": { |     "@types/d3-scale": { | ||||||
|       "version": "4.0.8", |       "version": "4.0.8", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", |       "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", | ||||||
| @@ -14293,6 +14332,15 @@ | |||||||
|         "@types/send": "*" |         "@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": { |     "@types/fs-extra": { | ||||||
|       "version": "9.0.13", |       "version": "9.0.13", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", |       "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", |       "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", | ||||||
|       "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" |       "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": { |     "@types/node": { | ||||||
|       "version": "20.11.19", |       "version": "20.11.19", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", |       "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", | ||||||
|   | |||||||
| @@ -112,12 +112,15 @@ | |||||||
|     "@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/csurf": "^1.11.5", | ||||||
|     "@types/escape-html": "^1.0.4", |     "@types/escape-html": "^1.0.4", | ||||||
|     "@types/express": "^4.17.21", |     "@types/express": "^4.17.21", | ||||||
|  |     "@types/express-session": "^1.18.0", | ||||||
|     "@types/html": "^1.0.4", |     "@types/html": "^1.0.4", | ||||||
|     "@types/ini": "^4.1.0", |     "@types/ini": "^4.1.0", | ||||||
|     "@types/jsdom": "^21.1.6", |     "@types/jsdom": "^21.1.6", | ||||||
|     "@types/mime-types": "^2.1.4", |     "@types/mime-types": "^2.1.4", | ||||||
|  |     "@types/multer": "^1.4.11", | ||||||
|     "@types/node": "^20.11.19", |     "@types/node": "^20.11.19", | ||||||
|     "@types/sanitize-html": "^2.11.0", |     "@types/sanitize-html": "^2.11.0", | ||||||
|     "@types/sax": "^1.2.7", |     "@types/sax": "^1.2.7", | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ const favicon = require('serve-favicon'); | |||||||
| const cookieParser = require('cookie-parser'); | const cookieParser = require('cookie-parser'); | ||||||
| const helmet = require('helmet'); | const helmet = require('helmet'); | ||||||
| const compression = require('compression'); | const compression = require('compression'); | ||||||
| const sessionParser = require('./routes/session_parser.js'); | const sessionParser = require('./routes/session_parser'); | ||||||
| const utils = require('./services/utils'); | const utils = require('./services/utils'); | ||||||
|  |  | ||||||
| require('./services/handlers'); | require('./services/handlers'); | ||||||
| @@ -37,10 +37,10 @@ app.use(`/robots.txt`, express.static(path.join(__dirname, 'public/robots.txt')) | |||||||
| app.use(sessionParser); | 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.js').register(app); | require('./routes/assets').register(app); | ||||||
| require('./routes/routes.js').register(app); | require('./routes/routes.js').register(app); | ||||||
| require('./routes/custom.js').register(app); | require('./routes/custom').register(app); | ||||||
| require('./routes/error_handlers.js').register(app); | require('./routes/error_handlers').register(app); | ||||||
|  |  | ||||||
| // triggers sync timer | // triggers sync timer | ||||||
| require('./services/sync'); | require('./services/sync'); | ||||||
|   | |||||||
| @@ -14,11 +14,12 @@ import ValidationError = require('../../errors/validation_error'); | |||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import BNote = require('../../becca/entities/bnote'); | import BNote = require('../../becca/entities/bnote'); | ||||||
| import BAttachment = require('../../becca/entities/battachment'); | 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 note = becca.getNoteOrThrow(req.params.noteId); | ||||||
|  |  | ||||||
|     const file = (req as any).file; |     const file = req.file; | ||||||
|     note.saveRevision(); |     note.saveRevision(); | ||||||
|  |  | ||||||
|     note.mime = file.mimetype.toLowerCase(); |     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 attachment = becca.getAttachmentOrThrow(req.params.attachmentId); | ||||||
|     const file = (req as any).file; |     const file = req.file; | ||||||
|  |  | ||||||
|     attachment.getNote().saveRevision(); |     attachment.getNote().saveRevision(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import fs = require('fs'); | |||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import BNote = require('../../becca/entities/bnote'); | import BNote = require('../../becca/entities/bnote'); | ||||||
| import BRevision = require('../../becca/entities/brevision'); | import BRevision = require('../../becca/entities/brevision'); | ||||||
|  | import { AppRequest } from '../route-interface'; | ||||||
|  |  | ||||||
| function returnImageFromNote(req: Request, res: Response) { | function returnImageFromNote(req: Request, res: Response) { | ||||||
|     const image = becca.getNote(req.params.noteId); |     const image = becca.getNote(req.params.noteId); | ||||||
| @@ -81,9 +82,9 @@ function returnAttachedImage(req: Request, res: Response) { | |||||||
|     res.send(attachment.getContent()); |     res.send(attachment.getContent()); | ||||||
| } | } | ||||||
|  |  | ||||||
| function updateImage(req: Request) { | function updateImage(req: AppRequest) { | ||||||
|     const {noteId} = req.params; |     const {noteId} = req.params; | ||||||
|     const {file} = (req as any); |     const {file} = req; | ||||||
|  |  | ||||||
|     const note = becca.getNoteOrThrow(noteId); |     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); |     imageService.updateImage(noteId, file.buffer, file.originalname); | ||||||
|  |  | ||||||
|     return { uploaded: true }; |     return { uploaded: true }; | ||||||
|   | |||||||
| @@ -13,8 +13,9 @@ import TaskContext = require('../../services/task_context'); | |||||||
| import ValidationError = require('../../errors/validation_error'); | import ValidationError = require('../../errors/validation_error'); | ||||||
| import { Request } from 'express'; | import { Request } from 'express'; | ||||||
| import BNote = require('../../becca/entities/bnote'); | 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 { parentNoteId } = req.params; | ||||||
|     const { taskId, last } = req.body; |     const { taskId, last } = req.body; | ||||||
|  |  | ||||||
| @@ -27,7 +28,7 @@ async function importNotesToBranch(req: Request) { | |||||||
|         replaceUnderscoresWithSpaces: req.body.replaceUnderscoresWithSpaces !== 'false' |         replaceUnderscoresWithSpaces: req.body.replaceUnderscoresWithSpaces !== 'false' | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const file = (req as any).file; |     const file = req.file; | ||||||
|  |  | ||||||
|     if (!file) { |     if (!file) { | ||||||
|         throw new ValidationError("No file has been uploaded"); |         throw new ValidationError("No file has been uploaded"); | ||||||
| @@ -49,7 +50,7 @@ async function importNotesToBranch(req: Request) { | |||||||
|     const taskContext = TaskContext.getInstance(taskId, 'importNotes', options); |     const taskContext = TaskContext.getInstance(taskId, 'importNotes', options); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|         if (extension === '.zip' && options.explodeArchives) { |         if (extension === '.zip' && options.explodeArchives && typeof file.buffer !== "string") { | ||||||
|             note = await zipImportService.importZip(taskContext, file.buffer, parentNote); |             note = await zipImportService.importZip(taskContext, file.buffer, parentNote); | ||||||
|         } else if (extension === '.opml' && options.explodeArchives) { |         } else if (extension === '.opml' && options.explodeArchives) { | ||||||
|             const importResult = await opmlImportService.importOpml(taskContext, file.buffer, parentNote); |             const importResult = await opmlImportService.importOpml(taskContext, file.buffer, parentNote); | ||||||
| @@ -96,7 +97,7 @@ async function importNotesToBranch(req: Request) { | |||||||
|     return note.getPojo(); |     return note.getPojo(); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function importAttachmentsToNote(req: Request) { | async function importAttachmentsToNote(req: AppRequest) { | ||||||
|     const { parentNoteId } = req.params; |     const { parentNoteId } = req.params; | ||||||
|     const { taskId, last } = req.body; |     const { taskId, last } = req.body; | ||||||
|  |  | ||||||
| @@ -104,7 +105,7 @@ async function importAttachmentsToNote(req: Request) { | |||||||
|         shrinkImages: req.body.shrinkImages !== 'false', |         shrinkImages: req.body.shrinkImages !== 'false', | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const file = (req as any).file; |     const file = req.file; | ||||||
|  |  | ||||||
|     if (!file) { |     if (!file) { | ||||||
|         throw new ValidationError("No file has been uploaded"); |         throw new ValidationError("No file has been uploaded"); | ||||||
|   | |||||||
| @@ -13,8 +13,9 @@ import sql = require('../../services/sql'); | |||||||
| import ws = require('../../services/ws'); | import ws = require('../../services/ws'); | ||||||
| import etapiTokenService = require('../../services/etapi_tokens'); | import etapiTokenService = require('../../services/etapi_tokens'); | ||||||
| import { Request } from 'express'; | import { Request } from 'express'; | ||||||
|  | import { AppRequest } from '../route-interface'; | ||||||
|  |  | ||||||
| function loginSync(req: Request) { | function loginSync(req: AppRequest) { | ||||||
|     if (!sqlInit.schemaExists()) { |     if (!sqlInit.schemaExists()) { | ||||||
|         return [500, { message: "DB schema does not exist, can't sync." }]; |         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." }]; |         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 { |     return { | ||||||
|         instanceId: instanceId, |         instanceId: instanceId, | ||||||
|   | |||||||
| @@ -6,13 +6,17 @@ import noteService = require('../../services/notes'); | |||||||
| import sanitize_attribute_name = require('../../services/sanitize_attribute_name'); | import sanitize_attribute_name = require('../../services/sanitize_attribute_name'); | ||||||
| import specialNotesService = require('../../services/special_notes'); | import specialNotesService = require('../../services/special_notes'); | ||||||
| import { Request } from 'express'; | import { Request } from 'express'; | ||||||
|  | import { AppRequest } from '../route-interface'; | ||||||
|  |  | ||||||
| function uploadImage(req: Request) { | function uploadImage(req: AppRequest) { | ||||||
|     const file = (req as any).file; |     const file = req.file; | ||||||
|  |  | ||||||
|     if (!["image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"].includes(file.mimetype)) { |     if (!["image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"].includes(file.mimetype)) { | ||||||
|         return [400, `Unknown image type: ${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); |     const uploadedImageType = imageType(file.buffer); | ||||||
|     if (!uploadedImageType) { |     if (!uploadedImageType) { | ||||||
| @@ -20,14 +24,10 @@ function uploadImage(req: Request) { | |||||||
|     } |     } | ||||||
|     const originalName = `Sender image.${uploadedImageType.ext}`; |     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"]; |         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 parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']); | ||||||
|  |  | ||||||
|     const { note, noteId } = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true); |     const { note, noteId } = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true); | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| const assetPath = require('../services/asset_path'); | import assetPath = require('../services/asset_path'); | ||||||
| const path = require("path"); | import path = require("path"); | ||||||
| const express = require("express"); | import express = require("express"); | ||||||
| const env = require('../services/env'); | 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()) { |     if (!env.isDev()) { | ||||||
|         options = { |         options = { | ||||||
|             maxAge: '1y', |             maxAge: '1y', | ||||||
| @@ -13,7 +14,7 @@ const persistentCacheStatic = (root, options) => { | |||||||
|     return express.static(root, options); |     return express.static(root, options); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function register(app) { | function register(app: express.Application) { | ||||||
|     const srcRoot = path.join(__dirname, '..'); |     const srcRoot = path.join(__dirname, '..'); | ||||||
|     app.use(`/${assetPath}/app`, persistentCacheStatic(path.join(srcRoot, 'public/app'))); |     app.use(`/${assetPath}/app`, persistentCacheStatic(path.join(srcRoot, 'public/app'))); | ||||||
|     app.use(`/${assetPath}/app-dist`, persistentCacheStatic(path.join(srcRoot, 'public/app-dist'))); |     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/'))); |     app.use(`/${assetPath}/node_modules/panzoom/dist/`, persistentCacheStatic(path.join(srcRoot, '..', 'node_modules/panzoom/dist/'))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | export = { | ||||||
|     register |     register | ||||||
| }; | }; | ||||||
| @@ -1,21 +1,22 @@ | |||||||
| const log = require('../services/log'); | import log = require('../services/log'); | ||||||
| const fileService = require('./api/files'); | import fileService = require('./api/files'); | ||||||
| const scriptService = require('../services/script'); | import scriptService = require('../services/script'); | ||||||
| const cls = require('../services/cls'); | import cls = require('../services/cls'); | ||||||
| const sql = require('../services/sql'); | import sql = require('../services/sql'); | ||||||
| const becca = require('../becca/becca'); | 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
 |     // express puts content after first slash into 0 index element
 | ||||||
| 
 | 
 | ||||||
|     const path = req.params.path + req.params[0]; |     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)); |     const attrs = attributeIds.map(attrId => becca.getAttribute(attrId)); | ||||||
| 
 | 
 | ||||||
|     for (const attr of attrs) { |     for (const attr of attrs) { | ||||||
|         if (!attr.value.trim()) { |         if (!attr?.value.trim()) { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -25,7 +26,7 @@ function handleRequest(req, res) { | |||||||
|         try { |         try { | ||||||
|             match = path.match(regex); |             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}`); |             log.error(`Testing path for label '${attr.attributeId}', regex '${attr.value}' failed with error: ${e.message}, stack: ${e.stack}`); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| @@ -46,7 +47,7 @@ function handleRequest(req, res) { | |||||||
|                     res |                     res | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|             catch (e) { |             catch (e: any) { | ||||||
|                 log.error(`Custom handler '${note.noteId}' failed with: ${e.message}, ${e.stack}`); |                 log.error(`Custom handler '${note.noteId}' failed with: ${e.message}, ${e.stack}`); | ||||||
| 
 | 
 | ||||||
|                 res.setHeader("Content-Type", "text/plain") |                 res.setHeader("Content-Type", "text/plain") | ||||||
| @@ -72,10 +73,10 @@ function handleRequest(req, res) { | |||||||
|         .send(message); |         .send(message); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function register(router) { | function register(router: Router) { | ||||||
|     // explicitly no CSRF middleware since it's meant to allow integration from external services
 |     // 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(req); | ||||||
|         cls.namespace.bindEmitter(res); |         cls.namespace.bindEmitter(res); | ||||||
| 
 | 
 | ||||||
| @@ -83,6 +84,6 @@ function register(router) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | export = { | ||||||
|     register |     register | ||||||
| }; | }; | ||||||
| @@ -1,6 +1,17 @@ | |||||||
|  | import { Application } from "express"; | ||||||
|  | 
 | ||||||
| const ipcMain = require('electron').ipcMain; | 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) => { |     ipcMain.on('server-request', (event, arg) => { | ||||||
|         const req = { |         const req = { | ||||||
|             url: arg.url, |             url: arg.url, | ||||||
| @@ -12,9 +23,9 @@ function init(app) { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         const respHeaders = {}; |         const respHeaders: Record<string, string> = {}; | ||||||
| 
 | 
 | ||||||
|         const res = { |         const res: Response = { | ||||||
|             statusCode: 200, |             statusCode: 200, | ||||||
|             getHeader: name => respHeaders[name], |             getHeader: name => respHeaders[name], | ||||||
|             setHeader: (name, value) => { |             setHeader: (name, value) => { | ||||||
| @@ -45,4 +56,4 @@ function init(app) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = init; | export = init; | ||||||
| @@ -1,7 +1,8 @@ | |||||||
| const log = require('../services/log'); | import { Application, NextFunction, Request, Response } from 'express'; | ||||||
|  | import log = require('../services/log'); | ||||||
| 
 | 
 | ||||||
| function register(app) { | function register(app: Application) { | ||||||
|     app.use((err, req, res, next) => { |     app.use((err: any, req: Request, res: Response, next: NextFunction) => { | ||||||
|         if (err.code !== 'EBADCSRFTOKEN') { |         if (err.code !== 'EBADCSRFTOKEN') { | ||||||
|             return next(err); |             return next(err); | ||||||
|         } |         } | ||||||
| @@ -16,12 +17,12 @@ function register(app) { | |||||||
|     // catch 404 and forward to error handler
 |     // catch 404 and forward to error handler
 | ||||||
|     app.use((req, res, next) => { |     app.use((req, res, next) => { | ||||||
|         const err = new Error(`Router not found for request ${req.method} ${req.url}`); |         const err = new Error(`Router not found for request ${req.method} ${req.url}`); | ||||||
|         err.status = 404; |         (err as any).status = 404; | ||||||
|         next(err); |         next(err); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // error handler
 |     // error handler
 | ||||||
|     app.use((err, req, res, next) => { |     app.use((err: any, req: Request, res: Response, next: NextFunction) => { | ||||||
|         if (err && err.message && ( |         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(".js.map")) | ||||||
|             || (err.message.includes("Router not found for request") && err.message.includes(".css.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 |     register | ||||||
| }; | }; | ||||||
| @@ -1,18 +1,19 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const sql = require('../services/sql'); | import sql = require('../services/sql'); | ||||||
| const attributeService = require('../services/attributes'); | import attributeService = require('../services/attributes'); | ||||||
| const config = require('../services/config'); | import config = require('../services/config'); | ||||||
| const optionService = require('../services/options'); | import optionService = require('../services/options'); | ||||||
| const log = require('../services/log'); | import log = require('../services/log'); | ||||||
| const env = require('../services/env'); | import env = require('../services/env'); | ||||||
| const utils = require('../services/utils'); | import utils = require('../services/utils'); | ||||||
| const protectedSessionService = require('../services/protected_session'); | import protectedSessionService = require('../services/protected_session'); | ||||||
| const packageJson = require('../../package.json'); | import packageJson = require('../../package.json'); | ||||||
| const assetPath = require('../services/asset_path'); | import assetPath = require('../services/asset_path'); | ||||||
| const appPath = require('../services/app_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 options = optionService.getOptionMap(); | ||||||
| 
 | 
 | ||||||
|     const view = (!utils.isElectron() && req.cookies['trilium-device'] === 'mobile') |     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') { |     if (theme === 'light') { | ||||||
|         return false; // light theme is always loaded as baseline
 |         return false; // light theme is always loaded as baseline
 | ||||||
|     } else if (theme === 'dark') { |     } else if (theme === 'dark') { | ||||||
| @@ -63,6 +64,6 @@ function getAppCssNoteIds() { | |||||||
|     return attributeService.getNotesWithLabel('appCss').map(note => note.noteId); |     return attributeService.getNotesWithLabel('appCss').map(note => note.noteId); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | export = { | ||||||
|     index |     index | ||||||
| }; | }; | ||||||
| @@ -1,15 +1,17 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const utils = require('../services/utils'); | import utils = require('../services/utils'); | ||||||
| const optionService = require('../services/options'); | import optionService = require('../services/options'); | ||||||
| const myScryptService = require('../services/encryption/my_scrypt'); | import myScryptService = require('../services/encryption/my_scrypt'); | ||||||
| const log = require('../services/log'); | import log = require('../services/log'); | ||||||
| const passwordService = require('../services/encryption/password'); | import passwordService = require('../services/encryption/password'); | ||||||
| const assetPath = require('../services/asset_path'); | import assetPath = require('../services/asset_path'); | ||||||
| const appPath = require('../services/app_path'); | import appPath = require('../services/app_path'); | ||||||
| const ValidationError = require('../errors/validation_error'); | 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', { |     res.render('login', { | ||||||
|         failedAuth: false, |         failedAuth: false, | ||||||
|         assetPath: assetPath, |         assetPath: assetPath, | ||||||
| @@ -17,7 +19,7 @@ function loginPage(req, res) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function setPasswordPage(req, res) { | function setPasswordPage(req: Request, res: Response) { | ||||||
|     res.render('set_password', { |     res.render('set_password', { | ||||||
|         error: false, |         error: false, | ||||||
|         assetPath: assetPath, |         assetPath: assetPath, | ||||||
| @@ -25,7 +27,7 @@ function setPasswordPage(req, res) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function setPassword(req, res) { | function setPassword(req: Request, res: Response) { | ||||||
|     if (passwordService.isPasswordSet()) { |     if (passwordService.isPasswordSet()) { | ||||||
|         throw new ValidationError("Password has been already set"); |         throw new ValidationError("Password has been already set"); | ||||||
|     } |     } | ||||||
| @@ -55,7 +57,7 @@ function setPassword(req, res) { | |||||||
|     res.redirect('login'); |     res.redirect('login'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function login(req, res) { | function login(req: AppRequest, res: Response) { | ||||||
|     const guessedPassword = req.body.password; |     const guessedPassword = req.body.password; | ||||||
| 
 | 
 | ||||||
|     if (verifyPassword(guessedPassword)) { |     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 hashed_password = utils.fromBase64(optionService.getOption('passwordVerificationHash')); | ||||||
| 
 | 
 | ||||||
|     const guess_hashed = myScryptService.getVerificationHash(guessedPassword); |     const guess_hashed = myScryptService.getVerificationHash(guessedPassword); | ||||||
| @@ -91,7 +93,7 @@ function verifyPassword(guessedPassword) { | |||||||
|     return guess_hashed.equals(hashed_password); |     return guess_hashed.equals(hashed_password); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function logout(req, res) { | function logout(req: AppRequest, res: Response) { | ||||||
|     req.session.regenerate(() => { |     req.session.regenerate(() => { | ||||||
|         req.session.loggedIn = false; |         req.session.loggedIn = false; | ||||||
| 
 | 
 | ||||||
| @@ -100,7 +102,7 @@ function logout(req, res) { | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | export = { | ||||||
|     loginPage, |     loginPage, | ||||||
|     setPasswordPage, |     setPasswordPage, | ||||||
|     setPassword, |     setPassword, | ||||||
							
								
								
									
										20
									
								
								src/routes/route-interface.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/routes/route-interface.ts
									
									
									
									
									
										Normal 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; | ||||||
|  | } | ||||||
| @@ -18,8 +18,8 @@ const ValidationError = require('../errors/validation_error'); | |||||||
|  |  | ||||||
| // page routes | // page routes | ||||||
| const setupRoute = require('./setup'); | const setupRoute = require('./setup'); | ||||||
| const loginRoute = require('./login.js'); | const loginRoute = require('./login'); | ||||||
| const indexRoute = require('./index.js'); | const indexRoute = require('./index'); | ||||||
|  |  | ||||||
| // API routes | // API routes | ||||||
| const treeApiRoute = require('./api/tree'); | const treeApiRoute = require('./api/tree'); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| const session = require("express-session"); | import session = require("express-session"); | ||||||
| const sessionSecret = require('../services/session_secret'); | import sessionSecret = require('../services/session_secret'); | ||||||
| const dataDir = require('../services/data_dir'); | import dataDir = require('../services/data_dir'); | ||||||
| const FileStore = require('session-file-store')(session); | const FileStore = require('session-file-store')(session); | ||||||
| 
 | 
 | ||||||
| const sessionParser = session({ | const sessionParser = session({ | ||||||
| @@ -19,4 +19,4 @@ const sessionParser = session({ | |||||||
|     }) |     }) | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| module.exports = sessionParser; | export = sessionParser; | ||||||
| @@ -1,12 +1,13 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const sqlInit = require('../services/sql_init'); | import sqlInit = require('../services/sql_init'); | ||||||
| const setupService = require('../services/setup'); | import setupService = require('../services/setup'); | ||||||
| const utils = require('../services/utils'); | import utils = require('../services/utils'); | ||||||
| const assetPath = require('../services/asset_path'); | import assetPath = require('../services/asset_path'); | ||||||
| const appPath = require('../services/app_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 (sqlInit.isDbInitialized()) { | ||||||
|         if (utils.isElectron()) { |         if (utils.isElectron()) { | ||||||
|             const windowService = require('../services/window'); |             const windowService = require('../services/window'); | ||||||
| @@ -37,6 +38,6 @@ function setupPage(req, res) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | export = { | ||||||
|     setupPage |     setupPage | ||||||
| }; | }; | ||||||
| @@ -8,19 +8,10 @@ import passwordEncryptionService = require('./encryption/password_encryption'); | |||||||
| import config = require('./config'); | import config = require('./config'); | ||||||
| import passwordService = require('./encryption/password'); | import passwordService = require('./encryption/password'); | ||||||
| import type { NextFunction, Request, Response } from 'express'; | import type { NextFunction, Request, Response } from 'express'; | ||||||
|  | import { AppRequest } from '../routes/route-interface'; | ||||||
|  |  | ||||||
| const noAuthentication = config.General && config.General.noAuthentication === true; | 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) { | function checkAuth(req: AppRequest, res: Response, next: NextFunction) { | ||||||
|     if (!sqlInit.isDbInitialized()) { |     if (!sqlInit.isDbInitialized()) { | ||||||
|         res.redirect("setup"); |         res.redirect("setup"); | ||||||
|   | |||||||
| @@ -1,7 +1,11 @@ | |||||||
|  | import { Request, Response } from "express"; | ||||||
| import AbstractBeccaEntity = require("../becca/entities/abstract_becca_entity"); | import AbstractBeccaEntity = require("../becca/entities/abstract_becca_entity"); | ||||||
| import BNote = require("../becca/entities/bnote"); | import BNote = require("../becca/entities/bnote"); | ||||||
|  |  | ||||||
| export interface ApiParams { | export interface ApiParams { | ||||||
|     startNote?: BNote; |     startNote?: BNote; | ||||||
|     originEntity?: AbstractBeccaEntity<any>; |     originEntity?: AbstractBeccaEntity<any>; | ||||||
|  |     pathParams?: string[], | ||||||
|  |     req?: Request, | ||||||
|  |     res?: Response | ||||||
| } | } | ||||||
| @@ -28,7 +28,7 @@ interface OpmlOutline { | |||||||
|     outline: 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) |     const xml = await new Promise<OpmlXml>(function(resolve, reject) | ||||||
|     { |     { | ||||||
|         parseString(fileBuffer, function (err: any, result: OpmlXml) { |         parseString(fileBuffer, function (err: any, result: OpmlXml) { | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import log = require('./log'); | |||||||
|  |  | ||||||
| const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`; | const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`; | ||||||
|  |  | ||||||
| let sessionSecret; | let sessionSecret: string; | ||||||
|  |  | ||||||
| const ENCODING = "ascii"; | const ENCODING = "ascii"; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user