配置外置:新增 server/env.js 零依赖.env加载器(启动最先加载,真实环境变量优先);数据库迁出源码树至 ~/.starraid(.env 的 DATA_DIR 可配,支持 ~ 展开);star-raid/.env 进 gitignore + .env.example 模板;DEPLOY/AGENTS 同步。教训记录:WAL 模式迁移前必须 checkpoint(本次迁移误删 WAL 丢测试数据,用户确认无所谓)

This commit is contained in:
JOJO 2026-08-06 11:07:37 +08:00
parent 0d75304335
commit e178bc9f1b
7 changed files with 61 additions and 13 deletions

2
.gitignore vendored
View File

@ -3,4 +3,4 @@
research/ research/
.playwright-mcp/ .playwright-mcp/
cache/ cache/
star-raid/data/ star-raid/.env

View File

@ -18,10 +18,11 @@ cd star-raid
# 语法检查(每次改完 JS 必须跑server/ 也要查) # 语法检查(每次改完 JS 必须跑server/ 也要查)
for f in js/*.js server/*.js; do node --check "$f" || echo "FAIL $f"; done for f in js/*.js server/*.js; do node --check "$f" || echo "FAIL $f"; done
# 启动完整版(游戏+后端Node≥22.5 # 启动完整版(游戏+后端Node≥22.5,自动读取 star-raid/.env
node server/server.js # 或 npm start访问 http://localhost:8643 node server/server.js # 或 npm start访问 http://localhost:8643
# 注意8643 现由 node server 占用;旧 python http.server 试玩方式已废弃 # 注意8643 现由 node server 占用;旧 python http.server 试玩方式已废弃
# 数据库star-raid/data/starraid.dbgit 忽略,删除重启自动重建空库) # 数据库:默认 ~/.starraid/starraid.db源码树之外.env 的 DATA_DIR 可改)
# 警告WAL 模式,备份/迁移库文件前必须停服或 wal_checkpoint直接拷主库会丢数据
# Git仓库根 = 工作区根目录,游戏在子目录) # Git仓库根 = 工作区根目录,游戏在子目录)
git add -A && git commit -m "提交信息" git add -A && git commit -m "提交信息"
@ -41,11 +42,12 @@ star-raid/
├── css/style.css # 全部样式(像素风 UI 变量配色) ├── css/style.css # 全部样式(像素风 UI 变量配色)
├── server/ # 后端(零依赖 node:http+node:sqlite ├── server/ # 后端(零依赖 node:http+node:sqlite
│ ├── server.js # 入口:静态白名单+/api路由+安全头 │ ├── server.js # 入口:静态白名单+/api路由+安全头
│ ├── env.js # .env 加载(启动最先加载,环境变量优先)
│ ├── db.js # SQLite schemausers/sessions/user_stats/codex_unlocks/runs │ ├── db.js # SQLite schemausers/sessions/user_stats/codex_unlocks/runs
│ ├── auth.js # scrypt密码哈希+服务端session │ ├── auth.js # scrypt密码哈希+服务端session
│ ├── api.js # API处理器CODEX_KEYS 白名单(新增装备必须同步!) │ ├── api.js # API处理器CODEX_KEYS 白名单(新增装备必须同步!)
│ └── util.js # body解析/限流/输入校验 │ └── util.js # body解析/限流/输入校验
├── data/ # SQLite 数据库git 忽略 ├── .env # 本机配置(不进 git模板 .env.example
├── js/ ├── js/
│ ├── config.js # BAL 平衡参数、常量 │ ├── config.js # BAL 平衡参数、常量
│ ├── data.js # WEAPONS/SUBS/DRONES 装备数据表 │ ├── data.js # WEAPONS/SUBS/DRONES 装备数据表

9
star-raid/.env.example Normal file
View File

@ -0,0 +1,9 @@
# Star Raid 服务端配置模板 —— 复制为 .env 后按机器修改
# 监听端口
PORT=8643
# 监听地址
HOST=0.0.0.0
# 数据库目录(绝对路径,勿放源码目录内;支持 ~ 开头)
DATA_DIR=~/.starraid
# HTTPS 部署时置 1Cookie 加 Secure
COOKIE_SECURE=0

View File

@ -3,23 +3,24 @@
## 运行要求 ## 运行要求
- **Node.js ≥ 22.5**(使用内置 `node:sqlite`,零 npm 依赖,无需 `npm install` - **Node.js ≥ 22.5**(使用内置 `node:sqlite`,零 npm 依赖,无需 `npm install`
- SQLite 数据库文件自动创建于 `star-raid/data/starraid.db`(已在 .gitignore - 配置:`star-raid/.env`**不进 git**,模板见 `.env.example`,复制后按机器修改);启动时自动加载,真实环境变量优先于 .env
- 数据库文件默认在 **`~/.starraid/starraid.db`(源码目录之外)**,由 `DATA_DIR` 配置
## 启动 ## 启动
```bash ```bash
cd star-raid cd star-raid
npm start # = node server/server.js npm start # = node server/server.js(自动读取 .env
# 或指定环境变量 # 或环境变量临时覆盖(优先级高于 .env
PORT=8643 HOST=0.0.0.0 node server/server.js PORT=9000 node server/server.js
``` ```
| 环境变量 | 默认 | 说明 | | 配置项(.env / 环境变量 | 默认 | 说明 |
|---|---|---| |---|---|---|
| `PORT` | `8643` | 监听端口 | | `PORT` | `8643` | 监听端口 |
| `HOST` | `0.0.0.0` | 监听地址 | | `HOST` | `0.0.0.0` | 监听地址 |
| `DATA_DIR` | `~/.starraid` | **数据库目录(勿放源码树内)**,支持 `~` 开头 |
| `COOKIE_SECURE` | 空 | **HTTPS 部署时必须设为 `1`**Cookie 加 Secure | | `COOKIE_SECURE` | 空 | **HTTPS 部署时必须设为 `1`**Cookie 加 Secure |
| `DATA_DIR` | `star-raid/data` | 数据库目录 |
## 公网部署nginx + HTTPS 推荐) ## 公网部署nginx + HTTPS 推荐)
@ -57,5 +58,6 @@ server {
## 数据维护 ## 数据维护
- 备份:拷贝 `data/starraid.db`WAL 模式,建议先 `PRAGMA wal_checkpoint` 或直接停服拷贝) - 数据库位置:`DATA_DIR`(默认 `~/.starraid`)下的 `starraid.db` + `-wal`/`-shm`
- 重置排行榜:停服后删除 `data/` 下文件,重启自动重建空库 - **WAL 模式警告:备份/迁移前必须先合并日志**——停服后拷贝,或执行 `PRAGMA wal_checkpoint(TRUNCATE);` 再拷。直接拷主库文件会丢数据2026-08-06 已踩坑,测试数据全灭)
- 重置排行榜:停服后删除 `DATA_DIR` 下文件,重启自动重建空库

View File

@ -3,8 +3,10 @@
const { DatabaseSync } = require("node:sqlite"); const { DatabaseSync } = require("node:sqlite");
const path = require("node:path"); const path = require("node:path");
const fs = require("node:fs"); const fs = require("node:fs");
const { expandHome } = require("./env");
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, "..", "data"); /* 数据目录不放源码树:默认 ~/.starraid可用 DATA_DIR 环境变量 / .env 覆盖 */
const DATA_DIR = expandHome(process.env.DATA_DIR || path.join(require("node:os").homedir(), ".starraid"));
fs.mkdirSync(DATA_DIR, { recursive: true }); fs.mkdirSync(DATA_DIR, { recursive: true });
const db = new DatabaseSync(path.join(DATA_DIR, "starraid.db")); const db = new DatabaseSync(path.join(DATA_DIR, "starraid.db"));

