npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

validata

v5.0.7

Published

Type safe data validation and sanitization

Downloads

2,987

Readme

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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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:

  • StringFormat.ULID() - https://github.com/ulid/spec
  • StringFormat.UUID() - https://www.ietf.org/rfc/rfc4122.txt
  • StringFormat.password(requirements: PasswordRequirements) - Password format with minimum requirements

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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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, path?: Path[]) => boolean | Issue[] - custom validation function; if false or Issue[] 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;
// }