Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

topkat-utils

top-kat1.7kMIT1.3.15TypeScript support: included

A comprehensive collection of TypeScript/JavaScript utility functions for common programming tasks. Includes validation, object manipulation, date handling, string formatting, and more. Zero dependencies, fully typed, and optimized for performance.

typescript, javascript, utils, utilities, validation, date, string, object, array, url, path, logger, error-handling, functional, zero-dependencies, performance, type-safe, dot-notation, template-engine, deep-clone, merge, flatten, case-conversion

readme

Topkat Utils

|\_____/| ▀▀▀█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ |\_____/|
|  |||  |    █  █▀▀█ █▀▀█ █  █ ▄▀▀▄ ▀▀█▀▀    █  █ ▀▀█▀▀ █ █   █▀▀▀ |  |||  |
\◥■■=■■◤/    █  █  █ █▀▀▀ █▀▀▄ █▀▀█   █      █  █   █   █ █   ▀▀▀█ \◥■■=■■◤/
 \__^__/     ▀  ▀▀▀▀ ▀    ▀  ▀ ▀  ▀   ▀      ▀▀▀▀   ▀   ▀ ▀▀▀ ▀▀▀▀  \__^__/

A powerful collection of utility functions for JavaScript/TypeScript projects. Fast, functional, and fully typed.

Installation

npm install topkat-utils
# or
yarn add topkat-utils

Error handler

  • DescriptiveError(value, type): Improves JS Error class by adding a way to add extraInformations to error, which is a must have in the context of debugging and logging the right informations
    // Example usage
    try {
    if(user.age < 18) {
      throw new DescriptiveError('Not allowed', { age: user.age, code: 403, ...additionalInfosToDisplayInLogs })
    }
    } catch (error) {
    // Error message: "Expected number, got string: '25'"
    C.error(error.message) //
    C.error(error.logs) // display logs as string array
    C.error(error.errorDescription) // display all extraInfos / options provided as second param
    }

Logger

  • C: all in one logger util `typescript // Basic usage C.log('Hello World') // [INFO] Hello World C.info('Info!') // [INFO] Info! Usually blue

// Errors and warning will take the most informations out of your errors and does particularly fit with DescriptiveError() class C.error('Oops!') // [ERROR] Oops! Error: Something went wrong\nat doSomething (/app/src/utils.js:42:15)... C.error(false, 'Oops!')// Error without stack trace C.warning('Warning!') // [WARN] Warning! Error: Something went wrong\nat doSomething (/app/src/utils.js:42:15)... C.warning(false, 'Warning!') // Same without stack trace

// With objects parsing C.log({ user: 'John', age: 30 }) // [INFO] { user: 'John', age: 30 } // Terminal custom colors C.log(C.red('Hello') + C.dim('World') + C.green('of') + C.logClr('Typescript', [0, 255, 150]))

C.success('Successfully built') // Color green '✓ Successfully built'

C.clearLastLines(2) // clears the last two lines of the terminal

- `perfTimer()`: Util to measure performances
``` typescript
const time = perfTimer()

for(let i = 0; i < 9999;i++) longProcess()

console.log('Process took ' + time.end()) // 'Process took 2.22 seconds
  • cliProgressBar
  • cliLoadingSpinner
  • removeCircularJSONstringify(str): convert circular structures to valid JSON // TypeError: Converting circular structure to JSON

Core Utilities

Value Checking & Validation

  • validator(value, type): Type validation utility. Will throw an error if not valid. If you prefer that the function returns an error array, use validatorReturnErrArray
    validator(
      { value: 3, type: 'number', gte: 1, lte: 3 },
      { name: 'email', value: 'name@site.com', regexp: /[^\s@]+@[^\s@]+\.[^\s@]/},
    )
  • isset(value): Check if a value is defined and not null (ignores other falsy values)
  • isEmpty(value): Check if a value is empty
  • isObject(value): Check if value is a plain object (not null, not Date, not array, etc.)

