import { nanoid } from 'nanoid'; import { randomUUID } from 'crypto'; /** * Get database type (reads env var each time to handle module loading order) */ function getDbType(): string { return process.env.DB_TYPE || 'sqlite'; } /** * Generate a unique ID appropriate for the database type. * - SQLite: returns nanoid (21-char alphanumeric) * - PostgreSQL: returns UUID v4 */ export function generateId(): string { return getDbType() === 'postgres' ? randomUUID() : nanoid(21); } export function generateTicketCode(): string { return `TKT-${nanoid(8).toUpperCase()}`; } /** * Get current timestamp in the format appropriate for the database type. * - SQLite: returns ISO string * - PostgreSQL: returns Date object */ export function getNow(): string | Date { const now = new Date(); return getDbType() === 'postgres' ? now : now.toISOString(); } /** * Convert a date value to the appropriate format for the database type. * - SQLite: returns ISO string * - PostgreSQL: returns Date object */ export function toDbDate(date: Date | string): string | Date { const d = typeof date === 'string' ? new Date(date) : date; return getDbType() === 'postgres' ? d : d.toISOString(); } /** * Convert a boolean value to the appropriate format for the database type. * - SQLite: returns boolean (true/false) for mode: 'boolean' * - PostgreSQL: returns integer (1/0) for pgInteger columns */ export function toDbBool(value: boolean): boolean | number { return getDbType() === 'postgres' ? (value ? 1 : 0) : value; } /** * Convert all boolean values in an object to the appropriate database format. * Useful for converting request data before database insert/update. */ export function convertBooleansForDb>(obj: T): T { if (getDbType() !== 'postgres') { return obj; // SQLite handles booleans automatically } const result = { ...obj }; for (const key in result) { if (typeof result[key] === 'boolean') { (result as any)[key] = result[key] ? 1 : 0; } } return result; } export function formatCurrency(amount: number, currency: string = 'PYG'): string { return new Intl.NumberFormat('es-PY', { style: 'currency', currency, }).format(amount); } export function calculateAvailableSeats(capacity: number, bookedCount: number): number { return Math.max(0, capacity - bookedCount); } export function isEventSoldOut(capacity: number, bookedCount: number): boolean { return bookedCount >= capacity; } export function sanitizeHtml(str: string): string { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }