feat: configure postgresql as primary database with neon connection

- Updated .env to use PostgreSQL (neondb) instead of SQLite
- Updated drizzle.ts to support DATABASE_URL connection string
- Regenerated migrations for PostgreSQL syntax
- Bot successfully connects and operates with PostgreSQL
- All database operations working correctly
This commit is contained in:
MythEclipse
2026-05-14 16:25:39 +07:00
parent c63a61460c
commit 35269b5bef
7 changed files with 332 additions and 213 deletions

View File

@@ -0,0 +1,69 @@
CREATE TABLE "attachments" (
"id" text PRIMARY KEY NOT NULL,
"message_id" text NOT NULL,
"guild_id" text NOT NULL,
"channel_id" text NOT NULL,
"thread_id" text,
"user_id" text NOT NULL,
"filename" text NOT NULL,
"size" integer NOT NULL,
"type" text NOT NULL,
"discord_url" text NOT NULL,
"uploaded_url" text,
"upload_status" text DEFAULT 'pending' NOT NULL,
"upload_error" text,
"created_at" bigint NOT NULL,
"uploaded_at" bigint
);
--> statement-breakpoint
CREATE TABLE "messages" (
"id" text PRIMARY KEY NOT NULL,
"guild_id" text NOT NULL,
"channel_id" text NOT NULL,
"thread_id" text,
"user_id" text NOT NULL,
"username" text NOT NULL,
"avatar_url" text,
"content" text NOT NULL,
"edited_content" text,
"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,
"ai_moderation_flags" text,
"ai_moderation_score" real,
"ai_moderation_raw" text,
"ai_analysis" text,
"ai_analyzed_at" bigint,
"ai_error" text
);
--> statement-breakpoint
CREATE TABLE "muxer_jobs" (
"id" text PRIMARY KEY NOT NULL,
"data" text NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"attempts" integer DEFAULT 0 NOT NULL,
"maxAttempts" integer DEFAULT 3 NOT NULL,
"createdAt" bigint NOT NULL,
"updatedAt" bigint NOT NULL,
"error" text
);
--> statement-breakpoint
CREATE TABLE "ui_state" (
"key" text PRIMARY KEY NOT NULL,
"value" text NOT NULL,
"updated_at" bigint NOT NULL
);
--> statement-breakpoint
ALTER TABLE "attachments" ADD CONSTRAINT "fk_attachments_message_id" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "idx_attachments_channel" ON "attachments" USING btree ("channel_id");--> statement-breakpoint
CREATE INDEX "idx_attachments_message" ON "attachments" USING btree ("message_id");--> statement-breakpoint
CREATE INDEX "idx_attachments_status" ON "attachments" USING btree ("upload_status");--> statement-breakpoint
CREATE INDEX "idx_messages_channel" ON "messages" USING btree ("channel_id");--> statement-breakpoint
CREATE INDEX "idx_messages_user" ON "messages" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "idx_messages_created" ON "messages" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "idx_messages_thread" ON "messages" USING btree ("thread_id");--> statement-breakpoint
CREATE INDEX "idx_muxer_jobs_status" ON "muxer_jobs" USING btree ("status");--> statement-breakpoint
CREATE INDEX "idx_muxer_jobs_createdAt" ON "muxer_jobs" USING btree ("createdAt");

View File

