private-connect 0.3.1 → 0.3.3
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 +52 -25
- package/dist/index.d.ts +2 -2
- package/dist/index.js +284 -11
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,50 +1,78 @@
|
|
|
1
1
|
# private-connect
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Zero-friction connectivity tools. No signup required.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
# Test connectivity to any service
|
|
9
|
+
npx private-connect test db.internal:5432
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# Create a temporary public tunnel
|
|
12
|
+
npx private-connect tunnel 3000
|
|
13
|
+
```
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
# Test database connectivity
|
|
15
|
-
npx private-connect test db.internal:5432
|
|
15
|
+
## Commands
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
npx private-connect test redis:6379
|
|
17
|
+
### `test` - Test connectivity
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
npx private-connect test
|
|
19
|
+
```bash
|
|
20
|
+
npx private-connect test <target>
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
**Examples:**
|
|
24
|
+
```bash
|
|
25
|
+
npx private-connect test db.internal:5432 # Database
|
|
26
|
+
npx private-connect test redis:6379 # Redis
|
|
27
|
+
npx private-connect test https://api.internal # API
|
|
28
|
+
```
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
**What it checks:**
|
|
27
31
|
- TCP connection
|
|
28
|
-
- Port accessibility
|
|
29
32
|
- TLS/SSL (if applicable)
|
|
30
|
-
-
|
|
33
|
+
- HTTP response (for web services)
|
|
34
|
+
- Latency
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
### `tunnel` - Create a temporary tunnel
|
|
33
37
|
|
|
38
|
+
```bash
|
|
39
|
+
npx private-connect tunnel <port>
|
|
34
40
|
```
|
|
35
|
-
Testing db.internal:5432...
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
✓ TCP connection (45ms)
|
|
39
|
-
✓ Port open
|
|
40
|
-
✓ PostgreSQL detected
|
|
42
|
+
Instantly expose a local service to the internet. No signup required.
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
**Examples:**
|
|
45
|
+
```bash
|
|
46
|
+
npx private-connect tunnel 3000 # Expose localhost:3000
|
|
47
|
+
npx private-connect tunnel localhost:8080 # Specify host and port
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Output:**
|
|
51
|
+
```
|
|
52
|
+
Private Connect - Temporary Tunnel
|
|
53
|
+
────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
Local: localhost:3000
|
|
56
|
+
Public: https://api.privateconnect.co/t/abc123
|
|
57
|
+
Expires: 120 minutes
|
|
58
|
+
|
|
59
|
+
────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
Press Ctrl+C to stop
|
|
62
|
+
|
|
63
|
+
[12:00:01] GET /api/users
|
|
64
|
+
[12:00:02] POST /api/login
|
|
43
65
|
```
|
|
44
66
|
|
|
67
|
+
**Features:**
|
|
68
|
+
- No signup or account required
|
|
69
|
+
- Auto-expires in 2 hours
|
|
70
|
+
- Real-time request logging
|
|
71
|
+
- Works with any HTTP service
|
|
72
|
+
|
|
45
73
|
## Need more?
|
|
46
74
|
|
|
47
|
-
For
|
|
75
|
+
For permanent tunnels, sharing with teammates, and AI agent integration:
|
|
48
76
|
|
|
49
77
|
```bash
|
|
50
78
|
curl -fsSL https://privateconnect.co/install.sh | bash
|
|
@@ -52,4 +80,3 @@ connect up
|
|
|
52
80
|
```
|
|
53
81
|
|
|
54
82
|
→ [privateconnect.co](https://privateconnect.co)
|
|
55
|
-
|
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Private Connect CLI
|
|
4
4
|
*
|
|
5
|
-
* Zero-friction connectivity testing. No signup required.
|
|
5
|
+
* Zero-friction connectivity testing and temporary tunnels. No signup required.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* npx private-connect test vault.internal:8200
|
|
9
|
-
* npx private-connect
|
|
9
|
+
* npx private-connect tunnel 3000
|
|
10
10
|
*/
|
|
11
11
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Private Connect CLI
|
|
5
5
|
*
|
|
6
|
-
* Zero-friction connectivity testing. No signup required.
|
|
6
|
+
* Zero-friction connectivity testing and temporary tunnels. No signup required.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
9
|
* npx private-connect test vault.internal:8200
|
|
10
|
-
* npx private-connect
|
|
10
|
+
* npx private-connect tunnel 3000
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
const net = require("net");
|
|
@@ -15,6 +15,8 @@ const tls = require("tls");
|
|
|
15
15
|
const https = require("https");
|
|
16
16
|
const http = require("http");
|
|
17
17
|
const url_1 = require("url");
|
|
18
|
+
const crypto_1 = require("crypto");
|
|
19
|
+
const socket_io_client_1 = require("socket.io-client");
|
|
18
20
|
// Colors (no dependencies)
|
|
19
21
|
const c = {
|
|
20
22
|
reset: '\x1b[0m',
|
|
@@ -220,27 +222,288 @@ function printCta(success) {
|
|
|
220
222
|
}
|
|
221
223
|
function printHelp() {
|
|
222
224
|
console.log(`
|
|
223
|
-
${c.bold}Private Connect${c.reset} -
|
|
225
|
+
${c.bold}Private Connect${c.reset} - Zero-friction connectivity tools
|
|
224
226
|
|
|
225
|
-
${c.bold}
|
|
226
|
-
|
|
227
|
+
${c.bold}Commands:${c.reset}
|
|
228
|
+
test <target> Test connectivity to any service
|
|
229
|
+
tunnel <port> Create a temporary public tunnel
|
|
227
230
|
|
|
228
231
|
${c.bold}Examples:${c.reset}
|
|
229
232
|
npx private-connect test vault.internal:8200
|
|
230
233
|
npx private-connect test https://api.example.com
|
|
231
|
-
npx private-connect
|
|
234
|
+
npx private-connect tunnel 3000
|
|
235
|
+
npx private-connect tunnel localhost:8080
|
|
232
236
|
|
|
233
|
-
${c.bold}
|
|
237
|
+
${c.bold}Tunnel:${c.reset}
|
|
238
|
+
• No signup required
|
|
239
|
+
• Auto-expires in 2 hours
|
|
240
|
+
• Get a public URL instantly
|
|
241
|
+
|
|
242
|
+
${c.bold}Test:${c.reset}
|
|
234
243
|
• TCP reachability
|
|
235
244
|
• TLS validation
|
|
236
|
-
• HTTP response
|
|
245
|
+
• HTTP response
|
|
237
246
|
• Latency
|
|
238
247
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
${c.dim}For full features: https://privateconnect.co${c.reset}
|
|
248
|
+
${c.dim}For permanent tunnels: https://privateconnect.co${c.reset}
|
|
242
249
|
`);
|
|
243
250
|
}
|
|
251
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
252
|
+
// Temporary Tunnel
|
|
253
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
254
|
+
const HUB_URL = process.env.CONNECT_HUB_URL || 'https://api.privateconnect.co';
|
|
255
|
+
const TUNNEL_DOMAIN = process.env.CONNECT_TUNNEL_DOMAIN || 'tunnel.privateconnect.co';
|
|
256
|
+
async function createTemporaryTunnel(options) {
|
|
257
|
+
const { host, port, ttl = 120 } = options;
|
|
258
|
+
console.log();
|
|
259
|
+
console.log(`${c.bold}Private Connect${c.reset} - Temporary Tunnel`);
|
|
260
|
+
console.log(`${c.gray}────────────────────────────────────${c.reset}`);
|
|
261
|
+
console.log();
|
|
262
|
+
// Check if local service is running
|
|
263
|
+
process.stdout.write(` Checking ${c.cyan}${host}:${port}${c.reset}... `);
|
|
264
|
+
const localCheck = await testTcp(host, port, 2000);
|
|
265
|
+
if (!localCheck.ok) {
|
|
266
|
+
console.log(`${fail}`);
|
|
267
|
+
console.log();
|
|
268
|
+
console.log(` ${c.red}Cannot connect to ${host}:${port}${c.reset}`);
|
|
269
|
+
console.log(` ${c.gray}Make sure your service is running${c.reset}`);
|
|
270
|
+
console.log();
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
console.log(`${ok}`);
|
|
274
|
+
// Generate a temporary tunnel ID
|
|
275
|
+
const tunnelId = (0, crypto_1.randomBytes)(6).toString('hex');
|
|
276
|
+
const publicUrl = `https://${tunnelId}.${TUNNEL_DOMAIN}`;
|
|
277
|
+
// Request tunnel from hub
|
|
278
|
+
process.stdout.write(` Requesting tunnel... `);
|
|
279
|
+
try {
|
|
280
|
+
const response = await httpRequest(`${HUB_URL}/v1/tunnels/temporary`, {
|
|
281
|
+
method: 'POST',
|
|
282
|
+
headers: { 'Content-Type': 'application/json' },
|
|
283
|
+
body: JSON.stringify({
|
|
284
|
+
tunnelId,
|
|
285
|
+
localHost: host,
|
|
286
|
+
localPort: port,
|
|
287
|
+
ttlMinutes: ttl,
|
|
288
|
+
}),
|
|
289
|
+
});
|
|
290
|
+
if (!response.ok) {
|
|
291
|
+
console.log(`${fail}`);
|
|
292
|
+
console.log();
|
|
293
|
+
if (response.status === 503 || response.status === 404 || response.status === 501) {
|
|
294
|
+
console.log(` ${c.yellow}Temporary tunnels coming soon!${c.reset}`);
|
|
295
|
+
console.log();
|
|
296
|
+
console.log(` For now, use the full CLI:`);
|
|
297
|
+
console.log(` ${c.cyan}curl -fsSL https://privateconnect.co/install.sh | bash${c.reset}`);
|
|
298
|
+
console.log(` ${c.cyan}connect up && connect localhost:${port} --share${c.reset}`);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
console.log(` ${c.red}Failed to create tunnel: ${response.status}${c.reset}`);
|
|
302
|
+
}
|
|
303
|
+
console.log();
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
console.log(`${ok}`);
|
|
307
|
+
console.log();
|
|
308
|
+
console.log(`${c.gray}────────────────────────────────────${c.reset}`);
|
|
309
|
+
console.log();
|
|
310
|
+
const data = JSON.parse(response.body);
|
|
311
|
+
// For local dev, adjust the WS URL
|
|
312
|
+
let wsUrl = data.tunnel.wsUrl;
|
|
313
|
+
if (HUB_URL.includes('localhost')) {
|
|
314
|
+
wsUrl = HUB_URL.replace('http', 'ws') + '/temp-tunnel';
|
|
315
|
+
}
|
|
316
|
+
console.log();
|
|
317
|
+
console.log(`${c.gray}────────────────────────────────────${c.reset}`);
|
|
318
|
+
console.log();
|
|
319
|
+
console.log(` ${c.bold}Local:${c.reset} ${c.cyan}${host}:${port}${c.reset}`);
|
|
320
|
+
console.log(` ${c.bold}Public:${c.reset} ${c.green}${data.tunnel.publicUrl}${c.reset}`);
|
|
321
|
+
console.log(` ${c.bold}Expires:${c.reset} ${data.tunnel.ttlMinutes} minutes`);
|
|
322
|
+
console.log();
|
|
323
|
+
console.log(`${c.gray}────────────────────────────────────${c.reset}`);
|
|
324
|
+
console.log();
|
|
325
|
+
console.log(` ${c.dim}Press Ctrl+C to stop${c.reset}`);
|
|
326
|
+
console.log();
|
|
327
|
+
// Keep connection alive and handle incoming requests
|
|
328
|
+
await runTunnelProxy(data.tunnel.tunnelId, wsUrl, host, port);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
console.log(`${fail}`);
|
|
332
|
+
console.log();
|
|
333
|
+
if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') {
|
|
334
|
+
console.log(` ${c.yellow}Temporary tunnels coming soon!${c.reset}`);
|
|
335
|
+
console.log();
|
|
336
|
+
console.log(` For now, use the full CLI:`);
|
|
337
|
+
console.log(` ${c.cyan}curl -fsSL https://privateconnect.co/install.sh | bash${c.reset}`);
|
|
338
|
+
console.log(` ${c.cyan}connect up && connect localhost:${port} --share${c.reset}`);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
console.log(` ${c.red}Error: ${err.message}${c.reset}`);
|
|
342
|
+
}
|
|
343
|
+
console.log();
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Simple HTTP request helper (no dependencies)
|
|
348
|
+
function httpRequest(url, options) {
|
|
349
|
+
return new Promise((resolve, reject) => {
|
|
350
|
+
const parsedUrl = new url_1.URL(url);
|
|
351
|
+
const client = parsedUrl.protocol === 'https:' ? https : http;
|
|
352
|
+
const req = client.request(url, {
|
|
353
|
+
method: options.method || 'GET',
|
|
354
|
+
headers: options.headers,
|
|
355
|
+
}, (res) => {
|
|
356
|
+
let body = '';
|
|
357
|
+
res.on('data', chunk => body += chunk);
|
|
358
|
+
res.on('end', () => {
|
|
359
|
+
resolve({
|
|
360
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
361
|
+
status: res.statusCode,
|
|
362
|
+
body,
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
req.on('error', reject);
|
|
367
|
+
req.on('timeout', () => reject(new Error('Request timeout')));
|
|
368
|
+
if (options.body) {
|
|
369
|
+
req.write(options.body);
|
|
370
|
+
}
|
|
371
|
+
req.end();
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Connect to hub via WebSocket and forward HTTP requests to local service
|
|
376
|
+
*/
|
|
377
|
+
async function runTunnelProxy(tunnelId, wsUrl, localHost, localPort) {
|
|
378
|
+
return new Promise((resolve) => {
|
|
379
|
+
// Extract base URL and namespace
|
|
380
|
+
const url = new url_1.URL(wsUrl.replace('ws://', 'http://').replace('wss://', 'https://'));
|
|
381
|
+
const baseUrl = `${url.protocol}//${url.host}`;
|
|
382
|
+
const namespace = url.pathname || '/temp-tunnel';
|
|
383
|
+
const socket = (0, socket_io_client_1.io)(`${baseUrl}${namespace}`, {
|
|
384
|
+
transports: ['websocket'],
|
|
385
|
+
reconnection: true,
|
|
386
|
+
reconnectionAttempts: 10,
|
|
387
|
+
reconnectionDelay: 1000,
|
|
388
|
+
});
|
|
389
|
+
let requestCount = 0;
|
|
390
|
+
socket.on('connect', () => {
|
|
391
|
+
// Register this tunnel
|
|
392
|
+
socket.emit('register', { tunnelId }, (response) => {
|
|
393
|
+
if (!response.success) {
|
|
394
|
+
console.log(` ${c.red}Failed to register: ${response.error}${c.reset}`);
|
|
395
|
+
socket.disconnect();
|
|
396
|
+
resolve();
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
socket.on('disconnect', (reason) => {
|
|
401
|
+
if (reason === 'io server disconnect') {
|
|
402
|
+
console.log(` ${c.yellow}Tunnel expired or closed by server${c.reset}`);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
socket.on('tunnel_expired', () => {
|
|
406
|
+
console.log();
|
|
407
|
+
console.log(` ${c.yellow}Tunnel expired${c.reset}`);
|
|
408
|
+
console.log();
|
|
409
|
+
socket.disconnect();
|
|
410
|
+
resolve();
|
|
411
|
+
});
|
|
412
|
+
socket.on('connect_error', (err) => {
|
|
413
|
+
console.log(` ${c.red}Connection error: ${err.message}${c.reset}`);
|
|
414
|
+
});
|
|
415
|
+
// Handle incoming HTTP requests from the hub
|
|
416
|
+
socket.on('http_request', async (data) => {
|
|
417
|
+
requestCount++;
|
|
418
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
419
|
+
console.log(` ${c.gray}[${timestamp}]${c.reset} ${c.cyan}${data.method}${c.reset} ${data.path}`);
|
|
420
|
+
try {
|
|
421
|
+
// Forward request to local service
|
|
422
|
+
const response = await forwardToLocal(localHost, localPort, data);
|
|
423
|
+
// Send response back to hub
|
|
424
|
+
socket.emit('http_response', {
|
|
425
|
+
requestId: data.requestId,
|
|
426
|
+
status: response.status,
|
|
427
|
+
headers: response.headers,
|
|
428
|
+
body: response.body,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
catch (err) {
|
|
432
|
+
// Send error response
|
|
433
|
+
socket.emit('http_response', {
|
|
434
|
+
requestId: data.requestId,
|
|
435
|
+
status: 502,
|
|
436
|
+
headers: { 'content-type': 'application/json' },
|
|
437
|
+
body: JSON.stringify({ error: 'Bad Gateway', message: err.message }),
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
// Handle shutdown
|
|
442
|
+
process.on('SIGINT', () => {
|
|
443
|
+
console.log();
|
|
444
|
+
console.log(` ${c.yellow}Tunnel closed${c.reset}`);
|
|
445
|
+
console.log(` ${c.gray}Handled ${requestCount} requests${c.reset}`);
|
|
446
|
+
console.log();
|
|
447
|
+
socket.disconnect();
|
|
448
|
+
resolve();
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Forward an HTTP request to the local service
|
|
454
|
+
*/
|
|
455
|
+
function forwardToLocal(host, port, request) {
|
|
456
|
+
return new Promise((resolve, reject) => {
|
|
457
|
+
const options = {
|
|
458
|
+
hostname: host,
|
|
459
|
+
port: port,
|
|
460
|
+
path: request.path,
|
|
461
|
+
method: request.method,
|
|
462
|
+
headers: { ...request.headers, host: `${host}:${port}` },
|
|
463
|
+
timeout: 30000,
|
|
464
|
+
};
|
|
465
|
+
const req = http.request(options, (res) => {
|
|
466
|
+
const chunks = [];
|
|
467
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
468
|
+
res.on('end', () => {
|
|
469
|
+
const body = Buffer.concat(chunks).toString('utf-8');
|
|
470
|
+
const headers = {};
|
|
471
|
+
for (const [key, value] of Object.entries(res.headers)) {
|
|
472
|
+
if (typeof value === 'string') {
|
|
473
|
+
headers[key] = value;
|
|
474
|
+
}
|
|
475
|
+
else if (Array.isArray(value)) {
|
|
476
|
+
headers[key] = value.join(', ');
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
resolve({
|
|
480
|
+
status: res.statusCode || 500,
|
|
481
|
+
headers,
|
|
482
|
+
body,
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
req.on('error', reject);
|
|
487
|
+
req.on('timeout', () => reject(new Error('Request timeout')));
|
|
488
|
+
if (request.body) {
|
|
489
|
+
req.write(request.body);
|
|
490
|
+
}
|
|
491
|
+
req.end();
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
function parseTunnelTarget(target) {
|
|
495
|
+
// Handle just port number
|
|
496
|
+
if (/^\d+$/.test(target)) {
|
|
497
|
+
return { host: 'localhost', port: parseInt(target, 10) };
|
|
498
|
+
}
|
|
499
|
+
// Handle host:port
|
|
500
|
+
const parts = target.split(':');
|
|
501
|
+
if (parts.length === 2) {
|
|
502
|
+
return { host: parts[0], port: parseInt(parts[1], 10) };
|
|
503
|
+
}
|
|
504
|
+
// Default to localhost with provided port
|
|
505
|
+
return { host: 'localhost', port: parseInt(target, 10) || 3000 };
|
|
506
|
+
}
|
|
244
507
|
// Main
|
|
245
508
|
const args = process.argv.slice(2);
|
|
246
509
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
@@ -255,6 +518,16 @@ if (args[0] === 'test') {
|
|
|
255
518
|
}
|
|
256
519
|
runTest(args[1]).catch(console.error);
|
|
257
520
|
}
|
|
521
|
+
else if (args[0] === 'tunnel') {
|
|
522
|
+
if (!args[1]) {
|
|
523
|
+
console.error(`${c.red}Error: Port required${c.reset}`);
|
|
524
|
+
console.error(`Usage: npx private-connect tunnel <port>`);
|
|
525
|
+
console.error(` npx private-connect tunnel localhost:3000`);
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
528
|
+
const { host, port } = parseTunnelTarget(args[1]);
|
|
529
|
+
createTemporaryTunnel({ host, port }).catch(console.error);
|
|
530
|
+
}
|
|
258
531
|
else {
|
|
259
532
|
// Default to test if just a target is provided
|
|
260
533
|
runTest(args[0]).catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "private-connect",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Test connectivity to any service. No signup required.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"private-connect": "./dist/index.js"
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
"url": "https://github.com/treadiehq/private-connect.git",
|
|
27
27
|
"directory": "packages/cli"
|
|
28
28
|
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"socket.io-client": "^4.7.0"
|
|
31
|
+
},
|
|
29
32
|
"devDependencies": {
|
|
30
33
|
"@types/node": "^20.0.0",
|
|
31
34
|
"typescript": "^5.0.0"
|