nanoeffects 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/{action-creator-DprJV-pN.d.ts → action-creator-CXIq6GWK.d.ts} +1 -1
  2. package/dist/actions.d.ts +3 -3
  3. package/dist/{context-types-BiTMp_lW.d.ts → context-types-BO1QE6W2.d.ts} +1 -1
  4. package/dist/context.d.ts +2 -2
  5. package/dist/dev.d.ts +2 -2
  6. package/dist/effects.d.ts +2 -2
  7. package/dist/guard.d.ts +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/match.d.ts +1 -1
  10. package/dist/{module-Fk4OtkZk.d.ts → module-BXNaEXE9.d.ts} +2 -2
  11. package/dist/notrace/{action-creator-BWd9FWt6.d.ts → action-creator-JUwIsFUl.d.ts} +1 -1
  12. package/dist/notrace/actions.d.ts +2 -2
  13. package/dist/notrace/effects.d.ts +2 -2
  14. package/dist/notrace/index.d.ts +1 -1
  15. package/dist/notrace/{plugin-DmAYT3Xk.d.ts → plugin-dLdTM2JL.d.ts} +1 -1
  16. package/dist/notrace/policies.d.ts +158 -2
  17. package/dist/notrace/policies.js +1 -1
  18. package/dist/notrace/redux.d.ts +1 -1
  19. package/dist/observable.d.ts +1 -1
  20. package/dist/oop.d.ts +1 -1
  21. package/dist/{plugin-2d3uuW7o.d.ts → plugin-B8La3K9m.d.ts} +2 -2
  22. package/dist/policies.d.ts +159 -3
  23. package/dist/policies.js +1 -1
  24. package/dist/react.d.ts +2 -2
  25. package/dist/redux.d.ts +1 -1
  26. package/dist/scope.d.ts +2 -2
  27. package/dist/signal.d.ts +2 -2
  28. package/dist/svelte.d.ts +1 -1
  29. package/dist/testing.d.ts +1 -1
  30. package/dist/trace.d.ts +1 -1
  31. package/dist/{types-DxPZDzZG.d.ts → types-ByoeMqVh.d.ts} +2 -2
  32. package/dist/vue.d.ts +1 -1
  33. package/dist/{with-policy-Y12d-yx6.d.ts → with-policy-e4yx1vhN.d.ts} +1 -1
  34. package/docs/package.md +1 -1
  35. package/docs/policies.md +188 -0
  36. package/docs/recipes.md +90 -0
  37. package/docs/ru/package.md +1 -1
  38. package/docs/ru/policies.md +188 -0
  39. package/docs/ru/recipes.md +90 -0
  40. package/llms-full.txt +279 -1
  41. package/llms.txt +1 -1
  42. package/package.json +2 -2
@@ -10,7 +10,7 @@ type PayloadOf<P> = undefined extends P ? [payload?: P] : [payload: P];
10
10
  type EventMap = Record<string, unknown>;
11
11
  type Keys<E> = keyof E & string;
12
12
  type Task<P, E extends EventMap, R = unknown> = (payload: P, ctx: Context<E>) => R;
13
- type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "allSettled" | "action" | "emit";
13
+ type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "dedupe" | "distinct" | "rateLimit" | "batch" | "allSettled" | "action" | "emit";
14
14
  type Phase = "start" | "done" | "error" | "cancel" | "drop";
