A schema validation package that supports direct validation of MongoDB update modifier objects.
—
Comprehensive validation system supporting object validation, MongoDB modifiers, custom validators, and detailed error reporting.
Primary validation method that throws errors on validation failure.
/**
* Validates an object against the schema, throwing an error if validation fails
* @param obj - Object to validate
* @param options - Validation options
* @throws ValidationError if validation fails
*/
validate(obj: any, options?: ValidationOptions): void;
interface ValidationOptions {
/** Extended custom context for validation functions */
extendedCustomContext?: Record<string | number | symbol, unknown>;
/** Array of field keys to ignore during validation */
ignore?: string[];
/** Array of field keys to validate (validates only these keys) */
keys?: string[];
/** Whether to validate as MongoDB modifier document */
modifier?: boolean;
/** MongoObject instance for modifier validation */
mongoObject?: any;
/** Whether this is an upsert operation */
upsert?: boolean;
}Usage Examples:
import SimpleSchema from "simpl-schema";
const userSchema = new SimpleSchema({
name: String,
email: String,
age: Number
});
// Basic validation - throws on error
try {
userSchema.validate({ name: "John", email: "john@example.com", age: 25 });
console.log("Valid!");
} catch (error) {
console.log("Validation failed:", error.message);
}
// Validate specific keys only
userSchema.validate(
{ name: "John", age: 25 },
{ keys: ['name', 'age'] }
);
// Validate MongoDB modifier document
userSchema.validate(
{ $set: { name: "John Doe" } },
{ modifier: true }
);Class-level validation method for one-off validations without creating schema instances.
/**
* Static validation method for validating against schema definitions
* @param obj - Object to validate
* @param schema - Schema instance or definition to validate against
* @param options - Validation options
* @throws ValidationError if validation fails
*/
static validate(obj: any, schema: SimpleSchema | SchemaDefinition, options?: ValidationOptions): void;Usage Examples:
// Validate against schema definition directly
SimpleSchema.validate(
{ name: "John", age: 25 },
{ name: String, age: Number }
);
// Validate against existing schema
const userSchema = new SimpleSchema({ name: String, age: Number });
SimpleSchema.validate({ name: "John", age: 25 }, userSchema);Async validation method that returns validation errors as a promise instead of throwing.
/**
* Validates an object and returns validation errors as a promise
* @param obj - Object to validate
* @param options - Validation options
* @returns Promise that resolves to array of validation errors
*/
async validateAndReturnErrorsPromise(obj: any, options: ValidationOptions): Promise<ValidationError[]>;Usage Examples:
const userSchema = new SimpleSchema({
name: { type: String, min: 2 },
email: { type: String, regEx: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
age: { type: Number, min: 0 }
});
// Async validation that returns errors instead of throwing
const errors = await userSchema.validateAndReturnErrorsPromise({
name: "J", // Too short
email: "invalid", // Invalid format
age: -5 // Below minimum
});
console.log(errors);
// [
// { name: 'name', type: 'minString', value: 'J', message: 'Name must be at least 2 characters' },
// { name: 'email', type: 'regEx', value: 'invalid', message: 'Email failed regular expression validation' },
// { name: 'age', type: 'minNumber', value: -5, message: 'Age must be at least 0' }
// ]
// Handle validation in async context
try {
const validationErrors = await userSchema.validateAndReturnErrorsPromise(userData);
if (validationErrors.length > 0) {
// Handle validation errors
validationErrors.forEach(error => {
console.log(`Field ${error.name}: ${error.message}`);
});
} else {
console.log('Validation passed!');
}
} catch (error) {
console.log('Validation system error:', error);
}Create reusable validator functions for repeated validation scenarios.
/**
* Returns a validator function that can be called repeatedly
* @param options - Validation options with additional configuration
* @returns Function that validates objects and returns boolean or throws
*/
validator(options?: ValidationOptions & {
clean?: boolean;
returnErrorsPromise?: boolean;
}): Function;
/**
* Returns a form-specific validator function that returns errors as a promise
* @param options - Form validation options
* @returns Function that validates and returns promise with validation errors
*/
getFormValidator(options?: ValidationOptions): (obj: Record<string, any>) => Promise<ValidationError[]>;Usage Examples:
const userSchema = new SimpleSchema({
name: String,
email: String
});
// Create validator that throws on error
const validateUser = userSchema.validator();
validateUser({ name: "John", email: "john@example.com" });
// Create validator that cleans before validating
const cleanAndValidate = userSchema.validator({ clean: true });
// Create validator that returns promise with errors
const asyncValidator = userSchema.validator({ returnErrorsPromise: true });
asyncValidator(userData).then(errors => {
if (errors.length > 0) {
console.log("Validation errors:", errors);
}
});
// Create form validator (always returns promise with errors)
const formValidator = userSchema.getFormValidator();
formValidator(formData).then(errors => {
if (errors.length > 0) {
// Display form errors to user
errors.forEach(error => {
displayFieldError(error.name, error.message);
});
} else {
// Submit form
submitForm(formData);
}
});Create validation contexts for collecting errors without throwing exceptions.
/**
* Creates a new validation context for this schema
* @returns New ValidationContext instance
*/
newContext(): ValidationContext;
/**
* Gets or creates a named validation context
* @param name - Context name for reuse
* @returns Named ValidationContext instance
*/
namedContext(name?: string): ValidationContext;Usage Examples:
const userSchema = new SimpleSchema({
name: String,
email: String
});
// Create new context
const context = userSchema.newContext();
const isValid = context.validate({ name: "John" }); // false
if (!isValid) {
console.log(context.validationErrors()); // Array of errors
}
// Use named context for persistence
const formContext = userSchema.namedContext('userForm');
formContext.validate(formData);
// Later, reuse the same context
const sameContext = userSchema.namedContext('userForm');
console.log(sameContext.validationErrors());Add custom validation logic at the schema or field level.
/**
* Adds a custom validator function to this schema instance
* @param func - Validator function to add
*/
addValidator(func: ValidatorFunction): void;
/**
* Adds a document-level validator function to this schema instance
* @param func - Document validator function to add
*/
addDocValidator(func: DocValidatorFunction): void;
/**
* Adds a custom validator function globally to all schema instances
* @param func - Validator function to add globally
*/
static addValidator(func: ValidatorFunction): void;
/**
* Adds a document-level validator function globally to all schema instances
* @param func - Document validator function to add globally
*/
static addDocValidator(func: DocValidatorFunction): void;
// Validator function types
type ValidatorFunction = (this: ValidatorContext) => void | undefined | boolean | string | ValidationErrorResult;
type DocValidatorFunction = (this: DocValidatorContext, obj: Record<string, unknown>) => ValidationError[];
interface ValidatorContext {
key: string;
keyPath: string;
value: any;
definition: StandardSchemaKeyDefinitionWithSimpleTypes;
isSet: boolean;
operator: string | null;
validationContext: ValidationContext;
field(key: string): FieldInfo<any>;
siblingField(key: string): FieldInfo<any>;
addValidationErrors(errors: ValidationError[]): void;
}Usage Examples:
// Field-level custom validator
const userSchema = new SimpleSchema({
email: {
type: String,
custom() {
if (!this.value.includes('@')) {
return 'emailInvalid';
}
}
},
password: {
type: String,
min: 8,
custom() {
if (!/[A-Z]/.test(this.value)) {
return 'passwordNeedsUppercase';
}
}
}
});
// Schema-level custom validator
userSchema.addValidator(function() {
if (this.key === 'confirmPassword') {
const password = this.field('password').value;
if (password !== this.value) {
return 'passwordMismatch';
}
}
});
// Document-level validator
userSchema.addDocValidator(function(obj) {
const errors = [];
if (obj.age < 18 && obj.hasAccount) {
errors.push({
name: 'hasAccount',
type: 'minorWithAccount',
value: obj.hasAccount
});
}
return errors;
});
// Global validator affecting all schemas
SimpleSchema.addValidator(function() {
if (this.key.endsWith('Email') && this.isSet) {
if (!this.value.includes('@')) {
return 'mustBeEmail';
}
}
});Validate MongoDB update modifier documents like $set, $unset, $push, etc.
// Enable modifier validation in options
interface ValidationOptions {
/** Whether to validate as MongoDB modifier document */
modifier?: boolean;
/** MongoObject instance for advanced modifier validation */
mongoObject?: any;
/** Whether this is an upsert operation */
upsert?: boolean;
}Usage Examples:
const userSchema = new SimpleSchema({
'profile.name': String,
'profile.age': Number,
tags: [String],
lastLogin: Date
});
// Validate $set modifier
userSchema.validate({
$set: {
'profile.name': 'John Doe',
'profile.age': 30
}
}, { modifier: true });
// Validate $push modifier
userSchema.validate({
$push: {
tags: 'javascript'
}
}, { modifier: true });
// Validate $unset modifier
userSchema.validate({
$unset: {
'profile.age': ""
}
}, { modifier: true });
// Complex modifier with multiple operations
userSchema.validate({
$set: { 'profile.name': 'Jane Doe' },
$push: { tags: 'react' },
$currentDate: { lastLogin: true }
}, { modifier: true });Handle validation operations that return promises for async validation scenarios.
/**
* Validates and returns errors as a promise
* @param obj - Object to validate
* @param options - Validation options
* @returns Promise resolving to array of ValidationError objects
*/
validateAndReturnErrorsPromise(obj: any, options: ValidationOptions): Promise<ValidationError[]>;Usage Examples:
const userSchema = new SimpleSchema({
username: {
type: String,
custom() {
// Simulate async validation (e.g., checking uniqueness)
return new Promise((resolve) => {
setTimeout(() => {
if (this.value === 'admin') {
resolve('usernameNotAllowed');
} else {
resolve();
}
}, 100);
});
}
}
});
// Use async validation
userSchema.validateAndReturnErrorsPromise({ username: 'admin' })
.then(errors => {
if (errors.length > 0) {
console.log('Validation errors:', errors);
} else {
console.log('Valid!');
}
});interface ValidationError {
/** Localized error message */
message?: string;
/** Field name that failed validation */
name: string;
/** Type of validation error */
type: string;
/** Value that failed validation */
value: any;
/** Additional error properties */
[prop: string]: any;
}
interface ValidationErrorResult {
type: string;
value?: any;
message?: string;
}
interface FieldInfo<ValueType> {
value: ValueType;
isSet: boolean;
operator: string | null;
}Install with Tessl CLI
npx tessl i tessl/npm-simpl-schema