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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lollipop-onl/myzod-to-zod

v1.2.0

Published

A codemod to migrate from myzod to zod v3

Readme

myzod-to-zod

Open in StackBlitz

npm version Tests

A codemod to automatically migrate your codebase from myzod to zod v3.

This tool uses AST transformations to safely and accurately convert myzod validation schemas to their zod v3 equivalents, achieving 100% automated conversion for supported patterns.

✨ Features

  • 🔄 100% Test Coverage: All transformation patterns tested and verified
  • 🛡️ AST-based: Safe transformations that preserve code structure and comments
  • High Success Rate: Converts common myzod patterns automatically
  • 🎯 Precise: Only transforms myzod-related code, leaves everything else untouched
  • 📚 Well Documented: Comprehensive guide for manual migration steps

🚀 Quick Start

Interactive CLI (Recommended)

npx @lollipop-onl/myzod-to-zod

Non-interactive CLI

# Preview changes (dry run)
npx @lollipop-onl/myzod-to-zod "src/**/*.ts"

# Apply transformations
npx @lollipop-onl/myzod-to-zod "src/**/*.ts" --write

Install as Package

npm install -D @lollipop-onl/myzod-to-zod

📖 Example

Before (myzod)

import myzod from 'myzod';

const userSchema = myzod.object({
  name: myzod.string().min(1).max(50),
  email: myzod.string().pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
  age: myzod.number().min(0).max(150).optional(),
  isActive: myzod.boolean().default(true),
});

// Complex transformations
const statusSchema = myzod.literals('active', 'inactive', 'pending');
const coerceSchema = myzod.number().coerce();
const validatedSchema = myzod.string().withPredicate(
  s => s.length > 0,
  'String must not be empty'
);

// Schema shape access
const userShape = userSchema.shape();

// Type inference
type User = myzod.Infer<typeof userSchema>;
type Status = myzod.Infer<typeof statusSchema>;

After (zod v3)

import { z } from 'zod';

