Builder Validation API
The validation system ensures DDEX XML output complies with schema requirements, business rules, and partner specifications before generation.
Validation Classes
DDEXValidator
Main validation engine for DDEX Builder:
class DDEXValidator {
  constructor(options?: ValidationOptions);
  validate(data: any, version?: string): ValidationResult;
  validateAsync(data: any, version?: string): Promise<ValidationResult>;
  addCustomRule(rule: ValidationRule): void;
  removeCustomRule(ruleName: string): boolean;
  getAvailableRules(): ValidationRule[];
}
ValidationOptions
Configuration for the validation engine:
interface ValidationOptions {
  strictMode?: boolean;           // Strict schema compliance
  allowPartnerExtensions?: boolean; // Allow partner-specific extensions
  customRules?: ValidationRule[];   // Custom validation rules
  skipOptionalFields?: boolean;     // Skip validation of optional fields
  maxErrors?: number;              // Maximum errors before stopping
  enableWarnings?: boolean;        // Include warnings in results
}
Validation Rules
Built-in Rules
The validator includes comprehensive built-in rules:
enum BuiltInRules {
  // Schema validation
  SCHEMA_COMPLIANCE = 'schemaCompliance',
  REQUIRED_FIELDS = 'requiredFields',
  DATA_TYPES = 'dataTypes',
  
  // Business logic
  UNIQUE_IDENTIFIERS = 'uniqueIdentifiers',
  REFERENCE_INTEGRITY = 'referenceIntegrity',
  DATE_CONSISTENCY = 'dateConsistency',
  
  // Format validation
  ISRC_FORMAT = 'isrcFormat',
  UPC_FORMAT = 'upcFormat',
  PARTY_IDENTIFIERS = 'partyIdentifiers',
  
