clairo 1.0.2 → 1.0.4
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/dist/cli.js +77 -11
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -125,6 +125,33 @@ function getCurrentBranch() {
|
|
|
125
125
|
return { success: false, error: "Failed to get current branch" };
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
+
function findRemoteWithBranch(branch) {
|
|
129
|
+
try {
|
|
130
|
+
const remoteBranches = execSync("git branch -r", {
|
|
131
|
+
encoding: "utf-8",
|
|
132
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
133
|
+
});
|
|
134
|
+
const remotes = listRemotes();
|
|
135
|
+
if (!remotes.success) {
|
|
136
|
+
return { success: false, error: "Failed to list remotes" };
|
|
137
|
+
}
|
|
138
|
+
for (const remote of remotes.data) {
|
|
139
|
+
if (remoteBranches.includes(`${remote.name}/${branch}`)) {
|
|
140
|
+
const sshMatch = remote.url.match(/git@github\.com:(.+?)\/(.+?)(?:\.git)?$/);
|
|
141
|
+
if (sshMatch) {
|
|
142
|
+
return { success: true, data: { remote: remote.name, owner: sshMatch[1] } };
|
|
143
|
+
}
|
|
144
|
+
const httpsMatch = remote.url.match(/https:\/\/github\.com\/(.+?)\/(.+?)(?:\.git)?$/);
|
|
145
|
+
if (httpsMatch) {
|
|
146
|
+
return { success: true, data: { remote: remote.name, owner: httpsMatch[1] } };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { success: false, error: "Branch not found on any remote" };
|
|
151
|
+
} catch {
|
|
152
|
+
return { success: false, error: "Failed to find remote with branch" };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
128
155
|
|
|
129
156
|
// src/lib/github/index.ts
|
|
130
157
|
import { exec } from "child_process";
|
|
@@ -730,6 +757,15 @@ function getCheckIcon(check) {
|
|
|
730
757
|
if (check.status === "COMPLETED") return "\u2713";
|
|
731
758
|
return "?";
|
|
732
759
|
}
|
|
760
|
+
function getCheckSortOrder(check) {
|
|
761
|
+
const conclusion = check.conclusion ?? check.state;
|
|
762
|
+
if (conclusion === "FAILURE" || conclusion === "ERROR") return 0;
|
|
763
|
+
if (conclusion === "PENDING" || check.status === "IN_PROGRESS" || check.status === "QUEUED" || check.status === "WAITING")
|
|
764
|
+
return 1;
|
|
765
|
+
if (conclusion === "SKIPPED" || conclusion === "NEUTRAL") return 2;
|
|
766
|
+
if (conclusion === "SUCCESS" || check.status === "COMPLETED") return 3;
|
|
767
|
+
return 4;
|
|
768
|
+
}
|
|
733
769
|
function PRDetailsBox({ pr, loading, error, isFocused }) {
|
|
734
770
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
735
771
|
const scrollRef = useRef(null);
|
|
@@ -824,12 +860,25 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
|
|
|
824
860
|
] }),
|
|
825
861
|
(((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
826
862
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
863
|
+
Array.from(
|
|
864
|
+
((_g = pr.statusCheckRollup) == null ? void 0 : _g.reduce((acc, check) => {
|
|
865
|
+
const key = check.name ?? check.context ?? "";
|
|
866
|
+
const existing = acc.get(key);
|
|
867
|
+
if (!existing || (check.startedAt ?? "") > (existing.startedAt ?? "")) {
|
|
868
|
+
acc.set(key, check);
|
|
869
|
+
}
|
|
870
|
+
return acc;
|
|
871
|
+
}, /* @__PURE__ */ new Map()).values()) ?? []
|
|
872
|
+
).sort((a, b) => getCheckSortOrder(a) - getCheckSortOrder(b)).map((check, idx) => {
|
|
873
|
+
const jobName = check.name ?? check.context;
|
|
874
|
+
const displayName = check.workflowName ? `${check.workflowName} / ${jobName}` : jobName;
|
|
875
|
+
return /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
|
|
876
|
+
" ",
|
|
877
|
+
getCheckIcon(check),
|
|
878
|
+
" ",
|
|
879
|
+
displayName
|
|
880
|
+
] }, idx);
|
|
881
|
+
})
|
|
833
882
|
] }),
|
|
834
883
|
pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
835
884
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
|
|
@@ -896,7 +945,7 @@ function PullRequestsBox({
|
|
|
896
945
|
if (key.downArrow || input === "j") {
|
|
897
946
|
setHighlightedIndex((prev) => Math.min(totalItems - 1, prev + 1));
|
|
898
947
|
}
|
|
899
|
-
if (
|
|
948
|
+
if (input === " ") {
|
|
900
949
|
if (highlightedIndex === prs.length) {
|
|
901
950
|
onCreatePR();
|
|
902
951
|
} else if (prs[highlightedIndex]) {
|
|
@@ -967,7 +1016,7 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
|
|
|
967
1016
|
if (key.downArrow || input === "j") {
|
|
968
1017
|
setHighlightedIndex((prev) => Math.min(remotes.length - 1, prev + 1));
|
|
969
1018
|
}
|
|
970
|
-
if (
|
|
1019
|
+
if (input === " ") {
|
|
971
1020
|
onSelect(remotes[highlightedIndex].name);
|
|
972
1021
|
}
|
|
973
1022
|
},
|
|
@@ -1027,8 +1076,9 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
|
|
|
1027
1076
|
}
|
|
1028
1077
|
const bindings = [];
|
|
1029
1078
|
if (focusedBox === "remotes") {
|
|
1030
|
-
bindings.push({ key: "
|
|
1079
|
+
bindings.push({ key: "Space", label: "Select Remote" });
|
|
1031
1080
|
} else if (focusedBox === "prs") {
|
|
1081
|
+
bindings.push({ key: "Space", label: "Select" });
|
|
1032
1082
|
bindings.push({ key: "n", label: "New PR", color: "green" });
|
|
1033
1083
|
bindings.push({ key: "r", label: "Refresh" });
|
|
1034
1084
|
bindings.push({ key: "o", label: "Open", color: "green" });
|
|
@@ -1140,11 +1190,24 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
|
|
|
1140
1190
|
const prNumbersBeforeCreate = useRef2(/* @__PURE__ */ new Set());
|
|
1141
1191
|
const pollingIntervalRef = useRef2(null);
|
|
1142
1192
|
const handleCreatePR = useCallback(() => {
|
|
1193
|
+
if (!currentBranch) {
|
|
1194
|
+
setErrors((prev) => ({ ...prev, prs: "No branch detected" }));
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
const remoteResult = findRemoteWithBranch(currentBranch);
|
|
1198
|
+
if (!remoteResult.success) {
|
|
1199
|
+
setErrors((prev) => ({ ...prev, prs: "Push your branch to a remote first" }));
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1143
1202
|
prNumbersBeforeCreate.current = new Set(prs.map((pr) => pr.number));
|
|
1144
|
-
|
|
1203
|
+
const headFlag = `${remoteResult.data.owner}:${currentBranch}`;
|
|
1204
|
+
exec3(`gh pr create --web --head "${headFlag}"`, (error) => {
|
|
1145
1205
|
process.stdout.emit("resize");
|
|
1206
|
+
if (error) {
|
|
1207
|
+
setErrors((prev) => ({ ...prev, prs: `Failed to create PR: ${error.message}` }));
|
|
1208
|
+
}
|
|
1146
1209
|
});
|
|
1147
|
-
if (!
|
|
1210
|
+
if (!currentRepoSlug) return;
|
|
1148
1211
|
let attempts = 0;
|
|
1149
1212
|
const maxAttempts = 24;
|
|
1150
1213
|
const pollInterval = 5e3;
|
|
@@ -1193,6 +1256,9 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
|
|
|
1193
1256
|
if (focusedBox === "prs") refreshPRs();
|
|
1194
1257
|
if (focusedBox === "details") refreshDetails();
|
|
1195
1258
|
}
|
|
1259
|
+
if (input === "n" && focusedBox === "prs") {
|
|
1260
|
+
handleCreatePR();
|
|
1261
|
+
}
|
|
1196
1262
|
},
|
|
1197
1263
|
{ isActive: isFocused }
|
|
1198
1264
|
);
|