CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-simpl-schema

A schema validation package that supports direct validation of MongoDB update modifier objects.

Pending
Overview
Eval results
Files

validation-context.mddocs/

Validation Context

Validation context management for collecting validation errors, checking validity, and providing detailed error information without throwing exceptions.

Capabilities

ValidationContext Class

The ValidationContext class provides a way to collect validation errors instead of throwing exceptions immediately.

/**
 * Validation context for collecting and managing validation errors
 */
class ValidationContext {
  /** Optional context name for identification */
  name?: string;
  
  /**
   * Validates an object and returns success status
   * @param obj - Object to validate
   * @param options - Validation options
   * @returns true if valid, false if validation errors occurred
   */
  validate(obj: ObjectToValidate, options?: ValidationOptions): boolean;
  
  /**
   * Checks if the context currently has no validation errors
   * @returns true if no errors, false if errors exist
   */
  isValid(): boolean;
  
  /**
   * Gets all current validation errors
   * @returns Array of ValidationError objects
   */
  validationErrors(): ValidationError[];
  
  /**
   * Sets the validation errors, replacing any existing errors
   * @param errors - Array of ValidationError objects to set
   */
  setValidationErrors(errors: ValidationError[]): void;
  
  /**
   * Adds validation errors to the existing errors
   * @param errors - Array of ValidationError objects to add
   */
  addValidationErrors(errors: ValidationError[]): void;
  
  /**
   * Clears all validation errors from the context
   */
  reset(): void;
  
  /**
   * Gets the first validation error for a specific key
   * @param key - Field key to get error for
   * @param genericKey - Generic version of key for array items
   * @returns ValidationError object or undefined if no error
   */  
  getErrorForKey(key: string, genericKey?: string): ValidationError | undefined;
  
  /**
   * Checks if a specific key has validation errors
   * @param key - Field key to check
   * @param genericKey - Generic version of key for array items
   * @returns true if key has errors, false otherwise
   */
  keyIsInvalid(key: string, genericKey?: string): boolean;
  
  /**
   * Gets formatted error message for a specific key
   * @param key - Field key to get message for
   * @param genericKey - Generic version of key for array items
   * @returns Error message string or empty string if no error
   */
  keyErrorMessage(key: string, genericKey?: string): string;
  
  /**
   * Cleans a document using the context's schema
   * @param doc - Document to clean
   * @param options - Cleaning options
   * @returns Cleaned document
   */
  clean(doc: Record<string | number | symbol, unknown>, options?: CleanOptions): Record<string | number | symbol, unknown>;
}

interface ValidationOptions {
  extendedCustomContext?: Record<string | number | symbol, unknown>;
  ignore?: string[];
  keys?: string[];
  modifier?: boolean;
  mongoObject?: any;
  upsert?: boolean;
}

type ObjectToValidate = Record<string | number | symbol, unknown>;

Usage Examples:

import SimpleSchema from "simpl-schema";

const userSchema = new SimpleSchema({
  name: {
    type: String,
    min: 2,
    max: 50
  },
  email: {
    type: String,
    regEx: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
  },
  age: {
    type: Number,
    min: 18,
    max: 120
  }
});

// Create a validation context
const context = userSchema.newContext();

// Validate invalid data
const userData = {
  name: "A",              // Too short
  email: "invalid-email", // Invalid format
  age: 15                 // Too young
};

const isValid = context.validate(userData);
console.log(isValid); // false

// Get all errors
const errors = context.validationErrors();
console.log(errors);
// [
//   { name: 'name', type: 'minString', value: 'A' },
//   { name: 'email', type: 'regEx', value: 'invalid-email' },
//   { name: 'age', type: 'minNumber', value: 15 }
// ]

// Check validity
console.log(context.isValid()); // false

// Get specific error
const nameError = context.getErrorForKey('name');
console.log(nameError); // { name: 'name', type: 'minString', value: 'A' }

// Check if specific key is invalid
console.log(context.keyIsInvalid('email')); // true
console.log(context.keyIsInvalid('nonexistent')); // false

// Get error message for key
console.log(context.keyErrorMessage('age')); // "Age must be at least 18"

Creating Validation Contexts

Methods to create and manage validation contexts.

/**
 * Creates a new validation context for the schema
 * @returns New ValidationContext instance
 */
newContext(): ValidationContext;

/**
 * Gets or creates a named validation context that persists
 * @param name - Context name for reuse and identification
 * @returns Named ValidationContext instance
 */
namedContext(name?: string): ValidationContext;

Usage Examples:

const userSchema = new SimpleSchema({
  name: String,
  email: String
});

// Create new context each time
const context1 = userSchema.newContext();
const context2 = userSchema.newContext();
console.log(context1 === context2); // false - different instances

// Use named contexts for persistence
const formContext = userSchema.namedContext('userForm');
formContext.validate({ name: 'John' }); // Invalid - missing email

// Later, get the same named context
const sameContext = userSchema.namedContext('userForm');
console.log(formContext === sameContext); // true - same instance
console.log(sameContext.validationErrors()); // Still has errors from before

// Different named context
const adminContext = userSchema.namedContext('adminForm');
console.log(adminContext.validationErrors()); // Empty - different context

Error Management

Methods for managing validation errors within a context.

/**
 * Manually set validation errors, replacing existing ones
 * @param errors - Array of ValidationError objects
 */
setValidationErrors(errors: ValidationError[]): void;

/**
 * Add additional validation errors to existing ones
 * @param errors - Array of ValidationError objects to add
 */
addValidationErrors(errors: ValidationError[]): void;

