/** * Database service for user data operations */ import { saveUserDataLocal, getUserByUidLocal, initLocalDb } from './local-db-service'; /** * Initialize the database schema * @param {Object} env - Environment variables containing D1 database binding * @returns {Promise} - Whether initialization was successful */ async function initializeDatabase(env) { try { if (!env.PROMPT_MANAGER_DB) { console.log('D1 database binding not found, skipping initialization'); return false; } // Create user_data table if it doesn't exist try { // Use a single-line SQL statement to avoid parsing issues with D1 await env.PROMPT_MANAGER_DB.exec(`CREATE TABLE IF NOT EXISTS user_data (id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE NOT NULL, email TEXT NOT NULL, firebase_uid TEXT, firstname TEXT, lastname TEXT, company_name TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);`); // Create indexes in a single-line format as well await env.PROMPT_MANAGER_DB.exec(`CREATE INDEX IF NOT EXISTS idx_user_data_uid ON user_data(uid);`); await env.PROMPT_MANAGER_DB.exec(`CREATE INDEX IF NOT EXISTS idx_user_data_email ON user_data(email);`); console.log('Database schema initialized successfully'); } catch (dbError) { console.error('Error creating schema:', dbError); // If we can't create the table, just return mock data return false; } return true; } catch (error) { console.error('Error initializing database schema:', error); return false; } } /** * Save user data from decrypted cookie to D1 database * @param {Object} userData - The decrypted user data * @param {Object} env - Environment variables containing D1 database binding * @returns {Promise} - Result of the operation */ export async function saveUserData(userData, env) { try { // Initialize database schema if needed await initializeDatabase(env); // Check if required database binding exists if (!env.PROMPT_MANAGER_DB) { console.log('D1 database binding not found, using local database'); // Use our local database implementation return await saveUserDataLocal(userData); } // Extract user data from the decrypted cookie const { uid, email, firebase_uid, firstname, lastname, company_name } = userData; // Validate required fields if (!uid || !email) { return { success: false, error: 'Missing required fields (uid, email)' }; } try { // Check if user already exists const existingUser = await env.PROMPT_MANAGER_DB.prepare( 'SELECT id FROM user_data WHERE uid = ?' ).bind(uid).first(); let result; if (existingUser) { // Update existing user result = await env.PROMPT_MANAGER_DB.prepare(` UPDATE user_data SET email = ?, firebase_uid = ?, firstname = ?, lastname = ?, company_name = ?, updated_at = CURRENT_TIMESTAMP WHERE uid = ? `).bind(email, firebase_uid, firstname, lastname, company_name, uid).run(); return { success: true, message: 'User data updated successfully', updated: true, uid }; } else { // Insert new user result = await env.PROMPT_MANAGER_DB.prepare(` INSERT INTO user_data (uid, email, firebase_uid, firstname, lastname, company_name) VALUES (?, ?, ?, ?, ?, ?) `).bind(uid, email, firebase_uid, firstname, lastname, company_name).run(); return { success: true, message: 'User data saved successfully', updated: false, uid }; } } catch (dbError) { console.error('Database operation failed:', dbError); // Return success with the data even if DB operation failed return { success: true, message: 'User data processed (DB operation failed)', error: dbError.message, updated: false, uid, userData }; } } catch (error) { console.error('Error saving user data:', error); return { success: false, error: error.message }; } } /** * Get user data by uid * @param {string} uid - The user's unique identifier * @param {Object} env - Environment variables containing D1 database binding * @returns {Promise} - User data or null if not found */ export async function getUserByUid(uid, env) { try { // Initialize database schema if needed await initializeDatabase(env); if (!env.PROMPT_MANAGER_DB) { console.log('D1 database binding not found, using local database'); // Use our local database implementation return await getUserByUidLocal(uid); } const user = await env.PROMPT_MANAGER_DB.prepare( 'SELECT * FROM user_data WHERE uid = ?' ).bind(uid).first(); return user; } catch (error) { console.error('Error getting user data:', error); return null; } }