git-stack-cli 0.2.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/__fixtures__/metadata.js +763 -0
  4. package/dist/__fixtures__/metadata.json +186 -0
  5. package/dist/app/App.js +30 -0
  6. package/dist/app/ArgCheck.js +21 -0
  7. package/dist/app/Await.js +45 -0
  8. package/dist/app/Brackets.js +10 -0
  9. package/dist/app/Counter.js +19 -0
  10. package/dist/app/Debug.js +31 -0
  11. package/dist/app/DependencyCheck.js +52 -0
  12. package/dist/app/Exit.js +14 -0
  13. package/dist/app/GatherMetadata copy.js +54 -0
  14. package/dist/app/GatherMetadata.js +54 -0
  15. package/dist/app/GithubApiError.js +49 -0
  16. package/dist/app/InitMetadata.js +14 -0
  17. package/dist/app/KeepAlive.js +11 -0
  18. package/dist/app/Main copy.js +200 -0
  19. package/dist/app/ManualRebase.js +126 -0
  20. package/dist/app/MultiSelect copy.js +76 -0
  21. package/dist/app/MultiSelect.js +136 -0
  22. package/dist/app/Output.js +9 -0
  23. package/dist/app/Parens copy.js +9 -0
  24. package/dist/app/Parens.js +9 -0
  25. package/dist/app/PostRebaseStatus copy.js +23 -0
  26. package/dist/app/PostRebaseStatus.js +23 -0
  27. package/dist/app/PreSelectCommitRanges copy.js +29 -0
  28. package/dist/app/PreSelectCommitRanges.js +11 -0
  29. package/dist/app/SelectCommitRange.js +1 -0
  30. package/dist/app/SelectCommitRanges.js +182 -0
  31. package/dist/app/Status copy.js +46 -0
  32. package/dist/app/Status.js +45 -0
  33. package/dist/app/StatusTable.js +94 -0
  34. package/dist/app/Store.js +73 -0
  35. package/dist/app/Waterfall.js +20 -0
  36. package/dist/app/YesNoPrompt copy.js +24 -0
  37. package/dist/app/YesNoPrompt.js +23 -0
  38. package/dist/app/main.js +31 -0
  39. package/dist/cli.js +9 -0
  40. package/dist/command.js +22 -0
  41. package/dist/core/CommitMetadata.js +143 -0
  42. package/dist/core/Metadata.js +36 -0
  43. package/dist/core/ZustandStore.js +23 -0
  44. package/dist/core/assertNever.js +4 -0
  45. package/dist/core/cache.js +39 -0
  46. package/dist/core/capitalize.js +5 -0
  47. package/dist/core/clamp.js +6 -0
  48. package/dist/core/cli copy.js +44 -0
  49. package/dist/core/cli.js +44 -0
  50. package/dist/core/color.js +83 -0
  51. package/dist/core/date.js +18 -0
  52. package/dist/core/dependency_check.js +27 -0
  53. package/dist/core/exit.js +4 -0
  54. package/dist/core/get_commit_metadata.js +61 -0
  55. package/dist/core/github.js +45 -0
  56. package/dist/core/invariant.js +5 -0
  57. package/dist/core/is_command_available.js +15 -0
  58. package/dist/core/json.js +35 -0
  59. package/dist/core/match_group.js +9 -0
  60. package/dist/core/serialize_json.js +17 -0
  61. package/dist/core/sleep.js +3 -0
  62. package/dist/core/wrap_index.js +10 -0
  63. package/dist/index.js +13 -0
  64. package/dist/main copy.js +266 -0
  65. package/dist/main.backup.js +266 -0
  66. package/dist/main.js +265 -0
  67. package/package.json +51 -0
