Agent Skills: JavaScript Micro-Utilities

Zero-dependency JavaScript utilities using native APIs and just-* micro-packages. Use when manipulating objects, arrays, strings, numbers, or functions. Scan tables for native solution first (backticks), fall back to just-* package only when needed. Prefer native over dependencies.

UncategorizedID: matthewharwood/fantasy-phonics/js-micro-utilities

Install this agent skill to your local

pnpm dlx add-skill https://github.com/matthewharwood/fantasy-phonics/tree/HEAD/.claude/skills/js-micro-utilities

Skill Files

Browse the full folder contents for js-micro-utilities.

Download Skill

Loading file tree…

.claude/skills/js-micro-utilities/SKILL.md

Skill Metadata

Name
js-micro-utilities
Description
Zero-dependency JavaScript utilities using native APIs and just-* micro-packages. Use when manipulating objects, arrays, strings, numbers, or functions. Scan tables for native solution first (backticks), fall back to just-* package only when needed. Prefer native over dependencies.

JavaScript Micro-Utilities

Zero-dependency utilities for common JavaScript operations. Prefer native APIs (in backticks) over packages. Install just-* packages only when native solutions don't exist.

Installation

npm i just-diff just-compare just-extend just-pick just-omit  # objects
npm i just-shuffle just-partition just-range just-order-by    # arrays
npm i just-debounce-it just-throttle just-memoize just-once   # functions

Import with ESM:

import diff from 'just-diff';
import shuffle from 'just-shuffle';

Collections {}[]

| Need | Solution | |------|----------| | Deep diff two objects/arrays | just-diff | | Apply JSON-patch to object | just-diff-apply | | Deep equality check | just-compare | | Deep clone | structuredClone(obj) | | Extract property from array | arr.map(x => x.prop) | | Remove nullish from array | arr.filter(x => x != null) |


Objects {}

Merging

| Need | Solution | |------|----------| | Deep merge | just-extend | | Shallow merge | {...a, ...b} or Object.assign(target, src) |

Extracting

| Need | Solution | |------|----------| | Values as array | Object.values(obj) | | Key-value pairs | Object.entries(obj) | | Keep only certain keys | just-pick | | Exclude certain keys | just-omit |

Transforming

// Filter properties
Object.fromEntries(Object.entries(obj).filter(([k, v]) => predicate(k, v)))

// Map values
Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)]))

// Map keys
Object.fromEntries(Object.entries(obj).map(([k, v]) => [fn(k), v]))

// Swap keys/values
Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]))

// Reduce to value
Object.entries(obj).reduce((acc, [k, v]) => ..., init)

Deep Operations

| Need | Solution | |------|----------| | Map values recursively | just-deep-map-values | | Safe nested get | obj?.a?.b?.c | | Safe nested set | just-safe-set | | Check nested exists | obj?.a?.b !== undefined |

Type Checking

| Need | Solution | |------|----------| | Is empty | just-is-empty | | Has circular refs | just-is-circular | | Is primitive | typeof x !== 'object' \|\| x === null | | Better typeof | just-typeof (distinguishes array, null, date, regexp) |


Arrays []

Access

| Need | Solution | |------|----------| | Last element | arr.at(-1) | | All except first | arr.slice(1) | | Random element | just-random |

Creating

| Need | Solution | |------|----------| | Number sequence | just-range | | All combinations | just-cartesian-product | | All orderings | just-permutations |

Transforming

| Need | Solution | |------|----------| | Dedupe primitives | [...new Set(arr)] | | Flatten nested | arr.flat(depth) | | Remove falsy | arr.filter(Boolean) | | Shuffle | just-shuffle | | Chunk into groups | just-split |

Sorting

| Need | Solution | |------|----------| | Immutable sort by prop | arr.toSorted((a, b) => a.prop - b.prop) | | Multi-prop sort | just-order-by |

Set Operations

| Need | Solution | |------|----------| | Intersection | arr1.filter(x => arr2.includes(x)) | | Difference | arr.filter(x => !remove.includes(x)) | | Union (deduped) | [...new Set([...a, ...b])] |

