nanoeffects 0.26.0 → 0.28.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 +85 -30
- package/dist/{action-creator-Bpa8BUS9.d.ts → action-creator-CcAEvUnw.d.ts} +90 -23
- package/dist/actions.d.ts +54 -21
- package/dist/actions.js +1 -1
- package/dist/bus-DlpEluzd.js +1 -0
- package/dist/{context-types-BKIH5a8s.d.ts → context-types-hCKgU8sC.d.ts} +1 -1
- package/dist/context.d.ts +2 -2
- package/dist/dev.d.ts +2 -2
- package/dist/dev.js +1 -1
- package/dist/effects.d.ts +2 -2
- package/dist/event-DVcW0mME.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/match.d.ts +1 -1
- package/dist/{module-B6rg5NIb.d.ts → module-C_oEXw1n.d.ts} +40 -57
- package/dist/notrace/{action-creator-D2CotugT.d.ts → action-creator-DxOvVo8I.d.ts} +90 -23
- package/dist/notrace/actions.d.ts +114 -98
- package/dist/notrace/actions.js +1 -1
- package/dist/notrace/bus-DmKn4SDD.js +1 -0
- package/dist/notrace/effects.d.ts +2 -2
- package/dist/notrace/index.d.ts +2 -2
- package/dist/notrace/index.js +1 -1
- package/dist/notrace/{plugin-Dz6hq8Jg.d.ts → plugin-lJjjd-SN.d.ts} +1 -1
- package/dist/notrace/policies.d.ts +1 -1
- package/dist/notrace/policies.js +1 -1
- package/dist/notrace/redux.d.ts +1 -1
- package/dist/observable.d.ts +6 -6
- package/dist/oop.d.ts +2 -2
- package/dist/oop.js +1 -1
- package/dist/{plugin-D-j1DarG.d.ts → plugin-CuvIgjnX.d.ts} +2 -2
- package/dist/policies.d.ts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/redux.d.ts +1 -1
- package/dist/scope.d.ts +2 -2
- package/dist/signal.d.ts +1 -1
- package/dist/signal.js +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/trace.d.ts +1 -1
- package/dist/{types-Bkuhnkq6.d.ts → types-FV8fuvI9.d.ts} +2 -2
- package/dist/vue.d.ts +1 -1
- package/dist/{with-policy-BeH8wCkX.d.ts → with-policy-3bhFLEXs.d.ts} +1 -1
- package/docs/README.md +5 -4
- package/docs/actions.md +94 -53
- package/docs/chat-example.md +8 -8
- package/docs/chat-widget.md +135 -0
- package/docs/context.md +1 -1
- package/docs/errors.md +1 -1
- package/docs/guide.md +26 -26
- package/docs/hmr.md +1 -1
- package/docs/motivation.md +10 -4
- package/docs/oop.md +1 -1
- package/docs/package.md +2 -2
- package/docs/plugins.md +23 -23
- package/docs/query-libraries.md +14 -14
- package/docs/scope.md +22 -22
- package/docs/server.md +12 -12
- package/docs/stability.md +2 -2
- package/docs/starter.md +3 -3
- package/docs/tracing.md +5 -5
- package/docs/typescript.md +16 -16
- package/llms-full.txt +380 -194
- package/llms.txt +3 -2
- package/package.json +5 -4
- package/dist/bus-hHp-T7JV.js +0 -1
- package/dist/event-0RIBGYqS.js +0 -1
- package/dist/notrace/bus-BdyvumpX.js +0 -1
- package/dist/notrace/promise-CSLpzwSR.js +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://bundlephobia.com/package/nanoeffects)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Move business logic and side effects out of React, Vue and Svelte components into plain `async` functions, with cancellation built in.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -15,38 +15,37 @@ npm install nanoeffects
|
|
|
15
15
|
|
|
16
16
|
ESM only, no dependencies, types included.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Want to try it first? [Open the playground](https://stackblitz.com/github/nanoeffects/nanoeffects/tree/main/examples/playground): a search box with `debounce` and `latest`, running in your browser, no install. More playgrounds (React) and recipes: [Examples](examples/README.md).
|
|
18
|
+
New project: `npm create nanoeffects@latest my-app` ([Docs](docs/starter.md)). Try it first: [playground](https://stackblitz.com/github/nanoeffects/nanoeffects/tree/main/examples/playground) in your browser, no install.
|
|
21
19
|
|
|
22
20
|
## Create a bus
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
The project is built on the event emitter pattern, also known as [publish–subscribe](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern): every handler is an `on` listener and every message an `emit`. You rarely need to think about it, because policies, actions and modules (below) do the work. Full API of the bus (`once`, `off`, options): [Guide](docs/guide.md#1-create-a-bus).
|
|
25
23
|
|
|
26
24
|
```js
|
|
27
25
|
import { createBus } from "nanoeffects";
|
|
28
26
|
|
|
29
27
|
const bus = createBus(); // event bus; each handler call is a task
|
|
28
|
+
const cart = [];
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
// two independent listeners of one event; on returns the function that unsubscribes
|
|
31
|
+
const unbind = bus.on("cart/added", (item) => analytics.track("add", item));
|
|
32
|
+
bus.on("cart/added", (item) => cart.push(item));
|
|
34
33
|
|
|
35
|
-
bus.emit("
|
|
36
|
-
unbind();
|
|
34
|
+
bus.emit("cart/added", { id: "p1" }); // both listeners run, cart has the item
|
|
35
|
+
unbind(); // stop tracking
|
|
37
36
|
```
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
## Keep the logic out of the component
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
In a SPA, a newer search should abort the older one. Wrap the handler in `latest` and pass `ctx.signal` to `fetch` (and similar APIs).
|
|
40
|
+
A newer search should abort the older one. Put it in a handler outside the component, wrapped in `latest`.
|
|
44
41
|
|
|
45
42
|
```js
|
|
43
|
+
// search.js — no React, Vue or Svelte in this file
|
|
46
44
|
import { createBus } from "nanoeffects";
|
|
47
45
|
import { latest } from "nanoeffects/policies";
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
// createBus — one bus for the logic of the app
|
|
48
|
+
export const bus = createBus();
|
|
50
49
|
|
|
51
50
|
// latest — a newer run aborts the older one
|
|
52
51
|
bus.on(
|
|
@@ -59,40 +58,96 @@ bus.on(
|
|
|
59
58
|
);
|
|
60
59
|
```
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
`ctx.signal` is a standard [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal), built into browsers and Node: `fetch` and many other APIs accept it and stop when it aborts.
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
The handler knows nothing about the UI: it only emits `results`. The component sends `search` and listens to `results`. React has hooks for it (`useEventState`, `useEmitter`: [React](docs/react.md#show-the-last-value-of-an-event-as-state)), and [Vue](docs/vue.md) and [Svelte](docs/svelte.md) have their own helpers:
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
```jsx
|
|
66
|
+
// SearchBox.jsx
|
|
67
|
+
import { useEffect, useState } from "react";
|
|
68
|
+
import { bus } from "./search";
|
|
69
|
+
|
|
70
|
+
export function SearchBox() {
|
|
71
|
+
const [items, setItems] = useState([]);
|
|
72
|
+
|
|
73
|
+
// on returns the unbind function; returning it removes the listener on unmount
|
|
74
|
+
useEffect(() => bus.on("results", setItems), []);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<>
|
|
78
|
+
<input onChange={(event) => bus.emit("search", event.target.value)} />
|
|
79
|
+
<ul>
|
|
80
|
+
{items.map((item) => (
|
|
81
|
+
<li key={item.id}>{item.title}</li>
|
|
82
|
+
))}
|
|
83
|
+
</ul>
|
|
84
|
+
</>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Load data and await the result
|
|
90
|
+
|
|
91
|
+
Give an action a handler, and `emit` returns its result. The caller does not import the request.
|
|
67
92
|
|
|
68
93
|
```js
|
|
69
94
|
import { createBus } from "nanoeffects";
|
|
70
|
-
import {
|
|
95
|
+
import { createAction } from "nanoeffects/actions";
|
|
71
96
|
|
|
72
97
|
const bus = createBus();
|
|
73
98
|
|
|
74
|
-
//
|
|
75
|
-
const
|
|
99
|
+
// createAction with a handler — emit returns what the handler returns
|
|
100
|
+
const getUser = createAction("user/get", async (id, ctx) => {
|
|
101
|
+
const response = await fetch(`/users/${id}`, { signal: ctx.signal });
|
|
102
|
+
return response.json();
|
|
103
|
+
});
|
|
76
104
|
|
|
77
|
-
const
|
|
105
|
+
const user = await bus.emit(getUser("1"));
|
|
78
106
|
```
|
|
79
107
|
|
|
80
|
-
|
|
108
|
+
This is one way to load data. If you already use React Query or SWR, keep them: see [Query libraries](docs/query-libraries.md).
|
|
109
|
+
|
|
110
|
+
## Take dependencies from the context
|
|
111
|
+
|
|
112
|
+
Put an API client, a store or a logger on every task once. A test passes a fake one. Here the client is an [axios](https://axios-http.com) instance, but any object works.
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import axios from "axios";
|
|
116
|
+
import { createBus } from "nanoeffects";
|
|
117
|
+
|
|
118
|
+
const api = axios.create({ baseURL: "/api" });
|
|
119
|
+
|
|
120
|
+
// context — every task gets these fields: the bus is the container for your dependencies
|
|
121
|
+
const bus = createBus({ context: { api } });
|
|
122
|
+
|
|
123
|
+
bus.on("save", async (draft, ctx) => {
|
|
124
|
+
await ctx.api.put("/drafts", draft, { signal: ctx.signal });
|
|
125
|
+
});
|
|
126
|
+
```
|
|
81
127
|
|
|
82
128
|
## Docs
|
|
83
129
|
|
|
84
|
-
Start with the [Guide](docs/guide.md)
|
|
130
|
+
Start with the [Guide](docs/guide.md), or jump by need:
|
|
85
131
|
|
|
86
132
|
| Need | Page |
|
|
87
133
|
| ---- | ---- |
|
|
88
134
|
| Async UI races (search, submit) | [Policies](docs/policies.md) |
|
|
89
135
|
| Retry, timeout, wait for events | [Effects](docs/effects.md) |
|
|
90
|
-
| Domain logic off the UI | [Actions,
|
|
91
|
-
| Redux / Zustand / MobX | [Stores](docs/stores.md) |
|
|
136
|
+
| Domain logic off the UI | [Actions, handlers, modules](docs/actions.md) |
|
|
137
|
+
| Redux / Zustand / MobX / Pinia next to the bus | [Stores](docs/stores.md) |
|
|
138
|
+
| Coming from redux-saga, RxJS or a small emitter | [redux-saga](docs/migrating-from-saga.md), [RxJS](docs/migrating-from-rxjs.md), [mitt and nanoevents](docs/migrating-from-mitt.md) |
|
|
92
139
|
| See what ran and why (console, Redux DevTools) | [Tracing](docs/tracing.md) |
|
|
93
140
|
|
|
94
|
-
[Full index and package entries](docs/README.md) · [Examples](examples/README.md)
|
|
141
|
+
[Full index and package entries](docs/README.md) · [Examples](examples/README.md)
|
|
142
|
+
|
|
143
|
+
## Why
|
|
144
|
+
|
|
145
|
+
Requests, timers and races pile up in components, so the logic goes into services. Those need cancel, retry, shared dependencies and a way to see what ran. [redux-saga](https://redux-saga.js.org) does it with generators, [RxJS](https://rxjs.dev) with streams. nanoeffects keeps plain `async` functions and adds one idea, the built-in [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal).
|
|
146
|
+
|
|
147
|
+
The bus is only the heart: any emitter ([`nanoevents`](https://github.com/ai/nanoevents) is ~100 bytes, [many more](https://github.com/gajus/sister#similar-libraries)) can send events. On top come cancellable tasks, a context for dependencies, actions and modules per domain, and tracing with Redux DevTools.
|
|
148
|
+
|
|
149
|
+
- **Plain `async` functions.** No generators, no streams.
|
|
150
|
+
- **Fits what you have.** Recipes for [Redux Toolkit, Zustand, MobX and Pinia](docs/stores.md), an [RxJS](docs/migrating-from-rxjs.md) bridge, helpers for [React](docs/react.md), [Vue](docs/vue.md) and [Svelte](docs/svelte.md).
|
|
151
|
+
- **Tiny, no dependencies.** `createBus` is about 1.4 kB gzip (1.3 kB brotli). Safe inside an SDK.
|
|
95
152
|
|
|
96
|
-
|
|
97
|
-
- **Cancellation first.** Aborting a task aborts its children and drops its result.
|
|
98
|
-
- **One model** instead of hand-rolled `AbortController`, lodash debounce, and retry glue.
|
|
153
|
+
More: [Why nanoeffects exists](docs/motivation.md).
|
|
@@ -36,6 +36,27 @@ type UnsubscribeCallback = () => void;
|
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/core/store.d.ts
|
|
38
38
|
declare const anyEventType = "*";
|
|
39
|
+
type AnyType = "*";
|
|
40
|
+
interface UnsubscribeTask<E extends EventMap> {
|
|
41
|
+
(task: Task<DataOf<E[Keys<E>]>, E>): void;
|
|
42
|
+
<K extends AnyType>(key: K, task?: Task<DataOf<E[Keys<E>]>, E>): void;
|
|
43
|
+
<K extends Keys<E>>(key: K, task?: Task<DataOf<E[K]>, E>): void;
|
|
44
|
+
}
|
|
45
|
+
type Store<E extends EventMap> = {
|
|
46
|
+
get: {
|
|
47
|
+
/** Every listener of every event, in the order of the events. */
|
|
48
|
+
(): Task<DataOf<E[Keys<E>]>, E>[];
|
|
49
|
+
(key: AnyType): Task<DataOf<E[Keys<E>]>, E>[];
|
|
50
|
+
<K extends Keys<E>>(key: K): Task<DataOf<E[K]>, E>[];
|
|
51
|
+
};
|
|
52
|
+
add: {
|
|
53
|
+
(key: AnyType, task: Task<DataOf<E[Keys<E>]>, E>): UnsubscribeCallback;
|
|
54
|
+
<K extends Keys<E>>(key: K, task: Task<DataOf<E[K]>, E>): UnsubscribeCallback;
|
|
55
|
+
};
|
|
56
|
+
remove: UnsubscribeTask<E>;
|
|
57
|
+
/** Drops every key; lists already handed out by `get` stay as they were. */
|
|
58
|
+
clear: () => void;
|
|
59
|
+
};
|
|
39
60
|
//#endregion
|
|
40
61
|
//#region src/core/tracer.d.ts
|
|
41
62
|
/**
|
|
@@ -71,7 +92,7 @@ interface Tracer<Ref extends object = object> {
|
|
|
71
92
|
/** Subscribes to every event; handlers receive the payload of any of them. */
|
|
72
93
|
type AnyEvent = typeof anyEventType;
|
|
73
94
|
type EventKey<E extends EventMap> = Keys<E>;
|
|
74
|
-
type EventPayload<E extends EventMap> = E[EventKey<E>]
|
|
95
|
+
type EventPayload<E extends EventMap> = DataOf<E[EventKey<E>]>;
|
|
75
96
|
type WithType<K extends string> = {
|
|
76
97
|
type: K;
|
|
77
98
|
};
|
|
@@ -91,7 +112,7 @@ type WithSignal = {
|
|
|
91
112
|
type HandlerRef<E extends EventMap, Response = unknown> = (action: Action<E>) => Response;
|
|
92
113
|
type Handler<E extends EventMap, Response = unknown, K extends EventKey<E> = EventKey<E>> = { [P in K]: {
|
|
93
114
|
type: P;
|
|
94
|
-
(payload: E[P]): Response;
|
|
115
|
+
(payload: DataOf<E[P]>): Response;
|
|
95
116
|
}; }[K];
|
|
96
117
|
type Action<E extends EventMap> = {
|
|
97
118
|
type: EventKey<E>;
|
|
@@ -125,35 +146,45 @@ type Command<P = never, R = unknown> = {
|
|
|
125
146
|
readonly wrap?: (run: (payload: never, ctx: never) => unknown) => (payload: never, ctx: never) => unknown;
|
|
126
147
|
};
|
|
127
148
|
/**
|
|
128
|
-
* What the bus needs to run
|
|
129
|
-
* `nanoeffects/actions`, holds the handlers bound to
|
|
130
|
-
* right one, so a bus without `
|
|
149
|
+
* What the bus needs to run the handlers of actions. The implementation,
|
|
150
|
+
* `actionsPlugin` in `nanoeffects/actions`, holds the handlers bound to
|
|
151
|
+
* actions and runs the right one, so a bus without `actions` carries none of
|
|
152
|
+
* that. `bound` tells, for an event type, whether a handler is bound to it: an
|
|
153
|
+
* action with no handler of its own is a command only then. A runner that has
|
|
154
|
+
* no `bound` runs commands only.
|
|
131
155
|
*/
|
|
132
|
-
interface
|
|
156
|
+
interface Actions {
|
|
133
157
|
run(command: Command, payload: unknown, ctx: unknown): unknown;
|
|
158
|
+
bound?(type: string): Command | undefined;
|
|
134
159
|
}
|
|
135
160
|
/** Anything `emit` takes as its first argument: an event type, an action or a command. */
|
|
136
161
|
type Emittable<E extends EventMap> = EventKey<E> | Command | CommandCall | EventLike<E>;
|
|
137
162
|
type Emit<E extends EventMap> = {
|
|
138
|
-
|
|
163
|
+
/**
|
|
164
|
+
* On a bus without an event map the caller can say what a handler bound for
|
|
165
|
+
* the type returns: `bus.emit<string>("user/getId")`. With a map the parameter
|
|
166
|
+
* is `never`, so this form is not taken and no check of names or payloads is lost.
|
|
167
|
+
*/
|
|
168
|
+
<R = void>(type: string extends EventKey<E> ? string : never, ...payload: unknown[]): R;
|
|
169
|
+
<K extends EventKey<E>>(event: K, ...payload: PayloadOf<DataOf<E[K]>>): ResultOf<E[K]>;
|
|
139
170
|
/** Before Handler: a command is callable too, and must return its result type. */
|
|
140
171
|
<P, R>(command: Command<P, R>, ...payload: PayloadOf<P>): R;
|
|
141
172
|
/** A scope as the second argument replaces context fields for the tasks of this emit; see `scopePlugin`. */
|
|
142
173
|
<P, R, F>(call: CommandCall<P, R> & WithScope<F>, scope?: EmitScope<E, F>): R;
|
|
143
174
|
<P, R>(call: CommandCall<P, R>, scope?: EmitScope<E>): R;
|
|
144
|
-
<K extends EventKey<E>, R>(event: Handler<E, R, K>, ...payload: PayloadOf<E[K]
|
|
175
|
+
<K extends EventKey<E>, R>(event: Handler<E, R, K>, ...payload: PayloadOf<DataOf<E[K]>>): R;
|
|
145
176
|
<F>(event: EventLike<E> & WithScope<F>, scope?: EmitScope<E, F>): void;
|
|
146
177
|
(event: EventLike<E>, scope?: EmitScope<E>): void;
|
|
147
178
|
};
|
|
148
179
|
type On<E extends EventMap> = {
|
|
149
180
|
(event: AnyEvent, fn: Task<EventPayload<E>, E>, options?: ListenerOptions): UnsubscribeCallback;
|
|
150
|
-
<K extends EventKey<E>>(event: K, fn: Task<E[K]
|
|
181
|
+
<K extends EventKey<E>>(event: K, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
|
|
151
182
|
/** An action creator without a payload type: the payload comes from the event map. */
|
|
152
183
|
/** The creators and commands that carry a scope come first: the handler sees their fields. */
|
|
153
|
-
<K extends EventKey<E>, F>(creator: FreeActionCreator<K, F> & WithScope<F>, fn: Task<E[K]
|
|
184
|
+
<K extends EventKey<E>, F>(creator: FreeActionCreator<K, F> & WithScope<F>, fn: Task<DataOf<E[K]>, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
|
|
154
185
|
<P, F>(creator: ActionCreator<P, string, PayloadOf<P>, F> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
|
|
155
186
|
<P, F>(command: Command<P, unknown> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
|
|
156
|
-
<K extends EventKey<E>>(creator: FreeActionCreator<K>, fn: Task<E[K]
|
|
187
|
+
<K extends EventKey<E>>(creator: FreeActionCreator<K>, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
|
|
157
188
|
/** An action creator: the payload comes from it, so an event map is not needed. */
|
|
158
189
|
<P>(creator: ActionCreator<P>, fn: Task<P, E>, options?: ListenerOptions): UnsubscribeCallback;
|
|
159
190
|
/** A command: the payload comes from it too. */
|
|
@@ -162,7 +193,7 @@ type On<E extends EventMap> = {
|
|
|
162
193
|
type: K;
|
|
163
194
|
}>(event: Event & {
|
|
164
195
|
type: K;
|
|
165
|
-
}, fn: Task<E[K]
|
|
196
|
+
}, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
|
|
166
197
|
};
|
|
167
198
|
type Off<E extends EventMap> = {
|
|
168
199
|
/** Removes every listener of every event (including `"*"`). */
|
|
@@ -170,12 +201,12 @@ type Off<E extends EventMap> = {
|
|
|
170
201
|
(event: AnyEvent): void;
|
|
171
202
|
(event: AnyEvent, fn: Task<EventPayload<E>, E>): void;
|
|
172
203
|
<K extends EventKey<E>>(event: K): void;
|
|
173
|
-
<K extends EventKey<E>>(event: K, fn: Task<E[K]
|
|
204
|
+
<K extends EventKey<E>>(event: K, fn: Task<DataOf<E[K]>, E>): void;
|
|
174
205
|
<K extends EventKey<E>, Event extends {
|
|
175
206
|
type: K;
|
|
176
207
|
}>(event: Event & {
|
|
177
208
|
type: K;
|
|
178
|
-
}, fn: Task<E[K]
|
|
209
|
+
}, fn: Task<DataOf<E[K]>, E>): void;
|
|
179
210
|
<P>(command: Command<P, unknown>, fn?: Task<P, E>): void;
|
|
180
211
|
};
|
|
181
212
|
declare const contextKey: unique symbol;
|
|
@@ -239,6 +270,24 @@ interface Bus<E extends EventMap> {
|
|
|
239
270
|
*/
|
|
240
271
|
once: On<E>;
|
|
241
272
|
off: Off<E>;
|
|
273
|
+
/**
|
|
274
|
+
* The listeners an event has right now, in the order they run: what `on`,
|
|
275
|
+
* `once`, `ctx.on` and the `on` of a module registered, as the bus holds them
|
|
276
|
+
* (a plugin may have wrapped a function, so compare the length, not the
|
|
277
|
+
* functions). It takes the event name as a string, as the bus stores it, not
|
|
278
|
+
* an action creator: use `creator.type`. `"*"` gives the any-event listeners,
|
|
279
|
+
* which a named event does not include. The array is not changed afterwards: a later `on` or unbind
|
|
280
|
+
* gives the next `get` a new one.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* const unbind = bus.on("saved", save);
|
|
285
|
+
* bus.get("saved").length; // 1
|
|
286
|
+
* unbind();
|
|
287
|
+
* bus.get("saved").length; // 0
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
get: Store<E>["get"];
|
|
242
291
|
emit: Emit<E>;
|
|
243
292
|
/**
|
|
244
293
|
* Calls `plugin` with the bus and returns what it returns: an api, a
|
|
@@ -246,10 +295,10 @@ interface Bus<E extends EventMap> {
|
|
|
246
295
|
* no list of them. See `modulePlugin` in `nanoeffects/actions`.
|
|
247
296
|
*/
|
|
248
297
|
use<R>(plugin: (bus: Bus<E>) => R): R;
|
|
249
|
-
/** `BusOptions.context` and `.trace`, and `
|
|
298
|
+
/** `BusOptions.context` and `.trace`, and `actions`, for what makes tasks of its own, like `modulePlugin`. */
|
|
250
299
|
readonly ctx?: ContextOption<E> | undefined;
|
|
251
|
-
/** What runs the
|
|
252
|
-
|
|
300
|
+
/** What runs the handlers of actions; `actionsPlugin` and `modulePlugin` set it. Without one a command runs its own handler. */
|
|
301
|
+
actions?: Actions | undefined;
|
|
253
302
|
readonly trace?: Tracer | undefined;
|
|
254
303
|
/** Called with every new task context to add fields to it, for what needs the task, like `effectsPlugin`. Chain to the previous one. */
|
|
255
304
|
addContext?: ((ctx: object) => void) | undefined;
|
|
@@ -267,8 +316,8 @@ type BusOptions<E extends EventMap> = {
|
|
|
267
316
|
onError?: (error: unknown, event: Action<E>) => void;
|
|
268
317
|
/**
|
|
269
318
|
* Called when an event is emitted and nobody listens to it: the usual sign
|
|
270
|
-
* of a typo in an event name. Not called for commands,
|
|
271
|
-
* handler to run. Typically a warning in development only.
|
|
319
|
+
* of a typo in an event name. Not called for commands, nor for an action with
|
|
320
|
+
* a handler bound in `actions`, which always have a handler to run. Typically a warning in development only.
|
|
272
321
|
*
|
|
273
322
|
* @example
|
|
274
323
|
* ```ts
|
|
@@ -360,15 +409,33 @@ type Merge<A, B> = Omit<A, keyof B> & B;
|
|
|
360
409
|
type WithFields<E extends EventMap, F> = [unknown] extends [F] ? E : Omit<E, keyof WithContext<object>> & WithContext<Merge<ContextOf<E>, F>>;
|
|
361
410
|
//#endregion
|
|
362
411
|
//#region src/core/action-creator.d.ts
|
|
363
|
-
type WithPayload<E extends EventMap, K extends Keys<E>> = undefined extends E[K] ? {
|
|
412
|
+
type WithPayload<E extends EventMap, K extends Keys<E>> = undefined extends DataOf<E[K]> ? {
|
|
364
413
|
type: K;
|
|
365
|
-
payload?: E[K]
|
|
414
|
+
payload?: DataOf<E[K]>;
|
|
366
415
|
} : {
|
|
367
416
|
type: K;
|
|
368
|
-
payload: E[K]
|
|
417
|
+
payload: DataOf<E[K]>;
|
|
369
418
|
};
|
|
370
419
|
type Absent<P> = [P] extends [void] ? undefined : P;
|
|
371
420
|
type Made<P, T extends string> = WithPayload<{ [K in T]: Absent<P>; }, T>;
|
|
421
|
+
declare const callBrand: unique symbol;
|
|
422
|
+
/**
|
|
423
|
+
* A payload type together with the type of what a handler of the action
|
|
424
|
+
* returns, for an event map or `createAction`:
|
|
425
|
+
* `type Events = { "user/getId": Call<void, string> }`, and then
|
|
426
|
+
* `bus.emit("user/getId")` is a `string`. A type only: it adds nothing to a
|
|
427
|
+
* bundle, and an entry that is not a `Call` means a payload, with no result.
|
|
428
|
+
*/
|
|
429
|
+
type Call<P = void, R = void> = {
|
|
430
|
+
readonly [callBrand]: {
|
|
431
|
+
payload: P;
|
|
432
|
+
result: R;
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
/** The payload type of an entry of an event map: the `P` of a `Call<P, R>`, the entry itself otherwise. */
|
|
436
|
+
type DataOf<T> = T extends Call<infer P, unknown> ? P : T;
|
|
437
|
+
/** What `emit` returns for an entry of an event map: the `R` of a `Call<P, R>`, `void` otherwise. */
|
|
438
|
+
type ResultOf<T> = T extends Call<unknown, infer R> ? R : void;
|
|
372
439
|
declare const free: unique symbol;
|
|
373
440
|
type Free = typeof free;
|
|
374
441
|
/**
|
|
@@ -411,4 +478,4 @@ interface ActionCreator<P = void, T extends string = string, A extends unknown[]
|
|
|
411
478
|
toString(): T;
|
|
412
479
|
}
|
|
413
480
|
//#endregion
|
|
414
|
-
export {
|
|
481
|
+
export { EventsOf as A, Tracer as B, ContextOf as C, EventKey as D, Emittable as E, WithContext as F, PayloadOf as G, EventMap as H, WithSignal as I, Trace as J, Phase as K, WithType as L, HandlerRef as M, Off as N, EventLike as O, On as P, commandCall as R, Context as S, Emit as T, Keys as U, EffectName as V, ListenerOptions as W, TraceLogger as X, TraceEvent as Y, UnsubscribeCallback as Z, AnyEvent as _, FreeActionCreator as a, Command as b, Scope as c, BoundForm as d, Effect as f, Actions as g, Action as h, Free as i, Handler as j, EventPayload as k, WithFields as l, Signaled as m, Call as n, WithPayload as o, Effects as p, Task as q, DataOf as r, EmitScope as s, ActionCreator as t, WithScope as u, Bus as v, ContextOption as w, CommandCall as x, BusOptions as y, createBus as z };
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as Scoped, t as FieldsOfScope } from "./types-
|
|
3
|
-
import { a as createModule, c as CarryingCalls, d as
|
|
1
|
+
import { D as EventKey, G as PayloadOf, H as EventMap, a as FreeActionCreator, c as Scope, i as Free, n as Call, q as Task, t as ActionCreator, u as WithScope, v as Bus } from "./action-creator-CcAEvUnw.js";
|
|
2
|
+
import { r as Scoped, t as FieldsOfScope } from "./types-FV8fuvI9.js";
|
|
3
|
+
import { a as createModule, c as CarryingCalls, d as actionsPlugin, f as setHandler, l as MadeCommand, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as Binding, t as Module, u as ScopedCommand } from "./module-C_oEXw1n.js";
|
|
4
4
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
5
5
|
//#region src/actions/action.d.ts
|
|
6
|
+
type Reserved = "handle" | "prepare";
|
|
7
|
+
type Made<P, T extends string> = [P] extends [Free] ? FreeActionCreator<T> : [P] extends [Call<infer Q, infer R>] ? MadeCommand<Q, R, T> : ActionCreator<P, T>;
|
|
6
8
|
type ScopedCreator<P, T extends string, F> = [P] extends [Free] ? FreeActionCreator<T, F> & WithScope<F> : ActionCreator<P, T, PayloadOf<P>, F> & WithScope<F>;
|
|
9
|
+
type ScopeOf<S> = Omit<S, Reserved>;
|
|
10
|
+
type PreparedCommand<P, R, T extends string, A extends unknown[], F> = ((...args: A) => ReturnType<MadeCommand<P, R, T>> & WithScope<F>) & Omit<MadeCommand<P, R, T>, never> & WithScope<F>;
|
|
7
11
|
/**
|
|
8
|
-
* Creates an action creator, as in Redux Toolkit.
|
|
12
|
+
* Creates an action creator, as in Redux Toolkit. With a handler it makes a
|
|
13
|
+
* command: `bus.emit(getUser("1"))` runs the handler and returns its result.
|
|
9
14
|
*
|
|
10
15
|
* - `createAction("user/loaded")` needs no generics: the payload type comes
|
|
11
16
|
* from the event map of the bus that the action goes to, and the literal
|
|
12
|
-
* type of the action is kept.
|
|
17
|
+
* type of the action is kept. An action with no handler is an event.
|
|
13
18
|
* - `createAction<User>("user/loaded")` gives the payload type, for a bus
|
|
14
19
|
* without an event map or to check the calls of the creator. The type of
|
|
15
20
|
* the action is then `string`; to keep the literal, give it as the second
|
|
16
21
|
* generic: `createAction<User, "user/loaded">("user/loaded")`.
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
* - A
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
+
* - `createAction<Call<Mail, void>>("mail/send")` also says what a handler
|
|
23
|
+
* bound later returns; see `Call`.
|
|
24
|
+
* - A function as the second argument is the handler: it gets the payload and
|
|
25
|
+
* the context of the task, and `emit` returns what it returns. It can be
|
|
26
|
+
* wrapped in a policy, e.g. `latest(fn)`. A handler bound for the type in
|
|
27
|
+
* `actionsPlugin` wins over it.
|
|
28
|
+
* - The options object, as the second argument or the third after a handler,
|
|
29
|
+
* is `{ handle, prepare, ...scope }`: `handle` is the handler, `prepare`
|
|
30
|
+
* builds the payload from several arguments (both types are inferred), and
|
|
31
|
+
* every other field is the scope. A scope as the last argument,
|
|
32
|
+
* `{ cache, $effects: { race } }`, puts those fields on the context of the
|
|
33
|
+
* handler and of the listeners of its calls; it works on a bus that uses
|
|
34
|
+
* `scopePlugin` from `nanoeffects/scope` and is ignored on any other.
|
|
22
35
|
*
|
|
23
36
|
* @example
|
|
24
37
|
* ```ts
|
|
@@ -27,22 +40,42 @@ type ScopedCreator<P, T extends string, F> = [P] extends [Free] ? FreeActionCrea
|
|
|
27
40
|
* added.type; // "counter/added"
|
|
28
41
|
* added.match(action); // true for actions of this type
|
|
29
42
|
*
|
|
30
|
-
* const renamed = createAction("user/renamed",
|
|
31
|
-
* payload: { id, name },
|
|
32
|
-
* })
|
|
43
|
+
* const renamed = createAction("user/renamed", {
|
|
44
|
+
* prepare: (id: string, name: string) => ({ payload: { id, name } }),
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* const getUser = createAction("user/get", (id: string, { signal }) =>
|
|
48
|
+
* fetchUser(id, { signal }),
|
|
49
|
+
* );
|
|
50
|
+
* const user = await bus.emit(getUser("1"));
|
|
33
51
|
*
|
|
34
52
|
* bus.emit(added(2));
|
|
35
53
|
* bus.on(added, (n) => console.log(n));
|
|
36
54
|
* ```
|
|
37
55
|
*/
|
|
38
|
-
export declare function createAction<P = Free, T extends string = string>(type: T):
|
|
39
|
-
export declare function createAction<
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
export declare function createAction<P = Free, T extends string = string>(type: T): Made<P, T>;
|
|
57
|
+
export declare function createAction<P = void, R = void, T extends string = string, E extends EventMap = EventMap>(type: T, handler: Task<P, E, R>): MadeCommand<P, R, T>;
|
|
58
|
+
export declare function createAction<P, R, A extends unknown[], T extends string, S extends Scope = Record<never, never>>(type: T, handler: Task<P, Scoped<EventMap, ScopeOf<S>>, R>, options: {
|
|
59
|
+
prepare: (...args: A) => {
|
|
60
|
+
payload: P;
|
|
61
|
+
};
|
|
62
|
+
} & S): PreparedCommand<P, R, T, A, FieldsOfScope<EventMap, ScopeOf<S>>>;
|
|
63
|
+
export declare function createAction<P, R, A extends unknown[], T extends string, S extends Scope = Record<never, never>>(type: T, options: {
|
|
64
|
+
handle: Task<P, Scoped<EventMap, ScopeOf<S>>, R>;
|
|
65
|
+
prepare: (...args: A) => {
|
|
66
|
+
payload: P;
|
|
67
|
+
};
|
|
68
|
+
} & S): PreparedCommand<P, R, T, A, FieldsOfScope<EventMap, ScopeOf<S>>>;
|
|
69
|
+
export declare function createAction<P, R, T extends string, S extends Scope = Record<never, never>>(type: T, handler: Task<P, Scoped<EventMap, S>, R>, scope: S): ScopedCommand<P, R, T, FieldsOfScope<EventMap, S>>;
|
|
70
|
+
export declare function createAction<P, R, T extends string, S extends Scope = Record<never, never>>(type: T, options: {
|
|
71
|
+
handle: Task<P, Scoped<EventMap, ScopeOf<S>>, R>;
|
|
72
|
+
} & S): ScopedCommand<P, R, T, FieldsOfScope<EventMap, ScopeOf<S>>>;
|
|
73
|
+
export declare function createAction<A extends unknown[], P, T extends string, S extends Scope = Record<never, never>>(type: T, options: {
|
|
74
|
+
prepare: (...args: A) => {
|
|
75
|
+
payload: P;
|
|
76
|
+
};
|
|
77
|
+
} & S): ActionCreator<P, T, A, FieldsOfScope<EventMap, ScopeOf<S>>> & WithScope<FieldsOfScope<EventMap, ScopeOf<S>>>;
|
|
42
78
|
export declare function createAction<P = Free, T extends string = string, S extends Scope = Record<never, never>>(type: T, scope: S): ScopedCreator<P, T, FieldsOfScope<EventMap, S>>;
|
|
43
|
-
export declare function createAction<A extends unknown[], P, T extends string, S extends Scope>(type: T, prepare: (...args: A) => {
|
|
44
|
-
payload: P;
|
|
45
|
-
}, scope: S): ActionCreator<P, T, A, FieldsOfScope<EventMap, S>> & WithScope<FieldsOfScope<EventMap, S>>;
|
|
46
79
|
//#endregion
|
|
47
80
|
//#region src/actions/emitter.d.ts
|
|
48
81
|
/** What `emitterPlugin` adds to the bus. */
|
|
@@ -161,4 +194,4 @@ export declare const createJob: <P = void, R = void, T extends string = string,
|
|
|
161
194
|
/** Context values and `$effects` for the handler and for the listeners of the outcome; see `scopePlugin`. */
|
|
162
195
|
scope?: X) => CarryingCalls<Job<P, R, T, S, F, PE, CE>, P, Promise<Awaited<R> | undefined>, FieldsOfScope<E, X>>;
|
|
163
196
|
//#endregion
|
|
164
|
-
export { type ActionCreator, type Binding, type EmitterApi, type FreeActionCreator, type Job, type Module, type ModuleApi, type ModuleContext,
|
|
197
|
+
export { type ActionCreator, type Binding, type EmitterApi, type FreeActionCreator, type Job, type Module, type ModuleApi, type ModuleContext, actionsPlugin, createModule, modulePlugin, setHandler };
|
package/dist/actions.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as e,i as t,l as n,n as r,u as i}from"./context-UcmrAIhP.js";import{t as a}from"./event-
|
|
1
|
+
import{d as e,i as t,l as n,n as r,u as i}from"./context-UcmrAIhP.js";import{t as a}from"./event-DVcW0mME.js";import{r as o}from"./bus-DlpEluzd.js";import{n as s,t as c}from"./lifecycle-key-8iX8RUVD.js";import{t as l}from"./origin-key-BbWN3gmN.js";import{t as u}from"./scope-key-B7l7mUS5.js";import{t as d}from"./mount-each-D54UqAhZ.js";const f=(e,t)=>(t&&Object.defineProperty(e,u,{value:t}),e),p=(e,t)=>({...e,...t,$effects:{...e.$effects,...t.$effects}}),m=e=>Reflect.get(e,u),h=e=>{let t=Object.assign(n=>o(t,e,n),{type:e});return t},g=e=>typeof e==`object`&&!!e&&Reflect.get(e,`signal`)instanceof AbortSignal&&typeof Reflect.get(e,`emit`)==`function`;var _=class extends Error{};function v(e,t,n){return y(e,t,n)}function y(e,t,n,r){let i=t=>t.type===e,a=e=>r?e.length===2&&g(e[1]):typeof e[1]==`object`;function s(...i){let[s,c]=i;if(a(i)){if(!t)throw new _(`No handler for command "${e}"`);return t(s,c)}let u=r&&Reflect.apply(r,null,i),d=u?u.payload:s;return f(o(l,e,d),n)}let c=Object.assign(s,{type:e,match:i,toString:()=>e}),l=f(c,n);return l}function b(e,t){return[e,t]}const x=e=>typeof Reflect.get(e??{},`handle`)==`function`,S=(e=[])=>t=>{let n=t.actions;if(x(n))return n.handle(e),n;let r=/* @__PURE__ */ new Map,i=(e,t)=>{let n={fn:t};return r.set(e,[...r.get(e)??[],n]),()=>{let t=(r.get(e)??[]).filter(e=>e!==n);t.length>0?r.set(e,t):r.delete(e)}};function o(e,t){if(t)return i(a(e),t);let n=e.map(([e,t])=>i(a(e),t));return()=>{for(let e of n)e()}}o(e);let s={run:(e,t,n)=>{let i=(r.get(e.type)??[]).at(-1)?.fn,a=i&&e.wrap?e.wrap(i):i??e;return Reflect.apply(a,null,[t,n])},handle:o,bound:e=>r.has(e)?h(e):void 0};return t.actions=s,s};function C(e,t,n){let{handle:r,prepare:i,scope:a}=w(typeof t==`function`?n:t),o=typeof t==`function`?t:r;return o?y(e,o,a,i):Object.assign(f((...t)=>{let n=i&&Reflect.apply(i,null,t);return f({type:e,payload:n?n.payload:t[0]},a)},a),{type:e,match:t=>t.type===e,toString:()=>e})}const w=e=>{if(!e)return{};let{handle:t,prepare:n,...r}=e,i=typeof t==`function`,a=typeof n==`function`;if(!i&&!a)return{scope:e};let o=Object.keys(r).length>0?r:void 0;return{...i&&{handle:t},...a&&{prepare:n},...o&&{scope:o}}},T=()=>e=>{function t(t,n){return(...r)=>{let i=t(...r),a=Reflect.get(e,l);a?a(i,n):e.emit(i)}}return Object.assign(e,{emitter:t})},E=e=>typeof e==`string`?C(e):e,D=(e,t,n,r)=>{let i=m(t);e.emit(Reflect.apply(t,null,[n]),r&&i?p(r,i):r)},O=(t,r,i,a)=>{let o=t;o[n]=!0;try{D(t,r,i,a)}catch(t){e(`cancel listener`,t)}o[n]=!1},k=e=>{try{return Promise.resolve(e())}catch(e){if(e instanceof _)throw e;return Promise.reject(e)}},A=(t,n,r={},a)=>{let l=v(t,n),u=e=>E(r[e]??`${t}/${e}`),d=u(`pending`),p=u(`success`),m=u(`fail`),h=u(`cancel`),g=(t,n,r,o)=>{let s=r,l=`idle`,u=()=>{},f=()=>{l=`closed`,u()},g=e=>{l===`started`&&(f(),O(s,h,e,a))},_=()=>{l===`idle`&&(l=`started`,u=i(s,g),D(s,d,n,a))},v=e=>{l===`started`&&(f(),s.signal.aborted?O(s,h,s.signal.reason,a):`error`in e?D(s,m,e.error,a):D(s,p,e.value,a))};return Reflect.set(s,c,{start:_,cancel:g,done:v,drop:()=>{l===`idle`&&(l=`closed`)}}),k(()=>(o||_(),Reflect.apply(t,null,[n,r]))).then(e=>(v({value:e}),e),t=>{if(l===`idle`)try{_()}catch(t){e(`pending listener`,t)}v({error:t})})},_=e=>{let t=Reflect.get(e,s)===!0;return(n,r)=>g(e,n,r,t)},y=Reflect.get(n??{},s)===!0;function b(e,r){return typeof r==`object`?n?g(l,e,r,y):Reflect.apply(l,null,[e,r]):f(o(S,t,e),a)}let x=Object.assign(b,{type:t,match:l.match,wrap:_,pending:d,success:p,fail:m,cancel:h}),S=f(x,a);return S},j=e=>typeof e==`object`&&!!e,M=e=>{if(typeof e==`string`)return e;if(j(e)||typeof e==`function`){let t=Reflect.get(e,`type`);return typeof t==`string`?t:e}return e},N=(e,t)=>{let[n,r]=e;return n===void 0||Object.is(M(n),M(t[0]))&&(r===void 0||Object.is(r,t[1]))},P=e=>{let t={on:e.on,once:e.once,off:e.off},n=[],r=!0,i=(t,n)=>Reflect.apply(t,e,n),a=(e,t)=>(...a)=>{if(!r)return i(t,a);let o={kind:e,args:a,dropped:!1};return n.push(o),()=>{o.live?o.live():o.dropped=!0}},o=e=>(...t)=>{if(!r)return i(e,t);for(let e of n)e.kind!==`off`&&N(t,e.args)&&(e.dropped=!0);n.push({kind:`off`,args:t,dropped:!1})},s=a(`on`,t.on),c=a(`once`,t.once),l=o(t.off);return e.on=s,e.once=c,e.off=l,{release:()=>{r=!1,e.on===s&&(e.on=t.on),e.once===c&&(e.once=t.once),e.off===l&&(e.off=t.off)},replay:()=>{for(let e of n.splice(0))if(!e.dropped){if(e.kind===`off`)i(t.off,e.args);else{let n=e.kind===`on`?t.on:t.once;e.live=i(n,e.args)}}}}};function F(e,t,n){return n?{name:e,setup:t,scope:n}:{name:e,setup:t}}const I=(e,t)=>n=>t?e.fitScope?.(t,n)??n:n,L=(e,t,n)=>{n&&e.applyScope?.(t,n)},R=(e,t,n)=>Array.isArray(t)?[t.map(([t,n])=>[t,e(n)]),n]:[t,e(n)],z=(e,t)=>{let n=e.on;return(...e)=>{let[r,i,...a]=e;return Reflect.apply(n,null,[r,t(i),...a])}},B=e=>(t,...n)=>{e.run(t,...n).catch(t=>{if(!e.signal.aborted)throw t})},V=(n=[])=>a=>{let o=a.actions??S()(a),s={handle:(...e)=>{if(!o.handle)throw Error("modulePlugin: the `actions` of the bus is not a registry from `actionsPlugin()`");return Reflect.apply(o.handle,null,e)}},c=e=>{let n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map;return{mount:o=>{let l=n.get(o);if(l)return l;let u=r.get(o.name);u&&n.get(u)?.();let d=t(e,o.name),f=d.ctx,p=c(f),m=()=>{n.delete(o),r.get(o.name)===o&&r.delete(o.name),f.abort(),d.unlink()};n.set(o,m),r.set(o.name,o);let h=o.scope,g=I(a,h),_=(e,t)=>{let n=Reflect.apply(s.handle,null,R(g,e,t));return i(f,n),n},v=(...e)=>{let t=e.map(e=>typeof e==`function`?_(e,e):p.mount(e));return()=>{for(let e of t)e()}},y=B(f),b=z(f,g);try{L(a,f,h),o.setup(Object.assign(f,{handle:_,use:v,spawn:y,on:b}))}catch(e){throw m(),e}return m},unmount:e=>n.get(e)?.(),isMounted:e=>n.has(e)}},l=P(a),u=a.emit,f=a.get,p,m=(e=!0)=>{if(p)return p;l.release(),a.emit===h&&(a.emit=u);let t=r({event:{type:`app`,payload:void 0},bus:a,tracer:a.trace});p={root:t,apps:d(c(t.ctx))};try{e&&p.apps.mount(...n)}finally{l.replay()}return p},h=(...e)=>(m(),Reflect.apply(u,a,e));a.emit=h,a.get=((...e)=>(m(),Reflect.apply(f,a,e))),n.length>0&&queueMicrotask(()=>{try{m()}catch(t){e(`the modules of the app could not start`,t)}});let g={get actions(){return m(),o},mount:(...e)=>{let{root:t,apps:n}=m();return t.ctx.signal.throwIfAborted(),n.mount(...e)},unmount:(...e)=>m().apps.unmount(...e),isMounted:e=>m().apps.isMounted(e),dispose:()=>m(!1).root.ctx.abort(),createModule:F};return a.app=g,g};export{S as actionsPlugin,C as createAction,A as createJob,F as createModule,T as emitterPlugin,V as modulePlugin,b as setHandler};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as e,n as t,o as n,r}from"./context-UcmrAIhP.js";import{n as i,t as a}from"./event-DVcW0mME.js";const o=()=>{let e={},t={},n=n=>(t[n]=void 0,e[n]??=/* @__PURE__ */ new Map,e[n]),r=(e,t)=>{let r=n(e),i=r.get(t)??0;i>1?r.set(t,i-1):t?r.delete(t):r.clear()},i=()=>{e={},t={}},a=n=>n===void 0?Object.keys(e).flatMap(a):(t[n]??=[...e[n]??[]].flatMap(([e,t])=>Array(t).fill(e)),t[n]);return{get:a,add:(e,t)=>{let i=n(e);return i.set(t,(i.get(t)??0)+1),()=>r(e,t)},remove:r,clear:i}},s=Symbol(),c=(e,t,n)=>{let r={type:t,payload:n};return Object.defineProperty(r,s,{value:e,enumerable:!1}),r},l=e=>{if(typeof e==`function`)return e;if(typeof e==`object`&&e&&s in e)return e[s]},u=(e,t,n)=>Reflect.apply(e,null,[t,n]),d=(s={})=>{let c=o(),d=(e,t)=>c.add(a(e),t),f=(e,t)=>{let n=d(e,(e,r)=>(n(),t(e,r)));return n},p=(e,t)=>{e===void 0?c.clear():c.remove(a(e),t)},m=e=>t({event:e,bus:g,tracer:s.trace,parent:{ref:r()}}).ctx,h=(t,n)=>{let{onError:r}=s,i=m(n);if(!r){t(n.payload,i);return}let a=t=>{try{r(t,n)}catch(t){e(`onError failed`,t)}};try{let e=t(n.payload,i);typeof e?.then==`function`&&Promise.resolve(e).catch(a)}catch(e){a(e)}},g={get:c.get,on:d,off:p,once:f,emit:(e,t)=>{let r=a(e),o=i(e,t),d={type:r,payload:o},f=l(e);f||=g.actions?.bound?.(r);let p=[...c.get(r),...c.get(`*`)];p.length===0&&!f&&s.onUnhandled?.(d);for(let e of p)h(e,d);if(f){let e=m(d),t=g.actions?.run??u;return n(e,`command`,()=>t(f,o,e))}},use:e=>e(g),ctx:s.context,trace:s.trace};return g};export{d as n,c as r,l as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as ContextOf, H as EventMap } from "./action-creator-CcAEvUnw.js";
|
|
2
2
|
//#region src/core/context-types.d.ts
|
|
3
3
|
/** What a function that makes the fields of a task gets to see. */
|
|
4
4
|
type ContextTask = {
|
package/dist/context.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as NoClash, t as ContextTask } from "./context-types-
|
|
1
|
+
import { F as WithContext, H as EventMap, v as Bus } from "./action-creator-CcAEvUnw.js";
|
|
2
|
+
import { n as NoClash, t as ContextTask } from "./context-types-hCKgU8sC.js";
|
|
3
3
|
//#region src/context/plugin.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Puts `fields` on the context of every task of the bus: a store, a client, a
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as WithApp, n as ModuleApi } from "./module-
|
|
1
|
+
import { H as EventMap, Z as UnsubscribeCallback, v as Bus } from "./action-creator-CcAEvUnw.js";
|
|
2
|
+
import { i as WithApp, n as ModuleApi } from "./module-C_oEXw1n.js";
|
|
3
3
|
//#region src/dev/types.d.ts
|
|
4
4
|
/** The parts of what `modulePlugin` returned that the diagnostics report. */
|
|
5
5
|
type ReportedApp<E extends EventMap> = Pick<ModuleApi<E>, "mount" | "unmount" | "isMounted">;
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./event-
|
|
1
|
+
import{t as e}from"./event-DVcW0mME.js";import{t}from"./mount-each-D54UqAhZ.js";const n=`[nanoeffects]`,r=(e={})=>t=>{let{maxListeners:n=10,leaks:r=!0,modules:i=!0,app:s}=e,c=e.log??(e=>console.warn(e)),l=e.log??(e=>console.info(e)),u=[];return r&&u.push(a(t,n,c)),i&&u.push(o(t,s,l)),()=>{for(let e of u.splice(0))e()}},i=t=>typeof t==`function`&&typeof Reflect.get(t,`type`)!=`string`?`*`:e(t),a=(e,t,r)=>{let a=e.on,o=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Set,c=!0,l=(...l)=>{if(!c)return Reflect.apply(a,e,l);let[u]=l,d=i(u),f=(o.get(d)??0)+1;o.set(d,f),f>t&&!s.has(d)&&(s.add(d),r(`${n} ${f} listeners of "${d}" were added and not unsubscribed (more than ${t}). A file that is reloaded and subscribes again, or an unsubscribe that is never called?`));let p=Reflect.apply(a,e,l),m=!1;return()=>{if(!m){m=!0;let e=(o.get(d)??1)-1;o.set(d,e),e<=t&&s.delete(d)}p()}};return e.on=l,()=>{c=!1,e.on===l&&(e.on=a)}},o=(e,t,n)=>{let r=t??e.app;if(r)return s(r,n);let i,a;return Object.defineProperty(e,"app",{configurable:!0,enumerable:!0,get:()=>i,set:e=>{a?.(),i=e,a=e?s(e,n):void 0}}),()=>{a?.(),Object.defineProperty(e,"app",{configurable:!0,enumerable:!0,writable:!0,value:i})}},s=(e,r)=>{let{mount:i,unmount:a}=e,o=/* @__PURE__ */ new Map,s=t({mount:t=>{let a=o.get(t.name);if(a===t&&e.isMounted(t))return i(t);let s=a!==void 0&&e.isMounted(a),c=i(t);return o.set(t.name,t),r(`${n} module "${t.name}" ${s?`replaced`:`mounted`}`),()=>{e.isMounted(t)&&r(`${n} module "${t.name}" unmounted`),c()}},unmount:t=>{e.isMounted(t)&&r(`${n} module "${t.name}" unmounted`),a(t)},isMounted:t=>e.isMounted(t)});return e.mount=s.mount,e.unmount=s.unmount,()=>{e.mount=i,e.unmount=a}};export{r as devPlugin};
|
package/dist/effects.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as RaceStarter, c as all, d as GroupOptions, f as Starter, i as take, l as ChildOf, m as delay, n as effectsPlugin, o as race, p as StarterOf, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-
|
|
1
|
+
import { H as EventMap, I as WithSignal, S as Context, f as Effect, q as Task } from "./action-creator-CcAEvUnw.js";
|
|
2
|
+
import { a as RaceStarter, c as all, d as GroupOptions, f as Starter, i as take, l as ChildOf, m as delay, n as effectsPlugin, o as race, p as StarterOf, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-CuvIgjnX.js";
|
|
3
3
|
//#region src/utils/onAbort.d.ts
|
|
4
4
|
export declare const onAbort: (ctx: {
|
|
5
5
|
signal?: AbortSignal | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=e=>e.type??e,t=(e,t)=>typeof e==`object`?e.payload:t;export{t as n,e as t};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { type Action, type AnyEvent, type Bus, type BusOptions, type
|
|
1
|
+
import { A as EventsOf, C as ContextOf, D as EventKey, E as Emittable, F as WithContext, G as PayloadOf, H as EventMap, I as WithSignal, L as WithType, M as HandlerRef, N as Off, O as EventLike, P as On, S as Context, T as Emit, U as Keys, Z as UnsubscribeCallback, _ as AnyEvent, b as Command, g as Actions, h as Action, j as Handler, k as EventPayload, n as Call, o as WithPayload, q as Task, v as Bus, w as ContextOption, x as CommandCall, y as BusOptions, z as createBus } from "./action-creator-CcAEvUnw.js";
|
|
2
|
+
export { type Action, type Actions, type AnyEvent, type Bus, type BusOptions, type Call, type Command, type CommandCall, type Context, type ContextOf, type ContextOption, type Emit, type Emittable, type EventKey, type EventLike, type EventMap, type EventPayload, type EventsOf, type Handler, type HandlerRef, type Keys, type Off, type On, type PayloadOf, type Task, type UnsubscribeCallback, type WithContext, type WithPayload, type WithSignal, type WithType, createBus };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{n as createBus}from"./bus-
|
|
1
|
+
export{n as createBus}from"./bus-DlpEluzd.js";
|