diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a43a1858d..ba0c747fb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: branches: - 'develop' - 'feature/update*' + - 'feature/server_esm*' paths-ignore: - 'docs/**' diff --git a/bin/better-sqlite3/linux-desktop-better_sqlite3.node b/bin/better-sqlite3/linux-desktop-better_sqlite3.node old mode 100644 new mode 100755 index 180186307..dc587cec5 Binary files a/bin/better-sqlite3/linux-desktop-better_sqlite3.node and b/bin/better-sqlite3/linux-desktop-better_sqlite3.node differ diff --git a/bin/better-sqlite3/linux-server-better_sqlite3.node b/bin/better-sqlite3/linux-server-better_sqlite3.node old mode 100644 new mode 100755 index ca173a3c6..00c00a96f Binary files a/bin/better-sqlite3/linux-server-better_sqlite3.node and b/bin/better-sqlite3/linux-server-better_sqlite3.node differ diff --git a/bin/better-sqlite3/mac-arm64-better_sqlite3.node b/bin/better-sqlite3/mac-arm64-better_sqlite3.node old mode 100644 new mode 100755 index 9709dcd23..3eadd64bc Binary files a/bin/better-sqlite3/mac-arm64-better_sqlite3.node and b/bin/better-sqlite3/mac-arm64-better_sqlite3.node differ diff --git a/bin/better-sqlite3/mac-x64-better_sqlite3.node b/bin/better-sqlite3/mac-x64-better_sqlite3.node old mode 100644 new mode 100755 index 70835a3f8..0bb7c6a56 Binary files a/bin/better-sqlite3/mac-x64-better_sqlite3.node and b/bin/better-sqlite3/mac-x64-better_sqlite3.node differ diff --git a/bin/better-sqlite3/update.sh b/bin/better-sqlite3/update.sh new file mode 100755 index 000000000..74dbeb01b --- /dev/null +++ b/bin/better-sqlite3/update.sh @@ -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" \ No newline at end of file diff --git a/bin/better-sqlite3/win-better_sqlite3.node b/bin/better-sqlite3/win-better_sqlite3.node index b5ced20b5..5020e45eb 100644 Binary files a/bin/better-sqlite3/win-better_sqlite3.node and b/bin/better-sqlite3/win-better_sqlite3.node differ diff --git a/bin/build-debian.sh b/bin/build-debian.sh index d973d2f36..ecf88f359 100755 --- a/bin/build-debian.sh +++ b/bin/build-debian.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + if ! command -v dpkg-deb &> /dev/null; then echo "Missing command: dpkg-deb" exit 1 diff --git a/bin/build-docker.sh b/bin/build-docker.sh index 2b3794677..9d614eb2b 100755 --- a/bin/build-docker.sh +++ b/bin/build-docker.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + VERSION=`jq -r ".version" package.json` SERIES=${VERSION:0:4}-latest diff --git a/bin/build-linux-x64.sh b/bin/build-linux-x64.sh index 7b7b91a8a..90d179f2d 100755 --- a/bin/build-linux-x64.sh +++ b/bin/build-linux-x64.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + if ! command -v jq &> /dev/null; then echo "Missing command: jq" exit 1 @@ -24,8 +26,6 @@ SRC_DIR=./dist/trilium-linux-x64-src [ "$1" != "DONTCOPY" ] && ./bin/copy-trilium.sh "$SRC_DIR" -rm -r "$SRC_DIR"/src/public/app-dist/*.mobile.* - 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 @@ -55,4 +55,4 @@ pushd dist tar cJf "trilium-linux-x64-${VERSION}.tar.xz" trilium-linux-x64 popd -bin/build-debian.sh +#bin/build-debian.sh diff --git a/bin/build-mac-arm64.sh b/bin/build-mac-arm64.sh index 219435344..c1b4ff144 100755 --- a/bin/build-mac-arm64.sh +++ b/bin/build-mac-arm64.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + SRC_DIR=./dist/trilium-mac-arm64-src 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 -rm -r $SRC_DIR/src/public/app-dist/*.mobile.* - 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 @@ -34,5 +34,4 @@ VERSION=`jq -r ".version" package.json` cd dist -rm trilium-mac-arm64-${VERSION}.zip zip -r9 --symlinks trilium-mac-arm64-${VERSION}.zip trilium-mac-arm64 diff --git a/bin/build-mac-x64.sh b/bin/build-mac-x64.sh index ba05322ae..890cf6d3d 100755 --- a/bin/build-mac-x64.sh +++ b/bin/build-mac-x64.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + SRC_DIR=./dist/trilium-mac-x64-src 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 -rm -r $SRC_DIR/src/public/app-dist/*.mobile.* - 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 @@ -34,5 +34,4 @@ VERSION=`jq -r ".version" package.json` cd dist -rm trilium-mac-x64-${VERSION}.zip zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64 diff --git a/bin/build-server.sh b/bin/build-server.sh index 94a3650ef..33a93bf5a 100755 --- a/bin/build-server.sh +++ b/bin/build-server.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + PKG_DIR=dist/trilium-linux-x64-server 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_modules/electron* -rm -r $PKG_DIR/webpack* 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 diff --git a/bin/build-win-x64.sh b/bin/build-win-x64.sh index f71296cd5..1d5780d2a 100755 --- a/bin/build-win-x64.sh +++ b/bin/build-win-x64.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + if ! command -v wine &> /dev/null; then echo "Missing command: wine" 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 -rm -r $SRC_DIR/src/public/app-dist/*.mobile.* - 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 diff --git a/bin/build.sh b/bin/build.sh index 513bd1129..7fb41cfcb 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e # Fail on any command error + if ! command -v jq &> /dev/null; then echo "Missing command: jq" 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-arm64-src -set -e bin/build-win-x64.sh DONTCOPY bin/build-mac-x64.sh DONTCOPY diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh index c8b38e25c..9f63aaaa8 100755 --- a/bin/copy-trilium.sh +++ b/bin/copy-trilium.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash +set -e # Fail on any command error shopt -s globstar if [[ $# -eq 0 ]] ; then diff --git a/bin/update-build-info.ts b/bin/update-build-info.ts index 94b56b606..d1c327b7d 100644 --- a/bin/update-build-info.ts +++ b/bin/update-build-info.ts @@ -16,7 +16,7 @@ function getGitRevision() { } const output = `\ -export = { +export default { buildDate: "${getBuildDate()}", buildRevision: "${getGitRevision()}" }; diff --git a/electron.ts b/electron.ts index 754b73bac..5c112d56d 100644 --- a/electron.ts +++ b/electron.ts @@ -9,7 +9,7 @@ import windowService from "./src/services/window.js"; import tray from "./src/services/tray.js"; // 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); } @@ -67,4 +67,4 @@ electron.app.on("will-quit", () => { // this is to disable electron warning spam in the dev console (local development only) process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true"; -require('./src/www.js'); +await import('./src/www.js'); diff --git a/forge.config.js b/forge.config.cjs similarity index 100% rename from forge.config.js rename to forge.config.cjs diff --git a/nodemon.json b/nodemon.json index 86e1c2ca4..1266e1b4c 100644 --- a/nodemon.json +++ b/nodemon.json @@ -2,7 +2,7 @@ "restartable": "rs", "ignore": [".git", "node_modules/**/node_modules", "src/public/"], "verbose": false, - "exec": "ts-node", + "exec": "tsx", "watch": ["src/"], "signal": "SIGTERM", "env": { diff --git a/package-lock.json b/package-lock.json index c1d41949a..a6818fc89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,11 @@ "@braintree/sanitize-url": "^7.1.0", "@electron/remote": "2.1.2", "@excalidraw/excalidraw": "^0.17.6", + "@types/electron-squirrel-startup": "^1.0.2", "archiver": "^7.0.1", "async-mutex": "^0.5.0", "axios": "^1.7.2", - "better-sqlite3": "8.5.0", + "better-sqlite3": "^11.1.2", "boxicons": "2.1.4", "chokidar": "3.6.0", "cls-hooked": "4.2.2", @@ -58,7 +59,7 @@ "mermaid": "^10.9.1", "mime-types": "2.1.35", "multer": "1.4.5-lts.1", - "node-abi": "3.56.0", + "node-abi": "^3.65.0", "normalize-strings": "1.1.1", "panzoom": "9.4.3", "print-this": "2.0.0", @@ -97,6 +98,7 @@ "@types/compression": "^1.7.5", "@types/cookie-parser": "^1.4.7", "@types/csurf": "^1.11.5", + "@types/debounce": "^1.2.4", "@types/ejs": "^3.1.5", "@types/escape-html": "^1.0.4", "@types/express": "^4.17.21", @@ -107,7 +109,6 @@ "@types/jsdom": "^21.1.6", "@types/mime-types": "^2.1.4", "@types/multer": "^1.4.11", - "@types/node": "^20.11.19", "@types/safe-compare": "^1.1.2", "@types/sanitize-html": "^2.11.0", "@types/sax": "^1.2.7", @@ -120,7 +121,7 @@ "@types/ws": "^8.5.10", "@types/xml2js": "^0.4.14", "cross-env": "7.0.3", - "electron": "25.9.8", + "electron": "^31.2.1", "electron-packager": "17.1.2", "electron-rebuild": "3.2.9", "esm": "3.2.25", @@ -132,6 +133,7 @@ "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tslib": "^2.6.2", + "tsx": "^4.16.2", "typescript": "^5.3.3", "webpack": "^5.93.0", "webpack-cli": "5.1.4" @@ -1389,6 +1391,22 @@ "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": { "version": "0.17.6", "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", "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": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", @@ -2222,6 +2246,11 @@ "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "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": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.4.tgz", @@ -2447,9 +2476,9 @@ } }, "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dependencies": { "undici-types": "~5.26.4" } @@ -3206,6 +3235,11 @@ "@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": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3228,6 +3262,21 @@ "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": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -3371,9 +3420,10 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "node_modules/asar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", - "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", + "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", "optional": true, "dependencies": { "chromium-pickle-js": "^0.2.0", @@ -3572,13 +3622,13 @@ } }, "node_modules/better-sqlite3": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.5.0.tgz", - "integrity": "sha512-vbPcv/Hx5WYdyNg/NbcfyaBZyv9s/NVbxb7yCeC5Bq1pVocNxeL2tZmSu3Rlm4IEOTjYdGyzWQgyx0OSdORBzw==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz", + "integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==", "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", - "prebuild-install": "^7.1.0" + "prebuild-install": "^7.1.1" } }, "node_modules/bezier-easing": { @@ -5760,13 +5810,13 @@ } }, "node_modules/electron": { - "version": "25.9.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-25.9.8.tgz", - "integrity": "sha512-PGgp6PH46QVENHuAHc2NT1Su8Q1qov7qIl2jI5tsDpTibwV2zD8539AeWBQySeBU4dhbj9onIl7+1bXQ0wefBg==", + "version": "31.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.2.1.tgz", + "integrity": "sha512-g3CLKjl4yuXt6VWm/KpgEjYYhFiCl19RgUn8lOC8zV/56ZXAS3+mqV4wWzicE/7vSYXs6GRO7vkYRwrwhX3Gaw==", "hasInstallScript": true, "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^18.11.18", + "@types/node": "^20.9.0", "extract-zip": "^2.0.1" }, "bin": { @@ -5858,9 +5908,9 @@ } }, "node_modules/electron-installer-common/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "optional": true, "engines": { "node": ">= 10.0.0" @@ -5920,9 +5970,9 @@ } }, "node_modules/electron-installer-debian/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "optional": true, "engines": { "node": ">= 10.0.0" @@ -6203,14 +6253,6 @@ "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": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.2.tgz", @@ -6322,6 +6364,44 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "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": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -7323,6 +7403,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "optional": true }, "node_modules/get-caller-file": { @@ -7408,6 +7489,18 @@ "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": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -8617,9 +8710,9 @@ } }, "node_modules/jsdom": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", - "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", + "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -8627,11 +8720,11 @@ "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "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", - "nwsapi": "^2.2.10", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", @@ -8640,7 +8733,7 @@ "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.17.0", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -10124,9 +10217,9 @@ "dev": true }, "node_modules/node-abi": { - "version": "3.56.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", - "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", "dependencies": { "semver": "^7.3.5" }, @@ -10837,29 +10930,35 @@ "dev": true }, "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==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, "dependencies": { - "lru-cache": "^10.2.0", + "lru-cache": "^9.1.1 || ^10.0.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/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==" + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", + "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } }, "node_modules/path-scurry/node_modules/minipass": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", + "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -11720,6 +11819,15 @@ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", "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": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -13024,7 +13132,7 @@ "node_modules/tiny-each-async": { "version": "2.0.3", "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 }, "node_modules/tiny-invariant": { @@ -13255,6 +13363,25 @@ "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": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -13842,9 +13969,9 @@ "dev": true }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "optional": true, "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index ea74bfe48..1aa887245 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,13 @@ "type": "git", "url": "https://github.com/TriliumNext/Notes.git" }, + "type": "module", "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-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", - "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-no-dir": "npm run prepare-dist && cross-env TRILIUM_SAFE_MODE=1 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": "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 .", "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", @@ -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-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", - "webpack": "webpack -c webpack.config.ts", - "test-jasmine": "cross-env TRILIUM_DATA_DIR=./data-test ts-node ./node_modules/jasmine/bin/jasmine", - "test-es6": "ts-node -r esm spec-es6/attribute_parser.spec.ts", + "webpack": "cross-env NODE_OPTIONS=--loader=ts-node/esm webpack -c webpack.config.ts", + "test-jasmine": "cross-env TRILIUM_DATA_DIR=./data-test tsx ./node_modules/.bin/jasmine", + "test-es6": "tsx -r esm spec-es6/attribute_parser.spec.ts", "test": "npm run test-jasmine && npm run test-es6", "start-electron-forge": "npm run prepare-dist && electron-forge start", "make-electron": "npm run webpack && npm run prepare-dist && electron-forge make", "package-electron": "electron-forge package", - "prepare-dist": "rimraf ./dist && tsc && ts-node ./bin/copy-dist.ts", - "update-build-info": "ts-node bin/update-build-info.ts", + "prepare-dist": "rimraf ./dist && tsc && tsx ./bin/copy-dist.ts", + "update-build-info": "tsx bin/update-build-info.ts", "errors": "tsc --watch --noEmit" }, "dependencies": { "@braintree/sanitize-url": "^7.1.0", "@electron/remote": "2.1.2", "@excalidraw/excalidraw": "^0.17.6", + "@types/electron-squirrel-startup": "^1.0.2", "archiver": "^7.0.1", "async-mutex": "^0.5.0", "axios": "^1.7.2", - "better-sqlite3": "8.5.0", + "better-sqlite3": "^11.1.2", "boxicons": "2.1.4", "chokidar": "3.6.0", "cls-hooked": "4.2.2", @@ -94,7 +96,7 @@ "mermaid": "^10.9.1", "mime-types": "2.1.35", "multer": "1.4.5-lts.1", - "node-abi": "3.56.0", + "node-abi": "^3.65.0", "normalize-strings": "1.1.1", "panzoom": "9.4.3", "print-this": "2.0.0", @@ -130,6 +132,7 @@ "@types/compression": "^1.7.5", "@types/cookie-parser": "^1.4.7", "@types/csurf": "^1.11.5", + "@types/debounce": "^1.2.4", "@types/ejs": "^3.1.5", "@types/escape-html": "^1.0.4", "@types/express": "^4.17.21", @@ -140,7 +143,6 @@ "@types/jsdom": "^21.1.6", "@types/mime-types": "^2.1.4", "@types/multer": "^1.4.11", - "@types/node": "^20.11.19", "@types/safe-compare": "^1.1.2", "@types/sanitize-html": "^2.11.0", "@types/sax": "^1.2.7", @@ -153,7 +155,7 @@ "@types/ws": "^8.5.10", "@types/xml2js": "^0.4.14", "cross-env": "7.0.3", - "electron": "25.9.8", + "electron": "^31.2.1", "electron-packager": "17.1.2", "electron-rebuild": "3.2.9", "esm": "3.2.25", @@ -165,6 +167,7 @@ "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tslib": "^2.6.2", + "tsx": "^4.16.2", "typescript": "^5.3.3", "webpack": "^5.93.0", "webpack-cli": "5.1.4" diff --git a/spec/etapi/import.ts b/spec/etapi/import.ts index 88c9e0a88..942a9871f 100644 --- a/spec/etapi/import.ts +++ b/spec/etapi/import.ts @@ -1,12 +1,15 @@ import etapi from "../support/etapi.js"; import fs from "fs"; import path from "path"; +import { fileURLToPath } from "url"; etapi.describeEtapi("import", () => { // temporarily skip this test since test-export.zip is missing xit("import", async () => { + const scriptDir = path.dirname(fileURLToPath(import.meta.url)); + const zipFileBuffer = fs.readFileSync( - path.resolve(__dirname, "test-export.zip") + path.resolve(scriptDir, "test-export.zip") ); const response = await etapi.postEtapiContent( diff --git a/src/anonymize.ts b/src/anonymize.ts index 89f9d2d0c..15fb4dde0 100644 --- a/src/anonymize.ts +++ b/src/anonymize.ts @@ -1,6 +1,6 @@ import anonymizationService from "./services/anonymization.js"; import sqlInit from "./services/sql_init.js"; -require('./becca/entity_constructor'); +await import("./becca/entity_constructor"); sqlInit.dbReady.then(async () => { try { diff --git a/src/app.ts b/src/app.ts index e6da1bcfe..0260d30e5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,16 +4,29 @@ import favicon from "serve-favicon"; import cookieParser from "cookie-parser"; import helmet from "helmet"; import compression from "compression"; +import { fileURLToPath } from "url"; +import { dirname } from "path"; import sessionParser from "./routes/session_parser.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'); -require('./becca/becca_loader'); +await import('./services/handlers'); +await import('./becca/becca_loader'); const app = express(); +const scriptDir = dirname(fileURLToPath(import.meta.url)); + +// Initialize DB +sql_init.initializeDb(); + // view engine setup -app.set('views', path.join(__dirname, 'views')); +app.set('views', path.join(scriptDir, 'views')); app.set('view engine', 'ejs'); if (!utils.isElectron()) { @@ -31,30 +44,32 @@ app.use(express.json({ limit: '500mb' })); app.use(express.raw({ limit: '500mb' })); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'public/root'))); -app.use(`/manifest.webmanifest`, express.static(path.join(__dirname, 'public/manifest.webmanifest'))); -app.use(`/robots.txt`, express.static(path.join(__dirname, 'public/robots.txt'))); +app.use(express.static(path.join(scriptDir, 'public/root'))); +app.use(`/manifest.webmanifest`, express.static(path.join(scriptDir, 'public/manifest.webmanifest'))); +app.use(`/robots.txt`, express.static(path.join(scriptDir, 'public/robots.txt'))); 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); -require('./routes/routes').register(app); -require('./routes/custom').register(app); -require('./routes/error_handlers').register(app); +assets.register(app); +routes.register(app); +custom.register(app); +error_handlers.register(app); // triggers sync timer -require('./services/sync'); +await import("./services/sync"); // triggers backup timer -require('./services/backup'); +await import('./services/backup'); // trigger consistency checks timer -require('./services/consistency_checks'); +await import('./services/consistency_checks'); -require('./services/scheduler'); +await import('./services/scheduler'); + +startScheduledCleanup(); if (utils.isElectron()) { - require('@electron/remote/main').initialize(); + (await import('@electron/remote/main')).initialize(); } export default app; diff --git a/src/becca/entities/abstract_becca_entity.ts b/src/becca/entities/abstract_becca_entity.ts index 67d7d6031..1259217df 100644 --- a/src/becca/entities/abstract_becca_entity.ts +++ b/src/becca/entities/abstract_becca_entity.ts @@ -10,8 +10,7 @@ import log from "../../services/log.js"; import protectedSessionService from "../../services/protected_session.js"; import blobService from "../../services/blob.js"; import Becca, { ConstructorData } from '../becca-interface'; - -let becca: Becca; +import becca from "../becca.js"; interface ContentOpts { forceSave?: boolean; @@ -47,11 +46,7 @@ abstract class AbstractBeccaEntity> { } protected get becca(): Becca { - if (!becca) { - becca = require('../becca'); - } - - return becca as Becca; + return becca; } protected putEntityChange(isDeleted: boolean) { diff --git a/src/etapi/spec.ts b/src/etapi/spec.ts index a5cad4c2a..9c183e9c1 100644 --- a/src/etapi/spec.ts +++ b/src/etapi/spec.ts @@ -3,7 +3,8 @@ import { Router } from "express"; import fs from "fs"; 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; function register(router: Router) { diff --git a/src/etapi/validators.ts b/src/etapi/validators.ts index 81ab051d0..37aafecef 100644 --- a/src/etapi/validators.ts +++ b/src/etapi/validators.ts @@ -1,5 +1,6 @@ import noteTypeService from "../services/note_types.js"; import dateUtils from "../services/date_utils.js"; +import becca from "../becca/becca.js"; function mandatory(obj: unknown) { if (obj === undefined) { @@ -64,8 +65,6 @@ function isNoteId(obj: unknown) { return; } - const becca = require('../becca/becca'); - if (typeof obj !== 'string') { return `'${obj}' is not a valid noteId`; } diff --git a/src/routes/assets.ts b/src/routes/assets.ts index a03819a83..a1004e33b 100644 --- a/src/routes/assets.ts +++ b/src/routes/assets.ts @@ -1,5 +1,6 @@ import assetPath from "../services/asset_path.js"; import path from "path"; +import { fileURLToPath } from "url"; import express from "express"; import env from "../services/env.js"; import serveStatic from "serve-static"; @@ -15,7 +16,7 @@ const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOp }; 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-dist`, persistentCacheStatic(path.join(srcRoot, 'public/app-dist'))); app.use(`/${assetPath}/fonts`, persistentCacheStatic(path.join(srcRoot, 'public/fonts'))); diff --git a/src/routes/electron.ts b/src/routes/electron.ts index be78d13ec..358c49e31 100644 --- a/src/routes/electron.ts +++ b/src/routes/electron.ts @@ -1,7 +1,6 @@ +import { ipcMain } from "electron"; import { Application } from "express"; -const ipcMain = require('electron').ipcMain; - interface Response { statusCode: number; getHeader: (name: string) => string; diff --git a/src/routes/setup.ts b/src/routes/setup.ts index 2d6c43e0d..f9fab6b34 100644 --- a/src/routes/setup.ts +++ b/src/routes/setup.ts @@ -10,12 +10,8 @@ import { Request, Response } from 'express'; function setupPage(req: Request, res: Response) { if (sqlInit.isDbInitialized()) { if (utils.isElectron()) { - const windowService = require('../services/window'); - const { app } = require('electron'); - windowService.createMainWindow(app); - windowService.closeSetupWindow(); - } - else { + handleElectronRedirect(); + } else { 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 { setupPage }; diff --git a/src/services/asset_path.ts b/src/services/asset_path.ts index 72a21fdb9..ffb88f626 100644 --- a/src/services/asset_path.ts +++ b/src/services/asset_path.ts @@ -1,3 +1,3 @@ -import packageJson from "../../package.json"; +import packageJson from "../../package.json" assert { type: "json" }; export default `assets/v${packageJson.version}`; diff --git a/src/services/consistency_checks.ts b/src/services/consistency_checks.ts index 82e4e2216..a36b4490d 100644 --- a/src/services/consistency_checks.ts +++ b/src/services/consistency_checks.ts @@ -16,6 +16,7 @@ import sanitizeAttributeName from "./sanitize_attribute_name.js"; import noteTypesService from "../services/note_types.js"; import { BranchRow } from '../becca/entities/rows'; import { EntityChange } from './entity_changes_interface'; +import becca_loader from "../becca/becca_loader.js"; const noteTypes = noteTypesService.getNoteTypeNames(); class ConsistencyChecks { @@ -825,7 +826,7 @@ class ConsistencyChecks { } if (this.reloadNeeded) { - require('../becca/becca_loader').reload("consistency checks need becca reload"); + becca_loader.reload("consistency checks need becca reload"); } return !this.unrecoveredConsistencyErrors; diff --git a/src/services/erase.ts b/src/services/erase.ts index 5b7261ec9..1d7dcd738 100644 --- a/src/services/erase.ts +++ b/src/services/erase.ts @@ -177,14 +177,16 @@ function eraseScheduledAttachments(eraseUnusedAttachmentsAfterSeconds: number | eraseAttachments(attachmentIdsToErase); } -sqlInit.dbReady.then(() => { - // first cleanup kickoff 5 minutes after startup - 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); -}); +export function startScheduledCleanup() { + sqlInit.dbReady.then(() => { + // first cleanup kickoff 5 minutes after startup + 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); + }); +} export default { eraseDeletedNotesNow, @@ -192,5 +194,5 @@ export default { eraseNotesWithDeleteId, eraseUnusedBlobs, eraseAttachments, - eraseRevisions + eraseRevisions, }; diff --git a/src/services/import/markdown.ts b/src/services/import/markdown.ts index b5a022d1e..e3b4d6aa2 100644 --- a/src/services/import/markdown.ts +++ b/src/services/import/markdown.ts @@ -1,11 +1,11 @@ "use strict"; -import marked from "marked"; +import { parse } from "marked"; import htmlSanitizer from "../html_sanitizer.js"; import importUtils from "./utils.js"; function renderToHtml(content: string, title: string) { - const html = marked.parse(content, { + const html = parse(content, { async: false }) as string; const h1Handled = importUtils.handleH1(html, title); // h1 handling needs to come before sanitization diff --git a/src/services/migration.ts b/src/services/migration.ts index 4e1f82473..4355a99a5 100644 --- a/src/services/migration.ts +++ b/src/services/migration.ts @@ -20,7 +20,7 @@ async function migrate() { 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."); - utils.crash(); + await utils.crash(); return; } @@ -67,12 +67,12 @@ async function migrate() { cls.setMigrationRunning(true); - sql.transactional(() => { + sql.transactional(async () => { for (const mig of migrations) { try { log.info(`Attempting migration to version ${mig.dbVersion}`); - executeMigration(mig); + await executeMigration(mig); sql.execute(`UPDATE options SET value = ? @@ -84,7 +84,7 @@ async function migrate() { log.error("migration failed, crashing hard"); // this is not very user-friendly :-/ 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') { const migrationSql = fs.readFileSync(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`).toString('utf8'); @@ -106,7 +106,7 @@ function executeMigration(mig: MigrationInfo) { } else if (mig.type === 'js') { console.log("Migration with JS module"); - const migrationModule = require(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`); + const migrationModule = await import(`${resourceDir.MIGRATIONS_DIR}/${mig.file}`); migrationModule(); } else { 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') { 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()) { diff --git a/src/services/options_init.ts b/src/services/options_init.ts index 4edaa70d7..b06bf0afd 100644 --- a/src/services/options_init.ts +++ b/src/services/options_init.ts @@ -16,7 +16,7 @@ interface NotSyncedOpts { syncProxy?: string; } -function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts = {}) { +async function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts = {}) { optionService.createOption('openNoteContexts', JSON.stringify([ { 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 if (utils.isElectron()) { - const {nativeTheme} = require('electron'); + const {nativeTheme} = await import("electron"); theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light'; } diff --git a/src/services/protected_session.ts b/src/services/protected_session.ts index f29b73d17..b24b971d4 100644 --- a/src/services/protected_session.ts +++ b/src/services/protected_session.ts @@ -2,6 +2,8 @@ import log from "./log.js"; import dataEncryptionService from "./encryption/data_encryption.js"; +import options from "./options.js"; +import ws from "./ws.js"; let dataKey: Buffer | null = null; @@ -56,7 +58,6 @@ function touchProtectedSession() { } function checkProtectedSessionExpiration() { - const options = require('./options'); const protectedSessionTimeout = options.getOptionInt('protectedSessionTimeout'); if (isProtectedSessionAvailable() && lastProtectedSessionOperationDate @@ -66,7 +67,7 @@ function checkProtectedSessionExpiration() { log.info("Expiring protected session"); - require('./ws').reloadFrontend("leaving protected session"); + ws.reloadFrontend("leaving protected session"); } } diff --git a/src/services/request.ts b/src/services/request.ts index fe057024c..40ea5b278 100644 --- a/src/services/request.ts +++ b/src/services/request.ts @@ -33,7 +33,7 @@ interface Client { request(opts: ClientOpts): Request; } -function exec(opts: ExecOpts): Promise { +async function exec(opts: ExecOpts): Promise { const client = getClient(opts); // hack for cases where electron.net does not work, but we don't want to set proxy @@ -47,10 +47,10 @@ function exec(opts: ExecOpts): Promise { requestId: 'n/a' }; - const proxyAgent = getProxyAgent(opts); + const proxyAgent = await getProxyAgent(opts); const parsedTargetUrl = url.parse(opts.url); - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { try { const headers: Record = { Cookie: (opts.cookieJar && opts.cookieJar.header) || "", @@ -64,7 +64,7 @@ function exec(opts: ExecOpts): Promise { headers['trilium-cred'] = Buffer.from(`dummy:${opts.auth.password}`).toString('base64'); } - const request = client.request({ + const request = (await client).request({ method: opts.method, // url is used by electron net module url: opts.url, @@ -137,7 +137,7 @@ function exec(opts: ExecOpts): Promise { }); } -function getImage(imageUrl: string): Promise { +async function getImage(imageUrl: string): Promise { const proxyConf = syncOptions.getSyncProxy(); const opts: ClientOpts = { method: 'GET', @@ -145,8 +145,8 @@ function getImage(imageUrl: string): Promise { proxy: proxyConf !== "noproxy" ? proxyConf : null }; - const client = getClient(opts); - const proxyAgent = getProxyAgent(opts); + const client = await getClient(opts); + const proxyAgent = await getProxyAgent(opts); const parsedTargetUrl = url.parse(opts.url); return new Promise((resolve, reject) => { @@ -189,7 +189,7 @@ function getImage(imageUrl: string): Promise { const HTTP = 'http:', HTTPS = 'https:'; -function getProxyAgent(opts: ClientOpts) { +async function getProxyAgent(opts: ClientOpts) { if (!opts.proxy) { return null; } @@ -201,25 +201,23 @@ function getProxyAgent(opts: ClientOpts) { } const AgentClass = HTTP === protocol - ? require('http-proxy-agent').HttpProxyAgent - : require('https-proxy-agent').HttpsProxyAgent; + ? (await import('http-proxy-agent')).HttpProxyAgent + : (await import('https-proxy-agent')).HttpsProxyAgent; return new AgentClass(opts.proxy); } -function getClient(opts: ClientOpts): Client { +async function getClient(opts: ClientOpts): Promise { // it's not clear how to explicitly configure proxy (as opposed to system proxy), // so in that case, we always use node's modules if (utils.isElectron() && !opts.proxy) { - return require('electron').net as Client; - } - else { + return (await import('electron')).net as Client; + } else { const {protocol} = url.parse(opts.url); if (protocol === 'http:' || protocol === 'https:') { - return require(protocol.substr(0, protocol.length - 1)); - } - else { + return await import(protocol.substr(0, protocol.length - 1)); + } else { throw new Error(`Unrecognized protocol '${protocol}'`); } } diff --git a/src/services/resource_dir.ts b/src/services/resource_dir.ts index 7e194dc67..923f277cf 100644 --- a/src/services/resource_dir.ts +++ b/src/services/resource_dir.ts @@ -2,7 +2,8 @@ import log from "./log.js"; import path from "path"; 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 const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../.."); diff --git a/src/services/search/expressions/note_flat_text.ts b/src/services/search/expressions/note_flat_text.ts index d433eb991..3bd101005 100644 --- a/src/services/search/expressions/note_flat_text.ts +++ b/src/services/search/expressions/note_flat_text.ts @@ -7,6 +7,7 @@ import Expression from "./expression.js"; import NoteSet from "../note_set.js"; import becca from "../../../becca/becca.js"; import utils from "../../utils.js"; +import beccaService from "../../../becca/becca_service.js"; class NoteFlatTextExp extends Expression { private tokens: string[]; @@ -18,8 +19,6 @@ class NoteFlatTextExp extends Expression { } 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(); /** diff --git a/src/services/sql_init.ts b/src/services/sql_init.ts index 2c10d97ab..2a4d96715 100644 --- a/src/services/sql_init.ts +++ b/src/services/sql_init.ts @@ -15,11 +15,12 @@ import optionsInitService from "./options_init.js"; import BNote from "../becca/entities/bnote.js"; import BBranch from "../becca/entities/bbranch.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(); -cls.init(initDbConnection); - function schemaExists() { return !!sql.getValue(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'options'`); @@ -65,7 +66,7 @@ async function createInitialDatabase() { sql.executeScript(schema); - require('../becca/becca_loader').load(); + becca_loader.load(); log.info("Creating root note ..."); @@ -88,7 +89,7 @@ async function createInitialDatabase() { optionsInitService.initDocumentOptions(); optionsInitService.initNotSyncedOptions(true, {}); optionsInitService.initStartupOptions(); - require('./encryption/password').resetPassword(); + password.resetPassword(); }); log.info("Importing demo content ..."); @@ -129,7 +130,7 @@ function createDatabaseForSync(options: OptionRow[], syncServerHost = '', syncPr sql.transactional(() => { sql.executeScript(schema); - require('./options_init').initNotSyncedOptions(false, { syncServerHost, syncProxy }); + optionsInitService.initNotSyncedOptions(false, { syncServerHost, syncProxy }); // document options required for sync to kick off for (const opt of options) { @@ -157,29 +158,33 @@ function optimize() { 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() { return sql.getValue("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 { dbReady, @@ -188,5 +193,6 @@ export default { createInitialDatabase, createDatabaseForSync, setDbAsInitialized, - getDbSize + getDbSize, + initializeDb }; diff --git a/src/services/sync.ts b/src/services/sync.ts index 9f6bdeb8a..3390babb9 100644 --- a/src/services/sync.ts +++ b/src/services/sync.ts @@ -21,6 +21,7 @@ import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_in import { CookieJar, ExecOpts } from './request_interface'; import setupService from "./setup.js"; import consistency_checks from "./consistency_checks.js"; +import becca_loader from "../becca/becca_loader.js"; let proxyToggle = true; @@ -442,7 +443,7 @@ function getOutstandingPullCount() { return outstandingPullCount; } -require('../becca/becca_loader').beccaLoaded.then(() => { +becca_loader.beccaLoaded.then(() => { setInterval(cls.wrap(sync), 60000); // kickoff initial sync immediately, but should happen after initial consistency checks diff --git a/src/services/tray.ts b/src/services/tray.ts index 0b6211ced..a163a5a22 100644 --- a/src/services/tray.ts +++ b/src/services/tray.ts @@ -2,12 +2,14 @@ import { Menu, Tray } from 'electron'; import path from "path"; import windowService from "./window.js"; import optionService from "./options.js"; +import { fileURLToPath } from "url"; let tray: Tray; // `mainWindow.isVisible` doesn't work with `mainWindow.show` and `mainWindow.hide` - it returns `false` when the window // is minimized let isVisible = true; + // Inspired by https://github.com/signalapp/Signal-Desktop/blob/dcb5bb672635c4b29a51adec8a5658e3834ec8fc/app/tray_icon.ts#L20 const getIconSize = () => { switch (process.platform) { @@ -23,7 +25,7 @@ const getIconPath = () => { const iconSize = getIconSize(); return path.join( - __dirname, + path.dirname(fileURLToPath(import.meta.url)), "../..", "images", "app-icons", diff --git a/src/services/utils.ts b/src/services/utils.ts index 1b75046d0..0747f744f 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -125,11 +125,10 @@ function escapeRegExp(str: string) { return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); } -function crash() { +async function crash() { if (isElectron()) { - require('electron').app.exit(1); - } - else { + (await import("electron")).app.exit(1); + } else { process.exit(1); } } diff --git a/src/services/window.ts b/src/services/window.ts index bf84081fc..236fca441 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -10,6 +10,9 @@ import keyboardActionsService from "./keyboard_actions.js"; import remoteMain from "@electron/remote/main" import { App, BrowserWindow, WebContents, ipcMain } from 'electron'; +import { fileURLToPath } from "url"; +import { dirname } from "path"; + // Prevent the window being garbage collected let mainWindow: BrowserWindow | null; let setupWindow: BrowserWindow | null; @@ -17,7 +20,7 @@ let setupWindow: BrowserWindow | null; async function createExtraWindow(extraWindowHash: string) { const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); - const { BrowserWindow } = require('electron'); + const { BrowserWindow } = await import('electron'); const win = new BrowserWindow({ width: 1000, @@ -43,7 +46,7 @@ ipcMain.on('create-extra-window', (event, arg) => { }); 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({ // 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 { BrowserWindow } = require('electron'); // should not be statically imported + const { BrowserWindow } = (await import('electron')); // should not be statically imported mainWindow = new BrowserWindow({ x: mainWindowState.x, @@ -100,7 +103,11 @@ function configureWebContents(webContents: WebContents, spellcheckEnabled: boole remoteMain.enable(webContents); mainWindow.webContents.setWindowOpenHandler((details) => { - require('electron').shell.openExternal(details.url); + async function openExternal() { + (await import('electron')).shell.openExternal(details.url); + } + + openExternal(); return { action: 'deny' } }); @@ -124,11 +131,11 @@ function configureWebContents(webContents: WebContents, spellcheckEnabled: boole } 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() { - const { BrowserWindow } = require('electron'); // should not be statically imported + const { BrowserWindow } = await import("electron"); // should not be statically imported setupWindow = new BrowserWindow({ width: 800, height: 800, @@ -152,7 +159,7 @@ function closeSetupWindow() { } async function registerGlobalShortcuts() { - const { globalShortcut } = require('electron'); + const { globalShortcut } = await import("electron"); await sqlInit.dbReady; diff --git a/src/services/ws.ts b/src/services/ws.ts index d53f416ec..4a7628b2a 100644 --- a/src/services/ws.ts +++ b/src/services/ws.ts @@ -14,8 +14,8 @@ import { IncomingMessage, Server } from 'http'; import { EntityChange } from './entity_changes_interface'; if (env.isDev()) { - const chokidar = require('chokidar'); - const debounce = require('debounce'); + const chokidar = (await import("chokidar")).default; + const debounce = (await import("debounce")).default; const debouncedReloadFrontend = debounce(() => reloadFrontend("source code change"), 200); chokidar .watch('src/public') diff --git a/src/share/shaca/entities/abstract_shaca_entity.ts b/src/share/shaca/entities/abstract_shaca_entity.ts index 6bf7c3d63..b46f428de 100644 --- a/src/share/shaca/entities/abstract_shaca_entity.ts +++ b/src/share/shaca/entities/abstract_shaca_entity.ts @@ -1,13 +1,8 @@ +import shaca from "../shaca"; import Shaca from "../shaca-interface"; -let shaca: Shaca; - class AbstractShacaEntity { get shaca(): Shaca { - if (!shaca) { - shaca = require('../shaca'); - } - return shaca; } } diff --git a/src/share/sql.ts b/src/share/sql.ts index 0f39dd77d..87e9cf133 100644 --- a/src/share/sql.ts +++ b/src/share/sql.ts @@ -2,16 +2,21 @@ import Database from "better-sqlite3"; 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 => { - process.on(eventType, () => { - 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(); - } +sql_init.dbReady.then(() => { + dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true }); + + [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach(eventType => { + process.on(eventType, () => { + 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(); + } + }); }); }); diff --git a/src/www.ts b/src/www.ts index 7f0b14aa5..609551a0a 100644 --- a/src/www.ts +++ b/src/www.ts @@ -39,7 +39,7 @@ if (!semver.satisfies(process.version, ">=10.5.0")) { 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 * 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. */ if (utils.isElectron()) { - require('electron').app.requestSingleInstanceLock(); + (await import('electron')).app.requestSingleInstanceLock(); } 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 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. if (utils.isElectron()) { - const electronRouting = require('./routes/electron'); - electronRouting(app); + const electronRouting = await import('./routes/electron'); + electronRouting.default(app); } } diff --git a/tsconfig.json b/tsconfig.json index b8e0605f4..5898cb05d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "moduleResolution": "Bundler", - "module": "ES2015", - "target": "ES2018", + "module": "ESNext", + "target": "ES2020", "declaration": false, "sourceMap": true, "outDir": "./build", @@ -22,9 +22,6 @@ "./spec-es6/**/*.ts" ], "exclude": ["./node_modules/**/*"], - "ts-node": { - "files": true - }, "files": [ "src/types.d.ts" ] diff --git a/webpack.config.ts b/webpack.config.ts index 1c67bbe84..30293de06 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,7 +1,9 @@ +import { fileURLToPath } from "url"; import path from "path"; import assetPath from "./src/services/asset_path.js"; -module.exports = { +const rootDir = path.dirname(fileURLToPath(import.meta.url)); +export default { mode: 'production', entry: { setup: './src/public/app/setup.js', @@ -10,7 +12,7 @@ module.exports = { }, output: { publicPath: `${assetPath}/app-dist/`, - path: path.resolve(__dirname, 'src/public/app-dist'), + path: path.resolve(rootDir, 'src/public/app-dist'), filename: '[name].js', }, devtool: 'source-map',