ccmanager 4.2.1 → 4.2.2
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/README.md +5 -5
- package/dist/components/Menu.js +4 -1
- package/dist/components/Menu.test.js +72 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ npm install -g ccmanager
|
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
56
|
npm install
|
|
57
|
-
|
|
57
|
+
bun run build
|
|
58
58
|
npm start
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -353,17 +353,17 @@ For complete setup instructions and troubleshooting, see [docs/git-worktree-conf
|
|
|
353
353
|
npm install
|
|
354
354
|
|
|
355
355
|
# Run in development mode
|
|
356
|
-
|
|
356
|
+
bun run dev
|
|
357
357
|
|
|
358
358
|
# Build
|
|
359
|
-
|
|
359
|
+
bun run build
|
|
360
360
|
|
|
361
361
|
# Run tests
|
|
362
362
|
npm test
|
|
363
363
|
|
|
364
364
|
# Run linter
|
|
365
|
-
|
|
365
|
+
bun run lint
|
|
366
366
|
|
|
367
367
|
# Run type checker
|
|
368
|
-
|
|
368
|
+
bun run typecheck
|
|
369
369
|
```
|
package/dist/components/Menu.js
CHANGED
|
@@ -39,7 +39,10 @@ const Menu = ({ sessionManager, worktreeService, initialSnapshot, onSnapshotChan
|
|
|
39
39
|
loadError: initialSnapshot?.loadError ?? null,
|
|
40
40
|
});
|
|
41
41
|
const worktrees = useGitStatus(baseWorktrees, defaultBranch);
|
|
42
|
-
|
|
42
|
+
// Seed from the in-memory session list so the cached snapshot renders with its
|
|
43
|
+
// sessions attached. Waiting for the async git load would leave every row
|
|
44
|
+
// session-less for that window, disabling the Space session-actions shortcut.
|
|
45
|
+
const [sessions, setSessions] = useState(() => sessionManager.getAllSessions());
|
|
43
46
|
const [items, setItems] = useState([]);
|
|
44
47
|
const [recentProjects, setRecentProjects] = useState([]);
|
|
45
48
|
const [highlightedWorktreePath, setHighlightedWorktreePath] = useState(null);
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { render } from 'ink-testing-library';
|
|
3
|
+
import { useInput } from 'ink';
|
|
3
4
|
import Menu from './Menu.js';
|
|
4
5
|
import { SessionManager } from '../services/sessionManager.js';
|
|
5
6
|
import { WorktreeService } from '../services/worktreeService.js';
|
|
6
7
|
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
+
const makeKey = (overrides = {}) => ({
|
|
9
|
+
upArrow: false,
|
|
10
|
+
downArrow: false,
|
|
11
|
+
leftArrow: false,
|
|
12
|
+
rightArrow: false,
|
|
13
|
+
pageDown: false,
|
|
14
|
+
pageUp: false,
|
|
15
|
+
home: false,
|
|
16
|
+
end: false,
|
|
17
|
+
return: false,
|
|
18
|
+
escape: false,
|
|
19
|
+
ctrl: false,
|
|
20
|
+
shift: false,
|
|
21
|
+
tab: false,
|
|
22
|
+
backspace: false,
|
|
23
|
+
delete: false,
|
|
24
|
+
meta: false,
|
|
25
|
+
...overrides,
|
|
26
|
+
});
|
|
7
27
|
// Mock bunTerminal to avoid native module issues in tests
|
|
8
28
|
vi.mock('../services/bunTerminal.js', () => ({
|
|
9
29
|
spawn: vi.fn(function () {
|
|
@@ -216,8 +236,9 @@ describe('Menu component Effect-based error handling', () => {
|
|
|
216
236
|
expect(lastFrame()).toContain('cached-branch');
|
|
217
237
|
expect(getDefaultBranchSpy).toHaveBeenCalled();
|
|
218
238
|
resolveWorktrees([refreshedWorktree]);
|
|
219
|
-
await
|
|
220
|
-
|
|
239
|
+
await vi.waitFor(() => {
|
|
240
|
+
expect(lastFrame()).toContain('refreshed-branch');
|
|
241
|
+
});
|
|
221
242
|
expect(onSnapshotChange).toHaveBeenCalledWith({
|
|
222
243
|
worktrees: [refreshedWorktree],
|
|
223
244
|
defaultBranch: 'main',
|
|
@@ -253,6 +274,55 @@ describe('Menu component Effect-based error handling', () => {
|
|
|
253
274
|
loadError: expect.stringContaining('temporary failure'),
|
|
254
275
|
});
|
|
255
276
|
});
|
|
277
|
+
it('should handle the Space session-actions shortcut on a cached snapshot before the refresh completes', async () => {
|
|
278
|
+
const { Effect } = await import('effect');
|
|
279
|
+
const cachedWorktree = {
|
|
280
|
+
path: '/test/cached',
|
|
281
|
+
branch: 'cached-branch',
|
|
282
|
+
isMainWorktree: true,
|
|
283
|
+
hasSession: true,
|
|
284
|
+
};
|
|
285
|
+
const cachedSession = {
|
|
286
|
+
id: 'session-cached',
|
|
287
|
+
worktreePath: '/test/cached',
|
|
288
|
+
lastAccessedAt: 1,
|
|
289
|
+
stateMutex: {
|
|
290
|
+
getSnapshot: () => ({
|
|
291
|
+
state: 'idle',
|
|
292
|
+
backgroundTaskCount: 0,
|
|
293
|
+
teamMemberCount: 0,
|
|
294
|
+
}),
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
vi.spyOn(sessionManager, 'getAllSessions').mockReturnValue([cachedSession]);
|
|
298
|
+
// Never resolve the refresh, so only the cached snapshot is on screen.
|
|
299
|
+
vi.spyOn(worktreeService, 'getWorktreesEffect').mockReturnValue(Effect.promise(() => new Promise(() => { })));
|
|
300
|
+
vi.spyOn(worktreeService, 'getDefaultBranchEffect').mockReturnValue(Effect.succeed('main'));
|
|
301
|
+
const onMenuAction = vi.fn();
|
|
302
|
+
vi.mocked(useInput).mockClear();
|
|
303
|
+
render(_jsx(Menu, { sessionManager: sessionManager, worktreeService: worktreeService, initialSnapshot: {
|
|
304
|
+
worktrees: [cachedWorktree],
|
|
305
|
+
defaultBranch: 'main',
|
|
306
|
+
}, onMenuAction: onMenuAction, version: "test" }));
|
|
307
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
308
|
+
// Menu's hotkey handler bails out when raw mode is unavailable.
|
|
309
|
+
const origSetRawMode = process.stdin.setRawMode;
|
|
310
|
+
process.stdin.setRawMode = vi.fn();
|
|
311
|
+
try {
|
|
312
|
+
const calls = vi.mocked(useInput).mock.calls;
|
|
313
|
+
const handler = calls[calls.length - 1]?.[0];
|
|
314
|
+
expect(handler).toBeDefined();
|
|
315
|
+
handler(' ', makeKey());
|
|
316
|
+
}
|
|
317
|
+
finally {
|
|
318
|
+
process.stdin.setRawMode = origSetRawMode;
|
|
319
|
+
}
|
|
320
|
+
expect(onMenuAction).toHaveBeenCalledWith({
|
|
321
|
+
type: 'sessionActions',
|
|
322
|
+
session: cachedSession,
|
|
323
|
+
worktreePath: '/test/cached',
|
|
324
|
+
});
|
|
325
|
+
});
|
|
256
326
|
});
|
|
257
327
|
describe('Menu component rendering', () => {
|
|
258
328
|
let sessionManager;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccmanager",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.2",
|
|
4
4
|
"description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kodai Kabasawa",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"bin"
|
|
42
42
|
],
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@kodaikabasawa/ccmanager-darwin-arm64": "4.2.
|
|
45
|
-
"@kodaikabasawa/ccmanager-darwin-x64": "4.2.
|
|
46
|
-
"@kodaikabasawa/ccmanager-linux-arm64": "4.2.
|
|
47
|
-
"@kodaikabasawa/ccmanager-linux-x64": "4.2.
|
|
48
|
-
"@kodaikabasawa/ccmanager-win32-x64": "4.2.
|
|
44
|
+
"@kodaikabasawa/ccmanager-darwin-arm64": "4.2.2",
|
|
45
|
+
"@kodaikabasawa/ccmanager-darwin-x64": "4.2.2",
|
|
46
|
+
"@kodaikabasawa/ccmanager-linux-arm64": "4.2.2",
|
|
47
|
+
"@kodaikabasawa/ccmanager-linux-x64": "4.2.2",
|
|
48
|
+
"@kodaikabasawa/ccmanager-win32-x64": "4.2.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@eslint/js": "^9.28.0",
|