const userSchema = z.object({
  name: z.string().min(1).max(50),
  email: z.string().regex(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
  age: z.number().min(0).max(150).optional(),
  isActive: z.boolean().default(true),
});

// Complex transformations
const statusSchema = z.union([z.literal("active"), z.literal("inactive"), z.literal("pending")]);
const coerceSchema = z.coerce.number();
const validatedSchema = z.string().refine(
  s => s.length > 0,
  'String must not be empty'
);

// Schema shape access
const userShape = userSchema.shape;

// Type inference
type User = z.infer<typeof userSchema>;
type Status = z.infer<typeof statusSchema>;

🔄 Transformation Coverage

✅ Fully Automated

Basic Types

  • myzod.string()z.string()
  • myzod.number()z.number()
  • myzod.boolean()z.boolean()
  • myzod.literal()z.literal()
  • myzod.object()z.object()
  • myzod.array()z.array()
  • myzod.union()z.union()
  • myzod.tuple()z.tuple()
  • myzod.record()z.record()
  • myzod.dictionary()z.record() (with automatic .optional() handling)

Constraints & Validation

  • .min() / .max().min() / .max()
  • .pattern().regex()
  • .default().default()
  • .optional().optional()
  • .nullable().nullable()
  • Array length constraints

Advanced Transformations

  • .withPredicate().refine() (Custom validation)
  • .map().transform() (Value transformation)
  • .check().safeParse().success (Boolean validation)
  • .shape().shape (Schema shape access)
  • .partial().partial() (Object partial types)
  • .collectErrors()removed (zod collects errors by default)
  • myzod.number().coerce()z.coerce.number() (Structural change)
  • myzod.intersection()z.intersection() (Intersection types)
  • myzod.literals('a', 'b')z.union([z.literal('a'), z.literal('b')]) (Complex expansion)
  • myzod.enum(Color)z.nativeEnum(Color) (TypeScript enums)

Type System

  • myzod.Infer<typeof T>z.infer<typeof T> (Type inference)

🔧 Manual Migration Required

While this codemod handles 100% of schema definition patterns automatically, error handling requires manual attention:

1. ValidationError Imports

⚠️ Manual Change Required

// Before
import myzod, { ValidationError } from 'myzod';

// After (manual fix needed)
import { z } from 'zod';
// Remove ValidationError import entirely

Why: zod uses a different error handling pattern that doesn't require importing error types.

2. Error Handling Patterns

⚠️ Manual Change Required

// Before
const result = schema.try(data);
if (result instanceof myzod.ValidationError) {
  // Handle error
}

// After (manual fix needed)  
const result = schema.safeParse(data);
if (!result.success) {
  // Handle error with result.error
}

Why: myzod and zod have fundamentally different error handling APIs.

3. Object Property Handling Differences

⚠️ Manual Change Required

// myzod (rejects unknown properties by default)
const schema = myzod.object({
  name: myzod.string()
});
// schema.parse({name: "John", extra: "value"}) -> ValidationError

// Equivalent strict behavior in zod
const schema = z.object({
  name: z.string()
}).strict();
// schema.parse({name: "John", extra: "value"}) -> ZodError

// zod default behavior (strips unknown properties)
const schema = z.object({
  name: z.string()
});
// schema.parse({name: "John", extra: "value"}) -> {name: "John"}

// myzod.allowUnknownKeys() equivalent in zod (passes through unknown properties)
const schema = z.object({
  name: z.string()
}).passthrough();
// schema.parse({name: "John", extra: "value"}) -> {name: "John", extra: "value"}

Why:

  • myzod default: Rejects unknown properties (strict)
  • zod default: Strips unknown properties (lenient)
  • Migration impact: Objects with extra properties will behave differently

Solution:

  • Use z.object().strict() instead of z.object() to match myzod's default behavior
  • Or use z.object().passthrough() for myzod's .allowUnknownKeys() behavior

📖 For detailed error handling migration patterns and examples, see our Error Handling Migration Guide - ValidationError and .try() patterns

📋 Post-Migration Checklist

After running the codemod, please:

  1. Remove ValidationError Imports: Remove { ValidationError } from import statements
  2. Review Error Handling: Update .try() calls to .safeParse() and instanceof checks
  3. Test Thoroughly: Run your test suite to catch any behavioral differences
  4. Update Dependencies: Remove myzod and ensure zod v3 is installed

🛠️ Installation & Setup

Prerequisites

  • Node.js 18+
  • TypeScript project
  • myzod schemas in your codebase

Steps

  1. Backup your code (recommended)
  2. Install zod v3 in your project:
    npm install zod@3
  3. Run the codemod:
    npx @lollipop-onl/myzod-to-zod "src/**/*.ts" --write
  4. Follow the manual migration steps above
  5. Remove myzod:
    npm uninstall myzod
  6. Test thoroughly

🐛 Troubleshooting

Common Issues

"SyntaxError: Unexpected token"

  • Ensure your TypeScript files are valid before running the codemod
  • Check that file paths are correctly specified

"No files found"

  • Use quotes around glob patterns: "src/**/*.ts"
  • Verify the path patterns match your project structure

"Some transformations missing"

  • Check the manual migration section above
  • Report missing patterns as GitHub issues

"Type errors after migration"

  • Review error handling patterns (.try().safeParse())
  • Ensure zod v3 is properly installed
  • Check for any remaining myzod imports

Getting Help

  1. Check the manual migration guide above
  2. Review the troubleshooting section
  3. Open an issue with a minimal reproduction

🧪 Development

Running Tests

npm test                    # Run all tests
npm run test:watch         # Watch mode
npm run typecheck          # Type checking

Building

npm run build              # Build the codemod

Project Structure

myzod-to-zod/
├── src/                   # Main implementation
│   ├── index.ts          # CLI entry point
│   ├── migrate.ts        # AST transformation logic
│   ├── collect-imports.ts # Import analysis
│   └── myzod-node.ts     # AST utilities
├── test/                 # Test suite
│   ├── scenarios.ts      # Main test file
│   └── __scenarios__/    # 45 test cases with README
└── docs/                 # Developer documentation
    ├── implementation-guide.md           # AST architecture guide
    ├── api-transformation-reference.md   # Complete transformation patterns
    ├── library-comparison-reference.md   # Performance comparison & migration rationale
    └── error-handling-migration.md       # ValidationError & try() migration guide

📚 Resources

🤝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new transformation patterns
  4. Ensure all tests pass
  5. Submit a pull request

Adding New Transformations

  1. Add test cases in test/__scenarios__/
  2. Implement transformation in src/migrate.ts
  3. Update documentation
  4. Follow TDD principles

📄 License

MIT License. See LICENSE for details.

🙏 Acknowledgments

  • Inspired by zod-v3-to-v4
  • Built with ts-morph for safe AST transformations
  • Thanks to the myzod and zod communities

Need help? Open an issue or check our troubleshooting guide.