@light-auth/core
Version:
light auth core framework agnostic, using arctic
201 lines (194 loc) • 8.72 kB
JavaScript
/*! @light-auth/core v0.3.1 2025-06-13 */
'use client';
const DEFAULT_BASE_PATH = "/api/auth";
/** Resolves the basePath, defaults to "/api/default" if not provided or falsy */
function resolveBasePath(basePath, env) {
let resolvedBasePath = basePath || env?.["LIGHT_AUTH_BASE_PATH"] || DEFAULT_BASE_PATH;
if (!resolvedBasePath.startsWith("/"))
resolvedBasePath = `/${resolvedBasePath}`;
// Ensure the base path does not end with "/"
if (resolvedBasePath.endsWith("/"))
resolvedBasePath = resolvedBasePath.slice(0, -1);
// Ensure the base path does not contain double slashes
if (resolvedBasePath.includes("//"))
resolvedBasePath = resolvedBasePath.replace(/\/\//g, "/");
return resolvedBasePath;
}
/**
* this function is used to make a request to the light auth server
* it can be done from the server side or the client side
*
* it will use the router to get the url and the headers (if server side)
*/
async function internalFetch(args) {
const { config, body, method = "GET", headers } = args;
const { router } = config;
const env = config.env;
const basePath = resolveBasePath(config.basePath, env);
// check if we are on the server side or client side
// if we are on the server side, we need to use the router to get the url and headers
// if we are on the client side, we can use the window object to get the url and headers
const isServerSide = typeof window === "undefined";
const bodyBytes = body ? new TextEncoder().encode(body.toString()) : undefined;
// get all the headers from the request
let requestHeaders = headers ?? null;
if (router && isServerSide)
requestHeaders = await router.getHeaders({ env, basePath, ...args });
// get the full url from the router if available
let url = args.endpoint;
if (router && isServerSide)
url = await router.getUrl({ env, basePath, ...args });
const request = bodyBytes
? new Request(url.toString(), { method: method, headers: requestHeaders ?? new Headers(), body: bodyBytes })
: new Request(url.toString(), { method: method, headers: requestHeaders ?? new Headers() });
let response = null;
try {
response = await fetch(request);
}
catch (error) {
console.error("Error:", error);
throw new Error(`light-auth: Request failed with error ${error}`);
}
if (!response || !response.ok) {
throw new Error(`light-auth: Request failed with status ${response?.status}`);
}
const contentType = response.headers.get("Content-Type");
if (contentType && contentType.includes("application/x-www-form-urlencoded")) {
const formResponse = await response.text();
const formData = new URLSearchParams(formResponse);
const result = {};
for (const [key, value] of formData.entries()) {
result[key] = value;
}
return result;
}
if (contentType && (contentType.includes("application/json") || contentType.includes("text/plain"))) {
const jsonResponse = await response.json();
return jsonResponse;
}
if (contentType && contentType.includes("application/octet-stream")) {
const blobResponse = await response.blob();
return blobResponse;
}
return null;
}
async function getCsrfToken(args) {
const isServerSide = typeof window === "undefined";
if (isServerSide)
return;
const { config } = args;
// Get a csrf token from the server
const endpoint = `${config.basePath}/csrf`;
const csrfToken = await internalFetch({ endpoint, method: "POST", ...args });
if (!csrfToken)
throw new Error("light-auth: Failed to get csrf token");
// Check if the csrf token cookie, called light_auth_csrf_token exist
const csrfTokenCookie = document.cookie.split("; ").find((row) => row.startsWith("light_auth_csrf_token="));
if (csrfTokenCookie)
window.document.cookie = `light_auth_csrf_token=; path=/; max-age=0;`;
// Set the csrf token in the cookie store
window.document.cookie = `light_auth_csrf_token=${csrfToken.csrfTokenHash}.${csrfToken.csrfToken}; path=/; secure=true}`;
}
function createSigninClientFunction(config) {
return async (args = {}) => {
const { providerName, callbackUrl = "/" } = args;
// check if we are on the server side or client side
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: signin function should not be called on the server side");
// Get a csrf token from the server and set it in the cookie store
await getCsrfToken({ config, ...args });
window.location.href = `${config.basePath}/login/${providerName}?callbackUrl=${encodeURIComponent(callbackUrl)}`;
};
}
function createSignoutClientFunction(config) {
return async (args = {}) => {
const { revokeToken = true, callbackUrl = "/" } = args;
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: signout function should not be called on the server side");
// Get a csrf token from the server and set it in the cookie store
await getCsrfToken({ config, ...args });
window.location.href = `${config.basePath}/logout?revokeToken=${revokeToken}&callbackUrl=${encodeURIComponent(callbackUrl)}`;
};
}
function createFetchSessionClientFunction(config) {
return async (args) => {
try {
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: fetchSession function should not be called on the server side");
// get the session from the server using the api endpoint
const session = await internalFetch({ config, method: "POST", endpoint: `${config.basePath}/session`, ...args });
return session ?? null;
}
catch (error) {
console.error("Error:", error);
return null;
}
};
}
function createSetSessionClientFunction(config) {
return async (session, args) => {
try {
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: setSession function should not be called on the server side");
// get the session from the server using the api endpoint
const updatedSession = await internalFetch({
config,
method: "POST",
body: JSON.stringify(session),
endpoint: `${config.basePath}/set_session`,
...args,
});
return updatedSession ?? null;
}
catch (error) {
console.error("Error:", error);
return null;
}
};
}
function createFetchUserClientFunction(config) {
return async (args) => {
try {
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: getUser function should not be called on the server side");
const endpoint = args?.providerUserId ? `${config.basePath}/user/${args.providerUserId}` : `${config.basePath}/user`;
// get the user from the user adapter
const user = await internalFetch({ config, method: "POST", endpoint, ...args });
if (!user)
return null;
return user;
}
catch (error) {
console.error("light-auth: Error in createLightAuthUserFunction:", error);
return null;
}
};
}
function createSetUserClientFunction(config) {
return async (user, args) => {
try {
const isServerSide = typeof window === "undefined";
if (isServerSide)
throw new Error("light-auth-client: setUser function should not be called on the server side");
const updatedUser = await internalFetch({
config,
method: "POST",
body: JSON.stringify(user),
endpoint: `${config.basePath}/set_user`,
...args,
});
return updatedUser ?? null;
}
catch (error) {
console.error("Error:", error);
return null;
}
};
}
export { DEFAULT_BASE_PATH, createFetchSessionClientFunction, createFetchUserClientFunction, createSetSessionClientFunction, createSetUserClientFunction, createSigninClientFunction, createSignoutClientFunction, resolveBasePath };
//# sourceMappingURL=index.mjs.map