episoda 0.2.45 → 0.2.47
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/daemon/daemon-process.js +32 -175
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +15 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -821,14 +821,25 @@ var require_git_executor = __commonJS({
|
|
|
821
821
|
const baseBranch = command.baseBranch || "main";
|
|
822
822
|
try {
|
|
823
823
|
let stdout;
|
|
824
|
+
let comparisonSucceeded = false;
|
|
824
825
|
try {
|
|
825
|
-
const result = await execAsync2(`git log
|
|
826
|
+
const result = await execAsync2(`git log origin/${baseBranch}.."${command.branch}" --pretty=format:"%H|%an|%ae|%aI|%s" -n ${limit} --`, { cwd, timeout: options?.timeout || 1e4 });
|
|
826
827
|
stdout = result.stdout;
|
|
827
|
-
|
|
828
|
+
comparisonSucceeded = true;
|
|
829
|
+
} catch {
|
|
828
830
|
try {
|
|
829
|
-
const result = await execAsync2(`git log "${command.branch}" --pretty=format:"%H|%an|%ae|%aI|%s" -n ${limit} --`, { cwd, timeout: options?.timeout || 1e4 });
|
|
831
|
+
const result = await execAsync2(`git log ${baseBranch}.."${command.branch}" --pretty=format:"%H|%an|%ae|%aI|%s" -n ${limit} --`, { cwd, timeout: options?.timeout || 1e4 });
|
|
830
832
|
stdout = result.stdout;
|
|
831
|
-
|
|
833
|
+
comparisonSucceeded = true;
|
|
834
|
+
} catch {
|
|
835
|
+
stdout = "";
|
|
836
|
+
comparisonSucceeded = false;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
if (!comparisonSucceeded) {
|
|
840
|
+
try {
|
|
841
|
+
await execAsync2(`git rev-parse --verify "${command.branch}"`, { cwd, timeout: options?.timeout || 5e3 });
|
|
842
|
+
} catch {
|
|
832
843
|
return {
|
|
833
844
|
success: false,
|
|
834
845
|
error: "BRANCH_NOT_FOUND",
|
|
@@ -2682,7 +2693,7 @@ var require_package = __commonJS({
|
|
|
2682
2693
|
"package.json"(exports2, module2) {
|
|
2683
2694
|
module2.exports = {
|
|
2684
2695
|
name: "episoda",
|
|
2685
|
-
version: "0.2.
|
|
2696
|
+
version: "0.2.47",
|
|
2686
2697
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2687
2698
|
main: "dist/index.js",
|
|
2688
2699
|
types: "dist/index.d.ts",
|
|
@@ -4096,14 +4107,11 @@ var TUNNEL_PID_DIR = path7.join(os2.homedir(), ".episoda", "tunnels");
|
|
|
4096
4107
|
var TUNNEL_TIMEOUTS = {
|
|
4097
4108
|
/** Time to wait for Named Tunnel connection (includes API token fetch + connect) */
|
|
4098
4109
|
NAMED_TUNNEL_CONNECT: 6e4,
|
|
4099
|
-
/** Time to wait for Quick Tunnel connection (simpler, faster connection) */
|
|
4100
|
-
QUICK_TUNNEL_CONNECT: 3e4,
|
|
4101
4110
|
/** Time to wait for cloudflared process to start before giving up */
|
|
4102
4111
|
PROCESS_START: 1e4,
|
|
4103
4112
|
/** Grace period after starting cloudflared before checking status */
|
|
4104
4113
|
STARTUP_GRACE: 2e3
|
|
4105
4114
|
};
|
|
4106
|
-
var TUNNEL_URL_REGEX = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/i;
|
|
4107
4115
|
var DEFAULT_RECONNECT_CONFIG = {
|
|
4108
4116
|
maxRetries: 5,
|
|
4109
4117
|
initialDelayMs: 1e3,
|
|
@@ -4558,151 +4566,21 @@ var TunnelManager = class extends import_events.EventEmitter {
|
|
|
4558
4566
|
});
|
|
4559
4567
|
}
|
|
4560
4568
|
/**
|
|
4561
|
-
* EP948:
|
|
4569
|
+
* EP948: Start tunnel process (Named Tunnels only)
|
|
4570
|
+
* EP1020: Removed Quick Tunnel fallback - Named Tunnels are the only supported mode
|
|
4562
4571
|
*/
|
|
4563
4572
|
async startTunnelProcess(options, existingState) {
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
return
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
return this.startQuickTunnelProcess(options, existingState);
|
|
4570
|
-
}
|
|
4571
|
-
/**
|
|
4572
|
-
* EP672-9: Internal method to start the tunnel process (Quick Tunnel mode)
|
|
4573
|
-
* Separated from startTunnel to support reconnection
|
|
4574
|
-
*/
|
|
4575
|
-
async startQuickTunnelProcess(options, existingState) {
|
|
4576
|
-
const { moduleUid, port = 3e3, onUrl, onStatusChange } = options;
|
|
4577
|
-
if (!this.cloudflaredPath) {
|
|
4578
|
-
try {
|
|
4579
|
-
this.cloudflaredPath = await ensureCloudflared();
|
|
4580
|
-
} catch (error) {
|
|
4581
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4582
|
-
return { success: false, error: `Failed to get cloudflared: ${errorMessage}` };
|
|
4583
|
-
}
|
|
4584
|
-
}
|
|
4585
|
-
return new Promise((resolve3) => {
|
|
4586
|
-
const tunnelInfo = {
|
|
4587
|
-
moduleUid,
|
|
4588
|
-
url: "",
|
|
4589
|
-
port,
|
|
4590
|
-
status: "starting",
|
|
4591
|
-
startedAt: /* @__PURE__ */ new Date(),
|
|
4592
|
-
process: null
|
|
4593
|
-
// Will be set below
|
|
4594
|
-
};
|
|
4595
|
-
const process2 = (0, import_child_process6.spawn)(this.cloudflaredPath, [
|
|
4596
|
-
"tunnel",
|
|
4597
|
-
"--url",
|
|
4598
|
-
`http://localhost:${port}`
|
|
4599
|
-
], {
|
|
4600
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
4601
|
-
});
|
|
4602
|
-
tunnelInfo.process = process2;
|
|
4603
|
-
tunnelInfo.pid = process2.pid;
|
|
4604
|
-
if (process2.pid) {
|
|
4605
|
-
this.writePidFile(moduleUid, process2.pid);
|
|
4606
|
-
}
|
|
4607
|
-
const state = existingState || {
|
|
4608
|
-
info: tunnelInfo,
|
|
4609
|
-
options,
|
|
4610
|
-
intentionallyStopped: false,
|
|
4611
|
-
retryCount: 0,
|
|
4612
|
-
retryTimeoutId: null
|
|
4613
|
-
};
|
|
4614
|
-
state.info = tunnelInfo;
|
|
4615
|
-
this.tunnelStates.set(moduleUid, state);
|
|
4616
|
-
let urlFound = false;
|
|
4617
|
-
let stdoutBuffer = "";
|
|
4618
|
-
let stderrBuffer = "";
|
|
4619
|
-
const parseOutput = (data) => {
|
|
4620
|
-
if (urlFound) return;
|
|
4621
|
-
const match = data.match(TUNNEL_URL_REGEX);
|
|
4622
|
-
if (match) {
|
|
4623
|
-
urlFound = true;
|
|
4624
|
-
tunnelInfo.url = match[0];
|
|
4625
|
-
tunnelInfo.status = "connected";
|
|
4626
|
-
onStatusChange?.("connected");
|
|
4627
|
-
onUrl?.(tunnelInfo.url);
|
|
4628
|
-
this.emitEvent({
|
|
4629
|
-
type: "started",
|
|
4630
|
-
moduleUid,
|
|
4631
|
-
url: tunnelInfo.url
|
|
4632
|
-
});
|
|
4633
|
-
resolve3({ success: true, url: tunnelInfo.url });
|
|
4634
|
-
}
|
|
4573
|
+
if (!options.tunnelToken) {
|
|
4574
|
+
console.error(`[Tunnel] EP1020: No tunnel token available for ${options.moduleUid}`);
|
|
4575
|
+
return {
|
|
4576
|
+
success: false,
|
|
4577
|
+
error: "Named Tunnel token required. Quick Tunnels are no longer supported."
|
|
4635
4578
|
};
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
parseOutput(stdoutBuffer);
|
|
4639
|
-
});
|
|
4640
|
-
process2.stderr?.on("data", (data) => {
|
|
4641
|
-
stderrBuffer += data.toString();
|
|
4642
|
-
parseOutput(stderrBuffer);
|
|
4643
|
-
});
|
|
4644
|
-
process2.on("exit", (code, signal) => {
|
|
4645
|
-
const wasConnected = tunnelInfo.status === "connected";
|
|
4646
|
-
tunnelInfo.status = "disconnected";
|
|
4647
|
-
const currentState = this.tunnelStates.get(moduleUid);
|
|
4648
|
-
if (!urlFound) {
|
|
4649
|
-
const errorMsg = `Tunnel process exited with code ${code}`;
|
|
4650
|
-
tunnelInfo.status = "error";
|
|
4651
|
-
tunnelInfo.error = errorMsg;
|
|
4652
|
-
if (currentState && !currentState.intentionallyStopped) {
|
|
4653
|
-
this.attemptReconnect(moduleUid);
|
|
4654
|
-
} else {
|
|
4655
|
-
this.tunnelStates.delete(moduleUid);
|
|
4656
|
-
onStatusChange?.("error", errorMsg);
|
|
4657
|
-
this.emitEvent({ type: "error", moduleUid, error: errorMsg });
|
|
4658
|
-
}
|
|
4659
|
-
resolve3({ success: false, error: errorMsg });
|
|
4660
|
-
} else if (wasConnected) {
|
|
4661
|
-
if (currentState && !currentState.intentionallyStopped) {
|
|
4662
|
-
console.log(`[Tunnel] ${moduleUid} crashed unexpectedly, attempting reconnect...`);
|
|
4663
|
-
onStatusChange?.("reconnecting");
|
|
4664
|
-
this.attemptReconnect(moduleUid);
|
|
4665
|
-
} else {
|
|
4666
|
-
this.tunnelStates.delete(moduleUid);
|
|
4667
|
-
onStatusChange?.("disconnected");
|
|
4668
|
-
this.emitEvent({ type: "stopped", moduleUid });
|
|
4669
|
-
}
|
|
4670
|
-
}
|
|
4671
|
-
});
|
|
4672
|
-
process2.on("error", (error) => {
|
|
4673
|
-
tunnelInfo.status = "error";
|
|
4674
|
-
tunnelInfo.error = error.message;
|
|
4675
|
-
const currentState = this.tunnelStates.get(moduleUid);
|
|
4676
|
-
if (currentState && !currentState.intentionallyStopped) {
|
|
4677
|
-
this.attemptReconnect(moduleUid);
|
|
4678
|
-
} else {
|
|
4679
|
-
this.tunnelStates.delete(moduleUid);
|
|
4680
|
-
onStatusChange?.("error", error.message);
|
|
4681
|
-
this.emitEvent({ type: "error", moduleUid, error: error.message });
|
|
4682
|
-
}
|
|
4683
|
-
if (!urlFound) {
|
|
4684
|
-
resolve3({ success: false, error: error.message });
|
|
4685
|
-
}
|
|
4686
|
-
});
|
|
4687
|
-
setTimeout(() => {
|
|
4688
|
-
if (!urlFound) {
|
|
4689
|
-
process2.kill();
|
|
4690
|
-
const errorMsg = "Tunnel startup timed out after 30 seconds";
|
|
4691
|
-
tunnelInfo.status = "error";
|
|
4692
|
-
tunnelInfo.error = errorMsg;
|
|
4693
|
-
const currentState = this.tunnelStates.get(moduleUid);
|
|
4694
|
-
if (currentState && !currentState.intentionallyStopped) {
|
|
4695
|
-
this.attemptReconnect(moduleUid);
|
|
4696
|
-
} else {
|
|
4697
|
-
this.tunnelStates.delete(moduleUid);
|
|
4698
|
-
onStatusChange?.("error", errorMsg);
|
|
4699
|
-
this.emitEvent({ type: "error", moduleUid, error: errorMsg });
|
|
4700
|
-
}
|
|
4701
|
-
resolve3({ success: false, error: errorMsg });
|
|
4702
|
-
}
|
|
4703
|
-
}, TUNNEL_TIMEOUTS.QUICK_TUNNEL_CONNECT);
|
|
4704
|
-
});
|
|
4579
|
+
}
|
|
4580
|
+
return this.startNamedTunnelProcess(options, existingState);
|
|
4705
4581
|
}
|
|
4582
|
+
// EP1020: startQuickTunnelProcess removed - Quick Tunnels no longer supported
|
|
4583
|
+
// All tunnels now use Named Tunnels via Cloudflare API
|
|
4706
4584
|
/**
|
|
4707
4585
|
* Start a tunnel for a module
|
|
4708
4586
|
*
|
|
@@ -4771,8 +4649,11 @@ var TunnelManager = class extends import_events.EventEmitter {
|
|
|
4771
4649
|
previewUrl: provisionResult.tunnel.preview_url
|
|
4772
4650
|
};
|
|
4773
4651
|
} else {
|
|
4774
|
-
console.
|
|
4775
|
-
|
|
4652
|
+
console.error(`[Tunnel] EP1020: Named Tunnel provisioning failed for ${moduleUid}: ${provisionResult.error}`);
|
|
4653
|
+
return {
|
|
4654
|
+
success: false,
|
|
4655
|
+
error: `Named Tunnel provisioning failed: ${provisionResult.error}`
|
|
4656
|
+
};
|
|
4776
4657
|
}
|
|
4777
4658
|
}
|
|
4778
4659
|
return this.startTunnelProcess(resolvedOptions);
|
|
@@ -9254,18 +9135,6 @@ var Daemon = class _Daemon {
|
|
|
9254
9135
|
const result2 = await previewManager.restartPreview(moduleUid);
|
|
9255
9136
|
if (result2.success && result2.previewUrl) {
|
|
9256
9137
|
console.log(`[Daemon] EP833: Preview restarted for ${moduleUid}: ${result2.previewUrl}`);
|
|
9257
|
-
try {
|
|
9258
|
-
await fetchWithAuth(`${apiUrl}/api/modules/${moduleUid}/tunnel`, {
|
|
9259
|
-
method: "POST",
|
|
9260
|
-
body: JSON.stringify({
|
|
9261
|
-
tunnel_url: result2.previewUrl,
|
|
9262
|
-
tunnel_error: null,
|
|
9263
|
-
restart_reason: "health_check_failure"
|
|
9264
|
-
})
|
|
9265
|
-
});
|
|
9266
|
-
} catch (e) {
|
|
9267
|
-
console.warn(`[Daemon] EP833: Failed to report restarted tunnel URL`);
|
|
9268
|
-
}
|
|
9269
9138
|
} else {
|
|
9270
9139
|
console.error(`[Daemon] EP833: Preview restart failed for ${moduleUid}: ${result2.error}`);
|
|
9271
9140
|
}
|
|
@@ -9290,18 +9159,6 @@ var Daemon = class _Daemon {
|
|
|
9290
9159
|
});
|
|
9291
9160
|
if (result.success && result.previewUrl) {
|
|
9292
9161
|
console.log(`[Daemon] EP833: Preview started for ${moduleUid}: ${result.previewUrl}`);
|
|
9293
|
-
try {
|
|
9294
|
-
await fetchWithAuth(`${apiUrl}/api/modules/${moduleUid}/tunnel`, {
|
|
9295
|
-
method: "POST",
|
|
9296
|
-
body: JSON.stringify({
|
|
9297
|
-
tunnel_url: result.previewUrl,
|
|
9298
|
-
tunnel_error: null,
|
|
9299
|
-
restart_reason: "health_check_failure"
|
|
9300
|
-
})
|
|
9301
|
-
});
|
|
9302
|
-
} catch (e) {
|
|
9303
|
-
console.warn(`[Daemon] EP833: Failed to report restarted tunnel URL`);
|
|
9304
|
-
}
|
|
9305
9162
|
} else {
|
|
9306
9163
|
console.error(`[Daemon] EP833: Preview start failed for ${moduleUid}: ${result.error}`);
|
|
9307
9164
|
}
|