@mherod/get-cookie 2.0.0-rc.9 → 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.
Files changed (77) 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/build-indexes.ts +108 -0
  8. package/dist/cli.js +2 -0
  9. package/dist/index.js +1 -846
  10. package/dist/index.js.map +1 -0
  11. package/dist/module.js +1446 -0
  12. package/dist/module.js.map +1 -0
  13. package/dist/prompt.2b8c61c0.js +40 -0
  14. package/dist/prompt.536a2c51.js +40 -0
  15. package/dist/prompt.fb2c7dad.js.map +1 -0
  16. package/dist/types.d.ts +30 -0
  17. package/dist/types.d.ts.map +1 -0
  18. package/jest.config.ts +14 -0
  19. package/package-lock.json +3862 -8098
  20. package/package.json +49 -35
  21. package/src/CookieRow.ts +8 -0
  22. package/src/CookieSpec.ts +20 -0
  23. package/src/CookieStore.ts +24 -7
  24. package/src/ExportedCookie.ts +12 -0
  25. package/src/FetchResponse.ts +1 -3
  26. package/src/FileCookieStore.ts +178 -0
  27. package/src/StringToRegex.ts +10 -0
  28. package/src/argv.ts +27 -2
  29. package/src/browsers/CompositeCookieQueryStrategy.ts +36 -38
  30. package/src/browsers/CookieQueryStrategy.ts +1 -0
  31. package/src/browsers/CookieStoreQueryStrategy.ts +29 -22
  32. package/src/browsers/QuerySqliteThenTransform.ts +85 -0
  33. package/src/browsers/chrome/ChromeApplicationSupport.ts +10 -0
  34. package/src/browsers/chrome/ChromeCookieQueryStrategy.ts +131 -0
  35. package/src/browsers/chrome/decrypt.ts +118 -0
  36. package/src/browsers/chrome/getChromePassword.ts +11 -0
  37. package/src/browsers/{FirefoxCookieQueryStrategy.ts → firefox/FirefoxCookieQueryStrategy.ts} +19 -16
  38. package/src/browsers/getEncryptedChromeCookie.ts +87 -0
  39. package/src/browsers/index.ts +12 -0
  40. package/src/browsers/mock/MockCookieQueryStrategy.ts +18 -0
  41. package/src/browsers/{SafariCookieQueryStrategy.ts → safari/SafariCookieQueryStrategy.ts} +3 -2
  42. package/src/cli.ts +43 -67
  43. package/src/cliQueryCookies.ts +55 -0
  44. package/src/comboQueryCookieSpec.test.ts +92 -0
  45. package/src/comboQueryCookieSpec.ts +29 -0
  46. package/src/cookieQueryOptions.ts +20 -0
  47. package/src/cookieSpecsFromUrl.test.ts +65 -0
  48. package/src/cookieSpecsFromUrl.ts +27 -0
  49. package/src/execSimple.ts +13 -0
  50. package/src/fetchWithCookies.test.ts +32 -0
  51. package/src/fetchWithCookies.ts +123 -49
  52. package/src/findAllFiles.ts +25 -49
  53. package/src/getChromeCookie.ts +6 -4
  54. package/src/getCookie.ts +6 -3
  55. package/src/getFirefoxCookie.ts +6 -4
  56. package/src/getGroupedRenderedCookies.ts +7 -17
  57. package/src/getMergedRenderedCookies.test.ts +43 -0
  58. package/src/getMergedRenderedCookies.ts +13 -21
  59. package/src/global.ts +1 -1
  60. package/src/index.ts +0 -7
  61. package/src/isValidJwt.ts +2 -2
  62. package/src/listChromeProfiles.ts +45 -0
  63. package/src/logger.ts +13 -0
  64. package/src/processBeforeReturn.ts +26 -0
  65. package/src/queryCookies.ts +11 -3
  66. package/src/util/flatMapAsync.test.ts +55 -0
  67. package/src/util/flatMapAsync.ts +37 -0
  68. package/src/util/index.ts +1 -0
  69. package/tsconfig.json +14 -11
  70. package/.github/dependabot.yml +0 -6
  71. package/.prettierrc.json +0 -1
  72. package/src/IsCookieRow.ts +0 -9
  73. package/src/IsExportedCookie.ts +0 -9
  74. package/src/browsers/ChromeCookieQueryStrategy.ts +0 -343
  75. package/src/doSqliteQuery1.ts +0 -47
  76. package/src/doSqliteQuery1Params.ts +0 -7
  77. package/src/utils.ts +0 -25
