76 lines · 2.0 KB
| 1 | /** |
| 2 | * Activity logging service. |
| 3 | * Records events for the activity feed. |
| 4 | */ |
| 5 | |
| 6 | export type ActivityAction = 'push' | 'create_repo' | 'create_mr' | 'merge_mr' | 'close_mr' | 'comment'; |
| 7 | |
| 8 | export interface ActivityDetails { |
| 9 | ref?: string; |
| 10 | commits?: number; |
| 11 | mr_number?: number; |
| 12 | mr_title?: string; |
| 13 | [key: string]: any; |
| 14 | } |
| 15 | |
| 16 | export class ActivityService { |
| 17 | constructor(private db: D1Database) {} |
| 18 | |
| 19 | /** Log an activity event. */ |
| 20 | async log( |
| 21 | repoId: string | null, |
| 22 | userId: string | null, |
| 23 | action: ActivityAction, |
| 24 | details?: ActivityDetails |
| 25 | ): Promise<void> { |
| 26 | await this.db |
| 27 | .prepare( |
| 28 | `INSERT INTO activity_log (repo_id, user_id, action, details) |
| 29 | VALUES (?, ?, ?, ?)` |
| 30 | ) |
| 31 | .bind(repoId, userId, action, details ? JSON.stringify(details) : null) |
| 32 | .run(); |
| 33 | } |
| 34 | |
| 35 | /** Get activity feed for a repo. */ |
| 36 | async getRepoActivity(repoId: string, limit: number = 20): Promise<any[]> { |
| 37 | const result = await this.db |
| 38 | .prepare( |
| 39 | `SELECT al.*, u.username |
| 40 | FROM activity_log al |
| 41 | LEFT JOIN users u ON al.user_id = u.id |
| 42 | WHERE al.repo_id = ? |
| 43 | ORDER BY al.created_at DESC |
| 44 | LIMIT ?` |
| 45 | ) |
| 46 | .bind(repoId, limit) |
| 47 | .all(); |
| 48 | |
| 49 | return result.results.map((row: any) => ({ |
| 50 | ...row, |
| 51 | details: row.details ? JSON.parse(row.details) : null, |
| 52 | })); |
| 53 | } |
| 54 | |
| 55 | /** Get global activity feed (across all repos). */ |
| 56 | async getGlobalActivity(limit: number = 20): Promise<any[]> { |
| 57 | const result = await this.db |
| 58 | .prepare( |
| 59 | `SELECT al.*, u.username, r.name as repo_name, |
| 60 | (SELECT username FROM users WHERE id = r.owner_id) as repo_owner |
| 61 | FROM activity_log al |
| 62 | LEFT JOIN users u ON al.user_id = u.id |
| 63 | LEFT JOIN repositories r ON al.repo_id = r.id |
| 64 | ORDER BY al.created_at DESC |
| 65 | LIMIT ?` |
| 66 | ) |
| 67 | .bind(limit) |
| 68 | .all(); |
| 69 | |
| 70 | return result.results.map((row: any) => ({ |
| 71 | ...row, |
| 72 | details: row.details ? JSON.parse(row.details) : null, |
| 73 | })); |
| 74 | } |
| 75 | } |
| 76 |