120 lines
3.3 KiB
JavaScript
120 lines
3.3 KiB
JavaScript
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);
|
|
});
|