phantom-zod
v1.7.4
Published
TypeScript-first schema validation library built on Zod
Downloads
46
Readme
© 2025 Dave Carty. Licensed under the ISC License.
Phantom Zod
A TypeScript-first schema validation library built on top of Zod, providing pre-built validators for common data types with comprehensive error handling and customizable messages.
Table of Contents
- Features
- Installation
- Quick Start
- String Parameter Overloads
- Using the
pzNamespace - Object Schema Construction
- Complete Example
- Available Schemas
- Localization Support
- Error Message Customization
- Phone Number Formats
- Advanced Usage
- TypeScript Support
- Testing
- Contributing
- License
- Changelog
Features
- 🚀 Unified
pznamespace - Access all schemas from a single import - 🎯 TypeScript-first - Built with TypeScript for full type safety
- 🌐 Localization support - Multi-language error messages
- 📝 Custom error messages - Flexible message customization
- ⚡ Performance optimized - Built on Zod with additional optimizations
- 🧪 Comprehensive testing - 1300+ test cases covering edge cases
- 📚 Complete schema library - Validation for all common data types
Installation
npm install phantom-zod
# or
yarn add phantom-zod
# or
pnpm add phantom-zodQuick Start
import { pz } from "phantom-zod";
// Simple validation with options object
const email = pz.EmailRequired({ msg: "Email" });
const result = email.parse("[email protected]"); // ✅ '[email protected]'
// Or use the simplified string parameter overload
const emailSimple = pz.EmailRequired("Email");
const resultSimple = emailSimple.parse("[email protected]"); // ✅ '[email protected]'
// ✨ NEW: Chainable .default() support!
const emailWithDefault = pz.EmailRequired("Email").default("[email protected]");
const defaultResult = emailWithDefault.parse(undefined); // ✅ '[email protected]'String Parameter Overloads
Phantom Zod v1.5+ supports simplified string parameter usage for most schemas. Instead of always passing an options object, you can pass a string directly as the field name for basic validation:
Basic Usage
import { pz } from "phantom-zod";
// Traditional options object approach
const emailTraditional = pz.EmailRequired({ msg: "Email Address" });
// Simplified string parameter approach (equivalent)
const emailSimple = pz.EmailRequired("Email Address");
// Both produce the same validation behavior
emailTraditional.parse("[email protected]"); // ✅ '[email protected]'
emailSimple.parse("[email protected]"); // ✅ '[email protected]'
// Error messages work the same way
emailTraditional.parse(""); // ❌ "Email Address is required"
emailSimple.parse(""); // ❌ "Email Address is required"When to Use Each Approach
Use string parameters when:
- You only need to set the field name/message
- You want cleaner, more concise code
- You're building simple validation schemas
Use options objects when:
- You need additional configuration (minLength, maxLength, format, etc.)
- You want to use custom message types (MsgType.Message)
- You need locale-specific configurations
Examples by Schema Type
import { pz } from "phantom-zod";
// String schemas
const name = pz.StringRequired("Full Name"); // Simple
const bio = pz.StringOptional({ msg: "Bio", maxLength: 500 }); // With constraints
// Email schemas
const email = pz.EmailRequired("Email"); // Simple
const workEmail = pz.Html5EmailRequired("Work Email"); // Simple
// UUID schemas
const userId = pz.UuidV7Required("User ID"); // Simple
const sessionId = pz.UuidRequired("Session ID"); // Simple
// Number schemas
const count = pz.NumberRequired("Count"); // Simple
const age = pz.NumberRequired({ msg: "Age", min: 0, max: 120 }); // With constraints
// Boolean schemas
const isActive = pz.BooleanRequired("Active Status"); // Simple
// Date schemas
const birthDate = pz.DateStringRequired("Birth Date"); // Simple
const timestamp = pz.DateTimeStringOptional("Timestamp"); // Simple
// Complex schemas that support string overloads
const address = pz.AddressOptional("Home Address"); // Simple
const phone = pz.PhoneRequired("Phone Number"); // Simple (uses default E.164 format)
// Record schemas
const settings = pz.RecordOptional(z.string(), "User Settings"); // Simple
const counters = pz.RecordRequired(z.number(), "Counters"); // Simple
// When you need format options, use the options object
const phoneNational = pz.PhoneRequired({
msg: "Phone Number",
format: PhoneFormat.National
});
// When you need record constraints, use the options object
const restrictedConfig = pz.RecordRequired(z.string(), {
msg: "Configuration",
allowedKeys: ["host", "port", "timeout"],
requiredKeys: ["host", "port"],
});Backwards Compatibility
The string parameter overloads are fully backwards compatible. All existing code using options objects will continue to work exactly as before. The string overloads are additional convenience methods that complement the existing API.
🔗 Native Zod Chaining Support
Phantom Zod v1.6+ provides dual-mode validation combining the best of both worlds:
- Options-based API - Our stable, proven approach with unified options across all schemas
- Native Zod Chaining - Direct access to Zod's chainable methods for enhanced flexibility
Two Ways to Build Schemas
1. Options-Based Approach (Recommended)
import { pz } from "phantom-zod";
// ✅ Consistent, reliable API across all schema types
const userSchema = z.object({
name: pz.StringRequired({ msg: "Full Name", minLength: 2, maxLength: 50 }),
email: pz.EmailRequired("Email Address"),
age: pz.NumberRequired({ msg: "Age", min: 0, max: 120 }),
website: pz.UrlOptional("Website"),
phone: pz.PhoneOptional({ msg: "Phone", format: PhoneFormat.National }),
isActive: pz.BooleanRequired("Active Status"),
});2. Native Zod Chaining (Power Users)
import { pz } from "phantom-zod";
// ✨ NEW: Direct Zod chaining support for String and Number schemas
const userSchema = z.object({
name: pz.StringRequired().min(2).max(50).default("Anonymous"),
age: pz.NumberRequired().min(0).max(120).default(18),
score: pz.IntegerRequired().min(0).max(100),
balance: pz.PositiveRequired().max(1000000),
description: pz.StringOptional().default(""),
});Native Chaining Features
String Schema Chaining
// StringRequired supports full chaining
const name = pz.StringRequired()
.min(2) // Minimum length
.max(50) // Maximum length
.trim() // Automatic trimming
.default("Anonymous"); // Default value
// StringOptional supports .default() only
const bio = pz.StringOptional().default("");Number Schema Chaining
// NumberRequired supports full chaining
const age = pz.NumberRequired()
.min(0) // Minimum value
.max(120) // Maximum value
.default(18); // Default value
// Specialized schemas with native methods
const score = pz.IntegerRequired().min(0).max(100); // .int() applied
const price = pz.PositiveRequired().max(1000000); // .positive() applied
const temp = pz.NonNegativeRequired().max(100); // .nonnegative() applied
// NumberOptional supports .default() only
const rating = pz.NumberOptional().default(0);⚠️ Zod Chaining Limitations & Solutions
Problem: Optional Schemas Break Zod Chaining
// ❌ This doesn't work - Zod's .optional() removes chaining methods
const schema = pz.StringOptional();
schema.min(5); // ❌ TypeScript Error: Property 'min' does not exist
const numSchema = pz.NumberOptional();
numSchema.max(100); // ❌ TypeScript Error: Property 'max' does not existRoot Cause: Zod's .optional() method fundamentally changes the schema type, removing all type-specific methods like .min(), .max(), .trim(), etc.
✅ Solution: Use Our Options-Based API
// ✅ Our options API overcomes Zod's limitation
const optionalString = pz.StringOptional({
msg: "Bio",
minLength: 5,
maxLength: 500
}); // Works perfectly!
const optionalNumber = pz.NumberOptional({
msg: "Score",
min: 0,
max: 100
}); // Works perfectly!
// ✅ Alternative: Use .default() for optional behavior
const stringWithDefault = pz.StringRequired().min(5).max(500).default("");
const numberWithDefault = pz.NumberRequired().min(0).max(100).default(0);When to Use Each Approach
| Use Options-Based When: | Use Native Chaining When: | |------------------------|----------------------------| | ✅ Building optional schemas with constraints | ✅ Building required schemas only | | ✅ Need consistent API across all schema types | ✅ Want direct Zod ecosystem integration | | ✅ Complex schemas (Email, URL, Phone) | ✅ Simple string/number validation | | ✅ Custom error messages | ✅ Leveraging existing Zod knowledge | | ✅ Team consistency and maintainability | ✅ Maximum performance |
Hybrid Approach (Best Practice)
import { z } from "zod";
import { pz } from "phantom-zod";
const userSchema = z.object({
// Use chaining for simple required fields
name: pz.StringRequired().min(2).max(50),
age: pz.NumberRequired().min(0).max(120),
// Use options for optional fields with constraints
bio: pz.StringOptional({ msg: "Bio", maxLength: 500 }),
score: pz.NumberOptional({ msg: "Score", min: 0, max: 100 }),
// Use options for complex schemas
email: pz.EmailRequired("Email Address"),
phone: pz.PhoneOptional({ msg: "Phone", format: PhoneFormat.National }),
website: pz.UrlOptional("Website"),
});Backward Compatibility
All existing code continues to work unchanged. The native chaining is an additive enhancement that doesn't break any existing functionality.
// ✅ All existing code still works
const legacySchema = pz.StringRequired({ msg: "Name", minLength: 2 });
const modernSchema = pz.StringRequired().min(2); // New optionUsing the pz Namespace
Phantom Zod provides all schemas through a unified pz namespace, making it easy to access any validation schema from a single import:
import { pz } from "phantom-zod";
// String validation with trimming
const name = pz.StringRequired("Full Name");
name.parse(" John Doe "); // ✅ 'John Doe'
// Email validation
const email = pz.EmailRequired("Email Address");
email.parse("[email protected]"); // ✅ '[email protected]'
// Phone validation (E.164 format default)
const phone = pz.PhoneOptional("Phone Number");
phone.parse("(555) 123-4567"); // ✅ '+15551234567' (E.164 format)
// UUID validation (supports v4, v6, v7)
const id = pz.UuidV7Required("User ID");
id.parse("018f6d6e-f14d-7c2a-b732-c6d5730303e0"); // ✅ Valid UUIDv7
// Number validation with constraints
const age = pz.NumberRequired({ msg: "Age", min: 0, max: 120 });
age.parse(25); // ✅ 25
// URL validation
const website = pz.UrlOptional("Website");
website.parse("https://example.com"); // ✅ 'https://example.com'
// Date validation
const birthDate = pz.DateStringOptional("Birth Date");
birthDate.parse("1990-01-15"); // ✅ '1990-01-15'
// Boolean validation
const isActive = pz.BooleanRequired("Active Status");
isActive.parse(true); // ✅ true
// Array validation
const tags = pz.StringArrayOptional("Tags");
tags.parse(["javascript", "typescript", "react"]); // ✅ ['javascript', 'typescript', 'react']
// Money validation with currency (requires options object)
const price = pz.MoneyRequired({ msg: "Price", currency: "USD" });
price.parse({ amount: 99.99, currency: "USD" }); // ✅ Valid money objectObject Schema Construction
The real power of Phantom Zod comes when building complex object schemas using the pz namespace with Zod's object construction:
import { z } from "zod";
import { pz } from "phantom-zod";
// User profile schema
const userProfileSchema = z.object({
// Personal information
id: pz.UuidV7Required("User ID"),
email: pz.EmailRequired("Email Address"),
firstName: pz.StringRequired("First Name"),
lastName: pz.StringRequired("Last Name"),
displayName: pz.StringOptional("Display Name"),
// Contact information
phone: pz.PhoneOptional("Phone Number"),
website: pz.UrlOptional("Personal Website"),
// Profile details
age: pz.NumberOptional({ msg: "Age", min: 13, max: 120 }),
isActive: pz.BooleanRequired("Account Status"),
role: pz.EnumRequired(["admin", "user", "moderator"], "User Role"),
tags: pz.StringArrayOptional("Profile Tags"),
// Address
address: pz.AddressOptional("Home Address"),
// Timestamps
createdAt: pz.DateStringRequired("Created Date"),
lastLoginAt: pz.DateTimeStringOptional("Last Login"),
});
// Product schema with money handling
const productSchema = z.object({
id: pz.UuidRequired("Product ID"),
name: pz.StringRequired({
msg: "Product Name",
minLength: 2,
maxLength: 100,
}),
description: pz.StringOptional({ msg: "Description", maxLength: 500 }),
price: pz.MoneyRequired("Price"),
category: pz.EnumRequired(["electronics", "clothing", "books"], "Category"),
tags: pz.StringArrayOptional({ msg: "Product Tags", maxItems: 10 }),
isAvailable: pz.BooleanRequired("Availability"),
website: pz.UrlOptional("Product URL"),
});Complete Example
Here's a comprehensive example showing schema definition, validation, and error handling:
import { z } from "zod";
import { pz } from "phantom-zod";
// Define a comprehensive user registration schema
const userRegistrationSchema = z.object({
// Required fields
email: pz.EmailRequired({ msg: "Email Address" }),
password: pz.StringRequired({ msg: "Password", minLength: 8 }),
firstName: pz.StringRequired({ msg: "First Name" }),
lastName: pz.StringRequired({ msg: "Last Name" }),
// Optional fields
phone: pz.PhoneOptional({ msg: "Phone Number" }),
website: pz.UrlOptional({ msg: "Personal Website" }),
age: pz.NumberOptional({ msg: "Age", min: 13, max: 120 }),
// Complex fields
interests: pz.StringArrayOptional({ msg: "Interests" }),
address: z
.object({
street: pz.StringRequired({ msg: "Street Address" }),
city: pz.StringRequired({ msg: "City" }),
state: pz.StringRequired({ msg: "State", minLength: 2, maxLength: 2 }),
zipCode: pz.PostalCodeRequired({ msg: "ZIP Code" }),
})
.optional(),
// Preferences
newsletter: pz.BooleanRequired({ msg: "Newsletter Subscription" }),
accountType: pz.EnumRequired(["personal", "business"], {
msg: "Account Type",
}),
});
// Type inference
type UserRegistration = z.infer<typeof userRegistrationSchema>;
// Example data
const registrationData = {
email: " [email protected] ", // Will be trimmed
password: "securePassword123",
firstName: "John",
lastName: "Doe",
phone: "(555) 123-4567", // Will be normalized to +15551234567
website: "https://johndoe.com",
age: 25,
interests: ["programming", "reading", "hiking"],
address: {
street: "123 Main St",
city: "New York",
state: "NY",
zipCode: "10001",
},
newsletter: true,
accountType: "personal" as const,
};
// Validation with error handling
try {
const validatedUser = userRegistrationSchema.parse(registrationData);
console.log("Validation successful:", validatedUser);
// The result will have:
// - Trimmed email: '[email protected]'
// - Normalized phone: '+15551234567'
// - All other data validated and type-safe
} catch (error) {
if (error instanceof z.ZodError) {
console.log("Validation errors:");
error.issues.forEach((issue) => {
console.log(`- ${issue.path.join(".")}: ${issue.message}`);
});
}
}
// Safe parsing (doesn't throw)
const result = userRegistrationSchema.safeParse(registrationData);
if (result.success) {
console.log("User data:", result.data);
} else {
console.log("Validation failed:", result.error.issues);
}
// Example with invalid data
const invalidData = {
email: "not-an-email", // Invalid email
password: "123", // Too short
firstName: "", // Empty string
lastName: "Doe",
age: 150, // Too high
phone: "invalid-phone", // Invalid phone
website: "not-a-url", // Invalid URL
accountType: "invalid-type", // Invalid enum value
newsletter: "yes", // Should be boolean
};
const invalidResult = userRegistrationSchema.safeParse(invalidData);
console.log("Validation errors for invalid data:");
invalidResult.error?.issues.forEach((issue) => {
console.log(`- ${issue.path.join(".")}: ${issue.message}`);
});
// Output will show specific, helpful error messages:
// - email: Email Address must be a valid email address
// - password: Password must be at least 8 characters
// - firstName: First Name is required
// - age: Age must be at most 120
// - phone: Phone Number must be a valid phone number
// - website: Personal Website must be a valid URL
// - accountType: Account Type must be one of: personal, business
// - newsletter: Newsletter Subscription must be a booleanAvailable Schemas
Phantom Zod provides a comprehensive set of validation schemas accessible through the pz namespace:
📝 String Schemas
pz.StringRequired({ msg, minLength, maxLength })- Required string with trimmingpz.StringOptional({ msg, minLength, maxLength })- Optional string with trimming
📚 View detailed String schemas documentation →
📧 Email Schemas
pz.EmailRequired({ msg })- Required email validationpz.EmailOptional({ msg })- Optional email validationpz.Html5EmailRequired({ msg })- HTML5-compliant email validationpz.Rfc5322EmailRequired({ msg })- RFC 5322-compliant email validationpz.UnicodeEmailRequired({ msg })- Unicode-friendly email validation
📚 View detailed Email schemas documentation →
📱 Phone Schemas
pz.PhoneRequired({ msg, format })- Required phone number (E.164/National)pz.PhoneOptional({ msg, format })- Optional phone number
📚 View detailed Phone schemas documentation →
🆔 UUID Schemas
pz.UuidRequired({ msg })- Any UUID versionpz.UuidOptional({ msg })- Optional UUIDpz.UuidV4Required({ msg })- Specific UUIDv4pz.UuidV6Required({ msg })- Specific UUIDv6pz.UuidV7Required({ msg })- Specific UUIDv7pz.NanoidRequired({ msg })- Nanoid validation
📚 View detailed UUID schemas documentation →
🔢 Number Schemas
pz.NumberRequired({ msg, min, max })- Required number with constraintspz.NumberOptional({ msg, min, max })- Optional numberpz.IntegerRequired({ msg, min, max })- Integer validationpz.PositiveRequired({ msg })- Positive numbers onlypz.NonNegativeRequired({ msg })- Non-negative numbers
📚 View detailed Number schemas documentation →
🗓️ Date Schemas
pz.DateRequired({ msg })- Date object validationpz.DateOptional({ msg })- Optional date objectpz.DateStringRequired({ msg })- ISO date string (YYYY-MM-DD)pz.DateStringOptional({ msg })- Optional ISO date stringpz.DateTimeStringRequired({ msg })- ISO datetime stringpz.TimeStringRequired({ msg })- ISO time string (HH:MM:SS)pz.TimezoneDateTimeRequired({ msg })- NEW Strict timezone-aware datetimepz.TimezoneDateTimeOptional({ msg })- NEW Optional timezone-aware datetime
📚 View detailed Date schemas documentation →
✅ Boolean Schemas
pz.BooleanRequired({ msg })- Required booleanpz.BooleanOptional({ msg })- Optional booleanpz.BooleanStringRequired({ msg })- Boolean as string ("true"/"false")
📚 View detailed Boolean schemas documentation →
📋 Array Schemas
pz.StringArrayRequired({ msg, minItems, maxItems })- Required string arraypz.StringArrayOptional({ msg, minItems, maxItems })- Optional string array
📚 View detailed Array schemas documentation →
🔗 URL Schemas
pz.UrlRequired({ msg, protocol, hostname })- Required URL validationpz.UrlOptional({ msg, protocol, hostname })- Optional URL validationpz.HttpsUrlRequired({ msg })- HTTPS-only URLspz.WebUrlRequired({ msg })- HTTP/HTTPS URLs
📚 View detailed URL schemas documentation →
🏠 Address Schemas
pz.AddressRequired({ msg })- Complete address validationpz.AddressOptional({ msg })- Optional addresspz.AddressUS({ msg })- US-specific address validationpz.PostalCodeRequired({ msg })- US ZIP code validation
📚 View detailed Address schemas documentation → | Postal Code schemas →
💰 Money Schemas
pz.MoneyRequired({ msg, currency, decimalPlaces })- Money object validationpz.MoneyOptional({ msg, currency, decimalPlaces })- Optional moneypz.CurrencyCode({ msg })- ISO 4217 currency codespz.MoneyAmount({ msg, decimalPlaces })- Money amount validation
📚 View detailed Money schemas documentation →
🌐 Network Schemas
pz.IPv4Required({ msg })- IPv4 address validationpz.IPv6Required({ msg })- IPv6 address validationpz.MacAddressRequired({ msg })- MAC address validationpz.NetworkAddressGeneric({ msg })- Any network address type
📚 View detailed Network schemas documentation →
👤 User Schemas
pz.UserRequired({ msg })- Complete user objectpz.UserOptional({ msg })- Optional user objectpz.Username({ msg, minLength, maxLength })- Username validationpz.Password({ msg, minLength, requirements })- Password validationpz.UserRegistration({ msg })- User registration schema
📚 View detailed User schemas documentation →
📁 File Upload Schemas
pz.FileUploadRequired({ msg, maxSize, allowedTypes })- File validationpz.FileUploadOptional({ msg, maxSize, allowedTypes })- Optional filepz.ImageUpload({ msg, maxSize })- Image-specific validationpz.DocumentUpload({ msg, maxSize })- Document validation
📚 View detailed File Upload schemas documentation →
🏷️ Enum Schemas
pz.EnumRequired(values, { msg })- Required enum validationpz.EnumOptional(values, { msg })- Optional enum validation
📚 View detailed Enum schemas documentation →
🆔 ID List Schemas
pz.IdListRequired({ msg, minItems, maxItems })- UUID list validationpz.UniqueIdList({ msg })- Unique ID list validationpz.MongoIdRequired({ msg })- MongoDB ObjectId validation
📚 View detailed ID List schemas documentation →
📊 Record Schemas
pz.RecordRequired(valueSchema, { msg, minEntries, maxEntries, allowedKeys, requiredKeys, keyPattern })- Required key-value record validationpz.RecordOptional(valueSchema, { msg, minEntries, maxEntries, allowedKeys, requiredKeys, keyPattern })- Optional key-value record validation
📚 View detailed Record schemas documentation →
Error Message Customization
All schemas support two types of error messages:
Field Name (Default)
The message is treated as a field name and incorporated into standard error messages.
const schema = pz.EmailRequired({ msg: "Email Address" });
schema.parse(""); // "Email Address is required"
schema.parse("invalid"); // "Email Address must be a valid email address"Custom Message
Use MsgType.Message to provide complete custom error messages.
import { pz, MsgType } from "phantom-zod";
const schema = pz.EmailRequired({
msg: "Please enter a valid email address",
msgType: MsgType.Message,
});
schema.parse("invalid"); // "Please enter a valid email address"Phone Number Formats
The library supports two phone number formats:
E.164 Format (Default)
International format with country code: +11234567890
import { pz, PhoneFormat } from "phantom-zod";
const schema = pz.PhoneOptional({ msg: "Phone", format: PhoneFormat.E164 });
// or simply:
const schema = pz.PhoneOptional({ msg: "Phone" }); // E.164 is defaultNational Format
US national format without country code: 1234567890
import { pz, PhoneFormat } from "phantom-zod";
const schema = pz.PhoneOptional({ msg: "Phone", format: PhoneFormat.National });Advanced Usage
Form Validation
import { z } from "zod";
import { pz } from "phantom-zod";
const userSchema = z.object({
name: pz.StringRequired({ msg: "Full Name" }),
email: pz.EmailRequired({ msg: "Email Address" }),
phone: pz.PhoneOptional({ msg: "Phone Number" }),
company: pz.StringOptional({ msg: "Company Name" }),
});
type User = z.infer<typeof userSchema>;
const userData = {
name: " John Doe ",
email: "[email protected]",
phone: "(555) 123-4567",
company: undefined,
};
const result = userSchema.parse(userData);
// Result:
// {
// name: 'John Doe',
// email: '[email protected]',
// phone: '+15551234567',
// company: ''
// }Error Handling
import { ZodError } from "zod";
import { pz } from "phantom-zod";
const schema = pz.EmailRequired({ msg: "Email" });
try {
schema.parse("invalid-email");
} catch (error) {
if (error instanceof ZodError) {
console.log(error.issues[0].message); // "Email must be a valid email address"
}
}TypeScript Support
The library is built with TypeScript and provides full type safety:
import { z } from "zod";
import { pz } from "phantom-zod";
const emailSchema = pz.EmailRequired({ msg: "Email" });
const phoneSchema = pz.PhoneOptional({ msg: "Phone" });
type Email = z.infer<typeof emailSchema>; // string
type Phone = z.infer<typeof phoneSchema>; // string | undefinedTesting
The library includes comprehensive tests with 190+ test cases covering:
- ✅ Valid input scenarios
- ❌ Invalid input scenarios
- 🔄 Data transformation
- 📱 Phone number normalization
- 🌐 Unicode support
- ⚡ Performance testing
- 🧠 Memory safety
Run tests:
npm test
npm run test:coverage
npm run test:watchContributing
We welcome contributions! Please see our Contributing Guide for detailed information on:
- Development workflow and branch protection
- Code standards and testing requirements
- Pull request process
- Architecture overview and development tips
Quick Start for Contributors
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make changes and add tests
- Format code:
npm run format - Run tests:
npm test - Submit a pull request
The main branch is protected and requires pull requests for all changes.
License
ISC License - see LICENSE file for details.
Changelog
Version 1.5.0 (Current Feature Branch)
- 🚀 Universal String Parameter Overloads: Comprehensive string parameter support across all schema types
- Direct string parameter usage for all schemas:
pz.EmailRequired("Email") - Extended beyond basic schemas to include complex types (Address, Money, Network, etc.)
- Backwards compatible with existing options object approach
- Cleaner, more concise schema definitions for rapid development
- Direct string parameter usage for all schemas:
- 🌍 NEW: Strict Timezone-Aware DateTime Schemas: Enhanced datetime validation with timezone enforcement
pz.TimezoneDateTimeRequired()- Enforces timezone presence in ISO 8601 datetime stringspz.TimezoneDateTimeOptional()- Optional timezone-aware datetime validation- Rejects naive datetime strings and Date objects, accepts only timezone-aware ISO strings
- Perfect for multi-timezone applications, audit trails, API contracts, and compliance requirements
- Uses Zod's built-in
datetime({ offset: true })with custom localized error messages - Supports both UTC 'Z' notation and offset formats (±HH:MM)
- 📋 Enhanced Schema Coverage: String overloads added to:
- Address, Array, Boolean, Date, Email schemas
- Enum, File Upload, ID List, Money schemas
- Network, Number, Phone, Postal Code schemas
- String, URL, User, UUID schemas
- NEW: Timezone-aware datetime schemas with string parameter support
- 🧪 Expanded Test Suite: Comprehensive test coverage for all string parameter overloads and timezone schemas
- 📚 Updated Documentation: Examples and usage patterns updated throughout, including timezone schema guides
Version 1.4.0
- 📚 Comprehensive Schema Documentation: Complete documentation overhaul
- Individual schema documentation files for each category (18 total)
- Cross-linked documentation structure from main README
- Detailed examples, usage patterns, and best practices
- Form validation examples and real-world use cases
- 🏗️ Project Structure Enhancement: Added WARP.md with mandatory branching workflow
- 🔧 Development Workflow: Established feature branch requirements and CI/CD automation
- ✨ Documentation Quality: Professional-grade documentation ready for production use
Version 1.3.0
- 🔧 Developer Experience Improvements: Enhanced TypeScript integration and IntelliSense support
- ⚡ Performance Optimizations: Improved schema creation and validation performance
- 🐛 Bug Fixes: Resolved edge cases in phone number validation and locale handling
- 📖 Documentation Updates: Improved API documentation and usage examples
- 🎯 Type Safety: Enhanced TypeScript definitions for better compile-time checking
Version 1.2.1
- 🐛 Critical Bug Fixes: Resolved issues with localization message loading
- 🔧 Build Improvements: Enhanced build process for better distribution
- 📦 Dependency Updates: Updated to latest compatible versions
Version 1.2.0
- 🎯 Schema Refinements: Enhanced validation logic for complex data types
- 🌍 Localization Enhancements: Additional locale support and improved message formatting
- 🔒 Type Safety Improvements: Stricter TypeScript definitions and better error handling
- 🧪 Test Suite Expansion: Added comprehensive edge case testing and validation scenarios
- 🏗️ Architecture Improvements: Refined factory patterns for better maintainability
Version 1.1.0
- 🌐 Localization Support: Added comprehensive internationalization system
- Multi-language error message support
- Dynamic locale switching with fallback handling
- Type-safe message parameter injection
- Extensible locale system for custom languages
- 📋 Extended Schema Library: Added comprehensive validation schemas
- Date, Number, UUID, Boolean, Enum schemas
- Array, URL, Postal Code, Address schemas
- Money, Network (IP/MAC), User credential schemas
- File upload and Pagination schemas
- 🏗️ Enhanced Architecture: Improved factory pattern for schema creation
- 📚 Comprehensive Documentation: Updated with localization examples and new schema usage
- 🧪 Extended Test Coverage: Added 1000+ tests for localization and new schemas
Version 1.0.0
- 🎉 Initial Release: Foundation of Phantom Zod validation library
- 📧 Email Validation: Comprehensive email validation schemas with multiple formats
- 📱 Phone Number Support: Validation with E.164 and national formats
- 📝 String Validation: Automatic trimming and length constraints
- 🧪 Comprehensive Testing: 190+ test cases covering all scenarios
- 🔷 TypeScript Support: Full type safety and inference
- 🛠️ Utility Functions: Common operations and helper functions
