Add new build and database setup scripts to package.json for production
This commit is contained in:
77
scripts/migrate-production.js
Normal file
77
scripts/migrate-production.js
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Production database migration script for DigitalOcean deployment
|
||||
* This script runs database migrations against the production MySQL database
|
||||
*/
|
||||
|
||||
import { drizzle } from 'drizzle-orm/mysql2';
|
||||
import mysql from 'mysql2/promise';
|
||||
import { migrate } from 'drizzle-orm/mysql2/migrator';
|
||||
import { config } from 'dotenv';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Load environment variables
|
||||
config();
|
||||
|
||||
async function runMigrations() {
|
||||
console.log('🚀 Starting production database migration...');
|
||||
|
||||
if (!process.env.DATABASE_URL) {
|
||||
console.error('❌ DATABASE_URL environment variable is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let connection;
|
||||
|
||||
try {
|
||||
// Parse DATABASE_URL for DigitalOcean managed database
|
||||
const dbUrl = new URL(process.env.DATABASE_URL);
|
||||
|
||||
// Create connection to MySQL
|
||||
connection = await mysql.createConnection({
|
||||
host: dbUrl.hostname,
|
||||
port: parseInt(dbUrl.port) || 25060,
|
||||
user: dbUrl.username,
|
||||
password: dbUrl.password,
|
||||
database: dbUrl.pathname.slice(1), // Remove leading slash
|
||||
ssl: {
|
||||
rejectUnauthorized: false // DigitalOcean managed databases use SSL
|
||||
},
|
||||
connectTimeout: 60000,
|
||||
acquireTimeout: 60000,
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
console.log('✅ Connected to database');
|
||||
|
||||
// Create drizzle instance
|
||||
const db = drizzle(connection);
|
||||
|
||||
// Run migrations
|
||||
console.log('🔄 Running migrations...');
|
||||
await migrate(db, { migrationsFolder: join(__dirname, '../drizzle') });
|
||||
|
||||
console.log('✅ Migrations completed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Migration failed:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('🔌 Database connection closed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run migrations if this script is executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runMigrations().catch(console.error);
|
||||
}
|
||||
|
||||
export { runMigrations };
|
116
scripts/setup-production-db.js
Normal file
116
scripts/setup-production-db.js
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Production database setup script for DigitalOcean
|
||||
* This script sets up the initial database structure and creates a default admin user
|
||||
*/
|
||||
|
||||
import { drizzle } from 'drizzle-orm/mysql2';
|
||||
import mysql from 'mysql2/promise';
|
||||
import { migrate } from 'drizzle-orm/mysql2/migrator';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { config } from 'dotenv';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
import * as schema from '../src/lib/db/schema.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Load environment variables
|
||||
config();
|
||||
|
||||
async function setupProductionDatabase() {
|
||||
console.log('🚀 Setting up production database...');
|
||||
|
||||
if (!process.env.DATABASE_URL) {
|
||||
console.error('❌ DATABASE_URL environment variable is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let connection;
|
||||
|
||||
try {
|
||||
// Parse DATABASE_URL for DigitalOcean managed database
|
||||
const dbUrl = new URL(process.env.DATABASE_URL);
|
||||
|
||||
// Create connection to MySQL
|
||||
connection = await mysql.createConnection({
|
||||
host: dbUrl.hostname,
|
||||
port: parseInt(dbUrl.port) || 25060,
|
||||
user: dbUrl.username,
|
||||
password: dbUrl.password,
|
||||
database: dbUrl.pathname.slice(1), // Remove leading slash
|
||||
ssl: {
|
||||
rejectUnauthorized: false // DigitalOcean managed databases use SSL
|
||||
},
|
||||
connectTimeout: 60000,
|
||||
acquireTimeout: 60000,
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
console.log('✅ Connected to database');
|
||||
|
||||
// Create drizzle instance
|
||||
const db = drizzle(connection, { schema });
|
||||
|
||||
// Run migrations
|
||||
console.log('🔄 Running migrations...');
|
||||
await migrate(db, { migrationsFolder: join(__dirname, '../drizzle') });
|
||||
console.log('✅ Migrations completed');
|
||||
|
||||
// Create default admin user
|
||||
console.log('👤 Creating default admin user...');
|
||||
|
||||
const adminEmail = process.env.ADMIN_EMAIL || 'admin@scriptshare.com';
|
||||
const adminPassword = process.env.ADMIN_PASSWORD || 'admin123';
|
||||
const adminUsername = process.env.ADMIN_USERNAME || 'admin';
|
||||
|
||||
// Check if admin user already exists
|
||||
const existingAdmin = await db.query.users.findFirst({
|
||||
where: (users, { eq }) => eq(users.email, adminEmail)
|
||||
});
|
||||
|
||||
if (existingAdmin) {
|
||||
console.log('ℹ️ Admin user already exists, skipping creation');
|
||||
} else {
|
||||
const hashedPassword = await bcrypt.hash(adminPassword, 10);
|
||||
|
||||
await db.insert(schema.users).values({
|
||||
id: nanoid(),
|
||||
email: adminEmail,
|
||||
username: adminUsername,
|
||||
displayName: 'System Administrator',
|
||||
isAdmin: true,
|
||||
isModerator: true,
|
||||
avatarUrl: null,
|
||||
bio: 'Default system administrator account'
|
||||
});
|
||||
|
||||
console.log('✅ Default admin user created');
|
||||
console.log(`📧 Email: ${adminEmail}`);
|
||||
console.log(`👤 Username: ${adminUsername}`);
|
||||
console.log(`🔑 Password: ${adminPassword}`);
|
||||
console.log('⚠️ Please change the default password after first login!');
|
||||
}
|
||||
|
||||
console.log('🎉 Production database setup completed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Setup failed:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('🔌 Database connection closed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run setup if this script is executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
setupProductionDatabase().catch(console.error);
|
||||
}
|
||||
|
||||
export { setupProductionDatabase };
|
Reference in New Issue
Block a user