const crypto = require('node:crypto'); const fs = require('node:fs'); const path = require('node:path'); const postgres = require('postgres'); function readEnvFile(filePath) { if (!fs.existsSync(filePath)) { return {}; } const content = fs.readFileSync(filePath, 'utf8'); return Object.fromEntries( content .split(/\r?\n/) .map((line) => line.trim()) .filter((line) => line && !line.startsWith('#') && line.includes('=')) .map((line) => { const index = line.indexOf('='); const key = line.slice(0, index).trim(); const value = line.slice(index + 1).trim(); return [key, value]; }) ); } function resolveDatabaseUrl() { if (process.env.DATABASE_URL) { return process.env.DATABASE_URL; } const rootDir = process.cwd(); const envLocal = readEnvFile(path.join(rootDir, '.env.local')); if (envLocal.DATABASE_URL) { return envLocal.DATABASE_URL; } const env = readEnvFile(path.join(rootDir, '.env')); if (env.DATABASE_URL) { return env.DATABASE_URL; } throw new Error('DATABASE_URL was not found in process.env, .env.local, or .env'); } function getMigrationFiles(rootDir) { return fs .readdirSync(path.join(rootDir, 'drizzle')) .filter((file) => file.endsWith('.sql')) .sort((left, right) => left.localeCompare(right)); } async function main() { const databaseUrl = resolveDatabaseUrl(); const databaseName = new URL(databaseUrl).pathname.replace(/^\//, ''); const rootDir = process.cwd(); const migrationFiles = getMigrationFiles(rootDir); if (!databaseName) { throw new Error('DATABASE_URL must include a database name'); } const sql = postgres(databaseUrl, { max: 1, prepare: false }); console.log(`Resetting database "${databaseName}"...`); try { await sql` select pg_terminate_backend(pid) from pg_stat_activity where datname = current_database() and pid <> pg_backend_pid() `; await sql.unsafe('drop schema if exists drizzle cascade'); await sql.unsafe('drop schema if exists public cascade'); await sql.unsafe('create schema public'); await sql.unsafe('grant all on schema public to public'); await sql.unsafe('grant all on schema public to postgres'); await sql.unsafe('create schema drizzle'); await sql.unsafe(` create table drizzle.__drizzle_migrations ( id serial primary key, hash text not null, created_at bigint not null ) `); for (const fileName of migrationFiles) { const filePath = path.join(rootDir, 'drizzle', fileName); const sqlContent = fs.readFileSync(filePath, 'utf8'); const statements = sqlContent .split('--> statement-breakpoint') .map((statement) => statement.trim()) .filter(Boolean); for (const statement of statements) { await sql.unsafe(statement); } const hash = crypto.createHash('sha256').update(sqlContent).digest('hex'); await sql` insert into drizzle.__drizzle_migrations (hash, created_at) values (${hash}, ${String(Date.now())}) `; } } finally { await sql.end(); } console.log('Database reset completed.'); } main().catch((error) => { console.error('Failed to reset database.'); console.error(error); process.exit(1); });