Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
31 lines
1 KiB
TypeScript
31 lines
1 KiB
TypeScript
/**
|
|
* Session token holder: memory first, mirrored to localStorage so a reload
|
|
* keeps the session. Listeners let the auth store react when the API client
|
|
* clears a token (401) or a mutation hands back a re-issued one.
|
|
*/
|
|
|
|
const STORAGE_KEY = "tmbh.session";
|
|
|
|
let memory: string | null | undefined;
|
|
const listeners = new Set<(token: string | null) => void>();
|
|
|
|
export function getSessionToken(): string | null {
|
|
if (memory !== undefined) return memory;
|
|
if (typeof window === "undefined") return null;
|
|
memory = window.localStorage.getItem(STORAGE_KEY);
|
|
return memory;
|
|
}
|
|
|
|
export function setSessionToken(token: string | null): void {
|
|
memory = token;
|
|
if (typeof window !== "undefined") {
|
|
if (token === null) window.localStorage.removeItem(STORAGE_KEY);
|
|
else window.localStorage.setItem(STORAGE_KEY, token);
|
|
}
|
|
for (const listener of listeners) listener(token);
|
|
}
|
|
|
|
export function onSessionTokenChange(listener: (token: string | null) => void): () => void {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
}
|