The entire surface of datavolve: one factory, three builder members, and the result types they produce.
datavolve()
Creates an empty, immutable datavolve instance.
.add(version, evolve)
Appends an evolution and returns a new datavolve instance whose output type is inferred from evolve’s return value.
version- a positive integer, sequential from1. Adding a non-sequential version throws immediately (a build-time programmer error), which also protects you from silently misaligning stored data if an evolution is deleted.evolve-(prev) => next.previsunknownfor version1, and the previous evolution’s output type thereafter.
.run(data, fromVersion)
Runs the applicable evolutions. Total - it never throws; an evolution that itself throws is caught and reported. Returns an EvolveResult.
data: unknown- the stored value.fromVersion: number- the versiondatais currently at. Required.
.latestVersion
The highest version datavolve knows about. Use it to stamp data on write-back:
storage.setItem(
key,
JSON.stringify({ version: settings.latestVersion, value }),
);
Types
type EvolveResult<T> =
| { success: true; value: T; version: number } // version = the version `value` is now at (always latestVersion)
| { success: false; error: EvolveError };
type EvolveError =
| { code: "ahead"; fromVersion: number; latestVersion: number }
| { code: "malformed"; fromVersion: number }
| { code: "failed"; failedVersion: number; cause: unknown };
type Datavolve<T>; // the datavolve instance, generic over its latest output type
Version Behavior
fromVersion | Result |
|---|---|
=== latestVersion | success, value returned unchanged (no-op fast path) |
0 ≤ fromVersion < latestVersion | success, evolutions (fromVersion, latestVersion] applied in order |
> latestVersion | failure ahead |
< 0 or non-integer | failure malformed |
| an evolution throws | failure failed (with cause) |