'use strict'; var web = require('solid-js/web'); var solidJs = require('solid-js'); var store = require('solid-js/store'); // src/cookies.ts // src/tools.ts exports.addClearMethod = (storage) => { if (typeof storage.clear === "function") { return storage; } storage.clear = () => { let key; while (key = storage.key(0)) { storage.removeItem(key); } }; return storage; }; var methodKeys = ["clear", "getItem", "getAll", "setItem", "removeItem", "key", "getLength"]; exports.addWithOptionsMethod = (storage) => { storage.withOptions = (options) => methodKeys.reduce( (wrapped, key) => { if (typeof storage[key] === "function") { wrapped[key] = (...args) => { args[storage[key].length - 1] = options; return storage[key](...args); }; } return wrapped; }, { get length() { return storage.length; }, withOptions: (options2) => storage.withOptions(options2) } ); return storage; }; var callStorageMethod = (storages, method, args = [], first = false) => { const results = storages.map((storage) => storage[method](...args)); const isAsync = results.some( (result) => typeof result === "object" && typeof result?.then === "function" ); return isAsync ? first ? Promise.race(results) : Promise.all(results) : first ? results.filter(Boolean)[0] : results; }; var isNumber = (n) => typeof n === "number"; exports.multiplexStorage = (...storages) => ({ clear: () => callStorageMethod(storages, "clear"), getItem: (key) => callStorageMethod(storages, "getItem", [key], true), setItem: (key, value) => callStorageMethod(storages, "setItem", [key, value]), removeItem: (key) => callStorageMethod(storages, "removeItem", [key]), key: (no) => callStorageMethod(storages, "key", [no], true), get length() { const lengths = storages.map( (storage) => storage.length ); const isAsync = lengths.some( (len) => len && typeof len === "object" && typeof len?.then === "function" ); return isAsync ? Promise.all(lengths).then((lens) => Math.max(...lens.filter(isNumber))) : Math.max(...lengths.filter(isNumber)); } }); exports.makeObjectStorage = (object) => ({ getItem: (key) => Object.hasOwn(object, key) && object[key] || null, setItem: (key, value) => { object[key] = value; }, removeItem: (key) => { delete object[key]; }, key: (index) => Object.keys(object)[index], get length() { return Object.keys(object).length; }, clear: () => Object.keys(object).forEach((key) => { delete object[key]; }) }); // src/cookies.ts var cookiePropertyMap = { domain: "Domain", expires: "Expires", path: "Path", secure: "Secure", httpOnly: "HttpOnly", maxAge: "Max-Age", sameSite: "SameSite" }; function serializeCookieOptions(options) { if (!options) return ""; const result = Object.entries(options).map(([key, value]) => { const serializedKey = cookiePropertyMap[key]; if (!serializedKey) return void 0; if (value instanceof Date) return `${serializedKey}=${value.toUTCString()}`; if (typeof value === "boolean") return value ? `${serializedKey}` : void 0; return `${serializedKey}=${value}`; }).filter((v) => !!v); return result.length != 0 ? `; ${result.join("; ")}` : ""; } function deserializeCookieOptions(cookie, key) { const found = cookie.match(`(^|;)\\s*${key}\\s*=\\s*([^;]+)`)?.pop(); return found != null ? decodeURIComponent(found) : null; } var getRequestHeaders = web.isServer ? () => web.getRequestEvent()?.request.headers || new Headers() : () => new Headers(); var getResponseHeaders = web.isServer ? () => web.getRequestEvent()?.response.headers || new Headers() : () => new Headers(); exports.cookieStorage = exports.addWithOptionsMethod( exports.addClearMethod({ _read: web.isServer ? (options) => { const requestCookies = (options?.getRequestHeaders?.() || getRequestHeaders()).get( "Cookie" ); const responseCookies = (options?.getResponseHeaders?.() || getResponseHeaders()).get( "Set-Cookie" ); const cookies = {}; const addCookie = (_, key, val) => cookies[key] = val; requestCookies?.replace(/(?:^|;)([^=]+)=([^;]+)/g, addCookie); responseCookies?.replace(/(?:^|, )([^=]+)=([^;]+)/g, addCookie); return Object.entries(cookies).map((keyval) => keyval.join("=")).join("; "); } : () => document.cookie, _write: web.isServer ? (key, value, options) => { const responseHeaders = getResponseHeaders(); const currentCookies = responseHeaders.get("Set-Cookie")?.split(", ").filter((cookie) => cookie && !cookie.startsWith(`${key}=`)) ?? []; responseHeaders.set( "Set-Cookie", [...currentCookies, `${key}=${value}${serializeCookieOptions(options)}`].join(", ") ); } : (key, value, options) => { document.cookie = `${key}=${value}${serializeCookieOptions(options)}`; }, getItem: (key, options) => deserializeCookieOptions(exports.cookieStorage._read(options), key), setItem: (key, value, options) => { exports.cookieStorage._write( key, value.replace(/[\u00c0-\uffff\&;]/g, (c) => encodeURIComponent(c)), options ); }, removeItem: (key, options) => { exports.cookieStorage._write(key, "deleted", { ...options, expires: /* @__PURE__ */ new Date(0) }); }, key: (index, options) => { let key = null; let count = 0; exports.cookieStorage._read(options).replace(/(?:^|;)\s*(.+?)\s*=\s*[^;]+/g, (_, found) => { if (!key && found && count++ === index) { key = found; } return ""; }); return key; }, getLength: (options) => { let length = 0; exports.cookieStorage._read(options).replace(/(?:^|;)\s*.+?\s*=\s*[^;]+/g, (found) => { length += found ? 1 : 0; return ""; }); return length; }, get length() { return this.getLength(); } }) ); function makePersisted(signal, options = {}) { const storage = options.storage || globalThis.localStorage; const name = options.name || `storage-${solidJs.createUniqueId()}`; if (!storage) { return [signal[0], signal[1], null]; } const storageOptions = options.storageOptions; const serialize = options.serialize || JSON.stringify.bind(JSON); const deserialize = options.deserialize || JSON.parse.bind(JSON); const init = storage.getItem(name, storageOptions); const set = typeof signal[0] === "function" ? (data) => { try { const value = deserialize(data); signal[1](() => value); } catch (e) { if (web.isDev) console.warn(e); } } : (data) => { try { const value = deserialize(data); signal[1](store.reconcile(value)); } catch (e) { if (web.isDev) console.warn(e); } }; let unchanged = true; if (init instanceof Promise) init.then((data) => unchanged && data && set(data)); else if (init) set(init); if (typeof options.sync?.[0] === "function") { const get = typeof signal[0] === "function" ? signal[0] : () => signal[0]; options.sync[0]((data) => { if (data.key !== name || !web.isServer && (data.url || globalThis.location.href) !== globalThis.location.href || data.newValue === serialize(solidJs.untrack(get))) { return; } set(data.newValue); }); } return [ signal[0], typeof signal[0] === "function" ? (value) => { const output = signal[1](value); const serialized = value != null ? serialize(output) : value; options.sync?.[1](name, serialized); if (serialized != null) storage.setItem(name, serialized, storageOptions); else storage.removeItem(name, storageOptions); unchanged = false; return output; } : (...args) => { signal[1](...args); const value = serialize(solidJs.untrack(() => signal[0])); options.sync?.[1](name, value); storage.setItem(name, value, storageOptions); unchanged = false; }, init ]; } exports.storageSync = [ (subscriber) => window.addEventListener("storage", (ev) => subscriber(ev)), () => { } ]; exports.messageSync = (channel = window) => [ (subscriber) => channel.addEventListener("message", (ev) => { subscriber(ev.data); }), (key, newValue) => channel.postMessage( { key, newValue, timeStamp: +/* @__PURE__ */ new Date(), url: location.href }, location.origin ) ]; exports.wsSync = (ws, warnOnError = web.isDev) => [ (subscriber) => ws.addEventListener("message", (ev) => { try { const data = JSON.parse(ev.data); if (["key", "newValue", "timeStamp"].every((item) => Object.hasOwn(data, item))) { subscriber(data); } } catch (e) { if (warnOnError) console.warn(e); } }), (key, newValue) => ws.send( JSON.stringify({ key, newValue, timeStamp: +/* @__PURE__ */ new Date(), ...web.isServer ? {} : { url: location.href } }) ) ]; exports.multiplexSync = (...syncAPIs) => [ (subscriber) => syncAPIs.forEach(([subscribe]) => subscribe(subscriber)), (key, value) => syncAPIs.forEach(([_, updater]) => updater(key, value)) ]; exports.makePersisted = makePersisted;