episoda 0.2.27 → 0.2.29
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 +14 -14
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +219 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2649,7 +2649,7 @@ var require_dist = __commonJS({
|
|
|
2649
2649
|
|
|
2650
2650
|
// src/index.ts
|
|
2651
2651
|
var import_commander = require("commander");
|
|
2652
|
-
var
|
|
2652
|
+
var import_core15 = __toESM(require_dist());
|
|
2653
2653
|
|
|
2654
2654
|
// src/commands/dev.ts
|
|
2655
2655
|
var import_core4 = __toESM(require_dist());
|
|
@@ -3671,8 +3671,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3671
3671
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
3672
3672
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
3673
3673
|
try {
|
|
3674
|
-
const { execSync:
|
|
3675
|
-
|
|
3674
|
+
const { execSync: execSync9 } = require("child_process");
|
|
3675
|
+
execSync9(script, {
|
|
3676
3676
|
cwd: worktree.worktreePath,
|
|
3677
3677
|
stdio: "inherit",
|
|
3678
3678
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -3706,8 +3706,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
3706
3706
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
3707
3707
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
3708
3708
|
try {
|
|
3709
|
-
const { execSync:
|
|
3710
|
-
|
|
3709
|
+
const { execSync: execSync9 } = require("child_process");
|
|
3710
|
+
execSync9(script, {
|
|
3711
3711
|
cwd: worktree.worktreePath,
|
|
3712
3712
|
stdio: "inherit",
|
|
3713
3713
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -4886,6 +4886,60 @@ ${exportLine}
|
|
|
4886
4886
|
|
|
4887
4887
|
// src/commands/status.ts
|
|
4888
4888
|
var import_core8 = __toESM(require_dist());
|
|
4889
|
+
|
|
4890
|
+
// src/utils/update-checker.ts
|
|
4891
|
+
var import_child_process7 = require("child_process");
|
|
4892
|
+
var semver = __toESM(require("semver"));
|
|
4893
|
+
var PACKAGE_NAME = "episoda";
|
|
4894
|
+
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
4895
|
+
async function checkForUpdates(currentVersion) {
|
|
4896
|
+
try {
|
|
4897
|
+
const controller = new AbortController();
|
|
4898
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
4899
|
+
const response = await fetch(`${NPM_REGISTRY}/${PACKAGE_NAME}/latest`, {
|
|
4900
|
+
signal: controller.signal
|
|
4901
|
+
});
|
|
4902
|
+
clearTimeout(timeoutId);
|
|
4903
|
+
if (!response.ok) {
|
|
4904
|
+
return { currentVersion, latestVersion: currentVersion, updateAvailable: false };
|
|
4905
|
+
}
|
|
4906
|
+
const data = await response.json();
|
|
4907
|
+
const latestVersion = data.version;
|
|
4908
|
+
return {
|
|
4909
|
+
currentVersion,
|
|
4910
|
+
latestVersion,
|
|
4911
|
+
updateAvailable: semver.gt(latestVersion, currentVersion)
|
|
4912
|
+
};
|
|
4913
|
+
} catch (error) {
|
|
4914
|
+
return { currentVersion, latestVersion: currentVersion, updateAvailable: false, offline: true };
|
|
4915
|
+
}
|
|
4916
|
+
}
|
|
4917
|
+
function performBackgroundUpdate() {
|
|
4918
|
+
try {
|
|
4919
|
+
const child = (0, import_child_process7.spawn)("npm", ["update", "-g", PACKAGE_NAME], {
|
|
4920
|
+
detached: true,
|
|
4921
|
+
stdio: "ignore",
|
|
4922
|
+
// Use shell on Windows for proper npm execution
|
|
4923
|
+
shell: process.platform === "win32"
|
|
4924
|
+
});
|
|
4925
|
+
child.unref();
|
|
4926
|
+
} catch (error) {
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
function getInstalledVersion() {
|
|
4930
|
+
try {
|
|
4931
|
+
const output = (0, import_child_process7.execSync)(`npm list -g ${PACKAGE_NAME} --json`, {
|
|
4932
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
4933
|
+
timeout: 1e4
|
|
4934
|
+
}).toString();
|
|
4935
|
+
const data = JSON.parse(output);
|
|
4936
|
+
return data?.dependencies?.[PACKAGE_NAME]?.version || null;
|
|
4937
|
+
} catch {
|
|
4938
|
+
return null;
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
|
|
4942
|
+
// src/commands/status.ts
|
|
4889
4943
|
async function statusCommand(options = {}) {
|
|
4890
4944
|
status.info("Checking CLI status...");
|
|
4891
4945
|
status.info("");
|
|
@@ -4904,7 +4958,17 @@ async function statusCommand(options = {}) {
|
|
|
4904
4958
|
status.info("Configuration:");
|
|
4905
4959
|
status.info(` Project ID: ${config.project_id}`);
|
|
4906
4960
|
status.info(` API URL: ${config.api_url}`);
|
|
4907
|
-
|
|
4961
|
+
if (!options.skipUpdateCheck) {
|
|
4962
|
+
const updateResult = await checkForUpdates(import_core8.VERSION);
|
|
4963
|
+
if (updateResult.updateAvailable) {
|
|
4964
|
+
status.info(` CLI Version: ${import_core8.VERSION} \u2B06 updating to ${updateResult.latestVersion}...`);
|
|
4965
|
+
performBackgroundUpdate();
|
|
4966
|
+
} else {
|
|
4967
|
+
status.info(` CLI Version: ${import_core8.VERSION} \u2713`);
|
|
4968
|
+
}
|
|
4969
|
+
} else {
|
|
4970
|
+
status.info(` CLI Version: ${import_core8.VERSION}`);
|
|
4971
|
+
}
|
|
4908
4972
|
status.info(` Config file: ${(0, import_core8.getConfigPath)()}`);
|
|
4909
4973
|
status.info("");
|
|
4910
4974
|
if (!config.access_token || config.access_token === "") {
|
|
@@ -5797,8 +5861,142 @@ async function listWorktrees(options) {
|
|
|
5797
5861
|
console.log("");
|
|
5798
5862
|
}
|
|
5799
5863
|
|
|
5864
|
+
// src/commands/update.ts
|
|
5865
|
+
var import_child_process8 = require("child_process");
|
|
5866
|
+
var import_core14 = __toESM(require_dist());
|
|
5867
|
+
async function isDaemonRunning2() {
|
|
5868
|
+
try {
|
|
5869
|
+
const daemonStatus = await getStatus();
|
|
5870
|
+
return !!daemonStatus;
|
|
5871
|
+
} catch {
|
|
5872
|
+
return false;
|
|
5873
|
+
}
|
|
5874
|
+
}
|
|
5875
|
+
function stopDaemon2() {
|
|
5876
|
+
try {
|
|
5877
|
+
(0, import_child_process8.execSync)("episoda stop", { stdio: "pipe" });
|
|
5878
|
+
return true;
|
|
5879
|
+
} catch {
|
|
5880
|
+
return false;
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
function startDaemon2() {
|
|
5884
|
+
try {
|
|
5885
|
+
const child = (0, import_child_process8.spawn)("episoda", ["dev"], {
|
|
5886
|
+
detached: true,
|
|
5887
|
+
stdio: "ignore",
|
|
5888
|
+
shell: process.platform === "win32"
|
|
5889
|
+
});
|
|
5890
|
+
child.unref();
|
|
5891
|
+
return true;
|
|
5892
|
+
} catch {
|
|
5893
|
+
return false;
|
|
5894
|
+
}
|
|
5895
|
+
}
|
|
5896
|
+
function performUpdate() {
|
|
5897
|
+
try {
|
|
5898
|
+
(0, import_child_process8.execSync)("npm update -g episoda", {
|
|
5899
|
+
stdio: "pipe",
|
|
5900
|
+
timeout: 12e4
|
|
5901
|
+
// 2 minute timeout
|
|
5902
|
+
});
|
|
5903
|
+
return { success: true };
|
|
5904
|
+
} catch (error) {
|
|
5905
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5906
|
+
if (message.includes("EACCES") || message.includes("permission denied")) {
|
|
5907
|
+
return {
|
|
5908
|
+
success: false,
|
|
5909
|
+
error: "Permission denied. Try running with sudo:\n sudo npm update -g episoda"
|
|
5910
|
+
};
|
|
5911
|
+
}
|
|
5912
|
+
return { success: false, error: message };
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
async function updateCommand(options = {}) {
|
|
5916
|
+
const currentVersion = import_core14.VERSION;
|
|
5917
|
+
status.info(`Current version: ${currentVersion}`);
|
|
5918
|
+
status.info("Checking for updates...");
|
|
5919
|
+
const result = await checkForUpdates(currentVersion);
|
|
5920
|
+
if (result.offline) {
|
|
5921
|
+
status.warning("\u26A0 Could not check for updates (offline or network error)");
|
|
5922
|
+
status.info(` Current version: ${currentVersion}`);
|
|
5923
|
+
status.info("");
|
|
5924
|
+
status.info("Check your internet connection and try again.");
|
|
5925
|
+
return;
|
|
5926
|
+
}
|
|
5927
|
+
if (!result.updateAvailable) {
|
|
5928
|
+
status.success(`\u2713 Already up to date (${currentVersion})`);
|
|
5929
|
+
return;
|
|
5930
|
+
}
|
|
5931
|
+
status.info(`Update available: ${result.currentVersion} \u2192 ${result.latestVersion}`);
|
|
5932
|
+
if (options.check) {
|
|
5933
|
+
status.info("");
|
|
5934
|
+
status.info('Run "episoda update" to install the update.');
|
|
5935
|
+
return;
|
|
5936
|
+
}
|
|
5937
|
+
if (!options.yes) {
|
|
5938
|
+
status.info("");
|
|
5939
|
+
status.info("To update, run:");
|
|
5940
|
+
status.info(" episoda update -y");
|
|
5941
|
+
status.info("");
|
|
5942
|
+
status.info("Or with daemon restart:");
|
|
5943
|
+
status.info(" episoda update -y --restart");
|
|
5944
|
+
return;
|
|
5945
|
+
}
|
|
5946
|
+
const daemonWasRunning = options.restart ? await isDaemonRunning2() : false;
|
|
5947
|
+
if (options.restart && daemonWasRunning) {
|
|
5948
|
+
status.info("Stopping daemon before update...");
|
|
5949
|
+
if (!stopDaemon2()) {
|
|
5950
|
+
status.warning("Could not stop daemon gracefully, continuing with update...");
|
|
5951
|
+
}
|
|
5952
|
+
}
|
|
5953
|
+
status.info("Updating...");
|
|
5954
|
+
const updateResult = performUpdate();
|
|
5955
|
+
if (!updateResult.success) {
|
|
5956
|
+
status.error(`\u2717 Update failed: ${updateResult.error}`);
|
|
5957
|
+
if (options.restart && daemonWasRunning) {
|
|
5958
|
+
status.info("Restarting daemon...");
|
|
5959
|
+
startDaemon2();
|
|
5960
|
+
}
|
|
5961
|
+
process.exit(1);
|
|
5962
|
+
}
|
|
5963
|
+
const installedVersion = getInstalledVersion();
|
|
5964
|
+
if (installedVersion && installedVersion !== result.latestVersion) {
|
|
5965
|
+
status.warning(`\u26A0 Update completed but version mismatch detected`);
|
|
5966
|
+
status.info(` Expected: ${result.latestVersion}`);
|
|
5967
|
+
status.info(` Installed: ${installedVersion}`);
|
|
5968
|
+
status.info("");
|
|
5969
|
+
status.info("Try running manually: npm update -g episoda");
|
|
5970
|
+
} else if (installedVersion) {
|
|
5971
|
+
status.success(`\u2713 Updated to ${installedVersion}`);
|
|
5972
|
+
} else {
|
|
5973
|
+
status.success(`\u2713 Updated to ${result.latestVersion}`);
|
|
5974
|
+
}
|
|
5975
|
+
if (options.restart && daemonWasRunning) {
|
|
5976
|
+
status.info("Restarting daemon...");
|
|
5977
|
+
await new Promise((resolve4) => setTimeout(resolve4, 1e3));
|
|
5978
|
+
if (startDaemon2()) {
|
|
5979
|
+
status.success("\u2713 Daemon restarted");
|
|
5980
|
+
status.info("");
|
|
5981
|
+
status.info('Run "episoda status" to verify connection.');
|
|
5982
|
+
} else {
|
|
5983
|
+
status.warning("Could not restart daemon automatically.");
|
|
5984
|
+
status.info('Run "episoda dev" to start the daemon.');
|
|
5985
|
+
}
|
|
5986
|
+
} else if (options.restart) {
|
|
5987
|
+
status.info("Daemon was not running, skipping restart.");
|
|
5988
|
+
} else {
|
|
5989
|
+
const daemonRunning = await isDaemonRunning2();
|
|
5990
|
+
if (daemonRunning) {
|
|
5991
|
+
status.info("");
|
|
5992
|
+
status.info("Note: Restart the daemon to use the new version:");
|
|
5993
|
+
status.info(" episoda stop && episoda dev");
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5997
|
+
|
|
5800
5998
|
// src/index.ts
|
|
5801
|
-
import_commander.program.name("episoda").description("Episoda CLI - local development with git worktree isolation").version(
|
|
5999
|
+
import_commander.program.name("episoda").description("Episoda CLI - local development with git worktree isolation").version(import_core15.VERSION);
|
|
5802
6000
|
import_commander.program.command("auth").description("Authenticate to Episoda via OAuth and configure CLI").option("--api-url <url>", "API URL (default: https://episoda.dev)").action(async (options) => {
|
|
5803
6001
|
try {
|
|
5804
6002
|
await authCommand(options);
|
|
@@ -5830,9 +6028,13 @@ import_commander.program.command("dev").description("Connect to Episoda and star
|
|
|
5830
6028
|
process.exit(1);
|
|
5831
6029
|
}
|
|
5832
6030
|
});
|
|
5833
|
-
import_commander.program.command("status").description("Show connection status").option("--verify", "Verify connection is healthy (not just connected)").option("--local", "Only check local daemon state (faster, but may be stale)").action(async (options) => {
|
|
6031
|
+
import_commander.program.command("status").description("Show connection status").option("--verify", "Verify connection is healthy (not just connected)").option("--local", "Only check local daemon state (faster, but may be stale)").option("--skip-update-check", "Skip CLI version update check (faster)").action(async (options) => {
|
|
5834
6032
|
try {
|
|
5835
|
-
await statusCommand({
|
|
6033
|
+
await statusCommand({
|
|
6034
|
+
verify: options.verify,
|
|
6035
|
+
local: options.local,
|
|
6036
|
+
skipUpdateCheck: options.skipUpdateCheck
|
|
6037
|
+
});
|
|
5836
6038
|
} catch (error) {
|
|
5837
6039
|
status.error(`Status check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
5838
6040
|
process.exit(1);
|
|
@@ -5854,6 +6056,14 @@ import_commander.program.command("disconnect").description("Disconnect from epis
|
|
|
5854
6056
|
process.exit(1);
|
|
5855
6057
|
}
|
|
5856
6058
|
});
|
|
6059
|
+
import_commander.program.command("update").description("Check for updates and optionally install them").option("-y, --yes", "Auto-update without prompting").option("--check", "Just check for updates, do not install").option("--restart", "Restart daemon after update if it was running").action(async (options) => {
|
|
6060
|
+
try {
|
|
6061
|
+
await updateCommand(options);
|
|
6062
|
+
} catch (error) {
|
|
6063
|
+
status.error(`Update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
6064
|
+
process.exit(1);
|
|
6065
|
+
}
|
|
6066
|
+
});
|
|
5857
6067
|
import_commander.program.command("clone").description("Clone a project for multi-module development").argument("<workspace/project>", "Workspace and project slug (e.g., my-team/my-project)").option("--api-url <url>", "API URL (default: https://episoda.dev)").action(async (slug, options) => {
|
|
5858
6068
|
try {
|
|
5859
6069
|
await cloneCommand(slug, options);
|