event-emission 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,1126 @@
1
+ // @bun @bun-cjs
2
+ (function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
7
+ var __toCommonJS = (from) => {
8
+ var entry = __moduleCache.get(from), desc;
9
+ if (entry)
10
+ return entry;
11
+ entry = __defProp({}, "__esModule", { value: true });
12
+ if (from && typeof from === "object" || typeof from === "function")
13
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ }));
17
+ __moduleCache.set(from, entry);
18
+ return entry;
19
+ };
20
+ var __export = (target, all) => {
21
+ for (var name in all)
22
+ __defProp(target, name, {
23
+ get: all[name],
24
+ enumerable: true,
25
+ configurable: true,
26
+ set: (newValue) => all[name] = () => newValue
27
+ });
28
+ };
29
+
30
+ // src/index.ts
31
+ var exports_src = {};
32
+ __export(exports_src, {
33
+ setupEventForwarding: () => setupEventForwarding,
34
+ pipe: () => pipe,
35
+ isObserved: () => isObserved,
36
+ getOriginal: () => getOriginal,
37
+ fromEventTarget: () => fromEventTarget,
38
+ forwardToEventTarget: () => forwardToEventTarget,
39
+ createEventTarget: () => createEventTarget,
40
+ SymbolObservable: () => SymbolObservable,
41
+ PROXY_MARKER: () => PROXY_MARKER,
42
+ ORIGINAL_TARGET: () => ORIGINAL_TARGET,
43
+ Eventful: () => Eventful,
44
+ BufferOverflowError: () => BufferOverflowError
45
+ });
46
+ module.exports = __toCommonJS(exports_src);
47
+
48
+ // src/symbols.ts
49
+ var SymbolObservable = typeof Symbol === "function" && Symbol.observable || Symbol.for("@@observable");
50
+ if (typeof Symbol === "function") {
51
+ Symbol.observable = SymbolObservable;
52
+ }
53
+ // src/errors.ts
54
+ class BufferOverflowError extends Error {
55
+ constructor(eventType, bufferSize) {
56
+ super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
57
+ this.name = "BufferOverflowError";
58
+ }
59
+ }
60
+ // src/observe.ts
61
+ var PROXY_MARKER = Symbol.for("@lasercat/eventful/proxy");
62
+ var ORIGINAL_TARGET = Symbol.for("@lasercat/eventful/original");
63
+ var ARRAY_MUTATORS = new Set([
64
+ "push",
65
+ "pop",
66
+ "shift",
67
+ "unshift",
68
+ "splice",
69
+ "sort",
70
+ "reverse",
71
+ "fill",
72
+ "copyWithin"
73
+ ]);
74
+ function isProxyable(value) {
75
+ return value !== null && typeof value === "object" && !isProxied(value) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof Map) && !(value instanceof Set) && !(value instanceof WeakMap) && !(value instanceof WeakSet) && !(value instanceof Promise) && !(value instanceof Error) && !(value instanceof ArrayBuffer) && !ArrayBuffer.isView(value);
76
+ }
77
+ function isProxied(value) {
78
+ return typeof value === "object" && value !== null && value[PROXY_MARKER] === true;
79
+ }
80
+ function isArrayMutator(prop) {
81
+ return typeof prop === "string" && ARRAY_MUTATORS.has(prop);
82
+ }
83
+ function cloneAlongPath(obj, path) {
84
+ if (obj === null || typeof obj !== "object") {
85
+ return obj;
86
+ }
87
+ if (!path) {
88
+ return Array.isArray(obj) ? [...obj] : { ...obj };
89
+ }
90
+ const parts = path.split(".");
91
+ if (Array.isArray(obj)) {
92
+ return [...obj];
93
+ }
94
+ const result = { ...obj };
95
+ let current = result;
96
+ for (let i = 0;i < parts.length; i++) {
97
+ const key = parts[i];
98
+ const value = current[key];
99
+ if (value !== null && typeof value === "object") {
100
+ current[key] = Array.isArray(value) ? [...value] : { ...value };
101
+ if (i < parts.length - 1) {
102
+ current = current[key];
103
+ }
104
+ } else {
105
+ break;
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ function cloneForComparison(obj, strategy, changedPath) {
111
+ if (obj === null || typeof obj !== "object")
112
+ return obj;
113
+ switch (strategy) {
114
+ case "shallow":
115
+ return Array.isArray(obj) ? [...obj] : { ...obj };
116
+ case "deep":
117
+ return structuredClone(obj);
118
+ case "path":
119
+ return cloneAlongPath(obj, changedPath);
120
+ default:
121
+ return obj;
122
+ }
123
+ }
124
+ function computeArrayDiff(method, before, _after, args) {
125
+ switch (method) {
126
+ case "push":
127
+ return { added: args };
128
+ case "pop":
129
+ return { removed: before.length > 0 ? [before[before.length - 1]] : [] };
130
+ case "shift":
131
+ return { removed: before.length > 0 ? [before[0]] : [] };
132
+ case "unshift":
133
+ return { added: args };
134
+ case "splice": {
135
+ const [start, deleteCount, ...items] = args;
136
+ const actualStart = start < 0 ? Math.max(before.length + start, 0) : Math.min(start, before.length);
137
+ const actualDeleteCount = Math.min(deleteCount ?? before.length - actualStart, before.length - actualStart);
138
+ return {
139
+ removed: before.slice(actualStart, actualStart + actualDeleteCount),
140
+ added: items
141
+ };
142
+ }
143
+ case "sort":
144
+ case "reverse":
145
+ case "fill":
146
+ case "copyWithin":
147
+ return {};
148
+ default:
149
+ return {};
150
+ }
151
+ }
152
+ var proxyRegistry = new WeakMap;
153
+ function getContextRegistry(target) {
154
+ let contextMap = proxyRegistry.get(target);
155
+ if (!contextMap) {
156
+ contextMap = new WeakMap;
157
+ proxyRegistry.set(target, contextMap);
158
+ }
159
+ return contextMap;
160
+ }
161
+ function createArrayMethodInterceptor(array, method, path, context) {
162
+ const original = array[method];
163
+ return function(...args) {
164
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path);
165
+ const previousItems = [...array];
166
+ const result = original.apply(this, args);
167
+ const { added, removed } = computeArrayDiff(method, previousItems, array, args);
168
+ const methodEventPath = path ? `update:${path}.${method}` : `update:${method}`;
169
+ const arrayEventPath = path ? `update:${path}` : "update:";
170
+ context.eventTarget.dispatchEvent({
171
+ type: methodEventPath,
172
+ detail: {
173
+ method,
174
+ args,
175
+ result,
176
+ added,
177
+ removed,
178
+ current: context.originalRoot,
179
+ previous: previousState
180
+ }
181
+ });
182
+ if (path) {
183
+ context.eventTarget.dispatchEvent({
184
+ type: arrayEventPath,
185
+ detail: {
186
+ value: array,
187
+ current: context.originalRoot,
188
+ previous: previousState
189
+ }
190
+ });
191
+ }
192
+ context.eventTarget.dispatchEvent({
193
+ type: "update",
194
+ detail: {
195
+ current: context.originalRoot,
196
+ previous: previousState
197
+ }
198
+ });
199
+ return result;
200
+ };
201
+ }
202
+ function createObservableProxyInternal(target, path, context) {
203
+ const contextRegistry = getContextRegistry(target);
204
+ const existing = contextRegistry.get(context);
205
+ if (existing) {
206
+ return existing.proxy;
207
+ }
208
+ const proxy = new Proxy(target, {
209
+ get(obj, prop, receiver) {
210
+ if (prop === PROXY_MARKER)
211
+ return true;
212
+ if (prop === ORIGINAL_TARGET)
213
+ return obj;
214
+ if (typeof prop === "symbol") {
215
+ return Reflect.get(obj, prop, receiver);
216
+ }
217
+ const value = Reflect.get(obj, prop, receiver);
218
+ if (Array.isArray(obj) && isArrayMutator(prop)) {
219
+ return createArrayMethodInterceptor(obj, prop, path, context);
220
+ }
221
+ if (context.options.deep && isProxyable(value)) {
222
+ const nestedPath = path ? `${path}.${prop}` : prop;
223
+ return createObservableProxyInternal(value, nestedPath, context);
224
+ }
225
+ return value;
226
+ },
227
+ set(obj, prop, value, receiver) {
228
+ if (typeof prop === "symbol") {
229
+ return Reflect.set(obj, prop, value, receiver);
230
+ }
231
+ const oldValue = Reflect.get(obj, prop, receiver);
232
+ if (Object.is(oldValue, value)) {
233
+ return true;
234
+ }
235
+ const propPath = path ? `${path}.${prop}` : prop;
236
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
237
+ const success = Reflect.set(obj, prop, value, receiver);
238
+ if (success) {
239
+ context.eventTarget.dispatchEvent({
240
+ type: `update:${propPath}`,
241
+ detail: {
242
+ value,
243
+ current: context.originalRoot,
244
+ previous: previousState
245
+ }
246
+ });
247
+ context.eventTarget.dispatchEvent({
248
+ type: "update",
249
+ detail: {
250
+ current: context.originalRoot,
251
+ previous: previousState
252
+ }
253
+ });
254
+ }
255
+ return success;
256
+ },
257
+ deleteProperty(obj, prop) {
258
+ if (typeof prop === "symbol") {
259
+ return Reflect.deleteProperty(obj, prop);
260
+ }
261
+ const propPath = path ? `${path}.${String(prop)}` : String(prop);
262
+ const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath);
263
+ const success = Reflect.deleteProperty(obj, prop);
264
+ if (success) {
265
+ context.eventTarget.dispatchEvent({
266
+ type: `update:${propPath}`,
267
+ detail: {
268
+ value: undefined,
269
+ current: context.originalRoot,
270
+ previous: previousState
271
+ }
272
+ });
273
+ context.eventTarget.dispatchEvent({
274
+ type: "update",
275
+ detail: {
276
+ current: context.originalRoot,
277
+ previous: previousState
278
+ }
279
+ });
280
+ }
281
+ return success;
282
+ }
283
+ });
284
+ contextRegistry.set(context, {
285
+ proxy,
286
+ path
287
+ });
288
+ return proxy;
289
+ }
290
+ function isEventTarget(obj) {
291
+ return typeof obj === "object" && obj !== null && typeof obj.addEventListener === "function" && typeof obj.removeEventListener === "function" && typeof obj.dispatchEvent === "function";
292
+ }
293
+ function setupEventForwarding(source, target) {
294
+ const handlers = new Map;
295
+ const forwardHandler = (type) => (event) => {
296
+ const detail = event.detail ?? event;
297
+ target.dispatchEvent({
298
+ type,
299
+ detail
300
+ });
301
+ };
302
+ const originalAddEventListener = target.addEventListener.bind(target);
303
+ const wrappedAddEventListener = (type, listener, options) => {
304
+ if (!handlers.has(type) && type !== "update" && !type.startsWith("update:")) {
305
+ const handler = forwardHandler(type);
306
+ handlers.set(type, handler);
307
+ source.addEventListener(type, handler);
308
+ }
309
+ return originalAddEventListener(type, listener, options);
310
+ };
311
+ target.addEventListener = wrappedAddEventListener;
312
+ return () => {
313
+ target.addEventListener = originalAddEventListener;
314
+ for (const [type, handler] of handlers) {
315
+ source.removeEventListener(type, handler);
316
+ }
317
+ handlers.clear();
318
+ };
319
+ }
320
+ function isObserved(obj) {
321
+ return isProxied(obj);
322
+ }
323
+ function getOriginal(proxy) {
324
+ if (!isProxied(proxy)) {
325
+ return proxy;
326
+ }
327
+ return proxy[ORIGINAL_TARGET] ?? proxy;
328
+ }
329
+ function createObservableProxy(target, eventTarget, options) {
330
+ const resolvedOptions = {
331
+ deep: options?.deep ?? true,
332
+ cloneStrategy: options?.cloneStrategy ?? "path"
333
+ };
334
+ const context = {
335
+ eventTarget,
336
+ originalRoot: target,
337
+ options: resolvedOptions
338
+ };
339
+ const proxy = createObservableProxyInternal(target, "", context);
340
+ if (isEventTarget(target)) {
341
+ setupEventForwarding(target, eventTarget);
342
+ }
343
+ return proxy;
344
+ }
345
+
346
+ // src/factory.ts
347
+ function matchesWildcard(eventType, pattern) {
348
+ if (pattern === "*")
349
+ return true;
350
+ if (pattern.endsWith(":*")) {
351
+ const namespace = pattern.slice(0, -2);
352
+ return eventType.startsWith(namespace + ":");
353
+ }
354
+ return false;
355
+ }
356
+ function createEventTarget(targetOrOpts, opts) {
357
+ if (opts?.observe === true && targetOrOpts && typeof targetOrOpts === "object") {
358
+ const target = targetOrOpts;
359
+ const eventTarget = createEventTargetInternal({
360
+ onListenerError: opts.onListenerError
361
+ });
362
+ const proxy = createObservableProxy(target, eventTarget, {
363
+ deep: opts.deep,
364
+ cloneStrategy: opts.cloneStrategy
365
+ });
366
+ const methodNames = [
367
+ "addEventListener",
368
+ "removeEventListener",
369
+ "dispatchEvent",
370
+ "clear",
371
+ "once",
372
+ "removeAllListeners",
373
+ "pipe",
374
+ "addWildcardListener",
375
+ "removeWildcardListener",
376
+ "complete",
377
+ "subscribe",
378
+ "toObservable",
379
+ "events"
380
+ ];
381
+ for (const name of methodNames) {
382
+ Object.defineProperty(proxy, name, {
383
+ value: eventTarget[name],
384
+ writable: false,
385
+ enumerable: false,
386
+ configurable: true
387
+ });
388
+ }
389
+ Object.defineProperty(proxy, "completed", {
390
+ get: () => eventTarget.completed,
391
+ enumerable: false,
392
+ configurable: true
393
+ });
394
+ return proxy;
395
+ }
396
+ return createEventTargetInternal(targetOrOpts);
397
+ }
398
+ function createEventTargetInternal(opts) {
399
+ const listeners = new Map;
400
+ const wildcardListeners = new Set;
401
+ let isCompleted = false;
402
+ const completionCallbacks = new Set;
403
+ const handleListenerError = (eventType, error) => {
404
+ if (eventType === "error")
405
+ return;
406
+ if (opts?.onListenerError) {
407
+ opts.onListenerError(eventType, error);
408
+ return;
409
+ }
410
+ const errorListeners = listeners.get("error");
411
+ if (errorListeners && errorListeners.size > 0) {
412
+ for (const rec of Array.from(errorListeners)) {
413
+ try {
414
+ rec.fn({ type: "error", detail: error });
415
+ } catch {}
416
+ if (rec.once)
417
+ errorListeners.delete(rec);
418
+ }
419
+ } else {
420
+ throw error;
421
+ }
422
+ };
423
+ const notifyWildcardListeners = (eventType, detail) => {
424
+ if (wildcardListeners.size === 0)
425
+ return;
426
+ for (const rec of Array.from(wildcardListeners)) {
427
+ if (!matchesWildcard(eventType, rec.pattern))
428
+ continue;
429
+ const wildcardEvent = {
430
+ type: rec.pattern,
431
+ originalType: eventType,
432
+ detail
433
+ };
434
+ try {
435
+ const res = rec.fn(wildcardEvent);
436
+ if (res && typeof res.then === "function") {
437
+ res.catch((error) => {
438
+ try {
439
+ handleListenerError(eventType, error);
440
+ } catch (rethrown) {
441
+ queueMicrotask(() => {
442
+ throw rethrown;
443
+ });
444
+ }
445
+ });
446
+ }
447
+ } catch (error) {
448
+ handleListenerError(eventType, error);
449
+ } finally {
450
+ if (rec.once)
451
+ wildcardListeners.delete(rec);
452
+ }
453
+ }
454
+ };
455
+ const addEventListener = (type, listener, options) => {
456
+ if (isCompleted) {
457
+ return () => {};
458
+ }
459
+ const opts2 = options ?? {};
460
+ const record = {
461
+ fn: listener,
462
+ once: opts2.once,
463
+ signal: opts2.signal
464
+ };
465
+ let set = listeners.get(type);
466
+ if (!set) {
467
+ set = new Set;
468
+ listeners.set(type, set);
469
+ }
470
+ set.add(record);
471
+ const unsubscribe = () => {
472
+ const setNow = listeners.get(type);
473
+ setNow?.delete(record);
474
+ if (record.signal && record.abortHandler) {
475
+ record.signal.removeEventListener("abort", record.abortHandler);
476
+ }
477
+ };
478
+ if (opts2.signal) {
479
+ const onAbort = () => unsubscribe();
480
+ record.abortHandler = onAbort;
481
+ opts2.signal.addEventListener("abort", onAbort, { once: true });
482
+ if (opts2.signal.aborted)
483
+ onAbort();
484
+ }
485
+ return unsubscribe;
486
+ };
487
+ const addWildcardListener = (pattern, listener, options) => {
488
+ if (isCompleted)
489
+ return () => {};
490
+ const opts2 = options ?? {};
491
+ const record = {
492
+ fn: listener,
493
+ pattern,
494
+ once: opts2.once,
495
+ signal: opts2.signal
496
+ };
497
+ wildcardListeners.add(record);
498
+ const unsubscribe = () => {
499
+ wildcardListeners.delete(record);
500
+ if (record.signal && record.abortHandler) {
501
+ record.signal.removeEventListener("abort", record.abortHandler);
502
+ }
503
+ };
504
+ if (opts2.signal) {
505
+ const onAbort = () => unsubscribe();
506
+ record.abortHandler = onAbort;
507
+ opts2.signal.addEventListener("abort", onAbort, { once: true });
508
+ if (opts2.signal.aborted)
509
+ onAbort();
510
+ }
511
+ return unsubscribe;
512
+ };
513
+ const removeWildcardListener = (pattern, listener) => {
514
+ for (const record of wildcardListeners) {
515
+ if (record.pattern === pattern && record.fn === listener) {
516
+ wildcardListeners.delete(record);
517
+ if (record.signal && record.abortHandler) {
518
+ record.signal.removeEventListener("abort", record.abortHandler);
519
+ }
520
+ break;
521
+ }
522
+ }
523
+ };
524
+ const dispatchEvent = (event) => {
525
+ if (isCompleted)
526
+ return false;
527
+ notifyWildcardListeners(event.type, event.detail);
528
+ const set = listeners.get(event.type);
529
+ if (!set || set.size === 0)
530
+ return true;
531
+ for (const rec of Array.from(set)) {
532
+ try {
533
+ const res = rec.fn(event);
534
+ if (res && typeof res.then === "function") {
535
+ res.catch((error) => {
536
+ try {
537
+ handleListenerError(event.type, error);
538
+ } catch (rethrown) {
539
+ queueMicrotask(() => {
540
+ throw rethrown;
541
+ });
542
+ }
543
+ });
544
+ }
545
+ } catch (error) {
546
+ handleListenerError(event.type, error);
547
+ } finally {
548
+ if (rec.once)
549
+ set.delete(rec);
550
+ }
551
+ }
552
+ return true;
553
+ };
554
+ const removeEventListener = (type, listener) => {
555
+ const set = listeners.get(type);
556
+ if (!set)
557
+ return;
558
+ for (const record of set) {
559
+ if (record.fn === listener) {
560
+ set.delete(record);
561
+ if (record.signal && record.abortHandler) {
562
+ record.signal.removeEventListener("abort", record.abortHandler);
563
+ }
564
+ break;
565
+ }
566
+ }
567
+ };
568
+ const clear = () => {
569
+ for (const set of listeners.values()) {
570
+ for (const record of set) {
571
+ if (record.signal && record.abortHandler) {
572
+ record.signal.removeEventListener("abort", record.abortHandler);
573
+ }
574
+ }
575
+ set.clear();
576
+ }
577
+ listeners.clear();
578
+ for (const record of wildcardListeners) {
579
+ if (record.signal && record.abortHandler) {
580
+ record.signal.removeEventListener("abort", record.abortHandler);
581
+ }
582
+ }
583
+ wildcardListeners.clear();
584
+ };
585
+ const once = (type, listener, options) => {
586
+ return addEventListener(type, listener, { ...options, once: true });
587
+ };
588
+ const removeAllListeners = (type) => {
589
+ if (type !== undefined) {
590
+ const set = listeners.get(type);
591
+ if (set) {
592
+ for (const record of set) {
593
+ if (record.signal && record.abortHandler) {
594
+ record.signal.removeEventListener("abort", record.abortHandler);
595
+ }
596
+ }
597
+ set.clear();
598
+ listeners.delete(type);
599
+ }
600
+ } else {
601
+ for (const set of listeners.values()) {
602
+ for (const record of set) {
603
+ if (record.signal && record.abortHandler) {
604
+ record.signal.removeEventListener("abort", record.abortHandler);
605
+ }
606
+ }
607
+ set.clear();
608
+ }
609
+ listeners.clear();
610
+ for (const record of wildcardListeners) {
611
+ if (record.signal && record.abortHandler) {
612
+ record.signal.removeEventListener("abort", record.abortHandler);
613
+ }
614
+ }
615
+ wildcardListeners.clear();
616
+ }
617
+ };
618
+ const pipe = (target2, mapFn) => {
619
+ if (isCompleted) {
620
+ return () => {};
621
+ }
622
+ const unsubscribes = [];
623
+ const subscribedTypes = new Set;
624
+ const subscribeToType = (type) => {
625
+ if (subscribedTypes.has(type))
626
+ return;
627
+ subscribedTypes.add(type);
628
+ const unsub = addEventListener(type, (event) => {
629
+ if (mapFn) {
630
+ const mapped = mapFn(event);
631
+ if (mapped !== null) {
632
+ target2.dispatchEvent(mapped);
633
+ }
634
+ } else {
635
+ target2.dispatchEvent(event);
636
+ }
637
+ });
638
+ unsubscribes.push(unsub);
639
+ };
640
+ for (const type of listeners.keys()) {
641
+ subscribeToType(type);
642
+ }
643
+ const completionUnsub = () => {
644
+ for (const unsub of unsubscribes) {
645
+ unsub();
646
+ }
647
+ };
648
+ completionCallbacks.add(completionUnsub);
649
+ return () => {
650
+ completionCallbacks.delete(completionUnsub);
651
+ for (const unsub of unsubscribes) {
652
+ unsub();
653
+ }
654
+ };
655
+ };
656
+ const complete = () => {
657
+ if (isCompleted)
658
+ return;
659
+ isCompleted = true;
660
+ for (const cb of completionCallbacks) {
661
+ try {
662
+ cb();
663
+ } catch (err) {
664
+ try {
665
+ handleListenerError("complete", err);
666
+ } catch {}
667
+ }
668
+ }
669
+ completionCallbacks.clear();
670
+ for (const set of listeners.values()) {
671
+ for (const record of set) {
672
+ if (record.signal && record.abortHandler) {
673
+ record.signal.removeEventListener("abort", record.abortHandler);
674
+ }
675
+ }
676
+ set.clear();
677
+ }
678
+ listeners.clear();
679
+ for (const record of wildcardListeners) {
680
+ if (record.signal && record.abortHandler) {
681
+ record.signal.removeEventListener("abort", record.abortHandler);
682
+ }
683
+ }
684
+ wildcardListeners.clear();
685
+ };
686
+ const subscribe = (type, observerOrNext, error, completeHandler) => {
687
+ let observer;
688
+ if (typeof observerOrNext === "function") {
689
+ observer = {
690
+ next: observerOrNext,
691
+ error,
692
+ complete: completeHandler
693
+ };
694
+ } else {
695
+ observer = observerOrNext ?? {};
696
+ }
697
+ let closed = false;
698
+ if (isCompleted) {
699
+ if (observer.complete) {
700
+ try {
701
+ observer.complete();
702
+ } catch {}
703
+ }
704
+ return {
705
+ unsubscribe: () => {
706
+ closed = true;
707
+ },
708
+ get closed() {
709
+ return closed || isCompleted;
710
+ }
711
+ };
712
+ }
713
+ const unsub = addEventListener(type, (event) => {
714
+ if (closed)
715
+ return;
716
+ if (observer.next) {
717
+ try {
718
+ observer.next(event);
719
+ } catch (err) {
720
+ if (observer.error) {
721
+ try {
722
+ observer.error(err);
723
+ } catch {}
724
+ }
725
+ }
726
+ }
727
+ });
728
+ const onComplete = () => {
729
+ if (closed)
730
+ return;
731
+ closed = true;
732
+ if (observer.complete) {
733
+ try {
734
+ observer.complete();
735
+ } catch {}
736
+ }
737
+ };
738
+ completionCallbacks.add(onComplete);
739
+ return {
740
+ unsubscribe: () => {
741
+ if (closed)
742
+ return;
743
+ closed = true;
744
+ completionCallbacks.delete(onComplete);
745
+ unsub();
746
+ },
747
+ get closed() {
748
+ return closed || isCompleted;
749
+ }
750
+ };
751
+ };
752
+ const toObservable = () => {
753
+ const observable = {
754
+ subscribe: (observerOrNext, errorFn, completeFn) => {
755
+ let next;
756
+ let error;
757
+ let completeCallback;
758
+ if (typeof observerOrNext === "function") {
759
+ next = observerOrNext;
760
+ error = errorFn;
761
+ completeCallback = completeFn;
762
+ } else if (observerOrNext) {
763
+ next = observerOrNext.next?.bind(observerOrNext);
764
+ error = observerOrNext.error?.bind(observerOrNext);
765
+ completeCallback = observerOrNext.complete?.bind(observerOrNext);
766
+ }
767
+ let closed = false;
768
+ if (isCompleted) {
769
+ if (completeCallback) {
770
+ try {
771
+ completeCallback();
772
+ } catch {}
773
+ }
774
+ return {
775
+ unsubscribe: () => {
776
+ closed = true;
777
+ },
778
+ get closed() {
779
+ return true;
780
+ }
781
+ };
782
+ }
783
+ const wildcardListener = (event) => {
784
+ if (closed)
785
+ return;
786
+ if (next) {
787
+ try {
788
+ next({ type: event.originalType, detail: event.detail });
789
+ } catch (err) {
790
+ if (error) {
791
+ try {
792
+ error(err);
793
+ } catch {}
794
+ }
795
+ }
796
+ }
797
+ };
798
+ const unsubscribe = addWildcardListener("*", wildcardListener);
799
+ const onComplete = () => {
800
+ if (closed)
801
+ return;
802
+ closed = true;
803
+ if (completeCallback) {
804
+ try {
805
+ completeCallback();
806
+ } catch {}
807
+ }
808
+ };
809
+ completionCallbacks.add(onComplete);
810
+ return {
811
+ unsubscribe: () => {
812
+ if (closed)
813
+ return;
814
+ closed = true;
815
+ unsubscribe();
816
+ completionCallbacks.delete(onComplete);
817
+ },
818
+ get closed() {
819
+ return closed || isCompleted;
820
+ }
821
+ };
822
+ },
823
+ [SymbolObservable]() {
824
+ return observable;
825
+ }
826
+ };
827
+ return observable;
828
+ };
829
+ function events(type, options) {
830
+ if (isCompleted) {
831
+ return {
832
+ [Symbol.asyncIterator]() {
833
+ return this;
834
+ },
835
+ next() {
836
+ return Promise.resolve({
837
+ value: undefined,
838
+ done: true
839
+ });
840
+ },
841
+ return() {
842
+ return Promise.resolve({
843
+ value: undefined,
844
+ done: true
845
+ });
846
+ }
847
+ };
848
+ }
849
+ const signal = options?.signal;
850
+ const bufferSize = options?.bufferSize ?? Infinity;
851
+ const overflowStrategy = options?.overflowStrategy ?? "drop-oldest";
852
+ const buffer = [];
853
+ let resolve = null;
854
+ let done = false;
855
+ let hasOverflow = false;
856
+ const unsub = addEventListener(type, (event) => {
857
+ if (done)
858
+ return;
859
+ if (resolve) {
860
+ const r = resolve;
861
+ resolve = null;
862
+ r({ value: event, done: false });
863
+ } else {
864
+ if (buffer.length >= bufferSize && bufferSize !== Infinity) {
865
+ switch (overflowStrategy) {
866
+ case "drop-oldest":
867
+ buffer.shift();
868
+ buffer.push(event);
869
+ break;
870
+ case "drop-latest":
871
+ break;
872
+ case "throw":
873
+ unsub();
874
+ completionCallbacks.delete(onComplete);
875
+ done = true;
876
+ hasOverflow = true;
877
+ return;
878
+ }
879
+ } else {
880
+ buffer.push(event);
881
+ }
882
+ }
883
+ });
884
+ const onComplete = () => {
885
+ done = true;
886
+ if (resolve) {
887
+ const r = resolve;
888
+ resolve = null;
889
+ r({ value: undefined, done: true });
890
+ }
891
+ };
892
+ completionCallbacks.add(onComplete);
893
+ let onAbort = null;
894
+ if (signal) {
895
+ onAbort = () => {
896
+ done = true;
897
+ completionCallbacks.delete(onComplete);
898
+ unsub();
899
+ if (resolve) {
900
+ const r = resolve;
901
+ resolve = null;
902
+ r({ value: undefined, done: true });
903
+ }
904
+ };
905
+ signal.addEventListener("abort", onAbort, { once: true });
906
+ if (signal.aborted)
907
+ onAbort();
908
+ }
909
+ const iterator = {
910
+ [Symbol.asyncIterator]() {
911
+ return this;
912
+ },
913
+ async next() {
914
+ if (buffer.length > 0) {
915
+ return { value: buffer.shift(), done: false };
916
+ }
917
+ if (hasOverflow) {
918
+ hasOverflow = false;
919
+ throw new BufferOverflowError(type, bufferSize);
920
+ }
921
+ if (done) {
922
+ return { value: undefined, done: true };
923
+ }
924
+ if (resolve !== null) {
925
+ return Promise.reject(new Error("Concurrent calls to next() are not supported on this async iterator"));
926
+ }
927
+ return new Promise((_resolve, _reject) => {
928
+ if (done) {
929
+ _resolve({ value: undefined, done: true });
930
+ return;
931
+ }
932
+ if (hasOverflow) {
933
+ hasOverflow = false;
934
+ _reject(new BufferOverflowError(type, bufferSize));
935
+ return;
936
+ }
937
+ resolve = _resolve;
938
+ });
939
+ },
940
+ return() {
941
+ if (resolve) {
942
+ const r = resolve;
943
+ resolve = null;
944
+ r({ value: undefined, done: true });
945
+ }
946
+ done = true;
947
+ completionCallbacks.delete(onComplete);
948
+ unsub();
949
+ if (signal && onAbort) {
950
+ signal.removeEventListener("abort", onAbort);
951
+ }
952
+ return Promise.resolve({
953
+ value: undefined,
954
+ done: true
955
+ });
956
+ }
957
+ };
958
+ return iterator;
959
+ }
960
+ const target = {
961
+ addEventListener,
962
+ removeEventListener,
963
+ dispatchEvent,
964
+ clear,
965
+ once,
966
+ removeAllListeners,
967
+ pipe,
968
+ addWildcardListener,
969
+ removeWildcardListener,
970
+ complete,
971
+ get completed() {
972
+ return isCompleted;
973
+ },
974
+ subscribe,
975
+ toObservable,
976
+ events
977
+ };
978
+ target[SymbolObservable] = () => {
979
+ return toObservable();
980
+ };
981
+ return target;
982
+ }
983
+ // src/interop.ts
984
+ function forwardToEventTarget(source, target, options) {
985
+ const unsubscribe = source.addWildcardListener("*", (event) => {
986
+ const domEvent = {
987
+ type: event.originalType,
988
+ detail: event.detail
989
+ };
990
+ target.dispatchEvent(domEvent);
991
+ }, options);
992
+ return unsubscribe;
993
+ }
994
+ function fromEventTarget(domTarget, eventTypes, options) {
995
+ const eventful = createEventTarget({
996
+ onListenerError: options?.onListenerError
997
+ });
998
+ const handlers = new Map;
999
+ for (const type of eventTypes) {
1000
+ const handler = (event) => {
1001
+ eventful.dispatchEvent({
1002
+ type,
1003
+ detail: event.detail ?? event
1004
+ });
1005
+ };
1006
+ handlers.set(type, handler);
1007
+ domTarget.addEventListener(type, handler);
1008
+ }
1009
+ let onAbort = null;
1010
+ if (options?.signal) {
1011
+ onAbort = () => {
1012
+ for (const [type, handler] of handlers) {
1013
+ domTarget.removeEventListener(type, handler);
1014
+ }
1015
+ handlers.clear();
1016
+ eventful.complete();
1017
+ };
1018
+ options.signal.addEventListener("abort", onAbort, { once: true });
1019
+ if (options.signal.aborted)
1020
+ onAbort();
1021
+ }
1022
+ return {
1023
+ addEventListener: eventful.addEventListener,
1024
+ removeEventListener: eventful.removeEventListener,
1025
+ dispatchEvent: eventful.dispatchEvent,
1026
+ clear: eventful.clear,
1027
+ once: eventful.once,
1028
+ removeAllListeners: eventful.removeAllListeners,
1029
+ pipe: eventful.pipe,
1030
+ addWildcardListener: eventful.addWildcardListener,
1031
+ removeWildcardListener: eventful.removeWildcardListener,
1032
+ subscribe: eventful.subscribe,
1033
+ toObservable: eventful.toObservable,
1034
+ complete: eventful.complete,
1035
+ get completed() {
1036
+ return eventful.completed;
1037
+ },
1038
+ events: eventful.events,
1039
+ destroy: () => {
1040
+ if (options?.signal && onAbort) {
1041
+ options.signal.removeEventListener("abort", onAbort);
1042
+ }
1043
+ for (const [type, handler] of handlers) {
1044
+ domTarget.removeEventListener(type, handler);
1045
+ }
1046
+ handlers.clear();
1047
+ eventful.complete();
1048
+ }
1049
+ };
1050
+ }
1051
+ function pipe(source, target, options) {
1052
+ return source.addWildcardListener("*", (event) => {
1053
+ target.dispatchEvent({
1054
+ type: event.originalType,
1055
+ detail: event.detail
1056
+ });
1057
+ }, options);
1058
+ }
1059
+ // src/eventful.ts
1060
+ class Eventful {
1061
+ #target;
1062
+ constructor() {
1063
+ this.#target = createEventTarget();
1064
+ }
1065
+ addEventListener(type, listener, options) {
1066
+ return this.#target.addEventListener(type, listener, options);
1067
+ }
1068
+ removeEventListener(type, listener) {
1069
+ this.#target.removeEventListener(type, listener);
1070
+ }
1071
+ dispatchEvent(event) {
1072
+ return this.#target.dispatchEvent(event);
1073
+ }
1074
+ once(type, listener, options) {
1075
+ return this.#target.once(type, listener, options);
1076
+ }
1077
+ removeAllListeners(type) {
1078
+ this.#target.removeAllListeners(type);
1079
+ }
1080
+ clear() {
1081
+ this.#target.clear();
1082
+ }
1083
+ pipe(target, mapFn) {
1084
+ return this.#target.pipe(target, mapFn);
1085
+ }
1086
+ addWildcardListener(pattern, listener, options) {
1087
+ return this.#target.addWildcardListener(pattern, listener, options);
1088
+ }
1089
+ removeWildcardListener(pattern, listener) {
1090
+ this.#target.removeWildcardListener(pattern, listener);
1091
+ }
1092
+ subscribe(typeOrObserver, observerOrNext, error, completeHandler) {
1093
+ if (typeof typeOrObserver === "string") {
1094
+ return this.#target.subscribe(typeOrObserver, observerOrNext, error, completeHandler);
1095
+ }
1096
+ if (typeof typeOrObserver === "function") {
1097
+ return this.#target.toObservable().subscribe(typeOrObserver);
1098
+ }
1099
+ if (typeof typeOrObserver === "object" && typeOrObserver !== null) {
1100
+ const maybeObserver = typeOrObserver;
1101
+ if (typeof maybeObserver.next === "function" || typeof maybeObserver.error === "function" || typeof maybeObserver.complete === "function") {
1102
+ return this.#target.toObservable().subscribe(typeOrObserver);
1103
+ }
1104
+ return this.#target.toObservable().subscribe({});
1105
+ }
1106
+ throw new Error("subscribe() requires a string event type, callback function, or observer object");
1107
+ }
1108
+ toObservable() {
1109
+ return this.#target.toObservable();
1110
+ }
1111
+ [SymbolObservable]() {
1112
+ return this.toObservable();
1113
+ }
1114
+ complete() {
1115
+ this.#target.complete();
1116
+ }
1117
+ get completed() {
1118
+ return this.#target.completed;
1119
+ }
1120
+ events(type, options) {
1121
+ return this.#target.events(type, options);
1122
+ }
1123
+ }
1124
+ })
1125
+
1126
+ //# debugId=C000AD057E5BF10964756E2164756E21