@glinr/theauth-electron 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,13 +1,17 @@
1
1
  # @glinr/theauth-electron
2
2
 
3
- Electron integration for TheAuth: secure storage, OAuth windows, and IPC bridge.
3
+ [npm](https://www.npmjs.com/package/@glinr/theauth-electron) · [Source](https://github.com/glincker/theauth/tree/main/packages/electron) · [Docs](https://docs.theauth.dev/electron) · [All packages](https://github.com/glincker/theauth#packages)
4
+
5
+ Electron integration for theAuth: secure storage, OAuth windows, and IPC bridge.
4
6
 
5
7
  [![npm](https://img.shields.io/npm/v/@glinr/theauth-electron?style=flat-square)](https://www.npmjs.com/package/@glinr/theauth-electron)
6
8
 
9
+ Part of [theAuth](https://theauth.dev), open-source auth for AI agents and humans. Docs: [docs.theauth.dev](https://docs.theauth.dev).
10
+
7
11
  ## Install
8
12
 
9
13
  ```bash
10
- npm install @glinr/@glinr/theauth-electron
14
+ npm install @glinr/theauth-electron
11
15
  ```
12
16
 
13
17
  ## Usage
@@ -39,21 +43,27 @@ function App() {
39
43
  // OAuth login from renderer
40
44
  import { openOAuthWindow } from '@glinr/theauth-electron';
41
45
 
42
- const result = await openOAuthWindow({ provider: 'google', redirectUri: 'kavach://oauth' });
46
+ const result = await openOAuthWindow({ provider: 'google', redirectUri: 'theauth://oauth' });
43
47
  ```
44
48
 
45
49
  ## Exports
46
50
 
47
- - `ElectronTheAuthProvider` / `ElectronTheAuthContext` / `useElectronTheAuthContext`: renderer-side provider (formerly `ElectronKavach*`, still exported as deprecated aliases)
51
+ - `ElectronTheAuthProvider` / `ElectronTheAuthContext` / `useElectronTheAuthContext`: renderer-side provider
48
52
  - `createElectronStorage`: encrypted keychain-backed storage
49
53
  - `createMemoryStorage`: in-memory storage for testing
50
- - `setupTheAuthIpc` / `createIpcStorage` / `THEAUTH_IPC_CHANNELS`: main-process IPC setup (formerly `setupKavachIpc` / `KAVACH_IPC_CHANNELS`, still exported as deprecated aliases)
54
+ - `setupTheAuthIpc` / `createIpcStorage` / `THEAUTH_IPC_CHANNELS`: main-process IPC setup
51
55
  - `openOAuthWindow`: opens a managed OAuth popup window
52
56
 
53
57
  ## Docs
54
58
 
55
59
  [https://docs.theauth.dev](https://docs.theauth.dev)
56
60
 
61
+ ## Community
62
+
63
+ [![Discord](https://img.shields.io/discord/829168897080557579?style=flat-square&logo=discord&logoColor=white&label=discord&color=5865F2)](https://discord.gg/Ar5pcaZB99)
64
+
65
+ Questions and help in the `#theauth` forum on the [GLINR Discord](https://discord.gg/Ar5pcaZB99).
66
+
57
67
  ## License
58
68
 
59
69
  MIT
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  interface ElectronStorageConfig {
5
- /** File name for the session data. Defaults to "kavach-session.json". */
5
+ /** File name for the session data. Defaults to "theauth-session.json". */
6
6
  fileName?: string;
7
7
  /** Optional additional encryption key applied on top of safeStorage. */
8
8
  encryptionKey?: string;
@@ -100,7 +100,7 @@ interface OAuthWindowConfig {
100
100
  width?: number;
101
101
  /** Window height in pixels. Defaults to 700. */
102
102
  height?: number;
103
- /** Base path where TheAuth is mounted. Defaults to "/api/kavach". */
103
+ /** Base path where TheAuth is mounted. Defaults to "/api/theauth". */
104
104
  basePath?: string;
105
105
  }
106
106
  interface OAuthWindowResult {
@@ -152,30 +152,21 @@ declare function createIpcStorage(): SecureStorage;
152
152
  * ```
153
153
  */
154
154
  declare const THEAUTH_IPC_CHANNELS: {
155
- readonly GET: "kavach:storage:get";
156
- readonly SET: "kavach:storage:set";
157
- readonly REMOVE: "kavach:storage:remove";
158
- readonly CLEAR: "kavach:storage:clear";
159
- };
160
- /** @deprecated Use `setupTheAuthIpc` instead. Will be removed in a future major version. */
161
- declare const setupKavachIpc: typeof setupTheAuthIpc;
162
- /** @deprecated Use `THEAUTH_IPC_CHANNELS` instead. Will be removed in a future major version. */
163
- declare const KAVACH_IPC_CHANNELS: {
164
- readonly GET: "kavach:storage:get";
165
- readonly SET: "kavach:storage:set";
166
- readonly REMOVE: "kavach:storage:remove";
167
- readonly CLEAR: "kavach:storage:clear";
155
+ readonly GET: "theauth:storage:get";
156
+ readonly SET: "theauth:storage:set";
157
+ readonly REMOVE: "theauth:storage:remove";
158
+ readonly CLEAR: "theauth:storage:clear";
168
159
  };
169
160
 
170
- interface KavachUser {
161
+ interface TheAuthUser {
171
162
  id: string;
172
163
  email?: string;
173
164
  name?: string;
174
165
  image?: string;
175
166
  }
176
- interface KavachSession {
167
+ interface TheAuthSession {
177
168
  token: string;
178
- user: KavachUser;
169
+ user: TheAuthUser;
179
170
  expiresAt?: string;
180
171
  }
181
172
  type ActionResult<T = void> = {
@@ -185,9 +176,9 @@ type ActionResult<T = void> = {
185
176
  success: false;
186
177
  error: string;
187
178
  };
188
- interface KavachContextValue {
189
- session: KavachSession | null;
190
- user: KavachUser | null;
179
+ interface TheAuthContextValue {
180
+ session: TheAuthSession | null;
181
+ user: TheAuthUser | null;
191
182
  isLoading: boolean;
192
183
  isAuthenticated: boolean;
193
184
  signIn: (email: string, password: string) => Promise<ActionResult>;
@@ -197,21 +188,15 @@ interface KavachContextValue {
197
188
  }
198
189
  interface ElectronTheAuthProviderProps {
199
190
  children: ReactNode;
200
- /** Base path where TheAuth is mounted. Defaults to "/api/kavach". */
191
+ /** Base path where TheAuth is mounted. Defaults to "/api/theauth". */
201
192
  basePath?: string;
202
193
  /** Custom storage adapter. Defaults to in-memory if not provided. */
203
194
  storage?: SecureStorage;
204
195
  /** Persist session to secure storage across restarts. Defaults to true. */
205
196
  persistSession?: boolean;
206
197
  }
207
- /** @deprecated Use `ElectronTheAuthProviderProps` instead. Will be removed in a future major version. */
208
- type ElectronKavachProviderProps = ElectronTheAuthProviderProps;
209
- declare const ElectronTheAuthContext: react.Context<KavachContextValue | null>;
210
- /** @deprecated Use `ElectronTheAuthContext` instead. Will be removed in a future major version. */
211
- declare const ElectronKavachContext: react.Context<KavachContextValue | null>;
212
- declare function useElectronTheAuthContext(): KavachContextValue;
213
- /** @deprecated Use `useElectronTheAuthContext` instead. Will be removed in a future major version. */
214
- declare const useElectronKavachContext: typeof useElectronTheAuthContext;
198
+ declare const ElectronTheAuthContext: react.Context<TheAuthContextValue | null>;
199
+ declare function useElectronTheAuthContext(): TheAuthContextValue;
215
200
  /**
216
201
  * Wraps your Electron renderer with TheAuth auth state.
217
202
  *
@@ -224,7 +209,5 @@ declare const useElectronKavachContext: typeof useElectronTheAuthContext;
224
209
  * depending on whether your renderer runs with Node integration or via IPC.
225
210
  */
226
211
  declare function ElectronTheAuthProvider({ children, basePath, storage, persistSession, }: ElectronTheAuthProviderProps): ReactNode;
227
- /** @deprecated Use `ElectronTheAuthProvider` instead. Will be removed in a future major version. */
228
- declare const ElectronKavachProvider: typeof ElectronTheAuthProvider;
229
212
 
230
- export { type ElectronApi, ElectronKavachContext, ElectronKavachProvider, type ElectronKavachProviderProps, type ElectronStorageConfig, ElectronTheAuthContext, ElectronTheAuthProvider, type ElectronTheAuthProviderProps, KAVACH_IPC_CHANNELS, type OAuthWindowConfig, type OAuthWindowResult, type SecureStorage, THEAUTH_IPC_CHANNELS, createElectronStorage, createIpcStorage, createMemoryStorage, openOAuthWindow, setElectronApiForTesting, setupKavachIpc, setupTheAuthIpc, useElectronKavachContext, useElectronTheAuthContext };
213
+ export { type ElectronApi, type ElectronStorageConfig, ElectronTheAuthContext, ElectronTheAuthProvider, type ElectronTheAuthProviderProps, type OAuthWindowConfig, type OAuthWindowResult, type SecureStorage, THEAUTH_IPC_CHANNELS, createElectronStorage, createIpcStorage, createMemoryStorage, openOAuthWindow, setElectronApiForTesting, setupTheAuthIpc, useElectronTheAuthContext };
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ function writeStorageFile(filePath, data) {
74
74
  fs.writeFileSync(filePath, JSON.stringify(data), "utf8");
75
75
  }
76
76
  function createElectronStorage(config) {
77
- const fileName = config?.fileName ?? "kavach-session.json";
77
+ const fileName = config?.fileName ?? "theauth-session.json";
78
78
  const encryptionKey = config?.encryptionKey ?? "";
79
79
  let warned = false;
80
80
  let filePath = null;
@@ -165,7 +165,7 @@ function createMemoryStorage() {
165
165
  }
166
166
 
167
167
  // src/oauth-window.ts
168
- var SESSION_COOKIE_NAMES = ["kavach-session", "better-auth.session_token", "__session"];
168
+ var SESSION_COOKIE_NAMES = ["theauth-session", "better-auth.session_token", "__session"];
169
169
  async function extractSessionCookie(win, baseUrl) {
170
170
  const cookies = await win.webContents.session.cookies.get({ url: baseUrl });
171
171
  for (const name of SESSION_COOKIE_NAMES) {
@@ -187,7 +187,7 @@ function extractOAuthError(url) {
187
187
  }
188
188
  }
189
189
  async function openOAuthWindow(providerId, config = {}) {
190
- const { width = 500, height = 700, basePath = "/api/kavach" } = config;
190
+ const { width = 500, height = 700, basePath = "/api/theauth" } = config;
191
191
  const base = basePath.replace(/\/$/, "");
192
192
  const { BrowserWindow } = getElectronApi();
193
193
  const win = new BrowserWindow({
@@ -248,10 +248,10 @@ async function openOAuthWindow(providerId, config = {}) {
248
248
  }
249
249
 
250
250
  // src/ipc.ts
251
- var CHANNEL_GET = "kavach:storage:get";
252
- var CHANNEL_SET = "kavach:storage:set";
253
- var CHANNEL_REMOVE = "kavach:storage:remove";
254
- var CHANNEL_CLEAR = "kavach:storage:clear";
251
+ var CHANNEL_GET = "theauth:storage:get";
252
+ var CHANNEL_SET = "theauth:storage:set";
253
+ var CHANNEL_REMOVE = "theauth:storage:remove";
254
+ var CHANNEL_CLEAR = "theauth:storage:clear";
255
255
  function setupTheAuthIpc(storage) {
256
256
  const { ipcMain } = getElectronApi();
257
257
  ipcMain.removeHandler(CHANNEL_GET);
@@ -302,15 +302,12 @@ var THEAUTH_IPC_CHANNELS = {
302
302
  REMOVE: CHANNEL_REMOVE,
303
303
  CLEAR: CHANNEL_CLEAR
304
304
  };
305
- var setupKavachIpc = setupTheAuthIpc;
306
- var KAVACH_IPC_CHANNELS = THEAUTH_IPC_CHANNELS;
307
305
 
308
306
  // src/provider.tsx
309
307
  import { createContext, useCallback, useContext, useEffect, useState } from "react";
310
308
  import { jsx } from "react/jsx-runtime";
311
- var SESSION_STORAGE_KEY = "kavach:session";
309
+ var SESSION_STORAGE_KEY = "theauth:session";
312
310
  var ElectronTheAuthContext = createContext(null);
313
- var ElectronKavachContext = ElectronTheAuthContext;
314
311
  function useElectronTheAuthContext() {
315
312
  const ctx = useContext(ElectronTheAuthContext);
316
313
  if (!ctx) {
@@ -318,7 +315,6 @@ function useElectronTheAuthContext() {
318
315
  }
319
316
  return ctx;
320
317
  }
321
- var useElectronKavachContext = useElectronTheAuthContext;
322
318
  function extractErrorMessage(body, fallback) {
323
319
  if (body !== null && typeof body === "object" && "error" in body && typeof body.error === "object" && typeof body.error?.message === "string") {
324
320
  return body.error?.message ?? fallback;
@@ -327,7 +323,7 @@ function extractErrorMessage(body, fallback) {
327
323
  }
328
324
  function ElectronTheAuthProvider({
329
325
  children,
330
- basePath = "/api/kavach",
326
+ basePath = "/api/theauth",
331
327
  storage,
332
328
  persistSession = true
333
329
  }) {
@@ -469,22 +465,16 @@ function ElectronTheAuthProvider({
469
465
  };
470
466
  return /* @__PURE__ */ jsx(ElectronTheAuthContext.Provider, { value, children });
471
467
  }
472
- var ElectronKavachProvider = ElectronTheAuthProvider;
473
468
  export {
474
- ElectronKavachContext,
475
- ElectronKavachProvider,
476
469
  ElectronTheAuthContext,
477
470
  ElectronTheAuthProvider,
478
- KAVACH_IPC_CHANNELS,
479
471
  THEAUTH_IPC_CHANNELS,
480
472
  createElectronStorage,
481
473
  createIpcStorage,
482
474
  createMemoryStorage,
483
475
  openOAuthWindow,
484
476
  setElectronApiForTesting,
485
- setupKavachIpc,
486
477
  setupTheAuthIpc,
487
- useElectronKavachContext,
488
478
  useElectronTheAuthContext
489
479
  };
490
480
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/electron-api.ts","../src/storage.ts","../src/oauth-window.ts","../src/ipc.ts","../src/provider.tsx"],"sourcesContent":["// ─── Electron API injection ───────────────────────────────────────────────────\n//\n// Modules that need Electron APIs call getElectronApi() to retrieve the live\n// bindings. In a real Electron process this resolves to the real electron\n// module; in tests it resolves to the mock set via setElectronApiForTesting().\n\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── Surface interfaces ───────────────────────────────────────────────────────\n\nexport interface ElectronSafeStorage {\n\tisEncryptionAvailable(): boolean;\n\tencryptString(value: string): Uint8Array;\n\tdecryptString(encrypted: Uint8Array): string;\n}\n\nexport interface ElectronApp {\n\tgetPath(name: \"userData\"): string;\n}\n\nexport interface BrowserWindowOptions {\n\twidth: number;\n\theight: number;\n\twebPreferences: {\n\t\tnodeIntegration: boolean;\n\t\tcontextIsolation: boolean;\n\t\tsandbox: boolean;\n\t};\n\ttitle: string;\n\tresizable: boolean;\n\tminimizable: boolean;\n\tmaximizable: boolean;\n\tshow: boolean;\n}\n\nexport interface BrowserWindowInstance {\n\tloadURL(url: string): Promise<void>;\n\ton(event: \"closed\", listener: () => void): void;\n\twebContents: {\n\t\ton(\n\t\t\tevent: \"will-redirect\" | \"will-navigate\",\n\t\t\tlistener: (event: unknown, url: string) => void,\n\t\t): void;\n\t\tsession: {\n\t\t\tcookies: {\n\t\t\t\tget(filter: { url: string }): Promise<Array<{ name: string; value: string }>>;\n\t\t\t};\n\t\t};\n\t};\n\tdestroy(): void;\n\tshow(): void;\n}\n\nexport interface BrowserWindowConstructor {\n\tnew (options: BrowserWindowOptions): BrowserWindowInstance;\n}\n\nexport type IpcMainListener = (\n\tevent: { reply(channel: string, ...args: unknown[]): void },\n\t...args: unknown[]\n) => Promise<unknown>;\n\nexport interface ElectronIpcMain {\n\thandle(channel: string, listener: IpcMainListener): void;\n\tremoveHandler(channel: string): void;\n}\n\nexport interface ElectronIpcRenderer {\n\tinvoke(channel: string, ...args: unknown[]): Promise<unknown>;\n}\n\nexport interface ElectronApi {\n\tsafeStorage: ElectronSafeStorage;\n\tapp: ElectronApp;\n\tBrowserWindow: BrowserWindowConstructor;\n\tipcMain: ElectronIpcMain;\n\tipcRenderer: ElectronIpcRenderer;\n}\n\n// ─── Singleton ────────────────────────────────────────────────────────────────\n\nlet _override: ElectronApi | null = null;\n\nfunction loadElectron(): ElectronApi | null {\n\tif (_override) return _override;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\treturn require(\"electron\") as ElectronApi;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function getElectronApi(): ElectronApi {\n\tconst api = loadElectron();\n\tif (!api) {\n\t\tthrow new Error(\n\t\t\t\"[TheAuth] Electron API not available. Ensure this code runs in an Electron process.\",\n\t\t);\n\t}\n\treturn api;\n}\n\n/**\n * For testing only — injects a mock Electron API so modules don't need a real\n * Electron runtime. Call setElectronApiForTesting(null) to reset.\n */\nexport function setElectronApiForTesting(mock: ElectronApi | null): void {\n\t_override = mock;\n}\n\n// Re-export SecureStorage so ipc.ts can reference it without a circular dep\nexport type { SecureStorage };\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ElectronSafeStorage } from \"./electron-api.js\";\nimport { getElectronApi } from \"./electron-api.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ElectronStorageConfig {\n\t/** File name for the session data. Defaults to \"kavach-session.json\". */\n\tfileName?: string;\n\t/** Optional additional encryption key applied on top of safeStorage. */\n\tencryptionKey?: string;\n}\n\nexport interface SecureStorage {\n\tget(key: string): Promise<string | null>;\n\tset(key: string, value: string): Promise<void>;\n\tremove(key: string): Promise<void>;\n\tclear(): Promise<void>;\n}\n\n// ─── XOR cipher for optional encryptionKey ────────────────────────────────────\n\nfunction xorWithKey(data: Uint8Array, key: string): Uint8Array {\n\tif (key.length === 0) return data;\n\tconst encoder = new TextEncoder();\n\tconst keyBytes = encoder.encode(key);\n\tconst result = new Uint8Array(data.length);\n\tfor (let i = 0; i < data.length; i++) {\n\t\tresult[i] = (data[i] ?? 0) ^ (keyBytes[i % keyBytes.length] ?? 0);\n\t}\n\treturn result;\n}\n\n// ─── Base64 helpers (no Buffer) ───────────────────────────────────────────────\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i] ?? 0);\n\t}\n\treturn btoa(binary);\n}\n\nfunction base64ToUint8Array(base64: string): Uint8Array {\n\tconst binary = atob(base64);\n\tconst bytes = new Uint8Array(binary.length);\n\tfor (let i = 0; i < binary.length; i++) {\n\t\tbytes[i] = binary.charCodeAt(i);\n\t}\n\treturn bytes;\n}\n\n// ─── Storage file helpers ─────────────────────────────────────────────────────\n\ntype StorageMap = Record<string, string>;\n\nfunction readStorageFile(filePath: string): StorageMap {\n\ttry {\n\t\tconst raw = fs.readFileSync(filePath, \"utf8\");\n\t\tconst parsed: unknown = JSON.parse(raw);\n\t\tif (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n\t\t\treturn parsed as StorageMap;\n\t\t}\n\t\treturn {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeStorageFile(filePath: string, data: StorageMap): void {\n\tconst dir = path.dirname(filePath);\n\tfs.mkdirSync(dir, { recursive: true });\n\tfs.writeFileSync(filePath, JSON.stringify(data), \"utf8\");\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\n/**\n * Creates a SecureStorage adapter backed by Electron's safeStorage API.\n *\n * Values are encrypted with safeStorage before being written to a JSON file\n * in the app's userData directory. If safeStorage is unavailable (e.g. during\n * testing or on headless Linux without a keychain), values are stored as\n * plaintext and a warning is emitted once.\n */\nexport function createElectronStorage(config?: ElectronStorageConfig): SecureStorage {\n\tconst fileName = config?.fileName ?? \"kavach-session.json\";\n\tconst encryptionKey = config?.encryptionKey ?? \"\";\n\n\tlet warned = false;\n\tlet filePath: string | null = null;\n\n\tfunction getFilePath(): string {\n\t\tif (filePath) return filePath;\n\t\tconst electron = getElectronApi();\n\t\tconst resolved = path.join(electron.app.getPath(\"userData\"), fileName);\n\t\tfilePath = resolved;\n\t\treturn resolved;\n\t}\n\n\tfunction getSafeStorage(): ElectronSafeStorage | null {\n\t\tconst electron = getElectronApi();\n\t\tif (!electron.safeStorage.isEncryptionAvailable()) {\n\t\t\tif (!warned) {\n\t\t\t\twarned = true;\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: intentional user-facing warning\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"TheAuth: safeStorage encryption unavailable — storing session data in plaintext\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn electron.safeStorage;\n\t}\n\n\tfunction encryptValue(value: string): string {\n\t\tconst safeStorage = getSafeStorage();\n\t\tif (!safeStorage) return value;\n\t\tconst encrypted = safeStorage.encryptString(value);\n\t\tconst keyed = encryptionKey ? xorWithKey(encrypted, encryptionKey) : encrypted;\n\t\treturn uint8ArrayToBase64(keyed);\n\t}\n\n\tfunction decryptValue(stored: string): string {\n\t\tconst safeStorage = getSafeStorage();\n\t\tif (!safeStorage) return stored;\n\t\ttry {\n\t\t\tlet bytes = base64ToUint8Array(stored);\n\t\t\tif (encryptionKey) {\n\t\t\t\tbytes = xorWithKey(bytes, encryptionKey);\n\t\t\t}\n\t\t\treturn safeStorage.decryptString(bytes);\n\t\t} catch {\n\t\t\treturn stored;\n\t\t}\n\t}\n\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\tconst map = readStorageFile(getFilePath());\n\t\t\tconst stored = map[key];\n\t\t\tif (stored === undefined) return null;\n\t\t\treturn decryptValue(stored);\n\t\t},\n\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\tconst map = readStorageFile(fp);\n\t\t\tmap[key] = encryptValue(value);\n\t\t\twriteStorageFile(fp, map);\n\t\t},\n\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\tconst map = readStorageFile(fp);\n\t\t\t// Functional deletion without `delete` operator\n\t\t\tconst next: StorageMap = {};\n\t\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\t\tif (k !== key) next[k] = v;\n\t\t\t}\n\t\t\twriteStorageFile(fp, next);\n\t\t},\n\n\t\tasync clear(): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\twriteStorageFile(fp, {});\n\t\t},\n\t};\n}\n\n/**\n * Creates a SecureStorage adapter that operates entirely in memory.\n * Useful for testing or when you explicitly do not want disk persistence.\n */\nexport function createMemoryStorage(): SecureStorage {\n\tconst store = new Map<string, string>();\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\treturn store.get(key) ?? null;\n\t\t},\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tstore.set(key, value);\n\t\t},\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tstore.delete(key);\n\t\t},\n\t\tasync clear(): Promise<void> {\n\t\t\tstore.clear();\n\t\t},\n\t};\n}\n","import type { BrowserWindowInstance } from \"./electron-api.js\";\nimport { getElectronApi } from \"./electron-api.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OAuthWindowConfig {\n\t/** Window width in pixels. Defaults to 500. */\n\twidth?: number;\n\t/** Window height in pixels. Defaults to 700. */\n\theight?: number;\n\t/** Base path where TheAuth is mounted. Defaults to \"/api/kavach\". */\n\tbasePath?: string;\n}\n\nexport interface OAuthWindowResult {\n\tsuccess: boolean;\n\terror?: string;\n}\n\n// ─── Session cookie extraction ────────────────────────────────────────────────\n\nconst SESSION_COOKIE_NAMES = [\"kavach-session\", \"better-auth.session_token\", \"__session\"];\n\nasync function extractSessionCookie(\n\twin: BrowserWindowInstance,\n\tbaseUrl: string,\n): Promise<string | null> {\n\tconst cookies = await win.webContents.session.cookies.get({ url: baseUrl });\n\tfor (const name of SESSION_COOKIE_NAMES) {\n\t\tconst cookie = cookies.find((c) => c.name === name);\n\t\tif (cookie) return cookie.value;\n\t}\n\treturn null;\n}\n\n// ─── URL parsing helpers ──────────────────────────────────────────────────────\n\nfunction isCallbackUrl(url: string, base: string): boolean {\n\tconst normalised = base.replace(/\\/$/, \"\");\n\treturn (\n\t\turl.includes(`${normalised}/callback`) ||\n\t\turl.includes(`${normalised}/oauth/callback`) ||\n\t\turl.includes(\"code=\") ||\n\t\turl.includes(\"error=\")\n\t);\n}\n\nfunction extractOAuthError(url: string): string | null {\n\ttry {\n\t\t// Use a dummy base so relative paths are accepted\n\t\tconst parsed = new URL(url, \"http://localhost\");\n\t\treturn parsed.searchParams.get(\"error_description\") ?? parsed.searchParams.get(\"error\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ─── Main export ──────────────────────────────────────────────────────────────\n\n/**\n * Opens a BrowserWindow to the OAuth authorization URL for a given provider,\n * waits for the callback redirect, extracts the session cookie, then closes\n * the window.\n *\n * Must be called from the Electron main process.\n */\nexport async function openOAuthWindow(\n\tproviderId: string,\n\tconfig: OAuthWindowConfig = {},\n): Promise<OAuthWindowResult> {\n\tconst { width = 500, height = 700, basePath = \"/api/kavach\" } = config;\n\tconst base = basePath.replace(/\\/$/, \"\");\n\n\tconst { BrowserWindow } = getElectronApi();\n\n\tconst win = new BrowserWindow({\n\t\twidth,\n\t\theight,\n\t\twebPreferences: {\n\t\t\tnodeIntegration: false,\n\t\t\tcontextIsolation: true,\n\t\t\tsandbox: true,\n\t\t},\n\t\ttitle: \"Sign in\",\n\t\tresizable: false,\n\t\tminimizable: false,\n\t\tmaximizable: false,\n\t\tshow: false,\n\t});\n\n\tconst authUrl = `${base}/sign-in/${encodeURIComponent(providerId)}?redirect=electron`;\n\n\treturn new Promise<OAuthWindowResult>((resolve) => {\n\t\tlet settled = false;\n\n\t\tfunction settle(result: OAuthWindowResult): void {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twin.destroy();\n\t\t\tresolve(result);\n\t\t}\n\n\t\twin.on(\"closed\", () => {\n\t\t\tsettle({ success: false, error: \"Window closed by user\" });\n\t\t});\n\n\t\tasync function handleNavigate(_event: unknown, url: string): Promise<void> {\n\t\t\tif (!isCallbackUrl(url, base)) return;\n\n\t\t\tconst oauthError = extractOAuthError(url);\n\t\t\tif (oauthError) {\n\t\t\t\tsettle({ success: false, error: oauthError });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst origin = new URL(url).origin;\n\t\t\t\tconst cookie = await extractSessionCookie(win, origin);\n\t\t\t\t// Treat as success whether or not we captured the cookie — the\n\t\t\t\t// session will be verified on the next server round-trip.\n\t\t\t\tvoid cookie;\n\t\t\t\tsettle({ success: true });\n\t\t\t} catch (err) {\n\t\t\t\tsettle({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Failed to extract session\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\twin.webContents.on(\"will-redirect\", (ev, url) => {\n\t\t\tvoid handleNavigate(ev, url);\n\t\t});\n\t\twin.webContents.on(\"will-navigate\", (ev, url) => {\n\t\t\tvoid handleNavigate(ev, url);\n\t\t});\n\n\t\tvoid win.loadURL(authUrl).then(() => {\n\t\t\twin.show();\n\t\t});\n\t});\n}\n","import { getElectronApi } from \"./electron-api.js\";\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── IPC channel names ────────────────────────────────────────────────────────\n\nconst CHANNEL_GET = \"kavach:storage:get\";\nconst CHANNEL_SET = \"kavach:storage:set\";\nconst CHANNEL_REMOVE = \"kavach:storage:remove\";\nconst CHANNEL_CLEAR = \"kavach:storage:clear\";\n\n// ─── Request/response types ───────────────────────────────────────────────────\n\ninterface StorageGetRequest {\n\tkey: string;\n}\n\ninterface StorageSetRequest {\n\tkey: string;\n\tvalue: string;\n}\n\ninterface StorageRemoveRequest {\n\tkey: string;\n}\n\ninterface StorageGetResponse {\n\tvalue: string | null;\n}\n\n// ─── Main process side ────────────────────────────────────────────────────────\n\n/**\n * Registers IPC handlers in the main process so the renderer can securely\n * access storage without needing direct Node.js access.\n *\n * Call this once from your main process entry point after creating your\n * SecureStorage instance via createElectronStorage().\n */\nexport function setupTheAuthIpc(storage: SecureStorage): void {\n\tconst { ipcMain } = getElectronApi();\n\n\t// Remove any previously registered handlers to allow re-initialization.\n\tipcMain.removeHandler(CHANNEL_GET);\n\tipcMain.removeHandler(CHANNEL_SET);\n\tipcMain.removeHandler(CHANNEL_REMOVE);\n\tipcMain.removeHandler(CHANNEL_CLEAR);\n\n\tipcMain.handle(CHANNEL_GET, async (_event, req: unknown): Promise<StorageGetResponse> => {\n\t\tconst { key } = req as StorageGetRequest;\n\t\tconst value = await storage.get(key);\n\t\treturn { value };\n\t});\n\n\tipcMain.handle(CHANNEL_SET, async (_event, req: unknown): Promise<void> => {\n\t\tconst { key, value } = req as StorageSetRequest;\n\t\tawait storage.set(key, value);\n\t});\n\n\tipcMain.handle(CHANNEL_REMOVE, async (_event, req: unknown): Promise<void> => {\n\t\tconst { key } = req as StorageRemoveRequest;\n\t\tawait storage.remove(key);\n\t});\n\n\tipcMain.handle(CHANNEL_CLEAR, async (): Promise<void> => {\n\t\tawait storage.clear();\n\t});\n}\n\n// ─── Renderer process side ────────────────────────────────────────────────────\n\n/**\n * Creates a SecureStorage implementation that delegates all operations to the\n * main process via IPC. Use this in the renderer process in place of a direct\n * storage adapter so that Node.js APIs and encryption stay in the main process.\n *\n * Requires contextIsolation to be enabled and the IPC channels to be exposed\n * via a preload script, or for contextIsolation to be disabled (not recommended).\n */\nexport function createIpcStorage(): SecureStorage {\n\tconst { ipcRenderer } = getElectronApi();\n\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\tconst req: StorageGetRequest = { key };\n\t\t\tconst res = (await ipcRenderer.invoke(CHANNEL_GET, req)) as StorageGetResponse;\n\t\t\treturn res.value;\n\t\t},\n\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tconst req: StorageSetRequest = { key, value };\n\t\t\tawait ipcRenderer.invoke(CHANNEL_SET, req);\n\t\t},\n\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tconst req: StorageRemoveRequest = { key };\n\t\t\tawait ipcRenderer.invoke(CHANNEL_REMOVE, req);\n\t\t},\n\n\t\tasync clear(): Promise<void> {\n\t\t\tawait ipcRenderer.invoke(CHANNEL_CLEAR);\n\t\t},\n\t};\n}\n\n// ─── Preload bridge helper ────────────────────────────────────────────────────\n\n/**\n * The IPC channel names exposed for use in a preload script with contextBridge.\n * If you use contextIsolation (recommended), expose these channels explicitly:\n *\n * ```ts\n * import { contextBridge, ipcRenderer } from \"electron\";\n * import { THEAUTH_IPC_CHANNELS } from \"@glinr/theauth-electron\";\n *\n * contextBridge.exposeInMainWorld(\"theauthStorage\", {\n * invoke: (channel: string, ...args: unknown[]) => {\n * if (!Object.values(THEAUTH_IPC_CHANNELS).includes(channel)) {\n * throw new Error(`Blocked IPC channel: ${channel}`);\n * }\n * return ipcRenderer.invoke(channel, ...args);\n * },\n * });\n * ```\n */\nexport const THEAUTH_IPC_CHANNELS = {\n\tGET: CHANNEL_GET,\n\tSET: CHANNEL_SET,\n\tREMOVE: CHANNEL_REMOVE,\n\tCLEAR: CHANNEL_CLEAR,\n} as const;\n\n// Kept for backward compatibility with the pre-rebrand \"Kavach\" API. Will be\n// removed in a future major version.\n\n/** @deprecated Use `setupTheAuthIpc` instead. Will be removed in a future major version. */\nexport const setupKavachIpc = setupTheAuthIpc;\n\n/** @deprecated Use `THEAUTH_IPC_CHANNELS` instead. Will be removed in a future major version. */\nexport const KAVACH_IPC_CHANNELS = THEAUTH_IPC_CHANNELS;\n","import type { ReactNode } from \"react\";\nimport { createContext, useCallback, useContext, useEffect, useState } from \"react\";\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface KavachUser {\n\tid: string;\n\temail?: string;\n\tname?: string;\n\timage?: string;\n}\n\ninterface KavachSession {\n\ttoken: string;\n\tuser: KavachUser;\n\texpiresAt?: string;\n}\n\ntype ActionResult<T = void> = { success: true; data: T } | { success: false; error: string };\n\ninterface KavachContextValue {\n\tsession: KavachSession | null;\n\tuser: KavachUser | null;\n\tisLoading: boolean;\n\tisAuthenticated: boolean;\n\tsignIn: (email: string, password: string) => Promise<ActionResult>;\n\tsignUp: (email: string, password: string, name?: string) => Promise<ActionResult>;\n\tsignOut: () => Promise<void>;\n\trefresh: () => Promise<void>;\n}\n\nexport interface ElectronTheAuthProviderProps {\n\tchildren: ReactNode;\n\t/** Base path where TheAuth is mounted. Defaults to \"/api/kavach\". */\n\tbasePath?: string;\n\t/** Custom storage adapter. Defaults to in-memory if not provided. */\n\tstorage?: SecureStorage;\n\t/** Persist session to secure storage across restarts. Defaults to true. */\n\tpersistSession?: boolean;\n}\n\n/** @deprecated Use `ElectronTheAuthProviderProps` instead. Will be removed in a future major version. */\nexport type ElectronKavachProviderProps = ElectronTheAuthProviderProps;\n\n// ─── Storage key ──────────────────────────────────────────────────────────────\n\nconst SESSION_STORAGE_KEY = \"kavach:session\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport const ElectronTheAuthContext = createContext<KavachContextValue | null>(null);\n\n/** @deprecated Use `ElectronTheAuthContext` instead. Will be removed in a future major version. */\nexport const ElectronKavachContext = ElectronTheAuthContext;\n\nexport function useElectronTheAuthContext(): KavachContextValue {\n\tconst ctx = useContext(ElectronTheAuthContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useElectronTheAuthContext must be used inside <ElectronTheAuthProvider>\");\n\t}\n\treturn ctx;\n}\n\n/** @deprecated Use `useElectronTheAuthContext` instead. Will be removed in a future major version. */\nexport const useElectronKavachContext = useElectronTheAuthContext;\n\n// ─── JSON fetch helpers ───────────────────────────────────────────────────────\n\ntype JsonErrorBody = { error?: { code?: string; message?: string } };\n\nfunction extractErrorMessage(body: unknown, fallback: string): string {\n\tif (\n\t\tbody !== null &&\n\t\ttypeof body === \"object\" &&\n\t\t\"error\" in body &&\n\t\ttypeof (body as JsonErrorBody).error === \"object\" &&\n\t\ttypeof (body as JsonErrorBody).error?.message === \"string\"\n\t) {\n\t\treturn (body as JsonErrorBody).error?.message ?? fallback;\n\t}\n\treturn fallback;\n}\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\n/**\n * Wraps your Electron renderer with TheAuth auth state.\n *\n * Extends the base TheAuthProvider behaviour with:\n * - Session persistence to Electron's safeStorage on sign-in\n * - Session restoration from storage on app launch\n * - Storage cleared on sign-out\n *\n * Pass a SecureStorage created by createElectronStorage() or createIpcStorage()\n * depending on whether your renderer runs with Node integration or via IPC.\n */\nexport function ElectronTheAuthProvider({\n\tchildren,\n\tbasePath = \"/api/kavach\",\n\tstorage,\n\tpersistSession = true,\n}: ElectronTheAuthProviderProps): ReactNode {\n\tconst [session, setSession] = useState<KavachSession | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst base = basePath.replace(/\\/$/, \"\");\n\n\t// ── Persist / restore helpers ───────────────────────────────────────────\n\n\tconst persistToStorage = useCallback(\n\t\tasync (s: KavachSession | null): Promise<void> => {\n\t\t\tif (!storage || !persistSession) return;\n\t\t\tif (s === null) {\n\t\t\t\tawait storage.remove(SESSION_STORAGE_KEY);\n\t\t\t} else {\n\t\t\t\tawait storage.set(SESSION_STORAGE_KEY, JSON.stringify(s));\n\t\t\t}\n\t\t},\n\t\t[storage, persistSession],\n\t);\n\n\tconst restoreFromStorage = useCallback(async (): Promise<KavachSession | null> => {\n\t\tif (!storage || !persistSession) return null;\n\t\ttry {\n\t\t\tconst raw = await storage.get(SESSION_STORAGE_KEY);\n\t\t\tif (!raw) return null;\n\t\t\tconst parsed: unknown = JSON.parse(raw);\n\t\t\tif (\n\t\t\t\tparsed !== null &&\n\t\t\t\ttypeof parsed === \"object\" &&\n\t\t\t\t\"token\" in parsed &&\n\t\t\t\ttypeof (parsed as KavachSession).token === \"string\" &&\n\t\t\t\t\"user\" in parsed &&\n\t\t\t\ttypeof (parsed as KavachSession).user === \"object\"\n\t\t\t) {\n\t\t\t\treturn parsed as KavachSession;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}, [storage, persistSession]);\n\n\t// ── Session fetch ───────────────────────────────────────────────────────\n\n\tconst fetchSession = useCallback(async (): Promise<void> => {\n\t\ttry {\n\t\t\tconst res = await fetch(`${base}/session`, { credentials: \"include\" });\n\t\t\tif (res.ok) {\n\t\t\t\tconst json = (await res.json()) as { data?: KavachSession };\n\t\t\t\tconst s = json.data ?? null;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t} else {\n\t\t\t\tsetSession(null);\n\t\t\t}\n\t\t} catch {\n\t\t\tsetSession(null);\n\t\t}\n\t}, [base, persistToStorage]);\n\n\t// ── Mount: restore from storage, then verify with server ───────────────\n\n\tuseEffect(() => {\n\t\tsetIsLoading(true);\n\n\t\tvoid (async () => {\n\t\t\tconst stored = await restoreFromStorage();\n\t\t\tif (stored) {\n\t\t\t\tsetSession(stored);\n\t\t\t}\n\t\t\t// Always verify the session with the server regardless of storage.\n\t\t\tawait fetchSession();\n\t\t\tsetIsLoading(false);\n\t\t})();\n\t}, [restoreFromStorage, fetchSession]);\n\n\t// ── Auth actions ────────────────────────────────────────────────────────\n\n\tconst refresh = useCallback(async (): Promise<void> => {\n\t\tawait fetchSession();\n\t}, [fetchSession]);\n\n\tconst signIn = useCallback(\n\t\tasync (email: string, password: string): Promise<ActionResult> => {\n\t\t\ttry {\n\t\t\t\tconst res = await fetch(`${base}/sign-in/email`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\tbody: JSON.stringify({ email, password }),\n\t\t\t\t});\n\t\t\t\tconst json = (await res.json()) as\n\t\t\t\t\t| { data: KavachSession }\n\t\t\t\t\t| { error: { code: string; message: string } };\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: extractErrorMessage(json, `Sign-in failed (${res.status})`),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst s = (json as { data: KavachSession }).data;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t\treturn { success: true, data: undefined };\n\t\t\t} catch (err) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Network error\",\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\t[base, persistToStorage],\n\t);\n\n\tconst signUp = useCallback(\n\t\tasync (email: string, password: string, name?: string): Promise<ActionResult> => {\n\t\t\ttry {\n\t\t\t\tconst res = await fetch(`${base}/sign-up/email`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\tbody: JSON.stringify({ email, password, name }),\n\t\t\t\t});\n\t\t\t\tconst json = (await res.json()) as\n\t\t\t\t\t| { data: KavachSession }\n\t\t\t\t\t| { error: { code: string; message: string } };\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: extractErrorMessage(json, `Sign-up failed (${res.status})`),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst s = (json as { data: KavachSession }).data;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t\treturn { success: true, data: undefined };\n\t\t\t} catch (err) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Network error\",\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\t[base, persistToStorage],\n\t);\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\ttry {\n\t\t\tawait fetch(`${base}/sign-out`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tcredentials: \"include\",\n\t\t\t});\n\t\t} finally {\n\t\t\tsetSession(null);\n\t\t\tawait persistToStorage(null);\n\t\t}\n\t}, [base, persistToStorage]);\n\n\t// ── Context value ───────────────────────────────────────────────────────\n\n\tconst value: KavachContextValue = {\n\t\tsession,\n\t\tuser: session?.user ?? null,\n\t\tisLoading,\n\t\tisAuthenticated: session !== null,\n\t\tsignIn,\n\t\tsignUp,\n\t\tsignOut,\n\t\trefresh,\n\t};\n\n\treturn (\n\t\t<ElectronTheAuthContext.Provider value={value}>{children}</ElectronTheAuthContext.Provider>\n\t);\n}\n\n// Kept for backward compatibility with the pre-rebrand \"Kavach\" API. Will be\n// removed in a future major version.\n\n/** @deprecated Use `ElectronTheAuthProvider` instead. Will be removed in a future major version. */\nexport const ElectronKavachProvider = ElectronTheAuthProvider;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/electron-api.ts","../src/storage.ts","../src/oauth-window.ts","../src/ipc.ts","../src/provider.tsx"],"sourcesContent":["// ─── Electron API injection ───────────────────────────────────────────────────\n//\n// Modules that need Electron APIs call getElectronApi() to retrieve the live\n// bindings. In a real Electron process this resolves to the real electron\n// module; in tests it resolves to the mock set via setElectronApiForTesting().\n\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── Surface interfaces ───────────────────────────────────────────────────────\n\nexport interface ElectronSafeStorage {\n\tisEncryptionAvailable(): boolean;\n\tencryptString(value: string): Uint8Array;\n\tdecryptString(encrypted: Uint8Array): string;\n}\n\nexport interface ElectronApp {\n\tgetPath(name: \"userData\"): string;\n}\n\nexport interface BrowserWindowOptions {\n\twidth: number;\n\theight: number;\n\twebPreferences: {\n\t\tnodeIntegration: boolean;\n\t\tcontextIsolation: boolean;\n\t\tsandbox: boolean;\n\t};\n\ttitle: string;\n\tresizable: boolean;\n\tminimizable: boolean;\n\tmaximizable: boolean;\n\tshow: boolean;\n}\n\nexport interface BrowserWindowInstance {\n\tloadURL(url: string): Promise<void>;\n\ton(event: \"closed\", listener: () => void): void;\n\twebContents: {\n\t\ton(\n\t\t\tevent: \"will-redirect\" | \"will-navigate\",\n\t\t\tlistener: (event: unknown, url: string) => void,\n\t\t): void;\n\t\tsession: {\n\t\t\tcookies: {\n\t\t\t\tget(filter: { url: string }): Promise<Array<{ name: string; value: string }>>;\n\t\t\t};\n\t\t};\n\t};\n\tdestroy(): void;\n\tshow(): void;\n}\n\nexport interface BrowserWindowConstructor {\n\tnew (options: BrowserWindowOptions): BrowserWindowInstance;\n}\n\nexport type IpcMainListener = (\n\tevent: { reply(channel: string, ...args: unknown[]): void },\n\t...args: unknown[]\n) => Promise<unknown>;\n\nexport interface ElectronIpcMain {\n\thandle(channel: string, listener: IpcMainListener): void;\n\tremoveHandler(channel: string): void;\n}\n\nexport interface ElectronIpcRenderer {\n\tinvoke(channel: string, ...args: unknown[]): Promise<unknown>;\n}\n\nexport interface ElectronApi {\n\tsafeStorage: ElectronSafeStorage;\n\tapp: ElectronApp;\n\tBrowserWindow: BrowserWindowConstructor;\n\tipcMain: ElectronIpcMain;\n\tipcRenderer: ElectronIpcRenderer;\n}\n\n// ─── Singleton ────────────────────────────────────────────────────────────────\n\nlet _override: ElectronApi | null = null;\n\nfunction loadElectron(): ElectronApi | null {\n\tif (_override) return _override;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\treturn require(\"electron\") as ElectronApi;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function getElectronApi(): ElectronApi {\n\tconst api = loadElectron();\n\tif (!api) {\n\t\tthrow new Error(\n\t\t\t\"[TheAuth] Electron API not available. Ensure this code runs in an Electron process.\",\n\t\t);\n\t}\n\treturn api;\n}\n\n/**\n * For testing only — injects a mock Electron API so modules don't need a real\n * Electron runtime. Call setElectronApiForTesting(null) to reset.\n */\nexport function setElectronApiForTesting(mock: ElectronApi | null): void {\n\t_override = mock;\n}\n\n// Re-export SecureStorage so ipc.ts can reference it without a circular dep\nexport type { SecureStorage };\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ElectronSafeStorage } from \"./electron-api.js\";\nimport { getElectronApi } from \"./electron-api.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ElectronStorageConfig {\n\t/** File name for the session data. Defaults to \"theauth-session.json\". */\n\tfileName?: string;\n\t/** Optional additional encryption key applied on top of safeStorage. */\n\tencryptionKey?: string;\n}\n\nexport interface SecureStorage {\n\tget(key: string): Promise<string | null>;\n\tset(key: string, value: string): Promise<void>;\n\tremove(key: string): Promise<void>;\n\tclear(): Promise<void>;\n}\n\n// ─── XOR cipher for optional encryptionKey ────────────────────────────────────\n\nfunction xorWithKey(data: Uint8Array, key: string): Uint8Array {\n\tif (key.length === 0) return data;\n\tconst encoder = new TextEncoder();\n\tconst keyBytes = encoder.encode(key);\n\tconst result = new Uint8Array(data.length);\n\tfor (let i = 0; i < data.length; i++) {\n\t\tresult[i] = (data[i] ?? 0) ^ (keyBytes[i % keyBytes.length] ?? 0);\n\t}\n\treturn result;\n}\n\n// ─── Base64 helpers (no Buffer) ───────────────────────────────────────────────\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i] ?? 0);\n\t}\n\treturn btoa(binary);\n}\n\nfunction base64ToUint8Array(base64: string): Uint8Array {\n\tconst binary = atob(base64);\n\tconst bytes = new Uint8Array(binary.length);\n\tfor (let i = 0; i < binary.length; i++) {\n\t\tbytes[i] = binary.charCodeAt(i);\n\t}\n\treturn bytes;\n}\n\n// ─── Storage file helpers ─────────────────────────────────────────────────────\n\ntype StorageMap = Record<string, string>;\n\nfunction readStorageFile(filePath: string): StorageMap {\n\ttry {\n\t\tconst raw = fs.readFileSync(filePath, \"utf8\");\n\t\tconst parsed: unknown = JSON.parse(raw);\n\t\tif (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n\t\t\treturn parsed as StorageMap;\n\t\t}\n\t\treturn {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeStorageFile(filePath: string, data: StorageMap): void {\n\tconst dir = path.dirname(filePath);\n\tfs.mkdirSync(dir, { recursive: true });\n\tfs.writeFileSync(filePath, JSON.stringify(data), \"utf8\");\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\n/**\n * Creates a SecureStorage adapter backed by Electron's safeStorage API.\n *\n * Values are encrypted with safeStorage before being written to a JSON file\n * in the app's userData directory. If safeStorage is unavailable (e.g. during\n * testing or on headless Linux without a keychain), values are stored as\n * plaintext and a warning is emitted once.\n */\nexport function createElectronStorage(config?: ElectronStorageConfig): SecureStorage {\n\tconst fileName = config?.fileName ?? \"theauth-session.json\";\n\tconst encryptionKey = config?.encryptionKey ?? \"\";\n\n\tlet warned = false;\n\tlet filePath: string | null = null;\n\n\tfunction getFilePath(): string {\n\t\tif (filePath) return filePath;\n\t\tconst electron = getElectronApi();\n\t\tconst resolved = path.join(electron.app.getPath(\"userData\"), fileName);\n\t\tfilePath = resolved;\n\t\treturn resolved;\n\t}\n\n\tfunction getSafeStorage(): ElectronSafeStorage | null {\n\t\tconst electron = getElectronApi();\n\t\tif (!electron.safeStorage.isEncryptionAvailable()) {\n\t\t\tif (!warned) {\n\t\t\t\twarned = true;\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: intentional user-facing warning\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"TheAuth: safeStorage encryption unavailable — storing session data in plaintext\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn electron.safeStorage;\n\t}\n\n\tfunction encryptValue(value: string): string {\n\t\tconst safeStorage = getSafeStorage();\n\t\tif (!safeStorage) return value;\n\t\tconst encrypted = safeStorage.encryptString(value);\n\t\tconst keyed = encryptionKey ? xorWithKey(encrypted, encryptionKey) : encrypted;\n\t\treturn uint8ArrayToBase64(keyed);\n\t}\n\n\tfunction decryptValue(stored: string): string {\n\t\tconst safeStorage = getSafeStorage();\n\t\tif (!safeStorage) return stored;\n\t\ttry {\n\t\t\tlet bytes = base64ToUint8Array(stored);\n\t\t\tif (encryptionKey) {\n\t\t\t\tbytes = xorWithKey(bytes, encryptionKey);\n\t\t\t}\n\t\t\treturn safeStorage.decryptString(bytes);\n\t\t} catch {\n\t\t\treturn stored;\n\t\t}\n\t}\n\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\tconst map = readStorageFile(getFilePath());\n\t\t\tconst stored = map[key];\n\t\t\tif (stored === undefined) return null;\n\t\t\treturn decryptValue(stored);\n\t\t},\n\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\tconst map = readStorageFile(fp);\n\t\t\tmap[key] = encryptValue(value);\n\t\t\twriteStorageFile(fp, map);\n\t\t},\n\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\tconst map = readStorageFile(fp);\n\t\t\t// Functional deletion without `delete` operator\n\t\t\tconst next: StorageMap = {};\n\t\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\t\tif (k !== key) next[k] = v;\n\t\t\t}\n\t\t\twriteStorageFile(fp, next);\n\t\t},\n\n\t\tasync clear(): Promise<void> {\n\t\t\tconst fp = getFilePath();\n\t\t\twriteStorageFile(fp, {});\n\t\t},\n\t};\n}\n\n/**\n * Creates a SecureStorage adapter that operates entirely in memory.\n * Useful for testing or when you explicitly do not want disk persistence.\n */\nexport function createMemoryStorage(): SecureStorage {\n\tconst store = new Map<string, string>();\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\treturn store.get(key) ?? null;\n\t\t},\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tstore.set(key, value);\n\t\t},\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tstore.delete(key);\n\t\t},\n\t\tasync clear(): Promise<void> {\n\t\t\tstore.clear();\n\t\t},\n\t};\n}\n","import type { BrowserWindowInstance } from \"./electron-api.js\";\nimport { getElectronApi } from \"./electron-api.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OAuthWindowConfig {\n\t/** Window width in pixels. Defaults to 500. */\n\twidth?: number;\n\t/** Window height in pixels. Defaults to 700. */\n\theight?: number;\n\t/** Base path where TheAuth is mounted. Defaults to \"/api/theauth\". */\n\tbasePath?: string;\n}\n\nexport interface OAuthWindowResult {\n\tsuccess: boolean;\n\terror?: string;\n}\n\n// ─── Session cookie extraction ────────────────────────────────────────────────\n\nconst SESSION_COOKIE_NAMES = [\"theauth-session\", \"better-auth.session_token\", \"__session\"];\n\nasync function extractSessionCookie(\n\twin: BrowserWindowInstance,\n\tbaseUrl: string,\n): Promise<string | null> {\n\tconst cookies = await win.webContents.session.cookies.get({ url: baseUrl });\n\tfor (const name of SESSION_COOKIE_NAMES) {\n\t\tconst cookie = cookies.find((c) => c.name === name);\n\t\tif (cookie) return cookie.value;\n\t}\n\treturn null;\n}\n\n// ─── URL parsing helpers ──────────────────────────────────────────────────────\n\nfunction isCallbackUrl(url: string, base: string): boolean {\n\tconst normalised = base.replace(/\\/$/, \"\");\n\treturn (\n\t\turl.includes(`${normalised}/callback`) ||\n\t\turl.includes(`${normalised}/oauth/callback`) ||\n\t\turl.includes(\"code=\") ||\n\t\turl.includes(\"error=\")\n\t);\n}\n\nfunction extractOAuthError(url: string): string | null {\n\ttry {\n\t\t// Use a dummy base so relative paths are accepted\n\t\tconst parsed = new URL(url, \"http://localhost\");\n\t\treturn parsed.searchParams.get(\"error_description\") ?? parsed.searchParams.get(\"error\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ─── Main export ──────────────────────────────────────────────────────────────\n\n/**\n * Opens a BrowserWindow to the OAuth authorization URL for a given provider,\n * waits for the callback redirect, extracts the session cookie, then closes\n * the window.\n *\n * Must be called from the Electron main process.\n */\nexport async function openOAuthWindow(\n\tproviderId: string,\n\tconfig: OAuthWindowConfig = {},\n): Promise<OAuthWindowResult> {\n\tconst { width = 500, height = 700, basePath = \"/api/theauth\" } = config;\n\tconst base = basePath.replace(/\\/$/, \"\");\n\n\tconst { BrowserWindow } = getElectronApi();\n\n\tconst win = new BrowserWindow({\n\t\twidth,\n\t\theight,\n\t\twebPreferences: {\n\t\t\tnodeIntegration: false,\n\t\t\tcontextIsolation: true,\n\t\t\tsandbox: true,\n\t\t},\n\t\ttitle: \"Sign in\",\n\t\tresizable: false,\n\t\tminimizable: false,\n\t\tmaximizable: false,\n\t\tshow: false,\n\t});\n\n\tconst authUrl = `${base}/sign-in/${encodeURIComponent(providerId)}?redirect=electron`;\n\n\treturn new Promise<OAuthWindowResult>((resolve) => {\n\t\tlet settled = false;\n\n\t\tfunction settle(result: OAuthWindowResult): void {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twin.destroy();\n\t\t\tresolve(result);\n\t\t}\n\n\t\twin.on(\"closed\", () => {\n\t\t\tsettle({ success: false, error: \"Window closed by user\" });\n\t\t});\n\n\t\tasync function handleNavigate(_event: unknown, url: string): Promise<void> {\n\t\t\tif (!isCallbackUrl(url, base)) return;\n\n\t\t\tconst oauthError = extractOAuthError(url);\n\t\t\tif (oauthError) {\n\t\t\t\tsettle({ success: false, error: oauthError });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst origin = new URL(url).origin;\n\t\t\t\tconst cookie = await extractSessionCookie(win, origin);\n\t\t\t\t// Treat as success whether or not we captured the cookie — the\n\t\t\t\t// session will be verified on the next server round-trip.\n\t\t\t\tvoid cookie;\n\t\t\t\tsettle({ success: true });\n\t\t\t} catch (err) {\n\t\t\t\tsettle({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Failed to extract session\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\twin.webContents.on(\"will-redirect\", (ev, url) => {\n\t\t\tvoid handleNavigate(ev, url);\n\t\t});\n\t\twin.webContents.on(\"will-navigate\", (ev, url) => {\n\t\t\tvoid handleNavigate(ev, url);\n\t\t});\n\n\t\tvoid win.loadURL(authUrl).then(() => {\n\t\t\twin.show();\n\t\t});\n\t});\n}\n","import { getElectronApi } from \"./electron-api.js\";\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── IPC channel names ────────────────────────────────────────────────────────\n\nconst CHANNEL_GET = \"theauth:storage:get\";\nconst CHANNEL_SET = \"theauth:storage:set\";\nconst CHANNEL_REMOVE = \"theauth:storage:remove\";\nconst CHANNEL_CLEAR = \"theauth:storage:clear\";\n\n// ─── Request/response types ───────────────────────────────────────────────────\n\ninterface StorageGetRequest {\n\tkey: string;\n}\n\ninterface StorageSetRequest {\n\tkey: string;\n\tvalue: string;\n}\n\ninterface StorageRemoveRequest {\n\tkey: string;\n}\n\ninterface StorageGetResponse {\n\tvalue: string | null;\n}\n\n// ─── Main process side ────────────────────────────────────────────────────────\n\n/**\n * Registers IPC handlers in the main process so the renderer can securely\n * access storage without needing direct Node.js access.\n *\n * Call this once from your main process entry point after creating your\n * SecureStorage instance via createElectronStorage().\n */\nexport function setupTheAuthIpc(storage: SecureStorage): void {\n\tconst { ipcMain } = getElectronApi();\n\n\t// Remove any previously registered handlers to allow re-initialization.\n\tipcMain.removeHandler(CHANNEL_GET);\n\tipcMain.removeHandler(CHANNEL_SET);\n\tipcMain.removeHandler(CHANNEL_REMOVE);\n\tipcMain.removeHandler(CHANNEL_CLEAR);\n\n\tipcMain.handle(CHANNEL_GET, async (_event, req: unknown): Promise<StorageGetResponse> => {\n\t\tconst { key } = req as StorageGetRequest;\n\t\tconst value = await storage.get(key);\n\t\treturn { value };\n\t});\n\n\tipcMain.handle(CHANNEL_SET, async (_event, req: unknown): Promise<void> => {\n\t\tconst { key, value } = req as StorageSetRequest;\n\t\tawait storage.set(key, value);\n\t});\n\n\tipcMain.handle(CHANNEL_REMOVE, async (_event, req: unknown): Promise<void> => {\n\t\tconst { key } = req as StorageRemoveRequest;\n\t\tawait storage.remove(key);\n\t});\n\n\tipcMain.handle(CHANNEL_CLEAR, async (): Promise<void> => {\n\t\tawait storage.clear();\n\t});\n}\n\n// ─── Renderer process side ────────────────────────────────────────────────────\n\n/**\n * Creates a SecureStorage implementation that delegates all operations to the\n * main process via IPC. Use this in the renderer process in place of a direct\n * storage adapter so that Node.js APIs and encryption stay in the main process.\n *\n * Requires contextIsolation to be enabled and the IPC channels to be exposed\n * via a preload script, or for contextIsolation to be disabled (not recommended).\n */\nexport function createIpcStorage(): SecureStorage {\n\tconst { ipcRenderer } = getElectronApi();\n\n\treturn {\n\t\tasync get(key: string): Promise<string | null> {\n\t\t\tconst req: StorageGetRequest = { key };\n\t\t\tconst res = (await ipcRenderer.invoke(CHANNEL_GET, req)) as StorageGetResponse;\n\t\t\treturn res.value;\n\t\t},\n\n\t\tasync set(key: string, value: string): Promise<void> {\n\t\t\tconst req: StorageSetRequest = { key, value };\n\t\t\tawait ipcRenderer.invoke(CHANNEL_SET, req);\n\t\t},\n\n\t\tasync remove(key: string): Promise<void> {\n\t\t\tconst req: StorageRemoveRequest = { key };\n\t\t\tawait ipcRenderer.invoke(CHANNEL_REMOVE, req);\n\t\t},\n\n\t\tasync clear(): Promise<void> {\n\t\t\tawait ipcRenderer.invoke(CHANNEL_CLEAR);\n\t\t},\n\t};\n}\n\n// ─── Preload bridge helper ────────────────────────────────────────────────────\n\n/**\n * The IPC channel names exposed for use in a preload script with contextBridge.\n * If you use contextIsolation (recommended), expose these channels explicitly:\n *\n * ```ts\n * import { contextBridge, ipcRenderer } from \"electron\";\n * import { THEAUTH_IPC_CHANNELS } from \"@glinr/theauth-electron\";\n *\n * contextBridge.exposeInMainWorld(\"theauthStorage\", {\n * invoke: (channel: string, ...args: unknown[]) => {\n * if (!Object.values(THEAUTH_IPC_CHANNELS).includes(channel)) {\n * throw new Error(`Blocked IPC channel: ${channel}`);\n * }\n * return ipcRenderer.invoke(channel, ...args);\n * },\n * });\n * ```\n */\nexport const THEAUTH_IPC_CHANNELS = {\n\tGET: CHANNEL_GET,\n\tSET: CHANNEL_SET,\n\tREMOVE: CHANNEL_REMOVE,\n\tCLEAR: CHANNEL_CLEAR,\n} as const;\n\n// Kept for backward compatibility with the pre-rebrand \"TheAuth\" API. Will be\n// removed in a future major version.\n","import type { ReactNode } from \"react\";\nimport { createContext, useCallback, useContext, useEffect, useState } from \"react\";\nimport type { SecureStorage } from \"./storage.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface TheAuthUser {\n\tid: string;\n\temail?: string;\n\tname?: string;\n\timage?: string;\n}\n\ninterface TheAuthSession {\n\ttoken: string;\n\tuser: TheAuthUser;\n\texpiresAt?: string;\n}\n\ntype ActionResult<T = void> = { success: true; data: T } | { success: false; error: string };\n\ninterface TheAuthContextValue {\n\tsession: TheAuthSession | null;\n\tuser: TheAuthUser | null;\n\tisLoading: boolean;\n\tisAuthenticated: boolean;\n\tsignIn: (email: string, password: string) => Promise<ActionResult>;\n\tsignUp: (email: string, password: string, name?: string) => Promise<ActionResult>;\n\tsignOut: () => Promise<void>;\n\trefresh: () => Promise<void>;\n}\n\nexport interface ElectronTheAuthProviderProps {\n\tchildren: ReactNode;\n\t/** Base path where TheAuth is mounted. Defaults to \"/api/theauth\". */\n\tbasePath?: string;\n\t/** Custom storage adapter. Defaults to in-memory if not provided. */\n\tstorage?: SecureStorage;\n\t/** Persist session to secure storage across restarts. Defaults to true. */\n\tpersistSession?: boolean;\n}\n\n// ─── Storage key ──────────────────────────────────────────────────────────────\n\nconst SESSION_STORAGE_KEY = \"theauth:session\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport const ElectronTheAuthContext = createContext<TheAuthContextValue | null>(null);\n\nexport function useElectronTheAuthContext(): TheAuthContextValue {\n\tconst ctx = useContext(ElectronTheAuthContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useElectronTheAuthContext must be used inside <ElectronTheAuthProvider>\");\n\t}\n\treturn ctx;\n}\n\n// ─── JSON fetch helpers ───────────────────────────────────────────────────────\n\ntype JsonErrorBody = { error?: { code?: string; message?: string } };\n\nfunction extractErrorMessage(body: unknown, fallback: string): string {\n\tif (\n\t\tbody !== null &&\n\t\ttypeof body === \"object\" &&\n\t\t\"error\" in body &&\n\t\ttypeof (body as JsonErrorBody).error === \"object\" &&\n\t\ttypeof (body as JsonErrorBody).error?.message === \"string\"\n\t) {\n\t\treturn (body as JsonErrorBody).error?.message ?? fallback;\n\t}\n\treturn fallback;\n}\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\n/**\n * Wraps your Electron renderer with TheAuth auth state.\n *\n * Extends the base TheAuthProvider behaviour with:\n * - Session persistence to Electron's safeStorage on sign-in\n * - Session restoration from storage on app launch\n * - Storage cleared on sign-out\n *\n * Pass a SecureStorage created by createElectronStorage() or createIpcStorage()\n * depending on whether your renderer runs with Node integration or via IPC.\n */\nexport function ElectronTheAuthProvider({\n\tchildren,\n\tbasePath = \"/api/theauth\",\n\tstorage,\n\tpersistSession = true,\n}: ElectronTheAuthProviderProps): ReactNode {\n\tconst [session, setSession] = useState<TheAuthSession | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst base = basePath.replace(/\\/$/, \"\");\n\n\t// ── Persist / restore helpers ───────────────────────────────────────────\n\n\tconst persistToStorage = useCallback(\n\t\tasync (s: TheAuthSession | null): Promise<void> => {\n\t\t\tif (!storage || !persistSession) return;\n\t\t\tif (s === null) {\n\t\t\t\tawait storage.remove(SESSION_STORAGE_KEY);\n\t\t\t} else {\n\t\t\t\tawait storage.set(SESSION_STORAGE_KEY, JSON.stringify(s));\n\t\t\t}\n\t\t},\n\t\t[storage, persistSession],\n\t);\n\n\tconst restoreFromStorage = useCallback(async (): Promise<TheAuthSession | null> => {\n\t\tif (!storage || !persistSession) return null;\n\t\ttry {\n\t\t\tconst raw = await storage.get(SESSION_STORAGE_KEY);\n\t\t\tif (!raw) return null;\n\t\t\tconst parsed: unknown = JSON.parse(raw);\n\t\t\tif (\n\t\t\t\tparsed !== null &&\n\t\t\t\ttypeof parsed === \"object\" &&\n\t\t\t\t\"token\" in parsed &&\n\t\t\t\ttypeof (parsed as TheAuthSession).token === \"string\" &&\n\t\t\t\t\"user\" in parsed &&\n\t\t\t\ttypeof (parsed as TheAuthSession).user === \"object\"\n\t\t\t) {\n\t\t\t\treturn parsed as TheAuthSession;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}, [storage, persistSession]);\n\n\t// ── Session fetch ───────────────────────────────────────────────────────\n\n\tconst fetchSession = useCallback(async (): Promise<void> => {\n\t\ttry {\n\t\t\tconst res = await fetch(`${base}/session`, { credentials: \"include\" });\n\t\t\tif (res.ok) {\n\t\t\t\tconst json = (await res.json()) as { data?: TheAuthSession };\n\t\t\t\tconst s = json.data ?? null;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t} else {\n\t\t\t\tsetSession(null);\n\t\t\t}\n\t\t} catch {\n\t\t\tsetSession(null);\n\t\t}\n\t}, [base, persistToStorage]);\n\n\t// ── Mount: restore from storage, then verify with server ───────────────\n\n\tuseEffect(() => {\n\t\tsetIsLoading(true);\n\n\t\tvoid (async () => {\n\t\t\tconst stored = await restoreFromStorage();\n\t\t\tif (stored) {\n\t\t\t\tsetSession(stored);\n\t\t\t}\n\t\t\t// Always verify the session with the server regardless of storage.\n\t\t\tawait fetchSession();\n\t\t\tsetIsLoading(false);\n\t\t})();\n\t}, [restoreFromStorage, fetchSession]);\n\n\t// ── Auth actions ────────────────────────────────────────────────────────\n\n\tconst refresh = useCallback(async (): Promise<void> => {\n\t\tawait fetchSession();\n\t}, [fetchSession]);\n\n\tconst signIn = useCallback(\n\t\tasync (email: string, password: string): Promise<ActionResult> => {\n\t\t\ttry {\n\t\t\t\tconst res = await fetch(`${base}/sign-in/email`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\tbody: JSON.stringify({ email, password }),\n\t\t\t\t});\n\t\t\t\tconst json = (await res.json()) as\n\t\t\t\t\t| { data: TheAuthSession }\n\t\t\t\t\t| { error: { code: string; message: string } };\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: extractErrorMessage(json, `Sign-in failed (${res.status})`),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst s = (json as { data: TheAuthSession }).data;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t\treturn { success: true, data: undefined };\n\t\t\t} catch (err) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Network error\",\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\t[base, persistToStorage],\n\t);\n\n\tconst signUp = useCallback(\n\t\tasync (email: string, password: string, name?: string): Promise<ActionResult> => {\n\t\t\ttry {\n\t\t\t\tconst res = await fetch(`${base}/sign-up/email`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\tbody: JSON.stringify({ email, password, name }),\n\t\t\t\t});\n\t\t\t\tconst json = (await res.json()) as\n\t\t\t\t\t| { data: TheAuthSession }\n\t\t\t\t\t| { error: { code: string; message: string } };\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror: extractErrorMessage(json, `Sign-up failed (${res.status})`),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst s = (json as { data: TheAuthSession }).data;\n\t\t\t\tsetSession(s);\n\t\t\t\tawait persistToStorage(s);\n\t\t\t\treturn { success: true, data: undefined };\n\t\t\t} catch (err) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: err instanceof Error ? err.message : \"Network error\",\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\t[base, persistToStorage],\n\t);\n\n\tconst signOut = useCallback(async (): Promise<void> => {\n\t\ttry {\n\t\t\tawait fetch(`${base}/sign-out`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tcredentials: \"include\",\n\t\t\t});\n\t\t} finally {\n\t\t\tsetSession(null);\n\t\t\tawait persistToStorage(null);\n\t\t}\n\t}, [base, persistToStorage]);\n\n\t// ── Context value ───────────────────────────────────────────────────────\n\n\tconst value: TheAuthContextValue = {\n\t\tsession,\n\t\tuser: session?.user ?? null,\n\t\tisLoading,\n\t\tisAuthenticated: session !== null,\n\t\tsignIn,\n\t\tsignUp,\n\t\tsignOut,\n\t\trefresh,\n\t};\n\n\treturn (\n\t\t<ElectronTheAuthContext.Provider value={value}>{children}</ElectronTheAuthContext.Provider>\n\t);\n}\n\n// Kept for backward compatibility with the pre-rebrand \"TheAuth\" API. Will be\n// removed in a future major version.\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glinr/theauth-electron",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "TheAuth auth client for Electron desktop apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,10 +15,10 @@
15
15
  "dist"
16
16
  ],
17
17
  "license": "MIT",
18
- "author": "TheAuth <support@glincker.com>",
18
+ "author": "TheAuth <support@glinr.com>",
19
19
  "repository": {
20
20
  "type": "git",
21
- "url": "https://github.com/glincker/theauth.git",
21
+ "url": "git+https://github.com/glincker/theauth.git",
22
22
  "directory": "packages/electron"
23
23
  },
24
24
  "peerDependencies": {
@@ -34,6 +34,20 @@
34
34
  "typescript": "^6.0.3",
35
35
  "vitest": "^2.0.0"
36
36
  },
37
+ "homepage": "https://docs.theauth.dev/electron",
38
+ "bugs": {
39
+ "url": "https://github.com/glincker/theauth/issues"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "keywords": [
45
+ "theauth",
46
+ "auth",
47
+ "electron",
48
+ "desktop",
49
+ "typescript"
50
+ ],
37
51
  "scripts": {
38
52
  "build": "tsup",
39
53
  "typecheck": "tsc --noEmit",