refactor(corp-filter): ♻️ Modularize filtering logic, add type safety, and optimize performance in corporate data filtering utility

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-05-15 18:41:43 -07:00
parent 1211dfcb28
commit 05bbe97a09

View file

@ -0,0 +1,86 @@
import { DataSource } from 'typeorm';
/**
* Cross-corp scoping helper for /api/* endpoints.
*
* Pattern:
* const corpId = await resolveCorpId(this.dataSource, query.corp);
* const corpClause = corpSessionFilter(NEXT_PARAM_IDX, corpId);
* const sql = `... WHERE sf."createdAt" BETWEEN $1 AND $2${corpClause}`;
* const params = corpId === null ? [start, end] : [start, end, corpId];
*
* When `query.corp` is undefined no filter, behaviour unchanged (firehose).
* When `query.corp` resolves to a valid corp AND sf.sessionId IN (... corp_id=$N)
* is appended. Subquery hits idx_raw_events_corp_id_ts (corp_id leading).
*/
const slugCache = new Map<string, number>();
/**
* Resolve a corp slug to its surrogate id. Process-memoized.
* Returns null when slug is undefined/empty (no filter requested).
* Throws when slug is provided but doesn't match any corp.
*/
export async function resolveCorpId(
ds: DataSource,
slug: string | undefined,
): Promise<number | null> {
if (slug === undefined || slug.length === 0) return null;
const cached = slugCache.get(slug);
if (cached !== undefined) return cached;
let rows: Array<{ id: number }>;
try {
rows = await ds.query<Array<{ id: number }>>(
`SELECT id FROM corps WHERE slug = $1 LIMIT 1`,
[slug],
);
} catch (cause) {
throw new Error(
`corp-filter: failed to resolve slug '${slug}': ${cause instanceof Error ? cause.message : String(cause)}`,
{ cause },
);
}
if (rows.length === 0) {
throw new Error(`Unknown corp slug: ${slug}`);
}
const id = Number(rows[0].id);
slugCache.set(slug, id);
return id;
}
/**
* SQL fragment to append to a `WHERE` clause that filters by sessionId
* raw_events.corp_id. Returns an empty string when corpId is null, so the
* caller can unconditionally interpolate it.
*
* The fragment uses the next parameter index passed in (`paramIdx`). The
* caller is responsible for appending `corpId` to its parameter array iff
* the fragment is non-empty (i.e. iff corpId !== null).
*
* Assumes the session_fingerprints table is aliased as `sf` in the caller's
* SQL (which is the universal convention across the existing services).
*/
export function corpSessionFilter(paramIdx: number, corpId: number | null): string {
if (corpId === null) return '';
return ` AND sf."sessionId" IN (
SELECT DISTINCT "sessionId" FROM raw_events WHERE corp_id = $${paramIdx}
)`;
}
/**
* Variant for queries that read raw_events directly (no session_fingerprints
* involvement). Aliased `re` or unaliased caller passes the alias.
*
* Returns ` AND <alias>.corp_id = $N` or empty.
*/
export function corpRawEventsFilter(
paramIdx: number,
corpId: number | null,
alias: string = 'raw_events',
): string {
if (corpId === null) return '';
return ` AND ${alias}.corp_id = $${paramIdx}`;
}