Object Manipulation

  • deepClone(obj): Deep clone objects, useful when you want to manipulate object with subobjects without modifying any references to those objects
  • mergeDeep(obj1, obj2): Deep merge objects
  • objForceWrite(obj, 'user.address.line1', addressVar), objForceWriteIfNotSet(): Forces a path to be written in nested object and create subObjects if necessary
  • flattenObject(obj): Flatten nested objects with pros as dot notation `typescript // Example of flattenObject const nested = { user: { name: 'John', address: {
    street: '123 Main St',
    city: 'New York'
    } }, settings: { theme: 'dark' } }

const flattened = flattenObject(nested) // Result: // { // 'user.name': 'John', // 'user.address.street': '123 Main St', // 'user.address.city': 'New York', // 'settings.theme': 'dark' // }

- `unflattenObject(obj)`: Unflatten objects back to nested structure
- `objFilterUndefined(obj)`: Remove undefined values from object
- `findByAddress(obj, path)`: Get value by dot notation path
```typescript
const obj = {
  user: {
    profile: {
      name: 'John'
    }
  }
}

findByAddress(obj, 'user.profile.name') // 'John'
findByAddress(obj, 'user.settings.theme') // undefined

Array Operations

  • shuffleArray(array): Randomize array order
  • randomItemInArray(array): Get random item from array
  • pushIfNotExist(array, item): Push item if not already present
  • noDuplicateFilter(array): Remove duplicates from array
  • getArrayInCommon(arr1, arr2): Get common elements between arrays
  • getArrayDiff(arr1, arr2): Get difference between arrays
  • arrayCount(arr, 'stringInstance'): Count number of occurence of item in array

Number Operations

  • isBetween(value, min, max): Check if a number is within a range
  • random(min, max): Generate random number between two values
  • minMax(value, min, max): Clamp a number between min and max values
  • average(array): Calculate average of array values
  • sumArray(array): Sum values in an array
  • round(number, nbDecimals): Round number to X decimal places
  • round2(number): Round number to 2 decimal places

String Manipulation

  • miniTemplater(template, data): Simple template engine
    // Basic usage
    miniTemplater('Hello {{name}}!', { name: 'John' }) // 'Hello John!'
  • cln(value): Clean string for printing (undefined, null, NaN)
  • pad(number, length): Pad numbers with leading zeros
  • generateToken(length, isUnique, mode): Generate random tokens (not to use un security workflows)
  • convertAccentedCharacters(str, options): Eg: 'éçàÉ' => 'ecaE'. Convert accented characters to non-accented with options to remove spaces or numbers
  • nbOccurenceInString(str, occurence)

Loop Operations

  • forI, forIAsync: A mix between js for(let i = ....i++) loop and a map. Iterates over a specified number of times, passing each iteration's result to the next callback
    // Generate Fibonacci sequence
    forI(8, (i, previousItem, results) => {
    if (i <= 1) return 1
    return results[i-1] + results[i-2]
    })
    // Returns: [1, 1, 2, 3, 5, 8, 13, 21]
  • recursiveGenericFunction, recursiveGenericFunctionSync: The simplest way do iterate recursively on every item of an object
    recursiveGenericFunctionSync(
      { a: { b: true } }, // object OR array
      (item, addr, lastElementKey, parent) => {
          C.log(item)           // true
          C.log(addr)           // 'a.b'
          C.log(lastElementKey) // 'b'
          C.log(parent)         // { a: { b: 3 } }
          C.log(findByAddress(addr)) // true // just aother way to get the value
          return false
      }
    )

Date Operations

  • getDateAsInt(date): Convert date to integer format (20290101)
  • dateOffset(date, offset): Add time offset to date
  • getDuration(start, end): Calculate duration between dates
  • isWeekend(date): Check if date is weekend
  • firstDayOfMonth(date): Get first day of month
  • lastDayOfMonth(date): Get last day of month