15
15
  type TraceEvent<E = Record<string, unknown>> = { [K in Keys<E>]: {
16
16
  id: number;
package/dist/actions.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { G as PayloadOf, H as EventMap, T as EventKey, a as FreeActionCreator, c as Scope, i as Free, n as Call, q as Task, t as ActionCreator, u as WithScope, v as Bus } from "./action-creator-DprJV-pN.js";
2
- import { r as Scoped, t as FieldsOfScope } from "./types-DxPZDzZG.js";
3
- import { a as createModule, c as MadeHandled, l as ScopedHandled, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as CarryingCalls, t as Module, u as actionsPlugin } from "./module-Fk4OtkZk.js";
1
+ import { G as PayloadOf, H as EventMap, T as EventKey, a as FreeActionCreator, c as Scope, i as Free, n as Call, q as Task, t as ActionCreator, u as WithScope, v as Bus } from "./action-creator-CXIq6GWK.js";
2
+ import { r as Scoped, t as FieldsOfScope } from "./types-ByoeMqVh.js";
3
+ import { a as createModule, c as MadeHandled, l as ScopedHandled, n as ModuleApi, o as modulePlugin, r as ModuleContext, s as CarryingCalls, t as Module, u as actionsPlugin } from "./module-BXNaEXE9.js";
4
4
  import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
5
5
  //#region src/actions/action.d.ts
6
6
  type Reserved = "handle" | "prepare";
@@ -1,4 +1,4 @@
1
- import { H as EventMap, x as ContextOf } from "./action-creator-DprJV-pN.js";
1
+ import { H as EventMap, x as ContextOf } from "./action-creator-CXIq6GWK.js";
2
2
  //#region src/core/signal-field-key.d.ts
3
3
  /**
4
4
  * Where `fromSignal` keeps the function that makes a context field from the signal of a
package/dist/context.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as WithContext, H as EventMap, v as Bus } from "./action-creator-DprJV-pN.js";
2
- import { i as Resolved, r as NoClash, t as ContextTask } from "./context-types-BiTMp_lW.js";
1
+ import { F as WithContext, H as EventMap, v as Bus } from "./action-creator-CXIq6GWK.js";
2
+ import { i as Resolved, r as NoClash, t as ContextTask } from "./context-types-BO1QE6W2.js";
3
3
  //#region src/context/plugin.d.ts
4
4
  /**
5
5
  * Puts `fields` on the context of every task of the bus: a store, a client, a
package/dist/dev.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as EventMap, Q as UnsubscribeCallback, v as Bus } from "./action-creator-DprJV-pN.js";
2
- import { i as WithApp, n as ModuleApi } from "./module-Fk4OtkZk.js";
1
+ import { H as EventMap, Q as UnsubscribeCallback, v as Bus } from "./action-creator-CXIq6GWK.js";
2
+ import { i as WithApp, n as ModuleApi } from "./module-BXNaEXE9.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 { H as EventMap, I as WithSignal, b as Context, f as Effect, q as Task } from "./action-creator-DprJV-pN.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-2d3uuW7o.js";
1
+ import { H as EventMap, I as WithSignal, b as Context, f as Effect, q as Task } from "./action-creator-CXIq6GWK.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-B8La3K9m.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
package/dist/guard.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as EventMap, v as Bus } from "./action-creator-DprJV-pN.js";
1
+ import { H as EventMap, v as Bus } from "./action-creator-CXIq6GWK.js";
2
2
  //#region src/guard/plugin.d.ts
3
3
  /** What a guard found when it refused an emit. */
4
4
  type LimitFinding = {
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as HandledCall, C as Emit, D as EventPayload, E as EventLike, F as WithContext, G as PayloadOf, H as EventMap, I as WithSignal, L as WithType, M as HandlerRef, N as Off, O as EventsOf, P as On, Q as UnsubscribeCallback, R as createBus, S as ContextOption, T as EventKey, U as Keys, _ as AnyEvent, b as Context, g as Actions, h as Action, j as Handler, k as Handled, n as Call, o as WithPayload, q as Task, v as Bus, w as Emittable, x as ContextOf, y as BusOptions } from "./action-creator-DprJV-pN.js";
1
+ import { A as HandledCall, C as Emit, D as EventPayload, E as EventLike, F as WithContext, G as PayloadOf, H as EventMap, I as WithSignal, L as WithType, M as HandlerRef, N as Off, O as EventsOf, P as On, Q as UnsubscribeCallback, R as createBus, S as ContextOption, T as EventKey, U as Keys, _ as AnyEvent, b as Context, g as Actions, h as Action, j as Handler, k as Handled, n as Call, o as WithPayload, q as Task, v as Bus, w as Emittable, x as ContextOf, y as BusOptions } from "./action-creator-CXIq6GWK.js";
2
2
  export { type Action, type Actions, type AnyEvent, type Bus, type BusOptions, type Call, type Context, type ContextOf, type ContextOption, type Emit, type Emittable, type EventKey, type EventLike, type EventMap, type EventPayload, type EventsOf, type Handled, type HandledCall, type Handler, type HandlerRef, type Keys, type Off, type On, type PayloadOf, type Task, type UnsubscribeCallback, type WithContext, type WithPayload, type WithSignal, type WithType, createBus };
package/dist/match.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as EventPayload, H as EventMap, Q as UnsubscribeCallback, h as Action, q as Task, v as Bus } from "./action-creator-DprJV-pN.js";
1
+ import { D as EventPayload, H as EventMap, Q as UnsubscribeCallback, h as Action, q as Task, v as Bus } from "./action-creator-CXIq6GWK.js";
2
2
  //#region src/match/plugin.d.ts
3
3
  /** A function over the action of an event: `{ type, payload }`. */
4
4
  type Predicate<E extends EventMap> = (action: Action<E>) => boolean;
@@ -1,5 +1,5 @@
1
- import { A as HandledCall, G as PayloadOf, H as EventMap, Q as UnsubscribeCallback, b as Context, c as Scope, g as Actions, k as Handled, q as Task, u as WithScope, v as Bus, z as handledCall } from "./action-creator-DprJV-pN.js";
2
- import { n as ScopeSlots, r as Scoped } from "./types-DxPZDzZG.js";
1
+ import { A as HandledCall, G as PayloadOf, H as EventMap, Q as UnsubscribeCallback, b as Context, c as Scope, g as Actions, k as Handled, q as Task, u as WithScope, v as Bus, z as handledCall } from "./action-creator-CXIq6GWK.js";
2
+ import { n as ScopeSlots, r as Scoped } from "./types-ByoeMqVh.js";
3
3
  //#region src/actions/handled.d.ts
4
4
  /** What `createAction` returns: an action that also tells whether an action is of its type. */
5
5
  type MadeHandled<P, R, T extends string> = Handled<P, R> & {
@@ -10,7 +10,7 @@ type PayloadOf<P> = undefined extends P ? [payload?: P] : [payload: P];
10
10
  type EventMap = Record<string, unknown>;
11
11
  type Keys<E> = keyof E & string;
12
12
  type Task<P, E extends EventMap, R = unknown> = (payload: P, ctx: Context<E>) => R;
13
- type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "allSettled" | "action" | "emit";
13
+ type EffectName = "every" | "latest" | "leading" | "debounce" | "throttle" | "run" | "all" | "race" | "retry" | "timeout" | "poll" | "take" | "queue" | "dedupe" | "distinct" | "rateLimit" | "batch" | "allSettled" | "action" | "emit";
14
14
  type Phase = "start" | "done" | "error" | "cancel" | "drop";
15
15
  type UnsubscribeCallback = () => void;
16
16
  //#endregion
@@ -1,5 +1,5 @@
1
- import { B as Task, D as HandledCall, E as Handled, I as handledCall, L as EventMap, S as EventKey, V as UnsubscribeCallback, _ as Context, c as WithScope, d as Effects, h as Bus, i as FreeActionCreator, n as Call, o as Scope, p as Actions, r as Free, s as WithFields, t as ActionCreator, z as PayloadOf } from "./action-creator-BWd9FWt6.js";
2
- import { t as BoundOf } from "./plugin-DmAYT3Xk.js";
1
+ import { B as Task, D as HandledCall, E as Handled, I as handledCall, L as EventMap, S as EventKey, V as UnsubscribeCallback, _ as Context, c as WithScope, d as Effects, h as Bus, i as FreeActionCreator, n as Call, o as Scope, p as Actions, r as Free, s as WithFields, t as ActionCreator, z as PayloadOf } from "./action-creator-JUwIsFUl.js";
2
+ import { t as BoundOf } from "./plugin-dLdTM2JL.js";
3
3
  import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
4
4
  //#region src/scope/types.d.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { B as Task, L as EventMap, N as WithSignal, _ as Context, u as Effect } from "./action-creator-BWd9FWt6.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-DmAYT3Xk.js";
1
+ import { B as Task, L as EventMap, N as WithSignal, _ as Context, u as Effect } from "./action-creator-JUwIsFUl.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-dLdTM2JL.js";
3
3
  //#region src/utils/onAbort.d.ts
4
4
  export declare const onAbort: (ctx: {
5
5
  signal?: AbortSignal | undefined;
@@ -1,2 +1,2 @@
1
- import { A as Off, B as Task, C as EventLike, D as HandledCall, E as Handled, F as createBus, L as EventMap, M as WithContext, N as WithSignal, O as Handler, P as WithType, R as Keys, S as EventKey, T as EventsOf, V as UnsubscribeCallback, _ as Context, a as WithPayload, b as Emit, f as Action, g as BusOptions, h as Bus, j as On, k as HandlerRef, m as AnyEvent, n as Call, p as Actions, v as ContextOf, w as EventPayload, x as Emittable, y as ContextOption, z as PayloadOf } from "./action-creator-BWd9FWt6.js";
1
+ import { A as Off, B as Task, C as EventLike, D as HandledCall, E as Handled, F as createBus, L as EventMap, M as WithContext, N as WithSignal, O as Handler, P as WithType, R as Keys, S as EventKey, T as EventsOf, V as UnsubscribeCallback, _ as Context, a as WithPayload, b as Emit, f as Action, g as BusOptions, h as Bus, j as On, k as HandlerRef, m as AnyEvent, n as Call, p as Actions, v as ContextOf, w as EventPayload, x as Emittable, y as ContextOption, z as PayloadOf } from "./action-creator-JUwIsFUl.js";
2
2
  export { type Action, type Actions, type AnyEvent, type Bus, type BusOptions, type Call, type Context, type ContextOf, type ContextOption, type Emit, type Emittable, type EventKey, type EventLike, type EventMap, type EventPayload, type EventsOf, type Handled, type HandledCall, type Handler, type HandlerRef, type Keys, type Off, type On, type PayloadOf, type Task, type UnsubscribeCallback, type WithContext, type WithPayload, type WithSignal, type WithType, createBus };
@@ -1,4 +1,4 @@
1
- import { L as EventMap, M as WithContext, R as Keys, _ as Context, d as Effects, h as Bus, i as FreeActionCreator, l as BoundForm, t as ActionCreator, v as ContextOf } from "./action-creator-BWd9FWt6.js";
1
+ import { L as EventMap, M as WithContext, R as Keys, _ as Context, d as Effects, h as Bus, i as FreeActionCreator, l as BoundForm, t as ActionCreator, v as ContextOf } from "./action-creator-JUwIsFUl.js";
2
2
  //#region src/core/context-types.d.ts
3
3
  /**
4
4
  * `unknown` when none of the `fields` is already a context field of the bus,
@@ -1,4 +1,4 @@
1
- import { B as Task, L as EventMap, z as PayloadOf } from "./action-creator-BWd9FWt6.js";
1
+ import { B as Task, L as EventMap, z as PayloadOf } from "./action-creator-JUwIsFUl.js";
2
2
  //#region src/policies/keyed.d.ts
3
3
  /** Options shared by every policy that can keep its state per key. */
4
4
  type KeyOption<P> = {
@@ -18,6 +18,45 @@ type Keyed<O, P> = O & {
18
18
  key: (payload: P) => unknown;
19
19
  };
20
20
  //#endregion
21
+ //#region src/policies/batch.d.ts
22
+ type BatchOptions<P = never> = KeyOption<P> & {
23
+ /** Send the batch at once when it holds this many payloads. Default: no limit. */
24
+ maxSize?: number;
25
+ };
26
+ /** What `batch(ms)` returns: it turns a task that takes an array into a `batch` task. */
27
+ type BatchWrapper = <P, E extends EventMap, R>(fn: Task<P[], E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
28
+ /** What `batch(ms, { key })` returns: the payload type comes from `key`. */
29
+ type KeyedBatchWrapper<P> = <E extends EventMap, R>(fn: Task<P[], E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
30
+ /**
31
+ * Collects the payloads of the calls that come in a window of `ms`, then
32
+ * calls `fn` once with all of them, as an array in the order of the calls.
33
+ * The window opens at the first call and does not move when more calls come
34
+ * (it is not a debounce); with `options.maxSize` a full batch is sent at once.
35
+ *
36
+ * Every call returns a promise with what `fn` returned for its batch: the
37
+ * same value for all of them, or the same error. `fn` gets the context of the
38
+ * first caller that is still waiting; if its task aborts while `fn` runs, the
39
+ * run is aborted and the callers of that batch resolve with `undefined`.
40
+ * A call that aborts while the batch is collecting is taken out of it. With
41
+ * `options.key` each key collects its own batch.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * bus.on(
46
+ * "track",
47
+ * batch(500, async (events) => {
48
+ * await api.sendEvents(events);
49
+ * }),
50
+ * );
51
+ *
52
+ * bus.emit("track", { name: "open" });
53
+ * bus.emit("track", { name: "click" }); // both go in one request, 500 ms later
54
+ * ```
55
+ */
56
+ export declare function batch<P, E extends EventMap, R>(ms: number, fn: Task<P[], E, R>, options?: BatchOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
57
+ export declare function batch(ms: number, options?: Unkeyed<BatchOptions>): BatchWrapper;
58
+ export declare function batch<P>(ms: number, options: Keyed<BatchOptions<P>, P>): KeyedBatchWrapper<P>;
59
+ //#endregion
21
60
  //#region src/policies/debounce.d.ts
22
61
  type DebounceResult<R> = Promise<R | undefined> | Promise<Awaited<R> | undefined> | undefined;
23
62
  type DebounceOptions<P = never> = KeyOption<P> & {
@@ -54,6 +93,81 @@ export declare function debounce<P, E extends EventMap, R>(ms: number, fn: Task<
54
93
  export declare function debounce(ms: number, options?: Unkeyed<DebounceOptions>): DebounceWrapper;
55
94
  export declare function debounce<P>(ms: number, options: Keyed<DebounceOptions<P>, P>): KeyedDebounceWrapper<P>;
56
95
  //#endregion
96
+ //#region src/policies/dedupe.d.ts
97
+ type DedupeOptions<P = never> = KeyOption<P>;
98
+ /** What `dedupe()` returns: it turns a task into a `dedupe` task. */
99
+ type DedupeWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
100
+ /** What `dedupe({ key })` returns: the payload type comes from `key`. */
101
+ type KeyedDedupeWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
102
+ /**
103
+ * Calls with the same key that come while a run is going wait for that run
104
+ * instead of starting their own: `fn` runs once, and every caller gets its
105
+ * result, or its error. Nothing is kept after the run settles, so this is
106
+ * not a cache: the next call starts `fn` again.
107
+ *
108
+ * The key is the payload itself (compared like a `Map` key) unless
109
+ * `options.key` says otherwise; `key: () => "all"` shares one run between
110
+ * every call.
111
+ *
112
+ * The run belongs to the task of the first caller. A caller whose task aborts
113
+ * resolves with `undefined` and the others go on; when it is the first caller
114
+ * that aborts, the run is aborted and started again with the context of the
115
+ * first caller that is still waiting, so `fn` may run twice for one request:
116
+ * use it for reads, not for writes.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * bus.on(
121
+ * "user/load",
122
+ * dedupe(async (id, { signal }) => api.getUser(id, { signal })),
123
+ * );
124
+ *
125
+ * bus.emit("user/load", 1); // runs
126
+ * bus.emit("user/load", 1); // waits for the first run, one request in all
127
+ * ```
128
+ */
129
+ export declare function dedupe<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: DedupeOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
130
+ export declare function dedupe(options?: Unkeyed<DedupeOptions>): DedupeWrapper;
131
+ export declare function dedupe<P>(options: Keyed<DedupeOptions<P>, P>): KeyedDedupeWrapper<P>;
132
+ //#endregion
133
+ //#region src/policies/distinct.d.ts
134
+ type DistinctOptions<P = never> = KeyOption<P> & {
135
+ /** Tells whether two payloads are the same one. Default: `Object.is`. */
136
+ equals?: (previous: P, next: P) => boolean;
137
+ };
138
+ /** What `distinct()` returns: it turns a task into a `distinct` task. */
139
+ type DistinctWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
140
+ /** What `distinct({ key })` returns: the payload type comes from `key`. */
141
+ type KeyedDistinctWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
142
+ /**
143
+ * Skips a call whose payload equals the payload of the last call that was
144
+ * let through (`Object.is`, or `options.equals`). A skipped call does not run
145
+ * the handler and returns `undefined`. The first call is always let through.
146
+ *
147
+ * Only the last payload is kept, never a result. A payload is remembered from
148
+ * the moment its run starts, so the same payload that comes while it runs is
149
+ * skipped; it is forgotten when the run fails or its task aborts, so a retry
150
+ * runs. With `options.key` each key remembers its own payload. That memory is
151
+ * the point of the policy, so it is not dropped when a key is idle: take keys
152
+ * from a bounded set.
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * bus.on(
157
+ * "draft/save",
158
+ * distinct(async (draft) => {
159
+ * await api.save(draft);
160
+ * }),
161
+ * );
162
+ *
163
+ * bus.emit("draft/save", "text"); // runs
164
+ * bus.emit("draft/save", "text"); // skipped, the same text
165
+ * ```
166
+ */
167
+ export declare function distinct<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: DistinctOptions<P>): Task<P, E, R | Promise<Awaited<R>> | undefined>;
168
+ export declare function distinct(options?: Unkeyed<DistinctOptions>): DistinctWrapper;
169
+ export declare function distinct<P>(options: Keyed<DistinctOptions<P>, P>): KeyedDistinctWrapper<P>;
170
+ //#endregion
57
171
  //#region src/policies/latest.d.ts
58
172
  type LatestOptions<P = never> = KeyOption<P>;
59
173
  type LatestResult<R> = R | Promise<Awaited<R> | undefined> | undefined;
@@ -172,6 +286,48 @@ export declare function queue<P, E extends EventMap, R>(fn: Task<P, E, R>, optio
172
286
  export declare function queue(options?: Unkeyed<QueueOptions>): QueueWrapper;
173
287
  export declare function queue<P>(options: Keyed<QueueOptions<P>, P>): KeyedQueueWrapper<P>;
174
288
  //#endregion
289
+ //#region src/policies/rate-limit.d.ts
290
+ type RateLimitOptions<P = never> = KeyOption<P> & {
291
+ /**
292
+ * What to do with a call that arrives when the window is full: keep it
293
+ * until it can start (`"wait"`, the default) or drop it (`"drop"`; the call
294
+ * resolves with `undefined`).
295
+ */
296
+ overflow?: "wait" | "drop";
297
+ };
298
+ /** What `rateLimit(limit, ms)` returns: it turns a task into a `rateLimit` task. */
299
+ type RateLimitWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
300
+ /** What `rateLimit(limit, ms, { key })` returns: the payload type comes from `key`. */
301
+ type KeyedRateLimitWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
302
+ /**
303
+ * At most `limit` runs start in any window of `ms` milliseconds (a sliding
304
+ * window, counted back from each call), for an API with a quota. A call over
305
+ * the limit waits and starts, in the order of the calls, when the oldest start
306
+ * leaves the window; with `overflow: "drop"` it is dropped instead.
307
+ *
308
+ * It limits starts, not how many runs go at the same time: put `queue` around
309
+ * it for that. Every call returns a promise with the result of its own run;
310
+ * the task of a call that aborts while it waits leaves the line, and aborting
311
+ * a run that started does not give its place in the window back. With
312
+ * `options.key` each key has its own window; the state of a key is dropped
313
+ * once its window is empty. A `limit` below 1 is 1; `ms` follows `setTimer`.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * bus.on(
318
+ * "geocode",
319
+ * rateLimit(5, 1000, async (address, { signal }) => {
320
+ * return api.geocode(address, { signal });
321
+ * }),
322
+ * );
323
+ *
324
+ * // the first five calls in a second run at once, the rest wait for the window
325
+ * ```
326
+ */
327
+ export declare function rateLimit<P, E extends EventMap, R>(limit: number, ms: number, fn: Task<P, E, R>, options?: RateLimitOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
328
+ export declare function rateLimit(limit: number, ms: number, options?: Unkeyed<RateLimitOptions>): RateLimitWrapper;
329
+ export declare function rateLimit<P>(limit: number, ms: number, options: Keyed<RateLimitOptions<P>, P>): KeyedRateLimitWrapper<P>;
330
+ //#endregion
175
331
  //#region src/policies/throttle.d.ts
176
332
  type ThrottleOptions<P = never> = KeyOption<P> & {
177
333
  /** Run the first call at once, when the throttle is idle. Default `true`. */
@@ -241,4 +397,4 @@ type PolicyFunction<P, R> = {
241
397
  */
242
398
  export declare const withPolicy: <P, R>(task: Task<P, EventMap, R>) => PolicyFunction<P, R>;
243
399
  //#endregion
244
- export type { DebounceOptions, LatestOptions, LeadingOptions, PolicyFunction, QueueOptions, ThrottleOptions };
400
+ export type { BatchOptions, DebounceOptions, DedupeOptions, DistinctOptions, LatestOptions, LeadingOptions, PolicyFunction, QueueOptions, RateLimitOptions, ThrottleOptions };
@@ -1 +1 @@
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"./lifecycle-key-8iX8RUVD.js";const d=e=>typeof e!=`object`||!e?!1:`then`in e&&typeof e.then==`function`,f=(e,t)=>d(e)?Promise.resolve(e).finally(t):(t(),e),p=e=>Reflect.get(e,u),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,l,!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,l)=>{if(r?.abort(),l.signal.aborted)return;let{ctx:u,unlink:f}=a(l);r=u;let p=c(u,e),h=!1,g=()=>{u.signal.aborted||(h=!0,m(u),s(u,e,`start`))};i(u,e=>{v(u,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),r===u&&(r=null,n())},y=e=>{if(!u.signal.aborted)return p(h?`done`:`drop`),e};try{let e=t(o,u,g);return d(e)?Promise.resolve(e).then(y,e=>{if(!u.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),u.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 f(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
+ 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"./lifecycle-key-8iX8RUVD.js";const d=e=>typeof e!=`object`||!e?!1:`then`in e&&typeof e.then==`function`,f=(e,t)=>d(e)?Promise.resolve(e).finally(t):(t(),e),p=e=>Reflect.get(e,u),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,l,!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),s=!1;if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e),s=!0}let c=i.signal.aborted;try{return o(r,i)}finally{s&&c&&n.get(a)===o&&n.delete(a)}}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t,n){return x(t,n,(t,n)=>E(e,t,n))}const T=e=>typeof e==`number`?e>=1?Math.floor(e):1:1/0,E=(e,t,n)=>{let r=T(n.maxSize);return C(n.key,n=>D(e,r,t,n))},D=(n,r,a,o)=>{let s=[],c=null,l=0,u=()=>{s.length===0&&l===0&&o()},d=()=>{c&&=(e(c),null)},f=(e,t)=>{for(let n of e.members)`error`in t?n.reject(t.error):n.resolve(t.value)},p=(e,t)=>{l--;let[n]=e.members;n&&!e.dead&&_(n.ctx,t);for(let t of e.members)t.stop(),t!==n&&g(t.ctx,`batch`);u(),e.dead||f(e,t)},m=()=>{d();let e=s;s=[];let[t]=e;if(!t){u();return}let n={members:e,dead:!1};for(let t of e)t.run=n;l++;let r=e.map(e=>e.payload),i;try{i=Promise.resolve(h(t.ctx,`batch`,()=>a(r,t.ctx)))}catch(e){i=Promise.reject(e)}i.then(e=>p(n,{value:e}),e=>p(n,{error:e}))},v=e=>{let t=e.run;if(!t)s.splice(s.indexOf(e),1),g(e.ctx,`batch`),e.resolve(void 0),s.length===0&&(d(),u());else if(e.resolve(void 0),e===t.members[0]){t.dead=!0;for(let e of t.members)e.resolve(void 0)}};return(e,a)=>new Promise((o,l)=>{if(a.signal.aborted){o(void 0);return}let u={payload:e,ctx:a,resolve:o,reject:l,stop:i(a,()=>v(u))};s.push(u),s.length>=r?m():s.length===1&&(c=t(m,n))})};function O(e,t){return x(e,t,k)}const k=(e,t)=>C(t.key,t=>A(`latest`,(t,n,r)=>(r(),e(t,n)),t)),A=(e,t,n=b)=>{let r=null;return(o,l)=>{if(r?.abort(),l.signal.aborted)return;let{ctx:u,unlink:f}=a(l);r=u;let p=c(u,e),h=!1,g=()=>{u.signal.aborted||(h=!0,m(u),s(u,e,`start`))};i(u,e=>{v(u,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),r===u&&(r=null,n())},y=e=>{if(!u.signal.aborted)return p(h?`done`:`drop`),e};try{let e=t(o,u,g);return d(e)?Promise.resolve(e).then(y,e=>{if(!u.signal.aborted)throw p(`error`,e),e}).finally(_):(_(),y(e))}catch(e){if(_(),u.signal.aborted)return;throw p(`error`,e),e}}};function j(e,t,n){return x(t,n,(t,n)=>M(e,t,n))}const M=(e,t,n)=>C(n.key,r=>P(e,t,n,r)),N=(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))}},P=(e,t,r,a)=>{let o=r.leading??!1,s=r.trailing??!0;if(!s)return N(e,t,o,a);let c=!1,l=0,u=A(`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 F(e,t){return x(e,t,L)}const I=e=>e,L=(e,t)=>C(t.key??I,t=>R(e,t)),R=(e,t)=>{let n=[],r=0,a=(e,i)=>{if(e!==r)return;let[a]=n;a&&_(a.ctx,i);let o=n.splice(0);for(let e of o)e.stop(),e!==a&&g(e.ctx,`dedupe`);t();for(let e of o)`error`in i?e.reject(i.error):e.resolve(i.value)},o=()=>{let[t]=n;if(!t)return;r++;let i=r,o;try{o=Promise.resolve(h(t.ctx,`dedupe`,()=>e(t.payload,t.ctx)))}catch(e){o=Promise.reject(e)}o.then(e=>a(i,{value:e}),e=>a(i,{error:e}))},s=(e,i)=>{let a=n.indexOf(e);a<0||(n.splice(a,1),e.resolve(void 0),v(e.ctx,a===0,i),a===0&&(r++,n.length>0?o():t()))};return(e,t)=>new Promise((r,a)=>{if(t.signal.aborted){r(void 0);return}let c={payload:e,ctx:t,resolve:r,reject:a,stop:i(t,e=>s(c,e))};n.push(c),n.length===1&&o()})};function z(e,t){return x(e,t,B)}const B=(e,t)=>{let n=t.equals??Object.is;return C(t.key,()=>{let t=null;return(r,a)=>{if(a.signal.aborted)return;if(t&&n(t.payload,r)){g(a,`distinct`);return}let o={payload:r};t=o;let s=()=>{t===o&&(t=null)},c=i(a,s);try{let t=h(a,`distinct`,()=>e(r,a));return d(t)?Promise.resolve(t).then(e=>(c(),e),e=>{throw c(),s(),e}):(c(),t)}catch(e){throw c(),s(),e}}})};function V(e,t){return x(e,t,H)}const H=(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 f(h(a,`leading`,()=>e(r,a)),s)}catch(e){throw s(),e}}});function U(e,t){return x(e,t,W)}const W=(e,t)=>C(t.key,n=>G(e,t,n)),G=(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 K(e,t,n,r){return x(n,r,(n,r)=>q(e,t,n,r))}const q=(e,t,n,r)=>{let i=e>=1?Math.floor(e):1;return C(r.key,e=>J(i,t,r.overflow===`drop`,n,e))},J=(n,r,a,o,s)=>{let c=[],l=[],u=null,d=()=>{let e=Date.now();for(;c.length>0&&(c[0]??0)+r<=e;)c.shift()},f=()=>{u&&=(e(u),null);let[n]=c;n===void 0?l.length===0&&s():u=t(p,n+r-Date.now())};function p(){for(u=null,d();l.length>0&&c.length<n;)l.shift()?.start();f()}return(e,t)=>new Promise((r,s)=>{if(t.signal.aborted){r(void 0);return}let u=b,p=()=>{u(),g(t,`rateLimit`),r(void 0)},m=()=>{if(u(),t.signal.aborted){p();return}c.push(Date.now());let n=i(t,()=>r(void 0)),a;try{a=Promise.resolve(h(t,`rateLimit`,()=>o(e,t)))}catch(e){a=Promise.reject(e)}a.then(e=>{n(),_(t,{value:e}),r(t.signal.aborted?void 0:e)},e=>{n(),_(t,{error:e}),t.signal.aborted?r(void 0):s(e)})};if(d(),l.length===0&&c.length<n){m(),f();return}if(a){p();return}let v={start:m,drop:p};l.push(v),u=i(t,()=>{let e=l.indexOf(v);e>=0&&l.splice(e,1),p(),l.length===0&&c.length===0&&f()}),f()})};function Y(e,t,n){return x(t,n,(t,n)=>X(e,t,n))}const X=(e,t,n)=>C(n.key,r=>Z(e,t,n,r)),Z=(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)}},Q=Reflect.get(Symbol,`dispose`),$=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 Q&&Reflect.set(i,Q,()=>r()),i};export{w as batch,j as debounce,F as dedupe,z as distinct,O as latest,V as leading,U as queue,K as rateLimit,Y as throttle,$ as withPolicy};
@@ -1,4 +1,4 @@
1
- import { L as EventMap, h as Bus } from "./action-creator-BWd9FWt6.js";
1
+ import { L as EventMap, h as Bus } from "./action-creator-JUwIsFUl.js";
2
2
  import { t as OriginOptions } from "./origin-key-CxK0SkeG.js";
3
3
  //#region src/store/redux/middleware.d.ts
4
4
  /** What Redux passes through a middleware: an action is a plain object with a `type`. */
@@ -1,4 +1,4 @@
1
- import { H as EventMap, P as On, U as Keys, a as FreeActionCreator, k as Handled, r as DataOf, t as ActionCreator, v as Bus } from "./action-creator-DprJV-pN.js";
1
+ import { H as EventMap, P as On, U as Keys, a as FreeActionCreator, k as Handled, r as DataOf, t as ActionCreator, v as Bus } from "./action-creator-CXIq6GWK.js";
2
2
  //#region src/observable.d.ts
3
3
  declare global {
4
4
  interface SymbolConstructor {
package/dist/oop.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as EventMap, W as ListenerOptions, k as Handled, t as ActionCreator, v as Bus } from "./action-creator-DprJV-pN.js";
1
+ import { H as EventMap, W as ListenerOptions, k as Handled, t as ActionCreator, v as Bus } from "./action-creator-CXIq6GWK.js";
2
2
  //#region src/oop/types.d.ts
3
3
  type Slots = "ctx" | "actions" | "trace" | "addContext" | "applyScope" | "fitScope" | "app" | "use";
4
4
  type AnyFunction = (...args: never[]) => unknown;
@@ -1,5 +1,5 @@
1
- import { F as WithContext, H as EventMap, U as Keys, a as FreeActionCreator, b as Context, d as BoundForm, p as Effects, t as ActionCreator, v as Bus } from "./action-creator-DprJV-pN.js";
2
- import { r as NoClash } from "./context-types-BiTMp_lW.js";
1
+ import { F as WithContext, H as EventMap, U as Keys, a as FreeActionCreator, b as Context, d as BoundForm, p as Effects, t as ActionCreator, v as Bus } from "./action-creator-CXIq6GWK.js";
2
+ import { r as NoClash } from "./context-types-BO1QE6W2.js";
3
3
  //#region src/utils/delay.d.ts
4
4
  type Milliseconds = number | (() => number);
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { H as EventMap, q as Task } from "./action-creator-DprJV-pN.js";
2
- import { n as withPolicy, t as PolicyFunction } from "./with-policy-Y12d-yx6.js";
1
+ import { H as EventMap, q as Task } from "./action-creator-CXIq6GWK.js";
2
+ import { n as withPolicy, t as PolicyFunction } from "./with-policy-e4yx1vhN.js";
3
3
  //#region src/policies/keyed.d.ts
4
4
  /** Options shared by every policy that can keep its state per key. */
5
5
  type KeyOption<P> = {
@@ -19,6 +19,45 @@ type Keyed<O, P> = O & {
19
19
  key: (payload: P) => unknown;
20
20
  };
21
21
  //#endregion
22
+ //#region src/policies/batch.d.ts
23
+ type BatchOptions<P = never> = KeyOption<P> & {
24
+ /** Send the batch at once when it holds this many payloads. Default: no limit. */
25
+ maxSize?: number;
26
+ };
27
+ /** What `batch(ms)` returns: it turns a task that takes an array into a `batch` task. */
28
+ type BatchWrapper = <P, E extends EventMap, R>(fn: Task<P[], E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
29
+ /** What `batch(ms, { key })` returns: the payload type comes from `key`. */
30
+ type KeyedBatchWrapper<P> = <E extends EventMap, R>(fn: Task<P[], E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
31
+ /**
32
+ * Collects the payloads of the calls that come in a window of `ms`, then
33
+ * calls `fn` once with all of them, as an array in the order of the calls.
34
+ * The window opens at the first call and does not move when more calls come
35
+ * (it is not a debounce); with `options.maxSize` a full batch is sent at once.
36
+ *
37
+ * Every call returns a promise with what `fn` returned for its batch: the
38
+ * same value for all of them, or the same error. `fn` gets the context of the
39
+ * first caller that is still waiting; if its task aborts while `fn` runs, the
40
+ * run is aborted and the callers of that batch resolve with `undefined`.
41
+ * A call that aborts while the batch is collecting is taken out of it. With
42
+ * `options.key` each key collects its own batch.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * bus.on(
47
+ * "track",
48
+ * batch(500, async (events) => {
49
+ * await api.sendEvents(events);
50
+ * }),
51
+ * );
52
+ *
53
+ * bus.emit("track", { name: "open" });
54
+ * bus.emit("track", { name: "click" }); // both go in one request, 500 ms later
55
+ * ```
56
+ */
57
+ export declare function batch<P, E extends EventMap, R>(ms: number, fn: Task<P[], E, R>, options?: BatchOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
58
+ export declare function batch(ms: number, options?: Unkeyed<BatchOptions>): BatchWrapper;
59
+ export declare function batch<P>(ms: number, options: Keyed<BatchOptions<P>, P>): KeyedBatchWrapper<P>;
60
+ //#endregion
22
61
  //#region src/policies/debounce.d.ts
23
62
  type DebounceResult<R> = Promise<R | undefined> | Promise<Awaited<R> | undefined> | undefined;
24
63
  type DebounceOptions<P = never> = KeyOption<P> & {
@@ -55,6 +94,81 @@ export declare function debounce<P, E extends EventMap, R>(ms: number, fn: Task<
55
94
  export declare function debounce(ms: number, options?: Unkeyed<DebounceOptions>): DebounceWrapper;
56
95
  export declare function debounce<P>(ms: number, options: Keyed<DebounceOptions<P>, P>): KeyedDebounceWrapper<P>;
57
96
  //#endregion
97
+ //#region src/policies/dedupe.d.ts
98
+ type DedupeOptions<P = never> = KeyOption<P>;
99
+ /** What `dedupe()` returns: it turns a task into a `dedupe` task. */
100
+ type DedupeWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
101
+ /** What `dedupe({ key })` returns: the payload type comes from `key`. */
102
+ type KeyedDedupeWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
103
+ /**
104
+ * Calls with the same key that come while a run is going wait for that run
105
+ * instead of starting their own: `fn` runs once, and every caller gets its
106
+ * result, or its error. Nothing is kept after the run settles, so this is
107
+ * not a cache: the next call starts `fn` again.
108
+ *
109
+ * The key is the payload itself (compared like a `Map` key) unless
110
+ * `options.key` says otherwise; `key: () => "all"` shares one run between
111
+ * every call.
112
+ *
113
+ * The run belongs to the task of the first caller. A caller whose task aborts
114
+ * resolves with `undefined` and the others go on; when it is the first caller
115
+ * that aborts, the run is aborted and started again with the context of the
116
+ * first caller that is still waiting, so `fn` may run twice for one request:
117
+ * use it for reads, not for writes.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * bus.on(
122
+ * "user/load",
123
+ * dedupe(async (id, { signal }) => api.getUser(id, { signal })),
124
+ * );
125
+ *
126
+ * bus.emit("user/load", 1); // runs
127
+ * bus.emit("user/load", 1); // waits for the first run, one request in all
128
+ * ```
129
+ */
130
+ export declare function dedupe<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: DedupeOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
131
+ export declare function dedupe(options?: Unkeyed<DedupeOptions>): DedupeWrapper;
132
+ export declare function dedupe<P>(options: Keyed<DedupeOptions<P>, P>): KeyedDedupeWrapper<P>;
133
+ //#endregion
134
+ //#region src/policies/distinct.d.ts
135
+ type DistinctOptions<P = never> = KeyOption<P> & {
136
+ /** Tells whether two payloads are the same one. Default: `Object.is`. */
137
+ equals?: (previous: P, next: P) => boolean;
138
+ };
139
+ /** What `distinct()` returns: it turns a task into a `distinct` task. */
140
+ type DistinctWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
141
+ /** What `distinct({ key })` returns: the payload type comes from `key`. */
142
+ type KeyedDistinctWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, R | Promise<Awaited<R>> | undefined>;
143
+ /**
144
+ * Skips a call whose payload equals the payload of the last call that was
145
+ * let through (`Object.is`, or `options.equals`). A skipped call does not run
146
+ * the handler and returns `undefined`. The first call is always let through.
147
+ *
148
+ * Only the last payload is kept, never a result. A payload is remembered from
149
+ * the moment its run starts, so the same payload that comes while it runs is
150
+ * skipped; it is forgotten when the run fails or its task aborts, so a retry
151
+ * runs. With `options.key` each key remembers its own payload. That memory is
152
+ * the point of the policy, so it is not dropped when a key is idle: take keys
153
+ * from a bounded set.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * bus.on(
158
+ * "draft/save",
159
+ * distinct(async (draft) => {
160
+ * await api.save(draft);
161
+ * }),
162
+ * );
163
+ *
164
+ * bus.emit("draft/save", "text"); // runs
165
+ * bus.emit("draft/save", "text"); // skipped, the same text
166
+ * ```
167
+ */
168
+ export declare function distinct<P, E extends EventMap, R>(fn: Task<P, E, R>, options?: DistinctOptions<P>): Task<P, E, R | Promise<Awaited<R>> | undefined>;
169
+ export declare function distinct(options?: Unkeyed<DistinctOptions>): DistinctWrapper;
170
+ export declare function distinct<P>(options: Keyed<DistinctOptions<P>, P>): KeyedDistinctWrapper<P>;
171
+ //#endregion
58
172
  //#region src/policies/latest.d.ts
59
173
  type LatestOptions<P = never> = KeyOption<P>;
60
174
  type LatestResult<R> = R | Promise<Awaited<R> | undefined> | undefined;
@@ -173,6 +287,48 @@ export declare function queue<P, E extends EventMap, R>(fn: Task<P, E, R>, optio
173
287
  export declare function queue(options?: Unkeyed<QueueOptions>): QueueWrapper;
174
288
  export declare function queue<P>(options: Keyed<QueueOptions<P>, P>): KeyedQueueWrapper<P>;
175
289
  //#endregion
290
+ //#region src/policies/rate-limit.d.ts
291
+ type RateLimitOptions<P = never> = KeyOption<P> & {
292
+ /**
293
+ * What to do with a call that arrives when the window is full: keep it
294
+ * until it can start (`"wait"`, the default) or drop it (`"drop"`; the call
295
+ * resolves with `undefined`).
296
+ */
297
+ overflow?: "wait" | "drop";
298
+ };
299
+ /** What `rateLimit(limit, ms)` returns: it turns a task into a `rateLimit` task. */
300
+ type RateLimitWrapper = <P, E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
301
+ /** What `rateLimit(limit, ms, { key })` returns: the payload type comes from `key`. */
302
+ type KeyedRateLimitWrapper<P> = <E extends EventMap, R>(fn: Task<P, E, R>) => Task<P, E, Promise<Awaited<R> | undefined>>;
303
+ /**
304
+ * At most `limit` runs start in any window of `ms` milliseconds (a sliding
305
+ * window, counted back from each call), for an API with a quota. A call over
306
+ * the limit waits and starts, in the order of the calls, when the oldest start
307
+ * leaves the window; with `overflow: "drop"` it is dropped instead.
308
+ *
309
+ * It limits starts, not how many runs go at the same time: put `queue` around
310
+ * it for that. Every call returns a promise with the result of its own run;
311
+ * the task of a call that aborts while it waits leaves the line, and aborting
312
+ * a run that started does not give its place in the window back. With
313
+ * `options.key` each key has its own window; the state of a key is dropped
314
+ * once its window is empty. A `limit` below 1 is 1; `ms` follows `setTimer`.
315
+ *
316
+ * @example
317
+ * ```ts
318
+ * bus.on(
319
+ * "geocode",
320
+ * rateLimit(5, 1000, async (address, { signal }) => {
321
+ * return api.geocode(address, { signal });
322
+ * }),
323
+ * );
324
+ *
325
+ * // the first five calls in a second run at once, the rest wait for the window
326
+ * ```
327
+ */
328
+ export declare function rateLimit<P, E extends EventMap, R>(limit: number, ms: number, fn: Task<P, E, R>, options?: RateLimitOptions<P>): Task<P, E, Promise<Awaited<R> | undefined>>;
329
+ export declare function rateLimit(limit: number, ms: number, options?: Unkeyed<RateLimitOptions>): RateLimitWrapper;
330
+ export declare function rateLimit<P>(limit: number, ms: number, options: Keyed<RateLimitOptions<P>, P>): KeyedRateLimitWrapper<P>;
331
+ //#endregion
176
332
  //#region src/policies/throttle.d.ts
177
333
  type ThrottleOptions<P = never> = KeyOption<P> & {
178
334
  /** Run the first call at once, when the throttle is idle. Default `true`. */
@@ -214,4 +370,4 @@ export declare function throttle<P, E extends EventMap, R>(ms: number, fn: Task<
214
370
  export declare function throttle(ms: number, options?: Unkeyed<ThrottleOptions>): ThrottleWrapper;
215
371
  export declare function throttle<P>(ms: number, options: Keyed<ThrottleOptions<P>, P>): KeyedThrottleWrapper<P>;
216
372
  //#endregion
217
- export { type DebounceOptions, type LatestOptions, type LeadingOptions, type PolicyFunction, type QueueOptions, type ThrottleOptions, withPolicy };
373
+ export { type BatchOptions, type DebounceOptions, type DedupeOptions, type DistinctOptions, type LatestOptions, type LeadingOptions, type PolicyFunction, type QueueOptions, type RateLimitOptions, type ThrottleOptions, withPolicy };
package/dist/policies.js CHANGED
@@ -1 +1 @@
1
- import{n as e,r as t,t as n}from"./delay-5OhJZZQ0.js";import{t as r}from"./onAbort-BgMfspK4.js";import{i,o as a,s as o,t as s}from"./context-Dp_QRXzb.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-BmL0eRU3.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,t,n)=>(m(e),a(e,t,n)),g=(e,t)=>{o(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 a=null;return(l,u)=>{if(a?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=i(u);a=d;let p=s(d,e),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),o(d,e,`start`))};r(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),a===d&&(a=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,i,a)=>{let o=i.leading??!1,s=i.trailing??!0;if(!s)return k(e,t,o,a);let c=!1,l=0,u=E(`debounce`,([i,a],o,u)=>{let d=l;return r(o,()=>{l===d&&(c=!1)}),n(o,e).then(()=>{if(c=!1,s&&!a)return u(),t(i,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(i,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=r(a,s);try{return l(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,t,n)=>{let i=t.concurrency??1,a=t.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 t=!0,i=()=>{c(),s===0&&o.length===0&&n()},a=(e=!1)=>{t&&(t=!1,s--,e?queueMicrotask(i):i())},g=r(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(t.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=r(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)}};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-5OhJZZQ0.js";import{t as r}from"./onAbort-BgMfspK4.js";import{i,o as a,s as o,t as s}from"./context-Dp_QRXzb.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-BmL0eRU3.js";const p=e=>Reflect.get(e,d),m=e=>{p(e)?.start()},h=(e,t,n)=>(m(e),a(e,t,n)),g=(e,t)=>{o(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),s=!1;if(!o){let e=t(()=>{n.get(a)===e&&n.delete(a)});o=e,n.set(a,e),s=!0}let c=i.signal.aborted;try{return o(r,i)}finally{s&&c&&n.get(a)===o&&n.delete(a)}}},C=(e,t)=>y(e?S(e,t):t(b));function w(e,t,n){return x(t,n,(t,n)=>E(e,t,n))}const T=e=>typeof e==`number`?e>=1?Math.floor(e):1:1/0,E=(e,t,n)=>{let r=T(n.maxSize);return C(n.key,n=>D(e,r,t,n))},D=(n,i,a,o)=>{let s=[],c=null,l=0,u=()=>{s.length===0&&l===0&&o()},d=()=>{c&&=(e(c),null)},f=(e,t)=>{for(let n of e.members)`error`in t?n.reject(t.error):n.resolve(t.value)},p=(e,t)=>{l--;let[n]=e.members;n&&!e.dead&&_(n.ctx,t);for(let t of e.members)t.stop(),t!==n&&g(t.ctx,`batch`);u(),e.dead||f(e,t)},m=()=>{d();let e=s;s=[];let[t]=e;if(!t){u();return}let n={members:e,dead:!1};for(let t of e)t.run=n;l++;let r=e.map(e=>e.payload),i;try{i=Promise.resolve(h(t.ctx,`batch`,()=>a(r,t.ctx)))}catch(e){i=Promise.reject(e)}i.then(e=>p(n,{value:e}),e=>p(n,{error:e}))},v=e=>{let t=e.run;if(!t)s.splice(s.indexOf(e),1),g(e.ctx,`batch`),e.resolve(void 0),s.length===0&&(d(),u());else if(e.resolve(void 0),e===t.members[0]){t.dead=!0;for(let e of t.members)e.resolve(void 0)}};return(e,a)=>new Promise((o,l)=>{if(a.signal.aborted){o(void 0);return}let u={payload:e,ctx:a,resolve:o,reject:l,stop:r(a,()=>v(u))};s.push(u),s.length>=i?m():s.length===1&&(c=t(m,n))})};function O(e,t){return x(e,t,k)}const k=(e,t)=>C(t.key,t=>A(`latest`,(t,n,r)=>(r(),e(t,n)),t)),A=(e,t,n=b)=>{let a=null;return(l,u)=>{if(a?.abort(),u.signal.aborted)return;let{ctx:d,unlink:f}=i(u);a=d;let p=s(d,e),h=!1,g=()=>{d.signal.aborted||(h=!0,m(d),o(d,e,`start`))};r(d,e=>{v(d,h,e),p(h?`cancel`:`drop`)});let _=()=>{f(),a===d&&(a=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 j(e,t,n){return x(t,n,(t,n)=>M(e,t,n))}const M=(e,t,n)=>C(n.key,r=>P(e,t,n,r)),N=(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))}},P=(e,t,i,a)=>{let o=i.leading??!1,s=i.trailing??!0;if(!s)return N(e,t,o,a);let c=!1,l=0,u=A(`debounce`,([i,a],o,u)=>{let d=l;return r(o,()=>{l===d&&(c=!1)}),n(o,e).then(()=>{if(c=!1,s&&!a)return u(),t(i,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 F(e,t){return x(e,t,L)}const I=e=>e,L=(e,t)=>C(t.key??I,t=>R(e,t)),R=(e,t)=>{let n=[],i=0,a=(e,r)=>{if(e!==i)return;let[a]=n;a&&_(a.ctx,r);let o=n.splice(0);for(let e of o)e.stop(),e!==a&&g(e.ctx,`dedupe`);t();for(let e of o)`error`in r?e.reject(r.error):e.resolve(r.value)},o=()=>{let[t]=n;if(!t)return;i++;let r=i,o;try{o=Promise.resolve(h(t.ctx,`dedupe`,()=>e(t.payload,t.ctx)))}catch(e){o=Promise.reject(e)}o.then(e=>a(r,{value:e}),e=>a(r,{error:e}))},s=(e,r)=>{let a=n.indexOf(e);a<0||(n.splice(a,1),e.resolve(void 0),v(e.ctx,a===0,r),a===0&&(i++,n.length>0?o():t()))};return(e,t)=>new Promise((i,a)=>{if(t.signal.aborted){i(void 0);return}let c={payload:e,ctx:t,resolve:i,reject:a,stop:r(t,e=>s(c,e))};n.push(c),n.length===1&&o()})};function z(e,t){return x(e,t,B)}const B=(e,t)=>{let n=t.equals??Object.is;return C(t.key,()=>{let t=null;return(i,a)=>{if(a.signal.aborted)return;if(t&&n(t.payload,i)){g(a,`distinct`);return}let o={payload:i};t=o;let s=()=>{t===o&&(t=null)},l=r(a,s);try{let t=h(a,`distinct`,()=>e(i,a));return c(t)?Promise.resolve(t).then(e=>(l(),e),e=>{throw l(),s(),e}):(l(),t)}catch(e){throw l(),s(),e}}})};function V(e,t){return x(e,t,H)}const H=(e,t)=>C(t.key,t=>{let n=null;return(i,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=r(a,s);try{return l(h(a,`leading`,()=>e(i,a)),s)}catch(e){throw s(),e}}});function U(e,t){return x(e,t,W)}const W=(e,t)=>C(t.key,n=>G(e,t,n)),G=(e,t,n)=>{let i=t.concurrency??1,a=t.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 t=!0,i=()=>{c(),s===0&&o.length===0&&n()},a=(e=!1)=>{t&&(t=!1,s--,e?queueMicrotask(i):i())},g=r(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(t.overflow!==`drop-old`||a<=0){m();return}o.shift()?.drop()}let y={start:v,drop:m};o.push(y),p=r(u,()=>{let e=o.indexOf(y);e>=0&&o.splice(e,1),m()})})};function K(e,t,n,r){return x(n,r,(n,r)=>q(e,t,n,r))}const q=(e,t,n,r)=>{let i=e>=1?Math.floor(e):1;return C(r.key,e=>J(i,t,r.overflow===`drop`,n,e))},J=(n,i,a,o,s)=>{let c=[],l=[],u=null,d=()=>{let e=Date.now();for(;c.length>0&&(c[0]??0)+i<=e;)c.shift()},f=()=>{u&&=(e(u),null);let[n]=c;n===void 0?l.length===0&&s():u=t(p,n+i-Date.now())};function p(){for(u=null,d();l.length>0&&c.length<n;)l.shift()?.start();f()}return(e,t)=>new Promise((i,s)=>{if(t.signal.aborted){i(void 0);return}let u=b,p=()=>{u(),g(t,`rateLimit`),i(void 0)},m=()=>{if(u(),t.signal.aborted){p();return}c.push(Date.now());let n=r(t,()=>i(void 0)),a;try{a=Promise.resolve(h(t,`rateLimit`,()=>o(e,t)))}catch(e){a=Promise.reject(e)}a.then(e=>{n(),_(t,{value:e}),i(t.signal.aborted?void 0:e)},e=>{n(),_(t,{error:e}),t.signal.aborted?i(void 0):s(e)})};if(d(),l.length===0&&c.length<n){m(),f();return}if(a){p();return}let v={start:m,drop:p};l.push(v),u=r(t,()=>{let e=l.indexOf(v);e>=0&&l.splice(e,1),p(),l.length===0&&c.length===0&&f()}),f()})};function Y(e,t,n){return x(t,n,(t,n)=>X(e,t,n))}const X=(e,t,n)=>C(n.key,r=>Z(e,t,n,r)),Z=(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{w as batch,j as debounce,F as dedupe,z as distinct,O as latest,V as leading,U as queue,K as rateLimit,Y as throttle,f as withPolicy};