All files / lib/validations package.ts

100% Statements 46/46
100% Branches 1/1
100% Functions 1/1
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x         1x           1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x         1x         1x 1x 1x 1x 1x 1x                   1x 6x 6x 6x 6x 6x 6x   6x 6x 6x 6x 6x 6x   6x 6x 6x  
import { z } from 'zod';
 
/**
 * Supported currencies
 */
export const currencyEnum = z.enum(['INR', 'USD', 'EUR', 'GBP']);
export type Currency = z.infer<typeof currencyEnum>;
 
/**
 * Create package schema
 */
export const createPackageSchema = z.object({
  title: z
    .string()
    .min(2, 'Title must be at least 2 characters')
    .max(100, 'Title must be at most 100 characters'),
  description: z
    .string()
    .max(500, 'Description must be at most 500 characters')
    .optional()
    .nullable(),
  price: z
    .number()
    .int('Price must be a whole number (in smallest currency unit)')
    .min(0, 'Price cannot be negative'),
  currency: currencyEnum.default('INR'),
  duration: z.string().max(50, 'Duration must be at most 50 characters').optional().nullable(),
  features: z.array(z.string().max(200)).max(10, 'Maximum 10 features allowed').default([]),
  is_active: z.boolean().default(true),
  is_featured: z.boolean().default(false),
  display_order: z.number().int().min(0).default(0),
});
 
/**
 * Update package schema (partial)
 */
export const updatePackageSchema = createPackageSchema.partial();
 
/**
 * Package with ID (for responses)
 */
export const packageSchema = createPackageSchema.extend({
  id: z.string().uuid(),
  profile_id: z.string().uuid(),
  created_at: z.string().datetime(),
  updated_at: z.string().datetime(),
});
 
// Type exports
export type CreatePackageInput = z.infer<typeof createPackageSchema>;
export type UpdatePackageInput = z.infer<typeof updatePackageSchema>;
export type Package = z.infer<typeof packageSchema>;
 
/**
 * Format price for display
 */
export function formatPrice(priceInSmallestUnit: number, currency: Currency): string {
  const divisors: Record<Currency, number> = {
    INR: 100, // paise to rupees
    USD: 100, // cents to dollars
    EUR: 100, // cents to euros
    GBP: 100, // pence to pounds
  };
 
  const symbols: Record<Currency, string> = {
    INR: '₹',
    USD: '$',
    EUR: '€',
    GBP: '£',
  };
 
  const amount = priceInSmallestUnit / divisors[currency];
  return `${symbols[currency]}${amount.toLocaleString('en-IN')}`;
}