@ekipnico/utils
v1.0.3
Published
General-purpose TypeScript utilities
Readme
@ekipnico/utils
General-purpose TypeScript utilities for array, object, date, string manipulation and more. Zero dependencies (except for minimal helper libs), fully typed, and tree-shakeable.
Installation
npm install @ekipnico/utilsUsage
Import Everything
import { groupBy, debounce, sha1, deepClone } from '@ekipnico/utils';
// Use utilities
const grouped = groupBy([1, 2, 3, 4], n => n % 2);
const debouncedFn = debounce(() => console.log('Called!'), 300);
const hash = await sha1('hello world');Import Specific Modules (Tree-shakeable)
// Import only what you need - better for bundle size
import { groupBy, sortBy } from '@ekipnico/utils/array';
import { debounce } from '@ekipnico/utils/debounce';
import { sha1 } from '@ekipnico/utils/hash';
import { deepClone } from '@ekipnico/utils/object';Available Modules
📋 Array Utilities (@ekipnico/utils/array)
import {
toArray,
sort,
sortBy,
groupBy,
upsert,
removeWhere,
shuffle
} from '@ekipnico/utils/array';
// Convert value to array
toArray(5); // [5]
toArray([1, 2]); // [1, 2]
// Sort by predicate
const users = [{ age: 30 }, { age: 20 }];
sort(users, u => u.age); // Sorted by age (ascending)
sortBy(users, 'age', true); // Sort by key (descending)
// Group by function
const nums = [1, 2, 3, 4, 5];
groupBy(nums, n => n % 2); // Map { 0 => [2, 4], 1 => [1, 3, 5] }
// Upsert (update or insert)
const items = [{ id: 1, name: 'A' }];
upsert(items, { id: 1, name: 'B' }, i => i.id === 1); // Updates existing
// Remove where predicate matches
removeWhere(items, i => i.id === 1); // Removes first match
// Shuffle array
shuffle([1, 2, 3, 4, 5]); // Random order📅 Date Utilities (@ekipnico/utils/date)
import {
formatDate,
formatTime,
formatDateTime,
parseDate,
addDays,
diffDays
} from '@ekipnico/utils/date';
const now = new Date();
// Formatting
formatDate(now); // "2025-10-21"
formatTime(now); // "14:30:45"
formatDateTime(now); // "2025-10-21 14:30:45"
// Parsing
parseDate('2025-10-21'); // Date object
// Date arithmetic
addDays(now, 7); // Date 7 days from now
diffDays(now, tomorrow); // Difference in days🔤 String Utilities (@ekipnico/utils/string)
import {
capitalize,
camelCase,
kebabCase,
truncate,
slugify
} from '@ekipnico/utils/string';
capitalize('hello world'); // "Hello world"
camelCase('hello-world'); // "helloWorld"
kebabCase('helloWorld'); // "hello-world"
truncate('Long text...', 10); // "Long text..."
slugify('Hello World!'); // "hello-world"🎯 Object Utilities (@ekipnico/utils/object)
import {
deepClone,
deepMerge,
pick,
omit,
isEqual
} from '@ekipnico/utils/object';
const obj = { a: 1, b: { c: 2 } };
// Deep clone
deepClone(obj); // New deep copy
// Deep merge
deepMerge(obj, { b: { d: 3 } }); // { a: 1, b: { c: 2, d: 3 } }
// Pick/omit properties
pick(obj, ['a']); // { a: 1 }
omit(obj, ['b']); // { a: 1 }
// Deep equality
isEqual(obj, { a: 1, b: { c: 2 } }); // true🔐 Hash Utilities (@ekipnico/utils/hash)
import { sha1, bufferToHex } from '@ekipnico/utils/hash';
// SHA-1 hashing (async)
const hash = await sha1('hello world');
// "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
// Buffer to hex conversion
const buffer = new Uint8Array([255, 0, 128]);
bufferToHex(buffer.buffer); // "ff0080"⏱️ Debounce (@ekipnico/utils/debounce)
import { debounce } from '@ekipnico/utils/debounce';
// Create debounced function
const debouncedSearch = debounce((query: string) => {
console.log('Searching for:', query);
}, 300);
// Call multiple times - only last call executes after 300ms
debouncedSearch('a');
debouncedSearch('ab');
debouncedSearch('abc'); // Only this executes (after 300ms)🕐 Throttle (@ekipnico/utils/throttle)
import { throttle } from '@ekipnico/utils/throttle';
// Create throttled function
const throttledScroll = throttle(() => {
console.log('Scroll handler');
}, 100);
// Call multiple times - executes at most once per 100ms
window.addEventListener('scroll', throttledScroll);🔄 Poll (@ekipnico/utils/poll)
import { poll } from '@ekipnico/utils/poll';
// Poll until condition is met
await poll(
async () => {
const response = await fetch('/api/status');
return response.ok;
},
{ interval: 1000, timeout: 10000 }
);🎲 ID Generation (@ekipnico/utils/id)
import { generateId, uuid } from '@ekipnico/utils/id';
// Generate short ID (uses nanoid)
generateId(); // "V1StGXR8_Z5jdHi6B-myT"
// Generate UUID v4
uuid(); // "550e8400-e29b-41d4-a716-446655440000"📐 Math Utilities (@ekipnico/utils/math)
import { clamp, random, average, sum } from '@ekipnico/utils/math';
clamp(15, 0, 10); // 10 (clamped to max)
random(1, 10); // Random integer between 1-10
average([1, 2, 3, 4, 5]); // 3
sum([1, 2, 3]); // 6🎨 Event System (@ekipnico/utils/event)
import { EventEmitter } from '@ekipnico/utils/event';
// Type-safe event emitter (uses nanoevent)
const emitter = new EventEmitter<{ update: { id: string } }>();
// Subscribe
emitter.on('update', (data) => {
console.log('Updated:', data.id);
});
// Emit
emitter.emit('update', { id: '123' });🔧 JSON Utilities (@ekipnico/utils/json)
import { safeJsonParse, safeJsonStringify } from '@ekipnico/utils/json';
// Safe parsing (returns null on error instead of throwing)
safeJsonParse('{"valid": true}'); // { valid: true }
safeJsonParse('invalid json'); // null
// Safe stringify (handles circular refs)
safeJsonStringify({ a: 1 }); // '{"a":1}'🎛️ Enum Coercion (@ekipnico/utils/coerce-enum)
import { coerceEnum } from '@ekipnico/utils/coerce-enum';
enum Status { Active = 'active', Inactive = 'inactive' }
// Safely coerce to enum
coerceEnum('active', Status); // Status.Active
coerceEnum('invalid', Status); // undefinedPublishing
This package is configured for easy publishing to npm:
# Bump version and publish
npm version patch # or minor, major
# This automatically:
# 1. Runs build
# 2. Publishes to npm with --access=public
# 3. Pushes git tags to origin/mainManual Publishing
# Build
npm run build
# Test
npm test
# Publish
npm publish --access=publicDevelopment
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Clean build artifacts
npm run cleanTypeScript Support
This package is written in TypeScript and exports full type definitions. All functions are fully typed.
import { groupBy } from '@ekipnico/utils/array';
const users = [
{ id: 1, role: 'admin' },
{ id: 2, role: 'user' }
];
// TypeScript knows the return type: Map<string, { id: number, role: string }[]>
const grouped = groupBy(users, u => u.role);Tree-Shaking
This package is fully tree-shakeable. Import only what you need:
// ✅ Only array.js is bundled
import { groupBy } from '@ekipnico/utils/array';
// ❌ Entire package is bundled
import { groupBy } from '@ekipnico/utils';License
MIT
Contributing
Pull requests welcome! Please ensure:
- All functions are pure (no side effects)
- Full TypeScript types
- Unit tests for new utilities
- Update this README with examples
