From a3fde4daa17e7d1e5ea1f8eb908de3a2dab61f4d Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Thu, 23 Apr 2026 08:00:13 +0000 Subject: [PATCH] simplex-chat-nodejs: add PostgreSQL backend build support (#6845) * simplex-chat-nodejs: add PostgreSQL backend build support * simplex-chat-nodejs: fix postgres install command in README --- .github/workflows/build.yml | 114 +++++++++++++++++- packages/simplex-chat-nodejs/README.md | 26 ++++ .../simplex-chat-nodejs/src/download-libs.js | 27 ++++- scripts/desktop/build-lib-linux.sh | 9 +- 4 files changed, 168 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c6cb7a3a7..6c588f1f7a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -377,6 +377,100 @@ jobs: exit 1 fi +# ================================= +# Linux PostgreSQL Library Build +# ================================= + + build-linux-postgres: + name: "ubuntu-22.04-x86_64 (Postgres lib), GHC: ${{ needs.variables.outputs.GHC_VER }}" + needs: [maybe-release, variables] + runs-on: ubuntu-22.04 + if: startsWith(github.ref, 'refs/tags/v') + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Get UID and GID + id: ids + run: | + echo "uid=$(id -u)" >> $GITHUB_OUTPUT + echo "gid=$(id -g)" >> $GITHUB_OUTPUT + + - name: Free disk space + shell: bash + run: ./scripts/ci/linux_util_free_space.sh + + - name: Restore cached build + uses: actions/cache@v4 + with: + path: | + ~/.cabal/store + dist-newstyle + key: ubuntu-22.04-x86_64-postgres-ghc${{ needs.variables.outputs.GHC_VER }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }} + + - name: Set up Docker Buildx + uses: simplex-chat/docker-setup-buildx-action@v3 + + - name: Build and cache Docker image + uses: simplex-chat/docker-build-push-action@v6 + with: + context: . + load: true + file: Dockerfile.build + tags: build/22.04:latest + build-args: | + TAG=22.04 + HASH=sha256:5c8b2c0a6c745bc177669abfaa716b4bc57d58e2ea3882fb5da67f4d59e3dda5 + GHC=${{ needs.variables.outputs.GHC_VER }} + USER_UID=${{ steps.ids.outputs.uid }} + USER_GID=${{ steps.ids.outputs.gid }} + + - name: Start container + shell: bash + run: | + docker run -t -d \ + --name builder \ + -v ~/.cabal:/root/.cabal \ + -v /home/runner/work/_temp:/home/runner/work/_temp \ + -v ${{ github.workspace }}:/project \ + build/22.04:latest + + - name: Prepare cabal.project.local + shell: bash + run: | + echo "ignore-project: False" >> cabal.project.local + echo "package direct-sqlcipher" >> cabal.project.local + echo " flags: +openssl" >> cabal.project.local + + - name: Build postgres library + shell: docker exec -t builder sh -eu {0} + run: | + cabal clean + cabal update + scripts/desktop/build-lib-linux.sh postgres + + - name: Copy libs from container + shell: bash + run: | + ARCH=x86_64 + GHC_VER=${{ needs.variables.outputs.GHC_VER }} + BUILD_DIR=$(echo dist-newstyle/build/${ARCH}-linux/ghc-${GHC_VER}/simplex-chat-*) + mkdir -p postgres-libs + cp ${BUILD_DIR}/build/libsimplex.so postgres-libs/ + cp ${BUILD_DIR}/build/deps/* postgres-libs/ + + - name: Upload postgres libs artifact + uses: actions/upload-artifact@v4 + with: + name: simplex-libs-linux-postgres-x86_64 + path: postgres-libs/ + + - name: Fix permissions for cache + shell: bash + run: | + sudo chmod -R 777 dist-newstyle ~/.cabal + sudo chown -R $(id -u):$(id -g) dist-newstyle ~/.cabal + # ========================= # MacOS Build # ========================= @@ -613,7 +707,7 @@ jobs: release-nodejs-libs: runs-on: ubuntu-latest - needs: [build-linux, build-macos] + needs: [build-linux, build-linux-postgres, build-macos] if: startsWith(github.ref, 'refs/tags/v') && (!cancelled()) steps: - name: Checkout current repository @@ -622,6 +716,13 @@ jobs: - name: Install packages for archiving run: sudo apt install -y msitools gcc-mingw-w64 + - name: Download postgres libs artifact + if: needs.build-linux-postgres.result == 'success' + uses: actions/download-artifact@v4 + with: + name: simplex-libs-linux-postgres-x86_64 + path: ${{ runner.temp }}/postgres-libs + - name: Build archives run: | INIT_DIR='${{ runner.temp }}/artifacts' @@ -678,6 +779,17 @@ jobs: zip -r "${PREFIX}-windows-x86_64.zip" libs mv "${PREFIX}-windows-x86_64.zip" "$RELEASE_DIR" && cd "$INIT_DIR" + # Linux PostgreSQL (only if postgres build succeeded) + # ------------------------------------------------- + POSTGRES_LIBS='${{ runner.temp }}/postgres-libs' + if [ -d "$POSTGRES_LIBS" ]; then + mkdir -p linux-postgres/libs + cp "${POSTGRES_LIBS}"/*.so linux-postgres/libs/ + cd linux-postgres + zip -r "${PREFIX}-linux-x86_64-postgres.zip" libs + mv "${PREFIX}-linux-x86_64-postgres.zip" "$RELEASE_DIR" && cd "$INIT_DIR" + fi + - name: Create release in libs repo and upload artifacts uses: softprops/action-gh-release@v2 with: diff --git a/packages/simplex-chat-nodejs/README.md b/packages/simplex-chat-nodejs/README.md index e75dab3f96..ba5a758e0f 100644 --- a/packages/simplex-chat-nodejs/README.md +++ b/packages/simplex-chat-nodejs/README.md @@ -62,6 +62,32 @@ There is an example with more options in [./examples/squaring-bot.ts](./examples You can run it with: `npx ts-node ./examples/squaring-bot.ts` +## PostgreSQL backend + +By default, the package uses SQLite. To use PostgreSQL instead: + +```bash +npm install simplex-chat --simplex_backend=postgres +``` + +Or persist the setting in `.npmrc`: + +```ini +simplex_backend=postgres +``` + +### Prerequisites (PostgreSQL) + +- `libpq5` must be installed on the host system (`apt install libpq5` on Debian/Ubuntu) +- PostgreSQL backend is only available for Linux x86_64 +- A PostgreSQL server accessible via connection string + +### API difference + +With the PostgreSQL backend, `chatMigrateInit` arguments change meaning: +- First argument: schema prefix (instead of DB file prefix) +- Second argument: connection string (instead of encryption key) + ## Documentation The library docs are [here](./docs/README.md). diff --git a/packages/simplex-chat-nodejs/src/download-libs.js b/packages/simplex-chat-nodejs/src/download-libs.js index 25d4127ea4..bd30e8f56d 100644 --- a/packages/simplex-chat-nodejs/src/download-libs.js +++ b/packages/simplex-chat-nodejs/src/download-libs.js @@ -5,6 +5,18 @@ const extract = require('extract-zip'); const GITHUB_REPO = 'simplex-chat/simplex-chat-libs'; const RELEASE_TAG = 'v6.5.0-beta.9'; +const BACKEND = (process.env.SIMPLEX_BACKEND || process.env.npm_config_simplex_backend || 'sqlite').toLowerCase(); + +if (BACKEND !== 'sqlite' && BACKEND !== 'postgres') { + console.error(`✗ Invalid SIMPLEX_BACKEND: "${BACKEND}". Must be "sqlite" or "postgres".`); + process.exit(1); +} + +if (BACKEND === 'postgres' && (process.platform !== 'linux' || process.arch !== 'x64')) { + console.error(`✗ SIMPLEX_BACKEND=postgres is only supported on Linux x86_64.`); + process.exit(1); +} + const ROOT_DIR = process.cwd(); // Root of the package being installed const LIBS_DIR = path.join(ROOT_DIR, 'libs') const INSTALLED_FILE = path.join(LIBS_DIR, 'installed.txt'); @@ -56,11 +68,12 @@ function isAlreadyInstalled() { try { const installedVersion = fs.readFileSync(INSTALLED_FILE, 'utf-8').trim(); - if (installedVersion === RELEASE_TAG) { - console.log(`✓ Libraries version ${RELEASE_TAG} already installed`); + const expectedVersion = `${RELEASE_TAG}:${BACKEND}`; + if (installedVersion === expectedVersion) { + console.log(`✓ Libraries version ${RELEASE_TAG}:${BACKEND} already installed`); return true; } else { - console.log(`Version mismatch: installed ${installedVersion}, need ${RELEASE_TAG}`); + console.log(`Version mismatch: installed ${installedVersion}, need ${expectedVersion}`); cleanLibsDirectory(); return false; } @@ -79,12 +92,14 @@ async function install() { const { platformName, archName } = getPlatformInfo(); const repoName = GITHUB_REPO.split('/')[1]; - const zipFilename = `${repoName}-${platformName}-${archName}.zip`; + const backendSuffix = BACKEND === 'postgres' ? '-postgres' : ''; + const zipFilename = `${repoName}-${platformName}-${archName}${backendSuffix}.zip`; const ZIP_URL = `https://github.com/${GITHUB_REPO}/releases/download/${RELEASE_TAG}/${zipFilename}`; const ZIP_PATH = path.join(ROOT_DIR, zipFilename); const TEMP_EXTRACT_DIR = path.join(ROOT_DIR, '.temp-extract'); console.log(`Detected: ${platformName} ${archName}`); + console.log(`Backend: ${BACKEND}`); console.log(`Downloading: ${zipFilename}`); // Create libs directory @@ -124,8 +139,8 @@ async function install() { } // Write installed.txt with version - fs.writeFileSync(INSTALLED_FILE, RELEASE_TAG, 'utf-8'); - console.log(`✓ Wrote version ${RELEASE_TAG} to installed.txt`); + fs.writeFileSync(INSTALLED_FILE, `${RELEASE_TAG}:${BACKEND}`, 'utf-8'); + console.log(`✓ Wrote version ${RELEASE_TAG}:${BACKEND} to installed.txt`); // Cleanup fs.rmSync(TEMP_EXTRACT_DIR, { recursive: true, force: true }); diff --git a/scripts/desktop/build-lib-linux.sh b/scripts/desktop/build-lib-linux.sh index 7868a125b6..a2684b87d2 100755 --- a/scripts/desktop/build-lib-linux.sh +++ b/scripts/desktop/build-lib-linux.sh @@ -8,6 +8,7 @@ function readlink() { OS=linux ARCH="$(uname -m)" +DATABASE_BACKEND="${1:-sqlite}" GHC_VERSION=9.6.3 if [ "$ARCH" == "aarch64" ]; then @@ -25,7 +26,13 @@ for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done #rm -rf $BUILD_DIR -cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -optl-Wl,-soname,libsimplex.so -flink-rts -threaded' --constraint 'simplexmq +client_library' --constraint 'simplex-chat +client_library' +if [[ "$DATABASE_BACKEND" == "postgres" ]]; then + echo "Building with postgres backend..." + cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -optl-Wl,-soname,libsimplex.so -flink-rts -threaded' --constraint 'simplexmq +client_library +client_postgres' --constraint 'simplex-chat +client_library +client_postgres' +else + echo "Building with sqlite backend..." + cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -optl-Wl,-soname,libsimplex.so -flink-rts -threaded' --constraint 'simplexmq +client_library' --constraint 'simplex-chat +client_library' +fi cd $BUILD_DIR/build mv libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so libsimplex.so 2> /dev/null || true #patchelf --add-needed libHSrts_thr-ghc${GHC_VERSION}.so libsimplex.so