nugit-cli 0.0.1-alpha → 0.1.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.
Files changed (39) hide show
  1. package/package.json +1 -1
  2. package/src/api-client.js +10 -11
  3. package/src/github-device-flow.js +1 -1
  4. package/src/github-oauth-client-id.js +11 -0
  5. package/src/github-pr-social.js +42 -0
  6. package/src/github-rest.js +114 -6
  7. package/src/nugit-stack.js +20 -0
  8. package/src/nugit-start.js +4 -4
  9. package/src/nugit.js +37 -22
  10. package/src/review-hub/review-autoapprove.js +95 -0
  11. package/src/review-hub/review-hub-back.js +10 -0
  12. package/src/review-hub/review-hub-ink.js +166 -0
  13. package/src/review-hub/run-review-hub.js +188 -0
  14. package/src/split-view/run-split.js +16 -3
  15. package/src/split-view/split-ink.js +2 -2
  16. package/src/stack-discover.js +9 -1
  17. package/src/stack-infer-from-prs.js +71 -0
  18. package/src/stack-view/diff-line-map.js +62 -0
  19. package/src/stack-view/fetch-pr-data.js +104 -4
  20. package/src/stack-view/infer-chains-to-pick-stacks.js +70 -0
  21. package/src/stack-view/ink-app.js +1853 -156
  22. package/src/stack-view/loading-ink.js +44 -0
  23. package/src/stack-view/merge-alternate-pick-stacks.js +223 -0
  24. package/src/stack-view/patch-preview-merge.js +108 -0
  25. package/src/stack-view/remote-infer-doc.js +93 -0
  26. package/src/stack-view/repo-picker-back.js +10 -0
  27. package/src/stack-view/run-stack-view.js +685 -50
  28. package/src/stack-view/run-view-entry.js +119 -0
  29. package/src/stack-view/sgr-mouse.js +56 -0
  30. package/src/stack-view/stack-branch-graph.js +95 -0
  31. package/src/stack-view/stack-pick-graph.js +93 -0
  32. package/src/stack-view/stack-pick-ink.js +270 -0
  33. package/src/stack-view/stack-pick-layout.js +19 -0
  34. package/src/stack-view/stack-pick-sort.js +188 -0
  35. package/src/stack-view/terminal-fullscreen.js +45 -0
  36. package/src/stack-view/tree-ascii.js +73 -0
  37. package/src/stack-view/view-md-plain.js +23 -0
  38. package/src/stack-view/view-repo-picker-ink.js +293 -0
  39. package/src/stack-view/view-tui-sequential.js +126 -0
