UNPKG

@magic-mustard/sqlsync

Version:

SQLSync simplifies database schema evolution by allowing a declarative approach to table management

117 lines (116 loc) 5.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlterEnumsProcessor = void 0; const namespace_1 = require("../namespace"); const namespace_2 = require("./namespace"); const logger_1 = require("../../utils/logger"); const crypto_1 = require("crypto"); class AlterEnumsProcessor extends namespace_1.Parser.AbstractProcessor { constructor(file, appender, handler, contentBetweenFlags) { super(file, appender, handler, contentBetweenFlags); } process() { // Extract alter enum statements from the file content const alterEnumBlocks = this.getAlterEnumBlocks(); // Process each block of statements this.processAlterEnumBlocks(alterEnumBlocks); } getAlterEnumBlocks() { // Extract ALTER TYPE or ALTER ENUM statements directly from file content const content = this.file.contents; const alterEnumRegex = /ALTER\s+(?:TYPE|ENUM)\s+\w+\s*\.\s*\w+\s+[^;]*;/gi; const matches = content.match(alterEnumRegex) || []; logger_1.logger.debug(`Extracted ALTER TYPE/ENUM statements: ${matches.length} found`); return matches; } hasAlterEnumStatements() { try { const blocks = this.getAlterEnumBlocks(); return blocks.length > 0; } catch (error) { return false; } } processAlterEnumBlocks(blocks) { // Get the full migration state for alter enums const migrationState = this.state.getMigrationState(namespace_2.Enums.AlterEnumStateIndex); for (const block of blocks) { if (!this.validateAlterEnumBlock(block)) { logger_1.logger.warn(`Invalid ALTER TYPE/ENUM block in file: ${this.file.path}`); continue; } const statements = this.splitIntoAlterStatements(block); for (const statement of statements) { const checksum = this.generateChecksum(statement); // Check if this statement already exists in any migration let statementExists = false; for (const [, namespaceData] of Object.entries(migrationState)) { if (namespaceData[namespace_2.Enums.AlterEnumStateIndex] && Object.values(namespaceData[namespace_2.Enums.AlterEnumStateIndex]).some((statements) => Array.isArray(statements) && statements.includes(checksum))) { statementExists = true; break; } if (statementExists) break; } if (statementExists) { // Silently ignore as it's already in the state continue; } // Get the current migration state to update using getLatestMigrationName const currentMigration = this.migrations.getLatestMigrationName(); if (!migrationState[currentMigration]) { migrationState[currentMigration] = { [namespace_2.Enums.AlterEnumStateIndex]: {} }; } const currentState = migrationState[currentMigration]; // Extract schema and enum name from the ALTER TYPE/ENUM statement const schemaEnumName = this.extractSchemaEnumNameFromAlter(statement); if (!schemaEnumName) { logger_1.logger.error(`Failed to extract schema and enum name from ALTER TYPE/ENUM statement in file: ${this.file.path}`); continue; } // If new, add to state if (!currentState[namespace_2.Enums.AlterEnumStateIndex][schemaEnumName]) { currentState[namespace_2.Enums.AlterEnumStateIndex][schemaEnumName] = []; } currentState[namespace_2.Enums.AlterEnumStateIndex][schemaEnumName].push(checksum); // Update state for the latest migration only console.log("AlterEnumsProcessor | State before update:", JSON.stringify(currentState, null, 2)); this.state.updateMigrationState(currentState); // Append to migration this.migrations.append({ token: statement, filePath: this.file.path, checksum: checksum }); } } } splitIntoAlterStatements(block) { // Simple split based on semicolon for now; could be improved with a proper SQL parser return block.split(';') .filter(statement => statement.trim().length > 0 && statement.match(/ALTER\s+(?:TYPE|ENUM)/i)) .map(statement => statement.trim() + ';'); } generateChecksum(statement) { return (0, crypto_1.createHash)('sha256').update(statement).digest('hex'); } validateAlterEnumBlock(block) { // Check if the block contains at least one ALTER TYPE statement const alterTypeCount = (block.match(/ALTER\s+(?:TYPE|ENUM)/i) || []).length; return alterTypeCount > 0; } extractSchemaEnumNameFromAlter(statement) { const schemaMatch = statement.match(/ALTER\s+(?:TYPE|ENUM)\s+(?:(\w+)\.)?(\w+)/i); if (!schemaMatch) { return null; } const schema = schemaMatch[1]; if (!schema) { throw new Error(`Invalid ALTER TYPE/ENUM statement in file ${this.file.path}: Schema must be specified (e.g., public.user_role).`); } const enumName = schemaMatch[2]; return `${schema}.${enumName}`; } } exports.AlterEnumsProcessor = AlterEnumsProcessor;