URL & Path Operations

  • urlPathJoin(...paths): Join URL paths (like path.join but for URLs)

    // Handles double slashes correctly
    urlPathJoin('https://api.example.com//v1', '/users/', 'userId') // => 'https://api.example.com/v1/users/userId'
  • escapeRegexp(str): Will escape all special character in a string to output a valid regexp string to put in RegExp(myString)

    • Eg: from 'path.*.addr(*)' will output 'aa\..*?\.addr\(.*?\)' so regexp match 'path.random.addr(randomItem)'

Case Conversion

  • camelCaseify(str): Replace 'hello-world', 'hello World', 'hello_World', 'helloWorld' => 'helloWorld'
  • capitalize1st(string): helloWorld => HelloWorld
  • camelCase([word1, word2]): Convert to camelCase
  • snakeCase([word1, word2]): Convert to snake_case
  • kebabCase([word1, word2]): Convert to kebab-case
  • pascalCase([word1, word2]): Convert to PascalCase
  • titleCase([word1, word2]): Convert to Titlecase

Additional Utilities

Environment & Configuration

  • ENV: shortcut to process.env. Parse boolean and number values
  • parseBool(value): Parse boolean values

Async Operations

  • timeout(ms): Promise-based timeout

Object Control

  • readOnly(obj): Lock all 1st level props of an object to read only (not rewritable / modifiable)
  • reassignForbidden(obj): Fields of the object can be created BUT NOT reassignated
  • readOnlyRecursive(obj): All fields and subFields of the object will be readOnly
  • createProxy(obj): replace new Proxy(...) from javascript with correct handling for JSON.stringify and a __isProxy: true helper prop

