@furystack/utils 8.1.10 → 8.2.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/CHANGELOG.md +56 -0
- package/esm/event-hub.d.ts +21 -0
- package/esm/event-hub.d.ts.map +1 -1
- package/esm/event-hub.js +48 -1
- package/esm/event-hub.js.map +1 -1
- package/esm/event-hub.spec.js +112 -0
- package/esm/event-hub.spec.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/observable-value.d.ts +9 -0
- package/esm/observable-value.d.ts.map +1 -1
- package/esm/observable-value.js +13 -2
- package/esm/observable-value.js.map +1 -1
- package/esm/observable-value.spec.d.ts.map +1 -1
- package/esm/observable-value.spec.js +73 -0
- package/esm/observable-value.spec.js.map +1 -1
- package/esm/semaphore.d.ts +104 -0
- package/esm/semaphore.d.ts.map +1 -0
- package/esm/semaphore.js +185 -0
- package/esm/semaphore.js.map +1 -0
- package/esm/semaphore.spec.d.ts +2 -0
- package/esm/semaphore.spec.d.ts.map +1 -0
- package/esm/semaphore.spec.js +356 -0
- package/esm/semaphore.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/event-hub.spec.ts +153 -0
- package/src/event-hub.ts +57 -1
- package/src/index.ts +1 -0
- package/src/observable-value.spec.ts +102 -0
- package/src/observable-value.ts +18 -2
- package/src/semaphore.spec.ts +467 -0
- package/src/semaphore.ts +237 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semaphore.spec.js","sourceRoot":"","sources":["../src/semaphore.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/event-hub.spec.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import type { ListenerErrorPayload } from './event-hub.js'
|
|
2
3
|
import { EventHub } from './event-hub.js'
|
|
4
|
+
import { sleepAsync } from './sleep-async.js'
|
|
3
5
|
|
|
4
6
|
describe('EventHub', () => {
|
|
5
7
|
it('Should fail on type errors', () => {
|
|
@@ -97,4 +99,155 @@ describe('EventHub', () => {
|
|
|
97
99
|
hub.emit('test', 'test')
|
|
98
100
|
expect(listener).not.toBeCalled()
|
|
99
101
|
})
|
|
102
|
+
|
|
103
|
+
describe('Error resilience', () => {
|
|
104
|
+
it('should catch sync throws from listeners and still notify other listeners', () => {
|
|
105
|
+
const hub = new EventHub<{ test: number }>()
|
|
106
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
107
|
+
|
|
108
|
+
const throwingListener = () => {
|
|
109
|
+
throw new Error('listener error')
|
|
110
|
+
}
|
|
111
|
+
const goodListener = vi.fn()
|
|
112
|
+
|
|
113
|
+
hub.addListener('test', throwingListener)
|
|
114
|
+
hub.addListener('test', goodListener)
|
|
115
|
+
|
|
116
|
+
hub.emit('test', 42)
|
|
117
|
+
|
|
118
|
+
expect(goodListener).toBeCalledWith(42)
|
|
119
|
+
expect(goodListener).toBeCalledTimes(1)
|
|
120
|
+
expect(consoleErrorSpy).toHaveBeenCalled()
|
|
121
|
+
|
|
122
|
+
consoleErrorSpy.mockRestore()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('should catch async rejections from listeners', async () => {
|
|
126
|
+
const hub = new EventHub<{ test: number }>()
|
|
127
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
128
|
+
|
|
129
|
+
const rejectingListener = async () => {
|
|
130
|
+
throw new Error('async listener error')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
hub.addListener('test', rejectingListener)
|
|
134
|
+
hub.emit('test', 42)
|
|
135
|
+
|
|
136
|
+
await sleepAsync(10)
|
|
137
|
+
|
|
138
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Unhandled EventHub listener error', {
|
|
139
|
+
event: 'test',
|
|
140
|
+
error: expect.any(Error) as Error,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
consoleErrorSpy.mockRestore()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('should route sync errors to onListenerError listeners when registered', () => {
|
|
147
|
+
const hub = new EventHub<{ test: number; onListenerError: ListenerErrorPayload }>()
|
|
148
|
+
const errorHandler = vi.fn()
|
|
149
|
+
|
|
150
|
+
hub.addListener('onListenerError', errorHandler)
|
|
151
|
+
hub.addListener('test', () => {
|
|
152
|
+
throw new Error('boom')
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
hub.emit('test', 1)
|
|
156
|
+
|
|
157
|
+
expect(errorHandler).toBeCalledTimes(1)
|
|
158
|
+
expect(errorHandler).toBeCalledWith({
|
|
159
|
+
event: 'test',
|
|
160
|
+
error: expect.any(Error) as Error,
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('should route async rejections to onListenerError listeners when registered', async () => {
|
|
165
|
+
const hub = new EventHub<{ test: number; onListenerError: ListenerErrorPayload }>()
|
|
166
|
+
const errorHandler = vi.fn()
|
|
167
|
+
|
|
168
|
+
hub.addListener('onListenerError', errorHandler)
|
|
169
|
+
hub.addListener('test', async () => {
|
|
170
|
+
throw new Error('async boom')
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
hub.emit('test', 1)
|
|
174
|
+
await sleepAsync(10)
|
|
175
|
+
|
|
176
|
+
expect(errorHandler).toBeCalledTimes(1)
|
|
177
|
+
expect(errorHandler).toBeCalledWith({
|
|
178
|
+
event: 'test',
|
|
179
|
+
error: expect.any(Error) as Error,
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('should fall back to console.error if onListenerError handler returns a rejected promise', async () => {
|
|
184
|
+
const hub = new EventHub<{ test: number; onListenerError: ListenerErrorPayload }>()
|
|
185
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
186
|
+
|
|
187
|
+
hub.addListener('onListenerError', async () => {
|
|
188
|
+
throw new Error('async error handler fails')
|
|
189
|
+
})
|
|
190
|
+
hub.addListener('test', () => {
|
|
191
|
+
throw new Error('original error')
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
hub.emit('test', 1)
|
|
195
|
+
await sleepAsync(10)
|
|
196
|
+
|
|
197
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Error in onListenerError handler', expect.any(Error))
|
|
198
|
+
|
|
199
|
+
consoleErrorSpy.mockRestore()
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('should fall back to console.error if onListenerError handler itself throws', () => {
|
|
203
|
+
const hub = new EventHub<{ test: number; onListenerError: ListenerErrorPayload }>()
|
|
204
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
205
|
+
|
|
206
|
+
hub.addListener('onListenerError', () => {
|
|
207
|
+
throw new Error('error handler also fails')
|
|
208
|
+
})
|
|
209
|
+
hub.addListener('test', () => {
|
|
210
|
+
throw new Error('original error')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
hub.emit('test', 1)
|
|
214
|
+
|
|
215
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Error in onListenerError handler', expect.any(Error))
|
|
216
|
+
|
|
217
|
+
consoleErrorSpy.mockRestore()
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('should go straight to console.error when onListenerError event itself has a failing listener', () => {
|
|
221
|
+
const hub = new EventHub<{ onListenerError: ListenerErrorPayload }>()
|
|
222
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
223
|
+
|
|
224
|
+
hub.addListener('onListenerError', () => {
|
|
225
|
+
throw new Error('meta error')
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
hub.emit('onListenerError', { event: 'test', error: new Error('original') })
|
|
229
|
+
|
|
230
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Error in onListenerError handler', expect.any(Error))
|
|
231
|
+
|
|
232
|
+
consoleErrorSpy.mockRestore()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('should fall back to console.error when no onListenerError listeners are registered', () => {
|
|
236
|
+
const hub = new EventHub<{ test: number }>()
|
|
237
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
238
|
+
|
|
239
|
+
hub.addListener('test', () => {
|
|
240
|
+
throw new Error('no handler')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
hub.emit('test', 1)
|
|
244
|
+
|
|
245
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Unhandled EventHub listener error', {
|
|
246
|
+
event: 'test',
|
|
247
|
+
error: expect.any(Error) as Error,
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
consoleErrorSpy.mockRestore()
|
|
251
|
+
})
|
|
252
|
+
})
|
|
100
253
|
})
|
package/src/event-hub.ts
CHANGED
|
@@ -2,10 +2,25 @@ type ListenerFunction<EventTypeMap extends object, T extends keyof EventTypeMap>
|
|
|
2
2
|
arg: EventTypeMap[T],
|
|
3
3
|
) => void | PromiseLike<void>
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Payload emitted when a listener throws or rejects during {@link EventHub.emit}.
|
|
7
|
+
* Subscribe to the `onListenerError` event to receive these.
|
|
8
|
+
*/
|
|
9
|
+
export type ListenerErrorPayload = {
|
|
10
|
+
/** The event name that was being emitted when the error occurred */
|
|
11
|
+
event: string | number | symbol
|
|
12
|
+
/** The error thrown or rejected by the listener */
|
|
13
|
+
error: unknown
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
/**
|
|
6
17
|
* A typed event emitter that provides type-safe event subscription and emission.
|
|
7
18
|
* Use this to create strongly-typed pub/sub patterns in your application.
|
|
8
19
|
*
|
|
20
|
+
* Listener errors (sync throws and async rejections) are caught automatically.
|
|
21
|
+
* If `onListenerError` listeners are registered, errors are routed there.
|
|
22
|
+
* Otherwise, they are logged via `console.error`.
|
|
23
|
+
*
|
|
9
24
|
* @typeParam EventTypeMap - An object type where keys are event names and values are event payload types
|
|
10
25
|
* @example
|
|
11
26
|
* ```ts
|
|
@@ -13,6 +28,7 @@ type ListenerFunction<EventTypeMap extends object, T extends keyof EventTypeMap>
|
|
|
13
28
|
* userLoggedIn: { userId: string }
|
|
14
29
|
* userLoggedOut: { userId: string }
|
|
15
30
|
* dataUpdated: { items: string[] }
|
|
31
|
+
* onListenerError: ListenerErrorPayload
|
|
16
32
|
* }
|
|
17
33
|
*
|
|
18
34
|
* const hub = new EventHub<MyEvents>()
|
|
@@ -22,6 +38,11 @@ type ListenerFunction<EventTypeMap extends object, T extends keyof EventTypeMap>
|
|
|
22
38
|
* console.log('User logged in:', event.userId)
|
|
23
39
|
* })
|
|
24
40
|
*
|
|
41
|
+
* // Handle listener errors
|
|
42
|
+
* hub.subscribe('onListenerError', ({ event, error }) => {
|
|
43
|
+
* console.error(`Listener for "${String(event)}" failed:`, error)
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
25
46
|
* // Emit events
|
|
26
47
|
* hub.emit('userLoggedIn', { userId: '123' })
|
|
27
48
|
*
|
|
@@ -59,9 +80,44 @@ export class EventHub<EventTypeMap extends object> implements Disposable {
|
|
|
59
80
|
return { [Symbol.dispose]: () => this.removeListener(event, listener) }
|
|
60
81
|
}
|
|
61
82
|
|
|
83
|
+
private handleListenerError(event: keyof EventTypeMap, error: unknown) {
|
|
84
|
+
if (event === 'onListenerError') {
|
|
85
|
+
console.error('Error in onListenerError handler', error)
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
const errorListeners = this.listeners.get('onListenerError' as keyof EventTypeMap)
|
|
89
|
+
if (errorListeners?.size) {
|
|
90
|
+
for (const errorListener of errorListeners) {
|
|
91
|
+
try {
|
|
92
|
+
const result = errorListener({ event, error } as EventTypeMap[keyof EventTypeMap])
|
|
93
|
+
if (result && typeof result.then === 'function') {
|
|
94
|
+
result.then(undefined, (err: unknown) => {
|
|
95
|
+
console.error('Error in onListenerError handler', err)
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
console.error('Error in onListenerError handler', err)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
console.error('Unhandled EventHub listener error', { event, error })
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
62
107
|
public emit<TEvent extends keyof EventTypeMap>(event: TEvent, arg: EventTypeMap[TEvent]) {
|
|
63
108
|
if (this.listeners.has(event)) {
|
|
64
|
-
this.listeners.get(event)!.forEach((listener) =>
|
|
109
|
+
this.listeners.get(event)!.forEach((listener) => {
|
|
110
|
+
try {
|
|
111
|
+
const result = listener(arg)
|
|
112
|
+
if (result && typeof result.then === 'function') {
|
|
113
|
+
result.then(undefined, (error: unknown) => {
|
|
114
|
+
this.handleListenerError(event, error)
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
this.handleListenerError(event, error)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
65
121
|
}
|
|
66
122
|
}
|
|
67
123
|
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './is-async-disposable.js'
|
|
|
5
5
|
export * from './is-disposable.js'
|
|
6
6
|
export * from './observable-value.js'
|
|
7
7
|
export * from './path-helper.js'
|
|
8
|
+
export * from './semaphore.js'
|
|
8
9
|
export * from './sleep-async.js'
|
|
9
10
|
export * from './sort-by.js'
|
|
10
11
|
export * from './tuple.js'
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest'
|
|
2
2
|
import { ObservableValue } from './observable-value.js'
|
|
3
|
+
import { sleepAsync } from './sleep-async.js'
|
|
3
4
|
import { using } from './using.js'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -205,4 +206,105 @@ export const observableTests = describe('Observable', () => {
|
|
|
205
206
|
})
|
|
206
207
|
})
|
|
207
208
|
})
|
|
209
|
+
|
|
210
|
+
describe('Observer error handling', () => {
|
|
211
|
+
it('should catch sync throws from observer callbacks and still notify other observers', () => {
|
|
212
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
213
|
+
|
|
214
|
+
using(new ObservableValue(0), (v) => {
|
|
215
|
+
const goodCallback = vi.fn()
|
|
216
|
+
|
|
217
|
+
v.subscribe(() => {
|
|
218
|
+
throw new Error('observer error')
|
|
219
|
+
})
|
|
220
|
+
v.subscribe(goodCallback)
|
|
221
|
+
|
|
222
|
+
v.setValue(1)
|
|
223
|
+
|
|
224
|
+
expect(goodCallback).toBeCalledWith(1)
|
|
225
|
+
expect(goodCallback).toBeCalledTimes(1)
|
|
226
|
+
expect(consoleErrorSpy).toHaveBeenCalled()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
consoleErrorSpy.mockRestore()
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('should catch async rejections from observer callbacks', async () => {
|
|
233
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
234
|
+
|
|
235
|
+
using(new ObservableValue(0), (v) => {
|
|
236
|
+
v.subscribe(async () => {
|
|
237
|
+
throw new Error('async observer error')
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
v.setValue(1)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
await sleepAsync(10)
|
|
244
|
+
|
|
245
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Error in ObservableValue observer', expect.any(Error))
|
|
246
|
+
|
|
247
|
+
consoleErrorSpy.mockRestore()
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should catch errors thrown by filter functions', () => {
|
|
251
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
252
|
+
|
|
253
|
+
using(new ObservableValue(0), (v) => {
|
|
254
|
+
const goodCallback = vi.fn()
|
|
255
|
+
|
|
256
|
+
v.subscribe(
|
|
257
|
+
() => {
|
|
258
|
+
/* never reached */
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
filter: () => {
|
|
262
|
+
throw new Error('filter error')
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
)
|
|
266
|
+
v.subscribe(goodCallback)
|
|
267
|
+
|
|
268
|
+
v.setValue(1)
|
|
269
|
+
|
|
270
|
+
expect(goodCallback).toBeCalledWith(1)
|
|
271
|
+
expect(consoleErrorSpy).toHaveBeenCalled()
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
consoleErrorSpy.mockRestore()
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('should use custom onError callback when provided', () => {
|
|
278
|
+
const onError = vi.fn()
|
|
279
|
+
|
|
280
|
+
using(new ObservableValue(0, { onError }), (v) => {
|
|
281
|
+
v.subscribe(() => {
|
|
282
|
+
throw new Error('custom error')
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
v.setValue(1)
|
|
286
|
+
|
|
287
|
+
expect(onError).toBeCalledTimes(1)
|
|
288
|
+
expect(onError).toBeCalledWith({
|
|
289
|
+
error: expect.any(Error) as Error,
|
|
290
|
+
observer: expect.objectContaining({ callback: expect.any(Function) as () => void }) as object,
|
|
291
|
+
})
|
|
292
|
+
})
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('should update the value even when observers throw', () => {
|
|
296
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
297
|
+
|
|
298
|
+
using(new ObservableValue(0), (v) => {
|
|
299
|
+
v.subscribe(() => {
|
|
300
|
+
throw new Error('error')
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
v.setValue(42)
|
|
304
|
+
expect(v.getValue()).toBe(42)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
consoleErrorSpy.mockRestore()
|
|
308
|
+
})
|
|
309
|
+
})
|
|
208
310
|
})
|
package/src/observable-value.ts
CHANGED
|
@@ -23,6 +23,12 @@ export type ObservableValueOptions<T> = {
|
|
|
23
23
|
* @returns whether the value should be updated and the observers should be notified
|
|
24
24
|
*/
|
|
25
25
|
compare: (lastValue: T, nextValue: T) => boolean
|
|
26
|
+
/**
|
|
27
|
+
* Called when an observer callback or filter throws (sync) or rejects (async).
|
|
28
|
+
* All remaining observers are still notified even when one fails.
|
|
29
|
+
* Defaults to logging the error via `console.error`.
|
|
30
|
+
*/
|
|
31
|
+
onError: (options: { error: unknown; observer: ValueObserver<T> }) => void
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
const defaultComparer = <T>(a: T, b: T) => a !== b
|
|
@@ -112,8 +118,17 @@ export class ObservableValue<T> implements Disposable {
|
|
|
112
118
|
if (this.options.compare(this.currentValue, newValue)) {
|
|
113
119
|
this.currentValue = newValue
|
|
114
120
|
this.observers.forEach((observer) => {
|
|
115
|
-
|
|
116
|
-
observer.
|
|
121
|
+
try {
|
|
122
|
+
if (observer.options?.filter?.(this.currentValue, newValue) !== false) {
|
|
123
|
+
const result = observer.callback(newValue)
|
|
124
|
+
if (result && typeof result.then === 'function') {
|
|
125
|
+
result.then(undefined, (error: unknown) => {
|
|
126
|
+
this.options.onError({ error, observer })
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.options.onError({ error, observer })
|
|
117
132
|
}
|
|
118
133
|
})
|
|
119
134
|
}
|
|
@@ -136,6 +151,7 @@ export class ObservableValue<T> implements Disposable {
|
|
|
136
151
|
constructor(initialValue: T, options?: Partial<ObservableValueOptions<T>>) {
|
|
137
152
|
this.options = {
|
|
138
153
|
compare: defaultComparer,
|
|
154
|
+
onError: ({ error }) => console.error('Error in ObservableValue observer', error),
|
|
139
155
|
...options,
|
|
140
156
|
}
|
|
141
157
|
this.currentValue = initialValue
|