UNPKG

@deepbrainspace/nx-surrealdb

Version:

NX plugin for SurrealDB migrations with modular architecture

172 lines 7.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PatternResolver = void 0; const tslib_1 = require("tslib"); const migration_file_processor_1 = require("./migration-file-processor"); const debug_1 = require("../infrastructure/debug"); const fs = tslib_1.__importStar(require("fs/promises")); const path = tslib_1.__importStar(require("path")); class PatternResolver { constructor(resolver, basePath) { this.resolver = resolver; this.basePath = basePath; this.debug = debug_1.Debug.scope('pattern-resolver'); } /** * Resolve module patterns using auto-globbing * Examples: "10" -> "010_auth", "auth" -> "010_auth", "010_auth" -> "010_auth" */ resolveModules(patterns) { const resolved = []; const notFound = []; const allModules = this.resolver.getAllModules(); for (const pattern of patterns) { const moduleId = this.findMatchingModule(pattern, allModules); if (moduleId) { resolved.push({ moduleId, pattern }); } else { notFound.push(pattern); } } return { resolved, notFound }; } /** * Resolve filename patterns using auto-globbing * Examples: "1" -> "0001_authentication_up.surql", "auth" -> "0001_authentication_up.surql" */ async resolveFilenames(patterns, targetModules, direction = 'up') { const resolved = []; const notFound = []; // Determine which modules to search in const modulesToSearch = targetModules || this.resolver.getAllModules(); for (const pattern of patterns) { const candidates = []; // Search each module for matching files for (const moduleId of modulesToSearch) { const moduleFiles = await this.getModuleFiles(moduleId, direction); const matchingFile = this.findMatchingFile(pattern, moduleFiles, moduleId); if (matchingFile) { candidates.push(matchingFile); } } if (candidates.length === 0) { notFound.push(pattern); } else if (candidates.length === 1) { // Single match - perfect resolved.push(candidates[0]); } else { // Multiple matches - take all of them regardless of module specification // This allows users to operate on files with the same pattern across multiple modules resolved.push(...candidates); this.debug.log(`Multiple matches for pattern "${pattern}": ${candidates .map(c => `${c.moduleId}/${c.filename}`) .join(', ')}`); } } return { resolved, notFound }; } /** * Special rollback filename resolution - handles dependency checking */ async resolveRollbackFilenames(patterns, targetModules) { const result = await this.resolveFilenames(patterns, targetModules, 'down'); const dependencyWarnings = []; // For rollback, check if the resolved files have dependency conflicts for (const resolved of result.resolved) { // Get all modules that would be affected by this rollback const affectedModules = [resolved.moduleId]; // Validate rollback dependencies const validation = this.resolver.validateRollback(resolved.moduleId, affectedModules); if (!validation.canRollback) { dependencyWarnings.push(`Warning: Rolling back ${resolved.filename} may cause dependency conflicts: ${validation.blockedBy.join(', ')}`); } } return { ...result, dependencyWarnings, }; } findMatchingModule(pattern, allModules) { const normalizedPattern = pattern.trim().toLowerCase(); const patternAsNumber = parseInt(normalizedPattern, 10); const isNumericPattern = !isNaN(patternAsNumber) && /^\d+$/.test(normalizedPattern); // Try index-based mapping first for small numbers (0-based indexing) if (isNumericPattern && patternAsNumber >= 0 && patternAsNumber < allModules.length) { return allModules[patternAsNumber]; } // Try number-based mapping for larger numbers or when index mapping fails const normalizedPatternNumber = isNumericPattern ? patternAsNumber.toString() : null; for (const moduleId of allModules) { const match = moduleId.match(PatternResolver.MODULE_PATTERN); if (!match) continue; const [, number, name] = match; const normalizedNumber = parseInt(number, 10).toString(); if (moduleId.toLowerCase() === normalizedPattern || (normalizedPatternNumber !== null && normalizedPatternNumber === normalizedNumber) || normalizedPattern === name.toLowerCase() || normalizedPattern === `${normalizedNumber}_${name.toLowerCase()}` || normalizedPattern === `${number}_${name.toLowerCase()}`) { return moduleId; } } return null; } findMatchingFile(pattern, files, moduleId) { const normalizedPattern = pattern.trim().toLowerCase(); for (const filename of files) { if (this.matchesFilePattern(filename, normalizedPattern)) { const parsed = migration_file_processor_1.MigrationFileProcessor.parseMigrationFile(filename); if (parsed) { return { filename, pattern, moduleId, number: parsed.number, name: parsed.name, direction: parsed.direction, }; } } } return null; } matchesFilePattern(filename, pattern) { const migration = migration_file_processor_1.MigrationFileProcessor.parseMigrationFile(filename); if (!migration) return false; const lowerPattern = pattern.toLowerCase(); const lowerFilename = filename.toLowerCase(); // For exact filename matches, don't remove leading zeros if (lowerFilename === lowerPattern || lowerFilename === `${lowerPattern}.surql`) { return true; } // For numeric and name patterns, apply normalization const normalizedPattern = pattern.replace(/^0+/, '').toLowerCase(); const normalizedNumber = parseInt(migration.number, 10).toString(); const normalizedMigrationName = migration.name.toLowerCase(); return (normalizedPattern === normalizedNumber || normalizedPattern === normalizedMigrationName || normalizedMigrationName.includes(normalizedPattern) || // Substring matching normalizedPattern === `${normalizedNumber}_${normalizedMigrationName}` || normalizedPattern === `${migration.number}_${normalizedMigrationName}`); } async getModuleFiles(moduleId, direction) { try { const modulePath = path.join(this.basePath, moduleId); const files = await fs.readdir(modulePath); return migration_file_processor_1.MigrationFileProcessor.filterMigrationFiles(files, undefined, direction); } catch (error) { this.debug.log(`Could not read files from module ${moduleId}: ${error.message}`); return []; } } } exports.PatternResolver = PatternResolver; PatternResolver.MODULE_PATTERN = /^(\d{1,4})_(.+)$/; PatternResolver.MIGRATION_PATTERN = /^(\d{4})_(.+?)_(up|down)\.surql$/; //# sourceMappingURL=pattern-resolver.js.map