// ------------------------------------------------------------- // WARNING: this file is used by both the client and the server. // Do not use any browser or node-specific API! // ------------------------------------------------------------- import setCookie from 'set-cookie-parser'; function validateCookie(cookie, meta, js = false) { if (cookie.httpOnly && !!js) return false; if (cookie.domain.startsWith('.')) { if (!meta.url.hostname.endsWith(cookie.domain.slice(1))) return false; return true; } if (cookie.domain !== meta.url.hostname) return false; if (cookie.secure && meta.url.protocol === 'http:') return false; if (!meta.url.pathname.startsWith(cookie.path)) return false; return true; } async function db(openDB) { const db = await openDB('__op', 1, { upgrade(db, oldVersion, newVersion, transaction) { const store = db.createObjectStore('cookies', { keyPath: 'id', }); store.createIndex('path', 'path'); }, }); db.transaction(['cookies'], 'readwrite').store.index('path'); return db; } function serialize(cookies = [], meta, js) { let str = ''; for (const cookie of cookies) { if (!validateCookie(cookie, meta, js)) continue; if (str.length) str += '; '; str += cookie.name; str += '='; str += cookie.value; } return str; } async function getCookies(db) { const now = new Date(); return (await db.getAll('cookies')).filter((cookie) => { let expired = false; if (cookie.set) { if (cookie.maxAge) { expired = cookie.set.getTime() + cookie.maxAge * 1e3 < now; } else if (cookie.expires) { expired = new Date(cookie.expires.toLocaleString()) < now; } } if (expired) { db.delete('cookies', cookie.id); return false; } return true; }); } function setCookies(data, db, meta) { if (!db) return false; const cookies = setCookie(data, { decodeValues: false, }); for (const cookie of cookies) { if (!cookie.domain) cookie.domain = '.' + meta.url.hostname; if (!cookie.path) cookie.path = '/'; if (!cookie.domain.startsWith('.')) { cookie.domain = '.' + cookie.domain; } db.put('cookies', { ...cookie, id: `${cookie.domain}@${cookie.path}@${cookie.name}`, set: new Date(Date.now()), }); } return true; } export { validateCookie, getCookies, setCookies, db, serialize };