gh-manager-cli 1.39.1 → 1.40.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
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.40.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.39.1...v1.40.0) (2026-06-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* background fetch-all pagination with light bulk query ([#50](https://github.com/wiiiimm/gh-manager-cli/issues/50)) ([932deb8](https://github.com/wiiiimm/gh-manager-cli/commit/932deb85736bf999bde3c6f4d9bab02aaece8610))
|
|
7
|
+
|
|
1
8
|
## [1.39.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.39.0...v1.39.1) (2026-06-05)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Interactive terminal app to browse and manage your personal GitHub repositories.
|
|
|
22
22
|
`gh-manager-cli` replaces tedious web clicking with powerful terminal commands:
|
|
23
23
|
|
|
24
24
|
### ❌ GitHub Website Pain Points → ✅ Our Solution
|
|
25
|
-
- **Slow pagination** (
|
|
25
|
+
- **Slow pagination** (page-by-page) → Whole account loaded in the background, browse and search everything instantly
|
|
26
26
|
- **Multiple clicks per action** → Single keypress for any operation
|
|
27
27
|
- **No bulk operations** → Archive, delete, or modify multiple repos at once
|
|
28
28
|
- **Buried settings menus** → Direct keyboard shortcuts for everything
|
|
@@ -73,7 +73,7 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
|
|
|
73
73
|
### Core Repository Management
|
|
74
74
|
- **Authentication**: GitHub OAuth (recommended) or Personal Access Token with secure storage
|
|
75
75
|
- **Repository Listing**: Browse all your personal repositories with metadata (stars, forks, language, etc.)
|
|
76
|
-
- **
|
|
76
|
+
- **Background Fetch-All**: Loads your entire account in the background after the first page, so filtering/sorting/search are instant and complete
|
|
77
77
|
- **Interactive Sorting**: Modal-based sort selection (updated, pushed, name, stars) with modal-based direction selection
|
|
78
78
|
- **Smart Search**: Server-side search through repository names and descriptions (3+ characters)
|
|
79
79
|
- **Visibility Filter**: Modal-based visibility filter (All, Public, Private/Internal for enterprise) with smart filtering
|
|
@@ -305,8 +305,9 @@ Status bar shows loaded count vs total. A rate-limit line displays `remaining/li
|
|
|
305
305
|
## Pagination Details
|
|
306
306
|
|
|
307
307
|
- Uses GitHub GraphQL `viewer.repositories` with `ownerAffiliations: OWNER`, ordered by `UPDATED_AT DESC`.
|
|
308
|
-
-
|
|
309
|
-
-
|
|
308
|
+
- **Background fetch-all:** the first page renders immediately, then the remaining repositories load in the background until the whole account is cached locally. Filtering, sorting, and search then operate over the complete set, client-side and instant.
|
|
309
|
+
- Fetches 100 repos per page by default (configurable via `REPOS_PER_FETCH` environment variable, 1-100).
|
|
310
|
+
- Reads `totalCount` from the first page and shows background-load progress (`loaded/total`) while filling. The list stays usable from the first page throughout; very large accounts simply take longer to finish loading.
|
|
310
311
|
|
|
311
312
|
## Development
|
|
312
313
|
|
|
@@ -621,11 +621,8 @@ async function fetchViewerReposPageUnified(token, first, after, orderBy, include
|
|
|
621
621
|
updatedAt
|
|
622
622
|
pushedAt
|
|
623
623
|
diskUsage
|
|
624
|
-
${includeForkTracking ? `
|
|
625
|
-
parent { nameWithOwner defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } } }
|
|
626
|
-
defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } }` : `
|
|
627
624
|
parent { nameWithOwner }
|
|
628
|
-
defaultBranchRef { name }
|
|
625
|
+
defaultBranchRef { name }
|
|
629
626
|
}
|
|
630
627
|
}
|
|
631
628
|
}
|
|
@@ -657,11 +654,8 @@ async function fetchViewerReposPageUnified(token, first, after, orderBy, include
|
|
|
657
654
|
updatedAt
|
|
658
655
|
pushedAt
|
|
659
656
|
diskUsage
|
|
660
|
-
${includeForkTracking ? `
|
|
661
|
-
parent { nameWithOwner defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } } }
|
|
662
|
-
defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } }` : `
|
|
663
657
|
parent { nameWithOwner }
|
|
664
|
-
defaultBranchRef { name }
|
|
658
|
+
defaultBranchRef { name }
|
|
665
659
|
}
|
|
666
660
|
}
|
|
667
661
|
}
|
|
@@ -742,11 +736,8 @@ async function searchRepositoriesUnified(token, viewer, text, first, after, sort
|
|
|
742
736
|
updatedAt
|
|
743
737
|
pushedAt
|
|
744
738
|
diskUsage
|
|
745
|
-
${includeForkTracking ? `
|
|
746
|
-
parent { nameWithOwner defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } } }
|
|
747
|
-
defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } }` : `
|
|
748
739
|
parent { nameWithOwner }
|
|
749
|
-
defaultBranchRef { name }
|
|
740
|
+
defaultBranchRef { name }
|
|
750
741
|
}
|
|
751
742
|
}
|
|
752
743
|
}
|
package/dist/index.js
CHANGED
|
@@ -27,14 +27,14 @@ import {
|
|
|
27
27
|
updateCacheAfterRename,
|
|
28
28
|
updateCacheAfterVisibilityChange,
|
|
29
29
|
updateCacheWithRepository
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-UOGN2QJU.js";
|
|
31
31
|
|
|
32
32
|
// package.json
|
|
33
33
|
var require_package = __commonJS({
|
|
34
34
|
"package.json"(exports, module) {
|
|
35
35
|
module.exports = {
|
|
36
36
|
name: "gh-manager-cli",
|
|
37
|
-
version: "1.
|
|
37
|
+
version: "1.40.0",
|
|
38
38
|
private: false,
|
|
39
39
|
description: "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
40
40
|
license: "MIT",
|
|
@@ -487,7 +487,7 @@ function OrgSwitcher({ token, currentContext, onSelect, onClose }) {
|
|
|
487
487
|
try {
|
|
488
488
|
setLoading(true);
|
|
489
489
|
setError(null);
|
|
490
|
-
const client = await import("./github-
|
|
490
|
+
const client = await import("./github-ASGTM4ZX.js").then((m) => m.makeClient(token));
|
|
491
491
|
const orgs = await fetchViewerOrganizations(client);
|
|
492
492
|
setOrganizations(orgs);
|
|
493
493
|
const entOrgs = /* @__PURE__ */ new Set();
|
|
@@ -1967,11 +1967,11 @@ var getPageSize = () => {
|
|
|
1967
1967
|
const envValue = process.env.REPOS_PER_FETCH;
|
|
1968
1968
|
if (envValue) {
|
|
1969
1969
|
const parsed = parseInt(envValue, 10);
|
|
1970
|
-
if (!isNaN(parsed) && parsed >= 1 && parsed <=
|
|
1970
|
+
if (!isNaN(parsed) && parsed >= 1 && parsed <= 100) {
|
|
1971
1971
|
return parsed;
|
|
1972
1972
|
}
|
|
1973
1973
|
}
|
|
1974
|
-
return
|
|
1974
|
+
return 100;
|
|
1975
1975
|
};
|
|
1976
1976
|
var PAGE_SIZE = getPageSize();
|
|
1977
1977
|
function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextChange, initialOrgSlug: initialOrgSlug2 }) {
|
|
@@ -2678,26 +2678,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2678
2678
|
fetchPage(null, true, false, void 0, policy);
|
|
2679
2679
|
}, [client, prefsLoaded, ownerContext, ownerAffiliations]);
|
|
2680
2680
|
useEffect12(() => {
|
|
2681
|
-
if (
|
|
2682
|
-
if (items.length > 0) {
|
|
2683
|
-
let policy = "cache-first";
|
|
2684
|
-
const orgLogin = ownerContext !== "personal" ? ownerContext.login : void 0;
|
|
2685
|
-
try {
|
|
2686
|
-
const key = makeApolloKey({
|
|
2687
|
-
viewer: viewerLogin || "unknown",
|
|
2688
|
-
sortKey,
|
|
2689
|
-
sortDir,
|
|
2690
|
-
pageSize: PAGE_SIZE,
|
|
2691
|
-
forkTracking,
|
|
2692
|
-
ownerContext: orgLogin ? `org:${orgLogin}` : "personal",
|
|
2693
|
-
affiliations: ownerAffiliations.join(",")
|
|
2694
|
-
});
|
|
2695
|
-
policy = isFresh(key) ? "cache-first" : "network-only";
|
|
2696
|
-
} catch {
|
|
2697
|
-
}
|
|
2698
|
-
fetchPage(null, true, true, void 0, policy);
|
|
2699
|
-
}
|
|
2700
|
-
} else {
|
|
2681
|
+
if (searchActive) {
|
|
2701
2682
|
if (!searchLoading && filter.trim().length >= 3) {
|
|
2702
2683
|
let policy = "cache-first";
|
|
2703
2684
|
try {
|
|
@@ -3284,20 +3265,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3284
3265
|
const nearEnd = visibleItems.length > 0 && cursor >= prefetchThreshold;
|
|
3285
3266
|
const rawItemsLength = starsMode ? starredItems.length : searchActive ? searchItems.length : items.length;
|
|
3286
3267
|
const filterDrainedPage = visibleItems.length === 0 && archiveFilter !== "all" && rawItemsLength > 0;
|
|
3287
|
-
const shouldFetch = nearEnd || filterDrainedPage;
|
|
3288
3268
|
if (starsMode) {
|
|
3289
|
-
if (!starredLoading && starredHasNextPage
|
|
3290
|
-
addDebugMessage(`[Infinite Scroll] Prefetching starred repos at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3269
|
+
if (!starredLoading && starredHasNextPage) {
|
|
3291
3270
|
fetchStarredRepositories(starredEndCursor);
|
|
3292
3271
|
}
|
|
3293
3272
|
} else if (searchActive) {
|
|
3294
|
-
if (!searchLoading && searchHasNextPage &&
|
|
3295
|
-
addDebugMessage(`[Infinite Scroll] Prefetching search results at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3273
|
+
if (!searchLoading && searchHasNextPage && (nearEnd || filterDrainedPage)) {
|
|
3296
3274
|
fetchSearchPage(searchEndCursor);
|
|
3297
3275
|
}
|
|
3298
3276
|
} else {
|
|
3299
|
-
if (!loading && !loadingMore && hasNextPage
|
|
3300
|
-
addDebugMessage(`[Infinite Scroll] Prefetching repos at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3277
|
+
if (!loading && !loadingMore && hasNextPage) {
|
|
3301
3278
|
fetchPage(endCursor);
|
|
3302
3279
|
}
|
|
3303
3280
|
}
|
|
@@ -3324,7 +3301,8 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3324
3301
|
searchActive ? searchTotalCount : totalCount,
|
|
3325
3302
|
")"
|
|
3326
3303
|
] }),
|
|
3327
|
-
|
|
3304
|
+
loadingMore && hasNextPage && !starsMode && !searchActive && totalCount > 0 && /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: ` \xB7 loading ${items.length}/${totalCount}` }),
|
|
3305
|
+
(loading || searchLoading || loadingMore) && /* @__PURE__ */ jsx20(Box19, { width: 2, flexShrink: 0, flexGrow: 0, marginLeft: 1, children: /* @__PURE__ */ jsx20(Text20, { color: "yellow", children: /* @__PURE__ */ jsx20(SlowSpinner, {}) }) })
|
|
3328
3306
|
] }),
|
|
3329
3307
|
(rateLimit || restRateLimit) && /* @__PURE__ */ jsxs19(Text20, { color: lowRate ? "yellow" : "gray", children: [
|
|
3330
3308
|
"GraphQL: ",
|
|
@@ -3856,7 +3834,14 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3856
3834
|
repo.nameWithOwner
|
|
3857
3835
|
);
|
|
3858
3836
|
}),
|
|
3859
|
-
loadingMore && hasNextPage && /* @__PURE__ */ jsx20(Box19, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs19(Box19, { flexDirection: "row", children: [
|
|
3837
|
+
loadingMore && hasNextPage && !starsMode && !searchActive && /* @__PURE__ */ jsx20(Box19, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs19(Box19, { flexDirection: "row", children: [
|
|
3838
|
+
/* @__PURE__ */ jsx20(Box19, { width: 2, flexShrink: 0, flexGrow: 0, marginRight: 1, children: /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: /* @__PURE__ */ jsx20(SlowSpinner, {}) }) }),
|
|
3839
|
+
/* @__PURE__ */ jsxs19(Text20, { color: "cyan", children: [
|
|
3840
|
+
"Loading repositories\u2026 ",
|
|
3841
|
+
totalCount > 0 ? `(${items.length}/${totalCount})` : `(${items.length})`
|
|
3842
|
+
] })
|
|
3843
|
+
] }) }),
|
|
3844
|
+
loadingMore && hasNextPage && (starsMode || searchActive) && /* @__PURE__ */ jsx20(Box19, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs19(Box19, { flexDirection: "row", children: [
|
|
3860
3845
|
/* @__PURE__ */ jsx20(Box19, { width: 2, flexShrink: 0, flexGrow: 0, marginRight: 1, children: /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: /* @__PURE__ */ jsx20(SlowSpinner, {}) }) }),
|
|
3861
3846
|
/* @__PURE__ */ jsx20(Text20, { color: "cyan", children: "Loading more repositories..." })
|
|
3862
3847
|
] }) }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gh-manager-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
6
6
|
"license": "MIT",
|