npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

runzod

v2.2.0

Published

Codemod to migrate from runtypes to zod

Downloads

29

Readme

runzod

A codemod to migrate from runtypes to zod.

Features

  • Transforms imports/requires from runtypes to zod
  • Converts type definitions to zod schemas
  • Updates validation methods (check → parse, guard → safeParse)
  • Converts Static to z.infer
  • Works with TypeScript files
  • Preserves code style and formatting

Installation

pnpm dlx runzod <path-to-your-code>

Usage

runzod <directory> [options]

Options

  • --dry: Do not write to files, just show what would be changed
  • --extensions: File extensions to process (default: ts,tsx)
  • --help, -h: Show help message
  • --verbose, -v: Show more information during processing

Examples

# Transform all TypeScript files in the src directory
pnpm dlx runzod ./src

# Dry run to see what would be changed
pnpm dlx runzod ./src --dry

# Transform only specific file extensions
pnpm dlx runzod ./src --extensions ts,tsx

# Show verbose output
pnpm dlx runzod ./src -v

Transformations

| Runtypes | Zod | | ----------------------------------- | ----------------------------------- | | import { String } from 'runtypes' | import { z } from 'zod' | | String | z.string() | | Number | z.number() | | Boolean | z.boolean() | | BigInt | z.bigint() | | Undefined | z.undefined() | | Null | z.null() | | Array(String) | z.array(z.string()) | | Tuple(String, Number) | z.tuple([z.string(), z.number()]) | | Object({...}) | z.object({...}) | | Record(String, Number) | z.record(z.string(), z.number()) | | Union(A, B, C) | z.union([A, B, C]) | | Intersect(A, B) | z.intersection([A, B]) | | Literal(x) | z.literal(x) | | Optional(String) | z.string().optional() | | String.optional() | z.string().optional() | | String.withConstraint(...) | z.string().refine(...) | | String.withBrand("Brand") | z.string().brand("Brand") | | Type.check(data) | Type.parse(data) | | Type.guard(data) | Type.safeParse(data) | | Static<typeof Type> | z.infer<typeof Type> |

Examples

Basic Usage

// Before (runtypes)
import { String, Number, Boolean, Array, Object, type Static } from "runtypes";

const User = Object({
  name: String,
  age: Number,
  isActive: Boolean,
  tags: Array(String),
});

type User = Static<typeof User>;

if (User.guard(data)) {
  console.log(`User ${data.name} is ${data.age} years old`);
}

// After (zod)
import { z } from "zod";

const User = z.object({
  name: z.string(),
  age: z.number(),
  isActive: z.boolean(),
  tags: z.array(z.string()),
});

type User = z.infer<typeof User>;

const result = User.safeParse(data);
if (result.success) {
  console.log(`User ${result.data.name} is ${result.data.age} years old`);
}

Branded Types

// Before (runtypes)
import { String, withBrand, type Static } from "runtypes";

const UserId = String.withBrand("UserId");
type UserId = Static<typeof UserId>;

// After (zod)
import { z } from "zod";

const UserId = z.string().brand("UserId");
type UserId = z.infer<typeof UserId>;

Limitations

The codemod handles most common cases, but there are some limitations:

  • Complex constraints may need manual adjustment
  • The match pattern from runtypes needs manual conversion to zod patterns
  • Recursive types may require adjustments
  • Some method chaining might require manual fixes
  • Branded type handling might require additional changes

Post-Migration Steps

After running the codemod:

  1. Add "zod" to your dependencies if it's not already there
  2. Review the transformed files manually
  3. Update validation logic based on zod's patterns:
    • runtype.guard(data) becomes schema.safeParse(data) (but you'll need to access result.data when success is true)
    • Error handling differs between libraries
  4. Run your tests to ensure everything still works

Development

# Install dependencies
npm install

# Build the project
npm run build

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Test on example files
npm run test:codemod

License

MIT