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

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 (65) hide show
  1. package/.idea/runConfigurations/build.xml +12 -0
  2. package/.parcelrc +12 -0
  3. package/.prettierignore +5 -0
  4. package/.prettierrc +12 -0
  5. package/.terserrc +26 -0
  6. package/README.md +2 -2
  7. package/dist/cli.js +2 -0
  8. package/dist/index.js +2 -687
  9. package/dist/index.js.map +1 -0
  10. package/dist/module.js +1323 -0
  11. package/dist/module.js.map +1 -0
  12. package/dist/prompt.2b8c61c0.js +40 -0
  13. package/dist/prompt.536a2c51.js +40 -0
  14. package/dist/prompt.fb2c7dad.js.map +1 -0
  15. package/dist/types.d.ts +25 -0
  16. package/dist/types.d.ts.map +1 -0
  17. package/jest.config.ts +14 -0
  18. package/package-lock.json +2688 -6684
  19. package/package.json +42 -35
  20. package/src/CookieRow.ts +1 -0
  21. package/src/CookieSpec.ts +3 -1
  22. package/src/CookieStore.ts +27 -0
  23. package/src/ExportedCookie.ts +13 -0
  24. package/src/FetchResponse.ts +1 -2
  25. package/src/FileCookieStore.ts +175 -0
  26. package/src/StringToRegex.ts +16 -0
  27. package/src/argv.ts +29 -0
  28. package/src/browsers/ChromeApplicationSupport.ts +10 -0
  29. package/src/browsers/ChromeCookieQueryStrategy.ts +71 -131
  30. package/src/browsers/CompositeCookieQueryStrategy.ts +35 -11
  31. package/src/browsers/CookieQueryStrategy.ts +2 -0
  32. package/src/browsers/CookieStoreQueryStrategy.ts +99 -0
  33. package/src/browsers/DoSqliteQueryWithTransform.ts +85 -0
  34. package/src/browsers/FirefoxCookieQueryStrategy.ts +12 -7
  35. package/src/browsers/SafariCookieQueryStrategy.ts +3 -0
  36. package/src/browsers/decrypt.ts +118 -0
  37. package/src/browsers/getChromePassword.ts +9 -0
  38. package/src/cli.ts +52 -36
  39. package/src/comboQueryCookieSpec.ts +24 -0
  40. package/src/cookieSpecsFromUrl.ts +26 -0
  41. package/src/execSimple.ts +13 -0
  42. package/src/fetchWithCookies.ts +105 -38
  43. package/src/findAllFiles.ts +26 -54
  44. package/src/getChromeCookie.ts +19 -0
  45. package/src/getCookie.ts +20 -0
  46. package/src/getFirefoxCookie.ts +19 -0
  47. package/src/getGroupedRenderedCookies.ts +11 -24
  48. package/src/getMergedRenderedCookies.ts +12 -0
  49. package/src/global.ts +1 -1
  50. package/src/index.ts +14 -58
  51. package/src/isValidJwt.ts +4 -4
  52. package/src/listChromeProfiles.ts +45 -0
  53. package/src/logger.ts +3 -0
  54. package/src/queryCookies.ts +20 -11
  55. package/src/resultsRendered.ts +6 -3
  56. package/src/util/flatMapAsync.test.ts +55 -0
  57. package/src/util/flatMapAsync.ts +37 -0
  58. package/tsconfig.json +12 -16
  59. package/.github/dependabot.yml +0 -6
  60. package/.prettierrc.json +0 -1
  61. package/src/IsExportedCookie.ts +0 -9
  62. package/src/MemoryCookieStore.ts +0 -5
  63. package/src/browsers/MemoryCookieJarQueryStrategy.ts +0 -53
  64. package/src/doSqliteQuery1.ts +0 -51
  65. package/src/utils.ts +0 -50
@@ -1,18 +1,24 @@
1
1
  import CookieQueryStrategy from "./CookieQueryStrategy";
