objeasy
v2.3.2
Published
A lightweight utility toolkit to control and manage plain JavaScript objects with precision.
Maintainers
Readme
objeasy

A lightweight utility toolkit to control and manage plain JavaScript objects with precision.
Table of Contents
- Features
- Installation
- Quick Start
- Usage Examples
- API Documentation
- TypeScript Support
- Benchmarks
- Error Handling
- Best Practices
- Contributing
- License
Features
High performance - Optimized for speed and memory efficiency
Type-safe - Full TypeScript support with detailed type definitions
Flexible options - Configurable behavior for different use cases
Lightweight - Zero dependencies, minimal footprint
Well-tested - 149 comprehensive tests ensuring reliability
Immutable - All operations return new objects, preserving originals
Deep operations - Support for nested object manipulation
Installation
# Using npm
npm install objeasy
# Using yarn
yarn add objeasy
# Using pnpm
pnpm add objeasyQuick Start
// CommonJS
const { pickit, modifyit, mergeit, transformit, omitit, flattenit } = require('objeasy');
// ES6 Modules
import { pickit, modifyit, mergeit, transformit, omitit, flattenit } from 'objeasy';
// Example usage
const user = {
id: 1,
name: 'John Doe',
email: '[email protected]',
age: 30,
role: 'developer',
address: {
city: 'New York',
country: 'USA'
}
};
// Pick specific keys
const basicInfo = pickit(user, ['name', 'email']);
// Result: { name: 'John Doe', email: '[email protected]' }
// Transform values
const upperCaseInfo = transformit(user, {
name: value => value.toUpperCase(),
role: value => value.toUpperCase()
});
// Result: { id: 1, name: 'JOHN DOE', email: '[email protected]', age: 30, role: 'DEVELOPER', address: {...} }Usage Examples
Advanced Object Picking with Deep Support
const user = {
id: 1,
profile: {
name: 'John Doe',
contact: {
email: '[email protected]',
phone: '+1234567890'
}
},
preferences: {
theme: 'dark',
language: 'en'
}
};
// Deep picking with dot notation
const contactInfo = pickit(user, ['id', 'profile.contact.email'], { deep: true });
// Result: { id: 1, 'profile.contact.email': '[email protected]' }
// Non-strict mode (skip missing keys)
const safeInfo = pickit(user, ['id', 'nonexistent'], { strict: false });
// Result: { id: 1 }Object Modification and Property Erasing
const product = {
id: 'P001',
name: 'Laptop',
price: 999,
category: 'Electronics',
internalNotes: 'For admin only'
};
// Modify properties
const updatedProduct = modifyit(product, {
price: 899,
onSale: true
});
// Result: { id: 'P001', name: 'Laptop', price: 899, category: 'Electronics', internalNotes: 'For admin only', onSale: true }
// Erase sensitive properties
const publicProduct = modifyit(product, ['internalNotes'], { erase: true });
// Result: { id: 'P001', name: 'Laptop', price: 999, category: 'Electronics' }Advanced Object Merging
const defaultConfig = {
api: {
baseUrl: 'https://api.example.com',
timeout: 5000
},
features: ['auth', 'logging']
};
const userConfig = {
api: {
timeout: 10000,
retries: 3
},
features: ['auth', 'analytics'],
debug: true
};
// Deep merge with array concatenation
const finalConfig = mergeit(defaultConfig, userConfig, {
deep: true,
arrays: true,
strategy: 'unique'
});
// Result: {
// api: { baseUrl: 'https://api.example.com', timeout: 10000, retries: 3 },
// features: ['auth', 'logging', 'analytics'],
// debug: true
// }Complex Object Transformation
const users = {
user1: { name: 'john doe', role: 'admin', lastLogin: '2023-01-15' },
user2: { name: 'jane smith', role: 'user', lastLogin: '2023-01-10' },
user3: { name: 'bob wilson', role: 'moderator', lastLogin: null }
};
// Transform with conditional logic and filtering
const processedUsers = transformit(
users,
{
name: value =>
value
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' '),
role: value => value.toUpperCase(),
lastLogin: value => (value ? new Date(value).toLocaleDateString() : 'Never')
},
{
deep: true,
excludeKeys: ['user3'] // Skip user3
}
);Object Flattening for API Processing
const complexData = {
user: {
profile: {
personal: {
name: 'John Doe',
age: 30
},
contact: {
email: '[email protected]'
}
},
settings: {
theme: 'dark',
notifications: true
}
}
};
const flattened = flattenit(complexData);
// Result: {
// 'user.profile.personal.name': 'John Doe',
// 'user.profile.personal.age': 30,
// 'user.profile.contact.email': '[email protected]',
// 'user.settings.theme': 'dark',
// 'user.settings.notifications': true
// }API Documentation
pickit()
Extract specific keys from an object with optional deep path support.
pickit(originalObject: object, keysToPick: string[], options?: PickitOptions): objectParameters:
originalObject- The source object to extract keys fromkeysToPick- Array of keys to extract (supports dot notation withdeep: true)options- Configuration options
Options:
strict(boolean, default:true) - Throw error if key doesn't existdeep(boolean, default:false) - Enable dot notation path picking
Example:
const user = { id: 1, name: 'John', profile: { email: '[email protected]' } };
// Basic usage
pickit(user, ['id', 'name']); // { id: 1, name: 'John' }
// Deep picking
pickit(user, ['id', 'profile.email'], { deep: true });
// { id: 1, 'profile.email': '[email protected]' }modifyit()
Modify or erase properties from an object.
modifyit(originalObject: object, modifications: object | string[], options?: ModifyitOptions): objectParameters:
originalObject- The object to modifymodifications- Object with new values or array of keys to eraseoptions- Configuration options
Options:
erase(boolean, default:false) - Erase mode: treat modifications as keys to removestrict(boolean, default:false) - Throw error when modifying non-existent keys
Example:
const user = { id: 1, name: 'John', temp: 'remove me' };
// Modify properties
modifyit(user, { name: 'Jane', age: 25 });
// { id: 1, name: 'Jane', temp: 'remove me', age: 25 }
// Erase properties
modifyit(user, ['temp'], { erase: true });
// { id: 1, name: 'John' }mergeit()
Merge multiple objects with advanced options for deep merging and array handling.
mergeit(target: object, ...sources: object[], options?: MergeitOptions): objectParameters:
target- The target object to merge intosources- One or more source objects to mergeoptions- Configuration options
Options:
deep(boolean, default:true) - Enable deep merging of nested objectsarrays(boolean, default:false) - Enable array merging instead of replacementstrategy(string, default:'replace') - Array merge strategy:'concat','replace', or'unique'
Example:
const base = { a: 1, nested: { x: 1 }, arr: [1, 2] };
const extension = { b: 2, nested: { y: 2 }, arr: [3, 4] };
// Deep merge with unique array strategy
mergeit(base, extension, { arrays: true, strategy: 'unique' });
// { a: 1, b: 2, nested: { x: 1, y: 2 }, arr: [1, 2, 3, 4] }transformit()
Transform object values using mapper functions with advanced filtering options.
transformit(originalObject: object, mappers: object | Function, options?: TransformitOptions): objectParameters:
originalObject- The object to transformmappers- Object with mapper functions for each key or single function for all valuesoptions- Configuration options
Options:
strict(boolean, default:false) - Throw error if mapper not found for a keydeep(boolean, default:false) - Recursively transform nested objectsincludeKeys(string[]) - Whitelist of keys to transformexcludeKeys(string[]) - Blacklist of keys to skip
Example:
const data = { name: 'john', age: 30, role: 'admin' };
// Transform specific properties
transformit(data, {
name: value => value.toUpperCase(),
age: value => `${value} years old`
});
// { name: 'JOHN', age: '30 years old', role: 'admin' }
// Transform with filtering
transformit(data, value => (typeof value === 'string' ? value.toUpperCase() : value), {
includeKeys: ['name', 'role']
});
// { name: 'JOHN', age: 30, role: 'ADMIN' }omitit()
Remove specific keys from an object (inverse of pickit).
omitit(originalObject: object, keysToOmit: string[], options?: OmititOptions): objectParameters:
originalObject- The source object to omit keys fromkeysToOmit- Array of keys to excludeoptions- Configuration options
Options:
strict(boolean, default:false) - Throw error if key to omit doesn't existdeep(boolean, default:false) - Enable deep omitting with dot notation
Example:
const user = { id: 1, name: 'John', password: 'secret', profile: { ssn: '123' } };
// Basic omitting
omitit(user, ['password']);
// { id: 1, name: 'John', profile: { ssn: '123' } }
// Deep omitting
omitit(user, ['password', 'profile.ssn'], { deep: true });
// { id: 1, name: 'John', profile: {} }flattenit()
Flatten nested objects into single-level objects with dot notation keys.
flattenit(originalObject: object, prefix?: string): objectParameters:
originalObject- The object to flattenprefix- Internal parameter for recursion (usually omitted)
Example:
const nested = {
user: {
profile: { name: 'John', age: 30 },
settings: { theme: 'dark' }
}
};
flattenit(nested);
// {
// 'user.profile.name': 'John',
// 'user.profile.age': 30,
// 'user.settings.theme': 'dark'
// }TypeScript Support
objeasy provides comprehensive TypeScript support with detailed type definitions:
import { pickit, PickitOptions, transformit, MapperFunction } from 'objeasy';
interface User {
id: number;
name: string;
email: string;
profile: {
age: number;
city: string;
};
}
const user: User = {
id: 1,
name: 'John Doe',
email: '[email protected]',
profile: { age: 30, city: 'New York' }
};
// Type-safe operations
const basicInfo = pickit(user, ['id', 'name']); // Inferred type
const options: PickitOptions = { strict: false, deep: true };
// Custom mapper with proper typing
const stringMapper: MapperFunction<string> = (value: string) => value.toUpperCase();Benchmarks
objeasy is optimized for performance across all operations:
Performance Metrics (1000 iterations):
PICKIT Performance:
✓ Basic Picking: 0.002ms per operation
✓ Large Dataset: 0.002ms per operation
✓ Complex Object: 0.001ms per operation
MODIFYIT Performance:
✓ Basic Modify: 0.003ms per operation
✓ Erase Mode: 0.002ms per operation
✓ Large Dataset: 0.004ms per operation
MERGEIT Performance:
✓ Shallow Merge: 0.004ms per operation
✓ Deep Merge: 0.008ms per operation
✓ Array Strategies: 0.006ms per operation
TRANSFORMIT Performance:
✓ Basic Transform: 0.005ms per operation
✓ Deep Transform: 0.012ms per operation
✓ Filtered Transform: 0.007ms per operation
Memory Usage: Optimized for minimal heap allocation
All operations maintain O(n) complexity for object sizeRun benchmarks locally:
npm run benchmarkError Handling
objeasy provides clear, actionable error messages:
// TypeError examples
pickit(null, ['key']);
// TypeError: Original object must be a non-null object.
pickit({}, 'not-array');
// TypeError: Keys to pick must be an array.
// Strict mode errors
pickit({ a: 1 }, ['b'], { strict: true });
// Error: Key "b" does not exist in the original object.
transformit({}, { a: 'not-function' });
// TypeError: Mapper for key "a" must be a function.Best Practices
1. Use Appropriate Strict Modes
// For known object shapes - use strict mode (default for pickit)
const userInfo = pickit(user, ['id', 'name'], { strict: true });
// For dynamic/uncertain data - disable strict mode
const dynamicData = pickit(apiResponse, ['optionalField'], { strict: false });2. Leverage Deep Operations
// Prefer deep operations for nested structures
const settings = pickit(config, ['database.host', 'cache.ttl'], { deep: true });
// Use dot notation for precise targeting
const sanitized = omitit(user, ['profile.ssn', 'internal.secrets'], { deep: true });3. Optimize Performance
// For large datasets, prefer shallow operations when possible
const basicFields = pickit(largeObject, ['id', 'name']); // Fast
// Use transformit filtering for selective updates
const processed = transformit(data, mapper, { includeKeys: ['specific', 'fields'] });4. Chain Operations
// Combine functions for complex transformations
const result = transformit(omitit(user, ['password', 'secrets']), { name: n => n.toUpperCase() });Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/kareemaboueid/objeasy.git
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run benchmarks
npm run benchmark
# Lint and format
npm run lint:fix
npm run format:fixTesting
We maintain 100% test coverage with 149 comprehensive tests:
# Run all tests
npm test
# Watch mode for development
npm run test:watch
# Generate coverage report
npm run test:coverageCode Quality
We enforce strict code quality standards:
- ESLint - JavaScript/TypeScript linting
- Prettier - Code formatting
- Husky - Git hooks for quality checks
- TypeScript - Type checking
License
MIT © Kareem Aboueid