@@ -0,0 +1,182 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { v4 as uuid_v4 } from "uuid";
4
+ import { invariant } from "../core/invariant.js";
5
+ import { wrap_index } from "../core/wrap_index.js";
6
+ import { MultiSelect } from "./MultiSelect.js";
7
+ import { Parens } from "./Parens.js";
8
+ import { Store } from "./Store.js";
9
+ export function SelectCommitRanges() {
10
+ const commit_range = Store.useState((state) => state.commit_range);
11
+ invariant(commit_range, "commit_range must exist");
12
+ return React.createElement(SelectCommitRangesInternal, { commit_range: commit_range });
13
+ }
14
+ function SelectCommitRangesInternal(props) {
15
+ const actions = Store.useActions();
16
+ const [new_group_list, create_group] = React.useReducer((group_list, id) => {
17
+ return group_list.concat({
18
+ id,
19
+ title: id,
20
+ });
21
+ }, []);
22
+ const [commit_map, update_commit_map] = React.useReducer((map, args) => {
23
+ map.set(args.key, args.value);
24
+ // console.debug("update_commit_map", map, args);
25
+ return new Map(map);
26
+ }, new Map(), (map) => {
27
+ for (const commit of props.commit_range.commit_list) {
28
+ map.set(commit.sha, commit.branch_id);
29
+ }
30
+ return new Map(map);
31
+ });
32
+ const group_list = [];
33
+ // detect if there are unassigned commits
34
+ // unshift an unassigned group if so to collect them
35
+ let unassigned_count = 0;
36
+ for (const [, group_id] of commit_map.entries()) {
37
+ if (group_id === null) {
38
+ // console.debug("unassigned commit detected", sha);
39
+ unassigned_count++;
40
+ }
41
+ }
42
+ if (unassigned_count) {
43
+ group_list.push({
44
+ id: "unassigned",
45
+ title: "Unassigned",
46
+ });
47
+ }
48
+ group_list.push(...new_group_list);
49
+ for (const group of props.commit_range.group_list) {
50
+ if (group.pr) {
51
+ group_list.push({
52
+ id: group.id,
53
+ title: group.pr.title,
54
+ });
55
+ }
56
+ }
57
+ const [selected_group_id, set_selected_group_id] = React.useState(group_list[0].id);
58
+ const isUnassigned = selected_group_id === "unassigned";
59
+ const current_index = group_list.findIndex((g) => g.id === selected_group_id);
60
+ Ink.useInput((input, key) => {
61
+ const inputLower = input.toLowerCase();
62
+ if (unassigned_count === 0 && inputLower === "s") {
63
+ actions.set((state) => {
64
+ state.commit_map = {};
65
+ for (const [sha, id] of commit_map.entries()) {
66
+ if (id) {
67
+ state.commit_map[sha] = id;
68
+ }
69
+ }
70
+ state.step = "manual-rebase";
71
+ });
72
+ return;
73
+ }
74
+ // only allow create when on unassigned group
75
+ if (isUnassigned && inputLower === "c") {
76
+ const id = uuid_v4();
77
+ actions.output(React.createElement(Ink.Box, null,
78
+ React.createElement(Ink.Text, { dimColor: true }, "Created new group "),
79
+ React.createElement(Ink.Text, { color: "blueBright" }, id)));
80
+ create_group(id);
81
+ set_selected_group_id(id);
82
+ return;
83
+ }
84
+ if (key.leftArrow) {
85
+ const new_index = wrap_index(current_index - 1, group_list);
86
+ const next_group = group_list[new_index];
87
+ return set_selected_group_id(next_group.id);
88
+ }
89
+ if (key.rightArrow) {
90
+ const new_index = wrap_index(current_index + 1, group_list);
91
+ const next_group = group_list[new_index];
92
+ return set_selected_group_id(next_group.id);
93
+ }
94
+ });
95
+ const group = group_list[current_index];
96
+ // <- (2/4) #742 Title A ->
97
+ const max_group_label_width = 64;
98
+ let group_title_width = max_group_label_width;
99
+ const left_arrow = `${SYMBOL.left} `;
100
+ const right_arrow = ` ${SYMBOL.right}`;
101
+ const group_position = `(${current_index + 1}/${group_list.length}) `;
102
+ const title = group.title || "Unassigned";
103
+ group_title_width -= group_position.length;
104
+ group_title_width -= left_arrow.length + right_arrow.length;
105
+ group_title_width = Math.min(title.length, group_title_width);
106
+ const items = props.commit_range.commit_list.map((commit) => {
107
+ const commit_metadata_id = commit_map.get(commit.sha);
108
+ const selected = commit_metadata_id !== null;
109
+ let disabled;
110
+ if (isUnassigned) {
111
+ disabled = true;
112
+ }
113
+ else {
114
+ disabled = Boolean(selected && commit_metadata_id !== group.id);
115
+ }
116
+ return {
117
+ label: commit.message,
118
+ value: commit,
119
+ selected,
120
+ disabled,
121
+ };
122
+ });
123
+ items.reverse();
124
+ // console.debug({ group, isUnassigned });
125
+ return (React.createElement(Ink.Box, { flexDirection: "column" },
126
+ React.createElement(Ink.Box, { height: 1 }),
127
+ React.createElement(MultiSelect, { key: current_index, items: items, onSelect: (args) => {
128
+ // console.debug("onSelect", args);
129
+ const key = args.item.sha;
130
+ let value;
131
+ if (args.selected) {
132
+ value = group.id;
133
+ }
134
+ else {
135
+ value = null;
136
+ }
137
+ update_commit_map({ key, value });
138
+ } }),
139
+ React.createElement(Ink.Box, { height: 1 }),
140
+ React.createElement(Ink.Box, { width: max_group_label_width, flexDirection: "row" },
141
+ React.createElement(Ink.Text, null, left_arrow),
142
+ React.createElement(Ink.Text, null, group_position),
143
+ React.createElement(Ink.Box, { width: group_title_width, justifyContent: "center" },
144
+ React.createElement(Ink.Text, { wrap: "truncate-end" }, title)),
145
+ React.createElement(Ink.Text, null, right_arrow)),
146
+ React.createElement(Ink.Box, { height: 1 }),
147
+ unassigned_count > 0 ? (React.createElement(Ink.Text, { color: "gray" },
148
+ React.createElement(Ink.Text, { color: "#3b82f6", bold: true }, unassigned_count),
149
+ React.createElement(Ink.Text, null, " unassigned commits"),
150
+ !isUnassigned ? null : (React.createElement(Ink.Text, { color: "gray" },
151
+ React.createElement(Ink.Text, null, ", press "),
152
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, "c"),
153
+ " to ",
154
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" },
155
+ React.createElement(Parens, null, "c"),
156
+ "reate"),
157
+ " a new group")))) : (React.createElement(Ink.Text, null,
158
+ "🎉 Done! Press ",
159
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, "s"),
160
+ " to ",
161
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" },
162
+ React.createElement(Parens, null, "s"),
163
+ "ync"),
164
+ " the commits to Github")),
165
+ React.createElement(Ink.Box, null,
166
+ React.createElement(Ink.Text, { color: "gray" },
167
+ React.createElement(Ink.Text, null, "Press "),
168
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.left),
169
+ " and ",
170
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.right),
171
+ " to view PR groups")),
172
+ React.createElement(Ink.Box, null,
173
+ React.createElement(Ink.Text, { color: "gray" },
174
+ React.createElement(Ink.Text, null, "Press "),
175
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.enter),
176
+ " to toggle commit selection"))));
177
+ }
178
+ const SYMBOL = {
179
+ left: "←",
180
+ right: "→",
181
+ enter: "Enter",
182
+ };
@@ -0,0 +1,46 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { invariant } from "../core/invariant.js";
4
+ import { Await } from "./Await.js";
5
+ import { StatusTable } from "./StatusTable.js";
6
+ import { Store } from "./Store.js";
7
+ export function Status() {
8
+ const argv = Store.useState((state) => state.argv);
9
+ invariant(argv, "argv must exist");
10
+ return React.createElement(Await, { fallback: null, function: () => run({ argv }) });
11
+ }
12
+ async function run(args) {
13
+ const actions = Store.getState().actions;
14
+ const commit_range = Store.getState().commit_range;
15
+ invariant(commit_range, "commit_range must exist");
16
+ actions.output(React.createElement(StatusTable, null));
17
+ let needs_update = false;
18
+ for (const group of commit_range.group_list) {
19
+ if (group.dirty) {
20
+ needs_update = true;
21
+ break;
22
+ }
23
+ }
24
+ if (args.argv.check) {
25
+ actions.exit(0);
26
+ }
27
+ else if (args.argv.force) {
28
+ Store.setState((state) => {
29
+ state.step = "select-commit-ranges";
30
+ });
31
+ }
32
+ else if (needs_update) {
33
+ Store.setState((state) => {
34
+ state.step = "pre-select-commit-ranges";
35
+ });
36
+ }
37
+ else {
38
+ actions.newline();
39
+ actions.output(React.createElement(Ink.Text, null, "\u2705 Everything up to date."));
40
+ actions.output(React.createElement(Ink.Text, { color: "gray" },
41
+ React.createElement(Ink.Text, null, "Run with"),
42
+ React.createElement(Ink.Text, { bold: true, color: "yellow" }, ` --force `),
43
+ React.createElement(Ink.Text, null, "to force update all pull requests.")));
44
+ actions.exit(0);
45
+ }
46
+ }
@@ -0,0 +1,45 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { invariant } from "../core/invariant.js";
4
+ import { Await } from "./Await.js";
5
+ import { StatusTable } from "./StatusTable.js";
6
+ import { Store } from "./Store.js";
7
+ export function Status() {
8
+ const argv = Store.useState((state) => state.argv);
9
+ invariant(argv, "argv must exist");
10
+ return React.createElement(Await, { fallback: null, function: () => run({ argv }) });
11
+ }
12
+ async function run(args) {
13
+ const actions = Store.getState().actions;
14
+ const commit_range = Store.getState().commit_range;
15
+ invariant(commit_range, "commit_range must exist");
16
+ actions.output(React.createElement(StatusTable, null));
17
+ let needs_update = false;
18
+ for (const group of commit_range.group_list) {
19
+ if (group.dirty) {
20
+ needs_update = true;
21
+ break;
22
+ }
23
+ }
24
+ if (args.argv.check) {
25
+ actions.exit(0);
26
+ }
27
+ else if (args.argv.force) {
28
+ Store.setState((state) => {
29
+ state.step = "select-commit-ranges";
30
+ });
31
+ }
32
+ else if (needs_update) {
33
+ Store.setState((state) => {
34
+ state.step = "pre-select-commit-ranges";
35
+ });
36
+ }
37
+ else {
38
+ actions.output(React.createElement(Ink.Text, null, "\u2705 Everything up to date."));
39
+ actions.output(React.createElement(Ink.Text, { color: "gray" },
40
+ React.createElement(Ink.Text, null, "Run with"),
41
+ React.createElement(Ink.Text, { bold: true, color: "yellow" }, ` --force `),
42
+ React.createElement(Ink.Text, null, "to force update all pull requests.")));
43
+ actions.exit(0);
44
+ }
45
+ }
@@ -0,0 +1,94 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { clamp } from "../core/clamp.js";
4
+ import { invariant } from "../core/invariant.js";
5
+ import { Store } from "./Store.js";
6
+ export function StatusTable() {
7
+ const commit_range = Store.useState((state) => state.commit_range);
8
+ invariant(commit_range, "commit_range must exist");
9
+ const row_list = [];
10
+ for (const group of commit_range.group_list) {
11
+ const row = {
12
+ icon: "",
13
+ count: "",
14
+ status: "",
15
+ title: "",
16
+ url: "",
17
+ };
18
+ if (!group.pr) {
19
+ row.icon = "⭑";
20
+ row.status = "NEW";
21
+ row.title = "Unassigned";
22
+ row.count = `0/${group.commits.length}`;
23
+ row.url = "";
24
+ }
25
+ else {
26
+ if (group.dirty) {
27
+ row.icon = "!";
28
+ row.status = "OUTDATED";
29
+ }
30
+ else {
31
+ row.icon = "✔";
32
+ row.status = "SYNCED";
33
+ }
34
+ row.title = group.pr.title;
35
+ row.count = `${group.pr.commits.length}/${group.commits.length}`;
36
+ row.url = group.pr.url;
37
+ }
38
+ row_list.push(row);
39
+ }
40
+ if (!row_list.length) {
41
+ return React.createElement(Ink.Text, { dimColor: true }, "No data found.");
42
+ }
43
+ // walk data and discover max width for each column
44
+ const sample_row = row_list[0];
45
+ const col_list = Object.keys(sample_row);
46
+ const max_col_width = {};
47
+ for (const col of col_list) {
48
+ max_col_width[col] = 0;
49
+ }
50
+ for (const row of row_list) {
51
+ for (const col of col_list) {
52
+ const value = row[col];
53
+ max_col_width[col] = Math.max(value.length, max_col_width[col]);
54
+ }
55
+ }
56
+ const { stdout } = Ink.useStdout();
57
+ const available_width = stdout.columns;
58
+ const columnGap = 2;
59
+ const breathing_room = 10;
60
+ const max_title_width = Math.min(max_col_width.title, MAX_TITLE_LENGTH);
61
+ const remaining_space = clamp(available_width -
62
+ // icon
63
+ max_col_width.icon -
64
+ // status
65
+ max_col_width.status -
66
+ // commits
67
+ max_col_width.count -
68
+ // url
69
+ max_col_width.url -
70
+ // gap * col count
71
+ columnGap * col_list.length -
72
+ // remove some extra space
73
+ breathing_room, 0, max_title_width);
74
+ const title_width = remaining_space;
75
+ return (React.createElement(Ink.Box, { flexDirection: "column", width: available_width },
76
+ React.createElement(Ink.Box, { height: 1 }),
77
+ row_list.map((row) => {
78
+ return (React.createElement(Ink.Box, { key: row.url,
79
+ // borderStyle="round"
80
+ flexDirection: "row", columnGap: columnGap, width: available_width },
81
+ React.createElement(Ink.Box, { width: max_col_width.icon },
82
+ React.createElement(Ink.Text, null, row.icon)),
83
+ React.createElement(Ink.Box, { width: max_col_width.status },
84
+ React.createElement(Ink.Text, null, row.status)),
85
+ React.createElement(Ink.Box, { width: max_col_width.count },
86
+ React.createElement(Ink.Text, null, row.count)),
87
+ React.createElement(Ink.Box, { width: title_width },
88
+ React.createElement(Ink.Text, { wrap: "truncate-end" }, row.title)),
89
+ React.createElement(Ink.Box, { width: max_col_width.url },
90
+ React.createElement(Ink.Text, null, row.url))));
91
+ }),
92
+ React.createElement(Ink.Box, { height: 1 })));
93
+ }
94
+ const MAX_TITLE_LENGTH = 50;
@@ -0,0 +1,73 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { createStore, useStore } from "zustand";
4
+ import { immer } from "zustand/middleware/immer";
5
+ import { Exit } from "./Exit.js";
6
+ const BaseStore = createStore()(immer((set, get) => ({
7
+ argv: null,
8
+ ink: null,
9
+ cwd: null,
10
+ head: null,
11
+ merge_base: null,
12
+ branch_name: null,
13
+ commit_range: null,
14
+ commit_map: null,
15
+ step: "loading",
16
+ output: [],
17
+ pr: {},
18
+ actions: {
19
+ exit(code, clear = true) {
20
+ set((state) => {
21
+ state.mutate.output(state, React.createElement(Exit, { clear: clear, code: code }));
22
+ });
23
+ },
24
+ clear() {
25
+ get().ink?.clear();
26
+ },
27
+ unmount() {
28
+ get().ink?.unmount();
29
+ },
30
+ newline() {
31
+ set((state) => {
32
+ state.mutate.output(state, React.createElement(Ink.Text, null, "\u200E"));
33
+ });
34
+ },
35
+ output(node) {
36
+ set((state) => {
37
+ state.mutate.output(state, node);
38
+ });
39
+ },
40
+ debug(node) {
41
+ set((state) => {
42
+ if (state.argv?.debug) {
43
+ state.mutate.output(state, node);
44
+ }
45
+ });
46
+ },
47
+ reset_pr() {
48
+ set((state) => {
49
+ state.pr = {};
50
+ });
51
+ },
52
+ set(setter) {
53
+ set((state) => {
54
+ setter(state);
55
+ });
56
+ },
57
+ },
58
+ mutate: {
59
+ output(state, node) {
60
+ state.output.push(node);
61
+ },
62
+ },
63
+ })));
64
+ function useState(selector) {
65
+ return useStore(BaseStore, selector);
66
+ }
67
+ function useActions() {
68
+ return useState((state) => state.actions);
69
+ }
70
+ const getState = BaseStore.getState;
71
+ const setState = BaseStore.setState;
72
+ const subscribe = BaseStore.subscribe;
73
+ export const Store = { useActions, useState, getState, setState, subscribe };
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { sleep } from "../core/sleep.js";
4
+ import { Await } from "./Await.js";
5
+ import { Store } from "./Store.js";
6
+ export function Waterfall() {
7
+ return (React.createElement(Await, { fallback: React.createElement(Ink.Text, null, "Loading..."), function: async () => {
8
+ await sleep(3 * 1000);
9
+ Store.getState().actions.output(React.createElement(Ink.Text, null, "apple"));
10
+ } },
11
+ React.createElement(Await, { fallback: React.createElement(Ink.Text, null, "Loading..."), function: async () => {
12
+ await sleep(3 * 1000);
13
+ Store.getState().actions.output(React.createElement(Ink.Text, null, "banana"));
14
+ } },
15
+ React.createElement(Await, { fallback: React.createElement(Ink.Text, null, "Loading..."), function: async () => {
16
+ await sleep(3 * 1000);
17
+ Store.getState().actions.output(React.createElement(Ink.Text, null, "orange"));
18
+ } },
19
+ React.createElement(Ink.Text, null, "Waterfall")))));
20
+ }
@@ -0,0 +1,24 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ export function YesNoPrompt(props) {
4
+ Ink.useInput((input) => {
5
+ const inputLower = input.toLowerCase();
6
+ switch (inputLower) {
7
+ case "n":
8
+ return props.onNo();
9
+ case "y":
10
+ return props.onYes();
11
+ }
12
+ });
13
+ return (React.createElement(Ink.Box, { flexDirection: "column" },
14
+ React.createElement(Ink.Box, null,
15
+ React.createElement(Ink.Text, { color: "yellow" }, props.message),
16
+ React.createElement(Ink.Text, null, " "),
17
+ React.createElement(Ink.Text, { color: "#06b6d4" },
18
+ "(",
19
+ React.createElement(Ink.Text, { color: "gray" },
20
+ React.createElement(Ink.Text, { color: "#22c55e", dimColor: true }, "Y"),
21
+ "/",
22
+ React.createElement(Ink.Text, { color: "#ef4444", dimColor: true }, "n")),
23
+ ")"))));
24
+ }
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ import * as Ink from "ink";
3
+ import { Parens } from "./Parens.js";
4
+ export function YesNoPrompt(props) {
5
+ Ink.useInput((input) => {
6
+ const inputLower = input.toLowerCase();
7
+ switch (inputLower) {
8
+ case "n":
9
+ return props.onNo();
10
+ case "y":
11
+ return props.onYes();
12
+ }
13
+ });
14
+ return (React.createElement(Ink.Box, { flexDirection: "column" },
15
+ React.createElement(Ink.Box, null,
16
+ React.createElement(Ink.Text, { color: "yellow" }, props.message),
17
+ React.createElement(Ink.Text, null, " "),
18
+ React.createElement(Parens, null,
19
+ React.createElement(Ink.Text, { color: "gray" },
20
+ React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, "Y"),
21
+ "/",
22
+ React.createElement(Ink.Text, { color: "#ef4444" }, "n"))))));
23
+ }
@@ -0,0 +1,31 @@
1
+ import * as React from "react";
2
+ import { assertNever } from "../core/assertNever.js";
3
+ import { GithubApiError } from "./GithubApiError.js";
4
+ import { ManualRebase } from "./ManualRebase.js";
5
+ import { PostRebaseStatus } from "./PostRebaseStatus.js";
6
+ import { PreSelectCommitRanges } from "./PreSelectCommitRanges.js";
7
+ import { SelectCommitRanges } from "./SelectCommitRanges.js";
8
+ import { Status } from "./Status.js";
9
+ import { Store } from "./Store.js";
10
+ export function Main() {
11
+ const step = Store.useState((state) => state.step);
12
+ switch (step) {
13
+ case "github-api-error":
14
+ return React.createElement(GithubApiError, null);
15
+ case "loading":
16
+ return null;
17
+ case "status":
18
+ return React.createElement(Status, null);
19
+ case "pre-select-commit-ranges":
20
+ return React.createElement(PreSelectCommitRanges, null);
21
+ case "select-commit-ranges":
22
+ return React.createElement(SelectCommitRanges, null);
23
+ case "manual-rebase":
24
+ return React.createElement(ManualRebase, null);
25
+ case "post-rebase-status":
26
+ return React.createElement(PostRebaseStatus, null);
27
+ default:
28
+ assertNever(step);
29
+ return null;
30
+ }
31
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import * as React from "react";
3
+ import * as Ink from "ink";
4
+ import { App } from "./app/App.js";
5
+ import { command } from "./command.js";
6
+ const argv = await command();
7
+ const ink = {};
8
+ const app = Ink.render(React.createElement(App, { argv: argv, ink: ink }));
9
+ Object.assign(ink, app);
@@ -0,0 +1,22 @@
1
+ import yargs from "yargs";
2
+ import { hideBin } from "yargs/helpers";
3
+ export async function command() {
4
+ return yargs(hideBin(process.argv))
5
+ .option("force", {
6
+ type: "boolean",
7
+ description: "force",
8
+ })
9
+ .option("check", {
10
+ type: "boolean",
11
+ description: "check",
12
+ })
13
+ .option("debug", {
14
+ type: "boolean",
15
+ description: "debug",
16
+ })
17
+ .option("mock-metadata", {
18
+ type: "boolean",
19
+ description: "mock-metadata",
20
+ })
21
+ .help().argv;
22
+ }