  // Technical requirements
  DURATION_FORMAT = 'durationFormat',
  TERRITORY_CODES = 'territoryCodes',
  LANGUAGE_CODES = 'languageCodes'
}
Custom Validation Rules
Create custom rules for specific business requirements:
interface ValidationRule {
  name: string;
  description: string;
  severity: 'error' | 'warning' | 'info';
  validate: (data: any, context: ValidationContext) => ValidationError[];
}
// Example custom rule
const customISRCRule: ValidationRule = {
  name: 'customISRCValidation',
  description: 'Validates ISRC format for our catalog',
  severity: 'error',
  validate: (data, context) => {
    const errors: ValidationError[] = [];
    
    data.resources?.soundRecordings?.forEach((recording, index) => {
      const isrc = recording.soundRecordingId?.isrc;
      if (isrc && !isrc.match(/^[A-Z]{2}[A-Z0-9]{3}\d{7}$/)) {
        errors.push({
          path: `resources.soundRecordings[${index}].soundRecordingId.isrc`,
          message: 'ISRC must follow format: CC-XXX-YY-NNNNN',
          code: 'INVALID_ISRC_FORMAT',
          severity: 'error',
          value: isrc
        });
      }
    });
    
    return errors;
  }
};
Validation Results
ValidationResult
Complete validation outcome:
interface ValidationResult {
  isValid: boolean;
  errors: ValidationError[];
  warnings: ValidationError[];
  info: ValidationError[];
  summary: ValidationSummary;
  metadata: ValidationMetadata;
}
ValidationError
Individual validation issue:
interface ValidationError {
  path: string;           // JSON path to the invalid field
  message: string;        // Human-readable error message
  code: string;          // Machine-readable error code
  severity: 'error' | 'warning' | 'info';
  value?: any;           // The invalid value
  expectedType?: string; // Expected data type
  suggestions?: string[]; // Possible fixes
}
ValidationSummary
High-level validation statistics:
interface ValidationSummary {
  totalChecks: number;
  errorCount: number;
  warningCount: number;
  infoCount: number;
  rulesCoverage: number;  // Percentage of rules that ran
  validationTime: number; // Time taken in milliseconds
}
Usage Examples
Basic Validation
import { DdexBuilder, DDEXValidator } from 'ddex-builder';
const validator = new DDEXValidator({
  strictMode: true,
  enableWarnings: true
});
const releaseData = {
  releaseId: 'R123456789',
  title: 'Example Album',
  // ... other release data
};
const result = validator.validate(releaseData, '4.3');
if (!result.isValid) {
  console.error(`Validation failed with ${result.errors.length} errors:`);
  result.errors.forEach(error => {
    console.error(`- ${error.path}: ${error.message}`);
  });
} else {
  console.log('Validation passed!');
}
Async Validation with Custom Rules
const validator = new DDEXValidator();
// Add custom rules
validator.addCustomRule(customISRCRule);
validator.addCustomRule(labelCodeValidationRule);
// Validate asynchronously
const result = await validator.validateAsync(releaseData, '4.3');
// Process results
if (result.warnings.length > 0) {
  console.warn('Validation warnings:');
  result.warnings.forEach(warning => {
    console.warn(`- ${warning.path}: ${warning.message}`);
  });
}
Integration with Builder
const builder = new DdexBuilder({
  validation: {
    enabled: true,
    strictMode: false,
    customRules: [customISRCRule],
    maxErrors: 50
  }
});
try {
  // Builder automatically validates before building
  const xml = await builder.build(releaseData);
  console.log('Build successful!');
} catch (error) {
  if (error.validationErrors) {
    console.error('Validation errors prevented build:');
    error.validationErrors.forEach(err => {
      console.error(`- ${err.path}: ${err.message}`);
    });
  }
}
Partner-Specific Validation
Preset Validation Rules
import { DDEXValidator, PartnerPresets } from 'ddex-builder';
// Use Spotify-specific validation
const spotifyValidator = new DDEXValidator({
  preset: PartnerPresets.SPOTIFY,
  strictMode: true
});
// Custom partner validation
const customPartnerRules = {
  maxTrackCount: 500,
  requiredArtworkDimensions: { width: 1400, height: 1400 },
  requiredPreviewClips: true,
  allowedTerritories: ['US', 'CA', 'MX']
};
const partnerValidator = new DDEXValidator({
  customRules: createPartnerRules(customPartnerRules)
});
Multi-Partner Validation
const multiValidator = new DDEXValidator();
// Validate against multiple partner requirements
const partners = ['spotify', 'apple', 'youtube'];
const results = {};
for (const partner of partners) {
  const preset = PartnerPresets[partner.toUpperCase()];
  const validator = new DDEXValidator({ preset });
  results[partner] = validator.validate(releaseData);
}
// Find common issues
const commonErrors = findCommonValidationIssues(results);
console.log('Issues affecting multiple partners:', commonErrors);
Performance Optimization
Validation Caching
const validator = new DDEXValidator({
  cache: {
    enabled: true,
    maxSize: 1000,    // Cache up to 1000 validation results
    ttl: 3600000      // 1 hour cache lifetime
  }
});
// Subsequent validations of identical data will use cache
const result1 = validator.validate(releaseData);
const result2 = validator.validate(releaseData); // Uses cache
Selective Validation
// Only validate specific sections
const partialResult = validator.validate(releaseData, '4.3', {
  sections: ['releases', 'resources'],
  skipRules: ['territoryValidation', 'dealValidation']
});
// Validate only changed fields
const incrementalResult = validator.validateIncremental(
  originalData,
  changedData,
  changedPaths
);
Error Recovery
Validation with Auto-Fix
const validator = new DDEXValidator({
  autoFix: {
    enabled: true,
    maxFixes: 10,
    allowedFixes: [
      'trimWhitespace',
      'formatDates', 
      'normalizeIdentifiers'
    ]
  }
});
const result = validator.validate(releaseData);
if (result.autoFixed) {
  console.log(`Auto-fixed ${result.autoFixed.length} issues:`);
  result.autoFixed.forEach(fix => {
    console.log(`- ${fix.path}: ${fix.description}`);
  });
}
Graceful Degradation
const validator = new DDEXValidator({
  errorHandling: {
    strategy: 'continue',    // Continue validation after errors
    maxErrors: 100,          // Stop after 100 errors
    reportPartialResults: true
  }
});
const result = validator.validate(problematicData);
// Even with errors, get partial validation results
if (result.partialResults) {
  console.log(`Validated ${result.partialResults.coverage}% of data`);
}
See Also
- Builder API Reference - Main builder documentation
- TypeScript API - TypeScript-specific validation
- Python API - Python validation examples
- Error Handling Guide - Error handling strategies