nanoeffects 0.23.1 → 0.25.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 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-CBoV9m7W.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-D1VVKbE0.js";
2
+ import { r as Scoped, t as FieldsOfScope } from "./types-DWjyeii7.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-B5V47MZ0.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>;
@@ -0,0 +1 @@
1
+ import{u as e}from"./context-UcmrAIhP.js";const t=e=>typeof e==`object`&&!!e,n=2**31-1,r=(e,t)=>{let r={id:null};if(t===1/0)return r;let i=t=>{r.id=setTimeout(()=>{t>n?i(t-n):(r.id=null,e())},Math.min(t,n))};return i(t>0?t:0),r},i=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},a=(t,n)=>new Promise((a,o)=>{let s=r(()=>{c(),a()},typeof n==`function`?n():n),c=e(t,e=>{i(s),o(e)})});function o(e,n){return t(e)?a(e,n):t=>a(t,e)}export{t as i,i as n,r,o as t};
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-D1VVKbE0.js";
2
+ import { i as WithApp, n as ModuleApi } from "./module-B5V47MZ0.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
- import { P as WithSignal, W as Task, u as Effect, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
- import { a as RaceStarter, c as all, d as Starter, f as delay, i as take, l as ChildOf, n as effectsPlugin, o as race, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-BZK83Z3N.js";
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 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-B6UQyoVd.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
@@ -68,6 +68,18 @@ type CancellableExecutor<T> = (handle: CancellableHandle<T>) => void;
68
68
  */
69
69
  export declare const cancellable: <T = void>(ctx: WithSignal, executor: CancellableExecutor<T>) => Promise<T>;
70
70
  //#endregion
71
+ //#region src/effects/starter-call.d.ts
72
+ /**
73
+ * What the Task of `retry`, `timeout` and `poll` is: a Task for every payload, and a starter of
74
+ * `race`, `all` and `allSettled` when its function accepts `undefined` as the payload (a group has
75
+ * none). The Task signature is last: TypeScript infers a handler from the last one.
76
+ */
77
+ type Startable<P, E extends EventMap, R> = StarterPayload<P, E> extends true ? {
78
+ (child: Context<E>): R;
79
+ (payload: P, ctx: Context<E>): R;
80
+ } : Task<P, E, R>;
81
+ type StarterPayload<P, E extends EventMap> = undefined extends P ? true : Context<E> extends P ? true : false;
82
+ //#endregion
71
83
  //#region src/effects/poll.d.ts
72
84
  type PollOptions = {
73
85
  /** Also call `fn` at once, not only after the first `ms`. Default `false`. */
@@ -105,7 +117,7 @@ type PollOptions = {
105
117
  * ```
106
118
  */
107
119
  type PollMs = number | ((call: number) => number);
108
- export declare function poll<P, E extends EventMap, R>(ms: PollMs, task: Task<P, E, R>, options?: PollOptions): Task<P, E, Promise<void>>;
120
+ export declare function poll<P, E extends EventMap, R>(ms: PollMs, task: Task<P, E, R>, options?: PollOptions): Startable<P, E, Promise<void>>;
109
121
  export declare function poll(ctx: WithSignal, fn: (tick: number) => unknown, ms: PollMs, options?: PollOptions): Promise<void>;
110
122
  //#endregion
111
123
  //#region src/effects/retry.d.ts
@@ -143,7 +155,7 @@ type RetryOptions = {
143
155
  * ```
144
156
  */
145
157
  type RetryFn<T> = (attempt: number) => T | PromiseLike<T>;
146
- export declare function retry<P, E extends EventMap, R>(task: Task<P, E, R>, options?: RetryOptions): Task<P, E, Promise<Awaited<R>>>;
158
+ export declare function retry<P, E extends EventMap, R>(task: Task<P, E, R>, options?: RetryOptions): Startable<P, E, Promise<Awaited<R>>>;
147
159
  export declare function retry<T>(ctx: {
148
160
  signal?: AbortSignal;
149
161
  }, fn: RetryFn<T>, options?: RetryOptions): Promise<T>;
@@ -170,9 +182,9 @@ export declare function retry<T>(ctx: {
170
182
  * });
171
183
  * ```
172
184
  */
173
- export declare function timeout<P, E extends EventMap, R>(ms: number, task: Task<P, E, R>): Task<P, E, Promise<Awaited<R>>>;
185
+ export declare function timeout<P, E extends EventMap, R>(ms: number, task: Task<P, E, R>): Startable<P, E, Promise<Awaited<R>>>;
174
186
  export declare function timeout<C extends {
175
187
  signal?: AbortSignal;
176
188
  }, T>(ctx: C, ms: number, starter: Starter<T, ChildOf<C>>): Promise<T>;
177
189
  //#endregion
178
- export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type PollOptions, type RaceStarter, type RetryOptions, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
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{d as e,i as t,o as n,s as r,t as i,u as a}from"./context-UcmrAIhP.js";import{n as o,r as s,t as c}from"./delay-mxZkTg17.js";const l=(e,t)=>t?.signal?new Promise((n,r)=>{let i=a(t,r);e.then(n,r).finally(i)}):e,u=async(e,n,o,s)=>{n?.signal?.throwIfAborted();let{ctx:c,unlink:u}=t(n??{}),d=i(c,e);r(c,e,`start`),a(c,()=>d(`cancel`));try{let e=await l(o(c),n);return d(`done`),s?.(!1),e}catch(e){throw d(`error`,e),s?.(!0),e}finally{u()}},d=async(e,r)=>{let{ctx:i,unlink:a}=t(e);try{return await n(i,`run`,()=>r(i))}finally{a()}},f=e=>e,p=(e,t)=>n=>e(t,f(n)),m=e=>Array.isArray(e)?Array(e.length):{},h=(e,r)=>{let i=Object.entries(r).map(([r,i])=>{let a=t(e),o=()=>i(a.ctx);return{key:r,task:new Promise(e=>e(n(a.ctx,`run`,o))).finally(a.unlink),cancel:a.ctx.abort}});return{tasks:i.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of i)e.cancel()}}},g=(e,t,n,r,i)=>{let a=()=>{};return u(e,t,async e=>{let t=h(e,n);return a=t.cancelAll,r(t.tasks)},e=>{(e||i===`end`)&&a()})};function _(e,t){return g(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const v=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function y(e,t){return g(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>v(e))),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const b=e=>e>0?e:0,x=(e={})=>{let t=b(e.base??100),n=e.factor??2,r=b(e.max??1/0),i=e.jitter??!1;return e=>{let a=b(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},S=(t,n)=>t.signal.aborted?Promise.reject(t.signal.reason):new Promise((r,i)=>{let o=[],s=`pending`,c=t=>{try{t()}catch(t){e(`cancel cleanup failed`,t)}},l=a(t,e=>{s=`cancelled`;for(let e of o.reverse())c(e);i(e)}),u=e=>(...t)=>{s===`pending`&&(s=`settled`,l(),o.length=0,e(...t))},d=e=>{s===`pending`?o.push(e):s===`cancelled`&&c(e)};try{n({resolve:u(r),reject:u(i),onCancel:d})}catch(e){u(i)(e)}}),C=Symbol(`nanoeffects.effects.effect`),w=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[C]===n){let r=(...t)=>n(e,...t);r[C]=n,Reflect.set(e,t,r)}}},t},T=(e,t,n,r)=>{if(e.signal.aborted)return Promise.resolve();let i=r.leading??!1,c=r.waitForFn??!1;return u(`poll`,e,e=>new Promise((r,l)=>{let u=0,f=null,p=()=>{f!==null&&(o(f),f=null)},m=e=>{try{f=s(h,typeof n==`function`?n(e):n)}catch(e){p(),l(e)}},h=()=>{f=null,c||m(u+1),g()},g=()=>{let n=u++;d(e,e=>t(e,n)).then(()=>{c&&!e.signal.aborted&&m(u)},e=>{p(),l(e)})};a(e,p),i?(g(),c||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function E(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{};return(t,n)=>T(n,p(r,t),e,i)}let i=t;return T(e,(e,t)=>i(t),n,r)}function D(e,t){let n=m(t);return Object.keys(t).length===0?Promise.resolve(n):g(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)}const O=(e,t,n)=>typeof e==`function`?e(t,n):e,k=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),A=(e,t,n)=>u(`retry`,e,async e=>{let{times:r,delay:i,shouldRetry:a}=k(n);for(let n=1;;n++)try{return await d(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<r)||!a(t,n))throw t;let o=O(i,n,t);o>0&&await c(e,o)}});function j(e,t,n={}){if(typeof e==`function`){let n=e;return(e,r)=>A(r,p(n,e),t??{})}let r=t;return A(e,(e,t)=>r(t),n)}function M(e,t,n={}){return u(`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))}))}const N=(e,r,i)=>u(`timeout`,e,async e=>{let a=t(e),c=s(()=>a.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await l(Promise.resolve(n(a.ctx,`run`,()=>i(a.ctx))),a.ctx)}finally{o(c),a.unlink()}});function P(e,t,n){if(typeof e==`number`){let n=t;return(t,r)=>N(r,e,p(n,t))}return N(e,t,n)}export{_ as all,y as allSettled,x as backoff,S as cancellable,c as delay,w as effectsPlugin,a as onAbort,E as poll,D as race,j as retry,M as take,P as timeout};
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-CBoV9m7W.js";
2
+ import { n as ScopeSlots, r as Scoped, t as FieldsOfScope } from "./types-DWjyeii7.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-BEvYzo8Q.js";
2
+ import { t as BoundOf } from "./plugin-ks-oNq5n.js";
3
3
  import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
