Nuclear Powered Marshmallows

    validata
    TypeScript icon, indicating that this package has built-in type declarations

    4.0.18 • Public • Published

    Validata

    Type safe data validation and sanitization.

    See also

    Getting started

    npm i validata

    Basic usage

    import { asString, isObject, isString, maybeString } from 'validata';
    
    interface Sample {
      maybeString: string | undefined;
      myString: string;
      numericString: string;
    }
    
    const sample = isObject<Sample>({
      maybeString: maybeString(), // will allow string data type or sanitize to undefined
      myString: isString(), // will allow only string data type
      numericString: asString(), // will allow string or attempt to convert to string
    });
    
    console.log(
      JSON.stringify(
        sample.process({
          maybeString: 123,
          myString: 123,
          numericString: 123,
        })
      )
    );
    
    /*
    FAIL: Outputs:
    {"issues":[{"path":["maybeString"],"value":123,"reason":"incorrect-type","info":{"expectedType":"string"}},{"path":["myString"],"value":123,"reason":"incorrect-type","info":{"expectedType":"string"}}]}
    */
    
    console.log(
      JSON.stringify(
        sample.process({
          myString: '123',
          numericString: 123,
        })
      )
    );
    
    /*
    SUCCESS: Outputs:
    {"value":{"myString":"123","numericString":"123"}}
    */

    API

    Checks:

    • isAny
    • Array
      • isArray
      • maybeArray
      • asArray
      • maybeAsArray
    • Boolean
      • isBoolean
      • maybeBoolean
      • asBoolean
      • maybeAsBoolean
    • Date
      • isDate
      • maybeDate
      • asDate
      • maybeAsDate
    • Enum
      • isEnum
      • maybeEnum
      • asEnum
      • maybeAsEnum
    • Number
      • isNumber
      • maybeNumber
      • asNumber
      • maybeAsNumber
    • Object
      • isObject
      • maybeObject
      • asObject
      • maybeAsObject
    • Record
      • isRecord
      • maybeRecord
      • asRecord
      • maybeAsRecord
    • String
      • isString
      • maybeString
      • asString
      • maybeAsString
    • Tuple
      • isTuple
      • maybeTuple
    • Url
      • isUrl
      • maybeUrl
      • asUrl
      • maybeAsUrl
    • isNullable
    • asNullable

    Types

    • TypeOf

    Work is done by a typed ValueProcessor, as returned byisObject<T>() or asNumber().

    interface ValueProcessor<T> {
      process(value: unknown): Result<T>;
    }

    The process() method returns a Result<T>.The Result is either a list of issues (meaning validation failures) or the accepted value (it may be coerced/altered from the original).

    type Result<T> = ValueResult<T> | IssueResult;
    
    interface ValueResult<T> {
      value: T;
    }
    
    interface IssueResult {
      issues: Issue[];
    }

    Naming conventions

    is... e.g. isNumber

    • if the value is of the type it will be accepted
    • null or undefined cause an issue
    • otherwise it will cause an issue

    maybe... e.g. maybeNumber

    • if the value is of the type it will be accepted
    • null or undefined it will sanitized to undefined
    • otherwise it will cause an issue

    as... e.g. asNumber

    • if the value is of the type it will be accepted
    • null or undefined converted to default, if provided, or cause an issue
    • if the value can be converted to the type, it will be converted and used
    • if the value is cannot be converted the default will be used if provided
    • otherwise it will cause an issue

    maybeAs... e.g. maybeAsNumber

    • if the value is of the type it will be accepted
    • null or undefined converted to default, if provided, or sanitized to undefined
    • if the value can be converted to the type it will be converted and used
    • if the value is cannot be converted the default will be used if provided
    • otherwise it will cause an issue // * otherwise it will be sanitized to undefined

    Checks

    isArray, maybeArray, asArray, maybeAsArray

    Usage:

    isArray(itemProcessor, options);
    maybeArray(itemProcessor, options);
    asArray(itemProcessor, options);
    maybeAsArray(itemProcessor, options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • coerceMaxLength? number - if there are more items than this, some will be removed
    • maxLength?: number - if there are more items than this, it's an error max-length
    • minLength?: number - if there are less items than this, it's an error min-length
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    Example:

    isArray<number>(isNumber({ max: 20, min: 10 }), { coerceMaxLength: 7 });

    isBoolean, maybeBoolean, asBoolean, maybeAsBoolean

    Usage:

    isBoolean(options);
    maybeBoolean(options);
    asBoolean(options);
    maybeAsBoolean(options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    isDate, maybeDate, asDate, maybeAsDate

    Usage:

    isDate(options);
    maybeDate(options);
    asDate(options);
    maybeAsDate(options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • format - custom date format used in conversion from string to Date see Luxon formatting
    • maxFuture?: Duration - if the value is after this duration into the future, it's an error max-future
    • maxPast?: Duration - if the value is before this duration into the past, it's an error max-past
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    isEnum, maybeEnum, asEnum, maybeAsEnum

    Usage:

    isEnum(Enum);
    maybeNumber(Enum);
    asNumber(Enum);
    maybeAsNumber(Enum);

    Example:

    // String based Enum
    enum EnumOne {
      A = 'A',
      B = 'B',
      C = 'C',
    }
    isEnum(EnumOne); // Allows "A", "B", "C"
    
    // Number based Enum
    enum EnumTwo {
      A,
      B,
      C,
    }
    isEnum(EnumTwo); // Allows 0, 1, 2
    
    // Converting to an Enum using it's key or value
    asEnum(EnumTwo); // Allows 1, 2, 3, "A", "B", "C"
    asEnum(EnumTwo).process('A'));       // { value: 0 }
    asEnum(EnumTwo).process(0));         // { value: 0 }
    asEnum(EnumTwo).process(EnumOne.A)); // { value: 0 }

    isNumber, maybeNumber, asNumber, maybeAsNumber

    Usage:

    isNumber(options);
    maybeNumber(options);
    asNumber(options);
    maybeAsNumber(options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • coerceMin?: number - if the value is less than this, it will be set to this value
    • coerceMax?: number - if the value is more than this, it will be set to this value
    • max?: number - if the value is than this, it's an error max
    • min?: number - if the value is than this, it's an error min
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    isObject, maybeObject, asObject, maybeAsObject

    Usage:

    isObject(contract, options);
    maybeObject(contract, options);
    asObject(contract, options); // will parse string JSON as object
    maybeAsObject(contract, options); // will parse string JSON as object
    // where `contract` is Record<string, ValueProcessor>

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    Example:

    interface Sample {
      myString: string;
      maybeString: string | undefined;
      numericString: string;
    }
    
    const check = isObject<Sample>({
      maybeString: maybeString(), // if these don't match the interface TypeScript will error
      myString: isString(),
      numericString: asString(),
    });

    isRecord, maybeRecord, asRecord, maybeAsRecord

    Usage:

    isRecord<V>(check, options);
    maybeRecord<V>(check, options);
    asRecord<V>(check, options);
    maybeAsRecord<V>(check, options);
    // where `check` is ValueProcessor<V>, and Record<string, V> is the type to be processed

    Options:

    • keyRegex?: RegExp - regular expression to check each key name, or it's an error key-regex
    • maxKeys?: number - if the number of keys in the object is more than this, it's an error max-keys
    • minKeys?: number - if the number of keys in the object is more than this, it's an error max-keys
    • validator?: (value: Record<string, V>, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    Example:

    const check = isRecord(isString());
    check.process({ foo: 'bar' });

    isString, maybeString, asString, maybeAsString

    Usage:

    isString(options);
    maybeString(options);
    asString(options);
    maybeAsString(options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • limitLength?: number - if the length of the string is more than this, it will be truncated to this length
    • padStart?: StringPadding - pad the start of the string up to given value
    • padEnd?: StringPadding - pad the end of the string up to given value
    • trim?: 'start' | 'end' | 'both' | 'none' - removes the leading and/or trailing white space and line terminator characters from the string
    • regex?: RegExp - regular expression that must be matched, or it's an error regex
    • maxLength?: number - if the length of the string is more than this, it's an error max-length
    • minLength?: number - if the length of the string is less than this, it's an error min-length
    • format:? StringFormatCheck - extension point for string format checking, if check fails it's an issue format with info.expectedFormat set
    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    StringPadding:

    • length: number - will pad up until this length
    • padWith: string - the value to pad with

    StringFormat:

    Example:

    const check = isString({
      limitLength: 6,
      padStart: { length: 6, padWith: '-' },
    });
    const check = isString({
      format: StringFormat.ULID(),
    });
    const check = isString({
      format: StringFormat.password({
        minLength: 10, // default=8
        numberChars: 2, // default=1
        lowerCaseChars: 2, // default=1
        upperCaseChars: 2, // default=1
        specialChars: 0, // default=1
      }),
    });
    // change case
    import { pascalCase } from 'change-case';
    
    const check = isString({
      transform: pascalCase,
    });
    const check = isString({
      maxLength: 10,
      minLength: 8,
      regex: /^[A-Z]+$/,
    });
    import validator from 'validator';
    
    const check = isString({
      validator: validator.isEmail,
      validatorOptions: { allow_display_name: true },
    });

    isTuple, maybeTuple

    Usage:

    isTuple(options);
    maybeTuple(options);

    Options:

    • validator?: (value: T, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    Example:

    type MyTuple = [number, string];
    const check = isTuple([isNumber({ max: 9, min: 3 }), isString({ regex: /^\w+$/ })]);

    isUrl, maybeUrl, asUrl, maybeAsUrl

    Working with Node's URL object

    Usage:

    isUrl(options);
    maybeUrl(options);
    asUrl(options);
    maybeAsUrl(options);

    Options:

    • converter?: (value: unknown, options?: any) => T | undefined - custom converter function, if not defined or undefined is returned then built in conversions will be run
    • convertOptions - options to pass to the converter
    • setProtocol?: string - will coerce the protocol to the given value, if present
    • protocol?: string - given URL must have this protocol, or it's an error invalid-protocol
    • validator?: (value: URL, options?: any) => boolean - custom validation function; if false is returned it's an error
    • validatorOptions?: any - options to pass to the validator

    Example:

    const check = asUrl({
      protocol: 'https',
    });

    isNullable

    Any other check can be wrapped into isNullable to accept null.

    Example:

    const check = isNullable(isString({ min: 3 }));

    asNullable

    Any other check can be wrapped into asNullable to accept null.

    Options:

    • default - can be null or return type or a function with return type of the wrapped check

    Example:

    const check = asNullable(isString({ min: 3 }));
    const check = asNullable(isString({ min: 3 }), { default: null });
    const check = asNullable(isString({ min: 3 }), { default: 'text' });
    const check = asNullable(isString({ min: 3 }), { default: () => 'text' });

    Types

    Types can be extracted from a ValueProcessor or a Contract-like pure object.

    const sampleContract = {
      maybeString: maybeString(),
      myString: isString(),
      numericString: asString(),
    };
    const sample = isObject(sampleContract);
    
    // both are same as
    export type SampleContract = TypeOf<typeof sample>;
    export type Sample = TypeOf<typeof sample>;
    // interface Sample {
    //   myString: string;
    //   maybeString: string | undefined;
    //   numericString: string;
    // }

    Install

    npm i validata

    DownloadsWeekly Downloads

    1,162

    Version

    4.0.18

    License

    MIT

    Unpacked Size

    615 kB

    Total Files

    149

    Last publish

    Collaborators

    • gregbacchus