Merge pull request #243 from TriliumNext/feature/server_esm_part3

Server ESM port: Getting things to run
This commit is contained in:
Elian Doran 2024-07-27 15:20:52 +03:00 committed by GitHub
commit 48cf41b5a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
52 changed files with 435 additions and 229 deletions

View File

@ -4,6 +4,7 @@ on:
branches: branches:
- 'develop' - 'develop'
- 'feature/update*' - 'feature/update*'
- 'feature/server_esm*'
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'

BIN
bin/better-sqlite3/linux-desktop-better_sqlite3.node Normal file → Executable file

Binary file not shown.

BIN
bin/better-sqlite3/linux-server-better_sqlite3.node Normal file → Executable file

Binary file not shown.

BIN
bin/better-sqlite3/mac-arm64-better_sqlite3.node Normal file → Executable file

Binary file not shown.

BIN
bin/better-sqlite3/mac-x64-better_sqlite3.node Normal file → Executable file

Binary file not shown.

38
bin/better-sqlite3/update.sh Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
ELECTRON_VERSION="electron-v125"
NODE_VERSION="node-v115"
if ! command -v jq &> /dev/null; then
echo "Missing command: jq"
exit 1
fi
script_dir=$(realpath $(dirname $0))
cd "$script_dir"
BETTER_SQLITE3_VERSION=$(jq -r '.dependencies.["better-sqlite3"]' ../../package.json | grep -oP "\d+\.\d+\.\d+")
if [ -z $BETTER_SQLITE3_VERSION ]; then
echo "Unable to determine better-sqlite3 version."
exit 2
fi
echo "Version: $BETTER_SQLITE3_VERSION"
function download() {
version="$1"
platform="$2"
dest_name="$3"
url=https://github.com/WiseLibs/better-sqlite3/releases/download/v${BETTER_SQLITE3_VERSION}/better-sqlite3-v${BETTER_SQLITE3_VERSION}-${version}-${platform}.tar.gz
temp_file="temp.tar.gz"
curl -L "$url" -o "$temp_file"
tar -xzvf "$temp_file"
mv build/Release/better_sqlite3.node "$dest_name-better_sqlite3.node"
rm -rf build
rm -f "$temp_file"
}
download $NODE_VERSION "linux-x64" "linux-server"
download $ELECTRON_VERSION "linux-x64" "linux-desktop"
download $ELECTRON_VERSION "win32-x64" "win"
download $ELECTRON_VERSION "darwin-x64" "mac-x64"
download $ELECTRON_VERSION "darwin-arm64" "mac-arm64"

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
if ! command -v dpkg-deb &> /dev/null; then if ! command -v dpkg-deb &> /dev/null; then
echo "Missing command: dpkg-deb" echo "Missing command: dpkg-deb"
exit 1 exit 1

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
VERSION=`jq -r ".version" package.json` VERSION=`jq -r ".version" package.json`
SERIES=${VERSION:0:4}-latest SERIES=${VERSION:0:4}-latest

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
if ! command -v jq &> /dev/null; then if ! command -v jq &> /dev/null; then
echo "Missing command: jq" echo "Missing command: jq"
exit 1 exit 1
@ -24,8 +26,6 @@ SRC_DIR=./dist/trilium-linux-x64-src
[ "$1" != "DONTCOPY" ] && ./bin/copy-trilium.sh "$SRC_DIR" [ "$1" != "DONTCOPY" ] && ./bin/copy-trilium.sh "$SRC_DIR"
rm -r "$SRC_DIR"/src/public/app-dist/*.mobile.*
echo "Copying required linux-x64 binaries" echo "Copying required linux-x64 binaries"
cp -r bin/better-sqlite3/linux-desktop-better_sqlite3.node "$SRC_DIR"/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/linux-desktop-better_sqlite3.node "$SRC_DIR"/node_modules/better-sqlite3/build/Release/better_sqlite3.node
@ -55,4 +55,4 @@ pushd dist
tar cJf "trilium-linux-x64-${VERSION}.tar.xz" trilium-linux-x64 tar cJf "trilium-linux-x64-${VERSION}.tar.xz" trilium-linux-x64
popd popd
bin/build-debian.sh #bin/build-debian.sh

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
SRC_DIR=./dist/trilium-mac-arm64-src SRC_DIR=./dist/trilium-mac-arm64-src
if [ "$1" != "DONTCOPY" ] if [ "$1" != "DONTCOPY" ]
@ -11,8 +13,6 @@ echo "Copying required mac arm64 binaries"
cp -r bin/better-sqlite3/mac-arm64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/mac-arm64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
echo "Packaging mac arm64 electron build" echo "Packaging mac arm64 electron build"
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=arm64 --overwrite --icon=images/app-icons/mac/icon.icns ./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=arm64 --overwrite --icon=images/app-icons/mac/icon.icns
@ -34,5 +34,4 @@ VERSION=`jq -r ".version" package.json`
cd dist cd dist
rm trilium-mac-arm64-${VERSION}.zip
zip -r9 --symlinks trilium-mac-arm64-${VERSION}.zip trilium-mac-arm64 zip -r9 --symlinks trilium-mac-arm64-${VERSION}.zip trilium-mac-arm64

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
SRC_DIR=./dist/trilium-mac-x64-src SRC_DIR=./dist/trilium-mac-x64-src
if [ "$1" != "DONTCOPY" ] if [ "$1" != "DONTCOPY" ]
@ -11,8 +13,6 @@ echo "Copying required mac x64 binaries"
cp -r bin/better-sqlite3/mac-x64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/mac-x64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
echo "Packaging mac x64 electron build" echo "Packaging mac x64 electron build"
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns ./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
@ -34,5 +34,4 @@ VERSION=`jq -r ".version" package.json`
cd dist cd dist
rm trilium-mac-x64-${VERSION}.zip
zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64 zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
PKG_DIR=dist/trilium-linux-x64-server PKG_DIR=dist/trilium-linux-x64-server
NODE_VERSION=20.15.1 NODE_VERSION=20.15.1
@ -20,7 +22,6 @@ rm -r $PKG_DIR/node/lib/node_modules/npm
rm -r $PKG_DIR/node/include/node rm -r $PKG_DIR/node/include/node
rm -r $PKG_DIR/node_modules/electron* rm -r $PKG_DIR/node_modules/electron*
rm -r $PKG_DIR/webpack*
rm -r $PKG_DIR/electron.js rm -r $PKG_DIR/electron.js
cp -r bin/better-sqlite3/linux-server-better_sqlite3.node $PKG_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/linux-server-better_sqlite3.node $PKG_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
if ! command -v wine &> /dev/null; then if ! command -v wine &> /dev/null; then
echo "Missing command: wine" echo "Missing command: wine"
exit 1 exit 1
@ -16,8 +18,6 @@ echo "Copying required windows binaries"
cp -r bin/better-sqlite3/win-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/win-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
echo "Packaging windows x64 electron build" echo "Packaging windows x64 electron build"
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico ./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
if ! command -v jq &> /dev/null; then if ! command -v jq &> /dev/null; then
echo "Missing command: jq" echo "Missing command: jq"
exit 1 exit 1
@ -40,7 +42,6 @@ cp -r $SRC_DIR ./dist/trilium-windows-x64-src
cp -r $SRC_DIR ./dist/trilium-mac-x64-src cp -r $SRC_DIR ./dist/trilium-mac-x64-src
cp -r $SRC_DIR ./dist/trilium-mac-arm64-src cp -r $SRC_DIR ./dist/trilium-mac-arm64-src
set -e
bin/build-win-x64.sh DONTCOPY bin/build-win-x64.sh DONTCOPY
bin/build-mac-x64.sh DONTCOPY bin/build-mac-x64.sh DONTCOPY

View File

@ -1,5 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Fail on any command error
shopt -s globstar shopt -s globstar
if [[ $# -eq 0 ]] ; then if [[ $# -eq 0 ]] ; then

View File

@ -16,7 +16,7 @@ function getGitRevision() {
} }
const output = `\ const output = `\
export = { export default {
buildDate: "${getBuildDate()}", buildDate: "${getBuildDate()}",
buildRevision: "${getGitRevision()}" buildRevision: "${getGitRevision()}"
}; };

View File

@ -9,7 +9,7 @@ import windowService from "./src/services/window.js";
import tray from "./src/services/tray.js"; import tray from "./src/services/tray.js";
// Prevent Trilium starting twice on first install and on uninstall for the Windows installer. // Prevent Trilium starting twice on first install and on uninstall for the Windows installer.
if (require('electron-squirrel-startup')) { if (await import('electron-squirrel-startup')) {
process.exit(0); process.exit(0);
} }
@ -67,4 +67,4 @@ electron.app.on("will-quit", () => {
// this is to disable electron warning spam in the dev console (local development only) // this is to disable electron warning spam in the dev console (local development only)
process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true"; process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true";
require('./src/www.js'); await import('./src/www.js');

View File

@ -2,7 +2,7 @@
"restartable": "rs", "restartable": "rs",
"ignore": [".git", "node_modules/**/node_modules", "src/public/"], "ignore": [".git", "node_modules/**/node_modules", "src/public/"],
"verbose": false, "verbose": false,
"exec": "ts-node", "exec": "tsx",
"watch": ["src/"], "watch": ["src/"],
"signal": "SIGTERM", "signal": "SIGTERM",
"env": { "env": {

235
package-lock.json generated
View File

@ -12,10 +12,11 @@
"@braintree/sanitize-url": "^7.1.0", "@braintree/sanitize-url": "^7.1.0",
"@electron/remote": "2.1.2", "@electron/remote": "2.1.2",
"@excalidraw/excalidraw": "^0.17.6", "@excalidraw/excalidraw": "^0.17.6",
"@types/electron-squirrel-startup": "^1.0.2",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"async-mutex": "^0.5.0", "async-mutex": "^0.5.0",
"axios": "^1.7.2", "axios": "^1.7.2",
"better-sqlite3": "8.5.0", "better-sqlite3": "^11.1.2",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
@ -58,7 +59,7 @@
"mermaid": "^10.9.1", "mermaid": "^10.9.1",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"node-abi": "3.56.0", "node-abi": "^3.65.0",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"panzoom": "9.4.3", "panzoom": "9.4.3",
"print-this": "2.0.0", "print-this": "2.0.0",
@ -97,6 +98,7 @@
"@types/compression": "^1.7.5", "@types/compression": "^1.7.5",
"@types/cookie-parser": "^1.4.7", "@types/cookie-parser": "^1.4.7",
"@types/csurf": "^1.11.5", "@types/csurf": "^1.11.5",
"@types/debounce": "^1.2.4",
"@types/ejs": "^3.1.5", "@types/ejs": "^3.1.5",
"@types/escape-html": "^1.0.4", "@types/escape-html": "^1.0.4",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
@ -107,7 +109,6 @@
"@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/multer": "^1.4.11",
"@types/node": "^20.11.19",
"@types/safe-compare": "^1.1.2", "@types/safe-compare": "^1.1.2",
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7", "@types/sax": "^1.2.7",
@ -120,7 +121,7 @@
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
"@types/xml2js": "^0.4.14", "@types/xml2js": "^0.4.14",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"electron": "25.9.8", "electron": "^31.2.1",
"electron-packager": "17.1.2", "electron-packager": "17.1.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"esm": "3.2.25", "esm": "3.2.25",
@ -132,6 +133,7 @@
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tslib": "^2.6.2", "tslib": "^2.6.2",
"tsx": "^4.16.2",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"webpack": "^5.93.0", "webpack": "^5.93.0",
"webpack-cli": "5.1.4" "webpack-cli": "5.1.4"
@ -1389,6 +1391,22 @@
"node": ">=14.14" "node": ">=14.14"
} }
}, },
"node_modules/@esbuild/win32-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@excalidraw/excalidraw": { "node_modules/@excalidraw/excalidraw": {
"version": "0.17.6", "version": "0.17.6",
"resolved": "https://registry.npmjs.org/@excalidraw/excalidraw/-/excalidraw-0.17.6.tgz", "resolved": "https://registry.npmjs.org/@excalidraw/excalidraw/-/excalidraw-0.17.6.tgz",
@ -2208,6 +2226,12 @@
"resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
"integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
}, },
"node_modules/@types/debounce": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.4.tgz",
"integrity": "sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==",
"dev": true
},
"node_modules/@types/debug": { "node_modules/@types/debug": {
"version": "4.1.9", "version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz",
@ -2222,6 +2246,11 @@
"integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==",
"dev": true "dev": true
}, },
"node_modules/@types/electron-squirrel-startup": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/electron-squirrel-startup/-/electron-squirrel-startup-1.0.2.tgz",
"integrity": "sha512-AzxnvBzNh8K/0SmxMmZtpJf1/IWoGXLP+pQDuUaVkPyotI8ryvAtBSqgxR/qOSvxWHYWrxkeNsJ+Ca5xOuUxJQ=="
},
"node_modules/@types/escape-html": { "node_modules/@types/escape-html": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.4.tgz",
@ -2447,9 +2476,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.14.10", "version": "20.14.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
"integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -3206,6 +3235,11 @@
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
} }
}, },
"node_modules/archiver-utils/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
},
"node_modules/archiver-utils/node_modules/minimatch": { "node_modules/archiver-utils/node_modules/minimatch": {
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@ -3228,6 +3262,21 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/archiver-utils/node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/archiver-utils/node_modules/readable-stream": { "node_modules/archiver-utils/node_modules/readable-stream": {
"version": "4.5.2", "version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
@ -3371,9 +3420,10 @@
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
}, },
"node_modules/asar": { "node_modules/asar": {
"version": "3.1.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz",
"integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==",
"deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"chromium-pickle-js": "^0.2.0", "chromium-pickle-js": "^0.2.0",
@ -3572,13 +3622,13 @@
} }
}, },
"node_modules/better-sqlite3": { "node_modules/better-sqlite3": {
"version": "8.5.0", "version": "11.1.2",
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.5.0.tgz", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
"integrity": "sha512-vbPcv/Hx5WYdyNg/NbcfyaBZyv9s/NVbxb7yCeC5Bq1pVocNxeL2tZmSu3Rlm4IEOTjYdGyzWQgyx0OSdORBzw==", "integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"bindings": "^1.5.0", "bindings": "^1.5.0",
"prebuild-install": "^7.1.0" "prebuild-install": "^7.1.1"
} }
}, },
"node_modules/bezier-easing": { "node_modules/bezier-easing": {
@ -5760,13 +5810,13 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "25.9.8", "version": "31.2.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-25.9.8.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-31.2.1.tgz",
"integrity": "sha512-PGgp6PH46QVENHuAHc2NT1Su8Q1qov7qIl2jI5tsDpTibwV2zD8539AeWBQySeBU4dhbj9onIl7+1bXQ0wefBg==", "integrity": "sha512-g3CLKjl4yuXt6VWm/KpgEjYYhFiCl19RgUn8lOC8zV/56ZXAS3+mqV4wWzicE/7vSYXs6GRO7vkYRwrwhX3Gaw==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
"@types/node": "^18.11.18", "@types/node": "^20.9.0",
"extract-zip": "^2.0.1" "extract-zip": "^2.0.1"
}, },
"bin": { "bin": {
@ -5858,9 +5908,9 @@
} }
}, },
"node_modules/electron-installer-common/node_modules/universalify": { "node_modules/electron-installer-common/node_modules/universalify": {
"version": "2.0.0", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"optional": true, "optional": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
@ -5920,9 +5970,9 @@
} }
}, },
"node_modules/electron-installer-debian/node_modules/universalify": { "node_modules/electron-installer-debian/node_modules/universalify": {
"version": "2.0.0", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"optional": true, "optional": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
@ -6203,14 +6253,6 @@
"node": ">=6 <7 || >=8" "node": ">=6 <7 || >=8"
} }
}, },
"node_modules/electron/node_modules/@types/node": {
"version": "18.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz",
"integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/elkjs": { "node_modules/elkjs": {
"version": "0.9.2", "version": "0.9.2",
"resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.2.tgz", "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.2.tgz",
@ -6322,6 +6364,44 @@
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"optional": true "optional": true
}, },
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.21.5",
"@esbuild/android-arm": "0.21.5",
"@esbuild/android-arm64": "0.21.5",
"@esbuild/android-x64": "0.21.5",
"@esbuild/darwin-arm64": "0.21.5",
"@esbuild/darwin-x64": "0.21.5",
"@esbuild/freebsd-arm64": "0.21.5",
"@esbuild/freebsd-x64": "0.21.5",
"@esbuild/linux-arm": "0.21.5",
"@esbuild/linux-arm64": "0.21.5",
"@esbuild/linux-ia32": "0.21.5",
"@esbuild/linux-loong64": "0.21.5",
"@esbuild/linux-mips64el": "0.21.5",
"@esbuild/linux-ppc64": "0.21.5",
"@esbuild/linux-riscv64": "0.21.5",
"@esbuild/linux-s390x": "0.21.5",
"@esbuild/linux-x64": "0.21.5",
"@esbuild/netbsd-x64": "0.21.5",
"@esbuild/openbsd-x64": "0.21.5",
"@esbuild/sunos-x64": "0.21.5",
"@esbuild/win32-arm64": "0.21.5",
"@esbuild/win32-ia32": "0.21.5",
"@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -7323,6 +7403,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz",
"integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==", "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"optional": true "optional": true
}, },
"node_modules/get-caller-file": { "node_modules/get-caller-file": {
@ -7408,6 +7489,18 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/get-tsconfig": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz",
"integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==",
"dev": true,
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/getpass": { "node_modules/getpass": {
"version": "0.1.7", "version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@ -8617,9 +8710,9 @@
} }
}, },
"node_modules/jsdom": { "node_modules/jsdom": {
"version": "24.1.0", "version": "24.1.1",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz",
"integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==",
"dependencies": { "dependencies": {
"cssstyle": "^4.0.1", "cssstyle": "^4.0.1",
"data-urls": "^5.0.0", "data-urls": "^5.0.0",
@ -8627,11 +8720,11 @@
"form-data": "^4.0.0", "form-data": "^4.0.0",
"html-encoding-sniffer": "^4.0.0", "html-encoding-sniffer": "^4.0.0",
"http-proxy-agent": "^7.0.2", "http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.4", "https-proxy-agent": "^7.0.5",
"is-potential-custom-element-name": "^1.0.1", "is-potential-custom-element-name": "^1.0.1",
"nwsapi": "^2.2.10", "nwsapi": "^2.2.12",
"parse5": "^7.1.2", "parse5": "^7.1.2",
"rrweb-cssom": "^0.7.0", "rrweb-cssom": "^0.7.1",
"saxes": "^6.0.0", "saxes": "^6.0.0",
"symbol-tree": "^3.2.4", "symbol-tree": "^3.2.4",
"tough-cookie": "^4.1.4", "tough-cookie": "^4.1.4",
@ -8640,7 +8733,7 @@
"whatwg-encoding": "^3.1.1", "whatwg-encoding": "^3.1.1",
"whatwg-mimetype": "^4.0.0", "whatwg-mimetype": "^4.0.0",
"whatwg-url": "^14.0.0", "whatwg-url": "^14.0.0",
"ws": "^8.17.0", "ws": "^8.18.0",
"xml-name-validator": "^5.0.0" "xml-name-validator": "^5.0.0"
}, },
"engines": { "engines": {
@ -10124,9 +10217,9 @@
"dev": true "dev": true
}, },
"node_modules/node-abi": { "node_modules/node-abi": {
"version": "3.56.0", "version": "3.65.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz",
"integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==",
"dependencies": { "dependencies": {
"semver": "^7.3.5" "semver": "^7.3.5"
}, },
@ -10837,29 +10930,35 @@
"dev": true "dev": true
}, },
"node_modules/path-scurry": { "node_modules/path-scurry": {
"version": "1.11.1", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"dev": true,
"dependencies": { "dependencies": {
"lru-cache": "^10.2.0", "lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.18" "node": ">=16 || 14 >=14.17"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/path-scurry/node_modules/lru-cache": { "node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.4.3", "version": "9.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
}, },
"node_modules/path-scurry/node_modules/minipass": { "node_modules/path-scurry/node_modules/minipass": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz",
"integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==",
"dev": true,
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
@ -11720,6 +11819,15 @@
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
}, },
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/responselike": { "node_modules/responselike": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
@ -13024,7 +13132,7 @@
"node_modules/tiny-each-async": { "node_modules/tiny-each-async": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz",
"integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=", "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==",
"optional": true "optional": true
}, },
"node_modules/tiny-invariant": { "node_modules/tiny-invariant": {
@ -13255,6 +13363,25 @@
"node": ">=0.6.x" "node": ">=0.6.x"
} }
}, },
"node_modules/tsx": {
"version": "4.16.2",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz",
"integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==",
"dev": true,
"dependencies": {
"esbuild": "~0.21.5",
"get-tsconfig": "^4.7.5"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"node_modules/tunnel-agent": { "node_modules/tunnel-agent": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@ -13842,9 +13969,9 @@
"dev": true "dev": true
}, },
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"optional": true, "optional": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"

View File

@ -18,12 +18,13 @@
"type": "git", "type": "git",
"url": "https://github.com/TriliumNext/Notes.git" "url": "https://github.com/TriliumNext/Notes.git"
}, },
"type": "module",
"scripts": { "scripts": {
"start-server": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts", "start-server": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts", "start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"qstart-server": "npm run qswitch-server && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts", "qstart-server": "npm run qswitch-server && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"start-electron": "npm run prepare-dist && cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron.js --inspect=5858 .", "start-electron": "rimraf ./dist && tsc && tsx ./bin/copy-dist.ts && cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron.js --inspect=5858 .",
"start-electron-no-dir": "npm run prepare-dist && cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev electron ./dist/electron.js --inspect=5858 .", "start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
"qstart-electron": "npm run qswitch-electron && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .", "qstart-electron": "npm run qswitch-electron && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
"start-test-server": "npm run qswitch-server; rimraf ./data-test; cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 ts-node src/www.ts", "start-test-server": "npm run qswitch-server; rimraf ./data-test; cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 ts-node src/www.ts",
"switch-server": "rimraf ./node_modules/better-sqlite3 && npm install", "switch-server": "rimraf ./node_modules/better-sqlite3 && npm install",
@ -33,25 +34,26 @@
"build-backend-docs": "rimraf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js", "build-backend-docs": "rimraf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js",
"build-frontend-docs": "rimraf ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js", "build-frontend-docs": "rimraf ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js",
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs", "build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
"webpack": "webpack -c webpack.config.ts", "webpack": "cross-env NODE_OPTIONS=--loader=ts-node/esm webpack -c webpack.config.ts",
"test-jasmine": "cross-env TRILIUM_DATA_DIR=./data-test ts-node ./node_modules/jasmine/bin/jasmine", "test-jasmine": "cross-env TRILIUM_DATA_DIR=./data-test tsx ./node_modules/.bin/jasmine",
"test-es6": "ts-node -r esm spec-es6/attribute_parser.spec.ts", "test-es6": "tsx -r esm spec-es6/attribute_parser.spec.ts",
"test": "npm run test-jasmine && npm run test-es6", "test": "npm run test-jasmine && npm run test-es6",
"start-electron-forge": "npm run prepare-dist && electron-forge start", "start-electron-forge": "npm run prepare-dist && electron-forge start",
"make-electron": "npm run webpack && npm run prepare-dist && electron-forge make", "make-electron": "npm run webpack && npm run prepare-dist && electron-forge make",
"package-electron": "electron-forge package", "package-electron": "electron-forge package",
"prepare-dist": "rimraf ./dist && tsc && ts-node ./bin/copy-dist.ts", "prepare-dist": "rimraf ./dist && tsc && tsx ./bin/copy-dist.ts",
"update-build-info": "ts-node bin/update-build-info.ts", "update-build-info": "tsx bin/update-build-info.ts",
"errors": "tsc --watch --noEmit" "errors": "tsc --watch --noEmit"
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.1.0", "@braintree/sanitize-url": "^7.1.0",
"@electron/remote": "2.1.2", "@electron/remote": "2.1.2",
"@excalidraw/excalidraw": "^0.17.6", "@excalidraw/excalidraw": "^0.17.6",
"@types/electron-squirrel-startup": "^1.0.2",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"async-mutex": "^0.5.0", "async-mutex": "^0.5.0",
"axios": "^1.7.2", "axios": "^1.7.2",
"better-sqlite3": "8.5.0", "better-sqlite3": "^11.1.2",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
@ -94,7 +96,7 @@
"mermaid": "^10.9.1", "mermaid": "^10.9.1",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"node-abi": "3.56.0", "node-abi": "^3.65.0",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"panzoom": "9.4.3", "panzoom": "9.4.3",
"print-this": "2.0.0", "print-this": "2.0.0",
@ -130,6 +132,7 @@
"@types/compression": "^1.7.5", "@types/compression": "^1.7.5",
"@types/cookie-parser": "^1.4.7", "@types/cookie-parser": "^1.4.7",
"@types/csurf": "^1.11.5", "@types/csurf": "^1.11.5",
"@types/debounce": "^1.2.4",
"@types/ejs": "^3.1.5", "@types/ejs": "^3.1.5",
"@types/escape-html": "^1.0.4", "@types/escape-html": "^1.0.4",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
@ -140,7 +143,6 @@
"@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/multer": "^1.4.11",
"@types/node": "^20.11.19",
"@types/safe-compare": "^1.1.2", "@types/safe-compare": "^1.1.2",
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/sax": "^1.2.7", "@types/sax": "^1.2.7",
@ -153,7 +155,7 @@
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
"@types/xml2js": "^0.4.14", "@types/xml2js": "^0.4.14",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"electron": "25.9.8", "electron": "^31.2.1",
"electron-packager": "17.1.2", "electron-packager": "17.1.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"esm": "3.2.25", "esm": "3.2.25",
@ -165,6 +167,7 @@
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tslib": "^2.6.2", "tslib": "^2.6.2",
"tsx": "^4.16.2",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"webpack": "^5.93.0", "webpack": "^5.93.0",
"webpack-cli": "5.1.4" "webpack-cli": "5.1.4"

View File

@ -1,12 +1,15 @@
import etapi from "../support/etapi.js"; import etapi from "../support/etapi.js";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import { fileURLToPath } from "url";
etapi.describeEtapi("import", () => { etapi.describeEtapi("import", () => {
// temporarily skip this test since test-export.zip is missing // temporarily skip this test since test-export.zip is missing
xit("import", async () => { xit("import", async () => {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const zipFileBuffer = fs.readFileSync( const zipFileBuffer = fs.readFileSync(
path.resolve(__dirname, "test-export.zip") path.resolve(scriptDir, "test-export.zip")
); );
const response = await etapi.postEtapiContent( const response = await etapi.postEtapiContent(

View File

@ -1,6 +1,6 @@
import anonymizationService from "./services/anonymization.js"; import anonymizationService from "./services/anonymization.js";
import sqlInit from "./services/sql_init.js"; import sqlInit from "./services/sql_init.js";
require('./becca/entity_constructor'); await import("./becca/entity_constructor");
sqlInit.dbReady.then(async () => { sqlInit.dbReady.then(async () => {
try { try {

View File

@ -4,16 +4,29 @@ import favicon from "serve-favicon";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import helmet from "helmet"; import helmet from "helmet";
import compression from "compression"; import compression from "compression";
import { fileURLToPath } from "url";
import { dirname } from "path";
import sessionParser from "./routes/session_parser.js"; import sessionParser from "./routes/session_parser.js";
import utils from "./services/utils.js"; import utils from "./services/utils.js";
import assets from "./routes/assets.js";
import routes from "./routes/routes.js";
import custom from "./routes/custom.js";
import error_handlers from "./routes/error_handlers.js";
import { startScheduledCleanup } from "./services/erase.js";
import sql_init from "./services/sql_init.js";
require('./services/handlers'); await import('./services/handlers');
require('./becca/becca_loader'); await import('./becca/becca_loader');
const app = express(); const app = express();
const scriptDir = dirname(fileURLToPath(import.meta.url));
// Initialize DB
sql_init.initializeDb();
// view engine setup // view engine setup
app.set('views', path.join(__dirname, 'views')); app.set('views', path.join(scriptDir, 'views'));
app.set('view engine', 'ejs'); app.set('view engine', 'ejs');
if (!utils.isElectron()) { if (!utils.isElectron()) {
@ -31,30 +44,32 @@ app.use(express.json({ limit: '500mb' }));
app.use(express.raw({ limit: '500mb' })); app.use(express.raw({ limit: '500mb' }));
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public/root'))); app.use(express.static(path.join(scriptDir, 'public/root')));
app.use(`/manifest.webmanifest`, express.static(path.join(__dirname, 'public/manifest.webmanifest'))); app.use(`/manifest.webmanifest`, express.static(path.join(scriptDir, 'public/manifest.webmanifest')));
app.use(`/robots.txt`, express.static(path.join(__dirname, 'public/robots.txt'))); app.use(`/robots.txt`, express.static(path.join(scriptDir, 'public/robots.txt')));
app.use(sessionParser); app.use(sessionParser);
app.use(favicon(`${__dirname}/../images/app-icons/win/icon.ico`)); app.use(favicon(`${scriptDir}/../images/app-icons/win/icon.ico`));
require('./routes/assets').register(app); assets.register(app);
require('./routes/routes').register(app); routes.register(app);
require('./routes/custom').register(app); custom.register(app);
require('./routes/error_handlers').register(app); error_handlers.register(app);
// triggers sync timer // triggers sync timer
require('./services/sync'); await import("./services/sync");
// triggers backup timer // triggers backup timer
require('./services/backup'); await import('./services/backup');
// trigger consistency checks timer // trigger consistency checks timer
require('./services/consistency_checks'); await import('./services/consistency_checks');
require('./services/scheduler'); await import('./services/scheduler');
startScheduledCleanup();
if (utils.isElectron()) { if (utils.isElectron()) {
require('@electron/remote/main').initialize(); (await import('@electron/remote/main')).initialize();
} }
export default app; export default app;

View File

@ -10,8 +10,7 @@ import log from "../../services/log.js";
import protectedSessionService from "../../services/protected_session.js"; import protectedSessionService from "../../services/protected_session.js";
import blobService from "../../services/blob.js"; import blobService from "../../services/blob.js";
import Becca, { ConstructorData } from '../becca-interface'; import Becca, { ConstructorData } from '../becca-interface';
import becca from "../becca.js";
let becca: Becca;
interface ContentOpts { interface ContentOpts {
forceSave?: boolean; forceSave?: boolean;
@ -47,11 +46,7 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
} }
protected get becca(): Becca { protected get becca(): Becca {
if (!becca) { return becca;
becca = require('../becca');
}
return becca as Becca;
} }
protected putEntityChange(isDeleted: boolean) { protected putEntityChange(isDeleted: boolean) {

View File

@ -3,7 +3,8 @@ import { Router } from "express";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
const specPath = path.join(__dirname, 'etapi.openapi.yaml'); import { fileURLToPath } from "url";
const specPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'etapi.openapi.yaml');
let spec: string | null = null; let spec: string | null = null;
function register(router: Router) { function register(router: Router) {

View File

@ -1,5 +1,6 @@
import noteTypeService from "../services/note_types.js"; import noteTypeService from "../services/note_types.js";
import dateUtils from "../services/date_utils.js"; import dateUtils from "../services/date_utils.js";
import becca from "../becca/becca.js";
function mandatory(obj: unknown) { function mandatory(obj: unknown) {
if (obj === undefined) { if (obj === undefined) {
@ -64,8 +65,6 @@ function isNoteId(obj: unknown) {
return; return;
} }
const becca = require('../becca/becca');
if (typeof obj !== 'string') { if (typeof obj !== 'string') {
return `'${obj}' is not a valid noteId`; return `'${obj}' is not a valid noteId`;
} }

View File

@ -1,5 +1,6 @@
import assetPath from "../services/asset_path.js"; import assetPath from "../services/asset_path.js";
import path from "path"; import path from "path";
import { fileURLToPath } from "url";
import express from "express"; import express from "express";
import env from "../services/env.js"; import env from "../services/env.js";
import serveStatic from "serve-static"; import serveStatic from "serve-static";
@ -15,7 +16,7 @@ const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOp
}; };
function register(app: express.Application) { function register(app: express.Application) {
const srcRoot = path.join(__dirname, '..'); const srcRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
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')));
app.use(`/${assetPath}/fonts`, persistentCacheStatic(path.join(srcRoot, 'public/fonts'))); app.use(`/${assetPath}/fonts`, persistentCacheStatic(path.join(srcRoot, 'public/fonts')));

View File

@ -1,7 +1,6 @@
import { ipcMain } from "electron";
import { Application } from "express"; import { Application } from "express";
const ipcMain = require('electron').ipcMain;
interface Response { interface Response {
statusCode: number; statusCode: number;
getHeader: (name: string) => string; getHeader: (name: string) => string;

View File

@ -10,12 +10,8 @@ import { Request, Response } from 'express';
function setupPage(req: Request, res: Response) { function setupPage(req: Request, res: Response) {
if (sqlInit.isDbInitialized()) { if (sqlInit.isDbInitialized()) {
if (utils.isElectron()) { if (utils.isElectron()) {
const windowService = require('../services/window'); handleElectronRedirect();
const { app } = require('electron'); } else {
windowService.createMainWindow(app);
windowService.closeSetupWindow();
}
else {
res.redirect('.'); res.redirect('.');
} }
@ -38,6 +34,13 @@ function setupPage(req: Request, res: Response) {
}); });
} }
async function handleElectronRedirect() {
const windowService = (await import("../services/window")).default;
const { app } = await import("electron");
windowService.createMainWindow(app);
windowService.closeSetupWindow();
}
export default { export default {
setupPage setupPage
}; };

View File

@ -1,3 +1,3 @@
import packageJson from "../../package.json"; import packageJson from "../../package.json" assert { type: "json" };
export default `assets/v${packageJson.version}`; export default `assets/v${packageJson.version}`;

View File

@ -16,6 +16,7 @@ import sanitizeAttributeName from "./sanitize_attribute_name.js";
import noteTypesService from "../services/note_types.js"; import noteTypesService from "../services/note_types.js";
import { BranchRow } from '../becca/entities/rows'; import { BranchRow } from '../becca/entities/rows';
import { EntityChange } from './entity_changes_interface'; import { EntityChange } from './entity_changes_interface';
import becca_loader from "../becca/becca_loader.js";
const noteTypes = noteTypesService.getNoteTypeNames(); const noteTypes = noteTypesService.getNoteTypeNames();
class ConsistencyChecks { class ConsistencyChecks {
@ -825,7 +826,7 @@ class ConsistencyChecks {
} }
if (this.reloadNeeded) { if (this.reloadNeeded) {
require('../becca/becca_loader').reload("consistency checks need becca reload"); becca_loader.reload("consistency checks need becca reload");
} }
return !this.unrecoveredConsistencyErrors; return !this.unrecoveredConsistencyErrors;

View File

@ -177,14 +177,16 @@ function eraseScheduledAttachments(eraseUnusedAttachmentsAfterSeconds: number |
eraseAttachments(attachmentIdsToErase); eraseAttachments(attachmentIdsToErase);
} }
sqlInit.dbReady.then(() => { export function startScheduledCleanup() {
// first cleanup kickoff 5 minutes after startup sqlInit.dbReady.then(() => {
setTimeout(cls.wrap(() => eraseDeletedEntities()), 5 * 60 * 1000); // first cleanup kickoff 5 minutes after startup
setTimeout(cls.wrap(() => eraseScheduledAttachments()), 6 * 60 * 1000); setTimeout(cls.wrap(() => eraseDeletedEntities()), 5 * 60 * 1000);
setTimeout(cls.wrap(() => eraseScheduledAttachments()), 6 * 60 * 1000);
setInterval(cls.wrap(() => eraseDeletedEntities()), 4 * 3600 * 1000);
setInterval(cls.wrap(() => eraseScheduledAttachments()), 3600 * 1000); setInterval(cls.wrap(() => eraseDeletedEntities()), 4 * 3600 * 1000);
}); setInterval(cls.wrap(() => eraseScheduledAttachments()), 3600 * 1000);
});
}
export default { export default {
eraseDeletedNotesNow, eraseDeletedNotesNow,
@ -192,5 +194,5 @@ export default {
eraseNotesWithDeleteId, eraseNotesWithDeleteId,
eraseUnusedBlobs, eraseUnusedBlobs,
eraseAttachments, eraseAttachments,
eraseRevisions eraseRevisions,
}; };

View File

@ -1,11 +1,11 @@
"use strict"; "use strict";
import marked from "marked"; import { parse } from "marked";
import htmlSanitizer from "../html_sanitizer.js"; import htmlSanitizer from "../html_sanitizer.js";
import importUtils from "./utils.js"; import importUtils from "./utils.js";
function renderToHtml(content: string, title: string) { function renderToHtml(content: string, title: string) {
const html = marked.parse(content, { const html = parse(content, {
async: false async: false
}) as string; }) as string;
const h1Handled = importUtils.handleH1(html, title); // h1 handling needs to come before sanitization const h1Handled = importUtils.handleH1(html, title); // h1 handling needs to come before sanitization

View File

@ -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.");
utils.crash(); await utils.crash();
return; return;
} }
@ -67,12 +67,12 @@ async function migrate() {
cls.setMigrationRunning(true); cls.setMigrationRunning(true);
sql.transactional(() => { sql.transactional(async () => {
for (const mig of migrations) { for (const mig of migrations) {
try { try {
log.info(`Attempting migration to version ${mig.dbVersion}`); log.info(`Attempting migration to version ${mig.dbVersion}`);
executeMigration(mig); await executeMigration(mig);
sql.execute(`UPDATE options sql.execute(`UPDATE options
SET value = ? SET value = ?
@ -84,7 +84,7 @@ async function migrate() {
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(); utils.crash();
break; // crash() above does not seem to work right away break; // crash() is sometimes async
} }
} }
}); });
@ -96,7 +96,7 @@ async function migrate() {
} }
} }
function executeMigration(mig: MigrationInfo) { async function executeMigration(mig: MigrationInfo) {
if (mig.type === 'sql') { if (mig.type === 'sql') {
const migrationSql = fs.readFileSync(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`).toString('utf8'); const migrationSql = fs.readFileSync(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`).toString('utf8');
@ -106,7 +106,7 @@ function executeMigration(mig: MigrationInfo) {
} else if (mig.type === 'js') { } else if (mig.type === 'js') {
console.log("Migration with JS module"); console.log("Migration with JS module");
const migrationModule = require(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`); const migrationModule = await import(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`);
migrationModule(); migrationModule();
} else { } else {
throw new Error(`Unknown migration type '${mig.type}'`); throw new Error(`Unknown migration type '${mig.type}'`);
@ -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.`);
utils.crash(); await utils.crash();
} }
if (!isDbUpToDate()) { if (!isDbUpToDate()) {

View File

@ -16,7 +16,7 @@ interface NotSyncedOpts {
syncProxy?: string; syncProxy?: string;
} }
function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts = {}) { async function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts = {}) {
optionService.createOption('openNoteContexts', JSON.stringify([ optionService.createOption('openNoteContexts', JSON.stringify([
{ {
notePath: 'root', notePath: 'root',
@ -37,7 +37,7 @@ function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts = {}) {
let theme = 'dark'; // default based on the poll in https://github.com/zadam/trilium/issues/2516 let theme = 'dark'; // default based on the poll in https://github.com/zadam/trilium/issues/2516
if (utils.isElectron()) { if (utils.isElectron()) {
const {nativeTheme} = require('electron'); const {nativeTheme} = await import("electron");
theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light'; theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
} }

View File

@ -2,6 +2,8 @@
import log from "./log.js"; import log from "./log.js";
import dataEncryptionService from "./encryption/data_encryption.js"; import dataEncryptionService from "./encryption/data_encryption.js";
import options from "./options.js";
import ws from "./ws.js";
let dataKey: Buffer | null = null; let dataKey: Buffer | null = null;
@ -56,7 +58,6 @@ function touchProtectedSession() {
} }
function checkProtectedSessionExpiration() { function checkProtectedSessionExpiration() {
const options = require('./options');
const protectedSessionTimeout = options.getOptionInt('protectedSessionTimeout'); const protectedSessionTimeout = options.getOptionInt('protectedSessionTimeout');
if (isProtectedSessionAvailable() if (isProtectedSessionAvailable()
&& lastProtectedSessionOperationDate && lastProtectedSessionOperationDate
@ -66,7 +67,7 @@ function checkProtectedSessionExpiration() {
log.info("Expiring protected session"); log.info("Expiring protected session");
require('./ws').reloadFrontend("leaving protected session"); ws.reloadFrontend("leaving protected session");
} }
} }

View File

@ -33,7 +33,7 @@ interface Client {
request(opts: ClientOpts): Request; request(opts: ClientOpts): Request;
} }
function exec<T>(opts: ExecOpts): Promise<T> { async function exec<T>(opts: ExecOpts): Promise<T> {
const client = getClient(opts); const client = getClient(opts);
// hack for cases where electron.net does not work, but we don't want to set proxy // hack for cases where electron.net does not work, but we don't want to set proxy
@ -47,10 +47,10 @@ function exec<T>(opts: ExecOpts): Promise<T> {
requestId: 'n/a' requestId: 'n/a'
}; };
const proxyAgent = getProxyAgent(opts); const proxyAgent = await getProxyAgent(opts);
const parsedTargetUrl = url.parse(opts.url); const parsedTargetUrl = url.parse(opts.url);
return new Promise((resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
const headers: Record<string, string | number> = { const headers: Record<string, string | number> = {
Cookie: (opts.cookieJar && opts.cookieJar.header) || "", Cookie: (opts.cookieJar && opts.cookieJar.header) || "",
@ -64,7 +64,7 @@ function exec<T>(opts: ExecOpts): Promise<T> {
headers['trilium-cred'] = Buffer.from(`dummy:${opts.auth.password}`).toString('base64'); headers['trilium-cred'] = Buffer.from(`dummy:${opts.auth.password}`).toString('base64');
} }
const request = client.request({ const request = (await client).request({
method: opts.method, method: opts.method,
// url is used by electron net module // url is used by electron net module
url: opts.url, url: opts.url,
@ -137,7 +137,7 @@ function exec<T>(opts: ExecOpts): Promise<T> {
}); });
} }
function getImage(imageUrl: string): Promise<Buffer> { async function getImage(imageUrl: string): Promise<Buffer> {
const proxyConf = syncOptions.getSyncProxy(); const proxyConf = syncOptions.getSyncProxy();
const opts: ClientOpts = { const opts: ClientOpts = {
method: 'GET', method: 'GET',
@ -145,8 +145,8 @@ function getImage(imageUrl: string): Promise<Buffer> {
proxy: proxyConf !== "noproxy" ? proxyConf : null proxy: proxyConf !== "noproxy" ? proxyConf : null
}; };
const client = getClient(opts); const client = await getClient(opts);
const proxyAgent = getProxyAgent(opts); const proxyAgent = await getProxyAgent(opts);
const parsedTargetUrl = url.parse(opts.url); const parsedTargetUrl = url.parse(opts.url);
return new Promise<Buffer>((resolve, reject) => { return new Promise<Buffer>((resolve, reject) => {
@ -189,7 +189,7 @@ function getImage(imageUrl: string): Promise<Buffer> {
const HTTP = 'http:', HTTPS = 'https:'; const HTTP = 'http:', HTTPS = 'https:';
function getProxyAgent(opts: ClientOpts) { async function getProxyAgent(opts: ClientOpts) {
if (!opts.proxy) { if (!opts.proxy) {
return null; return null;
} }
@ -201,25 +201,23 @@ function getProxyAgent(opts: ClientOpts) {
} }
const AgentClass = HTTP === protocol const AgentClass = HTTP === protocol
? require('http-proxy-agent').HttpProxyAgent ? (await import('http-proxy-agent')).HttpProxyAgent
: require('https-proxy-agent').HttpsProxyAgent; : (await import('https-proxy-agent')).HttpsProxyAgent;
return new AgentClass(opts.proxy); return new AgentClass(opts.proxy);
} }
function getClient(opts: ClientOpts): 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 (utils.isElectron() && !opts.proxy) {
return require('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);
if (protocol === 'http:' || protocol === 'https:') { if (protocol === 'http:' || protocol === 'https:') {
return require(protocol.substr(0, protocol.length - 1)); return await import(protocol.substr(0, protocol.length - 1));
} } else {
else {
throw new Error(`Unrecognized protocol '${protocol}'`); throw new Error(`Unrecognized protocol '${protocol}'`);
} }
} }

View File

@ -2,7 +2,8 @@ import log from "./log.js";
import path from "path"; import path from "path";
import fs from "fs"; import fs from "fs";
export const RESOURCE_DIR = path.resolve(__dirname, "../.."); import { fileURLToPath } from "url";
export const RESOURCE_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
// where the "trilium" executable is // where the "trilium" executable is
const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../.."); const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../..");

View File

@ -7,6 +7,7 @@ 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 utils from "../../utils.js";
import beccaService from "../../../becca/becca_service.js";
class NoteFlatTextExp extends Expression { class NoteFlatTextExp extends Expression {
private tokens: string[]; private tokens: string[];
@ -18,8 +19,6 @@ class NoteFlatTextExp extends Expression {
} }
execute(inputNoteSet: NoteSet, executionContext: any, searchContext: SearchContext) { execute(inputNoteSet: NoteSet, executionContext: any, searchContext: SearchContext) {
// has deps on SQL which breaks unit test so needs to be dynamically required
const beccaService = require('../../../becca/becca_service');
const resultNoteSet = new NoteSet(); const resultNoteSet = new NoteSet();
/** /**

View File

@ -15,11 +15,12 @@ import optionsInitService from "./options_init.js";
import BNote from "../becca/entities/bnote.js"; import BNote from "../becca/entities/bnote.js";
import BBranch from "../becca/entities/bbranch.js"; import BBranch from "../becca/entities/bbranch.js";
import zipImportService from "./import/zip.js"; import zipImportService from "./import/zip.js";
import becca_loader from "../becca/becca_loader.js";
import password from "./encryption/password.js";
import backup from "./backup.js";
const dbReady = utils.deferred<void>(); const dbReady = utils.deferred<void>();
cls.init(initDbConnection);
function schemaExists() { function schemaExists() {
return !!sql.getValue(`SELECT name FROM sqlite_master return !!sql.getValue(`SELECT name FROM sqlite_master
WHERE type = 'table' AND name = 'options'`); WHERE type = 'table' AND name = 'options'`);
@ -65,7 +66,7 @@ async function createInitialDatabase() {
sql.executeScript(schema); sql.executeScript(schema);
require('../becca/becca_loader').load(); becca_loader.load();
log.info("Creating root note ..."); log.info("Creating root note ...");
@ -88,7 +89,7 @@ async function createInitialDatabase() {
optionsInitService.initDocumentOptions(); optionsInitService.initDocumentOptions();
optionsInitService.initNotSyncedOptions(true, {}); optionsInitService.initNotSyncedOptions(true, {});
optionsInitService.initStartupOptions(); optionsInitService.initStartupOptions();
require('./encryption/password').resetPassword(); password.resetPassword();
}); });
log.info("Importing demo content ..."); log.info("Importing demo content ...");
@ -129,7 +130,7 @@ function createDatabaseForSync(options: OptionRow[], syncServerHost = '', syncPr
sql.transactional(() => { sql.transactional(() => {
sql.executeScript(schema); sql.executeScript(schema);
require('./options_init').initNotSyncedOptions(false, { syncServerHost, syncProxy }); optionsInitService.initNotSyncedOptions(false, { syncServerHost, syncProxy });
// document options required for sync to kick off // document options required for sync to kick off
for (const opt of options) { for (const opt of options) {
@ -157,29 +158,33 @@ function optimize() {
log.info(`Optimization finished in ${Date.now() - start}ms.`); log.info(`Optimization finished in ${Date.now() - start}ms.`);
} }
dbReady.then(() => {
if (config.General && config.General.noBackup === true) {
log.info("Disabling scheduled backups.");
return;
}
setInterval(() => require('./backup').regularBackup(), 4 * 60 * 60 * 1000);
// kickoff first backup soon after start up
setTimeout(() => require('./backup').regularBackup(), 5 * 60 * 1000);
// optimize is usually inexpensive no-op, so running it semi-frequently is not a big deal
setTimeout(() => optimize(), 60 * 60 * 1000);
setInterval(() => optimize(), 10 * 60 * 60 * 1000);
});
function getDbSize() { function getDbSize() {
return sql.getValue<number>("SELECT page_count * page_size / 1000 as size FROM pragma_page_count(), pragma_page_size()"); return sql.getValue<number>("SELECT page_count * page_size / 1000 as size FROM pragma_page_count(), pragma_page_size()");
} }
log.info(`DB size: ${getDbSize()} KB`); function initializeDb() {
cls.init(initDbConnection);
log.info(`DB size: ${getDbSize()} KB`);
dbReady.then(() => {
if (config.General && config.General.noBackup === true) {
log.info("Disabling scheduled backups.");
return;
}
setInterval(() => backup.regularBackup(), 4 * 60 * 60 * 1000);
// kickoff first backup soon after start up
setTimeout(() => backup.regularBackup(), 5 * 60 * 1000);
// optimize is usually inexpensive no-op, so running it semi-frequently is not a big deal
setTimeout(() => optimize(), 60 * 60 * 1000);
setInterval(() => optimize(), 10 * 60 * 60 * 1000);
});
}
export default { export default {
dbReady, dbReady,
@ -188,5 +193,6 @@ export default {
createInitialDatabase, createInitialDatabase,
createDatabaseForSync, createDatabaseForSync,
setDbAsInitialized, setDbAsInitialized,
getDbSize getDbSize,
initializeDb
}; };

View File

@ -21,6 +21,7 @@ import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_in
import { CookieJar, ExecOpts } from './request_interface'; import { CookieJar, ExecOpts } from './request_interface';
import setupService from "./setup.js"; import setupService from "./setup.js";
import consistency_checks from "./consistency_checks.js"; import consistency_checks from "./consistency_checks.js";
import becca_loader from "../becca/becca_loader.js";
let proxyToggle = true; let proxyToggle = true;
@ -442,7 +443,7 @@ function getOutstandingPullCount() {
return outstandingPullCount; return outstandingPullCount;
} }
require('../becca/becca_loader').beccaLoaded.then(() => { becca_loader.beccaLoaded.then(() => {
setInterval(cls.wrap(sync), 60000); setInterval(cls.wrap(sync), 60000);
// kickoff initial sync immediately, but should happen after initial consistency checks // kickoff initial sync immediately, but should happen after initial consistency checks

View File

@ -2,12 +2,14 @@ import { Menu, Tray } from 'electron';
import path from "path"; import path from "path";
import windowService from "./window.js"; import windowService from "./window.js";
import optionService from "./options.js"; import optionService from "./options.js";
import { fileURLToPath } from "url";
let tray: Tray; let tray: Tray;
// `mainWindow.isVisible` doesn't work with `mainWindow.show` and `mainWindow.hide` - it returns `false` when the window // `mainWindow.isVisible` doesn't work with `mainWindow.show` and `mainWindow.hide` - it returns `false` when the window
// is minimized // is minimized
let isVisible = true; let isVisible = true;
// Inspired by https://github.com/signalapp/Signal-Desktop/blob/dcb5bb672635c4b29a51adec8a5658e3834ec8fc/app/tray_icon.ts#L20 // Inspired by https://github.com/signalapp/Signal-Desktop/blob/dcb5bb672635c4b29a51adec8a5658e3834ec8fc/app/tray_icon.ts#L20
const getIconSize = () => { const getIconSize = () => {
switch (process.platform) { switch (process.platform) {
@ -23,7 +25,7 @@ const getIconPath = () => {
const iconSize = getIconSize(); const iconSize = getIconSize();
return path.join( return path.join(
__dirname, path.dirname(fileURLToPath(import.meta.url)),
"../..", "../..",
"images", "images",
"app-icons", "app-icons",

View File

@ -125,11 +125,10 @@ function escapeRegExp(str: string) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
} }
function crash() { async function crash() {
if (isElectron()) { if (isElectron()) {
require('electron').app.exit(1); (await import("electron")).app.exit(1);
} } else {
else {
process.exit(1); process.exit(1);
} }
} }

View File

@ -10,6 +10,9 @@ import keyboardActionsService from "./keyboard_actions.js";
import remoteMain from "@electron/remote/main" import remoteMain from "@electron/remote/main"
import { App, BrowserWindow, WebContents, ipcMain } from 'electron'; import { App, BrowserWindow, WebContents, ipcMain } from 'electron';
import { fileURLToPath } from "url";
import { dirname } from "path";
// Prevent the window being garbage collected // Prevent the window being garbage collected
let mainWindow: BrowserWindow | null; let mainWindow: BrowserWindow | null;
let setupWindow: BrowserWindow | null; let setupWindow: BrowserWindow | null;
@ -17,7 +20,7 @@ let setupWindow: BrowserWindow | null;
async function createExtraWindow(extraWindowHash: string) { async function createExtraWindow(extraWindowHash: string) {
const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled');
const { BrowserWindow } = require('electron'); const { BrowserWindow } = await import('electron');
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 1000, width: 1000,
@ -43,7 +46,7 @@ ipcMain.on('create-extra-window', (event, arg) => {
}); });
async function createMainWindow(app: App) { async function createMainWindow(app: App) {
const windowStateKeeper = require('electron-window-state'); // should not be statically imported const windowStateKeeper = (await import('electron-window-state')).default; // should not be statically imported
const mainWindowState = windowStateKeeper({ const mainWindowState = windowStateKeeper({
// default window width & height, so it's usable on a 1600 * 900 display (including some extra panels etc.) // default window width & height, so it's usable on a 1600 * 900 display (including some extra panels etc.)
@ -53,7 +56,7 @@ async function createMainWindow(app: App) {
const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled');
const { BrowserWindow } = require('electron'); // should not be statically imported const { BrowserWindow } = (await import('electron')); // should not be statically imported
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
x: mainWindowState.x, x: mainWindowState.x,
@ -100,7 +103,11 @@ function configureWebContents(webContents: WebContents, spellcheckEnabled: boole
remoteMain.enable(webContents); remoteMain.enable(webContents);
mainWindow.webContents.setWindowOpenHandler((details) => { mainWindow.webContents.setWindowOpenHandler((details) => {
require('electron').shell.openExternal(details.url); async function openExternal() {
(await import('electron')).shell.openExternal(details.url);
}
openExternal();
return { action: 'deny' } return { action: 'deny' }
}); });
@ -124,11 +131,11 @@ function configureWebContents(webContents: WebContents, spellcheckEnabled: boole
} }
function getIcon() { function getIcon() {
return path.join(__dirname, '../../images/app-icons/png/256x256' + (env.isDev() ? '-dev' : '') + '.png'); return path.join(dirname(fileURLToPath(import.meta.url)), '../../images/app-icons/png/256x256' + (env.isDev() ? '-dev' : '') + '.png');
} }
async function createSetupWindow() { async function createSetupWindow() {
const { BrowserWindow } = require('electron'); // should not be statically imported const { BrowserWindow } = await import("electron"); // should not be statically imported
setupWindow = new BrowserWindow({ setupWindow = new BrowserWindow({
width: 800, width: 800,
height: 800, height: 800,
@ -152,7 +159,7 @@ function closeSetupWindow() {
} }
async function registerGlobalShortcuts() { async function registerGlobalShortcuts() {
const { globalShortcut } = require('electron'); const { globalShortcut } = await import("electron");
await sqlInit.dbReady; await sqlInit.dbReady;

View File

@ -14,8 +14,8 @@ import { IncomingMessage, Server } from 'http';
import { EntityChange } from './entity_changes_interface'; import { EntityChange } from './entity_changes_interface';
if (env.isDev()) { if (env.isDev()) {
const chokidar = require('chokidar'); const chokidar = (await import("chokidar")).default;
const debounce = require('debounce'); 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('src/public') .watch('src/public')

View File

@ -1,13 +1,8 @@
import shaca from "../shaca";
import Shaca from "../shaca-interface"; import Shaca from "../shaca-interface";
let shaca: Shaca;
class AbstractShacaEntity { class AbstractShacaEntity {
get shaca(): Shaca { get shaca(): Shaca {
if (!shaca) {
shaca = require('../shaca');
}
return shaca; return shaca;
} }
} }

View File

@ -2,16 +2,21 @@
import Database from "better-sqlite3"; import Database from "better-sqlite3";
import dataDir from "../services/data_dir.js"; import dataDir from "../services/data_dir.js";
import sql_init from "../services/sql_init.js";
const dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true }); let dbConnection!: Database.Database;
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => { sql_init.dbReady.then(() => {
process.on(eventType, () => { dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true });
if (dbConnection) {
// closing connection is especially important to fold -wal file into the main DB file [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => {
// (see https://sqlite.org/tempfiles.html for details) process.on(eventType, () => {
dbConnection.close(); if (dbConnection) {
} // closing connection is especially important to fold -wal file into the main DB file
// (see https://sqlite.org/tempfiles.html for details)
dbConnection.close();
}
});
}); });
}); });

View File

@ -39,7 +39,7 @@ if (!semver.satisfies(process.version, ">=10.5.0")) {
startTrilium(); startTrilium();
function startTrilium() { async function startTrilium() {
/** /**
* The intended behavior is to detect when a second instance is running, in that case open the old instance * The intended behavior is to detect when a second instance is running, in that case open the old instance
* instead of the new one. This is complicated by the fact that it is possible to run multiple instances of Trilium * instead of the new one. This is complicated by the fact that it is possible to run multiple instances of Trilium
@ -54,12 +54,12 @@ function startTrilium() {
* to do a complex evaluation. * to do a complex evaluation.
*/ */
if (utils.isElectron()) { if (utils.isElectron()) {
require('electron').app.requestSingleInstanceLock(); (await import('electron')).app.requestSingleInstanceLock();
} }
log.info(JSON.stringify(appInfo, null, 2)); log.info(JSON.stringify(appInfo, null, 2));
const cpuInfos = require('os').cpus(); const cpuInfos = (await import('os')).cpus();
if (cpuInfos && cpuInfos[0] !== undefined) { // https://github.com/zadam/trilium/pull/3957 if (cpuInfos && cpuInfos[0] !== undefined) { // https://github.com/zadam/trilium/pull/3957
log.info(`CPU model: ${cpuInfos[0].model}, logical cores: ${cpuInfos.length} freq: ${cpuInfos[0].speed} Mhz`); // for perf. issues it's good to know the rough configuration log.info(`CPU model: ${cpuInfos[0].model}, logical cores: ${cpuInfos.length} freq: ${cpuInfos[0].speed} Mhz`); // for perf. issues it's good to know the rough configuration
} }
@ -69,8 +69,8 @@ function startTrilium() {
ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible. ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible.
if (utils.isElectron()) { if (utils.isElectron()) {
const electronRouting = require('./routes/electron'); const electronRouting = await import('./routes/electron');
electronRouting(app); electronRouting.default(app);
} }
} }

View File

@ -1,8 +1,8 @@
{ {
"compilerOptions": { "compilerOptions": {
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"module": "ES2015", "module": "ESNext",
"target": "ES2018", "target": "ES2020",
"declaration": false, "declaration": false,
"sourceMap": true, "sourceMap": true,
"outDir": "./build", "outDir": "./build",
@ -22,9 +22,6 @@
"./spec-es6/**/*.ts" "./spec-es6/**/*.ts"
], ],
"exclude": ["./node_modules/**/*"], "exclude": ["./node_modules/**/*"],
"ts-node": {
"files": true
},
"files": [ "files": [
"src/types.d.ts" "src/types.d.ts"
] ]

View File

@ -1,7 +1,9 @@
import { fileURLToPath } from "url";
import path from "path"; import path from "path";
import assetPath from "./src/services/asset_path.js"; import assetPath from "./src/services/asset_path.js";
module.exports = { const rootDir = path.dirname(fileURLToPath(import.meta.url));
export default {
mode: 'production', mode: 'production',
entry: { entry: {
setup: './src/public/app/setup.js', setup: './src/public/app/setup.js',
@ -10,7 +12,7 @@ module.exports = {
}, },
output: { output: {
publicPath: `${assetPath}/app-dist/`, publicPath: `${assetPath}/app-dist/`,
path: path.resolve(__dirname, 'src/public/app-dist'), path: path.resolve(rootDir, 'src/public/app-dist'),
filename: '[name].js', filename: '[name].js',
}, },
devtool: 'source-map', devtool: 'source-map',