4
4
  //#region src/scope/types.d.ts
5
5
  /**
@@ -0,0 +1 @@
1
+ import{c as e}from"./context-_HWcdjZf.js";const t=e=>typeof e==`object`&&!!e,n=2**31-1,r=(e,t)=>{let r={id:null};if(t===1/0)return r;let i=t=>{r.id=setTimeout(()=>{t>n?i(t-n):(r.id=null,e())},Math.min(t,n))};return i(t>0?t:0),r},i=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},a=(t,n)=>new Promise((a,o)=>{let s=r(()=>{c(),a()},typeof n==`function`?n():n),c=e(t,e=>{i(s),o(e)})});function o(e,n){return t(e)?a(e,n):t=>a(t,e)}export{t as i,i as n,r,o as t};
@@ -1,5 +1,5 @@
1
- import { F as EventMap, M as WithSignal, R as Task, l as Effect } from "./action-creator-D2CotugT.js";
2
- import { a as RaceStarter, c as all, d as Starter, f as delay, i as take, l as ChildOf, n as effectsPlugin, o as race, r as TakeOptions, s as allSettled, u as EffectContext } from "./plugin-BEvYzo8Q.js";
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 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-ks-oNq5n.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
@@ -68,6 +68,18 @@ type CancellableExecutor<T> = (handle: CancellableHandle<T>) => void;
68
68
  */
69
69
  export declare const cancellable: <T = void>(ctx: WithSignal, executor: CancellableExecutor<T>) => Promise<T>;
70
70
  //#endregion
71
+ //#region src/effects/starter-call.d.ts
72
+ /**
73
+ * What the Task of `retry`, `timeout` and `poll` is: a Task for every payload, and a starter of
74
+ * `race`, `all` and `allSettled` when its function accepts `undefined` as the payload (a group has
75
+ * none). The Task signature is last: TypeScript infers a handler from the last one.
76
+ */
77
+ type Startable<P, E extends EventMap, R> = StarterPayload<P, E> extends true ? {
78
+ (child: Context<E>): R;
79
+ (payload: P, ctx: Context<E>): R;
80
+ } : Task<P, E, R>;
81
+ type StarterPayload<P, E extends EventMap> = undefined extends P ? true : Context<E> extends P ? true : false;
82
+ //#endregion
71
83
  //#region src/effects/poll.d.ts
72
84
  type PollOptions = {
73
85
  /** Also call `fn` at once, not only after the first `ms`. Default `false`. */
@@ -105,7 +117,7 @@ type PollOptions = {
105
117
  * ```
106
118
  */
107
119
  type PollMs = number | ((call: number) => number);
108
- export declare function poll<P, E extends EventMap, R>(ms: PollMs, task: Task<P, E, R>, options?: PollOptions): Task<P, E, Promise<void>>;
120
+ export declare function poll<P, E extends EventMap, R>(ms: PollMs, task: Task<P, E, R>, options?: PollOptions): Startable<P, E, Promise<void>>;
109
121
  export declare function poll(ctx: WithSignal, fn: (tick: number) => unknown, ms: PollMs, options?: PollOptions): Promise<void>;
110
122
  //#endregion
111
123
  //#region src/effects/retry.d.ts
@@ -143,7 +155,7 @@ type RetryOptions = {
143
155
  * ```
144
156
  */
145
157
  type RetryFn<T> = (attempt: number) => T | PromiseLike<T>;
146
- export declare function retry<P, E extends EventMap, R>(task: Task<P, E, R>, options?: RetryOptions): Task<P, E, Promise<Awaited<R>>>;
158
+ export declare function retry<P, E extends EventMap, R>(task: Task<P, E, R>, options?: RetryOptions): Startable<P, E, Promise<Awaited<R>>>;
147
159
  export declare function retry<T>(ctx: {
148
160
  signal?: AbortSignal;
149
161
  }, fn: RetryFn<T>, options?: RetryOptions): Promise<T>;
@@ -170,9 +182,9 @@ export declare function retry<T>(ctx: {
170
182
  * });
171
183
  * ```
172
184
  */
173
- export declare function timeout<P, E extends EventMap, R>(ms: number, task: Task<P, E, R>): Task<P, E, Promise<Awaited<R>>>;
185
+ export declare function timeout<P, E extends EventMap, R>(ms: number, task: Task<P, E, R>): Startable<P, E, Promise<Awaited<R>>>;
174
186
  export declare function timeout<C extends {
175
187
  signal?: AbortSignal;
176
188
  }, T>(ctx: C, ms: number, starter: Starter<T, ChildOf<C>>): Promise<T>;
177
189
  //#endregion
178
- export { type BackoffOptions, type CancellableExecutor, type CancellableHandle, type Effect, type EffectContext, type PollOptions, type RaceStarter, type RetryOptions, type TakeOptions, all, allSettled, delay, effectsPlugin, race, take };
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 };
@@ -1 +1 @@
1
- import{a as e,c as t,i as n,l as r,o as i,t as a}from"./context-_HWcdjZf.js";import{n as o,r as s,t as c}from"./delay-CqKplsaY.js";const l=(e,n)=>n?.signal?new Promise((r,i)=>{let a=t(n,i);e.then(r,i).finally(a)}):e,u=async(e,r,o,s)=>{r?.signal?.throwIfAborted();let{ctx:c,unlink:u}=n(r??{}),d=a(c,e);i(c,e,`start`),t(c,()=>d(`cancel`));try{let e=await l(o(c),r);return d(`done`),s?.(!1),e}catch(e){throw d(`error`,e),s?.(!0),e}finally{u()}},d=async(t,r)=>{let{ctx:i,unlink:a}=n(t);try{return await e(i,`run`,()=>r(i))}finally{a()}},f=e=>e,p=(e,t)=>n=>e(t,f(n)),m=e=>Array.isArray(e)?Array(e.length):{},h=(t,r)=>{let i=Object.entries(r).map(([r,i])=>{let a=n(t),o=()=>i(a.ctx);return{key:r,task:new Promise(t=>t(e(a.ctx,`run`,o))).finally(a.unlink),cancel:a.ctx.abort}});return{tasks:i.map(({key:e,task:t})=>[e,t]),cancelAll:()=>{for(let e of i)e.cancel()}}},g=(e,t,n,r,i)=>{let a=()=>{};return u(e,t,async e=>{let t=h(e,n);return a=t.cancelAll,r(t.tasks)},e=>{(e||i===`end`)&&a()})};function _(e,t){return g(`all`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>e)),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const v=e=>e.then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}));function y(e,t){return g(`allSettled`,e,t,async e=>{let n=await Promise.all(e.map(([,e])=>v(e))),r=m(t);for(let[t,[i]]of e.entries())r[i]=n[t];return r},`failure`)}const b=e=>e>0?e:0,x=(e={})=>{let t=b(e.base??100),n=e.factor??2,r=b(e.max??1/0),i=e.jitter??!1;return e=>{let a=b(Math.min(r,t*n**(e-1)));return i?Math.random()*a||0:a}},S=(e,n)=>e.signal.aborted?Promise.reject(e.signal.reason):new Promise((i,a)=>{let o=[],s=`pending`,c=e=>{try{e()}catch(e){r(`cancel cleanup failed`,e)}},l=t(e,e=>{s=`cancelled`;for(let e of o.reverse())c(e);a(e)}),u=e=>(...t)=>{s===`pending`&&(s=`settled`,l(),o.length=0,e(...t))},d=e=>{s===`pending`?o.push(e):s===`cancelled`&&c(e)};try{n({resolve:u(i),reject:u(a),onCancel:d})}catch(e){u(a)(e)}}),C=Symbol(`nanoeffects.effects.effect`),w=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[C]===n){let r=(...t)=>n(e,...t);r[C]=n,Reflect.set(e,t,r)}}},t},T=(e,n,r,i)=>{if(e.signal.aborted)return Promise.resolve();let a=i.leading??!1,c=i.waitForFn??!1;return u(`poll`,e,e=>new Promise((i,l)=>{let u=0,f=null,p=()=>{f!==null&&(o(f),f=null)},m=e=>{try{f=s(h,typeof r==`function`?r(e):r)}catch(e){p(),l(e)}},h=()=>{f=null,c||m(u+1),g()},g=()=>{let t=u++;d(e,e=>n(e,t)).then(()=>{c&&!e.signal.aborted&&m(u)},e=>{p(),l(e)})};t(e,p),a?(g(),c||m(u)):m(0)})).catch(t=>{if(!e.signal.aborted)throw t})};function E(e,t,n,r={}){if(typeof e!=`object`){let r=t,i=n??{};return(t,n)=>T(n,p(r,t),e,i)}let i=t;return T(e,(e,t)=>i(t),n,r)}function D(e,t){let n=m(t);return Object.keys(t).length===0?Promise.resolve(n):g(`race`,e,t,async e=>{let[t,r]=await Promise.race(e.map(([e,t])=>t.then(t=>[e,t])));return n[t]=r,n},`end`)}const O=(e,t,n)=>typeof e==`function`?e(t,n):e,k=e=>({times:e.times??3,delay:e.delay??0,shouldRetry:e.shouldRetry??(()=>!0)}),A=(e,t,n)=>u(`retry`,e,async e=>{let{times:r,delay:i,shouldRetry:a}=k(n);for(let n=1;;n++)try{return await d(e,e=>t(e,n))}catch(t){if(e.signal.throwIfAborted(),!(n<r)||!a(t,n))throw t;let o=O(i,n,t);o>0&&await c(e,o)}});function j(e,t,n={}){if(typeof e==`function`){let n=e;return(e,r)=>A(r,p(n,e),t??{})}let r=t;return A(e,(e,t)=>r(t),n)}function M(e,n,r={}){return u(`take`,e,i=>new Promise((a,o)=>{let{predicate:s}=r,c=[],l=()=>{for(let e of c)e()},u=e=>{l(),o(e)},d=n;c.push(e.on(d,e=>{(!s||s(e))&&(l(),a(e))})),c.push(t(i,u)),c.push(t({signal:r.signal},u))}))}const N=(t,r,i)=>u(`timeout`,t,async t=>{let a=n(t),c=s(()=>a.ctx.abort(new DOMException(`Timed out after ${r}ms`,`TimeoutError`)),r);try{return await l(Promise.resolve(e(a.ctx,`run`,()=>i(a.ctx))),a.ctx)}finally{o(c),a.unlink()}});function P(e,t,n){if(typeof e==`number`){let n=t;return(t,r)=>N(r,e,p(n,t))}return N(e,t,n)}export{_ as all,y as allSettled,x as backoff,S as cancellable,c as delay,w as effectsPlugin,t as onAbort,E as poll,D as race,j as retry,M as take,P as timeout};
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};
@@ -7,11 +7,17 @@ import { F as EventMap, I as Keys, c as BoundForm, j as WithContext, p as Bus, r
7
7
  type NoClash<Fields extends object, E extends EventMap> = [keyof Fields & keyof ContextOf<E>] extends [never] ? unknown : never;
8
8
  //#endregion
9
9
  //#region src/utils/delay.d.ts
10
+ type Milliseconds = number | (() => number);
10
11
  /**
11
12
  * Resolves after `ms`, or rejects early if `ctx.signal` aborts. `ms` can be a
12
13
  * function that returns the number of ms, called once when the delay starts:
13
14
  * handy for a random pause (jitter).
14
15
  *
16
+ * Without `ctx`, `delay(ms)` returns a starter for `race`, `all` and
17
+ * `allSettled`: they call it with the context of its own child task, and it
18
+ * waits then. It starts no timer before that, and one starter can be used in
19
+ * several groups. Do not `await` it on its own: it is a function, not a promise.
20
+ *
15
21
  * @example
16
22
  * ```ts
17
23
  * await delay({}, 500);
@@ -24,11 +30,20 @@ type NoClash<Fields extends object, E extends EventMap> = [keyof Fields & keyof
24
30
  * await delay(ctx, 1000);
25
31
  * await load();
26
32
  * });
33
+ *
34
+ * // as a starter: the loser of the race is cancelled
35
+ * const result = await race(ctx, {
36
+ * waited: delay(1000),
37
+ * cancelled: take(cancel),
38
+ * });
27
39
  * ```
28
40
  */
29
- declare const delay: (ctx: {
41
+ declare function delay(ms: Milliseconds): (child: {
42
+ signal?: AbortSignal | undefined;
43
+ }) => Promise<void>;
44
+ declare function delay(ctx: {
30
45
  signal?: AbortSignal | undefined;
31
- }, ms: number | (() => number)) => Promise<void>;
46
+ }, ms: Milliseconds): Promise<void>;
32
47
  //#endregion
33
48
  //#region src/effects/run.d.ts
34
49
  /** What a starter gets when the effect was called with `{}` or a bare `{ signal }`. */
@@ -43,6 +58,25 @@ type EffectContext = {
43
58
  */
44
59
  type ChildOf<C> = C extends Context<infer E> ? Context<E> : EffectContext;
45
60
  type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
61
+ /**
62
+ * A starter of a group on a bus with the events `E`, with the result `R`. A starter written in a
63
+ * group needs no type: the group gives it. Use this for one kept in a variable, where nothing
64
+ * tells the checker which bus it is for.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const load: StarterOf<Events> = all({ user: retry(() => loadUser(1)) });
69
+ * const user: StarterOf<Events, User> = retry(() => loadUser(1));
70
+ *
71
+ * bus.on("open", async (_, ctx) => race(ctx, { load, user }));
72
+ * ```
73
+ */
74
+ type StarterOf$1<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
+ };
46
80
  //#endregion
