export interface TouchedSlSource { connectionId: string; sourceName: string; } export type TouchedSlSourceSet = Map>; export function createTouchedSlSources(entries: TouchedSlSource[] = []): TouchedSlSourceSet { const touched: TouchedSlSourceSet = new Map(); for (const entry of entries) { addTouchedSlSource(touched, entry.connectionId, entry.sourceName); } return touched; } export function addTouchedSlSource(touched: TouchedSlSourceSet, connectionId: string, sourceName: string): void { const bucket = touched.get(connectionId) ?? new Set(); bucket.add(sourceName); touched.set(connectionId, bucket); } export function deleteTouchedSlSource(touched: TouchedSlSourceSet, connectionId: string, sourceName: string): void { const bucket = touched.get(connectionId); if (!bucket) { return; } bucket.delete(sourceName); if (bucket.size === 0) { touched.delete(connectionId); } } /** @internal */ export function hasTouchedSlSource(touched: TouchedSlSourceSet, connectionId: string, sourceName: string): boolean { return touched.get(connectionId)?.has(sourceName) ?? false; } export function listTouchedSlSources(touched: TouchedSlSourceSet): TouchedSlSource[] { const out: TouchedSlSource[] = []; for (const [connectionId, sources] of touched) { for (const sourceName of sources) { out.push({ connectionId, sourceName }); } } return out.sort((left, right) => { const byConnection = left.connectionId.localeCompare(right.connectionId); return byConnection === 0 ? left.sourceName.localeCompare(right.sourceName) : byConnection; }); } export function touchedSlSourceCount(touched: TouchedSlSourceSet): number { let total = 0; for (const sources of touched.values()) { total += sources.size; } return total; } export function touchedSlSourceNamesForConnection(touched: TouchedSlSourceSet, connectionId: string): string[] { return [...(touched.get(connectionId) ?? [])].sort(); }