- 实现签到主页面,包含签到按钮、连续天数、今日状态展示 - 实现签到记录页面,包含日历视图和签到历史列表 - 实现个人中心页面,包含用户信息和签到统计 - 后端实现签到、查询状态、查询历史三个接口 - 使用 Supabase 存储签到记录数据 - 采用星空主题设计,深蓝紫渐变背景 + 金色星光强调色 - 完成所有接口测试和前后端匹配验证 - 通过 ESLint 检查和编译验证
116 lines
2.6 KiB
TypeScript
Executable File
116 lines
2.6 KiB
TypeScript
Executable File
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 };
|