@mherod/get-cookie 2.1.1 → 2.1.3

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 (56) hide show
  1. package/.parcelrc +2 -7
  2. package/bun.lockb +0 -0
  3. package/dist/cli.js +18319 -2
  4. package/dist/index.js +24531 -1279
  5. package/dist/types.d.ts +361 -30
  6. package/package-lock.json +3997 -6448
  7. package/package.json +8 -52
  8. package/src/CookieRow.ts +35 -7
  9. package/src/CookieSpec.ts +32 -14
  10. package/src/SpecialCases.ts +6 -5
  11. package/src/StringToRegex.ts +4 -4
  12. package/src/browsers/CompositeCookieQueryStrategy.ts +34 -28
  13. package/src/browsers/CookieQueryStrategy.ts +1 -1
  14. package/src/browsers/CookieStoreQueryStrategy.ts +71 -55
  15. package/src/browsers/QuerySqliteThenTransform.ts +27 -64
  16. package/src/browsers/chrome/ChromeApplicationSupport.ts +4 -0
  17. package/src/browsers/chrome/ChromeCookieQueryStrategy.ts +118 -91
  18. package/src/browsers/chrome/decrypt.ts +133 -97
  19. package/src/browsers/chrome/getChromePassword.ts +22 -5
  20. package/src/browsers/firefox/FirefoxCookieQueryStrategy.ts +19 -13
  21. package/src/browsers/getEncryptedChromeCookie.ts +101 -66
  22. package/src/browsers/mock/MockCookieQueryStrategy.ts +8 -4
  23. package/src/browsers/safari/SafariCookieQueryStrategy.ts +34 -3
  24. package/src/cli.ts +36 -29
  25. package/src/cliQueryCookies.ts +14 -4
  26. package/src/comboQueryCookieSpec.ts +7 -10
  27. package/src/cookieQueryOptions.ts +8 -1
  28. package/src/cookieSpecsFromUrl.ts +53 -7
  29. package/src/decodeBinaryCookies.ts +72 -0
  30. package/src/execSimple.ts +1 -2
  31. package/src/fetchWithCookies.ts +172 -144
  32. package/src/findAllFiles.ts +10 -0
  33. package/src/getChromeCookie.ts +6 -8
  34. package/src/getCookie.ts +8 -8
  35. package/src/getFirefoxCookie.ts +13 -9
  36. package/src/getGroupedRenderedCookies.ts +29 -6
  37. package/src/getMergedRenderedCookies.ts +4 -2
  38. package/src/global.ts +2 -2
  39. package/src/isValidJwt.ts +6 -4
  40. package/src/listChromeProfiles.ts +18 -10
  41. package/src/logger.ts +0 -1
  42. package/src/processBeforeReturn.ts +15 -12
  43. package/src/queryCookies.ts +22 -17
  44. package/src/resultsRendered.ts +20 -7
  45. package/src/unpackHeaders.ts +10 -8
  46. package/src/util/flatMapAsync.ts +20 -16
  47. package/tsconfig.json +4 -4
  48. package/dist/index.js.map +0 -1
  49. package/dist/module.js +0 -1446
  50. package/dist/module.js.map +0 -1
  51. package/dist/prompt.2b8c61c0.js +0 -40
  52. package/dist/prompt.536a2c51.js +0 -40
  53. package/dist/prompt.fb2c7dad.js.map +0 -1
  54. package/dist/types.d.ts.map +0 -1
  55. package/src/CookieStore.ts +0 -27
  56. package/src/FileCookieStore.ts +0 -178
@@ -16,116 +16,143 @@ import logger from "../../logger";
16
16
  export const consola = logger.withTag("ChromeCookieQueryStrategy");
17
17
 
18
18
  export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
19
- browserName = "Chrome";
19
+ browserName: string = "Chrome";
20
20
 
21
21
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
22
- if (process.platform !== "darwin") {
23
- throw new Error("This only works on macOS");
24
- }
22
+ this.ensurePlatformIsMacOS();
25
23
  if (env.FIREFOX_ONLY) {
26
24
  return [];
27
25
  }
28
- return getChromeCookies({
26
+ return this.getChromeCookies({
29
27
  requireJwt: false,
30
28
  name,
31
29
  domain,
32
30
  });
33
31
  }
34
- }
35
32
 
