nanoeffects 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/{action-creator-BrZF6hXc.d.ts → action-creator-CQlFgQm4.d.ts} +29 -13
  2. package/dist/actions.d.ts +12 -5
  3. package/dist/actions.js +1 -1
  4. package/dist/bus-Cdw5ajKF.js +1 -0
  5. package/dist/context-CJGW6OWj.js +1 -0
  6. package/dist/{context-plugin--HkNN1ha.d.ts → context-plugin-Cphk8jfq.d.ts} +1 -1
  7. package/dist/{delay-CIHnOh_L.js → delay-BnBdGPh7.js} +1 -1
  8. package/dist/dev.d.ts +2 -2
  9. package/dist/effects.d.ts +2 -2
  10. package/dist/effects.js +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +1 -1
  13. package/dist/match.d.ts +1 -1
  14. package/dist/match.js +1 -1
  15. package/dist/{module-DqKegXHt.d.ts → module-woawvR28.d.ts} +3 -3
  16. package/dist/notrace/{action-creator-DHAEgwuh.d.ts → action-creator-Ls3Gy3jk.d.ts} +28 -12
  17. package/dist/notrace/actions.d.ts +12 -5
  18. package/dist/notrace/actions.js +1 -1
  19. package/dist/notrace/bus-G2AdGObY.js +1 -0
  20. package/dist/notrace/{context-plugin-BapQkGwQ.d.ts → context-plugin-BQa-wtbj.d.ts} +1 -1
  21. package/dist/notrace/effects.d.ts +2 -2
  22. package/dist/notrace/index.d.ts +2 -2
  23. package/dist/notrace/index.js +1 -1
  24. package/dist/notrace/origin-key-BbWN3gmN.js +1 -0
  25. package/dist/notrace/origin-key-CxK0SkeG.d.ts +10 -0
  26. package/dist/notrace/{plugin-Cxadz6uU.d.ts → plugin-Cw45_-Bo.d.ts} +2 -2
  27. package/dist/notrace/policies.d.ts +1 -1
  28. package/dist/notrace/redux.d.ts +4 -3
  29. package/dist/notrace/redux.js +1 -1
  30. package/dist/observable.d.ts +1 -1
  31. package/dist/oop.d.ts +13 -7
  32. package/dist/oop.js +1 -1
  33. package/dist/origin-key-BbWN3gmN.js +1 -0
  34. package/dist/origin-key-CxK0SkeG.d.ts +10 -0
  35. package/dist/{plugin-DkXCvsmB.d.ts → plugin-BrTsPg2Y.d.ts} +2 -2
  36. package/dist/policies.d.ts +2 -2
  37. package/dist/policies.js +1 -1
  38. package/dist/react.d.ts +15 -8
  39. package/dist/react.js +1 -1
  40. package/dist/redux.d.ts +4 -3
  41. package/dist/redux.js +1 -1
  42. package/dist/scope.d.ts +2 -2
  43. package/dist/scope.js +1 -1
  44. package/dist/signal.d.ts +1 -1
  45. package/dist/signal.js +1 -1
  46. package/dist/trace.d.ts +65 -14
  47. package/dist/trace.js +1 -1
  48. package/dist/{types-KavbvHix.d.ts → types-bzocBVYc.d.ts} +2 -2
  49. package/dist/{with-policy-DBV9dh2F.js → with-policy-CW50Edgk.js} +1 -1
  50. package/dist/{with-policy-CqUS-VWW.d.ts → with-policy-_zP3OKGy.d.ts} +1 -1
  51. package/docs/oop.md +2 -0
  52. package/docs/package.md +1 -1
  53. package/docs/plugins.md +16 -1
  54. package/docs/scope.md +1 -1
  55. package/docs/stores.md +5 -1
  56. package/docs/tracing.md +184 -8
  57. package/llms-full.txt +210 -13
  58. package/llms.txt +1 -1
  59. package/package.json +3 -3
  60. package/dist/bus-CkTHUAvq.js +0 -1
  61. package/dist/context-COgyNlrC.js +0 -1
  62. package/dist/notrace/bus-BmCTo8BG.js +0 -1
  63. package/dist/onAbort-BgMfspK4.js +0 -1
package/dist/oop.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { B as EventMap, _ as Command, h as Bus, t as ActionCreator } from "./action-creator-BrZF6hXc.js";
1
+ import { B as EventMap, H as ListenerOptions, _ as Command, h as Bus, t as ActionCreator } from "./action-creator-CQlFgQm4.js";
2
2
  //#region src/oop/types.d.ts
3
3
  type Slots = "ctx" | "commands" | "trace" | "addContext" | "applyScope" | "fitScope" | "app" | "use";
4
4
  type AnyFunction = (...args: never[]) => unknown;
@@ -64,8 +64,10 @@ export declare function WithBus(): <C extends Constructor>(Base: C) => Extended<
64
64
  * Makes a method of a class from `extendBus` or `@WithBus` a handler of `event`
65
65
  * for each instance, with `this` bound to the instance, from the construction
66
66
  * until `dispose()`. `wrap` takes the bound handler and returns the one to
67
- * subscribe, such as `latest`. An event emitted inside the constructor of the
68
- * base class does not reach it: the subscription is made right after.
67
+ * subscribe, such as `latest`. `{ traceId }`, as the second or the third
68
+ * argument, names the method in the trace (see `tracePlugin`). An event emitted
69
+ * inside the constructor of the base class does not reach it: the
70
+ * subscription is made right after.
69
71
  *
70
72
  * @example
71
73
  * ```ts
@@ -75,11 +77,15 @@ export declare function WithBus(): <C extends Constructor>(Base: C) => Extended<
75
77
  * }
76
78
  * ```
77
79
  */
78
- export declare function On<P>(event: EventOf<P>, wrap?: Wrap): MethodDecorator<P>;
79
- export declare function On(event: string, wrap?: Wrap): MethodDecorator<never>;
80
+ export declare function On<P>(event: EventOf<P>, wrap?: Wrap, options?: ListenerOptions): MethodDecorator<P>;
81
+ export declare function On<P>(event: EventOf<P>, options: ListenerOptions): MethodDecorator<P>;
82
+ export declare function On(event: string, wrap?: Wrap, options?: ListenerOptions): MethodDecorator<never>;
83
+ export declare function On(event: string, options: ListenerOptions): MethodDecorator<never>;
80
84
  /** Like `On`, but the handler runs at most once for an instance. */
81
- export declare function Once<P>(event: EventOf<P>, wrap?: Wrap): MethodDecorator<P>;
82
- export declare function Once(event: string, wrap?: Wrap): MethodDecorator<never>;
85
+ export declare function Once<P>(event: EventOf<P>, wrap?: Wrap, options?: ListenerOptions): MethodDecorator<P>;
86
+ export declare function Once<P>(event: EventOf<P>, options: ListenerOptions): MethodDecorator<P>;
87
+ export declare function Once(event: string, wrap?: Wrap, options?: ListenerOptions): MethodDecorator<never>;
88
+ export declare function Once(event: string, options: ListenerOptions): MethodDecorator<never>;
83
89
  //#endregion
84
90
  //#region src/oop/extend.d.ts