@@ -0,0 +1,126 @@
1
+ import React from "react";
2
+ import { render } from "ink";
3
+ import { StackPickInk } from "./stack-pick-ink.js";
4
+ import { inferChainsToPickStacks } from "./infer-chains-to-pick-stacks.js";
5
+ import { clearInkScreen } from "./terminal-fullscreen.js";
6
+
7
+ /** Resolved by {@link pickStackIndexWithInk} when Backspace requests the repo picker (allowBackToRepo only). */
8
+ export const STACK_PICK_BACK_TO_REPO = Symbol("STACK_PICK_BACK_TO_REPO");
9
+
10
+ /**
11
+ * @param {object} args
12
+ * @param {{ tip_pr_number: number, tip_head_branch: string, pr_count: number, created_by: string, prs: unknown[], tip_updated_at?: string, inferChainIndex?: number, inferDiffAdd?: number, inferDiffDel?: number }[]} args.stacks
13
+ * @param {string} [args.title]
14
+ * @param {boolean} [args.allowBackToRepo]
15
+ * @param {number | null | undefined} [args.viewingTipPrNumber]
16
+ * @param {string | null | undefined} [args.viewingHeadRef]
17
+ * @returns {Promise<(typeof args.stacks)[0] | null | typeof STACK_PICK_BACK_TO_REPO>}
18
+ */
19
+ function runStackPickInkOnce({
20
+ stacks,
21
+ title = "Choose stack to view",
22
+ allowBackToRepo = false,
23
+ /** When true with {@link allowBackToRepo}, Esc and q also return to repo (repo-picker loop only). */
24
+ escapeToRepo = false,
25
+ viewingTipPrNumber,
26
+ viewingHeadRef
27
+ }) {
28
+ clearInkScreen();
29
+ return new Promise((resolve) => {
30
+ let settled = false;
31
+ const inst = render(
32
+ React.createElement(StackPickInk, {
33
+ stacks,
34
+ title,
35
+ viewingTipPrNumber,
36
+ viewingHeadRef,
37
+ escapeToRepo: escapeToRepo === true,
38
+ onPick: (picked) => {
39
+ if (!settled) {
40
+ settled = true;
41
+ try {
42
+ inst.clear();
43
+ } catch {
44
+ /* ignore */
45
+ }
46
+ resolve(picked);
47
+ }
48
+ },
49
+ onRequestBack:
50
+ allowBackToRepo === true
51
+ ? () => {
52
+ if (!settled) {
53
+ settled = true;
54
+ try {
55
+ inst.clear();
56
+ } catch {
57
+ /* ignore */
58
+ }
59
+ resolve(STACK_PICK_BACK_TO_REPO);
60
+ }
61
+ }
62
+ : undefined
63
+ })
64
+ );
65
+ void inst.waitUntilExit().then(() => {
66
+ try {
67
+ inst.clear();
68
+ } catch {
69
+ /* ignore */
70
+ }
71
+ if (!settled) {
72
+ settled = true;
73
+ resolve(null);
74
+ }
75
+ });
76
+ });
77
+ }
78
+
79
+ /**
80
+ * @param {{ tip_pr_number: number, tip_head_branch: string, pr_count: number, created_by: string, prs: unknown[], tip_updated_at?: string }[]} stacks
81
+ * @param {{ allowBackToRepo?: boolean, escapeToRepo?: boolean, viewingTipPrNumber?: number | null, viewingHeadRef?: string | null }} [opts]
82
+ * @returns {Promise<(typeof stacks)[0] | null | typeof STACK_PICK_BACK_TO_REPO>}
83
+ */
84
+ export async function pickStackIndexWithInk(stacks, opts) {
85
+ return runStackPickInkOnce({
86
+ stacks,
87
+ title: "Choose stack to view",
88
+ allowBackToRepo: opts?.allowBackToRepo === true,
89
+ escapeToRepo: opts?.escapeToRepo === true,
90
+ viewingTipPrNumber: opts?.viewingTipPrNumber,
91
+ viewingHeadRef: opts?.viewingHeadRef
92
+ });
93
+ }
94
+
95
+ /**
96
+ * @param {number[][]} chains bottom → tip PR numbers per chain
97
+ * @param {unknown[]} pulls GitHub pull objects (same list used to build chains)
98
+ * @param {{ allowBackToRepo?: boolean }} [opts] Backspace resolves -2 for repo-picker loop
99
+ * @returns {Promise<number>} chain index, or -1 for q / cancel (use largest stack), or -2 back to repo
100
+ */
101
+ export async function pickInferChainIndexWithInk(chains, pulls, opts) {
102
+ const stacks = inferChainsToPickStacks(chains, pulls);
103
+ const r = await runStackPickInkOnce({
104
+ stacks,
105
+ title: "Choose stack to view",
106
+ allowBackToRepo: opts?.allowBackToRepo === true,
107
+ escapeToRepo: opts?.allowBackToRepo === true
108
+ });
109
+ if (r === STACK_PICK_BACK_TO_REPO) {
110
+ return -2;
111
+ }
112
+ if (r == null) {
113
+ return -1;
114
+ }
115
+ if (typeof r.inferChainIndex === "number") {
116
+ return r.inferChainIndex;
117
+ }
118
+ const tip = typeof r.tip_pr_number === "number" ? r.tip_pr_number : null;
119
+ if (tip != null) {
120
+ const fi = chains.findIndex((c) => Array.isArray(c) && c.length > 0 && c[c.length - 1] === tip);
121
+ if (fi >= 0) {
122
+ return fi;
123
+ }
124
+ }
125
+ return -1;
126
+ }