@nadershak/utils
v1.0.1
Published
Reusable, tree-shakable utilities for any front-end project
Downloads
180
Maintainers
Readme
@nadershak/utils
A comprehensive, tree-shakable TypeScript utility library for front-end projects. Works with React, Vue, Angular, Svelte, or Vanilla JS.
Features
- 🌳 Tree-shakable - Import only what you need
- 📦 TypeScript - Full type safety and IntelliSense support
- 🧪 Well-tested - Comprehensive unit tests with Vitest
- 🚀 Modern - ES modules and CommonJS support
- 📚 Well-documented - JSDoc comments for all utilities
Installation
npm install @nadershak/utils
# or
yarn add @nadershak/utils
# or
pnpm add @nadershak/utilsUsage
Import individual utilities
import { capitalize, debounce, formatDate } from '@nadershak/utils';
const text = capitalize('hello world'); // 'Hello world'
const debouncedFn = debounce(() => console.log('Hello'), 300);
const formatted = formatDate(new Date()); // '1/15/2023'Import React hooks
import { useLocalStorage } from '@nadershak/utils/react';
function MyComponent() {
const [user, setUser] = useLocalStorage('user', { name: 'Guest' });
// ...
}API Reference
String Utilities
capitalize(str: string): string
Capitalizes the first letter of a string.
capitalize('hello') // 'Hello'
capitalize('HELLO') // 'Hello'camelCase(str: string): string
Converts a string to camelCase.
camelCase('hello world') // 'helloWorld'
camelCase('hello-world') // 'helloWorld'kebabCase(str: string): string
Converts a string to kebab-case.
kebabCase('hello world') // 'hello-world'
kebabCase('HelloWorld') // 'hello-world'truncate(str: string, length: number, suffix?: string): string
Truncates a string to a specified length.
truncate('Hello world', 5) // 'Hello...'
truncate('Hello world', 5, '') // 'Hello'stripHTML(str: string): string
Removes HTML tags from a string.
stripHTML('<p>Hello <b>world</b></p>') // 'Hello world'randomString(length?: number, chars?: string): string
Generates a random string.
randomString(8) // 'aB3dEf9h'
randomString(8, '0123456789') // '12345678'normalizeString(str: string): string
Normalizes a string by removing diacritics.
normalizeString('Café') // 'cafe'
normalizeString('Müller') // 'muller'isEmail(str: string): boolean
Validates if a string is a valid email address.
isEmail('[email protected]') // true
isEmail('invalid-email') // falseisPhone(str: string): boolean
Validates if a string is a valid phone number.
isPhone('+1234567890') // true
isPhone('(123) 456-7890') // trueNumber Utilities
clamp(value: number, min: number, max: number): number
Clamps a number between min and max.
clamp(15, 0, 10) // 10
clamp(-5, 0, 10) // 0
clamp(5, 0, 10) // 5randomInt(min?: number, max?: number): number
Generates a random integer.
randomInt(1, 10) // Random number between 1 and 10isNumeric(value: unknown): boolean
Checks if a value is numeric.
isNumeric(123) // true
isNumeric('123') // true
isNumeric('abc') // falseroundTo(value: number, decimals?: number): number
Rounds a number to specified decimal places.
roundTo(3.14159, 2) // 3.14
roundTo(3.14159, 0) // 3percentage(value: number, total: number, decimals?: number): number
Calculates percentage.
percentage(25, 100) // 25
percentage(1, 3) // 33.33formatNumber(value: number, locale?: string, options?: Intl.NumberFormatOptions): string
Formats a number with thousand separators.
formatNumber(1234567.89) // '1,234,567.89'
formatNumber(1234567.89, 'de-DE') // '1.234.567,89'Date Utilities
formatDate(date: Date | string | number, format?: string | Intl.DateTimeFormatOptions, options?: Intl.DateTimeFormatOptions): string
Formats a date. Supports custom separators, locale strings, or Intl.DateTimeFormatOptions.
formatDate(new Date('2023-01-15')) // '1/15/2023'
formatDate(new Date('2023-01-15'), '-') // '1-15-2023'
formatDate(new Date('2023-01-15'), 'en-GB') // '15/01/2023'
formatDate(new Date('2023-01-15'), 'en-US', { dateStyle: 'full' }) // 'Sunday, January 15, 2023'timeAgo(date: Date | string | number, now?: Date): string
Returns a human-readable time ago string.
timeAgo(new Date(Date.now() - 3600000)) // '1 hour ago'
timeAgo(new Date(Date.now() - 86400000)) // '1 day ago'isValidDate(value: unknown): value is Date
Checks if a value is a valid Date object.
isValidDate(new Date()) // true
isValidDate(new Date('invalid')) // falseaddDays(date: Date | string | number, days: number): Date
Adds days to a date.
addDays(new Date('2023-01-15'), 5) // Date object for 2023-01-20subtractDays(date: Date | string | number, days: number): Date
Subtracts days from a date.
subtractDays(new Date('2023-01-15'), 5) // Date object for 2023-01-10compareDates(date1: Date | string | number, date2: Date | string | number): number
Compares two dates.
compareDates(new Date('2023-01-15'), new Date('2023-01-20')) // -1
compareDates(new Date('2023-01-15'), new Date('2023-01-15')) // 0getDayName(date: Date | string | number, locale?: string, format?: 'long' | 'short' | 'narrow'): string
Gets the day name.
getDayName(new Date('2023-01-15')) // 'Sunday'
getDayName(new Date('2023-01-15'), 'en-US', 'short') // 'Sun'getMonthName(date: Date | string | number, locale?: string, format?: 'long' | 'short' | 'narrow'): string
Gets the month name.
getMonthName(new Date('2023-01-15')) // 'January'
getMonthName(new Date('2023-01-15'), 'en-US', 'short') // 'Jan'Array Utilities
unique<T>(arr: T[]): T[]
Returns unique values from an array.
unique([1, 2, 2, 3, 3, 3]) // [1, 2, 3]chunk<T>(arr: T[], size: number): T[][]
Splits an array into chunks.
chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]flatten<T>(arr: (T | T[])[], depth?: number): T[]
Flattens a nested array.
flatten([1, [2, 3], [4, [5]]]) // [1, 2, 3, 4, [5]]
flatten([1, [2, 3], [4, [5]]], 2) // [1, 2, 3, 4, 5]shuffle<T>(arr: T[]): T[]
Shuffles an array.
shuffle([1, 2, 3, 4, 5]) // [3, 1, 5, 2, 4] (random order)sortByKey<T>(arr: T[], key: keyof T, direction?: 'asc' | 'desc'): T[]
Sorts an array of objects by a key.
sortByKey([{ name: 'Bob', age: 30 }, { name: 'Alice', age: 25 }], 'age')
// [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }]removeItem<T>(arr: T[], item: T): T[]
Removes an item from an array.
removeItem([1, 2, 3, 2], 2) // [1, 3]groupBy<T>(arr: T[], key: keyof T | ((item: T) => string | number)): Record<string, T[]>
Groups an array by a key.
groupBy([{ type: 'fruit', name: 'apple' }, { type: 'fruit', name: 'banana' }, { type: 'veg', name: 'carrot' }], 'type')
// { fruit: [...], veg: [...] }Object Utilities
deepClone<T>(obj: T): T
Creates a deep clone of an object.
const obj = { a: 1, b: { c: 2 } };
const cloned = deepClone(obj);
cloned.b.c = 3;
// obj.b.c is still 2deepMerge<T>(target: T, ...sources: Partial<T>[]): T
Deeply merges objects.
deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 })
// { a: 1, b: { c: 2, d: 3 }, e: 4 }isEmptyObject(obj: unknown): boolean
Checks if an object is empty.
isEmptyObject({}) // true
isEmptyObject({ a: 1 }) // falseomit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>
Creates an object with omitted properties.
omit({ a: 1, b: 2, c: 3 }, ['a', 'c']) // { b: 2 }pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>
Creates an object with only specified properties.
pick({ a: 1, b: 2, c: 3 }, ['a', 'c']) // { a: 1, c: 3 }getNestedValue<T>(obj: Record<string, unknown>, path: string, defaultValue?: T): T | undefined
Gets a nested value from an object.
getNestedValue({ user: { profile: { name: 'John' } } }, 'user.profile.name') // 'John'
getNestedValue({ user: { profile: { name: 'John' } } }, 'user.profile.age', 0) // 0Validation Utilities
isEmail(str: string): boolean
Validates email address.
isEmail('[email protected]') // trueisURL(str: string): boolean
Validates URL.
isURL('https://example.com') // trueisPhoneNumber(str: string): boolean
Validates phone number.
isPhoneNumber('+1234567890') // trueisStrongPassword(str: string): boolean
Validates strong password.
isStrongPassword('MyP@ssw0rd') // trueisJSON(str: string): boolean
Validates JSON string.
isJSON('{"key": "value"}') // trueisUUID(str: string): boolean
Validates UUID.
isUUID('550e8400-e29b-41d4-a716-446655440000') // trueisEmpty(value: unknown): boolean
Checks if a value is empty.
isEmpty('') // true
isEmpty([]) // true
isEmpty({}) // true
isEmpty(null) // trueDOM Utilities
addClass(element: Element | string, className: string): void
Adds a CSS class to an element.
addClass('#myElement', 'active')
addClass(document.querySelector('.item'), 'highlighted')removeClass(element: Element | string, className: string): void
Removes a CSS class from an element.
removeClass('#myElement', 'active')toggleClass(element: Element | string, className: string): boolean
Toggles a CSS class on an element.
toggleClass('#myElement', 'active')scrollToTop(behavior?: ScrollBehavior): void
Scrolls to the top.
scrollToTop() // smooth scroll
scrollToTop('auto') // instant scrollscrollToBottom(behavior?: ScrollBehavior): void
Scrolls to the bottom.
scrollToBottom()isInViewport(element: Element | string, partial?: boolean): boolean
Checks if an element is in the viewport.
isInViewport('#myElement') // true if visible
isInViewport('#myElement', true) // true if partially visiblegetOffset(element: Element | string): { top: number; left: number }
Gets the offset position of an element.
getOffset('#myElement') // { top: 100, left: 50 }Storage Utilities
setLocal<T>(key: string, value: T): void
Sets a value in localStorage.
setLocal('user', { name: 'John', age: 30 })
setLocal('theme', 'dark')getLocal<T>(key: string, defaultValue?: T): T | undefined
Gets a value from localStorage.
const user = getLocal('user', { name: 'Guest' })
const theme = getLocal('theme', 'light')removeLocal(key: string): void
Removes a value from localStorage.
removeLocal('user')setSession<T>(key: string, value: T): void
Sets a value in sessionStorage.
setSession('tempData', { id: 123 })getSession<T>(key: string, defaultValue?: T): T | undefined
Gets a value from sessionStorage.
const tempData = getSession('tempData', {})removeSession(key: string): void
Removes a value from sessionStorage.
removeSession('tempData')copyToClipboard(text: string): Promise<void>
Copies text to clipboard.
await copyToClipboard('Hello World')downloadFile(content: string | Blob, filename: string, mimeType?: string): void
Downloads a file.
downloadFile('Hello World', 'hello.txt')
downloadFile(new Blob(['data']), 'data.bin', 'application/octet-stream')Async Utilities
sleep(ms: number): Promise<void>
Creates a promise that resolves after a delay.
await sleep(1000) // waits 1 secondretry<T>(fn: () => Promise<T>, retries?: number, delay?: number): Promise<T>
Retries an async function.
const result = await retry(() => fetchData(), 3, 1000)debouncePromise<T>(fn: T, delay: number): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>
Debounces a promise-returning function.
const debouncedFetch = debouncePromise(fetchData, 300)
await debouncedFetch() // only the last call will resolvetimeoutPromise<T>(promise: Promise<T>, timeout: number, errorMessage?: string): Promise<T>
Wraps a promise with a timeout.
const result = await timeoutPromise(fetchData(), 5000, 'Request timed out')Performance Utilities
debounce<T>(fn: T, delay: number): (...args: Parameters<T>) => void
Debounces a function.
const debouncedSearch = debounce((query) => search(query), 300)
debouncedSearch('hello') // will only execute after 300ms of no callsthrottle<T>(fn: T, delay: number): (...args: Parameters<T>) => void
Throttles a function.
const throttledScroll = throttle(() => handleScroll(), 100)
throttledScroll() // will execute at most once per 100msmemoize<T>(fn: T, keyFn?: (...args: Parameters<T>) => string): (...args: Parameters<T>) => ReturnType<T>
Memoizes a function.
const memoizedExpensive = memoize((n) => expensiveCalculation(n))
memoizedExpensive(5) // calculates and caches
memoizedExpensive(5) // returns cached resultNetwork Utilities
fetchJSON<T>(url: string, options?: RequestInit): Promise<T>
Fetches JSON data.
const data = await fetchJSON('/api/users')
const user = await fetchJSON('/api/user/1', { method: 'POST', body: JSON.stringify({ name: 'John' }) })fetchWithTimeout(url: string, timeout?: number, options?: RequestInit): Promise<Response>
Fetches with timeout.
const response = await fetchWithTimeout('/api/data', 3000)parseQueryString(queryString?: string): Record<string, string>
Parses a query string.
parseQueryString('?name=John&age=30') // { name: 'John', age: '30' }
parseQueryString() // parses window.location.searchcreateQueryString(params: Record<string, string | number | boolean>): string
Creates a query string.
createQueryString({ name: 'John', age: 30 }) // '?name=John&age=30'React Hooks
useThrottle<T>(value: T, delay?: number): T
Throttles a value.
const [scrollY, setScrollY] = useState(0);
const throttledScroll = useThrottle(scrollY, 100);useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void]
Manages localStorage with React state.
const [user, setUser] = useLocalStorage('user', { name: 'Guest' });
setUser({ name: 'John' }); // updates both state and localStorageuseSessionStorage<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void]
Manages sessionStorage with React state.
const [viewMode, setViewMode] = useSessionStorage('viewMode', 'list');usePrevious<T>(value: T): T | undefined
Returns the previous value.
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);useBoolean(initialValue?: boolean)
Manages boolean state with convenient helpers.
const { value, toggle, setTrue, setFalse } = useBoolean(false);
toggle(); // toggles the value
setTrue(); // sets to true
setFalse(); // sets to falseuseUpdateEffect(effect: () => void | (() => void), deps: unknown[]): void
Runs an effect only on updates.
useUpdateEffect(() => {
console.log('Component updated');
}, [someValue]);Security Utilities
sanitizeInput(input: string): string
Sanitizes user input by escaping HTML.
sanitizeInput('<script>alert("xss")</script>') // '<script>alert("xss")</script>'hashString(str: string, algorithm?: string): Promise<string>
Hashes a string using Web Crypto API.
const hash = await hashString('password123')secureCompare(a: string, b: string): boolean
Performs constant-time string comparison.
secureCompare('secret', 'secret') // true
secureCompare('secret', 'wrong') // falseMisc Utilities
uuid(): string
Generates a UUID v4.
uuid() // '550e8400-e29b-41d4-a716-446655440000'generateId(prefix?: string, length?: number): string
Generates a unique ID.
generateId() // 'a1b2c3d4'
generateId('user', 12) // 'user_a1b2c3d4e5f6'isClient(): boolean
Checks if running in browser.
if (isClient()) {
// browser-only code
}isServer(): boolean
Checks if running on server.
if (isServer()) {
// server-only code
}Types
DeepPartial<T>
Makes all properties deeply partial.
type User = { name: string; address: { city: string } };
type PartialUser = DeepPartial<User>; // { name?: string; address?: { city?: string } }Nullable<T>
Makes T nullable.
type MaybeString = Nullable<string>; // string | nullOptional<T>
Makes T optional.
type MaybeString = Optional<string>; // string | undefinedValueOf<T>
Extracts value type from object.
type User = { name: string; age: number };
type UserValue = ValueOf<User>; // string | numberTree Shaking
This package is fully tree-shakable. Import only what you need:
// ✅ Good - only imports what you use
import { capitalize, debounce } from '@nadershak/utils';
// ❌ Avoid - imports everything
import * as utils from '@nadershak/utils';Development
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build
# Type check
npm run typecheckLicense
MIT