Splitting

// Split at index
[arr.slice(0, i), arr.slice(i)]

// Split by predicate → [matches, nonMatches]
import partition from 'just-partition';
const [evens, odds] = partition(arr, x => x % 2 === 0);

Grouping

// Native grouping (ES2024)
Object.groupBy(arr, item => item.category)

// Array to object by key
Object.fromEntries(arr.map(x => [x[key], x]))

// Zip arrays together
import zip from 'just-zip-it';
zip([1, 2], ['a', 'b']) // [[1, 'a'], [2, 'b']]

Inserting

// Insert at index (immutable)
arr.toSpliced(i, 0, ...items)

Statistics Σ

| Need | Solution | |------|----------| | Average | arr.reduce((a, b) => a + b, 0) / arr.length | | Median | just-median | | Mode | just-mode | | Percentile | just-percentile | | Variance | just-variance | | Std deviation | just-standard-deviation | | Skewness | just-skewness |


Strings ""

Padding & Truncation

| Need | Solution | |------|----------| | Pad start | str.padStart(n, char) | | Pad end | str.padEnd(n, char) | | Truncate with ... | just-truncate | | Truncate at word | just-prune |

Case Conversion

| Need | Solution | |------|----------| | camelCase | just-camel-case | | kebab-case | just-kebab-case | | snake_case | just-snake-case | | PascalCase | just-pascal-case | | Capitalize first | str[0].toUpperCase() + str.slice(1) |

Replacement

| Need | Solution | |------|----------| | Replace all | str.replaceAll(find, replace) | | Remove whitespace | str.replaceAll(' ', '') | | Template interpolation | just-template (supports {{a.b.c}} paths) |


Numbers +-

| Need | Solution | |------|----------| | Clamp to range | Math.min(Math.max(n, min), max) | | Is prime | just-is-prime | | True modulo (neg-safe) | just-modulo | | Random int in range | Math.floor(Math.random() * (max - min + 1)) + min |


Functions =>

Composition

| Need | Solution | |------|----------| | Right-to-left f(g(h(x))) | just-compose | | Left-to-right h(g(f(x))) | just-pipe |

Partial Application

| Need | Solution | |------|----------| | Curry | just-curry-it | | Fix args with placeholders | just-partial-it | | Swap first two args | just-flip | | Method to function | Function.prototype.call.bind(method) |

Rate Limiting

| Need | Solution | |------|----------| | Debounce (wait for pause) | just-debounce-it | | Throttle (once per interval) | just-throttle | | Run only first call | just-once |

Caching

| Need | Solution | |------|----------| | Memoize by args | just-memoize | | Cache last call only | just-memoize-last |


Quick Reference

Most Common Native

// Clone
const copy = structuredClone(obj);

// Dedupe
const unique = [...new Set(arr)];

// Last element
const last = arr.at(-1);

// Safe access
const val = obj?.deeply?.nested?.prop;

// Group by
const grouped = Object.groupBy(items, x => x.type);

// Immutable sort
const sorted = arr.toSorted((a, b) => a.name.localeCompare(b.name));

Most Common just-*

import debounce from 'just-debounce-it';
import throttle from 'just-throttle';
import pick from 'just-pick';
import omit from 'just-omit';
import shuffle from 'just-shuffle';
import partition from 'just-partition';

// Debounce input handler
const handleInput = debounce(value => search(value), 300);

// Throttle scroll handler
const handleScroll = throttle(() => updatePosition(), 100);

// Pick specific keys
const subset = pick(user, ['id', 'name', 'email']);

// Omit sensitive keys
const safe = omit(user, ['password', 'token']);

// Shuffle array
const randomized = shuffle(cards);

// Split by condition
const [valid, invalid] = partition(inputs, x => x.isValid);

Decision Tree

  1. Can native API do it? → Use native (zero deps)
  2. Is it a one-liner? → Write inline
  3. Need tested edge cases? → Use just-* package
  4. Complex algorithm? → Use just-* package
JavaScript Micro-Utilities Skill | Agent Skills