JSPM

@bernierllc/csv-validator

0.1.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 18
  • Score
    100M100P100Q66585F
  • License ISC

Atomic CSV validation utilities with type checking and custom rules

Package Exports

  • @bernierllc/csv-validator
  • @bernierllc/csv-validator/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bernierllc/csv-validator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@bernierllc/csv-validator

Atomic CSV validation utilities with type checking and custom rules.

Features

  • Type Validation: Validate data against common types (string, number, email, phone, URL, date, boolean, select)
  • Custom Validators: Create custom validation functions for complex business rules
  • Business Rules: Define cross-field validation rules with priority
  • Error Analysis: Get detailed statistics and suggestions for bulk fixes
  • Type Conversion: Convert string values to appropriate types
  • Zero Dependencies: Pure TypeScript with no external dependencies

Installation

npm install @bernierllc/csv-validator

Quick Start

import { validateImportData, validators, ValidationField } from '@bernierllc/csv-validator';

// Define your validation fields
const fields: ValidationField[] = [
  {
    key: 'name',
    label: 'Name',
    type: 'string',
    required: true
  },
  {
    key: 'email',
    label: 'Email',
    type: 'email',
    required: false
  },
  {
    key: 'age',
    label: 'Age',
    type: 'integer',
    required: false,
    validation: { min: 0, max: 120 }
  }
];

// Validate your data
const rows = [
  { name: 'John Doe', email: 'john@example.com', age: '30' },
  { name: '', email: 'invalid-email', age: '150' }
];

const validatedRows = validateImportData(rows, fields);

console.log(validatedRows[0].isValid); // true
console.log(validatedRows[1].isValid); // false
console.log(validatedRows[1].errors); // Array of validation errors

API Reference

Core Functions

validateImportData(rows, fields, customValidators?, businessRules?)

Validates an array of data rows against field definitions.

const validatedRows = validateImportData(
  transformedRows,
  fields,
  customValidators,
  businessRules
);

validateField(value, type, validation?, rowData?)

Validates a single field value.

const result = validateField('test@example.com', 'email');
// { isValid: true }

validateRequired(value)

Checks if a required field has a value.

const result = validateRequired('');
// { isValid: false, error: 'This field is required' }

Field Types

  • string - Text validation with optional length constraints
  • number - Numeric validation with optional min/max
  • integer - Whole number validation
  • boolean - Boolean value validation (true/false, yes/no, 1/0)
  • email - Email format validation
  • phone - Phone number validation
  • url - URL format validation
  • date - Date validation with optional format
  • select - Enum value validation
  • multiselect - Multiple enum values
  • custom - Custom validation function

Validation Rules

const validation = {
  min: 1,                    // Minimum value/length
  max: 100,                  // Maximum value/length
  pattern: '^[A-Z]+$',       // Regex pattern
  enum: ['A', 'B', 'C'],     // Allowed values
  dateFormat: 'YYYY-MM-DD',  // Date format
  custom: (value, row) => ({ // Custom validation
    isValid: value.length > 0,
    error: 'Custom error message'
  })
};

Custom Validators

const customValidators: CustomValidator[] = [
  {
    name: 'nameLength',
    fields: ['name'],
    validate: (data) => ({
      isValid: data.name.length >= 3,
      error: 'Name must be at least 3 characters'
    })
  }
];

Business Rules

const businessRules: BusinessRule[] = [
  {
    name: 'adultEmail',
    description: 'Adults must have email',
    fields: ['age', 'email'],
    validate: (data) => ({
      isValid: data.age < 18 || data.email,
      error: 'Adults must provide an email address'
    }),
    priority: 1
  }
];

Error Analysis

getValidationStats(rows)

Get comprehensive validation statistics.

const stats = getValidationStats(validatedRows);
// {
//   total: 100,
//   valid: 85,
//   invalid: 15,
//   errorBreakdown: { required: 5, format: 10 },
//   commonErrors: [...]
// }

groupErrorsByField(rows)