@@ -0,0 +1,55 @@
1
+ import { flatMapAsync } from "./flatMapAsync";
2
+
3
+ describe("flatMapAsync", () => {
4
+ it("should apply async callback to each element, wait for all promises to fulfill and flatten the resulting array", async () => {
5
+ const array = [1, 2, 3];
6
+ const callback = async (value: number) => [value, value * 2];
7
+ const result = await flatMapAsync(array, callback);
8
+ expect(result).toEqual([1, 2, 2, 4, 3, 6]);
9
+ });
10
+
11
+ it("should handle errors with the provided error callback", async () => {
12
+ const array = [1, 2, 3];
13
+ const callback = async (value: number) => {
14
+ if (value === 2) {
15
+ throw new Error("Test error");
16
+ }
17
+ return [value, value * 2];
18
+ };
19
+ const errorCallback = (error: any) => [0];
20
+ const result = await flatMapAsync(array, callback, errorCallback);
21
+ expect(result).toEqual([1, 2, 0, 3, 6]);
22
+ });
23
+
24
+ it("should return an empty array when input array is empty", async () => {
25
+ const array: number[] = [];
26
+ const callback = async (value: number) => [value, value * 2];
27
+ const result = await flatMapAsync(array, callback);
28
+ expect(result).toEqual([]);
29
+ });
30
+
31
+ it("should return an array with single element when input array has one element", async () => {
32
+ const array = [1];
33
+ const callback = async (value: number) => [value, value * 2];
34
+ const result = await flatMapAsync(array, callback);
35
+ expect(result).toEqual([1, 2]);
36
+ });
37
+
38
+ it("should handle null values in the array", async () => {
39
+ const array = [1, null, 3];
40
+ const callback = async (value: number) =>
41
+ value ? [value, value * 2] : [0];
42
+ // @ts-expect-error
43
+ const result = await flatMapAsync(array, callback);
44
+ expect(result).toEqual([1, 2, 0, 3, 6]);
45
+ });
46
+
47
+ it("should handle undefined values in the array", async () => {
48
+ const array = [1, undefined, 3];
49
+ const callback = async (value: number) =>
50
+ value ? [value, value * 2] : [0];
51
+ // @ts-expect-error
52
+ const result = await flatMapAsync(array, callback);
53
+ expect(result).toEqual([1, 2, 0, 3, 6]);
54
+ });
55
+ });
@@ -0,0 +1,37 @@
1
+ // This utility function applies an async callback to each element of the input array (just like Array.prototype.map),
2
+ // waits for all resulting promises to fulfill (similar to Promise.all), and then flattens the resulting array (like Array.prototype.flat).
3
+
4
+ export async function flatMapAsync<T, O>(
5
+ array: T[], // The input array to transform.
6
+ callback: (value: T, index: number, array: T[]) => Promise<O[]>, // The async function to apply to each input array element.,
7
+ or?: O[] | ((error: any) => O[] | Promise<O[]>), // An optional callback to handle errors.
8
+ ): Promise<O[]> {
9
+ if (or) {
10
+ return flatMapAsync(
11
+ array,
12
+ async (value: T, index: number, array: T[]) => {
13
+ try {
14
+ return await callback(value, index, array);
15
+ } catch (error) {
16
+ return typeof or == "function" ? or(error) : or;
17
+ }
18
+ },
19
+ //
20
+ );
21
+ }
22
+
23
+ // Step 1: Use Array.prototype.map to transform each element of the input array with the provided callback.
24
+ // This will result in an array of promises.
25
+ const ps: Promise<O>[] = array.map(callback) as Promise<O>[];
26
+
27
+ // Step 2: Use Promise.all to wait for all promises in the array to fulfill.
28
+ // This will give us an array of fulfilled promise values.
29
+ const awaitedAll: Awaited<O>[] = await Promise.all(ps);
30
+
31
+ // Step 3: Flatten the array of fulfilled promise values into a single array.
32
+ // Note: The '@ts-ignore' comment is used to suppress TypeScript compiler warnings, as .flat() method might not be recognized
33
+ // as a valid method for an array of Awaited<O> instances. However, this code assumes that the result of Promise.all
34
+ // is indeed an array that can be flattened.
35
+ // @ts-ignore
36
+ return awaitedAll.flat() as O[];
37
+ }
@@ -0,0 +1 @@
1
+ export * from "./flatMapAsync";
package/tsconfig.json CHANGED
@@ -3,21 +3,24 @@
3
3
  "src/**.ts",
