Skip to content

Commit e2b6a9f

Browse files
authored
fix(expo): preserve token cache method context (#8713)
1 parent ff0cfef commit e2b6a9f

3 files changed

Lines changed: 52 additions & 2 deletions

File tree

.changeset/clean-token-cache.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/expo': patch
3+
---
4+
5+
Preserve custom token cache method context when initializing the native Clerk singleton.

packages/expo/src/provider/singleton/__tests__/createClerkInstance.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { Clerk } from '@clerk/clerk-js';
22
import { beforeEach, describe, expect, test, vi } from 'vitest';
33

4+
import type { TokenCache } from '../../../cache/types';
5+
import { CLERK_CLIENT_JWT_KEY } from '../../../constants';
6+
47
const mocks = vi.hoisted(() => {
58
return {
69
constructorSpy: vi.fn(),
@@ -239,4 +242,46 @@ describe('createClerkInstance', () => {
239242
}),
240243
).toThrow(/`proxyUrl` must be a string/);
241244
});
245+
246+
test('preserves tokenCache method context for class instances', async () => {
247+
class InstanceTokenCache implements TokenCache {
248+
private readonly tokens = new Map<string, string>();
249+
250+
getToken(key: string) {
251+
return Promise.resolve(this.tokens.get(key) ?? null);
252+
}
253+
254+
saveToken(key: string, token: string) {
255+
this.tokens.set(key, token);
256+
return Promise.resolve();
257+
}
258+
}
259+
260+
const tokenCache = new InstanceTokenCache();
261+
await tokenCache.saveToken(CLERK_CLIENT_JWT_KEY, 'cached-token');
262+
263+
const createClerkInstance = await loadCreateClerkInstance();
264+
const getClerkInstance = createClerkInstance(MockClerk as unknown as typeof Clerk);
265+
const clerk = getClerkInstance({
266+
publishableKey: 'pk_test_123',
267+
tokenCache,
268+
}) as unknown as MockClerk;
269+
270+
const beforeRequest = clerk.__internal_onBeforeRequest.mock.calls[0][0];
271+
const requestInit = {
272+
headers: new Headers(),
273+
url: new URL('https://clerk.example.com/v1/client'),
274+
};
275+
await beforeRequest(requestInit);
276+
277+
expect(requestInit.headers.get('authorization')).toBe('cached-token');
278+
279+
const afterResponse = clerk.__internal_onAfterResponse.mock.calls[0][0];
280+
await afterResponse(requestInit, {
281+
headers: new Headers({ authorization: 'fresh-token' }),
282+
payload: null,
283+
});
284+
285+
await expect(tokenCache.getToken(CLERK_CLIENT_JWT_KEY)).resolves.toBe('fresh-token');
286+
});
242287
});

packages/expo/src/provider/singleton/createClerkInstance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ export function createClerkInstance(ClerkClass: typeof Clerk) {
106106
tokenCache.clearToken?.(CLERK_CLIENT_JWT_KEY);
107107
}
108108

109-
const getToken = tokenCache.getToken;
110-
const saveToken = tokenCache.saveToken;
109+
const getToken = (key: string) => tokenCache.getToken(key);
110+
const saveToken = (key: string, token: string) => tokenCache.saveToken(key, token);
111111

112112
__internal_clerkOptions = { publishableKey, proxyUrl, domain };
113113
__internal_clerk = new ClerkClass(publishableKey, { proxyUrl, domain }) as unknown as BrowserClerk;

0 commit comments

Comments
 (0)