|
UnENVerse 0.42.6
Local-first desktop secrets manager — TypeScript frontend
|
Session cookies — Phase 23, step 5. More...
import type;Functions | |
| function export | parseCookieHeader (raw:string) |
Split a document.cookie string, or a Cookie: header. | |
| function export | parseCookiesTxt (raw:string) |
Parse a Netscape cookies.txt. | |
| function | fromJsonCookie (raw:Record< string, unknown >) |
| A single value from a browser-extension JSON export, which vary in spelling. | |
| function export | parseAnyCookies (raw:string) |
| Whatever was pasted, as cookies. | |
| function export | toCookieHeader (cookies:Cookie[]) |
The Cookie: header value — what a request actually sends. | |
| function export | toCookiesTxt (cookies:Cookie[]) |
Netscape cookies.txt, for curl -b and yt-dlp --cookies. | |
Variables | |
| export interface | Cookie |
| One cookie, with whatever attributes the source carried. | |
| value | __pad0__ |
| domain | __pad1__ |
Attributes are absent for a jar pasted as a bare document.cookie string. | |
| path | __pad2__ |
| secure | __pad3__ |
| http_only | __pad4__ |
| expires | __pad5__ |
| Unix seconds. | |
| const | COOKIE_PREFIX_RE = /^__(?:Host|Secure)-/i |
| Cookie prefixes that are an instruction to the browser, not part of the name. | |
Session cookies — Phase 23, step 5.
@description The twin of unv-cli/src/cookies.rs, pinned by tests/fixtures/parity/cookies.json and asserted from both sides.
Spotify (sp_dc/sp_key), YouTube (SAPISID), Instagram (sessionid + csrftoken + ds_user_id) and everything driven by yt-dlp are used through a session cookie and nothing else. Before this there was no home for one: the jar went in a free-text field, the User-Agent it was minted against went nowhere, and replay without the matching User-Agent usually 401s — so the vault held half a credential and did not say which half was missing.
The form has to split a pasted document.cookie as it is typed, and an IPC round trip per keystroke is not a form — the same reason the TOTP seed parser exists twice. So both halves are written twice and pinned by one fixture.
The Netscape format needs a domain, an include-subdomains flag, a path, a secure flag and an expiry per cookie. A jar pasted as a bare document.cookie string carries none of them. Writing a file yt-dlp silently ignores is worse than not offering the button, so the export refuses and names the attributes it does not have.
| function export parseCookieHeader | ( | raw:string | ) |
Split a document.cookie string, or a Cookie: header.
Deliberately forgiving: half the jars people paste come out of a devtools panel with a trailing ;, a stray newline, or the Cookie: prefix still attached. Losing the whole jar over one of those helps nobody — and unlike an otpauth:// URI there is no checksum to tell a mangled jar from a good one, so the rule is to take what parses and drop what does not.
| function export parseCookiesTxt | ( | raw:string | ) |
Parse a Netscape cookies.txt.
Seven tab-separated fields: domain, include-subdomains, path, secure, expiry, name, value. The #HttpOnly_ line prefix is curl's extension and carries the flag, so it is read rather than treated as a comment.
| function fromJsonCookie | ( | raw:Record< string, unknown > | ) |
A single value from a browser-extension JSON export, which vary in spelling.
Every field is taken only when it is already a string rather than stringified: this is a parsed JSON document from a file the user picked, i.e. untrusted input (invariant 4), and String(someObject) would quietly put [object Object] into a cookie name rather than rejecting the row. Parse the array shape every "Copy all as JSON" / cookie-editor extension writes.
| function export parseAnyCookies | ( | raw:string | ) |
Whatever was pasted, as cookies.
One entry point rather than three, because the user pasting a jar does not know which of the three formats their browser gave them — and asking is a worse question than looking.
| function export toCookieHeader | ( | cookies:Cookie[] | ) |
The Cookie: header value — what a request actually sends.
Which attributes cookies.txt needs and this jar does not have.
| function export toCookiesTxt | ( | cookies:Cookie[] | ) |
Netscape cookies.txt, for curl -b and yt-dlp --cookies.
Throws when the attributes are not there. A jar pasted as a bare document.cookie string has no domain and no path, and a file missing them is one yt-dlp reads and silently ignores — which the user discovers as "the
download is not logged in", with nothing pointing at the file. The browser-extension array shape, so a jar round-trips back into a browser. Playwright storageState; fail rather than silently lose sessionStorage or origin. The cookie name with any __Host- / __Secure- prefix removed. Every cookie an entry holds, from wherever it keeps them.
The jar lives in api_key as a header string, and the individual cookies live in extra_vars once the user has split them — with attrs carrying what cookies.txt needs and a pasted document.cookie string does not have. Reading both and preferring the split form is what lets one entry serve the header export (which needs no attributes) and the cookies.txt export (which needs all of them).
Twin: cookies_of in unv-cli/src/entries.rs.
| export interface Cookie |
One cookie, with whatever attributes the source carried.
| value __pad0__ |
| domain __pad1__ |
Attributes are absent for a jar pasted as a bare document.cookie string.
| path __pad2__ |
| secure __pad3__ |
| http_only __pad4__ |
| expires __pad5__ |
Unix seconds.
0 / absent is a session cookie.
| const COOKIE_PREFIX_RE = /^__(?:Host|Secure)-/i |
Cookie prefixes that are an instruction to the browser, not part of the name.
Stripped, never transliterated — see stripCookiePrefix in state.ts, which does the same for the generated variable name. That three cookies can collapse into one name is exactly the case the collision check has to warn about.