keptSession
A kept sign-in as a Session: its requests DPoP-bound (or an app password's bearer token), its tokens
refreshed once if the PDS says they've expired, and kept again in store; signing out forgets it there.
import { dpopFetch, refreshSession, sessionOver } from "#codebase/tcmts/atproto"; import type { OAuthSession, Session, SessionStore } from "#codebase/tcmts/atproto"; export function keptSession(s: OAuthSession, store?: SessionStore): Session { const send = async (p: string, init: RequestInit = {}): Promise<Response> => { const go = () => s.dpopKey ? dpopFetch(s.dpopKey, `${s.pds}${p}`, init, s.accessToken) : fetch(`${s.pds}${p}`, { ...init, headers: { ...(init.headers as Record<string, string> | undefined), authorization: `Bearer ${s.accessToken}`, }, }); const res = await go(); // (an app password's token that's expired is a 400 ExpiredToken) const expired = res.status === 401 || (!s.dpopKey && res.status === 400 && ( (await res .clone() .json() .catch(() => ({}))) as { error?: string } ).error === "ExpiredToken"); if (!expired || !(await refreshSession(s))) return res; store?.keep(s.did, s); return go(); }; return sessionOver({ did: s.did, ...(s.handle ? { handle: s.handle } : {}), scope: s.scope, send, signOut: async () => store?.keep(s.did, undefined), }); }
uses
- tcmts.atproto.OAuthSession
- tcmts.atproto.Session
- tcmts.atproto.SessionStore
- tcmts.atproto.dpopFetch
- tcmts.atproto.refreshSession
- tcmts.atproto.sessionOver