atprotoSession

tcmts.atproto.atprotoSession · #xd6byllv · term · runs on the server

uses tcmts.atproto.readSessions, which uses node:fs

A sign-in for scope, as who (a handle or DID) or, without one, the one used last: kept from before (its tokens refreshed if they've expired), or a new one, in the browser, kept for next time.

import { keepSession, readSessions, refreshSession, Refused, signIn } from "#codebase/tcmts/atproto";
import type { OAuthSession } from "#codebase/tcmts/atproto";

export async function atprotoSession(o: {
  who?: string;
  scope: string;
  why: string;
  tell?: (line: string) => void;
}): Promise<OAuthSession> {
  const kept = readSessions();
  const who = o.who?.trim().replace(/^@/, "").toLowerCase();
  const s = who
    ? Object.values(kept.sessions).find((x) => x.did === who || x.handle?.toLowerCase() === who)
    : kept.last
      ? kept.sessions[kept.last]
      : undefined;
  const covers = (x: OAuthSession) =>
    o.scope.split(" ").every((p) => x.scope.split(" ").includes(p));
  if (s && covers(s) && (s.expiresAt - 60_000 > Date.now() || (await refreshSession(s)))) {
    if (kept.last !== s.did) keepSession(s.did, s);
    return s;
  }
  const as = who ?? s?.handle ?? s?.did;
  if (!as)
    throw new Refused(`${o.why}: sign in with --as <handle> (once: it's kept for next time)`);
  const fresh = await signIn(as, o.scope, o.tell);
  keepSession(fresh.did, fresh);
  return fresh;
}

uses

used by