@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/README.md CHANGED
@@ -161,11 +161,13 @@ const value = event.pipe(1); // value = 4
161
161
  - **Aliases**: `on()`, `listen()`, `subscribe()`
162
162
  - `removeListener(listener, context?, tag?)` - Remove specific listener
163
163
  - **Aliases**: `un()`, `off()`, `remove()`, `unsubscribe()`
164
+ - `updateListenerOptions(listener, context?, nextOptions?)` - Update a registered listener's soft options (`limit`, `start`, `async`, `tags`, `extraData`, `alwaysFirst`/`alwaysLast`) **in place**, preserving its `called`/`count` counters. Matches the listener by `listener` + `context`. Returns `true` if a listener was found. `context` is an identity field and is not updated here (resubscribe to change it); `first` is insertion-time only and ignored. Lowering `limit` to at/below the current `called` removes the listener immediately.
164
165
  - `hasListener(listener?, context?, tag?)` - Check if listener exists
165
166
  - **Aliases**: `has()`
166
167
  - `removeAllListeners(tag?)` - Remove all listeners (optionally by tag)
167
168
  - `trigger(...args)` - Trigger the event
168
169
  - **Aliases**: `emit()`, `dispatch()`
170
+ - `setOptions(options)` - Update event options in place. Accepts any `EventOptions` field (`async`, `limit`, `autoTrigger`, `filter`, `filterContext`, `maxListeners`). Does not reset the internal `triggered` count.
169
171
 
170
172
  #### Collector Methods
171
173
 
@@ -481,10 +483,12 @@ customSource.trigger("appStart");
481
483
  - `once(name, handler, options?)` - Add one-time listener
482
484
  - `removeListener(name, handler, context?, tag?)` - Remove listener
483
485
  - **Aliases**: `un()`, `off()`, `remove()`, `unsubscribe()`
486
+ - `updateListenerOptions(name, handler, context?, nextOptions?)` - Update a registered listener's soft options in place (see Event's `updateListenerOptions`). Returns `false` if the event does not exist.
484
487
  - `trigger(name, ...args)` - Trigger specific event
485
488
  - **Aliases**: `emit()`, `dispatch()`
486
489
  - `get(name)` - Get event instance by name
487
490
  - `add(name, options?)` - Add new event to bus
491
+ - `setOptions(options?)` - Update bus options. Present per-event entries in `eventOptions` are applied to already-created events via `event.setOptions`, and future events use the latest stored options. A removed event-name entry leaves the existing event unchanged.
488
492
 
489
493
  #### Collector Methods
490
494
 
@@ -560,27 +564,31 @@ const result = await fetchUserAction.invoke("user123");
560
564
  #### Core Methods
561
565
 
562
566
  - `invoke(...args)` - Execute the action
567
+ - `setAction(fn)` - Replace the action function in place. Subsequent `invoke()` calls use the new function; all response, before-action and error listeners are preserved (they live in separate events). The replacement must keep a compatible signature.
563
568
  - `addListener(handler, options?)` - Add response listener
564
569
  - **Aliases**: `on()`, `listen()`, `subscribe()`
565
570
  - `removeListener(handler, context?, tag?)` - Remove listener
566
571
  - **Aliases**: `un()`, `off()`, `remove()`, `unsubscribe()`
567
- - `hasListener(handler?, context?, tag?)` - Check if listener exists
568
- - **Aliases**: `has()`
572
+ - `updateListenerOptions(handler, context?, nextOptions?)` - Update a response listener's soft options in place (see Event's `updateListenerOptions`)
569
573
  - `removeAllListeners(tag?)` - Remove all listeners
570
574
 
571
575
  #### Error Handling
572
576
 
573
577
  - `addErrorListener(handler, context?)` - Add error listener
574
578
  - `removeErrorListener(handler, context?)` - Remove error listener
575
- - `hasErrorListeners()` - Check if error listeners exist
576
579
  - `removeAllErrorListeners(tag?)` - Remove all error listeners
