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

Package detail

@andranik-arakelyan/js-utilities

Javascript utilities

javascript, typescript, utilities, helper-functions, commonjs, es2022, es2023, nodejs, npm-package, js-tools, typescript-library, utility-functions, toolkit, code-reuse, modular, async, promises, retry, backoff, array-manipulation, wait, delay, random-generation, debugging, runtime-info, shuffle, fisher-yates, exponential-backoff, stack-trace, type-safe, array-utils, promise-utils, data-structures, stack, queue, fifo, lifo, collection, generic-types, typescript-generics, algorithms

readme

js-utilities

npm version License: MIT

Utility functions for all JavaScript/TypeScript environments.

Table of Contents

Installation

To install the package, use npm:

npm install @andranik-arakelyan/js-utilities

Usage

Import the utilities you need in your project:

import {arraySubtract} from '@andranik-arakelyan/js-utilities';

const result = arraySubtract([1, 3, 5] , [ 1, 2, 3]);
console.log( 'result', result ); // [5]

Features

Data Structures

Stack<T>

A generic type-safe implementation of a Stack data structure with LIFO (Last-In-First-Out) operations.

import { Stack } from '@andranik-arakelyan/js-utilities';

// Create a new stack of numbers
const stack = new Stack<number>();

// Push elements onto the stack
stack.push(1);
stack.push(2);
stack.push(3);

console.log(stack.peek()); // 3 (returns the top element without removing it)
console.log(stack.pop());  // 3 (removes and returns the top element)
console.log(stack.size()); // 2 (returns the current number of elements)
console.log(stack.isEmpty()); // false

Queue<T>

A generic type-safe implementation of a Queue data structure with FIFO (First-In-First-Out) operations.

import { Queue } from '@andranik-arakelyan/js-utilities';

// Create a new queue of strings
const queue = new Queue<string>();

// Enqueue elements
queue.enqueue("first");
queue.enqueue("second");
queue.enqueue("third");

console.log(queue.peek()); // "first" (returns the front element without removing it)
console.log(queue.dequeue()); // "first" (removes and returns the front element)
console.log(queue.size()); // 2 (returns the current number of elements)
console.log(queue.isEmpty()); // false

Array Utilities

arraySubtract

Subtracts elements of one array from another.

import { arraySubtract } from '@andranik-arakelyan/js-utilities';

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [1, 3, 5];
const result = arraySubtract(arr1, arr2);
console.log(result); // [2, 4]

arraySplit

Splits an array into chunks based on a separator.

import { arraySplit } from '@andranik-arakelyan/js-utilities';

// Using a value as separator
const result1 = arraySplit([1, 2, 3, 0, 4, 5, 0, 6], 0);
console.log(result1); // [[1, 2, 3], [4, 5], [6]]

// Using a function as separator
const result2 = arraySplit([1, 2, 3, 4, 5, 6], (item) => item % 2 === 0);
console.log(result2); // [[1], [3], [5]]

shuffle

Randomly shuffles an array using the Fisher-Yates algorithm. This algorithm is superior to naive shuffling approaches (like sorting with a random comparator) because it guarantees a truly random permutation with equal probability for each possible outcome and has optimal O(n) time complexity.

import { shuffle } from '@andranik-arakelyan/js-utilities';

const array = [1, 2, 3, 4, 5];
const shuffled = shuffle(array);
console.log(shuffled); // Example output: [3, 1, 5, 2, 4]
console.log(array); // Original array remains unchanged: [1, 2, 3, 4, 5]

unique

Returns a new array with duplicate values removed. Optionally accepts a function to determine the key for uniqueness comparison.

import { unique } from '@andranik-arakelyan/js-utilities';

// Remove duplicates from primitive values
const numbers = [1, 2, 2, 3, 1, 4];
console.log(unique(numbers)); // [1, 2, 3, 4]

// With objects using a custom key selector
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 1, name: 'Alice (duplicate)' }
];
const uniqueUsers = unique(users, user => user.id);
console.log(uniqueUsers); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

groupBy

Groups array elements by a key selector function. Returns a Map where keys are the result of the key selector function and values are arrays of elements that share the same key.

import { groupBy } from '@andranik-arakelyan/js-utilities';

// Group numbers by even/odd
const numbers = [1, 2, 3, 4, 5, 6];
const grouped = groupBy(numbers, n => n % 2 === 0 ? 'even' : 'odd');
console.log(grouped); // Map { 'odd' => [1, 3, 5], 'even' => [2, 4, 6] }

// Group objects by property
const users = [
  { name: 'Alice', department: 'Engineering' },
  { name: 'Bob', department: 'Marketing' },
  { name: 'Charlie', department: 'Engineering' }
];
const byDepartment = groupBy(users, user => user.department);
console.log(byDepartment);
// Map { 
//   'Engineering' => [
//     { name: 'Alice', department: 'Engineering' }, 
//     { name: 'Charlie', department: 'Engineering' }
//   ],
//   'Marketing' => [{ name: 'Bob', department: 'Marketing' }]
// }

