@glinr/theauth-electron 0.1.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
@@ -16,21 +20,21 @@ Set up the IPC bridge in the main process, then use the provider in the renderer
16
20
 
17
21
  ```ts
18
22
  // main.ts (main process)
19
- import { setupKavachIpc, createElectronStorage } from '@glinr/theauth-electron';
23
+ import { setupTheAuthIpc, createElectronStorage } from '@glinr/theauth-electron';
20
24
 
21
25
  const storage = createElectronStorage({ encryptionKey: process.env.STORAGE_KEY });
22
- setupKavachIpc({ storage });
26
+ setupTheAuthIpc({ storage });
23
27
  ```
24
28
 
25
29
  ```tsx
26
30
  // renderer.tsx
27
- import { ElectronKavachProvider, useElectronKavachContext } from '@glinr/theauth-electron';
31
+ import { ElectronTheAuthProvider, useElectronTheAuthContext } from '@glinr/theauth-electron';
28
32
 
29
33
  function App() {
30
34
  return (
31
- <ElectronKavachProvider apiUrl="https://auth.yourapp.com" tenantId="your-tenant-id">
35
+ <ElectronTheAuthProvider apiUrl="https://auth.yourapp.com" tenantId="your-tenant-id">
32
36
  <MainWindow />
33
- </ElectronKavachProvider>
37
+ </ElectronTheAuthProvider>
34
38
  );
35
39
  }
36
40
  ```
@@ -39,20 +43,26 @@ 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
- - `ElectronKavachProvider` / `ElectronKavachContext` / `useElectronKavachContext`: renderer-side provider
51
+ - `ElectronTheAuthProvider` / `ElectronTheAuthContext` / `useElectronTheAuthContext`: renderer-side provider
48
52
  - `createElectronStorage`: encrypted keychain-backed storage
49
53
  - `createMemoryStorage`: in-memory storage for testing
