git-stack-cli 1.15.0 → 2.0.0-beta

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 (59) hide show
  1. package/README.md +15 -14
  2. package/dist/js/index.js +45709 -0
  3. package/package.json +17 -23
  4. package/scripts/bun-build.ts +109 -0
  5. package/scripts/bun-compile.ts +79 -0
  6. package/scripts/npm-prepublishOnly.ts +1 -1
  7. package/scripts/release-brew.ts +26 -48
  8. package/scripts/release-github.ts +21 -9
  9. package/scripts/release-npm.ts +8 -11
  10. package/src/app/App.tsx +39 -31
  11. package/src/app/AutoUpdate.tsx +9 -24
  12. package/src/app/CherryPickCheck.tsx +1 -2
  13. package/src/app/Debug.tsx +3 -5
  14. package/src/app/DependencyCheck.tsx +6 -6
  15. package/src/app/DetectInitialPR.tsx +2 -8
  16. package/src/app/DirtyCheck.tsx +15 -1
  17. package/src/app/Exit.tsx +1 -5
  18. package/src/app/FormatText.tsx +1 -5
  19. package/src/app/GatherMetadata.tsx +6 -13
  20. package/src/app/GithubApiError.tsx +1 -1
  21. package/src/app/HandleCtrlCSigint.tsx +1 -12
  22. package/src/app/LocalCommitStatus.tsx +1 -3
  23. package/src/app/LogTimestamp.tsx +1 -5
  24. package/src/app/ManualRebase.tsx +4 -8
  25. package/src/app/MultiSelect.tsx +2 -2
  26. package/src/app/PostRebaseStatus.tsx +2 -0
  27. package/src/app/PreManualRebase.tsx +3 -5
  28. package/src/app/RebaseCheck.tsx +1 -2
  29. package/src/app/SelectCommitRanges.tsx +6 -10
  30. package/src/app/Status.tsx +1 -1
  31. package/src/app/StatusTable.tsx +1 -4
  32. package/src/app/Store.tsx +5 -1
  33. package/src/app/SyncGithub.tsx +4 -16
  34. package/src/app/Table.tsx +4 -14
  35. package/src/app/TextInput.tsx +2 -7
  36. package/src/app/VerboseDebugInfo.tsx +1 -5
  37. package/src/app/YesNoPrompt.tsx +42 -31
  38. package/src/command.ts +8 -17
  39. package/src/commands/Fixup.tsx +15 -22
  40. package/src/commands/Log.tsx +3 -7
  41. package/src/commands/Rebase.tsx +6 -8
  42. package/src/components/ErrorBoundary.tsx +79 -0
  43. package/src/components/ExitingGate.tsx +27 -0
  44. package/src/core/CommitMetadata.ts +1 -1
  45. package/src/core/GitReviseTodo.test.ts +3 -3
  46. package/src/core/GitReviseTodo.ts +8 -12
  47. package/src/core/Metadata.test.ts +4 -4
  48. package/src/core/StackSummaryTable.ts +3 -3
  49. package/src/core/chalk.ts +1 -5
  50. package/src/core/cli.ts +2 -2
  51. package/src/core/github.tsx +7 -13
  52. package/src/core/pretty_json.ts +1 -6
  53. package/src/github/gh.auth_status.test.ts +2 -6
  54. package/src/index.tsx +28 -3
  55. package/src/types/global.d.ts +0 -1
  56. package/tsconfig.json +1 -1
  57. package/dist/cjs/index.cjs +0 -38461
  58. package/rollup.config.js +0 -54
  59. package/scripts/build-standalone.ts +0 -73
