devportal-tunnel 1.0.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.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # DevPortal Tunnel CLI
2
+
3
+ Expose your localhost to the internet with a single command.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g devportal
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Start a tunnel
14
+
15
+ ```bash
16
+ # Expose port 3000
17
+ devportal 3000
18
+
19
+ # With custom subdomain
20
+ devportal 3000 --subdomain my-api
21
+
22
+ # Password protected
23
+ devportal 3000 --password secret123
24
+
25
+ # Show QR code for mobile
26
+ devportal 3000 --qr
27
+
28
+ # Temporary demo link (expires in 2 hours)
29
+ devportal 3000 --demo
30
+ ```
31
+
32
+ ### List active tunnels
33
+
34
+ ```bash
35
+ devportal ls
36
+ ```
37
+
38
+ ### Stop a tunnel
39
+
40
+ ```bash
41
+ # Stop specific tunnel
42
+ devportal stop <tunnel-id>
43
+
44
+ # Stop all tunnels
45
+ devportal stop --all
46
+ ```
47
+
48
+ ### Replay requests
49
+
50
+ ```bash
51
+ # Replay a captured request
52
+ devportal replay <request-id>
53
+
54
+ # With modified headers
55
+ devportal replay <request-id> --header "X-Debug: true"
56
+
57
+ # With modified body
58
+ devportal replay <request-id> --body '{"test": true}'
59
+ ```
60
+
61
+ ### Stream logs
62
+
63
+ ```bash
64
+ devportal logs <tunnel-id>
65
+ ```
66
+
67
+ ### Device info
68
+
69
+ ```bash
70
+ devportal whoami
71
+ ```
72
+
73
+ ## Configuration
74
+
75
+ DevPortal stores configuration in `~/.devportal/`:
76
+
77
+ - `device.json` - Your unique device ID
78
+ - `tunnels.json` - Active tunnel information
79
+
80
+ ## Publishing to npm
81
+
82
+ 1. Create an npm account at https://www.npmjs.com
83
+ 2. Login: `npm login`
84
+ 3. Build: `npm run build`
85
+ 4. Publish: `npm publish`
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ # Install dependencies
91
+ npm install
92
+
93
+ # Run in development
94
+ npm run dev 3000
95
+
96
+ # Build
97
+ npm run build
98
+ ```
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,2 @@
1
+ export declare function listTunnels(): Promise<void>;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAmCjD"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listTunnels = listTunnels;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const tunnels_1 = require("../utils/tunnels");
9
+ async function listTunnels() {
10
+ const tunnels = (0, tunnels_1.getTunnels)().filter((t) => t.status === 'live');
11
+ if (tunnels.length === 0) {
12
+ console.log(chalk_1.default.yellow('No active tunnels'));
13
+ console.log(chalk_1.default.gray('Start one with: devportal <port>'));
14
+ return;
15
+ }
16
+ console.log(chalk_1.default.bold('Active Tunnels'));
17
+ console.log();
18
+ // Table header
19
+ const header = [
20
+ chalk_1.default.gray('ID'.padEnd(15)),
21
+ chalk_1.default.gray('Name'.padEnd(22)),
22
+ chalk_1.default.gray('Port'.padEnd(6)),
23
+ chalk_1.default.gray('URL'),
24
+ ].join(' ');
25
+ console.log(header);
26
+ console.log(chalk_1.default.gray('─'.repeat(80)));
27
+ // Table rows
28
+ for (const tunnel of tunnels) {
29
+ const row = [
30
+ chalk_1.default.white(tunnel.id.padEnd(15)),
31
+ chalk_1.default.cyan(tunnel.name.padEnd(22)),
32
+ chalk_1.default.white(tunnel.localPort.toString().padEnd(6)),
33
+ chalk_1.default.underline(tunnel.url),
34
+ ].join(' ');
35
+ console.log(row);
36
+ }
37
+ console.log();
38
+ console.log(chalk_1.default.gray(`${tunnels.length} tunnel(s) active`));
39
+ }
40
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":";;;;;AAGA,kCAmCC;AAtCD,kDAA0B;AAC1B,8CAA8C;AAEvC,KAAK,UAAU,WAAW;IAC/B,MAAM,OAAO,GAAG,IAAA,oBAAU,GAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,eAAe;IACf,MAAM,MAAM,GAAG;QACb,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7B,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5B,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC;KAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAExC,aAAa;IACb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG;YACV,eAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAClC,eAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAClD,eAAK,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;SAC5B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function showLogs(tunnelId: string): Promise<void>;
2
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAGA,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE9D"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.showLogs = showLogs;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const tunnels_1 = require("../utils/tunnels");
9
+ async function showLogs(tunnelId) {
10
+ const tunnel = (0, tunnels_1.getTunnel)(tunnelId);
11
+ if (!tunnel) {
12
+ console.log(chalk_1.default.red(`Tunnel not found: ${tunnelId}`));
13
+ return;
14
+ }
15
+ if (tunnel.status !== 'live') {
16
+ console.log(chalk_1.default.yellow(`Tunnel ${tunnel.name} is not active`));
17
+ return;
18
+ }
19
+ console.log(chalk_1.default.gray(`Streaming logs for ${tunnel.name}...`));
20
+ console.log(chalk_1.default.gray(`URL: ${tunnel.url}`));
21
+ console.log(chalk_1.default.gray('Press Ctrl+C to stop'));
22
+ console.log();
23
+ console.log(chalk_1.default.gray('─'.repeat(70)));
24
+ console.log();
25
+ // Simulate log streaming
26
+ const methods = ['GET', 'POST', 'PUT', 'DELETE'];
27
+ const paths = ['/api/users', '/api/auth', '/api/data', '/webhook', '/health'];
28
+ const statuses = [200, 200, 200, 201, 400, 401, 404];
29
+ const logEntry = () => {
30
+ const method = methods[Math.floor(Math.random() * methods.length)];
31
+ const path = paths[Math.floor(Math.random() * paths.length)];
32
+ const status = statuses[Math.floor(Math.random() * statuses.length)];
33
+ const duration = Math.floor(Math.random() * 200) + 20;
34
+ const ip = `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
35
+ const methodColor = {
36
+ GET: chalk_1.default.green,
37
+ POST: chalk_1.default.blue,
38
+ PUT: chalk_1.default.yellow,
39
+ DELETE: chalk_1.default.red,
40
+ }[method] || chalk_1.default.white;
41
+ const statusColor = status < 300 ? chalk_1.default.green : status < 400 ? chalk_1.default.yellow : chalk_1.default.red;
42
+ const timestamp = new Date().toISOString();
43
+ console.log(chalk_1.default.gray(timestamp), chalk_1.default.gray(ip.padEnd(15)), methodColor(method.padEnd(6)), chalk_1.default.white(path.padEnd(20)), statusColor(status.toString()), chalk_1.default.gray(`${duration}ms`));
44
+ const nextInterval = Math.floor(Math.random() * 5000) + 1000;
45
+ setTimeout(logEntry, nextInterval);
46
+ };
47
+ // Handle shutdown
48
+ process.on('SIGINT', () => {
49
+ console.log();
50
+ console.log(chalk_1.default.gray('Log streaming stopped'));
51
+ process.exit(0);
52
+ });
53
+ // Start logging
54
+ logEntry();
55
+ // Keep process alive
56
+ await new Promise(() => { });
57
+ }
58
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface ReplayOptions {
2
+ header?: string;
3
+ body?: string;
4
+ }
5
+ export declare function replayRequest(requestId: string, options: ReplayOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+C5F"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.replayRequest = replayRequest;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ async function replayRequest(requestId, options) {
10
+ const spinner = (0, ora_1.default)(`Replaying request ${requestId}...`).start();
11
+ // Simulate replay delay
12
+ await sleep(800);
13
+ // Mock request data
14
+ const mockRequest = {
15
+ id: requestId,
16
+ method: 'POST',
17
+ path: '/api/webhook',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'X-Webhook-Event': 'payment.completed',
21
+ },
22
+ body: { event: 'payment.completed', amount: 99.99 },
23
+ };
24
+ spinner.succeed(chalk_1.default.green('Request replayed'));
25
+ console.log();
26
+ // Display request info
27
+ console.log(chalk_1.default.gray('Request:'));
28
+ console.log(chalk_1.default.blue(` ${mockRequest.method}`), chalk_1.default.white(mockRequest.path));
29
+ console.log();
30
+ if (options.header) {
31
+ console.log(chalk_1.default.gray('Modified headers:'));
32
+ console.log(chalk_1.default.yellow(` ${options.header}`));
33
+ console.log();
34
+ }
35
+ if (options.body) {
36
+ console.log(chalk_1.default.gray('Modified body:'));
37
+ console.log(chalk_1.default.yellow(` ${options.body}`));
38
+ console.log();
39
+ }
40
+ // Simulate response
41
+ const status = 200;
42
+ const duration = Math.floor(Math.random() * 100) + 30;
43
+ console.log(chalk_1.default.gray('Response:'));
44
+ console.log(chalk_1.default.green(` ${status} OK`), chalk_1.default.gray(`(${duration}ms)`));
45
+ console.log();
46
+ console.log(chalk_1.default.gray('Body:'));
47
+ console.log(chalk_1.default.white(' { "success": true, "message": "Webhook processed" }'));
48
+ }
49
+ function sleep(ms) {
50
+ return new Promise((resolve) => setTimeout(resolve, ms));
51
+ }
52
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":";;;;;AAQA,sCA+CC;AAvDD,kDAA0B;AAC1B,8CAAsB;AAOf,KAAK,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAsB;IAC3E,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,qBAAqB,SAAS,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;IAEjE,wBAAwB;IACxB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAEjB,oBAAoB;IACpB,MAAM,WAAW,GAAG;QAClB,EAAE,EAAE,SAAS;QACb,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,iBAAiB,EAAE,mBAAmB;SACvC;QACD,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,KAAK,EAAE;KACpD,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,eAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,uBAAuB;IACvB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,eAAK,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAG,GAAG,CAAC;IACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,10 @@
1
+ interface StartOptions {
2
+ subdomain?: string;
3
+ password?: string;
4
+ demo?: boolean;
5
+ qr?: boolean;
6
+ authHeader?: string;
7
+ }
8
+ export declare function startTunnel(port: number, options: StartOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AASA,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EpF"}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.startTunnel = startTunnel;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const ora_1 = __importDefault(require("ora"));
42
+ const http = __importStar(require("http"));
43
+ const tunnels_1 = require("../utils/tunnels");
44
+ const device_1 = require("../utils/device");
45
+ // @ts-ignore - qrcode-terminal doesn't have types
46
+ const qrcode = __importStar(require("qrcode-terminal"));
47
+ async function startTunnel(port, options) {
48
+ const spinner = (0, ora_1.default)('Establishing tunnel...').start();
49
+ // Check if local server is running
50
+ const isPortOpen = await checkPort(port);
51
+ if (!isPortOpen) {
52
+ spinner.warn(chalk_1.default.yellow(`No server detected on port ${port}`));
53
+ console.log(chalk_1.default.gray(` Make sure your local server is running first`));
54
+ console.log(chalk_1.default.gray(` Example: npm run dev`));
55
+ console.log();
56
+ }
57
+ // Generate tunnel info
58
+ const name = options.subdomain || (0, tunnels_1.generateTunnelName)();
59
+ const tunnelId = `t-${Date.now().toString(36)}`;
60
+ const url = `https://${name}.devportal.live`;
61
+ // Simulate connection delay
62
+ await sleep(1500);
63
+ const tunnel = {
64
+ id: tunnelId,
65
+ name,
66
+ url,
67
+ localPort: port,
68
+ status: 'live',
69
+ createdAt: new Date().toISOString(),
70
+ pid: process.pid,
71
+ };
72
+ (0, tunnels_1.addTunnel)(tunnel);
73
+ spinner.succeed(chalk_1.default.green('Tunnel established'));
74
+ console.log();
75
+ // Display tunnel info
76
+ console.log(chalk_1.default.gray(' Local server: '), chalk_1.default.white(`http://localhost:${port}`));
77
+ console.log(chalk_1.default.gray(' Public URL: '), chalk_1.default.cyan.underline(url));
78
+ console.log(chalk_1.default.gray(' Tunnel ID: '), chalk_1.default.white(tunnelId));
79
+ if (options.password) {
80
+ console.log(chalk_1.default.gray(' Password: '), chalk_1.default.yellow('Protected'));
81
+ }
82
+ if (options.demo) {
83
+ console.log(chalk_1.default.gray(' Expires: '), chalk_1.default.yellow('2 hours'));
84
+ }
85
+ console.log();
86
+ console.log(chalk_1.default.gray(' Dashboard: '), chalk_1.default.underline(`https://devportal.live/dashboard/${(0, device_1.getDeviceId)()}`));
87
+ console.log();
88
+ // Show QR code if requested
89
+ if (options.qr) {
90
+ console.log(chalk_1.default.gray(' Scan to open on mobile:'));
91
+ console.log();
92
+ qrcode.generate(url, { small: true });
93
+ console.log();
94
+ }
95
+ // Start mock request logging
96
+ console.log(chalk_1.default.gray(' Waiting for requests... (Press Ctrl+C to stop)'));
97
+ console.log();
98
+ // Simulate incoming requests
99
+ simulateRequests();
100
+ // Handle shutdown
101
+ process.on('SIGINT', () => {
102
+ console.log();
103
+ console.log(chalk_1.default.yellow('Tunnel stopped'));
104
+ process.exit(0);
105
+ });
106
+ // Keep process alive
107
+ await new Promise(() => { });
108
+ }
109
+ async function checkPort(port) {
110
+ return new Promise((resolve) => {
111
+ const req = http.request({ host: 'localhost', port, timeout: 1000 }, () => {
112
+ resolve(true);
113
+ });
114
+ req.on('error', () => resolve(false));
115
+ req.on('timeout', () => resolve(false));
116
+ req.end();
117
+ });
118
+ }
119
+ function sleep(ms) {
120
+ return new Promise((resolve) => setTimeout(resolve, ms));
121
+ }
122
+ function simulateRequests() {
123
+ const methods = ['GET', 'POST', 'PUT', 'DELETE'];
124
+ const paths = ['/api/users', '/api/auth', '/api/data', '/webhook', '/health', '/api/items'];
125
+ const statuses = [200, 200, 200, 201, 400, 401, 404, 500];
126
+ const logRequest = () => {
127
+ const method = methods[Math.floor(Math.random() * methods.length)];
128
+ const path = paths[Math.floor(Math.random() * paths.length)];
129
+ const status = statuses[Math.floor(Math.random() * statuses.length)];
130
+ const duration = Math.floor(Math.random() * 200) + 20;
131
+ const methodColor = {
132
+ GET: chalk_1.default.green,
133
+ POST: chalk_1.default.blue,
134
+ PUT: chalk_1.default.yellow,
135
+ DELETE: chalk_1.default.red,
136
+ }[method] || chalk_1.default.white;
137
+ const statusColor = status < 300 ? chalk_1.default.green : status < 400 ? chalk_1.default.yellow : chalk_1.default.red;
138
+ const timestamp = new Date().toLocaleTimeString();
139
+ console.log(chalk_1.default.gray(timestamp), methodColor(method.padEnd(6)), chalk_1.default.white(path.padEnd(20)), statusColor(status.toString()), chalk_1.default.gray(`${duration}ms`));
140
+ // Schedule next request (random interval 2-8 seconds)
141
+ const nextInterval = Math.floor(Math.random() * 6000) + 2000;
142
+ setTimeout(logRequest, nextInterval);
143
+ };
144
+ // Start after initial delay
145
+ setTimeout(logRequest, 3000);
146
+ }
147
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,kCA4EC;AA7FD,kDAA0B;AAC1B,8CAAsB;AACtB,2CAA6B;AAC7B,8CAA6E;AAC7E,4CAA8C;AAE9C,kDAAkD;AAClD,wDAA0C;AAUnC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,OAAqB;IACnE,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,wBAAwB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEtD,mCAAmC;IACnC,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,eAAK,CAAC,MAAM,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,uBAAuB;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,IAAA,4BAAkB,GAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IAChD,MAAM,GAAG,GAAG,WAAW,IAAI,iBAAiB,CAAC;IAE7C,4BAA4B;IAC5B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAElB,MAAM,MAAM,GAAe;QACzB,EAAE,EAAE,QAAQ;QACZ,IAAI;QACJ,GAAG;QACH,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC;IAEF,IAAA,mBAAS,EAAC,MAAM,CAAC,CAAC;IAElB,OAAO,CAAC,OAAO,CAAC,eAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,sBAAsB;IACtB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEnE,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,eAAK,CAAC,SAAS,CAAC,oCAAoC,IAAA,oBAAW,GAAE,EAAE,CAAC,CAAC,CAAC;IAClH,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,4BAA4B;IAC5B,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,6BAA6B;IAC7B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,6BAA6B;IAC7B,gBAAgB,EAAE,CAAC;IAEnB,kBAAkB;IAClB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;QAEtD,MAAM,WAAW,GAAG;YAClB,GAAG,EAAE,eAAK,CAAC,KAAK;YAChB,IAAI,EAAE,eAAK,CAAC,IAAI;YAChB,GAAG,EAAE,eAAK,CAAC,MAAM;YACjB,MAAM,EAAE,eAAK,CAAC,GAAG;SAClB,CAAC,MAAM,CAAC,IAAI,eAAK,CAAC,KAAK,CAAC;QAEzB,MAAM,WAAW,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,eAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,eAAK,CAAC,MAAM,CAAC,CAAC,CAAC,eAAK,CAAC,GAAG,CAAC;QAEzF,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EACrB,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAC7B,eAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAC5B,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAC9B,eAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,CAC5B,CAAC;QAEF,sDAAsD;QACtD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC7D,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,4BAA4B;IAC5B,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface StopOptions {
2
+ all?: boolean;
3
+ }
4
+ export declare function stopTunnel(tunnelId: string | undefined, options: StopOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDlG"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.stopTunnel = stopTunnel;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const tunnels_1 = require("../utils/tunnels");
10
+ async function stopTunnel(tunnelId, options) {
11
+ const tunnels = (0, tunnels_1.getTunnels)();
12
+ const liveTunnels = tunnels.filter((t) => t.status === 'live');
13
+ if (liveTunnels.length === 0) {
14
+ console.log(chalk_1.default.yellow('No active tunnels to stop'));
15
+ return;
16
+ }
17
+ if (options.all) {
18
+ const spinner = (0, ora_1.default)('Stopping all tunnels...').start();
19
+ // Mark all as stopped
20
+ const updated = tunnels.map((t) => ({ ...t, status: 'stopped' }));
21
+ (0, tunnels_1.saveTunnels)(updated);
22
+ await sleep(500);
23
+ spinner.succeed(chalk_1.default.green(`Stopped ${liveTunnels.length} tunnel(s)`));
24
+ return;
25
+ }
26
+ if (!tunnelId) {
27
+ console.log(chalk_1.default.red('Please specify a tunnel ID or use --all'));
28
+ console.log(chalk_1.default.gray('Usage: devportal stop <tunnel-id>'));
29
+ console.log(chalk_1.default.gray(' devportal stop --all'));
30
+ console.log();
31
+ console.log(chalk_1.default.gray('Active tunnels:'));
32
+ for (const t of liveTunnels) {
33
+ console.log(chalk_1.default.gray(` ${t.id} (${t.name})`));
34
+ }
35
+ return;
36
+ }
37
+ // Find tunnel by ID or name
38
+ const tunnel = liveTunnels.find((t) => t.id === tunnelId || t.name === tunnelId);
39
+ if (!tunnel) {
40
+ console.log(chalk_1.default.red(`Tunnel not found: ${tunnelId}`));
41
+ console.log(chalk_1.default.gray('Active tunnels:'));
42
+ for (const t of liveTunnels) {
43
+ console.log(chalk_1.default.gray(` ${t.id} (${t.name})`));
44
+ }
45
+ return;
46
+ }
47
+ const spinner = (0, ora_1.default)(`Stopping tunnel ${tunnel.name}...`).start();
48
+ (0, tunnels_1.updateTunnel)(tunnel.id, { status: 'stopped' });
49
+ await sleep(500);
50
+ spinner.succeed(chalk_1.default.green(`Tunnel ${tunnel.name} stopped`));
51
+ }
52
+ function sleep(ms) {
53
+ return new Promise((resolve) => setTimeout(resolve, ms));
54
+ }
55
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":";;;;;AAQA,gCAmDC;AA3DD,kDAA0B;AAC1B,8CAAsB;AACtB,8CAAyE;AAMlE,KAAK,UAAU,UAAU,CAAC,QAA4B,EAAE,OAAoB;IACjF,MAAM,OAAO,GAAG,IAAA,oBAAU,GAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAE/D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,yBAAyB,CAAC,CAAC,KAAK,EAAE,CAAC;QAEvD,sBAAsB;QACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC,CAAC,CAAC;QAC3E,IAAA,qBAAW,EAAC,OAAO,CAAC,CAAC;QAErB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACjB,OAAO,CAAC,OAAO,CAAC,eAAK,CAAC,KAAK,CAAC,WAAW,WAAW,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO;IACT,CAAC;IAED,4BAA4B;IAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAEjF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,mBAAmB,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;IAEjE,IAAA,sBAAY,EAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAE/C,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO,CAAC,OAAO,CAAC,eAAK,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const start_1 = require("./commands/start");
10
+ const list_1 = require("./commands/list");
11
+ const stop_1 = require("./commands/stop");
12
+ const replay_1 = require("./commands/replay");
13
+ const logs_1 = require("./commands/logs");
14
+ const device_1 = require("./utils/device");
15
+ const program = new commander_1.Command();
16
+ // ASCII art logo
17
+ const logo = `
18
+ ${chalk_1.default.cyan('╔═══════════════════════════════════════╗')}
19
+ ${chalk_1.default.cyan('║')} ${chalk_1.default.bold.white('DevPortal')} - Share localhost instantly ${chalk_1.default.cyan('║')}
20
+ ${chalk_1.default.cyan('╚═══════════════════════════════════════╝')}
21
+ `;
22
+ program
23
+ .name('devportal')
24
+ .description('Expose your localhost to the internet with a single command')
25
+ .version('1.0.0')
26
+ .hook('preAction', () => {
27
+ console.log(logo);
28
+ });
29
+ // Main command: devportal <port>
30
+ program
31
+ .argument('[port]', 'Local port to expose', '3000')
32
+ .option('-s, --subdomain <name>', 'Custom subdomain for your URL')
33
+ .option('-p, --password <pass>', 'Password protect the tunnel')
34
+ .option('--demo', 'Create a temporary link that expires in 2 hours')
35
+ .option('--qr', 'Display QR code in terminal')
36
+ .option('--auth-header <header>', 'Add authorization header to requests')
37
+ .action(async (port, options) => {
38
+ if (port && !isNaN(parseInt(port))) {
39
+ await (0, start_1.startTunnel)(parseInt(port), options);
40
+ }
41
+ else {
42
+ program.help();
43
+ }
44
+ });
45
+ // List tunnels: devportal ls
46
+ program
47
+ .command('ls')
48
+ .alias('list')
49
+ .description('List all active tunnels')
50
+ .action(async () => {
51
+ await (0, list_1.listTunnels)();
52
+ });
53
+ // Stop tunnel: devportal stop <id>
54
+ program
55
+ .command('stop [tunnelId]')
56
+ .description('Stop a tunnel by ID')
57
+ .option('-a, --all', 'Stop all active tunnels')
58
+ .action(async (tunnelId, options) => {
59
+ await (0, stop_1.stopTunnel)(tunnelId, options);
60
+ });
61
+ // Replay request: devportal replay <requestId>
62
+ program
63
+ .command('replay <requestId>')
64
+ .description('Replay a captured request')
65
+ .option('-H, --header <header>', 'Add or override a header')
66
+ .option('-b, --body <body>', 'Override request body')
67
+ .action(async (requestId, options) => {
68
+ await (0, replay_1.replayRequest)(requestId, options);
69
+ });
70
+ // Stream logs: devportal logs <tunnelId>
71
+ program
72
+ .command('logs <tunnelId>')
73
+ .description('Stream live request logs from a tunnel')
74
+ .action(async (tunnelId) => {
75
+ await (0, logs_1.showLogs)(tunnelId);
76
+ });
77
+ // Device info command
78
+ program
79
+ .command('whoami')
80
+ .description('Show current device ID')
81
+ .action(() => {
82
+ const deviceId = (0, device_1.getDeviceId)();
83
+ console.log(chalk_1.default.gray('Device ID:'), chalk_1.default.cyan(deviceId));
84
+ console.log(chalk_1.default.gray('Dashboard:'), chalk_1.default.underline(`https://devportal.live/dashboard/${deviceId}`));
85
+ });
86
+ program.parse();
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function getDeviceId(): string;
2
+ export declare function getConfigDir(): string;
3
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAaA,wBAAgB,WAAW,IAAI,MAAM,CAwBpC;AAQD,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getDeviceId = getDeviceId;
37
+ exports.getConfigDir = getConfigDir;
38
+ const fs = __importStar(require("fs"));
39
+ const os = __importStar(require("os"));
40
+ const path = __importStar(require("path"));
41
+ const crypto = __importStar(require("crypto"));
42
+ const CONFIG_DIR = path.join(os.homedir(), '.devportal');
43
+ const DEVICE_FILE = path.join(CONFIG_DIR, 'device.json');
44
+ function getDeviceId() {
45
+ ensureConfigDir();
46
+ if (fs.existsSync(DEVICE_FILE)) {
47
+ try {
48
+ const config = JSON.parse(fs.readFileSync(DEVICE_FILE, 'utf-8'));
49
+ return config.deviceId;
50
+ }
51
+ catch {
52
+ // Corrupted file, regenerate
53
+ }
54
+ }
55
+ // Generate new device ID
56
+ const timestamp = Date.now().toString(36);
57
+ const random = crypto.randomBytes(4).toString('hex');
58
+ const deviceId = `dev_${timestamp}_${random}`;
59
+ const config = {
60
+ deviceId,
61
+ createdAt: new Date().toISOString(),
62
+ };
63
+ fs.writeFileSync(DEVICE_FILE, JSON.stringify(config, null, 2));
64
+ return deviceId;
65
+ }
66
+ function ensureConfigDir() {
67
+ if (!fs.existsSync(CONFIG_DIR)) {
68
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
69
+ }
70
+ }
71
+ function getConfigDir() {
72
+ ensureConfigDir();
73
+ return CONFIG_DIR;
74
+ }
75
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,kCAwBC;AAQD,oCAGC;AAhDD,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAiC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACzD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAOzD,SAAgB,WAAW;IACzB,eAAe,EAAE,CAAC;IAElB,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAiB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/E,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,CAAC;IAE9C,MAAM,MAAM,GAAiB;QAC3B,QAAQ;QACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,eAAe;IACtB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAgB,YAAY;IAC1B,eAAe,EAAE,CAAC;IAClB,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface TunnelInfo {
2
+ id: string;
3
+ name: string;
4
+ url: string;
5
+ localPort: number;
6
+ status: 'live' | 'stopped';
7
+ createdAt: string;
8
+ pid?: number;
9
+ }
10
+ export declare function getTunnels(): TunnelInfo[];
11
+ export declare function saveTunnels(tunnels: TunnelInfo[]): void;
12
+ export declare function addTunnel(tunnel: TunnelInfo): void;
13
+ export declare function removeTunnel(id: string): void;
14
+ export declare function updateTunnel(id: string, updates: Partial<TunnelInfo>): void;
15
+ export declare function getTunnel(id: string): TunnelInfo | undefined;
16
+ export declare function generateTunnelName(): string;
17
+ //# sourceMappingURL=tunnels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnels.d.ts","sourceRoot":"","sources":["../../src/utils/tunnels.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,wBAAgB,UAAU,IAAI,UAAU,EAAE,CASzC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAEvD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAIlD;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAG7C;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAK3E;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE5D;AAMD,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getTunnels = getTunnels;
37
+ exports.saveTunnels = saveTunnels;
38
+ exports.addTunnel = addTunnel;
39
+ exports.removeTunnel = removeTunnel;
40
+ exports.updateTunnel = updateTunnel;
41
+ exports.getTunnel = getTunnel;
42
+ exports.generateTunnelName = generateTunnelName;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const device_1 = require("./device");
46
+ const TUNNELS_FILE = path.join((0, device_1.getConfigDir)(), 'tunnels.json');
47
+ function getTunnels() {
48
+ if (!fs.existsSync(TUNNELS_FILE)) {
49
+ return [];
50
+ }
51
+ try {
52
+ return JSON.parse(fs.readFileSync(TUNNELS_FILE, 'utf-8'));
53
+ }
54
+ catch {
55
+ return [];
56
+ }
57
+ }
58
+ function saveTunnels(tunnels) {
59
+ fs.writeFileSync(TUNNELS_FILE, JSON.stringify(tunnels, null, 2));
60
+ }
61
+ function addTunnel(tunnel) {
62
+ const tunnels = getTunnels();
63
+ tunnels.push(tunnel);
64
+ saveTunnels(tunnels);
65
+ }
66
+ function removeTunnel(id) {
67
+ const tunnels = getTunnels().filter((t) => t.id !== id);
68
+ saveTunnels(tunnels);
69
+ }
70
+ function updateTunnel(id, updates) {
71
+ const tunnels = getTunnels().map((t) => t.id === id ? { ...t, ...updates } : t);
72
+ saveTunnels(tunnels);
73
+ }
74
+ function getTunnel(id) {
75
+ return getTunnels().find((t) => t.id === id || t.name === id);
76
+ }
77
+ // Generate random tunnel name
78
+ const adjectives = ['purple', 'cosmic', 'hidden', 'crystal', 'silent', 'golden', 'frozen', 'blazing', 'lunar', 'neon'];
79
+ const nouns = ['horizon', 'lake', 'forest', 'ocean', 'canyon', 'river', 'meadow', 'summit', 'valley', 'storm'];
80
+ function generateTunnelName() {
81
+ const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
82
+ const noun = nouns[Math.floor(Math.random() * nouns.length)];
83
+ const num = Math.floor(Math.random() * 900) + 100;
84
+ return `${adj}-${noun}-${num}`;
85
+ }
86
+ //# sourceMappingURL=tunnels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnels.js","sourceRoot":"","sources":["../../src/utils/tunnels.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "devportal-tunnel",
3
+ "version": "1.0.0",
4
+ "description": "Expose your localhost to the internet with a single command",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "devportal-tunnel": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "ts-node src/index.ts",
12
+ "start": "node dist/index.js",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "tunnel",
17
+ "localhost",
18
+ "ngrok",
19
+ "dev",
20
+ "webhook",
21
+ "api",
22
+ "debugging"
23
+ ],
24
+ "author": "",
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "chalk": "^4.1.2",
28
+ "commander": "^11.1.0",
29
+ "ora": "^5.4.1",
30
+ "qrcode-terminal": "^0.12.0",
31
+ "ws": "^8.16.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.10.0",
35
+ "@types/ws": "^8.5.10",
36
+ "ts-node": "^10.9.2",
37
+ "typescript": "^5.3.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=16.0.0"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": ""
45
+ },
46
+ "files": [
47
+ "dist"
48
+ ]
49
+ }