@portlens/cli 1.0.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.
@@ -0,0 +1,113 @@
1
+ import chalk from "chalk";
2
+ // ── Helpers ───────────────────────────────────────────────────────────────────
3
+ /** Strip ANSI escape codes to get the printable width of a string. */
4
+ function visibleLength(s) {
5
+ return s.replace(/\x1b\[[0-9;]*m/g, "").length;
6
+ }
7
+ function padRight(s, width) {
8
+ const extra = width - visibleLength(s);
9
+ return extra > 0 ? s + " ".repeat(extra) : s;
10
+ }
11
+ function formatExpiry(expiresAt) {
12
+ if (!expiresAt)
13
+ return "No expiry";
14
+ const ms = new Date(expiresAt).getTime() - Date.now();
15
+ if (ms <= 0)
16
+ return "Expired";
17
+ const totalSec = Math.floor(ms / 1000);
18
+ const hours = Math.floor(totalSec / 3600);
19
+ const mins = Math.floor((totalSec % 3600) / 60);
20
+ const secs = totalSec % 60;
21
+ if (hours > 0)
22
+ return `${hours}h ${String(mins).padStart(2, "0")}m`;
23
+ if (mins > 0)
24
+ return `${mins}m ${String(secs).padStart(2, "0")}s`;
25
+ return `${secs}s`;
26
+ }
27
+ // ── Status line ───────────────────────────────────────────────────────────────
28
+ function rttLabel(rtt) {
29
+ const text = `(${rtt}ms)`;
30
+ if (rtt > 2_000)
31
+ return chalk.red(text);
32
+ if (rtt > 500)
33
+ return chalk.yellow(text);
34
+ return chalk.greenBright(text);
35
+ }
36
+ function statusLine(opts) {
37
+ switch (opts.status) {
38
+ case "connected": {
39
+ const base = chalk.greenBright("● Connected");
40
+ return opts.rtt !== undefined
41
+ ? `${base} ${rttLabel(opts.rtt)}`
42
+ : base;
43
+ }
44
+ case "reconnecting": {
45
+ if (opts.reconnectInfo) {
46
+ const { delayMs, attempt, maxAttempts } = opts.reconnectInfo;
47
+ const secs = Math.floor(delayMs / 1000) || "<1";
48
+ return chalk.yellow(`◌ Reconnecting... (in ${secs}s, ${attempt + 1}/${maxAttempts})`);
49
+ }
50
+ return chalk.yellow("◌ Reconnecting...");
51
+ }
52
+ case "disconnected":
53
+ return chalk.red("○ Disconnected");
54
+ }
55
+ }
56
+ // ── Box renderer ──────────────────────────────────────────────────────────────
57
+ const LABEL_COL = 9; // length of "Share URL"
58
+ const LEFT_PAD = 2;
59
+ const RIGHT_PAD = 2;
60
+ function buildRows(opts) {
61
+ return [
62
+ { label: "Share URL", value: opts.shareUrl },
63
+ { label: "Local", value: `http://localhost:${opts.localPort}` },
64
+ { label: "Expires", value: formatExpiry(opts.expiresAt) },
65
+ { label: "Status", value: statusLine(opts) },
66
+ ];
67
+ }
68
+ /** Render the info box and return it as a string (ends with \n). */
69
+ export function renderBox(opts) {
70
+ const rows = buildRows(opts);
71
+ const title = chalk.white.bold("PortLens tunnel active");
72
+ const rowLines = rows.map(({ label, value }) => {
73
+ const lbl = chalk.dim(label.padEnd(LABEL_COL));
74
+ const val = label === "Share URL"
75
+ ? chalk.greenBright.bold(value)
76
+ : label === "Status"
77
+ ? value // already coloured by statusLine()
78
+ : chalk.white(value);
79
+ return `${lbl} ${val}`;
80
+ });
81
+ const allLines = [title, "", ...rowLines];
82
+ const contentWidth = Math.max(...allLines.map(visibleLength));
83
+ const innerWidth = LEFT_PAD + contentWidth + RIGHT_PAD;
84
+ const border = chalk.green;
85
+ const h = "─".repeat(innerWidth);
86
+ const out = [];
87
+ out.push(border(`╭${h}╮`));
88
+ for (const line of allLines) {
89
+ out.push(`${border("│")}${" ".repeat(LEFT_PAD)}${padRight(line, contentWidth)}${" ".repeat(RIGHT_PAD)}${border("│")}`);
90
+ }
91
+ out.push(border(`╰${h}╯`));
92
+ return out.join("\n") + "\n";
93
+ }
94
+ /** Number of terminal lines the box occupies (used for cursor repositioning). */
95
+ export function boxLineCount(_opts) {
96
+ // top border + title + blank + 4 rows + bottom border = 8
97
+ return 8;
98
+ }
99
+ /** Print the box for the first time. */
100
+ export function printBox(opts) {
101
+ process.stdout.write(renderBox(opts));
102
+ }
103
+ /**
104
+ * Overwrite the previously printed box in-place.
105
+ * Call this only when the box is the last thing printed to stdout
106
+ * (no other writes since the previous printBox / updateBox).
107
+ */
108
+ export function updateBox(opts) {
109
+ const lines = boxLineCount(opts);
110
+ process.stdout.write(`\x1b[${lines}A`); // cursor up
111
+ process.stdout.write(renderBox(opts));
112
+ }
113
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,iFAAiF;AAEjF,sEAAsE;AACtE,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;AACjD,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS,EAAE,KAAa;IACxC,MAAM,KAAK,GAAG,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,YAAY,CAAC,SAAwB;IAC5C,IAAI,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IACnC,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtD,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAO,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,MAAM,IAAI,GAAO,QAAQ,GAAG,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;IACpE,IAAI,IAAI,GAAI,CAAC;QAAE,OAAO,GAAG,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;IACnE,OAAO,GAAG,IAAI,GAAG,CAAC;AACpB,CAAC;AA+BD,iFAAiF;AAEjF,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;IAC1B,IAAI,GAAG,GAAG,KAAK;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,GAAK,GAAG;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,UAAU,CAAC,IAAgB;IAClC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC,GAAG,KAAK,SAAS;gBAC3B,CAAC,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBACjC,CAAC,CAAC,IAAI,CAAC;QACX,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;gBAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC;gBAChD,OAAO,KAAK,CAAC,MAAM,CACjB,yBAAyB,IAAI,MAAM,OAAO,GAAG,CAAC,IAAI,WAAW,GAAG,CACjE,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,cAAc;YACjB,OAAO,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,MAAM,SAAS,GAAI,CAAC,CAAC,CAAG,wBAAwB;AAChD,MAAM,QAAQ,GAAK,CAAC,CAAC;AACrB,MAAM,SAAS,GAAI,CAAC,CAAC;AAIrB,SAAS,SAAS,CAAC,IAAgB;IACjC,OAAO;QACL,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE;QAC5C,EAAE,KAAK,EAAE,OAAO,EAAM,KAAK,EAAE,oBAAoB,IAAI,CAAC,SAAS,EAAE,EAAE;QACnE,EAAE,KAAK,EAAE,SAAS,EAAI,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QAC3D,EAAE,KAAK,EAAE,QAAQ,EAAK,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE;KAChD,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,KAAK,GAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/C,MAAM,GAAG,GACP,KAAK,KAAK,WAAW;YACnB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YAC/B,CAAC,CAAC,KAAK,KAAK,QAAQ;gBACpB,CAAC,CAAC,KAAK,CAAa,mCAAmC;gBACvD,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,GAAG,GAAG,KAAK,GAAG,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAM,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAK,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAC;IAEzD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,MAAM,CAAC,GAAQ,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAEtC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CACN,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAC7G,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,0DAA0D;IAC1D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,QAAQ,CAAC,IAAgB;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAG,YAAY;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACxC,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":""}