pubblue 0.4.10 → 0.4.12

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",
@@ -1,3 +1,6 @@
1
+ import {
2
+ TunnelApiError
3
+ } from "./chunk-7NFHPJ76.js";
1
4
  import {
2
5
  CHANNELS,
3
6
  CONTROL_CHANNEL,
@@ -6,24 +9,58 @@ import {
6
9
  makeAckMessage,
7
10
  parseAckMessage,
8
11
  shouldAcknowledgeMessage
9
- } from "./chunk-MW35LBNH.js";
12
+ } from "./chunk-4YTJ2WKF.js";
10
13
 
11
14
  // src/lib/tunnel-daemon.ts
12
15
  import * as fs from "fs";
13
16
  import * as net from "net";
14
17
  import * as path from "path";
15
18
 
16
- // src/lib/ack-routing.ts
19
+ // ../shared/ack-routing-core.ts
17
20
  function resolveAckChannel(input) {
18
21
  if (input.messageChannelOpen) return input.messageChannel;
19
22
  if (input.controlChannelOpen) return CONTROL_CHANNEL;
20
23
  return null;
21
24
  }
22
25
 
23
- // src/lib/tunnel-daemon.ts
26
+ // src/lib/tunnel-daemon-offer.ts
27
+ function generateOffer(peer, timeoutMs) {
28
+ return new Promise((resolve, reject) => {
29
+ let resolved = false;
30
+ const done = (sdp, type) => {
31
+ if (resolved) return;
32
+ resolved = true;
33
+ clearTimeout(timeout);
34
+ resolve(JSON.stringify({ sdp, type }));
35
+ };
36
+ peer.onLocalDescription((sdp, type) => {
37
+ done(sdp, type);
38
+ });
39
+ peer.onGatheringStateChange((state) => {
40
+ if (state === "complete" && !resolved) {
41
+ const desc = peer.localDescription();
42
+ if (desc) done(desc.sdp, desc.type);
43
+ }
44
+ });
45
+ const timeout = setTimeout(() => {
46
+ if (resolved) return;
47
+ const desc = peer.localDescription();
48
+ if (desc) {
49
+ done(desc.sdp, desc.type);
50
+ } else {
51
+ resolved = true;
52
+ reject(new Error(`Timed out after ${timeoutMs}ms`));
53
+ }
54
+ }, timeoutMs);
55
+ peer.setLocalDescription();
56
+ });
57
+ }
58
+
59
+ // src/lib/tunnel-daemon-shared.ts
24
60
  var OFFER_TIMEOUT_MS = 1e4;
25
- var SIGNAL_POLL_WAITING_MS = 500;
26
- var SIGNAL_POLL_CONNECTED_MS = 2e3;
61
+ var SIGNAL_POLL_WAITING_MS = 5e3;
62
+ var SIGNAL_POLL_CONNECTED_MS = 15e3;
63
+ var LOCAL_CANDIDATE_FLUSH_MS = 2e3;
27
64
  var RECOVERY_DELAY_MS = 1e3;
28
65
  var WRITE_ACK_TIMEOUT_MS = 5e3;
29
66
  var NOT_CONNECTED_WRITE_ERROR = "No browser connected. Ask the user to open the tunnel URL first, then retry.";
@@ -36,8 +73,18 @@ function shouldRecoverForBrowserAnswerChange(params) {
36
73
  if (!incomingBrowserAnswer) return false;
37
74
  return incomingBrowserAnswer !== lastAppliedBrowserAnswer;
38
75
  }
76
+ function getSignalPollDelayMs(params) {
77
+ const baseDelay = params.remoteDescriptionApplied ? SIGNAL_POLL_CONNECTED_MS : SIGNAL_POLL_WAITING_MS;
78
+ if (params.retryAfterSeconds === void 0) return baseDelay;
79
+ if (!Number.isFinite(params.retryAfterSeconds) || params.retryAfterSeconds <= 0) {
80
+ return baseDelay;
81
+ }
82
+ return Math.max(baseDelay, Math.ceil(params.retryAfterSeconds * 1e3));
83
+ }
84
+
85
+ // src/lib/tunnel-daemon.ts
39
86
  async function startDaemon(config) {
40
- const { tunnelId, apiClient, socketPath, infoPath } = config;
87
+ const { tunnelId, apiClient, socketPath, infoPath, cliVersion } = config;
41
88
  const ndc = await import("node-datachannel");
42
89
  const buffer = { messages: [] };
43
90
  const startTime = Date.now();
@@ -286,7 +333,7 @@ async function startDaemon(config) {
286
333
  await apiClient.signal(tunnelId, { candidates: newOnes }).catch((error) => {
287
334
  debugLog("failed to publish local ICE candidates", error);
288
335
  });
289
- }, 500);
336
+ }, LOCAL_CANDIDATE_FLUSH_MS);
290
337
  localCandidateStopTimer = setTimeout(() => {
291
338
  clearLocalCandidateTimers();
292
339
  }, 3e4);
@@ -406,12 +453,16 @@ async function startDaemon(config) {
406
453
  }
407
454
  async function runPollingLoop() {
408
455
  if (stopped) return;
456
+ let retryAfterSeconds;
409
457
  try {
410
458
  await pollSignalingOnce();
411
459
  } catch (error) {
460
+ if (error instanceof TunnelApiError && error.status === 429) {
461
+ retryAfterSeconds = error.retryAfterSeconds;
462
+ }
412
463
  markError("signaling poll failed", error);
413
464
  }
414
- scheduleNextPoll(remoteDescriptionApplied ? SIGNAL_POLL_CONNECTED_MS : SIGNAL_POLL_WAITING_MS);
465
+ scheduleNextPoll(getSignalPollDelayMs({ remoteDescriptionApplied, retryAfterSeconds }));
415
466
  }
416
467
  async function runNegotiationCycle() {
417
468
  if (!peer) throw new Error("PeerConnection not initialized");
@@ -497,7 +548,7 @@ async function startDaemon(config) {
497
548
  if (!fs.existsSync(infoDir)) fs.mkdirSync(infoDir, { recursive: true });
498
549
  fs.writeFileSync(
499
550
  infoPath,
500
- JSON.stringify({ pid: process.pid, tunnelId, socketPath, startedAt: startTime })
551
+ JSON.stringify({ pid: process.pid, tunnelId, socketPath, startedAt: startTime, cliVersion })
501
552
  );
502
553
  scheduleNextPoll(0);
503
554
  async function cleanup() {
@@ -617,40 +668,10 @@ async function startDaemon(config) {
617
668
  }
618
669
  }
619
670
  }
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
671
 
652
672
  export {
653
673
  getTunnelWriteReadinessError,
654
674
  shouldRecoverForBrowserAnswerChange,
675
+ getSignalPollDelayMs,
655
676
  startDaemon
656
677
  };