import type { Kysely, Transaction } from 'kysely'; import type { IdentityDatabaseSchema } from '../types/database'; import type { FactRecord, TopicRecord } from '../types/domain'; export type DatabaseExecutor = Kysely | Transaction; export interface FactTopicJoinRow extends TopicRecord { fact_id: string; role: string | null; position: number; } export async function findFactRowsForTopicId( executor: DatabaseExecutor, topicId: string, ): Promise { return executor .selectFrom('facts') .innerJoin('fact_topics', 'fact_topics.fact_id', 'facts.id') .selectAll('facts') .where('fact_topics.topic_id', '=', topicId) .orderBy('facts.created_at', 'asc') .execute(); } export async function findFactRowsConnectingTopicIds( executor: DatabaseExecutor, topicIds: string[], ): Promise { if (topicIds.length === 0) { return []; } return executor .selectFrom('facts') .innerJoin('fact_topics', 'fact_topics.fact_id', 'facts.id') .selectAll('facts') .where('fact_topics.topic_id', 'in', topicIds) .groupBy('facts.id') .having((eb) => eb.fn.count('fact_topics.topic_id'), '=', topicIds.length) .orderBy('facts.created_at', 'asc') .execute(); } export async function findTopicLinksForFactIds( executor: DatabaseExecutor, factIds: string[], ): Promise { if (factIds.length === 0) { return []; } return executor .selectFrom('fact_topics') .innerJoin('topics', 'topics.id', 'fact_topics.topic_id') .selectAll('topics') .select([ 'fact_topics.fact_id as fact_id', 'fact_topics.role as role', 'fact_topics.position as position', ]) .where('fact_topics.fact_id', 'in', factIds) .orderBy('fact_topics.position', 'asc') .execute() as Promise; }