@mherod/get-cookie 2.0.0-rc.29 → 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.
@@ -1,19 +1,20 @@
1
1
  import CookieQueryStrategy from "./CookieQueryStrategy";
2
- import { execSimple } from "../utils";
3
- import { env, HOME } from "../global";
4
- import fs, { existsSync } from "fs";
2
+ import { env } from "../global";
3
+ import { existsSync } from "fs";
5
4
  import { findAllFiles } from "../findAllFiles";
6
- import * as crypto from "crypto";
7
- import * as path from "path";
5
+ import { join } from "path";
8
6
  import { merge } from "lodash";
9
7
  import { isCookieRow } from "../IsCookieRow";
10
- import { isExportedCookie } from "../IsExportedCookie";
8
+ import { isExportedCookie } from "../ExportedCookie";
11
9
  import CookieRow from "../CookieRow";
12
10
  import ExportedCookie from "../ExportedCookie";
13
11
  import { stringToRegex } from "../StringToRegex";
14
12
  import { parsedArgs } from "../argv";
15
- import * as sqlite3 from "sqlite3";
16
- import { DoSqliteQuery1Params } from "../doSqliteQuery1Params";
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";
17
18
 
18
19
  export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
19
20
  browserName = "Chrome";
@@ -55,7 +56,7 @@ async function getPromise1(
55
56
  async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
56
57
  try {
57
58
  const files: string[] = await findAllFiles({
58
- path: chromeLocal,
59
+ path: chromeApplicationSupport,
59
60
  name: "Cookies",
60
61
  });
61
62
  const promises: Promise<CookieRow[]>[] = files.map((file) =>
@@ -131,18 +132,10 @@ Promise<ExportedCookie[]> {
131
132
  return results;
132
133
  }
133
134
 
134
- const chromeLocal = path.join(
135
- HOME,
136
- "Library",
137
- "Application Support",
138
- "Google",
139
- "Chrome"
140
- );
141
-
142
135
  async function getEncryptedChromeCookie({
143
136
  name,
144
137
  domain,
145
- file = path.join(chromeLocal, "Default", "Cookies"),
138
+ file = join(chromeApplicationSupport, "Default", "Cookies"),
146
139
  }: //
147
140
  {
148
141
  name: string;
@@ -154,38 +147,47 @@ async function getEncryptedChromeCookie({
154
147
  }
155
148
  if (parsedArgs.verbose) {
156
149
  const s = file.split("/").slice(-3).join("/");
157
- 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
+ );
158
153
  }
159
154
  let sql;
160
155
  //language=SQL
161
- sql = "SELECT * FROM cookies";
162
- // sql = "SELECT encrypted_value, name, host_key FROM cookies";
163
-
156
+ sql = "SELECT encrypted_value, name, host_key, expires_utc FROM cookies";
157
+ // Define a regular expression to match wildcard characters
164
158
  const wildcardRegexp = /^([*%])$/i;
159
+ // Check if the name does not contain wildcard characters
165
160
  const specifiedName = name.match(wildcardRegexp) == null;
161
+ // Check if the domain does not contain wildcard characters
166
162
  const specifiedDomain = domain.match(wildcardRegexp) == null;
163
+ // Check if the domain contains wildcard characters
167
164
  const wildcardDomain = domain.match(/[%*]/) != null;
165
+ // Determine if we should query the domain based on the previous checks
168
166
  const queryDomain = specifiedDomain && !wildcardDomain;
169
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
170
169
  if (specifiedName || queryDomain) {
171
170
  sql += ` WHERE `;
171
+ // If the name is specified, we add a condition to the SQL query to match the name
172
172
  if (specifiedName) {
173
173
  sql += `name = '${name}'`;
174
+ // If we also need to query the domain, we add an AND operator to the SQL query
174
175
  if (queryDomain) {
175
176
  sql += ` AND `;
176
177
  }
177
178
  }
179
+ // If we need to query the domain, we add a condition to the SQL query to match the domain
178
180
  if (queryDomain) {
179
- // leading dot replaced with % to match subdomains
181
+ // The leading dot is replaced with % to match subdomains
180
182
  const sqlEmbedDomain = domain.replace(/^[.%]?/, "%");
181
183
  sql += `host_key LIKE '${sqlEmbedDomain}';`;
182
184
  }
183
185
  }
184
186
  if (parsedArgs.verbose) {
185
- console.log("sql", sql);
187
+ consola.info("Querying:", sql);
186
188
  }
187
189
  const domainRegexp: RegExp = stringToRegex(domain);
188
- const sqliteQuery1: CookieRow[] = await doChromeSqliteQuery1({
190
+ const sqliteQuery1: CookieRow[] = await doSqliteQueryWithTransform({
189
191
  file: file,
190
192
  sql: sql,
191
193
  rowFilter: (row) => {
@@ -199,157 +201,13 @@ async function getEncryptedChromeCookie({
199
201
  value: row["encrypted_value"],
200
202
  };
201
203
  if (parsedArgs.verbose) {
202
- console.log("CookieRow", cookieRow);
204
+ consola.info("Found", cookieRow);
203
205
  }
204
206
  return cookieRow;
205
207
  },
206
208
  });
207
209
  return sqliteQuery1.filter((row) => {
210
+ // TODO: is this needed?
208
211
  return row.domain.match(domainRegexp) != null;
209
212
  });
210
213
  }
211
-
212
- async function getChromePassword(): Promise<string> {
213
- return execSimple(
214
- 'security find-generic-password -w -s "Chrome Safe Storage"'
215
- );
216
- }
217
-
218
- async function decrypt(
219
- password: crypto.BinaryLike,
220
- encryptedData: Buffer
221
- ): Promise<string> {
222
- if (typeof password !== "string") {
223
- throw new Error("password must be a string: " + password);
224
- }
225
- let encryptedData1: any;
226
- encryptedData1 = encryptedData;
227
- if (encryptedData1 == null || typeof encryptedData1 !== "object") {
228
- throw new Error("encryptedData must be a object: " + encryptedData1);
229
- }
230
- if (!(encryptedData1 instanceof Buffer)) {
231
- if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
232
- [encryptedData1] = encryptedData1;
233
- if (parsedArgs.verbose) {
234
- console.log(
235
- `encryptedData is an array of buffers, selected first: ${encryptedData1}`
236
- );
237
- }
238
- } else {
239
- throw new Error("encryptedData must be a Buffer: " + encryptedData1);
240
- }
241
- encryptedData1 = Buffer.from(encryptedData1);
242
- }
243
- if (parsedArgs.verbose) {
244
- console.log(`Trying to decrypt with password ${password}`);
245
- }
246
- return new Promise((resolve, reject) => {
247
- crypto.pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
248
- try {
249
- if (error) {
250
- if (parsedArgs.verbose) {
251
- console.log("Error doing pbkdf2", error);
252
- }
253
- reject(error);
254
- return;
255
- }
256
-
257
- if (buffer.length !== 16) {
258
- if (parsedArgs.verbose) {
259
- console.log(
260
- "Error doing pbkdf2, buffer length is not 16",
261
- buffer.length
262
- );
263
- }
264
- reject(new Error("Buffer length is not 16"));
265
- return;
266
- }
267
-
268
- const str = new Array(17).join(" ");
269
- const iv = Buffer.from(str, "binary");
270
- const decipher = crypto.createDecipheriv("aes-128-cbc", buffer, iv);
271
- decipher.setAutoPadding(false);
272
-
273
- if (encryptedData1 && encryptedData1.slice) {
274
- encryptedData1 = encryptedData1.slice(3);
275
- }
276
-
277
- if (encryptedData1.length % 16 !== 0) {
278
- if (parsedArgs.verbose) {
279
- console.log(
280
- "Error doing pbkdf2, encryptedData length is not a multiple of 16",
281
- encryptedData1.length
282
- );
283
- }
284
- reject(new Error("encryptedData length is not a multiple of 16"));
285
- return;
286
- }
287
-
288
- let decoded = decipher.update(encryptedData1);
289
- try {
290
- decipher.final("utf-8");
291
- } catch (e) {
292
- if (parsedArgs.verbose) {
293
- console.log("Error doing decipher.final()", e);
294
- }
295
- reject(e);
296
- return;
297
- }
298
-
299
- const padding = decoded[decoded.length - 1];
300
- if (padding) {
301
- decoded = decoded.slice(0, 0 - padding);
302
- }
303
- // noinspection JSCheckFunctionSignatures
304
- const decodedString = decoded.toString("utf8");
305
- resolve(decodedString);
306
- } catch (e) {
307
- reject(e);
308
- }
309
- });
310
- });
311
- }
312
-
313
- export async function doChromeSqliteQuery1({
314
- file,
315
- sql,
316
- rowFilter = () => true,
317
- rowTransform,
318
- }: DoSqliteQuery1Params): Promise<CookieRow[]> {
319
- if (!file || (file && !fs.existsSync(file))) {
320
- throw new Error(`doSqliteQuery1: file ${file} does not exist`);
321
- }
322
- const db = new sqlite3.Database(file);
323
- return new Promise((resolve, reject) => {
324
- db.all(sql, (err: Error, rows: any[]) => {
325
- if (err) {
326
- reject(err);
327
- return;
328
- }
329
- const rows1: any[] = rows;
330
- if (rows1 == null || rows1.length === 0) {
331
- resolve([]);
332
- return;
333
- }
334
- if (Array.isArray(rows1)) {
335
- const cookieRows: CookieRow[] = rows1
336
- .filter(rowFilter)
337
- .map((row: any) => {
338
- const newVar = {
339
- meta: {
340
- file: file,
341
- },
342
- };
343
- const cookieRow: CookieRow = rowTransform(row);
344
- return merge(newVar, cookieRow);
345
- });
346
- resolve(cookieRows);
347
- return;
348
- }
349
- if (parsedArgs.verbose) {
350
- console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
351
- }
352
- resolve([rows1]);
353
- });
354
- });
355
- }
@@ -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,57 +1,14 @@
1
1
  import * as path from "path";
2
2
  import CookieQueryStrategy from "./CookieQueryStrategy";
3
3
  import { HOME } from "../global";
4
- import fs, { existsSync } from "fs";
4
+ import { existsSync } from "fs";
5
5
  import { findAllFiles } from "../findAllFiles";
6
6
  import ExportedCookie from "../ExportedCookie";
7
7
  import CookieRow from "../CookieRow";
8
8
  import CookieSpec from "../CookieSpec";
9
9
  import { specialCases } from "../SpecialCases";
10
10
  import { parsedArgs } from "../argv";
11
- import { DoSqliteQuery1Params } from "../doSqliteQuery1Params";
12
- import * as sqlite3 from "sqlite3";
13
- import { merge } from "lodash";
14
-
15
- export async function doSqliteQuery1({
16
- file,
17
- sql,
18
- rowTransform,
19
- }: DoSqliteQuery1Params): Promise<CookieRow[]> {
20
- if (!file || (file && !fs.existsSync(file))) {
21
- throw new Error(`doSqliteQuery1: file ${file} does not exist`);
22
- }
23
- const db = new sqlite3.Database(file);
24
- return new Promise((resolve, reject) => {
25
- db.all(sql, (err: Error, rows: any[]) => {
26
- if (err) {
27
- reject(err);
28
- return;
29
- }
30
- const rows1: any[] = rows;
31
- if (rows1 == null || rows1.length === 0) {
32
- resolve([]);
33
- return;
34
- }
35
- if (Array.isArray(rows1)) {
36
- const cookieRows: CookieRow[] = rows1.map((row: any) => {
37
- const newVar = {
38
- meta: {
39
- file: file,
40
- },
41
- };
42
- const cookieRow: CookieRow = rowTransform(row);
43
- return merge(newVar, cookieRow);
44
- });
45
- resolve(cookieRows);
46
- return;
47
- }
48
- if (parsedArgs.verbose) {
49
- console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
50
- }
51
- resolve([rows1]);
52
- });
53
- });
54
- }
11
+ import { doSqliteQueryWithTransform } from "./DoSqliteQueryWithTransform";
55
12
 
56
13
  export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
57
14
  browserName = "Firefox";
@@ -81,7 +38,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
81
38
  async #getFirefoxCookie(
82
39
  { name, domain }: CookieSpec //
83
40
  ) {
84
- const files: string[] = await findAllFiles({
41
+ const files: string[] = findAllFiles({
85
42
  path: path.join(
86
43
  HOME,
87
44
  "Library",
@@ -133,7 +90,7 @@ export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
133
90
  };
134
91
  };
135
92
  try {
136
- return await doSqliteQuery1({
93
+ return await doSqliteQueryWithTransform({
137
94
  file,
138
95
  sql,
139
96
  rowTransform,
@@ -0,0 +1,118 @@
1
+ import { BinaryLike, createDecipheriv, pbkdf2 } from "crypto";
2
+ import { parsedArgs } from "../argv";
3
+ import consola from "consola";
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);
14
+ }
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);
20
+ }
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
26
+ if (parsedArgs.verbose) {
27
+ console.log(
28
+ `encryptedData is an array of buffers, selected first: ${encryptedData1}`
29
+ );
30
+ }
31
+ } else {
32
+ throw new Error("encryptedData must be a Buffer: " + encryptedData1);
33
+ }
34
+ encryptedData1 = Buffer.from(encryptedData1);
35
+ }
36
+ // Log the password being used for decryption
37
+ if (parsedArgs.verbose) {
38
+ consola.start(`Trying to decrypt with password: ${password}`);
39
+ }
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);
49
+ }
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(
58
+ "Error doing pbkdf2, buffer length is not 16",
59
+ buffer.length
60
+ );
61
+ }
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);
112
+ } catch (e) {
113
+ // Reject the promise if there is an error
114
+ reject(e);
115
+ }
116
+ });
117
+ });
118
+ }
@@ -0,0 +1,9 @@
1
+ import { execSimple } from "../execSimple";
2
+
3
+ const chromePassword: Promise<string> = execSimple(
4
+ 'security find-generic-password -w -s "Chrome Safe Storage"'
5
+ );
6
+
7
+ export async function getChromePassword(): Promise<string> {
8
+ return await chromePassword;
9
+ }
@@ -0,0 +1,13 @@
1
+ import { execSync } from "child_process";
2
+
3
+ export async function execSimple(command: string): Promise<string> {
4
+ try {
5
+ const stdout = execSync(command, {
6
+ encoding: "binary",
7
+ maxBuffer: 5 * 1024,
8
+ });
9
+ return stdout.trim();
10
+ } catch (error) {
11
+ throw error;
12
+ }
13
+ }
@@ -1,65 +1,38 @@
1
- import * as fs from "fs";
2
- import { readdir } from "fs/promises";
1
+ import { existsSync } from "fs";
3
2
  import { parsedArgs } from "./argv";
