fluxy-bot 0.5.39 → 0.5.41
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/bin/cli.js +87 -19
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -81,6 +81,19 @@ WantedBy=multi-user.target
|
|
|
81
81
|
`;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
function killAndWait(child, timeout = 10_000) {
|
|
85
|
+
return new Promise((resolve) => {
|
|
86
|
+
child.removeAllListeners('exit');
|
|
87
|
+
child.on('exit', () => resolve());
|
|
88
|
+
child.kill('SIGTERM');
|
|
89
|
+
// Force kill after timeout if SIGTERM doesn't work
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
try { child.kill('SIGKILL'); } catch {}
|
|
92
|
+
setTimeout(resolve, 500);
|
|
93
|
+
}, timeout);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
84
97
|
// ── UI helpers ──
|
|
85
98
|
|
|
86
99
|
const c = {
|
|
@@ -433,9 +446,7 @@ async function init() {
|
|
|
433
446
|
|
|
434
447
|
// Install systemd daemon on Linux
|
|
435
448
|
if (hasSystemd) {
|
|
436
|
-
child
|
|
437
|
-
child.kill('SIGTERM');
|
|
438
|
-
await new Promise((r) => setTimeout(r, 4000));
|
|
449
|
+
await killAndWait(child);
|
|
439
450
|
const nodePath = process.execPath;
|
|
440
451
|
const realHome = os.homedir();
|
|
441
452
|
const res = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
|
|
@@ -472,6 +483,21 @@ async function start() {
|
|
|
472
483
|
return init();
|
|
473
484
|
}
|
|
474
485
|
|
|
486
|
+
// If daemon is already running, don't start a second instance
|
|
487
|
+
if (os.platform() === 'linux' && isServiceInstalled() && isServiceActive()) {
|
|
488
|
+
banner();
|
|
489
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
|
|
490
|
+
console.log(`\n ${c.blue}●${c.reset} Fluxy is already running as a daemon.\n`);
|
|
491
|
+
if (config.relay?.url) {
|
|
492
|
+
console.log(` ${c.dim}URL:${c.reset} ${c.pink}${link(config.relay.url)}${c.reset}`);
|
|
493
|
+
}
|
|
494
|
+
console.log(` ${c.dim}Status:${c.reset} ${c.pink}fluxy daemon status${c.reset}`);
|
|
495
|
+
console.log(` ${c.dim}Logs:${c.reset} ${c.pink}fluxy daemon logs${c.reset}`);
|
|
496
|
+
console.log(` ${c.dim}Restart:${c.reset} ${c.pink}fluxy daemon restart${c.reset}`);
|
|
497
|
+
console.log(` ${c.dim}Stop:${c.reset} ${c.pink}fluxy daemon stop${c.reset}\n`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
475
501
|
const isLinux = os.platform() === 'linux';
|
|
476
502
|
const hasSystemd = isLinux && (() => { try { execSync('systemctl --version', { stdio: 'ignore' }); return true; } catch { return false; } })();
|
|
477
503
|
const needsDaemon = hasSystemd && !isServiceInstalled();
|
|
@@ -511,9 +537,7 @@ async function start() {
|
|
|
511
537
|
|
|
512
538
|
// Install systemd daemon on Linux if not already installed
|
|
513
539
|
if (needsDaemon) {
|
|
514
|
-
child
|
|
515
|
-
child.kill('SIGTERM');
|
|
516
|
-
await new Promise((r) => setTimeout(r, 4000));
|
|
540
|
+
await killAndWait(child);
|
|
517
541
|
const nodePath = process.execPath;
|
|
518
542
|
const realHome = os.homedir();
|
|
519
543
|
const res = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
|
|
@@ -546,17 +570,33 @@ async function start() {
|
|
|
546
570
|
}
|
|
547
571
|
|
|
548
572
|
async function status() {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
573
|
+
const config = fs.existsSync(CONFIG_PATH) ? JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')) : null;
|
|
574
|
+
const daemonRunning = os.platform() === 'linux' && isServiceInstalled() && isServiceActive();
|
|
575
|
+
|
|
576
|
+
// Try health endpoint
|
|
577
|
+
let healthOk = false;
|
|
578
|
+
let uptime = null;
|
|
579
|
+
if (config) {
|
|
580
|
+
try {
|
|
581
|
+
const res = await fetch(`http://localhost:${config.port}/api/health`);
|
|
582
|
+
const data = await res.json();
|
|
583
|
+
healthOk = true;
|
|
584
|
+
uptime = data.uptime;
|
|
585
|
+
} catch {}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (healthOk) {
|
|
589
|
+
console.log(`\n ${c.blue}●${c.reset} Fluxy is running${daemonRunning ? ` ${c.dim}(daemon)${c.reset}` : ''}`);
|
|
590
|
+
if (uptime != null) console.log(` ${c.dim}Uptime: ${uptime}s${c.reset}`);
|
|
591
|
+
if (config?.relay?.url) {
|
|
556
592
|
console.log(` ${c.dim}URL: ${c.reset}${c.pink}${link(config.relay.url)}${c.reset}`);
|
|
557
593
|
}
|
|
558
594
|
console.log(` ${c.dim}Config: ${CONFIG_PATH}${c.reset}\n`);
|
|
559
|
-
}
|
|
595
|
+
} else if (daemonRunning) {
|
|
596
|
+
console.log(`\n ${c.yellow}●${c.reset} Fluxy daemon is running but not responding yet.`);
|
|
597
|
+
console.log(` ${c.dim}It may still be starting up. Check logs:${c.reset}`);
|
|
598
|
+
console.log(` ${c.pink}fluxy daemon logs${c.reset}\n`);
|
|
599
|
+
} else {
|
|
560
600
|
console.log(`\n ${c.dim}●${c.reset} Fluxy is not running.\n`);
|
|
561
601
|
}
|
|
562
602
|
}
|
|
@@ -586,16 +626,29 @@ async function update() {
|
|
|
586
626
|
|
|
587
627
|
console.log(` ${c.dim}v${currentVersion} → v${latest.version}${c.reset}\n`);
|
|
588
628
|
|
|
629
|
+
const daemonWasRunning = os.platform() === 'linux' && isServiceInstalled() && isServiceActive();
|
|
630
|
+
|
|
589
631
|
const steps = [
|
|
632
|
+
...(daemonWasRunning ? ['Stopping daemon'] : []),
|
|
590
633
|
'Downloading update',
|
|
591
634
|
'Updating files',
|
|
592
635
|
'Installing dependencies',
|
|
593
636
|
'Building interface',
|
|
637
|
+
...(daemonWasRunning ? ['Restarting daemon'] : []),
|
|
594
638
|
];
|
|
595
639
|
|
|
596
640
|
const stepper = new Stepper(steps);
|
|
597
641
|
stepper.start();
|
|
598
642
|
|
|
643
|
+
// Stop daemon before updating files
|
|
644
|
+
if (daemonWasRunning) {
|
|
645
|
+
try {
|
|
646
|
+
const cmd = needsSudo() ? `sudo systemctl stop ${SERVICE_NAME}` : `systemctl stop ${SERVICE_NAME}`;
|
|
647
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
648
|
+
} catch {}
|
|
649
|
+
stepper.advance();
|
|
650
|
+
}
|
|
651
|
+
|
|
599
652
|
// Download tarball
|
|
600
653
|
const tarballUrl = latest.dist.tarball;
|
|
601
654
|
const tmpDir = path.join(os.tmpdir(), `fluxy-update-${Date.now()}`);
|
|
@@ -670,17 +723,32 @@ async function update() {
|
|
|
670
723
|
// Clean up
|
|
671
724
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
672
725
|
|
|
726
|
+
// Restart daemon if it was running
|
|
727
|
+
if (daemonWasRunning) {
|
|
728
|
+
try {
|
|
729
|
+
const cmd = needsSudo() ? `sudo systemctl start ${SERVICE_NAME}` : `systemctl start ${SERVICE_NAME}`;
|
|
730
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
731
|
+
} catch {}
|
|
732
|
+
stepper.advance();
|
|
733
|
+
}
|
|
734
|
+
|
|
673
735
|
stepper.finish();
|
|
674
736
|
|
|
675
737
|
console.log(`\n ${c.blue}${c.bold}✔ Updated to v${latest.version}${c.reset}\n`);
|
|
676
738
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
try {
|
|
680
|
-
execSync(`systemctl restart ${SERVICE_NAME}`, { stdio: 'ignore' });
|
|
739
|
+
if (daemonWasRunning) {
|
|
740
|
+
if (isServiceActive()) {
|
|
681
741
|
console.log(` ${c.blue}✔${c.reset} Daemon restarted with new version.\n`);
|
|
742
|
+
} else {
|
|
743
|
+
console.log(` ${c.yellow}⚠${c.reset} Daemon may still be starting. Check ${c.pink}fluxy daemon status${c.reset}\n`);
|
|
744
|
+
}
|
|
745
|
+
} else if (os.platform() === 'linux' && isServiceInstalled()) {
|
|
746
|
+
try {
|
|
747
|
+
const cmd = needsSudo() ? `sudo systemctl start ${SERVICE_NAME}` : `systemctl start ${SERVICE_NAME}`;
|
|
748
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
749
|
+
console.log(` ${c.blue}✔${c.reset} Daemon started with new version.\n`);
|
|
682
750
|
} catch {
|
|
683
|
-
console.log(` ${c.
|
|
751
|
+
console.log(` ${c.dim}Run ${c.reset}${c.pink}fluxy daemon start${c.reset}${c.dim} to launch.${c.reset}\n`);
|
|
684
752
|
}
|
|
685
753
|
} else {
|
|
686
754
|
console.log(` ${c.dim}Run ${c.reset}${c.pink}fluxy start${c.reset}${c.dim} to launch.${c.reset}\n`);
|