diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml
index 0f85dd260..dca9bc3b8 100644
--- a/.github/actions/build-electron/action.yml
+++ b/.github/actions/build-electron/action.yml
@@ -1,3 +1,6 @@
+name: "Build Electron App"
+description: "Builds and packages the Electron app for different platforms"
+
inputs:
os:
description: "One of the supported platforms: macos, linux, windows"
@@ -6,34 +9,205 @@ inputs:
description: "The architecture to build for: x64, arm64"
required: true
extension:
- description: "Platform specific extension to build: dmg, deb, exe"
+ description: "Platform specific extensions to copy in the output: dmg, deb, rpm, exe, zip"
required: true
+
runs:
using: composite
steps:
- - name: Set up Python for appdmg to be installed
+ # Certificate setup
+ - name: Import Apple certificates
+ if: inputs.os == 'macos'
+ uses: apple-actions/import-codesign-certs@v2
+ with:
+ p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
+ p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
+ keychain: build
+ keychain-password: ${{ github.run_id }}
+
+ - name: Install Installer certificate
+ if: inputs.os == 'macos'
+ uses: apple-actions/import-codesign-certs@v2
+ with:
+ p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
+ p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
+ keychain: build
+ keychain-password: ${{ github.run_id }}
+ # We don't need to create a keychain here because we're using the build keychain that was created in the previous step
+ create-keychain: false
+
+ - name: Verify certificates
+ if: inputs.os == 'macos'
+ shell: bash
+ run: |
+ echo "Available signing identities:"
+ security find-identity -v -p codesigning build.keychain
+
+ - name: Set up Python and other macOS dependencies
if: ${{ inputs.os == 'macos' }}
shell: bash
- run: brew install python-setuptools
- - name: Install rpm on Ubuntu for RPM package building
+ run: |
+ brew install python-setuptools
+ brew install create-dmg
+
+ - name: Install dependencies for RPM and Flatpak package building
if: ${{ inputs.os == 'linux' }}
shell: bash
- run: sudo apt install rpm
+ run: |
+ sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils
+ flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
+ FLATPAK_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi)
+ FLATPAK_VERSION='24.08'
+ flatpak install --user --no-deps --arch $FLATPAK_ARCH --assumeyes runtime/org.freedesktop.Platform/$FLATPAK_ARCH/$FLATPAK_VERSION runtime/org.freedesktop.Sdk/$FLATPAK_ARCH/$FLATPAK_VERSION org.electronjs.Electron2.BaseApp/$FLATPAK_ARCH/$FLATPAK_VERSION
+
+ # Build setup
- name: Install dependencies
shell: bash
run: npm ci
+
- name: Update build info
shell: bash
- run: npm run update-build-info
- - name: Run electron-forge
+ run: npm run chore:update-build-info
+
+ # Critical debugging configuration
+ - name: Run electron-forge build with enhanced logging
shell: bash
- run: npm run make-electron -- --arch=${{ inputs.arch }}
+ env:
+ # Pass through required environment variables for signing and notarization
+ APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }}
+ APPLE_ID: ${{ env.APPLE_ID }}
+ APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
+ run: |
+ # Map OS names to Electron Forge platform names
+ if [ "${{ inputs.os }}" = "macos" ]; then
+ PLATFORM="darwin"
+ elif [ "${{ inputs.os }}" = "windows" ]; then
+ PLATFORM="win32"
+ else
+ PLATFORM="${{ inputs.os }}"
+ fi
+
+ npm run electron-forge:make -- \
+ --arch=${{ inputs.arch }} \
+ --platform=$PLATFORM
+
+ # Add DMG signing step
+ - name: Sign DMG
+ if: inputs.os == 'macos'
+ shell: bash
+ run: |
+ echo "Signing DMG file..."
+ dmg_file=$(find out -name "*.dmg" -print -quit)
+ if [ -n "$dmg_file" ]; then
+ echo "Found DMG: $dmg_file"
+ # Get the first valid signing identity from the keychain
+ SIGNING_IDENTITY=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
+ if [ -z "$SIGNING_IDENTITY" ]; then
+ echo "Error: No valid Developer ID Application certificate found in keychain"
+ exit 1
+ fi
+ echo "Using signing identity: $SIGNING_IDENTITY"
+ # Sign the DMG
+ codesign --force --sign "$SIGNING_IDENTITY" --options runtime --timestamp "$dmg_file"
+ # Notarize the DMG
+ xcrun notarytool submit "$dmg_file" --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait
+ # Staple the notarization ticket
+ xcrun stapler staple "$dmg_file"
+ else
+ echo "No DMG found to sign"
+ fi
+
+ - name: Verify code signing
+ if: inputs.os == 'macos'
+ shell: bash
+ run: |
+ echo "Verifying code signing for all artifacts..."
+
+ # First check the .app bundle
+ echo "Looking for .app bundle..."
+ app_bundle=$(find out -name "*.app" -print -quit)
+ if [ -n "$app_bundle" ]; then
+ echo "Found app bundle: $app_bundle"
+ echo "Verifying app bundle signing..."
+ codesign --verify --deep --strict --verbose=2 "$app_bundle"
+ echo "Displaying app bundle signing info..."
+ codesign --display --verbose=2 "$app_bundle"
+
+ echo "Checking entitlements..."
+ codesign --display --entitlements :- "$app_bundle"
+
+ echo "Checking notarization status..."
+ xcrun stapler validate "$app_bundle" || echo "Warning: App bundle not notarized yet"
+ else
+ echo "No .app bundle found to verify"
+ fi
+
+ # Then check DMG if it exists
+ echo "Looking for DMG..."
+ dmg_file=$(find out -name "*.dmg" -print -quit)
+ if [ -n "$dmg_file" ]; then
+ echo "Found DMG: $dmg_file"
+ echo "Verifying DMG signing..."
+ codesign --verify --deep --strict --verbose=2 "$dmg_file"
+ echo "Displaying DMG signing info..."
+ codesign --display --verbose=2 "$dmg_file"
+
+ echo "Checking DMG notarization..."
+ xcrun stapler validate "$dmg_file" || echo "Warning: DMG not notarized yet"
+ else
+ echo "No DMG found to verify"
+ fi
+
+ # Finally check ZIP if it exists
+ echo "Looking for ZIP..."
+ zip_file=$(find out -name "*.zip" -print -quit)
+ if [ -n "$zip_file" ]; then
+ echo "Found ZIP: $zip_file"
+ echo "Note: ZIP files are not code signed, but their contents should be"
+ fi
+
- name: Prepare artifacts
shell: bash
run: |
- mkdir -p upload;
- for ext in ${{ join(inputs.extension, ' ') }};
- do
- file=$(find out/make -name "*.$ext" -print -quit);
- cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.$ext";
- done
+ mkdir -p upload
+
+ if [ "${{ inputs.os }}" = "macos" ]; then
+ # For macOS, we need to look in specific directories based on the maker
+ echo "Collecting macOS artifacts..."
+
+ # Look for DMG files recursively
+ echo "Looking for DMG files..."
+ dmg_file=$(find out -name "*.dmg" -print -quit)
+ if [ -n "$dmg_file" ]; then
+ echo "Found DMG: $dmg_file"
+ cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ inputs.arch }}.dmg"
+ else
+ echo "Warning: No DMG file found"
+ fi
+
+ # Look for ZIP files recursively
+ echo "Looking for ZIP files..."
+ zip_file=$(find out -name "*.zip" -print -quit)
+ if [ -n "$zip_file" ]; then
+ echo "Found ZIP: $zip_file"
+ cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ inputs.arch }}.zip"
+ else
+ echo "Warning: No ZIP file found"
+ fi
+ else
+ # For other platforms, use the existing logic but with better error handling
+ echo "Collecting artifacts for ${{ inputs.os }}..."
+ for ext in ${{ inputs.extension }}; do
+ echo "Looking for .$ext files..."
+ file=$(find out -name "*.$ext" -print -quit)
+ if [ -n "$file" ]; then
+ echo "Found $file for extension $ext"
+ cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.$ext"
+ else
+ echo "Warning: No file found with extension .$ext"
+ fi
+ done
+ fi
+
+ echo "Final contents of upload directory:"
+ ls -la upload/
diff --git a/.github/actions/build-server/action.yml b/.github/actions/build-server/action.yml
index 162116e87..7423b8c4a 100644
--- a/.github/actions/build-server/action.yml
+++ b/.github/actions/build-server/action.yml
@@ -1,4 +1,7 @@
inputs:
+ os:
+ description: "One of the supported platforms: windows"
+ required: true
arch:
description: "The architecture to build for: x64, arm64"
required: true
@@ -18,11 +21,11 @@ runs:
MATRIX_ARCH: ${{ inputs.arch }}
shell: bash
run: |
- npm run update-build-info
+ npm run chore:update-build-info
./bin/build-server.sh
- name: Prepare artifacts
shell: bash
run: |
mkdir -p upload
file=$(find dist -name '*.tar.xz' -print -quit)
- cp "$file" "upload/TriliumNextNotes-linux-${{ inputs.arch }}-${{ github.ref_name }}.tar.xz"
+ cp "$file" "upload/TriliumNextNotes-Server-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.tar.xz"
diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml
index e3f2393b9..0c1be531a 100644
--- a/.github/workflows/main-docker.yml
+++ b/.github/workflows/main-docker.yml
@@ -33,7 +33,7 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v4
-
+
- name: Set IMAGE_NAME to lowercase
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
- name: Set TEST_TAG to lowercase
@@ -47,16 +47,16 @@ jobs:
with:
node-version: 20
cache: "npm"
-
+
- name: Install npm dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
-
+
- name: Run the TypeScript build
run: npx tsc
-
+
- name: Create server-package.json
run: cat package.json | grep -v electron > server-package.json
@@ -69,12 +69,12 @@ jobs:
tags: ${{ env.TEST_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
-
+
- name: Validate container run output
run: |
CONTAINER_ID=$(docker run -d --log-driver=journald --rm --network=host -e TRILIUM_PORT=8082 --volume ./integration-tests/db:/home/node/trilium-data --name trilium_local ${{ env.TEST_TAG }})
echo "Container ID: $CONTAINER_ID"
-
+
- name: Wait for the healthchecks to pass
uses: stringbean/docker-healthcheck-action@v3
with:
@@ -82,7 +82,7 @@ jobs:
wait-time: 50
require-status: running
require-healthy: true
-
+
- name: Run Playwright tests
run: TRILIUM_DOCKER=1 npx playwright test
- uses: actions/upload-artifact@v4
@@ -100,7 +100,20 @@ jobs:
build:
name: Build Docker images
- runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - dockerfile: Dockerfile.alpine
+ platform: linux/amd64
+ image: ubuntu-latest
+ - dockerfile: Dockerfile
+ platform: linux/arm64
+ image: ubuntu-24.04-arm
+ - dockerfile: Dockerfile
+ platform: linux/arm/v7
+ image: ubuntu-24.04-arm
+ runs-on: ${{ matrix.image }}
needs:
- test_docker
permissions:
@@ -108,16 +121,6 @@ jobs:
packages: write
attestations: write
id-token: write
- strategy:
- fail-fast: false
- matrix:
- include:
- - dockerfile: Dockerfile.alpine
- platform: linux/amd64
- - dockerfile: Dockerfile
- platform: linux/arm64
- - dockerfile: Dockerfile
- platform: linux/arm/v7
steps:
- name: Prepare
run: |
@@ -144,13 +147,13 @@ jobs:
type=sha
flavor: |
latest=false
-
+
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
+
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
+
- name: Set up node & dependencies
uses: actions/setup-node@v4
@@ -169,14 +172,14 @@ jobs:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
+
- name: Login to DockerHub
uses: docker/login-action@v3
with:
registry: ${{ env.DOCKERHUB_REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
+
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
@@ -186,13 +189,13 @@ jobs:
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
-
+
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
-
+
- name: Upload digest
uses: actions/upload-artifact@v4
with:
@@ -220,7 +223,7 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
+
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
@@ -237,14 +240,14 @@ jobs:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
+
- name: Login to DockerHub
uses: docker/login-action@v3
with:
registry: ${{ env.DOCKERHUB_REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
+
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
@@ -255,7 +258,7 @@ jobs:
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
$(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
-
+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
$(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
@@ -267,25 +270,25 @@ jobs:
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
$(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
-
+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
$(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
-
+
# Small delay to ensure stable tag is fully propagated
sleep 5
-
+
# Now update latest tags
docker buildx imagetools create \
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
-
+
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
-
+
fi
-
+
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 0a852bcd4..b469ac79b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -23,16 +23,46 @@ jobs:
os:
- name: macos
image: macos-latest
- extension: dmg
+ extension: [dmg, zip]
- name: linux
image: ubuntu-latest
- extension: deb
+ extension: [deb, rpm, zip, flatpak]
- name: windows
image: windows-latest
- extension: exe
+ extension: [exe, zip]
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
+
+ # Set up certificates and keychain for macOS
+ - name: Install Apple Certificates
+ if: matrix.os.name == 'macos'
+ env:
+ APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
+ APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
+ INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
+ INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
+ KEYCHAIN_PASSWORD: ${{ github.run_id }}
+ run: |
+ # Create keychain
+ security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+ security default-keychain -s build.keychain
+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+ security set-keychain-settings -t 3600 -u build.keychain
+
+ # Import application certificate
+ echo "$APP_CERTIFICATE_BASE64" | base64 --decode > application.p12
+ security import application.p12 -k build.keychain -P "$APP_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
+ rm application.p12
+
+ # Import installer certificate
+ echo "$INSTALLER_CERTIFICATE_BASE64" | base64 --decode > installer.p12
+ security import installer.p12 -k build.keychain -P "$INSTALLER_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
+ rm installer.p12
+
+ # Update keychain settings
+ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
+
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
@@ -43,6 +73,17 @@ jobs:
os: ${{ matrix.os.name }}
arch: ${{ matrix.arch }}
extension: ${{ matrix.os.extension }}
+ env:
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
+ APPLE_ID: ${{ secrets.APPLE_ID }}
+ APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
+
+ # Clean up keychain after build
+ - name: Clean up keychain
+ if: matrix.os.name == 'macos' && always()
+ run: |
+ security delete-keychain build.keychain
+
- name: Publish artifacts
uses: actions/upload-artifact@v4
with:
@@ -53,6 +94,7 @@ jobs:
with:
name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}.${{matrix.os.extension}}
path: upload/*.${{ matrix.os.extension }}
+
build_linux_server:
name: Build Linux Server
strategy:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index c0be60cd8..c339fd37d 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -20,13 +20,13 @@ jobs:
os:
- name: macos
image: macos-latest
- extension: dmg
+ extension: [dmg, zip]
- name: linux
image: ubuntu-latest
- extension: deb
+ extension: [deb, rpm, zip, flatpak]
- name: windows
image: windows-latest
- extension: exe
+ extension: [exe, zip]
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
@@ -38,32 +38,25 @@ jobs:
shell: bash
run: npm ci
- name: Update nightly version
- run: npm run ci-update-nightly-version
+ run: npm run chore:ci-update-nightly-version
- name: Run the build
uses: ./.github/actions/build-electron
with:
os: ${{ matrix.os.name }}
arch: ${{ matrix.arch }}
- extension: ${{ matrix.os.extension }}
- - run: find output
+ extension: ${{ join(matrix.os.extension, ' ') }}
- - name: Deploy release
- uses: WebFreak001/deploy-nightly@v3.2.0
+ - name: Publish release
+ uses: softprops/action-gh-release@v2
with:
- upload_url: ${{ env.GITHUB_UPLOAD_URL }}
- release_id: ${{ env.GITHUB_RELEASE_ID }}
- asset_path: upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.zip # path to archive to upload
- asset_name: TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}-nightly.zip # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
- asset_content_type: application/zip # required by GitHub API
+ make_latest: false
+ prerelease: true
+ draft: false
+ fail_on_unmatched_files: true
+ files: upload/*.*
+ tag_name: nightly
+ name: Nightly Build
- - name: Deploy installer release
- uses: WebFreak001/deploy-nightly@v3.2.0
- with:
- upload_url: ${{ env.GITHUB_UPLOAD_URL }}
- release_id: ${{ env.GITHUB_RELEASE_ID }}
- asset_path: upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }} # path to archive to upload
- asset_name: TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}-nightly.${{ matrix.os.extension }} # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
- asset_content_type: application/zip # required by GitHub API
nightly-server:
name: Deploy server nightly
strategy:
@@ -82,13 +75,16 @@ jobs:
- name: Run the build
uses: ./.github/actions/build-server
with:
+ os: linux
arch: ${{ matrix.arch }}
- - name: Deploy release
- uses: WebFreak001/deploy-nightly@v3.2.0
+ - name: Publish release
+ uses: softprops/action-gh-release@v2
with:
- upload_url: ${{ env.GITHUB_UPLOAD_URL }}
- release_id: ${{ env.GITHUB_RELEASE_ID }}
- asset_path: upload/TriliumNextNotes-linux-${{ matrix.arch }}-${{ github.ref_name }}.tar.xz # path to archive to upload
- asset_name: TriliumNextNotes-linux-${{ matrix.arch }}-nightly.zip # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
- asset_content_type: application/zip # required by GitHub API
+ make_latest: false
+ prerelease: true
+ draft: false
+ fail_on_unmatched_files: true
+ files: upload/*.*
+ tag_name: nightly
+ name: Nightly Build
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b806e4a09..dc523893b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,10 +23,10 @@ jobs:
extension: [dmg, zip]
- name: linux
image: ubuntu-latest
- extension: [deb, rpm, zip]
+ extension: [deb, rpm, zip, flatpak]
- name: windows
image: windows-latest
- extension: exe
+ extension: [exe, zip]
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
@@ -39,13 +39,23 @@ jobs:
with:
os: ${{ matrix.os.name }}
arch: ${{ matrix.arch }}
- extension: ${{ matrix.os.extension }}
+ extension: ${{ join(matrix.os.extension, ' ') }}
+ env:
+ APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
+ APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
+ APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
+ APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
+ APPLE_ID: ${{ secrets.APPLE_ID }}
+ APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
+
- name: Publish release
uses: softprops/action-gh-release@v2
with:
draft: true
fail_on_unmatched_files: true
files: upload/*.*
+
build_linux_server-x64:
name: Build Linux Server
strategy:
@@ -64,6 +74,7 @@ jobs:
- name: Run the build
uses: ./.github/actions/build-server
with:
+ os: linux
arch: ${{ matrix.arch }}
- name: Publish release
diff --git a/.gitignore b/.gitignore
index 09804755d..bc1575665 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.cache
.DS_Store
node_modules/
dist/
@@ -7,6 +8,7 @@ src/public/app-dist/
npm-debug.log
yarn-error.log
po-*/
+.flatpak-builder/
*.db
!integration-tests/db/document.db
diff --git a/.gitpod.yml b/.gitpod.yml
index 2b77be7b7..f87a115d0 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -4,7 +4,7 @@ image:
tasks:
- before: nvm install 20.15.1 && nvm use 20.15.1
init: npm install
- command: npm run start-server
+ command: npm run server:start
ports:
- port: 8080
diff --git a/.vscode/launch.json b/.vscode/launch.json
index f8d4780a1..cf21b9ce1 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -5,8 +5,8 @@
{
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
- "name": "nodemon start-server",
- "program": "${workspaceFolder}/src/www",
+ "name": "nodemon server:start",
+ "program": "${workspaceFolder}/src/main",
"request": "launch",
"restart": true,
"runtimeExecutable": "nodemon",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a9c07eb28..0733583d4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -18,5 +18,6 @@
"github-actions.workflows.pinned.workflows": [".github/workflows/nightly.yml"],
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features"
- }
+ },
+ "npm.exclude": ["**/build", "**/dist", "**/out/**"]
}
diff --git a/Dockerfile b/Dockerfile
index 959c244a9..365e4d07f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# Build stage
-FROM node:22.13.1-bullseye-slim AS builder
+FROM node:22.14.0-bullseye-slim AS builder
# Configure build dependencies in a single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -25,7 +25,7 @@ RUN cp -R build/src/* src/. && \
cp build/docker_healthcheck.js . && \
rm docker_healthcheck.ts && \
npm install && \
- npm run webpack && \
+ npm run build:webpack && \
npm prune --omit=dev && \
npm cache clean --force && \
cp -r src/public/app/doc_notes src/public/app-dist/. && \
@@ -36,7 +36,7 @@ RUN cp -R build/src/* src/. && \
rm -r build
# Runtime stage
-FROM node:22.13.1-bullseye-slim
+FROM node:22.14.0-bullseye-slim
# Install only runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
diff --git a/Dockerfile.alpine b/Dockerfile.alpine
index f7b49b94c..36d6f0b7b 100644
--- a/Dockerfile.alpine
+++ b/Dockerfile.alpine
@@ -1,5 +1,5 @@
# Build stage
-FROM node:22.13.1-alpine AS builder
+FROM node:22.14.0-alpine AS builder
# Configure build dependencies
RUN apk add --no-cache --virtual .build-dependencies \
@@ -24,7 +24,7 @@ RUN cp -R build/src/* src/. && \
cp build/docker_healthcheck.js . && \
rm docker_healthcheck.ts && \
npm install && \
- npm run webpack && \
+ npm run build:webpack && \
npm prune --omit=dev && \
npm cache clean --force && \
cp -r src/public/app/doc_notes src/public/app-dist/. && \
@@ -35,7 +35,7 @@ RUN cp -R build/src/* src/. && \
rm -r build
# Runtime stage
-FROM node:22.13.1-alpine
+FROM node:22.14.0-alpine
# Install runtime dependencies
RUN apk add --no-cache su-exec shadow
diff --git a/README-ZH_CN.md b/README-ZH_CN.md
index f6aa860b1..1f6bbaf55 100644
--- a/README-ZH_CN.md
+++ b/README-ZH_CN.md
@@ -78,7 +78,7 @@ Trilium 也提供 Flatpak:
```shell
npm install
-npm run start-server
+npm run server:start
```
## 👏 致谢
diff --git a/README.es.md b/README.es.md
index a2ea94144..bfa57fe45 100644
--- a/README.es.md
+++ b/README.es.md
@@ -86,7 +86,7 @@ Clone localmente y ejecute
```shell
npm install
-npm run start-server
+npm run server:start
```
## 👏 Reconocimientos
diff --git a/README.it.md b/README.it.md
index a778230c7..750027c1a 100644
--- a/README.it.md
+++ b/README.it.md
@@ -73,7 +73,7 @@ Clona localmente ed esegui
```shell
npm install
-npm run start-server
+npm run server:start
```
## 👏 Riconoscimenti
diff --git a/README.ja.md b/README.ja.md
index 110b779c5..757638770 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -54,7 +54,7 @@ Trilium は Flatpak としても提供されます:
```shell
npm install
-npm run start-server
+npm run server:start
```
## 📢 シャウトアウト
diff --git a/README.md b/README.md
index 1800f667e..0170c8135 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,7 @@ You can also read [Patterns of personal knowledge base](https://triliumnext.gith
git clone https://github.com/TriliumNext/Notes.git
cd Notes
npm install
-npm run start-server
+npm run server:start
```
### Documentation
@@ -118,8 +118,10 @@ Head on over to our [Docs repo](https://github.com/TriliumNext/Docs)
## 🤝 Support
-You can support the original Trilium developer using GitHub Sponsors, [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
-Support for the TriliumNext organization will be possible in the near future.
+Support for the TriliumNext organization will be possible in the near future. For now, you can:
+- Support continued development on TriliumNext by supporting our developers: [eliandoran](https://github.com/sponsors/eliandoran) (See the [repository insights]([developers]([url](https://github.com/TriliumNext/Notes/graphs/contributors))) for a full list)
+- Show a token of gratitude to the original Trilium developer ([zadam](https://github.com/sponsors/zadam)) via [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
+
## 🔑 License
diff --git a/README.ru.md b/README.ru.md
index d78738915..e2336efb3 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -44,7 +44,7 @@ Trilium предоставляется в виде десктопного при
```shell
npm install
-npm run start-server
+npm run server:start
```
## 👏 Благодарности
diff --git a/bin/copy-dist.ts b/bin/copy-dist.ts
index 6ffc2cf98..2a2b75d56 100644
--- a/bin/copy-dist.ts
+++ b/bin/copy-dist.ts
@@ -7,9 +7,9 @@ const DEST_DIR_NODE_MODULES = path.join(DEST_DIR, "node_modules");
const VERBOSE = process.env.VERBOSE;
-function log(...args) {
+function log(...args: any[]) {
if (VERBOSE) {
- console.log(args);
+ console.log(...args);
}
}
@@ -29,7 +29,12 @@ const copy = async () => {
fs.copySync(path.join("build", srcFile), destFile, { recursive: true });
}
- const filesToCopy = ["config-sample.ini", "tsconfig.webpack.json"];
+ const filesToCopy = [
+ "config-sample.ini",
+ "tsconfig.webpack.json",
+ "./src/etapi/etapi.openapi.yaml",
+ "./src/routes/api/openapi.json"
+ ];
for (const file of filesToCopy) {
log(`Copying ${file}`);
await fs.copy(file, path.join(DEST_DIR, file));
@@ -90,7 +95,6 @@ const copy = async () => {
"node_modules/mark.js/dist/",
"node_modules/normalize.css/",
"node_modules/jquery.fancytree/dist/",
- "node_modules/bootstrap/dist/",
"node_modules/autocomplete.js/dist/",
"node_modules/codemirror/lib/",
"node_modules/codemirror/addon/",
diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh
index 221e8a0ea..e1d0e197f 100755
--- a/bin/copy-trilium.sh
+++ b/bin/copy-trilium.sh
@@ -23,7 +23,7 @@ rm -rf "$DIR"
mkdir -pv "$DIR"
echo Webpack start
-npm run webpack
+npm run build:webpack
echo Webpack finish
echo "Copying Trilium to build directory $DIR"
diff --git a/bin/generate-openapi.ts b/bin/generate-openapi.ts
new file mode 100644
index 000000000..4bd97a76f
--- /dev/null
+++ b/bin/generate-openapi.ts
@@ -0,0 +1,189 @@
+import { fileURLToPath } from "url";
+import { dirname, join } from "path";
+import swaggerJsdoc from 'swagger-jsdoc';
+import fs from "fs";
+
+/*
+ * Usage: npm run generate-openapi | tail -n1 > x.json
+ *
+ * Inspect generated file by opening it in https://editor-next.swagger.io/
+ *
+ */
+
+const options = {
+ definition: {
+ openapi: '3.1.1',
+ info: {
+ title: 'Trilium Notes - Sync server API',
+ version: '0.96.6',
+ description: "This is the internal sync server API used by Trilium Notes / TriliumNext Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts).",
+ contact: {
+ name: "TriliumNext issue tracker",
+ url: "https://github.com/TriliumNext/Notes/issues",
+ },
+ license: {
+ name: "GNU Free Documentation License 1.3 (or later)",
+ url: "https://www.gnu.org/licenses/fdl-1.3",
+ },
+ },
+ },
+ apis: [
+ // Put individual files here to have them ordered first.
+ './src/routes/api/setup.ts',
+ // all other files
+ './src/routes/api/*.ts', './bin/generate-openapi.js'
+ ],
+};
+
+const openapiSpecification = swaggerJsdoc(options);
+const scriptDir = dirname(fileURLToPath(import.meta.url));
+const outputPath = join(scriptDir, "..", "src", "routes", "api", "openapi.json");
+fs.writeFileSync(outputPath, JSON.stringify(openapiSpecification));
+console.log("Saved to ", outputPath);
+
+/**
+ * @swagger
+ * tags:
+ * - name: auth
+ * description: Authentication
+ * - name: sync
+ * description: Synchronization
+ * - name: data
+ */
+
+/**
+ * @swagger
+ * components:
+ * schemas:
+ * Attribute:
+ * type: object
+ * properties:
+ * attributeId:
+ * type: string
+ * example: "4G1DPrI58PAb"
+ * noteId:
+ * $ref: "#/components/schemas/NoteId"
+ * type:
+ * type: string
+ * enum: ["attribute", "relation"]
+ * name:
+ * type: string
+ * example: "internalLink"
+ * value:
+ * type: string
+ * example: "hA8aHSpTRdZ6"
+ * description: "If type = \"relation\", a note ID. Otherwise, the attribute content."
+ * position:
+ * type: integer
+ * example: 20
+ * isInheritable:
+ * type: boolean
+ * Blob:
+ * type: object
+ * properties:
+ * blobId:
+ * type: string
+ * example: "8iqMIB8eiY1tPYmElfjm"
+ * content:
+ * type:
+ * - string
+ * - 'null'
+ * description: "`null` if not text."
+ * contentLength:
+ * type: integer
+ * dateModified:
+ * $ref: "#/components/schemas/DateTime"
+ * utcDateModified:
+ * $ref: "#/components/schemas/UtcDateTime"
+ * Branch:
+ * type: object
+ * properties:
+ * branchId:
+ * $ref: "#/components/schemas/BranchId"
+ * noteId:
+ * $ref: "#/components/schemas/NoteId"
+ * parentNoteId:
+ * $ref: "#/components/schemas/NoteId"
+ * notePosition:
+ * type: integer
+ * example: 20
+ * prefix:
+ * type:
+ * - string
+ * - 'null'
+ * isExpanded:
+ * type: boolean
+ * BranchId:
+ * type: string
+ * example: "WUjhaGp4EKah_ur11rSfHkzeV"
+ * description: Equal to `{parentNoteId}_{noteId}`
+ * DateTime:
+ * type: string
+ * example: "2025-02-14 08:19:59.203+0100"
+ * EntityChange:
+ * type: object
+ * properties:
+ * entityChange:
+ * type: object
+ * properties:
+ * entityName:
+ * type: string
+ * example: "notes"
+ * description: Database table for this entity.
+ * changeId:
+ * type: string
+ * example: "changeId9630"
+ * description: ID, referenced in `entity_changes` table.
+ * entity:
+ * type: object
+ * description: Encoded entity data. Object has one property for each database column.
+ * Note:
+ * type: object
+ * properties:
+ * noteId:
+ * $ref: "#/components/schemas/NoteId"
+ * title:
+ * type: string
+ * isProtected:
+ * type: boolean
+ * type:
+ * type: string
+ * example: "text"
+ * enum: ["text", "code", "render", "file", "image", "search", "relationMap", "book", "noteMap", "mermaid", "canvas", "webView", "launcher", "doc", "contentWidget", "mindMap", "geoMap"]
+ * description: "[Reference list](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/note_types.ts)"
+ * mime:
+ * type: string
+ * example: "text/html"
+ * blobId:
+ * type: string
+ * example: "z4PhNX7vuL3xVChQ1m2A"
+ * NoteId:
+ * type: string
+ * example: "ur11rSfHkzeV"
+ * description: "12-character note ID. Special values: \"none\"`, `\"root\"."
+ * Timestamps:
+ * type: object
+ * properties:
+ * dateCreated:
+ * $ref: "#/components/schemas/DateTime"
+ * dateModified:
+ * $ref: "#/components/schemas/DateTime"
+ * utcDateCreated:
+ * $ref: "#/components/schemas/UtcDateTime"
+ * utcDateModified:
+ * $ref: "#/components/schemas/UtcDateTime"
+ * UtcDateTime:
+ * type: string
+ * example: "2025-02-13T07:42:47.698Z"
+ * description: "Result of `new Date().toISOString().replace('T', ' ')`"
+ * securitySchemes:
+ * user-password:
+ * type: apiKey
+ * name: trilium-cred
+ * in: header
+ * description: "Username and password, formatted as `user:password`"
+ * session:
+ * type: apiKey
+ * in: cookie
+ * name: trilium.sid
+ */
diff --git a/bin/release.sh b/bin/release.sh
index fea1e030f..6d7093bc2 100755
--- a/bin/release.sh
+++ b/bin/release.sh
@@ -1,7 +1,5 @@
#!/usr/bin/env bash
-export GITHUB_REPO=trilium
-
if [[ $# -eq 0 ]] ; then
echo "Missing argument of new version"
exit 1
@@ -32,7 +30,7 @@ mv package.json.tmp package.json
git add package.json
-npm run update-build-info
+npm run chore:update-build-info
git add src/services/build.ts
@@ -40,10 +38,18 @@ TAG=v$VERSION
echo "Committing package.json version change"
-git commit -m "release $VERSION"
+git commit -m "chore(release): $VERSION"
git push
echo "Tagging commit with $TAG"
git tag $TAG
git push origin $TAG
+
+echo "Updating master"
+
+git fetch
+git checkout master
+git reset --hard origin/master
+git merge origin/develop
+git push
\ No newline at end of file
diff --git a/config-sample.ini b/config-sample.ini
index 90c7fa17e..baa026730 100644
--- a/config-sample.ini
+++ b/config-sample.ini
@@ -28,6 +28,21 @@ keyPath=
# expressjs shortcuts are supported: loopback(127.0.0.1/8, ::1/128), linklocal(169.254.0.0/16, fe80::/10), uniquelocal(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7)
trustedReverseProxy=false
+
+[Session]
+# Use this setting to set a custom value for the "Path" Attribute value of the session cookie.
+# This can be useful, when you have several instances running on the same domain, under different paths (e.g. by using a reverse proxy).
+# It prevents your instances from overwriting each others' cookies, allowing you to stay logged in multiple instances simultanteously.
+# E.g. if you have instances running under https://your-domain.com/triliumNext/instanceA and https://your-domain.com/triliumNext/instanceB
+# you would want to set the cookiePath value to "/triliumNext/instanceA" for your first and "/triliumNext/instanceB" for your second instance
+cookiePath=/
+
+# Use this setting to set a custom value for the "Max-Age" Attribute of the session cookie.
+# This controls how long your session will be valid, before it expires and you need to log in again, when you use the "Remember Me" option.
+# Value needs to be entered in Seconds.
+# Default value is 1814400 Seconds, which is 21 Days.
+cookieMaxAge=1814400
+
[Sync]
#syncServerHost=
#syncServerTimeout=
diff --git a/db/demo.zip b/db/demo.zip
index b972fedd2..39c0875fe 100644
Binary files a/db/demo.zip and b/db/demo.zip differ
diff --git a/db/migrations/0229__tasks.sql b/db/migrations/0229__tasks.sql
new file mode 100644
index 000000000..4d0381db2
--- /dev/null
+++ b/db/migrations/0229__tasks.sql
@@ -0,0 +1,10 @@
+CREATE TABLE IF NOT EXISTS "tasks"
+(
+ "taskId" TEXT NOT NULL PRIMARY KEY,
+ "parentNoteId" TEXT NOT NULL,
+ "title" TEXT NOT NULL DEFAULT "",
+ "dueDate" INTEGER,
+ "isDone" INTEGER NOT NULL DEFAULT 0,
+ "isDeleted" INTEGER NOT NULL DEFAULT 0,
+ "utcDateModified" TEXT NOT NULL
+);
\ No newline at end of file
diff --git a/db/schema.sql b/db/schema.sql
index 1b4c46321..77361f5ed 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -132,3 +132,14 @@ CREATE INDEX IDX_attachments_ownerId_role
CREATE INDEX IDX_notes_blobId on notes (blobId);
CREATE INDEX IDX_revisions_blobId on revisions (blobId);
CREATE INDEX IDX_attachments_blobId on attachments (blobId);
+
+CREATE TABLE IF NOT EXISTS "tasks"
+(
+ "taskId" TEXT NOT NULL PRIMARY KEY,
+ "parentNoteId" TEXT NOT NULL,
+ "title" TEXT NOT NULL DEFAULT "",
+ "dueDate" INTEGER,
+ "isDone" INTEGER NOT NULL DEFAULT 0,
+ "isDeleted" INTEGER NOT NULL DEFAULT 0,
+ "utcDateModified" TEXT NOT NULL
+);
\ No newline at end of file
diff --git a/docs/X4N03xLYEWnN.html b/docs/X4N03xLYEWnN.html
index 2b686480d..b8e844cba 100644
--- a/docs/X4N03xLYEWnN.html
+++ b/docs/X4N03xLYEWnN.html
@@ -38,12 +38,12 @@
-
The native node bindings
better-sqlite3 has native Node bindings. With updates of better-sqlite3, but also of Electron and Node.js versions, these bindings need to be updated.
Note that Electron and Node.js versions need different versions of these bindings, since Electron usually packs a different version of Node.js.
During development, npm install tries to build or reuse prebuilt natives for the current Node.js version. This makes npm run start-server work out of the box. Trying to run npm run start-electron with these versions generally causes an error such as this:
Uncaught Exception:
+ The native node bindings
better-sqlite3 has native Node bindings. With updates of better-sqlite3, but also of Electron and Node.js versions, these bindings need to be updated.
Note that Electron and Node.js versions need different versions of these bindings, since Electron usually packs a different version of Node.js.
During development, npm install tries to build or reuse prebuilt natives for the current Node.js version. This makes npm run server:start work out of the box. Trying to run npm run electron:start with these versions generally causes an error such as this:
Uncaught Exception:
Error: The module '/Users/elian/Projects/Notes/node_modules/better-sqlite3/build/Release/better_sqlite3.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 108. This version of Node.js requires
NODE_MODULE_VERSION 116. Please try re-compiling or re-installing
-the module (for instance, using `npm rebuild` or `npm install`).
How the natives are handled
Locally, this can be fixed by rebuilding the binaries, which is what npm run switch-electron does, which uses electron-rebuild under the hood.
When the deliveries are built (see Build deliveries locally), it is not feasible to rebuild the dependencies since we are building for multiple platforms. Luckily, better-sqlite3 provides these prebuilt binaries from us, available as artifacts on their GitHub releases page.
The build script manages the natives for better-sqlite3 by keeping a copy of the .node file for every platform in bin/better-sqlite3.
Whenever the version of better-sqlite3 changes, the .node files must also be renewed based on their releases page. To simplify this process, a script was created in bin/better-sqlite3/update.sh.
How to update the natives
The update script needs to know the version of Electron or Node.js for which to download the prebuilt binaries.
If you get errors during download, check on the releases page to ensure that this particular combination of Electron/Node actually exists for the given release.
To determine the NODE_MODULE_VERSION that is required, look for This version of Node.js requires
NODE_MODULE_VERSION in the error when starting Trilium via:
npm run start-electron (or run any Electron delivery), case in which the ELECTRON_VERSION variable needs to be changed.npm run start-server (or run the Linux server delivery), case in which the NODE_VERSION variable needs to be changed.
Check which files got changed after running the update script and for each platform that got changed, test it locally via Build deliveries locally or via the CI.
+the module (for instance, using `npm rebuild` or `npm install`).
How the natives are handled
Locally, this can be fixed by rebuilding the binaries, which is what npm run electron:switch does, which uses electron-rebuild under the hood.
When the deliveries are built (see Build deliveries locally), it is not feasible to rebuild the dependencies since we are building for multiple platforms. Luckily, better-sqlite3 provides these prebuilt binaries from us, available as artifacts on their GitHub releases page.
The build script manages the natives for better-sqlite3 by keeping a copy of the .node file for every platform in bin/better-sqlite3.
Whenever the version of better-sqlite3 changes, the .node files must also be renewed based on their releases page. To simplify this process, a script was created in bin/better-sqlite3/update.sh.
How to update the natives
The update script needs to know the version of Electron or Node.js for which to download the prebuilt binaries.
If you get errors during download, check on the releases page to ensure that this particular combination of Electron/Node actually exists for the given release.
To determine the NODE_MODULE_VERSION that is required, look for This version of Node.js requires
NODE_MODULE_VERSION in the error when starting Trilium via:
npm run electron:start (or run any Electron delivery), case in which the ELECTRON_VERSION variable needs to be changed.npm run server:start (or run the Linux server delivery), case in which the NODE_VERSION variable needs to be changed.
Check which files got changed after running the update script and for each platform that got changed, test it locally via Build deliveries locally or via the CI.
diff --git a/docs/XxqZW6JjkW2g.html b/docs/XxqZW6JjkW2g.html
index 3307c8c4f..25b34176c 100644
--- a/docs/XxqZW6JjkW2g.html
+++ b/docs/XxqZW6JjkW2g.html
@@ -38,7 +38,7 @@
-
Server live reload
If running the server using npm run start-server, the server will watch for changes in src/public and trigger a frontend reload if that occurs.
Electron live reload
Similarly, npm run start-electron supports live refresh as well.
However, a core difference is that Electron watches dist/src/public instead of src/public since Electron runs on its own copy of the files.
To ameliorate that, a separate watch script has been implemented which automatically copies files from src/public to dist/src/public whenever a change is detected. To run it:
npm run
Technical details
- This mechanism is managed at server level by watching for changes in
services/ws.ts.
+
Server live reload
If running the server using npm run server:start, the server will watch for changes in src/public and trigger a frontend reload if that occurs.
Electron live reload
Similarly, npm run electron:start supports live refresh as well.
However, a core difference is that Electron watches dist/src/public instead of src/public since Electron runs on its own copy of the files.
To ameliorate that, a separate watch script has been implemented which automatically copies files from src/public to dist/src/public whenever a change is detected. To run it:
npm run
Technical details
- This mechanism is managed at server level by watching for changes in
services/ws.ts.
diff --git a/docs/backend_api/index.html b/docs/backend_api/index.html
index 612058e6f..6c27bd07a 100644
--- a/docs/backend_api/index.html
+++ b/docs/backend_api/index.html
@@ -71,7 +71,7 @@