@mherod/get-cookie 2.0.0-rc.8 → 2.1.0
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/.idea/runConfigurations/build.xml +12 -0
- package/.parcelrc +12 -0
- package/.prettierignore +5 -0
- package/.prettierrc +12 -0
- package/.terserrc +26 -0
- package/README.md +2 -2
- package/build-indexes.ts +108 -0
- package/dist/cli.js +2 -0
- package/dist/index.js +1 -823
- package/dist/index.js.map +1 -0
- package/dist/module.js +1446 -0
- package/dist/module.js.map +1 -0
- package/dist/prompt.2b8c61c0.js +40 -0
- package/dist/prompt.536a2c51.js +40 -0
- package/dist/prompt.fb2c7dad.js.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/jest.config.ts +14 -0
- package/package-lock.json +3862 -8098
- package/package.json +49 -35
- package/src/CookieRow.ts +8 -0
- package/src/CookieSpec.ts +20 -0
- package/src/CookieStore.ts +24 -7
- package/src/ExportedCookie.ts +12 -0
- package/src/FetchResponse.ts +1 -3
- package/src/FileCookieStore.ts +178 -0
- package/src/StringToRegex.ts +10 -0
- package/src/argv.ts +27 -2
- package/src/browsers/CompositeCookieQueryStrategy.ts +36 -38
- package/src/browsers/CookieQueryStrategy.ts +1 -0
- package/src/browsers/CookieStoreQueryStrategy.ts +29 -22
- package/src/browsers/QuerySqliteThenTransform.ts +85 -0
- package/src/browsers/chrome/ChromeApplicationSupport.ts +10 -0
- package/src/browsers/chrome/ChromeCookieQueryStrategy.ts +131 -0
- package/src/browsers/chrome/decrypt.ts +118 -0
- package/src/browsers/chrome/getChromePassword.ts +11 -0
- package/src/browsers/{FirefoxCookieQueryStrategy.ts → firefox/FirefoxCookieQueryStrategy.ts} +19 -16
- package/src/browsers/getEncryptedChromeCookie.ts +87 -0
- package/src/browsers/index.ts +12 -0
- package/src/browsers/mock/MockCookieQueryStrategy.ts +18 -0
- package/src/browsers/{SafariCookieQueryStrategy.ts → safari/SafariCookieQueryStrategy.ts} +3 -2
- package/src/cli.ts +43 -67
- package/src/cliQueryCookies.ts +55 -0
- package/src/comboQueryCookieSpec.test.ts +92 -0
- package/src/comboQueryCookieSpec.ts +29 -0
- package/src/cookieQueryOptions.ts +20 -0
- package/src/cookieSpecsFromUrl.test.ts +65 -0
- package/src/cookieSpecsFromUrl.ts +27 -0
- package/src/execSimple.ts +13 -0
- package/src/fetchWithCookies.test.ts +32 -0
- package/src/fetchWithCookies.ts +124 -47
- package/src/findAllFiles.ts +25 -49
- package/src/getChromeCookie.ts +6 -4
- package/src/getCookie.ts +6 -3
- package/src/getFirefoxCookie.ts +6 -4
- package/src/getGroupedRenderedCookies.ts +7 -17
- package/src/getMergedRenderedCookies.test.ts +43 -0
- package/src/getMergedRenderedCookies.ts +17 -0
- package/src/global.ts +1 -1
- package/src/index.ts +2 -7
- package/src/isValidJwt.ts +2 -2
- package/src/listChromeProfiles.ts +45 -0
- package/src/logger.ts +13 -0
- package/src/processBeforeReturn.ts +26 -0
- package/src/queryCookies.ts +11 -3
- package/src/util/flatMapAsync.test.ts +55 -0
- package/src/util/flatMapAsync.ts +37 -0
- package/src/util/index.ts +1 -0
- package/tsconfig.json +14 -11
- package/.github/dependabot.yml +0 -6
- package/.prettierrc.json +0 -1
- package/src/IsCookieRow.ts +0 -9
- package/src/IsExportedCookie.ts +0 -9
- package/src/browsers/ChromeCookieQueryStrategy.ts +0 -343
- package/src/doSqliteQuery1.ts +0 -47
- package/src/doSqliteQuery1Params.ts +0 -7
- package/src/utils.ts +0 -25
package/src/cli.ts
CHANGED
|
@@ -1,111 +1,87 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
2
|
|
|
3
3
|
import { argv, parsedArgs } from "./argv";
|
|
4
|
-
import { queryCookies } from "./queryCookies";
|
|
5
|
-
import { groupBy } from "lodash";
|
|
6
|
-
import { green, red, yellow } from "colorette";
|
|
7
|
-
import { resultsRendered } from "./resultsRendered";
|
|
8
4
|
import { fetchWithCookies } from "./fetchWithCookies";
|
|
9
5
|
import { unpackHeaders } from "./unpackHeaders";
|
|
10
6
|
import CookieSpec from "./CookieSpec";
|
|
7
|
+
import { cookieSpecsFromUrl } from "./cookieSpecsFromUrl";
|
|
8
|
+
import logger from "./logger";
|
|
9
|
+
import { cliQueryCookies } from "./cliQueryCookies";
|
|
11
10
|
|
|
12
|
-
async function
|
|
13
|
-
try {
|
|
14
|
-
const results = await queryCookies({ name, domain });
|
|
15
|
-
if (results == null || results.length == 0) {
|
|
16
|
-
console.error(red("No results"));
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (parsedArgs["dump"] || parsedArgs["d"]) {
|
|
20
|
-
console.log(results);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (parsedArgs["dump-grouped"] || parsedArgs["D"]) {
|
|
24
|
-
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
25
|
-
console.log(green(JSON.stringify(groupedByFile, null, 2)));
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (
|
|
29
|
-
parsedArgs["render"] ||
|
|
30
|
-
parsedArgs["render-merged"] ||
|
|
31
|
-
parsedArgs["r"]
|
|
32
|
-
) {
|
|
33
|
-
console.log(yellow(resultsRendered(results)));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (parsedArgs["render-grouped"] || parsedArgs["R"]) {
|
|
37
|
-
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
38
|
-
for (const file of Object.keys(groupedByFile)) {
|
|
39
|
-
let results = groupedByFile[file];
|
|
40
|
-
console.log(green(file) + ": ", yellow(resultsRendered(results)));
|
|
41
|
-
}
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
for (const result of results) {
|
|
45
|
-
console.log(result.value);
|
|
46
|
-
}
|
|
47
|
-
} catch (e) {
|
|
48
|
-
console.error(e);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function main() {
|
|
11
|
+
async function main() {
|
|
53
12
|
if (parsedArgs["help"] || parsedArgs["h"]) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
13
|
+
logger.log(`Usage: ${argv[1]} [name] [domain] [options] `);
|
|
14
|
+
logger.log(`Options:`);
|
|
15
|
+
logger.log(` -h, --help: Show this help`);
|
|
16
|
+
logger.log(` -v, --verbose: Show verbose output`);
|
|
17
|
+
logger.log(` -d, --dump: Dump all results`);
|
|
18
|
+
logger.log(` -D, --dump-grouped: Dump all results, grouped by profile`);
|
|
19
|
+
logger.log(` -r, --render: Render all results`);
|
|
61
20
|
return;
|
|
62
21
|
}
|
|
63
22
|
|
|
23
|
+
parsedArgs["verbose"] = parsedArgs["verbose"] || parsedArgs["v"];
|
|
24
|
+
|
|
64
25
|
const fetchUrl: string = parsedArgs["fetch"] || parsedArgs["F"];
|
|
65
26
|
if (fetchUrl) {
|
|
66
27
|
let url: URL;
|
|
67
28
|
try {
|
|
68
29
|
url = new URL(<string>fetchUrl);
|
|
69
30
|
} catch (e) {
|
|
70
|
-
|
|
31
|
+
logger.error("Invalid URL", fetchUrl);
|
|
71
32
|
return;
|
|
72
33
|
}
|
|
34
|
+
logger.start("Fetching", url.href);
|
|
73
35
|
const headerArgs: string[] | string = parsedArgs["H"];
|
|
74
36
|
const headers = unpackHeaders(headerArgs);
|
|
75
37
|
const onfulfilled = (res: Response) => {
|
|
76
38
|
if (parsedArgs["dump-response-headers"]) {
|
|
77
39
|
res.headers.forEach((value: string, key: string) => {
|
|
78
|
-
|
|
40
|
+
logger.log(`${key}: ${value}`);
|
|
79
41
|
});
|
|
80
42
|
}
|
|
81
43
|
if (parsedArgs["dump-response-body"]) {
|
|
82
44
|
res.text().then((r) => {
|
|
83
|
-
|
|
45
|
+
logger.log(r);
|
|
84
46
|
});
|
|
85
47
|
}
|
|
86
48
|
return;
|
|
87
49
|
};
|
|
88
|
-
fetchWithCookies(
|
|
50
|
+
return fetchWithCookies(
|
|
89
51
|
url,
|
|
90
52
|
{
|
|
91
53
|
//
|
|
92
54
|
headers,
|
|
93
|
-
}
|
|
55
|
+
},
|
|
94
56
|
//
|
|
95
57
|
).then(
|
|
96
|
-
|
|
97
|
-
|
|
58
|
+
(res) => {
|
|
59
|
+
logger.debug("Response", res);
|
|
60
|
+
onfulfilled(res);
|
|
61
|
+
},
|
|
62
|
+
logger.error,
|
|
98
63
|
//
|
|
99
64
|
);
|
|
100
|
-
return;
|
|
101
65
|
}
|
|
102
66
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
67
|
+
const cookieSpecs: CookieSpec[] = [];
|
|
68
|
+
const argUrl: string = parsedArgs["url"] || parsedArgs["u"];
|
|
69
|
+
if (argUrl) {
|
|
70
|
+
for (const cookieSpec of cookieSpecsFromUrl(argUrl)) {
|
|
71
|
+
cookieSpecs.push(cookieSpec);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
cookieSpecs.push({
|
|
75
|
+
name: parsedArgs["name"] || parsedArgs["_"][0] || "%",
|
|
76
|
+
domain: parsedArgs["domain"] || parsedArgs["_"][1] || "%",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (parsedArgs.verbose) {
|
|
81
|
+
logger.log("cookieSpecs", cookieSpecs);
|
|
82
|
+
}
|
|
107
83
|
|
|
108
|
-
cliQueryCookies(
|
|
84
|
+
await cliQueryCookies(cookieSpecs).catch(logger.error);
|
|
109
85
|
}
|
|
110
86
|
|
|
111
|
-
main();
|
|
87
|
+
main().then((r) => r, logger.error);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import CookieSpec from "./CookieSpec";
|
|
2
|
+
import ExportedCookie from "./ExportedCookie";
|
|
3
|
+
import { comboQueryCookieSpec } from "./comboQueryCookieSpec";
|
|
4
|
+
import { groupBy } from "lodash";
|
|
5
|
+
import logger from "./logger";
|
|
6
|
+
import { parsedArgs } from "./argv";
|
|
7
|
+
import { resultsRendered } from "./resultsRendered";
|
|
8
|
+
|
|
9
|
+
export async function cliQueryCookies(
|
|
10
|
+
cookieSpec: CookieSpec | CookieSpec[],
|
|
11
|
+
limit?: number,
|
|
12
|
+
removeExpired?: boolean,
|
|
13
|
+
//
|
|
14
|
+
) {
|
|
15
|
+
try {
|
|
16
|
+
const results: ExportedCookie[] = await comboQueryCookieSpec(cookieSpec, {
|
|
17
|
+
limit,
|
|
18
|
+
removeExpired,
|
|
19
|
+
});
|
|
20
|
+
if (results == null || results.length == 0) {
|
|
21
|
+
logger.error("No results");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (parsedArgs["dump"] || parsedArgs["d"]) {
|
|
25
|
+
logger.log(results);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (parsedArgs["dump-grouped"] || parsedArgs["D"]) {
|
|
29
|
+
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
30
|
+
logger.log(JSON.stringify(groupedByFile, null, 2));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (
|
|
34
|
+
parsedArgs["render"] ||
|
|
35
|
+
parsedArgs["render-merged"] ||
|
|
36
|
+
parsedArgs["r"]
|
|
37
|
+
) {
|
|
38
|
+
logger.log(resultsRendered(results));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (parsedArgs["render-grouped"] || parsedArgs["R"]) {
|
|
42
|
+
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
43
|
+
for (const file of Object.keys(groupedByFile)) {
|
|
44
|
+
let results = groupedByFile[file];
|
|
45
|
+
logger.log(file, ": ", resultsRendered(results));
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (const result of results) {
|
|
50
|
+
logger.log(result.value);
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
logger.error(e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { MultiCookieSpec } from "./CookieSpec";
|
|
2
|
+
import CookieQueryStrategy from "./browsers/CookieQueryStrategy";
|
|
3
|
+
import MockCookieQueryStrategy from "./browsers/mock/MockCookieQueryStrategy";
|
|
4
|
+
import { comboQueryCookieSpec } from "./comboQueryCookieSpec";
|
|
5
|
+
import { CookieQueryOptions } from "./cookieQueryOptions";
|
|
6
|
+
|
|
7
|
+
describe("comboQueryCookieSpec", () => {
|
|
8
|
+
let cookieSpec: MultiCookieSpec;
|
|
9
|
+
let options: CookieQueryOptions<CookieQueryStrategy>;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
cookieSpec = {
|
|
13
|
+
domain: "example.com",
|
|
14
|
+
name: "test",
|
|
15
|
+
};
|
|
16
|
+
options = {
|
|
17
|
+
strategy: new MockCookieQueryStrategy([
|
|
18
|
+
// mock available cookies here
|
|
19
|
+
{
|
|
20
|
+
name: "test",
|
|
21
|
+
value: "test",
|
|
22
|
+
domain: "example.com",
|
|
23
|
+
expiry: "Infinity",
|
|
24
|
+
},
|
|
25
|
+
]),
|
|
26
|
+
limit: 10,
|
|
27
|
+
removeExpired: true,
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should return an array of cookies", async () => {
|
|
32
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
33
|
+
expect(result).toBeInstanceOf(Array);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should limit the number of cookies returned", async () => {
|
|
37
|
+
options.limit = 5;
|
|
38
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
39
|
+
expect(result.length).toBeLessThanOrEqual(5);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should return cookies with the correct domain", async () => {
|
|
43
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
44
|
+
expect(result[0].domain).toBe("example.com");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should return cookies with the correct name", async () => {
|
|
48
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
49
|
+
expect(result[0].name).toBe("test");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should return cookies with the correct value", async () => {
|
|
53
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
54
|
+
expect(result[0].value).toBe("test");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should return cookies with the correct expiry", async () => {
|
|
58
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
59
|
+
expect(result[0].expiry).toBe("Infinity");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should return cookies with the correct meta", async () => {
|
|
63
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
64
|
+
expect(result[0].meta).toBeUndefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should return cookies when limit is undefined", async () => {
|
|
68
|
+
options.limit = undefined;
|
|
69
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
70
|
+
expect(result.length).toBe(1);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should return cookies when removeExpired is false", async () => {
|
|
74
|
+
options.removeExpired = false;
|
|
75
|
+
const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
76
|
+
expect(result.length).toBe(1);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// it('should not return cookies when removeExpired is true and expiry is past', async () => {
|
|
80
|
+
// options.removeExpired = true;
|
|
81
|
+
// cookieSpec.expiry = new Date('2000-01-01');
|
|
82
|
+
// const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
83
|
+
// expect(result.length).toBe(0);
|
|
84
|
+
// });
|
|
85
|
+
|
|
86
|
+
// it('should return cookies when removeExpired is true and expiry is future', async () => {
|
|
87
|
+
// options.removeExpired = true;
|
|
88
|
+
// cookieSpec.expiry = new Date('3000-01-01');
|
|
89
|
+
// const result = await comboQueryCookieSpec(cookieSpec, options);
|
|
90
|
+
// expect(result.length).toBe(1);
|
|
91
|
+
// });
|
|
92
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import CookieSpec, { MultiCookieSpec } from "./CookieSpec";
|
|
2
|
+
import ExportedCookie from "./ExportedCookie";
|
|
3
|
+
import { queryCookies } from "./queryCookies";
|
|
4
|
+
import { flatMapAsync } from "./util";
|
|
5
|
+
import CookieQueryStrategy from "./browsers/CookieQueryStrategy";
|
|
6
|
+
import { CookieQueryOptions, mergedWithDefaults } from "./cookieQueryOptions";
|
|
7
|
+
import { processBeforeReturn } from "./processBeforeReturn";
|
|
8
|
+
|
|
9
|
+
export async function comboQueryCookieSpec(
|
|
10
|
+
cookieSpec: MultiCookieSpec,
|
|
11
|
+
options?: CookieQueryOptions<CookieQueryStrategy>,
|
|
12
|
+
): Promise<ExportedCookie[]> {
|
|
13
|
+
const optsWithDefaults: CookieQueryOptions<CookieQueryStrategy> =
|
|
14
|
+
mergedWithDefaults(options);
|
|
15
|
+
const fn = (cs: CookieSpec) => queryCookies(cs, optsWithDefaults);
|
|
16
|
+
|
|
17
|
+
if (Array.isArray(cookieSpec)) {
|
|
18
|
+
const cookiesForMultiSpec: ExportedCookie[] = await flatMapAsync(
|
|
19
|
+
cookieSpec,
|
|
20
|
+
async (cs: CookieSpec) => {
|
|
21
|
+
return await fn(cs);
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
return processBeforeReturn(cookiesForMultiSpec, options);
|
|
25
|
+
} else {
|
|
26
|
+
const cookiesForSingleSpec: ExportedCookie[] = await fn(cookieSpec);
|
|
27
|
+
return processBeforeReturn(cookiesForSingleSpec, options);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import CookieQueryStrategy from "./browsers/CookieQueryStrategy";
|
|
2
|
+
import CompositeCookieQueryStrategy from "./browsers/CompositeCookieQueryStrategy";
|
|
3
|
+
import { merge } from "lodash";
|
|
4
|
+
|
|
5
|
+
export type CookieQueryOptions<T extends CookieQueryStrategy> = {
|
|
6
|
+
strategy?: T;
|
|
7
|
+
limit?: number;
|
|
8
|
+
removeExpired?: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const defaultCookieQueryOptions: CookieQueryOptions<CookieQueryStrategy> =
|
|
12
|
+
{
|
|
13
|
+
strategy: new CompositeCookieQueryStrategy(),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function mergedWithDefaults<T extends CookieQueryStrategy>(
|
|
17
|
+
options?: CookieQueryOptions<T>,
|
|
18
|
+
): CookieQueryOptions<T> {
|
|
19
|
+
return merge(defaultCookieQueryOptions, options);
|
|
20
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cookieSpecsFromUrl } from "./cookieSpecsFromUrl";
|
|
2
|
+
import { isCookieSpec } from "./CookieSpec";
|
|
3
|
+
import { uniqBy } from "lodash";
|
|
4
|
+
|
|
5
|
+
describe("cookieSpecsFromUrl", () => {
|
|
6
|
+
it("should return an array of cookie specs", () => {
|
|
7
|
+
const url = "https://example.com/";
|
|
8
|
+
const result = cookieSpecsFromUrl(url);
|
|
9
|
+
expect(result).toBeInstanceOf(Array);
|
|
10
|
+
expect(isCookieSpec(result[0])).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should handle string URLs", () => {
|
|
14
|
+
const url = "https://example.com/";
|
|
15
|
+
const result = cookieSpecsFromUrl(url);
|
|
16
|
+
expect(result[0].domain).toContain("example.com");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should handle URL objects", () => {
|
|
20
|
+
const url = new URL("https://example.com/");
|
|
21
|
+
const result = cookieSpecsFromUrl(url);
|
|
22
|
+
expect(result[0].domain).toContain("example.com");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should handle empty string URL", () => {
|
|
26
|
+
const url = "";
|
|
27
|
+
const result = cookieSpecsFromUrl(url);
|
|
28
|
+
expect(result).toEqual([]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should handle invalid URL", () => {
|
|
32
|
+
const url = "invalid_url";
|
|
33
|
+
try {
|
|
34
|
+
const result = cookieSpecsFromUrl(url);
|
|
35
|
+
} catch (error: any) {
|
|
36
|
+
expect(error.message).toContain("Invalid URL");
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should return unique cookie specs", () => {
|
|
41
|
+
const url = "https://example.com/";
|
|
42
|
+
const result = cookieSpecsFromUrl(url);
|
|
43
|
+
const uniqueResults = uniqBy(result, JSON.stringify);
|
|
44
|
+
expect(result.length).toEqual(uniqueResults.length);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should return correct cookie specs for URL with subdomain", () => {
|
|
48
|
+
const url = "https://sub.example.com/";
|
|
49
|
+
const result = cookieSpecsFromUrl(url);
|
|
50
|
+
expect(result).toContainEqual({ name: "%", domain: "sub.example.com" });
|
|
51
|
+
expect(result).toContainEqual({ name: "%", domain: "%.example.com" });
|
|
52
|
+
expect(result).toContainEqual({ name: "%", domain: "example.com" });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should return correct cookie specs for URL with multiple subdomains", () => {
|
|
56
|
+
const url = "https://sub.sub2.example.com/";
|
|
57
|
+
const result = cookieSpecsFromUrl(url);
|
|
58
|
+
expect(result).toContainEqual({
|
|
59
|
+
name: "%",
|
|
60
|
+
domain: "sub.sub2.example.com",
|
|
61
|
+
});
|
|
62
|
+
expect(result).toContainEqual({ name: "%", domain: "%.example.com" });
|
|
63
|
+
expect(result).toContainEqual({ name: "%", domain: "example.com" });
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import CookieSpec from "./CookieSpec";
|
|
2
|
+
import { uniqBy } from "lodash";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generates a list of cookie specifications from a given URL.
|
|
6
|
+
* Each cookie spec consists of a domain and a name, where the name is a wildcard.
|
|
7
|
+
* The domain is formatted to enable querying against the cookie store for matching cookies.
|
|
8
|
+
* @param url - The URL to generate cookie specs from.
|
|
9
|
+
* @returns An array of unique cookie specifications.
|
|
10
|
+
*/
|
|
11
|
+
export function cookieSpecsFromUrl(url: URL | string): CookieSpec[] {
|
|
12
|
+
if (!url || url === "") {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const urlObj = typeof url === "string" ? new URL(url) : url;
|
|
17
|
+
const hostnameParts = urlObj.hostname.split(".");
|
|
18
|
+
const topLevelDomain = hostnameParts.slice(-2).join(".");
|
|
19
|
+
|
|
20
|
+
const cookieSpecs: CookieSpec[] = [
|
|
21
|
+
{ name: "%", domain: `%.${topLevelDomain}` },
|
|
22
|
+
{ name: "%", domain: urlObj.hostname },
|
|
23
|
+
{ name: "%", domain: topLevelDomain },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
return uniqBy(cookieSpecs, JSON.stringify);
|
|
27
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { fetchWithCookies } from "./fetchWithCookies";
|
|
2
|
+
import { FetchFn } from "./fetchWithCookies";
|
|
3
|
+
|
|
4
|
+
describe("fetchWithCookies", () => {
|
|
5
|
+
let mockFetch: FetchFn;
|
|
6
|
+
let mockResponse: Response;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
mockFetch = jest.fn();
|
|
10
|
+
mockResponse = new Response("mock body", { status: 200 });
|
|
11
|
+
(mockFetch as jest.Mock).mockResolvedValue(mockResponse);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// it("should call fetch with the correct arguments", async () => {
|
|
15
|
+
// const url = "https://example.com/";
|
|
16
|
+
// const options: RequestInit = {
|
|
17
|
+
// method: "GET",
|
|
18
|
+
// headers: { "User-Agent": userAgent },
|
|
19
|
+
// redirect: "manual"
|
|
20
|
+
// //
|
|
21
|
+
// };
|
|
22
|
+
// await fetchWithCookies(url, options, mockFetch);
|
|
23
|
+
// expect(mockFetch).toBeCalledWith(url, options);
|
|
24
|
+
// });
|
|
25
|
+
|
|
26
|
+
it("should return the response from fetch", async () => {
|
|
27
|
+
const url = "https://example.com/";
|
|
28
|
+
const options = { method: "GET" };
|
|
29
|
+
const response = await fetchWithCookies(url, options, mockFetch);
|
|
30
|
+
expect(response).toBe(mockResponse);
|
|
31
|
+
});
|
|
32
|
+
});
|