/**
 * Clear all validation errors from the context
 */
reset(): void;

Usage Examples:

const context = userSchema.newContext();

// Manually set errors
context.setValidationErrors([
  { name: 'email', type: 'required', value: undefined },
  { name: 'age', type: 'minNumber', value: 15 }
]);

console.log(context.validationErrors().length); // 2

// Add more errors
context.addValidationErrors([
  { name: 'name', type: 'minString', value: 'A' }
]);

console.log(context.validationErrors().length); // 3

// Clear all errors
context.reset();
console.log(context.validationErrors().length); // 0
console.log(context.isValid()); // true

Key-Specific Error Queries

Methods for checking errors on specific fields.

/**
 * Get the first error for a specific field key
 * @param key - Field key to check
 * @param genericKey - Generic key for array items (e.g., 'items.$')
 * @returns ValidationError or undefined
 */
getErrorForKey(key: string, genericKey?: string): ValidationError | undefined;

/**
 * Check if a specific field key is invalid
 * @param key - Field key to check
 * @param genericKey - Generic key for array items
 * @returns true if field has errors
 */
keyIsInvalid(key: string, genericKey?: string): boolean;

/**
 * Get formatted error message for a specific field key
 * @param key - Field key to get message for
 * @param genericKey - Generic key for array items
 * @returns Error message string
 */
keyErrorMessage(key: string, genericKey?: string): string;

Usage Examples:

const schema = new SimpleSchema({
  name: String,
  tags: [String],
  'tags.$': {
    type: String,
    min: 2
  }
});

const context = schema.newContext();

// Validate data with errors
context.validate({
  name: '',        // Required but empty
  tags: ['ok', 'x'] // Second tag too short
});

// Check specific field errors
console.log(context.keyIsInvalid('name')); // true
console.log(context.keyIsInvalid('tags')); // false - array itself is valid
console.log(context.keyIsInvalid('tags.1')); // true - specific array item invalid

// Get specific errors
const nameError = context.getErrorForKey('name');
console.log(nameError?.type); // 'required'

const tagError = context.getErrorForKey('tags.1', 'tags.$');
console.log(tagError?.type); // 'minString'

// Get error messages
console.log(context.keyErrorMessage('name')); // "Name is required"
console.log(context.keyErrorMessage('tags.1')); // "Tags $ must be at least 2 characters"

Context-Based Cleaning

Use validation context for cleaning operations.

/**
 * Clean a document using the context's schema
 * @param doc - Document to clean
 * @param options - Cleaning options
 * @returns Cleaned document
 */
clean(doc: Record<string | number | symbol, unknown>, options?: CleanOptions): Record<string | number | symbol, unknown>;

Usage Examples:

const schema = new SimpleSchema({
  name: {
    type: String,
    trim: true
  },
  age: Number
});

const context = schema.newContext();

const dirtyData = {
  name: '  John Doe  ',
  age: '25',
  extra: 'field'
};

// Clean using context
const cleaned = context.clean(dirtyData, {
  autoConvert: true,
  trimStrings: true,
  filter: true
});

console.log(cleaned);
// { name: 'John Doe', age: 25 }

// Validate the cleaned data
const isValid = context.validate(cleaned);
console.log(isValid); // true

Working with MongoDB Modifiers

Validate MongoDB update modifiers using validation contexts.

// ValidationContext works with modifier validation
context.validate(modifierDoc, { modifier: true });

Usage Examples:

const schema = new SimpleSchema({
  'profile.name': String,
  'profile.age': Number,
  tags: [String]
});

const context = schema.newContext();

// Validate $set modifier
const isValidSet = context.validate({
  $set: {
    'profile.name': 'John Doe',
    'profile.age': 30
  }
}, { modifier: true });

console.log(isValidSet); // true

// Validate invalid $push modifier
const isValidPush = context.validate({
  $push: {
    tags: null // Invalid - can't push null
  }
}, { modifier: true });

console.log(isValidPush); // false
console.log(context.validationErrors());

Form Integration Patterns

Common patterns for using validation contexts with forms.

Usage Examples:

// Form validation helper
class FormValidator {
  constructor(schema, formName) {
    this.schema = schema;
    this.context = schema.namedContext(formName);
  }
  
  validate(formData) {
    // Clean and validate
    const cleaned = this.context.clean(formData, {
      autoConvert: true,
      trimStrings: true,
      filter: true
    });
    
    const isValid = this.context.validate(cleaned);
    
    return {
      isValid,
      errors: this.context.validationErrors(),
      cleanedData: cleaned
    };
  }
  
  getFieldError(fieldName) {
    return this.context.keyErrorMessage(fieldName);
  }
  
  isFieldInvalid(fieldName) {
    return this.context.keyIsInvalid(fieldName);
  }
  
  reset() {
    this.context.reset();
  }
}

// Usage
const userSchema = new SimpleSchema({...});
const validator = new FormValidator(userSchema, 'userRegistration');

const result = validator.validate(formData);
if (!result.isValid) {
  console.log('Form errors:', result.errors);
}

Types

interface ValidationError {
  /** Field name that failed validation */
  name: string;
  /** Type of validation error */
  type: string;
  /** Value that failed validation */
  value: any;
  /** Localized error message (optional) */
  message?: string;
  /** Additional error properties */
  [prop: string]: any;
}

Install with Tessl CLI

npx tessl i tessl/npm-simpl-schema

docs

data-cleaning.md

index.md

schema-definition.md

schema-introspection.md

utility-functions.md

validation-context.md

validation.md

tile.json