ccmanager 0.1.15 → 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 (38) hide show
  1. package/dist/cli.js +3 -0
  2. package/dist/components/App.js +35 -1
  3. package/dist/components/ConfigureCommand.js +367 -121
  4. package/dist/components/Menu.js +18 -18
  5. package/dist/components/PresetSelector.d.ts +7 -0
  6. package/dist/components/PresetSelector.js +52 -0
  7. package/dist/hooks/useGitStatus.d.ts +2 -0
  8. package/dist/hooks/useGitStatus.js +52 -0
  9. package/dist/hooks/useGitStatus.test.d.ts +1 -0
  10. package/dist/hooks/useGitStatus.test.js +186 -0
  11. package/dist/services/configurationManager.d.ts +11 -1
  12. package/dist/services/configurationManager.js +111 -3
  13. package/dist/services/configurationManager.selectPresetOnStart.test.d.ts +1 -0
  14. package/dist/services/configurationManager.selectPresetOnStart.test.js +103 -0
  15. package/dist/services/configurationManager.test.d.ts +1 -0
  16. package/dist/services/configurationManager.test.js +313 -0
  17. package/dist/services/sessionManager.d.ts +1 -0
  18. package/dist/services/sessionManager.js +69 -0
  19. package/dist/services/sessionManager.test.js +103 -0
  20. package/dist/services/worktreeConfigManager.d.ts +10 -0
  21. package/dist/services/worktreeConfigManager.js +27 -0
  22. package/dist/services/worktreeService.js +8 -0
  23. package/dist/services/worktreeService.test.js +8 -0
  24. package/dist/types/index.d.ts +16 -0
  25. package/dist/utils/concurrencyLimit.d.ts +4 -0
  26. package/dist/utils/concurrencyLimit.js +30 -0
  27. package/dist/utils/concurrencyLimit.test.d.ts +1 -0
  28. package/dist/utils/concurrencyLimit.test.js +63 -0
  29. package/dist/utils/gitStatus.d.ts +19 -0
  30. package/dist/utils/gitStatus.js +146 -0
  31. package/dist/utils/gitStatus.test.d.ts +1 -0
  32. package/dist/utils/gitStatus.test.js +141 -0
  33. package/dist/utils/worktreeConfig.d.ts +3 -0
  34. package/dist/utils/worktreeConfig.js +43 -0
  35. package/dist/utils/worktreeUtils.d.ts +37 -0
  36. package/dist/utils/worktreeUtils.js +114 -0
  37. package/dist/utils/worktreeUtils.test.js +105 -1
  38. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { generateWorktreeDirectory, extractBranchParts, } from './worktreeUtils.js';
