TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import 'server-only';2import { sql, type SQL } from 'drizzle-orm';3import { getDb } from '@rareindex/database';45/** Run a raw SQL statement and return typed rows (drizzle `execute` returns row arrays for postgres-js). */6export async function rows<T extends Record<string, unknown>>(query: SQL): Promise<T[]> {7 // pnpm resolves two drizzle-orm instances (pg peer via pg-boss vs postgres); the SQL object is identical at runtime.8 const res = await getDb().execute(query as unknown as string);9 return res as unknown as T[];10}1112export async function one<T extends Record<string, unknown>>(query: SQL): Promise<T | null> {13 const r = await rows<T>(query);14 return r[0] ?? null;15}1617export function num(v: unknown): number | null {18 if (v === null || v === undefined || v === '') return null;19 const n = Number(v);20 return Number.isFinite(n) ? n : null;21}2223export function int(v: unknown): number {24 const n = Number(v);25 return Number.isFinite(n) ? Math.trunc(n) : 0;26}2728export function str(v: unknown): string | null {29 return v === null || v === undefined ? null : String(v);30}3132export function date(v: unknown): Date | null {33 if (!v) return null;34 const d = v instanceof Date ? v : new Date(String(v));35 return Number.isNaN(d.getTime()) ? null : d;36}3738export function joinAnd(parts: SQL[]): SQL {39 return parts.length ? sql.join(parts, sql` AND `) : sql`true`;40}4142/** Postgres text[] literal from a JS string array (drizzle expands bare arrays into tuples, not arrays). */43export function textArray(values: string[]): SQL {44 if (!values.length) return sql`ARRAY[]::text[]`;45 return sql`ARRAY[${sql.join(values.map((v) => sql`${v}`), sql`, `)}]::text[]`;46}4748/** ISO string for timestamp params (postgres-js `execute` does not serialise Date instances). */49export function iso(d: Date): string {50 return d.toISOString();51}5253export function clampPage(page: unknown, size = 50): { limit: number; offset: number; page: number } {54 const p = Math.max(1, Math.trunc(Number(page) || 1));55 return { limit: size, offset: (p - 1) * size, page: p };56}5758export { sql };59