UNPKG

supa-seed

Version:

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

420 lines โ€ข 21.7 kB
"use strict"; /** * CLI Commands for Storage Integration System */ Object.defineProperty(exports, "__esModule", { value: true }); exports.StorageCommands = void 0; const framework_adapter_1 = require("../../features/integration/framework-adapter"); const storage_integration_manager_1 = require("../../features/generation/storage/storage-integration-manager"); const enhanced_supabase_client_1 = require("../../core/utils/enhanced-supabase-client"); const storage_config_1 = require("../../core/config/storage-config"); class StorageCommands { /** * Format file size in human readable format */ static formatFileSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`; } /** * Test storage permissions and connectivity */ static async testStorage(options) { const client = (0, enhanced_supabase_client_1.createEnhancedSupabaseClient)(options.url || process.env.SUPABASE_URL || 'http://127.0.0.1:54321', options.key || process.env.SUPABASE_SERVICE_ROLE_KEY || ''); try { console.log('๐Ÿ” Testing storage connectivity and permissions...\n'); // Initialize framework adapter to get proper configuration const adapter = new framework_adapter_1.FrameworkAdapter(client, undefined, { debug: options.verbose || false, frameworkOverride: options.framework }); await adapter.initialize(); const strategy = adapter.getCurrentStrategy(); // Get storage configuration const storageConfig = strategy?.getStorageConfig?.() || storage_config_1.StorageConfigUtils.getFrameworkConfig('generic').config; const bucketName = options.bucket || storageConfig.bucketName || 'media'; console.log('๐Ÿ“‹ Storage Test Configuration:'); console.log(` Framework: ${strategy?.name || 'generic'}`); console.log(` Bucket: ${bucketName}`); console.log(` Domain: ${storageConfig.domain || 'general'}`); console.log(` RLS Enabled: ${storageConfig.respectRLS ? 'โœ…' : 'โŒ'}`); // Initialize storage manager const storageManager = new storage_integration_manager_1.StorageIntegrationManager(client, { ...storageConfig, bucketName }); // Test permissions console.log('\n๐Ÿ”’ Testing storage permissions...'); const permissionCheck = await storageManager.checkStoragePermissions(bucketName); console.log(` Read Access: ${permissionCheck.canRead ? 'โœ…' : 'โŒ'}`); console.log(` Write Access: ${permissionCheck.canWrite ? 'โœ…' : 'โŒ'}`); console.log(` Delete Access: ${permissionCheck.canDelete ? 'โœ…' : 'โŒ'}`); console.log(` Permission Level: ${permissionCheck.permissionLevel}`); if (permissionCheck.rlsPolicies.length > 0) { console.log(` RLS Policies: ${permissionCheck.rlsPolicies.length} detected`); if (options.verbose) { console.log('\n ๐Ÿ“‹ RLS Policies:'); permissionCheck.rlsPolicies.forEach(policy => { console.log(` โ€ข ${policy.name} (${policy.policy_type})`); }); } } if (permissionCheck.restrictions.length > 0) { console.log('\n โš ๏ธ Restrictions:'); permissionCheck.restrictions.forEach(restriction => { console.log(` โ€ข ${restriction}`); }); } // Test quota console.log('\n๐Ÿ“Š Checking storage quota...'); const quotaInfo = await storageManager.getStorageQuota(bucketName); console.log(` Current Usage: ${StorageCommands.formatFileSize(quotaInfo.currentUsage)}`); console.log(` Total Quota: ${StorageCommands.formatFileSize(quotaInfo.totalQuota)}`); console.log(` Usage Percentage: ${quotaInfo.usagePercentage.toFixed(1)}%`); console.log(` Files Count: ${quotaInfo.filesCount}`); console.log(` Near Limit: ${quotaInfo.isNearLimit ? 'โš ๏ธ Yes' : 'โœ… No'}`); // Show recommendations const allRecommendations = [ ...permissionCheck.recommendations, ...quotaInfo.recommendations ]; if (allRecommendations.length > 0) { console.log('\n๐Ÿ’ก Recommendations:'); [...new Set(allRecommendations)].forEach(rec => { console.log(` โ€ข ${rec}`); }); } console.log('\nโœ… Storage test completed'); } catch (error) { console.error('โŒ Storage test failed:', error.message); if (options.verbose) { console.error('Debug details:', error); } process.exit(1); } } /** * Generate and upload test media files */ static async generateMedia(options) { const client = (0, enhanced_supabase_client_1.createEnhancedSupabaseClient)(options.url || process.env.SUPABASE_URL || 'http://127.0.0.1:54321', options.key || process.env.SUPABASE_SERVICE_ROLE_KEY || ''); try { const setupId = options.setupId || `test-setup-${Date.now()}`; const count = options.count || 3; console.log(`๐Ÿ–ผ๏ธ Generating ${count} media files for setup: ${setupId}\n`); // Initialize framework adapter const adapter = new framework_adapter_1.FrameworkAdapter(client, undefined, { debug: options.verbose || false, frameworkOverride: options.framework }); await adapter.initialize(); const strategy = adapter.getCurrentStrategy(); if (!strategy) { throw new Error('No strategy available for media generation'); } // Check if strategy supports storage if (!strategy.integrateWithStorage) { throw new Error(`Strategy ${strategy.name} does not support storage integration`); } // Prepare custom configuration const customConfig = { imagesPerSetup: count }; if (options.domain) { customConfig.domain = options.domain; } if (options.bucket) { customConfig.bucketName = options.bucket; } if (options.enableRealImages !== undefined) { customConfig.enableRealImages = options.enableRealImages; } console.log('๐Ÿ“‹ Media Generation Configuration:'); console.log(` Framework: ${strategy.name}`); console.log(` Setup ID: ${setupId}`); console.log(` Account ID: ${options.accountId || 'none'}`); console.log(` Images Count: ${count}`); console.log(` Real Images: ${customConfig.enableRealImages ? 'โœ…' : 'โŒ'}`); console.log(` Domain: ${customConfig.domain || 'default'}`); // Execute storage integration console.log('\n๐Ÿš€ Starting media generation...'); const result = await strategy.integrateWithStorage(setupId, options.accountId, customConfig); // Display results console.log(`\n๐Ÿ“Š Media Generation Results:`); console.log(` Success: ${result.success ? 'โœ…' : 'โŒ'}`); console.log(` Files Processed: ${result.totalFilesProcessed}`); console.log(` Files Uploaded: ${result.totalFilesUploaded}`); console.log(` Total Size: ${StorageCommands.formatFileSize(result.totalSize)}`); console.log(` Execution Time: ${result.executionTime}ms`); if (result.mediaAttachments.length > 0) { console.log(`\n๐Ÿ“Ž Generated Media Attachments:`); result.mediaAttachments.forEach((attachment, index) => { console.log(` ${index + 1}. ${attachment.file_name}`); console.log(` Type: ${attachment.file_type}`); console.log(` Size: ${StorageCommands.formatFileSize(attachment.file_size)}`); console.log(` Path: ${attachment.file_path}`); if (options.verbose) { console.log(` Alt Text: ${attachment.alt_text}`); console.log(` Description: ${attachment.description}`); } }); } if (result.warnings.length > 0) { console.log('\nโš ๏ธ Warnings:'); result.warnings.forEach(warning => { console.log(` โ€ข ${warning}`); }); } if (result.errors.length > 0) { console.log('\nโŒ Errors:'); result.errors.forEach(error => { console.log(` โ€ข ${error}`); }); } if (result.recommendations.length > 0) { console.log('\n๐Ÿ’ก Recommendations:'); result.recommendations.forEach(rec => { console.log(` โ€ข ${rec}`); }); } console.log('\nโœ… Media generation completed'); } catch (error) { console.error('โŒ Media generation failed:', error.message); if (options.verbose) { console.error('Debug details:', error); } process.exit(1); } } /** * Show storage configuration for a framework */ static async showConfig(options) { const client = (0, enhanced_supabase_client_1.createEnhancedSupabaseClient)(options.url || process.env.SUPABASE_URL || 'http://127.0.0.1:54321', options.key || process.env.SUPABASE_SERVICE_ROLE_KEY || ''); try { console.log('โš™๏ธ Storage Configuration Analysis\n'); // Initialize framework adapter const adapter = new framework_adapter_1.FrameworkAdapter(client, undefined, { debug: options.verbose || false, frameworkOverride: options.framework }); await adapter.initialize(); const strategy = adapter.getCurrentStrategy(); const frameworkName = strategy?.name || 'generic'; console.log(`๐Ÿ“‹ Framework: ${frameworkName}`); // Get framework-specific storage configuration const frameworkConfig = storage_config_1.StorageConfigUtils.getFrameworkConfig(frameworkName); const mergedConfig = storage_config_1.StorageConfigUtils.getMergedConfig(frameworkName); const envConfig = storage_config_1.StorageConfigUtils.getEnvironmentConfig(); console.log('\n๐Ÿ—๏ธ Framework Storage Configuration:'); console.log(` Bucket Name: ${frameworkConfig.config.bucketName}`); console.log(` Domain: ${frameworkConfig.config.domain}`); console.log(` Bucket Strategy: ${frameworkConfig.bucketStrategy}`); console.log(` Media Strategy: ${frameworkConfig.mediaAttachmentStrategy}`); console.log(` RLS Respect: ${frameworkConfig.config.respectRLS ? 'โœ…' : 'โŒ'}`); console.log(` Real Images: ${frameworkConfig.config.enableRealImages ? 'โœ…' : 'โŒ'}`); console.log(` Images Per Setup: ${frameworkConfig.config.imagesPerSetup}`); if (frameworkConfig.config.categories) { console.log(` Categories: ${frameworkConfig.config.categories.join(', ')}`); } console.log('\n๐ŸŒ Environment Configuration:'); console.log(` Environment: ${process.env.NODE_ENV || 'development'}`); console.log(` Real Images Override: ${envConfig.enableRealImages ? 'โœ…' : 'โŒ'}`); console.log(` RLS Override: ${envConfig.respectRLS ? 'โœ…' : 'โŒ'}`); console.log('\n๐Ÿ”ง Default Permissions:'); console.log(` Respect RLS: ${frameworkConfig.defaultPermissions.respectRLS ? 'โœ…' : 'โŒ'}`); console.log(` Enable Public URLs: ${frameworkConfig.defaultPermissions.enablePublicUrls ? 'โœ…' : 'โŒ'}`); console.log(` Require Auth: ${frameworkConfig.defaultPermissions.requireAuth ? 'โœ…' : 'โŒ'}`); // Validate configuration console.log('\nโœ… Configuration Validation:'); const validation = storage_config_1.StorageConfigUtils.validate(mergedConfig); console.log(` Valid: ${validation.isValid ? 'โœ…' : 'โŒ'}`); if (validation.errors.length > 0) { console.log('\nโŒ Configuration Errors:'); validation.errors.forEach(error => { console.log(` โ€ข ${error}`); }); } if (validation.warnings.length > 0) { console.log('\nโš ๏ธ Configuration Warnings:'); validation.warnings.forEach(warning => { console.log(` โ€ข ${warning}`); }); } // Get recommendations const recommendations = storage_config_1.StorageConfigUtils.getRecommendations(frameworkName, mergedConfig); if (recommendations.length > 0) { console.log('\n๐Ÿ’ก Recommendations:'); recommendations.forEach(rec => { console.log(` โ€ข ${rec}`); }); } // Show API key status console.log('\n๐Ÿ”‘ API Key Status:'); console.log(` Unsplash: ${process.env.UNSPLASH_ACCESS_KEY ? 'โœ… Configured' : 'โŒ Missing'}`); console.log(` Pixabay: ${process.env.PIXABAY_API_KEY ? 'โœ… Configured' : 'โŒ Missing'}`); if (options.verbose) { console.log('\n๐Ÿ” Full Merged Configuration:'); console.log(JSON.stringify(mergedConfig, null, 2)); } console.log('\nโœ… Configuration analysis completed'); } catch (error) { console.error('โŒ Configuration analysis failed:', error.message); if (options.verbose) { console.error('Debug details:', error); } process.exit(1); } } /** * Check media attachments for a setup */ static async listMedia(options) { const client = (0, enhanced_supabase_client_1.createEnhancedSupabaseClient)(options.url || process.env.SUPABASE_URL || 'http://127.0.0.1:54321', options.key || process.env.SUPABASE_SERVICE_ROLE_KEY || ''); try { console.log('๐Ÿ“Ž Listing media attachments...\n'); const setupId = options.setupId; const accountId = options.accountId; if (!setupId && !accountId) { console.log('โš ๏ธ Please specify either --setup-id or --account-id to filter results'); return; } // Build query let query = client.from('media_attachments').select('*'); if (setupId) { query = query.eq('setup_id', setupId); } if (accountId) { query = query.eq('account_id', accountId); } query = query.order('created_at', { ascending: false }); const { data: mediaAttachments, error } = await query; if (error) { throw new Error(`Failed to fetch media attachments: ${error.message}`); } if (!mediaAttachments || mediaAttachments.length === 0) { console.log('๐Ÿ“ญ No media attachments found'); return; } console.log(`๐Ÿ“Š Found ${mediaAttachments.length} media attachment(s):`); mediaAttachments.forEach((attachment, index) => { console.log(`\n ${index + 1}. ${attachment.file_name}`); console.log(` ID: ${attachment.id}`); console.log(` Setup ID: ${attachment.setup_id || 'N/A'}`); console.log(` Account ID: ${attachment.account_id || 'N/A'}`); console.log(` Type: ${attachment.file_type}`); console.log(` Size: ${attachment.file_size} bytes`); console.log(` Bucket: ${attachment.storage_bucket}`); console.log(` Path: ${attachment.file_path}`); console.log(` Status: ${attachment.upload_status}`); console.log(` Public: ${attachment.is_public ? 'โœ…' : 'โŒ'}`); console.log(` Created: ${new Date(attachment.created_at).toLocaleString()}`); if (options.verbose) { console.log(` Alt Text: ${attachment.alt_text || 'N/A'}`); console.log(` Description: ${attachment.description || 'N/A'}`); if (attachment.metadata) { console.log(` Metadata: ${JSON.stringify(attachment.metadata, null, 8)}`); } } }); console.log('\nโœ… Media listing completed'); } catch (error) { console.error('โŒ Media listing failed:', error.message); if (options.verbose) { console.error('Debug details:', error); } process.exit(1); } } /** * Clean up media attachments and storage files */ static async cleanupMedia(options) { const client = (0, enhanced_supabase_client_1.createEnhancedSupabaseClient)(options.url || process.env.SUPABASE_URL || 'http://127.0.0.1:54321', options.key || process.env.SUPABASE_SERVICE_ROLE_KEY || ''); try { console.log('๐Ÿงน Cleaning up media attachments and storage files...\n'); const setupId = options.setupId; const bucketName = options.bucket || 'media'; if (!setupId) { console.log('โš ๏ธ Please specify --setup-id to target specific media for cleanup'); return; } // Get media attachments to clean up const { data: mediaAttachments, error: queryError } = await client .from('media_attachments') .select('*') .eq('setup_id', setupId); if (queryError) { throw new Error(`Failed to fetch media attachments: ${queryError.message}`); } if (!mediaAttachments || mediaAttachments.length === 0) { console.log('๐Ÿ“ญ No media attachments found for cleanup'); return; } console.log(`๐Ÿ“Š Found ${mediaAttachments.length} media attachment(s) to clean up`); let deletedFiles = 0; let deletedRecords = 0; const errors = []; // Clean up storage files console.log('\n๐Ÿ—‘๏ธ Deleting storage files...'); for (const attachment of mediaAttachments) { try { const { error: deleteError } = await client.storage .from(bucketName) .remove([attachment.file_path]); if (deleteError) { errors.push(`Failed to delete ${attachment.file_path}: ${deleteError.message}`); } else { deletedFiles++; console.log(` โœ… Deleted: ${attachment.file_name}`); } } catch (error) { errors.push(`Error deleting ${attachment.file_path}: ${error.message}`); } } // Clean up database records console.log('\n๐Ÿ—ƒ๏ธ Deleting database records...'); const { error: deleteRecordsError } = await client .from('media_attachments') .delete() .eq('setup_id', setupId); if (deleteRecordsError) { errors.push(`Failed to delete media attachment records: ${deleteRecordsError.message}`); } else { deletedRecords = mediaAttachments.length; console.log(` โœ… Deleted ${deletedRecords} database record(s)`); } // Summary console.log(`\n๐Ÿ“Š Cleanup Summary:`); console.log(` Files Deleted: ${deletedFiles}/${mediaAttachments.length}`); console.log(` Records Deleted: ${deletedRecords}/${mediaAttachments.length}`); if (errors.length > 0) { console.log('\nโŒ Cleanup Errors:'); errors.forEach(error => { console.log(` โ€ข ${error}`); }); } console.log('\nโœ… Media cleanup completed'); } catch (error) { console.error('โŒ Media cleanup failed:', error.message); if (options.verbose) { console.error('Debug details:', error); } process.exit(1); } } } exports.StorageCommands = StorageCommands; //# sourceMappingURL=storage-commands.js.map