@ferueda/grove-cli 0.1.0 → 0.1.2
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/cli.d.ts +1 -0
- package/dist/cli.js +21 -3
- package/dist/commands/acquire.d.ts.map +1 -1
- package/dist/commands/acquire.js +5 -4
- package/dist/commands/destroy.d.ts.map +1 -1
- package/dist/commands/destroy.js +3 -4
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +2 -2
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +7 -2
- package/dist/error-handler.d.ts +3 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +30 -0
- package/package.json +9 -2
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { Command } from "commander";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { handleError, setDebug } from "./error-handler.js";
|
|
2
5
|
import { acquireCmd } from "./commands/acquire.js";
|
|
3
6
|
import { releaseCmd } from "./commands/release.js";
|
|
4
7
|
import { statusCmd } from "./commands/status.js";
|
|
5
8
|
import { destroyCmd, destroyAllCmd } from "./commands/destroy.js";
|
|
9
|
+
process.on("uncaughtException", (err) => {
|
|
10
|
+
console.error(pc.red(`Fatal: ${err.message}`));
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
});
|
|
13
|
+
process.on("unhandledRejection", (reason) => {
|
|
14
|
+
console.error(pc.red(`Unhandled rejection: ${reason}`));
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
});
|
|
6
17
|
const program = new Command();
|
|
7
18
|
program
|
|
8
19
|
.name("grove")
|
|
9
20
|
.description("CLI for Grove - A programmatic git worktree pool manager")
|
|
10
|
-
.version("0.1.0")
|
|
21
|
+
.version("0.1.0")
|
|
22
|
+
.option("--debug", "Show verbose error output including stack traces")
|
|
23
|
+
.hook("preAction", (thisCommand) => {
|
|
24
|
+
const opts = thisCommand.optsWithGlobals();
|
|
25
|
+
if (opts.debug)
|
|
26
|
+
setDebug(true);
|
|
27
|
+
});
|
|
11
28
|
program.addCommand(acquireCmd);
|
|
12
29
|
program.addCommand(releaseCmd);
|
|
13
30
|
program.addCommand(statusCmd);
|
|
@@ -17,6 +34,7 @@ try {
|
|
|
17
34
|
await program.parseAsync(process.argv);
|
|
18
35
|
}
|
|
19
36
|
catch (err) {
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
if (process.exitCode !== 1) {
|
|
38
|
+
handleError(err);
|
|
39
|
+
}
|
|
22
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acquire.d.ts","sourceRoot":"","sources":["../../src/commands/acquire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"acquire.d.ts","sourceRoot":"","sources":["../../src/commands/acquire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,UAAU,SA4CnB,CAAC"}
|
package/dist/commands/acquire.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { loadGrove } from "../utils.js";
|
|
3
|
+
import { handleError } from "../error-handler.js";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
4
5
|
import pc from "picocolors";
|
|
5
6
|
export const acquireCmd = new Command("acquire")
|
|
@@ -29,8 +30,9 @@ export const acquireCmd = new Command("acquire")
|
|
|
29
30
|
await grove.release(slot.path);
|
|
30
31
|
console.error(pc.green("🌳 Worktree returned to pool."));
|
|
31
32
|
}
|
|
32
|
-
catch (
|
|
33
|
-
|
|
33
|
+
catch (releaseErr) {
|
|
34
|
+
const msg = releaseErr instanceof Error ? releaseErr.message : String(releaseErr);
|
|
35
|
+
console.error(pc.red(`🌳 Warning: failed to release worktree: ${msg}`));
|
|
34
36
|
}
|
|
35
37
|
process.exit(code ?? 0);
|
|
36
38
|
});
|
|
@@ -41,7 +43,6 @@ export const acquireCmd = new Command("acquire")
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
catch (err) {
|
|
44
|
-
|
|
45
|
-
process.exit(1);
|
|
46
|
+
handleError(err);
|
|
46
47
|
}
|
|
47
48
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../src/commands/destroy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../src/commands/destroy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,UAAU,SAanB,CAAC;AAEL,eAAO,MAAM,aAAa,SAYtB,CAAC"}
|
package/dist/commands/destroy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { loadGrove } from "../utils.js";
|
|
3
|
+
import { handleError } from "../error-handler.js";
|
|
3
4
|
import pc from "picocolors";
|
|
4
5
|
export const destroyCmd = new Command("destroy")
|
|
5
6
|
.description("Destroy a specific worktree from the pool")
|
|
@@ -13,8 +14,7 @@ export const destroyCmd = new Command("destroy")
|
|
|
13
14
|
console.error(pc.green(`🌳 Destroyed worktree at ${worktreePath}`));
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
16
|
-
|
|
17
|
-
process.exit(1);
|
|
17
|
+
handleError(err);
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
export const destroyAllCmd = new Command("destroy-all")
|
|
@@ -28,7 +28,6 @@ export const destroyAllCmd = new Command("destroy-all")
|
|
|
28
28
|
console.error(pc.green("🌳 Destroyed all worktrees in the pool."));
|
|
29
29
|
}
|
|
30
30
|
catch (err) {
|
|
31
|
-
|
|
32
|
-
process.exit(1);
|
|
31
|
+
handleError(err);
|
|
33
32
|
}
|
|
34
33
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../src/commands/release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../src/commands/release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,UAAU,SAcnB,CAAC"}
|
package/dist/commands/release.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { loadGrove } from "../utils.js";
|
|
3
|
+
import { handleError } from "../error-handler.js";
|
|
3
4
|
import pc from "picocolors";
|
|
4
5
|
export const releaseCmd = new Command("release")
|
|
5
6
|
.description("Release a worktree back to the pool")
|
|
@@ -13,7 +14,6 @@ export const releaseCmd = new Command("release")
|
|
|
13
14
|
console.error(pc.green("🌳 Worktree returned to pool."));
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
16
|
-
|
|
17
|
-
process.exit(1);
|
|
17
|
+
handleError(err);
|
|
18
18
|
}
|
|
19
19
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,SAAS,SAqDlB,CAAC"}
|
package/dist/commands/status.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { loadGrove } from "../utils.js";
|
|
3
|
+
import { handleError } from "../error-handler.js";
|
|
3
4
|
import pc from "picocolors";
|
|
4
5
|
export const statusCmd = new Command("status")
|
|
5
6
|
.description("Show the status of all worktrees in the pool")
|
|
6
7
|
.option("-r, --repo <path>", "Path to repository root")
|
|
8
|
+
.option("--json", "Output status as JSON")
|
|
7
9
|
.action(async (options) => {
|
|
8
10
|
try {
|
|
9
11
|
const grove = await loadGrove({ repo: options.repo });
|
|
10
12
|
const trees = await grove.list();
|
|
13
|
+
if (options.json) {
|
|
14
|
+
process.stdout.write(JSON.stringify(trees, null, 2) + "\n");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
11
17
|
if (trees.length === 0) {
|
|
12
18
|
console.log("🌳 No worktrees in pool.");
|
|
13
19
|
return;
|
|
@@ -41,7 +47,6 @@ export const statusCmd = new Command("status")
|
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
catch (err) {
|
|
44
|
-
|
|
45
|
-
process.exit(1);
|
|
50
|
+
handleError(err);
|
|
46
51
|
}
|
|
47
52
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"AAKA,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAsB/C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { GroveError, GitCommandError } from "@ferueda/grove";
|
|
3
|
+
let debugEnabled = false;
|
|
4
|
+
export function setDebug(enabled) {
|
|
5
|
+
debugEnabled = enabled;
|
|
6
|
+
}
|
|
7
|
+
export function handleError(err) {
|
|
8
|
+
if (err instanceof GroveError) {
|
|
9
|
+
console.error(pc.red(`[${err.code}] ${err.message}`));
|
|
10
|
+
if (debugEnabled) {
|
|
11
|
+
if (err instanceof GitCommandError && err.stderr) {
|
|
12
|
+
console.error(pc.gray(`git stderr: ${err.stderr}`));
|
|
13
|
+
}
|
|
14
|
+
if (err.stack) {
|
|
15
|
+
console.error(pc.gray(err.stack));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else if (err instanceof Error) {
|
|
20
|
+
console.error(pc.red(err.message));
|
|
21
|
+
if (debugEnabled && err.stack) {
|
|
22
|
+
console.error(pc.gray(err.stack));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.error(pc.red(String(err)));
|
|
27
|
+
}
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferueda/grove-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/ferueda/grove.git"
|
|
7
|
+
},
|
|
4
8
|
"files": [
|
|
5
9
|
"dist"
|
|
6
10
|
],
|
|
7
11
|
"type": "module",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
8
15
|
"bin": {
|
|
9
16
|
"grove": "./dist/cli.js"
|
|
10
17
|
},
|
|
@@ -12,7 +19,7 @@
|
|
|
12
19
|
"commander": "^13.0.0",
|
|
13
20
|
"execa": "^9.6.0",
|
|
14
21
|
"picocolors": "^1.1.0",
|
|
15
|
-
"@ferueda/grove": "0.1.
|
|
22
|
+
"@ferueda/grove": "0.1.2"
|
|
16
23
|
},
|
|
17
24
|
"scripts": {
|
|
18
25
|
"build": "tsgo -p tsconfig.json"
|