feat(release): publish minimal self-contained Magent source
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
const AUTH_STATE_COOKIE = "magent_logged_in";
|
||||
|
||||
export const getApiBase = () => process.env.NEXT_PUBLIC_API_BASE ?? "/api";
|
||||
|
||||
const setCookie = (name: string, value: string, maxAgeSeconds: number) => {
|
||||
if (typeof document === "undefined") return;
|
||||
document.cookie = `${name}=${value}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
|
||||
};
|
||||
|
||||
const clearCookie = (name: string) => {
|
||||
if (typeof document === "undefined") return;
|
||||
document.cookie = `${name}=; Max-Age=0; Path=/; SameSite=Lax`;
|
||||
};
|
||||
|
||||
export const getToken = () => {
|
||||
if (typeof document === "undefined") return null;
|
||||
const cookies = document.cookie.split(";").map((entry) => entry.trim());
|
||||
const marker = cookies.find((entry) => entry.startsWith(`${AUTH_STATE_COOKIE}=`));
|
||||
if (!marker) return null;
|
||||
const [, value] = marker.split("=", 2);
|
||||
return value || null;
|
||||
};
|
||||
|
||||
export const setToken = (_token: string) => {
|
||||
setCookie(AUTH_STATE_COOKIE, "1", 60 * 60 * 12);
|
||||
};
|
||||
|
||||
export const clearToken = () => {
|
||||
clearCookie(AUTH_STATE_COOKIE);
|
||||
if (typeof window === "undefined") return;
|
||||
const baseUrl = getApiBase();
|
||||
void fetch(`${baseUrl}/auth/logout`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
keepalive: true,
|
||||
}).catch(() => undefined);
|
||||
};
|
||||
|
||||
export const logout = async () => {
|
||||
const baseUrl = getApiBase();
|
||||
clearCookie(AUTH_STATE_COOKIE);
|
||||
await fetch(`${baseUrl}/auth/logout`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
};
|
||||
|
||||
export const authFetch = (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const headers = new Headers(init?.headers || {});
|
||||
return fetch(input, { ...init, headers, credentials: "include" });
|
||||
};
|
||||
|
||||
export const getEventStreamToken = async () => {
|
||||
const baseUrl = getApiBase();
|
||||
const response = await authFetch(`${baseUrl}/auth/stream-token`);
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
throw new Error(text || `Stream token request failed: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const token = typeof data?.stream_token === "string" ? data.stream_token : "";
|
||||
if (!token) {
|
||||
throw new Error("Stream token not returned");
|
||||
}
|
||||
return token;
|
||||
};
|
||||
|
||||
export class UnauthorizedError extends Error {
|
||||
constructor() {
|
||||
super("Unauthorized");
|
||||
this.name = "UnauthorizedError";
|
||||
}
|
||||
}
|
||||
|
||||
export class ForbiddenError extends Error {
|
||||
constructor() {
|
||||
super("Forbidden");
|
||||
this.name = "ForbiddenError";
|
||||
}
|
||||
}
|
||||
|
||||
export const authFetchOrThrow = async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const response = await authFetch(input, init);
|
||||
if (response.status === 401) {
|
||||
clearToken();
|
||||
throw new UnauthorizedError();
|
||||
}
|
||||
if (response.status === 403) {
|
||||
throw new ForbiddenError();
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
export const readResponseText = async (response: Response) => {
|
||||
try {
|
||||
return (await response.text()).trim();
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user