@myfoto/common-shared
v1.0.6
Published
Common utilities and middleware for MyFoto microservices architecture
Maintainers
Readme
@myfoto/common-shared
A comprehensive utility library for Glow Up microservices built with TypeScript. This package provides common functionality including error handling, validation, database utilities, logging, RabbitMQ event system, and more.
Installation
npm install @myfoto/common-sharedFeatures
- 🚨 Error Handling - Custom error classes with consistent serialization
- ✅ Validation - Zod-based request/response validation with common patterns
- 🗃️ Database Utilities - Prisma helpers, transactions, and health checks
- 🔐 Password Management - Hashing, validation, and secure token generation
- 📄 Response Formatting - Standardized API responses with pagination
- 📊 Pagination - Cursor and offset-based pagination utilities
- 📝 Logging - Structured logging with performance monitoring
- 🛡️ Middleware - Rate limiting, error handling, and more
- 🐰 RabbitMQ Event System - Type-safe event-driven architecture with publishers and subscribers
Quick Start
import {
// Error classes
BadRequestError,
NotFoundError,
ValidationPatterns,
// Utilities
PasswordService,
ResponseFormatter,
PaginationService,
Logger,
DatabaseService,
// Middleware
errorHandler,
validateRequest,
responseFormatter,
} from '@glow-up/common-shared';
// Use in your Express app
import express from 'express';
const app = express();
// Add response formatter middleware
app.use(responseFormatter);
// Add error handler (should be last)
app.use(errorHandler);Error Handling
Custom Error Classes
import {
BadRequestError,
NotFoundError,
ValidationError,
} from '@glow-up/common-shared';
// Throw errors that will be automatically handled
throw new BadRequestError('Invalid input data');
throw new NotFoundError('User not found');
throw new ValidationError([
{ field: 'email', message: 'Invalid email format' },
]);Error Handler Middleware
import { errorHandler } from '@glow-up/common-shared';
// Add as the last middleware
app.use(errorHandler);Validation
Request Validation with Zod
import { validateRequest, ValidationPatterns } from '@glow-up/common-shared';
import { z } from 'zod';
// Use predefined patterns
const loginSchema = {
body: z.object({
email: ValidationPatterns.email(),
password: z.string().min(1),
}),
};
app.post('/login', validateRequest(loginSchema), (req, res) => {
// req.body is now validated and typed
const { email, password } = req.body;
res.success({ message: 'Login successful' });
});
// Common validation middleware
import { ValidationMiddleware } from '@glow-up/common-shared';
app.post(
'/register',
ValidationMiddleware.validateRegistration(),
(req, res) => {
// Handles email, password, name validation
},
);Response Formatting
Standardized API Responses
import { ResponseFormatter } from '@glow-up/common-shared';
// Success response
ResponseFormatter.success(res, { user: userData }, 'User created');
// { success: true, message: 'User created', data: { user: userData }, metadata: { timestamp: ... } }
// Error response
ResponseFormatter.error(res, 'Invalid credentials', 'Login failed', 401);
// Paginated response
ResponseFormatter.paginated(res, users, { page: 1, limit: 10, total: 100 });
// Using middleware (adds methods to res object)
app.use(responseFormatter);
app.get('/users', (req, res) => {
res.success(users, 'Users retrieved');
res.paginated(users, paginationInfo);
res.notFound('User not found');
});Pagination
import { PaginationService, parseSort } from '@glow-up/common-shared';
// Parse pagination params
const pagination = PaginationService.parsePagination({
page: req.query.page,
limit: req.query.limit,
});
// For Prisma
const prismaOptions = PaginationService.toPrisma(pagination, sort);
const users = await prisma.user.findMany(prismaOptions);
// Generate metadata
const metadata = PaginationService.generateMetadata(
pagination.page,
pagination.limit,
totalUsers,
);
res.paginated(users, metadata);Database Utilities
import { DatabaseService } from '@glow-up/common-shared';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
const dbService = new DatabaseService(prisma);
// Health check
const health = await dbService.healthCheck();
// Transactions
const result = await dbService.withTransaction(async tx => {
const user = await tx.user.create({ data: userData });
const profile = await tx.profile.create({
data: { userId: user.id, ...profileData },
});
return { user, profile };
});
// Batch operations
await dbService.batchCreate('user', userDataArray, 50);
// Soft delete
await dbService.softDelete('user', { id: userId });Password Management
import { PasswordService } from '@glow-up/common-shared';
// Hash password
const hashedPassword = await PasswordService.hashPassword('mypassword');
// Compare password
const isValid = await PasswordService.comparePassword(
'mypassword',
hashedPassword,
);
// Generate secure tokens
const token = PasswordService.generateSecureToken(32);
const resetToken = PasswordService.generatePasswordResetToken();
// Check password strength
const strength = PasswordService.checkPasswordStrength('mypassword');
console.log(strength.isStrong); // boolean
console.log(strength.feedback); // array of suggestionsRabbitMQ Event System
Quick Start
import {
Publisher,
Subscriber,
Exchanges,
RoutingKeys,
UserProfileCreatedEvent
} from '@myfoto/common-shared';
import { Channel } from 'amqplib';
// Create a publisher
export class UserProfileCreatedPublisher extends Publisher<UserProfileCreatedEvent> {
exchange = Exchanges.UserProfile;
routingKey = RoutingKeys.UserProfileCreated;
}
// Publish an event
const publisher = new UserProfileCreatedPublisher(channel);
await publisher.publish({
userId: '123',
name: 'John Doe',
email: '[email protected]',
});
// Create a subscriber
export class UserProfileCreatedSubscriber extends Subscriber<UserProfileCreatedEvent> {
exchange = Exchanges.UserProfile;
routingKey = RoutingKeys.UserProfileCreated;
async onMessage(data: UserProfileCreatedEvent['data'], msg: ConsumeMessage): Promise<void> {
console.log('User created:', data);
// Your business logic here
}
}
// Subscribe to events
const subscriber = new UserProfileCreatedSubscriber(channel);
await subscriber.subscribe();Features
- ✅ Type-safe events - Full TypeScript support with autocomplete
- ✅ Centralized definitions - All events defined in one package
- ✅ Consistent naming - Clear routing key conventions
- ✅ Durable queues - Messages persist across restarts
- ✅ Error handling - Automatic message requeuing on failures
- ✅ Documentation - Comprehensive guides and examples
Available Events
User Profile: UserProfileCreatedEvent, UserProfileUpdatedEvent, UserProfileDeletedEvent
Product: ProductCreatedEvent, ProductUpdatedEvent, ProductDeletedEvent, ProductStockChangedEvent
Order: OrderCreatedEvent, OrderUpdatedEvent, OrderCompletedEvent, OrderCancelledEvent
Routing Key Convention
Format: <service>.<entity>.<action>
Examples:
user_profile.profile.createdproduct.product.updatedorder.order.completed
Documentation
Logging
import { Logger, createLogger, requestLogger } from '@myfoto/common-shared';
// Use default logger
import { log } from '@glow-up/common-shared';
log.info('Application started');
log.error('Something went wrong', error, { userId: '123' });
// Create custom logger
const logger = createLogger({
level: 'debug',
enableFile: true,
filePath: './logs/app.log',
});
// Add request logging middleware
app.use(requestLogger(logger));
// Performance logging
import { timeOperation } from '@glow-up/common-shared';
const result = await timeOperation(
'database-query',
() => prisma.user.findMany(),
logger,
);Validation Patterns
import { ValidationPatterns } from '@glow-up/common-shared';
// Email with normalization
ValidationPatterns.email();
// Strong password requirements
ValidationPatterns.password();
// UUID validation
ValidationPatterns.uuid();
// Pagination parameters
ValidationPatterns.pagination();
// Phone number
ValidationPatterns.phoneNumber();
// Custom enum with case insensitive matching
ValidationPatterns.enumCaseInsensitive(['ACTIVE', 'INACTIVE']);TypeScript Support
This package is built with TypeScript and provides full type definitions. All utilities are properly typed for the best development experience.
// Types are automatically inferred
import {
ApiResponse,
PaginatedResponse,
LogLevel,
} from '@glow-up/common-shared';
// Extend Express types (automatically included)
declare global {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
roles?: string[];
};
}
interface Response {
success: (data?: any, message?: string) => void;
error: (errors: any, message?: string, statusCode?: number) => void;
// ... other response methods
}
}
}Peer Dependencies
Make sure to install peer dependencies if you're using related features:
# For database utilities
npm install @prisma/client
# For logging to files (if using file logging)
npm install winstonContributing
This package is part of the Glow Up microservices ecosystem. When adding new utilities:
- Follow the existing patterns and TypeScript conventions
- Add proper JSDoc documentation
- Include unit tests
- Update this README with usage examples
License
MIT License - see LICENSE file for details.
Changelog
1.0.0
- Initial release with core utilities
- Error handling system
- Validation middleware
- Database utilities
- Response formatting
- Pagination helpers
- Logging system
- Password management
