pure-effect 0.11.0 → 0.13.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/index.d.ts CHANGED
@@ -27,14 +27,19 @@ export type CommandState<R, T, E = unknown, Ctx = unknown> = {
27
27
  * `Parallel` no argument is passed at all.
28
28
  */
29
29
  cmd: (signal?: AbortSignal) => Promise<R> | R;
30
- next: (result: R) => Effect<T, E, Ctx>;
30
+ /**
31
+ * Method syntax, not a function-typed property, on every state's `next`: `strictFunctionTypes`
32
+ * checks a property's parameter contravariantly, which made a `CommandState<never, ...>` (a `cmd`
33
+ * that only throws) unassignable to `Effect`. Method parameters are bivariant, so it is accepted.
34
+ */
35
+ next(result: R): Effect<T, E, Ctx>;
31
36
  meta?: CommandMeta;
32
37
  initialInput?: unknown;
33
38
  };
34
39
 
35
40
  export type AskState<T, E = unknown, Ctx = unknown> = {
36
41
  type: 'Ask';
37
- next: (context: Ctx) => Effect<T, E, Ctx>;
42
+ next(context: Ctx): Effect<T, E, Ctx>;
38
43
  initialInput?: unknown;
39
44
  };
40
45
 
@@ -53,7 +58,7 @@ export type RetryState<T, E = unknown, Ctx = unknown> = {
53
58
  type: 'Retry';
54
59
  effect: Effect<T, any, Ctx>;
55
60
  options: RetryOptions & { onExhausted?: (error: RetryExhaustedError<any>) => Effect<T, any, Ctx> };
56
- next: (value: T) => Effect<T, E, Ctx>;
61
+ next(value: T): Effect<T, E, Ctx>;
57
62
  initialInput?: unknown;
58
63
  };
59
64
 
