Package Exports
- @hiennc24/common
- @hiennc24/common/lib/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@hiennc24/common) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Stop Writing Boilerplate. Start Shipping Features.
Production-ready TypeScript utilities that eliminate 1000+ lines of repetitive code from your Node.js projects.
๐ Quick Start
import { NotFoundError, sanitizeMongoFilter, CacheManager } from '@hiennc24/common';
// Production-ready error handling in one line
throw new NotFoundError('User not found', 'USER_NOT_FOUND', { userId: '123' });
// NoSQL injection protection built-in
const safeFilter = sanitizeMongoFilter(userInput); // Automatically strips $where, $function, etc.
// Multi-tenant caching without the headache
const cache = new CacheManager(redisClient, logger, 'user-service');๐ฏ Why @hiennc24/common?
Because every Node.js project needs the same 80% of utilities, but nobody wants to write them twice.
- Zero compromises on security - Built-in NoSQL injection prevention with circular reference protection
- Battle-tested reliability - 188/188 tests passing, production-ready since v1.0
- Type-safe by design - Full TypeScript definitions with intelligent autocomplete
- Multi-tenant ready - Database connections and caching with tenant isolation out of the box
- Actually maintained - Regular security audits, zero known vulnerabilities
- Tree-shakeable - Import only what you need, ESM + CommonJS support
๐ฆ Installation
npm install @hiennc24/commonNo peer dependencies. Works with Express, NestJS, Fastify, or any Node.js framework.
๐ก Core Features
๐ก๏ธ Production-Ready Error Handling
Stop writing custom error classes. Get 10 HTTP-aware errors with proper TypeScript types and prototype chains.
Before @hiennc24/common:
// 30+ lines of boilerplate per error class
class NotFoundError extends Error {
public code: number;
public details?: any;
constructor(message: string, details?: any) {
super(message);
this.name = 'NotFoundError';
this.code = 404;
this.details = details;
Object.setPrototypeOf(this, NotFoundError.prototype);
}
}
// Repeat for ValidationError, UnauthorizedError, ServerError...After @hiennc24/common:
import {
NotFoundError,
ValidationError,
UnauthorizedError,
ErrorFactory
} from '@hiennc24/common';
// Use directly
throw new NotFoundError('User not found', 'USER_NOT_FOUND', { userId: '123' });
// Or use the factory for common patterns
throw ErrorFactory.createNotFoundError('User', userId, { requestId });
throw ErrorFactory.createValidationError('Invalid email', ['email'], { value });Includes: ServerError, NotFoundError, ValidationError, UnauthorizedError, PermissionDeniedError, BadRequestError, ConflictError, AlreadyExistsError, TooManyRequestsError, ServiceUnavailableError
๐ Built-in Security Against NoSQL Injection
Your MongoDB queries are only as secure as your input sanitization.
import { sanitizeMongoFilter } from '@hiennc24/common';
// Dangerous user input
const maliciousInput = {
email: 'user@example.com',
$where: 'this.password.length > 0', // ๐จ Injection attempt - blocked
$function: { body: 'return true' } // ๐จ Code execution - blocked
};
// Automatically strips dangerous operators
const safeFilter = sanitizeMongoFilter(maliciousInput);
// Result: { email: 'user@example.com' } โ
// Handles circular references (prevents DoS)
const circular: any = { a: 1 };
circular.self = circular;
sanitizeMongoFilter(circular); // Won't crash your app โ
Protects against: $where, $function, $expr, $accumulator, $mapReduce, group, and other code execution operators. Safe query operators like $ne, $regex, $in are allowed.
๐๏ธ Multi-Tenant Database Management
Managing connections for 100+ tenants? ConnectMultipleDB handles caching, retry logic, and automatic cleanup.
import { ConnectMultipleDB } from '@hiennc24/common';
const dbManager = new ConnectMultipleDB(
logger,
redisCache,
{ getConnectionString: async (domain) => fetchFromVault(domain) },
{ maxPoolSize: 10, maxConnecting: 5 }
);
// Automatically caches connections per tenant
const tenantA_DB = await dbManager.getConnection('tenant-a.com');
const tenantB_DB = await dbManager.getConnection('tenant-b.com');
// Auto-closes idle connections after 2 hours (configurable)
// Retry logic with exponential backoff built-inFeatures:
- Connection pooling per tenant
- Redis-backed caching (1-hour TTL)
- Automatic idle connection cleanup
- Configurable retry attempts (default: 5)
- Domain validation and encryption support
โ Type-Safe Validation Service
Stop repeating the same null checks and type guards.
import { ValidationService } from '@hiennc24/common';
// Before: Manual validation everywhere
if (!entity || typeof entity !== 'object') {
throw new Error('Invalid entity');
}
if (!filter || typeof filter !== 'object') {
throw new Error('Invalid filter');
}
// After: One-liner validation with context
ValidationService.validateEntity(entity, 'createUser');
ValidationService.validateFilter(filter, 'findUsers');
ValidationService.validateCondition(condition, 'updateUser');
ValidationService.validatePipeline(pipeline, 'aggregateData');
// Throws ValidationError with method context for better debugging๐ฏ MongoDB-Style Field Projection
Filter entity fields like MongoDB projections, but for plain JavaScript objects.
import { FieldProjector } from '@hiennc24/common';
const user = {
id: '123',
email: 'user@example.com',
password: 'hashed_password',
role: 'admin',
createdAt: new Date()
};
// Include only specific fields (MongoDB-style)
const publicUser = FieldProjector.project(user, 'id email role');
// { id: '123', email: 'user@example.com', role: 'admin' }
// Exclude sensitive fields
const safeUser = FieldProjector.project(user, '-password -createdAt');
// { id: '123', email: 'user@example.com', role: 'admin' }
// Object notation also supported
const projected = FieldProjector.project(user, { email: 1, role: 1 });Perfect for: API responses, logging sanitization, DTOs, GraphQL resolvers
โก Smart Caching with Multi-Tenancy
Redis caching that understands your multi-tenant architecture.
import { CacheManager } from '@hiennc24/common';
const cache = new CacheManager<User>(
redisClient,
logger,
'user-service',
'tenant-a.com' // Automatic tenant isolation
);
// Cache with automatic key generation
await cache.set('user:123', userData, { ttl: 3600 });
// Get with type safety
const user = await cache.get<User>('user:123');
// Tenant-specific keys automatically
// Actual Redis key: "tenant-a.com:user-service:user:123"Features:
- Automatic tenant isolation
- Release version support (cache invalidation on deploy)
- Reference-based caching for complex objects
- Type-safe generics
- Development mode bypass
๐ AES Encryption Utilities
Simple, secure encryption for configuration and secrets.
import { Crypto } from '@hiennc24/common';
const encrypted = Crypto.encrypt('sensitive-data', 'your-secret-key');
const decrypted = Crypto.decrypt(encrypted, 'your-secret-key');
// Perfect for: API keys in config, connection strings, tokens๐ Structured Logging with Winston
Pre-configured Winston logger with context support.
import { logger } from '@hiennc24/common';
logger.info('User created', { userId: '123', email: 'user@example.com' });
logger.error('Database error', { error: err.message, stack: err.stack });
logger.warn('Rate limit approaching', { requests: 95, limit: 100 });๐ ๏ธ Essential Helpers
Utilities you copy-paste between projects.
import {
isChanged,
findChangedValue,
waitByPromise,
isUndefinedOrNull,
isStringAndNotEmpty
} from '@hiennc24/common';
// Detect changes between objects
const hasChanges = isChanged(originalUser, updatedUser);
// Find exactly what changed
const delta = findChangedValue(originalUser, updatedUser);
// { email: 'new@example.com', role: 'admin' }
// Async sleep
await waitByPromise(1000); // Wait 1 second
// Type guards
if (isStringAndNotEmpty(value)) {
// TypeScript knows value is string
}๐งช Battle-Tested Quality
- โ 188/188 tests passing - Comprehensive test coverage for every feature
- โ
100% TypeScript - Full type definitions with zero
anyabuse - โ
Zero security vulnerabilities - Regular audits with
npm audit - โ Production-ready - Used in multi-tenant SaaS platforms since v1.0
- โ Actively maintained - Security patches within 48 hours
๐ Full API Reference
Error Classes
AppError- Base error class with enhanced detailsServerError(500) - Internal server errorsNotFoundError(404) - Resource not foundValidationError(400) - Input validation failedUnauthorizedError(401) - Authentication requiredPermissionDeniedError(403) - Insufficient permissionsBadRequestError(400) - Invalid request formatConflictError(409) - Resource conflictAlreadyExistsError(422) - Resource already existsTooManyRequestsError(429) - Rate limit exceededServiceUnavailableError(503) - Service unavailable
Error Utilities
ErrorUtils.createErrorResponse()- Standardized error responsesErrorUtils.isOperationalError()- Distinguish operational vs programming errorsErrorFactory.createValidationError()- Validation errors with field contextErrorFactory.createAuthError()- Authentication errorsErrorFactory.createNotFoundError()- Resource not found errors
Security
sanitizeMongoFilter(filter)- Remove dangerous MongoDB operatorsCrypto.encrypt(data, key)- AES encryptionCrypto.decrypt(data, key)- AES decryption
Database
ConnectMultipleDB- Multi-tenant database connection managergetConnection(domain)- Get/create connection for tenantcloseConnection(domain)- Close specific connectioncloseAllConnections()- Cleanup all connections
Validation
ValidationService.validateEntity()- Validate entity objectsValidationService.validateFilter()- Validate filter objectsValidationService.validateCondition()- Validate query conditionsValidationService.validatePipeline()- Validate aggregation pipelines
Field Projection
FieldProjector.project(entity, projection)- Apply MongoDB-style field filtering
Caching
CacheManager<T>- Redis caching with multi-tenancyset(key, value, options)- Cache dataget<T>(key)- Retrieve cached datadelete(key)- Remove from cacheclear()- Clear all cache
Helpers
isChanged(source, dest)- Deep equality checkfindChangedValue(source, dest)- Find changed propertieswaitByPromise(ms)- Async sleepisUndefinedOrNull(value)- Type guard for null/undefinedisStringAndNotEmpty(value)- Type guard for non-empty stringsgenerateTimestamp()- Get current timestamp
Logging
logger.info(),logger.error(),logger.warn(),logger.debug()- Winston-based logging
๐ค Contributing
Found a bug? Have a feature request? Contributions welcome!
- Fork the repository: https://github.com/hiennc24/common
- Create your feature branch:
git checkout -b feature/amazing-feature - Run tests:
npm test(all 188 must pass) - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
Before submitting:
- Add tests for new features
- Ensure TypeScript types are correct
- Update documentation if needed
๐ Issues & Support
- Bug Reports: GitHub Issues
- Security Issues: Email author directly (see package.json)
- Questions: Open a discussion on GitHub
๐ License
ISC License - Copyright (c) Hien Nguyen
See LICENSE for details.
๐ Support This Project
If @hiennc24/common saves you from writing boilerplate, give it a star on GitHub!
โญ Star on GitHub โญ
Every star helps other developers discover this package and motivates continued maintenance.
๐ฆ Package Stats
- Bundle Size: Tree-shakeable ESM + CommonJS
- Dependencies: 6 production dependencies (axios, cron, crypto-js, express, lodash, winston)
- Node Version: 14+ (TypeScript 4.9+)
- Framework Agnostic: Works with Express, NestJS, Fastify, Koa, etc.
Stop reinventing the wheel. Start with @hiennc24/common.
npm install @hiennc24/common