feat(25-00): create chat_files and chat_file_references DB schema + migrations

- Add chatFiles Drizzle schema with companyId, conversationId, messageId, filename, mimeType, sizeBytes, objectKey, sha256, source, category, projectId columns
- Add chatFileReferences Drizzle schema for cross-conversation file references
- Add 0053_create_chat_files.sql migration with all columns, FKs, and indexes
- Add 0054_create_chat_file_references.sql migration with cascade deletes
- Export both tables from schema/index.ts
- Update _journal.json with entries for idx 53 and 54
This commit is contained in:
Nexus Dev 2026-04-01 22:59:51 +00:00
parent d72c065fc7
commit df88eaa56f
6 changed files with 108 additions and 0 deletions

View file

@ -0,0 +1,26 @@
CREATE TABLE IF NOT EXISTS "chat_files" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"company_id" uuid NOT NULL,
"conversation_id" uuid,
"message_id" uuid,
"filename" text NOT NULL,
"original_filename" text NOT NULL,
"mime_type" text NOT NULL,
"size_bytes" integer NOT NULL,
"object_key" text NOT NULL,
"sha256" text NOT NULL,
"source" text NOT NULL,
"category" text,
"project_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "chat_files_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "companies"("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT "chat_files_conversation_id_chat_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "chat_conversations"("id") ON DELETE SET NULL ON UPDATE NO ACTION,
CONSTRAINT "chat_files_message_id_chat_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "chat_messages"("id") ON DELETE SET NULL ON UPDATE NO ACTION,
CONSTRAINT "chat_files_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE NO ACTION
);
CREATE INDEX IF NOT EXISTS "chat_files_conversation_idx" ON "chat_files" ("conversation_id");
CREATE INDEX IF NOT EXISTS "chat_files_message_idx" ON "chat_files" ("message_id");
CREATE INDEX IF NOT EXISTS "chat_files_company_created_idx" ON "chat_files" ("company_id", "created_at");
CREATE INDEX IF NOT EXISTS "chat_files_project_idx" ON "chat_files" ("project_id");

View file

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS "chat_file_references" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"file_id" uuid NOT NULL,
"conversation_id" uuid NOT NULL,
"message_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "chat_file_references_file_id_chat_files_id_fk" FOREIGN KEY ("file_id") REFERENCES "chat_files"("id") ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT "chat_file_references_conversation_id_chat_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "chat_conversations"("id") ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT "chat_file_references_message_id_chat_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "chat_messages"("id") ON DELETE SET NULL ON UPDATE NO ACTION
);
CREATE INDEX IF NOT EXISTS "chat_file_refs_file_idx" ON "chat_file_references" ("file_id");
CREATE INDEX IF NOT EXISTS "chat_file_refs_conversation_idx" ON "chat_file_references" ("conversation_id");
CREATE INDEX IF NOT EXISTS "chat_file_refs_message_idx" ON "chat_file_references" ("message_id");

View file

@ -365,6 +365,20 @@
"when": 1775200002000,
"tag": "0052_create_chat_message_bookmarks",
"breakpoints": true
},
{
"idx": 53,
"version": "7",
"when": 1775300000000,
"tag": "0053_create_chat_files",
"breakpoints": true
},
{
"idx": 54,
"version": "7",
"when": 1775300001000,
"tag": "0054_create_chat_file_references",
"breakpoints": true
}
]
}

View file

@ -0,0 +1,20 @@
import { pgTable, uuid, timestamp, index } from "drizzle-orm/pg-core";
import { chatFiles } from "./chat_files.js";
import { chatConversations } from "./chat_conversations.js";
import { chatMessages } from "./chat_messages.js";
export const chatFileReferences = pgTable(
"chat_file_references",
{
id: uuid("id").primaryKey().defaultRandom(),
fileId: uuid("file_id").notNull().references(() => chatFiles.id, { onDelete: "cascade" }),
conversationId: uuid("conversation_id").notNull().references(() => chatConversations.id, { onDelete: "cascade" }),
messageId: uuid("message_id").references(() => chatMessages.id, { onDelete: "set null" }),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => ({
fileIdx: index("chat_file_refs_file_idx").on(table.fileId),
conversationIdx: index("chat_file_refs_conversation_idx").on(table.conversationId),
messageIdx: index("chat_file_refs_message_idx").on(table.messageId),
}),
);

View file

@ -0,0 +1,32 @@
import { pgTable, uuid, text, integer, timestamp, index } from "drizzle-orm/pg-core";
import { companies } from "./companies.js";
import { chatConversations } from "./chat_conversations.js";
import { chatMessages } from "./chat_messages.js";
import { projects } from "./projects.js";
export const chatFiles = pgTable(
"chat_files",
{
id: uuid("id").primaryKey().defaultRandom(),
companyId: uuid("company_id").notNull().references(() => companies.id),
conversationId: uuid("conversation_id").references(() => chatConversations.id, { onDelete: "set null" }),
messageId: uuid("message_id").references(() => chatMessages.id, { onDelete: "set null" }),
filename: text("filename").notNull(),
originalFilename: text("original_filename").notNull(),
mimeType: text("mime_type").notNull(),
sizeBytes: integer("size_bytes").notNull(),
objectKey: text("object_key").notNull(),
sha256: text("sha256").notNull(),
source: text("source").notNull(),
category: text("category"),
projectId: uuid("project_id").references(() => projects.id, { onDelete: "set null" }),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => ({
conversationIdx: index("chat_files_conversation_idx").on(table.conversationId),
messageIdx: index("chat_files_message_idx").on(table.messageId),
companyCreatedIdx: index("chat_files_company_created_idx").on(table.companyId, table.createdAt),
projectIdx: index("chat_files_project_idx").on(table.projectId),
}),
);

View file

@ -61,3 +61,5 @@ export { pluginLogs } from "./plugin_logs.js";
export { chatConversations } from "./chat_conversations.js";
export { chatMessages } from "./chat_messages.js";
export { chatMessageBookmarks } from "./chat_message_bookmarks.js";
export { chatFiles } from "./chat_files.js";
export { chatFileReferences } from "./chat_file_references.js";