nanoeffects 0.24.0 → 0.26.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/actions.d.ts +2 -2
- package/dist/dev.d.ts +1 -1
- package/dist/effects.d.ts +2 -2
- package/dist/effects.js +1 -1
- package/dist/{module-ChMx7hHT.d.ts → module-B6rg5NIb.d.ts} +1 -1
- package/dist/notrace/actions.d.ts +1 -1
- package/dist/notrace/effects.d.ts +2 -2
- package/dist/notrace/effects.js +1 -1
- package/dist/notrace/{plugin-jkWtYPT7.d.ts → plugin-Dz6hq8Jg.d.ts} +22 -16
- package/dist/{plugin-CGIdsEGF.d.ts → plugin-D-j1DarG.d.ts} +22 -16
- package/dist/scope.d.ts +1 -1
- package/dist/{types-B0DMvfsU.d.ts → types-Bkuhnkq6.d.ts} +1 -1
- package/docs/README.md +1 -0
- package/docs/effects.md +24 -1
- package/docs/oop.md +2 -0
- package/docs/stability.md +90 -0
- package/llms-full.txt +120 -1
- package/llms.txt +1 -0
- package/package.json +2 -2
package/dist/actions.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { H as PayloadOf, T as EventKey, W as Task, c as WithScope, h as Bus, n as Free, o as Scope, r as FreeActionCreator, t as ActionCreator, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
-
import { r as Scoped, t as FieldsOfScope } from "./types-
|
|
3
|
-
import { a as createModule, c as CarryingCalls, d as commandsPlugin, f as createCommand, l as MadeCommand, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as Binding, t as Module, u as bindHandler } from "./module-
|
|
2
|
+
import { r as Scoped, t as FieldsOfScope } from "./types-Bkuhnkq6.js";
|
|
3
|
+
import { a as createModule, c as CarryingCalls, d as commandsPlugin, f as createCommand, l as MadeCommand, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as Binding, t as Module, u as bindHandler } from "./module-B6rg5NIb.js";
|
|
4
4
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
5
5
|
//#region src/actions/action.d.ts
|
|
6
6
|
type ScopedCreator<P, T extends string, F> = [P] extends [Free] ? FreeActionCreator<T, F> & WithScope<F> : ActionCreator<P, T, PayloadOf<P>, F> & WithScope<F>;
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { J as UnsubscribeCallback, h as Bus, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
-
import { i as WithApp, n as ModuleApi } from "./module-
|
|
2
|
+
import { i as WithApp, n as ModuleApi } from "./module-B6rg5NIb.js";
|
|
3
3
|
//#region src/dev/types.d.ts
|
|
4
4
|
/** The parts of what `modulePlugin` returned that the diagnostics report. */
|
|
5
5
|
type ReportedApp<E extends EventMap> = Pick<ModuleApi<E>, "mount" | "unmount" | "isMounted">;
|
package/dist/effects.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { P as WithSignal, W as Task, b as Context, u as Effect, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
-
import { a as RaceStarter, c as all, d as
|
|
2
|
+
import { a as RaceStarter, c as all, d as GroupOptions, f as Starter, i as take, l as ChildOf, m as delay, n as effectsPlugin, o as race, p as StarterOf, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-D-j1DarG.js";
|
|
3
3
|
//#region src/utils/onAbort.d.ts
|
|
4
4
|
export declare const onAbort: (ctx: {
|
|
5
5
|
signal?: AbortSignal | undefined;
|
|
@@ -187,4 +187,4 @@ export declare function timeout<C extends {
|
|
|
187
187
|
signal?: AbortSignal;
|
|
188
188
|
}, T>(ctx: C, ms: number, starter: Starter<T, ChildOf<C>>): Promise<T>;
|
|
189
189
|
//#endregion
|
|
190
|
-
export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type PollOptions, type RaceStarter, type RetryOptions, type StarterOf, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
|
|
190
|
+
export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type GroupOptions, type PollOptions, type RaceStarter, type RetryOptions, type StarterOf, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
|
package/dist/effects.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,n as t,r as n,t as r}from"./delay-18LJ8jSk.js";import{d as i,i as a,o,s,t as c,u as l}from"./context-UcmrAIhP.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=l(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:o}=a(t??{}),d=c(i,e);s(i,e,`start`),l(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{o()}},f=async(e,t)=>{let{ctx:n,unlink:r}=a(e);try{return await o(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=a(e),i=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(o(r.ctx,`run`,i))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=(t,n)=>{if(t.length
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"./delay-18LJ8jSk.js";import{d as i,i as a,o,s,t as c,u as l}from"./context-UcmrAIhP.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=l(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:o}=a(t??{}),d=c(i,e);s(i,e,`start`),l(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{o()}},f=async(e,t)=>{let{ctx:n,unlink:r}=a(e);try{return await o(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=a(e),i=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(o(r.ctx,`run`,i))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=e=>{let t=e?.concurrency??1/0;if(t!==1/0&&!(Number.isInteger(t)&&t>=1))throw RangeError(`concurrency must be a positive integer`);return t},v=(e,t,n,r)=>{let i=Object.entries(t),s=[],c=i.map(([e])=>[e,new Promise(e=>s.push(e))]),l=/* @__PURE__ */ new Set,u=0,d=0,f=!1,p=()=>{for(;!f&&!e.signal.aborted&&d<n&&u<i.length;){let t=u++,[,n]=i[t],c=a(e),m=()=>n(c.ctx),h=()=>{c.unlink(),l.delete(c.ctx.abort),d--};l.add(c.ctx.abort),d++;let g=new Promise(e=>e(o(c.ctx,`run`,m))).then(e=>(h(),p(),e),e=>{throw h(),f=r,p(),e});s[t]?.(g)}};return p(),{tasks:c,cancelAll:()=>{f=!0;for(let e of l)e()}}},y=(t,n)=>{if(t.length!==1)return n(...t);let[r]=t;if(e(Reflect.get(r,`signal`)))throw TypeError(`A group takes effects: call it as (effects), or as (ctx, effects); a context alone has none`);return e=>n(e,r)},b=(e,t,n,r,i,a)=>{let o=_(a),s=()=>{};return d(e,t,async t=>{let i=o===1/0?g(t,n):v(t,n,o,e===`all`);return s=i.cancelAll,r(i.tasks)},e=>{(e||i===`end`)&&s()})};function x(...e){return y(e,S)}const S=(e,t,n)=>b(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),C=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function w(...e){return y(e,T)}const T=(e,t,n)=>b(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>C(e))),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),E=e=>e>0?e:0,D=(e={})=>{let t=E(e.base??100),n=e.factor??2,r=E(e.max??1/0),i=e.jitter??!1;return e=>{let a=E(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},O=(e,t)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((n,r)=>{let a=[],o=`pending`,s=e=>{try{e()}catch(e){i(`cancel cleanup failed`,e)}},c=l(e,e=>{o=`cancelled`;for(let e of a.reverse())s(e);r(e)}),u=e=>(...t)=>{o===`pending`&&(o=`settled`,c(),a.length=0,e(...t))},d=e=>{o===`pending`?a.push(e):o===`cancelled`&&s(e)};try{t({resolve:u(n),reject:u(r),onCancel:d})}catch(e){u(r)(e)}}),k=Symbol(`nanoeffects.effects.effect`),A=e=>t=>{let n=t.addContext,r=Object.entries(e);return t.addContext=e=>{n?.(e);for(let[t,n]of r){let r=Reflect.get(e,t);if(r===void 0||r[k]===n){let r=(...t)=>n(e,...t);r[k]=n,Reflect.set(e,t,r)}}},t},j=()=>/* @__PURE__ */ TypeError(`A Task is called as (payload, ctx), or as (ctx) when a group starts it; the single argument is not a context`),M=t=>{if(e(t)&&`signal`in t)return t;throw j()},N=(e,t,n)=>t===void 0?n(M(e),void 0):n(t,e),P=(e,r,i,a)=>{if(e.signal.aborted)return Promise.resolve();let o=a.leading??!1,s=a.waitForFn??!1;return d(`poll`,e,e=>new Promise((a,c)=>{let u=0,d=null,p=()=>{d!==null&&(t(d),d=null)},m=e=>{try{d=n(h,typeof i==`function`?i(e):i)}catch(e){p(),c(e)}},h=()=>{d=null,s||m(u+1),g()},g=()=>{let t=u++;f(e,e=>r(e,t)).then(()=>{s&&!e.signal.aborted&&m(u)},e=>{p(),c(e)})};l(e,p),o?(g(),s||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function F(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{},a=(t,n)=>P(t,m(r,n),e,i);return(e,t)=>N(e,t,a)}let i=t;return P(e,(e,t)=>i(t),n,r)}function I(...e){return y(e,L)}const L=(e,t)=>{let n=h(t);return Object.keys(t).length===0?Promise.resolve(n):b(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)},R=(e,t,n)=>typeof e==`function`?e(t,n):e,z=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),B=(e,t,n)=>d(`retry`,e,async e=>{let{times:i,delay:a,shouldRetry:o}=z(n);for(let n=1;;n++)try{return await f(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<i)||!o(t,n))throw t;let s=R(a,n,t);s>0&&await r(e,s)}});function V(e,t,n={}){if(typeof e==`function`){let n=e,r=t??{},i=(e,t)=>B(e,m(n,t),r);return(e,t)=>N(e,t,i)}let r=t;return B(e,(e,t)=>r(t),n)}const H=(e,t,n={})=>d(`take`,e,r=>new Promise((i,a)=>{let{predicate:o}=n,s=[],c=()=>{for(let e of s)e()},u=e=>{c(),a(e)},d=t;s.push(e.on(d,e=>{(!o||o(e))&&(c(),i(e))})),s.push(l(r,u)),s.push(l({signal:n.signal},u))}));function U(t,n,r){if(e(t))return H(t,n,r);let i=n;return e=>H(e,t,i)}const W=(e,r,i)=>d(`timeout`,e,async e=>{let s=a(e),c=n(()=>s.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await u(Promise.resolve(o(s.ctx,`run`,()=>i(s.ctx))),s.ctx)}finally{t(c),s.unlink()}});function G(e,t,n){if(typeof e==`number`){let n=t,r=(t,r)=>W(t,e,m(n,r));return(e,t)=>N(e,t,r)}return W(e,t,n)}export{x as all,w as allSettled,D as backoff,O as cancellable,r as delay,A as effectsPlugin,l as onAbort,F as poll,I as race,V as retry,U as take,G as timeout};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { H as PayloadOf, J as UnsubscribeCallback, W as Task, _ as Command, b as Context, c as WithScope, h as Bus, o as Scope, v as CommandCall, y as Commands, z as EventMap } from "./action-creator-Bpa8BUS9.js";
|
|
2
|
-
import { n as ScopeSlots, r as Scoped, t as FieldsOfScope } from "./types-
|
|
2
|
+
import { n as ScopeSlots, r as Scoped, t as FieldsOfScope } from "./types-Bkuhnkq6.js";
|
|
3
3
|
//#region src/actions/command.d.ts
|
|
4
4
|
/** What `createCommand` returns: a command that also tells whether an action is of its type. */
|
|
5
5
|
type MadeCommand<P, R, T extends string> = Command<P, R> & {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { C as EventKey, F as EventMap, L as PayloadOf, R as Task, _ as Commands, a as Scope, g as CommandCall, h as Command, n as Free, o as WithFields, p as Bus, r as FreeActionCreator, s as WithScope, t as ActionCreator, u as Effects, v as Context, z as UnsubscribeCallback } from "./action-creator-D2CotugT.js";
|
|
2
|
-
import { t as BoundOf } from "./plugin-
|
|
2
|
+
import { t as BoundOf } from "./plugin-Dz6hq8Jg.js";
|
|
3
3
|
import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
|
|
4
4
|
//#region src/scope/types.d.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as EventMap, M as WithSignal, R as Task, l as Effect, v as Context } from "./action-creator-D2CotugT.js";
|
|
2
|
-
import { a as RaceStarter, c as all, d as
|
|
2
|
+
import { a as RaceStarter, c as all, d as GroupOptions, f as Starter, i as take, l as ChildOf, m as delay, n as effectsPlugin, o as race, p as StarterOf, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-Dz6hq8Jg.js";
|
|
3
3
|
//#region src/utils/onAbort.d.ts
|
|
4
4
|
export declare const onAbort: (ctx: {
|
|
5
5
|
signal?: AbortSignal | undefined;
|
|
@@ -187,4 +187,4 @@ export declare function timeout<C extends {
|
|
|
187
187
|
signal?: AbortSignal;
|
|
188
188
|
}, T>(ctx: C, ms: number, starter: Starter<T, ChildOf<C>>): Promise<T>;
|
|
189
189
|
//#endregion
|
|
190
|
-
export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type PollOptions, type RaceStarter, type RetryOptions, type StarterOf, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
|
|
190
|
+
export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type GroupOptions, type PollOptions, type RaceStarter, type RetryOptions, type StarterOf, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
|
package/dist/notrace/effects.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,n as t,r as n,t as r}from"./delay-Besb3X1O.js";import{a as i,c as a,i as o,l as s,o as c,t as l}from"./context-_HWcdjZf.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=a(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:s}=o(t??{}),d=l(i,e);c(i,e,`start`),a(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{s()}},f=async(e,t)=>{let{ctx:n,unlink:r}=o(e);try{return await i(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=o(e),a=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(i(r.ctx,`run`,a))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=(t,n)=>{if(t.length
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"./delay-Besb3X1O.js";import{a as i,c as a,i as o,l as s,o as c,t as l}from"./context-_HWcdjZf.js";const u=(e,t)=>t?.signal?new Promise((n,r)=>{let i=a(t,r);e.then(n,r).finally(i)}):e,d=async(e,t,n,r)=>{t?.signal?.throwIfAborted();let{ctx:i,unlink:s}=o(t??{}),d=l(i,e);c(i,e,`start`),a(i,()=>d(`cancel`));try{let e=await u(n(i),t);return d(`done`),r?.(!1),e}catch(e){throw d(`error`,e),r?.(!0),e}finally{s()}},f=async(e,t)=>{let{ctx:n,unlink:r}=o(e);try{return await i(n,`run`,()=>t(n))}finally{r()}},p=e=>e,m=(e,t)=>n=>e(t,p(n)),h=e=>Array.isArray(e)?Array(e.length):{},g=(e,t)=>{let n=Object.entries(t).map(([t,n])=>{let r=o(e),a=()=>n(r.ctx);return{key:t,task:new Promise(e=>e(i(r.ctx,`run`,a))).finally(r.unlink),cancel:r.ctx.abort}});return{tasks:n.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of n)e.cancel()}}},_=e=>{let t=e?.concurrency??1/0;if(t!==1/0&&!(Number.isInteger(t)&&t>=1))throw RangeError(`concurrency must be a positive integer`);return t},v=(e,t,n,r)=>{let a=Object.entries(t),s=[],c=a.map(([e])=>[e,new Promise(e=>s.push(e))]),l=/* @__PURE__ */ new Set,u=0,d=0,f=!1,p=()=>{for(;!f&&!e.signal.aborted&&d<n&&u<a.length;){let t=u++,[,n]=a[t],c=o(e),m=()=>n(c.ctx),h=()=>{c.unlink(),l.delete(c.ctx.abort),d--};l.add(c.ctx.abort),d++;let g=new Promise(e=>e(i(c.ctx,`run`,m))).then(e=>(h(),p(),e),e=>{throw h(),f=r,p(),e});s[t]?.(g)}};return p(),{tasks:c,cancelAll:()=>{f=!0;for(let e of l)e()}}},y=(t,n)=>{if(t.length!==1)return n(...t);let[r]=t;if(e(Reflect.get(r,`signal`)))throw TypeError(`A group takes effects: call it as (effects), or as (ctx, effects); a context alone has none`);return e=>n(e,r)},b=(e,t,n,r,i,a)=>{let o=_(a),s=()=>{};return d(e,t,async t=>{let i=o===1/0?g(t,n):v(t,n,o,e===`all`);return s=i.cancelAll,r(i.tasks)},e=>{(e||i===`end`)&&s()})};function x(...e){return y(e,S)}const S=(e,t,n)=>b(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),C=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function w(...e){return y(e,T)}const T=(e,t,n)=>b(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>C(e))),r=h(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`,n),E=e=>e>0?e:0,D=(e={})=>{let t=E(e.base??100),n=e.factor??2,r=E(e.max??1/0),i=e.jitter??!1;return e=>{let a=E(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},O=(e,t)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((n,r)=>{let i=[],o=`pending`,c=e=>{try{e()}catch(e){s(`cancel cleanup failed`,e)}},l=a(e,e=>{o=`cancelled`;for(let e of i.reverse())c(e);r(e)}),u=e=>(...t)=>{o===`pending`&&(o=`settled`,l(),i.length=0,e(...t))},d=e=>{o===`pending`?i.push(e):o===`cancelled`&&c(e)};try{t({resolve:u(n),reject:u(r),onCancel:d})}catch(e){u(r)(e)}}),k=Symbol(`nanoeffects.effects.effect`),A=e=>t=>{let n=t.addContext,r=Object.entries(e);return t.addContext=e=>{n?.(e);for(let[t,n]of r){let r=Reflect.get(e,t);if(r===void 0||r[k]===n){let r=(...t)=>n(e,...t);r[k]=n,Reflect.set(e,t,r)}}},t},j=()=>/* @__PURE__ */ TypeError(`A Task is called as (payload, ctx), or as (ctx) when a group starts it; the single argument is not a context`),M=t=>{if(e(t)&&`signal`in t)return t;throw j()},N=(e,t,n)=>t===void 0?n(M(e),void 0):n(t,e),P=(e,r,i,o)=>{if(e.signal.aborted)return Promise.resolve();let s=o.leading??!1,c=o.waitForFn??!1;return d(`poll`,e,e=>new Promise((o,l)=>{let u=0,d=null,p=()=>{d!==null&&(t(d),d=null)},m=e=>{try{d=n(h,typeof i==`function`?i(e):i)}catch(e){p(),l(e)}},h=()=>{d=null,c||m(u+1),g()},g=()=>{let t=u++;f(e,e=>r(e,t)).then(()=>{c&&!e.signal.aborted&&m(u)},e=>{p(),l(e)})};a(e,p),s?(g(),c||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function F(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{},a=(t,n)=>P(t,m(r,n),e,i);return(e,t)=>N(e,t,a)}let i=t;return P(e,(e,t)=>i(t),n,r)}function I(...e){return y(e,L)}const L=(e,t)=>{let n=h(t);return Object.keys(t).length===0?Promise.resolve(n):b(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)},R=(e,t,n)=>typeof e==`function`?e(t,n):e,z=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),B=(e,t,n)=>d(`retry`,e,async e=>{let{times:i,delay:a,shouldRetry:o}=z(n);for(let n=1;;n++)try{return await f(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<i)||!o(t,n))throw t;let s=R(a,n,t);s>0&&await r(e,s)}});function V(e,t,n={}){if(typeof e==`function`){let n=e,r=t??{},i=(e,t)=>B(e,m(n,t),r);return(e,t)=>N(e,t,i)}let r=t;return B(e,(e,t)=>r(t),n)}const H=(e,t,n={})=>d(`take`,e,r=>new Promise((i,o)=>{let{predicate:s}=n,c=[],l=()=>{for(let e of c)e()},u=e=>{l(),o(e)},d=t;c.push(e.on(d,e=>{(!s||s(e))&&(l(),i(e))})),c.push(a(r,u)),c.push(a({signal:n.signal},u))}));function U(t,n,r){if(e(t))return H(t,n,r);let i=n;return e=>H(e,t,i)}const W=(e,r,a)=>d(`timeout`,e,async e=>{let s=o(e),c=n(()=>s.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await u(Promise.resolve(i(s.ctx,`run`,()=>a(s.ctx))),s.ctx)}finally{t(c),s.unlink()}});function G(e,t,n){if(typeof e==`number`){let n=t,r=(t,r)=>W(t,e,m(n,r));return(e,t)=>N(e,t,r)}return W(e,t,n)}export{x as all,w as allSettled,D as backoff,O as cancellable,r as delay,A as effectsPlugin,a as onAbort,F as poll,I as race,V as retry,U as take,G as timeout};
|
|
@@ -71,7 +71,12 @@ type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
|
|
|
71
71
|
* bus.on("open", async (_, ctx) => race(ctx, { load, user }));
|
|
72
72
|
* ```
|
|
73
73
|
*/
|
|
74
|
-
type StarterOf
|
|
74
|
+
type StarterOf<E extends EventMap, R = unknown> = Starter<R, Context<E>>;
|
|
75
|
+
/** Options of `all` and `allSettled`. */
|
|
76
|
+
type GroupOptions = {
|
|
77
|
+
/** At most this many starters run at once; the next starts when one settles. Default: no limit. */
|
|
78
|
+
concurrency?: number | undefined;
|
|
79
|
+
};
|
|
75
80
|
//#endregion
|
|
76
81
|
//#region src/effects/all.d.ts
|
|
77
82
|
/**
|
|
@@ -91,10 +96,10 @@ type StarterOf$1<E extends EventMap, R = unknown> = Starter<R, Context<E>>;
|
|
|
91
96
|
*/
|
|
92
97
|
declare function all<C extends {
|
|
93
98
|
signal?: AbortSignal;
|
|
94
|
-
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
99
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
95
100
|
declare function all<C extends {
|
|
96
101
|
signal?: AbortSignal;
|
|
97
|
-
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
102
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
98
103
|
declare function all<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
99
104
|
declare function all<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
100
105
|
//#endregion
|
|
@@ -119,14 +124,15 @@ declare function all<Child, const T extends readonly Starter<unknown, Child>[]>(
|
|
|
119
124
|
*/
|
|
120
125
|
declare function allSettled<C extends {
|
|
121
126
|
signal?: AbortSignal;
|
|
122
|
-
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
127
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
123
128
|
declare function allSettled<C extends {
|
|
124
129
|
signal?: AbortSignal;
|
|
125
|
-
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
130
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
126
131
|
declare function allSettled<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
127
132
|
declare function allSettled<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
128
133
|
//#endregion
|
|
129
134
|
//#region src/effects/race.d.ts
|
|
135
|
+
/** @deprecated Use `StarterOf<Events, Result>`; this name goes in 1.0.0. */
|
|
130
136
|
type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
|
|
131
137
|
/**
|
|
132
138
|
* Runs all starters; first to settle wins, losers are cancelled via `ctx.abort`.
|
|
@@ -147,12 +153,12 @@ type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
|
|
|
147
153
|
*/
|
|
148
154
|
declare function race<C extends {
|
|
149
155
|
signal?: AbortSignal;
|
|
150
|
-
}, T extends Record<string,
|
|
156
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
151
157
|
declare function race<C extends {
|
|
152
158
|
signal?: AbortSignal;
|
|
153
|
-
}, const T extends readonly
|
|
154
|
-
declare function race<Child, T extends Record<string,
|
|
155
|
-
declare function race<Child, const T extends readonly
|
|
159
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
160
|
+
declare function race<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
161
|
+
declare function race<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
156
162
|
//#endregion
|
|
157
163
|
//#region src/effects/take.d.ts
|
|
158
164
|
type TakeOptions<P> = {
|
|
@@ -233,12 +239,12 @@ type Bound<E extends EventMap, Child> = {
|
|
|
233
239
|
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
234
240
|
};
|
|
235
241
|
all: {
|
|
236
|
-
<T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
237
|
-
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
242
|
+
<T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
243
|
+
<const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
238
244
|
};
|
|
239
245
|
allSettled: {
|
|
240
|
-
<T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
241
|
-
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
246
|
+
<T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
247
|
+
<const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
242
248
|
};
|
|
243
249
|
take: {
|
|
244
250
|
<K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): Promise<E[K]>;
|
|
@@ -254,9 +260,9 @@ type Helpers = Effects;
|
|
|
254
260
|
* The effects as a handler sees them: the built-in ones keep their hand-written
|
|
255
261
|
* types, any other loses its first parameter, or has the type `Effect<F>` says.
|
|
256
262
|
*/
|
|
257
|
-
type BoundOf<H extends Helpers, E extends EventMap> = { [K in keyof H]: K extends keyof Bound<E,
|
|
263
|
+
type BoundOf<H extends Helpers, E extends EventMap> = { [K in keyof H]: K extends keyof Bound<E, BoundStarter<H, E>> ? H[K] extends Supported[K] ? Bound<E, BoundStarter<H, E>>[K] : BoundForm<H[K]> : BoundForm<H[K]>; };
|
|
258
264
|
/** What a starter of a bound `race` / `all` / `allSettled` gets: the context of its child, with the same bound effects. */
|
|
259
|
-
type
|
|
265
|
+
type BoundStarter<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H, E>;
|
|
260
266
|
/**
|
|
261
267
|
* Puts the effects you pass on the context of every task of the bus, bound to
|
|
262
268
|
* that task, so a handler can write `({ race })` instead of `race(ctx, …)`.
|
|
@@ -280,4 +286,4 @@ type StarterOf<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H,
|
|
|
280
286
|
*/
|
|
281
287
|
declare const effectsPlugin: <H extends Helpers>(helpers: H) => <E extends EventMap>(bus: Bus<E> & NoClash<BoundOf<H, E>, E>) => Bus<E & WithContext<BoundOf<H, E>>>;
|
|
282
288
|
//#endregion
|
|
283
|
-
export { RaceStarter as a, all as c,
|
|
289
|
+
export { RaceStarter as a, all as c, GroupOptions as d, Starter as f, take as i, ChildOf as l, delay as m, effectsPlugin as n, race as o, StarterOf as p, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
|
|
@@ -65,7 +65,12 @@ type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
|
|
|
65
65
|
* bus.on("open", async (_, ctx) => race(ctx, { load, user }));
|
|
66
66
|
* ```
|
|
67
67
|
*/
|
|
68
|
-
type StarterOf
|
|
68
|
+
type StarterOf<E extends EventMap, R = unknown> = Starter<R, Context<E>>;
|
|
69
|
+
/** Options of `all` and `allSettled`. */
|
|
70
|
+
type GroupOptions = {
|
|
71
|
+
/** At most this many starters run at once; the next starts when one settles. Default: no limit. */
|
|
72
|
+
concurrency?: number | undefined;
|
|
73
|
+
};
|
|
69
74
|
//#endregion
|
|
70
75
|
//#region src/effects/all.d.ts
|
|
71
76
|
/**
|
|
@@ -85,10 +90,10 @@ type StarterOf$1<E extends EventMap, R = unknown> = Starter<R, Context<E>>;
|
|
|
85
90
|
*/
|
|
86
91
|
declare function all<C extends {
|
|
87
92
|
signal?: AbortSignal;
|
|
88
|
-
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
93
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
89
94
|
declare function all<C extends {
|
|
90
95
|
signal?: AbortSignal;
|
|
91
|
-
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
96
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
92
97
|
declare function all<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
93
98
|
declare function all<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
94
99
|
//#endregion
|
|
@@ -113,14 +118,15 @@ declare function all<Child, const T extends readonly Starter<unknown, Child>[]>(
|
|
|
113
118
|
*/
|
|
114
119
|
declare function allSettled<C extends {
|
|
115
120
|
signal?: AbortSignal;
|
|
116
|
-
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
121
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
117
122
|
declare function allSettled<C extends {
|
|
118
123
|
signal?: AbortSignal;
|
|
119
|
-
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
124
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
120
125
|
declare function allSettled<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
121
126
|
declare function allSettled<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
122
127
|
//#endregion
|
|
123
128
|
//#region src/effects/race.d.ts
|
|
129
|
+
/** @deprecated Use `StarterOf<Events, Result>`; this name goes in 1.0.0. */
|
|
124
130
|
type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
|
|
125
131
|
/**
|
|
126
132
|
* Runs all starters; first to settle wins, losers are cancelled via `ctx.abort`.
|
|
@@ -141,12 +147,12 @@ type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
|
|
|
141
147
|
*/
|
|
142
148
|
declare function race<C extends {
|
|
143
149
|
signal?: AbortSignal;
|
|
144
|
-
}, T extends Record<string,
|
|
150
|
+
}, T extends Record<string, Starter<unknown, ChildOf<C>>>>(ctx: C, effects: T): Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
145
151
|
declare function race<C extends {
|
|
146
152
|
signal?: AbortSignal;
|
|
147
|
-
}, const T extends readonly
|
|
148
|
-
declare function race<Child, T extends Record<string,
|
|
149
|
-
declare function race<Child, const T extends readonly
|
|
153
|
+
}, const T extends readonly Starter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
154
|
+
declare function race<Child, T extends Record<string, Starter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
155
|
+
declare function race<Child, const T extends readonly Starter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
150
156
|
//#endregion
|
|
151
157
|
//#region src/effects/take.d.ts
|
|
152
158
|
type TakeOptions<P> = {
|
|
@@ -227,12 +233,12 @@ type Bound<E extends EventMap, Child> = {
|
|
|
227
233
|
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
|
|
228
234
|
};
|
|
229
235
|
all: {
|
|
230
|
-
<T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
231
|
-
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
236
|
+
<T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
237
|
+
<const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
|
|
232
238
|
};
|
|
233
239
|
allSettled: {
|
|
234
|
-
<T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
235
|
-
<const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
240
|
+
<T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
241
|
+
<const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
|
|
236
242
|
};
|
|
237
243
|
take: {
|
|
238
244
|
<K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): Promise<E[K]>;
|
|
@@ -248,9 +254,9 @@ type Helpers = Effects;
|
|
|
248
254
|
* The effects as a handler sees them: the built-in ones keep their hand-written
|
|
249
255
|
* types, any other loses its first parameter, or has the type `Effect<F>` says.
|
|
250
256
|
*/
|
|
251
|
-
type BoundOf<H extends Helpers, E extends EventMap> = { [K in keyof H]: K extends keyof Bound<E,
|
|
257
|
+
type BoundOf<H extends Helpers, E extends EventMap> = { [K in keyof H]: K extends keyof Bound<E, BoundStarter<H, E>> ? H[K] extends Supported[K] ? Bound<E, BoundStarter<H, E>>[K] : BoundForm<H[K]> : BoundForm<H[K]>; };
|
|
252
258
|
/** What a starter of a bound `race` / `all` / `allSettled` gets: the context of its child, with the same bound effects. */
|
|
253
|
-
type
|
|
259
|
+
type BoundStarter<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H, E>;
|
|
254
260
|
/**
|
|
255
261
|
* Puts the effects you pass on the context of every task of the bus, bound to
|
|
256
262
|
* that task, so a handler can write `({ race })` instead of `race(ctx, …)`.
|
|
@@ -274,4 +280,4 @@ type StarterOf<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H,
|
|
|
274
280
|
*/
|
|
275
281
|
declare const effectsPlugin: <H extends Helpers>(helpers: H) => <E extends EventMap>(bus: Bus<E> & NoClash<BoundOf<H, E>, E>) => Bus<E & WithContext<BoundOf<H, E>>>;
|
|
276
282
|
//#endregion
|
|
277
|
-
export { RaceStarter as a, all as c,
|
|
283
|
+
export { RaceStarter as a, all as c, GroupOptions as d, Starter as f, take as i, ChildOf as l, delay as m, effectsPlugin as n, race as o, StarterOf as p, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
|
package/dist/scope.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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-
|
|
2
|
+
import { n as ScopeSlots, r as Scoped } from "./types-Bkuhnkq6.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
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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-
|
|
2
|
+
import { t as BoundOf } from "./plugin-D-j1DarG.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/docs/README.md
CHANGED
|
@@ -42,6 +42,7 @@ Code for every guide step: [`examples/guide.ts`](../examples/guide.ts) (type-che
|
|
|
42
42
|
- [TypeScript in many files](typescript.md) — keep the types of the bus in commands and modules
|
|
43
43
|
- [Errors and unheard events](errors.md)
|
|
44
44
|
- [Package entries](package.md) — which import holds what
|
|
45
|
+
- [Stability](stability.md) — which entries are stable, what is breaking, supported versions
|
|
45
46
|
- [Plugins](plugins.md) — every plugin of a bus, what it returns, and the order to use them in
|
|
46
47
|
- [Tracing](tracing.md) — loggers, Redux DevTools, `notrace`
|
|
47
48
|
- [Observable](observable.md) — events as TC39 Observables
|
package/docs/effects.md
CHANGED
|
@@ -347,7 +347,7 @@ bus.on("open", async (id, ctx) => {
|
|
|
347
347
|
});
|
|
348
348
|
```
|
|
349
349
|
|
|
350
|
-
The same call with a payload and a context, `(payload, ctx)`, is the Task that `bus.on` and `ctx.run` use, and it does not change.
|
|
350
|
+
The same call with a payload and a context, `(payload, ctx)`, is the Task that `bus.on` and `ctx.run` use, and it does not change. `retry`, `timeout` and `poll` therefore have three call forms: with `ctx`, as a Task, and as a starter. All three stay; [Stability](stability.md#rely-on-these-call-forms) says how they are told apart.
|
|
351
351
|
|
|
352
352
|
**`all`, `allSettled` and `race` without `ctx` are starters too**, so a group nests in another group with no wrapper. Load two things, but give up after five seconds:
|
|
353
353
|
|
|
@@ -376,6 +376,29 @@ bus.on("open", async (id, ctx) => {
|
|
|
376
376
|
|
|
377
377
|
One argument is the short form and two arguments are the form with `ctx`: `all(effects)` returns a starter, `all(ctx, effects)` runs the group. The inner group stops with the outer one and cancels its own starters. Passing only a context, `all(ctx)`, is a mistake and throws a `TypeError` at once. A group starter written in a group needs no type. One kept in a variable outside a group does not know its bus: in TypeScript, annotate it with `StarterOf<Events>`, or `StarterOf<Events, Result>` when you need its value.
|
|
378
378
|
|
|
379
|
+
**Limit how many run at once.** `all` and `allSettled` start every starter together. Over a long list that is a burst of requests. Pass `{ concurrency }` as the third argument and at most that many run at a time; the next one starts when a running one settles:
|
|
380
|
+
|
|
381
|
+
```js
|
|
382
|
+
import { createBus } from "nanoeffects";
|
|
383
|
+
import { all, retry } from "nanoeffects/effects";
|
|
384
|
+
|
|
385
|
+
const bus = createBus();
|
|
386
|
+
|
|
387
|
+
bus.on("sync", async (ids, ctx) => {
|
|
388
|
+
// all with concurrency — 5 loads at a time, results in the order of ids
|
|
389
|
+
const users = await all(
|
|
390
|
+
ctx,
|
|
391
|
+
ids.map((id) => retry(() => loadUser(id), { times: 2 })),
|
|
392
|
+
{ concurrency: 5 },
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
render(users);
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
The result has the same order and shape as without the option. If one starter of `all` fails, the running ones are cancelled and the waiting ones are never called. `allSettled` goes on after a failure. When `ctx` aborts, both stop and start nothing more. A value that is not a positive integer (`0`, `-1`, `NaN`, `1.5`) throws a `RangeError` before anything starts; `Infinity` means no limit. `race` has no `concurrency`: it ends at the first result, so a starter that waited for a free slot would never run. The form without `ctx` takes no options, because a second argument would look like the form with `ctx`, so a group starter inside another group takes none; write `(child) => all(child, effects, { concurrency: 5 })` there.
|
|
400
|
+
|
|
401
|
+
|
|
379
402
|
**A starter gets the context of its own child task.** Pass `child` as the first argument to any effect, as a handler passes `ctx`: when the race ends, `child` is aborted and stops exactly this effect. The outer `ctx` is only for `race` itself. Your own API takes the signal in its options: `({ signal }) => fetchUser(id, { signal })`. The same holds for `all`, `allSettled` and `timeout`.
|
|
380
403
|
|
|
381
404
|
If `ctx` is `{}` or a bare `{ signal }` (outside a task), `child` has only `signal` and `abort`, so it fits `delay` and `poll` but not `take`, which needs a bus.
|
package/docs/oop.md
CHANGED
|
@@ -261,6 +261,8 @@ export const Cache = extendBus(bus, CacheBase);
|
|
|
261
261
|
|
|
262
262
|
## Subscribe a method with `@On` and `@Once`
|
|
263
263
|
|
|
264
|
+
`On` here is a decorator. The main entry also exports a type named `On`, the type of `bus.on`; they are different things in different imports, and a file that needs both can rename one: `import { On as OnDecorator } from "nanoeffects/oop"`.
|
|
265
|
+
|
|
264
266
|
A decorator turns a method into a handler of an event for each instance, with `this` bound. You write no `this.on` in the constructor, and `dispose()` ends the subscription too.
|
|
265
267
|
|
|
266
268
|
The bus and the events are the same as above, in TypeScript:
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Know what is stable
|
|
2
|
+
|
|
3
|
+
Use this page to decide what you can rely on. It says which imports are stable, what counts as a breaking change, which versions are supported, and which call forms stay.
|
|
4
|
+
|
|
5
|
+
## See which entries are stable
|
|
6
|
+
|
|
7
|
+
A stable entry follows the rules below. An unstable entry can change in any minor release; every change is written in the [CHANGELOG](../CHANGELOG.md), and nothing promises a deprecation period first.
|
|
8
|
+
|
|
9
|
+
| Import | Status | Note |
|
|
10
|
+
| ------ | ------ | ---- |
|
|
11
|
+
| `nanoeffects` | Stable | `createBus` and the types of a bus |
|
|
12
|
+
| `nanoeffects/effects` | Stable | `retry`, `timeout`, `poll`, `take`, `delay`, `all`, `allSettled`, `race`, `backoff`, `cancellable`, `effectsPlugin` |
|
|
13
|
+
| `nanoeffects/policies` | Stable | `latest`, `leading`, `debounce`, `throttle`, `queue`, `withPolicy` |
|
|
14
|
+
| `nanoeffects/actions` | Stable | `createAction`, `createCommand`, `createJob`, `createModule` and their plugins |
|
|
15
|
+
| `nanoeffects/trace` | Stable: the contract | `Tracer`, `Trace`, `TraceEvent`, `TraceLogger`, `Phase`, `EffectName` and `tracePlugin` |
|
|
16
|
+
| `nanoeffects/trace` | Unstable: the tools | `createTracer`, `consoleLogger`, `performanceLogger`, `createTraceRecorder`, `reduxDevtools` and their option types |
|
|
17
|
+
| `nanoeffects/scope` | Unstable | `scopePlugin`, `effect` |
|
|
18
|
+
| `nanoeffects/match` | Unstable | `matchPlugin` |
|
|
19
|
+
| `nanoeffects/signal` | Unstable | `signalPlugin` |
|
|
20
|
+
| `nanoeffects/context` | Unstable | `contextPlugin` |
|
|
21
|
+
| `nanoeffects/oop` | Unstable | `Emitter`, `extendBus`, `On`, `Once`, `WithBus`, `disposeBus` |
|
|
22
|
+
| `nanoeffects/observable` | Unstable | `createObserve`, `Subject` |
|
|
23
|
+
| `nanoeffects/redux` | Unstable | `createEffectsMiddleware` |
|
|
24
|
+
| `nanoeffects/react` | Unstable | `reactPlugin`, `usePolicy` |
|
|
25
|
+
| `nanoeffects/svelte` | Unstable | `sveltePlugin` |
|
|
26
|
+
| `nanoeffects/vue` | Unstable | `vuePlugin` |
|
|
27
|
+
| `nanoeffects/dev` | Unstable | `devPlugin` |
|
|
28
|
+
|
|
29
|
+
The adapters (`react`, `vue`, `svelte`, `redux`) are unstable because they follow the APIs of other libraries and have had little use. They can become stable after the library has been in use for a while.
|
|
30
|
+
|
|
31
|
+
## Know what is a breaking change
|
|
32
|
+
|
|
33
|
+
For a stable entry, these changes are breaking:
|
|
34
|
+
|
|
35
|
+
- A change in what a call does at run time.
|
|
36
|
+
- A change in a type that stops code that compiled before from compiling.
|
|
37
|
+
- A removed or renamed export.
|
|
38
|
+
|
|
39
|
+
A stricter type that only finds mistakes in code that was already wrong is not breaking. It ships in a minor release with a note in the CHANGELOG.
|
|
40
|
+
|
|
41
|
+
These are not covered by the promise:
|
|
42
|
+
|
|
43
|
+
- Any unstable entry.
|
|
44
|
+
- The text of the messages of `nanoeffects/dev`.
|
|
45
|
+
- The payload details of trace events. The shape of an event (`id`, `parentId`, `rootId`, `type`, `effect`, `phase`) is covered; the contents of `payload` are not.
|
|
46
|
+
|
|
47
|
+
Before version 1.0.0, a breaking change ships in a minor release under `### Breaking` in the CHANGELOG. From 1.0.0 it ships only in a major release.
|
|
48
|
+
|
|
49
|
+
A deprecated export keeps working and is removed only in a major release. `RaceStarter` is deprecated: use `StarterOf` instead.
|
|
50
|
+
|
|
51
|
+
## Check the supported versions
|
|
52
|
+
|
|
53
|
+
| What | Supported |
|
|
54
|
+
| ---- | --------- |
|
|
55
|
+
| Node.js, the library | 18, 20, 22 and 24 (a smoke test runs the built package on each) |
|
|
56
|
+
| Node.js, the dev tools and the trace in a browser | 22 and newer |
|
|
57
|
+
| TypeScript | The types are written and checked with TypeScript 7. TypeScript 5.9 is used for the Vue tools and for the test of the exports. Older versions are not tested. |
|
|
58
|
+
| React | 18 or newer (`nanoeffects/react`) |
|
|
59
|
+
| Vue | 3.3 or newer (`nanoeffects/vue`) |
|
|
60
|
+
| Svelte | 5 or newer (`nanoeffects/svelte`) |
|
|
61
|
+
|
|
62
|
+
The library has no dependencies. React, Vue and Svelte are optional peer dependencies of their own entries only.
|
|
63
|
+
|
|
64
|
+
## Rely on these call forms
|
|
65
|
+
|
|
66
|
+
`retry`, `timeout` and `poll` have three call forms, and all three stay:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { createBus } from "nanoeffects";
|
|
70
|
+
import { race, retry } from "nanoeffects/effects";
|
|
71
|
+
|
|
72
|
+
const bus = createBus();
|
|
73
|
+
|
|
74
|
+
bus.on("open", async (id, ctx) => {
|
|
75
|
+
// with ctx: you pass the context, the function gets the signal
|
|
76
|
+
const user = await retry(ctx, ({ signal }) => fetchUser(id, { signal }), { times: 3 });
|
|
77
|
+
|
|
78
|
+
// as a starter: a group (race, all, allSettled, timeout) calls it with its child
|
|
79
|
+
const result = await race(ctx, {
|
|
80
|
+
user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// as a Task: a function of (payload, ctx), which bus.on and ctx.run call
|
|
85
|
+
bus.on("reload", retry((id, { signal }) => fetchUser(id, { signal }), { times: 3 }));
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The forms are told apart by the arguments: a context first is the form with `ctx`; a function called with a payload and a context is the Task; the same function called by a group with one argument, its child, is the starter. The rule is part of the contract and does not depend on how many parameters your function declares.
|
|
89
|
+
|
|
90
|
+
`all` and `allSettled` take options only in the form with `ctx`, `all(ctx, effects, { concurrency })`. The form without `ctx` has one argument, so a second one would look like the `ctx` form. `race` takes no `concurrency`: it ends at the first result, so a starter that waited for a free slot would never run. See [Effects](effects.md#run-several-starters-together).
|
package/llms-full.txt
CHANGED
|
@@ -721,6 +721,100 @@ The package ships plain-text files for assistants that write code with it:
|
|
|
721
721
|
|
|
722
722
|
Find them in `node_modules/nanoeffects/`, or load `llms-full.txt` from a CDN such as `https://unpkg.com/nanoeffects/llms-full.txt`. All match the installed version.
|
|
723
723
|
|
|
724
|
+
---
|
|
725
|
+
Source: docs/stability.md
|
|
726
|
+
|
|
727
|
+
# Know what is stable
|
|
728
|
+
|
|
729
|
+
Use this page to decide what you can rely on. It says which imports are stable, what counts as a breaking change, which versions are supported, and which call forms stay.
|
|
730
|
+
|
|
731
|
+
## See which entries are stable
|
|
732
|
+
|
|
733
|
+
A stable entry follows the rules below. An unstable entry can change in any minor release; every change is written in the [CHANGELOG](../CHANGELOG.md), and nothing promises a deprecation period first.
|
|
734
|
+
|
|
735
|
+
| Import | Status | Note |
|
|
736
|
+
| ------ | ------ | ---- |
|
|
737
|
+
| `nanoeffects` | Stable | `createBus` and the types of a bus |
|
|
738
|
+
| `nanoeffects/effects` | Stable | `retry`, `timeout`, `poll`, `take`, `delay`, `all`, `allSettled`, `race`, `backoff`, `cancellable`, `effectsPlugin` |
|
|
739
|
+
| `nanoeffects/policies` | Stable | `latest`, `leading`, `debounce`, `throttle`, `queue`, `withPolicy` |
|
|
740
|
+
| `nanoeffects/actions` | Stable | `createAction`, `createCommand`, `createJob`, `createModule` and their plugins |
|
|
741
|
+
| `nanoeffects/trace` | Stable: the contract | `Tracer`, `Trace`, `TraceEvent`, `TraceLogger`, `Phase`, `EffectName` and `tracePlugin` |
|
|
742
|
+
| `nanoeffects/trace` | Unstable: the tools | `createTracer`, `consoleLogger`, `performanceLogger`, `createTraceRecorder`, `reduxDevtools` and their option types |
|
|
743
|
+
| `nanoeffects/scope` | Unstable | `scopePlugin`, `effect` |
|
|
744
|
+
| `nanoeffects/match` | Unstable | `matchPlugin` |
|
|
745
|
+
| `nanoeffects/signal` | Unstable | `signalPlugin` |
|
|
746
|
+
| `nanoeffects/context` | Unstable | `contextPlugin` |
|
|
747
|
+
| `nanoeffects/oop` | Unstable | `Emitter`, `extendBus`, `On`, `Once`, `WithBus`, `disposeBus` |
|
|
748
|
+
| `nanoeffects/observable` | Unstable | `createObserve`, `Subject` |
|
|
749
|
+
| `nanoeffects/redux` | Unstable | `createEffectsMiddleware` |
|
|
750
|
+
| `nanoeffects/react` | Unstable | `reactPlugin`, `usePolicy` |
|
|
751
|
+
| `nanoeffects/svelte` | Unstable | `sveltePlugin` |
|
|
752
|
+
| `nanoeffects/vue` | Unstable | `vuePlugin` |
|
|
753
|
+
| `nanoeffects/dev` | Unstable | `devPlugin` |
|
|
754
|
+
|
|
755
|
+
The adapters (`react`, `vue`, `svelte`, `redux`) are unstable because they follow the APIs of other libraries and have had little use. They can become stable after the library has been in use for a while.
|
|
756
|
+
|
|
757
|
+
## Know what is a breaking change
|
|
758
|
+
|
|
759
|
+
For a stable entry, these changes are breaking:
|
|
760
|
+
|
|
761
|
+
- A change in what a call does at run time.
|
|
762
|
+
- A change in a type that stops code that compiled before from compiling.
|
|
763
|
+
- A removed or renamed export.
|
|
764
|
+
|
|
765
|
+
A stricter type that only finds mistakes in code that was already wrong is not breaking. It ships in a minor release with a note in the CHANGELOG.
|
|
766
|
+
|
|
767
|
+
These are not covered by the promise:
|
|
768
|
+
|
|
769
|
+
- Any unstable entry.
|
|
770
|
+
- The text of the messages of `nanoeffects/dev`.
|
|
771
|
+
- The payload details of trace events. The shape of an event (`id`, `parentId`, `rootId`, `type`, `effect`, `phase`) is covered; the contents of `payload` are not.
|
|
772
|
+
|
|
773
|
+
Before version 1.0.0, a breaking change ships in a minor release under `### Breaking` in the CHANGELOG. From 1.0.0 it ships only in a major release.
|
|
774
|
+
|
|
775
|
+
A deprecated export keeps working and is removed only in a major release. `RaceStarter` is deprecated: use `StarterOf` instead.
|
|
776
|
+
|
|
777
|
+
## Check the supported versions
|
|
778
|
+
|
|
779
|
+
| What | Supported |
|
|
780
|
+
| ---- | --------- |
|
|
781
|
+
| Node.js, the library | 18, 20, 22 and 24 (a smoke test runs the built package on each) |
|
|
782
|
+
| Node.js, the dev tools and the trace in a browser | 22 and newer |
|
|
783
|
+
| TypeScript | The types are written and checked with TypeScript 7. TypeScript 5.9 is used for the Vue tools and for the test of the exports. Older versions are not tested. |
|
|
784
|
+
| React | 18 or newer (`nanoeffects/react`) |
|
|
785
|
+
| Vue | 3.3 or newer (`nanoeffects/vue`) |
|
|
786
|
+
| Svelte | 5 or newer (`nanoeffects/svelte`) |
|
|
787
|
+
|
|
788
|
+
The library has no dependencies. React, Vue and Svelte are optional peer dependencies of their own entries only.
|
|
789
|
+
|
|
790
|
+
## Rely on these call forms
|
|
791
|
+
|
|
792
|
+
`retry`, `timeout` and `poll` have three call forms, and all three stay:
|
|
793
|
+
|
|
794
|
+
```js
|
|
795
|
+
import { createBus } from "nanoeffects";
|
|
796
|
+
import { race, retry } from "nanoeffects/effects";
|
|
797
|
+
|
|
798
|
+
const bus = createBus();
|
|
799
|
+
|
|
800
|
+
bus.on("open", async (id, ctx) => {
|
|
801
|
+
// with ctx: you pass the context, the function gets the signal
|
|
802
|
+
const user = await retry(ctx, ({ signal }) => fetchUser(id, { signal }), { times: 3 });
|
|
803
|
+
|
|
804
|
+
// as a starter: a group (race, all, allSettled, timeout) calls it with its child
|
|
805
|
+
const result = await race(ctx, {
|
|
806
|
+
user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
|
|
807
|
+
});
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
// as a Task: a function of (payload, ctx), which bus.on and ctx.run call
|
|
811
|
+
bus.on("reload", retry((id, { signal }) => fetchUser(id, { signal }), { times: 3 }));
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
The forms are told apart by the arguments: a context first is the form with `ctx`; a function called with a payload and a context is the Task; the same function called by a group with one argument, its child, is the starter. The rule is part of the contract and does not depend on how many parameters your function declares.
|
|
815
|
+
|
|
816
|
+
`all` and `allSettled` take options only in the form with `ctx`, `all(ctx, effects, { concurrency })`. The form without `ctx` has one argument, so a second one would look like the `ctx` form. `race` takes no `concurrency`: it ends at the first result, so a starter that waited for a free slot would never run. See [Effects](effects.md#run-several-starters-together).
|
|
817
|
+
|
|
724
818
|
---
|
|
725
819
|
Source: docs/plugins.md
|
|
726
820
|
|
|
@@ -1943,7 +2037,7 @@ bus.on("open", async (id, ctx) => {
|
|
|
1943
2037
|
});
|
|
1944
2038
|
```
|
|
1945
2039
|
|
|
1946
|
-
The same call with a payload and a context, `(payload, ctx)`, is the Task that `bus.on` and `ctx.run` use, and it does not change.
|
|
2040
|
+
The same call with a payload and a context, `(payload, ctx)`, is the Task that `bus.on` and `ctx.run` use, and it does not change. `retry`, `timeout` and `poll` therefore have three call forms: with `ctx`, as a Task, and as a starter. All three stay; [Stability](stability.md#rely-on-these-call-forms) says how they are told apart.
|
|
1947
2041
|
|
|
1948
2042
|
**`all`, `allSettled` and `race` without `ctx` are starters too**, so a group nests in another group with no wrapper. Load two things, but give up after five seconds:
|
|
1949
2043
|
|
|
@@ -1972,6 +2066,29 @@ bus.on("open", async (id, ctx) => {
|
|
|
1972
2066
|
|
|
1973
2067
|
One argument is the short form and two arguments are the form with `ctx`: `all(effects)` returns a starter, `all(ctx, effects)` runs the group. The inner group stops with the outer one and cancels its own starters. Passing only a context, `all(ctx)`, is a mistake and throws a `TypeError` at once. A group starter written in a group needs no type. One kept in a variable outside a group does not know its bus: in TypeScript, annotate it with `StarterOf<Events>`, or `StarterOf<Events, Result>` when you need its value.
|
|
1974
2068
|
|
|
2069
|
+
**Limit how many run at once.** `all` and `allSettled` start every starter together. Over a long list that is a burst of requests. Pass `{ concurrency }` as the third argument and at most that many run at a time; the next one starts when a running one settles:
|
|
2070
|
+
|
|
2071
|
+
```js
|
|
2072
|
+
import { createBus } from "nanoeffects";
|
|
2073
|
+
import { all, retry } from "nanoeffects/effects";
|
|
2074
|
+
|
|
2075
|
+
const bus = createBus();
|
|
2076
|
+
|
|
2077
|
+
bus.on("sync", async (ids, ctx) => {
|
|
2078
|
+
// all with concurrency — 5 loads at a time, results in the order of ids
|
|
2079
|
+
const users = await all(
|
|
2080
|
+
ctx,
|
|
2081
|
+
ids.map((id) => retry(() => loadUser(id), { times: 2 })),
|
|
2082
|
+
{ concurrency: 5 },
|
|
2083
|
+
);
|
|
2084
|
+
|
|
2085
|
+
render(users);
|
|
2086
|
+
});
|
|
2087
|
+
```
|
|
2088
|
+
|
|
2089
|
+
The result has the same order and shape as without the option. If one starter of `all` fails, the running ones are cancelled and the waiting ones are never called. `allSettled` goes on after a failure. When `ctx` aborts, both stop and start nothing more. A value that is not a positive integer (`0`, `-1`, `NaN`, `1.5`) throws a `RangeError` before anything starts; `Infinity` means no limit. `race` has no `concurrency`: it ends at the first result, so a starter that waited for a free slot would never run. The form without `ctx` takes no options, because a second argument would look like the form with `ctx`, so a group starter inside another group takes none; write `(child) => all(child, effects, { concurrency: 5 })` there.
|
|
2090
|
+
|
|
2091
|
+
|
|
1975
2092
|
**A starter gets the context of its own child task.** Pass `child` as the first argument to any effect, as a handler passes `ctx`: when the race ends, `child` is aborted and stops exactly this effect. The outer `ctx` is only for `race` itself. Your own API takes the signal in its options: `({ signal }) => fetchUser(id, { signal })`. The same holds for `all`, `allSettled` and `timeout`.
|
|
1976
2093
|
|
|
1977
2094
|
If `ctx` is `{}` or a bare `{ signal }` (outside a task), `child` has only `signal` and `abort`, so it fits `delay` and `poll` but not `take`, which needs a bus.
|
|
@@ -4690,6 +4807,8 @@ export const Cache = extendBus(bus, CacheBase);
|
|
|
4690
4807
|
|
|
4691
4808
|
## Subscribe a method with `@On` and `@Once`
|
|
4692
4809
|
|
|
4810
|
+
`On` here is a decorator. The main entry also exports a type named `On`, the type of `bus.on`; they are different things in different imports, and a file that needs both can rename one: `import { On as OnDecorator } from "nanoeffects/oop"`.
|
|
4811
|
+
|
|
4693
4812
|
A decorator turns a method into a handler of an event for each instance, with `this` bound. You write no `this.on` in the constructor, and `dispose()` ends the subscription too.
|
|
4694
4813
|
|
|
4695
4814
|
The bus and the events are the same as above, in TypeScript:
|
package/llms.txt
CHANGED
|
@@ -18,6 +18,7 @@ Rules that generated code often gets wrong:
|
|
|
18
18
|
- [Start a project from a template](docs/starter.md): `npm create nanoeffects` makes a Vite project (`vanilla`, `react`, `vue-ts`, `svelte-ts` and others, in JavaScript or TypeScript) with a bus, `debounce` and `latest`
|
|
19
19
|
- [Why nanoeffects exists](docs/motivation.md): no dependencies and no global state for SDKs and Module Federation, and why not Redux, Effector or RxJS
|
|
20
20
|
- [Package entries](docs/package.md): which import holds what
|
|
21
|
+
- [Stability](docs/stability.md): which entries are stable or unstable, what a breaking change is, the supported Node, TypeScript and framework versions, the call forms that stay
|
|
21
22
|
- [Plugins](docs/plugins.md): every plugin of a bus, what `bus.use` returns, and the order to use them in
|
|
22
23
|
|
|
23
24
|
## Async UI and unreliable networks
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nanoeffects",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Cancel stale async work and fix race conditions in event handlers: a typed event bus where every handler is a task with an AbortSignal, plus latest, debounce, throttle, queue, retry, timeout and poll. About 1.4 kB gzip.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"event-bus",
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
{
|
|
221
221
|
"name": "effects (all)",
|
|
222
222
|
"path": "dist/effects.js",
|
|
223
|
-
"limit": "
|
|
223
|
+
"limit": "3 kB"
|
|
224
224
|
},
|
|
225
225
|
{
|
|
226
226
|
"name": "actions (all)",
|