Files
parking_solution/apps/web/src/lib/desktop-updater.ts
T
julian 276b048fa9
Build desktop / desktop (push) Successful in 4m13s
Build & push images / images (push) Successful in 2m48s
CI / check (push) Successful in 42s
Release desktop / bundle (push) Successful in 4m37s
fix(desktop): sync tauri.conf.json version to the release tag, stop swallowing install failures
v0.1.1 was tagged but tauri.conf.json's own "version" field (what Tauri
bakes into the bundle filename/internal version) stayed at 0.1.0 — the
signed binary didn't match what latest.json claimed to describe, so every
update download failed signature verification. desktop-updater.ts's single
catch{} swallowed that identically to "offline", so it looked like nothing
happened at all. release.yml now syncs tauri.conf.json's version from the
git tag before building; the updater now logs a real post-accept failure
instead of silently reverting.
2026-09-03 12:24:04 +02:00

63 lines
2.6 KiB
TypeScript

// Desktop auto-update — prompt-on-update flow.
//
// Runs ONLY inside the Tauri desktop shell; a plain browser has no updater, so
// this is a guarded no-op there. On launch it checks the configured update
// endpoint (tauri.conf.json → plugins.updater); if a signed newer version is
// available it asks the operator, then downloads + installs and relaunches.
//
// The plugins are imported dynamically so the browser build never bundles them
// and never tries to resolve the Tauri APIs. Offline-first: a failed check (no
// network — the appliance is usually offline) is swallowed; updates only happen
// when someone has brought the box online (e.g. a phone hotspot) on purpose.
/** True when running inside the Tauri webview (not a normal browser). */
function inTauri(): boolean {
return typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
}
export interface UpdatePrompt {
/** Newer version string offered by the server. */
version: string;
/** Release notes, if the server provided them. */
notes?: string;
}
/**
* Check for an update. If one is available, calls `confirm` (your UI) with the
* version/notes; when it resolves true, downloads + installs and relaunches.
* No-op (resolves silently) in the browser or when no update / offline.
*/
export async function checkForDesktopUpdate(
confirm: (info: UpdatePrompt) => Promise<boolean>,
): Promise<void> {
if (!inTauri()) return;
try {
const { check } = await import("@tauri-apps/plugin-updater");
const update = await check();
if (!update) return; // up to date
const accepted = await confirm({ version: update.version, notes: update.body });
if (!accepted) return;
// Download + install the signed update (signature verified against the
// pubkey in tauri.conf.json), then relaunch into the new version.
try {
await update.downloadAndInstall();
} catch (err) {
// A real update WAS found and accepted — this is a genuine install
// failure (bad signature, corrupted download, disk/permission issue),
// not "offline". Surface it instead of silently reverting to the old
// version with no explanation.
console.error("desktop update download/install failed:", err);
throw err;
}
const { relaunch } = await import("@tauri-apps/plugin-process");
await relaunch();
} catch (err) {
// Offline / endpoint unreachable / no update server yet → ignore. The app
// keeps running on the current version; checking again next launch. Still
// log it so a real install failure (rethrown above) isn't invisible.
console.warn("desktop update check/apply skipped:", err);
}
}