supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
857 lines • 40 kB
JavaScript
;
/**
* Pattern Analyzers for Epic 2: Smart Platform Detection Engine
* Advanced pattern recognition for individual/team/hybrid platform architecture detection
* Part of Task 2.1.2: Create pattern analyzers for individual/team/hybrid recognition
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PatternAnalysisOrchestrator = exports.HybridPlatformAnalyzer = exports.TeamPlatformAnalyzer = exports.IndividualPlatformAnalyzer = void 0;
const logger_1 = require("../../core/utils/logger");
/**
* Individual Platform Pattern Analyzer
* Detects patterns indicating individual creator/user-centric platforms
*/
class IndividualPlatformAnalyzer {
constructor() {
this.indicators = {
userCentricTables: [
'users', 'profiles', 'user_profiles', 'accounts', 'personal_accounts'
],
contentFocusedTables: [
'posts', 'articles', 'content', 'media', 'images', 'videos', 'galleries',
'projects', 'portfolios', 'creations', 'works', 'pieces'
],
simpleAccountPatterns: [
'is_personal_account', 'account_type', 'user_type', 'profile_type'
],
limitedCollaboration: [
'followers', 'following', 'likes', 'favorites', 'bookmarks', 'comments'
],
personalProfilePatterns: [
'bio', 'about', 'description', 'avatar', 'profile_picture', 'banner',
'social_links', 'website', 'location', 'skills', 'interests'
]
};
}
/**
* Analyze schema for individual platform patterns
*/
async analyzeIndividualPatterns(context) {
const results = [];
// Pattern 1: User-centric content creation
results.push(await this.analyzeUserCentricPattern(context));
// Pattern 2: Simple account structure
results.push(await this.analyzeSimpleAccountPattern(context));
// Pattern 3: Personal profile emphasis
results.push(await this.analyzePersonalProfilePattern(context));
// Pattern 4: Limited collaboration features
results.push(await this.analyzeLimitedCollaborationPattern(context));
// Pattern 5: Direct user-content ownership
results.push(await this.analyzeDirectOwnershipPattern(context));
return results.filter(result => result.matched);
}
/**
* Analyze user-centric content creation pattern
*/
async analyzeUserCentricPattern(context) {
const pattern = {
id: 'individual_user_centric',
name: 'User-Centric Content Creation',
description: 'Content tables directly linked to individual users without team structures',
indicatesArchitecture: ['individual'],
confidenceWeight: 0.8,
tablePatterns: this.indicators.userCentricTables,
columnPatterns: ['user_id', 'author_id', 'creator_id', 'owner_id'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 2,
exclusive: false
};
const matchedTables = context.schema.tableNames.filter(table => this.indicators.userCentricTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const contentTables = context.schema.tableNames.filter(table => this.indicators.contentFocusedTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
// Check for direct user-content relationships
const userContentRelationships = context.schema.relationships.filter(rel => matchedTables.some(userTable => rel.fromTable === userTable) &&
contentTables.some(contentTable => rel.toTable === contentTable));
const matched = matchedTables.length >= 1 && contentTables.length >= 1;
const matchConfidence = Math.min((matchedTables.length * 0.3 + contentTables.length * 0.4 + userContentRelationships.length * 0.3), 1.0);
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: [...matchedTables, ...contentTables],
matchedColumns: ['user_id', 'author_id', 'creator_id'],
matchedConstraints: [],
matchedRelationships: userContentRelationships.map(rel => `${rel.fromTable}->${rel.toTable}`),
matchedFunctions: []
},
architectureIndication: {
type: 'individual',
confidence: matchConfidence,
reasoning: `Found ${matchedTables.length} user tables and ${contentTables.length} content tables with direct relationships`
}
};
}
/**
* Analyze simple account structure pattern
*/
async analyzeSimpleAccountPattern(context) {
const pattern = {
id: 'individual_simple_accounts',
name: 'Simple Account Structure',
description: 'Simple account structures without complex team/organization hierarchies',
indicatesArchitecture: ['individual'],
confidenceWeight: 0.7,
tablePatterns: ['accounts', 'users', 'profiles'],
columnPatterns: this.indicators.simpleAccountPatterns,
constraintPatterns: ['accounts_slug_null_if_personal_account_true'],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const accountTables = context.schema.tableNames.filter(table => ['accounts', 'users', 'profiles'].some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
// Check for personal account indicators in constraints
const personalAccountConstraints = context.schema.constraints.filter(constraint => constraint.constraintName?.toLowerCase().includes('personal_account') ||
constraint.constraintName?.toLowerCase().includes('is_personal'));
// Look for absence of complex team structures
const teamTables = context.schema.tableNames.filter(table => ['organizations', 'teams', 'workspaces', 'groups'].some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = accountTables.length >= 1 && teamTables.length <= 1;
const matchConfidence = accountTables.length > 0 ?
Math.max(0.6 - (teamTables.length * 0.2), 0.1) + (personalAccountConstraints.length * 0.3) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: accountTables,
matchedColumns: this.indicators.simpleAccountPatterns,
matchedConstraints: personalAccountConstraints.map(c => c.constraintName),
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'individual',
confidence: matchConfidence,
reasoning: `Simple account structure detected with ${accountTables.length} account tables and minimal team infrastructure`
}
};
}
/**
* Analyze personal profile emphasis pattern
*/
async analyzePersonalProfilePattern(context) {
const pattern = {
id: 'individual_personal_profile',
name: 'Personal Profile Emphasis',
description: 'Rich personal profile features indicating individual-focused platform',
indicatesArchitecture: ['individual'],
confidenceWeight: 0.6,
tablePatterns: ['profiles', 'user_profiles', 'personal_info'],
columnPatterns: this.indicators.personalProfilePatterns,
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 3,
exclusive: false
};
const profileTables = context.schema.tableNames.filter(table => table.toLowerCase().includes('profile'));
// This would require column-level analysis which we'll simulate
const personalProfileFeatures = this.indicators.personalProfilePatterns.length;
const estimatedMatches = Math.floor(personalProfileFeatures * 0.6); // Simulate typical coverage
const matched = profileTables.length >= 1 && estimatedMatches >= pattern.minimumMatches;
const matchConfidence = profileTables.length > 0 ?
Math.min((profileTables.length * 0.4) + (estimatedMatches / personalProfileFeatures * 0.6), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: profileTables,
matchedColumns: this.indicators.personalProfilePatterns.slice(0, estimatedMatches),
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'individual',
confidence: matchConfidence,
reasoning: `Rich personal profile features detected in ${profileTables.length} profile tables`
}
};
}
/**
* Analyze limited collaboration pattern
*/
async analyzeLimitedCollaborationPattern(context) {
const pattern = {
id: 'individual_limited_collaboration',
name: 'Limited Collaboration Features',
description: 'Simple social features without complex team collaboration',
indicatesArchitecture: ['individual'],
confidenceWeight: 0.5,
tablePatterns: this.indicators.limitedCollaboration,
columnPatterns: ['follower_id', 'following_id', 'user_id'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const socialTables = context.schema.tableNames.filter(table => this.indicators.limitedCollaboration.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
// Check for absence of complex collaboration tables
const complexCollabTables = context.schema.tableNames.filter(table => ['workspaces', 'projects', 'teams', 'channels', 'rooms'].some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = socialTables.length >= 1 && complexCollabTables.length === 0;
const matchConfidence = socialTables.length > 0 ?
Math.min((socialTables.length * 0.3) + (complexCollabTables.length === 0 ? 0.7 : 0), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: socialTables,
matchedColumns: ['follower_id', 'following_id', 'user_id'],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'individual',
confidence: matchConfidence,
reasoning: `Simple social features without complex collaboration infrastructure`
}
};
}
/**
* Analyze direct ownership pattern
*/
async analyzeDirectOwnershipPattern(context) {
const pattern = {
id: 'individual_direct_ownership',
name: 'Direct User-Content Ownership',
description: 'Direct ownership relationships without team/organization mediation',
indicatesArchitecture: ['individual'],
confidenceWeight: 0.9,
tablePatterns: [],
columnPatterns: ['user_id', 'owner_id', 'creator_id', 'author_id'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 2,
exclusive: false
};
// Count direct user-content relationships
const directRelationships = context.schema.relationships.filter(rel => ['user_id', 'owner_id', 'creator_id', 'author_id'].includes(rel.columnName?.toLowerCase() || ''));
// Look for mediated relationships through organizations/teams
const mediatedRelationships = context.schema.relationships.filter(rel => ['organization_id', 'team_id', 'workspace_id', 'group_id'].includes(rel.columnName?.toLowerCase() || ''));
const directToMediatedRatio = mediatedRelationships.length === 0 ?
1.0 : directRelationships.length / (directRelationships.length + mediatedRelationships.length);
const matched = directRelationships.length >= pattern.minimumMatches && directToMediatedRatio > 0.7;
const matchConfidence = matched ?
Math.min((directRelationships.length * 0.2) + (directToMediatedRatio * 0.8), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: [],
matchedColumns: directRelationships.map(rel => rel.columnName).filter(Boolean),
matchedConstraints: [],
matchedRelationships: directRelationships.map(rel => `${rel.fromTable}->${rel.toTable}`),
matchedFunctions: []
},
architectureIndication: {
type: 'individual',
confidence: matchConfidence,
reasoning: `Direct ownership pattern with ${directRelationships.length} direct relationships vs ${mediatedRelationships.length} mediated`
}
};
}
}
exports.IndividualPlatformAnalyzer = IndividualPlatformAnalyzer;
/**
* Team Platform Pattern Analyzer
* Detects patterns indicating team collaboration platforms
*/
class TeamPlatformAnalyzer {
constructor() {
this.indicators = {
teamOrganizationTables: [
'organizations', 'teams', 'companies', 'workspaces', 'groups'
],
memberManagementTables: [
'members', 'team_members', 'organization_members', 'workspace_members',
'user_organizations', 'user_teams', 'memberships'
],
workspaceProjectTables: [
'workspaces', 'projects', 'channels', 'rooms', 'boards', 'tasks'
],
permissionSystemTables: [
'roles', 'permissions', 'user_roles', 'role_permissions', 'access_controls'
],
collaborationTables: [
'invitations', 'invites', 'collaborations', 'shared_resources', 'discussions'
],
roleHierarchyPatterns: [
'owner', 'admin', 'member', 'viewer', 'is_owner', 'role', 'permission_level'
]
};
}
/**
* Analyze schema for team platform patterns
*/
async analyzeTeamPatterns(context) {
const results = [];
// Pattern 1: Organization/team structure
results.push(await this.analyzeOrganizationStructurePattern(context));
// Pattern 2: Member management system
results.push(await this.analyzeMemberManagementPattern(context));
// Pattern 3: Workspace/project collaboration
results.push(await this.analyzeWorkspaceCollaborationPattern(context));
// Pattern 4: Complex permission system
results.push(await this.analyzePermissionSystemPattern(context));
// Pattern 5: Role hierarchy
results.push(await this.analyzeRoleHierarchyPattern(context));
return results.filter(result => result.matched);
}
/**
* Analyze organization structure pattern
*/
async analyzeOrganizationStructurePattern(context) {
const pattern = {
id: 'team_organization_structure',
name: 'Organization/Team Structure',
description: 'Dedicated tables for organizations, teams, or workspaces',
indicatesArchitecture: ['team'],
confidenceWeight: 0.9,
tablePatterns: this.indicators.teamOrganizationTables,
columnPatterns: ['organization_id', 'team_id', 'workspace_id'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const orgTables = context.schema.tableNames.filter(table => this.indicators.teamOrganizationTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
// Check for organization-scoped relationships
const orgRelationships = context.schema.relationships.filter(rel => ['organization_id', 'team_id', 'workspace_id'].includes(rel.columnName?.toLowerCase() || ''));
const matched = orgTables.length >= 1;
const matchConfidence = matched ?
Math.min((orgTables.length * 0.4) + (orgRelationships.length * 0.1), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: orgTables,
matchedColumns: ['organization_id', 'team_id', 'workspace_id'],
matchedConstraints: [],
matchedRelationships: orgRelationships.map(rel => `${rel.fromTable}->${rel.toTable}`),
matchedFunctions: []
},
architectureIndication: {
type: 'team',
confidence: matchConfidence,
reasoning: `Organization structure detected with ${orgTables.length} org tables and ${orgRelationships.length} org relationships`
}
};
}
/**
* Analyze member management pattern
*/
async analyzeMemberManagementPattern(context) {
const pattern = {
id: 'team_member_management',
name: 'Member Management System',
description: 'Dedicated member management with roles and permissions',
indicatesArchitecture: ['team'],
confidenceWeight: 0.8,
tablePatterns: this.indicators.memberManagementTables,
columnPatterns: ['user_id', 'organization_id', 'role', 'is_owner'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const memberTables = context.schema.tableNames.filter(table => this.indicators.memberManagementTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
// Check for member-related constraints
const memberConstraints = context.schema.constraints.filter(constraint => constraint.constraintName?.toLowerCase().includes('member') ||
constraint.constraintName?.toLowerCase().includes('organization_member') ||
constraint.constraintName?.toLowerCase().includes('unique'));
const matched = memberTables.length >= 1;
const matchConfidence = matched ?
Math.min((memberTables.length * 0.5) + (memberConstraints.length * 0.2), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: memberTables,
matchedColumns: ['user_id', 'organization_id', 'role', 'is_owner'],
matchedConstraints: memberConstraints.map(c => c.constraintName),
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'team',
confidence: matchConfidence,
reasoning: `Member management system with ${memberTables.length} member tables and ${memberConstraints.length} related constraints`
}
};
}
/**
* Analyze workspace collaboration pattern
*/
async analyzeWorkspaceCollaborationPattern(context) {
const pattern = {
id: 'team_workspace_collaboration',
name: 'Workspace/Project Collaboration',
description: 'Collaborative workspaces, projects, or shared resources',
indicatesArchitecture: ['team'],
confidenceWeight: 0.7,
tablePatterns: this.indicators.workspaceProjectTables,
columnPatterns: ['workspace_id', 'project_id', 'shared_with'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const workspaceTables = context.schema.tableNames.filter(table => this.indicators.workspaceProjectTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const collaborationTables = context.schema.tableNames.filter(table => this.indicators.collaborationTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = workspaceTables.length >= 1 || collaborationTables.length >= 1;
const matchConfidence = matched ?
Math.min((workspaceTables.length * 0.4) + (collaborationTables.length * 0.3), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: [...workspaceTables, ...collaborationTables],
matchedColumns: ['workspace_id', 'project_id', 'shared_with'],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'team',
confidence: matchConfidence,
reasoning: `Collaboration features with ${workspaceTables.length} workspace tables and ${collaborationTables.length} collaboration tables`
}
};
}
/**
* Analyze permission system pattern
*/
async analyzePermissionSystemPattern(context) {
const pattern = {
id: 'team_permission_system',
name: 'Complex Permission System',
description: 'Sophisticated role-based access control system',
indicatesArchitecture: ['team'],
confidenceWeight: 0.8,
tablePatterns: this.indicators.permissionSystemTables,
columnPatterns: ['role_id', 'permission_id', 'access_level'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const permissionTables = context.schema.tableNames.filter(table => this.indicators.permissionSystemTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = permissionTables.length >= 1;
const matchConfidence = matched ?
Math.min(permissionTables.length * 0.6, 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: permissionTables,
matchedColumns: ['role_id', 'permission_id', 'access_level'],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'team',
confidence: matchConfidence,
reasoning: `Complex permission system with ${permissionTables.length} permission-related tables`
}
};
}
/**
* Analyze role hierarchy pattern
*/
async analyzeRoleHierarchyPattern(context) {
const pattern = {
id: 'team_role_hierarchy',
name: 'Role Hierarchy System',
description: 'Hierarchical role system with different permission levels',
indicatesArchitecture: ['team'],
confidenceWeight: 0.6,
tablePatterns: [],
columnPatterns: this.indicators.roleHierarchyPatterns,
constraintPatterns: ['role', 'permission', 'access'],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 2,
exclusive: false
};
// Check for role-related constraints
const roleConstraints = context.schema.constraints.filter(constraint => this.indicators.roleHierarchyPatterns.some(pattern => constraint.constraintName?.toLowerCase().includes(pattern.toLowerCase())));
const matched = roleConstraints.length >= pattern.minimumMatches;
const matchConfidence = matched ?
Math.min(roleConstraints.length * 0.3, 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: [],
matchedColumns: this.indicators.roleHierarchyPatterns.slice(0, roleConstraints.length),
matchedConstraints: roleConstraints.map(c => c.constraintName),
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'team',
confidence: matchConfidence,
reasoning: `Role hierarchy detected with ${roleConstraints.length} role-related constraints`
}
};
}
}
exports.TeamPlatformAnalyzer = TeamPlatformAnalyzer;
/**
* Hybrid Platform Pattern Analyzer
* Detects patterns indicating hybrid individual/team platforms
*/
class HybridPlatformAnalyzer {
constructor() {
this.indicators = {
flexibleAccountTables: [
'accounts', 'user_accounts', 'flexible_accounts', 'multi_accounts'
],
mixedOwnershipPatterns: [
'personal_', 'team_', 'shared_', 'organization_', 'individual_'
],
scalablePermissionTables: [
'access_controls', 'permissions', 'scoped_permissions', 'contextual_permissions'
],
dualCapabilityTables: [
'workspaces', 'projects', 'content', 'resources', 'items'
],
contextSwitchingPatterns: [
'context', 'scope', 'mode', 'view_as', 'acting_as'
]
};
}
/**
* Analyze schema for hybrid platform patterns
*/
async analyzeHybridPatterns(context) {
const results = [];
// Pattern 1: Flexible account system
results.push(await this.analyzeFlexibleAccountPattern(context));
// Pattern 2: Mixed ownership models
results.push(await this.analyzeMixedOwnershipPattern(context));
// Pattern 3: Context-aware permissions
results.push(await this.analyzeContextAwarePermissionsPattern(context));
// Pattern 4: Dual capability features
results.push(await this.analyzeDualCapabilityPattern(context));
// Pattern 5: Both individual and team features present
results.push(await this.analyzeCoexistingFeaturesPattern(context));
return results.filter(result => result.matched);
}
/**
* Analyze flexible account pattern
*/
async analyzeFlexibleAccountPattern(context) {
const pattern = {
id: 'hybrid_flexible_accounts',
name: 'Flexible Account System',
description: 'Account system supporting both individual and team usage',
indicatesArchitecture: ['hybrid'],
confidenceWeight: 0.8,
tablePatterns: this.indicators.flexibleAccountTables,
columnPatterns: ['is_personal_account', 'account_type', 'account_mode'],
constraintPatterns: ['accounts_slug_null_if_personal_account'],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const accountTables = context.schema.tableNames.filter(table => table.toLowerCase().includes('account'));
// Check for flexible account indicators in constraints
const flexibilityConstraints = context.schema.constraints.filter(constraint => constraint.constraintName?.toLowerCase().includes('personal_account') ||
constraint.constraintName?.toLowerCase().includes('account_type'));
const matched = accountTables.length >= 1 && flexibilityConstraints.length >= 1;
const matchConfidence = matched ?
Math.min((accountTables.length * 0.4) + (flexibilityConstraints.length * 0.6), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: accountTables,
matchedColumns: ['is_personal_account', 'account_type', 'account_mode'],
matchedConstraints: flexibilityConstraints.map(c => c.constraintName),
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'hybrid',
confidence: matchConfidence,
reasoning: `Flexible account system with ${accountTables.length} account tables and ${flexibilityConstraints.length} flexibility constraints`
}
};
}
/**
* Analyze mixed ownership pattern
*/
async analyzeMixedOwnershipPattern(context) {
const pattern = {
id: 'hybrid_mixed_ownership',
name: 'Mixed Ownership Model',
description: 'Content can be owned by individuals or teams/organizations',
indicatesArchitecture: ['hybrid'],
confidenceWeight: 0.7,
tablePatterns: [],
columnPatterns: ['user_id', 'organization_id', 'team_id', 'owner_type'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 2,
exclusive: false
};
// Check for tables with both individual and team ownership columns
const mixedOwnershipTables = context.schema.tableNames.filter(tableName => {
const tableRels = context.schema.relationships.filter(rel => rel.fromTable === tableName);
const hasUserOwnership = tableRels.some(rel => ['user_id', 'owner_id', 'created_by'].includes(rel.columnName?.toLowerCase() || ''));
const hasTeamOwnership = tableRels.some(rel => ['organization_id', 'team_id', 'workspace_id'].includes(rel.columnName?.toLowerCase() || ''));
return hasUserOwnership && hasTeamOwnership;
});
const matched = mixedOwnershipTables.length >= 1;
const matchConfidence = matched ?
Math.min(mixedOwnershipTables.length * 0.5, 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: mixedOwnershipTables,
matchedColumns: ['user_id', 'organization_id', 'team_id', 'owner_type'],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'hybrid',
confidence: matchConfidence,
reasoning: `Mixed ownership model with ${mixedOwnershipTables.length} tables supporting both individual and team ownership`
}
};
}
/**
* Analyze context-aware permissions pattern
*/
async analyzeContextAwarePermissionsPattern(context) {
const pattern = {
id: 'hybrid_context_permissions',
name: 'Context-Aware Permissions',
description: 'Permission system that adapts to individual vs team context',
indicatesArchitecture: ['hybrid'],
confidenceWeight: 0.6,
tablePatterns: this.indicators.scalablePermissionTables,
columnPatterns: this.indicators.contextSwitchingPatterns,
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const permissionTables = context.schema.tableNames.filter(table => this.indicators.scalablePermissionTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = permissionTables.length >= 1;
const matchConfidence = matched ?
Math.min(permissionTables.length * 0.7, 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: permissionTables,
matchedColumns: this.indicators.contextSwitchingPatterns,
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'hybrid',
confidence: matchConfidence,
reasoning: `Context-aware permission system with ${permissionTables.length} adaptive permission tables`
}
};
}
/**
* Analyze dual capability pattern
*/
async analyzeDualCapabilityPattern(context) {
const pattern = {
id: 'hybrid_dual_capability',
name: 'Dual Capability Features',
description: 'Features that work in both individual and team contexts',
indicatesArchitecture: ['hybrid'],
confidenceWeight: 0.8,
tablePatterns: this.indicators.dualCapabilityTables,
columnPatterns: ['scope', 'visibility', 'access_type'],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: false
};
const dualTables = context.schema.tableNames.filter(table => this.indicators.dualCapabilityTables.some(pattern => table.toLowerCase().includes(pattern.toLowerCase())));
const matched = dualTables.length >= 2; // Need multiple types for hybrid
const matchConfidence = matched ?
Math.min(dualTables.length * 0.3, 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: dualTables,
matchedColumns: ['scope', 'visibility', 'access_type'],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'hybrid',
confidence: matchConfidence,
reasoning: `Dual capability features with ${dualTables.length} tables supporting both contexts`
}
};
}
/**
* Analyze coexisting features pattern
*/
async analyzeCoexistingFeaturesPattern(context) {
const pattern = {
id: 'hybrid_coexisting_features',
name: 'Coexisting Individual and Team Features',
description: 'Platform has both individual-focused and team-focused features',
indicatesArchitecture: ['hybrid'],
confidenceWeight: 0.9,
tablePatterns: [],
columnPatterns: [],
constraintPatterns: [],
relationshipPatterns: [],
functionPatterns: [],
minimumMatches: 1,
exclusive: true
};
// Check for both individual and team indicators
const individualAnalyzer = new IndividualPlatformAnalyzer();
const teamAnalyzer = new TeamPlatformAnalyzer();
const individualResults = await individualAnalyzer.analyzeIndividualPatterns(context);
const teamResults = await teamAnalyzer.analyzeTeamPatterns(context);
const individualScore = individualResults.reduce((sum, result) => sum + (result.matched ? result.matchConfidence : 0), 0) / Math.max(individualResults.length, 1);
const teamScore = teamResults.reduce((sum, result) => sum + (result.matched ? result.matchConfidence : 0), 0) / Math.max(teamResults.length, 1);
// Hybrid indicates balance between individual and team features
const balance = 1 - Math.abs(individualScore - teamScore);
const minRequiredFeatures = Math.min(individualScore, teamScore);
const matched = individualScore > 0.3 && teamScore > 0.3 && balance > 0.4;
const matchConfidence = matched ?
Math.min((balance * 0.5) + (minRequiredFeatures * 0.5), 1.0) : 0;
return {
pattern,
matched,
matchConfidence,
matchDetails: {
matchedTables: [],
matchedColumns: [],
matchedConstraints: [],
matchedRelationships: [],
matchedFunctions: []
},
architectureIndication: {
type: 'hybrid',
confidence: matchConfidence,
reasoning: `Coexisting features detected: individual score ${individualScore.toFixed(2)}, team score ${teamScore.toFixed(2)}, balance ${balance.toFixed(2)}`
}
};
}
}
exports.HybridPlatformAnalyzer = HybridPlatformAnalyzer;
/**
* Pattern Analysis Orchestrator
* Coordinates all pattern analyzers and provides unified results
*/
class PatternAnalysisOrchestrator {
constructor() {
this.individualAnalyzer = new IndividualPlatformAnalyzer();
this.teamAnalyzer = new TeamPlatformAnalyzer();
this.hybridAnalyzer = new HybridPlatformAnalyzer();
}
/**
* Run comprehensive pattern analysis across all architecture types
*/
async analyzeAllPatterns(context) {
logger_1.Logger.debug('Starting comprehensive pattern analysis');
const [individualResults, teamResults, hybridResults] = await Promise.all([
this.individualAnalyzer.analyzeIndividualPatterns(context),
this.teamAnalyzer.analyzeTeamPatterns(context),
this.hybridAnalyzer.analyzeHybridPatterns(context)
]);
// Calculate aggregate scores
const individualScore = this.calculateAggregateScore(individualResults);
const teamScore = this.calculateAggregateScore(teamResults);
const hybridScore = this.calculateAggregateScore(hybridResults);
// Determine strongest architecture
const scores = [
{ type: 'individual', score: individualScore },
{ type: 'team', score: teamScore },
{ type: 'hybrid', score: hybridScore }
];
scores.sort((a, b) => b.score - a.score);
const strongestArchitecture = scores[0].type;
const confidence = scores[0].score;
logger_1.Logger.debug(`Pattern analysis complete: ${strongestArchitecture} (${confidence.toFixed(2)})`);
return {
individual: individualResults,
team: teamResults,
hybrid: hybridResults,
summary: {
individualScore,
teamScore,
hybridScore,
strongestArchitecture,
confidence
}
};
}
/**
* Calculate aggregate score from pattern analysis results
*/
calculateAggregateScore(results) {
if (results.length === 0)
return 0;
const weightedSum = results.reduce((sum, result) => {
if (!result.matched)
return sum;
return sum + (result.matchConfidence * result.pattern.confidenceWeight);
}, 0);
const totalWeight = results.reduce((sum, result) => {
if (!result.matched)
return sum;
return sum + result.pattern.confidenceWeight;
}, 0);
return totalWeight > 0 ? weightedSum / totalWeight : 0;
}
}
exports.PatternAnalysisOrchestrator = PatternAnalysisOrchestrator;
exports.default = PatternAnalysisOrchestrator;
//# sourceMappingURL=pattern-analyzers.js.map