feat: add share schema and Discord account reconciliation

This commit is contained in:
2026-08-16 00:48:24 +07:00 Unverified
parent 59a9cc1c19
commit b8e6389ac3
11 changed files with 2517 additions and 13 deletions
+15 -10
View File
@@ -4,21 +4,26 @@ import {
timestamp,
integer,
primaryKey,
uniqueIndex,
} from "drizzle-orm/pg-core";
import type { AdapterAccount } from "next-auth/adapters";
export const accountSchema = pgSchema("account");
export const users = accountSchema.table("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 users = accountSchema.table(
"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"),
},
(user) => [uniqueIndex("user_discord_id_unique").on(user.discordId)]
);
export const accounts = accountSchema.table(
"account",
+85
View File
@@ -0,0 +1,85 @@
import { randomBytes } from "node:crypto";
import {
index,
pgSchema,
text,
timestamp,
} from "drizzle-orm/pg-core";
import { uuidv7 } from "uuidv7";
import { users } from "./account";
import { cdn } from "./form";
export const shareSchema = pgSchema("share");
export type ShareSource = "web" | "bot";
const SHARE_ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
export function createShareId() {
let id = "";
while (id.length < 8) {
for (const value of randomBytes(8)) {
if (value >= 252) continue;
id += SHARE_ID_ALPHABET[value % SHARE_ID_ALPHABET.length];
if (id.length === 8) break;
}
}
return id;
}
export const shareTexts = shareSchema.table(
"text",
{
id: text("id").primaryKey().$defaultFn(createShareId),
content: text("content").notNull(),
description: text("description"),
imageCdnId: text("image_cdn_id").references(() => cdn.id, {
onDelete: "set null",
}),
source: text("source").$type<ShareSource>().notNull(),
authorId: text("author_id").references(() => users.id, {
onDelete: "set null",
}),
authorDiscordId: text("author_discord_id").notNull(),
authorName: text("author_name").notNull(),
authorAvatarUrl: text("author_avatar_url"),
createdAt: timestamp("created_at", { mode: "date", withTimezone: true })
.defaultNow()
.notNull(),
},
(share) => [
index("share_text_author_created_idx").on(
share.authorDiscordId,
share.createdAt
),
]
);
export const shareComments = shareSchema.table(
"comment",
{
id: text("id")
.primaryKey()
.$defaultFn(() => uuidv7()),
shareId: text("share_id")
.notNull()
.references(() => shareTexts.id, { onDelete: "cascade" }),
body: text("body").notNull(),
authorId: text("author_id").references(() => users.id, {
onDelete: "set null",
}),
authorDiscordId: text("author_discord_id").notNull(),
authorName: text("author_name").notNull(),
authorAvatarUrl: text("author_avatar_url"),
createdAt: timestamp("created_at", { mode: "date", withTimezone: true })
.defaultNow()
.notNull(),
},
(comment) => [
index("share_comment_share_created_id_idx").on(
comment.shareId,
comment.createdAt,
comment.id
),
]
);