@kodus/cli 0.1.6 → 0.1.8

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 (85) hide show
  1. package/README.md +0 -45
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +6 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/__tests__/hook.test.d.ts +2 -0
  6. package/dist/commands/__tests__/hook.test.d.ts.map +1 -0
  7. package/dist/commands/__tests__/hook.test.js +105 -0
  8. package/dist/commands/__tests__/hook.test.js.map +1 -0
  9. package/dist/commands/auth/login.d.ts.map +1 -1
  10. package/dist/commands/auth/login.js +0 -13
  11. package/dist/commands/auth/login.js.map +1 -1
  12. package/dist/commands/auth/status.d.ts.map +1 -1
  13. package/dist/commands/auth/status.js +1 -13
  14. package/dist/commands/auth/status.js.map +1 -1
  15. package/dist/commands/hook/index.d.ts +3 -0
  16. package/dist/commands/hook/index.d.ts.map +1 -0
  17. package/dist/commands/hook/index.js +23 -0
  18. package/dist/commands/hook/index.js.map +1 -0
  19. package/dist/commands/hook/install.d.ts +9 -0
  20. package/dist/commands/hook/install.d.ts.map +1 -0
  21. package/dist/commands/hook/install.js +84 -0
  22. package/dist/commands/hook/install.js.map +1 -0
  23. package/dist/commands/hook/status.d.ts +2 -0
  24. package/dist/commands/hook/status.d.ts.map +1 -0
  25. package/dist/commands/hook/status.js +34 -0
  26. package/dist/commands/hook/status.js.map +1 -0
  27. package/dist/commands/hook/uninstall.d.ts +2 -0
  28. package/dist/commands/hook/uninstall.d.ts.map +1 -0
  29. package/dist/commands/hook/uninstall.js +29 -0
  30. package/dist/commands/hook/uninstall.js.map +1 -0
  31. package/dist/commands/review.d.ts.map +1 -1
  32. package/dist/commands/review.js +82 -13
  33. package/dist/commands/review.js.map +1 -1
  34. package/dist/constants.d.ts +1 -1
  35. package/dist/constants.d.ts.map +1 -1
  36. package/dist/constants.js +4 -1
  37. package/dist/constants.js.map +1 -1
  38. package/dist/services/__tests__/auth.service.test.d.ts +2 -0
  39. package/dist/services/__tests__/auth.service.test.d.ts.map +1 -0
  40. package/dist/services/__tests__/auth.service.test.js +167 -0
  41. package/dist/services/__tests__/auth.service.test.js.map +1 -0
  42. package/dist/services/__tests__/git.service.test.d.ts +2 -0
  43. package/dist/services/__tests__/git.service.test.d.ts.map +1 -0
  44. package/dist/services/__tests__/git.service.test.js +61 -0
  45. package/dist/services/__tests__/git.service.test.js.map +1 -0
  46. package/dist/services/__tests__/review.service.test.d.ts +2 -0
  47. package/dist/services/__tests__/review.service.test.d.ts.map +1 -0
  48. package/dist/services/__tests__/review.service.test.js +132 -0
  49. package/dist/services/__tests__/review.service.test.js.map +1 -0
  50. package/dist/services/api/api.interface.d.ts +0 -1
  51. package/dist/services/api/api.interface.d.ts.map +1 -1
  52. package/dist/services/api/api.real.d.ts.map +1 -1
  53. package/dist/services/api/api.real.js +92 -21
  54. package/dist/services/api/api.real.js.map +1 -1
  55. package/dist/services/auth.service.d.ts +1 -2
  56. package/dist/services/auth.service.d.ts.map +1 -1
  57. package/dist/services/auth.service.js +1 -4
  58. package/dist/services/auth.service.js.map +1 -1
  59. package/dist/services/context.service.d.ts +1 -1
  60. package/dist/services/context.service.d.ts.map +1 -1
  61. package/dist/services/context.service.js +20 -1
  62. package/dist/services/context.service.js.map +1 -1
  63. package/dist/services/git.service.d.ts +3 -0
  64. package/dist/services/git.service.d.ts.map +1 -1
  65. package/dist/services/git.service.js +96 -13
  66. package/dist/services/git.service.js.map +1 -1
  67. package/dist/services/review.service.d.ts +7 -5
  68. package/dist/services/review.service.d.ts.map +1 -1
  69. package/dist/services/review.service.js +63 -3
  70. package/dist/services/review.service.js.map +1 -1
  71. package/dist/utils/__tests__/update-check.test.d.ts +2 -0
  72. package/dist/utils/__tests__/update-check.test.d.ts.map +1 -0
  73. package/dist/utils/__tests__/update-check.test.js +26 -0
  74. package/dist/utils/__tests__/update-check.test.js.map +1 -0
  75. package/dist/utils/rate-limit.js +1 -1
  76. package/dist/utils/rate-limit.js.map +1 -1
  77. package/dist/utils/update-check.d.ts +3 -0
  78. package/dist/utils/update-check.d.ts.map +1 -0
  79. package/dist/utils/update-check.js +106 -0
  80. package/dist/utils/update-check.js.map +1 -0
  81. package/package.json +6 -2
  82. package/dist/commands/auth/signup.d.ts +0 -2
  83. package/dist/commands/auth/signup.d.ts.map +0 -1
  84. package/dist/commands/auth/signup.js +0 -59
  85. package/dist/commands/auth/signup.js.map +0 -1