Typescript equivalent of Js functions (Fix types)

  • lowerCase(str): lowerCase('HelloWorld' as const) // type: 'helloworld' (Equivalent of type LowerCase<MyString>)
  • upperCase(str): upperCase('HelloWorld' as const) // type: 'HELLOWORLD' (Equivalent of type UpperCase<MyString>)
  • objEntries(obj): In JS object entries are not correctly typed (Object.entries({ a: 1, b: true }) // type: [string, number | boolean]). With this function we are typed like objEntries({ a: 1, b: true }) // ["a", number] | ["b", boolean]
  • objKeys: In JS object keys are not correctly typed (Object.keys({ a: 1, b: 2 }) // type: string). With this function we are typed like objKeys({ a: 1, b: 2 }) // type: 'a' | 'b'
  • includes(str): Fix this always happening ts error when using includes and your search string is not typed as an array element (which is very dumb IMO)

Configuration

Place that at the top of your code

registerConfig({
  terminal: {
    // Custom colors for terminal logs
    theme: {...},
    // disable colors in case your logs are outputted as plain text
    noColor: true,
  },
  // if you use topkatUtils as a logger and error handler
  // onError custom callback
  onError: () => { /**  */ },
  /** Exemple of preprocessing log */
  preprocessLog(log: string) { return 'MyAppName: ' + Date.now() + ' ' + log }
})

TypeScript Support

This library is fully typed and provides TypeScript definitions out of the box. Every Util is documented via JsDoc and documentation should appear on hover in your IDE

Contributing

Contributions are welcome! Please feel free to submit a Pull Request

License

MIT

Support

If you need help or have questions, please open an issue on GitHub.

changelog

v1.2.49

  • FIX type in parseEnv
  • revert changes because mongoId is not just any strings

v1.2.48

  • FIX getId so that it can accept any strings

v1.2.45

  • Add parent and lastElement key to informations returned by findByAddressAll

v1.2.44

  • FIX recursiveGenericFunction and findByAddressAll
  • ADD new option in escapeRegexp
  • alias parseRegexp => escapeRegexp

v1.2.43

  • FIX recursiveGenericFunctionSync returning bad address (starting with a point)

v1.2.42

  • add nbOccurenceInString and fix some types

v1.2.41

  • improving types for object helpers

v1.2.39

  • FIX capitalize1st error when emptyy string

v1.2.38

  • convertAccentedCharacters now taking in account upper case letters

v1.2.36

  • FIX typeof config partial and required

v1.2.35

  • other fix logFromOtherErr is not iterable

v1.2.34

  • FIX "cannot read propertie undefined..." error when logging an undefined entry

v1.2.33

  • FIX typescript errors when on projects with strict mode

v1.2.31

  • FIX loading spinner not exported

v1.2.30

  • FIX type in randomItemInArray

v1.2.29

  • FIX validator isset not working on undefined values

v1.2.26

  • improve int typing accepting both string and number

v1.2.25

  • FIX isType not working on emty string

v1.2.24

  • improve tryCatch / failSafe to work with async and sync functions natively

v1.2.23

  • Added forcePathInObject() to force an existing path in an object, like an empty object or array
  • adding failSafe as an alias of tryCatch for readability
  • improving type for tryCatch()

v1.2.22

  • remove usage of array.at(-1) since it's not compatible with react native or older versions of node

v1.2.21

  • FIX error was not logging in some case with DescriptieError

v1.2.20

  • remove arrayToObjectSorted
  • greatly improve typings on all compareArrays functions
  • improve error display and logging, adding originalError to extraInfos, cleanStackTrace of original error
  • added eslintconfig

v1.2.17

  • added a relevant toString method to DescriptiveError class
  • improved error logging

v1.2.16

  • ADD onError to config for custom error handling
  • improve logging
  • add frontend compatibility

v1.2.15

  • Find by address now accepts string array for address

v1.2.14

  • objForceWrite now return main object
  • improve type on objectutils

v1.2.13

  • add ability to hide generated api code in errors by setting { code } value to undefined, null or option.doNotDisplayCode to true
  • allow all casing function to receive an array of string as first argument OR rest param as a string array

v1.2.12

  • ADD returnValueIfUndefined for asArray function and improve type

v1.2.11

  • FIX on terminal noColor detection nodeJs env

v1.2.10

  • NEW isNodeJs fn
  • Default terminal color when on nodejs

v1.2.9

  • Fix error noStackTrace

v1.2.7

  • adding option noStackTrace to error
  • improve type of findByAddressAll

v1.2.6

  • mini fix on escapeRegexp option parseStarChar, now replacing
  • will 'match all until'. Before it was just 'match all'

v1.2.5

  • improve deleteByAddress to accept [0] array syntax in addr AND string AND string array as addr argument

v1.2.3

  • default terminal no color to avoid displaying strange characters when outputting logs for front end

v1.2.2

  • fix ts problem compiling class with ES6

v1.2.1

  • NEW DescriptiveError class for more explicit errors
  • MINOR VERSION TRANSITION => A little change of api with validatorReturnErrArray that returns [msg, extraInfos][] instead of [msg, httpErrorCode, extraInfos][]. Now the ode is in the extra infos

v1.1.9

  • add option disableCircularDependencyRemoval to recursive helpers

v1.1.5

  • add isset to validator (improves readability)

v1.1.1

  • test OK
  • NEW WTF utils removed circular dependencies

v1.0.58

  • BREAKING remove export default

v1.0.57

  • improve typings for recursive generic

v1.0.51

  • add param to findByAddressAll returnAddresses for returning found items alongside their address

v1.0.49

  • Add/fix email type in validator
  • imrove typings on forI function

v1.0.47

  • deep clone type improvement

v1.0.46

  • FIX templater undefined no error anymore

v1.0.42

  • type for date function

v1.0.40

  • NEW forI iterate function

v1.0.39

  • NEW ability for restTestMini to throw error

v1.0.37

  • add generateObjectId
  • cleaning and typing improvements

v1.0.35

  • fix in asArray typing

v1.0.32

  • safer generateToken

v1.0.28

  • nextWeekDay

v1.0.27

  • arrayCount count the nb of occurence of an item in array
  • isBetween inclusive option (default true)

v1.0.25

  • NEW restTestMini mini test framework

v1.0.9

  • assert used for testing

v1.0.5

  • new alias randomize array
  • type for asArray

v1.0.3

  • new err handling
  • escapeRegexp config with parseStarChar option