indisposed 0.0.8 โ†’ 0.1.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/README.md CHANGED
@@ -10,6 +10,8 @@ The missing utilities for JavaScript's [Explicit Resource Management](https://gi
10
10
 
11
11
  - ๐Ÿงน **Resource Management** - Convert any resource into a disposable with `toDisposable` and `toAsyncDisposable`
12
12
  - ๐ŸŽง **Event Handlers** - Transform event emitters into disposable iterators with `on` and promises with `once`
13
+ - โฑ๏ธ **Timing Utilities** - Disposable `timeout` and `interval` for clean timer management
14
+ - ๐Ÿ“ก **Channels** - Build async iterators from push-based sources with `channel`
13
15
  - ๐Ÿ”’ **Scoped Execution** - Execute code with automatic cleanup using `invoke`
14
16
  - ๐Ÿ“ฆ **Zero Dependencies** - Lightweight and focused
15
17
  - ๐Ÿ”ง **TypeScript First** - Full type safety and inference
@@ -133,7 +135,7 @@ import { once } from "indisposed";
133
135
  }
134
136
  ```
135
137
 
136
- ### `on(emitter, event, maxBuffer?)`
138
+ ### `on(emitter, event, options?)`
137
139
 
138
140
  Create a disposable async iterator for multiple events.
139
141
 
@@ -164,6 +166,109 @@ import { on } from "indisposed";
164
166
  console.log(`Position: ${x}, ${y}`);
165
167
  }
166
168
  }
169
+
170
+ // With buffer options
171
+ {
172
+ using events = on(emitter, "data", { maxBuffer: 10, drain: true });
173
+ // ...
174
+ }
175
+ ```
176
+
177
+ ### `timeout(ms)`
178
+
179
+ Create a disposable promise that resolves after a delay.
180
+
181
+ ```typescript
182
+ import { timeout } from "indisposed";
183
+
184
+ // Basic usage
185
+ await timeout(1000);
186
+ console.log("1 second passed");
187
+
188
+ // With using - automatically clears timeout when scope exits
189
+ {
190
+ using timer = timeout(5000);
191
+ await timer;
192
+ } // timeout cleared if scope exits early
193
+
194
+ // Racing with other promises
195
+ {
196
+ using timer = timeout(10000);
197
+ using data = once(socket, "data");
198
+
199
+ await Promise.race([timer, data]);
200
+ } // both cleaned up regardless of which wins
201
+ ```
202
+
203
+ ### `interval(ms, options?)`
204
+
205
+ Create a disposable async iterator that yields incrementing numbers at a fixed interval.
206
+
207
+ ```typescript
208
+ import { interval } from "indisposed";
209
+
210
+ // Basic usage - tick every second
211
+ {
212
+ using ticks = interval(1000);
213
+
214
+ for await (const tick of ticks) {
215
+ console.log(`Tick ${tick}`); // 0, 1, 2, ...
216
+ if (tick >= 5) break;
217
+ }
218
+ } // interval automatically cleared
219
+
220
+ // Polling pattern
221
+ {
222
+ using poll = interval(5000);
223
+
224
+ for await (const _ of poll) {
225
+ const status = await checkStatus();
226
+ if (status === "complete") break;
227
+ }
228
+ }
229
+
230
+ // With options
231
+ const ticks = interval(100, { maxBuffer: 10, drain: true });
232
+ ```
233
+
234
+ ### `channel<T>(options?)`
235
+
236
+ Create a buffered async channel for pushing values and consuming them via async iteration.
237
+
238
+ This is a low-level primitive for building async iterators from push-based sources.
239
+ The channel separates producer (`push`) and consumer (`iterator`) concerns - only expose
240
+ the `iterator` to downstream code.
241
+
242
+ **Options:**
243
+
244
+ - `maxBuffer` - Maximum events to buffer (default: 100). Set to 0 for no buffering.
245
+ - `drain` - Whether to drain buffered events on dispose (default: false)
246
+
247
+ ```typescript
248
+ import { channel } from "indisposed";
249
+
250
+ // Basic usage - producer keeps the channel, consumer gets the iterator
251
+ const ch = channel<string>();
252
+
253
+ // Producer side
254
+ ch.push("hello");
255
+ ch.push("world");
256
+
257
+ // Consumer side - only sees the iterator
258
+ {
259
+ using iter = ch.iterator;
260
+ for await (const value of iter) {
261
+ console.log(value);
262
+ if (shouldStop) break;
263
+ }
264
+ }
265
+
266
+ // Building a custom async source
267
+ function createDataStream() {
268
+ const ch = channel<Data>();
269
+ source.on("data", (d) => ch.push(d));
270
+ return ch.iterator; // Only expose the iterator
271
+ }
167
272
  ```
168
273
 
169
274
  ### `invoke<T>(fn)`
@@ -0,0 +1,82 @@
1
+ export type ChannelOptions = {
2
+ /**
3
+ * Maximum amount of events to be buffered.
4
+ * When buffer is full, oldest events are dropped.
5
+ * Set to 0 to disable buffering (only deliver to waiting consumers).
6
+ * @default 100
7
+ */
8
+ maxBuffer?: number;
9
+ /**
10
+ * Whether to drain buffered events before ending iteration on dispose.
11
+ * When true, buffered events will still be yielded after dispose is called.
12
+ * When false, dispose immediately ends iteration and discards buffered events.
13
+ * @default false
14
+ */
15
+ drain?: boolean;
16
+ };
17
+ /**
18
+ * The iterator portion of a channel - this is what consumers see.
19
+ */
20
+ export type ChannelIterator<T> = AsyncIterableIterator<T, undefined, void> & {
21
+ [Symbol.dispose]: () => void;
22
+ };
23
+ /**
24
+ * The full channel handle with push capability - for internal/producer use.
25
+ */
26
+ export type Channel<T> = {
27
+ /**
28
+ * Push a value into the channel.
29
+ * If there are waiting consumers, the value is delivered immediately.
30
+ * Otherwise, it's buffered (subject to maxBuffer).
31
+ */
32
+ push: (value: T) => void;
33
+ /**
34
+ * Whether the channel is closed.
35
+ */
36
+ readonly closed: boolean;
37
+ /**
38
+ * The async iterator for consuming values.
39
+ * This is what should be exposed to downstream consumers.
40
+ */
41
+ iterator: ChannelIterator<T>;
42
+ };
43
+ /**
44
+ * Creates a buffered async channel for pushing values and consuming them via async iteration.
45
+ *
46
+ * This is a low-level primitive for building async iterators from push-based sources
47
+ * like event emitters, intervals, or any producer that pushes values over time.
48
+ *
49
+ * The returned channel has a `push` method for producers and an `iterator` property
50
+ * for consumers. Only expose the `iterator` to downstream code.
51
+ *
52
+ * @param options - Channel configuration
53
+ * @returns A channel with push capability and a disposable async iterator
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * // Basic usage - producer keeps the channel, consumer gets the iterator
58
+ * const ch = channel<string>();
59
+ *
60
+ * // Producer side
61
+ * ch.push("hello");
62
+ * ch.push("world");
63
+ *
64
+ * // Consumer side - only sees the iterator
65
+ * for await (const value of ch.iterator) {
66
+ * console.log(value);
67
+ * if (shouldStop) break;
68
+ * }
69
+ * ```
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * // Building a custom async iterator
74
+ * function myAsyncSource() {
75
+ * const ch = channel<number>();
76
+ * // ... set up producer that calls ch.push()
77
+ * return ch.iterator; // Only expose the iterator
78
+ * }
79
+ * ```
80
+ */
81
+ export declare function channel<T>(options?: ChannelOptions): Channel<T>;
82
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/functions/channel.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC5B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAOF;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,qBAAqB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG;IAC5E,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IACxB;;;;OAIG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CA6F/D"}
@@ -1,4 +1,5 @@
1
1
  import { EventHandlerParams, EventNames, Fn } from '../types';
