many fixes resultnig from latest refactoring
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 5m11s

This commit is contained in:
2025-12-08 22:12:04 -08:00
parent 158778c2ec
commit e156c385a5
39 changed files with 867 additions and 141 deletions

View File

@@ -3,7 +3,7 @@ import type { Pool, PoolClient } from 'pg';
import { getPool } from './connection.db';
import { logger } from '../logger.server';
import { UniqueConstraintError, ForeignKeyConstraintError } from './errors.db';
import { Profile, MasterGroceryItem, ShoppingList, ActivityLogItem, UserProfile } from '../../types';
import { Profile, MasterGroceryItem, ShoppingList, ActivityLogItem, UserProfile, SearchQuery } from '../../types';
import { ShoppingRepository } from './shopping.db';
import { PersonalizationRepository } from './personalization.db';
@@ -374,6 +374,85 @@ export class UserRepository {
logger.error('Database error in deleteResetToken:', { error });
}
}
/**
* Creates a following relationship between two users.
* @param followerId The ID of the user who is following.
* @param followingId The ID of the user being followed.
*/
async followUser(followerId: string, followingId: string): Promise<void> {
try {
await this.db.query(
'INSERT INTO public.user_follows (follower_id, following_id) VALUES ($1, $2) ON CONFLICT (follower_id, following_id) DO NOTHING',
[followerId, followingId]
);
} catch (error) {
if (error instanceof Error && 'code' in error && error.code === '23503') {
throw new ForeignKeyConstraintError('One or both users do not exist.');
}
logger.error('Database error in followUser:', { error, followerId, followingId });
throw new Error('Failed to follow user.');
}
}
/**
* Removes a following relationship between two users.
* @param followerId The ID of the user who is unfollowing.
* @param followingId The ID of the user being unfollowed.
*/
async unfollowUser(followerId: string, followingId: string): Promise<void> {
try {
await this.db.query('DELETE FROM public.user_follows WHERE follower_id = $1 AND following_id = $2', [followerId, followingId]);
} catch (error) {
logger.error('Database error in unfollowUser:', { error, followerId, followingId });
throw new Error('Failed to unfollow user.');
}
}
/**
* Retrieves a personalized activity feed for a user, based on the actions of users they follow.
* @param userId The ID of the user for whom to generate the feed.
* @param limit The number of feed items to retrieve.
* @param offset The number of feed items to skip for pagination.
* @returns A promise that resolves to an array of ActivityLogItem objects.
*/
async getUserFeed(userId: string, limit: number, offset: number): Promise<ActivityLogItem[]> {
try {
const query = `
SELECT al.*, p.full_name as user_full_name, p.avatar_url as user_avatar_url
FROM public.activity_log al
JOIN public.user_follows uf ON al.user_id = uf.following_id
JOIN public.profiles p ON al.user_id = p.user_id
WHERE uf.follower_id = $1
ORDER BY al.created_at DESC
LIMIT $2 OFFSET $3;
`;
const res = await this.db.query<ActivityLogItem>(query, [userId, limit, offset]);
return res.rows;
} catch (error) {
logger.error('Database error in getUserFeed:', { error, userId });
throw new Error('Failed to retrieve user feed.');
}
}
/**
* Logs a search query made by a user.
* @param queryData The search query data to log.
* @returns A promise that resolves to the created SearchQuery object.
*/
async logSearchQuery(queryData: Omit<SearchQuery, 'search_query_id' | 'created_at'>): Promise<SearchQuery> {
const { user_id, query_text, result_count, was_successful } = queryData;
try {
const res = await this.db.query<SearchQuery>(
'INSERT INTO public.search_queries (user_id, query_text, result_count, was_successful) VALUES ($1, $2, $3, $4) RETURNING *',
[user_id, query_text, result_count, was_successful]
);
return res.rows[0];
} catch (error) {
logger.error('Database error in logSearchQuery:', { error, queryData });
throw new Error('Failed to log search query.');
}
}
}
/**