JavaScript/TypeScript utility functions
npm install @osmova/js-utils
npm install js-utils
yarn add js-utils
formatCurrency(value, currency?, locale?) | Formats number as currency with locale support | formatCurrency(1234.56) → "1 234,56 €" |
formatNumber(value, options?) | Formats number with locale-specific separators | formatNumber(1234.56, {decimals: 2}) → "1 234,56" |
formatPercent(value, options?) | Formats number as percentage | formatPercent(0.1556) → "15,56 %" |
clamp(value, min, max) | Clamps number between min and max values | clamp(150, 0, 100) → 100 |
randomInt(min, max) | Generates random integer between min and max (inclusive) | randomInt(1, 10) → 7 |
chunk(array, size) | Splits array into chunks of specified size | chunk([1,2,3,4,5], 2) → [[1,2], [3,4], [5]] |
uniq(array) | Removes duplicate values from array | uniq([1,2,2,3]) → [1,2,3] |
unique(array) | Alias for uniq | unique([1,2,2,3]) → [1,2,3] |
compact(array) | Removes falsy values from array | compact([0,1,false,2,'',3]) → [1,2,3] |
sortBy(array, iteratee, order?) | Sorts array by property or function | sortBy([{age:30},{age:20}], 'age') → [{age:20},{age:30}] |
range(start, end?, step?) | Creates array of numbers from start to end | range(5) → [0,1,2,3,4] |
capitalize(str) | Capitalizes first letter | capitalize('hello') → "Hello" |
camelize(str, options?) | Converts to camelCase | camelize('hello-world') → "helloWorld" |
camelToSnakeCase(str) | Converts camelCase to snake_case | camelToSnakeCase('helloWorld') → "hello_world" |
snakeToCamelCase(str) | Converts snake_case to camelCase | snakeToCamelCase('hello_world') → "helloWorld" |
humanize(str) | Converts string to human-readable format | humanize('firstName') → "First Name" |
slugify(str) | Creates URL-friendly slug | slugify('Hello World!') → "hello_world" |
basename(path, sep?) | Gets filename from path | basename('/path/to/file.txt') → "file.txt" |
stripExtension(str) | Removes file extension | stripExtension('file.txt') → "file" |
isValidURL(str, opts?) | Validates URL format | isValidURL('https://example.com') → true |
nl2br(str, replaceMode?, isXhtml?) | Converts newlines to HTML breaks | nl2br('line1\nline2') → "line1
line2" |
getStringBetween(str, start, end) | Extracts string between delimiters | getStringBetween('a[b]c', '[', ']') → "b" |
truncate(str, length, options?) | Truncates string to specified length | truncate('Hello World', 5) → "Hello..." |
isEmail(str) | Validates email format | isEmail('test@example.com') → true |
rgb2hex(rgb) | Converts RGB to hex color | rgb2hex('rgb(255, 0, 0)') → "#ff0000" |
composeURL(...parts) | Joins URL parts | composeURL('api', 'users', '1') → "api/users/1" |
generatePassword(opts?) | Generates secure password | generatePassword({length: 16}) → "aB3$kL9..." |
isObject(item) | Checks if value is object | isObject({}) → true |
isEmpty(value, opts?) | Checks if value is empty | isEmpty([]) → true |
isNumeric(value) | Checks if value is numeric | isNumeric('123') → true |
softMerge(base, values, options?) | Shallow merge objects | softMerge({a: 1}, {b: 2}) → {a: 1, b: 2} |
deepMerge(...objects) | Deep merge multiple objects | deepMerge({a: {x: 1}}, {a: {y: 2}}) → {a: {x: 1, y: 2}} |
objectFilter(obj, predicate) | Filters object properties | objectFilter({a: 1, b: 2}, v => v > 1) → {b: 2} |
groupBy(array, keys) | Groups array by property/properties | groupBy([{type: 'A'}, {type: 'B'}], 'type') |
valueByIndex(object, index) | Gets value by numeric index | valueByIndex({a: 1, b: 2}, 0) → 1 |
indexByKey(object, key) | Gets index of key in object | indexByKey({a: 1, b: 2}, 'b') → 1 |
keyByValue(object, value) | Gets key by value | keyByValue({a: 1, b: 2}, 2) → 'b' |
removeItemOnce(array, value) | Removes first occurrence from array | removeItemOnce([1, 2, 1], 1) → [2, 1] |
removeUnsetValues(obj, options?) | Removes null/undefined values | removeUnsetValues({a: 1, b: null}) → {a: 1} |
objectToFormData(obj, params?) | Converts object to FormData | objectToFormData({name: 'John'}) → FormData |
diff(obj1, obj2, opts?) | Compares two objects | diff({a: 1}, {a: 2}) → {a: {from: 1, to: 2}} |
clone(obj, options?) | Shallow/deep clone object | clone({a: {b: 1}}) → {a: {b: 1}} |
containsFiles(input) | Checks if input contains File/Blob instances | containsFiles({avatar: new File(...)}) → true |
deepClone(obj) | Deep clone object | deepClone({a: {b: 1}}) → {a: {b: 1}} |
deepFind(input, predicate) | Recursively finds first matching value | deepFind({a: {b: 1}}, v => v === 1) → 1 |
deepSome(input, predicate) | Recursively checks if any value matches | deepSome([1, [2, [3]]], v => v === 3) → true |
flattenObject(obj, prefix?, result?, options?) | Flattens nested object | flattenObject({a: {b: 1}}) → {'a.b': 1} |
getByPath(obj, path, defaultValue?) | Gets value by dot notation path | getByPath({a: {b: 1}}, 'a.b') → 1 |
isset(target, options?) | Checks if value is set (not null/undefined) | isset({a: 1}) → true |
toFormData(input, options?) | Converts input to FormData | toFormData({name: 'John'}) → FormData |
pick(obj, keys) | Creates new object with only specified keys | pick({a:1,b:2,c:3}, ['a','c']) → {a:1,c:3} |
omit(obj, keys) | Creates new object excluding specified keys | omit({a:1,b:2,c:3}, ['b']) → {a:1,c:3} |
parseDate(input) | Parses various date formats | parseDate('2023-01-01') → Date |
parsePeriod(period) | Parses period strings | parsePeriod('2023-01') → {start: Date, end: Date} |
sleep(ms) | Promise-based delay | await sleep(1000) |
retry(fn, maxAttempts?, baseDelay?) | Retries function with exponential backoff | await retry(() => fetch('/api'), 3, 1000) |
promiseAllLimit(promises, limit) | Execute promises with concurrency limit | await promiseAllLimit([p1, p2, p3], 2) |
withTimeout(promise, timeoutMs, timeoutMessage?) | Adds timeout to promise | await withTimeout(fetch('/api'), 5000) |
downloadBlob(blob, filename, options?) | Downloads a Blob as a file in browser | downloadBlob(csvBlob, 'data.csv') |
downloadUrl(url, filename?, options?) | Downloads a file from URL | downloadUrl('https://example.com/file.pdf', 'doc.pdf') |
openBlob(blob, options?) | Opens Blob in new browser tab | openBlob(pdfBlob) |
handleBlobDownload(blob, filename, options?) | Download or open Blob based on options | handleBlobDownload(blob, 'file.pdf', {download: true}) |
dataUrlToBlob(dataUrl) | Converts data URL to Blob | dataUrlToBlob('data:text/plain;base64,...') |
debounce(func, delay, options?) | Debounces function execution with optional immediate mode | debounce(() => console.log('hi'), 300) |
throttle(func, delay, options?) | Throttles function execution to limit frequency | throttle(() => console.log('scroll'), 1000) |
loadExternalScript(src, opts?) | Dynamically loads external scripts (browser only) | await loadExternalScript('https://cdn.example.com/lib.js') |
genUuid(options?) | Generates UUID with version support (v1 or v4) | genUuid({version: 4}) → "550e8400-e29b-41d4-a716-446655440000" |
parseLanguageCode(code, options?) | Extracts language code from locale | parseLanguageCode('en-US') → 'en' |
parseBool(value) | Parses boolean from various formats | parseBool('1') → true, parseBool(0) → false |
isValidCss(prop, val) | Validates CSS property and value | isValidCss('color', '#ff0000') → true |
isValidHex(color) | Validates hex color format | isValidHex('#ff0000') → true |
isValidColor(color) | Validates color format (hex, named, rgb, hsl) | isValidColor('red') → true |
bash
Run Node.js tests
yarn test:node
Run browser tests (automated with Puppeteer)
yarn test:browser
Run all tests
yarn test:all
``