You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.2 KiB
TypeScript

import type { Database } from 'bun:sqlite';
// ---------------------------------------------------------------------------
// Snapshot freshness
// ---------------------------------------------------------------------------
function maxSnapshotAgeMs(): number {
const raw = Number(process.env.MAX_MEMBERS_SNAPSHOT_AGE_MS);
return Number.isFinite(raw) && raw > 0 ? raw : 24 * 60 * 60 * 1000; // 24h default
}
export function isSnapshotFresh(
db: Database,
groupId: string,
nowMs: number = Date.now()
): boolean {
try {
const row = db
.prepare(`SELECT last_verified FROM groups WHERE id = ?`)
.get(groupId) as { last_verified?: string | null } | undefined;
const lv = row?.last_verified ? String(row.last_verified) : null;
if (!lv) return false;
const iso = lv.includes('T') ? lv : lv.replace(' ', 'T') + 'Z';
const ms = Date.parse(iso);
if (!Number.isFinite(ms)) return false;
return nowMs - ms <= maxSnapshotAgeMs();
} catch {
return false;
}
}
// ---------------------------------------------------------------------------
// Membership queries
// ---------------------------------------------------------------------------
export function isUserActiveInGroup(
db: Database,
userId: string,
groupId: string
): boolean {
if (!userId || !groupId) return false;
const row = db
.prepare(
`SELECT 1 FROM group_members WHERE group_id = ? AND user_id = ? AND is_active = 1 LIMIT 1`
)
.get(groupId, userId);
return !!row;
}
export function getActiveGroupIdsForUser(
db: Database,
userId: string
): string[] {
if (!userId) return [];
const rows = db
.prepare(
`SELECT gm.group_id AS id
FROM group_members gm
JOIN groups g ON g.id = gm.group_id
WHERE gm.user_id = ? AND gm.is_active = 1 AND g.active = 1
AND COALESCE(g.is_community,0) = 0
AND COALESCE(g.archived,0) = 0`
)
.all(userId) as Array<{ id: string }>;
return [...new Set(rows.map(r => String(r.id)))];
}
export function getFreshMemberGroupsForUser(
db: Database,
userId: string
): string[] {
return getActiveGroupIdsForUser(db, userId).filter(gid =>
isSnapshotFresh(db, gid)
);
}