@kuindji/reactive 1.0.24 → 1.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.
Files changed (53) hide show
  1. package/README.md +34 -11
  2. package/dist/action.d.ts +12 -10
  3. package/dist/action.js +20 -10
  4. package/dist/actionBus.d.ts +8 -4
  5. package/dist/actionBus.js +34 -2
  6. package/dist/actionMap.d.ts +21 -19
  7. package/dist/actionMap.js +10 -4
  8. package/dist/event.d.ts +3 -2
  9. package/dist/event.js +112 -58
  10. package/dist/eventBus.d.ts +5 -3
  11. package/dist/eventBus.js +88 -31
  12. package/dist/index.d.ts +7 -7
  13. package/dist/index.js +7 -7
  14. package/dist/lib/actionMapInternal.d.ts +8 -0
  15. package/dist/lib/actionMapInternal.js +8 -0
  16. package/dist/lib/isPromiseLike.d.ts +1 -0
  17. package/dist/lib/isPromiseLike.js +5 -0
  18. package/dist/lib/normalizeEventOptions.d.ts +13 -0
  19. package/dist/lib/normalizeEventOptions.js +21 -0
  20. package/dist/react/ErrorBoundary.d.ts +1 -1
  21. package/dist/react/listenerOptionsEqual.d.ts +27 -0
  22. package/dist/react/listenerOptionsEqual.js +121 -0
  23. package/dist/react/useAction.d.ts +3 -3
  24. package/dist/react/useAction.js +10 -7
  25. package/dist/react/useActionBus.d.ts +4 -4
  26. package/dist/react/useActionBus.js +32 -2
  27. package/dist/react/useActionMap.d.ts +4 -4
  28. package/dist/react/useActionMap.js +40 -7
  29. package/dist/react/useEvent.d.ts +2 -2
  30. package/dist/react/useEvent.js +18 -2
  31. package/dist/react/useEventBus.d.ts +2 -2
  32. package/dist/react/useEventBus.js +14 -10
  33. package/dist/react/useListenToAction.d.ts +1 -1
  34. package/dist/react/useListenToAction.js +17 -38
  35. package/dist/react/useListenToActionBus.d.ts +3 -3
  36. package/dist/react/useListenToActionBus.js +15 -9
  37. package/dist/react/useListenToEvent.d.ts +2 -2
  38. package/dist/react/useListenToEvent.js +8 -6
  39. package/dist/react/useListenToEventBus.d.ts +3 -3
  40. package/dist/react/useListenToEventBus.js +9 -7
  41. package/dist/react/useListenToStoreChanges.d.ts +3 -3
  42. package/dist/react/useListenToStoreChanges.js +9 -7
  43. package/dist/react/useReconciledListener.d.ts +33 -0
  44. package/dist/react/useReconciledListener.js +44 -0
  45. package/dist/react/useStore.d.ts +2 -2
  46. package/dist/react/useStore.js +71 -19
  47. package/dist/react/useStoreState.d.ts +2 -2
  48. package/dist/react/useStoreState.js +14 -21
  49. package/dist/react.d.ts +13 -13
  50. package/dist/react.js +13 -13
  51. package/dist/store.d.ts +9 -8
  52. package/dist/store.js +91 -24
  53. package/package.json +13 -3
