qworks-io/utils


🛠 A collection of light-weight methods and helpers for defensive programming

License: ISC

Language: TypeScript

Keywords: async, defensive-programming, helpers, javascript, light-weight, nodejs, typescript, utilities


CircleCI codecov npm version GuardRails Security Responsible Disclosure

JavaScript / TypeScript Utilities

A collection of light-weight methods and helpers for defensive programming.

Prereqs & Install

  • Node >=9.10.0
  • npm >=6.1.0

Please note that the TypeScript target is ES6.

npm install @usefultools/utils

Usage

There are 6 main modules available:

Async

Available methods:

  • withTimeout
  • timeout
  • makeRecoverable

Examples

withTimeout

The below will resolve source after 750ms.

function findUserById(id: number) {
  const source = () => http.get(`/api/users/${id}`)
  return withTimeout(source, 750)
}

timeout

The below will reject if asyncOperation takes more than 0.5 seconds.

function work() {
  const source = asyncOperation() // can take 0-2 seconds
  return timeout(source, 500)
}

makeRecoverable

The below will retry 5 times.

function getUsers() {
  const source = () => http.get("/api/users")
  return makeRecoverable(source, 5)
}

The below will retry 3 times, each time with a delay of 250ms.

function getUsers() {
  const source = () => http.get("/api/users")
  return makeRecoverable(source, 3, 250)
}

The below will retry thrice if the error caught is a SyntaxError.

function initService() {
  const source = () => service.init()
  return makeRecoverable(source, 3, 0, SyntaxError)
}

Full test Docs here.


Conditionals

Available methods:

  • isNull
  • isUndefined
  • isMissing
  • isPresent
  • isBoolean
  • isArray
  • isObject
  • isString
  • isNumber
  • isInteger
  • isFunction
  • isNonEmptyString
  • isNonEmptyArray
  • isTrue
  • isFalse
  • isPositiveInteger
  • isNonNegativeInteger
  • hasOneItem
  • hasMultipleItems
  • isConstructable
  • hasOnlyKeys
  • isEqual

Examples

isNull

Find out whether value is null

isNull(null) // true

isNull(undefined) // false
isNull(0) // false
isNull(NaN) // false

isUndefined

Find out whether type of value is undefined

isUndefined(undefined) // true

isUndefined(null) // false
isUndefined(0) // false

isMissing

Find out whether value is null or undefined, therefore "missing"

isMissing(null) // true
isMissing(undefined) // true

isMissing(0) // false
isMissing(NaN) // false
isMissing("") // false

isPresent

Find out whether value is not null and not undefined, therefore "present"

isPresent(0) // true
isPresent(NaN) // true
isPresent("") // true

isPresent(null) // false
isPresent(undefined) // false

isBoolean

Find out whether value is of type Boolean

isBoolean(true) // true
isBoolean(false) // true

isBoolean(0) // false

isArray

Find out whether value is of type Array

isArray([]) // true
isArray([null, undefined]) // true

isArray({}) // false

isObject

Find out whether value is of type Object

isObject({}) // true

isObject(new Function()) // false
isObject([]) // false

isString

Find out whether value is of type String

isString("") // true

isString(new String()) // false

isNumber

Find out whether value is of type Number

isNumber(42) // true
isNumber(Math.PI) // true
isNumber(Infinity) // true

isNumber(NaN) // false

isInteger

Find out whether value is of type Number and is an Integer

isInteger(42) // true

isInteger(Math.PI) // false
isInteger(Infinity) // false
isInteger(NaN) // false

isFunction

Find out whether value is of type Function

isFunction(() => {}) // true
isFunction(ReferenceError) // true

isFunction(new ReferenceError()) // false

isNonEmptyString

Find out whether value is of type String, and has at least 1 character

isNonEmptyString("Hello, World!") // true

isNonEmptyString("") // false

isNonEmptyArray

Find out whether value is of type Array and has at least one element

isNonEmptyArray([null]) // true

isNonEmptyArray([]) // false

isTrue

Find out whether value is of type Boolean and is true

isTrue(true) // true

isTrue(1) // false
isTrue(false) // false

isFalse

Find out whether value is of type Boolean and is false

isFalse(false) // true

isFalse(0) // false
isFalse(true) // false

isPositiveInteger

Find out whether value is an Integer and greater than 0

isPositiveInteger(42) // true

isPositiveInteger(0) // false
isPositiveInteger(-42) // false

isNonNegativeInteger

Find out whether value is an Integer and greater or equal to 0

isNonNegativeInteger(42) // true
isNonNegativeInteger(0) // true

