import { pgTable, text, timestamp, boolean, integer, pgEnum, } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; export const userRoleEnum = pgEnum("user_role", ["user", "moderator", "admin"]); export const tierEnum = pgEnum("tier", ["free", "pro"]); export const unitPrefEnum = pgEnum("unit_pref", ["metric", "imperial"]); export const users = pgTable("users", { id: text("id").primaryKey(), email: text("email").notNull().unique(), emailVerified: boolean("email_verified").notNull().default(false), name: text("name").notNull(), avatarUrl: text("avatar_url"), bio: text("bio"), username: text("username").unique(), role: userRoleEnum("role").notNull().default("user"), tier: tierEnum("tier").notNull().default("free"), unitPref: unitPrefEnum("unit_pref").notNull().default("metric"), locale: text("locale").notNull().default("en"), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); // Better Auth requires these tables export const sessions = pgTable("sessions", { id: text("id").primaryKey(), expiresAt: timestamp("expires_at").notNull(), token: text("token").notNull().unique(), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), ipAddress: text("ip_address"), userAgent: text("user_agent"), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), }); export const accounts = pgTable("accounts", { id: text("id").primaryKey(), accountId: text("account_id").notNull(), providerId: text("provider_id").notNull(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), accessToken: text("access_token"), refreshToken: text("refresh_token"), idToken: text("id_token"), accessTokenExpiresAt: timestamp("access_token_expires_at"), refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), scope: text("scope"), password: text("password"), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); export const verifications = pgTable("verifications", { id: text("id").primaryKey(), identifier: text("identifier").notNull(), value: text("value").notNull(), expiresAt: timestamp("expires_at").notNull(), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); export const userFollows = pgTable("user_follows", { followerId: text("follower_id").notNull().references(() => users.id, { onDelete: "cascade" }), followingId: text("following_id").notNull().references(() => users.id, { onDelete: "cascade" }), createdAt: timestamp("created_at").notNull().defaultNow(), }); export const apiKeys = pgTable("api_keys", { id: text("id").primaryKey(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), name: text("name").notNull(), keyHash: text("key_hash").notNull().unique(), lastUsedAt: timestamp("last_used_at"), createdAt: timestamp("created_at").notNull().defaultNow(), }); export const userAiKeys = pgTable("user_ai_keys", { id: text("id").primaryKey(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), provider: text("provider").notNull(), encryptedKey: text("encrypted_key").notNull(), createdAt: timestamp("created_at").notNull().defaultNow(), }); export const usersRelations = relations(users, ({ many }) => ({ sessions: many(sessions), accounts: many(accounts), followers: many(userFollows, { relationName: "following" }), following: many(userFollows, { relationName: "follower" }), apiKeys: many(apiKeys), aiKeys: many(userAiKeys), })); export const userAiKeysRelations = relations(userAiKeys, ({ one }) => ({ user: one(users, { fields: [userAiKeys.userId], references: [users.id] }), })); export const userFollowsRelations = relations(userFollows, ({ one }) => ({ follower: one(users, { fields: [userFollows.followerId], references: [users.id], relationName: "follower" }), following: one(users, { fields: [userFollows.followingId], references: [users.id], relationName: "following" }), })); export const pushSubscriptions = pgTable("push_subscriptions", { id: text("id").primaryKey(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), endpoint: text("endpoint").notNull().unique(), p256dh: text("p256dh").notNull(), auth: text("auth").notNull(), createdAt: timestamp("created_at").notNull().defaultNow(), }); export const userNutritionGoals = pgTable("user_nutrition_goals", { id: text("id").primaryKey(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }).unique(), caloriesKcal: integer("calories_kcal"), proteinG: integer("protein_g"), carbsG: integer("carbs_g"), fatG: integer("fat_g"), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); export const pushSubscriptionsRelations = relations(pushSubscriptions, ({ one }) => ({ user: one(users, { fields: [pushSubscriptions.userId], references: [users.id] }), })); export const userNutritionGoalsRelations = relations(userNutritionGoals, ({ one }) => ({ user: one(users, { fields: [userNutritionGoals.userId], references: [users.id] }), })); export const userModelPrefs = pgTable("user_model_prefs", { id: text("id").primaryKey(), userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }).unique(), textProvider: text("text_provider"), textModel: text("text_model"), visionProvider: text("vision_provider"), visionModel: text("vision_model"), mealPlanProvider: text("meal_plan_provider"), mealPlanModel: text("meal_plan_model"), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); export const userModelPrefsRelations = relations(userModelPrefs, ({ one }) => ({ user: one(users, { fields: [userModelPrefs.userId], references: [users.id] }), }));