@forgehive/hive-sdk 0.0.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.
@@ -0,0 +1,268 @@
1
+ import axios from 'axios'
2
+ import { HiveLogClient, Quality } from '../index'
3
+
4
+ // Mock axios
5
+ jest.mock('axios')
6
+ const mockedAxios = axios as jest.Mocked<typeof axios>
7
+
8
+ describe('HiveLogClient setQuality', () => {
9
+ const originalEnv = process.env
10
+ let client: HiveLogClient
11
+
12
+ beforeEach(() => {
13
+ jest.resetModules()
14
+ process.env = { ...originalEnv }
15
+
16
+ // Set up environment variables
17
+ process.env.HIVE_API_KEY = 'test-api-key'
18
+ process.env.HIVE_API_SECRET = 'test-api-secret'
19
+ process.env.HIVE_HOST = 'https://test-host.com'
20
+
21
+ // Create client instance
22
+ client = new HiveLogClient('test-project')
23
+
24
+ // Clear all mocks
25
+ jest.clearAllMocks()
26
+ })
27
+
28
+ afterAll(() => {
29
+ process.env = originalEnv
30
+ })
31
+
32
+ describe('successful setQuality', () => {
33
+ it('should set quality successfully and return true', async () => {
34
+ // Mock successful axios response
35
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
36
+
37
+ const quality: Quality = {
38
+ score: 8.5,
39
+ reason: 'Good performance with minor improvements needed',
40
+ suggestions: 'Consider optimizing the database query for better performance'
41
+ }
42
+
43
+ const result = await client.setQuality('test-task', 'test-uuid-123', quality)
44
+
45
+ expect(result).toBe(true)
46
+ expect(mockedAxios.post).toHaveBeenCalledTimes(1)
47
+ expect(mockedAxios.post).toHaveBeenCalledWith(
48
+ 'https://test-host.com/api/tasks/test-task/logs/test-uuid-123/set-quality',
49
+ {
50
+ quality
51
+ },
52
+ {
53
+ headers: {
54
+ Authorization: 'Bearer test-api-key:test-api-secret',
55
+ 'Content-Type': 'application/json'
56
+ }
57
+ }
58
+ )
59
+ })
60
+
61
+ it('should handle perfect score quality', async () => {
62
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
63
+
64
+ const perfectQuality: Quality = {
65
+ score: 10,
66
+ reason: 'Excellent implementation with no issues found',
67
+ suggestions: 'No improvements needed, great work!'
68
+ }
69
+
70
+ const result = await client.setQuality('perfect-task', 'perfect-uuid', perfectQuality)
71
+
72
+ expect(result).toBe(true)
73
+ expect(mockedAxios.post).toHaveBeenCalledWith(
74
+ 'https://test-host.com/api/tasks/perfect-task/logs/perfect-uuid/set-quality',
75
+ {
76
+ quality: perfectQuality
77
+ },
78
+ expect.any(Object)
79
+ )
80
+ })
81
+
82
+ it('should handle poor score quality with detailed suggestions', async () => {
83
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
84
+
85
+ const poorQuality: Quality = {
86
+ score: 2.0,
87
+ reason: 'Multiple issues found including performance problems and code quality issues',
88
+ suggestions: 'Refactor the main function, add error handling, optimize database queries, and improve variable naming conventions'
89
+ }
90
+
91
+ const result = await client.setQuality('poor-task', 'poor-uuid', poorQuality)
92
+
93
+ expect(result).toBe(true)
94
+ expect(mockedAxios.post).toHaveBeenCalledWith(
95
+ 'https://test-host.com/api/tasks/poor-task/logs/poor-uuid/set-quality',
96
+ {
97
+ quality: poorQuality
98
+ },
99
+ expect.any(Object)
100
+ )
101
+ })
102
+
103
+ it('should handle edge case scores', async () => {
104
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
105
+
106
+ const edgeCaseQuality: Quality = {
107
+ score: 0,
108
+ reason: 'Critical failure in implementation',
109
+ suggestions: 'Complete rewrite required'
110
+ }
111
+
112
+ const result = await client.setQuality('edge-task', 'edge-uuid', edgeCaseQuality)
113
+
114
+ expect(result).toBe(true)
115
+ })
116
+ })
117
+
118
+ describe('failed setQuality', () => {
119
+ it('should return false when axios throws an error', async () => {
120
+ // Mock axios to throw an error
121
+ mockedAxios.post.mockRejectedValueOnce(new Error('Network error'))
122
+
123
+ const quality: Quality = {
124
+ score: 7.0,
125
+ reason: 'Test quality',
126
+ suggestions: 'Test suggestions'
127
+ }
128
+
129
+ const result = await client.setQuality('test-task', 'test-uuid', quality)
130
+
131
+ expect(result).toBe(false)
132
+ })
133
+
134
+ it('should return false when server returns 404', async () => {
135
+ // Mock axios to throw a 404 error
136
+ const notFoundError = new Error('Request failed with status code 404')
137
+ mockedAxios.post.mockRejectedValueOnce(notFoundError)
138
+
139
+ const quality: Quality = {
140
+ score: 5.0,
141
+ reason: 'Not found test',
142
+ suggestions: 'Test suggestions for not found'
143
+ }
144
+
145
+ const result = await client.setQuality('non-existent-task', 'non-existent-uuid', quality)
146
+
147
+ expect(result).toBe(false)
148
+ })
149
+
150
+ it('should return false when server returns 500', async () => {
151
+ // Mock axios to throw a server error
152
+ const serverError = new Error('Internal Server Error')
153
+ mockedAxios.post.mockRejectedValueOnce(serverError)
154
+
155
+ const quality: Quality = {
156
+ score: 6.0,
157
+ reason: 'Server error test',
158
+ suggestions: 'Test suggestions for server error'
159
+ }
160
+
161
+ const result = await client.setQuality('test-task', 'test-uuid', quality)
162
+
163
+ expect(result).toBe(false)
164
+ })
165
+
166
+ it('should return false when unauthorized', async () => {
167
+ // Mock axios to throw an unauthorized error
168
+ const unauthorizedError = new Error('Request failed with status code 401')
169
+ mockedAxios.post.mockRejectedValueOnce(unauthorizedError)
170
+
171
+ const quality: Quality = {
172
+ score: 3.0,
173
+ reason: 'Unauthorized test',
174
+ suggestions: 'Check API credentials'
175
+ }
176
+
177
+ const result = await client.setQuality('test-task', 'test-uuid', quality)
178
+
179
+ expect(result).toBe(false)
180
+ })
181
+ })
182
+
183
+ describe('setQuality parameters', () => {
184
+ it('should handle special characters in taskName and uuid', async () => {
185
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
186
+
187
+ const quality: Quality = {
188
+ score: 4.5,
189
+ reason: 'Special characters test',
190
+ suggestions: 'Handle special characters properly'
191
+ }
192
+
193
+ const result = await client.setQuality('task-with-special-chars-!@#', 'uuid-with-special-chars-!@#', quality)
194
+
195
+ expect(result).toBe(true)
196
+ expect(mockedAxios.post).toHaveBeenCalledWith(
197
+ 'https://test-host.com/api/tasks/task-with-special-chars-!@#/logs/uuid-with-special-chars-!@#/set-quality',
198
+ { quality },
199
+ expect.any(Object)
200
+ )
201
+ })
202
+
203
+ it('should handle decimal scores correctly', async () => {
204
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
205
+
206
+ const quality: Quality = {
207
+ score: 7.123456789,
208
+ reason: 'Decimal precision test',
209
+ suggestions: 'Maintain precision in quality scores'
210
+ }
211
+
212
+ const result = await client.setQuality('decimal-task', 'decimal-uuid', quality)
213
+
214
+ expect(result).toBe(true)
215
+ expect(mockedAxios.post).toHaveBeenCalledWith(
216
+ 'https://test-host.com/api/tasks/decimal-task/logs/decimal-uuid/set-quality',
217
+ { quality },
218
+ expect.any(Object)
219
+ )
220
+ })
221
+
222
+ it('should handle long reason and suggestions', async () => {
223
+ mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
224
+
225
+ const longReason = 'This is a very long reason that explains in detail what went wrong with the implementation and why the score is what it is. '.repeat(5)
226
+ const longSuggestions = 'Here are detailed suggestions for improvement: 1. Refactor the main function, 2. Add comprehensive error handling, 3. Optimize database queries, 4. Improve code documentation, 5. Add unit tests. '.repeat(3)
227
+
228
+ const quality: Quality = {
229
+ score: 3.5,
230
+ reason: longReason,
231
+ suggestions: longSuggestions
232
+ }
233
+
234
+ const result = await client.setQuality('long-text-task', 'long-text-uuid', quality)
235
+
236
+ expect(result).toBe(true)
237
+ expect(mockedAxios.post).toHaveBeenCalledWith(
238
+ 'https://test-host.com/api/tasks/long-text-task/logs/long-text-uuid/set-quality',
239
+ { quality },
240
+ expect.any(Object)
241
+ )
242
+ })
243
+ })
244
+
245
+ describe('silent mode behavior', () => {
246
+ it('should throw error when credentials are missing', async () => {
247
+ // Create client without credentials
248
+ process.env.HIVE_API_KEY = ''
249
+ process.env.HIVE_API_SECRET = ''
250
+ process.env.HIVE_HOST = ''
251
+
252
+ const silentClient = new HiveLogClient('silent-project')
253
+
254
+ const quality: Quality = {
255
+ score: 8.0,
256
+ reason: 'Test quality for silent mode',
257
+ suggestions: 'This should not be processed'
258
+ }
259
+
260
+ await expect(silentClient.setQuality('test-task', 'test-uuid', quality))
261
+ .rejects
262
+ .toThrow('Missing Hive API credentials or host, get them at https://forgehive.dev')
263
+
264
+ // Verify axios was never called
265
+ expect(mockedAxios.post).not.toHaveBeenCalled()
266
+ })
267
+ })
268
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strictNullChecks": true,
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "resolveJsonModule": true,
7
+ "esModuleInterop": true,
8
+ "module": "commonjs",
9
+ "moduleResolution": "node",
10
+ "declaration": true,
11
+ "target": "es2020",
12
+ "lib": ["es2020", "dom"]
13
+ },
14
+ "files": ["src/index.ts"],
15
+ "include": ["src/**/*.ts", "src/**/*.json"],
16
+ "exclude": ["node_modules", "dist/*"]
17
+ }