datavolve

  • 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) => next function. There are no reverse migrations and no side effects.
  • Never throws. run returns 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.

Explore more open source projects