sdlc-hub/web/src/auth/token.ts
Andrey Epifancev ef9ec9f46d feat(sdlc-rename): бренд SDLC Hub и ключи хранилища sdlc-hub-* с переносом
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 11:56:58 +04:00

36 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// клиентский токен хаба: localStorage["sdlc-hub-token"] (со старого "sdlc-hub-token" переносится при чтении) и копия в памяти на случай
// закрытого хранилища. reason — почему показан экран входа: "bad" — токен не подошёл (ответ 401)
import { readMigrated } from "../api/legacyStorage";
export const TOKEN_KEY = "sdlc-hub-token";
export const TOKEN_RE = /^[\x21-\x7e]+$/; // печатный ASCII без пробелов: иначе fetch бросит TypeError на заголовке
export type LoginReason = "none" | "bad";
export interface AuthSnapshot { token: string; reason: LoginReason }
const readStored = (): string => {
return readMigrated(TOKEN_KEY) ?? "";
};
let state: AuthSnapshot = { token: readStored(), reason: "none" };
const listeners = new Set<() => void>();
const emit = (next: AuthSnapshot) => { state = next; listeners.forEach((l) => l()); };
export const getAuth = (): AuthSnapshot => state;
export const getToken = (): string => state.token;
export function setToken(token: string): void {
try { localStorage.setItem(TOKEN_KEY, token); } catch { /* закрытое хранилище: токен только в памяти */ }
emit({ token, reason: "none" });
}
export function clearToken(reason: LoginReason = "none"): void {
try { localStorage.removeItem(TOKEN_KEY); } catch { /* закрытое хранилище */ }
emit({ token: "", reason });
}
export function subscribe(fn: () => void): () => void {
listeners.add(fn);
return () => { listeners.delete(fn); };
}