mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	refactor(services): use named imports from utils
This commit is contained in:
		| @@ -6,7 +6,7 @@ import log from "./log.js"; | |||||||
| import os from "os"; | import os from "os"; | ||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
| import config from "./config.js"; | import config from "./config.js"; | ||||||
| import utils from "./utils.js"; | import { isElectron } from "./utils.js"; | ||||||
|  |  | ||||||
| const template = `[Desktop Entry] | const template = `[Desktop Entry] | ||||||
| Type=Application | Type=Application | ||||||
| @@ -23,7 +23,7 @@ Terminal=false | |||||||
|  * We overwrite this file during every run as it might have been updated. |  * We overwrite this file during every run as it might have been updated. | ||||||
|  */ |  */ | ||||||
| function installLocalAppIcon() { | function installLocalAppIcon() { | ||||||
|     if (!utils.isElectron() |     if (!isElectron() | ||||||
|         || ["win32", "darwin"].includes(os.platform()) |         || ["win32", "darwin"].includes(os.platform()) | ||||||
|         || (config.General && config.General.noDesktopIcon)) { |         || (config.General && config.General.noDesktopIcon)) { | ||||||
|         return; |         return; | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| import etapiTokenService from "./etapi_tokens.js"; | import etapiTokenService from "./etapi_tokens.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import sqlInit from "./sql_init.js"; | import sqlInit from "./sql_init.js"; | ||||||
| import utils from "./utils.js"; | import { isElectron } from "./utils.js"; | ||||||
| import passwordEncryptionService from "./encryption/password_encryption.js"; | import passwordEncryptionService from "./encryption/password_encryption.js"; | ||||||
| import config from "./config.js"; | import config from "./config.js"; | ||||||
| import passwordService from "./encryption/password.js"; | import passwordService from "./encryption/password.js"; | ||||||
| @@ -15,7 +15,7 @@ function checkAuth(req: Request, res: Response, next: NextFunction) { | |||||||
|     if (!sqlInit.isDbInitialized()) { |     if (!sqlInit.isDbInitialized()) { | ||||||
|         res.redirect("setup"); |         res.redirect("setup"); | ||||||
|     } |     } | ||||||
|     else if (!req.session.loggedIn && !utils.isElectron() && !noAuthentication) { |     else if (!req.session.loggedIn && !isElectron() && !noAuthentication) { | ||||||
|         res.redirect("login"); |         res.redirect("login"); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
| @@ -26,7 +26,7 @@ function checkAuth(req: Request, res: Response, next: NextFunction) { | |||||||
| // for electron things which need network stuff | // for electron things which need network stuff | ||||||
| //  currently, we're doing that for file upload because handling form data seems to be difficult | //  currently, we're doing that for file upload because handling form data seems to be difficult | ||||||
| function checkApiAuthOrElectron(req: Request, res: Response, next: NextFunction) { | function checkApiAuthOrElectron(req: Request, res: Response, next: NextFunction) { | ||||||
|     if (!req.session.loggedIn && !utils.isElectron() && !noAuthentication) { |     if (!req.session.loggedIn && !isElectron() && !noAuthentication) { | ||||||
|         reject(req, res, "Logged in session not found"); |         reject(req, res, "Logged in session not found"); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
| @@ -53,7 +53,7 @@ function checkAppInitialized(req: Request, res: Response, next: NextFunction) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function checkPasswordSet(req: Request, res: Response, next: NextFunction) { | function checkPasswordSet(req: Request, res: Response, next: NextFunction) { | ||||||
|     if (!utils.isElectron() && !passwordService.isPasswordSet()) { |     if (!isElectron() && !passwordService.isPasswordSet()) { | ||||||
|         res.redirect("set-password"); |         res.redirect("set-password"); | ||||||
|     } else { |     } else { | ||||||
|         next(); |         next(); | ||||||
| @@ -61,7 +61,7 @@ function checkPasswordSet(req: Request, res: Response, next: NextFunction) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function checkPasswordNotSet(req: Request, res: Response, next: NextFunction) { | function checkPasswordNotSet(req: Request, res: Response, next: NextFunction) { | ||||||
|     if (!utils.isElectron() && passwordService.isPasswordSet()) { |     if (!isElectron() && passwordService.isPasswordSet()) { | ||||||
|         res.redirect("login"); |         res.redirect("login"); | ||||||
|     } else { |     } else { | ||||||
|         next(); |         next(); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import noteService from "./notes.js"; | import noteService from "./notes.js"; | ||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import utils from "./utils.js"; | import { randomString, escapeHtml, unescapeHtml } from "./utils.js"; | ||||||
| import attributeService from "./attributes.js"; | import attributeService from "./attributes.js"; | ||||||
| import dateNoteService from "./date_notes.js"; | import dateNoteService from "./date_notes.js"; | ||||||
| import treeService from "./tree.js"; | import treeService from "./tree.js"; | ||||||
| @@ -549,9 +549,9 @@ function BackendScriptApi(this: Api, currentNote: BNote, apiParams: ApiParams) { | |||||||
|  |  | ||||||
|     this.setNoteToParent = treeService.setNoteToParent; |     this.setNoteToParent = treeService.setNoteToParent; | ||||||
|     this.transactional = sql.transactional; |     this.transactional = sql.transactional; | ||||||
|     this.randomString = utils.randomString; |     this.randomString = randomString; | ||||||
|     this.escapeHtml = utils.escapeHtml; |     this.escapeHtml = escapeHtml; | ||||||
|     this.unescapeHtml = utils.unescapeHtml; |     this.unescapeHtml = unescapeHtml; | ||||||
|     this.sql = sql; |     this.sql = sql; | ||||||
|     this.getAppInfo = () => appInfo; |     this.getAppInfo = () => appInfo; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import becca from "../becca/becca.js"; | import becca from "../becca/becca.js"; | ||||||
| import NotFoundError from "../errors/not_found_error.js"; | import NotFoundError from "../errors/not_found_error.js"; | ||||||
| import protectedSessionService from "./protected_session.js"; | import protectedSessionService from "./protected_session.js"; | ||||||
| import utils from "./utils.js"; | import { hash } from "./utils.js"; | ||||||
| import type { Blob } from "./blob-interface.js"; | import type { Blob } from "./blob-interface.js"; | ||||||
|  |  | ||||||
| function getBlobPojo(entityName: string, entityId: string, opts?: { preview: boolean }) { | function getBlobPojo(entityName: string, entityId: string, opts?: { preview: boolean }) { | ||||||
| @@ -51,7 +51,7 @@ function processContent(content: Buffer | string | null, isProtected: boolean, i | |||||||
| } | } | ||||||
|  |  | ||||||
| function calculateContentHash({blobId, content}: Blob) { | function calculateContentHash({blobId, content}: Blob) { | ||||||
|     return utils.hash(`${blobId}|${content.toString()}`); |     return hash(`${blobId}|${content.toString()}`); | ||||||
| } | } | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import log from "./log.js"; | |||||||
| import becca from "../becca/becca.js"; | import becca from "../becca/becca.js"; | ||||||
| import cloningService from "./cloning.js"; | import cloningService from "./cloning.js"; | ||||||
| import branchService from "./branches.js"; | import branchService from "./branches.js"; | ||||||
| import utils from "./utils.js"; | import { randomString } from "./utils.js"; | ||||||
| import eraseService from "./erase.js"; | import eraseService from "./erase.js"; | ||||||
| import BNote from "../becca/entities/bnote.js"; | import BNote from "../becca/entities/bnote.js"; | ||||||
|  |  | ||||||
| @@ -32,7 +32,7 @@ const ACTION_HANDLERS: Record<string, ActionHandler> = { | |||||||
|         note.addRelation(action.relationName, action.targetNoteId); |         note.addRelation(action.relationName, action.targetNoteId); | ||||||
|     }, |     }, | ||||||
|     deleteNote: (action, note) => { |     deleteNote: (action, note) => { | ||||||
|         const deleteId = `searchbulkaction-${utils.randomString(10)}`; |         const deleteId = `searchbulkaction-${randomString(10)}`; | ||||||
|  |  | ||||||
|         note.deleteNote(deleteId); |         note.deleteNote(deleteId); | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import fs from "fs"; | |||||||
| import themeNames from "./code_block_theme_names.json" with { type: "json" } | import themeNames from "./code_block_theme_names.json" with { type: "json" } | ||||||
| import { t } from "i18next"; | import { t } from "i18next"; | ||||||
| import { join } from "path"; | import { join } from "path"; | ||||||
| import utils from "./utils.js"; | import { isElectron, getResourceDir } from "./utils.js"; | ||||||
| import env from "./env.js"; | import env from "./env.js"; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -31,7 +31,7 @@ interface ColorTheme { | |||||||
|  * @returns the supported themes, grouped. |  * @returns the supported themes, grouped. | ||||||
|  */ |  */ | ||||||
| export function listSyntaxHighlightingThemes() { | export function listSyntaxHighlightingThemes() { | ||||||
|     const path = join(utils.getResourceDir(), getStylesDirectory()); |     const path = join(getResourceDir(), getStylesDirectory()); | ||||||
|     const systemThemes = readThemesFromFileSystem(path); |     const systemThemes = readThemesFromFileSystem(path); | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
| @@ -46,7 +46,7 @@ export function listSyntaxHighlightingThemes() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function getStylesDirectory() { | function getStylesDirectory() { | ||||||
|     if (utils.isElectron() && !env.isDev()) { |     if (isElectron() && !env.isDev()) { | ||||||
|         return "styles"; |         return "styles"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import utils from "./utils.js"; | import { hash } from "./utils.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import eraseService from "./erase.js"; | import eraseService from "./erase.js"; | ||||||
|  |  | ||||||
| @@ -43,7 +43,7 @@ function getEntityHashes() { | |||||||
|  |  | ||||||
|     for (const entityHashMap of Object.values(hashMap)) { |     for (const entityHashMap of Object.values(hashMap)) { | ||||||
|         for (const key in entityHashMap) { |         for (const key in entityHashMap) { | ||||||
|             entityHashMap[key] = utils.hash(entityHashMap[key]); |             entityHashMap[key] = hash(entityHashMap[key]); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| import sql from "../sql.js"; | import sql from "../sql.js"; | ||||||
| import optionService from "../options.js"; | import optionService from "../options.js"; | ||||||
| import myScryptService from "./my_scrypt.js"; | import myScryptService from "./my_scrypt.js"; | ||||||
| import utils from "../utils.js"; | import { randomSecureToken, toBase64 } from "../utils.js"; | ||||||
| import passwordEncryptionService from "./password_encryption.js"; | import passwordEncryptionService from "./password_encryption.js"; | ||||||
|  |  | ||||||
| function isPasswordSet() { | function isPasswordSet() { | ||||||
| @@ -25,10 +25,10 @@ function changePassword(currentPassword: string, newPassword: string) { | |||||||
|     sql.transactional(() => { |     sql.transactional(() => { | ||||||
|         const decryptedDataKey = passwordEncryptionService.getDataKey(currentPassword); |         const decryptedDataKey = passwordEncryptionService.getDataKey(currentPassword); | ||||||
|  |  | ||||||
|         optionService.setOption('passwordVerificationSalt', utils.randomSecureToken(32)); |         optionService.setOption('passwordVerificationSalt', randomSecureToken(32)); | ||||||
|         optionService.setOption('passwordDerivedKeySalt', utils.randomSecureToken(32)); |         optionService.setOption('passwordDerivedKeySalt', randomSecureToken(32)); | ||||||
|  |  | ||||||
|         const newPasswordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(newPassword)); |         const newPasswordVerificationKey = toBase64(myScryptService.getVerificationHash(newPassword)); | ||||||
|  |  | ||||||
|         if (decryptedDataKey) { |         if (decryptedDataKey) { | ||||||
|             // TODO: what should happen if the decrypted data key is null? |             // TODO: what should happen if the decrypted data key is null? | ||||||
| @@ -48,16 +48,16 @@ function setPassword(password: string) { | |||||||
|         throw new Error("Password is set already. Either change it or perform 'reset password' first."); |         throw new Error("Password is set already. Either change it or perform 'reset password' first."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true); |     optionService.createOption('passwordVerificationSalt', randomSecureToken(32), true); | ||||||
|     optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true); |     optionService.createOption('passwordDerivedKeySalt', randomSecureToken(32), true); | ||||||
|  |  | ||||||
|     const passwordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(password)); |     const passwordVerificationKey = toBase64(myScryptService.getVerificationHash(password)); | ||||||
|     optionService.createOption('passwordVerificationHash', passwordVerificationKey, true); |     optionService.createOption('passwordVerificationHash', passwordVerificationKey, true); | ||||||
|  |  | ||||||
|     // passwordEncryptionService expects these options to already exist |     // passwordEncryptionService expects these options to already exist | ||||||
|     optionService.createOption('encryptedDataKey', '', true); |     optionService.createOption('encryptedDataKey', '', true); | ||||||
|  |  | ||||||
|     passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16)); |     passwordEncryptionService.setDataKey(password, randomSecureToken(16)); | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|         success: true |         success: true | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| import optionService from "../options.js"; | import optionService from "../options.js"; | ||||||
| import myScryptService from "./my_scrypt.js"; | import myScryptService from "./my_scrypt.js"; | ||||||
| import utils from "../utils.js"; | import { toBase64 } from "../utils.js"; | ||||||
| import dataEncryptionService from "./data_encryption.js"; | import dataEncryptionService from "./data_encryption.js"; | ||||||
|  |  | ||||||
| function verifyPassword(password: string) { | function verifyPassword(password: string) { | ||||||
|     const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password)); |     const givenPasswordHash = toBase64(myScryptService.getVerificationHash(password)); | ||||||
|  |  | ||||||
|     const dbPasswordHash = optionService.getOptionOrNull('passwordVerificationHash'); |     const dbPasswordHash = optionService.getOptionOrNull('passwordVerificationHash'); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import sql from "./sql.js"; | |||||||
| import dateUtils from "./date_utils.js"; | import dateUtils from "./date_utils.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import cls from "./cls.js"; | import cls from "./cls.js"; | ||||||
| import utils from "./utils.js"; | import { randomString } from "./utils.js"; | ||||||
| import instanceId from "./instance_id.js"; | import instanceId from "./instance_id.js"; | ||||||
| import becca from "../becca/becca.js"; | import becca from "../becca/becca.js"; | ||||||
| import blobService from "../services/blob.js"; | import blobService from "../services/blob.js"; | ||||||
| @@ -30,7 +30,7 @@ function putEntityChange(origEntityChange: EntityChange) { | |||||||
|     delete ec.id; |     delete ec.id; | ||||||
|  |  | ||||||
|     if (!ec.changeId) { |     if (!ec.changeId) { | ||||||
|         ec.changeId = utils.randomString(12); |         ec.changeId = randomString(12); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ec.componentId = ec.componentId || cls.getComponentId() || "NA"; // NA = not available |     ec.componentId = ec.componentId || cls.getComponentId() || "NA"; // NA = not available | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import becca from "../becca/becca.js"; | import becca from "../becca/becca.js"; | ||||||
| import utils from "./utils.js"; | import { fromBase64, randomSecureToken } from "./utils.js"; | ||||||
| import BEtapiToken from "../becca/entities/betapi_token.js"; | import BEtapiToken from "../becca/entities/betapi_token.js"; | ||||||
| import crypto from "crypto"; | import crypto from "crypto"; | ||||||
|  |  | ||||||
| @@ -12,7 +12,7 @@ function getTokenHash(token: crypto.BinaryLike) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function createToken(tokenName: string) { | function createToken(tokenName: string) { | ||||||
|     const token = utils.randomSecureToken(32); |     const token = randomSecureToken(32); | ||||||
|     const tokenHash = getTokenHash(token); |     const tokenHash = getTokenHash(token); | ||||||
|  |  | ||||||
|     const etapiToken = new BEtapiToken({ |     const etapiToken = new BEtapiToken({ | ||||||
| @@ -34,7 +34,7 @@ function parseAuthToken(auth: string | undefined) { | |||||||
|         // allow also basic auth format for systems which allow this type of authentication |         // allow also basic auth format for systems which allow this type of authentication | ||||||
|         // expect ETAPI token in the password field, require "etapi" username |         // expect ETAPI token in the password field, require "etapi" username | ||||||
|         // https://github.com/zadam/trilium/issues/3181 |         // https://github.com/zadam/trilium/issues/3181 | ||||||
|         const basicAuthStr = utils.fromBase64(auth.substring(6)).toString("utf-8"); |         const basicAuthStr = fromBase64(auth.substring(6)).toString("utf-8"); | ||||||
|         const basicAuthChunks = basicAuthStr.split(":"); |         const basicAuthChunks = basicAuthStr.split(":"); | ||||||
|  |  | ||||||
|         if (basicAuthChunks.length !== 2) { |         if (basicAuthChunks.length !== 2) { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| import utils from "../utils.js"; | import { getContentDisposition, stripTags } from "../utils.js"; | ||||||
| import becca from "../../becca/becca.js"; | import becca from "../../becca/becca.js"; | ||||||
| import TaskContext from "../task_context.js"; | import TaskContext from "../task_context.js"; | ||||||
| import BBranch from "../../becca/entities/bbranch.js"; | import BBranch from "../../becca/entities/bbranch.js"; | ||||||
| @@ -58,7 +58,7 @@ function exportToOpml(taskContext: TaskContext, branch: BBranch, version: string | |||||||
|  |  | ||||||
|     const filename = `${branch.prefix ? (`${branch.prefix} - `) : ''}${note.title}.opml`; |     const filename = `${branch.prefix ? (`${branch.prefix} - `) : ''}${note.title}.opml`; | ||||||
|  |  | ||||||
|     res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); |     res.setHeader('Content-Disposition', getContentDisposition(filename)); | ||||||
|     res.setHeader('Content-Type', 'text/x-opml'); |     res.setHeader('Content-Type', 'text/x-opml'); | ||||||
|  |  | ||||||
|     res.write(`<?xml version="1.0" encoding="UTF-8"?> |     res.write(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
| @@ -83,7 +83,7 @@ function prepareText(text: string) { | |||||||
|     const newLines = text.replace(/(<p[^>]*>|<br\s*\/?>)/g, '\n') |     const newLines = text.replace(/(<p[^>]*>|<br\s*\/?>)/g, '\n') | ||||||
|         .replace(/ /g, ' '); // nbsp isn't in XML standard (only HTML) |         .replace(/ /g, ' '); // nbsp isn't in XML standard (only HTML) | ||||||
|  |  | ||||||
|     const stripped = utils.stripTags(newLines); |     const stripped = stripTags(newLines); | ||||||
|  |  | ||||||
|     const escaped = escapeXmlAttribute(stripped); |     const escaped = escapeXmlAttribute(stripped); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| import mimeTypes from "mime-types"; | import mimeTypes from "mime-types"; | ||||||
| import html from "html"; | import html from "html"; | ||||||
| import utils from "../utils.js"; | import { getContentDisposition, escapeHtml } from "../utils.js"; | ||||||
| import mdService from "./md.js"; | import mdService from "./md.js"; | ||||||
| import becca from "../../becca/becca.js"; | import becca from "../../becca/becca.js"; | ||||||
| import TaskContext from "../task_context.js"; | import TaskContext from "../task_context.js"; | ||||||
| @@ -61,7 +61,7 @@ function exportSingleNote(taskContext: TaskContext, branch: BBranch, format: "ht | |||||||
|  |  | ||||||
|     const fileName = `${note.title}.${extension}`; |     const fileName = `${note.title}.${extension}`; | ||||||
|  |  | ||||||
|     res.setHeader('Content-Disposition', utils.getContentDisposition(fileName)); |     res.setHeader('Content-Disposition', getContentDisposition(fileName)); | ||||||
|     res.setHeader('Content-Type', `${mime}; charset=UTF-8`); |     res.setHeader('Content-Type', `${mime}; charset=UTF-8`); | ||||||
|  |  | ||||||
|     res.send(payload); |     res.send(payload); | ||||||
| @@ -119,7 +119,7 @@ function inlineAttachments(content: string) { | |||||||
|         const base64Content = attachmentContent.toString('base64'); |         const base64Content = attachmentContent.toString('base64'); | ||||||
|         const hrefValue = `data:${attachment.mime};base64,${base64Content}`; |         const hrefValue = `data:${attachment.mime};base64,${base64Content}`; | ||||||
|  |  | ||||||
|         return `href="${hrefValue}" download="${utils.escapeHtml(attachment.title)}"`; |         return `href="${hrefValue}" download="${escapeHtml(attachment.title)}"`; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     return content; |     return content; | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import path from "path"; | |||||||
| import mimeTypes from "mime-types"; | import mimeTypes from "mime-types"; | ||||||
| import mdService from "./md.js"; | import mdService from "./md.js"; | ||||||
| import packageInfo from "../../../package.json" with { type: "json" }; | import packageInfo from "../../../package.json" with { type: "json" }; | ||||||
| import utils from "../utils.js"; | import { getContentDisposition, escapeHtml } from "../utils.js"; | ||||||
| import protectedSessionService from "../protected_session.js"; | import protectedSessionService from "../protected_session.js"; | ||||||
| import sanitize from "sanitize-filename"; | import sanitize from "sanitize-filename"; | ||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
| @@ -311,7 +311,7 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h | |||||||
|                 if (!noteMeta?.notePath?.length) { throw new Error("Missing note path."); } |                 if (!noteMeta?.notePath?.length) { throw new Error("Missing note path."); } | ||||||
|  |  | ||||||
|                 const cssUrl = `${"../".repeat(noteMeta.notePath.length - 1)}style.css`; |                 const cssUrl = `${"../".repeat(noteMeta.notePath.length - 1)}style.css`; | ||||||
|                 const htmlTitle = utils.escapeHtml(title); |                 const htmlTitle = escapeHtml(title); | ||||||
|  |  | ||||||
|                 // <base> element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809 |                 // <base> element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809 | ||||||
|                 content = `<html> |                 content = `<html> | ||||||
| @@ -411,7 +411,7 @@ ${markdownContent}`; | |||||||
|         function saveNavigationInner(meta: NoteMeta) { |         function saveNavigationInner(meta: NoteMeta) { | ||||||
|             let html = '<li>'; |             let html = '<li>'; | ||||||
|  |  | ||||||
|             const escapedTitle = utils.escapeHtml(`${meta.prefix ? `${meta.prefix} - ` : ''}${meta.title}`); |             const escapedTitle = escapeHtml(`${meta.prefix ? `${meta.prefix} - ` : ''}${meta.title}`); | ||||||
|  |  | ||||||
|             if (meta.dataFileName && meta.noteId) { |             if (meta.dataFileName && meta.noteId) { | ||||||
|                 const targetUrl = getNoteTargetUrl(meta.noteId, rootMeta); |                 const targetUrl = getNoteTargetUrl(meta.noteId, rootMeta); | ||||||
| @@ -568,7 +568,7 @@ ${markdownContent}`; | |||||||
|     const zipFileName = `${branch.prefix ? `${branch.prefix} - ` : ""}${note.getTitleOrProtected()}.zip`; |     const zipFileName = `${branch.prefix ? `${branch.prefix} - ` : ""}${note.getTitleOrProtected()}.zip`; | ||||||
|  |  | ||||||
|     if (setHeaders && "setHeader" in res) { |     if (setHeaders && "setHeader" in res) { | ||||||
|         res.setHeader('Content-Disposition', utils.getContentDisposition(zipFileName)); |         res.setHeader('Content-Disposition', getContentDisposition(zipFileName)); | ||||||
|         res.setHeader('Content-Type', 'application/zip'); |         res.setHeader('Content-Type', 'application/zip'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| import config from "./config.js"; | import config from "./config.js"; | ||||||
| import utils from "./utils.js"; | import { isElectron } from "./utils.js"; | ||||||
|  |  | ||||||
| function getHost() { | function getHost() { | ||||||
|     const envHost = process.env.TRILIUM_HOST; |     const envHost = process.env.TRILIUM_HOST; | ||||||
|     if (envHost && !utils.isElectron) { |     if (envHost && !isElectron) { | ||||||
|         return envHost; |         return envHost; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import sax from "sax"; | |||||||
| import stream from "stream"; | import stream from "stream"; | ||||||
| import { Throttle } from 'stream-throttle'; | import { Throttle } from 'stream-throttle'; | ||||||
| import log from "../log.js"; | import log from "../log.js"; | ||||||
| import utils from "../utils.js"; | import { md5, escapeHtml, fromBase64 } from "../utils.js"; | ||||||
| import sql from "../sql.js"; | import sql from "../sql.js"; | ||||||
| import noteService from "../notes.js"; | import noteService from "../notes.js"; | ||||||
| import imageService from "../image.js"; | import imageService from "../image.js"; | ||||||
| @@ -291,10 +291,10 @@ function importEnex(taskContext: TaskContext, file: File, parentNote: BNote): Pr | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (typeof resource.content === "string") { |             if (typeof resource.content === "string") { | ||||||
|                 resource.content = utils.fromBase64(resource.content); |                 resource.content = fromBase64(resource.content); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             const hash = utils.md5(resource.content); |             const hash = md5(resource.content); | ||||||
|  |  | ||||||
|             // skip all checked/unchecked checkboxes from OneNote |             // skip all checked/unchecked checkboxes from OneNote | ||||||
|             if (['74de5d3d1286f01bac98d32a09f601d9', |             if (['74de5d3d1286f01bac98d32a09f601d9', | ||||||
| @@ -332,7 +332,7 @@ function importEnex(taskContext: TaskContext, file: File, parentNote: BNote): Pr | |||||||
|  |  | ||||||
|                 taskContext.increaseProgressCount(); |                 taskContext.increaseProgressCount(); | ||||||
|  |  | ||||||
|                 const resourceLink = `<a href="#root/${resourceNote.noteId}">${utils.escapeHtml(resource.title)}</a>`; |                 const resourceLink = `<a href="#root/${resourceNote.noteId}">${escapeHtml(resource.title)}</a>`; | ||||||
|  |  | ||||||
|                 content = (content || "").replace(mediaRegex, resourceLink); |                 content = (content || "").replace(mediaRegex, resourceLink); | ||||||
|             }; |             }; | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import imageService from "../../services/image.js"; | |||||||
| import protectedSessionService from "../protected_session.js"; | import protectedSessionService from "../protected_session.js"; | ||||||
| import markdownService from "./markdown.js"; | import markdownService from "./markdown.js"; | ||||||
| import mimeService from "./mime.js"; | import mimeService from "./mime.js"; | ||||||
| import utils from "../../services/utils.js"; | import { getNoteTitle } from "../../services/utils.js"; | ||||||
| import importUtils from "./utils.js"; | import importUtils from "./utils.js"; | ||||||
| import htmlSanitizer from "../html_sanitizer.js"; | import htmlSanitizer from "../html_sanitizer.js"; | ||||||
| import { File } from "./common.js"; | import { File } from "./common.js"; | ||||||
| @@ -68,7 +68,7 @@ function importFile(taskContext: TaskContext, file: File, parentNote: BNote) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function importCodeNote(taskContext: TaskContext, file: File, parentNote: BNote) { | function importCodeNote(taskContext: TaskContext, file: File, parentNote: BNote) { | ||||||
|     const title = utils.getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); |     const title = getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); | ||||||
|     const content = file.buffer.toString("utf-8"); |     const content = file.buffer.toString("utf-8"); | ||||||
|     const detectedMime = mimeService.getMime(file.originalname) || file.mimetype; |     const detectedMime = mimeService.getMime(file.originalname) || file.mimetype; | ||||||
|     const mime = mimeService.normalizeMimeType(detectedMime); |     const mime = mimeService.normalizeMimeType(detectedMime); | ||||||
| @@ -88,7 +88,7 @@ function importCodeNote(taskContext: TaskContext, file: File, parentNote: BNote) | |||||||
| } | } | ||||||
|  |  | ||||||
| function importPlainText(taskContext: TaskContext, file: File, parentNote: BNote) { | function importPlainText(taskContext: TaskContext, file: File, parentNote: BNote) { | ||||||
|     const title = utils.getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); |     const title = getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); | ||||||
|     const plainTextContent = file.buffer.toString("utf-8"); |     const plainTextContent = file.buffer.toString("utf-8"); | ||||||
|     const htmlContent = convertTextToHtml(plainTextContent); |     const htmlContent = convertTextToHtml(plainTextContent); | ||||||
|  |  | ||||||
| @@ -125,7 +125,7 @@ function convertTextToHtml(text: string) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function importMarkdown(taskContext: TaskContext, file: File, parentNote: BNote) { | function importMarkdown(taskContext: TaskContext, file: File, parentNote: BNote) { | ||||||
|     const title = utils.getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); |     const title = getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); | ||||||
|  |  | ||||||
|     const markdownContent = file.buffer.toString("utf-8"); |     const markdownContent = file.buffer.toString("utf-8"); | ||||||
|     let htmlContent = markdownService.renderToHtml(markdownContent, title); |     let htmlContent = markdownService.renderToHtml(markdownContent, title); | ||||||
| @@ -154,7 +154,7 @@ function importHtml(taskContext: TaskContext, file: File, parentNote: BNote) { | |||||||
|     // Try to get title from HTML first, fall back to filename |     // Try to get title from HTML first, fall back to filename | ||||||
|     // We do this before sanitization since that turns all <h1>s into <h2> |     // We do this before sanitization since that turns all <h1>s into <h2> | ||||||
|     const htmlTitle = importUtils.extractHtmlTitle(content); |     const htmlTitle = importUtils.extractHtmlTitle(content); | ||||||
|     const title = htmlTitle || utils.getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); |     const title = htmlTitle || getNoteTitle(file.originalname, !!taskContext.data?.replaceUnderscoresWithSpaces); | ||||||
|  |  | ||||||
|     content = importUtils.handleH1(content, title); |     content = importUtils.handleH1(content, title); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| import BAttribute from "../../becca/entities/battribute.js"; | import BAttribute from "../../becca/entities/battribute.js"; | ||||||
| import utils from "../../services/utils.js"; | import { removeTextFileExtension, newEntityId, getNoteTitle } from "../../services/utils.js"; | ||||||
| import log from "../../services/log.js"; | import log from "../../services/log.js"; | ||||||
| import noteService from "../../services/notes.js"; | import noteService from "../../services/notes.js"; | ||||||
| import attributeService from "../../services/attributes.js"; | import attributeService from "../../services/attributes.js"; | ||||||
| @@ -51,7 +51,7 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!noteIdMap[origNoteId]) { |         if (!noteIdMap[origNoteId]) { | ||||||
|             noteIdMap[origNoteId] = utils.newEntityId(); |             noteIdMap[origNoteId] = newEntityId(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return noteIdMap[origNoteId]; |         return noteIdMap[origNoteId]; | ||||||
| @@ -64,7 +64,7 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!attachmentIdMap[origAttachmentId]) { |         if (!attachmentIdMap[origAttachmentId]) { | ||||||
|             attachmentIdMap[origAttachmentId] = utils.newEntityId(); |             attachmentIdMap[origAttachmentId] = newEntityId(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return attachmentIdMap[origAttachmentId]; |         return attachmentIdMap[origAttachmentId]; | ||||||
| @@ -152,13 +152,13 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo | |||||||
|  |  | ||||||
|         // in case we lack metadata, we treat e.g. "Programming.html" and "Programming" as the same note |         // in case we lack metadata, we treat e.g. "Programming.html" and "Programming" as the same note | ||||||
|         // (one data file, the other directory for children) |         // (one data file, the other directory for children) | ||||||
|         const filePathNoExt = utils.removeTextFileExtension(filePath); |         const filePathNoExt = removeTextFileExtension(filePath); | ||||||
|  |  | ||||||
|         if (filePathNoExt in createdPaths) { |         if (filePathNoExt in createdPaths) { | ||||||
|             return createdPaths[filePathNoExt]; |             return createdPaths[filePathNoExt]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const noteId = utils.newEntityId(); |         const noteId = newEntityId(); | ||||||
|  |  | ||||||
|         createdPaths[filePathNoExt] = noteId; |         createdPaths[filePathNoExt] = noteId; | ||||||
|  |  | ||||||
| @@ -225,7 +225,7 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const noteTitle = utils.getNoteTitle(filePath, !!taskContext.data?.replaceUnderscoresWithSpaces, noteMeta); |         const noteTitle = getNoteTitle(filePath, !!taskContext.data?.replaceUnderscoresWithSpaces, noteMeta); | ||||||
|         const parentNoteId = getParentNoteId(filePath, parentNoteMeta); |         const parentNoteId = getParentNoteId(filePath, parentNoteMeta); | ||||||
|  |  | ||||||
|         if (!parentNoteId) { |         if (!parentNoteId) { | ||||||
| @@ -466,7 +466,7 @@ async function importZip(taskContext: TaskContext, fileBuffer: Buffer, importRoo | |||||||
|             content = content.toString("utf-8"); |             content = content.toString("utf-8"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const noteTitle = utils.getNoteTitle(filePath, taskContext.data?.replaceUnderscoresWithSpaces || false, noteMeta); |         const noteTitle = getNoteTitle(filePath, taskContext.data?.replaceUnderscoresWithSpaces || false, noteMeta); | ||||||
|  |  | ||||||
|         content = processNoteContent(noteMeta, type, mime, content, noteTitle || "", filePath); |         content = processNoteContent(noteMeta, type, mime, content, noteTitle || "", filePath); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import utils from "./utils.js"; | import { randomString } from "./utils.js"; | ||||||
|  |  | ||||||
| const instanceId = utils.randomString(12); | const instanceId = randomString(12); | ||||||
|  |  | ||||||
| export default instanceId; | export default instanceId; | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import backupService from "./backup.js"; | |||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import fs from "fs-extra"; | import fs from "fs-extra"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import utils from "./utils.js"; | import { crash } from "./utils.js"; | ||||||
| import resourceDir from "./resource_dir.js"; | import resourceDir from "./resource_dir.js"; | ||||||
| import appInfo from "./app_info.js"; | import appInfo from "./app_info.js"; | ||||||
| import cls from "./cls.js"; | import cls from "./cls.js"; | ||||||
| @@ -20,7 +20,7 @@ async function migrate() { | |||||||
|     if (currentDbVersion < 214) { |     if (currentDbVersion < 214) { | ||||||
|         log.error("Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version."); |         log.error("Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version."); | ||||||
|  |  | ||||||
|         await utils.crash(); |         await crash(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -83,7 +83,7 @@ async function migrate() { | |||||||
|                 log.error(`error during migration to version ${mig.dbVersion}: ${e.stack}`); |                 log.error(`error during migration to version ${mig.dbVersion}: ${e.stack}`); | ||||||
|                 log.error("migration failed, crashing hard"); // this is not very user-friendly :-/ |                 log.error("migration failed, crashing hard"); // this is not very user-friendly :-/ | ||||||
|  |  | ||||||
|                 utils.crash(); |                 crash(); | ||||||
|                 break; // crash() is sometimes async |                 break; // crash() is sometimes async | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -135,7 +135,7 @@ async function migrateIfNecessary() { | |||||||
|     if (currentDbVersion > appInfo.dbVersion && process.env.TRILIUM_IGNORE_DB_VERSION !== 'true') { |     if (currentDbVersion > appInfo.dbVersion && process.env.TRILIUM_IGNORE_DB_VERSION !== 'true') { | ||||||
|         log.error(`Current DB version ${currentDbVersion} is newer than the current DB version ${appInfo.dbVersion}, which means that it was created by a newer and incompatible version of Trilium. Upgrade to the latest version of Trilium to resolve this issue.`); |         log.error(`Current DB version ${currentDbVersion} is newer than the current DB version ${appInfo.dbVersion}, which means that it was created by a newer and incompatible version of Trilium. Upgrade to the latest version of Trilium to resolve this issue.`); | ||||||
|  |  | ||||||
|         await utils.crash(); |         await crash(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!isDbUpToDate()) { |     if (!isDbUpToDate()) { | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import eventService from "./events.js"; | |||||||
| import cls from "../services/cls.js"; | import cls from "../services/cls.js"; | ||||||
| import protectedSessionService from "../services/protected_session.js"; | import protectedSessionService from "../services/protected_session.js"; | ||||||
| import log from "../services/log.js"; | import log from "../services/log.js"; | ||||||
| import utils from "../services/utils.js"; | import { newEntityId, isString, unescapeHtml, quoteRegex, toMap } from "../services/utils.js"; | ||||||
| import revisionService from "./revisions.js"; | import revisionService from "./revisions.js"; | ||||||
| import request from "./request.js"; | import request from "./request.js"; | ||||||
| import path from "path"; | import path from "path"; | ||||||
| @@ -465,7 +465,7 @@ function findRelationMapLinks(content: string, foundLinks: FoundLink[]) { | |||||||
| const imageUrlToAttachmentIdMapping: Record<string, string> = {}; | const imageUrlToAttachmentIdMapping: Record<string, string> = {}; | ||||||
|  |  | ||||||
| async function downloadImage(noteId: string, imageUrl: string) { | async function downloadImage(noteId: string, imageUrl: string) { | ||||||
|     const unescapedUrl = utils.unescapeHtml(imageUrl); |     const unescapedUrl = unescapeHtml(imageUrl); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|         let imageBuffer: Buffer; |         let imageBuffer: Buffer; | ||||||
| @@ -508,7 +508,7 @@ async function downloadImage(noteId: string, imageUrl: string) { | |||||||
| const downloadImagePromises: Record<string, Promise<void>> = {}; | const downloadImagePromises: Record<string, Promise<void>> = {}; | ||||||
|  |  | ||||||
| function replaceUrl(content: string, url: string, attachment: Attachment) { | function replaceUrl(content: string, url: string, attachment: Attachment) { | ||||||
|     const quotedUrl = utils.quoteRegex(url); |     const quotedUrl = quoteRegex(url); | ||||||
|  |  | ||||||
|     return content.replace(new RegExp(`\\s+src=[\"']${quotedUrl}[\"']`, "ig"), ` src="api/attachments/${attachment.attachmentId}/image/${encodeURIComponent(attachment.title)}"`); |     return content.replace(new RegExp(`\\s+src=[\"']${quotedUrl}[\"']`, "ig"), ` src="api/attachments/${attachment.attachmentId}/image/${encodeURIComponent(attachment.title)}"`); | ||||||
| } | } | ||||||
| @@ -744,7 +744,7 @@ function updateNoteData(noteId: string, content: string, attachments: Attachment | |||||||
|     note.setContent(newContent, { forceFrontendReload }); |     note.setContent(newContent, { forceFrontendReload }); | ||||||
|  |  | ||||||
|     if (attachments?.length > 0) { |     if (attachments?.length > 0) { | ||||||
|         const existingAttachmentsByTitle = utils.toMap(note.getAttachments({includeContentLength: false}), 'title'); |         const existingAttachmentsByTitle = toMap(note.getAttachments({includeContentLength: false}), 'title'); | ||||||
|  |  | ||||||
|         for (const {attachmentId, role, mime, title, position, content} of attachments) { |         for (const {attachmentId, role, mime, title, position, content} of attachments) { | ||||||
|             if (attachmentId || !(title in existingAttachmentsByTitle)) { |             if (attachmentId || !(title in existingAttachmentsByTitle)) { | ||||||
| @@ -886,7 +886,7 @@ async function asyncPostProcessContent(note: BNote, content: string | Buffer) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (note.hasStringContent() && !utils.isString(content)) { |     if (note.hasStringContent() && !isString(content)) { | ||||||
|         content = content.toString(); |         content = content.toString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1035,7 +1035,7 @@ function getNoteIdMapping(origNote: BNote) { | |||||||
|  |  | ||||||
|     // pregenerate new noteIds since we'll need to fix relation references even for not yet created notes |     // pregenerate new noteIds since we'll need to fix relation references even for not yet created notes | ||||||
|     for (const origNoteId of origNote.getDescendantNoteIds()) { |     for (const origNoteId of origNote.getDescendantNoteIds()) { | ||||||
|         noteIdMapping[origNoteId] = utils.newEntityId(); |         noteIdMapping[origNoteId] = newEntityId(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return noteIdMapping; |     return noteIdMapping; | ||||||
|   | |||||||
| @@ -1,15 +1,15 @@ | |||||||
| import optionService from "./options.js"; | import optionService from "./options.js"; | ||||||
| import type { OptionMap } from "./options.js"; | import type { OptionMap } from "./options.js"; | ||||||
| import appInfo from "./app_info.js"; | import appInfo from "./app_info.js"; | ||||||
| import utils from "./utils.js"; | import { randomSecureToken } from "./utils.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import dateUtils from "./date_utils.js"; | import dateUtils from "./date_utils.js"; | ||||||
| import keyboardActions from "./keyboard_actions.js"; | import keyboardActions from "./keyboard_actions.js"; | ||||||
| import { KeyboardShortcutWithRequiredActionName } from './keyboard_actions_interface.js'; | import { KeyboardShortcutWithRequiredActionName } from './keyboard_actions_interface.js'; | ||||||
|  |  | ||||||
| function initDocumentOptions() { | function initDocumentOptions() { | ||||||
|     optionService.createOption('documentId', utils.randomSecureToken(16), false); |     optionService.createOption('documentId', randomSecureToken(16), false); | ||||||
|     optionService.createOption('documentSecret', utils.randomSecureToken(16), false); |     optionService.createOption('documentSecret', randomSecureToken(16), false); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import config from "./config.js"; | import config from "./config.js"; | ||||||
| import utils from "./utils.js"; | import { isElectron } from "./utils.js"; | ||||||
| import env from "./env.js"; | import env from "./env.js"; | ||||||
| import dataDir from "./data_dir.js"; | import dataDir from "./data_dir.js"; | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ let port: number; | |||||||
|  |  | ||||||
| if (process.env.TRILIUM_PORT) { | if (process.env.TRILIUM_PORT) { | ||||||
|     port = parseAndValidate(process.env.TRILIUM_PORT, "environment variable TRILIUM_PORT"); |     port = parseAndValidate(process.env.TRILIUM_PORT, "environment variable TRILIUM_PORT"); | ||||||
| } else if (utils.isElectron()) { | } else if (isElectron()) { | ||||||
|     port = env.isDev() ? 37740 : 37840; |     port = env.isDev() ? 37740 : 37840; | ||||||
| } else { | } else { | ||||||
|     port = parseAndValidate(config['Network']['port'] || '3000', `Network.port in ${dataDir.CONFIG_INI_PATH}`); |     port = parseAndValidate(config['Network']['port'] || '3000', `Network.port in ${dataDir.CONFIG_INI_PATH}`); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| import utils from "./utils.js"; | import { isElectron } from "./utils.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import url from "url"; | import url from "url"; | ||||||
| import syncOptions from "./sync_options.js"; | import syncOptions from "./sync_options.js"; | ||||||
| @@ -210,7 +210,7 @@ async function getProxyAgent(opts: ClientOpts) { | |||||||
| async function getClient(opts: ClientOpts): Promise<Client> { | async function getClient(opts: ClientOpts): Promise<Client> { | ||||||
|     // it's not clear how to explicitly configure proxy (as opposed to system proxy), |     // it's not clear how to explicitly configure proxy (as opposed to system proxy), | ||||||
|     // so in that case, we always use node's modules |     // so in that case, we always use node's modules | ||||||
|     if (utils.isElectron() && !opts.proxy) { |     if (isElectron() && !opts.proxy) { | ||||||
|         return (await import('electron')).net as Client; |         return (await import('electron')).net as Client; | ||||||
|     } else { |     } else { | ||||||
|         const {protocol} = url.parse(opts.url); |         const {protocol} = url.parse(opts.url); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import utils from "./utils.js"; | import { toObject } from "./utils.js"; | ||||||
| import BackendScriptApi from "./backend_script_api.js"; | import BackendScriptApi from "./backend_script_api.js"; | ||||||
| import BNote from "../becca/entities/bnote.js"; | import BNote from "../becca/entities/bnote.js"; | ||||||
| import { ApiParams } from './backend_script_api_interface.js'; | import { ApiParams } from './backend_script_api_interface.js'; | ||||||
| @@ -16,8 +16,8 @@ class ScriptContext { | |||||||
|     constructor(allNotes: BNote[], apiParams: ApiParams) { |     constructor(allNotes: BNote[], apiParams: ApiParams) { | ||||||
|         this.allNotes = allNotes; |         this.allNotes = allNotes; | ||||||
|         this.modules = {}; |         this.modules = {}; | ||||||
|         this.notes = utils.toObject(allNotes, note => [note.noteId, note]); |         this.notes = toObject(allNotes, note => [note.noteId, note]); | ||||||
|         this.apis = utils.toObject(allNotes, note => [note.noteId, new BackendScriptApi(note, apiParams)]); |         this.apis = toObject(allNotes, note => [note.noteId, new BackendScriptApi(note, apiParams)]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     require(moduleNoteIds: string[]) { |     require(moduleNoteIds: string[]) { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import log from "../../log.js"; | |||||||
| import becca from "../../../becca/becca.js"; | import becca from "../../../becca/becca.js"; | ||||||
| import protectedSessionService from "../../protected_session.js"; | import protectedSessionService from "../../protected_session.js"; | ||||||
| import striptags from "striptags"; | import striptags from "striptags"; | ||||||
| import utils from "../../utils.js"; | import { normalize } from "../../utils.js"; | ||||||
| import sql from "../../sql.js"; | import sql from "../../sql.js"; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -125,7 +125,7 @@ class NoteContentFulltextExp extends Expression { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     preprocessContent(content: string | Buffer, type: string, mime: string) { |     preprocessContent(content: string | Buffer, type: string, mime: string) { | ||||||
|         content = utils.normalize(content.toString()); |         content = normalize(content.toString()); | ||||||
|  |  | ||||||
|         if (type === 'text' && mime === 'text/html') { |         if (type === 'text' && mime === 'text/html') { | ||||||
|             if (!this.raw && content.length < 20000) { // striptags is slow for very large notes |             if (!this.raw && content.length < 20000) { // striptags is slow for very large notes | ||||||
| @@ -183,7 +183,7 @@ class NoteContentFulltextExp extends Expression { | |||||||
|             const topicsString = topicsArray.join(", "); |             const topicsString = topicsArray.join(", "); | ||||||
|              |              | ||||||
|          |          | ||||||
|             content = utils.normalize(topicsString.toString()); |             content = normalize(topicsString.toString()); | ||||||
|           }  |           }  | ||||||
|         else if (type === 'canvas' && mime === 'application/json') { |         else if (type === 'canvas' && mime === 'application/json') { | ||||||
|             interface Element { |             interface Element { | ||||||
| @@ -199,7 +199,7 @@ class NoteContentFulltextExp extends Expression { | |||||||
|                 .filter((element: Element) => element.type === 'text' && element.text) // Filter for 'text' type elements with a 'text' property |                 .filter((element: Element) => element.type === 'text' && element.text) // Filter for 'text' type elements with a 'text' property | ||||||
|                 .map((element: Element) => element.text!); // Use `!` to assert `text` is defined after filtering |                 .map((element: Element) => element.text!); // Use `!` to assert `text` is defined after filtering | ||||||
|  |  | ||||||
|             content =utils.normalize(texts.toString()) |             content = normalize(texts.toString()) | ||||||
|           } |           } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import SearchContext from "../search_context.js"; | |||||||
| import Expression from "./expression.js"; | import Expression from "./expression.js"; | ||||||
| import NoteSet from "../note_set.js"; | import NoteSet from "../note_set.js"; | ||||||
| import becca from "../../../becca/becca.js"; | import becca from "../../../becca/becca.js"; | ||||||
| import utils from "../../utils.js"; | import { normalize } from "../../utils.js"; | ||||||
| import beccaService from "../../../becca/becca_service.js"; | import beccaService from "../../../becca/becca_service.js"; | ||||||
|  |  | ||||||
| class NoteFlatTextExp extends Expression { | class NoteFlatTextExp extends Expression { | ||||||
| @@ -61,8 +61,8 @@ class NoteFlatTextExp extends Expression { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             for (const attribute of note.getOwnedAttributes()) { |             for (const attribute of note.getOwnedAttributes()) { | ||||||
|                 const normalizedName = utils.normalize(attribute.name); |                 const normalizedName = normalize(attribute.name); | ||||||
|                 const normalizedValue = utils.normalize(attribute.value); |                 const normalizedValue = normalize(attribute.value); | ||||||
|  |  | ||||||
|                 for (const token of remainingTokens) { |                 for (const token of remainingTokens) { | ||||||
|                     if (normalizedName.includes(token) || normalizedValue.includes(token)) { |                     if (normalizedName.includes(token) || normalizedValue.includes(token)) { | ||||||
| @@ -72,7 +72,7 @@ class NoteFlatTextExp extends Expression { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             for (const parentNote of note.parents) { |             for (const parentNote of note.parents) { | ||||||
|                 const title = utils.normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); |                 const title = normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); | ||||||
|                 const foundTokens = foundAttrTokens.slice(); |                 const foundTokens = foundAttrTokens.slice(); | ||||||
|  |  | ||||||
|                 for (const token of remainingTokens) { |                 for (const token of remainingTokens) { | ||||||
| @@ -109,8 +109,8 @@ class NoteFlatTextExp extends Expression { | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 for (const attribute of note.ownedAttributes) { |                 for (const attribute of note.ownedAttributes) { | ||||||
|                     if (utils.normalize(attribute.name).includes(token) |                     if (normalize(attribute.name).includes(token) | ||||||
|                         || utils.normalize(attribute.value).includes(token)) { |                         || normalize(attribute.value).includes(token)) { | ||||||
|  |  | ||||||
|                         foundAttrTokens.push(token); |                         foundAttrTokens.push(token); | ||||||
|                     } |                     } | ||||||
| @@ -118,7 +118,7 @@ class NoteFlatTextExp extends Expression { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             for (const parentNote of note.parents) { |             for (const parentNote of note.parents) { | ||||||
|                 const title = utils.normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); |                 const title = normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); | ||||||
|                 const foundTokens = foundAttrTokens.slice(); |                 const foundTokens = foundAttrTokens.slice(); | ||||||
|  |  | ||||||
|                 for (const token of this.tokens) { |                 for (const token of this.tokens) { | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ import OrderByAndLimitExp from "../expressions/order_by_and_limit.js"; | |||||||
| import AncestorExp from "../expressions/ancestor.js"; | import AncestorExp from "../expressions/ancestor.js"; | ||||||
| import buildComparator from "./build_comparator.js"; | import buildComparator from "./build_comparator.js"; | ||||||
| import ValueExtractor from "../value_extractor.js"; | import ValueExtractor from "../value_extractor.js"; | ||||||
| import utils from "../../utils.js"; | import { removeDiacritic } from "../../utils.js"; | ||||||
| import TrueExp from "../expressions/true.js"; | import TrueExp from "../expressions/true.js"; | ||||||
| import IsHiddenExp from "../expressions/is_hidden.js"; | import IsHiddenExp from "../expressions/is_hidden.js"; | ||||||
| import SearchContext from "../search_context.js"; | import SearchContext from "../search_context.js"; | ||||||
| @@ -25,7 +25,7 @@ import { TokenData, TokenStructure } from "./types.js"; | |||||||
| import Expression from "../expressions/expression.js"; | import Expression from "../expressions/expression.js"; | ||||||
|  |  | ||||||
| function getFulltext(_tokens: TokenData[], searchContext: SearchContext) { | function getFulltext(_tokens: TokenData[], searchContext: SearchContext) { | ||||||
|     const tokens: string[] = _tokens.map(t => utils.removeDiacritic(t.token)); |     const tokens: string[] = _tokens.map(t => removeDiacritic(t.token)); | ||||||
|  |  | ||||||
|     searchContext.highlightedTokens.push(...tokens); |     searchContext.highlightedTokens.push(...tokens); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import SearchResult from "../search_result.js"; | |||||||
| import SearchContext from "../search_context.js"; | import SearchContext from "../search_context.js"; | ||||||
| import becca from "../../../becca/becca.js"; | import becca from "../../../becca/becca.js"; | ||||||
| import beccaService from "../../../becca/becca_service.js"; | import beccaService from "../../../becca/becca_service.js"; | ||||||
| import utils from "../../utils.js"; | import { normalize, escapeHtml, escapeRegExp } from "../../utils.js"; | ||||||
| import log from "../../log.js"; | import log from "../../log.js"; | ||||||
| import hoistedNoteService from "../../hoisted_note.js"; | import hoistedNoteService from "../../hoisted_note.js"; | ||||||
| import BNote from "../../../becca/entities/bnote.js"; | import BNote from "../../../becca/entities/bnote.js"; | ||||||
| @@ -403,8 +403,8 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (highlightedTokens.find(token => utils.normalize(attr.name).includes(token) |             if (highlightedTokens.find(token => normalize(attr.name).includes(token) | ||||||
|                 || utils.normalize(attr.value).includes(token))) { |                 || normalize(attr.value).includes(token))) { | ||||||
|  |  | ||||||
|                 result.highlightedNotePathTitle += ` "${formatAttribute(attr)}'`; |                 result.highlightedNotePathTitle += ` "${formatAttribute(attr)}'`; | ||||||
|             } |             } | ||||||
| @@ -423,7 +423,7 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens | |||||||
|  |  | ||||||
|         for (const result of searchResults) { |         for (const result of searchResults) { | ||||||
|             // Reset token |             // Reset token | ||||||
|             const tokenRegex = new RegExp(utils.escapeRegExp(token), "gi"); |             const tokenRegex = new RegExp(escapeRegExp(token), "gi"); | ||||||
|             let match; |             let match; | ||||||
|  |  | ||||||
|             // Find all matches |             // Find all matches | ||||||
| @@ -449,15 +449,15 @@ function highlightSearchResults(searchResults: SearchResult[], highlightedTokens | |||||||
|  |  | ||||||
| function formatAttribute(attr: BAttribute) { | function formatAttribute(attr: BAttribute) { | ||||||
|     if (attr.type === 'relation') { |     if (attr.type === 'relation') { | ||||||
|         return `~${utils.escapeHtml(attr.name)}=…`; |         return `~${escapeHtml(attr.name)}=…`; | ||||||
|     } |     } | ||||||
|     else if (attr.type === 'label') { |     else if (attr.type === 'label') { | ||||||
|         let label = `#${utils.escapeHtml(attr.name)}`; |         let label = `#${escapeHtml(attr.name)}`; | ||||||
|  |  | ||||||
|         if (attr.value) { |         if (attr.value) { | ||||||
|             const val = /[^\w-]/.test(attr.value) ? `"${attr.value}"` : attr.value; |             const val = /[^\w-]/.test(attr.value) ? `"${attr.value}"` : attr.value; | ||||||
|  |  | ||||||
|             label += `=${utils.escapeHtml(val)}`; |             label += `=${escapeHtml(val)}`; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return label; |         return label; | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
| import dataDir from "./data_dir.js"; | import dataDir from "./data_dir.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import utils from "./utils.js" | import { randomSecureToken } from "./utils.js" | ||||||
|  |  | ||||||
| const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`; | const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`; | ||||||
|  |  | ||||||
| @@ -12,7 +12,7 @@ let sessionSecret: string; | |||||||
| const ENCODING = "ascii"; | const ENCODING = "ascii"; | ||||||
|  |  | ||||||
| if (!fs.existsSync(sessionSecretPath)) { | if (!fs.existsSync(sessionSecretPath)) { | ||||||
|     sessionSecret = utils.randomSecureToken(64).slice(0, 64); |     sessionSecret = randomSecureToken(64).slice(0, 64); | ||||||
|  |  | ||||||
|     log.info("Generated session secret"); |     log.info("Generated session secret"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import optionService from "./options.js"; | |||||||
| import syncOptions from "./sync_options.js"; | import syncOptions from "./sync_options.js"; | ||||||
| import request from "./request.js"; | import request from "./request.js"; | ||||||
| import appInfo from "./app_info.js"; | import appInfo from "./app_info.js"; | ||||||
| import utils from "./utils.js"; | import { timeLimit } from "./utils.js"; | ||||||
| import becca from "../becca/becca.js"; | import becca from "../becca/becca.js"; | ||||||
| import { SetupStatusResponse, SetupSyncSeedResponse } from './api-interface.js'; | import { SetupStatusResponse, SetupSyncSeedResponse } from './api-interface.js'; | ||||||
|  |  | ||||||
| @@ -47,7 +47,7 @@ async function sendSeedToSyncServer() { | |||||||
| async function requestToSyncServer<T>(method: string, path: string, body?: string | {}): Promise<T> { | async function requestToSyncServer<T>(method: string, path: string, body?: string | {}): Promise<T> { | ||||||
|     const timeout = syncOptions.getSyncTimeout(); |     const timeout = syncOptions.getSyncTimeout(); | ||||||
|  |  | ||||||
|     return await utils.timeLimit(request.exec({ |     return await timeLimit(request.exec({ | ||||||
|         method, |         method, | ||||||
|         url: syncOptions.getSyncServerHost() + path, |         url: syncOptions.getSyncServerHost() + path, | ||||||
|         body, |         body, | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import log from "./log.js"; | |||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
| import resourceDir from "./resource_dir.js"; | import resourceDir from "./resource_dir.js"; | ||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import utils from "./utils.js"; | import { isElectron, deferred } from "./utils.js"; | ||||||
| import optionService from "./options.js"; | import optionService from "./options.js"; | ||||||
| import port from "./port.js"; | import port from "./port.js"; | ||||||
| import BOption from "../becca/entities/boption.js"; | import BOption from "../becca/entities/boption.js"; | ||||||
| @@ -18,7 +18,7 @@ import becca_loader from "../becca/becca_loader.js"; | |||||||
| import password from "./encryption/password.js"; | import password from "./encryption/password.js"; | ||||||
| import backup from "./backup.js"; | import backup from "./backup.js"; | ||||||
|  |  | ||||||
| const dbReady = utils.deferred<void>(); | const dbReady = deferred<void>(); | ||||||
|  |  | ||||||
| function schemaExists() { | function schemaExists() { | ||||||
|     return !!sql.getValue(`SELECT name FROM sqlite_master |     return !!sql.getValue(`SELECT name FROM sqlite_master | ||||||
| @@ -38,7 +38,7 @@ function isDbInitialized() { | |||||||
| async function initDbConnection() { | async function initDbConnection() { | ||||||
|     if (!isDbInitialized()) { |     if (!isDbInitialized()) { | ||||||
|         log.info(`DB not initialized, please visit setup page` + |         log.info(`DB not initialized, please visit setup page` + | ||||||
|             (utils.isElectron() ? '' : ` - http://[your-server-host]:${port} to see instructions on how to initialize Trilium.`)); |             (isElectron() ? '' : ` - http://[your-server-host]:${port} to see instructions on how to initialize Trilium.`)); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import optionService from "./options.js"; | import optionService from "./options.js"; | ||||||
| import utils from "./utils.js"; | import { hmac, randomString, timeLimit } from "./utils.js"; | ||||||
| import instanceId from "./instance_id.js"; | import instanceId from "./instance_id.js"; | ||||||
| import dateUtils from "./date_utils.js"; | import dateUtils from "./date_utils.js"; | ||||||
| import syncUpdateService from "./sync_update.js"; | import syncUpdateService from "./sync_update.js"; | ||||||
| @@ -121,7 +121,7 @@ async function doLogin(): Promise<SyncContext> { | |||||||
|     const timestamp = dateUtils.utcNowDateTime(); |     const timestamp = dateUtils.utcNowDateTime(); | ||||||
|  |  | ||||||
|     const documentSecret = optionService.getOption('documentSecret'); |     const documentSecret = optionService.getOption('documentSecret'); | ||||||
|     const hash = utils.hmac(documentSecret, timestamp); |     const hash = hmac(documentSecret, timestamp); | ||||||
|  |  | ||||||
|     const syncContext: SyncContext = { cookieJar: {} }; |     const syncContext: SyncContext = { cookieJar: {} }; | ||||||
|     const resp = await syncRequest<SyncResponse>(syncContext, 'POST', '/api/login/sync', { |     const resp = await syncRequest<SyncResponse>(syncContext, 'POST', '/api/login/sync', { | ||||||
| @@ -156,7 +156,7 @@ async function doLogin(): Promise<SyncContext> { | |||||||
| async function pullChanges(syncContext: SyncContext) { | async function pullChanges(syncContext: SyncContext) { | ||||||
|     while (true) { |     while (true) { | ||||||
|         const lastSyncedPull = getLastSyncedPull(); |         const lastSyncedPull = getLastSyncedPull(); | ||||||
|         const logMarkerId = utils.randomString(10); // to easily pair sync events between client and server logs |         const logMarkerId = randomString(10); // to easily pair sync events between client and server logs | ||||||
|         const changesUri = `/api/sync/changed?instanceId=${instanceId}&lastEntityChangeId=${lastSyncedPull}&logMarkerId=${logMarkerId}`; |         const changesUri = `/api/sync/changed?instanceId=${instanceId}&lastEntityChangeId=${lastSyncedPull}&logMarkerId=${logMarkerId}`; | ||||||
|  |  | ||||||
|         const startDate = Date.now(); |         const startDate = Date.now(); | ||||||
| @@ -234,7 +234,7 @@ async function pushChanges(syncContext: SyncContext) { | |||||||
|         const entityChangesRecords = getEntityChangeRecords(filteredEntityChanges); |         const entityChangesRecords = getEntityChangeRecords(filteredEntityChanges); | ||||||
|         const startDate = new Date(); |         const startDate = new Date(); | ||||||
|  |  | ||||||
|         const logMarkerId = utils.randomString(10); // to easily pair sync events between client and server logs |         const logMarkerId = randomString(10); // to easily pair sync events between client and server logs | ||||||
|  |  | ||||||
|         await syncRequest(syncContext, 'PUT', `/api/sync/update?logMarkerId=${logMarkerId}`, { |         await syncRequest(syncContext, 'PUT', `/api/sync/update?logMarkerId=${logMarkerId}`, { | ||||||
|             entities: entityChangesRecords, |             entities: entityChangesRecords, | ||||||
| @@ -310,7 +310,7 @@ async function syncRequest<T extends {}>(syncContext: SyncContext, method: strin | |||||||
|  |  | ||||||
|     let response; |     let response; | ||||||
|  |  | ||||||
|     const requestId = utils.randomString(10); |     const requestId = randomString(10); | ||||||
|     const pageCount = Math.max(1, Math.ceil(body.length / PAGE_SIZE)); |     const pageCount = Math.max(1, Math.ceil(body.length / PAGE_SIZE)); | ||||||
|  |  | ||||||
|     for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) { |     for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) { | ||||||
| @@ -328,7 +328,7 @@ async function syncRequest<T extends {}>(syncContext: SyncContext, method: strin | |||||||
|             proxy: proxyToggle ? syncOptions.getSyncProxy() : null |             proxy: proxyToggle ? syncOptions.getSyncProxy() : null | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         response = await utils.timeLimit(request.exec(opts), timeout) as T; |         response = await timeLimit(request.exec(opts), timeout) as T; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return response; |     return response; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import WebSocket from "ws"; | import WebSocket from "ws"; | ||||||
| import utils from "./utils.js"; | import { isElectron, randomString } from "./utils.js"; | ||||||
| import log from "./log.js"; | import log from "./log.js"; | ||||||
| import sql from "./sql.js"; | import sql from "./sql.js"; | ||||||
| import cls from "./cls.js"; | import cls from "./cls.js"; | ||||||
| @@ -18,7 +18,7 @@ if (env.isDev()) { | |||||||
|     const debounce = (await import("debounce")).default; |     const debounce = (await import("debounce")).default; | ||||||
|     const debouncedReloadFrontend = debounce(() => reloadFrontend("source code change"), 200); |     const debouncedReloadFrontend = debounce(() => reloadFrontend("source code change"), 200); | ||||||
|     chokidar |     chokidar | ||||||
|         .watch(utils.isElectron() ? 'dist/src/public' : 'src/public') |         .watch(isElectron() ? 'dist/src/public' : 'src/public') | ||||||
|         .on('add', debouncedReloadFrontend) |         .on('add', debouncedReloadFrontend) | ||||||
|         .on('change', debouncedReloadFrontend) |         .on('change', debouncedReloadFrontend) | ||||||
|         .on('unlink', debouncedReloadFrontend); |         .on('unlink', debouncedReloadFrontend); | ||||||
| @@ -62,7 +62,7 @@ function init(httpServer: Server, sessionParser: SessionParser) { | |||||||
|     webSocketServer = new WebSocket.Server({ |     webSocketServer = new WebSocket.Server({ | ||||||
|         verifyClient: (info, done) => { |         verifyClient: (info, done) => { | ||||||
|             sessionParser(info.req, {}, () => { |             sessionParser(info.req, {}, () => { | ||||||
|                 const allowed = utils.isElectron() |                 const allowed = isElectron() | ||||||
|                     || (info.req as any).session.loggedIn |                     || (info.req as any).session.loggedIn | ||||||
|                     || (config.General && config.General.noAuthentication); |                     || (config.General && config.General.noAuthentication); | ||||||
|  |  | ||||||
| @@ -77,7 +77,7 @@ function init(httpServer: Server, sessionParser: SessionParser) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     webSocketServer.on('connection', (ws, req) => { |     webSocketServer.on('connection', (ws, req) => { | ||||||
|         (ws as any).id = utils.randomString(10); |         (ws as any).id = randomString(10); | ||||||
|  |  | ||||||
|         console.log(`websocket client connected`); |         console.log(`websocket client connected`); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user