import {type OAuthSession} from '@atproto/oauth-client-browser' import {type PersistedAccount} from '#/state/persisted' import {type Metrics} from '#/analytics/metrics' export type SessionAccount = PersistedAccount export type ReauthenticationOptions = { scope?: string /** Start OAuth from the initiating press without showing the login chooser. */ directOAuth?: boolean /** Main account sign-in may change the AppView before authorization. */ allowAppServerSwitch?: boolean } /** Session-change events understood by the reducer and logging hooks. */ export type AtpSessionEvent = 'update' | 'expired' | 'network-error' export type SessionStateContext = { accounts: SessionAccount[] currentAccount: SessionAccount | undefined hasSession: boolean } export type SessionApiContext = { createAccount: ( props: { service: string email: string password: string handle: string birthDate: Date inviteCode?: string verificationPhone?: string verificationCode?: string }, metrics: Metrics['account:create:success'], ) => Promise login: ( props: { service: string identifier: string password: string authFactorToken?: string | undefined oauthSession?: OAuthSession }, logContext: Metrics['account:loggedIn']['logContext'], ) => Promise logoutCurrentAccount: ( logContext: Metrics['account:loggedOut']['logContext'], ) => void logoutEveryAccount: ( logContext: Metrics['account:loggedOut']['logContext'], ) => void resumeSession: ( account: SessionAccount, isSwitchingAccounts?: boolean, ) => Promise removeAccount: (account: SessionAccount) => void reorderAccounts: (accounts: SessionAccount[]) => void /** * Calls `getSession` and patches the email fields of the current account. * Unlike `resumeSession`, this does not rotate tokens or rebuild the session, * so it produces no session-change side effects. */ partialRefreshSession: () => Promise /** * Rotates the session's tokens and resolves with the resulting account * snapshot, or `undefined` when logged out. * * Rejects when nothing was rotated, so a resolved promise means "tokens * rotated". Every caller relies on that: the verification dialogs close on * resolution, and `SignupQueued` re-checks the token scope. * * The snapshot is returned rather than read off `currentAccount`, because the * session's `onUpdated` hook -> `store.dispatch` path is a render cycle away * and `SignupQueued` branches synchronously on the fresh `accessJwt`. */ refreshSession: () => Promise /** * Creates a short-lived legacy agent for a stored account. Witchsky uses * this when an action is performed as an alternate account, including OAuth * accounts that do not have persisted JWTs. */ /** Refresh only this saved account; never switch accounts or navigate. */ reauthenticateAccount: ( account: SessionAccount, options?: ReauthenticationOptions, ) => Promise createEphemeralAgent: ( account: SessionAccount, ) => Promise }