- 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>
23 lines
792 B
TypeScript
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`;
|
|
}
|