@clerk/expo 3.1.3-snapshot.v20260311230607 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -1
- package/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt +37 -55
- package/dist/errorThrower.d.ts +1 -1
- package/dist/hooks/useUserProfileModal.d.ts.map +1 -1
- package/dist/hooks/useUserProfileModal.js +6 -22
- package/dist/hooks/useUserProfileModal.js.map +1 -1
- package/dist/native/UserButton.d.ts.map +1 -1
- package/dist/native/UserButton.js +16 -21
- package/dist/native/UserButton.js.map +1 -1
- package/dist/provider/ClerkProvider.d.ts.map +1 -1
- package/dist/provider/ClerkProvider.js +21 -77
- package/dist/provider/ClerkProvider.js.map +1 -1
- package/dist/provider/singleton/createClerkInstance.d.ts.map +1 -1
- package/dist/provider/singleton/createClerkInstance.js +29 -8
- package/dist/provider/singleton/createClerkInstance.js.map +1 -1
- package/dist/provider/singleton/types.d.ts +3 -1
- package/dist/provider/singleton/types.d.ts.map +1 -1
- package/dist/provider/singleton/types.js.map +1 -1
- package/dist/specs/NativeClerkModule.d.ts.map +1 -1
- package/dist/specs/NativeClerkModule.js +2 -1
- package/dist/specs/NativeClerkModule.js.map +1 -1
- package/dist/utils/errors.d.ts +3 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +23 -0
- package/dist/utils/errors.js.map +1 -1
- package/ios/ClerkExpoModule.swift +23 -5
- package/ios/ClerkViewFactory.swift +128 -188
- package/ios/templates/ClerkViewFactory.swift +22 -101
- package/package.json +6 -6
- package/src/specs/NativeClerkModule.ts +1 -1
package/android/build.gradle
CHANGED
|
@@ -18,7 +18,7 @@ ext {
|
|
|
18
18
|
credentialsVersion = "1.3.0"
|
|
19
19
|
googleIdVersion = "1.1.1"
|
|
20
20
|
kotlinxCoroutinesVersion = "1.7.3"
|
|
21
|
-
clerkAndroidApiVersion = "1.0.
|
|
21
|
+
clerkAndroidApiVersion = "1.0.6"
|
|
22
22
|
clerkAndroidUiVersion = "1.0.9"
|
|
23
23
|
composeVersion = "1.7.0"
|
|
24
24
|
activityComposeVersion = "1.9.0"
|
|
@@ -5,7 +5,6 @@ import android.content.Context
|
|
|
5
5
|
import android.content.Intent
|
|
6
6
|
import android.util.Log
|
|
7
7
|
import com.clerk.api.Clerk
|
|
8
|
-
import com.clerk.api.network.serialization.ClerkResult
|
|
9
8
|
import com.facebook.react.bridge.ActivityEventListener
|
|
10
9
|
import com.facebook.react.bridge.Promise
|
|
11
10
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
@@ -68,63 +67,41 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
68
67
|
try {
|
|
69
68
|
publishableKey = pubKey
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
// If the JS SDK has a bearer token, write it to the native SDK's
|
|
71
|
+
// SharedPreferences so both SDKs share the same Clerk API client.
|
|
72
|
+
if (!bearerToken.isNullOrEmpty()) {
|
|
73
|
+
reactApplicationContext.getSharedPreferences("clerk_preferences", Context.MODE_PRIVATE)
|
|
74
|
+
.edit()
|
|
75
|
+
.putString("DEVICE_TOKEN", bearerToken)
|
|
76
|
+
.apply()
|
|
77
|
+
debugLog(TAG, "configure - wrote JS bearer token to native SharedPreferences")
|
|
78
|
+
}
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Wait for initialization to complete with timeout
|
|
84
|
-
try {
|
|
85
|
-
withTimeout(10_000L) {
|
|
86
|
-
Clerk.isInitialized.first { it }
|
|
87
|
-
}
|
|
88
|
-
} catch (e: TimeoutCancellationException) {
|
|
89
|
-
val initError = Clerk.initializationError.value
|
|
90
|
-
val message = if (initError != null) {
|
|
91
|
-
"Clerk initialization timed out: ${initError.message}"
|
|
92
|
-
} else {
|
|
93
|
-
"Clerk initialization timed out after 10 seconds"
|
|
94
|
-
}
|
|
95
|
-
promise.reject("E_TIMEOUT", message)
|
|
96
|
-
return@launch
|
|
97
|
-
}
|
|
80
|
+
Clerk.initialize(reactApplicationContext, pubKey)
|
|
98
81
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
82
|
+
// Wait for initialization to complete with timeout
|
|
83
|
+
try {
|
|
84
|
+
withTimeout(10_000L) {
|
|
85
|
+
Clerk.isInitialized.first { it }
|
|
86
|
+
}
|
|
87
|
+
} catch (e: TimeoutCancellationException) {
|
|
88
|
+
val initError = Clerk.initializationError.value
|
|
89
|
+
val message = if (initError != null) {
|
|
90
|
+
"Clerk initialization timed out: ${initError.message}"
|
|
103
91
|
} else {
|
|
104
|
-
|
|
92
|
+
"Clerk initialization timed out after 10 seconds"
|
|
105
93
|
}
|
|
94
|
+
promise.reject("E_TIMEOUT", message)
|
|
106
95
|
return@launch
|
|
107
96
|
}
|
|
108
97
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Wait for session to appear with the new token (up to 5s)
|
|
118
|
-
try {
|
|
119
|
-
withTimeout(5_000L) {
|
|
120
|
-
Clerk.sessionFlow.first { it != null }
|
|
121
|
-
}
|
|
122
|
-
} catch (_: TimeoutCancellationException) {
|
|
123
|
-
debugLog(TAG, "configure - session did not appear after token update")
|
|
124
|
-
}
|
|
98
|
+
// Check for initialization errors
|
|
99
|
+
val error = Clerk.initializationError.value
|
|
100
|
+
if (error != null) {
|
|
101
|
+
promise.reject("E_INIT_FAILED", "Failed to initialize Clerk SDK: ${error.message}")
|
|
102
|
+
} else {
|
|
103
|
+
promise.resolve(null)
|
|
125
104
|
}
|
|
126
|
-
|
|
127
|
-
promise.resolve(null)
|
|
128
105
|
} catch (e: Exception) {
|
|
129
106
|
promise.reject("E_INIT_FAILED", "Failed to initialize Clerk SDK: ${e.message}", e)
|
|
130
107
|
}
|
|
@@ -197,15 +174,15 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
197
174
|
@ReactMethod
|
|
198
175
|
override fun getSession(promise: Promise) {
|
|
199
176
|
if (!Clerk.isInitialized.value) {
|
|
200
|
-
|
|
201
|
-
// so callers can proceed to call configure() with a bearer token.
|
|
202
|
-
promise.resolve(null)
|
|
177
|
+
promise.reject("E_NOT_INITIALIZED", "Clerk SDK is not initialized. Call configure() first.")
|
|
203
178
|
return
|
|
204
179
|
}
|
|
205
180
|
|
|
206
181
|
val session = Clerk.session
|
|
207
182
|
val user = Clerk.user
|
|
208
183
|
|
|
184
|
+
debugLog(TAG, "getSession - hasSession: ${session != null}, hasUser: ${user != null}")
|
|
185
|
+
|
|
209
186
|
val result = WritableNativeMap()
|
|
210
187
|
|
|
211
188
|
session?.let {
|
|
@@ -240,6 +217,7 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
240
217
|
try {
|
|
241
218
|
val prefs = reactApplicationContext.getSharedPreferences("clerk_preferences", Context.MODE_PRIVATE)
|
|
242
219
|
val deviceToken = prefs.getString("DEVICE_TOKEN", null)
|
|
220
|
+
debugLog(TAG, "getClientToken - deviceToken: ${if (deviceToken != null) "found" else "null"}")
|
|
243
221
|
promise.resolve(deviceToken)
|
|
244
222
|
} catch (e: Exception) {
|
|
245
223
|
debugLog(TAG, "getClientToken failed: ${e.message}")
|
|
@@ -252,8 +230,7 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
252
230
|
@ReactMethod
|
|
253
231
|
override fun signOut(promise: Promise) {
|
|
254
232
|
if (!Clerk.isInitialized.value) {
|
|
255
|
-
|
|
256
|
-
promise.resolve(null)
|
|
233
|
+
promise.reject("E_NOT_INITIALIZED", "Clerk SDK is not initialized. Call configure() first.")
|
|
257
234
|
return
|
|
258
235
|
}
|
|
259
236
|
|
|
@@ -281,6 +258,8 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
281
258
|
}
|
|
282
259
|
|
|
283
260
|
private fun handleAuthResult(resultCode: Int, data: Intent?) {
|
|
261
|
+
debugLog(TAG, "handleAuthResult - resultCode: $resultCode")
|
|
262
|
+
|
|
284
263
|
val promise = pendingAuthPromise ?: return
|
|
285
264
|
pendingAuthPromise = null
|
|
286
265
|
|
|
@@ -288,6 +267,8 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
288
267
|
val session = Clerk.session
|
|
289
268
|
val user = Clerk.user
|
|
290
269
|
|
|
270
|
+
debugLog(TAG, "handleAuthResult - hasSession: ${session != null}, hasUser: ${user != null}")
|
|
271
|
+
|
|
291
272
|
val result = WritableNativeMap()
|
|
292
273
|
|
|
293
274
|
// Top-level sessionId for JS SDK compatibility (matches iOS response format)
|
|
@@ -315,6 +296,7 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
|
|
|
315
296
|
|
|
316
297
|
promise.resolve(result)
|
|
317
298
|
} else {
|
|
299
|
+
debugLog(TAG, "handleAuthResult - user cancelled")
|
|
318
300
|
val result = WritableNativeMap()
|
|
319
301
|
result.putBoolean("cancelled", true)
|
|
320
302
|
promise.resolve(result)
|
package/dist/errorThrower.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUserProfileModal.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserProfileModal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useUserProfileModal.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserProfileModal.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,IAAI,yBAAyB,CA4D/D"}
|
|
@@ -23,16 +23,13 @@ __export(useUserProfileModal_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(useUserProfileModal_exports);
|
|
24
24
|
var import_react = require("@clerk/react");
|
|
25
25
|
var import_react2 = require("react");
|
|
26
|
-
var import_constants = require("../constants");
|
|
27
|
-
var import_token_cache = require("../token-cache");
|
|
28
26
|
var import_native_module = require("../utils/native-module");
|
|
29
27
|
function useUserProfileModal() {
|
|
30
28
|
var _a;
|
|
31
29
|
const clerk = (0, import_react.useClerk)();
|
|
32
|
-
const { user } = (0, import_react.useUser)();
|
|
33
30
|
const presentingRef = (0, import_react2.useRef)(false);
|
|
34
31
|
const presentUserProfile = (0, import_react2.useCallback)(async () => {
|
|
35
|
-
var _a2, _b, _c, _d, _e, _f
|
|
32
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
36
33
|
if (presentingRef.current) {
|
|
37
34
|
return;
|
|
38
35
|
}
|
|
@@ -41,27 +38,14 @@ function useUserProfileModal() {
|
|
|
41
38
|
}
|
|
42
39
|
presentingRef.current = true;
|
|
43
40
|
try {
|
|
44
|
-
let hadNativeSessionBefore = false;
|
|
45
|
-
if (user && ((_b = import_native_module.ClerkExpoModule) == null ? void 0 : _b.getSession) && ((_c = import_native_module.ClerkExpoModule) == null ? void 0 : _c.configure)) {
|
|
46
|
-
const preCheck = await import_native_module.ClerkExpoModule.getSession();
|
|
47
|
-
hadNativeSessionBefore = !!((preCheck == null ? void 0 : preCheck.sessionId) || ((_d = preCheck == null ? void 0 : preCheck.session) == null ? void 0 : _d.id));
|
|
48
|
-
if (!hadNativeSessionBefore) {
|
|
49
|
-
const bearerToken = (_f = await ((_e = import_token_cache.tokenCache) == null ? void 0 : _e.getToken(import_constants.CLERK_CLIENT_JWT_KEY))) != null ? _f : null;
|
|
50
|
-
if (bearerToken) {
|
|
51
|
-
await import_native_module.ClerkExpoModule.configure(clerk.publishableKey, bearerToken);
|
|
52
|
-
const postConfigure = await import_native_module.ClerkExpoModule.getSession();
|
|
53
|
-
hadNativeSessionBefore = !!((postConfigure == null ? void 0 : postConfigure.sessionId) || ((_g = postConfigure == null ? void 0 : postConfigure.session) == null ? void 0 : _g.id));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
41
|
await import_native_module.ClerkExpoModule.presentUserProfile({
|
|
58
42
|
dismissable: true
|
|
59
43
|
});
|
|
60
|
-
const sessionCheck = await ((
|
|
61
|
-
const hasNativeSession = !!((sessionCheck == null ? void 0 : sessionCheck.sessionId) || ((
|
|
62
|
-
if (!hasNativeSession
|
|
44
|
+
const sessionCheck = await ((_c = (_b = import_native_module.ClerkExpoModule).getSession) == null ? void 0 : _c.call(_b));
|
|
45
|
+
const hasNativeSession = !!((sessionCheck == null ? void 0 : sessionCheck.sessionId) || ((_d = sessionCheck == null ? void 0 : sessionCheck.session) == null ? void 0 : _d.id));
|
|
46
|
+
if (!hasNativeSession) {
|
|
63
47
|
try {
|
|
64
|
-
await ((
|
|
48
|
+
await ((_f = (_e = import_native_module.ClerkExpoModule).signOut) == null ? void 0 : _f.call(_e));
|
|
65
49
|
} catch (e) {
|
|
66
50
|
if (false) {
|
|
67
51
|
console.warn("[useUserProfileModal] Native signOut error (may already be signed out):", e);
|
|
@@ -84,7 +68,7 @@ function useUserProfileModal() {
|
|
|
84
68
|
} finally {
|
|
85
69
|
presentingRef.current = false;
|
|
86
70
|
}
|
|
87
|
-
}, [clerk
|
|
71
|
+
}, [clerk]);
|
|
88
72
|
return {
|
|
89
73
|
presentUserProfile,
|
|
90
74
|
isAvailable: import_native_module.isNativeSupported && !!((_a = import_native_module.ClerkExpoModule) == null ? void 0 : _a.presentUserProfile)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useUserProfileModal.ts"],"sourcesContent":["import { useClerk
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useUserProfileModal.ts"],"sourcesContent":["import { useClerk } from '@clerk/react';\nimport { useCallback, useRef } from 'react';\n\nimport { ClerkExpoModule as ClerkExpo, isNativeSupported } from '../utils/native-module';\n\n// Raw result from the native module (may vary by platform)\ntype NativeSessionResult = {\n sessionId?: string;\n session?: { id: string };\n};\n\nexport interface UseUserProfileModalReturn {\n /**\n * Present the native user profile modal.\n *\n * The returned promise resolves when the modal is dismissed.\n * If the user signed out from within the profile modal,\n * the JS SDK session is automatically cleared.\n */\n presentUserProfile: () => Promise<void>;\n\n /**\n * Whether the native module supports presenting the profile modal.\n */\n isAvailable: boolean;\n}\n\n/**\n * Imperative hook for presenting the native user profile modal.\n *\n * Call `presentUserProfile()` from a button's `onPress` to show the native\n * profile management screen (SwiftUI on iOS, Jetpack Compose on Android).\n * The promise resolves when the modal is dismissed.\n *\n * Sign-out is detected automatically — if the user signs out from within\n * the profile modal, the JS SDK session is cleared so `useAuth()` updates\n * reactively.\n *\n * @example\n * ```tsx\n * import { useUserProfileModal } from '@clerk/expo';\n *\n * function MyScreen() {\n * const { presentUserProfile } = useUserProfileModal();\n *\n * return (\n * <TouchableOpacity onPress={presentUserProfile}>\n * <Text>Manage Profile</Text>\n * </TouchableOpacity>\n * );\n * }\n * ```\n */\nexport function useUserProfileModal(): UseUserProfileModalReturn {\n const clerk = useClerk();\n const presentingRef = useRef(false);\n\n const presentUserProfile = useCallback(async () => {\n if (presentingRef.current) {\n return;\n }\n\n if (!isNativeSupported || !ClerkExpo?.presentUserProfile) {\n return;\n }\n\n presentingRef.current = true;\n try {\n await ClerkExpo.presentUserProfile({\n dismissable: true,\n });\n\n // Check if native session still exists after modal closes\n // If session is null, user signed out from the native UI\n const sessionCheck = (await ClerkExpo.getSession?.()) as NativeSessionResult | null;\n const hasNativeSession = !!(sessionCheck?.sessionId || sessionCheck?.session?.id);\n\n if (!hasNativeSession) {\n // Clear native session explicitly (may already be cleared, but ensure it)\n try {\n await ClerkExpo.signOut?.();\n } catch (e) {\n if (__DEV__) {\n console.warn('[useUserProfileModal] Native signOut error (may already be signed out):', e);\n }\n }\n\n // Sign out from JS SDK to update isSignedIn state\n if (clerk?.signOut) {\n try {\n await clerk.signOut();\n } catch (e) {\n if (__DEV__) {\n console.warn('[useUserProfileModal] Best-effort JS SDK signOut failed:', e);\n }\n }\n }\n }\n } catch (error) {\n // Dismissal resolves successfully with { dismissed: true }, so reaching\n // here means a real native error (E_NOT_INITIALIZED, E_CREATE_FAILED, E_NO_ROOT_VC).\n if (__DEV__) {\n console.error('[useUserProfileModal] presentUserProfile failed:', error);\n }\n } finally {\n presentingRef.current = false;\n }\n }, [clerk]);\n\n return {\n presentUserProfile,\n isAvailable: isNativeSupported && !!ClerkExpo?.presentUserProfile,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyB;AACzB,IAAAA,gBAAoC;AAEpC,2BAAgE;AAkDzD,SAAS,sBAAiD;AArDjE;AAsDE,QAAM,YAAQ,uBAAS;AACvB,QAAM,oBAAgB,sBAAO,KAAK;AAElC,QAAM,yBAAqB,2BAAY,YAAY;AAzDrD,QAAAC,KAAA;AA0DI,QAAI,cAAc,SAAS;AACzB;AAAA,IACF;AAEA,QAAI,CAAC,0CAAqB,GAACA,MAAA,qBAAAC,oBAAA,gBAAAD,IAAW,qBAAoB;AACxD;AAAA,IACF;AAEA,kBAAc,UAAU;AACxB,QAAI;AACF,YAAM,qBAAAC,gBAAU,mBAAmB;AAAA,QACjC,aAAa;AAAA,MACf,CAAC;AAID,YAAM,eAAgB,QAAM,gCAAAA,iBAAU,eAAV;AAC5B,YAAM,mBAAmB,CAAC,GAAE,6CAAc,gBAAa,kDAAc,YAAd,mBAAuB;AAE9E,UAAI,CAAC,kBAAkB;AAErB,YAAI;AACF,kBAAM,gCAAAA,iBAAU,YAAV;AAAA,QACR,SAAS,GAAG;AACV,cAAI,OAAS;AACX,oBAAQ,KAAK,2EAA2E,CAAC;AAAA,UAC3F;AAAA,QACF;AAGA,YAAI,+BAAO,SAAS;AAClB,cAAI;AACF,kBAAM,MAAM,QAAQ;AAAA,UACtB,SAAS,GAAG;AACV,gBAAI,OAAS;AACX,sBAAQ,KAAK,4DAA4D,CAAC;AAAA,YAC5E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAGd,UAAI,OAAS;AACX,gBAAQ,MAAM,oDAAoD,KAAK;AAAA,MACzE;AAAA,IACF,UAAE;AACA,oBAAc,UAAU;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO;AAAA,IACL;AAAA,IACA,aAAa,0CAAqB,CAAC,GAAC,0BAAAA,oBAAA,mBAAW;AAAA,EACjD;AACF;","names":["import_react","_a","ClerkExpo"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../src/native/UserButton.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../src/native/UserButton.tsx"],"names":[],"mappings":"AA8BA;;GAEG;AAEH,MAAM,WAAW,eAAe;CAAG;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,2CA0IjD"}
|
|
@@ -25,8 +25,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
25
25
|
var import_react = require("@clerk/react");
|
|
26
26
|
var import_react2 = require("react");
|
|
27
27
|
var import_react_native = require("react-native");
|
|
28
|
-
var import_constants = require("../constants");
|
|
29
|
-
var import_token_cache = require("../token-cache");
|
|
30
28
|
var import_native_module = require("../utils/native-module");
|
|
31
29
|
function getInitials(user) {
|
|
32
30
|
var _a;
|
|
@@ -73,7 +71,7 @@ function UserButton(_props) {
|
|
|
73
71
|
primaryEmailAddress: (_d = clerkUser.primaryEmailAddress) == null ? void 0 : _d.emailAddress
|
|
74
72
|
} : null;
|
|
75
73
|
const handlePress = async () => {
|
|
76
|
-
var _a2, _b2, _c2, _d2, _e, _f
|
|
74
|
+
var _a2, _b2, _c2, _d2, _e, _f;
|
|
77
75
|
if (presentingRef.current) {
|
|
78
76
|
return;
|
|
79
77
|
}
|
|
@@ -82,28 +80,15 @@ function UserButton(_props) {
|
|
|
82
80
|
}
|
|
83
81
|
presentingRef.current = true;
|
|
84
82
|
try {
|
|
85
|
-
let hadNativeSessionBefore = false;
|
|
86
|
-
if (clerkUser && ((_b2 = import_native_module.ClerkExpoModule) == null ? void 0 : _b2.getSession) && ((_c2 = import_native_module.ClerkExpoModule) == null ? void 0 : _c2.configure)) {
|
|
87
|
-
const preCheck = await import_native_module.ClerkExpoModule.getSession();
|
|
88
|
-
hadNativeSessionBefore = !!((preCheck == null ? void 0 : preCheck.sessionId) || ((_d2 = preCheck == null ? void 0 : preCheck.session) == null ? void 0 : _d2.id));
|
|
89
|
-
if (!hadNativeSessionBefore) {
|
|
90
|
-
const bearerToken = (_f = await ((_e = import_token_cache.tokenCache) == null ? void 0 : _e.getToken(import_constants.CLERK_CLIENT_JWT_KEY))) != null ? _f : null;
|
|
91
|
-
if (bearerToken) {
|
|
92
|
-
await import_native_module.ClerkExpoModule.configure(clerk.publishableKey, bearerToken);
|
|
93
|
-
const postConfigure = await import_native_module.ClerkExpoModule.getSession();
|
|
94
|
-
hadNativeSessionBefore = !!((postConfigure == null ? void 0 : postConfigure.sessionId) || ((_g = postConfigure == null ? void 0 : postConfigure.session) == null ? void 0 : _g.id));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
83
|
await import_native_module.ClerkExpoModule.presentUserProfile({
|
|
99
84
|
dismissable: true
|
|
100
85
|
});
|
|
101
|
-
const sessionCheck = await ((
|
|
102
|
-
const hasNativeSession = !!((sessionCheck == null ? void 0 : sessionCheck.sessionId) || ((
|
|
103
|
-
if (!hasNativeSession
|
|
86
|
+
const sessionCheck = await ((_c2 = (_b2 = import_native_module.ClerkExpoModule).getSession) == null ? void 0 : _c2.call(_b2));
|
|
87
|
+
const hasNativeSession = !!((sessionCheck == null ? void 0 : sessionCheck.sessionId) || ((_d2 = sessionCheck == null ? void 0 : sessionCheck.session) == null ? void 0 : _d2.id));
|
|
88
|
+
if (!hasNativeSession) {
|
|
104
89
|
setNativeUser(null);
|
|
105
90
|
try {
|
|
106
|
-
await ((
|
|
91
|
+
await ((_f = (_e = import_native_module.ClerkExpoModule).signOut) == null ? void 0 : _f.call(_e));
|
|
107
92
|
} catch (e) {
|
|
108
93
|
if (false) {
|
|
109
94
|
console.warn("[UserButton] Native signOut error (may already be signed out):", e);
|
|
@@ -114,7 +99,17 @@ function UserButton(_props) {
|
|
|
114
99
|
await clerk.signOut();
|
|
115
100
|
} catch (e) {
|
|
116
101
|
if (false) {
|
|
117
|
-
console.warn("[UserButton] JS SDK signOut error:", e);
|
|
102
|
+
console.warn("[UserButton] JS SDK signOut error, attempting reload:", e);
|
|
103
|
+
}
|
|
104
|
+
const clerkRecord = clerk;
|
|
105
|
+
if (typeof clerkRecord.__internal_reloadInitialResources === "function") {
|
|
106
|
+
try {
|
|
107
|
+
await clerkRecord.__internal_reloadInitialResources();
|
|
108
|
+
} catch (reloadErr) {
|
|
109
|
+
if (false) {
|
|
110
|
+
console.warn("[UserButton] Best-effort reload failed:", reloadErr);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
118
113
|
}
|
|
119
114
|
}
|
|
120
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/native/UserButton.tsx"],"sourcesContent":["import { useClerk, useUser } from '@clerk/react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';\n\nimport { CLERK_CLIENT_JWT_KEY } from '../constants';\nimport { tokenCache } from '../token-cache';\nimport { ClerkExpoModule as ClerkExpo, isNativeSupported } from '../utils/native-module';\n\n// Raw result from native module (may vary by platform)\ninterface NativeSessionResult {\n sessionId?: string;\n session?: { id: string };\n user?: { id: string; firstName?: string; lastName?: string; imageUrl?: string; primaryEmailAddress?: string };\n}\n\nfunction getInitials(user: { firstName?: string; lastName?: string } | null): string {\n if (user?.firstName) {\n const first = user.firstName.charAt(0).toUpperCase();\n const last = user.lastName?.charAt(0).toUpperCase() || '';\n return first + last;\n }\n return 'U';\n}\n\ninterface NativeUser {\n id: string;\n firstName?: string;\n lastName?: string;\n imageUrl?: string;\n primaryEmailAddress?: string;\n}\n\n/**\n * Props for the UserButton component.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface UserButtonProps {}\n\n/**\n * A pre-built native button component that displays the user's avatar and opens their profile.\n *\n * `UserButton` renders a circular button showing the user's profile image (or initials if\n * no image is available). When tapped, it presents the native profile management modal.\n *\n * Sign-out is detected automatically and synced with the JS SDK, causing `useAuth()` to\n * update reactively. Use `useAuth()` in a `useEffect` to react to sign-out.\n *\n * @example Basic usage in a header\n * ```tsx\n * import { UserButton } from '@clerk/expo/native';\n *\n * export default function Header() {\n * return (\n * <View style={styles.header}>\n * <Text style={styles.title}>My App</Text>\n * <UserButton />\n * </View>\n * );\n * }\n * ```\n *\n * @example Reacting to sign-out\n * ```tsx\n * import { UserButton } from '@clerk/expo/native';\n * import { useAuth } from '@clerk/expo';\n *\n * export default function Header() {\n * const { isSignedIn } = useAuth();\n *\n * useEffect(() => {\n * if (!isSignedIn) router.replace('/sign-in');\n * }, [isSignedIn]);\n *\n * return <UserButton style={{ width: 40, height: 40 }} />;\n * }\n * ```\n *\n * @see {@link UserProfileView} The profile view that opens when tapped\n * @see {@link https://clerk.com/docs/components/user/user-button} Clerk UserButton Documentation\n */\nexport function UserButton(_props: UserButtonProps) {\n const [nativeUser, setNativeUser] = useState<NativeUser | null>(null);\n const presentingRef = useRef(false);\n const clerk = useClerk();\n // Use the reactive user hook from clerk-react to observe sign-out state changes\n const { user: clerkUser } = useUser();\n\n // Fetch native user data on mount and when clerk user changes\n useEffect(() => {\n const fetchUser = async () => {\n if (!isNativeSupported || !ClerkExpo?.getSession) {\n return;\n }\n\n try {\n const result = (await ClerkExpo.getSession()) as NativeSessionResult | null;\n const hasSession = !!(result?.sessionId || result?.session?.id);\n if (hasSession && result?.user) {\n setNativeUser(result.user);\n } else {\n // Clear local state if no native session\n setNativeUser(null);\n }\n } catch (err) {\n if (__DEV__) {\n console.error('[UserButton] Error fetching user:', err);\n }\n }\n };\n\n void fetchUser();\n }, [clerkUser?.id]); // Re-fetch when clerk user changes (including sign-out)\n\n // Derive the user to display - prefer native data, fall back to clerk-react data\n const user: NativeUser | null =\n nativeUser ??\n (clerkUser\n ? {\n id: clerkUser.id,\n firstName: clerkUser.firstName ?? undefined,\n lastName: clerkUser.lastName ?? undefined,\n imageUrl: clerkUser.imageUrl ?? undefined,\n primaryEmailAddress: clerkUser.primaryEmailAddress?.emailAddress,\n }\n : null);\n\n const handlePress = async () => {\n if (presentingRef.current) {\n return;\n }\n\n if (!isNativeSupported || !ClerkExpo?.presentUserProfile) {\n return;\n }\n\n presentingRef.current = true;\n try {\n // Track whether native had a session before the modal, so we can distinguish\n // \"user signed out from within the modal\" from \"native never had a session\".\n let hadNativeSessionBefore = false;\n\n // If native doesn't have a session but JS does (e.g. user signed in via custom form),\n // sync the JS SDK's bearer token to native and wait for it before presenting.\n if (clerkUser && ClerkExpo?.getSession && ClerkExpo?.configure) {\n const preCheck = (await ClerkExpo.getSession()) as NativeSessionResult | null;\n hadNativeSessionBefore = !!(preCheck?.sessionId || preCheck?.session?.id);\n\n if (!hadNativeSessionBefore) {\n const bearerToken = (await tokenCache?.getToken(CLERK_CLIENT_JWT_KEY)) ?? null;\n if (bearerToken) {\n await ClerkExpo.configure(clerk.publishableKey, bearerToken);\n\n // Re-check if configure produced a session\n const postConfigure = (await ClerkExpo.getSession()) as NativeSessionResult | null;\n hadNativeSessionBefore = !!(postConfigure?.sessionId || postConfigure?.session?.id);\n }\n }\n }\n\n await ClerkExpo.presentUserProfile({\n dismissable: true,\n });\n\n // Check if native session still exists after modal closes.\n // Only sign out the JS SDK if the native SDK HAD a session before the modal\n // and now it's gone (meaning the user signed out from within the native UI).\n // If native never had a session (e.g. force refresh didn't work), don't sign out JS.\n const sessionCheck = (await ClerkExpo.getSession?.()) as NativeSessionResult | null;\n const hasNativeSession = !!(sessionCheck?.sessionId || sessionCheck?.session?.id);\n\n if (!hasNativeSession && hadNativeSessionBefore) {\n // Clear local state immediately for instant UI feedback\n setNativeUser(null);\n\n // Clear native session explicitly (may already be cleared, but ensure it)\n try {\n await ClerkExpo.signOut?.();\n } catch (e) {\n if (__DEV__) {\n console.warn('[UserButton] Native signOut error (may already be signed out):', e);\n }\n }\n\n // Sign out from JS SDK to update isSignedIn state\n if (clerk?.signOut) {\n try {\n await clerk.signOut();\n } catch (e) {\n if (__DEV__) {\n console.warn('[UserButton] JS SDK signOut error:', e);\n }\n }\n }\n }\n } catch (error) {\n if (__DEV__) {\n console.error('[UserButton] presentUserProfile failed:', error);\n }\n } finally {\n presentingRef.current = false;\n }\n };\n\n // Show fallback when native modules aren't available\n if (!isNativeSupported || !ClerkExpo) {\n return (\n <View style={styles.button}>\n <Text style={styles.text}>?</Text>\n </View>\n );\n }\n\n return (\n <TouchableOpacity\n onPress={() => void handlePress()}\n style={styles.button}\n >\n {user?.imageUrl ? (\n <Image\n source={{ uri: user.imageUrl }}\n style={styles.avatarImage}\n />\n ) : (\n <View style={styles.avatar}>\n <Text style={styles.avatarText}>{getInitials(user)}</Text>\n </View>\n )}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n },\n avatar: {\n flex: 1,\n backgroundColor: '#6366f1',\n justifyContent: 'center',\n alignItems: 'center',\n },\n avatarImage: {\n width: '100%',\n height: '100%',\n },\n avatarText: {\n color: 'white',\n fontSize: 14,\n fontWeight: '600',\n },\n text: {\n fontSize: 14,\n color: '#666',\n },\n});\n"],"mappings":"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","names":["import_react","_a","_b","ClerkExpo","_c","_d"]}
|
|
1
|
+
{"version":3,"sources":["../../src/native/UserButton.tsx"],"sourcesContent":["import { useClerk, useUser } from '@clerk/react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';\n\nimport { ClerkExpoModule as ClerkExpo, isNativeSupported } from '../utils/native-module';\n\n// Raw result from native module (may vary by platform)\ninterface NativeSessionResult {\n sessionId?: string;\n session?: { id: string };\n user?: { id: string; firstName?: string; lastName?: string; imageUrl?: string; primaryEmailAddress?: string };\n}\n\nfunction getInitials(user: { firstName?: string; lastName?: string } | null): string {\n if (user?.firstName) {\n const first = user.firstName.charAt(0).toUpperCase();\n const last = user.lastName?.charAt(0).toUpperCase() || '';\n return first + last;\n }\n return 'U';\n}\n\ninterface NativeUser {\n id: string;\n firstName?: string;\n lastName?: string;\n imageUrl?: string;\n primaryEmailAddress?: string;\n}\n\n/**\n * Props for the UserButton component.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface UserButtonProps {}\n\n/**\n * A pre-built native button component that displays the user's avatar and opens their profile.\n *\n * `UserButton` renders a circular button showing the user's profile image (or initials if\n * no image is available). When tapped, it presents the native profile management modal.\n *\n * Sign-out is detected automatically and synced with the JS SDK, causing `useAuth()` to\n * update reactively. Use `useAuth()` in a `useEffect` to react to sign-out.\n *\n * @example Basic usage in a header\n * ```tsx\n * import { UserButton } from '@clerk/expo/native';\n *\n * export default function Header() {\n * return (\n * <View style={styles.header}>\n * <Text style={styles.title}>My App</Text>\n * <UserButton />\n * </View>\n * );\n * }\n * ```\n *\n * @example Reacting to sign-out\n * ```tsx\n * import { UserButton } from '@clerk/expo/native';\n * import { useAuth } from '@clerk/expo';\n *\n * export default function Header() {\n * const { isSignedIn } = useAuth();\n *\n * useEffect(() => {\n * if (!isSignedIn) router.replace('/sign-in');\n * }, [isSignedIn]);\n *\n * return <UserButton style={{ width: 40, height: 40 }} />;\n * }\n * ```\n *\n * @see {@link UserProfileView} The profile view that opens when tapped\n * @see {@link https://clerk.com/docs/components/user/user-button} Clerk UserButton Documentation\n */\nexport function UserButton(_props: UserButtonProps) {\n const [nativeUser, setNativeUser] = useState<NativeUser | null>(null);\n const presentingRef = useRef(false);\n const clerk = useClerk();\n // Use the reactive user hook from clerk-react to observe sign-out state changes\n const { user: clerkUser } = useUser();\n\n // Fetch native user data on mount and when clerk user changes\n useEffect(() => {\n const fetchUser = async () => {\n if (!isNativeSupported || !ClerkExpo?.getSession) {\n return;\n }\n\n try {\n const result = (await ClerkExpo.getSession()) as NativeSessionResult | null;\n const hasSession = !!(result?.sessionId || result?.session?.id);\n if (hasSession && result?.user) {\n setNativeUser(result.user);\n } else {\n // Clear local state if no native session\n setNativeUser(null);\n }\n } catch (err) {\n if (__DEV__) {\n console.error('[UserButton] Error fetching user:', err);\n }\n }\n };\n\n void fetchUser();\n }, [clerkUser?.id]); // Re-fetch when clerk user changes (including sign-out)\n\n // Derive the user to display - prefer native data, fall back to clerk-react data\n const user: NativeUser | null =\n nativeUser ??\n (clerkUser\n ? {\n id: clerkUser.id,\n firstName: clerkUser.firstName ?? undefined,\n lastName: clerkUser.lastName ?? undefined,\n imageUrl: clerkUser.imageUrl ?? undefined,\n primaryEmailAddress: clerkUser.primaryEmailAddress?.emailAddress,\n }\n : null);\n\n const handlePress = async () => {\n if (presentingRef.current) {\n return;\n }\n\n if (!isNativeSupported || !ClerkExpo?.presentUserProfile) {\n return;\n }\n\n presentingRef.current = true;\n try {\n await ClerkExpo.presentUserProfile({\n dismissable: true,\n });\n\n // Check if native session still exists after modal closes\n // If session is null, user signed out from the native UI\n const sessionCheck = (await ClerkExpo.getSession?.()) as NativeSessionResult | null;\n const hasNativeSession = !!(sessionCheck?.sessionId || sessionCheck?.session?.id);\n\n if (!hasNativeSession) {\n // Clear local state immediately for instant UI feedback\n setNativeUser(null);\n\n // Clear native session explicitly (may already be cleared, but ensure it)\n try {\n await ClerkExpo.signOut?.();\n } catch (e) {\n if (__DEV__) {\n console.warn('[UserButton] Native signOut error (may already be signed out):', e);\n }\n }\n\n // Sign out from JS SDK to update isSignedIn state\n if (clerk?.signOut) {\n try {\n await clerk.signOut();\n } catch (e) {\n if (__DEV__) {\n console.warn('[UserButton] JS SDK signOut error, attempting reload:', e);\n }\n // Even if signOut throws, try to force reload to clear stale state\n const clerkRecord = clerk as unknown as Record<string, unknown>;\n if (typeof clerkRecord.__internal_reloadInitialResources === 'function') {\n try {\n await (clerkRecord.__internal_reloadInitialResources as () => Promise<void>)();\n } catch (reloadErr) {\n if (__DEV__) {\n console.warn('[UserButton] Best-effort reload failed:', reloadErr);\n }\n }\n }\n }\n }\n }\n } catch (error) {\n // Dismissal resolves successfully with { dismissed: true }, so reaching\n // here means a real native error (E_NOT_INITIALIZED, E_CREATE_FAILED, E_NO_ROOT_VC).\n if (__DEV__) {\n console.error('[UserButton] presentUserProfile failed:', error);\n }\n } finally {\n presentingRef.current = false;\n }\n };\n\n // Show fallback when native modules aren't available\n if (!isNativeSupported || !ClerkExpo) {\n return (\n <View style={styles.button}>\n <Text style={styles.text}>?</Text>\n </View>\n );\n }\n\n return (\n <TouchableOpacity\n onPress={() => void handlePress()}\n style={styles.button}\n >\n {user?.imageUrl ? (\n <Image\n source={{ uri: user.imageUrl }}\n style={styles.avatarImage}\n />\n ) : (\n <View style={styles.avatar}>\n <Text style={styles.avatarText}>{getInitials(user)}</Text>\n </View>\n )}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n },\n avatar: {\n flex: 1,\n backgroundColor: '#6366f1',\n justifyContent: 'center',\n alignItems: 'center',\n },\n avatarImage: {\n width: '100%',\n height: '100%',\n },\n avatarText: {\n color: 'white',\n fontSize: 14,\n fontWeight: '600',\n },\n text: {\n fontSize: 14,\n color: '#666',\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkMQ;AAlMR,mBAAkC;AAClC,IAAAA,gBAA4C;AAC5C,0BAAgE;AAEhE,2BAAgE;AAShE,SAAS,YAAY,MAAgE;AAbrF;AAcE,MAAI,6BAAM,WAAW;AACnB,UAAM,QAAQ,KAAK,UAAU,OAAO,CAAC,EAAE,YAAY;AACnD,UAAM,SAAO,UAAK,aAAL,mBAAe,OAAO,GAAG,kBAAiB;AACvD,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AA0DO,SAAS,WAAW,QAAyB;AA9EpD;AA+EE,QAAM,CAAC,YAAY,aAAa,QAAI,wBAA4B,IAAI;AACpE,QAAM,oBAAgB,sBAAO,KAAK;AAClC,QAAM,YAAQ,uBAAS;AAEvB,QAAM,EAAE,MAAM,UAAU,QAAI,sBAAQ;AAGpC,+BAAU,MAAM;AACd,UAAM,YAAY,YAAY;AAvFlC,UAAAC,KAAAC;AAwFM,UAAI,CAAC,0CAAqB,GAACD,MAAA,qBAAAE,oBAAA,gBAAAF,IAAW,aAAY;AAChD;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAU,MAAM,qBAAAE,gBAAU,WAAW;AAC3C,cAAM,aAAa,CAAC,GAAE,iCAAQ,gBAAaD,MAAA,iCAAQ,YAAR,gBAAAA,IAAiB;AAC5D,YAAI,eAAc,iCAAQ,OAAM;AAC9B,wBAAc,OAAO,IAAI;AAAA,QAC3B,OAAO;AAEL,wBAAc,IAAI;AAAA,QACpB;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,OAAS;AACX,kBAAQ,MAAM,qCAAqC,GAAG;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAEA,SAAK,UAAU;AAAA,EACjB,GAAG,CAAC,uCAAW,EAAE,CAAC;AAGlB,QAAM,OACJ,kCACC,YACG;AAAA,IACE,IAAI,UAAU;AAAA,IACd,YAAW,eAAU,cAAV,YAAuB;AAAA,IAClC,WAAU,eAAU,aAAV,YAAsB;AAAA,IAChC,WAAU,eAAU,aAAV,YAAsB;AAAA,IAChC,sBAAqB,eAAU,wBAAV,mBAA+B;AAAA,EACtD,IACA;AAEN,QAAM,cAAc,YAAY;AA5HlC,QAAAD,KAAAC,KAAAE,KAAAC,KAAA;AA6HI,QAAI,cAAc,SAAS;AACzB;AAAA,IACF;AAEA,QAAI,CAAC,0CAAqB,GAACJ,MAAA,qBAAAE,oBAAA,gBAAAF,IAAW,qBAAoB;AACxD;AAAA,IACF;AAEA,kBAAc,UAAU;AACxB,QAAI;AACF,YAAM,qBAAAE,gBAAU,mBAAmB;AAAA,QACjC,aAAa;AAAA,MACf,CAAC;AAID,YAAM,eAAgB,QAAMC,OAAAF,MAAA,qBAAAC,iBAAU,eAAV,gBAAAC,IAAA,KAAAF;AAC5B,YAAM,mBAAmB,CAAC,GAAE,6CAAc,gBAAaG,MAAA,6CAAc,YAAd,gBAAAA,IAAuB;AAE9E,UAAI,CAAC,kBAAkB;AAErB,sBAAc,IAAI;AAGlB,YAAI;AACF,kBAAM,gCAAAF,iBAAU,YAAV;AAAA,QACR,SAAS,GAAG;AACV,cAAI,OAAS;AACX,oBAAQ,KAAK,kEAAkE,CAAC;AAAA,UAClF;AAAA,QACF;AAGA,YAAI,+BAAO,SAAS;AAClB,cAAI;AACF,kBAAM,MAAM,QAAQ;AAAA,UACtB,SAAS,GAAG;AACV,gBAAI,OAAS;AACX,sBAAQ,KAAK,yDAAyD,CAAC;AAAA,YACzE;AAEA,kBAAM,cAAc;AACpB,gBAAI,OAAO,YAAY,sCAAsC,YAAY;AACvE,kBAAI;AACF,sBAAO,YAAY,kCAA0D;AAAA,cAC/E,SAAS,WAAW;AAClB,oBAAI,OAAS;AACX,0BAAQ,KAAK,2CAA2C,SAAS;AAAA,gBACnE;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAGd,UAAI,OAAS;AACX,gBAAQ,MAAM,2CAA2C,KAAK;AAAA,MAChE;AAAA,IACF,UAAE;AACA,oBAAc,UAAU;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI,CAAC,0CAAqB,CAAC,qBAAAA,iBAAW;AACpC,WACE,4CAAC,4BAAK,OAAO,OAAO,QAClB,sDAAC,4BAAK,OAAO,OAAO,MAAM,eAAC,GAC7B;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM,KAAK,YAAY;AAAA,MAChC,OAAO,OAAO;AAAA,MAEb,wCAAM,YACL;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ,EAAE,KAAK,KAAK,SAAS;AAAA,UAC7B,OAAO,OAAO;AAAA;AAAA,MAChB,IAEA,4CAAC,4BAAK,OAAO,OAAO,QAClB,sDAAC,4BAAK,OAAO,OAAO,YAAa,sBAAY,IAAI,GAAE,GACrD;AAAA;AAAA,EAEJ;AAEJ;AAEA,MAAM,SAAS,+BAAW,OAAO;AAAA,EAC/B,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AACF,CAAC;","names":["import_react","_a","_b","ClerkExpo","_c","_d"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClerkProvider.d.ts","sourceRoot":"","sources":["../../src/provider/ClerkProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ClerkProvider.d.ts","sourceRoot":"","sources":["../../src/provider/ClerkProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAA+C,KAAK,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAI7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,MAAM,kBAAkB,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC,GAAG;IAC3G;;;;;;;;;;OAUG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,CAAC;IACvE;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;CAClF,CAAC;AAOF,wBAAgB,aAAa,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CA0P9F"}
|
|
@@ -33,9 +33,8 @@ __export(ClerkProvider_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(ClerkProvider_exports);
|
|
34
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
35
|
var import_polyfills = require("../polyfills");
|
|
36
|
-
var import_react = require("@clerk/react");
|
|
37
36
|
var import_internal = require("@clerk/react/internal");
|
|
38
|
-
var
|
|
37
|
+
var import_react = require("react");
|
|
39
38
|
var import_react_native = require("react-native");
|
|
40
39
|
var import_constants = require("../constants");
|
|
41
40
|
var import_useNativeAuthEvents = require("../hooks/useNativeAuthEvents");
|
|
@@ -45,74 +44,25 @@ var import_runtime = require("../utils/runtime");
|
|
|
45
44
|
var import_singleton = require("./singleton");
|
|
46
45
|
const SDK_METADATA = {
|
|
47
46
|
name: "@clerk/expo",
|
|
48
|
-
version: "3.1.3
|
|
47
|
+
version: "3.1.3"
|
|
49
48
|
};
|
|
50
|
-
function NativeSessionSync({
|
|
51
|
-
publishableKey,
|
|
52
|
-
tokenCache
|
|
53
|
-
}) {
|
|
54
|
-
const { isSignedIn } = (0, import_react.useAuth)();
|
|
55
|
-
const hasSyncedRef = (0, import_react2.useRef)(false);
|
|
56
|
-
const effectiveTokenCache = tokenCache != null ? tokenCache : import_token_cache.tokenCache;
|
|
57
|
-
(0, import_react2.useEffect)(() => {
|
|
58
|
-
if (!isSignedIn) {
|
|
59
|
-
hasSyncedRef.current = false;
|
|
60
|
-
const ClerkExpo = import_NativeClerkModule.default;
|
|
61
|
-
if (ClerkExpo == null ? void 0 : ClerkExpo.signOut) {
|
|
62
|
-
void ClerkExpo.signOut().catch((error) => {
|
|
63
|
-
if (false) {
|
|
64
|
-
console.warn("[NativeSessionSync] Failed to clear native session:", error);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (hasSyncedRef.current) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const syncToNative = async () => {
|
|
74
|
-
var _a, _b;
|
|
75
|
-
try {
|
|
76
|
-
const ClerkExpo = import_NativeClerkModule.default;
|
|
77
|
-
if (!(ClerkExpo == null ? void 0 : ClerkExpo.configure) || !(ClerkExpo == null ? void 0 : ClerkExpo.getSession)) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const nativeSession = await ClerkExpo.getSession();
|
|
81
|
-
const hasNativeSession = !!((nativeSession == null ? void 0 : nativeSession.sessionId) || ((_a = nativeSession == null ? void 0 : nativeSession.session) == null ? void 0 : _a.id));
|
|
82
|
-
if (hasNativeSession) {
|
|
83
|
-
hasSyncedRef.current = true;
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const bearerToken = (_b = await (effectiveTokenCache == null ? void 0 : effectiveTokenCache.getToken(import_constants.CLERK_CLIENT_JWT_KEY))) != null ? _b : null;
|
|
87
|
-
if (bearerToken) {
|
|
88
|
-
await ClerkExpo.configure(publishableKey, bearerToken);
|
|
89
|
-
hasSyncedRef.current = true;
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
if (false) {
|
|
93
|
-
console.warn("[NativeSessionSync] Failed to sync JS session to native:", error);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
void syncToNative();
|
|
98
|
-
}, [isSignedIn, publishableKey, effectiveTokenCache]);
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
49
|
function ClerkProvider(props) {
|
|
102
50
|
const {
|
|
103
51
|
children,
|
|
104
52
|
tokenCache,
|
|
105
53
|
publishableKey,
|
|
54
|
+
proxyUrl,
|
|
55
|
+
domain,
|
|
106
56
|
__experimental_passkeys,
|
|
107
57
|
experimental,
|
|
108
58
|
__experimental_resourceCache,
|
|
109
59
|
...rest
|
|
110
60
|
} = props;
|
|
111
61
|
const pk = publishableKey;
|
|
112
|
-
const pendingNativeSessionRef = (0,
|
|
113
|
-
const initStartedRef = (0,
|
|
114
|
-
const sessionSyncedRef = (0,
|
|
115
|
-
(0,
|
|
62
|
+
const pendingNativeSessionRef = (0, import_react.useRef)(null);
|
|
63
|
+
const initStartedRef = (0, import_react.useRef)(false);
|
|
64
|
+
const sessionSyncedRef = (0, import_react.useRef)(false);
|
|
65
|
+
(0, import_react.useEffect)(() => {
|
|
116
66
|
pendingNativeSessionRef.current = null;
|
|
117
67
|
initStartedRef.current = false;
|
|
118
68
|
sessionSyncedRef.current = false;
|
|
@@ -120,23 +70,24 @@ function ClerkProvider(props) {
|
|
|
120
70
|
const clerkInstance = (0, import_runtime.isNative)() ? (0, import_singleton.getClerkInstance)({
|
|
121
71
|
publishableKey: pk,
|
|
122
72
|
tokenCache,
|
|
73
|
+
proxyUrl,
|
|
74
|
+
domain,
|
|
123
75
|
__experimental_passkeys,
|
|
124
76
|
__experimental_resourceCache
|
|
125
77
|
}) : null;
|
|
126
|
-
const isMountedRef = (0,
|
|
127
|
-
(0,
|
|
78
|
+
const isMountedRef = (0, import_react.useRef)(true);
|
|
79
|
+
(0, import_react.useEffect)(() => {
|
|
128
80
|
isMountedRef.current = true;
|
|
129
81
|
if ((import_react_native.Platform.OS === "ios" || import_react_native.Platform.OS === "android") && pk && !initStartedRef.current) {
|
|
130
82
|
initStartedRef.current = true;
|
|
131
83
|
const configureNativeClerk = async () => {
|
|
132
|
-
var _a, _b, _c, _d, _e, _f;
|
|
84
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
133
85
|
try {
|
|
134
86
|
const ClerkExpo = import_NativeClerkModule.default;
|
|
135
87
|
if (ClerkExpo == null ? void 0 : ClerkExpo.configure) {
|
|
136
|
-
const effectiveTokenCache = tokenCache != null ? tokenCache : import_token_cache.tokenCache;
|
|
137
88
|
let bearerToken = null;
|
|
138
89
|
try {
|
|
139
|
-
bearerToken = (
|
|
90
|
+
bearerToken = (_b = await ((_a = import_token_cache.tokenCache) == null ? void 0 : _a.getToken(import_constants.CLERK_CLIENT_JWT_KEY))) != null ? _b : null;
|
|
140
91
|
} catch (e) {
|
|
141
92
|
if (false) {
|
|
142
93
|
console.warn("[ClerkProvider] Token cache read failed:", e);
|
|
@@ -155,7 +106,7 @@ function ClerkProvider(props) {
|
|
|
155
106
|
}
|
|
156
107
|
if (ClerkExpo == null ? void 0 : ClerkExpo.getSession) {
|
|
157
108
|
const nativeSession = await ClerkExpo.getSession();
|
|
158
|
-
sessionId = (
|
|
109
|
+
sessionId = (_e = (_d = nativeSession == null ? void 0 : nativeSession.sessionId) != null ? _d : (_c = nativeSession == null ? void 0 : nativeSession.session) == null ? void 0 : _c.id) != null ? _e : null;
|
|
159
110
|
if (sessionId) {
|
|
160
111
|
break;
|
|
161
112
|
}
|
|
@@ -189,7 +140,7 @@ function ClerkProvider(props) {
|
|
|
189
140
|
if (!sessionSyncedRef.current && typeof clerkInstance.setActive === "function") {
|
|
190
141
|
sessionSyncedRef.current = true;
|
|
191
142
|
const pendingSession = pendingNativeSessionRef.current;
|
|
192
|
-
const sessionInClient = (
|
|
143
|
+
const sessionInClient = (_g = (_f = clerkInstance.client) == null ? void 0 : _f.sessions) == null ? void 0 : _g.some(
|
|
193
144
|
(s) => s.id === pendingSession
|
|
194
145
|
);
|
|
195
146
|
if (!sessionInClient && typeof clerkAny.__internal_reloadInitialResources === "function") {
|
|
@@ -225,7 +176,7 @@ function ClerkProvider(props) {
|
|
|
225
176
|
};
|
|
226
177
|
}, [pk, clerkInstance]);
|
|
227
178
|
const { nativeAuthState } = (0, import_useNativeAuthEvents.useNativeAuthEvents)();
|
|
228
|
-
(0,
|
|
179
|
+
(0, import_react.useEffect)(() => {
|
|
229
180
|
if (!nativeAuthState || !clerkInstance) {
|
|
230
181
|
return;
|
|
231
182
|
}
|
|
@@ -273,11 +224,13 @@ function ClerkProvider(props) {
|
|
|
273
224
|
}
|
|
274
225
|
}
|
|
275
226
|
}
|
|
276
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
277
228
|
import_internal.InternalClerkProvider,
|
|
278
229
|
{
|
|
279
230
|
...rest,
|
|
280
231
|
publishableKey: pk,
|
|
232
|
+
proxyUrl,
|
|
233
|
+
domain,
|
|
281
234
|
sdkMetadata: SDK_METADATA,
|
|
282
235
|
Clerk: clerkInstance,
|
|
283
236
|
standardBrowser: !(0, import_runtime.isNative)(),
|
|
@@ -287,16 +240,7 @@ function ClerkProvider(props) {
|
|
|
287
240
|
rethrowOfflineNetworkErrors: !!__experimental_resourceCache || (experimental == null ? void 0 : experimental.rethrowOfflineNetworkErrors),
|
|
288
241
|
...(0, import_runtime.isNative)() && { runtimeEnvironment: "headless" }
|
|
289
242
|
},
|
|
290
|
-
children
|
|
291
|
-
(0, import_runtime.isNative)() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
292
|
-
NativeSessionSync,
|
|
293
|
-
{
|
|
294
|
-
publishableKey: pk,
|
|
295
|
-
tokenCache
|
|
296
|
-
}
|
|
297
|
-
),
|
|
298
|
-
children
|
|
299
|
-
]
|
|
243
|
+
children
|
|
300
244
|
},
|
|
301
245
|
pk
|
|
302
246
|
);
|