@@ -66,7 +71,7 @@ export type RetryExhaustedError<E = unknown> = {
66
71
  export type ParallelState<T extends readonly unknown[], R, E = unknown, Ctx = unknown> = {
67
72
  type: 'Parallel';
68
73
  effects: { [K in keyof T]: Effect<T[K], E, Ctx> };
69
- next: (values: [...T]) => Effect<R, E, Ctx>;
74
+ next(values: [...T]): Effect<R, E, Ctx>;
70
75
  initialInput?: unknown;
71
76
  };
72
77
 
@@ -291,22 +296,26 @@ export interface EffectConfiguration {
291
296
  }
292
297
 
293
298
  /**
294
- * Configures the global runner. Several configurations can be passed and are merged, which is how
295
- * independent concerns share the one slot each hook has: `onStep` and `onRun` nest with the first
296
- * outermost, `onBeforeCommand` interceptors all run in order, and `retry` merges with later winning.
297
- * Merging does not accumulate across calls: a later call replaces the previous wiring, and calling
298
- * this with nothing resets every slot to its default.
299
- *
300
- * Returns a function that puts back whatever was installed when this call was made, so a caller can
301
- * install hooks without owning the global wiring forever. Restoring is a snapshot rather than a stack:
302
- * if a later call has run since, restoring reverts to the older snapshot and discards the newer one.
299
+ * Adds a layer to the global runner's wiring and returns a function that removes it. Layers merge:
300
+ * `onStep` and `onRun` nest with the earliest layer outermost, `onBeforeCommand` interceptors all run
301
+ * in the order installed, and `retry` merges with later layers winning. Several configurations passed
302
+ * to one call form one layer, which is the same as installing them in separate calls. Calling with no
303
+ * arguments at all removes every layer; a call whose arguments are all `undefined` adds and removes nothing.
303
304
  */
304
305
  export declare function configureEffect(...configs: (EffectConfiguration | undefined)[]): () => void;
305
306
 
307
+ /**
308
+ * A per-call configuration for `runEffect`. With `inherit: true` (default) the call's hooks are added to
309
+ * the wiring `configureEffect` installed: where both define a hook the two nest, global outermost, and
310
+ * `retry` merges with the call winning. With `inherit: false` the global wiring is ignored, so unset
311
+ * slots fall back to the library defaults.
312
+ */
313
+ export type CallConfiguration = EffectConfiguration & { inherit?: boolean };
314
+
306
315
  export declare function runEffect<T, E = unknown, Ctx = unknown>(
307
316
  effect: Effect<T, E, Ctx>,
308
317
  context?: Ctx,
309
- callConfig?: EffectConfiguration
318
+ callConfig?: CallConfiguration
310
319
  ): Promise<SuccessState<T> | FailureState<E>>;
311
320
 
312
321
  export type ReplayStep = {
@@ -397,7 +406,10 @@ export interface ReplayOptions<Ctx = unknown> {
397
406
  context?: Ctx;
398
407
  /** Strip `Retry` delays so a replay does not wait out production backoff (default `true`). */
399
408
  fastRetry?: boolean;
400
- /** Allow configured `onRun` / `onBeforeCommand` to fire (default `false`). */
409
+ /**
410
+ * Run the replay inside the global hooks, resolver innermost, so configured hooks observe it
411
+ * (default `false`, which ignores the global hooks). Global `retry` defaults apply either way.
412
+ */
401
413
  hooks?: boolean;
402
414
  /**
403
415
  * What to do when the Resolver has no recording for a step.
@@ -406,29 +418,45 @@ export interface ReplayOptions<Ctx = unknown> {
406
418
  */
407
419
  onMissing?: 'throw' | 'execute';
408
420
  onResolved?: (step: ReplayStep, outcome: ReplayOutcome | undefined) => void;
409
- /**
410
- * Legacy matching mode, used only for a trace whose entries carry no `path`. `true` (default)
411
- * consumes entries positionally and raises a `TimeParadox` on divergence; `false` matches
412
- * per-Command FIFO queues, which used to be required for flows containing `Parallel`. Ignored
413
- * for a trace carrying paths, which is matched by path, and when a Resolver is supplied, since
414
- * that Resolver has already chosen how it matches.
415
- */
416
- strict?: boolean;
421
+ }
422
+
423
+ /**
424
+ * What a replay returns: the flow's own outcome and, for a trace, the recorded entries the flow
425
+ * never asked for. A flow that stops issuing Commands early mismatches nothing, so `result` can be a
426
+ * `Success` with steps left over; `unreached` is where that shows. It is absent for a Resolver,
427
+ * since only a trace knows what it holds.
428
+ */
429
+ export interface Replay<T, E = unknown> {
430
+ result: SuccessState<T> | FailureState<E>;
431
+ unreached: TraceEntry[];
417
432
  }
418
433
 
419
434
  /**
420
435
  * Pass a trace to replay it directly, or a Resolver when traces are stored in some other
421
436
  * shape. To observe a replay rather than change how it resolves, use `onResolved`.
422
437
  * A malformed trace rejects with a `ReplayError`.
438
+ *
439
+ * Three overloads: a trace yields `unreached`, a Resolver yields none, and a source only known
440
+ * as the union of the two (a wrapper forwarding whatever it was handed) yields it as optional.
423
441
  */
442
+ export declare function replayEffect<T, E = unknown, Ctx = unknown>(
443
+ effect: Effect<T, E, Ctx>,
444
+ trace: TraceLog | TraceEntry[],
445
+ options?: ReplayOptions<Ctx>
446
+ ): Promise<Replay<T, E>>;
447
+ export declare function replayEffect<T, E = unknown, Ctx = unknown>(
448
+ effect: Effect<T, E, Ctx>,
449
+ resolver: Resolver,
450
+ options?: ReplayOptions<Ctx>
451
+ ): Promise<Omit<Replay<T, E>, 'unreached'>>;
424
452
  export declare function replayEffect<T, E = unknown, Ctx = unknown>(
425
453
  effect: Effect<T, E, Ctx>,
426
454
  traceOrResolver: Resolver | TraceLog | TraceEntry[],
427
455
  options?: ReplayOptions<Ctx>
428
- ): Promise<SuccessState<T> | FailureState<E>>;
456
+ ): Promise<Omit<Replay<T, E>, 'unreached'> & { unreached?: TraceEntry[] }>;
429
457
 
430
458
  export declare function timeTravel<T, E = unknown, Ctx = unknown>(
431
459
  flowFn: (input: any) => Effect<T, E, Ctx>,
432
460
  traceLog: TraceLog,
433
- options?: { strict?: boolean; log?: (...args: any[]) => void; context?: Ctx; version?: string }
461
+ options?: { log?: (...args: any[]) => void; context?: Ctx; version?: string }
434
462
  ): Promise<SuccessState<T> | FailureState<E>>;