@goodea/echolet 0.1.0 → 0.1.1

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.js CHANGED
@@ -38126,9 +38126,6 @@ function getClientDbPath(callsign) {
38126
38126
  function getCardPath(callsign) {
38127
38127
  return path.join(getProfileDir(callsign), "identity.card.json");
38128
38128
  }
38129
- function getProfileConfigPath(callsign) {
38130
- return path.join(getProfileDir(callsign), "config.json");
38131
- }
38132
38129
  function getRunDir() {
38133
38130
  return path.join(getEcholetHome(), "run");
38134
38131
  }
@@ -38397,19 +38394,40 @@ var prompts_exports = {};
38397
38394
  __export(prompts_exports, {
38398
38395
  ask: () => ask,
38399
38396
  askChoice: () => askChoice,
38400
- confirm: () => confirm
38397
+ closeReadline: () => closeReadline,
38398
+ confirm: () => confirm,
38399
+ getReadline: () => getReadline
38401
38400
  });
38402
- import { createInterface } from "node:readline/promises";
38401
+ import { createInterface } from "node:readline";
38403
38402
  import { stdin as input, stdout as output } from "node:process";
38403
+ function getReadline() {
38404
+ if (!sharedRl) {
38405
+ sharedRl = createInterface({ input, output });
38406
+ sharedIterator = sharedRl[Symbol.asyncIterator]();
38407
+ sharedRl.on("close", () => {
38408
+ sharedRl = null;
38409
+ sharedIterator = null;
38410
+ });
38411
+ }
38412
+ return { rl: sharedRl, iterator: sharedIterator };
38413
+ }
38414
+ function closeReadline() {
38415
+ if (sharedRl) {
38416
+ sharedRl.close();
38417
+ sharedRl = null;
38418
+ sharedIterator = null;
38419
+ }
38420
+ }
38404
38421
  async function ask(question, defaultValue = "") {
38405
- const rl = createInterface({ input, output });
38422
+ const { rl, iterator } = getReadline();
38406
38423
  const promptText = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
38407
- try {
38408
- const answer = await rl.question(promptText);
38409
- return answer.trim() || defaultValue;
38410
- } finally {
38411
- rl.close();
38424
+ rl.setPrompt(promptText);
38425
+ rl.prompt();
38426
+ const { value, done } = await iterator.next();
38427
+ if (done || typeof value !== "string" || !value.trim()) {
38428
+ return defaultValue;
38412
38429
  }
38430
+ return value.trim();
38413
38431
  }
38414
38432
  async function confirm(question, defaultYes = true) {
38415
38433
  const hint = defaultYes ? "[Y/n]" : "[y/N]";
@@ -38432,22 +38450,29 @@ ${question}`);
38432
38450
  const fallback = choices[defaultIndex];
38433
38451
  return fallback ? fallback.value : choices[0]?.value ?? "";
38434
38452
  }
38453
+ var sharedRl, sharedIterator;
38435
38454
  var init_prompts = __esm({
38436
38455
  "src/operator/prompts.ts"() {
38437
38456
  "use strict";
38457
+ sharedRl = null;
38458
+ sharedIterator = null;
38438
38459
  }
38439
38460
  });
38440
38461
 
38441
38462
  // src/operator/station.ts
38442
38463
  var station_exports = {};
38443
38464
  __export(station_exports, {
38444
- handleStationCommand: () => handleStationCommand
38465
+ handleStationCommand: () => handleStationCommand,
38466
+ readStationProfileConfig: () => readStationProfileConfig
38445
38467
  });
38446
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "node:fs";
38447
- import { resolve as resolve2, dirname as dirname2 } from "node:path";
38468
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, rmSync } from "node:fs";
38469
+ import { resolve as resolve2, dirname as dirname2, join as join4 } from "node:path";
38448
38470
  import { fileURLToPath } from "node:url";
38449
38471
  import { exec, spawn as spawn2 } from "node:child_process";
38450
- import { randomBytes as randomBytes2 } from "node:crypto";
38472
+ import { randomBytes as randomBytes2, randomUUID as randomUUID4 } from "node:crypto";
38473
+ function readStationProfileConfig(profileDir) {
38474
+ return parseClientConfig(JSON.parse(readFileSync4(join4(profileDir, "config.json"), "utf8")));
38475
+ }
38451
38476
  function resolveWebServerPath() {
38452
38477
  const candidates = [
38453
38478
  resolve2(HERE, "../web-dist/server.js"),
@@ -38474,14 +38499,23 @@ async function handleStationCommand(args) {
38474
38499
  `);
38475
38500
  const callsign = await ask("\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043F\u043E\u0437\u044B\u0432\u043D\u043E\u0439 \u0441\u0442\u0430\u043D\u0446\u0438\u0438 (Callsign)", "Echo-Operator");
38476
38501
  const dir = getProfileDir(callsign);
38477
- if (existsSync5(dir) && existsSync5(getClientDbPath(callsign))) {
38478
- const overwrite = await confirm(`\u0421\u0442\u0430\u043D\u0446\u0438\u044F "${callsign}" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041F\u0435\u0440\u0435\u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u043A\u043B\u044E\u0447\u0438? (\u0412\u041D\u0418\u041C\u0410\u041D\u0418\u0415: \u0434\u0430\u043D\u043D\u044B\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u044B)`, false);
38479
- if (!overwrite) {
38480
- console.log("\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u0430.");
38481
- return;
38502
+ if (existsSync5(dir)) {
38503
+ if (existsSync5(getClientDbPath(callsign))) {
38504
+ const overwrite = await confirm(`\u0421\u0442\u0430\u043D\u0446\u0438\u044F "${callsign}" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041F\u0435\u0440\u0435\u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u043A\u043B\u044E\u0447\u0438? (\u0412\u041D\u0418\u041C\u0410\u041D\u0418\u0415: \u0434\u0430\u043D\u043D\u044B\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043B\u0435\u043D\u044B)`, false);
38505
+ if (!overwrite) {
38506
+ console.log("\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u0430.");
38507
+ closeReadline();
38508
+ return;
38509
+ }
38482
38510
  }
38511
+ rmSync(dir, { recursive: true, force: true });
38512
+ }
38513
+ let relayUrl = (await ask("URL \u0440\u0435\u0442\u0440\u0430\u043D\u0441\u043B\u044F\u0442\u043E\u0440\u0430/\u0440\u0435\u043B\u0435\u044F", "https://depr.tail5a88fb.ts.net:8443")).trim();
38514
+ try {
38515
+ const u = new URL(relayUrl);
38516
+ relayUrl = u.origin;
38517
+ } catch {
38483
38518
  }
38484
- const relayUrl = await ask("URL \u0440\u0435\u0442\u0440\u0430\u043D\u0441\u043B\u044F\u0442\u043E\u0440\u0430/\u0440\u0435\u043B\u0435\u044F", "https://depr.tail5a88fb.ts.net:8443");
38485
38519
  mkdirSync3(dir, { recursive: true, mode: 448 });
38486
38520
  const key = randomBytes2(32);
38487
38521
  const storeKeyBase64 = key.toString("base64url");
@@ -38492,13 +38526,13 @@ async function handleStationCommand(args) {
38492
38526
  \u23F3 \u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u043A\u0440\u0438\u043F\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u0438\u0445 \u0441\u0432\u044F\u0437\u043E\u043A Double Ratchet & PreKeys...`);
38493
38527
  const profileConfig = {
38494
38528
  profile_version: 1,
38495
- profile_id: callsign,
38529
+ profile_id: randomUUID4(),
38496
38530
  relay_url: relayUrl,
38497
38531
  database_path: "client.sqlite",
38498
38532
  store_key_env: "ECHOLET_STORE_KEY",
38499
- request_timeout_ms: 1e4
38533
+ request_timeout_ms: 1e4,
38534
+ poll_batch_size: 20
38500
38535
  };
38501
- writeFileSync4(getProfileConfigPath(callsign), JSON.stringify(profileConfig, null, 2), { mode: 384 });
38502
38536
  process.env.ECHOLET_STORE_KEY = storeKeyBase64;
38503
38537
  const profile = await openProfile({
38504
38538
  profileDir: dir,
@@ -38511,23 +38545,23 @@ async function handleStationCommand(args) {
38511
38545
  const cardPath = getCardPath(callsign);
38512
38546
  writeFileSync4(cardPath, JSON.stringify(card, null, 2), { mode: 384 });
38513
38547
  console.log(`\u2705 \u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0430\u0431\u043E\u043D\u0435\u043D\u0442\u0430 \u044D\u043A\u0441\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0430: ${cardPath}`);
38514
- console.log(`\u23F3 \u041F\u0443\u0431\u043B\u0438\u043A\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u0434-\u043A\u043B\u044E\u0447\u0435\u0439 (PreKeys) \u043D\u0430 \u0440\u0435\u043B\u0435\u0435...`);
38515
- try {
38516
- const messenger = await openOutboundMessenger({
38517
- profileDir: dir,
38518
- environment: process.env,
38519
- relay: new RelayClient({ baseUrl: relayUrl, timeoutMs: 1e4 })
38520
- });
38521
- await messenger.publish();
38522
- await messenger.close();
38523
- console.log(`\u2705 \u0421\u0432\u044F\u0437\u043A\u0438 \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u043D\u044B \u043D\u0430 \u0440\u0435\u0442\u0440\u0430\u043D\u0441\u043B\u044F\u0442\u043E\u0440\u0435!`);
38524
- } catch (err) {
38525
- console.warn(`\u26A0\uFE0F \u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u0442\u044C \u043A\u043B\u044E\u0447\u0438 \u043D\u0430 \u0440\u0435\u043B\u0435\u0435 \u043F\u0440\u044F\u043C\u043E \u0441\u0435\u0439\u0447\u0430\u0441: ${err.message}`);
38526
- console.warn(`(\u0421\u0442\u0430\u043D\u0446\u0438\u044F \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u0443\u0435\u0442 \u0438\u0445 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043F\u0440\u0438 \u043F\u0435\u0440\u0432\u043E\u043C \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u043A \u0441\u0435\u0442\u0438)`);
38527
- }
38528
38548
  } finally {
38529
38549
  await profile.close();
38530
38550
  }
38551
+ console.log(`\u23F3 \u041F\u0443\u0431\u043B\u0438\u043A\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u0434-\u043A\u043B\u044E\u0447\u0435\u0439 (PreKeys) \u043D\u0430 \u0440\u0435\u043B\u0435\u0435...`);
38552
+ try {
38553
+ const messenger = await openOutboundMessenger({
38554
+ profileDir: dir,
38555
+ environment: process.env,
38556
+ relay: new RelayClient({ baseUrl: relayUrl, timeoutMs: 1e4 })
38557
+ });
38558
+ await messenger.publish();
38559
+ await messenger.close();
38560
+ console.log(`\u2705 \u0421\u0432\u044F\u0437\u043A\u0438 \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u043D\u044B \u043D\u0430 \u0440\u0435\u0442\u0440\u0430\u043D\u0441\u043B\u044F\u0442\u043E\u0440\u0435!`);
38561
+ } catch (err) {
38562
+ console.warn(`\u26A0\uFE0F \u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u0442\u044C \u043A\u043B\u044E\u0447\u0438 \u043D\u0430 \u0440\u0435\u043B\u0435\u0435 \u043F\u0440\u044F\u043C\u043E \u0441\u0435\u0439\u0447\u0430\u0441: ${err.message}`);
38563
+ console.warn(`(\u0421\u0442\u0430\u043D\u0446\u0438\u044F \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u0443\u0435\u0442 \u0438\u0445 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043F\u0440\u0438 \u043F\u0435\u0440\u0432\u043E\u043C \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u043A \u0441\u0435\u0442\u0438)`);
38564
+ }
38531
38565
  const globalCfg = getGlobalConfig();
38532
38566
  globalCfg.activeProfile = callsign;
38533
38567
  saveGlobalConfig(globalCfg);
@@ -38535,6 +38569,7 @@ async function handleStationCommand(args) {
38535
38569
  \u{1F389} \u0421\u0442\u0430\u043D\u0446\u0438\u044F "${callsign}" \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u0441\u043E\u0437\u0434\u0430\u043D\u0430 \u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u0430 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439!`);
38536
38570
  console.log(`\u0417\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u0432\u0435\u0431-\u043A\u043B\u0438\u0435\u043D\u0442 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439: echolet station start
38537
38571
  `);
38572
+ closeReadline();
38538
38573
  return;
38539
38574
  }
38540
38575
  if (sub === "start") {
@@ -38563,6 +38598,7 @@ async function handleStationCommand(args) {
38563
38598
  process.exit(1);
38564
38599
  }
38565
38600
  const storeKey = readFileSync4(keyPath, "utf8").trim();
38601
+ const profileConfig = readStationProfileConfig(profileDir);
38566
38602
  const serverScript = resolveWebServerPath();
38567
38603
  if (!existsSync5(serverScript)) {
38568
38604
  console.error(`\u041E\u0448\u0438\u0431\u043A\u0430: \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u043F\u043E \u043F\u0443\u0442\u0438 ${serverScript}.`);
@@ -38576,11 +38612,15 @@ async function handleStationCommand(args) {
38576
38612
  "--profile",
38577
38613
  profileDir,
38578
38614
  "--label",
38579
- targetProfile
38615
+ targetProfile,
38616
+ "--relay-url",
38617
+ profileConfig.relay_url,
38618
+ "--store-key-env",
38619
+ profileConfig.store_key_env
38580
38620
  ];
38581
38621
  const env = {
38582
38622
  ...process.env,
38583
- ECHOLET_STORE_KEY: storeKey,
38623
+ [profileConfig.store_key_env]: storeKey,
38584
38624
  ECHOLET_CLI_PATH: process.argv[1] || resolve2(HERE, "../dist/cli.js")
38585
38625
  };
38586
38626
  if (isDaemon) {
@@ -38659,6 +38699,7 @@ var init_station = __esm({
38659
38699
  init_profile();
38660
38700
  init_outbound();
38661
38701
  init_relayClient();
38702
+ init_config();
38662
38703
  HERE = typeof __dirname !== "undefined" ? __dirname : dirname2(fileURLToPath(import.meta.url));
38663
38704
  }
38664
38705
  });
@@ -38669,12 +38710,12 @@ __export(repeater_exports, {
38669
38710
  handleRepeaterCommand: () => handleRepeaterCommand
38670
38711
  });
38671
38712
  import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "node:fs";
38672
- import { join as join4 } from "node:path";
38713
+ import { join as join5 } from "node:path";
38673
38714
  import { execSync as execSync2, spawn as spawn3 } from "node:child_process";
38674
38715
  async function handleRepeaterCommand(args) {
38675
38716
  const sub = args[0] || "status";
38676
38717
  const { repeater } = ensureGlobalDirs();
38677
- const envFile = join4(repeater, "config.env");
38718
+ const envFile = join5(repeater, "config.env");
38678
38719
  if (sub === "setup") {
38679
38720
  console.log(`
38680
38721
  === \u{1F4E1} \u041D\u0410\u0421\u0422\u0420\u041E\u0419\u041A\u0410 \u041B\u041E\u041A\u0410\u041B\u042C\u041D\u041E\u0413\u041E \u0420\u0415\u041F\u0418\u0422\u0415\u0420\u0410 ECHOLET ===
@@ -38701,14 +38742,14 @@ async function handleRepeaterCommand(args) {
38701
38742
  const envContent = [
38702
38743
  `ECHOLET_NODE_CALLSIGN=${callsign}`,
38703
38744
  `ECHOLET_HTTP_ADDR=0.0.0.0:${port}`,
38704
- `ECHOLET_DATA_DIR=${join4(repeater, "data")}`,
38745
+ `ECHOLET_DATA_DIR=${join5(repeater, "data")}`,
38705
38746
  `ECHOLET_LOG_LEVEL=info`,
38706
38747
  `ECHOLET_MODE=${mode}`,
38707
38748
  `ECHOLET_PORT=${port}`,
38708
38749
  tlsCert ? `ECHOLET_TLS_CERT_FILE=${tlsCert}` : "",
38709
38750
  tlsKey ? `ECHOLET_TLS_KEY_FILE=${tlsKey}` : ""
38710
38751
  ].filter(Boolean).join("\n") + "\n";
38711
- mkdirSync4(join4(repeater, "data"), { recursive: true, mode: 448 });
38752
+ mkdirSync4(join5(repeater, "data"), { recursive: true, mode: 448 });
38712
38753
  writeFileSync5(envFile, envContent, { mode: 384 });
38713
38754
  console.log(`
38714
38755
  \u2705 \u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 \u0432: ${envFile}`);
@@ -38746,7 +38787,7 @@ async function handleRepeaterCommand(args) {
38746
38787
  }
38747
38788
  if (!imageExists) {
38748
38789
  console.log("\u{1F528} \u041E\u0431\u0440\u0430\u0437 echolet-relay:latest \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D. \u0417\u0430\u043F\u0443\u0441\u043A\u0430\u044E \u0441\u0431\u043E\u0440\u043A\u0443...");
38749
- const root = join4(__dirname, "../../..");
38790
+ const root = join5(__dirname, "../../..");
38750
38791
  execSync2("docker build -t echolet-relay:latest -f apps/relay/Dockerfile apps/relay", {
38751
38792
  cwd: root,
38752
38793
  stdio: "inherit"
@@ -38756,7 +38797,7 @@ async function handleRepeaterCommand(args) {
38756
38797
  execSync2("docker rm -f echolet-relay", { stdio: "ignore" });
38757
38798
  } catch {
38758
38799
  }
38759
- const dataDir = join4(repeater, "data");
38800
+ const dataDir = join5(repeater, "data");
38760
38801
  mkdirSync4(dataDir, { recursive: true, mode: 448 });
38761
38802
  const cmd = `docker run -d --name echolet-relay --restart unless-stopped --user 10001:10001 -p 127.0.0.1:${port}:8443 -e ECHOLET_HTTP_ADDR=0.0.0.0:8443 -e ECHOLET_DATA_DIR=/var/lib/echolet -e ECHOLET_NODE_CALLSIGN=${callsign} -v ${dataDir}:/var/lib/echolet echolet-relay:latest`;
38762
38803
  const id = execSync2(cmd, { encoding: "utf8" }).trim();
@@ -38774,7 +38815,7 @@ async function handleRepeaterCommand(args) {
38774
38815
  const env = {
38775
38816
  ...process.env,
38776
38817
  ECHOLET_HTTP_ADDR: `:${port}`,
38777
- ECHOLET_DATA_DIR: join4(repeater, "data"),
38818
+ ECHOLET_DATA_DIR: join5(repeater, "data"),
38778
38819
  ECHOLET_NODE_CALLSIGN: callsign
38779
38820
  };
38780
38821
  if (isDaemon) {
@@ -38869,8 +38910,8 @@ var profile_exports = {};
38869
38910
  __export(profile_exports, {
38870
38911
  handleProfileCommand: () => handleProfileCommand
38871
38912
  });
38872
- import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6, rmSync } from "node:fs";
38873
- import { join as join5 } from "node:path";
38913
+ import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6, rmSync as rmSync2 } from "node:fs";
38914
+ import { join as join6 } from "node:path";
38874
38915
  async function handleProfileCommand(args) {
38875
38916
  const sub = args[0] || "list";
38876
38917
  if (sub === "list") {
@@ -38888,7 +38929,7 @@ async function handleProfileCommand(args) {
38888
38929
  const isCurrent = name === config2.activeProfile || profiles.length === 1 && !config2.activeProfile;
38889
38930
  const activeMark = isCurrent ? " \u2B50 [\u0410\u041A\u0422\u0418\u0412\u041D\u0410\u042F]" : "";
38890
38931
  const dir = getProfileDir(name);
38891
- const hasDb = existsSync7(join5(dir, "client.sqlite"));
38932
+ const hasDb = existsSync7(join6(dir, "client.sqlite"));
38892
38933
  const status = hasDb ? "\u2705 \u0413\u043E\u0442\u043E\u0432\u0430" : "\u26A0\uFE0F \u041D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u0430";
38893
38934
  console.log(` \u{1F4FB} ${name.padEnd(20)} ${status}${activeMark}`);
38894
38935
  }
@@ -38922,7 +38963,7 @@ async function handleProfileCommand(args) {
38922
38963
  process.exit(1);
38923
38964
  }
38924
38965
  const dir = getProfileDir(target);
38925
- const cardPath = join5(dir, "identity.card.json");
38966
+ const cardPath = join6(dir, "identity.card.json");
38926
38967
  if (!existsSync7(cardPath)) {
38927
38968
  console.error(`\u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u043F\u0440\u043E\u0444\u0438\u043B\u044F ${target} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430 \u043D\u0430 \u0434\u0438\u0441\u043A\u0435 (${cardPath}).`);
38928
38969
  process.exit(1);
@@ -38956,7 +38997,7 @@ async function handleProfileCommand(args) {
38956
38997
  const { confirm: confirm2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
38957
38998
  const ok = await confirm2(`\u0412\u044B \u0422\u041E\u0427\u041D\u041E \u0443\u0432\u0435\u0440\u0435\u043D\u044B, \u0447\u0442\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0411\u0415\u0417\u0412\u041E\u0417\u0412\u0420\u0410\u0422\u041D\u041E \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0442\u0430\u043D\u0446\u0438\u044E "${target}" \u0438 \u0432\u0441\u044E \u0438\u0441\u0442\u043E\u0440\u0438\u044E?`, false);
38958
38999
  if (ok) {
38959
- rmSync(dir, { recursive: true, force: true });
39000
+ rmSync2(dir, { recursive: true, force: true });
38960
39001
  const config2 = getGlobalConfig();
38961
39002
  if (config2.activeProfile === target) {
38962
39003
  config2.activeProfile = void 0;
@@ -38983,7 +39024,7 @@ __export(contact_exports, {
38983
39024
  handleContactCommand: () => handleContactCommand
38984
39025
  });
38985
39026
  import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
38986
- import { join as join6 } from "node:path";
39027
+ import { join as join7 } from "node:path";
38987
39028
  async function handleContactCommand(args) {
38988
39029
  const sub = args[0] || "list";
38989
39030
  const config2 = getGlobalConfig();
@@ -38994,7 +39035,7 @@ async function handleContactCommand(args) {
38994
39035
  }
38995
39036
  const profileDir = getProfileDir(profileName);
38996
39037
  const storeKeyPath = getStoreKeyPath(profileName);
38997
- if (!existsSync8(storeKeyPath) || !existsSync8(join6(profileDir, "client.sqlite"))) {
39038
+ if (!existsSync8(storeKeyPath) || !existsSync8(join7(profileDir, "client.sqlite"))) {
38998
39039
  console.error(`\u041E\u0448\u0438\u0431\u043A\u0430: \u043F\u0440\u043E\u0444\u0438\u043B\u044C "${profileName}" \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0451\u043D \u0438\u043B\u0438 \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043A\u043B\u044E\u0447\u0435\u0439.`);
38999
39040
  process.exit(1);
39000
39041
  }
@@ -39098,9 +39139,9 @@ var init_contact = __esm({
39098
39139
 
39099
39140
  // src/commands/cli.ts
39100
39141
  init_config();
39101
- import { randomUUID as randomUUID4 } from "node:crypto";
39142
+ import { randomUUID as randomUUID5 } from "node:crypto";
39102
39143
  import { readFile, writeFile } from "node:fs/promises";
39103
- import { join as join7, resolve as resolve3 } from "node:path";
39144
+ import { join as join8, resolve as resolve3 } from "node:path";
39104
39145
  import { parseArgs } from "node:util";
39105
39146
 
39106
39147
  // src/runtime/inbound.ts
@@ -39423,7 +39464,7 @@ async function resolveSendBody(values) {
39423
39464
  }
39424
39465
  async function loadConfig(profileDir) {
39425
39466
  try {
39426
- const raw = await readFile(join7(resolve3(profileDir), "config.json"), "utf8");
39467
+ const raw = await readFile(join8(resolve3(profileDir), "config.json"), "utf8");
39427
39468
  return parseClientConfig(JSON.parse(raw));
39428
39469
  } catch (error40) {
39429
39470
  if (error40 instanceof ConfigurationError) throw error40;
@@ -39503,7 +39544,7 @@ async function execute(command, values) {
39503
39544
  case "init": {
39504
39545
  const config2 = parseClientConfig({
39505
39546
  profile_version: 1,
39506
- profile_id: randomUUID4(),
39547
+ profile_id: randomUUID5(),
39507
39548
  relay_url: required2(values, "relay-url"),
39508
39549
  database_path: "client.sqlite",
39509
39550
  store_key_env: required2(values, "store-key-env"),
@@ -39575,7 +39616,7 @@ async function execute(command, values) {
39575
39616
  }
39576
39617
  }
39577
39618
  case "send": {
39578
- const messageId = values["message-id"] ?? randomUUID4();
39619
+ const messageId = values["message-id"] ?? randomUUID5();
39579
39620
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(messageId)) throw inputFailure("INVALID_MESSAGE_ID");
39580
39621
  const config2 = await loadConfig(profileDir);
39581
39622
  let messenger;
@@ -39654,7 +39695,7 @@ async function main() {
39654
39695
  const rawArgs = process.argv.slice(2);
39655
39696
  const first = rawArgs[0];
39656
39697
  if (first === "--version" || first === "-v" || first === "version") {
39657
- console.log("0.1.0");
39698
+ console.log(true ? "0.1.1" : "0.1.1");
39658
39699
  return 0;
39659
39700
  }
39660
39701
  if (!first || first === "--help" || first === "-h" || first === "help") {
@@ -39662,35 +39703,41 @@ async function main() {
39662
39703
  printHelp2();
39663
39704
  return 0;
39664
39705
  }
39665
- if (first === "station") {
39666
- const { handleStationCommand: handleStationCommand2 } = await Promise.resolve().then(() => (init_station(), station_exports));
39667
- await handleStationCommand2(rawArgs.slice(1));
39668
- return 0;
39669
- }
39670
- if (first === "repeater") {
39671
- const { handleRepeaterCommand: handleRepeaterCommand2 } = await Promise.resolve().then(() => (init_repeater(), repeater_exports));
39672
- await handleRepeaterCommand2(rawArgs.slice(1));
39673
- return 0;
39674
- }
39675
- if (first === "profile") {
39676
- const { handleProfileCommand: handleProfileCommand2 } = await Promise.resolve().then(() => (init_profile2(), profile_exports));
39677
- await handleProfileCommand2(rawArgs.slice(1));
39678
- return 0;
39679
- }
39680
- if (first === "contact" && rawArgs[1] !== "export" && rawArgs[1] !== "import") {
39681
- const { handleContactCommand: handleContactCommand2 } = await Promise.resolve().then(() => (init_contact(), contact_exports));
39682
- await handleContactCommand2(rawArgs.slice(1));
39683
- return 0;
39684
- }
39685
- if (first === "radio" || first === "tui") {
39686
- const { dirname: dirname3, resolve: resolve4 } = await import("node:path");
39687
- const { fileURLToPath: fileURLToPath2 } = await import("node:url");
39688
- const { spawn: spawn4 } = await import("node:child_process");
39689
- const here = dirname3(fileURLToPath2(import.meta.url));
39690
- const tuiScript = resolve4(here, "tui.js");
39691
- const child = spawn4(process.execPath, [tuiScript, ...rawArgs.slice(1)], { stdio: "inherit" });
39692
- await new Promise((res) => child.on("exit", res));
39693
- return 0;
39706
+ try {
39707
+ if (first === "station") {
39708
+ const { handleStationCommand: handleStationCommand2 } = await Promise.resolve().then(() => (init_station(), station_exports));
39709
+ await handleStationCommand2(rawArgs.slice(1));
39710
+ return 0;
39711
+ }
39712
+ if (first === "repeater") {
39713
+ const { handleRepeaterCommand: handleRepeaterCommand2 } = await Promise.resolve().then(() => (init_repeater(), repeater_exports));
39714
+ await handleRepeaterCommand2(rawArgs.slice(1));
39715
+ return 0;
39716
+ }
39717
+ if (first === "profile") {
39718
+ const { handleProfileCommand: handleProfileCommand2 } = await Promise.resolve().then(() => (init_profile2(), profile_exports));
39719
+ await handleProfileCommand2(rawArgs.slice(1));
39720
+ return 0;
39721
+ }
39722
+ if (first === "contact" && rawArgs[1] !== "export" && rawArgs[1] !== "import") {
39723
+ const { handleContactCommand: handleContactCommand2 } = await Promise.resolve().then(() => (init_contact(), contact_exports));
39724
+ await handleContactCommand2(rawArgs.slice(1));
39725
+ return 0;
39726
+ }
39727
+ if (first === "radio" || first === "tui") {
39728
+ const { dirname: dirname3, resolve: resolve4 } = await import("node:path");
39729
+ const { fileURLToPath: fileURLToPath2 } = await import("node:url");
39730
+ const { spawn: spawn4 } = await import("node:child_process");
39731
+ const here = dirname3(fileURLToPath2(import.meta.url));
39732
+ const tuiScript = resolve4(here, "tui.js");
39733
+ const child = spawn4(process.execPath, [tuiScript, ...rawArgs.slice(1)], { stdio: "inherit" });
39734
+ await new Promise((res) => child.on("exit", res));
39735
+ return 0;
39736
+ }
39737
+ } catch (err) {
39738
+ console.error(`
39739
+ \u274C \u041E\u0448\u0438\u0431\u043A\u0430: ${err?.message || err}`);
39740
+ return 1;
39694
39741
  }
39695
39742
  try {
39696
39743
  const parsed = parseCommand(rawArgs);
package/dist/tui.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@goodea/echolet",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=22.13"
8
8
  },
9
9
  "bin": {
10
- "echolet": "./dist/cli.js",
11
- "echolet-tui": "./dist/tui.js"
10
+ "echolet": "dist/cli.js",
11
+ "echolet-tui": "dist/tui.js"
12
12
  },
13
13
  "files": [
14
14
  "dist",