| 251 | }; |
| 252 | |
| 253 | export async function getGroupStats( |
| 254 | projectId: string, |
| 255 | groupIds: string[] |
| 256 | ): Promise<Map<string, IServiceGroupStats>> { |
| 257 | if (groupIds.length === 0) { |
| 258 | return new Map(); |
| 259 | } |
| 260 | |
| 261 | const rows = await chQuery<{ |
| 262 | group_id: string; |
| 263 | member_count: number; |
| 264 | last_active_at: string; |
| 265 | }>(` |
| 266 | SELECT |
| 267 | g AS group_id, |
| 268 | uniqExact(profile_id) AS member_count, |
| 269 | max(created_at) AS last_active_at |
| 270 | FROM ${TABLE_NAMES.events} |
| 271 | ARRAY JOIN groups AS g |
| 272 | WHERE project_id = ${sqlstring.escape(projectId)} |
| 273 | AND g IN (${groupIds.map((id) => sqlstring.escape(id)).join(',')}) |
| 274 | AND profile_id != device_id |
| 275 | GROUP BY g |
| 276 | `); |
| 277 | |
| 278 | return new Map( |
| 279 | rows.map((r) => [ |
| 280 | r.group_id, |
| 281 | { |
| 282 | groupId: r.group_id, |
| 283 | memberCount: r.member_count, |
| 284 | lastActiveAt: r.last_active_at ? new Date(r.last_active_at) : null, |
| 285 | }, |
| 286 | ]) |
| 287 | ); |
| 288 | } |
| 289 | |
| 290 | export async function getGroupsByIds( |
| 291 | projectId: string, |