@better-auth/electron 1.5.0-beta.13 → 1.5.0-beta.16

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,257 @@
1
+ import electron, { contextBridge } from "electron";
2
+
3
+ //#region ../core/dist/utils/error-codes.mjs
4
+ function defineErrorCodes(codes) {
5
+ return Object.fromEntries(Object.entries(codes).map(([key, value]) => [key, {
6
+ code: key,
7
+ message: value,
8
+ toString: () => key
9
+ }]));
10
+ }
11
+
12
+ //#endregion
13
+ //#region ../core/dist/error/codes.mjs
14
+ const BASE_ERROR_CODES = defineErrorCodes({
15
+ USER_NOT_FOUND: "User not found",
16
+ FAILED_TO_CREATE_USER: "Failed to create user",
17
+ FAILED_TO_CREATE_SESSION: "Failed to create session",
18
+ FAILED_TO_UPDATE_USER: "Failed to update user",
19
+ FAILED_TO_GET_SESSION: "Failed to get session",
20
+ INVALID_PASSWORD: "Invalid password",
21
+ INVALID_EMAIL: "Invalid email",
22
+ INVALID_EMAIL_OR_PASSWORD: "Invalid email or password",
23
+ INVALID_USER: "Invalid user",
24
+ SOCIAL_ACCOUNT_ALREADY_LINKED: "Social account already linked",
25
+ PROVIDER_NOT_FOUND: "Provider not found",
26
+ INVALID_TOKEN: "Invalid token",
27
+ TOKEN_EXPIRED: "Token expired",
28
+ ID_TOKEN_NOT_SUPPORTED: "id_token not supported",
29
+ FAILED_TO_GET_USER_INFO: "Failed to get user info",
30
+ USER_EMAIL_NOT_FOUND: "User email not found",
31
+ EMAIL_NOT_VERIFIED: "Email not verified",
32
+ PASSWORD_TOO_SHORT: "Password too short",
33
+ PASSWORD_TOO_LONG: "Password too long",
34
+ USER_ALREADY_EXISTS: "User already exists.",
35
+ USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL: "User already exists. Use another email.",
36
+ EMAIL_CAN_NOT_BE_UPDATED: "Email can not be updated",
37
+ CREDENTIAL_ACCOUNT_NOT_FOUND: "Credential account not found",
38
+ SESSION_EXPIRED: "Session expired. Re-authenticate to perform this action.",
39
+ FAILED_TO_UNLINK_LAST_ACCOUNT: "You can't unlink your last account",
40
+ ACCOUNT_NOT_FOUND: "Account not found",
41
+ USER_ALREADY_HAS_PASSWORD: "User already has a password. Provide that to delete the account.",
42
+ CROSS_SITE_NAVIGATION_LOGIN_BLOCKED: "Cross-site navigation login blocked. This request appears to be a CSRF attack.",
43
+ VERIFICATION_EMAIL_NOT_ENABLED: "Verification email isn't enabled",
44
+ EMAIL_ALREADY_VERIFIED: "Email is already verified",
45
+ EMAIL_MISMATCH: "Email mismatch",
46
+ SESSION_NOT_FRESH: "Session is not fresh",
47
+ LINKED_ACCOUNT_ALREADY_EXISTS: "Linked account already exists",
48
+ INVALID_ORIGIN: "Invalid origin",
49
+ INVALID_CALLBACK_URL: "Invalid callbackURL",
50
+ INVALID_REDIRECT_URL: "Invalid redirectURL",
51
+ INVALID_ERROR_CALLBACK_URL: "Invalid errorCallbackURL",
52
+ INVALID_NEW_USER_CALLBACK_URL: "Invalid newUserCallbackURL",
53
+ MISSING_OR_NULL_ORIGIN: "Missing or null Origin",
54
+ CALLBACK_URL_REQUIRED: "callbackURL is required",
55
+ FAILED_TO_CREATE_VERIFICATION: "Unable to create verification",
56
+ FIELD_NOT_ALLOWED: "Field not allowed to be set",
57
+ ASYNC_VALIDATION_NOT_SUPPORTED: "Async validation is not supported",
58
+ VALIDATION_ERROR: "Validation Error",
59
+ MISSING_FIELD: "Field is required",
60
+ METHOD_NOT_ALLOWED_DEFER_SESSION_REQUIRED: "POST method requires deferSessionRefresh to be enabled in session config",
61
+ BODY_MUST_BE_AN_OBJECT: "Body must be an object",
62
+ PASSWORD_ALREADY_SET: "User already has a password set"
63
+ });
64
+
65
+ //#endregion
66
+ //#region ../../node_modules/.pnpm/better-call@1.3.2_zod@4.3.6/node_modules/better-call/dist/error.mjs
67
+ function isErrorStackTraceLimitWritable() {
68
+ const desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit");
69
+ if (desc === void 0) return Object.isExtensible(Error);
70
+ return Object.prototype.hasOwnProperty.call(desc, "writable") ? desc.writable : desc.set !== void 0;
71
+ }
72
+ /**
73
+ * Hide internal stack frames from the error stack trace.
74
+ */
75
+ function hideInternalStackFrames(stack) {
76
+ const lines = stack.split("\n at ");
77
+ if (lines.length <= 1) return stack;
78
+ lines.splice(1, 1);
79
+ return lines.join("\n at ");
80
+ }
81
+ /**
82
+ * Creates a custom error class that hides stack frames.
83
+ */
84
+ function makeErrorForHideStackFrame(Base, clazz) {
85
+ class HideStackFramesError extends Base {
86
+ #hiddenStack;
87
+ constructor(...args) {
88
+ if (isErrorStackTraceLimitWritable()) {
89
+ const limit = Error.stackTraceLimit;
90
+ Error.stackTraceLimit = 0;
91
+ super(...args);
92
+ Error.stackTraceLimit = limit;
93
+ } else super(...args);
94
+ const stack = (/* @__PURE__ */ new Error()).stack;
95
+ if (stack) this.#hiddenStack = hideInternalStackFrames(stack.replace(/^Error/, this.name));
96
+ }
97
+ get errorStack() {
98
+ return this.#hiddenStack;
99
+ }
100
+ }
101
+ Object.defineProperty(HideStackFramesError.prototype, "constructor", {
102
+ get() {
103
+ return clazz;
104
+ },
105
+ enumerable: false,
106
+ configurable: true
107
+ });
108
+ return HideStackFramesError;
109
+ }
110
+ const statusCodes = {
111
+ OK: 200,
112
+ CREATED: 201,
113
+ ACCEPTED: 202,
114
+ NO_CONTENT: 204,
115
+ MULTIPLE_CHOICES: 300,
116
+ MOVED_PERMANENTLY: 301,
117
+ FOUND: 302,
118
+ SEE_OTHER: 303,
119
+ NOT_MODIFIED: 304,
120
+ TEMPORARY_REDIRECT: 307,
121
+ BAD_REQUEST: 400,
122
+ UNAUTHORIZED: 401,
123
+ PAYMENT_REQUIRED: 402,
124
+ FORBIDDEN: 403,
125
+ NOT_FOUND: 404,
126
+ METHOD_NOT_ALLOWED: 405,
127
+ NOT_ACCEPTABLE: 406,
128
+ PROXY_AUTHENTICATION_REQUIRED: 407,
129
+ REQUEST_TIMEOUT: 408,
130
+ CONFLICT: 409,
131
+ GONE: 410,
132
+ LENGTH_REQUIRED: 411,
133
+ PRECONDITION_FAILED: 412,
134
+ PAYLOAD_TOO_LARGE: 413,
135
+ URI_TOO_LONG: 414,
136
+ UNSUPPORTED_MEDIA_TYPE: 415,
137
+ RANGE_NOT_SATISFIABLE: 416,
138
+ EXPECTATION_FAILED: 417,
139
+ "I'M_A_TEAPOT": 418,
140
+ MISDIRECTED_REQUEST: 421,
141
+ UNPROCESSABLE_ENTITY: 422,
142
+ LOCKED: 423,
143
+ FAILED_DEPENDENCY: 424,
144
+ TOO_EARLY: 425,
145
+ UPGRADE_REQUIRED: 426,
146
+ PRECONDITION_REQUIRED: 428,
147
+ TOO_MANY_REQUESTS: 429,
148
+ REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
149
+ UNAVAILABLE_FOR_LEGAL_REASONS: 451,
150
+ INTERNAL_SERVER_ERROR: 500,
151
+ NOT_IMPLEMENTED: 501,
152
+ BAD_GATEWAY: 502,
153
+ SERVICE_UNAVAILABLE: 503,
154
+ GATEWAY_TIMEOUT: 504,
155
+ HTTP_VERSION_NOT_SUPPORTED: 505,
156
+ VARIANT_ALSO_NEGOTIATES: 506,
157
+ INSUFFICIENT_STORAGE: 507,
158
+ LOOP_DETECTED: 508,
159
+ NOT_EXTENDED: 510,
160
+ NETWORK_AUTHENTICATION_REQUIRED: 511
161
+ };
162
+ var InternalAPIError = class extends Error {
163
+ constructor(status = "INTERNAL_SERVER_ERROR", body = void 0, headers = {}, statusCode = typeof status === "number" ? status : statusCodes[status]) {
164
+ super(body?.message, body?.cause ? { cause: body.cause } : void 0);
165
+ this.status = status;
166
+ this.body = body;
167
+ this.headers = headers;
168
+ this.statusCode = statusCode;
169
+ this.name = "APIError";
170
+ this.status = status;
171
+ this.headers = headers;
172
+ this.statusCode = statusCode;
173
+ this.body = body;
174
+ }
175
+ };
176
+ const kAPIErrorHeaderSymbol = Symbol.for("better-call:api-error-headers");
177
+ const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);
178
+
179
+ //#endregion
180
+ //#region ../core/dist/error/index.mjs
181
+ var BetterAuthError = class extends Error {
182
+ constructor(message, options) {
183
+ super(message, options);
184
+ this.name = "BetterAuthError";
185
+ this.message = message;
186
+ this.stack = "";
187
+ }
188
+ };
189
+
190
+ //#endregion
191
+ //#region src/utils.ts
192
+ function isProcessType(type) {
193
+ return typeof process !== "undefined" && process.type === type;
194
+ }
195
+ function getChannelPrefixWithDelimiter(ns = "better-auth") {
196
+ return ns.length > 0 ? ns + ":" : ns;
197
+ }
198
+
199
+ //#endregion
200
+ //#region src/preload.ts
201
+ const { ipcRenderer } = electron;
202
+ function listenerFactory(channel, listener) {
203
+ ipcRenderer.on(channel, listener);
204
+ return () => {
205
+ ipcRenderer.off(channel, listener);
206
+ };
207
+ }
208
+ /**
209
+ * Exposes IPC bridges to the renderer process.
210
+ */
211
+ function exposeBridges(opts) {
212
+ if (!process.contextIsolated) throw new BetterAuthError("Context isolation must be enabled to use IPC bridges securely.");
213
+ const prefix = getChannelPrefixWithDelimiter(opts.channelPrefix);
214
+ const bridges = {
215
+ getUser: async () => {
216
+ return await ipcRenderer.invoke(`${prefix}getUser`);
217
+ },
218
+ requestAuth: async (options) => {
219
+ await ipcRenderer.invoke(`${prefix}requestAuth`, options);
220
+ },
221
+ signOut: async () => {
222
+ await ipcRenderer.invoke(`${prefix}signOut`);
223
+ },
224
+ authenticate: async (data) => {
225
+ await ipcRenderer.invoke(`${prefix}authenticate`, data);
226
+ },
227
+ onAuthenticated: (callback) => {
228
+ return listenerFactory(`${prefix}authenticated`, async (_evt, user) => {
229
+ await callback(user);
230
+ });
231
+ },
232
+ onUserUpdated: (callback) => {
233
+ return listenerFactory(`${prefix}user-updated`, async (_evt, user) => {
234
+ await callback(user);
235
+ });
236
+ },
237
+ onAuthError: (callback) => {
238
+ return listenerFactory(`${prefix}error`, async (_evt, context) => {
239
+ await callback(context);
240
+ });
241
+ }
242
+ };
243
+ for (const [key, value] of Object.entries(bridges)) contextBridge.exposeInMainWorld(key, value);
244
+ return {};
245
+ }
246
+ /**
247
+ * Sets up the renderer process.
248
+ *
249
+ * - Exposes IPC bridges to the renderer process.
250
+ */
251
+ function setupRenderer(options = {}) {
252
+ if (!isProcessType("renderer")) throw new BetterAuthError("setupRenderer can only be called in the renderer process.");
253
+ exposeBridges(options);
254
+ }
255
+
256
+ //#endregion
257
+ export { setupRenderer };
package/dist/proxy.d.mts CHANGED
@@ -1,9 +1,16 @@
1
- import { r as ElectronProxyClientOptions } from "./authenticate-CWAVJ4W8.mjs";
1
+ import { c as ElectronProxyClientOptions } from "./browser-CCZQ2aoV.mjs";
2
+ import { electron } from "./index.mjs";
2
3
 
