Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions db-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,24 @@ function buildModuleList() {
.filter(Boolean);
}

function resolveModuleByKey(key: string) {
function resolveModuleByKey(key: string): { id: string; configKey: string; canDisable: boolean } | null {
const k = String(key || "").trim();
const catalog = loadModuleCatalog();
return catalog.find(
const raw = catalog.find(
(m) =>
String((m as Record<string, unknown>).id || "") === k ||
String((m as Record<string, unknown>).configKey || (m as Record<string, unknown>).config_key || "") === k
) as { id: string; configKey: string; canDisable: boolean } | null;
) as Record<string, unknown> | undefined;
if (!raw) return null;
const id = String(raw.id || "").trim();
const configKey = String(raw.configKey || raw.config_key || "").trim();
if (!id || !configKey) return null;
/* 与 buildModuleList.can_disable 同源:缺省视为可禁用,避免 list/disable 契约漂移(LSP) */
return {
id,
configKey,
canDisable: raw.canDisable !== false,
};
}

function setModuleEnabled(mod: { id: string; canDisable: boolean }, enabled: boolean) {
Expand Down
58 changes: 15 additions & 43 deletions db-server/src/routes/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,50 +71,21 @@ function createConfigRoutes({ json, projectRoot, listModules, getModuleTokens }:
function getAllConfigs(): Record<string, unknown> {
const modules = typeof listModules === "function" ? listModules() : [];
const module_tokens = typeof getModuleTokens === "function" ? getModuleTokens() : {};
/* 各资源走与单资源 GET 相同的 helper,避免 configs/all 与专用路由形状漂移(DRY/LSP) */
return {
// 与 /api/sfmc/modules 同源;ConfigManager.init 一次拉齐启停态(DRY)
modules,
// loopback-only 下发;SAPI 无 fs,靠此注入模块身份(DIP)
module_tokens,
settings: stripMeta(readJson(configPath(projectRoot, "settings.json")) as Record<string, unknown> | null),
areas: (arrayOrEmpty(readJson(configPath(projectRoot, "areas.json"))) as Array<Record<string, unknown>>)
.filter((r) => r && r.module && r.dimension != null)
.map((r) => stripMetaDeep(r)),
permissions: (
arrayOrEmpty(readJson(configPath(projectRoot, "permissions.json"))) as Array<Record<string, unknown>>
)
.filter((r) => r && r.player_name)
.map((r) => stripMetaDeep(r)),
banned_items: (arrayOrEmpty(readJson(configPath(projectRoot, "banned_items.json"))) as Array<string>)
.filter((i) => typeof i === "string" && i && !i.startsWith("_"))
.map((id) => ({ item_id: id })),
clean: stripMetaDeep(readJson(configPath(projectRoot, "clean.json")) ?? {}),
grids: (arrayOrEmpty(readJson(configPath(projectRoot, "grids.json"))) as Array<Record<string, unknown>>)
.filter((r) => r && r.name)
.map((r) => stripMetaDeep(r)),
peace_filters: (
arrayOrEmpty(readJson(configPath(projectRoot, "peace_filters.json"))) as Array<Record<string, unknown>>
)
.filter((r) => r && r.family)
.map((r) => stripMetaDeep(r)),
questions: (arrayOrEmpty(readJson(configPath(projectRoot, "questions.json"))) as Array<Record<string, unknown>>)
.filter((r) => r && r.question)
.map((r, idx: number) => {
const clean = stripMetaDeep(r) as Record<string, unknown>;
return {
id: idx + 1,
weight: clean.weight ?? 1,
question: clean.question,
answers: clean.answers ?? [],
msg_right: clean.msg_right ?? "",
msg_wrong: clean.msg_wrong ?? "",
explanation: clean.explanation ?? "",
min_rank: clean.min_rank ?? null,
max_rank: clean.max_rank ?? null,
rewards: clean.rewards ?? [],
punishments: clean.punishments ?? [],
};
}),
areas: getAreas(),
permissions: getPermissions(),
// ConfigManager.AllConfigs.banned_items: string[];勿再包成 {item_id}
banned_items: getBannedItems(),
clean: getClean(),
grids: getGrids(),
peace_filters: getPeaceFilters(),
questions: getQA(),
};
}

Expand Down Expand Up @@ -153,10 +124,11 @@ function createConfigRoutes({ json, projectRoot, listModules, getModuleTokens }:
.map((r) => stripMetaDeep(r));
}

function getBannedItems(): Array<{ item_id: string }> {
return (arrayOrEmpty(readCfg("banned_items.json")) as Array<string>)
.filter((i) => typeof i === "string" && i && !i.startsWith("_"))
.map((id) => ({ item_id: id }));
/** 返回 string[] —— 与 ConfigManager / GET /banned_items.items 契约一致。 */
function getBannedItems(): string[] {
return (arrayOrEmpty(readCfg("banned_items.json")) as Array<string>).filter(
(i) => typeof i === "string" && i && !i.startsWith("_")
);
}

function getClean(): { item_max: number; poll_interval: number } {
Expand Down Expand Up @@ -248,7 +220,7 @@ function createConfigRoutes({ json, projectRoot, listModules, getModuleTokens }:
}
if (requestPath === "/api/sfmc/banned_items") {
if (method === "GET") {
json(res, { items: getBannedItems().map((x) => x.item_id) });
json(res, { items: getBannedItems() });
return true;
}
}
Expand Down
14 changes: 12 additions & 2 deletions modules/sdk/@sfmc-sdk/src/module-loader/internal/config-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ type AllConfigs = {
end_z: number;
}>;
permissions: Array<{ player_name: string; level: number }>;
banned_items: string[];
/** 权威为 string[];兼容过渡期 {item_id} 信封 */
banned_items: Array<string | { item_id: string }>;
clean: { item_max?: number; poll_interval?: number };
grids: Array<{
name: string;
Expand Down Expand Up @@ -275,7 +276,16 @@ export class ConfigManager {
ConfigManager.cache.permissions[p.player_name] = p.level;
}

ConfigManager.cache.bannedItems = (all.banned_items || []).filter((s) => typeof s === "string");
/* 兼容旧信封 {item_id};权威形状为 string[](与 configs/all / GET banned_items 对齐) */
ConfigManager.cache.bannedItems = (all.banned_items || [])
.map((s) => {
if (typeof s === "string") return s;
if (s && typeof s === "object" && typeof (s as { item_id?: unknown }).item_id === "string") {
return (s as { item_id: string }).item_id;
}
return null;
})
.filter((s): s is string => typeof s === "string" && s.length > 0);

if (all.clean) {
ConfigManager.cache.clean = {
Expand Down
4 changes: 3 additions & 1 deletion modules/sdk/@sfmc-sdk/src/sapi/service/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export const service = {
authOpts()
);
if (!res.ok) {
throw new ServiceError(res.error ?? "service_error", "internal", res.status);
// LSP:与 db 客户端一致,保留服务端 code,勿一律打成 internal
const data = res.data as { error?: string; code?: string } | undefined;
throw new ServiceError(data?.error ?? res.error ?? "service_error", data?.code || "internal", res.status);
}
return (res.data as { ok: true; result: T }).result;
},
Expand Down
3 changes: 0 additions & 3 deletions sfmc/src/module-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ export const MODULE_CMD_NAMES = ["module", "mod"] as const;

export type ModuleCmdName = (typeof MODULE_CMD_NAMES)[number];

/** HELP 中主名+别名展示串(权威来源 MODULE_CMD_NAMES),如 "module/mod"。 */
export const MODULE_CMD_ALIAS_LABEL = MODULE_CMD_NAMES.join("/");

/** 判断是否为 module 顶层命令(含别名);避免 main/repl 再硬编码 case。 */
export function isModuleCommand(cmd: string | undefined): cmd is ModuleCmdName {
return !!cmd && (MODULE_CMD_NAMES as readonly string[]).includes(cmd);
Expand Down
3 changes: 0 additions & 3 deletions sfmc/src/repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ function setRaw(v: boolean): void {
} catch {}
}

/** HELP 行首:把 MODULE_CMD_NAMES 着色后用 / 拼接(如 module/mod)。 */
const MODULE_HELP_LABEL = MODULE_CMD_NAMES.map((n) => c.green(n)).join("/");

const welcome = `\n
${c.text(`⠪⡁⡯⠁`)}
${c.text(`⠒⠁⠃`)}${c.purple(`⠄`)}
Expand Down
7 changes: 7 additions & 0 deletions tools/check-ootb.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ async function main() {
if (!all.body.module_tokens || typeof all.body.module_tokens !== "object") {
throw new Error("configs/all 缺少 module_tokens");
}
// LSP:configs/all.banned_items 须为 string[](与 /banned_items、ConfigManager 同源)
if (Array.isArray(all.body.banned_items)) {
const bad = all.body.banned_items.find((x) => typeof x !== "string");
if (bad !== undefined) {
throw new Error(`configs/all.banned_items 须为 string[],收到 ${typeof bad}`);
}
}
pass(`db-server 启动 + 平台 API (modules=${mods.body.modules.length})`);
} catch (e) {
fail("db-server 启动 + 平台 API", e.message);
Expand Down
Loading