refactor: large codebase cleanup - consolidate schemas, migrate to Drizzle ORM, extract frontend components, modernize Docker builds
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 2m22s
Build & Deploy / build-and-push (backend) (push) Failing after 3m22s
Build & Deploy / build-and-push (proxy) (push) Successful in 1m36s
Build & Deploy / deploy (push) Skipped

- Consolidate all DB schema definitions into packages/shared as single source of truth
- Migrate backend from raw SQL to Drizzle ORM across all modules
- Extract frontend inline UI into separate component files
- Refactor discord-gateway circuitBreaker into conversationState + moderationState
- Convert messageStore to Proxy singleton pattern
- Add validateBody/validateQuery middleware + Zod schemas for API endpoints
- Modernize Docker builds with multi-stage + pnpm deploy
- Migrate CI/CD from deployment to image-based pipeline
- Remove 60+ unused/dead files (~15K lines)
- Update color scheme from sky-blue to teal-cyan
- Move DB connection management to @bete/shared/database

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Developer
2026-07-27 21:54:31 +07:00
co-authored by Claude Opus 4.8
parent 63f21513bd
commit 5802d02e29
223 changed files with 11499 additions and 13350 deletions
@@ -5,13 +5,15 @@ import {
COMMAND_VOICE_CONNECT,
COMMAND_VOICE_DISCONNECT,
type CommandReply,
pgMessagesTable,
VOICE_STATUS_KEY,
} from "@bete/shared";
import { eq } from "drizzle-orm";
import {
createChildLogger,
tryCommandThenFallback,
} from "../../shared/commandHelper.js";
import { getPool } from "../../shared/database/index.js";
import { getDatabase } from "../../shared/database/index.js";
import { publishCommand, readRedisStatus } from "../../shared/redis/index.js";
const logger = createChildLogger("voice.service");
@@ -78,11 +80,12 @@ export async function getGuilds(): Promise<Guild[]> {
return withFallback(
() => publishCommand<Guild[]>(COMMAND_GUILDS_LIST, {}),
async () => {
const pool = getPool();
const { rows } = await pool.query(
`SELECT DISTINCT guild_id FROM messages ORDER BY guild_id`,
);
return rows.map((row: Record<string, unknown>) => ({
const db = getDatabase();
const rows = await db
.selectDistinct({ guild_id: pgMessagesTable.guild_id })
.from(pgMessagesTable)
.orderBy(pgMessagesTable.guild_id);
return rows.map((row) => ({
id: String(row.guild_id ?? ""),
name: `Guild ${String(row.guild_id).slice(0, 8)}`,
icon: null,
@@ -101,12 +104,13 @@ export async function getTextChannels(guildId: string): Promise<Channel[]> {
return withFallback(
() => publishCommand<Channel[]>(COMMAND_GUILDS_TEXT_CHANNELS, { guildId }),
async () => {
const pool = getPool();
const { rows } = await pool.query(
`SELECT DISTINCT channel_id FROM messages WHERE guild_id = $1 ORDER BY channel_id`,
[guildId],
);
return rows.map((row: Record<string, unknown>) => ({
const db = getDatabase();
const rows = await db
.selectDistinct({ channel_id: pgMessagesTable.channel_id })
.from(pgMessagesTable)
.where(eq(pgMessagesTable.guild_id, guildId))
.orderBy(pgMessagesTable.channel_id);
return rows.map((row) => ({
id: String(row.channel_id ?? ""),
name: `Channel ${String(row.channel_id).slice(0, 8)}`,
type: "text" as const,