// Group by multiple criteria using composite keys
const products = [
  { name: 'Laptop', category: 'Electronics', inStock: true },
  { name: 'Phone', category: 'Electronics', inStock: false },
  { name: 'Desk', category: 'Furniture', inStock: true }
];
const byStatus = groupBy(products, p => `${p.category}-${p.inStock}`);
// Groups by category and stock status combined

Object Utilities

deepClone

Creates a deep clone of an object or array, creating a new copy of all nested objects and arrays. This function handles circular references and various JavaScript built-in types.

import { deepClone } from '@andranik-arakelyan/js-utilities';

// Simple object cloning
const obj = { a: 1, b: { c: 2 } };
const clone = deepClone(obj);
clone.b.c = 3;
console.log(obj.b.c); // Still 2

// Handling arrays and nested structures
const arr = [1, { x: [2, 3] }];
const cloneArr = deepClone(arr);
cloneArr[1].x[0] = 10;
console.log(arr[1].x[0]); // Still 2

// Handling circular references
const circular = { a: 1 };
circular.self = circular;
const cloneCircular = deepClone(circular);
console.log(cloneCircular.self === cloneCircular); // true

// Handling built-in types
const data = {
  date: new Date(),
  regex: /test/g,
  set: new Set([1, 2, 3]),
  map: new Map([['key', 'value']])
};
const cloneData = deepClone(data);
console.log(cloneData.date instanceof Date); // true
console.log(cloneData.regex instanceof RegExp); // true
console.log(cloneData.set instanceof Set); // true
console.log(cloneData.map instanceof Map); // true

Random Utilities

randomInt

Generates a random integer in a specified range.

import { randomInt } from '@andranik-arakelyan/js-utilities';

// Random number between 1 and 10
const random = randomInt(10, 1);
console.log(random); // Example output: 7

randomBoolean

Generates a random boolean value.

import { randomBoolean } from '@andranik-arakelyan/js-utilities';

const random = randomBoolean();
console.log(random); // Either true or false

Runtime Utilities

currentCodeInfo

Returns information about the current code execution context.

import { currentCodeInfo } from '@andranik-arakelyan/js-utilities';

function exampleFunction() {
  const info = currentCodeInfo();
  console.log(info);
  // Output: 
  // {
  //   className: "",
  //   methodName: "exampleFunction",
  //   filepath: "/path/to/your/file.js",
  //   filename: "file.js",
  //   lineNumber: 4,
  //   columnNumber: 15
  // }
}

exampleFunction();

Function Utilities

once

Creates a function that ensures the original function is only ever called once, regardless of how many times the returned function is called. Subsequent calls to the wrapped function return the result of the first invocation.

import { once } from '@andranik-arakelyan/js-utilities';

// Create a function that will only execute once
const initializeApp = once(() => {
  console.log('App initialized!');
  return 'Initialization complete';
});

// First call - function executes
const result1 = initializeApp(); // Logs: 'App initialized!'

// Subsequent calls - function is not executed again
const result2 = initializeApp(); // No log output

// Both calls return the same result
console.log(result1 === result2); // true

// Works with parameters and preserves this context
const obj = {
  data: 'example',
  process: once(function(this: { data: string }, prefix: string) {
    console.log(`Processing ${prefix} ${this.data}`);
    return `${prefix}-${this.data}`;
  })
};

// First call with parameters
obj.process('test'); // Logs: 'Processing test example', returns: 'test-example'

// Second call - function is not executed again even with different parameters
obj.process('another'); // No log output, still returns: 'test-example'

debounce

Creates a debounced function that delays invoking the provided function until after the specified wait time has elapsed since the last time it was invoked. The function will only execute once the wait period has elapsed with no new calls. This is particularly useful when dealing with events that fire rapidly, such as window resizing, scrolling, or keystrokes, when you want to execute the handler only after the user has stopped the action.

import { debounce } from '@andranik-arakelyan/js-utilities';

// Create a debounced version of a function
const handleInput = debounce((value) => {
  // This will only execute after the user has stopped typing for 300ms
  console.log('Processing input:', value);
  performSearch(value);
}, 300);

// Attach to an input event
inputElement.addEventListener('input', e => handleInput(e.target.value));

// Multiple rapid calls reset the timer each time
handleInput('a'); // Starts the timer
handleInput('ab'); // Cancels previous timer, starts a new one
handleInput('abc'); // Cancels previous timer, starts a new one
// After 300ms of no calls, the function executes with 'abc'

// With proper TypeScript typing
const calculateLayout = debounce((width: number, height: number): string => {
  // Expensive calculation that should not run on every resize event
  return `${width}x${height}`;
}, 100);

// Cancel a pending debounced call if needed
handleInput.cancel();

throttle

Creates a throttled function that only invokes the provided function at most once per every specified wait milliseconds, regardless of how many times it's called. This is useful when you want to limit the rate at which a function is executed, such as during scroll events or continuous button clicks.

import { throttle } from '@andranik-arakelyan/js-utilities';

// Create a throttled version of a function
const handleScroll = throttle(() => {
  // This will execute at most once every 300ms, even if scrolling continuously
  console.log('Processing scroll event');
}, 300);

