From e8e3571f8e02cb67ba3560f4eaf86201a7e31d57 Mon Sep 17 00:00:00 2001 From: Orlando Date: Thu, 2 Nov 2023 20:36:25 +0000 Subject: [PATCH] Add formatters --- CHANGELOG.md | 6 ++++++ README.md | 8 ++++++-- package.json | 3 ++- src/formatters/formatNumber.test.ts | 31 +++++++++++++++++++++++++++++ src/formatters/formatNumber.ts | 22 ++++++++++++++++++++ src/formatters/index.ts | 1 + src/helpers/arrayDiff.ts | 1 + src/helpers/truncate.ts | 4 ++-- src/index.ts | 1 + src/validators/isNumber.test.ts | 30 ++++++++++++++-------------- src/validators/isNumber.ts | 20 ++++++++++++++----- 11 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 src/formatters/formatNumber.test.ts create mode 100644 src/formatters/formatNumber.ts create mode 100644 src/formatters/index.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 12ebf3e..87ce0b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # deverything +## 0.34.0 + +### Minor Changes + +- formatters + ## 0.33.0 ### Minor Changes diff --git a/README.md b/README.md index 4178763..c507348 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ Contributions always welcome! - `isInt()` - `isEven()` - `isOdd()` - - `isPositive()` - - `isNegative()` + - `isPositiveInt()` + - `isNegativeInt()` - `isNumeric()` - ⭐ `isObject()` if it's a js plain Object - `isPromise()` @@ -90,6 +90,10 @@ Contributions always welcome! - `truncate()` truncate text, does not break emojis - `uniqueValues()` gets unique values in an array +### Formatters + +- `formatNumber()` 1000 => "1,000" or "1K" + ### Random data generators These functions are optimized for low entropy random data generation useful for Unit Testing, Storybook, Pass real validations, Reverse hacking, Penetration testing... diff --git a/package.json b/package.json index 4d7503a..9d521d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "deverything", - "version": "0.33.0", + "version": "0.34.0", "description": "Everything you need for Dev", "main": "./dist/index.js", "module": "./dist/index.mjs", @@ -29,6 +29,7 @@ "fake", "generator", "helpers", + "formatters", "numbers", "random", "testing", diff --git a/src/formatters/formatNumber.test.ts b/src/formatters/formatNumber.test.ts new file mode 100644 index 0000000..8cd1bc7 --- /dev/null +++ b/src/formatters/formatNumber.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test } from "@jest/globals"; +import { formatNumber } from "./formatNumber"; +import { randomInt } from "../random/randomInt"; + +describe("formatNumber", () => { + test("should return the same number if test is under a thousand", () => { + const value = randomInt(0, 999); + expect(formatNumber(value, { compact: true })).toBe(`${value}`); + }); + + test("should return a string in compact K notation if value is one thousand or above", () => { + const value = randomInt(1000, 9999); + expect(formatNumber(value, { compact: true })).toContain("K"); + }); + + test("should return a string in compact M notation if value is one million or above", () => { + const value = randomInt(1000000, 9999999); + expect(formatNumber(value, { compact: true })).toContain("M"); + }); + + test("should return a string with thousand separator but no compact notation", () => { + const formattedValue = formatNumber(randomInt(1000000, 9999999)); + expect(formattedValue).not.toContain("M"); + expect(formattedValue).toContain(","); + }); + + test("Retains floating point up to 3", () => { + const formattedValue = formatNumber(123456.123456); + expect(formattedValue).toEqual("123,456.123"); + }); +}); diff --git a/src/formatters/formatNumber.ts b/src/formatters/formatNumber.ts new file mode 100644 index 0000000..a1b7212 --- /dev/null +++ b/src/formatters/formatNumber.ts @@ -0,0 +1,22 @@ +/** + * + * @example formatNumber(1000, { compact: true }) // 1K + * @example formatNumber(1111, { maxDigits: 2 }) // 1,100 + * @example formatNumber(111111.123123123) // 111,111.123 + */ +export const formatNumber = ( + value: number, + { + compact, + maxDigits, + }: { + compact?: boolean; + maxDigits?: number; + } = {} +): string => { + const formatter = Intl.NumberFormat("en", { + notation: compact ? "compact" : "standard", + maximumSignificantDigits: maxDigits, + }); + return formatter.format(value); +}; diff --git a/src/formatters/index.ts b/src/formatters/index.ts new file mode 100644 index 0000000..9cbb2fc --- /dev/null +++ b/src/formatters/index.ts @@ -0,0 +1 @@ +export * from "./formatNumber"; diff --git a/src/helpers/arrayDiff.ts b/src/helpers/arrayDiff.ts index d23f4a7..7aa4940 100644 --- a/src/helpers/arrayDiff.ts +++ b/src/helpers/arrayDiff.ts @@ -1,5 +1,6 @@ import { uniqueValues } from "./uniqueValues"; +// TODO: optimize with maps? export const arrayDiff = (arr1: any[], arr2: any[]) => { return uniqueValues( arr1 diff --git a/src/helpers/truncate.ts b/src/helpers/truncate.ts index 2c3bd86..3088968 100644 --- a/src/helpers/truncate.ts +++ b/src/helpers/truncate.ts @@ -1,7 +1,7 @@ -import { isPositive } from "../validators/isNumber"; +import { isPositiveInt } from "../validators/isNumber"; export const truncate = (arg: string, limit: number, ellipsis = "...") => { - if (!isPositive(limit)) return arg; + if (!isPositiveInt(limit)) return arg; const argArray = [...arg]; // convert string to array, emoji and unicode safe diff --git a/src/index.ts b/src/index.ts index 23d7b2c..a79f0c5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,3 +4,4 @@ export * from "./math"; export * from "./random"; export * from "./types"; export * from "./validators"; +export * from "./formatters"; diff --git a/src/validators/isNumber.test.ts b/src/validators/isNumber.test.ts index 2950f01..cb16d99 100644 --- a/src/validators/isNumber.test.ts +++ b/src/validators/isNumber.test.ts @@ -2,10 +2,10 @@ import { expect, it, describe } from "@jest/globals"; import { isEven, isInt, - isNegative, + isNegativeInt, isNumber, isOdd, - isPositive, + isPositiveInt, } from "./isNumber"; describe("isNumber", function () { @@ -78,24 +78,24 @@ describe("isNumber", function () { }); }); - describe("isPositive", function () { + describe("isPositiveInt", function () { it("checks correctly", function () { - expect(isPositive(1)).toBe(true); - expect(isPositive(0)).toBe(false); - expect(isPositive(Infinity)).toBe(false); - expect(isPositive(-0)).toBe(false); - expect(isPositive("0" as unknown as number)).toBe(false); + expect(isPositiveInt(1)).toBe(true); + expect(isPositiveInt(0)).toBe(false); + expect(isPositiveInt(Infinity)).toBe(false); + expect(isPositiveInt(-0)).toBe(false); + expect(isPositiveInt("0" as unknown as number)).toBe(false); }); }); - describe("isNegative", function () { + describe("isNegativeInt", function () { it("checks correctly", function () { - expect(isNegative(1)).toBe(false); - expect(isNegative(-1e12)).toBe(true); - expect(isNegative(0)).toBe(false); - expect(isNegative(Infinity)).toBe(false); - expect(isNegative(-0)).toBe(false); - expect(isNegative("0" as unknown as number)).toBe(false); + expect(isNegativeInt(1)).toBe(false); + expect(isNegativeInt(-1e12)).toBe(true); + expect(isNegativeInt(0)).toBe(false); + expect(isNegativeInt(Infinity)).toBe(false); + expect(isNegativeInt(-0)).toBe(false); + expect(isNegativeInt("0" as unknown as number)).toBe(false); }); }); }); diff --git a/src/validators/isNumber.ts b/src/validators/isNumber.ts index da024c6..d944837 100644 --- a/src/validators/isNumber.ts +++ b/src/validators/isNumber.ts @@ -1,12 +1,22 @@ -export const isInt = (arg: number) => Number.isInteger(arg); +export const isInt = (arg: any) => Number.isInteger(arg); -export const isEven = (arg: number) => isInt(arg) && !(arg % 2); +export const isEven = (arg: any) => isInt(arg) && !(arg % 2); -export const isOdd = (arg: number) => isInt(arg) && !!(arg % 2); +export const isOdd = (arg: any) => isInt(arg) && !!(arg % 2); -export const isPositive = (arg: number) => isInt(arg) && arg > 0; +/** + * @deprecated use isPositiveInt instead + */ +export const isPositive = (arg: any) => isInt(arg) && arg > 0; -export const isNegative = (arg: number) => isInt(arg) && arg < 0; +export const isPositiveInt = (arg: any) => isInt(arg) && arg > 0; + +/** + * @deprecated use isNegativeInt instead + */ +export const isNegative = (arg: any) => isInt(arg) && arg < 0; + +export const isNegativeInt = (arg: any) => isInt(arg) && arg < 0; export const isNumber = (arg: any): arg is number => { return (