Миграции: JS-строки, транзакции, _migrations таблица. Без fs/path. Версия 0.1.23
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ipwhitelist",
|
||||
"version": "0.1.22",
|
||||
"version": "0.1.23",
|
||||
"description": "IP WhiteList microservice for cloud provider",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
module.exports = {
|
||||
version: '0.1.22',
|
||||
version: '0.1.23',
|
||||
|
||||
// ── Среда ─────────────────────────────────────────────────────────────────
|
||||
// APP_ENV=test → тестовый стенд (жёлтый баннер в UI, можно включать тестовый API)
|
||||
|
||||
+56
-3
@@ -1,11 +1,29 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// V2 — инициализация схемы БД
|
||||
// V2 — инициализация схемы БД + миграции
|
||||
//
|
||||
// ЭТО: CREATE TABLE IF NOT EXISTS — безопасный повторный запуск.
|
||||
// НИКАКИХ ALTER, миграций, DO$$ блоков. Только создание таблиц.
|
||||
// ЭТО: CREATE TABLE IF NOT EXISTS (идемпотентно) + applyMigrations().
|
||||
// ЗАЧЕМ: приложение само создаёт таблицы и применяет новые миграции при старте.
|
||||
//
|
||||
// МИГРАЦИИ: встроенные SQL-строки, не из файлов.
|
||||
// Каждая в транзакции (BEGIN/COMMIT), ошибка логируется и пропускается.
|
||||
// Без fs, path, process.exit.
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// ── Миграции (упорядочены, выполняются один раз) ──────────────────────────────
|
||||
const MIGRATIONS = [
|
||||
{
|
||||
name: '001_add_impersonated_by',
|
||||
sql: `ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS impersonated_by VARCHAR(255) DEFAULT NULL`,
|
||||
},
|
||||
{
|
||||
name: '002_add_audit_restore',
|
||||
sql: `ALTER TABLE audit_log DROP CONSTRAINT IF EXISTS audit_log_action_check;
|
||||
ALTER TABLE audit_log ADD CONSTRAINT audit_log_action_check CHECK (action IN ('CREATE','UPDATE','DELETE','RESTORE'))`,
|
||||
},
|
||||
];
|
||||
|
||||
async function ensureSchema(pool) {
|
||||
// 1. Таблицы
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS companies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
@@ -47,9 +65,44 @@ async function ensureSchema(pool) {
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_log_company_time
|
||||
ON audit_log(company_id, created_at DESC);
|
||||
|
||||
-- Таблица учёта выполненных миграций
|
||||
CREATE TABLE IF NOT EXISTS _migrations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) UNIQUE NOT NULL,
|
||||
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
console.log('[db] Schema ensured');
|
||||
|
||||
// 2. Миграции
|
||||
await applyMigrations(pool);
|
||||
}
|
||||
|
||||
async function applyMigrations(pool) {
|
||||
try {
|
||||
const done = new Set(
|
||||
(await pool.query('SELECT name FROM _migrations')).rows.map(r => r.name)
|
||||
);
|
||||
|
||||
for (const m of MIGRATIONS) {
|
||||
if (done.has(m.name)) continue;
|
||||
try {
|
||||
await pool.query('BEGIN');
|
||||
await pool.query(m.sql);
|
||||
await pool.query('INSERT INTO _migrations (name) VALUES ($1)', [m.name]);
|
||||
await pool.query('COMMIT');
|
||||
console.log('[db] Migration applied:', m.name);
|
||||
} catch (e) {
|
||||
await pool.query('ROLLBACK').catch(() => {});
|
||||
console.error('[db] Migration failed:', m.name, e.message);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[db] applyMigrations error:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { ensureSchema };
|
||||
module.exports = { ensureSchema };
|
||||
|
||||
Reference in New Issue
Block a user