Skip to content

React Native

@potalab/base/rn re-exports everything from @potalab/base and adds native session storage, background-aware token refresh and PKCE that works without crypto.subtle (Hermes). Native modules are passed in by your app, so the package has no hard native dependency.

Terminal window
npx expo install expo-secure-store expo-crypto expo-web-browser
pnpm add @potalab/base
import { AppState } from "react-native"
import * as SecureStore from "expo-secure-store"
import * as ExpoCrypto from "expo-crypto"
import { createClient, secureStoreAdapter, expoCrypto } from "@potalab/base/rn"
import type { Database } from "./db"
export const base = createClient<Database>({
url: process.env.EXPO_PUBLIC_POTALAB_BASE_URL!,
key: process.env.EXPO_PUBLIC_POTALAB_BASE_KEY!,
auth: { storage: secureStoreAdapter(SecureStore), crypto: expoCrypto(ExpoCrypto) },
appState: AppState, // pauses refresh in the background, refreshes on return if due
})

Open the provider in an in-app browser and parse the callback:

import * as WebBrowser from "expo-web-browser"
import { parseAuthCallback } from "@potalab/base/rn"
const redirectTo = "myapp://auth/callback"
const { data } = await base.auth.signInWithOAuth({ provider: "google", redirectTo, skipBrowserRedirect: true })
const res = await WebBrowser.openAuthSessionAsync(data.url!, redirectTo)
if (res.type === "success") {
const { code, error } = parseAuthCallback(res.url)
if (code) await base.auth.exchangeCodeForSession(code)
}

redirectTo must be on the project’s redirect allowlist. Custom app schemes such as myapp://auth are allowed.

  • PKCE without crypto.subtle: expoCrypto(), or the global getRandomValues with a pure-JS SHA-256.
  • expo-secure-store keys are sanitized and values over about 2 KB are split into chunks.
  • The client avoids URL.host and URL.searchParams.set, which React Native’s URL polyfill rejects.
  • Realtime uses React Native’s global WebSocket.
  • The returned client has a dispose() method to stop its timers and listeners.