import { chunks, MAX_IN_LIST, placeholders } from "./db";
import { repoDb } from "./scoped-db";
import { locate } from "./scoped-db/locators";
import { REACTION_CONTENTS } from "~/lib/reactions";
import type { ReactionContent, ReactionSubject, ReactionSummary } from "~/lib/reactions";
function isReaction(value: string): value is ReactionContent {
return REACTION_CONTENTS.some((content) => content === value);
}
/** Groups subject ids by the repository that holds them, via the locator directory. */
async function byRepo(subjectType: ReactionSubject, ids: string[]): Promise<Map<string, string[]>> {
const grouped = new Map<string, string[]>();
for (const id of ids) {
const repoId = await locate(subjectType, id);
if (!repoId) continue;
grouped.set(repoId, [...(grouped.get(repoId) ?? []), id]);
}
return grouped;
}
/**
* Aggregated reactions per subject id, with whether the viewer has reacted. Pass `repoId` when every subject is in
* that repository (the usual case: one thread); otherwise each subject's repository is looked up.
*/
export async function reactionSummaries(
subjectType: ReactionSubject,
ids: string[],
viewerId: string | null,
repoId?: string,
): Promise<Map<string, ReactionSummary[]>> {
const out = new Map<string, ReactionSummary[]>();
const unique = [...new Set(ids)];
if (unique.length === 0) return out;
const groups = repoId ? new Map([[repoId, unique]]) : await byRepo(subjectType, unique);
for (const [scope, part] of [...groups].flatMap(([scope, list]) =>
chunks(list, MAX_IN_LIST - 2).map((chunk) => [scope, chunk] as const),
)) {
const rows = await repoDb(scope).all<{
subject_id: string;