@mherod/get-cookie 4.0.2 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.husky/commit-msg +0 -0
  2. package/.husky/pre-commit +0 -0
  3. package/.husky/pre-push +0 -0
  4. package/.idea/prettier.xml +2 -1
  5. package/dist/chunk-A6MIB6FP.js +2 -0
  6. package/dist/chunk-A6MIB6FP.js.map +1 -0
  7. package/dist/chunk-CFMK2YSL.js +2 -0
  8. package/dist/chunk-CFMK2YSL.js.map +1 -0
  9. package/dist/chunk-IRERRCUF.js +2 -0
  10. package/dist/chunk-IRERRCUF.js.map +1 -0
  11. package/dist/chunk-UPNW543B.js +2 -0
  12. package/dist/chunk-UPNW543B.js.map +1 -0
  13. package/dist/cli.cjs +3 -4
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/{getChromeCookie-4ZWACG6M.js → getChromeCookie-CL3SRRWX.js} +2 -2
  16. package/dist/getChromeCookie-CL3SRRWX.js.map +1 -0
  17. package/dist/getCookie-WV5KDZN7.js +2 -0
  18. package/dist/getFirefoxCookie-BXQ2GXAW.js +2 -0
  19. package/dist/getFirefoxCookie-BXQ2GXAW.js.map +1 -0
  20. package/dist/getGroupedRenderedCookies-FNJ6FQVQ.js +2 -0
  21. package/dist/getGroupedRenderedCookies-FNJ6FQVQ.js.map +1 -0
  22. package/dist/getMergedRenderedCookies-PNC2LHSD.js +2 -0
  23. package/dist/getMergedRenderedCookies-PNC2LHSD.js.map +1 -0
  24. package/dist/index.cjs +3 -3
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +164 -152
  27. package/dist/index.d.ts +164 -152
  28. package/dist/index.js +1 -1
  29. package/dist/index.js.map +1 -1
  30. package/eslint.config.js +2 -1
  31. package/package.json +23 -19
  32. package/typedoc.json +3 -8
  33. package/dist/chunk-5ZT2G45S.js +0 -2
  34. package/dist/chunk-5ZT2G45S.js.map +0 -1
  35. package/dist/chunk-FR2MKDHT.js +0 -2
  36. package/dist/chunk-FR2MKDHT.js.map +0 -1
  37. package/dist/chunk-HMKSQBDC.js +0 -2
  38. package/dist/chunk-HMKSQBDC.js.map +0 -1
  39. package/dist/chunk-W3JALMAX.js +0 -2
  40. package/dist/chunk-W3JALMAX.js.map +0 -1
  41. package/dist/getChromeCookie-4ZWACG6M.js.map +0 -1
  42. package/dist/getCookie-43FKMQEZ.js +0 -2
  43. package/dist/getFirefoxCookie-OJYYZFZP.js +0 -2
  44. package/dist/getFirefoxCookie-OJYYZFZP.js.map +0 -1
  45. package/dist/getGroupedRenderedCookies-P5VZXZUC.js +0 -2
  46. package/dist/getGroupedRenderedCookies-P5VZXZUC.js.map +0 -1
  47. package/dist/getMergedRenderedCookies-C6TXK2I4.js +0 -2
  48. package/dist/getMergedRenderedCookies-C6TXK2I4.js.map +0 -1
  49. package/tsup.config.ts +0 -27
  50. /package/dist/{getCookie-43FKMQEZ.js.map → getCookie-WV5KDZN7.js.map} +0 -0
package/.husky/commit-msg CHANGED
File without changes
package/.husky/pre-commit CHANGED
File without changes
package/.husky/pre-push CHANGED
File without changes
@@ -1,8 +1,9 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
3
  <component name="PrettierConfiguration">
4
+ <option name="myConfigurationMode" value="AUTOMATIC" />
4
5
  <option name="myRunOnSave" value="true" />
5
6
  <option name="myRunOnReformat" value="true" />
6
- <option name="myFilesPattern" value="src/{**/*,*}.{js,json}" />
7
+ <option name="myFilesPattern" value="src/{**/*,*}.{js,json,ts}" />
7
8
  </component>
8
9
  </project>
