- 新增 MongoDB 存储层实现英雄、预设和版本数据的持久化 - 新增 push-meta 和 migrate-to-mongo 脚本支持数据同步迁移 - 支持开发版和线上设计版双模式运行 - 新增版本闸门机制,线上设计版落后时进入只读模式 - 优化前端 API 配置适配不同部署环境 - 新增线上设计版静态资源托管和路由回退
76 lines
2.8 KiB
JavaScript
76 lines
2.8 KiB
JavaScript
/**
|
||
* 英雄/预设存储层:开发版与线上设计版统一读写线上 MongoDB。
|
||
* - heroes 集合:每个英雄一条文档,uuid 唯一索引
|
||
* - templates 集合:预设库(_id='presets' 单文档)
|
||
* - meta 集合:版本闸门(_id='version' 单文档,schemaVersion 由开发版推送 meta 时写入)
|
||
* 技能/Buff 底座不进数据库,开发版走 TS 编译,线上版走 meta.json 快照。
|
||
*/
|
||
import { MongoClient } from 'mongodb'
|
||
|
||
const MONGO_URL = process.env.MONGO_URL || ''
|
||
const DB_NAME = process.env.MONGO_DB || 'heroconfig'
|
||
|
||
let client = null
|
||
let db = null
|
||
|
||
/** 惰性连接 MongoDB(单例复用) */
|
||
async function mongo() {
|
||
if (db) return db
|
||
if (!MONGO_URL) throw new Error('未配置 MONGO_URL 环境变量')
|
||
client = new MongoClient(MONGO_URL)
|
||
await client.connect()
|
||
db = client.db(DB_NAME)
|
||
// uuid 唯一索引:保证英雄按 uuid 幂等覆盖
|
||
await db.collection('heroes').createIndex({ uuid: 1 }, { unique: true })
|
||
return db
|
||
}
|
||
|
||
/** 读取全部英雄(按 uuid 升序,剥离 Mongo 内部 _id) */
|
||
export async function getHeroes() {
|
||
const docs = await (await mongo()).collection('heroes').find().sort({ uuid: 1 }).toArray()
|
||
return docs.map(({ _id, ...h }) => h)
|
||
}
|
||
|
||
/** 全量覆盖:upsert 传入英雄,并删除库中多余的 uuid */
|
||
export async function saveHeroes(heroes) {
|
||
const col = (await mongo()).collection('heroes')
|
||
for (const h of heroes) {
|
||
await col.replaceOne({ uuid: h.uuid }, h, { upsert: true })
|
||
}
|
||
await col.deleteMany({ uuid: { $nin: heroes.map((h) => h.uuid) } })
|
||
}
|
||
|
||
/** 读取预设库(无文档时返回空池) */
|
||
export async function getTemplates() {
|
||
const doc = await (await mongo()).collection('templates').findOne({ _id: 'presets' })
|
||
return {
|
||
triggerPresets: Array.isArray(doc?.triggerPresets) ? doc.triggerPresets : [],
|
||
fieldPresets: Array.isArray(doc?.fieldPresets) ? doc.fieldPresets : [],
|
||
}
|
||
}
|
||
|
||
/** 全量覆盖预设库 */
|
||
export async function saveTemplates(triggerPresets, fieldPresets) {
|
||
await (await mongo())
|
||
.collection('templates')
|
||
.replaceOne({ _id: 'presets' }, { _id: 'presets', triggerPresets, fieldPresets }, { upsert: true })
|
||
}
|
||
|
||
/** 读取库中数据结构版本(首次为 0) */
|
||
export async function getSchemaVersion() {
|
||
const doc = await (await mongo()).collection('meta').findOne({ _id: 'version' })
|
||
return doc?.schemaVersion ?? 0
|
||
}
|
||
|
||
/**
|
||
* 推送数据结构版本:只允许升不允许降,避免旧部署误把版本刷低导致线上版解锁写入。
|
||
* @returns {Promise<number>} 写入后的实际版本
|
||
*/
|
||
export async function bumpSchemaVersion(version) {
|
||
const col = (await mongo()).collection('meta')
|
||
const cur = await getSchemaVersion()
|
||
const next = Math.max(cur, version)
|
||
await col.replaceOne({ _id: 'version' }, { _id: 'version', schemaVersion: next, updatedAt: new Date() }, { upsert: true })
|
||
return next
|
||
}
|