Group errors by field name.

const grouped = groupErrorsByField(validatedRows);
// { name: [...], email: [...], age: [...] }

suggestBulkFixes(rows)

Get suggestions for bulk error fixes.

const suggestions = suggestBulkFixes(validatedRows);
// [
//   {
//     field: 'email',
//     error: 'Invalid email format',
//     suggestion: 'user@example.com',
//     affectedRows: [1, 2, 3],
//     confidence: 85
//   }
// ]

Type Conversion

convertFieldValue(value, type)

Convert string values to appropriate types.

convertFieldValue('123', 'number');     // 123
convertFieldValue('true', 'boolean');   // true
convertFieldValue('a,b,c', 'multiselect'); // ['a', 'b', 'c']

Built-in Validators

Email Validator

validators.email('test@example.com'); // { isValid: true }
validators.email('invalid'); // { isValid: false, error: 'Invalid email format', suggestion: 'invalid@example.com' }

Phone Validator

validators.phone('1234567890'); // { isValid: true, suggestion: '(123) 456-7890' }
validators.phone('123'); // { isValid: false, error: 'Phone number must be 10 or 11 digits' }

URL Validator

validators.url('https://example.com'); // { isValid: true }
validators.url('example.com'); // { isValid: true }
validators.url('not-a-url'); // { isValid: false, error: 'Invalid URL format', suggestion: 'https://not-a-url' }

Number Validator

validators.number('123.45'); // { isValid: true }
validators.number('123.45', { min: 100 }); // { isValid: false, error: 'Must be at least 100' }

Date Validator

validators.date('2023-01-01'); // { isValid: true }
validators.date('2023-01-01', { dateFormat: 'YYYY-MM-DD' }); // { isValid: true }
validators.date('invalid'); // { isValid: false, error: 'Invalid date format' }

Error Types

  • required - Missing required field
  • format - Invalid format (email, phone, URL, date)
  • type - Invalid data type
  • range - Value outside allowed range
  • enum - Value not in allowed list
  • custom - Custom validation failed
  • business - Business rule violation

Examples

Basic Validation

import { validateImportData, ValidationField } from '@bernierllc/csv-validator';

const fields: ValidationField[] = [
  { key: 'name', label: 'Name', type: 'string', required: true },
  { key: 'email', label: 'Email', type: 'email', required: false },
  { key: 'age', label: 'Age', type: 'integer', required: false, validation: { min: 0, max: 120 } }
];

const data = [
  { name: 'John', email: 'john@example.com', age: '30' },
  { name: '', email: 'invalid', age: '150' }
];

const results = validateImportData(data, fields);

Custom Validation

const customValidators = [
  {
    name: 'uniqueEmail',
    fields: ['email'],
    validate: (data) => {
      // Check if email is unique in database
      const isUnique = checkEmailUnique(data.email);
      return {
        isValid: isUnique,
        error: isUnique ? undefined : 'Email already exists'
      };
    }
  }
];

const results = validateImportData(data, fields, customValidators);

Business Rules

const businessRules = [
  {
    name: 'adultConsent',
    description: 'Adults must provide consent',
    fields: ['age', 'consent'],
    validate: (data) => ({
      isValid: data.age < 18 || data.consent === 'yes',
      error: 'Adults must provide consent'
    }),
    priority: 1
  }
];

const results = validateImportData(data, fields, undefined, businessRules);

Error Analysis

import { getValidationStats, suggestBulkFixes } from '@bernierllc/csv-validator';

const stats = getValidationStats(results);
console.log(`Valid: ${stats.valid}/${stats.total}`);

const suggestions = suggestBulkFixes(results);
suggestions.forEach(suggestion => {
  console.log(`Fix ${suggestion.field}: ${suggestion.suggestion} (${suggestion.confidence}% confidence)`);
});

License

ISC - See LICENSE file for details.

Contributing

This package is part of the Bernier LLC tools suite. Please refer to the main repository for contribution guidelines.