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/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..d5fb9133e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,17 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "errors", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "revealProblems": "never" + }, + "runOptions": { + "runOn": "folderOpen" + } + } + ] + } \ No newline at end of file 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 86c80a9a3..b57b94901 100644 --- a/electron.ts +++ b/electron.ts @@ -1,22 +1,24 @@ "use strict"; -import electron = require("electron"); -import sqlInit = require("./src/services/sql_init"); -import appIconService = require("./src/services/app_icon"); -import windowService = require("./src/services/window"); -import tray = require("./src/services/tray"); +import electron from "electron"; +import electronDebug from "electron-debug"; +import electronDl from "electron-dl"; +import sqlInit from "./src/services/sql_init.js"; +import appIconService from "./src/services/app_icon.js"; +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')).default) { process.exit(0); } // Adds debug features like hotkeys for triggering dev tools and reload -require("electron-debug")(); +electronDebug(); appIconService.installLocalAppIcon(); -require("electron-dl")({ saveAs: true }); +electronDl({ saveAs: true }); // needed for excalidraw export https://github.com/zadam/trilium/issues/4271 electron.app.commandLine.appendSwitch( @@ -65,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 bf5b43e1f..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,19 +109,19 @@ "@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", "@types/semver": "^7.5.8", "@types/serve-favicon": "^2.5.7", + "@types/session-file-store": "^1.2.5", "@types/stream-throttle": "^0.1.4", "@types/tmp": "^0.2.6", "@types/turndown": "^5.0.4", "@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", @@ -131,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" @@ -1388,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", @@ -2207,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", @@ -2221,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", @@ -2446,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" } @@ -2616,6 +2646,16 @@ "@types/node": "*" } }, + "node_modules/@types/session-file-store": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/session-file-store/-/session-file-store-1.2.5.tgz", + "integrity": "sha512-xjIyh40IznXLrvbAY/nmxu5cMcPcE3ZoDrSDvd02m6p8UjUgOtZAGI7Os5DDd6THuxClLWNhFo/awy1tYp64Bg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/express-session": "*" + } + }, "node_modules/@types/stream-throttle": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@types/stream-throttle/-/stream-throttle-0.1.4.tgz", @@ -3195,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", @@ -3217,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", @@ -3360,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", @@ -3561,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": { @@ -5749,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": { @@ -5847,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" @@ -5909,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" @@ -6192,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", @@ -6311,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", @@ -7312,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": { @@ -7397,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", @@ -8606,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", @@ -8616,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", @@ -8629,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": { @@ -10113,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" }, @@ -10826,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" } @@ -11709,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", @@ -13013,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": { @@ -13244,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", @@ -13831,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 9383b0a64..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,24 +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", @@ -93,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", @@ -129,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", @@ -139,19 +143,19 @@ "@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", "@types/semver": "^7.5.8", "@types/serve-favicon": "^2.5.7", + "@types/session-file-store": "^1.2.5", "@types/stream-throttle": "^0.1.4", "@types/tmp": "^0.2.6", "@types/turndown": "^5.0.4", "@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", @@ -163,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-es6/attribute_parser.spec.ts b/spec-es6/attribute_parser.spec.ts index ad96e7644..60f510d8d 100644 --- a/spec-es6/attribute_parser.spec.ts +++ b/spec-es6/attribute_parser.spec.ts @@ -1,6 +1,6 @@ import * as attributeParser from '../src/public/app/services/attribute_parser.js'; -import {describe, it, expect, execute} from './mini_test'; +import {describe, it, expect, execute} from './mini_test.js'; describe("Lexing", () => { it("simple label", () => { diff --git a/spec/etapi/app_info.ts b/spec/etapi/app_info.ts index 9ea99b143..6ba049357 100644 --- a/spec/etapi/app_info.ts +++ b/spec/etapi/app_info.ts @@ -1,4 +1,4 @@ -import etapi = require("../support/etapi"); +import etapi from "../support/etapi.js"; etapi.describeEtapi("app_info", () => { it("get", async () => { diff --git a/spec/etapi/backup.ts b/spec/etapi/backup.ts index 3afda9141..2f9532f71 100644 --- a/spec/etapi/backup.ts +++ b/spec/etapi/backup.ts @@ -1,4 +1,4 @@ -import etapi = require("../support/etapi"); +import etapi from "../support/etapi.js"; etapi.describeEtapi("backup", () => { it("create", async () => { diff --git a/spec/etapi/import.ts b/spec/etapi/import.ts index 7471387ab..942a9871f 100644 --- a/spec/etapi/import.ts +++ b/spec/etapi/import.ts @@ -1,12 +1,15 @@ -import etapi = require("../support/etapi"); -import fs = require("fs"); -import path = require("path"); +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/spec/etapi/notes.ts b/spec/etapi/notes.ts index 208a7088d..cbfd4de7e 100644 --- a/spec/etapi/notes.ts +++ b/spec/etapi/notes.ts @@ -1,5 +1,5 @@ -import crypto = require("crypto"); -import etapi = require("../support/etapi"); +import crypto from "crypto"; +import etapi from "../support/etapi.js"; etapi.describeEtapi("notes", () => { it("create", async () => { diff --git a/spec/search/becca_mocking.ts b/spec/search/becca_mocking.ts index cb4e62b60..eaae2741f 100644 --- a/spec/search/becca_mocking.ts +++ b/spec/search/becca_mocking.ts @@ -1,10 +1,10 @@ -import BNote = require("../../src/becca/entities/bnote"); -import BBranch = require("../../src/becca/entities/bbranch"); -import BAttribute = require("../../src/becca/entities/battribute"); -import becca = require("../../src/becca/becca"); -import randtoken = require("rand-token"); -import SearchResult = require("../../src/services/search/search_result"); -import { NoteType } from "../../src/becca/entities/rows"; +import BNote from "../../src/becca/entities/bnote.js"; +import BBranch from "../../src/becca/entities/bbranch.js"; +import BAttribute from "../../src/becca/entities/battribute.js"; +import becca from "../../src/becca/becca.js"; +import randtoken from "rand-token"; +import SearchResult from "../../src/services/search/search_result.js"; +import { NoteType } from "../../src/becca/entities/rows.js"; randtoken.generator({ source: "crypto" }); function findNoteByTitle( @@ -80,7 +80,7 @@ function note(title: string, extraParams = {}) { return new NoteBuilder(note); } -export = { +export default { NoteBuilder, findNoteByTitle, note, diff --git a/spec/search/lexer.spec.ts b/spec/search/lexer.spec.ts index 971f9cb13..d97f435c3 100644 --- a/spec/search/lexer.spec.ts +++ b/spec/search/lexer.spec.ts @@ -1,4 +1,4 @@ -import lex = require("../../src/services/search/services/lex"); +import lex from "../../src/services/search/services/lex.js"; describe("Lexer fulltext", () => { it("simple lexing", () => { diff --git a/spec/search/parens.spec.ts b/spec/search/parens.spec.ts index ae1ac5b2f..3bc900b8b 100644 --- a/spec/search/parens.spec.ts +++ b/spec/search/parens.spec.ts @@ -1,24 +1,26 @@ -const handleParens = require('../../src/services/search/services/handle_parens'); +import handleParens from "../../src/services/search/services/handle_parens.js"; +import { TokenStructure } from "../../src/services/search/services/types.js"; describe("Parens handler", () => { it("handles parens", () => { const input = ["(", "hello", ")", "and", "(", "(", "pick", "one", ")", "and", "another", ")"] .map(token => ({token})); - expect(handleParens(input)) - .toEqual([ + const actual: TokenStructure = [ + [ + {token: "hello"} + ], + {token: "and"}, + [ [ - {token: "hello"} + {token: "pick"}, + {token: "one"} ], {token: "and"}, - [ - [ - {token: "pick"}, - {token: "one"} - ], - {token: "and"}, - {token: "another"} - ] - ]); + {token: "another"} + ] + ]; + + expect(handleParens(input)).toEqual(actual); }); }); diff --git a/spec/search/parser.spec.ts b/spec/search/parser.spec.ts index d8ba2d7a6..003036664 100644 --- a/spec/search/parser.spec.ts +++ b/spec/search/parser.spec.ts @@ -2,9 +2,9 @@ // There are many issues with the types of the parser e.g. "parse" function returns "Expression" // but we access properties like "subExpressions" which is not defined in the "Expression" class. -import Expression = require('../../src/services/search/expressions/expression'); -import SearchContext = require('../../src/services/search/search_context'); -import parse = require('../../src/services/search/services/parse'); +import Expression from "../../src/services/search/expressions/expression.js"; +import SearchContext from "../../src/services/search/search_context.js"; +import parse from "../../src/services/search/services/parse.js"; function tokens(toks: Array, cur = 0): Array { return toks.map((arg) => { diff --git a/spec/search/search.spec.ts b/spec/search/search.spec.ts index 4d8a06aba..a058ae895 100644 --- a/spec/search/search.spec.ts +++ b/spec/search/search.spec.ts @@ -1,11 +1,10 @@ -import searchService = require('../../src/services/search/services/search'); -import BNote = require('../../src/becca/entities/bnote'); -import BBranch = require('../../src/becca/entities/bbranch'); -import SearchContext = require('../../src/services/search/search_context'); -import dateUtils = require('../../src/services/date_utils'); -import becca = require('../../src/becca/becca'); -// const { NoteBuilder, findNoteByTitle, note } = require("./becca_mocking"); -import becca_mocking = require('./becca_mocking'); +import searchService from "../../src/services/search/services/search.js"; +import BNote from "../../src/becca/entities/bnote.js"; +import BBranch from "../../src/becca/entities/bbranch.js"; +import SearchContext from "../../src/services/search/search_context.js"; +import dateUtils from "../../src/services/date_utils.js"; +import becca from "../../src/becca/becca.js"; +import becca_mocking from "./becca_mocking.js"; describe('Search', () => { let rootNote: any; diff --git a/spec/search/value_extractor.spec.ts b/spec/search/value_extractor.spec.ts index 28343bab8..1672ddbb6 100644 --- a/spec/search/value_extractor.spec.ts +++ b/spec/search/value_extractor.spec.ts @@ -1,7 +1,7 @@ -import becca_mocking = require('./becca_mocking'); -import ValueExtractor = require('../../src/services/search/value_extractor'); -import becca = require('../../src/becca/becca'); -import SearchContext = require('../../src/services/search/search_context'); +import becca_mocking from "./becca_mocking.js"; +import ValueExtractor from "../../src/services/search/value_extractor.js"; +import becca from "../../src/becca/becca.js"; +import SearchContext from "../../src/services/search/search_context.js"; const dsc = new SearchContext(); diff --git a/spec/support/etapi.ts b/spec/support/etapi.ts index 734b3adf3..19043d8fa 100644 --- a/spec/support/etapi.ts +++ b/spec/support/etapi.ts @@ -1,5 +1,5 @@ -import child_process = require("child_process"); -import kill = require("tree-kill"); +import child_process from "child_process"; +import kill from "tree-kill"; let etapiAuthToken: string | undefined; @@ -164,7 +164,7 @@ function checkStatus(response: Response): void { } } -export { +export default { describeEtapi, getEtapi, getEtapiResponse, diff --git a/src/anonymize.ts b/src/anonymize.ts index cd449e479..8ad803c63 100644 --- a/src/anonymize.ts +++ b/src/anonymize.ts @@ -1,6 +1,6 @@ -import anonymizationService = require('./services/anonymization'); -import sqlInit = require('./services/sql_init'); -require('./becca/entity_constructor'); +import anonymizationService from "./services/anonymization.js"; +import sqlInit from "./services/sql_init.js"; +await import("./becca/entity_constructor.js"); sqlInit.dbReady.then(async () => { try { diff --git a/src/app.ts b/src/app.ts index ceabe33f9..574a94eb6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,26 +1,39 @@ -import express = require('express'); -import path = require('path'); -import favicon = require('serve-favicon'); -import cookieParser = require('cookie-parser'); -import helmet = require('helmet'); -import compression = require('compression'); -import sessionParser = require('./routes/session_parser'); -import utils = require('./services/utils'); +import express from "express"; +import path from "path"; +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.js'); +await import('./becca/becca_loader.js'); 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()) { app.use(compression()); // HTTP compression } -app.use(helmet.default({ +app.use(helmet({ hidePoweredBy: false, // errors out in electron contentSecurityPolicy: false, crossOriginEmbedderPolicy: false @@ -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.js"); // triggers backup timer -require('./services/backup'); +await import('./services/backup.js'); // trigger consistency checks timer -require('./services/consistency_checks'); +await import('./services/consistency_checks.js'); -require('./services/scheduler'); +await import('./services/scheduler.js'); + +startScheduledCleanup(); if (utils.isElectron()) { - require('@electron/remote/main').initialize(); + (await import('@electron/remote/main/index.js')).initialize(); } -export = app; +export default app; diff --git a/src/becca/becca-interface.ts b/src/becca/becca-interface.ts index 21892676d..c5e9f6925 100644 --- a/src/becca/becca-interface.ts +++ b/src/becca/becca-interface.ts @@ -1,17 +1,17 @@ -import sql = require('../services/sql'); -import NoteSet = require('../services/search/note_set'); -import NotFoundError = require('../errors/not_found_error'); -import BOption = require('./entities/boption'); -import BNote = require('./entities/bnote'); -import BEtapiToken = require('./entities/betapi_token'); -import BAttribute = require('./entities/battribute'); -import BBranch = require('./entities/bbranch'); -import BRevision = require('./entities/brevision'); -import BAttachment = require('./entities/battachment'); -import { AttachmentRow, RevisionRow } from './entities/rows'; -import BBlob = require('./entities/bblob'); -import BRecentNote = require('./entities/brecent_note'); -import AbstractBeccaEntity = require('./entities/abstract_becca_entity'); +import sql from "../services/sql.js"; +import NoteSet from "../services/search/note_set.js"; +import NotFoundError from "../errors/not_found_error.js"; +import BOption from "./entities/boption.js"; +import BNote from "./entities/bnote.js"; +import BEtapiToken from "./entities/betapi_token.js"; +import BAttribute from "./entities/battribute.js"; +import BBranch from "./entities/bbranch.js"; +import BRevision from "./entities/brevision.js"; +import BAttachment from "./entities/battachment.js"; +import { AttachmentRow, BlobRow, RevisionRow } from './entities/rows.js'; +import BBlob from "./entities/bblob.js"; +import BRecentNote from "./entities/brecent_note.js"; +import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; interface AttachmentOpts { includeContentLength?: boolean; @@ -155,9 +155,7 @@ export default class Becca { } getRevision(revisionId: string): BRevision | null { - const row = sql.getRow("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]); - - const BRevision = require('./entities/brevision'); // avoiding circular dependency problems + const row = sql.getRow("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]); return row ? new BRevision(row) : null; } @@ -179,9 +177,7 @@ export default class Becca { WHERE attachmentId = ? AND isDeleted = 0` : `SELECT * FROM attachments WHERE attachmentId = ? AND isDeleted = 0`; - const BAttachment = require('./entities/battachment'); // avoiding circular dependency problems - - return sql.getRows(query, [attachmentId]) + return sql.getRows(query, [attachmentId]) .map(row => new BAttachment(row))[0]; } @@ -194,7 +190,6 @@ export default class Becca { } getAttachments(attachmentIds: string[]): BAttachment[] { - const BAttachment = require('./entities/battachment'); // avoiding circular dependency problems return sql.getManyRows("SELECT * FROM attachments WHERE attachmentId IN (???) AND isDeleted = 0", attachmentIds) .map(row => new BAttachment(row)); } @@ -204,9 +199,7 @@ export default class Becca { return null; } - const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]); - - const BBlob = require('./entities/bblob'); // avoiding circular dependency problems + const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]); return row ? new BBlob(row) : null; } @@ -248,16 +241,12 @@ export default class Becca { } getRecentNotesFromQuery(query: string, params: string[] = []): BRecentNote[] { - const rows = sql.getRows(query, params); - - const BRecentNote = require('./entities/brecent_note'); // avoiding circular dependency problems + const rows = sql.getRows(query, params); return rows.map(row => new BRecentNote(row)); } getRevisionsFromQuery(query: string, params: string[] = []): BRevision[] { const rows = sql.getRows(query, params); - - const BRevision = require('./entities/brevision'); // avoiding circular dependency problems return rows.map(row => new BRevision(row)); } diff --git a/src/becca/becca.ts b/src/becca/becca.ts index a66dc442d..d4270fe09 100644 --- a/src/becca/becca.ts +++ b/src/becca/becca.ts @@ -1,7 +1,7 @@ "use strict"; -import Becca from "./becca-interface"; +import Becca from "./becca-interface.js"; const becca = new Becca(); -export = becca; +export default becca; diff --git a/src/becca/becca_loader.ts b/src/becca/becca_loader.ts index b7ea941c8..041bdccbd 100644 --- a/src/becca/becca_loader.ts +++ b/src/becca/becca_loader.ts @@ -1,26 +1,28 @@ "use strict"; -import sql = require('../services/sql'); -import eventService = require('../services/events'); -import becca = require('./becca'); -import sqlInit = require('../services/sql_init'); -import log = require('../services/log'); -import BNote = require('./entities/bnote'); -import BBranch = require('./entities/bbranch'); -import BAttribute = require('./entities/battribute'); -import BOption = require('./entities/boption'); -import BEtapiToken = require('./entities/betapi_token'); -import cls = require('../services/cls'); -import entityConstructor = require('../becca/entity_constructor'); -import { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows'; -import AbstractBeccaEntity = require('./entities/abstract_becca_entity'); +import sql from "../services/sql.js"; +import eventService from "../services/events.js"; +import becca from "./becca.js"; +import sqlInit from "../services/sql_init.js"; +import log from "../services/log.js"; +import BNote from "./entities/bnote.js"; +import BBranch from "./entities/bbranch.js"; +import BAttribute from "./entities/battribute.js"; +import BOption from "./entities/boption.js"; +import BEtapiToken from "./entities/betapi_token.js"; +import cls from "../services/cls.js"; +import entityConstructor from "../becca/entity_constructor.js"; +import { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows.js'; +import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; +import options_init from "../services/options_init.js"; +import ws from "../services/ws.js"; const beccaLoaded = new Promise((res, rej) => { sqlInit.dbReady.then(() => { cls.init(() => { load(); - require('../services/options_init').initStartupOptions(); + options_init.initStartupOptions(); res(); }); @@ -73,7 +75,7 @@ function load() { function reload(reason: string) { load(); - require('../services/ws').reloadFrontend(reason || "becca reloaded"); + ws.reloadFrontend(reason || "becca reloaded"); } eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({ entityName, entityRow }) => { @@ -286,7 +288,7 @@ eventService.subscribeBeccaLoader(eventService.ENTER_PROTECTED_SESSION, () => { eventService.subscribeBeccaLoader(eventService.LEAVE_PROTECTED_SESSION, load); -export = { +export default { load, reload, beccaLoaded diff --git a/src/becca/becca_service.ts b/src/becca/becca_service.ts index 2a9eb2781..46d41fdbf 100644 --- a/src/becca/becca_service.ts +++ b/src/becca/becca_service.ts @@ -1,8 +1,8 @@ "use strict"; -import becca = require('./becca'); -import cls = require('../services/cls'); -import log = require('../services/log'); +import becca from "./becca.js"; +import cls from "../services/cls.js"; +import log from "../services/log.js"; function isNotePathArchived(notePath: string[]) { const noteId = notePath[notePath.length - 1]; @@ -82,7 +82,7 @@ function getNoteTitleForPath(notePathArray: string[]) { return titles.join(' / '); } -export = { +export default { getNoteTitle, getNoteTitleForPath, isNotePathArchived diff --git a/src/becca/entities/abstract_becca_entity.ts b/src/becca/entities/abstract_becca_entity.ts index ad4eeae03..0016b2a07 100644 --- a/src/becca/entities/abstract_becca_entity.ts +++ b/src/becca/entities/abstract_becca_entity.ts @@ -1,17 +1,16 @@ "use strict"; -import utils = require('../../services/utils'); -import sql = require('../../services/sql'); -import entityChangesService = require('../../services/entity_changes'); -import eventService = require('../../services/events'); -import dateUtils = require('../../services/date_utils'); -import cls = require('../../services/cls'); -import log = require('../../services/log'); -import protectedSessionService = require('../../services/protected_session'); -import blobService = require('../../services/blob'); -import Becca, { ConstructorData } from '../becca-interface'; - -let becca: Becca; +import utils from "../../services/utils.js"; +import sql from "../../services/sql.js"; +import entityChangesService from "../../services/entity_changes.js"; +import eventService from "../../services/events.js"; +import dateUtils from "../../services/date_utils.js"; +import cls from "../../services/cls.js"; +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.js'; +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) { @@ -327,4 +322,4 @@ abstract class AbstractBeccaEntity> { } } -export = AbstractBeccaEntity; +export default AbstractBeccaEntity; diff --git a/src/becca/entities/battachment.ts b/src/becca/entities/battachment.ts index 09f026ff0..ab90d345f 100644 --- a/src/becca/entities/battachment.ts +++ b/src/becca/entities/battachment.ts @@ -1,14 +1,15 @@ "use strict"; -import utils = require('../../services/utils'); -import dateUtils = require('../../services/date_utils'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import sql = require('../../services/sql'); -import protectedSessionService = require('../../services/protected_session'); -import log = require('../../services/log'); -import { AttachmentRow } from './rows'; -import BNote = require('./bnote'); -import BBranch = require('./bbranch'); +import utils from "../../services/utils.js"; +import dateUtils from "../../services/date_utils.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import sql from "../../services/sql.js"; +import protectedSessionService from "../../services/protected_session.js"; +import log from "../../services/log.js"; +import { AttachmentRow } from './rows.js'; +import BNote from "./bnote.js"; +import BBranch from "./bbranch.js"; +import noteService from "../../services/notes.js"; const attachmentRoleToNoteTypeMapping = { 'image': 'image', @@ -43,9 +44,6 @@ class BAttachment extends AbstractBeccaEntity { title!: string; type?: keyof typeof attachmentRoleToNoteTypeMapping; position?: number; - blobId?: string; - isProtected?: boolean; - dateModified?: string; utcDateScheduledForErasureSince?: string | null; /** optionally added to the entity */ contentLength?: number; @@ -157,8 +155,6 @@ class BAttachment extends AbstractBeccaEntity { throw new Error(`Cannot convert protected attachment outside of protected session`); } - const noteService = require('../../services/notes'); - const { note, branch } = noteService.createNewNote({ parentNoteId: this.ownerId, title: this.title, @@ -249,4 +245,4 @@ class BAttachment extends AbstractBeccaEntity { } } -export = BAttachment; +export default BAttachment; diff --git a/src/becca/entities/battribute.ts b/src/becca/entities/battribute.ts index 6ad1965ed..97df7b056 100644 --- a/src/becca/entities/battribute.ts +++ b/src/becca/entities/battribute.ts @@ -1,11 +1,11 @@ "use strict"; -import BNote = require('./bnote'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import dateUtils = require('../../services/date_utils'); -import promotedAttributeDefinitionParser = require('../../services/promoted_attribute_definition_parser'); -import sanitizeAttributeName = require('../../services/sanitize_attribute_name'); -import { AttributeRow, AttributeType } from './rows'; +import BNote from "./bnote.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import dateUtils from "../../services/date_utils.js"; +import promotedAttributeDefinitionParser from "../../services/promoted_attribute_definition_parser.js"; +import sanitizeAttributeName from "../../services/sanitize_attribute_name.js"; +import { AttributeRow, AttributeType } from './rows.js'; interface SavingOpts { skipValidation?: boolean; @@ -226,4 +226,4 @@ class BAttribute extends AbstractBeccaEntity { } } -export = BAttribute; +export default BAttribute; diff --git a/src/becca/entities/bblob.ts b/src/becca/entities/bblob.ts index 40d1c5885..7ce94eb2e 100644 --- a/src/becca/entities/bblob.ts +++ b/src/becca/entities/bblob.ts @@ -1,5 +1,5 @@ -import AbstractBeccaEntity = require("./abstract_becca_entity"); -import { BlobRow } from "./rows"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import { BlobRow } from "./rows.js"; // TODO: Why this does not extend the abstract becca? class BBlob extends AbstractBeccaEntity { @@ -7,11 +7,8 @@ class BBlob extends AbstractBeccaEntity { static get primaryKeyName() { return "blobId"; } static get hashedProperties() { return ["blobId", "content"]; } - blobId!: string; content!: string | Buffer; contentLength!: number; - dateModified!: string; - utcDateModified!: string; constructor(row: BlobRow) { super(); @@ -37,4 +34,4 @@ class BBlob extends AbstractBeccaEntity { } } -export = BBlob; +export default BBlob; diff --git a/src/becca/entities/bbranch.ts b/src/becca/entities/bbranch.ts index 0f904de92..daa71f917 100644 --- a/src/becca/entities/bbranch.ts +++ b/src/becca/entities/bbranch.ts @@ -1,13 +1,14 @@ "use strict"; -import BNote = require('./bnote'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import dateUtils = require('../../services/date_utils'); -import utils = require('../../services/utils'); -import TaskContext = require('../../services/task_context'); -import cls = require('../../services/cls'); -import log = require('../../services/log'); -import { BranchRow } from './rows'; +import BNote from "./bnote.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import dateUtils from "../../services/date_utils.js"; +import utils from "../../services/utils.js"; +import TaskContext from "../../services/task_context.js"; +import cls from "../../services/cls.js"; +import log from "../../services/log.js"; +import { BranchRow } from './rows.js'; +import handlers from "../../services/handlers.js"; /** * Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple @@ -28,7 +29,6 @@ class BBranch extends AbstractBeccaEntity { prefix!: string | null; notePosition!: number; isExpanded!: boolean; - utcDateModified?: string; constructor(row?: BranchRow) { super(); @@ -157,7 +157,6 @@ class BBranch extends AbstractBeccaEntity { if (parentBranches.length === 1 && parentBranches[0] === this) { // needs to be run before branches and attributes are deleted and thus attached relations disappear - const handlers = require('../../services/handlers'); handlers.runAttachedRelations(note, 'runOnNoteDeletion', note); } } @@ -285,4 +284,4 @@ class BBranch extends AbstractBeccaEntity { } } -export = BBranch; +export default BBranch; diff --git a/src/becca/entities/betapi_token.ts b/src/becca/entities/betapi_token.ts index 390b580bd..bfd4383e3 100644 --- a/src/becca/entities/betapi_token.ts +++ b/src/becca/entities/betapi_token.ts @@ -1,9 +1,9 @@ "use strict"; -import { EtapiTokenRow } from "./rows"; +import { EtapiTokenRow } from "./rows.js"; -import dateUtils = require('../../services/date_utils'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); +import dateUtils from "../../services/date_utils.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; /** * EtapiToken is an entity representing token used to authenticate against Trilium REST API from client applications. @@ -80,4 +80,4 @@ class BEtapiToken extends AbstractBeccaEntity { } } -export = BEtapiToken; +export default BEtapiToken; diff --git a/src/becca/entities/bnote.ts b/src/becca/entities/bnote.ts index a1d4cf395..3ae4d60b5 100644 --- a/src/becca/entities/bnote.ts +++ b/src/becca/entities/bnote.ts @@ -1,21 +1,25 @@ "use strict"; -import protectedSessionService = require('../../services/protected_session'); -import log = require('../../services/log'); -import sql = require('../../services/sql'); -import utils = require('../../services/utils'); -import dateUtils = require('../../services/date_utils'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import BRevision = require('./brevision'); -import BAttachment = require('./battachment'); -import TaskContext = require('../../services/task_context'); -import dayjs = require("dayjs"); -import utc = require('dayjs/plugin/utc'); -import eventService = require('../../services/events'); -import { AttachmentRow, NoteRow, NoteType, RevisionRow } from './rows'; -import BBranch = require('./bbranch'); -import BAttribute = require('./battribute'); -import { NotePojo } from '../becca-interface'; +import protectedSessionService from "../../services/protected_session.js"; +import log from "../../services/log.js"; +import sql from "../../services/sql.js"; +import utils from "../../services/utils.js"; +import dateUtils from "../../services/date_utils.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import BRevision from "./brevision.js"; +import BAttachment from "./battachment.js"; +import TaskContext from "../../services/task_context.js"; +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc.js"; +import eventService from "../../services/events.js"; +import { AttachmentRow, AttributeType, NoteRow, NoteType, RevisionRow } from './rows.js'; +import BBranch from "./bbranch.js"; +import BAttribute from "./battribute.js"; +import { NotePojo } from '../becca-interface.js'; +import searchService from "../../services/search/services/search.js"; +import cloningService, { CloneResponse } from "../../services/cloning.js"; +import noteService from "../../services/notes.js"; +import handlers from "../../services/handlers.js"; dayjs.extend(utc); const LABEL = 'label'; @@ -890,11 +894,9 @@ class BNote extends AbstractBeccaEntity { } try { - const searchService = require('../../services/search/services/search'); - const {searchResultNoteIds} = searchService.searchFromNote(this); - + const result = searchService.searchFromNote(this); const becca = this.becca; - return (searchResultNoteIds as string[]) // TODO: remove cast once search is converted + return (result.searchResultNoteIds) .map(resultNoteId => becca.notes[resultNoteId]) .filter(note => !!note); } @@ -1261,7 +1263,7 @@ class BNote extends AbstractBeccaEntity { * @param name - attribute name * @param value - attribute value (optional) */ - setAttribute(type: string, name: string, value?: string) { + setAttribute(type: AttributeType, name: string, value?: string) { const attributes = this.getOwnedAttributes(); const attr = attributes.find(attr => attr.type === type && attr.name === name); @@ -1274,8 +1276,6 @@ class BNote extends AbstractBeccaEntity { } } else { - const BAttribute = require('./battribute'); - new BAttribute({ noteId: this.noteId, type: type, @@ -1310,9 +1310,7 @@ class BNote extends AbstractBeccaEntity { * @param name - name of the attribute, not including the leading ~/# * @param value - value of the attribute - text for labels, target note ID for relations; optional. */ - addAttribute(type: string, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute { - const BAttribute = require('./battribute'); - + addAttribute(type: AttributeType, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute { return new BAttribute({ noteId: this.noteId, type: type, @@ -1351,7 +1349,7 @@ class BNote extends AbstractBeccaEntity { * @param name - attribute name * @param value - attribute value (optional) */ - toggleAttribute(type: string, enabled: boolean, name: string, value?: string) { + toggleAttribute(type: AttributeType, enabled: boolean, name: string, value?: string) { if (enabled) { this.setAttribute(type, name, value); } @@ -1423,8 +1421,6 @@ class BNote extends AbstractBeccaEntity { } searchNotesInSubtree(searchString: string) { - const searchService = require('../../services/search/services/search'); - return searchService.searchNotes(searchString) as BNote[]; } @@ -1432,12 +1428,16 @@ class BNote extends AbstractBeccaEntity { return this.searchNotesInSubtree(searchString)[0]; } - cloneTo(parentNoteId: string) { - const cloningService = require('../../services/cloning'); - + cloneTo(parentNoteId: string): CloneResponse { const branch = this.becca.getNote(parentNoteId)?.getParentBranches()[0]; + if (!branch?.branchId) { + return { + success: false, + message: "Unable to find the branch ID to clone." + }; + } - return cloningService.cloneNoteToBranch(this.noteId, branch?.branchId); + return cloningService.cloneNoteToBranch(this.noteId, branch.branchId); } isEligibleForConversionToAttachment(opts: ConvertOpts = { autoConversion: false }) { @@ -1508,7 +1508,6 @@ class BNote extends AbstractBeccaEntity { parentNote.setContent(fixedContent); - const noteService = require('../../services/notes'); noteService.asyncPostProcessContent(parentNote, fixedContent); // to mark an unused attachment for deletion this.deleteNote(); @@ -1535,7 +1534,6 @@ class BNote extends AbstractBeccaEntity { } // needs to be run before branches and attributes are deleted and thus attached relations disappear - const handlers = require('../../services/handlers'); handlers.runAttachedRelations(this, 'runOnNoteDeletion', this); taskContext.noteDeletionHandlerTriggered = true; @@ -1696,4 +1694,4 @@ class BNote extends AbstractBeccaEntity { } } -export = BNote; +export default BNote; diff --git a/src/becca/entities/boption.ts b/src/becca/entities/boption.ts index 48abee024..4ae5ba7a9 100644 --- a/src/becca/entities/boption.ts +++ b/src/becca/entities/boption.ts @@ -1,8 +1,8 @@ "use strict"; -import dateUtils = require('../../services/date_utils'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import { OptionRow } from './rows'; +import dateUtils from "../../services/date_utils.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import { OptionRow } from './rows.js'; /** * Option represents a name-value pair, either directly configurable by the user or some system property. @@ -14,7 +14,6 @@ class BOption extends AbstractBeccaEntity { name!: string; value!: string; - isSynced!: boolean; constructor(row?: OptionRow) { super(); @@ -48,4 +47,4 @@ class BOption extends AbstractBeccaEntity { } } -export = BOption; +export default BOption; diff --git a/src/becca/entities/brecent_note.ts b/src/becca/entities/brecent_note.ts index c19a83603..f9f31a98f 100644 --- a/src/becca/entities/brecent_note.ts +++ b/src/becca/entities/brecent_note.ts @@ -1,9 +1,9 @@ "use strict"; -import { RecentNoteRow } from "./rows"; +import { RecentNoteRow } from "./rows.js"; -import dateUtils = require('../../services/date_utils'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); +import dateUtils from "../../services/date_utils.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; /** * RecentNote represents recently visited note. @@ -15,7 +15,6 @@ class BRecentNote extends AbstractBeccaEntity { noteId!: string; notePath!: string; - utcDateCreated!: string; constructor(row: RecentNoteRow) { super(); @@ -38,4 +37,4 @@ class BRecentNote extends AbstractBeccaEntity { } } -export = BRecentNote; +export default BRecentNote; diff --git a/src/becca/entities/brevision.ts b/src/becca/entities/brevision.ts index 18a7a8df5..7448416ab 100644 --- a/src/becca/entities/brevision.ts +++ b/src/becca/entities/brevision.ts @@ -1,13 +1,14 @@ "use strict"; -import protectedSessionService = require('../../services/protected_session'); -import utils = require('../../services/utils'); -import dateUtils = require('../../services/date_utils'); -import becca = require('../becca'); -import AbstractBeccaEntity = require('./abstract_becca_entity'); -import sql = require('../../services/sql'); -import BAttachment = require('./battachment'); -import { AttachmentRow, RevisionRow } from './rows'; +import protectedSessionService from "../../services/protected_session.js"; +import utils from "../../services/utils.js"; +import dateUtils from "../../services/date_utils.js"; +import becca from "../becca.js"; +import AbstractBeccaEntity from "./abstract_becca_entity.js"; +import sql from "../../services/sql.js"; +import BAttachment from "./battachment.js"; +import { AttachmentRow, RevisionRow } from './rows.js'; +import eraseService from "../../services/erase.js"; interface ContentOpts { /** will also save this BRevision entity */ @@ -32,13 +33,9 @@ class BRevision extends AbstractBeccaEntity { noteId!: string; type!: string; mime!: string; - isProtected!: boolean; title!: string; - blobId?: string; dateLastEdited?: string; - dateCreated!: string; utcDateLastEdited?: string; - utcDateCreated!: string; contentLength?: number; content?: string | Buffer; @@ -164,7 +161,9 @@ class BRevision extends AbstractBeccaEntity { * Revisions are not soft-deletable, they are immediately hard-deleted (erased). */ eraseRevision() { - require("../../services/erase.js").eraseRevisions([this.revisionId]); + if (this.revisionId) { + eraseService.eraseRevisions([this.revisionId]); + } } beforeSaving() { @@ -211,4 +210,4 @@ class BRevision extends AbstractBeccaEntity { } } -export = BRevision; +export default BRevision; diff --git a/src/becca/entities/rows.ts b/src/becca/entities/rows.ts index 119d392ec..6c46bf301 100644 --- a/src/becca/entities/rows.ts +++ b/src/becca/entities/rows.ts @@ -42,7 +42,7 @@ export interface OptionRow { name: string; value: string; isSynced: boolean; - utcDateModified: string; + utcDateModified?: string; } export interface EtapiTokenRow { @@ -69,7 +69,7 @@ export interface AttributeRow { noteId?: string; type: AttributeType; name: string; - position?: number; + position?: number | null; value?: string; isInheritable?: boolean; utcDateModified?: string; diff --git a/src/becca/entity_constructor.ts b/src/becca/entity_constructor.ts index 01c51363a..49476961c 100644 --- a/src/becca/entity_constructor.ts +++ b/src/becca/entity_constructor.ts @@ -1,14 +1,14 @@ -import { ConstructorData } from './becca-interface'; -import AbstractBeccaEntity = require('./entities/abstract_becca_entity'); -import BAttachment = require('./entities/battachment'); -import BAttribute = require('./entities/battribute'); -import BBlob = require('./entities/bblob'); -import BBranch = require('./entities/bbranch'); -import BEtapiToken = require('./entities/betapi_token'); -import BNote = require('./entities/bnote'); -import BOption = require('./entities/boption'); -import BRecentNote = require('./entities/brecent_note'); -import BRevision = require('./entities/brevision'); +import { ConstructorData } from './becca-interface.js'; +import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; +import BAttachment from "./entities/battachment.js"; +import BAttribute from "./entities/battribute.js"; +import BBlob from "./entities/bblob.js"; +import BBranch from "./entities/bbranch.js"; +import BEtapiToken from "./entities/betapi_token.js"; +import BNote from "./entities/bnote.js"; +import BOption from "./entities/boption.js"; +import BRecentNote from "./entities/brecent_note.js"; +import BRevision from "./entities/brevision.js"; type EntityClass = new (row?: any) => AbstractBeccaEntity; @@ -32,6 +32,6 @@ function getEntityFromEntityName(entityName: keyof typeof ENTITY_NAME_TO_ENTITY) return ENTITY_NAME_TO_ENTITY[entityName]; } -export = { +export default { getEntityFromEntityName }; diff --git a/src/becca/similarity.ts b/src/becca/similarity.ts index e6721d0df..05b91f8ed 100644 --- a/src/becca/similarity.ts +++ b/src/becca/similarity.ts @@ -1,9 +1,9 @@ -import becca = require('./becca'); -import log = require('../services/log'); -import beccaService = require('./becca_service'); -import dateUtils = require('../services/date_utils'); +import becca from "./becca.js"; +import log from "../services/log.js"; +import beccaService from "./becca_service.js"; +import dateUtils from "../services/date_utils.js"; import { JSDOM } from "jsdom"; -import BNote = require('./entities/bnote'); +import BNote from "./entities/bnote.js"; const DEBUG = false; @@ -461,6 +461,6 @@ function setImmediatePromise() { }); } -export = { +export default { findSimilarNotes }; diff --git a/src/errors/not_found_error.ts b/src/errors/not_found_error.ts index f765e11f9..f6ffb0d7e 100644 --- a/src/errors/not_found_error.ts +++ b/src/errors/not_found_error.ts @@ -6,4 +6,4 @@ class NotFoundError { } } -export = NotFoundError; \ No newline at end of file +export default NotFoundError; \ No newline at end of file diff --git a/src/errors/validation_error.ts b/src/errors/validation_error.ts index 8b872bcbe..565082466 100644 --- a/src/errors/validation_error.ts +++ b/src/errors/validation_error.ts @@ -6,4 +6,4 @@ class ValidationError { } } -export = ValidationError; \ No newline at end of file +export default ValidationError; \ No newline at end of file diff --git a/src/etapi/app_info.ts b/src/etapi/app_info.ts index 81830fec2..53cb50ee4 100644 --- a/src/etapi/app_info.ts +++ b/src/etapi/app_info.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; -import appInfo = require('../services/app_info'); -import eu = require('./etapi_utils'); +import appInfo from "../services/app_info.js"; +import eu from "./etapi_utils.js"; function register(router: Router) { eu.route(router, 'get', '/etapi/app-info', (req, res, next) => { @@ -8,6 +8,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/attachments.ts b/src/etapi/attachments.ts index 802e9975f..949a6984d 100644 --- a/src/etapi/attachments.ts +++ b/src/etapi/attachments.ts @@ -1,11 +1,11 @@ -import becca = require('../becca/becca'); -import eu = require('./etapi_utils'); -import mappers = require('./mappers'); -import v = require('./validators'); -import utils = require('../services/utils'); +import becca from "../becca/becca.js"; +import eu from "./etapi_utils.js"; +import mappers from "./mappers.js"; +import v from "./validators.js"; +import utils from "../services/utils.js"; import { Router } from 'express'; -import { AttachmentRow } from '../becca/entities/rows'; -import { ValidatorMap } from './etapi-interface'; +import { AttachmentRow } from '../becca/entities/rows.js'; +import { ValidatorMap } from './etapi-interface.js'; function register(router: Router) { const ALLOWED_PROPERTIES_FOR_CREATE_ATTACHMENT: ValidatorMap = { @@ -104,6 +104,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/attributes.ts b/src/etapi/attributes.ts index 59865da62..4d749744b 100644 --- a/src/etapi/attributes.ts +++ b/src/etapi/attributes.ts @@ -1,11 +1,11 @@ -import becca = require('../becca/becca'); -import eu = require('./etapi_utils'); -import mappers = require('./mappers'); -import attributeService = require('../services/attributes'); -import v = require('./validators'); +import becca from "../becca/becca.js"; +import eu from "./etapi_utils.js"; +import mappers from "./mappers.js"; +import attributeService from "../services/attributes.js"; +import v from "./validators.js"; import { Router } from 'express'; -import { AttributeRow } from '../becca/entities/rows'; -import { ValidatorMap } from './etapi-interface'; +import { AttributeRow } from '../becca/entities/rows.js'; +import { ValidatorMap } from './etapi-interface.js'; function register(router: Router) { eu.route(router, 'get', '/etapi/attributes/:attributeId', (req, res, next) => { @@ -81,6 +81,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/auth.ts b/src/etapi/auth.ts index e6c440e52..4ca2fb45b 100644 --- a/src/etapi/auth.ts +++ b/src/etapi/auth.ts @@ -1,7 +1,7 @@ -import becca = require('../becca/becca'); -import eu = require('./etapi_utils'); -import passwordEncryptionService = require('../services/encryption/password_encryption'); -import etapiTokenService = require('../services/etapi_tokens'); +import becca from "../becca/becca.js"; +import eu from "./etapi_utils.js"; +import passwordEncryptionService from "../services/encryption/password_encryption.js"; +import etapiTokenService from "../services/etapi_tokens.js"; import { RequestHandler, Router } from 'express'; function register(router: Router, loginMiddleware: RequestHandler[]) { @@ -39,6 +39,6 @@ function register(router: Router, loginMiddleware: RequestHandler[]) { }); } -export = { +export default { register } diff --git a/src/etapi/backup.ts b/src/etapi/backup.ts index 50c2bd49c..f1b80630d 100644 --- a/src/etapi/backup.ts +++ b/src/etapi/backup.ts @@ -1,7 +1,7 @@ import { Router } from "express"; -import eu = require('./etapi_utils'); -import backupService = require('../services/backup'); +import eu from "./etapi_utils.js"; +import backupService from "../services/backup.js"; function register(router: Router) { eu.route(router, 'put', '/etapi/backup/:backupName', async (req, res, next) => { @@ -11,6 +11,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/branches.ts b/src/etapi/branches.ts index d41a5857b..8a6b61e2f 100644 --- a/src/etapi/branches.ts +++ b/src/etapi/branches.ts @@ -1,12 +1,12 @@ import { Router } from "express"; -import becca = require('../becca/becca'); -import eu = require('./etapi_utils'); -import mappers = require('./mappers'); -import BBranch = require('../becca/entities/bbranch'); -import entityChangesService = require('../services/entity_changes'); -import v = require('./validators'); -import { BranchRow } from "../becca/entities/rows"; +import becca from "../becca/becca.js"; +import eu from "./etapi_utils.js"; +import mappers from "./mappers.js"; +import BBranch from "../becca/entities/bbranch.js"; +import entityChangesService from "../services/entity_changes.js"; +import v from "./validators.js"; +import { BranchRow } from "../becca/entities/rows.js"; function register(router: Router) { eu.route(router, 'get', '/etapi/branches/:branchId', (req, res, next) => { @@ -84,6 +84,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/etapi_utils.ts b/src/etapi/etapi_utils.ts index 9799deef0..3ced5cc61 100644 --- a/src/etapi/etapi_utils.ts +++ b/src/etapi/etapi_utils.ts @@ -1,12 +1,12 @@ -import cls = require('../services/cls'); -import sql = require('../services/sql'); -import log = require('../services/log'); -import becca = require('../becca/becca'); -import etapiTokenService = require('../services/etapi_tokens'); -import config = require('../services/config'); +import cls from "../services/cls.js"; +import sql from "../services/sql.js"; +import log from "../services/log.js"; +import becca from "../becca/becca.js"; +import etapiTokenService from "../services/etapi_tokens.js"; +import config from "../services/config.js"; import { NextFunction, Request, RequestHandler, Response, Router } from 'express'; -import { AppRequest, AppRequestHandler } from '../routes/route-interface'; -import { ValidatorMap } from './etapi-interface'; +import { AppRequest, AppRequestHandler } from '../routes/route-interface.js'; +import { ValidatorMap } from './etapi-interface.js'; const GENERIC_CODE = "GENERIC"; type HttpMethod = "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head"; @@ -146,7 +146,7 @@ function validateAndPatch(target: any, source: any, allowedProperties: Validator } } -export = { +export default { EtapiError, sendError, route, diff --git a/src/etapi/mappers.ts b/src/etapi/mappers.ts index 537b51738..1caf21cf4 100644 --- a/src/etapi/mappers.ts +++ b/src/etapi/mappers.ts @@ -1,7 +1,7 @@ -import BAttachment = require("../becca/entities/battachment"); -import BAttribute = require("../becca/entities/battribute"); -import BBranch = require("../becca/entities/bbranch"); -import BNote = require("../becca/entities/bnote"); +import BAttachment from "../becca/entities/battachment.js"; +import BAttribute from "../becca/entities/battribute.js"; +import BBranch from "../becca/entities/bbranch.js"; +import BNote from "../becca/entities/bnote.js"; function mapNoteToPojo(note: BNote) { return { @@ -64,7 +64,7 @@ function mapAttachmentToPojo(attachment: BAttachment) { }; } -export = { +export default { mapNoteToPojo, mapBranchToPojo, mapAttributeToPojo, diff --git a/src/etapi/notes.ts b/src/etapi/notes.ts index 62263983f..846e77dc2 100644 --- a/src/etapi/notes.ts +++ b/src/etapi/notes.ts @@ -1,21 +1,20 @@ -import becca = require('../becca/becca'); -import utils = require('../services/utils'); -import eu = require('./etapi_utils'); -import mappers = require('./mappers'); -import noteService = require('../services/notes'); -import TaskContext = require('../services/task_context'); -import v = require('./validators'); -import searchService = require('../services/search/services/search'); -import SearchContext = require('../services/search/search_context'); -import zipExportService = require('../services/export/zip'); -import zipImportService = require('../services/import/zip'); +import becca from "../becca/becca.js"; +import utils from "../services/utils.js"; +import eu from "./etapi_utils.js"; +import mappers from "./mappers.js"; +import noteService from "../services/notes.js"; +import TaskContext from "../services/task_context.js"; +import v from "./validators.js"; +import searchService from "../services/search/services/search.js"; +import SearchContext from "../services/search/search_context.js"; +import zipExportService from "../services/export/zip.js"; +import zipImportService from "../services/import/zip.js"; import { Router } from 'express'; -import { AppRequest } from '../routes/route-interface'; +import { AppRequest } from '../routes/route-interface.js'; import { ParsedQs } from 'qs'; -import { NoteParams } from '../services/note-interface'; -import BNote = require('../becca/entities/bnote'); -import { SearchParams } from '../services/search/services/types'; -import { ValidatorMap } from './etapi-interface'; +import { NoteParams } from '../services/note-interface.js'; +import { SearchParams } from '../services/search/services/types.js'; +import { ValidatorMap } from './etapi-interface.js'; function register(router: Router) { eu.route(router, 'get', '/etapi/notes', (req, res, next) => { @@ -267,6 +266,6 @@ function parseInteger(obj: any, name: string) { return integer; } -export = { +export default { register }; diff --git a/src/etapi/spec.ts b/src/etapi/spec.ts index 530249d46..9c183e9c1 100644 --- a/src/etapi/spec.ts +++ b/src/etapi/spec.ts @@ -1,9 +1,10 @@ import { Router } from "express"; -import fs = require('fs'); -import path = require('path'); +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) { @@ -17,6 +18,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/special_notes.ts b/src/etapi/special_notes.ts index 4de5d77df..1df65c638 100644 --- a/src/etapi/special_notes.ts +++ b/src/etapi/special_notes.ts @@ -1,7 +1,7 @@ -import specialNotesService = require('../services/special_notes'); -import dateNotesService = require('../services/date_notes'); -import eu = require('./etapi_utils'); -import mappers = require('./mappers'); +import specialNotesService from "../services/special_notes.js"; +import dateNotesService from "../services/date_notes.js"; +import eu from "./etapi_utils.js"; +import mappers from "./mappers.js"; import { Router } from 'express'; const getDateInvalidError = (date: string) => new eu.EtapiError(400, "DATE_INVALID", `Date "${date}" is not valid.`); @@ -73,6 +73,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/etapi/validators.ts b/src/etapi/validators.ts index ce6935c7c..37aafecef 100644 --- a/src/etapi/validators.ts +++ b/src/etapi/validators.ts @@ -1,5 +1,6 @@ -import noteTypeService = require('../services/note_types'); -import dateUtils = require('../services/date_utils'); +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`; } @@ -107,7 +106,7 @@ function isValidEntityId(obj: unknown) { } } -export = { +export default { mandatory, notNull, isString, diff --git a/src/routes/api/app_info.ts b/src/routes/api/app_info.ts index 66a9bc366..87501e804 100644 --- a/src/routes/api/app_info.ts +++ b/src/routes/api/app_info.ts @@ -1,11 +1,11 @@ "use strict"; -import appInfo = require('../../services/app_info'); +import appInfo from "../../services/app_info.js"; function getAppInfo() { return appInfo; } -export = { +export default { getAppInfo }; diff --git a/src/routes/api/attachments.ts b/src/routes/api/attachments.ts index 9fde39fc5..d56bd1bbb 100644 --- a/src/routes/api/attachments.ts +++ b/src/routes/api/attachments.ts @@ -1,7 +1,7 @@ -import becca = require('../../becca/becca'); -import blobService = require('../../services/blob'); -import ValidationError = require('../../errors/validation_error'); -import imageService = require("../../services/image"); +import becca from "../../becca/becca.js"; +import blobService from "../../services/blob.js"; +import ValidationError from "../../errors/validation_error.js"; +import imageService from "../../services/image.js"; import { Request } from 'express'; function getAttachmentBlob(req: Request) { @@ -97,7 +97,7 @@ function convertAttachmentToNote(req: Request) { return attachment.convertToNote(); } -export = { +export default { getAttachmentBlob, getAttachments, getAttachment, diff --git a/src/routes/api/attributes.ts b/src/routes/api/attributes.ts index e66906f37..b31afecf4 100644 --- a/src/routes/api/attributes.ts +++ b/src/routes/api/attributes.ts @@ -1,11 +1,11 @@ "use strict"; -import sql = require('../../services/sql'); -import log = require('../../services/log'); -import attributeService = require('../../services/attributes'); -import BAttribute = require('../../becca/entities/battribute'); -import becca = require('../../becca/becca'); -import ValidationError = require('../../errors/validation_error'); +import sql from "../../services/sql.js"; +import log from "../../services/log.js"; +import attributeService from "../../services/attributes.js"; +import BAttribute from "../../becca/entities/battribute.js"; +import becca from "../../becca/becca.js"; +import ValidationError from "../../errors/validation_error.js"; import { Request } from 'express'; function getEffectiveNoteAttributes(req: Request) { @@ -238,7 +238,7 @@ function deleteRelation(req: Request) { } } -export = { +export default { updateNoteAttributes, updateNoteAttribute, setNoteAttribute, diff --git a/src/routes/api/autocomplete.ts b/src/routes/api/autocomplete.ts index 0aaa3f537..f238e7f1e 100644 --- a/src/routes/api/autocomplete.ts +++ b/src/routes/api/autocomplete.ts @@ -1,13 +1,13 @@ "use strict"; -import beccaService = require('../../becca/becca_service'); -import searchService = require('../../services/search/services/search'); -import log = require('../../services/log'); -import utils = require('../../services/utils'); -import cls = require('../../services/cls'); -import becca = require('../../becca/becca'); +import beccaService from "../../becca/becca_service.js"; +import searchService from "../../services/search/services/search.js"; +import log from "../../services/log.js"; +import utils from "../../services/utils.js"; +import cls from "../../services/cls.js"; +import becca from "../../becca/becca.js"; import { Request } from 'express'; -import ValidationError = require('../../errors/validation_error'); +import ValidationError from "../../errors/validation_error.js"; function getAutocomplete(req: Request) { if (typeof req.query.query !== "string") { @@ -75,6 +75,6 @@ function getRecentNotes(activeNoteId: string) { }); } -export = { +export default { getAutocomplete }; diff --git a/src/routes/api/backend_log.ts b/src/routes/api/backend_log.ts index a4dbac9ab..6e3af2a8e 100644 --- a/src/routes/api/backend_log.ts +++ b/src/routes/api/backend_log.ts @@ -1,8 +1,8 @@ "use strict"; -import fs = require('fs'); -import dateUtils = require('../../services/date_utils'); -import dataDir = require('../../services/data_dir'); +import fs from "fs"; +import dateUtils from "../../services/date_utils.js"; +import dataDir from "../../services/data_dir.js"; const { LOG_DIR } = dataDir; function getBackendLog() { @@ -17,6 +17,6 @@ function getBackendLog() { } } -export = { +export default { getBackendLog }; diff --git a/src/routes/api/branches.ts b/src/routes/api/branches.ts index 8c7562128..11141fbe8 100644 --- a/src/routes/api/branches.ts +++ b/src/routes/api/branches.ts @@ -1,16 +1,16 @@ "use strict"; -import sql = require('../../services/sql'); -import utils = require('../../services/utils'); -import entityChangesService = require('../../services/entity_changes'); -import treeService = require('../../services/tree'); -import eraseService = require('../../services/erase'); -import becca = require('../../becca/becca'); -import TaskContext = require('../../services/task_context'); -import branchService = require('../../services/branches'); -import log = require('../../services/log'); -import ValidationError = require('../../errors/validation_error'); -import eventService = require("../../services/events"); +import sql from "../../services/sql.js"; +import utils from "../../services/utils.js"; +import entityChangesService from "../../services/entity_changes.js"; +import treeService from "../../services/tree.js"; +import eraseService from "../../services/erase.js"; +import becca from "../../becca/becca.js"; +import TaskContext from "../../services/task_context.js"; +import branchService from "../../services/branches.js"; +import log from "../../services/log.js"; +import ValidationError from "../../errors/validation_error.js"; +import eventService from "../../services/events.js"; import { Request } from 'express'; /** @@ -224,7 +224,7 @@ function setPrefix(req: Request) { branch.save(); } -export = { +export default { moveBranchToParent, moveBranchBeforeNote, moveBranchAfterNote, diff --git a/src/routes/api/bulk_action.ts b/src/routes/api/bulk_action.ts index 4d1a3e98f..799d05952 100644 --- a/src/routes/api/bulk_action.ts +++ b/src/routes/api/bulk_action.ts @@ -1,6 +1,6 @@ import { Request } from 'express'; -import becca = require('../../becca/becca'); -import bulkActionService = require('../../services/bulk_actions'); +import becca from "../../becca/becca.js"; +import bulkActionService from "../../services/bulk_actions.js"; function execute(req: Request) { const {noteIds, includeDescendants} = req.body; @@ -43,7 +43,7 @@ function getAffectedNoteIds(noteIds: string[], includeDescendants: boolean) { return affectedNoteIds; } -export = { +export default { execute, getAffectedNoteCount }; diff --git a/src/routes/api/clipper.ts b/src/routes/api/clipper.ts index e7f523cec..ae181742c 100644 --- a/src/routes/api/clipper.ts +++ b/src/routes/api/clipper.ts @@ -2,22 +2,22 @@ import { Request } from "express"; -import attributeService = require('../../services/attributes'); -import cloneService = require('../../services/cloning'); -import noteService = require('../../services/notes'); -import dateNoteService = require('../../services/date_notes'); -import dateUtils = require('../../services/date_utils'); -import imageService = require('../../services/image'); -import appInfo = require('../../services/app_info'); -import ws = require('../../services/ws'); -import log = require('../../services/log'); -import utils = require('../../services/utils'); -import path = require('path'); -import htmlSanitizer = require('../../services/html_sanitizer'); -import attributeFormatter = require('../../services/attribute_formatter'); -import jsdom = require("jsdom"); -import BNote = require("../../becca/entities/bnote"); -import ValidationError = require("../../errors/validation_error"); +import attributeService from "../../services/attributes.js"; +import cloneService from "../../services/cloning.js"; +import noteService from "../../services/notes.js"; +import dateNoteService from "../../services/date_notes.js"; +import dateUtils from "../../services/date_utils.js"; +import imageService from "../../services/image.js"; +import appInfo from "../../services/app_info.js"; +import ws from "../../services/ws.js"; +import log from "../../services/log.js"; +import utils from "../../services/utils.js"; +import path from "path"; +import htmlSanitizer from "../../services/html_sanitizer.js"; +import attributeFormatter from "../../services/attribute_formatter.js"; +import jsdom from "jsdom"; +import BNote from "../../becca/entities/bnote.js"; +import ValidationError from "../../errors/validation_error.js"; const { JSDOM } = jsdom; interface Image { @@ -229,7 +229,7 @@ function findNotesByUrl(req: Request){ } } -export = { +export default { createNote, addClipping, openNote, diff --git a/src/routes/api/cloning.ts b/src/routes/api/cloning.ts index 8ab02900d..73de813cb 100644 --- a/src/routes/api/cloning.ts +++ b/src/routes/api/cloning.ts @@ -1,7 +1,7 @@ "use strict"; import { Request } from 'express'; -import cloningService = require('../../services/cloning'); +import cloningService from "../../services/cloning.js"; function cloneNoteToBranch(req: Request) { const {noteId, parentBranchId} = req.params; @@ -29,7 +29,7 @@ function toggleNoteInParent(req: Request) { return cloningService.toggleNoteInParent(present === 'true', noteId, parentNoteId); } -export = { +export default { cloneNoteToBranch, cloneNoteToParentNote, cloneNoteAfter, diff --git a/src/routes/api/database.ts b/src/routes/api/database.ts index 199862b41..8be084d12 100644 --- a/src/routes/api/database.ts +++ b/src/routes/api/database.ts @@ -1,12 +1,12 @@ "use strict"; -import sql = require('../../services/sql'); -import log = require('../../services/log'); -import backupService = require('../../services/backup'); -import anonymizationService = require('../../services/anonymization'); -import consistencyChecksService = require('../../services/consistency_checks'); +import sql from "../../services/sql.js"; +import log from "../../services/log.js"; +import backupService from "../../services/backup.js"; +import anonymizationService from "../../services/anonymization.js"; +import consistencyChecksService from "../../services/consistency_checks.js"; import { Request } from 'express'; -import ValidationError = require('../../errors/validation_error'); +import ValidationError from "../../errors/validation_error.js"; function getExistingBackups() { return backupService.getExistingBackups(); @@ -49,7 +49,7 @@ function checkIntegrity() { }; } -export = { +export default { getExistingBackups, backupDatabase, vacuumDatabase, diff --git a/src/routes/api/etapi_tokens.ts b/src/routes/api/etapi_tokens.ts index d7dd078bd..82cb470e8 100644 --- a/src/routes/api/etapi_tokens.ts +++ b/src/routes/api/etapi_tokens.ts @@ -1,5 +1,5 @@ import { Request } from 'express'; -import etapiTokenService = require('../../services/etapi_tokens'); +import etapiTokenService from "../../services/etapi_tokens.js"; function getTokens() { const tokens = etapiTokenService.getTokens(); @@ -21,7 +21,7 @@ function deleteToken(req: Request) { etapiTokenService.deleteToken(req.params.etapiTokenId); } -export = { +export default { getTokens, createToken, patchToken, diff --git a/src/routes/api/export.ts b/src/routes/api/export.ts index 7d6b3f683..f654487af 100644 --- a/src/routes/api/export.ts +++ b/src/routes/api/export.ts @@ -1,14 +1,14 @@ "use strict"; -import zipExportService = require('../../services/export/zip'); -import singleExportService = require('../../services/export/single'); -import opmlExportService = require('../../services/export/opml'); -import becca = require('../../becca/becca'); -import TaskContext = require('../../services/task_context'); -import log = require('../../services/log'); -import NotFoundError = require('../../errors/not_found_error'); +import zipExportService from "../../services/export/zip.js"; +import singleExportService from "../../services/export/single.js"; +import opmlExportService from "../../services/export/opml.js"; +import becca from "../../becca/becca.js"; +import TaskContext from "../../services/task_context.js"; +import log from "../../services/log.js"; +import NotFoundError from "../../errors/not_found_error.js"; import { Request, Response } from 'express'; -import ValidationError = require('../../errors/validation_error'); +import ValidationError from "../../errors/validation_error.js"; function exportBranch(req: Request, res: Response) { const {branchId, type, format, version, taskId} = req.params; @@ -55,6 +55,6 @@ function exportBranch(req: Request, res: Response) { } } -export = { +export default { exportBranch }; diff --git a/src/routes/api/files.ts b/src/routes/api/files.ts index 3bb269f7d..e05765ddb 100644 --- a/src/routes/api/files.ts +++ b/src/routes/api/files.ts @@ -1,20 +1,20 @@ "use strict"; -import protectedSessionService = require('../../services/protected_session'); -import utils = require('../../services/utils'); -import log = require('../../services/log'); -import noteService = require('../../services/notes'); -import tmp = require('tmp'); -import fs = require('fs'); +import protectedSessionService from "../../services/protected_session.js"; +import utils from "../../services/utils.js"; +import log from "../../services/log.js"; +import noteService from "../../services/notes.js"; +import tmp from "tmp"; +import fs from "fs"; import { Readable } from 'stream'; -import chokidar = require('chokidar'); -import ws = require('../../services/ws'); -import becca = require('../../becca/becca'); -import ValidationError = require('../../errors/validation_error'); +import chokidar from "chokidar"; +import ws from "../../services/ws.js"; +import becca from "../../becca/becca.js"; +import ValidationError from "../../errors/validation_error.js"; import { Request, Response } from 'express'; -import BNote = require('../../becca/entities/bnote'); -import BAttachment = require('../../becca/entities/battachment'); -import { AppRequest } from '../route-interface'; +import BNote from "../../becca/entities/bnote.js"; +import BAttachment from "../../becca/entities/battachment.js"; +import { AppRequest } from '../route-interface.js'; function updateFile(req: AppRequest) { const note = becca.getNoteOrThrow(req.params.noteId); @@ -245,7 +245,7 @@ function uploadModifiedFileToAttachment(req: Request) { attachment.setContent(fileContent); } -export = { +export default { updateFile, updateAttachment, openFile, diff --git a/src/routes/api/fonts.ts b/src/routes/api/fonts.ts index fc68dc920..0f0c85cb2 100644 --- a/src/routes/api/fonts.ts +++ b/src/routes/api/fonts.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import optionService = require('../../services/options'); +import optionService from "../../services/options.js"; function getFontCss(req: Request, res: Response) { res.setHeader('Content-Type', 'text/css'); @@ -35,6 +35,6 @@ function getFontCss(req: Request, res: Response) { res.send(style); } -export = { +export default { getFontCss }; diff --git a/src/routes/api/image.ts b/src/routes/api/image.ts index 926ad3ead..14167de70 100644 --- a/src/routes/api/image.ts +++ b/src/routes/api/image.ts @@ -1,13 +1,13 @@ "use strict"; -import imageService = require('../../services/image'); -import becca = require('../../becca/becca'); -const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; -import fs = require('fs'); +import imageService from "../../services/image.js"; +import becca from "../../becca/becca.js"; +import fs from "fs"; import { Request, Response } from 'express'; -import BNote = require('../../becca/entities/bnote'); -import BRevision = require('../../becca/entities/brevision'); -import { AppRequest } from '../route-interface'; +import BNote from "../../becca/entities/bnote.js"; +import BRevision from "../../becca/entities/brevision.js"; +import { AppRequest } from '../route-interface.js'; +import { RESOURCE_DIR } from "../../services/resource_dir.js"; function returnImageFromNote(req: Request, res: Response) { const image = becca.getNote(req.params.noteId); @@ -112,7 +112,7 @@ function updateImage(req: AppRequest) { return { uploaded: true }; } -export = { +export default { returnImageFromNote, returnImageFromRevision, returnAttachedImage, diff --git a/src/routes/api/import.ts b/src/routes/api/import.ts index f4e0b446e..1ea65d87b 100644 --- a/src/routes/api/import.ts +++ b/src/routes/api/import.ts @@ -1,19 +1,19 @@ "use strict"; -import enexImportService = require('../../services/import/enex'); -import opmlImportService = require('../../services/import/opml'); -import zipImportService = require('../../services/import/zip'); -import singleImportService = require('../../services/import/single'); -import cls = require('../../services/cls'); -import path = require('path'); -import becca = require('../../becca/becca'); -import beccaLoader = require('../../becca/becca_loader'); -import log = require('../../services/log'); -import TaskContext = require('../../services/task_context'); -import ValidationError = require('../../errors/validation_error'); +import enexImportService from "../../services/import/enex.js"; +import opmlImportService from "../../services/import/opml.js"; +import zipImportService from "../../services/import/zip.js"; +import singleImportService from "../../services/import/single.js"; +import cls from "../../services/cls.js"; +import path from "path"; +import becca from "../../becca/becca.js"; +import beccaLoader from "../../becca/becca_loader.js"; +import log from "../../services/log.js"; +import TaskContext from "../../services/task_context.js"; +import ValidationError from "../../errors/validation_error.js"; import { Request } from 'express'; -import BNote = require('../../becca/entities/bnote'); -import { AppRequest } from '../route-interface'; +import BNote from "../../becca/entities/bnote.js"; +import { AppRequest } from '../route-interface.js'; async function importNotesToBranch(req: AppRequest) { const { parentNoteId } = req.params; @@ -136,7 +136,7 @@ async function importAttachmentsToNote(req: AppRequest) { } } -export = { +export default { importNotesToBranch, importAttachmentsToNote }; diff --git a/src/routes/api/keys.ts b/src/routes/api/keys.ts index fe4f208f9..cd49c5c47 100644 --- a/src/routes/api/keys.ts +++ b/src/routes/api/keys.ts @@ -1,7 +1,7 @@ "use strict"; -import keyboardActions = require('../../services/keyboard_actions'); -import becca = require('../../becca/becca'); +import keyboardActions from "../../services/keyboard_actions.js"; +import becca from "../../becca/becca.js"; function getKeyboardActions() { return keyboardActions.getKeyboardActions(); @@ -14,7 +14,7 @@ function getShortcutsForNotes() { return labels.filter(attr => becca.getNote(attr.noteId)?.type !== 'launcher'); } -export = { +export default { getKeyboardActions, getShortcutsForNotes }; diff --git a/src/routes/api/login.ts b/src/routes/api/login.ts index a769c4627..f5b813d2b 100644 --- a/src/routes/api/login.ts +++ b/src/routes/api/login.ts @@ -1,19 +1,19 @@ "use strict"; -import options = require('../../services/options'); -import utils = require('../../services/utils'); -import dateUtils = require('../../services/date_utils'); -import instanceId = require('../../services/instance_id'); -import passwordEncryptionService = require('../../services/encryption/password_encryption'); -import protectedSessionService = require('../../services/protected_session'); -import appInfo = require('../../services/app_info'); -import eventService = require('../../services/events'); -import sqlInit = require('../../services/sql_init'); -import sql = require('../../services/sql'); -import ws = require('../../services/ws'); -import etapiTokenService = require('../../services/etapi_tokens'); +import options from "../../services/options.js"; +import utils from "../../services/utils.js"; +import dateUtils from "../../services/date_utils.js"; +import instanceId from "../../services/instance_id.js"; +import passwordEncryptionService from "../../services/encryption/password_encryption.js"; +import protectedSessionService from "../../services/protected_session.js"; +import appInfo from "../../services/app_info.js"; +import eventService from "../../services/events.js"; +import sqlInit from "../../services/sql_init.js"; +import sql from "../../services/sql.js"; +import ws from "../../services/ws.js"; +import etapiTokenService from "../../services/etapi_tokens.js"; import { Request } from 'express'; -import { AppRequest } from '../route-interface'; +import { AppRequest } from '../route-interface.js'; function loginSync(req: AppRequest) { if (!sqlInit.schemaExists()) { @@ -110,7 +110,7 @@ function token(req: Request) { return { token: authToken }; } -export = { +export default { loginSync, loginToProtectedSession, logoutFromProtectedSession, diff --git a/src/routes/api/note_map.ts b/src/routes/api/note_map.ts index 6abfc1878..4c4590e90 100644 --- a/src/routes/api/note_map.ts +++ b/src/routes/api/note_map.ts @@ -1,9 +1,9 @@ "use strict"; -import becca = require('../../becca/becca'); +import becca from "../../becca/becca.js"; import { JSDOM } from "jsdom"; -import BNote = require('../../becca/entities/bnote'); -import BAttribute = require('../../becca/entities/battribute'); +import BNote from "../../becca/entities/bnote.js"; +import BAttribute from "../../becca/entities/battribute.js"; import { Request } from 'express'; function buildDescendantCountMap(noteIdsToCount: string[]) { @@ -384,7 +384,7 @@ function getBacklinks(req: Request) { }); } -export = { +export default { getLinkMap, getTreeMap, getBacklinkCount, diff --git a/src/routes/api/notes.ts b/src/routes/api/notes.ts index c5e3e1c37..c47aad91c 100644 --- a/src/routes/api/notes.ts +++ b/src/routes/api/notes.ts @@ -1,18 +1,18 @@ "use strict"; -import noteService = require('../../services/notes'); -import eraseService = require('../../services/erase'); -import treeService = require('../../services/tree'); -import sql = require('../../services/sql'); -import utils = require('../../services/utils'); -import log = require('../../services/log'); -import TaskContext = require('../../services/task_context'); -import becca = require('../../becca/becca'); -import ValidationError = require('../../errors/validation_error'); -import blobService = require('../../services/blob'); +import noteService from "../../services/notes.js"; +import eraseService from "../../services/erase.js"; +import treeService from "../../services/tree.js"; +import sql from "../../services/sql.js"; +import utils from "../../services/utils.js"; +import log from "../../services/log.js"; +import TaskContext from "../../services/task_context.js"; +import becca from "../../becca/becca.js"; +import ValidationError from "../../errors/validation_error.js"; +import blobService from "../../services/blob.js"; import { Request } from 'express'; -import BBranch = require('../../becca/entities/bbranch'); -import { AttributeRow } from '../../becca/entities/rows'; +import BBranch from "../../becca/entities/bbranch.js"; +import { AttributeRow } from '../../becca/entities/rows.js'; function getNote(req: Request) { return becca.getNoteOrThrow(req.params.noteId); @@ -250,7 +250,7 @@ function convertNoteToAttachment(req: Request) { }; } -export = { +export default { getNote, getNoteBlob, getNoteMetadata, diff --git a/src/routes/api/options.ts b/src/routes/api/options.ts index 54630e825..2113746ba 100644 --- a/src/routes/api/options.ts +++ b/src/routes/api/options.ts @@ -1,9 +1,9 @@ "use strict"; -import optionService = require('../../services/options'); -import log = require('../../services/log'); -import searchService = require('../../services/search/services/search'); -import ValidationError = require('../../errors/validation_error'); +import optionService from "../../services/options.js"; +import log from "../../services/log.js"; +import searchService from "../../services/search/services/search.js"; +import ValidationError from "../../errors/validation_error.js"; import { Request } from 'express'; // options allowed to be updated directly in the Options dialog @@ -136,7 +136,7 @@ function isAllowed(name: string) { || name.startsWith("hideArchivedNotes"); } -export = { +export default { getOptions, updateOption, updateOptions, diff --git a/src/routes/api/other.ts b/src/routes/api/other.ts index 1d157f291..c09b5d62d 100644 --- a/src/routes/api/other.ts +++ b/src/routes/api/other.ts @@ -1,7 +1,7 @@ import { Request } from "express"; -import becca = require('../../becca/becca'); -import markdownService = require('../../services/import/markdown'); +import becca from "../../becca/becca.js"; +import markdownService from "../../services/import/markdown.js"; function getIconUsage() { const iconClassToCountMap: Record = {}; @@ -35,7 +35,7 @@ function renderMarkdown(req: Request) { }; } -export = { +export default { getIconUsage, renderMarkdown }; diff --git a/src/routes/api/password.ts b/src/routes/api/password.ts index 5fb4c89d6..03721ea3e 100644 --- a/src/routes/api/password.ts +++ b/src/routes/api/password.ts @@ -1,7 +1,7 @@ "use strict"; -import passwordService = require('../../services/encryption/password'); -import ValidationError = require('../../errors/validation_error'); +import passwordService from "../../services/encryption/password.js"; +import ValidationError from "../../errors/validation_error.js"; import { Request } from 'express'; function changePassword(req: Request) { @@ -22,7 +22,7 @@ function resetPassword(req: Request) { return passwordService.resetPassword(); } -export = { +export default { changePassword, resetPassword }; diff --git a/src/routes/api/recent_changes.ts b/src/routes/api/recent_changes.ts index bf662a784..788ae17e0 100644 --- a/src/routes/api/recent_changes.ts +++ b/src/routes/api/recent_changes.ts @@ -1,11 +1,11 @@ "use strict"; -import sql = require('../../services/sql'); -import protectedSessionService = require('../../services/protected_session'); -import noteService = require('../../services/notes'); -import becca = require('../../becca/becca'); +import sql from "../../services/sql.js"; +import protectedSessionService from "../../services/protected_session.js"; +import noteService from "../../services/notes.js"; +import becca from "../../becca/becca.js"; import { Request } from 'express'; -import { RevisionRow } from '../../becca/entities/rows'; +import { RevisionRow } from '../../becca/entities/rows.js'; interface RecentChangeRow { noteId: string; @@ -111,6 +111,6 @@ function getRecentChanges(req: Request) { return recentChanges; } -export = { +export default { getRecentChanges }; diff --git a/src/routes/api/recent_notes.ts b/src/routes/api/recent_notes.ts index 627bdd357..72a49f520 100644 --- a/src/routes/api/recent_notes.ts +++ b/src/routes/api/recent_notes.ts @@ -1,8 +1,8 @@ "use strict"; -import BRecentNote = require('../../becca/entities/brecent_note'); -import sql = require('../../services/sql'); -import dateUtils = require('../../services/date_utils'); +import BRecentNote from "../../becca/entities/brecent_note.js"; +import sql from "../../services/sql.js"; +import dateUtils from "../../services/date_utils.js"; import { Request } from 'express'; function addRecentNote(req: Request) { @@ -19,6 +19,6 @@ function addRecentNote(req: Request) { } } -export = { +export default { addRecentNote }; diff --git a/src/routes/api/relation-map.ts b/src/routes/api/relation-map.ts index c81496349..d24164899 100644 --- a/src/routes/api/relation-map.ts +++ b/src/routes/api/relation-map.ts @@ -1,6 +1,6 @@ import { Request } from 'express'; -import becca = require('../../becca/becca'); -import sql = require('../../services/sql'); +import becca from "../../becca/becca.js"; +import sql from "../../services/sql.js"; interface ResponseData { noteTitles: Record; @@ -76,6 +76,6 @@ function getRelationMap(req: Request) { return resp; } -export = { +export default { getRelationMap }; diff --git a/src/routes/api/revisions.ts b/src/routes/api/revisions.ts index 475b5b9b1..7e98318d5 100644 --- a/src/routes/api/revisions.ts +++ b/src/routes/api/revisions.ts @@ -1,18 +1,18 @@ "use strict"; -import beccaService = require('../../becca/becca_service'); -import revisionService = require('../../services/revisions'); -import utils = require('../../services/utils'); -import sql = require('../../services/sql'); -import cls = require('../../services/cls'); -import path = require('path'); -import becca = require('../../becca/becca'); -import blobService = require('../../services/blob'); -import eraseService = require("../../services/erase"); +import beccaService from "../../becca/becca_service.js"; +import revisionService from "../../services/revisions.js"; +import utils from "../../services/utils.js"; +import sql from "../../services/sql.js"; +import cls from "../../services/cls.js"; +import path from "path"; +import becca from "../../becca/becca.js"; +import blobService from "../../services/blob.js"; +import eraseService from "../../services/erase.js"; import { Request, Response } from 'express'; -import BRevision = require('../../becca/entities/brevision'); -import BNote = require('../../becca/entities/bnote'); -import { NotePojo } from '../../becca/becca-interface'; +import BRevision from "../../becca/entities/brevision.js"; +import BNote from "../../becca/entities/bnote.js"; +import { NotePojo } from '../../becca/becca-interface.js'; interface NotePath { noteId: string; @@ -64,6 +64,10 @@ function getRevision(req: Request) { function getRevisionFilename(revision: BRevision) { let filename = utils.formatDownloadTitle(revision.title, revision.type, revision.mime); + if (!revision.dateCreated) { + throw new Error("Missing creation date for revision."); + } + const extension = path.extname(filename); const date = revision.dateCreated .substr(0, 19) @@ -200,7 +204,7 @@ function getNotePathData(note: BNote): NotePath | undefined { } } -export = { +export default { getRevisionBlob, getRevisions, getRevision, diff --git a/src/routes/api/script.ts b/src/routes/api/script.ts index 8a1b3d072..92aa9fc24 100644 --- a/src/routes/api/script.ts +++ b/src/routes/api/script.ts @@ -1,10 +1,10 @@ "use strict"; -import scriptService = require('../../services/script'); -import attributeService = require('../../services/attributes'); -import becca = require('../../becca/becca'); -import syncService = require('../../services/sync'); -import sql = require('../../services/sql'); +import scriptService from "../../services/script.js"; +import attributeService from "../../services/attributes.js"; +import becca from "../../becca/becca.js"; +import syncService from "../../services/sync.js"; +import sql from "../../services/sql.js"; import { Request } from 'express'; interface ScriptBody { @@ -131,7 +131,7 @@ function getBundle(req: Request) { return scriptService.getScriptBundleForFrontend(note, script, params); } -export = { +export default { exec, run, getStartupBundles, diff --git a/src/routes/api/search.ts b/src/routes/api/search.ts index 358c0d1d2..fbfe74766 100644 --- a/src/routes/api/search.ts +++ b/src/routes/api/search.ts @@ -2,21 +2,21 @@ import { Request } from "express"; -import becca = require('../../becca/becca'); -import SearchContext = require('../../services/search/search_context'); -import searchService = require('../../services/search/services/search'); -import bulkActionService = require('../../services/bulk_actions'); -import cls = require('../../services/cls'); -import attributeFormatter = require('../../services/attribute_formatter'); -import ValidationError = require('../../errors/validation_error'); -import SearchResult = require("../../services/search/search_result"); +import becca from "../../becca/becca.js"; +import SearchContext from "../../services/search/search_context.js"; +import searchService, { EMPTY_RESULT, SearchNoteResult } from "../../services/search/services/search.js"; +import bulkActionService from "../../services/bulk_actions.js"; +import cls from "../../services/cls.js"; +import attributeFormatter from "../../services/attribute_formatter.js"; +import ValidationError from "../../errors/validation_error.js"; +import SearchResult from "../../services/search/search_result.js"; -function searchFromNote(req: Request) { +function searchFromNote(req: Request): SearchNoteResult { const note = becca.getNoteOrThrow(req.params.noteId); if (!note) { // this can be triggered from recent changes, and it's harmless to return an empty list rather than fail - return []; + return EMPTY_RESULT; } if (note.type !== 'search') { @@ -126,7 +126,7 @@ function searchTemplates() { }).map(note => note.noteId); } -export = { +export default { searchFromNote, searchAndExecute, getRelatedNotes, diff --git a/src/routes/api/sender.ts b/src/routes/api/sender.ts index 8d20c1fd9..e19086f56 100644 --- a/src/routes/api/sender.ts +++ b/src/routes/api/sender.ts @@ -1,12 +1,12 @@ "use strict"; -import imageType = require('image-type'); -import imageService = require('../../services/image'); -import noteService = require('../../services/notes'); -import sanitize_attribute_name = require('../../services/sanitize_attribute_name'); -import specialNotesService = require('../../services/special_notes'); +import imageType from "image-type"; +import imageService from "../../services/image.js"; +import noteService from "../../services/notes.js"; +import sanitize_attribute_name from "../../services/sanitize_attribute_name.js"; +import specialNotesService from "../../services/special_notes.js"; import { Request } from 'express'; -import { AppRequest } from '../route-interface'; +import { AppRequest } from '../route-interface.js'; function uploadImage(req: AppRequest) { const file = req.file; @@ -84,7 +84,7 @@ function saveNote(req: Request) { }; } -export = { +export default { uploadImage, saveNote }; diff --git a/src/routes/api/setup.ts b/src/routes/api/setup.ts index 9e63a2331..a4a473a3e 100644 --- a/src/routes/api/setup.ts +++ b/src/routes/api/setup.ts @@ -1,9 +1,9 @@ "use strict"; -import sqlInit = require('../../services/sql_init'); -import setupService = require('../../services/setup'); -import log = require('../../services/log'); -import appInfo = require('../../services/app_info'); +import sqlInit from "../../services/sql_init.js"; +import setupService from "../../services/setup.js"; +import log from "../../services/log.js"; +import appInfo from "../../services/app_info.js"; import { Request } from 'express'; function getStatus() { @@ -51,7 +51,7 @@ function getSyncSeed() { }; } -export = { +export default { getStatus, setupNewDocument, setupSyncFromServer, diff --git a/src/routes/api/similar_notes.ts b/src/routes/api/similar_notes.ts index f60d7f7c6..a845ee3a5 100644 --- a/src/routes/api/similar_notes.ts +++ b/src/routes/api/similar_notes.ts @@ -2,8 +2,8 @@ import { Request } from "express"; -import similarityService = require('../../becca/similarity'); -import becca = require('../../becca/becca'); +import similarityService from "../../becca/similarity.js"; +import becca from "../../becca/becca.js"; async function getSimilarNotes(req: Request) { const noteId = req.params.noteId; @@ -13,6 +13,6 @@ async function getSimilarNotes(req: Request) { return await similarityService.findSimilarNotes(noteId); } -export = { +export default { getSimilarNotes }; diff --git a/src/routes/api/special_notes.ts b/src/routes/api/special_notes.ts index 445cd7315..5d9dc2514 100644 --- a/src/routes/api/special_notes.ts +++ b/src/routes/api/special_notes.ts @@ -1,10 +1,10 @@ "use strict"; -import dateNoteService = require('../../services/date_notes'); -import sql = require('../../services/sql'); -import cls = require('../../services/cls'); -import specialNotesService = require('../../services/special_notes'); -import becca = require('../../becca/becca'); +import dateNoteService from "../../services/date_notes.js"; +import sql from "../../services/sql.js"; +import cls from "../../services/cls.js"; +import specialNotesService from "../../services/special_notes.js"; +import becca from "../../becca/becca.js"; import { Request } from 'express'; function getInboxNote(req: Request) { @@ -82,7 +82,7 @@ function createOrUpdateScriptLauncherFromApi(req: Request) { return specialNotesService.createOrUpdateScriptLauncherFromApi(req.body); } -export = { +export default { getInboxNote, getDayNote, getWeekNote, diff --git a/src/routes/api/sql.ts b/src/routes/api/sql.ts index 3bd1d3eca..9e2f6b09a 100644 --- a/src/routes/api/sql.ts +++ b/src/routes/api/sql.ts @@ -1,9 +1,9 @@ "use strict"; -import sql = require('../../services/sql'); -import becca = require('../../becca/becca'); +import sql from "../../services/sql.js"; +import becca from "../../becca/becca.js"; import { Request } from 'express'; -import ValidationError = require('../../errors/validation_error'); +import ValidationError from "../../errors/validation_error.js"; function getSchema() { const tableNames = sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`); @@ -66,7 +66,7 @@ function execute(req: Request) { } } -export = { +export default { getSchema, execute }; diff --git a/src/routes/api/stats.ts b/src/routes/api/stats.ts index 053647daa..aa948930e 100644 --- a/src/routes/api/stats.ts +++ b/src/routes/api/stats.ts @@ -1,5 +1,5 @@ -import sql = require('../../services/sql'); -import becca = require('../../becca/becca'); +import sql from "../../services/sql.js"; +import becca from "../../becca/becca.js"; import { Request } from 'express'; function getNoteSize(req: Request) { @@ -45,7 +45,7 @@ function getSubtreeSize(req: Request) { }; } -export = { +export default { getNoteSize, getSubtreeSize }; diff --git a/src/routes/api/sync.ts b/src/routes/api/sync.ts index 728065336..428a06c94 100644 --- a/src/routes/api/sync.ts +++ b/src/routes/api/sync.ts @@ -1,19 +1,20 @@ "use strict"; -import syncService = require('../../services/sync'); -import syncUpdateService = require('../../services/sync_update'); -import entityChangesService = require('../../services/entity_changes'); -import sql = require('../../services/sql'); -import sqlInit = require('../../services/sql_init'); -import optionService = require('../../services/options'); -import contentHashService = require('../../services/content_hash'); -import log = require('../../services/log'); -import syncOptions = require('../../services/sync_options'); -import utils = require('../../services/utils'); -import ws = require('../../services/ws'); +import syncService from "../../services/sync.js"; +import syncUpdateService from "../../services/sync_update.js"; +import entityChangesService from "../../services/entity_changes.js"; +import sql from "../../services/sql.js"; +import sqlInit from "../../services/sql_init.js"; +import optionService from "../../services/options.js"; +import contentHashService from "../../services/content_hash.js"; +import log from "../../services/log.js"; +import syncOptions from "../../services/sync_options.js"; +import utils from "../../services/utils.js"; +import ws from "../../services/ws.js"; import { Request } from 'express'; -import { EntityChange, EntityChangeRecord } from '../../services/entity_changes_interface'; -import ValidationError = require('../../errors/validation_error'); +import { EntityChange, EntityChangeRecord } from '../../services/entity_changes_interface.js'; +import ValidationError from "../../errors/validation_error.js"; +import consistencyChecksService from "../../services/consistency_checks.js"; async function testSync() { try { @@ -206,10 +207,10 @@ function queueSector(req: Request) { } function checkEntityChanges() { - require('../../services/consistency_checks').runEntityChangesChecks(); + consistencyChecksService.runEntityChangesChecks(); } -export = { +export default { testSync, checkSync, syncNow, diff --git a/src/routes/api/tree.ts b/src/routes/api/tree.ts index 1b172f10b..f519ea4f8 100644 --- a/src/routes/api/tree.ts +++ b/src/routes/api/tree.ts @@ -1,10 +1,10 @@ "use strict"; -import becca = require('../../becca/becca'); -import log = require('../../services/log'); -import NotFoundError = require('../../errors/not_found_error'); +import becca from "../../becca/becca.js"; +import log from "../../services/log.js"; +import NotFoundError from "../../errors/not_found_error.js"; import { Request } from 'express'; -import BNote = require('../../becca/entities/bnote'); +import BNote from "../../becca/entities/bnote.js"; function getNotesAndBranchesAndAttributes(_noteIds: string[] | Set) { const noteIds = new Set(_noteIds); @@ -160,7 +160,7 @@ function load(req: Request) { return getNotesAndBranchesAndAttributes(req.body.noteIds); } -export = { +export default { getTree, load }; diff --git a/src/routes/assets.ts b/src/routes/assets.ts index 8417c47b9..a1004e33b 100644 --- a/src/routes/assets.ts +++ b/src/routes/assets.ts @@ -1,8 +1,9 @@ -import assetPath = require('../services/asset_path'); -import path = require("path"); -import express = require("express"); -import env = require('../services/env'); -import serveStatic = require('serve-static'); +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"; const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOptions>>) => { if (!env.isDev()) { @@ -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'))); @@ -76,6 +77,6 @@ function register(app: express.Application) { app.use(`/${assetPath}/translations/`, persistentCacheStatic(path.join(srcRoot, "public", "translations/"))); } -export = { +export default { register }; diff --git a/src/routes/custom.ts b/src/routes/custom.ts index 1bdb94ac0..a2e2f900a 100644 --- a/src/routes/custom.ts +++ b/src/routes/custom.ts @@ -1,9 +1,9 @@ -import log = require('../services/log'); -import fileService = require('./api/files'); -import scriptService = require('../services/script'); -import cls = require('../services/cls'); -import sql = require('../services/sql'); -import becca = require('../becca/becca'); +import log from "../services/log.js"; +import fileService from "./api/files.js"; +import scriptService from "../services/script.js"; +import cls from "../services/cls.js"; +import sql from "../services/sql.js"; +import becca from "../becca/becca.js"; import { Request, Response, Router } from 'express'; function handleRequest(req: Request, res: Response) { @@ -84,6 +84,6 @@ function register(router: Router) { }); } -export = { +export default { register }; diff --git a/src/routes/electron.ts b/src/routes/electron.ts index 8a869d935..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; @@ -56,4 +55,4 @@ function init(app: Application) { }); } -export = init; +export default init; diff --git a/src/routes/error_handlers.ts b/src/routes/error_handlers.ts index 96d326bd9..f054a2683 100644 --- a/src/routes/error_handlers.ts +++ b/src/routes/error_handlers.ts @@ -1,5 +1,5 @@ import { Application, NextFunction, Request, Response } from 'express'; -import log = require('../services/log'); +import log from "../services/log.js"; function register(app: Application) { app.use((err: any, req: Request, res: Response, next: NextFunction) => { @@ -39,6 +39,6 @@ function register(app: Application) { }); } -export = { +export default { register }; diff --git a/src/routes/index.ts b/src/routes/index.ts index 2ede70f42..a9403ab26 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,16 +1,16 @@ "use strict"; -import sql = require('../services/sql'); -import attributeService = require('../services/attributes'); -import config = require('../services/config'); -import optionService = require('../services/options'); -import log = require('../services/log'); -import env = require('../services/env'); -import utils = require('../services/utils'); -import protectedSessionService = require('../services/protected_session'); -import packageJson = require('../../package.json'); -import assetPath = require('../services/asset_path'); -import appPath = require('../services/app_path'); +import sql from "../services/sql.js"; +import attributeService from "../services/attributes.js"; +import config from "../services/config.js"; +import optionService from "../services/options.js"; +import log from "../services/log.js"; +import env from "../services/env.js"; +import utils from "../services/utils.js"; +import protectedSessionService from "../services/protected_session.js"; +import packageJson from "../../package.json" with { type: "json" }; +import assetPath from "../services/asset_path.js"; +import appPath from "../services/app_path.js"; import { Request, Response } from 'express'; function index(req: Request, res: Response) { @@ -64,6 +64,6 @@ function getAppCssNoteIds() { return attributeService.getNotesWithLabel('appCss').map(note => note.noteId); } -export = { +export default { index }; diff --git a/src/routes/login.ts b/src/routes/login.ts index cce214fbe..aae82e042 100644 --- a/src/routes/login.ts +++ b/src/routes/login.ts @@ -1,15 +1,15 @@ "use strict"; -import utils = require('../services/utils'); -import optionService = require('../services/options'); -import myScryptService = require('../services/encryption/my_scrypt'); -import log = require('../services/log'); -import passwordService = require('../services/encryption/password'); -import assetPath = require('../services/asset_path'); -import appPath = require('../services/app_path'); -import ValidationError = require('../errors/validation_error'); +import utils from "../services/utils.js"; +import optionService from "../services/options.js"; +import myScryptService from "../services/encryption/my_scrypt.js"; +import log from "../services/log.js"; +import passwordService from "../services/encryption/password.js"; +import assetPath from "../services/asset_path.js"; +import appPath from "../services/app_path.js"; +import ValidationError from "../errors/validation_error.js"; import { Request, Response } from 'express'; -import { AppRequest } from './route-interface'; +import { AppRequest } from './route-interface.js'; function loginPage(req: Request, res: Response) { res.render('login', { @@ -102,7 +102,7 @@ function logout(req: AppRequest, res: Response) { } -export = { +export default { loginPage, setPasswordPage, setPassword, diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 55cad4cd5..5a3e181c5 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -1,76 +1,76 @@ "use strict"; -import utils = require('../services/utils'); -import multer = require('multer'); -import log = require('../services/log'); -import express = require('express'); +import utils from "../services/utils.js"; +import multer from "multer"; +import log from "../services/log.js"; +import express from "express"; const router = express.Router(); -import auth = require('../services/auth'); -import cls = require('../services/cls'); -import sql = require('../services/sql'); -import entityChangesService = require('../services/entity_changes'); -import csurf = require('csurf'); +import auth from "../services/auth.js"; +import cls from "../services/cls.js"; +import sql from "../services/sql.js"; +import entityChangesService from "../services/entity_changes.js"; +import csurf from "csurf"; import { createPartialContentHandler } from "express-partial-content"; -import rateLimit = require("express-rate-limit"); -import AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity'); -import NotFoundError = require('../errors/not_found_error'); -import ValidationError = require('../errors/validation_error'); +import rateLimit from "express-rate-limit"; +import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; +import NotFoundError from "../errors/not_found_error.js"; +import ValidationError from "../errors/validation_error.js"; // page routes -import setupRoute = require('./setup'); -import loginRoute = require('./login'); -import indexRoute = require('./index'); +import setupRoute from "./setup.js"; +import loginRoute from "./login.js"; +import indexRoute from "./index.js"; // API routes -import treeApiRoute = require('./api/tree'); -import notesApiRoute = require('./api/notes'); -import branchesApiRoute = require('./api/branches'); -import attachmentsApiRoute = require('./api/attachments'); -import autocompleteApiRoute = require('./api/autocomplete'); -import cloningApiRoute = require('./api/cloning'); -import revisionsApiRoute = require('./api/revisions'); -import recentChangesApiRoute = require('./api/recent_changes'); -import optionsApiRoute = require('./api/options'); -import passwordApiRoute = require('./api/password'); -import syncApiRoute = require('./api/sync'); -import loginApiRoute = require('./api/login'); -import recentNotesRoute = require('./api/recent_notes'); -import appInfoRoute = require('./api/app_info'); -import exportRoute = require('./api/export'); -import importRoute = require('./api/import'); -import setupApiRoute = require('./api/setup'); -import sqlRoute = require('./api/sql'); -import databaseRoute = require('./api/database'); -import imageRoute = require('./api/image'); -import attributesRoute = require('./api/attributes'); -import scriptRoute = require('./api/script'); -import senderRoute = require('./api/sender'); -import filesRoute = require('./api/files'); -import searchRoute = require('./api/search'); -import bulkActionRoute = require('./api/bulk_action'); -import specialNotesRoute = require('./api/special_notes'); -import noteMapRoute = require('./api/note_map'); -import clipperRoute = require('./api/clipper'); -import similarNotesRoute = require('./api/similar_notes'); -import keysRoute = require('./api/keys'); -import backendLogRoute = require('./api/backend_log'); -import statsRoute = require('./api/stats'); -import fontsRoute = require('./api/fonts'); -import etapiTokensApiRoutes = require('./api/etapi_tokens'); -import relationMapApiRoute = require('./api/relation-map'); -import otherRoute = require('./api/other'); -import shareRoutes = require('../share/routes'); +import treeApiRoute from "./api/tree.js"; +import notesApiRoute from "./api/notes.js"; +import branchesApiRoute from "./api/branches.js"; +import attachmentsApiRoute from "./api/attachments.js"; +import autocompleteApiRoute from "./api/autocomplete.js"; +import cloningApiRoute from "./api/cloning.js"; +import revisionsApiRoute from "./api/revisions.js"; +import recentChangesApiRoute from "./api/recent_changes.js"; +import optionsApiRoute from "./api/options.js"; +import passwordApiRoute from "./api/password.js"; +import syncApiRoute from "./api/sync.js"; +import loginApiRoute from "./api/login.js"; +import recentNotesRoute from "./api/recent_notes.js"; +import appInfoRoute from "./api/app_info.js"; +import exportRoute from "./api/export.js"; +import importRoute from "./api/import.js"; +import setupApiRoute from "./api/setup.js"; +import sqlRoute from "./api/sql.js"; +import databaseRoute from "./api/database.js"; +import imageRoute from "./api/image.js"; +import attributesRoute from "./api/attributes.js"; +import scriptRoute from "./api/script.js"; +import senderRoute from "./api/sender.js"; +import filesRoute from "./api/files.js"; +import searchRoute from "./api/search.js"; +import bulkActionRoute from "./api/bulk_action.js"; +import specialNotesRoute from "./api/special_notes.js"; +import noteMapRoute from "./api/note_map.js"; +import clipperRoute from "./api/clipper.js"; +import similarNotesRoute from "./api/similar_notes.js"; +import keysRoute from "./api/keys.js"; +import backendLogRoute from "./api/backend_log.js"; +import statsRoute from "./api/stats.js"; +import fontsRoute from "./api/fonts.js"; +import etapiTokensApiRoutes from "./api/etapi_tokens.js"; +import relationMapApiRoute from "./api/relation-map.js"; +import otherRoute from "./api/other.js"; +import shareRoutes from "../share/routes.js"; -import etapiAuthRoutes = require('../etapi/auth'); -import etapiAppInfoRoutes = require('../etapi/app_info'); -import etapiAttachmentRoutes = require('../etapi/attachments'); -import etapiAttributeRoutes = require('../etapi/attributes'); -import etapiBranchRoutes = require('../etapi/branches'); -import etapiNoteRoutes = require('../etapi/notes'); -import etapiSpecialNoteRoutes = require('../etapi/special_notes'); -import etapiSpecRoute = require('../etapi/spec'); -import etapiBackupRoute = require('../etapi/backup'); -import { AppRequest, AppRequestHandler } from './route-interface'; +import etapiAuthRoutes from "../etapi/auth.js"; +import etapiAppInfoRoutes from "../etapi/app_info.js"; +import etapiAttachmentRoutes from "../etapi/attachments.js"; +import etapiAttributeRoutes from "../etapi/attributes.js"; +import etapiBranchRoutes from "../etapi/branches.js"; +import etapiNoteRoutes from "../etapi/notes.js"; +import etapiSpecialNoteRoutes from "../etapi/special_notes.js"; +import etapiSpecRoute from "../etapi/spec.js"; +import etapiBackupRoute from "../etapi/backup.js"; +import { AppRequest, AppRequestHandler } from './route-interface.js'; const csrfMiddleware = csurf({ cookie: { @@ -106,7 +106,7 @@ function register(app: express.Application) { route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage); route(GET, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage); - const loginRateLimiter = rateLimit.rateLimit({ + const loginRateLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 10, // limit each IP to 10 requests per windowMs skipSuccessfulRequests: true // successful auth to rate-limited ETAPI routes isn't counted. However, successful auth to /login is still counted! @@ -517,6 +517,6 @@ function createUploadMiddleware() { return multer(multerOptions).single('upload'); } -export = { +export default { register }; diff --git a/src/routes/session_parser.ts b/src/routes/session_parser.ts index 431476f15..ee9918152 100644 --- a/src/routes/session_parser.ts +++ b/src/routes/session_parser.ts @@ -1,7 +1,8 @@ -import session = require("express-session"); -import sessionSecret = require('../services/session_secret'); -import dataDir = require('../services/data_dir'); -const FileStore = require('session-file-store')(session); +import session from "express-session"; +import sessionFileStore from "session-file-store"; +import sessionSecret from "../services/session_secret.js"; +import dataDir from "../services/data_dir.js"; +const FileStore = sessionFileStore(session); const sessionParser = session({ secret: sessionSecret, @@ -19,4 +20,4 @@ const sessionParser = session({ }) }); -export = sessionParser; +export default sessionParser; diff --git a/src/routes/setup.ts b/src/routes/setup.ts index 1d3521f4a..34d886aec 100644 --- a/src/routes/setup.ts +++ b/src/routes/setup.ts @@ -1,21 +1,17 @@ "use strict"; -import sqlInit = require('../services/sql_init'); -import setupService = require('../services/setup'); -import utils = require('../services/utils'); -import assetPath = require('../services/asset_path'); -import appPath = require('../services/app_path'); +import sqlInit from "../services/sql_init.js"; +import setupService from "../services/setup.js"; +import utils from "../services/utils.js"; +import assetPath from "../services/asset_path.js"; +import appPath from "../services/app_path.js"; 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) { }); } -export = { +async function handleElectronRedirect() { + const windowService = (await import("../services/window.js")).default; + const { app } = await import("electron"); + windowService.createMainWindow(app); + windowService.closeSetupWindow(); +} + +export default { setupPage }; diff --git a/src/services/anonymization.ts b/src/services/anonymization.ts index 4e17058a7..8c34122b6 100644 --- a/src/services/anonymization.ts +++ b/src/services/anonymization.ts @@ -1,10 +1,10 @@ -import BUILTIN_ATTRIBUTES = require('./builtin_attributes'); -import fs = require("fs-extra"); -import dataDir = require('./data_dir'); -import dateUtils = require('./date_utils'); -import Database = require("better-sqlite3"); -import sql = require('./sql'); -import path = require("path"); +import BUILTIN_ATTRIBUTES from "./builtin_attributes.js"; +import fs from "fs-extra"; +import dataDir from "./data_dir.js"; +import dateUtils from "./date_utils.js"; +import Database from "better-sqlite3"; +import sql from "./sql.js"; +import path from "path"; function getFullAnonymizationScript() { // we want to delete all non-builtin attributes because they can contain sensitive names and values @@ -90,7 +90,7 @@ function getExistingAnonymizedDatabases() { })); } -export = { +export default { getFullAnonymizationScript, createAnonymizedCopy, getExistingAnonymizedDatabases diff --git a/src/services/api-interface.ts b/src/services/api-interface.ts index 30c248693..a474b09d5 100644 --- a/src/services/api-interface.ts +++ b/src/services/api-interface.ts @@ -1,4 +1,4 @@ -import { OptionRow } from "../becca/entities/rows"; +import { OptionRow } from "../becca/entities/rows.js"; /** * Response for /api/setup/status. diff --git a/src/services/app_icon.ts b/src/services/app_icon.ts index 7a2a7dedf..c6361687c 100644 --- a/src/services/app_icon.ts +++ b/src/services/app_icon.ts @@ -1,12 +1,12 @@ "use strict"; -import path = require('path'); -import resourceDir = require('./resource_dir'); -import log = require('./log'); -import os = require('os'); -import fs = require('fs'); -import config = require('./config'); -import utils = require('./utils'); +import path from "path"; +import resourceDir from "./resource_dir.js"; +import log from "./log.js"; +import os from "os"; +import fs from "fs"; +import config from "./config.js"; +import utils from "./utils.js"; const template = `[Desktop Entry] Type=Application @@ -68,6 +68,6 @@ function getExePath() { return path.resolve(resourceDir.ELECTRON_APP_ROOT_DIR, 'trilium'); } -export = { +export default { installLocalAppIcon }; diff --git a/src/services/app_info.ts b/src/services/app_info.ts index 92bf2dee1..0f1ceba1f 100644 --- a/src/services/app_info.ts +++ b/src/services/app_info.ts @@ -1,14 +1,14 @@ "use strict"; -import build = require('./build'); -import packageJson = require('../../package.json'); -import dataDir = require('./data_dir'); +import build from "./build.js"; +import packageJson from "../../package.json" with { type: "json" }; +import dataDir from "./data_dir.js"; const APP_DB_VERSION = 228; const SYNC_VERSION = 32; const CLIPPER_PROTOCOL_VERSION = "1.0"; -export = { +export default { appVersion: packageJson.version, dbVersion: APP_DB_VERSION, nodeVersion: process.version, diff --git a/src/services/app_path.ts b/src/services/app_path.ts index 3bfa7de40..6d5e02231 100644 --- a/src/services/app_path.ts +++ b/src/services/app_path.ts @@ -1,6 +1,6 @@ -import assetPath = require('./asset_path'); -import env = require('./env'); +import assetPath from "./asset_path.js"; +import env from "./env.js"; -export = env.isDev() +export default env.isDev() ? assetPath + "/app" : assetPath + "/app-dist"; diff --git a/src/services/asset_path.ts b/src/services/asset_path.ts index 53ffebba9..ffb88f626 100644 --- a/src/services/asset_path.ts +++ b/src/services/asset_path.ts @@ -1,3 +1,3 @@ -import packageJson = require('../../package.json'); +import packageJson from "../../package.json" assert { type: "json" }; -export = `assets/v${packageJson.version}`; +export default `assets/v${packageJson.version}`; diff --git a/src/services/attribute_formatter.ts b/src/services/attribute_formatter.ts index a7b4b7500..31112be36 100644 --- a/src/services/attribute_formatter.ts +++ b/src/services/attribute_formatter.ts @@ -1,6 +1,6 @@ "use strict"; -import { AttributeRow } from "../becca/entities/rows"; +import { AttributeRow } from "../becca/entities/rows.js"; function formatAttrForSearch(attr: AttributeRow, searchWithValue: boolean) { let searchStr = ''; @@ -47,6 +47,6 @@ function formatValue(val: string) { } } -export = { +export default { formatAttrForSearch }; diff --git a/src/services/attributes.ts b/src/services/attributes.ts index 0ae77dc36..8f17249e2 100644 --- a/src/services/attributes.ts +++ b/src/services/attributes.ts @@ -1,13 +1,13 @@ "use strict"; -import searchService = require('./search/services/search'); -import sql = require('./sql'); -import becca = require('../becca/becca'); -import BAttribute = require('../becca/entities/battribute'); -import attributeFormatter = require('./attribute_formatter'); -import BUILTIN_ATTRIBUTES = require('./builtin_attributes'); -import BNote = require('../becca/entities/bnote'); -import { AttributeRow } from '../becca/entities/rows'; +import searchService from "./search/services/search.js"; +import sql from "./sql.js"; +import becca from "../becca/becca.js"; +import BAttribute from "../becca/entities/battribute.js"; +import attributeFormatter from "./attribute_formatter.js"; +import BUILTIN_ATTRIBUTES from "./builtin_attributes.js"; +import BNote from "../becca/entities/bnote.js"; +import { AttributeRow } from '../becca/entities/rows.js'; const ATTRIBUTE_TYPES = ['label', 'relation']; @@ -110,7 +110,7 @@ function isAttributeDangerous(type: string, name: string): boolean { ); } -export = { +export default { getNotesWithLabel, getNoteWithLabel, createLabel, diff --git a/src/services/auth.ts b/src/services/auth.ts index 39f2b430e..f19976616 100644 --- a/src/services/auth.ts +++ b/src/services/auth.ts @@ -1,14 +1,14 @@ "use strict"; -import etapiTokenService = require('./etapi_tokens'); -import log = require('./log'); -import sqlInit = require('./sql_init'); -import utils = require('./utils'); -import passwordEncryptionService = require('./encryption/password_encryption'); -import config = require('./config'); -import passwordService = require('./encryption/password'); +import etapiTokenService from "./etapi_tokens.js"; +import log from "./log.js"; +import sqlInit from "./sql_init.js"; +import utils from "./utils.js"; +import passwordEncryptionService from "./encryption/password_encryption.js"; +import config from "./config.js"; +import passwordService from "./encryption/password.js"; import type { NextFunction, Request, Response } from 'express'; -import { AppRequest } from '../routes/route-interface'; +import { AppRequest } from '../routes/route-interface.js'; const noAuthentication = config.General && config.General.noAuthentication === true; @@ -126,7 +126,7 @@ function checkCredentials(req: AppRequest, res: Response, next: NextFunction) { } } -export = { +export default { checkAuth, checkApiAuth, checkAppInitialized, diff --git a/src/services/backend_script_api.ts b/src/services/backend_script_api.ts index 29acac388..5180e4739 100644 --- a/src/services/backend_script_api.ts +++ b/src/services/backend_script_api.ts @@ -1,39 +1,39 @@ -import log = require('./log'); -import noteService = require('./notes'); -import sql = require('./sql'); -import utils = require('./utils'); -import attributeService = require('./attributes'); -import dateNoteService = require('./date_notes'); -import treeService = require('./tree'); -import config = require('./config'); -import axios = require('axios'); -import dayjs = require('dayjs'); -import xml2js = require('xml2js'); -import cloningService = require('./cloning'); -import appInfo = require('./app_info'); -import searchService = require('./search/services/search'); -import SearchContext = require('./search/search_context'); -import becca = require('../becca/becca'); -import ws = require('./ws'); -import SpacedUpdate = require('./spaced_update'); -import specialNotesService = require('./special_notes'); -import branchService = require('./branches'); -import exportService = require('./export/zip'); -import syncMutex = require('./sync_mutex'); -import backupService = require('./backup'); -import optionsService = require('./options'); -import BNote = require('../becca/entities/bnote'); -import AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity'); -import BBranch = require('../becca/entities/bbranch'); -import BAttribute = require('../becca/entities/battribute'); -import BAttachment = require('../becca/entities/battachment'); -import BRevision = require('../becca/entities/brevision'); -import BEtapiToken = require('../becca/entities/betapi_token'); -import BOption = require('../becca/entities/boption'); -import { AttributeRow, AttributeType, NoteType } from '../becca/entities/rows'; -import Becca from '../becca/becca-interface'; -import { NoteParams } from './note-interface'; -import { ApiParams } from './backend_script_api_interface'; +import log from "./log.js"; +import noteService from "./notes.js"; +import sql from "./sql.js"; +import utils from "./utils.js"; +import attributeService from "./attributes.js"; +import dateNoteService from "./date_notes.js"; +import treeService from "./tree.js"; +import config from "./config.js"; +import axios from "axios"; +import dayjs from "dayjs"; +import xml2js from "xml2js"; +import cloningService from "./cloning.js"; +import appInfo from "./app_info.js"; +import searchService from "./search/services/search.js"; +import SearchContext from "./search/search_context.js"; +import becca from "../becca/becca.js"; +import ws from "./ws.js"; +import SpacedUpdate from "./spaced_update.js"; +import specialNotesService from "./special_notes.js"; +import branchService from "./branches.js"; +import exportService from "./export/zip.js"; +import syncMutex from "./sync_mutex.js"; +import backupService from "./backup.js"; +import optionsService from "./options.js"; +import BNote from "../becca/entities/bnote.js"; +import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; +import BBranch from "../becca/entities/bbranch.js"; +import BAttribute from "../becca/entities/battribute.js"; +import BAttachment from "../becca/entities/battachment.js"; +import BRevision from "../becca/entities/brevision.js"; +import BEtapiToken from "../becca/entities/betapi_token.js"; +import BOption from "../becca/entities/boption.js"; +import { AttributeRow } from '../becca/entities/rows.js'; +import Becca from '../becca/becca-interface.js'; +import { NoteParams } from './note-interface.js'; +import { ApiParams } from './backend_script_api_interface.js'; /** @@ -651,6 +651,6 @@ function BackendScriptApi(this: Api, currentNote: BNote, apiParams: ApiParams) { } } -export = BackendScriptApi as any as { +export default BackendScriptApi as any as { new (currentNote: BNote, apiParams: ApiParams): Api }; diff --git a/src/services/backend_script_api_interface.ts b/src/services/backend_script_api_interface.ts index 5ffdf56c5..a315a1d24 100644 --- a/src/services/backend_script_api_interface.ts +++ b/src/services/backend_script_api_interface.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; -import AbstractBeccaEntity = require("../becca/entities/abstract_becca_entity"); -import BNote = require("../becca/entities/bnote"); +import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; +import BNote from "../becca/entities/bnote.js"; export interface ApiParams { startNote?: BNote | null; diff --git a/src/services/backup.ts b/src/services/backup.ts index 3000c9c9a..f9cad0a02 100644 --- a/src/services/backup.ts +++ b/src/services/backup.ts @@ -1,14 +1,14 @@ "use strict"; -import dateUtils = require('./date_utils'); -import optionService = require('./options'); -import fs = require('fs-extra'); -import dataDir = require('./data_dir'); -import log = require('./log'); -import syncMutexService = require('./sync_mutex'); -import cls = require('./cls'); -import sql = require('./sql'); -import path = require('path'); +import dateUtils from "./date_utils.js"; +import optionService from "./options.js"; +import fs from "fs-extra"; +import dataDir from "./data_dir.js"; +import log from "./log.js"; +import syncMutexService from "./sync_mutex.js"; +import cls from "./cls.js"; +import sql from "./sql.js"; +import path from "path"; type BackupType = ("daily" | "weekly" | "monthly"); @@ -75,7 +75,7 @@ if (!fs.existsSync(dataDir.BACKUP_DIR)) { fs.mkdirSync(dataDir.BACKUP_DIR, 0o700); } -export = { +export default { getExistingBackups, backupNow, regularBackup diff --git a/src/services/blob.ts b/src/services/blob.ts index 41d23adc5..03505075a 100644 --- a/src/services/blob.ts +++ b/src/services/blob.ts @@ -1,8 +1,8 @@ -import becca = require('../becca/becca'); -import NotFoundError = require('../errors/not_found_error'); -import protectedSessionService = require('./protected_session'); -import utils = require('./utils'); -import type { Blob } from "./blob-interface"; +import becca from "../becca/becca.js"; +import NotFoundError from "../errors/not_found_error.js"; +import protectedSessionService from "./protected_session.js"; +import utils from "./utils.js"; +import type { Blob } from "./blob-interface.js"; function getBlobPojo(entityName: string, entityId: string, opts?: { preview: boolean }) { // TODO: Unused opts. @@ -54,7 +54,7 @@ function calculateContentHash({blobId, content}: Blob) { return utils.hash(`${blobId}|${content.toString()}`); } -export = { +export default { getBlobPojo, processContent, calculateContentHash diff --git a/src/services/branches.ts b/src/services/branches.ts index 8e6971560..88454c4ab 100644 --- a/src/services/branches.ts +++ b/src/services/branches.ts @@ -1,6 +1,6 @@ -import treeService = require('./tree'); -import sql = require('./sql'); -import BBranch = require('../becca/entities/bbranch.js'); +import treeService from "./tree.js"; +import sql from "./sql.js"; +import BBranch from "../becca/entities/bbranch.js"; function moveBranchToNote(branchToMove: BBranch, targetParentNoteId: string) { if (branchToMove.parentNoteId === targetParentNoteId) { @@ -44,7 +44,7 @@ function moveBranchToBranch(branchToMove: BBranch, targetParentBranch: BBranch, return res; } -export = { +export default { moveBranchToBranch, moveBranchToNote }; diff --git a/src/services/build.ts b/src/services/build.ts index 71e95ea49..4fd5c6288 100644 --- a/src/services/build.ts +++ b/src/services/build.ts @@ -1,4 +1,4 @@ -export = { +export default { buildDate: "2024-07-21T10:25:01Z", buildRevision: "715a952148ae6e83fda0886f5ceec8dc329972ae" }; diff --git a/src/services/builtin_attributes.ts b/src/services/builtin_attributes.ts index 6ccabb4e1..649647b77 100644 --- a/src/services/builtin_attributes.ts +++ b/src/services/builtin_attributes.ts @@ -1,4 +1,4 @@ -export = [ +export default [ // label names { type: 'label', name: 'inbox' }, { type: 'label', name: 'disableVersioning' }, diff --git a/src/services/bulk_actions.ts b/src/services/bulk_actions.ts index 8abc11460..64c180405 100644 --- a/src/services/bulk_actions.ts +++ b/src/services/bulk_actions.ts @@ -1,10 +1,10 @@ -import log = require('./log'); -import becca = require('../becca/becca'); -import cloningService = require('./cloning'); -import branchService = require('./branches'); -import utils = require('./utils'); -import eraseService = require("./erase"); -import BNote = require('../becca/entities/bnote'); +import log from "./log.js"; +import becca from "../becca/becca.js"; +import cloningService from "./cloning.js"; +import branchService from "./branches.js"; +import utils from "./utils.js"; +import eraseService from "./erase.js"; +import BNote from "../becca/entities/bnote.js"; interface Action { labelName: string; @@ -111,7 +111,7 @@ const ACTION_HANDLERS: Record = { res = branchService.moveBranchToNote(note.getParentBranches()[0], action.targetParentNoteId); } - if (!res.success) { + if ("success" in res && !res.success) { log.info(`Moving/cloning note ${note.noteId} to ${action.targetParentNoteId} failed with error ${JSON.stringify(res)}`); } }, @@ -172,6 +172,6 @@ function executeActions(note: BNote, searchResultNoteIds: string[] | Set } } -export = { +export default { executeActions }; diff --git a/src/services/cloning.ts b/src/services/cloning.ts index 36c61a653..6f35e671f 100644 --- a/src/services/cloning.ts +++ b/src/services/cloning.ts @@ -1,18 +1,28 @@ "use strict"; -const sql = require('./sql'); -const eventChangesService = require('./entity_changes'); -const treeService = require('./tree'); -const BBranch = require('../becca/entities/bbranch'); -const becca = require('../becca/becca'); -const log = require('./log'); +import sql from './sql.js'; +import eventChangesService from './entity_changes.js'; +import treeService from './tree.js'; +import BBranch from '../becca/entities/bbranch.js'; +import becca from '../becca/becca.js'; +import log from './log.js'; -function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: string | null = null) { +export interface CloneResponse { + success: boolean; + message?: string; + branchId?: string; + notePath?: string; +} + +function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: string | null = null): CloneResponse { if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) { return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' }; } const parentNote = becca.getNote(parentNoteId); + if (!parentNote) { + return { success: false, message: 'Note cannot be cloned because the parent note could not be found.' }; + } if (parentNote.type === 'search') { return { @@ -31,7 +41,7 @@ function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: str noteId: noteId, parentNoteId: parentNoteId, prefix: prefix, - isExpanded: 0 + isExpanded: false }).save(); log.info(`Cloned note '${noteId}' to a new parent note '${parentNoteId}' with prefix '${prefix}'`); @@ -43,7 +53,7 @@ function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: str }; } -function cloneNoteToBranch(noteId: string, parentBranchId: string, prefix: string) { +function cloneNoteToBranch(noteId: string, parentBranchId: string, prefix?: string) { const parentBranch = becca.getBranch(parentBranchId); if (!parentBranch) { @@ -67,6 +77,9 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi const parentNote = becca.getNote(parentNoteId); + if (!parentNote) { + return { branch: null, success: false, message: "Can't find parent note." }; + } if (parentNote.type === 'search') { return { branch: null, success: false, message: "Can't clone into a search note" }; } @@ -81,7 +94,7 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi noteId: noteId, parentNoteId: parentNoteId, prefix: prefix, - isExpanded: 0 + isExpanded: false }).save(); log.info(`Ensured note '${noteId}' is in parent note '${parentNoteId}' with prefix '${branch.prefix}'`); @@ -90,7 +103,7 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi } function ensureNoteIsAbsentFromParent(noteId: string, parentNoteId: string) { - const branchId = sql.getValue(`SELECT branchId FROM branches WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0`, [noteId, parentNoteId]); + const branchId = sql.getValue(`SELECT branchId FROM branches WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0`, [noteId, parentNoteId]); const branch = becca.getBranch(branchId); if (branch) { @@ -137,13 +150,13 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) { if (!(noteId in becca.notes)) { return { success: false, message: `Note to be cloned '${noteId}' is deleted or does not exist.` }; - } else if (!(afterNote.parentNoteId in becca.notes)) { - return { success: false, message: `After note '${afterNote.parentNoteId}' is deleted or does not exist.` }; + } else if (!afterNote || !(afterNote.parentNoteId in becca.notes)) { + return { success: false, message: `After note '${afterNote?.parentNoteId}' is deleted or does not exist.` }; } const parentNote = becca.getNote(afterNote.parentNoteId); - if (parentNote.type === 'search') { + if (!parentNote || parentNote.type === 'search') { return { success: false, message: "Can't clone into a search note" @@ -167,7 +180,7 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) { noteId: noteId, parentNoteId: afterNote.parentNoteId, notePosition: afterNote.notePosition + 10, - isExpanded: 0 + isExpanded: false }).save(); log.info(`Cloned note '${noteId}' into parent note '${afterNote.parentNoteId}' after note '${afterNote.noteId}', branch '${afterBranchId}'`); @@ -175,7 +188,7 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) { return { success: true, branchId: branch.branchId }; } -export = { +export default { cloneNoteToBranch, cloneNoteToParentNote, ensureNoteIsPresentInParent, diff --git a/src/services/cls.ts b/src/services/cls.ts index d119c8a93..dbc527f4d 100644 --- a/src/services/cls.ts +++ b/src/services/cls.ts @@ -1,5 +1,5 @@ -import clsHooked = require('cls-hooked'); -import { EntityChange } from './entity_changes_interface'; +import clsHooked from "cls-hooked"; +import { EntityChange } from './entity_changes_interface.js'; const namespace = clsHooked.createNamespace("trilium"); type Callback = (...args: any[]) => any; @@ -96,7 +96,7 @@ function ignoreEntityChangeIds() { namespace.set('ignoreEntityChangeIds', true); } -export = { +export default { init, wrap, get, diff --git a/src/services/config.ts b/src/services/config.ts index f0437a2d1..a5469efb5 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -1,10 +1,10 @@ "use strict"; -import ini = require('ini'); -import fs = require('fs'); -import dataDir = require('./data_dir'); -import path = require('path'); -import resourceDir = require('./resource_dir'); +import ini from "ini"; +import fs from "fs"; +import dataDir from "./data_dir.js"; +import path from "path"; +import resourceDir from "./resource_dir.js"; const configSampleFilePath = path.resolve(resourceDir.RESOURCE_DIR, "config-sample.ini"); @@ -16,4 +16,4 @@ if (!fs.existsSync(dataDir.CONFIG_INI_PATH)) { const config = ini.parse(fs.readFileSync(dataDir.CONFIG_INI_PATH, 'utf-8')); -export = config; +export default config; diff --git a/src/services/consistency_checks.ts b/src/services/consistency_checks.ts index 1ec432883..b2bb50a6a 100644 --- a/src/services/consistency_checks.ts +++ b/src/services/consistency_checks.ts @@ -1,21 +1,22 @@ "use strict"; -import sql = require('./sql'); -import sqlInit = require('./sql_init'); -import log = require('./log'); -import ws = require('./ws'); -import syncMutexService = require('./sync_mutex'); -import cls = require('./cls'); -import entityChangesService = require('./entity_changes'); -import optionsService = require('./options'); -import BBranch = require('../becca/entities/bbranch'); -import becca = require('../becca/becca'); -import utils = require('../services/utils'); -import eraseService = require('../services/erase'); -import sanitizeAttributeName = require('./sanitize_attribute_name'); -import noteTypesService = require('../services/note_types'); -import { BranchRow } from '../becca/entities/rows'; -import { EntityChange } from './entity_changes_interface'; +import sql from "./sql.js"; +import sqlInit from "./sql_init.js"; +import log from "./log.js"; +import ws from "./ws.js"; +import syncMutexService from "./sync_mutex.js"; +import cls from "./cls.js"; +import entityChangesService from "./entity_changes.js"; +import optionsService from "./options.js"; +import BBranch from "../becca/entities/bbranch.js"; +import becca from "../becca/becca.js"; +import utils from "../services/utils.js"; +import eraseService from "../services/erase.js"; +import sanitizeAttributeName from "./sanitize_attribute_name.js"; +import noteTypesService from "../services/note_types.js"; +import { BranchRow } from '../becca/entities/rows.js'; +import { EntityChange } from './entity_changes_interface.js'; +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; @@ -913,7 +914,7 @@ sqlInit.dbReady.then(() => { setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000); }); -export = { +export default { runOnDemandChecks, runEntityChangesChecks }; diff --git a/src/services/content_hash.ts b/src/services/content_hash.ts index 2067e177f..4e5ffc568 100644 --- a/src/services/content_hash.ts +++ b/src/services/content_hash.ts @@ -1,9 +1,9 @@ "use strict"; -import sql = require('./sql'); -import utils = require('./utils'); -import log = require('./log'); -import eraseService = require('./erase'); +import sql from "./sql.js"; +import utils from "./utils.js"; +import log from "./log.js"; +import eraseService from "./erase.js"; type SectorHash = Record; @@ -80,7 +80,7 @@ function checkContentHashes(otherHashes: Record) { return failedChecks; } -export = { +export default { getEntityHashes, checkContentHashes }; diff --git a/src/services/data_dir.ts b/src/services/data_dir.ts index 1b267850a..7009b918f 100644 --- a/src/services/data_dir.ts +++ b/src/services/data_dir.ts @@ -8,9 +8,9 @@ * - as a fallback if the previous step fails, we'll use home dir */ -import os = require('os'); -import fs = require('fs'); -import path = require('path'); +import os from "os"; +import fs from "fs"; +import path from "path"; function getAppDataDir() { let appDataDir = os.homedir(); // fallback if OS is not recognized @@ -68,7 +68,7 @@ const LOG_DIR = process.env.TRILIUM_LOG_DIR || `${DIR_SEP}log`; const ANONYMIZED_DB_DIR = process.env.TRILIUM_ANONYMIZED_DB_DIR || `${DIR_SEP}anonymized-db`; const CONFIG_INI_PATH = process.env.TRILIUM_CONFIG_INI_PATH || `${DIR_SEP}config.ini`; -export = { +export default { TRILIUM_DATA_DIR, DOCUMENT_PATH, BACKUP_DIR, diff --git a/src/services/date_notes.ts b/src/services/date_notes.ts index 989106939..465757328 100644 --- a/src/services/date_notes.ts +++ b/src/services/date_notes.ts @@ -1,14 +1,14 @@ "use strict"; -import noteService = require('./notes'); -import attributeService = require('./attributes'); -import dateUtils = require('./date_utils'); -import sql = require('./sql'); -import protectedSessionService = require('./protected_session'); -import searchService = require('../services/search/services/search'); -import SearchContext = require('../services/search/search_context'); -import hoistedNoteService = require('./hoisted_note'); -import BNote = require('../becca/entities/bnote'); +import noteService from "./notes.js"; +import attributeService from "./attributes.js"; +import dateUtils from "./date_utils.js"; +import sql from "./sql.js"; +import protectedSessionService from "./protected_session.js"; +import searchService from "../services/search/services/search.js"; +import SearchContext from "../services/search/search_context.js"; +import hoistedNoteService from "./hoisted_note.js"; +import BNote from "../becca/entities/bnote.js"; const CALENDAR_ROOT_LABEL = 'calendarRoot'; const YEAR_LABEL = 'yearNote'; @@ -226,7 +226,7 @@ function getWeekNote(dateStr: string, options: WeekNoteOpts = {}, rootNote: BNot return getDayNote(dateStr, rootNote); } -export = { +export default { getRootCalendarNote, getYearNote, getMonthNote, diff --git a/src/services/date_utils.ts b/src/services/date_utils.ts index 88b6ecb69..7c882e55e 100644 --- a/src/services/date_utils.ts +++ b/src/services/date_utils.ts @@ -1,5 +1,5 @@ -import dayjs = require('dayjs'); -import cls = require('./cls'); +import dayjs from "dayjs"; +import cls from "./cls.js"; const LOCAL_DATETIME_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSSZZ'; const UTC_DATETIME_FORMAT = 'YYYY-MM-DD HH:mm:ssZ'; @@ -95,7 +95,7 @@ function validateUtcDateTime(str: string | undefined) { } } -export = { +export default { utcNowDateTime, localNowDateTime, localNowDate, diff --git a/src/services/encryption/data_encryption.ts b/src/services/encryption/data_encryption.ts index b82a0e8c6..2088db6bf 100644 --- a/src/services/encryption/data_encryption.ts +++ b/src/services/encryption/data_encryption.ts @@ -1,7 +1,7 @@ "use strict"; -import crypto = require('crypto'); -import log = require('../log'); +import crypto from "crypto"; +import log from "../log.js"; function arraysIdentical(a: any[] | Buffer, b: any[] | Buffer) { let i = a.length; @@ -112,7 +112,7 @@ function decryptString(dataKey: Buffer, cipherText: string) { return buffer.toString('utf-8'); } -export = { +export default { encrypt, decrypt, decryptString diff --git a/src/services/encryption/my_scrypt.ts b/src/services/encryption/my_scrypt.ts index c80632bc0..658f4f230 100644 --- a/src/services/encryption/my_scrypt.ts +++ b/src/services/encryption/my_scrypt.ts @@ -1,7 +1,7 @@ "use strict"; -import optionService = require('../options'); -import crypto = require('crypto'); +import optionService from "../options.js"; +import crypto from "crypto"; function getVerificationHash(password: crypto.BinaryLike) { const salt = optionService.getOption('passwordVerificationSalt'); @@ -22,7 +22,7 @@ function getScryptHash(password: crypto.BinaryLike, salt: crypto.BinaryLike) { return hashed; } -export = { +export default { getVerificationHash, getPasswordDerivedKey }; diff --git a/src/services/encryption/password.ts b/src/services/encryption/password.ts index 4d6bf66a3..89ed7add8 100644 --- a/src/services/encryption/password.ts +++ b/src/services/encryption/password.ts @@ -1,10 +1,10 @@ "use strict"; -import sql = require('../sql'); -import optionService = require('../options'); -import myScryptService = require('./my_scrypt'); -import utils = require('../utils'); -import passwordEncryptionService = require('./password_encryption'); +import sql from "../sql.js"; +import optionService from "../options.js"; +import myScryptService from "./my_scrypt.js"; +import utils from "../utils.js"; +import passwordEncryptionService from "./password_encryption.js"; function isPasswordSet() { return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'"); @@ -78,7 +78,7 @@ function resetPassword() { }; } -export = { +export default { isPasswordSet, changePassword, setPassword, diff --git a/src/services/encryption/password_encryption.ts b/src/services/encryption/password_encryption.ts index 36420d03d..de4277d58 100644 --- a/src/services/encryption/password_encryption.ts +++ b/src/services/encryption/password_encryption.ts @@ -1,7 +1,7 @@ -import optionService = require('../options'); -import myScryptService = require('./my_scrypt'); -import utils = require('../utils'); -import dataEncryptionService = require('./data_encryption'); +import optionService from "../options.js"; +import myScryptService from "./my_scrypt.js"; +import utils from "../utils.js"; +import dataEncryptionService from "./data_encryption.js"; function verifyPassword(password: string) { const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password)); @@ -33,7 +33,7 @@ function getDataKey(password: string) { return decryptedDataKey; } -export = { +export default { verifyPassword, getDataKey, setDataKey diff --git a/src/services/entity_changes.ts b/src/services/entity_changes.ts index 91f84f834..8937b49cd 100644 --- a/src/services/entity_changes.ts +++ b/src/services/entity_changes.ts @@ -1,13 +1,14 @@ -import sql = require('./sql'); -import dateUtils = require('./date_utils'); -import log = require('./log'); -import cls = require('./cls'); -import utils = require('./utils'); -import instanceId = require('./instance_id'); -import becca = require('../becca/becca'); -import blobService = require('../services/blob'); -import { EntityChange } from './entity_changes_interface'; -import type { Blob } from "./blob-interface"; +import sql from "./sql.js"; +import dateUtils from "./date_utils.js"; +import log from "./log.js"; +import cls from "./cls.js"; +import utils from "./utils.js"; +import instanceId from "./instance_id.js"; +import becca from "../becca/becca.js"; +import blobService from "../services/blob.js"; +import { EntityChange } from './entity_changes_interface.js'; +import type { Blob } from "./blob-interface.js"; +import eventService from "./events.js"; let maxEntityChangeId = 0; @@ -57,8 +58,6 @@ function putNoteReorderingEntityChange(parentNoteId: string, componentId?: strin instanceId }); - const eventService = require('./events'); - eventService.emit(eventService.ENTITY_CHANGED, { entityName: 'note_reordering', entity: sql.getMap(`SELECT branchId, notePosition FROM branches WHERE isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]) @@ -193,7 +192,7 @@ function recalculateMaxEntityChangeId() { maxEntityChangeId = sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes"); } -export = { +export default { putNoteReorderingEntityChange, putEntityChangeForOtherInstances, putEntityChangeWithForcedChange, diff --git a/src/services/env.ts b/src/services/env.ts index 23c94ee0f..28f39fea6 100644 --- a/src/services/env.ts +++ b/src/services/env.ts @@ -2,6 +2,6 @@ function isDev() { return !!(process.env.TRILIUM_ENV && process.env.TRILIUM_ENV === 'dev'); } -export = { +export default { isDev }; \ No newline at end of file diff --git a/src/services/erase.ts b/src/services/erase.ts index 6e6804f3d..f02595de8 100644 --- a/src/services/erase.ts +++ b/src/services/erase.ts @@ -1,12 +1,11 @@ -import sql = require("./sql"); -import revisionService = require("./revisions"); -import log = require("./log"); -import entityChangesService = require("./entity_changes"); -import optionService = require("./options"); -import dateUtils = require("./date_utils"); -import sqlInit = require("./sql_init"); -import cls = require("./cls"); -import { EntityChange } from "./entity_changes_interface"; +import sql from "./sql.js"; +import log from "./log.js"; +import entityChangesService from "./entity_changes.js"; +import optionService from "./options.js"; +import dateUtils from "./date_utils.js"; +import sqlInit from "./sql_init.js"; +import cls from "./cls.js"; +import { EntityChange } from "./entity_changes_interface.js"; function eraseNotes(noteIdsToErase: string[]) { if (noteIdsToErase.length === 0) { @@ -177,20 +176,22 @@ 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); +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); + }); +} - setInterval(cls.wrap(() => eraseDeletedEntities()), 4 * 3600 * 1000); - setInterval(cls.wrap(() => eraseScheduledAttachments()), 3600 * 1000); -}); - -export = { +export default { eraseDeletedNotesNow, eraseUnusedAttachmentsNow, eraseNotesWithDeleteId, eraseUnusedBlobs, eraseAttachments, - eraseRevisions + eraseRevisions, }; diff --git a/src/services/etapi_tokens.ts b/src/services/etapi_tokens.ts index 2989d3923..7f8d1cd2f 100644 --- a/src/services/etapi_tokens.ts +++ b/src/services/etapi_tokens.ts @@ -1,7 +1,7 @@ -import becca = require('../becca/becca'); -import utils = require('./utils'); -import BEtapiToken = require('../becca/entities/betapi_token'); -import crypto = require("crypto"); +import becca from "../becca/becca.js"; +import utils from "./utils.js"; +import BEtapiToken from "../becca/entities/betapi_token.js"; +import crypto from "crypto"; function getTokens() { return becca.getEtapiTokens(); @@ -114,7 +114,7 @@ function deleteToken(etapiTokenId: string) { etapiToken.markAsDeletedSimple(); } -export = { +export default { getTokens, createToken, renameToken, diff --git a/src/services/events.ts b/src/services/events.ts index 0eda326b9..1a7ed9eb8 100644 --- a/src/services/events.ts +++ b/src/services/events.ts @@ -1,4 +1,4 @@ -const log = require('./log'); +import log from "./log.js"; const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED"; const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION"; @@ -59,7 +59,7 @@ function emit(eventType: string, data?: any) { } } -export = { +export default { subscribe, subscribeBeccaLoader, emit, diff --git a/src/services/export/md.ts b/src/services/export/md.ts index 3e6754c1c..84af6f56f 100644 --- a/src/services/export/md.ts +++ b/src/services/export/md.ts @@ -1,7 +1,7 @@ "use strict"; -import TurndownService = require('turndown'); -import turndownPluginGfm = require('joplin-turndown-plugin-gfm'); +import TurndownService from "turndown"; +import turndownPluginGfm from "joplin-turndown-plugin-gfm"; let instance: TurndownService | null = null; @@ -14,6 +14,6 @@ function toMarkdown(content: string) { return instance.turndown(content); } -export = { +export default { toMarkdown }; diff --git a/src/services/export/opml.ts b/src/services/export/opml.ts index 63bdf14fd..c67e1378c 100644 --- a/src/services/export/opml.ts +++ b/src/services/export/opml.ts @@ -1,9 +1,9 @@ "use strict"; -import utils = require('../utils'); -import becca = require('../../becca/becca'); -import TaskContext = require('../task_context'); -import BBranch = require('../../becca/entities/bbranch'); +import utils from "../utils.js"; +import becca from "../../becca/becca.js"; +import TaskContext from "../task_context.js"; +import BBranch from "../../becca/entities/bbranch.js"; import { Response } from 'express'; function exportToOpml(taskContext: TaskContext, branch: BBranch, version: string, res: Response) { @@ -98,6 +98,6 @@ function escapeXmlAttribute(text: string) { .replace(/'/g, '''); } -export = { +export default { exportToOpml }; diff --git a/src/services/export/single.ts b/src/services/export/single.ts index b0f46e6e8..5e68de203 100644 --- a/src/services/export/single.ts +++ b/src/services/export/single.ts @@ -1,12 +1,12 @@ "use strict"; -import mimeTypes = require('mime-types'); -import html = require('html'); -import utils = require('../utils'); -import mdService = require('./md'); -import becca = require('../../becca/becca'); -import TaskContext = require('../task_context'); -import BBranch = require('../../becca/entities/bbranch'); +import mimeTypes from "mime-types"; +import html from "html"; +import utils from "../utils.js"; +import mdService from "./md.js"; +import becca from "../../becca/becca.js"; +import TaskContext from "../task_context.js"; +import BBranch from "../../becca/entities/bbranch.js"; import { Response } from 'express'; function exportSingleNote(taskContext: TaskContext, branch: BBranch, format: "html" | "markdown", res: Response) { @@ -125,6 +125,6 @@ function inlineAttachments(content: string) { return content; } -export = { +export default { exportSingleNote }; diff --git a/src/services/export/zip.ts b/src/services/export/zip.ts index b4093c848..c98c226c8 100644 --- a/src/services/export/zip.ts +++ b/src/services/export/zip.ts @@ -1,26 +1,26 @@ "use strict"; -import html = require('html'); -import dateUtils = require('../date_utils'); -import path = require('path'); -import mimeTypes = require('mime-types'); -import mdService = require('./md'); -import packageInfo = require('../../../package.json'); -import utils = require('../utils'); -import protectedSessionService = require('../protected_session'); -import sanitize = require("sanitize-filename"); -import fs = require("fs"); -import becca = require('../../becca/becca'); -const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; -import archiver = require('archiver'); -import log = require('../log'); -import TaskContext = require('../task_context'); -import ValidationError = require('../../errors/validation_error'); -import NoteMeta = require('../meta/note_meta'); -import AttachmentMeta = require('../meta/attachment_meta'); -import AttributeMeta = require('../meta/attribute_meta'); -import BBranch = require('../../becca/entities/bbranch'); +import html from "html"; +import dateUtils from "../date_utils.js"; +import path from "path"; +import mimeTypes from "mime-types"; +import mdService from "./md.js"; +import packageInfo from "../../../package.json" with { type: "json" }; +import utils from "../utils.js"; +import protectedSessionService from "../protected_session.js"; +import sanitize from "sanitize-filename"; +import fs from "fs"; +import becca from "../../becca/becca.js"; +import archiver from "archiver"; +import log from "../log.js"; +import TaskContext from "../task_context.js"; +import ValidationError from "../../errors/validation_error.js"; +import NoteMeta from "../meta/note_meta.js"; +import AttachmentMeta from "../meta/attachment_meta.js"; +import AttributeMeta from "../meta/attribute_meta.js"; +import BBranch from "../../becca/entities/bbranch.js"; import { Response } from 'express'; +import { RESOURCE_DIR } from "../resource_dir.js"; async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "html" | "markdown", res: Response | fs.WriteStream, setHeaders = true) { if (!['html', 'markdown'].includes(format)) { @@ -582,7 +582,7 @@ async function exportToZipFile(noteId: string, format: "markdown" | "html", zipF log.info(`Exported '${noteId}' with format '${format}' to '${zipFilePath}'`); } -export = { +export default { exportToZip, exportToZipFile }; diff --git a/src/services/handlers.ts b/src/services/handlers.ts index 9e10b778a..579924923 100644 --- a/src/services/handlers.ts +++ b/src/services/handlers.ts @@ -1,14 +1,14 @@ -import eventService = require('./events'); -import scriptService = require('./script'); -import treeService = require('./tree'); -import noteService = require('./notes'); -import becca = require('../becca/becca'); -import BAttribute = require('../becca/entities/battribute'); -import hiddenSubtreeService = require('./hidden_subtree'); -import oneTimeTimer = require('./one_time_timer'); -import BNote = require('../becca/entities/bnote'); -import AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity'); -import { DefinitionObject } from './promoted_attribute_definition_interface'; +import eventService from "./events.js"; +import scriptService from "./script.js"; +import treeService from "./tree.js"; +import noteService from "./notes.js"; +import becca from "../becca/becca.js"; +import BAttribute from "../becca/entities/battribute.js"; +import hiddenSubtreeService from "./hidden_subtree.js"; +import oneTimeTimer from "./one_time_timer.js"; +import BNote from "../becca/entities/bnote.js"; +import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; +import { DefinitionObject } from './promoted_attribute_definition_interface.js'; type Handler = (definition: DefinitionObject, note: BNote, targetNote: BNote) => void; @@ -249,6 +249,6 @@ eventService.subscribe(eventService.ENTITY_DELETED, ({ entityName, entity }) => } }); -export = { +export default { runAttachedRelations }; diff --git a/src/services/hidden_subtree.ts b/src/services/hidden_subtree.ts index 5478aed1c..563da456f 100644 --- a/src/services/hidden_subtree.ts +++ b/src/services/hidden_subtree.ts @@ -1,10 +1,10 @@ -import BAttribute = require("../becca/entities/battribute"); -import { AttributeType, NoteType } from "../becca/entities/rows"; +import BAttribute from "../becca/entities/battribute.js"; +import { AttributeType, NoteType } from "../becca/entities/rows.js"; -import becca = require('../becca/becca'); -import noteService = require('./notes'); -import log = require('./log'); -import migrationService = require('./migration'); +import becca from "../becca/becca.js"; +import noteService from "./notes.js"; +import log from "./log.js"; +import migrationService from "./migration.js"; const LBTPL_ROOT = "_lbTplRoot"; const LBTPL_BASE = "_lbTplBase"; @@ -362,7 +362,7 @@ function checkHiddenSubtreeRecursively(parentNoteId: string, item: Item) { } } -export = { +export default { checkHiddenSubtree, LBTPL_ROOT, LBTPL_BASE, diff --git a/src/services/hoisted_note.ts b/src/services/hoisted_note.ts index fca423269..798889c46 100644 --- a/src/services/hoisted_note.ts +++ b/src/services/hoisted_note.ts @@ -1,5 +1,5 @@ -import cls = require('./cls'); -import becca = require('../becca/becca'); +import cls from "./cls.js"; +import becca from "../becca/becca.js"; function getHoistedNoteId() { return cls.getHoistedNoteId(); @@ -33,7 +33,7 @@ function getWorkspaceNote() { } } -export = { +export default { getHoistedNoteId, getWorkspaceNote, isHoistedInHiddenSubtree diff --git a/src/services/host.ts b/src/services/host.ts index 3daef1504..d8a394e6d 100644 --- a/src/services/host.ts +++ b/src/services/host.ts @@ -1,3 +1,3 @@ -import config = require('./config'); +import config from "./config.js"; -export = process.env.TRILIUM_HOST || config['Network']['host'] || '0.0.0.0'; +export default process.env.TRILIUM_HOST || config['Network']['host'] || '0.0.0.0'; diff --git a/src/services/html_sanitizer.ts b/src/services/html_sanitizer.ts index 8e82edd3c..ec76883b8 100644 --- a/src/services/html_sanitizer.ts +++ b/src/services/html_sanitizer.ts @@ -1,5 +1,5 @@ -import sanitizeHtml = require('sanitize-html'); -import sanitizeUrl = require('@braintree/sanitize-url'); +import sanitizeHtml from "sanitize-html"; +import sanitizeUrl from "@braintree/sanitize-url"; // intended mainly as protection against XSS via import // secondarily, it (partly) protects against "CSS takeover" @@ -47,7 +47,7 @@ function sanitize(dirtyHtml: string) { }); } -export = { +export default { sanitize, sanitizeUrl: (url: string) => { return sanitizeUrl.sanitizeUrl(url).trim(); diff --git a/src/services/image.ts b/src/services/image.ts index 0a95b87d6..5bef79ac9 100644 --- a/src/services/image.ts +++ b/src/services/image.ts @@ -1,17 +1,17 @@ "use strict"; -import becca = require('../becca/becca'); -import log = require('./log'); -import protectedSessionService = require('./protected_session'); -import noteService = require('./notes'); -import optionService = require('./options'); -import sql = require('./sql'); -import jimp = require('jimp'); -import imageType = require('image-type'); -import sanitizeFilename = require('sanitize-filename'); -import isSvg = require('is-svg'); -import isAnimated = require('is-animated'); -import htmlSanitizer = require('./html_sanitizer'); +import becca from "../becca/becca.js"; +import log from "./log.js"; +import protectedSessionService from "./protected_session.js"; +import noteService from "./notes.js"; +import optionService from "./options.js"; +import sql from "./sql.js"; +import jimp from "jimp"; +import imageType from "image-type"; +import sanitizeFilename from "sanitize-filename"; +import isSvg from "is-svg"; +import isAnimated from "is-animated"; +import htmlSanitizer from "./html_sanitizer.js"; async function processImage(uploadBuffer: Buffer, originalName: string, shrinkImageSwitch: boolean) { const compressImages = optionService.getOptionBool("compressImages"); @@ -156,7 +156,6 @@ function saveImageToAttachment(noteId: string, uploadBuffer: Buffer, originalNam setTimeout(() => { sql.transactional(() => { const note = becca.getNoteOrThrow(noteId); - const noteService = require('../services/notes'); noteService.asyncPostProcessContent(note, note.getContent()); // to mark an unused attachment for deletion }); }, 5000); @@ -234,7 +233,7 @@ async function resize(buffer: Buffer, quality: number) { return resultBuffer; } -export = { +export default { saveImage, saveImageToAttachment, updateImage diff --git a/src/services/import/enex.ts b/src/services/import/enex.ts index 5e715a0ca..b6aa42072 100644 --- a/src/services/import/enex.ts +++ b/src/services/import/enex.ts @@ -1,17 +1,18 @@ -import sax = require("sax"); -import stream = require('stream'); +import sax from "sax"; +import stream from "stream"; import { Throttle } from 'stream-throttle'; -import log = require('../log'); -import utils = require('../utils'); -import sql = require('../sql'); -import noteService = require('../notes'); -import imageService = require('../image'); -import protectedSessionService = require('../protected_session'); -import htmlSanitizer = require('../html_sanitizer'); -import sanitizeAttributeName = require('../sanitize_attribute_name'); -import TaskContext = require("../task_context"); -import BNote = require("../../becca/entities/bnote"); -import { File } from "./common"; +import log from "../log.js"; +import utils from "../utils.js"; +import sql from "../sql.js"; +import noteService from "../notes.js"; +import imageService from "../image.js"; +import protectedSessionService from "../protected_session.js"; +import htmlSanitizer from "../html_sanitizer.js"; +import sanitizeAttributeName from "../sanitize_attribute_name.js"; +import TaskContext from "../task_context.js"; +import BNote from "../../becca/entities/bnote.js"; +import { File } from "./common.js"; +import { AttributeType } from "../../becca/entities/rows.js"; /** * date format is e.g. 20181121T193703Z or 2013-04-14T16:19:00.000Z (Mac evernote, see #3496) @@ -29,7 +30,7 @@ function parseDate(text: string) { } interface Attribute { - type: string; + type: AttributeType; name: string; value: string; } @@ -409,4 +410,4 @@ function importEnex(taskContext: TaskContext, file: File, parentNote: BNote): Pr }); } -export = { importEnex }; +export default { importEnex }; diff --git a/src/services/import/markdown.ts b/src/services/import/markdown.ts index 941bdbd31..e3b4d6aa2 100644 --- a/src/services/import/markdown.ts +++ b/src/services/import/markdown.ts @@ -1,17 +1,17 @@ "use strict"; -import marked = require("marked"); -import htmlSanitizer = require('../html_sanitizer'); -import importUtils = require('./utils'); +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 return htmlSanitizer.sanitize(h1Handled); } -export = { +export default { renderToHtml }; diff --git a/src/services/import/mime.ts b/src/services/import/mime.ts index dd4c96244..8b8316a59 100644 --- a/src/services/import/mime.ts +++ b/src/services/import/mime.ts @@ -1,8 +1,8 @@ "use strict"; -import mimeTypes = require('mime-types'); -import path = require('path'); -import { TaskData } from '../task_context_interface'; +import mimeTypes from "mime-types"; +import path from "path"; +import { TaskData } from '../task_context_interface.js'; const CODE_MIME_TYPES: Record = { 'text/plain': true, @@ -110,7 +110,7 @@ function normalizeMimeType(mime: string) { return undefined; } -export = { +export default { getMime, getType, normalizeMimeType diff --git a/src/services/import/opml.ts b/src/services/import/opml.ts index 78da6764c..32a633746 100644 --- a/src/services/import/opml.ts +++ b/src/services/import/opml.ts @@ -1,11 +1,11 @@ "use strict"; -import noteService = require('../../services/notes'); -import xml2js = require("xml2js"); -import protectedSessionService = require('../protected_session'); -import htmlSanitizer = require('../html_sanitizer'); -import TaskContext = require('../task_context'); -import BNote = require('../../becca/entities/bnote'); +import noteService from "../../services/notes.js"; +import xml2js from "xml2js"; +import protectedSessionService from "../protected_session.js"; +import htmlSanitizer from "../html_sanitizer.js"; +import TaskContext from "../task_context.js"; +import BNote from "../../becca/entities/bnote.js"; const parseString = xml2js.parseString; interface OpmlXml { @@ -108,6 +108,6 @@ function toHtml(text: string) { return `

${text.replace(/(?:\r\n|\r|\n)/g, '

')}

`; } -export = { +export default { importOpml }; diff --git a/src/services/import/single.ts b/src/services/import/single.ts index 2c13386a1..465d3b7a8 100644 --- a/src/services/import/single.ts +++ b/src/services/import/single.ts @@ -1,17 +1,17 @@ "use strict"; -import BNote = require("../../becca/entities/bnote"); -import TaskContext = require("../task_context"); +import BNote from "../../becca/entities/bnote.js"; +import TaskContext from "../task_context.js"; -import noteService = require('../../services/notes'); -import imageService = require('../../services/image'); -import protectedSessionService = require('../protected_session'); -import markdownService = require('./markdown'); -import mimeService = require('./mime'); -import utils = require('../../services/utils'); -import importUtils = require('./utils'); -import htmlSanitizer = require('../html_sanitizer'); -import { File } from "./common"; +import noteService from "../../services/notes.js"; +import imageService from "../../services/image.js"; +import protectedSessionService from "../protected_session.js"; +import markdownService from "./markdown.js"; +import mimeService from "./mime.js"; +import utils from "../../services/utils.js"; +import importUtils from "./utils.js"; +import htmlSanitizer from "../html_sanitizer.js"; +import { File } from "./common.js"; function importSingleFile(taskContext: TaskContext, file: File, parentNote: BNote) { const mime = mimeService.getMime(file.originalname) || file.mimetype; @@ -191,7 +191,7 @@ function importAttachment(taskContext: TaskContext, file: File, parentNote: BNot } } -export = { +export default { importSingleFile, importAttachment }; diff --git a/src/services/import/utils.ts b/src/services/import/utils.ts index 8b06f2167..b85700230 100644 --- a/src/services/import/utils.ts +++ b/src/services/import/utils.ts @@ -11,6 +11,6 @@ function handleH1(content: string, title: string) { return content; } -export = { +export default { handleH1 }; diff --git a/src/services/import/zip.ts b/src/services/import/zip.ts index 0c4008ddf..58aa8e994 100644 --- a/src/services/import/zip.ts +++ b/src/services/import/zip.ts @@ -1,26 +1,26 @@ "use strict"; -import BAttribute = require('../../becca/entities/battribute'); -import utils = require('../../services/utils'); -import log = require('../../services/log'); -import noteService = require('../../services/notes'); -import attributeService = require('../../services/attributes'); -import BBranch = require('../../becca/entities/bbranch'); -import path = require('path'); -import protectedSessionService = require('../protected_session'); -import mimeService = require('./mime'); -import treeService = require('../tree'); -import yauzl = require("yauzl"); -import htmlSanitizer = require('../html_sanitizer'); -import becca = require('../../becca/becca'); -import BAttachment = require('../../becca/entities/battachment'); -import markdownService = require('./markdown'); -import TaskContext = require('../task_context'); -import BNote = require('../../becca/entities/bnote'); -import NoteMeta = require('../meta/note_meta'); -import AttributeMeta = require('../meta/attribute_meta'); +import BAttribute from "../../becca/entities/battribute.js"; +import utils from "../../services/utils.js"; +import log from "../../services/log.js"; +import noteService from "../../services/notes.js"; +import attributeService from "../../services/attributes.js"; +import BBranch from "../../becca/entities/bbranch.js"; +import path from "path"; +import protectedSessionService from "../protected_session.js"; +import mimeService from "./mime.js"; +import treeService from "../tree.js"; +import yauzl from "yauzl"; +import htmlSanitizer from "../html_sanitizer.js"; +import becca from "../../becca/becca.js"; +import BAttachment from "../../becca/entities/battachment.js"; +import markdownService from "./markdown.js"; +import TaskContext from "../task_context.js"; +import BNote from "../../becca/entities/bnote.js"; +import NoteMeta from "../meta/note_meta.js"; +import AttributeMeta from "../meta/attribute_meta.js"; import { Stream } from 'stream'; -import { ALLOWED_NOTE_TYPES, NoteType } from '../../becca/entities/rows'; +import { ALLOWED_NOTE_TYPES, NoteType } from '../../becca/entities/rows.js'; interface MetaFile { files: NoteMeta[] @@ -656,6 +656,6 @@ function resolveNoteType(type: string | undefined): NoteType { } } -export = { +export default { importZip }; diff --git a/src/services/instance_id.ts b/src/services/instance_id.ts index 6e0eb503c..047325e6c 100644 --- a/src/services/instance_id.ts +++ b/src/services/instance_id.ts @@ -1,5 +1,5 @@ -import utils = require('./utils'); +import utils from "./utils.js"; const instanceId = utils.randomString(12); -export = instanceId; +export default instanceId; diff --git a/src/services/keyboard_actions.ts b/src/services/keyboard_actions.ts index 715c62684..e2e1e024a 100644 --- a/src/services/keyboard_actions.ts +++ b/src/services/keyboard_actions.ts @@ -1,9 +1,9 @@ "use strict"; -import optionService = require('./options'); -import log = require('./log'); -import utils = require('./utils'); -import { KeyboardShortcut } from './keyboard_actions_interface'; +import optionService from "./options.js"; +import log from "./log.js"; +import utils from "./utils.js"; +import { KeyboardShortcut } from './keyboard_actions_interface.js'; const isMac = process.platform === "darwin"; const isElectron = utils.isElectron(); @@ -637,7 +637,7 @@ function getKeyboardActions() { return actions; } -export = { +export default { DEFAULT_KEYBOARD_ACTIONS, getKeyboardActions }; diff --git a/src/services/log.ts b/src/services/log.ts index 1e8d0b9e1..9bd97a2a7 100644 --- a/src/services/log.ts +++ b/src/services/log.ts @@ -1,9 +1,9 @@ "use strict"; import { Request, Response } from "express"; -import fs = require("fs"); -import dataDir = require('./data_dir'); -import cls = require('./cls'); +import fs from "fs"; +import dataDir from "./data_dir.js"; +import cls from "./cls.js"; if (!fs.existsSync(dataDir.LOG_DIR)) { fs.mkdirSync(dataDir.LOG_DIR, 0o700); @@ -50,7 +50,7 @@ function checkDate(millisSinceMidnight: number) { return millisSinceMidnight; } -function log(str: string) { +function log(str: string | Error) { const bundleNoteId = cls.get("bundleNoteId"); if (bundleNoteId) { @@ -66,11 +66,11 @@ function log(str: string) { console.log(str); } -function info(message: string) { +function info(message: string | Error) { log(message); } -function error(message: string) { +function error(message: string | Error) { log(`ERROR: ${message}`); } @@ -117,7 +117,7 @@ function formatDate() { return `${pad(todaysMidnight.getFullYear())}-${pad(todaysMidnight.getMonth() + 1)}-${pad(todaysMidnight.getDate())}`; } -export = { +export default { info, error, request diff --git a/src/services/meta/attachment_meta.ts b/src/services/meta/attachment_meta.ts index 8c237ab21..6fef1989a 100644 --- a/src/services/meta/attachment_meta.ts +++ b/src/services/meta/attachment_meta.ts @@ -7,4 +7,4 @@ interface AttachmentMeta { dataFileName: string; } -export = AttachmentMeta; +export default AttachmentMeta; diff --git a/src/services/meta/attribute_meta.ts b/src/services/meta/attribute_meta.ts index de79df913..648dc1c1d 100644 --- a/src/services/meta/attribute_meta.ts +++ b/src/services/meta/attribute_meta.ts @@ -1,4 +1,4 @@ -import { AttributeType } from "../../becca/entities/rows"; +import { AttributeType } from "../../becca/entities/rows.js"; interface AttributeMeta { noteId?: string; @@ -9,4 +9,4 @@ interface AttributeMeta { position?: number; } -export = AttributeMeta; +export default AttributeMeta; diff --git a/src/services/meta/note_meta.ts b/src/services/meta/note_meta.ts index b3012f29a..a613c4781 100644 --- a/src/services/meta/note_meta.ts +++ b/src/services/meta/note_meta.ts @@ -1,5 +1,5 @@ -import AttachmentMeta = require("./attachment_meta"); -import AttributeMeta = require("./attribute_meta"); +import AttachmentMeta from "./attachment_meta.js"; +import AttributeMeta from "./attribute_meta.js"; interface NoteMeta { noteId?: string; @@ -23,4 +23,4 @@ interface NoteMeta { children?: NoteMeta[]; } -export = NoteMeta; +export default NoteMeta; diff --git a/src/services/migration.ts b/src/services/migration.ts index ca647c539..4355a99a5 100644 --- a/src/services/migration.ts +++ b/src/services/migration.ts @@ -1,11 +1,11 @@ -import backupService = require('./backup'); -import sql = require('./sql'); -import fs = require('fs-extra'); -import log = require('./log'); -import utils = require('./utils'); -import resourceDir = require('./resource_dir'); -import appInfo = require('./app_info'); -import cls = require('./cls'); +import backupService from "./backup.js"; +import sql from "./sql.js"; +import fs from "fs-extra"; +import log from "./log.js"; +import utils from "./utils.js"; +import resourceDir from "./resource_dir.js"; +import appInfo from "./app_info.js"; +import cls from "./cls.js"; interface MigrationInfo { dbVersion: number; @@ -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()) { @@ -143,7 +143,7 @@ async function migrateIfNecessary() { } } -export = { +export default { migrateIfNecessary, isDbUpToDate }; diff --git a/src/services/note-interface.ts b/src/services/note-interface.ts index 2cfa0b86a..194085bdb 100644 --- a/src/services/note-interface.ts +++ b/src/services/note-interface.ts @@ -1,4 +1,4 @@ -import { NoteType } from "../becca/entities/rows"; +import { NoteType } from "../becca/entities/rows.js"; export interface NoteParams { /** optionally can force specific noteId */ diff --git a/src/services/note_types.ts b/src/services/note_types.ts index 54d9d1f44..3828241bd 100644 --- a/src/services/note_types.ts +++ b/src/services/note_types.ts @@ -26,7 +26,7 @@ function getDefaultMimeForNoteType(typeName: string) { return typeRec.defaultMime; } -export = { +export default { getNoteTypeNames: () => noteTypes.map(nt => nt.type), getDefaultMimeForNoteType }; diff --git a/src/services/notes.ts b/src/services/notes.ts index 2e099392e..cee8a8f91 100644 --- a/src/services/notes.ts +++ b/src/services/notes.ts @@ -1,31 +1,32 @@ -import sql = require('./sql'); -import optionService = require('./options'); -import dateUtils = require('./date_utils'); -import entityChangesService = require('./entity_changes'); -import eventService = require('./events'); -import cls = require('../services/cls'); -import protectedSessionService = require('../services/protected_session'); -import log = require('../services/log'); -import utils = require('../services/utils'); -import revisionService = require('./revisions'); -import request = require('./request'); -import path = require('path'); -import url = require('url'); -import becca = require('../becca/becca'); -import BBranch = require('../becca/entities/bbranch'); -import BNote = require('../becca/entities/bnote'); -import BAttribute = require('../becca/entities/battribute'); -import BAttachment = require('../becca/entities/battachment'); -import dayjs = require("dayjs"); -import htmlSanitizer = require('./html_sanitizer'); -import ValidationError = require('../errors/validation_error'); -import noteTypesService = require('./note_types'); -import fs = require("fs"); -import ws = require('./ws'); -import html2plaintext = require('html2plaintext'); -import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from '../becca/entities/rows'; -import TaskContext = require('./task_context'); -import { NoteParams } from './note-interface'; +import sql from "./sql.js"; +import optionService from "./options.js"; +import dateUtils from "./date_utils.js"; +import entityChangesService from "./entity_changes.js"; +import eventService from "./events.js"; +import cls from "../services/cls.js"; +import protectedSessionService from "../services/protected_session.js"; +import log from "../services/log.js"; +import utils from "../services/utils.js"; +import revisionService from "./revisions.js"; +import request from "./request.js"; +import path from "path"; +import url from "url"; +import becca from "../becca/becca.js"; +import BBranch from "../becca/entities/bbranch.js"; +import BNote from "../becca/entities/bnote.js"; +import BAttribute from "../becca/entities/battribute.js"; +import BAttachment from "../becca/entities/battachment.js"; +import dayjs from "dayjs"; +import htmlSanitizer from "./html_sanitizer.js"; +import ValidationError from "../errors/validation_error.js"; +import noteTypesService from "./note_types.js"; +import fs from "fs"; +import ws from "./ws.js"; +import html2plaintext from "html2plaintext"; +import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from '../becca/entities/rows.js'; +import TaskContext from "./task_context.js"; +import { NoteParams } from './note-interface.js'; +import imageService from "./image.js"; interface FoundLink { name: "imageLink" | "internalLink" | "includeNoteLink" | "relationMapLink", @@ -466,7 +467,7 @@ async function downloadImage(noteId: string, imageUrl: string) { const unescapedUrl = utils.unescapeHtml(imageUrl); try { - let imageBuffer; + let imageBuffer: Buffer; if (imageUrl.toLowerCase().startsWith("file://")) { imageBuffer = await new Promise((res, rej) => { @@ -487,10 +488,13 @@ async function downloadImage(noteId: string, imageUrl: string) { const parsedUrl = url.parse(unescapedUrl); const title = path.basename(parsedUrl.pathname || ""); - const imageService = require('../services/image'); const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, title, true, true); - - imageUrlToAttachmentIdMapping[imageUrl] = attachment.attachmentId; + + if (attachment.attachmentId) { + imageUrlToAttachmentIdMapping[imageUrl] = attachment.attachmentId; + } else { + log.error(`Download of '${imageUrl}' due to no attachment ID.`); + } log.info(`Download of '${imageUrl}' succeeded and was saved as image attachment '${attachment.attachmentId}' of note '${noteId}'`); } @@ -520,7 +524,6 @@ function downloadImages(noteId: string, content: string) { const imageBase64 = url.substr(inlineImageMatch[0].length); const imageBuffer = Buffer.from(imageBase64, 'base64'); - const imageService = require('../services/image'); const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true); const encodedTitle = encodeURIComponent(attachment.title); @@ -1037,7 +1040,7 @@ function getNoteIdMapping(origNote: BNote) { return noteIdMapping; } -export = { +export default { createNewNote, createNewNoteWithTarget, updateNoteData, diff --git a/src/services/one_time_timer.ts b/src/services/one_time_timer.ts index 033a8b3c1..f2f514568 100644 --- a/src/services/one_time_timer.ts +++ b/src/services/one_time_timer.ts @@ -20,6 +20,6 @@ function scheduleExecution(name: string, milliseconds: number, cb: () => void) { }, milliseconds); } -export = { +export default { scheduleExecution }; diff --git a/src/services/options.ts b/src/services/options.ts index b658e4ff7..a8b7500fc 100644 --- a/src/services/options.ts +++ b/src/services/options.ts @@ -1,6 +1,7 @@ -import becca = require('../becca/becca'); -import { OptionRow } from '../becca/entities/rows'; -import sql = require('./sql'); +import becca from "../becca/becca.js"; +import BOption from "../becca/entities/boption.js"; +import { OptionRow } from '../becca/entities/rows.js'; +import sql from "./sql.js"; function getOptionOrNull(name: string): string | null { let option; @@ -68,10 +69,7 @@ function setOption(name: string, value: string | number | boolean) { } } -function createOption(name: string, value: string | number, isSynced: boolean) { - // to avoid circular dependency, need to find a better solution - const BOption = require('../becca/entities/boption'); - +function createOption(name: string, value: string, isSynced: boolean) { new BOption({ name: name, value: value, @@ -93,7 +91,7 @@ function getOptionMap() { return map; } -export = { +export default { getOption, getOptionInt, getOptionBool, diff --git a/src/services/options_init.ts b/src/services/options_init.ts index e2ba1520a..a50d57296 100644 --- a/src/services/options_init.ts +++ b/src/services/options_init.ts @@ -1,10 +1,10 @@ -import optionService = require('./options'); -import appInfo = require('./app_info'); -import utils = require('./utils'); -import log = require('./log'); -import dateUtils = require('./date_utils'); -import keyboardActions = require('./keyboard_actions'); -import { KeyboardShortcutWithRequiredActionName } from './keyboard_actions_interface'; +import optionService from "./options.js"; +import appInfo from "./app_info.js"; +import utils from "./utils.js"; +import log from "./log.js"; +import dateUtils from "./date_utils.js"; +import keyboardActions from "./keyboard_actions.js"; +import { KeyboardShortcutWithRequiredActionName } from './keyboard_actions_interface.js'; function initDocumentOptions() { optionService.createOption('documentId', utils.randomSecureToken(16), false); @@ -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'; } @@ -132,7 +132,7 @@ function getKeyboardDefaultOptions() { })); } -export = { +export default { initDocumentOptions, initNotSyncedOptions, initStartupOptions diff --git a/src/services/port.ts b/src/services/port.ts index c37992d42..ffb2e2bf2 100644 --- a/src/services/port.ts +++ b/src/services/port.ts @@ -1,7 +1,7 @@ -import config = require('./config'); -import utils = require('./utils'); -import env = require('./env'); -import dataDir = require('./data_dir'); +import config from "./config.js"; +import utils from "./utils.js"; +import env from "./env.js"; +import dataDir from "./data_dir.js"; function parseAndValidate(portStr: string, source: string) { const portNum = parseInt(portStr); @@ -24,4 +24,4 @@ if (process.env.TRILIUM_PORT) { port = parseAndValidate(config['Network']['port'] || '3000', `Network.port in ${dataDir.CONFIG_INI_PATH}`); } -export = port; +export default port; diff --git a/src/services/promoted_attribute_definition_parser.ts b/src/services/promoted_attribute_definition_parser.ts index 228c96093..ac066c788 100644 --- a/src/services/promoted_attribute_definition_parser.ts +++ b/src/services/promoted_attribute_definition_parser.ts @@ -1,4 +1,4 @@ -import { DefinitionObject } from "./promoted_attribute_definition_interface"; +import { DefinitionObject } from "./promoted_attribute_definition_interface.js"; function parse(value: string): DefinitionObject { const tokens = value.split(',').map(t => t.trim()); @@ -37,6 +37,6 @@ function parse(value: string): DefinitionObject { return defObj; } -export = { +export default { parse }; diff --git a/src/services/protected_session.ts b/src/services/protected_session.ts index 6c1d6c223..b24b971d4 100644 --- a/src/services/protected_session.ts +++ b/src/services/protected_session.ts @@ -1,7 +1,9 @@ "use strict"; -import log = require('./log'); -import dataEncryptionService = require('./encryption/data_encryption'); +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,11 +67,11 @@ function checkProtectedSessionExpiration() { log.info("Expiring protected session"); - require('./ws').reloadFrontend("leaving protected session"); + ws.reloadFrontend("leaving protected session"); } } -export = { +export default { setDataKey, resetDataKey, isProtectedSessionAvailable, diff --git a/src/services/request.ts b/src/services/request.ts index d4a17ad4e..d7be95233 100644 --- a/src/services/request.ts +++ b/src/services/request.ts @@ -1,10 +1,10 @@ "use strict"; -import utils = require('./utils'); -import log = require('./log'); -import url = require('url'); -import syncOptions = require('./sync_options'); -import { ExecOpts } from './request_interface'; +import utils from "./utils.js"; +import log from "./log.js"; +import url from "url"; +import syncOptions from "./sync_options.js"; +import { ExecOpts } from './request_interface.js'; // this service provides abstraction over node's HTTP/HTTPS and electron net.client APIs // this allows supporting system proxy @@ -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) { +async function getImage(imageUrl: string): Promise { const proxyConf = syncOptions.getSyncProxy(); const opts: ClientOpts = { method: 'GET', @@ -145,11 +145,11 @@ function getImage(imageUrl: string) { 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) => { + return new Promise((resolve, reject) => { try { const request = client.request({ method: opts.method, @@ -181,8 +181,7 @@ function getImage(imageUrl: string) { }); request.end(undefined); - } - catch (e: any) { + } catch (e: any) { reject(generateError(opts, e.message)); } }); @@ -190,7 +189,7 @@ function getImage(imageUrl: string) { const HTTP = 'http:', HTTPS = 'https:'; -function getProxyAgent(opts: ClientOpts) { +async function getProxyAgent(opts: ClientOpts) { if (!opts.proxy) { return null; } @@ -202,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}'`); } } @@ -233,7 +230,7 @@ function generateError(opts: { return new Error(`Request to ${opts.method} ${opts.url} failed, error: ${message}`); } -export = { +export default { exec, getImage }; diff --git a/src/services/resource_dir.ts b/src/services/resource_dir.ts index cba351ac8..923f277cf 100644 --- a/src/services/resource_dir.ts +++ b/src/services/resource_dir.ts @@ -1,8 +1,9 @@ -import log = require('./log'); -import path = require('path'); -import fs = require('fs'); +import log from "./log.js"; +import path from "path"; +import fs from "fs"; -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, "../.."); @@ -20,7 +21,7 @@ if (!fs.existsSync(MIGRATIONS_DIR)) { process.exit(1); } -export = { +export default { RESOURCE_DIR, MIGRATIONS_DIR, DB_INIT_DIR, diff --git a/src/services/revisions.ts b/src/services/revisions.ts index 9cd281c13..cfe8f04c6 100644 --- a/src/services/revisions.ts +++ b/src/services/revisions.ts @@ -1,10 +1,10 @@ "use strict"; -import log = require('./log'); -import sql = require('./sql'); -import protectedSessionService = require('./protected_session'); -import dateUtils = require('./date_utils'); -import BNote = require('../becca/entities/bnote'); +import log from "./log.js"; +import sql from "./sql.js"; +import protectedSessionService from "./protected_session.js"; +import dateUtils from "./date_utils.js"; +import BNote from "../becca/entities/bnote.js"; function protectRevisions(note: BNote) { if (!protectedSessionService.isProtectedSessionAvailable()) { @@ -44,6 +44,6 @@ function protectRevisions(note: BNote) { } } -export = { +export default { protectRevisions }; diff --git a/src/services/sanitize_attribute_name.ts b/src/services/sanitize_attribute_name.ts index 62b2b03b3..635588f80 100644 --- a/src/services/sanitize_attribute_name.ts +++ b/src/services/sanitize_attribute_name.ts @@ -13,6 +13,6 @@ function sanitizeAttributeName(origName: string) { } -export = { +export default { sanitizeAttributeName }; diff --git a/src/services/scheduler.ts b/src/services/scheduler.ts index 819de0e59..6d3dac8b8 100644 --- a/src/services/scheduler.ts +++ b/src/services/scheduler.ts @@ -1,12 +1,12 @@ -import scriptService = require('./script'); -import cls = require('./cls'); -import sqlInit = require('./sql_init'); -import config = require('./config'); -import log = require('./log'); -import attributeService = require('../services/attributes'); -import protectedSessionService = require('../services/protected_session'); -import hiddenSubtreeService = require('./hidden_subtree'); -import BNote = require('../becca/entities/bnote'); +import scriptService from "./script.js"; +import cls from "./cls.js"; +import sqlInit from "./sql_init.js"; +import config from "./config.js"; +import log from "./log.js"; +import attributeService from "../services/attributes.js"; +import protectedSessionService from "../services/protected_session.js"; +import hiddenSubtreeService from "./hidden_subtree.js"; +import BNote from "../becca/entities/bnote.js"; function getRunAtHours(note: BNote): number[] { try { diff --git a/src/services/script.ts b/src/services/script.ts index 1a864353a..5b4004bb5 100644 --- a/src/services/script.ts +++ b/src/services/script.ts @@ -1,9 +1,9 @@ -import ScriptContext = require('./script_context'); -import cls = require('./cls'); -import log = require('./log'); -import becca = require('../becca/becca'); -import BNote = require('../becca/entities/bnote'); -import { ApiParams } from './backend_script_api_interface'; +import ScriptContext from "./script_context.js"; +import cls from "./cls.js"; +import log from "./log.js"; +import becca from "../becca/becca.js"; +import BNote from "../becca/entities/bnote.js"; +import { ApiParams } from './backend_script_api_interface.js'; interface Bundle { note?: BNote; @@ -215,7 +215,7 @@ function sanitizeVariableName(str: string) { return str.replace(/[^a-z0-9_]/gim, ""); } -export = { +export default { executeNote, executeNoteNoException, executeScript, diff --git a/src/services/script_context.ts b/src/services/script_context.ts index 4de4863d0..d36c0d492 100644 --- a/src/services/script_context.ts +++ b/src/services/script_context.ts @@ -1,7 +1,7 @@ -import utils = require('./utils'); -import BackendScriptApi = require('./backend_script_api'); -import BNote = require('../becca/entities/bnote'); -import { ApiParams } from './backend_script_api_interface'; +import utils from "./utils.js"; +import BackendScriptApi from "./backend_script_api.js"; +import BNote from "../becca/entities/bnote.js"; +import { ApiParams } from './backend_script_api_interface.js'; type Module = { exports: any[]; @@ -34,4 +34,4 @@ class ScriptContext { }; } -export = ScriptContext; +export default ScriptContext; diff --git a/src/services/search/expressions/ancestor.ts b/src/services/search/expressions/ancestor.ts index 4e7380795..8016e1492 100644 --- a/src/services/search/expressions/ancestor.ts +++ b/src/services/search/expressions/ancestor.ts @@ -1,10 +1,10 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import log = require('../../log'); -import becca = require('../../../becca/becca'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import log from "../../log.js"; +import becca from "../../../becca/becca.js"; +import SearchContext from "../search_context.js"; class AncestorExp extends Expression { @@ -74,4 +74,4 @@ class AncestorExp extends Expression { } } -export = AncestorExp; +export default AncestorExp; diff --git a/src/services/search/expressions/and.ts b/src/services/search/expressions/and.ts index 82c73fe70..2a6e07877 100644 --- a/src/services/search/expressions/and.ts +++ b/src/services/search/expressions/and.ts @@ -1,9 +1,9 @@ "use strict"; -import NoteSet = require('../note_set'); -import SearchContext = require('../search_context'); -import Expression = require('./expression'); -import TrueExp = require('./true'); +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; +import Expression from "./expression.js"; +import TrueExp from "./true.js"; class AndExp extends Expression { private subExpressions: Expression[]; @@ -34,4 +34,4 @@ class AndExp extends Expression { } } -export = AndExp; +export default AndExp; diff --git a/src/services/search/expressions/attribute_exists.ts b/src/services/search/expressions/attribute_exists.ts index b1f01a1c0..625e4b2af 100644 --- a/src/services/search/expressions/attribute_exists.ts +++ b/src/services/search/expressions/attribute_exists.ts @@ -1,10 +1,10 @@ "use strict"; -import NoteSet = require("../note_set"); -import SearchContext = require("../search_context"); +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; -import becca = require('../../../becca/becca'); -import Expression = require('./expression'); +import becca from "../../../becca/becca.js"; +import Expression from "./expression.js"; class AttributeExistsExp extends Expression { @@ -48,4 +48,4 @@ class AttributeExistsExp extends Expression { } } -export = AttributeExistsExp; +export default AttributeExistsExp; diff --git a/src/services/search/expressions/child_of.ts b/src/services/search/expressions/child_of.ts index 10d31c00a..491eab3ef 100644 --- a/src/services/search/expressions/child_of.ts +++ b/src/services/search/expressions/child_of.ts @@ -1,8 +1,8 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; class ChildOfExp extends Expression { @@ -37,4 +37,4 @@ class ChildOfExp extends Expression { } } -export = ChildOfExp; +export default ChildOfExp; diff --git a/src/services/search/expressions/descendant_of.ts b/src/services/search/expressions/descendant_of.ts index 6994056c8..7a7444de8 100644 --- a/src/services/search/expressions/descendant_of.ts +++ b/src/services/search/expressions/descendant_of.ts @@ -1,9 +1,9 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import becca = require('../../../becca/becca'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import becca from "../../../becca/becca.js"; +import SearchContext from "../search_context.js"; class DescendantOfExp extends Expression { private subExpression: Expression; @@ -28,4 +28,4 @@ class DescendantOfExp extends Expression { } } -export = DescendantOfExp; +export default DescendantOfExp; diff --git a/src/services/search/expressions/expression.ts b/src/services/search/expressions/expression.ts index c74341ba2..2bff50e95 100644 --- a/src/services/search/expressions/expression.ts +++ b/src/services/search/expressions/expression.ts @@ -1,7 +1,7 @@ "use strict"; -import NoteSet = require("../note_set"); -import SearchContext = require("../search_context"); +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; abstract class Expression { name: string; @@ -13,4 +13,4 @@ abstract class Expression { abstract execute(inputNoteSet: NoteSet, executionContext: {}, searchContext: SearchContext): NoteSet; } -export = Expression; +export default Expression; diff --git a/src/services/search/expressions/is_hidden.ts b/src/services/search/expressions/is_hidden.ts index 81bef22b3..3ceeb5570 100644 --- a/src/services/search/expressions/is_hidden.ts +++ b/src/services/search/expressions/is_hidden.ts @@ -1,8 +1,8 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; /** * Note is hidden when all its note paths start in hidden subtree (i.e., the note is not cloned into visible tree) @@ -21,4 +21,4 @@ class IsHiddenExp extends Expression { } } -export = IsHiddenExp; +export default IsHiddenExp; diff --git a/src/services/search/expressions/label_comparison.ts b/src/services/search/expressions/label_comparison.ts index b455f82ca..85ef94096 100644 --- a/src/services/search/expressions/label_comparison.ts +++ b/src/services/search/expressions/label_comparison.ts @@ -1,9 +1,9 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import becca = require('../../../becca/becca'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import becca from "../../../becca/becca.js"; +import SearchContext from "../search_context.js"; type Comparator = (value: string) => boolean; @@ -46,4 +46,4 @@ class LabelComparisonExp extends Expression { } } -export = LabelComparisonExp; +export default LabelComparisonExp; diff --git a/src/services/search/expressions/not.ts b/src/services/search/expressions/not.ts index e1b31c84e..25f61f6db 100644 --- a/src/services/search/expressions/not.ts +++ b/src/services/search/expressions/not.ts @@ -1,8 +1,8 @@ "use strict"; -import NoteSet = require('../note_set'); -import SearchContext = require('../search_context'); -import Expression = require('./expression'); +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; +import Expression from "./expression.js"; class NotExp extends Expression { private subExpression: Expression; @@ -20,4 +20,4 @@ class NotExp extends Expression { } } -export = NotExp; +export default NotExp; diff --git a/src/services/search/expressions/note_content_fulltext.ts b/src/services/search/expressions/note_content_fulltext.ts index 02626bf16..79d9b5376 100644 --- a/src/services/search/expressions/note_content_fulltext.ts +++ b/src/services/search/expressions/note_content_fulltext.ts @@ -1,16 +1,16 @@ "use strict"; -import { NoteRow } from "../../../becca/entities/rows"; -import SearchContext = require("../search_context"); +import { NoteRow } from "../../../becca/entities/rows.js"; +import SearchContext from "../search_context.js"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import log = require('../../log'); -import becca = require('../../../becca/becca'); -import protectedSessionService = require('../../protected_session'); -import striptags = require('striptags'); -import utils = require('../../utils'); -import sql = require("../../sql"); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import log from "../../log.js"; +import becca from "../../../becca/becca.js"; +import protectedSessionService from "../../protected_session.js"; +import striptags from "striptags"; +import utils from "../../utils.js"; +import sql from "../../sql.js"; const ALLOWED_OPERATORS = ['=', '!=', '*=*', '*=', '=*', '%=']; @@ -155,4 +155,4 @@ class NoteContentFulltextExp extends Expression { } } -export = NoteContentFulltextExp; +export default NoteContentFulltextExp; diff --git a/src/services/search/expressions/note_flat_text.ts b/src/services/search/expressions/note_flat_text.ts index f163e8a7a..3bd101005 100644 --- a/src/services/search/expressions/note_flat_text.ts +++ b/src/services/search/expressions/note_flat_text.ts @@ -1,12 +1,13 @@ "use strict"; -import BNote = require("../../../becca/entities/bnote"); -import SearchContext = require("../search_context"); +import BNote from "../../../becca/entities/bnote.js"; +import SearchContext from "../search_context.js"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import becca = require('../../../becca/becca'); -import utils = require('../../utils'); +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(); /** @@ -172,4 +171,4 @@ class NoteFlatTextExp extends Expression { } } -export = NoteFlatTextExp; +export default NoteFlatTextExp; diff --git a/src/services/search/expressions/or.ts b/src/services/search/expressions/or.ts index f89e9070e..7b141129c 100644 --- a/src/services/search/expressions/or.ts +++ b/src/services/search/expressions/or.ts @@ -1,9 +1,9 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import TrueExp = require('./true'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import TrueExp from "./true.js"; +import SearchContext from "../search_context.js"; class OrExp extends Expression { private subExpressions: Expression[]; @@ -39,4 +39,4 @@ class OrExp extends Expression { } } -export = OrExp; +export default OrExp; diff --git a/src/services/search/expressions/order_by_and_limit.ts b/src/services/search/expressions/order_by_and_limit.ts index a3a37496f..9d0ff31c8 100644 --- a/src/services/search/expressions/order_by_and_limit.ts +++ b/src/services/search/expressions/order_by_and_limit.ts @@ -1,9 +1,9 @@ "use strict"; -import BNote = require("../../../becca/entities/bnote"); -import NoteSet = require("../note_set"); -import SearchContext = require("../search_context"); -import Expression = require("./expression"); +import BNote from "../../../becca/entities/bnote.js"; +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; +import Expression from "./expression.js"; interface ValueExtractor { extract: (note: BNote) => number | string | null; @@ -111,4 +111,4 @@ class OrderByAndLimitExp extends Expression { } } -export = OrderByAndLimitExp; +export default OrderByAndLimitExp; diff --git a/src/services/search/expressions/parent_of.ts b/src/services/search/expressions/parent_of.ts index bd7b9d304..8a51bbf62 100644 --- a/src/services/search/expressions/parent_of.ts +++ b/src/services/search/expressions/parent_of.ts @@ -1,8 +1,8 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; class ParentOfExp extends Expression { private subExpression: Expression; @@ -36,4 +36,4 @@ class ParentOfExp extends Expression { } } -export = ParentOfExp; +export default ParentOfExp; diff --git a/src/services/search/expressions/property_comparison.ts b/src/services/search/expressions/property_comparison.ts index 843b5a862..a6b072d09 100644 --- a/src/services/search/expressions/property_comparison.ts +++ b/src/services/search/expressions/property_comparison.ts @@ -1,8 +1,8 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import buildComparator = require('../services/build_comparator'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import buildComparator from "../services/build_comparator.js"; /** * Search string is lower cased for case-insensitive comparison. But when retrieving properties, @@ -87,4 +87,4 @@ class PropertyComparisonExp extends Expression { } } -export = PropertyComparisonExp; +export default PropertyComparisonExp; diff --git a/src/services/search/expressions/relation_where.ts b/src/services/search/expressions/relation_where.ts index 9f33dcecf..d973da0ce 100644 --- a/src/services/search/expressions/relation_where.ts +++ b/src/services/search/expressions/relation_where.ts @@ -1,9 +1,9 @@ "use strict"; -import Expression = require('./expression'); -import NoteSet = require('../note_set'); -import becca = require('../../../becca/becca'); -import SearchContext = require('../search_context'); +import Expression from "./expression.js"; +import NoteSet from "../note_set.js"; +import becca from "../../../becca/becca.js"; +import SearchContext from "../search_context.js"; class RelationWhereExp extends Expression { private relationName: string; @@ -42,4 +42,4 @@ class RelationWhereExp extends Expression { } } -export = RelationWhereExp; +export default RelationWhereExp; diff --git a/src/services/search/expressions/true.ts b/src/services/search/expressions/true.ts index a53d1afde..5858a1075 100644 --- a/src/services/search/expressions/true.ts +++ b/src/services/search/expressions/true.ts @@ -1,9 +1,9 @@ "use strict"; -import NoteSet = require("../note_set"); -import SearchContext = require("../search_context"); +import NoteSet from "../note_set.js"; +import SearchContext from "../search_context.js"; -import Expression = require('./expression'); +import Expression from "./expression.js"; class TrueExp extends Expression { execute(inputNoteSet: NoteSet, executionContext: {}, searchContext: SearchContext): NoteSet { @@ -11,4 +11,4 @@ class TrueExp extends Expression { } } -export = TrueExp; +export default TrueExp; diff --git a/src/services/search/note_set.ts b/src/services/search/note_set.ts index 47c644c38..6f56452b7 100644 --- a/src/services/search/note_set.ts +++ b/src/services/search/note_set.ts @@ -1,6 +1,6 @@ "use strict"; -import BNote = require("../../becca/entities/bnote"); +import BNote from "../../becca/entities/bnote.js"; class NoteSet { @@ -65,4 +65,4 @@ class NoteSet { } } -export = NoteSet; +export default NoteSet; diff --git a/src/services/search/search_context.ts b/src/services/search/search_context.ts index f7c1e2198..c024be9a7 100644 --- a/src/services/search/search_context.ts +++ b/src/services/search/search_context.ts @@ -1,7 +1,7 @@ "use strict"; -import hoistedNoteService = require('../hoisted_note'); -import { SearchParams } from './services/types'; +import hoistedNoteService from "../hoisted_note.js"; +import { SearchParams } from './services/types.js'; class SearchContext { @@ -68,4 +68,4 @@ class SearchContext { } } -export = SearchContext; +export default SearchContext; diff --git a/src/services/search/search_result.ts b/src/services/search/search_result.ts index cf651d58e..385999053 100644 --- a/src/services/search/search_result.ts +++ b/src/services/search/search_result.ts @@ -1,7 +1,7 @@ "use strict"; -import beccaService = require('../../becca/becca_service'); -import becca = require('../../becca/becca'); +import beccaService from "../../becca/becca_service.js"; +import becca from "../../becca/becca.js"; class SearchResult { notePathArray: string[]; @@ -67,4 +67,4 @@ class SearchResult { } } -export = SearchResult; +export default SearchResult; diff --git a/src/services/search/services/build_comparator.ts b/src/services/search/services/build_comparator.ts index 460c98809..c43de1ee3 100644 --- a/src/services/search/services/build_comparator.ts +++ b/src/services/search/services/build_comparator.ts @@ -42,4 +42,4 @@ function buildComparator(operator: string, comparedValue: string) { } } -export = buildComparator; +export default buildComparator; diff --git a/src/services/search/services/handle_parens.ts b/src/services/search/services/handle_parens.ts index 30d7e03fc..3ce0d1fd3 100644 --- a/src/services/search/services/handle_parens.ts +++ b/src/services/search/services/handle_parens.ts @@ -1,9 +1,9 @@ -import { TokenData } from "./types"; +import { TokenData, TokenStructure } from "./types.js"; /** * This will create a recursive object from a list of tokens - tokens between parenthesis are grouped in a single array */ -function handleParens(tokens: (TokenData | TokenData[])[]) { +function handleParens(tokens: TokenStructure) { if (tokens.length === 0) { return []; } @@ -47,4 +47,4 @@ function handleParens(tokens: (TokenData | TokenData[])[]) { } } -export = handleParens; +export default handleParens; diff --git a/src/services/search/services/lex.ts b/src/services/search/services/lex.ts index 516cf71df..3adfcdc56 100644 --- a/src/services/search/services/lex.ts +++ b/src/services/search/services/lex.ts @@ -1,4 +1,4 @@ -import { TokenData } from "./types"; +import { TokenData } from "./types.js"; function lex(str: string) { str = str.toLowerCase(); @@ -147,4 +147,4 @@ function lex(str: string) { } } -export = lex; +export default lex; diff --git a/src/services/search/services/parse.ts b/src/services/search/services/parse.ts index de943fdd2..5f7362623 100644 --- a/src/services/search/services/parse.ts +++ b/src/services/search/services/parse.ts @@ -1,28 +1,28 @@ "use strict"; -import dayjs = require("dayjs"); -import AndExp = require('../expressions/and'); -import OrExp = require('../expressions/or'); -import NotExp = require('../expressions/not'); -import ChildOfExp = require('../expressions/child_of'); -import DescendantOfExp = require('../expressions/descendant_of'); -import ParentOfExp = require('../expressions/parent_of'); -import RelationWhereExp = require('../expressions/relation_where'); -import PropertyComparisonExp = require('../expressions/property_comparison'); -import AttributeExistsExp = require('../expressions/attribute_exists'); -import LabelComparisonExp = require('../expressions/label_comparison'); -import NoteFlatTextExp = require('../expressions/note_flat_text'); -import NoteContentFulltextExp = require('../expressions/note_content_fulltext'); -import OrderByAndLimitExp = require('../expressions/order_by_and_limit'); -import AncestorExp = require('../expressions/ancestor'); -import buildComparator = require('./build_comparator'); -import ValueExtractor = require('../value_extractor'); -import utils = require('../../utils'); -import TrueExp = require('../expressions/true'); -import IsHiddenExp = require('../expressions/is_hidden'); -import SearchContext = require("../search_context"); -import { TokenData } from "./types"; -import Expression = require("../expressions/expression"); +import dayjs from "dayjs"; +import AndExp from "../expressions/and.js"; +import OrExp from "../expressions/or.js"; +import NotExp from "../expressions/not.js"; +import ChildOfExp from "../expressions/child_of.js"; +import DescendantOfExp from "../expressions/descendant_of.js"; +import ParentOfExp from "../expressions/parent_of.js"; +import RelationWhereExp from "../expressions/relation_where.js"; +import PropertyComparisonExp from "../expressions/property_comparison.js"; +import AttributeExistsExp from "../expressions/attribute_exists.js"; +import LabelComparisonExp from "../expressions/label_comparison.js"; +import NoteFlatTextExp from "../expressions/note_flat_text.js"; +import NoteContentFulltextExp from "../expressions/note_content_fulltext.js"; +import OrderByAndLimitExp from "../expressions/order_by_and_limit.js"; +import AncestorExp from "../expressions/ancestor.js"; +import buildComparator from "./build_comparator.js"; +import ValueExtractor from "../value_extractor.js"; +import utils from "../../utils.js"; +import TrueExp from "../expressions/true.js"; +import IsHiddenExp from "../expressions/is_hidden.js"; +import SearchContext from "../search_context.js"; +import { TokenData, TokenStructure } from "./types.js"; +import Expression from "../expressions/expression.js"; function getFulltext(_tokens: TokenData[], searchContext: SearchContext) { const tokens: string[] = _tokens.map(t => utils.removeDiacritic(t.token)); @@ -448,7 +448,7 @@ function getExpression(tokens: TokenData[], searchContext: SearchContext, level function parse({fulltextTokens, expressionTokens, searchContext}: { fulltextTokens: TokenData[], - expressionTokens: (TokenData | TokenData[])[], + expressionTokens: TokenStructure, searchContext: SearchContext, originalQuery: string }) { @@ -494,4 +494,4 @@ function getAncestorExp({ancestorNoteId, ancestorDepth, includeHiddenNotes}: Sea } } -export = parse; +export default parse; diff --git a/src/services/search/services/search.ts b/src/services/search/services/search.ts index 7461d5b4e..0c3fb87db 100644 --- a/src/services/search/services/search.ts +++ b/src/services/search/services/search.ts @@ -1,23 +1,36 @@ "use strict"; -import normalizeString = require("normalize-strings"); -import lex = require('./lex'); -import handleParens = require('./handle_parens'); -import parse = require('./parse'); -import SearchResult = require('../search_result'); -import SearchContext = require('../search_context'); -import becca = require('../../../becca/becca'); -import beccaService = require('../../../becca/becca_service'); -import utils = require('../../utils'); -import log = require('../../log'); -import hoistedNoteService = require('../../hoisted_note'); -import BNote = require("../../../becca/entities/bnote"); -import BAttribute = require("../../../becca/entities/battribute"); -import { SearchParams, TokenData } from "./types"; -import Expression = require("../expressions/expression"); -import sql = require("../../sql"); +import normalizeString from "normalize-strings"; +import lex from "./lex.js"; +import handleParens from "./handle_parens.js"; +import parse from "./parse.js"; +import SearchResult from "../search_result.js"; +import SearchContext from "../search_context.js"; +import becca from "../../../becca/becca.js"; +import beccaService from "../../../becca/becca_service.js"; +import utils from "../../utils.js"; +import log from "../../log.js"; +import hoistedNoteService from "../../hoisted_note.js"; +import BNote from "../../../becca/entities/bnote.js"; +import BAttribute from "../../../becca/entities/battribute.js"; +import { SearchParams, TokenStructure } from "./types.js"; +import Expression from "../expressions/expression.js"; +import sql from "../../sql.js"; +import scriptService from "../../script.js"; -function searchFromNote(note: BNote) { +export interface SearchNoteResult { + searchResultNoteIds: string[]; + highlightedTokens: string[]; + error: string | null; +} + +export const EMPTY_RESULT: SearchNoteResult = { + searchResultNoteIds: [], + highlightedTokens: [], + error: null +}; + +function searchFromNote(note: BNote): SearchNoteResult { let searchResultNoteIds; let highlightedTokens: string[]; @@ -78,7 +91,6 @@ function searchFromRelation(note: BNote, relationName: string) { return []; } - const scriptService = require('../../script'); // TODO: to avoid circular dependency const result = scriptService.executeNote(scriptNote, {originEntity: note}); if (!Array.isArray(result)) { @@ -273,7 +285,7 @@ function parseQueryToExpression(query: string, searchContext: SearchContext) { const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query); searchContext.fulltextQuery = fulltextQuery; - let structuredExpressionTokens: (TokenData | TokenData[])[]; + let structuredExpressionTokens: TokenStructure; try { structuredExpressionTokens = handleParens(expressionTokens); @@ -444,7 +456,7 @@ function formatAttribute(attr: BAttribute) { } } -export = { +export default { searchFromNote, searchNotesForAutocomplete, findResultsWithQuery, diff --git a/src/services/search/services/types.ts b/src/services/search/services/types.ts index 09450f760..2b12a3c65 100644 --- a/src/services/search/services/types.ts +++ b/src/services/search/services/types.ts @@ -1,3 +1,5 @@ +export type TokenStructure = (TokenData | TokenStructure)[]; + export interface TokenData { token: string; inQuotes?: boolean; diff --git a/src/services/search/value_extractor.ts b/src/services/search/value_extractor.ts index 4f2466f11..a6df8feda 100644 --- a/src/services/search/value_extractor.ts +++ b/src/services/search/value_extractor.ts @@ -1,6 +1,6 @@ "use strict"; -import BNote = require("../../becca/entities/bnote"); +import BNote from "../../becca/entities/bnote.js"; /** * Search string is lower cased for case-insensitive comparison. But when retrieving properties, @@ -134,4 +134,4 @@ class ValueExtractor { } } -export = ValueExtractor; +export default ValueExtractor; diff --git a/src/services/session_secret.ts b/src/services/session_secret.ts index 20b35efb2..2e67f1ed4 100644 --- a/src/services/session_secret.ts +++ b/src/services/session_secret.ts @@ -1,9 +1,9 @@ "use strict"; -import fs = require('fs'); -import crypto = require('crypto'); -import dataDir = require('./data_dir'); -import log = require('./log'); +import fs from "fs"; +import crypto from "crypto"; +import dataDir from "./data_dir.js"; +import log from "./log.js"; const sessionSecretPath = `${dataDir.TRILIUM_DATA_DIR}/session_secret.txt`; @@ -28,4 +28,4 @@ else { sessionSecret = fs.readFileSync(sessionSecretPath, ENCODING); } -export = sessionSecret; +export default sessionSecret; diff --git a/src/services/setup.ts b/src/services/setup.ts index 08b1ee806..0f3d26f58 100644 --- a/src/services/setup.ts +++ b/src/services/setup.ts @@ -1,13 +1,13 @@ -import syncService = require('./sync'); -import log = require('./log'); -import sqlInit = require('./sql_init'); -import optionService = require('./options'); -import syncOptions = require('./sync_options'); -import request = require('./request'); -import appInfo = require('./app_info'); -import utils = require('./utils'); -import becca = require('../becca/becca'); -import { SetupStatusResponse, SetupSyncSeedResponse } from './api-interface'; +import syncService from "./sync.js"; +import log from "./log.js"; +import sqlInit from "./sql_init.js"; +import optionService from "./options.js"; +import syncOptions from "./sync_options.js"; +import request from "./request.js"; +import appInfo from "./app_info.js"; +import utils from "./utils.js"; +import becca from "../becca/becca.js"; +import { SetupStatusResponse, SetupSyncSeedResponse } from './api-interface.js'; async function hasSyncServerSchemaAndSeed() { const response = await requestToSyncServer('GET', '/api/setup/status'); @@ -110,7 +110,7 @@ function getSyncSeedOptions() { ]; } -export = { +export default { hasSyncServerSchemaAndSeed, triggerSync, sendSeedToSyncServer, diff --git a/src/services/spaced_update.ts b/src/services/spaced_update.ts index 24417d18c..8fc5818be 100644 --- a/src/services/spaced_update.ts +++ b/src/services/spaced_update.ts @@ -74,4 +74,4 @@ class SpacedUpdate { } } -export = SpacedUpdate; +export default SpacedUpdate; diff --git a/src/services/special_notes.ts b/src/services/special_notes.ts index 65cc14c31..50ba2eccf 100644 --- a/src/services/special_notes.ts +++ b/src/services/special_notes.ts @@ -1,13 +1,13 @@ -import attributeService = require('./attributes'); -import dateNoteService = require('./date_notes'); -import becca = require('../becca/becca'); -import noteService = require('./notes'); -import dateUtils = require('./date_utils'); -import log = require('./log'); -import hoistedNoteService = require('./hoisted_note'); -import searchService = require('./search/services/search'); -import SearchContext = require('./search/search_context'); -import hiddenSubtree = require('./hidden_subtree'); +import attributeService from "./attributes.js"; +import dateNoteService from "./date_notes.js"; +import becca from "../becca/becca.js"; +import noteService from "./notes.js"; +import dateUtils from "./date_utils.js"; +import log from "./log.js"; +import hoistedNoteService from "./hoisted_note.js"; +import searchService from "./search/services/search.js"; +import SearchContext from "./search/search_context.js"; +import hiddenSubtree from "./hidden_subtree.js"; const { LBTPL_NOTE_LAUNCHER, LBTPL_CUSTOM_WIDGET, LBTPL_SPACER, LBTPL_SCRIPT } = hiddenSubtree; function getInboxNote(date: string) { @@ -287,7 +287,7 @@ function createOrUpdateScriptLauncherFromApi(opts: { return launcherNote; } -export = { +export default { getInboxNote, createSqlConsole, saveSqlConsole, diff --git a/src/services/sql.ts b/src/services/sql.ts index cb4a75df5..0d92e6209 100644 --- a/src/services/sql.ts +++ b/src/services/sql.ts @@ -4,12 +4,15 @@ * @module sql */ -import log = require('./log'); +import log from "./log.js"; import type { Statement, Database as DatabaseType, RunResult } from "better-sqlite3"; -import dataDir = require('./data_dir'); -import cls = require('./cls'); -import fs = require("fs-extra"); -import Database = require('better-sqlite3'); +import dataDir from "./data_dir.js"; +import cls from "./cls.js"; +import fs from "fs-extra"; +import Database from "better-sqlite3"; +import ws from "./ws.js"; +import becca_loader from "../becca/becca_loader.js"; +import entity_changes from "./entity_changes.js"; const dbConnection: DatabaseType = new Database(dataDir.DOCUMENT_PATH); dbConnection.pragma('journal_mode = WAL'); @@ -248,7 +251,7 @@ function transactional(func: (statement: Statement) => T) { const ret = (dbConnection.transaction(func) as any).deferred(); if (!dbConnection.inTransaction) { // i.e. transaction was really committed (and not just savepoint released) - require('./ws').sendTransactionEntityChangesToAllClients(); + ws.sendTransactionEntityChangesToAllClients(); } return ret; @@ -259,11 +262,11 @@ function transactional(func: (statement: Statement) => T) { if (entityChangeIds.length > 0) { log.info("Transaction rollback dirtied the becca, forcing reload."); - require('../becca/becca_loader').load(); + becca_loader.load(); } // the maxEntityChangeId has been incremented during failed transaction, need to recalculate - require('./entity_changes').recalculateMaxEntityChangeId(); + entity_changes.recalculateMaxEntityChangeId(); throw e; } @@ -314,7 +317,7 @@ function disableSlowQueryLogging(cb: () => T) { } } -export = { +export default { dbConnection, insert, replace, diff --git a/src/services/sql_init.ts b/src/services/sql_init.ts index 5c9937daa..a93750476 100644 --- a/src/services/sql_init.ts +++ b/src/services/sql_init.ts @@ -1,21 +1,26 @@ -import log = require('./log'); -import fs = require('fs'); -import resourceDir = require('./resource_dir'); -import sql = require('./sql'); -import utils = require('./utils'); -import optionService = require('./options'); -import port = require('./port'); -import BOption = require('../becca/entities/boption'); -import TaskContext = require('./task_context'); -import migrationService = require('./migration'); -import cls = require('./cls'); -import config = require('./config'); -import { OptionRow } from '../becca/entities/rows'; +import log from "./log.js"; +import fs from "fs"; +import resourceDir from "./resource_dir.js"; +import sql from "./sql.js"; +import utils from "./utils.js"; +import optionService from "./options.js"; +import port from "./port.js"; +import BOption from "../becca/entities/boption.js"; +import TaskContext from "./task_context.js"; +import migrationService from "./migration.js"; +import cls from "./cls.js"; +import config from "./config.js"; +import { OptionRow } from '../becca/entities/rows.js'; +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'`); @@ -54,17 +59,14 @@ async function createInitialDatabase() { const schema = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/schema.sql`, "utf-8"); const demoFile = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/demo.zip`); - let rootNote; + let rootNote!: BNote; sql.transactional(() => { log.info("Creating database schema ..."); sql.executeScript(schema); - require('../becca/becca_loader').load(); - - const BNote = require('../becca/entities/bnote'); - const BBranch = require('../becca/entities/bbranch'); + becca_loader.load(); log.info("Creating root note ..."); @@ -84,19 +86,16 @@ async function createInitialDatabase() { notePosition: 10 }).save(); - const optionsInitService = require('./options_init'); - optionsInitService.initDocumentOptions(); optionsInitService.initNotSyncedOptions(true, {}); optionsInitService.initStartupOptions(); - require('./encryption/password').resetPassword(); + password.resetPassword(); }); log.info("Importing demo content ..."); const dummyTaskContext = new TaskContext("no-progress-reporting", 'import', false); - const zipImportService = require('./import/zip'); await zipImportService.importZip(dummyTaskContext, demoFile, rootNote); sql.transactional(() => { @@ -106,7 +105,6 @@ async function createInitialDatabase() { const startNoteId = sql.getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition"); - const optionService = require('./options'); optionService.setOption('openNoteContexts', JSON.stringify([ { notePath: startNoteId, @@ -132,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) { @@ -160,36 +158,41 @@ 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); -export = { + 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, schemaExists, isDbInitialized, createInitialDatabase, createDatabaseForSync, setDbAsInitialized, - getDbSize + getDbSize, + initializeDb }; diff --git a/src/services/sync.ts b/src/services/sync.ts index 8c8183984..5864edb06 100644 --- a/src/services/sync.ts +++ b/src/services/sync.ts @@ -1,24 +1,27 @@ "use strict"; -import log = require('./log'); -import sql = require('./sql'); -import optionService = require('./options'); -import utils = require('./utils'); -import instanceId = require('./instance_id'); -import dateUtils = require('./date_utils'); -import syncUpdateService = require('./sync_update'); -import contentHashService = require('./content_hash'); -import appInfo = require('./app_info'); -import syncOptions = require('./sync_options'); -import syncMutexService = require('./sync_mutex'); -import cls = require('./cls'); -import request = require('./request'); -import ws = require('./ws'); -import entityChangesService = require('./entity_changes'); -import entityConstructor = require('../becca/entity_constructor'); -import becca = require('../becca/becca'); -import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface'; -import { CookieJar, ExecOpts } from './request_interface'; +import log from "./log.js"; +import sql from "./sql.js"; +import optionService from "./options.js"; +import utils from "./utils.js"; +import instanceId from "./instance_id.js"; +import dateUtils from "./date_utils.js"; +import syncUpdateService from "./sync_update.js"; +import contentHashService from "./content_hash.js"; +import appInfo from "./app_info.js"; +import syncOptions from "./sync_options.js"; +import syncMutexService from "./sync_mutex.js"; +import cls from "./cls.js"; +import request from "./request.js"; +import ws from "./ws.js"; +import entityChangesService from "./entity_changes.js"; +import entityConstructor from "../becca/entity_constructor.js"; +import becca from "../becca/becca.js"; +import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface.js'; +import { CookieJar, ExecOpts } from './request_interface.js'; +import setupService from "./setup.js"; +import consistency_checks from "./consistency_checks.js"; +import becca_loader from "../becca/becca_loader.js"; let proxyToggle = true; @@ -107,8 +110,6 @@ async function sync() { } async function login() { - const setupService = require('./setup'); // circular dependency issue - if (!await setupService.hasSyncServerSchemaAndSeed()) { await setupService.sendSeedToSyncServer(); } @@ -282,8 +283,7 @@ async function checkContentHash(syncContext: SyncContext) { if (failedChecks.length > 0) { // before re-queuing sectors, make sure the entity changes are correct - const consistencyChecks = require('./consistency_checks'); - consistencyChecks.runEntityChangesChecks(); + consistency_checks.runEntityChangesChecks(); await syncRequest(syncContext, 'POST', `/api/sync/check-entity-changes`); } @@ -443,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 @@ -453,7 +453,7 @@ require('../becca/becca_loader').beccaLoaded.then(() => { getLastSyncedPush(); }); -export = { +export default { sync, login, getEntityChangeRecords, diff --git a/src/services/sync_mutex.ts b/src/services/sync_mutex.ts index 9ad0fd08c..5bdbaa36f 100644 --- a/src/services/sync_mutex.ts +++ b/src/services/sync_mutex.ts @@ -3,7 +3,7 @@ * (like consistency checks) can use this mutex to make sure sync isn't currently running. */ -const Mutex = require('async-mutex').Mutex; +import { Mutex } from "async-mutex"; const instance = new Mutex(); async function doExclusively(func: () => T) { @@ -17,6 +17,6 @@ async function doExclusively(func: () => T) { } } -export = { +export default { doExclusively }; diff --git a/src/services/sync_options.ts b/src/services/sync_options.ts index 92aea6c3f..48cf39efd 100644 --- a/src/services/sync_options.ts +++ b/src/services/sync_options.ts @@ -1,7 +1,7 @@ "use strict"; -import optionService = require('./options'); -import config = require('./config'); +import optionService from "./options.js"; +import config from "./config.js"; /* * Primary configuration for sync is in the options (document), but we allow to override @@ -14,7 +14,7 @@ function get(name: string) { return (config['Sync'] && config['Sync'][name]) || optionService.getOption(name); } -export = { +export default { // env variable is the easiest way to guarantee we won't overwrite prod data during development // after copying prod document/data directory getSyncServerHost: () => process.env.TRILIUM_SYNC_SERVER_HOST || get('syncServerHost'), diff --git a/src/services/sync_update.ts b/src/services/sync_update.ts index 61d425438..275477ba2 100644 --- a/src/services/sync_update.ts +++ b/src/services/sync_update.ts @@ -1,10 +1,10 @@ -import sql = require('./sql'); -import log = require('./log'); -import entityChangesService = require('./entity_changes'); -import eventService = require('./events'); -import entityConstructor = require('../becca/entity_constructor'); -import ws = require('./ws'); -import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface'; +import sql from "./sql.js"; +import log from "./log.js"; +import entityChangesService from "./entity_changes.js"; +import eventService from "./events.js"; +import entityConstructor from "../becca/entity_constructor.js"; +import ws from "./ws.js"; +import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface.js'; interface UpdateContext { alreadyErased: number; @@ -182,6 +182,6 @@ function logUpdateContext(updateContext: UpdateContext) { log.info(message.substr(1, message.length - 2)); } -export = { +export default { updateEntities }; diff --git a/src/services/task_context.ts b/src/services/task_context.ts index 27f7d1358..0f3557674 100644 --- a/src/services/task_context.ts +++ b/src/services/task_context.ts @@ -1,7 +1,7 @@ "use strict"; -import { TaskData } from './task_context_interface'; -import ws = require('./ws'); +import { TaskData } from './task_context_interface.js'; +import ws from "./ws.js"; // taskId => TaskContext const taskContexts: Record = {}; @@ -77,4 +77,4 @@ class TaskContext { } } -export = TaskContext; +export default TaskContext; diff --git a/src/services/tray.ts b/src/services/tray.ts index 70d686adb..a163a5a22 100644 --- a/src/services/tray.ts +++ b/src/services/tray.ts @@ -1,13 +1,15 @@ import { Menu, Tray } from 'electron'; -import path = require('path'); -import windowService = require('./window'); -import optionService = require('./options'); +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", @@ -106,6 +108,6 @@ function createTray() { registerVisibilityListener(); } -export = { +export default { createTray } diff --git a/src/services/tree.ts b/src/services/tree.ts index d731fe6b0..0ab72e7f7 100644 --- a/src/services/tree.ts +++ b/src/services/tree.ts @@ -1,13 +1,19 @@ "use strict"; -import sql = require('./sql'); -import log = require('./log'); -import BBranch = require('../becca/entities/bbranch'); -import entityChangesService = require('./entity_changes'); -import becca = require('../becca/becca'); -import BNote = require('../becca/entities/bnote'); +import sql from "./sql.js"; +import log from "./log.js"; +import BBranch from "../becca/entities/bbranch.js"; +import entityChangesService from "./entity_changes.js"; +import becca from "../becca/becca.js"; +import BNote from "../becca/entities/bnote.js"; -function validateParentChild(parentNoteId: string, childNoteId: string, branchId: string | null = null) { +interface ValidationResponse { + branch: BBranch | null; + success: boolean; + message?: string; +} + +function validateParentChild(parentNoteId: string, childNoteId: string, branchId: string | null = null): ValidationResponse { if (['root', '_hidden', '_share', '_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(childNoteId)) { return { branch: null, success: false, message: `Cannot change this note's location.` }; } @@ -261,7 +267,7 @@ function setNoteToParent(noteId: string, prefix: string, parentNoteId: string) { } } -export = { +export default { validateParentChild, sortNotes, sortNotesIfNeeded, diff --git a/src/services/utils.ts b/src/services/utils.ts index aef261a6a..0747f744f 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -1,12 +1,14 @@ "use strict"; -import crypto = require('crypto'); -const randtoken = require('rand-token').generator({source: 'crypto'}); -import unescape = require('unescape'); -import escape = require('escape-html'); -import sanitize = require("sanitize-filename"); -import mimeTypes = require('mime-types'); -import path = require('path'); +import crypto from "crypto"; +import { generator } from "rand-token"; +import unescape from "unescape"; +import escape from "escape-html"; +import sanitize from "sanitize-filename"; +import mimeTypes from "mime-types"; +import path from "path"; + +const randtoken = generator({source: 'crypto'}); function newEntityId() { return randomString(12); @@ -123,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); } } @@ -173,7 +174,7 @@ function replaceAll(string: string, replaceWhat: string, replaceWith: string) { return string.replace(new RegExp(quotedReplaceWhat, "g"), replaceWith); } -function formatDownloadTitle(fileName: string, type: string, mime: string) { +function formatDownloadTitle(fileName: string, type: string | null, mime: string) { if (!fileName) { fileName = "untitled"; } @@ -182,7 +183,7 @@ function formatDownloadTitle(fileName: string, type: string, mime: string) { if (type === 'text') { return `${fileName}.html`; - } else if (['relationMap', 'canvas', 'search'].includes(type)) { + } else if (type && ['relationMap', 'canvas', 'search'].includes(type)) { return `${fileName}.json`; } else { if (!mime) { @@ -311,7 +312,7 @@ function isString(x: any) { return Object.prototype.toString.call(x) === "[object String]"; } -export = { +export default { randomSecureToken, randomString, md5, diff --git a/src/services/window.ts b/src/services/window.ts index ecc6395fb..e22ca382b 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -1,15 +1,18 @@ -import path = require('path'); -import url = require("url"); -import port = require('./port'); -import optionService = require('./options'); -import env = require('./env'); -import log = require('./log'); -import sqlInit = require('./sql_init'); -import cls = require('./cls'); -import keyboardActionsService = require('./keyboard_actions'); -import remoteMain = require("@electron/remote/main") +import path from "path"; +import url from "url"; +import port from "./port.js"; +import optionService from "./options.js"; +import env from "./env.js"; +import log from "./log.js"; +import sqlInit from "./sql_init.js"; +import cls from "./cls.js"; +import keyboardActionsService from "./keyboard_actions.js"; +import remoteMain from "@electron/remote/main/index.js" 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; @@ -193,7 +200,7 @@ function getMainWindow() { return mainWindow; } -export = { +export default { createMainWindow, createSetupWindow, closeSetupWindow, diff --git a/src/services/ws.ts b/src/services/ws.ts index ec7d47187..06ee20d58 100644 --- a/src/services/ws.ts +++ b/src/services/ws.ts @@ -1,21 +1,21 @@ -import WebSocket = require('ws'); -import utils = require('./utils'); -import log = require('./log'); -import sql = require('./sql'); -import cls = require('./cls'); -import config = require('./config'); -import syncMutexService = require('./sync_mutex'); -import protectedSessionService = require('./protected_session'); -import becca = require('../becca/becca'); -import AbstractBeccaEntity = require('../becca/entities/abstract_becca_entity'); +import WebSocket from "ws"; +import utils from "./utils.js"; +import log from "./log.js"; +import sql from "./sql.js"; +import cls from "./cls.js"; +import config from "./config.js"; +import syncMutexService from "./sync_mutex.js"; +import protectedSessionService from "./protected_session.js"; +import becca from "../becca/becca.js"; +import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; -import env = require('./env'); +import env from "./env.js"; import { IncomingMessage, Server } from 'http'; -import { EntityChange } from './entity_changes_interface'; +import { EntityChange } from './entity_changes_interface.js'; 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') @@ -275,7 +275,7 @@ function setLastSyncedPush(entityChangeId: number) { lastSyncedPush = entityChangeId; } -export = { +export default { init, sendMessageToAllClients, syncPushInProgress, diff --git a/src/share/content_renderer.ts b/src/share/content_renderer.ts index cb111008a..70cc5ceff 100644 --- a/src/share/content_renderer.ts +++ b/src/share/content_renderer.ts @@ -1,9 +1,9 @@ import { JSDOM } from "jsdom"; -import shaca = require('./shaca/shaca'); -import assetPath = require('../services/asset_path'); -import shareRoot = require('./share_root'); -import escapeHtml = require('escape-html'); -import SNote = require("./shaca/entities/snote"); +import shaca from "./shaca/shaca.js"; +import assetPath from "../services/asset_path.js"; +import shareRoot from "./share_root.js"; +import escapeHtml from "escape-html"; +import SNote from "./shaca/entities/snote.js"; interface Result { header: string; @@ -170,6 +170,6 @@ function renderFile(note: SNote, result: Result) { } } -export = { +export default { getContent }; diff --git a/src/share/routes.ts b/src/share/routes.ts index 97a0dd8e1..b491b5a7e 100644 --- a/src/share/routes.ts +++ b/src/share/routes.ts @@ -1,20 +1,21 @@ -import safeCompare = require('safe-compare'); -import ejs = require("ejs"); +import safeCompare from "safe-compare"; +import ejs from "ejs"; import type { Request, Response, Router } from "express"; -import shaca = require('./shaca/shaca'); -import shacaLoader = require('./shaca/shaca_loader'); -import shareRoot = require('./share_root'); -import contentRenderer = require('./content_renderer'); -import assetPath = require('../services/asset_path'); -import appPath = require('../services/app_path'); -import searchService = require('../services/search/services/search'); -import SearchContext = require('../services/search/search_context'); -import log = require('../services/log'); -import SNote = require('./shaca/entities/snote'); -import SBranch = require('./shaca/entities/sbranch'); -import SAttachment = require('./shaca/entities/sattachment'); +import shaca from "./shaca/shaca.js"; +import shacaLoader from "./shaca/shaca_loader.js"; +import shareRoot from "./share_root.js"; +import contentRenderer from "./content_renderer.js"; +import assetPath from "../services/asset_path.js"; +import appPath from "../services/app_path.js"; +import searchService from "../services/search/services/search.js"; +import SearchContext from "../services/search/search_context.js"; +import log from "../services/log.js"; +import SNote from "./shaca/entities/snote.js"; +import SBranch from "./shaca/entities/sbranch.js"; +import SAttachment from "./shaca/entities/sattachment.js"; +import utils from "../services/utils.js"; function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } { if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { @@ -249,8 +250,6 @@ function register(router: Router) { addNoIndexHeader(note, res); - const utils = require('../services/utils'); - const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); @@ -317,8 +316,6 @@ function register(router: Router) { addNoIndexHeader(attachment.note, res); - const utils = require('../services/utils'); - const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime); res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); @@ -383,6 +380,6 @@ function register(router: Router) { }); } -export = { +export default { register } diff --git a/src/share/shaca/entities/abstract_shaca_entity.ts b/src/share/shaca/entities/abstract_shaca_entity.ts index 20dba31ff..44b8efa6b 100644 --- a/src/share/shaca/entities/abstract_shaca_entity.ts +++ b/src/share/shaca/entities/abstract_shaca_entity.ts @@ -1,15 +1,10 @@ -import Shaca from "../shaca-interface"; - -let shaca: Shaca; +import shaca from "../shaca.js"; +import Shaca from "../shaca-interface.js"; class AbstractShacaEntity { get shaca(): Shaca { - if (!shaca) { - shaca = require('../shaca'); - } - return shaca; } } -export = AbstractShacaEntity; +export default AbstractShacaEntity; diff --git a/src/share/shaca/entities/sattachment.ts b/src/share/shaca/entities/sattachment.ts index 7951fe081..dc0ad7953 100644 --- a/src/share/shaca/entities/sattachment.ts +++ b/src/share/shaca/entities/sattachment.ts @@ -1,11 +1,11 @@ "use strict"; -import sql = require('../../sql'); -import utils = require('../../../services/utils'); -import AbstractShacaEntity = require('./abstract_shaca_entity'); -import SNote = require('./snote'); -import { Blob } from '../../../services/blob-interface'; -import { SAttachmentRow } from './rows'; +import sql from "../../sql.js"; +import utils from "../../../services/utils.js"; +import AbstractShacaEntity from "./abstract_shaca_entity.js"; +import SNote from "./snote.js"; +import { Blob } from '../../../services/blob-interface.js'; +import { SAttachmentRow } from './rows.js'; class SAttachment extends AbstractShacaEntity { private attachmentId: string; @@ -77,4 +77,4 @@ class SAttachment extends AbstractShacaEntity { } } -export = SAttachment; +export default SAttachment; diff --git a/src/share/shaca/entities/sattribute.ts b/src/share/shaca/entities/sattribute.ts index 6bd8418b1..2b7647e4e 100644 --- a/src/share/shaca/entities/sattribute.ts +++ b/src/share/shaca/entities/sattribute.ts @@ -1,9 +1,8 @@ "use strict"; -import { SAttributeRow } from "./rows"; -import SNote = require("./snote"); - -const AbstractShacaEntity = require('./abstract_shaca_entity'); +import AbstractShacaEntity from "./abstract_shaca_entity.js"; +import { SAttributeRow } from "./rows.js"; +import SNote from "./snote.js"; class SAttribute extends AbstractShacaEntity { @@ -110,4 +109,4 @@ class SAttribute extends AbstractShacaEntity { } } -export = SAttribute; +export default SAttribute; diff --git a/src/share/shaca/entities/sbranch.ts b/src/share/shaca/entities/sbranch.ts index b4ff9a73b..cb71ed780 100644 --- a/src/share/shaca/entities/sbranch.ts +++ b/src/share/shaca/entities/sbranch.ts @@ -1,8 +1,8 @@ "use strict"; -import AbstractShacaEntity = require('./abstract_shaca_entity'); -import { SBranchRow } from './rows'; -import SNote = require('./snote'); +import AbstractShacaEntity from "./abstract_shaca_entity.js"; +import { SBranchRow } from './rows.js'; +import SNote from "./snote.js"; class SBranch extends AbstractShacaEntity { @@ -59,4 +59,4 @@ class SBranch extends AbstractShacaEntity { } } -export = SBranch; +export default SBranch; diff --git a/src/share/shaca/entities/snote.ts b/src/share/shaca/entities/snote.ts index 18182f1d4..459b5d10f 100644 --- a/src/share/shaca/entities/snote.ts +++ b/src/share/shaca/entities/snote.ts @@ -1,14 +1,14 @@ "use strict"; -import sql = require('../../sql'); -import utils = require('../../../services/utils'); -import AbstractShacaEntity = require('./abstract_shaca_entity'); -import escape = require('escape-html'); -import { Blob } from '../../../services/blob-interface'; -import SAttachment = require('./sattachment'); -import SAttribute = require('./sattribute'); -import SBranch = require('./sbranch'); -import { SNoteRow } from './rows'; +import sql from "../../sql.js"; +import utils from "../../../services/utils.js"; +import AbstractShacaEntity from "./abstract_shaca_entity.js"; +import escape from "escape-html"; +import { Blob } from '../../../services/blob-interface.js'; +import SAttachment from "./sattachment.js"; +import SAttribute from "./sattribute.js"; +import SBranch from "./sbranch.js"; +import { SNoteRow } from './rows.js'; const LABEL = 'label'; const RELATION = 'relation'; @@ -27,7 +27,7 @@ class SNote extends AbstractShacaEntity { parentBranches: SBranch[]; parents: SNote[]; children: SNote[]; - private ownedAttributes: SAttribute[]; + ownedAttributes: SAttribute[]; private __attributeCache: SAttribute[] | null; private __inheritableAttributeCache: SAttribute[] | null; targetRelations: SAttribute[]; @@ -522,4 +522,4 @@ class SNote extends AbstractShacaEntity { } } -export = SNote; +export default SNote; diff --git a/src/share/shaca/shaca-interface.ts b/src/share/shaca/shaca-interface.ts index 9cff96eeb..f568e9cec 100644 --- a/src/share/shaca/shaca-interface.ts +++ b/src/share/shaca/shaca-interface.ts @@ -1,14 +1,14 @@ -import SAttachment = require("./entities/sattachment"); -import SAttribute = require("./entities/sattribute"); -import SBranch = require("./entities/sbranch"); -import SNote = require("./entities/snote"); +import SAttachment from "./entities/sattachment.js"; +import SAttribute from "./entities/sattribute.js"; +import SBranch from "./entities/sbranch.js"; +import SNote from "./entities/snote.js"; export default class Shaca { notes!: Record; branches!: Record; childParentToBranch!: Record; - private attributes!: Record; + attributes!: Record; attachments!: Record; aliasToNote!: Record; shareRootNote!: SNote | null; diff --git a/src/share/shaca/shaca.ts b/src/share/shaca/shaca.ts index d256b17e1..05f15b0b1 100644 --- a/src/share/shaca/shaca.ts +++ b/src/share/shaca/shaca.ts @@ -1,7 +1,7 @@ "use strict"; -import Shaca from "./shaca-interface"; +import Shaca from "./shaca-interface.js"; const shaca = new Shaca(); -export = shaca; +export default shaca; diff --git a/src/share/shaca/shaca_loader.ts b/src/share/shaca/shaca_loader.ts index 050e5e886..aab4bca24 100644 --- a/src/share/shaca/shaca_loader.ts +++ b/src/share/shaca/shaca_loader.ts @@ -1,15 +1,15 @@ "use strict"; -import sql = require('../sql'); -import shaca = require('./shaca'); -import log = require('../../services/log'); -import SNote = require('./entities/snote'); -import SBranch = require('./entities/sbranch'); -import SAttribute = require('./entities/sattribute'); -import SAttachment = require('./entities/sattachment'); -import shareRoot = require('../share_root'); -import eventService = require('../../services/events'); -import { SAttachmentRow, SAttributeRow, SBranchRow, SNoteRow } from './entities/rows'; +import sql from "../sql.js"; +import shaca from "./shaca.js"; +import log from "../../services/log.js"; +import SNote from "./entities/snote.js"; +import SBranch from "./entities/sbranch.js"; +import SAttribute from "./entities/sattribute.js"; +import SAttachment from "./entities/sattachment.js"; +import shareRoot from "../share_root.js"; +import eventService from "../../services/events.js"; +import { SAttachmentRow, SAttributeRow, SBranchRow, SNoteRow } from './entities/rows.js'; function load() { const start = Date.now(); @@ -92,7 +92,7 @@ eventService.subscribe([eventService.ENTITY_CREATED, eventService.ENTITY_CHANGED shaca.reset(); }); -export = { +export default { load, ensureLoad }; diff --git a/src/share/share_root.ts b/src/share/share_root.ts index a500d5ac4..453d5ae8f 100644 --- a/src/share/share_root.ts +++ b/src/share/share_root.ts @@ -1,3 +1,3 @@ -export = { +export default { SHARE_ROOT_NOTE_ID: '_share' } diff --git a/src/share/sql.ts b/src/share/sql.ts index a5465f4c2..87e9cf133 100644 --- a/src/share/sql.ts +++ b/src/share/sql.ts @@ -1,17 +1,22 @@ "use strict"; -import Database = require('better-sqlite3'); -import dataDir = require('../services/data_dir'); +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(); + } + }); }); }); @@ -27,7 +32,7 @@ function getColumn(query: string, params: string[] = []): T[] { return dbConnection.prepare(query).pluck().all(params) as T[]; } -export = { +export default { getRawRows, getRow, getColumn diff --git a/src/types.d.ts b/src/types.d.ts index 9fe04a204..a956b0e08 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -5,28 +5,28 @@ declare module 'unescape' { function unescape(str: string, type?: string): string; - export = unescape; + export default unescape; } declare module 'html2plaintext' { function html2plaintext(htmlText: string): string; - export = html2plaintext; + export default html2plaintext; } declare module 'normalize-strings' { function normalizeString(string: string): string; - export = normalizeString; + export default normalizeString; } declare module 'joplin-turndown-plugin-gfm' { - import TurndownService = require("turndown"); + import TurndownService from "turndown"; namespace gfm { function gfm(service: TurndownService): void; } - export = gfm; + export default gfm; } declare module 'is-animated' { function isAnimated(buffer: Buffer): boolean; - export = isAnimated; + export default isAnimated; } \ No newline at end of file diff --git a/src/www.ts b/src/www.ts index 3f9aa752e..3fc54e817 100644 --- a/src/www.ts +++ b/src/www.ts @@ -1,13 +1,26 @@ #!/usr/bin/env node +import app from "./app.js"; +import sessionParser from "./routes/session_parser.js"; +import fs from "fs"; +import http from "http"; +import https from "https"; +import config from "./services/config.js"; +import log from "./services/log.js"; +import appInfo from "./services/app_info.js"; +import ws from "./services/ws.js"; +import utils from "./services/utils.js"; +import port from "./services/port.js"; +import host from "./services/host.js"; +import semver from "semver"; // setup basic error handling even before requiring dependencies, since those can produce errors as well -process.on('unhandledRejection', error => { +process.on('unhandledRejection', (error: Error) => { // this makes sure that stacktrace of failed promise is printed out console.log(error); // but also try to log it into file - require('./services/log').info(error); + log.info(error); }); function exit() { @@ -18,19 +31,6 @@ function exit() { process.on('SIGINT', exit); process.on('SIGTERM', exit); -import app = require('./app'); -import sessionParser = require('./routes/session_parser'); -import fs = require('fs'); -import http = require('http'); -import https = require('https'); -import config = require('./services/config'); -import log = require('./services/log'); -import appInfo = require('./services/app_info'); -import ws = require('./services/ws'); -import utils = require('./services/utils'); -import port = require('./services/port'); -import host = require('./services/host'); -import semver = require('semver'); if (!semver.satisfies(process.version, ">=10.5.0")) { console.error("Trilium only supports node.js 10.5 and later"); @@ -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.js'); + electronRouting.default(app); } } diff --git a/tsconfig.json b/tsconfig.json index d9bbf4378..0d206e511 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,6 @@ { "compilerOptions": { - "moduleResolution": "Node16", - "module": "Node16", - "target": "ES2018", + "module": "NodeNext", "declaration": false, "sourceMap": true, "outDir": "./build", @@ -22,9 +20,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 bd7135e24..30293de06 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,7 +1,9 @@ -import path = require('path'); -import assetPath = require('./src/services/asset_path'); +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',