@mherod/get-cookie 2.0.0-beta.1 → 2.0.0-beta.10
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/codeStyles/Project.xml +59 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/get-cookie.iml +1 -0
- package/.prettierrc.json +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.js +563 -0
- package/dist/index.js.map +1 -0
- package/dist/module.js +533 -0
- package/dist/module.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +37 -13
- package/src/CookieRequest.ts +4 -0
- package/src/CookieRow.ts +6 -0
- package/src/ExportedCookie.ts +6 -0
- package/src/IsCookieRow.ts +5 -0
- package/src/IsExportedCookie.ts +5 -0
- package/src/argv.ts +1 -0
- package/src/browsers/ChromeCookieQueryStrategy.ts +259 -0
- package/src/browsers/{CompositeCookieQueryStrategy.js → CompositeCookieQueryStrategy.ts} +7 -5
- package/src/browsers/CookieQueryStrategy.ts +5 -0
- package/src/browsers/{FirefoxCookieQueryStrategy.js → FirefoxCookieQueryStrategy.ts} +30 -15
- package/src/browsers/SafariCookieQueryStrategy.ts +8 -0
- package/src/cli.ts +82 -0
- package/src/doSqliteQuery1.ts +41 -0
- package/src/fetchResponse.ts +11 -0
- package/src/fetchWithCookies.ts +62 -0
- package/src/{findAllFiles.js → findAllFiles.ts} +15 -20
- package/src/getGroupedRenderedCookies.ts +32 -0
- package/src/{global.js → global.ts} +2 -2
- package/src/{index.js → index.ts} +16 -18
- package/src/{isValidJwt.js → isValidJwt.ts} +1 -4
- package/src/queryCookies.ts +27 -0
- package/src/resultsRendered.ts +8 -0
- package/src/utils.ts +56 -0
- package/tsconfig.json +23 -0
- package/dist/main.js +0 -499
- package/dist/main.js.map +0 -1
- package/src/browsers/AbstractCookieQueryStrategy.js +0 -8
- package/src/browsers/ChromeCookieQueryStrategy.js +0 -263
- package/src/browsers/SafariCookieQueryStrategy.js +0 -3
- package/src/cli.js +0 -70
- package/src/queryCookies.js +0 -28
- package/src/utils.js +0 -181
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import AbstractCookieQueryStrategy from "./AbstractCookieQueryStrategy";
|
|
2
|
-
import {
|
|
3
|
-
doSqliteQuery1,
|
|
4
|
-
execSimple,
|
|
5
|
-
invalidString,
|
|
6
|
-
toStringOrNull,
|
|
7
|
-
toStringValue,
|
|
8
|
-
} from "../utils";
|
|
9
|
-
import { env, HOME } from "../global";
|
|
10
|
-
import { existsSync } from "fs";
|
|
11
|
-
import { findAllFiles } from "../findAllFiles";
|
|
12
|
-
import crypto from "crypto";
|
|
13
|
-
import * as path from "path";
|
|
14
|
-
|
|
15
|
-
export default class ChromeCookieQueryStrategy extends AbstractCookieQueryStrategy {
|
|
16
|
-
async queryCookies(name, domain) {
|
|
17
|
-
if (process.platform !== "darwin") {
|
|
18
|
-
throw new Error("This only works on macOS");
|
|
19
|
-
}
|
|
20
|
-
if (env.FIREFOX_ONLY) {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
const cookies = await getChromeCookies({ name, domain });
|
|
24
|
-
return cookies.map(toStringValue);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function getPromise1(name, domain, file) {
|
|
29
|
-
try {
|
|
30
|
-
return await getEncryptedChromeCookie({
|
|
31
|
-
name: name,
|
|
32
|
-
domain: domain,
|
|
33
|
-
file: file,
|
|
34
|
-
});
|
|
35
|
-
} catch (e) {
|
|
36
|
-
if (env.VERBOSE) {
|
|
37
|
-
console.log("Error getting encrypted cookie", e);
|
|
38
|
-
}
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function getPromise(name, domain) {
|
|
44
|
-
try {
|
|
45
|
-
const files = await findAllFiles({
|
|
46
|
-
path: chromeLocal,
|
|
47
|
-
name: "Cookies",
|
|
48
|
-
});
|
|
49
|
-
const promises = files.map((file) => getPromise1(name, domain, file));
|
|
50
|
-
const results1 = await Promise.all(promises);
|
|
51
|
-
const results2 = results1.flat();
|
|
52
|
-
if (env.VERBOSE) {
|
|
53
|
-
console.log("getEncryptedChromeCookie results", results2);
|
|
54
|
-
}
|
|
55
|
-
return results2.filter((result) => result);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
if (env.VERBOSE) {
|
|
58
|
-
console.log("error", error);
|
|
59
|
-
}
|
|
60
|
-
return [];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
66
|
-
* @param {string|undefined} name
|
|
67
|
-
* @param {string} domain
|
|
68
|
-
* @param {boolean} requireJwt
|
|
69
|
-
* @returns {Promise<[string]>}
|
|
70
|
-
*/
|
|
71
|
-
async function getChromeCookies({ name, domain = "%", requireJwt = false }) {
|
|
72
|
-
if (invalidString(name)) {
|
|
73
|
-
throw new Error("name must be a string");
|
|
74
|
-
}
|
|
75
|
-
if (invalidString(domain)) {
|
|
76
|
-
throw new Error("domain must be a string");
|
|
77
|
-
}
|
|
78
|
-
const encryptedDataItems = await getPromise(name, domain);
|
|
79
|
-
const password = await getChromePassword();
|
|
80
|
-
const decrypted = encryptedDataItems
|
|
81
|
-
.filter((encryptedData) => {
|
|
82
|
-
return encryptedData != null && encryptedData.length > 0;
|
|
83
|
-
})
|
|
84
|
-
.map(async (encryptedData) => {
|
|
85
|
-
if (env.VERBOSE) {
|
|
86
|
-
console.log("Received encrypted", encryptedData);
|
|
87
|
-
}
|
|
88
|
-
let d;
|
|
89
|
-
try {
|
|
90
|
-
d = await decrypt(password, encryptedData);
|
|
91
|
-
} catch (e) {
|
|
92
|
-
if (env.VERBOSE) {
|
|
93
|
-
console.log("Error decrypting cookie", e);
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
if (d) {
|
|
98
|
-
if (env.VERBOSE) {
|
|
99
|
-
console.log("Decrypted", d);
|
|
100
|
-
}
|
|
101
|
-
return d;
|
|
102
|
-
}
|
|
103
|
-
return null;
|
|
104
|
-
});
|
|
105
|
-
const results = await Promise.all(decrypted);
|
|
106
|
-
if (env.VERBOSE) {
|
|
107
|
-
console.log("results", results);
|
|
108
|
-
}
|
|
109
|
-
return results.map(toStringOrNull);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const chromeLocal = path.join(
|
|
113
|
-
HOME,
|
|
114
|
-
"Library",
|
|
115
|
-
"Application Support",
|
|
116
|
-
"Google",
|
|
117
|
-
"Chrome"
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
async function getEncryptedChromeCookie({
|
|
121
|
-
name,
|
|
122
|
-
domain,
|
|
123
|
-
file = path.join(chromeLocal, "Default", "Cookies"),
|
|
124
|
-
}) {
|
|
125
|
-
if (name && typeof name !== "string") {
|
|
126
|
-
throw new Error("name must be a string");
|
|
127
|
-
}
|
|
128
|
-
if (domain && typeof domain !== "string") {
|
|
129
|
-
throw new Error("domain must be a string");
|
|
130
|
-
}
|
|
131
|
-
if (file && typeof file !== "string") {
|
|
132
|
-
throw new Error("file must be a string");
|
|
133
|
-
}
|
|
134
|
-
if (!existsSync(file)) {
|
|
135
|
-
throw new Error(`File ${file} does not exist`);
|
|
136
|
-
}
|
|
137
|
-
if (env.VERBOSE) {
|
|
138
|
-
const s = file.split("/").slice(-3).join("/");
|
|
139
|
-
console.log(`Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`);
|
|
140
|
-
}
|
|
141
|
-
let sql;
|
|
142
|
-
sql = `SELECT encrypted_value FROM cookies`;
|
|
143
|
-
if (typeof name === "string" || typeof domain === "string") {
|
|
144
|
-
sql += ` WHERE `;
|
|
145
|
-
if (typeof name === "string") {
|
|
146
|
-
sql += `name = '${name}'`;
|
|
147
|
-
if (typeof domain === "string") {
|
|
148
|
-
sql += ` AND `;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (typeof domain === "string") {
|
|
152
|
-
sql += `host_key LIKE '${domain}';`;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return doSqliteQuery1(file, sql);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
*
|
|
160
|
-
* @returns {Promise<string>}
|
|
161
|
-
*/
|
|
162
|
-
async function getChromePassword() {
|
|
163
|
-
return execSimple(
|
|
164
|
-
'security find-generic-password -w -s "Chrome Safe Storage"'
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
*
|
|
170
|
-
* @param {string} password
|
|
171
|
-
* @param {Buffer} encryptedData
|
|
172
|
-
* @returns {Promise<string>}
|
|
173
|
-
*/
|
|
174
|
-
async function decrypt(password, encryptedData) {
|
|
175
|
-
if (typeof password !== "string") {
|
|
176
|
-
throw new Error("password must be a string: " + password);
|
|
177
|
-
}
|
|
178
|
-
let encryptedData1;
|
|
179
|
-
encryptedData1 = encryptedData;
|
|
180
|
-
if (encryptedData1 == null || typeof encryptedData1 !== "object") {
|
|
181
|
-
throw new Error("encryptedData must be a object: " + encryptedData1);
|
|
182
|
-
}
|
|
183
|
-
if (!(encryptedData1 instanceof Buffer)) {
|
|
184
|
-
if (Array.isArray(encryptedData1) && encryptedData1[0] instanceof Buffer) {
|
|
185
|
-
[encryptedData1] = encryptedData1;
|
|
186
|
-
if (env.VERBOSE) {
|
|
187
|
-
console.log(
|
|
188
|
-
`encryptedData is an array of buffers, selected first: ${encryptedData1}`
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
} else {
|
|
192
|
-
throw new Error("encryptedData must be a Buffer: " + encryptedData1);
|
|
193
|
-
}
|
|
194
|
-
encryptedData1 = Buffer.from(encryptedData1);
|
|
195
|
-
}
|
|
196
|
-
if (env.VERBOSE) {
|
|
197
|
-
console.log(`Trying to decrypt with password ${password}`);
|
|
198
|
-
}
|
|
199
|
-
return new Promise((resolve, reject) => {
|
|
200
|
-
crypto.pbkdf2(password, "saltysalt", 1003, 16, "sha1", (error, buffer) => {
|
|
201
|
-
try {
|
|
202
|
-
if (error) {
|
|
203
|
-
if (env.VERBOSE) {
|
|
204
|
-
console.log("Error doing pbkdf2", error);
|
|
205
|
-
}
|
|
206
|
-
reject(error);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (buffer.length !== 16) {
|
|
211
|
-
if (env.VERBOSE) {
|
|
212
|
-
console.log(
|
|
213
|
-
"Error doing pbkdf2, buffer length is not 16",
|
|
214
|
-
buffer.length
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
reject(new Error("Buffer length is not 16"));
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const iv = new Buffer.from(new Array(17).join(" "), "binary");
|
|
222
|
-
const decipher = crypto.createDecipheriv("aes-128-cbc", buffer, iv);
|
|
223
|
-
decipher.setAutoPadding(false);
|
|
224
|
-
|
|
225
|
-
if (encryptedData1 && encryptedData1.slice) {
|
|
226
|
-
encryptedData1 = encryptedData1.slice(3);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (encryptedData1.length % 16 !== 0) {
|
|
230
|
-
if (env.VERBOSE) {
|
|
231
|
-
console.log(
|
|
232
|
-
"Error doing pbkdf2, encryptedData length is not a multiple of 16",
|
|
233
|
-
encryptedData1.length
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
reject(new Error("encryptedData length is not a multiple of 16"));
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
let decoded = decipher.update(encryptedData1);
|
|
241
|
-
try {
|
|
242
|
-
decipher.final("utf-8");
|
|
243
|
-
} catch (e) {
|
|
244
|
-
if (env.VERBOSE) {
|
|
245
|
-
console.log("Error doing decipher.final()", e);
|
|
246
|
-
}
|
|
247
|
-
reject(e);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const padding = decoded[decoded.length - 1];
|
|
252
|
-
if (padding) {
|
|
253
|
-
decoded = decoded.slice(0, 0 - padding);
|
|
254
|
-
}
|
|
255
|
-
// noinspection JSCheckFunctionSignatures
|
|
256
|
-
decoded = decoded.toString("utf8");
|
|
257
|
-
resolve(decoded);
|
|
258
|
-
} catch (e) {
|
|
259
|
-
reject(e);
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
}
|
package/src/cli.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { version } from "../package.json";
|
|
4
|
-
import { env } from "./global";
|
|
5
|
-
import { queryCookies } from "./queryCookies";
|
|
6
|
-
|
|
7
|
-
const argv = process.argv;
|
|
8
|
-
|
|
9
|
-
async function cliQueryCookies(name, domain) {
|
|
10
|
-
try {
|
|
11
|
-
const results = await queryCookies({ name, domain });
|
|
12
|
-
if (results.length > 0) {
|
|
13
|
-
for (const result of results) {
|
|
14
|
-
console.log(result);
|
|
15
|
-
}
|
|
16
|
-
} else {
|
|
17
|
-
console.error("No results");
|
|
18
|
-
}
|
|
19
|
-
} catch (e) {
|
|
20
|
-
console.error(e);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (argv && argv.length > 2) {
|
|
25
|
-
if (argv.includes("--version") || argv.includes("-v")) {
|
|
26
|
-
console.log(version);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const name = argv[2];
|
|
31
|
-
|
|
32
|
-
let domain;
|
|
33
|
-
if (argv[3] != null && argv[3].indexOf(".") > -1) {
|
|
34
|
-
domain = argv[3];
|
|
35
|
-
} else {
|
|
36
|
-
domain = "%";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const tru = `${true}`;
|
|
40
|
-
|
|
41
|
-
if (argv.includes("--require-jwt")) {
|
|
42
|
-
env.REQUIRE_JWT = tru;
|
|
43
|
-
}
|
|
44
|
-
if (argv.includes("--verbose")) {
|
|
45
|
-
env.VERBOSE = tru;
|
|
46
|
-
}
|
|
47
|
-
if (argv.includes("--chrome-only")) {
|
|
48
|
-
env.CHROME_ONLY = tru;
|
|
49
|
-
}
|
|
50
|
-
if (argv.includes("--firefox-only")) {
|
|
51
|
-
env.FIREFOX_ONLY = tru;
|
|
52
|
-
}
|
|
53
|
-
if (argv.includes("--ignore-expired")) {
|
|
54
|
-
env.IGNORE_EXPIRED = tru;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (argv.includes("--single")) {
|
|
58
|
-
env.SINGLE = tru;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (env.VERBOSE) {
|
|
62
|
-
console.log("Verbose mode", argv);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
cliQueryCookies(name, domain)
|
|
66
|
-
.then(() => {
|
|
67
|
-
//
|
|
68
|
-
})
|
|
69
|
-
.catch(console.error);
|
|
70
|
-
}
|
package/src/queryCookies.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import CompositeCookieQueryStrategy from "./browsers/CompositeCookieQueryStrategy";
|
|
2
|
-
import { uniq } from "lodash";
|
|
3
|
-
import { env } from "./global";
|
|
4
|
-
import isValidJwt from "./isValidJwt";
|
|
5
|
-
|
|
6
|
-
export async function queryCookies(
|
|
7
|
-
{ name, domain },
|
|
8
|
-
strategy = new CompositeCookieQueryStrategy()
|
|
9
|
-
) {
|
|
10
|
-
const results = await strategy.queryCookies(name, domain);
|
|
11
|
-
const results1 = uniq(results).map((cookie) => {
|
|
12
|
-
return {
|
|
13
|
-
name: name,
|
|
14
|
-
domain: domain,
|
|
15
|
-
value: cookie,
|
|
16
|
-
};
|
|
17
|
-
});
|
|
18
|
-
const jwtCookies = [];
|
|
19
|
-
for (const result of results1) {
|
|
20
|
-
const value = result.value;
|
|
21
|
-
if (isValidJwt(value)) {
|
|
22
|
-
jwtCookies.push(result);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const results2 = env.REQUIRE_JWT ? jwtCookies : results1;
|
|
26
|
-
const resultsUniq = uniq(results2).map((cookie) => cookie.value);
|
|
27
|
-
return env.SINGLE ? [resultsUniq[0]] : resultsUniq;
|
|
28
|
-
}
|
package/src/utils.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
// noinspection JSUnusedGlobalSymbols
|
|
2
|
-
|
|
3
|
-
import { exec } from "child_process";
|
|
4
|
-
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
|
|
7
|
-
export async function execSimple(command) {
|
|
8
|
-
if (typeof command !== "string") {
|
|
9
|
-
throw new TypeError("execSimple: command must be a string");
|
|
10
|
-
}
|
|
11
|
-
if (process.env.VERBOSE) {
|
|
12
|
-
console.log(command);
|
|
13
|
-
}
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
exec(
|
|
16
|
-
command,
|
|
17
|
-
{ encoding: "binary", maxBuffer: 5 * 1024 },
|
|
18
|
-
(error, stdout, stderr) => {
|
|
19
|
-
if (error) {
|
|
20
|
-
reject(error);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (stderr) {
|
|
24
|
-
reject(error);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (stdout) {
|
|
28
|
-
resolve(stdout.toString("utf8").trim());
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function execAsBuffer(command) {
|
|
36
|
-
if (typeof command !== "string") {
|
|
37
|
-
throw new TypeError("execAsBuffer: command must be a string");
|
|
38
|
-
}
|
|
39
|
-
if (process.env.VERBOSE) {
|
|
40
|
-
console.log(command);
|
|
41
|
-
}
|
|
42
|
-
return await new Promise((resolve, reject) => {
|
|
43
|
-
exec(
|
|
44
|
-
command,
|
|
45
|
-
{ encoding: "binary", maxBuffer: 5 * 1024 },
|
|
46
|
-
(error, stdout, stderr) => {
|
|
47
|
-
if (error) {
|
|
48
|
-
reject(error);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (stderr) {
|
|
52
|
-
reject(error);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
let stdoutAsBuffer = stdout;
|
|
56
|
-
if (typeof stdoutAsBuffer === "string" && stdoutAsBuffer.length > 0) {
|
|
57
|
-
// noinspection JSCheckFunctionSignatures
|
|
58
|
-
stdoutAsBuffer = Buffer.from(stdoutAsBuffer, "binary").slice(0, -1);
|
|
59
|
-
}
|
|
60
|
-
if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
|
|
61
|
-
resolve(stdoutAsBuffer);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function toStringValue(r) {
|
|
69
|
-
if (process.env.VERBOSE) {
|
|
70
|
-
console.log("Printing value", r);
|
|
71
|
-
}
|
|
72
|
-
if (r) {
|
|
73
|
-
if (typeof r === "string") {
|
|
74
|
-
return r;
|
|
75
|
-
} else if (r.toString) {
|
|
76
|
-
// noinspection JSCheckFunctionSignatures
|
|
77
|
-
return r.toString("utf8");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function printStringValue(r) {
|
|
83
|
-
if (process.env.VERBOSE) {
|
|
84
|
-
console.log("Printing value", r);
|
|
85
|
-
}
|
|
86
|
-
if (r) {
|
|
87
|
-
if (typeof r === "string") {
|
|
88
|
-
console.log(r);
|
|
89
|
-
} else if (r.toString) {
|
|
90
|
-
// noinspection JSCheckFunctionSignatures
|
|
91
|
-
console.log(r.toString("utf8"));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
*
|
|
98
|
-
* @param result
|
|
99
|
-
* @returns {string|null}
|
|
100
|
-
*/
|
|
101
|
-
export function toStringOrNull(result) {
|
|
102
|
-
if (result == null) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
if (process.env.VERBOSE) {
|
|
106
|
-
console.log("result", result);
|
|
107
|
-
}
|
|
108
|
-
if (typeof result === "string" && result.length > 0) {
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
if (result.slice && result.toString) {
|
|
112
|
-
// noinspection JSCheckFunctionSignatures
|
|
113
|
-
return result.toString("utf8");
|
|
114
|
-
}
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
*
|
|
120
|
-
* @param {string} file
|
|
121
|
-
* @param {string} sql
|
|
122
|
-
* @returns {Promise<Buffer[]>}
|
|
123
|
-
*/
|
|
124
|
-
export async function doSqliteQuery1(file, sql) {
|
|
125
|
-
if (typeof sql !== "string") {
|
|
126
|
-
throw new TypeError("doSqliteQuery1: sql must be a string");
|
|
127
|
-
}
|
|
128
|
-
if (typeof file !== "string") {
|
|
129
|
-
throw new TypeError("doSqliteQuery1: file must be a string");
|
|
130
|
-
}
|
|
131
|
-
if (!fs.existsSync(file)) {
|
|
132
|
-
throw new Error(`doSqliteQuery1: file ${file} does not exist`);
|
|
133
|
-
}
|
|
134
|
-
if (process.env.VERBOSE) {
|
|
135
|
-
console.log(`doSqliteQuery1: file ${file}`);
|
|
136
|
-
console.log(`doSqliteQuery1: sql ${sql}`);
|
|
137
|
-
}
|
|
138
|
-
const sqlite3 = require("sqlite3");
|
|
139
|
-
const db = new sqlite3.Database(file);
|
|
140
|
-
return new Promise((resolve, reject) => {
|
|
141
|
-
db.all(sql, (err, rows) => {
|
|
142
|
-
if (err) {
|
|
143
|
-
if (process.env.VERBOSE) {
|
|
144
|
-
console.log(`doSqliteQuery1: error ${err}`);
|
|
145
|
-
}
|
|
146
|
-
reject(err);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const rows1 = rows;
|
|
150
|
-
if (rows1 == null || rows1.length === 0) {
|
|
151
|
-
if (process.env.VERBOSE) {
|
|
152
|
-
console.log(`doSqliteQuery1: no rows`);
|
|
153
|
-
}
|
|
154
|
-
resolve([]);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (Array.isArray(rows1)) {
|
|
158
|
-
if (process.env.VERBOSE) {
|
|
159
|
-
console.log(`doSqliteQuery1: ${rows1.length} rows`);
|
|
160
|
-
}
|
|
161
|
-
// noinspection JSCheckFunctionSignatures
|
|
162
|
-
const buffers = rows1
|
|
163
|
-
.flatMap((row) => Object.values(row))
|
|
164
|
-
.map((v) => Buffer.from(v, "binary"));
|
|
165
|
-
if (process.env.VERBOSE) {
|
|
166
|
-
console.log(`doSqliteQuery1: ${buffers.length} buffers`);
|
|
167
|
-
}
|
|
168
|
-
resolve(buffers);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (process.env.VERBOSE) {
|
|
172
|
-
console.log(`doSqliteQuery1: rows ${JSON.stringify(rows1)}`);
|
|
173
|
-
}
|
|
174
|
-
resolve([rows1]);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export function invalidString(input) {
|
|
180
|
-
return typeof input !== "string" || input.length === 0;
|
|
181
|
-
}
|