gh-manager-cli 1.42.0 → 1.44.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/CHANGELOG.md +14 -0
- package/README.md +11 -9
- package/dist/{chunk-UOGN2QJU.js → chunk-MKIUBPVD.js} +119 -1
- package/dist/{github-ASGTM4ZX.js → github-6HD7I2UI.js} +5 -1
- package/dist/index.js +632 -407
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.44.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.43.0...v1.44.0) (2026-06-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* theme-aware selected-row highlight with better contrast (SWR-364) ([#59](https://github.com/wiiiimm/gh-manager-cli/issues/59)) ([1b71cb2](https://github.com/wiiiimm/gh-manager-cli/commit/1b71cb2144b0773bb0d9538e3f30141e53346890)), closes [#1f4a57](https://github.com/wiiiimm/gh-manager-cli/issues/1f4a57) [#11294d](https://github.com/wiiiimm/gh-manager-cli/issues/11294d) [#14391f](https://github.com/wiiiimm/gh-manager-cli/issues/14391f) [#333333](https://github.com/wiiiimm/gh-manager-cli/issues/333333)
|
|
7
|
+
|
|
8
|
+
# [1.43.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.42.0...v1.43.0) (2026-06-05)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* fork ahead/behind enrichment, jump-to-upstream (P), and open-in-browser chooser (SWR-362) [semantic pr title] ([#53](https://github.com/wiiiimm/gh-manager-cli/issues/53)) ([ffd7b16](https://github.com/wiiiimm/gh-manager-cli/commit/ffd7b1644f7fad93721b6ab7287c0c3a1990f9e6))
|
|
14
|
+
|
|
1
15
|
# [1.42.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.41.0...v1.42.0) (2026-06-05)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -78,23 +78,24 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
|
|
|
78
78
|
- **Fuzzy Search**: Instant typo-tolerant search over the full cached repository set — no network calls in the search path (powered by [fuse.js](https://www.fusejs.io/))
|
|
79
79
|
- **Visibility Filter**: Modal-based visibility filter (All, Public, Private/Internal for enterprise) with smart filtering
|
|
80
80
|
- **Archive Filter**: Toggle-based archive filter (`A` key cycles All → Unarchived → Archived) for quick filtering by archive status
|
|
81
|
-
- **Fork
|
|
81
|
+
- **Fork Ahead/Behind Tracking**: After the background fetch-all completes, forks are enriched with both **ahead** and **behind** commit counts in a separate lightweight pass (batched 5 at a time to avoid rate-limit issues)
|
|
82
82
|
- **Stars Mode**: View and manage starred repositories (personal account only)
|
|
83
83
|
- **Repository Actions**:
|
|
84
84
|
- View detailed info (`I`) - Shows repository metadata, language, size, and timestamps
|
|
85
|
-
- Open in browser (Enter/`O`)
|
|
85
|
+
- Open in browser (Enter/`O`) — for forks a chooser lets you open this repo or the upstream
|
|
86
|
+
- Jump to upstream (`P`) — moves cursor to the parent if loaded; otherwise fetches and shows it
|
|
86
87
|
- Rename repository (`Ctrl+R`) with inline validation and automatic cache update
|
|
87
88
|
- Copy repository URL to clipboard (`C`) with SSH/HTTPS options
|
|
88
89
|
- Delete repository (`Del` or `Backspace`) with secure two-step confirmation
|
|
89
90
|
- Archive/unarchive repositories (`Ctrl+A`) with confirmation prompts
|
|
90
91
|
- Change repository visibility (`Ctrl+V`) - Switch between Public, Private, and Internal (enterprise only)
|
|
91
92
|
- Star/unstar repositories (`Ctrl+S`) - Toggle star status for any repository
|
|
92
|
-
- Sync forks with upstream (`Ctrl+F`) with automatic conflict detection
|
|
93
|
+
- Sync forks with upstream (`Ctrl+F`) with ahead/behind counts and automatic conflict detection
|
|
93
94
|
|
|
94
95
|
### User Interface & Experience
|
|
95
96
|
- **Keyboard Navigation**: Full keyboard control (arrow keys, PageUp/Down, `Ctrl+G`/`G`)
|
|
96
97
|
- **Display Density**: Toggle between compact/cozy/comfy spacing (`T`)
|
|
97
|
-
- **Colour Themes**: Four themes (Default, Ocean, Forest, Monochrome) cycled with `Shift+T`, persisted across restarts
|
|
98
|
+
- **Colour Themes**: Four themes (Default, Ocean, Forest, Monochrome) cycled with `Shift+T`, persisted across restarts; the selected-row highlight is theme-aware and tuned per theme for readable contrast
|
|
98
99
|
- **Visual Indicators**: Fork status, private/internal/archived badges, language colors, visibility status
|
|
99
100
|
- **Enterprise Support**: Full support for GitHub Enterprise with Internal repository visibility
|
|
100
101
|
- **Organization Context**: Switch between personal and organization accounts with ENT badge for enterprise orgs
|
|
@@ -271,17 +272,18 @@ Launch the app, then use the keys below:
|
|
|
271
272
|
- Stars: Number of stars
|
|
272
273
|
- **Sort Direction**: `D` to open sort direction modal (ascending/descending)
|
|
273
274
|
- **Display Density**: `T` to toggle compact/cozy/comfy
|
|
274
|
-
- **Colour Theme**: `Shift+T` to cycle themes (Default → Ocean → Forest → Monochrome); selection persists across restarts
|
|
275
|
-
- **Fork Status**: Always enabled
|
|
275
|
+
- **Colour Theme**: `Shift+T` to cycle themes (Default → Ocean → Forest → Monochrome); selection persists across restarts. Each theme defines its own selected-row highlight (a darker on-theme background) so the highlighted repository stays high-contrast
|
|
276
|
+
- **Fork Status**: Always enabled — shows commits **ahead** and **behind** upstream once enrichment completes (see below)
|
|
276
277
|
- **Visibility Filter**: `V` opens modal (All, Public, Private/Internal for enterprise)
|
|
277
278
|
- **Archive Filter**: `A` toggles archive filter (All → Unarchived → Archived)
|
|
278
279
|
- **Stars Mode**: `Shift+S` (personal account only) to toggle between your own repos and your starred repos
|
|
279
280
|
- Footer hint shows `Shift+S Starred` in normal mode and `Shift+S My Repos` in starred mode
|
|
280
281
|
|
|
281
282
|
### Navigation & Account
|
|
282
|
-
- **Open in browser**: Enter or `O`
|
|
283
|
+
- **Open in browser**: Enter or `O` — non-forks open directly; forks show a chooser (**This repository** / **Parent/upstream**, Esc cancels)
|
|
284
|
+
- **Jump to upstream**: `P` (on a fork) — moves cursor to the parent if it is already loaded; otherwise fetches the parent and shows it in the Info modal
|
|
283
285
|
- **Refresh**: `R`
|
|
284
|
-
- **
|
|
286
|
+
- **Organisation switcher**: `W` to switch between personal account and organisations
|
|
285
287
|
- **Logout**: `Ctrl+L`
|
|
286
288
|
- **Quit**: `Q`
|
|
287
289
|
|
|
@@ -294,7 +296,7 @@ Launch the app, then use the keys below:
|
|
|
294
296
|
- Type confirmation code → confirm (Y/Enter)
|
|
295
297
|
- Cancel: press `C` or Esc
|
|
296
298
|
- **Star/Unstar**: `Ctrl+S` to toggle star status for any repository
|
|
297
|
-
- **Sync fork**: `Ctrl+F` (for forks only, shows
|
|
299
|
+
- **Sync fork**: `Ctrl+F` (for forks only, shows ahead/behind counts and handles conflicts)
|
|
298
300
|
- **Rename repository**: `Ctrl+R` with inline validation
|
|
299
301
|
- **Copy URL**: `C` to copy repository URL to clipboard (SSH/HTTPS options)
|
|
300
302
|
|
|
@@ -1478,6 +1478,122 @@ async function inspectCacheStatus() {
|
|
|
1478
1478
|
`);
|
|
1479
1479
|
}
|
|
1480
1480
|
}
|
|
1481
|
+
async function enrichForksWithAheadBehind(client, forks) {
|
|
1482
|
+
if (forks.length === 0) return [];
|
|
1483
|
+
const results = [];
|
|
1484
|
+
const BATCH_SIZE = 5;
|
|
1485
|
+
for (let batchStart = 0; batchStart < forks.length; batchStart += BATCH_SIZE) {
|
|
1486
|
+
const batch = forks.slice(batchStart, batchStart + BATCH_SIZE);
|
|
1487
|
+
const queryParts = [];
|
|
1488
|
+
const variables = {};
|
|
1489
|
+
batch.forEach((fork, i) => {
|
|
1490
|
+
const [parentOwner, parentName] = fork.parentNameWithOwner.split("/");
|
|
1491
|
+
if (!parentOwner || !parentName) return;
|
|
1492
|
+
const varName = `fid${i}`;
|
|
1493
|
+
variables[varName] = fork.id;
|
|
1494
|
+
const safeOwner = parentOwner.replace(/[^a-zA-Z0-9_.\-]/g, "");
|
|
1495
|
+
const safeName = parentName.replace(/[^a-zA-Z0-9_.\-]/g, "");
|
|
1496
|
+
queryParts.push(`
|
|
1497
|
+
fork${i}: node(id: $${varName}) {
|
|
1498
|
+
... on Repository {
|
|
1499
|
+
id
|
|
1500
|
+
defaultBranchRef {
|
|
1501
|
+
target {
|
|
1502
|
+
... on Commit {
|
|
1503
|
+
history(first: 0) { totalCount }
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
parent${i}: repository(owner: "${safeOwner}", name: "${safeName}") {
|
|
1510
|
+
defaultBranchRef {
|
|
1511
|
+
target {
|
|
1512
|
+
... on Commit {
|
|
1513
|
+
history(first: 0) { totalCount }
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
`);
|
|
1519
|
+
});
|
|
1520
|
+
if (queryParts.length === 0) {
|
|
1521
|
+
batch.forEach((fork) => results.push({ id: fork.id, forkHistoryCount: null, parentHistoryCount: null }));
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
const varDefs = Object.entries(variables).map(([k]) => `$${k}: ID!`).join(", ");
|
|
1525
|
+
const query = `query EnrichForks(${varDefs}) { ${queryParts.join("\n")} }`;
|
|
1526
|
+
try {
|
|
1527
|
+
const res = await client(query, variables);
|
|
1528
|
+
batch.forEach((fork, i) => {
|
|
1529
|
+
const forkNode = res[`fork${i}`];
|
|
1530
|
+
const parentNode = res[`parent${i}`];
|
|
1531
|
+
const forkHistoryCount = forkNode?.defaultBranchRef?.target?.history?.totalCount ?? null;
|
|
1532
|
+
const parentHistoryCount = parentNode?.defaultBranchRef?.target?.history?.totalCount ?? null;
|
|
1533
|
+
results.push({ id: fork.id, forkHistoryCount, parentHistoryCount });
|
|
1534
|
+
});
|
|
1535
|
+
} catch (err) {
|
|
1536
|
+
logger.error("enrichForksWithAheadBehind batch failed", {
|
|
1537
|
+
error: err.message,
|
|
1538
|
+
batchSize: batch.length
|
|
1539
|
+
});
|
|
1540
|
+
batch.forEach((fork) => results.push({ id: fork.id, forkHistoryCount: null, parentHistoryCount: null }));
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return results;
|
|
1544
|
+
}
|
|
1545
|
+
async function fetchRepositoryByOwnerAndName(client, owner, name) {
|
|
1546
|
+
const query = (
|
|
1547
|
+
/* GraphQL */
|
|
1548
|
+
`
|
|
1549
|
+
query GetRepoByOwnerName($owner: String!, $name: String!) {
|
|
1550
|
+
repository(owner: $owner, name: $name) {
|
|
1551
|
+
id
|
|
1552
|
+
name
|
|
1553
|
+
nameWithOwner
|
|
1554
|
+
description
|
|
1555
|
+
pushedAt
|
|
1556
|
+
updatedAt
|
|
1557
|
+
isPrivate
|
|
1558
|
+
isArchived
|
|
1559
|
+
isFork
|
|
1560
|
+
visibility
|
|
1561
|
+
stargazerCount
|
|
1562
|
+
forkCount
|
|
1563
|
+
diskUsage
|
|
1564
|
+
viewerHasStarred
|
|
1565
|
+
owner { __typename login }
|
|
1566
|
+
primaryLanguage { name color }
|
|
1567
|
+
parent {
|
|
1568
|
+
nameWithOwner
|
|
1569
|
+
defaultBranchRef {
|
|
1570
|
+
target {
|
|
1571
|
+
... on Commit {
|
|
1572
|
+
history(first: 0) { totalCount }
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
defaultBranchRef {
|
|
1578
|
+
name
|
|
1579
|
+
target {
|
|
1580
|
+
... on Commit {
|
|
1581
|
+
history(first: 0) { totalCount }
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
`
|
|
1588
|
+
);
|
|
1589
|
+
try {
|
|
1590
|
+
const result = await client(query, { owner, name });
|
|
1591
|
+
return result.repository;
|
|
1592
|
+
} catch (err) {
|
|
1593
|
+
logger.error("fetchRepositoryByOwnerAndName failed", { owner, name, error: err.message });
|
|
1594
|
+
return null;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1481
1597
|
|
|
1482
1598
|
export {
|
|
1483
1599
|
__commonJS,
|
|
@@ -1508,5 +1624,7 @@ export {
|
|
|
1508
1624
|
fetchRestRateLimits,
|
|
1509
1625
|
updateCacheAfterRename,
|
|
1510
1626
|
renameRepositoryById,
|
|
1511
|
-
inspectCacheStatus
|
|
1627
|
+
inspectCacheStatus,
|
|
1628
|
+
enrichForksWithAheadBehind,
|
|
1629
|
+
fetchRepositoryByOwnerAndName
|
|
1512
1630
|
};
|
|
@@ -4,7 +4,9 @@ import {
|
|
|
4
4
|
changeRepositoryVisibility,
|
|
5
5
|
checkOrganizationIsEnterprise,
|
|
6
6
|
deleteRepositoryRest,
|
|
7
|
+
enrichForksWithAheadBehind,
|
|
7
8
|
fetchRepositoryById,
|
|
9
|
+
fetchRepositoryByOwnerAndName,
|
|
8
10
|
fetchRestRateLimits,
|
|
9
11
|
fetchViewerOrganizations,
|
|
10
12
|
fetchViewerReposPage,
|
|
@@ -26,13 +28,15 @@ import {
|
|
|
26
28
|
updateCacheAfterRename,
|
|
27
29
|
updateCacheAfterVisibilityChange,
|
|
28
30
|
updateCacheWithRepository
|
|
29
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-MKIUBPVD.js";
|
|
30
32
|
export {
|
|
31
33
|
archiveRepositoryById,
|
|
32
34
|
changeRepositoryVisibility,
|
|
33
35
|
checkOrganizationIsEnterprise,
|
|
34
36
|
deleteRepositoryRest,
|
|
37
|
+
enrichForksWithAheadBehind,
|
|
35
38
|
fetchRepositoryById,
|
|
39
|
+
fetchRepositoryByOwnerAndName,
|
|
36
40
|
fetchRestRateLimits,
|
|
37
41
|
fetchViewerOrganizations,
|
|
38
42
|
fetchViewerReposPage,
|