4
3
  import consola from "consola";
4
+ import { sync } from "fast-glob";
5
5
 
6
- export async function findAllFiles({
7
- path,
8
- name,
9
- maxDepth = 2,
10
- }: //
11
- {
6
+ type FindFilesOptions = {
12
7
  path: string;
13
8
  name: string;
14
9
  maxDepth?: number;
15
- }): //
16
- Promise<string[]> {
17
- const rootSegments = path.split("/").length;
18
- const files: string[] = [];
19
- let readdirSync;
20
- try {
21
- readdirSync = await readdir(path);
22
- } catch (e) {
23
- if (parsedArgs.verbose) {
24
- consola.error(`Error reading ${path}`, e);
25
- }
26
- return [];
10
+ };
11
+
12
+ export function findAllFiles(
13
+ //
14
+ { path, name, maxDepth = 2 }: FindFilesOptions
15
+ ): //
16
+ string[] {
17
+ if (!existsSync(path)) {
18
+ throw new Error(`Path ${path} does not exist`);
27
19
  }
28
- for (const file of readdirSync) {
29
- const filePath = path + "/" + file;
30
- let stat;
31
- try {
32
- stat = fs.statSync(filePath);
33
- } catch (e) {
34
- if (parsedArgs.verbose) {
35
- consola.error(`Error getting stat for ${filePath}`, e);
36
- }
37
- continue;
38
- }
39
- if (stat.isDirectory()) {
40
- if (filePath.split("/").length < rootSegments + maxDepth) {
41
- try {
42
- const subFiles = await findAllFiles({
43
- path: filePath,
44
- name: name,
45
- maxDepth: 2,
46
- });
47
- files.push(...subFiles);
48
- } catch (e) {
49
- if (parsedArgs.verbose) {
50
- consola.error(e);
51
- }
52
- }
53
- }
54
- } else if (file === name) {
55
- files.push(filePath);
56
- }
20
+
21
+ if (parsedArgs.verbose) {
22
+ consola.start(`Searching for ${name} files in ${path}`);
57
23
  }
24
+
25
+ const files: string[] = sync(`${path}/**/${name}`, {
26
+ onlyFiles: true,
27
+ deep: maxDepth,
28
+ });
29
+
58
30
  if (parsedArgs.verbose) {
59
31
  if (files.length > 0) {
60
- consola.log(`Found ${files.length} ${name} files`);
61
- consola.log(files);
32
+ consola.success(`Found ${files.length} ${name} files`);
33
+ consola.info(files);
62
34
  }
63
35
  }
36
+
64
37
  return files;
65
38
  }
@@ -2,7 +2,7 @@ import CookieSpec from "./CookieSpec";
2
2
  import ExportedCookie from "./ExportedCookie";
3
3
  import { queryCookies } from "./queryCookies";
4
4
  import ChromeCookieQueryStrategy from "./browsers/ChromeCookieQueryStrategy";
5
- import { isExportedCookie } from "./IsExportedCookie";
5
+ import { isExportedCookie } from "./ExportedCookie";
6
6
 
7
7
  export async function getChromeCookie(
8
8
  params: CookieSpec
package/src/global.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { merge } from "lodash";
2
2
 
3
3
  export const env: any = {};
4
- merge(env, process.env);
4
+ merge(env, process?.env ?? {});
5
5
  export const HOME: string = env["HOME"];
6
6
  if (!HOME) {
7
7
  throw new Error("HOME environment variable is not set");
package/src/index.ts CHANGED
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env node
2
- // noinspection JSUnusedGlobalSymbols
1
+ #!/usr/bin/env bun run
3
2
 
4
3
  import { getCookie } from "./getCookie";
5
4
  import { getChromeCookie } from "./getChromeCookie";