Add PostgreSQL support with SQLite/Postgres database compatibility layer

- Add dbGet/dbAll helper functions for database-agnostic queries
- Add toDbBool/convertBooleansForDb for boolean type conversion
- Add toDbDate/getNow for timestamp type handling
- Add generateId that returns UUID for Postgres, nanoid for SQLite
- Update all routes to use compatibility helpers
- Add normalizeEvent to return clean number types from Postgres decimal
- Add formatPrice utility for consistent price display
- Add legal pages admin interface with RichTextEditor
- Update carousel images
- Add drizzle migration files for PostgreSQL
This commit is contained in:
Michilis
2026-02-02 03:46:35 +00:00
parent 9410e83b89
commit bafd1425c4
61 changed files with 5015 additions and 881 deletions

View File

@@ -3,7 +3,7 @@ import * as argon2 from 'argon2';
import bcrypt from 'bcryptjs';
import crypto from 'crypto';
import { Context } from 'hono';
import { db, users, magicLinkTokens, userSessions } from '../db/index.js';
import { db, dbGet, dbAll, users, magicLinkTokens, userSessions } from '../db/index.js';
import { eq, and, gt } from 'drizzle-orm';
import { generateId, getNow } from './utils.js';
@@ -72,16 +72,17 @@ export async function verifyMagicLinkToken(
): Promise<{ valid: boolean; userId?: string; error?: string }> {
const now = getNow();
const tokenRecord = await (db as any)
.select()
.from(magicLinkTokens)
.where(
and(
eq((magicLinkTokens as any).token, token),
eq((magicLinkTokens as any).type, type)
const tokenRecord = await dbGet<any>(
(db as any)
.select()
.from(magicLinkTokens)
.where(
and(
eq((magicLinkTokens as any).token, token),
eq((magicLinkTokens as any).type, type)
)
)
)
.get();
);
if (!tokenRecord) {
return { valid: false, error: 'Invalid token' };
@@ -132,16 +133,17 @@ export async function createUserSession(
export async function getUserSessions(userId: string) {
const now = getNow();
return (db as any)
.select()
.from(userSessions)
.where(
and(
eq((userSessions as any).userId, userId),
gt((userSessions as any).expiresAt, now)
return dbAll(
(db as any)
.select()
.from(userSessions)
.where(
and(
eq((userSessions as any).userId, userId),
gt((userSessions as any).expiresAt, now)
)
)
)
.all();
);
}
// Invalidate a specific session
@@ -208,7 +210,7 @@ export async function verifyToken(token: string): Promise<JWTPayload | null> {
}
}
export async function getAuthUser(c: Context) {
export async function getAuthUser(c: Context): Promise<any | null> {
const authHeader = c.req.header('Authorization');
if (!authHeader?.startsWith('Bearer ')) {
return null;
@@ -221,7 +223,9 @@ export async function getAuthUser(c: Context) {
return null;
}
const user = await (db as any).select().from(users).where(eq((users as any).id, payload.sub)).get();
const user = await dbGet<any>(
(db as any).select().from(users).where(eq((users as any).id, payload.sub))
);
return user || null;
}
@@ -243,6 +247,8 @@ export function requireAuth(roles?: string[]) {
}
export async function isFirstUser(): Promise<boolean> {
const result = await (db as any).select().from(users).limit(1).all();
const result = await dbAll(
(db as any).select().from(users).limit(1)
);
return !result || result.length === 0;
}