This guide helps AI assistants understand and work with the zodown codebase effectively.
zodown is a runtime converter that enables developers to write Zod v4 schemas while maintaining compatibility with libraries that require Zod v3 (like @modelcontextprotocol/sdk). Zod 3 is available in the zod 4 package as zod/v3.
- Location:
src/zodown.ts - Purpose: Converts Zod v4 schemas to Zod v3 schemas at runtime
- Key features:
- Preserves all validations and refinements
- Handles circular references with WeakMap caching
- Maintains full type safety
DowngradeType<T>: Maps v4 types to v3 equivalentsInferDowngraded<T>: Helper for type inference- All type mappings preserve validation logic
pnpm test # Run tests in watch mode
pnpm test:run # Run tests once
pnpm test:coverage # Generate coverage reportpnpm build # Build for production
pnpm dev # Build in watch modepnpm lint # Check formatting
pnpm format # Fix formatting
pnpm typecheck # TypeScript type checkingWhen adding support for a new Zod type:
- Add type mapping in
DowngradeTypetype definition - Add conversion logic in the
downgrade()function - Handle any special validation rules or refinements
- Add comprehensive tests in
tests/zodown.test.ts
- Each Zod type should have multiple test cases
- Test both basic conversion and validation preservation
- Include edge cases and error scenarios
- Test type inference with TypeScript
- WeakMap caching prevents infinite recursion
- Lazy evaluation for recursive schemas
- Minimal overhead - only processes used schemas
The documentation site is built with Vue 3 and Vite:
- Location:
docs/ - Style: 1-bit retro terminal aesthetic
- Run locally:
pnpm docs:dev - Build:
pnpm docs:build
- Run tests:
pnpm test:run - Update version:
pnpm release - Bumpp will handle:
- Version bumping
- Changelog generation
- Git tagging
- NPM publishing
// In zodown.ts, find the appropriate type handler
if (s instanceof zod4.ZodString) {
// Add new validation handling here
if (check.kind === 'newValidation') {
result = result.newValidation(check.value, check.message)
}
}// Use console.warn for unknown types
console.warn(`Unknown Zod v4 type encountered: ${typeName}`)
// Fallback to z.unknown() for safety- WeakMap for Caching: Prevents memory leaks with circular references
- Recursive Downgrade: Handles nested schemas efficiently
- Type Preservation: Maintains TypeScript inference throughout
- Effect Handling: Special cases for refine, transform, preprocess
- Circular References: Handled via WeakMap caching
- Unknown Types: Falls back to
z.unknown()with warning - Type Inference: Use
InferDowngraded<T>helper
- Add unit tests for the specific type/feature
- Add integration tests with complex schemas
- Test type inference in TypeScript
- Check performance with large schemas
src/zodown.ts- Main converter implementationsrc/index.ts- Public API exportstests/zodown.test.ts- Comprehensive test suitetsup.config.ts- Build configurationvitest.config.ts- Test configuration
When contributing:
- Follow existing code patterns
- Add tests for new features
- Update this guide if needed
- Ensure all tests pass
- Run formatter before committing