@vincentt-xr/cli 0.1.1 → 0.1.2
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/dist/preview/runner.d.ts +8 -3
- package/dist/preview/runner.js +22 -7
- package/package.json +1 -1
package/dist/preview/runner.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ export interface StartPreviewOptions {
|
|
|
16
16
|
/** stdio for the app dev serve. "ignore" (default) keeps an MCP server's stdout
|
|
17
17
|
* clean; a CLI can pass "inherit" to surface build output. */
|
|
18
18
|
appStdio?: "ignore" | "inherit";
|
|
19
|
-
/** How long to wait for cloudflared to register before giving up (default
|
|
19
|
+
/** How long to wait for cloudflared to register before giving up (default 90s).
|
|
20
|
+
* Generous because on a network that blocks the QUIC edge, cloudflared spends
|
|
21
|
+
* ~20-30s failing QUIC before it falls back to the http2 edge, which does work. */
|
|
20
22
|
registerTimeoutMs?: number;
|
|
21
23
|
/** How long to wait for the app to serve before returning anyway (default 8s).
|
|
22
24
|
* Kept short so an MCP tool call stays within strict clients' ~30s timeout;
|
|
@@ -40,6 +42,9 @@ export interface RunningPreview {
|
|
|
40
42
|
export declare function startPreview(opts: StartPreviewOptions): Promise<RunningPreview>;
|
|
41
43
|
/**
|
|
42
44
|
* Resolve once cloudflared reports a live edge connection, reject if it exits
|
|
43
|
-
* first or never registers.
|
|
45
|
+
* first or never registers. On failure the rejection carries cloudflared's own
|
|
46
|
+
* recent output — otherwise "did not register" hides the real cause (an invalid
|
|
47
|
+
* run token, or a network that blocks the QUIC edge, the two common culprits).
|
|
48
|
+
* `onLine` streams each log line out live. Exported for unit testing.
|
|
44
49
|
*/
|
|
45
|
-
export declare function waitForRegister(tunnel: ChildProcess, timeoutMs: number): Promise<void>;
|
|
50
|
+
export declare function waitForRegister(tunnel: ChildProcess, timeoutMs: number, onLine?: (line: string) => void): Promise<void>;
|
package/dist/preview/runner.js
CHANGED
|
@@ -16,7 +16,7 @@ import { startSessionTunnel } from "./tunnel.js";
|
|
|
16
16
|
import { proxyWeb, proxyWs } from "./proxy.js";
|
|
17
17
|
import { getFreePort, isPortListening, waitForApp } from "./net.js";
|
|
18
18
|
export async function startPreview(opts) {
|
|
19
|
-
const { projectCwd, harnessPath = "/__harness", devCommand = ["npm", "run", "dev"], appStdio = "ignore", registerTimeoutMs =
|
|
19
|
+
const { projectCwd, harnessPath = "/__harness", devCommand = ["npm", "run", "dev"], appStdio = "ignore", registerTimeoutMs = 90_000, appReadyTimeoutMs = 8_000, onLog = () => undefined, } = opts;
|
|
20
20
|
// Resolve ports. The app port defaults to 5173; the relay + front ports are
|
|
21
21
|
// harness-internal, so auto-pick free ones (the relay port is returned for the
|
|
22
22
|
// MCP diag_* tools to point at) instead of colliding on fixed defaults.
|
|
@@ -70,7 +70,7 @@ export async function startPreview(opts) {
|
|
|
70
70
|
tunnel = spawn(cloudflaredBin, ["tunnel", "run", "--token", session.runToken], {
|
|
71
71
|
stdio: ["ignore", "pipe", "pipe"],
|
|
72
72
|
});
|
|
73
|
-
await waitForRegister(tunnel, registerTimeoutMs);
|
|
73
|
+
await waitForRegister(tunnel, registerTimeoutMs, (line) => onLog(`[cloudflared] ${line}`));
|
|
74
74
|
// Don't hand back a live URL that serves a blank page: wait for the app to
|
|
75
75
|
// actually respond. Non-fatal — a slow build still returns, flagged not-ready.
|
|
76
76
|
const appReady = reuseApp ? true : await waitForApp(appPort, appReadyTimeoutMs);
|
|
@@ -86,11 +86,15 @@ export async function startPreview(opts) {
|
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
88
|
* Resolve once cloudflared reports a live edge connection, reject if it exits
|
|
89
|
-
* first or never registers.
|
|
89
|
+
* first or never registers. On failure the rejection carries cloudflared's own
|
|
90
|
+
* recent output — otherwise "did not register" hides the real cause (an invalid
|
|
91
|
+
* run token, or a network that blocks the QUIC edge, the two common culprits).
|
|
92
|
+
* `onLine` streams each log line out live. Exported for unit testing.
|
|
90
93
|
*/
|
|
91
|
-
export function waitForRegister(tunnel, timeoutMs) {
|
|
94
|
+
export function waitForRegister(tunnel, timeoutMs, onLine) {
|
|
92
95
|
return new Promise((resolve, reject) => {
|
|
93
96
|
let settled = false;
|
|
97
|
+
const recent = [];
|
|
94
98
|
const finish = (fn) => {
|
|
95
99
|
if (settled)
|
|
96
100
|
return;
|
|
@@ -98,14 +102,25 @@ export function waitForRegister(tunnel, timeoutMs) {
|
|
|
98
102
|
clearTimeout(timer);
|
|
99
103
|
fn();
|
|
100
104
|
};
|
|
105
|
+
const tail = () => {
|
|
106
|
+
const lines = recent.slice(-15).join("\n").trim();
|
|
107
|
+
return lines ? `\ncloudflared output:\n${lines}` : "";
|
|
108
|
+
};
|
|
101
109
|
const scan = (buf) => {
|
|
102
|
-
|
|
110
|
+
const text = String(buf);
|
|
111
|
+
for (const line of text.split(/\r?\n/)) {
|
|
112
|
+
if (!line.trim())
|
|
113
|
+
continue;
|
|
114
|
+
recent.push(line);
|
|
115
|
+
onLine?.(line);
|
|
116
|
+
}
|
|
117
|
+
if (/Registered tunnel connection|Connection [^ ]+ registered/.test(text)) {
|
|
103
118
|
finish(resolve);
|
|
104
119
|
}
|
|
105
120
|
};
|
|
106
121
|
tunnel.stdout?.on("data", scan);
|
|
107
122
|
tunnel.stderr?.on("data", scan);
|
|
108
|
-
tunnel.on("exit", (code) => finish(() => reject(new Error(`cloudflared exited before registering (code ${code})
|
|
109
|
-
const timer = setTimeout(() => finish(() => reject(new Error(`cloudflared did not register within ${timeoutMs}ms
|
|
123
|
+
tunnel.on("exit", (code) => finish(() => reject(new Error(`cloudflared exited before registering (code ${code}).${tail()}`))));
|
|
124
|
+
const timer = setTimeout(() => finish(() => reject(new Error(`cloudflared did not register within ${timeoutMs}ms.${tail()}`))), timeoutMs);
|
|
110
125
|
});
|
|
111
126
|
}
|
package/package.json
CHANGED