xgen-dex-cli 1.2.1 → 1.3.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/dist/chunks/{chunk-QXSCKZEG.js → chunk-ULMEXJOR.js} +114 -29
- package/dist/chunks/chunk-ULMEXJOR.js.map +7 -0
- package/dist/chunks/{tui-DMHUMWPG.js → tui-GDC2NODL.js} +304 -138
- package/dist/chunks/tui-GDC2NODL.js.map +7 -0
- package/dist/cli.js +18 -11
- package/dist/cli.js.map +2 -2
- package/package.json +4 -2
- package/dist/chunks/chunk-QXSCKZEG.js.map +0 -7
- package/dist/chunks/tui-DMHUMWPG.js.map +0 -7
|
@@ -361,15 +361,26 @@ function validateProfileName(input) {
|
|
|
361
361
|
return name;
|
|
362
362
|
}
|
|
363
363
|
function validateServerUrl(input) {
|
|
364
|
+
const raw = input.trim();
|
|
365
|
+
if (!raw) {
|
|
366
|
+
throw new DexError("config_invalid", "\uC11C\uBC84 \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694.");
|
|
367
|
+
}
|
|
368
|
+
const hasScheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(raw);
|
|
369
|
+
const bare = raw.replace(/^\/+/, "");
|
|
370
|
+
const local = /^(localhost|127\.0\.0\.1|\[?::1\]?)(:|$|\/)/i.test(bare);
|
|
371
|
+
const candidate = hasScheme ? raw : `${local ? "http" : "https"}://${bare}`;
|
|
364
372
|
let url;
|
|
365
373
|
try {
|
|
366
|
-
url = new URL(
|
|
374
|
+
url = new URL(candidate);
|
|
367
375
|
} catch {
|
|
368
|
-
throw new DexError("config_invalid", "\uC11C\uBC84
|
|
376
|
+
throw new DexError("config_invalid", "\uC11C\uBC84 \uC8FC\uC18C\uB97C \uC54C\uC544\uBCFC \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC608: xgen.example.com");
|
|
369
377
|
}
|
|
370
378
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
371
379
|
throw new DexError("config_invalid", "\uC11C\uBC84 URL\uC740 http:// \uB610\uB294 https://\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.");
|
|
372
380
|
}
|
|
381
|
+
if (!url.hostname) {
|
|
382
|
+
throw new DexError("config_invalid", "\uC11C\uBC84 \uC8FC\uC18C\uC5D0 \uD638\uC2A4\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC608: xgen.example.com");
|
|
383
|
+
}
|
|
373
384
|
if (url.username || url.password || url.search || url.hash) {
|
|
374
385
|
throw new DexError("config_invalid", "\uC11C\uBC84 URL\uC5D0\uB294 \uC790\uACA9 \uC99D\uBA85, query, fragment\uB97C \uB123\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
375
386
|
}
|
|
@@ -4437,22 +4448,104 @@ var DexEngine = class {
|
|
|
4437
4448
|
};
|
|
4438
4449
|
|
|
4439
4450
|
// ../../packages/engine/src/credential-store.ts
|
|
4451
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4452
|
+
import { dirname as dirname3, join as join3 } from "node:path";
|
|
4440
4453
|
var SERVICE = "xgen-dex-cli";
|
|
4441
4454
|
var ACCOUNT_PREFIX = "profile:";
|
|
4455
|
+
var activeBackend = "file";
|
|
4456
|
+
function credentialBackend() {
|
|
4457
|
+
return activeBackend;
|
|
4458
|
+
}
|
|
4459
|
+
var keytarProbe = null;
|
|
4460
|
+
var KEYCHAIN_TIMEOUT_MS = 2e3;
|
|
4461
|
+
async function withTimeout2(work) {
|
|
4462
|
+
let timer;
|
|
4463
|
+
try {
|
|
4464
|
+
return await Promise.race([
|
|
4465
|
+
work,
|
|
4466
|
+
new Promise((_, reject) => {
|
|
4467
|
+
timer = setTimeout(() => reject(new Error("keychain timeout")), KEYCHAIN_TIMEOUT_MS);
|
|
4468
|
+
timer.unref?.();
|
|
4469
|
+
})
|
|
4470
|
+
]);
|
|
4471
|
+
} finally {
|
|
4472
|
+
if (timer) clearTimeout(timer);
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4442
4475
|
async function loadKeytar() {
|
|
4476
|
+
keytarProbe ??= (async () => {
|
|
4477
|
+
if (process.env.DEX_NO_KEYCHAIN === "1") return null;
|
|
4478
|
+
try {
|
|
4479
|
+
const loaded = await import("keytar");
|
|
4480
|
+
const keytar2 = loaded.default ?? loaded;
|
|
4481
|
+
if (!keytar2.getPassword || !keytar2.setPassword || !keytar2.deletePassword) return null;
|
|
4482
|
+
await withTimeout2(keytar2.getPassword(SERVICE, "__probe__"));
|
|
4483
|
+
return keytar2;
|
|
4484
|
+
} catch {
|
|
4485
|
+
return null;
|
|
4486
|
+
}
|
|
4487
|
+
})();
|
|
4488
|
+
const keytar = await keytarProbe;
|
|
4489
|
+
activeBackend = keytar ? "keychain" : "file";
|
|
4490
|
+
return keytar;
|
|
4491
|
+
}
|
|
4492
|
+
function filePath() {
|
|
4493
|
+
return join3(dataDirectory(), "credentials.json");
|
|
4494
|
+
}
|
|
4495
|
+
function readFileStore() {
|
|
4443
4496
|
try {
|
|
4444
|
-
const
|
|
4445
|
-
const
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
throw new DexError(
|
|
4450
|
-
"credential_store_unavailable",
|
|
4451
|
-
"OS \uD0A4\uCCB4\uC778\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. keytar \uC124\uCE58\uC640 OS \uD0A4\uB9C1 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
4452
|
-
error
|
|
4453
|
-
);
|
|
4497
|
+
const raw = readFileSync(filePath(), "utf8");
|
|
4498
|
+
const parsed = JSON.parse(raw);
|
|
4499
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
4500
|
+
} catch {
|
|
4501
|
+
return {};
|
|
4454
4502
|
}
|
|
4455
4503
|
}
|
|
4504
|
+
function writeFileStore(values) {
|
|
4505
|
+
const path = filePath();
|
|
4506
|
+
mkdirSync(dirname3(path), { recursive: true });
|
|
4507
|
+
const tmp = `${path}.tmp`;
|
|
4508
|
+
writeFileSync(tmp, JSON.stringify(values, null, 2), { encoding: "utf8", mode: 384 });
|
|
4509
|
+
try {
|
|
4510
|
+
chmodSync(tmp, 384);
|
|
4511
|
+
} catch {
|
|
4512
|
+
}
|
|
4513
|
+
renameSync(tmp, path);
|
|
4514
|
+
}
|
|
4515
|
+
async function secretGet(account) {
|
|
4516
|
+
const keytar = await loadKeytar();
|
|
4517
|
+
if (keytar) {
|
|
4518
|
+
try {
|
|
4519
|
+
return await withTimeout2(keytar.getPassword(SERVICE, account));
|
|
4520
|
+
} catch {
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
return readFileStore()[account] ?? null;
|
|
4524
|
+
}
|
|
4525
|
+
async function secretSet(account, value) {
|
|
4526
|
+
const keytar = await loadKeytar();
|
|
4527
|
+
if (keytar) {
|
|
4528
|
+
try {
|
|
4529
|
+
if (value === null) await withTimeout2(keytar.deletePassword(SERVICE, account));
|
|
4530
|
+
else await withTimeout2(keytar.setPassword(SERVICE, account, value));
|
|
4531
|
+
return;
|
|
4532
|
+
} catch {
|
|
4533
|
+
activeBackend = "file";
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
const values = readFileStore();
|
|
4537
|
+
if (value === null) delete values[account];
|
|
4538
|
+
else values[account] = value;
|
|
4539
|
+
if (Object.keys(values).length === 0 && existsSync(filePath())) {
|
|
4540
|
+
try {
|
|
4541
|
+
unlinkSync(filePath());
|
|
4542
|
+
} catch {
|
|
4543
|
+
writeFileStore(values);
|
|
4544
|
+
}
|
|
4545
|
+
return;
|
|
4546
|
+
}
|
|
4547
|
+
writeFileStore(values);
|
|
4548
|
+
}
|
|
4456
4549
|
function parseSession(raw) {
|
|
4457
4550
|
if (!raw) return null;
|
|
4458
4551
|
try {
|
|
@@ -4463,7 +4556,7 @@ function parseSession(raw) {
|
|
|
4463
4556
|
return null;
|
|
4464
4557
|
}
|
|
4465
4558
|
}
|
|
4466
|
-
var
|
|
4559
|
+
var SystemCredentialStore = class {
|
|
4467
4560
|
/**
|
|
4468
4561
|
* 엔진의 `SecretPort` 로 내보내는 두 함수 — 프로파일 세션 말고 **임의의 비밀**
|
|
4469
4562
|
* (MCP 서버 시크릿 · OAuth 상태)을 같은 백엔드에 둔다.
|
|
@@ -4472,29 +4565,20 @@ var KeytarCredentialStore = class {
|
|
|
4472
4565
|
* 하나의 질문이고, 두 곳에 나뉘면 로그아웃할 때 한쪽이 남는다.
|
|
4473
4566
|
*/
|
|
4474
4567
|
async getRaw(name) {
|
|
4475
|
-
|
|
4476
|
-
return keytar.getPassword(SERVICE, name);
|
|
4568
|
+
return secretGet(name);
|
|
4477
4569
|
}
|
|
4478
4570
|
async setRaw(name, value) {
|
|
4479
|
-
|
|
4480
|
-
if (value === null) {
|
|
4481
|
-
await keytar.deletePassword(SERVICE, name);
|
|
4482
|
-
return true;
|
|
4483
|
-
}
|
|
4484
|
-
await keytar.setPassword(SERVICE, name, value);
|
|
4571
|
+
await secretSet(name, value);
|
|
4485
4572
|
return true;
|
|
4486
4573
|
}
|
|
4487
4574
|
async get(profile) {
|
|
4488
|
-
|
|
4489
|
-
return parseSession(await keytar.getPassword(SERVICE, ACCOUNT_PREFIX + profile));
|
|
4575
|
+
return parseSession(await secretGet(ACCOUNT_PREFIX + profile));
|
|
4490
4576
|
}
|
|
4491
4577
|
async set(profile, session) {
|
|
4492
|
-
|
|
4493
|
-
await keytar.setPassword(SERVICE, ACCOUNT_PREFIX + profile, JSON.stringify(session));
|
|
4578
|
+
await secretSet(ACCOUNT_PREFIX + profile, JSON.stringify(session));
|
|
4494
4579
|
}
|
|
4495
4580
|
async delete(profile) {
|
|
4496
|
-
|
|
4497
|
-
await keytar.deletePassword(SERVICE, ACCOUNT_PREFIX + profile);
|
|
4581
|
+
await secretSet(ACCOUNT_PREFIX + profile, null);
|
|
4498
4582
|
}
|
|
4499
4583
|
};
|
|
4500
4584
|
|
|
@@ -4555,6 +4639,7 @@ export {
|
|
|
4555
4639
|
dataDirectory,
|
|
4556
4640
|
FileConfigStore,
|
|
4557
4641
|
DexEngine,
|
|
4558
|
-
|
|
4642
|
+
credentialBackend,
|
|
4643
|
+
SystemCredentialStore
|
|
4559
4644
|
};
|
|
4560
|
-
//# sourceMappingURL=chunk-
|
|
4645
|
+
//# sourceMappingURL=chunk-ULMEXJOR.js.map
|