pi-bridge 0.2.7 → 0.2.9

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/README.md CHANGED
@@ -67,6 +67,7 @@ pi loads — unaware of bridge restricts to remoteCwd
67
67
  → git branch in footer ✓
68
68
  ```
69
69
 
70
+
70
71
  ## What Gets Patched
71
72
 
72
73
  | API | Covered |
@@ -77,6 +78,8 @@ pi loads — unaware of bridge restricts to remoteCwd
77
78
  | `child_process.spawn` / `spawnSync` — runs in remote cwd via SSH | ✓ |
78
79
  | `fs.watch` / `fs.watchFile` — polls remote via HTTP (git branch updates) | ✓ |
79
80
 
81
+ `node`, `pi`, and `pii` spawns are always kept local — they need internet access and must never be redirected over SSH.
82
+
80
83
  ## Security
81
84
 
82
85
  | Layer | Protection |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-bridge",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Transparent filesystem bridge that makes pi run natively on a remote machine over SSH",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -47,7 +47,7 @@ function patchChildProcess(fakeRoot, remote) {
47
47
  */
48
48
  function isLocalOnly(file) {
49
49
  const name = normalizeCmd(file).toLowerCase();
50
- return name === 'node';
50
+ return name === 'node' || name === 'pi' || name === 'pii';
51
51
  }
52
52
 
53
53
  /**
@@ -4,6 +4,10 @@ const fs = require('fs');
4
4
  const os = require('os');
5
5
  const path = require('path');
6
6
 
7
+ // Capture rmSync before any monkey-patching so cleanup always hits the local
8
+ // filesystem rather than being redirected through the SSH bridge.
9
+ const origRmSync = fs.rmSync.bind(fs);
10
+
7
11
  /**
8
12
  * Create the fake local directory skeleton for the given remote path.
9
13
  * The structure mirrors the remote path so that path-mapper can convert
@@ -36,13 +40,14 @@ function createFakeDir(remoteCwd) {
36
40
 
37
41
  /**
38
42
  * Remove the fake root directory and all its contents.
39
- * Safe to call even if the directory does not exist.
43
+ * Uses the captured original rmSync to ensure the local directory is removed
44
+ * even when this is called after fs has been monkey-patched by the bridge.
40
45
  *
41
46
  * @param {string} fakeRoot - Path returned by createFakeDir
42
47
  */
43
48
  function removeFakeDir(fakeRoot) {
44
49
  try {
45
- fs.rmSync(fakeRoot, { recursive: true, force: true });
50
+ origRmSync(fakeRoot, { recursive: true, force: true });
46
51
  } catch (_) {
47
52
  // Best-effort removal — do not throw during cleanup
48
53
  }
@@ -192,10 +192,15 @@ function patchFs(fakeRoot, port, token) {
192
192
  if (process.platform === 'win32' && isBashPath(s)) return true;
193
193
  if (!s || !isFakePath(s, fakeRoot)) return orig.existsSync(p);
194
194
  try {
195
- return httpGet(port, token, '/exists?path=' + encodeURIComponent(rpath(s))).trim() === '1';
195
+ const remoteExists = httpGet(port, token, '/exists?path=' + encodeURIComponent(rpath(s))).trim() === '1';
196
+ // Also check locally: the fake dir root always exists on disk (pi-bridge
197
+ // creates it in preload). This lets pi's session-cwd check pass even when
198
+ // Node.js 24's ESM existsSync bypasses our patch and the remote check
199
+ // returns an unexpected result for the project root directory.
200
+ return remoteExists || orig.existsSync(p);
196
201
  } catch (e) {
197
202
  if (e.message && (e.message.includes('403') || e.message.includes('ENOENT'))) return false;
198
- throw e;
203
+ return orig.existsSync(p);
199
204
  }
200
205
  };
201
206