Files
erika/db/schema.ts
T

124 lines
4.1 KiB
TypeScript

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<AdapterAccount["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<QuestionType>().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<string[]>().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<string, string> }[]>()
.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(""),
});