@forgehive/hive-sdk 0.1.6 → 0.3.0
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 +318 -528
- package/dist/index.d.ts +0 -2
- package/dist/index.js +10 -66
- package/dist/test/metadata.test.js +123 -171
- package/dist/test/sendLog.test.js +199 -117
- package/package.json +3 -3
- package/src/index.ts +11 -78
- package/src/test/metadata.test.ts +143 -218
- package/src/test/sendLog.test.ts +237 -145
- package/dist/test/sendLogByUuid.test.d.ts +0 -1
- package/dist/test/sendLogByUuid.test.js +0 -222
- package/src/test/sendLogByUuid.test.ts +0 -272
package/src/test/sendLog.test.ts
CHANGED
|
@@ -1,21 +1,60 @@
|
|
|
1
1
|
import axios from 'axios'
|
|
2
|
+
import fs from 'fs'
|
|
2
3
|
import { HiveLogClient } from '../index'
|
|
3
4
|
|
|
4
|
-
// Mock axios
|
|
5
|
+
// Mock axios and fs
|
|
5
6
|
jest.mock('axios')
|
|
7
|
+
jest.mock('fs')
|
|
6
8
|
const mockedAxios = axios as jest.Mocked<typeof axios>
|
|
9
|
+
const mockedFs = fs as jest.Mocked<typeof fs>
|
|
7
10
|
|
|
8
11
|
describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
9
12
|
let client: HiveLogClient
|
|
10
13
|
|
|
11
14
|
const testConfig = {
|
|
12
15
|
projectName: 'test-project',
|
|
16
|
+
projectUuid: '550e8400-e29b-41d4-a716-446655440000',
|
|
13
17
|
apiKey: 'test-api-key',
|
|
14
18
|
apiSecret: 'test-api-secret',
|
|
15
|
-
host: 'https://test-host.com'
|
|
19
|
+
host: 'https://test-host.com',
|
|
20
|
+
forgeConfigPath: './forge.json'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const mockForgeConfig = {
|
|
24
|
+
project: {
|
|
25
|
+
name: 'test-project',
|
|
26
|
+
uuid: '550e8400-e29b-41d4-a716-446655440000'
|
|
27
|
+
},
|
|
28
|
+
tasks: {
|
|
29
|
+
'test-task': {
|
|
30
|
+
path: 'src/tasks/test.ts',
|
|
31
|
+
handler: 'testTask',
|
|
32
|
+
uuid: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
33
|
+
},
|
|
34
|
+
'complex-task': {
|
|
35
|
+
path: 'src/tasks/complex.ts',
|
|
36
|
+
handler: 'complexTask',
|
|
37
|
+
uuid: 'a45aafe3-8b01-4b58-b15d-9a96274858ee'
|
|
38
|
+
},
|
|
39
|
+
'error-task': {
|
|
40
|
+
path: 'src/tasks/error.ts',
|
|
41
|
+
handler: 'errorTask',
|
|
42
|
+
uuid: '8879271f-7e84-4748-bd11-4d81acf29fb6'
|
|
43
|
+
},
|
|
44
|
+
'metadata-task': {
|
|
45
|
+
path: 'src/tasks/metadata.ts',
|
|
46
|
+
handler: 'metadataTask',
|
|
47
|
+
uuid: 'fad2f735-ca09-4b8b-9c44-597de3641d28'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
16
50
|
}
|
|
17
51
|
|
|
18
52
|
beforeEach(() => {
|
|
53
|
+
// Mock fs.existsSync to return true
|
|
54
|
+
mockedFs.existsSync.mockReturnValue(true)
|
|
55
|
+
// Mock fs.readFileSync to return forge.json content
|
|
56
|
+
mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockForgeConfig))
|
|
57
|
+
|
|
19
58
|
// Create client instance with config
|
|
20
59
|
client = new HiveLogClient(testConfig)
|
|
21
60
|
|
|
@@ -41,27 +80,24 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
41
80
|
|
|
42
81
|
expect(result).toBe('success')
|
|
43
82
|
expect(mockedAxios.post).toHaveBeenCalledTimes(1)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
)
|
|
83
|
+
|
|
84
|
+
// Verify it uses the UUID endpoint
|
|
85
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
86
|
+
expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest')
|
|
87
|
+
|
|
88
|
+
// Verify request body structure
|
|
89
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
90
|
+
expect(requestBody.projectUuid).toBe(testConfig.projectUuid)
|
|
91
|
+
expect(requestBody.taskUuid).toBe('f47ac10b-58cc-4372-a567-0e02b2c3d479')
|
|
92
|
+
|
|
93
|
+
// Verify logItem has UUID generated
|
|
94
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
95
|
+
expect(logItem.uuid).toBeDefined()
|
|
96
|
+
expect(typeof logItem.uuid).toBe('string')
|
|
97
|
+
expect(logItem.input).toEqual({ value: 'test-input' })
|
|
98
|
+
expect(logItem.output).toEqual({ result: 'test-output' })
|
|
99
|
+
expect(logItem.taskName).toBe('test-task')
|
|
100
|
+
expect(logItem.type).toBe('success')
|
|
65
101
|
})
|
|
66
102
|
|
|
67
103
|
it('should handle ExecutionRecord with complex boundaries', async () => {
|
|
@@ -90,38 +126,18 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
90
126
|
const result = await client.sendLog(executionRecord)
|
|
91
127
|
|
|
92
128
|
expect(result).toBe('success')
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
input: ['SELECT * FROM users'],
|
|
106
|
-
output: [{ id: 123 }],
|
|
107
|
-
timing: { startTime: 1000, endTime: 1100, duration: 100 }
|
|
108
|
-
}],
|
|
109
|
-
api: [{
|
|
110
|
-
input: [{ endpoint: '/auth' }],
|
|
111
|
-
output: { token: 'jwt123' },
|
|
112
|
-
timing: { startTime: 1200, endTime: 1250, duration: 50 }
|
|
113
|
-
}]
|
|
114
|
-
},
|
|
115
|
-
metadata: { environment: 'test' }
|
|
116
|
-
})
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
headers: {
|
|
120
|
-
Authorization: 'Bearer test-api-key:test-api-secret',
|
|
121
|
-
'Content-Type': 'application/json'
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
)
|
|
129
|
+
|
|
130
|
+
// Verify request structure
|
|
131
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
132
|
+
expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest')
|
|
133
|
+
|
|
134
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
135
|
+
expect(requestBody.projectUuid).toBe(testConfig.projectUuid)
|
|
136
|
+
expect(requestBody.taskUuid).toBe('a45aafe3-8b01-4b58-b15d-9a96274858ee')
|
|
137
|
+
|
|
138
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
139
|
+
expect(logItem.uuid).toBeDefined()
|
|
140
|
+
expect(logItem.boundaries).toEqual(executionRecord.boundaries)
|
|
125
141
|
})
|
|
126
142
|
|
|
127
143
|
it('should handle ExecutionRecord with error', async () => {
|
|
@@ -140,32 +156,25 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
140
156
|
const result = await client.sendLog(executionRecord)
|
|
141
157
|
|
|
142
158
|
expect(result).toBe('success')
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
error: 'Task execution failed',
|
|
152
|
-
taskName: 'error-task',
|
|
153
|
-
type: 'error',
|
|
154
|
-
boundaries: {},
|
|
155
|
-
metadata: {}
|
|
156
|
-
})
|
|
157
|
-
},
|
|
158
|
-
expect.any(Object)
|
|
159
|
-
)
|
|
159
|
+
|
|
160
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
161
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
162
|
+
expect(requestBody.taskUuid).toBe('8879271f-7e84-4748-bd11-4d81acf29fb6')
|
|
163
|
+
|
|
164
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
165
|
+
expect(logItem.error).toBe('Task execution failed')
|
|
166
|
+
expect(logItem.type).toBe('error')
|
|
160
167
|
})
|
|
161
168
|
|
|
162
|
-
it('should
|
|
169
|
+
it('should preserve existing UUID when execution record already has one', async () => {
|
|
163
170
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
|
|
164
171
|
|
|
172
|
+
const existingUuid = '01234567-89ab-7def-8123-456789abcdef'
|
|
165
173
|
const executionRecord = {
|
|
174
|
+
uuid: existingUuid,
|
|
166
175
|
input: { value: 'test-input' },
|
|
167
176
|
output: { result: 'test-output' },
|
|
168
|
-
|
|
177
|
+
taskName: 'test-task',
|
|
169
178
|
type: 'success' as const,
|
|
170
179
|
boundaries: {},
|
|
171
180
|
metadata: {}
|
|
@@ -174,22 +183,38 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
174
183
|
const result = await client.sendLog(executionRecord)
|
|
175
184
|
|
|
176
185
|
expect(result).toBe('success')
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
|
|
186
|
+
|
|
187
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
188
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
189
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
190
|
+
|
|
191
|
+
expect(logItem.uuid).toBe(existingUuid)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('should generate UUID v7 when execution record has no UUID', async () => {
|
|
195
|
+
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } })
|
|
196
|
+
|
|
197
|
+
const executionRecord = {
|
|
198
|
+
input: { value: 'test-input' },
|
|
199
|
+
output: { result: 'test-output' },
|
|
200
|
+
taskName: 'test-task',
|
|
201
|
+
type: 'success' as const,
|
|
202
|
+
boundaries: {},
|
|
203
|
+
metadata: {}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const result = await client.sendLog(executionRecord)
|
|
207
|
+
|
|
208
|
+
expect(result).toBe('success')
|
|
209
|
+
|
|
210
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
211
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
212
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
213
|
+
|
|
214
|
+
expect(logItem.uuid).toBeDefined()
|
|
215
|
+
expect(typeof logItem.uuid).toBe('string')
|
|
216
|
+
// UUID v7 pattern
|
|
217
|
+
expect(logItem.uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)
|
|
193
218
|
})
|
|
194
219
|
})
|
|
195
220
|
|
|
@@ -217,26 +242,16 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
217
242
|
const result = await client.sendLog(executionRecord, sendLogMetadata)
|
|
218
243
|
|
|
219
244
|
expect(result).toBe('success')
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
boundaries: {},
|
|
231
|
-
metadata: {
|
|
232
|
-
recordMeta: 'from-record',
|
|
233
|
-
sharedKey: 'sendlog-value', // sendLog metadata takes priority
|
|
234
|
-
sendLogMeta: 'from-sendlog'
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
},
|
|
238
|
-
expect.any(Object)
|
|
239
|
-
)
|
|
245
|
+
|
|
246
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
247
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
248
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
249
|
+
|
|
250
|
+
expect(logItem.metadata).toEqual({
|
|
251
|
+
recordMeta: 'from-record',
|
|
252
|
+
sharedKey: 'sendlog-value', // sendLog metadata takes priority
|
|
253
|
+
sendLogMeta: 'from-sendlog'
|
|
254
|
+
})
|
|
240
255
|
})
|
|
241
256
|
})
|
|
242
257
|
|
|
@@ -275,6 +290,44 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
275
290
|
|
|
276
291
|
expect(result).toBe('error')
|
|
277
292
|
})
|
|
293
|
+
|
|
294
|
+
it('should return error when task is not found in forge.json', async () => {
|
|
295
|
+
const executionRecord = {
|
|
296
|
+
input: { value: 'test-input' },
|
|
297
|
+
taskName: 'nonexistent-task',
|
|
298
|
+
type: 'success' as const,
|
|
299
|
+
boundaries: {},
|
|
300
|
+
metadata: {}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const result = await client.sendLog(executionRecord)
|
|
304
|
+
|
|
305
|
+
expect(result).toBe('error')
|
|
306
|
+
expect(mockedAxios.post).not.toHaveBeenCalled()
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('should return error when projectUuid is not set', async () => {
|
|
310
|
+
// Create client without projectUuid
|
|
311
|
+
const clientWithoutUuid = new HiveLogClient({
|
|
312
|
+
projectName: 'test-project',
|
|
313
|
+
apiKey: 'test-key',
|
|
314
|
+
apiSecret: 'test-secret',
|
|
315
|
+
host: 'https://test-host.com'
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
const executionRecord = {
|
|
319
|
+
input: { value: 'test-input' },
|
|
320
|
+
taskName: 'test-task',
|
|
321
|
+
type: 'success' as const,
|
|
322
|
+
boundaries: {},
|
|
323
|
+
metadata: {}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const result = await clientWithoutUuid.sendLog(executionRecord)
|
|
327
|
+
|
|
328
|
+
expect(result).toBe('error')
|
|
329
|
+
expect(mockedAxios.post).not.toHaveBeenCalled()
|
|
330
|
+
})
|
|
278
331
|
})
|
|
279
332
|
|
|
280
333
|
describe('sendLog in silent mode', () => {
|
|
@@ -298,6 +351,50 @@ describe('HiveLogClient sendLog with ExecutionRecord', () => {
|
|
|
298
351
|
expect(mockedAxios.post).not.toHaveBeenCalled()
|
|
299
352
|
})
|
|
300
353
|
})
|
|
354
|
+
|
|
355
|
+
describe('sendLog with unknown task name', () => {
|
|
356
|
+
it('should return error when taskName is missing and defaults to unknown-task', async () => {
|
|
357
|
+
const executionRecord = {
|
|
358
|
+
input: { value: 'test-input' },
|
|
359
|
+
output: { result: 'test-output' },
|
|
360
|
+
// taskName is missing - will default to 'unknown-task'
|
|
361
|
+
type: 'success' as const,
|
|
362
|
+
boundaries: {},
|
|
363
|
+
metadata: {}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const result = await client.sendLog(executionRecord)
|
|
367
|
+
|
|
368
|
+
// Should return error because 'unknown-task' is not in forge.json
|
|
369
|
+
expect(result).toBe('error')
|
|
370
|
+
expect(mockedAxios.post).not.toHaveBeenCalled()
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
describe('sendLog response handling', () => {
|
|
375
|
+
it('should return response data when API returns object with uuid', async () => {
|
|
376
|
+
const responseData = {
|
|
377
|
+
uuid: 'log-uuid-123',
|
|
378
|
+
taskName: 'test-task',
|
|
379
|
+
projectName: 'test-project',
|
|
380
|
+
logItem: {},
|
|
381
|
+
createdAt: '2024-01-01T00:00:00Z'
|
|
382
|
+
}
|
|
383
|
+
mockedAxios.post.mockResolvedValueOnce({ data: responseData })
|
|
384
|
+
|
|
385
|
+
const executionRecord = {
|
|
386
|
+
input: { value: 'test' },
|
|
387
|
+
taskName: 'test-task',
|
|
388
|
+
type: 'success' as const,
|
|
389
|
+
boundaries: {},
|
|
390
|
+
metadata: {}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const result = await client.sendLog(executionRecord)
|
|
394
|
+
|
|
395
|
+
expect(result).toEqual(responseData)
|
|
396
|
+
})
|
|
397
|
+
})
|
|
301
398
|
})
|
|
302
399
|
|
|
303
400
|
|
|
@@ -306,12 +403,32 @@ describe('HiveLogClient getListener', () => {
|
|
|
306
403
|
|
|
307
404
|
const testConfig = {
|
|
308
405
|
projectName: 'test-project',
|
|
406
|
+
projectUuid: '550e8400-e29b-41d4-a716-446655440000',
|
|
309
407
|
apiKey: 'test-api-key',
|
|
310
408
|
apiSecret: 'test-api-secret',
|
|
311
|
-
host: 'https://test-host.com'
|
|
409
|
+
host: 'https://test-host.com',
|
|
410
|
+
forgeConfigPath: './forge.json'
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const mockForgeConfig = {
|
|
414
|
+
project: {
|
|
415
|
+
name: 'test-project',
|
|
416
|
+
uuid: '550e8400-e29b-41d4-a716-446655440000'
|
|
417
|
+
},
|
|
418
|
+
tasks: {
|
|
419
|
+
'test-task': {
|
|
420
|
+
path: 'src/tasks/test.ts',
|
|
421
|
+
handler: 'testTask',
|
|
422
|
+
uuid: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
423
|
+
}
|
|
424
|
+
}
|
|
312
425
|
}
|
|
313
426
|
|
|
314
427
|
beforeEach(() => {
|
|
428
|
+
// Mock fs
|
|
429
|
+
mockedFs.existsSync.mockReturnValue(true)
|
|
430
|
+
mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockForgeConfig))
|
|
431
|
+
|
|
315
432
|
client = new HiveLogClient(testConfig)
|
|
316
433
|
jest.clearAllMocks()
|
|
317
434
|
})
|
|
@@ -336,22 +453,10 @@ describe('HiveLogClient getListener', () => {
|
|
|
336
453
|
await listener(executionRecord)
|
|
337
454
|
|
|
338
455
|
expect(mockedAxios.post).toHaveBeenCalledTimes(1)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
taskName: 'test-task',
|
|
344
|
-
logItem: JSON.stringify({
|
|
345
|
-
input: { value: 'test-input' },
|
|
346
|
-
output: { result: 'test-output' },
|
|
347
|
-
taskName: 'test-task',
|
|
348
|
-
type: 'success',
|
|
349
|
-
boundaries: {},
|
|
350
|
-
metadata: {}
|
|
351
|
-
})
|
|
352
|
-
},
|
|
353
|
-
expect.any(Object)
|
|
354
|
-
)
|
|
456
|
+
|
|
457
|
+
// Verify it uses the UUID endpoint
|
|
458
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
459
|
+
expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest')
|
|
355
460
|
})
|
|
356
461
|
|
|
357
462
|
it('should return a function that calls sendLog with provided metadata', async () => {
|
|
@@ -370,24 +475,11 @@ describe('HiveLogClient getListener', () => {
|
|
|
370
475
|
|
|
371
476
|
await listener(executionRecord)
|
|
372
477
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
logItem: JSON.stringify({
|
|
379
|
-
input: { value: 'test-input' },
|
|
380
|
-
output: { result: 'test-output' },
|
|
381
|
-
taskName: 'test-task',
|
|
382
|
-
type: 'success',
|
|
383
|
-
boundaries: {},
|
|
384
|
-
metadata: {
|
|
385
|
-
recordMeta: 'from-record'
|
|
386
|
-
}
|
|
387
|
-
})
|
|
388
|
-
},
|
|
389
|
-
expect.any(Object)
|
|
390
|
-
)
|
|
478
|
+
const callArgs = mockedAxios.post.mock.calls[0]
|
|
479
|
+
const requestBody = callArgs[1] as { projectUuid: string; taskUuid: string; logItem: string }
|
|
480
|
+
const logItem = JSON.parse(requestBody.logItem)
|
|
481
|
+
|
|
482
|
+
expect(logItem.metadata).toEqual({ recordMeta: 'from-record' })
|
|
391
483
|
})
|
|
392
484
|
|
|
393
485
|
it('should handle listener errors gracefully', async () => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|