@nlozgachev/pipelined 0.64.0 → 0.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.d.ts CHANGED
@@ -1,2627 +1,3 @@
1
- import { M as Maybe, R as Result, T as Task } from './Task-9SJCMtG4.js';
2
- export { E as Equality, a as Err, F as Failed, N as None, O as Ok, b as Ordering, P as Passed, S as Some, V as Validation } from './Task-9SJCMtG4.js';
3
- import { o as WithValue, i as WithLog, D as Deferred, R as RetryOptions, n as WithTimeout, j as WithMinInterval, c as WithCooldown, W as WithConcurrency, m as WithSize, d as WithDuration, k as WithN, h as WithKind, e as WithError, b as TimeoutOptions, g as WithFirst, l as WithSecond } from './InternalTypes-CCXa8Kvr.js';
4
- import { D as Duration } from './Duration-DeyxG6VQ.js';
5
- import './types.js';
6
-
7
- /**
8
- * A type that can combine two values of type `A` into one, with a neutral starting value.
9
- * `empty` is the identity: `combine(empty)(a) === a` and `combine(a)(empty) === a`.
10
- * `combine(b)(a)` appends `b` onto `a` — `a` is the accumulated value, `b` is the new element.
11
- *
12
- * @example
13
- * ```ts
14
- * pipe(["hello", ", ", "world"], Combinable.fold(Combinable.string)); // "hello, world"
15
- * pipe([1, 2, 3, 4, 5], Combinable.fold(Combinable.sum)); // 15
16
- * ```
17
- */
18
- type Combinable<A> = {
19
- readonly empty: A;
20
- readonly combine: (b: A) => (a: A) => A;
21
- };
22
- declare const Combinable: {
23
- /**
24
- * Combines strings by concatenation. Empty string is the neutral element.
25
- *
26
- * @example
27
- * ```ts
28
- * pipe(["a", "b", "c"], Combinable.fold(Combinable.string)); // "abc"
29
- * ```
30
- */
31
- string: Combinable<string>;
32
- /**
33
- * Combines numbers by addition. `0` is the neutral element.
34
- *
35
- * @example
36
- * ```ts
37
- * pipe([1, 2, 3], Combinable.fold(Combinable.sum)); // 6
38
- * ```
39
- */
40
- sum: Combinable<number>;
41
- /**
42
- * Combines numbers by multiplication. `1` is the neutral element.
43
- *
44
- * @example
45
- * ```ts
46
- * pipe([2, 3, 4], Combinable.fold(Combinable.product)); // 24
47
- * ```
48
- */
49
- product: Combinable<number>;
50
- /**
51
- * Combines booleans with logical AND. `true` is the neutral element.
52
- *
53
- * @example
54
- * ```ts
55
- * pipe([true, true, false], Combinable.fold(Combinable.all)); // false
56
- * ```
57
- */
58
- all: Combinable<boolean>;
59
- /**
60
- * Combines booleans with logical OR. `false` is the neutral element.
61
- *
62
- * @example
63
- * ```ts
64
- * pipe([false, false, true], Combinable.fold(Combinable.any)); // true
65
- * ```
66
- */
67
- any: Combinable<boolean>;
68
- /**
69
- * Combines arrays by concatenation. Empty array is the neutral element.
70
- *
71
- * @example
72
- * ```ts
73
- * pipe([[1, 2], [3], [4, 5]], Combinable.fold(Combinable.array<number>())); // [1, 2, 3, 4, 5]
74
- * ```
75
- */
76
- array: <A>() => Combinable<readonly A[]>;
77
- /**
78
- * Lifts a `Combinable<A>` to `Combinable<Maybe<A>>`. `None` is the neutral element —
79
- * combining with `None` on either side returns the other value unchanged.
80
- * Two `Some` values combine their inner values using the inner `Combinable`.
81
- *
82
- * @example
83
- * ```ts
84
- * const c = Combinable.maybe(Combinable.sum);
85
- * c.combine(Maybe.make.some(3))(Maybe.make.some(2)); // Some(5)
86
- * c.combine(Maybe.make.none())(Maybe.make.some(5)); // Some(5)
87
- * ```
88
- */
89
- maybe: <A>(inner: Combinable<A>) => Combinable<Maybe<A>>;
90
- /**
91
- * Folds an array into a single value using the `Combinable`'s `empty` as the starting point.
92
- *
93
- * @example
94
- * ```ts
95
- * pipe([1, 2, 3, 4, 5], Combinable.fold(Combinable.sum)); // 15
96
- * pipe([], Combinable.fold(Combinable.sum)); // 0
97
- * ```
98
- */
99
- fold: <A>(c: Combinable<A>) => (data: readonly A[]) => A;
100
- /**
101
- * Derives a `Combinable` for a record of fields from field-level `Combinable` instances.
102
- *
103
- * @example
104
- * ```ts
105
- * const StatsCombinable = Combinable.struct({
106
- * count: Combinable.sum,
107
- * tags: Combinable.array<string>(),
108
- * });
109
- * ```
110
- */
111
- struct: <R extends Record<string, unknown>>(fields: { [K in keyof R]: Combinable<R[K]>; }) => Combinable<R>;
112
- };
113
-
114
- /**
115
- * A synchronous memoized computation. The factory function runs exactly once —
116
- * on the first call to `Lazy.evaluate` — and the result is cached for all subsequent calls.
117
- *
118
- * @example
119
- * ```ts
120
- * const config = Lazy.from(() => parseConfig(rawInput));
121
- *
122
- * pipe(
123
- * config,
124
- * Lazy.map(cfg => cfg.port),
125
- * Lazy.evaluate,
126
- * ); // parseConfig ran once; cfg.port returned
127
- * ```
128
- */
129
- type Lazy<A> = {
130
- readonly get: () => A;
131
- };
132
- declare const Lazy: {
133
- /**
134
- * Wraps a thunk in a `Lazy`. The thunk runs exactly once, on first `evaluate`.
135
- *
136
- * @example
137
- * ```ts
138
- * const expensive = Lazy.from(() => computeExpensiveValue(input));
139
- * ```
140
- */
141
- from: <A>(f: () => A) => Lazy<A>;
142
- /**
143
- * Forces evaluation and returns the cached result. Safe to call multiple times.
144
- *
145
- * @example
146
- * ```ts
147
- * const value = Lazy.evaluate(Lazy.from(() => 42)); // 42
148
- * ```
149
- */
150
- evaluate: <A>(lazy: Lazy<A>) => A;
151
- /**
152
- * Transforms the result of a `Lazy` without triggering evaluation.
153
- *
154
- * @example
155
- * ```ts
156
- * pipe(Lazy.from(() => loadConfig()), Lazy.map(cfg => cfg.port));
157
- * ```
158
- */
159
- map: <A, B>(f: (a: A) => B) => (lazy: Lazy<A>) => Lazy<B>;
160
- /**
161
- * Chains a `Lazy`-returning transformation without triggering evaluation.
162
- *
163
- * @example
164
- * ```ts
165
- * pipe(
166
- * Lazy.from(() => loadConfig()),
167
- * Lazy.chain(cfg => Lazy.from(() => openConnection(cfg.dbUrl))),
168
- * );
169
- * ```
170
- */
171
- chain: <A, B>(f: (a: A) => Lazy<B>) => (lazy: Lazy<A>) => Lazy<B>;
172
- /**
173
- * Runs a side effect on the value without changing it. Fires once, on first `evaluate`.
174
- *
175
- * @example
176
- * ```ts
177
- * pipe(Lazy.from(() => compute()), Lazy.tap(v => console.log("computed:", v)));
178
- * ```
179
- */
180
- tap: <A>(f: (a: A) => void) => (lazy: Lazy<A>) => Lazy<A>;
181
- };
182
-
183
- /**
184
- * Lens<S, A> focuses on a single value A inside a structure S, providing
185
- * a composable way to read and immutably update nested data.
186
- *
187
- * A Lens always succeeds: the focused value is guaranteed to exist.
188
- * For optional or indexed focuses, use Optional<S, A>.
189
- *
190
- * @example
191
- * ```ts
192
- * type Address = { city: string; zip: string };
193
- * type User = { name: string; address: Address };
194
- *
195
- * const addressLens = Lens.from.property<User>()("address");
196
- * const cityLens = Lens.from.property<Address>()("city");
197
- * const userCityLens = pipe(addressLens, Lens.andThen(cityLens));
198
- *
199
- * pipe(user, Lens.get(userCityLens)); // "Berlin"
200
- * pipe(user, Lens.set(userCityLens)("Hamburg")); // new User with city updated
201
- * pipe(user, Lens.modify(userCityLens)(c => c.toUpperCase())); // "BERLIN"
202
- * ```
203
- */
204
- type Lens<S, A> = {
205
- readonly get: (s: S) => A;
206
- readonly set: (a: A) => (s: S) => S;
207
- };
208
- declare const Lens: {
209
- from: {
210
- /**
211
- * Constructs a Lens from a getter and a setter.
212
- *
213
- * @example
214
- * ```ts
215
- * const nameLens = Lens.from.accessors(
216
- * (user: User) => user.name,
217
- * (name) => (user) => ({ ...user, name }),
218
- * );
219
- * ```
220
- */
221
- accessors: <S, A>(get: (s: S) => A, set: (a: A) => (s: S) => S) => Lens<S, A>;
222
- /**
223
- * Creates a Lens that focuses on a property of an object.
224
- * Call with the structure type first, then the key.
225
- *
226
- * @example
227
- * ```ts
228
- * const nameLens = Lens.from.property<User>()("name");
229
- * ```
230
- */
231
- property: <S>() => <K extends keyof S>(key: K) => Lens<S, S[K]>;
232
- };
233
- /**
234
- * Reads the focused value from a structure.
235
- *
236
- * @example
237
- * ```ts
238
- * pipe(user, Lens.get(nameLens)); // "Alice"
239
- * ```
240
- */
241
- get: <S, A>(lens: Lens<S, A>) => (s: S) => A;
242
- /**
243
- * Replaces the focused value within a structure, returning a new structure.
244
- *
245
- * @example
246
- * ```ts
247
- * pipe(user, Lens.set(nameLens)("Bob")); // new User with name "Bob"
248
- * ```
249
- */
250
- set: <S, A>(lens: Lens<S, A>) => (a: A) => (s: S) => S;
251
- /**
252
- * Applies a function to the focused value, returning a new structure.
253
- *
254
- * @example
255
- * ```ts
256
- * pipe(user, Lens.modify(nameLens)(n => n.toUpperCase())); // "ALICE"
257
- * ```
258
- */
259
- modify: <S, A>(lens: Lens<S, A>) => (f: (a: A) => A) => (s: S) => S;
260
- /**
261
- * Composes two Lenses: focuses through the outer, then through the inner.
262
- * Use in a pipe chain to build up a deep focus step by step.
263
- *
264
- * @example
265
- * ```ts
266
- * const userCityLens = pipe(
267
- * Lens.from.property<User>()("address"),
268
- * Lens.andThen(Lens.from.property<Address>()("city")),
269
- * );
270
- * ```
271
- */
272
- andThen: <A, B>(inner: Lens<A, B>) => <S>(outer: Lens<S, A>) => Lens<S, B>;
273
- /**
274
- * Composes a Lens with an Optional, producing an Optional.
275
- * Use when the next step in the focus is optional (may be absent).
276
- *
277
- * @example
278
- * ```ts
279
- * const userBioOpt = pipe(
280
- * Lens.from.property<User>()("profile"),
281
- * Lens.andThenOptional(Optional.from.property<Profile>()("bio")),
282
- * );
283
- * ```
284
- */
285
- andThenOptional: <A, B>(inner: Optional<A, B>) => <S>(outer: Lens<S, A>) => Optional<S, B>;
286
- /**
287
- * Converts a Lens to an Optional. Every Lens is a valid Optional
288
- * whose get always returns Some.
289
- *
290
- * @example
291
- * ```ts
292
- * pipe(
293
- * Lens.from.property<User>()("address"),
294
- * Lens.toOptional,
295
- * Optional.andThen(Optional.from.property<Address>()("landmark")),
296
- * );
297
- * ```
298
- */
299
- toOptional: <S, A>(lens: Lens<S, A>) => Optional<S, A>;
300
- };
301
-
302
- /**
303
- * A value paired with an accumulated log.
304
- *
305
- * `Logged<W, A>` pairs a result `A` with a sequence of log entries `W`. When
306
- * you sequence two `Logged` computations with `chain`, the logs are
307
- * automatically concatenated — you never have to thread the log array through
308
- * your code manually.
309
- *
310
- * @example
311
- * ```ts
312
- * const program = pipe(
313
- * Logged.from.value<string, number>(0),
314
- * Logged.chain(n => pipe(
315
- * Logged.from.entry("start"),
316
- * Logged.map(() => n + 1),
317
- * )),
318
- * Logged.chain(n => pipe(
319
- * Logged.from.entry("done"),
320
- * Logged.map(() => n * 10),
321
- * )),
322
- * );
323
- *
324
- * Logged.run(program); // [10, ["start", "done"]]
325
- * ```
326
- */
327
- type Logged<L, A> = WithValue<A> & WithLog<L>;
328
- declare const Logged: {
329
- from: {
330
- /**
331
- * Wraps a pure value into a `Logged` with an empty log.
332
- *
333
- * @example
334
- * ```ts
335
- * Logged.from.value<string, number>(42); // { value: 42, log: [] }
336
- * ```
337
- */
338
- value: <W, A>(val: A) => Logged<W, A>;
339
- /**
340
- * Creates a `Logged` that records a single log entry and produces no
341
- * meaningful value. Use this to append to the log inside a `chain`.
342
- *
343
- * @example
344
- * ```ts
345
- * Logged.from.entry("operation completed"); // { value: undefined, log: ["operation completed"] }
346
- * ```
347
- */
348
- entry: <W>(logEntry: W) => Logged<W, undefined>;
349
- };
350
- /**
351
- * Transforms the value inside a `Logged` without affecting the log.
352
- *
353
- * @example
354
- * ```ts
355
- * pipe(
356
- * Logged.from.value<string, number>(5),
357
- * Logged.map(n => n * 2),
358
- * ); // { value: 10, log: [] }
359
- * ```
360
- */
361
- map: <W, A, B>(f: (a: A) => B) => (data: Logged<W, A>) => Logged<W, B>;
362
- /**
363
- * Sequences two `Logged` computations, concatenating their logs.
364
- * The value from the first is passed to `f`; the resulting log entries are
365
- * appended after the entries from the first.
366
- *
367
- * Data-last — the first computation is the data being piped.
368
- *
369
- * @example
370
- * ```ts
371
- * const result = pipe(
372
- * Logged.from.value<string, number>(1),
373
- * Logged.chain(n => pipe(Logged.from.entry("step"), Logged.map(() => n + 1))),
374
- * Logged.chain(n => pipe(Logged.from.entry("done"), Logged.map(() => n * 10))),
375
- * );
376
- *
377
- * Logged.run(result); // [20, ["step", "done"]]
378
- * ```
379
- */
380
- chain: <W, A, B>(f: (a: A) => Logged<W, B>) => (data: Logged<W, A>) => Logged<W, B>;
381
- /**
382
- * Applies a function wrapped in a `Logged` to a value wrapped in a `Logged`,
383
- * concatenating both logs.
384
- *
385
- * @example
386
- * ```ts
387
- * const fn: Logged<string, (n: number) => number> = {
388
- * value: n => n * 2,
389
- * log: ["fn-loaded"],
390
- * };
391
- * const arg: Logged<string, number> = { value: 5, log: ["arg-loaded"] };
392
- *
393
- * const result = pipe(fn, Logged.ap(arg));
394
- * Logged.run(result); // [10, ["fn-loaded", "arg-loaded"]]
395
- * ```
396
- */
397
- ap: <W, A>(arg: Logged<W, A>) => <B>(data: Logged<W, (a: A) => B>) => Logged<W, B>;
398
- /**
399
- * Runs a side effect on the value without changing the `Logged`.
400
- * Useful for debugging or inspecting intermediate values.
401
- *
402
- * @example
403
- * ```ts
404
- * pipe(
405
- * Logged.from.value<string, number>(42),
406
- * Logged.tap(n => console.log("value:", n)),
407
- * );
408
- * ```
409
- */
410
- tap: <W, A>(f: (a: A) => void) => (data: Logged<W, A>) => Logged<W, A>;
411
- /**
412
- * Extracts the value and log as a `readonly [A, ReadonlyArray<W>]` tuple.
413
- * Use this at the boundary where you need to consume both.
414
- *
415
- * @example
416
- * ```ts
417
- * const result = pipe(
418
- * Logged.from.value<string, number>(1),
419
- * Logged.chain(n => pipe(Logged.from.entry("incremented"), Logged.map(() => n + 1))),
420
- * );
421
- *
422
- * const [value, log] = Logged.run(result);
423
- * // value = 2, log = ["incremented"]
424
- * ```
425
- */
426
- run: <W, A>(data: Logged<W, A>) => readonly [A, ReadonlyArray<W>];
427
- /**
428
- * Lifts a Logged value into an accumulator object.
429
- *
430
- * @example
431
- * ```ts
432
- * pipe(Logged.from.value<string, number>(42), Logged.bindTo("value")); // Logged({ value: 42 })
433
- * ```
434
- */
435
- bindTo: <K extends string>(key: K) => <W, A>(data: Logged<W, A>) => Logged<W, { [P in K]: A; }>;
436
- /**
437
- * Evaluates a new Logged using the current accumulator and attaches the output to a new key.
438
- *
439
- * @example
440
- * ```ts
441
- * pipe(
442
- * Logged.from.value<string, { a: number }>({ a: 1 }),
443
- * Logged.bind("b", ({ a }) => Logged.from.value<string, number>(a + 1))
444
- * ); // Logged({ value: { a: 1, b: 2 } })
445
- * ```
446
- */
447
- bind: <K extends string, W, A, B>(key: K, f: (a: A) => Logged<W, B>) => (data: Logged<W, A>) => Logged<W, A & { [P in K]: B; }>;
448
- /**
449
- * Focuses a Logged computation's value transformation using a Lens.
450
- *
451
- * @example
452
- * ```ts
453
- * const nameLens = Lens.from.property<{ name: string }>()("name");
454
- * const logged = Logged.from.value<string, { name: string }>({ name: "alice" });
455
- * pipe(logged, Logged.focus(nameLens)(s => s.toUpperCase()));
456
- * ```
457
- */
458
- focus: <S, A>(lens: Lens<S, A>) => <W>(f: (a: A) => A) => (data: Logged<W, S>) => Logged<W, S>;
459
- };
460
-
461
- type MaybeRetry<E, O> = O extends {
462
- retry: RetryOptions<E>;
463
- } ? Op.Retrying<E> : never;
464
- type AllInterpretOptions<I, E> = ({
465
- strategy: "once";
466
- retry?: RetryOptions<E>;
467
- } & WithTimeout<E>) | ({
468
- strategy: "restartable";
469
- retry?: RetryOptions<E>;
470
- } & WithMinInterval & WithTimeout<E>) | ({
471
- strategy: "exclusive";
472
- retry?: RetryOptions<E>;
473
- } & WithCooldown & WithTimeout<E>) | ({
474
- strategy: "queue";
475
- retry?: RetryOptions<E>;
476
- maxSize?: number;
477
- overflow?: "drop" | "replace-last";
478
- dedupe?: (a: I, b: I) => boolean;
479
- } & WithConcurrency & WithTimeout<E>) | ({
480
- strategy: "buffered";
481
- retry?: RetryOptions<E>;
482
- } & WithSize & WithTimeout<E>) | ({
483
- strategy: "debounced";
484
- retry?: RetryOptions<E>;
485
- leading?: true;
486
- maxWait?: Duration;
487
- } & WithDuration & WithTimeout<E>) | ({
488
- strategy: "throttled";
489
- retry?: RetryOptions<E>;
490
- trailing?: true;
491
- } & WithDuration & WithTimeout<E>) | ({
492
- strategy: "concurrent";
493
- retry?: RetryOptions<E>;
494
- overflow?: "queue" | "drop";
495
- } & WithN & WithTimeout<E>) | ({
496
- strategy: "keyed";
497
- perKey?: "exclusive" | "restartable";
498
- key: (input: I) => unknown;
499
- } & WithTimeout<E>);
500
- type KeyType<I, O> = O extends {
501
- key: (input: I) => infer K;
502
- } ? K : unknown;
503
- type InterpretResult<I, E, A, O> = [O] extends [{
504
- strategy: "throttled";
505
- trailing: true;
506
- }] ? Op.Manager<I, E, A, Op.ThrottledTrailingState<E, A> | MaybeRetry<E, O>> : [O] extends [{
507
- strategy: "throttled";
508
- }] ? Op.Manager<I, E, A, Op.ThrottledState<E, A> | MaybeRetry<E, O>> : [O] extends [{
509
- strategy: "debounced";
510
- }] ? Op.Manager<I, E, A, Op.DebouncedState<E, A> | MaybeRetry<E, O>> : [O] extends [{
511
- strategy: "concurrent";
512
- overflow: "queue";
513
- }] ? Op.Manager<I, E, A, Op.ConcurrentQueueState<E, A> | MaybeRetry<E, O>> : [O] extends [{
514
- strategy: "concurrent";
515
- }] ? Op.Manager<I, E, A, Op.ConcurrentDropState<E, A> | MaybeRetry<E, O>> : [O] extends [{
516
- strategy: "keyed";
517
- perKey: "restartable";
518
- }] ? Op.KeyedManager<I, KeyType<I, O>, E, Op.KeyedRestartablePerKey<E, A>> : [O] extends [{
519
- strategy: "keyed";
520
- }] ? Op.KeyedManager<I, KeyType<I, O>, E, Op.KeyedExclusivePerKey<E, A>> : [O] extends [{
521
- strategy: "once";
522
- }] ? Op.Manager<I, E, A, Op.OnceState<E, A> | MaybeRetry<E, O>> : [O] extends [{
523
- strategy: "restartable";
524
- }] ? Op.Manager<I, E, A, Op.RestartableState<E, A> | MaybeRetry<E, O>> : [O] extends [{
525
- strategy: "exclusive";
526
- }] ? Op.Manager<I, E, A, Op.ExclusiveState<E, A> | MaybeRetry<E, O>> : [O] extends [{
527
- strategy: "queue";
528
- overflow: "replace-last";
529
- dedupe: (a: I, b: I) => boolean;
530
- }] ? Op.Manager<I, E, A, Op.QueueDropAndReplaceState<E, A> | MaybeRetry<E, O>> : [O] extends [{
531
- strategy: "queue";
532
- overflow: "replace-last";
533
- }] ? Op.Manager<I, E, A, Op.QueueReplaceState<E, A> | MaybeRetry<E, O>> : [O] extends [{
534
- strategy: "queue";
535
- maxSize: number;
536
- }] ? Op.Manager<I, E, A, Op.QueueDropState<E, A> | MaybeRetry<E, O>> : [O] extends [{
537
- strategy: "queue";
538
- dedupe: (a: I, b: I) => boolean;
539
- }] ? Op.Manager<I, E, A, Op.QueueDropState<E, A> | MaybeRetry<E, O>> : [O] extends [{
540
- strategy: "queue";
541
- }] ? Op.Manager<I, E, A, Op.QueueState<E, A> | MaybeRetry<E, O>> : [O] extends [{
542
- strategy: "buffered";
543
- }] ? Op.Manager<I, E, A, Op.BufferedState<E, A> | MaybeRetry<E, O>> : never;
544
- declare function interpretFn<I, E, A, O extends AllInterpretOptions<I, E>>(op: Op<I, E, A>, options: O): InterpretResult<I, E, A, O>;
545
- /**
546
- * A reusable description of async work — decoupled from execution strategy and lifetime.
547
- *
548
- * Separate concerns:
549
- * - **What** to do: encoded in the `Op` via `Op.create`
550
- * - **How** to execute: chosen at `Op.interpret` time (restartable, exclusive, queue, etc.)
551
- *
552
- * An `Op` never runs on its own. It only executes when passed to `Op.interpret`, which
553
- * attaches a concurrency strategy and returns a `Manager` that owns the execution.
554
- *
555
- * @example
556
- * ```ts
557
- * const fetchUser = Op.create(
558
- * (signal) => (id: string) =>
559
- * fetch(`/users/${id}`, { signal }).then(r => {
560
- * if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
561
- * return r.json() as Promise<User>;
562
- * }),
563
- * (e) => new ApiError(e),
564
- * );
565
- *
566
- * const manager = Op.interpret(fetchUser, { strategy: "restartable" });
567
- * manager.subscribe(state => {
568
- * if (Op.is.pending(state)) showSpinner();
569
- * if (Op.is.ok(state)) render(state.value);
570
- * if (Op.is.err(state)) showError(state.error);
571
- * if (Op.is.nil(state)) resetUI();
572
- * });
573
- * manager.run(userId);
574
- * ```
575
- */
576
- type Op<I, E, A> = {
577
- /**
578
- * @internal — Used by `Op.interpret`. Do not call directly.
579
- * Returns `null` when the operation was aborted (signal fired before factory resolved).
580
- */
581
- readonly _factory: (input: I, signal: AbortSignal) => Deferred<Result<E, A> | null>;
582
- };
583
- declare const Op: {
584
- make: {
585
- /**
586
- * Creates an Ok outcome with the given value.
587
- *
588
- * @example
589
- * ```ts
590
- * Op.make.ok(42); // { kind: "OpOk", value: 42 }
591
- * ```
592
- */
593
- ok: <A>(value: A) => Op.Ok<A>;
594
- /**
595
- * Creates an Err outcome with the given error.
596
- *
597
- * @example
598
- * ```ts
599
- * Op.make.err("Something went wrong"); // { kind: "OpErr", error: "Something went wrong" }
600
- * ```
601
- */
602
- err: <E>(error: E) => Op.Err<E>;
603
- /**
604
- * Creates a Nil outcome with the given cancellation/drop reason.
605
- *
606
- * @example
607
- * ```ts
608
- * Op.make.nil("aborted"); // { kind: "OpNil", reason: "aborted" }
609
- * ```
610
- */
611
- nil: (reason: Op.NilReason) => Op.Nil;
612
- };
613
- is: {
614
- /**
615
- * Type guard that checks if an Op state is Idle.
616
- *
617
- * @example
618
- * ```ts
619
- * if (Op.is.idle(manager.state)) {
620
- * console.log("Ready to execute");
621
- * }
622
- * ```
623
- */
624
- idle: <E, A>(state: Op.State<E, A>) => state is Op.Idle;
625
- /**
626
- * Type guard that checks if an Op state is Pending (actively executing).
627
- *
628
- * @example
629
- * ```ts
630
- * if (Op.is.pending(manager.state)) {
631
- * showSpinner();
632
- * }
633
- * ```
634
- */
635
- pending: <E, A>(state: Op.State<E, A>) => state is Op.Pending;
636
- /**
637
- * Type guard that checks if an Op state is Queued (waiting in a concurrency queue).
638
- *
639
- * @example
640
- * ```ts
641
- * if (Op.is.queued(manager.state)) {
642
- * console.log("Position in queue:", manager.state.position);
643
- * }
644
- * ```
645
- */
646
- queued: <E, A>(state: Op.State<E, A>) => state is Op.Queued;
647
- /**
648
- * Type guard that checks if an Op state is Retrying after a failure.
649
- *
650
- * @example
651
- * ```ts
652
- * if (Op.is.retrying(manager.state)) {
653
- * console.log("Retry attempt:", manager.state.attempt);
654
- * }
655
- * ```
656
- */
657
- retrying: <E, A>(state: Op.State<E, A>) => state is Op.Retrying<E>;
658
- /**
659
- * Type guard that checks if an Op state or outcome is Ok.
660
- *
661
- * @example
662
- * ```ts
663
- * if (Op.is.ok(outcome)) {
664
- * render(outcome.value);
665
- * }
666
- * ```
667
- */
668
- ok: <E, A>(state: Op.State<E, A>) => state is Op.Ok<A>;
669
- /**
670
- * Type guard that checks if an Op state or outcome is Err.
671
- *
672
- * @example
673
- * ```ts
674
- * if (Op.is.err(outcome)) {
675
- * showError(outcome.error);
676
- * }
677
- * ```
678
- */
679
- err: <E, A>(state: Op.State<E, A>) => state is Op.Err<E>;
680
- /**
681
- * Type guard that checks if an Op state or outcome is Nil.
682
- *
683
- * @example
684
- * ```ts
685
- * if (Op.is.nil(outcome)) {
686
- * console.log("Skipped due to:", outcome.reason);
687
- * }
688
- * ```
689
- */
690
- nil: <E, A>(state: Op.State<E, A>) => state is Op.Nil;
691
- };
692
- create: <E, A, I = void>(factory: (signal: AbortSignal) => (input: I) => Promise<A>, onError: (e: unknown) => E) => Op<I, E, A>;
693
- lift: <I, A>(f: (input: I, signal: AbortSignal) => Promise<A>) => Op<I, unknown, A>;
694
- match: <E, A, B>(cases: {
695
- ok: (a: A) => B;
696
- err: (e: E) => B;
697
- nil: () => B;
698
- }) => (outcome: Op.Outcome<E, A>) => B;
699
- fold: <E, A, B>(onErr: (e: E) => B, onNil: () => B, onOk: (a: A) => B) => (outcome: Op.Outcome<E, A>) => B;
700
- getOrElse: <E, A, B>(defaultValue: () => B) => (outcome: Op.Outcome<E, A>) => A | B;
701
- map: <E, A, B>(f: (a: A) => B) => (outcome: Op.Outcome<E, A>) => Op.Outcome<E, B>;
702
- mapError: <E, F, A>(f: (e: E) => F) => (outcome: Op.Outcome<E, A>) => Op.Outcome<F, A>;
703
- chain: <E, A, B>(f: (a: A) => Op.Outcome<E, B>) => (outcome: Op.Outcome<E, A>) => Op.Outcome<E, B>;
704
- tap: <E, A>(f: (a: A) => void) => (outcome: Op.Outcome<E, A>) => Op.Outcome<E, A>;
705
- recover: <E, A, B>(f: (e: E) => Op.Outcome<E, B>) => (outcome: Op.Outcome<E, A>) => Op.Outcome<E, A | B>;
706
- to: {
707
- Result: <E, A>(onNil: () => E) => (outcome: Op.Outcome<E, A>) => Result<E, A>;
708
- Maybe: <E, A>(outcome: Op.Outcome<E, A>) => Maybe<A>;
709
- };
710
- all: <E, A>(invocations: ReadonlyArray<Deferred<Op.Outcome<E, A>>>) => Deferred<ReadonlyArray<Op.Outcome<E, A>>>;
711
- race: <E, A>(invocations: ReadonlyArray<Deferred<Op.Outcome<E, A>>>) => Deferred<Op.Outcome<E, A>>;
712
- wire: <I, E, A, S extends Op.State<E, A>>(source: Op.Manager<I, E, A, S>, f: (a: A) => void) => () => void;
713
- interpret: typeof interpretFn;
714
- };
715
- declare namespace Op {
716
- type Outcome<E, A> = Ok<A> | Err<E> | Nil;
717
- type Ok<A> = WithKind<"OpOk"> & WithValue<A>;
718
- type Err<E> = WithKind<"OpErr"> & WithError<E>;
719
- type Nil = WithKind<"OpNil"> & {
720
- readonly reason: NilReason;
721
- };
722
- type NilReason = "aborted" | "dropped" | "replaced" | "evicted";
723
- type AbortedNil = Nil & {
724
- readonly reason: "aborted";
725
- };
726
- type DroppedNil = Nil & {
727
- readonly reason: "dropped";
728
- };
729
- type ReplacedNil = Nil & {
730
- readonly reason: "replaced";
731
- };
732
- type EvictedNil = Nil & {
733
- readonly reason: "evicted";
734
- };
735
- type State<E, A> = Idle | Pending | Queued | Retrying<E> | Outcome<E, A>;
736
- type Idle = WithKind<"Idle">;
737
- type Pending = WithKind<"Pending">;
738
- type Queued = WithKind<"Queued"> & {
739
- readonly position: number;
740
- };
741
- type Retrying<E> = WithKind<"Retrying"> & {
742
- readonly attempt: number;
743
- readonly lastError: E;
744
- readonly nextRetryIn?: number;
745
- };
746
- type Manager<I, E, A, S extends State<E, A>> = {
747
- readonly state: S;
748
- run: (input: I) => Deferred<Exclude<S, Idle | Pending | Queued | Retrying<E>>>;
749
- abort: () => void;
750
- subscribe: (cb: (state: S) => void) => () => void;
751
- reset: () => void;
752
- poll: (input: I, options: {
753
- interval: Duration;
754
- }) => () => void;
755
- };
756
- type KeyedManager<I, K, E, PerKeyS> = {
757
- readonly state: ReadonlyMap<K, PerKeyS>;
758
- run: (input: I) => Deferred<Exclude<PerKeyS, Pending | Retrying<E>>>;
759
- abort: (key?: K) => void;
760
- subscribe: (cb: (state: ReadonlyMap<K, PerKeyS>) => void) => () => void;
761
- reset: () => void;
762
- poll: (input: I, options: {
763
- interval: Duration;
764
- }) => () => void;
765
- };
766
- type OnceState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | DroppedNil;
767
- type RetryableOnceState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil;
768
- type RestartableState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | ReplacedNil;
769
- type RetryableRestartableState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | ReplacedNil;
770
- type ExclusiveState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | DroppedNil;
771
- type RetryableExclusiveState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil;
772
- type QueueState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil;
773
- type RetryableQueueState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil;
774
- type QueueDropState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil | DroppedNil;
775
- type RetryableQueueDropState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil;
776
- type QueueReplaceState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil | EvictedNil;
777
- type RetryableQueueReplaceState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil | EvictedNil;
778
- type QueueDropAndReplaceState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil | DroppedNil | EvictedNil;
779
- type RetryableQueueDropAndReplaceState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil | EvictedNil;
780
- type BufferedState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil | EvictedNil;
781
- type RetryableBufferedState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil | EvictedNil;
782
- type DebouncedState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | EvictedNil;
783
- type RetryableDebouncedState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | EvictedNil;
784
- type ThrottledState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | DroppedNil;
785
- type RetryableThrottledState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil;
786
- type ThrottledTrailingState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | EvictedNil;
787
- type RetryableThrottledTrailingState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | EvictedNil;
788
- type ConcurrentQueueState<E, A> = Idle | Pending | Queued | Ok<A> | Err<E> | AbortedNil;
789
- type RetryableConcurrentQueueState<E, A> = Idle | Pending | Queued | Retrying<E> | Ok<A> | Err<E> | AbortedNil;
790
- type ConcurrentDropState<E, A> = Idle | Pending | Ok<A> | Err<E> | AbortedNil | DroppedNil;
791
- type RetryableConcurrentDropState<E, A> = Idle | Pending | Retrying<E> | Ok<A> | Err<E> | AbortedNil | DroppedNil;
792
- type KeyedExclusivePerKey<E, A> = Pending | Ok<A> | Err<E> | AbortedNil | DroppedNil;
793
- type KeyedRestartablePerKey<E, A> = Pending | Ok<A> | Err<E> | AbortedNil | ReplacedNil;
794
- type RetryOptions<E> = RetryOptions<E>;
795
- type TimeoutOptions<E> = TimeoutOptions<E>;
796
- }
797
-
798
- /** Keys of T for which undefined is assignable (i.e. optional fields). */
799
- type OptionalKeys<T> = {
800
- [K in keyof T]-?: undefined extends T[K] ? K : never;
801
- }[keyof T];
802
- /**
803
- * Optional<S, A> focuses on a value A inside a structure S that may or may
804
- * not be present. Like a Lens, but get returns Maybe<A>.
805
- *
806
- * Compose with other Optionals via `andThen`, or with a Lens via `andThenLens`.
807
- * Convert a Lens to an Optional with `Lens.toOptional`.
808
- *
809
- * @example
810
- * ```ts
811
- * type Profile = { username: string; bio?: string };
812
- *
813
- * const bioOpt = Optional.from.property<Profile>()("bio");
814
- *
815
- * pipe(profile, Optional.get(bioOpt)); // Some("hello") or None
816
- * pipe(profile, Optional.set(bioOpt)("hello")); // new Profile with bio set
817
- * pipe(profile, Optional.modify(bioOpt)(s => s + "!")); // appends if present
818
- * ```
819
- */
820
- type Optional<S, A> = {
821
- readonly get: (s: S) => Maybe<A>;
822
- readonly set: (a: A) => (s: S) => S;
823
- };
824
- declare const Optional: {
825
- from: {
826
- /**
827
- * Constructs an Optional from a getter (returning Maybe<A>) and a setter.
828
- *
829
- * @example
830
- * ```ts
831
- * const firstChar = Optional.from.accessors(
832
- * (s: string) => s.length > 0 ? Maybe.make.some(s[0]) : Maybe.make.none(),
833
- * (c) => (s) => s.length > 0 ? c + s.slice(1) : s,
834
- * );
835
- * ```
836
- */
837
- accessors: <S, A>(get: (s: S) => Maybe<A>, set: (a: A) => (s: S) => S) => Optional<S, A>;
838
- /**
839
- * Creates an Optional that focuses on an optional property of an object.
840
- * Only keys whose type includes undefined (i.e. `field?: T`) are accepted.
841
- * Call with the structure type first, then the key.
842
- *
843
- * @example
844
- * ```ts
845
- * type Profile = { username: string; bio?: string };
846
- * const bioOpt = Optional.from.property<Profile>()("bio");
847
- * ```
848
- */
849
- property: <S>() => <K extends OptionalKeys<S>>(key: K) => Optional<S, NonNullable<S[K]>>;
850
- };
851
- /**
852
- * Creates an Optional that focuses on an element at a given index in an array.
853
- * Returns None when the index is out of bounds; set is a no-op when out of bounds.
854
- *
855
- * @example
856
- * ```ts
857
- * const firstItem = Optional.index<string>(0);
858
- *
859
- * pipe(["a", "b"], Optional.get(firstItem)); // Some("a")
860
- * pipe([], Optional.get(firstItem)); // None
861
- * ```
862
- */
863
- index: <A>(i: number) => Optional<A[], A>;
864
- /**
865
- * Reads the focused value from a structure, returning Maybe<A>.
866
- *
867
- * @example
868
- * ```ts
869
- * pipe(profile, Optional.get(bioOpt)); // Some("...") or None
870
- * ```
871
- */
872
- get: <S, A>(opt: Optional<S, A>) => (s: S) => Maybe<A>;
873
- /**
874
- * Replaces the focused value within a structure.
875
- * For indexed focuses, this is a no-op when the index is out of bounds.
876
- *
877
- * @example
878
- * ```ts
879
- * pipe(profile, Optional.set(bioOpt)("hello"));
880
- * ```
881
- */
882
- set: <S, A>(opt: Optional<S, A>) => (a: A) => (s: S) => S;
883
- /**
884
- * Applies a function to the focused value if it is present; returns the
885
- * structure unchanged if the focus is absent.
886
- *
887
- * @example
888
- * ```ts
889
- * pipe(profile, Optional.modify(bioOpt)(s => s.toUpperCase()));
890
- * ```
891
- */
892
- modify: <S, A>(opt: Optional<S, A>) => (f: (a: A) => A) => (s: S) => S;
893
- /**
894
- * Returns the focused value or a default when the focus is absent.
895
- *
896
- * @example
897
- * ```ts
898
- * pipe(profile, Optional.getOrElse(bioOpt)(() => "no bio"));
899
- * ```
900
- */
901
- getOrElse: <S, A>(opt: Optional<S, A>) => (defaultValue: () => A) => (s: S) => A;
902
- /**
903
- * Extracts a value from an Optional focus using handlers for the present
904
- * and absent cases.
905
- *
906
- * @example
907
- * ```ts
908
- * pipe(profile, Optional.fold(bioOpt)(() => "no bio", (bio) => bio.toUpperCase()));
909
- * ```
910
- */
911
- fold: <S, A>(opt: Optional<S, A>) => <B>(onNone: () => B, onSome: (a: A) => B) => (s: S) => B;
912
- /**
913
- * Pattern matches on an Optional focus using a named-case object.
914
- *
915
- * @example
916
- * ```ts
917
- * pipe(
918
- * profile,
919
- * Optional.match(bioOpt)({ none: () => "no bio", some: (bio) => bio }),
920
- * );
921
- * ```
922
- */
923
- match: <S, A>(opt: Optional<S, A>) => <B>(cases: {
924
- none: () => B;
925
- some: (a: A) => B;
926
- }) => (s: S) => B;
927
- /**
928
- * Composes two Optionals: focuses through the outer, then through the inner.
929
- * Returns None if either focus is absent.
930
- *
931
- * @example
932
- * ```ts
933
- * const deepOpt = pipe(
934
- * Optional.from.property<User>()("address"),
935
- * Optional.andThen(Optional.from.property<Address>()("landmark")),
936
- * );
937
- * ```
938
- */
939
- andThen: <A, B>(inner: Optional<A, B>) => <S>(outer: Optional<S, A>) => Optional<S, B>;
940
- /**
941
- * Composes an Optional with a Lens, producing an Optional.
942
- * The Lens focuses within the value found by the Optional.
943
- *
944
- * @example
945
- * ```ts
946
- * const cityOpt = pipe(
947
- * Optional.from.property<User>()("address"),
948
- * Optional.andThenLens(Lens.from.property<Address>()("city")),
949
- * );
950
- * ```
951
- */
952
- andThenLens: <A, B>(inner: Lens<A, B>) => <S>(outer: Optional<S, A>) => Optional<S, B>;
953
- };
954
-
955
- /**
956
- * Pair<A, B> represents a pair of two values that are always both present.
957
- * It is a typed alias for `readonly [A, B]`.
958
- *
959
- * Use Pair when two values always travel together through a pipeline and you
960
- * want to transform either or both sides without destructuring.
961
- *
962
- * @example
963
- * ```ts
964
- * import { Pair } from "@nlozgachev/pipelined/core";
965
- * import { pipe } from "@nlozgachev/pipelined/composition";
966
- *
967
- * const entry = Pair.from.pair("alice", 42);
968
- *
969
- * pipe(
970
- * entry,
971
- * Pair.mapFirst((name) => name.toUpperCase()),
972
- * Pair.mapSecond((score) => score * 2),
973
- * Pair.fold((name, score) => `${name}: ${score}`),
974
- * ); // "ALICE: 84"
975
- * ```
976
- */
977
- type Pair<A, B> = readonly [A, B];
978
- declare const Pair: {
979
- from: {
980
- /**
981
- * Creates a Pair from two values.
982
- *
983
- * @example
984
- * ```ts
985
- * Pair.from.pair("Paris", 2_161_000); // ["Paris", 2161000]
986
- * ```
987
- */
988
- pair: <A, B>(first: A, second: B) => Pair<A, B>;
989
- /**
990
- * Creates a Pair from a two-element array.
991
- *
992
- * @example
993
- * ```ts
994
- * Pair.from.array(["Paris", 2_161_000] as const); // ["Paris", 2161000]
995
- * ```
996
- */
997
- array: <A, B>(arr: readonly [A, B]) => Pair<A, B>;
998
- };
999
- /**
1000
- * Returns the first value from the pair.
1001
- *
1002
- * @example
1003
- * ```ts
1004
- * Pair.first(Pair.from.pair("Paris", 2_161_000)); // "Paris"
1005
- * ```
1006
- */
1007
- first: <A, B>(p: Pair<A, B>) => A;
1008
- /**
1009
- * Returns the second value from the pair.
1010
- *
1011
- * @example
1012
- * ```ts
1013
- * Pair.second(Pair.from.pair("Paris", 2_161_000)); // 2161000
1014
- * ```
1015
- */
1016
- second: <A, B>(p: Pair<A, B>) => B;
1017
- /**
1018
- * Transforms the first value, leaving the second unchanged.
1019
- *
1020
- * @example
1021
- * ```ts
1022
- * pipe(Pair.from.pair("alice", 42), Pair.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
1023
- * ```
1024
- */
1025
- mapFirst: <A, C>(f: (a: A) => C) => <B>(p: Pair<A, B>) => Pair<C, B>;
1026
- /**
1027
- * Transforms the second value, leaving the first unchanged.
1028
- *
1029
- * @example
1030
- * ```ts
1031
- * pipe(Pair.from.pair("alice", 42), Pair.mapSecond((n) => n * 2)); // ["alice", 84]
1032
- * ```
1033
- */
1034
- mapSecond: <B, D>(f: (b: B) => D) => <A>(p: Pair<A, B>) => Pair<A, D>;
1035
- /**
1036
- * Transforms both values independently in a single step.
1037
- *
1038
- * @example
1039
- * ```ts
1040
- * pipe(
1041
- * Pair.from.pair("alice", 42),
1042
- * Pair.mapBoth(
1043
- * (name) => name.toUpperCase(),
1044
- * (score) => score * 2,
1045
- * ),
1046
- * ); // ["ALICE", 84]
1047
- * ```
1048
- */
1049
- mapBoth: <A, C, B, D>(onFirst: (a: A) => C, onSecond: (b: B) => D) => (p: Pair<A, B>) => Pair<C, D>;
1050
- /**
1051
- * Applies a binary function to both values, collapsing the pair into a single value.
1052
- * Useful as the final step when consuming a pair in a pipeline.
1053
- *
1054
- * @example
1055
- * ```ts
1056
- * pipe(Pair.from.pair("Alice", 100), Pair.fold((name, score) => `${name}: ${score}`));
1057
- * // "Alice: 100"
1058
- * ```
1059
- */
1060
- fold: <A, B, C>(f: (a: A, b: B) => C) => (p: Pair<A, B>) => C;
1061
- /**
1062
- * Swaps the two values: `[A, B]` becomes `[B, A]`.
1063
- *
1064
- * @example
1065
- * ```ts
1066
- * Pair.swap(Pair.from.pair("key", 1)); // [1, "key"]
1067
- * ```
1068
- */
1069
- swap: <A, B>(p: Pair<A, B>) => Pair<B, A>;
1070
- to: {
1071
- /**
1072
- * Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
1073
- *
1074
- * @example
1075
- * ```ts
1076
- * Pair.to.Array(Pair.from.pair("hello", 42)); // ["hello", 42]
1077
- * ```
1078
- */
1079
- Array: <A, B>(p: Pair<A, B>) => readonly (A | B)[];
1080
- };
1081
- /**
1082
- * Runs a side effect with both values without changing the pair.
1083
- * Useful for logging or debugging in the middle of a pipeline.
1084
- *
1085
- * @example
1086
- * ```ts
1087
- * pipe(
1088
- * Pair.from.pair("Paris", 2_161_000),
1089
- * Pair.tap((city, pop) => console.log(`${city}: ${pop}`)),
1090
- * Pair.mapSecond((n) => n / 1_000_000),
1091
- * ); // logs "Paris: 2161000", returns ["Paris", 2.161]
1092
- * ```
1093
- */
1094
- tap: <A, B>(f: (a: A, b: B) => void) => (p: Pair<A, B>) => Pair<A, B>;
1095
- };
1096
-
1097
- /**
1098
- * A boolean-valued function over a type `A`.
1099
- *
1100
- * A `Predicate<A>` is the simpler sibling of `Refinement<A, B>`: it tests whether a
1101
- * value satisfies a condition at runtime but carries no compile-time narrowing guarantee.
1102
- * Use it when you need to combine, negate, or adapt boolean checks as first-class values
1103
- * and do not require the extra type information that a `Refinement` provides.
1104
- *
1105
- * Every `Refinement<A, B>` is a `Predicate<A>` — convert with `Predicate.from.Refinement`
1106
- * when you want to compose a narrowing check alongside plain predicates.
1107
- *
1108
- * @example
1109
- * ```ts
1110
- * const isAdult: Predicate<number> = n => n >= 18;
1111
- * const isRetired: Predicate<number> = n => n >= 65;
1112
- *
1113
- * const isWorkingAge: Predicate<number> = pipe(
1114
- * isAdult,
1115
- * Predicate.and(Predicate.not(isRetired))
1116
- * );
1117
- *
1118
- * isWorkingAge(30); // true
1119
- * isWorkingAge(15); // false
1120
- * isWorkingAge(70); // false
1121
- * ```
1122
- */
1123
- type Predicate<A> = (a: A) => boolean;
1124
- declare const Predicate: {
1125
- /**
1126
- * Negates a predicate: the result passes exactly when the original fails.
1127
- *
1128
- * @example
1129
- * ```ts
1130
- * const isBlank: Predicate<string> = s => s.trim().length === 0;
1131
- * const isNotBlank = Predicate.not(isBlank);
1132
- *
1133
- * isNotBlank("hello"); // true
1134
- * isNotBlank(" "); // false
1135
- * ```
1136
- */
1137
- not: <A>(p: Predicate<A>) => Predicate<A>;
1138
- /**
1139
- * Combines two predicates with logical AND: passes only when both hold.
1140
- *
1141
- * Data-last — the first predicate is the data being piped.
1142
- *
1143
- * @example
1144
- * ```ts
1145
- * const isPositive: Predicate<number> = n => n > 0;
1146
- * const isEven: Predicate<number> = n => n % 2 === 0;
1147
- *
1148
- * const isPositiveEven: Predicate<number> = pipe(isPositive, Predicate.and(isEven));
1149
- *
1150
- * isPositiveEven(4); // true
1151
- * isPositiveEven(3); // false — positive but odd
1152
- * isPositiveEven(-2); // false — even but not positive
1153
- * ```
1154
- */
1155
- and: <A>(second: Predicate<A>) => (first: Predicate<A>) => Predicate<A>;
1156
- /**
1157
- * Combines two predicates with logical OR: passes when either holds.
1158
- *
1159
- * Data-last — the first predicate is the data being piped.
1160
- *
1161
- * @example
1162
- * ```ts
1163
- * const isChild: Predicate<number> = n => n < 13;
1164
- * const isSenior: Predicate<number> = n => n >= 65;
1165
- *
1166
- * const getsDiscount: Predicate<number> = pipe(isChild, Predicate.or(isSenior));
1167
- *
1168
- * getsDiscount(8); // true
1169
- * getsDiscount(70); // true
1170
- * getsDiscount(30); // false
1171
- * ```
1172
- */
1173
- or: <A>(second: Predicate<A>) => (first: Predicate<A>) => Predicate<A>;
1174
- /**
1175
- * Adapts a `Predicate<A>` to work on a different input type `B` by applying `f`
1176
- * to extract the relevant `A` from a `B` before running the check.
1177
- *
1178
- * Data-last — the predicate is the data being piped; `f` is the extractor.
1179
- *
1180
- * @example
1181
- * ```ts
1182
- * type User = { name: string; age: number };
1183
- *
1184
- * const isAdult: Predicate<number> = n => n >= 18;
1185
- *
1186
- * // Lift isAdult to work on Users by extracting the age field
1187
- * const isAdultUser: Predicate<User> = pipe(
1188
- * isAdult,
1189
- * Predicate.using((u: User) => u.age)
1190
- * );
1191
- *
1192
- * isAdultUser({ name: "Alice", age: 30 }); // true
1193
- * isAdultUser({ name: "Bob", age: 15 }); // false
1194
- * ```
1195
- */
1196
- using: <A, B>(f: (b: B) => A) => (p: Predicate<A>) => Predicate<B>;
1197
- /**
1198
- * Combines an array of predicates with AND: passes only when every predicate holds.
1199
- * Returns `true` for an empty array (vacuous truth).
1200
- *
1201
- * @example
1202
- * ```ts
1203
- * const checks: Predicate<string>[] = [
1204
- * s => s.length > 0,
1205
- * s => s.length <= 100,
1206
- * s => !s.includes("<"),
1207
- * ];
1208
- *
1209
- * Predicate.all(checks)("hello"); // true
1210
- * Predicate.all(checks)(""); // false — too short
1211
- * Predicate.all(checks)("<b>"); // false — contains "<"
1212
- * Predicate.all([])("anything"); // true
1213
- * ```
1214
- */
1215
- all: <A>(predicates: ReadonlyArray<Predicate<A>>) => Predicate<A>;
1216
- /**
1217
- * Combines an array of predicates with OR: passes when at least one holds.
1218
- * Returns `false` for an empty array.
1219
- *
1220
- * @example
1221
- * ```ts
1222
- * const acceptedFormats: Predicate<string>[] = [
1223
- * s => s.endsWith(".jpg"),
1224
- * s => s.endsWith(".png"),
1225
- * s => s.endsWith(".webp"),
1226
- * ];
1227
- *
1228
- * Predicate.any(acceptedFormats)("photo.jpg"); // true
1229
- * Predicate.any(acceptedFormats)("photo.gif"); // false
1230
- * Predicate.any([])("anything"); // false
1231
- * ```
1232
- */
1233
- any: <A>(predicates: ReadonlyArray<Predicate<A>>) => Predicate<A>;
1234
- from: {
1235
- /**
1236
- * Converts a `Refinement<A, B>` into a `Predicate<A>`, discarding the compile-time
1237
- * narrowing. Use this when you want to combine a type guard with plain predicates
1238
- * using `and`, `or`, or `all`.
1239
- *
1240
- * This is a zero-cost runtime type cast.
1241
- *
1242
- * @example
1243
- * ```ts
1244
- * const isString: Refinement<unknown, string> =
1245
- * Refinement.from.predicate(x => typeof x === "string");
1246
- *
1247
- * const isShortString: Predicate<unknown> = pipe(
1248
- * Predicate.from.Refinement(isString),
1249
- * Predicate.and(x => (x as string).length < 10)
1250
- * );
1251
- *
1252
- * isShortString("hi"); // true
1253
- * isShortString("a very long string that exceeds ten characters"); // false
1254
- * isShortString(42); // false
1255
- * ```
1256
- */
1257
- Refinement: <A, B extends A>(r: Refinement<A, B>) => Predicate<A>;
1258
- };
1259
- /**
1260
- * Performs declarative conditional branching over `[predicate, handler]` pairs,
1261
- * returning the handler result of the first matching predicate or evaluating the fallback.
1262
- *
1263
- * @example
1264
- * ```ts
1265
- * const classifyNumber = Predicate.match(
1266
- * [
1267
- * [(n: number) => n < 0, () => "negative"],
1268
- * [(n: number) => n === 0, () => "zero"],
1269
- * ],
1270
- * () => "positive",
1271
- * );
1272
- * classifyNumber(-5); // "negative"
1273
- * ```
1274
- */
1275
- match: <A, B>(branches: ReadonlyArray<readonly [Predicate<A>, (a: A) => B]>, fallback: (a: A) => B) => (a: A) => B;
1276
- };
1277
-
1278
- /**
1279
- * A computation that reads from a shared environment `R` and produces a value `A`.
1280
- * Use Reader to thread a dependency (config, logger, DB pool) through a pipeline
1281
- * without passing it explicitly to every function.
1282
- *
1283
- * @example
1284
- * ```ts
1285
- * type Config = { baseUrl: string; apiKey: string };
1286
- *
1287
- * const buildUrl = (path: string): Reader<Config, string> =>
1288
- * (config) => `${config.baseUrl}${path}`;
1289
- *
1290
- * const withAuth = (url: string): Reader<Config, string> =>
1291
- * (config) => `${url}?key=${config.apiKey}`;
1292
- *
1293
- * const fetchEndpoint = (path: string): Reader<Config, string> =>
1294
- * pipe(
1295
- * buildUrl(path),
1296
- * Reader.chain(withAuth)
1297
- * );
1298
- *
1299
- * // Inject the config once at the edge
1300
- * fetchEndpoint("/users")(appConfig); // "https://api.example.com/users?key=secret"
1301
- * ```
1302
- */
1303
- type Reader<R, A> = (env: R) => A;
1304
- declare const Reader: {
1305
- /**
1306
- * Lifts a pure value into a Reader. The environment is ignored.
1307
- *
1308
- * @example
1309
- * ```ts
1310
- * const always42: Reader<Config, number> = Reader.resolve(42);
1311
- * always42(anyConfig); // 42
1312
- * ```
1313
- */
1314
- resolve: <R, A>(value: A) => Reader<R, A>;
1315
- /**
1316
- * Returns the full environment as the result.
1317
- * The fundamental way to access the environment in a pipeline.
1318
- *
1319
- * @example
1320
- * ```ts
1321
- * pipe(
1322
- * Reader.ask<Config>(),
1323
- * Reader.map(config => config.baseUrl)
1324
- * )(appConfig); // "https://api.example.com"
1325
- * ```
1326
- */
1327
- ask: <R>() => Reader<R, R>;
1328
- /**
1329
- * Projects a value from the environment using a selector function.
1330
- * Equivalent to `pipe(Reader.ask(), Reader.map(f))` but more direct.
1331
- *
1332
- * @example
1333
- * ```ts
1334
- * const getBaseUrl: Reader<Config, string> = Reader.asks(c => c.baseUrl);
1335
- * getBaseUrl(appConfig); // "https://api.example.com"
1336
- * ```
1337
- */
1338
- asks: <R, A>(f: (env: R) => A) => Reader<R, A>;
1339
- /**
1340
- * Transforms the value produced by a Reader.
1341
- *
1342
- * @example
1343
- * ```ts
1344
- * pipe(
1345
- * Reader.asks((c: Config) => c.baseUrl),
1346
- * Reader.map(url => url.toUpperCase())
1347
- * )(appConfig); // "HTTPS://API.EXAMPLE.COM"
1348
- * ```
1349
- */
1350
- map: <R, A, B>(f: (a: A) => B) => (data: Reader<R, A>) => Reader<R, B>;
1351
- /**
1352
- * Sequences two Readers. Both see the same environment.
1353
- * The output of the first is passed to `f`, which returns the next Reader.
1354
- *
1355
- * @example
1356
- * ```ts
1357
- * const buildUrl = (path: string): Reader<Config, string> =>
1358
- * Reader.asks(c => `${c.baseUrl}${path}`);
1359
- *
1360
- * const addAuth = (url: string): Reader<Config, string> =>
1361
- * Reader.asks(c => `${url}?key=${c.apiKey}`);
1362
- *
1363
- * pipe(
1364
- * buildUrl("/items"),
1365
- * Reader.chain(addAuth)
1366
- * )(appConfig); // "https://api.example.com/items?key=secret"
1367
- * ```
1368
- */
1369
- chain: <R, A, B>(f: (a: A) => Reader<R, B>) => (data: Reader<R, A>) => Reader<R, B>;
1370
- /**
1371
- * Applies a function wrapped in a Reader to a value wrapped in a Reader.
1372
- * Both Readers see the same environment.
1373
- *
1374
- * @example
1375
- * ```ts
1376
- * const add = (a: number) => (b: number) => a + b;
1377
- * pipe(
1378
- * Reader.resolve<Config, typeof add>(add),
1379
- * Reader.ap(Reader.asks(c => c.timeout)),
1380
- * Reader.ap(Reader.resolve(5))
1381
- * )(appConfig);
1382
- * ```
1383
- */
1384
- ap: <R, A>(arg: Reader<R, A>) => <B>(data: Reader<R, (a: A) => B>) => Reader<R, B>;
1385
- /**
1386
- * Executes a side effect on the produced value without changing the Reader.
1387
- * Useful for logging or debugging inside a pipeline.
1388
- *
1389
- * @example
1390
- * ```ts
1391
- * pipe(
1392
- * buildUrl("/users"),
1393
- * Reader.tap(url => console.log("Requesting:", url)),
1394
- * Reader.chain(addAuth)
1395
- * )(appConfig);
1396
- * ```
1397
- */
1398
- tap: <R, A>(f: (a: A) => void) => (data: Reader<R, A>) => Reader<R, A>;
1399
- /**
1400
- * Adapts a Reader to work with a different (typically wider) environment
1401
- * by transforming the environment before passing it to the Reader.
1402
- * This lets you compose Readers that expect different environments.
1403
- *
1404
- * @example
1405
- * ```ts
1406
- * type AppEnv = { db: DbPool; config: Config; logger: Logger };
1407
- *
1408
- * // buildUrl only needs Config
1409
- * const buildUrl: Reader<Config, string> = Reader.asks(c => c.baseUrl);
1410
- *
1411
- * // Zoom in from AppEnv to Config
1412
- * const buildUrlFromApp: Reader<AppEnv, string> =
1413
- * pipe(buildUrl, Reader.local((env: AppEnv) => env.config));
1414
- *
1415
- * buildUrlFromApp(appEnv); // works with the full AppEnv
1416
- * ```
1417
- */
1418
- local: <R2, R>(f: (env: R2) => R) => <A>(data: Reader<R, A>) => Reader<R2, A>;
1419
- /**
1420
- * Runs a Reader by supplying the environment. Use this at the edge of your
1421
- * program where the environment is available.
1422
- *
1423
- * @example
1424
- * ```ts
1425
- * pipe(
1426
- * buildEndpoint("/users"),
1427
- * Reader.run(appConfig)
1428
- * ); // "https://api.example.com/users?key=secret"
1429
- * ```
1430
- */
1431
- run: <R>(env: R) => <A>(data: Reader<R, A>) => A;
1432
- /**
1433
- * Lifts a Reader value into an accumulator object.
1434
- *
1435
- * @example
1436
- * ```ts
1437
- * pipe(Reader.resolve(42), Reader.bindTo("value")); // Reader({ value: 42 })
1438
- * ```
1439
- */
1440
- bindTo: <K extends string>(key: K) => <R, A>(data: Reader<R, A>) => Reader<R, { [P in K]: A; }>;
1441
- /**
1442
- * Evaluates a new Reader using the current accumulator and attaches the output to a new key.
1443
- *
1444
- * @example
1445
- * ```ts
1446
- * pipe(
1447
- * Reader.resolve({ a: 1 }),
1448
- * Reader.bind("b", ({ a }) => Reader.resolve(a + 1))
1449
- * ); // Reader({ a: 1, b: 2 })
1450
- * ```
1451
- */
1452
- bind: <K extends string, R, A, B>(key: K, f: (a: A) => Reader<R, B>) => (data: Reader<R, A>) => Reader<R, A & { [P in K]: B; }>;
1453
- };
1454
-
1455
- /**
1456
- * A function from `A` to `A is B` — a type predicate paired with a runtime check.
1457
- *
1458
- * A `Refinement<A, B>` proves at compile time that a value of type `A` is actually
1459
- * the narrower type `B extends A`, backed by a runtime boolean test. Use it to
1460
- * express domain invariants (non-empty strings, positive numbers, valid emails) as
1461
- * first-class, composable values rather than one-off type guards scattered across
1462
- * the codebase.
1463
- *
1464
- * @example
1465
- * ```ts
1466
- * type NonEmptyString = string & { readonly _tag: "NonEmptyString" };
1467
- *
1468
- * const isNonEmpty: Refinement<string, NonEmptyString> =
1469
- * Refinement.from.predicate(s => s.length > 0);
1470
- *
1471
- * pipe(
1472
- * "hello",
1473
- * Refinement.to.Maybe(isNonEmpty)
1474
- * ); // Some("hello")
1475
- * ```
1476
- */
1477
- type Refinement<A, B extends A> = (a: A) => a is B;
1478
- declare const Refinement: {
1479
- from: {
1480
- /**
1481
- * Creates a `Refinement<A, B>` from a plain boolean predicate.
1482
- *
1483
- * This is an unsafe cast — the caller is responsible for ensuring that the
1484
- * predicate truly characterises values of type `B`. Use this only when
1485
- * bootstrapping a new refinement; prefer `compose`, `and`, or `or` to build
1486
- * derived refinements from existing ones.
1487
- *
1488
- * @example
1489
- * ```ts
1490
- * type PositiveNumber = number & { readonly _tag: "PositiveNumber" };
1491
- *
1492
- * const isPositive: Refinement<number, PositiveNumber> =
1493
- * Refinement.from.predicate(n => n > 0);
1494
- * ```
1495
- */
1496
- predicate: <A, B extends A>(f: (a: A) => boolean) => Refinement<A, B>;
1497
- };
1498
- /**
1499
- * Chains two refinements: if `ab` narrows `A` to `B` and `bc` narrows `B` to `C`,
1500
- * the result narrows `A` directly to `C`.
1501
- *
1502
- * Data-last — the first refinement `ab` is the data being piped.
1503
- *
1504
- * @example
1505
- * ```ts
1506
- * type NonEmptyString = string & { readonly _tag: "NonEmpty" };
1507
- * type TrimmedString = NonEmptyString & { readonly _tag: "Trimmed" };
1508
- *
1509
- * const isNonEmpty: Refinement<string, NonEmptyString> =
1510
- * Refinement.from.predicate(s => s.length > 0);
1511
- * const isTrimmed: Refinement<NonEmptyString, TrimmedString> =
1512
- * Refinement.from.predicate(s => s === s.trim());
1513
- *
1514
- * const isNonEmptyTrimmed: Refinement<string, TrimmedString> = pipe(
1515
- * isNonEmpty,
1516
- * Refinement.compose(isTrimmed)
1517
- * );
1518
- * ```
1519
- */
1520
- compose: <A, B extends A, C extends B>(bc: Refinement<B, C>) => (ab: Refinement<A, B>) => Refinement<A, C>;
1521
- /**
1522
- * Intersects two refinements: the result narrows `A` to `B & C`, passing only
1523
- * when both refinements hold simultaneously.
1524
- *
1525
- * Data-last — the first refinement is the data being piped.
1526
- *
1527
- * @example
1528
- * ```ts
1529
- * const isString: Refinement<unknown, string> = Refinement.from.predicate(x => typeof x === "string");
1530
- * const isNonEmpty: Refinement<unknown, { length: number }> =
1531
- * Refinement.from.predicate(x => (x as any).length > 0);
1532
- *
1533
- * const isNonEmptyString = pipe(isString, Refinement.and(isNonEmpty));
1534
- * isNonEmptyString("hi"); // true
1535
- * isNonEmptyString(""); // false
1536
- * ```
1537
- */
1538
- and: <A, C extends A>(second: Refinement<A, C>) => <B extends A>(first: Refinement<A, B>) => Refinement<A, B & C>;
1539
- /**
1540
- * Unions two refinements: the result narrows `A` to `B | C`, passing when either
1541
- * refinement holds.
1542
- *
1543
- * Data-last — the first refinement is the data being piped.
1544
- *
1545
- * @example
1546
- * ```ts
1547
- * const isString: Refinement<unknown, string> = Refinement.from.predicate(x => typeof x === "string");
1548
- * const isNumber: Refinement<unknown, number> = Refinement.from.predicate(x => typeof x === "number");
1549
- *
1550
- * const isStringOrNumber = pipe(isString, Refinement.or(isNumber));
1551
- * isStringOrNumber("hi"); // true
1552
- * isStringOrNumber(42); // true
1553
- * isStringOrNumber(true); // false
1554
- * ```
1555
- */
1556
- or: <A, C extends A>(second: Refinement<A, C>) => <B extends A>(first: Refinement<A, B>) => Refinement<A, B | C>;
1557
- to: {
1558
- /**
1559
- * Converts a `Refinement<A, B>` into a function `(a: A) => Maybe<B>`.
1560
- *
1561
- * Returns `Some(a)` when the refinement holds, `None` otherwise. Useful for
1562
- * integrating runtime validation into a `Maybe`-based pipeline.
1563
- *
1564
- * @example
1565
- * ```ts
1566
- * type PositiveNumber = number & { readonly _tag: "Positive" };
1567
- * const isPositive: Refinement<number, PositiveNumber> =
1568
- * Refinement.from.predicate(n => n > 0);
1569
- *
1570
- * pipe(-1, Refinement.to.Maybe(isPositive)); // None
1571
- * pipe(42, Refinement.to.Maybe(isPositive)); // Some(42)
1572
- * ```
1573
- */
1574
- Maybe: <A, B extends A>(r: Refinement<A, B>) => (a: A) => Maybe<B>;
1575
- /**
1576
- * Converts a `Refinement<A, B>` into a function `(a: A) => Result<E, B>`.
1577
- *
1578
- * Returns `Ok(a)` when the refinement holds, `Err(onFail(a))` otherwise. Use
1579
- * this to surface validation failures as typed errors inside a `Result` pipeline.
1580
- *
1581
- * @example
1582
- * ```ts
1583
- * type NonEmptyString = string & { readonly _tag: "NonEmpty" };
1584
- * const isNonEmpty: Refinement<string, NonEmptyString> =
1585
- * Refinement.from.predicate(s => s.length > 0);
1586
- *
1587
- * pipe("", Refinement.to.Result(isNonEmpty, () => "must not be empty")); // Err(...)
1588
- * pipe("hi", Refinement.to.Result(isNonEmpty, () => "must not be empty")); // Ok("hi")
1589
- * ```
1590
- */
1591
- Result: <A, B extends A, E>(r: Refinement<A, B>, onFail: (a: A) => E) => (a: A) => Result<E, B>;
1592
- };
1593
- };
1594
-
1595
- type NotAsked = WithKind<"NotAsked">;
1596
- type Loading = WithKind<"Loading">;
1597
- type Failure<E> = WithKind<"Failure"> & WithError<E>;
1598
- type Success<A> = WithKind<"Success"> & WithValue<A>;
1599
- /**
1600
- * RemoteData represents the state of an async data fetch.
1601
- * It has four states: NotAsked, Loading, Failure, and Success.
1602
- *
1603
- * Use RemoteData to model data fetching states explicitly,
1604
- * replacing the common `{ data: T | null; loading: boolean; error: Error | null }` pattern.
1605
- *
1606
- * @example
1607
- * ```ts
1608
- * const renderUser = pipe(
1609
- * userData,
1610
- * RemoteData.match({
1611
- * notAsked: () => "Click to load",
1612
- * loading: () => "Loading...",
1613
- * failure: e => `Error: ${e.message}`,
1614
- * success: user => `Hello, ${user.name}!`
1615
- * })
1616
- * );
1617
- * ```
1618
- */
1619
- type RemoteData<E, A> = NotAsked | Loading | Failure<E> | Success<A>;
1620
- declare const RemoteData: {
1621
- make: {
1622
- /**
1623
- * Creates a NotAsked RemoteData.
1624
- *
1625
- * @example
1626
- * ```ts
1627
- * RemoteData.make.notAsked(); // NotAsked
1628
- * ```
1629
- */
1630
- notAsked: () => NotAsked;
1631
- /**
1632
- * Creates a Loading RemoteData.
1633
- *
1634
- * @example
1635
- * ```ts
1636
- * RemoteData.make.loading(); // Loading
1637
- * ```
1638
- */
1639
- loading: () => Loading;
1640
- /**
1641
- * Creates a Failure RemoteData with the given error.
1642
- *
1643
- * @example
1644
- * ```ts
1645
- * RemoteData.make.failure("Network error"); // Failure("Network error")
1646
- * ```
1647
- */
1648
- failure: <E>(error: E) => Failure<E>;
1649
- /**
1650
- * Creates a Success RemoteData with the given value.
1651
- *
1652
- * @example
1653
- * ```ts
1654
- * RemoteData.make.success(42); // Success(42)
1655
- * ```
1656
- */
1657
- success: <A>(value: A) => Success<A>;
1658
- };
1659
- is: {
1660
- /**
1661
- * Type guard that checks if a RemoteData is NotAsked.
1662
- *
1663
- * @example
1664
- * ```ts
1665
- * const data = RemoteData.make.notAsked();
1666
- * if (RemoteData.is.notAsked(data)) {
1667
- * console.log("Data fetch not initiated");
1668
- * }
1669
- * ```
1670
- */
1671
- notAsked: <E, A>(data: RemoteData<E, A>) => data is NotAsked;
1672
- /**
1673
- * Type guard that checks if a RemoteData is Loading.
1674
- *
1675
- * @example
1676
- * ```ts
1677
- * const data = RemoteData.make.loading();
1678
- * if (RemoteData.is.loading(data)) {
1679
- * console.log("Data is loading");
1680
- * }
1681
- * ```
1682
- */
1683
- loading: <E, A>(data: RemoteData<E, A>) => data is Loading;
1684
- /**
1685
- * Type guard that checks if a RemoteData is Failure.
1686
- *
1687
- * @example
1688
- * ```ts
1689
- * const data = RemoteData.make.failure("Failed");
1690
- * if (RemoteData.is.failure(data)) {
1691
- * console.log(data.error); // "Failed"
1692
- * }
1693
- * ```
1694
- */
1695
- failure: <E, A>(data: RemoteData<E, A>) => data is Failure<E>;
1696
- /**
1697
- * Type guard that checks if a RemoteData is Success.
1698
- *
1699
- * @example
1700
- * ```ts
1701
- * const data = RemoteData.make.success(42);
1702
- * if (RemoteData.is.success(data)) {
1703
- * console.log(data.value); // 42
1704
- * }
1705
- * ```
1706
- */
1707
- success: <E, A>(data: RemoteData<E, A>) => data is Success<A>;
1708
- };
1709
- /**
1710
- * Transforms the success value inside a RemoteData.
1711
- *
1712
- * @example
1713
- * ```ts
1714
- * pipe(RemoteData.make.success(5), RemoteData.map(n => n * 2)); // Success(10)
1715
- * pipe(RemoteData.make.loading(), RemoteData.map(n => n * 2)); // Loading
1716
- * ```
1717
- */
1718
- map: <A, B>(f: (a: A) => B) => <E>(data: RemoteData<E, A>) => RemoteData<E, B>;
1719
- /**
1720
- * Transforms the error value inside a RemoteData.
1721
- *
1722
- * @example
1723
- * ```ts
1724
- * pipe(RemoteData.make.failure("oops"), RemoteData.mapError(e => e.toUpperCase())); // Failure("OOPS")
1725
- * ```
1726
- */
1727
- mapError: <E, F>(f: (e: E) => F) => <A>(data: RemoteData<E, A>) => RemoteData<F, A>;
1728
- /**
1729
- * Chains RemoteData computations. If the input is Success, passes the value to f.
1730
- * Otherwise, propagates the current state.
1731
- *
1732
- * @example
1733
- * ```ts
1734
- * pipe(
1735
- * RemoteData.make.success(5),
1736
- * RemoteData.chain(n => n > 0 ? RemoteData.make.success(n) : RemoteData.make.failure("negative"))
1737
- * );
1738
- * ```
1739
- */
1740
- chain: <E2, A, B>(f: (a: A) => RemoteData<E2, B>) => <E1 = never>(data: RemoteData<E1, A>) => RemoteData<E1 | E2, B>;
1741
- /**
1742
- * Applies a function wrapped in a RemoteData to a value wrapped in a RemoteData.
1743
- *
1744
- * @example
1745
- * ```ts
1746
- * const add = (a: number) => (b: number) => a + b;
1747
- * pipe(
1748
- * RemoteData.make.success(add),
1749
- * RemoteData.ap(RemoteData.make.success(5)),
1750
- * RemoteData.ap(RemoteData.make.success(3))
1751
- * ); // Success(8)
1752
- * ```
1753
- */
1754
- ap: <E, A>(arg: RemoteData<E, A>) => <B>(data: RemoteData<E, (a: A) => B>) => RemoteData<E, B>;
1755
- /**
1756
- * Extracts the value from a RemoteData by providing handlers for all four cases.
1757
- *
1758
- * @example
1759
- * ```ts
1760
- * pipe(
1761
- * userData,
1762
- * RemoteData.fold(
1763
- * e => `Error: ${e}`,
1764
- * () => "Not asked",
1765
- * () => "Loading...",
1766
- * value => `Got: ${value}`
1767
- * )
1768
- * );
1769
- * ```
1770
- */
1771
- fold: <E, A, B>(onFailure: (e: E) => B, onNotAsked: () => B, onLoading: () => B, onSuccess: (a: A) => B) => (data: RemoteData<E, A>) => B;
1772
- /**
1773
- * Pattern matches on a RemoteData, returning the result of the matching case.
1774
- *
1775
- * @example
1776
- * ```ts
1777
- * pipe(
1778
- * userData,
1779
- * RemoteData.match({
1780
- * notAsked: () => "Click to load",
1781
- * loading: () => "Loading...",
1782
- * failure: e => `Error: ${e}`,
1783
- * success: user => `Hello, ${user.name}!`
1784
- * })
1785
- * );
1786
- * ```
1787
- */
1788
- match: <E, A, B>(cases: {
1789
- notAsked: () => B;
1790
- loading: () => B;
1791
- failure: (e: E) => B;
1792
- success: (a: A) => B;
1793
- }) => (data: RemoteData<E, A>) => B;
1794
- /**
1795
- * Returns the success value or a default value if the RemoteData is not Success.
1796
- * The default can be a different type, widening the result to `A | B`.
1797
- *
1798
- * @example
1799
- * ```ts
1800
- * pipe(RemoteData.make.success(5), RemoteData.getOrElse(() => 0)); // 5
1801
- * pipe(RemoteData.make.loading(), RemoteData.getOrElse(() => 0)); // 0
1802
- * pipe(RemoteData.make.loading<string, number>(), RemoteData.getOrElse(() => null)); // null — typed as number | null
1803
- * ```
1804
- */
1805
- getOrElse: <B>(defaultValue: () => B) => <E, A>(data: RemoteData<E, A>) => A | B;
1806
- /**
1807
- * Executes a side effect on the success value without changing the RemoteData.
1808
- *
1809
- * @example
1810
- * ```ts
1811
- * pipe(
1812
- * RemoteData.make.success(5),
1813
- * RemoteData.tap(n => console.log("Value:", n)),
1814
- * RemoteData.map(n => n * 2)
1815
- * );
1816
- * ```
1817
- */
1818
- tap: <E, A>(f: (a: A) => void) => (data: RemoteData<E, A>) => RemoteData<E, A>;
1819
- /**
1820
- * Executes a side effect on the failure error without changing the RemoteData.
1821
- * Useful for logging errors.
1822
- *
1823
- * @example
1824
- * ```ts
1825
- * pipe(
1826
- * RemoteData.make.failure("not found"),
1827
- * RemoteData.tapError(e => console.error("fetch failed:", e)),
1828
- * RemoteData.map(render)
1829
- * );
1830
- * ```
1831
- */
1832
- tapError: <E, A>(f: (e: E) => void) => (data: RemoteData<E, A>) => RemoteData<E, A>;
1833
- /**
1834
- * Recovers from a Failure state by providing a fallback RemoteData.
1835
- * The fallback can produce a different success type, widening the result to `RemoteData<E, A | B>`.
1836
- */
1837
- recover: <E, B>(fallback: (e: E) => RemoteData<E, B>) => <A>(data: RemoteData<E, A>) => RemoteData<E, A | B>;
1838
- to: {
1839
- /**
1840
- * Converts a RemoteData to a Maybe.
1841
- * Success becomes Some, all other states become None.
1842
- */
1843
- Maybe: <E, A>(data: RemoteData<E, A>) => Maybe<A>;
1844
- /**
1845
- * Converts a RemoteData to a Result.
1846
- * Success becomes Ok, Failure becomes Err.
1847
- * NotAsked and Loading become Err with the provided fallback error.
1848
- *
1849
- * @example
1850
- * ```ts
1851
- * pipe(
1852
- * RemoteData.make.success(42),
1853
- * RemoteData.to.Result(() => "not loaded")
1854
- * ); // Ok(42)
1855
- * ```
1856
- */
1857
- Result: <E>(onNotReady: () => E) => <A>(data: RemoteData<E, A>) => Result<E, A>;
1858
- };
1859
- from: {
1860
- /**
1861
- * Converts a Result to a RemoteData.
1862
- * Ok becomes Success, Err becomes Failure.
1863
- *
1864
- * @example
1865
- * ```ts
1866
- * const result = await Task.Result.tryCatch(() => loadUser(), { onError: String })();
1867
- * setState(RemoteData.from.Result(result)); // Success(user) or Failure(msg)
1868
- * ```
1869
- */
1870
- Result: <E, A>(data: Result<E, A>) => RemoteData<E, A>;
1871
- /**
1872
- * Converts a Maybe to a RemoteData.
1873
- * Some becomes Success, None becomes Failure using the onNone error producer.
1874
- *
1875
- * @example
1876
- * ```ts
1877
- * pipe(Maybe.make.some(user), RemoteData.from.Maybe(() => "not found")); // Success(user)
1878
- * pipe(Maybe.make.none(), RemoteData.from.Maybe(() => "not found")); // Failure("not found")
1879
- * ```
1880
- */
1881
- Maybe: <E>(onNone: () => E) => <A>(data: Maybe<A>) => RemoteData<E, A>;
1882
- };
1883
- /**
1884
- * Filters a `Success` value. When the predicate passes, the value is kept. When it fails,
1885
- * `Success` becomes `Failure` using the error produced by `onFalse`. All other states pass through unchanged.
1886
- *
1887
- * @example
1888
- * ```ts
1889
- * RemoteData.filter(n => n > 0, n => `${n} is not a valid price`)(RemoteData.make.success(9.99));
1890
- * // Success(9.99)
1891
- * RemoteData.filter(n => n > 0, n => `${n} is not a valid price`)(RemoteData.make.success(-1));
1892
- * // Failure("-1 is not a valid price")
1893
- * RemoteData.filter(n => n > 0, () => "error")(RemoteData.make.loading()); // Loading
1894
- * ```
1895
- */
1896
- filter: <E, A>(pred: (a: A) => boolean, onFalse: (a: A) => E) => (data: RemoteData<E, A>) => RemoteData<E, A>;
1897
- };
1898
-
1899
- /**
1900
- * A Resource pairs an async acquisition step with a guaranteed cleanup step.
1901
- *
1902
- * Use it whenever something must be explicitly closed, released, or torn down
1903
- * after you are done with it — database connections, file handles, locks,
1904
- * temporary directories, or any object with a lifecycle.
1905
- *
1906
- * The key guarantee: `release` always runs after `Resource.use`, even when
1907
- * the work function returns an error. If `acquire` itself fails, `release` is
1908
- * skipped — there is nothing to clean up.
1909
- *
1910
- * Build a Resource with `Resource.from.handlers` or `Resource.from.Task`, then run it
1911
- * with `Resource.use`.
1912
- *
1913
- * @example
1914
- * ```ts
1915
- * const dbResource = Resource.from.handlers(
1916
- * Task.Result.tryCatch(() => openConnection(config), { onError: (e) => new DbError(e) }),
1917
- * (conn) => Task.tryCatch(() => conn.close(), { onError: () => {} })
1918
- * );
1919
- *
1920
- * const result = await pipe(
1921
- * dbResource,
1922
- * Resource.use((conn) => queryUser(conn, userId))
1923
- * )();
1924
- * // conn.close() is called whether queryUser succeeds or fails
1925
- * ```
1926
- */
1927
- type Resource<E, A> = {
1928
- readonly acquire: Task.Result<E, A>;
1929
- readonly release: (a: A) => Task<void>;
1930
- };
1931
- declare const Resource: {
1932
- from: {
1933
- /**
1934
- * Creates a Resource from an acquire operation that may fail and a release function.
1935
- *
1936
- * @example
1937
- * ```ts
1938
- * const fileResource = Resource.from.handlers(
1939
- * Task.Result.tryCatch(() => fs.promises.open("data.csv", "r"), { onError: toFileError }),
1940
- * (handle) => Task.tryCatch(() => handle.close(), { onError: () => {} })
1941
- * );
1942
- * ```
1943
- */
1944
- handlers: <E, A>(acquire: Task.Result<E, A>, release: (a: A) => Task<void>) => Resource<E, A>;
1945
- /**
1946
- * Creates a Resource from an acquire operation that cannot fail.
1947
- * Use this when opening the resource is guaranteed to succeed, such as
1948
- * in-memory locks, counters, or timers.
1949
- *
1950
- * @example
1951
- * ```ts
1952
- * const timerResource = Resource.from.Task<never, Timer>(
1953
- * Task.tryCatch(() => Promise.resolve(startTimer()), { onError: () => defaultTimer }),
1954
- * (timer) => Task.tryCatch(() => Promise.resolve(timer.stop()), { onError: () => {} })
1955
- * );
1956
- * ```
1957
- */
1958
- Task: <E, A>(acquire: Task<A>, release: (a: A) => Task<void>) => Resource<E, A>;
1959
- };
1960
- /**
1961
- * Acquires the resource, runs `f` with it, then releases it.
1962
- *
1963
- * Release always runs, even when `f` returns an error.
1964
- * If acquire fails, `f` and release are both skipped and the error is returned.
1965
- *
1966
- * @example
1967
- * ```ts
1968
- * const rows = await pipe(
1969
- * dbResource,
1970
- * Resource.use((conn) => runQuery(conn, "SELECT * FROM users"))
1971
- * )();
1972
- * // conn is closed whether the query succeeds or fails
1973
- * ```
1974
- */
1975
- use: <E, A, B>(f: (a: A) => Task.Result<E, B>) => (resource: Resource<E, A>) => Task.Result<E, B>;
1976
- /**
1977
- * Acquires two resources in sequence and presents them as a tuple.
1978
- * Resources are released in reverse order: the second is released before the first.
1979
- *
1980
- * If the second resource fails to acquire, the first is released immediately
1981
- * before returning the error.
1982
- *
1983
- * @example
1984
- * ```ts
1985
- * const combined = Resource.combine(dbResource, cacheResource);
1986
- *
1987
- * const result = await pipe(
1988
- * combined,
1989
- * Resource.use(([conn, cache]) => lookupWithFallback(conn, cache, userId))
1990
- * )();
1991
- * ```
1992
- */
1993
- combine: <E, A, B>(resourceA: Resource<E, A>, resourceB: Resource<E, B>) => Resource<E, readonly [A, B]>;
1994
- };
1995
-
1996
- /**
1997
- * A synchronous computation that threads a piece of mutable state `S` through
1998
- * a pipeline without exposing mutation at call sites.
1999
- *
2000
- * At runtime a `State<S, A>` is just a function from an initial state to a pair
2001
- * `[value, nextState]`. Nothing runs until you supply the initial state with
2002
- * `State.run`, `State.evaluate`, or `State.execute`.
2003
- *
2004
- * @example
2005
- * ```ts
2006
- * type Counter = number;
2007
- *
2008
- * const increment: State<Counter, undefined> = State.modify(n => n + 1);
2009
- * const getCount: State<Counter, Counter> = State.get();
2010
- *
2011
- * const program = pipe(
2012
- * increment,
2013
- * State.chain(() => increment),
2014
- * State.chain(() => getCount),
2015
- * );
2016
- *
2017
- * State.run(0)(program); // [2, 2] — value is 2, final state is 2
2018
- * ```
2019
- */
2020
- type State<S, A> = (s: S) => readonly [A, S];
2021
- declare const State: {
2022
- /**
2023
- * Lifts a pure value into a State computation. The state passes through unchanged.
2024
- *
2025
- * @example
2026
- * ```ts
2027
- * State.run(10)(State.resolve(42)); // [42, 10] — value 42, state unchanged
2028
- * ```
2029
- */
2030
- resolve: <S, A>(value: A) => State<S, A>;
2031
- /**
2032
- * Produces the current state as the value, without modifying it.
2033
- *
2034
- * @example
2035
- * ```ts
2036
- * const readStack: State<string[], string[]> = State.get();
2037
- * State.run(["a", "b"])(readStack); // [["a", "b"], ["a", "b"]]
2038
- * ```
2039
- */
2040
- get: <S>() => State<S, S>;
2041
- /**
2042
- * Reads a projection of the state without modifying it.
2043
- * Equivalent to `pipe(State.get(), State.map(f))` but more direct.
2044
- *
2045
- * @example
2046
- * ```ts
2047
- * type AppState = { count: number; label: string };
2048
- * const readCount: State<AppState, number> = State.gets(s => s.count);
2049
- * State.run({ count: 5, label: "x" })(readCount); // [5, { count: 5, label: "x" }]
2050
- * ```
2051
- */
2052
- gets: <S, A>(f: (s: S) => A) => State<S, A>;
2053
- /**
2054
- * Replaces the current state with a new value. Produces no meaningful value.
2055
- *
2056
- * @example
2057
- * ```ts
2058
- * const reset: State<number, undefined> = State.put(0);
2059
- * State.run(99)(reset); // [undefined, 0]
2060
- * ```
2061
- */
2062
- put: <S>(newState: S) => State<S, undefined>;
2063
- /**
2064
- * Applies a function to the current state to produce the next state.
2065
- * Produces no meaningful value.
2066
- *
2067
- * @example
2068
- * ```ts
2069
- * const push = (item: string): State<string[], undefined> =>
2070
- * State.modify(stack => [...stack, item]);
2071
- *
2072
- * State.run(["a"])(push("b")); // [undefined, ["a", "b"]]
2073
- * ```
2074
- */
2075
- modify: <S>(f: (s: S) => S) => State<S, undefined>;
2076
- /**
2077
- * Transforms the value produced by a State computation.
2078
- * The state transformation is unchanged.
2079
- *
2080
- * @example
2081
- * ```ts
2082
- * const readLength: State<string[], number> = pipe(
2083
- * State.get<string[]>(),
2084
- * State.map(stack => stack.length),
2085
- * );
2086
- *
2087
- * State.run(["a", "b", "c"])(readLength); // [3, ["a", "b", "c"]]
2088
- * ```
2089
- */
2090
- map: <S, A, B>(f: (a: A) => B) => (st: State<S, A>) => State<S, B>;
2091
- /**
2092
- * Sequences two State computations. The state output of the first is passed
2093
- * as the state input to the second.
2094
- *
2095
- * Data-last — the first computation is the data being piped.
2096
- *
2097
- * @example
2098
- * ```ts
2099
- * const push = (item: string): State<string[], undefined> =>
2100
- * State.modify(stack => [...stack, item]);
2101
- *
2102
- * const program = pipe(
2103
- * push("a"),
2104
- * State.chain(() => push("b")),
2105
- * State.chain(() => State.get<string[]>()),
2106
- * );
2107
- *
2108
- * State.evaluate([])(program); // ["a", "b"]
2109
- * ```
2110
- */
2111
- chain: <S, A, B>(f: (a: A) => State<S, B>) => (st: State<S, A>) => State<S, B>;
2112
- /**
2113
- * Applies a function wrapped in a State to a value wrapped in a State.
2114
- * The function computation runs first; its output state is the input to the
2115
- * argument computation.
2116
- *
2117
- * @example
2118
- * ```ts
2119
- * const addCounted = (n: number) => (m: number) => n + m;
2120
- * const program = pipe(
2121
- * State.resolve<number, typeof addCounted>(addCounted),
2122
- * State.ap(State.gets((s: number) => s * 2)),
2123
- * State.ap(State.gets((s: number) => s)),
2124
- * );
2125
- *
2126
- * State.evaluate(3)(program); // 6 + 3 = 9
2127
- * ```
2128
- */
2129
- ap: <S, A>(arg: State<S, A>) => <B>(fn: State<S, (a: A) => B>) => State<S, B>;
2130
- /**
2131
- * Runs a side effect on the produced value without changing the State computation.
2132
- *
2133
- * @example
2134
- * ```ts
2135
- * pipe(
2136
- * State.get<number>(),
2137
- * State.tap(n => console.log("current:", n)),
2138
- * State.chain(() => State.modify(n => n + 1)),
2139
- * );
2140
- * ```
2141
- */
2142
- tap: <S, A>(f: (a: A) => void) => (st: State<S, A>) => State<S, A>;
2143
- /**
2144
- * Runs a State computation with an initial state, returning both the
2145
- * produced value and the final state as a pair.
2146
- *
2147
- * Data-last — the computation is the data being piped.
2148
- *
2149
- * @example
2150
- * ```ts
2151
- * const program = pipe(
2152
- * State.modify<number>(n => n + 1),
2153
- * State.chain(() => State.get<number>()),
2154
- * );
2155
- *
2156
- * State.run(0)(program); // [1, 1]
2157
- * ```
2158
- */
2159
- run: <S>(initialState: S) => <A>(st: State<S, A>) => readonly [A, S];
2160
- /**
2161
- * Runs a State computation with an initial state, returning only the
2162
- * produced value (discarding the final state).
2163
- *
2164
- * @example
2165
- * ```ts
2166
- * State.evaluate([])(pipe(
2167
- * State.modify<string[]>(s => [...s, "x"]),
2168
- * State.chain(() => State.get<string[]>()),
2169
- * )); // ["x"]
2170
- * ```
2171
- */
2172
- evaluate: <S>(initialState: S) => <A>(st: State<S, A>) => A;
2173
- /**
2174
- * Runs a State computation with an initial state, returning only the
2175
- * final state (discarding the produced value).
2176
- *
2177
- * @example
2178
- * ```ts
2179
- * State.execute(0)(pipe(
2180
- * State.modify<number>(n => n + 10),
2181
- * State.chain(() => State.modify<number>(n => n * 2)),
2182
- * )); // 20
2183
- * ```
2184
- */
2185
- execute: <S>(initialState: S) => <A>(st: State<S, A>) => S;
2186
- /**
2187
- * Lifts a State value into an accumulator object.
2188
- *
2189
- * @example
2190
- * ```ts
2191
- * pipe(State.resolve(42), State.bindTo("value")); // State({ value: 42 })
2192
- * ```
2193
- */
2194
- bindTo: <K extends string>(key: K) => <S, A>(data: State<S, A>) => State<S, { [P in K]: A; }>;
2195
- /**
2196
- * Evaluates a new State using the current accumulator and attaches the output to a new key.
2197
- *
2198
- * @example
2199
- * ```ts
2200
- * pipe(
2201
- * State.resolve({ a: 1 }),
2202
- * State.bind("b", ({ a }) => State.resolve(a + 1))
2203
- * ); // State({ a: 1, b: 2 })
2204
- * ```
2205
- */
2206
- bind: <K extends string, S, A, B>(key: K, f: (a: A) => State<S, B>) => (data: State<S, A>) => State<S, A & { [P in K]: B; }>;
2207
- /**
2208
- * Focuses a State computation on a sub-state using a Lens.
2209
- *
2210
- * @example
2211
- * ```ts
2212
- * type AppState = { count: number; name: string };
2213
- * const countLens = Lens.from.property<AppState>()("count");
2214
- * const increment = State.modify((c: number) => c + 1);
2215
- * const focusedProgram = pipe(increment, State.focus(countLens));
2216
- * ```
2217
- */
2218
- focus: <S, A>(lens: Lens<S, A>) => <B>(stateOp: State<A, B>) => State<S, B>;
2219
- };
2220
-
2221
- /**
2222
- * An event stream pipeline for a typed message schema `S`.
2223
- *
2224
- * `Stream` provides typed event emission, sequence matching, state reduction,
2225
- * and structural stream forwarding.
2226
- *
2227
- * @example
2228
- * ```ts
2229
- * type AppMessages = {
2230
- * userLoggedIn: { userId: string };
2231
- * checkoutStarted: { amount: number };
2232
- * };
2233
- *
2234
- * const appStream = Stream.make<AppMessages>();
2235
- *
2236
- * const subscription = Stream.listen(
2237
- * appStream,
2238
- * ["userLoggedIn", "checkoutStarted"],
2239
- * { ordered: true }
2240
- * ).reduce(
2241
- * (msg, state) => {
2242
- * if (msg.kind === "checkoutStarted") {
2243
- * return { count: state.count + 1 };
2244
- * }
2245
- * return state;
2246
- * },
2247
- * { count: 0 }
2248
- * );
2249
- *
2250
- * Stream.emit(appStream, {
2251
- * kind: "userLoggedIn",
2252
- * value: { userId: "user-1" },
2253
- * });
2254
- * ```
2255
- */
2256
- type Stream<S extends Record<string, unknown>> = {
2257
- readonly options?: Stream.Options;
2258
- /** @internal */
2259
- readonly _listeners: Set<(msg: Stream.Message<S>) => void>;
2260
- /**
2261
- * @internal
2262
- * Lazy array snapshot of `_listeners`. Avoids allocating new array objects on every `emit` call
2263
- * (2.98x emission speedup, 0 heap allocations). Rebuilt whenever `_listeners` is mutated,
2264
- * guaranteeing reentrancy safety and preventing listeners subscribed mid-emission from executing early.
2265
- */
2266
- _listenerArray: Array<(msg: Stream.Message<S>) => void> | null;
2267
- /** @internal */
2268
- readonly _queue: Array<Stream.Message<S>>;
2269
- /** @internal */
2270
- _isEmitting: boolean;
2271
- };
2272
- declare const Stream: {
2273
- /**
2274
- * Constructs a new `Stream` instance.
2275
- *
2276
- * @example
2277
- * ```ts
2278
- * const stream = Stream.make<AppMessages>({ name: "app" });
2279
- * ```
2280
- */
2281
- make: <S extends Record<string, unknown>>(options?: Stream.Options) => Stream<S>;
2282
- /**
2283
- * Emits a message payload to one or more target streams.
2284
- *
2285
- * Uses a synchronous breadth-first trampoline queue to handle re-entrant emissions deterministically.
2286
- *
2287
- * @example
2288
- * ```ts
2289
- * Stream.emit(streamA, {
2290
- * kind: "userLoggedIn",
2291
- * value: { userId: "user-1" },
2292
- * });
2293
- *
2294
- * Stream.emit([streamA, streamB], {
2295
- * kind: "userLoggedIn",
2296
- * value: { userId: "user-1" },
2297
- * });
2298
- * ```
2299
- */
2300
- emit: <S extends Record<string, unknown>, K extends keyof S & string>(target: Stream<S> | ReadonlyArray<Stream<S>>, message: WithKind<K> & WithValue<S[K]>) => void;
2301
- /**
2302
- * Forwards messages from one stream to another (or multiple).
2303
- *
2304
- * @example
2305
- * ```ts
2306
- * const stop = Stream.forward({
2307
- * from: authStream,
2308
- * to: analyticsStream,
2309
- * only: ["userLoggedIn"],
2310
- * });
2311
- * ```
2312
- */
2313
- forward: <S extends Record<string, unknown>>(options: Stream.ForwardOptions<S>) => () => void;
2314
- /**
2315
- * Initiates listener registration on a stream for specific event kind(s) or sequence.
2316
- *
2317
- * @example
2318
- * ```ts
2319
- * const sub = Stream.listen(
2320
- * appStream,
2321
- * ["userLoggedIn", "checkoutStarted"],
2322
- * { ordered: true }
2323
- * ).reduce(
2324
- * (msg, state) => ({ count: state.count + 1 }),
2325
- * { count: 0 }
2326
- * );
2327
- * ```
2328
- */
2329
- listen: <S extends Record<string, unknown>, K extends keyof S & string>(stream: Stream<S>, events: K | ReadonlyArray<K>, options?: Stream.SequenceOptions<S>) => Stream.ListenerBuilder<S>;
2330
- };
2331
- declare namespace Stream {
2332
- type Message<S extends Record<string, unknown>> = {
2333
- [K in keyof S & string]: WithKind<K> & WithValue<S[K]>;
2334
- }[keyof S & string];
2335
- type Options = {
2336
- readonly name?: string;
2337
- readonly onError?: (error: unknown) => void;
2338
- };
2339
- type SequenceOptions<S extends Record<string, unknown>> = {
2340
- readonly ordered?: boolean;
2341
- readonly strict?: boolean;
2342
- readonly once?: boolean;
2343
- readonly reset?: (keyof S & string) | ReadonlyArray<keyof S & string>;
2344
- readonly optional?: (keyof S & string) | ReadonlyArray<keyof S & string>;
2345
- };
2346
- type Subscription<State> = {
2347
- readonly unsubscribe: () => void;
2348
- readonly getState: () => State;
2349
- };
2350
- type ForwardOptions<S extends Record<string, unknown>> = {
2351
- readonly from: Stream<S>;
2352
- readonly to: Stream<S> | ReadonlyArray<Stream<S>>;
2353
- readonly only?: ReadonlyArray<keyof S & string>;
2354
- };
2355
- type ListenerBuilder<S extends Record<string, unknown>> = {
2356
- readonly reduce: <State>(reducer: (msg: Message<S>, state: State) => State, initialState: State) => Subscription<State>;
2357
- readonly tap: (effect: (msg: Message<S>) => void) => () => void;
2358
- };
2359
- }
2360
-
2361
- type TheseFirst<T> = WithKind<"First"> & WithFirst<T>;
2362
- type TheseSecond<T> = WithKind<"Second"> & WithSecond<T>;
2363
- type TheseBoth<First, Second> = WithKind<"Both"> & WithFirst<First> & WithSecond<Second>;
2364
- /**
2365
- * These<A, B> is an inclusive-OR type: it holds a first value (A), a second
2366
- * value (B), or both simultaneously. Neither side carries a success/failure
2367
- * connotation — it is a neutral pair where any combination is valid.
2368
- *
2369
- * - First(a) — only a first value
2370
- * - Second(b) — only a second value
2371
- * - Both(a, b) — first and second values simultaneously
2372
- *
2373
- * A common use: lenient parsers or processors that carry a diagnostic note
2374
- * alongside a result, without losing either piece of information.
2375
- *
2376
- * @example
2377
- * ```ts
2378
- * const parse = (s: string): These<number, string> => {
2379
- * const trimmed = s.trim();
2380
- * const n = parseFloat(trimmed);
2381
- * if (isNaN(n)) return These.make.second("Not a number");
2382
- * if (s !== trimmed) return These.make.both(n, "Leading/trailing whitespace trimmed");
2383
- * return These.make.first(n);
2384
- * };
2385
- * ```
2386
- */
2387
- type These<A, B> = TheseFirst<A> | TheseSecond<B> | TheseBoth<A, B>;
2388
- declare const These: {
2389
- make: {
2390
- /**
2391
- * Creates a These holding only a first value.
2392
- *
2393
- * @example
2394
- * ```ts
2395
- * These.make.first(42); // { kind: "First", first: 42 }
2396
- * ```
2397
- */
2398
- first: <A>(value: A) => TheseFirst<A>;
2399
- /**
2400
- * Creates a These holding only a second value.
2401
- *
2402
- * @example
2403
- * ```ts
2404
- * These.make.second("warning"); // { kind: "Second", second: "warning" }
2405
- * ```
2406
- */
2407
- second: <B>(value: B) => TheseSecond<B>;
2408
- /**
2409
- * Creates a These holding both a first and a second value simultaneously.
2410
- *
2411
- * @example
2412
- * ```ts
2413
- * These.make.both(42, "Deprecated API used"); // { kind: "Both", first: 42, second: "Deprecated API used" }
2414
- * ```
2415
- */
2416
- both: <A, B>(f: A, s: B) => TheseBoth<A, B>;
2417
- };
2418
- is: {
2419
- /**
2420
- * Type guard — checks if a These holds only a first value.
2421
- *
2422
- * @example
2423
- * ```ts
2424
- * const val = These.make.first(42);
2425
- * if (These.is.first(val)) {
2426
- * console.log(val.first); // 42
2427
- * }
2428
- * ```
2429
- */
2430
- first: <A, B>(data: These<A, B>) => data is TheseFirst<A>;
2431
- /**
2432
- * Type guard — checks if a These holds only a second value.
2433
- *
2434
- * @example
2435
- * ```ts
2436
- * const val = These.make.second("warning");
2437
- * if (These.is.second(val)) {
2438
- * console.log(val.second); // "warning"
2439
- * }
2440
- * ```
2441
- */
2442
- second: <A, B>(data: These<A, B>) => data is TheseSecond<B>;
2443
- /**
2444
- * Type guard — checks if a These holds both values simultaneously.
2445
- *
2446
- * @example
2447
- * ```ts
2448
- * const val = These.make.both(42, "warning");
2449
- * if (These.is.both(val)) {
2450
- * console.log(val.first, val.second); // 42 "warning"
2451
- * }
2452
- * ```
2453
- */
2454
- both: <A, B>(data: These<A, B>) => data is TheseBoth<A, B>;
2455
- };
2456
- /**
2457
- * Returns true if the These contains a first value (First or Both).
2458
- *
2459
- * @example
2460
- * ```ts
2461
- * These.hasFirst(These.make.first(42)); // true
2462
- * These.hasFirst(These.make.both(42, "warn"));// true
2463
- * These.hasFirst(These.make.second("warn")); // false
2464
- * ```
2465
- */
2466
- hasFirst: <A, B>(data: These<A, B>) => data is TheseFirst<A> | TheseBoth<A, B>;
2467
- /**
2468
- * Returns true if the These contains a second value (Second or Both).
2469
- *
2470
- * @example
2471
- * ```ts
2472
- * These.hasSecond(These.make.second("warn")); // true
2473
- * These.hasSecond(These.make.both(42, "warn"));// true
2474
- * These.hasSecond(These.make.first(42)); // false
2475
- * ```
2476
- */
2477
- hasSecond: <A, B>(data: These<A, B>) => data is TheseSecond<B> | TheseBoth<A, B>;
2478
- /**
2479
- * Transforms the first value, leaving the second unchanged.
2480
- *
2481
- * @example
2482
- * ```ts
2483
- * pipe(These.make.first(5), These.mapFirst(n => n * 2)); // First(10)
2484
- * pipe(These.make.both(5, "warn"), These.mapFirst(n => n * 2)); // Both(10, "warn")
2485
- * pipe(These.make.second("warn"), These.mapFirst(n => n * 2)); // Second("warn")
2486
- * ```
2487
- */
2488
- mapFirst: <A, C>(f: (a: A) => C) => <B>(data: These<A, B>) => These<C, B>;
2489
- /**
2490
- * Transforms the second value, leaving the first unchanged.
2491
- *
2492
- * @example
2493
- * ```ts
2494
- * pipe(These.make.second("warn"), These.mapSecond(e => e.toUpperCase())); // Second("WARN")
2495
- * pipe(These.make.both(5, "warn"), These.mapSecond(e => e.toUpperCase())); // Both(5, "WARN")
2496
- * ```
2497
- */
2498
- mapSecond: <B, D>(f: (b: B) => D) => <A>(data: These<A, B>) => These<A, D>;
2499
- /**
2500
- * Transforms both the first and second values independently.
2501
- *
2502
- * @example
2503
- * ```ts
2504
- * pipe(
2505
- * These.make.both(5, "warn"),
2506
- * These.mapBoth(n => n * 2, e => e.toUpperCase())
2507
- * ); // Both(10, "WARN")
2508
- * ```
2509
- */
2510
- mapBoth: <A, C, B, D>(onFirst: (a: A) => C, onSecond: (b: B) => D) => (data: These<A, B>) => These<C, D>;
2511
- /**
2512
- * Chains These computations by passing the first value to f.
2513
- * Second propagates unchanged; First and Both apply f to the first value.
2514
- *
2515
- * @example
2516
- * ```ts
2517
- * const double = (n: number): These<number, string> => These.make.first(n * 2);
2518
- *
2519
- * pipe(These.make.first(5), These.chainFirst(double)); // First(10)
2520
- * pipe(These.make.both(5, "warn"), These.chainFirst(double)); // First(10)
2521
- * pipe(These.make.second("warn"), These.chainFirst(double)); // Second("warn")
2522
- * ```
2523
- */
2524
- chainFirst: <A, B, C>(f: (a: A) => These<C, B>) => (data: These<A, B>) => These<C, B>;
2525
- /**
2526
- * Chains These computations by passing the second value to f.
2527
- * First propagates unchanged; Second and Both apply f to the second value.
2528
- *
2529
- * @example
2530
- * ```ts
2531
- * const shout = (s: string): These<number, string> => These.make.second(s.toUpperCase());
2532
- *
2533
- * pipe(These.make.second("warn"), These.chainSecond(shout)); // Second("WARN")
2534
- * pipe(These.make.both(5, "warn"), These.chainSecond(shout)); // Second("WARN")
2535
- * pipe(These.make.first(5), These.chainSecond(shout)); // First(5)
2536
- * ```
2537
- */
2538
- chainSecond: <A, B, D>(f: (b: B) => These<A, D>) => (data: These<A, B>) => These<A, D>;
2539
- /**
2540
- * Extracts a value from a These by providing handlers for all three cases.
2541
- *
2542
- * @example
2543
- * ```ts
2544
- * pipe(
2545
- * these,
2546
- * These.fold(
2547
- * a => `First: ${a}`,
2548
- * b => `Second: ${b}`,
2549
- * (a, b) => `Both: ${a} / ${b}`
2550
- * )
2551
- * );
2552
- * ```
2553
- */
2554
- fold: <A, B, C>(onFirst: (a: A) => C, onSecond: (b: B) => C, onBoth: (a: A, b: B) => C) => (data: These<A, B>) => C;
2555
- /**
2556
- * Pattern matches on a These, returning the result of the matching case.
2557
- *
2558
- * @example
2559
- * ```ts
2560
- * pipe(
2561
- * these,
2562
- * These.match({
2563
- * first: a => `First: ${a}`,
2564
- * second: b => `Second: ${b}`,
2565
- * both: (a, b) => `Both: ${a} / ${b}`
2566
- * })
2567
- * );
2568
- * ```
2569
- */
2570
- match: <A, B, C>(cases: {
2571
- first: (a: A) => C;
2572
- second: (b: B) => C;
2573
- both: (a: A, b: B) => C;
2574
- }) => (data: These<A, B>) => C;
2575
- /**
2576
- * Returns the first value, or a default if the These has no first value.
2577
- * The default can be a different type, widening the result to `A | C`.
2578
- *
2579
- * @example
2580
- * ```ts
2581
- * pipe(These.make.first(5), These.getFirstOrElse(() => 0)); // 5
2582
- * pipe(These.make.both(5, "warn"), These.getFirstOrElse(() => 0)); // 5
2583
- * pipe(These.make.second("warn"), These.getFirstOrElse(() => 0)); // 0
2584
- * pipe(These.make.second("warn"), These.getFirstOrElse(() => null)); // null — typed as number | null
2585
- * ```
2586
- */
2587
- getFirstOrElse: <A, C>(defaultValue: () => C) => <B>(data: These<A, B>) => A | C;
2588
- /**
2589
- * Returns the second value, or a default if the These has no second value.
2590
- * The default can be a different type, widening the result to `B | D`.
2591
- *
2592
- * @example
2593
- * ```ts
2594
- * pipe(These.make.second("warn"), These.getSecondOrElse(() => "none")); // "warn"
2595
- * pipe(These.make.both(5, "warn"), These.getSecondOrElse(() => "none")); // "warn"
2596
- * pipe(These.make.first(5), These.getSecondOrElse(() => "none")); // "none"
2597
- * pipe(These.make.first(5), These.getSecondOrElse(() => null)); // null — typed as string | null
2598
- * ```
2599
- */
2600
- getSecondOrElse: <B, D>(defaultValue: () => D) => <A>(data: These<A, B>) => B | D;
2601
- /**
2602
- * Runs a side effect on the first value without changing the These.
2603
- * Useful for logging or debugging.
2604
- *
2605
- * @example
2606
- * ```ts
2607
- * pipe(These.make.first(5), These.tap(console.log)); // logs 5, returns First(5)
2608
- * ```
2609
- */
2610
- tap: <A>(f: (a: A) => void) => <B>(data: These<A, B>) => These<A, B>;
2611
- /**
2612
- * Swaps the roles of first and second values.
2613
- * - First(a) → Second(a)
2614
- * - Second(b) → First(b)
2615
- * - Both(a, b) → Both(b, a)
2616
- *
2617
- * @example
2618
- * ```ts
2619
- * These.swap(These.make.first(5)); // Second(5)
2620
- * These.swap(These.make.second("warn")); // First("warn")
2621
- * These.swap(These.make.both(5, "warn")); // Both("warn", 5)
2622
- * ```
2623
- */
2624
- swap: <A, B>(data: These<A, B>) => These<B, A>;
2625
- };
2626
-
2627
- export { Combinable, Deferred, type Failure, Lazy, Lens, type Loading, Logged, Maybe, type NotAsked, Op, Optional, Pair, Predicate, Reader, Refinement, RemoteData, Resource, Result, State, Stream, type Success, Task, These, type TheseBoth, type TheseFirst, type TheseSecond };
1
+ import { x as Deferred } from "./InternalTypes-DzDey5Do.js";
2
+ import { A as Logged, C as Pair, D as Maybe, E as Op, M as Lazy, N as Equality, O as None, P as Combinable, S as Predicate, T as Optional, _ as NotAsked, a as Task, b as Refinement, c as Validation, d as Err, f as Ok, g as Loading, h as Failure, i as TheseSecond, j as Lens, k as Some, l as Stream, m as Resource, n as TheseBoth, o as Failed, p as Result, r as TheseFirst, s as Passed, t as These, u as State, v as RemoteData, w as Ordering, x as Reader, y as Success } from "./index-B07Wr815.js";
3
+ export { Combinable, Deferred, Equality, Err, Failed, Failure, Lazy, Lens, Loading, Logged, Maybe, None, NotAsked, Ok, Op, Optional, Ordering, Pair, Passed, Predicate, Reader, Refinement, RemoteData, Resource, Result, Some, State, Stream, Success, Task, These, TheseBoth, TheseFirst, TheseSecond, Validation };