3
4
  //#region src/proxy.d.ts
4
5
  declare const electronProxyClient: (options: ElectronProxyClientOptions) => {
5
6
  id: "electron-proxy";
6
7
  getActions: () => {
8
+ electron: {
9
+ /**
10
+ * Gets the current authorization code from the cookie.
11
+ */
12
+ getAuthorizationCode: () => string | null;
13
+ };
7
14
  /**
8
15
  * Ensures redirecting to the Electron app.
9
16
  *
@@ -22,6 +29,10 @@ declare const electronProxyClient: (options: ElectronProxyClientOptions) => {
22
29
  interval?: number | undefined;
23
30
  } | undefined) => NodeJS.Timeout;
24
31
  };
32
+ pathMethods: {
33
+ "/electron/transfer-user": "POST";
34
+ };
35
+ $InferServerPlugin: ReturnType<typeof electron>;
25
36
  };
26
37
  //#endregion
27
38
  export { electronProxyClient };
package/dist/proxy.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as parseProtocolScheme } from "./utils-C3fLmbAT.mjs";
1
+ import { r as parseProtocolScheme } from "./utils-DecLU66o.mjs";
2
2
  import { parseCookies } from "better-auth/cookies";
3
3
 
4
4
  //#region src/proxy.ts
@@ -14,24 +14,32 @@ const electronProxyClient = (options) => {
14
14
  return {
15
15
  id: "electron-proxy",
16
16
  getActions: () => {
17
- return { ensureElectronRedirect: (cfg) => {
18
- const timeout = cfg?.timeout || 1e4;
19
- const interval = cfg?.interval || 100;
20
- const handleRedirect = () => {
21
- if (typeof document === "undefined") return false;
22
- const authorizationCode = parseCookies(document.cookie).get(redirectCookieName);
23
- if (!authorizationCode) return false;
24
- document.cookie = `${redirectCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
25
- window.location.replace(`${scheme}:/${opts.callbackPath}#token=${authorizationCode}`);
26
- return true;
27
- };
28
- const start = Date.now();
29
- const id = setInterval(() => {
30
- if (handleRedirect() || Date.now() - start > timeout) clearInterval(id);
31
- }, interval);
32
- return id;
33
- } };
34
- }
17
+ const getAuthorizationCode = () => {
18
+ if (typeof document === "undefined") return null;
19
+ return parseCookies(document.cookie).get(redirectCookieName) ?? null;
20
+ };
21
+ return {
22
+ electron: { getAuthorizationCode },
23
+ ensureElectronRedirect: (cfg) => {
24
+ const timeout = cfg?.timeout || 1e4;
25
+ const interval = cfg?.interval || 100;
26
+ const handleRedirect = () => {
27
+ const authorizationCode = getAuthorizationCode();
28
+ if (!authorizationCode) return false;
29
+ document.cookie = `${redirectCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
30
+ window.location.replace(`${scheme}:/${opts.callbackPath}#token=${authorizationCode}`);
31
+ return true;
32
+ };
33
+ const start = Date.now();
34
+ const id = setInterval(() => {
35
+ if (handleRedirect() || Date.now() - start > timeout) clearInterval(id);
36
+ }, interval);
37
+ return id;
38
+ }
39
+ };
40
+ },
41
+ pathMethods: { "/electron/transfer-user": "POST" },
42
+ $InferServerPlugin: {}
35
43
  };
36
44
  };
37
45
 
@@ -1,5 +1,5 @@
1
- import { i as Storage } from "./authenticate-CWAVJ4W8.mjs";
2
- import "./client-BBp9yCmE.mjs";
1
+ import { u as Storage } from "./browser-CCZQ2aoV.mjs";
2
+ import "./client.mjs";
3
3
  import { Options } from "conf";
4
4
 
5
5
  //#region src/storage.d.ts
@@ -12,6 +12,9 @@ function parseProtocolScheme(protocolOption) {
12
12
  privileges: protocolOption.privileges || {}
13
13
  };
14
14
  }
15
+ function getChannelPrefixWithDelimiter(ns = "better-auth") {
16
+ return ns.length > 0 ? ns + ":" : ns;
17
+ }
15
18
 
16
19
  //#endregion
17
- export { parseProtocolScheme as n, isProcessType as t };
20
+ export { isProcessType as n, parseProtocolScheme as r, getChannelPrefixWithDelimiter as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/electron",
3
- "version": "1.5.0-beta.13",
3
+ "version": "1.5.0-beta.16",
4
4
  "type": "module",
5
5
  "description": "Better Auth integration for Electron applications.",
6
6
  "main": "dist/index.mjs",
@@ -38,6 +38,11 @@
38
38
  "types": "./dist/proxy.d.mts",
39
39
  "default": "./dist/proxy.mjs"
40
40
  },
41
+ "./preload": {
42
+ "dev-source": "./src/preload.ts",
43
+ "types": "./dist/preload.d.mts",
44
+ "default": "./dist/preload.mjs"
45
+ },
41
46
  "./storage": {
42
47
  "dev-source": "./src/storage.ts",
43
48
  "types": "./dist/storage.d.mts",
@@ -55,6 +60,9 @@
55
60
  "proxy": [
56
61
  "./dist/proxy.d.mts"
57
62
  ],
63
+ "preload": [
64
+ "./dist/preload.d.mts"
65
+ ],
58
66
  "storage": [
59
67
  "./dist/storage.d.mts"
60
68
  ]
@@ -71,20 +79,22 @@
71
79
  "peerDependencies": {
72
80
  "@better-auth/utils": "0.3.1",
73
81
  "@better-fetch/fetch": "1.1.21",
74
- "better-call": "1.2.1",
82
+ "better-call": "1.3.2",
83
+ "electron": ">=36.0.0",
75
84
  "conf": "^15.0.2",
76
- "@better-auth/core": "1.5.0-beta.13",
77
- "better-auth": "1.5.0-beta.13"
85
+ "@better-auth/core": "1.5.0-beta.16",
86
+ "better-auth": "1.5.0-beta.16"
78
87
  },
79
88
  "dependencies": {
80
89
  "zod": "^4.3.5"
81
90
  },
82
91
  "devDependencies": {
83
92
  "@types/better-sqlite3": "^7.6.13",
93
+ "electron": "^38.8.0",
84
94
  "better-sqlite3": "^12.6.2",
85
- "tsdown": "^0.20.1",
86
- "@better-auth/core": "1.5.0-beta.13",
87
- "better-auth": "1.5.0-beta.13"
95
+ "tsdown": "^0.20.3",
96
+ "@better-auth/core": "1.5.0-beta.16",
97
+ "better-auth": "1.5.0-beta.16"
88
98
  },
89
99
  "engines": {
90
100
  "node": ">=22.0.0"
@@ -1,129 +0,0 @@
1
- import * as z from "zod";
2
- import { BetterFetch } from "@better-fetch/fetch";
3
-
4
- //#region src/types/client.d.ts
5
- interface Storage {
6
- getItem: (name: string) => unknown | null;
7
- setItem: (name: string, value: unknown) => void;
8
- }
9
- interface ElectronClientOptions {
10
- /**
11
- * The URL to redirect to for authentication.
12
- *
13
- * @example "http://localhost:3000/sign-in"
14
- */
15
- signInURL: string | URL;
16
- /**
17
- * The protocol scheme to use for deep linking in Electron.
18
- *
19
- * Should follow the reverse domain name notation to ensure uniqueness.
20
- *
21
- * @see {@link https://datatracker.ietf.org/doc/html/rfc8252#section-7.1}
22
- * @example "com.example.app"
23
- */
24
- protocol: string | {
25
- scheme: string;
26
- privileges?: Electron.Privileges | undefined;
27
- };
28
- /**
29
- * The callback path to use for authentication redirects.
30
- *
31
- * @default "/auth/callback"
32
- */
33
- callbackPath?: string;
34
- /**
35
- * An instance of a storage solution (e.g., `electron-store`)
36
- * to store session and cookie data.
37
- *
38
- * @example
39
- * ```ts
40
- * electronClient({
41
- * storage: window.localStorage,
42
- * });
43
- * ```
44
- */
45
- storage: Storage;
46
- /**
47
- * Prefix for local storage keys (e.g., "my-app_cookie", "my-app_session_data")
48
- * @default "better-auth"
49
- */
50
- storagePrefix?: string | undefined;
51
- /**
52
- * Prefix(es) for server cookie names to filter (e.g., "better-auth.session_token")
53
- * This is used to identify which cookies belong to better-auth to prevent
54
- * infinite refetching when third-party cookies are set.
55
- *
56
- * Can be a single string or an array of strings to match multiple prefixes.
57
- *
58
- * @default "better-auth"
59
- * @example "better-auth"
60
- * @example ["better-auth", "my-app"]
61
- */
62
- cookiePrefix?: string | string[] | undefined;
63
- /**
64
- * Channel prefix for IPC bridges (e.g., "better-auth:request-auth")
65
- *
66
- * @default "better-auth"
67
- */
68
- channelPrefix?: string | undefined;
69
- /**
70
- * Client ID to use for identifying the Electron client during authorization.
71
- *
72
- * @default "electron"
73
- */
74
- clientID?: string | undefined;
75
- /**
76
- * Whether to disable caching the session data locally.
77
- *
78
- * @default false
79
- */
80
- disableCache?: boolean | undefined;
81
- }
82
- interface ElectronProxyClientOptions {
83
- /**
84
- * The protocol scheme to use for deep linking in Electron.
85
- *
86
- * Should follow the reverse domain name notation to ensure uniqueness.
87
- *
88
- * Note that this must match the protocol scheme registered in the server plugin.
89
- *
90
- * @see {@link https://datatracker.ietf.org/doc/html/rfc8252#section-7.1}
91
- * @example "com.example.app"
92
- */
93
- protocol: string | {
94
- scheme: string;
95
- };
96
- /**
97
- * The callback path to use for authentication redirects.
98
- *
99
- * @default "/auth/callback"
100
- */
101
- callbackPath?: string;
102
- /**
103
- * Client ID to use for identifying the Electron client during authorization.
104
- *
105
- * @default "electron"
106
- */
107
- clientID?: string | undefined;
108
- /**
109
- * The prefix to use for cookies set by the plugin.
110
- *
111
- * @default "better-auth"
112
- */
113
- cookiePrefix?: string | undefined;
114
- }
115
- //#endregion
116
- //#region src/authenticate.d.ts
117
- declare const requestAuthOptionsSchema: z.ZodObject<{
118
- provider: z.ZodOptional<z.ZodString>;
119
- callbackURL: z.ZodOptional<z.ZodString>;
120
- newUserCallbackURL: z.ZodOptional<z.ZodString>;
121
- errorCallbackURL: z.ZodOptional<z.ZodString>;
122
- disableRedirect: z.ZodOptional<z.ZodBoolean>;
123
- scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
124
- requestSignUp: z.ZodOptional<z.ZodBoolean>;
125
- additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
126
- }, z.core.$strip>;
127
- type ElectronRequestAuthOptions = z.infer<typeof requestAuthOptionsSchema>;
128
- //#endregion
129
- export { Storage as i, ElectronClientOptions as n, ElectronProxyClientOptions as r, ElectronRequestAuthOptions as t };