| import { eq } from "drizzle-orm"; |
| import { drizzle } from "drizzle-orm/better-sqlite3"; |
| import Database from "better-sqlite3"; |
| import { InsertUser, users, projects, InsertProject, Project } from "../drizzle/schema"; |
|
|
| let _db: ReturnType<typeof drizzle> | null = null; |
|
|
| |
| export async function getDb() { |
| if (!_db && process.env.DATABASE_URL) { |
| try { |
| |
| const dbPath = process.env.DATABASE_URL.replace('file:', ''); |
| const sqlite = new Database(dbPath); |
| _db = drizzle(sqlite); |
| } catch (error) { |
| console.warn("[Database] Failed to connect:", error); |
| _db = null; |
| } |
| } |
| return _db; |
| } |
|
|
| |
| export async function upsertUser(user: InsertUser): Promise<void> { |
| if (!user.openId) { |
| throw new Error("User openId is required for upsert"); |
| } |
|
|
| const db = await getDb(); |
| if (!db) { |
| console.warn("[Database] Cannot upsert user: database not available"); |
| return; |
| } |
|
|
| try { |
| |
| const existingUser = await getUserByOpenId(user.openId); |
| |
| if (existingUser) { |
| |
| const updates: Partial<InsertUser> = {}; |
| if (user.name !== undefined) updates.name = user.name; |
| if (user.email !== undefined) updates.email = user.email; |
| if (user.loginMethod !== undefined) updates.loginMethod = user.loginMethod; |
| if (user.role !== undefined) updates.role = user.role; |
| if (user.lastSignedIn !== undefined) updates.lastSignedIn = user.lastSignedIn; |
| |
| await db.update(users).set(updates).where(eq(users.openId, user.openId)); |
| } else { |
| |
| await db.insert(users).values({ |
| openId: user.openId, |
| name: user.name || null, |
| email: user.email || null, |
| loginMethod: user.loginMethod || null, |
| role: user.role || "user", |
| lastSignedIn: user.lastSignedIn || new Date(), |
| }); |
| } |
| } catch (error) { |
| console.error("[Database] Failed to upsert user:", error); |
| throw error; |
| } |
| } |
|
|
| export async function getUserByOpenId(openId: string) { |
| const db = await getDb(); |
| if (!db) { |
| console.warn("[Database] Cannot get user: database not available"); |
| return undefined; |
| } |
|
|
| const result = await db.select().from(users).where(eq(users.openId, openId)).limit(1); |
|
|
| return result.length > 0 ? result[0] : undefined; |
| } |
|
|
| |
| |
| |
|
|
| |
| |
| |
| export async function getAllProjects(): Promise<Project[]> { |
| const db = await getDb(); |
| if (!db) { |
| console.warn("[Database] Cannot get projects: database not available"); |
| return []; |
| } |
|
|
| const result = await db.select().from(projects); |
| return result; |
| } |
|
|
| |
| |
| |
| export async function getProjectById(id: number): Promise<Project | undefined> { |
| const db = await getDb(); |
| if (!db) { |
| console.warn("[Database] Cannot get project: database not available"); |
| return undefined; |
| } |
|
|
| const result = await db.select().from(projects).where(eq(projects.id, id)).limit(1); |
| return result.length > 0 ? result[0] : undefined; |
| } |
|
|
| |
| |
| |
| export async function createProject(project: InsertProject): Promise<Project> { |
| const db = await getDb(); |
| if (!db) { |
| throw new Error("Database not available"); |
| } |
|
|
| const result = await db.insert(projects).values(project).returning(); |
| |
| if (!result || result.length === 0) { |
| throw new Error("Failed to create project"); |
| } |
| |
| return result[0]; |
| } |
|
|
| |
| |
| |
| export async function updateProject(id: number, updates: Partial<InsertProject>): Promise<Project> { |
| const db = await getDb(); |
| if (!db) { |
| throw new Error("Database not available"); |
| } |
|
|
| const result = await db.update(projects).set(updates).where(eq(projects.id, id)).returning(); |
| |
| if (!result || result.length === 0) { |
| throw new Error("Failed to update project"); |
| } |
| |
| return result[0]; |
| } |
|
|
| |
| |
| |
| export async function deleteProject(id: number): Promise<void> { |
| const db = await getDb(); |
| if (!db) { |
| throw new Error("Database not available"); |
| } |
|
|
| await db.delete(projects).where(eq(projects.id, id)); |
| } |
|
|
| |
| |
| |
| export async function batchReplaceProjects(newProjects: InsertProject[]): Promise<void> { |
| const db = await getDb(); |
| if (!db) { |
| throw new Error("Database not available"); |
| } |
|
|
| |
| await db.delete(projects); |
| |
| |
| if (newProjects.length > 0) { |
| await db.insert(projects).values(newProjects); |
| } |
| } |
|
|
| |
| |
| |
| export async function clearAllProjects(): Promise<void> { |
| const db = await getDb(); |
| if (!db) { |
| throw new Error("Database not available"); |
| } |
|
|
| await db.delete(projects); |
| } |
|
|