- Introduced "video" as a new content type across backend and frontend. - Updated validation schemas and MIME-type handling for video files. - Implemented file size limits for videos (10 MB max) in configuration. - Enhanced upload flow with auto-detection of file types (image, GIF, video). - Expanded media processing to handle video files and convert them to WebM format.
67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
import {
|
|
index,
|
|
integer,
|
|
pgEnum,
|
|
pgTable,
|
|
primaryKey,
|
|
timestamp,
|
|
uuid,
|
|
varchar,
|
|
} from "drizzle-orm/pg-core";
|
|
import { categories } from "./categories";
|
|
import { tags } from "./tags";
|
|
import { users } from "./users";
|
|
|
|
export const contentType = pgEnum("content_type", ["meme", "gif", "video"]);
|
|
|
|
export const contents = pgTable(
|
|
"contents",
|
|
{
|
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
userId: uuid("user_id")
|
|
.notNull()
|
|
.references(() => users.uuid, { onDelete: "cascade" }),
|
|
type: contentType("type").notNull(),
|
|
categoryId: uuid("category_id").references(() => categories.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
title: varchar("title", { length: 255 }).notNull(),
|
|
slug: varchar("slug", { length: 255 }).notNull().unique(),
|
|
storageKey: varchar("storage_key", { length: 512 }).notNull().unique(), // Clé interne S3
|
|
mimeType: varchar("mime_type", { length: 128 }).notNull(), // Pour le Content-Type HTTP
|
|
fileSize: integer("file_size").notNull(), // Taille en octets
|
|
views: integer("views").notNull().default(0),
|
|
usageCount: integer("usage_count").notNull().default(0),
|
|
createdAt: timestamp("created_at", { withTimezone: true })
|
|
.notNull()
|
|
.defaultNow(),
|
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
.notNull()
|
|
.defaultNow(),
|
|
deletedAt: timestamp("deleted_at", { withTimezone: true }), // Soft delete
|
|
},
|
|
(table) => ({
|
|
userIdIdx: index("contents_user_id_idx").on(table.userId),
|
|
storageKeyIdx: index("contents_storage_key_idx").on(table.storageKey),
|
|
deletedAtIdx: index("contents_deleted_at_idx").on(table.deletedAt),
|
|
}),
|
|
);
|
|
|
|
export const contentsToTags = pgTable(
|
|
"contents_to_tags",
|
|
{
|
|
contentId: uuid("content_id")
|
|
.notNull()
|
|
.references(() => contents.id, { onDelete: "cascade" }),
|
|
tagId: uuid("tag_id")
|
|
.notNull()
|
|
.references(() => tags.id, { onDelete: "cascade" }),
|
|
},
|
|
(t) => ({
|
|
pk: primaryKey({ columns: [t.contentId, t.tagId] }),
|
|
}),
|
|
);
|
|
|
|
export type ContentInDb = typeof contents.$inferSelect;
|
|
export type NewContentInDb = typeof contents.$inferInsert;
|