AuthSession — @gj-kit/expo-auth
@gj-kit/expo-auth에서 공개하는 interface입니다. package version 0.1.1의 release declaration을 그대로 표시합니다.
검증된 import 예제
섹션 제목: “검증된 import 예제”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;}이 선언은 매개변수, optionality, 제네릭, 반환값, 공개 union/type 계약의 정본입니다. 호출 전 필요한 환경·권한·오류 경계는 패키지 Golden path와 이 subpath의 import 조건을 함께 확인하세요.
Release context
섹션 제목: “Release context”- 패키지:
@gj-kit/expo-auth - 버전:
0.1.1 - 공개 entry:
. - 소스: GitHub
구현 주석
섹션 제목: “구현 주석”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).