pure-effect 0.18.0 → 0.20.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.
Files changed (5) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +678 -306
  3. package/index.d.ts +82 -22
  4. package/index.js +625 -48
  5. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to pure-effect are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and from 1.0.0 the project follows [Semantic Versioning](https://semver.org/). Before 1.0.0 a minor version could change behaviour; each such change is marked below.
4
4
 
5
+ ## [0.20.0] - 2026-10-13
6
+
7
+ ### Changed
8
+
9
+ - **Breaking: `recordEffect` takes the flow already called with its input, as `runEffect` and `replayEffect` do.** Write `recordEffect(checkoutFlow(input), options)` where you wrote `recordEffect(checkoutFlow, input, options)`. The trace still holds the input of a flow `effectPipe` or `effectGen` built, so `timeTravel` builds the flow again from it, and a flow built some other way records none, as it does when recorded in production. A call written the old way is refused as a flow passed without its input. In TypeScript the trace's `initialInput` is now `unknown`, as it is in a trace read back from storage.
10
+ - **Breaking: `Retry`'s `attempts` option is renamed `retries`, and so is the exhaustion's field.** It always counted the tries after the first, so `retries: 2` makes at most three calls, which the old name hid. `attempts` is refused as an option `Retry` does not have, as the flow is built, and `onExhausted` receives `{ retryExhausted, lastError, retries }`.
11
+ - **Breaking: `timeTravel` returns `{ result, unreached }`, as `replayEffect` does for a trace,** rather than the outcome alone, so a test can check the steps it narrated as never reached.
12
+ - **Running a generator flow again builds it again from its input, as calling an `async` function again does.** A `Retry` around a generator flow repeated its first Command as the first attempt built it and built the rest again, so a value the body made, such as an ID or the time, was one value in the first Command and another in the next: a retried reservation and charge could go out under two different IDs. One flow value run twice, or put in two branches of a `Parallel`, mixed its runs the same way. Each `Retry` attempt, each run and each branch now builds the flow afresh, so every Command in it gets the same values, and the first takes over the body that ran as the flow was built, so a single run still runs the body once. A flow a test walked before running it is built afresh too. Getting such a value from a Command is still the way to replay it.
13
+ - **A long loop in a generator flow no longer holds every earlier result.** Each step kept the answers before it, so the body could be run again, and a loop over 2,000 pages of 10,000 items held about 160 MB at its last page. Now that running a flow again builds it again, a run keeps only the answer it is on, as a pipeline does; a body a test walks keeps its answers, as walking a second branch needs them. An `onBeforeCommand` hook that answers the Command it was handed, by calling its `next`, now makes the run reject with an `EffectTypeError` when the interpreter reaches that step's answer, since the run keeps no earlier answers to run the body again with.
14
+ - **TypeScript: a step's `type` is `'Command' | 'Parallel'`, a `Parallel`'s `options` are always present, and `timeTravel`'s options are the named `TimeTravelOptions`.** An `onStep` hook and a `Resolver` can switch on the step's type, and a hook that declares it a plain `string` still fits.
15
+
16
+ ## [0.19.0] - 2026-10-11
17
+
18
+ ### Added
19
+
20
+ - **Flows can be written as generator functions.** `effectGen(function* (input) { ... })` builds a flow function from a generator that writes `yield* step(effect)` where `async` code writes `await`, so `if`s and `for` loops wrap steps as they wrap `await`. A plain return value is the flow's `Success`, a returned `Failure` stops it, and a returned Effect runs. The flow is made of the same nodes a pipeline is, so it records, replays, retries and runs in a `Parallel` as one does, and a recorded trace of a generator flow matches its pipeline's. When a step stops the flow, the body's `catch` and `finally` blocks run; a `catch` that recovers or throws another error, or a `finally` that runs a step, rejects the run. `step` throws an `EffectTypeError` when it is used other than with `yield*`, and so do the other common mistakes: a missing star, a yielded Promise, and an `async function*`. TypeScript infers each step's value, the error union and the context from the body.
21
+ - **A `Parallel` in which a branch threw records `threw: true` in its decision.** An `onStep` hook sees it in what `op` returns, and a replay of such a trace stops no generator flow, as production did not; a trace recorded without it replays as before.
22
+ - **`Ask()` with no argument reads the context.** It succeeds with the context itself, so a generator flow reads it with `yield* step(Ask())`, and TypeScript names its type with `Ask<AppContext>()`. `Ask(undefined)` still throws, since an explicit `undefined` is usually a misspelt name.
23
+
5
24
  ## [0.18.0] - 2026-10-09
6
25
 
7
26
  ### Changed
@@ -261,6 +280,8 @@ All notable changes to pure-effect are recorded here. The format follows [Keep a
261
280
 
262
281
  - Initial release: `Success`, `Failure`, `Command`, `effectPipe`, and `runEffect`.
263
282
 
283
+ [0.20.0]: https://github.com/aycangulez/pure-effect/compare/v0.19.0...v0.20.0
284
+ [0.19.0]: https://github.com/aycangulez/pure-effect/compare/v0.18.0...v0.19.0
264
285
  [0.18.0]: https://github.com/aycangulez/pure-effect/compare/v0.17.0...v0.18.0
265
286
  [0.17.0]: https://github.com/aycangulez/pure-effect/compare/v0.16.0...v0.17.0
266
287
  [0.16.0]: https://github.com/aycangulez/pure-effect/compare/v0.15.0...v0.16.0