import dayjs from 'dayjs'; import isURL from 'validator/lib/isURL.js'; import isIBAN from 'validator/lib/isIBAN.js'; import isEmail from 'validator/lib/isEmail.js'; import { type PostalCodeLocale } from 'validator/lib/isPostalCode.js'; import { type MobilePhoneLocale } from 'validator/lib/isMobilePhone.js'; import type { DateFieldOptions, FieldContext, PropertiesToOptional, SchemaTypes } from '../types.js'; import { type Prettify } from '@poppinss/types'; /** * Values that are considered true in HTML form context. * Includes boolean true, number 1, string '1', 'true', and 'on' (for checkboxes). */ export declare const BOOLEAN_POSITIVES: (string | number | boolean)[]; /** * Values that are considered false in HTML form context. * Includes boolean false, number 0, string '0', and 'false'. */ export declare const BOOLEAN_NEGATIVES: (string | number | boolean)[]; /** * Default date formats used when no specific format is provided. * Supports date-only (YYYY-MM-DD) and datetime (YYYY-MM-DD HH:mm:ss) formats. */ export declare const DEFAULT_DATE_FORMATS: string[]; /** * Regular expression for validating ULID (Universally Unique Lexicographically Sortable Identifier) format. * ULIDs are 26 characters long using Crockford's Base32 encoding. */ export declare const ULID: RegExp; /** * Collection of utility helpers used across the Vine validation library. * These helpers provide type-checking, coercion, and validation functions * that are optimized for HTML form data handling. * * @example * helpers.isString(value) // Type guard for strings * helpers.asBoolean(value) // Convert to boolean with HTML form semantics * helpers.isEmail(email) // Validate email addresses */ export declare const helpers: { /** * Checks if a value exists (is not null and not undefined). * Useful for checking if optional form fields have been provided. * * @param value - The value to check * @returns True if value is not null and not undefined * * @example * helpers.exists('hello') // true * helpers.exists(0) // true * helpers.exists(null) // false * helpers.exists(undefined) // false */ exists(value: any): boolean; /** * Checks if a value is missing (null or undefined). * The inverse of the exists method. * * @param value - The value to check * @returns True if value is null or undefined * * @example * helpers.isMissing(null) // true * helpers.isMissing(undefined) // true * helpers.isMissing('') // false * helpers.isMissing(0) // false */ isMissing(value: any): boolean; /** * Checks if a value represents a truthy boolean in HTML form context. * Recognizes common HTML form representations of true values. * * Accepted truthy values: * - true (boolean) * - 1 (number) * - "1" (string) * - "true" (string) * - "on" (string, for checkboxes) * * @param value - The value to check * @returns True if value represents a truthy boolean * * @example * helpers.isTrue(true) // true * helpers.isTrue('on') // true (checkbox checked) * helpers.isTrue('1') // true (form input) * helpers.isTrue('yes') // false */ isTrue(value: any): boolean; /** * Checks if a value represents a falsy boolean in HTML form context. * Recognizes common HTML form representations of false values. * * Accepted falsy values: * - false (boolean) * - 0 (number) * - "0" (string) * - "false" (string) * * @param value - The value to check * @returns True if value represents a falsy boolean * * @example * helpers.isFalse(false) // true * helpers.isFalse('0') // true (form input) * helpers.isFalse('false') // true (form input) * helpers.isFalse('no') // false */ isFalse(value: any): boolean; /** * Type guard that checks if a value is a string. * Narrows the TypeScript type to string when returning true. * * @param value - The value to check * @returns True if value is a string, with type narrowing * * @example * if (helpers.isString(value)) { * // value is now typed as string * console.log(value.toUpperCase()) * } */ isString(value: unknown): value is string; /** * Type guard that checks if a value is a plain JavaScript object. * Excludes null, arrays, and other non-plain objects. * * @template Value - The type of values in the object * @param value - The value to check * @returns True if value is a plain object, with type narrowing * * @example * helpers.isObject({}) // true * helpers.isObject([]) // false * helpers.isObject(null) // false * helpers.isObject(new Date()) // true (but not recommended for validation) */ isObject(value: unknown): value is Record; /** * Checks if an object contains all the specified keys. * Useful for validating object structure before processing. * * @param value - The object to check * @param keys - Array of key names that must exist * @returns True if all keys exist in the object * * @example * helpers.hasKeys({ name: 'John', age: 30 }, ['name']) // true * helpers.hasKeys({ name: 'John' }, ['name', 'age']) // false */ hasKeys(value: Record, keys: string[]): boolean; /** * Type guard that checks if a value is an array. * Narrows the TypeScript type to array when returning true. * * @template Value - The type of elements in the array * @param value - The value to check * @returns True if value is an array, with type narrowing * * @example * if (helpers.isArray(value)) { * // value is now typed as array * console.log(value.length) * } */ isArray(value: unknown): value is Value[]; /** * Checks if a value is numeric (number or string representing a number). * Useful for validating form inputs that should contain numeric values. * * @param value - The value to check * @returns True if value can be converted to a valid number * * @example * helpers.isNumeric(42) // true * helpers.isNumeric('42') // true * helpers.isNumeric('42.5') // true * helpers.isNumeric('abc') // false */ isNumeric(value: any): boolean; /** * Converts a value to a number using JavaScript's Number() constructor. * Handles null values explicitly by returning NaN. * * @param value - The value to convert to a number * @returns The numeric representation, or NaN if conversion fails * * @example * helpers.asNumber('42') // 42 * helpers.asNumber('42.5') // 42.5 * helpers.asNumber(null) // NaN * helpers.asNumber('abc') // NaN */ asNumber(value: any): number; /** * Converts a value to a boolean using HTML form semantics. * Returns null for values that cannot be reliably converted. * * Conversion rules: * - [true, 1, "1", "true", "on"] → true * - [false, 0, "0", "false"] → false * - Everything else → null * * @param value - The value to convert * @returns Boolean value, or null if conversion is ambiguous * * @example * helpers.asBoolean('true') // true * helpers.asBoolean('on') // true (checkbox checked) * helpers.asBoolean('false') // false * helpers.asBoolean('maybe') // null (ambiguous) */ asBoolean(value: any): boolean | null; /** * Converts a value to a Day.js date object with flexible format support. * Handles timestamps, ISO dates, and custom formats with intelligent fallbacks. * * @param value - The value to convert to a date (string, number, Date, etc.) * @param format - Date format(s) to use for parsing. Can be: * - Array of format strings (e.g., ['YYYY-MM-DD', 'DD/MM/YYYY']) * - Single format string * - Object with format and strict parsing options * - Special values: 'x' for timestamps, 'iso8601' for ISO dates * @returns Object containing the parsed Day.js instance and normalized formats * * @example * // Parse with default formats * helpers.asDayJS('2023-12-25') * // { dateTime: dayjs('2023-12-25'), formats: ['YYYY-MM-DD', 'YYYY-MM-DD HH:mm:ss'] } * * // Parse timestamp * helpers.asDayJS('1703548800000', ['x']) * // { dateTime: dayjs(1703548800000), formats: ['x'] } * * // Parse with custom format * helpers.asDayJS('25/12/2023', ['DD/MM/YYYY']) * // { dateTime: dayjs('25/12/2023', 'DD/MM/YYYY'), formats: ['DD/MM/YYYY'] } * * // ISO date fallback * helpers.asDayJS('2023-12-25T10:30:00Z', ['iso8601']) * // { dateTime: dayjs('2023-12-25T10:30:00Z'), formats: ['iso8601'] } */ asDayJS(value: any, format: DateFieldOptions["formats"]): { dateTime: dayjs.Dayjs; formats: string | string[] | dayjs.FormatObject; }; /** * Compares two values with intelligent type coercion. * The input value is cast to match the type of the expected value * for HTML form-friendly comparisons. * * @param inputValue - The input value to compare * @param expectedValue - The expected value to compare against * @returns Object with comparison result and the casted input value * * @example * // Number comparison * helpers.compareValues('42', 42) * // { isEqual: true, casted: 42 } * * // Boolean comparison * helpers.compareValues('true', true) * // { isEqual: true, casted: true } * * // String comparison (no casting) * helpers.compareValues('hello', 'world') * // { isEqual: false, casted: 'hello' } */ compareValues(inputValue: unknown, expectedValue: any): { isEqual: boolean; casted: unknown; }; /** Validates email addresses using comprehensive rules */ isEmail: typeof isEmail.default; /** Validates URLs with protocol and domain checking */ isURL: typeof isURL.default; /** Validates alphabetic characters only */ isAlpha: typeof import("validator").isAlpha; /** Validates alphanumeric characters only */ isAlphaNumeric: typeof import("validator").isAlphanumeric; /** Validates IP addresses (IPv4 and IPv6) */ isIP: typeof import("validator").isIP; /** Validates UUID strings in various formats */ isUUID: typeof import("validator").isUUID; /** Validates ASCII character strings */ isAscii: typeof import("validator").isAscii; /** Validates credit card numbers using Luhn algorithm */ isCreditCard: typeof import("validator").isCreditCard; /** Validates International Bank Account Numbers */ isIBAN: typeof isIBAN.default; /** Validates JSON Web Tokens */ isJWT: typeof import("validator").isJWT; /** Validates latitude/longitude coordinate pairs */ isLatLong: typeof import("validator").isLatLong; /** Validates mobile phone numbers for various locales */ isMobilePhone: typeof import("validator").isMobilePhone; /** Validates passport numbers for supported countries */ isPassportNumber: typeof import("validator").isPassportNumber; /** Validates VAT numbers for supported countries */ isVAT: typeof import("validator").isVAT; /** Validates postal codes for various countries */ isPostalCode: typeof import("validator").isPostalCode; /** Validates URL slugs (lowercase, hyphenated strings) */ isSlug: typeof import("validator").isSlug; /** Validates decimal numbers */ isDecimal: typeof import("validator").isDecimal; /** Array of supported mobile phone locales/countries */ mobileLocales: MobilePhoneLocale[]; /** Array of supported postal code country codes */ postalCountryCodes: PostalCodeLocale[]; /** Array of supported passport country codes */ passportCountryCodes: readonly ["AM", "AR", "AT", "AU", "AZ", "BE", "BG", "BR", "BY", "CA", "CH", "CY", "CZ", "DE", "DK", "DZ", "ES", "FI", "FR", "GB", "GR", "HR", "HU", "IE", "IN", "ID", "IR", "IS", "IT", "JM", "JP", "KR", "KZ", "LI", "LT", "LU", "LV", "LY", "MT", "MZ", "MY", "MX", "NL", "NZ", "PH", "PK", "PL", "PT", "RO", "RU", "SE", "SL", "SK", "TH", "TR", "UA", "US"]; /** * Validates if a value is a valid ULID (Universally Unique Lexicographically Sortable Identifier). * ULIDs are 26-character strings that are lexicographically sortable and URL-safe. * * @param value - The value to validate * @returns True if value is a valid ULID * * @example * helpers.isULID('01ARZ3NDEKTSV4RRFFQ69G5FAV') // true * helpers.isULID('invalid-ulid') // false * helpers.isULID('7ZZZZZZZZZZZZZZZZZZZZZZZZZ') // true (max valid ULID) * helpers.isULID('8AAAAAAAAAAAAAAAAAAAAAAAAA') // false (overflow) */ isULID(value: unknown): boolean; /** * Validates if a value is a valid hexadecimal color code. * Requires the '#' prefix and supports 3, 6, or 8 character hex codes. * * @param value - The string to validate as a hex color * @returns True if value is a valid hex color code * * @example * helpers.isHexColor('#FF0000') // true (red) * helpers.isHexColor('#f00') // true (short red) * helpers.isHexColor('#FF000080') // true (red with alpha) * helpers.isHexColor('FF0000') // false (missing #) * helpers.isHexColor('#GGGGGG') // false (invalid hex) */ isHexColor: (value: string) => boolean; /** * Validates if a URL has valid DNS records (A or AAAA records). * This performs an actual DNS lookup to verify the domain exists. * * @param url - The URL to check for DNS records * @returns Promise resolving to true if DNS records exist * * @example * await helpers.isActiveURL('https://example.com') // true * await helpers.isActiveURL('https://nonexistent-domain-12345.com') // false * * This function requires network access and may be slow. * Consider caching results for better performance. */ isActiveURL: (url: string) => Promise; /** * Checks if all elements in an array are unique. * For arrays of objects, you can specify one or more fields that must be unique. * Null and undefined values are ignored during uniqueness checks. * * @param dataSet - The array to check for uniqueness * @param fields - Optional field name(s) to check for uniqueness in object arrays * * @example * // Check uniqueness in primitive array * helpers.isDistinct([1, 2, 4, 5]) // true * helpers.isDistinct([1, 2, 2, 5]) // false * * @example * // Null and undefined values are ignored * helpers.isDistinct([1, null, 2, null, 4, 5]) // true * * @example * // Check uniqueness by single field in object array * helpers.isDistinct([ * { email: 'foo@bar.com', name: 'foo' }, * { email: 'baz@bar.com', name: 'baz' } * ], 'email') // true * * @example * // Check uniqueness by multiple fields (composite key) * helpers.isDistinct([ * { email: 'foo@bar.com', tenant_id: 1, name: 'foo' }, * { email: 'foo@bar.com', tenant_id: 2, name: 'baz' } * ], ['email', 'tenant_id']) // true (same email, different tenant) */ isDistinct: (dataSet: any[], fields?: string | string[]) => boolean; /** * Retrieves a nested value from the validation context. * Supports both dot notation for deep access and direct parent access. * * @param key - The key or dot-notation path to the value * @param field - The field context containing data and parent references * @returns The value at the specified path, or undefined if not found * * @example * // Dot notation for nested access * helpers.getNestedValue('user.profile.name', field) * * // Direct parent access * helpers.getNestedValue('confirmPassword', field) * * // Deep object access * helpers.getNestedValue('config.database.host', field) */ getNestedValue(key: string, field: FieldContext): any; /** * Converts all properties of an object schema to optional. * This is useful when you want to make all fields in a schema optional * at once, such as for update operations where all fields are optional. * * @param props - The object with schema properties * * @example * const createUserSchema = { * name: vine.string(), * email: vine.string().email(), * age: vine.number() * } * * // Make all fields optional for updates * const updateUserSchema = helpers.optional(createUserSchema) */ optional>(props: Props): Prettify>; };