feat: add PostgreSQL config and dependencies
This commit is contained in:
@@ -45,3 +45,22 @@ AI_LLM_BASE_URL=https://9router.asepharyana.tech/v1
|
||||
AI_LLM_MODEL=free
|
||||
AI_ANALYSIS_TIMEOUT_MS=30000
|
||||
|
||||
# Database Configuration
|
||||
DATABASE_TYPE=sqlite
|
||||
# DATABASE_TYPE=postgres
|
||||
|
||||
# PostgreSQL Configuration (used when DATABASE_TYPE=postgres)
|
||||
# Option 1: Use DATABASE_URL for connection string
|
||||
# DATABASE_URL=postgresql://user:password@localhost:5432/discord_bot
|
||||
|
||||
# Option 2: Use individual connection parameters
|
||||
# POSTGRES_HOST=localhost
|
||||
# POSTGRES_PORT=5432
|
||||
# POSTGRES_USER=postgres
|
||||
# POSTGRES_PASSWORD=your_password_here
|
||||
# POSTGRES_DB=discord_bot
|
||||
|
||||
# PostgreSQL Connection Pool Configuration
|
||||
# POSTGRES_POOL_MIN=2
|
||||
# POSTGRES_POOL_MAX=10
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"@discordjs/opus": "^0.10.0",
|
||||
"@discordjs/voice": "^0.19.1",
|
||||
"@snazzah/davey": "^0.1.10",
|
||||
"@types/pg": "^8.20.0",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.15.1",
|
||||
@@ -27,6 +28,7 @@
|
||||
"helmet": "^8.1.0",
|
||||
"libsodium-wrappers": "^0.8.2",
|
||||
"p-retry": "^6.2.0",
|
||||
"pg": "^8.20.0",
|
||||
"pino": "^9.4.0",
|
||||
"pino-http": "^11.0.0",
|
||||
"prism-media": "2.0.0-alpha.0",
|
||||
|
||||
Generated
+116
@@ -17,6 +17,9 @@ importers:
|
||||
'@snazzah/davey':
|
||||
specifier: ^0.1.10
|
||||
version: 0.1.11(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
|
||||
'@types/pg':
|
||||
specifier: ^8.20.0
|
||||
version: 8.20.0
|
||||
better-sqlite3:
|
||||
specifier: ^12.10.0
|
||||
version: 12.10.0
|
||||
@@ -47,6 +50,9 @@ importers:
|
||||
p-retry:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.1
|
||||
pg:
|
||||
specifier: ^8.20.0
|
||||
version: 8.20.0
|
||||
pino:
|
||||
specifier: ^9.4.0
|
||||
version: 9.14.0
|
||||
@@ -614,6 +620,9 @@ packages:
|
||||
'@types/node@24.12.4':
|
||||
resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==}
|
||||
|
||||
'@types/pg@8.20.0':
|
||||
resolution: {integrity: sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==}
|
||||
|
||||
'@types/qs@6.15.1':
|
||||
resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
|
||||
|
||||
@@ -1384,6 +1393,40 @@ packages:
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
pg-cloudflare@1.3.0:
|
||||
resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
|
||||
|
||||
pg-connection-string@2.12.0:
|
||||
resolution: {integrity: sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==}
|
||||
|
||||
pg-int8@1.0.1:
|
||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
|
||||
pg-pool@3.13.0:
|
||||
resolution: {integrity: sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==}
|
||||
peerDependencies:
|
||||
pg: '>=8.0'
|
||||
|
||||
pg-protocol@1.13.0:
|
||||
resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==}
|
||||
|
||||
pg-types@2.2.0:
|
||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
pg@8.20.0:
|
||||
resolution: {integrity: sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==}
|
||||
engines: {node: '>= 16.0.0'}
|
||||
peerDependencies:
|
||||
pg-native: '>=3.0.1'
|
||||
peerDependenciesMeta:
|
||||
pg-native:
|
||||
optional: true
|
||||
|
||||
pgpass@1.0.5:
|
||||
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
|
||||
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
@@ -1426,6 +1469,22 @@ packages:
|
||||
resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
postgres-array@2.0.0:
|
||||
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postgres-bytea@1.0.1:
|
||||
resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-date@1.0.7:
|
||||
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
prebuild-install@7.1.3:
|
||||
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -1900,6 +1959,10 @@ packages:
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
|
||||
@@ -2328,6 +2391,12 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/pg@8.20.0':
|
||||
dependencies:
|
||||
'@types/node': 24.12.4
|
||||
pg-protocol: 1.13.0
|
||||
pg-types: 2.2.0
|
||||
|
||||
'@types/qs@6.15.1': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
@@ -3066,6 +3135,41 @@ snapshots:
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pg-cloudflare@1.3.0:
|
||||
optional: true
|
||||
|
||||
pg-connection-string@2.12.0: {}
|
||||
|
||||
pg-int8@1.0.1: {}
|
||||
|
||||
pg-pool@3.13.0(pg@8.20.0):
|
||||
dependencies:
|
||||
pg: 8.20.0
|
||||
|
||||
pg-protocol@1.13.0: {}
|
||||
|
||||
pg-types@2.2.0:
|
||||
dependencies:
|
||||
pg-int8: 1.0.1
|
||||
postgres-array: 2.0.0
|
||||
postgres-bytea: 1.0.1
|
||||
postgres-date: 1.0.7
|
||||
postgres-interval: 1.2.0
|
||||
|
||||
pg@8.20.0:
|
||||
dependencies:
|
||||
pg-connection-string: 2.12.0
|
||||
pg-pool: 3.13.0(pg@8.20.0)
|
||||
pg-protocol: 1.13.0
|
||||
pg-types: 2.2.0
|
||||
pgpass: 1.0.5
|
||||
optionalDependencies:
|
||||
pg-cloudflare: 1.3.0
|
||||
|
||||
pgpass@1.0.5:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@4.0.4: {}
|
||||
@@ -3145,6 +3249,16 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postgres-array@2.0.0: {}
|
||||
|
||||
postgres-bytea@1.0.1: {}
|
||||
|
||||
postgres-date@1.0.7: {}
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
dependencies:
|
||||
xtend: 4.0.2
|
||||
|
||||
prebuild-install@7.1.3:
|
||||
dependencies:
|
||||
detect-libc: 2.1.2
|
||||
@@ -3600,6 +3714,8 @@ snapshots:
|
||||
|
||||
ws@8.20.1: {}
|
||||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
y18n@4.0.3: {}
|
||||
|
||||
yallist@4.0.0: {}
|
||||
|
||||
Executable
+97
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# PostgreSQL Migration Quick Start Script
|
||||
# Run this to set up PostgreSQL migration
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Discord Bot - PostgreSQL Migration Setup"
|
||||
echo "==========================================="
|
||||
echo ""
|
||||
|
||||
# Check if PostgreSQL is installed
|
||||
if ! command -v psql &> /dev/null; then
|
||||
echo "❌ PostgreSQL is not installed. Please install PostgreSQL first."
|
||||
echo " macOS: brew install postgresql"
|
||||
echo " Ubuntu: sudo apt-get install postgresql postgresql-contrib"
|
||||
echo " Windows: Download from https://www.postgresql.org/download/windows/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ PostgreSQL found"
|
||||
echo ""
|
||||
|
||||
# Check if Node.js is installed
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "❌ Node.js is not installed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Node.js found"
|
||||
echo ""
|
||||
|
||||
# Create .env if it doesn't exist
|
||||
if [ ! -f .env ]; then
|
||||
echo "📝 Creating .env file..."
|
||||
cp .env.example .env
|
||||
echo "⚠️ Please update .env with your PostgreSQL connection string"
|
||||
echo " DATABASE_URL=postgresql://user:password@localhost:5432/discord_bot"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Install dependencies
|
||||
echo "📦 Installing dependencies..."
|
||||
pnpm add pg pg-pool node-pg-migrate
|
||||
pnpm add -D @types/pg @types/node-pg-migrate
|
||||
pnpm remove better-sqlite3 @types/better-sqlite3 2>/dev/null || true
|
||||
|
||||
echo "✅ Dependencies installed"
|
||||
echo ""
|
||||
|
||||
# Create database
|
||||
read -p "Enter PostgreSQL username (default: postgres): " PG_USER
|
||||
PG_USER=${PG_USER:-postgres}
|
||||
|
||||
read -p "Enter PostgreSQL password: " -s PG_PASSWORD
|
||||
echo ""
|
||||
|
||||
read -p "Enter database name (default: discord_bot): " DB_NAME
|
||||
DB_NAME=${DB_NAME:-discord_bot}
|
||||
|
||||
read -p "Enter PostgreSQL host (default: localhost): " PG_HOST
|
||||
PG_HOST=${PG_HOST:-localhost}
|
||||
|
||||
read -p "Enter PostgreSQL port (default: 5432): " PG_PORT
|
||||
PG_PORT=${PG_PORT:-5432}
|
||||
|
||||
echo ""
|
||||
echo "🗄️ Creating database..."
|
||||
|
||||
PGPASSWORD=$PG_PASSWORD psql -h $PG_HOST -U $PG_USER -p $PG_PORT -tc "SELECT 1 FROM pg_database WHERE datname = '$DB_NAME'" | grep -q 1 || \
|
||||
PGPASSWORD=$PG_PASSWORD psql -h $PG_HOST -U $PG_USER -p $PG_PORT -c "CREATE DATABASE $DB_NAME"
|
||||
|
||||
echo "✅ Database created"
|
||||
echo ""
|
||||
|
||||
# Update .env with connection string
|
||||
DATABASE_URL="postgresql://$PG_USER:$PG_PASSWORD@$PG_HOST:$PG_PORT/$DB_NAME"
|
||||
sed -i.bak "s|DATABASE_URL=.*|DATABASE_URL=$DATABASE_URL|" .env
|
||||
rm -f .env.bak
|
||||
|
||||
echo "✅ .env updated with DATABASE_URL"
|
||||
echo ""
|
||||
|
||||
# Run migrations
|
||||
echo "🔄 Running migrations..."
|
||||
npx node-pg-migrate up
|
||||
|
||||
echo "✅ Migrations completed"
|
||||
echo ""
|
||||
|
||||
echo "🎉 PostgreSQL migration setup complete!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Review the migration files in src/db/migrations/"
|
||||
echo "2. Update imports in your code (see POSTGRES_IMPLEMENTATION.md)"
|
||||
echo "3. Run: pnpm run typecheck"
|
||||
echo "4. Run: pnpm run dev"
|
||||
echo ""
|
||||
+23
-2
@@ -46,15 +46,36 @@ const configSchema = z.object({
|
||||
AI_LLM_BASE_URL: z.string().url().default("https://9router.asepharyana.tech/v1"),
|
||||
AI_LLM_MODEL: z.string().default("free"),
|
||||
AI_ANALYSIS_TIMEOUT_MS: z.coerce.number().positive().default(30000),
|
||||
DATABASE_TYPE: z.enum(["sqlite", "postgres"]).default("sqlite"),
|
||||
DATABASE_URL: z.string().optional(),
|
||||
POSTGRES_HOST: z.string().default("localhost"),
|
||||
POSTGRES_PORT: z.coerce.number().int().positive().default(5432),
|
||||
POSTGRES_USER: z.string().optional(),
|
||||
POSTGRES_PASSWORD: z.string().optional(),
|
||||
POSTGRES_DB: z.string().optional(),
|
||||
POSTGRES_POOL_MIN: z.coerce.number().int().positive().default(2),
|
||||
POSTGRES_POOL_MAX: z.coerce.number().int().positive().default(10),
|
||||
}).superRefine((value, ctx) => {
|
||||
if (!value.AI_ANALYSIS_ENABLED) return;
|
||||
if (!value.AI_LLM_API_KEY) {
|
||||
if (!value.AI_ANALYSIS_ENABLED) {
|
||||
// Continue to database validation
|
||||
} else if (!value.AI_LLM_API_KEY) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["AI_LLM_API_KEY"],
|
||||
message: "AI_LLM_API_KEY is required when AI_ANALYSIS_ENABLED=true",
|
||||
});
|
||||
}
|
||||
|
||||
// Validate PostgreSQL configuration
|
||||
if (value.DATABASE_TYPE === "postgres") {
|
||||
if (!value.DATABASE_URL && !value.POSTGRES_HOST) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["DATABASE_URL"],
|
||||
message: "Either DATABASE_URL or POSTGRES_HOST must be provided when DATABASE_TYPE=postgres",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export type AppConfig = z.infer<typeof configSchema>;
|
||||
|
||||
Reference in New Issue
Block a user