isNonNegativeInteger(-42) // false

hasOneItem

Find out whether value is an Array and its length is 1

hasOneItem([null]) // true

hasOneItem([]) // false
hasOneItem([42, Math.PI]) // false

hasMultipleItems

Find out whether value is an Array and its length is more than 1

hasMultipleItems([42, Infinity]) // true

hasMultipleItems([]) // false
hasMultipleItems(["Hello, World"]) // false

isConstructable

Find out whether value is Constructable

isConstructable(new Function()) // true
isConstructable(function a() {}) // true
isConstructable(class {}) // true
isConstructable(class ClassName {}) // true

isConstructable(() => {}) // false

hasOnlyKeys

Find out whether value has only the keys provided

hasOnlyKeys({ a: "b", c: "d" }, ["a", "c"]) // true
hasOnlyKeys({ a: "b" }, ["a"]) // true
hasOnlyKeys({}, []) // true

hasOnlyKeys({ a: "b" }, ["c"]) // false
hasOnlyKeys({ a: "b", c: "d" }, ["a"]) // false

isEqual

Find out whether value 1 and value 2 are equal (shallow)

isEqual("Hello, World!", "Hello, World!") // true
isEqual(null, null) // true
isEqual(false, false) // true
isEqual(Math.PI, Math.PI) // true
isEqual(Infinity, Infinity) // true

isEqual([], []) // false
isEqual({}, {}) // false
isEqual(false, true) // false

Full test Docs here.


Env

Available methods:

  • getAsBool
  • getAsInt
  • getAsStr

NOTE: These methods are namespaced under env. The usage is therefore

import { env } from "@usefultools/utils"

env.getAsBool(...)
env.getAsInt(...)
env.getAsStr(...)

Examples

Assuming your process.env has loaded the following .env.

IS_PROD=true
ASYNC_MAX_TIMEOUT=2500
API_KEY=0351f02f-0be2-49d1-bfed-5c45275d4fd2

env.getAsBool

To retrieve the Boolean value of "IS_PROD" from process.env, you can use the following method.

env.getAsBool("IS_PROD") // true

If the raw value cannot be found, or the parsed value is not a Boolean, this function will throw a ReferenceError or a TypeError respectively.

env.getAsInt

To retrieve the Integer value of "ASYNC_MAX_TIMEOUT" from process.env, you can use the following method.

env.getAsInt("ASYNC_MAX_TIMEOUT") // 2500

If the raw value cannot be found, or the parsed value is not an Integer, this function will throw a ReferenceError or a TypeError respectively.

env.getAsStr

To retrieve the String value of "API_KEY" from process.env, you can use the following method.

env.getAsStr("API_KEY") // "0351f02f-0be2-49d1-bfed-5c45275d4fd2"

If the raw value cannot be found, this function will throw a ReferenceError.

In all of the above, you can also use your own env object like so:

// const env = { "IS_DEV": "false" }

env.getAsBool("IS_DEV", env) // false

Full test Docs here.


Helpers

Available methods:

  • noop
  • identity
  • getRandomIntInclusive
  • generateId
  • isValidId
  • generateUUID
  • isValidUUID
  • fill

Examples

noop

Sometimes you might want to provide a default callback parameter to some of your functions to prevent the application from crashing (on the off-chance someone or something accidentally calls them without any parameters). You can use the noop helper as shown below.

function doSomething(cb = noop) {
  let res: string

  try {
    await http.get("/api/healthcheck")
    res = "All works!"
  } catch (_err) {
    res = "There was an error!"
  }

  cb(res)
}

identity

Let's assume that doSomething prints its result (String) into the console, but applies onSuccess for a Ok result, and onError for a Err result. You might want to uppercase the success result, but leave the error message in its original form. You can use the identity helper as shown below.

function onSuccess(res: string) {
   return res.toUpperCase()
}

doSomething(onSuccess, identity)

getRandomIntInclusive

To get a random integer within a specified range, you can use the following:

getRandomIntInclusive(10, 99) // Yields integers between 10 and 99

generateId

To get a random id (underlying is the shortid library) use:

generateId() // "HJ5fy5p3G"
generateId() // "Byij0Ka3z"

isValidId

To confirm whether a value is a valid id (underlying is the shortid library) use:

isValidId("HJ5fy5p3G") // true
isValidId("foo") // false

generateUUID

To get a random UUID v4 (underlying is the uuid library) use:

generateUUID() // "b98c5086-1dcc-4822-9fa4-8f343f18e8de"
generateUUID() // "7118f7d9-70b1-4cb2-97da-3fe272bed7e8"

