indisposed 0.1.0 → 0.2.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.
@@ -1,6 +1,6 @@
1
- import { EventHandlerParams, EventNames, Fn } from '../types';
2
- import { ChannelOptions } from './channel';
3
- import { UnpackArray } from './fn';
1
+ import { EventHandlerParams, EventNames, Fn } from '#/types';
2
+ import { ChannelOptions } from '#/functions/channel';
3
+ import { UnpackArray } from '#/functions/fn';
4
4
  export type Subscription = (event: any, handler: Fn) => any;
5
5
  /**
6
6
  * Represents an event emitter with an `off` method for removing listeners.
@@ -94,7 +94,7 @@ export type OnResult<EventEmitter extends HasOn, Event extends EventNames<EventE
94
94
  * }
95
95
  * ```
96
96
  */
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> & {
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
98
  [Symbol.dispose]: () => void;
99
99
  } & {
100
100
  [Symbol.dispose]: () => void;
@@ -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,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"}
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,qBAAqB,CAAC;AACnE,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,gBAAgB,CAAC;AAE/D,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"}
@@ -1,4 +1,4 @@
1
- import { ChannelOptions } from './channel';
1
+ import { ChannelOptions } from '#/functions/channel';
2
2
  /**
3
3
  * Creates a disposable promise that resolves after a specified delay.
4
4
  *
@@ -1 +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"}
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/functions/timing.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './no-polyfill';
1
+ export * from '#/no-polyfill';
2
2
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,34 +1,18 @@
1
- import { channel, interval, invoke, on, once, timeout, toAsyncDisposable, toDisposable } from "./no-polyfill.js";
2
- const hasNativeDispose = typeof Symbol.dispose === "symbol" && typeof Symbol.asyncDispose === "symbol";
3
- if (!hasNativeDispose) {
4
- try {
5
- await import("./explicit-resource-management-BSyjFgS-.js").then((n) => n.e);
6
- } catch {
7
- console.warn(
8
- `Symbol.dispose and Symbol.asyncDispose are not available in this environment.
9
- To enable polyfill support, install core-js as a dependency.`
10
- );
11
- }
1
+ import { a as invoke, c as toDisposable, i as once, n as timeout, o as channel, r as on, s as toAsyncDisposable, t as interval } from "./no-polyfill-D3v5MBct.js";
2
+ //#region src/polyfill.ts
3
+ if (!(typeof Symbol.dispose === "symbol" && typeof Symbol.asyncDispose === "symbol")) try {
4
+ await import("core-js/proposals/explicit-resource-management");
5
+ } catch {
6
+ console.warn(`Symbol.dispose and Symbol.asyncDispose are not available in this environment.
7
+ To enable polyfill support, install core-js as a dependency.`);
12
8
  }
13
- const hasNativeWithResolvers = typeof Promise.withResolvers === "function";
14
- if (!hasNativeWithResolvers) {
15
- try {
16
- await import("./with-resolvers-0tPpPN4C.js").then((n) => n.w);
17
- } catch {
18
- console.warn(
19
- `Promise.withResolvers is not available in this environment.
20
- To enable polyfill support, install core-js as a dependency.`
21
- );
22
- }
9
+ if (!(typeof Promise.withResolvers === "function")) try {
10
+ await import("core-js/actual/promise/with-resolvers");
11
+ } catch {
12
+ console.warn(`Promise.withResolvers is not available in this environment.
13
+ To enable polyfill support, install core-js as a dependency.`);
23
14
  }
24
- export {
25
- channel,
26
- interval,
27
- invoke,
28
- on,
29
- once,
30
- timeout,
31
- toAsyncDisposable,
32
- toDisposable
33
- };
34
- //# sourceMappingURL=index.js.map
15
+ //#endregion
16
+ export { channel, interval, invoke, on, once, timeout, toAsyncDisposable, toDisposable };
17
+
18
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/polyfill.ts"],"sourcesContent":["const hasNativeDispose =\n\ttypeof Symbol.dispose === \"symbol\" && typeof Symbol.asyncDispose === \"symbol\";\n\nif (!hasNativeDispose) {\n\ttry {\n\t\t//@ts-expect-error It exists\n\t\tawait import(\"core-js/proposals/explicit-resource-management\");\n\t} catch {\n\t\tconsole.warn(\n\t\t\t`Symbol.dispose and Symbol.asyncDispose are not available in this environment.\n\t\t\tTo enable polyfill support, install core-js as a dependency.`,\n\t\t);\n\t}\n}\n\nconst hasNativeWithResolvers = typeof Promise.withResolvers === \"function\";\n\nif (!hasNativeWithResolvers) {\n\ttry {\n\t\t//@ts-expect-error It exists\n\t\tawait import(\"core-js/actual/promise/with-resolvers\");\n\t} catch {\n\t\tconsole.warn(\n\t\t\t`Promise.withResolvers is not available in this environment.\n\t\t\tTo enable polyfill support, install core-js as a dependency.`,\n\t\t);\n\t}\n}\n"],"names":[],"mappings":";AAAA,MAAM,mBACL,OAAO,OAAO,YAAY,YAAY,OAAO,OAAO,iBAAiB;AAEtE,IAAI,CAAC,kBAAkB;AACtB,MAAI;AAEH,UAAM,OAAO,4CAAgD,EAAA,KAAA,OAAA,EAAA,CAAA;AAAA,EAC9D,QAAQ;AACP,YAAQ;AAAA,MACP;AAAA;AAAA,IAAA;AAAA,EAGF;AACD;AAEA,MAAM,yBAAyB,OAAO,QAAQ,kBAAkB;AAEhE,IAAI,CAAC,wBAAwB;AAC5B,MAAI;AAEH,UAAM,OAAO,8BAAuC,EAAA,KAAA,OAAA,EAAA,CAAA;AAAA,EACrD,QAAQ;AACP,YAAQ;AAAA,MACP;AAAA;AAAA,IAAA;AAAA,EAGF;AACD;"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/polyfill.ts"],"sourcesContent":["const hasNativeDispose =\n\ttypeof Symbol.dispose === \"symbol\" && typeof Symbol.asyncDispose === \"symbol\";\n\nif (!hasNativeDispose) {\n\ttry {\n\t\t//@ts-expect-error It exists\n\t\tawait import(\"core-js/proposals/explicit-resource-management\");\n\t} catch {\n\t\tconsole.warn(\n\t\t\t`Symbol.dispose and Symbol.asyncDispose are not available in this environment.\n\t\t\tTo enable polyfill support, install core-js as a dependency.`,\n\t\t);\n\t}\n}\n\nconst hasNativeWithResolvers = typeof Promise.withResolvers === \"function\";\n\nif (!hasNativeWithResolvers) {\n\ttry {\n\t\t//@ts-expect-error It exists\n\t\tawait import(\"core-js/actual/promise/with-resolvers\");\n\t} catch {\n\t\tconsole.warn(\n\t\t\t`Promise.withResolvers is not available in this environment.\n\t\t\tTo enable polyfill support, install core-js as a dependency.`,\n\t\t);\n\t}\n}\n"],"mappings":";;AAGA,IAAI,EAFH,OAAO,OAAO,YAAY,YAAY,OAAO,OAAO,iBAAiB,WAGrE,IAAI;CAEH,MAAM,OAAO;AACd,QAAQ;CACP,QAAQ,KACP;gEAED;AACD;AAKD,IAAI,EAF2B,OAAO,QAAQ,kBAAkB,aAG/D,IAAI;CAEH,MAAM,OAAO;AACd,QAAQ;CACP,QAAQ,KACP;gEAED;AACD"}
@@ -0,0 +1,430 @@
1
+ //#region src/functions/disposable.ts
2
+ function hasDisposable(value) {
3
+ return value != null && typeof value === "object" && typeof value[Symbol.dispose] === "function";
4
+ }
5
+ function hasAsyncDisposable(value) {
6
+ return value != null && typeof value === "object" && typeof value[Symbol.asyncDispose] === "function";
7
+ }
8
+ /**
9
+ * Make a value disposable by adding a Symbol.dispose method
10
+ * @param value item to make disposable (must be an extensible object)
11
+ * @param disposeFn function that will cleanup the item
12
+ * @returns value that's disposable
13
+ * @example
14
+ * ```ts
15
+ * // Direct usage with extensible objects
16
+ * const resource = toDisposable({ handle: 123 }, (r) => closeHandle(r.handle));
17
+ * using handle = resource; // automatically disposed at end of scope
18
+ *
19
+ * // For non-extensible values (primitives, sealed objects, class instances), wrap them:
20
+ * const connection = new WebSocket('ws://localhost');
21
+ * const disposableConnection = toDisposable(
22
+ * { socket: connection },
23
+ * (wrapped) => wrapped.socket.close()
24
+ * );
25
+ * using conn = disposableConnection;
26
+ * ```
27
+ */
28
+ function toDisposable(value, disposeFn) {
29
+ let disposed = false;
30
+ const originalDispose = hasDisposable(value) ? value[Symbol.dispose] : void 0;
31
+ return Object.assign(value, { [Symbol.dispose]: () => {
32
+ if (disposed) return;
33
+ disposeFn(value);
34
+ originalDispose?.call(value);
35
+ disposed = true;
36
+ } });
37
+ }
38
+ /**
39
+ * Make a value async disposable by adding a Symbol.asyncDispose method
40
+ * @param value item to make disposable (must be an extensible object)
41
+ * @param disposeFn async function that will cleanup the item
42
+ * @returns value that's async disposable
43
+ * @example
44
+ * ```ts
45
+ * // Direct usage with extensible objects
46
+ * const resource = toAsyncDisposable({ stream: fs.createReadStream('file.txt') }, async (r) => {
47
+ * await r.stream.close();
48
+ * });
49
+ * await using file = resource; // automatically disposed at end of scope
50
+ *
51
+ * // For non-extensible values (sealed objects, class instances), wrap them:
52
+ * const database = new DatabaseConnection();
53
+ * const disposableDb = toAsyncDisposable(
54
+ * { connection: database },
55
+ * async (wrapped) => {
56
+ * await wrapped.connection.close();
57
+ * }
58
+ * );
59
+ * await using db = disposableDb;
60
+ * ```
61
+ */
62
+ function toAsyncDisposable(value, disposeFn) {
63
+ let disposingPromise;
64
+ const originalDispose = hasAsyncDisposable(value) ? value[Symbol.asyncDispose] : void 0;
65
+ return Object.assign(value, { [Symbol.asyncDispose]: async () => {
66
+ if (disposingPromise == null) disposingPromise = (async () => {
67
+ await disposeFn(value);
68
+ await originalDispose?.call(value);
69
+ })();
70
+ await disposingPromise;
71
+ } });
72
+ }
73
+ //#endregion
74
+ //#region src/functions/channel.ts
75
+ var DEFAULT_OPTIONS = {
76
+ maxBuffer: 100,
77
+ drain: false
78
+ };
79
+ /**
80
+ * Creates a buffered async channel for pushing values and consuming them via async iteration.
81
+ *
82
+ * This is a low-level primitive for building async iterators from push-based sources
83
+ * like event emitters, intervals, or any producer that pushes values over time.
84
+ *
85
+ * The returned channel has a `push` method for producers and an `iterator` property
86
+ * for consumers. Only expose the `iterator` to downstream code.
87
+ *
88
+ * @param options - Channel configuration
89
+ * @returns A channel with push capability and a disposable async iterator
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * // Basic usage - producer keeps the channel, consumer gets the iterator
94
+ * const ch = channel<string>();
95
+ *
96
+ * // Producer side
97
+ * ch.push("hello");
98
+ * ch.push("world");
99
+ *
100
+ * // Consumer side - only sees the iterator
101
+ * for await (const value of ch.iterator) {
102
+ * console.log(value);
103
+ * if (shouldStop) break;
104
+ * }
105
+ * ```
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * // Building a custom async iterator
110
+ * function myAsyncSource() {
111
+ * const ch = channel<number>();
112
+ * // ... set up producer that calls ch.push()
113
+ * return ch.iterator; // Only expose the iterator
114
+ * }
115
+ * ```
116
+ */
117
+ function channel(options) {
118
+ const { maxBuffer, drain: shouldDrain } = {
119
+ ...DEFAULT_OPTIONS,
120
+ ...options
121
+ };
122
+ let closed = false;
123
+ const events = [];
124
+ const waiters = [];
125
+ const doneResult = () => ({
126
+ value: void 0,
127
+ done: true
128
+ });
129
+ const drainQueue = () => {
130
+ while (!closed && events.length && waiters.length) {
131
+ const value = events.shift();
132
+ waiters.shift()({
133
+ value,
134
+ done: false
135
+ });
136
+ }
137
+ };
138
+ const push = (value) => {
139
+ if (closed) return;
140
+ if (maxBuffer <= 0) {
141
+ if (waiters.length) events.push(value);
142
+ } else {
143
+ events.push(value);
144
+ if (events.length > maxBuffer) events.shift();
145
+ }
146
+ drainQueue();
147
+ };
148
+ const dispose = () => {
149
+ if (closed) return;
150
+ closed = true;
151
+ if (shouldDrain) while (events.length && waiters.length) {
152
+ const value = events.shift();
153
+ waiters.shift()({
154
+ value,
155
+ done: false
156
+ });
157
+ }
158
+ while (waiters.length > 0) waiters.shift()?.(doneResult());
159
+ };
160
+ return {
161
+ push,
162
+ get closed() {
163
+ return closed;
164
+ },
165
+ iterator: {
166
+ async next() {
167
+ if (shouldDrain && events.length) return {
168
+ value: events.shift(),
169
+ done: false
170
+ };
171
+ if (closed) return doneResult();
172
+ if (events.length) return {
173
+ value: events.shift(),
174
+ done: false
175
+ };
176
+ return new Promise((resolve) => {
177
+ waiters.push(resolve);
178
+ drainQueue();
179
+ });
180
+ },
181
+ return() {
182
+ dispose();
183
+ return Promise.resolve(doneResult());
184
+ },
185
+ [Symbol.asyncIterator]() {
186
+ return this;
187
+ },
188
+ [Symbol.dispose]: dispose
189
+ }
190
+ };
191
+ }
192
+ //#endregion
193
+ //#region src/functions/fn.ts
194
+ function unpackArray(values) {
195
+ return values.length === 0 ? void 0 : values.length === 1 ? values[0] : values;
196
+ }
197
+ /**
198
+ * Utility just invokes the method being called immediately.
199
+ * Useful to scope resources to calling body.
200
+ * @param fn Function to invoke
201
+ * @returns Result of fn
202
+ * @example
203
+ * ```ts
204
+ * import {invoke, once, toAsyncDisposable} from "indisposed";
205
+ * import {WebSocketServer} from "ws";
206
+ *
207
+ * {
208
+ * await using wss = await invoke(async () => {
209
+ * const wss = toAsyncDisposable(
210
+ * new WebSocketServer({ host: "127.0.0.1", port: 0 }),
211
+ * (wss) =>
212
+ * new Promise((resolve, reject) => {
213
+ * wss.close((err) => {
214
+ * if (err) return reject(err);
215
+ * resolve(undefined);
216
+ * });
217
+ * }),
218
+ * );
219
+ * using listening = once(wss, "listening");
220
+ * using error = once(wss, "error", true);
221
+ *
222
+ * await Promise.race([listening, error]);
223
+ *
224
+ * return wss;
225
+ * });
226
+ *
227
+ * console.log("Server ready at", wss.address());
228
+ * // ... handle connections ...
229
+ * }
230
+ * // wss is automatically closed once the scope ends
231
+ * ```
232
+ */
233
+ function invoke(fn) {
234
+ return fn();
235
+ }
236
+ //#endregion
237
+ //#region src/functions/handlers.ts
238
+ /**
239
+ * Type-safe wrapper for event emitter's `once` method that preserves overload signatures.
240
+ *
241
+ * The return value is automatically unpacked:
242
+ * - Handlers with 0 parameters resolve to `undefined`
243
+ * - Handlers with 1 parameter resolve to that single value
244
+ * - Handlers with 2+ parameters resolve to an array of values
245
+ *
246
+ * @param emitter - Event emitter with `once` and `off` methods
247
+ * @param event - Event name (must match one of the emitter's overloads)
248
+ * @param rejects - When true, the promise rejects with the handler arguments instead of resolving
249
+ * @returns Disposable promise with the handler arguments and automatic cleanup via `off`
250
+ *
251
+ * @example
252
+ * ```ts
253
+ * type MyEmitter = {
254
+ * once(event: 'data', handler: (value: string) => void): void;
255
+ * once(event: 'error', handler: (error: Error) => void): number;
256
+ * once(event: 'multi', handler: (x: number, y: number) => void): void;
257
+ * off(event: string, handler: Fn): void;
258
+ * };
259
+ *
260
+ * declare const emitter: MyEmitter;
261
+ *
262
+ * // Single parameter: returns the value directly
263
+ * using result = once(emitter, 'data');
264
+ * console.log((await result).toUpperCase()); // string
265
+ *
266
+ * // Multiple parameters: returns as array
267
+ * using coords = once(emitter, 'multi');
268
+ * const [x, y] = await coords; // [number, number]
269
+ * ```
270
+ */
271
+ function once(emitter, event, rejects) {
272
+ const { promise, resolve, reject } = Promise.withResolvers();
273
+ const handler = (...args) => {
274
+ if (rejects) {
275
+ reject(args.length === 1 ? args[0] : args);
276
+ return;
277
+ }
278
+ resolve(unpackArray(args));
279
+ };
280
+ emitter.once(event, handler);
281
+ return toDisposable(promise, () => emitter.off(event, handler));
282
+ }
283
+ /**
284
+ * Type-safe wrapper for event emitter's `on` method that returns an async iterator.
285
+ *
286
+ * The yielded values are automatically unpacked:
287
+ * - Handlers with 0 parameters yield `undefined`
288
+ * - Handlers with 1 parameter yield that single value
289
+ * - Handlers with 2+ parameters yield an array of values
290
+ *
291
+ * @param emitter - Event emitter with `on` and `off` methods
292
+ * @param event - Event name (must match one of the emitter's overloads)
293
+ * @param options - Channel options (maxBuffer, etc.)
294
+ * @returns Disposable async iterator that yields handler arguments
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * type MyEmitter = {
299
+ * on(event: 'data', handler: (value: string) => void): void;
300
+ * on(event: 'position', handler: (x: number, y: number) => void): void;
301
+ * off(event: string, handler: Fn): void;
302
+ * };
303
+ *
304
+ * declare const emitter: MyEmitter;
305
+ *
306
+ * // Single parameter: yields values directly
307
+ * using iterator = on(emitter, 'data');
308
+ * for await (const value of iterator) {
309
+ * console.log(value.toUpperCase()); // string
310
+ * }
311
+ *
312
+ * // Multiple parameters: yields as array
313
+ * using positions = on(emitter, 'position');
314
+ * for await (const [x, y] of positions) {
315
+ * console.log(`Position: ${x}, ${y}`);
316
+ * }
317
+ * ```
318
+ */
319
+ function on(emitter, event, options) {
320
+ const ch = channel(options);
321
+ const handler = (...args) => {
322
+ ch.push(unpackArray(args));
323
+ };
324
+ emitter.on(event, handler);
325
+ return toDisposable(ch.iterator, () => {
326
+ emitter.off(event, handler);
327
+ });
328
+ }
329
+ //#endregion
330
+ //#region src/functions/timing.ts
331
+ /**
332
+ * Creates a disposable promise that resolves after a specified delay.
333
+ *
334
+ * The timeout is automatically cleared when disposed, preventing
335
+ * memory leaks and unnecessary timer execution.
336
+ *
337
+ * @param ms - Delay in milliseconds before the promise resolves
338
+ * @returns A disposable promise that resolves to `void` after the delay
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * // Basic usage - wait for 1 second
343
+ * await timeout(1000);
344
+ * console.log("1 second passed");
345
+ * ```
346
+ *
347
+ * @example
348
+ * ```ts
349
+ * // With using - automatically clears timeout when scope exits
350
+ * {
351
+ * using timer = timeout(5000);
352
+ * await timer;
353
+ * } // timeout cleared if scope exits early
354
+ * ```
355
+ *
356
+ * @example
357
+ * ```ts
358
+ * // Racing with other promises - losing timeout is cleaned up
359
+ * {
360
+ * using timer = timeout(10000);
361
+ * using data = once(socket, "data");
362
+ *
363
+ * await Promise.race([timer, data]);
364
+ * } // both cleaned up regardless of which wins
365
+ * ```
366
+ */
367
+ function timeout(ms) {
368
+ const timingPromise = Promise.withResolvers();
369
+ const timeoutId = setTimeout(timingPromise.resolve, ms);
370
+ return toDisposable(timingPromise.promise, () => clearTimeout(timeoutId));
371
+ }
372
+ /**
373
+ * Creates a disposable async iterator that yields incrementing numbers at a fixed interval.
374
+ *
375
+ * Values start at 0 and increment by 1 for each interval tick. The interval
376
+ * is automatically cleared when the iterator is disposed or iteration ends.
377
+ *
378
+ * @param ms - Interval duration in milliseconds between each tick
379
+ * @param options - Channel options for buffering behavior
380
+ * @param options.maxBuffer - Maximum events to buffer (default: 100). Set to 0 for no buffering.
381
+ * @param options.drain - Whether to drain buffer on close (default: false)
382
+ * @returns A disposable async iterator yielding incrementing numbers
383
+ *
384
+ * @example
385
+ * ```ts
386
+ * // Basic usage - tick every second
387
+ * {
388
+ * using ticks = interval(1000);
389
+ *
390
+ * for await (const tick of ticks) {
391
+ * console.log(`Tick ${tick}`); // 0, 1, 2, ...
392
+ * if (tick >= 5) break;
393
+ * }
394
+ * } // interval automatically cleared
395
+ * ```
396
+ *
397
+ * @example
398
+ * ```ts
399
+ * // Polling pattern
400
+ * {
401
+ * using poll = interval(5000);
402
+ *
403
+ * for await (const _ of poll) {
404
+ * const status = await checkStatus();
405
+ * if (status === "complete") break;
406
+ * }
407
+ * }
408
+ * ```
409
+ *
410
+ * @example
411
+ * ```ts
412
+ * // With no buffering - only deliver to waiting consumers
413
+ * const ticks = interval(100, { maxBuffer: 0 });
414
+ * ```
415
+ */
416
+ function interval(ms, options) {
417
+ const ch = channel(options);
418
+ let currentValue = 0;
419
+ const intervalId = setInterval(() => {
420
+ if (ch.closed) return;
421
+ ch.push(currentValue++);
422
+ }, ms);
423
+ return toDisposable(ch.iterator, () => {
424
+ clearInterval(intervalId);
425
+ });
426
+ }
427
+ //#endregion
428
+ export { invoke as a, toDisposable as c, once as i, timeout as n, channel as o, on as r, toAsyncDisposable as s, interval as t };
429
+
430
+ //# sourceMappingURL=no-polyfill-D3v5MBct.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-polyfill-D3v5MBct.js","names":[],"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 \"#/functions/disposable\";\nimport { channel, type ChannelOptions } from \"#/functions/channel\";\nimport { type UnpackArray, unpackArray } from \"#/functions/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 \"#/functions/disposable\";\nimport { channel, type ChannelOptions } from \"#/functions/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"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- export * from './functions/disposable';
2
- export * from './functions/handlers';
3
- export * from './functions/channel';
4
- export * from './functions/timing';
5
- export { invoke } from './functions/fn';
1
+ export * from '#/functions/disposable';
2
+ export * from '#/functions/handlers';
3
+ export * from '#/functions/channel';
4
+ export * from '#/functions/timing';
5
+ export { invoke } from '#/functions/fn';
6
6
  //# sourceMappingURL=no-polyfill.d.ts.map