2
+ import { ChannelOptions } from './channel';
2
3
  import { UnpackArray } from './fn';
3
4
  export type Subscription = (event: any, handler: Fn) => any;
4
5
  /**
@@ -67,7 +68,7 @@ export type OnResult<EventEmitter extends HasOn, Event extends EventNames<EventE
67
68
  *
68
69
  * @param emitter - Event emitter with `on` and `off` methods
69
70
  * @param event - Event name (must match one of the emitter's overloads)
70
- * @param maxBuffer - Maximum number of events to buffer (default: 100)
71
+ * @param options - Channel options (maxBuffer, etc.)
71
72
  * @returns Disposable async iterator that yields handler arguments
72
73
  *
73
74
  * @example
@@ -93,7 +94,9 @@ export type OnResult<EventEmitter extends HasOn, Event extends EventNames<EventE
93
94
  * }
94
95
  * ```
95
96
  */
96
- export declare function on<EventEmitter extends HasOn, const Event extends EventNames<EventEmitter["on"]>>(emitter: EventEmitter, event: Event, maxBuffer?: number): AsyncIterableIterator<UnpackArray<Parameters<import('../types').OverLoadFunctions<EventEmitter["on"]>> extends infer T ? T extends Parameters<import('../types').OverLoadFunctions<EventEmitter["on"]>> ? T extends unknown ? T extends [Event, infer Handler] ? import('../types').ExtractParams<Handler> extends infer P ? P extends any[] ? any[] extends P ? never : P : never : never : never : never : never : never>, undefined, void> & {
97
+ export declare function on<EventEmitter extends HasOn, const Event extends EventNames<EventEmitter["on"]>>(emitter: EventEmitter, event: Event, options?: ChannelOptions): AsyncIterableIterator<UnpackArray<Parameters<import('../types').OverLoadFunctions<EventEmitter["on"]>> extends infer T ? T extends Parameters<import('../types').OverLoadFunctions<EventEmitter["on"]>> ? T extends unknown ? T extends [Event, infer Handler] ? import('../types').ExtractParams<Handler> extends infer P ? P extends any[] ? any[] extends P ? never : P : never : never : never : never : never : never>, undefined, void> & {
98
+ [Symbol.dispose]: () => void;
99
+ } & {
97
100
  [Symbol.dispose]: () => void;
98
101
  };
99
102
  //# sourceMappingURL=handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/functions/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElE,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,MAAM,CAAC;AAErD,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,GAAG,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACpB,GAAG,EAAE,YAAY,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IACnB,EAAE,EAAE,YAAY,CAAC;CACjB,GAAG,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,YAAY,CAAC;CACnB,GAAG,MAAM,CAAC;AAEX,MAAM,MAAM,UAAU,CACrB,YAAY,SAAS,OAAO,EAC5B,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAC9C,OAAO,SAAS,OAAO,IACpB,OAAO,SAAS,IAAI,GACrB,KAAK,GACL,WAAW,CAAC,kBAAkB,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,IAAI,CACnB,YAAY,SAAS,OAAO,EAC5B,KAAK,CAAC,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EACpD,KAAK,CAAC,OAAO,SAAS,OAAO,GAAG,KAAK,EACpC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO;;EAavD;AAED,MAAM,MAAM,QAAQ,CACnB,YAAY,SAAS,KAAK,EAC1B,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IACzC,WAAW,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,EAAE,CACjB,YAAY,SAAS,KAAK,EAC1B,KAAK,CAAC,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EACjD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,SAAM;;EA0ErD"}
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/functions/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElE,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,MAAM,CAAC;AAErD,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,GAAG,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACpB,GAAG,EAAE,YAAY,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IACnB,EAAE,EAAE,YAAY,CAAC;CACjB,GAAG,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,YAAY,CAAC;CACnB,GAAG,MAAM,CAAC;AAEX,MAAM,MAAM,UAAU,CACrB,YAAY,SAAS,OAAO,EAC5B,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAC9C,OAAO,SAAS,OAAO,IACpB,OAAO,SAAS,IAAI,GACrB,KAAK,GACL,WAAW,CAAC,kBAAkB,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,IAAI,CACnB,YAAY,SAAS,OAAO,EAC5B,KAAK,CAAC,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EACpD,KAAK,CAAC,OAAO,SAAS,OAAO,GAAG,KAAK,EACpC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO;;EAavD;AAED,MAAM,MAAM,QAAQ,CACnB,YAAY,SAAS,KAAK,EAC1B,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IACzC,WAAW,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,EAAE,CACjB,YAAY,SAAS,KAAK,EAC1B,KAAK,CAAC,KAAK,SAAS,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EACjD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,cAAc;;;;EAc9D"}
@@ -0,0 +1,91 @@
1
+ import { ChannelOptions } from './channel';
2
+ /**
3
+ * Creates a disposable promise that resolves after a specified delay.
4
+ *
5
+ * The timeout is automatically cleared when disposed, preventing
6
+ * memory leaks and unnecessary timer execution.
7
+ *
8
+ * @param ms - Delay in milliseconds before the promise resolves
9
+ * @returns A disposable promise that resolves to `void` after the delay
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // Basic usage - wait for 1 second
14
+ * await timeout(1000);
15
+ * console.log("1 second passed");
16
+ * ```
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * // With using - automatically clears timeout when scope exits
21
+ * {
22
+ * using timer = timeout(5000);
23
+ * await timer;
24
+ * } // timeout cleared if scope exits early
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // Racing with other promises - losing timeout is cleaned up
30
+ * {
31
+ * using timer = timeout(10000);
32
+ * using data = once(socket, "data");
33
+ *
34
+ * await Promise.race([timer, data]);
35
+ * } // both cleaned up regardless of which wins
36
+ * ```
37
+ */
38
+ export declare function timeout(ms: number): Promise<void> & {
39
+ [Symbol.dispose]: () => void;
40
+ };
41
+ export type IntervalOptions = ChannelOptions;
42
+ /**
43
+ * Creates a disposable async iterator that yields incrementing numbers at a fixed interval.
44
+ *
45
+ * Values start at 0 and increment by 1 for each interval tick. The interval
46
+ * is automatically cleared when the iterator is disposed or iteration ends.
47
+ *
48
+ * @param ms - Interval duration in milliseconds between each tick
49
+ * @param options - Channel options for buffering behavior
50
+ * @param options.maxBuffer - Maximum events to buffer (default: 100). Set to 0 for no buffering.
51
+ * @param options.drain - Whether to drain buffer on close (default: false)
52
+ * @returns A disposable async iterator yielding incrementing numbers
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * // Basic usage - tick every second
57
+ * {
58
+ * using ticks = interval(1000);
59
+ *
60
+ * for await (const tick of ticks) {
61
+ * console.log(`Tick ${tick}`); // 0, 1, 2, ...
62
+ * if (tick >= 5) break;
63
+ * }
64
+ * } // interval automatically cleared
65
+ * ```
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * // Polling pattern
70
+ * {
71
+ * using poll = interval(5000);
72
+ *
73
+ * for await (const _ of poll) {
74
+ * const status = await checkStatus();
75
+ * if (status === "complete") break;
76
+ * }
77
+ * }
78
+ * ```
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * // With no buffering - only deliver to waiting consumers
83
+ * const ticks = interval(100, { maxBuffer: 0 });
84
+ * ```
85
+ */
86
+ export declare function interval(ms: number, options?: IntervalOptions): AsyncIterableIterator<number, undefined, void> & {
87
+ [Symbol.dispose]: () => void;
88
+ } & {
89
+ [Symbol.dispose]: () => void;
90
+ };
91
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/functions/timing.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM;;EAKjC;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe;;;;EAY7D"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { invoke, on, once, toAsyncDisposable, toDisposable } from "./no-polyfill.js";
1
+ import { channel, interval, invoke, on, once, timeout, toAsyncDisposable, toDisposable } from "./no-polyfill.js";
2
2
  const hasNativeDispose = typeof Symbol.dispose === "symbol" && typeof Symbol.asyncDispose === "symbol";
3
3
  if (!hasNativeDispose) {
4
4
  try {
@@ -22,9 +22,12 @@ if (!hasNativeWithResolvers) {
22
22
  }
23
23
  }
24
24
  export {
25
+ channel,
26
+ interval,
25
27
  invoke,
26
28
  on,
27
29
  once,
30
+ timeout,
28
31
  toAsyncDisposable,
29
32
  toDisposable
30
33
  };
@@ -1,4 +1,6 @@
1
1
  export * from './functions/disposable';
2
2
  export * from './functions/handlers';
3
+ export * from './functions/channel';
4
+ export * from './functions/timing';
3
5
  export { invoke } from './functions/fn';
4
6
  //# sourceMappingURL=no-polyfill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"no-polyfill.d.ts","sourceRoot":"","sources":["../src/no-polyfill.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"no-polyfill.d.ts","sourceRoot":"","sources":["../src/no-polyfill.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
@@ -31,55 +31,46 @@ function toAsyncDisposable(value, disposeFn) {
31
31
  }
32
32
  });
