UNPKG

supa-seed

Version:

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

433 lines 18.4 kB
"use strict"; /** * MakerKit Compatibility Layer * Ensures seamless integration with all MakerKit versions and patterns * Phase 1, Checkpoint A2 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MakerKitCompatibilityLayer = void 0; const logger_1 = require("../../core/utils/logger"); const schema_adapter_1 = require("../../core/schema-adapter"); class MakerKitCompatibilityLayer { constructor(client, config, schemaAdapter) { this.schemaInfo = null; this.client = client; this.config = config; this.schemaAdapter = schemaAdapter || new schema_adapter_1.SchemaAdapter(client); } /** * Initialize and validate MakerKit compatibility */ async initialize() { logger_1.Logger.info('🔧 Initializing MakerKit compatibility layer...'); // Detect schema and get compatibility info this.schemaInfo = await this.schemaAdapter.detectSchema(); // Validate compatibility const validation = await this.validateMakerKitCompatibility(); // Auto-configure based on detected version if needed if (this.config.makerkitVersion === 'auto') { this.config.makerkitVersion = this.schemaInfo.makerkitVersion; logger_1.Logger.info(`🎯 Auto-detected MakerKit version: ${this.config.makerkitVersion}`); } logger_1.Logger.info(`✅ MakerKit compatibility: ${validation.compatibility}`); return validation; } /** * Get the standard MakerKit test users based on version and config */ getStandardTestUsers() { const baseUsers = [ { email: 'test@makerkit.dev', name: 'Test User', username: 'test_user', role: 'admin', password: this.getPasswordForUser('test@makerkit.dev'), metadata: { role: 'admin', isTestUser: true, createdBy: 'supa-seed-makerkit-compatibility' } }, { email: 'owner@makerkit.dev', name: 'Owner User', username: 'owner_user', role: 'owner', password: this.getPasswordForUser('owner@makerkit.dev'), metadata: { role: 'owner', isTestUser: true, canCreateTeams: true, createdBy: 'supa-seed-makerkit-compatibility' } }, { email: 'member@makerkit.dev', name: 'Member User', username: 'member_user', role: 'member', password: this.getPasswordForUser('member@makerkit.dev'), metadata: { role: 'member', isTestUser: true, createdBy: 'supa-seed-makerkit-compatibility' } }, { email: 'custom@makerkit.dev', name: 'Custom User', username: 'custom_user', role: 'custom', password: this.getPasswordForUser('custom@makerkit.dev'), metadata: { role: 'custom', isTestUser: true, customizable: true, createdBy: 'supa-seed-makerkit-compatibility' } }, { email: 'super-admin@makerkit.dev', name: 'Super Admin', username: 'super_admin', role: 'super-admin', password: this.getPasswordForUser('super-admin@makerkit.dev'), metadata: { role: 'super-admin', isTestUser: true, hasSuperAdminAccess: true, createdBy: 'supa-seed-makerkit-compatibility' } } ]; // Add custom test emails if specified const customUsers = []; if (this.config.customTestEmails) { this.config.customTestEmails.forEach((email, index) => { customUsers.push({ email, name: `Custom User ${index + 1}`, username: `custom_${index + 1}`, role: 'custom', password: this.getPasswordForUser(email), metadata: { role: 'custom', isTestUser: true, isCustomEmail: true, createdBy: 'supa-seed-makerkit-compatibility' } }); }); } return [...baseUsers, ...customUsers]; } /** * Create standard test users with proper MakerKit integration */ async createStandardTestUsers() { const users = this.getStandardTestUsers(); const created = []; const failed = []; logger_1.Logger.info(`👥 Creating ${users.length} standard MakerKit test users...`); for (const user of users) { try { logger_1.Logger.info(` Creating: ${user.email} (${user.role})`); const result = await this.createMakerKitUser(user); if (result.success) { created.push(user); logger_1.Logger.info(` ✅ Created: ${user.email}`); } else { failed.push({ user, error: result.error || 'Unknown error' }); logger_1.Logger.warn(` ⚠️ Failed: ${user.email} - ${result.error}`); } } catch (error) { failed.push({ user, error: error.message }); logger_1.Logger.error(` ❌ Error creating ${user.email}:`, error); } } logger_1.Logger.info(`✅ Created ${created.length}/${users.length} standard test users`); if (failed.length > 0) { logger_1.Logger.warn(`⚠️ ${failed.length} users failed to create`); } return { created, failed }; } /** * Create a single MakerKit user with proper auth flow and account creation */ async createMakerKitUser(user) { if (!this.schemaInfo) { throw new Error('Schema not initialized. Call initialize() first.'); } const userId = crypto.randomUUID(); try { // Step 1: Create auth user (this is always required) const { error: authError } = await this.client.auth.admin.createUser({ id: userId, email: user.email, password: user.password, email_confirm: true, user_metadata: { full_name: user.name, username: user.username, role: user.role, ...user.metadata } }); if (authError) { return { success: false, error: `Auth creation failed: ${authError.message}` }; } // Step 2: Let MakerKit triggers handle account creation, or create manually if needed const accountResult = await this.handleAccountCreation(userId, user); if (!accountResult.success) { return { success: false, error: accountResult.error }; } // Step 3: Create team account if configured and user has appropriate role if (this.config.teamAccountCreation && (user.role === 'owner' || user.role === 'admin')) { await this.createTeamAccountForUser(userId, user); } // Step 4: Set up role hierarchy if supported if (this.config.roleHierarchy && this.schemaInfo.makerkitVersion !== 'none') { await this.setupUserRoles(userId, user); } return { success: true, userId }; } catch (error) { logger_1.Logger.error(`Failed to create MakerKit user ${user.email}:`, error); return { success: false, error: error.message }; } } /** * Handle account creation based on MakerKit version and configuration */ async handleAccountCreation(userId, user) { if (!this.schemaInfo) { return { success: false, error: 'Schema not initialized' }; } try { // For modern MakerKit (v2, v3), triggers should handle account creation if (this.schemaInfo.makerkitVersion === 'v2' || this.schemaInfo.makerkitVersion === 'v3') { // Wait a moment for triggers to execute await new Promise(resolve => setTimeout(resolve, 100)); // Verify the account was created by trigger const { data: account, error } = await this.client .from('accounts') .select('id, primary_owner_user_id') .eq('primary_owner_user_id', userId) .eq('is_personal_account', true) .single(); if (!error && account) { logger_1.Logger.debug(`Account created by MakerKit trigger for ${user.email}`); return { success: true }; } logger_1.Logger.debug(`Trigger didn't create account for ${user.email}, creating manually`); } // Fallback: Create account manually using schema adapter const result = await this.schemaAdapter.createUserForSchema({ id: userId, email: user.email, name: user.name, username: user.username, bio: this.generateUserBio(user), picture_url: this.generateProfileImage(user.name) }); if (result.success) { logger_1.Logger.debug(`Manual account creation successful for ${user.email}`); return { success: true }; } else { return { success: false, error: result.error }; } } catch (error) { logger_1.Logger.error(`Account creation failed for ${user.email}:`, error); return { success: false, error: error.message }; } } /** * Create team account for users with appropriate roles */ async createTeamAccountForUser(userId, user) { if (!this.schemaInfo?.hasAccounts) { logger_1.Logger.debug('No accounts table found, skipping team account creation'); return; } try { const teamName = `${user.name}'s Team`; const { error } = await this.client .from('accounts') .insert({ id: crypto.randomUUID(), name: teamName, primary_owner_user_id: userId, is_personal_account: false, slug: `${user.username}-team`, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }); if (error) { logger_1.Logger.warn(`Failed to create team account for ${user.email}:`, error.message); } else { logger_1.Logger.debug(`Created team account "${teamName}" for ${user.email}`); } } catch (error) { logger_1.Logger.warn(`Team account creation error for ${user.email}:`, error); } } /** * Set up user roles in the role hierarchy system */ async setupUserRoles(userId, user) { if (!this.schemaInfo?.hasAccounts) return; try { // This would interact with the roles/memberships system // Implementation depends on specific MakerKit version logger_1.Logger.debug(`Setting up roles for ${user.email} with role: ${user.role}`); // For now, roles are handled through user metadata and account memberships // Full implementation would depend on the specific role system in place } catch (error) { logger_1.Logger.warn(`Role setup failed for ${user.email}:`, error); } } /** * Validate MakerKit compatibility and provide recommendations */ async validateMakerKitCompatibility() { if (!this.schemaInfo) { return { isValid: false, compatibility: 'incompatible', issues: ['Schema information not available'], recommendations: ['Run schema detection first'], detectedVersion: 'none' }; } const issues = []; const recommendations = []; const detectedVersion = this.schemaInfo.makerkitVersion; // Check for basic MakerKit requirements if (!this.schemaInfo.hasAccounts && this.config.standardTestUsers) { issues.push('No accounts table found but standard test users requested'); recommendations.push('Disable standard test users or add accounts table'); } // Check version-specific requirements if (this.config.teamAccountCreation && detectedVersion === 'v1') { issues.push('Team account creation requested but MakerKit v1 has limited support'); recommendations.push('Upgrade to MakerKit v2+ for full team account support'); } if (this.config.subscriptionSupport && !this.schemaInfo.hasAccounts) { issues.push('Subscription support requested but no subscription system detected'); recommendations.push('Add subscription tables or disable subscription support'); } // Determine compatibility level let compatibility = 'full'; if (issues.length > 3) { compatibility = 'incompatible'; } else if (issues.length > 0 || detectedVersion === 'custom') { compatibility = 'partial'; } else if (detectedVersion === 'none') { compatibility = 'custom'; } // Add positive recommendations if (detectedVersion !== 'none') { recommendations.push(`MakerKit ${detectedVersion} detected - full compatibility available`); } if (this.schemaInfo.frameworkType === 'wildernest') { recommendations.push('Wildernest platform detected - consider using outdoor platform templates'); } return { isValid: issues.length === 0, compatibility, issues, recommendations, detectedVersion }; } /** * Get password for a user (from config overrides or default) */ getPasswordForUser(email) { const overrides = this.config.overrides?.testUserPasswords; if (overrides?.perUser?.[email]) { return overrides.perUser[email]; } if (overrides?.default) { return overrides.default; } return 'password123'; // Default password } /** * Generate appropriate user bio based on role and config */ generateUserBio(user) { const roleBios = { admin: `Administrator user for testing and development. Has full system access and can manage all aspects of the application.`, owner: `Team owner with full account management privileges. Can create teams, invite members, and manage subscriptions.`, member: `Team member with standard access permissions. Can collaborate on team projects and access shared resources.`, custom: `Custom test user for specific testing scenarios. Permissions and access can be configured as needed.`, 'super-admin': `Super administrator with system-wide access. Used for testing administrative functions and system management.` }; return roleBios[user.role] || 'Test user created by supa-seed MakerKit compatibility layer.'; } /** * Generate profile image URL for user */ generateProfileImage(name) { const [firstName, lastName] = name.split(' '); return `https://ui-avatars.com/api/?name=${encodeURIComponent(firstName + '+' + (lastName || 'User'))}&background=random&bold=true&size=200`; } /** * Get comprehensive compatibility information */ getCompatibilityInfo() { if (!this.schemaInfo) { throw new Error('Schema not initialized. Call initialize() first.'); } const supportedFeatures = []; const limitations = []; const recommendedSettings = {}; // Analyze supported features based on detected schema if (this.schemaInfo.hasAccounts) { supportedFeatures.push('Standard test users'); supportedFeatures.push('Personal accounts'); recommendedSettings.personalAccountCreation = true; } if (this.schemaInfo.makerkitVersion !== 'none') { supportedFeatures.push('MakerKit integration'); supportedFeatures.push('Auth flow preservation'); recommendedSettings.preserveAuthFlow = true; recommendedSettings.preserveRLS = true; } if (this.schemaInfo.makerkitVersion === 'v2' || this.schemaInfo.makerkitVersion === 'v3') { supportedFeatures.push('Team accounts'); supportedFeatures.push('Role hierarchy'); recommendedSettings.teamAccountCreation = true; recommendedSettings.roleHierarchy = true; } // Identify limitations if (this.schemaInfo.makerkitVersion === 'v1') { limitations.push('Limited team account support'); limitations.push('Basic role system only'); } if (this.schemaInfo.makerkitVersion === 'none') { limitations.push('No MakerKit-specific features available'); limitations.push('Manual account management required'); } return { detectedVersion: this.schemaInfo.makerkitVersion, supportedFeatures, recommendedSettings, limitations }; } } exports.MakerKitCompatibilityLayer = MakerKitCompatibilityLayer; //# sourceMappingURL=makerkit-compatibility.js.map