npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adhd/data-base-transforms

v2.3.0

Published

[![npm version](https://img.shields.io/npm/v/@adhd/data-base-transforms.svg)](https://www.npmjs.com/package/@adhd/data-base-transforms) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Build St

Readme

@adhd/data-base-transforms

npm version License: MIT Build Status

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-transforms

Function 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'); // true

Objects

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]); // 2

Texts

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 matching
  • src/lib/filters.ts – Type checks and comparisons
  • src/lib/function.ts – Function helpers, path access, diffing
  • src/lib/object.ts – Object utilities
  • src/lib/stats.ts – Math and statistics
  • src/lib/text.ts – String utilities
  • src/lib/humanize.ts – Human-readable formatting
  • src/lib/date.ts – Date utilities
  • src/lib/regex.ts – Regex utilities
  • src/lib/structures.ts – Stack, Queue, and Counter data structures

Testing

pnpm test

Extending

  • 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

MIT


For more information, see the API docs or visit the GitHub repository.