85
91
  /**
package/dist/oop.js CHANGED
@@ -1 +1 @@
1
- import{r as e}from"./bus-CkTHUAvq.js";const t=/* @__PURE__ */ new WeakMap,n=e=>typeof e==`function`,r=e=>Reflect.ownKeys(e).flatMap(t=>{let r=Reflect.getOwnPropertyDescriptor(e,t)?.value;return n(r)?[{key:t,value:r}]:[]}),i=/* @__PURE__ */ new WeakMap,a=e=>{let n=i.get(e);if(n)return n;let a=/* @__PURE__ */ new Set,o=[];for(let n=e;n&&n!==Object.prototype;n=Reflect.getPrototypeOf(n))for(let{key:e,value:i}of r(n)){if(e===`constructor`||a.has(e))continue;a.add(e);let n=t.get(i);n&&o.push({key:e,method:i,spec:n})}return i.set(e,o),o},o=/* @__PURE__ */ new WeakMap,s=e=>typeof e==`object`&&!!e||typeof e==`function`,c=e=>{let t=o.get(e);if(t)return t;let n=/* @__PURE__ */ new Set;return o.set(e,n),n},l=e=>{if(typeof e==`string`)return e;if(s(e)){let t=Reflect.get(e,`type`);return typeof t==`string`?t:e}return e},u=(e,t,n)=>Reflect.apply(Reflect.get(e,t),e,n),d=(e,t,n,r)=>{let[i,a,...o]=r,s=c(e),l={event:i,handler:a,off:()=>{}},d=u(t,n,[i,n===`once`?(e,t)=>(s.delete(l),typeof a==`function`?Reflect.apply(a,null,[e,t]):void 0):a,...o]),f=typeof d==`function`?()=>d():()=>{};return l.off=f,s.add(l),()=>{s.delete(l),f()}},f=(e,t,n)=>{let[r,i]=n,a=c(e);r===void 0&&a.clear();for(let e of[...a])Object.is(l(e.event),l(r))&&(i===void 0||e.handler===i)&&(a.delete(e),e.off());return u(t,`off`,n)},p=e=>{if(!s(e))return;let t=o.get(e);if(t){o.delete(e);for(let e of t)e.off()}},m=/* @__PURE__ */ new Set([`on`,`once`,`off`,`emit`,`ctx`,`commands`,`trace`,`addContext`,`applyScope`,`fitScope`,`app`,`use`]),h=Reflect.get(Symbol,`dispose`),g=e=>typeof e==`function`,_=(e,t,n,r)=>{n in t||Object.defineProperty(e,n,{configurable:!0,enumerable:!1,...r})},v=/* @__PURE__ */ new WeakMap,y=(e,t)=>{let n=v.get(e);if(n)return n;let r={on:(...n)=>d(e,t,`on`,n),once:(...n)=>d(e,t,`once`,n),off:(...n)=>f(e,t,n)};return v.set(e,r),r},b=(e,t)=>(...n)=>Reflect.apply(Reflect.get(e,t),e,n),x=(e,t)=>{for(let{method:n,spec:r}of a(Reflect.getPrototypeOf(e)??{})){let i=(t,r)=>Reflect.apply(n,e,[t,r]),a=r.wrap?r.wrap(i):i;d(e,t,r.once?`once`:`on`,[r.event,a])}},S=(e,t,n)=>{for(let r of[`on`,`once`,`off`])_(e,t,r,{get(){return y(this,n)[r]}});_(e,t,`emit`,{value:b(n,`emit`)});for(let[r,i]of Object.entries(n))typeof i==`function`&&!m.has(r)&&_(e,t,r,{value:b(n,r)});let r=function(){p(this)};_(e,t,`dispose`,{value:r}),h&&_(e,t,h,{value:r}),_(e,t,`bus`,{get:()=>n})},C=(e,t)=>{let n=function(...r){let i=Reflect.construct(t,r,new.target??n);return x(i,e),i};return Object.setPrototypeOf(n,t),n.prototype=Object.create(t.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),Object.defineProperty(n,"name",{value:t.name,configurable:!0}),`bus`in t||Object.defineProperty(n,"bus",{value:e,configurable:!0}),S(n.prototype,t.prototype,e),n};function w(t,n){if(g(t))return C(e(),t);if(!n)throw TypeError(`extendBus: pass the class to extend`);return C(t,n)}function T(e){return t=>e?w(e,t):w(t)}const E=e=>{let[t,n,r]=e;return typeof n==`string`||typeof n==`symbol`?Reflect.get(Object(r),`value`):t},D=(e,n,r)=>((...i)=>{let a=E(i);typeof a==`function`&&t.set(a,{event:e,wrap:n,once:r})});function O(e,t){return D(e,t,!1)}function k(e,t){return D(e,t,!0)}export{O as On,k as Once,T as WithBus,p as disposeBus,w as extendBus};
1
+ import{r as e}from"./bus-Cdw5ajKF.js";const t=/* @__PURE__ */ new WeakMap,n=e=>typeof e==`function`,r=e=>Reflect.ownKeys(e).flatMap(t=>{let r=Reflect.getOwnPropertyDescriptor(e,t)?.value;return n(r)?[{key:t,value:r}]:[]}),i=/* @__PURE__ */ new WeakMap,a=e=>{let n=i.get(e);if(n)return n;let a=/* @__PURE__ */ new Set,o=[];for(let n=e;n&&n!==Object.prototype;n=Reflect.getPrototypeOf(n))for(let{key:e,value:i}of r(n)){if(e===`constructor`||a.has(e))continue;a.add(e);let n=t.get(i);n&&o.push({key:e,method:i,spec:n})}return i.set(e,o),o},o=/* @__PURE__ */ new WeakMap,s=e=>typeof e==`object`&&!!e||typeof e==`function`,c=e=>{let t=o.get(e);if(t)return t;let n=/* @__PURE__ */ new Set;return o.set(e,n),n},l=e=>{if(typeof e==`string`)return e;if(s(e)){let t=Reflect.get(e,`type`);return typeof t==`string`?t:e}return e},u=(e,t,n)=>Reflect.apply(Reflect.get(e,t),e,n),d=(e,t,n,r)=>{let[i,a,...o]=r,s=c(e),l={event:i,handler:a,off:()=>{}},d=u(t,n,[i,n===`once`?(e,t)=>(s.delete(l),typeof a==`function`?Reflect.apply(a,null,[e,t]):void 0):a,...o]),f=typeof d==`function`?()=>d():()=>{};return l.off=f,s.add(l),()=>{s.delete(l),f()}},f=(e,t,n)=>{let[r,i]=n,a=c(e);r===void 0&&a.clear();for(let e of[...a])Object.is(l(e.event),l(r))&&(i===void 0||e.handler===i)&&(a.delete(e),e.off());return u(t,`off`,n)},p=e=>{if(!s(e))return;let t=o.get(e);if(t){o.delete(e);for(let e of t)e.off()}},m=/* @__PURE__ */ new Set([`on`,`once`,`off`,`emit`,`ctx`,`commands`,`trace`,`addContext`,`applyScope`,`fitScope`,`app`,`use`]),h=Reflect.get(Symbol,`dispose`),g=e=>typeof e==`function`,_=(e,t,n,r)=>{n in t||Object.defineProperty(e,n,{configurable:!0,enumerable:!1,...r})},v=/* @__PURE__ */ new WeakMap,y=(e,t)=>{let n=v.get(e);if(n)return n;let r={on:(...n)=>d(e,t,`on`,n),once:(...n)=>d(e,t,`once`,n),off:(...n)=>f(e,t,n)};return v.set(e,r),r},b=(e,t)=>(...n)=>Reflect.apply(Reflect.get(e,t),e,n),x=(e,t)=>{for(let{method:n,spec:r}of a(Reflect.getPrototypeOf(e)??{})){let i=(t,r)=>Reflect.apply(n,e,[t,r]),a=r.wrap?r.wrap(i):i,o=r.once?`once`:`on`;d(e,t,o,[r.event,a,r.options])}},S=(e,t,n)=>{for(let r of[`on`,`once`,`off`])_(e,t,r,{get(){return y(this,n)[r]}});_(e,t,`emit`,{value:b(n,`emit`)});for(let[r,i]of Object.entries(n))typeof i==`function`&&!m.has(r)&&_(e,t,r,{value:b(n,r)});let r=function(){p(this)};_(e,t,`dispose`,{value:r}),h&&_(e,t,h,{value:r}),_(e,t,`bus`,{get:()=>n})},C=(e,t)=>{let n=function(...r){let i=Reflect.construct(t,r,new.target??n);return x(i,e),i};return Object.setPrototypeOf(n,t),n.prototype=Object.create(t.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),Object.defineProperty(n,"name",{value:t.name,configurable:!0}),`bus`in t||Object.defineProperty(n,"bus",{value:e,configurable:!0}),S(n.prototype,t.prototype,e),n};function w(t,n){if(g(t))return C(e(),t);if(!n)throw TypeError(`extendBus: pass the class to extend`);return C(t,n)}function T(e){return t=>e?w(e,t):w(t)}const E=e=>{let[t,n,r]=e;return typeof n==`string`||typeof n==`symbol`?Reflect.get(Object(r),`value`):t},D=(e,n,r,i)=>((...a)=>{let o=E(a);if(typeof o==`function`){let a=typeof n==`function`?n:void 0,s=typeof n==`function`?r:n??r;t.set(o,{event:e,wrap:a,once:i,options:s})}});function O(e,t,n){return D(e,t,n,!1)}function k(e,t,n){return D(e,t,n,!0)}export{O as On,k as Once,T as WithBus,p as disposeBus,w as extendBus};
@@ -0,0 +1 @@
1
+ const e=Symbol.for(`nanoeffects.origin`);export{e as t};
@@ -0,0 +1,10 @@
1
+ //#region src/core/origin-key.d.ts
2
+ /** What an emitter tells the trace about itself. */
3
+ type OriginOptions = {
4
+ /** Names the subscription that emits; it is the `type` of the root task of the trace. */
5
+ traceId?: string;
6
+ /** Names the flow the emit belongs to; every task below it has it too. */
7
+ traceGroupId?: string;
8
+ };
9
+ //#endregion
10
+ export { OriginOptions as t };
@@ -1,5 +1,5 @@
1
- import { B as EventMap, N as WithContext, V as Keys, b as Context, d as Effects, h as Bus, l as BoundForm } from "./action-creator-BrZF6hXc.js";
2
- import { n as NoClash } from "./context-plugin--HkNN1ha.js";
1
+ import { B as EventMap, N as WithContext, V as Keys, b as Context, d as Effects, h as Bus, l as BoundForm } from "./action-creator-CQlFgQm4.js";
2
+ import { n as NoClash } from "./context-plugin-Cphk8jfq.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
@@ -1,5 +1,5 @@
1
- import { B as EventMap, W as Task } from "./action-creator-BrZF6hXc.js";
2
- import { n as withPolicy, t as PolicyFunction } from "./with-policy-CqUS-VWW.js";
1
+ import { B as EventMap, G as Task } from "./action-creator-CQlFgQm4.js";
2
+ import { n as withPolicy, t as PolicyFunction } from "./with-policy-_zP3OKGy.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> = {
package/dist/policies.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./onAbort-BgMfspK4.js";import{a as t,i as n,o as r,t as i}from"./context-COgyNlrC.js";import{n as a,r as o,t as s}from"./delay-CIHnOh_L.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-DBV9dh2F.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)=>{r(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)}},S=(e,t)=>y(e?x(e,t):t(b)),C=(e,t={})=>S(t.key,t=>w(`latest`,(t,n,r)=>(r(),e(t,n)),t)),w=(t,a,o=b)=>{let s=null;return(l,u)=>{if(s?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=n(u);s=d;let p=i(d,t),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),r(d,t,`start`))};e(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}}},T=(e,t,n={})=>S(n.key,r=>D(e,t,n,r)),E=(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))}},D=(t,n,r,i)=>{let a=r.leading??!1,o=r.trailing??!0;if(!o)return E(t,n,a,i);let c=!1,l=0,u=w(`debounce`,([r,i],a,u)=>{let d=l;return e(a,()=>{l===d&&(c=!1)}),s(a,t).then(()=>{if(c=!1,o&&!i)return u(),n(r,a)})},i);return(e,t)=>{if(t.signal.aborted)return;let r=a&&!c;c=!0,l++;let i=u([e,r],t);return r?Promise.resolve(h(t,`debounce`,()=>n(e,t))):i}},O=(t,n={})=>S(n.key,n=>{let r=null;return(i,a)=>{if(a.signal.aborted)return;if(r){g(a,`leading`);return}let o={};r=o;let s=()=>{c(),r===o&&(r=null,n())},c=e(a,s);try{return l(h(a,`leading`,()=>t(i,a)),s)}catch(e){throw s(),e}}}),k=(e,t={})=>S(t.key,n=>A(e,t,n)),A=(t,n,r)=>{let i=n.concurrency??1,a=n.limit??1/0,o=[],s=0,c=()=>{for(;s<i;){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 n=!0,i=()=>{n&&(n=!1,s--,c(),s===0&&o.length===0&&r())},a=e(u,()=>{i(),d(void 0)}),g;try{g=Promise.resolve(h(u,`queue`,()=>t(l,u)))}catch(e){g=Promise.reject(e)}let v=()=>{a(),i()};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<i){v();return}if(o.length>=a){if(n.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=e(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})},j=(e,t,n={})=>S(n.key,r=>M(e,t,n,r)),M=(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{T as debounce,C as latest,O as leading,k as queue,j as throttle,f as withPolicy};
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)}},S=(e,t)=>y(e?x(e,t):t(b)),C=(e,t={})=>S(t.key,t=>w(`latest`,(t,n,r)=>(r(),e(t,n)),t)),w=(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}}},T=(e,t,n={})=>S(n.key,r=>D(e,t,n,r)),E=(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))}},D=(e,t,n,r)=>{let a=n.leading??!1,o=n.trailing??!0;if(!o)return E(e,t,a,r);let c=!1,l=0,u=w(`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}},O=(e,t={})=>S(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}}}),k=(e,t={})=>S(t.key,n=>A(e,t,n)),A=(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()})})},j=(e,t,n={})=>S(n.key,r=>M(e,t,n,r)),M=(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{T as debounce,C as latest,O as leading,k as queue,j as throttle,f as withPolicy};
package/dist/react.d.ts CHANGED
@@ -1,9 +1,15 @@
1
- import { B as EventMap, T as EventKey, W as Task, h as Bus, r as FreeActionCreator, t as ActionCreator } from "./action-creator-BrZF6hXc.js";
2
- import { t as PolicyFunction } from "./with-policy-CqUS-VWW.js";
1
+ import { B as EventMap, G as Task, T as EventKey, h as Bus, r as FreeActionCreator, t as ActionCreator } from "./action-creator-CQlFgQm4.js";
2
+ import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
3
+ import { t as PolicyFunction } from "./with-policy-_zP3OKGy.js";
3
4
  //#region src/react/plugin.d.ts
4
- /** What `reactPlugin` adds to the bus. */
5
5
  /** Tells whether two values are the same: `Object.is` unless the caller gives another. */
6
6
  type Equals<V> = (previous: V, next: V) => boolean;
7
+ /** The third argument of `useEmitter`. */
8
+ type UseEmitterOptions<V> = OriginOptions & {
9
+ /** Tells whether a new value is the same as the previous one; `Object.is` when absent. */
10
+ equals?: Equals<V>;
11
+ };
12
+ /** What `reactPlugin` adds to the bus. */
7
13
  type ReactApi<E extends EventMap> = {
8
14
  /**
9
15
  * A React hook: after a render commits with a `value` that differs from the
@@ -13,18 +19,19 @@ type ReactApi<E extends EventMap> = {
13
19
  * `export const { useEmitter } = bus` gives a free hook.
14
20
  */
15
21
  useEmitter: {
16
- <K extends EventKey<E>>(event: K, value: E[K], equals?: Equals<E[K]>): void;
22
+ <K extends EventKey<E>>(event: K, value: E[K], options?: UseEmitterOptions<E[K]>): void;
17
23
  /** A creator without a payload type: the payload comes from the event map. */
18
- <K extends EventKey<E>>(creator: FreeActionCreator<K>, value: E[K], equals?: Equals<E[K]>): void;
19
- <P, T extends string>(creator: ActionCreator<P, T>, value: P, equals?: Equals<P>): void;
24
+ <K extends EventKey<E>>(creator: FreeActionCreator<K>, value: E[K], options?: UseEmitterOptions<E[K]>): void;
25
+ <P, T extends string>(creator: ActionCreator<P, T>, value: P, options?: UseEmitterOptions<P>): void;
20
26
  };
21
27
  };
22
28
  /**
23
29
  * Adds `bus.useEmitter(event, value)`: a hook that tells the bus when a value of
24
30
  * a component changes, without the traps of `useEffect(() => emit(value), [value])`
25
31
  * (an emit on mount, two on mount under StrictMode, a new `emit` re-running it).
26
- * Pass `equals` as the third argument for values that `Object.is` tells apart
27
- * although they are the same, such as a new object with the same fields.
32
+ * Pass `{ equals }` as the third argument for values that `Object.is` tells apart
33
+ * although they are the same, such as a new object with the same fields. `{ traceId }`
34
+ * names the subscription and `{ traceGroupId }` the flow in the trace of the bus.
28
35
  * Needs `react` 18 or newer. Returns the same bus.
29
36
  *
30
37
  * @example
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./with-policy-DBV9dh2F.js";import{useEffect as t,useMemo as n,useRef as r}from"react";const i=()=>e=>{function n(n,i,a){let o=r(i),s=r({event:n,equals:a});t(()=>{s.current={event:n,equals:a}}),t(()=>{let{event:t,equals:n}=s.current,r=n??Object.is,a=o.current;if(r(a,i))return;o.current=i;let c=typeof t==`function`?t(i):{type:t,payload:i};e.emit(c)},[i])}return Object.assign(e,{useEmitter:n})},a=(i,a,o=[])=>{let s=r(i);t(()=>{s.current=i});let c=n(()=>e(a((e,t)=>s.current(e,t))),o);return t(()=>()=>c.cancel(),[c]),c};export{i as reactPlugin,a as usePolicy};
1
+ import{t as e}from"./with-policy-CW50Edgk.js";import{t}from"./origin-key-BbWN3gmN.js";import{useEffect as n,useMemo as r,useRef as i}from"react";const a=()=>e=>{function r(r,a,o){let s=i(a),c=i({event:r,options:o});n(()=>{c.current={event:r,options:o}}),n(()=>{let{event:n,options:r}=c.current,i=r?.equals??Object.is,o=s.current;if(i(o,a))return;s.current=a;let l=typeof n==`function`?n(a):{type:n,payload:a},u=Reflect.get(e,t);u?u(l,r??{}):e.emit(l)},[a])}return Object.assign(e,{useEmitter:r})},o=(t,a,o=[])=>{let s=i(t);n(()=>{s.current=t});let c=r(()=>e(a((e,t)=>s.current(e,t))),o);return n(()=>()=>c.cancel(),[c]),c};export{a as reactPlugin,o as usePolicy};
package/dist/redux.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { B as EventMap, h as Bus } from "./action-creator-BrZF6hXc.js";
1
+ import { B as EventMap, h as Bus } from "./action-creator-CQlFgQm4.js";
2
+ import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
2
3
  //#region src/store/redux/middleware.d.ts
3
4
  /** What Redux passes through a middleware: an action is a plain object with a `type`. */
4
5
  type ReduxAction = {
5
6
  type: string;
6
7
  payload?: unknown;
7
8
  };
8
- type NanoeffectsMiddlewareOptions = {
9
+ type NanoeffectsMiddlewareOptions = OriginOptions & {
9
10
  /** Return `false` for the actions that the bus should not get. Default: all of them. */
10
11
  filter?: (action: ReduxAction) => boolean;
11
12
  /** Receives an error that `emit` throws, so `dispatch` does not. Default: the error is thrown. */
@@ -21,7 +22,7 @@ type ReduxStoreApi<State = unknown> = {
21
22
  }) => unknown;
22
23
  getState: () => State;
23
24
  };
24
- type EffectsMiddlewareOptions = Pick<NanoeffectsMiddlewareOptions, "filter">;
25
+ type EffectsMiddlewareOptions = Pick<NanoeffectsMiddlewareOptions, "filter" | "traceId" | "traceGroupId">;
25
26
  /**
26
27
  * Makes the Redux middleware that feeds a bus you already have: the actions of
27
28
  * the store reach its handlers, and every task gets `ctx.store`, the `dispatch`
package/dist/redux.js CHANGED
@@ -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};
1
+ import{t as e}from"./origin-key-BbWN3gmN.js";const t=e=>typeof e==`object`&&!!e&&`type`in e,n=(n,r={})=>{let i=n.emit,a=t=>{try{let a=Reflect.get(n,e);a?a(t,r):i(t)}catch(e){if(!r.onError)throw e;r.onError(e,t)}};return()=>e=>n=>{let i=e(n);return t(n)&&(r.filter?.(n)??!0)&&a(n),i}},r=(e,t={})=>{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=n(e,{...t.traceId===void 0?{}:{traceId:t.traceId},...t.traceGroupId===void 0?{}:{traceGroupId:t.traceGroupId},filter:e=>i.get(e)!==e.type&&(t.filter?.(e)??!0),onError:(e,{type:t})=>{globalThis.console?.error(`[nanoeffects] handler of "${t}" failed`,e)}});return e=>(r=e,o())};export{r as createEffectsMiddleware};
package/dist/scope.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as EventMap, a as EmitScope, d as Effects, f as Signaled, h as Bus, o as Scope, u as Effect } from "./action-creator-BrZF6hXc.js";
2
- import { n as ScopeSlots, r as Scoped } from "./types-KavbvHix.js";
1
+ import { B as EventMap, a as EmitScope, d as Effects, f as Signaled, h as Bus, o as Scope, u as Effect } from "./action-creator-CQlFgQm4.js";
2
+ import { n as ScopeSlots, r as Scoped } from "./types-bzocBVYc.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
package/dist/scope.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./scope-key-B7l7mUS5.js";const t=/* @__PURE__ */ new WeakSet;function n(e){return t.add(e),e}const r=/* @__PURE__ */ new Set([`signal`,`abort`,`emit`,`on`,`off`,`run`,`type`,`payload`]),i=[],a=Symbol(`nanoeffects.scope.call`),o=Symbol(`nanoeffects.scope.module`),s=Symbol(`nanoeffects.scope.watched`),c=e=>e,l=e=>typeof e==`function`&&t.has(e),u=(e,t)=>(...n)=>Reflect.apply(t,null,[e,...n]),d=(e,t)=>{if(!t)return;for(let n in t)if(n!==`$effects`&&!r.has(n)){let r=t[n];e[n]=l(r)?u(e,r):r}let n=t.$effects;if(n)for(let t in n){let i=n[t];i&&!r.has(t)&&(e[t]=u(e,i))}},f=(e,t,n)=>{d(e,n);for(let n of t)d(e,n)},p=e=>typeof e==`object`&&!!e,m=e=>p(e),h=e=>(p(e)||typeof e==`function`)&&`type`in e,g=e=>h(e)?e.type:e,_=(e,t)=>p(e)&&h(e)?e.payload:t[0],v=t=>p(t)||typeof t==`function`?Reflect.get(t,e):void 0,y=(e,t)=>{let n=v(e),r=p(e)&&m(t[0])?t[0]:void 0;if(n&&r)return[n,r];let i=n??r;return i?[i]:void 0},b=()=>e=>{let t,n,r,l=e=>{let n=e.run;if(n[s])return;let r=(r,...i)=>{let s=t;t=void 0;try{return n((t,n)=>{let i=e[a];return i&&u(n,i,e[o]),r(t,n)},...i)}finally{t=s}};r[s]=!0,e.run=r},u=(e,t,n)=>{e[a]=t,n&&(e[o]=n),f(e,t,n),l(e)},d=e.addContext;e.addContext=e=>{d?.(e);let i=c(e);t&&i.type===n&&Object.is(i.payload,r)&&u(i,t,void 0)},e.applyScope=(e,t)=>{let n=c(e);u(n,n[a]??i,t)},e.fitScope=(t,n)=>typeof n==`function`?(r,i)=>(e.applyScope?.(i,t),Reflect.apply(n,null,[r,i])):n;let p=e.emit;return e.emit=(e,...i)=>{let a=y(e,i);if(!(a||t))return p(e,...i);let o=t,s=n,c=r;t=a,n=g(e),r=_(e,i);try{return p(e,...i)}finally{t=o,n=s,r=c}},e};export{n as effect,b as scopePlugin};
1
+ import{t as e}from"./scope-key-B7l7mUS5.js";const t=/* @__PURE__ */ new WeakSet;function n(e){return t.add(e),e}const r=/* @__PURE__ */ new Set([`signal`,`abort`,`emit`,`on`,`off`,`run`,`type`,`payload`,`traceGroupId`]),i=[],a=Symbol(`nanoeffects.scope.call`),o=Symbol(`nanoeffects.scope.module`),s=Symbol(`nanoeffects.scope.watched`),c=e=>e,l=e=>typeof e==`function`&&t.has(e),u=(e,t)=>(...n)=>Reflect.apply(t,null,[e,...n]),d=(e,t)=>{if(!t)return;for(let n in t)if(n!==`$effects`&&!r.has(n)){let r=t[n];e[n]=l(r)?u(e,r):r}let n=t.$effects;if(n)for(let t in n){let i=n[t];i&&!r.has(t)&&(e[t]=u(e,i))}},f=(e,t,n)=>{d(e,n);for(let n of t)d(e,n)},p=e=>typeof e==`object`&&!!e,m=e=>p(e),h=e=>(p(e)||typeof e==`function`)&&`type`in e,g=e=>h(e)?e.type:e,_=(e,t)=>p(e)&&h(e)?e.payload:t[0],v=t=>p(t)||typeof t==`function`?Reflect.get(t,e):void 0,y=(e,t)=>{let n=v(e),r=p(e)&&m(t[0])?t[0]:void 0;if(n&&r)return[n,r];let i=n??r;return i?[i]:void 0},b=()=>e=>{let t,n,r,l=e=>{let n=e.run;if(n[s])return;let r=(r,...i)=>{let s=t;t=void 0;try{return n((t,n)=>{let i=e[a];return i&&u(n,i,e[o]),r(t,n)},...i)}finally{t=s}};r[s]=!0,e.run=r},u=(e,t,n)=>{e[a]=t,n&&(e[o]=n),f(e,t,n),l(e)},d=e.addContext;e.addContext=e=>{d?.(e);let i=c(e);t&&i.type===n&&Object.is(i.payload,r)&&u(i,t,void 0)},e.applyScope=(e,t)=>{let n=c(e);u(n,n[a]??i,t)},e.fitScope=(t,n)=>typeof n==`function`?(r,i)=>(e.applyScope?.(i,t),Reflect.apply(n,null,[r,i])):n;let p=e.emit;return e.emit=(e,...i)=>{let a=y(e,i);if(!(a||t))return p(e,...i);let o=t,s=n,c=r;t=a,n=g(e),r=_(e,i);try{return p(e,...i)}finally{t=o,n=s,r=c}},e};export{n as effect,b as scopePlugin};
package/dist/signal.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { B as EventMap, C as Emit, E as EventLike, a as EmitScope, c as WithScope, h as Bus, v as CommandCall } from "./action-creator-BrZF6hXc.js";
1
+ import { B as EventMap, C as Emit, E as EventLike, a as EmitScope, c as WithScope, h as Bus, v as CommandCall } from "./action-creator-CQlFgQm4.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 = {
package/dist/signal.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./onAbort-BgMfspK4.js";import{n as t}from"./promise-CSLpzwSR.js";import{n}from"./bus-CkTHUAvq.js";const r=e=>typeof e==`object`&&!!e,i=(e,t)=>{let n=t[0];if(!r(n)||!r(e)&&typeof e!=`function`)return;let i=Reflect.get(n,`signal`);return i instanceof AbortSignal?i:void 0},a=(r,i,a,o)=>{let s=e({signal:r},e=>{for(let{target:t}of i)t.abort(e)});return t(o)?o.then(s,s):n(a)&&s(),o},o=()=>e=>{let t,n,r=e.addContext;e.addContext=e=>{r?.(e),t?.push({target:e}),n?.aborted&&e.abort(n.reason)};let o=e.emit;return e.emit=(e,...r)=>{let s=i(e,r);if(!(s||t))return o(e,...r);let c=t,l=n,u=[];t=s?u:void 0,n=s;let d;try{d=o(e,...r)}finally{t=c,n=l}return s?a(s,u,e,d):d},e};export{o as signalPlugin};
1
+ import{u as e}from"./context-CJGW6OWj.js";import{n as t}from"./promise-CSLpzwSR.js";import{n}from"./bus-Cdw5ajKF.js";const r=e=>typeof e==`object`&&!!e,i=(e,t)=>{let n=t[0];if(!r(n)||!r(e)&&typeof e!=`function`)return;let i=Reflect.get(n,`signal`);return i instanceof AbortSignal?i:void 0},a=(r,i,a,o)=>{let s=e({signal:r},e=>{for(let{target:t}of i)t.abort(e)});return t(o)?o.then(s,s):n(a)&&s(),o},o=()=>e=>{let t,n,r=e.addContext;e.addContext=e=>{r?.(e),t?.push({target:e}),n?.aborted&&e.abort(n.reason)};let o=e.emit;return e.emit=(e,...r)=>{let s=i(e,r);if(!(s||t))return o(e,...r);let c=t,l=n,u=[];t=s?u:void 0,n=s;let d;try{d=o(e,...r)}finally{t=c,n=l}return s?a(s,u,e,d):d},e};export{o as signalPlugin};
package/dist/trace.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Trace, K as TraceEvent, L as Tracer, q as TraceLogger } from "./action-creator-BrZF6hXc.js";
1
+ import { B as EventMap, J as TraceLogger, K as Trace, L as Tracer, W as Phase, h as Bus, q as TraceEvent, z as EffectName } from "./action-creator-CQlFgQm4.js";
2
2
  //#region src/trace/console.d.ts
3
3
  type ConsoleLoggerOptions = {
4
4
  /** Defaults to `globalThis.console`. */
@@ -48,6 +48,36 @@ type PerformanceLoggerOptions = {
48
48
  */
49
49
  export declare const performanceLogger: (options?: PerformanceLoggerOptions) => TraceLogger;
50
50
  //#endregion
51
+ //#region src/trace/plugin.d.ts
52
+ /**
53
+ * Names and groups what the trace shows, on a bus that has a tracer:
54
+ *
55
+ * - `traceGroupId` in the scope of a command, a job or an action goes to every
56
+ * task that the call starts;
57
+ * - `useEmitter` and `bus.emitter` emit from a root task named by their
58
+ * `traceId`, so a chain says which subscription began it;
59
+ * - `bus.on(event, handler, { traceId })` and `once` name a listener: each call of
60
+ * it is a task with that `traceId`, and what it emits is below it;
61
+ * - each emit is reported as one event with `effect: "emit"`, also when nothing
62
+ * listens to it, so a log can show what was emitted and not only what ran.
63
+ *
64
+ * The plugin does nothing on a bus without a tracer, and without it all of these
65
+ * options are ignored, so a project can leave it out, or use it only in
66
+ * development, and nothing else changes. Returns the same bus.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import { createBus } from "nanoeffects";
71
+ * import { consoleLogger, createTracer, tracePlugin } from "nanoeffects/trace";
72
+ *
73
+ * const bus = createBus({ trace: createTracer(consoleLogger()) }).use(tracePlugin());
74
+ *
75
+ * // a listener that you can find in the log
76
+ * bus.on("name/changed", saveName, { traceId: "saveNotifier" });
77
+ * ```
78
+ */
79
+ export declare const tracePlugin: () => <E extends EventMap>(bus: Bus<E>) => Bus<E>;
80
+ //#endregion
51
81
  //#region src/trace/recorder.d.ts
52
82
  type Recorder<E = Record<string, unknown>> = TraceLogger<E> & {
53
83
  /** Every event received so far, in order. */
@@ -80,21 +110,38 @@ type ReduxExtension = {
80
110
  maxAge?: number;
81
111
  }) => ReduxConnection;
82
112
  };
113
+ /** A stage of a handler task: which policy (or `run`) and which phase of it. */
114
+ type PolicyStage = {
115
+ effect: EffectName;
116
+ phase: Phase;
117
+ };
118
+ /**
119
+ * Which stages of the handler tasks to show: `true` for all, a list of phases
120
+ * (`["cancel", "drop"]`), or a function of the stage.
121
+ */
122
+ type PolicyStages = boolean | readonly Phase[] | ((stage: PolicyStage) => boolean);
83
123
  type ReduxDevtoolsOptions = {
84
124
  /** Instance name in the Redux DevTools picker. */
85
125
  name?: string;
86
126
  /** Defaults to `globalThis.__REDUX_DEVTOOLS_EXTENSION__`. */
87
127
  extension?: ReduxExtension;
88
128
  /**
89
- * Also send the start of every task as an action. Default `false`: a task
90
- * is one action, sent when it ends, and the tasks that are running are in
91
- * the state.
129
+ * Also show the stages of the handler tasks, the tasks that a policy
130
+ * (`latest`, `debounce`, ...) or `ctx.run` starts: `true` for every phase, a
131
+ * list of phases, or a function of `{ effect, phase }`. Default: none, the
132
+ * log has the emits only. The error of a handler task is always shown.
133
+ */
134
+ policies?: PolicyStages;
135
+ /**
136
+ * Also send the start of every shown task as an action. Default `false`: a
137
+ * task is one action, sent when it ends, and the tasks that are running are
138
+ * in the state.
92
139
  */
93
140
  starts?: boolean;
94
141
  /**
95
- * How deep in the tree of tasks to show: `0` is the handler tasks only, `1`
96
- * also the effects they start (`retry`, `timeout`, ...), and so on. The
97
- * attempts and the starters under them are hidden at the default, `1`.
142
+ * How deep below the handler tasks to show: `0` is none, `1` also the
143
+ * effects they start (`retry`, `timeout`, ...), and so on. Default `0`.
144
+ * The handler tasks themselves are chosen by `policies`.
98
145
  */
99
146
  depth?: number;
100
147
  /** The number of actions that DevTools keeps; its own default is 50. */
@@ -105,21 +152,25 @@ type ReduxDevtoolsState = {
105
152
  running: Record<number, {
106
153
  type: string;
107
154
  effect: string;
155
+ traceGroupId?: string;
108
156
  }>;
109
157
  };
110
158
  /**
111
- * Trace logger that sends the tasks to Redux DevTools as actions
112
- * `type/effect/phase`, with the running tasks as state. By default it is quiet:
113
- * a task is one action, when it ends, and only the handler tasks and the
114
- * effects they start are shown (see `starts` and `depth` to show more).
115
- * Read-only: there is no time travel. Does nothing when the extension is not
116
- * installed.
159
+ * Trace logger that sends the trace to Redux DevTools. By default it is quiet:
160
+ * one action for each emit (`type` is the event name, it needs `tracePlugin`),
161
+ * and the failures of handlers. `policies` adds the stages of the handler tasks
162
+ * as actions `event/policy/phase`, and `depth` the effects below them; the
163
+ * running tasks are in the state. Read-only: there is no time travel. Does
164
+ * nothing when the extension is not installed.
117
165
  *
118
166
  * @example
119
167
  * ```ts
120
168
  * const bus = createBus<Events>({
121
169
  * trace: createTracer(reduxDevtools({ name: "app" })),
122
- * });
170
+ * }).use(tracePlugin());
171
+ *
172
+ * // and the cancelled and dropped calls of the policies
173
+ * reduxDevtools({ name: "app", policies: ["cancel", "drop"] });
123
174
  * ```
124
175
  */
125
176
  export declare const reduxDevtools: (options?: ReduxDevtoolsOptions) => TraceLogger;
package/dist/trace.js CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./onAbort-BgMfspK4.js";import{n}from"./promise-CSLpzwSR.js";const r=(e={})=>{let t=e.console??globalThis.console,n=e.prefix??`[nanoeffects]`,r=/* @__PURE__ */ new Map;return({id:e,parent:i,type:a,effect:o,phase:s,payload:c,error:l})=>{r.has(e)||r.set(e,typeof i==`number`?(r.get(i)??0)+1:0);let u=` `.repeat(r.get(e)??0);s!==`start`&&r.delete(e);let d=`${n} ${u}${a} · ${o} ${s}`;s===`error`?t?.error(d,l):t?.debug(d,c)}},i=(e={})=>{let t=e.performance??globalThis.performance,n=/* @__PURE__ */ new Map;return({id:e,parent:r,type:i,effect:a,phase:o,error:s})=>{if(!t)return;if(o===`start`){n.set(e,t.now());return}let c=`${i} · ${a} (${o})`,l={id:e,parent:r,phase:o,...o===`error`&&{error:String(s)}},u=n.get(e);n.delete(e),typeof u==`number`?t.measure(c,{start:u,end:t.now(),detail:l}):t.mark(c,{detail:l})}},a=()=>{let e=[];return Object.assign(t=>{e.push(t)},{events:e,clear:()=>{e.length=0}})},o=()=>{},s=(e={})=>{let t=e.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;if(!t)return o;let{starts:n=!1,depth:r=1,maxAge:i}=e,a=t.connect({name:e.name??`nanoeffects`,...i!==void 0&&{maxAge:i}}),s=/* @__PURE__ */ new Map,c=/* @__PURE__ */ new Map,l=()=>({running:Object.fromEntries(s)});return a.init(l()),({error:e,...t})=>{let i=(t.parent===void 0?-1:c.get(t.parent)??-1)+1,o=i<=r;t.phase===`start`?(c.set(t.id,i),o&&s.set(t.id,{type:t.type,effect:t.effect})):(c.delete(t.id),s.delete(t.id)),o&&(t.phase!==`start`||n)&&a.send({...t,type:`${t.type}/${t.effect}/${t.phase}`,event:t.type,...t.phase===`error`&&{error:e instanceof Error?e.message:e}},l())}},c=t=>{let n=typeof t==`function`?[t]:[...t??[]];return n.length===0?null:t=>{for(let r of n)try{r(t)}catch(t){e(`trace logger failed`,t)}}},l=()=>{},u=(e,r={})=>{let i=c(e),{filter:a,sample:o=1}=r,s=0,u=e=>typeof o==`function`?o({type:e.type,payload:e.payload}):Math.random()<o,d={task:(e,t)=>({id:++s,parent:t?.id,type:e.type,payload:e.payload,sampled:t?.sampled??u(e)}),report:(e,t,n,r)=>{if(!e.sampled)return;let o={id:e.id,type:e.type,effect:t,phase:n,payload:e.payload};typeof e.parent==`number`&&(o.parent=e.parent),n===`error`&&(o.error=r),(!a||a(o))&&i?.(o)},settler:(e,t)=>{if(!e.sampled)return l;let n=!1;return(r,i)=>{n||(n=!0,d.report(e,t,r,i))}},run:(e,r,i,a)=>{if(!e.sampled)return a();let o=d.settler(e,r);d.report(e,r,`start`),t({signal:i},()=>o(`cancel`));let s;try{s=a()}catch(e){throw o(`error`,e),e}return n(s)?Promise.resolve(s).then(e=>(o(`done`),e),e=>{throw o(`error`,e),e}):(o(`done`),s)}};return d};export{r as consoleLogger,a as createTraceRecorder,u as createTracer,i as performanceLogger,s as reduxDevtools};
1
+ import{a as e,c as t,d as n,n as r,o as i,r as a,s as o,u as s}from"./context-CJGW6OWj.js";import{n as c}from"./promise-CSLpzwSR.js";import{t as l}from"./origin-key-BbWN3gmN.js";import{t as u}from"./scope-key-B7l7mUS5.js";const d=(e={})=>{let t=e.console??globalThis.console,n=e.prefix??`[nanoeffects]`,r=/* @__PURE__ */ new Map;return({id:e,parentId:i,type:a,effect:o,phase:s,payload:c,error:l,traceGroupId:u})=>{r.has(e)||r.set(e,typeof i==`number`?(r.get(i)??0)+1:0);let d=` `.repeat(r.get(e)??0);s!==`start`&&r.delete(e);let f=u===void 0?``:` [${u}]`,p=`${n}${f} ${d}${a} · ${o} ${s}`;s===`error`?t?.error(p,l):t?.debug(p,c)}},f=(e={})=>{let t=e.performance??globalThis.performance,n=/* @__PURE__ */ new Map;return({id:e,parentId:r,rootId:i,traceGroupId:a,type:o,effect:s,phase:c,error:l})=>{if(!t)return;if(c===`start`){n.set(e,t.now());return}let u=`${o} · ${s} (${c})`,d={id:e,parentId:r,...i!==void 0&&{rootId:i},...a!==void 0&&{traceGroupId:a},phase:c,...c===`error`&&{error:String(l)}},f=n.get(e);n.delete(e),typeof f==`number`?t.measure(u,{start:f,end:t.now(),detail:d}):t.mark(u,{detail:d})}};let p;const m=()=>p,h=(e,t)=>{let n=p;p=e;try{return t()}finally{p=n}},g=(e,t,n={})=>{let{trace:i}=e;if(!i){e.emit(t);return}let{traceId:a,traceGroupId:s}=n,{ctx:c,unlink:l}=r({event:{type:a??t.type,payload:t,...s===void 0?{}:{traceGroupId:s}},bus:{emit:e.emit,on:e.on,off:e.off,ctx:e.ctx,addContext:e.addContext},tracer:i});o(c,`run`,`start`);try{c.emit(t),o(c,`run`,`done`)}catch(e){throw o(c,`run`,`error`,e),e}finally{l()}},_=e=>typeof e==`string`?e:Reflect.get(Object(e),`type`),v=(e,t)=>typeof e==`object`?Reflect.get(Object(e),`payload`):t[0],y=()=>n=>{if(!(t&&n.trace))return n;let{trace:r}=n,o=(e,t)=>{let n=r.task({type:_(e),payload:v(e,t)},a());r.report(n,`emit`,`done`)},s=n.emit;n.emit=(e,...t)=>h(e,()=>(o(e,t),s(e,...t))),Reflect.set(n,l,(e,t)=>{g(n,e,t)});let c=/* @__PURE__ */ new WeakMap,u=(e,t,n)=>{let r=c.get(t)??/* @__PURE__ */ new Map,i=_(e);r.set(i,[...r.get(i)??[],n]),c.set(t,r)},d=(e,t)=>(c.get(t)?.get(_(e)))?.pop(),f=(t,n)=>(r,a)=>(e(a,n),i(a,`run`,()=>t(r,a))),p=(e,t)=>(n,r,i)=>{let a=Reflect.get(Object(i),`traceId`);if(typeof a!=`string`)return e(n,r);let o=t?(e,t)=>(d(n,r),f(r,a)(e,t)):f(r,a);u(n,r,o);let s=e(n,o);return()=>{s()}},m=n.off,y=(e,t)=>{t===void 0?m(e):m(e,d(e,t)??t)},b=n.on,x=n.once;return n.on=p(b,!1),n.once=p(x,!0),n.off=y,n},b=()=>{let e=[];return Object.assign(t=>{e.push(t)},{events:e,clear:()=>{e.length=0}})},x=()=>{},S=()=>!1,C=()=>!0,w=e=>{if(typeof e==`function`)return e;if(Array.isArray(e)){let t=new Set(e);return({phase:e})=>t.has(e)}return e?C:S},T=(e={})=>{let t=e.extension??globalThis.__REDUX_DEVTOOLS_EXTENSION__;if(!t)return x;let{starts:n=!1,depth:r=0,maxAge:i}=e,a=w(e.policies),o=t.connect({name:e.name??`nanoeffects`,...i!==void 0&&{maxAge:i}}),s=/* @__PURE__ */ new Map,c=/* @__PURE__ */ new Map,l=()=>({running:Object.fromEntries(s)});o.init(l());let u=(e,t,n)=>n===0?a({effect:e,phase:t}):n<=r,d=(e,t)=>{e.phase===`start`?(c.set(e.id,t),u(e.effect,`start`,t)&&s.set(e.id,{type:e.type,effect:e.effect,...e.traceGroupId!==void 0&&{traceGroupId:e.traceGroupId}})):(c.delete(e.id),s.delete(e.id))},f=!1,p=!1,m=(e,t)=>{f||p||t!==0||e===`start`||(p=!0,globalThis.console?.warn(`[nanoeffects] reduxDevtools got a task but no emit event: add bus.use(tracePlugin()) to see the emits.`))},h=(e,t)=>{o.send({...e,type:`${e.type}/${e.effect}/${e.phase}`,event:e.type,...e.phase===`error`&&{error:t instanceof Error?t.message:t}},l())};return({error:e,...t})=>{if(t.effect===`emit`){f=!0,o.send({...t,event:t.type},l());return}let r=(t.parentId===void 0?-1:c.get(t.parentId)??-1)+1;d(t,r),m(t.phase,r),(t.phase===`error`&&r===0||u(t.effect,t.phase,r))&&(t.phase!==`start`||n)&&h(t,e)}},E=e=>{let t=typeof e==`function`?[e]:[...e??[]];return t.length===0?null:e=>{for(let r of t)try{r(e)}catch(e){n(`trace logger failed`,e)}}},D=()=>{},O=e=>{if(typeof e.traceGroupId==`string`)return e.traceGroupId;let t=m();if(typeof t!=`object`&&typeof t!=`function`||t===null)return;let n=Reflect.get(t,u),r=typeof n==`object`&&n?Reflect.get(n,`traceGroupId`):void 0;return typeof r==`string`?r:void 0},k=(e,t={})=>{let n=E(e),{filter:r,sample:i=1}=t,a=0,o=e=>typeof i==`function`?i({type:e.type,payload:e.payload}):Math.random()<i,l={task:(e,t)=>({id:++a,root:t?.root??a,parent:t?.id,type:e.type,payload:e.payload,sampled:t?.sampled??o(e),group:O(e)??t?.group}),rename:(e,t)=>{e.type=t},report:(e,t,i,a)=>{if(!e.sampled)return;let o={id:e.id,type:e.type,effect:t,phase:i,payload:e.payload};typeof e.parent==`number`&&(o.parentId=e.parent),e.root!==e.id&&(o.rootId=e.root),e.group!==void 0&&(o.traceGroupId=e.group),i===`error`&&(o.error=a),(!r||r(o))&&n?.(o)},settler:(e,t)=>{if(!e.sampled)return D;let n=!1;return(r,i)=>{n||(n=!0,l.report(e,t,r,i))}},run:(e,t,n,r)=>{if(!e.sampled)return r();let i=l.settler(e,t);l.report(e,t,`start`),s({signal:n},()=>i(`cancel`));let a;try{a=r()}catch(e){throw i(`error`,e),e}return c(a)?Promise.resolve(a).then(e=>(i(`done`),e),e=>{throw i(`error`,e),e}):(i(`done`),a)}};return l};export{d as consoleLogger,b as createTraceRecorder,k as createTracer,f as performanceLogger,T as reduxDevtools,y as tracePlugin};
@@ -1,5 +1,5 @@
1
- import { B as EventMap, d as Effects, o as Scope, s as WithFields } from "./action-creator-BrZF6hXc.js";
2
- import { t as BoundOf } from "./plugin-DkXCvsmB.js";
1
+ import { B as EventMap, d as Effects, o as Scope, s as WithFields } from "./action-creator-CQlFgQm4.js";
2
+ import { t as BoundOf } from "./plugin-BrTsPg2Y.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
@@ -1 +1 @@
1
- import{n as e}from"./context-COgyNlrC.js";const t=Reflect.get(Symbol,`dispose`),n=n=>{let r=new AbortController,i=async(...t)=>{let i=t[0],{ctx:a,unlink:o}=e({event:{type:`withPolicy`,payload:i},parent:{signal:r.signal}});try{return await n(i,a)}finally{o()}},a=e=>{r.abort(e),r=new AbortController},o=Object.assign(i,{cancel:a});return t&&Reflect.set(o,t,()=>a()),o};export{n as t};
1
+ import{n as e}from"./context-CJGW6OWj.js";const t=Reflect.get(Symbol,`dispose`),n=n=>{let r=new AbortController,i=async(...t)=>{let i=t[0],{ctx:a,unlink:o}=e({event:{type:`withPolicy`,payload:i},parent:{signal:r.signal}});try{return await n(i,a)}finally{o()}},a=e=>{r.abort(e),r=new AbortController},o=Object.assign(i,{cancel:a});return t&&Reflect.set(o,t,()=>a()),o};export{n as t};
@@ -1,4 +1,4 @@
1
- import { B as EventMap, H as PayloadOf, W as Task } from "./action-creator-BrZF6hXc.js";
1
+ import { B as EventMap, G as Task, U as PayloadOf } from "./action-creator-CQlFgQm4.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/oop.md CHANGED
@@ -194,6 +194,8 @@ Things to know:
194
194
  - On a class that `extendBus` did not make, a decorator does nothing.
195
195
  - Both the decorators of the language and `experimentalDecorators` work. Your compiler has to support the one you use: TypeScript 5 or newer for the first, and the `experimentalDecorators` option for the second.
196
196
 
197
+ Name a method for the [trace](tracing.md#name-a-listener) with `{ traceId }`, as the second argument or, after a wrapper, the third: `@On(queryChanged, { traceId: "searcher" })` or `@On(queryChanged, latest, { traceId: "searcher" })`. It needs `tracePlugin` on the bus and is ignored without it.
198
+
197
199
  ## Decorate the class with `@WithBus`
198
200
 
199
201
  `@WithBus(bus)` does what `extendBus(bus, Base)` does, as a class decorator. `@WithBus()` makes a bus for the class.
package/docs/package.md CHANGED
@@ -16,7 +16,7 @@ Imports are split so you only load what you use. `createBus` stays small; the re
16
16
  | `nanoeffects/observable` | `createObserve` |
17
17
  | `nanoeffects/react` | `reactPlugin`: adds the `useEmitter` hook to a bus (needs React 18 or newer) |
18
18
  | `nanoeffects/dev` | `devPlugin` (no-op in production) |
19
- | `nanoeffects/trace` | `createTracer` and the loggers |
19
+ | `nanoeffects/trace` | `createTracer`, the loggers and `tracePlugin` (names for the trace) |
20
20
 
21
21
  The `...Plugin` names above are used with `bus.use`. [Plugins](plugins.md) lists all of them, what each returns, and the order to use them in.
22
22
 
package/docs/plugins.md CHANGED
@@ -95,6 +95,7 @@ Add one of these when you meet its need. None of them is required.
95
95
  | [`signalPlugin`](#tie-an-emit-to-an-outside-signal-signalplugin) | `emit(call, { signal })` that aborts its tasks when an outside signal aborts. | `nanoeffects/signal` | The same bus, typed with the new `emit` |
96
96
  | [`matchPlugin`](#listen-to-a-group-of-events-matchplugin) | `on` that listens to a group of events which a function picks. | `nanoeffects/match` | The same bus, typed with the new overloads |
97
97
  | [`emitterPlugin`](#hand-the-bus-to-a-state-manager-emitterplugin) | A callback that emits an action, to give to a state manager. | `nanoeffects/actions` | The same bus, with `emitter` |
98
+ | [`tracePlugin`](#name-the-origin-and-the-flow-of-a-trace-traceplugin) | `traceId` and `traceGroupId` for a trace: the root of an emitter, a flow, a named listener. | `nanoeffects/trace` | The same bus |
98
99
  | [`reactPlugin`](#tell-the-bus-when-a-react-value-changes-reactplugin) | A React hook that emits when a value of a component changes. | `nanoeffects/react` | The same bus, with `useEmitter` |
99
100
  | [`devPlugin`](#find-leaks-while-you-develop-devplugin) | Warnings about listeners that pile up, and messages about modules, while you develop. | `nanoeffects/dev` | A function that disconnects it |
100
101
 
@@ -138,6 +139,20 @@ bus.emit(getUser("1"), { signal: controller.signal }); // runs the command
138
139
  controller.abort(); // ctx.signal of the handler aborts with it
139
140
  ```
140
141
 
142
+ ### Name the origin and the flow of a trace: `tracePlugin`
143
+
144
+ With a tracer on the bus, the plugin lets a trace say which subscription began a chain (`traceId` of `useEmitter` and `bus.emitter`), follow one flow by a `traceGroupId`, and show which listener ran (`bus.on(event, handler, { traceId })`). Without the plugin the options are ignored. More in [Tracing](tracing.md#show-which-subscription-began-a-chain).
145
+
146
+ ```js
147
+ import { createBus } from "nanoeffects";
148
+ import { consoleLogger, createTracer, tracePlugin } from "nanoeffects/trace";
149
+
150
+ // tracePlugin — names the roots, groups and listeners of the trace
151
+ const bus = createBus({ trace: createTracer(consoleLogger()) }).use(tracePlugin());
152
+
153
+ bus.on("name/changed", saveName, { traceId: "saveNotifier" }); // a listener you can find in the log
154
+ ```
155
+
141
156
  ### Listen to a group of events: `matchPlugin`
142
157
 
143
158
  `on`, `once` and `off` take a function that picks the events, such as every `user/*` event. A type guard narrows the payload. The subscription listens to every event, so for a few known events `on(creator, handler)` is cheaper. More in the [Guide](guide.md#pick-events-with-a-function).
@@ -174,7 +189,7 @@ $name.listen(bus.emitter(nameChanged)); // every change of $name emits nameChang
174
189
 
175
190
  ### Tell the bus when a React value changes: `reactPlugin`
176
191
 
177
- `useEmitter(event, value)` emits after a render commits with a new value. It does not emit on mount, and not twice under StrictMode. It needs React 18 or newer. More in [Stores](stores.md#react-sharing-a-value-across-components).
192
+ `useEmitter(event, value, options?)` emits after a render commits with a new value. It does not emit on mount, and not twice under StrictMode. The options are `{ equals, traceId, traceGroupId }`; the last two name the emit in the [trace](tracing.md#show-which-subscription-began-a-chain). It needs React 18 or newer. More in [Stores](stores.md#react-sharing-a-value-across-components).
178
193
 
179
194
  ```jsx
180
195
  import { useState } from "react";
package/docs/scope.md CHANGED
@@ -189,7 +189,7 @@ When several places set the same field, the strongest one wins:
189
189
  | 3 | the scope of the module that owns the handler |
190
190
  | 4 (weakest) | the bus: `createBus({ context })`, `contextPlugin`, `effectsPlugin` |
191
191
 
192
- The fields of the library (`signal`, `abort`, `emit`, `on`, `off`, `run`, `type`, `payload`) are never replaced. A child task (`ctx.run`, an attempt of `retry`) has the fields of its parent.
192
+ The fields of the library (`signal`, `abort`, `emit`, `on`, `off`, `run`, `type`, `payload`) are never replaced. The name `traceGroupId` is reserved: the tracer reads it, and it is not put on `ctx` ([Follow one flow](tracing.md#follow-one-flow-with-a-tracegroupid)). A child task (`ctx.run`, an attempt of `retry`) has the fields of its parent.
193
193
 
194
194
  ## Keep a generic effect generic
195
195
 
package/docs/stores.md CHANGED
@@ -83,6 +83,10 @@ String event names (`"user/requested"`) work the same. Use your usual RTK action
83
83
 
84
84
  The only option is `filter`, which keeps rejected actions away from the bus. Options of the bus (`onError`, `context`, `trace`) go to `createBus`. Use one bus for one store. Values that are not plain actions (thunks) go through untouched. Nothing here depends on the `redux` package at runtime.
85
85
 
86
+ ### Show which dispatch began a chain
87
+
88
+ With a tracer and `tracePlugin` on the bus, each dispatched action reaches the bus from a root task of the trace. Name it with `traceId`, and put the flow in a group with `traceGroupId`: `createEffectsMiddleware(bus, { traceId: "store", traceGroupId: "checkout" })`. Without a `traceId` the root has the type of the action. Without the plugin the options are ignored. More in [Tracing](tracing.md#show-which-subscription-began-a-chain).
89
+
86
90
  ### Type `ctx.store` (optional)
87
91
 
88
92
  Only if you want TypeScript to know `store` on handlers. **Skip this in JavaScript** — the middleware already puts `store` on the task at runtime. These lines do not connect the store across the app.
@@ -461,7 +465,7 @@ export function Results() {
461
465
  Two limits to know:
462
466
 
463
467
  - **All consumers re-render** on any change of the context value. Split it into two contexts (`query` and `items`) if that is slow.
464
- - **A new object counts as a change.** For a value that is rebuilt with the same content, pass a third argument that says when two values are the same: `useEmitter(profileChanged, profile, (previous, next) => previous.id === next.id)`.
468
+ - **A new object counts as a change.** For a value that is rebuilt with the same content, pass `equals` in the options, the third argument, to say when two values are the same: `useEmitter(profileChanged, profile, { equals: (previous, next) => previous.id === next.id })`. The same object takes `traceId` and `traceGroupId`, which name the subscription and the flow in the [trace](tracing.md#show-which-subscription-began-a-chain).
465
469
 
466
470
  `useEmitter` emits after the render, not at the moment of `setQuery`. To emit on every call, even with the same value, call an emitter from the event handler (`bus.emitter(action)`, see [Zustand](#zustand)) instead.
467
471