import { omit } from 'lodash' import { OAuthToken } from '../types' import { ENV, Session, UNAUTHENTICATED_SESSION_ID } from './session' type SessionManagerProps = { sessions?: Record currentSessionId?: string } export class SessionManager { sessions: Record currentSessionId: string constructor(props?: SessionManagerProps) { const { sessions, currentSessionId } = props || {} this.sessions = sessions || {} this.currentSessionId = currentSessionId || UNAUTHENTICATED_SESSION_ID } static hydrate(sessionManagerString: string) { try { const props = JSON.parse(sessionManagerString) return new SessionManager(props) } catch (_error) { return new SessionManager() } } get currentSession() { return Session.hydrate( this.sessions[this.currentSessionId] || new Session({}).toString() ) } setEnv(env: ENV) { // Get the current session (handles case where it doesn't exist) const session = this.currentSession session.env = env // Store the session with its ID this.upsertSession(session) } toString() { return JSON.stringify({ sessions: this.sessions, currentSessionId: this.currentSessionId }) } removeSession(sessionId: string) { // if unauthenticated, this is a no-op this.sessions = omit(this.sessions, sessionId) if (this.currentSessionId === sessionId) { this.currentSessionId = UNAUTHENTICATED_SESSION_ID } } switchSession(sessionId: string) { const sessionPresent = this.sessions[sessionId] if (!sessionPresent) { throw new Error(`Session ${sessionId} not found`) } this.currentSessionId = sessionId } upsertSession(session: Session) { this.sessions[session.id] = session.toString() this.currentSessionId = session.id } updateCurrentToken(token: OAuthToken) { const session = this.currentSession this.removeSession(session.id) session.token = token this.upsertSession(session) } }