# | Reusable Validation Library for Nickel # | Common validation contracts and helper functions # | Author: JesusPerezLorenzo # | Date: 2025-12-15 # | Status: Production Ready # ============================================================ # Common Validation Contracts # ============================================================ # IPv4 address validation (e.g., "192.168.1.1") let IpV4Contract = { label = "ValidIPv4", predicate = fun ip => std.string.is_match ip "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" } # CIDR notation validation (e.g., "192.168.1.0/24") let CidrContract = { label = "ValidCIDR", predicate = fun cidr => std.string.is_match cidr "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/\\d{1,2}$" } # Port range validation (1-65535) let PortContract = { label = "ValidPort", predicate = fun p => p > 0 && p < 65536 } # Semantic versioning validation (e.g., "1.2.3") let SemverContract = { label = "ValidSemver", predicate = fun v => std.string.is_match v "^\\d+\\.\\d+\\.\\d+$" } # Domain name validation (e.g., "example.com") let DomainContract = { label = "ValidDomain", predicate = fun d => std.string.is_match d "^[a-z0-9]([a-z0-9-\\.]{0,253}[a-z0-9])?$" } # OCI tag validation (e.g., "latest", "v1.0.0", "sha256-abc123") let OciTagContract = { label = "ValidOCITag", predicate = fun tag => std.string.is_match tag "^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$" } # ISO 8601 timestamp validation (e.g., "2025-12-15T10:30:00Z") let Iso8601Contract = { label = "ValidISO8601", predicate = fun ts => std.string.is_match ts "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$" } # Filesystem path validation (simple: non-empty, no double slashes) let PathContract = { label = "ValidPath", predicate = fun path => std.string.length path > 0 && !std.string.contains path "//" } # ============================================================ # Helper Functions for Common Validations # ============================================================ # Validate minimum string length let min_length = fun min_val => { label = "MinLength%{std.to_string min_val}", predicate = fun s => std.string.length s >= min_val } # Validate maximum string length let max_length = fun max_val => { label = "MaxLength%{std.to_string max_val}", predicate = fun s => std.string.length s <= max_val } # Validate numeric range let range = fun min_val max_val => { label = "Range[%{std.to_string min_val}-%{std.to_string max_val}]", predicate = fun n => n >= min_val && n <= max_val } # Validate enum (value must be in list) let enum = fun values => { label = "Enum[%{std.string.join "," values}]", predicate = fun v => std.array.elem v values } # Validate non-empty string let non_empty_string = { label = "NonEmptyString", predicate = fun s => std.string.length s > 0 } # Validate non-negative number let non_negative = { label = "NonNegative", predicate = fun n => n >= 0 } # Validate positive number let positive = { label = "Positive", predicate = fun n => n > 0 } # Validate boolean value let boolean_value = { label = "Boolean", predicate = fun b => b == true || b == false } # ============================================================ # Helper Functions for Custom Validation # ============================================================ # Validate all items in array satisfy predicate let all_items = fun predicate => fun items => std.array.all predicate items # Validate at least one item in array satisfies predicate let any_items = fun predicate => fun items => std.array.any predicate items # Validate record has all required keys let has_keys = fun required_keys => fun record => std.array.all (fun key => std.record.has_field record key ) required_keys # ============================================================ # Exports # ============================================================ { # Core validation contracts IpV4Contract = IpV4Contract, CidrContract = CidrContract, PortContract = PortContract, SemverContract = SemverContract, DomainContract = DomainContract, OciTagContract = OciTagContract, Iso8601Contract = Iso8601Contract, PathContract = PathContract, # Helper functions min_length = min_length, max_length = max_length, range = range, enum = enum, non_empty_string = non_empty_string, non_negative = non_negative, positive = positive, boolean_value = boolean_value, # Custom validators all_items = all_items, any_items = any_items, has_keys = has_keys, }