@dreamshive/better-auth-tauri 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rully Ardiansyah
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,401 @@
1
+ # @dreamshive/better-auth-tauri
2
+
3
+ [Better Auth](https://better-auth.com) plugin for [Tauri](https://tauri.app) desktop apps. OAuth happens in the user's **system browser**, not the embedded webview — the session cookie rides back through a custom URI scheme deep link, and every outgoing request in the app is transparently authenticated.
4
+
5
+ Mirrors the architecture of the official [`@better-auth/expo`](https://github.com/better-auth/better-auth/tree/main/packages/expo) package, adapted for Tauri's browser-style webview.
6
+
7
+ ## Why use this
8
+
9
+ - **OAuth providers that block embedded webviews still work** (Google's `disallowed_useragent`, enterprise SSO, upcoming Microsoft enforcement).
10
+ - **Users reuse their existing browser sessions** — no re-logging-in for github.com / google.com from inside your app.
11
+ - **Full address bar + padlock** — users can verify the provider's domain before signing in.
12
+ - **Same Better Auth API surface** — you keep using `authClient.signIn.social(...)` and `useSession()` as if nothing changed.
13
+
14
+ ## How it works
15
+
16
+ ```
17
+ ┌──────────────────┐ ┌────────────────┐ ┌──────────────┐
18
+ │ Tauri app │ │ System browser │ │ Auth service │
19
+ │ (WKWebView/ │ │ (Safari/Chrome)│ │ │
20
+ │ WebView2) │ │ │ │ │
21
+ └────────┬─────────┘ └────────┬───────┘ └──────┬───────┘
22
+ │ signIn.social() │ │
23
+ │ ─────────────────────────────┼───────────────────────>│
24
+ │ │ │
25
+ │ <── { url, disableRedirect } ──────────────────────────│
26
+ │ │ │
27
+ │ shell.open(url) │ │
28
+ │ ────────────────────────────>│ │
29
+ │ │ /tauri-authz-proxy │
30
+ │ │ ──────────────────────>│
31
+ │ │ Set-Cookie: state=... │
32
+ │ │ <──────────────────────│
33
+ │ │ │
34
+ │ │ github.com OAuth... │
35
+ │ │ <─redirect to callback─│
36
+ │ │ /callback/github │
37
+ │ │ ──────────────────────>│
38
+ │ │ │
39
+ │ │ <── 302 sokudo://?cookie=<session>
40
+ │ │ (after-hook appends cookie
41
+ │ │ to custom-scheme redirect)
42
+ │ │ │
43
+ │ <── OS routes sokudo:// ────│ │
44
+ │ │
45
+ │ store cookie in OS keychain │
46
+ │ inject as `x-tauri-cookie` header on future calls │
47
+ │ ─────────────────────────────────────────────────────>│
48
+ │ │
49
+ │ <── server plugin rewrites x-tauri-cookie → Cookie ───│
50
+ │ Better Auth validates, returns session │
51
+ ```
52
+
53
+ Two things worth calling out:
54
+
55
+ 1. **`x-tauri-cookie` header smuggling.** The Fetch spec marks `Cookie` as a [forbidden header name](https://fetch.spec.whatwg.org/#forbidden-header-name). Webviews silently drop attempts to set it. We smuggle the session through `x-tauri-cookie` and the **server** plugin rewrites it back to `Cookie` before Better Auth inspects the request.
56
+ 2. **`disableRedirect: true` auto-injection.** Better Auth's Vue/React client normally navigates `window.location.href` to the OAuth URL — fine in a browser, catastrophic in a single-window Tauri app (the webview takes over with the provider's login page). The client plugin injects `disableRedirect: true` into `/sign-in/social` and `/sign-in/oauth2` requests so the client stays put.
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ bun add @dreamshive/better-auth-tauri
62
+ # or: npm install / pnpm add / yarn add
63
+ ```
64
+
65
+ Peer Tauri plugins (install only in the desktop app that consumes the client):
66
+
67
+ ```bash
68
+ bun add @tauri-apps/plugin-shell @tauri-apps/plugin-deep-link
69
+ cd src-tauri
70
+ cargo add tauri-plugin-shell tauri-plugin-deep-link
71
+ ```
72
+
73
+ If you want the included focus/online managers to work, you also need:
74
+
75
+ ```bash
76
+ bun add @tauri-apps/api # onFocusChanged lives here
77
+ ```
78
+
79
+ ## Tauri configuration
80
+
81
+ ### 1. Register your URI scheme
82
+
83
+ `src-tauri/tauri.conf.json`:
84
+
85
+ ```json
86
+ {
87
+ "plugins": {
88
+ "deep-link": {
89
+ "desktop": {
90
+ "schemes": ["yourapp"]
91
+ }
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### 2. Initialize the Rust plugins
98
+
99
+ `src-tauri/src/lib.rs`:
100
+
101
+ ```rust
102
+ pub fn run() {
103
+ tauri::Builder::default()
104
+ .plugin(tauri_plugin_shell::init())
105
+ .plugin(tauri_plugin_deep_link::init())
106
+ // ... your other plugins
107
+ .run(tauri::generate_context!())
108
+ .expect("error while running tauri application");
109
+ }
110
+ ```
111
+
112
+ ### 3. Grant permissions
113
+
114
+ `src-tauri/capabilities/default.json`:
115
+
116
+ ```json
117
+ {
118
+ "permissions": [
119
+ "core:default",
120
+ "shell:allow-open",
121
+ "deep-link:default"
122
+ ]
123
+ }
124
+ ```
125
+
126
+ ### 4. (Highly recommended) Add `tauri-plugin-single-instance`
127
+
128
+ Without this, opening a `yourapp://` deep link from a browser while the Tauri app is already running may spawn a second window instead of reusing the first. Install:
129
+
130
+ ```bash
131
+ cd src-tauri
132
+ cargo add tauri-plugin-single-instance --features deep-link
133
+ ```
134
+
135
+ Register it **before** any other plugin in `lib.rs`:
136
+
137
+ ```rust
138
+ use tauri::{Emitter, Manager};
139
+
140
+ pub fn run() {
141
+ tauri::Builder::default()
142
+ .plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
143
+ if let Some(window) = app.get_webview_window("main") {
144
+ let _ = window.unminimize();
145
+ let _ = window.show();
146
+ let _ = window.set_focus();
147
+ }
148
+ for arg in argv.iter().skip(1) {
149
+ if arg.starts_with("yourapp://") {
150
+ let _ = app.emit("deep-link://new-url", vec![arg.clone()]);
151
+ }
152
+ }
153
+ }))
154
+ .plugin(tauri_plugin_shell::init())
155
+ .plugin(tauri_plugin_deep_link::init())
156
+ // ...
157
+ }
158
+ ```
159
+
160
+ ## Server setup (Better Auth backend)
161
+
162
+ ```ts
163
+ import { betterAuth } from "better-auth";
164
+ import { tauri } from "@dreamshive/better-auth-tauri";
165
+
166
+ export const auth = betterAuth({
167
+ // ... your existing config
168
+ trustedOrigins: ["yourapp://"],
169
+ plugins: [
170
+ tauri(),
171
+ // ... your other plugins
172
+ ],
173
+ });
174
+ ```
175
+
176
+ The server plugin:
177
+
178
+ 1. Remaps `tauri-origin` → `origin` so CSRF / trusted-origin checks accept the custom scheme.
179
+ 2. Rewrites `x-tauri-cookie` → `Cookie` so the session cookie smuggled by the client is visible to Better Auth.
180
+ 3. Appends `?cookie=<Set-Cookie>` to OAuth redirect URLs targeting custom schemes so the Tauri app can bridge the cookie jar.
181
+ 4. Exposes a `/tauri-authorization-proxy` endpoint that plants the OAuth `state` cookie in the system browser's jar before redirecting to the provider (prevents callback state mismatch).
182
+
183
+ ### CORS
184
+
185
+ Your auth server's CORS config must allow the custom headers this plugin sends:
186
+
187
+ ```ts
188
+ cors({
189
+ origin: [/* your frontend origins */, "yourapp://"],
190
+ credentials: true,
191
+ allowedHeaders: [
192
+ "Content-Type",
193
+ "Authorization",
194
+ "Cookie",
195
+ "tauri-origin",
196
+ "x-tauri-cookie",
197
+ "x-skip-oauth-proxy",
198
+ ],
199
+ })
200
+ ```
201
+
202
+ ## Client setup
203
+
204
+ ```ts
205
+ import { createAuthClient } from "better-auth/vue"; // or /react, /solid, etc.
206
+ import { tauriClient } from "@dreamshive/better-auth-tauri/client";
207
+ import { fetch as tauriFetch } from "@tauri-apps/plugin-http";
208
+ import { isTauri } from "@tauri-apps/api/core";
209
+
210
+ export const authClient = createAuthClient({
211
+ baseURL: "https://auth.example.com",
212
+ fetchOptions: {
213
+ // Always use tauriFetch in Tauri — the webview's native fetch() drops
214
+ // our smuggled headers and hits CORS on custom schemes.
215
+ customFetchImpl: (...args) =>
216
+ isTauri() ? tauriFetch(...args) : fetch(...args),
217
+ },
218
+ plugins: [
219
+ tauriClient({
220
+ scheme: "yourapp", // must match tauri.conf.json
221
+ cookiePrefix: "yourapp", // must match your server's cookie prefix
222
+ storage: {
223
+ // See "Secure storage" below — localStorage is dev-only.
224
+ getItem: (k) => localStorage.getItem(k),
225
+ setItem: (k, v) => localStorage.setItem(k, v),
226
+ },
227
+ }),
228
+ ],
229
+ });
230
+ ```
231
+
232
+ Then use Better Auth normally:
233
+
234
+ ```ts
235
+ await authClient.signIn.social({
236
+ provider: "github",
237
+ callbackURL: "/", // auto-rewritten to yourapp:///
238
+ });
239
+ ```
240
+
241
+ The plugin takes it from there.
242
+
243
+ ## Secure storage
244
+
245
+ `localStorage` is **not appropriate for production** — any XSS in your Tauri webview can read it directly.
246
+
247
+ For production, back the `storage` option with an encrypted store. Options, ranked by ergonomics:
248
+
249
+ ### Option A — OS keychain (recommended)
250
+
251
+ Expose `keyring-rs` via custom Tauri commands. Per-platform native secret store (Apple Keychain, Windows Credential Manager, Secret Service on Linux).
252
+
253
+ ```bash
254
+ cd src-tauri
255
+ cargo add keyring --features apple-native,windows-native,linux-native-sync-persistent
256
+ ```
257
+
258
+ ```rust
259
+ // src-tauri/src/keyring.rs
260
+ use keyring::Entry;
261
+
262
+ #[tauri::command]
263
+ pub fn keyring_get(service: String, key: String) -> Result<Option<String>, String> {
264
+ let entry = Entry::new(&service, &key).map_err(|e| e.to_string())?;
265
+ match entry.get_password() {
266
+ Ok(v) => Ok(Some(v)),
267
+ Err(keyring::Error::NoEntry) => Ok(None),
268
+ Err(e) => Err(e.to_string()),
269
+ }
270
+ }
271
+
272
+ #[tauri::command]
273
+ pub fn keyring_set(service: String, key: String, value: String) -> Result<(), String> {
274
+ let entry = Entry::new(&service, &key).map_err(|e| e.to_string())?;
275
+ entry.set_password(&value).map_err(|e| e.to_string())
276
+ }
277
+ ```
278
+
279
+ Register in `lib.rs`:
280
+
281
+ ```rust
282
+ mod keyring;
283
+
284
+ tauri::Builder::default()
285
+ .invoke_handler(tauri::generate_handler![
286
+ keyring::keyring_get,
287
+ keyring::keyring_set,
288
+ ])
289
+ ```
290
+
291
+ And in your client storage adapter:
292
+
293
+ ```ts
294
+ import { invoke } from "@tauri-apps/api/core";
295
+ const SERVICE = "com.yourapp.session";
296
+
297
+ const keyringStorage = {
298
+ getItem: (key: string) => invoke<string | null>("keyring_get", { service: SERVICE, key }),
299
+ setItem: (key: string, value: string) => invoke("keyring_set", { service: SERVICE, key, value }),
300
+ };
301
+ ```
302
+
303
+ ### Option B — `tauri-plugin-stronghold`
304
+
305
+ Official Tauri encrypted vault (IOTA Stronghold). Requires a master passphrase that the app supplies.
306
+
307
+ ### Option C — `@tauri-apps/plugin-store`
308
+
309
+ On-disk JSON, not encrypted, but lives behind Tauri IPC (not accessible from `document.localStorage`). Marginal improvement over `localStorage`.
310
+
311
+ ## Options
312
+
313
+ ### `tauri(options?)` — server plugin
314
+
315
+ | Option | Default | Description |
316
+ | --- | --- | --- |
317
+ | `disableOriginOverride` | `false` | Don't remap `tauri-origin` → `origin`. |
318
+
319
+ ### `tauriClient(options)` — client plugin
320
+
321
+ | Option | Default | Description |
322
+ | --- | --- | --- |
323
+ | `scheme` | — (required) | Custom URI scheme registered in `tauri.conf.json`. |
324
+ | `storage` | — (required) | Key/value storage adapter. Async methods supported. |
325
+ | `storagePrefix` | `"better-auth"` | Prefix for storage keys. |
326
+ | `cookiePrefix` | `"better-auth"` | Server cookie-name prefix(es). |
327
+ | `disableCache` | `false` | Disable local `/get-session` response cache. |
328
+ | `refetchOnWindowFocus` | `true` | Refetch session when the Tauri window regains focus. |
329
+ | `refetchOnReconnect` | `true` | Refetch session when the network comes back online. |
330
+
331
+ ## Exports
332
+
333
+ ```ts
334
+ // Server
335
+ import { tauri, tauriAuthorizationProxy } from "@dreamshive/better-auth-tauri";
336
+
337
+ // Client
338
+ import {
339
+ tauriClient,
340
+ setupTauriFocusManager, // manual wiring if you disabled auto-setup
341
+ setupTauriOnlineManager,
342
+ } from "@dreamshive/better-auth-tauri/client";
343
+ ```
344
+
345
+ ## macOS dev workflow
346
+
347
+ Deep-link URI schemes on macOS are registered with Launch Services through the app's `.app` bundle's `Info.plist`. **`tauri dev` does not produce a bundle** — it runs a raw binary which macOS can't route deep links to.
348
+
349
+ Official Tauri guidance for developing against the deep-link plugin on macOS:
350
+
351
+ ```bash
352
+ # Build once (also run after any Rust/plugin/capability change)
353
+ bun tauri build --debug
354
+ # Open the bundle so Launch Services indexes it
355
+ open src-tauri/target/debug/bundle/macos/your-app.app
356
+ ```
357
+
358
+ Frontend (Vue/React/Svelte) HMR works fine through the built app if you point `frontendDist` at your dev server:
359
+
360
+ ```json
361
+ // src-tauri/tauri.dev.conf.json
362
+ {
363
+ "$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
364
+ "build": {
365
+ "frontendDist": "http://localhost:3000",
366
+ "beforeBuildCommand": ""
367
+ }
368
+ }
369
+ ```
370
+
371
+ ```bash
372
+ bun tauri build --debug --config src-tauri/tauri.dev.conf.json
373
+ ```
374
+
375
+ ## Known limitations
376
+
377
+ - **macOS dev loop requires a bundle** (see above). Windows and Linux don't have this friction.
378
+ - **Scheme hijacking** — any app can register itself as a handler for your custom scheme. Production apps with meaningful attack surface should consider Universal Links (macOS) or App Links (Android equivalent).
379
+ - **Storage is the caller's responsibility.** This plugin doesn't bundle a secure-storage primitive; you provide the adapter.
380
+ - **No SSR support.** Tauri apps are client-only.
381
+
382
+ ## Comparison to `@better-auth/expo`
383
+
384
+ Feature-for-feature parity on the auth flow, plus two Tauri-specific additions:
385
+
386
+ | Feature | Expo | Tauri (this) |
387
+ | --- | --- | --- |
388
+ | OAuth via system browser | ✅ | ✅ |
389
+ | Cookie bridge via URL query param | ✅ | ✅ |
390
+ | Authorization proxy endpoint for state | ✅ | ✅ |
391
+ | Redirect-to-scheme callback rewrite | ✅ | ✅ |
392
+ | Sign-out local cleanup | ✅ | ✅ |
393
+ | Third-party cookie filter | ✅ | ✅ |
394
+ | Focus refetch manager | ✅ (React Query) | ✅ (notifies Better Auth session signal) |
395
+ | Online refetch manager | ✅ (React Query) | ✅ (notifies Better Auth session signal) |
396
+ | **`x-tauri-cookie` smuggling** | — | ✅ required (browser forbids `Cookie`) |
397
+ | **`disableRedirect: true` injection** | — | ✅ required (browser has `window.location`) |
398
+
399
+ ## License
400
+
401
+ MIT © [Rully Ardiansyah](https://github.com/DreamsHive)
@@ -0,0 +1,181 @@
1
+ import type { BetterAuthClientPlugin, ClientStore } from "better-auth/client";
2
+ export interface TauriClientStorage {
3
+ getItem: (key: string) => string | null | Promise<string | null>;
4
+ setItem: (key: string, value: string) => void | Promise<void>;
5
+ }
6
+ export interface TauriClientOptions {
7
+ /**
8
+ * The custom URI scheme registered for the Tauri app in `tauri.conf.json`
9
+ * under `plugins.deep-link.desktop.schemes`.
10
+ *
11
+ * Example: `"sokudo"` → produces `sokudo://` deep links.
12
+ */
13
+ scheme: string;
14
+ /**
15
+ * Persistent key/value storage for the local cookie jar and session cache.
16
+ * Provide an adapter around `@tauri-apps/plugin-store`, a keychain plugin,
17
+ * or `localStorage` for dev.
18
+ */
19
+ storage: TauriClientStorage;
20
+ /**
21
+ * Prefix for keys written to `storage`.
22
+ * @default "better-auth"
23
+ */
24
+ storagePrefix?: string;
25
+ /**
26
+ * The cookie-name prefix used by the Better Auth server. Used to filter
27
+ * the server's `Set-Cookie` header so third-party cookies (Cloudflare,
28
+ * analytics, etc.) don't trigger session refetches.
29
+ *
30
+ * Pass multiple prefixes if the server sets several (e.g. when you
31
+ * customize cookie names per instance).
32
+ *
33
+ * @default "better-auth"
34
+ */
35
+ cookiePrefix?: string | string[];
36
+ /** Disable the local `/get-session` response cache. */
37
+ disableCache?: boolean;
38
+ /**
39
+ * Refetch the session when the Tauri window regains focus.
40
+ * @default true
41
+ */
42
+ refetchOnWindowFocus?: boolean;
43
+ /**
44
+ * Refetch the session when the network comes back online.
45
+ * @default true
46
+ */
47
+ refetchOnReconnect?: boolean;
48
+ }
49
+ export declare const tauriClient: (opts: TauriClientOptions) => {
50
+ id: "tauri";
51
+ getActions(_: import("@better-fetch/fetch").BetterFetch, $store: ClientStore): {
52
+ /**
53
+ * Returns the currently-stored cookie string in the standard
54
+ * `key=value; key2=value2` format — useful if you need to attach it
55
+ * to a custom fetch outside of the Better Auth client.
56
+ */
57
+ getCookie: () => Promise<string>;
58
+ };
59
+ fetchPlugins: {
60
+ id: string;
61
+ name: string;
62
+ hooks: {
63
+ onSuccess(context: import("@better-fetch/fetch").SuccessContext<any>): Promise<void>;
64
+ };
65
+ init(url: string, options: ({
66
+ cache?: RequestCache | undefined;
67
+ credentials?: RequestCredentials | undefined;
68
+ headers?: (HeadersInit & (HeadersInit | {
69
+ accept: "application/json" | "text/plain" | "application/octet-stream";
70
+ "content-type": "application/json" | "text/plain" | "application/x-www-form-urlencoded" | "multipart/form-data" | "application/octet-stream";
71
+ authorization: "Bearer" | "Basic";
72
+ })) | undefined;
73
+ integrity?: string | undefined;
74
+ keepalive?: boolean | undefined;
75
+ method?: string | undefined;
76
+ mode?: RequestMode | undefined;
77
+ priority?: RequestPriority | undefined;
78
+ redirect?: RequestRedirect | undefined;
79
+ referrer?: string | undefined;
80
+ referrerPolicy?: ReferrerPolicy | undefined;
81
+ signal?: (AbortSignal | null) | undefined;
82
+ window?: null | undefined;
83
+ onRequest?: (<T extends Record<string, any>>(context: import("@better-fetch/fetch").RequestContext<T>) => Promise<import("@better-fetch/fetch").RequestContext | void> | import("@better-fetch/fetch").RequestContext | void) | undefined;
84
+ onResponse?: ((context: import("@better-fetch/fetch").ResponseContext) => Promise<Response | void | import("@better-fetch/fetch").ResponseContext> | Response | import("@better-fetch/fetch").ResponseContext | void) | undefined;
85
+ onSuccess?: ((context: import("@better-fetch/fetch").SuccessContext<any>) => Promise<void> | void) | undefined;
86
+ onError?: ((context: import("@better-fetch/fetch").ErrorContext) => Promise<void> | void) | undefined;
87
+ onRetry?: ((response: import("@better-fetch/fetch").ResponseContext) => Promise<void> | void) | undefined;
88
+ hookOptions?: {
89
+ cloneResponse?: boolean;
90
+ } | undefined;
91
+ timeout?: number | undefined;
92
+ customFetchImpl?: import("@better-fetch/fetch").FetchEsque | undefined;
93
+ plugins?: import("@better-fetch/fetch").BetterFetchPlugin[] | undefined;
94
+ baseURL?: string | undefined;
95
+ throw?: boolean | undefined;
96
+ auth?: ({
97
+ type: "Bearer";
98
+ token: string | Promise<string | undefined> | (() => string | Promise<string | undefined> | undefined) | undefined;
99
+ } | {
100
+ type: "Basic";
101
+ username: string | (() => string | undefined) | undefined;
102
+ password: string | (() => string | undefined) | undefined;
103
+ } | {
104
+ type: "Custom";
105
+ prefix: string | (() => string | undefined) | undefined;
106
+ value: string | (() => string | undefined) | undefined;
107
+ }) | undefined;
108
+ body?: any;
109
+ query?: any;
110
+ params?: any;
111
+ duplex?: "full" | "half" | undefined;
112
+ jsonParser?: ((text: string) => Promise<any> | any) | undefined;
113
+ retry?: import("@better-fetch/fetch").RetryOptions | undefined;
114
+ retryAttempt?: number | undefined;
115
+ output?: (import("@better-fetch/fetch").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
116
+ errorSchema?: import("@better-fetch/fetch").StandardSchemaV1 | undefined;
117
+ disableValidation?: boolean | undefined;
118
+ } & Record<string, any>) | undefined): Promise<{
119
+ url: string;
120
+ options: ({
121
+ cache?: RequestCache | undefined;
122
+ credentials?: RequestCredentials | undefined;
123
+ headers?: (HeadersInit & (HeadersInit | {
124
+ accept: "application/json" | "text/plain" | "application/octet-stream";
125
+ "content-type": "application/json" | "text/plain" | "application/x-www-form-urlencoded" | "multipart/form-data" | "application/octet-stream";
126
+ authorization: "Bearer" | "Basic";
127
+ })) | undefined;
128
+ integrity?: string | undefined;
129
+ keepalive?: boolean | undefined;
130
+ method?: string | undefined;
131
+ mode?: RequestMode | undefined;
132
+ priority?: RequestPriority | undefined;
133
+ redirect?: RequestRedirect | undefined;
134
+ referrer?: string | undefined;
135
+ referrerPolicy?: ReferrerPolicy | undefined;
136
+ signal?: (AbortSignal | null) | undefined;
137
+ window?: null | undefined;
138
+ onRequest?: (<T extends Record<string, any>>(context: import("@better-fetch/fetch").RequestContext<T>) => Promise<import("@better-fetch/fetch").RequestContext | void> | import("@better-fetch/fetch").RequestContext | void) | undefined;
139
+ onResponse?: ((context: import("@better-fetch/fetch").ResponseContext) => Promise<Response | void | import("@better-fetch/fetch").ResponseContext> | Response | import("@better-fetch/fetch").ResponseContext | void) | undefined;
140
+ onSuccess?: ((context: import("@better-fetch/fetch").SuccessContext<any>) => Promise<void> | void) | undefined;
141
+ onError?: ((context: import("@better-fetch/fetch").ErrorContext) => Promise<void> | void) | undefined;
142
+ onRetry?: ((response: import("@better-fetch/fetch").ResponseContext) => Promise<void> | void) | undefined;
143
+ hookOptions?: {
144
+ cloneResponse?: boolean;
145
+ } | undefined;
146
+ timeout?: number | undefined;
147
+ customFetchImpl?: import("@better-fetch/fetch").FetchEsque | undefined;
148
+ plugins?: import("@better-fetch/fetch").BetterFetchPlugin[] | undefined;
149
+ baseURL?: string | undefined;
150
+ throw?: boolean | undefined;
151
+ auth?: ({
152
+ type: "Bearer";
153
+ token: string | Promise<string | undefined> | (() => string | Promise<string | undefined> | undefined) | undefined;
154
+ } | {
155
+ type: "Basic";
156
+ username: string | (() => string | undefined) | undefined;
157
+ password: string | (() => string | undefined) | undefined;
158
+ } | {
159
+ type: "Custom";
160
+ prefix: string | (() => string | undefined) | undefined;
161
+ value: string | (() => string | undefined) | undefined;
162
+ }) | undefined;
163
+ body?: any;
164
+ query?: any;
165
+ params?: any;
166
+ duplex?: "full" | "half" | undefined;
167
+ jsonParser?: ((text: string) => Promise<any> | any) | undefined;
168
+ retry?: import("@better-fetch/fetch").RetryOptions | undefined;
169
+ retryAttempt?: number | undefined;
170
+ output?: (import("@better-fetch/fetch").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
171
+ errorSchema?: import("@better-fetch/fetch").StandardSchemaV1 | undefined;
172
+ disableValidation?: boolean | undefined;
173
+ } & Record<string, any>) | undefined;
174
+ }>;
175
+ }[];
176
+ };
177
+ export { PACKAGE_VERSION } from "./version";
178
+ export type { BetterAuthClientPlugin };
179
+ export { setupTauriFocusManager } from "./focus-manager";
180
+ export { setupTauriOnlineManager } from "./online-manager";
181
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAe5B,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,OAAO,EAAE,kBAAkB,CAAC;IAE5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEjC,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAsLD,eAAO,MAAM,WAAW,GAAI,MAAM,kBAAkB;;;QAoC5C;;;;WAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAsMmgC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAN9gC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,sBAAsB,EAAE,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}