pubblue 0.4.7 → 0.4.11

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.
@@ -1,4 +1,4 @@
1
- // src/lib/bridge-protocol.ts
1
+ // ../shared/bridge-protocol-core.ts
2
2
  var CONTROL_CHANNEL = "_control";
3
3
  var CHANNELS = {
4
4
  CHAT: "chat",
@@ -34,7 +34,11 @@ var TunnelApiClient = class {
34
34
  if (!res.ok) {
35
35
  if (res.status === 429) {
36
36
  const retrySuffix = retryAfterSeconds !== void 0 ? ` Retry after ${retryAfterSeconds}s.` : "";
37
- throw new TunnelApiError(`Rate limit exceeded.${retrySuffix}`, res.status, retryAfterSeconds);
37
+ throw new TunnelApiError(
38
+ `Rate limit exceeded.${retrySuffix}`,
39
+ res.status,
40
+ retryAfterSeconds
41
+ );
38
42
  }
39
43
  throw new TunnelApiError(data.error || `Request failed: ${res.status}`, res.status);
40
44
  }
@@ -6,21 +6,54 @@ import {
6
6
  makeAckMessage,
7
7
  parseAckMessage,
8
8
  shouldAcknowledgeMessage
9
- } from "./chunk-MW35LBNH.js";
9
+ } from "./chunk-4YTJ2WKF.js";
10
10
 
11
11
  // src/lib/tunnel-daemon.ts
12
12
  import * as fs from "fs";
13
13
  import * as net from "net";
14
14
  import * as path from "path";
15
15
 
16
- // src/lib/ack-routing.ts
16
+ // ../shared/ack-routing-core.ts
17
17
  function resolveAckChannel(input) {
18
18
  if (input.messageChannelOpen) return input.messageChannel;
19
19
  if (input.controlChannelOpen) return CONTROL_CHANNEL;
20
20
  return null;
21
21
  }
22
22
 
23
- // src/lib/tunnel-daemon.ts
23
+ // src/lib/tunnel-daemon-offer.ts
24
+ function generateOffer(peer, timeoutMs) {
25
+ return new Promise((resolve, reject) => {
26
+ let resolved = false;
27
+ const done = (sdp, type) => {
28
+ if (resolved) return;
29
+ resolved = true;
30
+ clearTimeout(timeout);
31
+ resolve(JSON.stringify({ sdp, type }));
32
+ };
33
+ peer.onLocalDescription((sdp, type) => {
34
+ done(sdp, type);
35
+ });
36
+ peer.onGatheringStateChange((state) => {
37
+ if (state === "complete" && !resolved) {
38
+ const desc = peer.localDescription();
39
+ if (desc) done(desc.sdp, desc.type);
40
+ }
41
+ });
42
+ const timeout = setTimeout(() => {
43
+ if (resolved) return;
44
+ const desc = peer.localDescription();
45
+ if (desc) {
46
+ done(desc.sdp, desc.type);
47
+ } else {
48
+ resolved = true;
49
+ reject(new Error(`Timed out after ${timeoutMs}ms`));
50
+ }
51
+ }, timeoutMs);
52
+ peer.setLocalDescription();
53
+ });
54
+ }
55
+
56
+ // src/lib/tunnel-daemon-shared.ts
24
57
  var OFFER_TIMEOUT_MS = 1e4;
25
58
  var SIGNAL_POLL_WAITING_MS = 500;
26
59
  var SIGNAL_POLL_CONNECTED_MS = 2e3;
@@ -36,8 +69,10 @@ function shouldRecoverForBrowserAnswerChange(params) {
36
69
  if (!incomingBrowserAnswer) return false;
37
70
  return incomingBrowserAnswer !== lastAppliedBrowserAnswer;
38
71
  }
72
+
73
+ // src/lib/tunnel-daemon.ts
39
74
  async function startDaemon(config) {
40
- const { tunnelId, apiClient, socketPath, infoPath } = config;
75
+ const { tunnelId, apiClient, socketPath, infoPath, cliVersion } = config;
41
76
  const ndc = await import("node-datachannel");
42
77
  const buffer = { messages: [] };
43
78
  const startTime = Date.now();
@@ -497,7 +532,7 @@ async function startDaemon(config) {
497
532
  if (!fs.existsSync(infoDir)) fs.mkdirSync(infoDir, { recursive: true });
498
533
  fs.writeFileSync(
499
534
  infoPath,
500
- JSON.stringify({ pid: process.pid, tunnelId, socketPath, startedAt: startTime })
535
+ JSON.stringify({ pid: process.pid, tunnelId, socketPath, startedAt: startTime, cliVersion })
501
536
  );
502
537
  scheduleNextPoll(0);
503
538
  async function cleanup() {
@@ -617,37 +652,6 @@ async function startDaemon(config) {
617
652
  }
618
653
  }
619
654
  }
620
- function generateOffer(peer, timeoutMs) {
621
- return new Promise((resolve, reject) => {
622
- let resolved = false;
623
- const done = (sdp, type) => {
624
- if (resolved) return;
625
- resolved = true;
626
- clearTimeout(timeout);
627
- resolve(JSON.stringify({ sdp, type }));
628
- };
629
- peer.onLocalDescription((sdp, type) => {
630
- done(sdp, type);
631
- });
632
- peer.onGatheringStateChange((state) => {
633
- if (state === "complete" && !resolved) {
634
- const desc = peer.localDescription();
635
- if (desc) done(desc.sdp, desc.type);
636
- }
637
- });
638
- const timeout = setTimeout(() => {
639
- if (resolved) return;
640
- const desc = peer.localDescription();
641
- if (desc) {
642
- done(desc.sdp, desc.type);
643
- } else {
644
- resolved = true;
645
- reject(new Error(`Timed out after ${timeoutMs}ms`));
646
- }
647
- }, timeoutMs);
648
- peer.setLocalDescription();
649
- });
650
- }
651
655
 
652
656
  export {
653
657
  getTunnelWriteReadinessError,
@@ -0,0 +1,56 @@
1
+ // src/lib/tunnel-ipc.ts
2
+ import * as net from "net";
3
+ function getSocketPath(tunnelId) {
4
+ return `/tmp/pubblue-${tunnelId}.sock`;
5
+ }
6
+ async function ipcCall(socketPath, request) {
7
+ return new Promise((resolve, reject) => {
8
+ let settled = false;
9
+ let timeoutId = null;
10
+ const finish = (fn) => {
11
+ if (settled) return;
12
+ settled = true;
13
+ if (timeoutId) clearTimeout(timeoutId);
14
+ fn();
15
+ };
16
+ const client = net.createConnection(socketPath, () => {
17
+ client.write(`${JSON.stringify(request)}
18
+ `);
19
+ });
20
+ let data = "";
21
+ client.on("data", (chunk) => {
22
+ data += chunk.toString();
23
+ const newlineIdx = data.indexOf("\n");
24
+ if (newlineIdx !== -1) {
25
+ const line = data.slice(0, newlineIdx);
26
+ client.end();
27
+ try {
28
+ finish(() => resolve(JSON.parse(line)));
29
+ } catch {
30
+ finish(() => reject(new Error("Invalid response from daemon")));
31
+ }
32
+ }
33
+ });
34
+ client.on("error", (err) => {
35
+ if (err.code === "ECONNREFUSED" || err.code === "ENOENT") {
36
+ finish(() => reject(new Error("Daemon not running. Is the tunnel still active?")));
37
+ } else {
38
+ finish(() => reject(err));
39
+ }
40
+ });
41
+ client.on("end", () => {
42
+ if (!data.includes("\n")) {
43
+ finish(() => reject(new Error("Daemon closed connection unexpectedly")));
44
+ }
45
+ });
46
+ timeoutId = setTimeout(() => {
47
+ client.destroy();
48
+ finish(() => reject(new Error("Daemon request timed out")));
49
+ }, 1e4);
50
+ });
51
+ }
52
+
53
+ export {
54
+ getSocketPath,
55
+ ipcCall
56
+ };