@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 +136 -89
- package/dist/tui.js +0 -0
- package/package.json +3 -3
- package/web-dist/client/bundle.js +5 -5
- package/web-dist/client/styles.css +453 -0
- package/web-dist/server.js +353 -82
- package/dist/cli.red-24474.js +0 -37801
- package/web-dist/client/audiophile_tube_ui_1789836391373.jpg +0 -0
- package/web-dist/client/cyberdeck_spectrum_ui_1789835241900.jpg +0 -0
- package/web-dist/client/echolet_obsidian_clean_1789834739350.jpg +0 -0
- package/web-dist/client/echolet_split_horizon_1789834765974.jpg +0 -0
- package/web-dist/client/echolet_tactical_terminal_1789834714340.jpg +0 -0
- package/web-dist/client/gallery.html +0 -541
- package/web-dist/client/glassmorphic_radio_ui_1789835283668.jpg +0 -0
- package/web-dist/client/nixie_tube_messenger_1789836184230.jpg +0 -0
- package/web-dist/client/op1_minimal_skin_1789836795427.jpg +0 -0
- package/web-dist/client/soviet_tube_radio_1789836251332.jpg +0 -0
- package/web-dist/client/stealth_zerotrace_ui_1789835261306.jpg +0 -0
- package/web-dist/client/steampunk_brass_ui_1789836339337.jpg +0 -0
- package/web-dist/client/tube_oscilloscope_ui_1789836294852.jpg +0 -0
- package/web-dist/client/vintage_radiola_ui_1789836216660.jpg +0 -0
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
|
-
|
|
38397
|
+
closeReadline: () => closeReadline,
|
|
38398
|
+
confirm: () => confirm,
|
|
38399
|
+
getReadline: () => getReadline
|
|
38401
38400
|
});
|
|
38402
|
-
import { createInterface } from "node:readline
|
|
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
|
|
38422
|
+
const { rl, iterator } = getReadline();
|
|
38406
38423
|
const promptText = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
38407
|
-
|
|
38408
|
-
|
|
38409
|
-
|
|
38410
|
-
|
|
38411
|
-
|
|
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)
|
|
38478
|
-
|
|
38479
|
-
|
|
38480
|
-
|
|
38481
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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=${
|
|
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(
|
|
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 =
|
|
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 =
|
|
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:
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
|
39142
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
39102
39143
|
import { readFile, writeFile } from "node:fs/promises";
|
|
39103
|
-
import { join as
|
|
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(
|
|
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:
|
|
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"] ??
|
|
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
|
-
|
|
39666
|
-
|
|
39667
|
-
|
|
39668
|
-
|
|
39669
|
-
|
|
39670
|
-
|
|
39671
|
-
|
|
39672
|
-
|
|
39673
|
-
|
|
39674
|
-
|
|
39675
|
-
|
|
39676
|
-
|
|
39677
|
-
|
|
39678
|
-
|
|
39679
|
-
|
|
39680
|
-
|
|
39681
|
-
|
|
39682
|
-
|
|
39683
|
-
|
|
39684
|
-
|
|
39685
|
-
|
|
39686
|
-
|
|
39687
|
-
|
|
39688
|
-
|
|
39689
|
-
|
|
39690
|
-
|
|
39691
|
-
|
|
39692
|
-
|
|
39693
|
-
|
|
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.
|
|
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": "
|
|
11
|
-
"echolet-tui": "
|
|
10
|
+
"echolet": "dist/cli.js",
|
|
11
|
+
"echolet-tui": "dist/tui.js"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|