feat: v3.0.0 - intelligent search, GitHub person/project mode, ELI5, 13+ sources
v3 rewrites the search engine from the ground up: - Intelligent pre-research: resolves X handles, GitHub repos, subreddits, TikTok hashtags, and YouTube channels before searching - GitHub person-mode: PR velocity, top repos by stars, release notes - GitHub project-mode: live star counts, README, releases, top issues - ELI5 mode: plain language synthesis, no jargon - 13+ sources: Reddit, X, YouTube, TikTok, Instagram, HN, Polymarket, GitHub, Threads, Pinterest, Perplexity, Bluesky, Web - Free Reddit comments via public JSON (no API key needed) - Fun judge v2: humor scoring baked into narrative - Cookie consent before browser scanning - 10,000 free ScrapeCreators calls - 1,012 tests Thank you to the community contributors whose issues and PRs shaped v3: @uppinote20 (#143), @zerone0x (#134, #136), @thinkun (#116), @thomasmktong (#124), @fanispoulinakisai-boop (#100), @pejmanjohn (#78), @zl190 (#115), @hnshah (#84, #85, #86) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
-22
@@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Peter Steinberger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
# @steipete/sweet-cookie
|
||||
|
||||
Inline-first browser cookie extraction for local tooling (no native addons).
|
||||
|
||||
Supports:
|
||||
- Inline payloads (JSON / base64 / file) — most reliable path.
|
||||
- Local browser reads (best effort): Chrome, Edge, Firefox, Safari (macOS).
|
||||
|
||||
Install:
|
||||
```bash
|
||||
npm i @steipete/sweet-cookie
|
||||
```
|
||||
|
||||
Usage:
|
||||
```ts
|
||||
import { getCookies, toCookieHeader } from '@steipete/sweet-cookie';
|
||||
|
||||
const { cookies, warnings } = await getCookies({
|
||||
url: 'https://example.com/',
|
||||
names: ['session', 'csrf'],
|
||||
browsers: ['chrome', 'edge', 'firefox', 'safari'],
|
||||
});
|
||||
|
||||
for (const w of warnings) console.warn(w);
|
||||
const cookieHeader = toCookieHeader(cookies, { dedupeByName: true });
|
||||
```
|
||||
|
||||
Docs + extension exporter: see the repo root README.
|
||||
|
||||
Generated
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
export { getCookies, toCookieHeader } from './public.js';
|
||||
export type { BrowserName, Cookie, CookieHeaderOptions, CookieMode, CookieSameSite, GetCookiesOptions, GetCookiesResult, } from './types.js';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EACX,WAAW,EACX,MAAM,EACN,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC"}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export { getCookies, toCookieHeader } from './public.js';
|
||||
//# sourceMappingURL=index.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromChrome(options: {
|
||||
profile?: string;
|
||||
timeoutMs?: number;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=chrome.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/providers/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK5D,wBAAsB,oBAAoB,CACzC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC5F,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
|
||||
Generated
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
import { getCookiesFromChromeSqliteLinux } from './chromeSqliteLinux.js';
|
||||
import { getCookiesFromChromeSqliteMac } from './chromeSqliteMac.js';
|
||||
import { getCookiesFromChromeSqliteWindows } from './chromeSqliteWindows.js';
|
||||
export async function getCookiesFromChrome(options, origins, allowlistNames) {
|
||||
const warnings = [];
|
||||
// Platform dispatch only. All real logic lives in the per-OS providers.
|
||||
if (process.platform === 'darwin') {
|
||||
const r = await getCookiesFromChromeSqliteMac(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
if (process.platform === 'linux') {
|
||||
const r = await getCookiesFromChromeSqliteLinux(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
const r = await getCookiesFromChromeSqliteWindows(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
//# sourceMappingURL=chrome.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/providers/chrome.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,OAA4F,EAC5F,OAAiB,EACjB,cAAkC;IAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,wEAAwE;IACxE,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,MAAM,6BAA6B,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAChF,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,+BAA+B,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAClF,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,iCAAiC,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QACpF,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;AAClC,CAAC"}
|
||||
Generated
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
export declare function deriveAes128CbcKeyFromPassword(password: string, options: {
|
||||
iterations: number;
|
||||
}): Buffer;
|
||||
export declare function decryptChromiumAes128CbcCookieValue(encryptedValue: Uint8Array, keyCandidates: readonly Buffer[], options: {
|
||||
stripHashPrefix: boolean;
|
||||
treatUnknownPrefixAsPlaintext?: boolean;
|
||||
}): string | null;
|
||||
export declare function decryptChromiumAes256GcmCookieValue(encryptedValue: Uint8Array, key: Buffer, options: {
|
||||
stripHashPrefix: boolean;
|
||||
}): string | null;
|
||||
//# sourceMappingURL=crypto.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/crypto.ts"],"names":[],"mappings":"AAIA,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7B,MAAM,CAIR;AAED,wBAAgB,mCAAmC,CAClD,cAAc,EAAE,UAAU,EAC1B,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,OAAO,EAAE;IAAE,eAAe,EAAE,OAAO,CAAC;IAAC,6BAA6B,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5E,MAAM,GAAG,IAAI,CA2Bf;AAED,wBAAgB,mCAAmC,CAClD,cAAc,EAAE,UAAU,EAC1B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;IAAE,eAAe,EAAE,OAAO,CAAA;CAAE,GACnC,MAAM,GAAG,IAAI,CAyBf"}
|
||||
Generated
Vendored
-100
@@ -1,100 +0,0 @@
|
||||
import { createDecipheriv, pbkdf2Sync } from 'node:crypto';
|
||||
const UTF8_DECODER = new TextDecoder('utf-8', { fatal: true });
|
||||
export function deriveAes128CbcKeyFromPassword(password, options) {
|
||||
// Chromium derives the AES-128-CBC key from "Chrome Safe Storage" using PBKDF2.
|
||||
// The salt/length/digest are fixed by Chromium ("saltysalt", 16 bytes, sha1).
|
||||
return pbkdf2Sync(password, 'saltysalt', options.iterations, 16, 'sha1');
|
||||
}
|
||||
export function decryptChromiumAes128CbcCookieValue(encryptedValue, keyCandidates, options) {
|
||||
const buf = Buffer.from(encryptedValue);
|
||||
if (buf.length < 3)
|
||||
return null;
|
||||
// Chromium prefixes encrypted cookies with `v10`, `v11`, ... (three bytes).
|
||||
const prefix = buf.subarray(0, 3).toString('utf8');
|
||||
const hasVersionPrefix = /^v\d\d$/.test(prefix);
|
||||
if (!hasVersionPrefix) {
|
||||
// Some platforms (notably macOS) can store plaintext values in `encrypted_value`.
|
||||
// Callers decide whether unknown prefixes should be treated as plaintext.
|
||||
if (options.treatUnknownPrefixAsPlaintext === false)
|
||||
return null;
|
||||
return decodeCookieValueBytes(buf, false);
|
||||
}
|
||||
const ciphertext = buf.subarray(3);
|
||||
if (!ciphertext.length)
|
||||
return '';
|
||||
for (const key of keyCandidates) {
|
||||
// Try multiple candidates because Linux may fall back to empty passwords depending on keyring state.
|
||||
const decrypted = tryDecryptAes128Cbc(ciphertext, key);
|
||||
if (!decrypted)
|
||||
continue;
|
||||
const decoded = decodeCookieValueBytes(decrypted, options.stripHashPrefix);
|
||||
if (decoded !== null)
|
||||
return decoded;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export function decryptChromiumAes256GcmCookieValue(encryptedValue, key, options) {
|
||||
const buf = Buffer.from(encryptedValue);
|
||||
if (buf.length < 3)
|
||||
return null;
|
||||
const prefix = buf.subarray(0, 3).toString('utf8');
|
||||
if (!/^v\d\d$/.test(prefix))
|
||||
return null;
|
||||
// AES-256-GCM layout:
|
||||
// - 12-byte nonce
|
||||
// - ciphertext
|
||||
// - 16-byte authentication tag
|
||||
const payload = buf.subarray(3);
|
||||
if (payload.length < 12 + 16)
|
||||
return null;
|
||||
const nonce = payload.subarray(0, 12);
|
||||
const authenticationTag = payload.subarray(payload.length - 16);
|
||||
const ciphertext = payload.subarray(12, payload.length - 16);
|
||||
try {
|
||||
const decipher = createDecipheriv('aes-256-gcm', key, nonce);
|
||||
decipher.setAuthTag(authenticationTag);
|
||||
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
||||
return decodeCookieValueBytes(plaintext, options.stripHashPrefix);
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function tryDecryptAes128Cbc(ciphertext, key) {
|
||||
try {
|
||||
// Chromium's legacy AES-128-CBC uses an IV of 16 spaces.
|
||||
const iv = Buffer.alloc(16, 0x20);
|
||||
const decipher = createDecipheriv('aes-128-cbc', key, iv);
|
||||
decipher.setAutoPadding(false);
|
||||
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
||||
return removePkcs7Padding(plaintext);
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function removePkcs7Padding(value) {
|
||||
if (!value.length)
|
||||
return value;
|
||||
const padding = value[value.length - 1];
|
||||
if (!padding || padding > 16)
|
||||
return value;
|
||||
return value.subarray(0, value.length - padding);
|
||||
}
|
||||
function decodeCookieValueBytes(value, stripHashPrefix) {
|
||||
// Chromium >= 24 prepends a 32-byte hash to cookie values.
|
||||
const bytes = stripHashPrefix && value.length >= 32 ? value.subarray(32) : value;
|
||||
try {
|
||||
return stripLeadingControlChars(UTF8_DECODER.decode(bytes));
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function stripLeadingControlChars(value) {
|
||||
let i = 0;
|
||||
while (i < value.length && value.charCodeAt(i) < 0x20)
|
||||
i += 1;
|
||||
return value.slice(i);
|
||||
}
|
||||
//# sourceMappingURL=crypto.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,YAAY,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/D,MAAM,UAAU,8BAA8B,CAC7C,QAAgB,EAChB,OAA+B;IAE/B,gFAAgF;IAChF,8EAA8E;IAC9E,OAAO,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,mCAAmC,CAClD,cAA0B,EAC1B,aAAgC,EAChC,OAA8E;IAE9E,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhC,4EAA4E;IAC5E,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvB,kFAAkF;QAClF,0EAA0E;QAC1E,IAAI,OAAO,CAAC,6BAA6B,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;QACjE,OAAO,sBAAsB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACjC,qGAAqG;QACrG,MAAM,SAAS,GAAG,mBAAmB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QAC3E,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,mCAAmC,CAClD,cAA0B,EAC1B,GAAW,EACX,OAAqC;IAErC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,sBAAsB;IACtB,kBAAkB;IAClB,eAAe;IACf,+BAA+B;IAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,iBAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAE7D,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7D,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACjF,OAAO,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB,EAAE,GAAW;IAC3D,IAAI,CAAC;QACJ,yDAAyD;QACzD,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC1D,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACjF,OAAO,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACxC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxC,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa,EAAE,eAAwB;IACtE,2DAA2D;IAC3D,MAAM,KAAK,GAAG,eAAe,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,IAAI,CAAC;QACJ,OAAO,wBAAwB,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAa;IAC9C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;QAAE,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC"}
|
||||
Generated
Vendored
-25
@@ -1,25 +0,0 @@
|
||||
export type LinuxKeyringBackend = 'gnome' | 'kwallet' | 'basic';
|
||||
/**
|
||||
* Read the "Safe Storage" password from a Linux keyring.
|
||||
*
|
||||
* Chromium browsers typically store their cookie encryption password under:
|
||||
* - service: "<Browser> Safe Storage"
|
||||
* - account: "<Browser>"
|
||||
*
|
||||
* We keep this logic in JS (no native deps) and return an empty password on failure
|
||||
* (Chromium may still have v10 cookies, and callers can use inline/export escape hatches).
|
||||
*/
|
||||
export declare function getLinuxChromiumSafeStoragePassword(options: {
|
||||
backend?: LinuxKeyringBackend;
|
||||
app: 'chrome' | 'edge';
|
||||
}): Promise<{
|
||||
password: string;
|
||||
warnings: string[];
|
||||
}>;
|
||||
export declare function getLinuxChromeSafeStoragePassword(options?: {
|
||||
backend?: LinuxKeyringBackend;
|
||||
}): Promise<{
|
||||
password: string;
|
||||
warnings: string[];
|
||||
}>;
|
||||
//# sourceMappingURL=linuxKeyring.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"linuxKeyring.d.ts","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/linuxKeyring.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhE;;;;;;;;;GASG;AACH,wBAAsB,mCAAmC,CAAC,OAAO,EAAE;IAClE,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA8DpD;AAED,wBAAsB,iCAAiC,CACtD,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAO,GAC7C,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAInD"}
|
||||
Generated
Vendored
-104
@@ -1,104 +0,0 @@
|
||||
import { execCapture } from '../../util/exec.js';
|
||||
/**
|
||||
* Read the "Safe Storage" password from a Linux keyring.
|
||||
*
|
||||
* Chromium browsers typically store their cookie encryption password under:
|
||||
* - service: "<Browser> Safe Storage"
|
||||
* - account: "<Browser>"
|
||||
*
|
||||
* We keep this logic in JS (no native deps) and return an empty password on failure
|
||||
* (Chromium may still have v10 cookies, and callers can use inline/export escape hatches).
|
||||
*/
|
||||
export async function getLinuxChromiumSafeStoragePassword(options) {
|
||||
const warnings = [];
|
||||
// Escape hatch: if callers already know the password (or want deterministic CI behavior),
|
||||
// they can bypass keyring probing entirely.
|
||||
const overrideKey = options.app === 'edge'
|
||||
? 'SWEET_COOKIE_EDGE_SAFE_STORAGE_PASSWORD'
|
||||
: 'SWEET_COOKIE_CHROME_SAFE_STORAGE_PASSWORD';
|
||||
const override = readEnv(overrideKey);
|
||||
if (override !== undefined)
|
||||
return { password: override, warnings };
|
||||
const backend = options.backend ?? parseLinuxKeyringBackend() ?? chooseLinuxKeyringBackend();
|
||||
// `basic` means "don't try keyrings" (Chrome will fall back to older/less-secure schemes on some setups).
|
||||
if (backend === 'basic')
|
||||
return { password: '', warnings };
|
||||
const service = options.app === 'edge' ? 'Microsoft Edge Safe Storage' : 'Chrome Safe Storage';
|
||||
const account = options.app === 'edge' ? 'Microsoft Edge' : 'Chrome';
|
||||
const folder = `${account} Keys`;
|
||||
if (backend === 'gnome') {
|
||||
// GNOME keyring: `secret-tool` is the simplest way to read libsecret entries.
|
||||
const res = await execCapture('secret-tool', ['lookup', 'service', service, 'account', account], { timeoutMs: 3_000 });
|
||||
if (res.code === 0)
|
||||
return { password: res.stdout.trim(), warnings };
|
||||
warnings.push('Failed to read Linux keyring via secret-tool; v11 cookies may be unavailable.');
|
||||
return { password: '', warnings };
|
||||
}
|
||||
// KDE keyring: query KWallet via `kwallet-query`, but the wallet name differs across KDE versions.
|
||||
const kdeVersion = (readEnv('KDE_SESSION_VERSION') ?? '').trim();
|
||||
const serviceName = kdeVersion === '6'
|
||||
? 'org.kde.kwalletd6'
|
||||
: kdeVersion === '5'
|
||||
? 'org.kde.kwalletd5'
|
||||
: 'org.kde.kwalletd';
|
||||
const walletPath = kdeVersion === '6'
|
||||
? '/modules/kwalletd6'
|
||||
: kdeVersion === '5'
|
||||
? '/modules/kwalletd5'
|
||||
: '/modules/kwalletd';
|
||||
const wallet = await getKWalletNetworkWallet(serviceName, walletPath);
|
||||
const passwordRes = await execCapture('kwallet-query', ['--read-password', service, '--folder', folder, wallet], { timeoutMs: 3_000 });
|
||||
if (passwordRes.code !== 0) {
|
||||
warnings.push('Failed to read Linux keyring via kwallet-query; v11 cookies may be unavailable.');
|
||||
return { password: '', warnings };
|
||||
}
|
||||
if (passwordRes.stdout.toLowerCase().startsWith('failed to read'))
|
||||
return { password: '', warnings };
|
||||
return { password: passwordRes.stdout.trim(), warnings };
|
||||
}
|
||||
export async function getLinuxChromeSafeStoragePassword(options = {}) {
|
||||
const args = { app: 'chrome' };
|
||||
if (options.backend !== undefined)
|
||||
args.backend = options.backend;
|
||||
return await getLinuxChromiumSafeStoragePassword(args);
|
||||
}
|
||||
function parseLinuxKeyringBackend() {
|
||||
const raw = readEnv('SWEET_COOKIE_LINUX_KEYRING');
|
||||
if (!raw)
|
||||
return undefined;
|
||||
const normalized = raw.toLowerCase();
|
||||
if (normalized === 'gnome')
|
||||
return 'gnome';
|
||||
if (normalized === 'kwallet')
|
||||
return 'kwallet';
|
||||
if (normalized === 'basic')
|
||||
return 'basic';
|
||||
return undefined;
|
||||
}
|
||||
function chooseLinuxKeyringBackend() {
|
||||
const xdg = readEnv('XDG_CURRENT_DESKTOP') ?? '';
|
||||
const isKde = xdg.split(':').some((p) => p.trim().toLowerCase() === 'kde') || !!readEnv('KDE_FULL_SESSION');
|
||||
return isKde ? 'kwallet' : 'gnome';
|
||||
}
|
||||
async function getKWalletNetworkWallet(serviceName, walletPath) {
|
||||
const res = await execCapture('dbus-send', [
|
||||
'--session',
|
||||
'--print-reply=literal',
|
||||
`--dest=${serviceName}`,
|
||||
walletPath,
|
||||
'org.kde.KWallet.networkWallet',
|
||||
], { timeoutMs: 3_000 });
|
||||
const fallback = 'kdewallet';
|
||||
if (res.code !== 0)
|
||||
return fallback;
|
||||
const raw = res.stdout.trim();
|
||||
if (!raw)
|
||||
return fallback;
|
||||
return raw.replaceAll('"', '').trim() || fallback;
|
||||
}
|
||||
function readEnv(key) {
|
||||
const value = process.env[key];
|
||||
const trimmed = typeof value === 'string' ? value.trim() : '';
|
||||
return trimmed.length ? trimmed : undefined;
|
||||
}
|
||||
//# sourceMappingURL=linuxKeyring.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"linuxKeyring.js","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/linuxKeyring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,OAGzD;IACA,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,0FAA0F;IAC1F,4CAA4C;IAC5C,MAAM,WAAW,GAChB,OAAO,CAAC,GAAG,KAAK,MAAM;QACrB,CAAC,CAAC,yCAAyC;QAC3C,CAAC,CAAC,2CAA2C,CAAC;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAEpE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,EAAE,IAAI,yBAAyB,EAAE,CAAC;IAC7F,0GAA0G;IAC1G,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IAE3D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC/F,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,MAAM,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC;IAEjC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACzB,8EAA8E;QAC9E,MAAM,GAAG,GAAG,MAAM,WAAW,CAC5B,aAAa,EACb,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAClD,EAAE,SAAS,EAAE,KAAK,EAAE,CACpB,CAAC;QACF,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;QACrE,QAAQ,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;QAC/F,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAED,mGAAmG;IACnG,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjE,MAAM,WAAW,GAChB,UAAU,KAAK,GAAG;QACjB,CAAC,CAAC,mBAAmB;QACrB,CAAC,CAAC,UAAU,KAAK,GAAG;YACnB,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,kBAAkB,CAAC;IACxB,MAAM,UAAU,GACf,UAAU,KAAK,GAAG;QACjB,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,UAAU,KAAK,GAAG;YACnB,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,mBAAmB,CAAC;IAEzB,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,MAAM,WAAW,CACpC,eAAe,EACf,CAAC,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EACxD,EAAE,SAAS,EAAE,KAAK,EAAE,CACpB,CAAC;IACF,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CACZ,iFAAiF,CACjF,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAChE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IACnC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACtD,UAA6C,EAAE;IAE/C,MAAM,IAAI,GAAqD,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;IACjF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAClE,OAAO,MAAM,mCAAmC,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,wBAAwB;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,UAAU,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IAC3C,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC/C,IAAI,UAAU,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IAC3C,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,KAAK,GACV,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AACpC,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,WAAmB,EAAE,UAAkB;IAC7E,MAAM,GAAG,GAAG,MAAM,WAAW,CAC5B,WAAW,EACX;QACC,WAAW;QACX,uBAAuB;QACvB,UAAU,WAAW,EAAE;QACvB,UAAU;QACV,+BAA+B;KAC/B,EACD,EAAE,SAAS,EAAE,KAAK,EAAE,CACpB,CAAC;IACF,MAAM,QAAQ,GAAG,WAAW,CAAC;IAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC;AACnD,CAAC;AAED,SAAS,OAAO,CAAC,GAAW;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC"}
|
||||
Generated
Vendored
-10
@@ -1,10 +0,0 @@
|
||||
import type { GetCookiesResult } from '../../types.js';
|
||||
export declare function getCookiesFromChromeSqliteDb(options: {
|
||||
dbPath: string;
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null, decrypt: (encryptedValue: Uint8Array, options: {
|
||||
stripHashPrefix: boolean;
|
||||
}) => string | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=shared.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/shared.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA0B,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAkB/E,wBAAsB,4BAA4B,CACjD,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxF,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAClC,OAAO,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE;IAAE,eAAe,EAAE,OAAO,CAAA;CAAE,KAAK,MAAM,GAAG,IAAI,GAC3F,OAAO,CAAC,gBAAgB,CAAC,CAsD3B"}
|
||||
Generated
Vendored
-293
@@ -1,293 +0,0 @@
|
||||
import { copyFileSync, existsSync, mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { normalizeExpiration } from '../../util/expire.js';
|
||||
import { hostMatchesCookieDomain } from '../../util/hostMatch.js';
|
||||
import { importNodeSqlite, supportsReadBigInts } from '../../util/nodeSqlite.js';
|
||||
import { isBunRuntime } from '../../util/runtime.js';
|
||||
export async function getCookiesFromChromeSqliteDb(options, origins, allowlistNames, decrypt) {
|
||||
const warnings = [];
|
||||
// Chrome can keep its cookie DB locked and/or rely on WAL sidecars.
|
||||
// Copying to a temp dir gives us a stable snapshot that both node:sqlite and bun:sqlite can open.
|
||||
const tempDir = mkdtempSync(path.join(tmpdir(), 'sweet-cookie-chrome-'));
|
||||
const tempDbPath = path.join(tempDir, 'Cookies');
|
||||
try {
|
||||
copyFileSync(options.dbPath, tempDbPath);
|
||||
// If WAL is enabled, the latest writes might live in `Cookies-wal`/`Cookies-shm`.
|
||||
// Copy them too when present so our snapshot reflects the current browser state.
|
||||
copySidecar(options.dbPath, `${tempDbPath}-wal`, '-wal');
|
||||
copySidecar(options.dbPath, `${tempDbPath}-shm`, '-shm');
|
||||
}
|
||||
catch (error) {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
warnings.push(`Failed to copy Chrome cookie DB: ${error instanceof Error ? error.message : String(error)}`);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
try {
|
||||
const hosts = origins.map((o) => new URL(o).hostname);
|
||||
const where = buildHostWhereClause(hosts, 'host_key');
|
||||
const metaVersion = await readChromiumMetaVersion(tempDbPath);
|
||||
// Chromium >= 24 stores a 32-byte hash prefix in decrypted cookie values.
|
||||
// We detect this via the `meta` table version and strip it when present.
|
||||
const stripHashPrefix = metaVersion >= 24;
|
||||
const rowsResult = await readChromeRows(tempDbPath, where);
|
||||
if (!rowsResult.ok) {
|
||||
warnings.push(rowsResult.error);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const collectOptions = {};
|
||||
if (options.profile)
|
||||
collectOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
collectOptions.includeExpired = options.includeExpired;
|
||||
const cookies = collectChromeCookiesFromRows(rowsResult.rows, collectOptions, hosts, allowlistNames, (encryptedValue) => decrypt(encryptedValue, { stripHashPrefix }), warnings);
|
||||
return { cookies: dedupeCookies(cookies), warnings };
|
||||
}
|
||||
finally {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
function collectChromeCookiesFromRows(rows, options, hosts, allowlistNames, decrypt, warnings) {
|
||||
const cookies = [];
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
let warnedEncryptedType = false;
|
||||
for (const row of rows) {
|
||||
const name = typeof row.name === 'string' ? row.name : null;
|
||||
if (!name)
|
||||
continue;
|
||||
if (allowlistNames && allowlistNames.size > 0 && !allowlistNames.has(name))
|
||||
continue;
|
||||
const hostKey = typeof row.host_key === 'string' ? row.host_key : null;
|
||||
if (!hostKey)
|
||||
continue;
|
||||
if (!hostMatchesAny(hosts, hostKey))
|
||||
continue;
|
||||
const rowPath = typeof row.path === 'string' ? row.path : '';
|
||||
const valueString = typeof row.value === 'string' ? row.value : null;
|
||||
let value = valueString;
|
||||
if (value === null || value.length === 0) {
|
||||
// Many modern Chromium cookies keep `value` empty and only store `encrypted_value`.
|
||||
// We decrypt on demand and drop rows we can't interpret.
|
||||
const encryptedBytes = getEncryptedBytes(row);
|
||||
if (!encryptedBytes) {
|
||||
if (!warnedEncryptedType && row.encrypted_value !== undefined) {
|
||||
warnings.push('Chrome cookie encrypted_value is in an unsupported type.');
|
||||
warnedEncryptedType = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
value = decrypt(encryptedBytes);
|
||||
}
|
||||
if (value === null)
|
||||
continue;
|
||||
const expiresRaw = typeof row.expires_utc === 'number' || typeof row.expires_utc === 'bigint'
|
||||
? row.expires_utc
|
||||
: tryParseInt(row.expires_utc);
|
||||
const expires = normalizeExpiration(expiresRaw ?? undefined);
|
||||
if (!options.includeExpired) {
|
||||
if (expires && expires < now)
|
||||
continue;
|
||||
}
|
||||
const secure = row.is_secure === 1 ||
|
||||
row.is_secure === 1n ||
|
||||
row.is_secure === '1' ||
|
||||
row.is_secure === true;
|
||||
const httpOnly = row.is_httponly === 1 ||
|
||||
row.is_httponly === 1n ||
|
||||
row.is_httponly === '1' ||
|
||||
row.is_httponly === true;
|
||||
const sameSite = normalizeChromiumSameSite(row.samesite);
|
||||
const source = { browser: 'chrome' };
|
||||
if (options.profile)
|
||||
source.profile = options.profile;
|
||||
const cookie = {
|
||||
name,
|
||||
value,
|
||||
domain: hostKey.startsWith('.') ? hostKey.slice(1) : hostKey,
|
||||
path: rowPath || '/',
|
||||
secure,
|
||||
httpOnly,
|
||||
source,
|
||||
};
|
||||
if (expires !== undefined)
|
||||
cookie.expires = expires;
|
||||
if (sameSite !== undefined)
|
||||
cookie.sameSite = sameSite;
|
||||
cookies.push(cookie);
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
function tryParseInt(value) {
|
||||
if (typeof value === 'bigint') {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
if (typeof value !== 'string')
|
||||
return null;
|
||||
const parsed = Number.parseInt(value, 10);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
function normalizeChromiumSameSite(value) {
|
||||
if (typeof value === 'bigint') {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? normalizeChromiumSameSite(parsed) : undefined;
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
if (value === 2)
|
||||
return 'Strict';
|
||||
if (value === 1)
|
||||
return 'Lax';
|
||||
if (value === 0)
|
||||
return 'None';
|
||||
return undefined;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const parsed = Number.parseInt(value, 10);
|
||||
if (Number.isFinite(parsed))
|
||||
return normalizeChromiumSameSite(parsed);
|
||||
const normalized = value.toLowerCase();
|
||||
if (normalized === 'strict')
|
||||
return 'Strict';
|
||||
if (normalized === 'lax')
|
||||
return 'Lax';
|
||||
if (normalized === 'none' || normalized === 'no_restriction')
|
||||
return 'None';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function getEncryptedBytes(row) {
|
||||
const raw = row.encrypted_value;
|
||||
if (raw instanceof Uint8Array)
|
||||
return raw;
|
||||
return null;
|
||||
}
|
||||
async function readChromiumMetaVersion(dbPath) {
|
||||
const sql = `SELECT value FROM meta WHERE key = 'version'`;
|
||||
const result = isBunRuntime()
|
||||
? await queryNodeOrBun({ kind: 'bun', dbPath, sql })
|
||||
: await queryNodeOrBun({ kind: 'node', dbPath, sql });
|
||||
if (!result.ok)
|
||||
return 0;
|
||||
const first = result.rows[0];
|
||||
const value = first?.value;
|
||||
if (typeof value === 'number')
|
||||
return Math.floor(value);
|
||||
if (typeof value === 'bigint') {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? Math.floor(parsed) : 0;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const parsed = Number.parseInt(value, 10);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
async function readChromeRows(dbPath, where) {
|
||||
const sqliteKind = isBunRuntime() ? 'bun' : 'node';
|
||||
const sqliteLabel = sqliteKind === 'bun' ? 'bun:sqlite' : 'node:sqlite';
|
||||
const sql = `SELECT name, value, host_key, path, expires_utc, samesite, encrypted_value, ` +
|
||||
`is_secure AS is_secure, is_httponly AS is_httponly ` +
|
||||
`FROM cookies WHERE (${where}) ORDER BY expires_utc DESC;`;
|
||||
const result = await queryNodeOrBun({ kind: sqliteKind, dbPath, sql });
|
||||
if (result.ok)
|
||||
return { ok: true, rows: result.rows };
|
||||
// Intentionally strict: only support modern Chromium cookie DB schemas.
|
||||
// If this fails, assume the local Chrome/Chromium is too old or uses a non-standard schema.
|
||||
return {
|
||||
ok: false,
|
||||
error: `${sqliteLabel} failed reading Chrome cookies (requires modern Chromium, e.g. Chrome >= 100): ${result.error}`,
|
||||
};
|
||||
}
|
||||
async function queryNodeOrBun(options) {
|
||||
try {
|
||||
if (options.kind === 'node') {
|
||||
// Node's `node:sqlite` is synchronous and returns plain JS values. Keep it boxed in a
|
||||
// small scope so callers don't need to care about runtime differences.
|
||||
const { DatabaseSync } = await importNodeSqlite();
|
||||
const dbOptions = { readOnly: true };
|
||||
if (supportsReadBigInts()) {
|
||||
dbOptions.readBigInts = true;
|
||||
}
|
||||
const db = new DatabaseSync(options.dbPath, dbOptions);
|
||||
try {
|
||||
const rows = db.prepare(options.sql).all();
|
||||
return { ok: true, rows };
|
||||
}
|
||||
finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
// Bun's sqlite API has a different surface (`Database` + `.query().all()`).
|
||||
const { Database } = await import('bun:sqlite');
|
||||
const db = new Database(options.dbPath, { readonly: true });
|
||||
try {
|
||||
const rows = db.query(options.sql).all();
|
||||
return { ok: true, rows };
|
||||
}
|
||||
finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
function copySidecar(sourceDbPath, target, suffix) {
|
||||
const sidecar = `${sourceDbPath}${suffix}`;
|
||||
if (!existsSync(sidecar))
|
||||
return;
|
||||
try {
|
||||
copyFileSync(sidecar, target);
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
function buildHostWhereClause(hosts, column) {
|
||||
const clauses = [];
|
||||
for (const host of hosts) {
|
||||
// Chrome cookies often live on parent domains (e.g. .google.com for gemini.google.com).
|
||||
// Include parent domains so the SQL filter doesn't drop valid session cookies.
|
||||
for (const candidate of expandHostCandidates(host)) {
|
||||
const escaped = sqlLiteral(candidate);
|
||||
const escapedDot = sqlLiteral(`.${candidate}`);
|
||||
const escapedLike = sqlLiteral(`%.${candidate}`);
|
||||
clauses.push(`${column} = ${escaped}`);
|
||||
clauses.push(`${column} = ${escapedDot}`);
|
||||
clauses.push(`${column} LIKE ${escapedLike}`);
|
||||
}
|
||||
}
|
||||
return clauses.length ? clauses.join(' OR ') : '1=0';
|
||||
}
|
||||
function sqlLiteral(value) {
|
||||
const escaped = value.replaceAll("'", "''");
|
||||
return `'${escaped}'`;
|
||||
}
|
||||
function expandHostCandidates(host) {
|
||||
const parts = host.split('.').filter(Boolean);
|
||||
if (parts.length <= 1)
|
||||
return [host];
|
||||
const candidates = new Set();
|
||||
candidates.add(host);
|
||||
// Include parent domains down to two labels (avoid TLD-only fragments).
|
||||
for (let i = 1; i <= parts.length - 2; i += 1) {
|
||||
const candidate = parts.slice(i).join('.');
|
||||
if (candidate)
|
||||
candidates.add(candidate);
|
||||
}
|
||||
return Array.from(candidates);
|
||||
}
|
||||
function hostMatchesAny(hosts, cookieHost) {
|
||||
const cookieDomain = cookieHost.startsWith('.') ? cookieHost.slice(1) : cookieHost;
|
||||
return hosts.some((host) => hostMatchesCookieDomain(host, cookieDomain));
|
||||
}
|
||||
function dedupeCookies(cookies) {
|
||||
const merged = new Map();
|
||||
for (const cookie of cookies) {
|
||||
const key = `${cookie.name}|${cookie.domain ?? ''}|${cookie.path ?? ''}`;
|
||||
if (!merged.has(key))
|
||||
merged.set(key, cookie);
|
||||
}
|
||||
return Array.from(merged.values());
|
||||
}
|
||||
//# sourceMappingURL=shared.js.map
|
||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-10
@@ -1,10 +0,0 @@
|
||||
export declare function dpapiUnprotect(data: Buffer, options?: {
|
||||
timeoutMs?: number;
|
||||
}): Promise<{
|
||||
ok: true;
|
||||
value: Buffer;
|
||||
} | {
|
||||
ok: false;
|
||||
error: string;
|
||||
}>;
|
||||
//# sourceMappingURL=windowsDpapi.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsDpapi.d.ts","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/windowsDpapi.ts"],"names":[],"mappings":"AAEA,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+BrE"}
|
||||
Generated
Vendored
-26
@@ -1,26 +0,0 @@
|
||||
import { execCapture } from '../../util/exec.js';
|
||||
export async function dpapiUnprotect(data, options = {}) {
|
||||
const timeoutMs = options.timeoutMs ?? 5_000;
|
||||
// There is no cross-platform JS API for Windows DPAPI, and we explicitly avoid native addons.
|
||||
// PowerShell can call ProtectedData.Unprotect for the current user, which matches Chrome's behavior.
|
||||
const inputB64 = data.toString('base64');
|
||||
const prelude = 'try { Add-Type -AssemblyName System.Security.Cryptography.ProtectedData -ErrorAction Stop } catch { try { Add-Type -AssemblyName System.Security -ErrorAction Stop } catch {} };';
|
||||
const script = prelude +
|
||||
`$in=[Convert]::FromBase64String('${inputB64}');` +
|
||||
`$out=[System.Security.Cryptography.ProtectedData]::Unprotect($in,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);` +
|
||||
`[Convert]::ToBase64String($out)`;
|
||||
const res = await execCapture('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], {
|
||||
timeoutMs,
|
||||
});
|
||||
if (res.code !== 0) {
|
||||
return { ok: false, error: res.stderr.trim() || `powershell exit ${res.code}` };
|
||||
}
|
||||
try {
|
||||
const out = Buffer.from(res.stdout.trim(), 'base64');
|
||||
return { ok: true, value: out };
|
||||
}
|
||||
catch (error) {
|
||||
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=windowsDpapi.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsDpapi.js","sourceRoot":"","sources":["../../../src/providers/chromeSqlite/windowsDpapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,IAAY,EACZ,UAAkC,EAAE;IAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAE7C,8FAA8F;IAC9F,qGAAqG;IACrG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,OAAO,GACZ,kLAAkL,CAAC;IACpL,MAAM,MAAM,GACX,OAAO;QACP,oCAAoC,QAAQ,KAAK;QACjD,0IAA0I;QAC1I,iCAAiC,CAAC;IAEnC,MAAM,GAAG,GAAG,MAAM,WAAW,CAC5B,YAAY,EACZ,CAAC,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,CAAC,EACrD;QACC,SAAS;KACT,CACD,CAAC;IACF,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,mBAAmB,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IACjF,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACrF,CAAC;AACF,CAAC"}
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromChromeSqliteLinux(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=chromeSqliteLinux.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteLinux.d.ts","sourceRoot":"","sources":["../../src/providers/chromeSqliteLinux.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASpD,wBAAsB,+BAA+B,CACpD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxE,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAkD3B"}
|
||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
||||
import { decryptChromiumAes128CbcCookieValue, deriveAes128CbcKeyFromPassword, } from './chromeSqlite/crypto.js';
|
||||
import { getLinuxChromeSafeStoragePassword } from './chromeSqlite/linuxKeyring.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { resolveChromiumCookiesDbLinux } from './chromium/linuxPaths.js';
|
||||
export async function getCookiesFromChromeSqliteLinux(options, origins, allowlistNames) {
|
||||
const args = {
|
||||
configDirName: 'google-chrome',
|
||||
};
|
||||
if (options.profile !== undefined)
|
||||
args.profile = options.profile;
|
||||
const dbPath = resolveChromiumCookiesDbLinux(args);
|
||||
if (!dbPath) {
|
||||
return { cookies: [], warnings: ['Chrome cookies database not found.'] };
|
||||
}
|
||||
const { password, warnings: keyringWarnings } = await getLinuxChromeSafeStoragePassword();
|
||||
// Linux uses multiple schemes depending on distro/keyring availability.
|
||||
// - v10 often uses the hard-coded "peanuts" password
|
||||
// - v11 uses "Chrome Safe Storage" from the keyring (may be empty/unavailable)
|
||||
const v10Key = deriveAes128CbcKeyFromPassword('peanuts', { iterations: 1 });
|
||||
const emptyKey = deriveAes128CbcKeyFromPassword('', { iterations: 1 });
|
||||
const v11Key = deriveAes128CbcKeyFromPassword(password, { iterations: 1 });
|
||||
const decrypt = (encryptedValue, opts) => {
|
||||
const prefix = Buffer.from(encryptedValue).subarray(0, 3).toString('utf8');
|
||||
if (prefix === 'v10') {
|
||||
return decryptChromiumAes128CbcCookieValue(encryptedValue, [v10Key, emptyKey], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: false,
|
||||
});
|
||||
}
|
||||
if (prefix === 'v11') {
|
||||
return decryptChromiumAes128CbcCookieValue(encryptedValue, [v11Key, emptyKey], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: false,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
const result = await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
result.warnings.unshift(...keyringWarnings);
|
||||
return result;
|
||||
}
|
||||
//# sourceMappingURL=chromeSqliteLinux.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteLinux.js","sourceRoot":"","sources":["../../src/providers/chromeSqliteLinux.ts"],"names":[],"mappings":"AACA,OAAO,EACN,mCAAmC,EACnC,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACpD,OAAwE,EACxE,OAAiB,EACjB,cAAkC;IAElC,MAAM,IAAI,GAAwD;QACjE,aAAa,EAAE,eAAe;KAC9B,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAClE,MAAM,MAAM,GAAG,6BAA6B,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,oCAAoC,CAAC,EAAE,CAAC;IAC1E,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,iCAAiC,EAAE,CAAC;IAE1F,wEAAwE;IACxE,qDAAqD;IACrD,+EAA+E;IAC/E,MAAM,MAAM,GAAG,8BAA8B,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,8BAA8B,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,8BAA8B,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAE3E,MAAM,OAAO,GAAG,CACf,cAA0B,EAC1B,IAAkC,EAClB,EAAE;QAClB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3E,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO,mCAAmC,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;gBAC9E,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,6BAA6B,EAAE,KAAK;aACpC,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO,mCAAmC,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;gBAC9E,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,6BAA6B,EAAE,KAAK;aACpC,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,SAAS,GACd;QACC,MAAM;KACN,CAAC;IACH,IAAI,OAAO,CAAC,OAAO;QAAE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzD,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;QAAE,SAAS,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAEjE,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAC/F,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AACf,CAAC"}
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromChromeSqliteMac(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=chromeSqliteMac.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteMac.d.ts","sourceRoot":"","sources":["../../src/providers/chromeSqliteMac.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASpD,wBAAsB,6BAA6B,CAClD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxE,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
|
||||
scripts/lib/vendor/bird-search/node_modules/@steipete/sweet-cookie/dist/providers/chromeSqliteMac.js
Generated
Vendored
-60
@@ -1,60 +0,0 @@
|
||||
import { homedir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { decryptChromiumAes128CbcCookieValue, deriveAes128CbcKeyFromPassword, } from './chromeSqlite/crypto.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { readKeychainGenericPasswordFirst } from './chromium/macosKeychain.js';
|
||||
import { resolveCookiesDbFromProfileOrRoots } from './chromium/paths.js';
|
||||
export async function getCookiesFromChromeSqliteMac(options, origins, allowlistNames) {
|
||||
const dbPath = resolveChromeCookiesDb(options.profile);
|
||||
if (!dbPath) {
|
||||
return { cookies: [], warnings: ['Chrome cookies database not found.'] };
|
||||
}
|
||||
const warnings = [];
|
||||
// On macOS, Chrome stores its "Safe Storage" secret in Keychain.
|
||||
// `security find-generic-password` is stable and avoids any native Node keychain modules.
|
||||
const passwordResult = await readKeychainGenericPasswordFirst({
|
||||
account: 'Chrome',
|
||||
services: ['Chrome Safe Storage'],
|
||||
timeoutMs: 3_000,
|
||||
label: 'Chrome Safe Storage',
|
||||
});
|
||||
if (!passwordResult.ok) {
|
||||
warnings.push(passwordResult.error);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const chromePassword = passwordResult.password.trim();
|
||||
if (!chromePassword) {
|
||||
warnings.push('macOS Keychain returned an empty Chrome Safe Storage password.');
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
// Chromium uses PBKDF2(password, "saltysalt", 1003, 16, sha1) for AES-128-CBC cookie values on macOS.
|
||||
const key = deriveAes128CbcKeyFromPassword(chromePassword, { iterations: 1003 });
|
||||
const decrypt = (encryptedValue, opts) => decryptChromiumAes128CbcCookieValue(encryptedValue, [key], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: true,
|
||||
});
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
const result = await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
result.warnings.unshift(...warnings);
|
||||
return result;
|
||||
}
|
||||
function resolveChromeCookiesDb(profile) {
|
||||
const home = homedir();
|
||||
/* c8 ignore next */
|
||||
const roots = process.platform === 'darwin'
|
||||
? [path.join(home, 'Library', 'Application Support', 'Google', 'Chrome')]
|
||||
: [];
|
||||
const args = { roots };
|
||||
if (profile !== undefined)
|
||||
args.profile = profile;
|
||||
return resolveCookiesDbFromProfileOrRoots(args);
|
||||
}
|
||||
//# sourceMappingURL=chromeSqliteMac.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteMac.js","sourceRoot":"","sources":["../../src/providers/chromeSqliteMac.ts"],"names":[],"mappings":"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"}
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromChromeSqliteWindows(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=chromeSqliteWindows.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteWindows.d.ts","sourceRoot":"","sources":["../../src/providers/chromeSqliteWindows.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,wBAAsB,iCAAiC,CACtD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxE,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAmC3B"}
|
||||
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
||||
import path from 'node:path';
|
||||
import { decryptChromiumAes256GcmCookieValue } from './chromeSqlite/crypto.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { getWindowsChromiumMasterKey } from './chromium/windowsMasterKey.js';
|
||||
import { resolveChromiumPathsWindows } from './chromium/windowsPaths.js';
|
||||
export async function getCookiesFromChromeSqliteWindows(options, origins, allowlistNames) {
|
||||
const resolveArgs = {
|
||||
localAppDataVendorPath: path.join('Google', 'Chrome', 'User Data'),
|
||||
};
|
||||
if (options.profile !== undefined)
|
||||
resolveArgs.profile = options.profile;
|
||||
const { dbPath, userDataDir } = resolveChromiumPathsWindows(resolveArgs);
|
||||
if (!dbPath || !userDataDir) {
|
||||
return { cookies: [], warnings: ['Chrome cookies database not found.'] };
|
||||
}
|
||||
// On Windows, Chrome stores an AES key in `Local State` encrypted with DPAPI (CurrentUser).
|
||||
// That master key is then used for AES-256-GCM cookie values (`v10`/`v11`/`v20` prefixes).
|
||||
const masterKey = await getWindowsChromiumMasterKey(userDataDir, 'Chrome');
|
||||
if (!masterKey.ok) {
|
||||
return { cookies: [], warnings: [masterKey.error] };
|
||||
}
|
||||
const decrypt = (encryptedValue, opts) => {
|
||||
return decryptChromiumAes256GcmCookieValue(encryptedValue, masterKey.value, {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
});
|
||||
};
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
return await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
}
|
||||
//# sourceMappingURL=chromeSqliteWindows.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"chromeSqliteWindows.js","sourceRoot":"","sources":["../../src/providers/chromeSqliteWindows.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,mCAAmC,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACtD,OAAwE,EACxE,OAAiB,EACjB,cAAkC;IAElC,MAAM,WAAW,GAAsD;QACtE,sBAAsB,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC;KAClE,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,oCAAoC,CAAC,EAAE,CAAC;IAC1E,CAAC;IAED,4FAA4F;IAC5F,2FAA2F;IAC3F,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC3E,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,OAAO,GAAG,CACf,cAA0B,EAC1B,IAAkC,EAClB,EAAE;QAClB,OAAO,mCAAmC,CAAC,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;YAC3E,eAAe,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,SAAS,GACd;QACC,MAAM;KACN,CAAC;IACH,IAAI,OAAO,CAAC,OAAO;QAAE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzD,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;QAAE,SAAS,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAEjE,OAAO,MAAM,4BAA4B,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AACxF,CAAC"}
|
||||
Generated
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
export declare function resolveChromiumCookiesDbLinux(options: {
|
||||
configDirName: string;
|
||||
profile?: string;
|
||||
}): string | null;
|
||||
//# sourceMappingURL=linuxPaths.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"linuxPaths.d.ts","sourceRoot":"","sources":["../../../src/providers/chromium/linuxPaths.ts"],"names":[],"mappings":"AAMA,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,GAAG,IAAI,CA0BhB"}
|
||||
Generated
Vendored
-33
@@ -1,33 +0,0 @@
|
||||
import { existsSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { expandPath, looksLikePath } from './paths.js';
|
||||
export function resolveChromiumCookiesDbLinux(options) {
|
||||
const home = homedir();
|
||||
// biome-ignore lint/complexity/useLiteralKeys: process.env is an index signature under strict TS.
|
||||
const configHome = process.env['XDG_CONFIG_HOME']?.trim() || path.join(home, '.config');
|
||||
const root = path.join(configHome, options.configDirName);
|
||||
if (options.profile && looksLikePath(options.profile)) {
|
||||
const candidate = expandPath(options.profile);
|
||||
if (candidate.endsWith('Cookies') && existsSync(candidate))
|
||||
return candidate;
|
||||
const direct = path.join(candidate, 'Cookies');
|
||||
if (existsSync(direct))
|
||||
return direct;
|
||||
const network = path.join(candidate, 'Network', 'Cookies');
|
||||
if (existsSync(network))
|
||||
return network;
|
||||
return null;
|
||||
}
|
||||
const profileDir = options.profile && options.profile.trim().length > 0 ? options.profile.trim() : 'Default';
|
||||
const candidates = [
|
||||
path.join(root, profileDir, 'Cookies'),
|
||||
path.join(root, profileDir, 'Network', 'Cookies'),
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (existsSync(candidate))
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//# sourceMappingURL=linuxPaths.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"linuxPaths.js","sourceRoot":"","sources":["../../../src/providers/chromium/linuxPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,UAAU,6BAA6B,CAAC,OAG7C;IACA,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,kGAAkG;IAClG,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACxF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1D,IAAI,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC;QACxC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GACf,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3F,MAAM,UAAU,GAAG;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;KACjD,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
|
||||
Generated
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
export declare function readKeychainGenericPassword(options: {
|
||||
account: string;
|
||||
service: string;
|
||||
timeoutMs: number;
|
||||
}): Promise<{
|
||||
ok: true;
|
||||
password: string;
|
||||
} | {
|
||||
ok: false;
|
||||
error: string;
|
||||
}>;
|
||||
export declare function readKeychainGenericPasswordFirst(options: {
|
||||
account: string;
|
||||
services: string[];
|
||||
timeoutMs: number;
|
||||
label: string;
|
||||
}): Promise<{
|
||||
ok: true;
|
||||
password: string;
|
||||
} | {
|
||||
ok: false;
|
||||
error: string;
|
||||
}>;
|
||||
//# sourceMappingURL=macosKeychain.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"macosKeychain.d.ts","sourceRoot":"","sources":["../../../src/providers/chromium/macosKeychain.ts"],"names":[],"mappings":"AAEA,wBAAsB,2BAA2B,CAAC,OAAO,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAczE;AAED,wBAAsB,gCAAgC,CAAC,OAAO,EAAE;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBzE"}
|
||||
Generated
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
import { execCapture } from '../../util/exec.js';
|
||||
export async function readKeychainGenericPassword(options) {
|
||||
const res = await execCapture('security', ['find-generic-password', '-w', '-a', options.account, '-s', options.service], { timeoutMs: options.timeoutMs });
|
||||
if (res.code === 0) {
|
||||
const password = res.stdout.trim();
|
||||
return { ok: true, password };
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
error: `${res.stderr.trim() || `exit ${res.code}`}`,
|
||||
};
|
||||
}
|
||||
export async function readKeychainGenericPasswordFirst(options) {
|
||||
let lastError = null;
|
||||
for (const service of options.services) {
|
||||
const r = await readKeychainGenericPassword({
|
||||
account: options.account,
|
||||
service,
|
||||
timeoutMs: options.timeoutMs,
|
||||
});
|
||||
if (r.ok)
|
||||
return r;
|
||||
lastError = r.error;
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
error: `Failed to read macOS Keychain (${options.label}): ${lastError ?? 'permission denied / keychain locked / entry missing.'}`,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=macosKeychain.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"macosKeychain.js","sourceRoot":"","sources":["../../../src/providers/chromium/macosKeychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,OAIjD;IACA,MAAM,GAAG,GAAG,MAAM,WAAW,CAC5B,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAC7E,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAChC,CAAC;IACF,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO;QACN,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,QAAQ,GAAG,CAAC,IAAI,EAAE,EAAE;KACnD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,OAKtD;IACA,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,MAAM,2BAA2B,CAAC;YAC3C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO;YACP,SAAS,EAAE,OAAO,CAAC,SAAS;SAC5B,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC;QACnB,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,OAAO;QACN,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,kCAAkC,OAAO,CAAC,KAAK,MAAM,SAAS,IAAI,sDAAsD,EAAE;KACjI,CAAC;AACH,CAAC"}
|
||||
Generated
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
export declare function looksLikePath(value: string): boolean;
|
||||
export declare function expandPath(input: string): string;
|
||||
export declare function safeStat(candidate: string): {
|
||||
isFile: () => boolean;
|
||||
isDirectory: () => boolean;
|
||||
} | null;
|
||||
export declare function resolveCookiesDbFromProfileOrRoots(options: {
|
||||
profile?: string;
|
||||
roots: string[];
|
||||
}): string | null;
|
||||
//# sourceMappingURL=paths.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/chromium/paths.ts"],"names":[],"mappings":"AAIA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,wBAAgB,QAAQ,CACvB,SAAS,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,MAAM,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,OAAO,CAAA;CAAE,GAAG,IAAI,CAM9D;AAED,wBAAgB,kCAAkC,CAAC,OAAO,EAAE;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,MAAM,GAAG,IAAI,CAuBhB"}
|
||||
Generated
Vendored
-43
@@ -1,43 +0,0 @@
|
||||
import { existsSync, statSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
export function looksLikePath(value) {
|
||||
return value.includes('/') || value.includes('\\');
|
||||
}
|
||||
export function expandPath(input) {
|
||||
if (input.startsWith('~/'))
|
||||
return path.join(homedir(), input.slice(2));
|
||||
return path.isAbsolute(input) ? input : path.resolve(process.cwd(), input);
|
||||
}
|
||||
export function safeStat(candidate) {
|
||||
try {
|
||||
return statSync(candidate);
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
export function resolveCookiesDbFromProfileOrRoots(options) {
|
||||
const candidates = [];
|
||||
if (options.profile && looksLikePath(options.profile)) {
|
||||
const expanded = expandPath(options.profile);
|
||||
const stat = safeStat(expanded);
|
||||
if (stat?.isFile())
|
||||
return expanded;
|
||||
candidates.push(path.join(expanded, 'Cookies'));
|
||||
candidates.push(path.join(expanded, 'Network', 'Cookies'));
|
||||
}
|
||||
else {
|
||||
const profileDir = options.profile && options.profile.trim().length > 0 ? options.profile.trim() : 'Default';
|
||||
for (const root of options.roots) {
|
||||
candidates.push(path.join(root, profileDir, 'Cookies'));
|
||||
candidates.push(path.join(root, profileDir, 'Network', 'Cookies'));
|
||||
}
|
||||
}
|
||||
for (const candidate of candidates) {
|
||||
if (existsSync(candidate))
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//# sourceMappingURL=paths.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/providers/chromium/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,aAAa,CAAC,KAAa;IAC1C,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACvC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,QAAQ,CACvB,SAAiB;IAEjB,IAAI,CAAC;QACJ,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,MAAM,UAAU,kCAAkC,CAAC,OAGlD;IACA,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,IAAI,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,IAAI,EAAE,MAAM,EAAE;YAAE,OAAO,QAAQ,CAAC;QACpC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QAChD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACP,MAAM,UAAU,GACf,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3F,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;YACxD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACpE,CAAC;IACF,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
|
||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
export declare function getWindowsChromiumMasterKey(userDataDir: string, label: string): Promise<{
|
||||
ok: true;
|
||||
value: Buffer;
|
||||
} | {
|
||||
ok: false;
|
||||
error: string;
|
||||
}>;
|
||||
//# sourceMappingURL=windowsMasterKey.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsMasterKey.d.ts","sourceRoot":"","sources":["../../../src/providers/chromium/windowsMasterKey.ts"],"names":[],"mappings":"AAKA,wBAAsB,2BAA2B,CAChD,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACX,OAAO,CACP;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B;IACA,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACb,CACH,CAsCA"}
|
||||
Generated
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { dpapiUnprotect } from '../chromeSqlite/windowsDpapi.js';
|
||||
export async function getWindowsChromiumMasterKey(userDataDir, label) {
|
||||
const localStatePath = path.join(userDataDir, 'Local State');
|
||||
if (!existsSync(localStatePath)) {
|
||||
return { ok: false, error: `${label} Local State file not found.` };
|
||||
}
|
||||
let encryptedKeyB64 = null;
|
||||
try {
|
||||
const raw = readFileSync(localStatePath, 'utf8');
|
||||
const parsed = JSON.parse(raw);
|
||||
encryptedKeyB64 =
|
||||
typeof parsed.os_crypt?.encrypted_key === 'string' ? parsed.os_crypt.encrypted_key : null;
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
ok: false,
|
||||
error: `Failed to parse ${label} Local State: ${error instanceof Error ? error.message : String(error)}`,
|
||||
};
|
||||
}
|
||||
if (!encryptedKeyB64)
|
||||
return { ok: false, error: `${label} Local State missing os_crypt.encrypted_key.` };
|
||||
let encryptedKey;
|
||||
try {
|
||||
encryptedKey = Buffer.from(encryptedKeyB64, 'base64');
|
||||
}
|
||||
catch {
|
||||
return { ok: false, error: `${label} Local State contains an invalid encrypted_key.` };
|
||||
}
|
||||
const prefix = Buffer.from('DPAPI', 'utf8');
|
||||
if (!encryptedKey.subarray(0, prefix.length).equals(prefix)) {
|
||||
return { ok: false, error: `${label} encrypted_key does not start with DPAPI prefix.` };
|
||||
}
|
||||
const unprotected = await dpapiUnprotect(encryptedKey.subarray(prefix.length));
|
||||
if (!unprotected.ok) {
|
||||
return { ok: false, error: `DPAPI decrypt failed: ${unprotected.error}` };
|
||||
}
|
||||
return { ok: true, value: unprotected.value };
|
||||
}
|
||||
//# sourceMappingURL=windowsMasterKey.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsMasterKey.js","sourceRoot":"","sources":["../../../src/providers/chromium/windowsMasterKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAChD,WAAmB,EACnB,KAAa;IAQb,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,8BAA8B,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA+C,CAAC;QAC7E,eAAe;YACd,OAAO,MAAM,CAAC,QAAQ,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO;YACN,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,mBAAmB,KAAK,iBAAiB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACxG,CAAC;IACH,CAAC;IAED,IAAI,CAAC,eAAe;QACnB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,8CAA8C,EAAE,CAAC;IAErF,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACJ,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,iDAAiD,EAAE,CAAC;IACxF,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,kDAAkD,EAAE,CAAC;IACzF,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;AAC/C,CAAC"}
|
||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
export declare function resolveChromiumPathsWindows(options: {
|
||||
localAppDataVendorPath: string;
|
||||
profile?: string;
|
||||
}): {
|
||||
dbPath: string | null;
|
||||
userDataDir: string | null;
|
||||
};
|
||||
//# sourceMappingURL=windowsPaths.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsPaths.d.ts","sourceRoot":"","sources":["../../../src/providers/chromium/windowsPaths.ts"],"names":[],"mappings":"AAKA,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACpD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAmCxD"}
|
||||
Generated
Vendored
-53
@@ -1,53 +0,0 @@
|
||||
import { existsSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { expandPath, looksLikePath } from './paths.js';
|
||||
export function resolveChromiumPathsWindows(options) {
|
||||
// biome-ignore lint/complexity/useLiteralKeys: process.env is an index signature under strict TS.
|
||||
const localAppData = process.env['LOCALAPPDATA'];
|
||||
const root = localAppData ? path.join(localAppData, options.localAppDataVendorPath) : null;
|
||||
if (options.profile && looksLikePath(options.profile)) {
|
||||
const expanded = expandPath(options.profile);
|
||||
const candidates = expanded.endsWith('Cookies')
|
||||
? [expanded]
|
||||
: [
|
||||
path.join(expanded, 'Network', 'Cookies'),
|
||||
path.join(expanded, 'Cookies'),
|
||||
path.join(expanded, 'Default', 'Network', 'Cookies'),
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (!existsSync(candidate))
|
||||
continue;
|
||||
const userDataDir = findUserDataDir(candidate);
|
||||
return { dbPath: candidate, userDataDir };
|
||||
}
|
||||
if (existsSync(path.join(expanded, 'Local State'))) {
|
||||
return { dbPath: null, userDataDir: expanded };
|
||||
}
|
||||
}
|
||||
const profileDir = options.profile && options.profile.trim().length > 0 ? options.profile.trim() : 'Default';
|
||||
if (!root)
|
||||
return { dbPath: null, userDataDir: null };
|
||||
const candidates = [
|
||||
path.join(root, profileDir, 'Network', 'Cookies'),
|
||||
path.join(root, profileDir, 'Cookies'),
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (existsSync(candidate))
|
||||
return { dbPath: candidate, userDataDir: root };
|
||||
}
|
||||
return { dbPath: null, userDataDir: root };
|
||||
}
|
||||
function findUserDataDir(cookiesDbPath) {
|
||||
let current = path.dirname(cookiesDbPath);
|
||||
for (let i = 0; i < 6; i += 1) {
|
||||
const localState = path.join(current, 'Local State');
|
||||
if (existsSync(localState))
|
||||
return current;
|
||||
const next = path.dirname(current);
|
||||
if (next === current)
|
||||
break;
|
||||
current = next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//# sourceMappingURL=windowsPaths.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"windowsPaths.js","sourceRoot":"","sources":["../../../src/providers/chromium/windowsPaths.ts"],"names":[],"mappings":"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"}
|
||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromEdge(options: {
|
||||
profile?: string;
|
||||
timeoutMs?: number;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=edge.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../../src/providers/edge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK5D,wBAAsB,kBAAkB,CACvC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC5F,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
|
||||
Generated
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
import { getCookiesFromEdgeSqliteLinux } from './edgeSqliteLinux.js';
|
||||
import { getCookiesFromEdgeSqliteMac } from './edgeSqliteMac.js';
|
||||
import { getCookiesFromEdgeSqliteWindows } from './edgeSqliteWindows.js';
|
||||
export async function getCookiesFromEdge(options, origins, allowlistNames) {
|
||||
const warnings = [];
|
||||
// Platform dispatch only. All real logic lives in the per-OS providers.
|
||||
if (process.platform === 'darwin') {
|
||||
const r = await getCookiesFromEdgeSqliteMac(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
if (process.platform === 'linux') {
|
||||
const r = await getCookiesFromEdgeSqliteLinux(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
const r = await getCookiesFromEdgeSqliteWindows(options, origins, allowlistNames);
|
||||
warnings.push(...r.warnings);
|
||||
const cookies = r.cookies;
|
||||
return { cookies, warnings };
|
||||
}
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
//# sourceMappingURL=edge.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edge.js","sourceRoot":"","sources":["../../src/providers/edge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,OAA4F,EAC5F,OAAiB,EACjB,cAAkC;IAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,wEAAwE;IACxE,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,MAAM,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAC9E,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,6BAA6B,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAChF,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,+BAA+B,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAClF,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAa,CAAC,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;AAClC,CAAC"}
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromEdgeSqliteLinux(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=edgeSqliteLinux.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteLinux.d.ts","sourceRoot":"","sources":["../../src/providers/edgeSqliteLinux.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASpD,wBAAsB,6BAA6B,CAClD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxE,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAoD3B"}
|
||||
scripts/lib/vendor/bird-search/node_modules/@steipete/sweet-cookie/dist/providers/edgeSqliteLinux.js
Generated
Vendored
-53
@@ -1,53 +0,0 @@
|
||||
import { decryptChromiumAes128CbcCookieValue, deriveAes128CbcKeyFromPassword, } from './chromeSqlite/crypto.js';
|
||||
import { getLinuxChromiumSafeStoragePassword } from './chromeSqlite/linuxKeyring.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { resolveChromiumCookiesDbLinux } from './chromium/linuxPaths.js';
|
||||
export async function getCookiesFromEdgeSqliteLinux(options, origins, allowlistNames) {
|
||||
const args = {
|
||||
configDirName: 'microsoft-edge',
|
||||
};
|
||||
if (options.profile !== undefined)
|
||||
args.profile = options.profile;
|
||||
const dbPath = resolveChromiumCookiesDbLinux(args);
|
||||
if (!dbPath) {
|
||||
return { cookies: [], warnings: ['Edge cookies database not found.'] };
|
||||
}
|
||||
const { password, warnings: keyringWarnings } = await getLinuxChromiumSafeStoragePassword({
|
||||
app: 'edge',
|
||||
});
|
||||
// Linux uses multiple schemes depending on distro/keyring availability.
|
||||
// - v10 often uses the hard-coded "peanuts" password
|
||||
// - v11 uses "<browser> Safe Storage" from the keyring (may be empty/unavailable)
|
||||
const v10Key = deriveAes128CbcKeyFromPassword('peanuts', { iterations: 1 });
|
||||
const emptyKey = deriveAes128CbcKeyFromPassword('', { iterations: 1 });
|
||||
const v11Key = deriveAes128CbcKeyFromPassword(password, { iterations: 1 });
|
||||
const decrypt = (encryptedValue, opts) => {
|
||||
const prefix = Buffer.from(encryptedValue).subarray(0, 3).toString('utf8');
|
||||
if (prefix === 'v10') {
|
||||
return decryptChromiumAes128CbcCookieValue(encryptedValue, [v10Key, emptyKey], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: false,
|
||||
});
|
||||
}
|
||||
if (prefix === 'v11') {
|
||||
return decryptChromiumAes128CbcCookieValue(encryptedValue, [v11Key, emptyKey], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: false,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
const result = await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
result.warnings.unshift(...keyringWarnings);
|
||||
return result;
|
||||
}
|
||||
//# sourceMappingURL=edgeSqliteLinux.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteLinux.js","sourceRoot":"","sources":["../../src/providers/edgeSqliteLinux.ts"],"names":[],"mappings":"AACA,OAAO,EACN,mCAAmC,EACnC,8BAA8B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mCAAmC,EAAE,MAAM,gCAAgC,CAAC;AACrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAClD,OAAwE,EACxE,OAAiB,EACjB,cAAkC;IAElC,MAAM,IAAI,GAAwD;QACjE,aAAa,EAAE,gBAAgB;KAC/B,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAClE,MAAM,MAAM,GAAG,6BAA6B,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,kCAAkC,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,mCAAmC,CAAC;QACzF,GAAG,EAAE,MAAM;KACX,CAAC,CAAC;IAEH,wEAAwE;IACxE,qDAAqD;IACrD,kFAAkF;IAClF,MAAM,MAAM,GAAG,8BAA8B,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,8BAA8B,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,8BAA8B,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAE3E,MAAM,OAAO,GAAG,CACf,cAA0B,EAC1B,IAAkC,EAClB,EAAE;QAClB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3E,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO,mCAAmC,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;gBAC9E,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,6BAA6B,EAAE,KAAK;aACpC,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO,mCAAmC,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;gBAC9E,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,6BAA6B,EAAE,KAAK;aACpC,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,SAAS,GACd;QACC,MAAM;KACN,CAAC;IACH,IAAI,OAAO,CAAC,OAAO;QAAE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzD,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;QAAE,SAAS,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAEjE,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAC/F,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AACf,CAAC"}
|
||||
scripts/lib/vendor/bird-search/node_modules/@steipete/sweet-cookie/dist/providers/edgeSqliteMac.d.ts
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromEdgeSqliteMac(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
timeoutMs?: number;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=edgeSqliteMac.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteMac.d.ts","sourceRoot":"","sources":["../../src/providers/edgeSqliteMac.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASpD,wBAAsB,2BAA2B,CAChD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5F,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA8C3B"}
|
||||
Generated
Vendored
-60
@@ -1,60 +0,0 @@
|
||||
import { homedir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { decryptChromiumAes128CbcCookieValue, deriveAes128CbcKeyFromPassword, } from './chromeSqlite/crypto.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { readKeychainGenericPasswordFirst } from './chromium/macosKeychain.js';
|
||||
import { resolveCookiesDbFromProfileOrRoots } from './chromium/paths.js';
|
||||
export async function getCookiesFromEdgeSqliteMac(options, origins, allowlistNames) {
|
||||
const dbPath = resolveEdgeCookiesDb(options.profile);
|
||||
if (!dbPath) {
|
||||
return { cookies: [], warnings: ['Edge cookies database not found.'] };
|
||||
}
|
||||
const warnings = [];
|
||||
// On macOS, Edge stores its "Safe Storage" secret in Keychain (same scheme as Chrome).
|
||||
// `security find-generic-password` is stable and avoids any native Node keychain modules.
|
||||
const passwordResult = await readKeychainGenericPasswordFirst({
|
||||
account: 'Microsoft Edge',
|
||||
services: ['Microsoft Edge Safe Storage', 'Microsoft Edge'],
|
||||
timeoutMs: options.timeoutMs ?? 3_000,
|
||||
label: 'Microsoft Edge Safe Storage',
|
||||
});
|
||||
if (!passwordResult.ok) {
|
||||
warnings.push(passwordResult.error);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const edgePassword = passwordResult.password.trim();
|
||||
if (!edgePassword) {
|
||||
warnings.push('macOS Keychain returned an empty Microsoft Edge Safe Storage password.');
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
// Chromium uses PBKDF2(password, "saltysalt", 1003, 16, sha1) for AES-128-CBC cookie values on macOS.
|
||||
const key = deriveAes128CbcKeyFromPassword(edgePassword, { iterations: 1003 });
|
||||
const decrypt = (encryptedValue, opts) => decryptChromiumAes128CbcCookieValue(encryptedValue, [key], {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
treatUnknownPrefixAsPlaintext: true,
|
||||
});
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
const result = await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
result.warnings.unshift(...warnings);
|
||||
return result;
|
||||
}
|
||||
function resolveEdgeCookiesDb(profile) {
|
||||
const home = homedir();
|
||||
/* c8 ignore next */
|
||||
const roots = process.platform === 'darwin'
|
||||
? [path.join(home, 'Library', 'Application Support', 'Microsoft Edge')]
|
||||
: [];
|
||||
const args = { roots };
|
||||
if (profile !== undefined)
|
||||
args.profile = profile;
|
||||
return resolveCookiesDbFromProfileOrRoots(args);
|
||||
}
|
||||
//# sourceMappingURL=edgeSqliteMac.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteMac.js","sourceRoot":"","sources":["../../src/providers/edgeSqliteMac.ts"],"names":[],"mappings":"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"}
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromEdgeSqliteWindows(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
debug?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=edgeSqliteWindows.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteWindows.d.ts","sourceRoot":"","sources":["../../src/providers/edgeSqliteWindows.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,wBAAsB,+BAA+B,CACpD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACxE,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAmC3B"}
|
||||
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
||||
import path from 'node:path';
|
||||
import { decryptChromiumAes256GcmCookieValue } from './chromeSqlite/crypto.js';
|
||||
import { getCookiesFromChromeSqliteDb } from './chromeSqlite/shared.js';
|
||||
import { getWindowsChromiumMasterKey } from './chromium/windowsMasterKey.js';
|
||||
import { resolveChromiumPathsWindows } from './chromium/windowsPaths.js';
|
||||
export async function getCookiesFromEdgeSqliteWindows(options, origins, allowlistNames) {
|
||||
const resolveArgs = {
|
||||
localAppDataVendorPath: path.join('Microsoft', 'Edge', 'User Data'),
|
||||
};
|
||||
if (options.profile !== undefined)
|
||||
resolveArgs.profile = options.profile;
|
||||
const { dbPath, userDataDir } = resolveChromiumPathsWindows(resolveArgs);
|
||||
if (!dbPath || !userDataDir) {
|
||||
return { cookies: [], warnings: ['Edge cookies database not found.'] };
|
||||
}
|
||||
// On Windows, Edge stores an AES key in `Local State` encrypted with DPAPI (CurrentUser).
|
||||
// That master key is then used for AES-256-GCM cookie values (`v10`/`v11`/`v20` prefixes).
|
||||
const masterKey = await getWindowsChromiumMasterKey(userDataDir, 'Edge');
|
||||
if (!masterKey.ok) {
|
||||
return { cookies: [], warnings: [masterKey.error] };
|
||||
}
|
||||
const decrypt = (encryptedValue, opts) => {
|
||||
return decryptChromiumAes256GcmCookieValue(encryptedValue, masterKey.value, {
|
||||
stripHashPrefix: opts.stripHashPrefix,
|
||||
});
|
||||
};
|
||||
const dbOptions = {
|
||||
dbPath,
|
||||
};
|
||||
if (options.profile)
|
||||
dbOptions.profile = options.profile;
|
||||
if (options.includeExpired !== undefined)
|
||||
dbOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
dbOptions.debug = options.debug;
|
||||
return await getCookiesFromChromeSqliteDb(dbOptions, origins, allowlistNames, decrypt);
|
||||
}
|
||||
//# sourceMappingURL=edgeSqliteWindows.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"edgeSqliteWindows.js","sourceRoot":"","sources":["../../src/providers/edgeSqliteWindows.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,mCAAmC,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACpD,OAAwE,EACxE,OAAiB,EACjB,cAAkC;IAElC,MAAM,WAAW,GAAsD;QACtE,sBAAsB,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC;KACnE,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,kCAAkC,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,0FAA0F;IAC1F,2FAA2F;IAC3F,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,OAAO,GAAG,CACf,cAA0B,EAC1B,IAAkC,EAClB,EAAE;QAClB,OAAO,mCAAmC,CAAC,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;YAC3E,eAAe,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,SAAS,GACd;QACC,MAAM;KACN,CAAC;IACH,IAAI,OAAO,CAAC,OAAO;QAAE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACzD,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;QAAE,SAAS,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAEjE,OAAO,MAAM,4BAA4B,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AACxF,CAAC"}
|
||||
scripts/lib/vendor/bird-search/node_modules/@steipete/sweet-cookie/dist/providers/firefoxSqlite.d.ts
Generated
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromFirefox(options: {
|
||||
profile?: string;
|
||||
includeExpired?: boolean;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=firefoxSqlite.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"firefoxSqlite.d.ts","sourceRoot":"","sources":["../../src/providers/firefoxSqlite.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA0B,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK5E,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,EACvD,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAmD3B"}
|
||||
Generated
Vendored
-257
@@ -1,257 +0,0 @@
|
||||
import { copyFileSync, existsSync, mkdtempSync, readdirSync, rmSync } from 'node:fs';
|
||||
import { homedir, tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { hostMatchesCookieDomain } from '../util/hostMatch.js';
|
||||
import { importNodeSqlite } from '../util/nodeSqlite.js';
|
||||
import { isBunRuntime } from '../util/runtime.js';
|
||||
export async function getCookiesFromFirefox(options, origins, allowlistNames) {
|
||||
const warnings = [];
|
||||
const dbPath = resolveFirefoxCookiesDb(options.profile);
|
||||
if (!dbPath) {
|
||||
warnings.push('Firefox cookies database not found.');
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const tempDir = mkdtempSync(path.join(tmpdir(), 'sweet-cookie-firefox-'));
|
||||
const tempDbPath = path.join(tempDir, 'cookies.sqlite');
|
||||
try {
|
||||
copyFileSync(dbPath, tempDbPath);
|
||||
copySidecar(dbPath, `${tempDbPath}-wal`, '-wal');
|
||||
copySidecar(dbPath, `${tempDbPath}-shm`, '-shm');
|
||||
}
|
||||
catch (error) {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
warnings.push(`Failed to copy Firefox cookie DB: ${error instanceof Error ? error.message : String(error)}`);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const hosts = origins.map((o) => new URL(o).hostname);
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const where = buildHostWhereClause(hosts);
|
||||
const expiryClause = options.includeExpired ? '' : ` AND (expiry = 0 OR expiry > ${now})`;
|
||||
const sql = `SELECT name, value, host, path, expiry, isSecure, isHttpOnly, sameSite ` +
|
||||
`FROM moz_cookies WHERE (${where})${expiryClause} ORDER BY expiry DESC;`;
|
||||
try {
|
||||
if (isBunRuntime()) {
|
||||
const bunResult = await queryFirefoxCookiesWithBunSqlite(tempDbPath, sql);
|
||||
if (!bunResult.ok) {
|
||||
warnings.push(`bun:sqlite failed reading Firefox cookies: ${bunResult.error}`);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const cookies = collectFirefoxCookiesFromRows(bunResult.rows, options, hosts, allowlistNames);
|
||||
return { cookies: dedupeCookies(cookies), warnings };
|
||||
}
|
||||
const nodeResult = await queryFirefoxCookiesWithNodeSqlite(tempDbPath, sql);
|
||||
if (!nodeResult.ok) {
|
||||
warnings.push(`node:sqlite failed reading Firefox cookies: ${nodeResult.error}`);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const cookies = collectFirefoxCookiesFromRows(nodeResult.rows, options, hosts, allowlistNames);
|
||||
return { cookies: dedupeCookies(cookies), warnings };
|
||||
}
|
||||
finally {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
async function queryFirefoxCookiesWithNodeSqlite(dbPath, sql) {
|
||||
try {
|
||||
const { DatabaseSync } = await importNodeSqlite();
|
||||
const db = new DatabaseSync(dbPath, { readOnly: true });
|
||||
try {
|
||||
const rows = db.prepare(sql).all();
|
||||
return { ok: true, rows };
|
||||
}
|
||||
finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
async function queryFirefoxCookiesWithBunSqlite(dbPath, sql) {
|
||||
try {
|
||||
const { Database } = await import('bun:sqlite');
|
||||
const db = new Database(dbPath, { readonly: true });
|
||||
try {
|
||||
const rows = db.query(sql).all();
|
||||
return { ok: true, rows };
|
||||
}
|
||||
finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
function collectFirefoxCookiesFromRows(rows, options, hosts, allowlistNames) {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const cookies = [];
|
||||
for (const row of rows) {
|
||||
const name = typeof row.name === 'string' ? row.name : null;
|
||||
const value = typeof row.value === 'string' ? row.value : null;
|
||||
const host = typeof row.host === 'string' ? row.host : null;
|
||||
const cookiePath = typeof row.path === 'string' ? row.path : '';
|
||||
if (!name || value === null || !host)
|
||||
continue;
|
||||
if (allowlistNames && allowlistNames.size > 0 && !allowlistNames.has(name))
|
||||
continue;
|
||||
if (!hostMatchesAny(hosts, host))
|
||||
continue;
|
||||
const expiryText = typeof row.expiry === 'number'
|
||||
? String(row.expiry)
|
||||
: typeof row.expiry === 'string'
|
||||
? row.expiry
|
||||
: undefined;
|
||||
const expires = normalizeFirefoxExpiry(expiryText);
|
||||
if (!options.includeExpired && expires && expires < now)
|
||||
continue;
|
||||
const isSecure = row.isSecure === 1 || row.isSecure === '1' || row.isSecure === true;
|
||||
const isHttpOnly = row.isHttpOnly === 1 || row.isHttpOnly === '1' || row.isHttpOnly === true;
|
||||
const cookie = {
|
||||
name,
|
||||
value,
|
||||
domain: host.startsWith('.') ? host.slice(1) : host,
|
||||
path: cookiePath || '/',
|
||||
secure: isSecure,
|
||||
httpOnly: isHttpOnly,
|
||||
};
|
||||
if (expires !== undefined)
|
||||
cookie.expires = expires;
|
||||
const normalizedSameSite = normalizeFirefoxSameSite(typeof row.sameSite === 'number'
|
||||
? String(row.sameSite)
|
||||
: typeof row.sameSite === 'string'
|
||||
? row.sameSite
|
||||
: undefined);
|
||||
if (normalizedSameSite !== undefined)
|
||||
cookie.sameSite = normalizedSameSite;
|
||||
const source = { browser: 'firefox' };
|
||||
if (options.profile)
|
||||
source.profile = options.profile;
|
||||
cookie.source = source;
|
||||
cookies.push(cookie);
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
function resolveFirefoxCookiesDb(profile) {
|
||||
const home = homedir();
|
||||
// biome-ignore lint/complexity/useLiteralKeys: process.env is an index signature under strict TS.
|
||||
const appData = process.env['APPDATA'];
|
||||
/* c8 ignore next 10 */
|
||||
const roots = process.platform === 'darwin'
|
||||
? [path.join(home, 'Library', 'Application Support', 'Firefox', 'Profiles')]
|
||||
: process.platform === 'linux'
|
||||
? [path.join(home, '.mozilla', 'firefox')]
|
||||
: process.platform === 'win32'
|
||||
? appData
|
||||
? [path.join(appData, 'Mozilla', 'Firefox', 'Profiles')]
|
||||
: []
|
||||
: [];
|
||||
if (profile && looksLikePath(profile)) {
|
||||
const candidate = profile.endsWith('cookies.sqlite')
|
||||
? profile
|
||||
: path.join(profile, 'cookies.sqlite');
|
||||
return existsSync(candidate) ? candidate : null;
|
||||
}
|
||||
for (const root of roots) {
|
||||
if (!root || !existsSync(root))
|
||||
continue;
|
||||
if (profile) {
|
||||
const candidate = path.join(root, profile, 'cookies.sqlite');
|
||||
if (existsSync(candidate))
|
||||
return candidate;
|
||||
continue;
|
||||
}
|
||||
const entries = safeReaddir(root);
|
||||
const defaultRelease = entries.find((e) => e.includes('default-release'));
|
||||
const picked = defaultRelease ?? entries[0];
|
||||
if (!picked)
|
||||
continue;
|
||||
const candidate = path.join(root, picked, 'cookies.sqlite');
|
||||
if (existsSync(candidate))
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function safeReaddir(dir) {
|
||||
try {
|
||||
return readdirSync(dir, { withFileTypes: true })
|
||||
.filter((e) => e.isDirectory())
|
||||
.map((e) => e.name);
|
||||
}
|
||||
catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
function looksLikePath(value) {
|
||||
return value.includes('/') || value.includes('\\');
|
||||
}
|
||||
function copySidecar(sourceDbPath, target, suffix) {
|
||||
const sidecar = `${sourceDbPath}${suffix}`;
|
||||
if (!existsSync(sidecar))
|
||||
return;
|
||||
try {
|
||||
copyFileSync(sidecar, target);
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
function buildHostWhereClause(hosts) {
|
||||
const clauses = [];
|
||||
for (const host of hosts) {
|
||||
const escaped = sqlLiteral(host);
|
||||
const escapedDot = sqlLiteral(`.${host}`);
|
||||
const escapedLike = sqlLiteral(`%.${host}`);
|
||||
clauses.push(`host = ${escaped}`);
|
||||
clauses.push(`host = ${escapedDot}`);
|
||||
clauses.push(`host LIKE ${escapedLike}`);
|
||||
}
|
||||
return clauses.length ? clauses.join(' OR ') : '1=0';
|
||||
}
|
||||
function sqlLiteral(value) {
|
||||
const escaped = value.replaceAll("'", "''");
|
||||
return `'${escaped}'`;
|
||||
}
|
||||
function normalizeFirefoxExpiry(expiry) {
|
||||
if (!expiry)
|
||||
return undefined;
|
||||
const value = Number.parseInt(expiry, 10);
|
||||
if (!Number.isFinite(value) || value <= 0)
|
||||
return undefined;
|
||||
return value;
|
||||
}
|
||||
function normalizeFirefoxSameSite(raw) {
|
||||
if (!raw)
|
||||
return undefined;
|
||||
const value = Number.parseInt(raw, 10);
|
||||
if (Number.isFinite(value)) {
|
||||
if (value === 2)
|
||||
return 'Strict';
|
||||
if (value === 1)
|
||||
return 'Lax';
|
||||
if (value === 0)
|
||||
return 'None';
|
||||
}
|
||||
const normalized = raw.toLowerCase();
|
||||
if (normalized === 'strict')
|
||||
return 'Strict';
|
||||
if (normalized === 'lax')
|
||||
return 'Lax';
|
||||
if (normalized === 'none')
|
||||
return 'None';
|
||||
return undefined;
|
||||
}
|
||||
function hostMatchesAny(hosts, cookieHost) {
|
||||
const cookieDomain = cookieHost.startsWith('.') ? cookieHost.slice(1) : cookieHost;
|
||||
return hosts.some((host) => hostMatchesCookieDomain(host, cookieDomain));
|
||||
}
|
||||
function dedupeCookies(cookies) {
|
||||
const merged = new Map();
|
||||
for (const cookie of cookies) {
|
||||
const key = `${cookie.name}|${cookie.domain ?? ''}|${cookie.path ?? ''}`;
|
||||
if (!merged.has(key))
|
||||
merged.set(key, cookie);
|
||||
}
|
||||
return Array.from(merged.values());
|
||||
}
|
||||
//# sourceMappingURL=firefoxSqlite.js.map
|
||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
type InlineSource = {
|
||||
source: string;
|
||||
payload: string;
|
||||
};
|
||||
export declare function getCookiesFromInline(inline: InlineSource, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
export {};
|
||||
//# sourceMappingURL=inline.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../../src/providers/inline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK5D,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAkC3B"}
|
||||
Generated
Vendored
-71
@@ -1,71 +0,0 @@
|
||||
import { tryDecodeBase64Json } from '../util/base64.js';
|
||||
import { readTextFileIfExists } from '../util/fs.js';
|
||||
import { hostMatchesCookieDomain } from '../util/hostMatch.js';
|
||||
export async function getCookiesFromInline(inline, origins, allowlistNames) {
|
||||
const warnings = [];
|
||||
// Inline sources can be:
|
||||
// - the payload itself (JSON or base64)
|
||||
// - a file path that contains JSON/base64
|
||||
//
|
||||
// We do a small heuristic: treat `*.json`/`*.base64` and explicit "file" sources as file paths first.
|
||||
const rawPayload = inline.source.endsWith('file') ||
|
||||
inline.payload.endsWith('.json') ||
|
||||
inline.payload.endsWith('.base64')
|
||||
? ((await readTextFileIfExists(inline.payload)) ?? inline.payload)
|
||||
: inline.payload;
|
||||
// If it looks like base64, decode it to JSON. Otherwise use it as-is.
|
||||
const decoded = tryDecodeBase64Json(rawPayload) ?? rawPayload;
|
||||
const parsed = tryParseCookiePayload(decoded);
|
||||
if (!parsed) {
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const hostAllow = new Set(origins.map((o) => new URL(o).hostname));
|
||||
const cookies = [];
|
||||
for (const cookie of parsed.cookies) {
|
||||
if (!cookie?.name)
|
||||
continue;
|
||||
if (allowlistNames && allowlistNames.size > 0 && !allowlistNames.has(cookie.name))
|
||||
continue;
|
||||
const domain = cookie.domain ?? (cookie.url ? safeHostnameFromUrl(cookie.url) : undefined);
|
||||
if (domain && hostAllow.size > 0 && !matchesAnyHost(hostAllow, domain))
|
||||
continue;
|
||||
cookies.push(cookie);
|
||||
}
|
||||
return { cookies, warnings };
|
||||
}
|
||||
function tryParseCookiePayload(input) {
|
||||
const trimmed = input.trim();
|
||||
if (!trimmed)
|
||||
return null;
|
||||
try {
|
||||
const parsed = JSON.parse(trimmed);
|
||||
if (Array.isArray(parsed)) {
|
||||
return { cookies: parsed };
|
||||
}
|
||||
if (parsed &&
|
||||
typeof parsed === 'object' &&
|
||||
Array.isArray(parsed.cookies)) {
|
||||
return { cookies: parsed.cookies };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function matchesAnyHost(hosts, cookieDomain) {
|
||||
for (const host of hosts) {
|
||||
if (hostMatchesCookieDomain(host, cookieDomain))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function safeHostnameFromUrl(url) {
|
||||
try {
|
||||
return new URL(url).hostname;
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=inline.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/providers/inline.ts"],"names":[],"mappings":"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"}
|
||||
Generated
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
import type { GetCookiesResult } from '../types.js';
|
||||
export declare function getCookiesFromSafari(options: {
|
||||
includeExpired?: boolean;
|
||||
file?: string;
|
||||
}, origins: string[], allowlistNames: Set<string> | null): Promise<GetCookiesResult>;
|
||||
//# sourceMappingURL=safariBinaryCookies.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"safariBinaryCookies.d.ts","sourceRoot":"","sources":["../../src/providers/safariBinaryCookies.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAU,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK5D,wBAAsB,oBAAoB,CACzC,OAAO,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACpD,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAqC3B"}
|
||||
Generated
Vendored
-173
@@ -1,173 +0,0 @@
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { hostMatchesCookieDomain } from '../util/hostMatch.js';
|
||||
const MAC_EPOCH_DELTA_SECONDS = 978_307_200;
|
||||
export async function getCookiesFromSafari(options, origins, allowlistNames) {
|
||||
const warnings = [];
|
||||
if (process.platform !== 'darwin') {
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const cookieFile = options.file ?? resolveSafariBinaryCookiesPath();
|
||||
if (!cookieFile) {
|
||||
warnings.push('Safari Cookies.binarycookies not found.');
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
const hosts = origins.map((o) => new URL(o).hostname);
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
try {
|
||||
const data = readFileSync(cookieFile);
|
||||
// Safari's `Cookies.binarycookies` is a small binary container with multiple "pages".
|
||||
// We decode only the fields we need (name/value/domain/path/flags/expiry).
|
||||
const parsed = decodeBinaryCookies(data);
|
||||
const cookies = [];
|
||||
for (const cookie of parsed) {
|
||||
if (!cookie.name)
|
||||
continue;
|
||||
if (allowlistNames && allowlistNames.size > 0 && !allowlistNames.has(cookie.name))
|
||||
continue;
|
||||
const domain = cookie.domain;
|
||||
if (!domain)
|
||||
continue;
|
||||
if (!hosts.some((h) => hostMatchesCookieDomain(h, domain)))
|
||||
continue;
|
||||
if (!options.includeExpired && cookie.expires && cookie.expires < now)
|
||||
continue;
|
||||
cookies.push(cookie);
|
||||
}
|
||||
return { cookies: dedupeCookies(cookies), warnings };
|
||||
}
|
||||
catch (error) {
|
||||
warnings.push(`Failed to read Safari cookies: ${error instanceof Error ? error.message : String(error)}`);
|
||||
return { cookies: [], warnings };
|
||||
}
|
||||
}
|
||||
function resolveSafariBinaryCookiesPath() {
|
||||
const home = homedir();
|
||||
const candidates = [
|
||||
path.join(home, 'Library', 'Cookies', 'Cookies.binarycookies'),
|
||||
path.join(home, 'Library', 'Containers', 'com.apple.Safari', 'Data', 'Library', 'Cookies', 'Cookies.binarycookies'),
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (existsSync(candidate))
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function decodeBinaryCookies(buffer) {
|
||||
if (buffer.length < 8)
|
||||
return [];
|
||||
if (buffer.subarray(0, 4).toString('utf8') !== 'cook')
|
||||
return [];
|
||||
const pageCount = buffer.readUInt32BE(4);
|
||||
let cursor = 8;
|
||||
const pageSizes = [];
|
||||
for (let i = 0; i < pageCount; i += 1) {
|
||||
pageSizes.push(buffer.readUInt32BE(cursor));
|
||||
cursor += 4;
|
||||
}
|
||||
const cookies = [];
|
||||
for (const pageSize of pageSizes) {
|
||||
const page = buffer.subarray(cursor, cursor + pageSize);
|
||||
cursor += pageSize;
|
||||
cookies.push(...decodePage(page));
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
function decodePage(page) {
|
||||
if (page.length < 16)
|
||||
return [];
|
||||
const header = page.readUInt32BE(0);
|
||||
if (header !== 0x00000100)
|
||||
return [];
|
||||
const cookieCount = page.readUInt32LE(4);
|
||||
const offsets = [];
|
||||
let cursor = 8;
|
||||
for (let i = 0; i < cookieCount; i += 1) {
|
||||
offsets.push(page.readUInt32LE(cursor));
|
||||
cursor += 4;
|
||||
}
|
||||
const cookies = [];
|
||||
for (const offset of offsets) {
|
||||
const cookie = decodeCookie(page.subarray(offset));
|
||||
if (cookie)
|
||||
cookies.push(cookie);
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
function decodeCookie(cookieBuffer) {
|
||||
if (cookieBuffer.length < 48)
|
||||
return null;
|
||||
const size = cookieBuffer.readUInt32LE(0);
|
||||
if (size < 48 || size > cookieBuffer.length)
|
||||
return null;
|
||||
const flagsValue = cookieBuffer.readUInt32LE(8);
|
||||
const isSecure = (flagsValue & 1) !== 0;
|
||||
const isHttpOnly = (flagsValue & 4) !== 0;
|
||||
const urlOffset = cookieBuffer.readUInt32LE(16);
|
||||
const nameOffset = cookieBuffer.readUInt32LE(20);
|
||||
const pathOffset = cookieBuffer.readUInt32LE(24);
|
||||
const valueOffset = cookieBuffer.readUInt32LE(28);
|
||||
// Safari stores dates as "Mac absolute time" (seconds since 2001-01-01).
|
||||
const expiration = readDoubleLE(cookieBuffer, 40);
|
||||
const rawUrl = readCString(cookieBuffer, urlOffset, size);
|
||||
const name = readCString(cookieBuffer, nameOffset, size);
|
||||
const cookiePath = readCString(cookieBuffer, pathOffset, size) ?? '/';
|
||||
const value = readCString(cookieBuffer, valueOffset, size) ?? '';
|
||||
if (!name)
|
||||
return null;
|
||||
const domain = rawUrl ? safeHostnameFromUrl(rawUrl) : undefined;
|
||||
const expires = expiration && expiration > 0 ? Math.round(expiration + MAC_EPOCH_DELTA_SECONDS) : undefined;
|
||||
const decoded = {
|
||||
name,
|
||||
value,
|
||||
path: cookiePath,
|
||||
secure: isSecure,
|
||||
httpOnly: isHttpOnly,
|
||||
source: { browser: 'safari' },
|
||||
};
|
||||
if (domain)
|
||||
decoded.domain = domain;
|
||||
if (expires !== undefined)
|
||||
decoded.expires = expires;
|
||||
return decoded;
|
||||
}
|
||||
function readDoubleLE(buffer, offset) {
|
||||
if (offset + 8 > buffer.length)
|
||||
return 0;
|
||||
const slice = buffer.subarray(offset, offset + 8);
|
||||
return slice.readDoubleLE(0);
|
||||
}
|
||||
function readCString(buffer, offset, end) {
|
||||
if (offset <= 0 || offset >= end)
|
||||
return null;
|
||||
let cursor = offset;
|
||||
while (cursor < end && buffer[cursor] !== 0)
|
||||
cursor += 1;
|
||||
if (cursor >= end)
|
||||
return null;
|
||||
return buffer.toString('utf8', offset, cursor);
|
||||
}
|
||||
function safeHostnameFromUrl(raw) {
|
||||
try {
|
||||
const url = raw.includes('://') ? raw : `https://${raw}`;
|
||||
const parsed = new URL(url);
|
||||
return parsed.hostname.startsWith('.') ? parsed.hostname.slice(1) : parsed.hostname;
|
||||
}
|
||||
catch {
|
||||
const cleaned = raw.trim();
|
||||
if (!cleaned)
|
||||
return undefined;
|
||||
return cleaned.startsWith('.') ? cleaned.slice(1) : cleaned;
|
||||
}
|
||||
}
|
||||
function dedupeCookies(cookies) {
|
||||
const merged = new Map();
|
||||
for (const cookie of cookies) {
|
||||
const key = `${cookie.name}|${cookie.domain ?? ''}|${cookie.path ?? ''}`;
|
||||
if (!merged.has(key))
|
||||
merged.set(key, cookie);
|
||||
}
|
||||
return Array.from(merged.values());
|
||||
}
|
||||
//# sourceMappingURL=safariBinaryCookies.js.map
|
||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-26
@@ -1,26 +0,0 @@
|
||||
import type { Cookie, CookieHeaderOptions, GetCookiesOptions, GetCookiesResult } from './types.js';
|
||||
/**
|
||||
* Read cookies for a URL from one or more browser backends (and/or inline payloads).
|
||||
*
|
||||
* Supported backends:
|
||||
* - `chrome`: macOS / Windows / Linux (Chromium-based; default discovery targets Google Chrome paths)
|
||||
* - `edge`: macOS / Windows / Linux (Chromium-based; default discovery targets Microsoft Edge paths)
|
||||
* - `firefox`: macOS / Windows / Linux
|
||||
* - `safari`: macOS only (`Cookies.binarycookies`)
|
||||
*
|
||||
* Runtime requirements:
|
||||
* - Node >= 22 (uses `node:sqlite`) or Bun (uses `bun:sqlite`)
|
||||
*
|
||||
* The function returns `{ cookies, warnings }`:
|
||||
* - `cookies`: best-effort results, filtered by `url`/`origins` and optional `names` allowlist
|
||||
* - `warnings`: non-fatal diagnostics (no raw cookie values)
|
||||
*/
|
||||
export declare function getCookies(options: GetCookiesOptions): Promise<GetCookiesResult>;
|
||||
/**
|
||||
* Convert cookies to an HTTP `Cookie` header value.
|
||||
*
|
||||
* This is a helper for typical Node fetch clients / HTTP libraries.
|
||||
* It does not validate cookie RFC edge cases; it simply joins `name=value` pairs.
|
||||
*/
|
||||
export declare function toCookieHeader(cookies: readonly Cookie[], options?: CookieHeaderOptions): string;
|
||||
//# sourceMappingURL=public.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../src/public.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEX,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAKpB;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2FtF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,GAAE,mBAAwB,GAC/B,MAAM,CAyBR"}
|
||||
Generated
Vendored
-195
@@ -1,195 +0,0 @@
|
||||
import { getCookiesFromChrome } from './providers/chrome.js';
|
||||
import { getCookiesFromEdge } from './providers/edge.js';
|
||||
import { getCookiesFromFirefox } from './providers/firefoxSqlite.js';
|
||||
import { getCookiesFromInline } from './providers/inline.js';
|
||||
import { getCookiesFromSafari } from './providers/safariBinaryCookies.js';
|
||||
import { normalizeOrigins } from './util/origins.js';
|
||||
const DEFAULT_BROWSERS = ['chrome', 'safari', 'firefox'];
|
||||
/**
|
||||
* Read cookies for a URL from one or more browser backends (and/or inline payloads).
|
||||
*
|
||||
* Supported backends:
|
||||
* - `chrome`: macOS / Windows / Linux (Chromium-based; default discovery targets Google Chrome paths)
|
||||
* - `edge`: macOS / Windows / Linux (Chromium-based; default discovery targets Microsoft Edge paths)
|
||||
* - `firefox`: macOS / Windows / Linux
|
||||
* - `safari`: macOS only (`Cookies.binarycookies`)
|
||||
*
|
||||
* Runtime requirements:
|
||||
* - Node >= 22 (uses `node:sqlite`) or Bun (uses `bun:sqlite`)
|
||||
*
|
||||
* The function returns `{ cookies, warnings }`:
|
||||
* - `cookies`: best-effort results, filtered by `url`/`origins` and optional `names` allowlist
|
||||
* - `warnings`: non-fatal diagnostics (no raw cookie values)
|
||||
*/
|
||||
export async function getCookies(options) {
|
||||
const warnings = [];
|
||||
const url = options.url;
|
||||
const origins = normalizeOrigins(url, options.origins);
|
||||
const names = normalizeNames(options.names);
|
||||
let browsers;
|
||||
if (Array.isArray(options.browsers) && options.browsers.length > 0) {
|
||||
browsers = options.browsers;
|
||||
}
|
||||
else {
|
||||
browsers = parseBrowsersEnv() ?? DEFAULT_BROWSERS;
|
||||
}
|
||||
const mode = options.mode ?? parseModeEnv() ?? 'merge';
|
||||
const inlineSources = await resolveInlineSources(options);
|
||||
// Inline sources are the most reliable path (they bypass DB locks + keychain prompts).
|
||||
// We short-circuit on the first inline source that yields any cookies.
|
||||
for (const source of inlineSources) {
|
||||
const inlineResult = await getCookiesFromInline(source, origins, names);
|
||||
warnings.push(...inlineResult.warnings);
|
||||
if (inlineResult.cookies.length) {
|
||||
return { cookies: inlineResult.cookies, warnings };
|
||||
}
|
||||
}
|
||||
const merged = new Map();
|
||||
const tryAdd = (cookie) => {
|
||||
// Dedupe by name+domain+path (a common stable identity for HTTP cookies).
|
||||
const domain = cookie.domain ?? '';
|
||||
const pathValue = cookie.path ?? '';
|
||||
const key = `${cookie.name}|${domain}|${pathValue}`;
|
||||
if (!merged.has(key)) {
|
||||
merged.set(key, cookie);
|
||||
}
|
||||
};
|
||||
for (const browser of browsers) {
|
||||
let result;
|
||||
if (browser === 'chrome') {
|
||||
const chromeOptions = {};
|
||||
const chromeProfile = options.chromeProfile ?? options.profile ?? readEnv('SWEET_COOKIE_CHROME_PROFILE');
|
||||
if (chromeProfile)
|
||||
chromeOptions.profile = chromeProfile;
|
||||
if (options.timeoutMs !== undefined)
|
||||
chromeOptions.timeoutMs = options.timeoutMs;
|
||||
if (options.includeExpired !== undefined)
|
||||
chromeOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
chromeOptions.debug = options.debug;
|
||||
result = await getCookiesFromChrome(chromeOptions, origins, names);
|
||||
}
|
||||
else if (browser === 'edge') {
|
||||
const edgeOptions = {};
|
||||
const edgeProfile = options.edgeProfile ??
|
||||
options.profile ??
|
||||
readEnv('SWEET_COOKIE_EDGE_PROFILE') ??
|
||||
readEnv('SWEET_COOKIE_CHROME_PROFILE');
|
||||
if (edgeProfile)
|
||||
edgeOptions.profile = edgeProfile;
|
||||
if (options.timeoutMs !== undefined)
|
||||
edgeOptions.timeoutMs = options.timeoutMs;
|
||||
if (options.includeExpired !== undefined)
|
||||
edgeOptions.includeExpired = options.includeExpired;
|
||||
if (options.debug !== undefined)
|
||||
edgeOptions.debug = options.debug;
|
||||
result = await getCookiesFromEdge(edgeOptions, origins, names);
|
||||
}
|
||||
else if (browser === 'firefox') {
|
||||
const firefoxOptions = {};
|
||||
const firefoxProfile = options.firefoxProfile ?? readEnv('SWEET_COOKIE_FIREFOX_PROFILE');
|
||||
if (firefoxProfile)
|
||||
firefoxOptions.profile = firefoxProfile;
|
||||
if (options.includeExpired !== undefined)
|
||||
firefoxOptions.includeExpired = options.includeExpired;
|
||||
result = await getCookiesFromFirefox(firefoxOptions, origins, names);
|
||||
}
|
||||
else {
|
||||
const safariOptions = {};
|
||||
if (options.includeExpired !== undefined)
|
||||
safariOptions.includeExpired = options.includeExpired;
|
||||
if (options.safariCookiesFile)
|
||||
safariOptions.file = options.safariCookiesFile;
|
||||
result = await getCookiesFromSafari(safariOptions, origins, names);
|
||||
}
|
||||
warnings.push(...result.warnings);
|
||||
if (mode === 'first' && result.cookies.length) {
|
||||
// "first" returns the first backend that produced anything (plus accumulated warnings).
|
||||
return { cookies: result.cookies, warnings };
|
||||
}
|
||||
for (const cookie of result.cookies) {
|
||||
tryAdd(cookie);
|
||||
}
|
||||
}
|
||||
return { cookies: Array.from(merged.values()), warnings };
|
||||
}
|
||||
/**
|
||||
* Convert cookies to an HTTP `Cookie` header value.
|
||||
*
|
||||
* This is a helper for typical Node fetch clients / HTTP libraries.
|
||||
* It does not validate cookie RFC edge cases; it simply joins `name=value` pairs.
|
||||
*/
|
||||
export function toCookieHeader(cookies, options = {}) {
|
||||
const sort = options.sort ?? 'name';
|
||||
const dedupeByName = options.dedupeByName ?? false;
|
||||
const items = cookies
|
||||
.filter((cookie) => cookie?.name && typeof cookie.value === 'string')
|
||||
.map((cookie) => ({ name: cookie.name, value: cookie.value }));
|
||||
const ordered = sort === 'name' ? items.slice().sort((a, b) => a.name.localeCompare(b.name)) : items;
|
||||
if (!dedupeByName) {
|
||||
return ordered.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');
|
||||
}
|
||||
const seen = new Set();
|
||||
const deduped = [];
|
||||
for (const cookie of ordered) {
|
||||
const key = cookie.name;
|
||||
if (seen.has(key))
|
||||
continue;
|
||||
seen.add(key);
|
||||
deduped.push(cookie);
|
||||
}
|
||||
return deduped.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');
|
||||
}
|
||||
function normalizeNames(names) {
|
||||
if (!names?.length)
|
||||
return null;
|
||||
const cleaned = names.map((n) => n.trim()).filter(Boolean);
|
||||
if (!cleaned.length)
|
||||
return null;
|
||||
return new Set(cleaned);
|
||||
}
|
||||
async function resolveInlineSources(options) {
|
||||
const sources = [];
|
||||
if (options.inlineCookiesJson) {
|
||||
sources.push({ source: 'inline-json', payload: options.inlineCookiesJson });
|
||||
}
|
||||
if (options.inlineCookiesBase64) {
|
||||
sources.push({ source: 'inline-base64', payload: options.inlineCookiesBase64 });
|
||||
}
|
||||
if (options.inlineCookiesFile) {
|
||||
sources.push({ source: 'inline-file', payload: options.inlineCookiesFile });
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
function parseBrowsersEnv() {
|
||||
const raw = readEnv('SWEET_COOKIE_BROWSERS') ?? readEnv('SWEET_COOKIE_SOURCES');
|
||||
if (!raw)
|
||||
return undefined;
|
||||
const tokens = raw
|
||||
.split(/[,\s]+/)
|
||||
.map((t) => t.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
const out = [];
|
||||
for (const token of tokens) {
|
||||
if (token === 'chrome' || token === 'edge' || token === 'firefox' || token === 'safari') {
|
||||
if (!out.includes(token))
|
||||
out.push(token);
|
||||
}
|
||||
}
|
||||
return out.length ? out : undefined;
|
||||
}
|
||||
function parseModeEnv() {
|
||||
const raw = readEnv('SWEET_COOKIE_MODE');
|
||||
if (!raw)
|
||||
return undefined;
|
||||
const normalized = raw.trim().toLowerCase();
|
||||
if (normalized === 'merge' || normalized === 'first')
|
||||
return normalized;
|
||||
return undefined;
|
||||
}
|
||||
function readEnv(key) {
|
||||
const value = process.env[key];
|
||||
const trimmed = typeof value === 'string' ? value.trim() : '';
|
||||
return trimmed.length ? trimmed : undefined;
|
||||
}
|
||||
//# sourceMappingURL=public.js.map
|
||||
Generated
Vendored
-1
File diff suppressed because one or more lines are too long
Generated
Vendored
-121
@@ -1,121 +0,0 @@
|
||||
/**
|
||||
* Supported browser backends.
|
||||
*
|
||||
* Notes:
|
||||
* - `safari` is macOS-only.
|
||||
* - `chrome` targets Google Chrome paths by default.
|
||||
* - `edge` targets Microsoft Edge paths by default.
|
||||
* - Other Chromium browsers often work by passing an explicit cookie DB path via `chromeProfile`
|
||||
* (or `edgeProfile` if you want to keep sources separate).
|
||||
* - Only modern Chromium cookie DB schemas are supported (roughly Chrome >= 100).
|
||||
*/
|
||||
export type BrowserName = 'chrome' | 'edge' | 'firefox' | 'safari';
|
||||
export type CookieSameSite = 'Strict' | 'Lax' | 'None';
|
||||
export interface Cookie {
|
||||
/** Cookie name (required). */
|
||||
name: string;
|
||||
/** Cookie value (required; may be empty string). */
|
||||
value: string;
|
||||
/** Hostname without leading dot (e.g. `example.com`). */
|
||||
domain?: string;
|
||||
/** Path (defaults to `/` when omitted). */
|
||||
path?: string;
|
||||
/**
|
||||
* Optional URL form. Useful when a cookie is host-only or when `domain` is not known.
|
||||
* If present, it should be a valid origin URL like `https://example.com`.
|
||||
*/
|
||||
url?: string;
|
||||
/** Unix timestamp in seconds. Omit for session cookies. */
|
||||
expires?: number;
|
||||
secure?: boolean;
|
||||
httpOnly?: boolean;
|
||||
sameSite?: CookieSameSite;
|
||||
source?: {
|
||||
browser: BrowserName;
|
||||
/** Optional profile identifier when resolved from a profile. */
|
||||
profile?: string;
|
||||
/** Optional origin that produced this cookie (implementation detail). */
|
||||
origin?: string;
|
||||
/** Optional store identifier (implementation detail; e.g. extension cookie store). */
|
||||
storeId?: string;
|
||||
};
|
||||
}
|
||||
export type CookieMode = 'merge' | 'first';
|
||||
export interface GetCookiesOptions {
|
||||
/**
|
||||
* Primary URL used to derive default origin filtering.
|
||||
* Must include a protocol (e.g. `https://example.com/`).
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* Additional origins to include when filtering cookies.
|
||||
* Useful for OAuth/SSO flows where cookies are set on multiple domains.
|
||||
*/
|
||||
origins?: string[];
|
||||
/** Allowlist of cookie names. When omitted, all matching cookies are returned. */
|
||||
names?: string[];
|
||||
/**
|
||||
* Which browser backends to try, in order.
|
||||
* Defaults to `chrome`, `safari`, `firefox` (and is also configurable via env).
|
||||
*/
|
||||
browsers?: BrowserName[];
|
||||
/** Alias for chromeProfile (common case). */
|
||||
profile?: string;
|
||||
/**
|
||||
* Chrome/Chromium profile selector.
|
||||
*
|
||||
* Accepted values:
|
||||
* - profile directory name like `Default` / `Profile 2`
|
||||
* - a path to a profile directory
|
||||
* - a path to a cookie DB file (`.../Network/Cookies` or `.../Cookies`)
|
||||
*/
|
||||
chromeProfile?: string;
|
||||
/**
|
||||
* Microsoft Edge profile selector.
|
||||
*
|
||||
* Accepted values:
|
||||
* - profile directory name like `Default` / `Profile 2`
|
||||
* - a path to a profile directory
|
||||
* - a path to a cookie DB file (`.../Network/Cookies` or `.../Cookies`)
|
||||
*/
|
||||
edgeProfile?: string;
|
||||
/**
|
||||
* Firefox profile selector (profile name or filesystem path).
|
||||
* If a directory is provided, `cookies.sqlite` is resolved within it.
|
||||
*/
|
||||
firefoxProfile?: string;
|
||||
/** Override path to Safari Cookies.binarycookies (for tests / debugging). */
|
||||
safariCookiesFile?: string;
|
||||
/** Include expired cookies (default: false). */
|
||||
includeExpired?: boolean;
|
||||
/** Timeout for OS helper calls (keychain/keyring/DPAPI). */
|
||||
timeoutMs?: number;
|
||||
/** Emit extra provider warnings (no raw cookie values). */
|
||||
debug?: boolean;
|
||||
/** Merge cookies across backends (`merge`) or return first successful backend (`first`). */
|
||||
mode?: CookieMode;
|
||||
/**
|
||||
* Inline cookie payload source. Commonly a file path exported by the extension.
|
||||
* If it looks like a file path, Sweet Cookie will attempt to read it.
|
||||
*/
|
||||
inlineCookiesFile?: string;
|
||||
/** Inline cookie payload as JSON string (either `Cookie[]` or `{ cookies: Cookie[] }`). */
|
||||
inlineCookiesJson?: string;
|
||||
/** Inline cookie payload as base64-encoded JSON. */
|
||||
inlineCookiesBase64?: string;
|
||||
}
|
||||
export interface GetCookiesResult {
|
||||
cookies: Cookie[];
|
||||
/**
|
||||
* Non-fatal warnings from providers (missing keyring tools, schema drift, unsupported cookies, etc).
|
||||
* Never includes raw cookie values.
|
||||
*/
|
||||
warnings: string[];
|
||||
}
|
||||
export interface CookieHeaderOptions {
|
||||
/** If true, keeps the first cookie value per name and drops duplicates. */
|
||||
dedupeByName?: boolean;
|
||||
/** Sorting strategy for the emitted header. */
|
||||
sort?: 'name' | 'none';
|
||||
}
|
||||
//# sourceMappingURL=types.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,MAAM;IACtB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE;QACR,OAAO,EAAE,WAAW,CAAC;QACrB,gEAAgE;QAChE,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,yEAAyE;QACzE,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,sFAAsF;QACtF,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACF;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4FAA4F;IAC5F,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB"}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
||||
Generated
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
export declare function tryDecodeBase64Json(input: string): string | null;
|
||||
//# sourceMappingURL=base64.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../../src/util/base64.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAahE"}
|
||||
Generated
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
export function tryDecodeBase64Json(input) {
|
||||
const trimmed = input.trim();
|
||||
if (!trimmed)
|
||||
return null;
|
||||
try {
|
||||
const encoding = /[-_]/.test(trimmed) ? 'base64url' : 'base64';
|
||||
const buf = Buffer.from(trimmed, encoding);
|
||||
const decoded = buf.toString('utf8').trim();
|
||||
if (!decoded)
|
||||
return null;
|
||||
JSON.parse(decoded);
|
||||
return decoded;
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=base64.js.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/util/base64.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAmB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC/E,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC"}
|
||||
Generated
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
export declare function execCapture(file: string, args: string[], options?: {
|
||||
timeoutMs?: number;
|
||||
}): Promise<{
|
||||
code: number;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}>;
|
||||
//# sourceMappingURL=exec.d.ts.map
|
||||
Generated
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/util/exec.ts"],"names":[],"mappings":"AAEA,wBAAsB,WAAW,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8G3D"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user