svelte-persisted-state
Version:
Svelte 5 persisted states, [svelte-persisted-store](https://github.com/joshnuss/svelte-persisted-store), but implemented with Svelte 5 Runes.
117 lines (116 loc) • 3.91 kB
JavaScript
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? decodeURIComponent(match[2]) : null;
}
function setCookie(name, value, options = {}) {
const { expireDays = 365, maxAge, path = '/', domain, secure = false, sameSite = 'Lax', httpOnly = false } = options;
let cookieString = `${name}=${encodeURIComponent(value)}`;
cookieString += `; path=${path}`;
// Use max-age if specified, otherwise use expires
if (maxAge !== undefined) {
cookieString += `; max-age=${maxAge}`;
}
else {
const expires = new Date(Date.now() + expireDays * 864e5).toUTCString();
cookieString += `; expires=${expires}`;
}
if (domain) {
cookieString += `; domain=${domain}`;
}
if (secure) {
cookieString += `; secure`;
}
cookieString += `; samesite=${sameSite}`;
if (httpOnly) {
cookieString += `; httponly`;
}
document.cookie = cookieString;
}
function getStorage(type, cookieOptions = {}) {
if (type === 'local')
return {
getItem: (k) => localStorage.getItem(k),
setItem: (k, v) => localStorage.setItem(k, v)
};
if (type === 'session')
return {
getItem: (k) => sessionStorage.getItem(k),
setItem: (k, v) => sessionStorage.setItem(k, v)
};
// cookie
return {
getItem: getCookie,
setItem: (k, v) => setCookie(k, v, cookieOptions)
};
}
export function persistedState(key, initialValue, options = {}) {
const { storage = 'local', serializer = JSON, syncTabs = true, cookieExpireDays, cookieOptions = {}, onWriteError = console.error, onParseError = console.error, beforeRead = (v) => v, beforeWrite = (v) => v } = options;
// Handle backward compatibility with cookieExpireDays
const finalCookieOptions = {
...cookieOptions,
...(cookieExpireDays !== undefined && { expireDays: cookieExpireDays })
};
const browser = typeof window !== 'undefined' && typeof document !== 'undefined';
const storageArea = browser ? getStorage(storage, finalCookieOptions) : null;
let storedValue;
try {
const item = storageArea?.getItem(key);
storedValue = item ? beforeRead(serializer.parse(item)) : initialValue;
}
catch (error) {
onParseError(error);
storedValue = initialValue;
}
let state = $state(storedValue);
function updateStorage(value) {
try {
const valueToStore = beforeWrite(value);
storageArea?.setItem(key, serializer.stringify(valueToStore));
}
catch (error) {
onWriteError(error);
}
}
if (syncTabs && typeof window !== 'undefined' && storage === 'local') {
window.addEventListener('storage', (event) => {
if (event.key === key && event.storageArea === localStorage) {
try {
const newValue = event.newValue ? serializer.parse(event.newValue) : initialValue;
state = beforeRead(newValue);
}
catch (error) {
onParseError(error);
}
}
});
}
$effect.root(() => {
$effect(() => {
updateStorage(state);
});
return () => { };
});
return {
/**
* @deprecated Use current to align with Svelte conventions
*/
get value() {
return state;
},
/**
* @deprecated Use current to align with Svelte conventions
*/
set value(newValue) {
state = newValue;
},
get current() {
return state;
},
set current(newValue) {
state = newValue;
},
reset() {
state = initialValue;
}
};
}