4
4
  "src/**.tsx",
5
5
  "src/**.js",
6
- "src/**.jsx"
6
+ "src/**.jsx",
7
+ "src/**.test.ts",
8
+ "src/**.test.js"
7
9
  ],
8
10
  "compilerOptions": {
9
11
  "moduleResolution": "node",
10
- "target": "es2021",
11
- "types": [
12
- "node"
13
- ],
14
- "lib": [
15
- "es2015",
16
- "es2017",
17
- "es2021",
18
- "dom"
19
- ],
12
+ "target": "es6",
13
+ "types": ["node", "jest"],
14
+ "lib": ["es2015", "es2017", "es2021", "dom"],
20
15
  "strict": true,
16
+ "skipDefaultLibCheck": true,
17
+ "skipLibCheck": true,
21
18
  "allowSyntheticDefaultImports": true,
19
+ "emitDeclarationOnly": true,
20
+ "declaration": true,
21
+ "esModuleInterop": true,
22
+ "module": "commonjs",
23
+ "outDir": "dist",
24
+ "outFile": "dist/types.d.ts"
22
25
  }
23
26
  }
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "npm"
4
- directory: "/"
5
- schedule:
6
- interval: "daily"
package/.prettierrc.json DELETED
@@ -1 +0,0 @@
1
- {}
@@ -1,9 +0,0 @@
1
- import CookieRow from "./CookieRow";
2
-
3
- export function isCookieRow(obj: any): obj is CookieRow {
4
- return (
5
- obj.domain !== undefined &&
6
- obj.name !== undefined &&
7
- obj.value !== undefined
8
- );
9
- }
@@ -1,9 +0,0 @@
1
- import ExportedCookie from "./ExportedCookie";
2
-
3
- export function isExportedCookie(obj: any): obj is ExportedCookie {
4
- return (
5
- obj.domain !== undefined &&
6
- obj.name !== undefined &&
7
- obj.value !== undefined
8
- );
9
- }
@@ -1,343 +0,0 @@
1
- import CookieQueryStrategy from "./CookieQueryStrategy";
2
- import { execSimple } from "../utils";
3
- import { env, HOME } from "../global";
4
- import { existsSync } from "fs";
5
- import { findAllFiles } from "../findAllFiles";
6
- import * as crypto from "crypto";
7
- import * as path from "path";
8
- import { doSqliteQuery1 } from "../doSqliteQuery1";
9
- import { merge } from "lodash";
10
- import { isCookieRow } from "../IsCookieRow";
11
- import { isExportedCookie } from "../IsExportedCookie";
12
- import CookieRow from "../CookieRow";
13
- import ExportedCookie from "../ExportedCookie";
14
- import { stringToRegex } from "../StringToRegex";
15
- import { parsedArgs } from "../argv";
16
- import fs from "fs";
17
- import * as sqlite3 from "sqlite3";
18
- import { DoSqliteQuery1Params } from "../doSqliteQuery1Params";
19
-
20
- export default class ChromeCookieQueryStrategy implements CookieQueryStrategy {
21
- browserName = "Chrome";
22
-
23
- async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
24
- if (process.platform !== "darwin") {
25
- throw new Error("This only works on macOS");
26
- }
27
- if (env.FIREFOX_ONLY) {
28
- return [];
29
- }
30
- return getChromeCookies({
31
- requireJwt: false,
32
- name,
33
- domain,
34
- });
35
- }
36
- }
37
-
38
- async function getPromise1(
39
- name: string,
40
- domain: string,
41
- file: string
42
- ): Promise<CookieRow[]> {
43
- try {
44
- return await getEncryptedChromeCookie({
45
- name: name,
46
- domain: domain,
47
- file: file,
48
- });
49
- } catch (e) {
50
- if (parsedArgs.verbose) {
51
- console.log("Error getting encrypted cookie", e);
52
- }
53
- return [];
54
- }
55
- }
56
-
57
- async function getPromise(name: string, domain: string): Promise<CookieRow[]> {
58
- try {
59
- const files: string[] = await findAllFiles({
60
- path: chromeLocal,
61
- name: "Cookies",
62
- });
63
- const promises: Promise<CookieRow[]>[] = files.map((file) =>
64
- getPromise1(name, domain, file)
65
- );
66
- const results1: CookieRow[][] = await Promise.all(promises);
67
- return results1.flat().filter(isCookieRow);
68
- } catch (error) {
69
- if (parsedArgs.verbose) {
70
- console.log("error", error);
71
- }
72
- return [];
73
- }
74
- }
75
-
76
- async function decryptValue(password: string, encryptedValue: Buffer) {
77
- let d: string | null;
78
- try {
79
- d = await decrypt(password, encryptedValue);
80
- } catch (e) {
81
- if (parsedArgs.verbose) {
82
- console.log("Error decrypting cookie", e);
83
- }
84
- d = null;
85
- }
86
- return d ?? encryptedValue.toString("utf-8");
87
- }
88
-
89
- async function getChromeCookies({
90
- name,
91
- domain = "%",
92
- requireJwt = false,
93
- }: {
94
- name: string;
95
- domain: string;
96
- requireJwt: boolean | undefined;
97
- //
98
- }): //
99
- Promise<ExportedCookie[]> {
100
- const encryptedDataItems: CookieRow[] = await getPromise(name, domain);
101
- const password: string = await getChromePassword();
102
- const decrypted: Promise<ExportedCookie | null>[] = encryptedDataItems
103
- .filter(({ value }) => value != null && value.length > 0)
104
- .map(async (cookieRow: CookieRow) => {
105
- const encryptedValue: Buffer = cookieRow.value;
106
- const decryptedValue = await decryptValue(password, encryptedValue);
107
- const meta = {};
108
- merge(meta, cookieRow.meta ?? {});
109
- const exportedCookie: ExportedCookie = {
110
- domain: cookieRow.domain,
111
- name: cookieRow.name,
112
- value: decryptedValue,
113
- meta: meta,
114
- };
115
- const expiry = cookieRow.expiry;
116
- if (expiry) {
117
- merge(exportedCookie, {
118
- expiry: new Date(expiry),
119
- });
120
- }
121
- return exportedCookie;
122
- });
123
- const results: ExportedCookie[] = (await Promise.all(decrypted)).filter(
124
- isExportedCookie
125
- );
126
- if (parsedArgs.verbose) {
127
- console.log("results", results);
128
- }
129
- return results;
130
- }
131
-
132
- const chromeLocal = path.join(
133
- HOME,
134
- "Library",
135
- "Application Support",
136
- "Google",
137
- "Chrome"
138
- );
139
-
140
- async function getEncryptedChromeCookie({
141
- name,
142
- domain,
143
- file = path.join(chromeLocal, "Default", "Cookies"),
144
- }: //
145
- {
146
- name: string;
147
- domain: string;
148
- file: string;
149
- }): Promise<CookieRow[]> {
150
- if (!existsSync(file)) {
151
- throw new Error(`File ${file} does not exist`);
152
- }
153
- if (parsedArgs.verbose) {
154
- const s = file.split("/").slice(-3).join("/");
155
- console.log(`Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`);
156
- }
157
- let sql;
158
- //language=SQL
159
- sql = "SELECT * FROM cookies";
160
- // sql = "SELECT encrypted_value, name, host_key FROM cookies";
161
-
162
- const wildcardRegexp = /^([*%])$/i;
163
- const specifiedName = name.match(wildcardRegexp) == null;
164
- const specifiedDomain = domain.match(wildcardRegexp) == null;
165
- const wildcardDomain = domain.match(/[%*]/) != null;
166
- const queryDomain = specifiedDomain && !wildcardDomain;
167
- // if we have a wildcard domain, we need to use a regexp
168
- if (specifiedName || queryDomain) {
169
- sql += ` WHERE `;
170
- if (specifiedName) {
171
- sql += `name = '${name}'`;
172
- if (queryDomain) {
173
- sql += ` AND `;
174
- }
175
- }
176
- if (queryDomain) {
177
- // leading dot replaced with % to match subdomains
178
- const sqlEmbedDomain = domain.replace(/^[.%]?/, "%");
179
- sql += `host_key LIKE '${sqlEmbedDomain}';`;
180
- }
181
- }
182
- const sqliteQuery1: CookieRow[] = await doChromeSqliteQuery1({
183
- file: file,
184
- sql: sql,
185
- rowTransform: (row) => {
186
- const cookieRow = {
187
- expiry: (row["expires_utc"] / 1000000 - 11644473600) * 1000,
188
- domain: row["host_key"],
189
- name: row["name"],
190
- value: row["encrypted_value"],
191
- };
192
- if (parsedArgs.verbose) {
193
- console.log("CookieRow", cookieRow);
194
- }
195
- return cookieRow;
196
- },
197
- });
198
- return sqliteQuery1.filter((row) => {
199
- return row.domain.match(stringToRegex(domain)) != null;
200
- });
201
- }
202
-
203
- async function getChromePassword(): Promise<string> {
204
- return execSimple(
205
- 'security find-generic-password -w -s "Chrome Safe Storage"'
206
- );
207
- }
208
-
209
- async function decrypt(
210
- password: crypto.BinaryLike,
211
- encryptedData: Buffer
212
- ): Promise<string> {
213
- if (typeof password !== "string") {
214
- throw new Error("password must be a string: " + password);
215
- }
216
- let encryptedData1: any;
217
- encryptedData1 = encryptedData;
218
- if (encryptedData1 == null || typeof encryptedData1 !== "object") {
219
- throw new Error("encryptedData must be a object: " + encryptedData1);
220
- }
221
- if (!(encryptedData1 instanceof Buffer)) {
222
- if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
223
- [encryptedData1] = encryptedData1;
224
- if (parsedArgs.verbose) {
225
- console.log(
226
- `encryptedData is an array of buffers, selected first: ${encryptedData1}`
227
- );
228
- }
229
- } else {
230
- throw new Error("encryptedData must be a Buffer: " + encryptedData1);
231
- }
232
- encryptedData1 = Buffer.from(encryptedData1);
233
- }
234
- if (parsedArgs.verbose) {
235
- console.log(`Trying to decrypt with password ${password}`);
236
- }
237
- return new Promise((resolve, reject) => {
238
- crypto.pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
239
- try {
240
- if (error) {
241
- if (parsedArgs.verbose) {
242
- console.log("Error doing pbkdf2", error);
243
- }
244
- reject(error);
245
- return;
246
- }
247
-
248
- if (buffer.length !== 16) {
249
- if (parsedArgs.verbose) {
250
- console.log(
251
- "Error doing pbkdf2, buffer length is not 16",
252
- buffer.length
253
- );
254
- }
255
- reject(new Error("Buffer length is not 16"));
256
- return;
257
- }
258
-
259
- const str = new Array(17).join(" ");
260
- const iv = Buffer.from(str, "binary");
261
- const decipher = crypto.createDecipheriv("aes-128-cbc", buffer, iv);
262
- decipher.setAutoPadding(false);
263
-
264
- if (encryptedData1 && encryptedData1.slice) {
265
- encryptedData1 = encryptedData1.slice(3);
266
- }
267
-
268
- if (encryptedData1.length % 16 !== 0) {
269
- if (parsedArgs.verbose) {
270
- console.log(
271
- "Error doing pbkdf2, encryptedData length is not a multiple of 16",
272
- encryptedData1.length
273
- );
274
- }
275
- reject(new Error("encryptedData length is not a multiple of 16"));
276
- return;
277
- }
278
-
279
- let decoded = decipher.update(encryptedData1);
280
- try {
281
- decipher.final("utf-8");
282
- } catch (e) {
283
- if (parsedArgs.verbose) {
284
- console.log("Error doing decipher.final()", e);
285
- }
286
- reject(e);
287
- return;
288
- }
289
-
290
- const padding = decoded[decoded.length - 1];
291
- if (padding) {
292
- decoded = decoded.slice(0, 0 - padding);
293
- }
294
- // noinspection JSCheckFunctionSignatures
295
- const decodedString = decoded.toString("utf8");
296
- resolve(decodedString);
297
- } catch (e) {
298
- reject(e);
299
- }
300
- });
301
- });
302
- }
303
-
304
- export async function doChromeSqliteQuery1({
305
- file,
306
- sql,
307
- rowTransform,
308
- }: DoSqliteQuery1Params): Promise<CookieRow[]> {
309
- if (!file || (file && !fs.existsSync(file))) {
310
- throw new Error(`doSqliteQuery1: file ${file} does not exist`);
311
- }
312
- const db = new sqlite3.Database(file);
313
- return new Promise((resolve, reject) => {
314
- db.all(sql, (err: Error, rows: any[]) => {
315
- if (err) {
316
- reject(err);
317
- return;
318
- }
319
- const rows1: any[] = rows;
320
- if (rows1 == null || rows1.length === 0) {
321
- resolve([]);
322
- return;
323
- }
324
- if (Array.isArray(rows1)) {
325
- const cookieRows: CookieRow[] = rows1.map((row: any) => {
326
- const newVar = {
327
- meta: {
328
- file: file,
329
- },
330
- };
331
- const cookieRow: CookieRow = rowTransform(row);
332
- return merge(newVar, cookieRow);
333
- });
334
- resolve(cookieRows);
335
- return;
336
- }
337
- if (parsedArgs.verbose) {
338
- console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
339
- }
340
- resolve([rows1]);
341
- });
342
- });
343
- }
@@ -1,47 +0,0 @@
1
- import * as fs from "fs";
2
- import * as sqlite3 from "sqlite3";
3
- import CookieRow from "./CookieRow";
4
- import { merge } from "lodash";
5
- import { parsedArgs } from "./argv";
6
- import { DoSqliteQuery1Params } from "./doSqliteQuery1Params";
7
-
8
- export async function doSqliteQuery1({
9
- file,
10
- sql,
11
- rowTransform,
12
- }: DoSqliteQuery1Params): Promise<CookieRow[]> {
13
- if (!file || (file && !fs.existsSync(file))) {
14
- throw new Error(`doSqliteQuery1: file ${file} does not exist`);
15
- }
16
- const db = new sqlite3.Database(file);
17
- return new Promise((resolve, reject) => {
18
- db.all(sql, (err: Error, rows: any[]) => {
19
- if (err) {
20
- reject(err);
21
- return;
22
- }
23
- const rows1: any[] = rows;
24
- if (rows1 == null || rows1.length === 0) {
25
- resolve([]);
26
- return;
27
- }
28
- if (Array.isArray(rows1)) {
29
- const cookieRows: CookieRow[] = rows1.map((row: any) => {
30
- const newVar = {
31
- meta: {
32
- file: file,
33
- },
34
- };
35
- const cookieRow: CookieRow = rowTransform(row);
36
- return merge(newVar, cookieRow);
37
- });
38
- resolve(cookieRows);
39
- return;
40
- }
41
- if (parsedArgs.verbose) {
42
- console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
43
- }
44
- resolve([rows1]);
45
- });
46
- });
47
- }
@@ -1,7 +0,0 @@
1
- import CookieRow from "./CookieRow";
2
-
3
- export interface DoSqliteQuery1Params {
4
- file: string;
5
- sql: string;
6
- rowTransform: (row: any) => CookieRow;
7
- }
package/src/utils.ts DELETED
@@ -1,25 +0,0 @@
1
- // noinspection JSUnusedGlobalSymbols
2
-
3
- import { exec, ExecException } from "child_process";
4
-
5
- export async function execSimple(command: string): Promise<string> {
6
- return new Promise((resolve, reject) => {
7
- exec(
8
- command,
9
- { encoding: "binary", maxBuffer: 5 * 1024 },
10
- (error: ExecException | null, stdout: string, stderr: string) => {
11
- if (error) {
12
- reject(error);
13
- return;
14
- }
15
- if (stderr) {
16
- reject(error);
17
- return;
18
- }
19
- if (stdout) {
20
- resolve(stdout.trim());
21
- }
22
- }
23
- );
24
- });
25
- }