Domify-Academy-Bot / schema.ts
Domify's picture
Upload 35 files
93c19dc verified
import {
int,
mysqlEnum,
mysqlTable,
text,
timestamp,
varchar,
longtext,
json,
} from "drizzle-orm/mysql-core";
/**
* Core user table backing auth flow.
* Extend this file with additional tables as your product grows.
* Columns use camelCase to match both database fields and generated types.
*/
export const users = mysqlTable("users", {
/**
* Surrogate primary key. Auto-incremented numeric value managed by the database.
* Use this for relations between tables.
*/
id: int("id").autoincrement().primaryKey(),
/** Manus OAuth identifier (openId) returned from the OAuth callback. Unique per user. */
openId: varchar("openId", { length: 64 }).notNull().unique(),
name: text("name"),
email: varchar("email", { length: 320 }),
loginMethod: varchar("loginMethod", { length: 64 }),
role: mysqlEnum("role", ["user", "admin"]).default("user").notNull(),
// Section 2: User tier for rate limiting and feature access
tier: varchar("tier", { length: 50 }).default("free").notNull(),
ipAddress: varchar("ipAddress", { length: 45 }),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
lastSignedIn: timestamp("lastSignedIn").defaultNow().notNull(),
});
export type User = typeof users.$inferSelect;
export type InsertUser = typeof users.$inferInsert;
/**
* Section 2: Conversations table
* Stores conversation metadata per user
*/
export const conversations = mysqlTable("conversations", {
id: int("id").autoincrement().primaryKey(),
userId: int("userId").notNull(),
title: text("title"),
mode: mysqlEnum("mode", ["ask", "imagine"]).default("ask").notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
export type Conversation = typeof conversations.$inferSelect;
export type InsertConversation = typeof conversations.$inferInsert;
/**
* Section 2: Messages table
* Stores individual messages in conversations
*/
export const messages = mysqlTable("messages", {
id: int("id").autoincrement().primaryKey(),
conversationId: int("conversationId").notNull(),
role: mysqlEnum("role", ["user", "assistant"]).notNull(),
content: longtext("content").notNull(),
// Section 5: Reasoning for DeepSeek-style thoughts
reasoning: text("reasoning"),
// Metadata for search results, model used, etc.
metadata: json("metadata"),
createdAt: timestamp("createdAt").defaultNow().notNull(),
});
export type Message = typeof messages.$inferSelect;
export type InsertMessage = typeof messages.$inferInsert;
/**
* Section 8: Images table
* Stores generated images from Imagine mode
*/
export const images = mysqlTable("images", {
id: int("id").autoincrement().primaryKey(),
userId: int("userId").notNull(),
conversationId: int("conversationId"),
prompt: text("prompt").notNull(),
url: text("url").notNull(),
// Metadata: model used, generation time, etc.
metadata: json("metadata"),
createdAt: timestamp("createdAt").defaultNow().notNull(),
});
export type Image = typeof images.$inferSelect;
export type InsertImage = typeof images.$inferInsert;
/**
* Section 2: Feedback table
* Stores user feedback (likes/dislikes) for Google Sheets logging
*/
export const feedback = mysqlTable("feedback", {
id: int("id").autoincrement().primaryKey(),
userId: int("userId").notNull(),
messageId: int("messageId"),
imageId: int("imageId"),
rating: mysqlEnum("rating", ["like", "dislike"]).notNull(),
comment: text("comment"),
createdAt: timestamp("createdAt").defaultNow().notNull(),
});
export type Feedback = typeof feedback.$inferSelect;
export type InsertFeedback = typeof feedback.$inferInsert;