@glinr/theauth-electron 0.1.0 → 0.2.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
@@ -16,21 +16,21 @@ Set up the IPC bridge in the main process, then use the provider in the renderer
16
16
 
17
17
  ```ts
18
18
  // main.ts (main process)
19
- import { setupKavachIpc, createElectronStorage } from '@glinr/theauth-electron';
19
+ import { setupTheAuthIpc, createElectronStorage } from '@glinr/theauth-electron';
20
20
 
21
21
  const storage = createElectronStorage({ encryptionKey: process.env.STORAGE_KEY });
22
- setupKavachIpc({ storage });
22
+ setupTheAuthIpc({ storage });
23
23
  ```
24
24
 
25
25
  ```tsx
26
26
  // renderer.tsx
27
- import { ElectronKavachProvider, useElectronKavachContext } from '@glinr/theauth-electron';
27
+ import { ElectronTheAuthProvider, useElectronTheAuthContext } from '@glinr/theauth-electron';
28
28
 
29
29
  function App() {
30
30
  return (
31
- <ElectronKavachProvider apiUrl="https://auth.yourapp.com" tenantId="your-tenant-id">
31
+ <ElectronTheAuthProvider apiUrl="https://auth.yourapp.com" tenantId="your-tenant-id">
32
32
  <MainWindow />
33
- </ElectronKavachProvider>
33
+ </ElectronTheAuthProvider>
34
34
  );
35
35
  }
36
36
  ```