@@ -23,6 +23,7 @@ export const reviewCommand = new Command('review')
23
23
  .option('-i, --interactive', 'Interactive mode: navigate and apply fixes')
24
24
  .option('--fix', 'Automatically apply all fixable issues')
25
25
  .option('--prompt-only', 'Output optimized for AI agents (minimal, structured)')
26
+ .option('--fail-on <severity>', 'Exit with code 1 if issues meet or exceed severity (info, warning, error, critical)')
26
27
  .option('--context <file>', 'Custom context file to include in review')
27
28
  .action(async (files, options, cmd) => {
28
29
  const globalOpts = cmd.optsWithGlobals();
@@ -41,19 +42,33 @@ export const reviewCommand = new Command('review')
41
42
  if (!globalOpts.quiet) {
42
43
  spinner.text = chalk.cyan('Getting file changes...');
43
44
  }
44
- let diff = await getDiff(files, options);
45
+ let diff = await getDiff(files, options, globalOpts.verbose);
45
46
  if (!diff) {
46
47
  spinner.fail(chalk.yellow('No changes to review'));
48
+ if (globalOpts.verbose) {
49
+ console.log(chalk.dim('[verbose] Checked scopes:'));
50
+ console.log(chalk.dim(` - Specific files: ${files && files.length > 0 ? files.join(', ') : 'none'}`));
51
+ console.log(chalk.dim(` - Branch comparison: ${options.branch || 'none'}`));
52
+ console.log(chalk.dim(` - Commit: ${options.commit || 'none'}`));
53
+ console.log(chalk.dim(` - Staged only: ${options.staged ? 'yes' : 'no'}`));
54
+ console.log(chalk.dim(` - Default: ${!files?.length && !options.branch && !options.commit && !options.staged ? 'working tree (staged + unstaged)' : 'no'}`));
55
+ }
47
56
  return;
48
57
  }
49
58
  // Enrich with project context
50
59
  if (!globalOpts.quiet) {
51
60
  spinner.text = chalk.cyan('Reading project context...');
52
61
  }
53
- diff = await contextService.enrichDiffWithContext(diff, options.context);
62
+ if (globalOpts.verbose) {
63
+ console.log(chalk.dim('[verbose] Reading project context files...'));
64
+ }
65
+ diff = await contextService.enrichDiffWithContext(diff, options.context, globalOpts.verbose);
54
66
  if (!globalOpts.quiet) {
55
67
  spinner.text = chalk.cyan('Analyzing code...');
56
68
  }
69
+ if (globalOpts.verbose) {
70
+ reviewService.setVerbose(true);
71
+ }
57
72
  result = await reviewService.analyze(diff, options.rulesOnly, options.fast, {
58
73
  files: files && files.length > 0 ? files : undefined,
59
74
  staged: options.staged,
@@ -76,19 +91,33 @@ export const reviewCommand = new Command('review')
76
91
  if (!globalOpts.quiet) {
77
92
  spinner.text = chalk.cyan('Getting file changes...');
78
93
  }
79
- let diff = await getDiff(files, options);
94
+ let diff = await getDiff(files, options, globalOpts.verbose);
80
95
  if (!diff) {
81
96
  spinner.fail(chalk.yellow('No changes to review'));
97
+ if (globalOpts.verbose) {
98
+ console.log(chalk.dim('[verbose] Checked scopes:'));
99
+ console.log(chalk.dim(` - Specific files: ${files && files.length > 0 ? files.join(', ') : 'none'}`));
100
+ console.log(chalk.dim(` - Branch comparison: ${options.branch || 'none'}`));
101
+ console.log(chalk.dim(` - Commit: ${options.commit || 'none'}`));
102
+ console.log(chalk.dim(` - Staged only: ${options.staged ? 'yes' : 'no'}`));
103
+ console.log(chalk.dim(` - Default: ${!files?.length && !options.branch && !options.commit && !options.staged ? 'working tree (staged + unstaged)' : 'no'}`));
104
+ }
82
105
  return;
83
106
  }
84
107
  // Enrich with project context
85
108
  if (!globalOpts.quiet) {
86
109
  spinner.text = chalk.cyan('Reading project context...');
87
110
  }
88
- diff = await contextService.enrichDiffWithContext(diff, options.context);
111
+ if (globalOpts.verbose) {
112
+ console.log(chalk.dim('[verbose] Reading project context files...'));
113
+ }
114
+ diff = await contextService.enrichDiffWithContext(diff, options.context, globalOpts.verbose);
89
115
  if (!globalOpts.quiet) {
90
116
  spinner.text = chalk.cyan('Analyzing code (trial mode)...');
91
117
  }
118
+ if (globalOpts.verbose) {
119
+ reviewService.setVerbose(true);
120
+ }
92
121
  result = await reviewService.trialAnalyze(diff);
93
122
  spinner.succeed(chalk.green(`Review complete! (Trial: ${result.trialInfo.reviewsUsed}/${result.trialInfo.reviewsLimit} reviews today)`));
94
123
  }
@@ -115,6 +144,15 @@ export const reviewCommand = new Command('review')
115
144
  else {
116
145
  console.log(output);
117
146
  }
147
+ // Check --fail-on after output
148
+ if (options.failOn) {
149
+ const severityOrder = { info: 0, warning: 1, error: 2, critical: 3 };
150
+ const threshold = severityOrder[options.failOn] ?? 0;
151
+ const hasBlockingIssues = result.issues.some((i) => (severityOrder[i.severity] ?? 0) >= threshold);
152
+ if (hasBlockingIssues) {
153
+ process.exit(1);
154
+ }
155
+ }
118
156
  }
119
157
  catch (error) {
120
158
  spinner.fail(chalk.red('Review failed'));
@@ -133,20 +171,51 @@ export const reviewCommand = new Command('review')
133
171
  process.exit(1);
134
172
  }
135
173
  });
