@odeva/cli 0.0.8 → 0.0.9

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.
@@ -67,9 +67,7 @@ class AppDev extends Command {
67
67
  }
68
68
  });
69
69
  await this.verifyLocalDevServer(port, server, api, registered);
70
- this.log(ui.dim("Starting Cloudflare tunnel..."));
71
- const tunnel = await startQuickTunnel(port);
72
- this.log(ui.ok(`Tunnel ready at ${ui.code(tunnel.url)}`));
70
+ const tunnel = await this.startReachableTunnel(port, server);
73
71
  registered = await this.registerDevWebhooks(api, loaded, tunnel.url);
74
72
  this.log("");
75
73
  this.log(`${ui.bold("Tunnel:")} ${tunnel.url}`);
@@ -78,7 +76,6 @@ class AppDev extends Command {
78
76
  this.log(` ${ui.dim("\u2192")} ${reg.config.topic.padEnd(28)} ${reg.fullUrl}`);
79
77
  }
80
78
  this.log("");
81
- await this.verifyDevServerReachable(tunnel, port, server, api, registered);
82
79
  const syncedUrls = await this.syncDevAppUrls(api, loaded, tunnel.url);
83
80
  this.printDevAppInfo(syncedUrls);
84
81
  await this.ensureDevAppInstalled(api, loaded, tunnel, port, server, registered);
@@ -244,6 +241,34 @@ class AppDev extends Command {
244
241
  throw err;
245
242
  }
246
243
  }
244
+ async startReachableTunnel(port, server) {
245
+ let lastError;
246
+ for (let attempt = 1; attempt <= 3; attempt += 1) {
247
+ this.log(ui.dim(`Starting Cloudflare tunnel${attempt > 1 ? ` (attempt ${attempt}/3)` : ""}...`));
248
+ const tunnel = await startQuickTunnel(port);
249
+ this.log(ui.ok(`Tunnel ready at ${ui.code(tunnel.url)}`));
250
+ this.log(ui.dim("Waiting 20s for trycloudflare DNS to propagate before first probe..."));
251
+ await new Promise((resolve) => setTimeout(resolve, 2e4));
252
+ this.log(ui.dim("Verifying dev server and tunnel... (trycloudflare can take up to 60s to propagate)"));
253
+ try {
254
+ const result = await waitForDevServerReachable({
255
+ localPort: port,
256
+ tunnelUrl: tunnel.url
257
+ });
258
+ this.log(ui.ok(`Tunnel verified via ${ui.code(result.path)} (HTTP ${result.tunnelStatus})`));
259
+ return tunnel;
260
+ } catch (err) {
261
+ lastError = err;
262
+ await tunnel.stop();
263
+ if (attempt < 3) {
264
+ const message = err instanceof Error ? err.message : String(err);
265
+ this.log(ui.warn(`Tunnel ${attempt}/3 was not reachable: ${message}`));
266
+ }
267
+ }
268
+ }
269
+ await server.stop();
270
+ throw lastError instanceof Error ? lastError : new CliError(String(lastError));
271
+ }
247
272
  async verifyDevServerReachable(tunnel, port, server, api, registered) {
248
273
  this.log(ui.dim("Verifying dev server and tunnel... (trycloudflare can take up to 60s to propagate)"));
249
274
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odeva/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Build apps on the Odeva booking platform — scaffold, develop, deploy.",
5
5
  "license": "MIT",
6
6
  "type": "module",