@contrail/type-validation
v1.0.50
Published
Defines various utilities and interfaces related to type validation.
Maintainers
Keywords
Readme
TypeRuleSet Technical Documentation
Overview
TypeRuleSets provide a powerful, conditional validation and constraint system for entities. They allow you to define rules that apply only when specific criteria are met, enabling dynamic validation based on entity state.
Data Structure
TypeRuleSet Interface
interface TypeRuleSet {
ruleSet: Array<ConditionalTypeRules>;
}ConditionalTypeRules Interface
interface ConditionalTypeRules {
criteria: FilterCriteria; // When to apply these rules
rules: Array<TypeRule>; // What rules to apply
}TypeRule Interface
interface TypeRule {
slug: string; // Property to validate (or "ALL" for all properties)
excludedSlugs?: string[]; // Properties to exclude when slug="ALL"
required?: boolean; // Whether the property is required
editable?: boolean; // Whether the property is editable
optionSetValues?: string[]; // Allowed option set values
invalidValues?: string[]; // Disallowed values
minValue?: number; // Minimum numeric value
maxValue?: number; // Maximum numeric value
validationFunction?: string; // Custom validation function
}Supported Filter Condition Types
The criteria field uses the same filter system as the rest of the application:
| Condition | Description | Example Use Cases |
| ----------------------- | ------------------------- | ------------------------------------- |
| EQUALS | Exact match | Status equals "active" |
| NOT_EQUAL_TO | Not equal to | Status not "archived" |
| GREATER_THAN | Numeric comparison | Priority > 5 |
| LESS_THAN | Numeric comparison | Cost < 1000 |
| GREATER_THAN_OR_EQUAL | Numeric comparison | Quantity >= 10 |
| LESS_THAN_OR_EQUAL | Numeric comparison | Rating <= 5 |
| STARTS_WITH | String prefix | Name starts with "Test" |
| ENDS_WITH | String suffix | File ends with ".pdf" |
| CONTAINS | String contains | Description contains "urgent" |
| IS_ANY_OF | Array membership | Category in ["A", "B", "C"] |
| IS_NONE_OF | Array exclusion | Status not in ["deleted", "archived"] |
| IS_EMPTY | Null/empty check | Required field is empty |
| IS_NOT_EMPTY | Has value | Optional field has value |
| IS_IN_LIST | Comma-separated values | Tag in "red,blue,green" |
| ARE_ANY_EMPTY | Check multiple properties | Any required field empty |
Rule Types and Behaviors
1. Editable Rules
Purpose: Control whether properties can be modified
{
slug: "ALL", // Apply to all properties
editable: false, // Make all properties read-only
excludedSlugs: ["name", "description"] // Except these
}2. Required Rules
Purpose: Make properties mandatory based on conditions
{
slug: "priority",
required: true // Priority must have a value
}3. Value Range Rules
Purpose: Enforce numeric constraints
{
slug: "quantity",
minValue: 1, // Must be at least 1
maxValue: 100 // Must be at most 100
}4. Option Set Validation
Purpose: Restrict values to specific options
{
slug: "status",
optionSetValues: ["active", "pending", "review"] // Only these values allowed
}5. Invalid Value Exclusion
Purpose: Prevent specific values
{
slug: "category",
invalidValues: ["deleted", "archived"] // These values are forbidden
}How It Works
1. Validation Process
- Criteria Evaluation: For each
ConditionalTypeRules, the system evaluates whether the entity meets the criteria - Rule Application: If criteria are met, all rules in that set are applied to the entity
- Error Collection: Validation errors are collected and returned
2. Return Value
The system returns an array of ValidationError objects:
interface ValidationError {
slug?: string; // Property that failed validation
value?: any; // The invalid value
message: string; // Human-readable error message
type?: ValidationErrorType; // WARNING or ERROR
}3. Editable Check Process
- Multiple TypeRuleSets can be evaluated
- If ANY rule set makes a property non-editable, it becomes read-only
- The
slug: "ALL"rule applies to all properties except those inexcludedSlugs
Advanced Features
1. Nested Property Access
Rules can target nested properties using dot notation:
{
slug: "itemFamily.lifecycleStage",
required: true
}2. Multiple Rule Sets
You can apply multiple TypeRuleSets to an entity. All rules from all matching sets are applied.
3. Option Set Intersection
When multiple rules define optionSetValues, the system finds the intersection (common values) of all sets.
4. Invalid Value Union
When multiple rules define invalidValues, the system combines all invalid values into a single forbidden set.
Example Use Cases
1. Lifecycle-Based Validation
{
ruleSet: [
{
criteria: {
propertyCriteria: [
{
filterPropertyDefinition: {
slug: 'lifecycleStage',
propertyType: PropertyType.SingleSelect,
},
filterConditionType: FilterConditionType.EQUALS,
criteriaValue: 'concept',
},
],
},
rules: [
{
slug: 'priority',
required: true,
minValue: 1,
maxValue: 5,
},
],
},
];
}2. Conditional Editability
{
ruleSet: [
{
criteria: {
propertyCriteria: [
{
filterPropertyDefinition: {
slug: 'status',
propertyType: PropertyType.SingleSelect,
},
filterConditionType: FilterConditionType.EQUALS,
criteriaValue: 'approved',
},
],
},
rules: [
{
slug: 'ALL',
editable: false,
excludedSlugs: ['notes'],
},
],
},
];
}3. Complex Multi-Criteria Rules
{
ruleSet: [
{
criteria: {
propertyCriteria: [
{
filterPropertyDefinition: {
slug: 'department',
propertyType: PropertyType.SingleSelect,
},
filterConditionType: FilterConditionType.EQUALS,
criteriaValue: 'engineering',
},
{
filterPropertyDefinition: {
slug: 'priority',
propertyType: PropertyType.Number,
},
filterConditionType: FilterConditionType.GREATER_THAN,
criteriaValue: 5,
},
],
},
rules: [
{
slug: 'approvalRequired',
required: true,
optionSetValues: ['yes'],
},
{
slug: 'ALL',
editable: false,
excludedSlugs: ['approvalRequired', 'notes'],
},
],
},
];
}Integration Points
- Type Validation: Used by
TypeManagedValidatorto validate entity changes - UI Constraints: Used by
TypeConstraintsHelperto determine editability and valid options - Option Set Filtering: Used by
OptionSetRuleExtractorto dynamically filter available options - Form Validation: Applied during form submission to prevent invalid data
Best Practices
1. Rule Organization
- Group related rules in the same
ConditionalTypeRulesobject - Use descriptive criteria that clearly indicate when rules should apply
- Keep rule sets focused on specific business scenarios
2. Performance Considerations
- Avoid overly complex criteria that require expensive evaluations
- Use specific property slugs rather than "ALL" when possible
- Consider the order of rule evaluation for optimal performance
3. Error Messages
- Provide clear, actionable error messages
- Include context about why a rule failed
- Use consistent messaging across similar validation failures
4. Testing
- Test rule sets with various entity states
- Verify that criteria properly filter rule application
- Ensure that multiple rule sets work together correctly
- Test edge cases like empty values and boundary conditions
Common Patterns
1. State-Based Validation
Use entity state to determine which validation rules apply:
// Only require approval for high-priority items
{
criteria: { /* priority > 5 */ },
rules: [{ slug: "approvalRequired", required: true }]
}2. Role-Based Constraints
Restrict editing based on user roles or entity ownership:
// Only allow editing of own items
{
criteria: { /* owner equals current user */ },
rules: [{ slug: "ALL", editable: true }]
}3. Workflow Enforcement
Ensure proper workflow progression:
// Lock fields after approval
{
criteria: { /* status equals "approved" */ },
rules: [{ slug: "ALL", editable: false, excludedSlugs: ["status"] }]
}This system provides a flexible, powerful way to implement complex business rules that adapt based on entity state and context.
