nanoeffects 0.28.0 → 0.30.1

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 (139) hide show
  1. package/README.md +6 -5
  2. package/dist/{action-creator-CcAEvUnw.d.ts → action-creator-6rlBTmH9.d.ts} +60 -33
  3. package/dist/actions.d.ts +18 -18
  4. package/dist/actions.js +1 -1
  5. package/dist/bus-DFlmNJ6h.js +1 -0
  6. package/dist/context-B5Z2RpJt.js +1 -0
  7. package/dist/context-types-DKNc5mkS.d.ts +31 -0
  8. package/dist/context.d.ts +8 -3
  9. package/dist/context.js +1 -1
  10. package/dist/{delay-18LJ8jSk.js → delay-5OhJZZQ0.js} +1 -1
  11. package/dist/dev.d.ts +44 -3
  12. package/dist/dev.js +2 -1
  13. package/dist/effects.d.ts +2 -2
  14. package/dist/effects.js +1 -1
  15. package/dist/emit-key-C6FL7Ewn.js +1 -0
  16. package/dist/guard.d.ts +59 -0
  17. package/dist/guard.js +1 -0
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +1 -1
  20. package/dist/match.d.ts +3 -3
  21. package/dist/match.js +1 -1
  22. package/dist/{module-C_oEXw1n.d.ts → module-G39MaVOt.d.ts} +38 -38
  23. package/dist/notrace/{action-creator-DxOvVo8I.d.ts → action-creator-BrMSO3RP.d.ts} +35 -32
  24. package/dist/notrace/actions.d.ts +52 -52
  25. package/dist/notrace/actions.js +1 -1
  26. package/dist/notrace/{bus-DmKn4SDD.js → bus-37nlVljc.js} +1 -1
  27. package/dist/notrace/effects.d.ts +2 -2
  28. package/dist/notrace/index.d.ts +2 -2
  29. package/dist/notrace/index.js +1 -1
  30. package/dist/notrace/{plugin-lJjjd-SN.d.ts → plugin-7GUL2EW5.d.ts} +1 -1
  31. package/dist/notrace/policies.d.ts +1 -1
  32. package/dist/notrace/redux.d.ts +1 -1
  33. package/dist/observable.d.ts +43 -1
  34. package/dist/observable.js +1 -1
  35. package/dist/onAbort-BgMfspK4.js +1 -0
  36. package/dist/oop.d.ts +3 -3
  37. package/dist/oop.js +1 -1
  38. package/dist/{plugin-CuvIgjnX.d.ts → plugin-BWNP23hr.d.ts} +2 -2
  39. package/dist/policies.d.ts +2 -2
  40. package/dist/policies.js +1 -1
  41. package/dist/production/dev.js +1 -1
  42. package/dist/react.d.ts +2 -2
  43. package/dist/react.js +1 -1
  44. package/dist/redux.d.ts +1 -1
  45. package/dist/scope.d.ts +9 -9
  46. package/dist/signal-field-key-CWT-3OXC.js +1 -0
  47. package/dist/signal.d.ts +34 -6
  48. package/dist/signal.js +1 -1
  49. package/dist/site-DLvUoXs3.js +1 -0
  50. package/dist/svelte.d.ts +1 -1
  51. package/dist/trace.d.ts +170 -6
  52. package/dist/trace.js +3 -1
  53. package/dist/{types-FV8fuvI9.d.ts → types-N_cdRr1r.d.ts} +2 -2
  54. package/dist/vue.d.ts +1 -1
  55. package/dist/{with-policy-D-SQRkPh.js → with-policy-CeM1rtES.js} +1 -1
  56. package/dist/{with-policy-3bhFLEXs.d.ts → with-policy-CthiBp_z.d.ts} +1 -1
  57. package/docs/README.md +65 -22
  58. package/docs/actions.md +56 -13
  59. package/docs/cancel-stale-requests.md +2 -0
  60. package/docs/chat-example.md +15 -1
  61. package/docs/chat-widget.md +9 -7
  62. package/docs/context.md +352 -8
  63. package/docs/debounce-and-abort.md +3 -1
  64. package/docs/debugging-loops.md +283 -0
  65. package/docs/effects.md +259 -131
  66. package/docs/errors.md +4 -2
  67. package/docs/examples.md +60 -0
  68. package/docs/guide.md +57 -22
  69. package/docs/hmr.md +35 -1
  70. package/docs/loop-guard.md +109 -0
  71. package/docs/migrating-from-effector.md +15 -2
  72. package/docs/migrating-from-mitt.md +6 -4
  73. package/docs/migrating-from-rxjs.md +2 -0
  74. package/docs/migrating-from-saga.md +2 -0
  75. package/docs/motivation.md +14 -21
  76. package/docs/observable.md +45 -0
  77. package/docs/oop.md +20 -1
  78. package/docs/package.md +25 -13
  79. package/docs/pass-the-signal.md +281 -0
  80. package/docs/plugins.md +90 -15
  81. package/docs/policies.md +73 -46
  82. package/docs/prevent-double-submit.md +3 -1
  83. package/docs/query-libraries.md +276 -6
  84. package/docs/react.md +50 -11
  85. package/docs/recipes.md +528 -0
  86. package/docs/ru/README.md +62 -0
  87. package/docs/ru/actions.md +412 -0
  88. package/docs/ru/cancel-stale-requests.md +106 -0
  89. package/docs/ru/chat-example.md +259 -0
  90. package/docs/ru/chat-widget.md +131 -0
  91. package/docs/ru/context.md +401 -0
  92. package/docs/ru/debounce-and-abort.md +105 -0
  93. package/docs/ru/debugging-loops.md +283 -0
  94. package/docs/ru/effects.md +538 -0
  95. package/docs/ru/errors.md +36 -0
  96. package/docs/ru/examples.md +60 -0
  97. package/docs/ru/guide.md +530 -0
  98. package/docs/ru/hmr.md +83 -0
  99. package/docs/ru/loop-guard.md +109 -0
  100. package/docs/ru/migrating-from-effector.md +339 -0
  101. package/docs/ru/migrating-from-mitt.md +99 -0
  102. package/docs/ru/migrating-from-rxjs.md +197 -0
  103. package/docs/ru/migrating-from-saga.md +97 -0
  104. package/docs/ru/motivation.md +47 -0
  105. package/docs/ru/observable.md +233 -0
  106. package/docs/ru/oop.md +431 -0
  107. package/docs/ru/package.md +42 -0
  108. package/docs/ru/pass-the-signal.md +281 -0
  109. package/docs/ru/plugins.md +398 -0
  110. package/docs/ru/policies.md +201 -0
  111. package/docs/ru/prevent-double-submit.md +122 -0
  112. package/docs/ru/query-libraries.md +392 -0
  113. package/docs/ru/react.md +309 -0
  114. package/docs/ru/recipes.md +528 -0
  115. package/docs/ru/semantics.md +19 -0
  116. package/docs/ru/server.md +204 -0
  117. package/docs/ru/starter.md +118 -0
  118. package/docs/ru/stores.md +673 -0
  119. package/docs/ru/svelte.md +78 -0
  120. package/docs/ru/tracing.md +466 -0
  121. package/docs/ru/typescript.md +170 -0
  122. package/docs/ru/vue.md +92 -0
  123. package/docs/semantics.md +12 -0
  124. package/docs/server.md +5 -3
  125. package/docs/starter.md +2 -0
  126. package/docs/stores.md +2 -0
  127. package/docs/svelte.md +3 -1
  128. package/docs/tracing.md +132 -7
  129. package/docs/typescript.md +3 -1
  130. package/docs/vue.md +3 -1
  131. package/llms-full.txt +2718 -545
  132. package/llms.txt +17 -14
  133. package/package.json +25 -8
  134. package/skills/nanoeffects/SKILL.md +2 -2
  135. package/dist/bus-DlpEluzd.js +0 -1
  136. package/dist/context-UcmrAIhP.js +0 -1
  137. package/dist/context-types-hCKgU8sC.d.ts +0 -14
  138. package/docs/scope.md +0 -266
  139. package/docs/stability.md +0 -90
