mirror of
https://github.com/tauri-apps/tauri-plugin-updater.git
synced 2026-01-31 00:55:19 +01:00
feat(updater): allow passing headers & timeout in Update.download* methods (#1661)
closes #1634 Committed via a GitHub action: https://github.com/tauri-apps/plugins-workspace/actions/runs/10673433181 Co-authored-by: amrbashir <amrbashir@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function s(e,t,s,n,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var n,i,r,a;"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.set(this,0),r.set(this,{}),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:a})=>{if(a===t(this,i,"f")){s(this,i,a+1),t(this,n,"f").call(this,e);const o=Object.keys(t(this,r,"f"));if(o.length>0){let e=a+1;for(const s of o.sort()){if(parseInt(s)!==e)break;{const i=t(this,r,"f")[s];delete t(this,r,"f")[s],t(this,n,"f").call(this,i),e+=1}}s(this,i,e)}}else t(this,r,"f")[a.toString()]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}async function d(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}n=new WeakMap,i=new WeakMap,r=new WeakMap;class l{get rid(){return t(this,a,"f")}constructor(e){a.set(this,void 0),s(this,a,e)}async close(){return d("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;class c extends l{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body}async download(e){const t=new o;e&&(t.onmessage=e);const s=await d("plugin:updater|download",{onEvent:t,rid:this.rid});this.downloadedBytes=new l(s)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await d("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e){const t=new o;e&&(t.onmessage=e),await d("plugin:updater|download_and_install",{onEvent:t,rid:this.rid})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=c,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await d("plugin:updater|check",{...e}).then((e=>e.available?new c(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function s(e,t,s,n,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var n,i,r,a;"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.set(this,0),r.set(this,{}),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:a})=>{if(a===t(this,i,"f")){s(this,i,a+1),t(this,n,"f").call(this,e);const o=Object.keys(t(this,r,"f"));if(o.length>0){let e=a+1;for(const s of o.sort()){if(parseInt(s)!==e)break;{const i=t(this,r,"f")[s];delete t(this,r,"f")[s],t(this,n,"f").call(this,i),e+=1}}s(this,i,e)}}else t(this,r,"f")[a.toString()]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}async function d(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}n=new WeakMap,i=new WeakMap,r=new WeakMap;class l{get rid(){return t(this,a,"f")}constructor(e){a.set(this,void 0),s(this,a,e)}async close(){return d("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;class c extends l{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body}async download(e,t){const s=new o;e&&(s.onmessage=e);const n=await d("plugin:updater|download",{onEvent:s,rid:this.rid,...t});this.downloadedBytes=new l(n)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await d("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){const s=new o;e&&(s.onmessage=e),await d("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=c,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await d("plugin:updater|check",{...e}).then((e=>e.available?new c(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
|
||||
|
||||
@@ -15,7 +15,7 @@ class Update extends core.Resource {
|
||||
this.body = metadata.body;
|
||||
}
|
||||
/** Download the updater package */
|
||||
async download(onEvent) {
|
||||
async download(onEvent, options) {
|
||||
const channel = new core.Channel();
|
||||
if (onEvent) {
|
||||
channel.onmessage = onEvent;
|
||||
@@ -23,6 +23,7 @@ class Update extends core.Resource {
|
||||
const downloadedBytesRid = await core.invoke("plugin:updater|download", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
this.downloadedBytes = new core.Resource(downloadedBytesRid);
|
||||
}
|
||||
@@ -39,7 +40,7 @@ class Update extends core.Resource {
|
||||
this.downloadedBytes = undefined;
|
||||
}
|
||||
/** Downloads the updater package and installs it */
|
||||
async downloadAndInstall(onEvent) {
|
||||
async downloadAndInstall(onEvent, options) {
|
||||
const channel = new core.Channel();
|
||||
if (onEvent) {
|
||||
channel.onmessage = onEvent;
|
||||
@@ -47,6 +48,7 @@ class Update extends core.Resource {
|
||||
await core.invoke("plugin:updater|download_and_install", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
async close() {
|
||||
|
||||
21
dist-js/index.d.ts
vendored
21
dist-js/index.d.ts
vendored
@@ -1,12 +1,12 @@
|
||||
import { Resource } from "@tauri-apps/api/core";
|
||||
/** Options used to check for updates */
|
||||
/** Options used when checking for updates */
|
||||
interface CheckOptions {
|
||||
/**
|
||||
* Request headers
|
||||
*/
|
||||
headers?: HeadersInit;
|
||||
/**
|
||||
* Timeout in seconds
|
||||
* Timeout in milliseconds
|
||||
*/
|
||||
timeout?: number;
|
||||
/**
|
||||
@@ -18,6 +18,17 @@ interface CheckOptions {
|
||||
*/
|
||||
target?: string;
|
||||
}
|
||||
/** Options used when downloading an update */
|
||||
interface DownloadOptions {
|
||||
/**
|
||||
* Request headers
|
||||
*/
|
||||
headers?: HeadersInit;
|
||||
/**
|
||||
* Timeout in milliseconds
|
||||
*/
|
||||
timeout?: number;
|
||||
}
|
||||
interface UpdateMetadata {
|
||||
rid: number;
|
||||
available: boolean;
|
||||
@@ -49,14 +60,14 @@ declare class Update extends Resource {
|
||||
private downloadedBytes?;
|
||||
constructor(metadata: UpdateMetadata);
|
||||
/** Download the updater package */
|
||||
download(onEvent?: (progress: DownloadEvent) => void): Promise<void>;
|
||||
download(onEvent?: (progress: DownloadEvent) => void, options?: DownloadOptions): Promise<void>;
|
||||
/** Install downloaded updater package */
|
||||
install(): Promise<void>;
|
||||
/** Downloads the updater package and installs it */
|
||||
downloadAndInstall(onEvent?: (progress: DownloadEvent) => void): Promise<void>;
|
||||
downloadAndInstall(onEvent?: (progress: DownloadEvent) => void, options?: DownloadOptions): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
}
|
||||
/** Check for updates, resolves to `null` if no updates are available */
|
||||
declare function check(options?: CheckOptions): Promise<Update | null>;
|
||||
export type { CheckOptions, DownloadEvent };
|
||||
export type { CheckOptions, DownloadOptions, DownloadEvent };
|
||||
export { check, Update };
|
||||
|
||||
@@ -13,7 +13,7 @@ class Update extends Resource {
|
||||
this.body = metadata.body;
|
||||
}
|
||||
/** Download the updater package */
|
||||
async download(onEvent) {
|
||||
async download(onEvent, options) {
|
||||
const channel = new Channel();
|
||||
if (onEvent) {
|
||||
channel.onmessage = onEvent;
|
||||
@@ -21,6 +21,7 @@ class Update extends Resource {
|
||||
const downloadedBytesRid = await invoke("plugin:updater|download", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
this.downloadedBytes = new Resource(downloadedBytesRid);
|
||||
}
|
||||
@@ -37,7 +38,7 @@ class Update extends Resource {
|
||||
this.downloadedBytes = undefined;
|
||||
}
|
||||
/** Downloads the updater package and installs it */
|
||||
async downloadAndInstall(onEvent) {
|
||||
async downloadAndInstall(onEvent, options) {
|
||||
const channel = new Channel();
|
||||
if (onEvent) {
|
||||
channel.onmessage = onEvent;
|
||||
@@ -45,6 +46,7 @@ class Update extends Resource {
|
||||
await invoke("plugin:updater|download_and_install", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
async close() {
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
import { invoke, Channel, Resource } from "@tauri-apps/api/core";
|
||||
|
||||
/** Options used to check for updates */
|
||||
/** Options used when checking for updates */
|
||||
interface CheckOptions {
|
||||
/**
|
||||
* Request headers
|
||||
*/
|
||||
headers?: HeadersInit;
|
||||
/**
|
||||
* Timeout in seconds
|
||||
* Timeout in milliseconds
|
||||
*/
|
||||
timeout?: number;
|
||||
/**
|
||||
@@ -24,6 +24,18 @@ interface CheckOptions {
|
||||
target?: string;
|
||||
}
|
||||
|
||||
/** Options used when downloading an update */
|
||||
interface DownloadOptions {
|
||||
/**
|
||||
* Request headers
|
||||
*/
|
||||
headers?: HeadersInit;
|
||||
/**
|
||||
* Timeout in milliseconds
|
||||
*/
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
interface UpdateMetadata {
|
||||
rid: number;
|
||||
available: boolean;
|
||||
@@ -57,7 +69,10 @@ class Update extends Resource {
|
||||
}
|
||||
|
||||
/** Download the updater package */
|
||||
async download(onEvent?: (progress: DownloadEvent) => void): Promise<void> {
|
||||
async download(
|
||||
onEvent?: (progress: DownloadEvent) => void,
|
||||
options?: DownloadOptions,
|
||||
): Promise<void> {
|
||||
const channel = new Channel<DownloadEvent>();
|
||||
if (onEvent) {
|
||||
channel.onmessage = onEvent;
|
||||
@@ -65,6 +80,7 @@ class Update extends Resource {
|
||||
const downloadedBytesRid = await invoke<number>("plugin:updater|download", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
this.downloadedBytes = new Resource(downloadedBytesRid);
|
||||
}
|
||||
@@ -87,6 +103,7 @@ class Update extends Resource {
|
||||
/** Downloads the updater package and installs it */
|
||||
async downloadAndInstall(
|
||||
onEvent?: (progress: DownloadEvent) => void,
|
||||
options?: DownloadOptions,
|
||||
): Promise<void> {
|
||||
const channel = new Channel<DownloadEvent>();
|
||||
if (onEvent) {
|
||||
@@ -95,6 +112,7 @@ class Update extends Resource {
|
||||
await invoke("plugin:updater|download_and_install", {
|
||||
onEvent: channel,
|
||||
rid: this.rid,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,5 +133,5 @@ async function check(options?: CheckOptions): Promise<Update | null> {
|
||||
}).then((meta) => (meta.available ? new Update(meta) : null));
|
||||
}
|
||||
|
||||
export type { CheckOptions, DownloadEvent };
|
||||
export type { CheckOptions, DownloadOptions, DownloadEvent };
|
||||
export { check, Update };
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
use crate::{Result, Update, UpdaterExt};
|
||||
|
||||
use http::{HeaderMap, HeaderName, HeaderValue};
|
||||
use serde::Serialize;
|
||||
use tauri::{ipc::Channel, Manager, Resource, ResourceId, Runtime, Webview};
|
||||
|
||||
use std::time::Duration;
|
||||
use std::{str::FromStr, time::Duration};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@@ -53,7 +54,7 @@ pub(crate) async fn check<R: Runtime>(
|
||||
}
|
||||
}
|
||||
if let Some(timeout) = timeout {
|
||||
builder = builder.timeout(Duration::from_secs(timeout));
|
||||
builder = builder.timeout(Duration::from_millis(timeout));
|
||||
}
|
||||
if let Some(ref proxy) = proxy {
|
||||
let url = Url::parse(proxy.as_str())?;
|
||||
@@ -83,8 +84,25 @@ pub(crate) async fn download<R: Runtime>(
|
||||
webview: Webview<R>,
|
||||
rid: ResourceId,
|
||||
on_event: Channel<DownloadEvent>,
|
||||
headers: Option<Vec<(String, String)>>,
|
||||
timeout: Option<u64>,
|
||||
) -> Result<ResourceId> {
|
||||
let update = webview.resources_table().get::<Update>(rid)?;
|
||||
|
||||
let mut update = (*update).clone();
|
||||
|
||||
if let Some(headers) = headers {
|
||||
let mut map = HeaderMap::new();
|
||||
for (k, v) in headers {
|
||||
map.append(HeaderName::from_str(&k)?, HeaderValue::from_str(&v)?);
|
||||
}
|
||||
update.headers = map;
|
||||
}
|
||||
|
||||
if let Some(timeout) = timeout {
|
||||
update.timeout = Some(Duration::from_millis(timeout));
|
||||
}
|
||||
|
||||
let mut first_chunk = true;
|
||||
let bytes = update
|
||||
.download(
|
||||
@@ -100,6 +118,7 @@ pub(crate) async fn download<R: Runtime>(
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(webview.resources_table().add(DownloadedBytes(bytes)))
|
||||
}
|
||||
|
||||
@@ -123,9 +142,25 @@ pub(crate) async fn download_and_install<R: Runtime>(
|
||||
webview: Webview<R>,
|
||||
rid: ResourceId,
|
||||
on_event: Channel<DownloadEvent>,
|
||||
headers: Option<Vec<(String, String)>>,
|
||||
timeout: Option<u64>,
|
||||
) -> Result<()> {
|
||||
let update = webview.resources_table().get::<Update>(rid)?;
|
||||
|
||||
let mut update = (*update).clone();
|
||||
|
||||
if let Some(headers) = headers {
|
||||
let mut map = HeaderMap::new();
|
||||
for (k, v) in headers {
|
||||
map.append(HeaderName::from_str(&k)?, HeaderValue::from_str(&v)?);
|
||||
}
|
||||
update.headers = map;
|
||||
}
|
||||
|
||||
if let Some(timeout) = timeout {
|
||||
update.timeout = Some(Duration::from_millis(timeout));
|
||||
}
|
||||
|
||||
let mut first_chunk = true;
|
||||
|
||||
update
|
||||
|
||||
@@ -68,6 +68,10 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
Http(#[from] http::Error),
|
||||
#[error(transparent)]
|
||||
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
|
||||
#[error(transparent)]
|
||||
InvalidHeaderName(#[from] http::header::InvalidHeaderName),
|
||||
#[error(transparent)]
|
||||
Tauri(#[from] tauri::Error),
|
||||
}
|
||||
|
||||
|
||||
@@ -469,10 +469,6 @@ impl Update {
|
||||
"Accept",
|
||||
HeaderValue::from_str("application/octet-stream").unwrap(),
|
||||
);
|
||||
headers.insert(
|
||||
"User-Agent",
|
||||
HeaderValue::from_str("tauri-updater").unwrap(),
|
||||
);
|
||||
|
||||
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
|
||||
if let Some(timeout) = self.timeout {
|
||||
|
||||
Reference in New Issue
Block a user