···11-import { drizzle } from "drizzle-orm/bun-sqlite";
22-import { Database } from "bun:sqlite";
11+import { drizzle } from "drizzle-orm/node-postgres";
22+import { Pool } from "pg";
33import * as schema from "./schema";
4455-// Use environment variable for the database path in production
66-const dbPath = process.env.DATABASE_PATH || "./local.db";
55+const pool = new Pool({
66+ connectionString: process.env.DATABASE_URL,
77+});
7888-// Create a SQLite database instance using Bun's built-in driver
99-const sqlite = new Database(dbPath);
99+export const db = drizzle(pool, { schema });
10101111-// Create a Drizzle instance with the database and schema
1212-export const db = drizzle(sqlite, { schema });
1111+// Set up triggers when initializing the database
1212+schema.setupTriggers(pool).catch(console.error);
13131414-// Export the sqlite instance and schema for use in other files
1515-export { sqlite, schema };
1414+export { pool, schema };
+52-21
src/libs/schema.ts
···11-import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
11+import { pgTable, text, integer } from "drizzle-orm/pg-core";
22+import type { Pool } from "pg";
2334// Define the takes table
44-export const takes = sqliteTable("takes", {
55+export const takes = pgTable("takes", {
56 id: text("id").primaryKey(),
67 userId: text("user_id").notNull(),
77- ts: text("ts"),
88- status: text("status").notNull().default("active"), // active, paused, waitingUpload, completed
88+ ts: text("ts").notNull(),
99 elapsedTimeMs: integer("elapsed_time_ms").notNull().default(0),
1010- targetDurationMs: integer("target_duration_ms").notNull(),
1111- periods: text("periods").notNull(), // JSON string of time periods
1212- lastResumeAt: integer("last_resume_at", { mode: "timestamp" }),
1313- createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
1414- () => new Date(),
1515- ),
1616- completedAt: integer("completed_at", { mode: "timestamp" }),
1717- takeUploadedAt: integer("take_uploaded_at", { mode: "timestamp" }),
1818- takeUrl: text("take_url"),
1010+ createdAt: integer("created_at")
1111+ .$defaultFn(() => Math.floor(new Date().getTime() / 1000))
1212+ .notNull(),
1313+ media: text("media").notNull().default("[]"), // array of media urls
1914 multiplier: text("multiplier").notNull().default("1.0"),
2020- notes: text("notes"),
2121- description: text("description"),
2222- notifiedLowTime: integer("notified_low_time", { mode: "boolean" }).default(
2323- false,
2424- ), // has user been notified about low time
2525- notifiedPauseExpiration: integer("notified_pause_expiration", {
2626- mode: "boolean",
2727- }).default(false), // has user been notified about pause expiration
1515+ notes: text("notes").notNull().default(""),
1616+});
1717+1818+export const users = pgTable("users", {
1919+ id: text("id").primaryKey(),
2020+ totalTakesTime: integer("total_takes_time").default(0),
2821});
2222+2323+export async function setupTriggers(pool: Pool) {
2424+ await pool.query(`
2525+ CREATE INDEX IF NOT EXISTS idx_takes_user_id ON takes(user_id);
2626+2727+ CREATE OR REPLACE FUNCTION update_user_total_time()
2828+ RETURNS TRIGGER AS $$
2929+ BEGIN
3030+ IF TG_OP = 'INSERT' THEN
3131+ UPDATE users
3232+ SET total_takes_time = COALESCE(total_takes_time, 0) + NEW.elapsed_time_ms
3333+ WHERE id = NEW.user_id;
3434+ ELSIF TG_OP = 'DELETE' THEN
3535+ UPDATE users
3636+ SET total_takes_time = COALESCE(total_takes_time, 0) - OLD.elapsed_time_ms
3737+ WHERE id = OLD.user_id;
3838+ ELSIF TG_OP = 'UPDATE' THEN
3939+ UPDATE users
4040+ SET total_takes_time = COALESCE(total_takes_time, 0) - OLD.elapsed_time_ms + NEW.elapsed_time_ms
4141+ WHERE id = NEW.user_id;
4242+ END IF;
4343+4444+ EXCEPTION WHEN OTHERS THEN
4545+ RAISE NOTICE 'Error updating user total time: %', SQLERRM;
4646+ RETURN NULL;
4747+4848+ RETURN NEW;
4949+ END;
5050+ $$ LANGUAGE plpgsql;
5151+5252+ DROP TRIGGER IF EXISTS update_user_total_time_trigger ON takes;
5353+5454+ CREATE TRIGGER update_user_total_time_trigger
5555+ AFTER INSERT OR UPDATE OR DELETE ON takes
5656+ FOR EACH ROW
5757+ EXECUTE FUNCTION update_user_total_time();
5858+ `);
5959+}