index.js

'use strict'

/**
 * exists will return true when `propertyName` is a property of `obj`, else false is returned.
 * You can also check for the existence of a property contained in a nested object by chaining
 * the properties.  Simply use a dot notation in the `propertyName` to specify the chain.
 *
 * @param {Object} obj `Object` to check
 * @param {String} propertyName the name of the property to be checked for.
 * @returns {Boolean} Returns true if `propertyName` is a property of `obj`.
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * let obj = { a: 1, b: { c: 0}}
 * ub.exists(obj,'a') //returns true
 * ub.exists(obj,'b.c') // returns true
 */
function exists(obj, propertyName) {
    let properties = (propertyName || '').split('.')
    while(properties.length){
        let pname = properties.shift()
        if(isObject(obj)){
            if(properties.length){
                return exists(obj[pname], properties.join('.'))
            } else {
                return Object.prototype.hasOwnProperty.call(obj, pname)
            }
        }
    }
    return false
}

/**
 * isBoolean tests if `variable` is of type Boolean
 *
 * @param {*} variable value to test
 * @returns {Boolean} Returns true if `variable` is a boolean
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.isBoolean(false) // returns true
 */
function isBoolean(variable) {
    return typeof variable === 'boolean'
}

/**
 * isString tests if `variable` is a String
 *
 * @param {*} variable value to test
 * @returns {Boolean} Returns true if `variable` is a String
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.isString('my string') // returns true
 */
function isString(variable) {
    return typeof variable === 'string'
}

/**
 * isJSON tests if `str` is valid JSON.
 *
 * @param {String} str String to test
 * @returns {Boolean}  Returns true if string is valid JSON
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.isJSON('{"abc":true}') // returns true
 * ub.isJSON('{"abc":true')  // returns false
 * ub.isJSON({"abc":true})   // returns false
 */
function isJSON(str) {
    try {
        if(isString(str)){
            return (JSON.parse(str) && !!str)
        } else {
            return false
        }
    } catch (e) {
        return false
    }
}

/**
 * isNull tests if `n` is `null` or `undefined`.
 *
 * @param {*} n value to test
 * @returns {Boolean} Returns true if the value is `null` or `undefined`
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.isNull(null)      // returns true
 * ub.isNull(undefined) // returns true
 * ub.isNull({})        // returns false
 */
function isNull(n) {
    return n == null
}

/**
 * isObject tests if `variable` is an object
 *
 * @param {*} variable value to test
 * @returns {Boolean} Returns true if `variable` is an object
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.isObject('{"abc":true}') // returns false
 * ub.isObject({"abc":true})   // returns true
 */
function isObject(variable) {
    let rv = !isNull(variable)
    if(rv){
        rv = typeof variable === 'object' && !Array.isArray(variable)
    }
    return rv
}

/**
 * nvl lets you replace null or undefined with a value of your choice. If `n` is
 * null or undefined, * then nvl returns `val`. If `n` is not null or undefined,
 * then nvl returns `n`.
 *
 * @param {*} n - The value you want to test for null or undefined
 * @param (*) val - The value you want returned when `n` is null or undefined
 * @returns {*} Returns `val` when `n` is null or undefined
 * @example
 * const ub = require('@nuskin/uncle-buck')
 *
 * ub.nvl(null,0)  // returns 0
 * ub.nvl('mystring','yourstring') // returns 'mystring'
 */
function nvl(n, val) {
    if (isNull(n)) {
        return val
    }
    return n
}

/**
 * sleep will suspend execution for an interval amount of time that is set in
 * milliseconds.  The default is 1 second.
 *
 * @param {Number} ms The number of milliseconds to sleep for
 * @example
 * const { sleep } = require('@nuskin/uncle-buck')
 * const myfunc = async () => {
 *   await sleep(2000) // sleep for 2 seconds
 *   // do something
 * }
 *
 * myfunc()
 */
function sleep(ms = 1000) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

/**
 * stringToJSON will convert a JSON string to a JavaScript object and return it. If
 * `value` is already a JavaScript object, the object is simply returned. An error is thrown
 * if `value` is not parseable or a JavaScript object.
 * @param {*} value The value to evaluate
 * @throws {Error} Thrown if `value` is not a valid JSON string or a JavaScript object.
 * @returns {object} The JavaScript object parsed from the JSON string.
 * @example
 * const { stringToJSON } = require('@nuskin/uncle-buck')
 * const jsonStr = JSON.stringify({ a: 1, b: '2', c: null })
 * const obj = stringToJSON(jsonStr)
 * 
 * console.log(obj)
 */
const stringToJSON = (value) => {
    if (isJSON(value)) {
        value = JSON.parse(value)
    } else if (!isObject(value)) {
        throw new Error(`Input is not a JSON string or a JavaScript object; received type: ${typeof value}`)
    }
    return value
}

module.exports = {
    exists,
    isBoolean,
    isJSON,
    isNull,
    isObject,
    isString,
    nvl,
    sleep,
    stringToJSON
}