gh-manager-cli 1.10.3 → 1.10.5
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,17 @@
|
|
|
1
|
+
## [1.10.5](https://github.com/wiiiimm/gh-manager-cli/compare/v1.10.4...v1.10.5) (2025-09-01)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* prevent duplicate modal handlers and improve modal UI ([79281d3](https://github.com/wiiiimm/gh-manager-cli/commit/79281d34fe42d3345885cad257e6800e94eb2bb3))
|
|
7
|
+
|
|
8
|
+
## [1.10.4](https://github.com/wiiiimm/gh-manager-cli/compare/v1.10.3...v1.10.4) (2025-09-01)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* eliminate duplicate sync handler to prevent double execution ([bf838b6](https://github.com/wiiiimm/gh-manager-cli/commit/bf838b66f5c8b7def294d3835278cd32254bce1f))
|
|
14
|
+
|
|
1
15
|
## [1.10.3](https://github.com/wiiiimm/gh-manager-cli/compare/v1.10.2...v1.10.3) (2025-09-01)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -668,19 +668,6 @@ async function syncForkWithUpstream(token, owner, repo, branch = "main") {
|
|
|
668
668
|
const body = await res.json();
|
|
669
669
|
return body;
|
|
670
670
|
}
|
|
671
|
-
if (res.status === 422) {
|
|
672
|
-
try {
|
|
673
|
-
const body = await res.json();
|
|
674
|
-
if (body && body.message && body.message.includes("There was a problem updating the branch")) {
|
|
675
|
-
return {
|
|
676
|
-
message: "Sync completed (with warnings)",
|
|
677
|
-
merge_type: "merge",
|
|
678
|
-
base_branch: branch
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
} catch {
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
671
|
let msg = `Fork sync failed (status ${res.status})`;
|
|
685
672
|
try {
|
|
686
673
|
const body = await res.json();
|
|
@@ -689,6 +676,9 @@ async function syncForkWithUpstream(token, owner, repo, branch = "main") {
|
|
|
689
676
|
if (res.status === 409) {
|
|
690
677
|
msg += " (conflicts detected - manual merge required)";
|
|
691
678
|
}
|
|
679
|
+
if (res.status === 422) {
|
|
680
|
+
msg += " (branch could not be synced)";
|
|
681
|
+
}
|
|
692
682
|
}
|
|
693
683
|
} catch {
|
|
694
684
|
}
|
package/dist/index.js
CHANGED
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
updateCacheAfterArchive,
|
|
17
17
|
updateCacheAfterDelete,
|
|
18
18
|
updateCacheWithRepository
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-XCFI3TG5.js";
|
|
20
20
|
|
|
21
21
|
// package.json
|
|
22
22
|
var require_package = __commonJS({
|
|
23
23
|
"package.json"(exports, module) {
|
|
24
24
|
module.exports = {
|
|
25
25
|
name: "gh-manager-cli",
|
|
26
|
-
version: "1.10.
|
|
26
|
+
version: "1.10.5",
|
|
27
27
|
private: false,
|
|
28
28
|
description: "Interactive CLI to manage your GitHub repos (personal) with Ink",
|
|
29
29
|
license: "MIT",
|
|
@@ -279,7 +279,7 @@ function OrgSwitcher({ token, currentContext, onSelect, onClose }) {
|
|
|
279
279
|
const loadOrgs = async () => {
|
|
280
280
|
try {
|
|
281
281
|
setLoading(true);
|
|
282
|
-
const client = await import("./github-
|
|
282
|
+
const client = await import("./github-6IFMCQKW.js").then((m) => m.makeClient(token));
|
|
283
283
|
const orgs = await fetchViewerOrganizations(client);
|
|
284
284
|
setOrganizations(orgs);
|
|
285
285
|
if (!isPersonalContext) {
|
|
@@ -486,6 +486,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
486
486
|
const [syncing, setSyncing] = useState3(false);
|
|
487
487
|
const [syncError, setSyncError] = useState3(null);
|
|
488
488
|
const [syncFocus, setSyncFocus] = useState3("confirm");
|
|
489
|
+
const [syncTrigger, setSyncTrigger] = useState3(false);
|
|
489
490
|
const [infoMode, setInfoMode] = useState3(false);
|
|
490
491
|
const [infoRepo, setInfoRepo] = useState3(null);
|
|
491
492
|
const [logoutMode, setLogoutMode] = useState3(false);
|
|
@@ -504,6 +505,67 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
504
505
|
setSyncing(false);
|
|
505
506
|
setSyncError(null);
|
|
506
507
|
setSyncFocus("confirm");
|
|
508
|
+
setSyncTrigger(false);
|
|
509
|
+
}
|
|
510
|
+
async function executeSync() {
|
|
511
|
+
if (!syncTarget || syncing) return;
|
|
512
|
+
try {
|
|
513
|
+
setSyncing(true);
|
|
514
|
+
const [owner, repo] = syncTarget.nameWithOwner.split("/");
|
|
515
|
+
const branchName = syncTarget.defaultBranchRef?.name || "main";
|
|
516
|
+
const result = await syncForkWithUpstream(token, owner, repo, branchName);
|
|
517
|
+
const updatedRepo = {
|
|
518
|
+
...syncTarget,
|
|
519
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
520
|
+
// If we're tracking fork commits and this is a fork with parent data, set commits to be in sync
|
|
521
|
+
...forkTracking && syncTarget.isFork && syncTarget.parent && syncTarget.defaultBranchRef?.target?.history && syncTarget.parent.defaultBranchRef?.target?.history ? {
|
|
522
|
+
defaultBranchRef: {
|
|
523
|
+
...syncTarget.defaultBranchRef,
|
|
524
|
+
target: {
|
|
525
|
+
...syncTarget.defaultBranchRef.target,
|
|
526
|
+
history: {
|
|
527
|
+
// Set fork's commit count equal to parent's (0 commits behind)
|
|
528
|
+
totalCount: syncTarget.parent.defaultBranchRef.target.history.totalCount
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} : {}
|
|
533
|
+
};
|
|
534
|
+
await updateCacheWithRepository(token, updatedRepo);
|
|
535
|
+
const updateSyncedRepo = (r) => {
|
|
536
|
+
if (r.id === syncTarget.id) {
|
|
537
|
+
return updatedRepo;
|
|
538
|
+
}
|
|
539
|
+
return r;
|
|
540
|
+
};
|
|
541
|
+
setItems((prev) => prev.map(updateSyncedRepo));
|
|
542
|
+
setSearchItems((prev) => prev.map(updateSyncedRepo));
|
|
543
|
+
closeSyncModal();
|
|
544
|
+
} catch (e) {
|
|
545
|
+
setSyncing(false);
|
|
546
|
+
setSyncError(e.message || "Failed to sync fork. Check permissions and network.");
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
async function executeArchive() {
|
|
550
|
+
if (!archiveTarget || archiving) return;
|
|
551
|
+
try {
|
|
552
|
+
setArchiving(true);
|
|
553
|
+
const isArchived = archiveTarget.isArchived;
|
|
554
|
+
const id = archiveTarget.id;
|
|
555
|
+
if (isArchived) {
|
|
556
|
+
await unarchiveRepositoryById(client, id);
|
|
557
|
+
} else {
|
|
558
|
+
await archiveRepositoryById(client, id);
|
|
559
|
+
}
|
|
560
|
+
await updateCacheAfterArchive(token, id, !isArchived);
|
|
561
|
+
const updateRepo = (r) => r.id === id ? { ...r, isArchived: !isArchived } : r;
|
|
562
|
+
setItems((prev) => prev.map(updateRepo));
|
|
563
|
+
setSearchItems((prev) => prev.map(updateRepo));
|
|
564
|
+
closeArchiveModal();
|
|
565
|
+
} catch (e) {
|
|
566
|
+
setArchiving(false);
|
|
567
|
+
setArchiveError("Failed to update archive state. Check permissions.");
|
|
568
|
+
}
|
|
507
569
|
}
|
|
508
570
|
function handleOrgContextChange(newContext) {
|
|
509
571
|
setOwnerContext(newContext);
|
|
@@ -795,13 +857,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
795
857
|
setConfirmFocus("cancel");
|
|
796
858
|
return;
|
|
797
859
|
}
|
|
798
|
-
if (key.return) {
|
|
799
|
-
if (confirmFocus === "delete") confirmDeleteNow();
|
|
800
|
-
else cancelDeleteModal();
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
860
|
if (input && input.toUpperCase() === "Y") {
|
|
804
|
-
|
|
861
|
+
if (confirmFocus === "delete") {
|
|
862
|
+
confirmDeleteNow();
|
|
863
|
+
} else {
|
|
864
|
+
cancelDeleteModal();
|
|
865
|
+
}
|
|
805
866
|
return;
|
|
806
867
|
}
|
|
807
868
|
}
|
|
@@ -820,29 +881,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
820
881
|
setArchiveFocus("cancel");
|
|
821
882
|
return;
|
|
822
883
|
}
|
|
823
|
-
if (
|
|
884
|
+
if (input && input.toUpperCase() === "Y") {
|
|
824
885
|
if (archiveFocus === "cancel") {
|
|
825
886
|
closeArchiveModal();
|
|
826
887
|
return;
|
|
827
888
|
}
|
|
828
|
-
|
|
829
|
-
(async () => {
|
|
830
|
-
try {
|
|
831
|
-
setArchiving(true);
|
|
832
|
-
const isArchived = archiveTarget.isArchived;
|
|
833
|
-
const id = archiveTarget.id;
|
|
834
|
-
if (isArchived) await unarchiveRepositoryById(client, id);
|
|
835
|
-
else await archiveRepositoryById(client, id);
|
|
836
|
-
await updateCacheAfterArchive(token, id, !isArchived);
|
|
837
|
-
const updateRepo = (r) => r.id === id ? { ...r, isArchived: !isArchived } : r;
|
|
838
|
-
setItems((prev) => prev.map(updateRepo));
|
|
839
|
-
setSearchItems((prev) => prev.map(updateRepo));
|
|
840
|
-
closeArchiveModal();
|
|
841
|
-
} catch (e) {
|
|
842
|
-
setArchiving(false);
|
|
843
|
-
setArchiveError("Failed to update archive state. Check permissions.");
|
|
844
|
-
}
|
|
845
|
-
})();
|
|
889
|
+
executeArchive();
|
|
846
890
|
return;
|
|
847
891
|
}
|
|
848
892
|
return;
|
|
@@ -860,50 +904,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
860
904
|
setSyncFocus("cancel");
|
|
861
905
|
return;
|
|
862
906
|
}
|
|
863
|
-
if (
|
|
907
|
+
if (input && input.toUpperCase() === "Y") {
|
|
864
908
|
if (syncFocus === "cancel") {
|
|
865
909
|
closeSyncModal();
|
|
866
|
-
|
|
910
|
+
} else {
|
|
911
|
+
executeSync();
|
|
867
912
|
}
|
|
868
|
-
if (!syncTarget) return;
|
|
869
|
-
(async () => {
|
|
870
|
-
try {
|
|
871
|
-
setSyncing(true);
|
|
872
|
-
const [owner, repo] = syncTarget.nameWithOwner.split("/");
|
|
873
|
-
const branchName = syncTarget.defaultBranchRef?.name || "main";
|
|
874
|
-
const result = await syncForkWithUpstream(token, owner, repo, branchName);
|
|
875
|
-
const updatedRepo = {
|
|
876
|
-
...syncTarget,
|
|
877
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
878
|
-
// If we're tracking fork commits and this is a fork with parent data, set commits to be in sync
|
|
879
|
-
...forkTracking && syncTarget.isFork && syncTarget.parent && syncTarget.defaultBranchRef?.target?.history && syncTarget.parent.defaultBranchRef?.target?.history ? {
|
|
880
|
-
defaultBranchRef: {
|
|
881
|
-
...syncTarget.defaultBranchRef,
|
|
882
|
-
target: {
|
|
883
|
-
...syncTarget.defaultBranchRef.target,
|
|
884
|
-
history: {
|
|
885
|
-
// Set fork's commit count equal to parent's (0 commits behind)
|
|
886
|
-
totalCount: syncTarget.parent.defaultBranchRef.target.history.totalCount
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
} : {}
|
|
891
|
-
};
|
|
892
|
-
await updateCacheWithRepository(token, updatedRepo);
|
|
893
|
-
const updateSyncedRepo = (r) => {
|
|
894
|
-
if (r.id === syncTarget.id) {
|
|
895
|
-
return updatedRepo;
|
|
896
|
-
}
|
|
897
|
-
return r;
|
|
898
|
-
};
|
|
899
|
-
setItems((prev) => prev.map(updateSyncedRepo));
|
|
900
|
-
setSearchItems((prev) => prev.map(updateSyncedRepo));
|
|
901
|
-
closeSyncModal();
|
|
902
|
-
} catch (e) {
|
|
903
|
-
setSyncing(false);
|
|
904
|
-
setSyncError(e.message || "Failed to sync fork. Check permissions and network.");
|
|
905
|
-
}
|
|
906
|
-
})();
|
|
907
913
|
return;
|
|
908
914
|
}
|
|
909
915
|
return;
|
|
@@ -1361,7 +1367,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1361
1367
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1362
1368
|
"Press Enter to ",
|
|
1363
1369
|
confirmFocus === "delete" ? "Delete" : "Cancel",
|
|
1364
|
-
"
|
|
1370
|
+
" | Y to Delete | C to Cancel"
|
|
1365
1371
|
] }) }),
|
|
1366
1372
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1367
1373
|
TextInput2,
|
|
@@ -1417,7 +1423,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1417
1423
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1418
1424
|
"Press Enter to ",
|
|
1419
1425
|
archiveFocus === "confirm" ? archiveTarget.isArchived ? "Unarchive" : "Archive" : "Cancel",
|
|
1420
|
-
"
|
|
1426
|
+
" | Y to ",
|
|
1427
|
+
archiveTarget.isArchived ? "Unarchive" : "Archive",
|
|
1428
|
+
" | C to Cancel"
|
|
1421
1429
|
] }) }),
|
|
1422
1430
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1423
1431
|
TextInput2,
|
|
@@ -1427,23 +1435,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1427
1435
|
},
|
|
1428
1436
|
onSubmit: () => {
|
|
1429
1437
|
if (archiveFocus === "confirm") {
|
|
1430
|
-
(
|
|
1431
|
-
try {
|
|
1432
|
-
setArchiving(true);
|
|
1433
|
-
const isArchived = archiveTarget.isArchived;
|
|
1434
|
-
const id = archiveTarget.id;
|
|
1435
|
-
if (isArchived) await unarchiveRepositoryById(client, id);
|
|
1436
|
-
else await archiveRepositoryById(client, id);
|
|
1437
|
-
await updateCacheAfterArchive(token, id, !isArchived);
|
|
1438
|
-
const updateRepo = (r) => r.id === id ? { ...r, isArchived: !isArchived } : r;
|
|
1439
|
-
setItems((prev) => prev.map(updateRepo));
|
|
1440
|
-
setSearchItems((prev) => prev.map(updateRepo));
|
|
1441
|
-
closeArchiveModal();
|
|
1442
|
-
} catch (e) {
|
|
1443
|
-
setArchiving(false);
|
|
1444
|
-
setArchiveError("Failed to update archive state. Check permissions.");
|
|
1445
|
-
}
|
|
1446
|
-
})();
|
|
1438
|
+
executeArchive();
|
|
1447
1439
|
} else {
|
|
1448
1440
|
closeArchiveModal();
|
|
1449
1441
|
}
|
|
@@ -1493,7 +1485,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1493
1485
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1494
1486
|
"Press Enter to ",
|
|
1495
1487
|
syncFocus === "confirm" ? "Sync" : "Cancel",
|
|
1496
|
-
"
|
|
1488
|
+
" | Y to Sync | C to Cancel"
|
|
1497
1489
|
] }) }),
|
|
1498
1490
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1499
1491
|
TextInput2,
|
|
@@ -1503,44 +1495,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1503
1495
|
},
|
|
1504
1496
|
onSubmit: () => {
|
|
1505
1497
|
if (syncFocus === "confirm") {
|
|
1506
|
-
(
|
|
1507
|
-
try {
|
|
1508
|
-
setSyncing(true);
|
|
1509
|
-
const [owner, repo] = syncTarget.nameWithOwner.split("/");
|
|
1510
|
-
const branchName = syncTarget.defaultBranchRef?.name || "main";
|
|
1511
|
-
const result = await syncForkWithUpstream(token, owner, repo, branchName);
|
|
1512
|
-
const updatedRepo = {
|
|
1513
|
-
...syncTarget,
|
|
1514
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1515
|
-
// If we're tracking fork commits and this is a fork with parent data, set commits to be in sync
|
|
1516
|
-
...forkTracking && syncTarget.isFork && syncTarget.parent && syncTarget.defaultBranchRef?.target?.history && syncTarget.parent.defaultBranchRef?.target?.history ? {
|
|
1517
|
-
defaultBranchRef: {
|
|
1518
|
-
...syncTarget.defaultBranchRef,
|
|
1519
|
-
target: {
|
|
1520
|
-
...syncTarget.defaultBranchRef.target,
|
|
1521
|
-
history: {
|
|
1522
|
-
// Set fork's commit count equal to parent's (0 commits behind)
|
|
1523
|
-
totalCount: syncTarget.parent.defaultBranchRef.target.history.totalCount
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
} : {}
|
|
1528
|
-
};
|
|
1529
|
-
await updateCacheWithRepository(token, updatedRepo);
|
|
1530
|
-
const updateSyncedRepo = (r) => {
|
|
1531
|
-
if (r.id === syncTarget.id) {
|
|
1532
|
-
return updatedRepo;
|
|
1533
|
-
}
|
|
1534
|
-
return r;
|
|
1535
|
-
};
|
|
1536
|
-
setItems((prev) => prev.map(updateSyncedRepo));
|
|
1537
|
-
setSearchItems((prev) => prev.map(updateSyncedRepo));
|
|
1538
|
-
closeSyncModal();
|
|
1539
|
-
} catch (e) {
|
|
1540
|
-
setSyncing(false);
|
|
1541
|
-
setSyncError(e.message || "Failed to sync fork. Check permissions and network.");
|
|
1542
|
-
}
|
|
1543
|
-
})();
|
|
1498
|
+
executeSync();
|
|
1544
1499
|
} else {
|
|
1545
1500
|
closeSyncModal();
|
|
1546
1501
|
}
|
|
@@ -1583,7 +1538,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1583
1538
|
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1584
1539
|
"Press Enter to ",
|
|
1585
1540
|
logoutFocus === "confirm" ? "Logout" : "Cancel",
|
|
1586
|
-
"
|
|
1541
|
+
" | Y to Logout | C to Cancel"
|
|
1587
1542
|
] }) })
|
|
1588
1543
|
] }) }) : orgSwitcherOpen ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx6(
|
|
1589
1544
|
OrgSwitcher,
|