@clerk/electron 0.0.9-snapshot.v20260702192602 → 0.0.9

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
@@ -96,6 +96,16 @@ import { passkeys } from '@clerk/electron/passkeys';
96
96
  </ClerkProvider>;
97
97
  ```
98
98
 
99
+ Pass `userAgent` to `createClerkBridge` before creating renderer windows to set an app-specific product token, such as `Acme Co/1.0.0`. Clerk preserves Electron's platform details, such as `Macintosh` or `Windows`, while using the product token for UserProfile session activity attribution:
100
+
101
+ ```ts
102
+ createClerkBridge({
103
+ storage: storage(),
104
+ renderer: { scheme: 'my-app', host: 'renderer' },
105
+ userAgent: 'Acme Co/1.0.0',
106
+ });
107
+ ```
108
+
99
109
  ## Content Security Policy
100
110
 
101
111
  `@clerk/electron` loads Clerk's prebuilt UI from Clerk's CDN at runtime rather than bundling it, so your renderer's Content Security Policy must allow Clerk's Frontend API host. If it doesn't, the UI script fails to load and Clerk components never render.
package/dist/cjs/index.js CHANGED
@@ -215,6 +215,12 @@ function assertValidRendererOriginConfig(renderer) {
215
215
  if (renderer.scheme.includes(":") || renderer.scheme.includes("/")) throw new Error("Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".");
216
216
  if (renderer.host.includes(":") || renderer.host.includes("/")) throw new Error("Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".");
217
217
  }
218
+ function buildUserAgentFallback(defaultUserAgent, productToken) {
219
+ const platformCommentStart = defaultUserAgent.indexOf("(");
220
+ const platformCommentEnd = defaultUserAgent.indexOf(")", platformCommentStart + 1);
221
+ if (platformCommentStart === -1 || platformCommentEnd === -1) return productToken;
222
+ return `Mozilla/5.0 ${defaultUserAgent.slice(platformCommentStart, platformCommentEnd + 1)} Gecko/20100101 ${productToken}`;
223
+ }
218
224
  /**
219
225
  * Creates the Clerk bridge for Electron's main process.
220
226
  *
@@ -227,6 +233,7 @@ function createClerkBridge(options) {
227
233
  const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);
228
234
  let cleanupOAuthTransport;
229
235
  const passkeys = options.passkeys ? setupPasskeysMain() : null;
236
+ if (options.userAgent) electron.app.userAgentFallback = buildUserAgentFallback(electron.app.userAgentFallback, options.userAgent);
230
237
  if (options.renderer) {
231
238
  assertValidRendererOriginConfig(options.renderer);
232
239
  electron.protocol.registerSchemesAsPrivileged([{
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["TOKEN_CACHE_CHANNELS","OAUTH_TRANSPORT_CHANNELS","shell","BrowserWindow","PASSKEY_CHANNELS"],"sources":["../../src/main/ipc-handlers.ts","../../src/main/oauth-transport.ts","../../src/main/passkey-handlers.ts","../../src/main/create-clerk-bridge.ts"],"sourcesContent":["import { ipcMain } from 'electron';\n\nimport { TOKEN_CACHE_CHANNELS } from '../shared/ipc';\nimport type { TokenStorage } from '../shared/types';\n\nexport function setupTokenCacheIpcHandlers(storage: TokenStorage): () => void {\n ipcMain.handle(TOKEN_CACHE_CHANNELS.getToken, (_event, key: string) => {\n return storage.getItem(key);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.saveToken, (_event, key: string, value: string) => {\n return storage.setItem(key, value);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.clearToken, (_event, key: string) => {\n return storage.removeItem(key);\n });\n\n return () => {\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.getToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.saveToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.clearToken);\n };\n}\n","import { app, ipcMain, shell } from 'electron';\n\nimport { OAUTH_TRANSPORT_CHANNELS } from '../shared/ipc';\nimport type { RendererSchemeOptions } from '../shared/types';\n\nconst CALLBACK_TIMEOUT_MS = 3 * 60 * 1000;\n\ntype PendingOAuthFlow = {\n resolve: (value: { callbackUrl: string }) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n};\n\ntype OAuthTransportOptions = {\n renderer: RendererSchemeOptions;\n};\n\nfunction buildRedirectUrl(options: OAuthTransportOptions): string {\n return `${options.renderer.scheme}://${options.renderer.host}/`;\n}\n\nfunction isMatchingCallbackUrl(url: string, redirectUrl: string): boolean {\n try {\n const callback = new URL(url);\n const expected = new URL(redirectUrl);\n\n return (\n callback.protocol === expected.protocol &&\n callback.host === expected.host &&\n callback.pathname === expected.pathname\n );\n } catch {\n return false;\n }\n}\n\nfunction assertExternalOAuthUrl(url: string): void {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {\n throw new TypeError(`Clerk: refusing to open unsupported OAuth URL protocol: ${parsedUrl.protocol}`);\n }\n}\n\nexport function setupOAuthTransportIpcHandlers(options: OAuthTransportOptions): () => void {\n const redirectUrl = buildRedirectUrl(options);\n let pendingOAuthFlow: PendingOAuthFlow | null = null;\n\n const disposePendingOAuthFlow = (reason?: Error): void => {\n if (!pendingOAuthFlow) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n clearTimeout(pendingOAuthFlow.timeout);\n pendingOAuthFlow = null;\n\n if (reason) {\n pending.reject(reason);\n }\n };\n\n const handleCallbackUrl = (url: string): void => {\n if (!pendingOAuthFlow || !isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n disposePendingOAuthFlow();\n pending.resolve({ callbackUrl: url });\n };\n\n const openUrlListener = (event: Electron.Event, url: string): void => {\n if (!isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n event.preventDefault();\n handleCallbackUrl(url);\n };\n\n const secondInstanceListener = (_event: Electron.Event, argv: string[]): void => {\n const callbackUrl = argv.find(url => isMatchingCallbackUrl(url, redirectUrl));\n\n if (callbackUrl) {\n handleCallbackUrl(callbackUrl);\n }\n };\n\n app.setAsDefaultProtocolClient(options.renderer.scheme);\n app.on('open-url', openUrlListener);\n app.on('second-instance', secondInstanceListener);\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl, () => {\n return redirectUrl;\n });\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.open, async (_event, url: string) => {\n if (pendingOAuthFlow) {\n throw new Error('Clerk: an OAuth flow is already pending.');\n }\n\n assertExternalOAuthUrl(url);\n\n const callbackPromise = new Promise<{ callbackUrl: string }>((resolve, reject) => {\n const timeout = setTimeout(() => {\n disposePendingOAuthFlow();\n reject(new Error('Clerk: OAuth callback timed out.'));\n }, CALLBACK_TIMEOUT_MS);\n\n pendingOAuthFlow = { resolve, reject, timeout };\n });\n\n try {\n await shell.openExternal(url);\n } catch (err) {\n disposePendingOAuthFlow(err instanceof Error ? err : new Error(String(err)));\n }\n\n return callbackPromise;\n });\n\n return () => {\n disposePendingOAuthFlow(new Error('Clerk: OAuth flow was cancelled.'));\n app.removeListener('open-url', openUrlListener);\n app.removeListener('second-instance', secondInstanceListener);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.open);\n };\n}\n","import type { IpcMainInvokeEvent } from 'electron';\nimport { BrowserWindow, ipcMain } from 'electron';\n\nimport { PASSKEY_CHANNELS } from '../shared/ipc';\nimport type {\n AuthenticationResponseJSON,\n PasskeyCapabilities,\n PasskeyIpcResult,\n PasskeyNativeErrorCode,\n RegistrationResponseJSON,\n SerializedPublicKeyCredentialCreationOptions,\n SerializedPublicKeyCredentialRequestOptions,\n SetupPasskeysMainReturn,\n} from '../shared/types';\n\n/**\n * Optional native module. Ceremony failures resolve as JSON envelopes so error\n * codes survive both the FFI and Electron IPC boundaries.\n */\ntype NativePasskeysModule = {\n isAvailable: () => boolean;\n capabilities: () => Omit<PasskeyCapabilities, 'available'>;\n createCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n getCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n};\n\nlet nativeModulePromise: Promise<NativePasskeysModule> | undefined;\n\nfunction loadNativeModule(): Promise<NativePasskeysModule> {\n // Keep the native module optional for apps that do not use passkeys.\n nativeModulePromise ??= import('@clerk/electron-passkeys').then(\n (module: { default?: NativePasskeysModule } & NativePasskeysModule) => module.default ?? module,\n error => {\n nativeModulePromise = undefined;\n throw new Error(\n 'Clerk: createClerkBridge({ passkeys: true }) requires the optional @clerk/electron-passkeys package. Install it with your package manager to enable native passkey support.',\n { cause: error },\n );\n },\n );\n return nativeModulePromise;\n}\n\nconst NATIVE_ERROR_CODES: PasskeyNativeErrorCode[] = ['cancelled', 'invalid_rp', 'not_supported', 'timeout', 'unknown'];\n\nfunction isPasskeyIpcResult<T>(value: unknown): value is PasskeyIpcResult<T> {\n if (!value || typeof value !== 'object' || typeof (value as { ok?: unknown }).ok !== 'boolean') {\n return false;\n }\n const result = value as { ok: boolean; credential?: unknown; error?: { code?: unknown } };\n return result.ok\n ? result.credential !== undefined\n : NATIVE_ERROR_CODES.includes(result.error?.code as PasskeyNativeErrorCode);\n}\n\nasync function invokeNative<T>(\n method: 'createCredential' | 'getCredential',\n event: IpcMainInvokeEvent,\n options: SerializedPublicKeyCredentialCreationOptions | SerializedPublicKeyCredentialRequestOptions,\n): Promise<PasskeyIpcResult<T>> {\n let native: NativePasskeysModule;\n try {\n native = await loadNativeModule();\n } catch (error) {\n return {\n ok: false,\n error: { code: 'not_supported', message: error instanceof Error ? error.message : String(error) },\n };\n }\n\n if (!native.isAvailable()) {\n return {\n ok: false,\n error: { code: 'not_supported', message: 'Native passkeys are not supported on this platform.' },\n };\n }\n\n // Subframes and webviews can host third-party content that must not be able\n // to run credential ceremonies for the app's RP ID.\n if (!event.senderFrame || event.senderFrame !== event.sender.mainFrame) {\n return {\n ok: false,\n error: { code: 'unknown', message: \"The passkey request did not originate from a window's main frame.\" },\n };\n }\n\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window) {\n return {\n ok: false,\n error: { code: 'unknown', message: 'The passkey request did not originate from a visible window.' },\n };\n }\n\n try {\n const resultJson = await native[method](window.getNativeWindowHandle(), JSON.stringify(options));\n const result: unknown = JSON.parse(resultJson);\n if (!isPasskeyIpcResult<T>(result)) {\n return { ok: false, error: { code: 'unknown', message: 'The native module returned an unexpected result.' } };\n }\n return result;\n } catch (error) {\n return { ok: false, error: { code: 'unknown', message: error instanceof Error ? error.message : String(error) } };\n }\n}\n\n/** Registers IPC handlers for native platform WebAuthn. */\nexport function setupPasskeysMain(): SetupPasskeysMainReturn {\n // Surface a missing optional dependency during setup, before the first ceremony.\n loadNativeModule().catch((error: Error) => console.warn(error.message));\n\n ipcMain.handle(\n PASSKEY_CHANNELS.create,\n (\n event,\n options: SerializedPublicKeyCredentialCreationOptions,\n ): Promise<PasskeyIpcResult<RegistrationResponseJSON>> => invokeNative('createCredential', event, options),\n );\n\n ipcMain.handle(\n PASSKEY_CHANNELS.get,\n (\n event,\n options: SerializedPublicKeyCredentialRequestOptions,\n ): Promise<PasskeyIpcResult<AuthenticationResponseJSON>> => invokeNative('getCredential', event, options),\n );\n\n ipcMain.handle(PASSKEY_CHANNELS.capabilities, async (): Promise<PasskeyCapabilities> => {\n try {\n const native = await loadNativeModule();\n if (!native.isAvailable()) {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n return { available: true, ...native.capabilities() };\n } catch {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n });\n\n return {\n cleanup() {\n ipcMain.removeHandler(PASSKEY_CHANNELS.create);\n ipcMain.removeHandler(PASSKEY_CHANNELS.get);\n ipcMain.removeHandler(PASSKEY_CHANNELS.capabilities);\n },\n };\n}\n","import { protocol } from 'electron';\n\nimport type { ClerkBridge, CreateClerkBridgeOptions } from '../shared/types';\nimport { setupTokenCacheIpcHandlers } from './ipc-handlers';\nimport { setupOAuthTransportIpcHandlers } from './oauth-transport';\nimport { setupPasskeysMain } from './passkey-handlers';\n\nfunction assertValidRendererOriginConfig(renderer: NonNullable<CreateClerkBridgeOptions['renderer']>): void {\n if (renderer.scheme.includes(':') || renderer.scheme.includes('/')) {\n throw new Error(\n 'Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".',\n );\n }\n\n if (renderer.host.includes(':') || renderer.host.includes('/')) {\n throw new Error(\n 'Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".',\n );\n }\n}\n\n/**\n * Creates the Clerk bridge for Electron's main process.\n *\n * The bridge owns Clerk's main-process IPC handlers, token persistence, and OAuth deep-link\n * transport. Call this before creating renderer windows, and call the returned `cleanup` method\n * when tearing down the app or test environment.\n */\nexport function createClerkBridge(options: CreateClerkBridgeOptions): ClerkBridge {\n if (!options.storage) {\n throw new Error(\n 'Clerk: createClerkBridge requires a storage adapter. Pass createClerkBridge({ storage: storage() }) from @clerk/electron/storage, or provide a custom storage adapter.',\n );\n }\n\n const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);\n let cleanupOAuthTransport: (() => void) | undefined;\n const passkeys = options.passkeys ? setupPasskeysMain() : null;\n\n if (options.renderer) {\n assertValidRendererOriginConfig(options.renderer);\n\n protocol.registerSchemesAsPrivileged([\n {\n scheme: options.renderer.scheme,\n privileges: {\n standard: true,\n secure: true,\n supportFetchAPI: true,\n corsEnabled: true,\n stream: true,\n ...options.renderer.privileges,\n },\n },\n ]);\n\n cleanupOAuthTransport = setupOAuthTransportIpcHandlers({\n renderer: options.renderer,\n });\n }\n\n return {\n cleanup() {\n cleanupTokenPersistence();\n cleanupOAuthTransport?.();\n passkeys?.cleanup();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["TOKEN_CACHE_CHANNELS","OAUTH_TRANSPORT_CHANNELS","shell","BrowserWindow","PASSKEY_CHANNELS","app"],"sources":["../../src/main/ipc-handlers.ts","../../src/main/oauth-transport.ts","../../src/main/passkey-handlers.ts","../../src/main/create-clerk-bridge.ts"],"sourcesContent":["import { ipcMain } from 'electron';\n\nimport { TOKEN_CACHE_CHANNELS } from '../shared/ipc';\nimport type { TokenStorage } from '../shared/types';\n\nexport function setupTokenCacheIpcHandlers(storage: TokenStorage): () => void {\n ipcMain.handle(TOKEN_CACHE_CHANNELS.getToken, (_event, key: string) => {\n return storage.getItem(key);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.saveToken, (_event, key: string, value: string) => {\n return storage.setItem(key, value);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.clearToken, (_event, key: string) => {\n return storage.removeItem(key);\n });\n\n return () => {\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.getToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.saveToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.clearToken);\n };\n}\n","import { app, ipcMain, shell } from 'electron';\n\nimport { OAUTH_TRANSPORT_CHANNELS } from '../shared/ipc';\nimport type { RendererSchemeOptions } from '../shared/types';\n\nconst CALLBACK_TIMEOUT_MS = 3 * 60 * 1000;\n\ntype PendingOAuthFlow = {\n resolve: (value: { callbackUrl: string }) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n};\n\ntype OAuthTransportOptions = {\n renderer: RendererSchemeOptions;\n};\n\nfunction buildRedirectUrl(options: OAuthTransportOptions): string {\n return `${options.renderer.scheme}://${options.renderer.host}/`;\n}\n\nfunction isMatchingCallbackUrl(url: string, redirectUrl: string): boolean {\n try {\n const callback = new URL(url);\n const expected = new URL(redirectUrl);\n\n return (\n callback.protocol === expected.protocol &&\n callback.host === expected.host &&\n callback.pathname === expected.pathname\n );\n } catch {\n return false;\n }\n}\n\nfunction assertExternalOAuthUrl(url: string): void {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {\n throw new TypeError(`Clerk: refusing to open unsupported OAuth URL protocol: ${parsedUrl.protocol}`);\n }\n}\n\nexport function setupOAuthTransportIpcHandlers(options: OAuthTransportOptions): () => void {\n const redirectUrl = buildRedirectUrl(options);\n let pendingOAuthFlow: PendingOAuthFlow | null = null;\n\n const disposePendingOAuthFlow = (reason?: Error): void => {\n if (!pendingOAuthFlow) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n clearTimeout(pendingOAuthFlow.timeout);\n pendingOAuthFlow = null;\n\n if (reason) {\n pending.reject(reason);\n }\n };\n\n const handleCallbackUrl = (url: string): void => {\n if (!pendingOAuthFlow || !isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n disposePendingOAuthFlow();\n pending.resolve({ callbackUrl: url });\n };\n\n const openUrlListener = (event: Electron.Event, url: string): void => {\n if (!isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n event.preventDefault();\n handleCallbackUrl(url);\n };\n\n const secondInstanceListener = (_event: Electron.Event, argv: string[]): void => {\n const callbackUrl = argv.find(url => isMatchingCallbackUrl(url, redirectUrl));\n\n if (callbackUrl) {\n handleCallbackUrl(callbackUrl);\n }\n };\n\n app.setAsDefaultProtocolClient(options.renderer.scheme);\n app.on('open-url', openUrlListener);\n app.on('second-instance', secondInstanceListener);\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl, () => {\n return redirectUrl;\n });\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.open, async (_event, url: string) => {\n if (pendingOAuthFlow) {\n throw new Error('Clerk: an OAuth flow is already pending.');\n }\n\n assertExternalOAuthUrl(url);\n\n const callbackPromise = new Promise<{ callbackUrl: string }>((resolve, reject) => {\n const timeout = setTimeout(() => {\n disposePendingOAuthFlow();\n reject(new Error('Clerk: OAuth callback timed out.'));\n }, CALLBACK_TIMEOUT_MS);\n\n pendingOAuthFlow = { resolve, reject, timeout };\n });\n\n try {\n await shell.openExternal(url);\n } catch (err) {\n disposePendingOAuthFlow(err instanceof Error ? err : new Error(String(err)));\n }\n\n return callbackPromise;\n });\n\n return () => {\n disposePendingOAuthFlow(new Error('Clerk: OAuth flow was cancelled.'));\n app.removeListener('open-url', openUrlListener);\n app.removeListener('second-instance', secondInstanceListener);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.open);\n };\n}\n","import type { IpcMainInvokeEvent } from 'electron';\nimport { BrowserWindow, ipcMain } from 'electron';\n\nimport { PASSKEY_CHANNELS } from '../shared/ipc';\nimport type {\n AuthenticationResponseJSON,\n PasskeyCapabilities,\n PasskeyIpcResult,\n PasskeyNativeErrorCode,\n RegistrationResponseJSON,\n SerializedPublicKeyCredentialCreationOptions,\n SerializedPublicKeyCredentialRequestOptions,\n SetupPasskeysMainReturn,\n} from '../shared/types';\n\n/**\n * Optional native module. Ceremony failures resolve as JSON envelopes so error\n * codes survive both the FFI and Electron IPC boundaries.\n */\ntype NativePasskeysModule = {\n isAvailable: () => boolean;\n capabilities: () => Omit<PasskeyCapabilities, 'available'>;\n createCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n getCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n};\n\nlet nativeModulePromise: Promise<NativePasskeysModule> | undefined;\n\nfunction loadNativeModule(): Promise<NativePasskeysModule> {\n // Keep the native module optional for apps that do not use passkeys.\n nativeModulePromise ??= import('@clerk/electron-passkeys').then(\n (module: { default?: NativePasskeysModule } & NativePasskeysModule) => module.default ?? module,\n error => {\n nativeModulePromise = undefined;\n throw new Error(\n 'Clerk: createClerkBridge({ passkeys: true }) requires the optional @clerk/electron-passkeys package. Install it with your package manager to enable native passkey support.',\n { cause: error },\n );\n },\n );\n return nativeModulePromise;\n}\n\nconst NATIVE_ERROR_CODES: PasskeyNativeErrorCode[] = ['cancelled', 'invalid_rp', 'not_supported', 'timeout', 'unknown'];\n\nfunction isPasskeyIpcResult<T>(value: unknown): value is PasskeyIpcResult<T> {\n if (!value || typeof value !== 'object' || typeof (value as { ok?: unknown }).ok !== 'boolean') {\n return false;\n }\n const result = value as { ok: boolean; credential?: unknown; error?: { code?: unknown } };\n return result.ok\n ? result.credential !== undefined\n : NATIVE_ERROR_CODES.includes(result.error?.code as PasskeyNativeErrorCode);\n}\n\nasync function invokeNative<T>(\n method: 'createCredential' | 'getCredential',\n event: IpcMainInvokeEvent,\n options: SerializedPublicKeyCredentialCreationOptions | SerializedPublicKeyCredentialRequestOptions,\n): Promise<PasskeyIpcResult<T>> {\n let native: NativePasskeysModule;\n try {\n native = await loadNativeModule();\n } catch (error) {\n return {\n ok: false,\n error: { code: 'not_supported', message: error instanceof Error ? error.message : String(error) },\n };\n }\n\n if (!native.isAvailable()) {\n return {\n ok: false,\n error: { code: 'not_supported', message: 'Native passkeys are not supported on this platform.' },\n };\n }\n\n // Subframes and webviews can host third-party content that must not be able\n // to run credential ceremonies for the app's RP ID.\n if (!event.senderFrame || event.senderFrame !== event.sender.mainFrame) {\n return {\n ok: false,\n error: { code: 'unknown', message: \"The passkey request did not originate from a window's main frame.\" },\n };\n }\n\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window) {\n return {\n ok: false,\n error: { code: 'unknown', message: 'The passkey request did not originate from a visible window.' },\n };\n }\n\n try {\n const resultJson = await native[method](window.getNativeWindowHandle(), JSON.stringify(options));\n const result: unknown = JSON.parse(resultJson);\n if (!isPasskeyIpcResult<T>(result)) {\n return { ok: false, error: { code: 'unknown', message: 'The native module returned an unexpected result.' } };\n }\n return result;\n } catch (error) {\n return { ok: false, error: { code: 'unknown', message: error instanceof Error ? error.message : String(error) } };\n }\n}\n\n/** Registers IPC handlers for native platform WebAuthn. */\nexport function setupPasskeysMain(): SetupPasskeysMainReturn {\n // Surface a missing optional dependency during setup, before the first ceremony.\n loadNativeModule().catch((error: Error) => console.warn(error.message));\n\n ipcMain.handle(\n PASSKEY_CHANNELS.create,\n (\n event,\n options: SerializedPublicKeyCredentialCreationOptions,\n ): Promise<PasskeyIpcResult<RegistrationResponseJSON>> => invokeNative('createCredential', event, options),\n );\n\n ipcMain.handle(\n PASSKEY_CHANNELS.get,\n (\n event,\n options: SerializedPublicKeyCredentialRequestOptions,\n ): Promise<PasskeyIpcResult<AuthenticationResponseJSON>> => invokeNative('getCredential', event, options),\n );\n\n ipcMain.handle(PASSKEY_CHANNELS.capabilities, async (): Promise<PasskeyCapabilities> => {\n try {\n const native = await loadNativeModule();\n if (!native.isAvailable()) {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n return { available: true, ...native.capabilities() };\n } catch {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n });\n\n return {\n cleanup() {\n ipcMain.removeHandler(PASSKEY_CHANNELS.create);\n ipcMain.removeHandler(PASSKEY_CHANNELS.get);\n ipcMain.removeHandler(PASSKEY_CHANNELS.capabilities);\n },\n };\n}\n","import { app, protocol } from 'electron';\n\nimport type { ClerkBridge, CreateClerkBridgeOptions } from '../shared/types';\nimport { setupTokenCacheIpcHandlers } from './ipc-handlers';\nimport { setupOAuthTransportIpcHandlers } from './oauth-transport';\nimport { setupPasskeysMain } from './passkey-handlers';\n\nfunction assertValidRendererOriginConfig(renderer: NonNullable<CreateClerkBridgeOptions['renderer']>): void {\n if (renderer.scheme.includes(':') || renderer.scheme.includes('/')) {\n throw new Error(\n 'Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".',\n );\n }\n\n if (renderer.host.includes(':') || renderer.host.includes('/')) {\n throw new Error(\n 'Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".',\n );\n }\n}\n\nfunction buildUserAgentFallback(defaultUserAgent: string, productToken: string): string {\n const platformCommentStart = defaultUserAgent.indexOf('(');\n const platformCommentEnd = defaultUserAgent.indexOf(')', platformCommentStart + 1);\n\n if (platformCommentStart === -1 || platformCommentEnd === -1) {\n return productToken;\n }\n\n const platformComment = defaultUserAgent.slice(platformCommentStart, platformCommentEnd + 1);\n\n // Clerk's session activity parser preserves the platform comment and treats the\n // token after Gecko as the app/browser name.\n return `Mozilla/5.0 ${platformComment} Gecko/20100101 ${productToken}`;\n}\n\n/**\n * Creates the Clerk bridge for Electron's main process.\n *\n * The bridge owns Clerk's main-process IPC handlers, token persistence, and OAuth deep-link\n * transport. Call this before creating renderer windows, and call the returned `cleanup` method\n * when tearing down the app or test environment.\n */\nexport function createClerkBridge(options: CreateClerkBridgeOptions): ClerkBridge {\n if (!options.storage) {\n throw new Error(\n 'Clerk: createClerkBridge requires a storage adapter. Pass createClerkBridge({ storage: storage() }) from @clerk/electron/storage, or provide a custom storage adapter.',\n );\n }\n\n const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);\n let cleanupOAuthTransport: (() => void) | undefined;\n const passkeys = options.passkeys ? setupPasskeysMain() : null;\n\n if (options.userAgent) {\n app.userAgentFallback = buildUserAgentFallback(app.userAgentFallback, options.userAgent);\n }\n\n if (options.renderer) {\n assertValidRendererOriginConfig(options.renderer);\n\n protocol.registerSchemesAsPrivileged([\n {\n scheme: options.renderer.scheme,\n privileges: {\n standard: true,\n secure: true,\n supportFetchAPI: true,\n corsEnabled: true,\n stream: true,\n ...options.renderer.privileges,\n },\n },\n ]);\n\n cleanupOAuthTransport = setupOAuthTransportIpcHandlers({\n renderer: options.renderer,\n });\n }\n\n return {\n cleanup() {\n cleanupTokenPersistence();\n cleanupOAuthTransport?.();\n passkeys?.cleanup();\n },\n };\n}\n"],"mappings":"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"}
@@ -25,7 +25,7 @@ function createClerkInstance(publishableKey, passkeys) {
25
25
  clerk.__internal_onBeforeRequest(async (request) => {
26
26
  request.credentials = "omit";
27
27
  request.url?.searchParams.append("_is_native", "1");
28
- request.url?.searchParams.append("_electron_sdk_version", "0.0.9-snapshot.v20260702192602");
28
+ request.url?.searchParams.append("_electron_sdk_version", "0.0.9");
29
29
  const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);
30
30
  if (token) {
31
31
  const headers = new Headers(request.headers);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Clerk","ALLOWED_PROTOCOLS","ReactClerkProvider"],"sources":["../../../src/react/create-clerk-instance.ts","../../../src/react/index.tsx"],"sourcesContent":["import { Clerk } from '@clerk/clerk-js';\n\n// Type-only import: the passkeys module is only bundled when the app imports\n// `@clerk/electron/passkeys` itself.\nimport type { PasskeySupport } from '../passkeys';\n\nconst CLERK_CLIENT_JWT_KEY = '__clerk_client_jwt';\n\ntype ClerkInstance = InstanceType<typeof Clerk>;\n\nlet cached: { instance: ClerkInstance; publishableKey: string } | null = null;\n\nfunction attachPasskeys(clerk: ClerkInstance, passkeys: PasskeySupport): void {\n clerk.__internal_createPublicCredentials = passkeys.create;\n clerk.__internal_getPublicCredentials = passkeys.get;\n clerk.__internal_isWebAuthnSupported = passkeys.isSupported;\n clerk.__internal_isWebAuthnAutofillSupported = passkeys.isAutoFillSupported;\n clerk.__internal_isWebAuthnPlatformAuthenticatorSupported = passkeys.isPlatformAuthenticatorSupported;\n}\n\nexport function createClerkInstance(publishableKey: string, passkeys?: PasskeySupport): ClerkInstance {\n if (cached?.publishableKey === publishableKey) {\n if (passkeys) {\n attachPasskeys(cached.instance, passkeys);\n }\n return cached.instance;\n }\n\n const clerk = new Clerk(publishableKey);\n\n if (passkeys) {\n attachPasskeys(clerk, passkeys);\n }\n\n clerk.__internal_onBeforeRequest(async request => {\n request.credentials = 'omit';\n request.url?.searchParams.append('_is_native', '1');\n request.url?.searchParams.append('_electron_sdk_version', PACKAGE_VERSION);\n\n const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);\n if (token) {\n const headers = new Headers(request.headers);\n headers.set('Authorization', `Bearer ${token}`);\n request.headers = headers;\n }\n });\n\n clerk.__internal_onAfterResponse(async (_request, response) => {\n const authorization = (response as Response).headers.get('Authorization');\n if (!authorization) {\n return;\n }\n\n const token = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : authorization;\n await window.__clerk_internal_electron?.tokenCache.saveToken(CLERK_CLIENT_JWT_KEY, token);\n });\n\n cached = { instance: clerk, publishableKey };\n return clerk;\n}\n","import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ReactClerkProvider } from '@clerk/react/internal';\nimport { ALLOWED_PROTOCOLS } from '@clerk/shared/internal/clerk-js/windowNavigate';\nimport { loadClerkUIScript } from '@clerk/shared/loadClerkJsScript';\nimport type { ClerkUIConstructor } from '@clerk/shared/ui';\nimport type { ReactNode } from 'react';\n\nimport type { PasskeySupport } from '../passkeys';\nimport { createClerkInstance } from './create-clerk-instance';\n\ntype ClerkOAuthTransport = NonNullable<ReactClerkProviderProps['__internal_oauthTransport']>;\n\nexport type ClerkProviderProps = Omit<\n ReactClerkProviderProps,\n 'Clerk' | 'children' | 'publishableKey' | 'standardBrowser' | 'ui' | '__internal_oauthTransport'\n> & {\n children: ReactNode;\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n */\n publishableKey: string;\n /**\n * Enables passkey support. Pass the `passkeys` export from `@clerk/electron/passkeys`;\n * when omitted, no passkey code is bundled or initialized.\n *\n * @example\n * ```tsx\n * import { passkeys } from '@clerk/electron/passkeys';\n *\n * <ClerkProvider publishableKey={publishableKey} passkeys={passkeys} />\n * ```\n */\n passkeys?: PasskeySupport;\n};\n\nlet cachedClerkUI: { promise: Promise<ClerkUIConstructor>; publishableKey: string } | null = null;\n\nfunction loadClerkUI(publishableKey: string, props: Partial<ClerkProviderProps>): Promise<ClerkUIConstructor> {\n if (cachedClerkUI?.publishableKey === publishableKey) {\n return cachedClerkUI.promise;\n }\n\n // Undocumented escape hatch for self-hosting/proxying the UI bundle; not part of the public props.\n const { __internal_clerkUIUrl, __internal_clerkUIVersion } = props as {\n __internal_clerkUIUrl?: string;\n __internal_clerkUIVersion?: string;\n };\n\n const promise = loadClerkUIScript({\n publishableKey,\n proxyUrl: typeof props.proxyUrl === 'string' ? props.proxyUrl : undefined,\n domain: typeof props.domain === 'string' ? props.domain : undefined,\n nonce: props.nonce,\n __internal_clerkUIUrl,\n __internal_clerkUIVersion,\n }).then(() => {\n if (!window.__internal_ClerkUICtor) {\n throw new Error(\n 'Clerk: Failed to load Clerk UI from the CDN. Ensure your Content Security Policy allows the Clerk Frontend API host in `script-src`. Contact support@clerk.com.',\n );\n }\n return window.__internal_ClerkUICtor;\n });\n\n cachedClerkUI = { promise, publishableKey };\n return promise;\n}\n\nfunction createOAuthTransport(): ClerkOAuthTransport | undefined {\n const bridge = window.__clerk_internal_electron?.oauthTransport;\n\n if (!bridge) {\n return undefined;\n }\n\n return {\n getRedirectUrl: () => bridge.getRedirectUrl(),\n open: url => bridge.open(url.href),\n };\n}\n\n/**\n * Infer the custom renderer scheme registered with `createClerkBridge({ renderer })`.\n * Built-in Clerk protocols and local file renderers are not inferred.\n */\nfunction defaultAllowedRedirectProtocols(): string[] | undefined {\n const protocol = typeof window !== 'undefined' ? window.location?.protocol : undefined;\n\n if (!protocol || ALLOWED_PROTOCOLS.includes(protocol) || protocol === 'file:') {\n return undefined;\n }\n\n return [protocol];\n}\n\nexport function ClerkProvider({\n children,\n publishableKey,\n passkeys,\n allowedRedirectProtocols,\n ...props\n}: ClerkProviderProps): JSX.Element {\n const clerk = createClerkInstance(publishableKey, passkeys);\n const oauthTransport = createOAuthTransport();\n const clerkUI = loadClerkUI(publishableKey, props);\n\n return (\n <ReactClerkProvider\n {...props}\n Clerk={clerk}\n __internal_oauthTransport={oauthTransport}\n allowedRedirectProtocols={allowedRedirectProtocols ?? defaultAllowedRedirectProtocols()}\n publishableKey={publishableKey}\n standardBrowser={false}\n ui={{ ClerkUI: clerkUI }}\n >\n {children}\n </ReactClerkProvider>\n );\n}\n\nexport * from '@clerk/react';\n"],"mappings":";;;;;;;;AAMA,MAAM,uBAAuB;AAI7B,IAAI,SAAqE;AAEzE,SAAS,eAAe,OAAsB,UAAgC;CAC5E,MAAM,qCAAqC,SAAS;CACpD,MAAM,kCAAkC,SAAS;CACjD,MAAM,iCAAiC,SAAS;CAChD,MAAM,yCAAyC,SAAS;CACxD,MAAM,sDAAsD,SAAS;AACvE;AAEA,SAAgB,oBAAoB,gBAAwB,UAA0C;CACpG,IAAI,QAAQ,mBAAmB,gBAAgB;EAC7C,IAAI,UACF,eAAe,OAAO,UAAU,QAAQ;EAE1C,OAAO,OAAO;CAChB;CAEA,MAAM,QAAQ,IAAIA,sBAAM,cAAc;CAEtC,IAAI,UACF,eAAe,OAAO,QAAQ;CAGhC,MAAM,2BAA2B,OAAM,YAAW;EAChD,QAAQ,cAAc;EACtB,QAAQ,KAAK,aAAa,OAAO,cAAc,GAAG;EAClD,QAAQ,KAAK,aAAa,OAAO,yDAAwC;EAEzE,MAAM,QAAQ,MAAM,OAAO,2BAA2B,WAAW,SAAS,oBAAoB;EAC9F,IAAI,OAAO;GACT,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;GAC3C,QAAQ,IAAI,iBAAiB,UAAU,OAAO;GAC9C,QAAQ,UAAU;EACpB;CACF,CAAC;CAED,MAAM,2BAA2B,OAAO,UAAU,aAAa;EAC7D,MAAM,gBAAiB,SAAsB,QAAQ,IAAI,eAAe;EACxE,IAAI,CAAC,eACH;EAGF,MAAM,QAAQ,cAAc,WAAW,SAAS,IAAI,cAAc,MAAM,CAAgB,IAAI;EAC5F,MAAM,OAAO,2BAA2B,WAAW,UAAU,sBAAsB,KAAK;CAC1F,CAAC;CAED,SAAS;EAAE,UAAU;EAAO;CAAe;CAC3C,OAAO;AACT;;;;ACxBA,IAAI,gBAAyF;AAE7F,SAAS,YAAY,gBAAwB,OAAiE;CAC5G,IAAI,eAAe,mBAAmB,gBACpC,OAAO,cAAc;CAIvB,MAAM,EAAE,uBAAuB,8BAA8B;CAK7D,MAAM,iEAA4B;EAChC;EACA,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;EAC1D,OAAO,MAAM;EACb;EACA;CACF,CAAC,CAAC,CAAC,WAAW;EACZ,IAAI,CAAC,OAAO,wBACV,MAAM,IAAI,MACR,iKACF;EAEF,OAAO,OAAO;CAChB,CAAC;CAED,gBAAgB;EAAE;EAAS;CAAe;CAC1C,OAAO;AACT;AAEA,SAAS,uBAAwD;CAC/D,MAAM,SAAS,OAAO,2BAA2B;CAEjD,IAAI,CAAC,QACH;CAGF,OAAO;EACL,sBAAsB,OAAO,eAAe;EAC5C,OAAM,QAAO,OAAO,KAAK,IAAI,IAAI;CACnC;AACF;;;;;AAMA,SAAS,kCAAwD;CAC/D,MAAM,WAAW,OAAO,WAAW,cAAc,OAAO,UAAU,WAAW;CAE7E,IAAI,CAAC,YAAYC,iEAAkB,SAAS,QAAQ,KAAK,aAAa,SACpE;CAGF,OAAO,CAAC,QAAQ;AAClB;AAEA,SAAgB,cAAc,EAC5B,UACA,gBACA,UACA,0BACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,oBAAoB,gBAAgB,QAAQ;CAC1D,MAAM,iBAAiB,qBAAqB;CAC5C,MAAM,UAAU,YAAY,gBAAgB,KAAK;CAEjD,OACE,2CAACC,6CAAD;EACE,GAAI;EACJ,OAAO;EACP,2BAA2B;EAC3B,0BAA0B,4BAA4B,gCAAgC;EACtE;EAChB,iBAAiB;EACjB,IAAI,EAAE,SAAS,QAAQ;EAEtB;CACiB;AAExB"}
1
+ {"version":3,"file":"index.js","names":["Clerk","ALLOWED_PROTOCOLS","ReactClerkProvider"],"sources":["../../../src/react/create-clerk-instance.ts","../../../src/react/index.tsx"],"sourcesContent":["import { Clerk } from '@clerk/clerk-js';\n\n// Type-only import: the passkeys module is only bundled when the app imports\n// `@clerk/electron/passkeys` itself.\nimport type { PasskeySupport } from '../passkeys';\n\nconst CLERK_CLIENT_JWT_KEY = '__clerk_client_jwt';\n\ntype ClerkInstance = InstanceType<typeof Clerk>;\n\nlet cached: { instance: ClerkInstance; publishableKey: string } | null = null;\n\nfunction attachPasskeys(clerk: ClerkInstance, passkeys: PasskeySupport): void {\n clerk.__internal_createPublicCredentials = passkeys.create;\n clerk.__internal_getPublicCredentials = passkeys.get;\n clerk.__internal_isWebAuthnSupported = passkeys.isSupported;\n clerk.__internal_isWebAuthnAutofillSupported = passkeys.isAutoFillSupported;\n clerk.__internal_isWebAuthnPlatformAuthenticatorSupported = passkeys.isPlatformAuthenticatorSupported;\n}\n\nexport function createClerkInstance(publishableKey: string, passkeys?: PasskeySupport): ClerkInstance {\n if (cached?.publishableKey === publishableKey) {\n if (passkeys) {\n attachPasskeys(cached.instance, passkeys);\n }\n return cached.instance;\n }\n\n const clerk = new Clerk(publishableKey);\n\n if (passkeys) {\n attachPasskeys(clerk, passkeys);\n }\n\n clerk.__internal_onBeforeRequest(async request => {\n request.credentials = 'omit';\n request.url?.searchParams.append('_is_native', '1');\n request.url?.searchParams.append('_electron_sdk_version', PACKAGE_VERSION);\n\n const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);\n if (token) {\n const headers = new Headers(request.headers);\n headers.set('Authorization', `Bearer ${token}`);\n request.headers = headers;\n }\n });\n\n clerk.__internal_onAfterResponse(async (_request, response) => {\n const authorization = (response as Response).headers.get('Authorization');\n if (!authorization) {\n return;\n }\n\n const token = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : authorization;\n await window.__clerk_internal_electron?.tokenCache.saveToken(CLERK_CLIENT_JWT_KEY, token);\n });\n\n cached = { instance: clerk, publishableKey };\n return clerk;\n}\n","import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ReactClerkProvider } from '@clerk/react/internal';\nimport { ALLOWED_PROTOCOLS } from '@clerk/shared/internal/clerk-js/windowNavigate';\nimport { loadClerkUIScript } from '@clerk/shared/loadClerkJsScript';\nimport type { ClerkUIConstructor } from '@clerk/shared/ui';\nimport type { ReactNode } from 'react';\n\nimport type { PasskeySupport } from '../passkeys';\nimport { createClerkInstance } from './create-clerk-instance';\n\ntype ClerkOAuthTransport = NonNullable<ReactClerkProviderProps['__internal_oauthTransport']>;\n\nexport type ClerkProviderProps = Omit<\n ReactClerkProviderProps,\n 'Clerk' | 'children' | 'publishableKey' | 'standardBrowser' | 'ui' | '__internal_oauthTransport'\n> & {\n children: ReactNode;\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n */\n publishableKey: string;\n /**\n * Enables passkey support. Pass the `passkeys` export from `@clerk/electron/passkeys`;\n * when omitted, no passkey code is bundled or initialized.\n *\n * @example\n * ```tsx\n * import { passkeys } from '@clerk/electron/passkeys';\n *\n * <ClerkProvider publishableKey={publishableKey} passkeys={passkeys} />\n * ```\n */\n passkeys?: PasskeySupport;\n};\n\nlet cachedClerkUI: { promise: Promise<ClerkUIConstructor>; publishableKey: string } | null = null;\n\nfunction loadClerkUI(publishableKey: string, props: Partial<ClerkProviderProps>): Promise<ClerkUIConstructor> {\n if (cachedClerkUI?.publishableKey === publishableKey) {\n return cachedClerkUI.promise;\n }\n\n // Undocumented escape hatch for self-hosting/proxying the UI bundle; not part of the public props.\n const { __internal_clerkUIUrl, __internal_clerkUIVersion } = props as {\n __internal_clerkUIUrl?: string;\n __internal_clerkUIVersion?: string;\n };\n\n const promise = loadClerkUIScript({\n publishableKey,\n proxyUrl: typeof props.proxyUrl === 'string' ? props.proxyUrl : undefined,\n domain: typeof props.domain === 'string' ? props.domain : undefined,\n nonce: props.nonce,\n __internal_clerkUIUrl,\n __internal_clerkUIVersion,\n }).then(() => {\n if (!window.__internal_ClerkUICtor) {\n throw new Error(\n 'Clerk: Failed to load Clerk UI from the CDN. Ensure your Content Security Policy allows the Clerk Frontend API host in `script-src`. Contact support@clerk.com.',\n );\n }\n return window.__internal_ClerkUICtor;\n });\n\n cachedClerkUI = { promise, publishableKey };\n return promise;\n}\n\nfunction createOAuthTransport(): ClerkOAuthTransport | undefined {\n const bridge = window.__clerk_internal_electron?.oauthTransport;\n\n if (!bridge) {\n return undefined;\n }\n\n return {\n getRedirectUrl: () => bridge.getRedirectUrl(),\n open: url => bridge.open(url.href),\n };\n}\n\n/**\n * Infer the custom renderer scheme registered with `createClerkBridge({ renderer })`.\n * Built-in Clerk protocols and local file renderers are not inferred.\n */\nfunction defaultAllowedRedirectProtocols(): string[] | undefined {\n const protocol = typeof window !== 'undefined' ? window.location?.protocol : undefined;\n\n if (!protocol || ALLOWED_PROTOCOLS.includes(protocol) || protocol === 'file:') {\n return undefined;\n }\n\n return [protocol];\n}\n\nexport function ClerkProvider({\n children,\n publishableKey,\n passkeys,\n allowedRedirectProtocols,\n ...props\n}: ClerkProviderProps): JSX.Element {\n const clerk = createClerkInstance(publishableKey, passkeys);\n const oauthTransport = createOAuthTransport();\n const clerkUI = loadClerkUI(publishableKey, props);\n\n return (\n <ReactClerkProvider\n {...props}\n Clerk={clerk}\n __internal_oauthTransport={oauthTransport}\n allowedRedirectProtocols={allowedRedirectProtocols ?? defaultAllowedRedirectProtocols()}\n publishableKey={publishableKey}\n standardBrowser={false}\n ui={{ ClerkUI: clerkUI }}\n >\n {children}\n </ReactClerkProvider>\n );\n}\n\nexport * from '@clerk/react';\n"],"mappings":";;;;;;;;AAMA,MAAM,uBAAuB;AAI7B,IAAI,SAAqE;AAEzE,SAAS,eAAe,OAAsB,UAAgC;CAC5E,MAAM,qCAAqC,SAAS;CACpD,MAAM,kCAAkC,SAAS;CACjD,MAAM,iCAAiC,SAAS;CAChD,MAAM,yCAAyC,SAAS;CACxD,MAAM,sDAAsD,SAAS;AACvE;AAEA,SAAgB,oBAAoB,gBAAwB,UAA0C;CACpG,IAAI,QAAQ,mBAAmB,gBAAgB;EAC7C,IAAI,UACF,eAAe,OAAO,UAAU,QAAQ;EAE1C,OAAO,OAAO;CAChB;CAEA,MAAM,QAAQ,IAAIA,sBAAM,cAAc;CAEtC,IAAI,UACF,eAAe,OAAO,QAAQ;CAGhC,MAAM,2BAA2B,OAAM,YAAW;EAChD,QAAQ,cAAc;EACtB,QAAQ,KAAK,aAAa,OAAO,cAAc,GAAG;EAClD,QAAQ,KAAK,aAAa,OAAO,gCAAwC;EAEzE,MAAM,QAAQ,MAAM,OAAO,2BAA2B,WAAW,SAAS,oBAAoB;EAC9F,IAAI,OAAO;GACT,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;GAC3C,QAAQ,IAAI,iBAAiB,UAAU,OAAO;GAC9C,QAAQ,UAAU;EACpB;CACF,CAAC;CAED,MAAM,2BAA2B,OAAO,UAAU,aAAa;EAC7D,MAAM,gBAAiB,SAAsB,QAAQ,IAAI,eAAe;EACxE,IAAI,CAAC,eACH;EAGF,MAAM,QAAQ,cAAc,WAAW,SAAS,IAAI,cAAc,MAAM,CAAgB,IAAI;EAC5F,MAAM,OAAO,2BAA2B,WAAW,UAAU,sBAAsB,KAAK;CAC1F,CAAC;CAED,SAAS;EAAE,UAAU;EAAO;CAAe;CAC3C,OAAO;AACT;;;;ACxBA,IAAI,gBAAyF;AAE7F,SAAS,YAAY,gBAAwB,OAAiE;CAC5G,IAAI,eAAe,mBAAmB,gBACpC,OAAO,cAAc;CAIvB,MAAM,EAAE,uBAAuB,8BAA8B;CAK7D,MAAM,iEAA4B;EAChC;EACA,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;EAC1D,OAAO,MAAM;EACb;EACA;CACF,CAAC,CAAC,CAAC,WAAW;EACZ,IAAI,CAAC,OAAO,wBACV,MAAM,IAAI,MACR,iKACF;EAEF,OAAO,OAAO;CAChB,CAAC;CAED,gBAAgB;EAAE;EAAS;CAAe;CAC1C,OAAO;AACT;AAEA,SAAS,uBAAwD;CAC/D,MAAM,SAAS,OAAO,2BAA2B;CAEjD,IAAI,CAAC,QACH;CAGF,OAAO;EACL,sBAAsB,OAAO,eAAe;EAC5C,OAAM,QAAO,OAAO,KAAK,IAAI,IAAI;CACnC;AACF;;;;;AAMA,SAAS,kCAAwD;CAC/D,MAAM,WAAW,OAAO,WAAW,cAAc,OAAO,UAAU,WAAW;CAE7E,IAAI,CAAC,YAAYC,iEAAkB,SAAS,QAAQ,KAAK,aAAa,SACpE;CAGF,OAAO,CAAC,QAAQ;AAClB;AAEA,SAAgB,cAAc,EAC5B,UACA,gBACA,UACA,0BACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,oBAAoB,gBAAgB,QAAQ;CAC1D,MAAM,iBAAiB,qBAAqB;CAC5C,MAAM,UAAU,YAAY,gBAAgB,KAAK;CAEjD,OACE,2CAACC,6CAAD;EACE,GAAI;EACJ,OAAO;EACP,2BAA2B;EAC3B,0BAA0B,4BAA4B,gCAAgC;EACtE;EAChB,iBAAiB;EACjB,IAAI,EAAE,SAAS,QAAQ;EAEtB;CACiB;AAExB"}
package/dist/esm/index.js CHANGED
@@ -214,6 +214,12 @@ function assertValidRendererOriginConfig(renderer) {
214
214
  if (renderer.scheme.includes(":") || renderer.scheme.includes("/")) throw new Error("Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".");
215
215
  if (renderer.host.includes(":") || renderer.host.includes("/")) throw new Error("Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".");
216
216
  }
217
+ function buildUserAgentFallback(defaultUserAgent, productToken) {
218
+ const platformCommentStart = defaultUserAgent.indexOf("(");
219
+ const platformCommentEnd = defaultUserAgent.indexOf(")", platformCommentStart + 1);
220
+ if (platformCommentStart === -1 || platformCommentEnd === -1) return productToken;
221
+ return `Mozilla/5.0 ${defaultUserAgent.slice(platformCommentStart, platformCommentEnd + 1)} Gecko/20100101 ${productToken}`;
222
+ }
217
223
  /**
218
224
  * Creates the Clerk bridge for Electron's main process.
219
225
  *
@@ -226,6 +232,7 @@ function createClerkBridge(options) {
226
232
  const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);
227
233
  let cleanupOAuthTransport;
228
234
  const passkeys = options.passkeys ? setupPasskeysMain() : null;
235
+ if (options.userAgent) app.userAgentFallback = buildUserAgentFallback(app.userAgentFallback, options.userAgent);
229
236
  if (options.renderer) {
230
237
  assertValidRendererOriginConfig(options.renderer);
231
238
  protocol.registerSchemesAsPrivileged([{
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/main/ipc-handlers.ts","../../src/main/oauth-transport.ts","../../src/main/passkey-handlers.ts","../../src/main/create-clerk-bridge.ts"],"sourcesContent":["import { ipcMain } from 'electron';\n\nimport { TOKEN_CACHE_CHANNELS } from '../shared/ipc';\nimport type { TokenStorage } from '../shared/types';\n\nexport function setupTokenCacheIpcHandlers(storage: TokenStorage): () => void {\n ipcMain.handle(TOKEN_CACHE_CHANNELS.getToken, (_event, key: string) => {\n return storage.getItem(key);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.saveToken, (_event, key: string, value: string) => {\n return storage.setItem(key, value);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.clearToken, (_event, key: string) => {\n return storage.removeItem(key);\n });\n\n return () => {\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.getToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.saveToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.clearToken);\n };\n}\n","import { app, ipcMain, shell } from 'electron';\n\nimport { OAUTH_TRANSPORT_CHANNELS } from '../shared/ipc';\nimport type { RendererSchemeOptions } from '../shared/types';\n\nconst CALLBACK_TIMEOUT_MS = 3 * 60 * 1000;\n\ntype PendingOAuthFlow = {\n resolve: (value: { callbackUrl: string }) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n};\n\ntype OAuthTransportOptions = {\n renderer: RendererSchemeOptions;\n};\n\nfunction buildRedirectUrl(options: OAuthTransportOptions): string {\n return `${options.renderer.scheme}://${options.renderer.host}/`;\n}\n\nfunction isMatchingCallbackUrl(url: string, redirectUrl: string): boolean {\n try {\n const callback = new URL(url);\n const expected = new URL(redirectUrl);\n\n return (\n callback.protocol === expected.protocol &&\n callback.host === expected.host &&\n callback.pathname === expected.pathname\n );\n } catch {\n return false;\n }\n}\n\nfunction assertExternalOAuthUrl(url: string): void {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {\n throw new TypeError(`Clerk: refusing to open unsupported OAuth URL protocol: ${parsedUrl.protocol}`);\n }\n}\n\nexport function setupOAuthTransportIpcHandlers(options: OAuthTransportOptions): () => void {\n const redirectUrl = buildRedirectUrl(options);\n let pendingOAuthFlow: PendingOAuthFlow | null = null;\n\n const disposePendingOAuthFlow = (reason?: Error): void => {\n if (!pendingOAuthFlow) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n clearTimeout(pendingOAuthFlow.timeout);\n pendingOAuthFlow = null;\n\n if (reason) {\n pending.reject(reason);\n }\n };\n\n const handleCallbackUrl = (url: string): void => {\n if (!pendingOAuthFlow || !isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n disposePendingOAuthFlow();\n pending.resolve({ callbackUrl: url });\n };\n\n const openUrlListener = (event: Electron.Event, url: string): void => {\n if (!isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n event.preventDefault();\n handleCallbackUrl(url);\n };\n\n const secondInstanceListener = (_event: Electron.Event, argv: string[]): void => {\n const callbackUrl = argv.find(url => isMatchingCallbackUrl(url, redirectUrl));\n\n if (callbackUrl) {\n handleCallbackUrl(callbackUrl);\n }\n };\n\n app.setAsDefaultProtocolClient(options.renderer.scheme);\n app.on('open-url', openUrlListener);\n app.on('second-instance', secondInstanceListener);\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl, () => {\n return redirectUrl;\n });\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.open, async (_event, url: string) => {\n if (pendingOAuthFlow) {\n throw new Error('Clerk: an OAuth flow is already pending.');\n }\n\n assertExternalOAuthUrl(url);\n\n const callbackPromise = new Promise<{ callbackUrl: string }>((resolve, reject) => {\n const timeout = setTimeout(() => {\n disposePendingOAuthFlow();\n reject(new Error('Clerk: OAuth callback timed out.'));\n }, CALLBACK_TIMEOUT_MS);\n\n pendingOAuthFlow = { resolve, reject, timeout };\n });\n\n try {\n await shell.openExternal(url);\n } catch (err) {\n disposePendingOAuthFlow(err instanceof Error ? err : new Error(String(err)));\n }\n\n return callbackPromise;\n });\n\n return () => {\n disposePendingOAuthFlow(new Error('Clerk: OAuth flow was cancelled.'));\n app.removeListener('open-url', openUrlListener);\n app.removeListener('second-instance', secondInstanceListener);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.open);\n };\n}\n","import type { IpcMainInvokeEvent } from 'electron';\nimport { BrowserWindow, ipcMain } from 'electron';\n\nimport { PASSKEY_CHANNELS } from '../shared/ipc';\nimport type {\n AuthenticationResponseJSON,\n PasskeyCapabilities,\n PasskeyIpcResult,\n PasskeyNativeErrorCode,\n RegistrationResponseJSON,\n SerializedPublicKeyCredentialCreationOptions,\n SerializedPublicKeyCredentialRequestOptions,\n SetupPasskeysMainReturn,\n} from '../shared/types';\n\n/**\n * Optional native module. Ceremony failures resolve as JSON envelopes so error\n * codes survive both the FFI and Electron IPC boundaries.\n */\ntype NativePasskeysModule = {\n isAvailable: () => boolean;\n capabilities: () => Omit<PasskeyCapabilities, 'available'>;\n createCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n getCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n};\n\nlet nativeModulePromise: Promise<NativePasskeysModule> | undefined;\n\nfunction loadNativeModule(): Promise<NativePasskeysModule> {\n // Keep the native module optional for apps that do not use passkeys.\n nativeModulePromise ??= import('@clerk/electron-passkeys').then(\n (module: { default?: NativePasskeysModule } & NativePasskeysModule) => module.default ?? module,\n error => {\n nativeModulePromise = undefined;\n throw new Error(\n 'Clerk: createClerkBridge({ passkeys: true }) requires the optional @clerk/electron-passkeys package. Install it with your package manager to enable native passkey support.',\n { cause: error },\n );\n },\n );\n return nativeModulePromise;\n}\n\nconst NATIVE_ERROR_CODES: PasskeyNativeErrorCode[] = ['cancelled', 'invalid_rp', 'not_supported', 'timeout', 'unknown'];\n\nfunction isPasskeyIpcResult<T>(value: unknown): value is PasskeyIpcResult<T> {\n if (!value || typeof value !== 'object' || typeof (value as { ok?: unknown }).ok !== 'boolean') {\n return false;\n }\n const result = value as { ok: boolean; credential?: unknown; error?: { code?: unknown } };\n return result.ok\n ? result.credential !== undefined\n : NATIVE_ERROR_CODES.includes(result.error?.code as PasskeyNativeErrorCode);\n}\n\nasync function invokeNative<T>(\n method: 'createCredential' | 'getCredential',\n event: IpcMainInvokeEvent,\n options: SerializedPublicKeyCredentialCreationOptions | SerializedPublicKeyCredentialRequestOptions,\n): Promise<PasskeyIpcResult<T>> {\n let native: NativePasskeysModule;\n try {\n native = await loadNativeModule();\n } catch (error) {\n return {\n ok: false,\n error: { code: 'not_supported', message: error instanceof Error ? error.message : String(error) },\n };\n }\n\n if (!native.isAvailable()) {\n return {\n ok: false,\n error: { code: 'not_supported', message: 'Native passkeys are not supported on this platform.' },\n };\n }\n\n // Subframes and webviews can host third-party content that must not be able\n // to run credential ceremonies for the app's RP ID.\n if (!event.senderFrame || event.senderFrame !== event.sender.mainFrame) {\n return {\n ok: false,\n error: { code: 'unknown', message: \"The passkey request did not originate from a window's main frame.\" },\n };\n }\n\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window) {\n return {\n ok: false,\n error: { code: 'unknown', message: 'The passkey request did not originate from a visible window.' },\n };\n }\n\n try {\n const resultJson = await native[method](window.getNativeWindowHandle(), JSON.stringify(options));\n const result: unknown = JSON.parse(resultJson);\n if (!isPasskeyIpcResult<T>(result)) {\n return { ok: false, error: { code: 'unknown', message: 'The native module returned an unexpected result.' } };\n }\n return result;\n } catch (error) {\n return { ok: false, error: { code: 'unknown', message: error instanceof Error ? error.message : String(error) } };\n }\n}\n\n/** Registers IPC handlers for native platform WebAuthn. */\nexport function setupPasskeysMain(): SetupPasskeysMainReturn {\n // Surface a missing optional dependency during setup, before the first ceremony.\n loadNativeModule().catch((error: Error) => console.warn(error.message));\n\n ipcMain.handle(\n PASSKEY_CHANNELS.create,\n (\n event,\n options: SerializedPublicKeyCredentialCreationOptions,\n ): Promise<PasskeyIpcResult<RegistrationResponseJSON>> => invokeNative('createCredential', event, options),\n );\n\n ipcMain.handle(\n PASSKEY_CHANNELS.get,\n (\n event,\n options: SerializedPublicKeyCredentialRequestOptions,\n ): Promise<PasskeyIpcResult<AuthenticationResponseJSON>> => invokeNative('getCredential', event, options),\n );\n\n ipcMain.handle(PASSKEY_CHANNELS.capabilities, async (): Promise<PasskeyCapabilities> => {\n try {\n const native = await loadNativeModule();\n if (!native.isAvailable()) {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n return { available: true, ...native.capabilities() };\n } catch {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n });\n\n return {\n cleanup() {\n ipcMain.removeHandler(PASSKEY_CHANNELS.create);\n ipcMain.removeHandler(PASSKEY_CHANNELS.get);\n ipcMain.removeHandler(PASSKEY_CHANNELS.capabilities);\n },\n };\n}\n","import { protocol } from 'electron';\n\nimport type { ClerkBridge, CreateClerkBridgeOptions } from '../shared/types';\nimport { setupTokenCacheIpcHandlers } from './ipc-handlers';\nimport { setupOAuthTransportIpcHandlers } from './oauth-transport';\nimport { setupPasskeysMain } from './passkey-handlers';\n\nfunction assertValidRendererOriginConfig(renderer: NonNullable<CreateClerkBridgeOptions['renderer']>): void {\n if (renderer.scheme.includes(':') || renderer.scheme.includes('/')) {\n throw new Error(\n 'Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".',\n );\n }\n\n if (renderer.host.includes(':') || renderer.host.includes('/')) {\n throw new Error(\n 'Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".',\n );\n }\n}\n\n/**\n * Creates the Clerk bridge for Electron's main process.\n *\n * The bridge owns Clerk's main-process IPC handlers, token persistence, and OAuth deep-link\n * transport. Call this before creating renderer windows, and call the returned `cleanup` method\n * when tearing down the app or test environment.\n */\nexport function createClerkBridge(options: CreateClerkBridgeOptions): ClerkBridge {\n if (!options.storage) {\n throw new Error(\n 'Clerk: createClerkBridge requires a storage adapter. Pass createClerkBridge({ storage: storage() }) from @clerk/electron/storage, or provide a custom storage adapter.',\n );\n }\n\n const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);\n let cleanupOAuthTransport: (() => void) | undefined;\n const passkeys = options.passkeys ? setupPasskeysMain() : null;\n\n if (options.renderer) {\n assertValidRendererOriginConfig(options.renderer);\n\n protocol.registerSchemesAsPrivileged([\n {\n scheme: options.renderer.scheme,\n privileges: {\n standard: true,\n secure: true,\n supportFetchAPI: true,\n corsEnabled: true,\n stream: true,\n ...options.renderer.privileges,\n },\n },\n ]);\n\n cleanupOAuthTransport = setupOAuthTransportIpcHandlers({\n renderer: options.renderer,\n });\n }\n\n return {\n cleanup() {\n cleanupTokenPersistence();\n cleanupOAuthTransport?.();\n passkeys?.cleanup();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/main/ipc-handlers.ts","../../src/main/oauth-transport.ts","../../src/main/passkey-handlers.ts","../../src/main/create-clerk-bridge.ts"],"sourcesContent":["import { ipcMain } from 'electron';\n\nimport { TOKEN_CACHE_CHANNELS } from '../shared/ipc';\nimport type { TokenStorage } from '../shared/types';\n\nexport function setupTokenCacheIpcHandlers(storage: TokenStorage): () => void {\n ipcMain.handle(TOKEN_CACHE_CHANNELS.getToken, (_event, key: string) => {\n return storage.getItem(key);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.saveToken, (_event, key: string, value: string) => {\n return storage.setItem(key, value);\n });\n\n ipcMain.handle(TOKEN_CACHE_CHANNELS.clearToken, (_event, key: string) => {\n return storage.removeItem(key);\n });\n\n return () => {\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.getToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.saveToken);\n ipcMain.removeHandler(TOKEN_CACHE_CHANNELS.clearToken);\n };\n}\n","import { app, ipcMain, shell } from 'electron';\n\nimport { OAUTH_TRANSPORT_CHANNELS } from '../shared/ipc';\nimport type { RendererSchemeOptions } from '../shared/types';\n\nconst CALLBACK_TIMEOUT_MS = 3 * 60 * 1000;\n\ntype PendingOAuthFlow = {\n resolve: (value: { callbackUrl: string }) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n};\n\ntype OAuthTransportOptions = {\n renderer: RendererSchemeOptions;\n};\n\nfunction buildRedirectUrl(options: OAuthTransportOptions): string {\n return `${options.renderer.scheme}://${options.renderer.host}/`;\n}\n\nfunction isMatchingCallbackUrl(url: string, redirectUrl: string): boolean {\n try {\n const callback = new URL(url);\n const expected = new URL(redirectUrl);\n\n return (\n callback.protocol === expected.protocol &&\n callback.host === expected.host &&\n callback.pathname === expected.pathname\n );\n } catch {\n return false;\n }\n}\n\nfunction assertExternalOAuthUrl(url: string): void {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {\n throw new TypeError(`Clerk: refusing to open unsupported OAuth URL protocol: ${parsedUrl.protocol}`);\n }\n}\n\nexport function setupOAuthTransportIpcHandlers(options: OAuthTransportOptions): () => void {\n const redirectUrl = buildRedirectUrl(options);\n let pendingOAuthFlow: PendingOAuthFlow | null = null;\n\n const disposePendingOAuthFlow = (reason?: Error): void => {\n if (!pendingOAuthFlow) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n clearTimeout(pendingOAuthFlow.timeout);\n pendingOAuthFlow = null;\n\n if (reason) {\n pending.reject(reason);\n }\n };\n\n const handleCallbackUrl = (url: string): void => {\n if (!pendingOAuthFlow || !isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n const pending = pendingOAuthFlow;\n disposePendingOAuthFlow();\n pending.resolve({ callbackUrl: url });\n };\n\n const openUrlListener = (event: Electron.Event, url: string): void => {\n if (!isMatchingCallbackUrl(url, redirectUrl)) {\n return;\n }\n\n event.preventDefault();\n handleCallbackUrl(url);\n };\n\n const secondInstanceListener = (_event: Electron.Event, argv: string[]): void => {\n const callbackUrl = argv.find(url => isMatchingCallbackUrl(url, redirectUrl));\n\n if (callbackUrl) {\n handleCallbackUrl(callbackUrl);\n }\n };\n\n app.setAsDefaultProtocolClient(options.renderer.scheme);\n app.on('open-url', openUrlListener);\n app.on('second-instance', secondInstanceListener);\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl, () => {\n return redirectUrl;\n });\n\n ipcMain.handle(OAUTH_TRANSPORT_CHANNELS.open, async (_event, url: string) => {\n if (pendingOAuthFlow) {\n throw new Error('Clerk: an OAuth flow is already pending.');\n }\n\n assertExternalOAuthUrl(url);\n\n const callbackPromise = new Promise<{ callbackUrl: string }>((resolve, reject) => {\n const timeout = setTimeout(() => {\n disposePendingOAuthFlow();\n reject(new Error('Clerk: OAuth callback timed out.'));\n }, CALLBACK_TIMEOUT_MS);\n\n pendingOAuthFlow = { resolve, reject, timeout };\n });\n\n try {\n await shell.openExternal(url);\n } catch (err) {\n disposePendingOAuthFlow(err instanceof Error ? err : new Error(String(err)));\n }\n\n return callbackPromise;\n });\n\n return () => {\n disposePendingOAuthFlow(new Error('Clerk: OAuth flow was cancelled.'));\n app.removeListener('open-url', openUrlListener);\n app.removeListener('second-instance', secondInstanceListener);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.getRedirectUrl);\n ipcMain.removeHandler(OAUTH_TRANSPORT_CHANNELS.open);\n };\n}\n","import type { IpcMainInvokeEvent } from 'electron';\nimport { BrowserWindow, ipcMain } from 'electron';\n\nimport { PASSKEY_CHANNELS } from '../shared/ipc';\nimport type {\n AuthenticationResponseJSON,\n PasskeyCapabilities,\n PasskeyIpcResult,\n PasskeyNativeErrorCode,\n RegistrationResponseJSON,\n SerializedPublicKeyCredentialCreationOptions,\n SerializedPublicKeyCredentialRequestOptions,\n SetupPasskeysMainReturn,\n} from '../shared/types';\n\n/**\n * Optional native module. Ceremony failures resolve as JSON envelopes so error\n * codes survive both the FFI and Electron IPC boundaries.\n */\ntype NativePasskeysModule = {\n isAvailable: () => boolean;\n capabilities: () => Omit<PasskeyCapabilities, 'available'>;\n createCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n getCredential: (windowHandle: Buffer, optionsJson: string) => Promise<string>;\n};\n\nlet nativeModulePromise: Promise<NativePasskeysModule> | undefined;\n\nfunction loadNativeModule(): Promise<NativePasskeysModule> {\n // Keep the native module optional for apps that do not use passkeys.\n nativeModulePromise ??= import('@clerk/electron-passkeys').then(\n (module: { default?: NativePasskeysModule } & NativePasskeysModule) => module.default ?? module,\n error => {\n nativeModulePromise = undefined;\n throw new Error(\n 'Clerk: createClerkBridge({ passkeys: true }) requires the optional @clerk/electron-passkeys package. Install it with your package manager to enable native passkey support.',\n { cause: error },\n );\n },\n );\n return nativeModulePromise;\n}\n\nconst NATIVE_ERROR_CODES: PasskeyNativeErrorCode[] = ['cancelled', 'invalid_rp', 'not_supported', 'timeout', 'unknown'];\n\nfunction isPasskeyIpcResult<T>(value: unknown): value is PasskeyIpcResult<T> {\n if (!value || typeof value !== 'object' || typeof (value as { ok?: unknown }).ok !== 'boolean') {\n return false;\n }\n const result = value as { ok: boolean; credential?: unknown; error?: { code?: unknown } };\n return result.ok\n ? result.credential !== undefined\n : NATIVE_ERROR_CODES.includes(result.error?.code as PasskeyNativeErrorCode);\n}\n\nasync function invokeNative<T>(\n method: 'createCredential' | 'getCredential',\n event: IpcMainInvokeEvent,\n options: SerializedPublicKeyCredentialCreationOptions | SerializedPublicKeyCredentialRequestOptions,\n): Promise<PasskeyIpcResult<T>> {\n let native: NativePasskeysModule;\n try {\n native = await loadNativeModule();\n } catch (error) {\n return {\n ok: false,\n error: { code: 'not_supported', message: error instanceof Error ? error.message : String(error) },\n };\n }\n\n if (!native.isAvailable()) {\n return {\n ok: false,\n error: { code: 'not_supported', message: 'Native passkeys are not supported on this platform.' },\n };\n }\n\n // Subframes and webviews can host third-party content that must not be able\n // to run credential ceremonies for the app's RP ID.\n if (!event.senderFrame || event.senderFrame !== event.sender.mainFrame) {\n return {\n ok: false,\n error: { code: 'unknown', message: \"The passkey request did not originate from a window's main frame.\" },\n };\n }\n\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window) {\n return {\n ok: false,\n error: { code: 'unknown', message: 'The passkey request did not originate from a visible window.' },\n };\n }\n\n try {\n const resultJson = await native[method](window.getNativeWindowHandle(), JSON.stringify(options));\n const result: unknown = JSON.parse(resultJson);\n if (!isPasskeyIpcResult<T>(result)) {\n return { ok: false, error: { code: 'unknown', message: 'The native module returned an unexpected result.' } };\n }\n return result;\n } catch (error) {\n return { ok: false, error: { code: 'unknown', message: error instanceof Error ? error.message : String(error) } };\n }\n}\n\n/** Registers IPC handlers for native platform WebAuthn. */\nexport function setupPasskeysMain(): SetupPasskeysMainReturn {\n // Surface a missing optional dependency during setup, before the first ceremony.\n loadNativeModule().catch((error: Error) => console.warn(error.message));\n\n ipcMain.handle(\n PASSKEY_CHANNELS.create,\n (\n event,\n options: SerializedPublicKeyCredentialCreationOptions,\n ): Promise<PasskeyIpcResult<RegistrationResponseJSON>> => invokeNative('createCredential', event, options),\n );\n\n ipcMain.handle(\n PASSKEY_CHANNELS.get,\n (\n event,\n options: SerializedPublicKeyCredentialRequestOptions,\n ): Promise<PasskeyIpcResult<AuthenticationResponseJSON>> => invokeNative('getCredential', event, options),\n );\n\n ipcMain.handle(PASSKEY_CHANNELS.capabilities, async (): Promise<PasskeyCapabilities> => {\n try {\n const native = await loadNativeModule();\n if (!native.isAvailable()) {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n return { available: true, ...native.capabilities() };\n } catch {\n return { available: false, platformAuthenticator: false, securityKeys: false };\n }\n });\n\n return {\n cleanup() {\n ipcMain.removeHandler(PASSKEY_CHANNELS.create);\n ipcMain.removeHandler(PASSKEY_CHANNELS.get);\n ipcMain.removeHandler(PASSKEY_CHANNELS.capabilities);\n },\n };\n}\n","import { app, protocol } from 'electron';\n\nimport type { ClerkBridge, CreateClerkBridgeOptions } from '../shared/types';\nimport { setupTokenCacheIpcHandlers } from './ipc-handlers';\nimport { setupOAuthTransportIpcHandlers } from './oauth-transport';\nimport { setupPasskeysMain } from './passkey-handlers';\n\nfunction assertValidRendererOriginConfig(renderer: NonNullable<CreateClerkBridgeOptions['renderer']>): void {\n if (renderer.scheme.includes(':') || renderer.scheme.includes('/')) {\n throw new Error(\n 'Clerk: renderer.scheme must be a scheme name like \"my-app\", not a URL or protocol like \"my-app://\".',\n );\n }\n\n if (renderer.host.includes(':') || renderer.host.includes('/')) {\n throw new Error(\n 'Clerk: renderer.host must be a host name like \"renderer\", not a URL or origin like \"my-app://renderer\".',\n );\n }\n}\n\nfunction buildUserAgentFallback(defaultUserAgent: string, productToken: string): string {\n const platformCommentStart = defaultUserAgent.indexOf('(');\n const platformCommentEnd = defaultUserAgent.indexOf(')', platformCommentStart + 1);\n\n if (platformCommentStart === -1 || platformCommentEnd === -1) {\n return productToken;\n }\n\n const platformComment = defaultUserAgent.slice(platformCommentStart, platformCommentEnd + 1);\n\n // Clerk's session activity parser preserves the platform comment and treats the\n // token after Gecko as the app/browser name.\n return `Mozilla/5.0 ${platformComment} Gecko/20100101 ${productToken}`;\n}\n\n/**\n * Creates the Clerk bridge for Electron's main process.\n *\n * The bridge owns Clerk's main-process IPC handlers, token persistence, and OAuth deep-link\n * transport. Call this before creating renderer windows, and call the returned `cleanup` method\n * when tearing down the app or test environment.\n */\nexport function createClerkBridge(options: CreateClerkBridgeOptions): ClerkBridge {\n if (!options.storage) {\n throw new Error(\n 'Clerk: createClerkBridge requires a storage adapter. Pass createClerkBridge({ storage: storage() }) from @clerk/electron/storage, or provide a custom storage adapter.',\n );\n }\n\n const cleanupTokenPersistence = setupTokenCacheIpcHandlers(options.storage);\n let cleanupOAuthTransport: (() => void) | undefined;\n const passkeys = options.passkeys ? setupPasskeysMain() : null;\n\n if (options.userAgent) {\n app.userAgentFallback = buildUserAgentFallback(app.userAgentFallback, options.userAgent);\n }\n\n if (options.renderer) {\n assertValidRendererOriginConfig(options.renderer);\n\n protocol.registerSchemesAsPrivileged([\n {\n scheme: options.renderer.scheme,\n privileges: {\n standard: true,\n secure: true,\n supportFetchAPI: true,\n corsEnabled: true,\n stream: true,\n ...options.renderer.privileges,\n },\n },\n ]);\n\n cleanupOAuthTransport = setupOAuthTransportIpcHandlers({\n renderer: options.renderer,\n });\n }\n\n return {\n cleanup() {\n cleanupTokenPersistence();\n cleanupOAuthTransport?.();\n passkeys?.cleanup();\n },\n };\n}\n"],"mappings":"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"}
@@ -26,7 +26,7 @@ function createClerkInstance(publishableKey, passkeys) {
26
26
  clerk.__internal_onBeforeRequest(async (request) => {
27
27
  request.credentials = "omit";
28
28
  request.url?.searchParams.append("_is_native", "1");
29
- request.url?.searchParams.append("_electron_sdk_version", "0.0.9-snapshot.v20260702192602");
29
+ request.url?.searchParams.append("_electron_sdk_version", "0.0.9");
30
30
  const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);
31
31
  if (token) {
32
32
  const headers = new Headers(request.headers);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ReactClerkProvider"],"sources":["../../../src/react/create-clerk-instance.ts","../../../src/react/index.tsx"],"sourcesContent":["import { Clerk } from '@clerk/clerk-js';\n\n// Type-only import: the passkeys module is only bundled when the app imports\n// `@clerk/electron/passkeys` itself.\nimport type { PasskeySupport } from '../passkeys';\n\nconst CLERK_CLIENT_JWT_KEY = '__clerk_client_jwt';\n\ntype ClerkInstance = InstanceType<typeof Clerk>;\n\nlet cached: { instance: ClerkInstance; publishableKey: string } | null = null;\n\nfunction attachPasskeys(clerk: ClerkInstance, passkeys: PasskeySupport): void {\n clerk.__internal_createPublicCredentials = passkeys.create;\n clerk.__internal_getPublicCredentials = passkeys.get;\n clerk.__internal_isWebAuthnSupported = passkeys.isSupported;\n clerk.__internal_isWebAuthnAutofillSupported = passkeys.isAutoFillSupported;\n clerk.__internal_isWebAuthnPlatformAuthenticatorSupported = passkeys.isPlatformAuthenticatorSupported;\n}\n\nexport function createClerkInstance(publishableKey: string, passkeys?: PasskeySupport): ClerkInstance {\n if (cached?.publishableKey === publishableKey) {\n if (passkeys) {\n attachPasskeys(cached.instance, passkeys);\n }\n return cached.instance;\n }\n\n const clerk = new Clerk(publishableKey);\n\n if (passkeys) {\n attachPasskeys(clerk, passkeys);\n }\n\n clerk.__internal_onBeforeRequest(async request => {\n request.credentials = 'omit';\n request.url?.searchParams.append('_is_native', '1');\n request.url?.searchParams.append('_electron_sdk_version', PACKAGE_VERSION);\n\n const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);\n if (token) {\n const headers = new Headers(request.headers);\n headers.set('Authorization', `Bearer ${token}`);\n request.headers = headers;\n }\n });\n\n clerk.__internal_onAfterResponse(async (_request, response) => {\n const authorization = (response as Response).headers.get('Authorization');\n if (!authorization) {\n return;\n }\n\n const token = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : authorization;\n await window.__clerk_internal_electron?.tokenCache.saveToken(CLERK_CLIENT_JWT_KEY, token);\n });\n\n cached = { instance: clerk, publishableKey };\n return clerk;\n}\n","import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ReactClerkProvider } from '@clerk/react/internal';\nimport { ALLOWED_PROTOCOLS } from '@clerk/shared/internal/clerk-js/windowNavigate';\nimport { loadClerkUIScript } from '@clerk/shared/loadClerkJsScript';\nimport type { ClerkUIConstructor } from '@clerk/shared/ui';\nimport type { ReactNode } from 'react';\n\nimport type { PasskeySupport } from '../passkeys';\nimport { createClerkInstance } from './create-clerk-instance';\n\ntype ClerkOAuthTransport = NonNullable<ReactClerkProviderProps['__internal_oauthTransport']>;\n\nexport type ClerkProviderProps = Omit<\n ReactClerkProviderProps,\n 'Clerk' | 'children' | 'publishableKey' | 'standardBrowser' | 'ui' | '__internal_oauthTransport'\n> & {\n children: ReactNode;\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n */\n publishableKey: string;\n /**\n * Enables passkey support. Pass the `passkeys` export from `@clerk/electron/passkeys`;\n * when omitted, no passkey code is bundled or initialized.\n *\n * @example\n * ```tsx\n * import { passkeys } from '@clerk/electron/passkeys';\n *\n * <ClerkProvider publishableKey={publishableKey} passkeys={passkeys} />\n * ```\n */\n passkeys?: PasskeySupport;\n};\n\nlet cachedClerkUI: { promise: Promise<ClerkUIConstructor>; publishableKey: string } | null = null;\n\nfunction loadClerkUI(publishableKey: string, props: Partial<ClerkProviderProps>): Promise<ClerkUIConstructor> {\n if (cachedClerkUI?.publishableKey === publishableKey) {\n return cachedClerkUI.promise;\n }\n\n // Undocumented escape hatch for self-hosting/proxying the UI bundle; not part of the public props.\n const { __internal_clerkUIUrl, __internal_clerkUIVersion } = props as {\n __internal_clerkUIUrl?: string;\n __internal_clerkUIVersion?: string;\n };\n\n const promise = loadClerkUIScript({\n publishableKey,\n proxyUrl: typeof props.proxyUrl === 'string' ? props.proxyUrl : undefined,\n domain: typeof props.domain === 'string' ? props.domain : undefined,\n nonce: props.nonce,\n __internal_clerkUIUrl,\n __internal_clerkUIVersion,\n }).then(() => {\n if (!window.__internal_ClerkUICtor) {\n throw new Error(\n 'Clerk: Failed to load Clerk UI from the CDN. Ensure your Content Security Policy allows the Clerk Frontend API host in `script-src`. Contact support@clerk.com.',\n );\n }\n return window.__internal_ClerkUICtor;\n });\n\n cachedClerkUI = { promise, publishableKey };\n return promise;\n}\n\nfunction createOAuthTransport(): ClerkOAuthTransport | undefined {\n const bridge = window.__clerk_internal_electron?.oauthTransport;\n\n if (!bridge) {\n return undefined;\n }\n\n return {\n getRedirectUrl: () => bridge.getRedirectUrl(),\n open: url => bridge.open(url.href),\n };\n}\n\n/**\n * Infer the custom renderer scheme registered with `createClerkBridge({ renderer })`.\n * Built-in Clerk protocols and local file renderers are not inferred.\n */\nfunction defaultAllowedRedirectProtocols(): string[] | undefined {\n const protocol = typeof window !== 'undefined' ? window.location?.protocol : undefined;\n\n if (!protocol || ALLOWED_PROTOCOLS.includes(protocol) || protocol === 'file:') {\n return undefined;\n }\n\n return [protocol];\n}\n\nexport function ClerkProvider({\n children,\n publishableKey,\n passkeys,\n allowedRedirectProtocols,\n ...props\n}: ClerkProviderProps): JSX.Element {\n const clerk = createClerkInstance(publishableKey, passkeys);\n const oauthTransport = createOAuthTransport();\n const clerkUI = loadClerkUI(publishableKey, props);\n\n return (\n <ReactClerkProvider\n {...props}\n Clerk={clerk}\n __internal_oauthTransport={oauthTransport}\n allowedRedirectProtocols={allowedRedirectProtocols ?? defaultAllowedRedirectProtocols()}\n publishableKey={publishableKey}\n standardBrowser={false}\n ui={{ ClerkUI: clerkUI }}\n >\n {children}\n </ReactClerkProvider>\n );\n}\n\nexport * from '@clerk/react';\n"],"mappings":";;;;;;;;;AAMA,MAAM,uBAAuB;AAI7B,IAAI,SAAqE;AAEzE,SAAS,eAAe,OAAsB,UAAgC;CAC5E,MAAM,qCAAqC,SAAS;CACpD,MAAM,kCAAkC,SAAS;CACjD,MAAM,iCAAiC,SAAS;CAChD,MAAM,yCAAyC,SAAS;CACxD,MAAM,sDAAsD,SAAS;AACvE;AAEA,SAAgB,oBAAoB,gBAAwB,UAA0C;CACpG,IAAI,QAAQ,mBAAmB,gBAAgB;EAC7C,IAAI,UACF,eAAe,OAAO,UAAU,QAAQ;EAE1C,OAAO,OAAO;CAChB;CAEA,MAAM,QAAQ,IAAI,MAAM,cAAc;CAEtC,IAAI,UACF,eAAe,OAAO,QAAQ;CAGhC,MAAM,2BAA2B,OAAM,YAAW;EAChD,QAAQ,cAAc;EACtB,QAAQ,KAAK,aAAa,OAAO,cAAc,GAAG;EAClD,QAAQ,KAAK,aAAa,OAAO,yDAAwC;EAEzE,MAAM,QAAQ,MAAM,OAAO,2BAA2B,WAAW,SAAS,oBAAoB;EAC9F,IAAI,OAAO;GACT,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;GAC3C,QAAQ,IAAI,iBAAiB,UAAU,OAAO;GAC9C,QAAQ,UAAU;EACpB;CACF,CAAC;CAED,MAAM,2BAA2B,OAAO,UAAU,aAAa;EAC7D,MAAM,gBAAiB,SAAsB,QAAQ,IAAI,eAAe;EACxE,IAAI,CAAC,eACH;EAGF,MAAM,QAAQ,cAAc,WAAW,SAAS,IAAI,cAAc,MAAM,CAAgB,IAAI;EAC5F,MAAM,OAAO,2BAA2B,WAAW,UAAU,sBAAsB,KAAK;CAC1F,CAAC;CAED,SAAS;EAAE,UAAU;EAAO;CAAe;CAC3C,OAAO;AACT;;;;ACxBA,IAAI,gBAAyF;AAE7F,SAAS,YAAY,gBAAwB,OAAiE;CAC5G,IAAI,eAAe,mBAAmB,gBACpC,OAAO,cAAc;CAIvB,MAAM,EAAE,uBAAuB,8BAA8B;CAK7D,MAAM,UAAU,kBAAkB;EAChC;EACA,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;EAC1D,OAAO,MAAM;EACb;EACA;CACF,CAAC,CAAC,CAAC,WAAW;EACZ,IAAI,CAAC,OAAO,wBACV,MAAM,IAAI,MACR,iKACF;EAEF,OAAO,OAAO;CAChB,CAAC;CAED,gBAAgB;EAAE;EAAS;CAAe;CAC1C,OAAO;AACT;AAEA,SAAS,uBAAwD;CAC/D,MAAM,SAAS,OAAO,2BAA2B;CAEjD,IAAI,CAAC,QACH;CAGF,OAAO;EACL,sBAAsB,OAAO,eAAe;EAC5C,OAAM,QAAO,OAAO,KAAK,IAAI,IAAI;CACnC;AACF;;;;;AAMA,SAAS,kCAAwD;CAC/D,MAAM,WAAW,OAAO,WAAW,cAAc,OAAO,UAAU,WAAW;CAE7E,IAAI,CAAC,YAAY,kBAAkB,SAAS,QAAQ,KAAK,aAAa,SACpE;CAGF,OAAO,CAAC,QAAQ;AAClB;AAEA,SAAgB,cAAc,EAC5B,UACA,gBACA,UACA,0BACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,oBAAoB,gBAAgB,QAAQ;CAC1D,MAAM,iBAAiB,qBAAqB;CAC5C,MAAM,UAAU,YAAY,gBAAgB,KAAK;CAEjD,OACE,oBAACA,uBAAD;EACE,GAAI;EACJ,OAAO;EACP,2BAA2B;EAC3B,0BAA0B,4BAA4B,gCAAgC;EACtE;EAChB,iBAAiB;EACjB,IAAI,EAAE,SAAS,QAAQ;EAEtB;CACiB;AAExB"}
1
+ {"version":3,"file":"index.js","names":["ReactClerkProvider"],"sources":["../../../src/react/create-clerk-instance.ts","../../../src/react/index.tsx"],"sourcesContent":["import { Clerk } from '@clerk/clerk-js';\n\n// Type-only import: the passkeys module is only bundled when the app imports\n// `@clerk/electron/passkeys` itself.\nimport type { PasskeySupport } from '../passkeys';\n\nconst CLERK_CLIENT_JWT_KEY = '__clerk_client_jwt';\n\ntype ClerkInstance = InstanceType<typeof Clerk>;\n\nlet cached: { instance: ClerkInstance; publishableKey: string } | null = null;\n\nfunction attachPasskeys(clerk: ClerkInstance, passkeys: PasskeySupport): void {\n clerk.__internal_createPublicCredentials = passkeys.create;\n clerk.__internal_getPublicCredentials = passkeys.get;\n clerk.__internal_isWebAuthnSupported = passkeys.isSupported;\n clerk.__internal_isWebAuthnAutofillSupported = passkeys.isAutoFillSupported;\n clerk.__internal_isWebAuthnPlatformAuthenticatorSupported = passkeys.isPlatformAuthenticatorSupported;\n}\n\nexport function createClerkInstance(publishableKey: string, passkeys?: PasskeySupport): ClerkInstance {\n if (cached?.publishableKey === publishableKey) {\n if (passkeys) {\n attachPasskeys(cached.instance, passkeys);\n }\n return cached.instance;\n }\n\n const clerk = new Clerk(publishableKey);\n\n if (passkeys) {\n attachPasskeys(clerk, passkeys);\n }\n\n clerk.__internal_onBeforeRequest(async request => {\n request.credentials = 'omit';\n request.url?.searchParams.append('_is_native', '1');\n request.url?.searchParams.append('_electron_sdk_version', PACKAGE_VERSION);\n\n const token = await window.__clerk_internal_electron?.tokenCache.getToken(CLERK_CLIENT_JWT_KEY);\n if (token) {\n const headers = new Headers(request.headers);\n headers.set('Authorization', `Bearer ${token}`);\n request.headers = headers;\n }\n });\n\n clerk.__internal_onAfterResponse(async (_request, response) => {\n const authorization = (response as Response).headers.get('Authorization');\n if (!authorization) {\n return;\n }\n\n const token = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : authorization;\n await window.__clerk_internal_electron?.tokenCache.saveToken(CLERK_CLIENT_JWT_KEY, token);\n });\n\n cached = { instance: clerk, publishableKey };\n return clerk;\n}\n","import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ReactClerkProvider } from '@clerk/react/internal';\nimport { ALLOWED_PROTOCOLS } from '@clerk/shared/internal/clerk-js/windowNavigate';\nimport { loadClerkUIScript } from '@clerk/shared/loadClerkJsScript';\nimport type { ClerkUIConstructor } from '@clerk/shared/ui';\nimport type { ReactNode } from 'react';\n\nimport type { PasskeySupport } from '../passkeys';\nimport { createClerkInstance } from './create-clerk-instance';\n\ntype ClerkOAuthTransport = NonNullable<ReactClerkProviderProps['__internal_oauthTransport']>;\n\nexport type ClerkProviderProps = Omit<\n ReactClerkProviderProps,\n 'Clerk' | 'children' | 'publishableKey' | 'standardBrowser' | 'ui' | '__internal_oauthTransport'\n> & {\n children: ReactNode;\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n */\n publishableKey: string;\n /**\n * Enables passkey support. Pass the `passkeys` export from `@clerk/electron/passkeys`;\n * when omitted, no passkey code is bundled or initialized.\n *\n * @example\n * ```tsx\n * import { passkeys } from '@clerk/electron/passkeys';\n *\n * <ClerkProvider publishableKey={publishableKey} passkeys={passkeys} />\n * ```\n */\n passkeys?: PasskeySupport;\n};\n\nlet cachedClerkUI: { promise: Promise<ClerkUIConstructor>; publishableKey: string } | null = null;\n\nfunction loadClerkUI(publishableKey: string, props: Partial<ClerkProviderProps>): Promise<ClerkUIConstructor> {\n if (cachedClerkUI?.publishableKey === publishableKey) {\n return cachedClerkUI.promise;\n }\n\n // Undocumented escape hatch for self-hosting/proxying the UI bundle; not part of the public props.\n const { __internal_clerkUIUrl, __internal_clerkUIVersion } = props as {\n __internal_clerkUIUrl?: string;\n __internal_clerkUIVersion?: string;\n };\n\n const promise = loadClerkUIScript({\n publishableKey,\n proxyUrl: typeof props.proxyUrl === 'string' ? props.proxyUrl : undefined,\n domain: typeof props.domain === 'string' ? props.domain : undefined,\n nonce: props.nonce,\n __internal_clerkUIUrl,\n __internal_clerkUIVersion,\n }).then(() => {\n if (!window.__internal_ClerkUICtor) {\n throw new Error(\n 'Clerk: Failed to load Clerk UI from the CDN. Ensure your Content Security Policy allows the Clerk Frontend API host in `script-src`. Contact support@clerk.com.',\n );\n }\n return window.__internal_ClerkUICtor;\n });\n\n cachedClerkUI = { promise, publishableKey };\n return promise;\n}\n\nfunction createOAuthTransport(): ClerkOAuthTransport | undefined {\n const bridge = window.__clerk_internal_electron?.oauthTransport;\n\n if (!bridge) {\n return undefined;\n }\n\n return {\n getRedirectUrl: () => bridge.getRedirectUrl(),\n open: url => bridge.open(url.href),\n };\n}\n\n/**\n * Infer the custom renderer scheme registered with `createClerkBridge({ renderer })`.\n * Built-in Clerk protocols and local file renderers are not inferred.\n */\nfunction defaultAllowedRedirectProtocols(): string[] | undefined {\n const protocol = typeof window !== 'undefined' ? window.location?.protocol : undefined;\n\n if (!protocol || ALLOWED_PROTOCOLS.includes(protocol) || protocol === 'file:') {\n return undefined;\n }\n\n return [protocol];\n}\n\nexport function ClerkProvider({\n children,\n publishableKey,\n passkeys,\n allowedRedirectProtocols,\n ...props\n}: ClerkProviderProps): JSX.Element {\n const clerk = createClerkInstance(publishableKey, passkeys);\n const oauthTransport = createOAuthTransport();\n const clerkUI = loadClerkUI(publishableKey, props);\n\n return (\n <ReactClerkProvider\n {...props}\n Clerk={clerk}\n __internal_oauthTransport={oauthTransport}\n allowedRedirectProtocols={allowedRedirectProtocols ?? defaultAllowedRedirectProtocols()}\n publishableKey={publishableKey}\n standardBrowser={false}\n ui={{ ClerkUI: clerkUI }}\n >\n {children}\n </ReactClerkProvider>\n );\n}\n\nexport * from '@clerk/react';\n"],"mappings":";;;;;;;;;AAMA,MAAM,uBAAuB;AAI7B,IAAI,SAAqE;AAEzE,SAAS,eAAe,OAAsB,UAAgC;CAC5E,MAAM,qCAAqC,SAAS;CACpD,MAAM,kCAAkC,SAAS;CACjD,MAAM,iCAAiC,SAAS;CAChD,MAAM,yCAAyC,SAAS;CACxD,MAAM,sDAAsD,SAAS;AACvE;AAEA,SAAgB,oBAAoB,gBAAwB,UAA0C;CACpG,IAAI,QAAQ,mBAAmB,gBAAgB;EAC7C,IAAI,UACF,eAAe,OAAO,UAAU,QAAQ;EAE1C,OAAO,OAAO;CAChB;CAEA,MAAM,QAAQ,IAAI,MAAM,cAAc;CAEtC,IAAI,UACF,eAAe,OAAO,QAAQ;CAGhC,MAAM,2BAA2B,OAAM,YAAW;EAChD,QAAQ,cAAc;EACtB,QAAQ,KAAK,aAAa,OAAO,cAAc,GAAG;EAClD,QAAQ,KAAK,aAAa,OAAO,gCAAwC;EAEzE,MAAM,QAAQ,MAAM,OAAO,2BAA2B,WAAW,SAAS,oBAAoB;EAC9F,IAAI,OAAO;GACT,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;GAC3C,QAAQ,IAAI,iBAAiB,UAAU,OAAO;GAC9C,QAAQ,UAAU;EACpB;CACF,CAAC;CAED,MAAM,2BAA2B,OAAO,UAAU,aAAa;EAC7D,MAAM,gBAAiB,SAAsB,QAAQ,IAAI,eAAe;EACxE,IAAI,CAAC,eACH;EAGF,MAAM,QAAQ,cAAc,WAAW,SAAS,IAAI,cAAc,MAAM,CAAgB,IAAI;EAC5F,MAAM,OAAO,2BAA2B,WAAW,UAAU,sBAAsB,KAAK;CAC1F,CAAC;CAED,SAAS;EAAE,UAAU;EAAO;CAAe;CAC3C,OAAO;AACT;;;;ACxBA,IAAI,gBAAyF;AAE7F,SAAS,YAAY,gBAAwB,OAAiE;CAC5G,IAAI,eAAe,mBAAmB,gBACpC,OAAO,cAAc;CAIvB,MAAM,EAAE,uBAAuB,8BAA8B;CAK7D,MAAM,UAAU,kBAAkB;EAChC;EACA,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;EAC1D,OAAO,MAAM;EACb;EACA;CACF,CAAC,CAAC,CAAC,WAAW;EACZ,IAAI,CAAC,OAAO,wBACV,MAAM,IAAI,MACR,iKACF;EAEF,OAAO,OAAO;CAChB,CAAC;CAED,gBAAgB;EAAE;EAAS;CAAe;CAC1C,OAAO;AACT;AAEA,SAAS,uBAAwD;CAC/D,MAAM,SAAS,OAAO,2BAA2B;CAEjD,IAAI,CAAC,QACH;CAGF,OAAO;EACL,sBAAsB,OAAO,eAAe;EAC5C,OAAM,QAAO,OAAO,KAAK,IAAI,IAAI;CACnC;AACF;;;;;AAMA,SAAS,kCAAwD;CAC/D,MAAM,WAAW,OAAO,WAAW,cAAc,OAAO,UAAU,WAAW;CAE7E,IAAI,CAAC,YAAY,kBAAkB,SAAS,QAAQ,KAAK,aAAa,SACpE;CAGF,OAAO,CAAC,QAAQ;AAClB;AAEA,SAAgB,cAAc,EAC5B,UACA,gBACA,UACA,0BACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,oBAAoB,gBAAgB,QAAQ;CAC1D,MAAM,iBAAiB,qBAAqB;CAC5C,MAAM,UAAU,YAAY,gBAAgB,KAAK;CAEjD,OACE,oBAACA,uBAAD;EACE,GAAI;EACJ,OAAO;EACP,2BAA2B;EAC3B,0BAA0B,4BAA4B,gCAAgC;EACtE;EAChB,iBAAiB;EACjB,IAAI,EAAE,SAAS,QAAQ;EAEtB;CACiB;AAExB"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-clerk-bridge.d.ts","sourceRoot":"","sources":["../../../src/main/create-clerk-bridge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAmB7E;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CAwChF"}
1
+ {"version":3,"file":"create-clerk-bridge.d.ts","sourceRoot":"","sources":["../../../src/main/create-clerk-bridge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAkC7E;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CA4ChF"}
@@ -19,6 +19,13 @@ export type CreateClerkBridgeOptions = {
19
19
  * the optional `@clerk/electron-passkeys` package and `exposeClerkBridge({ passkeys: true })`.
20
20
  */
21
21
  passkeys?: boolean;
22
+ /**
23
+ * Product token to use in Electron's user-agent fallback. Clerk uses the resulting
24
+ * user-agent for UserProfile session activity attribution when no webContents or
25
+ * session-level user-agent is set. The Electron platform comment is preserved so
26
+ * device details such as macOS or Windows can still be detected.
27
+ */
28
+ userAgent?: string;
22
29
  };
23
30
  export type ExposeClerkBridgeOptions = {
24
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerk/electron",
3
- "version": "0.0.9-snapshot.v20260702192602",
3
+ "version": "0.0.9",
4
4
  "description": "Clerk SDK for Electron",
5
5
  "keywords": [
6
6
  "clerk",
@@ -84,18 +84,18 @@
84
84
  ],
85
85
  "dependencies": {
86
86
  "tslib": "2.8.1",
87
- "@clerk/clerk-js": "6.23.1-snapshot.v20260702192602",
88
- "@clerk/react": "6.11.4-snapshot.v20260702192602",
89
- "@clerk/shared": "4.23.1-snapshot.v20260702192602"
87
+ "@clerk/clerk-js": "^6.24.0",
88
+ "@clerk/react": "^6.11.4",
89
+ "@clerk/shared": "^4.24.0"
90
90
  },
91
91
  "devDependencies": {
92
92
  "@types/node": "^22.19.17",
93
93
  "electron": "^39.2.6",
94
94
  "electron-store": "^8.2.0",
95
- "@clerk/electron-passkeys": "0.0.4-snapshot.v20260702192602"
95
+ "@clerk/electron-passkeys": "0.0.3"
96
96
  },
97
97
  "peerDependencies": {
98
- "@clerk/electron-passkeys": "0.0.4-snapshot.v20260702192602",
98
+ "@clerk/electron-passkeys": "*",
99
99
  "electron": ">=28",
100
100
  "electron-store": "^8.2.0",
101
101
  "react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0",