@@ -1,67 +0,0 @@
CREATE TABLE `attachments` (
`id` text PRIMARY KEY NOT NULL,
`message_id` text NOT NULL,
`guild_id` text NOT NULL,
`channel_id` text NOT NULL,
`thread_id` text,
`user_id` text NOT NULL,
`filename` text NOT NULL,
`size` integer NOT NULL,
`type` text NOT NULL,
`discord_url` text NOT NULL,
`uploaded_url` text,
`upload_status` text DEFAULT 'pending' NOT NULL,
`upload_error` text,
`created_at` integer NOT NULL,
`uploaded_at` integer
);
--> statement-breakpoint
CREATE INDEX `idx_attachments_channel` ON `attachments` (`channel_id`);--> statement-breakpoint
CREATE INDEX `idx_attachments_message` ON `attachments` (`message_id`);--> statement-breakpoint
CREATE INDEX `idx_attachments_status` ON `attachments` (`upload_status`);--> statement-breakpoint
CREATE TABLE `messages` (
`id` text PRIMARY KEY NOT NULL,
`guild_id` text NOT NULL,
`channel_id` text NOT NULL,
`thread_id` text,
`user_id` text NOT NULL,
`username` text NOT NULL,
`avatar_url` text,
`content` text NOT NULL,
`edited_content` text,
`created_at` integer NOT NULL,
`edited_at` integer,
`deleted_at` integer,
`type` text DEFAULT 'text' NOT NULL,
`metadata` text,
`ai_status` text DEFAULT 'pending' NOT NULL,
`ai_moderation_flags` text,
`ai_moderation_score` real,
`ai_moderation_raw` text,
`ai_analysis` text,
`ai_analyzed_at` integer,
`ai_error` text
);
--> statement-breakpoint
CREATE INDEX `idx_messages_channel` ON `messages` (`channel_id`);--> statement-breakpoint
CREATE INDEX `idx_messages_user` ON `messages` (`user_id`);--> statement-breakpoint
CREATE INDEX `idx_messages_created` ON `messages` (`created_at`);--> statement-breakpoint
CREATE INDEX `idx_messages_thread` ON `messages` (`thread_id`);--> statement-breakpoint
CREATE TABLE `muxer_jobs` (
`id` text PRIMARY KEY NOT NULL,
`data` text NOT NULL,
`status` text DEFAULT 'pending' NOT NULL,
`attempts` integer DEFAULT 0 NOT NULL,
`maxAttempts` integer DEFAULT 3 NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
`error` text
);
--> statement-breakpoint
CREATE INDEX `idx_muxer_jobs_status` ON `muxer_jobs` (`status`);--> statement-breakpoint
CREATE INDEX `idx_muxer_jobs_createdAt` ON `muxer_jobs` (`createdAt`);--> statement-breakpoint
CREATE TABLE `ui_state` (
`key` text PRIMARY KEY NOT NULL,
`value` text NOT NULL,
`updated_at` integer NOT NULL
);

View File

