episoda 0.2.24 → 0.2.26
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 +175 -54
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/hooks/post-checkout +12 -1
- package/dist/index.js +147 -133
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1549,15 +1549,15 @@ var require_git_executor = __commonJS({
|
|
|
1549
1549
|
try {
|
|
1550
1550
|
const { stdout: gitDir } = await execAsync("git rev-parse --git-dir", { cwd, timeout: 5e3 });
|
|
1551
1551
|
const gitDirPath = gitDir.trim();
|
|
1552
|
-
const
|
|
1552
|
+
const fs12 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1553
1553
|
const rebaseMergePath = `${gitDirPath}/rebase-merge`;
|
|
1554
1554
|
const rebaseApplyPath = `${gitDirPath}/rebase-apply`;
|
|
1555
1555
|
try {
|
|
1556
|
-
await
|
|
1556
|
+
await fs12.access(rebaseMergePath);
|
|
1557
1557
|
inRebase = true;
|
|
1558
1558
|
} catch {
|
|
1559
1559
|
try {
|
|
1560
|
-
await
|
|
1560
|
+
await fs12.access(rebaseApplyPath);
|
|
1561
1561
|
inRebase = true;
|
|
1562
1562
|
} catch {
|
|
1563
1563
|
inRebase = false;
|
|
@@ -1611,9 +1611,9 @@ var require_git_executor = __commonJS({
|
|
|
1611
1611
|
error: validation.error || "UNKNOWN_ERROR"
|
|
1612
1612
|
};
|
|
1613
1613
|
}
|
|
1614
|
-
const
|
|
1614
|
+
const fs12 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1615
1615
|
try {
|
|
1616
|
-
await
|
|
1616
|
+
await fs12.access(command.path);
|
|
1617
1617
|
return {
|
|
1618
1618
|
success: false,
|
|
1619
1619
|
error: "WORKTREE_EXISTS",
|
|
@@ -1664,9 +1664,9 @@ var require_git_executor = __commonJS({
|
|
|
1664
1664
|
*/
|
|
1665
1665
|
async executeWorktreeRemove(command, cwd, options) {
|
|
1666
1666
|
try {
|
|
1667
|
-
const
|
|
1667
|
+
const fs12 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1668
1668
|
try {
|
|
1669
|
-
await
|
|
1669
|
+
await fs12.access(command.path);
|
|
1670
1670
|
} catch {
|
|
1671
1671
|
return {
|
|
1672
1672
|
success: false,
|
|
@@ -1819,10 +1819,10 @@ var require_git_executor = __commonJS({
|
|
|
1819
1819
|
*/
|
|
1820
1820
|
async executeCloneBare(command, options) {
|
|
1821
1821
|
try {
|
|
1822
|
-
const
|
|
1823
|
-
const
|
|
1822
|
+
const fs12 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1823
|
+
const path14 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
1824
1824
|
try {
|
|
1825
|
-
await
|
|
1825
|
+
await fs12.access(command.path);
|
|
1826
1826
|
return {
|
|
1827
1827
|
success: false,
|
|
1828
1828
|
error: "BRANCH_ALREADY_EXISTS",
|
|
@@ -1831,9 +1831,9 @@ var require_git_executor = __commonJS({
|
|
|
1831
1831
|
};
|
|
1832
1832
|
} catch {
|
|
1833
1833
|
}
|
|
1834
|
-
const parentDir =
|
|
1834
|
+
const parentDir = path14.dirname(command.path);
|
|
1835
1835
|
try {
|
|
1836
|
-
await
|
|
1836
|
+
await fs12.mkdir(parentDir, { recursive: true });
|
|
1837
1837
|
} catch {
|
|
1838
1838
|
}
|
|
1839
1839
|
const { stdout, stderr } = await execAsync(
|
|
@@ -1876,22 +1876,22 @@ var require_git_executor = __commonJS({
|
|
|
1876
1876
|
*/
|
|
1877
1877
|
async executeProjectInfo(cwd, options) {
|
|
1878
1878
|
try {
|
|
1879
|
-
const
|
|
1880
|
-
const
|
|
1879
|
+
const fs12 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1880
|
+
const path14 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
1881
1881
|
let currentPath = cwd;
|
|
1882
1882
|
let projectPath = cwd;
|
|
1883
1883
|
let bareRepoPath;
|
|
1884
1884
|
for (let i = 0; i < 10; i++) {
|
|
1885
|
-
const bareDir =
|
|
1886
|
-
const episodaDir =
|
|
1885
|
+
const bareDir = path14.join(currentPath, ".bare");
|
|
1886
|
+
const episodaDir = path14.join(currentPath, ".episoda");
|
|
1887
1887
|
try {
|
|
1888
|
-
await
|
|
1889
|
-
await
|
|
1888
|
+
await fs12.access(bareDir);
|
|
1889
|
+
await fs12.access(episodaDir);
|
|
1890
1890
|
projectPath = currentPath;
|
|
1891
1891
|
bareRepoPath = bareDir;
|
|
1892
1892
|
break;
|
|
1893
1893
|
} catch {
|
|
1894
|
-
const parentPath =
|
|
1894
|
+
const parentPath = path14.dirname(currentPath);
|
|
1895
1895
|
if (parentPath === currentPath) {
|
|
1896
1896
|
break;
|
|
1897
1897
|
}
|
|
@@ -2485,31 +2485,31 @@ var require_auth = __commonJS({
|
|
|
2485
2485
|
exports2.loadConfig = loadConfig6;
|
|
2486
2486
|
exports2.saveConfig = saveConfig3;
|
|
2487
2487
|
exports2.validateToken = validateToken;
|
|
2488
|
-
var
|
|
2489
|
-
var
|
|
2488
|
+
var fs12 = __importStar(require("fs"));
|
|
2489
|
+
var path14 = __importStar(require("path"));
|
|
2490
2490
|
var os3 = __importStar(require("os"));
|
|
2491
2491
|
var child_process_1 = require("child_process");
|
|
2492
2492
|
var DEFAULT_CONFIG_FILE = "config.json";
|
|
2493
2493
|
function getConfigDir5() {
|
|
2494
|
-
return process.env.EPISODA_CONFIG_DIR ||
|
|
2494
|
+
return process.env.EPISODA_CONFIG_DIR || path14.join(os3.homedir(), ".episoda");
|
|
2495
2495
|
}
|
|
2496
2496
|
function getConfigPath4(configPath) {
|
|
2497
2497
|
if (configPath) {
|
|
2498
2498
|
return configPath;
|
|
2499
2499
|
}
|
|
2500
|
-
return
|
|
2500
|
+
return path14.join(getConfigDir5(), DEFAULT_CONFIG_FILE);
|
|
2501
2501
|
}
|
|
2502
2502
|
function ensureConfigDir(configPath) {
|
|
2503
|
-
const dir =
|
|
2504
|
-
const isNew = !
|
|
2503
|
+
const dir = path14.dirname(configPath);
|
|
2504
|
+
const isNew = !fs12.existsSync(dir);
|
|
2505
2505
|
if (isNew) {
|
|
2506
|
-
|
|
2506
|
+
fs12.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2507
2507
|
}
|
|
2508
2508
|
if (process.platform === "darwin") {
|
|
2509
|
-
const nosyncPath =
|
|
2510
|
-
if (isNew || !
|
|
2509
|
+
const nosyncPath = path14.join(dir, ".nosync");
|
|
2510
|
+
if (isNew || !fs12.existsSync(nosyncPath)) {
|
|
2511
2511
|
try {
|
|
2512
|
-
|
|
2512
|
+
fs12.writeFileSync(nosyncPath, "", { mode: 384 });
|
|
2513
2513
|
(0, child_process_1.execSync)(`xattr -w com.apple.fileprovider.ignore 1 "${dir}"`, {
|
|
2514
2514
|
stdio: "ignore",
|
|
2515
2515
|
timeout: 5e3
|
|
@@ -2521,11 +2521,11 @@ var require_auth = __commonJS({
|
|
|
2521
2521
|
}
|
|
2522
2522
|
async function loadConfig6(configPath) {
|
|
2523
2523
|
const fullPath = getConfigPath4(configPath);
|
|
2524
|
-
if (!
|
|
2524
|
+
if (!fs12.existsSync(fullPath)) {
|
|
2525
2525
|
return null;
|
|
2526
2526
|
}
|
|
2527
2527
|
try {
|
|
2528
|
-
const content =
|
|
2528
|
+
const content = fs12.readFileSync(fullPath, "utf8");
|
|
2529
2529
|
const config = JSON.parse(content);
|
|
2530
2530
|
return config;
|
|
2531
2531
|
} catch (error) {
|
|
@@ -2538,7 +2538,7 @@ var require_auth = __commonJS({
|
|
|
2538
2538
|
ensureConfigDir(fullPath);
|
|
2539
2539
|
try {
|
|
2540
2540
|
const content = JSON.stringify(config, null, 2);
|
|
2541
|
-
|
|
2541
|
+
fs12.writeFileSync(fullPath, content, { mode: 384 });
|
|
2542
2542
|
} catch (error) {
|
|
2543
2543
|
throw new Error(`Failed to save config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2544
2544
|
}
|
|
@@ -3125,9 +3125,9 @@ async function getDevServerStatus() {
|
|
|
3125
3125
|
}
|
|
3126
3126
|
|
|
3127
3127
|
// src/commands/dev.ts
|
|
3128
|
-
var
|
|
3129
|
-
var
|
|
3130
|
-
var
|
|
3128
|
+
var import_child_process3 = require("child_process");
|
|
3129
|
+
var path6 = __toESM(require("path"));
|
|
3130
|
+
var fs5 = __toESM(require("fs"));
|
|
3131
3131
|
|
|
3132
3132
|
// src/utils/port-check.ts
|
|
3133
3133
|
var net2 = __toESM(require("net"));
|
|
@@ -3784,7 +3784,7 @@ async function fetchProjectPath(config, projectId) {
|
|
|
3784
3784
|
return null;
|
|
3785
3785
|
}
|
|
3786
3786
|
}
|
|
3787
|
-
async function syncProjectPath(config, projectId,
|
|
3787
|
+
async function syncProjectPath(config, projectId, path14) {
|
|
3788
3788
|
if (!config.device_id || !config.access_token) {
|
|
3789
3789
|
return false;
|
|
3790
3790
|
}
|
|
@@ -3797,7 +3797,7 @@ async function syncProjectPath(config, projectId, path13) {
|
|
|
3797
3797
|
"Authorization": `Bearer ${config.access_token}`,
|
|
3798
3798
|
"Content-Type": "application/json"
|
|
3799
3799
|
},
|
|
3800
|
-
body: JSON.stringify({ path:
|
|
3800
|
+
body: JSON.stringify({ path: path14 })
|
|
3801
3801
|
});
|
|
3802
3802
|
if (!response.ok) {
|
|
3803
3803
|
console.debug(`[MachineSettings] syncProjectPath failed: ${response.status} ${response.statusText}`);
|
|
@@ -3809,11 +3809,35 @@ async function syncProjectPath(config, projectId, path13) {
|
|
|
3809
3809
|
}
|
|
3810
3810
|
}
|
|
3811
3811
|
|
|
3812
|
+
// src/utils/bootstrap.ts
|
|
3813
|
+
var fs4 = __toESM(require("fs"));
|
|
3814
|
+
var path5 = __toESM(require("path"));
|
|
3815
|
+
var import_child_process2 = require("child_process");
|
|
3816
|
+
async function extractBootstrapScripts(bareRepoPath, projectPath) {
|
|
3817
|
+
const scriptsDir = path5.join(projectPath, ".episoda", "scripts");
|
|
3818
|
+
const scriptPath = path5.join(scriptsDir, "api-helper.sh");
|
|
3819
|
+
if (fs4.existsSync(scriptPath)) {
|
|
3820
|
+
return false;
|
|
3821
|
+
}
|
|
3822
|
+
fs4.mkdirSync(scriptsDir, { recursive: true });
|
|
3823
|
+
try {
|
|
3824
|
+
const scriptContent = (0, import_child_process2.execSync)(
|
|
3825
|
+
`git --git-dir="${bareRepoPath}" show main:scripts/api-helper.sh`,
|
|
3826
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
3827
|
+
);
|
|
3828
|
+
fs4.writeFileSync(scriptPath, scriptContent, { mode: 493 });
|
|
3829
|
+
return true;
|
|
3830
|
+
} catch (error) {
|
|
3831
|
+
console.log("[bootstrap] Could not extract api-helper.sh:", error);
|
|
3832
|
+
return false;
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
|
|
3812
3836
|
// src/commands/dev.ts
|
|
3813
3837
|
var CONNECTION_MAX_RETRIES = 3;
|
|
3814
3838
|
function findGitRoot(startDir) {
|
|
3815
3839
|
try {
|
|
3816
|
-
const result = (0,
|
|
3840
|
+
const result = (0, import_child_process3.execSync)("git rev-parse --show-toplevel", {
|
|
3817
3841
|
cwd: startDir,
|
|
3818
3842
|
encoding: "utf-8",
|
|
3819
3843
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -3869,12 +3893,12 @@ async function devCommand(options = {}) {
|
|
|
3869
3893
|
}
|
|
3870
3894
|
let projectPath;
|
|
3871
3895
|
const serverPath = await fetchProjectPath(config, config.project_id);
|
|
3872
|
-
if (serverPath &&
|
|
3896
|
+
if (serverPath && fs5.existsSync(serverPath)) {
|
|
3873
3897
|
projectPath = serverPath;
|
|
3874
3898
|
status.debug(`Using server-synced project path: ${projectPath}`);
|
|
3875
3899
|
} else {
|
|
3876
3900
|
const detectedRoot = findGitRoot(options.cwd || process.cwd());
|
|
3877
|
-
projectPath = detectedRoot ||
|
|
3901
|
+
projectPath = detectedRoot || path6.resolve(options.cwd || process.cwd());
|
|
3878
3902
|
if (detectedRoot) {
|
|
3879
3903
|
status.debug(`Detected project root: ${projectPath}`);
|
|
3880
3904
|
} else {
|
|
@@ -3895,6 +3919,11 @@ async function devCommand(options = {}) {
|
|
|
3895
3919
|
status.info("");
|
|
3896
3920
|
process.exit(1);
|
|
3897
3921
|
}
|
|
3922
|
+
const bareRepoPath = path6.join(projectPath, ".bare");
|
|
3923
|
+
const scriptsExtracted = await extractBootstrapScripts(bareRepoPath, projectPath);
|
|
3924
|
+
if (scriptsExtracted) {
|
|
3925
|
+
status.success("\u2713 Bootstrap scripts extracted");
|
|
3926
|
+
}
|
|
3898
3927
|
let daemonPid = isDaemonRunning();
|
|
3899
3928
|
if (!daemonPid) {
|
|
3900
3929
|
status.info("Starting Episoda daemon...");
|
|
@@ -3987,7 +4016,7 @@ async function runDevServer(command, cwd, autoRestart) {
|
|
|
3987
4016
|
let shuttingDown = false;
|
|
3988
4017
|
const startServer = () => {
|
|
3989
4018
|
status.info(`Starting dev server: ${command.join(" ")}`);
|
|
3990
|
-
devProcess = (0,
|
|
4019
|
+
devProcess = (0, import_child_process3.spawn)(command[0], command.slice(1), {
|
|
3991
4020
|
cwd,
|
|
3992
4021
|
stdio: ["inherit", "inherit", "inherit"],
|
|
3993
4022
|
shell: true
|
|
@@ -4040,33 +4069,33 @@ Received ${signal}, shutting down...`);
|
|
|
4040
4069
|
|
|
4041
4070
|
// src/commands/auth.ts
|
|
4042
4071
|
var os = __toESM(require("os"));
|
|
4043
|
-
var
|
|
4044
|
-
var
|
|
4045
|
-
var
|
|
4072
|
+
var fs7 = __toESM(require("fs"));
|
|
4073
|
+
var path8 = __toESM(require("path"));
|
|
4074
|
+
var import_child_process5 = require("child_process");
|
|
4046
4075
|
var import_core6 = __toESM(require_dist());
|
|
4047
4076
|
|
|
4048
4077
|
// src/daemon/machine-id.ts
|
|
4049
|
-
var
|
|
4050
|
-
var
|
|
4078
|
+
var fs6 = __toESM(require("fs"));
|
|
4079
|
+
var path7 = __toESM(require("path"));
|
|
4051
4080
|
var crypto2 = __toESM(require("crypto"));
|
|
4052
|
-
var
|
|
4081
|
+
var import_child_process4 = require("child_process");
|
|
4053
4082
|
var import_core5 = __toESM(require_dist());
|
|
4054
4083
|
function isValidUUID(str) {
|
|
4055
4084
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4056
4085
|
return uuidRegex.test(str);
|
|
4057
4086
|
}
|
|
4058
4087
|
async function getMachineId() {
|
|
4059
|
-
const machineIdPath =
|
|
4088
|
+
const machineIdPath = path7.join((0, import_core5.getConfigDir)(), "machine-id");
|
|
4060
4089
|
try {
|
|
4061
|
-
if (
|
|
4062
|
-
const existingId =
|
|
4090
|
+
if (fs6.existsSync(machineIdPath)) {
|
|
4091
|
+
const existingId = fs6.readFileSync(machineIdPath, "utf-8").trim();
|
|
4063
4092
|
if (existingId) {
|
|
4064
4093
|
if (isValidUUID(existingId)) {
|
|
4065
4094
|
return existingId;
|
|
4066
4095
|
}
|
|
4067
4096
|
console.log("[MachineId] Migrating legacy machine ID to UUID format...");
|
|
4068
4097
|
const newUUID = generateMachineId();
|
|
4069
|
-
|
|
4098
|
+
fs6.writeFileSync(machineIdPath, newUUID, "utf-8");
|
|
4070
4099
|
console.log(`[MachineId] Migrated: ${existingId} \u2192 ${newUUID}`);
|
|
4071
4100
|
return newUUID;
|
|
4072
4101
|
}
|
|
@@ -4075,11 +4104,11 @@ async function getMachineId() {
|
|
|
4075
4104
|
}
|
|
4076
4105
|
const machineId = generateMachineId();
|
|
4077
4106
|
try {
|
|
4078
|
-
const dir =
|
|
4079
|
-
if (!
|
|
4080
|
-
|
|
4107
|
+
const dir = path7.dirname(machineIdPath);
|
|
4108
|
+
if (!fs6.existsSync(dir)) {
|
|
4109
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
4081
4110
|
}
|
|
4082
|
-
|
|
4111
|
+
fs6.writeFileSync(machineIdPath, machineId, "utf-8");
|
|
4083
4112
|
} catch (error) {
|
|
4084
4113
|
console.error("Warning: Could not save machine ID to disk:", error);
|
|
4085
4114
|
}
|
|
@@ -4088,7 +4117,7 @@ async function getMachineId() {
|
|
|
4088
4117
|
function getHardwareUUID() {
|
|
4089
4118
|
try {
|
|
4090
4119
|
if (process.platform === "darwin") {
|
|
4091
|
-
const output = (0,
|
|
4120
|
+
const output = (0, import_child_process4.execSync)(
|
|
4092
4121
|
`ioreg -d2 -c IOPlatformExpertDevice | awk -F\\" '/IOPlatformUUID/{print $(NF-1)}'`,
|
|
4093
4122
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4094
4123
|
).trim();
|
|
@@ -4096,20 +4125,20 @@ function getHardwareUUID() {
|
|
|
4096
4125
|
return output;
|
|
4097
4126
|
}
|
|
4098
4127
|
} else if (process.platform === "linux") {
|
|
4099
|
-
if (
|
|
4100
|
-
const machineId =
|
|
4128
|
+
if (fs6.existsSync("/etc/machine-id")) {
|
|
4129
|
+
const machineId = fs6.readFileSync("/etc/machine-id", "utf-8").trim();
|
|
4101
4130
|
if (machineId && machineId.length > 0) {
|
|
4102
4131
|
return machineId;
|
|
4103
4132
|
}
|
|
4104
4133
|
}
|
|
4105
|
-
if (
|
|
4106
|
-
const dbusId =
|
|
4134
|
+
if (fs6.existsSync("/var/lib/dbus/machine-id")) {
|
|
4135
|
+
const dbusId = fs6.readFileSync("/var/lib/dbus/machine-id", "utf-8").trim();
|
|
4107
4136
|
if (dbusId && dbusId.length > 0) {
|
|
4108
4137
|
return dbusId;
|
|
4109
4138
|
}
|
|
4110
4139
|
}
|
|
4111
4140
|
} else if (process.platform === "win32") {
|
|
4112
|
-
const output = (0,
|
|
4141
|
+
const output = (0, import_child_process4.execSync)("wmic csproduct get uuid", {
|
|
4113
4142
|
encoding: "utf-8",
|
|
4114
4143
|
timeout: 5e3
|
|
4115
4144
|
});
|
|
@@ -4548,7 +4577,7 @@ async function monitorAuthorization(apiUrl, deviceCode, expiresIn) {
|
|
|
4548
4577
|
resolve4(false);
|
|
4549
4578
|
}, expiresIn * 1e3);
|
|
4550
4579
|
const url = `${apiUrl}/api/oauth/authorize-stream?device_code=${deviceCode}`;
|
|
4551
|
-
const curlProcess = (0,
|
|
4580
|
+
const curlProcess = (0, import_child_process5.spawn)("curl", ["-N", url]);
|
|
4552
4581
|
let buffer = "";
|
|
4553
4582
|
curlProcess.stdout.on("data", (chunk) => {
|
|
4554
4583
|
buffer += chunk.toString();
|
|
@@ -4652,7 +4681,7 @@ function openBrowser(url) {
|
|
|
4652
4681
|
break;
|
|
4653
4682
|
}
|
|
4654
4683
|
try {
|
|
4655
|
-
(0,
|
|
4684
|
+
(0, import_child_process5.spawn)(command, args, {
|
|
4656
4685
|
detached: true,
|
|
4657
4686
|
stdio: "ignore"
|
|
4658
4687
|
}).unref();
|
|
@@ -4663,17 +4692,17 @@ function openBrowser(url) {
|
|
|
4663
4692
|
async function installGitCredentialHelper(apiUrl) {
|
|
4664
4693
|
try {
|
|
4665
4694
|
const homeDir = os.homedir();
|
|
4666
|
-
const episodaBinDir =
|
|
4667
|
-
const helperPath =
|
|
4668
|
-
|
|
4695
|
+
const episodaBinDir = path8.join(homeDir, ".episoda", "bin");
|
|
4696
|
+
const helperPath = path8.join(episodaBinDir, "git-credential-episoda");
|
|
4697
|
+
fs7.mkdirSync(episodaBinDir, { recursive: true });
|
|
4669
4698
|
const scriptContent = generateCredentialHelperScript(apiUrl);
|
|
4670
|
-
|
|
4699
|
+
fs7.writeFileSync(helperPath, scriptContent, { mode: 493 });
|
|
4671
4700
|
try {
|
|
4672
|
-
|
|
4701
|
+
fs7.accessSync(helperPath, fs7.constants.X_OK);
|
|
4673
4702
|
} catch {
|
|
4674
4703
|
}
|
|
4675
4704
|
try {
|
|
4676
|
-
const allHelpers = (0,
|
|
4705
|
+
const allHelpers = (0, import_child_process5.execSync)("git config --global --get-all credential.helper", {
|
|
4677
4706
|
encoding: "utf8",
|
|
4678
4707
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4679
4708
|
}).trim().split("\n");
|
|
@@ -4682,7 +4711,7 @@ async function installGitCredentialHelper(apiUrl) {
|
|
|
4682
4711
|
}
|
|
4683
4712
|
} catch {
|
|
4684
4713
|
}
|
|
4685
|
-
(0,
|
|
4714
|
+
(0, import_child_process5.execSync)(`git config --global --add credential.helper "${helperPath}"`, {
|
|
4686
4715
|
encoding: "utf8",
|
|
4687
4716
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4688
4717
|
});
|
|
@@ -4700,19 +4729,19 @@ function updateShellProfile(binDir) {
|
|
|
4700
4729
|
}
|
|
4701
4730
|
const homeDir = os.homedir();
|
|
4702
4731
|
const profiles = [
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4732
|
+
path8.join(homeDir, ".bashrc"),
|
|
4733
|
+
path8.join(homeDir, ".zshrc"),
|
|
4734
|
+
path8.join(homeDir, ".profile")
|
|
4706
4735
|
];
|
|
4707
4736
|
const exportLine = `export PATH="${binDir}:$PATH" # Added by episoda auth`;
|
|
4708
4737
|
for (const profile of profiles) {
|
|
4709
4738
|
try {
|
|
4710
|
-
if (
|
|
4711
|
-
const content =
|
|
4739
|
+
if (fs7.existsSync(profile)) {
|
|
4740
|
+
const content = fs7.readFileSync(profile, "utf8");
|
|
4712
4741
|
if (content.includes(".episoda/bin")) {
|
|
4713
4742
|
continue;
|
|
4714
4743
|
}
|
|
4715
|
-
|
|
4744
|
+
fs7.appendFileSync(profile, `
|
|
4716
4745
|
# Episoda CLI
|
|
4717
4746
|
${exportLine}
|
|
4718
4747
|
`);
|
|
@@ -4724,9 +4753,9 @@ ${exportLine}
|
|
|
4724
4753
|
|
|
4725
4754
|
// src/commands/connect.ts
|
|
4726
4755
|
var os2 = __toESM(require("os"));
|
|
4727
|
-
var
|
|
4728
|
-
var
|
|
4729
|
-
var
|
|
4756
|
+
var fs8 = __toESM(require("fs"));
|
|
4757
|
+
var path9 = __toESM(require("path"));
|
|
4758
|
+
var import_child_process6 = require("child_process");
|
|
4730
4759
|
var import_core7 = __toESM(require_dist());
|
|
4731
4760
|
async function connectCommand(options) {
|
|
4732
4761
|
const { code } = options;
|
|
@@ -4800,13 +4829,13 @@ async function exchangeUserCode(apiUrl, userCode, machineId) {
|
|
|
4800
4829
|
async function installGitCredentialHelper2(apiUrl) {
|
|
4801
4830
|
try {
|
|
4802
4831
|
const homeDir = os2.homedir();
|
|
4803
|
-
const episodaBinDir =
|
|
4804
|
-
const helperPath =
|
|
4805
|
-
|
|
4832
|
+
const episodaBinDir = path9.join(homeDir, ".episoda", "bin");
|
|
4833
|
+
const helperPath = path9.join(episodaBinDir, "git-credential-episoda");
|
|
4834
|
+
fs8.mkdirSync(episodaBinDir, { recursive: true });
|
|
4806
4835
|
const scriptContent = generateCredentialHelperScript(apiUrl);
|
|
4807
|
-
|
|
4836
|
+
fs8.writeFileSync(helperPath, scriptContent, { mode: 493 });
|
|
4808
4837
|
try {
|
|
4809
|
-
const allHelpers = (0,
|
|
4838
|
+
const allHelpers = (0, import_child_process6.execSync)("git config --global --get-all credential.helper", {
|
|
4810
4839
|
encoding: "utf8",
|
|
4811
4840
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4812
4841
|
}).trim().split("\n");
|
|
@@ -4815,7 +4844,7 @@ async function installGitCredentialHelper2(apiUrl) {
|
|
|
4815
4844
|
}
|
|
4816
4845
|
} catch {
|
|
4817
4846
|
}
|
|
4818
|
-
(0,
|
|
4847
|
+
(0, import_child_process6.execSync)(`git config --global --add credential.helper "${helperPath}"`, {
|
|
4819
4848
|
encoding: "utf8",
|
|
4820
4849
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4821
4850
|
});
|
|
@@ -4833,19 +4862,19 @@ function updateShellProfile2(binDir) {
|
|
|
4833
4862
|
}
|
|
4834
4863
|
const homeDir = os2.homedir();
|
|
4835
4864
|
const profiles = [
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4865
|
+
path9.join(homeDir, ".bashrc"),
|
|
4866
|
+
path9.join(homeDir, ".zshrc"),
|
|
4867
|
+
path9.join(homeDir, ".profile")
|
|
4839
4868
|
];
|
|
4840
4869
|
const exportLine = `export PATH="${binDir}:$PATH" # Added by episoda`;
|
|
4841
4870
|
for (const profile of profiles) {
|
|
4842
4871
|
try {
|
|
4843
|
-
if (
|
|
4844
|
-
const content =
|
|
4872
|
+
if (fs8.existsSync(profile)) {
|
|
4873
|
+
const content = fs8.readFileSync(profile, "utf8");
|
|
4845
4874
|
if (content.includes(".episoda/bin")) {
|
|
4846
4875
|
continue;
|
|
4847
4876
|
}
|
|
4848
|
-
|
|
4877
|
+
fs8.appendFileSync(profile, `
|
|
4849
4878
|
# Episoda CLI
|
|
4850
4879
|
${exportLine}
|
|
4851
4880
|
`);
|
|
@@ -5036,25 +5065,24 @@ async function stopCommand(options = {}) {
|
|
|
5036
5065
|
}
|
|
5037
5066
|
|
|
5038
5067
|
// src/commands/clone.ts
|
|
5039
|
-
var
|
|
5040
|
-
var
|
|
5041
|
-
var import_child_process6 = require("child_process");
|
|
5068
|
+
var fs10 = __toESM(require("fs"));
|
|
5069
|
+
var path11 = __toESM(require("path"));
|
|
5042
5070
|
var import_core10 = __toESM(require_dist());
|
|
5043
5071
|
|
|
5044
5072
|
// src/daemon/project-tracker.ts
|
|
5045
|
-
var
|
|
5046
|
-
var
|
|
5073
|
+
var fs9 = __toESM(require("fs"));
|
|
5074
|
+
var path10 = __toESM(require("path"));
|
|
5047
5075
|
var import_core9 = __toESM(require_dist());
|
|
5048
5076
|
function getProjectsFilePath() {
|
|
5049
|
-
return
|
|
5077
|
+
return path10.join((0, import_core9.getConfigDir)(), "projects.json");
|
|
5050
5078
|
}
|
|
5051
5079
|
function readProjects() {
|
|
5052
5080
|
const projectsPath = getProjectsFilePath();
|
|
5053
5081
|
try {
|
|
5054
|
-
if (!
|
|
5082
|
+
if (!fs9.existsSync(projectsPath)) {
|
|
5055
5083
|
return { projects: [] };
|
|
5056
5084
|
}
|
|
5057
|
-
const content =
|
|
5085
|
+
const content = fs9.readFileSync(projectsPath, "utf-8");
|
|
5058
5086
|
const data = JSON.parse(content);
|
|
5059
5087
|
if (!data.projects || !Array.isArray(data.projects)) {
|
|
5060
5088
|
console.warn("Invalid projects.json structure, resetting");
|
|
@@ -5069,11 +5097,11 @@ function readProjects() {
|
|
|
5069
5097
|
function writeProjects(data) {
|
|
5070
5098
|
const projectsPath = getProjectsFilePath();
|
|
5071
5099
|
try {
|
|
5072
|
-
const dir =
|
|
5073
|
-
if (!
|
|
5074
|
-
|
|
5100
|
+
const dir = path10.dirname(projectsPath);
|
|
5101
|
+
if (!fs9.existsSync(dir)) {
|
|
5102
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
5075
5103
|
}
|
|
5076
|
-
|
|
5104
|
+
fs9.writeFileSync(projectsPath, JSON.stringify(data, null, 2), "utf-8");
|
|
5077
5105
|
} catch (error) {
|
|
5078
5106
|
throw new Error(`Failed to write projects.json: ${error}`);
|
|
5079
5107
|
}
|
|
@@ -5097,7 +5125,7 @@ function addProject2(projectId, projectPath, options) {
|
|
|
5097
5125
|
console.log(`[ProjectTracker] Replacing project entry: ${existingById.path} -> ${projectPath}`);
|
|
5098
5126
|
data.projects.splice(existingByIdIndex, 1);
|
|
5099
5127
|
}
|
|
5100
|
-
const projectName =
|
|
5128
|
+
const projectName = path10.basename(projectPath);
|
|
5101
5129
|
const newProject = {
|
|
5102
5130
|
id: projectId,
|
|
5103
5131
|
path: projectPath,
|
|
@@ -5131,9 +5159,9 @@ async function cloneCommand(slugArg, options = {}) {
|
|
|
5131
5159
|
}
|
|
5132
5160
|
const apiUrl = options.apiUrl || config.api_url || "https://episoda.dev";
|
|
5133
5161
|
const projectPath = getProjectPath(workspaceSlug, projectSlug);
|
|
5134
|
-
if (
|
|
5135
|
-
const bareRepoPath =
|
|
5136
|
-
if (
|
|
5162
|
+
if (fs10.existsSync(projectPath)) {
|
|
5163
|
+
const bareRepoPath = path11.join(projectPath, ".bare");
|
|
5164
|
+
if (fs10.existsSync(bareRepoPath)) {
|
|
5137
5165
|
status.warning(`Project already cloned at ${projectPath}`);
|
|
5138
5166
|
status.info("");
|
|
5139
5167
|
status.info("Next steps:");
|
|
@@ -5165,7 +5193,7 @@ Please configure a repository in the project settings on episoda.dev.`
|
|
|
5165
5193
|
status.info("");
|
|
5166
5194
|
status.info("Creating project directory...");
|
|
5167
5195
|
const episodaRoot = getEpisodaRoot();
|
|
5168
|
-
|
|
5196
|
+
fs10.mkdirSync(projectPath, { recursive: true });
|
|
5169
5197
|
status.success(`\u2713 Created ${projectPath}`);
|
|
5170
5198
|
status.info("Cloning repository (bare)...");
|
|
5171
5199
|
try {
|
|
@@ -5203,9 +5231,9 @@ Please configure a repository in the project settings on episoda.dev.`
|
|
|
5203
5231
|
status.info(" 3. episoda checkout {moduleUid} # e.g., episoda checkout EP100");
|
|
5204
5232
|
status.info("");
|
|
5205
5233
|
} catch (error) {
|
|
5206
|
-
if (
|
|
5234
|
+
if (fs10.existsSync(projectPath)) {
|
|
5207
5235
|
try {
|
|
5208
|
-
|
|
5236
|
+
fs10.rmSync(projectPath, { recursive: true, force: true });
|
|
5209
5237
|
} catch {
|
|
5210
5238
|
}
|
|
5211
5239
|
}
|
|
@@ -5278,20 +5306,6 @@ ${errorBody}`
|
|
|
5278
5306
|
}
|
|
5279
5307
|
return data;
|
|
5280
5308
|
}
|
|
5281
|
-
async function extractBootstrapScripts(bareRepoPath, projectPath) {
|
|
5282
|
-
const scriptsDir = path10.join(projectPath, ".episoda", "scripts");
|
|
5283
|
-
fs9.mkdirSync(scriptsDir, { recursive: true });
|
|
5284
|
-
try {
|
|
5285
|
-
const scriptContent = (0, import_child_process6.execSync)(
|
|
5286
|
-
`git --git-dir="${bareRepoPath}" show main:scripts/api-helper.sh`,
|
|
5287
|
-
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
5288
|
-
);
|
|
5289
|
-
const scriptPath = path10.join(scriptsDir, "api-helper.sh");
|
|
5290
|
-
fs9.writeFileSync(scriptPath, scriptContent, { mode: 493 });
|
|
5291
|
-
} catch (error) {
|
|
5292
|
-
console.log("[clone] Could not extract api-helper.sh:", error);
|
|
5293
|
-
}
|
|
5294
|
-
}
|
|
5295
5309
|
|
|
5296
5310
|
// src/commands/checkout.ts
|
|
5297
5311
|
var import_core11 = __toESM(require_dist());
|
|
@@ -5471,7 +5485,7 @@ async function updateModuleCheckout(apiUrl, moduleId, accessToken, branchName) {
|
|
|
5471
5485
|
}
|
|
5472
5486
|
|
|
5473
5487
|
// src/commands/release.ts
|
|
5474
|
-
var
|
|
5488
|
+
var path12 = __toESM(require("path"));
|
|
5475
5489
|
var import_core12 = __toESM(require_dist());
|
|
5476
5490
|
async function releaseCommand(moduleUid, options = {}) {
|
|
5477
5491
|
if (!moduleUid || !moduleUid.match(/^EP\d+$/)) {
|
|
@@ -5518,7 +5532,7 @@ Commit or stash your changes first, or use --force to discard them.`
|
|
|
5518
5532
|
);
|
|
5519
5533
|
}
|
|
5520
5534
|
}
|
|
5521
|
-
const currentPath =
|
|
5535
|
+
const currentPath = path12.resolve(process.cwd());
|
|
5522
5536
|
if (currentPath.startsWith(existing.worktreePath)) {
|
|
5523
5537
|
status.warning("You are inside the worktree being released.");
|
|
5524
5538
|
status.info(`Please cd to ${projectRoot} first.`);
|
|
@@ -5592,8 +5606,8 @@ async function updateModuleRelease(apiUrl, projectId, workspaceSlug, moduleUid,
|
|
|
5592
5606
|
}
|
|
5593
5607
|
|
|
5594
5608
|
// src/commands/list.ts
|
|
5595
|
-
var
|
|
5596
|
-
var
|
|
5609
|
+
var fs11 = __toESM(require("fs"));
|
|
5610
|
+
var path13 = __toESM(require("path"));
|
|
5597
5611
|
var import_chalk2 = __toESM(require("chalk"));
|
|
5598
5612
|
var import_core13 = __toESM(require_dist());
|
|
5599
5613
|
async function listCommand(subcommand, options = {}) {
|
|
@@ -5605,7 +5619,7 @@ async function listCommand(subcommand, options = {}) {
|
|
|
5605
5619
|
}
|
|
5606
5620
|
async function listProjects(options) {
|
|
5607
5621
|
const episodaRoot = getEpisodaRoot();
|
|
5608
|
-
if (!
|
|
5622
|
+
if (!fs11.existsSync(episodaRoot)) {
|
|
5609
5623
|
status.info("No projects cloned yet.");
|
|
5610
5624
|
status.info("");
|
|
5611
5625
|
status.info("Clone a project with:");
|
|
@@ -5613,12 +5627,12 @@ async function listProjects(options) {
|
|
|
5613
5627
|
return;
|
|
5614
5628
|
}
|
|
5615
5629
|
const projects = [];
|
|
5616
|
-
const workspaces =
|
|
5630
|
+
const workspaces = fs11.readdirSync(episodaRoot, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("."));
|
|
5617
5631
|
for (const workspace of workspaces) {
|
|
5618
|
-
const workspacePath =
|
|
5619
|
-
const projectDirs =
|
|
5632
|
+
const workspacePath = path13.join(episodaRoot, workspace.name);
|
|
5633
|
+
const projectDirs = fs11.readdirSync(workspacePath, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("."));
|
|
5620
5634
|
for (const projectDir of projectDirs) {
|
|
5621
|
-
const projectPath =
|
|
5635
|
+
const projectPath = path13.join(workspacePath, projectDir.name);
|
|
5622
5636
|
if (await isWorktreeProject(projectPath)) {
|
|
5623
5637
|
const manager = new WorktreeManager(projectPath);
|
|
5624
5638
|
await manager.initialize();
|