SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
2.0 KB · 59 lines typescript
Raw Blame History
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