supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
264 lines • 9.68 kB
JavaScript
"use strict";
/**
* Framework-Aware Adapter
* Bridges the existing schema-adapter with the new framework strategy system
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrameworkAdapter = void 0;
const schema_adapter_1 = require("../../core/schema-adapter");
const strategy_registry_1 = require("./strategy-registry");
const makerkit_strategy_1 = require("./strategies/makerkit-strategy");
const generic_strategy_1 = require("./strategies/generic-strategy");
const logger_1 = require("../../core/utils/logger");
class FrameworkAdapter {
constructor(client, config, options = {}) {
this.client = client;
this.options = {
enableSchemaCache: true,
enableConstraintHandling: true,
debug: false,
...options
};
// Initialize schema adapter for backward compatibility
this.schemaAdapter = new schema_adapter_1.SchemaAdapter(client, config);
// Initialize strategy registry
this.strategyRegistry = new strategy_registry_1.StrategyRegistry(client, {
enableFallback: true,
minimumConfidence: 0.3,
debug: this.options.debug
});
}
/**
* Initialize the framework adapter
*/
async initialize() {
try {
logger_1.Logger.debug('Initializing framework adapter...');
// Register available strategies
await this.registerStrategies();
// Detect schema and select strategy
await this.detectAndSelectStrategy();
logger_1.Logger.success(`Framework adapter initialized with ${this.currentStrategy.name} strategy`);
}
catch (error) {
logger_1.Logger.error('Failed to initialize framework adapter:', error);
throw error;
}
}
/**
* Register all available strategies
*/
async registerStrategies() {
const strategies = [
new makerkit_strategy_1.MakerKitStrategy(),
new generic_strategy_1.GenericStrategy()
];
await this.strategyRegistry.registerAll(strategies);
logger_1.Logger.debug(`Registered ${strategies.length} framework strategies`);
}
/**
* Detect schema and select appropriate strategy
*/
async detectAndSelectStrategy() {
try {
// Get schema information from existing adapter
const schemaInfo = await this.schemaAdapter.detectSchema();
// Convert to new schema format
const databaseSchema = await this.convertSchemaInfo(schemaInfo);
// Select strategy
this.currentSelection = await this.strategyRegistry.selectStrategyWithOverride(databaseSchema, this.options.frameworkOverride);
this.currentStrategy = this.currentSelection.strategy;
logger_1.Logger.info(`Selected strategy: ${this.currentStrategy.name} (${this.currentSelection.reason})`);
logger_1.Logger.info(`Detection confidence: ${(this.currentSelection.detection.confidence * 100).toFixed(1)}%`);
if (this.options.debug) {
logger_1.Logger.debug('Detection details:', {
framework: this.currentSelection.detection.framework,
version: this.currentSelection.detection.version,
features: this.currentSelection.detection.detectedFeatures,
recommendations: this.currentSelection.detection.recommendations
});
}
}
catch (error) {
logger_1.Logger.error('Strategy selection failed:', error);
throw error;
}
}
/**
* Convert existing SchemaInfo to new DatabaseSchema format
*/
async convertSchemaInfo(schemaInfo) {
// For now, create a basic schema representation
// This will be enhanced as we build the constraint discovery system
const schema = {
tables: [],
functions: [],
triggers: [],
constraints: []
};
// Add basic table information based on detected tables
const tableNames = [];
if (schemaInfo.hasAccounts)
tableNames.push('accounts');
if (schemaInfo.hasProfiles)
tableNames.push('profiles');
if (schemaInfo.hasSetups)
tableNames.push('setups');
if (schemaInfo.hasTeams)
tableNames.push('teams');
if (schemaInfo.hasOrganizations)
tableNames.push('organizations');
// Add custom tables
tableNames.push(...schemaInfo.customTables);
// Create basic table info (will be enhanced with constraint discovery)
schema.tables = tableNames.map(name => ({
name,
columns: [], // Will be populated by constraint discovery
relationships: []
}));
// Add framework-specific function detection
if (schemaInfo.makerkitVersion !== 'none') {
// Add known MakerKit functions
schema.functions.push({
name: 'kit.setup_new_user',
schema: 'public',
arguments: [],
returnType: 'void'
});
}
return schema;
}
/**
* Create a user using the selected strategy
*/
async createUser(userData) {
if (!this.currentStrategy) {
throw new Error('Framework adapter not initialized. Call initialize() first.');
}
const startTime = Date.now();
try {
logger_1.Logger.debug(`Creating user with ${this.currentStrategy.name} strategy: ${userData.email}`);
const user = await this.currentStrategy.createUser(userData);
const executionTime = Date.now() - startTime;
return {
success: true,
data: user,
errors: [],
warnings: [],
appliedFixes: [],
strategy: this.currentStrategy.name,
executionTime
};
}
catch (error) {
const executionTime = Date.now() - startTime;
logger_1.Logger.error(`User creation failed with ${this.currentStrategy.name} strategy:`, error);
return {
success: false,
errors: [error.message],
warnings: [],
appliedFixes: [],
strategy: this.currentStrategy.name,
executionTime
};
}
}
/**
* Get the current strategy
*/
getCurrentStrategy() {
return this.currentStrategy;
}
/**
* Get strategy selection details
*/
getStrategySelection() {
return this.currentSelection;
}
/**
* Get framework recommendations
*/
getRecommendations() {
if (!this.currentStrategy) {
return ['Initialize framework adapter to get recommendations'];
}
const strategyRecommendations = this.currentStrategy.getRecommendations();
const detectionRecommendations = this.currentSelection?.detection.recommendations || [];
return [
...strategyRecommendations,
...detectionRecommendations
];
}
/**
* Check if a specific feature is supported
*/
supportsFeature(feature) {
return this.currentStrategy?.supportsFeature(feature) || false;
}
/**
* Get schema information (backward compatibility)
*/
async getSchemaInfo() {
return await this.schemaAdapter.detectSchema();
}
/**
* Get legacy user creation strategy (backward compatibility)
*/
getUserCreationStrategy() {
return this.schemaAdapter.getUserCreationStrategy();
}
/**
* Validate the current strategy setup
*/
async validateStrategy() {
if (!this.currentStrategy || !this.currentSelection) {
return {
valid: false,
issues: ['No strategy selected'],
recommendations: ['Initialize framework adapter']
};
}
const schema = await this.convertSchemaInfo(await this.getSchemaInfo());
return await this.strategyRegistry.validateStrategy(this.currentStrategy.name, schema);
}
/**
* Override the current strategy
*/
async overrideStrategy(strategyName) {
const strategy = this.strategyRegistry.getStrategy(strategyName);
if (!strategy) {
throw new Error(`Strategy '${strategyName}' not found`);
}
this.currentStrategy = strategy;
// Create a new selection result
const schema = await this.convertSchemaInfo(await this.getSchemaInfo());
const detection = await strategy.detect(schema);
this.currentSelection = {
strategy,
detection,
reason: 'manual_override'
};
logger_1.Logger.info(`Strategy overridden to: ${strategyName}`);
}
/**
* Get all available strategies
*/
getAvailableStrategies() {
return this.strategyRegistry.getStrategies().map(s => s.name);
}
/**
* Get detection results for all strategies
*/
async getAllDetectionResults() {
const schema = await this.convertSchemaInfo(await this.getSchemaInfo());
return await this.strategyRegistry.getAllDetectionResults(schema);
}
/**
* Get the currently active strategy
*/
getActiveStrategy() {
return this.currentStrategy;
}
}
exports.FrameworkAdapter = FrameworkAdapter;
//# sourceMappingURL=framework-adapter.js.map