byr-pt-cli 0.1.5 → 0.1.7
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/dist/{cli-Ds1ZVpjV.mjs → cli-Boa0FrUq.mjs} +34 -12
- package/dist/cli.mjs +4 -3
- package/dist/{client-BeMmaDg5.mjs → client-CmhKYsjk.mjs} +4 -1
- package/dist/commands/doctor.mjs +2 -1
- package/dist/{doctor-JqfcqakX.mjs → doctor-BFpvus4A.mjs} +4 -123
- package/dist/domain/client.mjs +2 -1
- package/dist/index.mjs +4 -3
- package/dist/store-CtnRgFKg.mjs +144 -0
- package/package.json +5 -5
- package/LICENSE +0 -21
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { renderBrowseOutput, runBrowseCommand } from "./commands/browse.mjs";
|
|
2
2
|
import { renderDownloadOutput, runDownloadCommand } from "./commands/download.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { c as writeAuthStore, i as maskCookieHeader, s as validateByrCookie, t as clearAuthStore } from "./store-CtnRgFKg.mjs";
|
|
4
|
+
import { i as resolveClientConfig, n as renderDoctorOutput, r as runDoctorCommand, t as getDoctorFailureCode } from "./doctor-BFpvus4A.mjs";
|
|
4
5
|
import { renderGetOutput, runGetCommand } from "./commands/get.mjs";
|
|
5
6
|
import { renderSearchOutput, runSearchCommand } from "./commands/search.mjs";
|
|
6
|
-
import { a as parseLoginForm, c as BYR_INCLDEAD_FACET, d as parseCategoryAliases, f as parseSimpleFacetAliases, i as looksLikeLoginPage, l as BYR_SPSTATE_FACET, o as HttpSession, s as BYR_BOOKMARKED_FACET, t as createByrClient, u as getByrMetadata } from "./client-
|
|
7
|
+
import { a as parseLoginForm, c as BYR_INCLDEAD_FACET, d as parseCategoryAliases, f as parseSimpleFacetAliases, i as looksLikeLoginPage, l as BYR_SPSTATE_FACET, o as HttpSession, s as BYR_BOOKMARKED_FACET, t as createByrClient, u as getByrMetadata } from "./client-CmhKYsjk.mjs";
|
|
7
8
|
import { createRequire } from "node:module";
|
|
8
9
|
import { writeFile } from "node:fs/promises";
|
|
9
10
|
import { createInterface } from "node:readline/promises";
|
|
@@ -12,7 +13,7 @@ import { spawnSync } from "node:child_process";
|
|
|
12
13
|
import { join } from "node:path";
|
|
13
14
|
import { tmpdir } from "node:os";
|
|
14
15
|
import { copyFileSync, existsSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
15
|
-
import { createDecipheriv, pbkdf2Sync, randomUUID } from "node:crypto";
|
|
16
|
+
import { createDecipheriv, createHash, pbkdf2Sync, randomUUID } from "node:crypto";
|
|
16
17
|
|
|
17
18
|
//#region src/domain/auth/browser.ts
|
|
18
19
|
const TARGET_DOMAINS = new Set([
|
|
@@ -60,7 +61,7 @@ function importCookieFromChrome(profile) {
|
|
|
60
61
|
"-separator",
|
|
61
62
|
" ",
|
|
62
63
|
tempDb,
|
|
63
|
-
"SELECT name, value, hex(encrypted_value) FROM cookies WHERE host_key IN ('.byr.pt','byr.pt','.bt.byr.cn','bt.byr.cn') AND name IN ('uid','pass','session_id','auth_token','refresh_token')"
|
|
64
|
+
"SELECT name, value, hex(encrypted_value), host_key FROM cookies WHERE host_key IN ('.byr.pt','byr.pt','.bt.byr.cn','bt.byr.cn') AND name IN ('uid','pass','session_id','auth_token','refresh_token')"
|
|
64
65
|
], { encoding: "utf8" });
|
|
65
66
|
if (sqlite.status !== 0) throw new CliAppError({
|
|
66
67
|
code: "E_AUTH_REQUIRED",
|
|
@@ -71,15 +72,16 @@ function importCookieFromChrome(profile) {
|
|
|
71
72
|
const lines = (sqlite.stdout ?? "").split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
72
73
|
let keyHex;
|
|
73
74
|
for (const line of lines) {
|
|
74
|
-
const [name, value, encryptedHex] = line.split(" ");
|
|
75
|
+
const [name, value = "", encryptedHex = "", hostKey = ""] = line.split(" ");
|
|
75
76
|
if (!AUTH_COOKIE_NAMES.has(name)) continue;
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
const normalized = normalizeCookieValue(value);
|
|
78
|
+
if (normalized) {
|
|
79
|
+
cookies.set(name, normalized);
|
|
78
80
|
continue;
|
|
79
81
|
}
|
|
80
82
|
if (!keyHex) keyHex = getChromeSafeStorageKeyHex();
|
|
81
83
|
if (!encryptedHex || encryptedHex.length === 0 || !keyHex) continue;
|
|
82
|
-
const resolved = decryptChromeCookieHex(encryptedHex, keyHex);
|
|
84
|
+
const resolved = decryptChromeCookieHex(encryptedHex, keyHex, hostKey);
|
|
83
85
|
if (resolved) cookies.set(name, resolved);
|
|
84
86
|
}
|
|
85
87
|
return {
|
|
@@ -112,13 +114,20 @@ function getChromeSafeStorageKeyHex() {
|
|
|
112
114
|
return pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1").toString("hex");
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
|
-
function decryptChromeCookieHex(encryptedHex, keyHex) {
|
|
117
|
+
function decryptChromeCookieHex(encryptedHex, keyHex, hostKey) {
|
|
116
118
|
try {
|
|
117
119
|
let encrypted = Buffer.from(encryptedHex, "hex");
|
|
118
120
|
if (encrypted.length === 0) return;
|
|
119
|
-
|
|
121
|
+
const version = encrypted.subarray(0, 3).toString("utf8");
|
|
122
|
+
if (version === "v10" || version === "v11") encrypted = encrypted.subarray(3);
|
|
120
123
|
const decipher = createDecipheriv("aes-128-cbc", Buffer.from(keyHex, "hex"), Buffer.alloc(16, 32));
|
|
121
|
-
|
|
124
|
+
let decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
125
|
+
const normalizedHostKey = hostKey?.trim();
|
|
126
|
+
if (normalizedHostKey && decrypted.length > 32) {
|
|
127
|
+
const digest = createHash("sha256").update(normalizedHostKey).digest();
|
|
128
|
+
if (decrypted.subarray(0, 32).equals(digest)) decrypted = decrypted.subarray(32);
|
|
129
|
+
}
|
|
130
|
+
return normalizeCookieValue(decrypted.toString("utf8").replaceAll("\0", "").trim());
|
|
122
131
|
} catch {
|
|
123
132
|
return;
|
|
124
133
|
}
|
|
@@ -182,7 +191,10 @@ function extractByrCookie(records, source) {
|
|
|
182
191
|
const map = /* @__PURE__ */ new Map();
|
|
183
192
|
for (const record of records) {
|
|
184
193
|
if (!TARGET_DOMAINS.has(record.domain)) continue;
|
|
185
|
-
if (AUTH_COOKIE_NAMES.has(record.name))
|
|
194
|
+
if (AUTH_COOKIE_NAMES.has(record.name)) {
|
|
195
|
+
const normalized = normalizeCookieValue(record.value);
|
|
196
|
+
if (normalized) map.set(record.name, normalized);
|
|
197
|
+
}
|
|
186
198
|
}
|
|
187
199
|
if (map.size === 0) return;
|
|
188
200
|
try {
|
|
@@ -214,6 +226,16 @@ function buildByrAuthCookieHeader(cookieMap, context) {
|
|
|
214
226
|
}
|
|
215
227
|
});
|
|
216
228
|
}
|
|
229
|
+
function normalizeCookieValue(value) {
|
|
230
|
+
const trimmed = value.trim();
|
|
231
|
+
if (trimmed.length === 0) return;
|
|
232
|
+
for (const char of trimmed) {
|
|
233
|
+
const code = char.charCodeAt(0);
|
|
234
|
+
if (code < 33 || code > 126) return;
|
|
235
|
+
if (char === ";" || char === ",") return;
|
|
236
|
+
}
|
|
237
|
+
return trimmed;
|
|
238
|
+
}
|
|
217
239
|
function parseBinaryCookies(buffer) {
|
|
218
240
|
if (buffer.length < 8 || buffer.subarray(0, 4).toString("ascii") !== "cook") return [];
|
|
219
241
|
const numPages = buffer.readUInt32BE(4);
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import "./
|
|
3
|
-
import
|
|
1
|
+
import "./store-CtnRgFKg.mjs";
|
|
2
|
+
import "./doctor-BFpvus4A.mjs";
|
|
3
|
+
import "./client-CmhKYsjk.mjs";
|
|
4
|
+
import { t as runCli } from "./cli-Boa0FrUq.mjs";
|
|
4
5
|
|
|
5
6
|
export { runCli };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { s as validateByrCookie } from "./store-CtnRgFKg.mjs";
|
|
1
2
|
import { CliAppError } from "clawkit-cli-core";
|
|
2
3
|
|
|
3
4
|
//#region src/domain/byr-metadata.ts
|
|
@@ -1198,13 +1199,15 @@ function parseTimeoutMs(value) {
|
|
|
1198
1199
|
function createByrClient(options = {}) {
|
|
1199
1200
|
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
1200
1201
|
const timeoutMs = sanitizeTimeout(options.timeoutMs);
|
|
1202
|
+
const cookie = options.cookie?.trim();
|
|
1203
|
+
if (cookie && cookie.length > 0) validateByrCookie(cookie);
|
|
1201
1204
|
const username = options.username?.trim() ?? "";
|
|
1202
1205
|
const password = options.password ?? "";
|
|
1203
1206
|
const session = new HttpSession({
|
|
1204
1207
|
baseUrl,
|
|
1205
1208
|
timeoutMs,
|
|
1206
1209
|
fetchImpl: options.fetchImpl,
|
|
1207
|
-
initialCookie:
|
|
1210
|
+
initialCookie: cookie,
|
|
1208
1211
|
userAgent: "byr-pt-cli"
|
|
1209
1212
|
});
|
|
1210
1213
|
let authInitialized = session.cookieSize() > 0;
|
package/dist/commands/doctor.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../store-CtnRgFKg.mjs";
|
|
2
|
+
import { n as renderDoctorOutput, r as runDoctorCommand, t as getDoctorFailureCode } from "../doctor-BFpvus4A.mjs";
|
|
2
3
|
|
|
3
4
|
export { getDoctorFailureCode, renderDoctorOutput, runDoctorCommand };
|
|
@@ -1,128 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as readAuthStore, n as getByrAuthStorePath, o as readJsonFile, r as getByrGlobalConfigPath, s as validateByrCookie } from "./store-CtnRgFKg.mjs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
2
3
|
import { CliAppError } from "clawkit-cli-core";
|
|
3
4
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import {
|
|
5
|
-
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
6
|
|
|
7
|
-
//#region src/domain/auth/store.ts
|
|
8
|
-
function getByrConfigDir() {
|
|
9
|
-
return join(homedir(), ".config", "byr-cli");
|
|
10
|
-
}
|
|
11
|
-
function getByrGlobalConfigPath() {
|
|
12
|
-
return join(getByrConfigDir(), "config.json");
|
|
13
|
-
}
|
|
14
|
-
function getByrAuthStorePath() {
|
|
15
|
-
return join(getByrConfigDir(), "auth.json");
|
|
16
|
-
}
|
|
17
|
-
async function readJsonFile(path) {
|
|
18
|
-
try {
|
|
19
|
-
const content = await readFile(path, "utf8");
|
|
20
|
-
return JSON.parse(content);
|
|
21
|
-
} catch (error) {
|
|
22
|
-
const nodeError = error;
|
|
23
|
-
if (nodeError.code === "ENOENT") return;
|
|
24
|
-
throw new CliAppError({
|
|
25
|
-
code: "E_AUTH_INVALID",
|
|
26
|
-
message: `Failed to read JSON file: ${path}`,
|
|
27
|
-
details: {
|
|
28
|
-
path,
|
|
29
|
-
reason: nodeError.message
|
|
30
|
-
},
|
|
31
|
-
cause: error
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
async function writeJsonFile(path, data) {
|
|
36
|
-
await mkdir(dirname(path), { recursive: true });
|
|
37
|
-
await writeFile(path, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
38
|
-
}
|
|
39
|
-
async function readAuthStore() {
|
|
40
|
-
const store = await readJsonFile(getByrAuthStorePath());
|
|
41
|
-
if (store === void 0) return;
|
|
42
|
-
if (typeof store.cookie !== "string" || typeof store.source !== "string" || typeof store.updatedAt !== "string") return;
|
|
43
|
-
return {
|
|
44
|
-
cookie: store.cookie,
|
|
45
|
-
source: store.source,
|
|
46
|
-
updatedAt: store.updatedAt
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
async function writeAuthStore(cookie, source) {
|
|
50
|
-
const store = {
|
|
51
|
-
cookie,
|
|
52
|
-
source,
|
|
53
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54
|
-
};
|
|
55
|
-
await writeJsonFile(getByrAuthStorePath(), store);
|
|
56
|
-
return store;
|
|
57
|
-
}
|
|
58
|
-
async function clearAuthStore() {
|
|
59
|
-
const authStorePath = getByrAuthStorePath();
|
|
60
|
-
let existed = true;
|
|
61
|
-
try {
|
|
62
|
-
await stat(authStorePath);
|
|
63
|
-
} catch (error) {
|
|
64
|
-
const nodeError = error;
|
|
65
|
-
if (nodeError.code === "ENOENT") existed = false;
|
|
66
|
-
else throw new CliAppError({
|
|
67
|
-
code: "E_AUTH_INVALID",
|
|
68
|
-
message: "Failed to inspect BYR auth store",
|
|
69
|
-
details: { reason: nodeError.message },
|
|
70
|
-
cause: error
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
await rm(authStorePath, { force: true });
|
|
75
|
-
return existed;
|
|
76
|
-
} catch (error) {
|
|
77
|
-
throw new CliAppError({
|
|
78
|
-
code: "E_AUTH_INVALID",
|
|
79
|
-
message: "Failed to clear BYR auth store",
|
|
80
|
-
details: { reason: error.message },
|
|
81
|
-
cause: error
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function parseCookieHeader(cookieHeader) {
|
|
86
|
-
const cookieMap = /* @__PURE__ */ new Map();
|
|
87
|
-
for (const part of cookieHeader.split(";")) {
|
|
88
|
-
const segment = part.trim();
|
|
89
|
-
if (segment.length === 0) continue;
|
|
90
|
-
const eqIndex = segment.indexOf("=");
|
|
91
|
-
if (eqIndex <= 0) continue;
|
|
92
|
-
const name = segment.slice(0, eqIndex).trim();
|
|
93
|
-
const value = segment.slice(eqIndex + 1).trim();
|
|
94
|
-
if (name.length > 0) cookieMap.set(name, value);
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
uid: cookieMap.get("uid"),
|
|
98
|
-
pass: cookieMap.get("pass"),
|
|
99
|
-
sessionId: cookieMap.get("session_id"),
|
|
100
|
-
authToken: cookieMap.get("auth_token"),
|
|
101
|
-
refreshToken: cookieMap.get("refresh_token"),
|
|
102
|
-
cookieMap
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
function validateByrCookie(cookieHeader) {
|
|
106
|
-
const parsed = parseCookieHeader(cookieHeader);
|
|
107
|
-
const hasLegacyCookie = Boolean(parsed.uid && parsed.pass);
|
|
108
|
-
const hasSessionCookie = Boolean(parsed.sessionId && parsed.authToken);
|
|
109
|
-
if (!hasLegacyCookie && !hasSessionCookie) throw new CliAppError({
|
|
110
|
-
code: "E_AUTH_INVALID",
|
|
111
|
-
message: "BYR cookie must include uid/pass or session_id/auth_token",
|
|
112
|
-
details: { requiredAnyOf: [["uid", "pass"], ["session_id", "auth_token"]] }
|
|
113
|
-
});
|
|
114
|
-
return parsed;
|
|
115
|
-
}
|
|
116
|
-
function maskCookieValue(value, visible = 4) {
|
|
117
|
-
if (value.length <= visible) return "*".repeat(value.length);
|
|
118
|
-
return `${value.slice(0, visible)}${"*".repeat(Math.max(4, value.length - visible))}`;
|
|
119
|
-
}
|
|
120
|
-
function maskCookieHeader(cookieHeader) {
|
|
121
|
-
const parsed = parseCookieHeader(cookieHeader);
|
|
122
|
-
return Array.from(parsed.cookieMap.entries()).map(([name, value]) => name === "uid" || name === "pass" ? `${name}=${maskCookieValue(value)}` : `${name}=***`).join("; ");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
//#endregion
|
|
126
7
|
//#region src/domain/auth/config.ts
|
|
127
8
|
function firstString(value) {
|
|
128
9
|
if (value === void 0) return;
|
|
@@ -411,4 +292,4 @@ function toCliError(error, fallbackCode) {
|
|
|
411
292
|
}
|
|
412
293
|
|
|
413
294
|
//#endregion
|
|
414
|
-
export {
|
|
295
|
+
export { resolveClientConfig as i, renderDoctorOutput as n, runDoctorCommand as r, getDoctorFailureCode as t };
|
package/dist/domain/client.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../store-CtnRgFKg.mjs";
|
|
2
|
+
import { n as createByrClientFromEnv, r as createMockByrClient, t as createByrClient } from "../client-CmhKYsjk.mjs";
|
|
2
3
|
|
|
3
4
|
export { createByrClient, createByrClientFromEnv, createMockByrClient };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./
|
|
3
|
-
import "./
|
|
4
|
-
import
|
|
2
|
+
import "./store-CtnRgFKg.mjs";
|
|
3
|
+
import "./doctor-BFpvus4A.mjs";
|
|
4
|
+
import "./client-CmhKYsjk.mjs";
|
|
5
|
+
import { t as runCli } from "./cli-Boa0FrUq.mjs";
|
|
5
6
|
|
|
6
7
|
//#region src/index.ts
|
|
7
8
|
const exitCode = await runCli(process.argv.slice(2));
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { CliAppError } from "clawkit-cli-core";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
|
|
6
|
+
//#region src/domain/auth/store.ts
|
|
7
|
+
function getByrConfigDir() {
|
|
8
|
+
return join(homedir(), ".config", "byr-cli");
|
|
9
|
+
}
|
|
10
|
+
function getByrGlobalConfigPath() {
|
|
11
|
+
return join(getByrConfigDir(), "config.json");
|
|
12
|
+
}
|
|
13
|
+
function getByrAuthStorePath() {
|
|
14
|
+
return join(getByrConfigDir(), "auth.json");
|
|
15
|
+
}
|
|
16
|
+
async function readJsonFile(path) {
|
|
17
|
+
try {
|
|
18
|
+
const content = await readFile(path, "utf8");
|
|
19
|
+
return JSON.parse(content);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
const nodeError = error;
|
|
22
|
+
if (nodeError.code === "ENOENT") return;
|
|
23
|
+
throw new CliAppError({
|
|
24
|
+
code: "E_AUTH_INVALID",
|
|
25
|
+
message: `Failed to read JSON file: ${path}`,
|
|
26
|
+
details: {
|
|
27
|
+
path,
|
|
28
|
+
reason: nodeError.message
|
|
29
|
+
},
|
|
30
|
+
cause: error
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function writeJsonFile(path, data) {
|
|
35
|
+
await mkdir(dirname(path), { recursive: true });
|
|
36
|
+
await writeFile(path, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
37
|
+
}
|
|
38
|
+
async function readAuthStore() {
|
|
39
|
+
const store = await readJsonFile(getByrAuthStorePath());
|
|
40
|
+
if (store === void 0) return;
|
|
41
|
+
if (typeof store.cookie !== "string" || typeof store.source !== "string" || typeof store.updatedAt !== "string") return;
|
|
42
|
+
return {
|
|
43
|
+
cookie: store.cookie,
|
|
44
|
+
source: store.source,
|
|
45
|
+
updatedAt: store.updatedAt
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function writeAuthStore(cookie, source) {
|
|
49
|
+
const store = {
|
|
50
|
+
cookie,
|
|
51
|
+
source,
|
|
52
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
53
|
+
};
|
|
54
|
+
await writeJsonFile(getByrAuthStorePath(), store);
|
|
55
|
+
return store;
|
|
56
|
+
}
|
|
57
|
+
async function clearAuthStore() {
|
|
58
|
+
const authStorePath = getByrAuthStorePath();
|
|
59
|
+
let existed = true;
|
|
60
|
+
try {
|
|
61
|
+
await stat(authStorePath);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const nodeError = error;
|
|
64
|
+
if (nodeError.code === "ENOENT") existed = false;
|
|
65
|
+
else throw new CliAppError({
|
|
66
|
+
code: "E_AUTH_INVALID",
|
|
67
|
+
message: "Failed to inspect BYR auth store",
|
|
68
|
+
details: { reason: nodeError.message },
|
|
69
|
+
cause: error
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
await rm(authStorePath, { force: true });
|
|
74
|
+
return existed;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new CliAppError({
|
|
77
|
+
code: "E_AUTH_INVALID",
|
|
78
|
+
message: "Failed to clear BYR auth store",
|
|
79
|
+
details: { reason: error.message },
|
|
80
|
+
cause: error
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function parseCookieHeader(cookieHeader) {
|
|
85
|
+
const cookieMap = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const part of cookieHeader.split(";")) {
|
|
87
|
+
const segment = part.trim();
|
|
88
|
+
if (segment.length === 0) continue;
|
|
89
|
+
const eqIndex = segment.indexOf("=");
|
|
90
|
+
if (eqIndex <= 0) continue;
|
|
91
|
+
const name = segment.slice(0, eqIndex).trim();
|
|
92
|
+
const value = segment.slice(eqIndex + 1).trim();
|
|
93
|
+
if (name.length > 0) cookieMap.set(name, value);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
uid: cookieMap.get("uid"),
|
|
97
|
+
pass: cookieMap.get("pass"),
|
|
98
|
+
sessionId: cookieMap.get("session_id"),
|
|
99
|
+
authToken: cookieMap.get("auth_token"),
|
|
100
|
+
refreshToken: cookieMap.get("refresh_token"),
|
|
101
|
+
cookieMap
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function validateByrCookie(cookieHeader) {
|
|
105
|
+
const parsed = parseCookieHeader(cookieHeader);
|
|
106
|
+
const hasLegacyCookie = Boolean(parsed.uid && parsed.pass);
|
|
107
|
+
const hasSessionCookie = Boolean(parsed.sessionId && parsed.authToken);
|
|
108
|
+
if (!hasLegacyCookie && !hasSessionCookie) throw new CliAppError({
|
|
109
|
+
code: "E_AUTH_INVALID",
|
|
110
|
+
message: "BYR cookie must include uid/pass or session_id/auth_token",
|
|
111
|
+
details: { requiredAnyOf: [["uid", "pass"], ["session_id", "auth_token"]] }
|
|
112
|
+
});
|
|
113
|
+
for (const [name, value] of parsed.cookieMap.entries()) {
|
|
114
|
+
const reason = getInvalidCookieValueReason(value);
|
|
115
|
+
if (reason !== void 0) throw new CliAppError({
|
|
116
|
+
code: "E_AUTH_INVALID",
|
|
117
|
+
message: `Invalid cookie value for ${name}`,
|
|
118
|
+
details: {
|
|
119
|
+
cookieName: name,
|
|
120
|
+
reason
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return parsed;
|
|
125
|
+
}
|
|
126
|
+
function getInvalidCookieValueReason(value) {
|
|
127
|
+
if (value.trim().length === 0) return "empty";
|
|
128
|
+
for (const char of value) {
|
|
129
|
+
const code = char.charCodeAt(0);
|
|
130
|
+
if (code < 33 || code > 126) return `non-ascii-character:${code}`;
|
|
131
|
+
if (char === ";" || char === ",") return `reserved-character:${char}`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function maskCookieValue(value, visible = 4) {
|
|
135
|
+
if (value.length <= visible) return "*".repeat(value.length);
|
|
136
|
+
return `${value.slice(0, visible)}${"*".repeat(Math.max(4, value.length - visible))}`;
|
|
137
|
+
}
|
|
138
|
+
function maskCookieHeader(cookieHeader) {
|
|
139
|
+
const parsed = parseCookieHeader(cookieHeader);
|
|
140
|
+
return Array.from(parsed.cookieMap.entries()).map(([name, value]) => name === "uid" || name === "pass" ? `${name}=${maskCookieValue(value)}` : `${name}=***`).join("; ");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
export { readAuthStore as a, writeAuthStore as c, maskCookieHeader as i, getByrAuthStorePath as n, readJsonFile as o, getByrGlobalConfigPath as r, validateByrCookie as s, clearAuthStore as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "byr-pt-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "BYR CLI with OpenClaw-friendly JSON contract",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
"import": "./dist/cli.mjs"
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"clawkit-cli-core": "^0.1.0"
|
|
25
|
-
},
|
|
26
23
|
"scripts": {
|
|
27
24
|
"build": "tsdown src/index.ts src/cli.ts src/domain/client.ts src/domain/types.ts src/commands/browse.ts src/commands/doctor.ts src/commands/download.ts src/commands/get.ts src/commands/search.ts --format esm --dts",
|
|
28
25
|
"test": "pnpm --filter clawkit-cli-core build && vitest run",
|
|
@@ -31,5 +28,8 @@
|
|
|
31
28
|
"check": "pnpm typecheck && pnpm test",
|
|
32
29
|
"skill:publish": "node ./scripts/skill-publish.mjs",
|
|
33
30
|
"skill:sync": "clawhub sync --root ./skill-openclaw --all"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"clawkit-cli-core": "workspace:^0.1.0"
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 onemoreproduct
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|