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(),
myString: isString(),
numericString: asString(),
});
console.log(
JSON.stringify(
sample.process({
maybeString: 123,
myString: 123,
numericString: 123,
})
)
);
console.log(
JSON.stringify(
sample.process({
myString: '123',
numericString: 123,
})
)
);
Upgrading to v6
V6 of validata
has been marked as a breaking change as it moves the packages luxon
, @types/luxon
and validata
from dependencies to peerDependencies. This better supports different package versions.
If you are using any of the validators that use these packages, you will need to install them directly into your project:
pnpm add luxon @types/luxon validata
API
Checks:
- isAny
- Array
- isArray
- maybeArray
- asArray
- maybeAsArray
- Boolean
- isBoolean
- maybeBoolean
- asBoolean
- maybeAsBoolean
- Date
- isDate
- maybeDate
- asDate
- maybeAsDate
- DateTime
- isDateTime
- maybeDateTime
- asDateTime
- maybeAsDateTime
- 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
- Url
- isUrl
- maybeUrl
- asUrl
- maybeAsUrl
- isNullable
- asNullable
Types
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
NOTE: Requires peer dependencies luxon
and @types/luxon
.
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
isDateTime
, maybeDateTime
, asDateTime
, maybeAsDateTime
Similar to above but for luxon DateTime.
NOTE: Requires peer dependencies luxon
and @types/luxon
.
Usage:
isDateTime(options);
maybeDateTime(options);
asDateTime(options);
maybeAsDateTime(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:
enum EnumOne {
A = 'A',
B = 'B',
C = 'C',
}
isEnum(EnumOne);
enum EnumTwo {
A,
B,
C,
}
isEnum(EnumTwo);
asEnum(EnumTwo);
asEnum(EnumTwo).process('A'));
asEnum(EnumTwo).process(0));
asEnum(EnumTwo).process(EnumOne.A));
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);
maybeAsObject(contract, 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
Example:
interface Sample {
myString: string;
maybeString: string | undefined;
numericString: string;
}
const check = isObject<Sample>({
maybeString: maybeString(),
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);
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:
Example:
const check = isString({
limitLength: 6,
padStart: { length: 6, padWith: '-' },
});
const check = isString({
format: StringFormat.ULID(),
});
const check = isString({
format: StringFormat.password({
minLength: 10,
numberChars: 2,
lowerCaseChars: 2,
upperCaseChars: 2,
specialChars: 0,
}),
});
const check = isString({
format: StringFormat.email({ allowDisplayName: false }),
});
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);
export type SampleContract = TypeOf<typeof sample>;
export type Sample = TypeOf<typeof sample>;