UNPKG

supergeneric

Version:

Supergeneric JS helper functions... formatters, math functions, sort functions, etc.

393 lines (281 loc) 10.9 kB
# supergeneric [![Version](https://img.shields.io/npm/v/supergeneric.svg?style=flat-square)](https://npmjs.com/package/supergeneric) [![Bundle Size](https://deno.bundlejs.com/?q=supergeneric&badge&badge-style=flat-square)](https://deno.bundlejs.com/?q=supergeneric) [![Coverage Status](https://img.shields.io/coveralls/github/kwhitley/supergeneric?style=flat-square)](https://coveralls.io/github/kwhitley/supergeneric) [![Issues](https://img.shields.io/github/issues/kwhitley/supergeneric?style=flat-square)](https://github.com/kwhitley/supergeneric/issues) [![Discord](https://img.shields.io/discord/832353585802903572?label=Discord&logo=Discord&style=flat-square&logoColor=fff)](https://discord.gg/53vyrZAu9u) A collection of lightweight, tree-shakable TypeScript utility functions for mathematical operations, array manipulation, object handling, and more. Designed for modern JavaScript/TypeScript projects with full type safety. ## Installation ```bash npm install supergeneric ``` ## Usage ```typescript // Import individual functions (recommended for tree-shaking) import { sum, average, sortBy } from 'supergeneric' // Or import specific functions directly import { sum } from 'supergeneric/sum' import { sortBy } from 'supergeneric/sortBy' ``` # Migrating from v3.x to v4.x Version 4.x includes several breaking changes and optimizations: ### 🗑️ Removed Functions - **`getMilliseconds()`** - Duration string parsing function has been removed - **`console`** - Color-injected console object has been removed ### ⚡ Performance Improvements - **`min()` and `max()`** - No longer use spread operator (`Math.min(...values)`), now use optimized loops - **Why**: Fixes "Maximum call stack size exceeded" errors on large arrays (>100k elements) - **Impact**: More reliable for large datasets, slightly larger bundle size (+30B gzipped each) - **Migration**: No code changes needed, functions work identically but handle large arrays better ### 🔧 API Changes - **`min()` and `max()`** - Now handle empty arrays consistently with other math functions - **Before**: `min([])` would return `Infinity`, `max([])` would return `-Infinity` - **After**: `min([])` and `max([])` return `undefined` (following the same pattern as `first()` and `last()`) ### 📦 Bundle Size Optimizations - Code-golfed optimizations applied across all functions for smaller bundle sizes - Bitwise operations used where appropriate (`>>` instead of `Math.floor`, `&` instead of `%`) - Eliminated unnecessary intermediate variables and redundant operations ### 🎯 Migration Guide **If you were using removed functions:** ```typescript // v3.x - REMOVED in v4.x import { getMilliseconds, console } from 'supergeneric' // v4.x - Use alternatives // For getMilliseconds: Use a dedicated duration parsing library like 'itty-time' or 'ms' import ms from 'itty-time' ms('1 hour') // 3600000 // For colored console: Use libraries like 'chalk' or 'kleur' import chalk from 'chalk' console.log(chalk.blue('Hello')) ``` **For large array handling (automatic improvement):** ```typescript // v3.x - Could fail on large arrays const largeArray = Array(200000).fill(0).map((_, i) => i) min(largeArray) // RangeError: Maximum call stack size exceeded // v4.x - Works reliably min(largeArray) // 0 (no errors) ``` All other functions remain backward compatible with the same APIs. # API Reference ## 📊 Mathematical Functions ### `sum(values: number[]): number` Returns the sum of all values in the array. ```typescript sum([1, 2, 3, 4]) // 10 ``` ### `average(values: number[]): number` Returns the arithmetic mean of all values. ```typescript average([1, 2, 3, 4]) // 2.5 ``` ### `mean(values: number[]): number` Alias for `average()`. Returns the arithmetic mean. ```typescript mean([1, 2, 3, 4]) // 2.5 ``` ### `min(values: number[]): number` Returns the smallest value. Optimized for large arrays. ```typescript min([7, 1, 4, 2]) // 1 ``` ### `max(values: number[]): number` Returns the largest value. Optimized for large arrays. ```typescript max([7, 1, 4, 2]) // 7 ``` ### `median(values: any[], sortBy?: (a: any, b: any) => number): any` Returns the median value from an array. ```typescript median([1, 2, 3, 4, 5]) // 3 median([1, 2, 3, 4]) // 2.5 // With custom comparator const items = [{ value: 3 }, { value: 1 }, { value: 4 }] median(items, (a, b) => a.value - b.value) // { value: 3 } ``` ### `stddev(values: number[]): number` Returns the standard deviation using the sample formula (n-1). ```typescript stddev([1, 2, 3, 4, 5]) // 1.5811388300841898 ``` ### `round(value: number, precision?: number): number` Rounds a number to the specified decimal places (default: 0). ```typescript round(3.14159) // 3 round(3.14159, 2) // 3.14 ``` ### `rounder(precision?: number): (value: number) => number` Returns a curried rounding function with preset precision. ```typescript const roundTo2 = rounder(2) [3.14159, 2.71828].map(roundTo2) // [3.14, 2.72] ``` ## 🔀 Array Functions ### `first<T>(values: T[]): T | undefined` Returns the first element of an array. ```typescript first([1, 2, 3]) // 1 first([]) // undefined ``` ### `last<T>(values: T[]): T | undefined` Returns the last element of an array. ```typescript last([1, 2, 3]) // 3 last([]) // undefined ``` ### `ascending<T>(a: T, b: T): number` Comparator function for ascending sort. ```typescript [3, 1, 4, 1, 5].sort(ascending) // [1, 1, 3, 4, 5] ``` ### `descending<T>(a: T, b: T): number` Comparator function for descending sort. ```typescript [3, 1, 4, 1, 5].sort(descending) // [5, 4, 3, 1, 1] ``` ### `sortBy<T>(key: keyof T | ((item: T) => any), options?: { descending?: boolean }): (a: T, b: T) => number` Creates a comparator function for sorting by property or extractor function. ```typescript const users = [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }, { name: 'Carol', age: 35 } ] // Sort by property users.sort(sortBy('age')) // sorted by age ascending users.sort(sortBy('name', { descending: true })) // by name descending // Sort by function users.sort(sortBy(u => u.name.length)) // by name length ``` ### `range(length?: number, options?: { from?: number }): number[]` Creates an array of sequential numbers. ```typescript range(5) // [0, 1, 2, 3, 4] range(3, { from: 5 }) // [5, 6, 7] ``` ### `transpose<T>(matrix: T[][]): T[][]` Transposes a 2D array (swaps rows and columns). ```typescript transpose([[1, 2], [3, 4], [5, 6]]) // [[1, 3, 5], [2, 4, 6]] ``` ### `onlyNumbers(values: any[]): number[]` Filters an array to only numeric values. ```typescript onlyNumbers([1, 'hello', 2.5, null, 42]) // [1, 2.5, 42] ``` ## 🎲 Random Functions ### `random(min: number, max: number): number` Returns a random integer between min and max (inclusive). ```typescript random(1, 6) // 4 (dice roll) random(10, 20) // 15 ``` ### `randomItem<T>(items: T[] | string): T | string` Returns a random element from an array or character from a string. ```typescript randomItem([1, 2, 3, 4, 5]) // 3 randomItem('hello') // 'e' ``` ### `randomArray(length?: number, fn?: () => any): any[]` Creates an array filled with results from a function. ```typescript randomArray(3) // [0.234, 0.789, 0.456] (random numbers) randomArray(3, () => random(1, 10)) // [7, 2, 9] ``` ### `generateHash(length?: number, options?: GenerateHashOptions): string` Generates a random alphanumeric string with extensive customization options. ```typescript generateHash() // 'aB3kL9' (6 chars, starts with letter) generateHash(8) // 'mK2pQ7R4' // Advanced options generateHash(10, { startWithLetter: false, ambiguous: false, // excludes similar-looking chars symbols: '!@#', only: 'ABCDEF123' // custom character set }) ``` ## 🔧 Utility Functions ### `binarySearch<T>(values: T[], by?: (item: T) => any): (target: any) => { item: T; index: number } | undefined` Performs binary search on a sorted array. Returns a search function. ```typescript const numbers = [1, 3, 5, 7, 9, 11] const search = binarySearch(numbers) search(5) // { item: 5, index: 2 } search(4) // undefined // With extractor function const items = [{ id: 1 }, { id: 3 }, { id: 5 }] const searchById = binarySearch(items, item => item.id) searchById(3) // { item: { id: 3 }, index: 1 } ``` ### `makePath(...segments: any[]): string` Joins path segments with '/' delimiter, handling empty values and duplicates. ```typescript makePath('users', 42, 'profile') // 'users/42/profile' makePath('api/', undefined, 'v1') // 'api/v1' // Custom delimiter makePath('a', 'b', 'c', { delimiter: '.' }) // 'a.b.c' ``` ### `required(message: string): never` Throws an error with the given message. Useful for required parameters. ```typescript function greet(name = required('name is required')) { return `Hello, ${name}!` } greet('Alice') // 'Hello, Alice!' greet() // throws: Error('name is required') ``` ## 🗃️ Object Functions ### `merge(...objects: object[]): object` Merges multiple objects into one. ```typescript merge({ a: 1 }, { b: 2 }, { c: 3 }) // { a: 1, b: 2, c: 3 } ``` ### `mergeClean(...objects: object[]): object` Merges objects and removes undefined properties. ```typescript mergeClean({ a: 1, b: undefined }, { c: 3 }) // { a: 1, c: 3 } ``` ### `numbers(value: any): any` Converts a value to a number if possible, otherwise returns unchanged. ```typescript ['1', '2.5', 'hello', 3].map(numbers) // [1, 2.5, 'hello', 3] ``` ### `dates(obj: any, key: string): any` Converts date-like properties to Date objects. ```typescript const data = { created_at: '2023-01-01', updated_time: '2023-12-31' } // Use with recurse() to process nested objects ``` ## 🔄 Data Transformation ### `convert(data: any, ...fns: Function[]): any` Applies multiple transformation functions to data recursively. ```typescript const data = { values: ['1', '2', '3'] } convert(data, numbers) // { values: [1, 2, 3] } ``` ### `recurse(fn: Function): (data: any) => any` Creates a function that applies a transformation recursively to nested data. ```typescript const deepNumbers = recurse(numbers) deepNumbers({ a: '1', b: { c: '2', d: ['3', '4'] } }) // { a: 1, b: { c: 2, d: [3, 4] } } ``` ## TypeScript Support All functions include full TypeScript definitions with proper generic types where applicable. The library is built with TypeScript and provides excellent IntelliSense support. ## Tree Shaking Import only the functions you need for optimal bundle size: ```typescript // Only imports the sum function import { sum } from 'supergeneric' // Or import directly for maximum tree-shaking import { sum } from 'supergeneric/sum' ``` ## Performance - Mathematical functions use optimized loops instead of spread operators for large arrays - Binary search provides O(log n) performance for sorted data - All functions are pure and side-effect free where possible ## License MIT