2
+ import { generateWorktreeDirectory, extractBranchParts, truncateString, prepareWorktreeItems, calculateColumnPositions, assembleWorktreeLabel, } from './worktreeUtils.js';
3
3
  describe('generateWorktreeDirectory', () => {
4
4
  describe('with default pattern', () => {
5
5
  it('should generate directory with sanitized branch name', () => {
@@ -72,3 +72,107 @@ describe('extractBranchParts', () => {
72
72
  });
73
73
  });
74
74
  });
75
+ describe('truncateString', () => {
76
+ it('should return original string if shorter than max length', () => {
77
+ expect(truncateString('hello', 10)).toBe('hello');
78
+ expect(truncateString('test', 4)).toBe('test');
79
+ });
80
+ it('should truncate and add ellipsis if longer than max length', () => {
81
+ expect(truncateString('hello world', 8)).toBe('hello...');
82
+ expect(truncateString('this is a long string', 10)).toBe('this is...');
83
+ });
84
+ it('should handle edge cases', () => {
85
+ expect(truncateString('', 5)).toBe('');
86
+ expect(truncateString('abc', 3)).toBe('abc');
87
+ expect(truncateString('abcd', 3)).toBe('...');
88
+ });
89
+ });
90
+ describe('prepareWorktreeItems', () => {
91
+ const mockWorktree = {
92
+ path: '/path/to/worktree',
93
+ branch: 'feature/test-branch',
94
+ isMainWorktree: false,
95
+ hasSession: false,
96
+ };
97
+ // Simplified mock
98
+ const mockSession = {
99
+ id: 'test-session',
100
+ worktreePath: '/path/to/worktree',
101
+ state: 'idle',
102
+ process: {},
103
+ output: [],
104
+ outputHistory: [],
105
+ lastActivity: new Date(),
106
+ isActive: true,
107
+ terminal: {},
108
+ };
109
+ it('should prepare basic worktree without git status', () => {
110
+ const items = prepareWorktreeItems([mockWorktree], []);
111
+ expect(items).toHaveLength(1);
112
+ expect(items[0]?.baseLabel).toBe('feature/test-branch');
113
+ });
114
+ it('should include session status in label', () => {
115
+ const items = prepareWorktreeItems([mockWorktree], [mockSession]);
116
+ expect(items[0]?.baseLabel).toContain('[○ Idle]');
117
+ });
118
+ it('should mark main worktree', () => {
119
+ const mainWorktree = { ...mockWorktree, isMainWorktree: true };
120
+ const items = prepareWorktreeItems([mainWorktree], []);
121
+ expect(items[0]?.baseLabel).toContain('(main)');
122
+ });
123
+ it('should truncate long branch names', () => {
124
+ const longBranch = {
125
+ ...mockWorktree,
126
+ branch: 'feature/this-is-a-very-long-branch-name-that-should-be-truncated',
127
+ };
128
+ const items = prepareWorktreeItems([longBranch], []);
129
+ expect(items[0]?.baseLabel.length).toBeLessThanOrEqual(50); // 40 + status + default
130
+ });
131
+ });
132
+ describe('column alignment', () => {
133
+ const mockItems = [
134
+ {
135
+ worktree: {},
136
+ baseLabel: 'feature/test-branch',
137
+ fileChanges: '\x1b[32m+10\x1b[0m \x1b[31m-5\x1b[0m',
138
+ aheadBehind: '\x1b[33m↑2 ↓3\x1b[0m',
139
+ parentBranch: '',
140
+ lengths: {
141
+ base: 19, // 'feature/test-branch'.length
142
+ fileChanges: 6, // '+10 -5'.length
143
+ aheadBehind: 5, // '↑2 ↓3'.length
144
+ parentBranch: 0,
145
+ },
146
+ },
147
+ {
148
+ worktree: {},
149
+ baseLabel: 'main',
150
+ fileChanges: '\x1b[32m+2\x1b[0m \x1b[31m-1\x1b[0m',
151
+ aheadBehind: '\x1b[33m↑1\x1b[0m',
152
+ parentBranch: '',
153
+ lengths: {
154
+ base: 4, // 'main'.length
155
+ fileChanges: 5, // '+2 -1'.length
156
+ aheadBehind: 2, // '↑1'.length
157
+ parentBranch: 0,
158
+ },
159
+ },
160
+ ];
161
+ it('should calculate column positions from items', () => {
162
+ const positions = calculateColumnPositions(mockItems);
163
+ expect(positions.fileChanges).toBe(21); // 19 + 2 padding
164
+ expect(positions.aheadBehind).toBeGreaterThan(positions.fileChanges);
165
+ expect(positions.parentBranch).toBeGreaterThan(positions.aheadBehind);
166
+ });
167
+ it('should assemble label with proper alignment', () => {
168
+ const item = mockItems[0];
169
+ const columns = calculateColumnPositions(mockItems);
170
+ const result = assembleWorktreeLabel(item, columns);
171
+ expect(result).toContain('feature/test-branch');
172
+ expect(result).toContain('\x1b[32m+10\x1b[0m');
173
+ expect(result).toContain('\x1b[33m↑2 ↓3\x1b[0m');
174
+ // Check alignment by stripping ANSI codes
175
+ const plain = result.replace(/\x1b\[[0-9;]*m/g, '');
176
+ expect(plain.indexOf('+10 -5')).toBe(21); // Should start at column 21
177
+ });
178
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccmanager",
3
- "version": "0.1.15",
3
+ "version": "0.2.1",
4
4
  "description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
5
5
  "license": "MIT",
6
6
  "author": "Kodai Kabasawa",