From 4492bbaf82dcedd2e5cbb807093fbc303e1773b7 Mon Sep 17 00:00:00 2001 From: panteliselef Date: Fri, 24 May 2024 17:57:30 +0300 Subject: [PATCH] chore(clerk-expo): Use `getClerkInstance` --- .changeset/calm-wasps-accept.md | 10 ++--- packages/expo/src/ClerkProvider.tsx | 13 +++--- packages/expo/src/index.ts | 4 +- packages/expo/src/singleton.ts | 64 +++++++++++++---------------- 4 files changed, 41 insertions(+), 50 deletions(-) diff --git a/.changeset/calm-wasps-accept.md b/.changeset/calm-wasps-accept.md index 88c309b7aa9..442818d3358 100644 --- a/.changeset/calm-wasps-accept.md +++ b/.changeset/calm-wasps-accept.md @@ -2,21 +2,21 @@ '@clerk/clerk-expo': minor --- -Introduce `createClerkClient` to avoid importing the Clerk class from clerk-js manually. +Introduce `getClerkIntance()` to avoid importing the Clerk class from clerk-js manually. This enables developers to create and access a Clerk instance in their application outside of React. ```tsx -import { ClerkProvider, createClerkClient } from "@clerk/expo" +import { ClerkProvider, getClerkIntance } from "@clerk/expo" -const clerkInstance = createClerkClient({ publishableKey: 'xxxx' }) +const clerkInstance = getClerkIntance({ publishableKey: 'xxxx' }) // Be sure to pass the new instance to ClerkProvider to avoid running multiple instances of Clerk in your application - + ... // Somewhere in your code, outside of React you can do -const token = await Clerk.session?.getToken(); +const token = await clerkInstance.session?.getToken(); fetch('http://example.com/', {headers: {Authorization: token }) ``` diff --git a/packages/expo/src/ClerkProvider.tsx b/packages/expo/src/ClerkProvider.tsx index cdccccbd110..cc5bf76d10a 100644 --- a/packages/expo/src/ClerkProvider.tsx +++ b/packages/expo/src/ClerkProvider.tsx @@ -7,25 +7,24 @@ import React from 'react'; import type { TokenCache } from './cache'; import { MemoryTokenCache } from './cache'; import { isReactNative } from './runtime'; -import { buildClerk } from './singleton'; +import { getClerkInstance } from './singleton'; export type ClerkProviderProps = ClerkReactProviderProps & { tokenCache?: TokenCache; }; export function ClerkProvider(props: ClerkProviderProps): JSX.Element { - const { children, tokenCache = MemoryTokenCache, publishableKey, Clerk, ...rest } = props; - const pkClerk = typeof Clerk !== 'function' ? Clerk?.publishableKey : undefined; - const key = publishableKey || pkClerk || process.env.CLERK_PUBLISHABLE_KEY || ''; + const { children, tokenCache = MemoryTokenCache, publishableKey, ...rest } = props; + const pk = publishableKey || process.env.CLERK_PUBLISHABLE_KEY || ''; return ( {children} diff --git a/packages/expo/src/index.ts b/packages/expo/src/index.ts index d90590cac36..4fa4c6b6a0e 100644 --- a/packages/expo/src/index.ts +++ b/packages/expo/src/index.ts @@ -18,10 +18,10 @@ export { export { isClerkAPIResponseError, isEmailLinkError, isKnownError, isMetamaskError } from '@clerk/clerk-react/errors'; /** - * @deprecated Use `createClerkClient()` instead. + * @deprecated Use `getClerkInstance()` instead. */ export { clerk as Clerk } from './singleton'; -export { createClerkClient } from './singleton'; +export { getClerkInstance } from './singleton'; export * from './ClerkProvider'; export * from './useOAuth'; diff --git a/packages/expo/src/singleton.ts b/packages/expo/src/singleton.ts index cf2b4c32f59..eb29936ea56 100644 --- a/packages/expo/src/singleton.ts +++ b/packages/expo/src/singleton.ts @@ -13,58 +13,50 @@ Clerk.sdkMetadata = { const KEY = '__clerk_client_jwt'; /** - * @deprecated This export will be dropped + * @deprecated Use `getClerkInstance` instead. `Clerk` will be removed in the next major version. */ export let clerk: HeadlessBrowserClerk; +let __internal_clerk: HeadlessBrowserClerk; type BuildClerkOptions = { publishableKey?: string; tokenCache?: TokenCache; }; -export function createClerkClient({ +export function getClerkInstance({ publishableKey = process.env.CLERK_PUBLISHABLE_KEY || '', tokenCache = MemoryTokenCache, }: BuildClerkOptions): HeadlessBrowserClerk { - const clerk = new Clerk(publishableKey); - - tokenCache.clearToken?.(KEY); - - const getToken = tokenCache.getToken; - const saveToken = tokenCache.saveToken; - - clerk.__unstable__onBeforeRequest(async (requestInit: FapiRequestInit) => { - // https://reactnative.dev/docs/0.61/network#known-issues-with-fetch-and-cookie-based-authentication - requestInit.credentials = 'omit'; - - requestInit.url?.searchParams.append('_is_native', '1'); - - const jwt = await getToken(KEY); - (requestInit.headers as Headers).set('authorization', jwt || ''); - }); + // Support "hot-swapping" the Clerk instance at runtime. See JS-598 for additional details. + const hasKeyChanged = __internal_clerk && publishableKey !== __internal_clerk.publishableKey; - // @ts-expect-error - clerk.__unstable__onAfterResponse(async (_: FapiRequestInit, response: FapiResponse) => { - const authHeader = response.headers.get('authorization'); - if (authHeader) { - await saveToken(KEY, authHeader); + if (!__internal_clerk || hasKeyChanged) { + if (hasKeyChanged) { + tokenCache.clearToken?.(KEY); } - }); - return clerk; -} + const getToken = tokenCache.getToken; + const saveToken = tokenCache.saveToken; + __internal_clerk = clerk = new Clerk(publishableKey); -export function buildClerk({ publishableKey, tokenCache }: Required): HeadlessBrowserClerk { - // Support "hot-swapping" the Clerk instance at runtime. See JS-598 for additional details. - const hasKeyChanged = clerk && publishableKey !== clerk.publishableKey; + // @ts-expect-error + __internal_clerk.__unstable__onBeforeRequest(async (requestInit: FapiRequestInit) => { + // https://reactnative.dev/docs/0.61/network#known-issues-with-fetch-and-cookie-based-authentication + requestInit.credentials = 'omit'; - if (hasKeyChanged) { - tokenCache.clearToken?.(KEY); - } + requestInit.url?.searchParams.append('_is_native', '1'); - if (!clerk || hasKeyChanged) { - clerk = createClerkClient({ publishableKey, tokenCache }); - } + const jwt = await getToken(KEY); + (requestInit.headers as Headers).set('authorization', jwt || ''); + }); - return clerk; + // @ts-expect-error + __internal_clerk.__unstable__onAfterResponse(async (_: FapiRequestInit, response: FapiResponse) => { + const authHeader = response.headers.get('authorization'); + if (authHeader) { + await saveToken(KEY, authHeader); + } + }); + } + return __internal_clerk; }