UNPKG

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
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; } }; }