@danieltmn/openbridge 0.6.0 → 0.6.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/CHANGELOG.md +12 -0
- package/README.md +12 -3
- package/package.json +1 -1
- package/src/cli.js +83 -10
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ Todos los cambios relevantes de OpenBridge. Formato basado en
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y
|
|
5
5
|
[Versionado Semantico](https://semver.org/lang/es/).
|
|
6
6
|
|
|
7
|
+
## [0.6.1] - 2026-09-14
|
|
8
|
+
|
|
9
|
+
### Agregado
|
|
10
|
+
|
|
11
|
+
- `openbridge bridge --background` (segundo plano; sobrevive al cierre de la
|
|
12
|
+
consola), `--stop` y `--status`. `openbridge pair`/`join` aceptan `--background`.
|
|
13
|
+
|
|
14
|
+
### Corregido
|
|
15
|
+
|
|
16
|
+
- `autostart` corre solo el puente cuando la PC pertenece a un hub remoto
|
|
17
|
+
(`join`/`pair`), en vez del server local.
|
|
18
|
+
|
|
7
19
|
## [0.6.0] - 2026-09-14
|
|
8
20
|
|
|
9
21
|
### Agregado
|
package/README.md
CHANGED
|
@@ -89,9 +89,9 @@ iniciar sesión** una vez; los chats, carpetas, túnel y push se conservan.
|
|
|
89
89
|
| `openbridge qr` | Muestra la URL (pública o local) como QR para escanear desde el celular |
|
|
90
90
|
| `openbridge tunnel` | Muestra o cambia el proveedor de túnel y su dominio fijo (`--domain`) |
|
|
91
91
|
| `openbridge logs` | Logs (`--follow`, `--server`, `--bridge`) |
|
|
92
|
-
| `openbridge bridge` | Corre **solo** el puente (`--
|
|
93
|
-
| `openbridge join` | Vincula esta PC como puente de un hub (`<url> --token --id --name`) |
|
|
94
|
-
| `openbridge pair` | Empareja esta PC con un **hub PHP** por código (`<url> [--id --name]`) |
|
|
92
|
+
| `openbridge bridge` | Corre **solo** el puente (`--background` = segundo plano, `--stop`, `--status`) |
|
|
93
|
+
| `openbridge join` | Vincula esta PC como puente de un hub (`<url> --token --id --name [--background]`) |
|
|
94
|
+
| `openbridge pair` | Empareja esta PC con un **hub PHP** por código (`<url> [--id --name] [--background]`) |
|
|
95
95
|
| `openbridge import` | Trae `data/` de OpenConex (`<data-dir> [--force]`) |
|
|
96
96
|
| `openbridge reset` | Borra chats/datos (`--session <id>`, `--yes`) |
|
|
97
97
|
| `openbridge autostart` | Arranque automático (`install`/`remove`) |
|
|
@@ -162,6 +162,15 @@ igual que OpenConex, y dejar que cada PC corra solo el puente:
|
|
|
162
162
|
|
|
163
163
|
Guía completa (requisitos, build, subida y emparejamiento): [`docs/DEPLOY-PHP.md`](docs/DEPLOY-PHP.md).
|
|
164
164
|
|
|
165
|
+
La PC corre el puente; para que siga tras cerrar la consola:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
openbridge bridge --background # arranca en segundo plano
|
|
169
|
+
openbridge bridge --status # ¿corre?
|
|
170
|
+
openbridge bridge --stop # detener
|
|
171
|
+
openbridge autostart install # arranca solo al iniciar sesión
|
|
172
|
+
```
|
|
173
|
+
|
|
165
174
|
## Túnel y URL estable
|
|
166
175
|
|
|
167
176
|
Proveedores (`--tunnel` o `openbridge tunnel <prov>`): `tunnelmole` (gratis, sin
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -682,12 +682,46 @@ async function cmdLogs(argv) {
|
|
|
682
682
|
// ---------------------------------------------------------------------------
|
|
683
683
|
// bridge (solo el puente, para modo hub remoto)
|
|
684
684
|
// ---------------------------------------------------------------------------
|
|
685
|
+
function bridgePid() {
|
|
686
|
+
try {
|
|
687
|
+
return parseInt(fs.readFileSync(paths.bridgeLockPath(), 'utf8'), 10) || 0;
|
|
688
|
+
} catch (e) {
|
|
689
|
+
return 0;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
685
693
|
async function cmdBridge(argv) {
|
|
686
694
|
const { flags } = parseArgs(argv);
|
|
687
695
|
if (!fs.existsSync(paths.configPath())) {
|
|
688
|
-
console.error('No hay configuracion de puente en ' + paths.home() + '. Corre primero: openbridge join <url> o openbridge
|
|
696
|
+
console.error('No hay configuracion de puente en ' + paths.home() + '. Corre primero: openbridge join <url> o openbridge pair <url>');
|
|
689
697
|
return 1;
|
|
690
698
|
}
|
|
699
|
+
|
|
700
|
+
if (flags.stop) {
|
|
701
|
+
const pid = bridgePid();
|
|
702
|
+
if (!pid || !pidAlive(pid)) {
|
|
703
|
+
try { fs.unlinkSync(paths.bridgeLockPath()); } catch (e) { /* nada */ }
|
|
704
|
+
console.log('El puente no esta corriendo.');
|
|
705
|
+
return 0;
|
|
706
|
+
}
|
|
707
|
+
killPid(pid);
|
|
708
|
+
try { fs.unlinkSync(paths.bridgeLockPath()); } catch (e) { /* nada */ }
|
|
709
|
+
console.log('Puente detenido (pid ' + pid + ').');
|
|
710
|
+
return 0;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const cfg = config.readBridge();
|
|
714
|
+
if (flags.status) {
|
|
715
|
+
const pid = bridgePid();
|
|
716
|
+
const live = pid && pidAlive(pid);
|
|
717
|
+
console.log('Puente: ' + (live ? 'corriendo (pid ' + pid + ')' : 'detenido'));
|
|
718
|
+
console.log(' hub : ' + (cfg.apiUrl || '(sin configurar)'));
|
|
719
|
+
console.log(' id : ' + (cfg.bridgeId || '(sin id)'));
|
|
720
|
+
console.log(' nombre : ' + (cfg.bridgeName || ''));
|
|
721
|
+
console.log(' log : ' + paths.bridgeLogPath());
|
|
722
|
+
return 0;
|
|
723
|
+
}
|
|
724
|
+
|
|
691
725
|
// Permite apuntar a otro hub sin editar config.json a mano.
|
|
692
726
|
const env = { ...process.env, OPENBRIDGE_HOME: paths.baseDir() };
|
|
693
727
|
if (flags.api) env.OPENBRIDGE_API_URL = String(flags.api);
|
|
@@ -695,6 +729,33 @@ async function cmdBridge(argv) {
|
|
|
695
729
|
if (flags.id) env.OPENBRIDGE_BRIDGE_ID = String(flags.id);
|
|
696
730
|
if (flags.name) env.OPENBRIDGE_BRIDGE_NAME = String(flags.name);
|
|
697
731
|
const bridgePath = path.join(__dirname, 'bridge', 'bridge.js');
|
|
732
|
+
|
|
733
|
+
// Segundo plano: detached + stdio ignorado; sobrevive al cierre de la consola.
|
|
734
|
+
if (flags.background || flags.bg || flags.detach || flags.d) {
|
|
735
|
+
const existing = bridgePid();
|
|
736
|
+
if (existing && pidAlive(existing)) {
|
|
737
|
+
console.log('El puente ya corre en segundo plano (pid ' + existing + ').');
|
|
738
|
+
console.log(' estado: openbridge bridge --status · detener: openbridge bridge --stop');
|
|
739
|
+
return 0;
|
|
740
|
+
}
|
|
741
|
+
const child = spawn(process.execPath, [bridgePath], {
|
|
742
|
+
cwd: paths.home(),
|
|
743
|
+
env,
|
|
744
|
+
stdio: 'ignore',
|
|
745
|
+
windowsHide: true,
|
|
746
|
+
detached: true,
|
|
747
|
+
});
|
|
748
|
+
child.unref();
|
|
749
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
750
|
+
const pid = bridgePid() || child.pid;
|
|
751
|
+
console.log('Puente en segundo plano (pid ' + pid + ').');
|
|
752
|
+
console.log(' hub : ' + (cfg.apiUrl || '(sin configurar)'));
|
|
753
|
+
console.log(' log : ' + paths.bridgeLogPath());
|
|
754
|
+
console.log(' estado : openbridge bridge --status');
|
|
755
|
+
console.log(' detener: openbridge bridge --stop');
|
|
756
|
+
return 0;
|
|
757
|
+
}
|
|
758
|
+
|
|
698
759
|
const child = spawn(process.execPath, [bridgePath], {
|
|
699
760
|
cwd: paths.home(),
|
|
700
761
|
env,
|
|
@@ -718,11 +779,16 @@ function hubApiUrl(raw) {
|
|
|
718
779
|
return u;
|
|
719
780
|
}
|
|
720
781
|
|
|
782
|
+
// Reenvia `--background` a `openbridge bridge` cuando join/pair lo piden.
|
|
783
|
+
function bridgeStartArgs(flags) {
|
|
784
|
+
return (flags.background || flags.bg || flags.detach || flags.d) ? ['--background'] : [];
|
|
785
|
+
}
|
|
786
|
+
|
|
721
787
|
async function cmdJoin(argv) {
|
|
722
788
|
const { flags, _ } = parseArgs(argv);
|
|
723
789
|
const url = String(_[0] || flags.api || '').trim();
|
|
724
790
|
if (!url || !/^https?:\/\//i.test(url)) {
|
|
725
|
-
console.error('Uso: openbridge join <url-del-hub> [--token <t>] [--id <pc>] [--name "<nombre>"] [--no-start]');
|
|
791
|
+
console.error('Uso: openbridge join <url-del-hub> [--token <t>] [--id <pc>] [--name "<nombre>"] [--no-start] [--background]');
|
|
726
792
|
console.error('Ej.: openbridge join https://mi-pc.trycloudflare.com --token <t> --id pc2 --name "PC oficina"');
|
|
727
793
|
console.error('(acepta la base, /chat.php o /api.php; se normaliza a /api.php)');
|
|
728
794
|
return 1;
|
|
@@ -747,7 +813,7 @@ async function cmdJoin(argv) {
|
|
|
747
813
|
}
|
|
748
814
|
console.log('');
|
|
749
815
|
console.log('Arrancando el puente (Ctrl+C para salir)...');
|
|
750
|
-
return cmdBridge(
|
|
816
|
+
return cmdBridge(bridgeStartArgs(flags));
|
|
751
817
|
}
|
|
752
818
|
|
|
753
819
|
// ---------------------------------------------------------------------------
|
|
@@ -771,7 +837,7 @@ async function cmdPair(argv) {
|
|
|
771
837
|
const { flags, _ } = parseArgs(argv);
|
|
772
838
|
const url = String(_[0] || flags.hub || flags.api || '').trim();
|
|
773
839
|
if (!/^https?:\/\//i.test(url)) {
|
|
774
|
-
console.error('Uso: openbridge pair <url-del-hub> [--id <pc>] [--name "<nombre>"] [--no-start]');
|
|
840
|
+
console.error('Uso: openbridge pair <url-del-hub> [--id <pc>] [--name "<nombre>"] [--no-start] [--background]');
|
|
775
841
|
console.error('Ej.: openbridge pair https://openbridge.tamnora.com --name "PC 1"');
|
|
776
842
|
return 1;
|
|
777
843
|
}
|
|
@@ -842,7 +908,7 @@ async function cmdPair(argv) {
|
|
|
842
908
|
return 0;
|
|
843
909
|
}
|
|
844
910
|
console.log('Arrancando el puente (Ctrl+C para salir)...');
|
|
845
|
-
return cmdBridge(
|
|
911
|
+
return cmdBridge(bridgeStartArgs(flags));
|
|
846
912
|
}
|
|
847
913
|
|
|
848
914
|
// ---------------------------------------------------------------------------
|
|
@@ -1062,12 +1128,18 @@ async function cmdAutostart(argv) {
|
|
|
1062
1128
|
}
|
|
1063
1129
|
try { fs.mkdirSync(path.dirname(target), { recursive: true }); } catch (e) { /* nada */ }
|
|
1064
1130
|
const home = paths.baseDir();
|
|
1131
|
+
// Si esta PC es un puente de un hub remoto (join/pair), el autostart corre
|
|
1132
|
+
// solo el puente; si es el hub local, corre el server.
|
|
1133
|
+
let acfg = { apiUrl: '' };
|
|
1134
|
+
try { acfg = config.readBridge(); } catch (e) { /* nada */ }
|
|
1135
|
+
const remote = /^https?:\/\//i.test(acfg.apiUrl || '') && !/127\.0\.0\.1|localhost/i.test(acfg.apiUrl);
|
|
1136
|
+
const runArgs = remote ? 'bridge' : 'server --stream --no-tunnel';
|
|
1065
1137
|
if (process.platform === 'win32') {
|
|
1066
1138
|
const ps = [
|
|
1067
1139
|
'$ws = New-Object -ComObject WScript.Shell;',
|
|
1068
1140
|
'$sc = $ws.CreateShortcut(' + JSON.stringify(target) + ');',
|
|
1069
1141
|
'$sc.TargetPath = ' + JSON.stringify(node) + ';',
|
|
1070
|
-
'$sc.Arguments = ' + JSON.stringify('"' + bin + '"
|
|
1142
|
+
'$sc.Arguments = ' + JSON.stringify('"' + bin + '" ' + runArgs) + ';',
|
|
1071
1143
|
'$sc.WorkingDirectory = ' + JSON.stringify(home) + ';',
|
|
1072
1144
|
'$sc.WindowStyle = 7;',
|
|
1073
1145
|
'$sc.Save();',
|
|
@@ -1080,7 +1152,8 @@ async function cmdAutostart(argv) {
|
|
|
1080
1152
|
+ '<plist version="1.0"><dict>'
|
|
1081
1153
|
+ '<key>Label</key><string>net.openbridge.server</string>'
|
|
1082
1154
|
+ '<key>ProgramArguments</key><array>'
|
|
1083
|
-
+ '<string>' + node + '</string><string>' + bin + '</string
|
|
1155
|
+
+ '<string>' + node + '</string><string>' + bin + '</string>'
|
|
1156
|
+
+ runArgs.split(' ').map((a) => '<string>' + a + '</string>').join('')
|
|
1084
1157
|
+ '</array>'
|
|
1085
1158
|
+ '<key>WorkingDirectory</key><string>' + home + '</string>'
|
|
1086
1159
|
+ '<key>RunAtLoad</key><true/><key>KeepAlive</key><true/>'
|
|
@@ -1089,7 +1162,7 @@ async function cmdAutostart(argv) {
|
|
|
1089
1162
|
} else {
|
|
1090
1163
|
const unit = '[Unit]\nDescription=OpenBridge\nAfter=network-online.target\n\n'
|
|
1091
1164
|
+ '[Service]\nType=simple\n'
|
|
1092
|
-
+ 'ExecStart=' + node + ' ' + bin + '
|
|
1165
|
+
+ 'ExecStart=' + node + ' ' + bin + ' ' + runArgs + '\n'
|
|
1093
1166
|
+ 'WorkingDirectory=' + home + '\nRestart=on-failure\n\n'
|
|
1094
1167
|
+ '[Install]\nWantedBy=default.target\n';
|
|
1095
1168
|
fs.writeFileSync(target, unit);
|
|
@@ -1097,7 +1170,7 @@ async function cmdAutostart(argv) {
|
|
|
1097
1170
|
spawnSync('systemctl', ['--user', 'enable', '--now', 'openbridge.service'], { windowsHide: true });
|
|
1098
1171
|
}
|
|
1099
1172
|
console.log('autostart instalado: ' + target);
|
|
1100
|
-
console.log(' (arranca `openbridge
|
|
1173
|
+
console.log(' (arranca `openbridge ' + runArgs + '` en ' + home + ')');
|
|
1101
1174
|
return 0;
|
|
1102
1175
|
}
|
|
1103
1176
|
|
|
@@ -1202,7 +1275,7 @@ function usage() {
|
|
|
1202
1275
|
console.log(' qr Muestra la URL (publica o local) como QR para el celular');
|
|
1203
1276
|
console.log(' tunnel Muestra o cambia el proveedor de tunel (tunnelmole|ngrok|cloudflare|none) [--domain]');
|
|
1204
1277
|
console.log(' logs Ultimas lineas de los logs (--follow --server --bridge)');
|
|
1205
|
-
console.log(' bridge Corre solo el puente (--
|
|
1278
|
+
console.log(' bridge Corre solo el puente (--background | --stop | --status)');
|
|
1206
1279
|
console.log(' join Vincula esta PC como puente de un hub (<url> --token --id --name)');
|
|
1207
1280
|
console.log(' pair Empareja esta PC con un hub PHP por codigo (<url> [--id --name])');
|
|
1208
1281
|
console.log(' import Trae data/ de OpenConex (<data-dir> [--force])');
|