@soorya-u/better-auth-desktop 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.
@@ -0,0 +1,61 @@
1
+ import { c as RequestAuthOptions, i as DesktopClientOptions, n as AuthUser, r as DesktopAdapter } from "./types-h9AEfSnq.mjs";
2
+ import { BetterFetch, CreateFetchOption } from "@better-fetch/fetch";
3
+ import { BetterAuthClientOptions } from "@better-auth/core";
4
+ import { User } from "@better-auth/core/db";
5
+
6
+ //#region src/core/exchange.d.ts
7
+ type ExchangeTokenArgs = {
8
+ $fetch: BetterFetch;
9
+ options: DesktopClientOptions;
10
+ token: string;
11
+ onAuthenticated: (user: AuthUser) => void;
12
+ fetchOptions?: Omit<CreateFetchOption, "method"> | undefined;
13
+ };
14
+ declare function exchangeToken({
15
+ $fetch,
16
+ options,
17
+ token,
18
+ onAuthenticated,
19
+ fetchOptions
20
+ }: ExchangeTokenArgs): Promise<{
21
+ data: {
22
+ token: string;
23
+ user: AuthUser;
24
+ };
25
+ error: null;
26
+ } | {
27
+ data: null;
28
+ error: {
29
+ message?: string | undefined;
30
+ status: number;
31
+ statusText: string;
32
+ };
33
+ }>;
34
+ type StartAuthFlowArgs = {
35
+ adapter: DesktopAdapter;
36
+ $fetch: BetterFetch;
37
+ clientOptions: BetterAuthClientOptions | undefined;
38
+ options: DesktopClientOptions;
39
+ cfg: RequestAuthOptions;
40
+ onAuthenticated: (user: AuthUser) => void;
41
+ onError?: (error: unknown) => void;
42
+ };
43
+ declare function startAuthFlow({
44
+ adapter,
45
+ $fetch,
46
+ clientOptions,
47
+ options,
48
+ cfg,
49
+ onAuthenticated,
50
+ onError
51
+ }: StartAuthFlowArgs): Promise<void>;
52
+ //#endregion
53
+ //#region src/core/user.d.ts
54
+ type FetchUserImageResult = {
55
+ bytes: Uint8Array;
56
+ mimeType: string;
57
+ };
58
+ declare function fetchUserImage(baseURL: string | undefined, url: string): Promise<FetchUserImageResult | null>;
59
+ declare function normalizeUserOutput<U extends User & Record<string, any>>(user: U, _options?: DesktopClientOptions | undefined): U;
60
+ //#endregion
61
+ export { StartAuthFlowArgs as a, ExchangeTokenArgs as i, fetchUserImage as n, exchangeToken as o, normalizeUserOutput as r, startAuthFlow as s, FetchUserImageResult as t };
@@ -0,0 +1,10 @@
1
+ import { a as LoopbackRequest, c as RequestAuthOptions, i as DesktopClientOptions, l as Storage, n as AuthUser, o as LoopbackResponse, r as DesktopAdapter, s as LoopbackServer, t as AuthEvent } from "./types-h9AEfSnq.mjs";
2
+ import { a as desktopClient, i as createDesktopCookieLayer, n as DesktopClientPluginOptions, r as DesktopCookieLayer, t as DesktopClientInternals } from "./client-De_zQzE1.mjs";
3
+ import { n as keychainStorage, t as KeychainStorageOptions } from "./storage-DtgX_vmE.mjs";
4
+ import { a as StartAuthFlowArgs, i as ExchangeTokenArgs, n as fetchUserImage, o as exchangeToken, r as normalizeUserOutput, s as startAuthFlow, t as FetchUserImageResult } from "./index-CP_2Wlut.mjs";
5
+ import { a as isAllowedLoopbackPort, i as generateNonce, n as LOOPBACK_HOST, o as parseLoopbackUrl, r as buildLoopbackUrl, s as successPage, t as AllowedLoopbackPorts } from "./loopback-ClkAoS2u.mjs";
6
+
7
+ //#region src/version.d.ts
8
+ declare const PACKAGE_VERSION: string;
9
+ //#endregion
10
+ export { AllowedLoopbackPorts, AuthEvent, AuthUser, DesktopAdapter, DesktopClientInternals, DesktopClientOptions, DesktopClientPluginOptions, DesktopCookieLayer, ExchangeTokenArgs, FetchUserImageResult, KeychainStorageOptions, LOOPBACK_HOST, LoopbackRequest, LoopbackResponse, LoopbackServer, PACKAGE_VERSION, RequestAuthOptions, StartAuthFlowArgs, Storage, buildLoopbackUrl, createDesktopCookieLayer, desktopClient, exchangeToken, fetchUserImage, generateNonce, isAllowedLoopbackPort, keychainStorage, normalizeUserOutput, parseLoopbackUrl, startAuthFlow, successPage };
package/dist/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import { t as PACKAGE_VERSION } from "./version-1hEssvcU.mjs";
2
+ import { n as desktopClient, t as createDesktopCookieLayer } from "./client-DhRcoap2.mjs";
3
+ import { a as parseLoopbackUrl, i as isAllowedLoopbackPort, n as buildLoopbackUrl, o as successPage, r as generateNonce, t as LOOPBACK_HOST } from "./loopback-DTQgg1Za.mjs";
4
+ import { i as normalizeUserOutput, n as startAuthFlow, r as fetchUserImage, t as exchangeToken } from "./exchange-DCZ0j_T5.mjs";
5
+ import { t as keychainStorage } from "./storage-BcwDmS-W.mjs";
6
+ import "./core/index.mjs";
7
+ export { LOOPBACK_HOST, PACKAGE_VERSION, buildLoopbackUrl, createDesktopCookieLayer, desktopClient, exchangeToken, fetchUserImage, generateNonce, isAllowedLoopbackPort, keychainStorage, normalizeUserOutput, parseLoopbackUrl, startAuthFlow, successPage };
@@ -0,0 +1,13 @@
1
+ //#region src/core/loopback.d.ts
2
+ declare const LOOPBACK_HOST = "127.0.0.1";
3
+ type AllowedLoopbackPorts = number[] | {
4
+ min: number;
5
+ max: number;
6
+ };
7
+ declare function generateNonce(): string;
8
+ declare function buildLoopbackUrl(port: number, path: string, nonce: string): string;
9
+ declare function parseLoopbackUrl(raw: string, allowedPorts?: AllowedLoopbackPorts): URL | null;
10
+ declare function isAllowedLoopbackPort(port: number, allowed: AllowedLoopbackPorts): boolean;
11
+ declare function successPage(title?: string, message?: string): string;
12
+ //#endregion
13
+ export { isAllowedLoopbackPort as a, generateNonce as i, LOOPBACK_HOST as n, parseLoopbackUrl as o, buildLoopbackUrl as r, successPage as s, AllowedLoopbackPorts as t };
@@ -0,0 +1,35 @@
1
+ import { generateRandomString } from "better-auth/crypto";
2
+ //#region src/core/loopback.ts
3
+ const LOOPBACK_HOST = "127.0.0.1";
4
+ function generateNonce() {
5
+ return generateRandomString(24, "a-z", "A-Z", "0-9");
6
+ }
7
+ function buildLoopbackUrl(port, path, nonce) {
8
+ const url = new URL(`http://${LOOPBACK_HOST}:${port}`);
9
+ url.pathname = path.startsWith("/") ? path : `/${path}`;
10
+ url.searchParams.set("nonce", nonce);
11
+ return url.toString();
12
+ }
13
+ function parseLoopbackUrl(raw, allowedPorts) {
14
+ let url;
15
+ try {
16
+ url = new URL(raw);
17
+ } catch {
18
+ return null;
19
+ }
20
+ if (url.protocol !== "http:") return null;
21
+ if (url.hostname !== "127.0.0.1") return null;
22
+ const port = Number(url.port);
23
+ if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
24
+ if (allowedPorts && !isAllowedLoopbackPort(port, allowedPorts)) return null;
25
+ return url;
26
+ }
27
+ function isAllowedLoopbackPort(port, allowed) {
28
+ if (Array.isArray(allowed)) return allowed.includes(port);
29
+ return port >= allowed.min && port <= allowed.max;
30
+ }
31
+ function successPage(title = "Signed in", message = "You can close this tab and return to the app.") {
32
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title></head><body style="font-family:system-ui,sans-serif;display:grid;place-items:center;min-height:100vh;margin:0;text-align:center"><main><h1 style="font-size:1.25rem;margin:0 0 .5rem">${title}</h1><p style="margin:0;opacity:.7">${message}</p></main></body></html>`;
33
+ }
34
+ //#endregion
35
+ export { parseLoopbackUrl as a, isAllowedLoopbackPort as i, buildLoopbackUrl as n, successPage as o, generateNonce as r, LOOPBACK_HOST as t };
@@ -0,0 +1,26 @@
1
+ import { c as RequestAuthOptions } from "../types-h9AEfSnq.mjs";
2
+ import { BetterFetchError } from "@better-fetch/fetch";
3
+ import { User } from "@better-auth/core/db";
4
+
5
+ //#region src/rpc/schema.d.ts
6
+ type AuthBridges = {
7
+ getUser(): Promise<(User & Record<string, any>) | null>;
8
+ requestAuth(options: RequestAuthOptions): Promise<void>;
9
+ signOut(): Promise<void>;
10
+ getUserImage(url: string): Promise<{
11
+ dataUrl: string | null;
12
+ }>;
13
+ onAuthenticated(callback: (user: User & Record<string, any>) => void): () => void;
14
+ onUserUpdated(callback: (user: (User & Record<string, any>) | null) => void): () => void;
15
+ onAuthError(callback: (context: {
16
+ error: BetterFetchError | {
17
+ message: string;
18
+ };
19
+ path?: string;
20
+ }) => void): () => void;
21
+ };
22
+ //#endregion
23
+ //#region src/rpc/webview.d.ts
24
+ declare function defineAuthWebviewRPC(): AuthBridges;
25
+ //#endregion
26
+ export { defineAuthWebviewRPC };
@@ -0,0 +1,325 @@
1
+ //#region node_modules/electrobun/dist/api/shared/rpc.ts
2
+ const MAX_ID = 1e10;
3
+ const DEFAULT_MAX_REQUEST_TIME = 1e3;
4
+ function missingTransportMethodError(methods, action) {
5
+ const methodsString = methods.map((m) => `"${m}"`).join(", ");
6
+ return /* @__PURE__ */ new Error(`This RPC instance cannot ${action} because the transport did not provide one or more of these methods: ${methodsString}`);
7
+ }
8
+ function createRPC(options = {}) {
9
+ let debugHooks = {};
10
+ let transport = {};
11
+ let requestHandler = void 0;
12
+ function setTransport(newTransport) {
13
+ if (transport.unregisterHandler) transport.unregisterHandler();
14
+ transport = newTransport;
15
+ transport.registerHandler?.(handler);
16
+ }
17
+ function setRequestHandler(h) {
18
+ if (typeof h === "function") {
19
+ requestHandler = h;
20
+ return;
21
+ }
22
+ requestHandler = (method, params) => {
23
+ const handlerFn = h[method];
24
+ if (handlerFn) return handlerFn(params);
25
+ const fallbackHandler = h._;
26
+ if (!fallbackHandler) throw new Error(`The requested method has no handler: ${String(method)}`);
27
+ return fallbackHandler(method, params);
28
+ };
29
+ }
30
+ const { maxRequestTime = DEFAULT_MAX_REQUEST_TIME } = options;
31
+ if (options.transport) setTransport(options.transport);
32
+ if (options.requestHandler) setRequestHandler(options.requestHandler);
33
+ if (options._debugHooks) debugHooks = options._debugHooks;
34
+ let lastRequestId = 0;
35
+ function getRequestId() {
36
+ if (lastRequestId <= MAX_ID) return ++lastRequestId;
37
+ return lastRequestId = 0;
38
+ }
39
+ const requestListeners = /* @__PURE__ */ new Map();
40
+ const requestTimeouts = /* @__PURE__ */ new Map();
41
+ function requestFn(method, ...args) {
42
+ const params = args[0];
43
+ return new Promise((resolve, reject) => {
44
+ if (!transport.send) throw missingTransportMethodError(["send"], "make requests");
45
+ const requestId = getRequestId();
46
+ const request = {
47
+ type: "request",
48
+ id: requestId,
49
+ method,
50
+ params
51
+ };
52
+ requestListeners.set(requestId, {
53
+ resolve,
54
+ reject
55
+ });
56
+ if (maxRequestTime !== Infinity) requestTimeouts.set(requestId, setTimeout(() => {
57
+ requestTimeouts.delete(requestId);
58
+ requestListeners.delete(requestId);
59
+ reject(/* @__PURE__ */ new Error("RPC request timed out."));
60
+ }, maxRequestTime));
61
+ debugHooks.onSend?.(request);
62
+ transport.send(request);
63
+ });
64
+ }
65
+ const request = new Proxy(requestFn, { get: (target, prop, receiver) => {
66
+ if (prop in target) return Reflect.get(target, prop, receiver);
67
+ return (params) => requestFn(prop, params);
68
+ } });
69
+ const requestProxy = request;
70
+ function sendFn(message, ...args) {
71
+ const payload = args[0];
72
+ if (!transport.send) throw missingTransportMethodError(["send"], "send messages");
73
+ const rpcMessage = {
74
+ type: "message",
75
+ id: message,
76
+ payload
77
+ };
78
+ debugHooks.onSend?.(rpcMessage);
79
+ transport.send(rpcMessage);
80
+ }
81
+ const send = new Proxy(sendFn, { get: (target, prop, receiver) => {
82
+ if (prop in target) return Reflect.get(target, prop, receiver);
83
+ return (payload) => sendFn(prop, payload);
84
+ } });
85
+ const sendProxy = send;
86
+ const messageListeners = /* @__PURE__ */ new Map();
87
+ const wildcardMessageListeners = /* @__PURE__ */ new Set();
88
+ function addMessageListener(message, listener) {
89
+ if (!transport.registerHandler) throw missingTransportMethodError(["registerHandler"], "register message listeners");
90
+ if (message === "*") {
91
+ wildcardMessageListeners.add(listener);
92
+ return;
93
+ }
94
+ if (!messageListeners.has(message)) messageListeners.set(message, /* @__PURE__ */ new Set());
95
+ messageListeners.get(message).add(listener);
96
+ }
97
+ function removeMessageListener(message, listener) {
98
+ if (message === "*") {
99
+ wildcardMessageListeners.delete(listener);
100
+ return;
101
+ }
102
+ messageListeners.get(message)?.delete(listener);
103
+ if (messageListeners.get(message)?.size === 0) messageListeners.delete(message);
104
+ }
105
+ async function handler(message) {
106
+ debugHooks.onReceive?.(message);
107
+ if (!("type" in message)) throw new Error("Message does not contain a type.");
108
+ if (message.type === "request") {
109
+ if (!transport.send || !requestHandler) throw missingTransportMethodError(["send", "requestHandler"], "handle requests");
110
+ const { id, method, params } = message;
111
+ let response;
112
+ try {
113
+ response = {
114
+ type: "response",
115
+ id,
116
+ success: true,
117
+ payload: await requestHandler(method, params)
118
+ };
119
+ } catch (error) {
120
+ if (!(error instanceof Error)) throw error;
121
+ response = {
122
+ type: "response",
123
+ id,
124
+ success: false,
125
+ error: error.message
126
+ };
127
+ }
128
+ debugHooks.onSend?.(response);
129
+ transport.send(response);
130
+ return;
131
+ }
132
+ if (message.type === "response") {
133
+ const timeout = requestTimeouts.get(message.id);
134
+ if (timeout != null) clearTimeout(timeout);
135
+ requestTimeouts.delete(message.id);
136
+ const { resolve, reject } = requestListeners.get(message.id) ?? {};
137
+ requestListeners.delete(message.id);
138
+ if (!message.success) reject?.(new Error(message.error));
139
+ else resolve?.(message.payload);
140
+ return;
141
+ }
142
+ if (message.type === "message") {
143
+ for (const listener of wildcardMessageListeners) listener(message.id, message.payload);
144
+ const listeners = messageListeners.get(message.id);
145
+ if (!listeners) return;
146
+ for (const listener of listeners) listener(message.payload);
147
+ return;
148
+ }
149
+ throw new Error(`Unexpected RPC message type: ${message.type}`);
150
+ }
151
+ return {
152
+ setTransport,
153
+ setRequestHandler,
154
+ request,
155
+ requestProxy,
156
+ send,
157
+ sendProxy,
158
+ addMessageListener,
159
+ removeMessageListener,
160
+ proxy: {
161
+ send: sendProxy,
162
+ request: requestProxy
163
+ }
164
+ };
165
+ }
166
+ function defineElectrobunRPC(_side, config) {
167
+ const rpc = createRPC({
168
+ maxRequestTime: config.maxRequestTime,
169
+ requestHandler: {
170
+ ...config.handlers.requests,
171
+ ...config.extraRequestHandlers
172
+ },
173
+ transport: { registerHandler: () => {} }
174
+ });
175
+ const messageHandlers = config.handlers.messages;
176
+ if (messageHandlers) rpc.addMessageListener("*", ((messageName, payload) => {
177
+ const globalHandler = messageHandlers["*"];
178
+ if (globalHandler) globalHandler(messageName, payload);
179
+ const messageHandler = messageHandlers[messageName];
180
+ if (messageHandler) messageHandler(payload);
181
+ }));
182
+ return rpc;
183
+ }
184
+ //#endregion
185
+ //#region node_modules/electrobun/dist/api/browser/index.ts
186
+ const WEBVIEW_ID = window.__electrobunWebviewId;
187
+ const RPC_SOCKET_PORT = window.__electrobunRpcSocketPort;
188
+ var Electroview = class {
189
+ bunSocket;
190
+ rpc;
191
+ rpcHandler;
192
+ constructor(config) {
193
+ this.rpc = config.rpc;
194
+ this.init();
195
+ }
196
+ init() {
197
+ this.initSocketToBun();
198
+ window.__electrobun.receiveMessageFromBun = this.receiveMessageFromBun.bind(this);
199
+ if (this.rpc) this.rpc.setTransport(this.createTransport());
200
+ }
201
+ initSocketToBun() {
202
+ if (!RPC_SOCKET_PORT || !WEBVIEW_ID) return;
203
+ const socket = new WebSocket(`ws://localhost:${RPC_SOCKET_PORT}/socket?webviewId=${WEBVIEW_ID}`);
204
+ this.bunSocket = socket;
205
+ socket.addEventListener("open", () => {});
206
+ socket.addEventListener("message", async (event) => {
207
+ const message = event.data;
208
+ if (typeof message === "string") try {
209
+ const encryptedPacket = JSON.parse(message);
210
+ const decrypted = await window.__electrobun_decrypt(encryptedPacket.encryptedData, encryptedPacket.iv, encryptedPacket.tag);
211
+ this.rpcHandler?.(JSON.parse(decrypted));
212
+ } catch (err) {
213
+ console.error("Error parsing bun message:", err);
214
+ }
215
+ else if (message instanceof Blob) {} else console.error("UNKNOWN DATA TYPE RECEIVED:", event.data);
216
+ });
217
+ socket.addEventListener("error", (event) => {
218
+ console.error("Socket error:", event);
219
+ });
220
+ socket.addEventListener("close", (_event) => {});
221
+ }
222
+ createTransport() {
223
+ const that = this;
224
+ return {
225
+ send(message) {
226
+ try {
227
+ const messageString = JSON.stringify(message);
228
+ that.bunBridge(messageString);
229
+ } catch (error) {
230
+ console.error("bun: failed to serialize message to webview", error);
231
+ }
232
+ },
233
+ registerHandler(handler) {
234
+ that.rpcHandler = handler;
235
+ }
236
+ };
237
+ }
238
+ async bunBridge(msg) {
239
+ if (this.bunSocket?.readyState === WebSocket.OPEN) try {
240
+ const { encryptedData, iv, tag } = await window.__electrobun_encrypt(msg);
241
+ const encryptedPacketString = JSON.stringify({
242
+ encryptedData,
243
+ iv,
244
+ tag
245
+ });
246
+ this.bunSocket.send(encryptedPacketString);
247
+ return;
248
+ } catch (error) {
249
+ console.error("Error sending message to bun via socket:", error);
250
+ }
251
+ window.__electrobunBunBridge?.postMessage(msg);
252
+ }
253
+ receiveMessageFromBun(msg) {
254
+ if (this.rpcHandler) this.rpcHandler(msg);
255
+ }
256
+ static defineRPC(config) {
257
+ return defineElectrobunRPC("webview", {
258
+ ...config,
259
+ extraRequestHandlers: { evaluateJavascriptWithResponse: ({ script }) => {
260
+ return new Promise((resolve) => {
261
+ try {
262
+ const result = new Function(script)();
263
+ if (result instanceof Promise) result.then((resolvedResult) => {
264
+ resolve(resolvedResult);
265
+ }).catch((error) => {
266
+ console.error("bun: async script execution failed", error);
267
+ resolve(String(error));
268
+ });
269
+ else resolve(result);
270
+ } catch (error) {
271
+ console.error("bun: failed to eval script", error);
272
+ resolve(String(error));
273
+ }
274
+ });
275
+ } }
276
+ });
277
+ }
278
+ };
279
+ //#endregion
280
+ //#region src/rpc/webview.ts
281
+ /**
282
+ * Renderer-side auth bridge for the Electrobun WebView. Call once at the top of
283
+ * your webview entry, then use the returned bridge:
284
+ *
285
+ * ```ts
286
+ * import { defineAuthWebviewRPC } from "@soorya-u/better-auth-desktop/rpc/webview";
287
+ * export const auth = defineAuthWebviewRPC();
288
+ *
289
+ * auth.onAuthenticated((user) => navigate("/threads"));
290
+ * await auth.requestAuth({ provider: "github" });
291
+ * ```
292
+ */
293
+ function defineAuthWebviewRPC() {
294
+ const rpc = Electroview.defineRPC({
295
+ maxRequestTime: 3e4,
296
+ handlers: {
297
+ requests: {},
298
+ messages: {}
299
+ }
300
+ });
301
+ new Electroview({ rpc });
302
+ return {
303
+ getUser: () => rpc.request.getUser({}),
304
+ requestAuth: (options) => rpc.request.requestAuth({ options }),
305
+ signOut: () => rpc.request.signOut({}),
306
+ getUserImage: (url) => rpc.request.getUserImage({ url }),
307
+ onAuthenticated: (callback) => {
308
+ const handler = (user) => callback(user);
309
+ rpc.addMessageListener("onAuthenticated", handler);
310
+ return () => rpc.removeMessageListener("onAuthenticated", handler);
311
+ },
312
+ onUserUpdated: (callback) => {
313
+ const handler = (user) => callback(user);
314
+ rpc.addMessageListener("onUserUpdated", handler);
315
+ return () => rpc.removeMessageListener("onUserUpdated", handler);
316
+ },
317
+ onAuthError: (callback) => {
318
+ const handler = (ctx) => callback(ctx);
319
+ rpc.addMessageListener("onAuthError", handler);
320
+ return () => rpc.removeMessageListener("onAuthError", handler);
321
+ }
322
+ };
323
+ }
324
+ //#endregion
325
+ export { defineAuthWebviewRPC };
@@ -0,0 +1,60 @@
1
+ import { t as AllowedLoopbackPorts } from "../loopback-ClkAoS2u.mjs";
2
+ import * as _$better_auth0 from "better-auth";
3
+ import { BetterAuthPlugin } from "better-auth";
4
+
5
+ //#region src/server/error-codes.d.ts
6
+ declare const DESKTOP_ERROR_CODES: {
7
+ INVALID_CLIENT_ID: _$better_auth0.RawError<"INVALID_CLIENT_ID">;
8
+ INVALID_TOKEN: _$better_auth0.RawError<"INVALID_TOKEN">;
9
+ STATE_MISMATCH: _$better_auth0.RawError<"STATE_MISMATCH">;
10
+ MISSING_CODE_CHALLENGE: _$better_auth0.RawError<"MISSING_CODE_CHALLENGE">;
11
+ INVALID_CODE_VERIFIER: _$better_auth0.RawError<"INVALID_CODE_VERIFIER">;
12
+ MISSING_STATE: _$better_auth0.RawError<"MISSING_STATE">;
13
+ MISSING_PKCE: _$better_auth0.RawError<"MISSING_PKCE">;
14
+ INVALID_PKCE_METHOD: _$better_auth0.RawError<"INVALID_PKCE_METHOD">;
15
+ INVALID_LOOPBACK_URL: _$better_auth0.RawError<"INVALID_LOOPBACK_URL">;
16
+ };
17
+ //#endregion
18
+ //#region src/server/types.d.ts
19
+ type DesktopServerOptions = {
20
+ /**
21
+ * Client ID used to identify the desktop client during authorization. Must
22
+ * match the `clientID` configured in the desktop adapter.
23
+ * @default "desktop"
24
+ */
25
+ clientID?: string;
26
+ /**
27
+ * Duration (in seconds) for which the one-time authorization code is valid.
28
+ * @default 300
29
+ */
30
+ codeExpiresIn?: number;
31
+ /**
32
+ * Disable rewriting the request `origin` from the `desktop-origin` header.
33
+ * @default false
34
+ */
35
+ disableOriginOverride?: boolean;
36
+ /**
37
+ * Name of the one-time-code query/hash parameter appended to the loopback or
38
+ * web-callback URL.
39
+ * @default "token"
40
+ */
41
+ hashKey?: string;
42
+ /**
43
+ * Optional branded web callback page. When set, `oauth-complete` redirects the
44
+ * browser here (`#token=…&loopback=…`) instead of straight to the loopback,
45
+ * and the page must call `forwardToDesktop()` to complete the hand-off.
46
+ * Leave unset for the default direct-to-loopback redirect.
47
+ */
48
+ webCallbackUrl?: string;
49
+ /**
50
+ * Optional hardening: restrict the loopback port the server is willing to
51
+ * redirect to. Either an explicit allowlist or an inclusive `{ min, max }`
52
+ * range. Omit to allow any ephemeral port.
53
+ */
54
+ allowedLoopbackPorts?: AllowedLoopbackPorts;
55
+ };
56
+ //#endregion
57
+ //#region src/server/plugin.d.ts
58
+ declare const betterAuthDesktop: (options?: DesktopServerOptions) => BetterAuthPlugin;
59
+ //#endregion
60
+ export { DESKTOP_ERROR_CODES, type DesktopServerOptions, betterAuthDesktop };