'use client'; const WORKS_OPERATIONS_AUTH_STORAGE_KEY = 'works-square.operations.auth.v1'; export function worksAccessToken(): string | null { try { const raw = window.localStorage.getItem(WORKS_OPERATIONS_AUTH_STORAGE_KEY); if (!raw) return null; const session = JSON.parse(raw) as { accessToken?: unknown; expiresAt?: unknown }; if (typeof session.accessToken !== 'string' || !session.accessToken.trim()) return null; if (typeof session.expiresAt === 'number' && session.expiresAt <= Date.now()) return null; return session.accessToken.trim(); } catch { return null; } } export function opsApiPath(pathname: string): string { const path = pathname.startsWith('/') ? pathname : `/${pathname}`; return `${process.env.NEXT_PUBLIC_OPENMAIC_BASE_PATH ?? ''}${path}`; } export function opsApiFetch(pathname: string, init: RequestInit = {}): Promise { const headers = new Headers(init.headers); const token = worksAccessToken(); if (token) headers.set('Authorization', `Bearer ${token}`); headers.set('Accept', headers.get('Accept') || 'application/json'); return fetch(opsApiPath(pathname), { ...init, headers }); } const OPS_PUBLIC_ASSET_ROOTS = [ '/avatars/', '/logos/', '/vendor/', '/mailuo-logo.png', '/openmaic-mark.png', '/logo-horizontal.png', ] as const; function opsRootRelativePath(pathname: string): string | null { if (pathname === '/api' || pathname.startsWith('/api/')) return opsApiPath(pathname); if (OPS_PUBLIC_ASSET_ROOTS.some((root) => pathname === root || pathname.startsWith(root))) { return opsApiPath(pathname); } return null; } /** Install before child effects so legacy root-relative API calls remain basePath-aware. */ export function installOpsBrowserBoundary(): () => void { if (process.env.NEXT_PUBLIC_OPENMAIC_DEPLOYMENT_ROLE !== 'ops') return () => undefined; const nativeFetch = window.fetch.bind(window); const wrappedFetch: typeof window.fetch = (input, init = {}) => { const mapped = typeof input === 'string' ? opsRootRelativePath(input) : null; if (!mapped) return nativeFetch(input, init); if (typeof input !== 'string' || !input.startsWith('/api')) return nativeFetch(mapped, init); const headers = new Headers(init.headers); const token = worksAccessToken(); if (token && !headers.has('Authorization')) headers.set('Authorization', `Bearer ${token}`); return nativeFetch(mapped, { ...init, headers }); }; window.fetch = wrappedFetch; const rewriteElement = (element: Element) => { for (const attribute of ['src', 'poster']) { const value = element.getAttribute(attribute); if (!value) continue; const mapped = opsRootRelativePath(value); if (mapped && mapped !== value && !value.startsWith('/api')) { element.setAttribute(attribute, mapped); } } }; const rewriteTree = (root: ParentNode) => { if (root instanceof Element) rewriteElement(root); root.querySelectorAll('[src], [poster]').forEach(rewriteElement); }; rewriteTree(document); const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === 'attributes') rewriteElement(mutation.target as Element); for (const node of mutation.addedNodes) { if (node instanceof Element) rewriteTree(node); } } }); observer.observe(document.documentElement, { subtree: true, childList: true, attributes: true, attributeFilter: ['src', 'poster'], }); let closed = false; return () => { if (closed) return; closed = true; observer.disconnect(); if (window.fetch === wrappedFetch) window.fetch = nativeFetch; }; }