Skip to content

AuthSession — @gj-kit/expo-auth

A public interface from @gj-kit/expo-auth. The signature below is taken directly from the 0.1.1 release declaration.

import { AuthSession } from '@gj-kit/expo-auth';
/**
* An auth session (design §3.5): storage binding (signIn/signOut), single-flight refresh with
* cross-tab adoption, retry-once request wrapping and the proactive refresh scheduler.
*
* ⚠ The single flight is **per instance** — create exactly one per app (a module-scope
* singleton is the recommended shape, §7-6).
*/
interface AuthSession {
/** The stored access token (bearer injection belongs to the app's HTTP layer — §6-1). */
getAccessToken(): Promise<string | null>;
getTokens(): Promise<TokenPair | null>;
/**
* Persist tokens and schedule the proactive refresh. (Calling the login API is app-owned.)
*
* - `persistence` is **required**: `clearTokens`/`signOut` reset the mode to the
* implementation default, so an optional here would let "session login → signOut →
* option-less re-login" silently promote to durable — betraying the shared-PC user who
* chose a session login. The library does not know the product's persistence policy, so a
* default would be a lie (§4.1-⑥). Only internal rotations use the mode-sticky omission
* (H14).
* - `accessTtlSeconds`: the login response's `expires_in` — first-priority TTL source for
* the initial schedule (§3.5 priority ①).
*/
signIn(tokens: TokenPair, options: {
readonly persistence: TokenPersistence;
readonly accessTtlSeconds?: number | undefined;
}): Promise<void>;
/** Cancel the schedule and clear tokens. Idempotent. */
signOut(): Promise<void>;
/**
* Single flight (H4): concurrent calls on this instance share one in-flight result. With a
* lock, the critical section is serialized across tabs (H5). After acquiring the lock the
* storage is re-read: if it was already rotated the pair is adopted without consuming it
* (H2b), and after a failed request a re-read that finds a rotation also adopts (H2).
* A `'rotated'` result is persisted only while the attempted pair is still the stored one
* (the H3 discipline applied to the success path): a signOut/signIn or another tab's write
* that raced the in-flight request wins — the outcome becomes `'signed-out'`/`'adopted'`
* and the stale rotation is discarded. `'refreshed'`/`'adopted'` return only after
* rescheduling completed.
*
* Lock-boundary invariant (§3.5): the critical section spans from the post-lock re-read
* (H2b) through persisting the result — `setTokens` for `'rotated'`, `clearTokens` for a
* confirmed invalid (H3) — and the lock is NOT released before persistence completes.
* Releasing earlier would let the next tab's post-lock re-read observe the pre-rotation
* state and replay a consumed single-use token.
*/
refresh(): Promise<RefreshOutcome>;
/**
* Eager refresh on foreground return (H9). Refreshes only when the remaining lifetime is
* ≤ `thresholdSeconds` (default 120). When the lifetime is unknown (non-JWT and no strategy)
* it returns `'not-needed'` — preserving the predecessor's behavior. The return union is the
* named type {@link EagerRefreshOutcome} (§3.4).
*/
refreshIfExpiringSoon(options?: {
readonly thresholdSeconds?: number | undefined;
}): Promise<EagerRefreshOutcome>;
/**
* 401 → refresh → retry exactly once (H6), structurally: the retry execution cannot re-enter
* the refresh path (the predecessor's `allowRefresh` boolean recursion is unrepresentable).
* `run` receives the access token current at each attempt (an expired header can never be
* replayed — H6). Flow: `run(current token)` → it throws `e` → if
* `shouldRetryAfterRefresh(e)` and a token existed, `refresh()` → on
* `'refreshed'`/`'adopted'` run once with the new token — that result is final (value or
* throw). Any other outcome (`'invalid'`/`'transient'`/`'signed-out'`) rethrows the original
* `e` — on transient the tokens are untouched, so upstream retry policy takes over (H1).
*/
runAuthorized<T>(run: (accessToken: string | null) => Promise<T>, options: {
/** Classifies "expired 401" in the app's error vocabulary. Required — no default (§4.1-④). */
readonly shouldRetryAfterRefresh: (error: unknown) => boolean;
}): Promise<T>;
/**
* (Re)arm the proactive refresh timer from the stored tokens. Hosts call this right after
* boot restore. Empty storage cancels instead of arming — the fallback TTL applies only to
* a present token whose expiry is unknown, so a never-signed-in app gets no timer and no
* spurious background `'signed-out'` outcome.
*/
scheduleRefresh(): Promise<void>;
cancelScheduledRefresh(): void;
/** Release the timer; every later method call throws `AuthError('session-disposed')`. */
dispose(): void;
}

This declaration is the source of truth for parameters, optionality, generics, return values, and public union/type contracts. Check the package golden path and this subpath’s import conditions for required environment, permission, and error boundaries before calling it.

  • Package: @gj-kit/expo-auth
  • Version: 0.1.1
  • Public entry: .
  • Source: GitHub