@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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ForgeHive
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # Hive SDK
2
+
3
+ A TypeScript/JavaScript SDK for interacting with the Forge Hive logging and quality assessment platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @forgehive/hive-sdk
9
+ ```
10
+
11
+ or with pnpm:
12
+
13
+ ```bash
14
+ pnpm add @forgehive/hive-sdk
15
+ ```
16
+
17
+ ## Setup
18
+
19
+ ### 1. Environment Variables
20
+
21
+ Before using the SDK, you need to set up the following environment variables:
22
+
23
+ ```bash
24
+ HIVE_API_KEY=your_api_key_here
25
+ HIVE_API_SECRET=your_api_secret_here
26
+ HIVE_HOST=https://your-hive-instance.com
27
+ ```
28
+
29
+ You can get your API credentials at [https://forgehive.dev](https://forgehive.dev).
30
+
31
+ ### 2. Basic Usage
32
+
33
+ ```typescript
34
+ import { createHiveLogClient } from '@forgehive/hive-sdk'
35
+
36
+ const hiveLogger = createHiveLogClient('Personal Knowledge Management System')
37
+ ```
38
+
39
+ ## API Methods
40
+
41
+ ### `isActive(): boolean`
42
+
43
+ Check if the client is properly initialized with credentials.
44
+
45
+ ```typescript
46
+ const hiveLogger = createHiveLogClient('My Project')
47
+
48
+ if (hiveLogger.isActive()) {
49
+ console.log('Client is initialized with credentials')
50
+ // Safe to call getLog and setQuality without try/catch
51
+ } else {
52
+ console.log('Client is in silent mode')
53
+ // Only sendLog will work (returns 'silent')
54
+ }
55
+ ```
56
+
57
+ **Returns:** `boolean` - `true` if credentials are available, `false` if in silent mode
58
+
59
+ ### `sendLog(taskName: string, logItem: unknown): Promise<'success' | 'error' | 'silent'>`
60
+
61
+ Sends a log entry to Hive for a specific task.
62
+
63
+ ```typescript
64
+ const status = await hiveLogger.sendLog('user-authentication', {
65
+ input: { username: 'john_doe', timestamp: Date.now() },
66
+ output: { success: true, userId: 12345 },
67
+ boundaries: {
68
+ database: [
69
+ {
70
+ input: 'SELECT * FROM users WHERE username = ?',
71
+ output: [{ id: 12345, username: 'john_doe' }],
72
+ error: null
73
+ }
74
+ ]
75
+ }
76
+ })
77
+
78
+ switch (status) {
79
+ case 'success':
80
+ console.log('Log sent successfully')
81
+ break
82
+ case 'error':
83
+ console.error('Failed to send log - network or API error')
84
+ break
85
+ case 'silent':
86
+ console.log('Running in silent mode - no credentials configured')
87
+ break
88
+ }
89
+ ```
90
+
91
+ **Parameters:**
92
+ - `taskName`: Name of the task being logged
93
+ - `logItem`: Object containing input, output, error, and boundaries data
94
+
95
+ **Returns:** `Promise<'success' | 'error' | 'silent'>` - Status of the operation
96
+
97
+ ### `getLog(taskName: string, uuid: string): Promise<LogApiResult | null>`
98
+
99
+ Retrieves a specific log entry from Hive.
100
+
101
+ ```typescript
102
+ try {
103
+ const logData = await hiveLogger.getLog('user-authentication', 'log-uuid-123')
104
+
105
+ if (logData && !isApiError(logData)) {
106
+ console.log('Log retrieved:', logData.logItem)
107
+ } else if (logData && isApiError(logData)) {
108
+ console.error('API Error:', logData.error)
109
+ } else {
110
+ console.error('Failed to retrieve log')
111
+ }
112
+ } catch (error) {
113
+ console.error('Missing credentials:', error.message)
114
+ }
115
+ ```
116
+
117
+ **Parameters:**
118
+ - `taskName`: Name of the task
119
+ - `uuid`: Unique identifier of the log entry
120
+
121
+ **Returns:** `Promise<LogApiResult | null>` - Log data, error object, or `null` if failed
122
+ **Throws:** Error when credentials are missing
123
+
124
+ ### `setQuality(taskName: string, uuid: string, quality: Quality): Promise<boolean>`
125
+
126
+ Sets a quality assessment for a specific log entry.
127
+
128
+ ```typescript
129
+ import { Quality } from '@forgehive/hive-sdk'
130
+
131
+ const quality: Quality = {
132
+ score: 8.5,
133
+ reason: 'Good performance with minor improvements needed',
134
+ suggestions: 'Consider optimizing the database query for better performance'
135
+ }
136
+
137
+ try {
138
+ const success = await hiveLogger.setQuality('user-authentication', 'log-uuid-123', quality)
139
+
140
+ if (success) {
141
+ console.log('Quality assessment saved')
142
+ } else {
143
+ console.error('Failed to save quality assessment')
144
+ }
145
+ } catch (error) {
146
+ console.error('Missing credentials:', error.message)
147
+ }
148
+ ```
149
+
150
+ **Parameters:**
151
+ - `taskName`: Name of the task
152
+ - `uuid`: Unique identifier of the log entry
153
+ - `quality`: Quality assessment object with score (number), reason (string), and suggestions (string)
154
+
155
+ **Returns:** `Promise<boolean>` - `true` if successful, `false` if failed
156
+ **Throws:** Error when credentials are missing
157
+
158
+ ## Types
159
+
160
+ ### `LogApiResponse`
161
+
162
+ ```typescript
163
+ interface LogApiResponse {
164
+ uuid: string
165
+ taskName: string
166
+ projectName: string
167
+ logItem: {
168
+ input: unknown
169
+ output?: unknown
170
+ error?: unknown
171
+ boundaries?: Record<string, Array<{ input: unknown; output: unknown, error: unknown }>>
172
+ }
173
+ replayFrom?: string
174
+ createdAt: string
175
+ }
176
+ ```
177
+
178
+ ### `Quality`
179
+
180
+ ```typescript
181
+ interface Quality {
182
+ score: number // Quality score (typically 0-10)
183
+ reason: string // Explanation for the score
184
+ suggestions: string // Suggestions for improvement
185
+ }
186
+ ```
187
+
188
+ ### `ApiError`
189
+
190
+ ```typescript
191
+ interface ApiError {
192
+ error: string
193
+ }
194
+ ```
195
+
196
+ ## Type Guards
197
+
198
+ ### `isApiError(response: unknown): response is ApiError`
199
+
200
+ Use this type guard to check if a response is an error:
201
+
202
+ ```typescript
203
+ import { isApiError } from '@forgehive/hive-sdk'
204
+
205
+ const result = await hiveLogger.getLog('task-name', 'log-uuid')
206
+
207
+ if (result && isApiError(result)) {
208
+ console.error('Error:', result.error)
209
+ } else if (result) {
210
+ console.log('Success:', result.logItem)
211
+ }
212
+ ```
213
+
214
+ ## Debugging
215
+
216
+ The SDK uses the `debug` package for internal logging. To enable debug logs, set the `DEBUG` environment variable:
217
+
218
+ ```bash
219
+ # Enable all hive-sdk debug logs
220
+ DEBUG=hive-sdk node your-app.js
221
+
222
+ # Enable all debug logs
223
+ DEBUG=* node your-app.js
224
+
225
+ # Enable hive-sdk logs along with other specific loggers
226
+ DEBUG=hive-sdk,express:* node your-app.js
227
+ ```
228
+
229
+ When debugging is enabled, you'll see detailed logs like:
230
+
231
+ ```
232
+ # Normal mode (with credentials)
233
+ hive-sdk Creating HiveLogClient for project "Personal Knowledge Management System" +0ms
234
+ hive-sdk HiveLogClient initialized for project "Personal Knowledge Management System" with host "https://your-hive-instance.com" +2ms
235
+ hive-sdk Sending log for task "user-authentication" to https://your-hive-instance.com/api/tasks/log-ingest +100ms
236
+ hive-sdk Success: Sent log for task "user-authentication" +250ms
237
+
238
+ # Silent mode (missing credentials)
239
+ hive-sdk Creating HiveLogClient for project "Personal Knowledge Management System" +0ms
240
+ hive-sdk HiveLogClient in silent mode for project "Personal Knowledge Management System" - missing credentials (get them at https://forgehive.dev) +2ms
241
+ hive-sdk Silent mode: Skipping sendLog for task "user-authentication" - client not initialized +100ms
242
+ hive-sdk Error: getLog for task "user-task" with uuid "some-uuid" - missing credentials +150ms
243
+
244
+ # Error handling
245
+ hive-sdk Error: Failed to send log for task "another-task": Network timeout +300ms
246
+ ```
247
+
248
+ ## Error Handling
249
+
250
+ The SDK handles errors gracefully:
251
+
252
+ - **Network errors**: Logged via debug, methods return `'error'` or `false`
253
+ - **Authentication errors**: Logged via debug, methods return `'error'` or `false`
254
+ - **API errors**: Returned as `ApiError` objects (for `getLog`) or logged via debug (for other methods)
255
+ - **Missing credentials**:
256
+ - `sendLog`: Returns `'silent'` (no errors thrown)
257
+ - `getLog` and `setQuality`: Throw errors
258
+
259
+ ```typescript
260
+ // sendLog works even without credentials (returns 'silent')
261
+ const hiveLogger = createHiveLogClient('My Project')
262
+
263
+ const status = await hiveLogger.sendLog('task-name', { data: 'example' })
264
+ if (status === 'error') {
265
+ console.error('Network or API error')
266
+ } else if (status === 'silent') {
267
+ console.log('Running in silent mode - no credentials')
268
+ }
269
+ ```
270
+
271
+ ### Error Handling Patterns
272
+
273
+ **Check credentials before API calls:**
274
+ ```typescript
275
+ const hiveLogger = createHiveLogClient('My Project')
276
+
277
+ if (hiveLogger.isActive()) {
278
+ // Safe to use all methods
279
+ const logData = await hiveLogger.getLog('task', 'uuid')
280
+ await hiveLogger.setQuality('task', 'uuid', quality)
281
+ } else {
282
+ console.log('Running in silent mode')
283
+ }
284
+ ```
285
+
286
+ **sendLog** - Returns status strings (never throws):
287
+ ```typescript
288
+ const status = await hiveLogger.sendLog('task', { data: 'test' })
289
+ // Returns: 'success', 'error', or 'silent'
290
+ ```
291
+
292
+ **getLog and setQuality** - Throw errors when credentials missing:
293
+ ```typescript
294
+ try {
295
+ await hiveLogger.getLog('task', 'uuid')
296
+ await hiveLogger.setQuality('task', 'uuid', quality)
297
+ } catch (error) {
298
+ console.error('Missing credentials:', error.message)
299
+ }
300
+ ```
301
+
302
+ ## Examples
303
+
304
+ ### Complete Example
305
+
306
+ ```typescript
307
+ import { createHiveLogClient, isApiError, Quality } from '@forgehive/hive-sdk'
308
+
309
+ async function main() {
310
+ // Initialize the client
311
+ const hiveLogger = createHiveLogClient('Personal Knowledge Management System')
312
+
313
+ // Send a log
314
+ const logData = {
315
+ input: { query: 'search for AI papers', userId: 123 },
316
+ output: { results: ['paper1.pdf', 'paper2.pdf'], count: 2 },
317
+ boundaries: {
318
+ search_engine: [
319
+ {
320
+ input: 'AI papers filetype:pdf',
321
+ output: { hits: 150, results: ['...'] },
322
+ error: null
323
+ }
324
+ ]
325
+ }
326
+ }
327
+
328
+ const status = await hiveLogger.sendLog('document-search', logData)
329
+ console.log('Log status:', status)
330
+
331
+ // Retrieve a log
332
+ try {
333
+ const retrievedLog = await hiveLogger.getLog('document-search', 'some-uuid')
334
+ if (retrievedLog && !isApiError(retrievedLog)) {
335
+ console.log('Retrieved log:', retrievedLog.logItem)
336
+
337
+ // Set quality assessment
338
+ const quality: Quality = {
339
+ score: 9.0,
340
+ reason: 'Excellent search results with high relevance',
341
+ suggestions: 'Consider adding result ranking by publication date'
342
+ }
343
+
344
+ const qualitySet = await hiveLogger.setQuality('document-search', retrievedLog.uuid, quality)
345
+ console.log('Quality assessment saved:', qualitySet)
346
+ }
347
+ } catch (error) {
348
+ console.error('Missing credentials for getLog/setQuality:', error.message)
349
+ }
350
+ }
351
+
352
+ main().catch(console.error)
353
+ ```
354
+
355
+ ## License
356
+
357
+ ISC
@@ -0,0 +1,42 @@
1
+ export interface LogApiResponse {
2
+ uuid: string;
3
+ taskName: string;
4
+ projectName: string;
5
+ logItem: {
6
+ input: unknown;
7
+ output?: unknown;
8
+ error?: unknown;
9
+ boundaries?: Record<string, Array<{
10
+ input: unknown;
11
+ output: unknown;
12
+ error: unknown;
13
+ }>>;
14
+ };
15
+ replayFrom?: string;
16
+ createdAt: string;
17
+ }
18
+ export interface ApiError {
19
+ error: string;
20
+ }
21
+ export interface LogApiSuccess extends LogApiResponse {
22
+ }
23
+ export type LogApiResult = LogApiSuccess | ApiError;
24
+ export interface Quality {
25
+ score: number;
26
+ reason: string;
27
+ suggestions: string;
28
+ }
29
+ export declare function isApiError(response: unknown): response is ApiError;
30
+ export declare class HiveLogClient {
31
+ private apiKey;
32
+ private apiSecret;
33
+ private host;
34
+ private projectName;
35
+ private isInitialized;
36
+ constructor(projectName: string);
37
+ isActive(): boolean;
38
+ sendLog(taskName: string, logItem: unknown): Promise<'success' | 'error' | 'silent'>;
39
+ getLog(taskName: string, uuid: string): Promise<LogApiResult | null>;
40
+ setQuality(taskName: string, uuid: string, quality: Quality): Promise<boolean>;
41
+ }
42
+ export declare const createHiveLogClient: (projectName: string) => HiveLogClient;
package/dist/index.js ADDED
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createHiveLogClient = exports.HiveLogClient = void 0;
7
+ exports.isApiError = isApiError;
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const debug_1 = __importDefault(require("debug"));
10
+ const log = (0, debug_1.default)('hive-sdk');
11
+ // Type guard to check if response is an error
12
+ function isApiError(response) {
13
+ return response !== null && typeof response === 'object' && 'error' in response;
14
+ }
15
+ class HiveLogClient {
16
+ constructor(projectName) {
17
+ const apiKey = process.env.HIVE_API_KEY;
18
+ const apiSecret = process.env.HIVE_API_SECRET;
19
+ const host = process.env.HIVE_HOST;
20
+ this.projectName = projectName;
21
+ if (!apiKey || !apiSecret || !host) {
22
+ this.apiKey = null;
23
+ this.apiSecret = null;
24
+ this.host = null;
25
+ this.isInitialized = false;
26
+ log('HiveLogClient in silent mode for project "%s" - missing credentials (get them at https://forgehive.dev)', projectName);
27
+ }
28
+ else {
29
+ this.apiKey = apiKey;
30
+ this.apiSecret = apiSecret;
31
+ this.host = host;
32
+ this.isInitialized = true;
33
+ log('HiveLogClient initialized for project "%s" with host "%s"', projectName, host);
34
+ }
35
+ }
36
+ isActive() {
37
+ return this.isInitialized;
38
+ }
39
+ async sendLog(taskName, logItem) {
40
+ if (!this.isInitialized) {
41
+ log('Silent mode: Skipping sendLog for task "%s" - client not initialized', taskName);
42
+ return 'silent';
43
+ }
44
+ try {
45
+ const logsUrl = `${this.host}/api/tasks/log-ingest`;
46
+ log('Sending log for task "%s" to %s', taskName, logsUrl);
47
+ const authToken = `${this.apiKey}:${this.apiSecret}`;
48
+ await axios_1.default.post(logsUrl, {
49
+ projectName: this.projectName,
50
+ taskName,
51
+ logItem: JSON.stringify(logItem)
52
+ }, {
53
+ headers: {
54
+ Authorization: `Bearer ${authToken}`,
55
+ 'Content-Type': 'application/json'
56
+ }
57
+ });
58
+ log('Success: Sent log for task "%s"', taskName);
59
+ return 'success';
60
+ }
61
+ catch (e) {
62
+ const error = e;
63
+ log('Error: Failed to send log for task "%s": %s', taskName, error.message);
64
+ return 'error';
65
+ }
66
+ }
67
+ async getLog(taskName, uuid) {
68
+ if (!this.isInitialized) {
69
+ log('Error: getLog for task "%s" with uuid "%s" - missing credentials', taskName, uuid);
70
+ throw new Error('Missing Hive API credentials or host, get them at https://forgehive.dev');
71
+ }
72
+ try {
73
+ const logUrl = `${this.host}/api/tasks/${taskName}/logs/${uuid}`;
74
+ log('Fetching log for task "%s" with uuid "%s" from %s', taskName, uuid, logUrl);
75
+ const authToken = `${this.apiKey}:${this.apiSecret}`;
76
+ const response = await axios_1.default.get(logUrl, {
77
+ headers: {
78
+ Authorization: `Bearer ${authToken}`,
79
+ 'Content-Type': 'application/json'
80
+ }
81
+ });
82
+ log('Success: Fetched log for task "%s" with uuid "%s"', taskName, uuid);
83
+ return response.data;
84
+ }
85
+ catch (e) {
86
+ const error = e;
87
+ log('Error: Failed to fetch log for task "%s" with uuid "%s": %s', taskName, uuid, error.message);
88
+ return null;
89
+ }
90
+ }
91
+ async setQuality(taskName, uuid, quality) {
92
+ if (!this.isInitialized) {
93
+ log('Error: setQuality for task "%s" with uuid "%s" - missing credentials', taskName, uuid);
94
+ throw new Error('Missing Hive API credentials or host, get them at https://forgehive.dev');
95
+ }
96
+ try {
97
+ const qualityUrl = `${this.host}/api/tasks/${taskName}/logs/${uuid}/set-quality`;
98
+ log('Setting quality for task "%s" with uuid "%s" (score: %d) to %s', taskName, uuid, quality.score, qualityUrl);
99
+ const authToken = `${this.apiKey}:${this.apiSecret}`;
100
+ await axios_1.default.post(qualityUrl, {
101
+ quality
102
+ }, {
103
+ headers: {
104
+ Authorization: `Bearer ${authToken}`,
105
+ 'Content-Type': 'application/json'
106
+ }
107
+ });
108
+ log('Success: Set quality for task "%s" with uuid "%s" (score: %d)', taskName, uuid, quality.score);
109
+ return true;
110
+ }
111
+ catch (e) {
112
+ const error = e;
113
+ log('Error: Failed to set quality for task "%s" with uuid "%s": %s', taskName, uuid, error.message);
114
+ return false;
115
+ }
116
+ }
117
+ }
118
+ exports.HiveLogClient = HiveLogClient;
119
+ const createHiveLogClient = (projectName) => {
120
+ log('Creating HiveLogClient for project "%s"', projectName);
121
+ return new HiveLogClient(projectName);
122
+ };
123
+ exports.createHiveLogClient = createHiveLogClient;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const axios_1 = __importDefault(require("axios"));
7
+ const index_1 = require("../index");
8
+ // Mock axios
9
+ jest.mock('axios');
10
+ const mockedAxios = axios_1.default;
11
+ describe('HiveLogClient getLog', () => {
12
+ const originalEnv = process.env;
13
+ let client;
14
+ beforeEach(() => {
15
+ jest.resetModules();
16
+ process.env = { ...originalEnv };
17
+ // Set up environment variables
18
+ process.env.HIVE_API_KEY = 'test-api-key';
19
+ process.env.HIVE_API_SECRET = 'test-api-secret';
20
+ process.env.HIVE_HOST = 'https://test-host.com';
21
+ // Create client instance
22
+ client = new index_1.HiveLogClient('test-project');
23
+ // Clear all mocks
24
+ jest.clearAllMocks();
25
+ });
26
+ afterAll(() => {
27
+ process.env = originalEnv;
28
+ });
29
+ describe('successful getLog', () => {
30
+ it('should fetch log successfully and return LogApiResponse', async () => {
31
+ const mockLogResponse = {
32
+ uuid: 'test-uuid-123',
33
+ taskName: 'test-task',
34
+ projectName: 'test-project',
35
+ logItem: {
36
+ input: { userId: 123, action: 'login' },
37
+ output: { success: true, sessionId: 'abc123' },
38
+ error: null,
39
+ boundaries: {
40
+ database: [{ input: 'SELECT * FROM users', output: [{ id: 123 }], error: null }]
41
+ }
42
+ },
43
+ replayFrom: 'some-replay-id',
44
+ createdAt: '2023-12-01T10:00:00Z'
45
+ };
46
+ // Mock successful axios response
47
+ mockedAxios.get.mockResolvedValueOnce({ data: mockLogResponse });
48
+ const result = await client.getLog('test-task', 'test-uuid-123');
49
+ expect(result).toEqual(mockLogResponse);
50
+ expect(mockedAxios.get).toHaveBeenCalledTimes(1);
51
+ expect(mockedAxios.get).toHaveBeenCalledWith('https://test-host.com/api/tasks/test-task/logs/test-uuid-123', {
52
+ headers: {
53
+ Authorization: 'Bearer test-api-key:test-api-secret',
54
+ 'Content-Type': 'application/json'
55
+ }
56
+ });
57
+ });
58
+ it('should handle API error response', async () => {
59
+ const mockErrorResponse = {
60
+ error: 'Log not found'
61
+ };
62
+ mockedAxios.get.mockResolvedValueOnce({ data: mockErrorResponse });
63
+ const result = await client.getLog('test-task', 'non-existent-uuid');
64
+ expect(result).toEqual(mockErrorResponse);
65
+ expect((0, index_1.isApiError)(result)).toBe(true);
66
+ });
67
+ it('should handle minimal log response', async () => {
68
+ const mockMinimalResponse = {
69
+ uuid: 'minimal-uuid',
70
+ taskName: 'minimal-task',
71
+ projectName: 'test-project',
72
+ logItem: {
73
+ input: 'simple input'
74
+ },
75
+ createdAt: '2023-12-01T10:00:00Z'
76
+ };
77
+ mockedAxios.get.mockResolvedValueOnce({ data: mockMinimalResponse });
78
+ const result = await client.getLog('minimal-task', 'minimal-uuid');
79
+ expect(result).toEqual(mockMinimalResponse);
80
+ expect((0, index_1.isApiError)(result)).toBe(false);
81
+ });
82
+ });
83
+ describe('failed getLog', () => {
84
+ it('should return null when axios throws an error', async () => {
85
+ // Mock axios to throw an error
86
+ mockedAxios.get.mockRejectedValueOnce(new Error('Network error'));
87
+ const result = await client.getLog('test-task', 'test-uuid');
88
+ expect(result).toBeNull();
89
+ });
90
+ it('should return null when server returns 404', async () => {
91
+ // Mock axios to throw a 404 error
92
+ const notFoundError = new Error('Request failed with status code 404');
93
+ mockedAxios.get.mockRejectedValueOnce(notFoundError);
94
+ const result = await client.getLog('test-task', 'non-existent-uuid');
95
+ expect(result).toBeNull();
96
+ });
97
+ it('should return null when server returns 500', async () => {
98
+ // Mock axios to throw a server error
99
+ const serverError = new Error('Server Error');
100
+ mockedAxios.get.mockRejectedValueOnce(serverError);
101
+ const result = await client.getLog('test-task', 'test-uuid');
102
+ expect(result).toBeNull();
103
+ });
104
+ });
105
+ describe('getLog parameters', () => {
106
+ it('should handle special characters in taskName and uuid', async () => {
107
+ const mockResponse = {
108
+ uuid: 'uuid-with-special-chars-!@#',
109
+ taskName: 'task-with-special-chars-!@#',
110
+ projectName: 'test-project',
111
+ logItem: { input: 'test' },
112
+ createdAt: '2023-12-01T10:00:00Z'
113
+ };
114
+ mockedAxios.get.mockResolvedValueOnce({ data: mockResponse });
115
+ const result = await client.getLog('task-with-special-chars-!@#', 'uuid-with-special-chars-!@#');
116
+ expect(result).toEqual(mockResponse);
117
+ expect(mockedAxios.get).toHaveBeenCalledWith('https://test-host.com/api/tasks/task-with-special-chars-!@#/logs/uuid-with-special-chars-!@#', expect.any(Object));
118
+ });
119
+ });
120
+ });
121
+ describe('isApiError type guard', () => {
122
+ it('should return true for ApiError objects', () => {
123
+ const apiError = { error: 'Something went wrong' };
124
+ expect((0, index_1.isApiError)(apiError)).toBe(true);
125
+ });
126
+ it('should return false for LogApiResponse objects', () => {
127
+ const logResponse = {
128
+ uuid: 'test-uuid',
129
+ taskName: 'test-task',
130
+ projectName: 'test-project',
131
+ logItem: { input: 'test' },
132
+ createdAt: '2023-12-01T10:00:00Z'
133
+ };
134
+ expect((0, index_1.isApiError)(logResponse)).toBe(false);
135
+ });
136
+ it('should return false for null or undefined', () => {
137
+ expect((0, index_1.isApiError)(null)).toBeFalsy();
138
+ expect((0, index_1.isApiError)(undefined)).toBeFalsy();
139
+ });
140
+ it('should return false for objects without error property', () => {
141
+ expect((0, index_1.isApiError)({ success: true })).toBe(false);
142
+ expect((0, index_1.isApiError)({ data: 'some data' })).toBe(false);
143
+ });
144
+ });
@@ -0,0 +1 @@
1
+ export {};