Skip to content

Commit

Permalink
feat(expo): Support for Expo Web
Browse files Browse the repository at this point in the history
  • Loading branch information
octoper committed May 28, 2024
1 parent ef8ef17 commit bc6fcc1
Show file tree
Hide file tree
Showing 18 changed files with 3,001 additions and 562 deletions.
3,429 changes: 2,894 additions & 535 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/expo/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module.exports = {
root: true,
extends: ['@clerk/custom/node', '@clerk/custom/typescript', '@clerk/custom/jest', '@clerk/custom/react'],
settings: {
'import/ignore': ['node_modules/react-native/index\\.js$'],
},
};
12 changes: 11 additions & 1 deletion packages/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,17 @@
},
"license": "MIT",
"author": "Clerk",
"main": "dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"react-native": "./src/index.ts",
"import": "./dist/index.js",
"require": "./dist/index.js"
}
},
"main": "dist/index",
"source": "src/index.js",
"react-native": "./src/index",
"typings": "dist/index.d.ts",
"files": [
"dist"
Expand Down Expand Up @@ -55,6 +64,7 @@
"@types/react-dom": "*",
"expo-auth-session": "^5.4.0",
"expo-web-browser": "^12.8.2",
"react-native": "^0.74.1",
"typescript": "*"
},
"peerDependencies": {
Expand Down
6 changes: 3 additions & 3 deletions packages/expo/src/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import React from 'react';

import type { TokenCache } from './cache';
import { MemoryTokenCache } from './cache';
import { isReactNative } from './runtime';
import { buildClerk } from './singleton';
import { isNative } from './utils/runtime';

export type ClerkProviderProps = ClerkReactProviderProps & {
tokenCache?: TokenCache;
Expand All @@ -24,8 +24,8 @@ export function ClerkProvider(props: ClerkProviderProps): JSX.Element {
key={key}
{...rest}
publishableKey={key}
Clerk={buildClerk({ key, tokenCache })}
standardBrowser={!isReactNative()}
Clerk={isNative() ? buildClerk({ key, tokenCache }) : null}
standardBrowser={!isNative()}
>
{children}
</ClerkReactProvider>
Expand Down
1 change: 1 addition & 0 deletions packages/expo/src/components/controlComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ClerkLoaded, ClerkLoading, SignedIn, SignedOut } from '@clerk/clerk-react';
2 changes: 2 additions & 0 deletions packages/expo/src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './controlComponents';
export * from './uiComponents';
30 changes: 30 additions & 0 deletions packages/expo/src/components/uiComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
OrganizationList as BaseOrganizationList,
OrganizationProfile as BaseOrganizationProfile,
OrganizationSwitcher as BaseOrganizationSwitcher,
SignIn as BaseSignIn,
SignUp as BaseSignUp,
UserButton as BaseUserButton,
} from '@clerk/clerk-react';
import React from 'react';
import { Platform, Text } from 'react-native';

const ErrorComponent = () => {
return <Text>Component not supported on ths platform</Text>;
};

function WrapComponent<T extends { displayName: string }>(component: T) {
// @ts-expect-error - This is a hack to make the function signature match the original
return Platform.select<T>({
// @ts-expect-error - This is a hack to make the function signature match the original
native: () => ErrorComponent,
default: () => component,
})();
}

export const SignIn: typeof BaseSignIn = WrapComponent(BaseSignIn);
export const SignUp: typeof BaseSignUp = WrapComponent(BaseSignUp);
export const UserButton: typeof BaseUserButton = WrapComponent(BaseUserButton);
export const OrganizationProfile: typeof BaseOrganizationProfile = WrapComponent(BaseOrganizationProfile);
export const OrganizationSwitcher: typeof BaseOrganizationSwitcher = WrapComponent(BaseOrganizationSwitcher);
export const OrganizationList: typeof BaseOrganizationList = WrapComponent(BaseOrganizationList);
14 changes: 14 additions & 0 deletions packages/expo/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export {
useAuth,
useClerk,
useEmailLink,
useOrganization,
useOrganizationList,
useSession,
useSessionList,
useSignIn,
useSignUp,
useUser,
} from '@clerk/clerk-react';

export * from './useOAuth';
1 change: 1 addition & 0 deletions packages/expo/src/hooks/useOAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useOAuthImpl';
File renamed without changes.
13 changes: 13 additions & 0 deletions packages/expo/src/hooks/useOAuthImpl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { OAuthStrategy } from '@clerk/types';
import { Platform } from 'react-native';

export type UseOAuthFlowParams = {
strategy: OAuthStrategy;
redirectUrl?: string;
unsafeMetadata?: SignUpUnsafeMetadata;
};
export function useOAuth(_useOAuthParams: UseOAuthFlowParams) {
if (Platform.OS === 'web') {
throw new Error('OAuth flow is not supported in web');
}
}
22 changes: 3 additions & 19 deletions packages/expo/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,12 @@
export {
ClerkLoaded,
ClerkLoading,
SignedIn,
SignedOut,
useAuth,
useClerk,
useEmailLink,
useOrganization,
useOrganizationList,
useSession,
useSessionList,
useSignIn,
useSignUp,
useUser,
} from '@clerk/clerk-react';
import { setErrorThrowerOptions } from '@clerk/clerk-react/internal';

export { isClerkAPIResponseError, isEmailLinkError, isKnownError, isMetamaskError } from '@clerk/clerk-react/errors';

export { clerk as Clerk } from './singleton';

export * from './ClerkProvider';
export * from './useOAuth';
export * from './hooks';
export * from './components';

// Override Clerk React error thrower to show that errors come from @clerk/clerk-expo
import { setErrorThrowerOptions } from '@clerk/clerk-react/internal';

setErrorThrowerOptions({ packageName: PACKAGE_NAME });
3 changes: 0 additions & 3 deletions packages/expo/src/runtime.ts

This file was deleted.

3 changes: 3 additions & 0 deletions packages/expo/src/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { buildErrorThrower } from '@clerk/shared/error';

export const errorThrower = buildErrorThrower({ packageName: PACKAGE_NAME });
2 changes: 2 additions & 0 deletions packages/expo/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './errors';
export * from './runtime';
18 changes: 18 additions & 0 deletions packages/expo/src/utils/runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Platform } from 'react-native';

export function isWeb(): boolean {
return Platform.OS === 'web';
}

export function isNative(): boolean {
return Platform.OS !== 'web';
}

export function isHermes() {
//@ts-expect-error HermesInternal is added only added by the Hermes JS Engine
return !!global.HermesInternal;
}

export function reactNativeVersion() {
return Platform.constants.reactNativeVersion;
}
3 changes: 2 additions & 1 deletion packages/expo/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"allowJs": true,
"target": "ES2019",
"noEmitOnError": false,
"incremental": true
"incremental": true,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
"include": ["src"]
}
1 change: 1 addition & 0 deletions packages/expo/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default defineConfig(overrideOptions => {
minify: false,
sourcemap: true,
legacyOutput: true,
skipNodeModulesBundle: true,
define: {
PACKAGE_NAME: `"${name}"`,
PACKAGE_VERSION: `"${version}"`,
Expand Down

0 comments on commit bc6fcc1

Please sign in to comment.