@mherod/get-cookie 2.0.0-rc.30 → 2.0.0-rc.32

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "2.0.0-rc.30",
3
+ "version": "2.0.0-rc.32",
4
4
  "description": "Node.js module for querying a local user's Chrome cookie",
5
5
  "source": "src/index.ts",
6
6
  "bin": "dist/cli.js",
@@ -14,6 +14,7 @@
14
14
  "clean": "git clean -fdX && rm -rf dist && yarn install",
15
15
  "lintfix": "prettier --write \"src/**/*.ts\"",
16
16
  "prebuild": "npm run lintfix",
17
+ "tsc": "tsc",
17
18
  "build": "parcel build --no-cache",
18
19
  "prepare": "parcel build --no-cache",
19
20
  "test": "jest",
@@ -61,7 +62,6 @@
61
62
  "author": "Matthew Herod",
62
63
  "license": "ISC",
63
64
  "dependencies": {
64
- "colorette": "2.0.20",
65
65
  "consola": "3.2.3",
66
66
  "cross-fetch": "^4.0.0",
67
67
  "destr": "2.0.2",
@@ -72,23 +72,31 @@
72
72
  "lru-cache": "^7.14.0",
73
73
  "minimist": "^1.2.7",
74
74
  "sqlite3": "^5.1.6",
75
- "tough-cookie": "^4.1.2",
76
- "user-agents": "^1.0.1178"
75
+ "tough-cookie": "^4.1.2"
77
76
  },
78
77
  "devDependencies": {
78
+ "@jest/globals": "^29.7.0",
79
79
  "@mapbox/node-pre-gyp": "^1.0.11",
80
80
  "@parcel/packager-ts": "^2.10.1",
81
81
  "@parcel/transformer-typescript-tsc": "^2.10.1",
82
82
  "@parcel/transformer-typescript-types": "^2.10.1",
83
+ "@types/jest": "^29.5.6",
83
84
  "@types/jsonwebtoken": "^8.5.9",
84
85
  "@types/lodash": "^4.14.186",
85
86
  "@types/minimist": "^1.2.2",
86
87
  "@types/node": "^18.11.4",
87
88
  "@types/tough-cookie": "^4.0.2",
88
89
  "@types/user-agents": "^1.0.2",
90
+ "jest": "^29.7.0",
89
91
  "parcel": "^2.10.1",
90
- "prettier": "^2.8.1",
92
+ "prettier": "^3.0.3",
93
+ "ts-jest": "^29.1.1",
91
94
  "ts-node": "^10.9.1",
92
- "typescript": "^5.2.2"
95
+ "typescript": "^5.1.6"
96
+ },
97
+ "parcelDependencies": {
98
+ "@parcel/transformer-typescript-tsc": "^2.10.1",
99
+ "@parcel/transformer-typescript-types": "^2.10.1",
100
+ "@parcel/packager-ts": "^2.10.1"
93
101
  }
94
102
  }
@@ -12,7 +12,7 @@ async function getCookieStore(): Promise<Store> {
12
12
  }
13
13
  const fileCookieStore = new FileCookieStore(
14
14
  `${env["HOME"]}/cookie-star.json`,
15
- memoryCookieStore
15
+ memoryCookieStore,
16
16
  );
17
17
  await fileCookieStore.waitUntilIdle();
18
18
  return fileCookieStore;
@@ -1,7 +1,6 @@
1
1
  // noinspection JSUnusedGlobalSymbols
2
- import type { Response } from "cross-fetch";
3
2
 
