user-article.repository.ts•6 kB
/**
* UserArticle repository implementation
*/
import {
UserArticle,
UserArticleCreateInput
} from '../models/prisma.types';
import { prisma } from '../utils/db';
import {
IRepository
} from './base.repository';
import { logger } from '../utils/logger';
/**
* Repository for user article interactions
*/
export class UserArticleRepository implements IRepository<UserArticle, number> {
/**
* Find user article by ID
* @param id UserArticle ID
* @returns UserArticle or null if not found
*/
async findById(id: number): Promise<UserArticle | null> {
try {
return await prisma.userArticle.findUnique({
where: { id }
});
} catch (error) {
logger.error('Error finding user article by ID:', error);
throw error;
}
}
/**
* Find all user articles
* @returns Array of user articles
*/
async findAll(): Promise<UserArticle[]> {
try {
return await prisma.userArticle.findMany();
} catch (error) {
logger.error('Error finding all user articles:', error);
throw error;
}
}
/**
* Create a new user article interaction
* @param data UserArticle data
* @returns Created user article
*/
async create(data: Omit<UserArticle, 'id' | 'createdAt' | 'updatedAt'>): Promise<UserArticle> {
try {
// Convert data to proper input format with proper relation connections
const { userId, articleId, ...rest } = data;
return await prisma.userArticle.create({
data: {
...rest,
user: { connect: { id: userId } },
article: { connect: { id: articleId } }
}
});
} catch (error) {
logger.error('Error creating user article:', error);
throw error;
}
}
/**
* Update a user article
* @param id UserArticle ID
* @param data Updated user article data
* @returns Updated user article
*/
async update(id: number, data: Partial<UserArticle>): Promise<UserArticle> {
try {
return await prisma.userArticle.update({
where: { id },
data
});
} catch (error) {
logger.error('Error updating user article:', error);
throw error;
}
}
/**
* Delete a user article
* @param id UserArticle ID
* @returns True if deleted, false otherwise
*/
async delete(id: number): Promise<boolean> {
try {
await prisma.userArticle.delete({
where: { id }
});
return true;
} catch (error) {
logger.error('Error deleting user article:', error);
return false;
}
}
/**
* Find user article by user ID and article ID
* @param userId User ID
* @param articleId Article ID
* @returns UserArticle or null if not found
*/
async findByUserAndArticle(userId: number, articleId: number): Promise<UserArticle | null> {
try {
return await prisma.userArticle.findUnique({
where: {
userId_articleId: {
userId,
articleId
}
}
});
} catch (error) {
logger.error('Error finding user article by user and article IDs:', error);
throw error;
}
}
/**
* Find all articles bookmarked by a user
* @param userId User ID
* @param limit Maximum number of results
* @returns Array of user articles
*/
async findBookmarkedByUser(userId: number, limit = 50): Promise<UserArticle[]> {
try {
return await prisma.userArticle.findMany({
where: {
userId,
isBookmarked: true
},
take: limit,
orderBy: {
createdAt: 'desc'
},
include: {
article: true
}
});
} catch (error) {
logger.error('Error finding bookmarked articles by user:', error);
throw error;
}
}
/**
* Find all articles read by a user
* @param userId User ID
* @param limit Maximum number of results
* @returns Array of user articles
*/
async findReadByUser(userId: number, limit = 50): Promise<UserArticle[]> {
try {
return await prisma.userArticle.findMany({
where: {
userId,
isRead: true
},
take: limit,
orderBy: {
readAt: 'desc'
},
include: {
article: true
}
});
} catch (error) {
logger.error('Error finding read articles by user:', error);
throw error;
}
}
/**
* Mark article as read by user
* @param userId User ID
* @param articleId Article ID
* @returns Updated or created user article
*/
async markAsRead(userId: number, articleId: number): Promise<UserArticle> {
try {
const now = new Date();
return await prisma.userArticle.upsert({
where: {
userId_articleId: {
userId,
articleId
}
},
update: {
isRead: true,
readAt: now
},
create: {
userId,
articleId,
isRead: true,
readAt: now
}
});
} catch (error) {
logger.error('Error marking article as read:', error);
throw error;
}
}
/**
* Toggle article bookmark status for user
* @param userId User ID
* @param articleId Article ID
* @returns Updated or created user article
*/
async toggleBookmark(userId: number, articleId: number): Promise<UserArticle> {
try {
const existing = await this.findByUserAndArticle(userId, articleId);
if (existing) {
return await prisma.userArticle.update({
where: { id: existing.id },
data: {
isBookmarked: !existing.isBookmarked
}
});
} else {
return await prisma.userArticle.create({
data: {
userId,
articleId,
isBookmarked: true
}
});
}
} catch (error) {
logger.error('Error toggling article bookmark:', error);
throw error;
}
}
}