@akiojin/gwt 2.0.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 (132) hide show
  1. package/README.ja.md +323 -0
  2. package/README.md +347 -0
  3. package/bin/gwt.js +5 -0
  4. package/package.json +125 -0
  5. package/src/claude-history.ts +717 -0
  6. package/src/claude.ts +292 -0
  7. package/src/cli/ui/__tests__/SKIPPED_TESTS.md +119 -0
  8. package/src/cli/ui/__tests__/acceptance/branchList.acceptance.test.tsx.skip +239 -0
  9. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +214 -0
  10. package/src/cli/ui/__tests__/acceptance/realtimeUpdate.acceptance.test.tsx.skip +219 -0
  11. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +183 -0
  12. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +313 -0
  13. package/src/cli/ui/__tests__/components/App.test.tsx +270 -0
  14. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +66 -0
  15. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +103 -0
  16. package/src/cli/ui/__tests__/components/common/Input.test.tsx +92 -0
  17. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +127 -0
  18. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +264 -0
  19. package/src/cli/ui/__tests__/components/common/Select.test.tsx +246 -0
  20. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +62 -0
  21. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +54 -0
  22. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +68 -0
  23. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +135 -0
  24. package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +153 -0
  25. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +215 -0
  26. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +293 -0
  27. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +161 -0
  28. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +215 -0
  29. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +99 -0
  30. package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +127 -0
  31. package/src/cli/ui/__tests__/hooks/useGitData.test.ts.skip +228 -0
  32. package/src/cli/ui/__tests__/hooks/useScreenState.test.ts +146 -0
  33. package/src/cli/ui/__tests__/hooks/useTerminalSize.test.ts +98 -0
  34. package/src/cli/ui/__tests__/integration/branchList.test.tsx.skip +253 -0
  35. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +306 -0
  36. package/src/cli/ui/__tests__/integration/navigation.test.tsx +405 -0
  37. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +505 -0
  38. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx.skip +216 -0
  39. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +180 -0
  40. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +237 -0
  41. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +775 -0
  42. package/src/cli/ui/__tests__/utils/statisticsCalculator.test.ts +243 -0
  43. package/src/cli/ui/components/App.tsx +793 -0
  44. package/src/cli/ui/components/common/Confirm.tsx +40 -0
  45. package/src/cli/ui/components/common/ErrorBoundary.tsx +57 -0
  46. package/src/cli/ui/components/common/Input.tsx +36 -0
  47. package/src/cli/ui/components/common/LoadingIndicator.tsx +95 -0
  48. package/src/cli/ui/components/common/Select.tsx +216 -0
  49. package/src/cli/ui/components/parts/Footer.tsx +41 -0
  50. package/src/cli/ui/components/parts/Header.test.tsx +85 -0
  51. package/src/cli/ui/components/parts/Header.tsx +63 -0
  52. package/src/cli/ui/components/parts/MergeStatusList.tsx +75 -0
  53. package/src/cli/ui/components/parts/ProgressBar.tsx +73 -0
  54. package/src/cli/ui/components/parts/ScrollableList.tsx +24 -0
  55. package/src/cli/ui/components/parts/Stats.tsx +67 -0
  56. package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +116 -0
  57. package/src/cli/ui/components/screens/BatchMergeProgressScreen.tsx +70 -0
  58. package/src/cli/ui/components/screens/BatchMergeResultScreen.tsx +104 -0
  59. package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +213 -0
  60. package/src/cli/ui/components/screens/BranchListScreen.tsx +299 -0
  61. package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +149 -0
  62. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +167 -0
  63. package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +100 -0
  64. package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +117 -0
  65. package/src/cli/ui/hooks/useBatchMerge.ts +96 -0
  66. package/src/cli/ui/hooks/useGitData.ts +157 -0
  67. package/src/cli/ui/hooks/useScreenState.ts +44 -0
  68. package/src/cli/ui/hooks/useTerminalSize.ts +33 -0
  69. package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +102 -0
  70. package/src/cli/ui/screens/__tests__/BranchActionSelectorScreen.test.tsx +151 -0
  71. package/src/cli/ui/types.ts +295 -0
  72. package/src/cli/ui/utils/baseBranch.ts +34 -0
  73. package/src/cli/ui/utils/branchFormatter.ts +222 -0
  74. package/src/cli/ui/utils/statisticsCalculator.ts +44 -0
  75. package/src/codex.ts +139 -0
  76. package/src/config/builtin-tools.ts +44 -0
  77. package/src/config/constants.ts +100 -0
  78. package/src/config/env-history.ts +45 -0
  79. package/src/config/index.ts +204 -0
  80. package/src/config/tools.ts +293 -0
  81. package/src/git.ts +1102 -0
  82. package/src/github.ts +158 -0
  83. package/src/index.test.ts +87 -0
  84. package/src/index.ts +684 -0
  85. package/src/index.ts.backup +1543 -0
  86. package/src/launcher.ts +142 -0
  87. package/src/repositories/git.repository.ts +129 -0
  88. package/src/repositories/github.repository.ts +83 -0
  89. package/src/repositories/worktree.repository.ts +69 -0
  90. package/src/services/BatchMergeService.ts +251 -0
  91. package/src/services/WorktreeOrchestrator.ts +115 -0
  92. package/src/services/__tests__/BatchMergeService.test.ts +518 -0
  93. package/src/services/__tests__/WorktreeOrchestrator.test.ts +258 -0
  94. package/src/services/dependency-installer.ts +199 -0
  95. package/src/services/git.service.ts +113 -0
  96. package/src/services/github.service.ts +61 -0
  97. package/src/services/worktree.service.ts +66 -0
  98. package/src/types/api.ts +241 -0
  99. package/src/types/tools.ts +235 -0
  100. package/src/utils/spinner.ts +54 -0
  101. package/src/utils/terminal.ts +272 -0
  102. package/src/utils.test.ts +43 -0
  103. package/src/utils.ts +60 -0
  104. package/src/web/client/index.html +12 -0
  105. package/src/web/client/src/components/BranchGraph.tsx +231 -0
  106. package/src/web/client/src/components/EnvEditor.tsx +145 -0
  107. package/src/web/client/src/components/Terminal.tsx +137 -0
  108. package/src/web/client/src/hooks/useBranches.ts +41 -0
  109. package/src/web/client/src/hooks/useConfig.ts +31 -0
  110. package/src/web/client/src/hooks/useSessions.ts +59 -0
  111. package/src/web/client/src/hooks/useWorktrees.ts +47 -0
  112. package/src/web/client/src/index.css +834 -0
  113. package/src/web/client/src/lib/api.ts +184 -0
  114. package/src/web/client/src/lib/websocket.ts +174 -0
  115. package/src/web/client/src/main.tsx +29 -0
  116. package/src/web/client/src/pages/BranchDetailPage.tsx +847 -0
  117. package/src/web/client/src/pages/BranchListPage.tsx +264 -0
  118. package/src/web/client/src/pages/ConfigManagementPage.tsx +203 -0
  119. package/src/web/client/src/router.tsx +27 -0
  120. package/src/web/client/vite.config.ts +21 -0
  121. package/src/web/server/env/importer.ts +54 -0
  122. package/src/web/server/index.ts +74 -0
  123. package/src/web/server/pty/manager.ts +189 -0
  124. package/src/web/server/routes/branches.ts +126 -0
  125. package/src/web/server/routes/config.ts +220 -0
  126. package/src/web/server/routes/index.ts +37 -0
  127. package/src/web/server/routes/sessions.ts +130 -0
  128. package/src/web/server/routes/worktrees.ts +108 -0
  129. package/src/web/server/services/branches.ts +368 -0
  130. package/src/web/server/services/worktrees.ts +85 -0
  131. package/src/web/server/websocket/handler.ts +180 -0
  132. package/src/worktree.ts +703 -0
