gh-manager-cli 1.44.0 → 1.45.1
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 +9 -2
- package/README.md +10 -0
- package/dist/{chunk-MKIUBPVD.js → chunk-WHX6IOTW.js} +81 -0
- package/dist/{github-6HD7I2UI.js → github-72MPRF5W.js} +5 -1
- package/dist/index.js +904 -447
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
## [1.45.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.45.0...v1.45.1) (2026-06-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* ignore modal input while async actions are in flight, add guard tests (SWR-368) [semantic pr title] ([#64](https://github.com/wiiiimm/gh-manager-cli/issues/64)) ([97d2e4e](https://github.com/wiiiimm/gh-manager-cli/commit/97d2e4e25fc5d10cd2305ffb3f594b3f0b094e20)), closes [#65](https://github.com/wiiiimm/gh-manager-cli/issues/65)
|
|
7
|
+
|
|
8
|
+
# [1.45.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.44.0...v1.45.0) (2026-06-07)
|
|
2
9
|
|
|
3
10
|
|
|
4
11
|
### Features
|
|
5
12
|
|
|
6
|
-
*
|
|
13
|
+
* add repository creation (Ctrl+N) and transfer (Shift+M) ([#60](https://github.com/wiiiimm/gh-manager-cli/issues/60)) ([2e9c271](https://github.com/wiiiimm/gh-manager-cli/commit/2e9c2711b985be9373a94483e0bd0b420dc48aec))
|
|
7
14
|
|
|
8
15
|
# [1.43.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.42.0...v1.43.0) (2026-06-05)
|
|
9
16
|
|
package/README.md
CHANGED
|
@@ -84,7 +84,9 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
|
|
|
84
84
|
- View detailed info (`I`) - Shows repository metadata, language, size, and timestamps
|
|
85
85
|
- Open in browser (Enter/`O`) — for forks a chooser lets you open this repo or the upstream
|
|
86
86
|
- Jump to upstream (`P`) — moves cursor to the parent if loaded; otherwise fetches and shows it
|
|
87
|
+
- Create new repository (`Ctrl+N`) — prompts for a name (with the personal/organisation slug shown in front), choose visibility with `Tab`, and surfaces GitHub errors inline
|
|
87
88
|
- Rename repository (`Ctrl+R`) with inline validation and automatic cache update
|
|
89
|
+
- Transfer repository to another owner (`Shift+M`) — prompts for the destination owner, requires a verification code, shows a final confirmation, and surfaces GitHub errors inline
|
|
88
90
|
- Copy repository URL to clipboard (`C`) with SSH/HTTPS options
|
|
89
91
|
- Delete repository (`Del` or `Backspace`) with secure two-step confirmation
|
|
90
92
|
- Archive/unarchive repositories (`Ctrl+A`) with confirmation prompts
|
|
@@ -288,6 +290,10 @@ Launch the app, then use the keys below:
|
|
|
288
290
|
- **Quit**: `Q`
|
|
289
291
|
|
|
290
292
|
### Repository Actions
|
|
293
|
+
- **Create repository**: `Ctrl+N` to create a new repository in the current context (personal or organisation)
|
|
294
|
+
- Prompts for a name with the owner slug (`owner/`) shown in front
|
|
295
|
+
- `Tab` cycles visibility (Private/Public, plus Internal for enterprise organisations)
|
|
296
|
+
- Enter to create; GitHub errors (e.g. name already exists) are shown inline
|
|
291
297
|
- **Repository info**: `I` to view detailed metadata (size, language, timestamps)
|
|
292
298
|
- **Cache info**: `K` to inspect Apollo cache status
|
|
293
299
|
- **Archive/Unarchive**: `Ctrl+A` with confirmation prompt
|
|
@@ -298,6 +304,10 @@ Launch the app, then use the keys below:
|
|
|
298
304
|
- **Star/Unstar**: `Ctrl+S` to toggle star status for any repository
|
|
299
305
|
- **Sync fork**: `Ctrl+F` (for forks only, shows ahead/behind counts and handles conflicts)
|
|
300
306
|
- **Rename repository**: `Ctrl+R` with inline validation
|
|
307
|
+
- **Transfer repository**: `Shift+M` (Move) to transfer ownership to another user or organisation
|
|
308
|
+
- Prompts for the destination owner (`new-owner/<repo>` preview)
|
|
309
|
+
- Requires typing a randomly generated verification code (like delete), then a final confirmation before transferring
|
|
310
|
+
- GitHub errors (e.g. insufficient permissions) are shown inline
|
|
301
311
|
- **Copy URL**: `C` to copy repository URL to clipboard (SSH/HTTPS options)
|
|
302
312
|
|
|
303
313
|
### General
|
|
@@ -811,6 +811,85 @@ async function deleteRepositoryRest(token, owner, repo) {
|
|
|
811
811
|
});
|
|
812
812
|
throw new Error(msg);
|
|
813
813
|
}
|
|
814
|
+
async function parseGitHubRestError(res, defaultMessage) {
|
|
815
|
+
let msg = defaultMessage;
|
|
816
|
+
try {
|
|
817
|
+
const errBody = await res.json();
|
|
818
|
+
if (errBody?.message) msg = errBody.message;
|
|
819
|
+
if (Array.isArray(errBody?.errors) && errBody.errors.length > 0) {
|
|
820
|
+
const details = errBody.errors.map((e) => e.message || (e.field ? `${e.field}: ${e.code}` : e.code)).filter(Boolean).join("; ");
|
|
821
|
+
if (details) msg += ` (${details})`;
|
|
822
|
+
}
|
|
823
|
+
} catch {
|
|
824
|
+
}
|
|
825
|
+
return msg;
|
|
826
|
+
}
|
|
827
|
+
async function createRepositoryRest(token, options) {
|
|
828
|
+
const { name, visibility, description, org } = options;
|
|
829
|
+
const url = org ? `https://api.github.com/orgs/${org}/repos` : `https://api.github.com/user/repos`;
|
|
830
|
+
const body = { name };
|
|
831
|
+
if (visibility === "INTERNAL") {
|
|
832
|
+
body.visibility = "internal";
|
|
833
|
+
} else {
|
|
834
|
+
body.private = visibility === "PRIVATE";
|
|
835
|
+
}
|
|
836
|
+
if (description) body.description = description;
|
|
837
|
+
logger.info("Creating repository", { name, visibility, org: org ?? null, url });
|
|
838
|
+
let res;
|
|
839
|
+
try {
|
|
840
|
+
res = await fetch(url, {
|
|
841
|
+
method: "POST",
|
|
842
|
+
headers: {
|
|
843
|
+
"Authorization": `token ${token}`,
|
|
844
|
+
"Accept": "application/vnd.github+json",
|
|
845
|
+
"Content-Type": "application/json",
|
|
846
|
+
"User-Agent": "gh-manager-cli"
|
|
847
|
+
},
|
|
848
|
+
body: JSON.stringify(body)
|
|
849
|
+
});
|
|
850
|
+
} catch (networkError) {
|
|
851
|
+
logger.error("Network error during repository creation", { error: networkError.message, name, org: org ?? null });
|
|
852
|
+
throw new Error(`Network error whilst creating repository: ${networkError.message}`);
|
|
853
|
+
}
|
|
854
|
+
if (res.status === 201) {
|
|
855
|
+
const data = await res.json();
|
|
856
|
+
logger.info("Successfully created repository", {
|
|
857
|
+
nameWithOwner: data.full_name,
|
|
858
|
+
url: data.html_url
|
|
859
|
+
});
|
|
860
|
+
return { nameWithOwner: data.full_name, url: data.html_url };
|
|
861
|
+
}
|
|
862
|
+
const msg = await parseGitHubRestError(res, `Failed to create repository (status ${res.status})`);
|
|
863
|
+
logger.error("Failed to create repository", { status: res.status, error: msg, name, org: org ?? null });
|
|
864
|
+
throw new Error(msg);
|
|
865
|
+
}
|
|
866
|
+
async function transferRepositoryRest(token, owner, repo, newOwner) {
|
|
867
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/transfer`;
|
|
868
|
+
logger.info("Transferring repository", { owner, repo, newOwner, url });
|
|
869
|
+
let res;
|
|
870
|
+
try {
|
|
871
|
+
res = await fetch(url, {
|
|
872
|
+
method: "POST",
|
|
873
|
+
headers: {
|
|
874
|
+
"Authorization": `token ${token}`,
|
|
875
|
+
"Accept": "application/vnd.github+json",
|
|
876
|
+
"Content-Type": "application/json",
|
|
877
|
+
"User-Agent": "gh-manager-cli"
|
|
878
|
+
},
|
|
879
|
+
body: JSON.stringify({ new_owner: newOwner })
|
|
880
|
+
});
|
|
881
|
+
} catch (networkError) {
|
|
882
|
+
logger.error("Network error during repository transfer", { error: networkError.message, owner, repo, newOwner });
|
|
883
|
+
throw new Error(`Network error whilst transferring repository: ${networkError.message}`);
|
|
884
|
+
}
|
|
885
|
+
if (res.status === 202 || res.status === 200) {
|
|
886
|
+
logger.info("Successfully initiated repository transfer", { owner, repo, newOwner, status: res.status });
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
const msg = await parseGitHubRestError(res, `Failed to transfer repository (status ${res.status})`);
|
|
890
|
+
logger.error("Failed to transfer repository", { status: res.status, error: msg, owner, repo, newOwner });
|
|
891
|
+
throw new Error(msg);
|
|
892
|
+
}
|
|
814
893
|
async function getStarredRepositories(client, first, after) {
|
|
815
894
|
logger.info("Fetching starred repositories", {
|
|
816
895
|
first,
|
|
@@ -1607,6 +1686,8 @@ export {
|
|
|
1607
1686
|
fetchViewerReposPageUnified,
|
|
1608
1687
|
searchRepositoriesUnified,
|
|
1609
1688
|
deleteRepositoryRest,
|
|
1689
|
+
createRepositoryRest,
|
|
1690
|
+
transferRepositoryRest,
|
|
1610
1691
|
getStarredRepositories,
|
|
1611
1692
|
starRepository,
|
|
1612
1693
|
unstarRepository,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
archiveRepositoryById,
|
|
4
4
|
changeRepositoryVisibility,
|
|
5
5
|
checkOrganizationIsEnterprise,
|
|
6
|
+
createRepositoryRest,
|
|
6
7
|
deleteRepositoryRest,
|
|
7
8
|
enrichForksWithAheadBehind,
|
|
8
9
|
fetchRepositoryById,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
searchRepositoriesUnified,
|
|
22
23
|
starRepository,
|
|
23
24
|
syncForkWithUpstream,
|
|
25
|
+
transferRepositoryRest,
|
|
24
26
|
unarchiveRepositoryById,
|
|
25
27
|
unstarRepository,
|
|
26
28
|
updateCacheAfterArchive,
|
|
@@ -28,11 +30,12 @@ import {
|
|
|
28
30
|
updateCacheAfterRename,
|
|
29
31
|
updateCacheAfterVisibilityChange,
|
|
30
32
|
updateCacheWithRepository
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-WHX6IOTW.js";
|
|
32
34
|
export {
|
|
33
35
|
archiveRepositoryById,
|
|
34
36
|
changeRepositoryVisibility,
|
|
35
37
|
checkOrganizationIsEnterprise,
|
|
38
|
+
createRepositoryRest,
|
|
36
39
|
deleteRepositoryRest,
|
|
37
40
|
enrichForksWithAheadBehind,
|
|
38
41
|
fetchRepositoryById,
|
|
@@ -51,6 +54,7 @@ export {
|
|
|
51
54
|
searchRepositoriesUnified,
|
|
52
55
|
starRepository,
|
|
53
56
|
syncForkWithUpstream,
|
|
57
|
+
transferRepositoryRest,
|
|
54
58
|
unarchiveRepositoryById,
|
|
55
59
|
unstarRepository,
|
|
56
60
|
updateCacheAfterArchive,
|