@lucia-auth/sveltekit
Version:
SvelteKit integration for Lucia
73 lines (72 loc) • 2.67 kB
JavaScript
import { get, derived } from "svelte/store";
import { onDestroy, setContext } from "svelte";
import { getContext } from "svelte";
export const getUser = () => {
const luciaContext = getContext("__lucia__");
if (!luciaContext)
throw new UndefinedError("__lucia__");
return luciaContext;
};
const generateId = () => {
const generateRandomNumber = () => {
const randomNumber = Math.random();
if (randomNumber !== 0)
return randomNumber;
return generateRandomNumber();
};
return generateRandomNumber().toString(36).slice(2, 7);
};
export class UndefinedError extends Error {
constructor(type) {
const errorMsg = {
"pageData._lucia": "page data property _lucia is undefined - Make sure handleServerSession(auth) is set up inside the root +layout.server.ts",
__lucia__: "context __lucia__ does not exist in your app - Make sure handleSession() is set inside the root +layout.svelte file"
};
super(errorMsg[type]);
}
}
export const handleSession = (pageStore, onSessionUpdate = () => { }) => {
const luciaStore = derived(pageStore, (val) => {
const luciaPageData = val.data._lucia;
if (luciaPageData === undefined)
throw new UndefinedError("pageData._lucia");
return luciaPageData;
});
const userStore = derived(luciaStore, (val) => val.user);
setContext("__lucia__", userStore);
if (typeof document === "undefined")
return;
const broadcastChannel = new BroadcastChannel("__lucia__");
const tabId = generateId();
let initialLuciaStoreSubscription = true;
const luciaStoreUnsubscribe = luciaStore.subscribe((newVal) => {
/*
prevent postMessage on store initialization
*/
if (initialLuciaStoreSubscription)
return (initialLuciaStoreSubscription = false);
broadcastChannel.postMessage({
tabId: tabId,
sessionChecksum: newVal.sessionChecksum
});
});
broadcastChannel.addEventListener("message", ({ data }) => {
const messageData = data;
/*
check if message is coming from the same tab
*/
if (messageData.tabId === tabId)
return;
const currentLuciaContext = get(luciaStore);
/*
check if session has changed from the previous page data
*/
if (messageData.sessionChecksum === currentLuciaContext.sessionChecksum)
return;
onSessionUpdate(!!messageData.sessionChecksum);
});
onDestroy(() => {
broadcastChannel.close();
luciaStoreUnsubscribe();
});
};