nanoeffects 0.26.0 → 0.27.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 (58) hide show
  1. package/README.md +76 -23
  2. package/dist/{action-creator-Bpa8BUS9.d.ts → action-creator-D_c223C7.d.ts} +51 -23
  3. package/dist/actions.d.ts +54 -21
  4. package/dist/actions.js +1 -1
  5. package/dist/{bus-hHp-T7JV.js → bus-DQDHUN5e.js} +1 -1
  6. package/dist/{context-types-BKIH5a8s.d.ts → context-types-nGtzhjxD.d.ts} +1 -1
  7. package/dist/context.d.ts +2 -2
  8. package/dist/dev.d.ts +2 -2
  9. package/dist/effects.d.ts +2 -2
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +1 -1
  12. package/dist/match.d.ts +1 -1
  13. package/dist/{module-B6rg5NIb.d.ts → module-WX0Gngnt.d.ts} +40 -57
  14. package/dist/notrace/{action-creator-D2CotugT.d.ts → action-creator-Bux7Zzsl.d.ts} +51 -23
  15. package/dist/notrace/actions.d.ts +114 -98
  16. package/dist/notrace/actions.js +1 -1
  17. package/dist/notrace/{bus-BdyvumpX.js → bus-CGi2lrd5.js} +1 -1
  18. package/dist/notrace/effects.d.ts +2 -2
  19. package/dist/notrace/index.d.ts +2 -2
  20. package/dist/notrace/index.js +1 -1
  21. package/dist/notrace/{plugin-Dz6hq8Jg.d.ts → plugin-CATXOxtj.d.ts} +1 -1
  22. package/dist/notrace/policies.d.ts +1 -1
  23. package/dist/notrace/redux.d.ts +1 -1
  24. package/dist/observable.d.ts +6 -6
  25. package/dist/oop.d.ts +2 -2
  26. package/dist/oop.js +1 -1
  27. package/dist/{plugin-D-j1DarG.d.ts → plugin-vvkmIIz2.d.ts} +2 -2
  28. package/dist/policies.d.ts +2 -2
  29. package/dist/react.d.ts +2 -2
  30. package/dist/redux.d.ts +1 -1
  31. package/dist/scope.d.ts +2 -2
  32. package/dist/signal.d.ts +1 -1
  33. package/dist/signal.js +1 -1
  34. package/dist/svelte.d.ts +1 -1
  35. package/dist/trace.d.ts +1 -1
  36. package/dist/{types-Bkuhnkq6.d.ts → types-Bf-LX_tE.d.ts} +2 -2
  37. package/dist/vue.d.ts +1 -1
  38. package/dist/{with-policy-BeH8wCkX.d.ts → with-policy-CPjx0sLm.d.ts} +1 -1
  39. package/docs/README.md +4 -4
  40. package/docs/actions.md +93 -52
  41. package/docs/chat-example.md +6 -6
  42. package/docs/context.md +1 -1
  43. package/docs/errors.md +1 -1
  44. package/docs/guide.md +25 -25
  45. package/docs/hmr.md +1 -1
  46. package/docs/motivation.md +10 -4
  47. package/docs/package.md +1 -1
  48. package/docs/plugins.md +23 -23
  49. package/docs/query-libraries.md +14 -14
  50. package/docs/scope.md +22 -22
  51. package/docs/server.md +12 -12
  52. package/docs/stability.md +2 -2
  53. package/docs/starter.md +1 -1
  54. package/docs/tracing.md +2 -2
  55. package/docs/typescript.md +16 -16
  56. package/llms-full.txt +230 -183
  57. package/llms.txt +2 -2
  58. package/package.json +4 -3
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![size](https://img.shields.io/bundlephobia/minzip/nanoeffects)](https://bundlephobia.com/package/nanoeffects)
6
6
  [![license](https://img.shields.io/npm/l/nanoeffects)](LICENSE)
7
7
 
8
- A small event bus for JavaScript apps. Each handler runs as a **task** with an `AbortSignal`, so you can cancel in-flight work. Policies (`latest`, `debounce`, …) and effects (`retry`, `timeout`, …) are plain functions you pass to `on`.
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,9 +15,7 @@ npm install nanoeffects
15
15
 
16
16
  ESM only, no dependencies, types included.
17
17
 
18
- Starting a new project? `npm create nanoeffects@latest my-app` makes a Vite app with a bus ([Docs](docs/starter.md)).
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
 
@@ -36,17 +34,19 @@ bus.emit("greet", "Ada"); // hello Ada
36
34
  unbind();
37
35
  ```
38
36
 
39
- That is enough for a small app or a widget. The handler’s second argument is a task context (`signal`, `emit`, …). See the [Guide](docs/guide.md).
37
+ That is enough for a small app or a widget. The handler’s second argument is a task context (`signal`, `emit`, …).
40
38
 
41
- ## Abort overlapping work
39
+ ## Keep the logic out of the component
42
40
 
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).
41
+ A newer search should abort the older one. Put it in a handler outside the component, wrapped in `latest`.
44
42
 
45
43
  ```js
44
+ // search.js — no React, Vue or Svelte in this file
46
45
  import { createBus } from "nanoeffects";
47
46
  import { latest } from "nanoeffects/policies";
48
47
 
49
- const bus = createBus();
48
+ // createBus — one bus for the logic of the app
49
+ export const bus = createBus();
50
50
 
51
51
  // latest — a newer run aborts the older one
52
52
  bus.on(
@@ -59,40 +59,93 @@ bus.on(
59
59
  );
60
60
  ```
61
61
 
62
- Same `on` / `emit`. Replace `api.search` with your own request.
62
+ `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
+
64
+ The handler knows nothing about the UI: it only emits `results`. The component sends `search` and listens to `results` ([Vue](docs/vue.md) and [Svelte](docs/svelte.md) work the same way):
65
+
66
+ ```jsx
67
+ // SearchBox.jsx
68
+ import { useEffect, useState } from "react";
69
+ import { bus } from "./search";
70
+
71
+ export function SearchBox() {
72
+ const [items, setItems] = useState([]);
73
+
74
+ // on returns the unbind function; returning it removes the listener on unmount
75
+ useEffect(() => bus.on("results", setItems), []);
76
+
77
+ return (
78
+ <>
79
+ <input onChange={(event) => bus.emit("search", event.target.value)} />
80
+ <ul>
81
+ {items.map((item) => (
82
+ <li key={item.id}>{item.title}</li>
83
+ ))}
84
+ </ul>
85
+ </>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ## Take dependencies from the context
91
+
92
+ Put the API client, a store or a logger on every task once. A test passes a fake one.
93
+
94
+ ```js
95
+ import { createBus } from "nanoeffects";
96
+
97
+ // context — every task gets these fields: the bus is the container for your dependencies
98
+ const bus = createBus({ context: { api } });
99
+
100
+ bus.on("save", async (draft, ctx) => {
101
+ await ctx.api.put(draft, { signal: ctx.signal });
102
+ });
103
+ ```
63
104
 
64
- ## Get a result from `emit`
105
+ ## Load data and await the result
65
106
 
66
- A **command** is like an event, but `emit` runs its handler and returns the result (a promise if the handler is async).
107
+ Give an action a handler, and `emit` returns its result. The caller does not import the request.
67
108
 
68
109
  ```js
69
110
  import { createBus } from "nanoeffects";
70
- import { createCommand } from "nanoeffects/actions";
111
+ import { createAction } from "nanoeffects/actions";
71
112
 
72
113
  const bus = createBus();
73
114
 
74
- // createCommand — emit runs the handler and returns what it returns
75
- const double = createCommand("math/double", (value) => value * 2);
115
+ // createAction with a handler — emit returns what the handler returns
116
+ const getUser = createAction("user/get", async (id, ctx) => {
117
+ const response = await fetch(`/users/${id}`, { signal: ctx.signal });
118
+ return response.json();
119
+ });
76
120
 
77
- const answer = bus.emit(double(21)); // 42
121
+ const user = await bus.emit(getUser("1"));
78
122
  ```
79
123
 
80
- More (contracts, jobs, modules): [Actions](docs/actions.md).
124
+ This is one way to load data. If you already use React Query or SWR, keep them: see [Query libraries](docs/query-libraries.md).
81
125
 
82
126
  ## Docs
83
127
 
84
- Start with the [Guide](docs/guide.md) (bus → policies → effects → modules). Or jump by need:
128
+ Start with the [Guide](docs/guide.md), or jump by need:
85
129
 
86
130
  | Need | Page |
87
131
  | ---- | ---- |
88
132
  | Async UI races (search, submit) | [Policies](docs/policies.md) |
89
133
  | Retry, timeout, wait for events | [Effects](docs/effects.md) |
90
- | Domain logic off the UI | [Actions, commands, modules](docs/actions.md) |
91
- | Redux / Zustand / MobX | [Stores](docs/stores.md) |
134
+ | Domain logic off the UI | [Actions, handlers, modules](docs/actions.md) |
135
+ | Redux / Zustand / MobX / Pinia next to the bus | [Stores](docs/stores.md) |
136
+ | 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
137
  | See what ran and why (console, Redux DevTools) | [Tracing](docs/tracing.md) |
93
138
 
94
- [Full index and package entries](docs/README.md) · [Examples](examples/README.md) · [Why nanoeffects exists](docs/motivation.md)
139
+ [Full index and package entries](docs/README.md) · [Examples](examples/README.md)
140
+
141
+ ## Why
142
+
143
+ 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).
144
+
145
+ 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.
146
+
147
+ - **Plain `async` functions.** No generators, no streams.
148
+ - **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).
149
+ - **Tiny, no dependencies.** `createBus` is about 1.4 kB gzip (1.3 kB brotli). Safe inside an SDK.
95
150
 
96
- - **Tiny.** `createBus` is about 1.4 kB gzip (1.3 kB brotli); other entries load only when imported.
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.
151
+ More: [Why nanoeffects exists](docs/motivation.md).
@@ -71,7 +71,7 @@ interface Tracer<Ref extends object = object> {
71
71
  /** Subscribes to every event; handlers receive the payload of any of them. */
72
72
  type AnyEvent = typeof anyEventType;
73
73
  type EventKey<E extends EventMap> = Keys<E>;
74
- type EventPayload<E extends EventMap> = E[EventKey<E>];
74
+ type EventPayload<E extends EventMap> = DataOf<E[EventKey<E>]>;
75
75
  type WithType<K extends string> = {
76
76
  type: K;
77
77
  };
@@ -91,7 +91,7 @@ type WithSignal = {
91
91
  type HandlerRef<E extends EventMap, Response = unknown> = (action: Action<E>) => Response;
92
92
  type Handler<E extends EventMap, Response = unknown, K extends EventKey<E> = EventKey<E>> = { [P in K]: {
93
93
  type: P;
94
- (payload: E[P]): Response;
94
+ (payload: DataOf<E[P]>): Response;
95
95
  }; }[K];
96
96
  type Action<E extends EventMap> = {
97
97
  type: EventKey<E>;
@@ -125,35 +125,45 @@ type Command<P = never, R = unknown> = {
125
125
  readonly wrap?: (run: (payload: never, ctx: never) => unknown) => (payload: never, ctx: never) => unknown;
126
126
  };
127
127
  /**
128
- * What the bus needs to run commands. The implementation, `commandsPlugin` in
129
- * `nanoeffects/actions`, holds the handlers bound to commands and runs the
130
- * right one, so a bus without `commands` carries none of that.
128
+ * What the bus needs to run the handlers of actions. The implementation,
129
+ * `actionsPlugin` in `nanoeffects/actions`, holds the handlers bound to
130
+ * actions and runs the right one, so a bus without `actions` carries none of
131
+ * that. `bound` tells, for an event type, whether a handler is bound to it: an
132
+ * action with no handler of its own is a command only then. A runner that has
133
+ * no `bound` runs commands only.
131
134
  */
132
- interface Commands {
135
+ interface Actions {
133
136
  run(command: Command, payload: unknown, ctx: unknown): unknown;
137
+ bound?(type: string): Command | undefined;
134
138
  }
135
139
  /** Anything `emit` takes as its first argument: an event type, an action or a command. */
136
140
  type Emittable<E extends EventMap> = EventKey<E> | Command | CommandCall | EventLike<E>;
137
141
  type Emit<E extends EventMap> = {
138
- <K extends EventKey<E>>(event: K, ...payload: PayloadOf<E[K]>): void;
142
+ /**
143
+ * On a bus without an event map the caller can say what a handler bound for
144
+ * the type returns: `bus.emit<string>("user/getId")`. With a map the parameter
145
+ * is `never`, so this form is not taken and no check of names or payloads is lost.
146
+ */
147
+ <R = void>(type: string extends EventKey<E> ? string : never, ...payload: unknown[]): R;
148
+ <K extends EventKey<E>>(event: K, ...payload: PayloadOf<DataOf<E[K]>>): ResultOf<E[K]>;
139
149
  /** Before Handler: a command is callable too, and must return its result type. */
140
150
  <P, R>(command: Command<P, R>, ...payload: PayloadOf<P>): R;
141
151
  /** A scope as the second argument replaces context fields for the tasks of this emit; see `scopePlugin`. */
142
152
  <P, R, F>(call: CommandCall<P, R> & WithScope<F>, scope?: EmitScope<E, F>): R;
143
153
  <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]>): R;
154
+ <K extends EventKey<E>, R>(event: Handler<E, R, K>, ...payload: PayloadOf<DataOf<E[K]>>): R;
145
155
  <F>(event: EventLike<E> & WithScope<F>, scope?: EmitScope<E, F>): void;
146
156
  (event: EventLike<E>, scope?: EmitScope<E>): void;
147
157
  };
148
158
  type On<E extends EventMap> = {
149
159
  (event: AnyEvent, fn: Task<EventPayload<E>, E>, options?: ListenerOptions): UnsubscribeCallback;
150
- <K extends EventKey<E>>(event: K, fn: Task<E[K], E>, options?: ListenerOptions): UnsubscribeCallback;
160
+ <K extends EventKey<E>>(event: K, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
151
161
  /** An action creator without a payload type: the payload comes from the event map. */
152
162
  /** 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], WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
163
+ <K extends EventKey<E>, F>(creator: FreeActionCreator<K, F> & WithScope<F>, fn: Task<DataOf<E[K]>, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
154
164
  <P, F>(creator: ActionCreator<P, string, PayloadOf<P>, F> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
155
165
  <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], E>, options?: ListenerOptions): UnsubscribeCallback;
166
+ <K extends EventKey<E>>(creator: FreeActionCreator<K>, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
157
167
  /** An action creator: the payload comes from it, so an event map is not needed. */
158
168
  <P>(creator: ActionCreator<P>, fn: Task<P, E>, options?: ListenerOptions): UnsubscribeCallback;
159
169
  /** A command: the payload comes from it too. */
@@ -162,7 +172,7 @@ type On<E extends EventMap> = {
162
172
  type: K;
163
173
  }>(event: Event & {
164
174
  type: K;
165
- }, fn: Task<E[K], E>, options?: ListenerOptions): UnsubscribeCallback;
175
+ }, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
166
176
  };
167
177
  type Off<E extends EventMap> = {
168
178
  /** Removes every listener of every event (including `"*"`). */
@@ -170,12 +180,12 @@ type Off<E extends EventMap> = {
170
180
  (event: AnyEvent): void;
171
181
  (event: AnyEvent, fn: Task<EventPayload<E>, E>): void;
172
182
  <K extends EventKey<E>>(event: K): void;
173
- <K extends EventKey<E>>(event: K, fn: Task<E[K], E>): void;
183
+ <K extends EventKey<E>>(event: K, fn: Task<DataOf<E[K]>, E>): void;
174
184
  <K extends EventKey<E>, Event extends {
175
185
  type: K;
176
186
  }>(event: Event & {
177
187
  type: K;
178
- }, fn: Task<E[K], E>): void;
188
+ }, fn: Task<DataOf<E[K]>, E>): void;
179
189
  <P>(command: Command<P, unknown>, fn?: Task<P, E>): void;
180
190
  };
181
191
  declare const contextKey: unique symbol;
@@ -246,10 +256,10 @@ interface Bus<E extends EventMap> {
246
256
  * no list of them. See `modulePlugin` in `nanoeffects/actions`.
247
257
  */
248
258
  use<R>(plugin: (bus: Bus<E>) => R): R;
249
- /** `BusOptions.context` and `.trace`, and `commands`, for what makes tasks of its own, like `modulePlugin`. */
259
+ /** `BusOptions.context` and `.trace`, and `actions`, for what makes tasks of its own, like `modulePlugin`. */
250
260
  readonly ctx?: ContextOption<E> | undefined;
251
- /** What runs the commands; `commandsPlugin` and `modulePlugin` set it. Without one a command runs its own handler. */
252
- commands?: Commands | undefined;
261
+ /** What runs the handlers of actions; `actionsPlugin` and `modulePlugin` set it. Without one a command runs its own handler. */
262
+ actions?: Actions | undefined;
253
263
  readonly trace?: Tracer | undefined;
254
264
  /** Called with every new task context to add fields to it, for what needs the task, like `effectsPlugin`. Chain to the previous one. */
255
265
  addContext?: ((ctx: object) => void) | undefined;
@@ -267,8 +277,8 @@ type BusOptions<E extends EventMap> = {
267
277
  onError?: (error: unknown, event: Action<E>) => void;
268
278
  /**
269
279
  * 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, which always have a
271
- * handler to run. Typically a warning in development only.
280
+ * of a typo in an event name. Not called for commands, nor for an action with
281
+ * a handler bound in `actions`, which always have a handler to run. Typically a warning in development only.
272
282
  *
273
283
  * @example
274
284
  * ```ts
@@ -360,15 +370,33 @@ type Merge<A, B> = Omit<A, keyof B> & B;
360
370
  type WithFields<E extends EventMap, F> = [unknown] extends [F] ? E : Omit<E, keyof WithContext<object>> & WithContext<Merge<ContextOf<E>, F>>;
361
371
  //#endregion
362
372
  //#region src/core/action-creator.d.ts
363
- type WithPayload<E extends EventMap, K extends Keys<E>> = undefined extends E[K] ? {
373
+ type WithPayload<E extends EventMap, K extends Keys<E>> = undefined extends DataOf<E[K]> ? {
364
374
  type: K;
365
- payload?: E[K];
375
+ payload?: DataOf<E[K]>;
366
376
  } : {
367
377
  type: K;
368
- payload: E[K];
378
+ payload: DataOf<E[K]>;
369
379
  };
370
380
  type Absent<P> = [P] extends [void] ? undefined : P;
371
381
  type Made<P, T extends string> = WithPayload<{ [K in T]: Absent<P>; }, T>;
382
+ declare const callBrand: unique symbol;
383
+ /**
384
+ * A payload type together with the type of what a handler of the action
385
+ * returns, for an event map or `createAction`:
386
+ * `type Events = { "user/getId": Call<void, string> }`, and then
387
+ * `bus.emit("user/getId")` is a `string`. A type only: it adds nothing to a
388
+ * bundle, and an entry that is not a `Call` means a payload, with no result.
389
+ */
390
+ type Call<P = void, R = void> = {
391
+ readonly [callBrand]: {
392
+ payload: P;
393
+ result: R;
394
+ };
395
+ };
396
+ /** The payload type of an entry of an event map: the `P` of a `Call<P, R>`, the entry itself otherwise. */
397
+ type DataOf<T> = T extends Call<infer P, unknown> ? P : T;
398
+ /** What `emit` returns for an entry of an event map: the `R` of a `Call<P, R>`, `void` otherwise. */
399
+ type ResultOf<T> = T extends Call<unknown, infer R> ? R : void;
372
400
  declare const free: unique symbol;
373
401
  type Free = typeof free;
374
402
  /**
@@ -411,4 +439,4 @@ interface ActionCreator<P = void, T extends string = string, A extends unknown[]
411
439
  toString(): T;
412
440
  }
413
441
  //#endregion
414
- export { HandlerRef as A, Keys as B, Emit as C, EventPayload as D, EventLike as E, WithType as F, Trace as G, PayloadOf as H, createBus as I, UnsubscribeCallback as J, TraceEvent as K, Tracer as L, On as M, WithContext as N, EventsOf as O, WithSignal as P, EffectName as R, ContextOption as S, EventKey as T, Phase as U, ListenerOptions as V, Task as W, Command as _, EmitScope as a, Context as b, WithScope as c, Effects as d, Signaled as f, BusOptions as g, Bus as h, WithPayload as i, Off as j, Handler as k, BoundForm as l, AnyEvent as m, Free as n, Scope as o, Action as p, TraceLogger as q, FreeActionCreator as r, WithFields as s, ActionCreator as t, Effect as u, CommandCall as v, Emittable as w, ContextOf as x, Commands as y, EventMap as z };
442
+ 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 { H as PayloadOf, T as EventKey, W as Task, c as WithScope, h as Bus, n as Free, o as Scope, r as FreeActionCreator, t as ActionCreator, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
- import { r as Scoped, t as FieldsOfScope } from "./types-Bkuhnkq6.js";
3
- import { a as createModule, c as CarryingCalls, d as commandsPlugin, f as createCommand, l as MadeCommand, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as Binding, t as Module, u as bindHandler } from "./module-B6rg5NIb.js";
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-D_c223C7.js";
2
+ import { r as Scoped, t as FieldsOfScope } from "./types-Bf-LX_tE.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-WX0Gngnt.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
- * - With `prepare` the arguments of the creator can differ from the payload,
18
- * and both types are inferred.
19
- * - A scope as the last argument, `{ cache, $effects: { race } }`, gives the
20
- * listeners of its calls those context fields; it works on a bus that uses `scopePlugin`
21
- * from `nanoeffects/scope` and is ignored on any other.
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", (id: string, name: string) => ({
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): [P] extends [Free] ? FreeActionCreator<T> : ActionCreator<P, T>;
39
- export declare function createAction<A extends unknown[], P, T extends string = string>(type: T, prepare: (...args: A) => {
40
- payload: P;
41
- }): ActionCreator<P, T, A>;
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, bindHandler, commandsPlugin, createCommand, createModule, modulePlugin };
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-0RIBGYqS.js";import{r as o}from"./bus-hHp-T7JV.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);function h(e,t,n){let r=typeof t==`function`?t:void 0,i=typeof t==`function`?n:t;return Object.assign(f((...t)=>f({type:e,payload:r?r(...t).payload:t[0]},i),i),{type:e,match:t=>t.type===e,toString:()=>e})}var g=class extends Error{};function _(e,t,n){let r=t=>t.type===e;function i(r,i){if(typeof i==`object`){if(!t)throw new g(`No handler for command "${e}"`);return t(r,i)}return f(o(s,e,r),n)}let a=Object.assign(i,{type:e,match:r}),s=f(a,n);return s}const v=(e,t)=>[e,t],y=e=>typeof Reflect.get(e??{},`handle`)==`function`,b=(e=[])=>t=>{let n=t.commands;if(y(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};return t.commands=s,s},x=()=>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})},S=e=>typeof e==`string`?h(e):e,C=(e,t,n,r)=>{let i=m(t);e.emit(Reflect.apply(t,null,[n]),r&&i?p(r,i):r)},w=(t,r,i,a)=>{let o=t;o[n]=!0;try{C(t,r,i,a)}catch(t){e(`cancel listener`,t)}o[n]=!1},T=e=>{try{return Promise.resolve(e())}catch(e){if(e instanceof g)throw e;return Promise.reject(e)}},E=(t,n,r={},a)=>{let l=_(t,n),u=e=>S(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(),w(s,h,e,a))},_=()=>{l===`idle`&&(l=`started`,u=i(s,g),C(s,d,n,a))},v=e=>{l===`started`&&(f(),s.signal.aborted?w(s,h,s.signal.reason,a):`error`in e?C(s,m,e.error,a):C(s,p,e.value,a))};return Reflect.set(s,c,{start:_,cancel:g,done:v,drop:()=>{l===`idle`&&(l=`closed`)}}),T(()=>(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})})},v=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(E,t,e),a)}let x=Object.assign(b,{type:t,match:l.match,wrap:v,pending:d,success:p,fail:m,cancel:h}),E=f(x,a);return E},D=e=>typeof e==`object`&&!!e,O=e=>{if(typeof e==`string`)return e;if(D(e)||typeof e==`function`){let t=Reflect.get(e,`type`);return typeof t==`string`?t:e}return e},k=(e,t)=>{let[n,r]=e;return n===void 0||Object.is(O(n),O(t[0]))&&(r===void 0||Object.is(r,t[1]))},A=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`&&k(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 j(e,t,n){return n?{name:e,setup:t,scope:n}:{name:e,setup:t}}const M=(e,t)=>n=>t?e.fitScope?.(t,n)??n:n,N=(e,t,n)=>{n&&e.applyScope?.(t,n)},P=(e,t,n)=>Array.isArray(t)?[t.map(([t,n])=>[t,e(n)]),n]:[t,e(n)],F=(e,t)=>{let n=e.on;return(...e)=>{let[r,i,...a]=e;return Reflect.apply(n,null,[r,t(i),...a])}},I=e=>(t,...n)=>{e.run(t,...n).catch(t=>{if(!e.signal.aborted)throw t})},L=(n=[])=>a=>{let o=a.commands??b()(a),s={handle:(...e)=>{if(!o.handle)throw Error("modulePlugin: the `commands` of the bus is not a registry from `commandsPlugin()`");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=M(a,h),_=(e,t)=>{let n=Reflect.apply(s.handle,null,P(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=I(f),b=F(f,g);try{N(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=A(a),u=a.emit,f,p=(e=!0)=>{if(f)return f;l.release(),a.emit===m&&(a.emit=u);let t=r({event:{type:`app`,payload:void 0},bus:a,tracer:a.trace});f={root:t,apps:d(c(t.ctx))};try{e&&f.apps.mount(...n)}finally{l.replay()}return f},m=(...e)=>(p(),Reflect.apply(u,a,e));a.emit=m,n.length>0&&queueMicrotask(()=>{try{p()}catch(t){e(`the modules of the app could not start`,t)}});let h={get commands(){return p(),o},mount:(...e)=>{let{root:t,apps:n}=p();return t.ctx.signal.throwIfAborted(),n.mount(...e)},unmount:(...e)=>p().apps.unmount(...e),isMounted:e=>p().apps.isMounted(e),dispose:()=>p(!1).root.ctx.abort(),createModule:j};return a.app=h,h};export{v as bindHandler,b as commandsPlugin,h as createAction,_ as createCommand,E as createJob,j as createModule,x as emitterPlugin,L as modulePlugin};
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-0RIBGYqS.js";import{r as o}from"./bus-DQDHUN5e.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,p=(e=!0)=>{if(f)return f;l.release(),a.emit===m&&(a.emit=u);let t=r({event:{type:`app`,payload:void 0},bus:a,tracer:a.trace});f={root:t,apps:d(c(t.ctx))};try{e&&f.apps.mount(...n)}finally{l.replay()}return f},m=(...e)=>(p(),Reflect.apply(u,a,e));a.emit=m,n.length>0&&queueMicrotask(()=>{try{p()}catch(t){e(`the modules of the app could not start`,t)}});let h={get actions(){return p(),o},mount:(...e)=>{let{root:t,apps:n}=p();return t.ctx.signal.throwIfAborted(),n.mount(...e)},unmount:(...e)=>p().apps.unmount(...e),isMounted:e=>p().apps.isMounted(e),dispose:()=>p(!1).root.ctx.abort(),createModule:F};return a.app=h,h};export{S as actionsPlugin,C as createAction,A as createJob,F as createModule,T as emitterPlugin,V as modulePlugin,b as setHandler};
@@ -1 +1 @@
1
- import{d as e,n as t,o as n,r}from"./context-UcmrAIhP.js";import{n as i}from"./promise-CSLpzwSR.js";import{n as a,t as o}from"./event-0RIBGYqS.js";const s=()=>{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()};return{get:n=>(t[n]??=[...e[n]??[]].flatMap(([e,t])=>Array(t).fill(e)),t[n]),add:(e,t)=>{let i=n(e);return i.set(t,(i.get(t)??0)+1),()=>{r(e,t)}},remove:r,clear:()=>{e={},t={}}}},c=Symbol(),l=(e,t,n)=>{let r={type:t,payload:n};return Object.defineProperty(r,c,{value:e,enumerable:!1}),r},u=e=>{if(typeof e==`function`)return e;if(typeof e==`object`&&e&&c in e)return e[c]},d=(e,t,n)=>Reflect.apply(e,null,[t,n]),f=(c={})=>{let l=s(),f=(e,t)=>l.add(o(e),t),p=(e,t)=>{let n=f(e,(e,r)=>(n(),t(e,r)));return n},m=(e,t)=>{e===void 0?l.clear():l.remove(o(e),t)},h=(n,a)=>{let{onError:o}=c,{ctx:s}=t({event:a,bus:g,tracer:c.trace,parent:{ref:r()}});if(!o){n(a.payload,s);return}let l=t=>{try{o(t,a)}catch(t){e(`onError failed`,t)}};try{let e=n(a.payload,s);i(e)&&Promise.resolve(e).catch(l)}catch(e){l(e)}},g={on:f,once:p,off:m,emit:(e,i)=>{let s=o(e),f=a(e,i),p={type:s,payload:f},m=u(e),_=[...l.get(s),...l.get(`*`)];_.length===0&&!m&&c.onUnhandled?.(p);for(let e of _)h(e,p);if(m){let{ctx:e}=t({event:p,bus:g,tracer:c.trace,parent:{ref:r()}}),i=g.commands?.run??d;return n(e,`command`,()=>i(m,f,e))}},use:e=>e(g),ctx:c.context,trace:c.trace};return g};export{f as n,l as r,u as t};
1
+ import{d as e,n as t,o as n,r}from"./context-UcmrAIhP.js";import{n as i}from"./promise-CSLpzwSR.js";import{n as a,t as o}from"./event-0RIBGYqS.js";const s=()=>{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()};return{get:n=>(t[n]??=[...e[n]??[]].flatMap(([e,t])=>Array(t).fill(e)),t[n]),add:(e,t)=>{let i=n(e);return i.set(t,(i.get(t)??0)+1),()=>{r(e,t)}},remove:r,clear:()=>{e={},t={}}}},c=Symbol(),l=(e,t,n)=>{let r={type:t,payload:n};return Object.defineProperty(r,c,{value:e,enumerable:!1}),r},u=e=>{if(typeof e==`function`)return e;if(typeof e==`object`&&e&&c in e)return e[c]},d=(e,t,n)=>Reflect.apply(e,null,[t,n]),f=(c={})=>{let l=s(),f=(e,t)=>l.add(o(e),t),p=(e,t)=>{let n=f(e,(e,r)=>(n(),t(e,r)));return n},m=(e,t)=>{e===void 0?l.clear():l.remove(o(e),t)},h=(n,a)=>{let{onError:o}=c,{ctx:s}=t({event:a,bus:g,tracer:c.trace,parent:{ref:r()}});if(!o){n(a.payload,s);return}let l=t=>{try{o(t,a)}catch(t){e(`onError failed`,t)}};try{let e=n(a.payload,s);i(e)&&Promise.resolve(e).catch(l)}catch(e){l(e)}},g={on:f,once:p,off:m,emit:(e,i)=>{let s=o(e),f=a(e,i),p={type:s,payload:f},m=u(e);m||=g.actions?.bound?.(s);let _=[...l.get(s),...l.get(`*`)];_.length===0&&!m&&c.onUnhandled?.(p);for(let e of _)h(e,p);if(m){let{ctx:e}=t({event:p,bus:g,tracer:c.trace,parent:{ref:r()}}),i=g.actions?.run??d;return n(e,`command`,()=>i(m,f,e))}},use:e=>e(g),ctx:c.context,trace:c.trace};return g};export{f as n,l as r,u as t};
@@ -1,4 +1,4 @@
1
- import { x as ContextOf, z as EventMap } from "./action-creator-Bpa8BUS9.js";
1
+ import { C as ContextOf, H as EventMap } from "./action-creator-D_c223C7.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 { N as WithContext, h as Bus, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
- import { n as NoClash, t as ContextTask } from "./context-types-BKIH5a8s.js";
1
+ import { F as WithContext, H as EventMap, v as Bus } from "./action-creator-D_c223C7.js";
2
+ import { n as NoClash, t as ContextTask } from "./context-types-nGtzhjxD.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 { J as UnsubscribeCallback, h as Bus, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
- import { i as WithApp, n as ModuleApi } from "./module-B6rg5NIb.js";
1
+ import { H as EventMap, Z as UnsubscribeCallback, v as Bus } from "./action-creator-D_c223C7.js";
2
+ import { i as WithApp, n as ModuleApi } from "./module-WX0Gngnt.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/effects.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as WithSignal, W as Task, b as Context, u as Effect, z as EventMap } from "./action-creator-Bpa8BUS9.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-D-j1DarG.js";
1
+ import { H as EventMap, I as WithSignal, S as Context, f as Effect, q as Task } from "./action-creator-D_c223C7.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-vvkmIIz2.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as HandlerRef, B as Keys, C as Emit, D as EventPayload, E as EventLike, F as WithType, H as PayloadOf, I as createBus, J as UnsubscribeCallback, M as On, N as WithContext, O as EventsOf, P as WithSignal, S as ContextOption, T as EventKey, W as Task, _ as Command, b as Context, g as BusOptions, h as Bus, i as WithPayload, j as Off, k as Handler, m as AnyEvent, p as Action, v as CommandCall, w as Emittable, x as ContextOf, y as Commands, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
- export { type Action, type AnyEvent, type Bus, type BusOptions, type Command, type CommandCall, type Commands, 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 };
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-D_c223C7.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-hHp-T7JV.js";
1
+ export{n as createBus}from"./bus-DQDHUN5e.js";
package/dist/match.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as EventPayload, J as UnsubscribeCallback, W as Task, h as Bus, p as Action, z as EventMap } from "./action-creator-Bpa8BUS9.js";
1
+ import { H as EventMap, Z as UnsubscribeCallback, h as Action, k as EventPayload, q as Task, v as Bus } from "./action-creator-D_c223C7.js";
2
2
  //#region src/match/plugin.d.ts
3
3
  /** A function over the action of an event: `{ type, payload }`. */
4
4
  type Predicate<E extends EventMap> = (action: Action<E>) => boolean;