~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
57 lines · 1.4 KB Raw History
import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';
import { forgetCredentials } from '#/lib/credential.js';
import {
  canWrite,
  currentSession,
  onSessionEnded,
  signOut as revoke,
} from '#/lib/oauth.js';

/**
 * @typedef {Object} SessionContextValue
 * @property {import('#/lib/oauth.js').Session|null} session
 * @property {(value: import('#/lib/oauth.js').Session|null) => void} setSession
 * @property {() => Promise<void>} endSession
 * @property {boolean} writable - whether the granted scope permits a write
 */

const SessionContext = createContext(
  /** @type {SessionContextValue} */ (/** @type {unknown} */ ({})),
);

export function SessionProvider({ children }) {
  const [session, setSession] = useState(() => currentSession());

  const endSession = useCallback(async () => {
    await revoke(session);
    forgetCredentials();
    setSession(null);
  }, [session]);

  // A refusal from the server, rather than a sign-out the reader asked for. The
  // credentials go with it: each one was issued against this session.
  useEffect(() => {
    onSessionEnded(() => {
      forgetCredentials();
      setSession(null);
    });
  }, []);

  return (
    <SessionContext.Provider
      value={{ session, setSession, endSession, writable: canWrite(session) }}
    >
      {children}
    </SessionContext.Provider>
  );
}

export function useSession() {
  return useContext(SessionContext);
}