2
- import { execSimple } from "../utils";
3
- import { env, HOME } from "../global";
2
+ import { env } from "../global";
4
3
  import { existsSync } from "fs";
5
4
  import { findAllFiles } from "../findAllFiles";
6
- import * as crypto from "crypto";
7
- import * as path from "path";
8
- import { doSqliteQuery1 } from "../doSqliteQuery1";
5
+ import { join } from "path";
9
6
  import { merge } from "lodash";
10
7
  import { isCookieRow } from "../IsCookieRow";
11
- import { isExportedCookie } from "../IsExportedCookie";
8
+ import { isExportedCookie } from "../ExportedCookie";
12
9
  import CookieRow from "../CookieRow";
13
10
  import ExportedCookie from "../ExportedCookie";
11
+ import { stringToRegex } from "../StringToRegex";
12
+ import { parsedArgs } from "../argv";
13
+ import consola from "consola";
14
+ import { getChromePassword } from "./getChromePassword";
15
+ import { chromeApplicationSupport } from "./ChromeApplicationSupport";
16
+ import { decrypt } from "./decrypt";
17
+ import { doSqliteQueryWithTransform } from "./DoSqliteQueryWithTransform";
14
18
 
15
19
  export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
20
+ browserName = "Chrome";
21
+
16
22
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
17
23
  if (process.platform !== "darwin") {
18
24
  throw new Error("This only works on macOS");
@@ -40,7 +46,7 @@ async function getPromise1(
40
46
  file: file,
41
47
  });
