@clerk/expo 3.4.7-snapshot.v20260618154136 → 3.4.7

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.
Files changed (31) hide show
  1. package/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt +65 -33
  2. package/dist/google-one-tap/ClerkGoogleOneTapSignIn.d.ts +2 -1
  3. package/dist/google-one-tap/ClerkGoogleOneTapSignIn.d.ts.map +1 -1
  4. package/dist/google-one-tap/ClerkGoogleOneTapSignIn.js +2 -1
  5. package/dist/google-one-tap/ClerkGoogleOneTapSignIn.js.map +1 -1
  6. package/dist/google-one-tap/types.d.ts +18 -2
  7. package/dist/google-one-tap/types.d.ts.map +1 -1
  8. package/dist/hooks/useNativeClientEvents.d.ts.map +1 -1
  9. package/dist/hooks/useNativeClientEvents.js +8 -1
  10. package/dist/hooks/useNativeClientEvents.js.map +1 -1
  11. package/dist/provider/ClerkProvider.js +1 -1
  12. package/dist/provider/nativeClientSync.d.ts.map +1 -1
  13. package/dist/provider/nativeClientSync.js +11 -7
  14. package/dist/provider/nativeClientSync.js.map +1 -1
  15. package/dist/specs/NativeClerkModule.android.d.ts +1 -1
  16. package/dist/specs/NativeClerkModule.android.d.ts.map +1 -1
  17. package/dist/specs/NativeClerkModule.android.js.map +1 -1
  18. package/dist/specs/NativeClerkModule.d.ts +1 -1
  19. package/dist/specs/NativeClerkModule.d.ts.map +1 -1
  20. package/dist/specs/NativeClerkModule.js.map +1 -1
  21. package/dist/utils/native-module.d.ts +3 -3
  22. package/dist/utils/native-module.d.ts.map +1 -1
  23. package/dist/utils/native-module.js +1 -1
  24. package/dist/utils/native-module.js.map +1 -1
  25. package/ios/ClerkExpoModule.m +1 -0
  26. package/ios/ClerkExpoModule.swift +9 -2
  27. package/ios/ClerkGoogleSignInModule.swift +1 -4
  28. package/ios/ClerkNativeBridge.swift +26 -32
  29. package/package.json +6 -6
  30. package/src/specs/NativeClerkModule.android.ts +5 -1
  31. package/src/specs/NativeClerkModule.ts +5 -1
@@ -73,8 +73,13 @@ class ClerkExpoModule : Module() {
73
73
  getClientToken(promise)
74
74
  }
75
75
 
76
- AsyncFunction("syncFromJsClientToken") { clientToken: String?, sourceId: String?, promise: Promise ->
77
- syncFromJsClientToken(clientToken, sourceId, promise)
76
+ AsyncFunction("syncFromJsClientToken") { clientToken: String?, sourceId: String?, shouldRefreshClient: Boolean?, promise: Promise ->
77
+ syncFromJsClientToken(
78
+ clientToken,
79
+ sourceId,
80
+ shouldRefreshClient ?: clientToken.isNullOrBlank(),
81
+ promise
82
+ )
78
83
  }
79
84
  }
80
85
 
@@ -169,7 +174,7 @@ class ClerkExpoModule : Module() {
169
174
  // before resolving the configure call.
170
175
  if (!bearerToken.isNullOrEmpty()) {
171
176
  withTimeout(5_000L) {
172
- Clerk.sessionFlow.first { it != null }
177
+ Clerk.clientFlow.first { it != null }
173
178
  }
174
179
  }
175
180
  } catch (e: TimeoutCancellationException) {
@@ -230,10 +235,10 @@ class ClerkExpoModule : Module() {
230
235
 
231
236
  try {
232
237
  withTimeout(5_000L) {
233
- Clerk.sessionFlow.first { it != null }
238
+ Clerk.clientFlow.first { it != null }
234
239
  }
235
240
  } catch (_: TimeoutCancellationException) {
236
- debugLog(TAG, "configure - session did not appear after reconfigure token update")
241
+ debugLog(TAG, "configure - client did not appear after reconfigure token update")
237
242
  }
238
243
  }
239
244
 
@@ -251,13 +256,13 @@ class ClerkExpoModule : Module() {
251
256
  debugLog(TAG, "configure - updateDeviceToken failed: ${result.error}")
252
257
  }
253
258
 
254
- // Wait for session to appear with the new token (up to 5s)
259
+ // Wait for client state to hydrate with the new token (up to 5s).
255
260
  try {
256
261
  withTimeout(5_000L) {
257
- Clerk.sessionFlow.first { it != null }
262
+ Clerk.clientFlow.first { it != null }
258
263
  }
259
264
  } catch (_: TimeoutCancellationException) {
260
- debugLog(TAG, "configure - session did not appear after token update")
265
+ debugLog(TAG, "configure - client did not appear after token update")
261
266
  }
262
267
  }
263
268
 
