UNPKG

supa-seed

Version:

A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support

1,002 lines 43.3 kB
"use strict"; /** * Generic Framework Strategy * Fallback strategy for databases without specific framework patterns */ Object.defineProperty(exports, "__esModule", { value: true }); exports.GenericStrategy = void 0; const constraint_discovery_engine_1 = require("../../analysis/constraint-discovery-engine"); const constraint_registry_1 = require("../../analysis/constraint-registry"); const business_logic_analyzer_1 = require("../../analysis/business-logic-analyzer"); const rls_compliant_seeder_1 = require("../../../schema/rls-compliant-seeder"); const relationship_analyzer_1 = require("../../analysis/relationship-analyzer"); const junction_table_handler_1 = require("../../../schema/junction-table-handler"); const multi_tenant_manager_1 = require("../../../schema/multi-tenant-manager"); const storage_integration_manager_1 = require("../../generation/storage/storage-integration-manager"); const logger_1 = require("../../../core/utils/logger"); class GenericStrategy { constructor() { this.name = 'generic'; this.discoveredConstraints = new Map(); } async initialize(client) { this.client = client; this.constraintEngine = new constraint_discovery_engine_1.ConstraintDiscoveryEngine(client); this.constraintRegistry = new constraint_registry_1.ConstraintRegistry({ enablePriorityHandling: false, enableFallbackHandlers: true, logHandlerSelection: false }); // Initialize business logic analyzer for generic patterns this.businessLogicAnalyzer = new business_logic_analyzer_1.BusinessLogicAnalyzer(client, { frameworkHints: [], expectedPatterns: ['direct_insertion'] }); // Initialize RLS compliant seeder with service role preference for generic this.rlsCompliantSeeder = new rls_compliant_seeder_1.RLSCompliantSeeder(client, undefined, { enableRLSCompliance: true, createUserContext: false, useServiceRole: true // Generic strategy prefers service role bypass }); // Initialize relationship analyzer with generic options this.relationshipAnalyzer = new relationship_analyzer_1.RelationshipAnalyzer(client, { schemas: ['public'], detectJunctionTables: true, analyzeTenantScoping: false, // Generic strategy doesn't assume tenant scoping includeOptionalRelationships: true, enableCaching: true, generateRecommendations: true }); // Initialize junction table handler this.junctionTableHandler = new junction_table_handler_1.JunctionTableHandler(client); // Initialize multi-tenant manager with generic configuration this.multiTenantManager = new multi_tenant_manager_1.MultiTenantManager(client, { enableMultiTenant: false, // Generic strategy doesn't assume multi-tenant by default tenantColumn: 'tenant_id', // Generic default, can be overridden tenantScopeDetection: 'auto', validationEnabled: false, // Less strict for generic strictIsolation: false, allowSharedResources: true, dataGenerationOptions: { generatePersonalAccounts: false, // Generic doesn't distinguish account types generateTeamAccounts: false, personalAccountRatio: 1.0, dataDistributionStrategy: 'even', crossTenantDataAllowed: true, // More permissive for generic sharedResourcesEnabled: true, accountTypes: [], minUsersPerTenant: 1, maxUsersPerTenant: 1, minProjectsPerTenant: 1, maxProjectsPerTenant: 1, allowCrossTenantRelationships: true, sharedTables: [], // Will be discovered respectTenantPlans: false, enforceTenantLimits: false } }); // Initialize storage integration manager with generic defaults this.storageIntegrationManager = new storage_integration_manager_1.StorageIntegrationManager(client, { bucketName: 'media', // Generic default bucket domain: 'general', respectRLS: true, // Generic strategy respects RLS by default enableRealImages: false, // Use mock images for generic imagesPerSetup: 5, categories: ['general', 'placeholder'], storageRootPath: 'uploads' }); // Register generic handlers const handlers = this.getConstraintHandlers(); this.constraintRegistry.registerHandlers(handlers); } getPriority() { return 1; // Lowest priority - fallback strategy } async detect(schema) { // Generic strategy always has low confidence - it's a fallback let confidence = 0.1; const detectedFeatures = []; const recommendations = []; try { // Check for basic user-related tables const hasUsersTable = schema.tables.some(t => t.name === 'users'); const hasAccountsTable = schema.tables.some(t => t.name === 'accounts'); const hasProfilesTable = schema.tables.some(t => t.name === 'profiles'); if (hasUsersTable || hasAccountsTable || hasProfilesTable) { confidence = 0.2; detectedFeatures.push('basic_user_tables'); } // Check for auth integration const hasAuthTriggers = schema.triggers.some(t => t.table === 'users' || t.function.includes('auth')); if (hasAuthTriggers) { detectedFeatures.push('auth_integration'); recommendations.push('Consider auth-based user creation for better integration'); } // Basic constraint discovery if (schema.constraints.length > 0) { detectedFeatures.push('has_constraints'); recommendations.push('Enable constraint discovery for better seeding reliability'); } // Always provide fallback recommendations recommendations.push('Using generic strategy - consider framework-specific strategy if available'); recommendations.push('Enable constraint validation for safer operations'); if (confidence < 0.3) { recommendations.push('Low framework detection - consider manual configuration'); } return { framework: this.name, confidence, detectedFeatures, recommendations }; } catch (error) { logger_1.Logger.warn(`Generic detection failed: ${error.message}`); return { framework: this.name, confidence: 0.1, detectedFeatures: ['fallback_mode'], recommendations: ['Using fallback mode due to detection error'] }; } } async createUser(data) { try { logger_1.Logger.debug(`Creating generic user: ${data.email}`); // Try auth-based creation first (safer approach) let user; let useAuthCreation = true; try { const { data: authUser, error: authError } = await this.client.auth.admin.createUser({ email: data.email, password: data.password || 'defaultPassword123!', email_confirm: true, user_metadata: { name: data.name, username: data.username, avatar_url: data.avatar, bio: data.bio, ...data.metadata } }); if (authError) { logger_1.Logger.warn(`Auth creation failed, falling back to direct insertion: ${authError.message}`); useAuthCreation = false; } else if (authUser.user) { user = { id: authUser.user.id, email: authUser.user.email, name: data.name, username: data.username, avatar: data.avatar, created_at: authUser.user.created_at, metadata: authUser.user.user_metadata }; } else { useAuthCreation = false; } } catch (error) { logger_1.Logger.warn(`Auth creation error, using direct insertion: ${error.message}`); useAuthCreation = false; } // Fallback to direct table insertion if (!useAuthCreation) { user = await this.createUserDirectly(data); } // Try to create related records in common tables await this.createRelatedRecords(user, data); return user; } catch (error) { logger_1.Logger.error(`Generic user creation failed: ${error.message}`); throw error; } } async createUserDirectly(data) { // Generate a UUID for the user const userId = crypto.randomUUID(); const now = new Date().toISOString(); // Try multiple table patterns const tablesToTry = ['accounts', 'profiles', 'users']; let createdUser = null; for (const tableName of tablesToTry) { try { // Check if table exists by trying to query it const { error: testError } = await this.client .from(tableName) .select('id') .limit(1); if (testError && testError.code === 'PGRST116') { // Table doesn't exist, skip continue; } // Prepare data for this table const constraintResult = await this.handleConstraints(tableName, { id: userId, email: data.email, name: data.name, username: data.username, avatar_url: data.avatar, bio: data.bio, created_at: now, updated_at: now }); const { error: insertError } = await this.client .from(tableName) .insert(constraintResult.modifiedData); if (!insertError) { createdUser = { id: userId, email: data.email, name: data.name, username: data.username, avatar: data.avatar, created_at: now, metadata: data.metadata }; logger_1.Logger.debug(`User created in ${tableName} table`); break; } else { logger_1.Logger.debug(`Failed to create user in ${tableName}: ${insertError.message}`); } } catch (error) { logger_1.Logger.debug(`Error trying ${tableName} table: ${error.message}`); } } if (!createdUser) { throw new Error('Failed to create user in any available table'); } return createdUser; } async createRelatedRecords(user, data) { // Try to create records in other common tables const relatedTables = ['profiles', 'accounts']; for (const tableName of relatedTables) { try { // Check if table exists and user doesn't already exist there const { data: existing, error: existError } = await this.client .from(tableName) .select('id') .eq('id', user.id) .single(); if (existError && existError.code !== 'PGRST116') { // Error other than table not found continue; } if (existing) { // User already exists in this table continue; } // Try to create related record const constraintResult = await this.handleConstraints(tableName, { id: user.id, email: user.email, name: user.name, username: user.username, avatar_url: user.avatar, bio: data.bio, created_at: user.created_at, updated_at: user.created_at }); const { error: insertError } = await this.client .from(tableName) .insert(constraintResult.modifiedData); if (!insertError) { logger_1.Logger.debug(`Related record created in ${tableName}`); } } catch (error) { logger_1.Logger.debug(`Failed to create related record in ${tableName}: ${error.message}`); } } } async handleConstraints(table, data) { const appliedFixes = []; const warnings = []; let processedData = { ...data }; try { // Basic constraint handling for common patterns // Handle common timestamp fields if (!processedData.created_at) { processedData.created_at = new Date().toISOString(); appliedFixes.push({ type: 'set_field', field: 'created_at', oldValue: undefined, newValue: processedData.created_at, reason: 'Set default created_at timestamp', confidence: 0.9 }); } if (!processedData.updated_at) { processedData.updated_at = processedData.created_at || new Date().toISOString(); appliedFixes.push({ type: 'set_field', field: 'updated_at', oldValue: undefined, newValue: processedData.updated_at, reason: 'Set default updated_at timestamp', confidence: 0.9 }); } // Handle nullable vs non-nullable patterns if (table === 'accounts' && processedData.slug === undefined) { // If we can't determine if slug should be null, make it nullable processedData.slug = null; appliedFixes.push({ type: 'set_field', field: 'slug', oldValue: undefined, newValue: null, reason: 'Default slug to null for compatibility', confidence: 0.8 }); } // Remove undefined values that might cause insertion issues Object.keys(processedData).forEach(key => { if (processedData[key] === undefined) { delete processedData[key]; appliedFixes.push({ type: 'remove_field', field: key, oldValue: undefined, newValue: undefined, reason: 'Remove undefined value to prevent insertion errors', confidence: 0.95 }); } }); // Handle common field mapping if (processedData.avatar_url && !processedData.avatar) { processedData.avatar = processedData.avatar_url; } if (processedData.avatar && !processedData.avatar_url) { processedData.avatar_url = processedData.avatar; } return { success: true, originalData: data, modifiedData: processedData, appliedFixes, warnings, errors: [], bypassRequired: false }; } catch (error) { logger_1.Logger.warn(`Generic constraint handling failed for ${table}: ${error.message}`); return { success: false, originalData: data, modifiedData: processedData, appliedFixes, warnings: [...warnings, `Constraint handling error: ${error.message}`], errors: [error.message], bypassRequired: true }; } } getRecommendations() { return [ 'Generic strategy provides basic compatibility with any schema', 'Consider using a framework-specific strategy for better integration', 'Enable constraint discovery to improve data integrity', 'Use auth.admin.createUser() when possible for better Supabase integration', 'Test seeding with small data sets first to identify schema-specific issues' ]; } supportsFeature(feature) { const supportedFeatures = [ 'basic_user_creation', 'direct_insertion', 'fallback_behavior', 'constraint_basic_handling', 'multi_table_attempts', 'constraint_discovery' ]; return supportedFeatures.includes(feature); } /** * Discover constraints using generic analysis */ async discoverConstraints(tableNames) { if (!this.constraintEngine) { throw new Error('Constraint engine not initialized'); } try { logger_1.Logger.debug('Discovering constraints with generic strategy'); const discoveryResult = await this.constraintEngine.discoverConstraints(tableNames || []); // Convert discovery engine tables to constraint types format const convertedTables = discoveryResult.tables.map(table => ({ table: table.tableName, schema: 'public', checkConstraints: [], foreignKeyConstraints: [], uniqueConstraints: [], primaryKeyConstraints: [], notNullConstraints: [], confidence: discoveryResult.confidence, discoveryTimestamp: new Date().toISOString() })); return { success: true, tables: convertedTables, totalConstraints: discoveryResult.businessRules.length, confidence: discoveryResult.confidence, errors: [], warnings: [], recommendations: [ ...this.getRecommendations(), 'Consider using a framework-specific strategy for better constraint handling' ] }; } catch (error) { logger_1.Logger.error('Generic constraint discovery failed:', error); return { success: false, tables: [], totalConstraints: 0, confidence: 0, errors: [error.message], warnings: [], recommendations: ['Review constraint discovery configuration'] }; } } /** * Get generic constraint handlers */ getConstraintHandlers() { return [ { id: 'generic_basic_check', type: 'check', priority: 10, description: 'Basic handler for check constraints', canHandle: () => true, handle: (constraint, data) => ({ success: true, originalData: { ...data }, modifiedData: { ...data }, appliedFixes: [], warnings: [`Basic handling for check constraint: ${constraint.constraintName || 'unknown'}`], errors: [], bypassRequired: false }) }, { id: 'generic_basic_foreign_key', type: 'foreign_key', priority: 10, description: 'Basic handler for foreign key constraints', canHandle: () => true, handle: (constraint, data) => ({ success: true, originalData: { ...data }, modifiedData: { ...data }, appliedFixes: [], warnings: [`Foreign key reference: ensure ${constraint.referencedTable} exists`], errors: [], bypassRequired: false }) } ]; } /** * Apply constraint fixes using generic logic */ async applyConstraintFixes(table, data, constraints) { if (!this.constraintRegistry) { throw new Error('Constraint registry not initialized'); } try { logger_1.Logger.debug(`Applying generic constraint fixes for table: ${table}`); const result = this.constraintRegistry.handleTableConstraints(constraints, data); // Add generic safety measures if (!result.modifiedData.created_at) { result.modifiedData.created_at = new Date().toISOString(); result.appliedFixes.push({ type: 'set_field', field: 'created_at', oldValue: undefined, newValue: result.modifiedData.created_at, reason: 'Set default timestamp', confidence: 0.9 }); } return result; } catch (error) { logger_1.Logger.error('Generic constraint fix application failed:', error); return { success: false, originalData: data, modifiedData: data, appliedFixes: [], warnings: [], errors: [error.message], bypassRequired: true }; } } /** * Analyze business logic patterns for generic strategy */ async analyzeBusinessLogic() { if (!this.businessLogicAnalyzer) { throw new Error('Business logic analyzer not initialized'); } try { logger_1.Logger.debug('Analyzing generic business logic patterns'); const analysis = await this.businessLogicAnalyzer.analyzeBusinessLogic(); // Add generic-specific enhancements to the analysis if (analysis.success) { analysis.framework = 'generic'; // Generic strategy typically has lower confidence for business logic analysis.confidence = Math.min(analysis.confidence, 0.7); // Add generic-specific recommendations const genericRecommendations = [ 'Consider framework-specific strategy for better business logic compliance', 'Use service role for RLS bypass when needed', 'Enable constraint discovery for better data integrity' ]; analysis.warnings.push(...genericRecommendations); } return analysis; } catch (error) { logger_1.Logger.error('Generic business logic analysis failed:', error); throw error; } } /** * Seed data with RLS compliance for generic strategy */ async seedWithRLSCompliance(table, data, userContext) { if (!this.rlsCompliantSeeder) { throw new Error('RLS compliant seeder not initialized'); } try { logger_1.Logger.debug(`Generic RLS-compliant seeding for table: ${table}`); // For generic strategy, we often prefer service role bypass const result = await this.rlsCompliantSeeder.seedWithRLSCompliance(table, data, userContext); // Add generic-specific context to the result if (result.success && result.bypassesUsed.length > 0) { result.warnings = result.warnings || []; result.warnings.push('Used service role bypass for generic seeding'); } return result; } catch (error) { logger_1.Logger.error(`Generic RLS-compliant seeding failed for ${table}:`, error); throw error; } } /** * Get RLS compliance options for generic strategy */ getRLSComplianceOptions() { return { enableRLSCompliance: true, useServiceRole: true, // Generic strategy prefers service role bypass createUserContext: false, bypassOnFailure: true, // More permissive for generic use validateAfterInsert: false, logPolicyViolations: true, maxRetries: 1 }; } /** * Analyze database relationships for generic strategy */ async analyzeRelationships() { if (!this.relationshipAnalyzer) { throw new Error('Relationship analyzer not initialized'); } try { logger_1.Logger.debug('Analyzing relationships for generic strategy'); const analysis = await this.relationshipAnalyzer.analyzeRelationships(); // Add generic-specific enhancements to the analysis if (analysis.success) { // Generic strategy has lower confidence since it doesn't know framework specifics analysis.analysisMetadata.confidence = Math.min(analysis.analysisMetadata.confidence, 0.8); // Add generic-specific recommendations analysis.recommendations.push('Consider using framework-specific strategy for better relationship handling'); analysis.recommendations.push('Verify tenant boundaries if using multi-tenant architecture'); } return analysis; } catch (error) { logger_1.Logger.error('Generic relationship analysis failed:', error); throw error; } } /** * Get dependency graph for generic strategy */ async getDependencyGraph() { if (!this.relationshipAnalyzer) { throw new Error('Relationship analyzer not initialized'); } try { logger_1.Logger.debug('Building generic dependency graph'); const analysis = await this.relationshipAnalyzer.analyzeRelationships(); if (!analysis.success) { throw new Error('Failed to analyze relationships for dependency graph'); } return analysis.dependencyGraph; } catch (error) { logger_1.Logger.error('Generic dependency graph creation failed:', error); throw error; } } /** * Detect junction tables with generic patterns */ async detectJunctionTables() { if (!this.junctionTableHandler || !this.relationshipAnalyzer) { throw new Error('Junction table handler or relationship analyzer not initialized'); } try { logger_1.Logger.debug('Detecting junction tables for generic strategy'); const dependencyGraph = await this.getDependencyGraph(); const result = await this.junctionTableHandler.detectJunctionTables(dependencyGraph); // Add generic-specific recommendations if (result.success && result.junctionTables.length > 0) { result.recommendations.push('Verify junction table patterns match your application architecture'); result.recommendations.push('Consider framework-specific strategy for optimized junction table handling'); } return result; } catch (error) { logger_1.Logger.error('Generic junction table detection failed:', error); return { success: false, junctionTables: [], relationshipPatterns: [], totalRelationships: 0, confidence: 0, warnings: [], errors: [error.message], recommendations: [] }; } } /** * Seed junction table with generic options */ async seedJunctionTable(tableName, options = {}) { if (!this.junctionTableHandler) { throw new Error('Junction table handler not initialized'); } try { logger_1.Logger.debug(`Seeding generic junction table: ${tableName}`); // Generic-specific junction seeding options const genericOptions = { generateRelationships: true, relationshipDensity: 0.3, // Conservative density for generic use respectCardinality: true, avoidOrphans: true, distributionStrategy: 'random', // Random distribution works well generically generateMetadata: false, // Less metadata assumption for generic includeTimestamps: true, validateForeignKeys: true, ...options }; const result = await this.junctionTableHandler.seedJunctionTable(tableName, genericOptions); // Add generic-specific context to the result if (result.success) { result.warnings = result.warnings || []; result.warnings.push('Used generic junction table seeding - consider framework-specific optimization'); } return result; } catch (error) { logger_1.Logger.error(`Generic junction table seeding failed for ${tableName}:`, error); throw error; } } /** * Get optimal seeding order for generic schemas */ async getSeedingOrder() { if (!this.relationshipAnalyzer) { throw new Error('Relationship analyzer not initialized'); } try { logger_1.Logger.debug('Calculating generic seeding order'); const analysis = await this.relationshipAnalyzer.analyzeRelationships(); if (!analysis.success) { throw new Error('Failed to analyze relationships for seeding order'); } const seedingOrder = analysis.seedingOrder.seedingOrder; logger_1.Logger.info(`Generic seeding order: ${seedingOrder.join(' → ')}`); return seedingOrder; } catch (error) { logger_1.Logger.error('Generic seeding order calculation failed:', error); throw error; } } /** * Multi-Tenant Methods Implementation (Basic Generic Support) */ /** * Discover tenant-scoped tables and relationships */ async discoverTenantScopes() { if (!this.multiTenantManager) { throw new Error('Multi-tenant manager not initialized'); } logger_1.Logger.info('🔍 Generic tenant scope discovery (basic support)...'); try { const result = await this.multiTenantManager.discoverTenantScopes(); // Add generic strategy notes if (result.success) { result.recommendations.push('Generic strategy: Multi-tenant support is basic', 'Consider using a framework-specific strategy for better tenant support', 'Manual configuration may be required for complex tenant patterns'); } return result; } catch (error) { logger_1.Logger.error('Generic tenant scope discovery failed:', error); throw error; } } /** * Create tenant-aware data with basic support */ async createTenantScopedData(tenantId, tableName, data, options = {}) { if (!this.multiTenantManager) { throw new Error('Multi-tenant manager not initialized'); } logger_1.Logger.debug(`🔍 Generic tenant-scoped data creation for ${tableName} (basic support)`); try { // Generic strategy just passes through to the multi-tenant manager // without any framework-specific transformations return await this.multiTenantManager.createTenantScopedData(tableName, tenantId, data, options); } catch (error) { logger_1.Logger.error(`Generic tenant-scoped data creation failed for ${tableName}:`, error); throw error; } } /** * Generate basic tenant accounts (generic implementation) */ async generateTenantAccounts(count, options = {}) { if (!this.multiTenantManager) { throw new Error('Multi-tenant manager not initialized'); } logger_1.Logger.info(`🔍 Generating ${count} generic tenant accounts (basic support)...`); try { // Generic strategy generates simple tenant info without creating database records const tenants = await this.multiTenantManager.generateTenantAccounts(count, { ...options, generatePersonalAccounts: false, // Generic doesn't distinguish types generateTeamAccounts: false, personalAccountRatio: 1.0, dataDistributionStrategy: 'even' }); logger_1.Logger.success(`✅ Generated ${tenants.length} generic tenant accounts`); logger_1.Logger.info('💡 Note: Generic strategy provides basic tenant support only'); logger_1.Logger.info('💡 Consider using MakerKit or framework-specific strategy for full support'); return tenants; } catch (error) { logger_1.Logger.error('Generic tenant account generation failed:', error); throw error; } } /** * Basic tenant isolation validation */ async validateTenantIsolation(tenantId) { if (!this.multiTenantManager) { throw new Error('Multi-tenant manager not initialized'); } logger_1.Logger.info(`📊 Generic tenant isolation validation for: ${tenantId} (basic support)`); try { const report = await this.multiTenantManager.createTenantIsolationReport(tenantId); // Add generic strategy notes report.recommendations.push('Generic strategy: Basic tenant isolation validation only', 'Framework-specific strategies provide more comprehensive validation', 'Manual verification may be required for complex scenarios'); return report; } catch (error) { logger_1.Logger.error(`Generic tenant isolation validation failed for ${tenantId}:`, error); throw error; } } /** * Basic multi-tenant data seeding */ async seedMultiTenantData(tenants, options = {}) { logger_1.Logger.info(`🌱 Generic multi-tenant data seeding for ${tenants.length} tenants (basic support)...`); const startTime = Date.now(); const errors = []; const warnings = [ 'Generic strategy provides basic multi-tenant support only', 'Framework-specific strategies offer more comprehensive tenant features' ]; try { // Basic implementation - just return minimal result const result = { success: true, tenantsCreated: tenants.length, personalAccounts: 0, // Generic doesn't distinguish types teamAccounts: 0, totalRecords: 0, tenantScopedRecords: 0, crossTenantReferences: 0, validationResult: { isValid: true, violations: [], warnings: warnings, recommendations: [ 'Generic strategy completed basic tenant setup', 'Consider using framework-specific strategy for production use', 'Manual data seeding may be required for complex scenarios' ], isolationScore: 0.5 // Basic score for generic }, executionTime: Date.now() - startTime, errors, warnings, tenantDetails: tenants.map(tenant => ({ tenantId: tenant.id, tenantType: tenant.type, recordsCreated: 0, tablesSeeded: [], relationships: 0, isolationScore: 0.5, errors: [], warnings: [] })) }; logger_1.Logger.success(`✅ Generic multi-tenant seeding completed (basic support)`); return result; } catch (error) { logger_1.Logger.error('Generic multi-tenant seeding failed:', error); throw error; } } /** * Get tenant scope information for a table */ async getTenantScopeInfo(tableName) { if (!this.multiTenantManager) { throw new Error('Multi-tenant manager not initialized'); } const scopeInfo = this.multiTenantManager.getTenantScopeInfo(tableName); return scopeInfo || null; } /** * Storage Integration Methods (Basic Generic Support) */ /** * Integrate with Supabase Storage for file uploads */ async integrateWithStorage(setupId, accountId, config) { if (!this.storageIntegrationManager) { throw new Error('Storage integration manager not initialized'); } logger_1.Logger.info(`🗂️ Generic storage integration for setup: ${setupId} (basic support)`); try { // Generic strategy uses conservative settings const genericConfig = { domain: 'general', enableRealImages: false, // Use mock images for generic compatibility imagesPerSetup: 3, // Conservative count for generic respectRLS: true, categories: ['general', 'placeholder', 'mock'], ...config }; const result = await this.storageIntegrationManager.seedWithStorageFiles(setupId, accountId, genericConfig); // Add generic strategy context if (result.success) { result.warnings = result.warnings || []; result.warnings.push('Generic strategy: Basic storage integration only'); result.recommendations.push('Consider framework-specific strategy for advanced storage features'); } return result; } catch (error) { logger_1.Logger.error(`Generic storage integration failed for ${setupId}:`, error); throw error; } } /** * Check storage permissions (basic generic implementation) */ async checkStoragePermissions(bucketName) { if (!this.storageIntegrationManager) { throw new Error('Storage integration manager not initialized'); } logger_1.Logger.debug(`🔒 Generic storage permission check for: ${bucketName} (basic support)`); try { const result = await this.storageIntegrationManager.checkStoragePermissions(bucketName); // Add generic strategy notes result.recommendations.push('Generic strategy: Basic permission checking only'); result.recommendations.push('Framework-specific strategies provide more comprehensive permission validation'); return result; } catch (error) { logger_1.Logger.error(`Generic storage permission check failed for ${bucketName}:`, error); throw error; } } /** * Get storage quota information (basic generic implementation) */ async getStorageQuota(bucketName) { if (!this.storageIntegrationManager) { throw new Error('Storage integration manager not initialized'); } logger_1.Logger.debug(`📊 Generic storage quota check for: ${bucketName} (basic support)`); try { const result = await this.storageIntegrationManager.getStorageQuota(bucketName); // Add generic strategy notes result.recommendations = result.recommendations || []; result.recommendations.push('Generic strategy: Basic quota monitoring only'); result.recommendations.push('Consider monitoring tools for production usage'); return result; } catch (error) { logger_1.Logger.error(`Generic storage quota check failed for ${bucketName}:`, error); throw error; } } /** * Generate media attachments (basic generic implementation) */ async generateMediaAttachments(entityId, entityType, count = 2, config) { logger_1.Logger.info(`🖼️ Generic media generation for ${entityType}:${entityId} (basic support)`); try { // Generic strategy generates minimal media attachments const setupId = `${entityType}_${entityId}_${Date.now()}`; const result = await this.integrateWithStorage(setupId, entityId, { imagesPerSetup: Math.min(count, 3), // Limit for generic use domain: 'general', enableRealImages: false, categories: ['general', 'placeholder'], ...config }); if (result.success) { logger_1.Logger.success(`✅ Generated ${result.mediaAttachments.length} media attachments (generic)`); logger_1.Logger.info('💡 Note: Generic strategy provides basic media generation only'); return result.mediaAttachments; } else { logger_1.Logger.warn('⚠️ Generic media generation completed with errors'); return []; } } catch (error) { logger_1.Logger.error(`Generic media generation failed for ${entityType}:${entityId}:`, error); return []; } } /** * Get storage configuration for generic strategy */ getStorageConfig() { return { bucketName: 'media', domain: 'general', respectRLS: true, enableRealImages: false, // Generic uses mock images for compatibility imagesPerSetup: 3, categories: ['general', 'placeholder', 'mock'], storageRootPath: 'uploads' }; } } exports.GenericStrategy = GenericStrategy; //# sourceMappingURL=generic-strategy.js.map