102 lines
2.6 KiB
JavaScript
102 lines
2.6 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;
|
|
}
|
|
}
|
|
|
|
function getMigrationVersion(file) {
|
|
const match = file.match(/^(\d+)_/);
|
|
return match ? match[1] : file;
|
|
}
|
|
|
|
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 version = getMigrationVersion(file);
|
|
const [rows] = await connection.query(
|
|
`
|
|
SELECT version
|
|
FROM schema_migrations
|
|
WHERE version = ?
|
|
OR version = ?
|
|
OR version LIKE ?
|
|
`,
|
|
[version, file, `${version}\\_%`],
|
|
);
|
|
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 (?)',
|
|
[version],
|
|
);
|
|
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);
|
|
});
|