Files
akmon/push-receiver-service/setup-supabase.js
2026-01-20 08:04:15 +08:00

250 lines
8.9 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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;