supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
847 lines • 38.3 kB
JavaScript
"use strict";
/**
* Architecture Detection Engine for Epic 2: Smart Platform Detection Engine
* Main engine for detecting platform architecture (individual/team/hybrid) with confidence scoring
* Part of Task 2.1.3: Implement main architecture detection engine with confidence scoring
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArchitectureDetectionEngine = void 0;
const logger_1 = require("../../core/utils/logger");
const pattern_analyzers_1 = require("./pattern-analyzers");
/**
* Main Architecture Detection Engine
* Orchestrates the complete platform architecture detection process
*/
class ArchitectureDetectionEngine {
constructor() {
this.detectionCache = new Map();
this.statistics = {
totalDetections: 0,
resultsByArchitecture: { individual: 0, team: 0, hybrid: 0 },
averageDetectionTime: 0,
averageConfidence: 0,
cacheHitRate: 0,
commonEvidenceTypes: {
table_pattern: 0,
column_analysis: 0,
relationship_pattern: 0,
constraint_pattern: 0,
function_analysis: 0,
naming_convention: 0,
data_pattern: 0,
business_logic: 0
},
errorRates: {},
performanceMetrics: {
fastestDetection: Infinity,
slowestDetection: 0,
memoryUsage: 0
}
};
this.patternOrchestrator = new pattern_analyzers_1.PatternAnalysisOrchestrator();
}
/**
* Detect platform architecture from database schema
*/
async detectArchitecture(context, config = {}) {
const startTime = Date.now();
// Merge config with defaults
const detectionConfig = this.mergeWithDefaults(config);
logger_1.Logger.info(`Starting architecture detection with strategy: ${detectionConfig.strategy}`);
try {
// Check cache if enabled
if (detectionConfig.useCaching) {
const cached = this.getCachedResult(context, detectionConfig);
if (cached) {
this.statistics.totalDetections++;
return cached;
}
}
// Handle manual overrides first
if (detectionConfig.manualOverrides?.architectureType) {
const overrideResult = await this.handleManualOverride(context, detectionConfig);
if (overrideResult) {
this.updateStatistics(overrideResult, startTime);
return overrideResult;
}
}
// Execute detection based on strategy
const result = await this.executeDetectionStrategy(context, detectionConfig, startTime);
// Cache result if enabled
if (detectionConfig.useCaching) {
this.cacheResult(context, detectionConfig, result);
}
this.updateStatistics(result, startTime);
logger_1.Logger.info(`Architecture detection completed: ${result.architectureType} (confidence: ${result.confidence.toFixed(3)})`);
return result;
}
catch (error) {
logger_1.Logger.error('Architecture detection failed:', error);
// Return fallback result
const fallbackResult = this.createFallbackResult(context, error, startTime);
this.updateStatistics(fallbackResult, startTime);
return fallbackResult;
}
}
/**
* Execute detection based on configured strategy
*/
async executeDetectionStrategy(context, config, startTime) {
switch (config.strategy) {
case 'comprehensive':
return await this.comprehensiveDetection(context, config, startTime);
case 'fast':
return await this.fastDetection(context, config, startTime);
case 'conservative':
return await this.conservativeDetection(context, config, startTime);
case 'aggressive':
return await this.aggressiveDetection(context, config, startTime);
default:
return await this.comprehensiveDetection(context, config, startTime);
}
}
/**
* Comprehensive detection strategy - thorough analysis with maximum accuracy
*/
async comprehensiveDetection(context, config, startTime) {
logger_1.Logger.debug('Executing comprehensive detection strategy');
// Run all pattern analyses
const patternResults = await this.patternOrchestrator.analyzeAllPatterns(context);
// Collect evidence from all sources
const evidence = await this.collectComprehensiveEvidence(context, patternResults);
// Analyze platform features in depth
const platformFeatures = await this.analyzePlatformFeatures(context, patternResults);
// Calculate confidence with multiple factors
const confidenceAnalysis = this.calculateComprehensiveConfidence(patternResults, evidence, platformFeatures);
// Generate detailed reasoning
const reasoning = this.generateDetailedReasoning(patternResults, evidence, platformFeatures);
// Create alternative analysis
const alternatives = this.generateAlternatives(patternResults, confidenceAnalysis);
// Generate recommendations
const recommendations = this.generateRecommendations(confidenceAnalysis.architectureType, confidenceAnalysis.confidence, evidence, platformFeatures);
return {
architectureType: confidenceAnalysis.architectureType,
confidence: confidenceAnalysis.confidence,
confidenceLevel: this.getConfidenceLevel(confidenceAnalysis.confidence),
evidence,
platformFeatures,
detectedFeatures: platformFeatures.map(feature => feature.name),
reasoning,
alternatives,
recommendations,
detectionMetrics: {
executionTime: Date.now() - startTime,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: evidence.length,
schemaComplexity: this.calculateSchemaComplexity(context),
strategyUsed: 'comprehensive'
},
warnings: [],
errors: []
};
}
/**
* Fast detection strategy - quick analysis with good accuracy
*/
async fastDetection(context, config, startTime) {
logger_1.Logger.debug('Executing fast detection strategy');
// Use simplified pattern analysis
const patternResults = await this.patternOrchestrator.analyzeAllPatterns(context);
// Focus on high-confidence evidence only
const evidence = await this.collectHighConfidenceEvidence(context, patternResults);
// Analyze key platform features only
const platformFeatures = await this.analyzeKeyPlatformFeatures(context, patternResults);
// Quick confidence calculation
const architectureType = patternResults.summary.strongestArchitecture;
const confidence = Math.min(patternResults.summary.confidence * 0.9, 0.95); // Slightly lower for fast mode
const reasoning = [`Fast analysis identified ${architectureType} architecture based on key patterns`];
const alternatives = this.generateSimpleAlternatives(patternResults);
const recommendations = this.generateBasicRecommendations(architectureType, confidence);
return {
architectureType,
confidence,
confidenceLevel: this.getConfidenceLevel(confidence),
evidence,
platformFeatures,
detectedFeatures: platformFeatures.map(feature => feature.name),
reasoning,
alternatives,
recommendations,
detectionMetrics: {
executionTime: Date.now() - startTime,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: evidence.length,
schemaComplexity: this.calculateSchemaComplexity(context),
strategyUsed: 'fast'
},
warnings: ['Fast detection mode - some patterns may not be fully analyzed'],
errors: []
};
}
/**
* Conservative detection strategy - high precision, may classify as hybrid when uncertain
*/
async conservativeDetection(context, config, startTime) {
logger_1.Logger.debug('Executing conservative detection strategy');
const patternResults = await this.patternOrchestrator.analyzeAllPatterns(context);
const evidence = await this.collectHighConfidenceEvidence(context, patternResults);
const platformFeatures = await this.analyzePlatformFeatures(context, patternResults);
// Conservative logic: require high confidence or default to hybrid
let architectureType;
let confidence;
const individualScore = patternResults.summary.individualScore;
const teamScore = patternResults.summary.teamScore;
const hybridScore = patternResults.summary.hybridScore;
const maxScore = Math.max(individualScore, teamScore, hybridScore);
const secondMaxScore = [individualScore, teamScore, hybridScore]
.sort((a, b) => b - a)[1];
// Require significant margin to avoid hybrid classification
const margin = maxScore - secondMaxScore;
if (maxScore > 0.8 && margin > 0.3) {
architectureType = patternResults.summary.strongestArchitecture;
confidence = maxScore * 0.95; // Conservative confidence reduction
}
else {
// Default to hybrid when uncertain
architectureType = 'hybrid';
confidence = Math.max(hybridScore, 0.6); // Minimum reasonable confidence for hybrid
}
const reasoning = [
`Conservative analysis with margin threshold (${margin.toFixed(2)})`,
`Selected ${architectureType} with confidence adjustments for reliability`
];
const alternatives = this.generateAlternatives(patternResults, { architectureType, confidence });
const recommendations = this.generateRecommendations(architectureType, confidence, evidence, platformFeatures);
return {
architectureType,
confidence,
confidenceLevel: this.getConfidenceLevel(confidence),
evidence,
platformFeatures,
detectedFeatures: platformFeatures.map(feature => feature.name),
reasoning,
alternatives,
recommendations,
detectionMetrics: {
executionTime: Date.now() - startTime,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: evidence.length,
schemaComplexity: this.calculateSchemaComplexity(context),
strategyUsed: 'conservative'
},
warnings: ['Conservative mode - may classify ambiguous cases as hybrid'],
errors: []
};
}
/**
* Aggressive detection strategy - favor clear classifications, higher confidence
*/
async aggressiveDetection(context, config, startTime) {
logger_1.Logger.debug('Executing aggressive detection strategy');
const patternResults = await this.patternOrchestrator.analyzeAllPatterns(context);
const evidence = await this.collectAllEvidence(context, patternResults);
const platformFeatures = await this.analyzePlatformFeatures(context, patternResults);
// Aggressive logic: boost confidence and favor definitive classifications
const architectureType = patternResults.summary.strongestArchitecture;
const baseConfidence = patternResults.summary.confidence;
// Boost confidence for clear winners
const confidence = Math.min(baseConfidence * 1.1, 0.99);
const reasoning = [
`Aggressive analysis boosted confidence for clear ${architectureType} classification`,
`Based on ${evidence.length} evidence pieces and ${platformFeatures.length} platform features`
];
const alternatives = this.generateAlternatives(patternResults, { architectureType, confidence });
const recommendations = this.generateRecommendations(architectureType, confidence, evidence, platformFeatures);
return {
architectureType,
confidence,
confidenceLevel: this.getConfidenceLevel(confidence),
evidence,
platformFeatures,
detectedFeatures: platformFeatures.map(feature => feature.name),
reasoning,
alternatives,
recommendations,
detectionMetrics: {
executionTime: Date.now() - startTime,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: evidence.length,
schemaComplexity: this.calculateSchemaComplexity(context),
strategyUsed: 'aggressive'
},
warnings: ['Aggressive mode - confidence may be optimistically high'],
errors: []
};
}
/**
* Collect comprehensive evidence from all analysis sources
*/
async collectComprehensiveEvidence(context, patternResults) {
const evidence = [];
// Evidence from pattern matching
for (const category of ['individual', 'team', 'hybrid']) {
const results = patternResults[category] || [];
for (const result of results) {
if (result.matched && result.matchConfidence > 0.3) {
evidence.push({
type: 'table_pattern',
description: `${result.pattern.name}: ${result.architectureIndication.reasoning}`,
confidence: result.matchConfidence,
weight: result.pattern.confidenceWeight,
supportingData: {
tables: result.matchDetails.matchedTables,
columns: result.matchDetails.matchedColumns,
constraints: result.matchDetails.matchedConstraints,
patterns: [result.pattern.id],
samples: []
},
architectureIndicators: {
individual: category === 'individual' ? result.matchConfidence : 0,
team: category === 'team' ? result.matchConfidence : 0,
hybrid: category === 'hybrid' ? result.matchConfidence : 0
}
});
}
}
}
// Evidence from schema structure
const structuralEvidence = await this.collectStructuralEvidence(context);
evidence.push(...structuralEvidence);
// Evidence from relationships
const relationshipEvidence = await this.collectRelationshipEvidence(context);
evidence.push(...relationshipEvidence);
// Evidence from constraints
const constraintEvidence = await this.collectConstraintEvidence(context);
evidence.push(...constraintEvidence);
return evidence.sort((a, b) => (b.confidence * b.weight) - (a.confidence * a.weight));
}
/**
* Collect structural evidence from schema analysis
*/
async collectStructuralEvidence(context) {
const evidence = [];
// Table count and complexity analysis
const tableCount = context.schema.tableCount;
const relationshipCount = context.schema.relationships.length;
const constraintCount = context.schema.constraints.length;
// Individual platforms tend to be simpler
if (tableCount <= 10 && relationshipCount <= 15) {
evidence.push({
type: 'data_pattern',
description: `Simple schema structure (${tableCount} tables, ${relationshipCount} relationships)`,
confidence: 0.7,
weight: 0.6,
supportingData: {
tables: context.schema.tableNames,
samples: [{ tableCount, relationshipCount, constraintCount }]
},
architectureIndicators: {
individual: 0.8,
team: 0.2,
hybrid: 0.4
}
});
}
// Team platforms tend to be more complex
if (tableCount >= 15 && relationshipCount >= 25) {
evidence.push({
type: 'data_pattern',
description: `Complex schema structure (${tableCount} tables, ${relationshipCount} relationships)`,
confidence: 0.8,
weight: 0.7,
supportingData: {
tables: context.schema.tableNames,
samples: [{ tableCount, relationshipCount, constraintCount }]
},
architectureIndicators: {
individual: 0.1,
team: 0.9,
hybrid: 0.6
}
});
}
return evidence;
}
/**
* Collect relationship evidence
*/
async collectRelationshipEvidence(context) {
const evidence = [];
// Analyze relationship patterns
const userRelationships = context.schema.relationships.filter(rel => ['user_id', 'owner_id', 'created_by'].includes(rel.columnName?.toLowerCase() || ''));
const organizationRelationships = context.schema.relationships.filter(rel => ['organization_id', 'team_id', 'workspace_id'].includes(rel.columnName?.toLowerCase() || ''));
// Strong user-centric relationships indicate individual platform
if (userRelationships.length > organizationRelationships.length * 2) {
evidence.push({
type: 'relationship_pattern',
description: `Strong user-centric relationships (${userRelationships.length} user vs ${organizationRelationships.length} org)`,
confidence: 0.8,
weight: 0.8,
supportingData: {
patterns: userRelationships.map(rel => `${rel.fromTable}->${rel.toTable}`)
},
architectureIndicators: {
individual: 0.9,
team: 0.1,
hybrid: 0.3
}
});
}
// Strong organization-centric relationships indicate team platform
if (organizationRelationships.length > userRelationships.length) {
evidence.push({
type: 'relationship_pattern',
description: `Strong organization-centric relationships (${organizationRelationships.length} org vs ${userRelationships.length} user)`,
confidence: 0.8,
weight: 0.8,
supportingData: {
patterns: organizationRelationships.map(rel => `${rel.fromTable}->${rel.toTable}`)
},
architectureIndicators: {
individual: 0.1,
team: 0.9,
hybrid: 0.4
}
});
}
// Balanced relationships indicate hybrid platform
const ratio = userRelationships.length / Math.max(organizationRelationships.length, 1);
if (ratio > 0.5 && ratio < 2.0 && userRelationships.length > 2 && organizationRelationships.length > 2) {
evidence.push({
type: 'relationship_pattern',
description: `Balanced user/organization relationships (ratio: ${ratio.toFixed(2)})`,
confidence: 0.7,
weight: 0.9,
supportingData: {
patterns: [...userRelationships, ...organizationRelationships].map(rel => `${rel.fromTable}->${rel.toTable}`)
},
architectureIndicators: {
individual: 0.3,
team: 0.3,
hybrid: 0.8
}
});
}
return evidence;
}
/**
* Collect constraint evidence
*/
async collectConstraintEvidence(context) {
const evidence = [];
// MakerKit personal account constraints indicate hybrid capability
const personalAccountConstraints = context.schema.constraints.filter(constraint => constraint.constraintName?.toLowerCase().includes('personal_account') ||
constraint.constraintName?.toLowerCase().includes('accounts_slug_null_if_personal'));
if (personalAccountConstraints.length > 0) {
evidence.push({
type: 'constraint_pattern',
description: `MakerKit personal account constraints detected (${personalAccountConstraints.length})`,
confidence: 0.9,
weight: 0.8,
supportingData: {
constraints: personalAccountConstraints.map(c => c.constraintName)
},
architectureIndicators: {
individual: 0.4,
team: 0.4,
hybrid: 0.9
}
});
}
return evidence;
}
/**
* Collect high-confidence evidence only (for fast/conservative modes)
*/
async collectHighConfidenceEvidence(context, patternResults) {
const allEvidence = await this.collectComprehensiveEvidence(context, patternResults);
return allEvidence.filter(evidence => evidence.confidence >= 0.7);
}
/**
* Collect all available evidence (for aggressive mode)
*/
async collectAllEvidence(context, patternResults) {
return await this.collectComprehensiveEvidence(context, patternResults);
}
/**
* Analyze platform features in depth
*/
async analyzePlatformFeatures(context, patternResults) {
const features = [];
// Authentication features
if (context.schema.tableNames.some(table => ['users', 'auth', 'authentication'].some(pattern => table.toLowerCase().includes(pattern)))) {
features.push({
id: 'authentication',
name: 'User Authentication',
category: 'authentication',
present: true,
confidence: 0.9,
evidence: ['Users/auth tables detected'],
implementingTables: context.schema.tableNames.filter(table => ['users', 'auth'].some(pattern => table.toLowerCase().includes(pattern))),
typicallyIndicates: ['individual', 'team', 'hybrid'],
commonInDomains: ['outdoor', 'saas', 'ecommerce', 'social']
});
}
// Organization features
if (context.schema.tableNames.some(table => ['organizations', 'teams', 'workspaces'].some(pattern => table.toLowerCase().includes(pattern)))) {
features.push({
id: 'organizations',
name: 'Organization Management',
category: 'organization',
present: true,
confidence: 0.95,
evidence: ['Organization/team tables detected'],
implementingTables: context.schema.tableNames.filter(table => ['organizations', 'teams', 'workspaces'].some(pattern => table.toLowerCase().includes(pattern))),
typicallyIndicates: ['team', 'hybrid'],
commonInDomains: ['saas', 'ecommerce']
});
}
// Content creation features
const contentTables = context.schema.tableNames.filter(table => ['posts', 'articles', 'content', 'media', 'projects'].some(pattern => table.toLowerCase().includes(pattern)));
if (contentTables.length > 0) {
features.push({
id: 'content_creation',
name: 'Content Creation',
category: 'content_creation',
present: true,
confidence: 0.8,
evidence: [`${contentTables.length} content-related tables`],
implementingTables: contentTables,
typicallyIndicates: ['individual', 'hybrid'],
commonInDomains: ['outdoor', 'social']
});
}
return features;
}
/**
* Analyze key platform features only (for fast mode)
*/
async analyzeKeyPlatformFeatures(context, patternResults) {
const allFeatures = await this.analyzePlatformFeatures(context, patternResults);
return allFeatures.filter(feature => ['authentication', 'organizations', 'content_creation'].includes(feature.id));
}
/**
* Calculate comprehensive confidence score
*/
calculateComprehensiveConfidence(patternResults, evidence, platformFeatures) {
const scores = {
individual: 0,
team: 0,
hybrid: 0
};
// Weight evidence by confidence and weight
for (const item of evidence) {
const effectiveWeight = item.confidence * item.weight;
scores.individual += item.architectureIndicators.individual * effectiveWeight;
scores.team += item.architectureIndicators.team * effectiveWeight;
scores.hybrid += item.architectureIndicators.hybrid * effectiveWeight;
}
// Normalize scores
const totalWeight = evidence.reduce((sum, item) => sum + (item.confidence * item.weight), 0);
if (totalWeight > 0) {
scores.individual /= totalWeight;
scores.team /= totalWeight;
scores.hybrid /= totalWeight;
}
// Find highest scoring architecture
const architectureTypes = ['individual', 'team', 'hybrid'];
const sortedArchitectures = architectureTypes.sort((a, b) => scores[b] - scores[a]);
const architectureType = sortedArchitectures[0];
const confidence = scores[architectureType];
return { architectureType, confidence };
}
/**
* Generate detailed reasoning for the detection
*/
generateDetailedReasoning(patternResults, evidence, platformFeatures) {
const reasoning = [];
// Pattern analysis summary
reasoning.push(`Pattern analysis: individual=${patternResults.summary.individualScore.toFixed(2)}, team=${patternResults.summary.teamScore.toFixed(2)}, hybrid=${patternResults.summary.hybridScore.toFixed(2)}`);
// Key evidence summary
const topEvidence = evidence.slice(0, 3);
if (topEvidence.length > 0) {
reasoning.push(`Top evidence: ${topEvidence.map(e => e.description).join('; ')}`);
}
// Platform features summary
const presentFeatures = platformFeatures.filter(f => f.present);
if (presentFeatures.length > 0) {
reasoning.push(`Platform features: ${presentFeatures.map(f => f.name).join(', ')}`);
}
return reasoning;
}
/**
* Generate alternative architecture possibilities
*/
generateAlternatives(patternResults, confidenceAnalysis) {
const alternatives = [];
const scores = [
{ type: 'individual', score: patternResults.summary.individualScore },
{ type: 'team', score: patternResults.summary.teamScore },
{ type: 'hybrid', score: patternResults.summary.hybridScore }
];
// Sort by score and exclude the primary result
scores
.filter(s => s.type !== confidenceAnalysis.architectureType)
.sort((a, b) => b.score - a.score)
.forEach(alt => {
if (alt.score > 0.2) { // Only include reasonable alternatives
alternatives.push({
architectureType: alt.type,
confidence: alt.score,
reasoning: `Alternative based on ${alt.type} pattern analysis`
});
}
});
return alternatives;
}
/**
* Generate simple alternatives (for fast mode)
*/
generateSimpleAlternatives(patternResults) {
const scores = [
{ type: 'individual', score: patternResults.summary.individualScore },
{ type: 'team', score: patternResults.summary.teamScore },
{ type: 'hybrid', score: patternResults.summary.hybridScore }
];
return scores
.sort((a, b) => b.score - a.score)
.slice(1, 2) // Just the second-best option
.map(alt => ({
architectureType: alt.type,
confidence: alt.score,
reasoning: `Secondary option from pattern analysis`
}));
}
/**
* Generate recommendations based on detection results
*/
generateRecommendations(architectureType, confidence, evidence, platformFeatures) {
const recommendations = [];
// Confidence-based recommendations
if (confidence < 0.6) {
recommendations.push('Low confidence detection - consider manual verification');
recommendations.push('Review schema patterns and add more distinguishing features');
}
else if (confidence > 0.9) {
recommendations.push('High confidence detection - proceed with detected architecture');
}
// Architecture-specific recommendations
switch (architectureType) {
case 'individual':
recommendations.push('Configure individual creator user archetypes');
recommendations.push('Use content-focused seeding patterns');
break;
case 'team':
recommendations.push('Configure team collaboration features');
recommendations.push('Use organization-based seeding patterns');
break;
case 'hybrid':
recommendations.push('Configure flexible user archetypes for both individual and team use');
recommendations.push('Use adaptive seeding patterns based on account type');
break;
}
// Feature-based recommendations
const missingFeatures = platformFeatures.filter(f => !f.present);
if (missingFeatures.length > 0) {
recommendations.push(`Consider adding: ${missingFeatures.map(f => f.name).join(', ')}`);
}
return recommendations;
}
/**
* Generate basic recommendations (for fast mode)
*/
generateBasicRecommendations(architectureType, confidence) {
const recommendations = [];
if (confidence < 0.7) {
recommendations.push('Consider manual verification due to moderate confidence');
}
recommendations.push(`Proceed with ${architectureType} architecture configuration`);
return recommendations;
}
/**
* Get confidence level from numeric confidence
*/
getConfidenceLevel(confidence) {
if (confidence >= 0.9)
return 'very_high';
if (confidence >= 0.7)
return 'high';
if (confidence >= 0.5)
return 'medium';
if (confidence >= 0.3)
return 'low';
return 'very_low';
}
/**
* Calculate schema complexity score
*/
calculateSchemaComplexity(context) {
const tableCount = context.schema.tableCount;
const relationshipCount = context.schema.relationships.length;
const constraintCount = context.schema.constraints.length;
// Normalize to 0-1 scale
const tableComplexity = Math.min(tableCount / 50, 1);
const relationshipComplexity = Math.min(relationshipCount / 100, 1);
const constraintComplexity = Math.min(constraintCount / 50, 1);
return (tableComplexity + relationshipComplexity + constraintComplexity) / 3;
}
/**
* Handle manual override
*/
async handleManualOverride(context, config) {
const override = config.manualOverrides;
if (!override?.architectureType)
return null;
logger_1.Logger.info(`Processing manual override: ${override.architectureType}`);
// Validate override against detected patterns
const validation = await this.validateOverride(context, override);
// Create basic result for override
const result = {
architectureType: override.architectureType,
confidence: 0.95, // High confidence for manual override
confidenceLevel: 'very_high',
evidence: override.customEvidence || [],
platformFeatures: [],
detectedFeatures: [],
reasoning: ['Manual override specified', `Architecture forced to: ${override.architectureType}`],
alternatives: [],
recommendations: validation.recommendations,
detectionMetrics: {
executionTime: 0,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: override.customEvidence?.length || 0,
schemaComplexity: this.calculateSchemaComplexity(context),
strategyUsed: config.strategy
},
warnings: validation.warnings,
errors: []
};
// Add conflicts as warnings
result.warnings.push(...validation.conflicts.map(c => `Override conflict (${c.severity}): ${c.description}`));
return result;
}
/**
* Validate manual override against detected patterns
*/
async validateOverride(context, override) {
// For now, simple validation - could be enhanced
return {
isValid: true,
warnings: ['Manual override in effect - automatic detection bypassed'],
conflicts: [],
recommendations: ['Verify that the manual override matches your intended architecture']
};
}
/**
* Create fallback result for errors
*/
createFallbackResult(context, error, startTime) {
return {
architectureType: 'hybrid', // Safe fallback
confidence: 0.5,
confidenceLevel: 'medium',
evidence: [],
platformFeatures: [],
detectedFeatures: [],
reasoning: ['Detection failed, using fallback hybrid classification'],
alternatives: [],
recommendations: ['Manual architecture verification recommended due to detection failure'],
detectionMetrics: {
executionTime: Date.now() - startTime,
tablesAnalyzed: context.schema.tableCount,
evidenceCount: 0,
schemaComplexity: 0,
strategyUsed: 'comprehensive'
},
warnings: ['Detection process encountered errors'],
errors: [error.message]
};
}
/**
* Merge config with defaults
*/
mergeWithDefaults(config) {
return {
strategy: 'comprehensive',
confidenceThreshold: 0.7,
includeDetailedEvidence: true,
analyzeBusinessLogic: true,
analyzeRLSPolicies: true,
deepRelationshipAnalysis: true,
excludeTables: [],
maxExecutionTime: 30000, // 30 seconds
useCaching: true,
...config
};
}
/**
* Cache management methods
*/
getCachedResult(context, config) {
const schemaHash = this.generateSchemaHash(context);
const cached = this.detectionCache.get(schemaHash);
if (cached && cached.timestamp + cached.ttl > Date.now()) {
logger_1.Logger.debug('Using cached detection result');
this.statistics.cacheHitRate = (this.statistics.cacheHitRate * this.statistics.totalDetections + 1) / (this.statistics.totalDetections + 1);
return cached.result;
}
return null;
}
cacheResult(context, config, result) {
const schemaHash = this.generateSchemaHash(context);
this.detectionCache.set(schemaHash, {
schemaHash,
result,
timestamp: Date.now(),
config,
ttl: 60000 // 1 minute TTL
});
}
generateSchemaHash(context) {
const hashData = {
tableNames: context.schema.tableNames.sort(),
relationshipCount: context.schema.relationships.length,
constraintCount: context.schema.constraints.length
};
return Buffer.from(JSON.stringify(hashData)).toString('base64');
}
/**
* Update detection statistics
*/
updateStatistics(result, startTime) {
this.statistics.totalDetections++;
this.statistics.resultsByArchitecture[result.architectureType]++;
const executionTime = Date.now() - startTime;
this.statistics.averageDetectionTime =
(this.statistics.averageDetectionTime * (this.statistics.totalDetections - 1) + executionTime) /
this.statistics.totalDetections;
this.statistics.averageConfidence =
(this.statistics.averageConfidence * (this.statistics.totalDetections - 1) + result.confidence) /
this.statistics.totalDetections;
// Update performance metrics
this.statistics.performanceMetrics.fastestDetection =
Math.min(this.statistics.performanceMetrics.fastestDetection, executionTime);
this.statistics.performanceMetrics.slowestDetection =
Math.max(this.statistics.performanceMetrics.slowestDetection, executionTime);
// Update evidence type statistics
for (const evidence of result.evidence) {
this.statistics.commonEvidenceTypes[evidence.type]++;
}
}
/**
* Get detection statistics
*/
getStatistics() {
return { ...this.statistics };
}
/**
* Clear detection cache
*/
clearCache() {
this.detectionCache.clear();
logger_1.Logger.debug('Detection cache cleared');
}
}
exports.ArchitectureDetectionEngine = ArchitectureDetectionEngine;
exports.default = ArchitectureDetectionEngine;
//# sourceMappingURL=architecture-detector.js.map