32
star-raid/server/env.js Normal file
View File

@ -0,0 +1,32 @@
"use strict";
/* ================= .env =================
启动时最先加载读取 star-raid/.env注入 process.env
约定真实环境变量优先已存在的不覆盖.env 仅作默认 */
const fs = require("node:fs");
const path = require("node:path");
const ENV_PATH = path.join(__dirname, "..", ".env");
if (fs.existsSync(ENV_PATH)) {
for (const line of fs.readFileSync(ENV_PATH, "utf8").split(/\r?\n/)) {
const s = line.trim();
if (!s || s.startsWith("#")) continue;
const i = s.indexOf("=");
if (i <= 0) continue;
const key = s.slice(0, i).trim();
let val = s.slice(i + 1).trim();
// 去掉成对引号
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'")))
val = val.slice(1, -1);
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) && process.env[key] === undefined)
process.env[key] = val;
}
}
/* 路径展开:支持 ~ 开头 */
function expandHome(p) {
if (p === "~") return require("node:os").homedir();
if (p && p.startsWith("~/")) return require("node:os").homedir() + p.slice(1);
return p;
}
module.exports = { expandHome };

View File

@ -2,6 +2,7 @@
/* ================= Star Raid ================= /* ================= Star Raid =================
零依赖node:http + node:sqlite静态资源白名单 + /api 路由 + 安全头 */ 零依赖node:http + node:sqlite静态资源白名单 + /api 路由 + 安全头 */
const http = require("node:http"); const http = require("node:http");
require("./env"); // 必须先于 db 加载:数据库目录等配置来自 .env
const fs = require("node:fs"); const fs = require("node:fs");
const path = require("node:path"); const path = require("node:path");
const db = require("./db"); const db = require("./db");