type-compiler
Version:
A TypeScript compiler plugin for enhanced runtime type checking and analysis with Zod validation
324 lines (287 loc) • 9.83 kB
text/typescript
/**
* Example code demonstrating the use of special field validators
*/
import { z } from 'zod';
import {
User,
Location,
Server,
Contact,
Order,
OrderItem,
Product,
WebsiteConfig,
LoginCredentials,
PasswordReset,
GeoPoint,
// New types with pattern-based field validators
EcommerceProduct,
ProductDimensions,
UserActivity,
Transaction,
Theme,
AnalyticsData,
ShippingOrder
} from './types';
// Import the automatically generated Zod schemas
// In a real application, these would be generated by the type-compiler
// For this example, we're importing them as if they were generated
import {
zUser,
zLocation,
zServer,
zContact,
zOrder,
zOrderItem,
zProduct,
zWebsiteConfig,
zLoginCredentials,
zPasswordReset,
zGeoPoint,
// New schemas
zEcommerceProduct,
zProductDimensions,
zUserActivity,
zTransaction,
zTheme,
zAnalyticsData,
zShippingOrder
} from './schemas';
// Example data
const validUser: User = {
uuid: '123e4567-e89b-12d3-a456-426614174000',
username: 'johndoe',
email: 'john.doe@example.com',
password: 'P@ssw0rd!',
birthDate: '1990-01-01',
age: 33,
profileUrl: 'https://example.com/users/johndoe',
phoneNumber: '+12125551234',
createdAt: new Date()
};
const invalidUser = {
uuid: 'not-a-uuid',
username: 'a', // too short
email: 'not-an-email',
password: 'weak', // fails complexity requirements
birthDate: 'yesterday', // invalid date format
age: 200, // outside the allowed range
profileUrl: 'not-a-url',
phoneNumber: '123', // invalid phone number format
createdAt: 'now' // not a Date
};
const validLocation: Location = {
name: 'Central Park',
latitude: 40.7812,
longitude: -73.9665,
address: '59th to 110th St., New York, NY',
zipCode: '10022'
};
const validGeoPoint: GeoPoint = {
latitude: 40.7812,
longitude: -73.9665,
elevation: 100
};
// Function to validate data and print results
function validateAndPrint(schema: z.ZodType<any>, data: any, label: string): void {
console.log(`\n--- Validating ${label} ---`);
try {
const validated = schema.parse(data);
console.log('✅ Valid data:', JSON.stringify(validated, null, 2));
} catch (error) {
if (error instanceof z.ZodError) {
console.log('❌ Validation errors:');
error.errors.forEach(err => {
console.log(`- ${err.path.join('.')}: ${err.message}`);
});
} else {
console.error('Unexpected error:', error);
}
}
}
// Main function to demonstrate the validation
function main() {
console.log('=== Special Field Validators Example ===');
console.log('This example demonstrates how the type-compiler uses special field validators\n');
// Validate valid user
validateAndPrint(zUser, validUser, 'Valid User');
// Validate invalid user
validateAndPrint(zUser, invalidUser, 'Invalid User');
// Validate location with latitude/longitude
validateAndPrint(zLocation, validLocation, 'Valid Location');
// Validate GeoPoint - should use the same validators for latitude/longitude
validateAndPrint(zGeoPoint, validGeoPoint, 'Valid GeoPoint');
// Demonstrate multiple interfaces with the same special field
const contact: Contact = {
firstName: 'Jane',
lastName: 'Smith',
email: 'jane.smith@example.com',
phoneNumber: '+12125551234',
address: '123 Main St, New York, NY'
};
validateAndPrint(zContact, contact, 'Contact with email and phone');
// Login credentials with email and password
const credentials: LoginCredentials = {
email: 'user@example.com',
password: 'SecureP@ss123!'
};
validateAndPrint(zLoginCredentials, credentials, 'Login Credentials');
// Demonstrate more complex validation chains
const server: Server = {
hostname: 'api-server',
ipAddress: '192.168.1.1',
url: 'https://api.example.com',
port: 443,
lastChecked: new Date()
};
validateAndPrint(zServer, server, 'Server');
console.log('\n=== Pattern-Based Field Validation Examples ===');
console.log('These examples demonstrate how pattern-based field validators work\n');
// Demonstration of E-commerce product with various field patterns
const validProduct: EcommerceProduct = {
productId: 'prod-123',
sku: 'SKU-123-456',
name: 'Wireless Headphones',
description: 'Premium wireless headphones with noise cancellation',
basePrice: 99.99,
discountAmount: 20,
totalPrice: 79.99,
taxRate: 8.5,
stockCount: 42,
dimensions: {
width: 8.5,
height: 7.2,
depth: 3.1,
weight: 0.35,
sizeCategory: 'medium'
},
availableColors: ['black', 'white', 'blue'],
primaryColor: '#3366FF',
tags: ['electronics', 'audio', 'wireless'],
categories: ['headphones', 'accessories'],
isAvailable: true,
hasVariants: true,
productStatus: 'active',
createdAt: new Date(),
updatedAt: new Date()
};
validateAndPrint(zEcommerceProduct, validProduct, 'E-commerce Product (valid)');
// Invalid product demo
const invalidProduct = {
...validProduct,
basePrice: -10, // Invalid: negative price
taxRate: 120, // Invalid: rate > 100
stockCount: -5, // Invalid: negative count
primaryColor: 'blue', // Invalid: not a valid color format
dimensions: {
...validProduct.dimensions,
width: -1, // Invalid: negative dimension
},
productStatus: 'unknown', // Valid: string is accepted as fallback for enum
};
validateAndPrint(zEcommerceProduct, invalidProduct, 'E-commerce Product (invalid)');
// User activity with timestamps, counts, and booleans
const validActivity: UserActivity = {
activityId: 'act-123456',
userId: 'user-789',
sessionId: 'sess-456',
activityType: 'page_view',
startTime: new Date('2023-06-01T10:30:00Z'),
endTime: new Date('2023-06-01T10:35:00Z'),
loginDate: '2023-06-01', // String date that will be coerced
durationSeconds: 300,
completionRate: 85.5,
clickCount: 12,
pageViewCount: 7,
isCompleted: true,
canResume: false,
activityStatus: 'completed'
};
validateAndPrint(zUserActivity, validActivity, 'User Activity (valid)');
// Financial transaction with monetary values and rates
const validTransaction: Transaction = {
transactionId: 'tx-789012',
referenceCode: 'ref-12345',
amount: 250.75,
fee: 2.99,
totalAmount: 253.74,
interestRate: 4.5,
exchangeRate: 1.23,
transactionDate: new Date('2023-05-15'),
processedAt: new Date(),
shouldNotify: true,
transactionStatus: 'completed'
};
validateAndPrint(zTransaction, validTransaction, 'Financial Transaction (valid)');
// UI Theme with color validations
const validTheme: Theme = {
themeId: 'theme-dark',
name: 'Dark Mode',
primaryColor: '#121212',
secondaryColor: '#333333',
backgroundColor: '#000000',
textColor: '#FFFFFF',
accentColor: '#4285F4',
isDefault: false,
createdAt: new Date()
};
validateAndPrint(zTheme, validTheme, 'UI Theme (valid)');
// Analytics data with count and rate validations
const validAnalytics: AnalyticsData = {
metricId: 'metric-123',
pageId: 'page-home',
visitorCount: 5421,
conversionCount: 127,
bounceCount: 1834,
conversionRate: 2.34,
bounceRate: 33.8,
engagementRatio: 42.1,
recordedAt: new Date(),
periodStartDate: '2023-06-01',
periodEndDate: '2023-06-30',
isRealTime: false,
dataStatus: 'completed'
};
validateAndPrint(zAnalyticsData, validAnalytics, 'Analytics Data (valid)');
// Shipping order with status and dimension validations
const validOrder: ShippingOrder = {
orderId: 'order-123456',
trackingCode: 'track-789012',
shippingStatus: 'pending',
paymentStatus: 'completed',
orderStatus: 'processing',
shippingCost: 12.99,
packageWidth: 30,
packageHeight: 20,
packageLength: 40,
orderDate: new Date('2023-06-15'),
shipByDate: new Date('2023-06-18'),
deliveryTime: '2023-06-20T14:00:00Z',
isExpress: true,
hasInsurance: true,
items: ['item1', 'item2', 'item3']
};
validateAndPrint(zShippingOrder, validOrder, 'Shipping Order (valid)');
// Invalid dimension values
const invalidOrderDimensions = {
...validOrder,
packageWidth: -5, // Invalid: negative dimension
packageHeight: 0 // Invalid: zero dimension
};
validateAndPrint(zShippingOrder, invalidOrderDimensions, 'Shipping Order (invalid dimensions)');
console.log('\n=== Pattern Matching Summary ===');
console.log('The pattern-based field validators automatically applied appropriate validation rules based on field naming patterns:');
console.log('- Fields ending with "Id" or "Code" → string validation');
console.log('- Fields containing "price", "amount", "cost", etc. → monetary value validation');
console.log('- Fields ending with "Count" → positive integer validation');
console.log('- Fields matching dimension patterns (width, height, etc.) → positive number validation');
console.log('- Fields starting with "is", "has", "can", "should" → boolean validation');
console.log('- Fields ending with "Color" → color format validation');
console.log('- Fields ending with "Status" → enum validation with string fallback');
console.log('- Fields ending with "At", "Date", "Time" → date validation with coercion');
console.log('- Fields ending with "Percent", "Rate", "Ratio" → 0-100 range validation');
console.log('- Fields matching array patterns (tags, categories, etc.) → array validation');
console.log('\n=== Validation Complete ===');
}
// Run the main function
main();