| import { readFile } from "node:fs/promises"; |
| import mysql from "mysql2/promise"; |
|
|
| const DATABASE_URL = process.env.DATABASE_URL; |
| const BOOTSTRAP_SQL_PATH = new URL("../db/init/00-bootstrap.sql", import.meta.url); |
| const RETRY_DELAY_MS = 2000; |
| const MAX_ATTEMPTS = 30; |
|
|
| if (!DATABASE_URL) { |
| console.error("DATABASE_URL is required to bootstrap the database."); |
| process.exit(1); |
| } |
|
|
| const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); |
|
|
| async function connectWithRetry() { |
| let lastError; |
|
|
| for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) { |
| try { |
| const connection = await mysql.createConnection({ |
| uri: DATABASE_URL, |
| multipleStatements: true, |
| }); |
|
|
| await connection.query("SELECT 1"); |
| return connection; |
| } catch (error) { |
| lastError = error; |
| console.log( |
| `Database connection attempt ${attempt}/${MAX_ATTEMPTS} failed. Retrying in ${RETRY_DELAY_MS}ms.` |
| ); |
| await sleep(RETRY_DELAY_MS); |
| } |
| } |
|
|
| throw lastError; |
| } |
|
|
| async function tableExists(connection, tableName) { |
| const [rows] = await connection.query("SHOW TABLES LIKE ?", [tableName]); |
| return Array.isArray(rows) && rows.length > 0; |
| } |
|
|
| function stripUseStatement(sql) { |
| return sql.replace(/^\s*USE\s+[^;]+;\s*/i, ""); |
| } |
|
|
| async function bootstrapIfNeeded() { |
| const connection = await connectWithRetry(); |
|
|
| try { |
| const hasUsers = await tableExists(connection, "users"); |
| const hasSessions = await tableExists(connection, "sessions"); |
| const hasStores = await tableExists(connection, "stores"); |
|
|
| if (hasUsers && hasSessions && hasStores) { |
| console.log("Database bootstrap skipped because required tables already exist."); |
| return; |
| } |
|
|
| const sql = await readFile(BOOTSTRAP_SQL_PATH, "utf8"); |
| await connection.query(stripUseStatement(sql)); |
| console.log("Database bootstrap completed from db/init/00-bootstrap.sql."); |
| } finally { |
| await connection.end(); |
| } |
| } |
|
|
| bootstrapIfNeeded().catch((error) => { |
| console.error("Database bootstrap failed.", error); |
| process.exit(1); |
| }); |
|
|