@@ -1,358 +1,396 @@
{ {
"version": "6", "id": "2b9e2347-dd99-4bf8-bbcb-f407af29ca83",
"dialect": "sqlite",
"id": "0f1b703a-dee9-40f5-807c-776649af94d9",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": { "tables": {
"attachments": { "public.attachments": {
"name": "attachments", "name": "attachments",
"schema": "",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
"type": "text", "type": "text",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"message_id": { "message_id": {
"name": "message_id", "name": "message_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"guild_id": { "guild_id": {
"name": "guild_id", "name": "guild_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"channel_id": { "channel_id": {
"name": "channel_id", "name": "channel_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"thread_id": { "thread_id": {
"name": "thread_id", "name": "thread_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"user_id": { "user_id": {
"name": "user_id", "name": "user_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"filename": { "filename": {
"name": "filename", "name": "filename",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"size": { "size": {
"name": "size", "name": "size",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"type": { "type": {
"name": "type", "name": "type",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"discord_url": { "discord_url": {
"name": "discord_url", "name": "discord_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"uploaded_url": { "uploaded_url": {
"name": "uploaded_url", "name": "uploaded_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"upload_status": { "upload_status": {
"name": "upload_status", "name": "upload_status",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": "'pending'" "default": "'pending'"
}, },
"upload_error": { "upload_error": {
"name": "upload_error", "name": "upload_error",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"uploaded_at": { "uploaded_at": {
"name": "uploaded_at", "name": "uploaded_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
} }
}, },
"indexes": { "indexes": {
"idx_attachments_channel": { "idx_attachments_channel": {
"name": "idx_attachments_channel", "name": "idx_attachments_channel",
"columns": [ "columns": [
"channel_id" {
"expression": "channel_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_attachments_message": { "idx_attachments_message": {
"name": "idx_attachments_message", "name": "idx_attachments_message",
"columns": [ "columns": [
"message_id" {
"expression": "message_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_attachments_status": { "idx_attachments_status": {
"name": "idx_attachments_status", "name": "idx_attachments_status",
"columns": [ "columns": [
"upload_status" {
"expression": "upload_status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"fk_attachments_message_id": {
"name": "fk_attachments_message_id",
"tableFrom": "attachments",
"tableTo": "messages",
"columnsFrom": [
"message_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
} }
}, },
"foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}, },
"messages": { "public.messages": {
"name": "messages", "name": "messages",
"schema": "",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
"type": "text", "type": "text",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"guild_id": { "guild_id": {
"name": "guild_id", "name": "guild_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"channel_id": { "channel_id": {
"name": "channel_id", "name": "channel_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"thread_id": { "thread_id": {
"name": "thread_id", "name": "thread_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"user_id": { "user_id": {
"name": "user_id", "name": "user_id",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"username": { "username": {
"name": "username", "name": "username",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"avatar_url": { "avatar_url": {
"name": "avatar_url", "name": "avatar_url",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"content": { "content": {
"name": "content", "name": "content",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"edited_content": { "edited_content": {
"name": "edited_content", "name": "edited_content",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"edited_at": { "edited_at": {
"name": "edited_at", "name": "edited_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"deleted_at": { "deleted_at": {
"name": "deleted_at", "name": "deleted_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"type": { "type": {
"name": "type", "name": "type",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": "'text'" "default": "'text'"
}, },
"metadata": { "metadata": {
"name": "metadata", "name": "metadata",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_status": { "ai_status": {
"name": "ai_status", "name": "ai_status",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": "'pending'" "default": "'pending'"
}, },
"ai_moderation_flags": { "ai_moderation_flags": {
"name": "ai_moderation_flags", "name": "ai_moderation_flags",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_moderation_score": { "ai_moderation_score": {
"name": "ai_moderation_score", "name": "ai_moderation_score",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_moderation_raw": { "ai_moderation_raw": {
"name": "ai_moderation_raw", "name": "ai_moderation_raw",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_analysis": { "ai_analysis": {
"name": "ai_analysis", "name": "ai_analysis",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_analyzed_at": { "ai_analyzed_at": {
"name": "ai_analyzed_at", "name": "ai_analyzed_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ai_error": { "ai_error": {
"name": "ai_error", "name": "ai_error",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
} }
}, },
"indexes": { "indexes": {
"idx_messages_channel": { "idx_messages_channel": {
"name": "idx_messages_channel", "name": "idx_messages_channel",
"columns": [ "columns": [
"channel_id" {
"expression": "channel_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_messages_user": { "idx_messages_user": {
"name": "idx_messages_user", "name": "idx_messages_user",
"columns": [ "columns": [
"user_id" {
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_messages_created": { "idx_messages_created": {
"name": "idx_messages_created", "name": "idx_messages_created",
"columns": [ "columns": [
"created_at" {
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_messages_thread": { "idx_messages_thread": {
"name": "idx_messages_thread", "name": "idx_messages_thread",
"columns": [ "columns": [
"thread_id" {
"expression": "thread_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
} }
}, },
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}, },
"muxer_jobs": { "public.muxer_jobs": {
"name": "muxer_jobs", "name": "muxer_jobs",
"schema": "",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
"type": "text", "type": "text",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"data": { "data": {
"name": "data", "name": "data",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"status": { "status": {
"name": "status", "name": "status",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": "'pending'" "default": "'pending'"
}, },
"attempts": { "attempts": {
@@ -360,7 +398,6 @@
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": 0 "default": 0
}, },
"maxAttempts": { "maxAttempts": {
@@ -368,92 +405,107 @@
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false,
"default": 3 "default": 3
}, },
"createdAt": { "createdAt": {
"name": "createdAt", "name": "createdAt",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"updatedAt": { "updatedAt": {
"name": "updatedAt", "name": "updatedAt",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"error": { "error": {
"name": "error", "name": "error",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
} }
}, },
"indexes": { "indexes": {
"idx_muxer_jobs_status": { "idx_muxer_jobs_status": {
"name": "idx_muxer_jobs_status", "name": "idx_muxer_jobs_status",
"columns": [ "columns": [
"status" {
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}, },
"idx_muxer_jobs_createdAt": { "idx_muxer_jobs_createdAt": {
"name": "idx_muxer_jobs_createdAt", "name": "idx_muxer_jobs_createdAt",
"columns": [ "columns": [
"createdAt" {
"expression": "createdAt",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": false "isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
} }
}, },
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}, },
"ui_state": { "public.ui_state": {
"name": "ui_state", "name": "ui_state",
"schema": "",
"columns": { "columns": {
"key": { "key": {
"name": "key", "name": "key",
"type": "text", "type": "text",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"value": { "value": {
"name": "value", "name": "value",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"updated_at": { "updated_at": {
"name": "updated_at", "name": "updated_at",
"type": "integer", "type": "bigint",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
} }
}, },
"indexes": {}, "indexes": {},
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "policies": {},
"checkConstraints": {},
"isRLSEnabled": false
} }
}, },
"views": {},
"enums": {}, "enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": { "_meta": {
"columns": {},
"schemas": {}, "schemas": {},
"tables": {}, "tables": {}
"columns": {}
},
"internal": {
"indexes": {}
} }
} }

View File

@@ -1,12 +1,12 @@
{ {
"version": "7", "version": "7",
"dialect": "sqlite", "dialect": "postgresql",
"entries": [ "entries": [
{ {
"idx": 0, "idx": 0,
"version": "6", "version": "7",
"when": 1778747576917, "when": 1778750697764,
"tag": "0000_windy_victor_mancha", "tag": "0000_rare_kitty_pryde",
"breakpoints": true "breakpoints": true
} }
] ]

28
list-databases.ts Normal file
View File

@@ -0,0 +1,28 @@
import "dotenv/config";
import { Pool } from "pg";
async function listDatabases() {
// Connect to default postgres database first
const pool = new Pool({
host: "ep-long-glitter-ao3sjoyu-pooler.c-2.ap-southeast-1.aws.neon.tech",
port: 5432,
user: "neondb_owner",
password: "npg_2ziHMPwZCet9",
database: "postgres",
connectionTimeoutMillis: 10000,
ssl: { rejectUnauthorized: false },
});
try {
const result = await pool.query("SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;");
console.log("✅ Available databases:");
result.rows.forEach((row: any) => {
console.log(` - ${row.datname}`);
});
await pool.end();
} catch (error) {
console.error("❌ Error:", error instanceof Error ? error.message : String(error));
}
}
listDatabases();

View File

@@ -24,15 +24,26 @@ export async function initializeDatabase() {
} }
if (config.DATABASE_TYPE === "postgres") { if (config.DATABASE_TYPE === "postgres") {
const pool = new Pool({ let pool: Pool;
host: config.POSTGRES_HOST,
port: config.POSTGRES_PORT, // Use DATABASE_URL if available, otherwise build from individual variables
user: config.POSTGRES_USER, if (config.DATABASE_URL) {
password: config.POSTGRES_PASSWORD, pool = new Pool({
database: config.POSTGRES_DB, connectionString: config.DATABASE_URL,
min: config.POSTGRES_POOL_MIN, min: config.POSTGRES_POOL_MIN,
max: config.POSTGRES_POOL_MAX, max: config.POSTGRES_POOL_MAX,
}); });
} else {
pool = new Pool({
host: config.POSTGRES_HOST,
port: config.POSTGRES_PORT,
user: config.POSTGRES_USER,
password: config.POSTGRES_PASSWORD,
database: config.POSTGRES_DB,
min: config.POSTGRES_POOL_MIN,
max: config.POSTGRES_POOL_MAX,
});
}
db = drizzlePostgres(pool, { schema }); db = drizzlePostgres(pool, { schema });
logger.info("PostgreSQL database initialized"); logger.info("PostgreSQL database initialized");

26
test-pg-connection.ts Normal file
View File

@@ -0,0 +1,26 @@
import "dotenv/config";
import { Pool } from "pg";
const connectionString = process.env.DATABASE_URL;
console.log("Testing connection to:", connectionString?.replace(/:[^:]*@/, ":***@"));
async function testConnection() {
const pool = new Pool({
connectionString,
connectionTimeoutMillis: 10000,
statement_timeout: 10000,
});
try {
const result = await pool.query("SELECT NOW()");
console.log("✅ Connection successful!");
console.log("✅ Query result:", result.rows[0]);
await pool.end();
process.exit(0);
} catch (error) {
console.error("❌ Connection failed:", error instanceof Error ? error.message : String(error));
process.exit(1);
}
}
testConnection();