577
580
 
578
581
  #### Utility Methods
579
582
 
580
583
  - `promise(options?)` - Get promise for next invocation
581
- - `suspend(withQueue?)` - Suspend action execution
582
- - `resume()` - Resume action execution
583
- - `reset()` - Reset action state
584
+ - `beforeActionPromise(options?)` - Get promise for the next before-action call
585
+ - `errorPromise(options?)` - Get promise for the next action error
586
+
587
+ #### Before Action Methods
588
+
589
+ - `addBeforeActionListener(handler, options?)` - Add listener that runs before invocation
590
+ - `removeBeforeActionListener(handler, context?, tag?)` - Remove before-action listener
591
+ - `removeAllBeforeActionListeners(tag?)` - Remove all before-action listeners
584
592
 
585
593
  ## ActionMap
586
594
 
@@ -683,7 +691,10 @@ const user = await actionBus.invoke("fetchUser", "user123");
683
691
 
684
692
  #### Core Methods
685
693
 
686
- - `add(name, action)` - Add action to bus
694
+ - `add(name, action)` - Add action to bus (no-op if it already exists)
695
+ - `replace(name, action)` - Replace an existing action's function in place via `setAction` (preserving its listeners and the bus error-forwarding listener); adds it if the name is new
696
+ - `removeAction(name)` - Remove an action from the bus (named `removeAction` because `remove` is an alias for `removeListener`). Afterwards `invoke`/`on`/`un` for that name throw `Action <name> not found`.
697
+ - `has(name)` - Check if action exists
687
698
  - `get(name)` - Get action by name
688
699
  - `invoke(name, ...args)` - Invoke action by name
689
700
  - `addListener(name, handler, options?)` - Add listener to action
@@ -691,8 +702,7 @@ const user = await actionBus.invoke("fetchUser", "user123");
691
702
  - `once(name, handler, options?)` - Add one-time listener
692
703
  - `removeListener(name, handler, context?, tag?)` - Remove listener
693
704
  - **Aliases**: `un()`, `off()`, `remove()`, `unsubscribe()`
694
- - `has(name)` - Check if action exists
695
- - `remove(name)` - Remove action
705
+ - `updateListenerOptions(name, handler, context?, nextOptions?)` - Update a response listener's soft options in place (see Event's `updateListenerOptions`)
696
706
 
697
707
  #### Error Handling
698
708
 
@@ -753,11 +763,13 @@ const userData = userStore.get([ "name", "email" ]); // { name: string, email: s
753
763
  - `get(keys)` - Get multiple properties
754
764
  - `isEmpty()` - Check if store is empty
755
765
  - `getData()` - Get all store data
756
- - `reset()` - Reset store to initial state
766
+ - `reset()` - Clear store data
757
767
 
758
768
  #### Event Methods
759
769
 
760
- - `onChange(key, handler)` - Listen to property changes
770
+ - `onChange(key, handler, options?)` - Listen to property changes
771
+ - `removeOnChange(key, handler, context?, tag?)` - Remove a change listener
772
+ - `updateOnChangeOptions(key, handler, context?, nextOptions?)` - Update a change listener's soft options in place (see Event's `updateListenerOptions`)
761
773
  - `pipe(key, handler)` - Add data transformation pipeline
762
774
  - `control(event, handler)` - Control store events
763
775
 
@@ -953,6 +965,17 @@ useListenToStoreChanges(
953
965
  )
