7.5 KiB
7.5 KiB
AGENTS.md
RainWeb 个人云平台(博客 + 论坛 + 密码管理器 + 管理面板聚合)。Node.js 22+(推荐 22 LTS)、CommonJS、Express 4、better-sqlite3(原生 SQLite)。前端 React + Vite + React Router(前台原生样式 Material Design 3,后台 MUI 独立应用)。无测试、无 lint——前端改动进 frontend/src/,构建产物 public/dist/(gitignored)由 server 静态服务,部署必须 npm run build。
常用命令
npm start # 生产:node server.js(serve 构建产物 + /api)
npm run dev # 开发:vite dev server(5173,/api 与 /uploads 代理到 3101)
npm run build # 构建 React 前端 → public/dist/(index.html + admin.html + assets)
npm run preview # 预览构建产物
node cli.js <cmd> # status | health | db-check | start | stop | restart | port [N] | password | captcha | config | backup | upgrade
- 端口:
.env.json(gitignored){"port": N}或环境变量PORT,默认 3001;vite 代理目标硬编码 3101(vite.config.js),后端端口改了就同步改。 - CLI:
status、health、db-check、config、backup list支持--json;health/db-check检查失败返回非 0。backup prune必须明确--keep N,默认只预览,只有--yes才删除;backup restore <file>必须服务停止并带--yes,不会默认覆盖。 - CLI 的
start/stop/restart只操作经过 cwd 与命令行双重校验、确认属于本项目server.js的 PID,停止会先优雅等待。upgrade仅供自托管机器本地执行:升级前备份,要求 git 工作区干净,执行git pull --ff-only、npm install、npm run build,服务原本运行时重启并健康检查;失败返回非 0。 - CLI 密码命令默认交互输入;
config对密码、secret、token、JWT、私钥和 API key 等敏感配置统一脱敏。验证码参数需使用受支持的类型和值。 - 验证方式:后端改动启动后
curl接口;前端改动npm run dev热更新,或npm run build后刷新验证(需强刷一次,见下)。 - 部署后浏览器必须拿新 HTML:
serveIndex响应带Cache-Control: no-store;构建产物 assets 文件名带 hash,经/assets挂载长期缓存(immutable)。若用户白屏且 console 报 "MIME type text/html",先查是否npm run build缺失/旧产物。 - 首次启动自动建库播种:管理员
admin / admin123,并写入示例博文/论坛帖子;/setup.html初始化向导(POST /api/setup/complete用setup_complete门禁,非 adminOnly——新装无 token)。
数据层(db.js)
- better-sqlite3 是原生 SQLite:
data/rainweb.db单文件持久化,写操作经事务落盘。CLI 与 server 并发写库会等待(busy_timeout 5s)而非互相覆盖,但建议不要同时执行写操作。 - 建表在
initTables();列迁移用 try/catch 包裹ALTER TABLE ... ADD COLUMN(幂等、静默失败)确保列存在。新增列必须沿用此模式,否则旧库会崩。版本化迁移在migrateSchema():PRAGMA user_version记录 schema 版本,migrations 数组按 version 升序执行(current < m.version才运行并推进版本号)——新迁移写进 migrations 数组,不要散落 try/catch。 - 站点设置存
site_settings(key/value),通过db.getSetting/setSetting读写。 - cli.js 与 server.js 统一使用 db.js 的
data/rainweb.db;旧版data.db已由 server.js 首次启动时迁移为data/rainweb.db(旧文件改名data.db.bak)。
路由(server.js)
- 集中挂载所有
/api/*(auth、admin-links、announcements、forum、blog、passwords、settings、email、profile、captcha、upload、setup、proxy、import)。新路由必须在此挂载——后面有 SPA catch-all:非/api/一律回 dist/index.html。 - 挂载顺序关键:
serveIndex('/')→/assets(dist/assets,immutable)→ static(public) →/uploads→/api/*→/admin*(dist/admin.html)→ SSR 区(/blog/:id 等)→ catch-all。新路由注意别被 catch-all 吞掉。 middleware/auth.js:Bearer JWT;SECRET=process.env.JWT_SECRET(无硬编码回退——server.js 启动时若.env.json无jwt_secret则随机生成写入并设置环境变量);adminOnly会查库复查角色(用户被删/降权立即失效)。routes/setup.js:/complete用setup_complete门禁('1' 后 403),新密码禁止等于默认admin123。routes/proxy.js:面板嵌入代理——支持Authorizationheader 或?token=query(iframe 无法带 header);有内网地址拦截(SSRF)。- 验证码:内置 SVG + reCAPTCHA/Turnstile 第三方,服务端统一
resolveCaptcha校验(builtin 走 proof JWT,第三方走 siteverify)。
前端(React + Vite)
- 源码在
frontend/:src/main.jsx(前台入口)、src/App.jsx(前台布局 Layout + 路由表)、src/pages/(前台页面)、src/components/(Layout/MarkdownRenderer/CaptchaModal/MusicEmbed/BlogSidebar)、src/admin/(后台独立应用 MUI:main.jsx + AdminLayout + pages/)、src/api/(按模块封装的 fetch 层,client.js管 token)、src/lib/utils.js、src/theme.jsx。 - 前后台是两个独立入口(Vite 多入口),仅通过整页跳转连接:前台导航「管理后台」=
<a href="/admin">(后台路由 basename/admin)。 - 路由保持 v1 的
.html后缀路径(/blog.html、/forum.html等),SPA fallback 已支持,链接不用改。 frontend/index.html含${site_name}/${site_description}/${site_favicon}占位符,构建后由 server.jsserveIndex按 site_settings 运行时替换(务必保留这 3 个占位符)。- 主题:
data-theme="dark"属性在<html>上(public/css/style.css的[data-theme="dark"]选择器),非.dark类,非 prefers-color-scheme。切换逻辑在src/theme.jsx。 - 构建:
npm run build→public/dist/(gitignored,不入库)。生产部署必须构建,否则页面 500/白屏。 - 博文/帖子内容中的
[image:文件名]/[file:文件名]标签:前台由MarkdownRenderer(marked + DOMPurify 净化)、SEO 页由ssr.js渲染为/uploads/链接。所有 markdown 渲染必须过 DOMPurify。 - 登录态:token 存 localStorage(key
token),变更通过authchange事件通知 Layout 刷新(api/client.js的notifyAuthChange)。
SSR 与 SEO
ssr.js:/blog/:id、/forum/:id、/sitemap.xml(robots.txt 的域名取自site_url设置)。SSR 页引用/css/style.css(public/css 保留,勿删)。- 已发布博文(
published=1)才会 SSR 渲染,未发布返回 404。
版本与更新
- 版本号在根目录
VERSION文件,与package.json的 version 需同步。 - Web 更新接口已移除(P0 删除
/api/update/check、/api/update/run,无 RCE 面)。升级只走自托管机器本地的cli.js upgrade:升级前备份、检查干净工作区、git pull --ff-only(本地 origin:git.rainnya.asia 镜像)+ npm install + npm run build + 服务重启/健康检查。 - 上传附件在
uploads/(gitignored,头像在uploads/avatars/,白名单扩展名),壁纸在public/wallpaper/(仅 .gitkeep 入库)。
约定
- UI 文案、代码注释、commit message 均为中文,保持一致。
- 不要提交:
node_modules/、data/*、uploads/*、.env.json、server.pid、releases/、public/dist/。