4
- export default interface FetchResponse extends Response {
3
+ export default interface FetchResponse {
5
4
  status: number;
6
5
  statusText: string;
7
6
  headers: Headers;
@@ -15,7 +15,7 @@ export class FileCookieStore extends Store {
15
15
 
16
16
  constructor(
17
17
  filePath: string,
18
- internalStore: Store = new MemoryCookieStore()
18
+ internalStore: Store = new MemoryCookieStore(),
19
19
  ) {
20
20
  super();
21
21
 
@@ -25,7 +25,10 @@ export class FileCookieStore extends Store {
25
25
  logger.debug("Importing cookies from", filePath, internalStore);
26
26
 
27
27
  this.tasks.push(
28
- this.importSaved(filePath, internalStore).then(console.log, console.error)
28
+ this.importSaved(filePath, internalStore).then(
29
+ console.log,
30
+ console.error,
31
+ ),
29
32
  );
30
33
  }
31
34
 
@@ -47,7 +50,7 @@ export class FileCookieStore extends Store {
47
50
  if (fromJSON) {
48
51
  return this.putCookieInternal(fromJSON, store);
49
52
  }
50
- })
53
+ }),
51
54
  );
52
55
  cookies.push(...put);
53
56
  }
@@ -58,7 +61,7 @@ export class FileCookieStore extends Store {
58
61
  domain: string,
59
62
  path: string,
60
63
  key: string,
61
- cb: (err: Error | null, cookie: Cookie | null) => void
64
+ cb: (err: Error | null, cookie: Cookie | null) => void,
62
65
  ) {
63
66
  this.waitUntilIdle().finally(() => {
64
67
  this.internalStore.findCookie(domain, path, key, cb);
@@ -69,7 +72,7 @@ export class FileCookieStore extends Store {
69
72
  domain: string,
70
73
  path: string,
71
74
  allowSpecialUseDomain: boolean,
72
- cb: (err: Error | null, cookie: Cookie[]) => void
75
+ cb: (err: Error | null, cookie: Cookie[]) => void,
73
76
  ) {
74
77
  this.waitUntilIdle().finally(() => {
75
78
  this.internalStore.findCookies(domain, path, allowSpecialUseDomain, cb);
@@ -86,7 +89,7 @@ export class FileCookieStore extends Store {
86
89
  updateCookie(
87
90
  oldCookie: Cookie,
88
91
  newCookie: Cookie,
89
- cb: (err: Error | null) => void
92
+ cb: (err: Error | null) => void,
90
93
  ) {
91
94
  this.internalStore.updateCookie(oldCookie, newCookie, cb);
92
95
  this.internalStore.getAllCookies((err, cookies) => {
@@ -98,7 +101,7 @@ export class FileCookieStore extends Store {
98
101
  domain: string,
99
102
  path: string,
100
103
  key: string,
101
- cb: (err: Error | null) => void
104
+ cb: (err: Error | null) => void,
102
105
  ) {
103
106
  this.internalStore.removeCookie(domain, path, key, cb);
104
107
  this.internalStore.getAllCookies((err, cookies) => {
@@ -125,13 +128,13 @@ export class FileCookieStore extends Store {
125
128
 
126
129
  private async putCookieInternal(
127
130
  cookie: Cookie,
128
- store: Store
131
+ store: Store,
129
132
  ): Promise<Cookie> {
130
133
  await this.waitUntilIdle();
131
134
  return await new Promise<Cookie>(
132
135
  (
133
136
  resolve: (value: PromiseLike<Cookie> | Cookie) => void,
134
- reject: (reason?: any) => void
137
+ reject: (reason?: any) => void,
135
138
  ) => {
136
139
  store.putCookie(cookie, (err: Error | null) => {
137
140
  if (err) {
@@ -140,7 +143,7 @@ export class FileCookieStore extends Store {
140
143
  resolve(cookie);
141
144
  }
142
145
  });
143
- }
146
+ },
144
147
  );
145
148
  }
146
149
 
@@ -6,5 +6,5 @@ export const chromeApplicationSupport: string = join(
6
6
  "Library",
7
7
  "Application Support",
8
8
  "Google",
9
- "Chrome"
9
+ "Chrome",
10
10
  );
@@ -37,7 +37,7 @@ export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
37
37
  async function getPromise1(
38
38
  name: string,
39
39
  domain: string,
40
- file: string
40
+ file: string,
41
41
  ): Promise<CookieRow[]> {
42
42
  try {
43
43
  return await getEncryptedChromeCookie({
@@ -60,7 +60,7 @@ async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
60
60
  name: "Cookies",
61
61
  });
62
62
  const promises: Promise<CookieRow[]>[] = files.map((file) =>
63
- getPromise1(name, domain, file)
63
+ getPromise1(name, domain, file),
64
64
  );
65
65
  const results1: CookieRow[][] = await Promise.all(promises);
66
66
  return results1.flat().filter(isCookieRow);
@@ -124,7 +124,7 @@ Promise<ExportedCookie[]> {
124
124
  return exportedCookie;
125
125
  });
126
126
  const results: ExportedCookie[] = (await Promise.all(decrypted)).filter(
127
- isExportedCookie
127
+ isExportedCookie,
128
128
  );
129
129
  if (parsedArgs.verbose) {
130
130
  console.log("results", results);
@@ -148,7 +148,7 @@ async function getEncryptedChromeCookie({
148
148
  if (parsedArgs.verbose) {
149
149
  const s = file.split("/").slice(-3).join("/");
150
150
  consola.start(
151
- `Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`
151
+ `Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`,
152
152
  );
153
153
  }
154
154
  let sql;
@@ -4,15 +4,16 @@ import SafariCookieQueryStrategy from "./SafariCookieQueryStrategy";
4
4
  import CookieQueryStrategy from "./CookieQueryStrategy";
5
5
  import ExportedCookie from "../ExportedCookie";
6
6
  import LRUCache from "lru-cache";
7
- import { red } from "colorette";
8
7
  import { merge } from "lodash";
9
8
  import { parsedArgs } from "../argv";
9
+ import consola from "consola";
10
+ import { flatMapAsync } from "../util/flatMapAsync";
10
11
 
11
12
  const cache: LRUCache<string, ExportedCookie[]> = new LRUCache<
12
13
  string,
13
14
  ExportedCookie[]
14
15
  >({
15
- ttl: 1000 * 10,
16
+ ttl: 1000 * 10, // 10 seconds
16
17
  max: 10,
17
18
  });
18
19
 
@@ -21,10 +22,10 @@ export default class CompositeCookieQueryStrategy
21
22
  {
22
23
  browserName = "all";
23
24
 
24
- #strategies;
25
+ private readonly strategies;
25
26
 
26
27
  constructor() {
27
- this.#strategies = [
28
+ this.strategies = [
28
29
  // CookieStoreQueryStrategy,
29
30
  ChromeCookieQueryStrategy,
30
31
  FirefoxCookieQueryStrategy,
@@ -37,38 +38,33 @@ export default class CompositeCookieQueryStrategy
37
38
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
38
39
  // domain = domain.match(/(\w+.+\w+)/gi)?.pop() ?? domain;
39
40
  const key = `${name}:${domain}`;
40
- const cached = cache.get(key);
41
- if (cached) {
42
- return cached;
41
+ if (cache.has(key)) {
42
+ const cached = cache.get(key);
43
+ if (cached) {
44
+ return cached;
45
+ }
43
46
  }
44
47
  if (parsedArgs.verbose) {
45
- console.log("Querying cookies:", name, domain);
48
+ consola.log("Querying cookies:", name, domain);
46
49
  }
47
- const results: ExportedCookie[][] = await Promise.all(
48
- this.#strategies.map(async (strategy: CookieQueryStrategy) => {
49
- // @ts-ignore
50
- return strategy
51
- .queryCookies(name, domain)
52
- .then((cookies: ExportedCookie[]) => {
53
- return cookies.map((cookie: ExportedCookie) => {
54
- return merge(cookie, {
55
- meta: {
56
- browser: strategy.browserName,
57
- },
58
- });
50
+ const results = await flatMapAsync(this.strategies, async (strategy) => {
51
+ return strategy
52
+ .queryCookies(name, domain)
53
+ .then((cookies: ExportedCookie[]) => {
54
+ return cookies.map((cookie: ExportedCookie) => {
55
+ return merge(cookie, {
56
+ meta: {
57
+ browser: strategy.browserName,
58
+ },
59
59
  });
60
- })
61
- .catch((e) => {
62
- console.log(
63
- red(`Error querying ${strategy.browserName} cookies`),
64
- e
65
- );
66
- return [];
67
60
  });
68
- })
69
- );
70
- const flat: ExportedCookie[] = results.flat();
71
- cache.set(`${name}:${domain}`, flat);
72
- return flat;
61
+ })
62
+ .catch((e) => {
63
+ consola.error(`Error querying ${strategy.browserName} cookies`, e);
64
+ return [];
65
+ });
66
+ });
67
+ cache.set(`${name}:${domain}`, results);
68
+ return results;
73
69
  }
74
70
  }
@@ -77,7 +77,7 @@ export default class CookieStoreQueryStrategy implements CookieQueryStrategy {
77
77
  } else {
78
78
  resolve(cookies ?? []);
79
79
  }
80
- }
80
+ },
81
81
  );
82
82
  });
83
83
  }
@@ -92,7 +92,7 @@ export default class CookieStoreQueryStrategy implements CookieQueryStrategy {
92
92
  } else {
93
93
  resolve(cookies ?? []);
94
94
  }
95
- }
95
+ },
96
96
  );
97
97
  });
98
98
  }
@@ -27,7 +27,7 @@ function transformRows(
27
27
  rows: any[],
28
28
  rowFilter: (row: any) => boolean,
29
29
  rowTransform: (row: any) => CookieRow,
30
- file: string
30
+ file: string,
31
31
  //
32
32
  ): CookieRow[] {
33
33
  return rows.filter(rowFilter).map((row: any) => {
@@ -51,7 +51,7 @@ export async function doSqliteQueryWithTransform(
51
51
  sql,
52
52
  rowFilter = () => true,
53
53
  rowTransform,
54
- }: DoSqliteQueryWithTransformOptions
54
+ }: DoSqliteQueryWithTransformOptions,
55
55
  ): //
56
56
  Promise<CookieRow[]> {
57
57
  checkFileExistence(file);
@@ -72,7 +72,7 @@ Promise<CookieRow[]> {
72
72
  rows,
73
73
  rowFilter,
74
74
  rowTransform,
75
- file
75
+ file,
76
76
  );
77
77
 
78
78
  if (parsedArgs.verbose) {
@@ -36,7 +36,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
36
36
  }
37
37
 
38
38
  async #getFirefoxCookie(
39
- { name, domain }: CookieSpec //
39
+ { name, domain }: CookieSpec, //
40
40
  ) {
41
41
  const files: string[] = findAllFiles({
42
42
  path: path.join(
@@ -44,7 +44,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
44
44
  "Library",
45
45
  "Application Support",
46
46
  "Firefox",
47
- "Profiles"
47
+ "Profiles",
48
48
  ),
49
49
  name: "cookies.sqlite",
50
50
  });
@@ -59,7 +59,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
59
59
  async #queryCookiesDb(
60
60
  file: string,
61
61
  name: string,
62
- domain: string
62
+ domain: string,
63
63
  ): Promise<CookieRow[]> {
64
64
  if (file && !existsSync(file)) {
65
65
  throw new Error(`File ${file} does not exist`);
@@ -5,7 +5,7 @@ import consola from "consola";
5
5
  // Function to decrypt encrypted data using a password
6
6
  export async function decrypt(
7
7
  password: BinaryLike, // The password to use for decryption
8
- encryptedData: Buffer // The data to decrypt
8
+ encryptedData: Buffer, // The data to decrypt
9
9
  ): Promise<string> {
10
10
  // Returns a promise that resolves with the decrypted string
11
11
  // Check if password is a string
@@ -25,7 +25,7 @@ export async function decrypt(
25
25
  // Log if encryptedData is an array of buffers
26
26
  if (parsedArgs.verbose) {
27
27
  console.log(
28
- `encryptedData is an array of buffers, selected first: ${encryptedData1}`
28
+ `encryptedData is an array of buffers, selected first: ${encryptedData1}`,
29
29
  );
30
30
  }
31
31
  } else {
@@ -56,7 +56,7 @@ export async function decrypt(
56
56
  if (parsedArgs.verbose) {
57
57
  console.log(
58
58
  "Error doing pbkdf2, buffer length is not 16",
59
- buffer.length
59
+ buffer.length,
60
60
  );
61
61
  }
62
62
  reject(new Error("Buffer length is not 16"));
@@ -80,7 +80,7 @@ export async function decrypt(
80
80
  if (parsedArgs.verbose) {
81
81
  console.log(
82
82
  "Error doing pbkdf2, encryptedData length is not a multiple of 16",
83
- encryptedData1.length
83
+ encryptedData1.length,
84
84
  );
85
85
  }
86
86
  reject(new Error("encryptedData length is not a multiple of 16"));
@@ -1,7 +1,7 @@
1
1
  import { execSimple } from "../execSimple";
2
2
 
3
3
  const chromePassword: Promise<string> = execSimple(
4
- 'security find-generic-password -w -s "Chrome Safe Storage"'
4
+ 'security find-generic-password -w -s "Chrome Safe Storage"',
5
5
  );
6
6
 
7
7
  export async function getChromePassword(): Promise<string> {
package/src/cli.ts CHANGED
@@ -1,55 +1,12 @@
1
1
  #!/usr/bin/env ts-node
2
2
 
3
3
  import { argv, parsedArgs } from "./argv";
4
- import { groupBy } from "lodash";
5
- import { green, red, yellow } from "colorette";
6
- import { resultsRendered } from "./resultsRendered";
7
4
  import { fetchWithCookies } from "./fetchWithCookies";
8
5
  import { unpackHeaders } from "./unpackHeaders";
9
6
  import CookieSpec from "./CookieSpec";
10
- import { comboQueryCookieSpec } from "./comboQueryCookieSpec";
11
7
  import { cookieSpecsFromUrl } from "./cookieSpecsFromUrl";
12
8
  import logger from "./logger";
13
-
14
- async function cliQueryCookies(cookieSpec: CookieSpec | CookieSpec[]) {
15
- try {
16
- const results = await comboQueryCookieSpec(cookieSpec);
17
- if (results == null || results.length == 0) {
18
- logger.error(red("No results"));
19
- return;
20
- }
21
- if (parsedArgs["dump"] || parsedArgs["d"]) {
22
- logger.log(results);
23
- return;
24
- }
25
- if (parsedArgs["dump-grouped"] || parsedArgs["D"]) {
26
- const groupedByFile = groupBy(results, (r) => r.meta?.file);
27
- logger.log(green(JSON.stringify(groupedByFile, null, 2)));
28
- return;
29
- }
30
- if (
31
- parsedArgs["render"] ||
32
- parsedArgs["render-merged"] ||
33
- parsedArgs["r"]
34
- ) {
35
- logger.log(yellow(resultsRendered(results)));
36
- return;
37
- }
38
- if (parsedArgs["render-grouped"] || parsedArgs["R"]) {
39
- const groupedByFile = groupBy(results, (r) => r.meta?.file);
40
- for (const file of Object.keys(groupedByFile)) {
41
- let results = groupedByFile[file];
42
- logger.log(green(file) + ": ", yellow(resultsRendered(results)));
43
- }
44
- return;
45
- }
46
- for (const result of results) {
47
- logger.log(result.value);
48
- }
49
- } catch (e) {
50
- logger.error(e);
51
- }
52
- }
9
+ import { cliQueryCookies } from "./cliQueryCookies";
53
10
 
54
11
  async function main() {
55
12
  if (parsedArgs["help"] || parsedArgs["h"]) {
@@ -95,14 +52,14 @@ async function main() {
95
52
  {
96
53
  //
97
54
  headers,
98
- }
55
+ },
99
56
  //
100
57
  ).then(
101
58
  (res) => {
102
59
  logger.debug("Response", res);
103
60
  onfulfilled(res);
104
61
  },
105
- logger.error
62
+ logger.error,
106
63
  //
107
64
  );
108
65
  }
@@ -0,0 +1,62 @@
1
+ import CookieSpec from "./CookieSpec";
2
+ import { comboQueryCookieSpec } from "./comboQueryCookieSpec";
3
+ import logger from "./logger";
4
+ import { parsedArgs } from "./argv";
5
+ import { groupBy } from "lodash";
6
+ import { resultsRendered } from "./resultsRendered";
7
+ import ExportedCookie from "./ExportedCookie";
8
+ import { createConsola } from "consola";
9
+
10
+ const consola = createConsola({
11
+ fancy: true,
12
+ formatOptions: {
13
+ colors: true,
14
+ date: false,
15
+ },
16
+ });
17
+ consola.wrapConsole();
18
+
19
+ export async function cliQueryCookies(
20
+ cookieSpec: CookieSpec | CookieSpec[],
21
+ limit?: number,
22
+ removeExpired?: boolean,
23
+ //
24
+ ) {
25
+ try {
26
+ const results: ExportedCookie[] = await comboQueryCookieSpec(cookieSpec);
27
+ if (results == null || results.length == 0) {
28
+ consola.error("No results");
29
+ return;
30
+ }
31
+ if (parsedArgs["dump"] || parsedArgs["d"]) {
32
+ consola.log(results);
33
+ return;
34
+ }
35
+ if (parsedArgs["dump-grouped"] || parsedArgs["D"]) {
36
+ const groupedByFile = groupBy(results, (r) => r.meta?.file);
37
+ consola.log(JSON.stringify(groupedByFile, null, 2));
38
+ return;
39
+ }
40
+ if (
41
+ parsedArgs["render"] ||
42
+ parsedArgs["render-merged"] ||
43
+ parsedArgs["r"]
44
+ ) {
45
+ consola.log(resultsRendered(results));
46
+ return;
47
+ }
48
+ if (parsedArgs["render-grouped"] || parsedArgs["R"]) {
49
+ const groupedByFile = groupBy(results, (r) => r.meta?.file);
50
+ for (const file of Object.keys(groupedByFile)) {
51
+ let results = groupedByFile[file];
52
+ consola.log(file, ": ", resultsRendered(results));
53
+ }
54
+ return;
55
+ }
56
+ for (const result of results) {
57
+ logger.log(result.value);
58
+ }
59
+ } catch (e) {
60
+ logger.error(e);
61
+ }
62
+ }
@@ -2,23 +2,20 @@ import { MultiCookieSpec } from "./CookieSpec";
2
2
  import ExportedCookie from "./ExportedCookie";
3
3
  import { queryCookies } from "./queryCookies";
4
4
  import { uniqBy } from "lodash";
5
+ import { flatMapAsync } from "./util/flatMapAsync";
5
6
 
6
7
  export async function comboQueryCookieSpec(
7
- cookieSpec: MultiCookieSpec
8
+ cookieSpec: MultiCookieSpec,
8
9
  ): Promise<ExportedCookie[]> {
9
- const cookies: ExportedCookie[] = [];
10
10
  if (Array.isArray(cookieSpec)) {
11
- const results: Awaited<ExportedCookie[]>[] = await Promise.all(
12
- cookieSpec.map((cs) => {
13
- return queryCookies(cs);
14
- })
15
- );
16
- for (const exportedCookie of results.flat()) {
17
- cookies.push(exportedCookie);
18
- }
11
+ const cookiesForMultiSpec: ExportedCookie[] = //
12
+ await flatMapAsync(cookieSpec, async (cs) => {
13
+ return await queryCookies(cs);
14
+ });
15
+ return uniqBy(cookiesForMultiSpec, JSON.stringify);
19
16
  } else {
20
- const singleQuery: ExportedCookie[] = await queryCookies(cookieSpec);
21
- cookies.push(...singleQuery);
17
+ const cookiesForSingleSpec: ExportedCookie[] = //
18
+ await queryCookies(cookieSpec);
19
+ return uniqBy(cookiesForSingleSpec, JSON.stringify);
22
20
  }
23
- return uniqBy(cookies, JSON.stringify);
24
21
  }