@archlast/sdk-expo
v0.1.1
Published
Archlast SDK for Expo (React Native) with SecureStore and deep linking
Readme
@archlast/sdk-expo
Archlast SDK for Expo (React Native) with SecureStore and deep linking support.
Installation
npm install @archlast/sdk-expo
npx expo install expo-secure-storeFeatures
- Secure Storage: Uses
expo-secure-storefor session persistence - Deep Linking: OAuth callback support via deep links
- Better-Auth Wrapped: No need to install
better-authdirectly - React Native Hooks:
useAuth(),useSession() - Type-Safe: Full TypeScript support
Configuration
1. Update app.json
Add your app's scheme to app.json for deep linking:
{
"expo": {
"scheme": "archlast",
"extra": {
"eas": {
"projectId": "your-project-id"
}
}
}
}2. Update Metro Config
Enable package exports in metro.config.js:
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.resolver.unstable_enablePackageExports = true;
module.exports = config;Or use babel plugin resolution:
// babel.config.js
module.exports = function (api) {
return {
presets: ["babel-preset-expo"],
plugins: [
[
"module-resolver",
{
alias: {
"better-auth/react":
"./node_modules/better-auth/dist/client/react/index.mjs",
"better-auth/client/plugins":
"./node_modules/better-auth/dist/client/plugins/index.mjs",
"@better-auth/expo/client":
"./node_modules/@better-auth/expo/dist/client.mjs",
},
},
],
],
};
};3. Environment Variables
# Optional: Set Better-Auth server URL
EXPO_PUBLIC_BETTER_AUTH_URL=http://localhost:4000
# Or use Archlast URL
EXPO_PUBLIC_ARCHLAST_HTTP_URL=http://localhost:4000
# Optional: Set deep link scheme (default: archlast)
EXPO_PUBLIC_DEEP_LINK_SCHEME=archlastUsage
Basic Client
import { BaseClient } from "@archlast/sdk-expo";
const client = new BaseClient({
baseUrl: "http://localhost:4000",
});
// Query
const tasks = await client.query("listTasks", { limit: 10 });
// Mutate
const task = await client.mutate("createTask", {
text: "New task",
});Authentication
"use client";
import { authClient } from "@archlast/sdk-expo/auth";
import { useAuth } from "@archlast/sdk-expo/react";
export default function LoginScreen() {
const { signIn, session, isLoading } = useAuth();
const handleLogin = async () => {
await authClient.signIn.email({
email: "[email protected]",
password: "password",
});
};
if (isLoading) return <ActivityIndicator />;
if (session) {
return <Text>Welcome {session.user.name}</Text>;
}
return <Button title="Sign In" onPress={handleLogin} />;
}Deep Link Handling
For OAuth providers, handle the deep link callback:
{
"expo": {
"scheme": "archlast"
}
}import * as React from "react";
import { useEffect } from "react";
import { parseOAuthCallback, getInitialURL, addDeepLinkListener } from "@archlast/sdk-expo/linking";
export default function App() {
useEffect(() => {
// Handle initial URL (app opened from OAuth redirect)
getInitialURL().then((url) => {
if (url) {
const callback = parseOAuthCallback(url);
// Exchange code for session...
}
});
// Listen for deep links while app is running
const subscription = addDeepLinkListener(({ url }) => {
const callback = parseOAuthCallback(url);
// Handle callback...
});
return () => subscription.remove();
}, []);
return <YourRootComponent />;
}Social Sign-In
import { authClient } from "@archlast/sdk-expo/auth";
export default function SocialLogin() {
const handleGoogleLogin = async () => {
await authClient.signIn.social({
provider: "google",
callbackURL: "/dashboard", // Becomes archlast://dashboard
});
};
return <Button title="Login with Google" onPress={handleGoogleLogin} />;
}Protected Routes
import { useAuth } from "@archlast/sdk-expo/react";
export default function ProtectedScreen() {
const { session, isLoading } = useAuth();
if (isLoading) return <ActivityIndicator />;
if (!session) {
return <LoginPage />;
}
return <DashboardScreen />;
}API
Client Creation
import { BaseClient } from "@archlast/sdk-expo";
const client = new BaseClient({
baseUrl: string; // Archlast server URL
appId?: string; // Optional app ID for isolation
apiKey?: string; // Better-Auth API key
});Auth
authClient- Default Better-Auth clientuseSession()- Hook for session statecreateAuthClient(options)- Create custom client
Storage
secureStoreAdapter- SecureStore adapter for Better-AuthinitializeSecureStoreAdapter()- Initialize the SecureStore adapter
Linking
parseOAuthCallback(url)- Parse OAuth deep linkgetInitialURL()- Get app's opening URLaddDeepLinkListener(callback)- Listen for deep linksopenOAuthURL(url)- Open OAuth provider in browser
Session Persistence
Sessions are automatically persisted in SecureStore with these settings:
- Storage:
expo-secure-store(encrypted on most devices) - Prefix:
better-auth.session_token - Sync: Automatic with Better-Auth server
Web Support
The SDK works on Expo Web (in development) using:
- Cookies instead of SecureStore
- Standard browser navigation
- Same API as native
Troubleshooting
Metro Bundler Issues
If you see import errors, add to babel.config.js:
plugins: [
[
"module-resolver",
{
alias: {
"better-auth/react": "./node_modules/better-auth/dist/client/react/index.mjs",
"@better-auth/expo/client": "./node_modules/@better-auth/expo/dist/client.mjs",
},
},
],
];Deep Links Not Working
- Check
app.jsonhas the correct scheme - Ensure
EXPO_PUBLIC_DEEP_LINK_SCHEMEmatches - Test with:
npx expo url --scheme archlast
Clear Cache
npx expo start --clearLicense
MIT
