123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
- // SPDX-License-Identifier: Apache-2.0
- // SPDX-License-Identifier: MIT
- /**
- * Customize the auto updater flow.
- *
- * This package is also accessible with `window.__TAURI__.updater` when [`build.withGlobalTauri`](https://tauri.app/v1/api/config/#buildconfig.withglobaltauri) in `tauri.conf.json` is set to `true`.
- * @module
- */
- import { once, listen, emit, UnlistenFn } from './event'
- type UpdateStatus = 'PENDING' | 'ERROR' | 'DONE' | 'UPTODATE'
- interface UpdateStatusResult {
- error?: string
- status: UpdateStatus
- }
- interface UpdateManifest {
- version: string
- date: string
- body: string
- }
- interface UpdateResult {
- manifest?: UpdateManifest
- shouldUpdate: boolean
- }
- /**
- * Listen to an updater event.
- * @example
- * ```typescript
- * import { onUpdaterEvent } from "@tauri-apps/api/updater";
- * const unlisten = await onUpdaterEvent(({ error, status }) => {
- * console.log('Updater event', error, status);
- * });
- *
- * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
- * unlisten();
- * ```
- *
- * @param handler
- * @returns A promise resolving to a function to unlisten to the event.
- * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
- */
- async function onUpdaterEvent(
- handler: (status: UpdateStatusResult) => void
- ): Promise<UnlistenFn> {
- return listen('tauri://update-status', (data: { payload: any }) => {
- handler(data?.payload as UpdateStatusResult)
- })
- }
- /**
- * Install the update if there's one available.
- * @example
- * ```typescript
- * import { checkUpdate, installUpdate } from '@tauri-apps/api/updater';
- * const update = await checkUpdate();
- * if (update.shouldUpdate) {
- * console.log(`Installing update ${update.manifest?.version}, ${update.manifest?.date}, ${update.manifest.body}`);
- * await installUpdate();
- * }
- * ```
- *
- * @return A promise indicating the success or failure of the operation.
- */
- async function installUpdate(): Promise<void> {
- let unlistenerFn: UnlistenFn | undefined
- function cleanListener(): void {
- if (unlistenerFn) {
- unlistenerFn()
- }
- unlistenerFn = undefined
- }
- return new Promise((resolve, reject) => {
- function onStatusChange(statusResult: UpdateStatusResult): void {
- if (statusResult.error) {
- cleanListener()
- return reject(statusResult.error)
- }
- // install complete
- if (statusResult.status === 'DONE') {
- cleanListener()
- return resolve()
- }
- }
- // listen status change
- onUpdaterEvent(onStatusChange)
- .then((fn) => {
- unlistenerFn = fn
- })
- .catch((e) => {
- cleanListener()
- // dispatch the error to our checkUpdate
- throw e
- })
- // start the process we dont require much security as it's
- // handled by rust
- emit('tauri://update-install').catch((e) => {
- cleanListener()
- // dispatch the error to our checkUpdate
- throw e
- })
- })
- }
- /**
- * Checks if an update is available.
- * @example
- * ```typescript
- * import { checkUpdate } from '@tauri-apps/api/updater';
- * const update = await checkUpdate();
- * // now run installUpdate() if needed
- * ```
- *
- * @return Promise resolving to the update status.
- */
- async function checkUpdate(): Promise<UpdateResult> {
- let unlistenerFn: UnlistenFn | undefined
- function cleanListener(): void {
- if (unlistenerFn) {
- unlistenerFn()
- }
- unlistenerFn = undefined
- }
- return new Promise((resolve, reject) => {
- function onUpdateAvailable(manifest: UpdateManifest): void {
- cleanListener()
- return resolve({
- manifest,
- shouldUpdate: true
- })
- }
- function onStatusChange(statusResult: UpdateStatusResult): void {
- if (statusResult.error) {
- cleanListener()
- return reject(statusResult.error)
- }
- if (statusResult.status === 'UPTODATE') {
- cleanListener()
- return resolve({
- shouldUpdate: false
- })
- }
- }
- // wait to receive the latest update
- once('tauri://update-available', (data: { payload: any }) => {
- onUpdateAvailable(data?.payload as UpdateManifest)
- }).catch((e) => {
- cleanListener()
- // dispatch the error to our checkUpdate
- throw e
- })
- // listen status change
- onUpdaterEvent(onStatusChange)
- .then((fn) => {
- unlistenerFn = fn
- })
- .catch((e) => {
- cleanListener()
- // dispatch the error to our checkUpdate
- throw e
- })
- // start the process
- emit('tauri://update').catch((e) => {
- cleanListener()
- // dispatch the error to our checkUpdate
- throw e
- })
- })
- }
- export type { UpdateStatus, UpdateStatusResult, UpdateManifest, UpdateResult }
- export { onUpdaterEvent, installUpdate, checkUpdate }
|