@clerk/expo 3.5.0-canary.v20260619100729 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,16 +35,32 @@ private fun debugLog(tag: String, message: String) {
35
35
  class ClerkExpoModule : Module() {
36
36
  private val coroutineScope = CoroutineScope(Dispatchers.Main)
37
37
  private var clientStateObserverJob: Job? = null
38
- private var lastObservedClient: Client? = null
38
+ private var lastObservedClientState: ClientStateSnapshot? = null
39
39
  private var jsOriginatedClientSyncDepth = 0
40
40
  private var configuredPublishableKey: String? = null
41
41
 
42
+ private data class ClientStateSnapshot(
43
+ val client: Client?,
44
+ val deviceToken: String?
45
+ )
46
+
47
+ private data class ClientStateChanges(
48
+ val client: Boolean,
49
+ val deviceToken: Boolean
50
+ )
51
+
42
52
  companion object {
43
53
  private var sharedInstance: ClerkExpoModule? = null
44
54
 
45
55
  fun emitClientChanged(sourceId: String? = null) {
46
56
  val instance = sharedInstance ?: return
47
- instance.sendEvent(NATIVE_CLIENT_CHANGED_EVENT, instance.clientChangedPayload(sourceId))
57
+ instance.sendEvent(
58
+ NATIVE_CLIENT_CHANGED_EVENT,
59
+ instance.clientChangedPayload(
60
+ sourceId = sourceId,
61
+ changes = ClientStateChanges(client = true, deviceToken = true)
62
+ )
63
+ )
48
64
  }
49
65
  }
50
66
 
@@ -73,11 +89,17 @@ class ClerkExpoModule : Module() {
73
89
  getClientToken(promise)
74
90
  }
75
91
 
76
- AsyncFunction("syncFromJsClientToken") { clientToken: String?, sourceId: String?, shouldRefreshClient: Boolean?, promise: Promise ->
77
- syncFromJsClientToken(
78
- clientToken,
92
+ AsyncFunction("syncClientStateFromJs") {
93
+ deviceToken: String?,
94
+ sourceId: String?,
95
+ didChangeClient: Boolean,
96
+ didChangeDeviceToken: Boolean,
97
+ promise: Promise ->
98
+ syncClientStateFromJs(
99
+ deviceToken,
79
100
  sourceId,
80
- shouldRefreshClient ?: clientToken.isNullOrBlank(),
101
+ didChangeClient,
102
+ didChangeDeviceToken,
81
103
  promise
82
104
  )
83
105
  }
@@ -91,42 +113,80 @@ class ClerkExpoModule : Module() {
91
113
  return
92
114
  }
93
115
 
94
- lastObservedClient = Clerk.clientFlow.value
116
+ lastObservedClientState = clientStateSnapshot()
95
117
 
96
118
  clientStateObserverJob = coroutineScope.launch {
97
119
  Clerk.clientFlow.collect { client ->
98
- if (client == lastObservedClient) {
120
+ val previousClientState = lastObservedClientState
121
+ val newClientState = clientStateSnapshot(client)
122
+
123
+ if (newClientState == previousClientState) {
99
124
  return@collect
100
125
  }
101
126
 
102
- lastObservedClient = client
127
+ lastObservedClientState = newClientState
103
128
  if (jsOriginatedClientSyncDepth > 0) {
104
129
  return@collect
105
130
  }
106
131
 
107
- emitClientChanged()
132
+ sendEvent(
133
+ NATIVE_CLIENT_CHANGED_EVENT,
134
+ clientChangedPayload(
135
+ deviceToken = newClientState.deviceToken,
136
+ changes = ClientStateChanges(
137
+ client = newClientState.client != previousClientState?.client,
138
+ deviceToken = newClientState.deviceToken != previousClientState?.deviceToken
139
+ )
140
+ )
141
+ )
108
142
  }
109
143
  }
110
144
  }
111
145
 
112
- private fun clientChangedPayload(sourceId: String? = null): Map<String, Any?> {
113
- val result = mutableMapOf<String, Any?>(
114
- "clientToken" to try {
146
+ private fun clientStateSnapshot(client: Client? = Clerk.clientFlow.value): ClientStateSnapshot {
147
+ return ClientStateSnapshot(
148
+ client = client,
149
+ deviceToken = try {
115
150
  Clerk.getDeviceToken()
116
151
  } catch (e: Exception) {
117
- debugLog(TAG, "clientChangedPayload - getDeviceToken failed: ${e.message}")
152
+ debugLog(TAG, "clientStateSnapshot - getDeviceToken failed: ${e.message}")
118
153
  null
119
154
  }
120
155
  )
156
+ }
157
+
158
+ private fun clientChangedPayload(
159
+ sourceId: String? = null,
160
+ changes: ClientStateChanges,
161
+ deviceToken: String? = clientStateSnapshot().deviceToken
162
+ ): Map<String, Any?> {
163
+ val result = mutableMapOf<String, Any?>(
164
+ "changed" to mapOf(
165
+ "client" to changes.client,
166
+ "deviceToken" to changes.deviceToken
167
+ ),
168
+ "deviceToken" to deviceToken
169
+ )
121
170
  if (!sourceId.isNullOrEmpty()) {
122
171
  result["sourceId"] = sourceId
123
172
  }
124
173
  return result
125
174
  }
126
175
 
127
- private fun emitSyncedClientChanged(sourceId: String?) {
128
- lastObservedClient = Clerk.clientFlow.value
129
- emitClientChanged(sourceId)
176
+ private fun emitSyncedClientChanged(
177
+ sourceId: String?,
178
+ changes: ClientStateChanges,
179
+ snapshot: ClientStateSnapshot = clientStateSnapshot()
180
+ ) {
181
+ lastObservedClientState = snapshot
182
+ sendEvent(
183
+ NATIVE_CLIENT_CHANGED_EVENT,
184
+ clientChangedPayload(
185
+ sourceId = sourceId,
186
+ changes = changes,
187
+ deviceToken = snapshot.deviceToken
188
+ )
189
+ )
130
190
  }
131
191
 
132
192
  // MARK: - configure
@@ -288,12 +348,13 @@ class ClerkExpoModule : Module() {
288
348
  }
289
349
  }
290
350
 
291
- // MARK: - syncFromJsClientToken
351
+ // MARK: - syncClientStateFromJs
292
352
 
293
- private fun syncFromJsClientToken(
294
- clientToken: String?,
353
+ private fun syncClientStateFromJs(
354
+ deviceToken: String?,
295
355
  sourceId: String?,
296
- shouldRefreshClient: Boolean,
356
+ didChangeClient: Boolean,
357
+ didChangeDeviceToken: Boolean,
297
358
  promise: Promise
298
359
  ) {
299
360
  if (!Clerk.isInitialized.value) {
@@ -304,25 +365,21 @@ class ClerkExpoModule : Module() {
304
365
  coroutineScope.launch {
305
366
  try {
306
367
  jsOriginatedClientSyncDepth += 1
307
- if (!clientToken.isNullOrBlank()) {
368
+ val previousClientState = clientStateSnapshot()
369
+
370
+ if (didChangeDeviceToken && !deviceToken.isNullOrBlank()) {
308
371
  val currentDeviceToken = try {
309
372
  Clerk.getDeviceToken()
310
373
  } catch (_: Exception) {
311
374
  null
312
375
  }
313
376
 
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)) {
377
+ if (currentDeviceToken != deviceToken) {
378
+ when (val result = Clerk.updateDeviceToken(deviceToken)) {
322
379
  is ClerkResult.Failure -> {
323
380
  promise.reject(
324
381
  "E_SYNC_FROM_JS_FAILED",
325
- result.error?.firstMessage() ?: result.throwable?.message ?: "Client token sync failed",
382
+ result.error?.firstMessage() ?: result.throwable?.message ?: "Device token sync failed",
326
383
  null
327
384
  )
328
385
  return@launch
@@ -333,19 +390,14 @@ class ClerkExpoModule : Module() {
333
390
  Clerk.clientFlow.first { it != null }
334
391
  }
335
392
  } 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
393
+ debugLog(TAG, "syncClientStateFromJs - client did not appear after token update")
342
394
  }
343
395
  }
344
396
  }
345
397
  }
346
398
  }
347
399
 
348
- if (shouldRefreshClient) {
400
+ if (didChangeClient || didChangeDeviceToken) {
349
401
  when (val result = Clerk.refreshClient()) {
350
402
  is ClerkResult.Failure -> {
351
403
  promise.reject(
@@ -355,17 +407,33 @@ class ClerkExpoModule : Module() {
355
407
  )
356
408
  }
357
409
  is ClerkResult.Success -> {
358
- emitSyncedClientChanged(sourceId)
410
+ val newClientState = clientStateSnapshot()
411
+ emitSyncedClientChanged(
412
+ sourceId,
413
+ ClientStateChanges(
414
+ client = newClientState.client != previousClientState.client,
415
+ deviceToken = newClientState.deviceToken != previousClientState.deviceToken
416
+ ),
417
+ newClientState
418
+ )
359
419
  promise.resolve(null)
360
420
  }
361
421
  }
362
422
  return@launch
363
423
  }
364
424
 
365
- emitSyncedClientChanged(sourceId)
425
+ val newClientState = clientStateSnapshot()
426
+ emitSyncedClientChanged(
427
+ sourceId,
428
+ ClientStateChanges(
429
+ client = newClientState.client != previousClientState.client,
430
+ deviceToken = newClientState.deviceToken != previousClientState.deviceToken
431
+ ),
432
+ newClientState
433
+ )
366
434
  promise.resolve(null)
367
435
  } catch (e: Exception) {
368
- promise.reject("E_SYNC_FROM_JS_FAILED", e.message ?: "Client token sync failed", e)
436
+ promise.reject("E_SYNC_FROM_JS_FAILED", e.message ?: "Client state sync failed", e)
369
437
  } finally {
370
438
  jsOriginatedClientSyncDepth = maxOf(0, jsOriginatedClientSyncDepth - 1)
371
439
  }
@@ -1,5 +1,9 @@
1
1
  export interface NativeClientSnapshot {
2
- clientToken?: string | null;
2
+ changed: {
3
+ client: boolean;
4
+ deviceToken: boolean;
5
+ };
6
+ deviceToken: string | null;
3
7
  sourceId?: string | null;
4
8
  }
5
9
  /**
@@ -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;AAyBD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CAkCnE"}
1
+ {"version":3,"file":"useNativeClientEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useNativeClientEvents.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE;QACP,MAAM,EAAE,OAAO,CAAC;QAChB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,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;AAiCD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CAsCnE"}
@@ -10,6 +10,9 @@ function getNativeClientEventEmitter() {
10
10
  if (src_utils_native_module.ClerkExpoModule && typeof src_utils_native_module.ClerkExpoModule.addListener === "function") return src_utils_native_module.ClerkExpoModule;
11
11
  return null;
12
12
  }
13
+ function isNativeClientSnapshot(snapshot) {
14
+ return typeof snapshot?.changed?.client === "boolean" && typeof snapshot.changed.deviceToken === "boolean" && (typeof snapshot.deviceToken === "string" || snapshot.deviceToken === null);
15
+ }
13
16
  /**
14
17
  * Listens for native client events that should sync JS client state.
15
18
  */
@@ -22,6 +25,7 @@ function useNativeClientEvents() {
22
25
  const eventEmitter = getNativeClientEventEmitter();
23
26
  if (!eventEmitter) return;
24
27
  subscription = eventEmitter.addListener(nativeClientChangedEvent, (snapshot) => {
28
+ if (!isNativeClientSnapshot(snapshot)) return;
25
29
  setNativeClientEvent({
26
30
  issuedAt: Date.now(),
27
31
  ...snapshot
@@ -1 +1 @@
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"}
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 changed: {\n client: boolean;\n deviceToken: boolean;\n };\n deviceToken: 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\nfunction isNativeClientSnapshot(snapshot: NativeClientSnapshot | undefined): snapshot is NativeClientSnapshot {\n return (\n typeof snapshot?.changed?.client === 'boolean' &&\n typeof snapshot.changed.deviceToken === 'boolean' &&\n (typeof snapshot.deviceToken === 'string' || snapshot.deviceToken === null)\n );\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 if (!isNativeClientSnapshot(snapshot)) {\n return;\n }\n\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;AAiCjC,SAAS,8BAAgE;CACvE,IAAIA,sBAAS,OAAO,OAClB,OAAOC;CAGT,IAAIC,2CAAa,OAAOA,wCAAU,gBAAgB,YAChD,OAAOA;CAGT,OAAO;AACT;AAEA,SAAS,uBAAuB,UAA8E;CAC5G,OACE,OAAO,UAAU,SAAS,WAAW,aACrC,OAAO,SAAS,QAAQ,gBAAgB,cACvC,OAAO,SAAS,gBAAgB,YAAY,SAAS,gBAAgB;AAE1E;;;;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,IAAI,CAAC,uBAAuB,QAAQ,GAClC;IAGF,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,13 +11,13 @@ 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.5.0-canary.v20260619100729"
14
+ version: "3.5.0"
15
15
  };
16
16
  function ClerkProvider(props) {
17
17
  const { children, tokenCache, publishableKey, proxyUrl, domain, __experimental_passkeys, experimental, __experimental_resourceCache, ...rest } = props;
18
18
  const pk = publishableKey;
19
19
  const tokenCacheListenersRef = (0, react.useRef)(/* @__PURE__ */ new Set());
20
- const suppressTokenCacheNotificationsRef = (0, react.useRef)(false);
20
+ const suppressTokenCacheNotificationsRef = (0, react.useRef)(0);
21
21
  const nativeRefreshFromJsControllerRef = (0, react.useRef)(null);
22
22
  const syncableTokenCache = (0, src_provider_nativeClientSync.useSyncableTokenCache)({
23
23
  suppressTokenCacheNotificationsRef,
@@ -1 +1 @@
1
- {"version":3,"file":"ClerkProvider.js","names":["ClerkReactProvider","NativeClientSync"],"sources":["../../src/provider/ClerkProvider.tsx"],"sourcesContent":["import '../polyfills';\n\nimport type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ClerkReactProvider, type Ui } from '@clerk/react/internal';\nimport { useRef } from 'react';\n\nimport type { TokenCache } from '../cache/types';\nimport { isNative, isWeb } from '../utils/runtime';\nimport { maybeCompleteAuthSession } from './maybeCompleteAuthSession';\nimport {\n type ClientTokenCacheListener,\n NativeClientSync,\n type NativeRefreshFromJsController,\n useNativeClientBootstrap,\n useNativeClientEventSync,\n useSyncableTokenCache,\n} from './nativeClientSync';\nimport { getClerkInstance } from './singleton';\nimport type { BuildClerkOptions } from './singleton/types';\n\nexport type ClerkProviderProps<TUi extends Ui = Ui> = Omit<ReactClerkProviderProps<TUi>, 'publishableKey'> & {\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n * This is required for React Native / Expo apps. Environment variables inside node_modules\n * are not inlined during production builds, so the key must be passed explicitly.\n *\n * @example\n * ```tsx\n * const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!;\n * <ClerkProvider publishableKey={publishableKey}>\n * ```\n */\n publishableKey: string;\n /**\n * The token cache is used to persist the active user's session token. Clerk stores this token in memory by default, however it is recommended to use a token cache for production applications.\n * @see https://clerk.com/docs/quickstarts/expo#configure-the-token-cache-with-expo\n */\n tokenCache?: TokenCache;\n /**\n * Note: Passkey support in Expo is currently in a limited rollout phase.\n * If you're interested in using this feature, please contact us for early access or additional details.\n *\n * @experimental This API is experimental and may change at any moment.\n */\n __experimental_passkeys?: BuildClerkOptions['__experimental_passkeys'];\n /**\n * This cache is used to store the resources that Clerk fetches from the server when the network is offline.\n *\n * @experimental This API is experimental and may change at any moment.\n */\n __experimental_resourceCache?: BuildClerkOptions['__experimental_resourceCache'];\n};\n\nconst SDK_METADATA = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n};\n\nexport function ClerkProvider<TUi extends Ui = Ui>(props: ClerkProviderProps<TUi>): JSX.Element {\n const {\n children,\n tokenCache,\n publishableKey,\n proxyUrl,\n domain,\n __experimental_passkeys,\n experimental,\n __experimental_resourceCache,\n ...rest\n } = props;\n const pk = publishableKey;\n const tokenCacheListenersRef = useRef<Set<ClientTokenCacheListener>>(new Set());\n const suppressTokenCacheNotificationsRef = useRef(false);\n const nativeRefreshFromJsControllerRef = useRef<NativeRefreshFromJsController | null>(null);\n const syncableTokenCache = useSyncableTokenCache({\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n });\n\n const clerkInstance = isNative()\n ? getClerkInstance({\n publishableKey: pk,\n tokenCache: syncableTokenCache,\n proxyUrl,\n domain,\n __experimental_passkeys,\n __experimental_resourceCache,\n })\n : null;\n\n const suppressJsClientChangedRef = useRef(0);\n const isMountedRef = useNativeClientBootstrap({\n publishableKey: pk,\n suppressTokenCacheNotificationsRef,\n tokenCache: syncableTokenCache,\n clerkInstance,\n });\n useNativeClientEventSync({\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache: syncableTokenCache,\n });\n\n // Needed for `useOAuth` / `useSSO` to work correctly on web — must stay synchronous during render\n // so the redirect URL is caught before children mount. Resolves to a no-op on native via the\n // sibling `maybeCompleteAuthSession.ts`, which keeps Metro from statically bundling\n // `expo-web-browser` (an optional peer) for native consumers.\n if (isWeb()) {\n maybeCompleteAuthSession();\n }\n\n return (\n <ClerkReactProvider\n // Force reset the state when the provided key changes, this ensures that the provider does not retain stale state.\n // See JS-598 for additional context.\n key={pk}\n {...rest}\n publishableKey={pk}\n proxyUrl={proxyUrl}\n domain={domain}\n sdkMetadata={SDK_METADATA}\n Clerk={clerkInstance}\n standardBrowser={!isNative()}\n experimental={{\n ...experimental,\n // force the rethrowOfflineNetworkErrors flag to true if the asyncStorage is provided\n rethrowOfflineNetworkErrors: !!__experimental_resourceCache || experimental?.rethrowOfflineNetworkErrors,\n ...(isNative() && { runtimeEnvironment: 'headless' as const }),\n }}\n >\n {isNative() && (\n <NativeClientSync\n clerkInstance={clerkInstance}\n nativeRefreshFromJsControllerRef={nativeRefreshFromJsControllerRef}\n suppressJsClientChangedRef={suppressJsClientChangedRef}\n suppressTokenCacheNotificationsRef={suppressTokenCacheNotificationsRef}\n tokenCache={syncableTokenCache}\n tokenCacheListenersRef={tokenCacheListenersRef}\n />\n )}\n {children}\n </ClerkReactProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAqDA,MAAM,eAAe;CACnB;CACA;AACF;AAEA,SAAgB,cAAmC,OAA6C;CAC9F,MAAM,EACJ,UACA,YACA,gBACA,UACA,QACA,yBACA,cACA,8BACA,GAAG,SACD;CACJ,MAAM,KAAK;CACX,MAAM,2DAA+D,IAAI,IAAI,CAAC;CAC9E,MAAM,uDAA4C,KAAK;CACvD,MAAM,qDAAgF,IAAI;CAC1F,MAAM,8EAA2C;EAC/C;EACA;EACA;CACF,CAAC;CAED,MAAM,gDAAyB,iDACV;EACf,gBAAgB;EAChB,YAAY;EACZ;EACA;EACA;EACA;CACF,CAAC,IACD;CAEJ,MAAM,+CAAoC,CAAC;CAO3C,4DAAyB;EACvB;EACA,0EAR4C;GAC5C,gBAAgB;GAChB;GACA,YAAY;GACZ;EACF,CAGa;EACX;EACA;EACA;EACA,YAAY;CACd,CAAC;CAMD,iCAAU,GACR,oEAAyB;CAG3B,OACE,4CAACA,6CAAD;EAIE,GAAI;EACJ,gBAAgB;EACN;EACF;EACR,aAAa;EACb,OAAO;EACP,iBAAiB,iCAAU;EAC3B,cAAc;GACZ,GAAG;GAEH,6BAA6B,CAAC,CAAC,gCAAgC,cAAc;GAC7E,mCAAa,KAAK,EAAE,oBAAoB,WAAoB;EAC9D;YAhBF,iCAkBY,KACR,2CAACC,gDAAD;GACiB;GACmB;GACN;GACQ;GACpC,YAAY;GACY;EACzB,IAEF,QACiB;IA1Bb,EA0Ba;AAExB"}
1
+ {"version":3,"file":"ClerkProvider.js","names":["ClerkReactProvider","NativeClientSync"],"sources":["../../src/provider/ClerkProvider.tsx"],"sourcesContent":["import '../polyfills';\n\nimport type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react';\nimport { InternalClerkProvider as ClerkReactProvider, type Ui } from '@clerk/react/internal';\nimport { useRef } from 'react';\n\nimport type { TokenCache } from '../cache/types';\nimport { isNative, isWeb } from '../utils/runtime';\nimport { maybeCompleteAuthSession } from './maybeCompleteAuthSession';\nimport {\n type DeviceTokenCacheListener,\n NativeClientSync,\n type NativeRefreshFromJsController,\n useNativeClientBootstrap,\n useNativeClientEventSync,\n useSyncableTokenCache,\n} from './nativeClientSync';\nimport { getClerkInstance } from './singleton';\nimport type { BuildClerkOptions } from './singleton/types';\n\nexport type ClerkProviderProps<TUi extends Ui = Ui> = Omit<ReactClerkProviderProps<TUi>, 'publishableKey'> & {\n /**\n * Your Clerk publishable key, available in the Clerk Dashboard.\n * This is required for React Native / Expo apps. Environment variables inside node_modules\n * are not inlined during production builds, so the key must be passed explicitly.\n *\n * @example\n * ```tsx\n * const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!;\n * <ClerkProvider publishableKey={publishableKey}>\n * ```\n */\n publishableKey: string;\n /**\n * The token cache is used to persist the active user's session token. Clerk stores this token in memory by default, however it is recommended to use a token cache for production applications.\n * @see https://clerk.com/docs/quickstarts/expo#configure-the-token-cache-with-expo\n */\n tokenCache?: TokenCache;\n /**\n * Note: Passkey support in Expo is currently in a limited rollout phase.\n * If you're interested in using this feature, please contact us for early access or additional details.\n *\n * @experimental This API is experimental and may change at any moment.\n */\n __experimental_passkeys?: BuildClerkOptions['__experimental_passkeys'];\n /**\n * This cache is used to store the resources that Clerk fetches from the server when the network is offline.\n *\n * @experimental This API is experimental and may change at any moment.\n */\n __experimental_resourceCache?: BuildClerkOptions['__experimental_resourceCache'];\n};\n\nconst SDK_METADATA = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n};\n\nexport function ClerkProvider<TUi extends Ui = Ui>(props: ClerkProviderProps<TUi>): JSX.Element {\n const {\n children,\n tokenCache,\n publishableKey,\n proxyUrl,\n domain,\n __experimental_passkeys,\n experimental,\n __experimental_resourceCache,\n ...rest\n } = props;\n const pk = publishableKey;\n const tokenCacheListenersRef = useRef<Set<DeviceTokenCacheListener>>(new Set());\n const suppressTokenCacheNotificationsRef = useRef(0);\n const nativeRefreshFromJsControllerRef = useRef<NativeRefreshFromJsController | null>(null);\n const syncableTokenCache = useSyncableTokenCache({\n suppressTokenCacheNotificationsRef,\n tokenCache,\n tokenCacheListenersRef,\n });\n\n const clerkInstance = isNative()\n ? getClerkInstance({\n publishableKey: pk,\n tokenCache: syncableTokenCache,\n proxyUrl,\n domain,\n __experimental_passkeys,\n __experimental_resourceCache,\n })\n : null;\n\n const suppressJsClientChangedRef = useRef(0);\n const isMountedRef = useNativeClientBootstrap({\n publishableKey: pk,\n suppressTokenCacheNotificationsRef,\n tokenCache: syncableTokenCache,\n clerkInstance,\n });\n useNativeClientEventSync({\n clerkInstance,\n isMountedRef,\n nativeRefreshFromJsControllerRef,\n suppressJsClientChangedRef,\n suppressTokenCacheNotificationsRef,\n tokenCache: syncableTokenCache,\n });\n\n // Needed for `useOAuth` / `useSSO` to work correctly on web — must stay synchronous during render\n // so the redirect URL is caught before children mount. Resolves to a no-op on native via the\n // sibling `maybeCompleteAuthSession.ts`, which keeps Metro from statically bundling\n // `expo-web-browser` (an optional peer) for native consumers.\n if (isWeb()) {\n maybeCompleteAuthSession();\n }\n\n return (\n <ClerkReactProvider\n // Force reset the state when the provided key changes, this ensures that the provider does not retain stale state.\n // See JS-598 for additional context.\n key={pk}\n {...rest}\n publishableKey={pk}\n proxyUrl={proxyUrl}\n domain={domain}\n sdkMetadata={SDK_METADATA}\n Clerk={clerkInstance}\n standardBrowser={!isNative()}\n experimental={{\n ...experimental,\n // force the rethrowOfflineNetworkErrors flag to true if the asyncStorage is provided\n rethrowOfflineNetworkErrors: !!__experimental_resourceCache || experimental?.rethrowOfflineNetworkErrors,\n ...(isNative() && { runtimeEnvironment: 'headless' as const }),\n }}\n >\n {isNative() && (\n <NativeClientSync\n clerkInstance={clerkInstance}\n nativeRefreshFromJsControllerRef={nativeRefreshFromJsControllerRef}\n suppressJsClientChangedRef={suppressJsClientChangedRef}\n suppressTokenCacheNotificationsRef={suppressTokenCacheNotificationsRef}\n tokenCache={syncableTokenCache}\n tokenCacheListenersRef={tokenCacheListenersRef}\n />\n )}\n {children}\n </ClerkReactProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAqDA,MAAM,eAAe;CACnB;CACA;AACF;AAEA,SAAgB,cAAmC,OAA6C;CAC9F,MAAM,EACJ,UACA,YACA,gBACA,UACA,QACA,yBACA,cACA,8BACA,GAAG,SACD;CACJ,MAAM,KAAK;CACX,MAAM,2DAA+D,IAAI,IAAI,CAAC;CAC9E,MAAM,uDAA4C,CAAC;CACnD,MAAM,qDAAgF,IAAI;CAC1F,MAAM,8EAA2C;EAC/C;EACA;EACA;CACF,CAAC;CAED,MAAM,gDAAyB,iDACV;EACf,gBAAgB;EAChB,YAAY;EACZ;EACA;EACA;EACA;CACF,CAAC,IACD;CAEJ,MAAM,+CAAoC,CAAC;CAO3C,4DAAyB;EACvB;EACA,0EAR4C;GAC5C,gBAAgB;GAChB;GACA,YAAY;GACZ;EACF,CAGa;EACX;EACA;EACA;EACA,YAAY;CACd,CAAC;CAMD,iCAAU,GACR,oEAAyB;CAG3B,OACE,4CAACA,6CAAD;EAIE,GAAI;EACJ,gBAAgB;EACN;EACF;EACR,aAAa;EACb,OAAO;EACP,iBAAiB,iCAAU;EAC3B,cAAc;GACZ,GAAG;GAEH,6BAA6B,CAAC,CAAC,gCAAgC,cAAc;GAC7E,mCAAa,KAAK,EAAE,oBAAoB,WAAoB;EAC9D;YAhBF,iCAkBY,KACR,2CAACC,gDAAD;GACiB;GACmB;GACN;GACQ;GACpC,YAAY;GACY;EACzB,IAEF,QACiB;IA1Bb,EA0Ba;AAExB"}
@@ -23,11 +23,11 @@ export type SyncableClerkInstance = {
23
23
  export type NativeRefreshFromJsController = {
24
24
  cancel: () => void;
25
25
  };
26
- export type ClientTokenCacheListener = (clientToken: string | null) => void;
26
+ export type DeviceTokenCacheListener = (deviceToken: string | null) => void;
27
27
  export declare function useSyncableTokenCache({ suppressTokenCacheNotificationsRef, tokenCache, tokenCacheListenersRef, }: {
28
- suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;
28
+ suppressTokenCacheNotificationsRef: MutableRefObject<number>;
29
29
  tokenCache: TokenCache | undefined;
30
- tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;
30
+ tokenCacheListenersRef: MutableRefObject<Set<DeviceTokenCacheListener>>;
31
31
  }): TokenCache | undefined;
32
32
  /**
33
33
  * Syncs JS SDK client changes to the native Clerk SDK so native components
@@ -40,13 +40,13 @@ export declare function NativeClientSync({ clerkInstance, nativeRefreshFromJsCon
40
40
  clerkInstance: SyncableClerkInstance | null | undefined;
41
41
  nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;
42
42
  suppressJsClientChangedRef: MutableRefObject<number>;
43
- suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;
43
+ suppressTokenCacheNotificationsRef: MutableRefObject<number>;
44
44
  tokenCache: TokenCache | undefined;
45
- tokenCacheListenersRef: MutableRefObject<Set<ClientTokenCacheListener>>;
45
+ tokenCacheListenersRef: MutableRefObject<Set<DeviceTokenCacheListener>>;
46
46
  }): null;
47
47
  export declare function useNativeClientBootstrap({ publishableKey, suppressTokenCacheNotificationsRef, tokenCache, clerkInstance, }: {
48
48
  publishableKey: string;
49
- suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;
49
+ suppressTokenCacheNotificationsRef: MutableRefObject<number>;
50
50
  tokenCache: TokenCache | undefined;
51
51
  clerkInstance: SyncableClerkInstance | null | undefined;
52
52
  }): MutableRefObject<boolean>;
@@ -55,7 +55,7 @@ export declare function useNativeClientEventSync({ clerkInstance, isMountedRef,
55
55
  isMountedRef: MutableRefObject<boolean>;
56
56
  nativeRefreshFromJsControllerRef: MutableRefObject<NativeRefreshFromJsController | null>;
57
57
  suppressJsClientChangedRef: MutableRefObject<number>;
58
- suppressTokenCacheNotificationsRef: MutableRefObject<boolean>;
58
+ suppressTokenCacheNotificationsRef: MutableRefObject<number>;
59
59
  tokenCache: TokenCache | undefined;
60
60
  }): void;
61
61
  //# sourceMappingURL=nativeClientSync.d.ts.map
@@ -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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"}
@@ -8,8 +8,8 @@ let src_hooks_useNativeClientEvents = require("../hooks/useNativeClientEvents");
8
8
 
9
9
  //#region src/provider/nativeClientSync.tsx
10
10
  const tokenCacheReadTimeoutMs = 1e3;
11
- const clientTokenPollIntervalMs = 100;
12
- const clientTokenAvailabilityTimeoutMs = 3e3;
11
+ const nativeDeviceTokenPollIntervalMs = 100;
12
+ const nativeDeviceTokenAvailabilityTimeoutMs = 3e3;
13
13
  const nativeClientSyncSourceIdPrefix = "clerk-expo-js-sync";
14
14
  function delay(ms) {
15
15
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -18,19 +18,19 @@ function useSyncableTokenCache({ suppressTokenCacheNotificationsRef, tokenCache,
18
18
  return (0, react.useMemo)(() => {
19
19
  const effectiveTokenCache = tokenCache ?? (react_native.Platform.OS === "ios" || react_native.Platform.OS === "android" ? src_cache.MemoryTokenCache : void 0);
20
20
  if (!effectiveTokenCache) return;
21
- const notifyClientTokenListeners = (clientToken) => {
22
- if (suppressTokenCacheNotificationsRef.current) return;
23
- for (const listener of tokenCacheListenersRef.current) listener(clientToken);
21
+ const notifyDeviceTokenListeners = (deviceToken) => {
22
+ if (suppressTokenCacheNotificationsRef.current > 0) return;
23
+ for (const listener of tokenCacheListenersRef.current) listener(deviceToken);
24
24
  };
25
25
  return {
26
26
  getToken: (key) => effectiveTokenCache.getToken(key),
27
27
  saveToken: async (key, token) => {
28
28
  await effectiveTokenCache.saveToken(key, token);
29
- if (key === src_constants.CLERK_CLIENT_JWT_KEY) notifyClientTokenListeners(token);
29
+ if (key === src_constants.CLERK_CLIENT_JWT_KEY) notifyDeviceTokenListeners(token);
30
30
  },
31
31
  clearToken: async (key) => {
32
32
  await effectiveTokenCache.clearToken?.(key);
33
- if (key === src_constants.CLERK_CLIENT_JWT_KEY) notifyClientTokenListeners(null);
33
+ if (key === src_constants.CLERK_CLIENT_JWT_KEY) notifyDeviceTokenListeners(null);
34
34
  }
35
35
  };
36
36
  }, [
@@ -39,50 +39,46 @@ function useSyncableTokenCache({ suppressTokenCacheNotificationsRef, tokenCache,
39
39
  tokenCacheListenersRef
40
40
  ]);
41
41
  }
42
- function getNativeClientTokenFromSnapshot(snapshot) {
43
- if (!snapshot || !("clientToken" in snapshot)) return;
44
- return snapshot.clientToken ?? null;
45
- }
46
- async function readNativeClientToken({ waitForToken }) {
42
+ async function readNativeDeviceToken({ waitForToken }) {
47
43
  const ClerkExpo = src_utils_native_module.ClerkExpoModule;
48
44
  if (!ClerkExpo?.getClientToken) return null;
49
45
  const startedAt = Date.now();
50
- let remainingMs = clientTokenAvailabilityTimeoutMs;
46
+ let remainingMs = nativeDeviceTokenAvailabilityTimeoutMs;
51
47
  do {
52
- const nativeClientToken = await ClerkExpo.getClientToken();
53
- if (nativeClientToken) return nativeClientToken;
48
+ const nativeDeviceToken = await ClerkExpo.getClientToken();
49
+ if (nativeDeviceToken) return nativeDeviceToken;
54
50
  if (!waitForToken) return null;
55
- remainingMs = clientTokenAvailabilityTimeoutMs - (Date.now() - startedAt);
51
+ remainingMs = nativeDeviceTokenAvailabilityTimeoutMs - (Date.now() - startedAt);
56
52
  if (remainingMs <= 0) return null;
57
- await delay(Math.min(clientTokenPollIntervalMs, remainingMs));
53
+ await delay(Math.min(nativeDeviceTokenPollIntervalMs, remainingMs));
58
54
  } while (remainingMs > 0);
59
55
  return null;
60
56
  }
61
- async function syncClientTokenToCache(tokenCache, clientToken) {
62
- if (clientToken) {
63
- await tokenCache?.saveToken(src_constants.CLERK_CLIENT_JWT_KEY, clientToken);
57
+ async function syncDeviceTokenToCache(tokenCache, deviceToken) {
58
+ if (deviceToken) {
59
+ await tokenCache?.saveToken(src_constants.CLERK_CLIENT_JWT_KEY, deviceToken);
64
60
  return;
65
61
  }
66
62
  await tokenCache?.clearToken?.(src_constants.CLERK_CLIENT_JWT_KEY);
67
63
  }
68
- async function syncClientTokenToCacheWithoutNotifying({ clientToken, suppressTokenCacheNotificationsRef, tokenCache }) {
69
- suppressTokenCacheNotificationsRef.current = true;
64
+ async function syncDeviceTokenToCacheWithoutNotifying({ deviceToken, suppressTokenCacheNotificationsRef, tokenCache }) {
65
+ suppressTokenCacheNotificationsRef.current += 1;
70
66
  try {
71
- await syncClientTokenToCache(tokenCache, clientToken);
67
+ await syncDeviceTokenToCache(tokenCache, deviceToken);
72
68
  } finally {
73
- suppressTokenCacheNotificationsRef.current = false;
69
+ suppressTokenCacheNotificationsRef.current = Math.max(0, suppressTokenCacheNotificationsRef.current - 1);
74
70
  }
75
71
  }
76
- async function syncNativeTokenToCache({ clientToken, suppressTokenCacheNotificationsRef, tokenCache }) {
72
+ async function syncNativeDeviceTokenToCache({ deviceToken, suppressTokenCacheNotificationsRef, tokenCache }) {
77
73
  if (suppressTokenCacheNotificationsRef) {
78
- await syncClientTokenToCacheWithoutNotifying({
79
- clientToken,
74
+ await syncDeviceTokenToCacheWithoutNotifying({
75
+ deviceToken,
80
76
  suppressTokenCacheNotificationsRef,
81
77
  tokenCache
82
78
  });
83
79
  return;
84
80
  }
85
- await syncClientTokenToCache(tokenCache, clientToken);
81
+ await syncDeviceTokenToCache(tokenCache, deviceToken);
86
82
  }
87
83
  function getDefaultSignedInSession(client) {
88
84
  if (!client) return null;
@@ -92,21 +88,20 @@ function getDefaultSignedInSession(client) {
92
88
  }
93
89
  return client.signedInSessions[0] ?? null;
94
90
  }
95
- async function refreshJsClientWithoutEmitting(clerkInstance) {
91
+ async function refreshJsClientFromServer(clerkInstance) {
96
92
  const client = clerkInstance.client;
97
93
  if (typeof client?.fetch !== "function" || typeof clerkInstance.updateClient !== "function") return null;
98
94
  const refreshedClient = await client.fetch({ fetchMaxTries: 1 });
99
- const nextSession = getDefaultSignedInSession(refreshedClient);
100
- clerkInstance.updateClient(refreshedClient, { __internal_dangerouslySkipEmit: Boolean(nextSession) });
95
+ clerkInstance.updateClient(refreshedClient);
101
96
  return refreshedClient;
102
97
  }
103
- async function refreshJsClientFromNativeState({ clerkInstance, nativeClientToken, reloadInitialResources, suppressTokenCacheNotificationsRef, tokenCache }) {
104
- await syncNativeTokenToCache({
105
- clientToken: nativeClientToken,
98
+ async function refreshJsClientFromNativeState({ clerkInstance, nativeDeviceToken, reloadInitialResources, shouldSyncDeviceToken = true, suppressTokenCacheNotificationsRef, tokenCache }) {
99
+ if (shouldSyncDeviceToken) await syncNativeDeviceTokenToCache({
100
+ deviceToken: nativeDeviceToken,
106
101
  suppressTokenCacheNotificationsRef,
107
102
  tokenCache
108
103
  });
109
- if (await refreshJsClientWithoutEmitting(clerkInstance)) {
104
+ if (await refreshJsClientFromServer(clerkInstance)) {
110
105
  await reconcileJsActiveSessionFromClient({ clerkInstance });
111
106
  return true;
112
107
  }
@@ -117,9 +112,9 @@ async function refreshJsClientFromNativeState({ clerkInstance, nativeClientToken
117
112
  }
118
113
  return false;
119
114
  }
120
- async function reloadJsClientFromNativeState({ clerkInstance, nativeClientToken, suppressTokenCacheNotificationsRef, tokenCache }) {
121
- await syncNativeTokenToCache({
122
- clientToken: nativeClientToken,
115
+ async function reloadJsClientFromNativeState({ clerkInstance, nativeDeviceToken, suppressTokenCacheNotificationsRef, tokenCache }) {
116
+ await syncNativeDeviceTokenToCache({
117
+ deviceToken: nativeDeviceToken,
123
118
  suppressTokenCacheNotificationsRef,
124
119
  tokenCache
125
120
  });
@@ -127,13 +122,13 @@ async function reloadJsClientFromNativeState({ clerkInstance, nativeClientToken,
127
122
  await reconcileJsActiveSessionFromClient({ clerkInstance });
128
123
  return Boolean(getDefaultSignedInSession(clerkInstance.client));
129
124
  }
130
- async function recoverJsClientFromNativeToken({ clerkInstance, error, suppressTokenCacheNotificationsRef, tokenCache }) {
131
- const nativeClientToken = await readNativeClientToken({ waitForToken: false });
132
- if (!nativeClientToken) return false;
125
+ async function recoverJsClientFromNativeDeviceToken({ clerkInstance, error, suppressTokenCacheNotificationsRef, tokenCache }) {
126
+ const nativeDeviceToken = await readNativeDeviceToken({ waitForToken: false });
127
+ if (!nativeDeviceToken) return false;
133
128
  try {
134
129
  return await reloadJsClientFromNativeState({
135
130
  clerkInstance,
136
- nativeClientToken,
131
+ nativeDeviceToken,
137
132
  suppressTokenCacheNotificationsRef,
138
133
  tokenCache
139
134
  });
@@ -159,12 +154,15 @@ async function runWithSuppressedJsClientChanges(suppressJsClientChangedRef, task
159
154
  }
160
155
  function mergePendingNativeRefreshOptions(current, next) {
161
156
  if (!current) return next;
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;
157
+ const merged = {
158
+ didChangeClient: current.didChangeClient || next.didChangeClient,
159
+ didChangeDeviceToken: current.didChangeDeviceToken || next.didChangeDeviceToken
160
+ };
161
+ if ("deviceToken" in current) merged.deviceToken = current.deviceToken ?? null;
162
+ if ("deviceToken" in next) merged.deviceToken = next.deviceToken ?? null;
165
163
  return merged;
166
164
  }
167
- async function getCachedClientToken(tokenCache) {
165
+ async function getCachedDeviceToken(tokenCache) {
168
166
  if (!tokenCache) return null;
169
167
  let timeoutId;
170
168
  try {
@@ -176,15 +174,18 @@ async function getCachedClientToken(tokenCache) {
176
174
  }
177
175
  }
178
176
  async function syncNativeClientToJs({ clerkInstance, nativeRefreshFromJsControllerRef, nativeClientEvent, suppressJsClientChangedRef, suppressTokenCacheNotificationsRef, tokenCache }) {
179
- const nativeClientTokenFromEvent = getNativeClientTokenFromSnapshot(nativeClientEvent);
180
- const nativeClientToken = nativeClientTokenFromEvent !== void 0 ? nativeClientTokenFromEvent : await readNativeClientToken({ waitForToken: !nativeClientEvent });
181
- if (!nativeClientToken && !nativeClientEvent) return;
177
+ const didChangeClient = nativeClientEvent?.changed.client ?? true;
178
+ const didChangeDeviceToken = nativeClientEvent?.changed.deviceToken ?? true;
179
+ if (!didChangeClient && !didChangeDeviceToken) return;
180
+ const nativeDeviceToken = nativeClientEvent ? nativeClientEvent.deviceToken : await readNativeDeviceToken({ waitForToken: true });
181
+ if (!nativeDeviceToken && !nativeClientEvent) return;
182
182
  await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {
183
183
  nativeRefreshFromJsControllerRef?.current?.cancel();
184
184
  await refreshJsClientFromNativeState({
185
185
  clerkInstance,
186
- nativeClientToken,
186
+ nativeDeviceToken,
187
187
  reloadInitialResources: true,
188
+ shouldSyncDeviceToken: didChangeDeviceToken,
188
189
  suppressTokenCacheNotificationsRef,
189
190
  tokenCache
190
191
  });
@@ -236,7 +237,11 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
236
237
  });
237
238
  return;
238
239
  }
239
- originalUpdateClient(newClient, options);
240
+ if (options) {
241
+ originalUpdateClient(newClient, options);
242
+ return;
243
+ }
244
+ originalUpdateClient(newClient);
240
245
  };
241
246
  clerkInstance.updateClient = updateClient;
242
247
  return () => {
@@ -255,10 +260,10 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
255
260
  const refreshNativeFromJsClient = async (options, generation) => {
256
261
  const ClerkExpo = src_utils_native_module.ClerkExpoModule;
257
262
  if (!ClerkExpo || generation !== nativeRefreshGenerationRef.current) return;
258
- const bearerToken = "clientToken" in options ? options.clientToken ?? null : null;
263
+ const deviceToken = options.didChangeDeviceToken ? options.deviceToken ?? null : null;
259
264
  if (generation !== nativeRefreshGenerationRef.current) return;
260
265
  const sourceId = `${nativeClientSyncSourceIdPrefix}-${generation}`;
261
- await ClerkExpo.syncFromJsClientToken(bearerToken, sourceId, options.shouldRefreshClient);
266
+ await ClerkExpo.syncClientStateFromJs(deviceToken, sourceId, options.didChangeClient, options.didChangeDeviceToken);
262
267
  };
263
268
  let latestRunGeneration = initialGeneration;
264
269
  (async () => {
@@ -270,7 +275,10 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
270
275
  try {
271
276
  await refreshNativeFromJsClient(pendingOptions, generation);
272
277
  } catch (error) {}
273
- pendingOptions = pendingNativeRefreshRef.current ?? { shouldRefreshClient: false };
278
+ pendingOptions = pendingNativeRefreshRef.current ?? {
279
+ didChangeClient: false,
280
+ didChangeDeviceToken: false
281
+ };
274
282
  if (pendingNativeRefreshRef.current !== null) {
275
283
  generation = nativeRefreshGenerationRef.current + 1;
276
284
  nativeRefreshGenerationRef.current = generation;
@@ -281,10 +289,11 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
281
289
  });
282
290
  }, []);
283
291
  (0, react.useEffect)(() => {
284
- const listener = (clientToken) => {
292
+ const listener = (deviceToken) => {
285
293
  queueNativeRefreshFromJs({
286
- clientToken,
287
- shouldRefreshClient: clientToken === null
294
+ deviceToken,
295
+ didChangeClient: false,
296
+ didChangeDeviceToken: true
288
297
  });
289
298
  };
290
299
  const tokenCacheListeners = tokenCacheListenersRef.current;
@@ -305,13 +314,13 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
305
314
  try {
306
315
  if (await refreshJsClientFromNativeState({
307
316
  clerkInstance,
308
- nativeClientToken: await readNativeClientToken({ waitForToken: false }),
317
+ nativeDeviceToken: await readNativeDeviceToken({ waitForToken: false }),
309
318
  reloadInitialResources: false,
310
319
  suppressTokenCacheNotificationsRef,
311
320
  tokenCache
312
321
  })) return;
313
322
  } catch (error) {
314
- if (await recoverJsClientFromNativeToken({
323
+ if (await recoverJsClientFromNativeDeviceToken({
315
324
  clerkInstance,
316
325
  error,
317
326
  suppressTokenCacheNotificationsRef,
@@ -338,7 +347,10 @@ function NativeClientSync({ clerkInstance, nativeRefreshFromJsControllerRef, sup
338
347
  if (!clerkInstance || typeof clerkInstance.addListener !== "function") return;
339
348
  const unsubscribe = clerkInstance.addListener(() => {
340
349
  if (suppressJsClientChangedRef.current > 0) return;
341
- queueNativeRefreshFromJs({ shouldRefreshClient: true });
350
+ queueNativeRefreshFromJs({
351
+ didChangeClient: true,
352
+ didChangeDeviceToken: false
353
+ });
342
354
  }, { skipInitialEmit: true });
343
355
  return () => {
344
356
  unsubscribe();
@@ -368,12 +380,12 @@ function useNativeClientBootstrap({ publishableKey, suppressTokenCacheNotificati
368
380
  if (ClerkExpo?.configure) {
369
381
  await ClerkExpo.configure(publishableKey, null);
370
382
  if (!isMountedRef.current) return;
371
- let bearerToken = null;
383
+ let cachedDeviceToken = null;
372
384
  try {
373
- bearerToken = await getCachedClientToken(tokenCache);
385
+ cachedDeviceToken = await getCachedDeviceToken(tokenCache);
374
386
  } catch (e) {}
375
- if (bearerToken) {
376
- await ClerkExpo.configure(publishableKey, bearerToken);
387
+ if (cachedDeviceToken) {
388
+ await ClerkExpo.configure(publishableKey, cachedDeviceToken);
377
389
  if (!isMountedRef.current) return;
378
390
  }
379
391
  if (clerkInstance) {
@@ -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 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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"}
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 { type NativeClientEvent, useNativeClientEvents } from '../hooks/useNativeClientEvents';\nimport { ClerkExpoModule as NativeClerkModule } from '../utils/native-module';\n\nconst tokenCacheReadTimeoutMs = 1_000;\nconst nativeDeviceTokenPollIntervalMs = 100;\nconst nativeDeviceTokenAvailabilityTimeoutMs = 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 deviceToken?: string | null;\n didChangeClient: boolean;\n didChangeDeviceToken: boolean;\n};\n\nexport type NativeRefreshFromJsController = {\n cancel: () => void;\n};\n\nexport type DeviceTokenCacheListener = (deviceToken: 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<number>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<DeviceTokenCacheListener>>;\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 notifyDeviceTokenListeners = (deviceToken: string | null) => {\n if (suppressTokenCacheNotificationsRef.current > 0) {\n return;\n }\n\n for (const listener of tokenCacheListenersRef.current) {\n listener(deviceToken);\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 notifyDeviceTokenListeners(token);\n }\n },\n clearToken: async key => {\n await effectiveTokenCache.clearToken?.(key);\n if (key === CLERK_CLIENT_JWT_KEY) {\n notifyDeviceTokenListeners(null);\n }\n },\n };\n }, [suppressTokenCacheNotificationsRef, tokenCache, tokenCacheListenersRef]);\n}\n\nasync function readNativeDeviceToken({ 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 = nativeDeviceTokenAvailabilityTimeoutMs;\n\n do {\n const nativeDeviceToken = await ClerkExpo.getClientToken();\n if (nativeDeviceToken) {\n return nativeDeviceToken;\n }\n\n if (!waitForToken) {\n return null;\n }\n\n remainingMs = nativeDeviceTokenAvailabilityTimeoutMs - (Date.now() - startedAt);\n if (remainingMs <= 0) {\n return null;\n }\n\n await delay(Math.min(nativeDeviceTokenPollIntervalMs, remainingMs));\n } while (remainingMs > 0);\n\n return null;\n}\n\nasync function syncDeviceTokenToCache(tokenCache: TokenCache | undefined, deviceToken: string | null): Promise<void> {\n if (deviceToken) {\n await tokenCache?.saveToken(CLERK_CLIENT_JWT_KEY, deviceToken);\n return;\n }\n\n await tokenCache?.clearToken?.(CLERK_CLIENT_JWT_KEY);\n}\n\nasync function syncDeviceTokenToCacheWithoutNotifying({\n deviceToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n deviceToken: string | null;\n suppressTokenCacheNotificationsRef: MutableRefObject<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n suppressTokenCacheNotificationsRef.current += 1;\n try {\n await syncDeviceTokenToCache(tokenCache, deviceToken);\n } finally {\n suppressTokenCacheNotificationsRef.current = Math.max(0, suppressTokenCacheNotificationsRef.current - 1);\n }\n}\n\nasync function syncNativeDeviceTokenToCache({\n deviceToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n deviceToken: string | null;\n suppressTokenCacheNotificationsRef?: MutableRefObject<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n if (suppressTokenCacheNotificationsRef) {\n await syncDeviceTokenToCacheWithoutNotifying({\n deviceToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n return;\n }\n\n await syncDeviceTokenToCache(tokenCache, deviceToken);\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 refreshJsClientFromServer(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 clerkInstance.updateClient(refreshedClient);\n\n return refreshedClient;\n}\n\nasync function refreshJsClientFromNativeState({\n clerkInstance,\n nativeDeviceToken,\n reloadInitialResources,\n shouldSyncDeviceToken = true,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeDeviceToken: string | null;\n reloadInitialResources: boolean;\n shouldSyncDeviceToken?: boolean;\n suppressTokenCacheNotificationsRef?: MutableRefObject<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n if (shouldSyncDeviceToken) {\n await syncNativeDeviceTokenToCache({\n deviceToken: nativeDeviceToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n }\n\n const refreshedClient = await refreshJsClientFromServer(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 nativeDeviceToken,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n nativeDeviceToken: string;\n suppressTokenCacheNotificationsRef?: MutableRefObject<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n await syncNativeDeviceTokenToCache({\n deviceToken: nativeDeviceToken,\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 recoverJsClientFromNativeDeviceToken({\n clerkInstance,\n error,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n}: {\n clerkInstance: SyncableClerkInstance;\n error: unknown;\n suppressTokenCacheNotificationsRef: MutableRefObject<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<boolean> {\n const nativeDeviceToken = await readNativeDeviceToken({ waitForToken: false });\n if (!nativeDeviceToken) {\n return false;\n }\n\n if (__DEV__) {\n console.warn('[NativeClientSync] Failed to refresh JS client with native device token:', error);\n }\n\n try {\n return await reloadJsClientFromNativeState({\n clerkInstance,\n nativeDeviceToken,\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 didChangeClient: current.didChangeClient || next.didChangeClient,\n didChangeDeviceToken: current.didChangeDeviceToken || next.didChangeDeviceToken,\n };\n\n if ('deviceToken' in current) {\n merged.deviceToken = current.deviceToken ?? null;\n }\n\n if ('deviceToken' in next) {\n merged.deviceToken = next.deviceToken ?? null;\n }\n\n return merged;\n}\n\nasync function getCachedDeviceToken(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<number>;\n tokenCache: TokenCache | undefined;\n}): Promise<void> {\n const didChangeClient = nativeClientEvent?.changed.client ?? true;\n const didChangeDeviceToken = nativeClientEvent?.changed.deviceToken ?? true;\n\n if (!didChangeClient && !didChangeDeviceToken) {\n return;\n }\n\n const nativeDeviceToken = nativeClientEvent\n ? nativeClientEvent.deviceToken\n : await readNativeDeviceToken({\n waitForToken: true,\n });\n\n if (!nativeDeviceToken && !nativeClientEvent) {\n return;\n }\n\n await runWithSuppressedJsClientChanges(suppressJsClientChangedRef, async () => {\n nativeRefreshFromJsControllerRef?.current?.cancel();\n\n await refreshJsClientFromNativeState({\n clerkInstance,\n nativeDeviceToken,\n reloadInitialResources: true,\n shouldSyncDeviceToken: didChangeDeviceToken,\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<number>;\n tokenCache: TokenCache | undefined;\n tokenCacheListenersRef: MutableRefObject<Set<DeviceTokenCacheListener>>;\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 if (options) {\n originalUpdateClient(newClient, options);\n return;\n }\n\n originalUpdateClient(newClient);\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 deviceToken = options.didChangeDeviceToken ? (options.deviceToken ?? null) : null;\n if (generation !== nativeRefreshGenerationRef.current) {\n return;\n }\n\n const sourceId = `${nativeClientSyncSourceIdPrefix}-${generation}`;\n await ClerkExpo.syncClientStateFromJs(\n deviceToken,\n sourceId,\n options.didChangeClient,\n options.didChangeDeviceToken,\n );\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 didChangeClient: false,\n didChangeDeviceToken: false,\n };\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: DeviceTokenCacheListener = deviceToken => {\n queueNativeRefreshFromJs({\n deviceToken,\n didChangeClient: false,\n didChangeDeviceToken: true,\n });\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 nativeDeviceToken = await readNativeDeviceToken({ 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 nativeDeviceToken,\n reloadInitialResources: false,\n suppressTokenCacheNotificationsRef,\n tokenCache,\n });\n if (didRecover) {\n return;\n }\n } catch (error) {\n const didRecover = await recoverJsClientFromNativeDeviceToken({\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 didChangeClient: true,\n didChangeDeviceToken: false,\n });\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<number>;\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 cachedDeviceToken: string | null = null;\n try {\n cachedDeviceToken = await getCachedDeviceToken(tokenCache);\n } catch (e) {\n if (__DEV__) {\n console.warn('[ClerkProvider] Token cache read failed:', e);\n }\n }\n\n if (cachedDeviceToken) {\n await ClerkExpo.configure(publishableKey, cachedDeviceToken);\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<number>;\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, shouldRefreshClient?: boolean): Promise<void>;
5
+ syncClientStateFromJs(deviceToken: string | null, sourceId: string | null, didChangeClient: boolean, didChangeDeviceToken: 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,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
+ {"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,eAAe,EAAE,OAAO,EACxB,oBAAoB,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(\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"}
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 syncClientStateFromJs(\n deviceToken: string | null,\n sourceId: string | null,\n didChangeClient: boolean,\n didChangeDeviceToken: boolean,\n ): Promise<void>;\n removeListeners?(count: number): void;\n}\n\nexport default requireNativeModule<Spec>('ClerkExpo');\n"],"mappings":";;;AAiBA,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, shouldRefreshClient?: boolean): Promise<void>;
6
+ syncClientStateFromJs(deviceToken: string | null, sourceId: string | null, didChangeClient: boolean, didChangeDeviceToken: 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,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
+ {"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,eAAe,EAAE,OAAO,EACxB,oBAAoB,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(\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
+ {"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 syncClientStateFromJs(\n deviceToken: string | null,\n sourceId: string | null,\n didChangeClient: boolean,\n didChangeDeviceToken: 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":";;;AAoBA,gCAAeA,iCAAoB,IAAU,WAAW"}
@@ -6,7 +6,7 @@ type ClerkExpoNativeModule = {
6
6
  configure(publishableKey: string, bearerToken: string | null): Promise<void>;
7
7
  getClientToken(): Promise<string | null>;
8
8
  removeListeners?(count: number): void;
9
- syncFromJsClientToken(clientToken: string | null, sourceId: string | null, shouldRefreshClient?: boolean): Promise<void>;
9
+ syncClientStateFromJs(deviceToken: string | null, sourceId: string | null, didChangeClient: boolean, didChangeDeviceToken: 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,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"}
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,eAAe,EAAE,OAAO,EACxB,oBAAoB,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.configure === "function" && typeof maybeModule.getClientToken === "function" && typeof maybeModule.syncFromJsClientToken === "function";
12
+ return typeof maybeModule.configure === "function" && typeof maybeModule.getClientToken === "function" && typeof maybeModule.syncClientStateFromJs === "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(\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"}
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 syncClientStateFromJs(\n deviceToken: string | null,\n sourceId: string | null,\n didChangeClient: boolean,\n didChangeDeviceToken: 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.syncClientStateFromJs === '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;AAe1E,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"}
@@ -11,9 +11,10 @@ RCT_EXTERN_METHOD(configure:(NSString *)publishableKey
11
11
  RCT_EXTERN_METHOD(getClientToken:(RCTPromiseResolveBlock)resolve
12
12
  reject:(RCTPromiseRejectBlock)reject)
13
13
 
14
- RCT_EXTERN_METHOD(syncFromJsClientToken:(id)clientToken
14
+ RCT_EXTERN_METHOD(syncClientStateFromJs:(id)deviceToken
15
15
  sourceId:(id)sourceId
16
- shouldRefreshClient:(id)shouldRefreshClient
16
+ didChangeClient:(BOOL)didChangeClient
17
+ didChangeDeviceToken:(BOOL)didChangeDeviceToken
17
18
  resolve:(RCTPromiseResolveBlock)resolve
18
19
  reject:(RCTPromiseRejectBlock)reject)
19
20
 
@@ -86,23 +86,23 @@ class ClerkExpoModule: RCTEventEmitter {
86
86
  }
87
87
  }
88
88
 
89
- // MARK: - syncFromJsClientToken
89
+ // MARK: - syncClientStateFromJs
90
90
 
91
- @objc func syncFromJsClientToken(_ clientToken: Any?,
91
+ @objc func syncClientStateFromJs(_ deviceToken: Any?,
92
92
  sourceId: Any?,
93
- shouldRefreshClient: Any?,
93
+ didChangeClient: Bool,
94
+ didChangeDeviceToken: Bool,
94
95
  resolve: @escaping RCTPromiseResolveBlock,
95
96
  reject: @escaping RCTPromiseRejectBlock) {
96
- let normalizedClientToken = clientToken as? String
97
+ let normalizedDeviceToken = deviceToken as? String
97
98
  let normalizedSourceId = sourceId as? String
98
- let defaultShouldRefreshClient = normalizedClientToken?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true
99
- let normalizedShouldRefreshClient = (shouldRefreshClient as? Bool) ?? defaultShouldRefreshClient
100
99
  Task {
101
100
  do {
102
- try await ClerkNativeBridge.shared.syncFromJsClientToken(
103
- normalizedClientToken,
101
+ try await ClerkNativeBridge.shared.syncClientStateFromJs(
102
+ deviceToken: normalizedDeviceToken,
104
103
  sourceId: normalizedSourceId,
105
- shouldRefreshClient: normalizedShouldRefreshClient
104
+ didChangeClient: didChangeClient,
105
+ didChangeDeviceToken: didChangeDeviceToken
106
106
  )
107
107
  resolve(nil)
108
108
  } catch {
@@ -56,6 +56,13 @@ final class ClerkNativeBridge {
56
56
  let deviceToken: String?
57
57
  }
58
58
 
59
+ private struct ClientStateChanges {
60
+ let client: Bool
61
+ let deviceToken: Bool
62
+
63
+ static let all = ClientStateChanges(client: true, deviceToken: true)
64
+ }
65
+
59
66
  /// Resolves the keychain service name, checking ClerkKeychainService in Info.plist first
60
67
  /// (for extension apps sharing a keychain group), then falling back to the bundle identifier.
61
68
  private static var keychainService: String? {
@@ -104,7 +111,7 @@ final class ClerkNativeBridge {
104
111
  @MainActor
105
112
  private static func emitClientChangedIfReceivedToken(_ bearerToken: String?) {
106
113
  guard let token = bearerToken, !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return }
107
- Self.emitClientChanged(Self.clientChangedPayload())
114
+ Self.emitClientChanged(Self.clientChangedPayload(changes: .init(client: false, deviceToken: true)))
108
115
  }
109
116
 
110
117
  @MainActor
@@ -130,9 +137,14 @@ final class ClerkNativeBridge {
130
137
  guard let self, generation == self.clientObservationGeneration else { return }
131
138
 
132
139
  let newClientState = Self.clientStateSnapshot()
133
- if newClientState != self.lastObservedClientState {
140
+ if let previousClientState = self.lastObservedClientState, newClientState != previousClientState {
134
141
  self.lastObservedClientState = newClientState
135
- let payload = Self.clientChangedPayload()
142
+ let payload = Self.clientChangedPayload(
143
+ changes: .init(
144
+ client: newClientState.client != previousClientState.client,
145
+ deviceToken: newClientState.deviceToken != previousClientState.deviceToken
146
+ )
147
+ )
136
148
  Self.emitClientChanged(payload)
137
149
  }
138
150
 
@@ -152,9 +164,13 @@ final class ClerkNativeBridge {
152
164
  }
153
165
 
154
166
  @MainActor
155
- private static func clientChangedPayload(sourceId: String? = nil) -> [String: Any] {
167
+ private static func clientChangedPayload(sourceId: String? = nil, changes: ClientStateChanges = .all) -> [String: Any] {
156
168
  var payload: [String: Any] = [:]
157
- payload["clientToken"] = Clerk.shared.deviceToken ?? NSNull()
169
+ payload["changed"] = [
170
+ "client": changes.client,
171
+ "deviceToken": changes.deviceToken,
172
+ ]
173
+ payload["deviceToken"] = Clerk.shared.deviceToken ?? NSNull()
158
174
  if let sourceId, !sourceId.isEmpty {
159
175
  payload["sourceId"] = sourceId
160
176
  }
@@ -187,7 +203,7 @@ final class ClerkNativeBridge {
187
203
  @MainActor
188
204
  private static func waitForLoadedClient() async {
189
205
  // Wait for Clerk to finish loading client state from cached data + API refresh.
190
- // The bridge sync contract is client-token based, not session based.
206
+ // The bridge sync contract is device-token based, not session based.
191
207
  for _ in 0..<clerkLoadMaxAttempts {
192
208
  if Clerk.shared.isLoaded {
193
209
  return
@@ -256,23 +272,39 @@ final class ClerkNativeBridge {
256
272
  }
257
273
 
258
274
  @MainActor
259
- func syncFromJsClientToken(_ clientToken: String?, sourceId: String?, shouldRefreshClient: Bool) async throws {
275
+ func syncClientStateFromJs(
276
+ deviceToken: String?,
277
+ sourceId: String?,
278
+ didChangeClient: Bool,
279
+ didChangeDeviceToken: Bool
280
+ ) async throws {
260
281
  guard Self.clerkConfigured else { return }
261
282
 
262
- if let token = clientToken?.trimmingCharacters(in: .whitespacesAndNewlines), !token.isEmpty {
283
+ let previousClientState = Self.clientStateSnapshot()
284
+
285
+ if didChangeDeviceToken, let token = deviceToken?.trimmingCharacters(in: .whitespacesAndNewlines), !token.isEmpty {
263
286
  if Clerk.shared.deviceToken != token {
264
287
  _ = try await Clerk.shared.updateDeviceToken(token)
265
288
  await Self.waitForLoadedClient()
266
289
  }
267
290
  }
268
291
 
269
- if shouldRefreshClient {
292
+ if didChangeClient || didChangeDeviceToken {
270
293
  _ = try await Clerk.shared.refreshClient()
271
294
  await Self.waitForLoadedClient()
272
295
  }
273
296
 
274
- lastObservedClientState = Self.clientStateSnapshot()
275
- Self.emitClientChanged(Self.clientChangedPayload(sourceId: sourceId))
297
+ let newClientState = Self.clientStateSnapshot()
298
+ lastObservedClientState = newClientState
299
+ Self.emitClientChanged(
300
+ Self.clientChangedPayload(
301
+ sourceId: sourceId,
302
+ changes: .init(
303
+ client: newClientState.client != previousClientState.client,
304
+ deviceToken: newClientState.deviceToken != previousClientState.deviceToken
305
+ )
306
+ )
307
+ )
276
308
  }
277
309
 
278
310
  private static func postConfiguredNotification() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerk/expo",
3
- "version": "3.5.0-canary.v20260619100729",
3
+ "version": "3.5.0",
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.2-canary.v20260619100729",
108
- "@clerk/react": "6.10.4-canary.v20260619100729",
109
- "@clerk/shared": "4.19.2-canary.v20260619100729"
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.8-canary.v20260619100729"
123
+ "@clerk/expo-passkeys": "1.1.7"
124
124
  },
125
125
  "peerDependencies": {
126
- "@clerk/expo-passkeys": "1.1.8-canary.v20260619100729",
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,10 +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(
10
- clientToken: string | null,
9
+ syncClientStateFromJs(
10
+ deviceToken: string | null,
11
11
  sourceId: string | null,
12
- shouldRefreshClient?: boolean,
12
+ didChangeClient: boolean,
13
+ didChangeDeviceToken: boolean,
13
14
  ): Promise<void>;
14
15
  removeListeners?(count: number): void;
15
16
  }
@@ -7,10 +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(
11
- clientToken: string | null,
10
+ syncClientStateFromJs(
11
+ deviceToken: string | null,
12
12
  sourceId: string | null,
13
- shouldRefreshClient?: boolean,
13
+ didChangeClient: boolean,
14
+ didChangeDeviceToken: boolean,
14
15
  ): Promise<void>;
15
16
  // Required by NativeEventEmitter for internal native client change events.
16
17
  // This is not part of the public @clerk/expo API.