valirator
Version:
Powerful javascript by schema validation tool
391 lines (347 loc) • 6.93 kB
JavaScript
/**
* @description
* Empty function
*/
export function noop() {}
/**
* @description
* Check if type
*
* @param obj
* @param {string} typeStr - type string like: '[object Object]', '[object Array]' and etc
* @returns {boolean}
*/
export function isType(obj, typeStr) {
return Object.prototype.toString.call(obj) === typeStr;
}
/**
* @description
* Check if is Object
*
* @param obj
* @returns {boolean}
*/
export function isObject(obj) {
return isType(obj, '[object Object]');
}
/**
* @description
* Check if is Array
*
* @param obj
* @returns {boolean}
*/
export function isArray(obj) {
return isType(obj, '[object Array]');
}
/**
* @description
* Check if is Function
*
* @param obj
* @returns {boolean}
*/
export function isFunction(obj) {
return isType(obj, '[object Function]');
}
/**
* @description
* Check if is String
*
* @param obj
* @returns {boolean}
*/
export function isString(obj) {
return isType(obj, '[object String]');
}
/**
* @description
* Check if is Date
*
* @param obj
* @returns {boolean}
*/
export function isDate(obj) {
return isType(obj, '[object Date]');
}
/**
* @description
* Check if is Number
*
* @param obj
* @returns {boolean}
*/
export function isNumber(obj) {
return isType(obj, '[object Number]') && !isNaN(obj);
}
/**
* @description
* Check if is Boolean
*
* @param obj
* @returns {boolean}
*/
export function isBoolean(obj) {
return isType(obj, '[object Boolean]');
}
/**
* @description
* Check if is Empty
* Empty string -> true
* Empty array -> true
* Empty object -> true
*
* Anything else -> false
*
* @param obj
* @returns {boolean}
*/
export function isEmpty(obj) {
return obj === '' || (isArray(obj) && obj.length === 0) || (isObject(obj) && Object.keys(obj).length === 0);
}
/**
* @description
* Check if is Null
*
* @param obj
* @returns {boolean}
*/
export function isNull(obj) {
return isType(obj, '[object Null]');
}
/**
* @description
* Check if is Undefined
*
* @param obj
* @returns {boolean}
*/
export function isUndefined(obj) {
return isType(obj, '[object Undefined]');
}
/**
* @description
* Check is is Null or Undefined
*
* @param obj
* @returns {boolean}
*/
export function isNullOrUndefined(obj) {
return isNull(obj) || isUndefined(obj);
}
/**
* @description
* Check is object is defined (not null, not undefined, not empty string, object or array
*
* @param obj
* @returns {boolean}
*/
export function isDefined(obj) {
return !(isNullOrUndefined(obj) || isEmpty(obj));
}
/**
* @description
* Safe convert to String
*
* @param obj
* @returns {string}
*/
export function toString(obj) {
return String(obj);
}
/**
* @description
* Safe indexOf
*
* @param array
* @param value
* @returns {Number}
*/
export function indexOf(array, value) {
if (!isArray(array)) {
return -1;
}
return array.indexOf(value);
}
/**
* @description
* Safe check if value in array
*
* @param array
* @param value
* @returns {boolean}
*/
export function inArray(array, value) {
return isArray(array) && indexOf(array, value) !== -1;
}
/**
* @description
* Cast item to array
*
* @param array
* @returns {Array}
*/
export function castArray(array) {
return isArray(array) ? array : [array];
}
/**
* @description
* Safe check is object has property
*
* @param obj
* @param {string} prop - property name
* @returns {boolean}
*/
export function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
/**
* @description
* Safe set prototype
*
* @param obj
* @param proto
* @returns {Object}
*/
export function setPrototypeOf(obj, proto) {
if (Object.setPrototypeOf) {
return Object.setPrototypeOf(obj, proto);
}
obj.__proto__ = proto;
return obj;
}
/**
* @description
* Safe get prototype
*
* @param obj
* @returns {*}
*/
export function getPrototypeOf(obj) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
}
return obj.__proto__;
}
/**
* @description
* Get property value
*
* @param {Object} obj
* @param {string} path
* @param fallback - fallback value
* @returns {*}
*/
export function getProperty(obj, path = '', fallback = null) {
let result = obj;
let prop = toString(path);
if (path === '') {
return result;
}
if (!isDefined(obj)) {
return fallback;
}
do {
if (isObject(result)) {
if (hasOwnProperty(result, prop)) {
return result[prop];
}
const [first, ...rest] = prop.split('.');
result = result[first];
prop = rest.join('.');
} else {
break;
}
} while (prop);
if (result === null || result === undefined) {
return fallback;
}
return result;
}
/**
* @description
* Get property override in chain
*
* @param {Object} context
* @param {string} prop
* @returns {*}
*/
export function getPropertyOverride(context, prop) {
if (!context) {
return false;
}
return isFunction(context[prop]) ? context[prop] : getPropertyOverride(getPrototypeOf(context), prop);
}
/**
* @description
* Handle Promise or PromiseLike object
*
* @param {Promise|PromiseLike} promise
* @returns {Promise|PromiseLike}
*/
export function handlePromise(promise) {
if (promise && promise.then) {
return promise;
}
return {
then: cb => handlePromise(cb(promise)),
catch: noop,
value: promise,
isPromiseLike: true,
};
}
/**
* @description
* Handle array of Promises or PromiseLike objects
*
* @param promises
* @returns {Promise|PromiseLike}
*/
export function handlePromises(promises) {
const isAnyPromiseNotPromiseLike = promises.some(promise => promise && promise.then && !promise.isPromiseLike);
if (isAnyPromiseNotPromiseLike) {
return Promise.all(promises);
}
const results = promises.map(promise => promise.value);
return handlePromise(results);
}
/**
* @description
* Format message for rule
*
* @param {string|Function} message - message template
* @param {*} actual - actual value
* @param {*} expected - expected value
* @param {string} property - validating property
* @param {Object} obj - validating object
* @param {Function} rule - validating function
* @returns {Promise<string>|PromiseLike<string>}
*/
export function formatMessage(
message = 'No default message for rule "%{rule}"',
actual,
expected,
property,
obj,
rule,
) {
const lookup = {
actual,
expected,
property,
rule,
};
const formattedMessage = isFunction(message)
? message(actual, expected, property, obj)
: isString(message)
? message.replace(/%\{([a-z]+)\}/gi, (_, match) => lookup[match.toLowerCase()] || '')
: message;
return handlePromise(formattedMessage);
}
/**
* @typedef {Object} PromiseLike
* @property {Function} then
* @property {Function} catch
* @property {*} value
* @property {boolean} isPromiseLike
*/