@@ -0,0 +1,2 @@
1
+ import{z as e}from"zod";var k=e.object({name:e.string().trim().min(1,"Cookie name cannot be empty"),domain:e.string().trim().min(1,"Domain cannot be empty")}).strict(),y=e.object({file:e.string().trim().min(1,"File path cannot be empty").optional(),browser:e.string().trim().optional(),decrypted:e.boolean().optional(),secure:e.boolean().optional(),httpOnly:e.boolean().optional(),path:e.string().optional()}).catchall(e.unknown()).strict(),l=e.object({domain:e.string().trim().min(1,"Domain cannot be empty"),name:e.string().trim().min(1,"Cookie name cannot be empty"),value:e.string(),expiry:e.union([e.literal("Infinity"),e.date(),e.number().int().positive("Expiry must be a positive number")]).optional(),meta:y.optional()}).strict(),C=e.object({expiry:e.number().int().optional(),domain:e.string().trim().min(1,"Domain cannot be empty"),name:e.string().trim().min(1,"Cookie name cannot be empty"),value:e.union([e.string(),e.instanceof(Buffer)])}).strict(),x=e.object({format:e.enum(["merged","grouped"]).optional(),separator:e.string().optional(),showFilePaths:e.boolean().optional()}).strict(),u=e.enum(["Chrome","Firefox","Safari","internal","unknown"]),b=e.object({browserName:u,queryCookies:e.function().args(e.string(),e.string()).returns(e.promise(e.array(l)))}).strict();import{groupBy as f}from"lodash-es";function d(r,p={}){let{format:i="merged",showFilePaths:m=!0,separator:a="; "}=p;if(r.length===0)return i==="merged"?"":[];if(i==="merged")return r.map(o=>o.value).join(a);let s=f(r,o=>{var n,t;return(t=(n=o.meta)==null?void 0:n.file)!=null?t:"unknown"});return Object.entries(s).map(([o,n])=>{let t=n.map(c=>c.value).join(a);return m?`${o}: ${t}`:t})}export{l as a,d as b};
2
+ //# sourceMappingURL=chunk-A6MIB6FP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/schemas.ts","../src/core/cookies/renderCookies.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Schema for cookie specification parameters\n * Defines the required fields for identifying a cookie\n * @example\n * ```typescript\n * // Validate a cookie specification\n * const spec = {\n * name: 'session',\n * domain: 'example.com'\n * };\n * const result = CookieSpecSchema.safeParse(spec);\n * if (result.success) {\n * console.log('Valid cookie spec:', result.data);\n * } else {\n * console.error('Invalid cookie spec:', result.error);\n * }\n *\n * // Invalid spec (empty name)\n * const invalidSpec = {\n * name: '',\n * domain: 'example.com'\n * };\n * // Throws: \"Cookie name cannot be empty\"\n * CookieSpecSchema.parse(invalidSpec);\n * ```\n */\nexport const CookieSpecSchema = z\n .object({\n name: z.string().trim().min(1, \"Cookie name cannot be empty\"),\n domain: z.string().trim().min(1, \"Domain cannot be empty\"),\n })\n .strict();\n\n/**\n * Type definition for cookie specification\n * Used for specifying which cookie to query\n * @example\n * ```typescript\n * // Basic cookie spec\n * const spec: CookieSpec = {\n * name: 'auth',\n * domain: 'api.example.com'\n * };\n *\n * // Use in function parameters\n * function queryCookie(spec: CookieSpec): Promise<ExportedCookie[]> {\n * return getCookie(spec);\n * }\n *\n * // Array of specs\n * const specs: CookieSpec[] = [\n * { name: 'session', domain: 'app.example.com' },\n * { name: 'theme', domain: 'example.com' }\n * ];\n * ```\n */\nexport type CookieSpec = z.infer<typeof CookieSpecSchema>;\n\n/**\n * Schema for metadata about a cookie\n */\nexport const CookieMetaSchema = z\n .object({\n file: z.string().trim().min(1, \"File path cannot be empty\").optional(),\n browser: z.string().trim().optional(),\n decrypted: z.boolean().optional(),\n secure: z.boolean().optional(),\n httpOnly: z.boolean().optional(),\n path: z.string().optional(),\n })\n .catchall(z.unknown())\n .strict();\n\n/**\n * Type definition for cookie metadata\n */\nexport type CookieMeta = z.infer<typeof CookieMetaSchema>;\n\n/**\n * Schema for exported cookie data\n * Represents a cookie with all its properties and metadata\n * @example\n * ```typescript\n * // Validate an exported cookie\n * const cookie = {\n * domain: 'example.com',\n * name: 'session',\n * value: 'abc123',\n * expiry: new Date('2024-12-31'),\n * meta: {\n * file: '/path/to/cookies.db'\n * }\n * };\n * const result = ExportedCookieSchema.safeParse(cookie);\n * if (result.success) {\n * console.log('Valid cookie:', result.data);\n * } else {\n * console.error('Invalid cookie:', result.error);\n * }\n *\n * // Cookie with infinite expiry\n * const infiniteCookie = {\n * ...cookie,\n * expiry: \"Infinity\"\n * };\n * ExportedCookieSchema.parse(infiniteCookie); // OK\n * ```\n */\nexport const ExportedCookieSchema = z\n .object({\n domain: z.string().trim().min(1, \"Domain cannot be empty\"),\n name: z.string().trim().min(1, \"Cookie name cannot be empty\"),\n value: z.string(),\n expiry: z\n .union([\n z.literal(\"Infinity\"),\n z.date(),\n z.number().int().positive(\"Expiry must be a positive number\"),\n ])\n .optional(),\n meta: CookieMetaSchema.optional(),\n })\n .strict();\n\n/**\n * Type definition for exported cookie data\n * Represents the structure of a cookie after it has been retrieved\n * @example\n * ```typescript\n * // Basic exported cookie\n * const cookie: ExportedCookie = {\n * domain: 'example.com',\n * name: 'session',\n * value: 'abc123',\n * expiry: new Date('2024-12-31'),\n * meta: {\n * file: '/path/to/cookies.db'\n * }\n * };\n *\n * // Process exported cookies\n * function processCookies(cookies: ExportedCookie[]): string[] {\n * return cookies.map(cookie => `${cookie.name}=${cookie.value}`);\n * }\n *\n * // Filter expired cookies\n * function filterExpired(cookies: ExportedCookie[]): ExportedCookie[] {\n * const now = new Date();\n * return cookies.filter(cookie =>\n * cookie.expiry === \"Infinity\" ||\n * (cookie.expiry instanceof Date && cookie.expiry > now)\n * );\n * }\n * ```\n */\nexport type ExportedCookie = z.infer<typeof ExportedCookieSchema>;\n\n/**\n * Schema for raw cookie data from browser stores\n */\nexport const CookieRowSchema = z\n .object({\n expiry: z.number().int().optional(),\n domain: z.string().trim().min(1, \"Domain cannot be empty\"),\n name: z.string().trim().min(1, \"Cookie name cannot be empty\"),\n value: z.union([z.string(), z.instanceof(Buffer)]),\n })\n .strict();\n\n/**\n * Type definition for raw cookie data\n */\nexport type CookieRow = z.infer<typeof CookieRowSchema>;\n\n/**\n * Schema for cookie render options\n */\nexport const RenderOptionsSchema = z\n .object({\n format: z.enum([\"merged\", \"grouped\"]).optional(),\n separator: z.string().optional(),\n showFilePaths: z.boolean().optional(),\n })\n .strict();\n\n/**\n * Type definition for render options\n */\nexport type RenderOptions = z.infer<typeof RenderOptionsSchema>;\n\n/**\n * Schema for browser names\n */\nexport const BrowserNameSchema = z.enum([\n \"Chrome\",\n \"Firefox\",\n \"Safari\",\n \"internal\",\n \"unknown\",\n]);\n\n/**\n * Type definition for browser names\n */\nexport type BrowserName = z.infer<typeof BrowserNameSchema>;\n\n/**\n * Schema for cookie query strategy\n */\nexport const CookieQueryStrategySchema = z\n .object({\n browserName: BrowserNameSchema,\n queryCookies: z\n .function()\n .args(z.string(), z.string())\n .returns(z.promise(z.array(ExportedCookieSchema))),\n })\n .strict();\n\n/**\n * Type definition for cookie query strategy\n */\nexport type CookieQueryStrategy = z.infer<typeof CookieQueryStrategySchema>;\n\n/**\n * Type representing either a single cookie specification or an array of specifications.\n * Useful when you need to query multiple cookies in a single operation.\n * @example\n * ```typescript\n * // Single cookie spec\n * const single: MultiCookieSpec = {\n * domain: \"example.com\",\n * name: \"sessionId\"\n * };\n *\n * // Multiple cookie specs\n * const multiple: MultiCookieSpec = [\n * { domain: \"example.com\", name: \"sessionId\" },\n * { domain: \"api.example.com\", name: \"authToken\" }\n * ];\n * ```\n */\nexport type MultiCookieSpec = CookieSpec | CookieSpec[];\n","import { groupBy } from \"lodash-es\";\n\nimport { ExportedCookie, RenderOptions } from \"../../types/schemas\";\n\n/**\n * Renders cookies as a string or array of strings based on the provided format option.\n * Supports merged format for single string output or grouped format for file-based grouping.\n * @param cookies - The cookies to render\n * @param options - Options for rendering\n * @param options.format - The output format ('merged' or 'grouped')\n * @param options.showFilePaths - Whether to include file paths in grouped output\n * @param options.separator - Custom separator for cookie values\n * @returns A string for merged format, or array of strings for grouped format\n * @example\n * ```typescript\n * // Merged format (default)\n * const cookies = [\n * { value: 'sessionId=abc123' },\n * { value: 'theme=dark' }\n * ];\n * renderCookies(cookies);\n * // Returns: \"sessionId=abc123; theme=dark\"\n *\n * // Grouped format with file paths\n * const groupedCookies = [\n * { value: 'sessionId=abc123', meta: { file: 'auth.ts' } },\n * { value: 'theme=dark', meta: { file: 'preferences.ts' } }\n * ];\n * renderCookies(groupedCookies, { format: 'grouped', showFilePaths: true });\n * // Returns: [\"auth.ts: sessionId=abc123\", \"preferences.ts: theme=dark\"]\n * ```\n */\nexport function renderCookies(\n cookies: ExportedCookie[],\n options: RenderOptions = {},\n): string | string[] {\n const { format = \"merged\", showFilePaths = true, separator = \"; \" } = options;\n\n if (cookies.length === 0) {\n return format === \"merged\" ? \"\" : [];\n }\n\n if (format === \"merged\") {\n return cookies.map((c) => c.value).join(separator);\n }\n\n const groupedByFile = groupBy(cookies, (c) => c.meta?.file ?? \"unknown\");\n return Object.entries(groupedByFile).map(([file, fileCookies]) => {\n const values = fileCookies.map((c) => c.value).join(separator);\n return showFilePaths ? `${file}: ${values}` : values;\n });\n}\n"],"mappings":"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","names":["z","CookieSpecSchema","CookieMetaSchema","ExportedCookieSchema","CookieRowSchema","RenderOptionsSchema","BrowserNameSchema","CookieQueryStrategySchema","groupBy","renderCookies","cookies","options","format","showFilePaths","separator","c","groupedByFile","_a","_b","file","fileCookies","values"]}
@@ -0,0 +1,2 @@
1
+ import{a as g}from"./chunk-UPNW543B.js";import{a as l}from"./chunk-IRERRCUF.js";import{a as f,c as m}from"./chunk-56Z35D5R.js";import{join as B}from"path";import{readFileSync as S}from"fs";import{homedir as L}from"os";import{join as Q}from"path";var w=1706047360;function p(o,e){let t=e;for(;t<o.length&&o[t]!==0;)t++;return[o.toString("utf8",e,t),t+1]}function b(o,e){let t=o.readUInt32LE(e),n=e+43,r=o.readUInt32LE(n)-w,i=e+56,[a,c]=p(o,i);i=c;let[d,C]=p(o,i);i=C;let[h,x]=p(o,i);i=x;let[E,P]=p(o,i);return[{name:d,value:E,domain:a.startsWith(".")?a.slice(1):a,path:h||"/",expiry:r,creation:r},t]}function v(o,e,t){let n=e+5,s=o.readUInt32BE(n),r=e+s,i=[],a=e+t;for(;r<a-8;)try{let[c,d]=b(o,r);i.push(c),r+=d}catch(c){console.warn(`Error decoding cookie at offset ${r}:`,c);break}return i}function y(o){let e=S(o),t=e.readUInt32BE(4),n=[];for(let i=0;i<t;i++)n.push(e.readUInt32BE(8+i*4));let s=8+t*4,r=[];for(let i=0;i<t;i++)try{let a=v(e,s,n[i]);r.push(...a),s+=n[i]}catch(a){console.warn(`Error decoding page ${i}:`,a),s+=n[i]}return r}var u=class{constructor(){this.browserName="Safari"}getHomeDir(){let e=process.env.HOME;return typeof e!="string"||e.trim().length===0?(m("SafariCookieQueryStrategy","HOME environment variable not set"),""):e}getCookieDbPath(e){return B(e,"Library","Containers","com.apple.Safari","Data","Library","Cookies","Cookies.binarycookies")}decodeCookies(e,t,n){try{return y(e).filter(r=>r.name===t&&r.domain.includes(n)).map(r=>({domain:r.domain,name:r.name,value:r.value.toString(),expiry:typeof r.expiry=="number"&&r.expiry>0?new Date(r.expiry*1e3):"Infinity",meta:{file:e,browser:"Safari",decrypted:!1}}))}catch(s){return s instanceof Error?m("SafariCookieQueryStrategy",`Error decoding ${e}`,{error:s,name:t,domain:n}):m("SafariCookieQueryStrategy",`Error decoding ${e}`,{error:"Unknown error",name:t,domain:n}),[]}}async queryCookies(e,t){let n=this.getHomeDir();if(typeof n!="string"||n.length===0)return Promise.resolve([]);let s=this.getCookieDbPath(n);return Promise.resolve(this.decodeCookies(s,e,t))}};async function k(o){if(!o.name||!o.domain)return[];let{name:e,domain:t}=o;if(typeof e!="string"||typeof t!="string")return[];let n=[new g,new l,new u];return(await Promise.allSettled(n.map(r=>r.queryCookies(e,t)))).filter(r=>r.status==="fulfilled").flatMap(r=>r.value)}async function O(o){try{return await k(o)}catch(e){return f.warn("Error querying cookies:",e instanceof Error?e.message:String(e)),[]}}var j=O;export{O as a,j as b};
2
+ //# sourceMappingURL=chunk-CFMK2YSL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/browsers/safari/SafariCookieQueryStrategy.ts","../src/core/browsers/decodeBinaryCookies.ts","../src/core/cookies/queryCookies.ts","../src/core/cookies/getCookie.ts"],"sourcesContent":["import { join } from \"path\";\n\nimport { logError } from \"@utils/logHelpers\";\n\nimport type {\n BrowserName,\n CookieQueryStrategy,\n ExportedCookie,\n} from \"../../../types/schemas\";\nimport { decodeBinaryCookies } from \"../decodeBinaryCookies\";\n\n/**\n * Strategy for querying cookies from Safari browser\n */\nexport class SafariCookieQueryStrategy implements CookieQueryStrategy {\n /**\n * The browser name for this strategy\n */\n public readonly browserName: BrowserName = \"Safari\";\n\n /**\n * Gets the user's home directory\n * @returns The home directory path or empty string if not found\n */\n private getHomeDir(): string {\n const homeDir = process.env.HOME;\n if (typeof homeDir !== \"string\" || homeDir.trim().length === 0) {\n logError(\n \"SafariCookieQueryStrategy\",\n \"HOME environment variable not set\",\n );\n return \"\";\n }\n return homeDir;\n }\n\n /**\n * Gets the path to Safari's cookie database\n * @param homeDir - The user's home directory\n * @returns Path to the cookie database\n */\n private getCookieDbPath(homeDir: string): string {\n return join(\n homeDir,\n \"Library\",\n \"Containers\",\n \"com.apple.Safari\",\n \"Data\",\n \"Library\",\n \"Cookies\",\n \"Cookies.binarycookies\",\n );\n }\n\n /**\n * Decodes cookies from Safari's binary cookie file\n * @param cookieDbPath - Path to the cookie database\n * @param name - Name of the cookie to find\n * @param domain - Domain to filter cookies by\n * @returns Array of exported cookies\n */\n private decodeCookies(\n cookieDbPath: string,\n name: string,\n domain: string,\n ): ExportedCookie[] {\n try {\n const cookies = decodeBinaryCookies(cookieDbPath);\n return cookies\n .filter(\n (cookie) => cookie.name === name && cookie.domain.includes(domain),\n )\n .map((cookie) => ({\n domain: cookie.domain,\n name: cookie.name,\n value: cookie.value.toString(),\n expiry:\n typeof cookie.expiry === \"number\" && cookie.expiry > 0\n ? new Date(cookie.expiry * 1000)\n : \"Infinity\",\n meta: {\n file: cookieDbPath,\n browser: \"Safari\" as const,\n decrypted: false,\n },\n }));\n } catch (error) {\n if (error instanceof Error) {\n logError(\n \"SafariCookieQueryStrategy\",\n `Error decoding ${cookieDbPath}`,\n { error, name, domain },\n );\n } else {\n logError(\n \"SafariCookieQueryStrategy\",\n `Error decoding ${cookieDbPath}`,\n { error: \"Unknown error\", name, domain },\n );\n }\n return [];\n }\n }\n\n /**\n * Query Safari's cookie storage for cookies matching the given criteria\n * @param name - Name of the cookie to find\n * @param domain - Domain to filter cookies by\n * @returns Array of matching cookies, or empty array if none found\n */\n public async queryCookies(\n name: string,\n domain: string,\n ): Promise<ExportedCookie[]> {\n const homeDir = this.getHomeDir();\n if (typeof homeDir !== \"string\" || homeDir.length === 0) {\n return Promise.resolve([]);\n }\n\n const cookieDbPath = this.getCookieDbPath(homeDir);\n return Promise.resolve(this.decodeCookies(cookieDbPath, name, domain));\n }\n}\n","import { readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { join } from \"path\";\n\ninterface CookieRow {\n name: string;\n value: string;\n domain: string;\n path: string;\n expiry: number;\n creation: number;\n flags?: number;\n}\n\n// The date offset for Safari cookies (until 2017)\nconst SAFARI_DATE_OFFSET = 1706047360;\n\nfunction readNullTerminatedString(\n buffer: Buffer,\n offset: number,\n): [string, number] {\n let end = offset;\n while (end < buffer.length && buffer[end] !== 0) {\n end++;\n }\n return [buffer.toString(\"utf8\", offset, end), end + 1];\n}\n\nfunction decodeCookieHeader(\n buffer: Buffer,\n offset: number,\n): [CookieRow, number] {\n // First 4 bytes are the cookie size in little-endian\n const size = buffer.readUInt32LE(offset);\n\n // Read the date at offset 0x2B (43 bytes from start)\n const dateOffset = offset + 0x2b;\n const date = buffer.readUInt32LE(dateOffset);\n const timestamp = date - SAFARI_DATE_OFFSET;\n\n // Dynamic fields start at offset 0x38 (56 bytes from start)\n let currentOffset = offset + 0x38;\n const [domain, nextOffset] = readNullTerminatedString(buffer, currentOffset);\n currentOffset = nextOffset;\n\n const [name, nextOffset2] = readNullTerminatedString(buffer, currentOffset);\n currentOffset = nextOffset2;\n\n // The fields are path, then value\n const [path, nextOffset3] = readNullTerminatedString(buffer, currentOffset);\n currentOffset = nextOffset3;\n\n const [value, _] = readNullTerminatedString(buffer, currentOffset);\n\n return [\n {\n name,\n value,\n domain: domain.startsWith(\".\") ? domain.slice(1) : domain,\n path: path || \"/\", // Default to root path if empty\n expiry: timestamp,\n creation: timestamp, // We don't have creation time in this format\n },\n size,\n ];\n}\n\nfunction decodePage(\n buffer: Buffer,\n offset: number,\n pageSize: number,\n): CookieRow[] {\n // Skip first 5 bytes\n const headerLengthOffset = offset + 5;\n // Next 4 bytes contain header length\n const headerLength = buffer.readUInt32BE(headerLengthOffset);\n\n let currentOffset = offset + headerLength;\n const cookies: CookieRow[] = [];\n const pageEnd = offset + pageSize;\n\n // Read cookies until we reach the page end\n while (currentOffset < pageEnd - 8) {\n try {\n const [cookie, size] = decodeCookieHeader(buffer, currentOffset);\n cookies.push(cookie);\n currentOffset += size;\n } catch (error) {\n console.warn(`Error decoding cookie at offset ${currentOffset}:`, error);\n break;\n }\n }\n\n return cookies;\n}\n\n/**\n * Decodes a Safari binary cookie file into an array of cookie objects.\n * @param cookieDbPath - Path to the Safari Cookies.binarycookies file\n * @returns Array of decoded cookie objects\n * @throws {Error} If the file cannot be read or has invalid format\n */\nexport function decodeBinaryCookies(cookieDbPath: string): CookieRow[] {\n const buffer = readFileSync(cookieDbPath);\n\n // Skip first 4 bytes (header)\n const numPages = buffer.readUInt32BE(4);\n\n // Read the page sizes array (4 bytes per page)\n const pageSizes: number[] = [];\n for (let i = 0; i < numPages; i++) {\n pageSizes.push(buffer.readUInt32BE(8 + i * 4));\n }\n\n // Skip the page sizes array\n let offset = 8 + numPages * 4;\n const cookies: CookieRow[] = [];\n\n // Process each page\n for (let i = 0; i < numPages; i++) {\n try {\n const pageCookies = decodePage(buffer, offset, pageSizes[i]);\n cookies.push(...pageCookies);\n offset += pageSizes[i];\n } catch (error) {\n console.warn(`Error decoding page ${i}:`, error);\n offset += pageSizes[i];\n }\n }\n\n return cookies;\n}\n\n/**\n * Retrieves cookies from Safari's binary cookie store.\n * @returns Array of decoded Safari cookies\n */\nexport function getSafariCookies(): CookieRow[] {\n const cookieDbPath = join(\n homedir(),\n \"Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookies\",\n );\n return decodeBinaryCookies(cookieDbPath);\n}\n","import type { CookieSpec, ExportedCookie } from \"../../types/schemas\";\nimport { ChromeCookieQueryStrategy } from \"../browsers/chrome/ChromeCookieQueryStrategy\";\nimport { FirefoxCookieQueryStrategy } from \"../browsers/firefox/FirefoxCookieQueryStrategy\";\nimport { SafariCookieQueryStrategy } from \"../browsers/safari/SafariCookieQueryStrategy\";\n\n/**\n * Queries cookies from all available browser strategies (Chrome, Firefox, Safari).\n * This function acts as a unified interface to retrieve cookies across different browsers.\n * @param cookieSpec - The cookie specification to query\n * @param cookieSpec.name - The name pattern to match cookies against (can include '%' as wildcard)\n * @param cookieSpec.domain - The domain to match cookies against\n * @returns Promise resolving to array of exported cookies from all available browsers\n * @remarks\n * - Returns empty array if cookieSpec is invalid or missing required fields\n * - Aggregates results from all available browser strategies\n * - Failed browser queries are gracefully handled and excluded from results\n * - Both name and domain fields are required and must be strings\n * @example\n * ```typescript\n * const cookies = await queryCookies({\n * name: 'sessionId',\n * domain: 'example.com'\n * });\n * console.log(cookies); // Array of matching cookies from all browsers\n * ```\n */\nexport async function queryCookies(\n cookieSpec: CookieSpec,\n): Promise<ExportedCookie[]> {\n if (!cookieSpec.name || !cookieSpec.domain) {\n return [];\n }\n\n const { name, domain } = cookieSpec;\n if (typeof name !== \"string\" || typeof domain !== \"string\") {\n return [];\n }\n\n /**\n * Initialize all available browser-specific strategies\n * The order of strategies can affect performance but not functionality\n * Each strategy is responsible for its own error handling\n */\n const strategies = [\n new ChromeCookieQueryStrategy(),\n new FirefoxCookieQueryStrategy(),\n new SafariCookieQueryStrategy(),\n ];\n\n /**\n * Query all strategies in parallel and handle failures gracefully\n * Using Promise.allSettled ensures that failures in one strategy\n * don't prevent results from other strategies\n */\n const results = await Promise.allSettled(\n strategies.map((strategy) => strategy.queryCookies(name, domain)),\n );\n\n /**\n * Filter out failed promises and flatten successful results\n * Using PromiseFulfilledResult<ExportedCookie[]> ensures that only successful results are included\n */\n return results\n .filter(\n (result): result is PromiseFulfilledResult<ExportedCookie[]> =>\n result.status === \"fulfilled\",\n )\n .flatMap((result) => result.value);\n}\n\n/**\n * Default export of the queryCookies function.\n * This is the recommended way to import the function for most use cases.\n * @example\n * ```typescript\n * import queryCookies from './queryCookies';\n *\n * // Query cookies with specific name\n * const sessionCookies = await queryCookies({\n * name: 'sessionId',\n * domain: 'example.com'\n * });\n *\n * // Query all cookies for a domain using wildcard\n * const allCookies = await queryCookies({\n * name: '%',\n * domain: 'example.com'\n * });\n * ```\n */\nexport default queryCookies;\n","import type { CookieSpec, ExportedCookie } from \"../../types/schemas\";\nimport logger from \"../../utils/logger\";\n\nimport { queryCookies } from \"./queryCookies\";\n\n/**\n * Retrieves browser cookies that match the specified cookie name and domain criteria.\n * This function provides a way to search and filter cookies based on given specifications.\n * @param cookieSpec - The cookie specification containing search criteria\n * @param cookieSpec.name - The name of the cookie to search for\n * @param cookieSpec.domain - (optional) The domain to filter cookies by\n * @returns An array of ExportedCookie objects that match the specification\n * @throws Will catch and handle any errors during cookie querying, logging a warning\n * to the console without throwing to the caller\n * @example\n * ```typescript\n * // Get all cookies named \"sessionId\"\n * const cookies = await getCookie({ name: \"sessionId\" });\n * // Returns: [{ name: \"sessionId\", value: \"abc123\", domain: \".example.com\", ... }]\n *\n * // Get cookies named \"userPref\" from specific domain\n * const domainCookies = await getCookie({\n * name: \"userPref\",\n * domain: \"example.com\"\n * });\n * // Returns: [{ name: \"userPref\", value: \"darkMode\", domain: \"example.com\", ... }]\n * ```\n */\nexport async function getCookie(\n cookieSpec: CookieSpec,\n): Promise<ExportedCookie[]> {\n try {\n const cookies = await queryCookies(cookieSpec);\n return cookies;\n } catch (error: unknown) {\n logger.warn(\n \"Error querying cookies:\",\n error instanceof Error ? error.message : String(error),\n );\n return [];\n }\n}\n\n/**\n * Default export of the getCookie function.\n * @example\n * ```typescript\n * import getCookie from './getCookie';\n * const authCookies = await getCookie({\n * name: \"auth-token\",\n * domain: \"api.example.com\"\n * });\n * ```\n */\nexport default getCookie;\n"],"mappings":"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","names":["join","readFileSync","homedir","join","SAFARI_DATE_OFFSET","readNullTerminatedString","buffer","offset","end","decodeCookieHeader","size","dateOffset","timestamp","currentOffset","domain","nextOffset","name","nextOffset2","path","nextOffset3","value","_","decodePage","pageSize","headerLengthOffset","headerLength","cookies","pageEnd","cookie","error","decodeBinaryCookies","cookieDbPath","numPages","pageSizes","pageCookies","SafariCookieQueryStrategy","homeDir","logError","join","cookieDbPath","name","domain","decodeBinaryCookies","cookie","error","queryCookies","cookieSpec","name","domain","strategies","ChromeCookieQueryStrategy","FirefoxCookieQueryStrategy","SafariCookieQueryStrategy","strategy","result","getCookie","cookieSpec","queryCookies","error","logger_default","getCookie_default"]}
@@ -0,0 +1,2 @@
1
+ import{a as l,b as c}from"./chunk-5FUMK7M3.js";import{d as m,f as s}from"./chunk-56Z35D5R.js";import{join as p}from"path";function x(){let o=[],e=process.env.HOME;if(typeof e!="string"||e.length===0)return s("FirefoxCookieQuery","HOME environment variable not set"),o;let a=[p(e,"Library/Application Support/Firefox/Profiles/*/cookies.sqlite"),p(e,".mozilla/firefox/*/cookies.sqlite")];for(let f of a){let i=c(f);o.push(...i)}return m("FirefoxCookieQuery","Found Firefox cookie files",{files:o}),o}var u=class{constructor(){this.browserName="Firefox"}async queryCookies(e,a){let f=x(),i=[];for(let t of f)try{let n=await l({file:t,sql:"SELECT name, value, host as domain, expiry FROM moz_cookies WHERE name = ? AND host LIKE ?",params:[e,`%${a}%`],rowTransform:r=>({name:r.name,value:r.value,domain:r.domain,expiry:r.expiry>0?new Date(r.expiry*1e3):"Infinity",meta:{file:t,browser:"Firefox",decrypted:!1}})});i.push(...n)}catch(n){n instanceof Error?s("FirefoxCookieQuery",`Error reading Firefox cookie file ${t}`,{error:n.message}):s("FirefoxCookieQuery",`Error reading Firefox cookie file ${t}`)}return i}};export{u as a};
2
+ //# sourceMappingURL=chunk-IRERRCUF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/browsers/firefox/FirefoxCookieQueryStrategy.ts"],"sourcesContent":["import { join } from \"path\";\n\nimport { sync } from \"glob\";\n\nimport { logDebug, logWarn } from \"@utils/logHelpers\";\n\nimport {\n BrowserName,\n CookieQueryStrategy,\n ExportedCookie,\n} from \"../../../types/schemas\";\nimport { querySqliteThenTransform } from \"../QuerySqliteThenTransform\";\n\ninterface FirefoxCookieRow {\n name: string;\n value: string;\n domain: string;\n expiry: number;\n}\n\n/**\n * Find all Firefox cookie database files\n * @returns An array of file paths to Firefox cookie databases\n */\nfunction findFirefoxCookieFiles(): string[] {\n const files: string[] = [];\n const homedir = process.env.HOME;\n\n if (typeof homedir !== \"string\" || homedir.length === 0) {\n logWarn(\"FirefoxCookieQuery\", \"HOME environment variable not set\");\n return files;\n }\n\n const patterns = [\n join(\n homedir,\n \"Library/Application Support/Firefox/Profiles/*/cookies.sqlite\",\n ),\n join(homedir, \".mozilla/firefox/*/cookies.sqlite\"),\n ];\n\n for (const pattern of patterns) {\n const matches = sync(pattern);\n files.push(...matches);\n }\n\n logDebug(\"FirefoxCookieQuery\", \"Found Firefox cookie files\", { files });\n return files;\n}\n\n/**\n * Strategy for querying cookies from Firefox browser\n * @example\n */\nexport class FirefoxCookieQueryStrategy implements CookieQueryStrategy {\n /**\n *\n */\n public readonly browserName: BrowserName = \"Firefox\";\n\n /**\n * Queries cookies from Firefox's cookie store\n * @param name - The name pattern to match cookies against\n * @param domain - The domain pattern to match cookies against\n * @returns A promise that resolves to an array of exported cookies\n */\n public async queryCookies(\n name: string,\n domain: string,\n ): Promise<ExportedCookie[]> {\n const files = findFirefoxCookieFiles();\n const results: ExportedCookie[] = [];\n\n for (const file of files) {\n try {\n const cookies = await querySqliteThenTransform<\n FirefoxCookieRow,\n ExportedCookie\n >({\n file,\n sql: \"SELECT name, value, host as domain, expiry FROM moz_cookies WHERE name = ? AND host LIKE ?\",\n params: [name, `%${domain}%`],\n rowTransform: (row) => ({\n name: row.name,\n value: row.value,\n domain: row.domain,\n expiry: row.expiry > 0 ? new Date(row.expiry * 1000) : \"Infinity\",\n meta: {\n file,\n browser: \"Firefox\",\n decrypted: false,\n },\n }),\n });\n\n results.push(...cookies);\n } catch (error) {\n if (error instanceof Error) {\n logWarn(\n \"FirefoxCookieQuery\",\n `Error reading Firefox cookie file ${file}`,\n { error: error.message },\n );\n } else {\n logWarn(\n \"FirefoxCookieQuery\",\n `Error reading Firefox cookie file ${file}`,\n );\n }\n }\n }\n\n return results;\n }\n}\n"],"mappings":"8FAAA,OAAS,QAAAA,MAAY,OAwBrB,SAASC,GAAmC,CAC1C,IAAMC,EAAkB,CAAC,EACnBC,EAAU,QAAQ,IAAI,KAE5B,GAAI,OAAOA,GAAY,UAAYA,EAAQ,SAAW,EACpD,OAAAC,EAAQ,qBAAsB,mCAAmC,EAC1DF,EAGT,IAAMG,EAAW,CACfC,EACEH,EACA,+DACF,EACAG,EAAKH,EAAS,mCAAmC,CACnD,EAEA,QAAWI,KAAWF,EAAU,CAC9B,IAAMG,EAAUC,EAAKF,CAAO,EAC5BL,EAAM,KAAK,GAAGM,CAAO,CACvB,CAEA,OAAAE,EAAS,qBAAsB,6BAA8B,CAAE,MAAAR,CAAM,CAAC,EAC/DA,CACT,CAMO,IAAMS,EAAN,KAAgE,CAAhE,cAIL,KAAgB,YAA2B,UAQ3C,MAAa,aACXC,EACAC,EAC2B,CAC3B,IAAMX,EAAQD,EAAuB,EAC/Ba,EAA4B,CAAC,EAEnC,QAAWC,KAAQb,EACjB,GAAI,CACF,IAAMc,EAAU,MAAMC,EAGpB,CACA,KAAAF,EACA,IAAK,6FACL,OAAQ,CAACH,EAAM,IAAIC,CAAM,GAAG,EAC5B,aAAeK,IAAS,CACtB,KAAMA,EAAI,KACV,MAAOA,EAAI,MACX,OAAQA,EAAI,OACZ,OAAQA,EAAI,OAAS,EAAI,IAAI,KAAKA,EAAI,OAAS,GAAI,EAAI,WACvD,KAAM,CACJ,KAAAH,EACA,QAAS,UACT,UAAW,EACb,CACF,EACF,CAAC,EAEDD,EAAQ,KAAK,GAAGE,CAAO,CACzB,OAASG,EAAO,CACVA,aAAiB,MACnBf,EACE,qBACA,qCAAqCW,CAAI,GACzC,CAAE,MAAOI,EAAM,OAAQ,CACzB,EAEAf,EACE,qBACA,qCAAqCW,CAAI,EAC3C,CAEJ,CAGF,OAAOD,CACT,CACF","names":["join","findFirefoxCookieFiles","files","homedir","logWarn","patterns","join","pattern","matches","sync","logDebug","FirefoxCookieQueryStrategy","name","domain","results","file","cookies","querySqliteThenTransform","row","error"]}
@@ -0,0 +1,2 @@
1
+ import{a as C,b as w}from"./chunk-5FUMK7M3.js";import{a as d,b as h,c as l,d as c,e as y}from"./chunk-56Z35D5R.js";import{existsSync as q}from"fs";import{join as p}from"path";import L from"fast-glob";import{join as D}from"path";import{merge as O}from"lodash-es";var k={};O(k,process.env);var m=k.HOME;if(typeof m!="string"||m.length===0)throw new Error("HOME environment variable is not set or empty");var E,f=D((E=m)!=null?E:"","Library","Application Support","Google","Chrome");function T(r){if(typeof r!="string")return!1;let e=r.trim();return e.length===0?!1:q(e)}async function Q(){let r=[p(f,"Default/Cookies"),p(f,"Profile */Cookies"),p(f,"Profile Default/Cookies")],e=[];for(let t of r){let o=await L(t);e.push(...o)}return c("ChromeCookies","Found cookie files",{count:e.length,files:e}),e}function I(r,e){let t=r==="%",o=t?"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE host_key LIKE ?":"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE name = ? AND host_key LIKE ?",i=t?[`%${e}%`]:[r,`%${e}%`];return{sql:o,params:i}}async function M(r,e,t){try{let{sql:o,params:i}=I(e,t);c("ChromeCookies","Executing query",{sql:o,params:i});let n=await C({file:r,sql:o,params:i,rowTransform:s=>({name:s.name,domain:s.host_key,value:s.encrypted_value,expiry:s.expires_utc})});return h("QueryCookies",!0,{file:r,count:n.length}),n}catch(o){return l("Failed to read cookie file",o,{file:r}),[]}}async function x({name:r,domain:e,file:t}){let o=typeof t=="string"&&t.length>0?[t]:await Q();if(o.length===0)return c("ChromeCookies","No cookie files found"),[];let i=[];for(let n of o){if(!T(n)){c("ChromeCookies","Cookie file missing or invalid",{file:n});continue}let s=await M(n,r,e);i.push(...s)}return c("ChromeCookies","Query complete",{totalCookies:i.length}),i}import{readFileSync as sr}from"fs";import{join as lr}from"path";var N=d.withTag("listChromeProfiles");function P(){let r=w("./**/Cookies",{cwd:f,absolute:!0});return N.debug("Found cookie files:",r),r}import{createDecipheriv as A,pbkdf2 as H}from"crypto";import{memoize as _}from"lodash-es";var $=_(r=>r.length>=3&&r[0]===118&&r[1]===49&&r[2]===48?r.slice(3):r,r=>r.toString("hex")),z=_(r=>{let e=r[r.length-1];return e&&e<=16?r.slice(0,-e):r},r=>r.toString("hex"));function G(r){var t;let e=[/.*?0t(.+)$/,/.*?1e`(.+)$/,/.*?[`'](.+)$/,/[^\x20-\x7E]*([\x20-\x7E].+)$/];for(let o of e){let i=r.match(o),n=(t=i==null?void 0:i[1])!=null?t:"";if(n.length>0)return n}return r}async function S(r,e){if(typeof e!="string")throw new Error("password must be a string");if(!Buffer.isBuffer(r))throw new Error("encryptedData must be a Buffer");return new Promise((t,o)=>{H(e,"saltysalt",1003,16,"sha1",(i,n)=>{try{if(i){o(new Error("Failed to derive key: "+i.message));return}let s=$(r);if(s.length%16!==0){o(new Error("Encrypted data length is not a multiple of 16"));return}let g=Buffer.alloc(16," "),a=A("aes-128-cbc",n,g);a.setAutoPadding(!1);let u=a.update(s);try{a.final()}catch(B){o(new Error("Failed to finalize decryption: "+B.message));return}u=z(u);let R=u.toString("utf8");t(G(R))}catch(s){o(new Error("Decryption failed: "+s.message))}})})}import{memoize as V}from"lodash-es";var v=V(async()=>{if(process.platform!=="darwin")throw l("Chrome password retrieval failed",new Error("This only works on macOS"),{platform:process.platform}),new Error("This only works on macOS");try{let{getChromePassword:r}=await import("./getChromePassword-GTIXL733.js"),e=await r();return c("ChromePassword","Retrieved password successfully",{platform:"macOS"}),e}catch(r){throw l("Chrome password retrieval failed",r,{platform:"macOS"}),r}});function W(r){return typeof r!="number"||r<=0?"Infinity":new Date(r)}function b(r,e,t,o,i,n){return{domain:r,name:e,value:t,expiry:W(o),meta:{file:i,browser:"Chrome",decrypted:n}}}var F=class{constructor(){this.logger=y("ChromeCookieQueryStrategy");this.browserName="Chrome"}async queryCookies(e,t){try{if(this.logger.info("Querying cookies",{name:e,domain:t}),process.platform!=="darwin")return this.logger.warn("Platform not supported",{platform:process.platform}),[];let o=P();if(o.length===0)return this.logger.warn("No Chrome cookie files found"),[];let i=await v();return(await Promise.all(o.map(s=>this.processFile(s,e,t,i)))).flat()}catch(o){return o instanceof Error?l("Failed to query cookies",o,{name:e,domain:t}):l("Failed to query cookies",new Error(String(o)),{name:e,domain:t}),[]}}async processFile(e,t,o,i){try{let n=await x({name:t,domain:o,file:e}),s={file:e,password:i};return(await Promise.allSettled(n.map(a=>this.processCookie(a,s)))).map(a=>a.status==="fulfilled"?a.value:null).filter(a=>a!==null)}catch(n){return n instanceof Error?this.logger.error("Failed to process cookie file",{error:n,file:e}):this.logger.error("Failed to process cookie file",{error:String(n),file:e}),[]}}async processCookie(e,t){try{let o=Buffer.isBuffer(e.value)?e.value:Buffer.from(String(e.value)),i=await S(o,t.password);return b(e.domain,e.name,i,e.expiry,t.file,!0)}catch(o){return o instanceof Error?this.logger.warn("Failed to decrypt cookie",{error:o}):this.logger.warn("Failed to decrypt cookie",{error:String(o)}),b(e.domain,e.name,e.value.toString("utf-8"),e.expiry,t.file,!1)}}};export{F as a};
2
+ //# sourceMappingURL=chunk-UPNW543B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/browsers/getEncryptedChromeCookie.ts","../src/core/browsers/chrome/ChromeApplicationSupport.ts","../src/global.ts","../src/core/browsers/listChromeProfiles.ts","../src/core/browsers/chrome/decrypt.ts","../src/core/browsers/chrome/getChromePassword.ts","../src/core/browsers/chrome/ChromeCookieQueryStrategy.ts"],"sourcesContent":["import { existsSync } from \"fs\";\nimport { join } from \"path\";\n\nimport glob from \"fast-glob\";\n\nimport { logError, logDebug, logOperationResult } from \"@utils/logHelpers\";\n\nimport type { CookieRow } from \"../../types/schemas\";\n\nimport { chromeApplicationSupport } from \"./chrome/ChromeApplicationSupport\";\nimport { querySqliteThenTransform } from \"./QuerySqliteThenTransform\";\n\ninterface ChromeCookieRow {\n encrypted_value: Buffer;\n name: string;\n host_key: string;\n expires_utc: number;\n}\n\ninterface GetEncryptedCookieOptions {\n name: string;\n domain: string;\n file?: string;\n}\n\ninterface SqlQuery {\n sql: string;\n params: string[];\n}\n\n/**\n * Validates if a path is a valid, existing file\n * @param path - Path to validate\n * @returns true if path is valid and file exists, false otherwise\n */\nfunction isValidFilePath(path: unknown): path is string {\n if (typeof path !== \"string\") {\n return false;\n }\n\n const trimmedPath = path.trim();\n if (trimmedPath.length === 0) {\n return false;\n }\n\n return existsSync(trimmedPath);\n}\n\n/**\n * Get paths to Chrome cookie files\n * @returns A promise that resolves to an array of file paths\n */\nasync function getCookieFiles(): Promise<string[]> {\n const patterns = [\n join(chromeApplicationSupport, \"Default/Cookies\"),\n join(chromeApplicationSupport, \"Profile */Cookies\"),\n join(chromeApplicationSupport, \"Profile Default/Cookies\"),\n ];\n\n const files: string[] = [];\n for (const pattern of patterns) {\n const matches = await glob(pattern);\n files.push(...matches);\n }\n\n logDebug(\"ChromeCookies\", \"Found cookie files\", {\n count: files.length,\n files,\n });\n return files;\n}\n\n/**\n * Builds the SQL query for retrieving cookies\n * @param name - Cookie name to search for\n * @param domain - Domain to filter by\n * @returns SQL query and parameters\n */\nfunction buildSqlQuery(name: string, domain: string): SqlQuery {\n const isWildcard = name === \"%\";\n const sql = isWildcard\n ? `SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE host_key LIKE ?`\n : `SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE name = ? AND host_key LIKE ?`;\n const params = isWildcard ? [`%${domain}%`] : [name, `%${domain}%`];\n\n return { sql, params };\n}\n\n/**\n * Processes a single cookie file to extract matching cookies\n * @param cookieFile - Path to the cookie file\n * @param name - Cookie name to search for\n * @param domain - Domain to filter by\n * @returns Array of matching cookies\n */\nasync function processCookieFile(\n cookieFile: string,\n name: string,\n domain: string,\n): Promise<CookieRow[]> {\n try {\n const { sql, params } = buildSqlQuery(name, domain);\n logDebug(\"ChromeCookies\", \"Executing query\", { sql, params });\n\n const rows = await querySqliteThenTransform<ChromeCookieRow, CookieRow>({\n file: cookieFile,\n sql,\n params,\n rowTransform: (row: ChromeCookieRow): CookieRow => ({\n name: row.name,\n domain: row.host_key,\n value: row.encrypted_value,\n expiry: row.expires_utc,\n }),\n });\n\n logOperationResult(\"QueryCookies\", true, {\n file: cookieFile,\n count: rows.length,\n });\n return rows;\n } catch (error) {\n logError(\"Failed to read cookie file\", error, { file: cookieFile });\n return [];\n }\n}\n\n/**\n * Retrieve encrypted cookies from Chrome's cookie store\n * @param options - Options for querying Chrome cookies\n * @param options.name - The name of the cookie to retrieve\n * @param options.domain - The domain to retrieve cookies from\n * @param options.file - Optional specific cookie file to query\n * @returns Promise resolving to array of encrypted cookies\n */\nexport async function getEncryptedChromeCookie({\n name,\n domain,\n file,\n}: GetEncryptedCookieOptions): Promise<CookieRow[]> {\n const cookieFiles =\n typeof file === \"string\" && file.length > 0\n ? [file]\n : await getCookieFiles();\n\n if (cookieFiles.length === 0) {\n logDebug(\"ChromeCookies\", \"No cookie files found\");\n return [];\n }\n\n const results: CookieRow[] = [];\n for (const cookieFile of cookieFiles) {\n if (!isValidFilePath(cookieFile)) {\n logDebug(\"ChromeCookies\", \"Cookie file missing or invalid\", {\n file: cookieFile,\n });\n continue;\n }\n\n const cookies = await processCookieFile(cookieFile, name, domain);\n results.push(...cookies);\n }\n\n logDebug(\"ChromeCookies\", \"Query complete\", { totalCookies: results.length });\n return results;\n}\n","import { join } from \"path\";\n\nimport { HOME } from \"../../../global\";\n\n/**\n * The path to Chrome's application support directory on macOS\n * This constant is used to locate Chrome's profile and cookie storage directories\n * @example\n */\nexport const chromeApplicationSupport = join(\n HOME ?? \"\",\n \"Library\",\n \"Application Support\",\n \"Google\",\n \"Chrome\",\n);\n","import { merge } from \"lodash-es\";\n\n/**\n * Global environment variables object that merges with process.env\n * @example\n * // Access environment variables\n * const nodeEnv = env.NODE_ENV; // 'development'\n * const apiKey = env.API_KEY; // 'abc123'\n *\n * // Check if variable exists\n * if (env.DATABASE_URL) {\n * // Use database URL\n * }\n *\n * // Add new environment variables\n * env.CUSTOM_VAR = 'my-value';\n */\nexport const env: { [key: string]: string | undefined } = {};\nmerge(env, process.env);\n\n/**\n * User's home directory path from environment variables\n * @throws Error if HOME environment variable is not set\n * @example\n * // Access home directory path\n * const homePath = HOME; // '/home/username' or 'C:\\Users\\username'\n *\n * // Use in file path construction\n * const configPath = `${homePath}/.config/app`;\n *\n * // Error handling\n * if (typeof homePath === 'string' && homePath.length > 0) {\n * // Use home path\n * } else {\n * throw new Error('HOME environment variable is not set or empty');\n * }\n */\nexport const HOME: string | undefined = env[\"HOME\"];\nif (typeof HOME !== \"string\" || HOME.length === 0) {\n throw new Error(\"HOME environment variable is not set or empty\");\n}\n","// External imports\nimport { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\nimport { sync } from \"glob\";\n\n// Internal imports\nimport logger from \"@utils/logger\";\n\nimport { chromeApplicationSupport } from \"./chrome/ChromeApplicationSupport\";\n\nconst consola = logger.withTag(\"listChromeProfiles\");\n\n/**\n * Lists all Chrome profile paths that contain cookie files\n * @internal\n * @returns An array of absolute paths to Chrome cookie files\n * @throws {Error} If Chrome's application support directory cannot be accessed\n * @example\n * ```typescript\n * // Get all Chrome cookie file paths\n * const cookiePaths = listChromeProfilePaths();\n * // Returns: [\n * // '/Users/name/Library/Application Support/Chrome/Profile 1/Cookies',\n * // '/Users/name/Library/Application Support/Chrome/Profile 2/Cookies'\n * // ]\n *\n * // Handle errors\n * try {\n * const paths = listChromeProfilePaths();\n * } catch (error) {\n * console.error('Failed to access Chrome profiles:', error);\n * }\n * ```\n */\nexport function listChromeProfilePaths(): string[] {\n const files: string[] = sync(`./**/Cookies`, {\n cwd: chromeApplicationSupport,\n absolute: true,\n });\n\n consola.debug(\"Found cookie files:\", files);\n return files;\n}\n\n/**\n * Chrome Local State file structure\n * @internal\n */\ninterface ChromeLocalState {\n profile: {\n info_cache: Record<string, ChromeProfileInfo>;\n };\n}\n\n/**\n * Chrome profile information structure\n * @property {string} name - The name of the profile\n * @property {number} active_time - Unix timestamp of last profile activity\n * @property {string} account_id - Unique identifier for the Chrome profile\n * @property {Record<string, unknown>} accountcapabilities - Account feature flags\n * @property {string} email - User's email address\n * @property {string} full_name - User's full name\n * @property {boolean} is_using_default_avatar - Whether using default profile picture\n * @property {boolean} is_using_default_name - Whether using default profile name\n * @property {string} last_downloaded_gaia_picture_url_with_size - Profile picture URL\n * @property {string} local_auth_credentials - Authentication credentials\n * @property {string} shortcut_name - Profile shortcut name\n * @property {string} user_name - Username associated with profile\n */\ninterface ChromeProfileInfo {\n /** The name of the profile */\n name: string;\n /** Unix timestamp of last profile activity */\n active_time: number;\n /** Unique identifier for the Chrome profile */\n account_id: string;\n /** Account feature flags */\n accountcapabilities: Record<string, unknown>;\n /** User's email address */\n email: string;\n /** User's full name */\n full_name: string;\n /** Whether using default profile picture */\n is_using_default_avatar: boolean;\n /** Whether using default profile name */\n is_using_default_name: boolean;\n /** Profile picture URL */\n last_downloaded_gaia_picture_url_with_size: string;\n /** Authentication credentials */\n local_auth_credentials: string;\n /** Profile shortcut name */\n shortcut_name: string;\n /** Username associated with profile */\n user_name: string;\n}\n\n/**\n * Lists all Chrome profiles and their associated information\n * @internal\n * @returns An array of Chrome profile information objects. Returns empty array if profiles cannot be read\n * @throws {Error} If Chrome's application support directory cannot be accessed\n * @example\n * ```typescript\n * // Get all Chrome profiles\n * const profiles = listChromeProfiles();\n * // Returns: [\n * // {\n * // name: \"Default\",\n * // email: \"user@example.com\",\n * // full_name: \"John Doe\",\n * // ...\n * // },\n * // ...\n * // ]\n *\n * // Handle empty or error case\n * const profiles = listChromeProfiles();\n * if (profiles.length === 0) {\n * console.log('No Chrome profiles found or error occurred');\n * }\n * ```\n */\nexport function listChromeProfiles(): ChromeProfileInfo[] {\n try {\n const localStatePath = join(chromeApplicationSupport, \"Local State\");\n const localState = JSON.parse(\n readFileSync(localStatePath, \"utf8\"),\n ) as ChromeLocalState;\n return Object.values(localState.profile.info_cache);\n } catch (error) {\n if (error instanceof Error) {\n consola.error(\"Failed to read Chrome profiles:\", error.message);\n } else {\n consola.error(\"Failed to read Chrome profiles: Unknown error\");\n }\n return [];\n }\n}\n","// External imports\nimport { createDecipheriv, pbkdf2 } from \"crypto\";\n\nimport { memoize } from \"lodash-es\";\n\n/**\n * Removes the v10 prefix from the encrypted value if present\n * @param value - The encrypted value\n * @returns The value without the v10 prefix\n */\nconst removeV10Prefix = memoize(\n (value: Buffer): Buffer => {\n if (\n value.length >= 3 &&\n value[0] === 0x76 && // 'v'\n value[1] === 0x31 && // '1'\n value[2] === 0x30\n ) {\n // '0'\n return value.slice(3);\n }\n return value;\n },\n (value: Buffer) => value.toString(\"hex\"),\n);\n\n/**\n * Removes PKCS7 padding from the decrypted value\n * @param decrypted - The decrypted buffer\n * @returns The buffer without padding\n */\nconst removePadding = memoize(\n (decrypted: Buffer): Buffer => {\n const padding = decrypted[decrypted.length - 1];\n if (padding && padding <= 16) {\n return decrypted.slice(0, -padding);\n }\n return decrypted;\n },\n (decrypted: Buffer) => decrypted.toString(\"hex\"),\n);\n\n/**\n * Extracts the actual value from the decoded string by removing Chrome's prefixes\n * @param decodedString - The decoded string to clean up\n * @returns The cleaned up value\n */\nfunction extractValue(decodedString: string): string {\n const cleanupPatterns = [\n /.*?0t(.+)$/, // Pattern ending in \"0t\" followed by value\n /.*?1e`(.+)$/, // Pattern ending in \"1e`\" followed by value\n /.*?[`'](.+)$/, // Any backtick or quote followed by value\n /[^\\x20-\\x7E]*([\\x20-\\x7E].+)$/, // Non-printable chars followed by printable chars\n ];\n\n for (const pattern of cleanupPatterns) {\n const match = decodedString.match(pattern);\n const value = match?.[1] ?? \"\";\n if (value.length > 0) {\n return value;\n }\n }\n return decodedString;\n}\n\n/**\n * Decrypts Chrome's encrypted cookie values\n * @param encryptedValue - The encrypted cookie value as a Buffer\n * @param password - The Chrome encryption password\n * @returns A promise that resolves to the decrypted cookie value\n * @throws {Error} If decryption fails\n * @example\n */\nexport async function decrypt(\n encryptedValue: Buffer,\n password: string,\n): Promise<string> {\n if (typeof password !== \"string\") {\n throw new Error(\"password must be a string\");\n }\n if (!Buffer.isBuffer(encryptedValue)) {\n throw new Error(\"encryptedData must be a Buffer\");\n }\n\n return new Promise((resolve, reject) => {\n pbkdf2(password, \"saltysalt\", 1003, 16, \"sha1\", (error, key) => {\n try {\n if (error) {\n reject(new Error(\"Failed to derive key: \" + error.message));\n return;\n }\n\n const value = removeV10Prefix(encryptedValue);\n if (value.length % 16 !== 0) {\n reject(new Error(\"Encrypted data length is not a multiple of 16\"));\n return;\n }\n\n // Chrome's encryption parameters\n const iv = Buffer.alloc(16, \" \"); // 16 spaces\n const decipher = createDecipheriv(\"aes-128-cbc\", key, iv);\n decipher.setAutoPadding(false);\n\n // Decrypt the value\n let decrypted = decipher.update(value);\n try {\n decipher.final();\n } catch (e) {\n reject(\n new Error(\"Failed to finalize decryption: \" + (e as Error).message),\n );\n return;\n }\n\n decrypted = removePadding(decrypted);\n const decodedString = decrypted.toString(\"utf8\");\n resolve(extractValue(decodedString));\n } catch (e) {\n reject(new Error(\"Decryption failed: \" + (e as Error).message));\n }\n });\n });\n}\n","import { memoize } from \"lodash-es\";\n\nimport { logError, logDebug } from \"@utils/logHelpers\";\n\n/**\n * Retrieves the Chrome password for decrypting cookies\n * This is only supported on macOS\n * @returns A promise that resolves to the Chrome password\n * @throws {Error} If the platform is not macOS or if password retrieval fails\n * @example\n */\nexport const getChromePassword: () => Promise<string> = memoize(async () => {\n if (process.platform !== \"darwin\") {\n logError(\n \"Chrome password retrieval failed\",\n new Error(\"This only works on macOS\"),\n {\n platform: process.platform,\n },\n );\n throw new Error(\"This only works on macOS\");\n }\n\n try {\n const { getChromePassword: getMacOSPassword } = await import(\n \"./macos/getChromePassword\"\n );\n const password = await getMacOSPassword();\n logDebug(\"ChromePassword\", \"Retrieved password successfully\", {\n platform: \"macOS\",\n });\n return password;\n } catch (error) {\n logError(\"Chrome password retrieval failed\", error, { platform: \"macOS\" });\n throw error;\n }\n});\n","import { createTaggedLogger, logError } from \"@utils/logHelpers\";\n\nimport {\n BrowserName,\n CookieQueryStrategy,\n CookieRow,\n ExportedCookie,\n} from \"../../../types/schemas\";\nimport { getEncryptedChromeCookie } from \"../getEncryptedChromeCookie\";\nimport { listChromeProfilePaths } from \"../listChromeProfiles\";\n\nimport { decrypt } from \"./decrypt\";\nimport { getChromePassword } from \"./getChromePassword\";\n\ninterface DecryptionContext {\n file: string;\n password: string;\n}\n\nfunction getExpiryDate(expiry: number | undefined | null): Date | \"Infinity\" {\n if (typeof expiry !== \"number\" || expiry <= 0) {\n return \"Infinity\";\n }\n return new Date(expiry);\n}\n\nfunction createExportedCookie(\n domain: string,\n name: string,\n value: string,\n expiry: number | undefined | null,\n file: string,\n decrypted: boolean,\n): ExportedCookie {\n return {\n domain,\n name,\n value,\n expiry: getExpiryDate(expiry),\n meta: {\n file,\n browser: \"Chrome\",\n decrypted,\n },\n };\n}\n\n/**\n * Strategy for querying cookies from Chrome browser\n * @example\n * ```typescript\n * const strategy = new ChromeCookieQueryStrategy();\n * const cookies = await strategy.queryCookies('session', 'example.com');\n * ```\n */\nexport class ChromeCookieQueryStrategy implements CookieQueryStrategy {\n private readonly logger = createTaggedLogger(\"ChromeCookieQueryStrategy\");\n\n /**\n * The browser name for this strategy\n */\n public readonly browserName: BrowserName = \"Chrome\";\n\n /**\n * Queries cookies from Chrome's cookie store\n * @param name - The name pattern to match cookies against\n * @param domain - The domain pattern to match cookies against\n * @returns A promise that resolves to an array of exported cookies\n * @example\n * ```typescript\n * const strategy = new ChromeCookieQueryStrategy();\n * const cookies = await strategy.queryCookies('session', 'example.com');\n * console.log(cookies);\n * ```\n */\n public async queryCookies(\n name: string,\n domain: string,\n ): Promise<ExportedCookie[]> {\n try {\n this.logger.info(\"Querying cookies\", { name, domain });\n\n if (process.platform !== \"darwin\") {\n this.logger.warn(\"Platform not supported\", {\n platform: process.platform,\n });\n return [];\n }\n\n const cookieFiles = listChromeProfilePaths();\n if (cookieFiles.length === 0) {\n this.logger.warn(\"No Chrome cookie files found\");\n return [];\n }\n\n const password = await getChromePassword();\n const results = await Promise.all(\n cookieFiles.map((file) =>\n this.processFile(file, name, domain, password),\n ),\n );\n\n return results.flat();\n } catch (error) {\n if (error instanceof Error) {\n logError(\"Failed to query cookies\", error, { name, domain });\n } else {\n logError(\"Failed to query cookies\", new Error(String(error)), {\n name,\n domain,\n });\n }\n return [];\n }\n }\n\n private async processFile(\n file: string,\n name: string,\n domain: string,\n password: string,\n ): Promise<ExportedCookie[]> {\n try {\n const encryptedCookies = await getEncryptedChromeCookie({\n name,\n domain,\n file,\n });\n\n const context: DecryptionContext = { file, password };\n const results = await Promise.allSettled(\n encryptedCookies.map((cookie) => this.processCookie(cookie, context)),\n );\n\n return results\n .map((result) => (result.status === \"fulfilled\" ? result.value : null))\n .filter((cookie): cookie is ExportedCookie => cookie !== null);\n } catch (error) {\n if (error instanceof Error) {\n this.logger.error(\"Failed to process cookie file\", { error, file });\n } else {\n this.logger.error(\"Failed to process cookie file\", {\n error: String(error),\n file,\n });\n }\n return [];\n }\n }\n\n private async processCookie(\n cookie: CookieRow,\n context: DecryptionContext,\n ): Promise<ExportedCookie> {\n try {\n const value = Buffer.isBuffer(cookie.value)\n ? cookie.value\n : Buffer.from(String(cookie.value));\n\n const decryptedValue = await decrypt(value, context.password);\n return createExportedCookie(\n cookie.domain,\n cookie.name,\n decryptedValue,\n cookie.expiry,\n context.file,\n true,\n );\n } catch (error) {\n if (error instanceof Error) {\n this.logger.warn(\"Failed to decrypt cookie\", { error });\n } else {\n this.logger.warn(\"Failed to decrypt cookie\", { error: String(error) });\n }\n return createExportedCookie(\n cookie.domain,\n cookie.name,\n cookie.value.toString(\"utf-8\"),\n cookie.expiry,\n context.file,\n false,\n );\n }\n }\n}\n"],"mappings":"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","names":["existsSync","join","glob","join","merge","env","HOME","_a","chromeApplicationSupport","join","HOME","isValidFilePath","path","trimmedPath","existsSync","getCookieFiles","patterns","join","chromeApplicationSupport","files","pattern","matches","glob","logDebug","buildSqlQuery","name","domain","isWildcard","sql","params","processCookieFile","cookieFile","rows","querySqliteThenTransform","row","logOperationResult","error","logError","getEncryptedChromeCookie","file","cookieFiles","results","cookies","readFileSync","join","consola","logger_default","listChromeProfilePaths","files","sync","chromeApplicationSupport","createDecipheriv","pbkdf2","memoize","removeV10Prefix","value","removePadding","decrypted","padding","extractValue","decodedString","_a","cleanupPatterns","pattern","match","decrypt","encryptedValue","password","resolve","reject","error","key","iv","decipher","e","memoize","getChromePassword","memoize","logError","getMacOSPassword","password","logDebug","error","getExpiryDate","expiry","createExportedCookie","domain","name","value","file","decrypted","ChromeCookieQueryStrategy","createTaggedLogger","cookieFiles","listChromeProfilePaths","password","getChromePassword","error","logError","encryptedCookies","getEncryptedChromeCookie","context","cookie","result","decryptedValue","decrypt"]}