@@ -44,15 +44,15 @@ const result = await openOAuthWindow({ provider: 'google', redirectUri: 'kavach:
44
44
 
45
45
  ## Exports
46
46
 
47
- - `ElectronKavachProvider` / `ElectronKavachContext` / `useElectronKavachContext`: renderer-side provider
47
+ - `ElectronTheAuthProvider` / `ElectronTheAuthContext` / `useElectronTheAuthContext`: renderer-side provider (formerly `ElectronKavach*`, still exported as deprecated aliases)
48
48
  - `createElectronStorage`: encrypted keychain-backed storage
49
49
  - `createMemoryStorage`: in-memory storage for testing
50
- - `setupKavachIpc` / `createIpcStorage` / `KAVACH_IPC_CHANNELS`: main-process IPC setup
50
+ - `setupTheAuthIpc` / `createIpcStorage` / `THEAUTH_IPC_CHANNELS`: main-process IPC setup (formerly `setupKavachIpc` / `KAVACH_IPC_CHANNELS`, still exported as deprecated aliases)
51
51
  - `openOAuthWindow`: opens a managed OAuth popup window
52
52
 
53
53
  ## Docs
54
54
 
55
- [https://docs.theauth.com](https://docs.theauth.com)
55
+ [https://docs.theauth.dev](https://docs.theauth.dev)
56
56
 
57
57
  ## License
58
58
 
package/dist/index.d.ts CHANGED
@@ -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,6 +151,15 @@ declare function createIpcStorage(): SecureStorage;
151
151
  * });
152
152
  * ```
153
153
  */
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. */
154
163
  declare const KAVACH_IPC_CHANNELS: {
155
164
  readonly GET: "kavach:storage:get";
156
165
  readonly SET: "kavach:storage:set";
@@ -186,7 +195,7 @@ interface KavachContextValue {
186
195
  signOut: () => Promise<void>;
187
196
  refresh: () => Promise<void>;
188
197
  }
189
- interface ElectronKavachProviderProps {
198
+ interface ElectronTheAuthProviderProps {
190
199
  children: ReactNode;
191
200
  /** Base path where TheAuth is mounted. Defaults to "/api/kavach". */
192
201
  basePath?: string;
@@ -195,12 +204,18 @@ interface ElectronKavachProviderProps {
195
204
  /** Persist session to secure storage across restarts. Defaults to true. */
196
205
  persistSession?: boolean;
197
206
  }
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. */
198
211
  declare const ElectronKavachContext: react.Context<KavachContextValue | null>;
199
- declare function useElectronKavachContext(): KavachContextValue;
212
+ declare function useElectronTheAuthContext(): KavachContextValue;
213
+ /** @deprecated Use `useElectronTheAuthContext` instead. Will be removed in a future major version. */
214
+ declare const useElectronKavachContext: typeof useElectronTheAuthContext;
200
215
  /**
201
216
  * Wraps your Electron renderer with TheAuth auth state.
202
217
  *
203
- * Extends the base KavachProvider behaviour with:
218
+ * Extends the base TheAuthProvider behaviour with:
204
219
  * - Session persistence to Electron's safeStorage on sign-in
205
220
  * - Session restoration from storage on app launch
206
221
  * - Storage cleared on sign-out
@@ -208,6 +223,8 @@ declare function useElectronKavachContext(): KavachContextValue;
208
223
  * Pass a SecureStorage created by createElectronStorage() or createIpcStorage()
209
224
  * depending on whether your renderer runs with Node integration or via IPC.
210
225
  */
211
- declare function ElectronKavachProvider({ children, basePath, storage, persistSession, }: ElectronKavachProviderProps): ReactNode;
226
+ 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;
212
229
 
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 };
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 };
package/dist/index.js CHANGED
@@ -252,7 +252,7 @@ var CHANNEL_GET = "kavach:storage:get";
252
252
  var CHANNEL_SET = "kavach:storage:set";
253
253
  var CHANNEL_REMOVE = "kavach:storage:remove";
254
254
  var CHANNEL_CLEAR = "kavach:storage:clear";
255
- function setupKavachIpc(storage) {
255
+ function setupTheAuthIpc(storage) {
256
256
  const { ipcMain } = getElectronApi();
257
257
  ipcMain.removeHandler(CHANNEL_GET);
258
258
  ipcMain.removeHandler(CHANNEL_SET);
@@ -296,32 +296,36 @@ 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,
303
303
  CLEAR: CHANNEL_CLEAR
304
304
  };
305
+ var setupKavachIpc = setupTheAuthIpc;
306
+ var KAVACH_IPC_CHANNELS = THEAUTH_IPC_CHANNELS;
305
307
 
306
308
  // src/provider.tsx
307
309
  import { createContext, useCallback, useContext, useEffect, useState } from "react";
308
310
  import { jsx } from "react/jsx-runtime";
309
311
  var SESSION_STORAGE_KEY = "kavach:session";
310
- var ElectronKavachContext = createContext(null);
311
- function useElectronKavachContext() {
312
- const ctx = useContext(ElectronKavachContext);
312
+ var ElectronTheAuthContext = createContext(null);
313
+ var ElectronKavachContext = ElectronTheAuthContext;
314
+ function useElectronTheAuthContext() {
315
+ const ctx = useContext(ElectronTheAuthContext);
313
316
  if (!ctx) {
314
- throw new Error("useElectronKavachContext must be used inside <ElectronKavachProvider>");
317
+ throw new Error("useElectronTheAuthContext must be used inside <ElectronTheAuthProvider>");
315
318
  }
316
319
  return ctx;
317
320
  }
321
+ var useElectronKavachContext = useElectronTheAuthContext;
318
322
  function extractErrorMessage(body, fallback) {
319
323
  if (body !== null && typeof body === "object" && "error" in body && typeof body.error === "object" && typeof body.error?.message === "string") {
320
324
  return body.error?.message ?? fallback;
321
325
  }
322
326
  return fallback;
323
327
  }
324
- function ElectronKavachProvider({
328
+ function ElectronTheAuthProvider({
325
329
  children,
326
330
  basePath = "/api/kavach",
327
331
  storage,
@@ -463,18 +467,24 @@ function ElectronKavachProvider({
463
467
  signOut,
464
468
  refresh
465
469
  };
466
- return /* @__PURE__ */ jsx(ElectronKavachContext.Provider, { value, children });
470
+ return /* @__PURE__ */ jsx(ElectronTheAuthContext.Provider, { value, children });
467
471
  }
472
+ var ElectronKavachProvider = ElectronTheAuthProvider;
468
473
  export {
469
474
  ElectronKavachContext,
470
475
  ElectronKavachProvider,
476
+ ElectronTheAuthContext,
477
+ ElectronTheAuthProvider,
471
478
  KAVACH_IPC_CHANNELS,
479
+ THEAUTH_IPC_CHANNELS,
472
480
  createElectronStorage,
473
481
  createIpcStorage,
474
482
  createMemoryStorage,
475
483
  openOAuthWindow,
476
484
  setElectronApiForTesting,
477
485
  setupKavachIpc,
478
- useElectronKavachContext
486
+ setupTheAuthIpc,
487
+ useElectronKavachContext,
488
+ useElectronTheAuthContext
479
489
  };
480
490
  //# 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 \"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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glinr/theauth-electron",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TheAuth auth client for Electron desktop apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",