nanoeffects 0.19.1 → 0.21.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/dist/{action-creator-HFA_LZOH.d.ts → action-creator-Bpa8BUS9.d.ts} +18 -7
- package/dist/actions.d.ts +3 -3
- package/dist/actions.js +1 -1
- package/dist/{context-types-BNcs43eY.d.ts → context-types-BKIH5a8s.d.ts} +1 -1
- package/dist/context.d.ts +2 -2
- package/dist/dev.d.ts +2 -2
- package/dist/dev.js +1 -1
- package/dist/effects.d.ts +4 -8
- package/dist/index.d.ts +2 -2
- package/dist/match.d.ts +1 -1
- package/dist/{module-DTf73Wdq.d.ts → module-B0KVDNjY.d.ts} +14 -9
- package/dist/mount-each-D54UqAhZ.js +1 -0
- package/dist/notrace/{action-creator-CbFf398i.d.ts → action-creator-D2CotugT.d.ts} +16 -7
- package/dist/notrace/actions.d.ts +14 -9
- package/dist/notrace/actions.js +1 -1
- package/dist/notrace/effects.d.ts +4 -8
- package/dist/notrace/index.d.ts +2 -2
- package/dist/notrace/{plugin-C5vIjxhR.d.ts → plugin-C6KA4dX-.d.ts} +1 -1
- package/dist/notrace/policies.d.ts +51 -6
- package/dist/notrace/policies.js +1 -1
- package/dist/notrace/redux.d.ts +1 -1
- package/dist/observable.d.ts +1 -1
- package/dist/oop.d.ts +1 -1
- package/dist/{plugin-Sy8z9IId.d.ts → plugin-D9UTzGRG.d.ts} +2 -2
- package/dist/policies.d.ts +52 -7
- package/dist/policies.js +1 -1
- package/dist/react.d.ts +9 -8
- package/dist/redux.d.ts +1 -1
- package/dist/scope.d.ts +4 -4
- package/dist/signal.d.ts +1 -1
- package/dist/state-of-C19H6BoV.d.ts +10 -0
- package/dist/trace.d.ts +1 -1
- package/dist/{types-DaZT158m.d.ts → types-CbdJKC2z.d.ts} +2 -2
- package/dist/vue.d.ts +72 -0
- package/dist/vue.js +1 -0
- package/dist/{with-policy-C_mX7S54.d.ts → with-policy-BeH8wCkX.d.ts} +1 -1
- package/docs/README.md +2 -0
- package/docs/actions.md +31 -1
- package/docs/chat-example.md +246 -0
- package/docs/migrating-from-rxjs.md +58 -1
- package/docs/package.md +1 -0
- package/docs/plugins.md +3 -3
- package/docs/policies.md +27 -0
- package/docs/query-libraries.md +2 -0
- package/docs/react.md +5 -3
- package/docs/starter.md +25 -1
- package/docs/typescript.md +14 -0
- package/docs/vue.md +96 -0
- package/llms-full.txt +517 -10
- package/llms.txt +4 -2
- package/package.json +25 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as NoClash } from "./context-types-
|
|
1
|
+
import { B as Keys, N as WithContext, b as Context, d as Effects, h as Bus, l as BoundForm, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
+
import { n as NoClash } from "./context-types-BKIH5a8s.js";
|
|
3
3
|
//#region src/utils/delay.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Resolves after `ms`, or rejects early if `ctx.signal` aborts. `ms` can be a
|
package/dist/policies.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as withPolicy, t as PolicyFunction } from "./with-policy-
|
|
1
|
+
import { W as Task, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
+
import { n as withPolicy, t as PolicyFunction } from "./with-policy-BeH8wCkX.js";
|
|
3
3
|
//#region src/policies/keyed.d.ts
|
|
4
4
|
/** Options shared by every policy that can keep its state per key. */
|
|
5
5
|
type KeyOption<P> = {
|
|
@@ -10,6 +10,14 @@ type KeyOption<P> = {
|
|
|
10
10
|
*/
|
|
11
11
|
key?: (payload: P) => unknown;
|
|
12
12
|
};
|
|
13
|
+
/** Options of a policy called without a task: `key` is left out. */
|
|
14
|
+
type Unkeyed<O> = Omit<O, "key"> & {
|
|
15
|
+
key?: undefined;
|
|
16
|
+
};
|
|
17
|
+
/** Options of a policy called without a task, with a `key` that tells the payload type. */
|
|
18
|
+
type Keyed<O, P> = O & {
|
|
19
|
+
key: (payload: P) => unknown;
|
|
20
|
+
};
|
|
13
21
|
//#endregion
|
|
14
22
|
//#region src/policies/debounce.d.ts
|
|
15
23
|
type DebounceResult<R> = Promise<R | undefined> | Promise<Awaited<R> | undefined> | undefined;
|
|
@@ -19,6 +27,10 @@ type DebounceOptions<P = never> = KeyOption<P> & {
|
|
|
19
27
|
/** Run the last call of a burst after `ms` of quiet. Default `true`. */
|
|
20
28
|
trailing?: boolean;
|
|
21
29
|
};
|
|
30
|
+
/** What `debounce(ms)` returns: it turns a task into a `debounce` task. */
|
|
31
|
+
type DebounceWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, DebounceResult<R>>;
|
|
32
|
+
/** What `debounce(ms, { key })` returns: the payload type comes from `key`. */
|
|
33
|
+
type KeyedDebounceWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, DebounceResult<R>>;
|
|
22
34
|
/**
|
|
23
35
|
* Waits for `ms` of quiet, then runs; a new call restarts the wait and drops
|
|
24
36
|
* the previous. With `leading` the first call of a burst runs at once, and the
|
|
@@ -39,14 +51,24 @@ type DebounceOptions<P = never> = KeyOption<P> & {
|
|
|
39
51
|
* bus.emit("input", "re"); // only the last call runs, 300 ms after it
|
|
40
52
|
* ```
|
|
41
53
|
*/
|
|
42
|
-
export declare
|
|
54
|
+
export declare function debounce<P, E extends EventMap, R>(ms: number, fn: Task<P, E, R>, options?: DebounceOptions<P>): Task<P, E, DebounceResult<R>>;
|
|
55
|
+
export declare function debounce(ms: number, options?: Unkeyed<DebounceOptions>): DebounceWrapper;
|
|
56
|
+
export declare function debounce<P>(ms: number, options: Keyed<DebounceOptions<P>, P>): KeyedDebounceWrapper<P>;
|
|
43
57
|
//#endregion
|
|
44
58
|
//#region src/policies/latest.d.ts
|
|
45
59
|
type LatestOptions<P = never> = KeyOption<P>;
|
|
60
|
+
type LatestResult<R> = R | Promise<Awaited<R> | undefined> | undefined;
|
|
61
|
+
/** What `latest()` returns: it turns a task into a `latest` task. */
|
|
62
|
+
type LatestWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, LatestResult<R>>;
|
|
63
|
+
/** What `latest({ key })` returns: the payload type comes from `key`. */
|
|
64
|
+
type KeyedLatestWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, LatestResult<R>>;
|
|
46
65
|
/**
|
|
47
66
|
* Aborts the previous run when a new call arrives; stale results are dropped.
|
|
48
67
|
* With `options.key` each key has its own latest run.
|
|
49
68
|
*
|
|
69
|
+
* Called without the task, `latest()` returns a function that takes the task,
|
|
70
|
+
* so `usePolicy(callback, latest())` has no `(task) => ...` to get wrong.
|
|
71
|
+
*
|
|
50
72
|
* @example
|
|
51
73
|
* ```ts
|
|
52
74
|
* bus.on(
|
|
@@ -62,12 +84,21 @@ type LatestOptions<P = never> = KeyOption<P>;
|
|
|
62
84
|
*
|
|
63
85
|
* // one latest run per user instead of one for all
|
|
64
86
|
* bus.on("load", latest(loadUser, { key: (user) => user.id }));
|
|
87
|
+
*
|
|
88
|
+
* // without the task: for a hook that builds the task itself
|
|
89
|
+
* const search = usePolicy(runSearch, latest());
|
|
65
90
|
* ```
|
|
66
91
|
*/
|
|
67
|
-
export declare
|
|
92
|
+
export declare function latest<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: LatestOptions<P>): Task<P, E, LatestResult<R>>;
|
|
93
|
+
export declare function latest(options?: Unkeyed<LatestOptions>): LatestWrapper;
|
|
94
|
+
export declare function latest<P>(options: Keyed<LatestOptions<P>, P>): KeyedLatestWrapper<P>;
|
|
68
95
|
//#endregion
|
|
69
96
|
//#region src/policies/leading.d.ts
|
|
70
97
|
type LeadingOptions<P = never> = KeyOption<P>;
|
|
98
|
+
/** What `leading()` returns: it turns a task into a `leading` task. */
|
|
99
|
+
type LeadingWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
|
|
100
|
+
/** What `leading({ key })` returns: the payload type comes from `key`. */
|
|
101
|
+
type KeyedLeadingWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
|
|
71
102
|
/**
|
|
72
103
|
* Drops new calls while the task is still running. The lock is released when
|
|
73
104
|
* the run settles or when its task is aborted, whichever comes first, so a
|
|
@@ -87,7 +118,9 @@ type LeadingOptions<P = never> = KeyOption<P>;
|
|
|
87
118
|
* bus.emit("save", draft); // dropped while the first save is in flight
|
|
88
119
|
* ```
|
|
89
120
|
*/
|
|
90
|
-
export declare
|
|
121
|
+
export declare function leading<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: LeadingOptions<P>): Task<P, E, R | Promise<Awaited<R>> | undefined>;
|
|
122
|
+
export declare function leading(options?: Unkeyed<LeadingOptions>): LeadingWrapper;
|
|
123
|
+
export declare function leading<P>(options: Keyed<LeadingOptions<P>, P>): KeyedLeadingWrapper<P>;
|
|
91
124
|
//#endregion
|
|
92
125
|
//#region src/policies/queue.d.ts
|
|
93
126
|
type QueueOptions<P = never> = KeyOption<P> & {
|
|
@@ -102,6 +135,10 @@ type QueueOptions<P = never> = KeyOption<P> & {
|
|
|
102
135
|
*/
|
|
103
136
|
overflow?: "drop-new" | "drop-old";
|
|
104
137
|
};
|
|
138
|
+
/** What `queue()` returns: it turns a task into a `queue` task. */
|
|
139
|
+
type QueueWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
|
|
140
|
+
/** What `queue({ key })` returns: the payload type comes from `key`. */
|
|
141
|
+
type KeyedQueueWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
|
|
105
142
|
/**
|
|
106
143
|
* Runs calls one after another, in the order they arrived: a call starts when
|
|
107
144
|
* fewer than `concurrency` calls are running. Every call returns a promise with
|
|
@@ -132,7 +169,9 @@ type QueueOptions<P = never> = KeyOption<P> & {
|
|
|
132
169
|
* bus.emit("save", b); // waits for a, then runs
|
|
133
170
|
* ```
|
|
134
171
|
*/
|
|
135
|
-
export declare
|
|
172
|
+
export declare function queue<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: QueueOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
|
|
173
|
+
export declare function queue(options?: Unkeyed<QueueOptions>): QueueWrapper;
|
|
174
|
+
export declare function queue<P>(options: Keyed<QueueOptions<P>, P>): KeyedQueueWrapper<P>;
|
|
136
175
|
//#endregion
|
|
137
176
|
//#region src/policies/throttle.d.ts
|
|
138
177
|
type ThrottleOptions<P = never> = KeyOption<P> & {
|
|
@@ -141,6 +180,10 @@ type ThrottleOptions<P = never> = KeyOption<P> & {
|
|
|
141
180
|
/** Run the latest call made while waiting, at the end of the window. Default `true`. */
|
|
142
181
|
trailing?: boolean;
|
|
143
182
|
};
|
|
183
|
+
/** What `throttle(ms)` returns: it turns a task into a `throttle` task. */
|
|
184
|
+
type ThrottleWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<R | undefined> | undefined>;
|
|
185
|
+
/** What `throttle(ms, { key })` returns: the payload type comes from `key`. */
|
|
186
|
+
type KeyedThrottleWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<R | undefined> | undefined>;
|
|
144
187
|
/**
|
|
145
188
|
* At most one run per `ms`, with the semantics of lodash `throttle` (and
|
|
146
189
|
* patronum): a call made when the throttle is idle, that is, at least `ms`
|
|
@@ -167,6 +210,8 @@ type ThrottleOptions<P = never> = KeyOption<P> & {
|
|
|
167
210
|
* bus.emit("scroll", 30); // runs once the 200 ms window closes
|
|
168
211
|
* ```
|
|
169
212
|
*/
|
|
170
|
-
export declare
|
|
213
|
+
export declare function throttle<P, E extends EventMap, R>(ms: number, fn: Task<P, E, R>, options?: ThrottleOptions<P>): Task<P, E, R | Promise<R | undefined> | undefined>;
|
|
214
|
+
export declare function throttle(ms: number, options?: Unkeyed<ThrottleOptions>): ThrottleWrapper;
|
|
215
|
+
export declare function throttle<P>(ms: number, options: Keyed<ThrottleOptions<P>, P>): KeyedThrottleWrapper<P>;
|
|
171
216
|
//#endregion
|
|
172
217
|
export { type DebounceOptions, type LatestOptions, type LeadingOptions, type PolicyFunction, type QueueOptions, type ThrottleOptions, withPolicy };
|
package/dist/policies.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,o as t,s as n,t as r,u as i}from"./context-CJGW6OWj.js";import{n as a,r as o,t as s}from"./delay-BnBdGPh7.js";import{n as c,t as l}from"./promise-CSLpzwSR.js";import{n as u,t as d}from"./lifecycle-key-8iX8RUVD.js";import{t as f}from"./with-policy-CW50Edgk.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,n,r)=>(m(e),t(e,n,r)),g=(e,t)=>{n(e,t,`drop`),p(e)?.drop()},_=(e,t)=>{p(e)?.done(t)},v=(e,t,n)=>{let r=p(e);t?r?.cancel(n):r?.drop()},y=e=>(Reflect.set(e,u,!0),e),b=()=>{},x=(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)}},
|
|
1
|
+
import{i as e,o as t,s as n,t as r,u as i}from"./context-CJGW6OWj.js";import{n as a,r as o,t as s}from"./delay-BnBdGPh7.js";import{n as c,t as l}from"./promise-CSLpzwSR.js";import{n as u,t as d}from"./lifecycle-key-8iX8RUVD.js";import{t as f}from"./with-policy-CW50Edgk.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,n,r)=>(m(e),t(e,n,r)),g=(e,t)=>{n(e,t,`drop`),p(e)?.drop()},_=(e,t)=>{p(e)?.done(t)},v=(e,t,n)=>{let r=p(e);t?r?.cancel(n):r?.drop()},y=e=>(Reflect.set(e,u,!0),e),b=()=>{},x=(e,t,n)=>typeof e==`function`?n(e,t??{}):t=>n(t,e??{}),S=(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)}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t){return x(e,t,T)}const T=(e,t)=>C(t.key,t=>E(`latest`,(t,n,r)=>(r(),e(t,n)),t)),E=(t,a,o=b)=>{let s=null;return(l,u)=>{if(s?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=e(u);s=d;let p=r(d,t),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),n(d,t,`start`))};i(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),s===d&&(s=null,o())},y=e=>{if(!d.signal.aborted)return p(h?`done`:`drop`),e};try{let e=a(l,d,g);return c(e)?Promise.resolve(e).then(y,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),d.signal.aborted)return;throw p(`error`,e),e}}};function D(e,t,n){return x(t,n,(t,n)=>O(e,t,n))}const O=(e,t,n)=>C(n.key,r=>A(e,t,n,r)),k=(e,t,n,r)=>{let i=r!==b,s=null,c=null;return(l,u)=>{if(u.signal.aborted)return;let d=Date.now(),f=s===null||d-s>=e||d-s<0;return s=d,c!==null&&a(c),c=i?o(r,e):null,n&&f?Promise.resolve(h(u,`debounce`,()=>t(l,u))):(g(u,`debounce`),Promise.resolve(void 0))}},A=(e,t,n,r)=>{let a=n.leading??!1,o=n.trailing??!0;if(!o)return k(e,t,a,r);let c=!1,l=0,u=E(`debounce`,([n,r],a,u)=>{let d=l;return i(a,()=>{l===d&&(c=!1)}),s(a,e).then(()=>{if(c=!1,o&&!r)return u(),t(n,a)})},r);return(e,n)=>{if(n.signal.aborted)return;let r=a&&!c;c=!0,l++;let i=u([e,r],n);return r?Promise.resolve(h(n,`debounce`,()=>t(e,n))):i}};function j(e,t){return x(e,t,M)}const M=(e,t)=>C(t.key,t=>{let n=null;return(r,a)=>{if(a.signal.aborted)return;if(n){g(a,`leading`);return}let o={};n=o;let s=()=>{c(),n===o&&(n=null,t())},c=i(a,s);try{return l(h(a,`leading`,()=>e(r,a)),s)}catch(e){throw s(),e}}});function N(e,t){return x(e,t,P)}const P=(e,t)=>C(t.key,n=>F(e,t,n)),F=(e,t,n)=>{let r=t.concurrency??1,a=t.limit??1/0,o=[],s=0,c=()=>{for(;s<r;){let e=o.shift();if(!e)return;e.start()}};return(l,u)=>new Promise((d,f)=>{if(u.signal.aborted){d(void 0);return}let p=b,m=()=>{p(),g(u,`queue`),d(void 0)},v=()=>{if(p(),u.signal.aborted){m();return}s++;let t=!0,r=()=>{t&&(t=!1,s--,c(),s===0&&o.length===0&&n())},a=i(u,()=>{r(),d(void 0)}),g;try{g=Promise.resolve(h(u,`queue`,()=>e(l,u)))}catch(e){g=Promise.reject(e)}let v=()=>{a(),r()};g.then(e=>{_(u,{value:e}),v(),d(u.signal.aborted?void 0:e)},e=>{_(u,{error:e}),v(),u.signal.aborted?d(void 0):f(e)})};if(s<r){v();return}if(o.length>=a){if(t.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=i(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})};function I(e,t,n){return x(t,n,(t,n)=>L(e,t,n))}const L=(e,t,n)=>C(n.key,r=>R(e,t,n,r)),R=(e,t,n,r)=>{let i=n.leading??!0,s=n.trailing??!0,c=r!==b,l=null,u=0,d=null,f=null,p=null,m=!1,_=t=>l===null||t-l>=e||t-l<0||t-u>=e,v=e=>g(e,`throttle`),y=()=>{let e=p;p=null,e&&(v(e.ctx),e.resolve())},x=(e,t)=>(y(),new Promise((n,r)=>{p={payload:e,ctx:t,resolve:n,reject:r}})),S=(e,n,r)=>{y(),u=r,m=!0;try{return h(n,`throttle`,()=>t(e,n))}finally{m=!1}},C=()=>{c&&(f=o(w,e))},w=()=>{if(f=null,!c||d!==null||p)return;let t=Date.now(),n=Math.max(e-(t-(l??-1/0)),e-(t-u));n<=0?r():f=o(w,n)},T=e=>{d=null;let t=p;if(s&&t&&!t.ctx.signal.aborted){p=null;try{t.resolve(S(t.payload,t.ctx,e))}catch(e){t.reject(e)}}else y();w()},E=()=>{let t=Date.now();_(t)?T(t):d=o(E,Math.min(e-(t-(l??t)),e-(t-u)))},D=()=>{f!==null&&(a(f),f=null)},O=(e,t)=>{if(!s)v(t);else return x(e,t)},k=(e,t,n,r)=>{if(!r)v(t);else if(u=n,C(),!i)v(t);else return S(e,t,n)},A=(t,n,r,s)=>s&&d!==null?(a(d),d=o(E,e),S(t,n,r)):d===null&&(d=o(E,e),s&&(u=r,i))?S(t,n,r):O(t,n);return(e,t)=>{if(t.signal.aborted)return;let n=Date.now(),r=!m&&_(n);return l=n,D(),s?A(e,t,n,r):k(e,t,n,r)}};export{D as debounce,w as latest,j as leading,N as queue,I as throttle,f as withPolicy};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { T as EventKey, W as Task, h as Bus, r as FreeActionCreator, t as ActionCreator, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
2
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
3
|
-
import { t as PolicyFunction } from "./with-policy-
|
|
3
|
+
import { t as PolicyFunction } from "./with-policy-BeH8wCkX.js";
|
|
4
|
+
import { t as StateOf } from "./state-of-C19H6BoV.js";
|
|
4
5
|
//#region src/react/plugin.d.ts
|
|
5
6
|
/** Tells whether two values are the same: `Object.is` unless the caller gives another. */
|
|
6
7
|
type Equals<V> = (previous: V, next: V) => boolean;
|
|
@@ -46,8 +47,6 @@ type ReactApi<E extends EventMap> = {
|
|
|
46
47
|
};
|
|
47
48
|
/** What `useEventState` returns: the pair of `useState`, with the payload of the event as state. */
|
|
48
49
|
type EventState<P> = [P, (next: P | ((previous: P) => P)) => void];
|
|
49
|
-
type Widen<S> = [S] extends [never[]] ? unknown[] : S;
|
|
50
|
-
type StateOf<P, S> = unknown extends P ? Widen<S> : P;
|
|
51
50
|
/**
|
|
52
51
|
* Adds `bus.useEmitter(event, value)`: a hook that tells the bus when a value of
|
|
53
52
|
* a component changes, without the traps of `useEffect(() => emit(value), [value])`
|
|
@@ -86,9 +85,11 @@ export declare const reactPlugin: () => <E extends EventMap>(bus: Bus<E>) => Bus
|
|
|
86
85
|
* render. This hook keeps the policy across renders and calls the `callback` of
|
|
87
86
|
* the latest render, so an inline callback sees fresh props and state.
|
|
88
87
|
*
|
|
89
|
-
* `make`
|
|
90
|
-
*
|
|
91
|
-
*
|
|
88
|
+
* `make` builds the policy around the callback. Pass a policy called without
|
|
89
|
+
* its task (`debounce(300)`, `latest()`), or a function `(task) => policy` for
|
|
90
|
+
* a combined policy such as `(task) => throttle(100, latest(task))`; `task`
|
|
91
|
+
* runs the callback. `make` runs once, and again when an item of `deps`
|
|
92
|
+
* changes: list there what it reads, such as the wait time. The pending calls of the old function are
|
|
92
93
|
* cancelled then, and when the component unmounts. Needs `react` 18 or newer.
|
|
93
94
|
*
|
|
94
95
|
* @example
|
|
@@ -100,7 +101,7 @@ export declare const reactPlugin: () => <E extends EventMap>(bus: Bus<E>) => Bus
|
|
|
100
101
|
* const [results, setResults] = useState([]);
|
|
101
102
|
* const onChange = usePolicy(
|
|
102
103
|
* async (query: string) => setResults(await search(query)), // latest render's callback
|
|
103
|
-
*
|
|
104
|
+
* debounce(wait), // the policy, made once per wait
|
|
104
105
|
* [wait],
|
|
105
106
|
* );
|
|
106
107
|
* return <input onChange={(event) => onChange(event.target.value)} />;
|
package/dist/redux.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as Bus, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
2
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
3
3
|
//#region src/store/redux/middleware.d.ts
|
|
4
4
|
/** What Redux passes through a middleware: an action is a plain object with a `type`. */
|
package/dist/scope.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as ScopeSlots, r as Scoped } from "./types-
|
|
1
|
+
import { P as WithSignal, a as EmitScope, d as Effects, f as Signaled, h as Bus, o as Scope, u as Effect, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
+
import { n as ScopeSlots, r as Scoped } from "./types-CbdJKC2z.js";
|
|
3
3
|
//#region src/scope/effect.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Marks a function whose first parameter is `{ signal }` as an effect, so that
|
|
@@ -14,7 +14,7 @@ import { n as ScopeSlots, r as Scoped } from "./types-DaZT158m.js";
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```ts
|
|
17
|
-
* const first = effect(<T>(ctx:
|
|
17
|
+
* const first = effect(<T>(ctx: WithSignal, items: T[]) => items[0]);
|
|
18
18
|
*
|
|
19
19
|
* const getUser = createCommand(
|
|
20
20
|
* "user/get",
|
|
@@ -23,7 +23,7 @@ import { n as ScopeSlots, r as Scoped } from "./types-DaZT158m.js";
|
|
|
23
23
|
* );
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare function effect<A extends unknown[], R>(fn: (ctx:
|
|
26
|
+
export declare function effect<A extends unknown[], R>(fn: (ctx: WithSignal, ...args: A) => R): (...args: A) => R;
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/scope/plugin.d.ts
|
|
29
29
|
/**
|
package/dist/signal.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Emit, E as EventLike,
|
|
1
|
+
import { C as Emit, E as EventLike, a as EmitScope, c as WithScope, h as Bus, v as CommandCall, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
2
|
//#region src/signal/plugin.d.ts
|
|
3
3
|
/** What the second argument of `emit` takes besides the fields of a scope. */
|
|
4
4
|
type SignalOption = {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/core/state-of.d.ts
|
|
2
|
+
type Widen<S> = [S] extends [never[]] ? unknown[] : S;
|
|
3
|
+
/**
|
|
4
|
+
* The type of the state that keeps the last payload of an event (`useEventState`,
|
|
5
|
+
* `useEventRef`): the payload type when the event has one, and otherwise the type of the
|
|
6
|
+
* initial value, widened, so a creator without a payload type still gives a typed state.
|
|
7
|
+
*/
|
|
8
|
+
type StateOf<P, S> = unknown extends P ? Widen<S> : P;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { StateOf as t };
|
package/dist/trace.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as
|
|
1
|
+
import { G as Trace, K as TraceEvent, L as Tracer, R as EffectName, U as Phase, h as Bus, q as TraceLogger, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
2
|
//#region src/trace/console.d.ts
|
|
3
3
|
type ConsoleLoggerOptions = {
|
|
4
4
|
/** Defaults to `globalThis.console`. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BoundOf } from "./plugin-
|
|
1
|
+
import { d as Effects, o as Scope, s as WithFields, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
+
import { t as BoundOf } from "./plugin-D9UTzGRG.js";
|
|
3
3
|
//#region src/scope/types.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The slots `scopePlugin` fills for `modulePlugin`. They are not on `Bus`: a bus
|
package/dist/vue.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { T as EventKey, h as Bus, r as FreeActionCreator, t as ActionCreator, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
+
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
3
|
+
import { t as StateOf } from "./state-of-C19H6BoV.js";
|
|
4
|
+
import { ShallowRef, WatchSource, WatchStopHandle } from "vue";
|
|
5
|
+
//#region src/vue/plugin.d.ts
|
|
6
|
+
/** Tells whether two values are the same. */
|
|
7
|
+
type Equals<V> = (previous: V, next: V) => boolean;
|
|
8
|
+
/** The third argument of `watchEmitter`. */
|
|
9
|
+
type WatchEmitterOptions<V> = OriginOptions & {
|
|
10
|
+
/** Tells whether a new value is the same as the previous one, for a new object with the same fields. */
|
|
11
|
+
equals?: Equals<V>;
|
|
12
|
+
};
|
|
13
|
+
/** What `vuePlugin` adds to the bus. */
|
|
14
|
+
type VueApi<E extends EventMap> = {
|
|
15
|
+
/**
|
|
16
|
+
* Watches a ref or a getter and emits `event` with its new value when it changes. It
|
|
17
|
+
* does not emit when it is called, and it stops with the effect scope (a component) that
|
|
18
|
+
* called it. Like Vue's `watch`, it runs before the next render, so several changes in
|
|
19
|
+
* one tick emit once, with the last value. The method does not read `this`, so
|
|
20
|
+
* `export const { watchEmitter } = bus` gives a free function. It returns the function
|
|
21
|
+
* that stops it early.
|
|
22
|
+
*/
|
|
23
|
+
watchEmitter: {
|
|
24
|
+
<K extends EventKey<E>>(source: WatchSource<E[K]>, event: K, options?: WatchEmitterOptions<E[K]>): WatchStopHandle;
|
|
25
|
+
/** A creator without a payload type: the payload comes from the event map. */
|
|
26
|
+
<K extends EventKey<E>>(source: WatchSource<E[K]>, creator: FreeActionCreator<K>, options?: WatchEmitterOptions<E[K]>): WatchStopHandle;
|
|
27
|
+
<P, T extends string>(source: WatchSource<P>, creator: ActionCreator<P, T>, options?: WatchEmitterOptions<P>): WatchStopHandle;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* A ref that starts as `initial`, and that every emit of `event` sets to its payload
|
|
31
|
+
* while the effect scope (a component) that called it lives. A function payload is stored,
|
|
32
|
+
* not called. The bus keeps no values, so an event emitted before the call is not seen. It
|
|
33
|
+
* is state of one component, not a store. The method does not read `this`, so
|
|
34
|
+
* `export const { useEventRef } = bus` gives a free function.
|
|
35
|
+
*/
|
|
36
|
+
useEventRef: {
|
|
37
|
+
<K extends EventKey<E>, S>(event: K, initial: StateOf<E[K], S>): ShallowRef<StateOf<E[K], S>>;
|
|
38
|
+
/** A creator without a payload type: the payload comes from the event map. */
|
|
39
|
+
<K extends EventKey<E>, S>(creator: FreeActionCreator<K>, initial: StateOf<E[K], S>): ShallowRef<StateOf<E[K], S>>;
|
|
40
|
+
<P, T extends string>(creator: ActionCreator<P, T>, initial: P): ShallowRef<P>;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Adds `bus.watchEmitter(source, event)` and `bus.useEventRef(event, initial)`: the two
|
|
45
|
+
* jobs of a Vue component with the bus. `watchEmitter` tells the bus when a value of the
|
|
46
|
+
* component changes, and `useEventRef` keeps the last payload of an event in a ref. Pass
|
|
47
|
+
* `{ equals }` to `watchEmitter` for values that `Object.is` tells apart although they are
|
|
48
|
+
* the same, and `{ traceId }` and `{ traceGroupId }` to name the subscription and the flow
|
|
49
|
+
* in the trace of the bus. Needs `vue` 3.3 or newer. Returns the same bus.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { createBus } from "nanoeffects";
|
|
54
|
+
* import { createAction } from "nanoeffects/actions";
|
|
55
|
+
* import { vuePlugin } from "nanoeffects/vue";
|
|
56
|
+
* import { ref } from "vue";
|
|
57
|
+
*
|
|
58
|
+
* export const bus = createBus().use(vuePlugin());
|
|
59
|
+
* export const { watchEmitter, useEventRef } = bus; // free functions
|
|
60
|
+
*
|
|
61
|
+
* const nameChanged = createAction<string>("name/changed");
|
|
62
|
+
* const nameSaved = createAction<string[]>("name/saved");
|
|
63
|
+
*
|
|
64
|
+
* // inside setup():
|
|
65
|
+
* const name = ref("Adam");
|
|
66
|
+
* watchEmitter(name, nameChanged); // nameChanged("…") on every change of name, not on mount
|
|
67
|
+
* const saved = useEventRef(nameSaved, []); // Ref<string[]>, set by every nameSaved
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const vuePlugin: () => <E extends EventMap>(bus: Bus<E>) => Bus<E> & VueApi<E>;
|
|
71
|
+
//#endregion
|
|
72
|
+
export type { VueApi };
|
package/dist/vue.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./origin-key-BbWN3gmN.js";import{onScopeDispose as t,shallowRef as n,watch as r}from"vue";const i=()=>i=>{function a(t,n,a){return r(t,(t,r)=>{let o=r,s=t;if(a?.equals?.(o,s))return;let c=typeof n==`function`?n(s):{type:n,payload:t},l=Reflect.get(i,e);l?l(c,a??{}):i.emit(c)})}function o(e,r){let a=n(r),o=e;return t(i.on(o,e=>{a.value=e})),a}return Object.assign(i,{watchEmitter:a,useEventRef:o})};export{i as vuePlugin};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as PayloadOf, W as Task, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
2
|
//#region src/policies/with-policy.d.ts
|
|
3
3
|
/** What `withPolicy` returns: the task as a plain function that can be cancelled. */
|
|
4
4
|
type PolicyFunction<P, R> = {
|
package/docs/README.md
CHANGED
|
@@ -18,6 +18,7 @@ Code for every guide step: [`examples/guide.ts`](../examples/guide.ts) (type-che
|
|
|
18
18
|
| Domain logic off the UI | [Actions, commands, modules](actions.md) |
|
|
19
19
|
| Already on Redux / Zustand / MobX / Pinia | [Stores](stores.md) |
|
|
20
20
|
| A React form with async checks | [Build a sign-up form in React](react.md) |
|
|
21
|
+
| A Vue app | [Use nanoeffects in a Vue app](vue.md) |
|
|
21
22
|
| Old responses overwrite new ones | [Cancel stale requests](cancel-stale-requests.md) |
|
|
22
23
|
| Debounced input that must also cancel the old request | [Debounce and abort](debounce-and-abort.md) |
|
|
23
24
|
| A second click sends a second request | [Prevent a double submit](prevent-double-submit.md) |
|
|
@@ -32,6 +33,7 @@ Code for every guide step: [`examples/guide.ts`](../examples/guide.ts) (type-che
|
|
|
32
33
|
- [Effects and cancellation](effects.md) — `retry`, `timeout`, `poll`, `take`, `all`, …
|
|
33
34
|
- [Actions, commands, jobs and modules](actions.md)
|
|
34
35
|
- [Sign-up form in React](react.md) — one form: races, double submit, retry
|
|
36
|
+
- [nanoeffects in a Vue app](vue.md) — `watchEmitter` and `useEventRef`
|
|
35
37
|
- [Context fields](context.md) — store or client on every task
|
|
36
38
|
- [Use the bus from a class](oop.md) — `extendBus`, `@WithBus`, `@On`, and `dispose()` for the subscriptions of an instance
|
|
37
39
|
- [TypeScript in many files](typescript.md) — keep the types of the bus in commands and modules
|
package/docs/actions.md
CHANGED
|
@@ -6,6 +6,8 @@ If you only need `on` / `emit` or policies, stay in the [Guide](guide.md) until
|
|
|
6
6
|
|
|
7
7
|
Recipe without a UI framework: [`examples/modules.ts`](../examples/modules.ts).
|
|
8
8
|
|
|
9
|
+
A chat with four domains, jobs under policies and effects, and a stream tied to a module: [Build a chat with domains, modules and a small server](chat-example.md).
|
|
10
|
+
|
|
9
11
|
A whole project with two domains, a job and React as a thin layer: `npm create nanoeffects@latest my-app -- --template domains-ts` (see [Start a project from a template](starter.md#start-with-domains)).
|
|
10
12
|
|
|
11
13
|
## Return a value from `emit` with a command
|
|
@@ -252,11 +254,39 @@ app.commands.handle(getUser, fakeUser); // in a test
|
|
|
252
254
|
app.dispose(); // unmounts every module
|
|
253
255
|
```
|
|
254
256
|
|
|
257
|
+
`mount` and `unmount` take any number of modules. Use it to start the domains of an app yourself, at the moment you choose and in the order you give, when you do not give them to `modulePlugin`:
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
import { createModule } from "nanoeffects/actions";
|
|
261
|
+
import { app } from "./bus";
|
|
262
|
+
|
|
263
|
+
const userModule = createModule("user", (m) => {
|
|
264
|
+
m.on("user/loaded", (user) => console.log(user));
|
|
265
|
+
});
|
|
266
|
+
const orderModule = createModule("order", (m) => {
|
|
267
|
+
m.on("order/placed", (order) => console.log(order));
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// mount — start both modules, left to right
|
|
271
|
+
const stop = app.mount(userModule, orderModule);
|
|
272
|
+
|
|
273
|
+
// the returned function stops them again, last mounted first (orderModule, then userModule)
|
|
274
|
+
stop();
|
|
275
|
+
|
|
276
|
+
// the same for modules that you already have in an array: spread it
|
|
277
|
+
const modules = [userModule, orderModule];
|
|
278
|
+
app.mount(...modules);
|
|
279
|
+
app.unmount(...modules); // also in reverse order
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
If the `setup` of one module throws, the modules of that call that were already mounted are unmounted again and the error is thrown, so a call mounts all of its modules or none. A module that is mounted already is skipped.
|
|
283
|
+
|
|
255
284
|
- **Unmounting undoes everything** the module did: subscriptions, bound commands, sub-modules, and background tasks (aborted).
|
|
256
285
|
- **A module is known by its name.** Mounting a module whose name is taken replaces the mounted one (see [Hot reload](hmr.md)).
|
|
257
286
|
- **Registry.** If `bus.use(commandsPlugin())` ran first, that registry is used; otherwise the module plugin attaches its own. Either way it is `bus.commands` and `app.commands`.
|
|
258
287
|
- A disposed app cannot mount modules.
|
|
259
|
-
- **The given modules are mounted
|
|
288
|
+
- **The given modules are mounted at the end of the block that made the app**, or at the first use of the app or the bus if that comes first (the first `bus.emit`, or a call of `mount`, `unmount`, `isMounted`, `dispose`, or the read of `commands`). Nothing needs to use the app: `bus.use(modulePlugin([a, b]))` is enough to start them. The plugins that you use after `modulePlugin` in the same block still reach them, because the modules wait until that block has finished. A plugin used after an `await` can come too late: use every plugin before the first `await`. The `bus.on` calls made in between are held and made right after, so the listeners of a module stay ahead of them. See [using plugins in any order](plugins.md#use-them-in-any-order).
|
|
289
|
+
- **To mount by hand instead**, pass no modules: `modulePlugin()` starts nothing, and `app.mount(...)` starts the modules when you want.
|
|
260
290
|
- Module context = task context plus `handle`, `use`, and `spawn`:
|
|
261
291
|
- `handle` — give a command a handler (contract, or override).
|
|
262
292
|
- `use` — bring sub-modules and commands that carry a handler; the returned function undoes that call.
|