@danieltmn/openbridge 0.6.1 → 0.6.2

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,16 @@ 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.2] - 2026-09-14
8
+
9
+ ### Corregido
10
+
11
+ - **Tunel en Windows**: los shims `.cmd` (p. ej. `tmole`) se lanzaban con doble
12
+ cita (`cmd.exe /d /s /c "\"ruta\""`) y fallaban con "no se reconoce como un
13
+ comando". Ahora se usa `windowsVerbatimArguments` y, si `tmole` falla, el
14
+ puente **reintenta con `npx --yes tunnelmole`** (antes solo lo intentaba si
15
+ `tmole` no estaba en el PATH). Timeout del tunel: 85 s.
16
+
7
17
  ## [0.6.1] - 2026-09-14
8
18
 
9
19
  ### Agregado
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danieltmn/openbridge",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
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",
@@ -1700,10 +1700,24 @@ function tunnelSpawn(port, onLine, onFail, onUrls, triedNpx = false) {
1700
1700
  return;
1701
1701
  }
1702
1702
  const args = (spec.pre || []).concat(triedNpx ? ['--yes', 'tunnelmole', String(port)] : [String(port)]);
1703
+ let settled = false;
1704
+ // Si `tmole` existe pero falla (shim roto, sin PATH, etc.), reintentamos con
1705
+ // `npx --yes tunnelmole` en vez de darnos por vencidos.
1706
+ const retryNpx = () => {
1707
+ if (settled) return;
1708
+ settled = true;
1709
+ log('túnel: tmole falló, reintentando con npx tunnelmole…');
1710
+ tunnelSpawn(port, onLine, onFail, onUrls, true);
1711
+ };
1703
1712
  let proc;
1704
1713
  try {
1705
- proc = spawn(spec.bin, args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
1714
+ proc = spawn(spec.bin, args, {
1715
+ stdio: ['ignore', 'pipe', 'pipe'],
1716
+ windowsHide: true,
1717
+ windowsVerbatimArguments: !!spec.verbatim,
1718
+ });
1706
1719
  } catch (e) {
1720
+ if (!triedNpx) { retryNpx(); return; }
1707
1721
  onFail('no se pudo iniciar tunnelmole (' + e.message + '). Instalalo con: npm i -g tunnelmole');
1708
1722
  return;
1709
1723
  }
@@ -1711,14 +1725,17 @@ function tunnelSpawn(port, onLine, onFail, onUrls, triedNpx = false) {
1711
1725
  const feed = (d) => {
1712
1726
  buf += String(d);
1713
1727
  const urls = parseTunnelUrls(buf);
1714
- if (urls.https || urls.http) onUrls(urls);
1728
+ if (urls.https || urls.http) { settled = true; onUrls(urls); }
1715
1729
  };
1716
1730
  proc.stdout.on('data', feed);
1717
1731
  proc.stderr.on('data', feed);
1718
1732
  proc.on('error', (e) => {
1733
+ if (!triedNpx) { retryNpx(); return; }
1719
1734
  onFail('no se pudo iniciar tunnelmole (' + e.message + '). Instalalo con: npm i -g tunnelmole');
1720
1735
  });
1721
1736
  proc.on('exit', (code) => {
1737
+ if (settled) return;
1738
+ if (!triedNpx) { retryNpx(); return; }
1722
1739
  onFail('tmole terminó (código ' + code + ')' + (buf ? ': ' + buf.slice(0, 160).trim() : ''));
1723
1740
  });
1724
1741
  onLine(proc);
@@ -1756,10 +1773,10 @@ async function tunnelStart(cmd) {
1756
1773
  };
1757
1774
  entry = { port, proc: null, urls: { https: '', http: '' }, startedAt: Date.now() };
1758
1775
  tunnels.set(port, entry);
1759
- // 60 s: con el fallback de npx, la primera vez descarga tunnelmole.
1776
+ // 85 s: con el fallback de npx, la primera vez descarga tunnelmole.
1760
1777
  timer = setTimeout(() => {
1761
- finish(false, 'tunnelmole no devolvió URLs (60 s). ¿Está instalado? npm i -g tunnelmole');
1762
- }, 60000);
1778
+ finish(false, 'tunnelmole no devolvió URLs (85 s). ¿Está instalado? npm i -g tunnelmole');
1779
+ }, 85000);
1763
1780
  tunnelSpawn(
1764
1781
  port,
1765
1782
  (proc) => { entry.proc = proc; },
@@ -1913,7 +1930,9 @@ function procResolveBin(token, allowSet) {
1913
1930
  const found = procFindOnPath(bare);
1914
1931
  if (!found) throw new Error('no se encontró "' + token + '" en el PATH');
1915
1932
  if (found.ext.toLowerCase() === '.exe') return { bin: found.p, pre: [] };
1916
- return { bin: 'cmd.exe', pre: ['/d', '/s', '/c', '"' + found.p + '"'] };
1933
+ // Shim .cmd/.bat: se ejecuta con cmd.exe. `verbatim` evita que Node vuelva a
1934
+ // citar el argumento (que ya viene entre comillas) y cmd reciba "\"ruta\"".
1935
+ return { bin: 'cmd.exe', pre: ['/d', '/s', '/c', '"' + found.p + '"'], verbatim: true };
1917
1936
  }
1918
1937
 
1919
1938
  async function procDone(cmd, ok, payload, error) {
@@ -2000,6 +2019,7 @@ async function procStart(cmd) {
2000
2019
  stdio: ['ignore', 'pipe', 'pipe'],
2001
2020
  env: process.env,
2002
2021
  windowsHide: true,
2022
+ windowsVerbatimArguments: !!spec.verbatim,
2003
2023
  });
2004
2024
  } catch (e) {
2005
2025
  await procDone(cmd, false, null, 'no se pudo iniciar: ' + e.message);