isValidId

To confirm whether a value is a valid UUID v4 (underlying is the uuid library) use:

isValidUUID("1ad006bf-00c0-49de-bcf0-7c5eb2f83241") // true
isValidUUID("foo") // false

fill

To fill an array, use:

fill(4) // [0, 1, 2, 3]

Full test Docs here.


Match

Available methods:

  • match

Other exports:

  • _def

Examples

match

A basic pattern match:

const getMessage = (year: number): string => match(year)({
  [1984]: "The year is 1984.",
  [_def]: "Unfortunately, we cannot tell what year it is."
})

getMessage(1984) // "The year is 1984."
getMessage(1994) // "Unfortunately, we cannot tell what year it is."
getMessage(2024) // "Unfortunately, we cannot tell what year it is."

Advanced pattern matching, including assertions:

function isFutureYear(year) {
  return isPositiveInteger(year)
  && year > new Date().getFullYear()
}

function isCurrentYear(year) {
  return isPositiveInteger(year)
  && year === new Date().getFullYear()
}

const getMessage = (year: number): string => match(year)(
  [1984, "The year is 1984."],
  [isCurrentYear, x => `The year ${x} is up-to-date.`],
  [isFutureYear, x => `The year ${x} is in the future...`],
  [_def, "Unfortunately, we cannot tell what year it is."],
)

getMessage(1984) // "The year is 1984."
getMessage(2018) // "The year 2018 is up-to-date."
getMessage(2024) // "The year 2024 is in the future..."
getMessage(1333) // "Unfortunately, we cannot tell what year it is."

Full test Docs here.


ThrowIf

A collection of simple throwable assertions, all of which throw if the assertion fails.

Available methods:

  • throwIfMissing
  • throwIfPresent
  • throwIfNotBoolean
  • throwIfNotArray
  • throwIfNotObject
  • throwIfNotString
  • throwIfNotNumber
  • throwIfNotInteger
  • throwIfNotFunction
  • throwIfFalse
  • throwIfEmptyString
  • throwIfEmptyArray
  • throwIfNotPositiveInteger
  • throwIfNegativeInteger
  • throwIfNotConstructable

Examples

throwIfNotObject({}); // void
throwIfNotObject([]); // throws Error
throwIfNotObject(null); // throws Error
throwIfNotObject(undefined); // throws Error

You can also provide your own error messages, and errors.

throwIfMissing(someValue, '`someValue` missing!'); // throws Error('`someValue` missing!')
throwIfMissing(someValue, '`someValue` missing!', ReferenceError); // throws ReferenceError('`someValue` missing!')

Full test Docs here.


Development

  1. Install dependencies:
npm install
  1. Compile:
make compile
  1. Test:
make test # watch mode
make test-ci # CI mode / single run
  1. Format the codebase:
make format

Contributing

If you have comments, complaints, or ideas for improvements, feel free to open an issue or a pull request! See Contributing guide for details about project setup, testing, etc.

Author and license

This library was created by @LITCHI.IO. Main author and maintainer is Slavo Vojacek.

Contributors: Slavo Vojacek

@usefultools/utils is available under the ISC license. See the LICENSE file for more info.

Project Statistics

Sourcerank 7
Repository Size 379 KB
Stars 8
Forks 1
Watchers 2
Open issues 0
Dependencies 455
Contributors 4
Tags 50
Created
Last updated
Last pushed

Top Contributors See all

Slavo Vojacek renovate[bot] Renovate Bot

Packages Referencing this Repo

@usefultools/utils
A collection of light-weight methods and helpers for defensive programming
Latest release 6.3.0 - Updated - 8 stars
@openmaths/utils
A collection of light-weight methods and helpers for defensive programming
Latest release 5.0.0 - Updated - 8 stars

Recent Tags See all

v6.3.0 July 15, 2019
v6.2.1 December 02, 2018
v6.2.0 December 01, 2018
v6.1.0 November 01, 2018
v6.0.3 October 03, 2018
v6.0.2 October 01, 2018
v6.0.1 October 01, 2018
v6.0.0 October 01, 2018
v5.0.0 September 18, 2018
v4.0.2 August 23, 2018
v4.0.1 August 23, 2018
v4.0.0 August 23, 2018
v3.2.0 July 20, 2018
v3.1.0 July 20, 2018
v3.0.0 July 16, 2018

Something wrong with this page? Make a suggestion

Last synced: 2018-10-10 06:49:15 UTC

Login to resync this repository