Configuration

Transformations Example

Transform data during import with Zod

Basic Transformations

import { CSVImporter } from '@importcsv/react';
import { z } from 'zod';

const contactSchema = z.object({
  // Trim and normalize name
  name: z.string()
    .transform(s => s.trim())
    .transform(s => s.replace(/\s+/g, ' ')), // Remove extra spaces

  // Lowercase and trim email
  email: z.string()
    .email()
    .transform(s => s.trim().toLowerCase()),

  // Normalize phone number
  phone: z.string()
    .transform(s => s.replace(/[^0-9]/g, '')) // Remove non-digits
    .transform(s => s.length === 10 ? `+1${s}` : s) // Add country code
    .optional(),

  // Uppercase country code
  country: z.string()
    .transform(s => s.toUpperCase())
    .default('US'),

  // Parse date string
  created_at: z.string()
    .transform(s => new Date(s))
    .optional()
});

type Contact = z.infer<typeof contactSchema>;

export default function ContactImporter() {
  return (
    <CSVImporter
      schema={contactSchema}
      onComplete={(contacts: Contact[]) => {
        // All data is transformed and typed
        console.log(contacts[0].email); // "john@example.com" (lowercased)
        console.log(contacts[0].phone); // "+15550100" (normalized)
      }}
    />
  );
}

Common Transformation Patterns

Currency to Number

const schema = z.object({
  price: z.string()
    .transform(s => s.replace(/[$,]/g, '')) // Remove $ and commas
    .transform(s => parseFloat(s))
});

Date Parsing

const schema = z.object({
  // ISO date strings
  iso_date: z.string().datetime(),

  // Custom date format
  custom_date: z.string()
    .transform(s => {
      // Parse "MM/DD/YYYY" format
      const [month, day, year] = s.split('/');
      return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
    })
});

Enum Mapping

const statusMap = {
  'active': 'ACTIVE',
  'inactive': 'INACTIVE',
  'pending': 'PENDING'
} as const;

const schema = z.object({
  status: z.string()
    .transform(s => s.toLowerCase())
    .transform(s => statusMap[s as keyof typeof statusMap] || 'UNKNOWN')
});

Conditional Transformations

const schema = z.object({
  email: z.string()
    .email()
    .transform(s => {
      // Add default domain if missing
      return s.includes('@') ? s : `${s}@company.com`;
    })
});

Sample CSV

Name,Email,Phone,Country,Created At
  John Doe  ,JOHN@EXAMPLE.COM,(555) 010-0100,us,2024-01-15
Jane Smith  ,jane@EXAMPLE.COM,555-010-0101,US,2024-02-01

After Transformation

[
  {
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+15550100100",
    "country": "US",
    "created_at": "2024-01-15T00:00:00.000Z"
  }
]

Next Steps