Files
study_work/packages/backend/scripts/run-sql-migrations.js
T

90 lines
2.3 KiB
JavaScript

/* eslint-disable @typescript-eslint/no-require-imports */
const fs = require('node:fs');
const path = require('node:path');
const mysql = require('mysql2/promise');
function loadRootEnv() {
const envPath = path.resolve(__dirname, '../../../.env');
if (!fs.existsSync(envPath)) {
return;
}
const content = fs.readFileSync(envPath, 'utf8');
for (const line of content.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) {
continue;
}
const separatorIndex = trimmed.indexOf('=');
if (separatorIndex === -1) {
continue;
}
const key = trimmed.slice(0, separatorIndex).trim();
const value = trimmed
.slice(separatorIndex + 1)
.trim()
.replace(/^"|"$/g, '');
process.env[key] ??= value;
}
}
async function main() {
loadRootEnv();
if (!process.env.DATABASE_URL) {
throw new Error('DATABASE_URL is required');
}
const connection = await mysql.createConnection(process.env.DATABASE_URL);
const migrationsDir = path.resolve(__dirname, '../src/database/migrations');
const files = fs
.readdirSync(migrationsDir)
.filter((file) => file.endsWith('.sql'))
.sort();
await connection.query(`
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR(255) NOT NULL PRIMARY KEY,
applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
for (const file of files) {
const [rows] = await connection.query(
'SELECT version FROM schema_migrations WHERE version = ?',
[file],
);
if (rows.length > 0) {
console.log(`skip ${file}`);
continue;
}
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
await connection.beginTransaction();
try {
for (const statement of sql.split(/;\s*(?:\r?\n|$)/)) {
const trimmed = statement.trim();
if (trimmed) {
await connection.query(trimmed);
}
}
await connection.query(
'INSERT INTO schema_migrations (version) VALUES (?)',
[file],
);
await connection.commit();
console.log(`applied ${file}`);
} catch (error) {
await connection.rollback();
throw error;
}
}
await connection.end();
}
main().catch((error) => {
console.error(error);
process.exit(1);
});