954
966
  ```
955
967
 
968
+ ### Reconciliation across renders
969
+
970
+ Hook inputs are reconciled on every render using semantic comparison, so you
971
+ can safely pass inline objects (e.g. `{ tags: [tag] }`) without object identity
972
+ forcing a resubscribe:
973
+
974
+ - **Listener options** (`useListenToEvent`/`useListenToEventBus`/`useListenToActionBus`/`useListenToStoreChanges`) are compared field by field (`tags` is an order-insensitive set). A semantically equal object is a no-op. A changed soft option updates the live listener **in place**, preserving its `called`/`count` counters. Changing `context` (an identity field) resubscribes using the old context.
975
+ - **`useEvent` event options** and **`useEventBus` options** are reconciled via `setOptions` instead of being ignored (and `useEventBus` no longer throws when options change).
976
+ - **`useAction`/`useActionBus`/`useActionMap` action functions** are replaced in place via `setAction` (compared by reference), preserving all listeners; `useActionBus` also adds/removes actions as its map changes. The `useActionMap` key set is fixed by its type contract — a runtime key-set change throws.
977
+ - **`useStore` config** (`onChange`/`pipes`/`control`) is reconciled by category + key (functions compared by reference); only handlers added by the hook are touched. **`initialData` is seed-only** — it initializes the store once and later changes are intentionally ignored (live data is owned by `set`/`useStoreState`).
978
+
956
979
  ## ErrorBoundary
957
980
 
958
981
  ### Description
package/dist/action.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApiType, BaseHandler, ErrorListenerSignature, ErrorResponse } from "./lib/types";
1
+ import type { ApiType, BaseHandler, ErrorListenerSignature, ErrorResponse } from "./lib/types.js";
2
2
  export type ActionResponse<Response = any, Args extends unknown[] = unknown[]> = {
3
3
  response: Response;
4
4
  error: null;
@@ -24,13 +24,14 @@ export type ActionDefinitionHelper<A extends BaseHandler> = {
24
24
  };
25
25
  export declare function createAction<A extends BaseHandler>(action: A): ApiType<ActionDefinitionHelper<A>, {
26
26
  readonly invoke: (...args: Parameters<A>) => Promise<ActionResponse<Awaited<ReturnType<A>>, Parameters<A>>>;
27
- readonly addListener: (handler: ListenerSignature<A>, listenerOptions?: import("./event").ListenerOptions) => void;
27
+ readonly setAction: (nextAction: A) => void;
28
+ readonly addListener: (handler: ListenerSignature<A>, listenerOptions?: import("./event.js").ListenerOptions) => void;
28
29
  /** @alias addListener */
29
- readonly on: (handler: ListenerSignature<A>, listenerOptions?: import("./event").ListenerOptions) => void;
30
+ readonly on: (handler: ListenerSignature<A>, listenerOptions?: import("./event.js").ListenerOptions) => void;
30
31
  /** @alias addListener */
31
- readonly subscribe: (handler: ListenerSignature<A>, listenerOptions?: import("./event").ListenerOptions) => void;
32
+ readonly subscribe: (handler: ListenerSignature<A>, listenerOptions?: import("./event.js").ListenerOptions) => void;
32
33
  /** @alias addListener */
33
- readonly listen: (handler: ListenerSignature<A>, listenerOptions?: import("./event").ListenerOptions) => void;
34
+ readonly listen: (handler: ListenerSignature<A>, listenerOptions?: import("./event.js").ListenerOptions) => void;
34
35
  readonly removeAllListeners: (tag?: string) => void;
35
36
  readonly removeListener: (handler: ListenerSignature<A>, context?: object | null, tag?: string | null) => boolean;
36
37
  /** @alias removeListener */
@@ -41,15 +42,16 @@ export declare function createAction<A extends BaseHandler>(action: A): ApiType<
41
42
  readonly remove: (handler: ListenerSignature<A>, context?: object | null, tag?: string | null) => boolean;
42
43
  /** @alias removeListener */
43
44
  readonly unsubscribe: (handler: ListenerSignature<A>, context?: object | null, tag?: string | null) => boolean;
44
- readonly promise: (options?: import("./event").ListenerOptions) => Promise<[arg: ActionResponse<Awaited<ReturnType<A>>, Parameters<A>>]>;
45
- readonly addErrorListener: (handler: ErrorListenerSignature<Parameters<A>>, listenerOptions?: import("./event").ListenerOptions) => void;
45
+ readonly updateListenerOptions: (handler: ListenerSignature<A>, context?: object | null, nextOptions?: import("./event.js").ListenerOptions) => boolean;
46
+ readonly promise: (options?: import("./event.js").ListenerOptions) => Promise<[arg: ActionResponse<Awaited<ReturnType<A>>, Parameters<A>>]>;
47
+ readonly addErrorListener: (handler: ErrorListenerSignature<Parameters<A>>, listenerOptions?: import("./event.js").ListenerOptions) => void;
46
48
  readonly removeAllErrorListeners: (tag?: string) => void;
47
49
  readonly removeErrorListener: (handler: ErrorListenerSignature<Parameters<A>>, context?: object | null, tag?: string | null) => boolean;
48
- readonly errorPromise: (options?: import("./event").ListenerOptions) => Promise<[errorResponse: ErrorResponse<Parameters<A>>]>;
49
- readonly addBeforeActionListener: (handler: BeforeActionSignature<A>, listenerOptions?: import("./event").ListenerOptions) => void;
50
+ readonly errorPromise: (options?: import("./event.js").ListenerOptions) => Promise<[errorResponse: ErrorResponse<Parameters<A>>]>;
51
+ readonly addBeforeActionListener: (handler: BeforeActionSignature<A>, listenerOptions?: import("./event.js").ListenerOptions) => void;
50
52
  readonly removeAllBeforeActionListeners: (tag?: string) => void;
51
53
  readonly removeBeforeActionListener: (handler: BeforeActionSignature<A>, context?: object | null, tag?: string | null) => boolean;
52
- readonly beforeActionPromise: (options?: import("./event").ListenerOptions) => Promise<Parameters<A>>;
54
+ readonly beforeActionPromise: (options?: import("./event.js").ListenerOptions) => Promise<Parameters<A>>;
53
55
  }>;
54
56
  export type BaseActionDefinition = ActionDefinitionHelper<(...args: [any]) => any>;
55
57
  export type BaseAction = ReturnType<typeof createAction<(...args: [any]) => any>>;
package/dist/action.js CHANGED
@@ -7,18 +7,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createEvent } from "./event";
10
+ import { createEvent } from "./event.js";
11
+ import isPromiseLike from "./lib/isPromiseLike.js";
11
12
  export function createAction(action) {
12
- const { trigger, addListener, removeAllListeners, removeListener, promise, } = createEvent();
13
+ // The action function is held in a mutable variable so it can be swapped in
14
+ // place via setAction without disturbing any listeners (response, before
15
+ // and error listeners live in separate events independent of the function).
16
+ let actionFn = action;
17
+ const { trigger, addListener, removeAllListeners, removeListener, updateListenerOptions, promise, } = createEvent();
13
18
  const { all: triggerBeforeAction, addListener: addBeforeActionListener, removeAllListeners: removeAllBeforeActionListeners, removeListener: removeBeforeActionListener, promise: beforeActionPromise, } = createEvent();
14
19
  const { trigger: triggerError, addListener: addErrorListener, removeAllListeners: removeAllErrorListeners, removeListener: removeErrorListener, promise: errorPromise, hasListener: hasErrorListeners, } = createEvent();
15
20
  const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
16
21
  try {
17
- const beforeResults = triggerBeforeAction(...args);
18
- for (let before of beforeResults) {
19
- if (before instanceof Promise) {
20
- before = yield before;
21
- }
22
+ const beforeResponse = triggerBeforeAction(...args);
23
+ const beforeResults = isPromiseLike(beforeResponse)
24
+ ? yield Promise.resolve(beforeResponse)
25
+ : beforeResponse;
26
+ for (const before of beforeResults) {
22
27
  if (before === false) {
23
28
  const response = {
24
29
  response: null,
@@ -29,9 +34,9 @@ export function createAction(action) {
29
34
  return response;
30
35
  }
31
36
  }
32
- let result = action(...args);
33
- if (result instanceof Promise) {
34
- result = yield result;
37
+ let result = actionFn(...args);
38
+ if (isPromiseLike(result)) {
39
+ result = yield Promise.resolve(result);
35
40
  }
36
41
  const response = {
37
42
  response: result,
@@ -61,8 +66,12 @@ export function createAction(action) {
61
66
  return response;
62
67
  }
63
68
  });
69
+ const setAction = (nextAction) => {
70
+ actionFn = nextAction;
71
+ };
64
72
  const api = {
65
73
  invoke,
74
+ setAction,
66
75
  addListener,
67
76
  /** @alias addListener */
68
77
  on: addListener,
@@ -80,6 +89,7 @@ export function createAction(action) {
80
89
  remove: removeListener,
81
90
  /** @alias removeListener */
82
91
  unsubscribe: removeListener,
92
+ updateListenerOptions,
83
93
  promise,
84
94
  addErrorListener,
85
95
  removeAllErrorListeners,
@@ -1,6 +1,6 @@
1
- import { ActionDefinitionHelper, createAction } from "./action";
2
- import { ListenerOptions } from "./event";
3
- import type { ApiType, BaseHandler, ErrorListenerSignature, KeyOf, MapKey } from "./lib/types";
1
+ import { ActionDefinitionHelper, createAction } from "./action.js";
2
+ import { ListenerOptions } from "./event.js";
3
+ import type { ApiType, BaseHandler, ErrorListenerSignature, KeyOf, MapKey } from "./lib/types.js";
4
4
  export interface BaseActionsMap {
5
5
  [key: MapKey]: BaseHandler;
6
6
  }
@@ -16,8 +16,11 @@ export type ActionBusDefinitionHelper<ActionsMap extends BaseActionsMap> = {
16
16
  };
17
17
  export declare function createActionBus<ActionsMap extends BaseActionsMap>(initialActions?: ActionsMap, errorListener?: ErrorListenerSignature<any[]>): ApiType<ActionBusDefinitionHelper<ActionsMap>, {
18
18
  readonly add: (name: MapKey, action: BaseHandler) => void;
19
+ readonly replace: (name: MapKey, action: BaseHandler) => void;
20
+ readonly removeAction: (name: MapKey) => void;
21
+ readonly has: (name: MapKey) => boolean;
19
22
  readonly get: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K) => GetActionTypesMap<ActionsMap>[K];
20
- readonly invoke: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, ...args: GetActionDefinitionsMap<ActionsMap>[K]["actionArguments"]) => Promise<import("./action").ActionResponse<Awaited<ReturnType<ActionsMap[K]>>, Parameters<ActionsMap[K]>>>;
23
+ readonly invoke: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, ...args: GetActionDefinitionsMap<ActionsMap>[K]["actionArguments"]) => Promise<import("./action.js").ActionResponse<Awaited<ReturnType<ActionsMap[K]>>, Parameters<ActionsMap[K]>>>;
21
24
  readonly addListener: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, handler: GetActionDefinitionsMap<ActionsMap>[K]["listenerSignature"], options?: ListenerOptions) => void;
22
25
  /** @alias addListener */
23
26
  readonly on: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, handler: GetActionDefinitionsMap<ActionsMap>[K]["listenerSignature"], options?: ListenerOptions) => void;
@@ -35,6 +38,7 @@ export declare function createActionBus<ActionsMap extends BaseActionsMap>(initi
35
38
  readonly un: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, handler: GetActionDefinitionsMap<ActionsMap>[K]["listenerSignature"], context?: object | null, tag?: string | null) => boolean;
36
39
  /** @alias removeListener */
37
40
  readonly unsubscribe: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, handler: GetActionDefinitionsMap<ActionsMap>[K]["listenerSignature"], context?: object | null, tag?: string | null) => boolean;
41
+ readonly updateListenerOptions: <K extends KeyOf<GetActionDefinitionsMap<ActionsMap>>>(name: K, handler: GetActionDefinitionsMap<ActionsMap>[K]["listenerSignature"], context?: object | null, nextOptions?: ListenerOptions) => boolean;
38
42
  readonly addErrorListener: (handler: ErrorListenerSignature<any[]>, listenerOptions?: ListenerOptions) => void;
39
43
  readonly removeErrorListener: (handler: ErrorListenerSignature<any[]>, context?: object | null, tag?: string | null) => boolean;
40
44
  }>;
package/dist/actionBus.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createAction } from "./action";
2
- import { createEvent } from "./event";
1
+ import { createAction } from "./action.js";
2
+ import { createEvent } from "./event.js";
3
3
  export function createActionBus(initialActions = {}, errorListener) {
4
4
  const actions = new Map();
5
5
  const errorEvent = createEvent();
@@ -21,6 +21,27 @@ export function createActionBus(initialActions = {}, errorListener) {
21
21
  const get = (name) => {
22
22
  return actions.get(name);
23
23
  };
24
+ const has = (name) => {
25
+ return actions.has(name);
26
+ };
27
+ // Replace an action's function in place when it exists (preserving all of
28
+ // its listeners and the bus error-forwarding listener, which is attached to
29
+ // the action's error event, not the function); otherwise add it.
30
+ const replace = (name, action) => {
31
+ const existing = actions.get(name);
32
+ if (existing) {
33
+ existing.setAction(action);
34
+ }
35
+ else {
36
+ add(name, action);
37
+ }
38
+ };
39
+ // Named removeAction (not remove) because `remove` is an existing alias for
40
+ // removeListener. The removed action's listeners and its error-forwarding
41
+ // listener are dropped with it (they lived on the action's own events).
42
+ const removeAction = (name) => {
43
+ actions.delete(name);
44
+ };
24
45
  const invoke = (name, ...args) => {
25
46
  const action = get(name);
26
47
  if (!action) {
@@ -51,8 +72,18 @@ export function createActionBus(initialActions = {}, errorListener) {
51
72
  }
52
73
  return action.removeListener(handler, context, tag);
53
74
  };
75
+ const updateListenerOptions = (name, handler, context, nextOptions) => {
76
+ const action = get(name);
77
+ if (!action) {
78
+ return false;
79
+ }
80
+ return action.updateListenerOptions(handler, context, nextOptions);
81
+ };
54
82
  const api = {
55
83
  add,
84
+ replace,
85
+ removeAction,
86
+ has,
56
87
  get,
57
88
  invoke,
58
89
  addListener: on,
@@ -72,6 +103,7 @@ export function createActionBus(initialActions = {}, errorListener) {
72
103
  un: un,
73
104
  /** @alias removeListener */
74
105
  unsubscribe: un,
106
+ updateListenerOptions,
75
107
  addErrorListener: errorEvent.addListener,
76
108
  removeErrorListener: errorEvent.removeListener,
77
109
  };
@@ -1,27 +1,29 @@
1
- import type { ActionResponse } from "./action";
2
- import type { BaseActionsMap } from "./actionBus";
3
- import type { ErrorListenerSignature, ErrorResponse, KeyOf } from "./lib/types";
1
+ import type { ActionResponse } from "./action.js";
2
+ import type { BaseActionsMap } from "./actionBus.js";
3
+ import type { ErrorListenerSignature, ErrorResponse, KeyOf } from "./lib/types.js";
4
4
  export type { ActionResponse, BaseActionsMap, ErrorListenerSignature, ErrorResponse, };
5
5
  export declare function createActionMap<M extends BaseActionsMap>(actions: M, onAnyError?: ErrorListenerSignature<any[]> | ErrorListenerSignature<any[]>[]): { [key in KeyOf<M>]: {
6
6
  readonly invoke: (...args: Parameters<M[key]>) => Promise<ActionResponse<Awaited<ReturnType<M[key]>>, Parameters<M[key]>>>;
7
- readonly addListener: (handler: import("./action").ListenerSignature<M[key]>, listenerOptions?: import("./event").ListenerOptions) => void;
8
- readonly on: (handler: import("./action").ListenerSignature<M[key]>, listenerOptions?: import("./event").ListenerOptions) => void;
9
- readonly subscribe: (handler: import("./action").ListenerSignature<M[key]>, listenerOptions?: import("./event").ListenerOptions) => void;
10
- readonly listen: (handler: import("./action").ListenerSignature<M[key]>, listenerOptions?: import("./event").ListenerOptions) => void;
7
+ readonly setAction: (nextAction: M[key]) => void;
8
+ readonly addListener: (handler: import("./action.js").ListenerSignature<M[key]>, listenerOptions?: import("./event.js").ListenerOptions) => void;
9
+ readonly on: (handler: import("./action.js").ListenerSignature<M[key]>, listenerOptions?: import("./event.js").ListenerOptions) => void;
10
+ readonly subscribe: (handler: import("./action.js").ListenerSignature<M[key]>, listenerOptions?: import("./event.js").ListenerOptions) => void;
11
+ readonly listen: (handler: import("./action.js").ListenerSignature<M[key]>, listenerOptions?: import("./event.js").ListenerOptions) => void;
11
12
  readonly removeAllListeners: (tag?: string) => void;
12
- readonly removeListener: (handler: import("./action").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
13
- readonly un: (handler: import("./action").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
14
- readonly off: (handler: import("./action").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
15
- readonly remove: (handler: import("./action").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
16
- readonly unsubscribe: (handler: import("./action").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
17
- readonly promise: (options?: import("./event").ListenerOptions) => Promise<[arg: ActionResponse<Awaited<ReturnType<M[key]>>, Parameters<M[key]>>]>;
18
- readonly addErrorListener: (handler: ErrorListenerSignature<Parameters<M[key]>>, listenerOptions?: import("./event").ListenerOptions) => void;
13
+ readonly removeListener: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
14
+ readonly un: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
15
+ readonly off: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
16
+ readonly remove: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
17
+ readonly unsubscribe: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
18
+ readonly updateListenerOptions: (handler: import("./action.js").ListenerSignature<M[key]>, context?: object | null, nextOptions?: import("./event.js").ListenerOptions) => boolean;
19
+ readonly promise: (options?: import("./event.js").ListenerOptions) => Promise<[arg: ActionResponse<Awaited<ReturnType<M[key]>>, Parameters<M[key]>>]>;
20
+ readonly addErrorListener: (handler: ErrorListenerSignature<Parameters<M[key]>>, listenerOptions?: import("./event.js").ListenerOptions) => void;
19
21
  readonly removeAllErrorListeners: (tag?: string) => void;
20
22
  readonly removeErrorListener: (handler: ErrorListenerSignature<Parameters<M[key]>>, context?: object | null, tag?: string | null) => boolean;
21
- readonly errorPromise: (options?: import("./event").ListenerOptions) => Promise<[errorResponse: ErrorResponse<Parameters<M[key]>>]>;
22
- readonly addBeforeActionListener: (handler: import("./action").BeforeActionSignature<M[key]>, listenerOptions?: import("./event").ListenerOptions) => void;
23
+ readonly errorPromise: (options?: import("./event.js").ListenerOptions) => Promise<[errorResponse: ErrorResponse<Parameters<M[key]>>]>;
24
+ readonly addBeforeActionListener: (handler: import("./action.js").BeforeActionSignature<M[key]>, listenerOptions?: import("./event.js").ListenerOptions) => void;
23
25
  readonly removeAllBeforeActionListeners: (tag?: string) => void;
24
- readonly removeBeforeActionListener: (handler: import("./action").BeforeActionSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
25
- readonly beforeActionPromise: (options?: import("./event").ListenerOptions) => Promise<Parameters<M[key]>>;
26
- __type: import("./action").ActionDefinitionHelper<M[key]>;
26
+ readonly removeBeforeActionListener: (handler: import("./action.js").BeforeActionSignature<M[key]>, context?: object | null, tag?: string | null) => boolean;
27
+ readonly beforeActionPromise: (options?: import("./event.js").ListenerOptions) => Promise<Parameters<M[key]>>;
28
+ __type: import("./action.js").ActionDefinitionHelper<M[key]>;
27
29
  }; };
package/dist/actionMap.js CHANGED
@@ -1,15 +1,18 @@
1
- import { createAction } from "./action";
1
+ import { createAction } from "./action.js";
2
+ import { ActionMapSetErrorListeners } from "./lib/actionMapInternal.js";
2
3
  export function createActionMap(actions, onAnyError) {
4
+ let currentOnAnyError = onAnyError;
3
5
  const errorListenersMap = {};
4
6
  for (const key in actions) {
5
7
  errorListenersMap[key] = (errorResponse) => {
6
- if (Array.isArray(onAnyError)) {
7
- for (const listener of onAnyError) {
8
+ const handlers = currentOnAnyError;
9
+ if (Array.isArray(handlers)) {
10
+ for (const listener of handlers) {
8
11
  listener === null || listener === void 0 ? void 0 : listener(Object.assign({ name: key }, errorResponse));
9
12
  }
10
13
  }
11
14
  else {
12
- onAnyError === null || onAnyError === void 0 ? void 0 : onAnyError(Object.assign({ name: key }, errorResponse));
15
+ handlers === null || handlers === void 0 ? void 0 : handlers(Object.assign({ name: key }, errorResponse));
13
16
  }
14
17
  };
15
18
  }
@@ -19,5 +22,8 @@ export function createActionMap(actions, onAnyError) {
19
22
  action.addErrorListener(errorListenersMap[key]);
20
23
  map[key] = action;
21
24
  }
25
+ map[ActionMapSetErrorListeners] = (next) => {
26
+ currentOnAnyError = next;
27
+ };
22
28
  return map;
23
29
  }
package/dist/event.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApiType, BaseHandler, ErrorListenerSignature } from "./lib/types";
1
+ import type { ApiType, BaseHandler, ErrorListenerSignature } from "./lib/types.js";
2
2
  type Unarray<T> = T extends (infer U)[] ? U : T;
3
3
  interface BaseOptions {
4
4
  /**
@@ -93,6 +93,7 @@ export declare function createEvent<ListenerSignature extends BaseHandler>(event
93
93
  /** @alias addListener */
94
94
  readonly subscribe: (handler: ListenerSignature, listenerOptions?: ListenerOptions) => void;
95
95
  readonly removeListener: (handler: ListenerSignature, context?: object | null, tag?: string | null) => boolean;
96
+ readonly updateListenerOptions: (handler: ListenerSignature, context?: object | null, nextOptions?: ListenerOptions) => boolean;
96
97
  /** @alias removeListener */
97
98
  readonly un: (handler: ListenerSignature, context?: object | null, tag?: string | null) => boolean;
98
99
  /** @alias removeListener */
@@ -114,7 +115,7 @@ export declare function createEvent<ListenerSignature extends BaseHandler>(event
114
115
  readonly removeErrorListener: (handler: ErrorListenerSignature<Parameters<ListenerSignature>>, context?: object | null) => boolean;
115
116
  readonly suspend: (withQueue?: boolean) => void;
116
117
  readonly resume: () => void;
117
- readonly setOptions: (eventOptions: Pick<EventOptions<ListenerSignature>, "async" | "limit" | "autoTrigger">) => void;
118
+ readonly setOptions: (eventOptions: Partial<EventOptions<ListenerSignature>>) => void;
118
119
  readonly reset: () => void;
119
120
  readonly isSuspended: () => boolean;
120
121
  readonly isQueued: () => boolean;