'use strict';
const Rac = require('../Rac');
/**
* Internal utilities.
* @namespace utils
*/
/**
* Asserts that all passed parameters are objects or primitives. If any
* parameter is `null` or `undefined` a `{@link Rac.Exception.failedAssert}`
* is thrown.
*
* @param {...(Object|primitive)} parameters
* @returns {boolean}
*
* @function assertExists
* @memberof utils#
*/
exports.assertExists = function(...parameters) {
parameters.forEach((item, index) => {
if (item === null) {
throw Rac.Exception.failedAssert(
`Found null, expecting element to exist at index ${index}`);
}
if (item === undefined) {
throw Rac.Exception.failedAssert(
`Found undefined, expecting element to exist at index ${index}`);
}
});
}
/**
* Asserts that all `elements` are objects or the given `typeo`, otherwise a
* `{@link Rac.Exception.failedAssert}` is thrown.
*
* @param {function} type
* @param {...Object} elements
*
* @returns {boolean}
*
* @function assertType
* @memberof utils#
*/
exports.assertType = function(type, ...elements) {
elements.forEach(item => {
if (!(item instanceof type)) {
throw Rac.Exception.failedAssert(
`Element is unexpected type - element:${item} element-type:${typeName(item)} expected-type-name:${type.name}`);
}
});
}
/**
* Asserts that all `elements` are number primitives and not NaN, otherwise
* a `{@link Rac.Exception.failedAssert}` is thrown.
*
* @param {...number} elements
* @returns {boolean}
*
* @function assertNumber
* @memberof utils#
*/
exports.assertNumber = function(...elements) {
elements.forEach(item => {
if (typeof item !== 'number' || isNaN(item)) {
throw Rac.Exception.failedAssert(
`Element is unexpected type, expecting number primitive - element:${item} element-type:${typeName(item)}`);
}
});
}
/**
* Asserts that all `elements` are string primitives, otherwise
* a `{@link Rac.Exception.failedAssert}` is thrown.
*
* @param {...string} elements
* @returns {boolean}
*
* @function assertString
* @memberof utils#
*/
exports.assertString = function(...elements) {
elements.forEach(item => {
if (typeof item !== 'string') {
throw Rac.Exception.failedAssert(
`Element is unexpected type, expecting string primitive - element:${item} element-type:${typeName(item)}`);
}
});
}
/**
* Asserts that all `elements` are boolean primitives, otherwise a
* `{@link Rac.Exception.failedAssert}` is thrown.
*
* @param {...boolean} elements
* @returns {boolean}
*
* @function assertBoolean
* @memberof utils#
*/
exports.assertBoolean = function(...elements) {
elements.forEach(item => {
if (typeof item !== 'boolean') {
throw Rac.Exception.failedAssert(
`Element is unexpected type, expecting boolean primitive - element:${item} element-type:${typeName(item)}`);
}
});
}
/**
* Returns the constructor name of `obj`, or its type name.
* Convenience function for debugging and errors.
*
* @param {object} obj - An `Object` to get its type name
* @returns {string}
*
* @function typeName
* @memberof utils#
*/
function typeName(obj) {
if (obj === undefined) { return 'undefined'; }
if (obj === null) { return 'null'; }
if (typeof obj === 'function' && obj.name != null) {
return obj.name == ''
? `function`
: `function:${obj.name}`;
}
return obj.constructor.name ?? typeof obj;
}
exports.typeName = typeName;
/**
* Adds a constant to the given object, the constant is not enumerable and
* not configurable.
*
* @function addConstantTo
* @memberof utils#
*/
exports.addConstantTo = function(obj, propName, value) {
Object.defineProperty(obj, propName, {
enumerable: false,
configurable: false,
writable: false,
value: value
});
}
/**
* Returns a string of `number` format using fixed-point notation or the
* complete `number` string.
*
* @param {number} number - The number to format
* @param {?number} [digits] - The amount of digits to print, or `null` to
* print all digits.
*
* @returns {string}
*
* @function cutDigits
* @memberof utils#
*/
exports.cutDigits = function(number, digits = null) {
return digits === null
? number.toString()
: number.toFixed(digits);
}