158 lines
5.5 KiB
TypeScript
158 lines
5.5 KiB
TypeScript
export { UserMapper } from './user.mapper';
|
|
export { CompanyMapper } from './company.mapper';
|
|
export { CardsMapper } from './cards.mapper';
|
|
export { ChatMapper } from './chat.mapper';
|
|
export { ContactMapper } from './contact.mapper';
|
|
export { CompanyContactMapper } from './companyContact.mapper';
|
|
|
|
export * from '../dto/user.dto';
|
|
export * from '../dto/company.dto';
|
|
export * from '../dto/cards.dto';
|
|
export * from '../dto/chat.dto';
|
|
export * from '../dto/contact.dto';
|
|
export * from '../dto/companyContact.dto';
|
|
|
|
export * from '../entities/user.entity';
|
|
export * from '../entities/company.entity';
|
|
export * from '../entities/cards.entity';
|
|
export * from '../entities/chat.entity';
|
|
export * from '../entities/contact.entity';
|
|
export * from '../entities/companyContact.entity';
|
|
export interface MapperConfig {
|
|
includeRelations?: boolean;
|
|
includePrivateFields?: boolean;
|
|
userId?: number;
|
|
userCompanyId?: number;
|
|
}
|
|
|
|
export interface IMapper<TEntity, TCreateDto, TUpdateDto, TResponseDto> {
|
|
toEntity(createDto: TCreateDto): TEntity;
|
|
toResponseDto(entity: TEntity): TResponseDto;
|
|
updateEntity(entity: TEntity, updateDto: TUpdateDto): TEntity;
|
|
toResponseDtoArray(entities: TEntity[]): TResponseDto[];
|
|
canMapToResponse(entity: TEntity): boolean;
|
|
}
|
|
|
|
export class MapperUtils {
|
|
|
|
static applyPagination<T>(items: T[], page?: number, limit?: number): T[] {
|
|
if (!page || !limit) return items;
|
|
const startIndex = (page - 1) * limit;
|
|
return items.slice(startIndex, startIndex + limit);
|
|
}
|
|
|
|
static applySorting<T>(items: T[], sortBy?: string, sortOrder?: 'ASC' | 'DESC'): T[] {
|
|
if (!sortBy) return items;
|
|
|
|
return items.sort((a, b) => {
|
|
const aValue = (a as any)[sortBy];
|
|
const bValue = (b as any)[sortBy];
|
|
|
|
if (aValue < bValue) return sortOrder === 'DESC' ? 1 : -1;
|
|
if (aValue > bValue) return sortOrder === 'DESC' ? -1 : 1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
static applyTextFilter<T>(items: T[], searchText: string, searchFields: string[]): T[] {
|
|
if (!searchText) return items;
|
|
|
|
const lowerSearchText = searchText.toLowerCase();
|
|
return items.filter(item => {
|
|
return searchFields.some(field => {
|
|
const fieldValue = (item as any)[field];
|
|
return fieldValue && fieldValue.toString().toLowerCase().includes(lowerSearchText);
|
|
});
|
|
});
|
|
}
|
|
|
|
static applyDateRangeFilter<T>(items: T[], dateField: string, fromDate?: Date, toDate?: Date): T[] {
|
|
return items.filter(item => {
|
|
const itemDate = (item as any)[dateField];
|
|
if (!itemDate) return false;
|
|
|
|
if (fromDate && itemDate < fromDate) return false;
|
|
if (toDate && itemDate > toDate) return false;
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
static enumToDisplayString(enumValue: any): string {
|
|
return enumValue.toString().replace(/_/g, ' ').toLowerCase()
|
|
.replace(/\b\w/g, (char: string) => char.toUpperCase());
|
|
}
|
|
|
|
static isValidEmail(email: string): boolean {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(email);
|
|
}
|
|
|
|
static sanitizeSearchString(searchText: string): string {
|
|
return searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
}
|
|
|
|
static generateMessagePreview(message: string, length: number = 100): string {
|
|
if (message.length <= length) return message;
|
|
return message.substring(0, length).trim() + '...';
|
|
}
|
|
|
|
static getTimeAgo(date: Date): string {
|
|
const now = new Date();
|
|
const diff = now.getTime() - date.getTime();
|
|
const minutes = Math.floor(diff / (1000 * 60));
|
|
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
|
|
if (minutes < 60) return `${minutes} minutes ago`;
|
|
if (hours < 24) return `${hours} hours ago`;
|
|
if (days < 30) return `${days} days ago`;
|
|
return date.toLocaleDateString();
|
|
}
|
|
|
|
static deepClone<T>(obj: T): T {
|
|
return JSON.parse(JSON.stringify(obj));
|
|
}
|
|
|
|
static hasRequiredProperties<T>(obj: any, requiredProps: (keyof T)[]): boolean {
|
|
return requiredProps.every(prop => obj.hasOwnProperty(prop) && obj[prop] !== undefined);
|
|
}
|
|
|
|
static removeUndefinedProperties<T>(obj: T): T {
|
|
const cleaned = { ...obj } as any;
|
|
Object.keys(cleaned).forEach(key => {
|
|
if (cleaned[key] === undefined) {
|
|
delete cleaned[key];
|
|
}
|
|
});
|
|
return cleaned;
|
|
}
|
|
|
|
static groupBy<T, K extends keyof T>(array: T[], property: K): Map<T[K], T[]> {
|
|
const map = new Map<T[K], T[]>();
|
|
array.forEach(item => {
|
|
const key = item[property];
|
|
if (!map.has(key)) {
|
|
map.set(key, []);
|
|
}
|
|
map.get(key)!.push(item);
|
|
});
|
|
return map;
|
|
}
|
|
|
|
static getUniqueValues<T>(array: T[]): T[] {
|
|
return [...new Set(array)];
|
|
}
|
|
|
|
static calculateStats(numbers: number[]): { min: number; max: number; avg: number; sum: number } {
|
|
if (numbers.length === 0) return { min: 0, max: 0, avg: 0, sum: 0 };
|
|
|
|
const sum = numbers.reduce((acc, num) => acc + num, 0);
|
|
const avg = sum / numbers.length;
|
|
const min = Math.min(...numbers);
|
|
const max = Math.max(...numbers);
|
|
|
|
return { min, max, avg, sum };
|
|
}
|
|
}
|