"use strict"; /* TODO: toDisplay conversion between unit scales (eg. IEC -> metric bytes) */ const util = require("util"); const chalk = require("chalk"); function capitalize(string) { return string[0].toUpperCase() + string.slice(1); } module.exports = function makeUnits(unitSpecs) { let resultObject = {}; unitSpecs.forEach((spec, i) => { let proto = { [util.inspect.custom]: function (_depth, options) { let inspectString = ` ${this.amount} ${this.unit}`; if (options.colors === true) { return chalk.cyan(inspectString); } else { return inspectString; } }, toString: function () { /* TODO: Make this auto-convert */ return `${this.amount} ${this.unit}`; }, } unitSpecs.forEach((otherSpec, otherI) => { let factor = 1; if (otherI < i) { /* Convert downwards, to smaller units (== larger numbers) */ unitSpecs.slice(otherI, i).reverse().forEach((specStep) => { factor = factor * specStep.toNext; }); } else if (otherI > i) { /* Convert upwards, to larger units (== smaller numbers) */ unitSpecs.slice(i, otherI).forEach((specStep) => { factor = factor / specStep.toNext; }); } proto[`to${capitalize(otherSpec.unit)}`] = function () { return resultObject[otherSpec.unit](this.amount * factor); }; }); resultObject[spec.unit] = function createUnit(value) { if (typeof value !== "number") { throw new Error("Value must be numeric"); } else { return Object.assign(Object.create(proto), { unit: spec.unit, amount: value }); } } }); return resultObject; };