136
- async function getDiff(files, options) {
174
+ async function getDiff(files, options, verbose) {
175
+ let diff;
176
+ gitService.setVerbose(!!verbose);
137
177
  if (files && files.length > 0) {
138
- return gitService.getDiffForFiles(files);
178
+ if (verbose) {
179
+ console.log(chalk.dim(`[verbose] Getting diff for specific files: ${files.join(', ')}`));
180
+ }
181
+ diff = await gitService.getDiffForFiles(files);
182
+ }
183
+ else if (options.branch) {
184
+ if (verbose) {
185
+ console.log(chalk.dim(`[verbose] Getting diff for branch: ${options.branch}`));
186
+ }
187
+ diff = await gitService.getDiffForBranch(options.branch);
188
+ }
189
+ else if (options.commit) {
190
+ if (verbose) {
191
+ console.log(chalk.dim(`[verbose] Getting diff for commit: ${options.commit}`));
192
+ }
193
+ diff = await gitService.getDiffForCommit(options.commit);
139
194
  }
140
- if (options.branch) {
141
- return gitService.getDiffForBranch(options.branch);
195
+ else if (options.staged) {
196
+ if (verbose) {
197
+ console.log(chalk.dim('[verbose] Getting staged diff only'));
198
+ }
199
+ diff = await gitService.getStagedDiff();
142
200
  }
143
- if (options.commit) {
144
- return gitService.getDiffForCommit(options.commit);
201
+ else {
202
+ if (verbose) {
203
+ console.log(chalk.dim('[verbose] Getting working tree diff (staged + unstaged)'));
204
+ }
205
+ diff = await gitService.getWorkingTreeDiff();
145
206
  }
146
- if (options.staged) {
147
- return gitService.getStagedDiff();
207
+ if (verbose) {
208
+ console.log(chalk.dim(`[verbose] Diff result: ${diff ? `${diff.length} characters` : 'empty'}`));
209
+ if (!diff) {
210
+ console.log(chalk.dim('[verbose] No changes detected in the requested scope'));
211
+ }
212
+ else {
213
+ // Show first 500 chars of diff for debugging
214
+ const preview = diff.substring(0, 500);
215
+ console.log(chalk.dim(`[verbose] Diff preview:\n${preview}${diff.length > 500 ? '\n... (truncated)' : ''}`));
216
+ }
148
217
  }
149
- return gitService.getWorkingTreeDiff();
218
+ return diff;
150
219
  }
151
220
  function formatOutput(result, format) {
152
221
  switch (format) {
@@ -1 +1 @@
1
- {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  export declare const API_URL: string;
2
- export declare const CLI_VERSION = "1.0.0";
2
+ export declare const CLI_VERSION: string;
3
3
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,QAAsD,CAAC;AAC3E,eAAO,MAAM,WAAW,UAAU,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO,QAAsD,CAAC;AAC3E,eAAO,MAAM,WAAW,QAAc,CAAC"}
package/dist/constants.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const pkg = require('../package.json');
1
4
  export const API_URL = process.env.KODUS_API_URL || 'https://api.kodus.io';
2
- export const CLI_VERSION = '1.0.0';
5
+ export const CLI_VERSION = pkg.version;
3
6
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,sBAAsB,CAAC;AAC3E,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAE9D,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,sBAAsB,CAAC;AAC3E,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/auth.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { AuthError } from '../../types/index.js';
3
+ vi.mock('../api/index.js', () => ({
4
+ api: {
5
+ auth: {
6
+ login: vi.fn(),
7
+ refresh: vi.fn(),
8
+ logout: vi.fn(),
9
+ generateCIToken: vi.fn(),
10
+ verify: vi.fn(),
11
+ },
12
+ },
13
+ }));
14
+ vi.mock('../../utils/credentials.js', () => ({
15
+ loadCredentials: vi.fn(),
16
+ saveCredentials: vi.fn(),
17
+ clearCredentials: vi.fn(),
18
+ }));
19
+ vi.mock('../../utils/config.js', () => ({
20
+ loadConfig: vi.fn(),
21
+ }));
22
+ import { api } from '../api/index.js';
23
+ import { loadCredentials, saveCredentials, clearCredentials } from '../../utils/credentials.js';
24
+ import { loadConfig } from '../../utils/config.js';
25
+ import { AuthService } from '../auth.service.js';
26
+ const mockApi = vi.mocked(api);
27
+ const mockLoadCredentials = vi.mocked(loadCredentials);
28
+ const mockSaveCredentials = vi.mocked(saveCredentials);
29
+ const mockClearCredentials = vi.mocked(clearCredentials);
30
+ const mockLoadConfig = vi.mocked(loadConfig);
31
+ function makeCredentials(overrides = {}) {
32
+ return {
33
+ accessToken: 'access-token',
34
+ refreshToken: 'refresh-token',
35
+ expiresAt: Date.now() + 3600 * 1000,
36
+ user: { id: 'u1', email: 'test@example.com', orgs: [] },
37
+ ...overrides,
38
+ };
39
+ }
40
+ function makeAuthResponse(overrides = {}) {
41
+ return {
42
+ accessToken: 'new-access-token',
43
+ refreshToken: 'new-refresh-token',
44
+ expiresIn: 3600,
45
+ user: { id: 'u1', email: 'test@example.com', orgs: [] },
46
+ ...overrides,
47
+ };
48
+ }
49
+ describe('AuthService', () => {
50
+ let authService;
51
+ beforeEach(() => {
52
+ vi.clearAllMocks();
53
+ authService = new AuthService();
54
+ });
55
+ describe('login', () => {
56
+ it('calls api.auth.login and saves credentials', async () => {
57
+ const response = makeAuthResponse();
58
+ mockApi.auth.login = vi.fn().mockResolvedValue(response);
59
+ await authService.login('test@example.com', 'password123');
60
+ expect(mockApi.auth.login).toHaveBeenCalledWith('test@example.com', 'password123');
61
+ expect(mockSaveCredentials).toHaveBeenCalledWith(expect.objectContaining({
62
+ accessToken: 'new-access-token',
63
+ refreshToken: 'new-refresh-token',
64
+ }));
65
+ });
66
+ });
67
+ describe('logout', () => {
68
+ it('calls api.auth.logout and clears credentials and cache', async () => {
69
+ const creds = makeCredentials();
70
+ mockLoadCredentials.mockResolvedValue(creds);
71
+ mockApi.auth.logout = vi.fn().mockResolvedValue(undefined);
72
+ await authService.logout();
73
+ expect(mockApi.auth.logout).toHaveBeenCalledWith('access-token');
74
+ expect(mockClearCredentials).toHaveBeenCalled();
75
+ });
76
+ it('ignores API errors during logout silently', async () => {
77
+ const creds = makeCredentials();
78
+ mockLoadCredentials.mockResolvedValue(creds);
79
+ mockApi.auth.logout = vi.fn().mockRejectedValue(new Error('Network error'));
80
+ await authService.logout();
81
+ expect(mockClearCredentials).toHaveBeenCalled();
82
+ });
83
+ });
84
+ describe('isAuthenticated', () => {
85
+ it('returns true when credentials exist', async () => {
86
+ mockLoadCredentials.mockResolvedValue(makeCredentials());
87
+ const result = await authService.isAuthenticated();
88
+ expect(result).toBe(true);
89
+ });
90
+ it('returns true when teamKey exists (no credentials)', async () => {
91
+ mockLoadCredentials.mockResolvedValue(null);
92
+ mockLoadConfig.mockResolvedValue({ teamKey: 'kodus_abc123' });
93
+ const result = await authService.isAuthenticated();
94
+ expect(result).toBe(true);
95
+ });
96
+ it('returns false when neither credentials nor teamKey exist', async () => {
97
+ mockLoadCredentials.mockResolvedValue(null);
98
+ mockLoadConfig.mockResolvedValue(null);
99
+ const result = await authService.isAuthenticated();
100
+ expect(result).toBe(false);
101
+ });
102
+ });
103
+ describe('getValidToken', () => {
104
+ it('returns teamKey when it exists', async () => {
105
+ mockLoadConfig.mockResolvedValue({ teamKey: 'kodus_team_key' });
106
+ const token = await authService.getValidToken();
107
+ expect(token).toBe('kodus_team_key');
108
+ });
109
+ it('returns accessToken when not expired', async () => {
110
+ mockLoadConfig.mockResolvedValue(null);
111
+ const creds = makeCredentials({ expiresAt: Date.now() + 60 * 60 * 1000 });
112
+ mockLoadCredentials.mockResolvedValue(creds);
113
+ const token = await authService.getValidToken();
114
+ expect(token).toBe('access-token');
115
+ });
116
+ it('refreshes token when expired and saves new credentials', async () => {
117
+ mockLoadConfig.mockResolvedValue(null);
118
+ const expiredCreds = makeCredentials({ expiresAt: Date.now() - 1000 });
119
+ mockLoadCredentials.mockResolvedValue(expiredCreds);
120
+ const newResponse = makeAuthResponse({ accessToken: 'refreshed-token' });
121
+ mockApi.auth.refresh = vi.fn().mockResolvedValue(newResponse);
122
+ const token = await authService.getValidToken();
123
+ expect(token).toBe('refreshed-token');
124
+ expect(mockApi.auth.refresh).toHaveBeenCalledWith('refresh-token');
125
+ expect(mockSaveCredentials).toHaveBeenCalledWith(expect.objectContaining({ accessToken: 'refreshed-token' }));
126
+ });
127
+ it('throws AuthError and clears credentials when refresh fails', async () => {
128
+ mockLoadConfig.mockResolvedValue(null);
129
+ const expiredCreds = makeCredentials({ expiresAt: Date.now() - 1000 });
130
+ mockLoadCredentials.mockResolvedValue(expiredCreds);
131
+ mockApi.auth.refresh = vi.fn().mockRejectedValue(new Error('refresh failed'));
132
+ await expect(authService.getValidToken()).rejects.toThrow(AuthError);
133
+ expect(mockClearCredentials).toHaveBeenCalled();
134
+ });
135
+ it('throws AuthError when no credentials exist', async () => {
136
+ mockLoadConfig.mockResolvedValue(null);
137
+ mockLoadCredentials.mockResolvedValue(null);
138
+ await expect(authService.getValidToken()).rejects.toThrow(AuthError);
139
+ });
140
+ });
141
+ describe('getCredentials', () => {
142
+ it('caches credentials after first load', async () => {
143
+ const creds = makeCredentials();
144
+ mockLoadCredentials.mockResolvedValue(creds);
145
+ const first = await authService.getCredentials();
146
+ const second = await authService.getCredentials();
147
+ expect(first).toBe(second);
148
+ expect(mockLoadCredentials).toHaveBeenCalledTimes(1);
149
+ });
150
+ });
151
+ describe('verifyToken', () => {
152
+ it('returns { valid: false } when no credentials exist', async () => {
153
+ mockLoadCredentials.mockResolvedValue(null);
154
+ const result = await authService.verifyToken();
155
+ expect(result).toEqual({ valid: false });
156
+ });
157
+ it('delegates to api.auth.verify with accessToken', async () => {
158
+ const creds = makeCredentials();
159
+ mockLoadCredentials.mockResolvedValue(creds);
160
+ mockApi.auth.verify = vi.fn().mockResolvedValue({ valid: true, user: { id: 'u1' } });
161
+ const result = await authService.verifyToken();
162
+ expect(mockApi.auth.verify).toHaveBeenCalledWith('access-token');
163
+ expect(result).toEqual({ valid: true, user: { id: 'u1' } });
164
+ });
165
+ });
166
+ });
167
+ //# sourceMappingURL=auth.service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/auth.service.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=git.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/git.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { gitService } from '../git.service.js';
3
+ describe('inferPlatform', () => {
4
+ it('detects GitHub from HTTPS URL', () => {
5
+ expect(gitService.inferPlatform('https://github.com/org/repo.git')).toBe('GITHUB');
6
+ });
7
+ it('detects GitHub from SSH URL', () => {
8
+ expect(gitService.inferPlatform('git@github.com:org/repo.git')).toBe('GITHUB');
9
+ });
10
+ it('detects GitLab from HTTPS URL', () => {
11
+ expect(gitService.inferPlatform('https://gitlab.com/org/repo.git')).toBe('GITLAB');
12
+ });
13
+ it('detects GitLab from SSH URL', () => {
14
+ expect(gitService.inferPlatform('git@gitlab.com:org/repo.git')).toBe('GITLAB');
15
+ });
16
+ it('detects Bitbucket from HTTPS URL', () => {
17
+ expect(gitService.inferPlatform('https://bitbucket.org/org/repo.git')).toBe('BITBUCKET');
18
+ });
19
+ it('detects Bitbucket from SSH URL', () => {
20
+ expect(gitService.inferPlatform('git@bitbucket.org:org/repo.git')).toBe('BITBUCKET');
21
+ });
22
+ it('detects Azure DevOps from dev.azure.com URL', () => {
23
+ expect(gitService.inferPlatform('https://dev.azure.com/org/project/_git/repo')).toBe('AZURE_REPOS');
24
+ });
25
+ it('detects Azure DevOps from visualstudio.com URL', () => {
26
+ expect(gitService.inferPlatform('https://org.visualstudio.com/project/_git/repo')).toBe('AZURE_REPOS');
27
+ });
28
+ it('returns undefined for null', () => {
29
+ expect(gitService.inferPlatform(null)).toBeUndefined();
30
+ });
31
+ it('returns undefined for undefined', () => {
32
+ expect(gitService.inferPlatform(undefined)).toBeUndefined();
33
+ });
34
+ it('returns undefined for unknown host', () => {
35
+ expect(gitService.inferPlatform('https://selfhosted.example.com/org/repo.git')).toBeUndefined();
36
+ });
37
+ });
38
+ describe('parseGitStatus', () => {
39
+ it('maps A to added', () => {
40
+ expect(gitService.parseGitStatus('A')).toBe('added');
41
+ });
42
+ it('maps D to deleted', () => {
43
+ expect(gitService.parseGitStatus('D')).toBe('deleted');
44
+ });
45
+ it('maps R to renamed', () => {
46
+ expect(gitService.parseGitStatus('R')).toBe('renamed');
47
+ });
48
+ it('maps M to modified', () => {
49
+ expect(gitService.parseGitStatus('M')).toBe('modified');
50
+ });
51
+ it('maps unknown char to modified', () => {
52
+ expect(gitService.parseGitStatus('X')).toBe('modified');
53
+ });
54
+ it('handles lowercase input', () => {
55
+ expect(gitService.parseGitStatus('a')).toBe('added');
56
+ });
57
+ it('handles status with trailing info (e.g. R100)', () => {
58
+ expect(gitService.parseGitStatus('R100')).toBe('renamed');
59
+ });
60
+ });
61
+ //# sourceMappingURL=git.service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/git.service.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,oCAAoC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,6CAA6C,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,gDAAgD,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,6CAA6C,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=review.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/review.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,132 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { reviewService } from '../review.service.js';
3
+ describe('normalizeSeverity', () => {
4
+ it('maps critical to critical', () => {
5
+ expect(reviewService.normalizeSeverity('critical')).toBe('critical');
6
+ });
7
+ it('maps high to error', () => {
8
+ expect(reviewService.normalizeSeverity('high')).toBe('error');
9
+ });
10
+ it('maps error to error', () => {
11
+ expect(reviewService.normalizeSeverity('error')).toBe('error');
12
+ });
13
+ it('maps medium to warning', () => {
14
+ expect(reviewService.normalizeSeverity('medium')).toBe('warning');
15
+ });
16
+ it('maps warning to warning', () => {
17
+ expect(reviewService.normalizeSeverity('warning')).toBe('warning');
18
+ });
19
+ it('maps low to info', () => {
20
+ expect(reviewService.normalizeSeverity('low')).toBe('info');
21
+ });
22
+ it('maps info to info', () => {
23
+ expect(reviewService.normalizeSeverity('info')).toBe('info');
24
+ });
25
+ it('maps undefined to info', () => {
26
+ expect(reviewService.normalizeSeverity(undefined)).toBe('info');
27
+ });
28
+ it('maps unknown string to info', () => {
29
+ expect(reviewService.normalizeSeverity('something')).toBe('info');
30
+ });
31
+ it('is case-insensitive', () => {
32
+ expect(reviewService.normalizeSeverity('CRITICAL')).toBe('critical');
33
+ expect(reviewService.normalizeSeverity('High')).toBe('error');
34
+ expect(reviewService.normalizeSeverity('WARNING')).toBe('warning');
35
+ });
36
+ });
37
+ describe('normalizeSuggestionsResponse', () => {
38
+ it('normalizes response with issues array', () => {
39
+ const response = {
40
+ summary: 'Found issues',
41
+ issues: [
42
+ { file: 'a.ts', line: 1, severity: 'error', message: 'bug' },
43
+ ],
44
+ filesAnalyzed: 1,
45
+ duration: 100,
46
+ };
47
+ const result = reviewService.normalizeSuggestionsResponse(response);
48
+ expect(result.summary).toBe('Found issues');
49
+ expect(result.issues).toHaveLength(1);
50
+ expect(result.issues[0].file).toBe('a.ts');
51
+ expect(result.filesAnalyzed).toBe(1);
52
+ expect(result.duration).toBe(100);
53
+ });
54
+ it('normalizes response with suggestions array', () => {
55
+ const response = {
56
+ suggestions: [
57
+ { file: 'b.ts', line: 5, severity: 'warning', message: 'style issue' },
58
+ ],
59
+ };
60
+ const result = reviewService.normalizeSuggestionsResponse(response);
61
+ expect(result.issues).toHaveLength(1);
62
+ expect(result.issues[0].file).toBe('b.ts');
63
+ expect(result.summary).toBe('Pull request suggestions');
64
+ });
65
+ it('normalizes response with suggestions object (files + prLevel)', () => {
66
+ const response = {
67
+ suggestions: {
68
+ files: [
69
+ {
70
+ id: '1',
71
+ relevantFile: 'c.ts',
72
+ suggestionContent: 'Fix this',
73
+ oneSentenceSummary: 'Fix summary',
74
+ label: 'security',
75
+ severity: 'high',
76
+ relevantLinesStart: 10,
77
+ relevantLinesEnd: 15,
78
+ },
79
+ ],
80
+ prLevel: [
81
+ {
82
+ id: '2',
83
+ suggestionContent: 'Improve PR description',
84
+ oneSentenceSummary: 'PR summary',
85
+ label: 'docs',
86
+ severity: 'low',
87
+ },
88
+ ],
89
+ },
90
+ };
91
+ const result = reviewService.normalizeSuggestionsResponse(response);
92
+ expect(result.issues).toHaveLength(2);
93
+ const fileIssue = result.issues[0];
94
+ expect(fileIssue.file).toBe('c.ts');
95
+ expect(fileIssue.line).toBe(10);
96
+ expect(fileIssue.endLine).toBe(15);
97
+ expect(fileIssue.severity).toBe('error'); // high → error
98
+ expect(fileIssue.message).toBe('Fix this');
99
+ expect(fileIssue.suggestion).toBe('Fix summary');
100
+ expect(fileIssue.ruleId).toBe('security');
101
+ const prIssue = result.issues[1];
102
+ expect(prIssue.file).toBe('PR');
103
+ expect(prIssue.line).toBe(0);
104
+ expect(prIssue.severity).toBe('info'); // low → info
105
+ expect(prIssue.message).toBe('Improve PR description');
106
+ });
107
+ it('handles empty response', () => {
108
+ const response = {};
109
+ const result = reviewService.normalizeSuggestionsResponse(response);
110
+ expect(result.issues).toHaveLength(0);
111
+ expect(result.summary).toBe('Pull request suggestions');
112
+ expect(result.filesAnalyzed).toBe(0);
113
+ expect(result.duration).toBe(0);
114
+ });
115
+ it('uses filePath over relevantFile when available', () => {
116
+ const response = {
117
+ suggestions: {
118
+ files: [
119
+ {
120
+ id: '1',
121
+ relevantFile: 'old-path.ts',
122
+ filePath: 'new-path.ts',
123
+ suggestionContent: 'Fix',
124
+ },
125
+ ],
126
+ },
127
+ };
128
+ const result = reviewService.normalizeSuggestionsResponse(response);
129
+ expect(result.issues[0].file).toBe('new-path.ts');
130
+ });
131
+ });
132
+ //# sourceMappingURL=review.service.test.js.map