import { pgTable, text, timestamp, boolean, integer, jsonb, primaryKey, } from "drizzle-orm/pg-core"; import type { AdapterAccount } from "next-auth/adapters"; // ─── Auth.js tables ──────────────────────────────────────────────────────── export const users = pgTable("user", { id: text("id") .primaryKey() .$defaultFn(() => crypto.randomUUID()), name: text("name"), email: text("email").unique(), emailVerified: timestamp("emailVerified", { mode: "date" }), image: text("image"), discordId: text("discord_id"), }); export const accounts = pgTable( "account", { userId: text("userId") .notNull() .references(() => users.id, { onDelete: "cascade" }), type: text("type").$type().notNull(), provider: text("provider").notNull(), providerAccountId: text("providerAccountId").notNull(), refresh_token: text("refresh_token"), access_token: text("access_token"), expires_at: integer("expires_at"), token_type: text("token_type"), scope: text("scope"), id_token: text("id_token"), session_state: text("session_state"), }, (account) => [ primaryKey({ columns: [account.provider, account.providerAccountId] }), ] ); export const sessions = pgTable("session", { sessionToken: text("sessionToken").primaryKey(), userId: text("userId") .notNull() .references(() => users.id, { onDelete: "cascade" }), expires: timestamp("expires", { mode: "date" }).notNull(), }); export const verificationTokens = pgTable( "verificationToken", { identifier: text("identifier").notNull(), token: text("token").notNull(), expires: timestamp("expires", { mode: "date" }).notNull(), }, (vt) => [primaryKey({ columns: [vt.identifier, vt.token] })] ); // ─── Form tables ──────────────────────────────────────────────────────────── export const forms = pgTable("form", { id: text("id") .primaryKey() .$defaultFn(() => crypto.randomUUID()), title: text("title").notNull(), description: text("description"), createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull(), isOpen: boolean("is_open").notNull().default(true), discordWebhookUrl: text("discord_webhook_url"), discordWebhookTemplate: text("discord_webhook_template"), discordWebhookUpdateTemplate: text("discord_webhook_update_template"), }); export type QuestionType = "text" | "textarea" | "radio" | "checkbox"; export const questions = pgTable("question", { id: text("id") .primaryKey() .$defaultFn(() => crypto.randomUUID()), formId: text("form_id") .notNull() .references(() => forms.id, { onDelete: "cascade" }), type: text("type").$type().notNull().default("text"), label: text("label").notNull(), imageUrl: text("image_url"), displayOrder: integer("display_order").notNull().default(0), required: boolean("required").notNull().default(false), options: jsonb("options").$type().default([]), }); export const submissions = pgTable("submission", { id: text("id") .primaryKey() .$defaultFn(() => crypto.randomUUID()), formId: text("form_id") .notNull() .references(() => forms.id, { onDelete: "cascade" }), userDiscordId: text("user_discord_id"), userName: text("user_name"), submittedAt: timestamp("submitted_at", { mode: "date" }).defaultNow().notNull(), editHistory: jsonb("edit_history") .$type<{ editedAt: string; oldAnswers: Record }[]>() .default([]), }); export const answers = pgTable("answer", { id: text("id") .primaryKey() .$defaultFn(() => crypto.randomUUID()), submissionId: text("submission_id") .notNull() .references(() => submissions.id, { onDelete: "cascade" }), questionId: text("question_id") .notNull() .references(() => questions.id, { onDelete: "cascade" }), value: text("value").notNull().default(""), });