11import { inBrowser } from './browser' ;
2- import type { ClerkStatus , GetTokenOptions , LoadedClerk } from './types' ;
2+ import { ClerkRuntimeError } from './errors/clerkRuntimeError' ;
3+ import type { Clerk , ClerkStatus , GetTokenOptions , LoadedClerk } from './types' ;
34
45const POLL_INTERVAL_MS = 50 ;
56const MAX_POLL_RETRIES = 100 ; // 5 seconds of polling
67const TIMEOUT_MS = 10000 ; // 10 second absolute timeout
78
8- type WindowClerk = LoadedClerk & {
9- status ?: ClerkStatus ;
10- loaded ?: boolean ;
11- on ?: ( event : 'status' , handler : ( status : ClerkStatus ) => void , opts ?: { notify ?: boolean } ) => void ;
12- off ?: ( event : 'status' , handler : ( status : ClerkStatus ) => void ) => void ;
13- } ;
14-
15- function getWindowClerk ( ) : WindowClerk | undefined {
9+ function getWindowClerk ( ) : Clerk | undefined {
1610 if ( inBrowser ( ) && 'Clerk' in window ) {
17- return ( window as unknown as { Clerk ?: WindowClerk } ) . Clerk ;
11+ return ( window as unknown as { Clerk ?: Clerk } ) . Clerk ;
1812 }
1913 return undefined ;
2014}
2115
22- class ClerkNotLoadedError extends Error {
23- constructor ( ) {
24- super ( 'Clerk: Timeout waiting for Clerk to load. Ensure ClerkProvider is mounted.' ) ;
25- this . name = 'ClerkNotLoadedError' ;
26- }
27- }
28-
29- class ClerkNotAvailableError extends Error {
30- constructor ( ) {
31- super ( 'Clerk: getToken can only be used in browser environments.' ) ;
32- this . name = 'ClerkNotAvailableError' ;
33- }
34- }
35-
3616function waitForClerk ( ) : Promise < LoadedClerk > {
3717 return new Promise ( ( resolve , reject ) => {
3818 if ( ! inBrowser ( ) ) {
39- reject ( new ClerkNotAvailableError ( ) ) ;
19+ reject (
20+ new ClerkRuntimeError ( 'getToken can only be used in browser environments.' , {
21+ code : 'clerk_runtime_not_browser' ,
22+ } ) ,
23+ ) ;
4024 return ;
4125 }
4226
@@ -53,22 +37,25 @@ function waitForClerk(): Promise<LoadedClerk> {
5337 }
5438
5539 let retries = 0 ;
56- let timeoutId : ReturnType < typeof setTimeout > ;
5740 let statusHandler : ( ( status : ClerkStatus ) => void ) | undefined ;
5841 let pollTimeoutId : ReturnType < typeof setTimeout > ;
59- let currentClerk : WindowClerk | undefined = clerk ;
42+ let currentClerk : Clerk | undefined = clerk ;
6043
6144 const cleanup = ( ) => {
6245 clearTimeout ( timeoutId ) ;
6346 clearTimeout ( pollTimeoutId ) ;
64- if ( statusHandler && currentClerk ?. off ) {
47+ if ( statusHandler && currentClerk ) {
6548 currentClerk . off ( 'status' , statusHandler ) ;
6649 }
6750 } ;
6851
69- timeoutId = setTimeout ( ( ) => {
52+ const timeoutId = setTimeout ( ( ) => {
7053 cleanup ( ) ;
71- reject ( new ClerkNotLoadedError ( ) ) ;
54+ reject (
55+ new ClerkRuntimeError ( 'Timeout waiting for Clerk to load.' , {
56+ code : 'clerk_runtime_load_timeout' ,
57+ } ) ,
58+ ) ;
7259 } , TIMEOUT_MS ) ;
7360
7461 const checkAndResolve = ( ) => {
@@ -94,14 +81,18 @@ function waitForClerk(): Promise<LoadedClerk> {
9481 return ;
9582 }
9683
97- if ( ! statusHandler && currentClerk . on ) {
84+ if ( ! statusHandler ) {
9885 statusHandler = ( status : ClerkStatus ) => {
9986 if ( status === 'ready' || status === 'degraded' ) {
10087 cleanup ( ) ;
10188 resolve ( currentClerk as LoadedClerk ) ;
10289 } else if ( status === 'error' ) {
10390 cleanup ( ) ;
104- reject ( new ClerkNotLoadedError ( ) ) ;
91+ reject (
92+ new ClerkRuntimeError ( 'Clerk failed to initialize.' , {
93+ code : 'clerk_runtime_init_error' ,
94+ } ) ,
95+ ) ;
10596 }
10697 } ;
10798
@@ -123,10 +114,13 @@ function waitForClerk(): Promise<LoadedClerk> {
123114 * @param options.organizationId - Organization ID to include in the token
124115 * @param options.leewayInSeconds - Number of seconds of leeway for token expiration
125116 * @param options.skipCache - Whether to skip the token cache
126- * @returns A Promise that resolves to the session token, or `null` if:
127- * - The user is not signed in
128- * - Clerk failed to load
129- * - Called in a non-browser environment
117+ * @returns A Promise that resolves to the session token, or `null` if the user is not signed in
118+ *
119+ * @throws {ClerkRuntimeError } When called in a non-browser environment (code: `clerk_runtime_not_browser`)
120+ *
121+ * @throws {ClerkRuntimeError } When Clerk fails to load within timeout (code: `clerk_runtime_load_timeout`)
122+ *
123+ * @throws {ClerkRuntimeError } When Clerk fails to initialize (code: `clerk_runtime_init_error`)
130124 *
131125 * @example
132126 * ```typescript
@@ -143,18 +137,11 @@ function waitForClerk(): Promise<LoadedClerk> {
143137 * ```
144138 */
145139export async function getToken ( options ?: GetTokenOptions ) : Promise < string | null > {
146- try {
147- const clerk = await waitForClerk ( ) ;
140+ const clerk = await waitForClerk ( ) ;
148141
149- if ( ! clerk . session ) {
150- return null ;
151- }
152-
153- return await clerk . session . getToken ( options ) ;
154- } catch ( error ) {
155- if ( process . env . NODE_ENV === 'development' ) {
156- console . warn ( '[Clerk] getToken failed:' , error ) ;
157- }
142+ if ( ! clerk . session ) {
158143 return null ;
159144 }
145+
146+ return clerk . session . getToken ( options ) ;
160147}
0 commit comments