@fr0st/core
v3.1.4
Published
Small, focused utility library for arrays, functions, math, objects, strings, and type checks.
Maintainers
Readme
Frost Core
Small, focused utilities for arrays, functions, math, objects, strings, and type checks. Frost Core has zero runtime dependencies, works in Node and bundlers, and also ships a browser-friendly UMD bundle that exposes globalThis._.
Highlights
- Named exports for tree-shaking
- Prebuilt ESM and UMD bundles in
dist/ - No runtime dependencies
- JSDoc-powered IntelliSense
Installation
Node / bundlers
npm i @fr0st/coreFrost Core's package entry point is ESM-only. Use import syntax in Node and bundlers.
import { clamp, randomInt } from '@fr0st/core';Browser (ESM)
Import the minified ESM bundle directly from a CDN:
<script type="module">
import { clamp, randomInt } from 'https://cdn.jsdelivr.net/npm/@fr0st/core@latest/dist/frost-core.esm.min.js';
console.log(clamp(randomInt(10), 0, 9));
</script>Browser (UMD)
Load the bundle from your own copy or a CDN:
<script src="/path/to/dist/frost-core.min.js"></script>
<!-- or -->
<script src="https://cdn.jsdelivr.net/npm/@fr0st/core@latest/dist/frost-core.min.js"></script>
<script>
const { clamp, randomInt } = globalThis._;
console.log(clamp(randomInt(10), 0, 9));
</script>The package root resolves to the prebuilt ESM bundle. Published files under dist/ and src/ are also available through matching package subpaths.
Quick Start
import {
clamp,
debounce,
humanize,
range,
setDot,
} from '@fr0st/core';
const state = { user: { profile: { name: 'Ada' } } };
setDot(state, 'user.profile.name', 'Ada Lovelace');
const values = range(0, 10, 2);
const label = humanize('favoriteColor');
const save = debounce(() => {
console.log('saving', state, values, label);
}, 250);
console.log(clamp(14, 0, 10)); // 10
save();TypeScript note: Frost Core is written in JavaScript and uses JSDoc types, which most editors surface as IntelliSense.
API
All utilities are exported from @fr0st/core as named ESM exports.
Arrays
diff(array, ...arrays): values that exist only in the first arrayintersect(...arrays): unique values shared by all arraysmerge(array, ...arrays): appends arrays or array-like values into the first arrayrandomValue(array): random element from an array, ornullfor an empty arrayrange(start, end, step = 1): numeric sequence fromstarttowardendunique(array): remove duplicate valueswrap(value): normalize a value into an array, returning existing arrays as-is
import { diff, merge, range, unique, wrap } from '@fr0st/core';
diff([1, 2, 3], [2]); // [1, 3]
range(0, 5); // [0, 1, 2, 3, 4, 5]
range(0, 5, 2); // [0, 2, 4]
range(1, 1.4, 0.1); // [1, 1.1, 1.2, 1.3, 1.4]
unique([1, 1, 2]); // [1, 2]
wrap(undefined); // []
wrap(new Set([1, 2])); // [1, 2]
const out = [1];
merge(out, [2, 3]);
// out is now [1, 2, 3]DOM
getDOMProperty(node, property): read a DOM prototype property while bypassing named elements that shadow itcallDOMMethod(node, method, ...args): call a DOM prototype method with the node as its receiver
These helpers use prototype lookup when the prototype chain contains nodeType, bypassing own properties even when the prototype lookup returns undefined. Other values use ordinary property access, including plain document stand-ins and null-prototype objects. No browser globals or DOM constructors are required.
Functions
animation(callback, options): run at most once per animation framecompose(...callbacks): right-to-left function compositioncurry(callback): curry a function until its arity is satisfieddebounce(callback, wait, options): delay execution until calls settleevaluate(value): call a function or return a non-function as-isonce(callback): cache the first returned result, retrying after synchronous errorspartial(callback, ...defaultArgs): partially apply argumentspipe(...callbacks): left-to-right function compositionthrottle(callback, wait, options): run at most once per wait periodtimes(callback, amount): execute a callback repeatedly, stopping if it returnsfalse
import { compose, debounce, once, partial, pipe, throttle } from '@fr0st/core';
const add1 = (n) => n + 1;
const double = (n) => n * 2;
compose(add1, double)(3); // 7
pipe(add1, double)(3); // 8
const init = once(() => Math.random());
init() === init(); // true
partial((a, b) => [a, b], undefined, 2)(1); // [1, 2]
const debounced = debounce((value) => console.log(value), 100);
const throttled = throttle(() => console.log('tick'), 100);
debounced('last');
throttled();Math
clamp(value, min, max): clamp a number between boundsclampPercent(value): clamp a number between0and100dist(x1, y1, x2, y2): distance between two pointsinverseLerp(v1, v2, value): interpolation amount between two valueslen(x, y): vector lengthlerp(v1, v2, amount): linear interpolationmap(value, fromMin, fromMax, toMin, toMax): remap a value from one range to anotherrandom(a, b): random floating-point valuerandomInt(a, b): random integer, throwing when the bounds contain no integertoStep(value, step): round a number to a step size
import { clamp, dist, lerp, map, random, randomInt, toStep } from '@fr0st/core';
clamp(10, 0, 1); // 1
dist(0, 0, 3, 4); // 5
lerp(0, 10, 0.25); // 2.5
map(0.5, 0, 1, 0, 10); // 5
random(10); // 0 <= n < 10
randomInt(10, 50); // 10 <= n < 50
randomInt(1.2, 5.8); // 2, 3, 4, or 5
toStep(0.123, 0.05); // 0.1Objects
extend(object, ...objects): deep-merge values into the first objectflatten(object, prefix = ''): flatten plain-object paths into dot notation while preserving empty objectsforgetDot(object, key): delete a path from an objectgetDot(object, key, defaultValue): read a path from an objecthasDot(object, key): test whether a path existspluckDot(objects, key, defaultValue): read the same path from many objectssetDot(object, key, value, options): assign a path in an object
import { extend, flatten, getDot, pluckDot, setDot } from '@fr0st/core';
const obj = extend({ a: 1 }, { b: { c: 2 } });
getDot(obj, 'b.c'); // 2
flatten({ a: { b: 1 } }); // { 'a.b': 1 }
pluckDot([{ a: { b: 1 } }, { a: { b: 2 } }], 'a.b'); // [1, 2]
setDot(obj, 'b.c', 3);
obj.users = [{ active: false }, { active: false }];
setDot(obj, 'users.*.active', true);
obj.users; // [{ active: true }, { active: true }]
setDot(obj, 'user..name', 'Ada');
getDot(obj, 'user..name'); // 'Ada' (the middle key is an empty string)Strings
camelCase(string): convert text tocamelCasecapitalize(string): upper-case the first character and lower-case the restescape(string): escape HTML entitiesescapeRegExp(string): escape RegExp control charactershumanize(string): convert identifiers into readable wordskebabCase(string): convert text tokebab-casepascalCase(string): convert text toPascalCaserandomString(length, chars): create a random string from non-empty Unicode characterssnakeCase(string): convert text tosnake_caseunescape(string): unescape HTML entities
import { camelCase, escape, humanize, kebabCase, randomString, snakeCase } from '@fr0st/core';
camelCase('HELLO WORLD'); // 'helloWorld'
camelCase('XMLParser'); // 'xmlParser'
camelCase('MySQL'); // 'mySql'
humanize('helloWorld'); // 'Hello world'
kebabCase('helloWorld'); // 'hello-world'
snakeCase('helloWorld'); // 'hello_world'
escape('<div class="x">'); // '<div class="x">'
randomString(8); // e.g. 'aZ02kLmP'Testing
isArray(value)isArrayLike(value)isBoolean(value)isDocument(value)isElement(value)isFragment(value)isFunction(value)isNaN(value)isNode(value)isNull(value)isNumeric(value)isObject(value)isPlainObject(value)isShadow(value)isString(value)isText(value)isUndefined(value)isWindow(value)
import {
isArray,
isArrayLike,
isFunction,
isNumeric,
isPlainObject,
} from '@fr0st/core';
isArray([]); // true
isArrayLike({ 0: 'a', length: 1 }); // true
isFunction(() => {}); // true
isNumeric('123.45'); // true
isPlainObject({}); // trueBehavior Notes
merge()andextend()mutate and return the first argument.extend()recursively merges nested plain objects and arrays, including plain objects from other JavaScript contexts. Nested arrays merge by index and preserve sparse lengths without shortening existing arrays.wrap()returns existing arrays as-is, copies other iterable and array-like objects, and wraps scalar values in an array.undefinedbecomes[].debounce(),throttle(), andanimation()return wrapped functions withcancel().- Function wrappers preserve their call-site
thisvalue, and delayed wrappers use the most recent call-site value. Curried functions keep the context from the first call. range()uses the absolute value ofstep, returns[]forstep === 0, and includesendwhen it aligns with the step, allowing for small floating-point rounding errors.- Dot-path helpers use own properties and treat empty segments as empty-string keys.
setDot()supports*wildcard segments over existing keys and an{ overwrite }option, which defaults totrue.randomString()usesMath.random()and must not be used for passwords, tokens, or other security-sensitive values.random()andrandomInt()use an exclusive upper bound.- With one argument,
random()andrandomInt()use0as the other bound.randomInt()accepts bounds in either order and throws aRangeErrorwhen they contain no integer.
Development
npm test
npm run lint
npm run buildLicense
Frost Core is released under the MIT License.