@@ -0,0 +1,145 @@
1
+ import React from "react";
2
+
3
+ export interface EnvRow {
4
+ id: string;
5
+ key: string;
6
+ value: string;
7
+ importedFromOs?: boolean;
8
+ lastUpdated?: string | null;
9
+ }
10
+
11
+ interface EnvEditorProps {
12
+ title: string;
13
+ rows: EnvRow[];
14
+ onChange: (rows: EnvRow[]) => void;
15
+ description?: string;
16
+ allowAdd?: boolean;
17
+ emptyLabel?: string;
18
+ }
19
+
20
+ const KEY_PATTERN = /^[A-Z0-9_]+$/;
21
+
22
+ export function createEnvRow(variable?: Partial<EnvRow>): EnvRow {
23
+ const row: EnvRow = {
24
+ id: variable?.id ?? `env-${Date.now()}-${Math.random().toString(36).slice(2)}`,
25
+ key: variable?.key ?? "",
26
+ value: variable?.value ?? "",
27
+ };
28
+
29
+ if (typeof variable?.importedFromOs === "boolean") {
30
+ row.importedFromOs = variable.importedFromOs;
31
+ }
32
+ if (variable?.lastUpdated) {
33
+ row.lastUpdated = variable.lastUpdated;
34
+ }
35
+
36
+ return row;
37
+ }
38
+
39
+ function isInvalidKey(row: EnvRow): boolean {
40
+ if (!row.key) return true;
41
+ return !KEY_PATTERN.test(row.key);
42
+ }
43
+
44
+ export function EnvEditor({
45
+ title,
46
+ rows,
47
+ onChange,
48
+ description,
49
+ allowAdd = true,
50
+ emptyLabel = "環境変数はまだありません",
51
+ }: EnvEditorProps) {
52
+ const handleFieldChange = (id: string, field: "key" | "value", value: string) => {
53
+ onChange(
54
+ rows.map((row) =>
55
+ row.id === id
56
+ ? {
57
+ ...row,
58
+ [field]: field === "key" ? value.toUpperCase().replace(/[^A-Z0-9_]/g, "_") : value,
59
+ }
60
+ : row,
61
+ ),
62
+ );
63
+ };
64
+
65
+ const handleRemove = (id: string) => {
66
+ onChange(rows.filter((row) => row.id !== id));
67
+ };
68
+
69
+ const handleAdd = () => {
70
+ onChange([...rows, createEnvRow()]);
71
+ };
72
+
73
+ return (
74
+ <div className="env-editor">
75
+ <header className="env-editor__header">
76
+ <div>
77
+ <h3>{title}</h3>
78
+ {description && <p className="env-editor__description">{description}</p>}
79
+ </div>
80
+ {allowAdd && (
81
+ <button type="button" className="button button--secondary" onClick={handleAdd}>
82
+ 変数を追加
83
+ </button>
84
+ )}
85
+ </header>
86
+
87
+ {rows.length === 0 ? (
88
+ <p className="env-editor__empty">{emptyLabel}</p>
89
+ ) : (
90
+ <table className="env-editor__table">
91
+ <thead>
92
+ <tr>
93
+ <th>キー</th>
94
+ <th>値</th>
95
+ <th style={{ width: "140px" }}>操作</th>
96
+ </tr>
97
+ </thead>
98
+ <tbody>
99
+ {rows.map((row) => {
100
+ const keyInvalid = isInvalidKey(row);
101
+ return (
102
+ <tr key={row.id} className={keyInvalid ? "env-editor__row--invalid" : undefined}>
103
+ <td>
104
+ <input
105
+ type="text"
106
+ value={row.key}
107
+ onChange={(event) => handleFieldChange(row.id, "key", event.target.value)}
108
+ placeholder="EXAMPLE_KEY"
109
+ />
110
+ {row.importedFromOs && (
111
+ <span className="pill pill--info" style={{ marginLeft: "0.5rem" }}>
112
+ OSから取り込み
113
+ </span>
114
+ )}
115
+ {row.lastUpdated && (
116
+ <span className="env-editor__meta">更新: {new Date(row.lastUpdated).toLocaleString()}</span>
117
+ )}
118
+ {keyInvalid && <p className="env-editor__error">A-Z,0-9,_ のみ使用できます</p>}
119
+ </td>
120
+ <td>
121
+ <input
122
+ type="text"
123
+ value={row.value}
124
+ onChange={(event) => handleFieldChange(row.id, "value", event.target.value)}
125
+ placeholder="値"
126
+ />
127
+ </td>
128
+ <td>
129
+ <button
130
+ type="button"
131
+ className="button button--ghost"
132
+ onClick={() => handleRemove(row.id)}
133
+ >
134
+ 削除
135
+ </button>
136
+ </td>
137
+ </tr>
138
+ );
139
+ })}
140
+ </tbody>
141
+ </table>
142
+ )}
143
+ </div>
144
+ );
145
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Terminal Component
3
+ *
4
+ * xterm.jsを使用したブラウザ端末エミュレータ。
5
+ * WebSocket経由でPTYプロセスと通信します。
6
+ */
7
+
8
+ import React, { useEffect, useRef } from "react";
9
+ import { Terminal as XTerm } from "xterm";
10
+ import { FitAddon } from "xterm-addon-fit";
11
+ import { PTYWebSocket } from "../lib/websocket";
12
+ import "xterm/css/xterm.css";
13
+
14
+ export interface TerminalProps {
15
+ sessionId: string;
16
+ onExit?: (code: number) => void;
17
+ onError?: (message: string) => void;
18
+ }
19
+
20
+ export function Terminal({ sessionId, onExit, onError }: TerminalProps) {
21
+ const terminalRef = useRef<HTMLDivElement>(null);
22
+ const xtermRef = useRef<XTerm | null>(null);
23
+ const fitAddonRef = useRef<FitAddon | null>(null);
24
+ const wsRef = useRef<PTYWebSocket | null>(null);
25
+
26
+ useEffect(() => {
27
+ if (!terminalRef.current) {
28
+ return;
29
+ }
30
+
31
+ // xterm.jsのインスタンスを作成
32
+ const xterm = new XTerm({
33
+ cursorBlink: true,
34
+ fontSize: 14,
35
+ fontFamily: '"Cascadia Code", "SF Mono", Monaco, Consolas, monospace',
36
+ theme: {
37
+ background: "#1e1e1e",
38
+ foreground: "#d4d4d4",
39
+ cursor: "#aeafad",
40
+ black: "#000000",
41
+ red: "#cd3131",
42
+ green: "#0dbc79",
43
+ yellow: "#e5e510",
44
+ blue: "#2472c8",
45
+ magenta: "#bc3fbc",
46
+ cyan: "#11a8cd",
47
+ white: "#e5e5e5",
48
+ brightBlack: "#666666",
49
+ brightRed: "#f14c4c",
50
+ brightGreen: "#23d18b",
51
+ brightYellow: "#f5f543",
52
+ brightBlue: "#3b8eea",
53
+ brightMagenta: "#d670d6",
54
+ brightCyan: "#29b8db",
55
+ brightWhite: "#ffffff",
56
+ },
57
+ });
58
+
59
+ // FitAddonを追加
60
+ const fitAddon = new FitAddon();
61
+ xterm.loadAddon(fitAddon);
62
+
63
+ // ターミナルをDOMにマウント
64
+ xterm.open(terminalRef.current);
65
+ fitAddon.fit();
66
+
67
+ xtermRef.current = xterm;
68
+ fitAddonRef.current = fitAddon;
69
+
70
+ // WebSocket接続を確立
71
+ const ws = new PTYWebSocket(sessionId, {
72
+ onOutput: (data) => {
73
+ xterm.write(data);
74
+ },
75
+ onExit: (code) => {
76
+ xterm.write(`\r\n\r\n[Process exited with code ${code}]\r\n`);
77
+ onExit?.(code);
78
+ },
79
+ onError: (message) => {
80
+ xterm.write(`\r\n\r\n[Error: ${message}]\r\n`);
81
+ onError?.(message);
82
+ },
83
+ onOpen: () => {
84
+ xterm.write("Connected to session...\r\n");
85
+ },
86
+ onClose: () => {
87
+ xterm.write("\r\n[Connection closed]\r\n");
88
+ },
89
+ });
90
+
91
+ ws.connect();
92
+ wsRef.current = ws;
93
+
94
+ // ユーザー入力をWebSocketに送信
95
+ xterm.onData((data) => {
96
+ ws.sendInput(data);
97
+ });
98
+
99
+ // ウィンドウリサイズ時にターミナルサイズを調整
100
+ const handleResize = () => {
101
+ fitAddon.fit();
102
+ if (ws.isConnected()) {
103
+ ws.sendResize(xterm.cols, xterm.rows);
104
+ }
105
+ };
106
+
107
+ window.addEventListener("resize", handleResize);
108
+
109
+ let resizeObserver: ResizeObserver | null = null;
110
+ if (typeof ResizeObserver !== "undefined") {
111
+ resizeObserver = new ResizeObserver(() => {
112
+ handleResize();
113
+ });
114
+ resizeObserver.observe(terminalRef.current);
115
+ }
116
+
117
+ // クリーンアップ
118
+ return () => {
119
+ window.removeEventListener("resize", handleResize);
120
+ resizeObserver?.disconnect();
121
+ ws.disconnect();
122
+ xterm.dispose();
123
+ };
124
+ }, [sessionId, onExit, onError]);
125
+
126
+ return (
127
+ <div
128
+ ref={terminalRef}
129
+ style={{
130
+ width: "100%",
131
+ height: "100%",
132
+ padding: "8px",
133
+ backgroundColor: "#1e1e1e",
134
+ }}
135
+ />
136
+ );
137
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * ブランチ関連のReact Hook
3
+ */
4
+
5
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6
+ import { branchApi } from "../lib/api";
7
+ import type { Branch } from "../../../../types/api.js";
8
+
9
+ /**
10
+ * ブランチ一覧を取得
11
+ */
12
+ export function useBranches() {
13
+ return useQuery<Branch[]>({
14
+ queryKey: ["branches"],
15
+ queryFn: branchApi.list,
16
+ });
17
+ }
18
+
19
+ /**
20
+ * 特定のブランチ情報を取得
21
+ */
22
+ export function useBranch(branchName: string) {
23
+ return useQuery<Branch>({
24
+ queryKey: ["branches", branchName],
25
+ queryFn: () => branchApi.get(branchName),
26
+ enabled: !!branchName,
27
+ });
28
+ }
29
+
30
+ export function useSyncBranch(branchName: string) {
31
+ const queryClient = useQueryClient();
32
+
33
+ return useMutation({
34
+ mutationFn: (payload: { worktreePath: string }) =>
35
+ branchApi.sync(branchName, payload),
36
+ onSuccess: (result) => {
37
+ queryClient.setQueryData(["branches", branchName], result.branch);
38
+ queryClient.invalidateQueries({ queryKey: ["branches"] });
39
+ },
40
+ });
41
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Config Hooks
3
+ */
4
+
5
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6
+ import { configApi } from "../lib/api";
7
+ import type { ConfigPayload } from "../../../../types/api.js";
8
+
9
+ /**
10
+ * カスタムAIツール設定を取得
11
+ */
12
+ export function useConfig() {
13
+ return useQuery<ConfigPayload>({
14
+ queryKey: ["config"],
15
+ queryFn: configApi.get,
16
+ });
17
+ }
18
+
19
+ /**
20
+ * カスタムAIツール設定を更新
21
+ */
22
+ export function useUpdateConfig() {
23
+ const queryClient = useQueryClient();
24
+
25
+ return useMutation({
26
+ mutationFn: configApi.update,
27
+ onSuccess: (data: ConfigPayload) => {
28
+ queryClient.setQueryData(["config"], data);
29
+ },
30
+ });
31
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * セッション関連のReact Hook
3
+ */
4
+
5
+ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
6
+ import { sessionApi } from "../lib/api";
7
+ import type {
8
+ AIToolSession,
9
+ StartSessionRequest,
10
+ } from "../../../../types/api.js";
11
+
12
+ /**
13
+ * セッション一覧を取得
14
+ */
15
+ export function useSessions() {
16
+ return useQuery<AIToolSession[]>({
17
+ queryKey: ["sessions"],
18
+ queryFn: sessionApi.list,
19
+ });
20
+ }
21
+
22
+ /**
23
+ * 特定のセッション情報を取得
24
+ */
25
+ export function useSession(sessionId: string) {
26
+ return useQuery<AIToolSession>({
27
+ queryKey: ["sessions", sessionId],
28
+ queryFn: () => sessionApi.get(sessionId),
29
+ enabled: !!sessionId,
30
+ });
31
+ }
32
+
33
+ /**
34
+ * セッションを開始
35
+ */
36
+ export function useStartSession() {
37
+ const queryClient = useQueryClient();
38
+
39
+ return useMutation({
40
+ mutationFn: (request: StartSessionRequest) => sessionApi.start(request),
41
+ onSuccess: () => {
42
+ queryClient.invalidateQueries({ queryKey: ["sessions"] });
43
+ },
44
+ });
45
+ }
46
+
47
+ /**
48
+ * セッションを終了
49
+ */
50
+ export function useDeleteSession() {
51
+ const queryClient = useQueryClient();
52
+
53
+ return useMutation({
54
+ mutationFn: (sessionId: string) => sessionApi.delete(sessionId),
55
+ onSuccess: () => {
56
+ queryClient.invalidateQueries({ queryKey: ["sessions"] });
57
+ },
58
+ });
59
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Worktree関連のReact Hook
3
+ */
4
+
5
+ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
6
+ import { worktreeApi } from "../lib/api";
7
+ import type { Worktree, CreateWorktreeRequest } from "../../../../types/api.js";
8
+
9
+ /**
10
+ * Worktree一覧を取得
11
+ */
12
+ export function useWorktrees() {
13
+ return useQuery<Worktree[]>({
14
+ queryKey: ["worktrees"],
15
+ queryFn: worktreeApi.list,
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Worktreeを作成
21
+ */
22
+ export function useCreateWorktree() {
23
+ const queryClient = useQueryClient();
24
+
25
+ return useMutation({
26
+ mutationFn: (request: CreateWorktreeRequest) => worktreeApi.create(request),
27
+ onSuccess: () => {
28
+ queryClient.invalidateQueries({ queryKey: ["worktrees"] });
29
+ queryClient.invalidateQueries({ queryKey: ["branches"] });
30
+ },
31
+ });
32
+ }
33
+
34
+ /**
35
+ * Worktreeを削除
36
+ */
37
+ export function useDeleteWorktree() {
38
+ const queryClient = useQueryClient();
39
+
40
+ return useMutation({
41
+ mutationFn: (path: string) => worktreeApi.delete(path),
42
+ onSuccess: () => {
43
+ queryClient.invalidateQueries({ queryKey: ["worktrees"] });
44
+ queryClient.invalidateQueries({ queryKey: ["branches"] });
45
+ },
46
+ });
47
+ }