47
81
  //#region src/effects/all.d.ts
48
82
  /**
@@ -62,10 +96,12 @@ type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
62
96
  */
63
97
  declare function all<C extends {
64
98
  signal?: AbortSignal;
65
- }, 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]>>; }>;
66
100
  declare function all<C extends {
67
101
  signal?: AbortSignal;
68
- }, 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]>>; }>;
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]>>; }>;
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]>>; }>;
69
105
  //#endregion
70
106
  //#region src/effects/allSettled.d.ts
71
107
  /**
@@ -88,10 +124,12 @@ declare function all<C extends {
88
124
  */
89
125
  declare function allSettled<C extends {
90
126
  signal?: AbortSignal;
91
- }, 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]>>>; }>;
92
128
  declare function allSettled<C extends {
93
129
  signal?: AbortSignal;
94
- }, 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]>>>; }>;
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]>>>; }>;
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]>>>; }>;
95
133
  //#endregion
96
134
  //#region src/effects/race.d.ts
97
135
  type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
@@ -118,6 +156,8 @@ declare function race<C extends {
118
156
  declare function race<C extends {
119
157
  signal?: AbortSignal;
120
158
  }, const T extends readonly RaceStarter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
159
+ declare function race<Child, T extends Record<string, RaceStarter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
160
+ declare function race<Child, const T extends readonly RaceStarter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
121
161
  //#endregion
122
162
  //#region src/effects/take.d.ts
123
163
  type TakeOptions<P> = {
@@ -169,6 +209,18 @@ declare function take<E extends EventMap, P, T extends P>(ctx: Context<E>, creat
169
209
  predicate: (payload: P) => payload is T;
170
210
  }): Promise<T>;
171
211
  declare function take<E extends EventMap, P>(ctx: Context<E>, creator: ActionCreator<P>, options?: TakeOptions<P>): Promise<P>;
212
+ declare function take<E extends EventMap, K extends Keys<E>, T extends E[K]>(event: K, options: TakeOptions<E[K]> & {
213
+ predicate: (payload: E[K]) => payload is T;
214
+ }): (child: Context<E>) => Promise<T>;
215
+ declare function take<E extends EventMap, K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): (child: Context<E>) => Promise<E[K]>;
216
+ declare function take<E extends EventMap, K extends Keys<E>, T extends E[K]>(creator: FreeActionCreator<K>, options: TakeOptions<E[K]> & {
217
+ predicate: (payload: E[K]) => payload is T;
218
+ }): (child: Context<E>) => Promise<T>;
219
+ declare function take<E extends EventMap, K extends Keys<E>>(creator: FreeActionCreator<K>, options?: TakeOptions<E[K]>): (child: Context<E>) => Promise<E[K]>;
220
+ declare function take<E extends EventMap, P, T extends P>(creator: ActionCreator<P>, options: TakeOptions<P> & {
221
+ predicate: (payload: P) => payload is T;
222
+ }): (child: Context<E>) => Promise<T>;
223
+ declare function take<E extends EventMap, P>(creator: ActionCreator<P>, options?: TakeOptions<P>): (child: Context<E>) => Promise<P>;
172
224
  //#endregion
173
225
  //#region src/effects/plugin.d.ts
174
226
  /** The effects that `effectsPlugin` can put on `ctx`. */
@@ -186,12 +238,12 @@ type Bound<E extends EventMap, Child> = {
186
238
  <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
187
239
  };
188
240
  all: {
189
- <T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
190
- <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
241
+ <T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
242
+ <const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
191
243
  };
192
244
  allSettled: {
193
- <T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
194
- <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
245
+ <T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
246
+ <const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
195
247
  };
196
248
  take: {
197
249
  <K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): Promise<E[K]>;
@@ -233,4 +285,4 @@ type StarterOf<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H,
233
285
  */
234
286
  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>>>;
235
287
  //#endregion