42
48
  } catch (e) {
43
- if (env.VERBOSE) {
49
+ if (parsedArgs.verbose) {
44
50
  console.log("Error getting encrypted cookie", e);
45
51
  }
46
52
  return [];
@@ -50,16 +56,16 @@ async function getPromise1(
50
56
  async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
51
57
  try {
52
58
  const files: string[] = await findAllFiles({
53
- path: chromeLocal,
59
+ path: chromeApplicationSupport,
54
60
  name: "Cookies",
55
61
  });
56
62
  const promises: Promise<CookieRow[]>[] = files.map((file) =>
57
63
  getPromise1(name, domain, file)
58
64
  );
59
- const results1: Awaited<CookieRow[]>[] = await Promise.all(promises);
65
+ const results1: CookieRow[][] = await Promise.all(promises);
60
66
  return results1.flat().filter(isCookieRow);
61
67
  } catch (error) {
62
- if (env.VERBOSE) {
68
+ if (parsedArgs.verbose) {
63
69
  console.log("error", error);
64
70
  }
65
71
  return [];
@@ -71,7 +77,7 @@ async function decryptValue(password: string, encryptedValue: Buffer) {
71
77
  try {
72
78
  d = await decrypt(password, encryptedValue);
73
79
  } catch (e) {
74
- if (env.VERBOSE) {
80
+ if (parsedArgs.verbose) {
75
81
  console.log("Error decrypting cookie", e);
76
82
  }
77
83
  d = null;
@@ -99,34 +105,37 @@ Promise<ExportedCookie[]> {
99
105
  const decryptedValue = await decryptValue(password, encryptedValue);
100
106
  const meta = {};
101
107
  merge(meta, cookieRow.meta ?? {});
102
- return {
108
+ const exportedCookie: ExportedCookie = {
103
109
  domain: cookieRow.domain,
104
110
  name: cookieRow.name,
105
111
  value: decryptedValue,
106
112
  meta: meta,
107
113
  };
114
+ const expiry = cookieRow.expiry;
115
+ const mergeExpiry =
116
+ expiry != null && expiry > 0
117
+ ? {
118
+ expiry: new Date(expiry),
119
+ }
120
+ : {
121
+ expiry: "Infinity",
122
+ };
123
+ merge(exportedCookie, mergeExpiry);
124
+ return exportedCookie;
108
125
  });
109
126
  const results: ExportedCookie[] = (await Promise.all(decrypted)).filter(
110
127
  isExportedCookie
111
128
  );
112
- if (env.VERBOSE) {
129
+ if (parsedArgs.verbose) {
113
130
  console.log("results", results);
114
131
  }
115
132
  return results;
116
133
  }
117
134
 
118
- const chromeLocal = path.join(
119
- HOME,
120
- "Library",
121
- "Application Support",
122
- "Google",
123
- "Chrome"
124
- );
125
-
126
135
  async function getEncryptedChromeCookie({
127
136
  name,
128
137
  domain,
129
- file = path.join(chromeLocal, "Default", "Cookies"),
138
+ file = join(chromeApplicationSupport, "Default", "Cookies"),
130
139
  }: //
131
140
  {
132
141
  name: string;
@@ -136,138 +145,69 @@ async function getEncryptedChromeCookie({
136
145
  if (!existsSync(file)) {
137
146
  throw new Error(`File ${file} does not exist`);
138
147
  }
139
- if (env.VERBOSE) {
148
+ if (parsedArgs.verbose) {
140
149
  const s = file.split("/").slice(-3).join("/");
141
- console.log(`Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`);
150
+ consola.start(
151
+ `Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`
152
+ );
142
153
  }
143
154
  let sql;
144
155
  //language=SQL
145
- sql = "SELECT encrypted_value, name, host_key FROM cookies";
156
+ sql = "SELECT encrypted_value, name, host_key, expires_utc FROM cookies";
157
+ // Define a regular expression to match wildcard characters
146
158
  const wildcardRegexp = /^([*%])$/i;
159
+ // Check if the name does not contain wildcard characters
147
160
  const specifiedName = name.match(wildcardRegexp) == null;
161
+ // Check if the domain does not contain wildcard characters
148
162
  const specifiedDomain = domain.match(wildcardRegexp) == null;
149
- if (specifiedName || specifiedDomain) {
163
+ // Check if the domain contains wildcard characters
164
+ const wildcardDomain = domain.match(/[%*]/) != null;
165
+ // Determine if we should query the domain based on the previous checks
166
+ const queryDomain = specifiedDomain && !wildcardDomain;
167
+ // if we have a wildcard domain, we need to use a regexp
168
+ // If the name is specified or we need to query the domain, we add a WHERE clause to the SQL query
169
+ if (specifiedName || queryDomain) {
150
170
  sql += ` WHERE `;
171
+ // If the name is specified, we add a condition to the SQL query to match the name
151
172
  if (specifiedName) {
152
173
  sql += `name = '${name}'`;
153
- if (specifiedDomain) {
174
+ // If we also need to query the domain, we add an AND operator to the SQL query
175
+ if (queryDomain) {
154
176
  sql += ` AND `;
155
177
  }
156
178
  }
157
- if (specifiedDomain) {
158
- sql += `host_key LIKE '${domain}';`;
179
+ // If we need to query the domain, we add a condition to the SQL query to match the domain
180
+ if (queryDomain) {
181
+ // The leading dot is replaced with % to match subdomains
182
+ const sqlEmbedDomain = domain.replace(/^[.%]?/, "%");
183
+ sql += `host_key LIKE '${sqlEmbedDomain}';`;
159
184
  }
160
185
  }
161
- return doSqliteQuery1({
186
+ if (parsedArgs.verbose) {
187
+ consola.info("Querying:", sql);
188
+ }
189
+ const domainRegexp: RegExp = stringToRegex(domain);
190
+ const sqliteQuery1: CookieRow[] = await doSqliteQueryWithTransform({
162
191
  file: file,
163
192
  sql: sql,
193
+ rowFilter: (row) => {
194
+ return row["host_key"].match(domainRegexp) != null;
195
+ },
164
196
  rowTransform: (row) => {
165
- return {
197
+ const cookieRow = {
198
+ expiry: (row["expires_utc"] / 1000000 - 11644473600) * 1000,
166
199
  domain: row["host_key"],
167
200
  name: row["name"],
168
201
  value: row["encrypted_value"],
169
202
  };
203
+ if (parsedArgs.verbose) {
204
+ consola.info("Found", cookieRow);
205
+ }
206
+ return cookieRow;
170
207
  },
171
208
  });
172
- }
173
-
174
- async function getChromePassword(): Promise<string> {
175
- return execSimple(
176
- 'security find-generic-password -w -s "Chrome Safe Storage"'
177
- );
178
- }
179
-
180
- async function decrypt(
181
- password: crypto.BinaryLike,
182
- encryptedData: Buffer
183
- ): Promise<string> {
184
- if (typeof password !== "string") {
185
- throw new Error("password must be a string: " + password);
186
- }
187
- let encryptedData1: any;
188
- encryptedData1 = encryptedData;
189
- if (encryptedData1 == null || typeof encryptedData1 !== "object") {
190
- throw new Error("encryptedData must be a object: " + encryptedData1);
191
- }
192
- if (!(encryptedData1 instanceof Buffer)) {
193
- if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
194
- [encryptedData1] = encryptedData1;
195
- if (env.VERBOSE) {
196
- console.log(
197
- `encryptedData is an array of buffers, selected first: ${encryptedData1}`
198
- );
199
- }
200
- } else {
201
- throw new Error("encryptedData must be a Buffer: " + encryptedData1);
202
- }
203
- encryptedData1 = Buffer.from(encryptedData1);
204
- }
205
- if (env.VERBOSE) {
206
- console.log(`Trying to decrypt with password ${password}`);
207
- }
208
- return new Promise((resolve, reject) => {
209
- crypto.pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
210
- try {
211
- if (error) {
212
- if (env.VERBOSE) {
213
- console.log("Error doing pbkdf2", error);
214
- }
215
- reject(error);
216
- return;
217
- }
218
-
219
- if (buffer.length !== 16) {
220
- if (env.VERBOSE) {
221
- console.log(
222
- "Error doing pbkdf2, buffer length is not 16",
223
- buffer.length
224
- );
225
- }
226
- reject(new Error("Buffer length is not 16"));
227
- return;
228
- }
229
-
230
- const str = new Array(17).join(" ");
231
- const iv = Buffer.from(str, "binary");
232
- const decipher = crypto.createDecipheriv("aes-128-cbc", buffer, iv);
233
- decipher.setAutoPadding(false);
234
-
235
- if (encryptedData1 && encryptedData1.slice) {
236
- encryptedData1 = encryptedData1.slice(3);
237
- }
238
-
239
- if (encryptedData1.length % 16 !== 0) {
240
- if (env.VERBOSE) {
241
- console.log(
242
- "Error doing pbkdf2, encryptedData length is not a multiple of 16",
243
- encryptedData1.length
244
- );
245
- }
246
- reject(new Error("encryptedData length is not a multiple of 16"));
247
- return;
248
- }
249
-
250
- let decoded = decipher.update(encryptedData1);
251
- try {
252
- decipher.final("utf-8");
253
- } catch (e) {
254
- if (env.VERBOSE) {
255
- console.log("Error doing decipher.final()", e);
256
- }
257
- reject(e);
258
- return;
259
- }
260
-
261
- const padding = decoded[decoded.length - 1];
262
- if (padding) {
263
- decoded = decoded.slice(0, 0 - padding);
264
- }
265
- // noinspection JSCheckFunctionSignatures
266
- const decodedString = decoded.toString("utf8");
267
- resolve(decodedString);
268
- } catch (e) {
269
- reject(e);
270
- }
271
- });
209
+ return sqliteQuery1.filter((row) => {
210
+ // TODO: is this needed?
211
+ return row.domain.match(domainRegexp) != null;
272
212
  });
273
213
  }
@@ -4,21 +4,28 @@ 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 MemoryCookieStoreQueryStrategy from "./MemoryCookieJarQueryStrategy";
7
+ import { red } from "colorette";
8
+ import { merge } from "lodash";
9
+ import { parsedArgs } from "../argv";
8
10
 
9
- const cache = new LRUCache<string, ExportedCookie[]>({
10
- ttl: 1000 * 2,
11
+ const cache: LRUCache<string, ExportedCookie[]> = new LRUCache<
12
+ string,
13
+ ExportedCookie[]
14
+ >({
15
+ ttl: 1000 * 10,
11
16
  max: 10,
12
17
  });
13
18
 
14
19
  export default class CompositeCookieQueryStrategy
15
20
  implements CookieQueryStrategy
16
21
  {
22
+ browserName = "all";
23
+
17
24
  #strategies;
18
25
 
19
26
  constructor() {
20
27
  this.#strategies = [
21
- MemoryCookieStoreQueryStrategy,
28
+ // CookieStoreQueryStrategy,
22
29
  ChromeCookieQueryStrategy,
23
30
  FirefoxCookieQueryStrategy,
24
31
  SafariCookieQueryStrategy,
@@ -28,19 +35,36 @@ export default class CompositeCookieQueryStrategy
28
35
  }
29
36
 
30
37
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
38
+ // domain = domain.match(/(\w+.+\w+)/gi)?.pop() ?? domain;
31
39
  const key = `${name}:${domain}`;
32
40
  const cached = cache.get(key);
33
41
  if (cached) {
34
42
  return cached;
35
43
  }
36
- const results = await Promise.all(
37
- this.#strategies.map(async (strategy) => {
44
+ if (parsedArgs.verbose) {
45
+ console.log("Querying cookies:", name, domain);
46
+ }
47
+ const results: ExportedCookie[][] = await Promise.all(
48
+ this.#strategies.map(async (strategy: CookieQueryStrategy) => {
38
49
  // @ts-ignore
39
- const cookies: Promise<ExportedCookie[]> = strategy.queryCookies(
40
- name,
41
- domain
42
- );
43
- return cookies.catch(() => []);
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
+ });
59
+ });
60
+ })
61
+ .catch((e) => {
62
+ console.log(
63
+ red(`Error querying ${strategy.browserName} cookies`),
64
+ e
65
+ );
66
+ return [];
67
+ });
44
68
  })
45
69
  );
46
70
  const flat: ExportedCookie[] = results.flat();
@@ -1,5 +1,7 @@
1
1
  import ExportedCookie from "../ExportedCookie";
2
2
 
3
3
  export default interface CookieQueryStrategy {
4
+ browserName: string;
5
+
4
6
  queryCookies(name: string, domain: string): Promise<ExportedCookie[]>;
5
7
  }
@@ -0,0 +1,99 @@
1
+ import CookieQueryStrategy from "./CookieQueryStrategy";
2
+ import CookieSpec from "../CookieSpec";
3
+ import ExportedCookie from "../ExportedCookie";
4
+ import { Cookie, Store } from "tough-cookie";
5
+ import { cookieJarPromise, cookieStorePromise } from "../CookieStore";
6
+ import { stringToRegex } from "../StringToRegex";
7
+
8
+ export default class CookieStoreQueryStrategy implements CookieQueryStrategy {
9
+ browserName = "internal";
10
+
11
+ async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
12
+ const exportedCookies: ExportedCookie[] = [];
13
+
14
+ // if (name.match(/[%*]/) || domain.match(/[%*]/)) {
15
+ const cookies: Cookie[] = await this.#getAllCookies();
16
+ const allExportedCookies = cookies.map((cookie: Cookie) => {
17
+ return this.#extracted(cookie, { name, domain });
18
+ });
19
+ exportedCookies.push(...allExportedCookies);
20
+ // }
21
+
22
+ const wildcardRegexp = /^([*%])$/i;
23
+ if (name.match(wildcardRegexp) && domain.match(wildcardRegexp)) {
24
+ return exportedCookies;
25
+ }
26
+
27
+ const path = "/";
28
+
29
+ if (domain != "%") {
30
+ const domain1 = domain.match(/(\w+.+\w+)/gi)?.pop() ?? domain;
31
+ const url = new URL("https://" + domain1);
32
+ url.pathname = path;
33
+ const cookies: Cookie[] = await this.#getCookies(url.href);
34
+ const domainCookies = cookies.map((cookie: Cookie) => {
35
+ return this.#extracted(cookie, {
36
+ domain,
37
+ name,
38
+ });
39
+ });
40
+ exportedCookies.push(...domainCookies);
41
+ }
42
+
43
+ if (name == "%") {
44
+ return exportedCookies.filter((cookie: ExportedCookie) => {
45
+ return cookie.domain.match(stringToRegex(domain));
46
+ });
47
+ }
48
+
49
+ return exportedCookies.filter((cookie: ExportedCookie) => {
50
+ return (
51
+ cookie.name.match(stringToRegex(name)) &&
52
+ cookie.domain.match(stringToRegex(domain))
53
+ );
54
+ });
55
+ }
56
+
57
+ #extracted(cookie: Cookie, cookieSpec: CookieSpec): ExportedCookie {
58
+ return {
59
+ domain: cookie.domain ?? cookieSpec.domain,
60
+ name: cookie.key ?? cookieSpec.name,
61
+ value: cookie.value,
62
+ expiry: cookie.expires ?? "Infinity",
63
+ meta: {
64
+ file: "tough-cookie",
65
+ },
66
+ };
67
+ }
68
+
69
+ async #getCookies(url: string): Promise<Cookie[]> {
70
+ const cookieJar = await cookieJarPromise;
71
+ return new Promise((resolve, reject) => {
72
+ return cookieJar.getCookies(
73
+ url,
74
+ (err: Error | null, cookies: Cookie[]) => {
75
+ if (err) {
76
+ reject(err);
77
+ } else {
78
+ resolve(cookies ?? []);
79
+ }
80
+ }
81
+ );
82
+ });
83
+ }
84
+
85
+ async #getAllCookies(): Promise<Cookie[]> {
86
+ const cookieStore: Store = await cookieStorePromise;
87
+ return new Promise((resolve, reject) => {
88
+ return cookieStore.getAllCookies(
89
+ (err: Error | null, cookies: Cookie[]) => {
90
+ if (err) {
91
+ reject(err);
92
+ } else {
93
+ resolve(cookies ?? []);
94
+ }
95
+ }
96
+ );
97
+ });
98
+ }
99
+ }
@@ -0,0 +1,85 @@
1
+ import CookieRow from "../CookieRow";
2
+ import fs from "fs";
3
+ import { Database } from "sqlite3";
4
+ import { merge } from "lodash";
5
+ import { parsedArgs } from "../argv";
6
+ import consola from "consola";
7
+
8
+ export interface DoSqliteQueryWithTransformOptions {
9
+ file: string;
10
+ sql: string;
11
+ rowFilter?: (row: any) => boolean;
12
+ rowTransform: (row: any) => CookieRow;
13
+ }
14
+
15
+ function checkFileExistence(file: string) {
16
+ if (!file || !fs.existsSync(file)) {
17
+ throw new Error(`File ${file} does not exist`);
18
+ }
19
+ }
20
+
21
+ function createDatabase(file: string) {
22
+ return new Database(file);
23
+ }
24
+
25
+ function transformRows(
26
+ //
27
+ rows: any[],
28
+ rowFilter: (row: any) => boolean,
29
+ rowTransform: (row: any) => CookieRow,
30
+ file: string
31
+ //
32
+ ): CookieRow[] {
33
+ return rows.filter(rowFilter).map((row: any) => {
34
+ const metaData = {
35
+ meta: {
36
+ file: file,
37
+ },
38
+ };
39
+
40
+ const cookieRow: CookieRow = rowTransform(row);
41
+
42
+ return merge(metaData, cookieRow);
43
+ });
44
+ }
45
+
46
+ export async function doSqliteQueryWithTransform(
47
+ //
48
+ {
49
+ //
50
+ file,
51
+ sql,
52
+ rowFilter = () => true,
53
+ rowTransform,
54
+ }: DoSqliteQueryWithTransformOptions
55
+ ): //
56
+ Promise<CookieRow[]> {
57
+ checkFileExistence(file);
58
+
59
+ const db: Database = createDatabase(file);
60
+
61
+ return new Promise((resolve, reject) => {
62
+ db.all(sql, (err: Error, rows: any[]) => {
63
+ if (err) {
64
+ return reject(err);
65
+ }
66
+
67
+ if (!rows || rows.length === 0) {
68
+ return resolve([]);
69
+ }
70
+
71
+ const cookieRows: CookieRow[] = transformRows(
72
+ rows,
73
+ rowFilter,
74
+ rowTransform,
75
+ file
76
+ );
77
+
78
+ if (parsedArgs.verbose) {
79
+ consola.log(`Rows: ${JSON.stringify(rows)}`);
80
+ }
81
+
82
+ return resolve(cookieRows);
83
+ });
84
+ });
85
+ }
@@ -1,20 +1,24 @@
1
1
  import * as path from "path";
2
2
  import CookieQueryStrategy from "./CookieQueryStrategy";
3
- import { env, HOME } from "../global";
3
+ import { HOME } from "../global";
4
4
  import { existsSync } from "fs";
5
5
  import { findAllFiles } from "../findAllFiles";
6
- import { doSqliteQuery1 } from "../doSqliteQuery1";
7
6
  import ExportedCookie from "../ExportedCookie";
8
7
  import CookieRow from "../CookieRow";
9
8
  import CookieSpec from "../CookieSpec";
10
9
  import { specialCases } from "../SpecialCases";
10
+ import { parsedArgs } from "../argv";
11
+ import { doSqliteQueryWithTransform } from "./DoSqliteQueryWithTransform";
11
12
 
12
13
  export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
14
+ browserName = "Firefox";
15
+
13
16
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
14
17
  if (process.platform !== "darwin") {
15
- throw new Error("This only works on macOS");
18
+ // TODO: implement
19
+ return [];
16
20
  }
17
- if (env.CHROME_ONLY) {
21
+ if (parsedArgs.browser !== "firefox") {
18
22
  return [];
19
23
  }
20
24
  const cookies = await this.#getFirefoxCookie({ name, domain });
@@ -34,7 +38,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
34
38
  async #getFirefoxCookie(
35
39
  { name, domain }: CookieSpec //
36
40
  ) {
37
- const files: string[] = await findAllFiles({
41
+ const files: string[] = findAllFiles({
38
42
  path: path.join(
39
43
  HOME,
40
44
  "Library",
@@ -47,7 +51,8 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
47
51
  const fn: (file: string) => Promise<CookieRow[]> = async (file: string) => {
48
52
  return await this.#queryCookiesDb(file, name, domain);
49
53
  };
50
- const all: Awaited<CookieRow[]>[] = await Promise.all(files.map(fn));
54
+ const all: CookieRow[][] = await Promise.all(files.map(fn));
55
+ // flatten
51
56
  return all.flat();
52
57
  }
53
58
 
@@ -85,7 +90,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
85
90
  };
86
91
  };
87
92
  try {
88
- return await doSqliteQuery1({
93
+ return await doSqliteQueryWithTransform({
89
94
  file,
90
95
  sql,
91
96
  rowTransform,
@@ -2,7 +2,10 @@ import CookieQueryStrategy from "./CookieQueryStrategy";
2
2
  import ExportedCookie from "../ExportedCookie";
3
3
 
4
4
  export default class SafariCookieQueryStrategy implements CookieQueryStrategy {
5
+ browserName = "Safari";
6
+
5
7
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
8
+ // TODO: implement
6
9
  return [];
7
10
  }
8
11
  }