@acontplus/utils
October 23, 2025 · View on GitHub
Comprehensive utility library providing converters, formatters, helpers, validators, and error classes for TypeScript/JavaScript applications.
Installation
# Using npm
npm install @acontplus/utils
# Using pnpm
pnpm add @acontplus/utils
Features
- Converters: Color, decimal, and JSON conversion utilities
- Formatters: Date, number, and string formatting functions
- Helpers: Array, field, and object manipulation utilities
- Validators: Parameter and regex validation functions
- Error Classes: Custom error types for better error handling
- Models: Decimal options and configuration interfaces
- Type Definitions: Comprehensive TypeScript type definitions including date types
- Lightweight: Minimal external dependencies for optimal bundle size
Quick Start
import {
getRandomHexColor,
DateFormatter,
ArrayHelper,
NumberFormatter,
StringFormatter,
} from '@acontplus/utils';
// Generate random colors
const hexColor = getRandomHexColor(); // "#a3b2c1"
const rgbaColor = getRandomColor(0.8); // "rgba(163, 178, 193, 0.8)"
// Format dates
const formatted = DateFormatter.toString(new Date(), 'yyyy-MM-dd HH:mm:ss');
const futureDate = DateFormatter.addDays(new Date(), 7);
// Array operations
const isEmpty = ArrayHelper.isEmpty([]); // true
const maxValue = ArrayHelper.max([1, 5, 3, 9, 2]); // 9
// Number formatting
const currency = NumberFormatter.formatCurrency(1234.56); // "\$1,234.56"
const percentage = NumberFormatter.formatPercentage(0.85); // "85.00%"
API Reference
Converters
Color Converter
Generate random colors in different formats:
import { getRandomHexColor, getRandomColor } from '@acontplus/utils';
// Generate random hex color
const hex = getRandomHexColor(); // "#ff5733"
// Generate random RGBA color with opacity
const rgba = getRandomColor(0.7); // "rgba(255, 87, 51, 0.7)"
// Usage in charts or UI components
const chartColors = Array.from({ length: 5 }, () => getRandomHexColor());
// ["#a1b2c3", "#d4e5f6", "#789abc", "#def012", "#345678"]
Decimal Converter
High-precision decimal operations using decimal.js for financial and scientific calculations:
import { DecimalConverter, DecimalError } from '@acontplus/utils';
// Configuration
DecimalConverter.configure({
precision: 6,
returnAsNumber: true,
throwOnInfinity: false,
});
// Basic operations
const sum = DecimalConverter.add(0.1, 0.2); // 0.3 (precise)
const difference = DecimalConverter.subtract(1.0, 0.9); // 0.1 (precise)
const product = DecimalConverter.multiply(0.1, 3); // 0.3 (precise)
const quotient = DecimalConverter.divide(1, 3, { precision: 4 }); // 0.3333
// Mathematical operations
const power = DecimalConverter.power(2, 3); // 8
const sqrt = DecimalConverter.sqrt(16); // 4
const absolute = DecimalConverter.abs(-5.5); // 5.5
// Financial operations
const price = 1000;
const discounted = DecimalConverter.applyDiscount(price, 15); // 850
const withTax = DecimalConverter.addTax(discounted, 16); // 986
const percentage = DecimalConverter.percentage(1000, 8.5); // 85
// Interest calculations
const simpleInterest = DecimalConverter.simpleInterest(1000, 5, 2); // 100
const compoundInterest = DecimalConverter.compoundInterest(1000, 5, 2, 12); // 105.12
// Array operations
const values = [0.1, 0.2, 0.3, 0.4, 0.5];
const total = DecimalConverter.sum(values); // 1.5
const average = DecimalConverter.average(values); // 0.3
const median = DecimalConverter.median(values); // 0.3
const min = DecimalConverter.min(values); // 0.1
const max = DecimalConverter.max(values); // 0.5
// Comparisons
const isEqual = DecimalConverter.equals(0.1 + 0.2, 0.3); // true
const isGreater = DecimalConverter.greaterThan(0.3, 0.2); // true
const comparison = DecimalConverter.compare(0.1, 0.2); // -1
// Chain operations
const result = DecimalConverter.chain(1000)
.applyDiscount(10) // 900
.addTax(16) // 1044
.round(2) // 1044.00
.toNumber(); // 1044
// Formatting
const formatted = DecimalConverter.format(1234.5678, {
precision: 2,
thousandsSeparator: ',',
decimalSeparator: '.',
prefix: '$',
suffix: ' USD',
}); // "\$1,234.57 USD"
// Error handling
try {
const division = DecimalConverter.divide(10, 0);
} catch (error) {
if (error instanceof DecimalError) {
console.log(`Error in ${error.operation}: ${error.message}`);
}
}
// Operation history with chains
const chain = DecimalConverter.chain(100).multiply(1.16).subtract(50).round(2);
console.log(chain.getOperationHistory());
// ["Started with: 100", "Multiplied by: 1.16", "Subtracted: 50", "Rounded to 2 decimal places"]
JSON Converter
Safe JSON operations with error handling:
import { JsonConverter } from '@acontplus/utils';
// Safe JSON parsing
const data = JsonConverter.parse('{"name": "John"}', null);
// Returns parsed object or null if invalid
// Safe JSON stringification
const json = JsonConverter.stringify({ name: 'John' }, '{}');
// Returns JSON string or fallback if error
Formatters
Date Formatter
Comprehensive date manipulation and formatting:
import { DateFormatter } from '@acontplus/utils';
// Date arithmetic
const tomorrow = DateFormatter.addDays(new Date(), 1);
const nextMonth = DateFormatter.addMonths(new Date(), 1);
const nextYear = DateFormatter.addYears(new Date(), 1);
// Custom formatting
const formatted = DateFormatter.toString(new Date(), 'yyyy-MM-dd HH:mm:ss');
// "2024-01-15 14:30:45"
const shortDate = DateFormatter.toString(new Date(), 'dd/MM/yyyy');
// "15/01/2024"
// UTC formatting
const utcString = DateFormatter.toUTCString(new Date(), 'yyyy-MM-dd');
// Date comparisons
const isSameDay = DateFormatter.isSame(date1, date2, 'day');
const isSameYear = DateFormatter.isSame(date1, date2, 'year');
// Time range checking
const isInRange = DateFormatter.isInTimeRange(
new Date(),
{ hour: 9, minute: 0, second: 0 },
{ hour: 17, minute: 30, second: 0 },
); // Business hours check
// Validation
const isValid = DateFormatter.isValid(new Date('invalid')); // false
// Utility functions
const today = DateFormatter.getToday(); // Today at 00:00:00
const timestamp = DateFormatter.dateToTimestamp(new Date());
const dateFromTimestamp = DateFormatter.timestampToDate(1640995200000);
Number Formatter
Number formatting and validation:
import { NumberFormatter } from '@acontplus/utils';
// Currency formatting
const price = NumberFormatter.formatCurrency(1234.56, 'USD');
// "\$1,234.56"
const euroPrice = NumberFormatter.formatCurrency(1234.56, 'EUR');
// "€1,234.56"
// Percentage formatting
const percentage = NumberFormatter.formatPercentage(0.8542, 2);
// "85.42%"
// Decimal operations
const rounded = NumberFormatter.roundToDecimals(3.14159, 2); // 3.14
const fixed = NumberFormatter.toFixed(3.14159, 2); // "3.14"
// Validation
const isInteger = NumberFormatter.isInteger(42); // true
const isSafe = NumberFormatter.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
// Utility functions
const clamped = NumberFormatter.clamp(15, 0, 10); // 10
const comparison = NumberFormatter.compare(3.14159, 3.1416, 0.001); // 0 (equal within tolerance)
String Formatter
String manipulation and formatting utilities:
import { StringFormatter } from '@acontplus/utils';
// Case transformations
const capitalized = StringFormatter.capitalize('hello world'); // "Hello world"
const titleCase = StringFormatter.capitalizeWords('hello world'); // "Hello World"
// URL-friendly strings
const slug = StringFormatter.slugify('Hello World! 123'); // "hello-world-123"
// Text truncation
const truncated = StringFormatter.truncate('Long text here', 10); // "Long te..."
const customTruncated = StringFormatter.truncate('Long text', 8, '…'); // "Long t…"
// Accent removal
const normalized = StringFormatter.removeAccents('café résumé'); // "cafe resume"
// Random string generation
const randomId = StringFormatter.generateRandomString(8); // "aB3xY9mK"
// Validation
const isEmpty = StringFormatter.isNullOrWhitespace(' '); // true
const hasContent = StringFormatter.isNullOrWhitespace('hello'); // false
Helpers
Array Helper
Comprehensive array manipulation utilities:
import { ArrayHelper } from '@acontplus/utils';
// Array validation
const isEmpty = ArrayHelper.isEmpty([]); // true
const hasItems = ArrayHelper.isNotEmpty([1, 2, 3]); // true
// Element checking
const contains = ArrayHelper.contains([1, 2, 3], 2); // true
const containsAny = ArrayHelper.containsAny([1, 2, 3], [3, 4, 5]); // true
const containsAll = ArrayHelper.containsAll([1, 2, 3], [1, 2]); // true
// Array modification
const numbers = [1, 3, 5];
ArrayHelper.insert(numbers, 1, 2); // [1, 2, 3, 5]
ArrayHelper.remove(numbers, 3); // [1, 2, 5]
// Mathematical operations
const maxValue = ArrayHelper.max([1, 5, 3, 9, 2]); // 9
const minValue = ArrayHelper.min([1, 5, 3, 9, 2]); // 1
// Array slicing
const firstThree = ArrayHelper.take([1, 2, 3, 4, 5], 3); // [1, 2, 3]
const lastTwo = ArrayHelper.takeRight([1, 2, 3, 4, 5], 2); // [4, 5]
// Practical examples
const users = [{ name: 'John' }, { name: 'Jane' }, { name: 'Bob' }];
const hasUsers = ArrayHelper.isNotEmpty(users);
const topUsers = ArrayHelper.take(users, 2);
Object Helper
Object manipulation and validation utilities:
import { ObjectHelper } from '@acontplus/utils';
// Null/undefined checking
const isNull = ObjectHelper.isNullOrUndefined(null); // true
const isUndefined = ObjectHelper.isNullOrUndefined(undefined); // true
const hasValue = ObjectHelper.isNullOrUndefined('hello'); // false
// Type checking
const isArray = ObjectHelper.isArray([1, 2, 3]); // true
const isObject = ObjectHelper.isObject({ name: 'John' }); // true
const isString = ObjectHelper.isString('hello'); // true
const isNumber = ObjectHelper.isNumber(42); // true
// Practical usage in validation
function processUser(user: any) {
if (ObjectHelper.isNullOrUndefined(user)) {
throw new Error('User is required');
}
if (!ObjectHelper.isObject(user)) {
throw new Error('User must be an object');
}
// Process user...
}
Field Helper
Field-specific utility functions:
import { FieldHelper } from '@acontplus/utils';
// Field validation and manipulation
const isValidField = FieldHelper.isValid(fieldValue);
const processedField = FieldHelper.process(rawFieldData);
Validators
Parameter Validator
Parameter validation utilities:
import { ParameterValidator } from '@acontplus/utils';
// Parameter validation
const isValidParam = ParameterValidator.validate(parameter, rules);
const sanitizedParam = ParameterValidator.sanitize(userInput);
// Usage in functions
function calculatePrice(amount: number, taxRate: number) {
if (!ParameterValidator.isValidNumber(amount)) {
throw new InvalidParameterError('Amount must be a valid number');
}
if (!ParameterValidator.isValidRate(taxRate)) {
throw new InvalidParameterError('Tax rate must be between 0 and 1');
}
return amount * (1 + taxRate);
}
Regex Validator
Regular expression validation utilities:
import { RegexValidator } from '@acontplus/utils';
// Common validation patterns
const isEmail = RegexValidator.isEmail('user@example.com'); // true
const isPhone = RegexValidator.isPhone('+1-555-123-4567'); // true
const isUrl = RegexValidator.isUrl('https://example.com'); // true
// Custom pattern validation
const pattern = /^[A-Z]{2}\d{4}$/; // Two letters + four digits
const isValid = RegexValidator.test('AB1234', pattern); // true
// Form validation example
function validateForm(data: any) {
const errors: string[] = [];
if (!RegexValidator.isEmail(data.email)) {
errors.push('Invalid email format');
}
if (!RegexValidator.isPhone(data.phone)) {
errors.push('Invalid phone format');
}
return errors;
}
Error Classes
InvalidParameterError
Custom error class for parameter validation:
import { InvalidParameterError } from '@acontplus/utils';
// Throw specific parameter errors
function divide(a: number, b: number): number {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new InvalidParameterError('Both parameters must be numbers');
}
if (b === 0) {
throw new InvalidParameterError('Division by zero is not allowed');
}
return a / b;
}
// Error handling
try {
const result = divide(10, 0);
} catch (error) {
if (error instanceof InvalidParameterError) {
console.error('Parameter error:', error.message);
}
}
Type Definitions
Date Types
TypeScript interfaces for date-related operations:
import { TIME_OF_DAY, HOUR_OF_DAY, MINUTE_OF_DAY, SECOND_OF_DAY } from '@acontplus/utils';
// Time range definitions
const businessHours: TIME_OF_DAY = {
hour: 9,
minute: 0,
second: 0,
};
const closingTime: TIME_OF_DAY = {
hour: 17,
minute: 30,
second: 0,
};
// Type-safe time operations
function isBusinessHours(date: Date): boolean {
return DateFormatter.isInTimeRange(date, businessHours, closingTime);
}
Real-World Examples
E-commerce Price Calculator with DecimalConverter
import { DecimalConverter, DecimalError } from '@acontplus/utils';
class PriceCalculator {
calculateTotal(
basePrice: number,
taxRate: number,
discountPercent: number = 0,
shippingCost: number = 0,
): {
subtotal: number;
discount: number;
taxAmount: number;
shipping: number;
total: number;
formatted: string;
} {
try {
// Use chain operations for complex calculations
const calculation = DecimalConverter.chain(basePrice)
.applyDiscount(discountPercent)
.addTax(taxRate)
.add(shippingCost);
const subtotal = DecimalConverter.applyDiscount(basePrice, discountPercent);
const discount = DecimalConverter.percentage(basePrice, discountPercent);
const taxAmount = DecimalConverter.percentage(subtotal, taxRate);
const total = calculation.toNumber();
return {
subtotal: subtotal as number,
discount: discount as number,
taxAmount: taxAmount as number,
shipping: shippingCost,
total,
formatted: DecimalConverter.format(total, {
prefix: '$',
precision: 2,
thousandsSeparator: ',',
}),
};
} catch (error) {
if (error instanceof DecimalError) {
throw new Error(`Price calculation failed: ${error.message}`);
}
throw error;
}
}
calculateBulkDiscount(quantity: number, unitPrice: number): number {
if (quantity >= 100) return 15; // 15% discount
if (quantity >= 50) return 10; // 10% discount
if (quantity >= 10) return 5; // 5% discount
return 0;
}
}
// Usage
const calculator = new PriceCalculator();
const result = calculator.calculateTotal(99.99, 8.25, 10, 5.99);
console.log(result);
// {
// subtotal: 89.99,
// discount: 10.00,
// taxAmount: 7.42,
// shipping: 5.99,
// total: 103.40,
// formatted: "\$103.40"
// }
Form Validation System
import {
RegexValidator,
StringFormatter,
ObjectHelper,
InvalidParameterError,
} from '@acontplus/utils';
class FormValidator {
validateUser(userData: any): string[] {
const errors: string[] = [];
// Check if data exists
if (ObjectHelper.isNullOrUndefined(userData)) {
errors.push('User data is required');
return errors;
}
// Validate email
if (StringFormatter.isNullOrWhitespace(userData.email)) {
errors.push('Email is required');
} else if (!RegexValidator.isEmail(userData.email)) {
errors.push('Invalid email format');
}
// Validate name
if (StringFormatter.isNullOrWhitespace(userData.name)) {
errors.push('Name is required');
} else if (userData.name.length < 2) {
errors.push('Name must be at least 2 characters');
}
return errors;
}
sanitizeInput(input: string): string {
return StringFormatter.removeAccents(StringFormatter.capitalize(input.trim()));
}
}
Data Processing Pipeline
import { ArrayHelper, DateFormatter, ObjectHelper } from '@acontplus/utils';
class DataProcessor {
processUserData(users: any[]): any[] {
// Validate input
if (ArrayHelper.isEmpty(users)) {
return [];
}
return users
.filter(user => !ObjectHelper.isNullOrUndefined(user))
.map(user => ({
...user,
fullName: StringFormatter.capitalizeWords(user.name),
joinDate: DateFormatter.toString(new Date(user.joinDate), 'yyyy-MM-dd'),
isActive:
user.lastLogin &&
DateFormatter.compare(new Date(user.lastLogin), DateFormatter.addDays(new Date(), -30)) >
0,
}))
.slice(0, 100); // Take first 100 using ArrayHelper.take could also work
}
}