CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-async-validator

Comprehensive asynchronous form validation library with flexible rule-based schemas and built-in validation types.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error reporting with field-specific errors, custom messages, and structured error objects.

Capabilities

Error Types

Core error interfaces and types for validation results.

interface ValidateError {
  message?: string;
  fieldValue?: Value;
  field?: string;
}

type ValidateFieldsError = Record<string, ValidateError[]>;

type ValidateCallback = (
  errors: ValidateError[] | null,
  fields: ValidateFieldsError | Values
) => void;

type SyncErrorType = Error | string;

Validation Error Object

Individual validation error containing details about what failed.

interface ValidateError {
  /** Error message describing what validation failed */
  message?: string;
  /** The actual value that failed validation */
  fieldValue?: Value;
  /** The field name that failed validation */
  field?: string;
}

Usage Example:

const schema = new Schema({
  name: { type: "string", required: true, min: 2 }
});

try {
  await schema.validate({ name: "A" });
} catch (error) {
  console.log(error.errors[0]);
  // Output: {
  //   message: "name must be at least 2 characters",
  //   fieldValue: "A",
  //   field: "name"
  // }
}

Field-Specific Errors

Organized error mapping for easy field-level error handling.

type ValidateFieldsError = Record<string, ValidateError[]>;

Usage Example:

const schema = new Schema({
  name: { type: "string", required: true },
  email: { type: "email", required: true },
  age: { type: "number", min: 0 }
});

try {
  await schema.validate({
    name: "",
    email: "invalid-email",
    age: -5
  });
} catch (error) {
  console.log(error.fields);
  // Output: {
  //   name: [{ message: "name is required", field: "name", fieldValue: "" }],
  //   email: [{ message: "email is not a valid email", field: "email", fieldValue: "invalid-email" }],
  //   age: [{ message: "age cannot be less than 0", field: "age", fieldValue: -5 }]
  // }
  
  // Access specific field errors
  const nameErrors = error.fields.name;
  const emailErrors = error.fields.email;
}

Callback-Based Error Handling

Traditional callback pattern for handling validation results.

type ValidateCallback = (
  errors: ValidateError[] | null,
  fields: ValidateFieldsError | Values
) => void;

Usage Examples:

// Success case
schema.validate(validData, (errors, fields) => {
  if (errors) {
    // Validation failed
    console.log("Validation errors:", errors);
    console.log("Field errors:", fields);
  } else {
    // Validation passed - fields contains validated data
    console.log("Validation passed:", fields);
  }
});

// Error case
schema.validate(invalidData, (errors, fields) => {
  if (errors) {
    // Handle each error
    errors.forEach(error => {
      console.log(`Field ${error.field}: ${error.message}`);
    });
    
    // Handle field-specific errors
    Object.keys(fields).forEach(fieldName => {
      const fieldErrors = fields[fieldName];
      console.log(`${fieldName} has ${fieldErrors.length} errors`);
    });
  }
});

Promise-Based Error Handling

Modern promise/async-await pattern with structured error objects.

Usage Examples:

// Promise with .catch()
schema.validate(data)
  .then(validatedData => {
    console.log("Success:", validatedData);
  })
  .catch(error => {
    console.log("Validation failed");
    console.log("Errors:", error.errors);
    console.log("Fields:", error.fields);
  });

// Async/await with try-catch
try {
  const result = await schema.validate(data);
  console.log("Validation passed:", result);
} catch (error) {
  // error is an AsyncValidationError instance
  console.log("Validation failed");
  
  // Array of all errors
  error.errors.forEach(err => {
    console.log(`${err.field}: ${err.message}`);
  });
  
  // Field-organized errors
  Object.entries(error.fields).forEach(([field, errors]) => {
    console.log(`${field} has ${errors.length} error(s)`);
  });
}

AsyncValidationError Class

Structured error class thrown by promise-based validation.

class AsyncValidationError extends Error {
  errors: ValidateError[];
  fields: Record<string, ValidateError[]>;
  
  constructor(
    errors: ValidateError[],
    fields: Record<string, ValidateError[]>
  );
}

