2026-03-04 18:07:18 +01:00
|
|
|
import {
|
|
|
|
|
pgTable,
|
|
|
|
|
text,
|
|
|
|
|
timestamp,
|
|
|
|
|
boolean,
|
|
|
|
|
integer,
|
|
|
|
|
index,
|
|
|
|
|
uniqueIndex,
|
|
|
|
|
primaryKey,
|
|
|
|
|
} from "drizzle-orm/pg-core";
|
2026-03-04 18:42:58 +01:00
|
|
|
import { users } from "./users";
|
|
|
|
|
import { files } from "./files";
|
2026-03-04 18:07:18 +01:00
|
|
|
|
|
|
|
|
export const videos = pgTable(
|
|
|
|
|
"videos",
|
|
|
|
|
{
|
2026-03-04 22:27:54 +01:00
|
|
|
id: text("id")
|
|
|
|
|
.primaryKey()
|
|
|
|
|
.$defaultFn(() => crypto.randomUUID()),
|
2026-03-04 18:07:18 +01:00
|
|
|
slug: text("slug").notNull(),
|
|
|
|
|
title: text("title").notNull(),
|
|
|
|
|
description: text("description"),
|
|
|
|
|
image: text("image").references(() => files.id, { onDelete: "set null" }),
|
|
|
|
|
movie: text("movie").references(() => files.id, { onDelete: "set null" }),
|
|
|
|
|
tags: text("tags").array().default([]),
|
|
|
|
|
upload_date: timestamp("upload_date").notNull().defaultNow(),
|
|
|
|
|
premium: boolean("premium").default(false),
|
|
|
|
|
featured: boolean("featured").default(false),
|
|
|
|
|
likes_count: integer("likes_count").default(0),
|
|
|
|
|
plays_count: integer("plays_count").default(0),
|
|
|
|
|
},
|
|
|
|
|
(t) => [
|
|
|
|
|
uniqueIndex("videos_slug_idx").on(t.slug),
|
|
|
|
|
index("videos_upload_date_idx").on(t.upload_date),
|
|
|
|
|
index("videos_featured_idx").on(t.featured),
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const video_models = pgTable(
|
|
|
|
|
"video_models",
|
|
|
|
|
{
|
|
|
|
|
video_id: text("video_id")
|
|
|
|
|
.notNull()
|
|
|
|
|
.references(() => videos.id, { onDelete: "cascade" }),
|
|
|
|
|
user_id: text("user_id")
|
|
|
|
|
.notNull()
|
|
|
|
|
.references(() => users.id, { onDelete: "cascade" }),
|
|
|
|
|
},
|
|
|
|
|
(t) => [primaryKey({ columns: [t.video_id, t.user_id] })],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const video_likes = pgTable(
|
|
|
|
|
"video_likes",
|
|
|
|
|
{
|
2026-03-04 22:27:54 +01:00
|
|
|
id: text("id")
|
|
|
|
|
.primaryKey()
|
|
|
|
|
.$defaultFn(() => crypto.randomUUID()),
|
2026-03-04 18:07:18 +01:00
|
|
|
video_id: text("video_id")
|
|
|
|
|
.notNull()
|
|
|
|
|
.references(() => videos.id, { onDelete: "cascade" }),
|
|
|
|
|
user_id: text("user_id")
|
|
|
|
|
.notNull()
|
|
|
|
|
.references(() => users.id, { onDelete: "cascade" }),
|
|
|
|
|
date_created: timestamp("date_created").notNull().defaultNow(),
|
|
|
|
|
},
|
|
|
|
|
(t) => [
|
|
|
|
|
index("video_likes_video_idx").on(t.video_id),
|
|
|
|
|
index("video_likes_user_idx").on(t.user_id),
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const video_plays = pgTable(
|
|
|
|
|
"video_plays",
|
|
|
|
|
{
|
2026-03-04 22:27:54 +01:00
|
|
|
id: text("id")
|
|
|
|
|
.primaryKey()
|
|
|
|
|
.$defaultFn(() => crypto.randomUUID()),
|
2026-03-04 18:07:18 +01:00
|
|
|
video_id: text("video_id")
|
|
|
|
|
.notNull()
|
|
|
|
|
.references(() => videos.id, { onDelete: "cascade" }),
|
|
|
|
|
user_id: text("user_id").references(() => users.id, { onDelete: "set null" }),
|
|
|
|
|
session_id: text("session_id"),
|
|
|
|
|
duration_watched: integer("duration_watched"),
|
|
|
|
|
completed: boolean("completed").default(false),
|
|
|
|
|
date_created: timestamp("date_created").notNull().defaultNow(),
|
|
|
|
|
date_updated: timestamp("date_updated"),
|
|
|
|
|
},
|
|
|
|
|
(t) => [
|
|
|
|
|
index("video_plays_video_idx").on(t.video_id),
|
|
|
|
|
index("video_plays_user_idx").on(t.user_id),
|
|
|
|
|
index("video_plays_date_idx").on(t.date_created),
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export type Video = typeof videos.$inferSelect;
|
|
|
|
|
export type NewVideo = typeof videos.$inferInsert;
|