episoda 0.2.27 → 0.2.28
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 +190 -6
- 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,
|
|
@@ -5797,8 +5797,184 @@ async function listWorktrees(options) {
|
|
|
5797
5797
|
console.log("");
|
|
5798
5798
|
}
|
|
5799
5799
|
|
|
5800
|
+
// src/commands/update.ts
|
|
5801
|
+
var import_child_process8 = require("child_process");
|
|
5802
|
+
var import_core14 = __toESM(require_dist());
|
|
5803
|
+
|
|
5804
|
+
// src/utils/update-checker.ts
|
|
5805
|
+
var import_child_process7 = require("child_process");
|
|
5806
|
+
var semver = __toESM(require("semver"));
|
|
5807
|
+
var PACKAGE_NAME = "episoda";
|
|
5808
|
+
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
5809
|
+
async function checkForUpdates(currentVersion) {
|
|
5810
|
+
try {
|
|
5811
|
+
const controller = new AbortController();
|
|
5812
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
5813
|
+
const response = await fetch(`${NPM_REGISTRY}/${PACKAGE_NAME}/latest`, {
|
|
5814
|
+
signal: controller.signal
|
|
5815
|
+
});
|
|
5816
|
+
clearTimeout(timeoutId);
|
|
5817
|
+
if (!response.ok) {
|
|
5818
|
+
return { currentVersion, latestVersion: currentVersion, updateAvailable: false };
|
|
5819
|
+
}
|
|
5820
|
+
const data = await response.json();
|
|
5821
|
+
const latestVersion = data.version;
|
|
5822
|
+
return {
|
|
5823
|
+
currentVersion,
|
|
5824
|
+
latestVersion,
|
|
5825
|
+
updateAvailable: semver.gt(latestVersion, currentVersion)
|
|
5826
|
+
};
|
|
5827
|
+
} catch (error) {
|
|
5828
|
+
return { currentVersion, latestVersion: currentVersion, updateAvailable: false, offline: true };
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
function getInstalledVersion() {
|
|
5832
|
+
try {
|
|
5833
|
+
const output = (0, import_child_process7.execSync)(`npm list -g ${PACKAGE_NAME} --json`, {
|
|
5834
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5835
|
+
timeout: 1e4
|
|
5836
|
+
}).toString();
|
|
5837
|
+
const data = JSON.parse(output);
|
|
5838
|
+
return data?.dependencies?.[PACKAGE_NAME]?.version || null;
|
|
5839
|
+
} catch {
|
|
5840
|
+
return null;
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5844
|
+
// src/commands/update.ts
|
|
5845
|
+
async function isDaemonRunning2() {
|
|
5846
|
+
try {
|
|
5847
|
+
const daemonStatus = await getStatus();
|
|
5848
|
+
return !!daemonStatus;
|
|
5849
|
+
} catch {
|
|
5850
|
+
return false;
|
|
5851
|
+
}
|
|
5852
|
+
}
|
|
5853
|
+
function stopDaemon2() {
|
|
5854
|
+
try {
|
|
5855
|
+
(0, import_child_process8.execSync)("episoda stop", { stdio: "pipe" });
|
|
5856
|
+
return true;
|
|
5857
|
+
} catch {
|
|
5858
|
+
return false;
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
function startDaemon2() {
|
|
5862
|
+
try {
|
|
5863
|
+
const child = (0, import_child_process8.spawn)("episoda", ["dev"], {
|
|
5864
|
+
detached: true,
|
|
5865
|
+
stdio: "ignore",
|
|
5866
|
+
shell: process.platform === "win32"
|
|
5867
|
+
});
|
|
5868
|
+
child.unref();
|
|
5869
|
+
return true;
|
|
5870
|
+
} catch {
|
|
5871
|
+
return false;
|
|
5872
|
+
}
|
|
5873
|
+
}
|
|
5874
|
+
function performUpdate() {
|
|
5875
|
+
try {
|
|
5876
|
+
(0, import_child_process8.execSync)("npm update -g episoda", {
|
|
5877
|
+
stdio: "pipe",
|
|
5878
|
+
timeout: 12e4
|
|
5879
|
+
// 2 minute timeout
|
|
5880
|
+
});
|
|
5881
|
+
return { success: true };
|
|
5882
|
+
} catch (error) {
|
|
5883
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5884
|
+
if (message.includes("EACCES") || message.includes("permission denied")) {
|
|
5885
|
+
return {
|
|
5886
|
+
success: false,
|
|
5887
|
+
error: "Permission denied. Try running with sudo:\n sudo npm update -g episoda"
|
|
5888
|
+
};
|
|
5889
|
+
}
|
|
5890
|
+
return { success: false, error: message };
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
async function updateCommand(options = {}) {
|
|
5894
|
+
const currentVersion = import_core14.VERSION;
|
|
5895
|
+
status.info(`Current version: ${currentVersion}`);
|
|
5896
|
+
status.info("Checking for updates...");
|
|
5897
|
+
const result = await checkForUpdates(currentVersion);
|
|
5898
|
+
if (result.offline) {
|
|
5899
|
+
status.warning("\u26A0 Could not check for updates (offline or network error)");
|
|
5900
|
+
status.info(` Current version: ${currentVersion}`);
|
|
5901
|
+
status.info("");
|
|
5902
|
+
status.info("Check your internet connection and try again.");
|
|
5903
|
+
return;
|
|
5904
|
+
}
|
|
5905
|
+
if (!result.updateAvailable) {
|
|
5906
|
+
status.success(`\u2713 Already up to date (${currentVersion})`);
|
|
5907
|
+
return;
|
|
5908
|
+
}
|
|
5909
|
+
status.info(`Update available: ${result.currentVersion} \u2192 ${result.latestVersion}`);
|
|
5910
|
+
if (options.check) {
|
|
5911
|
+
status.info("");
|
|
5912
|
+
status.info('Run "episoda update" to install the update.');
|
|
5913
|
+
return;
|
|
5914
|
+
}
|
|
5915
|
+
if (!options.yes) {
|
|
5916
|
+
status.info("");
|
|
5917
|
+
status.info("To update, run:");
|
|
5918
|
+
status.info(" episoda update -y");
|
|
5919
|
+
status.info("");
|
|
5920
|
+
status.info("Or with daemon restart:");
|
|
5921
|
+
status.info(" episoda update -y --restart");
|
|
5922
|
+
return;
|
|
5923
|
+
}
|
|
5924
|
+
const daemonWasRunning = options.restart ? await isDaemonRunning2() : false;
|
|
5925
|
+
if (options.restart && daemonWasRunning) {
|
|
5926
|
+
status.info("Stopping daemon before update...");
|
|
5927
|
+
if (!stopDaemon2()) {
|
|
5928
|
+
status.warning("Could not stop daemon gracefully, continuing with update...");
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
status.info("Updating...");
|
|
5932
|
+
const updateResult = performUpdate();
|
|
5933
|
+
if (!updateResult.success) {
|
|
5934
|
+
status.error(`\u2717 Update failed: ${updateResult.error}`);
|
|
5935
|
+
if (options.restart && daemonWasRunning) {
|
|
5936
|
+
status.info("Restarting daemon...");
|
|
5937
|
+
startDaemon2();
|
|
5938
|
+
}
|
|
5939
|
+
process.exit(1);
|
|
5940
|
+
}
|
|
5941
|
+
const installedVersion = getInstalledVersion();
|
|
5942
|
+
if (installedVersion && installedVersion !== result.latestVersion) {
|
|
5943
|
+
status.warning(`\u26A0 Update completed but version mismatch detected`);
|
|
5944
|
+
status.info(` Expected: ${result.latestVersion}`);
|
|
5945
|
+
status.info(` Installed: ${installedVersion}`);
|
|
5946
|
+
status.info("");
|
|
5947
|
+
status.info("Try running manually: npm update -g episoda");
|
|
5948
|
+
} else if (installedVersion) {
|
|
5949
|
+
status.success(`\u2713 Updated to ${installedVersion}`);
|
|
5950
|
+
} else {
|
|
5951
|
+
status.success(`\u2713 Updated to ${result.latestVersion}`);
|
|
5952
|
+
}
|
|
5953
|
+
if (options.restart && daemonWasRunning) {
|
|
5954
|
+
status.info("Restarting daemon...");
|
|
5955
|
+
await new Promise((resolve4) => setTimeout(resolve4, 1e3));
|
|
5956
|
+
if (startDaemon2()) {
|
|
5957
|
+
status.success("\u2713 Daemon restarted");
|
|
5958
|
+
status.info("");
|
|
5959
|
+
status.info('Run "episoda status" to verify connection.');
|
|
5960
|
+
} else {
|
|
5961
|
+
status.warning("Could not restart daemon automatically.");
|
|
5962
|
+
status.info('Run "episoda dev" to start the daemon.');
|
|
5963
|
+
}
|
|
5964
|
+
} else if (options.restart) {
|
|
5965
|
+
status.info("Daemon was not running, skipping restart.");
|
|
5966
|
+
} else {
|
|
5967
|
+
const daemonRunning = await isDaemonRunning2();
|
|
5968
|
+
if (daemonRunning) {
|
|
5969
|
+
status.info("");
|
|
5970
|
+
status.info("Note: Restart the daemon to use the new version:");
|
|
5971
|
+
status.info(" episoda stop && episoda dev");
|
|
5972
|
+
}
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
|
|
5800
5976
|
// src/index.ts
|
|
5801
|
-
import_commander.program.name("episoda").description("Episoda CLI - local development with git worktree isolation").version(
|
|
5977
|
+
import_commander.program.name("episoda").description("Episoda CLI - local development with git worktree isolation").version(import_core15.VERSION);
|
|
5802
5978
|
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
5979
|
try {
|
|
5804
5980
|
await authCommand(options);
|
|
@@ -5854,6 +6030,14 @@ import_commander.program.command("disconnect").description("Disconnect from epis
|
|
|
5854
6030
|
process.exit(1);
|
|
5855
6031
|
}
|
|
5856
6032
|
});
|
|
6033
|
+
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) => {
|
|
6034
|
+
try {
|
|
6035
|
+
await updateCommand(options);
|
|
6036
|
+
} catch (error) {
|
|
6037
|
+
status.error(`Update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
6038
|
+
process.exit(1);
|
|
6039
|
+
}
|
|
6040
|
+
});
|
|
5857
6041
|
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
6042
|
try {
|
|
5859
6043
|
await cloneCommand(slug, options);
|