Files
dsh_shenxian/config/index.cjs
T
admin 452924d89c feat(config): 涉密内容外置到配置目录(档案 140)
把散落在代码里的真实部署值统一收进 config/,代码改为引用配置,
使仓库副本/开源导出不再带出生产域名、IP、内网路径与凭据。

新增 config/:platform.env.example(模板)· load.sh(shell 加载器)·
index.cjs(node 加载器)· README.md(键一览与优先级)。
真实值放 config/platform.env —— 已 .gitignore 排除,不入库、不进导出。

TS 侧新增 src/platform-paths.ts 作部署路径的唯一解析处(零副作用):
platformDir/stateDir/backupDir/artifactDir/installDir/scriptPath。
config.ts 接入这些字段;内置中继种子由生产 URL 改为空(改由
DSHS_OVERLAY_BOOTSTRAP_SEEDS 提供)。修掉 5 处硬编码绝对路径,
src/** 注释中性化 116 行/53 文件。

scripts/** 36 个内部运维脚本:真令牌/PG 口令/隧道目标/主机号/路径
一律改从配置取;web/wake.html 的注册域白名单改为运行时从
location.hostname 推导;test/** 夹具 119 行/13 文件改 RFC 2606/5737
保留值,并把「内置种子必须为空」固化为回归断言。

取证:tsc 0 错;npm test 373/375(唯一失败 lease 属既有);
全仓扫描(大小写不敏感)代码面涉密标识 = 0;已部署 47 并零回归
(/opt/dsh/* 未搬家,/var/lib/dshs/platform 未被误建)。
2026-09-19 15:12:19 +08:00

153 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* DSH 平台 — 脚本侧配置加载器(供 `scripts/` 下的 node 脚本使用)
*
* 与 `config/load.sh`(shell 侧)同一口径:
* **系统环境变量 > config/platform.env > 本模块的中性默认值**
*
* 用法(CJS):
* const cfg = require('../config/index.cjs')
* cfg.dataRoot() // 数据根
* cfg.stateDir() // <platformDir>/state
*
* 用法(ESM):
* import cfg from '../config/index.cjs'
*
* ⛔ 本模块**零副作用**(不建目录、不写文件);未配置文件时不报错。
*/
'use strict'
const fs = require('node:fs')
const os = require('node:os')
const path = require('node:path')
const ENV_FILE = process.env.DSH_CONFIG_FILE || path.join(__dirname, 'platform.env')
/** 读取 platform.env 到对象(缓存;解析失败返回空对象)。 */
let _fileCache = null
function fileEnv() {
if (_fileCache !== null) return _fileCache
const out = {}
try {
const text = fs.readFileSync(ENV_FILE, 'utf8')
for (const raw of text.split('\n')) {
const line = raw.trim()
if (line === '' || line.startsWith('#')) continue
const i = line.indexOf('=')
if (i <= 0) continue
const k = line.slice(0, i).trim()
let v = line.slice(i + 1).trim()
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) {
v = v.slice(1, -1)
}
if (k !== '') out[k] = v
}
} catch {
/* 文件不存在 ⇒ 全部走系统 env / 中性默认 */
}
_fileCache = out
return out
}
/** 取一个键:系统 env 优先,其次配置文件。 */
function get(key) {
const fromEnv = process.env[key]
if (fromEnv !== undefined && fromEnv !== '') return fromEnv
const fromFile = fileEnv()[key]
return fromFile !== undefined && fromFile !== '' ? fromFile : undefined
}
const isWin = process.platform === 'win32'
/** 数据根(每用户 home/ws、平台库)。 */
function dataRoot() {
return get('DSHS_DATA_ROOT') || path.join(os.homedir(), '.dshs')
}
/** 平台私有目录的父目录(其下 state / backups / artifacts)。 */
function platformDir() {
return get('DSH_PLATFORM_DIR') || path.join(dataRoot(), 'platform')
}
/** 平台状态目录。 */
function stateDir() {
return get('DSH_PLATFORM_STATE_DIR') || path.join(platformDir(), 'state')
}
/** 平台备份目录。 */
function backupDir() {
return get('DSH_PLATFORM_BACKUP_DIR') || path.join(platformDir(), 'backups')
}
/** 平台产物目录。 */
function artifactDir() {
return get('DSH_PLATFORM_ARTIFACT_DIR') || path.join(platformDir(), 'artifacts')
}
/** 代码安装根(`lib/`、`scripts/` 所在)。 */
function installDir() {
return get('DSH_INSTALL_DIR') || path.resolve(__dirname, '..')
}
/** 平台库文件路径(SQLite;Postgres 时用 dbUrl())。 */
function dbFile() {
return get('DSHS_DB_FILE') || path.join(dataRoot(), 'dshs.db')
}
/** 平台库连接串(未配置 ⇒ undefined,表示走 SQLite)。 */
function dbUrl() {
return get('DSHS_DB_URL')
}
/** 全员共享只读技能目录(`DSH_BUNDLED_SKILL_DIR`)。 */
function bundledSkillsDir() {
return get('DSHS_BUNDLED_SKILL_DIR') || path.join(dataRoot(), 'bundled-skills')
}
/** 每用户数据目录的父目录。 */
function usersDir() {
return get('DSHS_USERS_DIR') || path.join(dataRoot(), 'users')
}
/** 覆盖网络注册表 / 节点目录。 */
function overlayDir() {
return get('DSHS_OVERLAY_REGISTRY_DIR') || path.join(dataRoot(), 'overlay')
}
/** 代码安装根下的相对路径拼接(如 `installPath('lib','cli.js')`)。 */
function installPath(...parts) {
return path.join(installDir(), ...parts)
}
/** 本机在 `dsh_hosts.id` 里的标识。 */
function hostId() {
return get('DSHS_CLUSTER_HOST_ID') || get('DSHS_HOST_ID') || ''
}
/** 取多个键,一次返回(便于脚本解构)。 */
function all() {
return {
dataRoot: dataRoot(),
platformDir: platformDir(),
stateDir: stateDir(),
backupDir: backupDir(),
artifactDir: artifactDir(),
installDir: installDir(),
dbFile: dbFile(),
dbUrl: dbUrl(),
hostId: hostId(),
bundledSkillsDir: bundledSkillsDir(),
usersDir: usersDir(),
overlayDir: overlayDir(),
sep: isWin ? '\\' : '/',
}
}
module.exports = {
get, all,
dataRoot, platformDir, stateDir, backupDir, artifactDir,
installDir, installPath, dbFile, dbUrl, hostId,
bundledSkillsDir, usersDir, overlayDir,
ENV_FILE,
}