@@ -285,7 +290,12 @@ class ClerkExpoModule : Module() {
285
290
 
286
291
  // MARK: - syncFromJsClientToken
287
292
 
288
- private fun syncFromJsClientToken(clientToken: String?, sourceId: String?, promise: Promise) {
293
+ private fun syncFromJsClientToken(
294
+ clientToken: String?,
295
+ sourceId: String?,
296
+ shouldRefreshClient: Boolean,
297
+ promise: Promise
298
+ ) {
289
299
  if (!Clerk.isInitialized.value) {
290
300
  promise.resolve(null)
291
301
  return
@@ -295,43 +305,65 @@ class ClerkExpoModule : Module() {
295
305
  try {
296
306
  jsOriginatedClientSyncDepth += 1
297
307
  if (!clientToken.isNullOrBlank()) {
298
- when (val result = Clerk.updateDeviceToken(clientToken)) {
308
+ val currentDeviceToken = try {
309
+ Clerk.getDeviceToken()
310
+ } catch (_: Exception) {
311
+ null
312
+ }
313
+
314
+ if (currentDeviceToken == clientToken) {
315
+ if (!shouldRefreshClient) {
316
+ emitSyncedClientChanged(sourceId)
317
+ promise.resolve(null)
318
+ return@launch
319
+ }
320
+ } else {
321
+ when (val result = Clerk.updateDeviceToken(clientToken)) {
322
+ is ClerkResult.Failure -> {
323
+ promise.reject(
324
+ "E_SYNC_FROM_JS_FAILED",
325
+ result.error?.firstMessage() ?: result.throwable?.message ?: "Client token sync failed",
326
+ null
327
+ )
328
+ return@launch
329
+ }
330
+ is ClerkResult.Success -> {
331
+ try {
332
+ withTimeout(5_000L) {
333
+ Clerk.clientFlow.first { it != null }
334
+ }
335
+ } catch (_: TimeoutCancellationException) {
336
+ debugLog(TAG, "syncFromJsClientToken - client did not appear after token update")
337
+ }
338
+ if (!shouldRefreshClient) {
339
+ emitSyncedClientChanged(sourceId)
340
+ promise.resolve(null)
341
+ return@launch
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+
348
+ if (shouldRefreshClient) {
349
+ when (val result = Clerk.refreshClient()) {
299
350
  is ClerkResult.Failure -> {
300
351
  promise.reject(
301
352
  "E_SYNC_FROM_JS_FAILED",
302
- result.error?.firstMessage() ?: result.throwable?.message ?: "Client token sync failed",
353
+ result.error?.firstMessage() ?: result.throwable?.message ?: "Client refresh failed",
303
354
  null
304
355
  )
305
- return@launch
306
356
  }
307
357
  is ClerkResult.Success -> {
308
- try {
309
- withTimeout(5_000L) {
310
- Clerk.sessionFlow.first { it != null }
311
- }
312
- } catch (_: TimeoutCancellationException) {
313
- debugLog(TAG, "syncFromJsClientToken - session did not appear after token update")
314
- }
315
358
  emitSyncedClientChanged(sourceId)
316
359
  promise.resolve(null)
317
- return@launch
318
360
  }
319
361
  }
362
+ return@launch
320
363
  }
321
364
 
322
- when (val result = Clerk.refreshClient()) {
323
- is ClerkResult.Failure -> {
324
- promise.reject(
325
- "E_SYNC_FROM_JS_FAILED",
326
- result.error?.firstMessage() ?: result.throwable?.message ?: "Client refresh failed",
327
- null
328
- )
329
- }
330
- is ClerkResult.Success -> {
331
- emitSyncedClientChanged(sourceId)
332
- promise.resolve(null)
333
- }
334
- }
365
+ emitSyncedClientChanged(sourceId)
366
+ promise.resolve(null)
335
367
  } catch (e: Exception) {
336
368
  promise.reject("E_SYNC_FROM_JS_FAILED", e.message ?: "Client token sync failed", e)
337
369
  } finally {
@@ -45,7 +45,8 @@ export declare const ClerkGoogleOneTapSignIn: {
45
45
  *
46
46
  * @param params - Sign-in parameters
47
47
  * @param params.nonce - Cryptographic nonce for replay protection
48
- * @param params.filterByAuthorizedAccounts - Only show previously authorized accounts (default: true)
48
+ * @param params.filterByAuthorizedAccounts - Android only. Filter to previously authorized accounts.
49
+ * @param params.hint - iOS only. Hint for Google Sign-In.
49
50
  *
50
51
  * @returns Promise resolving to OneTapResponse
51
52
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ClerkGoogleOneTapSignIn.d.ts","sourceRoot":"","sources":["../../src/google-one-tap/ClerkGoogleOneTapSignIn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,qBAAqB,EACrB,YAAY,EACb,MAAM,SAAS,CAAC;AAYjB;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,iBAAiB,CAE3F;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,sBAAsB,CAE7G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,qBAAqB,CAE7F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAS1F;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;IAClC;;;;;;;OAOG;sBACe,eAAe,GAAG,IAAI;IAIxC;;;;;;;;;;;OAWG;oBACmB,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAgB5D;;;;;;;;;;OAUG;2BAC0B,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAgB1E;;;;;;;;;;OAUG;mCACkC,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAanF;;;;OAIG;eACc,OAAO,CAAC,IAAI,CAAC;CAG/B,CAAC;AAEF,YAAY,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,GACX,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"ClerkGoogleOneTapSignIn.d.ts","sourceRoot":"","sources":["../../src/google-one-tap/ClerkGoogleOneTapSignIn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,qBAAqB,EACrB,YAAY,EACb,MAAM,SAAS,CAAC;AAYjB;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,iBAAiB,CAE3F;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,sBAAsB,CAE7G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,IAAI,qBAAqB,CAE7F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAS1F;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;IAClC;;;;;;;OAOG;sBACe,eAAe,GAAG,IAAI;IAIxC;;;;;;;;;;;;OAYG;oBACmB,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAgB5D;;;;;;;;;;OAUG;2BAC0B,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAgB1E;;;;;;;;;;OAUG;mCACkC,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAanF;;;;OAIG;eACc,OAAO,CAAC,IAAI,CAAC;CAG/B,CAAC;AAEF,YAAY,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,GACX,MAAM,SAAS,CAAC"}
@@ -61,7 +61,8 @@ const ClerkGoogleOneTapSignIn = {
61
61
  *
62
62
  * @param params - Sign-in parameters
63
63
  * @param params.nonce - Cryptographic nonce for replay protection
64
- * @param params.filterByAuthorizedAccounts - Only show previously authorized accounts (default: true)
64
+ * @param params.filterByAuthorizedAccounts - Android only. Filter to previously authorized accounts.
65
+ * @param params.hint - iOS only. Hint for Google Sign-In.
65
66
  *
66
67
  * @returns Promise resolving to OneTapResponse
67
68
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ClerkGoogleOneTapSignIn.js","names":["NativeClerkGoogleSignIn"],"sources":["../../src/google-one-tap/ClerkGoogleOneTapSignIn.ts"],"sourcesContent":["import NativeClerkGoogleSignIn from '../specs/NativeClerkGoogleSignIn';\nimport type {\n CancelledResponse,\n ConfigureParams,\n CreateAccountParams,\n ExplicitSignInParams,\n NoSavedCredentialFound,\n OneTapResponse,\n OneTapSuccessResponse,\n SignInParams,\n} from './types';\n\nfunction getNativeModule(): NonNullable<typeof NativeClerkGoogleSignIn> {\n if (!NativeClerkGoogleSignIn) {\n throw new Error(\n 'ClerkGoogleSignIn native module is not available. ' +\n 'Ensure the @clerk/expo plugin is added to your app.json and you have run a development build.',\n );\n }\n return NativeClerkGoogleSignIn;\n}\n\n/**\n * Check if a response indicates the user cancelled the sign-in flow.\n */\nexport function isCancelledResponse(response: OneTapResponse): response is CancelledResponse {\n return response.type === 'cancelled';\n}\n\n/**\n * Check if a response indicates no saved credential was found.\n */\nexport function isNoSavedCredentialFoundResponse(response: OneTapResponse): response is NoSavedCredentialFound {\n return response.type === 'noSavedCredentialFound';\n}\n\n/**\n * Check if a response is a successful sign-in.\n */\nexport function isSuccessResponse(response: OneTapResponse): response is OneTapSuccessResponse {\n return response.type === 'success';\n}\n\n/**\n * Check if an error has code and message properties (Google Sign-In error).\n */\nexport function isErrorWithCode(error: unknown): error is { code: string; message: string } {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n typeof (error as { code: unknown }).code === 'string' &&\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n );\n}\n\n/**\n * Internal Google One Tap Sign-In module.\n *\n * This module provides native Google Sign-In functionality using Google's\n * Credential Manager API with full nonce support for replay attack protection.\n *\n * @internal This is an internal module. Use the `useSignInWithGoogle` hook instead.\n * @platform Android, iOS\n */\nexport const ClerkGoogleOneTapSignIn = {\n /**\n * Configure Google Sign-In. Must be called before any sign-in methods.\n *\n * @param params - Configuration parameters\n * @param params.webClientId - The web client ID from Google Cloud Console (required)\n * @param params.hostedDomain - Optional domain restriction\n * @param params.autoSelectEnabled - Auto-select for single credential (default: false)\n */\n configure(params: ConfigureParams): void {\n getNativeModule().configure(params as any);\n },\n\n /**\n * Attempt to sign in with saved credentials (One Tap).\n *\n * This method will show the One Tap UI if there are saved credentials,\n * or return a \"noSavedCredentialFound\" response if there are none.\n *\n * @param params - Sign-in parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n * @param params.filterByAuthorizedAccounts - Only show previously authorized accounts (default: true)\n *\n * @returns Promise resolving to OneTapResponse\n */\n async signIn(params?: SignInParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().signIn((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n if (error.code === 'NO_SAVED_CREDENTIAL_FOUND') {\n return { type: 'noSavedCredentialFound', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Create a new account (shows all Google accounts).\n *\n * This method shows the account picker with all available Google accounts,\n * not just previously authorized ones.\n *\n * @param params - Create account parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n *\n * @returns Promise resolving to OneTapResponse\n */\n async createAccount(params?: CreateAccountParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().createAccount((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n if (error.code === 'NO_SAVED_CREDENTIAL_FOUND') {\n return { type: 'noSavedCredentialFound', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Present explicit sign-in UI (Google Sign-In button flow).\n *\n * This shows the full Google Sign-In UI, similar to clicking a\n * \"Sign in with Google\" button.\n *\n * @param params - Explicit sign-in parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n *\n * @returns Promise resolving to OneTapResponse\n */\n async presentExplicitSignIn(params?: ExplicitSignInParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().presentExplicitSignIn((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Sign out and clear credential state.\n *\n * This disables automatic sign-in until the user signs in again.\n */\n async signOut(): Promise<void> {\n await getNativeModule().signOut();\n },\n};\n\nexport type {\n ConfigureParams,\n SignInParams,\n CreateAccountParams,\n ExplicitSignInParams,\n OneTapResponse,\n OneTapSuccessResponse,\n CancelledResponse,\n NoSavedCredentialFound,\n GoogleUser,\n} from './types';\n"],"mappings":";;;;;;AAYA,SAAS,kBAA+D;CACtE,IAAI,CAACA,2CACH,MAAM,IAAI,MACR,iJAEF;CAEF,OAAOA;AACT;;;;AAKA,SAAgB,oBAAoB,UAAyD;CAC3F,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,iCAAiC,UAA8D;CAC7G,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,kBAAkB,UAA6D;CAC7F,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,gBAAgB,OAA4D;CAC1F,OACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA4B,SAAS,YAC7C,aAAa,SACb,OAAQ,MAA+B,YAAY;AAEvD;;;;;;;;;;AAWA,MAAa,0BAA0B;;;;;;;;;CASrC,UAAU,QAA+B;EACvC,gBAAgB,CAAC,CAAC,UAAU,MAAa;CAC3C;;;;;;;;;;;;;CAcA,MAAM,OAAO,QAAgD;EAC3D,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,OAAQ,UAAkB,IAAI;EAChE,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GAAG;IAC1B,IAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;IAEzC,IAAI,MAAM,SAAS,6BACjB,OAAO;KAAE,MAAM;KAA0B,MAAM;IAAK;GAExD;GACA,MAAM;EACR;CACF;;;;;;;;;;;;CAaA,MAAM,cAAc,QAAuD;EACzE,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,cAAe,UAAkB,IAAI;EACvE,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GAAG;IAC1B,IAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;IAEzC,IAAI,MAAM,SAAS,6BACjB,OAAO;KAAE,MAAM;KAA0B,MAAM;IAAK;GAExD;GACA,MAAM;EACR;CACF;;;;;;;;;;;;CAaA,MAAM,sBAAsB,QAAwD;EAClF,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,sBAAuB,UAAkB,IAAI;EAC/E,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GACvB;QAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;GACzC;GAEF,MAAM;EACR;CACF;;;;;;CAOA,MAAM,UAAyB;EAC7B,MAAM,gBAAgB,CAAC,CAAC,QAAQ;CAClC;AACF"}
1
+ {"version":3,"file":"ClerkGoogleOneTapSignIn.js","names":["NativeClerkGoogleSignIn"],"sources":["../../src/google-one-tap/ClerkGoogleOneTapSignIn.ts"],"sourcesContent":["import NativeClerkGoogleSignIn from '../specs/NativeClerkGoogleSignIn';\nimport type {\n CancelledResponse,\n ConfigureParams,\n CreateAccountParams,\n ExplicitSignInParams,\n NoSavedCredentialFound,\n OneTapResponse,\n OneTapSuccessResponse,\n SignInParams,\n} from './types';\n\nfunction getNativeModule(): NonNullable<typeof NativeClerkGoogleSignIn> {\n if (!NativeClerkGoogleSignIn) {\n throw new Error(\n 'ClerkGoogleSignIn native module is not available. ' +\n 'Ensure the @clerk/expo plugin is added to your app.json and you have run a development build.',\n );\n }\n return NativeClerkGoogleSignIn;\n}\n\n/**\n * Check if a response indicates the user cancelled the sign-in flow.\n */\nexport function isCancelledResponse(response: OneTapResponse): response is CancelledResponse {\n return response.type === 'cancelled';\n}\n\n/**\n * Check if a response indicates no saved credential was found.\n */\nexport function isNoSavedCredentialFoundResponse(response: OneTapResponse): response is NoSavedCredentialFound {\n return response.type === 'noSavedCredentialFound';\n}\n\n/**\n * Check if a response is a successful sign-in.\n */\nexport function isSuccessResponse(response: OneTapResponse): response is OneTapSuccessResponse {\n return response.type === 'success';\n}\n\n/**\n * Check if an error has code and message properties (Google Sign-In error).\n */\nexport function isErrorWithCode(error: unknown): error is { code: string; message: string } {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n typeof (error as { code: unknown }).code === 'string' &&\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n );\n}\n\n/**\n * Internal Google One Tap Sign-In module.\n *\n * This module provides native Google Sign-In functionality using Google's\n * Credential Manager API with full nonce support for replay attack protection.\n *\n * @internal This is an internal module. Use the `useSignInWithGoogle` hook instead.\n * @platform Android, iOS\n */\nexport const ClerkGoogleOneTapSignIn = {\n /**\n * Configure Google Sign-In. Must be called before any sign-in methods.\n *\n * @param params - Configuration parameters\n * @param params.webClientId - The web client ID from Google Cloud Console (required)\n * @param params.hostedDomain - Optional domain restriction\n * @param params.autoSelectEnabled - Auto-select for single credential (default: false)\n */\n configure(params: ConfigureParams): void {\n getNativeModule().configure(params as any);\n },\n\n /**\n * Attempt to sign in with saved credentials (One Tap).\n *\n * This method will show the One Tap UI if there are saved credentials,\n * or return a \"noSavedCredentialFound\" response if there are none.\n *\n * @param params - Sign-in parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n * @param params.filterByAuthorizedAccounts - Android only. Filter to previously authorized accounts.\n * @param params.hint - iOS only. Hint for Google Sign-In.\n *\n * @returns Promise resolving to OneTapResponse\n */\n async signIn(params?: SignInParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().signIn((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n if (error.code === 'NO_SAVED_CREDENTIAL_FOUND') {\n return { type: 'noSavedCredentialFound', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Create a new account (shows all Google accounts).\n *\n * This method shows the account picker with all available Google accounts,\n * not just previously authorized ones.\n *\n * @param params - Create account parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n *\n * @returns Promise resolving to OneTapResponse\n */\n async createAccount(params?: CreateAccountParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().createAccount((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n if (error.code === 'NO_SAVED_CREDENTIAL_FOUND') {\n return { type: 'noSavedCredentialFound', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Present explicit sign-in UI (Google Sign-In button flow).\n *\n * This shows the full Google Sign-In UI, similar to clicking a\n * \"Sign in with Google\" button.\n *\n * @param params - Explicit sign-in parameters\n * @param params.nonce - Cryptographic nonce for replay protection\n *\n * @returns Promise resolving to OneTapResponse\n */\n async presentExplicitSignIn(params?: ExplicitSignInParams): Promise<OneTapResponse> {\n try {\n return (await getNativeModule().presentExplicitSignIn((params as any) ?? null)) as unknown as OneTapResponse;\n } catch (error) {\n if (isErrorWithCode(error)) {\n if (error.code === 'SIGN_IN_CANCELLED') {\n return { type: 'cancelled', data: null };\n }\n }\n throw error;\n }\n },\n\n /**\n * Sign out and clear credential state.\n *\n * This disables automatic sign-in until the user signs in again.\n */\n async signOut(): Promise<void> {\n await getNativeModule().signOut();\n },\n};\n\nexport type {\n ConfigureParams,\n SignInParams,\n CreateAccountParams,\n ExplicitSignInParams,\n OneTapResponse,\n OneTapSuccessResponse,\n CancelledResponse,\n NoSavedCredentialFound,\n GoogleUser,\n} from './types';\n"],"mappings":";;;;;;AAYA,SAAS,kBAA+D;CACtE,IAAI,CAACA,2CACH,MAAM,IAAI,MACR,iJAEF;CAEF,OAAOA;AACT;;;;AAKA,SAAgB,oBAAoB,UAAyD;CAC3F,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,iCAAiC,UAA8D;CAC7G,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,kBAAkB,UAA6D;CAC7F,OAAO,SAAS,SAAS;AAC3B;;;;AAKA,SAAgB,gBAAgB,OAA4D;CAC1F,OACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA4B,SAAS,YAC7C,aAAa,SACb,OAAQ,MAA+B,YAAY;AAEvD;;;;;;;;;;AAWA,MAAa,0BAA0B;;;;;;;;;CASrC,UAAU,QAA+B;EACvC,gBAAgB,CAAC,CAAC,UAAU,MAAa;CAC3C;;;;;;;;;;;;;;CAeA,MAAM,OAAO,QAAgD;EAC3D,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,OAAQ,UAAkB,IAAI;EAChE,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GAAG;IAC1B,IAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;IAEzC,IAAI,MAAM,SAAS,6BACjB,OAAO;KAAE,MAAM;KAA0B,MAAM;IAAK;GAExD;GACA,MAAM;EACR;CACF;;;;;;;;;;;;CAaA,MAAM,cAAc,QAAuD;EACzE,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,cAAe,UAAkB,IAAI;EACvE,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GAAG;IAC1B,IAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;IAEzC,IAAI,MAAM,SAAS,6BACjB,OAAO;KAAE,MAAM;KAA0B,MAAM;IAAK;GAExD;GACA,MAAM;EACR;CACF;;;;;;;;;;;;CAaA,MAAM,sBAAsB,QAAwD;EAClF,IAAI;GACF,OAAQ,MAAM,gBAAgB,CAAC,CAAC,sBAAuB,UAAkB,IAAI;EAC/E,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAK,GACvB;QAAI,MAAM,SAAS,qBACjB,OAAO;KAAE,MAAM;KAAa,MAAM;IAAK;GACzC;GAEF,MAAM;EACR;CACF;;;;;;CAOA,MAAM,UAAyB;EAC7B,MAAM,gBAAgB,CAAC,CAAC,QAAQ;CAClC;AACF"}
@@ -36,11 +36,27 @@ export type SignInParams = {
36
36
  */
37
37
  nonce?: string;
38
38
  /**
39
- * Whether to filter credentials to only show accounts that have been
40
- * previously authorized for this app.
39
+ * Android only. Whether to filter credentials to only show accounts that have
40
+ * previously authorized this app.
41
+ *
42
+ * No-op on iOS.
43
+ *
44
+ * @platform Android
41
45
  * @default true
42
46
  */
43
47
  filterByAuthorizedAccounts?: boolean;
48
+ /**
49
+ * iOS only. Hint passed to Google Sign-In, such as a user ID or email
50
+ * address.
51
+ *
52
+ * This may prefill or prioritize an account when possible, but does not
53
+ * restrict the account picker.
54
+ *
55
+ * No-op on Android.
56
+ *
57
+ * @platform iOS
58
+ */
59
+ hint?: string;
44
60
  };
45
61
  /**
46
62
  * Parameters for the createAccount method.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/google-one-tap/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ;;WAEG;QACH,OAAO,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,IAAI,EAAE,UAAU,CAAC;KAClB,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,sBAAsB,CAAC;AAEhG;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAC7B,mBAAmB,GACnB,2BAA2B,GAC3B,gBAAgB,GAChB,sBAAsB,GACtB,wBAAwB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,KAAK;IAC9C,IAAI,EAAE,qBAAqB,CAAC;CAC7B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/google-one-tap/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;;;OAQG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAErC;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ;;WAEG;QACH,OAAO,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,IAAI,EAAE,UAAU,CAAC;KAClB,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,sBAAsB,CAAC;AAEhG;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAC7B,mBAAmB,GACnB,2BAA2B,GAC3B,gBAAgB,GAChB,sBAAsB,GACtB,wBAAwB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,KAAK;IAC9C,IAAI,EAAE,qBAAqB,CAAC;CAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useNativeClientEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useNativeClientEvents.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,2BAA2B;IACnC,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C;AAaD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CA+BnE"}
1
+ {"version":3,"file":"useNativeClientEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useNativeClientEvents.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,2BAA2B;IACnC,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C;AAyBD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CAkCnE"}
@@ -5,6 +5,11 @@ let src_utils_native_module = require("../utils/native-module");
5
5
 
6
6
  //#region src/hooks/useNativeClientEvents.ts
7
7
  const nativeClientChangedEvent = "clerkNativeClientChanged";
8
+ function getNativeClientEventEmitter() {
9
+ if (react_native.Platform.OS === "ios") return react_native.DeviceEventEmitter;
10
+ if (src_utils_native_module.ClerkExpoModule && typeof src_utils_native_module.ClerkExpoModule.addListener === "function") return src_utils_native_module.ClerkExpoModule;
11
+ return null;
12
+ }
8
13
  /**
9
14
  * Listens for native client events that should sync JS client state.
10
15
  */
@@ -14,7 +19,9 @@ function useNativeClientEvents() {
14
19
  if (!src_utils_native_module.isNativeSupported || !src_utils_native_module.ClerkExpoModule) return;
15
20
  let subscription = null;
16
21
  try {
17
- subscription = (react_native.Platform.OS === "ios" ? react_native.DeviceEventEmitter : src_utils_native_module.ClerkExpoModule).addListener(nativeClientChangedEvent, (snapshot) => {
22
+ const eventEmitter = getNativeClientEventEmitter();
23
+ if (!eventEmitter) return;
24
+ subscription = eventEmitter.addListener(nativeClientChangedEvent, (snapshot) => {
18
25
  setNativeClientEvent({
19
26
  issuedAt: Date.now(),
20
27
  ...snapshot
@@ -1 +1 @@
1
- {"version":3,"file":"useNativeClientEvents.js","names":["isNativeSupported","ClerkExpo","Platform","DeviceEventEmitter"],"sources":["../../src/hooks/useNativeClientEvents.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { DeviceEventEmitter, Platform } from 'react-native';\n\nimport { ClerkExpoModule as ClerkExpo, isNativeSupported } from '../utils/native-module';\n\nconst nativeClientChangedEvent = 'clerkNativeClientChanged';\n\nexport interface NativeClientSnapshot {\n clientToken?: string | null;\n sourceId?: string | null;\n}\n\n/**\n * Local marker for a native client event.\n */\nexport interface NativeClientEvent extends NativeClientSnapshot {\n issuedAt: number;\n}\n\ninterface UseNativeClientEventsReturn {\n nativeClientEvent: NativeClientEvent | null;\n}\n\ntype RefreshClientEventSubscription = {\n remove: () => void;\n};\n\ntype RefreshClientEventEmitter = {\n addListener: (\n eventName: typeof nativeClientChangedEvent,\n listener: (snapshot?: NativeClientSnapshot) => void,\n ) => RefreshClientEventSubscription;\n};\n\n/**\n * Listens for native client events that should sync JS client state.\n */\nexport function useNativeClientEvents(): UseNativeClientEventsReturn {\n const [nativeClientEvent, setNativeClientEvent] = useState<NativeClientEvent | null>(null);\n\n useEffect(() => {\n if (!isNativeSupported || !ClerkExpo) {\n return;\n }\n\n let subscription: { remove: () => void } | null = null;\n\n try {\n const eventEmitter: RefreshClientEventEmitter =\n Platform.OS === 'ios' ? DeviceEventEmitter : (ClerkExpo as RefreshClientEventEmitter);\n\n subscription = eventEmitter.addListener(nativeClientChangedEvent, snapshot => {\n setNativeClientEvent({ issuedAt: Date.now(), ...snapshot });\n });\n } catch (error) {\n if (__DEV__) {\n console.error('[useNativeClientEvents] Failed to set up event listener:', error);\n }\n }\n\n return () => {\n subscription?.remove();\n };\n }, []);\n\n return {\n nativeClientEvent,\n };\n}\n"],"mappings":";;;;;;AAKA,MAAM,2BAA2B;;;;AAgCjC,SAAgB,wBAAqD;CACnE,MAAM,CAAC,mBAAmB,4CAA2D,IAAI;CAEzF,2BAAgB;EACd,IAAI,CAACA,6CAAqB,CAACC,yCACzB;EAGF,IAAI,eAA8C;EAElD,IAAI;GAIF,gBAFEC,sBAAS,OAAO,QAAQC,kCAAsBF,wCAErB,CAAC,YAAY,2BAA0B,aAAY;IAC5E,qBAAqB;KAAE,UAAU,KAAK,IAAI;KAAG,GAAG;IAAS,CAAC;GAC5D,CAAC;EACH,SAAS,OAAO,CAIhB;EAEA,aAAa;GACX,cAAc,OAAO;EACvB;CACF,GAAG,CAAC,CAAC;CAEL,OAAO,EACL,kBACF;AACF"}
1
+ {"version":3,"file":"useNativeClientEvents.js","names":["Platform","DeviceEventEmitter","ClerkExpo","isNativeSupported"],"sources":["../../src/hooks/useNativeClientEvents.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { DeviceEventEmitter, Platform } from 'react-native';\n\nimport { ClerkExpoModule as ClerkExpo, isNativeSupported } from '../utils/native-module';\n\nconst nativeClientChangedEvent = 'clerkNativeClientChanged';\n\nexport interface NativeClientSnapshot {\n clientToken?: string | null;\n sourceId?: string | null;\n}\n\n/**\n * Local marker for a native client event.\n */\nexport interface NativeClientEvent extends NativeClientSnapshot {\n issuedAt: number;\n}\n\ninterface UseNativeClientEventsReturn {\n nativeClientEvent: NativeClientEvent | null;\n}\n\ntype RefreshClientEventSubscription = {\n remove: () => void;\n};\n\ntype RefreshClientEventEmitter = {\n addListener: (\n eventName: typeof nativeClientChangedEvent,\n listener: (snapshot?: NativeClientSnapshot) => void,\n ) => RefreshClientEventSubscription;\n};\n\nfunction getNativeClientEventEmitter(): RefreshClientEventEmitter | null {\n if (Platform.OS === 'ios') {\n return DeviceEventEmitter;\n }\n\n if (ClerkExpo && typeof ClerkExpo.addListener === 'function') {\n return ClerkExpo as RefreshClientEventEmitter;\n }\n\n return null;\n}\n\n/**\n * Listens for native client events that should sync JS client state.\n */\nexport function useNativeClientEvents(): UseNativeClientEventsReturn {\n const [nativeClientEvent, setNativeClientEvent] = useState<NativeClientEvent | null>(null);\n\n useEffect(() => {\n if (!isNativeSupported || !ClerkExpo) {\n return;\n }\n\n let subscription: { remove: () => void } | null = null;\n\n try {\n const eventEmitter = getNativeClientEventEmitter();\n\n if (!eventEmitter) {\n return;\n }\n\n subscription = eventEmitter.addListener(nativeClientChangedEvent, snapshot => {\n setNativeClientEvent({ issuedAt: Date.now(), ...snapshot });\n });\n } catch (error) {\n if (__DEV__) {\n console.error('[useNativeClientEvents] Failed to set up event listener:', error);\n }\n }\n\n return () => {\n subscription?.remove();\n };\n }, []);\n\n return {\n nativeClientEvent,\n };\n}\n"],"mappings":";;;;;;AAKA,MAAM,2BAA2B;AA6BjC,SAAS,8BAAgE;CACvE,IAAIA,sBAAS,OAAO,OAClB,OAAOC;CAGT,IAAIC,2CAAa,OAAOA,wCAAU,gBAAgB,YAChD,OAAOA;CAGT,OAAO;AACT;;;;AAKA,SAAgB,wBAAqD;CACnE,MAAM,CAAC,mBAAmB,4CAA2D,IAAI;CAEzF,2BAAgB;EACd,IAAI,CAACC,6CAAqB,CAACD,yCACzB;EAGF,IAAI,eAA8C;EAElD,IAAI;GACF,MAAM,eAAe,4BAA4B;GAEjD,IAAI,CAAC,cACH;GAGF,eAAe,aAAa,YAAY,2BAA0B,aAAY;IAC5E,qBAAqB;KAAE,UAAU,KAAK,IAAI;KAAG,GAAG;IAAS,CAAC;GAC5D,CAAC;EACH,SAAS,OAAO,CAIhB;EAEA,aAAa;GACX,cAAc,OAAO;EACvB;CACF,GAAG,CAAC,CAAC;CAEL,OAAO,EACL,kBACF;AACF"}
@@ -11,7 +11,7 @@ let src_provider_nativeClientSync = require("./nativeClientSync");
11
11
  //#region src/provider/ClerkProvider.tsx
12
12
  const SDK_METADATA = {
13
13
  name: "@clerk/expo",
14
- version: "3.4.7-snapshot.v20260618154136"
14
+ version: "3.4.7"
15
15
  };
16
16
  function ClerkProvider(props) {
17
17
  const { children, tokenCache, publishableKey, proxyUrl, domain, __experimental_passkeys, experimental, __experimental_resourceCache, ...rest } = props;
@@ -1 +1 @@
1
- {"version":3,"file":"nativeClientSync.d.ts","sourceRoot":"","sources":["../../src/provider/nativeClientSync.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nativeClientSync.d.ts","sourceRoot":"","sources":["../../src/provider/nativeClientSync.tsx"],"names":[],"mappings":"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"}
@@ -159,8 +159,10 @@ async function runWithSuppressedJsClientChanges(suppressJsClientChangedRef, task
159
159
  }
160
160
  function mergePendingNativeRefreshOptions(current, next) {
161
161
  if (!current) return next;
162
- if ("clientToken" in next) return { clientToken: next.clientToken ?? null };
163
- return current;
162
+ const merged = { shouldRefreshClient: current.shouldRefreshClient || next.shouldRefreshClient };
163
+ if ("clientToken" in current) merged.clientToken = current.clientToken ?? null;
164
+ if ("clientToken" in next) merged.clientToken = next.clientToken ?? null;
165
+ return merged;
164
166
  }
165
167
  async function getCachedClientToken(tokenCache) {
166
168
  if (!tokenCache) return null;
@@ -243,7 +245,6 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
243
245
  }, [clerkInstance, suppressJsClientChangedRef]);
244
246
  const queueNativeRefreshFromJs = (0, react.useCallback)((options) => {
245
247
  if (isRefreshingNativeFromJsRef.current) {
246
- if (!("clientToken" in options)) return;
247
248
  pendingNativeRefreshRef.current = mergePendingNativeRefreshOptions(pendingNativeRefreshRef.current, options);
248
249
  nativeRefreshGenerationRef.current += 1;
249
250
  return;
@@ -257,7 +258,7 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
257
258
  const bearerToken = "clientToken" in options ? options.clientToken ?? null : null;
258
259
  if (generation !== nativeRefreshGenerationRef.current) return;
259
260
  const sourceId = `${nativeClientSyncSourceIdPrefix}-${generation}`;
260
- await ClerkExpo.syncFromJsClientToken(bearerToken, sourceId);
261
+ await ClerkExpo.syncFromJsClientToken(bearerToken, sourceId, options.shouldRefreshClient);
261
262
  };
262
263
  let latestRunGeneration = initialGeneration;
263
264
  (async () => {
@@ -269,7 +270,7 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
269
270
  try {
270
271
  await refreshNativeFromJsClient(pendingOptions, generation);
271
272
  } catch (error) {}
272
- pendingOptions = pendingNativeRefreshRef.current ?? {};
273
+ pendingOptions = pendingNativeRefreshRef.current ?? { shouldRefreshClient: false };
273
274
  if (pendingNativeRefreshRef.current !== null) {
274
275
  generation = nativeRefreshGenerationRef.current + 1;
275
276
  nativeRefreshGenerationRef.current = generation;
@@ -281,7 +282,10 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
281
282
  }, []);
282
283
  (0, react.useEffect)(() => {
283
284
  const listener = (clientToken) => {
284
- queueNativeRefreshFromJs({ clientToken });
285
+ queueNativeRefreshFromJs({
286
+ clientToken,
287
+ shouldRefreshClient: clientToken === null
288
+ });
285
289
  };
286
290
  const tokenCacheListeners = tokenCacheListenersRef.current;
287
291
  tokenCacheListeners.add(listener);
@@ -334,7 +338,7 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
334
338
  if (!clerkInstance || typeof clerkInstance.addListener !== "function") return;
335
339
  const unsubscribe = clerkInstance.addListener(() => {
336
340
  if (suppressJsClientChangedRef.current > 0) return;
337
- queueNativeRefreshFromJs({});
341
+ queueNativeRefreshFromJs({ shouldRefreshClient: true });
338
342
  }, { skipInitialEmit: true });
339
343
  return () => {
340
344
  unsubscribe();
@@ -1 +1 @@
1
- {"version":3,"file":"nativeClientSync.js","names":["Platform","MemoryTokenCache","CLERK_CLIENT_JWT_KEY","NativeClerkModule"],"sources":["../../src/provider/nativeClientSync.tsx"],"sourcesContent":["import type { ClientResource, SignedInSessionResource } from '@clerk/shared/types';\nimport { type MutableRefObject, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { Platform } from 'react-native';\n\nimport { MemoryTokenCache } from '../cache';\nimport type { TokenCache } from '../cache/types';\nimport { CLERK_CLIENT_JWT_KEY } from '../constants';\nimport {\n type NativeClientEvent,\n type NativeClientSnapshot,\n useNativeClientEvents,\n} from '../hooks/useNativeClientEvents';\nimport { ClerkExpoModule as NativeClerkModule } from '../utils/native-module';\n\nconst tokenCacheReadTimeoutMs = 1_000;\nconst clientTokenPollIntervalMs = 100;\nconst clientTokenAvailabilityTimeoutMs = 3_000;\nconst nativeClientSyncSourceIdPrefix = 'clerk-expo-js-sync';\n\nexport type SyncableClerkInstance = {\n addListener?: (listener: () => void, options?: { skipInitialEmit?: boolean }) => () => void;\n addOnLoaded?: (listener: () => void) => void;\n client?: ClientResource;\n handleUnauthenticated?: (options?: { broadcast?: boolean }) => Promise<unknown>;\n loaded?: boolean;\n session?: SignedInSessionResource | null;\n setActive?: (params: { session: SignedInSessionResource | string | null }) => Promise<void>;\n updateClient?: (client: ClientResource, options?: { __internal_dangerouslySkipEmit?: boolean }) => void;\n __internal_reloadInitialResources?: () => void | Promise<void>;\n};\n\ntype RefreshableClientResource = ClientResource & {\n fetch?: (options?: { fetchMaxTries?: number }) => Promise<ClientResource>;\n};\n\ntype NativeRefreshFromJsOptions = {\n clientToken?: string | null;\n};\n\nexport type NativeRefreshFromJsController = {\n cancel: () => void;\n};\n\nexport type ClientTokenCacheListener = (clientToken: string | null) => void;\n\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function useSyncableTokenCache({\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n}: {\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;\n}): TokenCache | undefined {\n return useMemo(() => {\n const effectiveTokenCache =\n tokenCache ?? (Platform.OS === 'ios' || Platform.OS === 'android' ? MemoryTokenCache : undefined);\n if (!effectiveTokenCache) {\n return undefined;\n }\n\n const notifyClientTokenListeners = (clientToken: string | null) => {\n if (suppressTokenCacheNotificationsRef.current) {\n return;\n }\n\n for (const listener of tokenCacheListenersRef.current) {\n listener(clientToken);\n }\n };\n\n return {\n getToken: key => effectiveTokenCache.getToken(key),\n saveToken: async (key, token) => {\n await effectiveTokenCache.saveToken(key, token);\n if (key === CLERK_CLIENT_JWT_KEY) {\n notifyClientTokenListeners(token);\n }\n },\n clearToken: async key => {\n await effectiveTokenCache.clearToken?.(key);\n if (key === CLERK_CLIENT_JWT_KEY) {\n notifyClientTokenListeners(null);\n }\n },\n };\n }, [suppressTokenCacheNotificationsRef, tokenCache, tokenCacheListenersRef]);\n}\n\nfunction getNativeClientTokenFromSnapshot(\n snapshot: NativeClientSnapshot | null | undefined,\n): string | null | undefined {\n if (!snapshot || !('clientToken' in snapshot)) {\n return undefined;\n }\n\n return snapshot.clientToken ?? null;\n}\n\nasync function readNativeClientToken({ waitForToken }: { waitForToken: boolean }): Promise<string | null> {\n const ClerkExpo = NativeClerkModule;\n if (!ClerkExpo?.getClientToken) {\n return null;\n }\n\n const startedAt = Date.now();\n let remainingMs = clientTokenAvailabilityTimeoutMs;\n\n do {\n const nativeClientToken = await ClerkExpo.getClientToken();\n if (nativeClientToken) {\n return nativeClientToken;\n }\n\n if (!waitForToken) {\n return null;\n }\n\n remainingMs = clientTokenAvailabilityTimeoutMs - (Date.now() - startedAt);\n if (remainingMs <= 0) {\n return null;\n }\n\n await delay(Math.min(clientTokenPollIntervalMs, remainingMs));\n } while (remainingMs > 0);\n\n return null;\n}\n\nasync function syncClientTokenToCache(tokenCache: TokenCache | undefined, clientToken: string | null): Promise<void> {\n if (clientToken) {\n await tokenCache?.saveToken(CLERK_CLIENT_JWT_KEY, clientToken);\n return;\n }\n\n await tokenCache?.clearToken?.(CLERK_CLIENT_JWT_KEY);\n}\n\nasync function syncClientTokenToCacheWithoutNotifying({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clientToken: string | null;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n suppressTokenCacheNotificationsRef.current = true;\n try {\n await syncClientTokenToCache(tokenCache, clientToken);\n } finally {\n suppressTokenCacheNotificationsRef.current = false;\n }\n}\n\nasync function syncNativeTokenToCache({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clientToken: string | null;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n if (suppressTokenCacheNotificationsRef) {\n await syncClientTokenToCacheWithoutNotifying({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n return;\n }\n\n await syncClientTokenToCache(tokenCache, clientToken);\n}\n\nfunction getDefaultSignedInSession(client: ClientResource | null | undefined): SignedInSessionResource | null {\n if (!client) {\n return null;\n }\n\n if (client.lastActiveSessionId) {\n const lastActiveSession = client.signedInSessions.find(session => session.id === client.lastActiveSessionId);\n if (lastActiveSession) {\n return lastActiveSession;\n }\n }\n\n return client.signedInSessions[0] ?? null;\n}\n\nasync function refreshJsClientWithoutEmitting(clerkInstance: SyncableClerkInstance): Promise<ClientResource | null> {\n const client = clerkInstance.client as RefreshableClientResource | undefined;\n\n if (typeof client?.fetch !== 'function' || typeof clerkInstance.updateClient !== 'function') {\n return null;\n }\n\n const refreshedClient = await client.fetch({ fetchMaxTries: 1 });\n const nextSession = getDefaultSignedInSession(refreshedClient);\n\n clerkInstance.updateClient(refreshedClient, {\n __internal_dangerouslySkipEmit: Boolean(nextSession),\n });\n\n return refreshedClient;\n}\n\nasync function refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeClientToken: string | null;\n reloadInitialResources: boolean;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n await syncNativeTokenToCache({\n clientToken: nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n\n const refreshedClient = await refreshJsClientWithoutEmitting(clerkInstance);\n if (refreshedClient) {\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return true;\n }\n\n if (reloadInitialResources && typeof clerkInstance.__internal_reloadInitialResources === 'function') {\n await clerkInstance.__internal_reloadInitialResources();\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return Boolean(getDefaultSignedInSession(clerkInstance.client));\n }\n\n return false;\n}\n\nasync function reloadJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeClientToken: string;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n await syncNativeTokenToCache({\n clientToken: nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n\n await clerkInstance.__internal_reloadInitialResources?.();\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return Boolean(getDefaultSignedInSession(clerkInstance.client));\n}\n\nasync function recoverJsClientFromNativeToken({\n clerkInstance,\n error,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n error: unknown;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n const nativeClientToken = await readNativeClientToken({ waitForToken: false });\n if (!nativeClientToken) {\n return false;\n }\n\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to refresh JS client with native client token:', error);\n }\n\n try {\n return await reloadJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n } catch (recoveryError) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to recover JS client after unauthenticated state:', recoveryError);\n }\n return false;\n }\n}\n\nasync function reconcileJsActiveSessionFromClient({\n clerkInstance,\n}: {\n clerkInstance: SyncableClerkInstance;\n}): Promise<void> {\n const fallbackSession = getDefaultSignedInSession(clerkInstance.client);\n if (!fallbackSession || typeof clerkInstance.setActive !== 'function') {\n return;\n }\n\n const currentSession = clerkInstance.session;\n const currentSessionStillExists = currentSession\n ? clerkInstance.client?.signedInSessions.some(session => session.id === currentSession.id)\n : false;\n\n if (currentSessionStillExists && currentSession?.id === fallbackSession.id) {\n return;\n }\n\n await clerkInstance.setActive({ session: fallbackSession });\n}\n\nasync function runWithSuppressedJsClientChanges<T>(\n suppressJsClientChangedRef: MutableRefObject<number> | undefined,\n task: () => Promise<T>,\n): Promise<T> {\n if (!suppressJsClientChangedRef) {\n return task();\n }\n\n suppressJsClientChangedRef.current += 1;\n try {\n return await task();\n } finally {\n suppressJsClientChangedRef.current = Math.max(0, suppressJsClientChangedRef.current - 1);\n }\n}\n\nfunction mergePendingNativeRefreshOptions(\n current: NativeRefreshFromJsOptions | null,\n next: NativeRefreshFromJsOptions,\n): NativeRefreshFromJsOptions {\n if (!current) {\n return next;\n }\n\n if ('clientToken' in next) {\n return {\n clientToken: next.clientToken ?? null,\n };\n }\n\n return current;\n}\n\nasync function getCachedClientToken(tokenCache: TokenCache | undefined): Promise<string | null> {\n if (!tokenCache) {\n return null;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n return (\n (await Promise.race([\n tokenCache.getToken(CLERK_CLIENT_JWT_KEY),\n new Promise<null>(resolve => {\n timeoutId = setTimeout(() => resolve(null), tokenCacheReadTimeoutMs);\n }),\n ])) ?? null\n );\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function syncNativeClientToJs({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n nativeClientEvent,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeRefreshFromJsControllerRef?: MutableRefObject<NativeRefreshFromJsController | null>;\n nativeClientEvent?: NativeClientEvent | null;\n suppressJsClientChangedRef?: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n const nativeClientTokenFromEvent = getNativeClientTokenFromSnapshot(nativeClientEvent);\n const nativeClientToken =\n nativeClientTokenFromEvent !== undefined\n ? nativeClientTokenFromEvent\n : await readNativeClientToken({\n waitForToken: !nativeClientEvent,\n });\n\n if (!nativeClientToken && !nativeClientEvent) {\n return;\n }\n\n await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n nativeRefreshFromJsControllerRef?.current?.cancel();\n\n await refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources: true,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n });\n}\n\n/**\n * Syncs JS SDK client changes to the native Clerk SDK so native components\n * (UserButton, UserProfileView) stay in sync after JS-owned resource changes.\n *\n * Must be rendered inside `ClerkReactProvider` so the Clerk instance has loaded\n * resources to emit.\n */\nexport function NativeClientSync({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n}: {\n clerkInstance: SyncableClerkInstance | null | undefined;\n nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;\n suppressJsClientChangedRef: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;\n}): null {\n const isRefreshingNativeFromJsRef = useRef(false);\n const pendingNativeRefreshRef = useRef<NativeRefreshFromJsOptions | null>(null);\n const nativeRefreshGenerationRef = useRef(0);\n\n const cancelNativeRefreshFromJs = useCallback(() => {\n pendingNativeRefreshRef.current = null;\n nativeRefreshGenerationRef.current += 1;\n isRefreshingNativeFromJsRef.current = false;\n }, []);\n\n useEffect(() => {\n nativeRefreshFromJsControllerRef.current = {\n cancel: cancelNativeRefreshFromJs,\n };\n\n return () => {\n if (nativeRefreshFromJsControllerRef.current?.cancel === cancelNativeRefreshFromJs) {\n nativeRefreshFromJsControllerRef.current = null;\n }\n };\n }, [cancelNativeRefreshFromJs, nativeRefreshFromJsControllerRef]);\n\n useEffect(() => {\n if (\n !clerkInstance ||\n typeof clerkInstance.updateClient !== 'function' ||\n typeof clerkInstance.setActive !== 'function'\n ) {\n return;\n }\n\n const originalUpdateClient = clerkInstance.updateClient.bind(clerkInstance);\n let isReconcilingRemovedActiveSession = false;\n\n const updateClient: SyncableClerkInstance['updateClient'] = (newClient, options) => {\n const currentSessionId = clerkInstance.session?.id;\n const fallbackSession = getDefaultSignedInSession(newClient);\n const currentSessionWasRemoved = currentSessionId\n ? !newClient.signedInSessions.some(session => session.id === currentSessionId)\n : false;\n const alreadyReconcilingRemovedActiveSession = isReconcilingRemovedActiveSession;\n\n if ((currentSessionWasRemoved || alreadyReconcilingRemovedActiveSession) && fallbackSession) {\n // Clerk JS briefly emits signed-out when the active session disappears,\n // even if the refreshed client still has another signed-in session.\n // Keep that transient state internal so native session switching does\n // not dismiss mounted native UI before setActive settles on JS.\n isReconcilingRemovedActiveSession = true;\n originalUpdateClient(newClient, { __internal_dangerouslySkipEmit: true });\n\n if (alreadyReconcilingRemovedActiveSession) {\n return;\n }\n\n void runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n try {\n await clerkInstance.setActive?.({ session: fallbackSession });\n } catch (error) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to set remaining active JS session:', error);\n }\n originalUpdateClient(newClient, options);\n } finally {\n isReconcilingRemovedActiveSession = false;\n }\n });\n return;\n }\n\n originalUpdateClient(newClient, options);\n };\n\n clerkInstance.updateClient = updateClient;\n\n return () => {\n if (clerkInstance.updateClient === updateClient) {\n clerkInstance.updateClient = originalUpdateClient;\n }\n };\n }, [clerkInstance, suppressJsClientChangedRef]);\n\n const queueNativeRefreshFromJs = useCallback((options: NativeRefreshFromJsOptions): void => {\n if (isRefreshingNativeFromJsRef.current) {\n if (!('clientToken' in options)) {\n return;\n }\n\n pendingNativeRefreshRef.current = mergePendingNativeRefreshOptions(pendingNativeRefreshRef.current, options);\n nativeRefreshGenerationRef.current += 1;\n return;\n }\n\n const initialGeneration = nativeRefreshGenerationRef.current + 1;\n nativeRefreshGenerationRef.current = initialGeneration;\n isRefreshingNativeFromJsRef.current = true;\n\n const refreshNativeFromJsClient = async (\n options: NativeRefreshFromJsOptions,\n generation: number,\n ): Promise<void> => {\n const ClerkExpo = NativeClerkModule;\n if (!ClerkExpo || generation !== nativeRefreshGenerationRef.current) {\n return;\n }\n\n const bearerToken = 'clientToken' in options ? (options.clientToken ?? null) : null;\n if (generation !== nativeRefreshGenerationRef.current) {\n return;\n }\n\n const sourceId = `${nativeClientSyncSourceIdPrefix}-${generation}`;\n await ClerkExpo.syncFromJsClientToken(bearerToken, sourceId);\n };\n\n let latestRunGeneration = initialGeneration;\n\n void (async () => {\n let pendingOptions = options;\n let generation = initialGeneration;\n do {\n latestRunGeneration = generation;\n pendingNativeRefreshRef.current = null;\n try {\n await refreshNativeFromJsClient(pendingOptions, generation);\n } catch (error: unknown) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to refresh native client from JS client change:', error);\n }\n }\n pendingOptions = pendingNativeRefreshRef.current ?? {};\n if (pendingNativeRefreshRef.current !== null) {\n generation = nativeRefreshGenerationRef.current + 1;\n nativeRefreshGenerationRef.current = generation;\n }\n } while (pendingNativeRefreshRef.current !== null);\n })().finally(() => {\n if (latestRunGeneration === nativeRefreshGenerationRef.current || pendingNativeRefreshRef.current === null) {\n isRefreshingNativeFromJsRef.current = false;\n }\n });\n }, []);\n\n useEffect(() => {\n const listener: ClientTokenCacheListener = clientToken => {\n queueNativeRefreshFromJs({ clientToken });\n };\n const tokenCacheListeners = tokenCacheListenersRef.current;\n\n tokenCacheListeners.add(listener);\n return () => {\n tokenCacheListeners.delete(listener);\n };\n }, [queueNativeRefreshFromJs, tokenCacheListenersRef]);\n\n useEffect(() => {\n if (!clerkInstance || typeof clerkInstance.handleUnauthenticated !== 'function') {\n return;\n }\n\n const originalHandleUnauthenticated = clerkInstance.handleUnauthenticated.bind(clerkInstance);\n let isHandlingUnauthenticated = false;\n\n const handleUnauthenticated: SyncableClerkInstance['handleUnauthenticated'] = async options => {\n if (isHandlingUnauthenticated) {\n return;\n }\n\n isHandlingUnauthenticated = true;\n try {\n return await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n try {\n const nativeClientToken = await readNativeClientToken({ waitForToken: false });\n // Native may have already moved the server-side client to a new\n // active session. Refresh JS before allowing Clerk JS' stale-session\n // 401 path to collapse the whole client to signed out.\n const didRecover = await refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources: false,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n if (didRecover) {\n return;\n }\n } catch (error) {\n const didRecover = await recoverJsClientFromNativeToken({\n clerkInstance,\n error,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n if (didRecover) {\n return;\n }\n }\n\n return originalHandleUnauthenticated(options);\n });\n } finally {\n isHandlingUnauthenticated = false;\n }\n };\n\n clerkInstance.handleUnauthenticated = handleUnauthenticated;\n\n return () => {\n if (clerkInstance.handleUnauthenticated === handleUnauthenticated) {\n clerkInstance.handleUnauthenticated = originalHandleUnauthenticated;\n }\n };\n }, [clerkInstance, suppressJsClientChangedRef, suppressTokenCacheNotificationsRef, tokenCache]);\n\n useEffect(() => {\n if (!clerkInstance || typeof clerkInstance.addListener !== 'function') {\n return;\n }\n\n const unsubscribe = clerkInstance.addListener(\n () => {\n if (suppressJsClientChangedRef.current > 0) {\n return;\n }\n\n queueNativeRefreshFromJs({});\n },\n { skipInitialEmit: true },\n );\n\n return () => {\n unsubscribe();\n };\n }, [clerkInstance, queueNativeRefreshFromJs, suppressJsClientChangedRef]);\n\n return null;\n}\n\nexport function useNativeClientBootstrap({\n publishableKey,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n clerkInstance,\n}: {\n publishableKey: string;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n clerkInstance: SyncableClerkInstance | null | undefined;\n}) {\n const initStartedRef = useRef(false);\n const nativeClientSyncedRef = useRef(false);\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n initStartedRef.current = false;\n nativeClientSyncedRef.current = false;\n }, [publishableKey]);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n if ((Platform.OS === 'ios' || Platform.OS === 'android') && publishableKey && !initStartedRef.current) {\n initStartedRef.current = true;\n\n const configureNativeClerk = async () => {\n try {\n const ClerkExpo = NativeClerkModule;\n\n if (ClerkExpo?.configure) {\n await ClerkExpo.configure(publishableKey, null);\n\n if (!isMountedRef.current) {\n return;\n }\n\n let bearerToken: string | null = null;\n try {\n bearerToken = await getCachedClientToken(tokenCache);\n } catch (e) {\n if (__DEV__) {\n console.warn('[ClerkProvider] Token cache read failed:', e);\n }\n }\n\n if (bearerToken) {\n await ClerkExpo.configure(publishableKey, bearerToken);\n\n if (!isMountedRef.current) {\n return;\n }\n }\n\n if (clerkInstance) {\n const waitForLoad = (): Promise<void> => {\n return new Promise(resolve => {\n if (clerkInstance.loaded) {\n resolve();\n } else if (typeof clerkInstance.addOnLoaded === 'function') {\n clerkInstance.addOnLoaded(() => resolve());\n } else {\n if (__DEV__) {\n console.warn('[ClerkProvider] Clerk instance has no loaded property or addOnLoaded method');\n }\n resolve();\n }\n });\n };\n\n await waitForLoad();\n\n if (!isMountedRef.current) {\n return;\n }\n\n if (!nativeClientSyncedRef.current) {\n nativeClientSyncedRef.current = true;\n await syncNativeClientToJs({\n clerkInstance,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n }\n }\n }\n } catch (error) {\n const isNativeModuleNotFound =\n error instanceof Error &&\n (error.message.includes('Cannot find native module') ||\n error.message.includes(\"TurboModuleRegistry.getEnforcing(...): 'ClerkExpo'\"));\n if (isNativeModuleNotFound) {\n if (__DEV__) {\n console.debug(\n `[ClerkProvider] Native Clerk module not available. ` +\n `To enable native features, add \"@clerk/expo\" to your app.json plugins array.`,\n );\n }\n } else if (__DEV__) {\n console.error(`[ClerkProvider] Failed to configure Clerk ${Platform.OS}:`, error);\n }\n }\n };\n void configureNativeClerk();\n }\n\n return () => {\n isMountedRef.current = false;\n };\n }, [publishableKey, suppressTokenCacheNotificationsRef, tokenCache, clerkInstance]);\n\n return isMountedRef;\n}\n\nexport function useNativeClientEventSync({\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance | null | undefined;\n isMountedRef: MutableRefObject<boolean>;\n nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;\n suppressJsClientChangedRef: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}) {\n const { nativeClientEvent } = useNativeClientEvents();\n\n useEffect(() => {\n if (!nativeClientEvent || !clerkInstance) {\n return;\n }\n\n if (nativeClientEvent.sourceId?.startsWith(nativeClientSyncSourceIdPrefix)) {\n return;\n }\n\n const syncNativeClientStateToJs = async () => {\n try {\n if (!isMountedRef.current) {\n return;\n }\n await syncNativeClientToJs({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n nativeClientEvent,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n } catch (error) {\n console.error(`[ClerkProvider] Failed to sync native client state:`, error);\n }\n };\n\n void syncNativeClientStateToJs();\n }, [\n nativeClientEvent,\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n ]);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nativeClientSync.js","names":["Platform","MemoryTokenCache","CLERK_CLIENT_JWT_KEY","NativeClerkModule"],"sources":["../../src/provider/nativeClientSync.tsx"],"sourcesContent":["import type { ClientResource, SignedInSessionResource } from '@clerk/shared/types';\nimport { type MutableRefObject, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { Platform } from 'react-native';\n\nimport { MemoryTokenCache } from '../cache';\nimport type { TokenCache } from '../cache/types';\nimport { CLERK_CLIENT_JWT_KEY } from '../constants';\nimport {\n type NativeClientEvent,\n type NativeClientSnapshot,\n useNativeClientEvents,\n} from '../hooks/useNativeClientEvents';\nimport { ClerkExpoModule as NativeClerkModule } from '../utils/native-module';\n\nconst tokenCacheReadTimeoutMs = 1_000;\nconst clientTokenPollIntervalMs = 100;\nconst clientTokenAvailabilityTimeoutMs = 3_000;\nconst nativeClientSyncSourceIdPrefix = 'clerk-expo-js-sync';\n\nexport type SyncableClerkInstance = {\n addListener?: (listener: () => void, options?: { skipInitialEmit?: boolean }) => () => void;\n addOnLoaded?: (listener: () => void) => void;\n client?: ClientResource;\n handleUnauthenticated?: (options?: { broadcast?: boolean }) => Promise<unknown>;\n loaded?: boolean;\n session?: SignedInSessionResource | null;\n setActive?: (params: { session: SignedInSessionResource | string | null }) => Promise<void>;\n updateClient?: (client: ClientResource, options?: { __internal_dangerouslySkipEmit?: boolean }) => void;\n __internal_reloadInitialResources?: () => void | Promise<void>;\n};\n\ntype RefreshableClientResource = ClientResource & {\n fetch?: (options?: { fetchMaxTries?: number }) => Promise<ClientResource>;\n};\n\ntype NativeRefreshFromJsOptions = {\n clientToken?: string | null;\n shouldRefreshClient: boolean;\n};\n\nexport type NativeRefreshFromJsController = {\n cancel: () => void;\n};\n\nexport type ClientTokenCacheListener = (clientToken: string | null) => void;\n\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport function useSyncableTokenCache({\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n}: {\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;\n}): TokenCache | undefined {\n return useMemo(() => {\n const effectiveTokenCache =\n tokenCache ?? (Platform.OS === 'ios' || Platform.OS === 'android' ? MemoryTokenCache : undefined);\n if (!effectiveTokenCache) {\n return undefined;\n }\n\n const notifyClientTokenListeners = (clientToken: string | null) => {\n if (suppressTokenCacheNotificationsRef.current) {\n return;\n }\n\n for (const listener of tokenCacheListenersRef.current) {\n listener(clientToken);\n }\n };\n\n return {\n getToken: key => effectiveTokenCache.getToken(key),\n saveToken: async (key, token) => {\n await effectiveTokenCache.saveToken(key, token);\n if (key === CLERK_CLIENT_JWT_KEY) {\n notifyClientTokenListeners(token);\n }\n },\n clearToken: async key => {\n await effectiveTokenCache.clearToken?.(key);\n if (key === CLERK_CLIENT_JWT_KEY) {\n notifyClientTokenListeners(null);\n }\n },\n };\n }, [suppressTokenCacheNotificationsRef, tokenCache, tokenCacheListenersRef]);\n}\n\nfunction getNativeClientTokenFromSnapshot(\n snapshot: NativeClientSnapshot | null | undefined,\n): string | null | undefined {\n if (!snapshot || !('clientToken' in snapshot)) {\n return undefined;\n }\n\n return snapshot.clientToken ?? null;\n}\n\nasync function readNativeClientToken({ waitForToken }: { waitForToken: boolean }): Promise<string | null> {\n const ClerkExpo = NativeClerkModule;\n if (!ClerkExpo?.getClientToken) {\n return null;\n }\n\n const startedAt = Date.now();\n let remainingMs = clientTokenAvailabilityTimeoutMs;\n\n do {\n const nativeClientToken = await ClerkExpo.getClientToken();\n if (nativeClientToken) {\n return nativeClientToken;\n }\n\n if (!waitForToken) {\n return null;\n }\n\n remainingMs = clientTokenAvailabilityTimeoutMs - (Date.now() - startedAt);\n if (remainingMs <= 0) {\n return null;\n }\n\n await delay(Math.min(clientTokenPollIntervalMs, remainingMs));\n } while (remainingMs > 0);\n\n return null;\n}\n\nasync function syncClientTokenToCache(tokenCache: TokenCache | undefined, clientToken: string | null): Promise<void> {\n if (clientToken) {\n await tokenCache?.saveToken(CLERK_CLIENT_JWT_KEY, clientToken);\n return;\n }\n\n await tokenCache?.clearToken?.(CLERK_CLIENT_JWT_KEY);\n}\n\nasync function syncClientTokenToCacheWithoutNotifying({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clientToken: string | null;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n suppressTokenCacheNotificationsRef.current = true;\n try {\n await syncClientTokenToCache(tokenCache, clientToken);\n } finally {\n suppressTokenCacheNotificationsRef.current = false;\n }\n}\n\nasync function syncNativeTokenToCache({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clientToken: string | null;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n if (suppressTokenCacheNotificationsRef) {\n await syncClientTokenToCacheWithoutNotifying({\n clientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n return;\n }\n\n await syncClientTokenToCache(tokenCache, clientToken);\n}\n\nfunction getDefaultSignedInSession(client: ClientResource | null | undefined): SignedInSessionResource | null {\n if (!client) {\n return null;\n }\n\n if (client.lastActiveSessionId) {\n const lastActiveSession = client.signedInSessions.find(session => session.id === client.lastActiveSessionId);\n if (lastActiveSession) {\n return lastActiveSession;\n }\n }\n\n return client.signedInSessions[0] ?? null;\n}\n\nasync function refreshJsClientWithoutEmitting(clerkInstance: SyncableClerkInstance): Promise<ClientResource | null> {\n const client = clerkInstance.client as RefreshableClientResource | undefined;\n\n if (typeof client?.fetch !== 'function' || typeof clerkInstance.updateClient !== 'function') {\n return null;\n }\n\n const refreshedClient = await client.fetch({ fetchMaxTries: 1 });\n const nextSession = getDefaultSignedInSession(refreshedClient);\n\n clerkInstance.updateClient(refreshedClient, {\n __internal_dangerouslySkipEmit: Boolean(nextSession),\n });\n\n return refreshedClient;\n}\n\nasync function refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeClientToken: string | null;\n reloadInitialResources: boolean;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n await syncNativeTokenToCache({\n clientToken: nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n\n const refreshedClient = await refreshJsClientWithoutEmitting(clerkInstance);\n if (refreshedClient) {\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return true;\n }\n\n if (reloadInitialResources && typeof clerkInstance.__internal_reloadInitialResources === 'function') {\n await clerkInstance.__internal_reloadInitialResources();\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return Boolean(getDefaultSignedInSession(clerkInstance.client));\n }\n\n return false;\n}\n\nasync function reloadJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeClientToken: string;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n await syncNativeTokenToCache({\n clientToken: nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n\n await clerkInstance.__internal_reloadInitialResources?.();\n await reconcileJsActiveSessionFromClient({\n clerkInstance,\n });\n return Boolean(getDefaultSignedInSession(clerkInstance.client));\n}\n\nasync function recoverJsClientFromNativeToken({\n clerkInstance,\n error,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n error: unknown;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n const nativeClientToken = await readNativeClientToken({ waitForToken: false });\n if (!nativeClientToken) {\n return false;\n }\n\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to refresh JS client with native client token:', error);\n }\n\n try {\n return await reloadJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n } catch (recoveryError) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to recover JS client after unauthenticated state:', recoveryError);\n }\n return false;\n }\n}\n\nasync function reconcileJsActiveSessionFromClient({\n clerkInstance,\n}: {\n clerkInstance: SyncableClerkInstance;\n}): Promise<void> {\n const fallbackSession = getDefaultSignedInSession(clerkInstance.client);\n if (!fallbackSession || typeof clerkInstance.setActive !== 'function') {\n return;\n }\n\n const currentSession = clerkInstance.session;\n const currentSessionStillExists = currentSession\n ? clerkInstance.client?.signedInSessions.some(session => session.id === currentSession.id)\n : false;\n\n if (currentSessionStillExists && currentSession?.id === fallbackSession.id) {\n return;\n }\n\n await clerkInstance.setActive({ session: fallbackSession });\n}\n\nasync function runWithSuppressedJsClientChanges<T>(\n suppressJsClientChangedRef: MutableRefObject<number> | undefined,\n task: () => Promise<T>,\n): Promise<T> {\n if (!suppressJsClientChangedRef) {\n return task();\n }\n\n suppressJsClientChangedRef.current += 1;\n try {\n return await task();\n } finally {\n suppressJsClientChangedRef.current = Math.max(0, suppressJsClientChangedRef.current - 1);\n }\n}\n\nfunction mergePendingNativeRefreshOptions(\n current: NativeRefreshFromJsOptions | null,\n next: NativeRefreshFromJsOptions,\n): NativeRefreshFromJsOptions {\n if (!current) {\n return next;\n }\n\n const merged: NativeRefreshFromJsOptions = {\n shouldRefreshClient: current.shouldRefreshClient || next.shouldRefreshClient,\n };\n\n if ('clientToken' in current) {\n merged.clientToken = current.clientToken ?? null;\n }\n\n if ('clientToken' in next) {\n merged.clientToken = next.clientToken ?? null;\n }\n\n return merged;\n}\n\nasync function getCachedClientToken(tokenCache: TokenCache | undefined): Promise<string | null> {\n if (!tokenCache) {\n return null;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n return (\n (await Promise.race([\n tokenCache.getToken(CLERK_CLIENT_JWT_KEY),\n new Promise<null>(resolve => {\n timeoutId = setTimeout(() => resolve(null), tokenCacheReadTimeoutMs);\n }),\n ])) ?? null\n );\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function syncNativeClientToJs({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n nativeClientEvent,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeRefreshFromJsControllerRef?: MutableRefObject<NativeRefreshFromJsController | null>;\n nativeClientEvent?: NativeClientEvent | null;\n suppressJsClientChangedRef?: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef?: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n const nativeClientTokenFromEvent = getNativeClientTokenFromSnapshot(nativeClientEvent);\n const nativeClientToken =\n nativeClientTokenFromEvent !== undefined\n ? nativeClientTokenFromEvent\n : await readNativeClientToken({\n waitForToken: !nativeClientEvent,\n });\n\n if (!nativeClientToken && !nativeClientEvent) {\n return;\n }\n\n await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n nativeRefreshFromJsControllerRef?.current?.cancel();\n\n await refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources: true,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n });\n}\n\n/**\n * Syncs JS SDK client changes to the native Clerk SDK so native components\n * (UserButton, UserProfileView) stay in sync after JS-owned resource changes.\n *\n * Must be rendered inside `ClerkReactProvider` so the Clerk instance has loaded\n * resources to emit.\n */\nexport function NativeClientSync({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n}: {\n clerkInstance: SyncableClerkInstance | null | undefined;\n nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;\n suppressJsClientChangedRef: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;\n}): null {\n const isRefreshingNativeFromJsRef = useRef(false);\n const pendingNativeRefreshRef = useRef<NativeRefreshFromJsOptions | null>(null);\n const nativeRefreshGenerationRef = useRef(0);\n\n const cancelNativeRefreshFromJs = useCallback(() => {\n pendingNativeRefreshRef.current = null;\n nativeRefreshGenerationRef.current += 1;\n isRefreshingNativeFromJsRef.current = false;\n }, []);\n\n useEffect(() => {\n nativeRefreshFromJsControllerRef.current = {\n cancel: cancelNativeRefreshFromJs,\n };\n\n return () => {\n if (nativeRefreshFromJsControllerRef.current?.cancel === cancelNativeRefreshFromJs) {\n nativeRefreshFromJsControllerRef.current = null;\n }\n };\n }, [cancelNativeRefreshFromJs, nativeRefreshFromJsControllerRef]);\n\n useEffect(() => {\n if (\n !clerkInstance ||\n typeof clerkInstance.updateClient !== 'function' ||\n typeof clerkInstance.setActive !== 'function'\n ) {\n return;\n }\n\n const originalUpdateClient = clerkInstance.updateClient.bind(clerkInstance);\n let isReconcilingRemovedActiveSession = false;\n\n const updateClient: SyncableClerkInstance['updateClient'] = (newClient, options) => {\n const currentSessionId = clerkInstance.session?.id;\n const fallbackSession = getDefaultSignedInSession(newClient);\n const currentSessionWasRemoved = currentSessionId\n ? !newClient.signedInSessions.some(session => session.id === currentSessionId)\n : false;\n const alreadyReconcilingRemovedActiveSession = isReconcilingRemovedActiveSession;\n\n if ((currentSessionWasRemoved || alreadyReconcilingRemovedActiveSession) && fallbackSession) {\n // Clerk JS briefly emits signed-out when the active session disappears,\n // even if the refreshed client still has another signed-in session.\n // Keep that transient state internal so native session switching does\n // not dismiss mounted native UI before setActive settles on JS.\n isReconcilingRemovedActiveSession = true;\n originalUpdateClient(newClient, { __internal_dangerouslySkipEmit: true });\n\n if (alreadyReconcilingRemovedActiveSession) {\n return;\n }\n\n void runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n try {\n await clerkInstance.setActive?.({ session: fallbackSession });\n } catch (error) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to set remaining active JS session:', error);\n }\n originalUpdateClient(newClient, options);\n } finally {\n isReconcilingRemovedActiveSession = false;\n }\n });\n return;\n }\n\n originalUpdateClient(newClient, options);\n };\n\n clerkInstance.updateClient = updateClient;\n\n return () => {\n if (clerkInstance.updateClient === updateClient) {\n clerkInstance.updateClient = originalUpdateClient;\n }\n };\n }, [clerkInstance, suppressJsClientChangedRef]);\n\n const queueNativeRefreshFromJs = useCallback((options: NativeRefreshFromJsOptions): void => {\n if (isRefreshingNativeFromJsRef.current) {\n pendingNativeRefreshRef.current = mergePendingNativeRefreshOptions(pendingNativeRefreshRef.current, options);\n nativeRefreshGenerationRef.current += 1;\n return;\n }\n\n const initialGeneration = nativeRefreshGenerationRef.current + 1;\n nativeRefreshGenerationRef.current = initialGeneration;\n isRefreshingNativeFromJsRef.current = true;\n\n const refreshNativeFromJsClient = async (\n options: NativeRefreshFromJsOptions,\n generation: number,\n ): Promise<void> => {\n const ClerkExpo = NativeClerkModule;\n if (!ClerkExpo || generation !== nativeRefreshGenerationRef.current) {\n return;\n }\n\n const bearerToken = 'clientToken' in options ? (options.clientToken ?? null) : null;\n if (generation !== nativeRefreshGenerationRef.current) {\n return;\n }\n\n const sourceId = `${nativeClientSyncSourceIdPrefix}-${generation}`;\n await ClerkExpo.syncFromJsClientToken(bearerToken, sourceId, options.shouldRefreshClient);\n };\n\n let latestRunGeneration = initialGeneration;\n\n void (async () => {\n let pendingOptions = options;\n let generation = initialGeneration;\n do {\n latestRunGeneration = generation;\n pendingNativeRefreshRef.current = null;\n try {\n await refreshNativeFromJsClient(pendingOptions, generation);\n } catch (error: unknown) {\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to refresh native client from JS client change:', error);\n }\n }\n pendingOptions = pendingNativeRefreshRef.current ?? { shouldRefreshClient: false };\n if (pendingNativeRefreshRef.current !== null) {\n generation = nativeRefreshGenerationRef.current + 1;\n nativeRefreshGenerationRef.current = generation;\n }\n } while (pendingNativeRefreshRef.current !== null);\n })().finally(() => {\n if (latestRunGeneration === nativeRefreshGenerationRef.current || pendingNativeRefreshRef.current === null) {\n isRefreshingNativeFromJsRef.current = false;\n }\n });\n }, []);\n\n useEffect(() => {\n const listener: ClientTokenCacheListener = clientToken => {\n queueNativeRefreshFromJs({ clientToken, shouldRefreshClient: clientToken === null });\n };\n const tokenCacheListeners = tokenCacheListenersRef.current;\n\n tokenCacheListeners.add(listener);\n return () => {\n tokenCacheListeners.delete(listener);\n };\n }, [queueNativeRefreshFromJs, tokenCacheListenersRef]);\n\n useEffect(() => {\n if (!clerkInstance || typeof clerkInstance.handleUnauthenticated !== 'function') {\n return;\n }\n\n const originalHandleUnauthenticated = clerkInstance.handleUnauthenticated.bind(clerkInstance);\n let isHandlingUnauthenticated = false;\n\n const handleUnauthenticated: SyncableClerkInstance['handleUnauthenticated'] = async options => {\n if (isHandlingUnauthenticated) {\n return;\n }\n\n isHandlingUnauthenticated = true;\n try {\n return await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n try {\n const nativeClientToken = await readNativeClientToken({ waitForToken: false });\n // Native may have already moved the server-side client to a new\n // active session. Refresh JS before allowing Clerk JS' stale-session\n // 401 path to collapse the whole client to signed out.\n const didRecover = await refreshJsClientFromNativeState({\n clerkInstance,\n nativeClientToken,\n reloadInitialResources: false,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n if (didRecover) {\n return;\n }\n } catch (error) {\n const didRecover = await recoverJsClientFromNativeToken({\n clerkInstance,\n error,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n if (didRecover) {\n return;\n }\n }\n\n return originalHandleUnauthenticated(options);\n });\n } finally {\n isHandlingUnauthenticated = false;\n }\n };\n\n clerkInstance.handleUnauthenticated = handleUnauthenticated;\n\n return () => {\n if (clerkInstance.handleUnauthenticated === handleUnauthenticated) {\n clerkInstance.handleUnauthenticated = originalHandleUnauthenticated;\n }\n };\n }, [clerkInstance, suppressJsClientChangedRef, suppressTokenCacheNotificationsRef, tokenCache]);\n\n useEffect(() => {\n if (!clerkInstance || typeof clerkInstance.addListener !== 'function') {\n return;\n }\n\n const unsubscribe = clerkInstance.addListener(\n () => {\n if (suppressJsClientChangedRef.current > 0) {\n return;\n }\n\n queueNativeRefreshFromJs({ shouldRefreshClient: true });\n },\n { skipInitialEmit: true },\n );\n\n return () => {\n unsubscribe();\n };\n }, [clerkInstance, queueNativeRefreshFromJs, suppressJsClientChangedRef]);\n\n return null;\n}\n\nexport function useNativeClientBootstrap({\n publishableKey,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n clerkInstance,\n}: {\n publishableKey: string;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n clerkInstance: SyncableClerkInstance | null | undefined;\n}) {\n const initStartedRef = useRef(false);\n const nativeClientSyncedRef = useRef(false);\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n initStartedRef.current = false;\n nativeClientSyncedRef.current = false;\n }, [publishableKey]);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n if ((Platform.OS === 'ios' || Platform.OS === 'android') && publishableKey && !initStartedRef.current) {\n initStartedRef.current = true;\n\n const configureNativeClerk = async () => {\n try {\n const ClerkExpo = NativeClerkModule;\n\n if (ClerkExpo?.configure) {\n await ClerkExpo.configure(publishableKey, null);\n\n if (!isMountedRef.current) {\n return;\n }\n\n let bearerToken: string | null = null;\n try {\n bearerToken = await getCachedClientToken(tokenCache);\n } catch (e) {\n if (__DEV__) {\n console.warn('[ClerkProvider] Token cache read failed:', e);\n }\n }\n\n if (bearerToken) {\n await ClerkExpo.configure(publishableKey, bearerToken);\n\n if (!isMountedRef.current) {\n return;\n }\n }\n\n if (clerkInstance) {\n const waitForLoad = (): Promise<void> => {\n return new Promise(resolve => {\n if (clerkInstance.loaded) {\n resolve();\n } else if (typeof clerkInstance.addOnLoaded === 'function') {\n clerkInstance.addOnLoaded(() => resolve());\n } else {\n if (__DEV__) {\n console.warn('[ClerkProvider] Clerk instance has no loaded property or addOnLoaded method');\n }\n resolve();\n }\n });\n };\n\n await waitForLoad();\n\n if (!isMountedRef.current) {\n return;\n }\n\n if (!nativeClientSyncedRef.current) {\n nativeClientSyncedRef.current = true;\n await syncNativeClientToJs({\n clerkInstance,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n }\n }\n }\n } catch (error) {\n const isNativeModuleNotFound =\n error instanceof Error &&\n (error.message.includes('Cannot find native module') ||\n error.message.includes(\"TurboModuleRegistry.getEnforcing(...): 'ClerkExpo'\"));\n if (isNativeModuleNotFound) {\n if (__DEV__) {\n console.debug(\n `[ClerkProvider] Native Clerk module not available. ` +\n `To enable native features, add \"@clerk/expo\" to your app.json plugins array.`,\n );\n }\n } else if (__DEV__) {\n console.error(`[ClerkProvider] Failed to configure Clerk ${Platform.OS}:`, error);\n }\n }\n };\n void configureNativeClerk();\n }\n\n return () => {\n isMountedRef.current = false;\n };\n }, [publishableKey, suppressTokenCacheNotificationsRef, tokenCache, clerkInstance]);\n\n return isMountedRef;\n}\n\nexport function useNativeClientEventSync({\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance | null | undefined;\n isMountedRef: MutableRefObject<boolean>;\n nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;\n suppressJsClientChangedRef: MutableRefObject<number>;\n suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;\n tokenCache: TokenCache | undefined;\n}) {\n const { nativeClientEvent } = useNativeClientEvents();\n\n useEffect(() => {\n if (!nativeClientEvent || !clerkInstance) {\n return;\n }\n\n if (nativeClientEvent.sourceId?.startsWith(nativeClientSyncSourceIdPrefix)) {\n return;\n }\n\n const syncNativeClientStateToJs = async () => {\n try {\n if (!isMountedRef.current) {\n return;\n }\n await syncNativeClientToJs({\n clerkInstance,\n nativeRefreshFromJsControllerRef,\n nativeClientEvent,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n } catch (error) {\n console.error(`[ClerkProvider] Failed to sync native client state:`, error);\n }\n };\n\n void syncNativeClientStateToJs();\n }, [\n nativeClientEvent,\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n ]);\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ interface Spec {
2
2
  addListener?(eventName: string): void;
3
3
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
4
4
  getClientToken(): Promise<string | null>;
5
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;
5
+ syncFromJsClientToken(clientToken: string | null, sourceId: string | null, shouldRefreshClient?: boolean): Promise<void>;
6
6
  removeListeners?(count: number): void;
7
7
  }
8
8
  declare const _default: Spec;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeClerkModule.android.d.ts","sourceRoot":"","sources":["../../src/specs/NativeClerkModule.android.ts"],"names":[],"mappings":"AAEA,UAAU,IAAI;IAGZ,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,eAAe,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;;AAED,wBAAsD"}
1
+ {"version":3,"file":"NativeClerkModule.android.d.ts","sourceRoot":"","sources":["../../src/specs/NativeClerkModule.android.ts"],"names":[],"mappings":"AAEA,UAAU,IAAI;IAGZ,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,qBAAqB,CACnB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,eAAe,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;;AAED,wBAAsD"}
@@ -1 +1 @@
1
- {"version":3,"file":"NativeClerkModule.android.js","names":[],"sources":["../../src/specs/NativeClerkModule.android.ts"],"sourcesContent":["import { requireNativeModule } from 'expo';\n\ninterface Spec {\n // addListener/removeListeners are present on the iOS RN event emitter module.\n // Android uses Expo Modules EventEmitter instead.\n addListener?(eventName: string): void;\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;\n removeListeners?(count: number): void;\n}\n\nexport default requireNativeModule<Spec>('ClerkExpo');\n"],"mappings":";;;AAYA,sEAAyC,WAAW"}
1
+ {"version":3,"file":"NativeClerkModule.android.js","names":[],"sources":["../../src/specs/NativeClerkModule.android.ts"],"sourcesContent":["import { requireNativeModule } from 'expo';\n\ninterface Spec {\n // addListener/removeListeners are present on the iOS RN event emitter module.\n // Android uses Expo Modules EventEmitter instead.\n addListener?(eventName: string): void;\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n syncFromJsClientToken(\n clientToken: string | null,\n sourceId: string | null,\n shouldRefreshClient?: boolean,\n ): Promise<void>;\n removeListeners?(count: number): void;\n}\n\nexport default requireNativeModule<Spec>('ClerkExpo');\n"],"mappings":";;;AAgBA,sEAAyC,WAAW"}
@@ -3,7 +3,7 @@ export interface Spec extends TurboModule {
3
3
  addListener(eventName: string): void;
4
4
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
5
5
  getClientToken(): Promise<string | null>;
6
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;
6
+ syncFromJsClientToken(clientToken: string | null, sourceId: string | null, shouldRefreshClient?: boolean): Promise<void>;
7
7
  removeListeners(count: number): void;
8
8
  }
9
9
  declare const _default: Spec | null;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeClerkModule.d.ts","sourceRoot":"","sources":["../../src/specs/NativeClerkModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IAGvC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG1F,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAA0D"}
1
+ {"version":3,"file":"NativeClerkModule.d.ts","sourceRoot":"","sources":["../../src/specs/NativeClerkModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IAGvC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,qBAAqB,CACnB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAA0D"}
@@ -1 +1 @@
1
- {"version":3,"file":"NativeClerkModule.js","names":["TurboModuleRegistry"],"sources":["../../src/specs/NativeClerkModule.ts"],"sourcesContent":["import type { TurboModule } from 'react-native';\nimport { TurboModuleRegistry } from 'react-native';\n\nexport interface Spec extends TurboModule {\n // Required by NativeEventEmitter for internal native client change events.\n // This is not part of the public @clerk/expo API.\n addListener(eventName: string): void;\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;\n // Required by NativeEventEmitter for internal native client change events.\n // This is not part of the public @clerk/expo API.\n removeListeners(count: number): void;\n}\n\nexport default TurboModuleRegistry.get<Spec>('ClerkExpo');\n"],"mappings":";;;AAeA,gCAAeA,iCAAoB,IAAU,WAAW"}
1
+ {"version":3,"file":"NativeClerkModule.js","names":["TurboModuleRegistry"],"sources":["../../src/specs/NativeClerkModule.ts"],"sourcesContent":["import type { TurboModule } from 'react-native';\nimport { TurboModuleRegistry } from 'react-native';\n\nexport interface Spec extends TurboModule {\n // Required by NativeEventEmitter for internal native client change events.\n // This is not part of the public @clerk/expo API.\n addListener(eventName: string): void;\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n syncFromJsClientToken(\n clientToken: string | null,\n sourceId: string | null,\n shouldRefreshClient?: boolean,\n ): Promise<void>;\n // Required by NativeEventEmitter for internal native client change events.\n // This is not part of the public @clerk/expo API.\n removeListeners(count: number): void;\n}\n\nexport default TurboModuleRegistry.get<Spec>('ClerkExpo');\n"],"mappings":";;;AAmBA,gCAAeA,iCAAoB,IAAU,WAAW"}
@@ -1,12 +1,12 @@
1
1
  export declare const isNativeSupported: boolean;
2
2
  type ClerkExpoNativeModule = {
3
- addListener(eventName: string, listener?: (...args: unknown[]) => void): {
3
+ addListener?(eventName: string, listener?: (...args: unknown[]) => void): {
4
4
  remove: () => void;
5
5
  };
6
6
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
7
7
  getClientToken(): Promise<string | null>;
8
- removeListeners(count: number): void;
9
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;
8
+ removeListeners?(count: number): void;
9
+ syncFromJsClientToken(clientToken: string | null, sourceId: string | null, shouldRefreshClient?: boolean): Promise<void>;
10
10
  };
11
11
  export declare const ClerkExpoModule: ClerkExpoNativeModule | null;
12
12
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"native-module.d.ts","sourceRoot":"","sources":["../../src/utils/native-module.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,SAAqD,CAAC;AAEpF,KAAK,qBAAqB,GAAG;IAC3B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAChG,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3F,CAAC;AAkDF,eAAO,MAAM,eAAe,8BAAqB,CAAC"}
1
+ {"version":3,"file":"native-module.d.ts","sourceRoot":"","sources":["../../src/utils/native-module.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,SAAqD,CAAC;AAEpF,KAAK,qBAAqB,GAAG;IAC3B,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACjG,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,eAAe,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,qBAAqB,CACnB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB,CAAC;AAgDF,eAAO,MAAM,eAAe,8BAAqB,CAAC"}
@@ -9,7 +9,7 @@ const isNativeSupported = react_native.Platform.OS === "ios" || react_native.Pla
9
9
  function isClerkExpoModule(module) {
10
10
  if (!module || typeof module !== "object") return false;
11
11
  const maybeModule = module;
12
- return typeof maybeModule.addListener === "function" && typeof maybeModule.configure === "function" && typeof maybeModule.getClientToken === "function" && typeof maybeModule.removeListeners === "function" && typeof maybeModule.syncFromJsClientToken === "function";
12
+ return typeof maybeModule.configure === "function" && typeof maybeModule.getClientToken === "function" && typeof maybeModule.syncFromJsClientToken === "function";
13
13
  }
14
14
  function loadNativeModule() {
15
15
  if (!isNativeSupported) return null;
@@ -1 +1 @@
1
- {"version":3,"file":"native-module.js","names":["Platform","NativeClerkModule"],"sources":["../../src/utils/native-module.ts"],"sourcesContent":["import { Platform } from 'react-native';\n\nimport NativeClerkModule from '../specs/NativeClerkModule';\n\nexport const isNativeSupported = Platform.OS === 'ios' || Platform.OS === 'android';\n\ntype ClerkExpoNativeModule = {\n addListener(eventName: string, listener?: (...args: unknown[]) => void): { remove: () => void };\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n removeListeners(count: number): void;\n syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;\n};\n\nfunction isClerkExpoModule(module: unknown): module is ClerkExpoNativeModule {\n if (!module || typeof module !== 'object') {\n return false;\n }\n const maybeModule = module as Record<string, unknown>;\n\n return (\n typeof maybeModule.addListener === 'function' &&\n typeof maybeModule.configure === 'function' &&\n typeof maybeModule.getClientToken === 'function' &&\n typeof maybeModule.removeListeners === 'function' &&\n typeof maybeModule.syncFromJsClientToken === 'function'\n );\n}\n\nfunction loadNativeModule(): ClerkExpoNativeModule | null {\n if (!isNativeSupported) {\n return null;\n }\n let nativeModule: unknown = null;\n\n try {\n nativeModule = NativeClerkModule;\n } catch (e) {\n if (__DEV__) {\n console.warn('[ClerkExpo] Native module not available:', e);\n }\n }\n\n if (isClerkExpoModule(nativeModule)) {\n return nativeModule;\n }\n\n try {\n // Expo SDK 54 can expose installed modules through Expo's module registry even\n // when the generated TurboModule object is incomplete.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { requireNativeModule } = require('expo');\n const expoModule = requireNativeModule('ClerkExpo');\n return isClerkExpoModule(expoModule) ? expoModule : null;\n } catch (e) {\n if (__DEV__ && !nativeModule) {\n console.warn('[ClerkExpo] Native module not available:', e);\n }\n return null;\n }\n}\n\nexport const ClerkExpoModule = loadNativeModule();\n"],"mappings":";;;;;;;AAIA,MAAa,oBAAoBA,sBAAS,OAAO,SAASA,sBAAS,OAAO;AAU1E,SAAS,kBAAkB,QAAkD;CAC3E,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,OAAO;CAET,MAAM,cAAc;CAEpB,OACE,OAAO,YAAY,gBAAgB,cACnC,OAAO,YAAY,cAAc,cACjC,OAAO,YAAY,mBAAmB,cACtC,OAAO,YAAY,oBAAoB,cACvC,OAAO,YAAY,0BAA0B;AAEjD;AAEA,SAAS,mBAAiD;CACxD,IAAI,CAAC,mBACH,OAAO;CAET,IAAI,eAAwB;CAE5B,IAAI;EACF,eAAeC;CACjB,SAAS,GAAG,CAIZ;CAEA,IAAI,kBAAkB,YAAY,GAChC,OAAO;CAGT,IAAI;EAIF,MAAM,EAAE,wBAAwB,QAAQ,MAAM;EAC9C,MAAM,aAAa,oBAAoB,WAAW;EAClD,OAAO,kBAAkB,UAAU,IAAI,aAAa;CACtD,SAAS,GAAG;EAIV,OAAO;CACT;AACF;AAEA,MAAa,kBAAkB,iBAAiB"}
1
+ {"version":3,"file":"native-module.js","names":["Platform","NativeClerkModule"],"sources":["../../src/utils/native-module.ts"],"sourcesContent":["import { Platform } from 'react-native';\n\nimport NativeClerkModule from '../specs/NativeClerkModule';\n\nexport const isNativeSupported = Platform.OS === 'ios' || Platform.OS === 'android';\n\ntype ClerkExpoNativeModule = {\n addListener?(eventName: string, listener?: (...args: unknown[]) => void): { remove: () => void };\n configure(publishableKey: string, bearerToken: string | null): Promise<void>;\n getClientToken(): Promise<string | null>;\n removeListeners?(count: number): void;\n syncFromJsClientToken(\n clientToken: string | null,\n sourceId: string | null,\n shouldRefreshClient?: boolean,\n ): Promise<void>;\n};\n\nfunction isClerkExpoModule(module: unknown): module is ClerkExpoNativeModule {\n if (!module || typeof module !== 'object') {\n return false;\n }\n const maybeModule = module as Record<string, unknown>;\n\n return (\n typeof maybeModule.configure === 'function' &&\n typeof maybeModule.getClientToken === 'function' &&\n typeof maybeModule.syncFromJsClientToken === 'function'\n );\n}\n\nfunction loadNativeModule(): ClerkExpoNativeModule | null {\n if (!isNativeSupported) {\n return null;\n }\n let nativeModule: unknown = null;\n\n try {\n nativeModule = NativeClerkModule;\n } catch (e) {\n if (__DEV__) {\n console.warn('[ClerkExpo] Native module not available:', e);\n }\n }\n\n if (isClerkExpoModule(nativeModule)) {\n return nativeModule;\n }\n\n try {\n // Expo SDK 54 can expose installed modules through Expo's module registry even\n // when the generated TurboModule object is incomplete.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { requireNativeModule } = require('expo');\n const expoModule = requireNativeModule('ClerkExpo');\n return isClerkExpoModule(expoModule) ? expoModule : null;\n } catch (e) {\n if (__DEV__ && !nativeModule) {\n console.warn('[ClerkExpo] Native module not available:', e);\n }\n return null;\n }\n}\n\nexport const ClerkExpoModule = loadNativeModule();\n"],"mappings":";;;;;;;AAIA,MAAa,oBAAoBA,sBAAS,OAAO,SAASA,sBAAS,OAAO;AAc1E,SAAS,kBAAkB,QAAkD;CAC3E,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,OAAO;CAET,MAAM,cAAc;CAEpB,OACE,OAAO,YAAY,cAAc,cACjC,OAAO,YAAY,mBAAmB,cACtC,OAAO,YAAY,0BAA0B;AAEjD;AAEA,SAAS,mBAAiD;CACxD,IAAI,CAAC,mBACH,OAAO;CAET,IAAI,eAAwB;CAE5B,IAAI;EACF,eAAeC;CACjB,SAAS,GAAG,CAIZ;CAEA,IAAI,kBAAkB,YAAY,GAChC,OAAO;CAGT,IAAI;EAIF,MAAM,EAAE,wBAAwB,QAAQ,MAAM;EAC9C,MAAM,aAAa,oBAAoB,WAAW;EAClD,OAAO,kBAAkB,UAAU,IAAI,aAAa;CACtD,SAAS,GAAG;EAIV,OAAO;CACT;AACF;AAEA,MAAa,kBAAkB,iBAAiB"}
@@ -13,6 +13,7 @@ RCT_EXTERN_METHOD(getClientToken:(RCTPromiseResolveBlock)resolve
13
13
 
14
14
  RCT_EXTERN_METHOD(syncFromJsClientToken:(id)clientToken
15
15
  sourceId:(id)sourceId
16
+ shouldRefreshClient:(id)shouldRefreshClient
16
17
  resolve:(RCTPromiseResolveBlock)resolve
17
18
  reject:(RCTPromiseRejectBlock)reject)
18
19
 
@@ -31,7 +31,7 @@ public protocol ClerkNativeBridgeProtocol {
31
31
  // SDK operations
32
32
  func configure(publishableKey: String, bearerToken: String?) async throws
33
33
  func getClientToken() async -> String?
34
- func syncFromJsClientToken(_ clientToken: String?, sourceId: String?) async throws
34
+ func syncFromJsClientToken(_ clientToken: String?, sourceId: String?, shouldRefreshClient: Bool) async throws
35
35
  }
36
36
 
37
37
  public protocol ClerkNativeBridgeReadyObserver: AnyObject {
@@ -154,6 +154,7 @@ class ClerkExpoModule: RCTEventEmitter {
154
154
 
155
155
  @objc func syncFromJsClientToken(_ clientToken: Any?,
156
156
  sourceId: Any?,
157
+ shouldRefreshClient: Any?,
157
158
  resolve: @escaping RCTPromiseResolveBlock,
158
159
  reject: @escaping RCTPromiseRejectBlock) {
159
160
  guard let bridge = clerkNativeBridge else {
@@ -163,9 +164,15 @@ class ClerkExpoModule: RCTEventEmitter {
163
164
 
164
165
  let normalizedClientToken = clientToken as? String
165
166
  let normalizedSourceId = sourceId as? String
167
+ let defaultShouldRefreshClient = normalizedClientToken?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true
168
+ let normalizedShouldRefreshClient = (shouldRefreshClient as? Bool) ?? defaultShouldRefreshClient
166
169
  Task {
167
170
  do {
168
- try await bridge.syncFromJsClientToken(normalizedClientToken, sourceId: normalizedSourceId)
171
+ try await bridge.syncFromJsClientToken(
172
+ normalizedClientToken,
173
+ sourceId: normalizedSourceId,
174
+ shouldRefreshClient: normalizedShouldRefreshClient
175
+ )
169
176
  resolve(nil)
170
177
  } catch {
171
178
  reject("E_SYNC_FROM_JS_FAILED", error.localizedDescription, error)
@@ -59,10 +59,7 @@ public class ClerkGoogleSignInModule: Module {
59
59
  return
60
60
  }
61
61
 
62
- let filterByAuthorized = params?["filterByAuthorizedAccounts"] as? Bool ?? false
63
- let hint: String? = filterByAuthorized
64
- ? GIDSignIn.sharedInstance.currentUser?.profile?.email
65
- : nil
62
+ let hint = params?["hint"] as? String
66
63
  let nonce = params?["nonce"] as? String
67
64
 
68
65
  GIDSignIn.sharedInstance.signIn(
@@ -21,8 +21,8 @@ private struct ClerkExpoHeaderMiddleware: ClerkRequestMiddleware {
21
21
 
22
22
  // MARK: - Native Bridge Implementation
23
23
 
24
- public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
25
- public static let shared = ClerkNativeBridge()
24
+ final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
25
+ static let shared = ClerkNativeBridge()
26
26
 
27
27
  private static let clerkLoadMaxAttempts = 30
28
28
  private static let clerkLoadIntervalNs: UInt64 = 100_000_000
@@ -53,21 +53,21 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
53
53
  }
54
54
 
55
55
  // Register this app-target bridge with the ClerkExpo module.
56
- @MainActor public static func register() {
56
+ @MainActor static func register() {
57
57
  shared.loadThemes()
58
58
  clerkNativeBridge = shared
59
59
  }
60
60
 
61
61
  @MainActor
62
- public func configure(publishableKey: String, bearerToken: String? = nil) async throws {
62
+ func configure(publishableKey: String, bearerToken: String? = nil) async throws {
63
63
  if Self.shouldReconfigure(for: publishableKey) {
64
64
  try await Clerk.reconfigure(publishableKey: publishableKey, options: Self.makeClerkOptions())
65
65
  Self.clerkConfigured = true
66
66
  Self.configuredPublishableKey = publishableKey
67
67
  startClientObserver(reset: true)
68
68
 
69
- let shouldWaitForSession = try await Self.syncTokenState(bearerToken: bearerToken)
70
- await Self.waitForLoadedSessionIfNeeded(shouldWaitForSession)
69
+ let shouldWaitForClient = try await Self.syncTokenState(bearerToken: bearerToken)
70
+ await Self.waitForLoadedClientIfNeeded(shouldWaitForClient)
71
71
  Self.emitClientChangedIfReceivedToken(bearerToken)
72
72
  emitClerkNativeBridgeReady()
73
73
  return
@@ -75,8 +75,8 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
75
75
 
76
76
  if Self.clerkConfigured {
77
77
  startClientObserver()
78
- let shouldWaitForSession = try await Self.syncTokenState(bearerToken: bearerToken)
79
- await Self.waitForLoadedSessionIfNeeded(shouldWaitForSession)
78
+ let shouldWaitForClient = try await Self.syncTokenState(bearerToken: bearerToken)
79
+ await Self.waitForLoadedClientIfNeeded(shouldWaitForClient)
80
80
  Self.emitClientChangedIfReceivedToken(bearerToken)
81
81
  return
82
82
  }
@@ -86,8 +86,8 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
86
86
  Clerk.configure(publishableKey: publishableKey, options: Self.makeClerkOptions())
87
87
  startClientObserver()
88
88
 
89
- let shouldWaitForSession = try await Self.syncTokenState(bearerToken: bearerToken)
90
- await Self.waitForLoadedSessionIfNeeded(shouldWaitForSession)
89
+ let shouldWaitForClient = try await Self.syncTokenState(bearerToken: bearerToken)
90
+ await Self.waitForLoadedClientIfNeeded(shouldWaitForClient)
91
91
  Self.emitClientChangedIfReceivedToken(bearerToken)
92
92
  emitClerkNativeBridgeReady()
93
93
  }
@@ -175,20 +175,10 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
175
175
  return .init(keychainConfig: .init(service: service), middleware: middleware)
176
176
  }
177
177
 
178
- @MainActor
179
- private static func waitForLoadedSession() async {
180
- // Wait for Clerk to finish loading (cached data + API refresh).
181
- // The static configure() fires off async refreshes; poll until loaded.
182
- for _ in 0..<clerkLoadMaxAttempts {
183
- if Clerk.shared.isLoaded && Clerk.shared.session != nil && Clerk.shared.user != nil {
184
- return
185
- }
186
- try? await Task.sleep(nanoseconds: clerkLoadIntervalNs)
187
- }
188
- }
189
-
190
178
  @MainActor
191
179
  private static func waitForLoadedClient() async {
180
+ // Wait for Clerk to finish loading client state from cached data + API refresh.
181
+ // The bridge sync contract is client-token based, not session based.
192
182
  for _ in 0..<clerkLoadMaxAttempts {
193
183
  if Clerk.shared.isLoaded {
194
184
  return
@@ -198,20 +188,20 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
198
188
  }
199
189
 
200
190
  @MainActor
201
- private static func waitForLoadedSessionIfNeeded(_ shouldWait: Bool) async {
191
+ private static func waitForLoadedClientIfNeeded(_ shouldWait: Bool) async {
202
192
  guard shouldWait else { return }
203
- await waitForLoadedSession()
193
+ await waitForLoadedClient()
204
194
  }
205
195
 
206
196
  @MainActor
207
- public func getClientToken() async -> String? {
197
+ func getClientToken() async -> String? {
208
198
  guard Self.clerkConfigured else { return nil }
209
199
  return Clerk.shared.deviceToken
210
200
  }
211
201
 
212
202
  // MARK: - Inline View Creation
213
203
 
214
- public func makeAuthViewController(
204
+ func makeAuthViewController(
215
205
  mode: String,
216
206
  dismissible: Bool,
217
207
  onEvent: @escaping (ClerkNativeViewEvent, [String: Any]) -> Void
@@ -229,7 +219,7 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
229
219
  )
230
220
  }
231
221
 
232
- public func makeUserProfileViewController(
222
+ func makeUserProfileViewController(
233
223
  dismissible: Bool,
234
224
  onEvent: @escaping (ClerkNativeViewEvent, [String: Any]) -> Void
235
225
  ) -> UIViewController? {
@@ -245,7 +235,7 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
245
235
  )
246
236
  }
247
237
 
248
- public func makeUserButtonViewController() -> UIViewController? {
238
+ func makeUserButtonViewController() -> UIViewController? {
249
239
  guard Self.clerkConfigured else { return nil }
250
240
 
251
241
  return makeHostingController(
@@ -257,13 +247,17 @@ public final class ClerkNativeBridge: ClerkNativeBridgeProtocol {
257
247
  }
258
248
 
259
249
  @MainActor
260
- public func syncFromJsClientToken(_ clientToken: String?, sourceId: String?) async throws {
250
+ func syncFromJsClientToken(_ clientToken: String?, sourceId: String?, shouldRefreshClient: Bool) async throws {
261
251
  guard Self.clerkConfigured else { return }
262
252
 
263
253
  if let token = clientToken?.trimmingCharacters(in: .whitespacesAndNewlines), !token.isEmpty {
264
- _ = try await Clerk.shared.updateDeviceToken(token)
265
- await Self.waitForLoadedSession()
266
- } else {
254
+ if Clerk.shared.deviceToken != token {
255
+ _ = try await Clerk.shared.updateDeviceToken(token)
256
+ await Self.waitForLoadedClient()
257
+ }
258
+ }
259
+
260
+ if shouldRefreshClient {
267
261
  _ = try await Clerk.shared.refreshClient()
268
262
  await Self.waitForLoadedClient()
269
263
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerk/expo",
3
- "version": "3.4.7-snapshot.v20260618154136",
3
+ "version": "3.4.7",
4
4
  "description": "Clerk React Native/Expo library",
5
5
  "keywords": [
6
6
  "react",
@@ -104,9 +104,9 @@
104
104
  "base-64": "^1.0.0",
105
105
  "react-native-url-polyfill": "2.0.0",
106
106
  "tslib": "2.8.1",
107
- "@clerk/clerk-js": "6.18.1-snapshot.v20260618154136",
108
- "@clerk/react": "6.10.3-snapshot.v20260618154136",
109
- "@clerk/shared": "4.19.1-snapshot.v20260618154136"
107
+ "@clerk/clerk-js": "^6.18.1",
108
+ "@clerk/react": "^6.10.3",
109
+ "@clerk/shared": "^4.19.1"
110
110
  },
111
111
  "devDependencies": {
112
112
  "@expo/config-plugins": "^54.0.4",
@@ -120,10 +120,10 @@
120
120
  "expo-secure-store": "^12.8.1",
121
121
  "expo-web-browser": "^12.8.2",
122
122
  "react-native": "^0.85.2",
123
- "@clerk/expo-passkeys": "1.1.7-snapshot.v20260618154136"
123
+ "@clerk/expo-passkeys": "1.1.7"
124
124
  },
125
125
  "peerDependencies": {
126
- "@clerk/expo-passkeys": "1.1.7-snapshot.v20260618154136",
126
+ "@clerk/expo-passkeys": ">=0.0.6",
127
127
  "expo": ">=53 <57",
128
128
  "expo-apple-authentication": ">=7.0.0",
129
129
  "expo-auth-session": ">=5",
@@ -6,7 +6,11 @@ interface Spec {
6
6
  addListener?(eventName: string): void;
7
7
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
8
8
  getClientToken(): Promise<string | null>;
9
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;
9
+ syncFromJsClientToken(
10
+ clientToken: string | null,
11
+ sourceId: string | null,
12
+ shouldRefreshClient?: boolean,
13
+ ): Promise<void>;
10
14
  removeListeners?(count: number): void;
11
15
  }
12
16
 
@@ -7,7 +7,11 @@ export interface Spec extends TurboModule {
7
7
  addListener(eventName: string): void;
8
8
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
9
9
  getClientToken(): Promise<string | null>;
10
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null): Promise<void>;
10
+ syncFromJsClientToken(
11
+ clientToken: string | null,
12
+ sourceId: string | null,
13
+ shouldRefreshClient?: boolean,
14
+ ): Promise<void>;
11
15
  // Required by NativeEventEmitter for internal native client change events.
12
16
  // This is not part of the public @clerk/expo API.
13
17
  removeListeners(count: number): void;