feat: 实现微博签到小程序功能
- 实现签到主页面,包含签到按钮、连续天数、今日状态展示 - 实现签到记录页面,包含日历视图和签到历史列表 - 实现个人中心页面,包含用户信息和签到统计 - 后端实现签到、查询状态、查询历史三个接口 - 使用 Supabase 存储签到记录数据 - 采用星空主题设计,深蓝紫渐变背景 + 金色星光强调色 - 完成所有接口测试和前后端匹配验证 - 通过 ESLint 检查和编译验证
This commit is contained in:
115
server/src/storage/database/supabase-client.ts
Executable file
115
server/src/storage/database/supabase-client.ts
Executable file
@@ -0,0 +1,115 @@
|
||||
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
let envLoaded = false;
|
||||
|
||||
interface SupabaseCredentials {
|
||||
url: string;
|
||||
anonKey: string;
|
||||
}
|
||||
|
||||
function loadEnv(): void {
|
||||
if (envLoaded || (process.env.COZE_SUPABASE_URL && process.env.COZE_SUPABASE_ANON_KEY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
require('dotenv').config();
|
||||
if (process.env.COZE_SUPABASE_URL && process.env.COZE_SUPABASE_ANON_KEY) {
|
||||
envLoaded = true;
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// dotenv not available
|
||||
}
|
||||
|
||||
const pythonCode = `
|
||||
import os
|
||||
import sys
|
||||
try:
|
||||
from coze_workload_identity import Client
|
||||
client = Client()
|
||||
env_vars = client.get_project_env_vars()
|
||||
client.close()
|
||||
for env_var in env_vars:
|
||||
print(f"{env_var.key}={env_var.value}")
|
||||
except Exception as e:
|
||||
print(f"# Error: {e}", file=sys.stderr)
|
||||
`;
|
||||
|
||||
const output = execSync(`python3 -c '${pythonCode.replace(/'/g, "'\"'\"'")}'`, {
|
||||
encoding: 'utf-8',
|
||||
timeout: 10000,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
const lines = output.trim().split('\n');
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('#')) continue;
|
||||
const eqIndex = line.indexOf('=');
|
||||
if (eqIndex > 0) {
|
||||
const key = line.substring(0, eqIndex);
|
||||
let value = line.substring(eqIndex + 1);
|
||||
if ((value.startsWith("'") && value.endsWith("'")) ||
|
||||
(value.startsWith('"') && value.endsWith('"'))) {
|
||||
value = value.slice(1, -1);
|
||||
}
|
||||
if (!process.env[key]) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
envLoaded = true;
|
||||
} catch {
|
||||
// Silently fail
|
||||
}
|
||||
}
|
||||
|
||||
function getSupabaseCredentials(): SupabaseCredentials {
|
||||
loadEnv();
|
||||
|
||||
const url = process.env.COZE_SUPABASE_URL;
|
||||
const anonKey = process.env.COZE_SUPABASE_ANON_KEY;
|
||||
|
||||
if (!url) {
|
||||
throw new Error('COZE_SUPABASE_URL is not set');
|
||||
}
|
||||
if (!anonKey) {
|
||||
throw new Error('COZE_SUPABASE_ANON_KEY is not set');
|
||||
}
|
||||
|
||||
return { url, anonKey };
|
||||
}
|
||||
|
||||
function getSupabaseClient(token?: string): SupabaseClient {
|
||||
const { url, anonKey } = getSupabaseCredentials();
|
||||
|
||||
if (token) {
|
||||
return createClient(url, anonKey, {
|
||||
global: {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
db: {
|
||||
timeout: 60000,
|
||||
},
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return createClient(url, anonKey, {
|
||||
db: {
|
||||
timeout: 60000,
|
||||
},
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { loadEnv, getSupabaseCredentials, getSupabaseClient };
|
||||
Reference in New Issue
Block a user