33
33
  }
34
- function unpackArray(values) {
35
- return values.length === 0 ? void 0 : values.length === 1 ? values[0] : values;
36
- }
37
- function invoke(fn) {
38
- return fn();
39
- }
40
- function once(emitter, event, rejects) {
41
- const { promise, resolve, reject } = Promise.withResolvers();
42
- const handler = (...args) => {
43
- if (rejects) {
44
- reject(args.length === 1 ? args[0] : args);
45
- return;
46
- }
47
- resolve(unpackArray(args));
48
- };
49
- emitter.once(event, handler);
50
- return toDisposable(promise, () => emitter.off(event, handler));
51
- }
52
- function on(emitter, event, maxBuffer = 100) {
53
- let done = false;
34
+ const DEFAULT_OPTIONS = {
35
+ maxBuffer: 100,
36
+ drain: false
37
+ };
38
+ function channel(options) {
39
+ const { maxBuffer, drain: shouldDrain } = { ...DEFAULT_OPTIONS, ...options };
40
+ let closed = false;
54
41
  const events = [];
55
42
  const waiters = [];
56
43
  const doneResult = () => ({
57
44
  value: void 0,
58
45
  done: true
59
46
  });
60
- const drain = () => {
61
- while (!done && events.length && waiters.length) {
47
+ const drainQueue = () => {
48
+ while (!closed && events.length && waiters.length) {
62
49
  const value = events.shift();
63
50
  const resolve = waiters.shift();
64
51
  resolve({ value, done: false });
65
52
  }
66
53
  };
67
- const handler = (...args) => {
68
- if (done) return;
69
- const value = unpackArray(args);
54
+ const push = (value) => {
55
+ if (closed) return;
70
56
  if (maxBuffer <= 0) {
71
57
  if (waiters.length) events.push(value);
72
58
  } else {
73
59
  events.push(value);
74
60
  if (events.length > maxBuffer) events.shift();
75
61
  }
76
- drain();
62
+ drainQueue();
77
63
  };
78
- emitter.on(event, handler);
79
64
  const dispose = () => {
80
- if (done) return;
81
- emitter.off(event, handler);
82
- done = true;
65
+ if (closed) return;
66
+ closed = true;
67
+ if (shouldDrain) {
68
+ while (events.length && waiters.length) {
69
+ const value = events.shift();
70
+ const resolve = waiters.shift();
71
+ resolve({ value, done: false });
72
+ }
73
+ }
83
74
  while (waiters.length > 0) {
84
75
  const waiter = waiters.shift();
85
76
  waiter?.(doneResult());
@@ -87,14 +78,18 @@ function on(emitter, event, maxBuffer = 100) {
87
78
  };
88
79
  const iterator = {
89
80
  async next() {
90
- if (done) {
81
+ if (shouldDrain && events.length) {
82
+ return { value: events.shift(), done: false };
83
+ }
84
+ if (closed) {
91
85
  return doneResult();
92
86
  }
93
- if (events.length)
87
+ if (events.length) {
94
88
  return { value: events.shift(), done: false };
89
+ }
95
90
  return new Promise((resolve) => {
96
91
  waiters.push(resolve);
97
- drain();
92
+ drainQueue();
98
93
  });
99
94
  },
100
95
  return() {
@@ -103,14 +98,68 @@ function on(emitter, event, maxBuffer = 100) {
103
98
  },
104
99
  [Symbol.asyncIterator]() {
105
100
  return this;
101
+ },
102
+ [Symbol.dispose]: dispose
103
+ };
104
+ return {
105
+ push,
106
+ get closed() {
107
+ return closed;
108
+ },
109
+ iterator
110
+ };
111
+ }
112
+ function unpackArray(values) {
113
+ return values.length === 0 ? void 0 : values.length === 1 ? values[0] : values;
114
+ }
115
+ function invoke(fn) {
116
+ return fn();
117
+ }
118
+ function once(emitter, event, rejects) {
119
+ const { promise, resolve, reject } = Promise.withResolvers();
120
+ const handler = (...args) => {
121
+ if (rejects) {
122
+ reject(args.length === 1 ? args[0] : args);
123
+ return;
106
124
  }
125
+ resolve(unpackArray(args));
126
+ };
127
+ emitter.once(event, handler);
128
+ return toDisposable(promise, () => emitter.off(event, handler));
129
+ }
130
+ function on(emitter, event, options) {
131
+ const ch = channel(options);
132
+ const handler = (...args) => {
133
+ ch.push(unpackArray(args));
107
134
  };
108
- return toDisposable(iterator, dispose);
135
+ emitter.on(event, handler);
136
+ return toDisposable(ch.iterator, () => {
137
+ emitter.off(event, handler);
138
+ });
139
+ }
140
+ function timeout(ms) {
141
+ const timingPromise = Promise.withResolvers();
142
+ const timeoutId = setTimeout(timingPromise.resolve, ms);
143
+ return toDisposable(timingPromise.promise, () => clearTimeout(timeoutId));
144
+ }
145
+ function interval(ms, options) {
146
+ const ch = channel(options);
147
+ let currentValue = 0;
148
+ const intervalId = setInterval(() => {
149
+ if (ch.closed) return;
150
+ ch.push(currentValue++);
151
+ }, ms);
152
+ return toDisposable(ch.iterator, () => {
153
+ clearInterval(intervalId);
154
+ });
109
155
  }
110
156
  export {
157
+ channel,
158
+ interval,
111
159
  invoke,
112
160
  on,
113
161
  once,
162
+ timeout,
114
163
  toAsyncDisposable,
115
164
  toDisposable
116
165
  };
@@ -1 +1 @@
1
- {"version":3,"file":"no-polyfill.js","sources":["../src/functions/disposable.ts","../src/functions/fn.ts","../src/functions/handlers.ts"],"sourcesContent":["/** Function that performs cleanup for a disposable resource */\nexport type DisposeFn<T> = (value: T) => unknown;\n\n/**\n * Object with a Symbol.dispose method for automatic cleanup\n * @see {@link toDisposable}\n */\nexport type Disposable<T extends object> = ReturnType<typeof toDisposable<T>>;\n\nfunction hasDisposable(\n\tvalue: unknown,\n): value is { [Symbol.dispose]: () => unknown } {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === \"object\" &&\n\t\ttypeof (value as any)[Symbol.dispose] === \"function\"\n\t);\n}\n\nfunction hasAsyncDisposable(\n\tvalue: unknown,\n): value is { [Symbol.asyncDispose]: () => PromiseLike<unknown> } {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === \"object\" &&\n\t\ttypeof (value as any)[Symbol.asyncDispose] === \"function\"\n\t);\n}\n\n/**\n * Make a value disposable by adding a Symbol.dispose method\n * @param value item to make disposable (must be an extensible object)\n * @param disposeFn function that will cleanup the item\n * @returns value that's disposable\n * @example\n * ```ts\n * // Direct usage with extensible objects\n * const resource = toDisposable({ handle: 123 }, (r) => closeHandle(r.handle));\n * using handle = resource; // automatically disposed at end of scope\n *\n * // For non-extensible values (primitives, sealed objects, class instances), wrap them:\n * const connection = new WebSocket('ws://localhost');\n * const disposableConnection = toDisposable(\n * { socket: connection },\n * (wrapped) => wrapped.socket.close()\n * );\n * using conn = disposableConnection;\n * ```\n */\nexport function toDisposable<T extends object>(\n\tvalue: T,\n\tdisposeFn: DisposeFn<T>,\n) {\n\tlet disposed = false;\n\n\tconst originalDispose = hasDisposable(value)\n\t\t? value[Symbol.dispose]\n\t\t: undefined;\n\n\treturn Object.assign(value, {\n\t\t[Symbol.dispose]: () => {\n\t\t\tif (disposed) return;\n\n\t\t\tdisposeFn(value);\n\t\t\toriginalDispose?.call(value);\n\t\t\tdisposed = true;\n\t\t},\n\t});\n}\n\n/** Async function that performs cleanup for a disposable resource */\nexport type AsyncDispose<T> = (value: T) => PromiseLike<unknown>;\n\n/**\n * Object with a Symbol.asyncDispose method for automatic async cleanup\n * @see {@link toAsyncDisposable}\n */\nexport type AsyncDisposable<T extends object> = ReturnType<\n\ttypeof toAsyncDisposable<T>\n>;\n\n/**\n * Make a value async disposable by adding a Symbol.asyncDispose method\n * @param value item to make disposable (must be an extensible object)\n * @param disposeFn async function that will cleanup the item\n * @returns value that's async disposable\n * @example\n * ```ts\n * // Direct usage with extensible objects\n * const resource = toAsyncDisposable({ stream: fs.createReadStream('file.txt') }, async (r) => {\n * await r.stream.close();\n * });\n * await using file = resource; // automatically disposed at end of scope\n *\n * // For non-extensible values (sealed objects, class instances), wrap them:\n * const database = new DatabaseConnection();\n * const disposableDb = toAsyncDisposable(\n * { connection: database },\n * async (wrapped) => {\n * await wrapped.connection.close();\n * }\n * );\n * await using db = disposableDb;\n * ```\n */\nexport function toAsyncDisposable<T extends object>(\n\tvalue: T,\n\tdisposeFn: AsyncDispose<T>,\n) {\n\tlet disposingPromise: PromiseLike<unknown> | undefined;\n\tconst originalDispose = hasAsyncDisposable(value)\n\t\t? value[Symbol.asyncDispose]\n\t\t: undefined;\n\n\treturn Object.assign(value, {\n\t\t[Symbol.asyncDispose]: async () => {\n\t\t\tif (disposingPromise == null) {\n\t\t\t\tdisposingPromise = (async () => {\n\t\t\t\t\tawait disposeFn(value);\n\t\t\t\t\tawait originalDispose?.call(value);\n\t\t\t\t})();\n\t\t\t}\n\t\t\tawait disposingPromise;\n\t\t},\n\t});\n}\n","export type UnpackArray<T extends unknown[]> = T[\"length\"] extends 0\n\t? undefined\n\t: T[\"length\"] extends 1\n\t\t? T[0]\n\t\t: T;\n\nexport function unpackArray<T extends unknown[]>(values: T) {\n\treturn (\n\t\tvalues.length === 0 ? undefined : values.length === 1 ? values[0] : values\n\t) as UnpackArray<T>;\n}\n\n/**\n * Utility just invokes the method being called immediately.\n * Useful to scope resources to calling body.\n * @param fn Function to invoke\n * @returns Result of fn\n * @example\n * ```ts\n * import {invoke, once, toAsyncDisposable} from \"indisposed\";\n * import {WebSocketServer} from \"ws\";\n *\n * {\n * \tawait using wss = await invoke(async () => {\n * \t\tconst wss = toAsyncDisposable(\n * \t\t\tnew WebSocketServer({ host: \"127.0.0.1\", port: 0 }),\n * \t\t\t(wss) =>\n * \t\t\t\tnew Promise((resolve, reject) => {\n * \t\t\t\t\twss.close((err) => {\n * \t\t\t\t\t\tif (err) return reject(err);\n * \t\t\t\t\t\tresolve(undefined);\n * \t\t\t\t\t});\n * \t\t\t\t}),\n * \t\t);\n * \t\tusing listening = once(wss, \"listening\");\n * \t\tusing error = once(wss, \"error\", true);\n *\n * \t\tawait Promise.race([listening, error]);\n *\n * \t\treturn wss;\n * \t});\n *\n * \tconsole.log(\"Server ready at\", wss.address());\n * \t// ... handle connections ...\n * }\n * // wss is automatically closed once the scope ends\n * ```\n */\nexport function invoke<TResult>(fn: () => TResult) {\n\treturn fn();\n}\n","import type { EventHandlerParams, EventNames, Fn } from \"~/types\";\nimport { toDisposable } from \"./disposable\";\nimport { type UnpackArray, unpackArray } from \"./fn\";\n\nexport type Subscription = (event: any, handler: Fn) => any;\n\n/**\n * Represents an event emitter with an `off` method for removing listeners.\n */\nexport type HasOff = {\n\toff: Subscription;\n};\n\n/**\n * Represents an event emitter with an `on` method for registering listeners.\n */\nexport type HasOn = {\n\ton: Subscription;\n} & HasOff;\n\n/**\n * Represents an event emitter with a `once` method for one-time listeners.\n */\nexport type HasOnce = {\n\tonce: Subscription;\n} & HasOff;\n\nexport type OnceResult<\n\tEventEmitter extends HasOnce,\n\tEvent extends EventNames<EventEmitter[\"once\"]>,\n\tRejects extends boolean,\n> = Rejects extends true\n\t? never\n\t: UnpackArray<EventHandlerParams<EventEmitter[\"once\"], Event>>;\n\n/**\n * Type-safe wrapper for event emitter's `once` method that preserves overload signatures.\n *\n * The return value is automatically unpacked:\n * - Handlers with 0 parameters resolve to `undefined`\n * - Handlers with 1 parameter resolve to that single value\n * - Handlers with 2+ parameters resolve to an array of values\n *\n * @param emitter - Event emitter with `once` and `off` methods\n * @param event - Event name (must match one of the emitter's overloads)\n * @param rejects - When true, the promise rejects with the handler arguments instead of resolving\n * @returns Disposable promise with the handler arguments and automatic cleanup via `off`\n *\n * @example\n * ```ts\n * type MyEmitter = {\n * once(event: 'data', handler: (value: string) => void): void;\n * once(event: 'error', handler: (error: Error) => void): number;\n * once(event: 'multi', handler: (x: number, y: number) => void): void;\n * off(event: string, handler: Fn): void;\n * };\n *\n * declare const emitter: MyEmitter;\n *\n * // Single parameter: returns the value directly\n * using result = once(emitter, 'data');\n * console.log((await result).toUpperCase()); // string\n *\n * // Multiple parameters: returns as array\n * using coords = once(emitter, 'multi');\n * const [x, y] = await coords; // [number, number]\n * ```\n */\nexport function once<\n\tEventEmitter extends HasOnce,\n\tconst Event extends EventNames<EventEmitter[\"once\"]>,\n\tconst Rejects extends boolean = false,\n>(emitter: EventEmitter, event: Event, rejects?: Rejects) {\n\tconst { promise, resolve, reject } =\n\t\tPromise.withResolvers<OnceResult<EventEmitter, Event, Rejects>>();\n\n\tconst handler: Fn = (...args: unknown[]) => {\n\t\tif (rejects) {\n\t\t\treject(args.length === 1 ? args[0] : args);\n\t\t\treturn;\n\t\t}\n\t\tresolve(unpackArray(args) as OnceResult<EventEmitter, Event, Rejects>);\n\t};\n\temitter.once(event, handler);\n\treturn toDisposable(promise, () => emitter.off(event, handler));\n}\n\nexport type OnResult<\n\tEventEmitter extends HasOn,\n\tEvent extends EventNames<EventEmitter[\"on\"]>,\n> = UnpackArray<EventHandlerParams<EventEmitter[\"on\"], Event>>;\n\n/**\n * Type-safe wrapper for event emitter's `on` method that returns an async iterator.\n *\n * The yielded values are automatically unpacked:\n * - Handlers with 0 parameters yield `undefined`\n * - Handlers with 1 parameter yield that single value\n * - Handlers with 2+ parameters yield an array of values\n *\n * @param emitter - Event emitter with `on` and `off` methods\n * @param event - Event name (must match one of the emitter's overloads)\n * @param maxBuffer - Maximum number of events to buffer (default: 100)\n * @returns Disposable async iterator that yields handler arguments\n *\n * @example\n * ```ts\n * type MyEmitter = {\n * on(event: 'data', handler: (value: string) => void): void;\n * on(event: 'position', handler: (x: number, y: number) => void): void;\n * off(event: string, handler: Fn): void;\n * };\n *\n * declare const emitter: MyEmitter;\n *\n * // Single parameter: yields values directly\n * using iterator = on(emitter, 'data');\n * for await (const value of iterator) {\n * console.log(value.toUpperCase()); // string\n * }\n *\n * // Multiple parameters: yields as array\n * using positions = on(emitter, 'position');\n * for await (const [x, y] of positions) {\n * console.log(`Position: ${x}, ${y}`);\n * }\n * ```\n */\nexport function on<\n\tEventEmitter extends HasOn,\n\tconst Event extends EventNames<EventEmitter[\"on\"]>,\n>(emitter: EventEmitter, event: Event, maxBuffer = 100) {\n\ttype Item = OnResult<EventEmitter, Event>;\n\ttype IterationResult = IteratorResult<Item, undefined>;\n\n\tlet done = false;\n\tconst events: Item[] = [];\n\tconst waiters: ((value: IterationResult) => void)[] = [];\n\n\tconst doneResult = () => ({\n\t\tvalue: undefined,\n\t\tdone: true as const,\n\t});\n\n\tconst drain = () => {\n\t\t// Pair off as many as possible, FIFO โ†” FIFO\n\t\twhile (!done && events.length && waiters.length) {\n\t\t\tconst value = events.shift()!;\n\t\t\tconst resolve = waiters.shift()!;\n\t\t\tresolve({ value, done: false });\n\t\t}\n\t};\n\n\tconst handler = (...args: unknown[]) => {\n\t\tif (done) return;\n\t\tconst value = unpackArray(args) as Item;\n\n\t\tif (maxBuffer <= 0) {\n\t\t\tif (waiters.length) events.push(value); // only deliver to waiters\n\t\t} else {\n\t\t\tevents.push(value);\n\t\t\tif (events.length > maxBuffer) events.shift();\n\t\t}\n\t\tdrain();\n\t};\n\n\temitter.on(event, handler);\n\n\tconst dispose = () => {\n\t\tif (done) return;\n\t\temitter.off(event, handler);\n\t\tdone = true;\n\n\t\twhile (waiters.length > 0) {\n\t\t\tconst waiter = waiters.shift();\n\t\t\twaiter?.(doneResult());\n\t\t}\n\t};\n\n\tconst iterator: AsyncIterableIterator<Item, undefined, void> = {\n\t\tasync next() {\n\t\t\t// If already disposed, return done\n\t\t\tif (done) {\n\t\t\t\treturn doneResult();\n\t\t\t}\n\n\t\t\tif (events.length)\n\t\t\t\treturn { value: events.shift()!, done: false } as const;\n\n\t\t\t// Wait for the next event\n\t\t\treturn new Promise<IterationResult>((resolve) => {\n\t\t\t\twaiters.push(resolve);\n\t\t\t\tdrain();\n\t\t\t});\n\t\t},\n\t\treturn() {\n\t\t\tdispose();\n\t\t\treturn Promise.resolve(doneResult());\n\t\t},\n\t\t[Symbol.asyncIterator]() {\n\t\t\treturn this;\n\t\t},\n\t};\n\n\treturn toDisposable(iterator, dispose);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"no-polyfill.js","sources":["../src/functions/disposable.ts","../src/functions/channel.ts","../src/functions/fn.ts","../src/functions/handlers.ts","../src/functions/timing.ts"],"sourcesContent":["/** Function that performs cleanup for a disposable resource */\nexport type DisposeFn<T> = (value: T) => unknown;\n\n/**\n * Object with a Symbol.dispose method for automatic cleanup\n * @see {@link toDisposable}\n */\nexport type Disposable<T extends object> = ReturnType<typeof toDisposable<T>>;\n\nfunction hasDisposable(\n\tvalue: unknown,\n): value is { [Symbol.dispose]: () => unknown } {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === \"object\" &&\n\t\ttypeof (value as any)[Symbol.dispose] === \"function\"\n\t);\n}\n\nfunction hasAsyncDisposable(\n\tvalue: unknown,\n): value is { [Symbol.asyncDispose]: () => PromiseLike<unknown> } {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === \"object\" &&\n\t\ttypeof (value as any)[Symbol.asyncDispose] === \"function\"\n\t);\n}\n\n/**\n * Make a value disposable by adding a Symbol.dispose method\n * @param value item to make disposable (must be an extensible object)\n * @param disposeFn function that will cleanup the item\n * @returns value that's disposable\n * @example\n * ```ts\n * // Direct usage with extensible objects\n * const resource = toDisposable({ handle: 123 }, (r) => closeHandle(r.handle));\n * using handle = resource; // automatically disposed at end of scope\n *\n * // For non-extensible values (primitives, sealed objects, class instances), wrap them:\n * const connection = new WebSocket('ws://localhost');\n * const disposableConnection = toDisposable(\n * { socket: connection },\n * (wrapped) => wrapped.socket.close()\n * );\n * using conn = disposableConnection;\n * ```\n */\nexport function toDisposable<T extends object>(\n\tvalue: T,\n\tdisposeFn: DisposeFn<T>,\n) {\n\tlet disposed = false;\n\n\tconst originalDispose = hasDisposable(value)\n\t\t? value[Symbol.dispose]\n\t\t: undefined;\n\n\treturn Object.assign(value, {\n\t\t[Symbol.dispose]: () => {\n\t\t\tif (disposed) return;\n\n\t\t\tdisposeFn(value);\n\t\t\toriginalDispose?.call(value);\n\t\t\tdisposed = true;\n\t\t},\n\t});\n}\n\n/** Async function that performs cleanup for a disposable resource */\nexport type AsyncDispose<T> = (value: T) => PromiseLike<unknown>;\n\n/**\n * Object with a Symbol.asyncDispose method for automatic async cleanup\n * @see {@link toAsyncDisposable}\n */\nexport type AsyncDisposable<T extends object> = ReturnType<\n\ttypeof toAsyncDisposable<T>\n>;\n\n/**\n * Make a value async disposable by adding a Symbol.asyncDispose method\n * @param value item to make disposable (must be an extensible object)\n * @param disposeFn async function that will cleanup the item\n * @returns value that's async disposable\n * @example\n * ```ts\n * // Direct usage with extensible objects\n * const resource = toAsyncDisposable({ stream: fs.createReadStream('file.txt') }, async (r) => {\n * await r.stream.close();\n * });\n * await using file = resource; // automatically disposed at end of scope\n *\n * // For non-extensible values (sealed objects, class instances), wrap them:\n * const database = new DatabaseConnection();\n * const disposableDb = toAsyncDisposable(\n * { connection: database },\n * async (wrapped) => {\n * await wrapped.connection.close();\n * }\n * );\n * await using db = disposableDb;\n * ```\n */\nexport function toAsyncDisposable<T extends object>(\n\tvalue: T,\n\tdisposeFn: AsyncDispose<T>,\n) {\n\tlet disposingPromise: PromiseLike<unknown> | undefined;\n\tconst originalDispose = hasAsyncDisposable(value)\n\t\t? value[Symbol.asyncDispose]\n\t\t: undefined;\n\n\treturn Object.assign(value, {\n\t\t[Symbol.asyncDispose]: async () => {\n\t\t\tif (disposingPromise == null) {\n\t\t\t\tdisposingPromise = (async () => {\n\t\t\t\t\tawait disposeFn(value);\n\t\t\t\t\tawait originalDispose?.call(value);\n\t\t\t\t})();\n\t\t\t}\n\t\t\tawait disposingPromise;\n\t\t},\n\t});\n}\n","export type ChannelOptions = {\n\t/**\n\t * Maximum amount of events to be buffered.\n\t * When buffer is full, oldest events are dropped.\n\t * Set to 0 to disable buffering (only deliver to waiting consumers).\n\t * @default 100\n\t */\n\tmaxBuffer?: number;\n\n\t/**\n\t * Whether to drain buffered events before ending iteration on dispose.\n\t * When true, buffered events will still be yielded after dispose is called.\n\t * When false, dispose immediately ends iteration and discards buffered events.\n\t * @default false\n\t */\n\tdrain?: boolean;\n};\n\nconst DEFAULT_OPTIONS = {\n\tmaxBuffer: 100,\n\tdrain: false,\n} satisfies ChannelOptions;\n\n/**\n * The iterator portion of a channel - this is what consumers see.\n */\nexport type ChannelIterator<T> = AsyncIterableIterator<T, undefined, void> & {\n\t[Symbol.dispose]: () => void;\n};\n\n/**\n * The full channel handle with push capability - for internal/producer use.\n */\nexport type Channel<T> = {\n\t/**\n\t * Push a value into the channel.\n\t * If there are waiting consumers, the value is delivered immediately.\n\t * Otherwise, it's buffered (subject to maxBuffer).\n\t */\n\tpush: (value: T) => void;\n\t/**\n\t * Whether the channel is closed.\n\t */\n\treadonly closed: boolean;\n\t/**\n\t * The async iterator for consuming values.\n\t * This is what should be exposed to downstream consumers.\n\t */\n\titerator: ChannelIterator<T>;\n};\n\n/**\n * Creates a buffered async channel for pushing values and consuming them via async iteration.\n *\n * This is a low-level primitive for building async iterators from push-based sources\n * like event emitters, intervals, or any producer that pushes values over time.\n *\n * The returned channel has a `push` method for producers and an `iterator` property\n * for consumers. Only expose the `iterator` to downstream code.\n *\n * @param options - Channel configuration\n * @returns A channel with push capability and a disposable async iterator\n *\n * @example\n * ```ts\n * // Basic usage - producer keeps the channel, consumer gets the iterator\n * const ch = channel<string>();\n *\n * // Producer side\n * ch.push(\"hello\");\n * ch.push(\"world\");\n *\n * // Consumer side - only sees the iterator\n * for await (const value of ch.iterator) {\n * console.log(value);\n * if (shouldStop) break;\n * }\n * ```\n *\n * @example\n * ```ts\n * // Building a custom async iterator\n * function myAsyncSource() {\n * const ch = channel<number>();\n * // ... set up producer that calls ch.push()\n * return ch.iterator; // Only expose the iterator\n * }\n * ```\n */\nexport function channel<T>(options?: ChannelOptions): Channel<T> {\n\tconst { maxBuffer, drain: shouldDrain } = { ...DEFAULT_OPTIONS, ...options };\n\ttype IterationResult = IteratorResult<T, undefined>;\n\n\tlet closed = false;\n\tconst events: T[] = [];\n\tconst waiters: ((value: IterationResult) => void)[] = [];\n\n\tconst doneResult = (): IterationResult => ({\n\t\tvalue: undefined,\n\t\tdone: true as const,\n\t});\n\n\tconst drainQueue = () => {\n\t\t// Pair off as many as possible, FIFO โ†” FIFO\n\t\twhile (!closed && events.length && waiters.length) {\n\t\t\tconst value = events.shift()!;\n\t\t\tconst resolve = waiters.shift()!;\n\t\t\tresolve({ value, done: false });\n\t\t}\n\t};\n\n\tconst push = (value: T) => {\n\t\tif (closed) return;\n\n\t\tif (maxBuffer <= 0) {\n\t\t\t// Only deliver to waiting consumers\n\t\t\tif (waiters.length) events.push(value);\n\t\t} else {\n\t\t\tevents.push(value);\n\t\t\tif (events.length > maxBuffer) events.shift();\n\t\t}\n\t\tdrainQueue();\n\t};\n\n\tconst dispose = () => {\n\t\tif (closed) return;\n\t\tclosed = true;\n\n\t\tif (shouldDrain) {\n\t\t\t// Drain buffered events to waiting consumers before signaling done\n\t\t\twhile (events.length && waiters.length) {\n\t\t\t\tconst value = events.shift()!;\n\t\t\t\tconst resolve = waiters.shift()!;\n\t\t\t\tresolve({ value, done: false });\n\t\t\t}\n\t\t}\n\n\t\t// Signal done to remaining waiters\n\t\twhile (waiters.length > 0) {\n\t\t\tconst waiter = waiters.shift();\n\t\t\twaiter?.(doneResult());\n\t\t}\n\t};\n\n\tconst iterator: ChannelIterator<T> = {\n\t\tasync next() {\n\t\t\t// If drain mode, return buffered events even after close\n\t\t\tif (shouldDrain && events.length) {\n\t\t\t\treturn { value: events.shift()!, done: false } as const;\n\t\t\t}\n\n\t\t\tif (closed) {\n\t\t\t\treturn doneResult();\n\t\t\t}\n\n\t\t\tif (events.length) {\n\t\t\t\treturn { value: events.shift()!, done: false } as const;\n\t\t\t}\n\n\t\t\t// Wait for the next event\n\t\t\treturn new Promise<IterationResult>((resolve) => {\n\t\t\t\twaiters.push(resolve);\n\t\t\t\tdrainQueue();\n\t\t\t});\n\t\t},\n\t\treturn() {\n\t\t\tdispose();\n\t\t\treturn Promise.resolve(doneResult());\n\t\t},\n\t\t[Symbol.asyncIterator]() {\n\t\t\treturn this;\n\t\t},\n\t\t[Symbol.dispose]: dispose,\n\t};\n\n\treturn {\n\t\tpush,\n\t\tget closed() {\n\t\t\treturn closed;\n\t\t},\n\t\titerator,\n\t};\n}\n","export type UnpackArray<T extends unknown[]> = T[\"length\"] extends 0\n\t? undefined\n\t: T[\"length\"] extends 1\n\t\t? T[0]\n\t\t: T;\n\nexport function unpackArray<T extends unknown[]>(values: T) {\n\treturn (\n\t\tvalues.length === 0 ? undefined : values.length === 1 ? values[0] : values\n\t) as UnpackArray<T>;\n}\n\n/**\n * Utility just invokes the method being called immediately.\n * Useful to scope resources to calling body.\n * @param fn Function to invoke\n * @returns Result of fn\n * @example\n * ```ts\n * import {invoke, once, toAsyncDisposable} from \"indisposed\";\n * import {WebSocketServer} from \"ws\";\n *\n * {\n * \tawait using wss = await invoke(async () => {\n * \t\tconst wss = toAsyncDisposable(\n * \t\t\tnew WebSocketServer({ host: \"127.0.0.1\", port: 0 }),\n * \t\t\t(wss) =>\n * \t\t\t\tnew Promise((resolve, reject) => {\n * \t\t\t\t\twss.close((err) => {\n * \t\t\t\t\t\tif (err) return reject(err);\n * \t\t\t\t\t\tresolve(undefined);\n * \t\t\t\t\t});\n * \t\t\t\t}),\n * \t\t);\n * \t\tusing listening = once(wss, \"listening\");\n * \t\tusing error = once(wss, \"error\", true);\n *\n * \t\tawait Promise.race([listening, error]);\n *\n * \t\treturn wss;\n * \t});\n *\n * \tconsole.log(\"Server ready at\", wss.address());\n * \t// ... handle connections ...\n * }\n * // wss is automatically closed once the scope ends\n * ```\n */\nexport function invoke<TResult>(fn: () => TResult) {\n\treturn fn();\n}\n","import type { EventHandlerParams, EventNames, Fn } from \"~/types\";\nimport { toDisposable } from \"./disposable\";\nimport { channel, type ChannelOptions } from \"./channel\";\nimport { type UnpackArray, unpackArray } from \"./fn\";\n\nexport type Subscription = (event: any, handler: Fn) => any;\n\n/**\n * Represents an event emitter with an `off` method for removing listeners.\n */\nexport type HasOff = {\n\toff: Subscription;\n};\n\n/**\n * Represents an event emitter with an `on` method for registering listeners.\n */\nexport type HasOn = {\n\ton: Subscription;\n} & HasOff;\n\n/**\n * Represents an event emitter with a `once` method for one-time listeners.\n */\nexport type HasOnce = {\n\tonce: Subscription;\n} & HasOff;\n\nexport type OnceResult<\n\tEventEmitter extends HasOnce,\n\tEvent extends EventNames<EventEmitter[\"once\"]>,\n\tRejects extends boolean,\n> = Rejects extends true\n\t? never\n\t: UnpackArray<EventHandlerParams<EventEmitter[\"once\"], Event>>;\n\n/**\n * Type-safe wrapper for event emitter's `once` method that preserves overload signatures.\n *\n * The return value is automatically unpacked:\n * - Handlers with 0 parameters resolve to `undefined`\n * - Handlers with 1 parameter resolve to that single value\n * - Handlers with 2+ parameters resolve to an array of values\n *\n * @param emitter - Event emitter with `once` and `off` methods\n * @param event - Event name (must match one of the emitter's overloads)\n * @param rejects - When true, the promise rejects with the handler arguments instead of resolving\n * @returns Disposable promise with the handler arguments and automatic cleanup via `off`\n *\n * @example\n * ```ts\n * type MyEmitter = {\n * once(event: 'data', handler: (value: string) => void): void;\n * once(event: 'error', handler: (error: Error) => void): number;\n * once(event: 'multi', handler: (x: number, y: number) => void): void;\n * off(event: string, handler: Fn): void;\n * };\n *\n * declare const emitter: MyEmitter;\n *\n * // Single parameter: returns the value directly\n * using result = once(emitter, 'data');\n * console.log((await result).toUpperCase()); // string\n *\n * // Multiple parameters: returns as array\n * using coords = once(emitter, 'multi');\n * const [x, y] = await coords; // [number, number]\n * ```\n */\nexport function once<\n\tEventEmitter extends HasOnce,\n\tconst Event extends EventNames<EventEmitter[\"once\"]>,\n\tconst Rejects extends boolean = false,\n>(emitter: EventEmitter, event: Event, rejects?: Rejects) {\n\tconst { promise, resolve, reject } =\n\t\tPromise.withResolvers<OnceResult<EventEmitter, Event, Rejects>>();\n\n\tconst handler: Fn = (...args: unknown[]) => {\n\t\tif (rejects) {\n\t\t\treject(args.length === 1 ? args[0] : args);\n\t\t\treturn;\n\t\t}\n\t\tresolve(unpackArray(args) as OnceResult<EventEmitter, Event, Rejects>);\n\t};\n\temitter.once(event, handler);\n\treturn toDisposable(promise, () => emitter.off(event, handler));\n}\n\nexport type OnResult<\n\tEventEmitter extends HasOn,\n\tEvent extends EventNames<EventEmitter[\"on\"]>,\n> = UnpackArray<EventHandlerParams<EventEmitter[\"on\"], Event>>;\n\n/**\n * Type-safe wrapper for event emitter's `on` method that returns an async iterator.\n *\n * The yielded values are automatically unpacked:\n * - Handlers with 0 parameters yield `undefined`\n * - Handlers with 1 parameter yield that single value\n * - Handlers with 2+ parameters yield an array of values\n *\n * @param emitter - Event emitter with `on` and `off` methods\n * @param event - Event name (must match one of the emitter's overloads)\n * @param options - Channel options (maxBuffer, etc.)\n * @returns Disposable async iterator that yields handler arguments\n *\n * @example\n * ```ts\n * type MyEmitter = {\n * on(event: 'data', handler: (value: string) => void): void;\n * on(event: 'position', handler: (x: number, y: number) => void): void;\n * off(event: string, handler: Fn): void;\n * };\n *\n * declare const emitter: MyEmitter;\n *\n * // Single parameter: yields values directly\n * using iterator = on(emitter, 'data');\n * for await (const value of iterator) {\n * console.log(value.toUpperCase()); // string\n * }\n *\n * // Multiple parameters: yields as array\n * using positions = on(emitter, 'position');\n * for await (const [x, y] of positions) {\n * console.log(`Position: ${x}, ${y}`);\n * }\n * ```\n */\nexport function on<\n\tEventEmitter extends HasOn,\n\tconst Event extends EventNames<EventEmitter[\"on\"]>,\n>(emitter: EventEmitter, event: Event, options?: ChannelOptions) {\n\ttype Item = OnResult<EventEmitter, Event>;\n\n\tconst ch = channel<Item>(options);\n\n\tconst handler = (...args: unknown[]) => {\n\t\tch.push(unpackArray(args) as Item);\n\t};\n\n\temitter.on(event, handler);\n\n\treturn toDisposable(ch.iterator, () => {\n\t\temitter.off(event, handler);\n\t});\n}\n","import { toDisposable } from \"./disposable\";\nimport { channel, type ChannelOptions } from \"./channel\";\n\n/**\n * Creates a disposable promise that resolves after a specified delay.\n *\n * The timeout is automatically cleared when disposed, preventing\n * memory leaks and unnecessary timer execution.\n *\n * @param ms - Delay in milliseconds before the promise resolves\n * @returns A disposable promise that resolves to `void` after the delay\n *\n * @example\n * ```ts\n * // Basic usage - wait for 1 second\n * await timeout(1000);\n * console.log(\"1 second passed\");\n * ```\n *\n * @example\n * ```ts\n * // With using - automatically clears timeout when scope exits\n * {\n * using timer = timeout(5000);\n * await timer;\n * } // timeout cleared if scope exits early\n * ```\n *\n * @example\n * ```ts\n * // Racing with other promises - losing timeout is cleaned up\n * {\n * using timer = timeout(10000);\n * using data = once(socket, \"data\");\n *\n * await Promise.race([timer, data]);\n * } // both cleaned up regardless of which wins\n * ```\n */\nexport function timeout(ms: number) {\n\tconst timingPromise = Promise.withResolvers<void>();\n\tconst timeoutId = setTimeout(timingPromise.resolve, ms);\n\n\treturn toDisposable(timingPromise.promise, () => clearTimeout(timeoutId));\n}\n\nexport type IntervalOptions = ChannelOptions;\n\n/**\n * Creates a disposable async iterator that yields incrementing numbers at a fixed interval.\n *\n * Values start at 0 and increment by 1 for each interval tick. The interval\n * is automatically cleared when the iterator is disposed or iteration ends.\n *\n * @param ms - Interval duration in milliseconds between each tick\n * @param options - Channel options for buffering behavior\n * @param options.maxBuffer - Maximum events to buffer (default: 100). Set to 0 for no buffering.\n * @param options.drain - Whether to drain buffer on close (default: false)\n * @returns A disposable async iterator yielding incrementing numbers\n *\n * @example\n * ```ts\n * // Basic usage - tick every second\n * {\n * using ticks = interval(1000);\n *\n * for await (const tick of ticks) {\n * console.log(`Tick ${tick}`); // 0, 1, 2, ...\n * if (tick >= 5) break;\n * }\n * } // interval automatically cleared\n * ```\n *\n * @example\n * ```ts\n * // Polling pattern\n * {\n * using poll = interval(5000);\n *\n * for await (const _ of poll) {\n * const status = await checkStatus();\n * if (status === \"complete\") break;\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * // With no buffering - only deliver to waiting consumers\n * const ticks = interval(100, { maxBuffer: 0 });\n * ```\n */\nexport function interval(ms: number, options?: IntervalOptions) {\n\tconst ch = channel<number>(options);\n\tlet currentValue = 0;\n\n\tconst intervalId = setInterval(() => {\n\t\tif (ch.closed) return;\n\t\tch.push(currentValue++);\n\t}, ms);\n\n\treturn toDisposable(ch.iterator, () => {\n\t\tclearInterval(intervalId);\n\t});\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -77,5 +77,5 @@
77
77
  "./src/polyfill.ts"
78
78
  ],
79
79
  "type": "module",
80
- "version": "0.0.8"
80
+ "version": "0.1.0"
81
81
  }