Usage Example:

try {
  await schema.validate(invalidData);
} catch (error) {
  if (error instanceof AsyncValidationError) {
    console.log("Async validation error occurred");
    console.log(`Total errors: ${error.errors.length}`);
    console.log(`Fields with errors: ${Object.keys(error.fields).length}`);
  }
}

Error Control Options

Configure error handling behavior through validation options.

interface ValidateOption {
  suppressWarning?: boolean;
  suppressValidatorError?: boolean;
  first?: boolean;
  firstFields?: boolean | string[];
  error?: (rule: InternalRuleItem, message: string) => ValidateError;
}

Suppress Warnings

Control warning output during validation.

suppressWarning?: boolean;

Usage Example:

// Suppress console warnings
await schema.validate(data, { suppressWarning: true });

Suppress Validator Errors

Control error throwing in custom validators.

suppressValidatorError?: boolean;

Usage Example:

await schema.validate(data, { suppressValidatorError: true });

First Error Only

Stop validation on the first error encountered.

first?: boolean;

Usage Example:

try {
  await schema.validate(data, { first: true });
} catch (error) {
  // Only contains the first error found
  console.log(`First error: ${error.errors[0].message}`);
}

First Field Errors

Stop validation on first error per field or specified fields.

firstFields?: boolean | string[];

Usage Examples:

// Stop on first error for all fields
await schema.validate(data, { firstFields: true });

// Stop on first error for specific fields only
await schema.validate(data, { 
  firstFields: ["username", "email"] 
});

Custom Error Factory

Provide custom error object creation function.

error?: (rule: InternalRuleItem, message: string) => ValidateError;

Usage Example:

await schema.validate(data, {
  error: (rule, message) => ({
    message: `Validation failed: ${message}`,
    field: rule.field,
    fieldValue: rule.value,
    timestamp: new Date().toISOString(),
    ruleType: rule.type
  })
});

Error Message Patterns

Common patterns for handling different error scenarios.

Field-Level Error Display

const displayFieldErrors = (fields) => {
  Object.entries(fields).forEach(([fieldName, errors]) => {
    const errorMessages = errors.map(err => err.message);
    console.log(`${fieldName}: ${errorMessages.join(', ')}`);
  });
};

try {
  await schema.validate(data);
} catch (error) {
  displayFieldErrors(error.fields);
}

Error Aggregation

const aggregateErrors = (errors) => {
  const summary = {
    total: errors.length,
    byField: {},
    byType: {}
  };
  
  errors.forEach(error => {
    // Group by field
    if (!summary.byField[error.field]) {
      summary.byField[error.field] = [];
    }
    summary.byField[error.field].push(error.message);
  });
  
  return summary;
};

try {
  await schema.validate(data);
} catch (error) {
  const summary = aggregateErrors(error.errors);
  console.log(`Total errors: ${summary.total}`);
}

Conditional Error Handling

const handleErrors = (error) => {
  if (error.errors.length === 1) {
    // Single error - show inline
    const err = error.errors[0];
    showInlineError(err.field, err.message);
  } else {
    // Multiple errors - show summary
    showErrorSummary(error.fields);
  }
};

try {
  await schema.validate(data);
} catch (error) {
  handleErrors(error);
}

Nested Object Error Handling

Handle errors in nested object validation.

Usage Example:

const schema = new Schema({
  user: {
    type: "object",
    fields: {
      profile: {
        type: "object",
        fields: {
          name: { type: "string", required: true },
          age: { type: "number", min: 0 }
        }
      }
    }
  }
});

try {
  await schema.validate({
    user: {
      profile: {
        name: "",
        age: -5
      }
    }
  });
} catch (error) {
  // Nested field errors use dot notation
  console.log(error.fields);
  // Output: {
  //   "user.profile.name": [{ message: "user.profile.name is required", ... }],
  //   "user.profile.age": [{ message: "user.profile.age cannot be less than 0", ... }]
  // }
}

docs

error-handling.md

index.md

messages.md

rules.md

schema.md

validation-types.md

tile.json