@volter/tunnel 1.1.1 → 1.2.0

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.
@@ -73,10 +73,26 @@ interface TunnelRequest {
73
73
  body: string | null;
74
74
  }
75
75
 
76
+ interface RateWindow {
77
+ limit: number;
78
+ remaining: number;
79
+ reset: number;
80
+ }
81
+
76
82
  interface TunnelRegistered {
77
83
  type: 'registered';
78
84
  tunnelId: string;
79
85
  url: string;
86
+ /** Metering snapshot for this account (present when the relay meters usage). */
87
+ account?: { slug: string; day: RateWindow; month: RateWindow; level: 'ok' | 'warn' | 'exceeded' };
88
+ }
89
+
90
+ /** Pushed by the relay when the account's usage level changes (ok→warn→exceeded). */
91
+ interface TunnelQuota {
92
+ type: 'quota';
93
+ level: 'ok' | 'warn' | 'exceeded';
94
+ day: RateWindow;
95
+ month: RateWindow;
80
96
  }
81
97
 
82
98
  interface TunnelWsUpgrade {
@@ -117,7 +133,8 @@ type TunnelMessage =
117
133
  | TunnelWsMessage
118
134
  | TunnelWsClose
119
135
  | TunnelRequestAbort
120
- | TunnelError;
136
+ | TunnelError
137
+ | TunnelQuota;
121
138
 
122
139
  // ============================================================================
123
140
  // Safe WebSocket close helpers
@@ -392,8 +409,13 @@ export function createTunnel({
392
409
  port,
393
410
  tunnelId: msg.tunnelId,
394
411
  url: msg.url,
412
+ account: msg.account?.slug,
413
+ dayRemaining: msg.account?.day.remaining,
414
+ dayLimit: msg.account?.day.limit,
395
415
  },
396
- `Tunnel registered: localhost:${port} → ${msg.url}`
416
+ msg.account
417
+ ? `Tunnel registered: localhost:${port} → ${msg.url} (${msg.account.slug}: ${msg.account.day.remaining}/${msg.account.day.limit} credits today)`
418
+ : `Tunnel registered: localhost:${port} → ${msg.url}`
397
419
  );
398
420
  onRegistered({
399
421
  url: msg.url,
@@ -411,6 +433,21 @@ export function createTunnel({
411
433
  });
412
434
  }
413
435
 
436
+ if (msg.type === 'quota') {
437
+ const line = `Tunnel quota ${msg.level}: ${msg.day.remaining}/${msg.day.limit} credits remaining today`;
438
+ const ctx = {
439
+ component: 'tunnel_client',
440
+ action: 'quota',
441
+ level: msg.level,
442
+ dayRemaining: msg.day.remaining,
443
+ dayLimit: msg.day.limit,
444
+ monthRemaining: msg.month.remaining,
445
+ };
446
+ if (msg.level === 'ok') log.info(ctx, line);
447
+ else log.warn(ctx, line);
448
+ return;
449
+ }
450
+
414
451
  if (msg.type === 'request') {
415
452
  const localReq = forwardRequest(port, localHost, msg, ws, activeRequests, async (err) => {
416
453
  // On ECONNREFUSED, re-resolve loopback and retry once
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/tunnel",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Volter tunnel — WebSocket-based HTTP/WS reverse tunnel: a relay server plus a client connector library and CLI.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",