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/CHANGELOG.md +148 -0
- package/README.md +132 -52
- package/index.d.ts +53 -25
- package/index.js +216 -131
- package/package.json +31 -3
- package/.prettierrc +0 -12
- package/CLAUDE.md +0 -202
- package/examples/opentelemetry-example.js +0 -164
- package/examples/recording-example.js +0 -104
- package/test/all.js +0 -2265
- package/test/types.test-d.ts +0 -268
- package/tsconfig.check.json +0 -12
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
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?:
|
|
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
|
-
/**
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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<
|
|
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?: {
|
|
461
|
+
options?: { log?: (...args: any[]) => void; context?: Ctx; version?: string }
|
|
434
462
|
): Promise<SuccessState<T> | FailureState<E>>;
|