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
JavaScript
;
/**
* 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