npm package: @myfoto/common-shared
Description: Common utilities and middleware for MyFoto microservices architecture
Author: Glow Up Team
Latest version: 1.0.6

# @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

```bash
npm install @myfoto/common-shared
```

## Features

- 🚨 **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

```typescript
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

```typescript
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

```typescript
import { errorHandler } from '@glow-up/common-shared';

// Add as the last middleware
app.use(errorHandler);
```

## Validation

### Request Validation with Zod

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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 suggestions
```

## RabbitMQ Event System

### Quick Start

```typescript
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: 'john@example.com',
});

// 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.created`
- `product.product.updated`
- `order.order.completed`

### Documentation

- 📚 [Full Event System Documentation](src/events/README.md)
- 📋 [Event Guidelines](EVENT_GUIDELINES.md)
- 🚀 [Quick Reference](QUICK_REFERENCE.md)
- 🔄 [Migration Guide](MIGRATION.md)

## Logging

```typescript
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

```typescript
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.

```typescript
// 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:

```bash
# For database utilities
npm install @prisma/client

# For logging to files (if using file logging)
npm install winston
```

## Contributing

This package is part of the Glow Up microservices ecosystem. When adding new utilities:

1. Follow the existing patterns and TypeScript conventions
2. Add proper JSDoc documentation
3. Include unit tests
4. 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