50
- - `setupKavachIpc` / `createIpcStorage` / `KAVACH_IPC_CHANNELS`: main-process IPC setup
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
- [https://docs.theauth.com](https://docs.theauth.com)
59
+ [https://docs.theauth.dev](https://docs.theauth.dev)
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).
56
66
 
57
67
  ## License
58
68
 
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 {
@@ -123,7 +123,7 @@ declare function openOAuthWindow(providerId: string, config?: OAuthWindowConfig)
123
123
  * Call this once from your main process entry point after creating your
124
124
  * SecureStorage instance via createElectronStorage().
125
125
  */
126
- declare function setupKavachIpc(storage: SecureStorage): void;
126
+ declare function setupTheAuthIpc(storage: SecureStorage): void;
127
127
  /**
128
128
  * Creates a SecureStorage implementation that delegates all operations to the
129
129
  * main process via IPC. Use this in the renderer process in place of a direct
@@ -139,11 +139,11 @@ declare function createIpcStorage(): SecureStorage;
139
139
  *
140
140
  * ```ts
141
141
  * import { contextBridge, ipcRenderer } from "electron";
142
- * import { KAVACH_IPC_CHANNELS } from "@glinr/theauth-electron";
142
+ * import { THEAUTH_IPC_CHANNELS } from "@glinr/theauth-electron";
143
143
  *
144
- * contextBridge.exposeInMainWorld("kavachStorage", {
144
+ * contextBridge.exposeInMainWorld("theauthStorage", {
145
145
  * invoke: (channel: string, ...args: unknown[]) => {
146
- * if (!Object.values(KAVACH_IPC_CHANNELS).includes(channel)) {
146
+ * if (!Object.values(THEAUTH_IPC_CHANNELS).includes(channel)) {
147
147
  * throw new Error(`Blocked IPC channel: ${channel}`);
148
148
  * }
149
149
  * return ipcRenderer.invoke(channel, ...args);
@@ -151,22 +151,22 @@ declare function createIpcStorage(): SecureStorage;
151
151
  * });
152
152
  * ```
153
153
  */
154
- declare const KAVACH_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";
154
+ declare const THEAUTH_IPC_CHANNELS: {
155
+ readonly GET: "theauth:storage:get";
156
+ readonly SET: "theauth:storage:set";
157
+ readonly REMOVE: "theauth:storage:remove";
158
+ readonly CLEAR: "theauth:storage:clear";
159
159
  };
160
160
 
161
- interface KavachUser {
161
+ interface TheAuthUser {
162
162
  id: string;
163
163
  email?: string;
164
164
  name?: string;
165
165
  image?: string;
166
166
  }
167
- interface KavachSession {
167
+ interface TheAuthSession {
168
168
  token: string;
169
- user: KavachUser;
169
+ user: TheAuthUser;
170
170
  expiresAt?: string;
171
171
  }
172
172
  type ActionResult<T = void> = {
@@ -176,9 +176,9 @@ type ActionResult<T = void> = {
176
176
  success: false;
177
177
  error: string;
178
178
  };
179
- interface KavachContextValue {
180
- session: KavachSession | null;
181
- user: KavachUser | null;
179
+ interface TheAuthContextValue {
180
+ session: TheAuthSession | null;
181
+ user: TheAuthUser | null;
182
182
  isLoading: boolean;
183
183
  isAuthenticated: boolean;
184
184
  signIn: (email: string, password: string) => Promise<ActionResult>;
@@ -186,21 +186,21 @@ interface KavachContextValue {
186
186
  signOut: () => Promise<void>;
187
187
  refresh: () => Promise<void>;
188
188
  }
189
- interface ElectronKavachProviderProps {
189
+ interface ElectronTheAuthProviderProps {
190
190
  children: ReactNode;
191
- /** Base path where TheAuth is mounted. Defaults to "/api/kavach". */
191
+ /** Base path where TheAuth is mounted. Defaults to "/api/theauth". */
192
192
  basePath?: string;
193
193
  /** Custom storage adapter. Defaults to in-memory if not provided. */
194
194
  storage?: SecureStorage;
195
195
  /** Persist session to secure storage across restarts. Defaults to true. */
196
196
  persistSession?: boolean;
197
197
  }
198
- declare const ElectronKavachContext: react.Context<KavachContextValue | null>;
199
- declare function useElectronKavachContext(): KavachContextValue;
198
+ declare const ElectronTheAuthContext: react.Context<TheAuthContextValue | null>;
199
+ declare function useElectronTheAuthContext(): TheAuthContextValue;
200
200
  /**
201
201
  * Wraps your Electron renderer with TheAuth auth state.
202
202
  *
203
- * Extends the base KavachProvider behaviour with:
203
+ * Extends the base TheAuthProvider behaviour with:
204
204
  * - Session persistence to Electron's safeStorage on sign-in
205
205
  * - Session restoration from storage on app launch
206
206
  * - Storage cleared on sign-out
@@ -208,6 +208,6 @@ declare function useElectronKavachContext(): KavachContextValue;
208
208
  * Pass a SecureStorage created by createElectronStorage() or createIpcStorage()
209
209
  * depending on whether your renderer runs with Node integration or via IPC.
210
210
  */
211
- declare function ElectronKavachProvider({ children, basePath, storage, persistSession, }: ElectronKavachProviderProps): ReactNode;
211
+ declare function ElectronTheAuthProvider({ children, basePath, storage, persistSession, }: ElectronTheAuthProviderProps): ReactNode;
212
212
 
213
- export { type ElectronApi, ElectronKavachContext, ElectronKavachProvider, type ElectronKavachProviderProps, type ElectronStorageConfig, KAVACH_IPC_CHANNELS, type OAuthWindowConfig, type OAuthWindowResult, type SecureStorage, createElectronStorage, createIpcStorage, createMemoryStorage, openOAuthWindow, setElectronApiForTesting, setupKavachIpc, useElectronKavachContext };
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,11 +248,11 @@ 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";
255
- function setupKavachIpc(storage) {
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
+ function setupTheAuthIpc(storage) {
256
256
  const { ipcMain } = getElectronApi();
257
257
  ipcMain.removeHandler(CHANNEL_GET);
258
258
  ipcMain.removeHandler(CHANNEL_SET);
@@ -296,7 +296,7 @@ function createIpcStorage() {
296
296
  }
297
297
  };
298
298
  }
299
- var KAVACH_IPC_CHANNELS = {
299
+ var THEAUTH_IPC_CHANNELS = {
300
300
  GET: CHANNEL_GET,
301
301
  SET: CHANNEL_SET,
302
302
  REMOVE: CHANNEL_REMOVE,
@@ -306,12 +306,12 @@ var KAVACH_IPC_CHANNELS = {
306
306
  // src/provider.tsx
307
307
  import { createContext, useCallback, useContext, useEffect, useState } from "react";
308
308
  import { jsx } from "react/jsx-runtime";
309
- var SESSION_STORAGE_KEY = "kavach:session";
310
- var ElectronKavachContext = createContext(null);
311
- function useElectronKavachContext() {
312
- const ctx = useContext(ElectronKavachContext);
309
+ var SESSION_STORAGE_KEY = "theauth:session";
310
+ var ElectronTheAuthContext = createContext(null);
311
+ function useElectronTheAuthContext() {
312
+ const ctx = useContext(ElectronTheAuthContext);
313
313
  if (!ctx) {
314
- throw new Error("useElectronKavachContext must be used inside <ElectronKavachProvider>");
314
+ throw new Error("useElectronTheAuthContext must be used inside <ElectronTheAuthProvider>");
315
315
  }
316
316
  return ctx;
317
317
  }
@@ -321,9 +321,9 @@ function extractErrorMessage(body, fallback) {
321
321
  }
322
322
  return fallback;
323
323
  }
324
- function ElectronKavachProvider({
324
+ function ElectronTheAuthProvider({
325
325
  children,
326
- basePath = "/api/kavach",
326
+ basePath = "/api/theauth",
327
327
  storage,
328
328
  persistSession = true
329
329
  }) {
@@ -463,18 +463,18 @@ function ElectronKavachProvider({
463
463
  signOut,
464
464
  refresh
465
465
  };
466
- return /* @__PURE__ */ jsx(ElectronKavachContext.Provider, { value, children });
466
+ return /* @__PURE__ */ jsx(ElectronTheAuthContext.Provider, { value, children });
467
467
  }
468
468
  export {
469
- ElectronKavachContext,
470
- ElectronKavachProvider,
471
- KAVACH_IPC_CHANNELS,
469
+ ElectronTheAuthContext,
470
+ ElectronTheAuthProvider,
471
+ THEAUTH_IPC_CHANNELS,
472
472
  createElectronStorage,
473
473
  createIpcStorage,
474
474
  createMemoryStorage,
475
475
  openOAuthWindow,
476
476
  setElectronApiForTesting,
477
- setupKavachIpc,
478
- useElectronKavachContext
477
+ setupTheAuthIpc,
478
+ useElectronTheAuthContext
479
479
  };
480
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 setupKavachIpc(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 { KAVACH_IPC_CHANNELS } from \"@glinr/theauth-electron\";\n *\n * contextBridge.exposeInMainWorld(\"kavachStorage\", {\n * invoke: (channel: string, ...args: unknown[]) => {\n * if (!Object.values(KAVACH_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 KAVACH_IPC_CHANNELS = {\n\tGET: CHANNEL_GET,\n\tSET: CHANNEL_SET,\n\tREMOVE: CHANNEL_REMOVE,\n\tCLEAR: CHANNEL_CLEAR,\n} as const;\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 ElectronKavachProviderProps {\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// ─── Storage key ──────────────────────────────────────────────────────────────\n\nconst SESSION_STORAGE_KEY = \"kavach:session\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport const ElectronKavachContext = createContext<KavachContextValue | null>(null);\n\nexport function useElectronKavachContext(): KavachContextValue {\n\tconst ctx = useContext(ElectronKavachContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useElectronKavachContext must be used inside <ElectronKavachProvider>\");\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 KavachProvider 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 ElectronKavachProvider({\n\tchildren,\n\tbasePath = \"/api/kavach\",\n\tstorage,\n\tpersistSession = true,\n}: ElectronKavachProviderProps): 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 <ElectronKavachContext.Provider value={value}>{children}</ElectronKavachContext.Provider>;\n}\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.1.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",