nanoeffects 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/{action-creator-D48fp13T.d.ts → action-creator-c292nK7v.d.ts} +130 -34
- package/dist/actions.d.ts +54 -5
- package/dist/actions.js +1 -1
- package/dist/{bus-Cho463Sq.js → bus-BAs9x7IQ.js} +1 -1
- package/dist/{context-DlA80GOA.js → context-CK0ZomWt.js} +1 -1
- package/dist/context-plugin-1pYmSQEG.d.ts +34 -0
- package/dist/dev.d.ts +2 -2
- package/dist/effects.d.ts +27 -129
- package/dist/effects.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/{module-DVX8aYlq.d.ts → module-BlF2KSgy.d.ts} +34 -5
- package/dist/notrace/{action-creator-D48fp13T.d.ts → action-creator-DKG_sIia.d.ts} +130 -34
- package/dist/notrace/actions.d.ts +96 -7
- package/dist/notrace/actions.js +1 -1
- package/dist/notrace/{bus-B12SvxLv.js → bus-Bdk0YyFQ.js} +1 -1
- package/dist/notrace/{context-yAWj0BFZ.js → context-CctVmHLC.js} +1 -1
- package/dist/notrace/context-plugin-Dt1IgVo8.d.ts +34 -0
- package/dist/notrace/{delay-Cgvn16oY.js → delay-B_W1tnkS.js} +1 -1
- package/dist/notrace/effects.d.ts +27 -129
- package/dist/notrace/effects.js +1 -1
- package/dist/notrace/index.d.ts +3 -2
- package/dist/notrace/index.js +1 -1
- package/dist/notrace/plugin-B0AXKusc.d.ts +207 -0
- package/dist/notrace/policies.d.ts +1 -1
- package/dist/notrace/policies.js +1 -1
- package/dist/notrace/redux.d.ts +18 -20
- package/dist/notrace/redux.js +1 -1
- package/dist/observable.d.ts +1 -1
- package/dist/plugin-CCYlC0XS.d.ts +207 -0
- package/dist/policies.d.ts +1 -1
- package/dist/policies.js +1 -1
- package/dist/react.d.ts +50 -0
- package/dist/react.js +1 -0
- package/dist/redux.d.ts +18 -20
- package/dist/redux.js +1 -1
- package/dist/scope-key-B7l7mUS5.js +1 -0
- package/dist/scope.d.ts +58 -0
- package/dist/scope.js +1 -0
- package/dist/trace.d.ts +1 -1
- package/dist/types-mLaAx-EZ.d.ts +15 -0
- package/docs/README.md +7 -1
- package/docs/actions.md +25 -1
- package/docs/context.md +26 -2
- package/docs/effects.md +83 -5
- package/docs/guide.md +24 -0
- package/docs/migrating-from-effector.md +293 -0
- package/docs/migrating-from-rxjs.md +127 -0
- package/docs/migrating-from-saga.md +93 -0
- package/docs/observable.md +1 -0
- package/docs/package.md +13 -2
- package/docs/policies.md +1 -0
- package/docs/react.md +157 -0
- package/docs/scope.md +226 -0
- package/docs/stores.md +429 -40
- package/docs/typescript.md +153 -0
- package/llms-full.txt +2925 -0
- package/llms.txt +49 -0
- package/package.json +44 -6
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { R as EventMap, j as WithContext, p as Bus, y as ContextOf } from "./action-creator-DKG_sIia.js";
|
|
2
|
+
//#region src/core/context-plugin.d.ts
|
|
3
|
+
/** What a function that makes the fields of a task gets to see. */
|
|
4
|
+
type ContextTask = {
|
|
5
|
+
type: string;
|
|
6
|
+
payload?: unknown;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* `unknown` when none of the `fields` is already a context field of the bus,
|
|
10
|
+
* else `never`: the call does not compile. Used as `bus: Bus<E> & NoClash<…>`.
|
|
11
|
+
*/
|
|
12
|
+
type NoClash<Fields extends object, E extends EventMap> = [keyof Fields & keyof ContextOf<E>] extends [never] ? unknown : never;
|
|
13
|
+
/**
|
|
14
|
+
* Puts `fields` on the context of every task of the bus: a store, a client, a
|
|
15
|
+
* logger. The types come from the value, so the event map needs no
|
|
16
|
+
* `WithContext`. Returns the same bus, typed with the fields. A function gets
|
|
17
|
+
* `{ type, payload }` of the task and returns its fields.
|
|
18
|
+
*
|
|
19
|
+
* Several uses merge with each other, with the `context` option of `createBus`
|
|
20
|
+
* and with `effectsPlugin`. A name that the bus already has is a type error. The
|
|
21
|
+
* fields of the library (`signal`, `emit`, `run`, …) win, and a field that the
|
|
22
|
+
* context already has is not replaced.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* type Events = { "user/loaded": User };
|
|
27
|
+
*
|
|
28
|
+
* const bus = createBus<Events>().use(contextPlugin({ store }));
|
|
29
|
+
* bus.on("user/loaded", (user, { store }) => store.put(user)); // ctx.store: Store
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare const contextPlugin: <Fields extends object>(fields: Fields | ((task: ContextTask) => Fields)) => <E extends EventMap>(bus: Bus<E> & NoClash<Fields, E>) => Bus<E & WithContext<Fields>>;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { NoClash as n, contextPlugin as r, ContextTask as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{s as e}from"./context-
|
|
1
|
+
import{s as e}from"./context-CctVmHLC.js";const t=2**31-1,n=(e,n)=>{let r={id:null};if(n===1/0)return r;let i=n=>{r.id=setTimeout(()=>{n>t?i(n-t):(r.id=null,e())},Math.min(n,t))};return i(n>0?n:0),r},r=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},i=(t,i)=>new Promise((a,o)=>{let s=n(()=>{c(),a()},typeof i==`function`?i():i),c=e(t,e=>{r(s),o(e)})});export{r as n,n as r,i as t};
|
|
@@ -1,89 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Resolves after `ms`, or rejects early if `ctx.signal` aborts. `ms` can be a
|
|
5
|
-
* function that returns the number of ms, called once when the delay starts:
|
|
6
|
-
* handy for a random pause (jitter).
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* await delay({}, 500);
|
|
11
|
-
*
|
|
12
|
-
* // 200 to 400 ms
|
|
13
|
-
* await delay({}, () => 200 + Math.random() * 200);
|
|
14
|
-
*
|
|
15
|
-
* // inside a task: stops waiting when the task is aborted
|
|
16
|
-
* bus.on("retry", async (_, ctx) => {
|
|
17
|
-
* await delay(ctx, 1000);
|
|
18
|
-
* await load();
|
|
19
|
-
* });
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export declare const delay: (ctx: {
|
|
23
|
-
signal?: AbortSignal | undefined;
|
|
24
|
-
}, ms: number | (() => number)) => Promise<void>;
|
|
25
|
-
//#endregion
|
|
1
|
+
import { H as Task, R as EventMap, l as Effect } from "./action-creator-DKG_sIia.js";
|
|
2
|
+
import { a as RaceStarter, c as all, d as delay, i as take, l as EffectContext, n as effectsPlugin, o as race, r as TakeOptions, s as allSettled, u as Starter } from "./plugin-B0AXKusc.js";
|
|
26
3
|
//#region src/utils/onAbort.d.ts
|
|
27
4
|
export declare const onAbort: (ctx: {
|
|
28
5
|
signal?: AbortSignal | undefined;
|
|
29
6
|
}, fn: (reason: unknown) => void) => (() => void);
|
|
30
7
|
//#endregion
|
|
31
|
-
//#region src/effects/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
8
|
+
//#region src/effects/backoff.d.ts
|
|
9
|
+
type BackoffOptions = {
|
|
10
|
+
/** Pause before the second attempt, in ms. Default 100. */
|
|
11
|
+
base?: number;
|
|
12
|
+
/** How many times each pause is longer than the one before. Default 2. */
|
|
13
|
+
factor?: number;
|
|
14
|
+
/** Longest pause, in ms. Default `Infinity`. */
|
|
15
|
+
max?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Use a random pause from 0 up to the computed one ("full jitter"), so
|
|
18
|
+
* clients that failed together do not retry together. Default `false`.
|
|
19
|
+
*/
|
|
20
|
+
jitter?: boolean;
|
|
36
21
|
};
|
|
37
|
-
type Starter<T> = (ctx: EffectContext) => T | PromiseLike<T>;
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/effects/all.d.ts
|
|
40
22
|
/**
|
|
41
|
-
*
|
|
23
|
+
* Builds the `delay` of `retry`: the pause grows as `base * factor ** (attempt - 1)`
|
|
24
|
+
* and never passes `max`. `retry` counts attempts from 1; `poll` counts calls from
|
|
25
|
+
* 0, so there the first pause is `base / factor`.
|
|
42
26
|
*
|
|
43
27
|
* @example
|
|
44
28
|
* ```ts
|
|
45
|
-
* bus.on(
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* });
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export declare function all<T extends Record<string, Starter<unknown>>>(ctx: {
|
|
56
|
-
signal?: AbortSignal;
|
|
57
|
-
}, effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
58
|
-
export declare function all<const T extends readonly Starter<unknown>[]>(ctx: {
|
|
59
|
-
signal?: AbortSignal;
|
|
60
|
-
}, effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/effects/allSettled.d.ts
|
|
63
|
-
/**
|
|
64
|
-
* Runs all starters and waits for every one to settle, whether it succeeds or
|
|
65
|
-
* fails: nothing is cancelled when a starter fails. The result has, for each
|
|
66
|
-
* starter, `{ status: "fulfilled", value }` or `{ status: "rejected", reason }`.
|
|
67
|
-
* Only an abort of `ctx` rejects it, with the abort reason.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```ts
|
|
71
|
-
* bus.on("load", async (id, ctx) => {
|
|
72
|
-
* const { user, posts } = await allSettled(ctx, {
|
|
73
|
-
* user: ({ signal }) => fetchUser(id, { signal }),
|
|
74
|
-
* posts: ({ signal }) => fetchPosts(id, { signal }),
|
|
75
|
-
* });
|
|
76
|
-
*
|
|
77
|
-
* if (user.status === "fulfilled") render(user.value);
|
|
78
|
-
* });
|
|
29
|
+
* bus.on(
|
|
30
|
+
* "load",
|
|
31
|
+
* retry(loadUser, {
|
|
32
|
+
* times: 5,
|
|
33
|
+
* delay: backoff({ base: 200, max: 5000, jitter: true }), // 200, 400, 800, ... up to 5 s, randomised
|
|
34
|
+
* }),
|
|
35
|
+
* );
|
|
79
36
|
* ```
|
|
80
37
|
*/
|
|
81
|
-
export declare
|
|
82
|
-
signal?: AbortSignal;
|
|
83
|
-
}, effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
84
|
-
export declare function allSettled<const T extends readonly Starter<unknown>[]>(ctx: {
|
|
85
|
-
signal?: AbortSignal;
|
|
86
|
-
}, effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
38
|
+
export declare const backoff: (options?: BackoffOptions) => (attempt: number) => number;
|
|
87
39
|
//#endregion
|
|
88
40
|
//#region src/effects/cancellable.d.ts
|
|
89
41
|
type CancellableHandle<T> = {
|
|
@@ -160,32 +112,6 @@ export declare function poll(ctx: {
|
|
|
160
112
|
signal: AbortSignal;
|
|
161
113
|
}, fn: (tick: number) => unknown, ms: PollMs, options?: PollOptions): Promise<void>;
|
|
162
114
|
//#endregion
|
|
163
|
-
//#region src/effects/race.d.ts
|
|
164
|
-
type RaceStarter<T> = Starter<T>;
|
|
165
|
-
/**
|
|
166
|
-
* Runs all starters; first to settle wins, losers are cancelled via `ctx.abort`.
|
|
167
|
-
* The result holds only the winner's value, under its key or index.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* bus.on("load", async (id, ctx) => {
|
|
172
|
-
* const result = await race(ctx, {
|
|
173
|
-
* data: ({ signal }) => fetchData(id, { signal }),
|
|
174
|
-
* timeout: ({ signal }) => delay({ signal }, 5000),
|
|
175
|
-
* });
|
|
176
|
-
*
|
|
177
|
-
* if ("timeout" in result) throw new Error("timed out");
|
|
178
|
-
* render(result.data);
|
|
179
|
-
* });
|
|
180
|
-
* ```
|
|
181
|
-
*/
|
|
182
|
-
export declare function race<T extends Record<string, RaceStarter<unknown>>>(ctx: {
|
|
183
|
-
signal?: AbortSignal;
|
|
184
|
-
}, effects: T): Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
185
|
-
export declare function race<const T extends readonly RaceStarter<unknown>[]>(ctx: {
|
|
186
|
-
signal?: AbortSignal;
|
|
187
|
-
}, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
188
|
-
//#endregion
|
|
189
115
|
//#region src/effects/retry.d.ts
|
|
190
116
|
type RetryOptions = {
|
|
191
117
|
/** Total number of attempts, the first one included. Default 3. */
|
|
@@ -226,34 +152,6 @@ export declare function retry<T>(ctx: {
|
|
|
226
152
|
signal?: AbortSignal;
|
|
227
153
|
}, fn: RetryFn<T>, options?: RetryOptions): Promise<T>;
|
|
228
154
|
//#endregion
|
|
229
|
-
//#region src/effects/take.d.ts
|
|
230
|
-
type TakeOptions<P> = {
|
|
231
|
-
/** Wait for the first payload this accepts; others are skipped. */
|
|
232
|
-
predicate?: (payload: P) => boolean;
|
|
233
|
-
/** Stop waiting when this aborts, e.g. the signal of a `race` starter. */
|
|
234
|
-
signal?: AbortSignal | undefined;
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* Waits for the next `event` on the bus and resolves with its payload. It sees
|
|
238
|
-
* only events emitted after the call, takes only one, and unsubscribes when it
|
|
239
|
-
* is done. If `ctx` (or `options.signal`) aborts first, it unsubscribes and
|
|
240
|
-
* rejects with the abort reason.
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* ```ts
|
|
244
|
-
* bus.on("login", async (user, ctx) => {
|
|
245
|
-
* const reason = await take(ctx, "logout");
|
|
246
|
-
* cleanup(user, reason);
|
|
247
|
-
* });
|
|
248
|
-
*
|
|
249
|
-
* // wait for a matching event, but not longer than 5 s
|
|
250
|
-
* const done = await timeout(ctx, 5000, ({ signal }) =>
|
|
251
|
-
* take(ctx, "saved", { signal, predicate: (id) => id === draftId }),
|
|
252
|
-
* );
|
|
253
|
-
* ```
|
|
254
|
-
*/
|
|
255
|
-
export declare const take: <E extends EventMap, K extends Keys<E>>(ctx: Context<E>, event: K, options?: TakeOptions<E[K]>) => Promise<E[K]>;
|
|
256
|
-
//#endregion
|
|
257
155
|
//#region src/effects/timeout.d.ts
|
|
258
156
|
/**
|
|
259
157
|
* Runs a function; if it takes longer than `ms`, aborts its signal and rejects
|
|
@@ -281,4 +179,4 @@ export declare function timeout<T>(ctx: {
|
|
|
281
179
|
signal?: AbortSignal;
|
|
282
180
|
}, ms: number, starter: Starter<T>): Promise<T>;
|
|
283
181
|
//#endregion
|
|
284
|
-
export type
|
|
182
|
+
export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type PollOptions, type RaceStarter, type RetryOptions, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
|
package/dist/notrace/effects.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,i as n,o as r,s as i,t as a}from"./context-
|
|
1
|
+
import{a as e,c as t,i as n,o as r,s as i,t as a}from"./context-CctVmHLC.js";import{n as o,r as s,t as c}from"./delay-B_W1tnkS.js";const l=(e,t)=>t?.signal?new Promise((n,r)=>{let a=i(t,r);e.then(n,r).finally(a)}):e,u=async(e,t,o,s)=>{t?.signal?.throwIfAborted();let{ctx:c,unlink:u}=n(t??{}),d=a(c,e);r(c,e,`start`),i(c,()=>d(`cancel`));try{let e=await l(o(c),t);return d(`done`),s?.(!1),e}catch(e){throw d(`error`,e),s?.(!0),e}finally{u()}},d=async(t,r)=>{let{ctx:i,unlink:a}=n(t);try{return await e(i,`run`,()=>r(i))}finally{a()}},f=e=>e,p=(e,t)=>n=>e(t,f(n)),m=e=>Array.isArray(e)?Array(e.length):{},h=(t,r)=>{let i=Object.entries(r).map(([r,i])=>{let a=n(t),o={signal:a.ctx.signal,abort:a.ctx.abort},s=()=>i(o);return{key:r,task:new Promise(t=>t(e(a.ctx,`run`,s))).finally(a.unlink),cancel:a.ctx.abort}});return{tasks:i.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of i)e.cancel()}}},g=(e,t,n,r,i)=>{let a=()=>{};return u(e,t,async e=>{let t=h(e,n);return a=t.cancelAll,r(t.tasks)},e=>{(e||i===`end`)&&a()})};function _(e,t){return g(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const v=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function y(e,t){return g(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>v(e))),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const b=e=>e>0?e:0,x=(e={})=>{let t=b(e.base??100),n=e.factor??2,r=b(e.max??1/0),i=e.jitter??!1;return e=>{let a=b(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},S=(e,n)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((r,a)=>{let o=[],s=`pending`,c=e=>{try{e()}catch(e){t(`cancel cleanup failed`,e)}},l=i(e,e=>{s=`cancelled`;for(let e of o.reverse())c(e);a(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{n({resolve:u(r),reject:u(a),onCancel:d})}catch(e){u(a)(e)}}),C=e=>t=>{let n=t.addContext,r=Object.entries(e);return t.addContext=e=>{n?.(e);for(let[t,n]of r)Object.assign(e,{[t]:(...t)=>n(e,...t)})},t},w=(e,t,n,r)=>{if(e.signal.aborted)return Promise.resolve();let a=r.leading??!1,c=r.waitForFn??!1;return u(`poll`,e,e=>new Promise((r,l)=>{let u=0,f=null,p=()=>{f!==null&&(o(f),f=null)},m=e=>{try{f=s(h,typeof n==`function`?n(e):n)}catch(e){p(),l(e)}},h=()=>{f=null,c||m(u+1),g()},g=()=>{let n=u++;d(e,e=>t(e,n)).then(()=>{c&&!e.signal.aborted&&m(u)},e=>{p(),l(e)})};i(e,p),a?(g(),c||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function T(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{};return(t,n)=>w(n,p(r,t),e,i)}let i=t;return w(e,(e,t)=>i(t),n,r)}function E(e,t){let n=m(t);return Object.keys(t).length===0?Promise.resolve(n):g(`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`)}const D=(e,t,n)=>typeof e==`function`?e(t,n):e,O=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),k=(e,t,n)=>u(`retry`,e,async e=>{let{times:r,delay:i,shouldRetry:a}=O(n);for(let n=1;;n++)try{return await d(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<r)||!a(t,n))throw t;let o=D(i,n,t);o>0&&await c(e,o)}});function A(e,t,n={}){if(typeof e==`function`){let n=e;return(e,r)=>k(r,p(n,e),t??{})}let r=t;return k(e,(e,t)=>r(t),n)}function j(e,t,n={}){return u(`take`,e,r=>new Promise((a,o)=>{let{predicate:s}=n,c=[],l=()=>{for(let e of c)e()},u=e=>{l(),o(e)};c.push(e.on(t,e=>{(!s||s(e))&&(l(),a(e))})),c.push(i(r,u)),c.push(i({signal:n.signal},u))}))}const M=(t,r,i)=>u(`timeout`,t,async t=>{let a=n(t),c=s(()=>a.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await l(Promise.resolve(e(a.ctx,`run`,()=>i(a.ctx))),a.ctx)}finally{o(c),a.unlink()}});function N(e,t,n){if(typeof e==`number`){let n=t;return(t,r)=>M(r,e,p(n,t))}let r=t,i=n;return M(e,r,e=>i({signal:e.signal,abort:e.abort}))}export{_ as all,y as allSettled,x as backoff,S as cancellable,c as delay,C as effectsPlugin,i as onAbort,T as poll,E as race,A as retry,j as take,N as timeout};
|
package/dist/notrace/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
|
|
1
|
+
import { A as On, B as PayloadOf, C as EventKey, D as Handler, E as EventsOf, F as Tracer, G as TraceLogger, H as Task, I as anyEventType, K as UnsubscribeCallback, L as EffectName, M as WithType, N as commandCall, O as HandlerRef, P as createBus, R as EventMap, S as Emittable, T as EventPayload, U as Trace, V as Phase, W as TraceEvent, _ as Commands, b as ContextOption, d as Action, f as AnyEvent, g as CommandCall, h as Command, i as WithPayload, j as WithContext, k as Off, m as BusOptions, p as Bus, v as Context, w as EventLike, x as Emit, y as ContextOf, z as Keys } from "./action-creator-DKG_sIia.js";
|
|
2
|
+
import { n as NoClash, r as contextPlugin, t as ContextTask } from "./context-plugin-Dt1IgVo8.js";
|
|
3
|
+
export { type Action, type AnyEvent, type Bus, type BusOptions, type Command, type CommandCall, type Commands, type Context, type ContextOf, type ContextOption, type ContextTask, type EffectName, type Emit, type Emittable, type EventKey, type EventLike, type EventMap, type EventPayload, type EventsOf, type Handler, type HandlerRef, type Keys, type NoClash, type Off, type On, type PayloadOf, type Phase, type Task, type Trace, type TraceEvent, type TraceLogger, type Tracer, type UnsubscribeCallback, type WithContext, type WithPayload, type WithType, anyEventType, commandCall, contextPlugin, createBus };
|
package/dist/notrace/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{i as e,n as t,t as n}from"./bus-Bdk0YyFQ.js";const r=e=>typeof e==`function`,i=e=>({type:Reflect.get(e,`type`),payload:Reflect.get(e,`payload`)}),a=e=>t=>{let n=t.addContext;return t.addContext=t=>{n?.(t);let a=r(e)?e(i(t)):e;for(let[e,n]of Object.entries(a))e in t||Reflect.set(t,e,n)},t};export{e as anyEventType,n as commandCall,a as contextPlugin,t as createBus};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { R as EventMap, c as BoundForm, j as WithContext, p as Bus, u as Effects, v as Context, z as Keys } from "./action-creator-DKG_sIia.js";
|
|
2
|
+
import { n as NoClash } from "./context-plugin-Dt1IgVo8.js";
|
|
3
|
+
//#region src/utils/delay.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolves after `ms`, or rejects early if `ctx.signal` aborts. `ms` can be a
|
|
6
|
+
* function that returns the number of ms, called once when the delay starts:
|
|
7
|
+
* handy for a random pause (jitter).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* await delay({}, 500);
|
|
12
|
+
*
|
|
13
|
+
* // 200 to 400 ms
|
|
14
|
+
* await delay({}, () => 200 + Math.random() * 200);
|
|
15
|
+
*
|
|
16
|
+
* // inside a task: stops waiting when the task is aborted
|
|
17
|
+
* bus.on("retry", async (_, ctx) => {
|
|
18
|
+
* await delay(ctx, 1000);
|
|
19
|
+
* await load();
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const delay: (ctx: {
|
|
24
|
+
signal?: AbortSignal | undefined;
|
|
25
|
+
}, ms: number | (() => number)) => Promise<void>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/effects/run.d.ts
|
|
28
|
+
/** Context passed into `race` / `all` effect starters. */
|
|
29
|
+
type EffectContext = {
|
|
30
|
+
signal: AbortSignal;
|
|
31
|
+
abort: (reason?: unknown) => void;
|
|
32
|
+
};
|
|
33
|
+
type Starter<T> = (ctx: EffectContext) => T | PromiseLike<T>;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/effects/all.d.ts
|
|
36
|
+
/**
|
|
37
|
+
* Runs all starters; waits for every result. On failure or parent abort, cancels the rest.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* bus.on("load", async (id, ctx) => {
|
|
42
|
+
* const { user, posts } = await all(ctx, {
|
|
43
|
+
* user: ({ signal }) => fetchUser(id, { signal }),
|
|
44
|
+
* posts: ({ signal }) => fetchPosts(id, { signal }),
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // arrays work too: const [user, posts] = await all(ctx, [getUser, getPosts]);
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare function all<T extends Record<string, Starter<unknown>>>(ctx: {
|
|
52
|
+
signal?: AbortSignal;
|
|
53
|
+
}, effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
54
|
+
declare function all<const T extends readonly Starter<unknown>[]>(ctx: {
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
}, effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/effects/allSettled.d.ts
|
|
59
|
+
/**
|
|
60
|
+
* Runs all starters and waits for every one to settle, whether it succeeds or
|
|
61
|
+
* fails: nothing is cancelled when a starter fails. The result has, for each
|
|
62
|
+
* starter, `{ status: "fulfilled", value }` or `{ status: "rejected", reason }`.
|
|
63
|
+
* Only an abort of `ctx` rejects it, with the abort reason.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* bus.on("load", async (id, ctx) => {
|
|
68
|
+
* const { user, posts } = await allSettled(ctx, {
|
|
69
|
+
* user: ({ signal }) => fetchUser(id, { signal }),
|
|
70
|
+
* posts: ({ signal }) => fetchPosts(id, { signal }),
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* if (user.status === "fulfilled") render(user.value);
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function allSettled<T extends Record<string, Starter<unknown>>>(ctx: {
|
|
78
|
+
signal?: AbortSignal;
|
|
79
|
+
}, effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
80
|
+
declare function allSettled<const T extends readonly Starter<unknown>[]>(ctx: {
|
|
81
|
+
signal?: AbortSignal;
|
|
82
|
+
}, effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/effects/race.d.ts
|
|
85
|
+
type RaceStarter<T> = Starter<T>;
|
|
86
|
+
/**
|
|
87
|
+
* Runs all starters; first to settle wins, losers are cancelled via `ctx.abort`.
|
|
88
|
+
* The result holds only the winner's value, under its key or index.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* bus.on("load", async (id, ctx) => {
|
|
93
|
+
* const result = await race(ctx, {
|
|
94
|
+
* data: ({ signal }) => fetchData(id, { signal }),
|
|
95
|
+
* timeout: ({ signal }) => delay({ signal }, 5000),
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* if ("timeout" in result) throw new Error("timed out");
|
|
99
|
+
* render(result.data);
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function race<T extends Record<string, RaceStarter<unknown>>>(ctx: {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}, effects: T): Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
106
|
+
declare function race<const T extends readonly RaceStarter<unknown>[]>(ctx: {
|
|
107
|
+
signal?: AbortSignal;
|
|
108
|
+
}, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/effects/take.d.ts
|
|
111
|
+
type TakeOptions<P> = {
|
|
112
|
+
/**
|
|
113
|
+
* Wait for the first payload this accepts; others are skipped. A type guard
|
|
114
|
+
* (`(payload): payload is T`) narrows the type of the result to `T`.
|
|
115
|
+
*/
|
|
116
|
+
predicate?: (payload: P) => boolean;
|
|
117
|
+
/** Stop waiting when this aborts, e.g. the signal of a `race` starter. */
|
|
118
|
+
signal?: AbortSignal | undefined;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Waits for the next `event` on the bus and resolves with its payload. It sees
|
|
122
|
+
* only events emitted after the call, takes only one, and unsubscribes when it
|
|
123
|
+
* is done. If `ctx` (or `options.signal`) aborts first, it unsubscribes and
|
|
124
|
+
* rejects with the abort reason.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* bus.on("login", async (user, ctx) => {
|
|
129
|
+
* const reason = await take(ctx, "logout");
|
|
130
|
+
* cleanup(user, reason);
|
|
131
|
+
* });
|
|
132
|
+
*
|
|
133
|
+
* // wait for a matching event, but not longer than 5 s
|
|
134
|
+
* const done = await timeout(ctx, 5000, ({ signal }) =>
|
|
135
|
+
* take(ctx, "saved", { signal, predicate: (id) => id === draftId }),
|
|
136
|
+
* );
|
|
137
|
+
*
|
|
138
|
+
* // a type guard narrows the result: `failed` is `{ ok: false }`
|
|
139
|
+
* const failed = await take(ctx, "result", {
|
|
140
|
+
* predicate: (result): result is { ok: false } => !result.ok,
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
declare function take<E extends EventMap, K extends Keys<E>, T extends E[K]>(ctx: Context<E>, event: K, options: TakeOptions<E[K]> & {
|
|
145
|
+
predicate: (payload: E[K]) => payload is T;
|
|
146
|
+
}): Promise<T>;
|
|
147
|
+
declare function take<E extends EventMap, K extends Keys<E>>(ctx: Context<E>, event: K, options?: TakeOptions<E[K]>): Promise<E[K]>;
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/effects/plugin.d.ts
|
|
150
|
+
/** The effects that `effectsPlugin` can put on `ctx`. */
|
|
151
|
+
type Supported = {
|
|
152
|
+
race: typeof race;
|
|
153
|
+
all: typeof all;
|
|
154
|
+
allSettled: typeof allSettled;
|
|
155
|
+
take: typeof take;
|
|
156
|
+
delay: typeof delay;
|
|
157
|
+
};
|
|
158
|
+
type Results = Record<string, Starter<unknown>>;
|
|
159
|
+
type List = readonly Starter<unknown>[];
|
|
160
|
+
/** Each supported effect without its leading `ctx` argument. `take` knows the events of the bus. */
|
|
161
|
+
type Bound<E extends EventMap> = {
|
|
162
|
+
race: {
|
|
163
|
+
<T extends Results>(effects: T): Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
164
|
+
<const T extends List>(effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
165
|
+
};
|
|
166
|
+
all: {
|
|
167
|
+
<T extends Results>(effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
168
|
+
<const T extends List>(effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
169
|
+
};
|
|
170
|
+
allSettled: {
|
|
171
|
+
<T extends Results>(effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
172
|
+
<const T extends List>(effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
173
|
+
};
|
|
174
|
+
take: <K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>) => Promise<E[K]>;
|
|
175
|
+
delay: (ms: number | (() => number)) => Promise<void>;
|
|
176
|
+
};
|
|
177
|
+
/** Any function whose first parameter takes `{ signal }` can go on the context, not only the built-in ones. */
|
|
178
|
+
type Helpers = Effects;
|
|
179
|
+
/**
|
|
180
|
+
* The effects as a handler sees them: the built-in ones keep their hand-written
|
|
181
|
+
* types, any other loses its first parameter, or has the type `Effect<F>` says.
|
|
182
|
+
*/
|
|
183
|
+
type BoundOf<H extends Helpers, E extends EventMap> = { [K in keyof H]: K extends keyof Bound<E> ? H[K] extends Supported[K] ? Bound<E>[K] : BoundForm<H[K]> : BoundForm<H[K]>; };
|
|
184
|
+
/**
|
|
185
|
+
* Puts the effects you pass on the context of every task of the bus, bound to
|
|
186
|
+
* that task, so a handler can write `({ race })` instead of `race(ctx, …)`.
|
|
187
|
+
* The key is the name of the effect: `race`, `all`, `allSettled`, `take`,
|
|
188
|
+
* `delay`. Returns the same bus, typed with the new fields.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* import { createBus } from "nanoeffects";
|
|
193
|
+
* import { all, delay, effectsPlugin, race } from "nanoeffects/effects";
|
|
194
|
+
*
|
|
195
|
+
* const bus = createBus().use(effectsPlugin({ race, delay }));
|
|
196
|
+
*
|
|
197
|
+
* bus.on("load", async (id, { race, delay }) => {
|
|
198
|
+
* const result = await race({
|
|
199
|
+
* data: ({ signal }) => fetchData(id, { signal }),
|
|
200
|
+
* timeout: () => delay(5000),
|
|
201
|
+
* });
|
|
202
|
+
* });
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare const effectsPlugin: <H extends Helpers>(helpers: H) => <E extends EventMap>(bus: Bus<E> & NoClash<BoundOf<H, E>, E>) => Bus<E & WithContext<BoundOf<H, E>>>;
|
|
206
|
+
//#endregion
|
|
207
|
+
export { RaceStarter as a, all as c, delay as d, take as i, EffectContext as l, effectsPlugin as n, race as o, TakeOptions as r, allSettled as s, BoundOf as t, Starter as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as Task, R as EventMap } from "./action-creator-DKG_sIia.js";
|
|
2
2
|
//#region src/policies/keyed.d.ts
|
|
3
3
|
/** Options shared by every policy that can keep its state per key. */
|
|
4
4
|
type KeyOption<P> = {
|
package/dist/notrace/policies.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,o as n,s as r,t as i}from"./context-
|
|
1
|
+
import{a as e,i as t,o as n,s as r,t as i}from"./context-CctVmHLC.js";import{n as a,r as o,t as s}from"./delay-B_W1tnkS.js";import{n as c,t as l}from"./promise-CSLpzwSR.js";const u=()=>{},d=(e,t)=>{let n=/* @__PURE__ */ new Map;return(r,i)=>{let a=e(r),o=n.get(a);if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e)}return o(r,i)}},f=(e,t)=>e?d(e,t):t(u),p=(e,t={})=>f(t.key,t=>m(`latest`,(t,n,r)=>(r(),e(t,n)),t)),m=(e,a,o=u)=>{let s=null;return(l,u)=>{if(s?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=t(u);s=d;let p=i(d,e),m=!1,h=()=>{d.signal.aborted||(m=!0,n(d,e,`start`))};r(d,()=>p(m?`cancel`:`drop`));let g=()=>{f(),s===d&&(s=null,o())},_=e=>{if(!d.signal.aborted)return p(m?`done`:`drop`),e};try{let e=a(l,d,h);return c(e)?Promise.resolve(e).then(_,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(g):(g(),_(e))}catch(e){if(g(),d.signal.aborted)return;throw p(`error`,e),e}}},h=(e,t,n={})=>f(n.key,r=>_(e,t,n,r)),g=(t,r,i,s)=>{let c=s!==u,l=null,d=null;return(u,f)=>{if(f.signal.aborted)return;let p=Date.now(),m=l===null||p-l>=t||p-l<0;return l=p,d!==null&&a(d),d=c?o(s,t):null,i&&m?Promise.resolve(e(f,`debounce`,()=>r(u,f))):(n(f,`debounce`,`drop`),Promise.resolve(void 0))}},_=(t,n,i,a)=>{let o=i.leading??!1,c=i.trailing??!0;if(!c)return g(t,n,o,a);let l=!1,u=0,d=m(`debounce`,([e,i],a,o)=>{let d=u;return r(a,()=>{u===d&&(l=!1)}),s(a,t).then(()=>{if(l=!1,c&&!i)return o(),n(e,a)})},a);return(t,r)=>{if(r.signal.aborted)return;let i=o&&!l;l=!0,u++;let a=d([t,i],r);return i?Promise.resolve(e(r,`debounce`,()=>n(t,r))):a}},v=(t,i={})=>f(i.key,i=>{let a=null;return(o,s)=>{if(s.signal.aborted)return;if(a){n(s,`leading`,`drop`);return}let c={};a=c;let u=()=>{d(),a===c&&(a=null,i())},d=r(s,u);try{return l(e(s,`leading`,()=>t(o,s)),u)}catch(e){throw u(),e}}}),y=(e,t={})=>f(t.key,n=>b(e,t,n)),b=(t,i,a)=>{let o=i.concurrency??1,s=i.limit??1/0,c=[],l=0,d=()=>{for(;l<o;){let e=c.shift();if(!e)return;e.start()}};return(f,p)=>new Promise((m,h)=>{if(p.signal.aborted){m(void 0);return}let g=u,_=()=>{g(),n(p,`queue`,`drop`),m(void 0)},v=()=>{if(g(),p.signal.aborted){_();return}l++;let n=!0,i=()=>{n&&(n=!1,l--,d(),l===0&&c.length===0&&a())},o=r(p,()=>{i(),m(void 0)}),s;try{s=Promise.resolve(e(p,`queue`,()=>t(f,p)))}catch(e){s=Promise.reject(e)}let u=()=>{o(),i()};s.then(e=>{u(),m(p.signal.aborted?void 0:e)},e=>{u(),p.signal.aborted?m(void 0):h(e)})};if(l<o){v();return}if(c.length>=s){if(i.overflow!==`drop-old`||s<=0){_();return}c.shift()?.drop()}let y={start:v,drop:_};c.push(y),g=r(p,()=>{let e=c.indexOf(y);e>=0&&c.splice(e,1),_()})})},x=(e,t,n={})=>f(n.key,r=>S(e,t,n,r)),S=(t,r,i,s)=>{let c=i.leading??!0,l=i.trailing??!0,d=s!==u,f=null,p=0,m=null,h=null,g=null,_=!1,v=e=>f===null||e-f>=t||e-f<0||e-p>=t,y=e=>n(e,`throttle`,`drop`),b=()=>{let e=g;g=null,e&&(y(e.ctx),e.resolve())},x=(e,t)=>(b(),new Promise((n,r)=>{g={payload:e,ctx:t,resolve:n,reject:r}})),S=(t,n,i)=>{b(),p=i,_=!0;try{return e(n,`throttle`,()=>r(t,n))}finally{_=!1}},C=()=>{d&&(h=o(w,t))},w=()=>{if(h=null,!d||m!==null||g)return;let e=Date.now(),n=Math.max(t-(e-(f??-1/0)),t-(e-p));n<=0?s():h=o(w,n)},T=e=>{m=null;let t=g;if(l&&t&&!t.ctx.signal.aborted){g=null;try{t.resolve(S(t.payload,t.ctx,e))}catch(e){t.reject(e)}}else b();w()},E=()=>{let e=Date.now();v(e)?T(e):m=o(E,Math.min(t-(e-(f??e)),t-(e-p)))},D=()=>{h!==null&&(a(h),h=null)},O=(e,t)=>{if(!l)y(t);else return x(e,t)},k=(e,t,n,r)=>{if(!r)y(t);else if(p=n,C(),!c)y(t);else return S(e,t,n)},A=(e,n,r,i)=>i&&m!==null?(a(m),m=o(E,t),S(e,n,r)):m===null&&(m=o(E,t),i&&(p=r,c))?S(e,n,r):O(e,n);return(e,t)=>{if(t.signal.aborted)return;let n=Date.now(),r=!_&&v(n);return f=n,D(),l?A(e,t,n,r):k(e,t,n,r)}};export{h as debounce,p as latest,v as leading,y as queue,x as throttle};
|
package/dist/notrace/redux.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { R as EventMap, p as Bus } from "./action-creator-DKG_sIia.js";
|
|
2
2
|
//#region src/store/redux/middleware.d.ts
|
|
3
3
|
/** What Redux passes through a middleware: an action is a plain object with a `type`. */
|
|
4
4
|
type ReduxAction = {
|
|
@@ -8,6 +8,8 @@ type ReduxAction = {
|
|
|
8
8
|
type NanoeffectsMiddlewareOptions = {
|
|
9
9
|
/** Return `false` for the actions that the bus should not get. Default: all of them. */
|
|
10
10
|
filter?: (action: ReduxAction) => boolean;
|
|
11
|
+
/** Receives an error that `emit` throws, so `dispatch` does not. Default: the error is thrown. */
|
|
12
|
+
onError?: (error: unknown, action: ReduxAction) => void;
|
|
11
13
|
};
|
|
12
14
|
//#endregion
|
|
13
15
|
//#region src/store/redux/effects.d.ts
|
|
@@ -19,48 +21,44 @@ type ReduxStoreApi<State = unknown> = {
|
|
|
19
21
|
}) => unknown;
|
|
20
22
|
getState: () => State;
|
|
21
23
|
};
|
|
22
|
-
type EffectsMiddlewareOptions
|
|
23
|
-
/** More fields for the context of every task, next to `store`. */
|
|
24
|
-
context?: object;
|
|
25
|
-
};
|
|
24
|
+
type EffectsMiddlewareOptions = Pick<NanoeffectsMiddlewareOptions, "filter">;
|
|
26
25
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* `getState` of the store, as soon as
|
|
30
|
-
* in the event map:
|
|
26
|
+
* Makes the Redux middleware that feeds a bus you already have: the actions of
|
|
27
|
+
* the store reach its handlers, and every task gets `ctx.store`, the `dispatch`
|
|
28
|
+
* and `getState` of the store, as soon as Redux has installed the middleware.
|
|
29
|
+
* Type it in the event map of the bus:
|
|
31
30
|
*
|
|
32
31
|
* ```ts
|
|
33
32
|
* type Events = { userRequested: string } & WithContext<{ store: ReduxStoreApi<RootState> }>;
|
|
34
33
|
* ```
|
|
35
34
|
*
|
|
36
|
-
*
|
|
35
|
+
* Use one bus for one store: a second store would replace the first in the
|
|
36
|
+
* contexts. Two things are looked after for you:
|
|
37
37
|
*
|
|
38
38
|
* - **A handler does not loop on its own action.** An action that a handler
|
|
39
39
|
* dispatches through `ctx.store` and that has the type the handler works on
|
|
40
40
|
* does not go back to the bus (a handler of `a` that dispatches `a`). Other
|
|
41
41
|
* handlers of that type do not get it either. Longer cycles, `a` to `b` to
|
|
42
42
|
* `a`, are yours to avoid.
|
|
43
|
-
* - **A failing handler does not break `dispatch`.**
|
|
44
|
-
*
|
|
45
|
-
* still throw to
|
|
43
|
+
* - **A failing handler does not break `dispatch`.** With `onError` on the bus
|
|
44
|
+
* the bus isolates the handlers. Without it the error is written to
|
|
45
|
+
* `console.error`, as in Redux Toolkit listeners. Reducers still throw to
|
|
46
|
+
* the caller.
|
|
46
47
|
*
|
|
47
48
|
* @example
|
|
48
49
|
* ```ts
|
|
49
|
-
* const
|
|
50
|
+
* const bus = createBus<Events>();
|
|
50
51
|
*
|
|
51
52
|
* const store = configureStore({
|
|
52
53
|
* reducer,
|
|
53
|
-
* middleware: (getDefault) => getDefault().concat(
|
|
54
|
+
* middleware: (getDefault) => getDefault().concat(createEffectsMiddleware(bus)),
|
|
54
55
|
* });
|
|
55
56
|
*
|
|
56
|
-
*
|
|
57
|
+
* bus.on(userRequested, latest(async (id, { store, signal }) => {
|
|
57
58
|
* store.dispatch(userLoaded(await fetchUser(id, { signal })));
|
|
58
59
|
* }));
|
|
59
60
|
* ```
|
|
60
61
|
*/
|
|
61
|
-
export declare const createEffectsMiddleware: <E extends EventMap
|
|
62
|
-
bus: Bus<E>;
|
|
63
|
-
middleware: (storeApi: ReduxStoreApi) => (next: (action: unknown) => unknown) => (action: unknown) => unknown;
|
|
64
|
-
};
|
|
62
|
+
export declare const createEffectsMiddleware: <E extends EventMap>(bus: Bus<E>, options?: EffectsMiddlewareOptions) => (storeApi: ReduxStoreApi) => (next: (action: unknown) => unknown) => (action: unknown) => unknown;
|
|
65
63
|
//#endregion
|
|
66
64
|
export type { EffectsMiddlewareOptions, ReduxStoreApi };
|
package/dist/notrace/redux.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=e=>typeof e==`object`&&!!e&&`type`in e,t=(t,n={})=>{let r=t.emit,i=e=>{try{r(e)}catch(t){if(!n.onError)throw t;n.onError(t,e)}};return()=>t=>r=>{let a=t(r);return e(r)&&(n.filter?.(r)??!0)&&i(r),a}},n=(e,n={})=>{let r,i=/* @__PURE__ */ new WeakMap,a=e.addContext;e.addContext=e=>{a?.(e);let t=r;if(!t)return;let{type:n}=e;Object.assign(e,{store:{getState:t.getState,dispatch:e=>{typeof e==`object`&&e&&i.set(e,n);let r=e;return t.dispatch(r)}}})};let o=t(e,{filter:e=>i.get(e)!==e.type&&(n.filter?.(e)??!0),onError:(e,{type:t})=>{globalThis.console?.error(`[nanoeffects] handler of "${t}" failed`,e)}});return e=>(r=e,o())};export{n as createEffectsMiddleware};
|
package/dist/observable.d.ts
CHANGED