36
- async function getPromise1(
37
- name: string,
38
- domain: string,
39
- file: string,
40
- ): Promise<CookieRow[]> {
41
- try {
42
- return await getEncryptedChromeCookie({
43
- name: name,
44
- domain: domain,
45
- file: file,
46
- });
47
- } catch (e) {
48
- if (parsedArgs.verbose) {
49
- console.log("Error getting encrypted cookie", e);
33
+ private ensurePlatformIsMacOS(): void {
34
+ if (process.platform !== "darwin") {
35
+ throw new Error("This only works on macOS");
50
36
  }
51
- return [];
52
37
  }
53
- }
54
38
 
55
- async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
56
- try {
57
- const files: string[] = findAllFiles({
58
- path: chromeApplicationSupport,
59
- name: "Cookies",
60
- });
61
- const results1: CookieRow[] = await flatMapAsync(files, async (file) => {
62
- return await getPromise1(name, domain, file);
63
- });
64
- return results1.filter(isCookieRow);
65
- } catch (error) {
66
- if (parsedArgs.verbose) {
67
- console.log("error", error);
39
+ private async getChromeCookies({
40
+ name,
41
+ domain = "%",
42
+ requireJwt = false,
43
+ }: {
44
+ name: string;
45
+ domain: string;
46
+ requireJwt: boolean | undefined;
47
+ }): Promise<ExportedCookie[]> {
48
+ const encryptedDataItems: CookieRow[] = await this.getEncryptedCookies(
49
+ name,
50
+ domain,
51
+ );
52
+
53
+ const password: string = await getChromePassword();
54
+ const decryptedCookies: ExportedCookie[] = await this.decryptCookies(
55
+ encryptedDataItems,
56
+ password,
57
+ );
58
+
59
+ return decryptedCookies;
60
+ }
61
+
62
+ private async getEncryptedCookies(
63
+ name: string,
64
+ domain: string,
65
+ ): Promise<CookieRow[]> {
66
+ try {
67
+ const files: string[] = findAllFiles({
68
+ path: chromeApplicationSupport,
69
+ name: "Cookies",
70
+ });
71
+
72
+ const results: CookieRow[] = await flatMapAsync(files, async (file) => {
73
+ return await this.getCookiesFromFile(name, domain, file);
74
+ });
75
+
76
+ return results.filter(isCookieRow);
77
+ } catch (error) {
78
+ consola.warn("Error finding encrypted cookies", error);
79
+ return [];
80
+ }
81
+ }
82
+
83
+ private async getCookiesFromFile(
84
+ name: string,
85
+ domain: string,
86
+ file: string,
87
+ ): Promise<CookieRow[]> {
88
+ try {
89
+ return await getEncryptedChromeCookie({
90
+ name: name,
91
+ domain: domain,
92
+ file: file,
93
+ });
94
+ } catch (e) {
95
+ consola.warn("Error getting encrypted cookie from file", e);
96
+ return [];
68
97
  }
69
- return [];
70
98
  }
71
- }
72
99
 
73
- async function decryptValue(password: string, encryptedValue: Buffer) {
74
- let d: string | null;
75
- try {
76
- d = await decrypt(password, encryptedValue);
77
- } catch (e) {
78
- if (parsedArgs.verbose) {
79
- console.log("Error decrypting cookie", e);
100
+ private async decryptCookies(
101
+ encryptedDataItems: CookieRow[],
102
+ password: string,
103
+ ): Promise<ExportedCookie[]> {
104
+ const decrypted: Promise<ExportedCookie | null>[] = encryptedDataItems
105
+ .filter(({ value }) => value != null && value.length > 0)
106
+ .map(async (cookieRow: CookieRow) => {
107
+ const encryptedValue: Uint8Array | Buffer = cookieRow.value;
108
+ const decryptedValue = await this.decryptValue(
109
+ password,
110
+ encryptedValue,
111
+ );
112
+ return this.createExportedCookie(cookieRow, decryptedValue);
113
+ });
114
+ return (await Promise.all(decrypted)).filter(isExportedCookie);
115
+ }
116
+
117
+ private async decryptValue(
118
+ password: string,
119
+ encryptedValue: Uint8Array | Buffer,
120
+ ): Promise<string> {
121
+ let decrypted: string | null;
122
+ try {
123
+ const bufferValue = Buffer.isBuffer(encryptedValue)
124
+ ? encryptedValue
125
+ : Buffer.from(encryptedValue);
126
+ decrypted = await decrypt(password, bufferValue);
127
+ } catch (e) {
128
+ consola.warn("Error decrypting cookie", e);
129
+ decrypted = null;
80
130
  }
81
- d = null;
131
+ return decrypted ?? encryptedValue.toString("utf-8");
82
132
  }
83
- return d ?? encryptedValue.toString("utf-8");
84
- }
85
133
 
86
- async function getChromeCookies({
87
- name,
88
- domain = "%",
89
- requireJwt = false,
90
- }: {
91
- name: string;
92
- domain: string;
93
- requireJwt: boolean | undefined;
94
- //
95
- }): //
96
- Promise<ExportedCookie[]> {
97
- const encryptedDataItems: CookieRow[] = await getPromise(name, domain);
98
- const password: string = await getChromePassword();
99
- const decrypted: Promise<ExportedCookie | null>[] = encryptedDataItems
100
- .filter(({ value }) => value != null && value.length > 0)
101
- .map(async (cookieRow: CookieRow) => {
102
- const encryptedValue: Buffer = cookieRow.value;
103
- const decryptedValue = await decryptValue(password, encryptedValue);
104
- const meta = {};
105
- merge(meta, cookieRow.meta ?? {});
106
- const exportedCookie: ExportedCookie = {
107
- domain: cookieRow.domain,
108
- name: cookieRow.name,
109
- value: decryptedValue,
110
- meta: meta,
111
- };
112
- const expiry = cookieRow.expiry;
113
- const mergeExpiry =
114
- expiry != null && expiry > 0
115
- ? {
116
- expiry: new Date(expiry),
117
- }
118
- : {
119
- expiry: "Infinity",
120
- };
121
- merge(exportedCookie, mergeExpiry);
122
- return exportedCookie;
123
- });
124
- const results: ExportedCookie[] = (await Promise.all(decrypted)).filter(
125
- isExportedCookie,
126
- );
127
- if (parsedArgs.verbose) {
128
- console.log("results", results);
134
+ private createExportedCookie(
135
+ cookieRow: CookieRow,
136
+ decryptedValue: string,
137
+ ): ExportedCookie {
138
+ const meta = {};
139
+ merge(meta, cookieRow.meta ?? {});
140
+ const exportedCookie: ExportedCookie = {
141
+ domain: cookieRow.domain,
142
+ name: cookieRow.name,
143
+ value: decryptedValue,
144
+ meta: meta,
145
+ };
146
+ const expiry = cookieRow.expiry;
147
+ const mergeExpiry =
148
+ expiry != null && expiry > 0
149
+ ? {
150
+ expiry: new Date(expiry),
151
+ }
152
+ : {
153
+ expiry: "Infinity",
154
+ };
155
+ merge(exportedCookie, mergeExpiry);
156
+ return exportedCookie;
129
157
  }
130
- return results;
131
158
  }
@@ -1,118 +1,154 @@
1
- import { BinaryLike, createDecipheriv, pbkdf2 } from "crypto";
1
+ import { createDecipheriv, pbkdf2 } from "crypto";
2
2
  import { parsedArgs } from "../../argv";
3
3
  import consola from "../../logger";
4
4
 
5
- // Function to decrypt encrypted data using a password
6
- export async function decrypt(
7
- password: BinaryLike, // The password to use for decryption
8
- encryptedData: Buffer, // The data to decrypt
9
- ): Promise<string> {
10
- // Returns a promise that resolves with the decrypted string
11
- // Check if password is a string
12
- if (typeof password !== "string") {
13
- throw new Error("password must be a string: " + password);
5
+ interface Decryptor {
6
+ decrypt(password: string, encryptedData: Buffer): Promise<string>;
7
+ }
8
+
9
+ class BufferDecryptor implements Decryptor {
10
+ async decrypt(password: string, encryptedData: Buffer): Promise<string> {
11
+ this.validatePassword(password);
12
+ const preparedData: Buffer =
13
+ this.validateAndPrepareEncryptedData(encryptedData);
14
+
15
+ if (parsedArgs.verbose) {
16
+ consola.start(`Trying to decrypt with password: ${password}`);
17
+ }
18
+
19
+ const decryptedData: string = await this.performDecryption(
20
+ password,
21
+ preparedData,
22
+ );
23
+
24
+ if (parsedArgs.verbose) {
25
+ consola.success(`Decryption successful: ${decryptedData}`);
26
+ }
27
+
28
+ return decryptedData;
14
29
  }
15
- let encryptedData1: any;
16
- encryptedData1 = encryptedData;
17
- // Check if encryptedData is an object
18
- if (encryptedData1 == null || typeof encryptedData1 !== "object") {
19
- throw new Error("encryptedData must be a object: " + encryptedData1);
30
+
31
+ private validatePassword(password: string): void {
32
+ if (typeof password !== "string") {
33
+ throw new Error("password must be a string: " + password);
34
+ }
20
35
  }
21
- // Check if encryptedData is a Buffer or an array of Buffers
22
- if (!(encryptedData1 instanceof Buffer)) {
23
- if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
24
- [encryptedData1] = encryptedData1;
25
- // Log if encryptedData is an array of buffers
36
+
37
+ private validateAndPrepareEncryptedData(encryptedData: Buffer): Buffer {
38
+ if (
39
+ encryptedData == null ||
40
+ !(
41
+ encryptedData instanceof Buffer ||
42
+ (Array.isArray(encryptedData) && Buffer.isBuffer(encryptedData[0]))
43
+ )
44
+ ) {
45
+ throw new Error(
46
+ "encryptedData must be a Buffer or an array of Buffers: " +
47
+ encryptedData,
48
+ );
49
+ }
50
+
51
+ if (Array.isArray(encryptedData) && Buffer.isBuffer(encryptedData[0])) {
52
+ encryptedData = encryptedData[0];
26
53
  if (parsedArgs.verbose) {
27
- console.log(
28
- `encryptedData is an array of buffers, selected first: ${encryptedData1}`,
54
+ consola.info(
55
+ `encryptedData is an array of buffers, selected first: ${encryptedData}`,
29
56
  );
30
57
  }
31
- } else {
32
- throw new Error("encryptedData must be a Buffer: " + encryptedData1);
33
58
  }
34
- encryptedData1 = Buffer.from(encryptedData1);
59
+
60
+ return Buffer.from(encryptedData);
35
61
  }
36
- // Log the password being used for decryption
37
- if (parsedArgs.verbose) {
38
- consola.start(`Trying to decrypt with password: ${password}`);
62
+
63
+ private performDecryption(
64
+ password: string,
65
+ encryptedData: Buffer,
66
+ ): Promise<string> {
67
+ return new Promise((resolve, reject) => {
68
+ this.deriveKey(password)
69
+ .then((key) => this.decryptData(key, encryptedData))
70
+ .then((decrypted) => resolve(decrypted))
71
+ .catch((error) => reject(error));
72
+ });
39
73
  }
40
- // Return a promise that resolves with the decrypted string
41
- return new Promise((resolve, reject) => {
42
- // Use pbkdf2 to derive a key from the password
43
- pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
44
- try {
45
- // Handle any errors from pbkdf2
46
- if (error) {
47
- if (parsedArgs.verbose) {
48
- console.log("Error doing pbkdf2", error);
74
+
75
+ private deriveKey(password: string): Promise<Buffer> {
76
+ return new Promise((resolve, reject) => {
77
+ pbkdf2(
78
+ password,
79
+ "saltysalt",
80
+ 1003,
81
+ 16,
82
+ "sha1",
83
+ (error: Error | null, buffer: Buffer) => {
84
+ if (error) {
85
+ this.logError("Error doing pbkdf2", error);
86
+ reject(error);
87
+ return;
49
88
  }
50
- reject(error);
51
- return;
52
- }
53
-
54
- // Check if the buffer length is 16
55
- if (buffer.length !== 16) {
56
- if (parsedArgs.verbose) {
57
- console.log(
89
+
90
+ if (buffer.length !== 16) {
91
+ this.logError(
58
92
  "Error doing pbkdf2, buffer length is not 16",
59
93
  buffer.length,
60
94
  );
95
+ reject(new Error("Buffer length is not 16"));
96
+ return;
61
97
  }
62
- reject(new Error("Buffer length is not 16"));
63
- return;
64
- }
65
-
66
- // Create an initialization vector
67
- const str = new Array(17).join(" ");
68
- const iv = Buffer.from(str, "binary");
69
- // Create a decipher using the derived key and initialization vector
70
- const decipher = createDecipheriv("aes-128-cbc", buffer, iv);
71
- decipher.setAutoPadding(false);
72
-
73
- // Remove the first 3 bytes from the encrypted data
74
- if (encryptedData1 && encryptedData1.slice) {
75
- encryptedData1 = encryptedData1.slice(3);
76
- }
77
-
78
- // Check if the encrypted data length is a multiple of 16
79
- if (encryptedData1.length % 16 !== 0) {
80
- if (parsedArgs.verbose) {
81
- console.log(
82
- "Error doing pbkdf2, encryptedData length is not a multiple of 16",
83
- encryptedData1.length,
84
- );
85
- }
86
- reject(new Error("encryptedData length is not a multiple of 16"));
87
- return;
88
- }
89
-
90
- // Update the decipher with the encrypted data
91
- let decoded = decipher.update(encryptedData1);
92
- try {
93
- // Finalize the decipher
94
- decipher.final("utf-8");
95
- } catch (e) {
96
- if (parsedArgs.verbose) {
97
- console.log("Error doing decipher.final()", e);
98
- }
99
- reject(e);
100
- return;
101
- }
102
-
103
- // Remove padding from the decoded data
104
- const padding = decoded[decoded.length - 1];
105
- if (padding) {
106
- decoded = decoded.slice(0, 0 - padding);
107
- }
108
- // Convert the decoded data to a string
109
- const decodedString = decoded.toString("utf8");
110
- // Resolve the promise with the decrypted string
111
- resolve(decodedString);
98
+
99
+ resolve(buffer);
100
+ },
101
+ );
102
+ });
103
+ }
104
+
105
+ private decryptData(key: Buffer, encryptedData: Buffer): Promise<string> {
106
+ return new Promise((resolve, reject) => {
107
+ const iv: Buffer = Buffer.from(new Array(17).join(" "), "binary");
108
+ const decipher = createDecipheriv("aes-128-cbc", key, iv);
109
+ decipher.setAutoPadding(false);
110
+
111
+ const slicedData: Buffer = encryptedData.slice(3);
112
+
113
+ if (slicedData.length % 16 !== 0) {
114
+ this.logError(
115
+ "Error, encryptedData length is not a multiple of 16",
116
+ slicedData.length,
117
+ );
118
+ reject(new Error("encryptedData length is not a multiple of 16"));
119
+ return;
120
+ }
121
+
122
+ let decoded: Buffer = decipher.update(slicedData);
123
+ try {
124
+ decipher.final("utf-8");
112
125
  } catch (e) {
113
- // Reject the promise if there is an error
126
+ this.logError("Error doing decipher.final()", e);
114
127
  reject(e);
128
+ return;
115
129
  }
130
+
131
+ const padding: number = decoded[decoded.length - 1];
132
+ if (padding) {
133
+ decoded = decoded.slice(0, 0 - padding);
134
+ }
135
+
136
+ resolve(decoded.toString("utf8"));
116
137
  });
117
- });
138
+ }
139
+
140
+ private logError(message: string, error: any): void {
141
+ if (parsedArgs.verbose) {
142
+ consola.error(message, error);
143
+ }
144
+ }
145
+ }
146
+
147
+ export const decryptor: Decryptor = new BufferDecryptor();
148
+
149
+ export async function decrypt(
150
+ password: string,
151
+ encryptedData: Buffer,
152
+ ): Promise<string> {
153
+ return decryptor.decrypt(password, encryptedData);
118
154
  }
@@ -1,11 +1,28 @@
1
1
  import { execSimple } from "../../execSimple";
2
2
 
3
- // top level so it's only called once and cached
4
- const chromePassword: Promise<string> =
3
+ interface PasswordRetriever {
4
+ retrievePassword(): Promise<string>;
5
+ }
6
+
7
+ class MacOSPasswordRetriever implements PasswordRetriever {
8
+ async retrievePassword(): Promise<string> {
9
+ return execSimple(
10
+ 'security find-generic-password -w -s "Chrome Safe Storage"',
11
+ );
12
+ }
13
+ }
14
+
15
+ class UnsupportedPlatformPasswordRetriever implements PasswordRetriever {
16
+ async retrievePassword(): Promise<string> {
17
+ return Promise.reject(new Error("This only works on macOS"));
18
+ }
19
+ }
20
+
21
+ const passwordRetriever: PasswordRetriever =
5
22
  process.platform == "darwin"
6
- ? execSimple('security find-generic-password -w -s "Chrome Safe Storage"')
7
- : Promise.reject(new Error("This only works on macOS"));
23
+ ? new MacOSPasswordRetriever()
24
+ : new UnsupportedPlatformPasswordRetriever();
8
25
 
9
26
  export async function getChromePassword(): Promise<string> {
10
- return await chromePassword;
27
+ return await passwordRetriever.retrievePassword();
11
28
  }
@@ -11,7 +11,7 @@ import { parsedArgs } from "../../argv";
11
11
  import { querySqliteThenTransform } from "../QuerySqliteThenTransform";
12
12
 
13
13
  export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
14
- browserName = "Firefox";
14
+ browserName: string = "Firefox";
15
15
 
16
16
  async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
17
17
  if (process.platform !== "darwin") {
@@ -21,13 +21,15 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
21
21
  if (parsedArgs.browser !== "firefox") {
22
22
  return [];
23
23
  }
24
- const cookies = await this.#getFirefoxCookie({ name, domain });
24
+ const cookies: CookieRow[] = await this.getFirefoxCookie({ name, domain });
25
25
  if (Array.isArray(cookies)) {
26
26
  return cookies.map((cookie: CookieRow) => {
27
27
  return {
28
28
  domain: cookie.domain,
29
29
  name: cookie.name,
30
- value: cookie.value.toString("utf8"),
30
+ value: Buffer.isBuffer(cookie.value)
31
+ ? cookie.value.toString("utf8")
32
+ : Buffer.from(cookie.value).toString("utf8"),
31
33
  };
32
34
  });
33
35
  } else {
@@ -35,9 +37,12 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
35
37
  }
36
38
  }
37
39
 
38
- async #getFirefoxCookie(
40
+ private async getFirefoxCookie(
39
41
  { name, domain }: CookieSpec, //
40
- ) {
42
+ ): Promise<CookieRow[]> {
43
+ if (!HOME) {
44
+ throw new Error("HOME environment variable is not set");
45
+ }
41
46
  const files: string[] = findAllFiles({
42
47
  path: path.join(
43
48
  HOME,
@@ -48,23 +53,24 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
48
53
  ),
49
54
  name: "cookies.sqlite",
50
55
  });
51
- const fn: (file: string) => Promise<CookieRow[]> = async (file: string) => {
52
- return await this.#queryCookiesDb(file, name, domain);
53
- };
54
- const all: CookieRow[][] = await Promise.all(files.map(fn));
56
+ const all: CookieRow[][] = await Promise.all(
57
+ files.map(async (file: string) => {
58
+ return await this.queryCookiesDb(file, name, domain);
59
+ }),
60
+ );
55
61
  // flatten
56
62
  return all.flat();
57
63
  }
58
64
 
59
- async #queryCookiesDb(
65
+ private async queryCookiesDb(
60
66
  file: string,
61
67
  name: string,
62
68
  domain: string,
63
69
  ): Promise<CookieRow[]> {
64
- if (file && !existsSync(file)) {
70
+ if (!existsSync(file)) {
65
71
  throw new Error(`File ${file} does not exist`);
66
72
  }
67
- let sql;
73
+ let sql: string;
68
74
  //language=SQL
69
75
  sql = "SELECT value, name, host FROM moz_cookies";
70
76
  const { specifiedName, specifiedDomain } = specialCases({ name, domain });
@@ -80,7 +86,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
80
86
  sql += `host LIKE '${domain}';`;
81
87
  }
82
88
  }
83
- const rowTransform = (row: any) => {
89
+ const rowTransform = (row: any): CookieRow => {
84
90
  // row is object key by column name
85
91
  const value = row.value as string;
86
92
  return {