supa-seed
Version:
A constraint-aware, framework-agnostic database seeding framework with deep PostgreSQL business logic discovery and MakerKit integration support
185 lines β’ 6.97 kB
JavaScript
"use strict";
/**
* Query Translation Layer
* FEAT-003: Memory Management & Schema Mapping Fixes - Phase 2
*
* Provides seamless query translation between framework-expected table names
* and actual schema table names. Wraps Supabase client operations.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryTranslator = void 0;
exports.createQueryTranslator = createQueryTranslator;
exports.translateTableName = translateTableName;
const logger_1 = require("../core/utils/logger");
const table_mapping_resolver_1 = require("./table-mapping-resolver");
/**
* Query translator that automatically maps table names in Supabase queries
*/
class QueryTranslator {
constructor(client, config) {
this.tableNameCache = new Map();
this.client = client;
this.config = config;
this.resolver = (0, table_mapping_resolver_1.createTableMappingResolver)(client, {
framework: config.framework,
customMappings: config.customMappings,
validateWithDatabase: config.enableValidation !== false
});
logger_1.Logger.debug('π QueryTranslator initialized:', {
framework: config.framework,
enableValidation: config.enableValidation,
enableCaching: config.enableCaching
});
}
/**
* Translate a framework-expected table name to actual table name
*/
async translateTableName(expectedTableName) {
// Check cache first if caching is enabled
if (this.config.enableCaching && this.tableNameCache.has(expectedTableName)) {
return this.tableNameCache.get(expectedTableName);
}
let actualTableName;
try {
// Determine table type based on expected name
const tableType = this.inferTableType(expectedTableName);
if (tableType) {
const result = await this.resolver.resolveTableName(expectedTableName, tableType);
actualTableName = result.actualTableName;
if (result.warnings.length > 0) {
logger_1.Logger.warn(`β οΈ Table translation warnings for '${expectedTableName}':`, result.warnings);
}
}
else {
// Fallback: use expected name as-is
actualTableName = expectedTableName;
logger_1.Logger.debug(`π No table type mapping for '${expectedTableName}', using as-is`);
}
}
catch (error) {
logger_1.Logger.warn(`β οΈ Table translation failed for '${expectedTableName}', using as-is:`, error);
actualTableName = expectedTableName;
}
// Cache the result if caching is enabled
if (this.config.enableCaching) {
this.tableNameCache.set(expectedTableName, actualTableName);
}
if (expectedTableName !== actualTableName) {
logger_1.Logger.debug(`πΊοΈ Table translated: ${expectedTableName} -> ${actualTableName}`);
}
return actualTableName;
}
/**
* Create a translated Supabase query builder
*/
async from(tableName) {
const actualTableName = await this.translateTableName(tableName);
return this.client.from(actualTableName);
}
/**
* Infer table type from expected table name for mapping resolution
*/
inferTableType(expectedTableName) {
// Map common table name patterns to table types
const patterns = {
// User tables
'users': 'userTable',
'accounts': 'userTable',
'profiles': 'userTable',
// Setup tables
'setups': 'setupTable',
'posts': 'setupTable',
// Base template tables
'base_templates': 'baseTemplateTable',
'setup_types': 'baseTemplateTable',
'templates': 'baseTemplateTable',
// Media tables
'media_attachments': 'mediaAttachmentsTable',
'attachments': 'mediaAttachmentsTable',
'media': 'mediaAttachmentsTable'
};
// Direct match
if (patterns[expectedTableName]) {
return patterns[expectedTableName];
}
// Pattern matching for partial matches
if (expectedTableName.includes('user') || expectedTableName.includes('account') || expectedTableName.includes('profile')) {
return 'userTable';
}
if (expectedTableName.includes('setup') || expectedTableName.includes('post')) {
return 'setupTable';
}
if (expectedTableName.includes('template') || expectedTableName.includes('type')) {
return 'baseTemplateTable';
}
if (expectedTableName.includes('media') || expectedTableName.includes('attachment')) {
return 'mediaAttachmentsTable';
}
return null;
}
/**
* Clear translation cache
*/
clearCache() {
this.tableNameCache.clear();
this.resolver.clearCache();
logger_1.Logger.debug('ποΈ QueryTranslator cache cleared');
}
/**
* Get translation statistics
*/
getStats() {
return {
cachedTranslations: this.tableNameCache.size,
framework: this.config.framework,
enableValidation: this.config.enableValidation !== false,
enableCaching: this.config.enableCaching !== false
};
}
/**
* Get all current table mappings
*/
async getAllMappings() {
const mappings = {};
// Common table names to check
const commonTables = [
'users', 'accounts', 'profiles',
'setups', 'posts',
'base_templates', 'setup_types', 'templates',
'media_attachments', 'attachments', 'media'
];
for (const tableName of commonTables) {
try {
const actualName = await this.translateTableName(tableName);
if (actualName !== tableName) {
mappings[tableName] = actualName;
}
}
catch (error) {
logger_1.Logger.debug(`Could not resolve mapping for table: ${tableName}`);
}
}
return mappings;
}
}
exports.QueryTranslator = QueryTranslator;
/**
* Factory function to create a query translator
*/
function createQueryTranslator(client, config) {
return new QueryTranslator(client, config);
}
/**
* Utility function for one-off table name translation
*/
async function translateTableName(client, framework, expectedTableName, customMappings) {
const translator = createQueryTranslator(client, {
framework,
customMappings,
enableValidation: true,
enableCaching: false
});
return translator.translateTableName(expectedTableName);
}
exports.default = QueryTranslator;
//# sourceMappingURL=query-translator.js.map