prisma-migrator
Version:
A Node.js library that extends Prisma ORM's migration with automatic rollback capabilities when migrations fail
132 lines • 4.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
exports.fileExists = fileExists;
exports.readFile = readFile;
exports.findProjectRoot = findProjectRoot;
exports.findMigrationsDir = findMigrationsDir;
exports.executeSql = executeSql;
exports.getRollbackFile = getRollbackFile;
exports.generateRandomString = generateRandomString;
exports.promptConfirmation = promptConfirmation;
const fs_1 = require("fs");
const path_1 = require("path");
const readline_1 = require("readline");
class Logger {
info(message) {
console.log(`ℹ️ ${message}`);
}
success(message) {
console.log(`✅ ${message}`);
}
error(message) {
console.error(`❌ ${message}`);
}
warn(message) {
console.warn(`⚠️ ${message}`);
}
debug(message) {
console.log(`🔍 ${message}`);
}
}
exports.Logger = Logger;
async function fileExists(filePath) {
try {
await fs_1.promises.access(filePath);
return true;
}
catch {
return false;
}
}
async function readFile(filePath) {
return await fs_1.promises.readFile(filePath, 'utf-8');
}
async function findProjectRoot() {
let currentDir = process.cwd();
while (currentDir !== '/') {
const packageJsonPath = (0, path_1.join)(currentDir, 'package.json');
const prismaSchemaPath = (0, path_1.join)(currentDir, 'prisma', 'schema.prisma');
if (await fileExists(packageJsonPath) || await fileExists(prismaSchemaPath)) {
return currentDir;
}
const parentDir = (0, path_1.resolve)(currentDir, '..');
if (parentDir === currentDir)
break;
currentDir = parentDir;
}
return process.cwd();
}
async function findMigrationsDir(customDir) {
if (customDir) {
const absolutePath = (0, path_1.resolve)(customDir);
if (await fileExists(absolutePath)) {
return absolutePath;
}
throw new Error(`Custom migrations directory not found: ${customDir}`);
}
const projectRoot = await findProjectRoot();
const possibleLocations = [
(0, path_1.join)(projectRoot, 'prisma', 'migrations'),
(0, path_1.join)(projectRoot, 'migrations'),
(0, path_1.join)(process.cwd(), 'prisma', 'migrations'),
(0, path_1.join)(process.cwd(), 'migrations'),
'./prisma/migrations',
'./migrations'
];
for (const location of possibleLocations) {
if (await fileExists(location)) {
return (0, path_1.resolve)(location);
}
}
throw new Error(`Could not find Prisma migrations directory. Searched: ${possibleLocations.join(', ')}`);
}
async function executeSql(sql, prisma, logger) {
logger.debug(`Executing SQL: ${sql.substring(0, 100)}...`);
const statements = sql
.split(';')
.map(stmt => stmt.trim())
.filter(stmt => stmt.length > 0);
for (const statement of statements) {
await prisma.$executeRawUnsafe(statement);
}
logger.debug('SQL executed successfully');
}
async function getRollbackFile(migrationName, migrationsDir) {
const migrationDir = (0, path_1.join)(migrationsDir, migrationName);
try {
const files = await fs_1.promises.readdir(migrationDir);
const rollbackFile = files.find(file => file.endsWith('rollback.sql'));
if (rollbackFile) {
return (0, path_1.join)(migrationDir, rollbackFile);
}
}
catch (error) {
return null;
}
return null;
}
function generateRandomString(length = 6) {
const chars = 'abcdefghijklmnopqrstuvwxyz';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
async function promptConfirmation(message) {
const randomString = generateRandomString();
console.log(`\n⚠️ ${message}`);
console.log(`🔒 To proceed, please type: ${randomString}`);
const rl = (0, readline_1.createInterface)({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question('Enter confirmation: ', (answer) => {
rl.close();
resolve(answer.trim() === randomString);
});
});
}
//# sourceMappingURL=utils.js.map