episoda 0.2.47 → 0.2.49

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.
@@ -2559,17 +2559,27 @@ var require_auth = __commonJS({
2559
2559
  }
2560
2560
  async function loadConfig7(configPath) {
2561
2561
  const fullPath = getConfigPath(configPath);
2562
- if (!fs18.existsSync(fullPath)) {
2563
- return null;
2562
+ if (fs18.existsSync(fullPath)) {
2563
+ try {
2564
+ const content = fs18.readFileSync(fullPath, "utf8");
2565
+ const config = JSON.parse(content);
2566
+ return config;
2567
+ } catch (error) {
2568
+ console.error("Error loading config:", error);
2569
+ }
2564
2570
  }
2565
- try {
2566
- const content = fs18.readFileSync(fullPath, "utf8");
2567
- const config = JSON.parse(content);
2568
- return config;
2569
- } catch (error) {
2570
- console.error("Error loading config:", error);
2571
- return null;
2571
+ if (process.env.EPISODA_ACCESS_TOKEN) {
2572
+ return {
2573
+ access_token: process.env.EPISODA_ACCESS_TOKEN,
2574
+ api_url: process.env.EPISODA_API_URL || "https://episoda.dev",
2575
+ project_id: process.env.EPISODA_PROJECT_ID || "",
2576
+ user_id: process.env.EPISODA_USER_ID || "",
2577
+ workspace_id: process.env.EPISODA_WORKSPACE_ID || "",
2578
+ workspace_slug: process.env.EPISODA_WORKSPACE,
2579
+ project_slug: process.env.EPISODA_PROJECT
2580
+ };
2572
2581
  }
2582
+ return null;
2573
2583
  }
2574
2584
  async function saveConfig2(config, configPath) {
2575
2585
  const fullPath = getConfigPath(configPath);
@@ -2693,7 +2703,7 @@ var require_package = __commonJS({
2693
2703
  "package.json"(exports2, module2) {
2694
2704
  module2.exports = {
2695
2705
  name: "episoda",
2696
- version: "0.2.47",
2706
+ version: "0.2.49",
2697
2707
  description: "CLI tool for Episoda local development workflow orchestration",
2698
2708
  main: "dist/index.js",
2699
2709
  types: "dist/index.d.ts",
@@ -2702,6 +2712,7 @@ var require_package = __commonJS({
2702
2712
  },
2703
2713
  scripts: {
2704
2714
  build: "tsup",
2715
+ "build:standalone": "tsup --config tsup.standalone.config.ts",
2705
2716
  dev: "tsup --watch",
2706
2717
  clean: "rm -rf dist",
2707
2718
  typecheck: "tsc --noEmit"
@@ -7510,9 +7521,7 @@ var Daemon = class _Daemon {
7510
7521
  // EP833: Track consecutive health check failures per tunnel
7511
7522
  this.tunnelHealthFailures = /* @__PURE__ */ new Map();
7512
7523
  // 3 second timeout for health checks
7513
- // EP911: Track last reported health status to avoid unnecessary DB writes
7514
- this.lastReportedHealthStatus = /* @__PURE__ */ new Map();
7515
- // moduleUid -> status
7524
+ // EP1020: lastReportedHealthStatus removed - health columns dropped from database
7516
7525
  // EP837: Prevent concurrent commit syncs (backpressure guard)
7517
7526
  this.commitSyncInProgress = false;
7518
7527
  // EP843: Per-module mutex for tunnel operations
@@ -7744,7 +7753,6 @@ var Daemon = class _Daemon {
7744
7753
  await tunnelManager.stopTunnel(moduleUid);
7745
7754
  await stopDevServer(moduleUid);
7746
7755
  await clearTunnelUrl(moduleUid);
7747
- this.lastReportedHealthStatus.delete(moduleUid);
7748
7756
  this.tunnelHealthFailures.delete(moduleUid);
7749
7757
  console.log(`[Daemon] EP823: Tunnel stopped for ${moduleUid}`);
7750
7758
  return { success: true };
@@ -9061,7 +9069,6 @@ var Daemon = class _Daemon {
9061
9069
  const isHealthy = await this.checkTunnelHealth(tunnel);
9062
9070
  if (isHealthy) {
9063
9071
  this.tunnelHealthFailures.delete(tunnel.moduleUid);
9064
- await this.reportTunnelHealth(tunnel.moduleUid, "healthy", config);
9065
9072
  } else {
9066
9073
  const failures = (this.tunnelHealthFailures.get(tunnel.moduleUid) || 0) + 1;
9067
9074
  this.tunnelHealthFailures.set(tunnel.moduleUid, failures);
@@ -9072,7 +9079,6 @@ var Daemon = class _Daemon {
9072
9079
  await this.restartTunnel(tunnel.moduleUid, tunnel.port);
9073
9080
  });
9074
9081
  this.tunnelHealthFailures.delete(tunnel.moduleUid);
9075
- await this.reportTunnelHealth(tunnel.moduleUid, "unhealthy", config);
9076
9082
  }
9077
9083
  }
9078
9084
  }
@@ -9166,33 +9172,8 @@ var Daemon = class _Daemon {
9166
9172
  console.error(`[Daemon] EP833: Error restarting preview for ${moduleUid}:`, error);
9167
9173
  }
9168
9174
  }
9169
- /**
9170
- * EP833: Report tunnel health status to the API
9171
- * EP904: Use fetchWithAuth for token refresh
9172
- * EP911: Only report when status CHANGES to reduce DB writes
9173
- */
9174
- async reportTunnelHealth(moduleUid, healthStatus, config) {
9175
- if (!config.access_token) {
9176
- return;
9177
- }
9178
- const lastStatus = this.lastReportedHealthStatus.get(moduleUid);
9179
- if (lastStatus === healthStatus) {
9180
- return;
9181
- }
9182
- const apiUrl = config.api_url || "https://episoda.dev";
9183
- try {
9184
- await fetchWithAuth(`${apiUrl}/api/modules/${moduleUid}/health`, {
9185
- method: "PATCH",
9186
- body: JSON.stringify({
9187
- tunnel_health_status: healthStatus,
9188
- tunnel_last_health_check: (/* @__PURE__ */ new Date()).toISOString()
9189
- })
9190
- });
9191
- this.lastReportedHealthStatus.set(moduleUid, healthStatus);
9192
- } catch (error) {
9193
- console.warn(`[Daemon] EP833: Failed to report health for ${moduleUid}:`, error instanceof Error ? error.message : error);
9194
- }
9195
- }
9175
+ // EP1020: reportTunnelHealth() removed - tunnel_health_status and tunnel_last_health_check columns dropped
9176
+ // Health checking (checkTunnelHealth) and auto-restart logic preserved for detecting dead tunnels
9196
9177
  /**
9197
9178
  * EP833: Kill processes matching a pattern
9198
9179
  * Used to clean up orphaned cloudflared processes