update check-db, add pgcrypto extension if not exists on init migration

This commit is contained in:
Francis Cao 2023-01-20 14:21:11 -08:00
parent fad38dc180
commit 7c0db0633f
2 changed files with 42 additions and 45 deletions

View File

@ -1,3 +1,6 @@
-- CreateExtension
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- CreateTable -- CreateTable
CREATE TABLE "user" ( CREATE TABLE "user" (
"user_id" UUID NOT NULL, "user_id" UUID NOT NULL,

View File

@ -2,14 +2,25 @@
require('dotenv').config(); require('dotenv').config();
const { PrismaClient } = require('@prisma/client'); const { PrismaClient } = require('@prisma/client');
const chalk = require('chalk'); const chalk = require('chalk');
const spawn = require('cross-spawn');
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const semver = require('semver');
if (process.env.SKIP_DB_CHECK) { if (process.env.SKIP_DB_CHECK) {
console.log('Skipping database check.'); console.log('Skipping database check.');
process.exit(0); process.exit(0);
} }
function getDatabaseType(url = process.env.DATABASE_URL) {
const type = process.env.DATABASE_TYPE || (url && url.split(':')[0]);
if (type === 'postgres') {
return 'postgresql';
}
return type;
}
const databaseType = getDatabaseType();
const prisma = new PrismaClient(); const prisma = new PrismaClient();
function success(msg) { function success(msg) {
@ -38,64 +49,47 @@ async function checkConnection() {
} }
} }
async function checkTables() { async function checkDatabaseVersion(databaseType) {
const query = await prisma.$queryRaw`select version() version`;
const version = semver.valid(semver.coerce(query[0].version));
const minVersion = databaseType === 'postgresql' ? '9.4.0' : '5.6.0';
if (semver.lt(version, minVersion)) {
throw new Error(
`Database version is not compatible. Please upgrade to ${databaseType} version to ${minVersion} or greater`,
);
}
success('Database version check successful.');
}
async function checkV1Tables() {
try { try {
await prisma.$queryRaw`select * from user limit 1`; await prisma.$queryRaw`select * from account limit 1`;
success('Database tables found.'); console.log('Umami v1 tables detected. To upgrade from v1 to v2 run');
console.log('npx @umami/migrate-v1-v2');
process.exit(0);
} catch (e) { } catch (e) {
error('Database tables not found.'); // Ignore
console.log('Adding tables...');
console.log(execSync('prisma migrate deploy').toString());
} }
} }
async function run(cmd, args) { async function applyMigration() {
const buffer = []; console.log(execSync('prisma migrate deploy').toString());
const proc = spawn(cmd, args);
return new Promise((resolve, reject) => {
proc.stdout.on('data', data => buffer.push(data));
proc.on('error', () => {
reject(new Error('Failed to run Prisma.'));
});
proc.on('exit', () => resolve(buffer.join('')));
});
}
async function checkMigrations() {
const output = await run('prisma', ['migrate', 'status']);
console.log(output);
const missingMigrations = output.includes('have not yet been applied');
const missingInitialMigration =
output.includes('01_init') && !output.includes('The last common migration is: 01_init');
const notManaged = output.includes('The current database is not managed');
if (notManaged || missingMigrations) {
console.log('Running update...');
if (missingInitialMigration) {
console.log(execSync('prisma migrate resolve --applied "01_init"').toString());
}
console.log(execSync('prisma migrate deploy').toString());
}
success('Database is up to date.'); success('Database is up to date.');
} }
(async () => { (async () => {
let err = false; let err = false;
for (let fn of [checkEnv, checkConnection, checkTables, checkMigrations]) { for (let fn of [checkEnv, checkConnection, checkDatabaseVersion, checkV1Tables, applyMigration]) {
try { try {
await fn(); fn.name === 'checkDatabaseVersion' ? await fn(databaseType) : await fn();
} catch (e) { } catch (e) {
console.log(chalk.red(`${e.message}`)); error(e.message);
err = true; err = true;
} finally { } finally {
await prisma.$disconnect(); await prisma.$disconnect();