236
- export { RaceStarter as a, all as c, Starter as d, delay as f, take as i, ChildOf as l, effectsPlugin as n, race as o, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
288
+ 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$1 as p, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
@@ -1 +1 @@
1
- import{a as e,c as t,i as n,n as r,o as i,t as a}from"./context-_HWcdjZf.js";import{n as o,r as s,t as c}from"./delay-CqKplsaY.js";import{n as l,t as u}from"./promise-CSLpzwSR.js";import{n as d,t as f}from"./lifecycle-key-8iX8RUVD.js";const p=e=>Reflect.get(e,f),m=e=>{p(e)?.start()},h=(t,n,r)=>(m(t),e(t,n,r)),g=(e,t)=>{i(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,d,!0),e),b=()=>{},x=(e,t,n)=>typeof e==`function`?n(e,t??{}):t=>n(t,e??{}),S=(e,t)=>{let n=/* @__PURE__ */ new Map;return(r,i)=>{let a=e(r),o=n.get(a);if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e)}return o(r,i)}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t){return x(e,t,T)}const T=(e,t)=>C(t.key,t=>E(`latest`,(t,n,r)=>(r(),e(t,n)),t)),E=(e,r,o=b)=>{let s=null;return(c,u)=>{if(s?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=n(u);s=d;let p=a(d,e),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),i(d,e,`start`))};t(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=r(c,d,g);return l(e)?Promise.resolve(e).then(y,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),d.signal.aborted)return;throw p(`error`,e),e}}};function D(e,t,n){return x(t,n,(t,n)=>O(e,t,n))}const O=(e,t,n)=>C(n.key,r=>A(e,t,n,r)),k=(e,t,n,r)=>{let i=r!==b,a=null,c=null;return(l,u)=>{if(u.signal.aborted)return;let d=Date.now(),f=a===null||d-a>=e||d-a<0;return a=d,c!==null&&o(c),c=i?s(r,e):null,n&&f?Promise.resolve(h(u,`debounce`,()=>t(l,u))):(g(u,`debounce`),Promise.resolve(void 0))}},A=(e,n,r,i)=>{let a=r.leading??!1,o=r.trailing??!0;if(!o)return k(e,n,a,i);let s=!1,l=0,u=E(`debounce`,([r,i],a,u)=>{let d=l;return t(a,()=>{l===d&&(s=!1)}),c(a,e).then(()=>{if(s=!1,o&&!i)return u(),n(r,a)})},i);return(e,t)=>{if(t.signal.aborted)return;let r=a&&!s;s=!0,l++;let i=u([e,r],t);return r?Promise.resolve(h(t,`debounce`,()=>n(e,t))):i}};function j(e,t){return x(e,t,M)}const M=(e,n)=>C(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=t(a,s);try{return u(h(a,`leading`,()=>e(i,a)),s)}catch(e){throw s(),e}}});function N(e,t){return x(e,t,P)}const P=(e,t)=>C(t.key,n=>F(e,t,n)),F=(e,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=()=>{c(),s===0&&o.length===0&&r()},a=(e=!1)=>{n&&(n=!1,s--,e?queueMicrotask(i):i())},g=t(u,()=>{a(!0),d(void 0)}),v;try{v=Promise.resolve(h(u,`queue`,()=>e(l,u)))}catch(e){v=Promise.reject(e)}let y=()=>{g(),a()};v.then(e=>{_(u,{value:e}),y(),d(u.signal.aborted?void 0:e)},e=>{_(u,{error:e}),y(),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=t(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})};function I(e,t,n){return x(t,n,(t,n)=>L(e,t,n))}const L=(e,t,n)=>C(n.key,r=>R(e,t,n,r)),R=(e,t,n,r)=>{let i=n.leading??!0,a=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=s(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=s(w,n)},T=e=>{d=null;let t=p;if(a&&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=s(E,Math.min(e-(t-(l??t)),e-(t-u)))},D=()=>{f!==null&&(o(f),f=null)},O=(e,t)=>{if(!a)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,a)=>a&&d!==null?(o(d),d=s(E,e),S(t,n,r)):d===null&&(d=s(E,e),a&&(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(),a?A(e,t,n,r):k(e,t,n,r)}},z=Reflect.get(Symbol,`dispose`),B=e=>{let t=new AbortController,n=async(...n)=>{let i=n[0],{ctx:a,unlink:o}=r({event:{type:`withPolicy`,payload:i},parent:{signal:t.signal}});try{return await e(i,a)}finally{o()}},i=e=>{t.abort(e),t=new AbortController},a=Object.assign(n,{cancel:i});return z&&Reflect.set(a,z,()=>i()),a};export{D as debounce,w as latest,j as leading,N as queue,I as throttle,B as withPolicy};
1
+ import{n as e,r as t,t as n}from"./delay-Besb3X1O.js";import{a as r,c as i,i as a,n as o,o as s,t as c}from"./context-_HWcdjZf.js";import{n as l,t as u}from"./promise-CSLpzwSR.js";import{n as d,t as f}from"./lifecycle-key-8iX8RUVD.js";const p=e=>Reflect.get(e,f),m=e=>{p(e)?.start()},h=(e,t,n)=>(m(e),r(e,t,n)),g=(e,t)=>{s(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,d,!0),e),b=()=>{},x=(e,t,n)=>typeof e==`function`?n(e,t??{}):t=>n(t,e??{}),S=(e,t)=>{let n=/* @__PURE__ */ new Map;return(r,i)=>{let a=e(r),o=n.get(a);if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e)}return o(r,i)}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t){return x(e,t,T)}const T=(e,t)=>C(t.key,t=>E(`latest`,(t,n,r)=>(r(),e(t,n)),t)),E=(e,t,n=b)=>{let r=null;return(o,u)=>{if(r?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=a(u);r=d;let p=c(d,e),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),s(d,e,`start`))};i(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),r===d&&(r=null,n())},y=e=>{if(!d.signal.aborted)return p(h?`done`:`drop`),e};try{let e=t(o,d,g);return l(e)?Promise.resolve(e).then(y,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),d.signal.aborted)return;throw p(`error`,e),e}}};function D(e,t,n){return x(t,n,(t,n)=>O(e,t,n))}const O=(e,t,n)=>C(n.key,r=>A(e,t,n,r)),k=(n,r,i,a)=>{let o=a!==b,s=null,c=null;return(l,u)=>{if(u.signal.aborted)return;let d=Date.now(),f=s===null||d-s>=n||d-s<0;return s=d,c!==null&&e(c),c=o?t(a,n):null,i&&f?Promise.resolve(h(u,`debounce`,()=>r(l,u))):(g(u,`debounce`),Promise.resolve(void 0))}},A=(e,t,r,a)=>{let o=r.leading??!1,s=r.trailing??!0;if(!s)return k(e,t,o,a);let c=!1,l=0,u=E(`debounce`,([r,a],o,u)=>{let d=l;return i(o,()=>{l===d&&(c=!1)}),n(o,e).then(()=>{if(c=!1,s&&!a)return u(),t(r,o)})},a);return(e,n)=>{if(n.signal.aborted)return;let r=o&&!c;c=!0,l++;let i=u([e,r],n);return r?Promise.resolve(h(n,`debounce`,()=>t(e,n))):i}};function j(e,t){return x(e,t,M)}const M=(e,t)=>C(t.key,t=>{let n=null;return(r,a)=>{if(a.signal.aborted)return;if(n){g(a,`leading`);return}let o={};n=o;let s=()=>{c(),n===o&&(n=null,t())},c=i(a,s);try{return u(h(a,`leading`,()=>e(r,a)),s)}catch(e){throw s(),e}}});function N(e,t){return x(e,t,P)}const P=(e,t)=>C(t.key,n=>F(e,t,n)),F=(e,t,n)=>{let r=t.concurrency??1,a=t.limit??1/0,o=[],s=0,c=()=>{for(;s<r;){let e=o.shift();if(!e)return;e.start()}};return(l,u)=>new Promise((d,f)=>{if(u.signal.aborted){d(void 0);return}let p=b,m=()=>{p(),g(u,`queue`),d(void 0)},v=()=>{if(p(),u.signal.aborted){m();return}s++;let t=!0,r=()=>{c(),s===0&&o.length===0&&n()},a=(e=!1)=>{t&&(t=!1,s--,e?queueMicrotask(r):r())},g=i(u,()=>{a(!0),d(void 0)}),v;try{v=Promise.resolve(h(u,`queue`,()=>e(l,u)))}catch(e){v=Promise.reject(e)}let y=()=>{g(),a()};v.then(e=>{_(u,{value:e}),y(),d(u.signal.aborted?void 0:e)},e=>{_(u,{error:e}),y(),u.signal.aborted?d(void 0):f(e)})};if(s<r){v();return}if(o.length>=a){if(t.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=i(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})};function I(e,t,n){return x(t,n,(t,n)=>L(e,t,n))}const L=(e,t,n)=>C(n.key,r=>R(e,t,n,r)),R=(n,r,i,a)=>{let o=i.leading??!0,s=i.trailing??!0,c=a!==b,l=null,u=0,d=null,f=null,p=null,m=!1,_=e=>l===null||e-l>=n||e-l<0||e-u>=n,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,t,n)=>{y(),u=n,m=!0;try{return h(t,`throttle`,()=>r(e,t))}finally{m=!1}},C=()=>{c&&(f=t(w,n))},w=()=>{if(f=null,!c||d!==null||p)return;let e=Date.now(),r=Math.max(n-(e-(l??-1/0)),n-(e-u));r<=0?a():f=t(w,r)},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 e=Date.now();_(e)?T(e):d=t(E,Math.min(n-(e-(l??e)),n-(e-u)))},D=()=>{f!==null&&(e(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(),!o)v(t);else return S(e,t,n)},A=(r,i,a,s)=>s&&d!==null?(e(d),d=t(E,n),S(r,i,a)):d===null&&(d=t(E,n),s&&(u=a,o))?S(r,i,a):O(r,i);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)}},z=Reflect.get(Symbol,`dispose`),B=e=>{let t=new AbortController,n=async(...n)=>{let r=n[0],{ctx:i,unlink:a}=o({event:{type:`withPolicy`,payload:r},parent:{signal:t.signal}});try{return await e(r,i)}finally{a()}},r=e=>{t.abort(e),t=new AbortController},i=Object.assign(n,{cancel:r});return z&&Reflect.set(i,z,()=>r()),i};export{D as debounce,w as latest,j as leading,N as queue,I as throttle,B as withPolicy};
@@ -1,11 +1,17 @@
1
1
  import { B as Keys, N as WithContext, b as Context, d as Effects, h as Bus, l as BoundForm, r as FreeActionCreator, t as ActionCreator, z as EventMap } from "./action-creator-Bpa8BUS9.js";