// Attach to a scroll event
window.addEventListener('scroll', handleScroll);

// With proper TypeScript typing
const updatePosition = throttle((x: number, y: number): string => {
  // Update UI based on position, but not too frequently
  return `${x},${y}`;
}, 100);

// Cancel a pending throttled call if needed
handleScroll.cancel();

Promise Utilities

wait

Creates a promise that resolves after a specified delay.

import { wait } from '@andranik-arakelyan/js-utilities';

// Wait for 1 second
await wait(1000);

// Chain with other operations
wait(500).then(() => console.log('Half a second has passed'));

// Use in an async function
async function delayedOperation() {
  console.log('Starting');
  await wait(2000);
  console.log('2 seconds have passed');
}

retry

Retries an async function with configurable attempts and exponential backoff.

import { retry } from '@andranik-arakelyan/js-utilities';

// Basic usage with default options (3 attempts)
const data = await retry(() => fetchData());

// With custom retry configuration
const result = await retry(
  () => riskyOperation(),
  { 
    attempts: 5,              // Maximum attempts including initial attempt
    delay: 1000,              // Initial delay in milliseconds
    backoffFactor: 2,         // Multiply delay by this factor after each attempt
    retryIf: (err) => err instanceof NetworkError,  // Only retry specific errors
    onRetry: (err, attempt) => console.log(`Retry attempt ${attempt}`) // Track retries
  }
);

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

NPM page

Git repository

License

This project is licensed under the MIT License - see the LICENSE file for details.

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

0.9.0 - 2025-06-10

Added

  • New array utility function:
    • groupBy function to group array elements by a key selector function
    • Returns a Map where keys are the result of the key selector function and values are arrays of grouped elements
    • Supports primitive values and complex object grouping with type safety
    • Handles empty arrays gracefully
    • Comprehensive test suite with edge cases and multiple usage examples

0.8.0 - 2025-06-03

Added

  • New object utility function:
    • deepClone function for creating deep copies of objects and arrays
    • Handles circular references and various JavaScript built-in types
    • Preserves type information for Date, RegExp, Set, and Map objects

0.7.0 - 2025-05-27

Added

  • New array utility function:
    • unique function to remove duplicate values from arrays
    • Supports custom key selectors for complex objects
    • Preserves original object references

0.6.0 - 2025-05-20

Added

  • New function utilities module enriched with several functions:
    • throttle function to limit how often a function can be called
    • debounce function to delay function execution until after a cooldown period
    • once function to ensure a function is only executed a single time

Changed

  • Removed AI_SUGGESTED_FEATURES.md file from the project

0.5.0 - 2025-05-13

Added

  • Stack<T> and Queue<T> data structures in data-structures module
    • Type-safe generic implementations for Stack and Queue
    • Stack provides LIFO (Last-In-First-Out) operations
    • Queue provides FIFO (First-In-First-Out) operations
    • Comprehensive test suite validating correct behavior

0.4.0 - 2025-05-06

Added

  • shuffle function in Array utilities module for randomly reordering array elements
    • Implements the Fisher-Yates (Knuth) shuffle algorithm
    • Offers efficient in-place shuffling with O(n) time complexity
    • Returns a new shuffled array without modifying the original
    • Fully tested with Jest for randomness and distribution

Changed

  • Added PUBLISHING.md documentation with guidelines for release process
  • Updated .npmignore configuration for better package management
  • Added AI_SUGGESTED_FEATURES.md with potential future development ideas

0.3.0 - 2025-04-29

Added

  • retry function in Promise utilities module for retrying async operations
    • Supports configurable number of attempts, delay, and exponential backoff
    • Provides conditional retry logic through the retryIf option
    • Includes callback for monitoring retry attempts with onRetry
    • Handles and preserves original error context

0.2.2 - 2025-05-10

Changed

  • Reduced npm package size significantly:
    • Enhanced .npmignore configuration to exclude development artifacts
    • Implemented JavaScript minification for production builds
    • Optimized bundle structure for faster downloads and installations
    • Removed source maps and unnecessary files from published package

0.2.1 - 2025-04-22

Added

  • wait function in Promise utilities module that creates a promise resolving after a specified delay
    • Provides a simple way to introduce delays in async code
    • Fully tested with Jest for accurate timing behavior
    • Handles edge cases like zero and negative values appropriately

0.1.0 - 2025-04-08

Added

  • arraySplit function for dividing arrays into chunks based on separators
    • Supports both value-based separation and predicate function criteria
    • Returns multi-dimensional array containing the split chunks
    • Preserves original element order within chunks

0.0.2 - 2025-03-22

Added

  • currentCodeInfo function for obtaining runtime code execution details
    • Returns class name, method name, file path and position information
    • Supports class methods, named functions and anonymous functions
    • Useful for logging, debugging and error reporting

0.0.1 - 2025-03-02

Added

  • Initial release with core utility functions:
    • arraySubtract for removing elements of one array from another
    • randomInt for generating random integers in a specified range
    • randomBoolean for producing random boolean values