- Typed chain. Each evolution gets the type of the previous version’s value. You don’t write types for the middle steps.
- Forward-only. Every evolution is a pure
(prev) => nextfunction. There are no reverse migrations and no side effects. - Never throws.
runreturns a result object, so the compiler makes you handle data that is newer than your build, a bad version number, or an evolution that failed. - Storage-agnostic. You pass the stored version in as an argument. datavolve never reads or writes storage.
- Tiny. 258 B, zero dependencies, ESM only.
import { datavolve } from "datavolve"
const settings = datavolve()
.add(1, (raw) => ({ theme: "light" }))
.add(2, (v1) => ({ ...v1, fontScale: 1 }))
.add(3, (v2) => ({ ...v2, theme: v2.theme === "light" ? "day" : "night" }))
const result = settings.run(storedValue, storedVersion)
if (result.success) {
save({ version: result.version, value: result.value })
}
The full API and guides for checking untrusted input are at datavolve.psdcoder.dev.
