PackageNew ConceptReleasedArticle

New Package: Type-safe JSON migration tool with Zod validation

When you store JSON locally, the structure inevitably changes over time. New fields get added, old ones get renamed, formats evolve. Without a proper migration system you end up with scattered if statements checking for old formats, or worse, data that silently breaks when the shape changes underneath you.

We've been dealing with this ourselves across a few projects and figured it was time to build something small and focused to handle it properly.


Now Released: a type-safe JSON migration library for TypeScript - @nanocollective/json-up


The idea

Define a chain of versioned migrations, each with a Zod schema and a transform function. When you call migrate(), it reads the current version from your data, runs every migration after that version in order, and validates the result at each step. You get full TypeScript inference throughout the chain, so if your transform returns the wrong shape, you know at compile time rather than at runtime.

const migrations = createMigrations()
  .add({
    version: 1,
    schema: z.object({ name: z.string() }),
    up: (data) => ({ name: data.name ?? "Unknown" }),
  })
  .add({
    version: 2,
    schema: z.object({ firstName: z.string(), lastName: z.string() }),
    up: (data) => {
      const [firstName = "", lastName = ""] = data.name.split(" ");
      return { firstName, lastName };
    },
  })
  .build();

const result = migrate({
  state: { _version: 1, name: "Jane Doe" },
  migrations,
});
// { _version: 2, firstName: "Jane", lastName: "Doe" }

It handles the common patterns you would expect: renaming fields, adding defaults, restructuring nested objects, transforming arrays, and migrating from unversioned legacy data. There are three distinct error types (ValidationError, MigrationError, VersionError) so you can handle failures precisely rather than catching a generic error and guessing.

What it looks like in practice

  • Fluent builder API for chaining migration steps together
  • Zod validation at every step, not just the final output
  • Automatic version tracking via a configurable version key (defaults to _version)
  • Full TypeScript inference across the entire migration chain
  • Zero runtime dependencies - only Zod as a peer dependency
  • Works with Zod v3 and v4

The whole thing installs with:

npm install @nanocollective/json-up zod

[!TIP] If your data already uses a field like version or schemaVersion, you can pass a custom key option to migrate() instead of the default _version.

Documentation

We've written up proper docs covering the full API, error handling, and common migration patterns:

Community

We're a small community-led team building local and privacy-first AI solutions under the Nano Collective and would love your help! Whether you're interested in contributing code, documentation, or just being part of our community, there are several ways to get involved.

If you want to contribute to the code:

  • Read our detailed CONTRIBUTING.md guide for information on development setup, coding standards, and how to submit your changes.

If you want to be part of our community or help with other aspects like design or marketing:

  • Join our Discord server to connect with other users, ask questions, share ideas, and get help: Join our Discord server
  • Head to our GitHub issues or discussions to open and join current conversations with others in the community.

Want to join the discussion? Head over to GitHub to share your thoughts!

View Discussion on GitHub