@sfmc-bds/db-server 0.2.0-beta.13 → 0.2.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/domain/bridge.d.ts +1 -5
- package/dist/domain/bridge.d.ts.map +1 -1
- package/dist/domain/bridge.js +15 -14
- package/dist/domain/bridge.js.map +2 -2
- package/dist/domain/installed-content.d.ts +84 -0
- package/dist/domain/installed-content.d.ts.map +1 -0
- package/dist/domain/installed-content.js +149 -0
- package/dist/domain/installed-content.js.map +7 -0
- package/dist/domain/qq-account-profile.d.ts +51 -0
- package/dist/domain/qq-account-profile.d.ts.map +1 -0
- package/dist/domain/qq-account-profile.js +129 -0
- package/dist/domain/qq-account-profile.js.map +7 -0
- package/dist/domain/qq-events.d.ts +2 -2
- package/dist/domain/qq-events.d.ts.map +1 -1
- package/dist/domain/qq-events.js +6 -3
- package/dist/domain/qq-events.js.map +2 -2
- package/dist/domain/schema.d.ts.map +1 -1
- package/dist/domain/schema.js +13 -0
- package/dist/domain/schema.js.map +2 -2
- package/dist/domain/system-status.d.ts +3 -0
- package/dist/domain/system-status.d.ts.map +1 -1
- package/dist/domain/system-status.js +27 -12
- package/dist/domain/system-status.js.map +2 -2
- package/dist/env.d.ts +0 -2
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +12 -24
- package/dist/env.js.map +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -21
- package/dist/index.js.map +3 -3
- package/dist/routes/config.d.ts +1 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +0 -4
- package/dist/routes/config.js.map +2 -2
- package/dist/routes/content.d.ts +23 -0
- package/dist/routes/content.d.ts.map +1 -0
- package/dist/routes/content.js +19 -0
- package/dist/routes/content.js.map +7 -0
- package/dist/routes/messages.d.ts +14 -6
- package/dist/routes/messages.d.ts.map +1 -1
- package/dist/routes/messages.js +22 -8
- package/dist/routes/messages.js.map +2 -2
- package/dist/routes/qq-bind.d.ts.map +1 -1
- package/dist/routes/qq-bind.js +29 -1
- package/dist/routes/qq-bind.js.map +2 -2
- package/dist/routes/qq-events.d.ts +6 -2
- package/dist/routes/qq-events.d.ts.map +1 -1
- package/dist/routes/qq-events.js +35 -1
- package/dist/routes/qq-events.js.map +3 -3
- package/dist/routes/qq-join.js +1 -1
- package/dist/routes/qq-join.js.map +2 -2
- package/dist/routes/status.d.ts +3 -11
- package/dist/routes/status.d.ts.map +1 -1
- package/dist/routes/status.js +39 -49
- package/dist/routes/status.js.map +2 -2
- package/package.json +4 -5
- package/dist/domain/bridge.test.d.ts +0 -2
- package/dist/domain/bridge.test.d.ts.map +0 -1
- package/dist/domain/bridge.test.js +0 -87
- package/dist/domain/bridge.test.js.map +0 -7
- package/dist/domain/messages-bridge-filter.test.d.ts +0 -5
- package/dist/domain/messages-bridge-filter.test.d.ts.map +0 -1
- package/dist/domain/messages-bridge-filter.test.js +0 -20
- package/dist/domain/messages-bridge-filter.test.js.map +0 -7
- package/dist/domain/player-session.test.d.ts +0 -2
- package/dist/domain/player-session.test.d.ts.map +0 -1
- package/dist/domain/player-session.test.js +0 -33
- package/dist/domain/player-session.test.js.map +0 -7
- package/dist/domain/qq-bind-status.test.d.ts +0 -2
- package/dist/domain/qq-bind-status.test.d.ts.map +0 -1
- package/dist/domain/qq-bind-status.test.js +0 -211
- package/dist/domain/qq-bind-status.test.js.map +0 -7
- package/dist/domain/qq-events.test.d.ts +0 -5
- package/dist/domain/qq-events.test.d.ts.map +0 -1
- package/dist/domain/qq-events.test.js +0 -170
- package/dist/domain/qq-events.test.js.map +0 -7
- package/dist/domain/qq-join.test.d.ts +0 -2
- package/dist/domain/qq-join.test.d.ts.map +0 -1
- package/dist/domain/qq-join.test.js +0 -353
- package/dist/domain/qq-join.test.js.map +0 -7
- package/dist/domain/system-status.test.d.ts +0 -5
- package/dist/domain/system-status.test.d.ts.map +0 -1
- package/dist/domain/system-status.test.js +0 -19
- package/dist/domain/system-status.test.js.map +0 -7
- package/dist/runtime.test.d.ts +0 -2
- package/dist/runtime.test.d.ts.map +0 -1
- package/dist/runtime.test.js +0 -477
- package/dist/runtime.test.js.map +0 -7
package/dist/env.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/env.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * env.ts \u2014 \u73AF\u5883\u914D\u7F6E\u52A0\u8F7D\n */\n\nimport {\n ensureCoreConfigs,\n loadEnsuredConfig,\n modulePath,\n DEFAULT_DB_CONFIG,\n DEFAULT_QQ_CONFIG,\n type QQBackend,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { log } from \"./lib/log.js\";\nimport { PROJECT_ROOT as RESOLVED_ROOT } from \"./project-root.js\";\n\n/** \u65E5\u5FD7\u8131\u654F\uFF1A\u5BC6\u94A5\u7C7B\u5B57\u6BB5\u4E0D\u6253\u5370\u660E\u6587 */\nconst SECRET_CONFIG_KEYS = new Set([\n \"qq_app_secret\",\n \"llbot_token\",\n \"http_auth\",\n \"agent_secret\",\n]);\n\nfunction redactConfigValue(key: string, value: unknown): string {\n if (SECRET_CONFIG_KEYS.has(key)) {\n const s = String(value ?? \"\");\n return s.length > 0 ? \"***\" : \"\";\n }\n return String(value);\n}\n\nexport interface EnvConfig {\n PROJECT_ROOT: string;\n PORT: number;\n HOST: string;\n DB_PATH: string;\n AUTH_TOKEN: string;\n // LLBot HTTP\n LLBOT_HOST: string;\n LLBOT_PORT: number;\n LLBOT_TOKEN: string;\n // QQ \u7FA4 / channel(\u4ECE qq_config.json \u900F\u51FA,\u7ED9 bridge / messages \u8DEF\u7531\u7528)\n QQ_GROUP_ID: string;\n
|
|
5
|
-
"mappings": "AAIA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["/**\n * env.ts \u2014 \u73AF\u5883\u914D\u7F6E\u52A0\u8F7D\n */\n\nimport {\n ensureCoreConfigs,\n loadEnsuredConfig,\n modulePath,\n DEFAULT_DB_CONFIG,\n DEFAULT_QQ_CONFIG,\n type QQBackend,\n type QQBridgeConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { log } from \"./lib/log.js\";\nimport { PROJECT_ROOT as RESOLVED_ROOT } from \"./project-root.js\";\n\n/** \u65E5\u5FD7\u8131\u654F\uFF1A\u5BC6\u94A5\u7C7B\u5B57\u6BB5\u4E0D\u6253\u5370\u660E\u6587 */\nconst SECRET_CONFIG_KEYS = new Set([\n \"qq_app_secret\",\n \"llbot_token\",\n \"http_auth\",\n \"agent_secret\",\n]);\n\nfunction redactConfigValue(key: string, value: unknown): string {\n if (SECRET_CONFIG_KEYS.has(key)) {\n const s = String(value ?? \"\");\n return s.length > 0 ? \"***\" : \"\";\n }\n return String(value);\n}\n\nexport interface EnvConfig {\n PROJECT_ROOT: string;\n PORT: number;\n HOST: string;\n DB_PATH: string;\n AUTH_TOKEN: string;\n // LLBot HTTP\n LLBOT_HOST: string;\n LLBOT_PORT: number;\n LLBOT_TOKEN: string;\n // QQ \u7FA4 / channel(\u4ECE qq_config.json \u900F\u51FA,\u7ED9 bridge / messages \u8DEF\u7531\u7528)\n QQ_GROUP_ID: string;\n // \u5B98\u65B9 Bot\n QQ_BACKEND: QQBackend;\n QQ_APP_ID: string;\n QQ_APP_SECRET: string;\n QQ_SANDBOX: boolean;\n QQ_GROUP_OPENID: string;\n MODULES_DIR: string;\n MODULE_CATALOG_PATH: string;\n MODULE_LOCK_PATH: string;\n dbconfig: Record<string, unknown>;\n qqconfig: Record<string, unknown>;\n}\n\nexport function loadEnv(): EnvConfig {\n const PROJECT_ROOT = RESOLVED_ROOT;\n /* \u542F\u52A8\u65F6\u786E\u8BA4 db/qq/permissions \u5B58\u5728;\u4E0D\u5B58\u5728\u5C31\u5199\u5E26\u9ED8\u8BA4\u503C\u7684\u9AA8\u67B6\u3002\n * \u4E0D\u4F9D\u8D56 wizard:wizard \u53EA\u586B\u5B57\u6BB5,\u9AA8\u67B6\u7531\u670D\u52A1\u81EA\u5DF1 ensure\u3002 */\n ensureCoreConfigs(PROJECT_ROOT, [\"db_config\", \"qq_config\", \"permissions\"]);\n const dbconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"db_config.json\",\n \"db_config\",\n { ...DEFAULT_DB_CONFIG } as Record<string, unknown>\n );\n const qqconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n );\n\n // \u2500\u2500 \u4F18\u5148\u7EA7:JSON > \u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF > \u9ED8\u8BA4\u503C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const envBaseline = { ...process.env };\n\n for (const [k, v] of Object.entries(dbconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n process.env[envKey] = String(v);\n log.info(`db_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n for (const [k, v] of Object.entries(qqconfig)) {\n if (v !== null && typeof v === \"object\") continue;\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n if (process.env[envKey] === undefined) {\n process.env[envKey] = String(v);\n log.info(`qq_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n }\n\n // \u5DE5\u5177:JSON > envBaseline(\u539F process.env) > default\n // \u8BED\u4E49:JSON \u91CC\u6709\u8FD9\u4E2A\u952E(\u975E undefined / null)\u5C31\u7528 JSON;\u7A7A\u4E32\u30010\u3001false \u90FD\u7B97\"\u663E\u5F0F\u914D\u7F6E\"\n // \u53EA\u6709 JSON \u5B8C\u5168\u6CA1\u8FD9\u4E2A\u952E(\u6216\u8005\u663E\u5F0F null)\u624D fall through \u5230 env\n function pick<T>(jsonVal: T | undefined | null, envKey: string, fallback: T, source: string): T {\n if (jsonVal !== undefined && jsonVal !== null) {\n return jsonVal;\n }\n const fromEnv = envBaseline[envKey];\n if (fromEnv !== undefined && fromEnv !== \"\") {\n log.info(`${source} \u672A\u5728 JSON \u4E2D\u914D\u7F6E,\u4F7F\u7528\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF ${envKey} = ${redactConfigValue(source, fromEnv)}`);\n return fromEnv as unknown as T;\n }\n return fallback;\n }\n\n const PORT = parseInt(String(pick(dbconfig[\"db_port\"] as number | undefined, \"DB_PORT\", 3001, \"db_port\")), 10);\n const HOST = \"127.0.0.1\";\n const DB_PATH_RAW = String(pick(dbconfig[\"dbDir\"] as string | undefined, \"DB_DIR\", \"data/sfmc_data.db\", \"dbDir\"));\n const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);\n const official = (qqconfig[\"official\"] ?? {}) as NonNullable<QQBridgeConfig[\"official\"]>;\n const llbot = (qqconfig[\"llbot\"] ?? {}) as NonNullable<QQBridgeConfig[\"llbot\"]>;\n const LLBOT_HOST = String(\n pick(llbot.host, \"LLBOT_HOST\", \"127.0.0.1\", \"llbot.host\")\n );\n const LLBOT_PORT = parseInt(\n String(pick(llbot.port, \"LLBOT_PORT\", 3004, \"llbot.port\")),\n 10\n );\n const LLBOT_TOKEN = String(pick(llbot.token, \"LLBOT_TOKEN\", \"\", \"llbot.token\"));\n const QQ_GROUP_ID = String(pick(llbot.group_id, \"QQ_GROUP_ID\", \"\", \"llbot.group_id\"));\n const rawBackend = String(\n pick(\n qqconfig[\"qq_backend\"] as string | undefined,\n \"QQ_BACKEND\",\n DEFAULT_QQ_CONFIG.qq_backend ?? \"official\",\n \"qq_backend\"\n )\n );\n const QQ_BACKEND: QQBackend = rawBackend === \"llbot\" ? \"llbot\" : \"official\";\n const QQ_APP_ID = String(pick(official.app_id, \"QQ_APP_ID\", \"\", \"official.app_id\"));\n const QQ_APP_SECRET = String(\n pick(official.app_secret, \"QQ_APP_SECRET\", \"\", \"official.app_secret\")\n );\n const sandboxRaw = pick(\n official.sandbox as boolean | string | undefined,\n \"QQ_SANDBOX\",\n false as boolean | string,\n \"official.sandbox\"\n );\n const QQ_SANDBOX =\n sandboxRaw === true || sandboxRaw === \"true\" || sandboxRaw === \"1\";\n const QQ_GROUP_OPENID = String(\n pick(official.group_openid, \"QQ_GROUP_OPENID\", \"\", \"official.group_openid\")\n );\n const AUTH_TOKEN = String(pick(dbconfig[\"http_auth\"] as string | undefined, \"HTTP_AUTH\", \"\", \"http_auth\"));\n const MODULES_DIR = dbconfig[\"modulesDir\"]\n ? resolve(PROJECT_ROOT, String(dbconfig[\"modulesDir\"]))\n : join(PROJECT_ROOT, \"modules\");\n const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, \"catalog.json\");\n const MODULE_LOCK_PATH = modulePath(MODULES_DIR, \"module-lock.json\");\n\n return {\n PROJECT_ROOT,\n PORT,\n HOST,\n DB_PATH,\n AUTH_TOKEN,\n LLBOT_HOST,\n LLBOT_PORT,\n LLBOT_TOKEN,\n QQ_GROUP_ID,\n QQ_BACKEND,\n QQ_APP_ID,\n QQ_APP_SECRET,\n QQ_SANDBOX,\n QQ_GROUP_OPENID,\n MODULES_DIR,\n MODULE_CATALOG_PATH,\n MODULE_LOCK_PATH,\n dbconfig,\n qqconfig,\n };\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAgBH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6B1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AAwB9B,QAAA,MAAM,gBAAgB,8DAA0E,CAAC;AAQjG,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AA4cH,OAAO,EAAE,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import http from "node:http";
|
|
2
|
+
import { SQL } from "sql-template-strings";
|
|
2
3
|
import { createPlatformTables } from "./db-tables.js";
|
|
3
4
|
import { initSchema } from "./domain/schema.js";
|
|
4
5
|
import { syncPlayerSession } from "./domain/player-session.js";
|
|
@@ -15,8 +16,8 @@ import { createServer, startConsole } from "./server.js";
|
|
|
15
16
|
import { ServiceRegistry } from "./service-registry.js";
|
|
16
17
|
import { registerEnabledBuiltinServices } from "./services/builtin-handlers.js";
|
|
17
18
|
import { TxRunner } from "./tx-runner.js";
|
|
18
|
-
import { ensureJson, patchJson, readJson } from "@sfmc-bds/sdk/node/config";
|
|
19
|
-
import { join } from "node:path";
|
|
19
|
+
import { configPath, ensureJson, patchJson, readJson } from "@sfmc-bds/sdk/node/config";
|
|
20
|
+
import path, { join } from "node:path";
|
|
20
21
|
import { jsonV2Fail } from "./routes/_shared.js";
|
|
21
22
|
import { createDbRoutes } from "./routes/db-routes.js";
|
|
22
23
|
import { createModuleConfigRoutes } from "./routes/module-config-routes.js";
|
|
@@ -25,7 +26,9 @@ import { forwardToQQBridge, makeOutboundConfig } from "./domain/bridge.js";
|
|
|
25
26
|
import { createQqEventsAggregator, resolveQqEventsConfig } from "./domain/qq-events.js";
|
|
26
27
|
import { body as sharedBody, json as sharedJson } from "./lib/http.js";
|
|
27
28
|
import { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from "./lib/module-state.js";
|
|
29
|
+
import { loadContentSnapshot } from "./domain/installed-content.js";
|
|
28
30
|
import { createConfigRoutes } from "./routes/config.js";
|
|
31
|
+
import { createContentRoutes } from "./routes/content.js";
|
|
29
32
|
import { createHealthRoutes } from "./routes/health.js";
|
|
30
33
|
import { createMessagesRoutes } from "./routes/messages.js";
|
|
31
34
|
import { createModuleRoutes } from "./routes/modules.js";
|
|
@@ -126,6 +129,29 @@ function buildModuleList() {
|
|
|
126
129
|
};
|
|
127
130
|
}).filter(Boolean);
|
|
128
131
|
}
|
|
132
|
+
function loadContentSnapshotForRequest() {
|
|
133
|
+
const modules = (buildModuleList() ?? []).flatMap((raw) => {
|
|
134
|
+
if (!raw || typeof raw !== "object") return [];
|
|
135
|
+
const row = raw;
|
|
136
|
+
const id = String(row.id ?? "").trim();
|
|
137
|
+
if (!id) return [];
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
id,
|
|
141
|
+
display_name: String(row.display_name || id),
|
|
142
|
+
enabled: row.enabled !== false
|
|
143
|
+
}
|
|
144
|
+
];
|
|
145
|
+
});
|
|
146
|
+
const cfg = readJson(configPath(env.PROJECT_ROOT, "bds_updater.json"));
|
|
147
|
+
const rawBds = typeof cfg?.bds_path === "string" ? cfg.bds_path.trim() : "";
|
|
148
|
+
const bdsRoot = rawBds ? path.isAbsolute(rawBds) ? rawBds : path.resolve(env.PROJECT_ROOT, rawBds) : null;
|
|
149
|
+
return loadContentSnapshot({
|
|
150
|
+
packagesDir: join(env.MODULES_DIR, "packages"),
|
|
151
|
+
modules,
|
|
152
|
+
bdsRoot
|
|
153
|
+
});
|
|
154
|
+
}
|
|
129
155
|
function moduleCanDisable(raw) {
|
|
130
156
|
return raw.canDisable !== false;
|
|
131
157
|
}
|
|
@@ -158,7 +184,7 @@ function setModuleEnabled(mod, enabled) {
|
|
|
158
184
|
});
|
|
159
185
|
}
|
|
160
186
|
const healthRoutes = createHealthRoutes();
|
|
161
|
-
const statusRoutes = createStatusRoutes({
|
|
187
|
+
const statusRoutes = createStatusRoutes({});
|
|
162
188
|
const qqBindRoutes = createQqBindRoutes({ query, body, json });
|
|
163
189
|
const QQ_LINK_CONFIG_KEY = "qq_link";
|
|
164
190
|
const QQ_LINK_DEFAULTS = {
|
|
@@ -212,13 +238,24 @@ const qqJoinRoutes = createQqJoinRoutes({
|
|
|
212
238
|
body,
|
|
213
239
|
json,
|
|
214
240
|
getAdminOpenids: () => {
|
|
215
|
-
const raw = env.qqconfig["
|
|
241
|
+
const raw = env.qqconfig["official"]?.admin_openids;
|
|
216
242
|
if (!Array.isArray(raw)) return [];
|
|
217
243
|
return raw.map((x) => String(x).trim()).filter(Boolean);
|
|
218
244
|
},
|
|
219
245
|
getJoinFlags: () => readJoinFlags(),
|
|
220
246
|
setJoinFlags: (partial) => writeJoinFlags(partial)
|
|
221
247
|
});
|
|
248
|
+
function readQqEventsSettings() {
|
|
249
|
+
const disk = readJson(join(env.PROJECT_ROOT, "configs", "qq_config.json"));
|
|
250
|
+
if (!disk) throw new Error("qq_config.json \u65E0\u6CD5\u8BFB\u53D6\uFF0C\u4E8B\u4EF6\u8BBE\u7F6E\u672A\u4FEE\u6539");
|
|
251
|
+
return resolveQqEventsConfig(disk.qq_events);
|
|
252
|
+
}
|
|
253
|
+
function writeQqEventsSettings(patch) {
|
|
254
|
+
const file = join(env.PROJECT_ROOT, "configs", "qq_config.json");
|
|
255
|
+
const settings = { ...readQqEventsSettings(), ...patch };
|
|
256
|
+
patchJson(file, { qq_events: settings });
|
|
257
|
+
return settings;
|
|
258
|
+
}
|
|
222
259
|
function currentOutbound() {
|
|
223
260
|
return makeOutboundConfig({
|
|
224
261
|
QQ_BACKEND: env.QQ_BACKEND,
|
|
@@ -229,25 +266,35 @@ function currentOutbound() {
|
|
|
229
266
|
QQ_APP_ID: env.QQ_APP_ID,
|
|
230
267
|
QQ_APP_SECRET: env.QQ_APP_SECRET,
|
|
231
268
|
QQ_SANDBOX: env.QQ_SANDBOX,
|
|
232
|
-
QQ_GROUP_OPENID: env.QQ_GROUP_OPENID
|
|
233
|
-
MCTOQQ_PREFIX: env.MCTOQQ_PREFIX
|
|
269
|
+
QQ_GROUP_OPENID: env.QQ_GROUP_OPENID
|
|
234
270
|
});
|
|
235
271
|
}
|
|
236
272
|
const qqEventsAggregator = createQqEventsAggregator({
|
|
237
|
-
getConfig:
|
|
273
|
+
getConfig: readQqEventsSettings,
|
|
238
274
|
getOutbound: () => currentOutbound()
|
|
239
275
|
});
|
|
240
276
|
const qqEventsRoutes = createQqEventsRoutes({
|
|
241
277
|
body,
|
|
242
278
|
json,
|
|
243
|
-
aggregator: qqEventsAggregator
|
|
279
|
+
aggregator: qqEventsAggregator,
|
|
280
|
+
getSettings: readQqEventsSettings,
|
|
281
|
+
setSettings: writeQqEventsSettings,
|
|
282
|
+
isAdmin: (openid, asGroupAdmin) => {
|
|
283
|
+
const admins = env.qqconfig["official"]?.admin_openids;
|
|
284
|
+
return Array.isArray(admins) && admins.includes(openid) || asGroupAdmin && readJoinFlags().treatGroupAdminsAsAdmins;
|
|
285
|
+
}
|
|
244
286
|
});
|
|
245
287
|
const messagesRoutes = createMessagesRoutes({
|
|
246
288
|
query,
|
|
247
289
|
body,
|
|
248
290
|
json,
|
|
249
|
-
|
|
250
|
-
|
|
291
|
+
getChannelForQQ: (channelId) => {
|
|
292
|
+
const rows = query(
|
|
293
|
+
SQL`SELECT * FROM sfmc_chat_channels WHERE id = ${channelId}`
|
|
294
|
+
);
|
|
295
|
+
return Array.isArray(rows) ? rows[0] ?? null : null;
|
|
296
|
+
},
|
|
297
|
+
forwardToQQBridge: (channelId, prefix, fromName, content, fromId) => forwardToQQBridge(currentOutbound(), channelId, prefix, fromName, content, fromId)
|
|
251
298
|
});
|
|
252
299
|
const configRoutes = createConfigRoutes({
|
|
253
300
|
json,
|
|
@@ -256,6 +303,10 @@ const configRoutes = createConfigRoutes({
|
|
|
256
303
|
listModules: () => buildModuleList(),
|
|
257
304
|
getModuleTokens: () => ({ ...moduleAuth.tokens })
|
|
258
305
|
});
|
|
306
|
+
const contentRoutes = createContentRoutes({
|
|
307
|
+
json,
|
|
308
|
+
loadSnapshot: loadContentSnapshotForRequest
|
|
309
|
+
});
|
|
259
310
|
const moduleRoutesInstance = createModuleRoutes({
|
|
260
311
|
loadModuleCatalog,
|
|
261
312
|
buildModuleList,
|
|
@@ -277,7 +328,7 @@ const moduleConfigRoutes = createModuleConfigRoutes({
|
|
|
277
328
|
});
|
|
278
329
|
async function handle(req, res) {
|
|
279
330
|
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
280
|
-
const
|
|
331
|
+
const path2 = url.pathname;
|
|
281
332
|
const method = req.method || "GET";
|
|
282
333
|
const params = url.searchParams;
|
|
283
334
|
const remote = req.socket.remoteAddress || "";
|
|
@@ -286,8 +337,8 @@ async function handle(req, res) {
|
|
|
286
337
|
return;
|
|
287
338
|
}
|
|
288
339
|
await body(req);
|
|
289
|
-
const isLegacyConfigAll =
|
|
290
|
-
const needsModuleAuth =
|
|
340
|
+
const isLegacyConfigAll = path2 === "/api/sfmc/configs/all";
|
|
341
|
+
const needsModuleAuth = path2.startsWith("/api/sfmc/db/") || path2.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+(?:\/(?:set|notify))?$/.test(path2) && !isLegacyConfigAll;
|
|
291
342
|
let moduleAuthCtx = null;
|
|
292
343
|
if (needsModuleAuth) {
|
|
293
344
|
const id = verifyModuleAuth({
|
|
@@ -306,8 +357,8 @@ async function handle(req, res) {
|
|
|
306
357
|
permissions: manifest?.permissions ?? []
|
|
307
358
|
};
|
|
308
359
|
} else {
|
|
309
|
-
const PUBLIC_GET =
|
|
310
|
-
const NEEDS_AUTH = !PUBLIC_GET && method !== "GET" && !(
|
|
360
|
+
const PUBLIC_GET = path2 === "/api/health" || path2 === "/api/sfmc/status" || path2 === "/api/sfmc/qq/join/apply-queue" || path2 === "/api/sfmc/qq/join/settings" || path2 === "/api/sfmc/qq/admin/action-queue" || method === "GET" && (path2 === "/api/sfmc/content" || path2 === "/api/sfmc/modules" || path2 === "/api/sfmc/modules/catalog" || path2.startsWith("/api/sfmc/modules/") || path2 === "/api/sfmc/qq/bind/me" || path2 === "/api/sfmc/qq/join/pending");
|
|
361
|
+
const NEEDS_AUTH = !PUBLIC_GET && method !== "GET" && !(path2.startsWith("/api/sfmc/qq/bind/") || path2.startsWith("/api/sfmc/qq/join/") || path2.startsWith("/api/sfmc/qq/admin/") || path2.startsWith("/api/sfmc/qq/events"));
|
|
311
362
|
if (env.AUTH_TOKEN && NEEDS_AUTH) {
|
|
312
363
|
const auth = req.headers["authorization"] || "";
|
|
313
364
|
const provided = auth.startsWith("Bearer ") ? auth.slice(7) : req.headers["x-db-token"] || "";
|
|
@@ -318,7 +369,7 @@ async function handle(req, res) {
|
|
|
318
369
|
}
|
|
319
370
|
}
|
|
320
371
|
try {
|
|
321
|
-
if (
|
|
372
|
+
if (path2 === "/api/sfmc/player-session" && method === "POST") {
|
|
322
373
|
const data = await body(req);
|
|
323
374
|
const playerName = String(data.playerName ?? "").trim();
|
|
324
375
|
const xuid = String(data.xuid ?? "").trim();
|
|
@@ -330,9 +381,9 @@ async function handle(req, res) {
|
|
|
330
381
|
json(res, { success: true });
|
|
331
382
|
return;
|
|
332
383
|
}
|
|
333
|
-
if (moduleAuthCtx && (
|
|
384
|
+
if (moduleAuthCtx && (path2.startsWith("/api/sfmc/db/") || path2.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+/.test(path2) && !isLegacyConfigAll)) {
|
|
334
385
|
const ctx = {
|
|
335
|
-
path,
|
|
386
|
+
path: path2,
|
|
336
387
|
method,
|
|
337
388
|
params,
|
|
338
389
|
req,
|
|
@@ -340,15 +391,16 @@ async function handle(req, res) {
|
|
|
340
391
|
moduleAuth: moduleAuthCtx
|
|
341
392
|
};
|
|
342
393
|
ctx["body"] = await body(req);
|
|
343
|
-
if (
|
|
394
|
+
if (path2.startsWith("/api/sfmc/db/")) {
|
|
344
395
|
if (await dbRoutes(ctx)) return;
|
|
345
|
-
} else if (
|
|
396
|
+
} else if (path2.startsWith("/api/sfmc/services")) {
|
|
346
397
|
if (await serviceRoutes(ctx)) return;
|
|
347
398
|
} else {
|
|
348
399
|
if (await moduleConfigRoutes(ctx)) return;
|
|
349
400
|
}
|
|
350
401
|
}
|
|
351
|
-
const ctxBase = { path, method, params, req, res };
|
|
402
|
+
const ctxBase = { path: path2, method, params, req, res };
|
|
403
|
+
if (await contentRoutes(ctxBase)) return;
|
|
352
404
|
if (await moduleRoutesInstance(ctxBase)) return;
|
|
353
405
|
if (await healthRoutes(ctxBase)) return;
|
|
354
406
|
if (await statusRoutes(ctxBase)) return;
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n *\n * \u5DE5\u4F5C\u6D41:\n * 1. \u52A0\u8F7D env\n * 2. \u6821\u9A8C Node \u7248\u672C\n * 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)\n * 4. loadManifestV2() \u2014 \u5931\u8D25 = \u542F\u52A8\u5931\u8D25\n * 5. filterEnabled(loaded, lockFileEnabled)\n * 6. buildModuleAuth({auth_token, enabled_modules}) \u2190 \u4E0E DB \u540C\u76EE\u5F55 module-tokens.json\n * 7. \u5B9E\u4F8B\u5316:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner\n * 8. \u88C5\u914D v2 \u8DEF\u7531 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)\n * \u53E6\u4FDD\u7559 messages(qq-bridge) + config/modules/health \u5E73\u53F0\u8DEF\u7531\n * 9. createServer + listen\n *\n * \u9274\u6743(handle \u5C42):\n * - /api/sfmc/db/*, /api/sfmc/services*, /api/sfmc/configs/:key(/set|notify)*\n * \u2192 module token (Authorization: Bearer ...) + ?moduleId=...\n * - \u5176\u4ED6:env.AUTH_TOKEN \u65E7 auth(NEEDS_AUTH)\n */\n\nimport http from \"node:http\";\n\nimport { createPlatformTables } from \"./db-tables.js\";\nimport { initSchema } from \"./domain/schema.js\";\nimport { syncPlayerSession } from \"./domain/player-session.js\";\nimport { loadEnv } from \"./env.js\";\nimport { createIdempotencyStore } from \"./lib/idempotency-store.js\";\nimport { log } from \"./lib/log.js\";\nimport { assertNodeVersion } from \"./lib/runtime.js\";\nimport { createQuery, openDatabase } from \"./lib/sqlite.js\";\nimport { loadManifestV2 } from \"./manifest-loader.js\";\nimport { buildModuleAuth, verifyModuleAuth } from \"./module-auth.js\";\nimport { syncModuleRuntimeState } from \"./module-runtime-sync.js\";\nimport { SchemaRegistry } from \"./schema-registry.js\";\nimport { createServer, startConsole } from \"./server.js\";\nimport { ServiceRegistry } from \"./service-registry.js\";\nimport { registerEnabledBuiltinServices } from \"./services/builtin-handlers.js\";\nimport { TxRunner } from \"./tx-runner.js\";\n\nimport { ensureJson, patchJson, readJson } from \"@sfmc-bds/sdk/node/config\";\nimport { join } from \"node:path\";\n\nimport { jsonV2Fail } from \"./routes/_shared.js\";\nimport { createDbRoutes } from \"./routes/db-routes.js\";\nimport { createModuleConfigRoutes } from \"./routes/module-config-routes.js\";\nimport { createServiceRoutes } from \"./routes/service-routes.js\";\n\nimport { forwardToQQBridge, makeOutboundConfig } from \"./domain/bridge.js\";\nimport { createQqEventsAggregator, resolveQqEventsConfig } from \"./domain/qq-events.js\";\nimport { body as sharedBody, json as sharedJson } from \"./lib/http.js\";\nimport { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from \"./lib/module-state.js\";\nimport { createConfigRoutes } from \"./routes/config.js\";\nimport { createHealthRoutes } from \"./routes/health.js\";\nimport { createMessagesRoutes } from \"./routes/messages.js\";\nimport { createModuleRoutes } from \"./routes/modules.js\";\nimport { createQqBindRoutes } from \"./routes/qq-bind.js\";\nimport { createQqEventsRoutes } from \"./routes/qq-events.js\";\nimport { createQqJoinRoutes, type JoinFeatureFlags } from \"./routes/qq-join.js\";\nimport { createStatusRoutes } from \"./routes/status.js\";\n\nif (!assertNodeVersion(22, 13)) {\n process.exit(2);\n}\n\nconst env = loadEnv();\nconst db = openDatabase(env.DB_PATH);\ncreatePlatformTables(db); // sfmc__audit / sfmc__idempotent\ninitSchema(db); // \u5E73\u53F0\u4E1A\u52A1 bootstrap \u8868(players/world/chat/...)\u2014\u2014qq-bridge \u5728 SAPI defineTable \u4E4B\u524D\u5C31\u9700\u8981\nconst query = createQuery(db);\n\n// \u2500\u2500 v2 manifest \u52A0\u8F7D(\u5931\u8D25 = \u542F\u52A8\u5931\u8D25)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst loadedManifest = loadManifestV2(); // throws on violation\nlog.success(\n `[manifest v2] loaded ${Object.keys(loadedManifest.modules).length} modules; provides ${loadedManifest.providesMap.size} services`\n);\n\n// \u2500\u2500 enabled \u96C6\u5408(\u4ECE lock file)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst lockFile = loadModuleLock(env.MODULE_LOCK_PATH);\nconst moduleCatalog = readJson<{ modules?: unknown[] }>(env.MODULE_CATALOG_PATH) ?? { modules: [] };\nconst catalogIds = new Set(\n Array.isArray(moduleCatalog.modules)\n ? (moduleCatalog.modules as Array<{ id?: string }>).map((m) => String(m.id || \"\")).filter((id) => id.length > 0)\n : []\n);\nconst enabledSet = new Set<string>();\nfor (const id of Object.keys(loadedManifest.modules)) {\n if (!catalogIds.has(id)) continue;\n const catalogEntry = (moduleCatalog.modules as Array<Record<string, unknown>>).find((m) => String(m.id) === id);\n if (!catalogEntry) continue;\n const defaultEnabled = catalogEntry.enabledByDefault !== false;\n if (isEnabled(lockFile, id, defaultEnabled)) enabledSet.add(id);\n}\nconst enabledManifests = new Map<string, NonNullable<(typeof loadedManifest.modules)[string]>>();\nfor (const id of enabledSet) {\n const m = loadedManifest.modules[id];\n if (m) enabledManifests.set(id, m);\n}\nlog.info(`[manifest v2] enabled: ${[...enabledSet].sort().join(\", \") || \"(none)\"}`);\n\n// \u2500\u2500 \u6A21\u5757 HMAC token map(\u4E0E DB \u540C\u76EE\u5F55 module-tokens.json)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst moduleAuth = buildModuleAuth({\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledModuleIds: [...enabledSet],\n});\n\n// \u2500\u2500 \u4E09\u4EF6\u5957 + \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst schemaRegistry = new SchemaRegistry(db);\nconst serviceRegistry = new ServiceRegistry();\nconst idempotent = createIdempotencyStore(db);\nconst txRunner = new TxRunner({\n db,\n query,\n schema: schemaRegistry,\n serviceRegistry,\n enabled: enabledManifests,\n});\n\n// \u2500\u2500 \u8FDB\u7A0B\u5185\u7F6E service handler(\u6269\u5C55\u70B9:BUILTIN_SERVICE_PLUGINS) \u2500\u2500\n{\n const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);\n if (plugins > 0) {\n log.success(`[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`);\n }\n}\n\nconst json = sharedJson;\nconst body = sharedBody;\n\n// \u2500\u2500 \u5DE5\u5177\u51FD\u6570 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction loadModuleCatalog() {\n return Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules : [];\n}\n\nfunction buildModuleList() {\n const catalog = loadModuleCatalog();\n return catalog\n .map((raw) => {\n const entry =\n (raw as Record<string, unknown>).entry && typeof (raw as Record<string, unknown>).entry === \"object\"\n ? ((raw as Record<string, unknown>).entry as Record<string, unknown>)\n : {};\n const id = String((raw as Record<string, unknown>).id || \"\").trim();\n const configKey = String(\n (raw as Record<string, unknown>).configKey || (raw as Record<string, unknown>).config_key || \"\"\n ).trim();\n if (!id || !configKey) return null;\n const state = lockFile.modules[id];\n const enabled = isEnabled(lockFile, id, (raw as Record<string, unknown>).enabledByDefault !== false);\n return {\n id,\n module_id: id,\n name: configKey,\n configKey,\n config_key: configKey,\n display_name: String((raw as Record<string, unknown>).name || configKey),\n description: String((raw as Record<string, unknown>).description || \"\"),\n default_enabled: (raw as Record<string, unknown>).enabledByDefault !== false,\n can_disable: moduleCanDisable(raw as Record<string, unknown>),\n // ConfigManager \u8BA4 installed!==false;\u5DF2\u88C5\u5305\u9ED8\u8BA4 true\n installed: true,\n requires: Array.isArray((raw as Record<string, unknown>).requires)\n ? ((raw as Record<string, unknown>).requires as unknown[]).filter(Boolean).map(String)\n : [],\n optional: Array.isArray((raw as Record<string, unknown>).optional)\n ? ((raw as Record<string, unknown>).optional as unknown[]).filter(Boolean).map(String)\n : [],\n commands: Array.isArray((raw as Record<string, unknown>).commands)\n ? ((raw as Record<string, unknown>).commands as unknown[]).filter(Boolean).map(String)\n : [],\n entry: {\n kind: String(entry.kind || \"\"),\n path: String(entry.path || \"\"),\n init: String(entry.init || \"\"),\n },\n updated_at: state?.updatedAt ?? null,\n enabled: !!enabled,\n };\n })\n .filter(Boolean);\n}\n\n/** catalog \u7701\u7565 canDisable \u65F6\u9ED8\u8BA4\u5141\u8BB8\u7981\u7528(\u4E0E buildModuleList.can_disable \u540C\u6E90)\u3002 */\nfunction moduleCanDisable(raw: Record<string, unknown>): boolean {\n return raw.canDisable !== false;\n}\n\nfunction resolveModuleByKey(key: string) {\n const k = String(key || \"\").trim();\n const catalog = loadModuleCatalog();\n const raw = catalog.find(\n (m) =>\n String((m as Record<string, unknown>).id || \"\") === k ||\n String((m as Record<string, unknown>).configKey || (m as Record<string, unknown>).config_key || \"\") === k\n ) as Record<string, unknown> | undefined;\n if (!raw) return null;\n const id = String(raw.id || \"\").trim();\n const configKey = String(raw.configKey || raw.config_key || \"\").trim();\n if (!id || !configKey) return null;\n /* LSP:\u4E0E buildModuleList.can_disable \u540C\u6E90 \u2014 \u7701\u7565\u5B57\u6BB5\u89C6\u4E3A\u53EF\u7981\u7528 */\n return { id, configKey, canDisable: moduleCanDisable(raw) };\n}\n\nfunction setModuleEnabled(mod: { id: string; canDisable: boolean }, enabled: boolean) {\n // \u76F4\u63A5\u66F4\u65B0\u542F\u52A8\u65F6\u7F13\u5B58\u7684 lockFile(\u800C\u975E\u53E6\u8BFB\u4E00\u4EFD\u65B0\u526F\u672C),\n // \u5426\u5219 buildModuleList() \u8BFB\u7684\u4ECD\u662F\u65E7\u7F13\u5B58,\u5BFC\u81F4\u542F\u505C\u540E enabled \u72B6\u6001\u4E0D\u7FFB\u8F6C\u3002\n updateModuleState(lockFile, mod.id, { enabled: !!enabled });\n // DRY:\u4E0E loadModuleLock \u5BF9\u79F0\u8D70 saveModuleLock,\u52FF\u6563\u843D writeJson\n saveModuleLock(env.MODULE_LOCK_PATH, lockFile);\n\n // DIP:\u70ED\u540C\u6B65 enabledSet / tokens / manifests / builtin handlers(\u4E0D\u91CD\u542F db-server)\n syncModuleRuntimeState({\n moduleId: mod.id,\n enabled: !!enabled,\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledSet,\n enabledManifests,\n loadedManifest,\n moduleAuth,\n serviceRegistry,\n builtinDeps: { query, db },\n });\n}\n\n// \u2500\u2500 \u5E73\u53F0\u8DEF\u7531(\u975E\u6A21\u5757\u4E1A\u52A1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst healthRoutes = createHealthRoutes();\nconst statusRoutes = createStatusRoutes({ query });\nconst qqBindRoutes = createQqBindRoutes({ query, body, json });\n\n/** \u6A21\u5757 qq-link \u7684\u914D\u7F6E\u6587\u4EF6\uFF08\u975E SDK qq_config\uFF09 */\nconst QQ_LINK_CONFIG_KEY = \"qq_link\";\nconst QQ_LINK_DEFAULTS = {\n allowlist_enabled: true,\n require_approval: true,\n /** \u662F\u5426\u5C06 QQ \u7FA4\u4E3B/\u7FA4\u7BA1\u89C6\u4F5C SFMC \u7BA1\u7406\u5458\uFF1B\u4EC5\u6539\u672C\u6587\u4EF6\uFF0CAPI/\u7FA4\u804A\u4E0D\u53EF\u5199 */\n treat_group_admins_as_admins: false,\n} as const;\n\nfunction asConfigBool(v: unknown, fallback: boolean): boolean {\n if (v === undefined || v === null) return fallback;\n if (typeof v === \"boolean\") return v;\n const s = String(v).trim().toLowerCase();\n if (s === \"true\" || s === \"1\" || s === \"yes\" || s === \"on\") return true;\n if (s === \"false\" || s === \"0\" || s === \"no\" || s === \"off\") return false;\n return fallback;\n}\n\nfunction qqLinkConfigFile(): string {\n return join(env.PROJECT_ROOT, \"configs\", `${QQ_LINK_CONFIG_KEY}.json`);\n}\n\nfunction readJoinFlags(): JoinFeatureFlags {\n // \u6A21\u5757\u914D\u7F6E configs/qq_link.json\uFF08\u975E SDK qq_config\uFF09\n const disk = ensureJson<Record<string, unknown>>(qqLinkConfigFile(), { ...QQ_LINK_DEFAULTS });\n return {\n allowlistEnabled: asConfigBool(disk.allowlist_enabled, QQ_LINK_DEFAULTS.allowlist_enabled),\n requireApproval: asConfigBool(disk.require_approval, QQ_LINK_DEFAULTS.require_approval),\n treatGroupAdminsAsAdmins: asConfigBool(\n disk.treat_group_admins_as_admins,\n QQ_LINK_DEFAULTS.treat_group_admins_as_admins\n ),\n };\n}\n\nfunction writeJoinFlags(partial: Partial<JoinFeatureFlags>): JoinFeatureFlags {\n const file = qqLinkConfigFile();\n ensureJson<Record<string, unknown>>(file, { ...QQ_LINK_DEFAULTS });\n const patch: Record<string, boolean> = {};\n if (partial.allowlistEnabled !== undefined) patch.allowlist_enabled = partial.allowlistEnabled;\n if (partial.requireApproval !== undefined) patch.require_approval = partial.requireApproval;\n // \u6545\u610F\u4E0D\u5199 treat_group_admins_as_admins\uFF1A\u4EC5\u4EBA\u5DE5\u6539 configs/qq_link.json\n if (Object.keys(patch).length > 0) {\n patchJson(file, patch);\n }\n return readJoinFlags();\n}\n\n// \u542F\u52A8\u5373\u843D\u76D8\u6A21\u5757\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u907F\u514D\u300C\u4ECE\u672A\u70B9\u8FC7\u914D\u7F6E/\u7533\u8BF7\u300D\u65F6 configs/qq_link.json \u4E0D\u5B58\u5728\n{\n const created = !readJson(qqLinkConfigFile());\n ensureJson<Record<string, unknown>>(qqLinkConfigFile(), { ...QQ_LINK_DEFAULTS });\n if (created) {\n log.info(`\u5DF2\u5199\u5165\u6A21\u5757\u914D\u7F6E\u9AA8\u67B6: configs/${QQ_LINK_CONFIG_KEY}.json`);\n }\n}\n\nconst qqJoinRoutes = createQqJoinRoutes({\n query,\n body,\n json,\n getAdminOpenids: () => {\n const raw = env.qqconfig[\"qq_admin_openids\"];\n if (!Array.isArray(raw)) return [];\n return raw.map((x) => String(x).trim()).filter(Boolean);\n },\n getJoinFlags: () => readJoinFlags(),\n setJoinFlags: (partial) => writeJoinFlags(partial),\n});\n\nfunction currentOutbound() {\n return makeOutboundConfig({\n QQ_BACKEND: env.QQ_BACKEND,\n LLBOT_HOST: env.LLBOT_HOST,\n LLBOT_PORT: env.LLBOT_PORT,\n LLBOT_TOKEN: env.LLBOT_TOKEN,\n QQ_GROUP_ID: env.QQ_GROUP_ID,\n QQ_APP_ID: env.QQ_APP_ID,\n QQ_APP_SECRET: env.QQ_APP_SECRET,\n QQ_SANDBOX: env.QQ_SANDBOX,\n QQ_GROUP_OPENID: env.QQ_GROUP_OPENID,\n MCTOQQ_PREFIX: env.MCTOQQ_PREFIX,\n });\n}\n\nconst qqEventsAggregator = createQqEventsAggregator({\n getConfig: () => resolveQqEventsConfig(env.qqconfig[\"qq_events\"]),\n getOutbound: () => currentOutbound(),\n});\nconst qqEventsRoutes = createQqEventsRoutes({\n body,\n json,\n aggregator: qqEventsAggregator,\n});\n\nconst messagesRoutes = createMessagesRoutes({\n query,\n body,\n json,\n getBridgeChannelId: () => String(env.QQ_BRIDGE_CHANNEL_ID ?? \"\").trim(),\n forwardToQQBridge: (channelId: string, fromName: string, content: string, fromId: string) =>\n forwardToQQBridge(currentOutbound(), channelId, fromName, content, fromId),\n});\nconst configRoutes = createConfigRoutes({\n json,\n projectRoot: env.PROJECT_ROOT,\n // DIP:\u8DEF\u7531\u4E0D\u8BFB lock/catalog/token \u6587\u4EF6,\u7531\u5165\u53E3\u6CE8\u5165\u4E0E /modules \u540C\u6E90\u6570\u636E\n listModules: () => buildModuleList() as Array<Record<string, unknown>>,\n getModuleTokens: () => ({ ...moduleAuth.tokens }),\n});\nconst moduleRoutesInstance = createModuleRoutes({\n loadModuleCatalog,\n buildModuleList: buildModuleList as unknown as () => Array<Record<string, unknown>>,\n resolveModuleByKey,\n setModuleEnabled,\n body,\n json,\n});\n\n// \u2500\u2500 v2 \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// \u7C7B\u578B\u65AD\u8A00\u6210 unknown \u51FD\u6570 \u2014 v2 routes \u7684 ctx \u7C7B\u578B\u4E0E RouteCtx \u4E0D\u517C\u5BB9,\n// \u4F46\u8C03\u7528\u5951\u7EA6({path, method, params, req, res, body?})\u662F\u7A33\u5B9A\u7684\u3002\nconst dbRoutes = createDbRoutes({ schemaRegistry, txRunner, idempotent, json }) as unknown as (\n ctx: Record<string, unknown>\n) => Promise<boolean>;\nconst serviceRoutes = createServiceRoutes({\n serviceRegistry,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\nconst moduleConfigRoutes = createModuleConfigRoutes({\n projectRoot: env.PROJECT_ROOT,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\n\n// \u2500\u2500 \u4E3B\u8BF7\u6C42\u5904\u7406\u5668 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nasync function handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n const url = new URL(req.url || \"/\", `http://${req.headers.host || \"localhost\"}`);\n const path = url.pathname;\n const method = req.method || \"GET\";\n const params = url.searchParams;\n\n // loopback \u7ED1\u5B9A\n const remote = req.socket.remoteAddress || \"\";\n if (remote && !remote.startsWith(\"127.\") && remote !== \"::1\" && remote !== \"::ffff:127.\") {\n json(res, { success: false, error: \"forbidden\" }, 403);\n return;\n }\n\n // \u2500\u2500 \u9884\u8BFB body(\u6240\u6709\u8DEF\u7531\u5171\u4EAB) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n await body(req);\n\n // \u2500\u2500 v2 \u6A21\u5757\u8EAB\u4EFD\u6821\u9A8C \u2192 \u5199\u5165\u8DEF\u7531 ctx.moduleAuth(LoD:\u4E0D\u6302 req \u79C1\u6709\u5B57\u6BB5) \u2500\u2500\n // \u6CE8\u610F:`/api/sfmc/configs/all` \u662F\u65E7\u7684\u4E00\u6B21\u6027\u914D\u7F6E\u5FEB\u7167\u7AEF\u70B9(SAPI ConfigManager.init\n // \u542F\u52A8\u5FC5\u7528),\u4E0D\u5C5E\u4E8E v2 \u6A21\u5757\u914D\u7F6E\u547D\u540D\u7A7A\u95F4(configs/<\u6A21\u5757 configKey>),\u5FC5\u987B\u8C41\u514D,\n // \u5426\u5219\u4F1A\u88AB\u6A21\u5757\u9274\u6743\u7F51\u5173\u62E6\u6210 401,\u5BFC\u81F4\u63D2\u4EF6\u7AEF\u8D77\u4E0D\u6765\u3002\n const isLegacyConfigAll = path === \"/api/sfmc/configs/all\";\n const needsModuleAuth =\n path.startsWith(\"/api/sfmc/db/\") ||\n path.startsWith(\"/api/sfmc/services\") ||\n (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+(?:\\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll);\n let moduleAuthCtx: { id: string; permissions: string[] } | null = null;\n if (needsModuleAuth) {\n const id = verifyModuleAuth({\n headers: req.headers,\n params,\n auth: moduleAuth,\n enabledModuleIds: enabledSet,\n });\n if (!id) {\n // LSP: v2 \u6A21\u5757\u95E8\u4E0E service-routes \u540C\u7528 ok \u65B9\u8A00\n jsonV2Fail(res, \"unauthorized: module identity invalid\", 401, \"unauthorized\");\n return;\n }\n const manifest = enabledManifests.get(id);\n moduleAuthCtx = {\n id,\n permissions: manifest?.permissions ?? [],\n };\n } else {\n // \u2500\u2500 \u65E7 env token \u9274\u6743(\u53EA\u5BF9 POST/PUT \u751F\u6548) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const PUBLIC_GET =\n path === \"/api/health\" ||\n path === \"/api/sfmc/status\" ||\n path === \"/api/sfmc/qq/join/apply-queue\" ||\n path === \"/api/sfmc/qq/join/settings\" ||\n path === \"/api/sfmc/qq/admin/action-queue\" ||\n (method === \"GET\" &&\n (path === \"/api/sfmc/modules\" ||\n path === \"/api/sfmc/modules/catalog\" ||\n path.startsWith(\"/api/sfmc/modules/\") ||\n path === \"/api/sfmc/qq/bind/me\" ||\n path === \"/api/sfmc/qq/join/pending\"));\n // bind/join/events POST \u4E0E messages \u4E00\u6837\u8D70\u65E7 AUTH_TOKEN\uFF08\u82E5\u914D\u7F6E\uFF09\uFF1B\u6E38\u620F/\u6865\u540C\u4E3A loopback\n const NEEDS_AUTH =\n !PUBLIC_GET &&\n method !== \"GET\" &&\n !(\n path.startsWith(\"/api/sfmc/qq/bind/\") ||\n path.startsWith(\"/api/sfmc/qq/join/\") ||\n path.startsWith(\"/api/sfmc/qq/admin/\") ||\n path.startsWith(\"/api/sfmc/qq/events\")\n );\n if (env.AUTH_TOKEN && NEEDS_AUTH) {\n const auth = req.headers[\"authorization\"] || \"\";\n const provided = auth.startsWith(\"Bearer \") ? auth.slice(7) : (req.headers[\"x-db-token\"] as string) || \"\";\n if (provided !== env.AUTH_TOKEN) {\n json(res, { success: false, error: \"unauthorized\" }, 401);\n return;\n }\n }\n }\n\n try {\n if (path === \"/api/sfmc/player-session\" && method === \"POST\") {\n const data = (await body(req)) as Record<string, unknown>;\n const playerName = String(data.playerName ?? \"\").trim();\n const xuid = String(data.xuid ?? \"\").trim();\n if (!playerName || !xuid) {\n json(res, { success: false, error: \"playerName_and_xuid_required\" }, 400);\n return;\n }\n syncPlayerSession(query, { playerName, xuid });\n json(res, { success: true });\n return;\n }\n // \u2500\u2500 v2 \u8DEF\u7531(\u4F18\u5148\u5339\u914D) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (\n moduleAuthCtx &&\n (path.startsWith(\"/api/sfmc/db/\") ||\n path.startsWith(\"/api/sfmc/services\") ||\n (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll))\n ) {\n const ctx: Record<string, unknown> = {\n path,\n method,\n params,\n req,\n res,\n moduleAuth: moduleAuthCtx,\n };\n // body \u5DF2\u5728\u4E0A\u9762 `await body(req)` \u9884\u8BFB\u5E76\u7F13\u5B58\u5230 req._bodyPromise;\n // \u8FD9\u91CC\u590D\u7528\u7F13\u5B58(\u539F\u5B9E\u73B0\u8BFB\u7684 req._body \u4ECE\u672A\u88AB\u8D4B\u503C,\u5BFC\u81F4\u6240\u6709 v2 \u8DEF\u7531 body \u6052\u4E3A\u7A7A)\u3002\n ctx[\"body\"] = await body(req);\n if (path.startsWith(\"/api/sfmc/db/\")) {\n if (await dbRoutes(ctx)) return;\n } else if (path.startsWith(\"/api/sfmc/services\")) {\n if (await serviceRoutes(ctx)) return;\n } else {\n if (await moduleConfigRoutes(ctx)) return;\n }\n }\n\n // \u2500\u2500 \u5E73\u53F0\u8DEF\u7531 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctxBase = { path, method, params, req, res } as {\n path: string;\n method: string;\n params: URLSearchParams;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n };\n if (await moduleRoutesInstance(ctxBase)) return;\n if (await healthRoutes(ctxBase)) return;\n if (await statusRoutes(ctxBase)) return;\n if (await qqBindRoutes(ctxBase)) return;\n if (await qqJoinRoutes(ctxBase)) return;\n if (await qqEventsRoutes(ctxBase)) return;\n if (await messagesRoutes(ctxBase)) return;\n if (await configRoutes(ctxBase)) return;\n\n json(res, { success: false, error: \"not_found\" }, 404);\n } catch (err) {\n log.err(err, \"DogeDB\");\n json(res, { success: false, error: (err as Error).message }, 500);\n }\n}\n\n// \u2500\u2500 \u542F\u52A8 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst server = createServer({\n env: { PORT: env.PORT, HOST: env.HOST, AUTH_TOKEN: env.AUTH_TOKEN },\n handle,\n});\nstartConsole(server, db);\n\nexport { db, enabledManifests, env, moduleAuth, query, schemaRegistry, serviceRegistry, txRunner };\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n *\n * \u5DE5\u4F5C\u6D41:\n * 1. \u52A0\u8F7D env\n * 2. \u6821\u9A8C Node \u7248\u672C\n * 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)\n * 4. loadManifestV2() \u2014 \u5931\u8D25 = \u542F\u52A8\u5931\u8D25\n * 5. filterEnabled(loaded, lockFileEnabled)\n * 6. buildModuleAuth({auth_token, enabled_modules}) \u2190 \u4E0E DB \u540C\u76EE\u5F55 module-tokens.json\n * 7. \u5B9E\u4F8B\u5316:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner\n * 8. \u88C5\u914D v2 \u8DEF\u7531 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)\n * \u53E6\u4FDD\u7559 messages(qq-bridge) + config/modules/health \u5E73\u53F0\u8DEF\u7531\n * 9. createServer + listen\n *\n * \u9274\u6743(handle \u5C42):\n * - /api/sfmc/db/*, /api/sfmc/services*, /api/sfmc/configs/:key(/set|notify)*\n * \u2192 module token (Authorization: Bearer ...) + ?moduleId=...\n * - \u5176\u4ED6:env.AUTH_TOKEN \u65E7 auth(NEEDS_AUTH)\n */\n\nimport http from \"node:http\";\nimport { SQL } from \"sql-template-strings\";\n\nimport { createPlatformTables } from \"./db-tables.js\";\nimport { initSchema } from \"./domain/schema.js\";\nimport { syncPlayerSession } from \"./domain/player-session.js\";\nimport { loadEnv } from \"./env.js\";\nimport { createIdempotencyStore } from \"./lib/idempotency-store.js\";\nimport { log } from \"./lib/log.js\";\nimport { assertNodeVersion } from \"./lib/runtime.js\";\nimport { createQuery, openDatabase } from \"./lib/sqlite.js\";\nimport { loadManifestV2 } from \"./manifest-loader.js\";\nimport { buildModuleAuth, verifyModuleAuth } from \"./module-auth.js\";\nimport { syncModuleRuntimeState } from \"./module-runtime-sync.js\";\nimport { SchemaRegistry } from \"./schema-registry.js\";\nimport { createServer, startConsole } from \"./server.js\";\nimport { ServiceRegistry } from \"./service-registry.js\";\nimport { registerEnabledBuiltinServices } from \"./services/builtin-handlers.js\";\nimport { TxRunner } from \"./tx-runner.js\";\n\nimport { configPath, ensureJson, patchJson, readJson } from \"@sfmc-bds/sdk/node/config\";\nimport path, { join } from \"node:path\";\n\nimport { jsonV2Fail } from \"./routes/_shared.js\";\nimport { createDbRoutes } from \"./routes/db-routes.js\";\nimport { createModuleConfigRoutes } from \"./routes/module-config-routes.js\";\nimport { createServiceRoutes } from \"./routes/service-routes.js\";\n\nimport { forwardToQQBridge, makeOutboundConfig } from \"./domain/bridge.js\";\nimport { createQqEventsAggregator, resolveQqEventsConfig, type ResolvedQqEventsConfig } from \"./domain/qq-events.js\";\nimport { body as sharedBody, json as sharedJson } from \"./lib/http.js\";\nimport { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from \"./lib/module-state.js\";\nimport { loadContentSnapshot } from \"./domain/installed-content.js\";\nimport { createConfigRoutes } from \"./routes/config.js\";\nimport { createContentRoutes } from \"./routes/content.js\";\nimport { createHealthRoutes } from \"./routes/health.js\";\nimport { createMessagesRoutes } from \"./routes/messages.js\";\nimport { createModuleRoutes } from \"./routes/modules.js\";\nimport { createQqBindRoutes } from \"./routes/qq-bind.js\";\nimport { createQqEventsRoutes } from \"./routes/qq-events.js\";\nimport { createQqJoinRoutes, type JoinFeatureFlags } from \"./routes/qq-join.js\";\nimport { createStatusRoutes } from \"./routes/status.js\";\n\nif (!assertNodeVersion(22, 13)) {\n process.exit(2);\n}\n\nconst env = loadEnv();\nconst db = openDatabase(env.DB_PATH);\ncreatePlatformTables(db); // sfmc__audit / sfmc__idempotent\ninitSchema(db); // \u5E73\u53F0\u4E1A\u52A1 bootstrap \u8868(players/world/chat/...)\u2014\u2014qq-bridge \u5728 SAPI defineTable \u4E4B\u524D\u5C31\u9700\u8981\nconst query = createQuery(db);\n\n// \u2500\u2500 v2 manifest \u52A0\u8F7D(\u5931\u8D25 = \u542F\u52A8\u5931\u8D25)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst loadedManifest = loadManifestV2(); // throws on violation\nlog.success(\n `[manifest v2] loaded ${Object.keys(loadedManifest.modules).length} modules; provides ${loadedManifest.providesMap.size} services`\n);\n\n// \u2500\u2500 enabled \u96C6\u5408(\u4ECE lock file)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst lockFile = loadModuleLock(env.MODULE_LOCK_PATH);\nconst moduleCatalog = readJson<{ modules?: unknown[] }>(env.MODULE_CATALOG_PATH) ?? { modules: [] };\nconst catalogIds = new Set(\n Array.isArray(moduleCatalog.modules)\n ? (moduleCatalog.modules as Array<{ id?: string }>).map((m) => String(m.id || \"\")).filter((id) => id.length > 0)\n : []\n);\nconst enabledSet = new Set<string>();\nfor (const id of Object.keys(loadedManifest.modules)) {\n if (!catalogIds.has(id)) continue;\n const catalogEntry = (moduleCatalog.modules as Array<Record<string, unknown>>).find((m) => String(m.id) === id);\n if (!catalogEntry) continue;\n const defaultEnabled = catalogEntry.enabledByDefault !== false;\n if (isEnabled(lockFile, id, defaultEnabled)) enabledSet.add(id);\n}\nconst enabledManifests = new Map<string, NonNullable<(typeof loadedManifest.modules)[string]>>();\nfor (const id of enabledSet) {\n const m = loadedManifest.modules[id];\n if (m) enabledManifests.set(id, m);\n}\nlog.info(`[manifest v2] enabled: ${[...enabledSet].sort().join(\", \") || \"(none)\"}`);\n\n// \u2500\u2500 \u6A21\u5757 HMAC token map(\u4E0E DB \u540C\u76EE\u5F55 module-tokens.json)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst moduleAuth = buildModuleAuth({\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledModuleIds: [...enabledSet],\n});\n\n// \u2500\u2500 \u4E09\u4EF6\u5957 + \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst schemaRegistry = new SchemaRegistry(db);\nconst serviceRegistry = new ServiceRegistry();\nconst idempotent = createIdempotencyStore(db);\nconst txRunner = new TxRunner({\n db,\n query,\n schema: schemaRegistry,\n serviceRegistry,\n enabled: enabledManifests,\n});\n\n// \u2500\u2500 \u8FDB\u7A0B\u5185\u7F6E service handler(\u6269\u5C55\u70B9:BUILTIN_SERVICE_PLUGINS) \u2500\u2500\n{\n const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);\n if (plugins > 0) {\n log.success(`[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`);\n }\n}\n\nconst json = sharedJson;\nconst body = sharedBody;\n\n// \u2500\u2500 \u5DE5\u5177\u51FD\u6570 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction loadModuleCatalog() {\n return Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules : [];\n}\n\nfunction buildModuleList() {\n const catalog = loadModuleCatalog();\n return catalog\n .map((raw) => {\n const entry =\n (raw as Record<string, unknown>).entry && typeof (raw as Record<string, unknown>).entry === \"object\"\n ? ((raw as Record<string, unknown>).entry as Record<string, unknown>)\n : {};\n const id = String((raw as Record<string, unknown>).id || \"\").trim();\n const configKey = String(\n (raw as Record<string, unknown>).configKey || (raw as Record<string, unknown>).config_key || \"\"\n ).trim();\n if (!id || !configKey) return null;\n const state = lockFile.modules[id];\n const enabled = isEnabled(lockFile, id, (raw as Record<string, unknown>).enabledByDefault !== false);\n return {\n id,\n module_id: id,\n name: configKey,\n configKey,\n config_key: configKey,\n display_name: String((raw as Record<string, unknown>).name || configKey),\n description: String((raw as Record<string, unknown>).description || \"\"),\n default_enabled: (raw as Record<string, unknown>).enabledByDefault !== false,\n can_disable: moduleCanDisable(raw as Record<string, unknown>),\n // ConfigManager \u8BA4 installed!==false;\u5DF2\u88C5\u5305\u9ED8\u8BA4 true\n installed: true,\n requires: Array.isArray((raw as Record<string, unknown>).requires)\n ? ((raw as Record<string, unknown>).requires as unknown[]).filter(Boolean).map(String)\n : [],\n optional: Array.isArray((raw as Record<string, unknown>).optional)\n ? ((raw as Record<string, unknown>).optional as unknown[]).filter(Boolean).map(String)\n : [],\n commands: Array.isArray((raw as Record<string, unknown>).commands)\n ? ((raw as Record<string, unknown>).commands as unknown[]).filter(Boolean).map(String)\n : [],\n entry: {\n kind: String(entry.kind || \"\"),\n path: String(entry.path || \"\"),\n init: String(entry.init || \"\"),\n },\n updated_at: state?.updatedAt ?? null,\n enabled: !!enabled,\n };\n })\n .filter(Boolean);\n}\n\n/**\n * QQ\u300C\u6A21\u5757 / \u4E16\u754C\u5305\u300D\u5FEB\u7167\u3002\u6BCF\u6B21\u8BF7\u6C42\u73B0\u8BFB catalog \u4E0E\u78C1\u76D8\uFF0C\u88C5\u5305\u540E\u4E0D\u7528\u91CD\u542F db-server\u3002\n */\nfunction loadContentSnapshotForRequest() {\n const modules = (buildModuleList() ?? []).flatMap((raw) => {\n if (!raw || typeof raw !== \"object\") return [];\n const row = raw as { id?: unknown; display_name?: unknown; enabled?: unknown };\n const id = String(row.id ?? \"\").trim();\n if (!id) return [];\n return [\n {\n id,\n display_name: String(row.display_name || id),\n enabled: row.enabled !== false,\n },\n ];\n });\n const cfg = readJson<{ bds_path?: string }>(configPath(env.PROJECT_ROOT, \"bds_updater.json\"));\n const rawBds = typeof cfg?.bds_path === \"string\" ? cfg.bds_path.trim() : \"\";\n const bdsRoot = rawBds ? (path.isAbsolute(rawBds) ? rawBds : path.resolve(env.PROJECT_ROOT, rawBds)) : null;\n return loadContentSnapshot({\n packagesDir: join(env.MODULES_DIR, \"packages\"),\n modules,\n bdsRoot,\n });\n}\n\n/** catalog \u7701\u7565 canDisable \u65F6\u9ED8\u8BA4\u5141\u8BB8\u7981\u7528(\u4E0E buildModuleList.can_disable \u540C\u6E90)\u3002 */\nfunction moduleCanDisable(raw: Record<string, unknown>): boolean {\n return raw.canDisable !== false;\n}\n\nfunction resolveModuleByKey(key: string) {\n const k = String(key || \"\").trim();\n const catalog = loadModuleCatalog();\n const raw = catalog.find(\n (m) =>\n String((m as Record<string, unknown>).id || \"\") === k ||\n String((m as Record<string, unknown>).configKey || (m as Record<string, unknown>).config_key || \"\") === k\n ) as Record<string, unknown> | undefined;\n if (!raw) return null;\n const id = String(raw.id || \"\").trim();\n const configKey = String(raw.configKey || raw.config_key || \"\").trim();\n if (!id || !configKey) return null;\n /* LSP:\u4E0E buildModuleList.can_disable \u540C\u6E90 \u2014 \u7701\u7565\u5B57\u6BB5\u89C6\u4E3A\u53EF\u7981\u7528 */\n return { id, configKey, canDisable: moduleCanDisable(raw) };\n}\n\nfunction setModuleEnabled(mod: { id: string; canDisable: boolean }, enabled: boolean) {\n // \u76F4\u63A5\u66F4\u65B0\u542F\u52A8\u65F6\u7F13\u5B58\u7684 lockFile(\u800C\u975E\u53E6\u8BFB\u4E00\u4EFD\u65B0\u526F\u672C),\n // \u5426\u5219 buildModuleList() \u8BFB\u7684\u4ECD\u662F\u65E7\u7F13\u5B58,\u5BFC\u81F4\u542F\u505C\u540E enabled \u72B6\u6001\u4E0D\u7FFB\u8F6C\u3002\n updateModuleState(lockFile, mod.id, { enabled: !!enabled });\n // DRY:\u4E0E loadModuleLock \u5BF9\u79F0\u8D70 saveModuleLock,\u52FF\u6563\u843D writeJson\n saveModuleLock(env.MODULE_LOCK_PATH, lockFile);\n\n // DIP:\u70ED\u540C\u6B65 enabledSet / tokens / manifests / builtin handlers(\u4E0D\u91CD\u542F db-server)\n syncModuleRuntimeState({\n moduleId: mod.id,\n enabled: !!enabled,\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledSet,\n enabledManifests,\n loadedManifest,\n moduleAuth,\n serviceRegistry,\n builtinDeps: { query, db },\n });\n}\n\n// \u2500\u2500 \u5E73\u53F0\u8DEF\u7531(\u975E\u6A21\u5757\u4E1A\u52A1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst healthRoutes = createHealthRoutes();\nconst statusRoutes = createStatusRoutes({});\nconst qqBindRoutes = createQqBindRoutes({ query, body, json });\n\n/** \u6A21\u5757 qq-link \u7684\u914D\u7F6E\u6587\u4EF6\uFF08\u975E SDK qq_config\uFF09 */\nconst QQ_LINK_CONFIG_KEY = \"qq_link\";\nconst QQ_LINK_DEFAULTS = {\n allowlist_enabled: true,\n require_approval: true,\n /** \u662F\u5426\u5C06 QQ \u7FA4\u4E3B/\u7FA4\u7BA1\u89C6\u4F5C SFMC \u7BA1\u7406\u5458\uFF1B\u4EC5\u6539\u672C\u6587\u4EF6\uFF0CAPI/\u7FA4\u804A\u4E0D\u53EF\u5199 */\n treat_group_admins_as_admins: false,\n} as const;\n\nfunction asConfigBool(v: unknown, fallback: boolean): boolean {\n if (v === undefined || v === null) return fallback;\n if (typeof v === \"boolean\") return v;\n const s = String(v).trim().toLowerCase();\n if (s === \"true\" || s === \"1\" || s === \"yes\" || s === \"on\") return true;\n if (s === \"false\" || s === \"0\" || s === \"no\" || s === \"off\") return false;\n return fallback;\n}\n\nfunction qqLinkConfigFile(): string {\n return join(env.PROJECT_ROOT, \"configs\", `${QQ_LINK_CONFIG_KEY}.json`);\n}\n\nfunction readJoinFlags(): JoinFeatureFlags {\n // \u6A21\u5757\u914D\u7F6E configs/qq_link.json\uFF08\u975E SDK qq_config\uFF09\n const disk = ensureJson<Record<string, unknown>>(qqLinkConfigFile(), { ...QQ_LINK_DEFAULTS });\n return {\n allowlistEnabled: asConfigBool(disk.allowlist_enabled, QQ_LINK_DEFAULTS.allowlist_enabled),\n requireApproval: asConfigBool(disk.require_approval, QQ_LINK_DEFAULTS.require_approval),\n treatGroupAdminsAsAdmins: asConfigBool(\n disk.treat_group_admins_as_admins,\n QQ_LINK_DEFAULTS.treat_group_admins_as_admins\n ),\n };\n}\n\nfunction writeJoinFlags(partial: Partial<JoinFeatureFlags>): JoinFeatureFlags {\n const file = qqLinkConfigFile();\n ensureJson<Record<string, unknown>>(file, { ...QQ_LINK_DEFAULTS });\n const patch: Record<string, boolean> = {};\n if (partial.allowlistEnabled !== undefined) patch.allowlist_enabled = partial.allowlistEnabled;\n if (partial.requireApproval !== undefined) patch.require_approval = partial.requireApproval;\n // \u6545\u610F\u4E0D\u5199 treat_group_admins_as_admins\uFF1A\u4EC5\u4EBA\u5DE5\u6539 configs/qq_link.json\n if (Object.keys(patch).length > 0) {\n patchJson(file, patch);\n }\n return readJoinFlags();\n}\n\n// \u542F\u52A8\u5373\u843D\u76D8\u6A21\u5757\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u907F\u514D\u300C\u4ECE\u672A\u70B9\u8FC7\u914D\u7F6E/\u7533\u8BF7\u300D\u65F6 configs/qq_link.json \u4E0D\u5B58\u5728\n{\n const created = !readJson(qqLinkConfigFile());\n ensureJson<Record<string, unknown>>(qqLinkConfigFile(), { ...QQ_LINK_DEFAULTS });\n if (created) {\n log.info(`\u5DF2\u5199\u5165\u6A21\u5757\u914D\u7F6E\u9AA8\u67B6: configs/${QQ_LINK_CONFIG_KEY}.json`);\n }\n}\n\nconst qqJoinRoutes = createQqJoinRoutes({\n query,\n body,\n json,\n getAdminOpenids: () => {\n const raw = (env.qqconfig[\"official\"] as { admin_openids?: unknown } | undefined)?.admin_openids;\n if (!Array.isArray(raw)) return [];\n return raw.map((x) => String(x).trim()).filter(Boolean);\n },\n getJoinFlags: () => readJoinFlags(),\n setJoinFlags: (partial) => writeJoinFlags(partial),\n});\n\nfunction readQqEventsSettings(): ResolvedQqEventsConfig {\n const disk = readJson<Record<string, unknown>>(join(env.PROJECT_ROOT, \"configs\", \"qq_config.json\"));\n if (!disk) throw new Error(\"qq_config.json \u65E0\u6CD5\u8BFB\u53D6\uFF0C\u4E8B\u4EF6\u8BBE\u7F6E\u672A\u4FEE\u6539\");\n return resolveQqEventsConfig(disk.qq_events);\n}\n\nfunction writeQqEventsSettings(patch: Partial<ResolvedQqEventsConfig>): ResolvedQqEventsConfig {\n const file = join(env.PROJECT_ROOT, \"configs\", \"qq_config.json\");\n const settings = { ...readQqEventsSettings(), ...patch };\n patchJson(file, { qq_events: settings });\n return settings;\n}\n\nfunction currentOutbound() {\n return makeOutboundConfig({\n QQ_BACKEND: env.QQ_BACKEND,\n LLBOT_HOST: env.LLBOT_HOST,\n LLBOT_PORT: env.LLBOT_PORT,\n LLBOT_TOKEN: env.LLBOT_TOKEN,\n QQ_GROUP_ID: env.QQ_GROUP_ID,\n QQ_APP_ID: env.QQ_APP_ID,\n QQ_APP_SECRET: env.QQ_APP_SECRET,\n QQ_SANDBOX: env.QQ_SANDBOX,\n QQ_GROUP_OPENID: env.QQ_GROUP_OPENID,\n });\n}\n\nconst qqEventsAggregator = createQqEventsAggregator({\n getConfig: readQqEventsSettings,\n getOutbound: () => currentOutbound(),\n});\nconst qqEventsRoutes = createQqEventsRoutes({\n body,\n json,\n aggregator: qqEventsAggregator,\n getSettings: readQqEventsSettings,\n setSettings: writeQqEventsSettings,\n isAdmin: (openid, asGroupAdmin) => {\n const admins = (env.qqconfig[\"official\"] as { admin_openids?: unknown } | undefined)?.admin_openids;\n return (\n (Array.isArray(admins) && admins.includes(openid)) ||\n (asGroupAdmin && readJoinFlags().treatGroupAdminsAsAdmins)\n );\n },\n});\n\nconst messagesRoutes = createMessagesRoutes({\n query,\n body,\n json,\n getChannelForQQ: (channelId: string) => {\n const rows = query(\n SQL`SELECT * FROM sfmc_chat_channels WHERE id = ${channelId}`\n );\n return Array.isArray(rows)\n ? (rows[0] as { prefix: string; forward_to_qq: number; source_game?: number; source_qq?: number; source_system?: number } | undefined) ?? null\n : null;\n },\n forwardToQQBridge: (channelId: string, prefix: string, fromName: string, content: string, fromId: string) =>\n forwardToQQBridge(currentOutbound(), channelId, prefix, fromName, content, fromId),\n});\nconst configRoutes = createConfigRoutes({\n json,\n projectRoot: env.PROJECT_ROOT,\n // DIP:\u8DEF\u7531\u4E0D\u8BFB lock/catalog/token \u6587\u4EF6,\u7531\u5165\u53E3\u6CE8\u5165\u4E0E /modules \u540C\u6E90\u6570\u636E\n listModules: () => buildModuleList() as Array<Record<string, unknown>>,\n getModuleTokens: () => ({ ...moduleAuth.tokens }),\n});\nconst contentRoutes = createContentRoutes({\n json,\n loadSnapshot: loadContentSnapshotForRequest,\n});\nconst moduleRoutesInstance = createModuleRoutes({\n loadModuleCatalog,\n buildModuleList: buildModuleList as unknown as () => Array<Record<string, unknown>>,\n resolveModuleByKey,\n setModuleEnabled,\n body,\n json,\n});\n\n// \u2500\u2500 v2 \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// \u7C7B\u578B\u65AD\u8A00\u6210 unknown \u51FD\u6570 \u2014 v2 routes \u7684 ctx \u7C7B\u578B\u4E0E RouteCtx \u4E0D\u517C\u5BB9,\n// \u4F46\u8C03\u7528\u5951\u7EA6({path, method, params, req, res, body?})\u662F\u7A33\u5B9A\u7684\u3002\nconst dbRoutes = createDbRoutes({ schemaRegistry, txRunner, idempotent, json }) as unknown as (\n ctx: Record<string, unknown>\n) => Promise<boolean>;\nconst serviceRoutes = createServiceRoutes({\n serviceRegistry,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\nconst moduleConfigRoutes = createModuleConfigRoutes({\n projectRoot: env.PROJECT_ROOT,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\n\n// \u2500\u2500 \u4E3B\u8BF7\u6C42\u5904\u7406\u5668 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nasync function handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n const url = new URL(req.url || \"/\", `http://${req.headers.host || \"localhost\"}`);\n const path = url.pathname;\n const method = req.method || \"GET\";\n const params = url.searchParams;\n\n // loopback \u7ED1\u5B9A\n const remote = req.socket.remoteAddress || \"\";\n if (remote && !remote.startsWith(\"127.\") && remote !== \"::1\" && remote !== \"::ffff:127.\") {\n json(res, { success: false, error: \"forbidden\" }, 403);\n return;\n }\n\n // \u2500\u2500 \u9884\u8BFB body(\u6240\u6709\u8DEF\u7531\u5171\u4EAB) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n await body(req);\n\n // \u2500\u2500 v2 \u6A21\u5757\u8EAB\u4EFD\u6821\u9A8C \u2192 \u5199\u5165\u8DEF\u7531 ctx.moduleAuth(LoD:\u4E0D\u6302 req \u79C1\u6709\u5B57\u6BB5) \u2500\u2500\n // \u6CE8\u610F:`/api/sfmc/configs/all` \u662F\u65E7\u7684\u4E00\u6B21\u6027\u914D\u7F6E\u5FEB\u7167\u7AEF\u70B9(SAPI ConfigManager.init\n // \u542F\u52A8\u5FC5\u7528),\u4E0D\u5C5E\u4E8E v2 \u6A21\u5757\u914D\u7F6E\u547D\u540D\u7A7A\u95F4(configs/<\u6A21\u5757 configKey>),\u5FC5\u987B\u8C41\u514D,\n // \u5426\u5219\u4F1A\u88AB\u6A21\u5757\u9274\u6743\u7F51\u5173\u62E6\u6210 401,\u5BFC\u81F4\u63D2\u4EF6\u7AEF\u8D77\u4E0D\u6765\u3002\n const isLegacyConfigAll = path === \"/api/sfmc/configs/all\";\n const needsModuleAuth =\n path.startsWith(\"/api/sfmc/db/\") ||\n path.startsWith(\"/api/sfmc/services\") ||\n (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+(?:\\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll);\n let moduleAuthCtx: { id: string; permissions: string[] } | null = null;\n if (needsModuleAuth) {\n const id = verifyModuleAuth({\n headers: req.headers,\n params,\n auth: moduleAuth,\n enabledModuleIds: enabledSet,\n });\n if (!id) {\n // LSP: v2 \u6A21\u5757\u95E8\u4E0E service-routes \u540C\u7528 ok \u65B9\u8A00\n jsonV2Fail(res, \"unauthorized: module identity invalid\", 401, \"unauthorized\");\n return;\n }\n const manifest = enabledManifests.get(id);\n moduleAuthCtx = {\n id,\n permissions: manifest?.permissions ?? [],\n };\n } else {\n // \u2500\u2500 \u65E7 env token \u9274\u6743(\u53EA\u5BF9 POST/PUT \u751F\u6548) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const PUBLIC_GET =\n path === \"/api/health\" ||\n path === \"/api/sfmc/status\" ||\n path === \"/api/sfmc/qq/join/apply-queue\" ||\n path === \"/api/sfmc/qq/join/settings\" ||\n path === \"/api/sfmc/qq/admin/action-queue\" ||\n (method === \"GET\" &&\n (path === \"/api/sfmc/content\" ||\n path === \"/api/sfmc/modules\" ||\n path === \"/api/sfmc/modules/catalog\" ||\n path.startsWith(\"/api/sfmc/modules/\") ||\n path === \"/api/sfmc/qq/bind/me\" ||\n path === \"/api/sfmc/qq/join/pending\"));\n // bind/join/events POST \u4E0E messages \u4E00\u6837\u8D70\u65E7 AUTH_TOKEN\uFF08\u82E5\u914D\u7F6E\uFF09\uFF1B\u6E38\u620F/\u6865\u540C\u4E3A loopback\n const NEEDS_AUTH =\n !PUBLIC_GET &&\n method !== \"GET\" &&\n !(\n path.startsWith(\"/api/sfmc/qq/bind/\") ||\n path.startsWith(\"/api/sfmc/qq/join/\") ||\n path.startsWith(\"/api/sfmc/qq/admin/\") ||\n path.startsWith(\"/api/sfmc/qq/events\")\n );\n if (env.AUTH_TOKEN && NEEDS_AUTH) {\n const auth = req.headers[\"authorization\"] || \"\";\n const provided = auth.startsWith(\"Bearer \") ? auth.slice(7) : (req.headers[\"x-db-token\"] as string) || \"\";\n if (provided !== env.AUTH_TOKEN) {\n json(res, { success: false, error: \"unauthorized\" }, 401);\n return;\n }\n }\n }\n\n try {\n if (path === \"/api/sfmc/player-session\" && method === \"POST\") {\n const data = (await body(req)) as Record<string, unknown>;\n const playerName = String(data.playerName ?? \"\").trim();\n const xuid = String(data.xuid ?? \"\").trim();\n if (!playerName || !xuid) {\n json(res, { success: false, error: \"playerName_and_xuid_required\" }, 400);\n return;\n }\n syncPlayerSession(query, { playerName, xuid });\n json(res, { success: true });\n return;\n }\n // \u2500\u2500 v2 \u8DEF\u7531(\u4F18\u5148\u5339\u914D) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (\n moduleAuthCtx &&\n (path.startsWith(\"/api/sfmc/db/\") ||\n path.startsWith(\"/api/sfmc/services\") ||\n (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll))\n ) {\n const ctx: Record<string, unknown> = {\n path,\n method,\n params,\n req,\n res,\n moduleAuth: moduleAuthCtx,\n };\n // body \u5DF2\u5728\u4E0A\u9762 `await body(req)` \u9884\u8BFB\u5E76\u7F13\u5B58\u5230 req._bodyPromise;\n // \u8FD9\u91CC\u590D\u7528\u7F13\u5B58(\u539F\u5B9E\u73B0\u8BFB\u7684 req._body \u4ECE\u672A\u88AB\u8D4B\u503C,\u5BFC\u81F4\u6240\u6709 v2 \u8DEF\u7531 body \u6052\u4E3A\u7A7A)\u3002\n ctx[\"body\"] = await body(req);\n if (path.startsWith(\"/api/sfmc/db/\")) {\n if (await dbRoutes(ctx)) return;\n } else if (path.startsWith(\"/api/sfmc/services\")) {\n if (await serviceRoutes(ctx)) return;\n } else {\n if (await moduleConfigRoutes(ctx)) return;\n }\n }\n\n // \u2500\u2500 \u5E73\u53F0\u8DEF\u7531 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctxBase = { path, method, params, req, res } as {\n path: string;\n method: string;\n params: URLSearchParams;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n };\n if (await contentRoutes(ctxBase)) return;\n if (await moduleRoutesInstance(ctxBase)) return;\n if (await healthRoutes(ctxBase)) return;\n if (await statusRoutes(ctxBase)) return;\n if (await qqBindRoutes(ctxBase)) return;\n if (await qqJoinRoutes(ctxBase)) return;\n if (await qqEventsRoutes(ctxBase)) return;\n if (await messagesRoutes(ctxBase)) return;\n if (await configRoutes(ctxBase)) return;\n\n json(res, { success: false, error: \"not_found\" }, 404);\n } catch (err) {\n log.err(err, \"DogeDB\");\n json(res, { success: false, error: (err as Error).message }, 500);\n }\n}\n\n// \u2500\u2500 \u542F\u52A8 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst server = createServer({\n env: { PORT: env.PORT, HOST: env.HOST, AUTH_TOKEN: env.AUTH_TOKEN },\n handle,\n});\nstartConsole(server, db);\n\nexport { db, enabledManifests, env, moduleAuth, query, schemaRegistry, serviceRegistry, txRunner };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path"]
|
|
7
7
|
}
|
package/dist/routes/config.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 路由列表:
|
|
5
5
|
* GET /api/sfmc/configs/all — SAPI ConfigManager 启动快照(仅平台域)
|
|
6
6
|
* GET /api/sfmc/settings — 平铺 settings.json(legacy)
|
|
7
|
-
* GET /api/sfmc/settings/:key — 含 land:*
|
|
7
|
+
* GET /api/sfmc/settings/:key — 含 land:* 等 fallback
|
|
8
8
|
* GET /api/sfmc/areas|permissions|… — legacy 只读 JSON(文件名对 db-server 为黑箱)
|
|
9
9
|
*
|
|
10
10
|
* DIP:模块/legacy JSON 不进 SDK ConfigName;本路由用 configDir + 文件名拼接路径。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,UAAU,IAAI;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnG,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAmCD,iBAAS,kBAAkB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,UAAU,IAAI;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnG,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAmCD,iBAAS,kBAAkB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,EAAE,IAAI,iDAqGhF;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,GAAG,EAAE,OAAO,MAAM,EAAE,cAAc,CAAC;CACpC,KAAG,OAAO,CAAC,OAAO,CAAC,CAuErB;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/routes/config.js
CHANGED
|
@@ -50,10 +50,6 @@ function createConfigRoutes({ json, projectRoot, listModules, getModuleTokens })
|
|
|
50
50
|
if (Object.prototype.hasOwnProperty.call(settings, key) && !isMetaKey(key)) {
|
|
51
51
|
return { value: settings[key], source: "settings.json" };
|
|
52
52
|
}
|
|
53
|
-
if (key === "bridge_channel_id") {
|
|
54
|
-
const qq = readPlatform("qq_config.json") ?? {};
|
|
55
|
-
if (qq.bridge_channel_id) return { value: qq.bridge_channel_id, source: "qq_config.json" };
|
|
56
|
-
}
|
|
57
53
|
if (key.startsWith("land:")) {
|
|
58
54
|
const land = readOpaque("land.json") ?? {};
|
|
59
55
|
if (Object.prototype.hasOwnProperty.call(land, key) && !isMetaKey(key)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/routes/config.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * routes/config.ts \u2014 \u914D\u7F6E\u8DEF\u7531\n *\n * \u8DEF\u7531\u5217\u8868\uFF1A\n * GET /api/sfmc/configs/all \u2014 SAPI ConfigManager \u542F\u52A8\u5FEB\u7167\uFF08\u4EC5\u5E73\u53F0\u57DF\uFF09\n * GET /api/sfmc/settings \u2014 \u5E73\u94FA settings.json\uFF08legacy\uFF09\n * GET /api/sfmc/settings/:key \u2014 \u542B land:*
|
|
5
|
-
"mappings": "AAaA,SAAS,YAAY;AACrB,SAAS,WAAW,YAAY,gBAAiC;AAiBjE,SAAS,UAAU,GAAoB;AACrC,SAAO,MAAM,aAAa,OAAO,CAAC,EAAE,WAAW,GAAG;AACpD;AAEA,SAAS,cAAc,GAAqB;AAC1C,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,IAAI,aAAa;AAChD,MAAI,KAAK,OAAO,MAAM,UAAU;AAC9B,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,CAA4B,GAAG;AACnE,UAAI,CAAC,UAAU,CAAC,EAAG,KAAI,CAAC,IAAI,cAAc,GAAG;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,UAAU,KAA8D;AAC/E,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACnE,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,CAAC,UAAU,CAAC,EAAG,KAAI,CAAC,IAAI;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,SAAS,UAAU,GAAoB;AACrC,SAAO,MAAM,QAAQ,OAAO,MAAM,WAAW,KAAK,UAAU,CAAC,IAAI,OAAO,KAAK,EAAE;AACjF;AAEA,SAAS,aAAa,GAAuB;AAC3C,SAAO,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC;AACjC;AAEA,SAAS,mBAAmB,EAAE,MAAM,aAAa,aAAa,gBAAgB,GAAS;AAErF,QAAM,eAAe,CAAC,SAA8B,SAAS,WAAW,aAAa,IAAI,CAAC;AAE1F,QAAM,aAAa,CAAC,aAA8B,SAAS,KAAK,UAAU,WAAW,GAAG,QAAQ,CAAC;AAMjG,WAAS,gBAAyC;AAChD,UAAM,UAAU,OAAO,gBAAgB,aAAa,YAAY,IAAI,CAAC;AACrE,UAAM,gBAAgB,OAAO,oBAAoB,aAAa,gBAAgB,IAAI,CAAC;AACnF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,UAAU,WAAW,eAAe,CAAmC;AAAA,MACjF,aAAa,eAAe;AAAA,IAC9B;AAAA,EACF;AAEA,WAAS,kBAAyD;AAChE,UAAM,MAAM,UAAU,WAAW,eAAe,CAAmC;AACnF,WAAO,OAAO,QAAQ,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,KAAK,OAAO,UAAU,KAAK,EAAE,EAAE;AAAA,EACrF;AAEA,WAAS,gBAAgB,KAAkD;AACzE,UAAM,WAAY,WAAW,eAAe,KAAwC,CAAC;AACrF,QAAI,OAAO,UAAU,eAAe,KAAK,UAAU,GAAG,KAAK,CAAC,UAAU,GAAG,GAAG;AAC1E,aAAO,EAAE,OAAO,SAAS,GAAG,GAAG,QAAQ,gBAAgB;AAAA,IACzD;AACA,QAAI,
|
|
4
|
+
"sourcesContent": ["/**\n * routes/config.ts \u2014 \u914D\u7F6E\u8DEF\u7531\n *\n * \u8DEF\u7531\u5217\u8868\uFF1A\n * GET /api/sfmc/configs/all \u2014 SAPI ConfigManager \u542F\u52A8\u5FEB\u7167\uFF08\u4EC5\u5E73\u53F0\u57DF\uFF09\n * GET /api/sfmc/settings \u2014 \u5E73\u94FA settings.json\uFF08legacy\uFF09\n * GET /api/sfmc/settings/:key \u2014 \u542B land:* \u7B49 fallback\n * GET /api/sfmc/areas|permissions|\u2026 \u2014 legacy \u53EA\u8BFB JSON\uFF08\u6587\u4EF6\u540D\u5BF9 db-server \u4E3A\u9ED1\u7BB1\uFF09\n *\n * DIP\uFF1A\u6A21\u5757/legacy JSON \u4E0D\u8FDB SDK ConfigName\uFF1B\u672C\u8DEF\u7531\u7528 configDir + \u6587\u4EF6\u540D\u62FC\u63A5\u8DEF\u5F84\u3002\n * \u6A21\u5757\u79C1\u6709\u914D\u7F6E\u7684\u8BFB\u5199\u6743\u5A01\u5165\u53E3\u662F module-config-routes\uFF08configs/:configKey\uFF09\u3002\n */\n\nimport { join } from \"node:path\";\nimport { configDir, configPath, readJson, type ConfigName } from \"@sfmc-bds/sdk/node/config\";\n\ninterface Deps {\n json: (res: import(\"http\").ServerResponse, data: Record<string, unknown>, status?: number) => void;\n projectRoot: string;\n /**\n * \u6CE8\u5165\u6A21\u5757\u5217\u8868(\u4E0E GET /api/sfmc/modules \u540C\u6E90 \u2014 DRY)\u3002\n * \u52FF\u5728\u672C\u8DEF\u7531\u518D\u8BFB catalog/lock(DIP:\u9AD8\u5C42\u88C5\u914D,\u8DEF\u7531\u53EA\u6D88\u8D39\u62BD\u8C61)\u3002\n */\n listModules?: () => Array<Record<string, unknown>>;\n /**\n * \u6CE8\u5165\u6A21\u5757 HMAC token \u8868(\u4EC5 loopback \u53EF\u8FBE;\u4F9B SAPI host-bootstrap \u6CE8\u5165\n * set*ModuleContext,\u56E0 SAPI \u4E0D\u80FD\u76F4\u63A5\u8BFB\u4E0E DB \u540C\u76EE\u5F55\u7684 module-tokens.json)\u3002\n */\n getModuleTokens?: () => Record<string, string>;\n}\n\nfunction isMetaKey(k: string): boolean {\n return k === \"$schema\" || String(k).startsWith(\"_\");\n}\n\nfunction stripMetaDeep(v: unknown): unknown {\n if (Array.isArray(v)) return v.map(stripMetaDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) {\n if (!isMetaKey(k)) out[k] = stripMetaDeep(val);\n }\n return out;\n }\n return v;\n}\n\nfunction stripMeta(obj: Record<string, unknown> | null): Record<string, unknown> {\n if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!isMetaKey(k)) out[k] = v;\n }\n return out;\n}\n\nfunction jsonValue(v: unknown): string {\n return v !== null && typeof v === \"object\" ? JSON.stringify(v) : String(v ?? \"\");\n}\n\nfunction arrayOrEmpty(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\nfunction createConfigRoutes({ json, projectRoot, listModules, getModuleTokens }: Deps) {\n /** \u5E73\u53F0 ConfigName\uFF08qq_config \u7B49\uFF09 */\n const readPlatform = (name: ConfigName): unknown => readJson(configPath(projectRoot, name));\n /** \u9ED1\u7BB1 JSON\uFF1A\u4EFB\u610F configs/<file>\uFF0C\u4E0D\u8FDB ConfigName */\n const readOpaque = (fileName: string): unknown => readJson(join(configDir(projectRoot), fileName));\n\n /**\n * SAPI ConfigManager \u5951\u7EA6\uFF1A\u53EA\u7F13\u5B58 modules / settings / permissions\u3002\n * \u52FF\u518D\u5F80 all \u585E areas \u7B49 legacy \u57DF\uFF08\u90A3\u4E9B\u8D70\u4E13\u7528 GET \u6216\u6A21\u5757 configKey\uFF09\u3002\n */\n function getAllConfigs(): Record<string, unknown> {\n const modules = typeof listModules === \"function\" ? listModules() : [];\n const module_tokens = typeof getModuleTokens === \"function\" ? getModuleTokens() : {};\n return {\n modules,\n module_tokens,\n settings: stripMeta(readOpaque(\"settings.json\") as Record<string, unknown> | null),\n permissions: getPermissions(),\n };\n }\n\n function getSettingsFlat(): Array<{ key: string; value: string }> {\n const obj = stripMeta(readOpaque(\"settings.json\") as Record<string, unknown> | null);\n return Object.entries(obj).map(([key, value]) => ({ key, value: jsonValue(value) }));\n }\n\n function getSettingByKey(key: string): { value: unknown; source?: string } {\n const settings = (readOpaque(\"settings.json\") as Record<string, unknown> | null) ?? {};\n if (Object.prototype.hasOwnProperty.call(settings, key) && !isMetaKey(key)) {\n return { value: settings[key], source: \"settings.json\" };\n }\n if (key.startsWith(\"land:\")) {\n const land = (readOpaque(\"land.json\") as Record<string, unknown> | null) ?? {};\n if (Object.prototype.hasOwnProperty.call(land, key) && !isMetaKey(key)) {\n return { value: land[key], source: \"land.json\" };\n }\n }\n return { value: null };\n }\n\n function getAreas(): unknown[] {\n return (arrayOrEmpty(readOpaque(\"areas.json\")) as Array<Record<string, unknown>>)\n .filter((r) => r && r.module && r.dimension != null)\n .map((r) => stripMetaDeep(r));\n }\n\n function getPermissions(): unknown[] {\n return (arrayOrEmpty(readPlatform(\"permissions.json\")) as Array<Record<string, unknown>>)\n .filter((r) => r && r.player_name)\n .map((r) => stripMetaDeep(r));\n }\n\n function getBannedItems(): string[] {\n return (arrayOrEmpty(readOpaque(\"banned_items.json\")) as Array<string>).filter(\n (i) => typeof i === \"string\" && i && !i.startsWith(\"_\")\n );\n }\n\n function getClean(): { item_max: number; poll_interval: number } {\n const c = stripMetaDeep(readOpaque(\"clean.json\") ?? {}) as Record<string, unknown>;\n return { item_max: (c.item_max as number) ?? 192, poll_interval: (c.poll_interval as number) ?? 60 };\n }\n\n function getGrids(): unknown[] {\n return (arrayOrEmpty(readOpaque(\"grids.json\")) as Array<Record<string, unknown>>)\n .filter((r) => r && r.name)\n .map((r) => stripMetaDeep(r));\n }\n\n function getPeaceFilters(): unknown[] {\n return (arrayOrEmpty(readOpaque(\"peace_filters.json\")) as Array<Record<string, unknown>>)\n .filter((r) => r && r.family)\n .map((r) => stripMetaDeep(r));\n }\n\n function getQA(): Array<Record<string, unknown>> {\n return (arrayOrEmpty(readOpaque(\"questions.json\")) as Array<Record<string, unknown>>)\n .filter((r) => r && r.question)\n .map((r, idx) => {\n const clean = stripMetaDeep(r) as Record<string, unknown>;\n return {\n id: idx + 1,\n weight: clean.weight ?? 1,\n question: clean.question,\n answers: clean.answers ?? [],\n msg_right: clean.msg_right ?? \"\",\n msg_wrong: clean.msg_wrong ?? \"\",\n explanation: clean.explanation ?? \"\",\n min_rank: clean.min_rank ?? null,\n max_rank: clean.max_rank ?? null,\n rewards: clean.rewards ?? [],\n punishments: clean.punishments ?? [],\n };\n });\n }\n\n return async function handleConfigRoute({\n path: requestPath,\n method,\n params,\n res,\n }: {\n path: string;\n method: string;\n params: URLSearchParams;\n res: import(\"http\").ServerResponse;\n }): Promise<boolean> {\n void params;\n if (requestPath === \"/api/sfmc/configs/all\") {\n if (method !== \"GET\") {\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n json(res, getAllConfigs());\n return true;\n }\n if (requestPath === \"/api/sfmc/settings\") {\n if (method === \"GET\") {\n json(res, { settings: getSettingsFlat() });\n return true;\n }\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n if (requestPath.startsWith(\"/api/sfmc/settings/\")) {\n const key = decodeURIComponent(requestPath.slice(\"/api/sfmc/settings/\".length));\n if (method === \"GET\") {\n json(res, getSettingByKey(key));\n return true;\n }\n json(res, { success: false, error: \"method_not_allowed\" }, 405);\n return true;\n }\n if (requestPath === \"/api/sfmc/areas\") {\n if (method === \"GET\") {\n json(res, { areas: getAreas() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/permissions\") {\n if (method === \"GET\") {\n json(res, { permissions: getPermissions() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/banned_items\") {\n if (method === \"GET\") {\n json(res, { items: getBannedItems() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/clean\") {\n if (method === \"GET\") {\n json(res, { clean: getClean() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/grids\") {\n if (method === \"GET\") {\n json(res, { grids: getGrids() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/peace_filters\") {\n if (method === \"GET\") {\n json(res, { filters: getPeaceFilters() });\n return true;\n }\n }\n if (requestPath === \"/api/sfmc/qa\") {\n if (method === \"GET\") {\n json(res, { questions: getQA() });\n return true;\n }\n }\n return false;\n };\n}\n\nexport { createConfigRoutes };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routes/content.ts — QQ 查询已装模块与世界资源包。
|
|
3
|
+
*
|
|
4
|
+
* GET /api/sfmc/content
|
|
5
|
+
*
|
|
6
|
+
* 只读。模块启停与资源包文件仍由 catalog / 世界目录维护,本路由不改它们。
|
|
7
|
+
*/
|
|
8
|
+
import type { ContentSnapshot } from "../domain/installed-content.js";
|
|
9
|
+
interface Deps {
|
|
10
|
+
json: (res: import("http").ServerResponse, data: Record<string, unknown>, status?: number) => void;
|
|
11
|
+
/** 每次请求现读,避免 db-server 启动后装包却一直返回旧列表。 */
|
|
12
|
+
loadSnapshot: () => ContentSnapshot;
|
|
13
|
+
}
|
|
14
|
+
/** 创建内容查询路由。当前只给 qq-bridge 的「模块」「资源包」命令使用。 */
|
|
15
|
+
declare function createContentRoutes({ json, loadSnapshot }: Deps): ({ path, method, res, }: {
|
|
16
|
+
path: string;
|
|
17
|
+
method: string;
|
|
18
|
+
params: URLSearchParams;
|
|
19
|
+
req: import("http").IncomingMessage;
|
|
20
|
+
res: import("http").ServerResponse;
|
|
21
|
+
}) => Promise<boolean>;
|
|
22
|
+
export { createContentRoutes };
|
|
23
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/routes/content.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,UAAU,IAAI;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnG,yCAAyC;IACzC,YAAY,EAAE,MAAM,eAAe,CAAC;CACrC;AAED,8CAA8C;AAC9C,iBAAS,mBAAmB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,4BAKpD;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,GAAG,EAAE,OAAO,MAAM,EAAE,eAAe,CAAC;IACpC,GAAG,EAAE,OAAO,MAAM,EAAE,cAAc,CAAC;CACpC,KAAG,OAAO,CAAC,OAAO,CAAC,CASrB;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|