@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 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 (`--api --token --id --name`) |
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danieltmn/openbridge",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Tu opencode en el celular, sin hosting: corre la app, el puente y un tunel publico desde tu PC.",
5
5
  "type": "commonjs",
6
6
  "author": "tamnora",
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 init');
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 + '" server --stream --no-tunnel') + ';',
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><string>server</string><string>--stream</string><string>--no-tunnel</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 + ' server --stream --no-tunnel\n'
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 server --stream --no-tunnel` en ' + home + ')');
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 (--api --token --id --name)');
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])');