/** * Supabase 数据库初始化脚本 * 自动检查并初始化 Supabase 数据库表结构 */ const SupabaseDatabaseManager = require('./lib/supabase-database'); const fs = require('fs'); const path = require('path'); require('dotenv').config(); class SupabaseDatabaseSetup { constructor() { this.db = new SupabaseDatabaseManager(); } async setup() { try { console.log('🔧 开始 Supabase 数据库初始化...'); // 测试 Supabase 连接 console.log('📡 测试 Supabase 数据库连接...'); await this.db.testConnection(); console.log('✅ Supabase 数据库连接成功'); // 检查环境变量 console.log('🔍 检查环境配置...'); this.checkEnvironmentVariables(); // 验证表结构 console.log('🔍 验证数据库表结构...'); await this.verifyTables(); // 插入测试数据 console.log('📝 插入测试数据...'); await this.insertTestData(); // 测试基本功能 console.log('🧪 测试基本功能...'); await this.testBasicFunctionality(); console.log('🎉 Supabase 数据库初始化完成!'); } catch (error) { console.error('❌ Supabase 数据库初始化失败:', error.message); throw error; } finally { await this.db.close(); } } checkEnvironmentVariables() { const requiredEnvVars = [ 'SUPABASE_URL', 'SUPABASE_SERVICE_ROLE_KEY' ]; const missingVars = requiredEnvVars.filter(varName => !process.env[varName]); if (missingVars.length > 0) { throw new Error(`缺少必要的环境变量: ${missingVars.join(', ')}`); } console.log('✅ 环境配置检查通过'); console.log(` - Supabase URL: ${process.env.SUPABASE_URL}`); console.log(` - Service Role Key: ${'*'.repeat(20)}${process.env.SUPABASE_SERVICE_ROLE_KEY.slice(-10)}`); } async verifyTables() { const expectedTables = [ 'ps_push_messages', 'ps_push_types', 'message_processing_logs', 'devices', 'users', 'system_stats' ]; try { // 检查每个表是否存在 for (const tableName of expectedTables) { const { data, error } = await this.db.supabase .from(tableName) .select('*') .limit(1); if (error) { console.log(`❌ 数据表 ${tableName} 不存在或无法访问`); console.log(` 错误: ${error.message}`); console.log(` 📋 请在 Supabase Dashboard 的 SQL Editor 中执行 database/supabase-init.sql`); throw new Error(`数据表 ${tableName} 不可用: ${error.message}`); } else { console.log(`✅ 数据表 ${tableName} 可用`); } } console.log('✅ 所有必要数据表验证通过'); } catch (error) { throw new Error(`数据表验证失败: ${error.message}`); } } async insertTestData() { try { // 检查是否已有测试数据 const { data: existingData } = await this.db.supabase .from('ps_push_messages') .select('id') .eq('user_id', 'test_user_supabase') .limit(1); if (existingData && existingData.length > 0) { console.log('ℹ️ 测试数据已存在,跳过插入'); return; } // 插入测试推送消息 const testMessages = [ { pushType: 'HEALTH', userId: 'test_user_supabase', deviceId: 'device_supabase_001', H: 75, O: 98, T: 36.5, source_ip: '127.0.0.1', user_agent: 'Supabase Test Client' }, { pushType: 'SOS', userId: 'test_user_supabase_002', deviceId: 'device_supabase_002', emergencyLevel: 'HIGH', lat: 39.9042, lng: 116.4074, source_ip: '127.0.0.1', user_agent: 'Supabase Test Client' }, { pushType: 'LOCATION', userId: 'test_user_supabase_003', deviceId: 'device_supabase_003', lat: 31.2304, lng: 121.4737, accuracy: 10, source_ip: '127.0.0.1', user_agent: 'Supabase Test Client' } ]; for (const message of testMessages) { await this.db.insertPushMessage(message); } console.log('✅ 测试数据插入完成'); } catch (error) { console.warn('⚠️ 测试数据插入失败:', error.message); // 不阻止初始化过程 } } async testBasicFunctionality() { try { // 测试插入消息 const testMessage = { pushType: 'TEST', userId: 'setup_test_user', deviceId: 'setup_test_device', testData: 'Supabase setup test', source_ip: '127.0.0.1', user_agent: 'Setup Test Client' }; const insertResult = await this.db.insertPushMessage(testMessage); console.log('✅ 消息插入测试通过'); // 测试获取统计信息 const stats = await this.db.getMessageStats(1); console.log('✅ 统计信息获取测试通过'); // 测试获取健康状态 const health = await this.db.getHealthStatus(); console.log('✅ 健康状态检查测试通过'); // 测试获取消息列表 const messages = await this.db.getPushMessages({ limit: 5 }); console.log('✅ 消息列表获取测试通过'); console.log('✅ 所有基本功能测试通过'); } catch (error) { throw new Error(`基本功能测试失败: ${error.message}`); } } async showSetupInstructions() { console.log('\n📋 Supabase 数据库设置说明:'); console.log(''); console.log('1. 创建 Supabase 项目:'); console.log(' - 访问 https://supabase.com/dashboard'); console.log(' - 点击 "New project" 创建新项目'); console.log(' - 记录项目的 URL 和 API Keys'); console.log(''); console.log('2. 执行数据库初始化脚本:'); console.log(' - 在 Supabase Dashboard 中打开 "SQL Editor"'); console.log(' - 复制 database/supabase-init.sql 文件内容'); console.log(' - 粘贴到 SQL Editor 中并执行'); console.log(''); console.log('3. 配置环境变量:'); console.log(' - 复制 .env.supabase 为 .env'); console.log(' - 更新 SUPABASE_URL 为您的项目 URL'); console.log(' - 更新 SUPABASE_SERVICE_ROLE_KEY 为您的 Service Role Key'); console.log(''); console.log('4. 启用实时功能 (可选):'); console.log(' - 在 Database > Replication 中'); console.log(' - 启用 push_messages 表的实时复制'); console.log(''); } } // 如果直接运行此脚本 if (require.main === module) { const setup = new SupabaseDatabaseSetup(); // 检查是否有必要的环境变量 if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) { console.log('⚠️ 缺少 Supabase 环境配置'); setup.showSetupInstructions(); process.exit(1); } setup.setup() .then(() => { console.log('🎉 Supabase 数据库设置完成,可以启动服务了!'); console.log(''); console.log('🚀 启动服务命令:'); console.log(' node supabase-server.js'); console.log(''); process.exit(0); }) .catch((error) => { console.error('❌ Supabase 数据库设置失败:', error.message); setup.showSetupInstructions(); process.exit(1); }); } module.exports = SupabaseDatabaseSetup;