'use strict'; function parse(str, options) { if (typeof str !== "string") { throw new TypeError("argument str must be a string"); } const obj = {}; const opt = options || {}; const dec = opt.decode || decode; let index = 0; while (index < str.length) { const eqIdx = str.indexOf("=", index); if (eqIdx === -1) { break; } let endIdx = str.indexOf(";", index); if (endIdx === -1) { endIdx = str.length; } else if (endIdx < eqIdx) { index = str.lastIndexOf(";", eqIdx - 1) + 1; continue; } const key = str.slice(index, eqIdx).trim(); if (opt?.filter && !opt?.filter(key)) { index = endIdx + 1; continue; } if (void 0 === obj[key]) { let val = str.slice(eqIdx + 1, endIdx).trim(); if (val.codePointAt(0) === 34) { val = val.slice(1, -1); } obj[key] = tryDecode(val, dec); } index = endIdx + 1; } return obj; } function decode(str) { return str.includes("%") ? decodeURIComponent(str) : str; } function tryDecode(str, decode2) { try { return decode2(str); } catch { return str; } } const fieldContentRegExp = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/; function serialize(name, value, options) { const opt = options || {}; const enc = opt.encode || encodeURIComponent; if (typeof enc !== "function") { throw new TypeError("option encode is invalid"); } if (!fieldContentRegExp.test(name)) { throw new TypeError("argument name is invalid"); } const encodedValue = enc(value); if (encodedValue && !fieldContentRegExp.test(encodedValue)) { throw new TypeError("argument val is invalid"); } let str = name + "=" + encodedValue; if (void 0 !== opt.maxAge && opt.maxAge !== null) { const maxAge = opt.maxAge - 0; if (Number.isNaN(maxAge) || !Number.isFinite(maxAge)) { throw new TypeError("option maxAge is invalid"); } str += "; Max-Age=" + Math.floor(maxAge); } if (opt.domain) { if (!fieldContentRegExp.test(opt.domain)) { throw new TypeError("option domain is invalid"); } str += "; Domain=" + opt.domain; } if (opt.path) { if (!fieldContentRegExp.test(opt.path)) { throw new TypeError("option path is invalid"); } str += "; Path=" + opt.path; } if (opt.expires) { if (!isDate(opt.expires) || Number.isNaN(opt.expires.valueOf())) { throw new TypeError("option expires is invalid"); } str += "; Expires=" + opt.expires.toUTCString(); } if (opt.httpOnly) { str += "; HttpOnly"; } if (opt.secure) { str += "; Secure"; } if (opt.priority) { const priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority; switch (priority) { case "low": { str += "; Priority=Low"; break; } case "medium": { str += "; Priority=Medium"; break; } case "high": { str += "; Priority=High"; break; } default: { throw new TypeError("option priority is invalid"); } } } if (opt.sameSite) { const sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite; switch (sameSite) { case true: { str += "; SameSite=Strict"; break; } case "lax": { str += "; SameSite=Lax"; break; } case "strict": { str += "; SameSite=Strict"; break; } case "none": { str += "; SameSite=None"; break; } default: { throw new TypeError("option sameSite is invalid"); } } } if (opt.partitioned) { str += "; Partitioned"; } return str; } function isDate(val) { return Object.prototype.toString.call(val) === "[object Date]" || val instanceof Date; } function parseSetCookie(setCookieValue, options) { const parts = (setCookieValue || "").split(";").filter((str) => typeof str === "string" && !!str.trim()); const nameValuePairStr = parts.shift() || ""; const parsed = _parseNameValuePair(nameValuePairStr); const name = parsed.name; let value = parsed.value; try { value = options?.decode === false ? value : (options?.decode || decodeURIComponent)(value); } catch { } const cookie = { name, value }; for (const part of parts) { const sides = part.split("="); const partKey = (sides.shift() || "").trimStart().toLowerCase(); const partValue = sides.join("="); switch (partKey) { case "expires": { cookie.expires = new Date(partValue); break; } case "max-age": { cookie.maxAge = Number.parseInt(partValue, 10); break; } case "secure": { cookie.secure = true; break; } case "httponly": { cookie.httpOnly = true; break; } case "samesite": { cookie.sameSite = partValue; break; } default: { cookie[partKey] = partValue; } } } return cookie; } function _parseNameValuePair(nameValuePairStr) { let name = ""; let value = ""; const nameValueArr = nameValuePairStr.split("="); if (nameValueArr.length > 1) { name = nameValueArr.shift(); value = nameValueArr.join("="); } else { value = nameValuePairStr; } return { name, value }; } function splitSetCookieString(cookiesString) { if (Array.isArray(cookiesString)) { return cookiesString.flatMap((c) => splitSetCookieString(c)); } if (typeof cookiesString !== "string") { return []; } const cookiesStrings = []; let pos = 0; let start; let ch; let lastComma; let nextStart; let cookiesSeparatorFound; const skipWhitespace = () => { while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) { pos += 1; } return pos < cookiesString.length; }; const notSpecialChar = () => { ch = cookiesString.charAt(pos); return ch !== "=" && ch !== ";" && ch !== ","; }; while (pos < cookiesString.length) { start = pos; cookiesSeparatorFound = false; while (skipWhitespace()) { ch = cookiesString.charAt(pos); if (ch === ",") { lastComma = pos; pos += 1; skipWhitespace(); nextStart = pos; while (pos < cookiesString.length && notSpecialChar()) { pos += 1; } if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") { cookiesSeparatorFound = true; pos = nextStart; cookiesStrings.push(cookiesString.slice(start, lastComma)); start = pos; } else { pos = lastComma + 1; } } else { pos += 1; } } if (!cookiesSeparatorFound || pos >= cookiesString.length) { cookiesStrings.push(cookiesString.slice(start, cookiesString.length)); } } return cookiesStrings; } exports.parse = parse; exports.parseSetCookie = parseSetCookie; exports.serialize = serialize; exports.splitSetCookieString = splitSetCookieString;