From 1500d42cd2021feb0cf1600c2b1352e785d75c55 Mon Sep 17 00:00:00 2001 From: sravan Date: Wed, 1 Jul 2026 17:03:18 +0530 Subject: [PATCH] feat(desktop): packaging + self-hosted auto-update (electron-builder/updater) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - package.json build config: NSIS installer, app icon, generic publish provider → https://remote.bizgaze.com/downloads/ (self-hosted update feed). - main.js: electron-updater checks the feed on launch + every 6h, downloads in the background, installs on restart. Active only in packaged builds. - build/icon.ico app icon; PACKAGING.md documents build/release/signing. - Key design: web/UI changes reach installed apps instantly (they load the live server); only native shell changes need an auto-updated build. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 4 ++ desktop/PACKAGING.md | 51 ++++++++++++++++++ desktop/build/icon.ico | Bin 0 -> 270622 bytes desktop/main.js | 12 +++++ desktop/package-lock.json | 105 +++++++++++++++++++++++++++++++++++--- desktop/package.json | 22 ++++++-- 6 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 desktop/PACKAGING.md create mode 100644 desktop/build/icon.ico diff --git a/.gitignore b/.gitignore index 00df4bd..0fae3f3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,10 @@ out/ mobile/android/ mobile/ios/ +# Keep the desktop app icon (a build RESOURCE), even though the global build/ rule ignores it +!desktop/build/ +!desktop/build/** + # Runtime media (created at startup by config.js) server/recordings/ server/transcripts/ diff --git a/desktop/PACKAGING.md b/desktop/PACKAGING.md new file mode 100644 index 0000000..97fd9ed --- /dev/null +++ b/desktop/PACKAGING.md @@ -0,0 +1,51 @@ +# Biz Connect Desktop — packaging & updates + +## How updates reach installed apps (two kinds) + +1. **Web / UI / feature / bug-fix changes → instant, no app update.** + The app loads the live UI from `https://remote.bizgaze.com`. Deploy the server + (`./deploy.sh`) and every installed desktop app has it on next open/reload. This is ~95% + of all changes. +2. **Native shell changes (`main.js` / `preload.js`) → auto-update.** + Baked into the `.exe`. Shipped via **electron-updater** against a **self-hosted feed** on + `https://remote.bizgaze.com/downloads/`. On launch (and every 6h) the app checks + `latest.yml`, downloads a newer version in the background, and installs on next restart. + +## Build an installer +```bash +cd desktop +npm install +npm run dist # electron-builder → dist/ (Win: NSIS .exe + latest.yml + .blockmap) +``` +Output in `desktop/dist/`: +- `Biz Connect Setup .exe` — the installer +- `latest.yml` — the update manifest electron-updater reads +- `*.blockmap` — enables delta downloads + +The release build points at production (`SERVER_URL` defaults to `https://remote.bizgaze.com` +in `main.js`). + +## Publish a release (self-hosted feed) +1. Bump `version` in `desktop/package.json` (semver — electron-updater compares this). +2. `npm run dist`. +3. Upload **all** of `dist/` (the `.exe`, `latest.yml`, `.blockmap`) to whatever the server + serves at `https://remote.bizgaze.com/downloads/`. + - Behind Nginx Proxy Manager: point `/downloads/` at a static folder, or add a static + route in the app. The files are large binaries — host them on disk/volume, **not** git. +4. Installed apps pick it up within 6h (or on next launch). + +> First release: users install the `.exe` manually (download link on your site). Every +> release after that updates automatically. + +## Code signing (add when the cert is ready) +Unsigned installers work but trip Windows SmartScreen ("More info → Run anyway"). To sign: +- **Azure Trusted Signing** (recommended): set `win.azureSignOptions` (or use the + `@electron/windows-sign` path) with the Trusted Signing account/endpoint. Cloud, no token. +- **EV/OV cert (.pfx or token)**: set env `CSC_LINK` (path to .pfx) + `CSC_KEY_PASSWORD`, + or configure a hardware-token signing tool. electron-builder signs automatically. +Once signing is on, auto-updates are silent (no SmartScreen). + +## App identity +`appId` = `com.bizgaze.connect.desktop`; the NSIS installer registers this as the +AppUserModelID and creates a Start-menu shortcut — which is also the prerequisite for the +**Phase D inline-reply Windows Toast notifications** (see ../CLIENTS.md). diff --git a/desktop/build/icon.ico b/desktop/build/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..10744bd7c7d652562523c1ae39d1709a067fef34 GIT binary patch literal 270622 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 { @@ -93,6 +99,12 @@ app.whenReady().then(() => { createWindow(); Menu.setApplicationMenu(null); // hide the default menu bar; the web UI is the chrome app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); + // Check for shell updates on launch, then every 6 hours. Only in packaged builds. + if (app.isPackaged && autoUpdater) { + const check = () => autoUpdater.checkForUpdatesAndNotify().catch(() => {}); + check(); + setInterval(check, 6 * 60 * 60 * 1000); + } }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); }); diff --git a/desktop/package-lock.json b/desktop/package-lock.json index bd4c041..0c1f118 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "biz-connect-desktop", "version": "0.1.0", + "dependencies": { + "electron-updater": "^6.3.9" + }, "devDependencies": { "electron": "^31.0.0", "electron-builder": "^24.13.3" @@ -906,7 +909,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/assert-plus": { @@ -1515,7 +1517,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1990,6 +1991,82 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-updater": { + "version": "6.8.9", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.8.9.tgz", + "integrity": "sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig==", + "license": "MIT", + "dependencies": { + "builder-util-runtime": "9.7.0", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "~7.7.3", + "tiny-typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/builder-util-runtime": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz", + "integrity": "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/electron-updater/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-updater/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-updater/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-updater/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2476,7 +2553,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-flag": { @@ -2768,7 +2844,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, "funding": [ { "type": "github", @@ -2846,7 +2921,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "dev": true, "license": "MIT" }, "node_modules/lazystream": { @@ -2922,6 +2996,12 @@ "license": "MIT", "peer": true }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -2930,6 +3010,13 @@ "license": "MIT", "peer": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -3116,7 +3203,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/node-addon-api": { @@ -3475,7 +3561,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -3826,6 +3911,12 @@ "node": ">= 10.0.0" } }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "license": "MIT" + }, "node_modules/tmp": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", diff --git a/desktop/package.json b/desktop/package.json index be16b6f..7a5d242 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -7,6 +7,9 @@ "start": "electron .", "dist": "electron-builder" }, + "dependencies": { + "electron-updater": "^6.3.9" + }, "devDependencies": { "electron": "^31.0.0", "electron-builder": "^24.13.3" @@ -14,9 +17,20 @@ "build": { "appId": "com.bizgaze.connect.desktop", "productName": "Biz Connect", - "files": ["main.js", "preload.js", "assets/**"], - "win": { "target": "nsis" }, - "mac": { "target": "dmg", "category": "public.app-category.business" }, - "linux": { "target": "AppImage" } + "directories": { "buildResources": "build", "output": "dist" }, + "publish": [ + { "provider": "generic", "url": "https://remote.bizgaze.com/downloads/" } + ], + "win": { "target": "nsis", "icon": "build/icon.ico" }, + "nsis": { + "oneClick": false, + "perMachine": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "createStartMenuShortcut": true, + "shortcutName": "Biz Connect" + }, + "mac": { "target": "dmg", "category": "public.app-category.business", "icon": "build/icon.ico" }, + "linux": { "target": "AppImage", "category": "Network" } } }