Skip to content

@gj-kit/expo-auth recipes

Each code block reuses a public-contract example already type-checked in the package README.

Choose storage and a refresh callback once; the package coordinates callers around that application-owned boundary.

Outcome: One app-owned session that persists login state and coordinates concurrent refreshes.

Application-owned boundary: Choose the storage adapter once and connect only your refresh-endpoint callback.

import { createAuthSession, type RefreshRequest } from '@gj-kit/expo-auth';
import { createTokenStorage, createWebLocksRefreshLock } from '@gj-kit/expo-auth/storage';
declare const refresh: RefreshRequest; // Your API client classifies rotated, invalid, or transient.
export const session = createAuthSession({
storage: createTokenStorage({ keyPrefix: 'myapp.auth' }),
lock: createWebLocksRefreshLock({ name: 'myapp.auth' }),
refresh,
});

2. Handle every refresh outcome explicitly

Section titled “2. Handle every refresh outcome explicitly”

Use the matcher so an omitted transient or rotated branch is a compile error.

The five endings of refresh() are consumed by key, so the omission that turns a network blip into a false logout is rejected at compile time; tokens is reachable only after narrowing to refreshed or adopted, and a refresh callback that throws arrives here as transient with the thrown value in cause.

import { matchRefreshOutcome, type RefreshOutcome } from '@gj-kit/expo-auth';
declare const outcome: RefreshOutcome; // the app owns this — it is `await session.refresh()`
declare const goToSignIn: () => null; // the app owns navigation
declare const report: (cause: unknown) => void; // the app owns telemetry
export const accessToken = matchRefreshOutcome<string | null>(outcome, {
refreshed: ({ tokens }) => tokens.accessToken, // `tokens` exists here and on `adopted` only
adopted: ({ tokens }) => tokens.accessToken,
'signed-out': () => goToSignIn(),
invalid: () => goToSignIn(), // a definitive server rejection
transient: ({ cause }) => {
report(cause); // stored tokens are left untouched — a 5xx is not a sign-out
return null;
},
});
// Delete the `transient` line above and tsc refuses the call:
// error TS2345: ... Property 'transient' is missing in type ... but required in type ...

Use the complete API reference for every export and import path.