uneventful 0.0.4 → 0.0.6

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.
@@ -0,0 +1,966 @@
1
+ /**
2
+ * Resolve a {@link Request} with a value.
3
+ *
4
+ * (For a curried version, see {@link resolver}.)
5
+ *
6
+ * @category Requests and Results
7
+ */
8
+ declare function resolve<T>(request: Request<T>, val: T): void;
9
+ /**
10
+ * Reject a {@link Request} with a reason.
11
+ *
12
+ * (For a curried version, see {@link rejecter}.)
13
+ *
14
+ * @category Requests and Results
15
+ */
16
+ declare function reject(request: Request<any>, reason: any): void;
17
+ /**
18
+ * Create a callback that will resolve the given {@link Request} with a value.
19
+ *
20
+ * @category Requests and Results
21
+ */
22
+ declare function resolver<T>(request: Request<T>): (val: T) => void;
23
+ /**
24
+ * Create a callback that will reject the given {@link Request} with a reason.
25
+ *
26
+ * @category Requests and Results
27
+ */
28
+ declare function rejecter(request: Request<any>): (err: any) => void;
29
+ /**
30
+ * A function that does nothing and returns void.
31
+ *
32
+ * @category Stream Consumers
33
+ */
34
+ declare function noop(): void;
35
+ /**
36
+ * An {@link ErrorResult} that hasn't yet been "handled" (by being passed to an
37
+ * error-specific handler, converted to a promise, given to {@link markHandled},
38
+ * etc.)
39
+ *
40
+ * @category Types and Interfaces
41
+ */
42
+ type UnhandledError = {
43
+ op: "throw";
44
+ val: undefined;
45
+ err: any;
46
+ };
47
+ /**
48
+ * An {@link ErrorResult} that has been marked "handled" (by being passed to an
49
+ * error-specific handler, converted to a promise, given to {@link markHandled},
50
+ * etc.)
51
+ *
52
+ * @category Types and Interfaces
53
+ */
54
+ type HandledError = {
55
+ op: "throw";
56
+ val: null;
57
+ err: any;
58
+ };
59
+ /**
60
+ * A result passed to a job's cleanup callbacks, or supplied by its
61
+ * .{@link Job.result result}() method.
62
+ *
63
+ * You can inspect a JobResult using functions like {@link isCancel}(),
64
+ * {@link isError}(), and {@link isValue}(). {@link getResult}() can be used to
65
+ * unwrap the value or throw the error.
66
+ *
67
+ * @category Types and Interfaces
68
+ */
69
+ type JobResult<T> = ValueResult<T> | ErrorResult | CancelResult;
70
+ /**
71
+ * A {@link JobResult} that indicates the job was canceled by its creator (via
72
+ * end() or restart()).
73
+ *
74
+ * @category Types and Interfaces
75
+ */
76
+ type CancelResult = {
77
+ op: "cancel";
78
+ val: undefined;
79
+ err: undefined;
80
+ };
81
+ /**
82
+ * The {@link JobResult} used to indicate a canceled job.
83
+ *
84
+ * @category Requests and Results
85
+ */
86
+ declare const CancelResult: Readonly<CancelResult>;
87
+ /**
88
+ * A {@link JobResult} that indicates the job was ended via a return() value.
89
+ *
90
+ * @category Types and Interfaces
91
+ */
92
+ type ValueResult<T> = {
93
+ op: "next";
94
+ val: T;
95
+ err: undefined;
96
+ };
97
+ /**
98
+ * Create a {@link ValueResult} from a value
99
+ *
100
+ * @category Requests and Results
101
+ */
102
+ declare function ValueResult<T>(val: T): ValueResult<T>;
103
+ /**
104
+ * A {@link JobResult} that indicates the job was ended via a throw() or other
105
+ * error.
106
+ *
107
+ * @category Types and Interfaces
108
+ */
109
+ type ErrorResult = UnhandledError | HandledError;
110
+ /**
111
+ * Create an {@link ErrorResult} from an error
112
+ *
113
+ * @category Requests and Results
114
+ */
115
+ declare function ErrorResult(err: any): UnhandledError;
116
+ /**
117
+ * Returns true if the given result is a {@link CancelResult}.
118
+ *
119
+ * @category Requests and Results
120
+ */
121
+ declare function isCancel(res: JobResult<any> | undefined): res is CancelResult;
122
+ /**
123
+ * Returns true if the given result is a {@link ValueResult}.
124
+ *
125
+ * @category Requests and Results
126
+ */
127
+ declare function isValue<T>(res: JobResult<T> | undefined): res is ValueResult<T>;
128
+ /**
129
+ * Returns true if the given result is a {@link ErrorResult}.
130
+ *
131
+ * @category Requests and Results
132
+ */
133
+ declare function isError(res: JobResult<any> | undefined): res is ErrorResult;
134
+ /**
135
+ * Returns true if the given result is an {@link UnhandledError}.
136
+ *
137
+ * @category Requests and Results
138
+ */
139
+ declare function isUnhandled(res: JobResult<any> | undefined): res is UnhandledError;
140
+ /**
141
+ * Returns true if the given result is a {@link HandledError} (an
142
+ * {@link ErrorResult} that has been touched by {@link markHandled}).
143
+ *
144
+ * @category Requests and Results
145
+ */
146
+ declare function isHandled(res: JobResult<any> | undefined): res is HandledError;
147
+ /**
148
+ * Return the error of an {@link ErrorResult} and mark it as handled. The
149
+ * {@link ErrorResult} is mutated in-place to become a {@link HandledError}.
150
+ *
151
+ * @category Requests and Results
152
+ */
153
+ declare function markHandled(res: ErrorResult): any;
154
+ /**
155
+ * Get the return value from a {@link JobResult}, throwing an appropriate error
156
+ * if the result isn't a {@link ValueResult}.
157
+ *
158
+ * @param res The job result you want to unwrap. Must not be undefined!
159
+ *
160
+ * @returns The value if the result is a {@link ValueResult}, or a thrown error
161
+ * if it's an {@link ErrorResult}. A {@link CancelError} is thrown if the job
162
+ * was canceled, or the error in the result is thrown.
163
+ *
164
+ * If the result is an error, it is marked as handled.
165
+ *
166
+ * @category Jobs
167
+ */
168
+ declare function getResult<T>(res: JobResult<T>): T;
169
+ /**
170
+ * Fulfill a Promise from a {@link JobResult}
171
+ *
172
+ * If the result is a {@link CancelResult}, the promise is rejected with a
173
+ * {@link CancelError}. Otherwise it is resolved or rejected according to the
174
+ * state of the result.
175
+ *
176
+ * @param resolve A value-taking function (first arg to `new Promise` callback)
177
+ *
178
+ * @param reject An error-taking function (second arg to `new Promise` callback)
179
+ *
180
+ * @param res The job result you want to settle the promise with. An error will
181
+ * be thrown if it's undefined.
182
+ *
183
+ * If the result is an error, it is marked as handled.
184
+ *
185
+ * @category Requests and Results
186
+ */
187
+ declare function fulfillPromise<T>(resolve: (v: T) => void, reject: (e: any) => void, res: JobResult<T>): void;
188
+ /**
189
+ * Propagate a {@link JobResult} to another job
190
+ *
191
+ * If the result is a {@link CancelResult}, the job will throw with a
192
+ * {@link CancelError}. Otherwise it is resolved or rejected according to the
193
+ * state of the result.
194
+ *
195
+ * @param job The job to terminate. If it's already ended, nothing changes: the
196
+ * result is not propagated and the error (if any) is not marked as handled.
197
+ *
198
+ * @param res The job result you want to settle the job with. An error will be
199
+ * thrown if it's undefined. If the result is an error, it is marked as
200
+ * handled.
201
+ *
202
+ * @category Requests and Results
203
+ */
204
+ declare function propagateResult<T>(job: Job<T>, res: JobResult<T>): void;
205
+ /**
206
+ * Error thrown when waiting for a result from a job that is canceled.
207
+ *
208
+ * If you `await`, `yield *`, `.then()`, `.catch()`, {@link getResult}() or
209
+ * otherwise wait on the result of a job that is canceled, this is the type
210
+ * of error you'll get.
211
+ *
212
+ * @category Errors
213
+ */
214
+ declare class CancelError extends Error {
215
+ }
216
+
217
+ /**
218
+ * A backpressure controller: returns true if downstream is ready to accept
219
+ * data.
220
+ *
221
+ * @param cb (optional) - a callback to run when the downstream consumer wishes
222
+ * to resume event production (i.e., when a sink calls
223
+ * {@link Throttle.resume}()). The callback is automatically unregistered when
224
+ * invoked, so the producer must re-register it after each call if it wishes to
225
+ * keep being called.
226
+ *
227
+ * @category Types and Interfaces
228
+ */
229
+ type Backpressure = (cb?: () => any) => boolean;
230
+ /**
231
+ * Create a backpressure control function for the given connection
232
+ *
233
+ * @category Stream Producers
234
+ */
235
+ declare function backpressure(inlet?: Inlet): Backpressure;
236
+ /**
237
+ * Control backpressure for listening streams. This interface is the API
238
+ * internal to the implementation of {@link backpressure}(). Unless you're
239
+ * implementing a backpressurable stream yourself, see the {@link Throttle}
240
+ * interface instead.
241
+ *
242
+ * @category Types and Interfaces
243
+ */
244
+ interface Inlet {
245
+ /** Is the main connection open? (i.e. is the creating job not closed yet?) */
246
+ isOpen(): boolean;
247
+ /** Is the connection ready to receive data? */
248
+ isReady(): boolean;
249
+ /**
250
+ * Register a callback to produce more data when the inlet is resumed
251
+ * (The callback is unregistered if the supplied job ends.)
252
+ */
253
+ onReady(cb: () => any, job: Job): this;
254
+ }
255
+ /**
256
+ * Control backpressure for listening streams
257
+ *
258
+ * Obtain instances via {@link throttle}(), then pass them into the appropriate
259
+ * stream-consuming API. (e.g. {@link connect}).
260
+ *
261
+ * @category Types and Interfaces
262
+ */
263
+ interface Throttle extends Inlet {
264
+ /** Set inlet status to "paused". */
265
+ pause(): void;
266
+ /**
267
+ * Un-pause, and iterate backpressure-able sources' onReady callbacks to
268
+ * resume sending immediately. (i.e., synchronously!)
269
+ */
270
+ resume(): void;
271
+ }
272
+ /**
273
+ * A Connection is a job that returns void when the connected stream ends
274
+ * itself. If the stream doesn't end itself (e.g. it's an event listener), the
275
+ * job will never return, and only end with a cancel or throw.
276
+ *
277
+ * @category Types and Interfaces
278
+ */
279
+ type Connection = Job<void>;
280
+ /**
281
+ * A Source is a function that can be called to arrange for data to be
282
+ * produced and sent to a {@link Sink} function for consumption, until the
283
+ * associated {@link Connection} is closed (either by the source or the sink,
284
+ * e.g. if the sink doesn't want more data or the source has no more to send).
285
+ *
286
+ * If the source is a backpressurable stream, it can use the (optional) supplied
287
+ * inlet (usually a {@link throttle}()) to rate-limit its output.
288
+ *
289
+ * A producer function *must* return the special {@link IsStream} value, so
290
+ * TypeScript can tell what functions are usable as sources. (Otherwise any
291
+ * void function with no arguments would appear to be usable as a source!)
292
+ *
293
+ * @category Types and Interfaces
294
+ */
295
+ interface Source<T> {
296
+ /** Subscribe sink to receive values */
297
+ (sink: Sink<T>, conn?: Connection, inlet?: Throttle | Inlet): typeof IsStream;
298
+ }
299
+ /**
300
+ * An uneventful stream is either a {@link Source} or a {@link SignalSource}.
301
+ * (Signals actually implement the {@link Source} interface as an overload, but
302
+ * TypeScript gets confused about that sometimes, so we generally declare our
303
+ * stream *inputs* as `Stream<T>` and our stream *outputs* as {@link Source}, so
304
+ * that TypeScript knows what's what.
305
+ *
306
+ * @category Types and Interfaces
307
+ */
308
+ type Stream<T> = Source<T> | SignalSource<T>;
309
+ /**
310
+ * The call signatures implemented by signals. (They can be used as sources, or
311
+ * called with no arguments to return a value.)
312
+ *
313
+ * This type is needed because TypeScript won't infer the overloads of
314
+ * {@link Signal} correctly otherwise. (Specifically, it won't allow it to be
315
+ * used as a zero-agument function.)
316
+ *
317
+ * @category Types and Interfaces
318
+ */
319
+ type SignalSource<T> = Source<T> & {
320
+ /** A signal object can be called to get its current value */
321
+ (): T;
322
+ };
323
+ /**
324
+ * A specially-typed string used to verify that a function supports uneventful's
325
+ * streaming protocol. Return it from a function to implement the
326
+ * {@link Source} type.
327
+ *
328
+ * @category Types and Interfaces
329
+ */
330
+ declare const IsStream: "uneventful/is-stream";
331
+ /**
332
+ * A `Sink` is a function that receives data from a {@link Stream}.
333
+ *
334
+ * @category Types and Interfaces
335
+ */
336
+ type Sink<T> = (val: T) => void;
337
+ /**
338
+ * A `Transformer` is a function that takes one stream and returns another,
339
+ * possibly one that produces data of a different type. Most operator functions
340
+ * return a transformer, allowing them to be combined via {@link pipe}().
341
+ *
342
+ * @category Types and Interfaces
343
+ */
344
+ type Transformer<T, V = T> = (input: Stream<T>) => Source<V>;
345
+ /**
346
+ * Subscribe a sink to a stream, returning a nested job. (Shorthand for
347
+ * .{@link Job.connect connect}(...) on the active job.)
348
+ *
349
+ * @param src An event source or signal
350
+ * @param sink A callback that will receive the events
351
+ * @param inlet Optional - a {@link throttle}() to control backpressure
352
+ *
353
+ * @returns A job that can be aborted to end the subscription, and which will
354
+ * end naturally (with a void return or error) if the stream ends itself.
355
+ *
356
+ * @category Stream Consumers
357
+ */
358
+ declare function connect<T>(src: Stream<T>, sink: Sink<T>, inlet?: Throttle | Inlet): Connection;
359
+ /**
360
+ * Create a backpressure controller for a stream. Pass it to one or more
361
+ * sources you're connecting to, and if they support backpressure they'll
362
+ * respond when you call its .pause() and .resume() methods.
363
+ *
364
+ * @param job - Optional: a job that controls readiness. (The throttle will
365
+ * pause indefinitely when the job ends.) Defaults to the currently-active job,
366
+ * but unlike most such defaults, it won't throw if no job is active.
367
+ *
368
+ * @category Stream Consumers
369
+ */
370
+ declare function throttle(job?: Job): Throttle;
371
+ /**
372
+ * Pipe a stream (or anything else) through a series of single-argument
373
+ * functions/operators
374
+ *
375
+ * e.g. the following creates a stream that outputs 4 and then 6:
376
+ *
377
+ * ```ts
378
+ * pipe(fromIterable([1,2,3,4]), skip(1), take(2), map(x => x*2))
379
+ * ```
380
+ *
381
+ * The first argument to pipe() can be any value, but all other arguments must
382
+ * be functions. The value is passed to the first function, and then the result
383
+ * is passed to the next function in turn, until all provided functions have
384
+ * been called with the result of the previous function. The return value is
385
+ * the last result, or the original value if no functions were given.
386
+ *
387
+ * The underlying implementation of pipe() works with any number of arguments,
388
+ * but due to TypeScript limitations we only have typing defined for a max of 9
389
+ * functions (10 arguments total). If you need more than 9 functions, you can
390
+ * stack some of them with {@link compose}(), e.g.:
391
+ *
392
+ * ```typescript
393
+ * pipe(
394
+ * aStream,
395
+ * compose(op1, op2, ...),
396
+ * compose(op10, op11, ...),
397
+ * compose(op19, ...),
398
+ * ...
399
+ * )
400
+ * ```
401
+ *
402
+ * @category Stream Operators
403
+ */
404
+ declare function pipe<A, B, C, D, E, F, G, H, I, J>(input: A, ...fns: Chain9<A, J, B, C, D, E, F, G, H, I>): J;
405
+ declare function pipe<A, B, C, D, E, F, G, H, I>(input: A, ...fns: Chain8<A, I, B, C, D, E, F, G, H>): I;
406
+ declare function pipe<A, B, C, D, E, F, G, H>(input: A, ...fns: Chain7<A, H, B, C, D, E, F, G>): H;
407
+ declare function pipe<A, B, C, D, E, F, G>(input: A, ...fns: Chain6<A, G, B, C, D, E, F>): G;
408
+ declare function pipe<A, B, C, D, E, F>(input: A, ...fns: Chain5<A, F, B, C, D, E>): F;
409
+ declare function pipe<A, B, C, D, E>(input: A, ...fns: Chain4<A, E, B, C, D>): E;
410
+ declare function pipe<A, B, C, D>(input: A, ...fns: Chain3<A, D, B, C>): D;
411
+ declare function pipe<A, B, C>(input: A, ...fns: Chain2<A, C, B>): C;
412
+ declare function pipe<A, B>(input: A, ...fns: Chain1<A, B>): B;
413
+ declare function pipe<A>(input: A): A;
414
+ declare function pipe(input: any, ...fns: Array<(v: any) => any>): any;
415
+ /**
416
+ * Compose a series of single-argument functions/operators in application order.
417
+ * (This is basically a deferred version of {@link pipe}().) For example:
418
+ *
419
+ * ```ts
420
+ * const func = compose(skip(1), take(2), map(x => x*2));
421
+ * const stream_4_6 = func(fromIterable([1,2,3,4])); // stream that outputs 4, 6
422
+ * ```
423
+ *
424
+ * As with `pipe()`, the declared typings only support composing up to 9
425
+ * functions at once; if you need more you'll need to nest calls to `compose()`
426
+ * (i.e. passing the result of a `compose()` as an argument to another
427
+ * `compose()` call.)
428
+ *
429
+ * @returns A function taking the same type as the first input function,
430
+ * returning the same type as the last input function.
431
+ *
432
+ * @category Stream Operators
433
+ */
434
+ declare function compose<A, B, C, D, E, F, G, H, I, J>(...fns: Chain9<A, J, B, C, D, E, F, G, H, I>): (a: A) => J;
435
+ declare function compose<A, B, C, D, E, F, G, H, I>(...fns: Chain8<A, I, B, C, D, E, F, G, H>): (a: A) => I;
436
+ declare function compose<A, B, C, D, E, F, G, H>(...fns: Chain7<A, H, B, C, D, E, F, G>): (a: A) => H;
437
+ declare function compose<A, B, C, D, E, F, G>(...fns: Chain6<A, G, B, C, D, E, F>): (a: A) => G;
438
+ declare function compose<A, B, C, D, E, F>(...fns: Chain5<A, F, B, C, D, E>): (a: A) => F;
439
+ declare function compose<A, B, C, D, E>(...fns: Chain4<A, E, B, C, D>): (a: A) => E;
440
+ declare function compose<A, B, C, D>(...fns: Chain3<A, D, B, C>): (a: A) => D;
441
+ declare function compose<A, B, C>(...fns: Chain2<A, C, B>): (a: A) => C;
442
+ declare function compose<A, B>(...fns: Chain1<A, B>): (a: A) => B;
443
+ declare function compose<A>(): (a: A) => A;
444
+ type Chain1<A, R> = [(v: A) => R];
445
+ type Chain2<A, R, B> = [...Chain1<A, B>, ...Chain1<B, R>];
446
+ type Chain3<A, R, B, C> = [...Chain1<A, B>, ...Chain2<B, R, C>];
447
+ type Chain4<A, R, B, C, D> = [...Chain1<A, B>, ...Chain3<B, R, C, D>];
448
+ type Chain5<A, R, B, C, D, E> = [...Chain1<A, B>, ...Chain4<B, R, C, D, E>];
449
+ type Chain6<A, R, B, C, D, E, F> = [...Chain1<A, B>, ...Chain5<B, R, C, D, E, F>];
450
+ type Chain7<A, R, B, C, D, E, F, G> = [...Chain1<A, B>, ...Chain6<B, R, C, D, E, F, G>];
451
+ type Chain8<A, R, B, C, D, E, F, G, H> = [...Chain1<A, B>, ...Chain7<B, R, C, D, E, F, G, H>];
452
+ type Chain9<A, R, B, C, D, E, F, G, H, I> = [...Chain1<A, B>, ...Chain8<B, R, C, D, E, F, G, H, I>];
453
+ /**
454
+ * Pass subscriber into a stream (or any arguments into any other function).
455
+ *
456
+ * This utility is mainly here for uses like:
457
+ *
458
+ * - `pipe(src, into(sink))`,
459
+ * - `pipe(src, into(sink, conn))`,
460
+ * - `pipe(src, into(restarting(sink)))`, etc.
461
+ *
462
+ * but can also be used for argument currying generally.
463
+ *
464
+ * @param args The arguments to pass to the stream (or other function)
465
+ *
466
+ * @returns a function that takes another function and calls it with the given args.
467
+ *
468
+ * @category Stream Consumers
469
+ */
470
+ declare function into<In extends any[], Out>(...args: In): (src: (...args: In) => Out) => Out;
471
+
472
+ /**
473
+ * An undefined or null value
474
+ *
475
+ * @category Types and Interfaces
476
+ */
477
+ type Nothing = undefined | null | void;
478
+ /**
479
+ * A function without a `this`
480
+ *
481
+ * @category Types and Interfaces
482
+ */
483
+ type PlainFunction = (this: void, ...args: any[]) => any;
484
+ /**
485
+ * Any function
486
+ *
487
+ * @category Types and Interfaces
488
+ */
489
+ type AnyFunction = (...args: any[]) => any;
490
+ /**
491
+ * A cleanup function is a callback invoked when a job is ended or restarted.
492
+ * It receives a result that indicates whether the job ended itself with a return
493
+ * value or error, or was canceled/restarted by its creator.
494
+ *
495
+ * @category Types and Interfaces
496
+ */
497
+ type CleanupFn<T = unknown> = (res: JobResult<T>) => unknown;
498
+ /**
499
+ * A function that can be called to dispose of something or unsubscribe
500
+ * something. It's called without arguments and returns void.
501
+ *
502
+ * @category Types and Interfaces
503
+ */
504
+ type DisposeFn = () => void;
505
+ /**
506
+ * An optional cleanup parameter or return.
507
+ *
508
+ * @category Types and Interfaces
509
+ */
510
+ type OptionalCleanup<T = unknown> = CleanupFn<T> | Nothing;
511
+ /**
512
+ * An asynchronous start function is called immediately in the new job and must
513
+ * return a {@link StartObj}, such as a job, generator, or promise. If a job or
514
+ * promise is returned, it will be awaited and its result used to asynchronously
515
+ * set the result of the returned job.
516
+ *
517
+ * If a generator is returned, it will be run asynchronously, in the context of
518
+ * the newly-started job. Any result it returns or error it throws will be
519
+ * treated as the result of the job. If the job is canceled, the iterator's
520
+ * `.return()` method will be called to abort it (thereby running any
521
+ * try-finally clauses in the generator), and the result of the call will be
522
+ * otherwise ignored.
523
+ *
524
+ * @template T The type the job will end up returning
525
+ * @template This The type of `this` the function accepts, if using two-argument
526
+ * start(). Defaults to void (for one-argument start()).
527
+ *
528
+ * @category Types and Interfaces
529
+ */
530
+ type AsyncStart<T, This = void> = (this: This, job: Job<T>) => StartObj<T>;
531
+ /**
532
+ * A synchronous start function returns void or a {@link CleanupFn}. It runs
533
+ * immediately and gets passed the newly created job as its first argument.
534
+ *
535
+ * @template T The type the job will end up returning
536
+ * @template This The type of `this` the function accepts, if using two-argument
537
+ * start(). Defaults to void (for one-argument start()).
538
+ *
539
+ * @category Types and Interfaces
540
+ */
541
+ type SyncStart<T, This = void> = (this: This, job: Job<T>) => OptionalCleanup;
542
+ /**
543
+ * A synchronous or asynchronous initializing function for use with the
544
+ * {@link start}() function or a job's {@link Job.start .start}() method.
545
+ *
546
+ * @template T The type the job will end up returning
547
+ * @template This The type of `this` the function accepts, if using two-argument
548
+ * start(). Defaults to void (for one-argument start()).
549
+ *
550
+ * @category Types and Interfaces
551
+ */
552
+ type StartFn<T, This = void> = AsyncStart<T, This> | SyncStart<T, This>;
553
+ /**
554
+ * An object that can be passed as a single argument to {@link start}() or a
555
+ * job's {@link Job.start .start}() method, such as a job, generator, or
556
+ * promise.
557
+ *
558
+ * @category Types and Interfaces
559
+ */
560
+ type StartObj<T> = Yielding<T> | Promise<T> | PromiseLike<T>;
561
+ /**
562
+ * A cancellable asynchronous operation with automatic resource cleanup.
563
+ *
564
+ * You can add cleanup callbacks to a job via {@link must}() or its
565
+ * .{@link must}() method. When the job is ended or canceled, the callbacks
566
+ * are (synchronously) run in reverse order -- a bit like a delayed and
567
+ * distributed collection of `finally` blocks.
568
+ *
569
+ * Jobs implement the Promise interface (then, catch, and finally) so they can
570
+ * be passed to Promise-using APIs or awaited by async functions. They also
571
+ * implement {@link Yielding}, so you can await their results from a
572
+ * {@link start}() using `yield *`. They also have
573
+ * {@link Job.return \.return()} and {@link Job.throw \.throw()} methods so
574
+ * you can end a job with a result or error.
575
+ *
576
+ * Most jobs, however, are not intended to produce results, and are merely
577
+ * canceled (using {@link Job.end \.end()} or
578
+ * {@link Job.restart \.restart()}).
579
+ *
580
+ * Jobs can be created using {@link start}(), {@link detached}.start(), and
581
+ * {@link makeJob}().
582
+ *
583
+ * @category Types and Interfaces
584
+ */
585
+ interface Job<T = any> extends Yielding<T>, Promise<T> {
586
+ /**
587
+ * The result of the job (canceled, returned value, or error), or
588
+ * undefined if the job isn't finished.
589
+ *
590
+ * @category Obtaining Results
591
+ */
592
+ result(): JobResult<T> | undefined;
593
+ /**
594
+ * Add a cleanup callback to be run when the job is ended or restarted.
595
+ * (Non-function values are ignored.) If the job has already ended, the
596
+ * callback will be invoked asynchronously in the next microtask. Cleanup
597
+ * functions are run in LIFO order, after any {@link Job.release}()
598
+ * callbacks (including those of the job's children), but before any
599
+ * {@link Job.do}() callbacks are run for the same job.
600
+ *
601
+ * Generally speaking, this method is used within a job to arrange for used
602
+ * resources to be cleaned up or to undo other state that was only supposed
603
+ * to be active while the job was running.
604
+ *
605
+ * @category Resource Tracking
606
+ */
607
+ must(cleanup?: OptionalCleanup): this;
608
+ /**
609
+ * Create a mutual-cleanup link with a resource that might be stopped or
610
+ * terminated in some way before the job ends. (Like a child process, a
611
+ * server connection, etc.)
612
+ *
613
+ * If a job uses a lot of such resources, using {@link Job.must} callbacks
614
+ * to trigger each one would result in an ever growing number of callbacks
615
+ * (and uncollectable reference to the no-longer-usable resources). So this
616
+ * method lets you *remove* a cleanup function when it's no longer needed:
617
+ * when the resource is closed or finished, invoking the callback returned
618
+ * by this method will remove the cleanup callback from the job, allowing
619
+ * the resource to be freed before the job ends, without accumulating an
620
+ * endless number of callbacks in the job. (Uneventful also uses this
621
+ * mechanism internally to link child jobs to their parents.)
622
+ *
623
+ * In order to ensure that all such "child" jobs, resources, and activities
624
+ * are marked as canceled *before* any side effects (such as events,
625
+ * callbacks or I/O operations) can occur, Uneventful prioritizes *all*
626
+ * release callbacks to run before *any* other callbacks of any kind. Since
627
+ * release callbacks are used for child jobs, this means that the entire job
628
+ * subtree is notified immediately of cancellation, before any other actions
629
+ * are taken. This ensures that no "stray" operations can continue, unaware
630
+ * that their job is canceled.
631
+ *
632
+ * This means, however, that release callbacks must do **only** simple
633
+ * actions that **can't** result in arbitrary code being synchronously run.
634
+ * (Some safe examples would be setting flags, cancelling event
635
+ * subscriptions, removing things from internal queues, etc.) Synchronously
636
+ * triggering events or other callbacks, however, runs the risk of that code
637
+ * doing things it wouldn't have done if it knew its job were canceled.
638
+ *
639
+ * Note that if you still need such actions to happen, your release callback
640
+ * can always add a new {@link Job.must}() or {@link Job.do}() callback at
641
+ * that point, and the callback will then get done during a later phase of
642
+ * job cleanup, without losing the benefits of the mutual-cleanup process.
643
+ *
644
+ * @param cleanup A cleanup callback. It will receive a {@link JobResult},
645
+ * and its return value is ignored.
646
+ *
647
+ * @returns A callback that should be used to remove the passed-in cleanup
648
+ * callback from the job, if the resource is disposed of before the job
649
+ * ends.
650
+ *
651
+ * @category Resource Tracking
652
+ */
653
+ release(cleanup: CleanupFn): DisposeFn;
654
+ /**
655
+ * Start a nested job using the given function (or {@link Yielding},
656
+ * promise, etc.). (Like {@link start}(), but using a specific job as the
657
+ * parent, rather than whatever job is active. Zero, one, and two arguments
658
+ * are supported, just as with start().)
659
+ *
660
+ * @category Execution Control
661
+ */
662
+ start<T>(init?: StartFn<T> | StartObj<T>): Job<T>;
663
+ start<T, This>(thisArg: This, fn: StartFn<T, This>): Job<T>;
664
+ /**
665
+ * Start a nested job that will end when the given stream does
666
+ *
667
+ * This is basically shorthand for `start<void>(job => void src(sink, job,
668
+ * inlet))` -- i.e. a quick way to subscribe to a finite and/or pausable stream.
669
+ *
670
+ * @param src An event source or signal
671
+ * @param sink A callback that will receive the events or values
672
+ * @param inlet Optional - a {@link throttle}() to control backpressure
673
+ * @returns A job that can be aborted to end the subscription, and which will
674
+ * end naturally (with a void return or error) if the stream ends itself.
675
+ *
676
+ * @category Execution Control
677
+ */
678
+ connect<T>(src: Stream<T>, sink: Sink<T>, inlet?: Throttle | Inlet): Connection;
679
+ /**
680
+ * Invoke a function with this job as the active one, so that calling the
681
+ * global {@link must} function will add cleanup callbacks to it,
682
+ * {@link start} will create child jobs of it, etc. (Note: signal
683
+ * dependency tracking is disabled for the duration of the call, as if it
684
+ * had been wrapped with {@link peek}().)
685
+ *
686
+ * @param fn The function to call
687
+ * @param args The arguments to call it with, if any
688
+ * @returns The result of calling fn(...args)
689
+ *
690
+ * @category Execution Control
691
+ */
692
+ run<F extends PlainFunction>(fn: F, ...args: Parameters<F>): ReturnType<F>;
693
+ /**
694
+ * Wrap a function so this job will be active when it's called.
695
+ *
696
+ * @param fn The function to wrap
697
+ *
698
+ * @returns A function with the same signature(s), but will have this job
699
+ * active when called. (Note: signal dependency tracking will be disabled
700
+ * for the duration of the call, as if it had been wrapped with
701
+ * {@link peek}().)
702
+ *
703
+ * @remarks Note that if the supplied function has any custom properties,
704
+ * they will *not* be available on the returned function at runtime, even
705
+ * though TypeScript will act as if they are present at compile time. This
706
+ * is because the only way to copy all overloads of a function signature is
707
+ * to copy the exact type (as TypeScript has no way to generically say,
708
+ * "this is a function with all the same overloads, but none of the
709
+ * properties").
710
+ *
711
+ * @category Execution Control
712
+ */
713
+ bind<F extends (...args: any[]) => any>(fn: F): F;
714
+ /**
715
+ * Release all resources held by the job.
716
+ *
717
+ * Arrange for all cleanup functions and result consumers added to the job
718
+ * (via release, must, do, etc.) be called in the appropriate order. When
719
+ * the call to end() returns, all child jobs will have been notified of
720
+ * their cancellation. (But not all of their cleanups or result consumers
721
+ * may have run yet, in the event that another job's end() is in progress
722
+ * when this method is called.)
723
+ *
724
+ * If any callbacks throw exceptions, they're converted to unhandled promise
725
+ * rejections (so that all of them will be called, even if one throws an
726
+ * error).
727
+ *
728
+ * Note: this method is a bound function, so you can pass it as a callback
729
+ * to another job, event source, etc.
730
+ *
731
+ * @category Execution Control
732
+ */
733
+ readonly end: () => void;
734
+ /**
735
+ * Invoke a callback with the result of a job. Similar to
736
+ * {@link Job.must}(), except that `do` callbacks run in FIFO order after
737
+ * all {@link Job.must}() and {@link Job.release}() callbacks are done for
738
+ * the same job.
739
+ *
740
+ * These callbacks are used internally to implement promises, and should
741
+ * generally be used when you want to perform actions based on the *result*
742
+ * of a job. (Whereas {@link Job.must}() callbacks are intended to clean up
743
+ * resources used by the job itself, and {@link Job.release}() callbacks are
744
+ * used to notify other activities (such as child jobs) that they are being
745
+ * canceled.)
746
+ *
747
+ * @remarks The .{@link Job.onError onError}(), .{@link Job.onError onValue}(),
748
+ * and .{@link Job.onError onCancel}() provide shortcuts for creating `do`
749
+ * callbacks that only run under specific end conditions.
750
+ *
751
+ * @category Obtaining Results
752
+ */
753
+ do(action: (res?: JobResult<T>) => unknown): this;
754
+ /**
755
+ * Invoke a callback if the job ends with an error.
756
+ *
757
+ * This is shorthand for a .{@link Job.do do}() callback that checks for an
758
+ * error and marks it handled, so it uses the same relative order and runs
759
+ * in the same group as other .do callbacks.
760
+ *
761
+ * @param cb A callback that will receive the error
762
+ *
763
+ * @category Obtaining Results
764
+ */
765
+ onError(cb: (err: any) => unknown): this;
766
+ /**
767
+ * Invoke a callback if the job ends with a return() value.
768
+ *
769
+ * This is shorthand for a .{@link Job.do do}() callback that checks for a
770
+ * value result, so it uses the same relative order and runs in the same
771
+ * group as other .do callbacks.
772
+ *
773
+ * @param cb A callback that will receive the value
774
+ *
775
+ * @category Obtaining Results
776
+ */
777
+ onValue(cb: (val: T) => unknown): this;
778
+ /**
779
+ * Invoke a callback if the job ends with an cancellation or
780
+ * .{@link Job.restart restart}().
781
+ *
782
+ * This is shorthand for a .{@link Job.do do}() callback that checks for an
783
+ * error and marks it handled, so it uses the same relative order and runs
784
+ * in the same group as other .do callbacks.
785
+ *
786
+ * @param cb A callback that will receive the error
787
+ *
788
+ * @category Obtaining Results
789
+ */
790
+ onCancel(cb: () => unknown): this;
791
+ /**
792
+ * Restart this job - works just like .{@link Job.end end}(), except that
793
+ * the job isn't ended, so cleanup callbacks can be added again and won't be
794
+ * invoked until the next restart or the job is ended. Note that the job's
795
+ * startup code will *not* be rerun: this just runs an early cleanup and
796
+ * then "uncancels" the job, changing its {@link Job.result result}() from
797
+ * {@link CancelResult} back to undefined. It's up to you to do any needed
798
+ * re-initialization.
799
+ *
800
+ * Unlinke .{@link Job.end end}(), restart() guarantees that *all* cleanups
801
+ * and result consumers for the target job will have completed running when
802
+ * it returns.
803
+ *
804
+ * @see The {@link restarting} wrapper can be used to make a function that
805
+ * runs over and over in the same job, restarting each time.
806
+ *
807
+ * @category Execution Control
808
+ */
809
+ restart(): this;
810
+ /**
811
+ * Informs a job of an unhandled error from one of its children.
812
+ *
813
+ * If the job has an .{@link Job.asyncCatch asyncCatch}() handler set, it
814
+ * will be called with the error, otherwise the job will end with the
815
+ * supplied error. If the error then isn't handled by a listener on the
816
+ * job, the error will cascade to an asyncThrow on the job's parent, until
817
+ * the {@link detached} job and its asyncCatch handler is reached. (Which
818
+ * defaults to creating an unhandled promise rejection.)
819
+ *
820
+ * Note: application code should not normally need to call this method
821
+ * directly, as it's automatically invoked on a job's parent if the job
822
+ * fails with no error listeners. (That is, if a job result isn't awaited
823
+ * by anything and has no onError handlers, and the job throws, then the
824
+ * error is automatically asyncThrow()n to the job's parent.)
825
+ *
826
+ * @param err The error thrown by the child job
827
+ *
828
+ * @category Handling Errors
829
+ */
830
+ asyncThrow(err: any): this;
831
+ /**
832
+ * Set up a callback to receive unhandled errors from child jobs.
833
+ *
834
+ * Setting an async-catch handler allows you to create robust parent jobs
835
+ * that log or report errors and restart either a single job or an entire
836
+ * group of them, in the event that a child job malfunctions in a way that's
837
+ * not caught elsewhere.
838
+ *
839
+ * @param handler Either an error-receiving callback, or null. If null,
840
+ * asyncThrow()n errors for the job will be passed to the job's throw()
841
+ * method instead. If a callback is given, it's called with `this` bound to
842
+ * the relevant job instance.
843
+ *
844
+ * @category Handling Errors
845
+ */
846
+ asyncCatch(handler: ((this: Job, err: any) => unknown) | null): this;
847
+ /**
848
+ * End the job with a thrown error, passing an {@link ErrorResult} to the
849
+ * cleanup callbacks. (Throws an error if the job is already ended or is
850
+ * currently restarting.) Provides the same execution and ordering
851
+ * guarantees as .{@link Job.end end}().
852
+ *
853
+ * Note: since this immediately ends the job with an error, it should only
854
+ * be called by the job when it is no longer able to continue. If you want
855
+ * to notify a job about an error in a *different* job, you may want to use
856
+ * .{@link Job.asyncThrow asyncThrow}() instead.
857
+ *
858
+ * @category Producing Results
859
+ */
860
+ throw(err: any): this;
861
+ /**
862
+ * End the job with a return value, passing a {@link ValueResult} to the
863
+ * cleanup callbacks. (Throws an error if the job is already ended or is
864
+ * currently restarting.) Provides the same execution and ordering
865
+ * guarantees as .{@link Job.end end}().
866
+ *
867
+ * @category Producing Results
868
+ */
869
+ return(val: T): this;
870
+ }
871
+ /**
872
+ * A pausable computation that ultimately produces a value of type T.
873
+ *
874
+ * An item of this type can be used to either create a job of type T, or awaited
875
+ * in a job via `yield *` to obtain the value.
876
+ *
877
+ * Any generator function that ultimately returns a value, implicitly returns a
878
+ * Yielding of that type, but it's best to *explicitly* declare this so that
879
+ * TypeScript can properly type check your yield expressions. (e.g. `function
880
+ * *(): Yielding<number> {}` for a generator function that ultimately returns a
881
+ * number.)
882
+ *
883
+ * Generator functions implementing this type should only ever `yield *` to
884
+ * things that are of Yielding type, such as a {@link Job}, {@link to}() or
885
+ * other generators declared Yielding.
886
+ *
887
+ * @yields {@link Suspend}\<any>
888
+ * @returns T
889
+ *
890
+ *
891
+ * @category Types and Interfaces
892
+ */
893
+ type Yielding<T> = {
894
+ /**
895
+ * An iterator suitable for use with `yield *` (in a job generator) to
896
+ * obtain a result.
897
+ *
898
+ * @category Obtaining Results
899
+ */
900
+ [Symbol.iterator](): JobIterator<T>;
901
+ };
902
+ /**
903
+ * An iterator yielding {@link Suspend} callbacks. (An implementation detail of
904
+ * the {@link Yielding} type.)
905
+ *
906
+ * @category Types and Interfaces
907
+ */
908
+ type JobIterator<T> = Generator<Suspend<any>, T, any>;
909
+ /**
910
+ * An asynchronous operation that can be waited on by a {@link Job}.
911
+ *
912
+ * When a {@link JobIterator} yields a Suspend, the job invokes it with a
913
+ * {@link Request}. The Suspend function should arrange for the request to be
914
+ * settled (via {@link resolve} or {@link reject}).
915
+ *
916
+ * Note: If the request is not settled, **the job will be suspended until
917
+ * cancelled by outside forces**. (Such as its enclosing job ending, or
918
+ * explicit throw()/return() calls on the job instance.)
919
+ *
920
+ * Also note that any subjobs the Suspend function creates (or cleanup callbacks
921
+ * it registers) **will not be cleaned up until the *calling* job ends**. So
922
+ * any resources that won't be needed once the job is resumed should be
923
+ * explicitly disposed of -- in which case you should probably just `yield *` to
924
+ * a {@link start}(), instead of yielding a Suspend!
925
+ *
926
+ * @category Types and Interfaces
927
+ */
928
+ type Suspend<T> = (request: Request<T>) => void;
929
+ /**
930
+ * A request for a value (or error) to be returned asynchronously.
931
+ *
932
+ * A request is like the inverse of a Promise: instead of waiting for it to
933
+ * settle, you settle it by passing it to {@link resolve}() or {@link reject}().
934
+ * Like a promise, it can only be settled once: resolving or rejecting it after
935
+ * it's already resolved or rejected has no effect.
936
+ *
937
+ * Settling a request will cause the requesting job (or other code) to resume
938
+ * immediately, running up to its next suspension or termination. (Unless it's
939
+ * settled while the requesting job is already on the call stack, in which case
940
+ * the job will be resumed later.)
941
+ *
942
+ * (Note: do not call a Request directly, unless you want your code to maybe
943
+ * break in future. Use resolve or reject (or {@link resolver}() or
944
+ * {@link rejecter}()), as 1) they'll shield you from future changes to this
945
+ * protocol and 2) they have better type checking anyway.)
946
+ *
947
+ * @category Types and Interfaces
948
+ */
949
+ interface Request<T> {
950
+ (op: "next", val: T, err?: any): void;
951
+ (op: "throw", val: undefined | null, err: any): void;
952
+ (op: "next" | "throw", val?: T | undefined | null, err?: any): void;
953
+ }
954
+ /**
955
+ * A subscribable function used to trigger signal recalculations
956
+ *
957
+ * It must accept a callback, and should arrange (via {@link must}()) to
958
+ * unsubscribe when its calling job ends. Once subscribed, it should
959
+ * invoke the callback to trigger recalculation of the signal(s) that
960
+ * were targeted via {@link recalcWhen}.
961
+ *
962
+ * @category Types and Interfaces
963
+ */
964
+ type RecalcSource = ((cb: () => void) => unknown);
965
+
966
+ export { type AnyFunction as A, type Backpressure as B, type CleanupFn as C, type DisposeFn as D, ErrorResult as E, backpressure as F, type Throttle as G, type HandledError as H, type Inlet as I, type Job as J, type Connection as K, type SignalSource as L, IsStream as M, type Nothing as N, type OptionalCleanup as O, type PlainFunction as P, connect as Q, type Request as R, type Source as S, type Transformer as T, type UnhandledError as U, ValueResult as V, throttle as W, pipe as X, type Yielding as Y, compose as Z, into as _, type Stream as a, type Sink as b, type StartFn as c, type StartObj as d, type AsyncStart as e, type SyncStart as f, type JobIterator as g, type Suspend as h, type RecalcSource as i, reject as j, resolver as k, rejecter as l, CancelResult as m, noop as n, type JobResult as o, isCancel as p, isValue as q, resolve as r, isError as s, isUnhandled as t, isHandled as u, markHandled as v, getResult as w, fulfillPromise as x, propagateResult as y, CancelError as z };