@adhd/data-base-transforms
v2.3.0
Published
[](https://www.npmjs.com/package/@adhd/data-base-transforms) [](https://opensource.org/licenses/MIT) [![Build St
Readme
@adhd/data-base-transforms
A comprehensive TypeScript utility library for data-base-transformsing, filtering, analyzing, and manipulating data structures. Designed for use in data pipelines, analytics, and application logic.
Why Use @adhd/data-base-transforms?
- Modular: Includes collections, filters, functions, objects, stats, and text utilities.
- Type-Safe: Built with TypeScript for reliable development and autocompletion.
- Expressive: Provides high-level helpers for common data operations.
- Efficient: Uses optimized native methods and patterns.
- Extensible: Easily compose and extend with your own utilities.
Installation
npm install @adhd/data-base-transforms
# or
pnpm add @adhd/data-base-transformsFunction Outline
Transform: Collections
| Function (params) | Description | | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | difference(arrays: any[][]) | Elements in first array not in others | | intersection(arrays: any[][]) | Elements common to all arrays | | flattenDeep(arr: any[][]) | Deeply flattens nested arrays | | keyByArray(array: any[], key: string) | Indexes array by a key | | keyBy(collection: any[], key: string) | Indexes array or object by a key | | isMatch(obj: any, target: any) | Deep partial match (does obj contain all of target?) | | omitBy(orig: ArrayOrObject, check: BooleanFilter) | Omits entries where check returns true | | pickBy(orig: ArrayOrObject, check: BooleanFilter) | Picks entries where check returns true | | pluck(arr: any[], key: string) | Extracts values for a key from array | | minBy(collection: T[], selector: Selector, compare?: ComparisonFunction) | Finds min by selector | | maxBy(collection: T[], selector: Selector, compare?: ComparisonFunction) | Finds max by selector | | filterInclude(arr: any[], obj) | Filters to items matching obj | | filterExclude(arr: any[], obj) | Filters out items matching obj | | first(arr: any[]) | Returns first element | | last(arr: any[]) | Returns last element | | unique(arr: any[]) | Returns unique elements | | uniqueBy(arr: any[], props: string[]) | Unique by multiple properties | | indexBy(arr: any[], prop: string) | Indexes array by property | | range(start: number, stop: number, step: number) | Generates a range of numbers |
Transform: Filters
| Function (params) | Description | | ---------------------------------------------------- | ------------------------------------- | | isArray(x: unknown) | Checks if value is array | | isString(x: unknown) | Checks if value is string | | isDefined(x: unknown) | Checks if value is not null/undefined | | isInt(x: unknown) | Checks if value is integer | | isFloat(x: unknown) | Checks if value is float | | isRegExp(x: unknown) | Checks if value is RegExp | | isTrue(a: any) | Checks if value is true | | isFalse(a: any) | Checks if value is false | | isLessThan(a: number, b: number) | Checks if a < b | | isGreaterThan(a: number, b: number) | Checks if a > b | | isIn(a: any, b: OneOfType<string,any[]>) | Checks if a in b | | isLike(a: string, b: string) | Checks if a contains b |
Transform: Objects
| Function (params) | Description | | ------------------------------------------------ | ----------------------------------------- | | keys(obj: object) | Returns object keys | | values(obj: object) | Returns object values | | entries(obj: object) | Returns object entries | | stringify(obj: object) | JSON stringify | | groupBy(arr: any[], props: string[]) | Groups array by properties | | omit(object, keys) | Omits specified keys | | pick(object, keys) | Picks specified keys | | allPaths(obj, matcher?) | Enumerates all paths of an object | | objectDifference(object, base) | Calculates difference between two objects | | deepCopy(object1: any) | Deep copy object | | deepEquals(object1, object2) | Deep equality check |
Transform: Stats
| Function (params) | Description | | --------------------------------------------------------- | ----------------------------- | | minMax(list: number[]) | Min/max of list | | randomRange(a: number, b: number) | Random float between a and b | | randomRangeInt(a: number, b: number) | Random int between a and b | | roundToIncrement(x: number, increment: number) | Rounds to increment | | normalizeBetween(x, min, max, newMin?, newMax?) | Normalizes value to new range | | normalize(list: number[], bounds?) | Normalizes a list to bounds | | getMin(a: number, b: number) | Minimum of two numbers | | getMax(a: number, b: number) | Maximum of two numbers | | histogram(iterable: any[]) | Histogram of values | | mostCommon(iterable: any[]) | Most common value |
Transform: Texts
| Function (params) | Description | | ------------------------------------------------ | -------------------------- | | capitalize(str: string) | Capitalizes string | | trim(str: string, c?: string) | Trims whitespace | | upperFirst(str: string) | Uppercases first character | | lowerFirst(str: string) | Lowercases first character | | trimStart(str: string, c?: string) | Trims start | | trimEnd(str: string, c?: string) | Trims end | | words(value: string) | Splits into words | | hyphenCase(str: string) | Converts to hyphen-case | | percent(n: number, precision?: number) | Formats percent |
Transform: Functions
| Function (params) | Description | | ---------------------------------------------------------------- | ----------------------------------- | | compose(...funcs: Function[]) | Composes functions | | noop() | No-op function | | extractThen(key: string, callback: Function) | Extracts value and applies callback | | get(obj: object, path: string, defaultValue?: any) | Gets value at path | | set(data: object, path: string, value: any) | Sets value at path | | getAll(obj, paths: string[]) | Gets values at multiple paths | | flow(funcs: Function[]) | Pipes value through functions | | partial(func, ...boundArgs) | Partially applies arguments | | throttle(func: Function, timeFrame: number) | Throttles function | | Differ.map(obj1, obj2) | Computes deep diff between objects |
Transform: Humanize
| Function (params) | Description | | ------------------------------------------------------------ | -------------------------------------- | | humanizeBytes(bytes: number, decimals?: number) | Formats bytes to human-readable string |
Transform: Date
| Function (params) | Description | | --------------------------------------------------- | ------------------------------------- | | formatDate(date: Date, formatStr?: string) | Formats date with format string | | humanDuration(d0: Date, d1: Date, unit?) | Human-readable duration between dates | | timeFromNow(date: Date) | Duration from now to date | | fromNow(count: number, unit?: string) | Date in the future from now |
Transform: Regex
| Function (params) | Description | | --------------------------------------------------- | ------------------------------------ | | escapePattern(s: string) | Escapes regex special characters | | mergePatterns(values: (string|number)[]) | Merges values into alternation regex | | rangeToRegex(n1?: number, n2?: number) | Numeric range to regex pattern |
Transform: Structures
| Class / Function | Description | | --------------------------- | ------------------------------------------------------------------------------ | | Stack<T> | LIFO stack with optional typed event callbacks (onPush, onPop, onClear) | | Queue<T> | FIFO queue with optional typed event callbacks (onEnqueue, onDequeue, onClear) | | Counter<T> | Tracks counts by key with optional typed key extractor function |
Collections
import { Collections } from '@adhd/data-base-transforms';
// difference: Elements in arr1 not in arr2
Collections.difference([
[1, 2, 3],
[2, 3, 4],
]); // [1]
// intersection: Elements common to both arrays
Collections.intersection([
[1, 2, 3],
[2, 3, 4],
]); // [2, 3]
// flattenDeep: Deeply flattens nested arrays
Collections.flattenDeep([[1, [2, [3]]], 4]); // [1, 2, 3, 4]
// keyByArray: Indexes array by a key
Collections.keyByArray([{ id: 1 }, { id: 2 }], 'id'); // { 1: { id: 1 }, 2: { id: 2 } }
// keyBy: Indexes array or object by a key
Collections.keyBy([{ id: 1 }, { id: 2 }], 'id'); // { 1: { id: 1 }, 2: { id: 2 } }
// omitBy: Omits entries where check returns true
Collections.omitBy({ a: 1, b: 2 }, (v) => v === 2); // { a: 1 }
// pickBy: Picks entries where check returns true
Collections.pickBy({ a: 1, b: 2 }, (v) => v === 2); // { b: 2 }
// pluck: Extracts values for a key from array
Collections.pluck([{ a: 1 }, { a: 2 }], 'a'); // [1, 2]
// minBy: Finds min by selector
Collections.minBy([{ x: 1 }, { x: 2 }], (o) => o.x); // { x: 1 }
// maxBy: Finds max by selector
Collections.maxBy([{ x: 1 }, { x: 2 }], (o) => o.x); // { x: 2 }
// first: Returns first element
Collections.first([1, 2, 3]); // 1
// last: Returns last element
Collections.last([1, 2, 3]); // 3
// unique: Returns unique elements
Collections.unique([1, 2, 2, 3]); // [1, 2, 3]
// uniqueBy: Unique by multiple properties
Collections.uniqueBy(
[
{ a: 1, b: 2 },
{ a: 1, b: 3 },
],
['a']
); // [{ a: 1, b: 2 }]
// indexBy: Indexes array by property
Collections.indexBy([{ id: 'a' }, { id: 'b' }], 'id'); // { a: { id: 'a' }, b: { id: 'b' } }
// isMatch: Deep partial match
Collections.isMatch({ a: 1, b: 2 }, { a: 1 }); // true
Collections.isMatch({ a: 1 }, { a: 1, b: 2 }); // false
// filterInclude/filterExclude: Filter by match
Collections.filterInclude([{ a: 1 }, { a: 2 }], { a: 1 }); // [{ a: 1 }]
Collections.filterExclude([{ a: 1 }, { a: 2 }], { a: 1 }); // [{ a: 2 }]
// range: Generates a range of numbers
Collections.range(1, 5, 1); // [1, 2, 3, 4, 5]Filters
import { Filters } from '@adhd/data-base-transforms';
// isArray: Checks if value is array
Filters.isArray([1, 2, 3]); // true
// isString: Checks if value is string
Filters.isString('hello'); // true
// isDefined: Checks if value is not null/undefined
Filters.isDefined(undefined); // false
// isInt: Checks if value is integer
Filters.isInt(42); // true
// isFloat: Checks if value is float
Filters.isFloat(3.14); // true
// isRegExp: Checks if value is RegExp
Filters.isRegExp(/abc/); // true
// isTrue: Checks if value is true
Filters.isTrue(true); // true
// isFalse: Checks if value is false
Filters.isFalse(false); // true
// isLessThan: Checks if a < b
Filters.isLessThan(1, 2); // true
// isGreaterThan: Checks if a > b
Filters.isGreaterThan(2, 1); // true
// isIn: Checks if a in b
Filters.isIn(2, [1, 2, 3]); // true
// isLike: Checks if a contains b
Filters.isLike('hello world', 'world'); // trueObjects
import { Objects } from '@adhd/data-base-transforms';
// keys: Returns object keys
Objects.keys({ a: 1, b: 2 }); // ['a', 'b']
// values: Returns object values
Objects.values({ a: 1, b: 2 }); // [1, 2]
// entries: Returns object entries
Objects.entries({ a: 1, b: 2 }); // [['a', 1], ['b', 2]]
// deepEquals: Deep equality check
Objects.deepEquals({ x: 1 }, { x: 1 }); // true
// objectDifference: Diff between two objects
Objects.objectDifference({ a: 1, b: 2 }, { a: 1 }); // { b: 2 }
// omit/pick: Select or exclude keys
Objects.omit({ a: 1, b: 2 }, ['a']); // { b: 2 }
Objects.pick({ a: 1, b: 2 }, ['a']); // { a: 1 }
// groupBy: Groups array by properties
Objects.groupBy([{ a: 1 }, { a: 2 }], ['a']);
// deepCopy: Deep copy object
Objects.deepCopy({ a: 1 }); // { a: 1 }
// allPaths: Enumerate all primitive-holding paths
Objects.allPaths({ x: { y: 1, z: [2] } }); // [['x', 'y'], ['x', 'z']]Stats
import { Stats } from '@adhd/data-base-transforms';
// minMax: Min/max of list
Stats.minMax([1, 2, 3, 4, 5]); // { min: 1, max: 5 }
// normalize: Normalize list to bounds
Stats.normalize([1, 2, 3, 4, 5], { min: 0, max: 4 }); // [0, 1, 2, 3, 4]
// randomRange: Random float between a and b
Stats.randomRange(10, 20); // e.g. 13.45
// randomRangeInt: Random int between a and b
Stats.randomRangeInt(1, 5); // e.g. 3
// roundToIncrement: Rounds to increment
Stats.roundToIncrement(7.3, 2); // 8
// getMin/getMax: Minimum/maximum of two numbers
Stats.getMin(3, 7); // 3
Stats.getMax(3, 7); // 7
// histogram: Histogram of values
Stats.histogram([1, 2, 2, 3]); // Map { 1 => 1, 2 => 2, 3 => 1 }
// mostCommon: Most common value
Stats.mostCommon([1, 2, 2, 3]); // 2Texts
import { Texts } from '@adhd/data-base-transforms';
// capitalize: Capitalizes string
Texts.capitalize('hello world'); // 'Hello world'
// trim: Trims whitespace
Texts.trim(' hello '); // 'hello'
// upperFirst: Uppercases first character
Texts.upperFirst('foo'); // 'Foo'
// lowerFirst: Lowercases first character
Texts.lowerFirst('Bar'); // 'bar'
// trimStart: Trims start
Texts.trimStart(' hello'); // 'hello'
// trimEnd: Trims end
Texts.trimEnd('hello '); // 'hello'
// words: Splits into words
Texts.words('hello world'); // ['hello', 'world']
// hyphenCase: Converts to hyphen-case
Texts.hyphenCase('Hello World'); // 'hello-world'
// percent: Formats percent
Texts.percent(0.1234); // '12.34%'Structures
import { Stack, Queue, Counter } from '@adhd/data-base-transforms';
// Stack: LIFO stack with event callbacks
const stack = new Stack<number>({
onPush: (value) => console.log('Pushed:', value),
onPop: (value) => console.log('Popped:', value),
onClear: () => console.log('Stack cleared'),
});
stack.push(1); // Logs: Pushed: 1
stack.push(2); // Logs: Pushed: 2
stack.pop(); // Logs: Popped: 2
stack.peek(); // Returns 1 (doesn't log)
stack.size; // 1
stack.isEmpty; // false
stack.clear(); // Logs: Stack cleared
// Queue: FIFO queue with event callbacks
const queue = new Queue<string>([], {
onEnqueue: (value) => console.log('Enqueued:', value),
onDequeue: (value) => console.log('Dequeued:', value),
onClear: () => console.log('Queue cleared'),
});
queue.enqueue('a'); // Logs: Enqueued: a
queue.enqueue('b'); // Logs: Enqueued: b
queue.dequeue(); // Logs: Dequeued: a
queue.length; // 1
// Counter: Track numeric values by key
const counter = new Counter<string>();
counter.increment('requests', 5); // Increment by 5
counter.increment('requests', 3); // Now 8
counter.decrement('requests', 2); // Now 6
console.log(counter.value('requests')); // 6
console.log(counter.toJson()); // { requests: 6 }
counter.reset('requests');
console.log(counter.value('requests')); // 0
// Counter with key extractor: Track by type
interface Item {
type: string;
count: number;
}
const typeCounter = new Counter<Item>((item) => item.type);
typeCounter.increment({ type: 'site', count: 0 }, 2);
typeCounter.increment({ type: 'local', count: 0 }, 1);
typeCounter.increment({ type: 'site', count: 0 });
typeCounter.decrement({ type: 'site', count: 0 });
console.log(typeCounter.toJson()); // { site: 2, local: 1 }
// Real-world example: Pipeline stack with live counter tracking
const pipeline = new Stack<[string, object]>();
const pipelineCounter = new Counter<[string, object]>((value) => value[0]);
const stackWithCounters = new Stack<[string, object]>({
onPush: (value) => pipelineCounter.increment(value),
onPop: (value) => pipelineCounter.decrement(value),
onClear: () => pipelineCounter.clear(),
});
stackWithCounters.push(['fetched', { url: 'https://...' }]);
stackWithCounters.push(['parsed', { content: '...' }]);
console.log(pipelineCounter.toJson()); // { fetched: 1, parsed: 1 }
const item = stackWithCounters.pop(); // Decrements 'parsed'
console.log(pipelineCounter.toJson()); // { fetched: 1, parsed: 0 }Functions
import { Functions } from '@adhd/data-base-transforms';
// compose: Composes functions
const add = (a: number) => a + 1;
const double = (a: number) => a * 2;
const composed = Functions.compose(add, double);
composed(3); // add(double(3)) => add(6) => 7
// noop: No-op function
Functions.noop(); // null
// extractThen: Extracts value and applies callback
Functions.extractThen('id', (id: number) => id * 2)([{ id: 5 }]); // 10
// get: Gets value at path
Functions.get({ a: { b: 2 } }, 'a.b'); // 2
// set: Sets value at path
const obj = { a: { b: 2 } };
Functions.set(obj, 'a.b', 3); // obj.a.b === 3
// throttle: Throttles function
const throttled = Functions.throttle(() => console.log('hi'), 1000);
throttled();API Reference
Collections: Array manipulation (difference, intersection, flatten, keyBy, isMatch, filterInclude, filterExclude, etc.)Filters: Type checks and comparison helpers (isArray,isString,isDefined,isEqual,isIn,isLike, etc.)Objects: Object utilities (keys,values,entries,omit,pick,groupBy,objectDifference,allPaths, etc.)Stats: Math and statistics helpers (minMax,normalize,normalizeBetween,histogram,mostCommon, etc.)Texts: String manipulation (capitalize,trim,upperFirst,words,hyphenCase, etc.)Functions: Function composition and helpers (compose,get,set,flow,partial,Differ, etc.)Humanize: Human-readable formatting (humanizeBytes)Date: Date utilities (formatDate,humanDuration,timeFromNow,fromNow)Regex: Regex utilities (escapePattern,mergePatterns,rangeToRegex)Structures: Data structures (Stack<T>,Queue<T>,Counter) with optional event callbacks
File Structure
src/lib/collections.ts– Array utilities and deep matchingsrc/lib/filters.ts– Type checks and comparisonssrc/lib/function.ts– Function helpers, path access, diffingsrc/lib/object.ts– Object utilitiessrc/lib/stats.ts– Math and statisticssrc/lib/text.ts– String utilitiessrc/lib/humanize.ts– Human-readable formattingsrc/lib/date.ts– Date utilitiessrc/lib/regex.ts– Regex utilitiessrc/lib/structures.ts– Stack, Queue, and Counter data structures
Testing
pnpm testExtending
- Add new utilities in the relevant module (collections, filters, etc.)
- Compose with existing helpers for advanced data data-base-transformsations
Contributing
Contributions are welcome! Please read the CONTRIBUTING.md for guidelines.
License
For more information, see the API docs or visit the GitHub repository.