2
2
  import { n as NoClash } from "./context-types-BKIH5a8s.js";
3
3
  //#region src/utils/delay.d.ts
4
+ type Milliseconds = number | (() => number);
4
5
  /**
5
6
  * Resolves after `ms`, or rejects early if `ctx.signal` aborts. `ms` can be a
6
7
  * function that returns the number of ms, called once when the delay starts:
7
8
  * handy for a random pause (jitter).
8
9
  *
10
+ * Without `ctx`, `delay(ms)` returns a starter for `race`, `all` and
11
+ * `allSettled`: they call it with the context of its own child task, and it
12
+ * waits then. It starts no timer before that, and one starter can be used in
13
+ * several groups. Do not `await` it on its own: it is a function, not a promise.
14
+ *
9
15
  * @example
10
16
  * ```ts
11
17
  * await delay({}, 500);
@@ -18,11 +24,20 @@ import { n as NoClash } from "./context-types-BKIH5a8s.js";
18
24
  * await delay(ctx, 1000);
19
25
  * await load();
20
26
  * });
27
+ *
28
+ * // as a starter: the loser of the race is cancelled
29
+ * const result = await race(ctx, {
30
+ * waited: delay(1000),
31
+ * cancelled: take(cancel),
32
+ * });
21
33
  * ```
22
34
  */
23
- declare const delay: (ctx: {
35
+ declare function delay(ms: Milliseconds): (child: {
36
+ signal?: AbortSignal | undefined;
37
+ }) => Promise<void>;
38
+ declare function delay(ctx: {
24
39
  signal?: AbortSignal | undefined;
25
- }, ms: number | (() => number)) => Promise<void>;
40
+ }, ms: Milliseconds): Promise<void>;
26
41
  //#endregion
27
42
  //#region src/effects/run.d.ts
28
43
  /** What a starter gets when the effect was called with `{}` or a bare `{ signal }`. */
@@ -37,6 +52,25 @@ type EffectContext = {
37
52
  */
38
53
  type ChildOf<C> = C extends Context<infer E> ? Context<E> : EffectContext;
39
54
  type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
55
+ /**
56
+ * A starter of a group on a bus with the events `E`, with the result `R`. A starter written in a
57
+ * group needs no type: the group gives it. Use this for one kept in a variable, where nothing
58
+ * tells the checker which bus it is for.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const load: StarterOf<Events> = all({ user: retry(() => loadUser(1)) });
63
+ * const user: StarterOf<Events, User> = retry(() => loadUser(1));
64
+ *
65
+ * bus.on("open", async (_, ctx) => race(ctx, { load, user }));
66
+ * ```
67
+ */
68
+ type StarterOf$1<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
+ };
40
74
  //#endregion
41
75
  //#region src/effects/all.d.ts
42
76
  /**
@@ -56,10 +90,12 @@ type Starter<T, Child = EffectContext> = (child: Child) => T | PromiseLike<T>;
56
90
  */
57
91
  declare function all<C extends {
58
92
  signal?: AbortSignal;
59
- }, 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]>>; }>;
60
94
  declare function all<C extends {
61
95
  signal?: AbortSignal;
62
- }, 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]>>; }>;
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]>>; }>;
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]>>; }>;
63
99
  //#endregion
64
100
  //#region src/effects/allSettled.d.ts
65
101
  /**
@@ -82,10 +118,12 @@ declare function all<C extends {
82
118
  */
83
119
  declare function allSettled<C extends {
84
120
  signal?: AbortSignal;
85
- }, 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]>>>; }>;
86
122
  declare function allSettled<C extends {
87
123
  signal?: AbortSignal;
88
- }, 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]>>>; }>;
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]>>>; }>;
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]>>>; }>;
89
127
  //#endregion
90
128
  //#region src/effects/race.d.ts
91
129
  type RaceStarter<T, Child = EffectContext> = Starter<T, Child>;
@@ -112,6 +150,8 @@ declare function race<C extends {
112
150
  declare function race<C extends {
113
151
  signal?: AbortSignal;
114
152
  }, const T extends readonly RaceStarter<unknown, ChildOf<C>>[]>(ctx: C, effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
153
+ declare function race<Child, T extends Record<string, RaceStarter<unknown, Child>>>(effects: T): (child: Child) => Promise<{ [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
154
+ declare function race<Child, const T extends readonly RaceStarter<unknown, Child>[]>(effects: T): (child: Child) => Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
115
155
  //#endregion
116
156
  //#region src/effects/take.d.ts
117
157
  type TakeOptions<P> = {
@@ -163,6 +203,18 @@ declare function take<E extends EventMap, P, T extends P>(ctx: Context<E>, creat
163
203
  predicate: (payload: P) => payload is T;
164
204
  }): Promise<T>;
165
205
  declare function take<E extends EventMap, P>(ctx: Context<E>, creator: ActionCreator<P>, options?: TakeOptions<P>): Promise<P>;
206
+ declare function take<E extends EventMap, K extends Keys<E>, T extends E[K]>(event: K, options: TakeOptions<E[K]> & {
207
+ predicate: (payload: E[K]) => payload is T;
208
+ }): (child: Context<E>) => Promise<T>;
209
+ declare function take<E extends EventMap, K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): (child: Context<E>) => Promise<E[K]>;
210
+ declare function take<E extends EventMap, K extends Keys<E>, T extends E[K]>(creator: FreeActionCreator<K>, options: TakeOptions<E[K]> & {
211
+ predicate: (payload: E[K]) => payload is T;
212
+ }): (child: Context<E>) => Promise<T>;
213
+ declare function take<E extends EventMap, K extends Keys<E>>(creator: FreeActionCreator<K>, options?: TakeOptions<E[K]>): (child: Context<E>) => Promise<E[K]>;
214
+ declare function take<E extends EventMap, P, T extends P>(creator: ActionCreator<P>, options: TakeOptions<P> & {
215
+ predicate: (payload: P) => payload is T;
216
+ }): (child: Context<E>) => Promise<T>;
217
+ declare function take<E extends EventMap, P>(creator: ActionCreator<P>, options?: TakeOptions<P>): (child: Context<E>) => Promise<P>;
166
218
  //#endregion
167
219
  //#region src/effects/plugin.d.ts
168
220
  /** The effects that `effectsPlugin` can put on `ctx`. */
@@ -180,12 +232,12 @@ type Bound<E extends EventMap, Child> = {
180
232
  <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]?: Awaited<ReturnType<T[K]>>; }>;
181
233
  };
182
234
  all: {
183
- <T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
184
- <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
235
+ <T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
236
+ <const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: Awaited<ReturnType<T[K]>>; }>;
185
237
  };
