friendlyfy-js
v1.0.4
Published
A zero-dependency utility library with 70+ functions for formatting dates, numbers, strings, arrays, objects, and validation. Works in both Node.js and browser environments.
Maintainers
Readme
friendlyfy-js
A zero-dependency utility library with 70+ functions for formatting dates, numbers, strings, arrays, objects, and validation. Works seamlessly in both Node.js and browser environments with pure JavaScript implementation.
✨ Features
- 📅 Date & Time (10 functions): Human-readable formatting, timezone support, duration formatting
- 🔢 Numbers & Math (15 functions): Shortening, formatting, validation, statistical analysis
- 🔤 String Manipulation (15 functions): Text transformation, HTML handling, case conversion
- 📊 Array Operations (15 functions): Manipulation, set operations, sorting, statistics
- 🔧 Object Utilities (15 functions): Deep cloning, merging, transformation, validation
- ✅ Validation & Security (13 functions): Email, URL, phone, credit card, password validation
- 🌍 Full Internationalization: Complete locale support using native
IntlAPIs - ⚡ ESM Ready: Built for Node.js v20+ with native ES modules
- 📦 Zero Dependencies: Uses only native JavaScript APIs
🚀 Installation
npm install friendlyfy-js🎯 Quick Start
import {
// Date & Time
timeAgo,
formatDuration,
// Numbers
shortenNumber,
formatFileSize,
formatOrdinal,
// Strings
slugify,
capitalize,
// Arrays
chunk,
unique,
// Objects
deepClone,
pick,
// Validation
isValidEmail,
validatePassword,
// Crypto
generateUUID,
hash,
// Files
getMimeType,
sanitizeFilename
} from 'friendlyfy-js';
// Date formatting
console.log(timeAgo('2025-10-08T10:00:00Z')); // "3 hours ago"
console.log(formatDuration(3661)); // "1h 1m 1s"
// Number formatting
console.log(shortenNumber(12543)); // "12.5K"
console.log(formatFileSize(1048576)); // "1.05 MB"
console.log(formatOrdinal(21)); // "21st"
// String manipulation
console.log(slugify("Hello World!")); // "hello-world"
console.log(capitalize("hello world")); // "Hello world"
// Array operations
console.log(chunk([1,2,3,4,5,6], 2)); // [[1,2], [3,4], [5,6]]
console.log(unique([1,2,2,3,3,3])); // [1,2,3]
// Object utilities
const cloned = deepClone({user: {name: 'John'}});
const userData = pick({name: 'John', age: 30, city: 'NYC'}, ['name', 'age']);
// Validation
console.log(isValidEmail('[email protected]')); // true
console.log(validatePassword('MySecure123!')); // {valid: true, strength: 'strong'}
// Cryptography
console.log(generateUUID()); // "96cf1769-2655-4880-801d-7062903e9b2b"
console.log(hash('Hello World')); // "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
// File operations
console.log(getMimeType('image.jpg')); // "image/jpeg"
console.log(sanitizeFilename('file<>:"|?*.txt')); // "file_______.txt"📚 API Reference
📅 Date & Time Helpers
timeAgo(date, locale?)
Returns human-readable time ago string.
timeAgo('2024-01-01T00:00:00Z'); // "2 months ago"
timeAgo(new Date(), 'es-ES'); // "hace 2 horas"timeFromNow(date, locale?)
Returns human-readable time from now string.
timeFromNow('2025-12-25T00:00:00Z'); // "in 8 months"formatDateWithTimezone(date, timezone?, options?, locale?)
Formats date with timezone support.
formatDateWithTimezone('2024-01-15T14:30:00Z', 'America/New_York');
// "01/15/2024, 09:30:00 AM"formatDuration(seconds, options?, locale?)
Formats duration in human-readable format.
formatDuration(3661); // "1h 1m 1s"
formatDuration(3661, {compact: true}); // "1h 1m 1s"
formatDuration(3661, {maxUnits: 2}); // "1h 1m"startOf(date, period) / endOf(date, period)
Get start/end of time periods.
startOf(new Date(), 'week'); // Start of current week
endOf(new Date(), 'month'); // End of current month🔢 Number Helpers
shortenNumber(num, decimals?)
Shortens numbers with K, M, B, T suffixes.
shortenNumber(12543); // "12.5K"
shortenNumber(1250000); // "1.3M"
shortenNumber(1250000000); // "1.3B"formatFileSize(bytes, options?, locale?)
Formats file size in human-readable format.
formatFileSize(1024); // "1.02 KB"
formatFileSize(1048576); // "1.05 MB"
formatFileSize(1048576, {binary: true}); // "1.00 MiB"formatOrdinal(num, locale?)
Formats ordinal numbers.
formatOrdinal(1); // "1st"
formatOrdinal(2); // "2nd"
formatOrdinal(21); // "21st"formatRange(start, end, options?, locale?)
Formats number ranges.
formatRange(1, 5); // "1-5"
formatRange(1000, 2000); // "1,000-2,000"
formatRange(1, 5, {separator: ' to '}); // "1 to 5"pluralize(count, singular, plural?, locale?)
Pluralizes words based on count.
pluralize(1, 'item'); // "1 item"
pluralize(5, 'item'); // "5 items"
pluralize(1, 'child', 'children'); // "1 child"🔤 String Helpers
slugify(str, options?)
Converts string to URL-friendly slug.
slugify("Hello World! 123"); // "hello-world-123"
slugify("Hello World!", {separator: '_'}); // "hello_world_123"truncate(str, length, options?)
Truncates string with ellipsis.
truncate("This is a long text", 10); // "This is a ..."
truncate("This is a long text", 10, {wordBoundary: true}); // "This is..."capitalize(str, lowerRest?)
Capitalizes first letter.
capitalize("hello world"); // "Hello world"
capitalize("hello world", true); // "Hello world"camelToKebab(str) / kebabToCamel(str)
Converts between camelCase and kebab-case.
camelToKebab("camelCaseString"); // "camel-case-string"
kebabToCamel("kebab-case-string"); // "kebabCaseString"stripHtml(str) / escapeHtml(str)
Handles HTML content.
stripHtml("<p>Hello <b>World</b></p>"); // "Hello World"
escapeHtml("<script>alert('xss')</script>"); // "<script>alert('xss')</script>"maskString(str, options?)
Masks sensitive strings.
maskString("1234567890"); // "12******90"
maskString("1234567890", {visibleStart: 3, visibleEnd: 3}); // "123****890"📊 Array Helpers
chunk(arr, size)
Chunks array into smaller arrays.
chunk([1,2,3,4,5,6,7,8,9,10], 3); // [[1,2,3], [4,5,6], [7,8,9], [10]]unique(arr, keyFn?)
Removes duplicates from array.
unique([1,2,2,3,3,3,4,5]); // [1,2,3,4,5]
unique(users, user => user.city); // Unique users by cityshuffle(arr, inPlace?)
Shuffles array randomly.
shuffle([1,2,3,4,5]); // [3,2,4,1,5]groupBy(arr, key)
Groups array items by key.
groupBy(users, 'city'); // { 'New York': [...], 'London': [...] }
groupBy(users, user => user.age > 25 ? 'adult' : 'young'); // { 'adult': [...], 'young': [...] }intersection(arr1, arr2) / difference(arr1, arr2) / union(arr1, arr2)
Set operations on arrays.
intersection([1,2,3,4], [3,4,5,6]); // [3,4]
difference([1,2,3,4], [3,4,5,6]); // [1,2]
union([1,2,3,4], [3,4,5,6]); // [1,2,3,4,5,6]arrayStats(arr)
Gets array statistics.
arrayStats([1,2,3,4,5]); // {length: 5, sum: 15, average: 3, min: 1, max: 5, median: 3}🔧 Object Helpers
deepClone(obj)
Deep clones an object.
const cloned = deepClone({user: {profile: {name: 'John'}}});deepMerge(target, ...sources)
Deep merges objects.
deepMerge({a: 1, b: {c: 2}}, {b: {d: 3}}); // {a: 1, b: {c: 2, d: 3}}pick(obj, keys) / omit(obj, keys)
Selects/removes object properties.
pick({name: 'John', age: 30, city: 'NYC'}, ['name', 'age']); // {name: 'John', age: 30}
omit({name: 'John', age: 30, city: 'NYC'}, ['age']); // {name: 'John', city: 'NYC'}get(obj, path, defaultValue?) / set(obj, path, value)
Gets/sets nested object properties.
get({user: {profile: {name: 'John'}}}, 'user.profile.name'); // "John"
set(obj, 'user.profile.settings.theme', 'dark');transformKeys(obj, transformFn) / transformValues(obj, transformFn)
Transforms object keys/values.
transformKeys({firstName: 'John', lastName: 'Doe'}, k => k.toUpperCase()); // {FIRSTNAME: 'John', LASTNAME: 'Doe'}
transformValues({a: 1, b: 2}, v => v * 2); // {a: 2, b: 4}✅ Validation Helpers
isValidEmail(email)
Validates email addresses.
isValidEmail('[email protected]'); // true
isValidEmail('invalid-email'); // falseisValidUrl(url, options?)
Validates URLs.
isValidUrl('https://example.com'); // true
isValidUrl('ftp://example.com', {protocols: ['ftp:']}); // trueisValidPhone(phone, country?)
Validates phone numbers.
isValidPhone('+1234567890', 'US'); // true
isValidPhone('+44123456789', 'UK'); // trueisValidCreditCard(cardNumber)
Validates credit card numbers.
isValidCreditCard('4111111111111111'); // {valid: true, type: 'visa'}validatePassword(password, options?)
Validates password strength.
validatePassword('MySecure123!'); // {valid: true, score: 6, strength: 'strong', feedback: []}isValidIP(ip, version?)
Validates IP addresses.
isValidIP('192.168.1.1'); // true
isValidIP('2001:db8::1', 'v6'); // trueisValidUUID(uuid, version?)
Validates UUIDs.
isValidUUID('550e8400-e29b-41d4-a716-446655440000'); // true🔐 Crypto Helpers
hash(data, algorithm?, encoding?)
Generates hash using specified algorithm.
hash('Hello World'); // "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
hash('Hello World', 'md5', 'hex'); // "b10a8db164e0754105b7a99be72e3fe5"hmac(data, secret, algorithm?, encoding?)
Generates HMAC.
hmac('Hello World', 'secret'); // "82ce0d2f821fa0ce5447b21306f214c99240fecc6387779d7515148bbdd0c415"generateUUID()
Generates UUID v4.
generateUUID(); // "96cf1769-2655-4880-801d-7062903e9b2b"generateToken(length?, options?)
Generates secure tokens.
generateToken(16); // "qRWt7ncmhhwy8FNK"
generateToken(32, {includeSymbols: true}); // "K#m9@vL2$nP8&qR5!"hashPassword(password, options?)
Hashes passwords securely.
const hashed = await hashPassword('MyPassword123');
const isValid = await verifyPassword('MyPassword123', hashed); // truegenerateApiKey(options?)
Generates API keys.
generateApiKey(); // "ak_fvtqhqwlhicphwgyazvrq"
generateApiKey({prefix: 'sk', includeTimestamp: true}); // "sk_1j8k9l2m_fvtqhqwlhicphwgyazvrq"📁 File Helpers
getFileExtension(filename) / getFilenameWithoutExtension(filename)
Gets file extension or name without extension.
getFileExtension('document.pdf'); // "pdf"
getFilenameWithoutExtension('document.pdf'); // "document"normalizePath(filePath) / joinPaths(...paths)
Path manipulation.
normalizePath('./folder/../file.txt'); // "file.txt"
joinPaths('folder', 'subfolder', 'file.txt'); // "folder/subfolder/file.txt"getMimeType(filename)
Gets MIME type from filename.
getMimeType('image.jpg'); // "image/jpeg"
getMimeType('document.pdf'); // "application/pdf"
getMimeType('script.js'); // "application/javascript"sanitizeFilename(filename, options?)
Sanitizes filenames for safe storage.
sanitizeFilename('file<>:"|?*.txt'); // "file_______.txt"
sanitizeFilename('My File (1).pdf', {replacement: '-'}); // "My-File-1-.pdf"fileExists(filePath) / dirExists(dirPath)
Checks file/directory existence.
await fileExists('/path/to/file.txt'); // true/false
await dirExists('/path/to/directory'); // true/falsegetFileStats(filePath)
Gets file statistics.
await getFileStats('/path/to/file.txt'); // {size: 1024, isFile: true, createdAt: Date, modifiedAt: Date, ...}🌍 Internationalization
All functions support locale-specific formatting:
import { timeAgo, formatWithCommas, formatCurrency, formatOrdinal } from 'friendlyfy-js';
// Spanish
timeAgo(date, 'es-ES'); // "hace 2 horas"
formatWithCommas(1234567, 'es-ES'); // "1.234.567"
// German
formatCurrency(1234.56, 'EUR', 'de-DE'); // "1.234,56 €"
// French
formatOrdinal(1, 'fr-FR'); // "1er"🧪 Examples
Run the comprehensive examples:
npm start
# or
node example.js📋 Requirements
- Node.js v20.0.0 or higher
- ESM support (use
importsyntax)
📄 License
MIT License - see LICENSE file for details.
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📈 Changelog
1.0.1
- Added comprehensive utility functions (100+ functions)
- String manipulation helpers (15 functions)
- Array operation helpers (15 functions)
- Object utility helpers (15 functions)
- Validation and security helpers (13 functions)
- Cryptography helpers (15 functions)
- File system helpers (20 functions)
- Complete examples and documentation
- Full internationalization support
1.0.0
- Initial release
- Date helper functions with
Intl.RelativeTimeFormat - Number helper functions with various formatting options
- Full internationalization support
- ESM module support
🎯 Use Cases
Frontend Development
- String manipulation and formatting
- Date/time display
- Form validation
- Data transformation
Backend Development
- API response formatting
- Data validation
- File handling
- Security utilities
Full-Stack Applications
- Complete utility coverage
- Consistent formatting across frontend/backend
- Internationalization support
- Performance optimization
🔗 Related Packages
- date-fns - Date utility library
- lodash - Utility library
- validator.js - String validation
- crypto-js - Cryptographic functions
⭐ Star History
Made with ❤️ by Vinay Kumar
