Production-ready TypeScript utilities for Node.js: multi-tenant database management, NoSQL injection protection, error handling, validation, caching, and more. Battle-tested with 188/188 tests.
npm install @hiennc24/commonProduction-ready TypeScript utilities that eliminate 1000+ lines of repetitive code from your Node.js projects.




``typescript
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');
`
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
`bash`
npm install @hiennc24/common
No peer dependencies. Works with Express, NestJS, Fastify, or any Node.js framework.
---
Stop writing custom error classes. Get 10 HTTP-aware errors with proper TypeScript types and prototype chains.
Before @hiennc24/common:
`typescript`
// 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:
`typescript
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
---
Your MongoDB queries are only as secure as your input sanitization.
`typescript
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.
---
Managing connections for 100+ tenants? ConnectMultipleDB handles caching, retry logic, and automatic cleanup.
`typescript
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-in
`
Features:
- Connection pooling per tenant
- Redis-backed caching (1-hour TTL)
- Automatic idle connection cleanup
- Configurable retry attempts (default: 5)
- Domain validation and encryption support
---
Stop repeating the same null checks and type guards.
`typescript
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
`
---
Filter entity fields like MongoDB projections, but for plain JavaScript objects.
`typescript
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
---
Redis caching that understands your multi-tenant architecture.
`typescript
import { CacheManager } from '@hiennc24/common';
const cache = new CacheManager
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
// 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
---
Simple, secure encryption for configuration and secrets.
`typescript
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
`
---
Pre-configured Winston logger with context support.
`typescript
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 });
`
---
Utilities you copy-paste between projects.
`typescript
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
}
`
---
- โ
188/188 tests passing - Comprehensive test coverage for every feature
- โ
100% TypeScript - Full type definitions with zero any abusenpm audit
- โ
Zero security vulnerabilities - Regular audits with
- โ
Production-ready - Used in multi-tenant SaaS platforms since v1.0
- โ
Actively maintained - Security patches within 48 hours
---
- Base error class with enhanced details
- ServerError (500) - Internal server errors
- NotFoundError (404) - Resource not found
- ValidationError (400) - Input validation failed
- UnauthorizedError (401) - Authentication required
- PermissionDeniedError (403) - Insufficient permissions
- BadRequestError (400) - Invalid request format
- ConflictError (409) - Resource conflict
- AlreadyExistsError (422) - Resource already exists
- TooManyRequestsError (429) - Rate limit exceeded
- ServiceUnavailableError (503) - Service unavailable$3
- ErrorUtils.createErrorResponse() - Standardized error responses
- ErrorUtils.isOperationalError() - Distinguish operational vs programming errors
- ErrorFactory.createValidationError() - Validation errors with field context
- ErrorFactory.createAuthError() - Authentication errors
- ErrorFactory.createNotFoundError() - Resource not found errors$3
- sanitizeMongoFilter(filter) - Remove dangerous MongoDB operators
- Crypto.encrypt(data, key) - AES encryption
- Crypto.decrypt(data, key) - AES decryption$3
- ConnectMultipleDB - Multi-tenant database connection manager
- getConnection(domain) - Get/create connection for tenant
- closeConnection(domain) - Close specific connection
- closeAllConnections() - Cleanup all connections$3
- ValidationService.validateEntity() - Validate entity objects
- ValidationService.validateFilter() - Validate filter objects
- ValidationService.validateCondition() - Validate query conditions
- ValidationService.validatePipeline() - Validate aggregation pipelines$3
- FieldProjector.project(entity, projection) - Apply MongoDB-style field filtering$3
- CacheManager - Redis caching with multi-tenancy
- set(key, value, options) - Cache data
- get - Retrieve cached data
- delete(key) - Remove from cache
- clear() - Clear all cache$3
- isChanged(source, dest) - Deep equality check
- findChangedValue(source, dest) - Find changed properties
- waitByPromise(ms) - Async sleep
- isUndefinedOrNull(value) - Type guard for null/undefined
- isStringAndNotEmpty(value) - Type guard for non-empty strings
- generateTimestamp() - Get current timestamp$3
- logger.info(), logger.error(), logger.warn(), logger.debug() - Winston-based logging---
๐ค Contributing
Found a bug? Have a feature request? Contributions welcome!
1. Fork the repository: https://github.com/hiennc24/common
2. Create your feature branch:
git checkout -b feature/amazing-feature
3. Run tests: npm test (all 188 must pass)
4. Commit changes: git commit -m 'Add amazing feature'
5. Push to branch: git push origin feature/amazing-feature
6. Open a Pull RequestBefore 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.
`bash
npm install @hiennc24/common
``