Refactor database handling to exclusively support PostgreSQL
- Removed SQLite support from the configuration and database initialization logic. - Updated database migration scripts to focus solely on PostgreSQL migrations. - Simplified logging messages to reflect PostgreSQL usage. - Adjusted database schema definitions to remove SQLite-specific types and structures. - Modified tests to ensure compatibility with PostgreSQL, including changes to table creation and data types. - Cleaned up unused imports and code related to SQLite.
This commit is contained in:
@@ -4,7 +4,6 @@ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
const originalEnv = process.env;
|
||||
|
||||
describe("Drizzle ORM Database", () => {
|
||||
let config: typeof import("../src/config").config;
|
||||
let drizzle: typeof import("../src/database/drizzle");
|
||||
let logger: ReturnType<typeof import("../src/logger").createChildLogger>;
|
||||
|
||||
@@ -14,22 +13,20 @@ describe("Drizzle ORM Database", () => {
|
||||
...originalEnv,
|
||||
DISCORD_TOKEN: "test-token",
|
||||
NODE_ENV: "test",
|
||||
DATABASE_TYPE: originalEnv.DATABASE_TYPE || "sqlite",
|
||||
};
|
||||
|
||||
// Reset modules to pick up new environment
|
||||
vi.resetModules();
|
||||
|
||||
// Import after environment is set
|
||||
const configModule = await import("../src/config");
|
||||
await import("../src/config");
|
||||
const drizzleModule = await import("../src/database/drizzle");
|
||||
const loggerModule = await import("../src/logger");
|
||||
|
||||
config = configModule.config;
|
||||
drizzle = drizzleModule;
|
||||
logger = loggerModule.createChildLogger("database.test");
|
||||
|
||||
logger.info(`Testing with DATABASE_TYPE: ${config.DATABASE_TYPE}`);
|
||||
logger.info("Testing PostgreSQL database initialization");
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { initializeMigrationSqliteDatabase } from "../../src/database/migrate";
|
||||
import { runMigrations } from "../../src/database/migrate";
|
||||
|
||||
describe("initializeMigrationSqliteDatabase", () => {
|
||||
it("creates a SQLite DB with WAL journal mode", () => {
|
||||
const dir = mkdtempSync(join(tmpdir(), "bete-migrate-"));
|
||||
const dbPath = join(dir, "test.db");
|
||||
const { sqlite, db } = initializeMigrationSqliteDatabase(dbPath);
|
||||
|
||||
try {
|
||||
expect(db).toBeDefined();
|
||||
expect(sqlite.pragma("journal_mode", { simple: true })).toBe("wal");
|
||||
} finally {
|
||||
sqlite.close();
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
describe("runMigrations", () => {
|
||||
it("exports the PostgreSQL migration runner", () => {
|
||||
expect(runMigrations).toBeTypeOf("function");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ type ModerationTestGlobal = typeof globalThis & {
|
||||
};
|
||||
|
||||
interface TestDatabase {
|
||||
run(sql: string): void;
|
||||
run(sql: string): Promise<unknown>;
|
||||
}
|
||||
|
||||
function getTestDatabase(): TestDatabase {
|
||||
@@ -63,8 +63,9 @@ function createMessage(id = "message-1"): TestMessage {
|
||||
|
||||
async function createTables() {
|
||||
const db = getTestDatabase();
|
||||
db.run(`DROP TABLE IF EXISTS "messages"`);
|
||||
db.run(`
|
||||
await db.run(`DROP TABLE IF EXISTS "attachments" CASCADE`);
|
||||
await db.run(`DROP TABLE IF EXISTS "messages" CASCADE`);
|
||||
await db.run(`
|
||||
CREATE TABLE IF NOT EXISTS "messages" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"guild_id" text NOT NULL,
|
||||
@@ -75,9 +76,9 @@ async function createTables() {
|
||||
"avatar_url" text,
|
||||
"content" text NOT NULL,
|
||||
"edited_content" text,
|
||||
"created_at" integer NOT NULL,
|
||||
"edited_at" integer,
|
||||
"deleted_at" integer,
|
||||
"created_at" bigint NOT NULL,
|
||||
"edited_at" bigint,
|
||||
"deleted_at" bigint,
|
||||
"type" text DEFAULT 'text' NOT NULL,
|
||||
"metadata" text,
|
||||
"ai_status" text DEFAULT 'pending' NOT NULL,
|
||||
@@ -89,11 +90,11 @@ async function createTables() {
|
||||
"ai_severity" text,
|
||||
"ai_confidence" real,
|
||||
"ai_recommended_action" text,
|
||||
"ai_analyzed_at" integer,
|
||||
"ai_analyzed_at" bigint,
|
||||
"ai_error" text
|
||||
)
|
||||
`);
|
||||
db.run(`
|
||||
await db.run(`
|
||||
DROP TABLE IF EXISTS "attachments";
|
||||
CREATE TABLE IF NOT EXISTS "attachments" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
@@ -109,8 +110,8 @@ async function createTables() {
|
||||
"uploaded_url" text,
|
||||
"upload_status" text DEFAULT 'pending' NOT NULL,
|
||||
"upload_error" text,
|
||||
"created_at" integer NOT NULL,
|
||||
"uploaded_at" integer
|
||||
"created_at" bigint NOT NULL,
|
||||
"uploaded_at" bigint
|
||||
)
|
||||
`);
|
||||
}
|
||||
@@ -124,8 +125,8 @@ describe("captureMessage", () => {
|
||||
beforeEach(async () => {
|
||||
queueMessageAnalysis.mockClear();
|
||||
const db = getTestDatabase();
|
||||
db.run(`DELETE FROM "attachments"`);
|
||||
db.run(`DELETE FROM "messages"`);
|
||||
await db.run(`DELETE FROM "attachments"`);
|
||||
await db.run(`DELETE FROM "messages"`);
|
||||
delete (globalThis as ModerationTestGlobal).moderationBroadcaster;
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import type { MessageRecord } from "../../src/moderation/types";
|
||||
|
||||
interface TestDatabase {
|
||||
run(sql: string): void;
|
||||
run(sql: string): Promise<unknown>;
|
||||
}
|
||||
|
||||
function getTestDatabase(): TestDatabase {
|
||||
@@ -45,12 +45,13 @@ describe("message cursor helpers", () => {
|
||||
describe("message query integration tests", () => {
|
||||
beforeAll(async () => {
|
||||
await initializeDatabase();
|
||||
// Create tables using Drizzle schema (SQLite doesn't support migrations with PostgreSQL syntax)
|
||||
// Create tables directly for isolated query integration tests
|
||||
const db = getTestDatabase();
|
||||
try {
|
||||
// Create messages table
|
||||
await db.run(`
|
||||
DROP TABLE IF EXISTS "messages";
|
||||
DROP TABLE IF EXISTS "attachments" CASCADE;
|
||||
DROP TABLE IF EXISTS "messages" CASCADE;
|
||||
CREATE TABLE IF NOT EXISTS "messages" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"guild_id" text NOT NULL,
|
||||
@@ -61,9 +62,9 @@ describe("message query integration tests", () => {
|
||||
"avatar_url" text,
|
||||
"content" text NOT NULL,
|
||||
"edited_content" text,
|
||||
"created_at" integer NOT NULL,
|
||||
"edited_at" integer,
|
||||
"deleted_at" integer,
|
||||
"created_at" bigint NOT NULL,
|
||||
"edited_at" bigint,
|
||||
"deleted_at" bigint,
|
||||
"type" text DEFAULT 'text' NOT NULL,
|
||||
"metadata" text,
|
||||
"ai_status" text DEFAULT 'pending' NOT NULL,
|
||||
@@ -75,7 +76,7 @@ describe("message query integration tests", () => {
|
||||
"ai_confidence" real,
|
||||
"ai_recommended_action" text,
|
||||
"ai_analysis" text,
|
||||
"ai_analyzed_at" integer,
|
||||
"ai_analyzed_at" bigint,
|
||||
"ai_error" text
|
||||
)
|
||||
`);
|
||||
@@ -97,8 +98,8 @@ describe("message query integration tests", () => {
|
||||
"uploaded_url" text,
|
||||
"upload_status" text DEFAULT 'pending' NOT NULL,
|
||||
"upload_error" text,
|
||||
"created_at" integer NOT NULL,
|
||||
"uploaded_at" integer
|
||||
"created_at" bigint NOT NULL,
|
||||
"uploaded_at" bigint
|
||||
)
|
||||
`);
|
||||
} catch (error) {
|
||||
@@ -110,8 +111,8 @@ describe("message query integration tests", () => {
|
||||
// Clear tables before each test
|
||||
try {
|
||||
const db = getTestDatabase();
|
||||
await db.run(`DELETE FROM "messages"`);
|
||||
await db.run(`DELETE FROM "attachments"`);
|
||||
await db.run(`DELETE FROM "messages"`);
|
||||
} catch (error) {
|
||||
logger.debug({ error }, "Could not clear tables");
|
||||
}
|
||||
@@ -614,6 +615,41 @@ describe("message query integration tests", () => {
|
||||
const msgId1 = "msg-att-1";
|
||||
const msgId2 = "msg-att-2";
|
||||
|
||||
await insertMessage({
|
||||
id: msgId1,
|
||||
guild_id: "guild-123",
|
||||
channel_id: "channel-456",
|
||||
thread_id: null,
|
||||
user_id: "user-789",
|
||||
username: "testuser",
|
||||
avatar_url: null,
|
||||
content: "message with attachment 1",
|
||||
edited_content: null,
|
||||
created_at: Date.now(),
|
||||
edited_at: null,
|
||||
deleted_at: null,
|
||||
type: "text",
|
||||
metadata: null,
|
||||
ai_status: "pending",
|
||||
});
|
||||
await insertMessage({
|
||||
id: msgId2,
|
||||
guild_id: "guild-123",
|
||||
channel_id: "channel-456",
|
||||
thread_id: null,
|
||||
user_id: "user-789",
|
||||
username: "testuser",
|
||||
avatar_url: null,
|
||||
content: "message with attachment 2",
|
||||
edited_content: null,
|
||||
created_at: Date.now(),
|
||||
edited_at: null,
|
||||
deleted_at: null,
|
||||
type: "text",
|
||||
metadata: null,
|
||||
ai_status: "pending",
|
||||
});
|
||||
|
||||
const attachment1 = {
|
||||
id: "att-1",
|
||||
message_id: msgId1,
|
||||
|
||||
Reference in New Issue
Block a user