AppForge: migrate off Supabase to external Postgres + Better Auth + local storage

- New Express + TypeScript backend (server/) with pg, Better Auth, local file storage
- De-Supabased Postgres schema (server/db) and TS reimplementations of DB functions
- Frontend data layer rewired to REST (rest-client + backend-client compat shim)
- Removed all Supabase references (code, config, deps, docs)
- New brand assets: gradient favicon/app icons + dark/white wordmark logos

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leon Serfaty
2026-06-28 04:50:29 -04:00
co-authored by Claude Opus 4.8
commit 1a8b8ee5a0
271 changed files with 63734 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
import { one } from '../db.js';
export type AppRole = 'admin' | 'moderator' | 'user';
/** Reimplements public.has_role(uuid, app_role). */
export async function hasRole(userId: string, role: AppRole): Promise<boolean> {
const row = await one<{ exists: boolean }>(
`SELECT EXISTS (SELECT 1 FROM public.user_roles WHERE user_id = $1 AND role = $2) AS exists`,
[userId, role]
);
return !!row?.exists;
}
/** Reimplements public.get_user_role(uuid). Returns null if none. */
export async function getUserRole(userId: string): Promise<AppRole | null> {
const row = await one<{ role: AppRole }>(
`SELECT role FROM public.user_roles WHERE user_id = $1 LIMIT 1`,
[userId]
);
return row?.role ?? null;
}
/** Reimplements public.no_admin_exists(). */
export async function noAdminExists(): Promise<boolean> {
const row = await one<{ exists: boolean }>(
`SELECT NOT EXISTS (SELECT 1 FROM public.user_roles WHERE role = 'admin') AS exists`
);
return !!row?.exists;
}