// session ของแอป note ฝั่ง client (ฉบับ token 2026-10-30 ตามคำขอผู้ใช้ "note ใช้ // แบบ add-in" — pattern เดียวกับ wordaddin/services/authService): access_token // + identity เก็บใน localStorage ("note-auth") หลังแลกจาก POST /api/note/auth/ // session · การเรียก API ของแอปผ่าน noteAuthFetch แนบ Authorization: Bearer // อัตโนมัติ · token หมดอายุแล้วถือว่าไม่มี session (ล้างทิ้ง) — localStorage อาจ // โยน (private mode/quota) ทุกจุดจึง try/catch // // client-only — ห้าม import จาก server component/module ฝั่ง server import { withBasePath } from "@/utils/base-path"; export type NoteSession = { token: string; userid: string; username: string; /** exp epoch มิลลิวินาที — พ้นเวลานี้ถือว่าไม่มี session */ expMs: number; }; const STORAGE_KEY = "note-auth"; export function readNoteSession(): NoteSession | null { try { const raw = window.localStorage.getItem(STORAGE_KEY); if (raw === null) return null; const parsed = JSON.parse(raw) as Partial | null; if ( parsed === null || typeof parsed !== "object" || typeof parsed.token !== "string" || parsed.token === "" || typeof parsed.userid !== "string" || parsed.userid === "" || typeof parsed.username !== "string" || typeof parsed.expMs !== "number" ) { window.localStorage.removeItem(STORAGE_KEY); return null; } if (parsed.expMs <= Date.now()) { window.localStorage.removeItem(STORAGE_KEY); return null; } return parsed as NoteSession; } catch { return null; } } export function saveNoteSession(session: NoteSession): void { try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(session)); } catch { // private mode/quota — เงียบไว้: ผู้ใช้เข้าผ่านลิงก์ e-Court ใหม่ได้เสมอ } } export function clearNoteSession(): void { try { window.localStorage.removeItem(STORAGE_KEY); } catch { // ignore } } /** fetch ของแอปพร้อม Bearer — path เป็น route API ของแอป ("/api/note/…") * ไม่มี session = throw "no-session" ให้ caller เปลี่ยนเป็นหน้า gate เอง */ export async function noteAuthFetch(path: string, init: RequestInit = {}): Promise { const session = readNoteSession(); if (session === null) throw new Error("no-session"); return fetch(withBasePath(path), { ...init, headers: { ...(init.headers ?? {}), authorization: `Bearer ${session.token}` }, }); }