yiekheng 17f9ee179f feat(db,web): pg_trgm + indexes + Postgres-backed cache and rate-limit
- Add cacheEntries and rateLimitBuckets tables to schema
- Generate migration 0002_left_jimmy_woo.sql with pg_trgm extension and all indexes
- Implement cache.ts (get/set/delete/getOrSet/sweep) backed by Postgres
- Implement rate-limit.ts (sliding-window UPSERT) backed by Postgres
- Implement search.ts (trigramMatch / trigramRank helpers)
- Add vitest 2.1.9 + vitest.config.ts; 7 unit tests pass (4 cache + 3 rate-limit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 23:03:10 +08:00

23 lines
792 B
TypeScript

import "server-only";
import { sql, type SQL } from "drizzle-orm";
/**
* Build a Drizzle WHERE fragment that fuzzy-matches `column` against `query`
* using pg_trgm's similarity operator. Returns `true` (no filter) when query is
* empty so callers can compose unconditionally.
*
* Caller must ensure a `gin_trgm_ops` index exists on the column.
*/
export function trigramMatch(column: SQL, query: string | null | undefined): SQL {
const q = (query ?? "").trim();
if (!q) return sql`true`;
return sql`${column} % ${q}`;
}
/** Order-by fragment that ranks rows by similarity descending. */
export function trigramRank(column: SQL, query: string | null | undefined): SQL {
const q = (query ?? "").trim();
if (!q) return sql`1`;
return sql`similarity(${column}, ${q}) DESC`;
}