package/README.md CHANGED
@@ -13,7 +13,7 @@ Move business logic and side effects out of React, Vue and Svelte components int
13
13
  npm install nanoeffects
14
14
  ```
15
15
 
16
- ESM only, no dependencies, types included.
16
+ `pnpm add nanoeffects` and `yarn add nanoeffects` work the same. The package is ESM only (use `import`, not `require`), has no dependencies and includes its types. It runs on Node 18 or newer and in any bundler.
17
17
 
18
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.
19
19
 
@@ -28,11 +28,11 @@ const bus = createBus(); // event bus; each handler call is a task
28
28
  const cart = [];
29
29
 
30
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));
31
+ const unbind = bus.on("cart/added", (item) => console.log("added", item));
32
32
  bus.on("cart/added", (item) => cart.push(item));
33
33
 
34
34
  bus.emit("cart/added", { id: "p1" }); // both listeners run, cart has the item
35
- unbind(); // stop tracking
35
+ unbind(); // stop logging
36
36
  ```
37
37
 
38
38
  ## Keep the logic out of the component
@@ -51,7 +51,8 @@ export const bus = createBus();
51
51
  bus.on(
52
52
  "search",
53
53
  latest(async (query, ctx) => {
54
- // signal — lets latest cancel this request, not only drop its result
54
+ // api is your own client (a fetch wrapper, axios, ...); signal lets latest cancel
55
+ // this request, not only drop its result
55
56
  const items = await api.search(query, { signal: ctx.signal });
56
57
  ctx.emit("results", items);
57
58
  }),
@@ -127,7 +128,7 @@ bus.on("save", async (draft, ctx) => {
127
128
 
128
129
  ## Docs
129
130
 
130
- Start with the [Guide](docs/guide.md), or jump by need:
131
+ Read it on the [docs site](https://nanoeffects.github.io/nanoeffects/) (search and sidebar; [in Russian](https://nanoeffects.github.io/nanoeffects/ru/)), or start with the [Guide](docs/guide.md) and jump by need:
131
132
 
132
133
  | Need | Page |
133
134
  | ---- | ---- |
@@ -1,14 +1,16 @@
1
1
  //#region src/core/types.d.ts
2
- /** The third argument of `on` and `once`: read by `tracePlugin`, ignored without it. */
2
+ /** The third argument of `on` and `once`: each field is read by the plugin that names it, ignored without it. */
3
3
  type ListenerOptions = {
4
- /** Names the listener in the trace: each call of it is a task with this `type`. */
4
+ /** Names the listener in the trace: each call of it is a task with this `type`. Read by `tracePlugin`. */
5
5
  traceId?: string;
6
+ /** Removes the listener when this aborts, and adds none if it aborted already. Read by `signalPlugin`. */
7
+ signal?: AbortSignal;
6
8
  };
7
9
  type PayloadOf<P> = undefined extends P ? [payload?: P] : [payload: P];
8
10
  type EventMap = Record<string, unknown>;
9
11
  type Keys<E> = keyof E & string;
10
12
  type Task<P, E extends EventMap, R = unknown> = (payload: P, ctx: Context<E>) => R;
11
- type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "allSettled" | "command" | "emit";
13
+ type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "allSettled" | "action" | "emit";
12
14
  type Phase = "start" | "done" | "error" | "cancel" | "drop";
13
15
  type TraceEvent<E = Record<string, unknown>> = { [K in Keys<E>]: {
14
16
  id: number;
@@ -29,7 +31,31 @@ type TraceEvent<E = Record<string, unknown>> = { [K in Keys<E>]: {
29
31
  * Adapters in `nanoeffects/trace` are factories that return one; pass it
30
32
  * through `createTracer` to `createBus({ trace })`.
31
33
  */
32
- type TraceLogger<E = Record<string, unknown>> = (event: TraceEvent<E>) => void;
34
+ type TraceLogger<E = Record<string, unknown>> = ((event: TraceEvent<E>) => void) & {
35
+ /**
36
+ * Optional: called when a task is made (and again when it is renamed), also for the tasks that
37
+ * never report an event, like a plain handler. Not called for a root that is not sampled.
38
+ */
39
+ task?: (task: TaskInfo) => void;
40
+ };
41
+ /** What a logger's `task` method gets about one task. */
42
+ type TaskInfo = {
43
+ /** Opaque handle of the task; the same one in the call for a rename. Key a `WeakMap` with it. */
44
+ ref: object;
45
+ /** Handle of the parent task; absent for a root. */
46
+ parent?: object;
47
+ /** The number the events of the task use as `id`. */
48
+ id: number;
49
+ /** The type of the task now: the event, or the name of a listener after a rename. */
50
+ type: string;
51
+ /** After a rename, the type the task had before it (the event the listener handles). */
52
+ event?: string;
53
+ /** `true` for the emit event that `tracePlugin` makes, which has no handler of its own. */
54
+ leaf?: boolean;
55
+ /** `false` for a task that `ctx.run` or an effect or a policy made inside a handler; `true` for the task of an emit. */
56
+ emitted?: boolean;
57
+ traceGroupId?: string;
58
+ };
33
59
  /** One logger or several; a throwing logger never breaks the task or the others. */
34
60
  type Trace<E = Record<string, unknown>> = TraceLogger<E> | readonly TraceLogger<E>[];
35
61
  type UnsubscribeCallback = () => void;
@@ -74,6 +100,7 @@ interface Tracer<Ref extends object = object> {
74
100
  type: string;
75
101
  payload?: unknown;
76
102
  traceGroupId?: string;
103
+ leaf?: boolean;
77
104
  }, parent?: Ref): Ref;
78
105
  /** Gives the task another `type`, for a task that is named after it was made (a named listener). A tracer may leave it out. */
79
106
  rename?(ref: Ref, type: string): void;
@@ -120,27 +147,27 @@ type Action<E extends EventMap> = {
120
147
  };
121
148
  type EventLike<E extends EventMap> = { [K in EventKey<E>]: WithPayload<E, K>; }[Keys<E>];
122
149
  /**
123
- * Brands `{ type, payload }` from a command call so `emit` can run the command.
150
+ * Brands `{ type, payload }` from a call of an action with a handler so `emit` can run the action.
124
151
  * Not enumerable on the object.
125
152
  */
126
- declare const commandCall: unique symbol;
153
+ declare const handledCall: unique symbol;
127
154
  /**
128
- * What `command(payload)` returns: an action-shaped value that `emit` runs as
129
- * that command. A plain `{ type, payload }` without this brand is notify-only.
155
+ * What `action(payload)` returns: an action-shaped value that `emit` runs as
156
+ * that action. A plain `{ type, payload }` without this brand is notify-only.
130
157
  */
131
- type CommandCall<P = unknown, R = unknown> = {
158
+ type HandledCall<P = unknown, R = unknown> = {
132
159
  type: string;
133
160
  payload: P;
134
- readonly [commandCall]: Command<P, R>;
161
+ readonly [handledCall]: Handled<P, R>;
135
162
  };
136
163
  /**
137
164
  * A typed request for a result. Calling it builds `{ type, payload }` like
138
- * `createAction`; `bus.emit(command(payload))` (or `bus.emit(command, payload)`)
165
+ * `createAction`; `bus.emit(action(payload))` (or `bus.emit(action, payload)`)
139
166
  * runs the handler as a task and returns what it returns. Made by
140
- * `createCommand` in `nanoeffects/actions`.
167
+ * `createAction` in `nanoeffects/actions`.
141
168
  */
142
- type Command<P = never, R = unknown> = {
143
- (payload: P): CommandCall<P, R>;
169
+ type Handled<P = never, R = unknown> = {
170
+ (payload: P): HandledCall<P, R>;
144
171
  readonly type: string;
145
172
  /** Wraps the handler that really runs, e.g. to route its outcome. */
146
173
  readonly wrap?: (run: (payload: never, ctx: never) => unknown) => (payload: never, ctx: never) => unknown;
@@ -150,15 +177,15 @@ type Command<P = never, R = unknown> = {
150
177
  * `actionsPlugin` in `nanoeffects/actions`, holds the handlers bound to
151
178
  * actions and runs the right one, so a bus without `actions` carries none of
152
179
  * 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.
180
+ * action with no handler of its own is an action only then. A runner that has
181
+ * no `bound` runs actions only.
155
182
  */
156
183
  interface Actions {
157
- run(command: Command, payload: unknown, ctx: unknown): unknown;
158
- bound?(type: string): Command | undefined;
184
+ run(handled: Handled, payload: unknown, ctx: unknown): unknown;
185
+ bound?(type: string): Handled | undefined;
159
186
  }
160
- /** Anything `emit` takes as its first argument: an event type, an action or a command. */
161
- type Emittable<E extends EventMap> = EventKey<E> | Command | CommandCall | EventLike<E>;
187
+ /** Anything `emit` takes as its first argument: an event type, an action creator or a call of one. */
188
+ type Emittable<E extends EventMap> = EventKey<E> | Handled | HandledCall | EventLike<E>;
162
189
  type Emit<E extends EventMap> = {
163
190
  /**
164
191
  * On a bus without an event map the caller can say what a handler bound for
@@ -167,11 +194,11 @@ type Emit<E extends EventMap> = {
167
194
  */
168
195
  <R = void>(type: string extends EventKey<E> ? string : never, ...payload: unknown[]): R;
169
196
  <K extends EventKey<E>>(event: K, ...payload: PayloadOf<DataOf<E[K]>>): ResultOf<E[K]>;
170
- /** Before Handler: a command is callable too, and must return its result type. */
171
- <P, R>(command: Command<P, R>, ...payload: PayloadOf<P>): R;
197
+ /** Before Handler: an action is callable too, and must return its result type. */
198
+ <P, R>(handled: Handled<P, R>, ...payload: PayloadOf<P>): R;
172
199
  /** A scope as the second argument replaces context fields for the tasks of this emit; see `scopePlugin`. */
173
- <P, R, F>(call: CommandCall<P, R> & WithScope<F>, scope?: EmitScope<E, F>): R;
174
- <P, R>(call: CommandCall<P, R>, scope?: EmitScope<E>): R;
200
+ <P, R, F>(call: HandledCall<P, R> & WithScope<F>, scope?: EmitScope<E, F>): R;
201
+ <P, R>(call: HandledCall<P, R>, scope?: EmitScope<E>): R;
175
202
  <K extends EventKey<E>, R>(event: Handler<E, R, K>, ...payload: PayloadOf<DataOf<E[K]>>): R;
176
203
  <F>(event: EventLike<E> & WithScope<F>, scope?: EmitScope<E, F>): void;
177
204
  (event: EventLike<E>, scope?: EmitScope<E>): void;
@@ -180,15 +207,15 @@ type On<E extends EventMap> = {
180
207
  (event: AnyEvent, fn: Task<EventPayload<E>, E>, options?: ListenerOptions): UnsubscribeCallback;
181
208
  <K extends EventKey<E>>(event: K, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
182
209
  /** An action creator without a payload type: the payload comes from the event map. */
183
- /** The creators and commands that carry a scope come first: the handler sees their fields. */
210
+ /** The creators and actions that carry a scope come first: the handler sees their fields. */
184
211
  <K extends EventKey<E>, F>(creator: FreeActionCreator<K, F> & WithScope<F>, fn: Task<DataOf<E[K]>, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
185
212
  <P, F>(creator: ActionCreator<P, string, PayloadOf<P>, F> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
186
- <P, F>(command: Command<P, unknown> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
213
+ <P, F>(handled: Handled<P, unknown> & WithScope<F>, fn: Task<P, WithFields<E, F>>, options?: ListenerOptions): UnsubscribeCallback;
187
214
  <K extends EventKey<E>>(creator: FreeActionCreator<K>, fn: Task<DataOf<E[K]>, E>, options?: ListenerOptions): UnsubscribeCallback;
188
215
  /** An action creator: the payload comes from it, so an event map is not needed. */
189
216
  <P>(creator: ActionCreator<P>, fn: Task<P, E>, options?: ListenerOptions): UnsubscribeCallback;
190
- /** A command: the payload comes from it too. */
191
- <P>(command: Command<P, unknown>, fn: Task<P, E>, options?: ListenerOptions): UnsubscribeCallback;
217
+ /** An action: the payload comes from it too. */
218
+ <P>(handled: Handled<P, unknown>, fn: Task<P, E>, options?: ListenerOptions): UnsubscribeCallback;
192
219
  <K extends EventKey<E>, Event extends {
193
220
  type: K;
194
221
  }>(event: Event & {
@@ -207,7 +234,7 @@ type Off<E extends EventMap> = {
207
234
  }>(event: Event & {
208
235
  type: K;
209
236
  }, fn: Task<DataOf<E[K]>, E>): void;
210
- <P>(command: Command<P, unknown>, fn?: Task<P, E>): void;
237
+ <P>(handled: Handled<P, unknown>, fn?: Task<P, E>): void;
211
238
  };
212
239
  declare const contextKey: unique symbol;
213
240
  /**
@@ -297,7 +324,7 @@ interface Bus<E extends EventMap> {
297
324
  use<R>(plugin: (bus: Bus<E>) => R): R;
298
325
  /** `BusOptions.context` and `.trace`, and `actions`, for what makes tasks of its own, like `modulePlugin`. */
299
326
  readonly ctx?: ContextOption<E> | undefined;
300
- /** What runs the handlers of actions; `actionsPlugin` and `modulePlugin` set it. Without one a command runs its own handler. */
327
+ /** What runs the handlers of actions; `actionsPlugin` and `modulePlugin` set it. Without one an action runs its own handler. */
301
328
  actions?: Actions | undefined;
302
329
  readonly trace?: Tracer | undefined;
303
330
  /** Called with every new task context to add fields to it, for what needs the task, like `effectsPlugin`. Chain to the previous one. */
@@ -316,7 +343,7 @@ type BusOptions<E extends EventMap> = {
316
343
  onError?: (error: unknown, event: Action<E>) => void;
317
344
  /**
318
345
  * Called when an event is emitted and nobody listens to it: the usual sign
319
- * of a typo in an event name. Not called for commands, nor for an action with
346
+ * of a typo in an event name. Not called for actions, nor for an action with
320
347
  * a handler bound in `actions`, which always have a handler to run. Typically a warning in development only.
321
348
  *
322
349
  * @example
@@ -369,7 +396,7 @@ type BoundForm<F> = typeof bound extends keyof F ? NonNullable<F[typeof bound &
369
396
  //#endregion
370
397
  //#region src/core/scope-types.d.ts
371
398
  declare const scopeFields: unique symbol;
372
- /** What an action creator, a command or a call knows of the scope it was made with: its fields, for the checker. */
399
+ /** What an action creator or a call knows of the scope it was made with: its fields, for the checker. */
373
400
  type WithScope<F> = {
374
401
  readonly [scopeFields]: F;
375
402
  };
@@ -478,4 +505,4 @@ interface ActionCreator<P = void, T extends string = string, A extends unknown[]
478
505
  toString(): T;
479
506
  }
480
507
  //#endregion
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 };
508
+ export { HandledCall as A, Tracer as B, Emit as C, EventPayload as D, EventLike as E, WithContext as F, PayloadOf as G, EventMap as H, WithSignal as I, TaskInfo as J, Phase as K, WithType as L, HandlerRef as M, Off as N, EventsOf as O, On as P, UnsubscribeCallback as Q, createBus as R, ContextOption as S, EventKey as T, Keys as U, EffectName as V, ListenerOptions as W, TraceEvent as X, Trace as Y, TraceLogger as Z, AnyEvent as _, FreeActionCreator as a, Context as b, Scope as c, BoundForm as d, Effect as f, Actions as g, Action as h, Free as i, Handler as j, Handled 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, Emittable as w, ContextOf as x, BusOptions as y, handledCall as z };
package/dist/actions.d.ts CHANGED
@@ -1,16 +1,16 @@
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";
1
+ import { G as PayloadOf, H as EventMap, T as EventKey, 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-6rlBTmH9.js";
2
+ import { r as Scoped, t as FieldsOfScope } from "./types-N_cdRr1r.js";
3
+ import { a as createModule, c as CarryingCalls, d as actionsPlugin, f as setHandler, l as MadeHandled, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as Binding, t as Module, u as ScopedHandled } from "./module-G39MaVOt.js";
4
4
  import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
5
5
  //#region src/actions/action.d.ts
6
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>;
7
+ type Made<P, T extends string> = [P] extends [Free] ? FreeActionCreator<T> : [P] extends [Call<infer Q, infer R>] ? MadeHandled<Q, R, T> : ActionCreator<P, T>;
8
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
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>;
10
+ type PreparedHandled<P, R, T extends string, A extends unknown[], F> = ((...args: A) => ReturnType<MadeHandled<P, R, T>> & WithScope<F>) & Omit<MadeHandled<P, R, T>, never> & WithScope<F>;
11
11
  /**
12
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.
13
+ * action: `bus.emit(getUser("1"))` runs the handler and returns its result.
14
14
  *
15
15
  * - `createAction("user/loaded")` needs no generics: the payload type comes
16
16
  * from the event map of the bus that the action goes to, and the literal
@@ -54,22 +54,22 @@ type PreparedCommand<P, R, T extends string, A extends unknown[], F> = ((...args
54
54
  * ```
55
55
  */
56
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>;
57
+ export declare function createAction<P = void, R = void, T extends string = string, E extends EventMap = EventMap>(type: T, handler: Task<P, E, R>): MadeHandled<P, R, T>;
58
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
59
  prepare: (...args: A) => {
60
60
  payload: P;
61
61
  };
62
- } & S): PreparedCommand<P, R, T, A, FieldsOfScope<EventMap, ScopeOf<S>>>;
62
+ } & S): PreparedHandled<P, R, T, A, FieldsOfScope<EventMap, ScopeOf<S>>>;
63
63
  export declare function createAction<P, R, A extends unknown[], T extends string, S extends Scope = Record<never, never>>(type: T, options: {
64
64
  handle: Task<P, Scoped<EventMap, ScopeOf<S>>, R>;
65
65
  prepare: (...args: A) => {
66
66
  payload: P;
67
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>>;
68
+ } & S): PreparedHandled<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): ScopedHandled<P, R, T, FieldsOfScope<EventMap, S>>;
70
70
  export declare function createAction<P, R, T extends string, S extends Scope = Record<never, never>>(type: T, options: {
71
71
  handle: Task<P, Scoped<EventMap, ScopeOf<S>>, R>;
72
- } & S): ScopedCommand<P, R, T, FieldsOfScope<EventMap, ScopeOf<S>>>;
72
+ } & S): ScopedHandled<P, R, T, FieldsOfScope<EventMap, ScopeOf<S>>>;
73
73
  export declare function createAction<A extends unknown[], P, T extends string, S extends Scope = Record<never, never>>(type: T, options: {
74
74
  prepare: (...args: A) => {
75
75
  payload: P;
@@ -127,8 +127,8 @@ type Creator = {
127
127
  readonly type: string;
128
128
  };
129
129
  type Outcome = string | Creator;
130
- /** What `createJob` returns: the command of the job, with its four actions as properties. */
131
- type Job<P, R, T extends string, S extends Outcome, F extends Outcome, PE extends Outcome = `${T}/pending`, CE extends Outcome = `${T}/cancel`> = MadeCommand<P, Promise<Awaited<R> | undefined>, T> & {
130
+ /** What `createJob` returns: the action of the job, with its four outcome creators as properties. */
131
+ type Job<P, R, T extends string, S extends Outcome, F extends Outcome, PE extends Outcome = `${T}/pending`, CE extends Outcome = `${T}/cancel`> = MadeHandled<P, Promise<Awaited<R> | undefined>, T> & {
132
132
  /** Made from a string with the payload of the call as its payload, or the creator that was given. */
133
133
  readonly pending: PE extends string ? ActionCreator<P, PE> : PE;
134
134
  /** Made from a string with the result as its payload, or the creator that was given. */
@@ -139,13 +139,13 @@ type Job<P, R, T extends string, S extends Outcome, F extends Outcome, PE extend
139
139
  readonly cancel: CE extends string ? ActionCreator<unknown, CE> : CE;
140
140
  };
141
141
  /**
142
- * Creates a job: a command whose outcome is sent on as actions. When the
142
+ * Creates a job: an action whose outcome is sent on as actions. When the
143
143
  * handler starts, `job.pending(payload)` is emitted on the bus. When it
144
144
  * succeeds, `job.success(result)` follows, and when it fails, `job.fail(error)`.
145
145
  * When the task is aborted after it started, `job.cancel(reason)` follows
146
146
  * instead. After `pending`, exactly one of the three closes the call. A job is
147
147
  * made for the case where nobody waits for the result and the bus carries it
148
- * on, like `createAsyncThunk` or an effector effect. It returns the command,
148
+ * on, like `createAsyncThunk` or an effector effect. It returns the action,
149
149
  * with the four actions on it.
150
150
  *
151
151
  * A scope as the last argument, `{ cache, $effects: { race } }`, gives the handler
@@ -159,14 +159,14 @@ type Job<P, R, T extends string, S extends Outcome, F extends Outcome, PE extend
159
159
  *
160
160
  * `bus.emit(job(payload))` returns a promise of the result. An error of the
161
161
  * handler always counts as handled: it goes to `job.fail` and the promise
162
- * resolves with `undefined`; a command is the tool for a result that must reject.
162
+ * resolves with `undefined`; an action is the tool for a result that must reject.
163
163
  * The actions are emitted as the task that ran the job, also for a handler bound
164
- * with `commands.handle`. Once the task is aborted, `success` and `fail` are
164
+ * with `actions.handle`. Once the task is aborted, `success` and `fail` are
165
165
  * skipped and `cancel` is sent when the handler settles (a handler that never
166
166
  * settles sends nothing). A call that does not start, because a policy drops it
167
167
  * or it is aborted while it waits in a `queue`, sends none of the four. A
168
168
  * missing handler is not an outcome: `emit` throws `MissingHandlerError`.
169
- * Calling the job builds `{ type, payload }` like a command; it does not run
169
+ * Calling the job builds `{ type, payload }` like an action; it does not run
170
170
  * the handler.
171
171
  *
172
172
  * @example
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-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};
1
+ import{n as e,t}from"./onAbort-BgMfspK4.js";import{i as n,n as r}from"./context-B5Z2RpJt.js";import{t as i}from"./emit-key-C6FL7Ewn.js";import{t as a}from"./event-DVcW0mME.js";import{r as o}from"./bus-DFlmNJ6h.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 action "${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,n,r,a)=>{let o=t;o[i]=!0;try{D(t,n,r,a)}catch(t){e(`cancel listener`,t)}o[i]=!1},k=e=>{try{return Promise.resolve(e())}catch(e){if(e instanceof _)throw e;return Promise.reject(e)}},A=(n,r,i={},a)=>{let l=v(n,r),u=e=>E(i[e]??`${n}/${e}`),d=u(`pending`),p=u(`success`),m=u(`fail`),h=u(`cancel`),g=(n,r,i,o)=>{let s=i,l=`idle`,u=()=>{},f=()=>{l=`closed`,u()},g=e=>{l===`started`&&(f(),O(s,h,e,a))},_=()=>{l===`idle`&&(l=`started`,u=t(s,g),D(s,d,r,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(n,null,[r,i]))).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(r??{},s)===!0;function b(e,t){return typeof t==`object`?r?g(l,e,t,y):Reflect.apply(l,null,[e,t]):f(o(S,n,e),a)}let x=Object.assign(b,{type:n,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=(i=[])=>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 r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Map;return{mount:o=>{let l=r.get(o);if(l)return l;let u=i.get(o.name);u&&r.get(u)?.();let d=n(e,o.name),f=d.ctx,p=c(f),m=()=>{r.delete(o),i.get(o.name)===o&&i.delete(o.name),f.abort(),d.unlink()};r.set(o,m),i.set(o.name,o);let h=o.scope,g=I(a,h),_=(e,n)=>{let r=Reflect.apply(s.handle,null,R(g,e,n));return t(f,r),r},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=>r.get(e)?.(),isMounted:e=>r.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(...i)}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))),i.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{n as e}from"./onAbort-BgMfspK4.js";import{n as t,o as n,r}from"./context-B5Z2RpJt.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,`action`,()=>t(f,o,e))}},use:e=>e(g),ctx:s.context,trace:s.trace};return g};export{l as n,c as r,d as t};
@@ -0,0 +1 @@
1
+ import{t as e}from"./onAbort-BgMfspK4.js";import{t}from"./emit-key-C6FL7Ewn.js";const n=t=>{let n=new AbortController;return{controller:n,unlink:e({signal:t},e=>n.abort(e))}},r=typeof __NANOEFFECTS_TRACE__>`u`||__NANOEFFECTS_TRACE__,i=/* @__PURE__ */ new WeakMap;let a;const o=()=>a,s=()=>{},c=(e,t,n,a)=>{let o=r&&i.get(e);o&&o.tracer.report(o.ref,t,n,a)},l=(e,t)=>{let n=r&&i.get(e);n&&n.tracer.rename?.(n.ref,t)},u=(e,t)=>{let n=r&&i.get(e);return n?n.tracer.settler(n.ref,t):s},d=(e,t,n)=>{let a=r&&i.get(e);return a?a.tracer.run(a.ref,t,e.signal,n):n()},f=Symbol(`nanoeffects.addContext`),p=(e,t)=>typeof e==`function`?e(t):e,m=({event:o,bus:c,tracer:l,parent:u})=>{let{controller:h,unlink:g}=n(u?.signal),{signal:_}=h,v=r&&l?{tracer:l,ref:l.task(o,u?.ref)}:void 0,y=(...e)=>{if(_.aborted&&!S[t])return;let n=c?.emit,r=a;a=v?.ref;try{return n?.(...e)}finally{a=r}},b=(...t)=>{if(_.aborted)return s;let n=c?.on,r=n?.(...t);if(!r)return s;let i=e({signal:_},r);return()=>{i(),r()}},x=async(e,...t)=>{_.throwIfAborted();let n=t[0],r=m({event:{type:o.type,payload:n},bus:c,tracer:l,parent:{signal:_,ref:v?.ref}});try{return await d(r.ctx,`run`,()=>e(n,r.ctx))}finally{r.unlink()}},S={...p(c?.ctx,o),type:o.type,payload:o.payload,signal:_,abort:e=>h.abort(e),emit:y,on:b,off:c?.off??s,run:x,[f]:c?.addContext};return c?.addContext?.(S),v&&i.set(S,v),{ctx:S,unlink:g}},h=(e,t)=>{let n=r?i.get(e):void 0;return m({event:{type:t??e.type??``,payload:e.payload},bus:{emit:e.emit,on:e.on,off:e.off,ctx:e,addContext:Reflect.get(e,f)},tracer:n?.tracer,parent:{signal:e.signal,ref:n?.ref}})};export{l as a,r as c,h as i,m as n,d as o,o as r,c as s,u as t};
@@ -0,0 +1,31 @@
1
+ import { H as EventMap, x as ContextOf } from "./action-creator-6rlBTmH9.js";
2
+ //#region src/core/signal-field-key.d.ts
3
+ /**
4
+ * Where `fromSignal` keeps the function that makes a context field from the signal of a
5
+ * task. `Symbol.for`, so `contextPlugin` finds it without importing `nanoeffects/signal`.
6
+ * `createBus` does not import this file.
7
+ */
8
+ declare const signalFieldKey: unique symbol;
9
+ //#endregion
10
+ //#region src/core/context-types.d.ts
11
+ /** What a function that makes the fields of a task gets to see. */
12
+ type ContextTask = {
13
+ type: string;
14
+ payload?: unknown;
15
+ };
16
+ /**
17
+ * `unknown` when none of the `fields` is already a context field of the bus,
18
+ * else `never`: the call does not compile. Used as `bus: Bus<E> & NoClash<…>`.
19
+ */
20
+ type NoClash<Fields extends object, E extends EventMap> = [keyof Fields & keyof ContextOf<E>] extends [never] ? unknown : never;
21
+ /**
22
+ * A context field that is made from the signal of each task, on its first read.
23
+ * Made by `fromSignal` in `nanoeffects/signal`; `contextPlugin` puts the made value on `ctx`.
24
+ */
25
+ type FromSignal<T> = {
26
+ readonly [signalFieldKey]: (signal: AbortSignal) => T;
27
+ };
28
+ /** `Fields` as `ctx` has them: a `FromSignal<T>` field is its `T`. */
29
+ type Resolved<Fields extends object> = { [K in keyof Fields]: Fields[K] extends FromSignal<infer T> ? T : Fields[K]; };
30
+ //#endregion
31
+ export { Resolved as i, FromSignal as n, NoClash as r, ContextTask as t };
package/dist/context.d.ts CHANGED
@@ -1,5 +1,5 @@
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";
1
+ import { F as WithContext, H as EventMap, v as Bus } from "./action-creator-6rlBTmH9.js";
2
+ import { i as Resolved, r as NoClash, t as ContextTask } from "./context-types-DKNc5mkS.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
@@ -12,6 +12,11 @@ import { n as NoClash, t as ContextTask } from "./context-types-hCKgU8sC.js";
12
12
  * fields of the library (`signal`, `emit`, `run`, …) win, and a field that the
13
13
  * context already has is not replaced.
14
14
  *
15
+ * A field made with `fromSignal` from `nanoeffects/signal` is built from the signal
16
+ * of each task, when the task first reads it, so a client or a handle that needs a
17
+ * signal is declared once. A child task (`ctx.run`) builds its own. It is not
18
+ * copied by `{ ...ctx }`.
19
+ *
15
20
  * @example
16
21
  * ```ts
17
22
  * type Events = { "user/loaded": User };
@@ -20,6 +25,6 @@ import { n as NoClash, t as ContextTask } from "./context-types-hCKgU8sC.js";
20
25
  * bus.on("user/loaded", (user, { store }) => store.put(user)); // ctx.store: Store
21
26
  * ```
22
27
  */
23
- export declare const contextPlugin: <Fields extends object>(fields: Fields | ((task: ContextTask) => Fields)) => <E extends EventMap>(bus: Bus<E> & NoClash<Fields, E>) => Bus<E & WithContext<Fields>>;
28
+ export declare const contextPlugin: <Fields extends object>(fields: Fields | ((task: ContextTask) => Fields)) => <E extends EventMap>(bus: Bus<E> & NoClash<Fields, E>) => Bus<E & WithContext<Resolved<Fields>>>;
24
29
  //#endregion
25
30
  export type { ContextTask, NoClash };
package/dist/context.js CHANGED
@@ -1 +1 @@
1
- const e=e=>typeof e==`function`,t=e=>({type:Reflect.get(e,`type`),payload:Reflect.get(e,`payload`)}),n=n=>r=>{let i=r.addContext;return r.addContext=r=>{i?.(r);let a=e(n)?n(t(r)):n;for(let[e,t]of Object.entries(a))e in r||Reflect.set(r,e,t)},r};export{n as contextPlugin};
1
+ import{t as e}from"./signal-field-key-CWT-3OXC.js";const t=e=>typeof e==`function`,n=e=>({type:Reflect.get(e,`type`),payload:Reflect.get(e,`payload`)}),r=t=>{if(typeof t==`object`&&t)return Reflect.get(t,e)},i=(e,t)=>({configurable:!0,get(){let n=t(Reflect.get(this,`signal`));return Object.defineProperty(this,e,{configurable:!0,writable:!0,value:n}),n}}),a=/* @__PURE__ */ new WeakMap,o=(e,t)=>{let n=r(t);if(!(n&&typeof t==`object`&&t))return;let o=a.get(t);if(o?.key===e)return o.lazy;let s=i(e,n);return a.set(t,{key:e,lazy:s}),s},s=e=>r=>{let i=r.addContext;return r.addContext=r=>{i?.(r);let a=t(e)?e(n(r)):e;for(let[e,t]of Object.entries(a)){if(e in r)continue;let n=o(e,t);n?Object.defineProperty(r,e,n):Reflect.set(r,e,t)}},r};export{s as contextPlugin};
@@ -1 +1 @@
1
- import{u as e}from"./context-UcmrAIhP.js";const t=e=>typeof e==`object`&&!!e,n=2**31-1,r=(e,t)=>{let r={id:null};if(t===1/0)return r;let i=t=>{r.id=setTimeout(()=>{t>n?i(t-n):(r.id=null,e())},Math.min(t,n))};return i(t>0?t:0),r},i=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},a=(t,n)=>new Promise((a,o)=>{let s=r(()=>{c(),a()},typeof n==`function`?n():n),c=e(t,e=>{i(s),o(e)})});function o(e,n){return t(e)?a(e,n):t=>a(t,e)}export{t as i,i as n,r,o as t};
1
+ import{t as e}from"./onAbort-BgMfspK4.js";const t=e=>typeof e==`object`&&!!e,n=2**31-1,r=(e,t)=>{let r={id:null};if(t===1/0)return r;let i=t=>{r.id=setTimeout(()=>{t>n?i(t-n):(r.id=null,e())},Math.min(t,n))};return i(t>0?t:0),r},i=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},a=(t,n)=>new Promise((a,o)=>{let s=r(()=>{c(),a()},typeof n==`function`?n():n),c=e(t,e=>{i(s),o(e)})});function o(e,n){return t(e)?a(e,n):t=>a(t,e)}export{t as i,i as n,r,o as t};
package/dist/dev.d.ts CHANGED
@@ -1,5 +1,5 @@
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";
1
+ import { H as EventMap, Q as UnsubscribeCallback, v as Bus } from "./action-creator-6rlBTmH9.js";
2
+ import { i as WithApp, n as ModuleApi } from "./module-G39MaVOt.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">;
@@ -10,11 +10,27 @@ type DevOptions<E extends EventMap = EventMap> = {
10
10
  leaks?: boolean;
11
11
  /** Report the modules of `app` that are mounted, replaced and unmounted. Default `true`. */
12
12
  modules?: boolean;
13
+ /** Warn when a handler emits after its task was aborted, which means it ignored `ctx.signal`. Default `true`. */
14
+ abandoned?: boolean;
13
15
  /** Receives every message. Default: `console.warn` for leaks and `console.info` for modules. */
14
16
  log?: (message: string) => void;
15
17
  /** What `modulePlugin` returned, to report its modules. Without it the app that `modulePlugin` put on the bus is used, in either order of the two plugins. */
16
18
  app?: ReportedApp<E>;
17
19
  };
20
+ /** One signal that a handler lost: it kept working after its task was aborted. */
21
+ type LostSignal = {
22
+ /** `emit`: the handler emitted after the abort (the emit was dropped); `on`: it subscribed after the abort. */
23
+ kind: "emit" | "on";
24
+ /** The type of the task that was aborted: the event its handler works on. */
25
+ handler: string;
26
+ /** The event that was emitted or subscribed to. */
27
+ event: string;
28
+ };
29
+ /** What `getLostSignalsCount` takes. */
30
+ type LostSignalsOptions = {
31
+ /** How long to wait, in ms, before counting, so handlers that are still running can finish. Default 0: one turn of the event loop. */
32
+ wait?: number;
33
+ };
18
34
  /** A plugin that connects the diagnostics to a bus; the function it returns disconnects them. */
19
35
  type DevPlugin = <E extends EventMap>(options?: DevOptions<E>) => (bus: Bus<E> & WithApp) => UnsubscribeCallback;
20
36
  //#endregion
@@ -28,6 +44,10 @@ type DevPlugin = <E extends EventMap>(options?: DevOptions<E>) => (bus: Bus<E> &
28
44
  * the count: a file that was reloaded and subscribes again, or an
29
45
  * unsubscribe that is never called. The count follows the function that `on`
30
46
  * returns; `bus.off(event, fn)` is not seen.
47
+ * - **Handlers that ignore the signal.** When a handler emits after its task was aborted (a newer
48
+ * call of `latest`, an unmounted module), the emit is dropped, and one warning names the handler
49
+ * and the event: the handler did not stop when it was cancelled, usually because `ctx.signal` was
50
+ * never given to the request. Nothing is added to the policies; the check is this plugin's.
31
51
  * - **Modules.** It reports a module that is mounted, replaced by name and
32
52
  * unmounted, for the app that `modulePlugin` returned: the `app` option, or
33
53
  * else the one `modulePlugin` put on the bus, whichever plugin was used first.
@@ -43,5 +63,26 @@ type DevPlugin = <E extends EventMap>(options?: DevOptions<E>) => (bus: Bus<E> &
43
63
  * ```
44
64
  */
45
65
  export declare const devPlugin: DevPlugin;
66
+ /**
67
+ * The signals that handlers of a bus lost so far, for a test: every emit or `ctx.on` that a handler made after
68
+ * its task was aborted (the bus drops it), which means the handler kept working after it was cancelled. The bus
69
+ * needs `devPlugin` with `abandoned` on. It waits one turn of the event loop first (`wait` for longer), so handlers
70
+ * that are finishing are counted.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const bus = createBus<Events>();
75
+ * bus.use(devPlugin({ log: () => {} }));
76
+ * bus.on("search", latest(searchHandler));
77
+ *
78
+ * bus.emit("search", "a");
79
+ * bus.emit("search", "ab"); // cancels the first call
80
+ *
81
+ * expect(await getLostSignalsCount(bus, { wait: 50 })).toBe(0);
82
+ * ```
83
+ */
84
+ export declare const getLostSignals: (bus: object, options?: LostSignalsOptions) => Promise<LostSignal[]>;
85
+ /** The number of signals that handlers of a bus lost so far: see `getLostSignals` for the list. */
86
+ export declare const getLostSignalsCount: (bus: object, options?: LostSignalsOptions) => Promise<number>;
46
87
  //#endregion
47
- export type { DevOptions, DevPlugin };
88
+ export type { DevOptions, DevPlugin, LostSignal, LostSignalsOptions };
package/dist/dev.js CHANGED
@@ -1 +1,2 @@
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};
1
+ import{t as e}from"./emit-key-C6FL7Ewn.js";import{t}from"./event-DVcW0mME.js";import{t as n}from"./site-DLvUoXs3.js";import{t as r}from"./mount-each-D54UqAhZ.js";const i=`[nanoeffects]`,a=(e={})=>t=>{let{maxListeners:n=10,leaks:r=!0,modules:i=!0,abandoned:a=!0,app:o}=e,s=e.log??(e=>console.warn(e)),c=e.log??(e=>console.info(e)),u=[];return r&&u.push(l(t,n,s)),i&&u.push(p(t,o,c)),a&&u.push(f(t,s)),()=>{for(let e of u.splice(0))e()}},o=e=>typeof e==`function`&&typeof Reflect.get(e,`type`)!=`string`?`*`:t(e),s=()=>(((/* @__PURE__ */ Error()).stack?.split(`
2
+ `)??[])[4]??``).trim().replace(/^at /,``),c=e=>{let t=e[2],r=typeof t==`object`&&t?Reflect.get(t,`traceId`):void 0,i=typeof r==`string`?s():``;return typeof r==`string`&&i!==``?n(r,i):()=>{}},l=(e,t,n)=>{let r=e.on,a=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Set,l=!0,u=(...u)=>{if(!l)return Reflect.apply(r,e,u);let[d]=u,f=o(d),p=(a.get(f)??0)+1;a.set(f,p),p>t&&!s.has(f)&&(s.add(f),n(`${i} ${p} listeners of "${f}" were added and not unsubscribed (more than ${t}). A file that is reloaded and subscribes again, or an unsubscribe that is never called?`));let m=Reflect.apply(r,e,u),h=c(u),g=!1;return()=>{if(!g){g=!0,h();let e=(a.get(f)??1)-1;a.set(f,e),e<=t&&s.delete(f)}m()}};return e.on=u,()=>{l=!1,e.on===u&&(e.on=r)}},u=e=>typeof e==`string`?e:String(Reflect.get(Object(e),`type`)),d=/* @__PURE__ */ new WeakMap,f=(t,n)=>{let r=t.addContext,a=/* @__PURE__ */ new Set,o=[];d.set(t,o);let s=!0,c=t=>{r?.(t);let c=t,l=c.emit;c.emit=(r,...d)=>{let f=Reflect.get(t,e),p=u(r),m=`${c.type}\u0000${p}`,h=s&&c.signal.aborted&&f!==!0;return h&&o.push({kind:`emit`,handler:c.type,event:p}),h&&!a.has(m)&&(a.add(m),n(`${i} the handler of "${c.type}" emitted "${p}" after its task was aborted, so the emit was dropped. The handler kept running after it was cancelled: pass ctx.signal to the request (fetch(url, { signal: ctx.signal })) or give ctx to an effect (retry(ctx, ...)).`)),l(r,...d)};let d=c.on;c.on=(e,...t)=>{let r=u(e),l=`${c.type}\u0000on\u0000${r}`,f=s&&c.signal.aborted;return f&&o.push({kind:`on`,handler:c.type,event:r}),f&&!a.has(l)&&(a.add(l),n(`${i} the handler of "${c.type}" subscribed to "${r}" after its task was aborted, so the subscription was dropped. The handler kept running after it was cancelled: pass ctx.signal to the request or give ctx to an effect.`)),d(e,...t)}};return t.addContext=c,()=>{s=!1,t.addContext===c&&(t.addContext=r)}},p=(e,t,n)=>{let r=t??e.app;if(r)return m(r,n);let i,a;return Object.defineProperty(e,"app",{configurable:!0,enumerable:!0,get:()=>i,set:e=>{a?.(),i=e,a=e?m(e,n):void 0}}),()=>{a?.(),Object.defineProperty(e,"app",{configurable:!0,enumerable:!0,writable:!0,value:i})}},m=(e,t)=>{let{mount:n,unmount:a}=e,o=/* @__PURE__ */ new Map,s=r({mount:r=>{let a=o.get(r.name);if(a===r&&e.isMounted(r))return n(r);let s=a!==void 0&&e.isMounted(a),c=n(r);return o.set(r.name,r),t(`${i} module "${r.name}" ${s?`replaced`:`mounted`}`),()=>{e.isMounted(r)&&t(`${i} module "${r.name}" unmounted`),c()}},unmount:n=>{e.isMounted(n)&&t(`${i} module "${n.name}" unmounted`),a(n)},isMounted:t=>e.isMounted(t)});return e.mount=s.mount,e.unmount=s.unmount,()=>{e.mount=n,e.unmount=a}},h=async(e,t={})=>{let n=d.get(e);if(!n)throw Error("getLostSignalsCount: the bus has no devPlugin, or devPlugin has `abandoned: false`. Use bus.use(devPlugin()) before the test.");return await new Promise(e=>setTimeout(e,t.wait??0)),[...n]},g=async(e,t={})=>(await h(e,t)).length;export{a as devPlugin,h as getLostSignals,g as getLostSignalsCount};
package/dist/effects.d.ts CHANGED
@@ -1,5 +1,5 @@
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";
1
+ import { H as EventMap, I as WithSignal, b as Context, f as Effect, q as Task } from "./action-creator-6rlBTmH9.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-BWNP23hr.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
package/dist/effects.js CHANGED
@@ -1 +1 @@
1
- import{i as e,n as t,r as n,t as r}from"./delay-18LJ8jSk.js";import{d as i,i as a,o,s,t as c,u as l}from"./context-UcmrAIhP.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=l(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:o}=a(t??{}),d=c(i,e);s(i,e,`start`),l(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{o()}},f=async(e,t)=>{let{ctx:n,unlink:r}=a(e);try{return await o(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=a(e),i=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(o(r.ctx,`run`,i))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=e=>{let t=e?.concurrency??1/0;if(t!==1/0&&!(Number.isInteger(t)&&t>=1))throw RangeError(`concurrency must be a positive integer`);return t},v=(e,t,n,r)=>{let i=Object.entries(t),s=[],c=i.map(([e])=>[e,new Promise(e=>s.push(e))]),l=/* @__PURE__ */ new Set,u=0,d=0,f=!1,p=()=>{for(;!f&&!e.signal.aborted&&d<n&&u<i.length;){let t=u++,[,n]=i[t],c=a(e),m=()=>n(c.ctx),h=()=>{c.unlink(),l.delete(c.ctx.abort),d--};l.add(c.ctx.abort),d++;let g=new Promise(e=>e(o(c.ctx,`run`,m))).then(e=>(h(),p(),e),e=>{throw h(),f=r,p(),e});s[t]?.(g)}};return p(),{tasks:c,cancelAll:()=>{f=!0;for(let e of l)e()}}},y=(t,n)=>{if(t.length!==1)return n(...t);let[r]=t;if(e(Reflect.get(r,`signal`)))throw TypeError(`A group takes effects: call it as (effects), or as (ctx, effects); a context alone has none`);return e=>n(e,r)},b=(e,t,n,r,i,a)=>{let o=_(a),s=()=>{};return d(e,t,async t=>{let i=o===1/0?g(t,n):v(t,n,o,e===`all`);return s=i.cancelAll,r(i.tasks)},e=>{(e||i===`end`)&&s()})};function x(...e){return y(e,S)}const S=(e,t,n)=>b(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),C=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function w(...e){return y(e,T)}const T=(e,t,n)=>b(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>C(e))),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),E=e=>e>0?e:0,D=(e={})=>{let t=E(e.base??100),n=e.factor??2,r=E(e.max??1/0),i=e.jitter??!1;return e=>{let a=E(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},O=(e,t)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((n,r)=>{let a=[],o=`pending`,s=e=>{try{e()}catch(e){i(`cancel cleanup failed`,e)}},c=l(e,e=>{o=`cancelled`;for(let e of a.reverse())s(e);r(e)}),u=e=>(...t)=>{o===`pending`&&(o=`settled`,c(),a.length=0,e(...t))},d=e=>{o===`pending`?a.push(e):o===`cancelled`&&s(e)};try{t({resolve:u(n),reject:u(r),onCancel:d})}catch(e){u(r)(e)}}),k=Symbol(`nanoeffects.effects.effect`),A=e=>t=>{let n=t.addContext,r=Object.entries(e);return t.addContext=e=>{n?.(e);for(let[t,n]of r){let r=Reflect.get(e,t);if(r===void 0||r[k]===n){let r=(...t)=>n(e,...t);r[k]=n,Reflect.set(e,t,r)}}},t},j=()=>/* @__PURE__ */ TypeError(`A Task is called as (payload, ctx), or as (ctx) when a group starts it; the single argument is not a context`),M=t=>{if(e(t)&&`signal`in t)return t;throw j()},N=(e,t,n)=>t===void 0?n(M(e),void 0):n(t,e),P=(e,r,i,a)=>{if(e.signal.aborted)return Promise.resolve();let o=a.leading??!1,s=a.waitForFn??!1;return d(`poll`,e,e=>new Promise((a,c)=>{let u=0,d=null,p=()=>{d!==null&&(t(d),d=null)},m=e=>{try{d=n(h,typeof i==`function`?i(e):i)}catch(e){p(),c(e)}},h=()=>{d=null,s||m(u+1),g()},g=()=>{let t=u++;f(e,e=>r(e,t)).then(()=>{s&&!e.signal.aborted&&m(u)},e=>{p(),c(e)})};l(e,p),o?(g(),s||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function F(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{},a=(t,n)=>P(t,m(r,n),e,i);return(e,t)=>N(e,t,a)}let i=t;return P(e,(e,t)=>i(t),n,r)}function I(...e){return y(e,L)}const L=(e,t)=>{let n=h(t);return Object.keys(t).length===0?Promise.resolve(n):b(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)},R=(e,t,n)=>typeof e==`function`?e(t,n):e,z=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),B=(e,t,n)=>d(`retry`,e,async e=>{let{times:i,delay:a,shouldRetry:o}=z(n);for(let n=1;;n++)try{return await f(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<i)||!o(t,n))throw t;let s=R(a,n,t);s>0&&await r(e,s)}});function V(e,t,n={}){if(typeof e==`function`){let n=e,r=t??{},i=(e,t)=>B(e,m(n,t),r);return(e,t)=>N(e,t,i)}let r=t;return B(e,(e,t)=>r(t),n)}const H=(e,t,n={})=>d(`take`,e,r=>new Promise((i,a)=>{let{predicate:o}=n,s=[],c=()=>{for(let e of s)e()},u=e=>{c(),a(e)},d=t;s.push(e.on(d,e=>{(!o||o(e))&&(c(),i(e))})),s.push(l(r,u)),s.push(l({signal:n.signal},u))}));function U(t,n,r){if(e(t))return H(t,n,r);let i=n;return e=>H(e,t,i)}const W=(e,r,i)=>d(`timeout`,e,async e=>{let s=a(e),c=n(()=>s.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await u(Promise.resolve(o(s.ctx,`run`,()=>i(s.ctx))),s.ctx)}finally{t(c),s.unlink()}});function G(e,t,n){if(typeof e==`number`){let n=t,r=(t,r)=>W(t,e,m(n,r));return(e,t)=>N(e,t,r)}return W(e,t,n)}export{x as all,w as allSettled,D as backoff,O as cancellable,r as delay,A as effectsPlugin,l as onAbort,F as poll,I as race,V as retry,U as take,G as timeout};
1
+ import{i as e,n as t,r as n,t as r}from"./delay-5OhJZZQ0.js";import{n as i,t as a}from"./onAbort-BgMfspK4.js";import{i as o,o as s,s as c,t as l}from"./context-B5Z2RpJt.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=a(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:s}=o(t??{}),d=l(i,e);c(i,e,`start`),a(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{s()}},f=async(e,t)=>{let{ctx:n,unlink:r}=o(e);try{return await s(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=o(e),i=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(s(r.ctx,`run`,i))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=e=>{let t=e?.concurrency??1/0;if(t!==1/0&&!(Number.isInteger(t)&&t>=1))throw RangeError(`concurrency must be a positive integer`);return t},v=(e,t,n,r)=>{let i=Object.entries(t),a=[],c=i.map(([e])=>[e,new Promise(e=>a.push(e))]),l=/* @__PURE__ */ new Set,u=0,d=0,f=!1,p=()=>{for(;!f&&!e.signal.aborted&&d<n&&u<i.length;){let t=u++,[,n]=i[t],c=o(e),m=()=>n(c.ctx),h=()=>{c.unlink(),l.delete(c.ctx.abort),d--};l.add(c.ctx.abort),d++;let g=new Promise(e=>e(s(c.ctx,`run`,m))).then(e=>(h(),p(),e),e=>{throw h(),f=r,p(),e});a[t]?.(g)}};return p(),{tasks:c,cancelAll:()=>{f=!0;for(let e of l)e()}}},y=(t,n)=>{if(t.length!==1)return n(...t);let[r]=t;if(e(Reflect.get(r,`signal`)))throw TypeError(`A group takes effects: call it as (effects), or as (ctx, effects); a context alone has none`);return e=>n(e,r)},b=(e,t,n,r,i,a)=>{let o=_(a),s=()=>{};return d(e,t,async t=>{let i=o===1/0?g(t,n):v(t,n,o,e===`all`);return s=i.cancelAll,r(i.tasks)},e=>{(e||i===`end`)&&s()})};function x(...e){return y(e,S)}const S=(e,t,n)=>b(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),C=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function w(...e){return y(e,T)}const T=(e,t,n)=>b(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>C(e))),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),E=e=>e>0?e:0,D=(e={})=>{let t=E(e.base??100),n=e.factor??2,r=E(e.max??1/0),i=e.jitter??!1;return e=>{let a=E(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},O=(e,t)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((n,r)=>{let o=[],s=`pending`,c=e=>{try{e()}catch(e){i(`cancel cleanup failed`,e)}},l=a(e,e=>{s=`cancelled`;for(let e of o.reverse())c(e);r(e)}),u=e=>(...t)=>{s===`pending`&&(s=`settled`,l(),o.length=0,e(...t))},d=e=>{s===`pending`?o.push(e):s===`cancelled`&&c(e)};try{t({resolve:u(n),reject:u(r),onCancel:d})}catch(e){u(r)(e)}}),k=Symbol(`nanoeffects.effects.effect`),A=e=>t=>{let n=t.addContext,r=Object.entries(e);return t.addContext=e=>{n?.(e);for(let[t,n]of r){let r=Reflect.get(e,t);if(r===void 0||r[k]===n){let r=(...t)=>n(e,...t);r[k]=n,Reflect.set(e,t,r)}}},t},j=()=>/* @__PURE__ */ TypeError(`A Task is called as (payload, ctx), or as (ctx) when a group starts it; the single argument is not a context`),M=t=>{if(e(t)&&`signal`in t)return t;throw j()},N=(e,t,n)=>t===void 0?n(M(e),void 0):n(t,e),P=(e,r,i,o)=>{if(e.signal.aborted)return Promise.resolve();let s=o.leading??!1,c=o.waitForFn??!1;return d(`poll`,e,e=>new Promise((o,l)=>{let u=0,d=null,p=()=>{d!==null&&(t(d),d=null)},m=e=>{try{d=n(h,typeof i==`function`?i(e):i)}catch(e){p(),l(e)}},h=()=>{d=null,c||m(u+1),g()},g=()=>{let t=u++;f(e,e=>r(e,t)).then(()=>{c&&!e.signal.aborted&&m(u)},e=>{p(),l(e)})};a(e,p),s?(g(),c||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function F(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{},a=(t,n)=>P(t,m(r,n),e,i);return(e,t)=>N(e,t,a)}let i=t;return P(e,(e,t)=>i(t),n,r)}function I(...e){return y(e,L)}const L=(e,t)=>{let n=h(t);return Object.keys(t).length===0?Promise.resolve(n):b(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)},R=(e,t,n)=>typeof e==`function`?e(t,n):e,z=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),B=(e,t,n)=>d(`retry`,e,async e=>{let{times:i,delay:a,shouldRetry:o}=z(n);for(let n=1;;n++)try{return await f(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<i)||!o(t,n))throw t;let s=R(a,n,t);s>0&&await r(e,s)}});function V(e,t,n={}){if(typeof e==`function`){let n=e,r=t??{},i=(e,t)=>B(e,m(n,t),r);return(e,t)=>N(e,t,i)}let r=t;return B(e,(e,t)=>r(t),n)}const H=(e,t,n={})=>d(`take`,e,r=>new Promise((i,o)=>{let{predicate:s}=n,c=[],l=()=>{for(let e of c)e()},u=e=>{l(),o(e)},d=t;c.push(e.on(d,e=>{(!s||s(e))&&(l(),i(e))})),c.push(a(r,u)),c.push(a({signal:n.signal},u))}));function U(t,n,r){if(e(t))return H(t,n,r);let i=n;return e=>H(e,t,i)}const W=(e,r,i)=>d(`timeout`,e,async e=>{let a=o(e),c=n(()=>a.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await u(Promise.resolve(s(a.ctx,`run`,()=>i(a.ctx))),a.ctx)}finally{t(c),a.unlink()}});function G(e,t,n){if(typeof e==`number`){let n=t,r=(t,r)=>W(t,e,m(n,r));return(e,t)=>N(e,t,r)}return W(e,t,n)}export{x as all,w as allSettled,D as backoff,O as cancellable,r as delay,A as effectsPlugin,a as onAbort,F as poll,I as race,V as retry,U as take,G as timeout};
@@ -0,0 +1 @@
1
+ const e=Symbol();export{e as t};