forked from imbytecat/fullstack-starter
- 将 db 中间件重命名为 dbProvider,同时保留 db 作为别名以避免破坏现有路由。 - 记录并解决开发环境中数据库迁移和类型检查工具使用问题。 - 完善许可证激活功能,新增数据表与初始化逻辑,实现UPSERT操作及单例模式,添加RPC接口支持,修复时间戳类型不匹配问题。 - 创建设备信息和待办事项数据表,并为设备指纹添加唯一索引。 - 添加许可证激活表及指纹唯一索引 - 添加设备信息和待办事项表的数据库模式快照,包含字段定义、主键约束及指纹唯一索引。 - 添加初始数据库模式快照,包含设备信息、许可证激活和待办事项三张表的结构定义。 - 添加新的迁移日志文件以记录数据库版本变更和迁移步骤 - 确保设备信息在数据库中正确初始化,使用硬件指纹唯一标识设备并支持并发安全的单例模式初始化。 - 初始化许可证激活记录,确保基于硬件指纹创建或更新激活信息。 - 添加许可证激活管理页面,包含设备指纹展示、许可证输入激活功能及激活状态实时反馈。 - 添加许可证页面路由配置并更新相关路由类型和路径映射。 - 添加设备信息获取与许可证设置的接口契约定义,包含数据校验 schema 和接口输入输出规范。 - 添加设备和许可证合约接口到导出契约对象中 - 添加许可证相关API契约,定义获取激活状态和激活许可证的输入输出结构。 - 初始化设备和许可激活状态,并将数据库中间件重命名为dbProvider,同时导出原始db名称以保持兼容性。 - 添加设备信息获取和许可证设置接口,确保设备初始化并安全处理数据读写。 - 添加设备和许可证路由到API路由器中。 - 添加许可证激活状态查询和激活功能,支持通过数据库记录管理许可证信息并返回激活时间戳。 - 添加设备信息表结构,包含指纹、指纹质量等级、许可证及激活时间字段。 - 添加设备信息和许可证激活相关数据模型导出 - 添加许可证激活记录表,包含指纹、许可证信息及激活时间字段。
62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import { getHardwareFingerprint } from '@/lib/fingerprint'
|
|
import { getDB } from '@/server/db'
|
|
import { deviceInfoTable } from '@/server/db/schema'
|
|
|
|
let initPromise: Promise<void> | null = null
|
|
|
|
/**
|
|
* 确保设备信息已在数据库中初始化
|
|
* 使用单例模式防止并发重复初始化
|
|
*/
|
|
export async function ensureDeviceInitialized(): Promise<void> {
|
|
if (initPromise) {
|
|
return initPromise
|
|
}
|
|
|
|
initPromise = (async () => {
|
|
try {
|
|
const db = getDB()
|
|
|
|
// 获取硬件指纹
|
|
let result: { fingerprint: string; quality: 'strong' | 'medium' | 'weak' }
|
|
try {
|
|
result = await getHardwareFingerprint({
|
|
cacheTtlMs: 10 * 60 * 1000,
|
|
includePrimaryDisk: true,
|
|
})
|
|
} catch (error) {
|
|
console.error('Failed to get hardware fingerprint:', error)
|
|
// 回退逻辑
|
|
result = {
|
|
fingerprint: `unknown-${Date.now()}`,
|
|
quality: 'weak' as const,
|
|
}
|
|
}
|
|
|
|
// 使用 UPSERT 逻辑更新或插入设备信息
|
|
await db
|
|
.insert(deviceInfoTable)
|
|
.values({
|
|
fingerprint: result.fingerprint,
|
|
fingerprintQuality: result.quality,
|
|
license: null,
|
|
licenseActivatedAt: null,
|
|
})
|
|
.onConflictDoUpdate({
|
|
target: deviceInfoTable.fingerprint,
|
|
set: {
|
|
fingerprintQuality: result.quality,
|
|
updatedAt: new Date(),
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('Failed to initialize device info:', error)
|
|
// 重置 promise 以允许重试
|
|
initPromise = null
|
|
throw error
|
|
}
|
|
})()
|
|
|
|
return initPromise
|
|
}
|