@@ -67,14 +67,10 @@ export function AutoUpdate(props: Props) {
67
67
 
68
68
  async function auto_update() {
69
69
  if (props_ref.current.verbose) {
70
- handle_output(
71
- <Ink.Text key="init">Checking for latest version...</Ink.Text>
72
- );
70
+ handle_output(<Ink.Text key="init">Checking for latest version...</Ink.Text>);
73
71
  }
74
72
 
75
- const timeout_ms = is_finite_value(props.timeoutMs)
76
- ? props.timeoutMs
77
- : 2 * 1000;
73
+ const timeout_ms = is_finite_value(props.timeoutMs) ? props.timeoutMs : 2 * 1000;
78
74
 
79
75
  const npm_json = await Promise.race([
80
76
  fetch_json(`https://registry.npmjs.org/${props.name}`),
@@ -94,12 +90,7 @@ export function AutoUpdate(props: Props) {
94
90
  const script_dir = path.dirname(script_path);
95
91
 
96
92
  // dist/ts/index.js
97
- const package_json_path = path.join(
98
- script_dir,
99
- "..",
100
- "..",
101
- "package.json"
102
- );
93
+ const package_json_path = path.join(script_dir, "..", "..", "package.json");
103
94
 
104
95
  type PackageJson = { version: string };
105
96
  const package_json = await read_json<PackageJson>(package_json_path);
@@ -121,7 +112,7 @@ export function AutoUpdate(props: Props) {
121
112
  latest_version: <Brackets>{latest_version}</Brackets>,
122
113
  local_version: <Brackets>{local_version}</Brackets>,
123
114
  }}
124
- />
115
+ />,
125
116
  );
126
117
  }
127
118
 
@@ -134,7 +125,7 @@ export function AutoUpdate(props: Props) {
134
125
  if (semver_result === -1) {
135
126
  // latest version is less than or equal to local version, skip auto update
136
127
  throw new Error(
137
- `latest version < local_version, skipping auto update [${latest_version} < ${local_version}]`
128
+ `latest version < local_version, skipping auto update [${latest_version} < ${local_version}]`,
138
129
  );
139
130
  }
140
131
 
@@ -156,7 +147,7 @@ export function AutoUpdate(props: Props) {
156
147
  handle_output(
157
148
  <Ink.Text key="error" color={colors.red}>
158
149
  {error?.message}
159
- </Ink.Text>
150
+ </Ink.Text>,
160
151
  );
161
152
  }
162
153
  })
@@ -185,16 +176,10 @@ export function AutoUpdate(props: Props) {
185
176
  wrapper={<Ink.Text />}
186
177
  message="Installing {name}@{version}..."
187
178
  values={{
188
- name: (
189
- <Ink.Text color={colors.yellow}>{props.name}</Ink.Text>
190
- ),
191
- version: (
192
- <Ink.Text color={colors.blue}>
193
- {state.latest_version}
194
- </Ink.Text>
195
- ),
179
+ name: <Ink.Text color={colors.yellow}>{props.name}</Ink.Text>,
180
+ version: <Ink.Text color={colors.blue}>{state.latest_version}</Ink.Text>,
196
181
  }}
197
- />
182
+ />,
198
183
  );
199
184
 
200
185
  patch({ status: "install" });
@@ -40,8 +40,7 @@ export function CherryPickCheck(props: Props) {
40
40
  <YesNoPrompt
41
41
  message={
42
42
  <Ink.Text color={colors.yellow}>
43
- <Command>git cherry-pick</Command> detected, would you like to
44
- abort it?
43
+ <Command>git cherry-pick</Command> detected, would you like to abort it?
45
44
  </Ink.Text>
46
45
  }
47
46
  onYes={async () => {
package/src/app/Debug.tsx CHANGED
@@ -20,12 +20,10 @@ export function Debug() {
20
20
  React.useEffect(
21
21
  function debugMessageOnce() {
22
22
  if (debug) {
23
- actions.output(
24
- <Ink.Text color={colors.yellow}>Debug mode enabled</Ink.Text>
25
- );
23
+ actions.output(<Ink.Text color={colors.yellow}>Debug mode enabled</Ink.Text>);
26
24
  }
27
25
  },
28
- [argv]
26
+ [argv],
29
27
  );
30
28
 
31
29
  React.useEffect(
@@ -46,7 +44,7 @@ export function Debug() {
46
44
  await fs.writeFile(output_file, content);
47
45
  }
48
46
  },
49
- [argv, state]
47
+ [argv, state],
50
48
  );
51
49
 
52
50
  return null;
@@ -55,7 +55,7 @@ function CheckGit(props: Props) {
55
55
  actions.output(
56
56
  <Ink.Text color={colors.yellow}>
57
57
  <Command>git</Command> must be installed.
58
- </Ink.Text>
58
+ </Ink.Text>,
59
59
  );
60
60
 
61
61
  actions.exit(2);
@@ -86,7 +86,7 @@ function CheckGithubCli(props: Props) {
86
86
  actions.output(
87
87
  <Ink.Text color={colors.yellow}>
88
88
  <Command>gh</Command> must be installed.
89
- </Ink.Text>
89
+ </Ink.Text>,
90
90
  );
91
91
 
92
92
  actions.output(
@@ -98,7 +98,7 @@ function CheckGithubCli(props: Props) {
98
98
 
99
99
  command: <Command>gh</Command>,
100
100
  }}
101
- />
101
+ />,
102
102
  );
103
103
 
104
104
  actions.exit(3);
@@ -150,7 +150,7 @@ function CheckGithubCliAuth(props: Props) {
150
150
 
151
151
  command: <Command>gh auth login</Command>,
152
152
  }}
153
- />
153
+ />,
154
154
  );
155
155
 
156
156
  actions.exit(4);
@@ -181,7 +181,7 @@ function CheckGitRevise(props: Props) {
181
181
  actions.output(
182
182
  <Ink.Text color={colors.yellow}>
183
183
  <Command>git revise</Command> must be installed.
184
- </Ink.Text>
184
+ </Ink.Text>,
185
185
  );
186
186
 
187
187
  actions.output(
@@ -199,7 +199,7 @@ function CheckGitRevise(props: Props) {
199
199
  </Parens>
200
200
  ),
201
201
  }}
202
- />
202
+ />,
203
203
  );
204
204
 
205
205
  actions.exit(10);
@@ -97,11 +97,7 @@ export function DetectInitialPR(props: Props) {
97
97
  return (
98
98
  <Await
99
99
  function={run}
100
- fallback={
101
- <Ink.Text color={colors.yellow}>
102
- Checking for existing PR on Github…
103
- </Ink.Text>
104
- }
100
+ fallback={<Ink.Text color={colors.yellow}>Checking for existing PR on Github…</Ink.Text>}
105
101
  />
106
102
  );
107
103
  }
@@ -167,9 +163,7 @@ export function DetectInitialPR(props: Props) {
167
163
  // get latest merge_base relative to local master
168
164
  const rebase_group_index = 0;
169
165
 
170
- const rebase_merge_base = (
171
- await cli(`git merge-base HEAD ${master_branch}`)
172
- ).stdout;
166
+ const rebase_merge_base = (await cli(`git merge-base HEAD ${master_branch}`)).stdout;
173
167
 
174
168
  await GitReviseTodo.execute({
175
169
  rebase_group_index,
@@ -33,6 +33,14 @@ export function DirtyCheck(props: Props) {
33
33
  case "done":
34
34
  return props.children;
35
35
 
36
+ case "stash":
37
+ return (
38
+ <FormatText
39
+ wrapper={<Ink.Text color={colors.yellow} />}
40
+ message="📦 Stashing uncommitted changes…"
41
+ />
42
+ );
43
+
36
44
  case "prompt":
37
45
  return (
38
46
  <Ink.Box flexDirection="column">
@@ -56,9 +64,15 @@ export function DirtyCheck(props: Props) {
56
64
  />
57
65
  }
58
66
  onYes={async () => {
67
+ patch({ status: "stash" });
68
+
59
69
  await cli("git stash --include-untracked");
60
70
 
61
- actions.output(<Ink.Text>📦 Changes saved to stash</Ink.Text>);
71
+ actions.output(
72
+ <Ink.Text color={colors.yellow}>
73
+ <FormatText message="📦 Changes saved to stash" />
74
+ </Ink.Text>,
75
+ );
62
76
 
63
77
  actions.set((state) => {
64
78
  state.is_dirty_check_stash = true;
package/src/app/Exit.tsx CHANGED
@@ -36,11 +36,7 @@ export function Exit(props: Props) {
36
36
  // restore git stash if necessary
37
37
  if (state.is_dirty_check_stash) {
38
38
  await cli("git stash pop");
39
- actions.output(
40
- <Ink.Text color={colors.green}>
41
- ✅ Changes restored from stash
42
- </Ink.Text>
43
- );
39
+ actions.output(<Ink.Text color={colors.green}>✅ Changes restored from stash</Ink.Text>);
44
40
  }
45
41
 
46
42
  // ensure output has a chance to render
@@ -13,11 +13,7 @@ export function FormatText(props: Props) {
13
13
  const wrapper = (props.wrapper as React.ReactElement) || <Ink.Text />;
14
14
 
15
15
  return (
16
- <FormattedMessage
17
- id="FormatText"
18
- defaultMessage={props.message}
19
- values={props.values}
20
- >
16
+ <FormattedMessage id="FormatText" defaultMessage={props.message} values={props.values}>
21
17
  {(chunks) => {
22
18
  return React.cloneElement(wrapper, {}, chunks);
23
19
  }}
@@ -15,9 +15,7 @@ type Props = {
15
15
  };
16
16
 
17
17
  export function GatherMetadata(props: Props) {
18
- const fallback = (
19
- <Ink.Text color={colors.yellow}>Gathering local git information…</Ink.Text>
20
- );
18
+ const fallback = <Ink.Text color={colors.yellow}>Gathering local git information…</Ink.Text>;
21
19
 
22
20
  return (
23
21
  <Await fallback={fallback} function={run}>
@@ -41,14 +39,12 @@ async function run() {
41
39
  values={{
42
40
  branch: <Brackets>{argv.branch}</Brackets>,
43
41
  }}
44
- />
42
+ />,
45
43
  );
46
44
 
47
45
  master_branch = argv.branch;
48
46
  } else {
49
- const detect_master = await cli(
50
- `git branch --list "${BRANCH.master}" --color=never`
51
- );
47
+ const detect_master = await cli(`git branch --list "${BRANCH.master}" --color=never`);
52
48
 
53
49
  if (detect_master.stdout !== "") {
54
50
  master_branch = BRANCH.master;
@@ -60,7 +56,7 @@ async function run() {
60
56
  master: <Brackets>{BRANCH.master}</Brackets>,
61
57
  main: <Brackets>{BRANCH.main}</Brackets>,
62
58
  }}
63
- />
59
+ />,
64
60
  );
65
61
 
66
62
  master_branch = BRANCH.main;
@@ -84,15 +80,12 @@ async function run() {
84
80
  }
85
81
 
86
82
  const head = (await cli("git rev-parse HEAD")).stdout;
87
- const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
88
- .stdout;
83
+ const merge_base = (await cli(`git merge-base HEAD ${master_branch}`)).stdout;
89
84
 
90
85
  // handle when there are no detected changes
91
86
  if (head === merge_base) {
92
87
  actions.newline();
93
- actions.output(
94
- <Ink.Text color={colors.gray}>No changes detected.</Ink.Text>
95
- );
88
+ actions.output(<Ink.Text color={colors.gray}>No changes detected.</Ink.Text>);
96
89
  actions.exit(0);
97
90
  return;
98
91
  }
@@ -69,6 +69,6 @@ async function run() {
69
69
  {time_until}
70
70
  </Ink.Text>
71
71
  </Parens>
72
- </Ink.Text>
72
+ </Ink.Text>,
73
73
  );
74
74
  }
@@ -10,8 +10,6 @@ import { sleep } from "~/core/sleep";
10
10
  export function HandleCtrlCSigint() {
11
11
  const actions = Store.useActions();
12
12
 
13
- const [exiting, set_exiting] = React.useState(false);
14
-
15
13
  Ink.useInput((input, key) => {
16
14
  handle_input().catch((err) => {
17
15
  // eslint-disable-next-line no-console
@@ -25,23 +23,14 @@ export function HandleCtrlCSigint() {
25
23
  actions.output(
26
24
  <Ink.Text color={colors.red}>
27
25
  <FormatText message="🚨 Ctrl+C detected" />
28
- </Ink.Text>
26
+ </Ink.Text>,
29
27
  );
30
28
 
31
- set_exiting(true);
32
29
  await sleep(1);
33
30
  actions.exit(235);
34
31
  }
35
32
  }
36
33
  });
37
34
 
38
- if (exiting) {
39
- return (
40
- <Ink.Text color={colors.red}>
41
- <FormatText message="🚨 Exiting…" />
42
- </Ink.Text>
43
- );
44
- }
45
-
46
35
  return null;
47
36
  }
@@ -15,9 +15,7 @@ type Props = {
15
15
  export function LocalCommitStatus(props: Props) {
16
16
  const argv = Store.useState((state) => state.argv);
17
17
 
18
- const fallback = (
19
- <Ink.Text color={colors.yellow}>Fetching PR status from Github…</Ink.Text>
20
- );
18
+ const fallback = <Ink.Text color={colors.yellow}>Fetching PR status from Github…</Ink.Text>;
21
19
 
22
20
  if (argv["mock-metadata"]) {
23
21
  return (
@@ -4,9 +4,5 @@ import * as Ink from "ink-cjs";
4
4
  import { DateTime } from "luxon";
5
5
 
6
6
  export function LogTimestamp() {
7
- return (
8
- <Ink.Text dimColor>
9
- {DateTime.now().toFormat("[yyyy-MM-dd HH:mm:ss.SSS] ")}
10
- </Ink.Text>
11
- );
7
+ return <Ink.Text dimColor>{DateTime.now().toFormat("[yyyy-MM-dd HH:mm:ss.SSS] ")}</Ink.Text>;
12
8
  }
@@ -16,10 +16,7 @@ import { short_id } from "~/core/short_id";
16
16
 
17
17
  export function ManualRebase() {
18
18
  return (
19
- <Await
20
- fallback={<Ink.Text color={colors.yellow}>Rebasing commits…</Ink.Text>}
21
- function={run}
22
- />
19
+ <Await fallback={<Ink.Text color={colors.yellow}>Rebasing commits…</Ink.Text>} function={run} />
23
20
  );
24
21
  }
25
22
 
@@ -48,8 +45,7 @@ async function run() {
48
45
 
49
46
  try {
50
47
  // get latest merge_base relative to local master
51
- const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
52
- .stdout;
48
+ const merge_base = (await cli(`git merge-base HEAD ${master_branch}`)).stdout;
53
49
 
54
50
  // immediately paint all commit to preserve selected commit ranges
55
51
  let commit_range = await CommitMetadata.range(commit_map);
@@ -173,7 +169,7 @@ async function run() {
173
169
  actions.output(
174
170
  <Ink.Text color={colors.yellow}>
175
171
  Restoring <Brackets>{branch_name}</Brackets>…
176
- </Ink.Text>
172
+ </Ink.Text>,
177
173
  );
178
174
 
179
175
  restore_git();
@@ -181,7 +177,7 @@ async function run() {
181
177
  actions.output(
182
178
  <Ink.Text color={colors.yellow}>
183
179
  Restored <Brackets>{branch_name}</Brackets>.
184
- </Ink.Text>
180
+ </Ink.Text>,
185
181
  );
186
182
  }
187
183
  }
@@ -51,7 +51,7 @@ export function MultiSelect<T>(props: Props<T>) {
51
51
  });
52
52
 
53
53
  return set;
54
- }
54
+ },
55
55
  );
56
56
 
57
57
  // clamp index to keep in item range
@@ -81,7 +81,7 @@ export function MultiSelect<T>(props: Props<T>) {
81
81
  }
82
82
 
83
83
  return 0;
84
- }
84
+ },
85
85
  );
86
86
 
87
87
  const selectRef = React.useRef(false);
@@ -26,4 +26,6 @@ async function run() {
26
26
  actions.output(<StatusTable />);
27
27
 
28
28
  actions.output(<Ink.Text>✅ Everything up to date.</Ink.Text>);
29
+
30
+ actions.exit(0);
29
31
  }
@@ -51,7 +51,7 @@ async function run() {
51
51
  values={{
52
52
  pr_filepath: <Brackets>{pr_template_fn("")}</Brackets>,
53
53
  }}
54
- />
54
+ />,
55
55
  );
56
56
 
57
57
  break;
@@ -75,12 +75,10 @@ async function run() {
75
75
  wrapper={<Ink.Text color={colors.yellow} />}
76
76
  message="{count} queryable templates found under {dir}, but not supported."
77
77
  values={{
78
- count: (
79
- <Ink.Text color={colors.blue}>{pr_templates.length}</Ink.Text>
80
- ),
78
+ count: <Ink.Text color={colors.blue}>{pr_templates.length}</Ink.Text>,
81
79
  dir: <Brackets>{PR_TEMPLATE.TemplateDir("")}</Brackets>,
82
80
  }}
83
- />
81
+ />,
84
82
  );
85
83
  }
86
84
 
@@ -40,8 +40,7 @@ export function RebaseCheck(props: Props) {
40
40
  <YesNoPrompt
41
41
  message={
42
42
  <Ink.Text color={colors.yellow}>
43
- <Command>git rebase</Command> detected, would you like to abort
44
- it?
43
+ <Command>git rebase</Command> detected, would you like to abort it?
45
44
  </Ink.Text>
46
45
  }
47
46
  onYes={async () => {
@@ -37,7 +37,7 @@ function SelectCommitRangesInternal(props: Props) {
37
37
 
38
38
  const [selected_group_id, set_selected_group_id] = React.useState(() => {
39
39
  const first_group = props.commit_range.group_list.find(
40
- (g) => g.id !== props.commit_range.UNASSIGNED
40
+ (g) => g.id !== props.commit_range.UNASSIGNED,
41
41
  );
42
42
 
43
43
  if (first_group) {
@@ -54,14 +54,11 @@ function SelectCommitRangesInternal(props: Props) {
54
54
  const next_group_list = group_list.concat(group);
55
55
  return next_group_list;
56
56
  },
57
- []
57
+ [],
58
58
  );
59
59
 
60
60
  const [commit_map, update_commit_map] = React.useReducer(
61
- (
62
- map: Map<string, null | string>,
63
- args: { key: string; value: null | string }
64
- ) => {
61
+ (map: Map<string, null | string>, args: { key: string; value: null | string }) => {
65
62
  map.set(args.key, args.value);
66
63
 
67
64
  // console.debug("update_commit_map", map, args);
@@ -74,7 +71,7 @@ function SelectCommitRangesInternal(props: Props) {
74
71
  }
75
72
 
76
73
  return new Map(map);
77
- }
74
+ },
78
75
  );
79
76
 
80
77
  const group_list: Array<SimpleGroup> = [];
@@ -88,8 +85,7 @@ function SelectCommitRangesInternal(props: Props) {
88
85
  }
89
86
  }
90
87
 
91
- const total_group_count =
92
- new_group_list.length + props.commit_range.group_list.length;
88
+ const total_group_count = new_group_list.length + props.commit_range.group_list.length;
93
89
 
94
90
  for (let i = 0; i < props.commit_range.group_list.length; i++) {
95
91
  const index = props.commit_range.group_list.length - i - 1;
@@ -411,7 +407,7 @@ function SelectCommitRangesInternal(props: Props) {
411
407
  group: <Brackets>{title}</Brackets>,
412
408
  note: <Parens>{id}</Parens>,
413
409
  }}
414
- />
410
+ />,
415
411
  );
416
412
 
417
413
  // console.debug("submit_group_input", { title, id });
@@ -59,7 +59,7 @@ async function run() {
59
59
  {` --force `}
60
60
  </Ink.Text>
61
61
  <Ink.Text>to force update all pull requests.</Ink.Text>
62
- </Ink.Text>
62
+ </Ink.Text>,
63
63
  );
64
64
 
65
65
  actions.exit(0);
@@ -84,10 +84,7 @@ function StatusColumn(props: TableColumnProps<Row>) {
84
84
  const value = props.row[props.column];
85
85
 
86
86
  return (
87
- <Ink.Text
88
- color={get_status_color(props.row)}
89
- bold={get_status_bold(props.row)}
90
- >
87
+ <Ink.Text color={get_status_color(props.row)} bold={get_status_bold(props.row)}>
91
88
  {get_status_icon(props.row)} {value}
92
89
  </Ink.Text>
93
90
  );
package/src/app/Store.tsx CHANGED
@@ -53,6 +53,7 @@ export type State = {
53
53
  sync_github: null | SyncGithubState;
54
54
  is_dirty_check_stash: boolean;
55
55
  abort_handler: null | AbortHandler;
56
+ is_exiting: boolean;
56
57
 
57
58
  step:
58
59
  | "github-api-error"
@@ -123,6 +124,7 @@ const BaseStore = createStore<State>()(
123
124
  sync_github: null,
124
125
  is_dirty_check_stash: false,
125
126
  abort_handler: null,
127
+ is_exiting: false,
126
128
 
127
129
  step: "loading",
128
130
 
@@ -134,6 +136,8 @@ const BaseStore = createStore<State>()(
134
136
  actions: {
135
137
  exit(code, clear = true) {
136
138
  set((state) => {
139
+ state.is_exiting = true;
140
+
137
141
  const node = <Exit clear={clear} code={code} />;
138
142
  state.mutate.output(state, { node });
139
143
  });
@@ -260,7 +264,7 @@ const BaseStore = createStore<State>()(
260
264
  return state.argv?.verbose || false;
261
265
  },
262
266
  },
263
- }))
267
+ })),
264
268
  );
265
269
 
266
270
  function renderOutputArgs(args: MutateOutputArgs) {
@@ -14,12 +14,7 @@ import { invariant } from "~/core/invariant";
14
14
  import type * as CommitMetadata from "~/core/CommitMetadata";
15
15
 
16
16
  export function SyncGithub() {
17
- return (
18
- <Await
19
- fallback={<Ink.Text color={colors.yellow}>Syncing…</Ink.Text>}
20
- function={run}
21
- />
22
- );
17
+ return <Await fallback={<Ink.Text color={colors.yellow}>Syncing…</Ink.Text>} function={run} />;
23
18
  }
24
19
 
25
20
  async function run() {
@@ -202,10 +197,7 @@ async function run() {
202
197
  }
203
198
  }
204
199
 
205
- async function after_push(args: {
206
- group: CommitMetadataGroup;
207
- pr_url_list: Array<string>;
208
- }) {
200
+ async function after_push(args: { group: CommitMetadataGroup; pr_url_list: Array<string> }) {
209
201
  const { group, pr_url_list } = args;
210
202
 
211
203
  invariant(group.base, "group.base must exist");
@@ -290,9 +282,7 @@ async function run() {
290
282
  }
291
283
 
292
284
  function handle_exit() {
293
- actions.output(
294
- <Ink.Text color={colors.yellow}>Restoring PR state…</Ink.Text>
295
- );
285
+ actions.output(<Ink.Text color={colors.yellow}>Restoring PR state…</Ink.Text>);
296
286
 
297
287
  for (const group of push_group_list) {
298
288
  // we may temporarily mark PR as a draft before editing it
@@ -310,9 +300,7 @@ async function run() {
310
300
  }
311
301
  }
312
302
 
313
- actions.output(
314
- <Ink.Text color={colors.yellow}>Restored PR state.</Ink.Text>
315
- );
303
+ actions.output(<Ink.Text color={colors.yellow}>Restored PR state.</Ink.Text>);
316
304
  }
317
305
  }
318
306
 
package/src/app/Table.tsx CHANGED
@@ -70,10 +70,7 @@ export function Table<T extends BaseRow>(props: Props<T>) {
70
70
  remaining_space -= breathing_room;
71
71
 
72
72
  if (props.fillColumn) {
73
- max_col_width[props.fillColumn] = Math.min(
74
- max_col_width[props.fillColumn],
75
- remaining_space
76
- );
73
+ max_col_width[props.fillColumn] = Math.min(max_col_width[props.fillColumn], remaining_space);
77
74
  }
78
75
  }
79
76
 
@@ -91,9 +88,7 @@ export function Table<T extends BaseRow>(props: Props<T>) {
91
88
  width={available_width}
92
89
  >
93
90
  {RowColumnList.map((column) => {
94
- const ColumnComponent = props.columns[
95
- column
96
- ] as ColumnComponent<T>;
91
+ const ColumnComponent = props.columns[column] as ColumnComponent<T>;
97
92
 
98
93
  return (
99
94
  <Ink.Box key={String(column)} width={max_col_width[column]}>
@@ -122,14 +117,9 @@ type BaseRow = Record<string, string | number>;
122
117
 
123
118
  type Column<T extends BaseRow> = keyof T;
124
119
 
125
- type ColumnComponent<T extends BaseRow> = (
126
- props: TableColumnProps<T>
127
- ) => React.ReactNode;
120
+ type ColumnComponent<T extends BaseRow> = (props: TableColumnProps<T>) => React.ReactNode;
128
121
 
129
- type ColumnComponentMap<T extends BaseRow> = Record<
130
- Column<T>,
131
- ColumnComponent<T>
132
- >;
122
+ type ColumnComponentMap<T extends BaseRow> = Record<Column<T>, ColumnComponent<T>>;
133
123
 
134
124
  export type TableColumnProps<T extends BaseRow> = {
135
125
  row: T;