zapdev 0.7.1 → 0.9.0
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/README.md +13 -0
- package/dist/cli.js +69 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,8 @@ zapdev commit
|
|
|
43
43
|
zapdev commit -t feat # force the type; the model still writes scope + description
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
Pushing is optimistic — no preliminary fetch, so the common case stays a single round-trip. If the push is rejected because the branch is behind its upstream, zapdev automatically runs `git pull --rebase` and retries the push once — no prompt, in every mode. A rebase conflict stops before pushing so you can resolve it, then re-run.
|
|
47
|
+
|
|
46
48
|
Without a TTY (piped / CI), it commits automatically and only pushes when `--push` is set.
|
|
47
49
|
|
|
48
50
|
### `zapdev reset`
|
|
@@ -65,6 +67,17 @@ zapdev reset -t dev # switch each repo to `dev` (or principal if absent
|
|
|
65
67
|
|
|
66
68
|
Deletion is permanent: branches via `git branch -D` (force), worktrees via `git worktree remove --force`. Worktrees are removed first so the branches they held become deletable. Without a TTY, pass `--yes` — otherwise the destructive step is refused. `node_modules` is never scanned.
|
|
67
69
|
|
|
70
|
+
## Shell aliases
|
|
71
|
+
|
|
72
|
+
`--yes` skips every prompt, which is exactly what you want behind a short alias. Two that pay off daily — add them to `~/.zshrc` or `~/.bashrc`:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
alias commit="zapdev commit --yes" # stage → generate message → commit, no prompts
|
|
76
|
+
alias git-reset="zapdev reset --yes --principal --pull" # switch each repo to its principal branch, wipe the rest, then pull
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`commit` collapses the whole stage → message → commit flow into one word. `git-reset` brings a workspace back to a clean principal state in one shot — point it at a parent directory to reset every child repo at once.
|
|
80
|
+
|
|
68
81
|
## Configuration
|
|
69
82
|
|
|
70
83
|
| Variable | Default | Description |
|
package/dist/cli.js
CHANGED
|
@@ -1718,7 +1718,7 @@ function _getBuiltinFlags(long, short, userNames, userAliases) {
|
|
|
1718
1718
|
// package.json
|
|
1719
1719
|
var package_default = {
|
|
1720
1720
|
name: "zapdev",
|
|
1721
|
-
version: "0.
|
|
1721
|
+
version: "0.9.0",
|
|
1722
1722
|
description: "Fast, performant and lightweight git chores and dev tools using your terminal and your own local LLM.",
|
|
1723
1723
|
type: "module",
|
|
1724
1724
|
bin: {
|
|
@@ -2222,6 +2222,16 @@ async function push() {
|
|
|
2222
2222
|
async function pushSetUpstream(branch) {
|
|
2223
2223
|
await git(["push", "-u", "origin", branch]);
|
|
2224
2224
|
}
|
|
2225
|
+
async function pullRebase() {
|
|
2226
|
+
await git(["pull", "--rebase"]);
|
|
2227
|
+
}
|
|
2228
|
+
async function fetchRemote() {
|
|
2229
|
+
await git(["fetch"]);
|
|
2230
|
+
}
|
|
2231
|
+
async function behindCount() {
|
|
2232
|
+
const out = await tryGit(["rev-list", "--count", `HEAD..${UPSTREAM_REF}`]);
|
|
2233
|
+
return out === null ? 0 : Number(out.trim()) || 0;
|
|
2234
|
+
}
|
|
2225
2235
|
async function findRepos(path) {
|
|
2226
2236
|
if (await isGitRepo(path)) return [path];
|
|
2227
2237
|
const entries = await readdir(path, { withFileTypes: true }).catch(() => null);
|
|
@@ -2467,16 +2477,8 @@ var commitCommand = defineCommand({
|
|
|
2467
2477
|
shouldPush = answer;
|
|
2468
2478
|
}
|
|
2469
2479
|
if (shouldPush) {
|
|
2470
|
-
const
|
|
2471
|
-
|
|
2472
|
-
try {
|
|
2473
|
-
const [upstream, branch] = await Promise.all([hasUpstream(), currentBranch()]);
|
|
2474
|
-
if (upstream) await push();
|
|
2475
|
-
else await pushSetUpstream(branch);
|
|
2476
|
-
pushLoader?.stop("\u2713 Pushed");
|
|
2477
|
-
} catch (error) {
|
|
2478
|
-
pushLoader?.error("Push failed");
|
|
2479
|
-
log.error(`Push failed: ${errorMessage(error)}`);
|
|
2480
|
+
const pushed = await pushOptimistic(interactive);
|
|
2481
|
+
if (!pushed) {
|
|
2480
2482
|
process.exitCode = 1;
|
|
2481
2483
|
return;
|
|
2482
2484
|
}
|
|
@@ -2484,6 +2486,62 @@ var commitCommand = defineCommand({
|
|
|
2484
2486
|
if (interactive) outro("Done.");
|
|
2485
2487
|
}
|
|
2486
2488
|
});
|
|
2489
|
+
async function rebaseOnUpstream(interactive) {
|
|
2490
|
+
const loader = interactive ? spinner() : void 0;
|
|
2491
|
+
loader?.start("Pulling --rebase");
|
|
2492
|
+
try {
|
|
2493
|
+
await pullRebase();
|
|
2494
|
+
loader?.stop("\u2713 Rebased on upstream");
|
|
2495
|
+
return true;
|
|
2496
|
+
} catch (error) {
|
|
2497
|
+
loader?.error("Rebase failed");
|
|
2498
|
+
log.error(`Rebase failed (resolve conflicts, then push): ${errorMessage(error)}`);
|
|
2499
|
+
return false;
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
async function pushOptimistic(interactive) {
|
|
2503
|
+
const [upstream, branch] = await Promise.all([hasUpstream(), currentBranch()]);
|
|
2504
|
+
const doPush = () => upstream ? push() : pushSetUpstream(branch);
|
|
2505
|
+
const first = await tryPush(interactive, doPush);
|
|
2506
|
+
if (first.ok) return true;
|
|
2507
|
+
if (upstream && await isBehind(interactive)) {
|
|
2508
|
+
if (!await rebaseOnUpstream(interactive)) return false;
|
|
2509
|
+
const retry = await tryPush(interactive, doPush);
|
|
2510
|
+
if (retry.ok) return true;
|
|
2511
|
+
log.error(`Push failed: ${errorMessage(retry.error)}`);
|
|
2512
|
+
return false;
|
|
2513
|
+
}
|
|
2514
|
+
log.error(`Push failed: ${errorMessage(first.error)}`);
|
|
2515
|
+
return false;
|
|
2516
|
+
}
|
|
2517
|
+
async function tryPush(interactive, doPush) {
|
|
2518
|
+
const loader = interactive ? spinner() : void 0;
|
|
2519
|
+
loader?.start("Pushing");
|
|
2520
|
+
try {
|
|
2521
|
+
await doPush();
|
|
2522
|
+
loader?.stop("\u2713 Pushed");
|
|
2523
|
+
return { ok: true };
|
|
2524
|
+
} catch (error) {
|
|
2525
|
+
loader?.error("Push failed");
|
|
2526
|
+
return { ok: false, error };
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
async function isBehind(interactive) {
|
|
2530
|
+
const loader = interactive ? spinner() : void 0;
|
|
2531
|
+
loader?.start("Checking upstream");
|
|
2532
|
+
try {
|
|
2533
|
+
await fetchRemote();
|
|
2534
|
+
const behind = await behindCount();
|
|
2535
|
+
loader?.stop(
|
|
2536
|
+
behind > 0 ? `Behind upstream by ${behind} commit${behind > 1 ? "s" : ""}` : "Up to date with upstream"
|
|
2537
|
+
);
|
|
2538
|
+
return behind > 0;
|
|
2539
|
+
} catch (error) {
|
|
2540
|
+
loader?.error("Could not check upstream");
|
|
2541
|
+
log.warn(`Could not check upstream: ${errorMessage(error)}`);
|
|
2542
|
+
return false;
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2487
2545
|
|
|
2488
2546
|
// src/commands/reset.ts
|
|
2489
2547
|
var CANCEL = /* @__PURE__ */ Symbol("cancel");
|