
Security News
MCP Community Begins Work on Official MCP Metaregistry
The MCP community is launching an official registry to standardize AI tool discovery and let agents dynamically find and install MCP servers.
Type safe data validation and sanitization.
See also
npm i validata
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"}}
*/
Checks:
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[];
}
is...
e.g. isNumber
null
or undefined
cause an issuemaybe...
e.g. maybeNumber
null
or undefined
it will sanitized to undefinedas...
e.g. asNumber
null
or undefined
converted to default, if provided, or cause an issuemaybeAs...
e.g. maybeAsNumber
null
or undefined
converted to default, if provided, or sanitized to undefinedisArray
, 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 runconvertOptions
- options to pass to the convertercoerceMaxLength? number
- if there are more items than this, some will be removedmaxLength?: 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 errorvalidatorOptions?: any
- options to pass to the validatorExample:
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 runconvertOptions
- options to pass to the convertervalidator?: (value: T, options?: any, path?: Path[]) => boolean | Issue[]
- custom validation function; if false or Issue[] is returned it's an errorvalidatorOptions?: any
- options to pass to the validatorisDate
, 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 runconvertOptions
- options to pass to the converterformat
- custom date format used in conversion from string
to Date
see Luxon formattingmaxFuture?: 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 errorvalidatorOptions?: any
- options to pass to the validatorisEnum
, 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 runconvertOptions
- options to pass to the convertercoerceMin?: number
- if the value is less than this, it will be set to this valuecoerceMax?: number
- if the value is more than this, it will be set to this valuemax?: 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 errorvalidatorOptions?: any
- options to pass to the validatorisObject
, 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 runconvertOptions
- options to pass to the convertervalidator?: (value: T, options?: any, path?: Path[]) => boolean | Issue[]
- custom validation function; if false or Issue[] is returned it's an errorvalidatorOptions?: any
- options to pass to the validatorExample:
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 errorvalidatorOptions?: any
- options to pass to the validatorExample:
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 runconvertOptions
- options to pass to the converterlimitLength?: number
- if the length of the string is more than this, it will be truncated to this lengthpadStart?: StringPadding
- pad the start of the string up to given valuepadEnd?: StringPadding
- pad the end of the string up to given valuetrim?: 'start' | 'end' | 'both' | 'none'
- removes the leading and/or trailing white space and line terminator characters from the stringregex?: 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
setvalidator?: (value: T, options?: any, path?: Path[]) => boolean | Issue[]
- custom validation function; if false or Issue[] is returned it's an errorvalidatorOptions?: any
- options to pass to the validatorStringPadding:
length: number
- will pad up until this lengthpadWith: string
- the value to pad withStringFormat:
StringFormat.ULID()
- https://github.com/ulid/specStringFormat.UUID()
- https://www.ietf.org/rfc/rfc4122.txtStringFormat.password(requirements: PasswordRequirements)
- Password format with minimum requirementsExample:
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 errorvalidatorOptions?: any
- options to pass to the validatorExample:
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 runconvertOptions
- options to pass to the convertersetProtocol?: string
- will coerce the protocol to the given value, if presentprotocol?: 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 errorvalidatorOptions?: any
- options to pass to the validatorExample:
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 checkExample:
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 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;
// }
FAQs
Type safe data validation and sanitization
The npm package validata receives a total of 570 weekly downloads. As such, validata popularity was classified as not popular.
We found that validata demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The MCP community is launching an official registry to standardize AI tool discovery and let agents dynamically find and install MCP servers.
Research
Security News
Socket uncovers an npm Trojan stealing crypto wallets and BullX credentials via obfuscated code and Telegram exfiltration.
Research
Security News
Malicious npm packages posing as developer tools target macOS Cursor IDE users, stealing credentials and modifying files to gain persistent backdoor access.