package/dist/event.js CHANGED
@@ -1,7 +1,8 @@
1
- import asyncCall from "./lib/asyncCall";
2
- import listenerSorter from "./lib/listenerSorter";
3
- import tagsIntersect from "./lib/tagsIntersect";
4
- import { TriggerReturnType } from "./lib/types";
1
+ import asyncCall from "./lib/asyncCall.js";
2
+ import isPromiseLike from "./lib/isPromiseLike.js";
3
+ import listenerSorter from "./lib/listenerSorter.js";
4
+ import tagsIntersect from "./lib/tagsIntersect.js";
5
+ import { TriggerReturnType } from "./lib/types.js";
5
6
  export function createEvent(eventOptions = {}) {
6
7
  let listeners = [];
7
8
  const errorListeners = [];
@@ -14,10 +15,12 @@ export function createEvent(eventOptions = {}) {
14
15
  let currentTagsFilter = null;
15
16
  const options = Object.assign({ async: null, limit: null, autoTrigger: null, filter: null, filterContext: null, maxListeners: 0 }, eventOptions);
16
17
  const addListener = (handler, listenerOptions = {}) => {
18
+ var _a;
17
19
  if (!handler) {
18
20
  return;
19
21
  }
20
- if (listeners.find((l) => l.handler === handler && l.context === listenerOptions.context)) {
22
+ const listenerContext = (_a = listenerOptions.context) !== null && _a !== void 0 ? _a : null;
23
+ if (listeners.find((l) => l.handler === handler && l.context === listenerContext)) {
21
24
  return;
22
25
  }
23
26
  if (options.maxListeners && listeners.length >= options.maxListeners) {
@@ -54,8 +57,12 @@ export function createEvent(eventOptions = {}) {
54
57
  }
55
58
  return false;
56
59
  };
57
- _trigger(lastTrigger);
58
- options.filter = prevFilter;
60
+ try {
61
+ _trigger(lastTrigger);
62
+ }
63
+ finally {
64
+ options.filter = prevFilter;
65
+ }
59
66
  }
60
67
  };
61
68
  const removeListener = (handler, context, tag) => {
@@ -80,6 +87,49 @@ export function createEvent(eventOptions = {}) {
80
87
  listeners.splice(inx, 1);
81
88
  return true;
82
89
  };
90
+ const updateListenerOptions = (handler, context = null, nextOptions = {}) => {
91
+ var _a, _b, _c, _d, _e, _f, _g;
92
+ const listenerContext = context !== null && context !== void 0 ? context : null;
93
+ const listener = listeners.find((l) => l.handler === handler && l.context === listenerContext);
94
+ if (!listener) {
95
+ return false;
96
+ }
97
+ const prevAlwaysFirst = listener.alwaysFirst;
98
+ const prevAlwaysLast = listener.alwaysLast;
99
+ // Soft fields, applying the same defaults as addListener so that a
100
+ // removed field resets to its default rather than lingering.
101
+ listener.limit = (_a = nextOptions.limit) !== null && _a !== void 0 ? _a : 0;
102
+ listener.start = (_b = nextOptions.start) !== null && _b !== void 0 ? _b : 1;
103
+ listener.tags = (_c = nextOptions.tags) !== null && _c !== void 0 ? _c : [];
104
+ listener.extraData = (_d = nextOptions.extraData) !== null && _d !== void 0 ? _d : null;
105
+ listener.alwaysFirst = (_e = nextOptions.alwaysFirst) !== null && _e !== void 0 ? _e : false;
106
+ listener.alwaysLast = (_f = nextOptions.alwaysLast) !== null && _f !== void 0 ? _f : false;
107
+ let nextAsync = (_g = nextOptions.async) !== null && _g !== void 0 ? _g : null;
108
+ if (nextAsync === true) {
109
+ nextAsync = 1;
110
+ }
111
+ listener.async = nextAsync;
112
+ // Re-sort if ordering hints changed. Unlike addListener we do NOT
113
+ // rewrite each listener's index here: the existing indices hold the
114
+ // original insertion order, and preserving them lets sorting restore
115
+ // that order when alwaysFirst/alwaysLast is cleared.
116
+ if (listener.alwaysFirst !== prevAlwaysFirst
117
+ || listener.alwaysLast !== prevAlwaysLast) {
118
+ if (listener.alwaysFirst === true || listener.alwaysLast === true) {
119
+ sortListeners = true;
120
+ }
121
+ if (sortListeners) {
122
+ listeners.sort((l1, l2) => listenerSorter(l1, l2));
123
+ }
124
+ }
125
+ // The core auto-remove check is a strict `called === limit`, so a
126
+ // listener whose `called` already exceeds the new limit would never
127
+ // auto-remove. Remove it immediately in that case.
128
+ if (listener.limit !== 0 && listener.called >= listener.limit) {
129
+ removeListener(listener.handler, listener.context);
130
+ }
131
+ return true;
132
+ };
83
133
  const hasListener = (handler, context, tag) => {
84
134
  if (handler) {
85
135
  return (listeners.findIndex((l) => {
@@ -137,7 +187,7 @@ export function createEvent(eventOptions = {}) {
137
187
  queued = false;
138
188
  if (queue.length > 0) {
139
189
  for (let i = 0, l = queue.length; i < l; i++) {
140
- _trigger(queue[i][0], queue[i][1]);
190
+ _trigger(queue[i][0], queue[i][1], queue[i][2]);
141
191
  }
142
192
  queue = [];
143
193
  }
@@ -156,7 +206,6 @@ export function createEvent(eventOptions = {}) {
156
206
  triggered = 0;
157
207
  lastTrigger = null;
158
208
  sortListeners = false;
159
- cachedPromise = null;
160
209
  };
161
210
  const _listenerCall = (listener, args, resolve = null) => {
162
211
  let isAsync = listener.async;
@@ -173,26 +222,29 @@ export function createEvent(eventOptions = {}) {
173
222
  const result = isAsync !== false
174
223
  ? asyncCall(listener.handler, listener.context, args, isAsync)
175
224
  : listener.handler.bind(listener.context)(...args);
176
- if (resolve !== null) {
177
- if (result instanceof Promise) {
178
- void result.then(resolve).catch((error) => {
179
- for (const errorListener of errorListeners) {
180
- errorListener.handler({
181
- error: error instanceof Error
182
- ? error
183
- : new Error(error),
184
- args: args,
185
- type: "event",
186
- });
187
- }
188
- if (errorListeners.length === 0) {
189
- throw error;
190
- }
191
- });
192
- }
193
- else {
194
- resolve(result);
225
+ if (isPromiseLike(result)) {
226
+ const handledResult = Promise.resolve(result).catch((error) => {
227
+ for (const errorListener of errorListeners) {
228
+ errorListener.handler({
229
+ error: error instanceof Error
230
+ ? error
231
+ : new Error(error),
232
+ args: args,
233
+ type: "event",
234
+ });
235
+ }
236
+ if (errorListeners.length === 0) {
237
+ throw error;
238
+ }
239
+ return undefined;
240
+ });
241
+ if (resolve !== null) {
242
+ void handledResult.then(resolve);
195
243
  }
244
+ return handledResult;
245
+ }
246
+ if (resolve !== null) {
247
+ resolve(result);
196
248
  }
197
249
  return result;
198
250
  }
@@ -236,8 +288,13 @@ export function createEvent(eventOptions = {}) {
236
288
  return _listenerCall(listener, args);
237
289
  };
238
290
  const _trigger = (args, returnType = null, tags) => {
291
+ var _a, _b;
239
292
  if (queued) {
240
- queue.push([args, returnType]);
293
+ queue.push([
294
+ args,
295
+ returnType,
296
+ (_b = (_a = (tags || currentTagsFilter)) === null || _a === void 0 ? void 0 : _a.slice()) !== null && _b !== void 0 ? _b : null,
297
+ ]);
241
298
  return;
242
299
  }
243
300
  if (suspended) {
@@ -303,9 +360,7 @@ export function createEvent(eventOptions = {}) {
303
360
  if (isConsequent && results.length > 0) {
304
361
  const prev = results[results.length - 1];
305
362
  if (hasPromises) {
306
- const prevPromise = prev instanceof Promise
307
- ? prev
308
- : Promise.resolve(prev);
363
+ const prevPromise = Promise.resolve(prev);
309
364
  listenerResult = prevPromise.then(((listener, args, returnType) => (value) => {
310
365
  return _listenerCallWPrev(listener, args, value, returnType);
311
366
  })(listener, args, returnType));
@@ -342,7 +397,7 @@ export function createEvent(eventOptions = {}) {
342
397
  }
343
398
  case TriggerReturnType.FIRST_NON_EMPTY: {
344
399
  if (!hasPromises
345
- && !(listenerResult instanceof Promise)
400
+ && !isPromiseLike(listenerResult)
346
401
  && listenerResult !== null
347
402
  && listenerResult !== undefined) {
348
403
  return listenerResult;
@@ -351,7 +406,7 @@ export function createEvent(eventOptions = {}) {
351
406
  }
352
407
  }
353
408
  }
354
- if (!hasPromises && listenerResult instanceof Promise) {
409
+ if (!hasPromises && isPromiseLike(listenerResult)) {
355
410
  hasPromises = true;
356
411
  }
357
412
  results.push(listenerResult);
@@ -405,33 +460,31 @@ export function createEvent(eventOptions = {}) {
405
460
  _trigger(args);
406
461
  };
407
462
  const withTags = (tags, callback) => {
463
+ const prevTagsFilter = currentTagsFilter;
408
464
  currentTagsFilter = tags;
409
465
  try {
410
466
  return callback();
411
467
  }
412
468
  finally {
413
- currentTagsFilter = null;
469
+ currentTagsFilter = prevTagsFilter;
414
470
  }
415
471
  };
416
- let cachedPromise = null;
417
472
  const promise = (options) => {
418
- return cachedPromise = cachedPromise
419
- || new Promise((resolve) => {
420
- options = Object.assign(Object.assign({}, (options || {})), { limit: 1 });
421
- const l = ((...args) => {
422
- resolve(args);
423
- cachedPromise = null;
424
- });
425
- addListener(l, options);
473
+ return new Promise((resolve) => {
474
+ options = Object.assign(Object.assign({}, (options || {})), { limit: 1 });
475
+ const l = ((...args) => {
476
+ resolve(args);
426
477
  });
478
+ addListener(l, options);
479
+ });
427
480
  };
428
481
  const first = (...args) => {
429
482
  return _trigger(args, TriggerReturnType.FIRST);
430
483
  };
431
484
  const resolveFirst = (...args) => {
432
485
  const response = _trigger(args, TriggerReturnType.FIRST);
433
- if (response instanceof Promise) {
434
- return response;
486
+ if (isPromiseLike(response)) {
487
+ return Promise.resolve(response);
435
488
  }
436
489
  return Promise.resolve(response);
437
490
  };
@@ -440,8 +493,8 @@ export function createEvent(eventOptions = {}) {
440
493
  };
441
494
  const resolveAll = (...args) => {
442
495
  const response = _trigger(args, TriggerReturnType.ALL);
443
- if (response instanceof Promise) {
444
- return response;
496
+ if (isPromiseLike(response)) {
497
+ return Promise.resolve(response);
445
498
  }
446
499
  return Promise.resolve(response);
447
500
  };
@@ -450,8 +503,8 @@ export function createEvent(eventOptions = {}) {
450
503
  };
451
504
  const resolveLast = (...args) => {
452
505
  const response = _trigger(args, TriggerReturnType.LAST);
453
- if (response instanceof Promise) {
454
- return response;
506
+ if (isPromiseLike(response)) {
507
+ return Promise.resolve(response);
455
508
  }
456
509
  return Promise.resolve(response);
457
510
  };
@@ -460,8 +513,8 @@ export function createEvent(eventOptions = {}) {
460
513
  };
461
514
  const resolveMerge = (...args) => {
462
515
  const response = _trigger(args, TriggerReturnType.MERGE);
463
- if (response instanceof Promise) {
464
- return response;
516
+ if (isPromiseLike(response)) {
517
+ return Promise.resolve(response);
465
518
  }
466
519
  return Promise.resolve(response);
467
520
  };
@@ -470,8 +523,8 @@ export function createEvent(eventOptions = {}) {
470
523
  };
471
524
  const resolveConcat = (...args) => {
472
525
  const response = _trigger(args, TriggerReturnType.CONCAT);
473
- if (response instanceof Promise) {
474
- return response;
526
+ if (isPromiseLike(response)) {
527
+ return Promise.resolve(response);
475
528
  }
476
529
  return Promise.resolve(response);
477
530
  };
@@ -480,8 +533,8 @@ export function createEvent(eventOptions = {}) {
480
533
  };
481
534
  const resolveFirstNonEmpty = (...args) => {
482
535
  const response = _trigger(args, TriggerReturnType.FIRST_NON_EMPTY);
483
- if (response instanceof Promise) {
484
- return response;
536
+ if (isPromiseLike(response)) {
537
+ return Promise.resolve(response);
485
538
  }
486
539
  return Promise.resolve(response);
487
540
  };
@@ -496,8 +549,8 @@ export function createEvent(eventOptions = {}) {
496
549
  };
497
550
  const resolvePipe = (...args) => {
498
551
  const response = _trigger(args, TriggerReturnType.PIPE);
499
- if (response instanceof Promise) {
500
- return response;
552
+ if (isPromiseLike(response)) {
553
+ return Promise.resolve(response);
501
554
  }
502
555
  return Promise.resolve(response);
503
556
  };
@@ -513,6 +566,7 @@ export function createEvent(eventOptions = {}) {
513
566
  /** @alias addListener */
514
567
  subscribe: addListener,
515
568
  removeListener,
569
+ updateListenerOptions,
516
570
  /** @alias removeListener */
517
571
  un: removeListener,
518
572
  /** @alias removeListener */
@@ -1,6 +1,6 @@
1
- import { createEvent } from "./event";
2
- import type { EventDefinitionHelper, EventOptions, ListenerOptions } from "./event";
3
- import { ApiType, BaseHandler, ErrorListenerSignature, KeyOf, MapKey, ProxyType, TriggerReturnType } from "./lib/types";
1
+ import { createEvent } from "./event.js";
2
+ import type { EventDefinitionHelper, EventOptions, ListenerOptions } from "./event.js";
3
+ import { ApiType, BaseHandler, ErrorListenerSignature, KeyOf, MapKey, ProxyType, TriggerReturnType } from "./lib/types.js";
4
4
  type InterceptorFunction = (name: MapKey, args: any[], tags: string[] | null, returnType: TriggerReturnType | null) => boolean;
5
5
  type RelaySource = {
6
6
  on: (name: any, fn: (...args: any[]) => any, options?: ListenerOptions) => void;
@@ -59,6 +59,7 @@ export declare function createEventBus<EventsMap extends BaseEventMap = DefaultE
59
59
  readonly remove: <K extends KeyOf<GetEventsMap<EventsMap>>, H extends GetEventsMap<EventsMap>[K]["signature"]>(name: K, handler: H, context?: object | null, tag?: string | null) => void;
60
60
  /** @alias removeListener */
61
61
  readonly unsubscribe: <K extends KeyOf<GetEventsMap<EventsMap>>, H extends GetEventsMap<EventsMap>[K]["signature"]>(name: K, handler: H, context?: object | null, tag?: string | null) => void;
62
+ readonly updateListenerOptions: <K extends KeyOf<GetEventsMap<EventsMap>>, H extends GetEventsMap<EventsMap>[K]["signature"]>(name: K, handler: H, context?: object | null, nextOptions?: ListenerOptions) => boolean;
62
63
  readonly trigger: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => void;
63
64
  /** @alias trigger */
64
65
  readonly emit: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => void;
@@ -66,6 +67,7 @@ export declare function createEventBus<EventsMap extends BaseEventMap = DefaultE
66
67
  readonly dispatch: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => void;
67
68
  readonly get: <K extends KeyOf<GetEventsMap<EventsMap>>>(name: K) => GetEventTypesMap<EventsMap>[K];
68
69
  readonly add: (name: MapKey, options?: EventOptions<BaseHandler>) => void;
70
+ readonly setOptions: (options?: EventBusOptions<BaseEventMap>) => void;
69
71
  readonly first: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => ReturnType<GetEventTypesMap<EventsMap>[K]["first"]>;
70
72
  readonly resolveFirst: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => ReturnType<GetEventTypesMap<EventsMap>[K]["resolveFirst"]>;
71
73
  readonly all: <K extends KeyOf<GetEventsMap<EventsMap>>, A extends GetEventsMap<EventsMap>[K]["arguments"]>(name: K, ...args: A) => ReturnType<GetEventTypesMap<EventsMap>[K]["all"]>;
package/dist/eventBus.js CHANGED
@@ -1,5 +1,7 @@
1
- import { createEvent } from "./event";
2
- import { ProxyType, TriggerReturnType, } from "./lib/types";
1
+ import { createEvent } from "./event.js";
2
+ import isPromiseLike from "./lib/isPromiseLike.js";
3
+ import { normalizeEventOptions } from "./lib/normalizeEventOptions.js";
4
+ import { ProxyType, TriggerReturnType, } from "./lib/types.js";
3
5
  function proxyReturnTypeToTriggerReturnType(proxyType) {
4
6
  switch (proxyType) {
5
7
  case ProxyType.TRIGGER:
@@ -71,6 +73,7 @@ function proxyReturnTypeToTriggerReturnType(proxyType) {
71
73
  }
72
74
  export function createEventBus(eventBusOptions) {
73
75
  const events = new Map();
76
+ let currentEventBusOptions = eventBusOptions;
74
77
  let currentTagsFilter = null;
75
78
  let interceptor = null;
76
79
  const proxyListeners = [];
@@ -135,10 +138,31 @@ export function createEventBus(eventBusOptions) {
135
138
  const _getOrAddEvent = (name) => {
136
139
  var _a;
137
140
  if (!events.has(name)) {
138
- events.set(name, createEvent((_a = eventBusOptions === null || eventBusOptions === void 0 ? void 0 : eventBusOptions.eventOptions) === null || _a === void 0 ? void 0 : _a[name]));
141
+ events.set(name, createEvent((_a = currentEventBusOptions === null || currentEventBusOptions === void 0 ? void 0 : currentEventBusOptions.eventOptions) === null || _a === void 0 ? void 0 : _a[name]));
139
142
  }
140
143
  return events.get(name);
141
144
  };
145
+ // Parameter is intentionally map-independent (like `add`) so that the
146
+ // method type is identical across instantiations and a typed bus stays
147
+ // assignable to BaseEventBus (which the React listener hooks rely on).
148
+ const setOptions = (options) => {
149
+ currentEventBusOptions = options;
150
+ const eventOptions = options === null || options === void 0 ? void 0 : options.eventOptions;
151
+ if (!eventOptions) {
152
+ return;
153
+ }
154
+ // Apply present entries to already-created events. Removed entries are
155
+ // intentionally left as-is (the bus can change an event's options but
156
+ // does not un-set them).
157
+ Object.keys(eventOptions).forEach((name) => {
158
+ const e = events.get(name);
159
+ if (e) {
160
+ // Normalize so fields removed from a present entry reset to
161
+ // their defaults (event.setOptions merges, it does not reset).
162
+ e.setOptions(normalizeEventOptions(eventOptions[name]));
163
+ }
164
+ });
165
+ };
142
166
  const intercept = (fn) => {
143
167
  interceptor = fn;
144
168
  };
@@ -168,7 +192,7 @@ export function createEventBus(eventBusOptions) {
168
192
  resolve,
169
193
  localEventNamePrefix: null,
170
194
  });
171
- evs.eventSource.on(name, listener.listener, evs.eventSource, options);
195
+ evs.eventSource.on(name, listener.listener, evs.eventSource);
172
196
  evs.subscribed.push(name);
173
197
  }
174
198
  });
@@ -192,23 +216,28 @@ export function createEventBus(eventBusOptions) {
192
216
  const isEmpty = !e.hasListener();
193
217
  eventSources.forEach((evs) => {
194
218
  const inx = evs.subscribed.indexOf(name);
195
- if (inx !== -1) {
219
+ if (inx !== -1 && isEmpty) {
196
220
  evs.subscribed.splice(inx, 1);
197
- if (isEmpty) {
198
- const { returnType, resolve } = proxyReturnTypeToTriggerReturnType(evs.eventSource.proxyType || ProxyType.TRIGGER);
199
- const listener = _getProxyListener({
200
- localEventName: null,
201
- remoteEventName: name,
202
- returnType,
203
- resolve,
204
- localEventNamePrefix: null,
205
- });
206
- evs.eventSource.un(name, listener.listener, evs.eventSource, tag);
207
- }
221
+ const { returnType, resolve } = proxyReturnTypeToTriggerReturnType(evs.eventSource.proxyType || ProxyType.TRIGGER);
222
+ const listener = _getProxyListener({
223
+ localEventName: null,
224
+ remoteEventName: name,
225
+ returnType,
226
+ resolve,
227
+ localEventNamePrefix: null,
228
+ });
229
+ evs.eventSource.un(name, listener.listener, evs.eventSource, tag);
208
230
  }
209
231
  });
210
232
  }
211
233
  };
234
+ const updateListenerOptions = (name, handler, context, nextOptions) => {
235
+ const e = events.get(name);
236
+ if (!e) {
237
+ return false;
238
+ }
239
+ return e.updateListenerOptions(handler, context !== null && context !== void 0 ? context : null, nextOptions);
240
+ };
212
241
  const _trigger = (name, args, returnType, resolve) => {
213
242
  if (name === "*") {
214
243
  return;
@@ -220,6 +249,20 @@ export function createEventBus(eventBusOptions) {
220
249
  }
221
250
  }
222
251
  const e = _getOrAddEvent(name);
252
+ const handleError = (error) => {
253
+ errorEvent.trigger({
254
+ name,
255
+ error: error instanceof Error
256
+ ? error
257
+ : new Error(String(error)),
258
+ args,
259
+ type: "event",
260
+ });
261
+ if (errorEvent.hasListener()) {
262
+ return undefined;
263
+ }
264
+ throw error;
265
+ };
223
266
  const runner = () => {
224
267
  let result;
225
268
  switch (returnType) {
@@ -276,21 +319,13 @@ export function createEventBus(eventBusOptions) {
276
319
  result = runner();
277
320
  }
278
321
  asterisk.trigger(name, args, currentTagsFilter);
322
+ if (isPromiseLike(result)) {
323
+ return Promise.resolve(result).catch(handleError);
324
+ }
279
325
  return result;
280
326
  }
281
327
  catch (error) {
282
- errorEvent.trigger({
283
- name,
284
- error: error instanceof Error
285
- ? error
286
- : new Error(String(error)),
287
- args,
288
- type: "event",
289
- });
290
- if (errorEvent.hasListener()) {
291
- return undefined;
292
- }
293
- throw error;
328
+ return handleError(error);
294
329
  }
295
330
  };
296
331
  const trigger = (name, ...args) => {
@@ -348,17 +383,18 @@ export function createEventBus(eventBusOptions) {
348
383
  return _trigger(name, args, TriggerReturnType.RAW, false);
349
384
  };
350
385
  const withTags = (tags, callback) => {
386
+ const prevTagsFilter = currentTagsFilter;
351
387
  currentTagsFilter = tags;
352
388
  try {
353
389
  return callback();
354
390
  }
355
391
  finally {
356
- currentTagsFilter = null;
392
+ currentTagsFilter = prevTagsFilter;
357
393
  }
358
394
  };
359
395
  const reset = () => {
360
396
  if (eventSources.length > 0) {
361
- eventSources.forEach((evs) => {
397
+ eventSources.slice().forEach((evs) => {
362
398
  removeEventSource(evs.eventSource);
363
399
  });
364
400
  }
@@ -417,9 +453,28 @@ export function createEventBus(eventBusOptions) {
417
453
  if (eventSources.find((evs) => evs.eventSource.name === eventSource.name)) {
418
454
  return;
419
455
  }
420
- eventSources.push({
456
+ const eventSourceData = {
421
457
  eventSource,
422
458
  subscribed: [],
459
+ };
460
+ eventSources.push(eventSourceData);
461
+ events.forEach((event, name) => {
462
+ if (!event.hasListener()
463
+ || eventSource.accepts === false
464
+ || (typeof eventSource.accepts === "function"
465
+ && !eventSource.accepts(name))) {
466
+ return;
467
+ }
468
+ const { returnType, resolve } = proxyReturnTypeToTriggerReturnType(eventSource.proxyType || ProxyType.TRIGGER);
469
+ const listener = _getProxyListener({
470
+ localEventName: null,
471
+ remoteEventName: name,
472
+ returnType,
473
+ resolve,
474
+ localEventNamePrefix: null,
475
+ });
476
+ eventSource.on(name, listener.listener, eventSource);
477
+ eventSourceData.subscribed.push(name);
423
478
  });
424
479
  };
425
480
  const removeEventSource = (eventSource) => {
@@ -462,6 +517,7 @@ export function createEventBus(eventBusOptions) {
462
517
  remove: un,
463
518
  /** @alias removeListener */
464
519
  unsubscribe: un,
520
+ updateListenerOptions,
465
521
  trigger,
466
522
  /** @alias trigger */
467
523
  emit: trigger,
@@ -469,6 +525,7 @@ export function createEventBus(eventBusOptions) {
469
525
  dispatch: trigger,
470
526
  get,
471
527
  add,
528
+ setOptions,
472
529
  first,
473
530
  resolveFirst,
474
531
  all,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export * from "./action";
2
- export * from "./actionBus";
3
- export * from "./actionMap";
4
- export * from "./event";
5
- export * from "./eventBus";
6
- export * from "./lib/types";
7
- export * from "./store";
1
+ export * from "./action.js";
2
+ export * from "./actionBus.js";
3
+ export * from "./actionMap.js";
4
+ export * from "./event.js";
5
+ export * from "./eventBus.js";
6
+ export * from "./lib/types.js";
7
+ export * from "./store.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- export * from "./action";
2
- export * from "./actionBus";
3
- export * from "./actionMap";
4
- export * from "./event";
5
- export * from "./eventBus";
6
- export * from "./lib/types";
7
- export * from "./store";
1
+ export * from "./action.js";
2
+ export * from "./actionBus.js";
3
+ export * from "./actionMap.js";
4
+ export * from "./event.js";
5
+ export * from "./eventBus.js";
6
+ export * from "./lib/types.js";
7
+ export * from "./store.js";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Internal-only symbol used to expose an in-place setter for an action map's
3
+ * forwarded error listeners. Lives under src/lib (which is not re-exported by
4
+ * the package root in index.ts) so it does not become part of the public API
5
+ * surface. Imported by createActionMap (to attach the setter) and by
6
+ * useActionMap (to call it during reconciliation).
7
+ */
8
+ export declare const ActionMapSetErrorListeners: unique symbol;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Internal-only symbol used to expose an in-place setter for an action map's
3
+ * forwarded error listeners. Lives under src/lib (which is not re-exported by
4
+ * the package root in index.ts) so it does not become part of the public API
5
+ * surface. Imported by createActionMap (to attach the setter) and by
6
+ * useActionMap (to call it during reconciliation).
7
+ */
8
+ export const ActionMapSetErrorListeners = Symbol("actionMapSetErrorListeners");
@@ -0,0 +1 @@
1
+ export default function isPromiseLike<T = unknown>(value: unknown): value is PromiseLike<T>;
@@ -0,0 +1,5 @@
1
+ export default function isPromiseLike(value) {
2
+ return ((typeof value === "object" || typeof value === "function")
3
+ && value !== null
4
+ && typeof value.then === "function");
5
+ }
@@ -0,0 +1,13 @@
1
+ import type { EventOptions } from "../event.js";
2
+ import type { BaseHandler } from "./types.js";
3
+ /**
4
+ * Produces a complete {@link EventOptions} object with every field set to the
5
+ * provided value or its createEvent default. Used by the reconciliation paths
6
+ * (useEvent and eventBus.setOptions) so that applying options via the
7
+ * merge-based event.setOptions also resets fields that were removed across
8
+ * renders, instead of leaving stale values from a previous render.
9
+ *
10
+ * Internal-only: this module lives under src/lib (not re-exported by the
11
+ * package root) and is not part of the public API surface.
12
+ */
13
+ export declare function normalizeEventOptions(options?: EventOptions<BaseHandler> | null): EventOptions<BaseHandler>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Produces a complete {@link EventOptions} object with every field set to the
3
+ * provided value or its createEvent default. Used by the reconciliation paths
4
+ * (useEvent and eventBus.setOptions) so that applying options via the
5
+ * merge-based event.setOptions also resets fields that were removed across
6
+ * renders, instead of leaving stale values from a previous render.
7
+ *
8
+ * Internal-only: this module lives under src/lib (not re-exported by the
9
+ * package root) and is not part of the public API surface.
10
+ */
11
+ export function normalizeEventOptions(options) {
12
+ var _a, _b, _c, _d, _e, _f;
13
+ return {
14
+ async: (_a = options === null || options === void 0 ? void 0 : options.async) !== null && _a !== void 0 ? _a : null,
15
+ limit: (_b = options === null || options === void 0 ? void 0 : options.limit) !== null && _b !== void 0 ? _b : null,
16
+ autoTrigger: (_c = options === null || options === void 0 ? void 0 : options.autoTrigger) !== null && _c !== void 0 ? _c : null,
17
+ filter: (_d = options === null || options === void 0 ? void 0 : options.filter) !== null && _d !== void 0 ? _d : null,
18
+ filterContext: (_e = options === null || options === void 0 ? void 0 : options.filterContext) !== null && _e !== void 0 ? _e : null,
19
+ maxListeners: (_f = options === null || options === void 0 ? void 0 : options.maxListeners) !== null && _f !== void 0 ? _f : 0,
20
+ };
21
+ }
@@ -1,4 +1,4 @@
1
- import type { ErrorListenerSignature, ErrorResponse } from "../lib/types";
1
+ import type { ErrorListenerSignature, ErrorResponse } from "../lib/types.js";
2
2
  export type ErrorBoundaryProps = {
3
3
  children: React.ReactNode;
4
4
  listener?: ErrorListenerSignature<any>;