@kuindji/reactive 1.0.23 → 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.
- package/README.md +34 -11
- package/dist/action.d.ts +12 -10
- package/dist/action.js +23 -16
- package/dist/actionBus.d.ts +8 -4
- package/dist/actionBus.js +37 -8
- package/dist/actionMap.d.ts +21 -19
- package/dist/actionMap.js +12 -9
- package/dist/event.d.ts +3 -2
- package/dist/event.js +160 -109
- package/dist/eventBus.d.ts +5 -3
- package/dist/eventBus.js +158 -104
- package/dist/index.d.ts +7 -7
- package/dist/index.js +7 -23
- package/dist/lib/actionMapInternal.d.ts +8 -0
- package/dist/lib/actionMapInternal.js +8 -0
- package/dist/lib/asyncCall.js +1 -4
- package/dist/lib/isPromiseLike.d.ts +1 -0
- package/dist/lib/isPromiseLike.js +5 -0
- package/dist/lib/listenerSorter.js +1 -4
- package/dist/lib/normalizeEventOptions.d.ts +13 -0
- package/dist/lib/normalizeEventOptions.js +21 -0
- package/dist/lib/tagsIntersect.js +1 -4
- package/dist/lib/types.js +4 -7
- package/dist/react/ErrorBoundary.d.ts +1 -1
- package/dist/react/ErrorBoundary.js +10 -13
- package/dist/react/listenerOptionsEqual.d.ts +27 -0
- package/dist/react/listenerOptionsEqual.js +121 -0
- package/dist/react/useAction.d.ts +3 -3
- package/dist/react/useAction.js +25 -25
- package/dist/react/useActionBus.d.ts +4 -4
- package/dist/react/useActionBus.js +41 -14
- package/dist/react/useActionMap.d.ts +4 -4
- package/dist/react/useActionMap.js +46 -16
- package/dist/react/useEvent.d.ts +2 -2
- package/dist/react/useEvent.js +30 -17
- package/dist/react/useEventBus.d.ts +2 -2
- package/dist/react/useEventBus.js +27 -26
- package/dist/react/useListenToAction.d.ts +1 -1
- package/dist/react/useListenToAction.js +24 -48
- package/dist/react/useListenToActionBus.d.ts +3 -3
- package/dist/react/useListenToActionBus.js +22 -19
- package/dist/react/useListenToEvent.d.ts +2 -2
- package/dist/react/useListenToEvent.js +13 -14
- package/dist/react/useListenToEventBus.d.ts +3 -3
- package/dist/react/useListenToEventBus.js +14 -15
- package/dist/react/useListenToStoreChanges.d.ts +3 -3
- package/dist/react/useListenToStoreChanges.js +12 -13
- package/dist/react/useReconciledListener.d.ts +33 -0
- package/dist/react/useReconciledListener.js +44 -0
- package/dist/react/useStore.d.ts +2 -2
- package/dist/react/useStore.js +72 -23
- package/dist/react/useStoreState.d.ts +2 -2
- package/dist/react/useStoreState.js +16 -26
- package/dist/react.d.ts +13 -13
- package/dist/react.js +13 -29
- package/dist/store.d.ts +9 -8
- package/dist/store.js +116 -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
|
-
- `
|
|
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
|
-
- `
|
|
582
|
-
- `
|
|
583
|
-
|
|
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
|
-
- `
|
|
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()` -
|
|
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
|
|
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
|
|
45
|
-
readonly
|
|
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
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,20 +7,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
import { createEvent } from "./event.js";
|
|
11
|
+
import isPromiseLike from "./lib/isPromiseLike.js";
|
|
12
|
+
export function createAction(action) {
|
|
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();
|
|
18
|
+
const { all: triggerBeforeAction, addListener: addBeforeActionListener, removeAllListeners: removeAllBeforeActionListeners, removeListener: removeBeforeActionListener, promise: beforeActionPromise, } = createEvent();
|
|
19
|
+
const { trigger: triggerError, addListener: addErrorListener, removeAllListeners: removeAllErrorListeners, removeListener: removeErrorListener, promise: errorPromise, hasListener: hasErrorListeners, } = createEvent();
|
|
18
20
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
19
21
|
try {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const beforeResponse = triggerBeforeAction(...args);
|
|
23
|
+
const beforeResults = isPromiseLike(beforeResponse)
|
|
24
|
+
? yield Promise.resolve(beforeResponse)
|
|
25
|
+
: beforeResponse;
|
|
26
|
+
for (const before of beforeResults) {
|
|
25
27
|
if (before === false) {
|
|
26
28
|
const response = {
|
|
27
29
|
response: null,
|
|
@@ -32,9 +34,9 @@ function createAction(action) {
|
|
|
32
34
|
return response;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
|
-
let result =
|
|
36
|
-
if (result
|
|
37
|
-
result = yield result;
|
|
37
|
+
let result = actionFn(...args);
|
|
38
|
+
if (isPromiseLike(result)) {
|
|
39
|
+
result = yield Promise.resolve(result);
|
|
38
40
|
}
|
|
39
41
|
const response = {
|
|
40
42
|
response: result,
|
|
@@ -64,8 +66,12 @@ function createAction(action) {
|
|
|
64
66
|
return response;
|
|
65
67
|
}
|
|
66
68
|
});
|
|
69
|
+
const setAction = (nextAction) => {
|
|
70
|
+
actionFn = nextAction;
|
|
71
|
+
};
|
|
67
72
|
const api = {
|
|
68
73
|
invoke,
|
|
74
|
+
setAction,
|
|
69
75
|
addListener,
|
|
70
76
|
/** @alias addListener */
|
|
71
77
|
on: addListener,
|
|
@@ -83,6 +89,7 @@ function createAction(action) {
|
|
|
83
89
|
remove: removeListener,
|
|
84
90
|
/** @alias removeListener */
|
|
85
91
|
unsubscribe: removeListener,
|
|
92
|
+
updateListenerOptions,
|
|
86
93
|
promise,
|
|
87
94
|
addErrorListener,
|
|
88
95
|
removeAllErrorListeners,
|
package/dist/actionBus.d.ts
CHANGED
|
@@ -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,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const action_1 = require("./action");
|
|
5
|
-
const event_1 = require("./event");
|
|
6
|
-
function createActionBus(initialActions = {}, errorListener) {
|
|
1
|
+
import { createAction } from "./action.js";
|
|
2
|
+
import { createEvent } from "./event.js";
|
|
3
|
+
export function createActionBus(initialActions = {}, errorListener) {
|
|
7
4
|
const actions = new Map();
|
|
8
|
-
const errorEvent =
|
|
5
|
+
const errorEvent = createEvent();
|
|
9
6
|
if (errorListener) {
|
|
10
7
|
errorEvent.addListener(errorListener);
|
|
11
8
|
}
|
|
12
9
|
const add = (name, action) => {
|
|
13
10
|
if (!actions.has(name)) {
|
|
14
|
-
const a =
|
|
11
|
+
const a = createAction(action);
|
|
15
12
|
a.addErrorListener(({ error, args }) => {
|
|
16
13
|
errorEvent.emit({ name, error, args, type: "action" });
|
|
17
14
|
});
|
|
@@ -24,6 +21,27 @@ function createActionBus(initialActions = {}, errorListener) {
|
|
|
24
21
|
const get = (name) => {
|
|
25
22
|
return actions.get(name);
|
|
26
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
|
+
};
|
|
27
45
|
const invoke = (name, ...args) => {
|
|
28
46
|
const action = get(name);
|
|
29
47
|
if (!action) {
|
|
@@ -54,8 +72,18 @@ function createActionBus(initialActions = {}, errorListener) {
|
|
|
54
72
|
}
|
|
55
73
|
return action.removeListener(handler, context, tag);
|
|
56
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
|
+
};
|
|
57
82
|
const api = {
|
|
58
83
|
add,
|
|
84
|
+
replace,
|
|
85
|
+
removeAction,
|
|
86
|
+
has,
|
|
59
87
|
get,
|
|
60
88
|
invoke,
|
|
61
89
|
addListener: on,
|
|
@@ -75,6 +103,7 @@ function createActionBus(initialActions = {}, errorListener) {
|
|
|
75
103
|
un: un,
|
|
76
104
|
/** @alias removeListener */
|
|
77
105
|
unsubscribe: un,
|
|
106
|
+
updateListenerOptions,
|
|
78
107
|
addErrorListener: errorEvent.addListener,
|
|
79
108
|
removeErrorListener: errorEvent.removeListener,
|
|
80
109
|
};
|
package/dist/actionMap.d.ts
CHANGED
|
@@ -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
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
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
|
|
18
|
-
readonly
|
|
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,26 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function createActionMap(actions, onAnyError) {
|
|
1
|
+
import { createAction } from "./action.js";
|
|
2
|
+
import { ActionMapSetErrorListeners } from "./lib/actionMapInternal.js";
|
|
3
|
+
export function createActionMap(actions, onAnyError) {
|
|
4
|
+
let currentOnAnyError = onAnyError;
|
|
6
5
|
const errorListenersMap = {};
|
|
7
6
|
for (const key in actions) {
|
|
8
7
|
errorListenersMap[key] = (errorResponse) => {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const handlers = currentOnAnyError;
|
|
9
|
+
if (Array.isArray(handlers)) {
|
|
10
|
+
for (const listener of handlers) {
|
|
11
11
|
listener === null || listener === void 0 ? void 0 : listener(Object.assign({ name: key }, errorResponse));
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
else {
|
|
15
|
-
|
|
15
|
+
handlers === null || handlers === void 0 ? void 0 : handlers(Object.assign({ name: key }, errorResponse));
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
const map = {};
|
|
20
20
|
for (const key in actions) {
|
|
21
|
-
const action =
|
|
21
|
+
const action = createAction(actions[key]);
|
|
22
22
|
action.addErrorListener(errorListenersMap[key]);
|
|
23
23
|
map[key] = action;
|
|
24
24
|
}
|
|
25
|
+
map[ActionMapSetErrorListeners] = (next) => {
|
|
26
|
+
currentOnAnyError = next;
|
|
27
|
+
};
|
|
25
28
|
return map;
|
|
26
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:
|
|
118
|
+
readonly setOptions: (eventOptions: Partial<EventOptions<ListenerSignature>>) => void;
|
|
118
119
|
readonly reset: () => void;
|
|
119
120
|
readonly isSuspended: () => boolean;
|
|
120
121
|
readonly isQueued: () => boolean;
|