186
238
  allSettled: {
187
- <T extends Record<string, Starter<unknown, Child>>>(effects: T): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
188
- <const T extends readonly Starter<unknown, Child>[]>(effects: T): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
239
+ <T extends Record<string, Starter<unknown, Child>>>(effects: T, options?: GroupOptions | null): Promise<{ [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
240
+ <const T extends readonly Starter<unknown, Child>[]>(effects: T, options?: GroupOptions | null): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<ReturnType<T[K]>>>; }>;
189
241
  };
190
242
  take: {
191
243
  <K extends Keys<E>>(event: K, options?: TakeOptions<E[K]>): Promise<E[K]>;
@@ -227,4 +279,4 @@ type StarterOf<H extends Helpers, E extends EventMap> = Context<E> & BoundOf<H,
227
279
  */
228
280
  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>>>;
229
281
  //#endregion
230
- export { RaceStarter as a, all as c, Starter as d, delay as f, take as i, ChildOf as l, effectsPlugin as n, race as o, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
282
+ 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$1 as p, TakeOptions as r, allSettled as s, BoundOf as t, EffectContext as u };
package/dist/policies.js CHANGED
@@ -1 +1 @@
1
- import{i as e,o as t,s as n,t as r,u as i}from"./context-UcmrAIhP.js";import{n as a,r as o,t as s}from"./delay-mxZkTg17.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-D-SQRkPh.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,n,r)=>(m(e),t(e,n,r)),g=(e,t)=>{n(e,t,`drop`),p(e)?.drop()},_=(e,t)=>{p(e)?.done(t)},v=(e,t,n)=>{let r=p(e);t?r?.cancel(n):r?.drop()},y=e=>(Reflect.set(e,u,!0),e),b=()=>{},x=(e,t,n)=>typeof e==`function`?n(e,t??{}):t=>n(t,e??{}),S=(e,t)=>{let n=/* @__PURE__ */ new Map;return(r,i)=>{let a=e(r),o=n.get(a);if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e)}return o(r,i)}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t){return x(e,t,T)}const T=(e,t)=>C(t.key,t=>E(`latest`,(t,n,r)=>(r(),e(t,n)),t)),E=(t,a,o=b)=>{let s=null;return(l,u)=>{if(s?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=e(u);s=d;let p=r(d,t),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),n(d,t,`start`))};i(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),s===d&&(s=null,o())},y=e=>{if(!d.signal.aborted)return p(h?`done`:`drop`),e};try{let e=a(l,d,g);return c(e)?Promise.resolve(e).then(y,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),d.signal.aborted)return;throw p(`error`,e),e}}};function D(e,t,n){return x(t,n,(t,n)=>O(e,t,n))}const O=(e,t,n)=>C(n.key,r=>A(e,t,n,r)),k=(e,t,n,r)=>{let i=r!==b,s=null,c=null;return(l,u)=>{if(u.signal.aborted)return;let d=Date.now(),f=s===null||d-s>=e||d-s<0;return s=d,c!==null&&a(c),c=i?o(r,e):null,n&&f?Promise.resolve(h(u,`debounce`,()=>t(l,u))):(g(u,`debounce`),Promise.resolve(void 0))}},A=(e,t,n,r)=>{let a=n.leading??!1,o=n.trailing??!0;if(!o)return k(e,t,a,r);let c=!1,l=0,u=E(`debounce`,([n,r],a,u)=>{let d=l;return i(a,()=>{l===d&&(c=!1)}),s(a,e).then(()=>{if(c=!1,o&&!r)return u(),t(n,a)})},r);return(e,n)=>{if(n.signal.aborted)return;let r=a&&!c;c=!0,l++;let i=u([e,r],n);return r?Promise.resolve(h(n,`debounce`,()=>t(e,n))):i}};function j(e,t){return x(e,t,M)}const M=(e,t)=>C(t.key,t=>{let n=null;return(r,a)=>{if(a.signal.aborted)return;if(n){g(a,`leading`);return}let o={};n=o;let s=()=>{c(),n===o&&(n=null,t())},c=i(a,s);try{return l(h(a,`leading`,()=>e(r,a)),s)}catch(e){throw s(),e}}});function N(e,t){return x(e,t,P)}const P=(e,t)=>C(t.key,n=>F(e,t,n)),F=(e,t,n)=>{let r=t.concurrency??1,a=t.limit??1/0,o=[],s=0,c=()=>{for(;s<r;){let e=o.shift();if(!e)return;e.start()}};return(l,u)=>new Promise((d,f)=>{if(u.signal.aborted){d(void 0);return}let p=b,m=()=>{p(),g(u,`queue`),d(void 0)},v=()=>{if(p(),u.signal.aborted){m();return}s++;let t=!0,r=()=>{c(),s===0&&o.length===0&&n()},a=(e=!1)=>{t&&(t=!1,s--,e?queueMicrotask(r):r())},g=i(u,()=>{a(!0),d(void 0)}),v;try{v=Promise.resolve(h(u,`queue`,()=>e(l,u)))}catch(e){v=Promise.reject(e)}let y=()=>{g(),a()};v.then(e=>{_(u,{value:e}),y(),d(u.signal.aborted?void 0:e)},e=>{_(u,{error:e}),y(),u.signal.aborted?d(void 0):f(e)})};if(s<r){v();return}if(o.length>=a){if(t.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=i(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})};function I(e,t,n){return x(t,n,(t,n)=>L(e,t,n))}const L=(e,t,n)=>C(n.key,r=>R(e,t,n,r)),R=(e,t,n,r)=>{let i=n.leading??!0,s=n.trailing??!0,c=r!==b,l=null,u=0,d=null,f=null,p=null,m=!1,_=t=>l===null||t-l>=e||t-l<0||t-u>=e,v=e=>g(e,`throttle`),y=()=>{let e=p;p=null,e&&(v(e.ctx),e.resolve())},x=(e,t)=>(y(),new Promise((n,r)=>{p={payload:e,ctx:t,resolve:n,reject:r}})),S=(e,n,r)=>{y(),u=r,m=!0;try{return h(n,`throttle`,()=>t(e,n))}finally{m=!1}},C=()=>{c&&(f=o(w,e))},w=()=>{if(f=null,!c||d!==null||p)return;let t=Date.now(),n=Math.max(e-(t-(l??-1/0)),e-(t-u));n<=0?r():f=o(w,n)},T=e=>{d=null;let t=p;if(s&&t&&!t.ctx.signal.aborted){p=null;try{t.resolve(S(t.payload,t.ctx,e))}catch(e){t.reject(e)}}else y();w()},E=()=>{let t=Date.now();_(t)?T(t):d=o(E,Math.min(e-(t-(l??t)),e-(t-u)))},D=()=>{f!==null&&(a(f),f=null)},O=(e,t)=>{if(!s)v(t);else return x(e,t)},k=(e,t,n,r)=>{if(!r)v(t);else if(u=n,C(),!i)v(t);else return S(e,t,n)},A=(t,n,r,s)=>s&&d!==null?(a(d),d=o(E,e),S(t,n,r)):d===null&&(d=o(E,e),s&&(u=r,i))?S(t,n,r):O(t,n);return(e,t)=>{if(t.signal.aborted)return;let n=Date.now(),r=!m&&_(n);return l=n,D(),s?A(e,t,n,r):k(e,t,n,r)}};export{D as debounce,w as latest,j as leading,N as queue,I as throttle,f as withPolicy};
1
+ import{n as e,r as t,t as n}from"./delay-18LJ8jSk.js";import{i as r,o as i,s as a,t as o,u as s}from"./context-UcmrAIhP.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-D-SQRkPh.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,t,n)=>(m(e),i(e,t,n)),g=(e,t)=>{a(e,t,`drop`),p(e)?.drop()},_=(e,t)=>{p(e)?.done(t)},v=(e,t,n)=>{let r=p(e);t?r?.cancel(n):r?.drop()},y=e=>(Reflect.set(e,u,!0),e),b=()=>{},x=(e,t,n)=>typeof e==`function`?n(e,t??{}):t=>n(t,e??{}),S=(e,t)=>{let n=/* @__PURE__ */ new Map;return(r,i)=>{let a=e(r),o=n.get(a);if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e)}return o(r,i)}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t){return x(e,t,T)}const T=(e,t)=>C(t.key,t=>E(`latest`,(t,n,r)=>(r(),e(t,n)),t)),E=(e,t,n=b)=>{let i=null;return(l,u)=>{if(i?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=r(u);i=d;let p=o(d,e),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),a(d,e,`start`))};s(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),i===d&&(i=null,n())},y=e=>{if(!d.signal.aborted)return p(h?`done`:`drop`),e};try{let e=t(l,d,g);return c(e)?Promise.resolve(e).then(y,e=>{if(!d.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),d.signal.aborted)return;throw p(`error`,e),e}}};function D(e,t,n){return x(t,n,(t,n)=>O(e,t,n))}const O=(e,t,n)=>C(n.key,r=>A(e,t,n,r)),k=(n,r,i,a)=>{let o=a!==b,s=null,c=null;return(l,u)=>{if(u.signal.aborted)return;let d=Date.now(),f=s===null||d-s>=n||d-s<0;return s=d,c!==null&&e(c),c=o?t(a,n):null,i&&f?Promise.resolve(h(u,`debounce`,()=>r(l,u))):(g(u,`debounce`),Promise.resolve(void 0))}},A=(e,t,r,i)=>{let a=r.leading??!1,o=r.trailing??!0;if(!o)return k(e,t,a,i);let c=!1,l=0,u=E(`debounce`,([r,i],a,u)=>{let d=l;return s(a,()=>{l===d&&(c=!1)}),n(a,e).then(()=>{if(c=!1,o&&!i)return u(),t(r,a)})},i);return(e,n)=>{if(n.signal.aborted)return;let r=a&&!c;c=!0,l++;let i=u([e,r],n);return r?Promise.resolve(h(n,`debounce`,()=>t(e,n))):i}};function j(e,t){return x(e,t,M)}const M=(e,t)=>C(t.key,t=>{let n=null;return(r,i)=>{if(i.signal.aborted)return;if(n){g(i,`leading`);return}let a={};n=a;let o=()=>{c(),n===a&&(n=null,t())},c=s(i,o);try{return l(h(i,`leading`,()=>e(r,i)),o)}catch(e){throw o(),e}}});function N(e,t){return x(e,t,P)}const P=(e,t)=>C(t.key,n=>F(e,t,n)),F=(e,t,n)=>{let r=t.concurrency??1,i=t.limit??1/0,a=[],o=0,c=()=>{for(;o<r;){let e=a.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}o++;let t=!0,r=()=>{c(),o===0&&a.length===0&&n()},i=(e=!1)=>{t&&(t=!1,o--,e?queueMicrotask(r):r())},g=s(u,()=>{i(!0),d(void 0)}),v;try{v=Promise.resolve(h(u,`queue`,()=>e(l,u)))}catch(e){v=Promise.reject(e)}let y=()=>{g(),i()};v.then(e=>{_(u,{value:e}),y(),d(u.signal.aborted?void 0:e)},e=>{_(u,{error:e}),y(),u.signal.aborted?d(void 0):f(e)})};if(o<r){v();return}if(a.length>=i){if(t.overflow!==`drop-old`||i<=0){m();return}a.shift()?.drop()}let y={start:v,drop:m};a.push(y),p=s(u,()=>{let e=a.indexOf(y);e>=0&&a.splice(e,1),m()})})};function I(e,t,n){return x(t,n,(t,n)=>L(e,t,n))}const L=(e,t,n)=>C(n.key,r=>R(e,t,n,r)),R=(n,r,i,a)=>{let o=i.leading??!0,s=i.trailing??!0,c=a!==b,l=null,u=0,d=null,f=null,p=null,m=!1,_=e=>l===null||e-l>=n||e-l<0||e-u>=n,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,t,n)=>{y(),u=n,m=!0;try{return h(t,`throttle`,()=>r(e,t))}finally{m=!1}},C=()=>{c&&(f=t(w,n))},w=()=>{if(f=null,!c||d!==null||p)return;let e=Date.now(),r=Math.max(n-(e-(l??-1/0)),n-(e-u));r<=0?a():f=t(w,r)},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 e=Date.now();_(e)?T(e):d=t(E,Math.min(n-(e-(l??e)),n-(e-u)))},D=()=>{f!==null&&(e(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(),!o)v(t);else return S(e,t,n)},A=(r,i,a,s)=>s&&d!==null?(e(d),d=t(E,n),S(r,i,a)):d===null&&(d=t(E,n),s&&(u=a,o))?S(r,i,a):O(r,i);return(e,t)=>{if(t.signal.aborted)return;let n=Date.now(),r=!m&&_(n);return l=n,D(),s?A(e,t,n,r):k(e,t,n,r)}};export{D as debounce,w as latest,j as leading,N as queue,I as throttle,f as withPolicy};
package/dist/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-CBoV9m7W.js";
2
+ import { n as ScopeSlots, r as Scoped } from "./types-DWjyeii7.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-BZK83Z3N.js";
2
+ import { t as BoundOf } from "./plugin-B6UQyoVd.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/effects.md CHANGED
@@ -264,8 +264,10 @@ bus.on("login", async (user, ctx) => {
264
264
  console.log(stopped);
265
265
 
266
266
  // wait for a matching event, but not longer than 5 s
267
- const id = await timeout(ctx, 5000, (child) =>
268
- take(child, "saved", { predicate: (savedId) => savedId === draft.id }),
267
+ const id = await timeout(
268
+ ctx,
269
+ 5000,
270
+ take("saved", { predicate: (savedId) => savedId === draft.id }), // take without ctx: a starter
269
271
  );
270
272
  });
271
273
  ```
@@ -273,7 +275,7 @@ bus.on("login", async (user, ctx) => {
273
275
  - Sees only events emitted after the call, takes one, and unsubscribes.
274
276
  - With an action creator the result has the payload type of the creator. A creator made without a payload type (`createAction("saved")`) takes it from the event map of the bus.
275
277
  - `options.predicate` skips payloads it rejects. In TypeScript, a type guard (`(payload): payload is Admin`) narrows the type of the result.
276
- - `options.signal` stops the wait. In a starter of `race`, `all` or `timeout` pass `child` as the first argument instead: it already carries the signal.
278
+ - `options.signal` stops the wait. Inside `race`, `all` or `timeout` you do not need it: the group already stops the starter, so write `take("saved")` without options.
277
279
  - On abort of the task or of `options.signal`, unsubscribes and rejects with the abort reason.
278
280
 
279
281
  ## Run several starters together
@@ -311,8 +313,8 @@ const bus = createBus();
311
313
  bus.on("save", async (draft, ctx) => {
312
314
  // race — the first starter to finish wins, the other is cancelled
313
315
  const result = await race(ctx, {
314
- waited: (child) => delay(child, 1000),
315
- cancelled: (child) => take(child, "cancel"),
316
+ waited: delay(1000), // delay without ctx — a starter: race gives it its own child
317
+ cancelled: take("cancel"), // take without ctx — the same, waits for the next "cancel"
316
318
  });
317
319
 
318
320
  if ("waited" in result) {
@@ -321,12 +323,88 @@ bus.on("save", async (draft, ctx) => {
321
323
  });
322
324
  ```
323
325
 
326
+ **`delay` and `take` without `ctx` are ready-made starters.** In a group, `delay(1000)` and `take("cancel")` do what `(child) => delay(child, 1000)` and `(child) => take(child, "cancel")` do. The group calls them with the child, so the wait stops with the group. Use this form inside `race`, `all`, `allSettled` and `timeout`; use `delay(ctx, 1000)` in plain handler code. A starter waits only when a group calls it: do not `await delay(1000)` on its own, it is a function, not a promise. Write `take("cancel")` in the group, as above; a starter stored in a variable outside it does not know the events of your bus, and you name them yourself in TypeScript (`const cancelled: StarterOf<Events> = take("cancel")`; `StarterOf` is exported by `nanoeffects/effects`).
327
+
328
+ The wrapper form of `retry`, `timeout` and `poll` is a starter too: a group calls it with the child, and the function you wrap gets `undefined` as its payload and the child as its context. Write the data it needs into a closure:
329
+
330
+ ```js
331
+ import { createBus } from "nanoeffects";
332
+ import { delay, race, retry } from "nanoeffects/effects";
333
+
334
+ const bus = createBus();
335
+
336
+ bus.on("open", async (id, ctx) => {
337
+ const result = await race(ctx, {
338
+ // retry without ctx — a starter: up to 3 attempts, each with the signal of the child
339
+ user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
340
+ // delay without ctx — the loser is cancelled when the other one finishes
341
+ waited: delay(5000),
342
+ });
343
+
344
+ if ("user" in result) {
345
+ render(result.user);
346
+ }
347
+ });
348
+ ```
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.
351
+
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
+
354
+ ```js
355
+ import { createBus } from "nanoeffects";
356
+ import { all, delay, race, retry } from "nanoeffects/effects";
357
+
358
+ const bus = createBus();
359
+
360
+ bus.on("open", async (id, ctx) => {
361
+ const result = await race(ctx, {
362
+ // all without ctx — a starter: loads both, each with up to 3 attempts
363
+ loaded: all({
364
+ user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
365
+ posts: retry((_, { signal }) => fetchPosts(id, { signal }), { times: 3 }),
366
+ }),
367
+ // delay without ctx — when it wins, the whole `all` above is cancelled
368
+ waited: delay(5000),
369
+ });
370
+
371
+ if ("loaded" in result) {
372
+ render(result.loaded.user, result.loaded.posts);
373
+ }
374
+ });
375
+ ```
376
+
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
+
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. A group starter inside another group takes no options; write `(child) => all(child, effects, { concurrency: 5 })` there.
400
+
401
+
324
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`.
325
403
 
326
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.
327
405
 
328
406
  ## Pass `ctx` outside a task
329
407
 
330
- Effects that wait inside a body take `ctx` first: `delay`, `all`, `allSettled`, `race`, `cancellable`, `onAbort`, `take`, and the `ctx` forms of `retry` / `timeout` / `poll`. Outside a task, pass `{}` or any object with a `signal`.
408
+ Effects that wait inside a body take `ctx` first: `delay`, `all`, `allSettled`, `race`, `cancellable`, `onAbort`, `take`, and the `ctx` forms of `retry` / `timeout` / `poll`. Outside a task, pass `{}` or any object with a `signal`. The one exception is `delay(ms)` and `take(event)` as starters of a group, which take no `ctx` (see above).
331
409
 
332
410
  For `fetch` and other APIs that take a signal, pass `ctx.signal`. A timeout without `race`: `AbortSignal.any([ctx.signal, AbortSignal.timeout(5000)])`.
package/docs/guide.md CHANGED
@@ -267,7 +267,7 @@ For one call in the middle of a body: `await retry(ctx, () => api.search(q, { si
267
267
 
268
268
  ```js
269
269
  import { createBus } from "nanoeffects";
270
- import { all, take } from "nanoeffects/effects";
270
+ import { all, delay, race, take } from "nanoeffects/effects";
271
271
 
272
272
  const bus = createBus();
273
273
 
@@ -285,6 +285,18 @@ bus.on("typed", async (query, ctx) => {
285
285
  const position = await take(ctx, "scroll");
286
286
  ctx.emit("scrolled", { query, position });
287
287
  });
288
+
289
+ // race — the first to finish wins, the other is cancelled
290
+ bus.on("save", async (draft, ctx) => {
291
+ const result = await race(ctx, {
292
+ cancelled: take("cancel"), // take without ctx — waits for the next "cancel"
293
+ waited: delay(1000), // delay without ctx — waits one second
294
+ });
295
+
296
+ if ("waited" in result) {
297
+ ctx.emit("saved", draft);
298
+ }
299
+ });
288
300
  ```
289
301
 
290
302
  More in [Effects](effects.md).
@@ -121,10 +121,10 @@ bus.on("watch", async (_, ctx) => {
121
121
  };
122
122
 
123
123
  await race(ctx, {
124
- // poll: a check every 5 s; waitForFn: the next pause starts after the check ends
125
- polling: (child) => poll(child, checkStatus, 5000, { waitForFn: true }),
126
- // take: resolves at the next "leave", and race stops the polling
127
- leave: (child) => take(child, "leave"),
124
+ // poll without ctx: a check every 5 s; waitForFn: the next pause starts after the check ends
125
+ polling: poll(5000, checkStatus, { waitForFn: true }),
126
+ // take without ctx: resolves at the next "leave", and race stops the polling
127
+ leave: take("leave"),
128
128
  });
129
129
  });
130
130
 
package/llms-full.txt CHANGED
@@ -284,7 +284,7 @@ For one call in the middle of a body: `await retry(ctx, () => api.search(q, { si
284
284
 
285
285
  ```js
286
286
  import { createBus } from "nanoeffects";
287
- import { all, take } from "nanoeffects/effects";
287
+ import { all, delay, race, take } from "nanoeffects/effects";
288
288
 
289
289
  const bus = createBus();
290
290
 
@@ -302,6 +302,18 @@ bus.on("typed", async (query, ctx) => {
302
302
  const position = await take(ctx, "scroll");
303
303
  ctx.emit("scrolled", { query, position });
304
304
  });
305
+
306
+ // race — the first to finish wins, the other is cancelled
307
+ bus.on("save", async (draft, ctx) => {
308
+ const result = await race(ctx, {
309
+ cancelled: take("cancel"), // take without ctx — waits for the next "cancel"
310
+ waited: delay(1000), // delay without ctx — waits one second
311
+ });
312
+
313
+ if ("waited" in result) {
314
+ ctx.emit("saved", draft);
315
+ }
316
+ });
305
317
  ```
306
318
 
307
319
  More in [Effects](effects.md).
@@ -1848,8 +1860,10 @@ bus.on("login", async (user, ctx) => {
1848
1860
  console.log(stopped);
1849
1861
 
1850
1862
  // wait for a matching event, but not longer than 5 s
1851
- const id = await timeout(ctx, 5000, (child) =>
1852
- take(child, "saved", { predicate: (savedId) => savedId === draft.id }),
1863
+ const id = await timeout(
1864
+ ctx,
1865
+ 5000,
1866
+ take("saved", { predicate: (savedId) => savedId === draft.id }), // take without ctx: a starter
1853
1867
  );
1854
1868
  });
1855
1869
  ```
@@ -1857,7 +1871,7 @@ bus.on("login", async (user, ctx) => {
1857
1871
  - Sees only events emitted after the call, takes one, and unsubscribes.
1858
1872
  - With an action creator the result has the payload type of the creator. A creator made without a payload type (`createAction("saved")`) takes it from the event map of the bus.
1859
1873
  - `options.predicate` skips payloads it rejects. In TypeScript, a type guard (`(payload): payload is Admin`) narrows the type of the result.
1860
- - `options.signal` stops the wait. In a starter of `race`, `all` or `timeout` pass `child` as the first argument instead: it already carries the signal.
1874
+ - `options.signal` stops the wait. Inside `race`, `all` or `timeout` you do not need it: the group already stops the starter, so write `take("saved")` without options.
1861
1875
  - On abort of the task or of `options.signal`, unsubscribes and rejects with the abort reason.
1862
1876
 
1863
1877
  ## Run several starters together
@@ -1895,8 +1909,8 @@ const bus = createBus();
1895
1909
  bus.on("save", async (draft, ctx) => {
1896
1910
  // race — the first starter to finish wins, the other is cancelled
1897
1911
  const result = await race(ctx, {
1898
- waited: (child) => delay(child, 1000),
1899
- cancelled: (child) => take(child, "cancel"),
1912
+ waited: delay(1000), // delay without ctx — a starter: race gives it its own child
1913
+ cancelled: take("cancel"), // take without ctx — the same, waits for the next "cancel"
1900
1914
  });
1901
1915
 
1902
1916
  if ("waited" in result) {
@@ -1905,13 +1919,89 @@ bus.on("save", async (draft, ctx) => {
1905
1919
  });
1906
1920
  ```
1907
1921
 
1922
+ **`delay` and `take` without `ctx` are ready-made starters.** In a group, `delay(1000)` and `take("cancel")` do what `(child) => delay(child, 1000)` and `(child) => take(child, "cancel")` do. The group calls them with the child, so the wait stops with the group. Use this form inside `race`, `all`, `allSettled` and `timeout`; use `delay(ctx, 1000)` in plain handler code. A starter waits only when a group calls it: do not `await delay(1000)` on its own, it is a function, not a promise. Write `take("cancel")` in the group, as above; a starter stored in a variable outside it does not know the events of your bus, and you name them yourself in TypeScript (`const cancelled: StarterOf<Events> = take("cancel")`; `StarterOf` is exported by `nanoeffects/effects`).
1923
+
1924
+ The wrapper form of `retry`, `timeout` and `poll` is a starter too: a group calls it with the child, and the function you wrap gets `undefined` as its payload and the child as its context. Write the data it needs into a closure:
1925
+
1926
+ ```js
1927
+ import { createBus } from "nanoeffects";
1928
+ import { delay, race, retry } from "nanoeffects/effects";
1929
+
1930
+ const bus = createBus();
1931
+
1932
+ bus.on("open", async (id, ctx) => {
1933
+ const result = await race(ctx, {
1934
+ // retry without ctx — a starter: up to 3 attempts, each with the signal of the child
1935
+ user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
1936
+ // delay without ctx — the loser is cancelled when the other one finishes
1937
+ waited: delay(5000),
1938
+ });
1939
+
1940
+ if ("user" in result) {
1941
+ render(result.user);
1942
+ }
1943
+ });
1944
+ ```
1945
+
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.
1947
+
1948
+ **`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
+
1950
+ ```js
1951
+ import { createBus } from "nanoeffects";
1952
+ import { all, delay, race, retry } from "nanoeffects/effects";
1953
+
1954
+ const bus = createBus();
1955
+
1956
+ bus.on("open", async (id, ctx) => {
1957
+ const result = await race(ctx, {
1958
+ // all without ctx — a starter: loads both, each with up to 3 attempts
1959
+ loaded: all({
1960
+ user: retry((_, { signal }) => fetchUser(id, { signal }), { times: 3 }),
1961
+ posts: retry((_, { signal }) => fetchPosts(id, { signal }), { times: 3 }),
1962
+ }),
1963
+ // delay without ctx — when it wins, the whole `all` above is cancelled
1964
+ waited: delay(5000),
1965
+ });
1966
+
1967
+ if ("loaded" in result) {
1968
+ render(result.loaded.user, result.loaded.posts);
1969
+ }
1970
+ });
1971
+ ```
1972
+
1973
+ 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
+
1975
+ **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:
1976
+
1977
+ ```js
1978
+ import { createBus } from "nanoeffects";
1979
+ import { all, retry } from "nanoeffects/effects";
1980
+
1981
+ const bus = createBus();
1982
+
1983
+ bus.on("sync", async (ids, ctx) => {
1984
+ // all with concurrency — 5 loads at a time, results in the order of ids
1985
+ const users = await all(
1986
+ ctx,
1987
+ ids.map((id) => retry(() => loadUser(id), { times: 2 })),
1988
+ { concurrency: 5 },
1989
+ );
1990
+
1991
+ render(users);
1992
+ });
1993
+ ```
1994
+
1995
+ 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. A group starter inside another group takes no options; write `(child) => all(child, effects, { concurrency: 5 })` there.
1996
+
1997
+
1908
1998
  **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`.
1909
1999
 
1910
2000
  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.
1911
2001
 
1912
2002
  ## Pass `ctx` outside a task
1913
2003
 
1914
- Effects that wait inside a body take `ctx` first: `delay`, `all`, `allSettled`, `race`, `cancellable`, `onAbort`, `take`, and the `ctx` forms of `retry` / `timeout` / `poll`. Outside a task, pass `{}` or any object with a `signal`.
2004
+ Effects that wait inside a body take `ctx` first: `delay`, `all`, `allSettled`, `race`, `cancellable`, `onAbort`, `take`, and the `ctx` forms of `retry` / `timeout` / `poll`. Outside a task, pass `{}` or any object with a `signal`. The one exception is `delay(ms)` and `take(event)` as starters of a group, which take no `ctx` (see above).
1915
2005
 
1916
2006
  For `fetch` and other APIs that take a signal, pass `ctx.signal`. A timeout without `race`: `AbortSignal.any([ctx.signal, AbortSignal.timeout(5000)])`.
1917
2007
 
@@ -5599,10 +5689,10 @@ bus.on("watch", async (_, ctx) => {
5599
5689
  };
5600
5690
 
5601
5691
  await race(ctx, {
5602
- // poll: a check every 5 s; waitForFn: the next pause starts after the check ends
5603
- polling: (child) => poll(child, checkStatus, 5000, { waitForFn: true }),
5604
- // take: resolves at the next "leave", and race stops the polling
5605
- leave: (child) => take(child, "leave"),
5692
+ // poll without ctx: a check every 5 s; waitForFn: the next pause starts after the check ends
5693
+ polling: poll(5000, checkStatus, { waitForFn: true }),
5694
+ // take without ctx: resolves at the next "leave", and race stops the polling
5695
+ leave: take("leave"),
5606
5696
  });
5607
5697
  });
5608
5698
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nanoeffects",
3
- "version": "0.23.1",
3
+ "version": "0.25.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": "2.5 kB"
223
+ "limit": "3 kB"
224
224
  },
225
225
  {
226
226
  "name": "actions (all)",
@@ -1 +0,0 @@
1
- import{u as e}from"./context-UcmrAIhP.js";const t=2**31-1,n=(e,n)=>{let r={id:null};if(n===1/0)return r;let i=n=>{r.id=setTimeout(()=>{n>t?i(n-t):(r.id=null,e())},Math.min(n,t))};return i(n>0?n:0),r},r=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},i=(t,i)=>new Promise((a,o)=>{let s=n(()=>{c(),a()},typeof i==`function`?i():i),c=e(t,e=>{r(s),o(e)})});export{r as n,n as r,i as t};
@@ -1 +0,0 @@
1
- import{c as e}from"./context-_HWcdjZf.js";const t=2**31-1,n=(e,n)=>{let r={id:null};if(n===1/0)return r;let i=n=>{r.id=setTimeout(()=>{n>t?i(n-t):(r.id=null,e())},Math.min(n,t))};return i(n>0?n:0),r},r=e=>{e.id!==null&&(clearTimeout(e.id),e.id=null)},i=(t,i)=>new Promise((a,o)=>{let s=n(()=>{c(),a()},typeof i==`function`?i():i),c=e(t,e=>{r(s),o(e)})});export{r as n,n as r,i as t};