@sfmc-bds/db-server 0.5.2 → 0.6.0
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/bind-providers.d.ts +59 -0
- package/dist/domain/bind-providers.d.ts.map +1 -0
- package/dist/domain/bind-providers.js +33 -0
- package/dist/domain/bind-providers.js.map +7 -0
- package/dist/domain/metrics.d.ts +5 -0
- package/dist/domain/metrics.d.ts.map +1 -1
- package/dist/domain/metrics.js +28 -2
- package/dist/domain/metrics.js.map +2 -2
- package/dist/domain/player-level.d.ts +29 -0
- package/dist/domain/player-level.d.ts.map +1 -0
- package/dist/domain/player-level.js +30 -0
- package/dist/domain/player-level.js.map +7 -0
- package/dist/domain/process-resources.d.ts +12 -0
- package/dist/domain/process-resources.d.ts.map +1 -1
- package/dist/domain/process-resources.js +72 -1
- package/dist/domain/process-resources.js.map +2 -2
- package/dist/domain/qq-bind.d.ts +21 -0
- package/dist/domain/qq-bind.d.ts.map +1 -0
- package/dist/domain/qq-bind.js +54 -0
- package/dist/domain/qq-bind.js.map +7 -0
- package/dist/domain/schema.d.ts +1 -0
- package/dist/domain/schema.d.ts.map +1 -1
- package/dist/domain/schema.js +26 -0
- package/dist/domain/schema.js.map +2 -2
- package/dist/domain/tracked-processes.d.ts +30 -0
- package/dist/domain/tracked-processes.d.ts.map +1 -0
- package/dist/domain/tracked-processes.js +78 -0
- package/dist/domain/tracked-processes.js.map +7 -0
- package/dist/domain/wechat-bind.d.ts +56 -0
- package/dist/domain/wechat-bind.d.ts.map +1 -0
- package/dist/domain/wechat-bind.js +84 -0
- package/dist/domain/wechat-bind.js.map +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -7
- package/dist/index.js.map +2 -2
- package/dist/lib/sqlite.d.ts +10 -0
- package/dist/lib/sqlite.d.ts.map +1 -1
- package/dist/lib/sqlite.js +17 -2
- package/dist/lib/sqlite.js.map +2 -2
- package/dist/routes/bind-confirm.d.ts +30 -0
- package/dist/routes/bind-confirm.d.ts.map +1 -0
- package/dist/routes/bind-confirm.js +27 -0
- package/dist/routes/bind-confirm.js.map +7 -0
- package/dist/routes/qq-bind.d.ts +3 -1
- package/dist/routes/qq-bind.d.ts.map +1 -1
- package/dist/routes/qq-bind.js +8 -64
- package/dist/routes/qq-bind.js.map +2 -2
- package/dist/routes/status.d.ts.map +1 -1
- package/dist/routes/status.js +10 -2
- package/dist/routes/status.js.map +2 -2
- package/dist/routes/wechat-bind.d.ts +39 -0
- package/dist/routes/wechat-bind.d.ts.map +1 -0
- package/dist/routes/wechat-bind.js +56 -0
- package/dist/routes/wechat-bind.js.map +7 -0
- package/package.json +5 -4
package/dist/routes/status.js
CHANGED
|
@@ -2,6 +2,7 @@ import { collectSystemStatus } from "../domain/system-status.js";
|
|
|
2
2
|
import { PROJECT_ROOT } from "../project-root.js";
|
|
3
3
|
import { METRICS_RAW_WINDOW_MS, MetricsHistory, ResourceHistory, clampMetricsSpan, parseMetrics } from "../domain/metrics.js";
|
|
4
4
|
import { collectProcessResources } from "../domain/process-resources.js";
|
|
5
|
+
import { collectTrackedProcesses } from "../domain/tracked-processes.js";
|
|
5
6
|
import fs from "node:fs";
|
|
6
7
|
import pathModule from "node:path";
|
|
7
8
|
import { stateDir } from "@sfmc-bds/sdk/node/config";
|
|
@@ -27,14 +28,21 @@ function createStatusRoutes({ collectSystem, projectRoot, query }) {
|
|
|
27
28
|
db: await collectProcessResources(system.db.pid, system.db.running),
|
|
28
29
|
bds: owned ? await collectProcessResources(system.bds.pid, system.bds.running) : null
|
|
29
30
|
};
|
|
31
|
+
const skip = /* @__PURE__ */ new Set();
|
|
32
|
+
if (processes.db.pid > 0) skip.add(processes.db.pid);
|
|
33
|
+
if (processes.bds && processes.bds.pid > 0) skip.add(processes.bds.pid);
|
|
34
|
+
const parts = await collectTrackedProcesses(root, skip);
|
|
35
|
+
const partsMb = {};
|
|
36
|
+
for (const part of parts) partsMb[part.key] = part.memoryMb;
|
|
30
37
|
resources?.append({
|
|
31
38
|
recordedAt: Date.now(),
|
|
32
39
|
hostUsedMb: system.host.memory.usedMb,
|
|
33
40
|
dbMb: processes.db.memoryMb,
|
|
34
|
-
bdsMb: processes.bds?.memoryMb ?? null
|
|
41
|
+
bdsMb: processes.bds?.memoryMb ?? null,
|
|
42
|
+
...Object.keys(partsMb).length ? { partsMb } : {}
|
|
35
43
|
});
|
|
36
44
|
lastCapture = Date.now();
|
|
37
|
-
return processes;
|
|
45
|
+
return { ...processes, ...parts.length ? { parts } : {} };
|
|
38
46
|
};
|
|
39
47
|
let systemCache;
|
|
40
48
|
let collecting;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/routes/status.ts"],
|
|
4
|
-
"sourcesContent": ["/** GET /api/sfmc/status \u4E0E BDS \u5B9E\u65F6\u5FEB\u7167\u5165\u53E3\u3002 */\n\nimport { collectSystemStatus, type SystemStatusSnapshot } from \"../domain/system-status.js\";\nimport { PROJECT_ROOT } from \"../project-root.js\";\nimport { METRICS_RAW_WINDOW_MS, MetricsHistory, ResourceHistory, clampMetricsSpan, parseMetrics, type MetricsSample } from \"../domain/metrics.js\";\nimport { collectProcessResources } from \"../domain/process-resources.js\";\nimport type { QueryFn } from \"../lib/sqlite.js\";\nimport fs from \"node:fs\";\nimport pathModule from \"node:path\";\nimport { stateDir } from \"@sfmc-bds/sdk/node/config\";\nimport { body, json, type RouteFactory } from \"./_shared.js\";\n\nconst FRESH_MS = 60_000;\n\ninterface LiveSnapshot {\n online: Array<{ name: string }>;\n world: { day: number; difficulty: string };\n updatedAt: number;\n}\n\ninterface Deps {\n collectSystem?: (projectRoot: string) => Promise<SystemStatusSnapshot>;\n projectRoot?: string;\n query?: QueryFn;\n}\n\nfunction createStatusRoutes({ collectSystem, projectRoot, query }: Deps): ReturnType<RouteFactory> {\n const root = projectRoot ?? PROJECT_ROOT;\n const collect = collectSystem ?? collectSystemStatus;\n let live: LiveSnapshot | null = null;\n let metrics: MetricsSample | null = null;\n const history = query ? new MetricsHistory(query) : undefined;\n const resources = query ? new ResourceHistory(query) : undefined;\n let lastCapture = 0;\n const captureResources = async (system: SystemStatusSnapshot | null) => {\n if (!system) return null;\n let ownedPid = 0;\n try { ownedPid = Number(fs.readFileSync(pathModule.join(stateDir(root), \"bds.pid\"), \"utf8\").trim()); } catch { /* \u672A\u6258\u7BA1\u5B9E\u4F8B\u4E0D\u731C\u6D4B\u8FDB\u7A0B\u5F52\u5C5E\u3002 */ }\n const owned = Number.isSafeInteger(ownedPid) && ownedPid > 0 && system.bds.pid === ownedPid;\n const processes = {\n db: await collectProcessResources(system.db.pid, system.db.running),\n bds: owned ? await collectProcessResources(system.bds.pid, system.bds.running) : null,\n };\n resources?.append({\n recordedAt: Date.now(),\n hostUsedMb: system.host.memory.usedMb,\n dbMb: processes.db.memoryMb,\n bdsMb: processes.bds?.memoryMb ?? null,\n });\n lastCapture = Date.now();\n return processes;\n };\n let systemCache: { data: SystemStatusSnapshot; at: number } | undefined;\n let collecting: Promise<SystemStatusSnapshot> | undefined;\n const getSystem = async () => {\n if (systemCache && Date.now() - systemCache.at < 5000) return systemCache.data;\n collecting ??= collect(root).then(data => { systemCache = { data, at: Date.now() }; return data; }).finally(() => { collecting = undefined; });\n return collecting;\n };\n if (resources) {\n const timer = setInterval(() => {\n if (Date.now() - lastCapture < 12_000) return;\n void getSystem().then(system => captureResources(system)).catch(() => undefined);\n }, 15_000);\n timer.unref();\n }\n\n return async function handle({ path, method, params, req, res }): Promise<boolean> {\n if (path === \"/api/sfmc/status/live\" || path === \"/api/sfmc/metrics/live\") {\n if (method !== \"POST\") {\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n const data = await body(req);\n const raw = data.players;\n const day = data.day;\n const difficulty = data.difficulty;\n if (\n !Array.isArray(raw) || raw.length > 1000 ||\n !raw.every((name) => typeof name === \"string\" && name.trim().length > 0 && name.length <= 64) ||\n typeof day !== \"number\" || !Number.isSafeInteger(day) || day < 0 ||\n typeof difficulty !== \"string\" || difficulty.length > 32\n ) {\n json(res, { success: false, error: \"invalid_live_status\" }, 400);\n return true;\n }\n if (path === \"/api/sfmc/metrics/live\") {\n const sample = parseMetrics(data, Date.now());\n if (!sample) { json(res, { success: false, error: \"invalid_metrics\" }, 400); return true; }\n history?.append(sample);\n metrics = sample;\n }\n live = {\n online: raw.map((name: string) => ({ name: name.trim() })),\n world: { day, difficulty },\n updatedAt: Date.now(),\n };\n json(res, { success: true });\n return true;\n }\n\n if (path !== \"/api/sfmc/status\" && path !== \"/api/sfmc/metrics\") return false;\n if (method !== \"GET\") {\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n\n let system: SystemStatusSnapshot | null = null;\n try {\n system = await getSystem();\n } catch {\n system = null;\n }\n\n const now = Date.now();\n const bds = system?.bds;\n const bdsAgeMs = typeof bds?.uptimeSec === \"number\" ? bds.uptimeSec * 1000 : null;\n const snapshot = live;\n const fresh = snapshot !== null &&\n bds?.state === \"running\" &&\n now - snapshot.updatedAt <= FRESH_MS &&\n (bdsAgeMs === null || now - snapshot.updatedAt <= bdsAgeMs + 2_000);\n const current = fresh ? snapshot : null;\n\n if (path === \"/api/sfmc/metrics\") {\n // \u8D44\u6E90\u6307\u6807\u53EA\u8BA4\u5F53\u524D\u5B9E\u4F8B\u7684 PID\uFF0C\u4E0D\u80FD\u4F7F\u7528\u5168\u673A\u626B\u63CF\u627E\u5230\u7684\u53E6\u4E00\u5957 BDS\u3002\n let ownedPid = 0;\n try { ownedPid = Number(fs.readFileSync(pathModule.join(stateDir(root), \"bds.pid\"), \"utf8\").trim()); } catch { /* \u672A\u6258\u7BA1\u5B9E\u4F8B\u4E0D\u731C\u6D4B\u8FDB\u7A0B\u5F52\u5C5E\u3002 */ }\n const owned = Number.isSafeInteger(ownedPid) && ownedPid > 0 && bds?.pid === ownedPid;\n const metricFresh = owned && metrics !== null && bds?.state === \"running\" && now - metrics.recordedAt <= 60_000 &&\n (bdsAgeMs === null || now - metrics.recordedAt <= bdsAgeMs + 2000);\n const processes = await captureResources(system);\n let span = METRICS_RAW_WINDOW_MS;\n const rawSpan = params.get(\"spanMs\");\n if (rawSpan) {\n try { span = clampMetricsSpan(Number(rawSpan)); } catch {\n json(res, { success: false, error: \"invalid_span\" }, 400);\n return true;\n }\n }\n json(res, { fresh: metricFresh, current: metricFresh ? metrics : null, updatedAt: metrics?.recordedAt ?? null,\n history: history?.read(now, span) ?? [], host: system?.host ?? null, processes, resourcesUpdatedAt: system ? Date.now() : null,\n resourceHistory: resources?.read(now, span) ?? [],\n note: metricFresh ? undefined : bds?.state === \"stopped\" ? \"\u670D\u52A1\u5668\u672A\u8FD0\u884C\" : \"\u7B49\u5F85\u5E73\u53F0\u6307\u6807\u540C\u6B65\" });\n return true;\n }\n\n json(res, {\n online: current?.online ?? [],\n world: current?.world ?? null,\n updatedAt: current?.updatedAt ?? null,\n host: system?.host ?? null,\n processes: system ? { db: system.db, bds: system.bds } : null,\n source: \"bds_script_live\",\n note: fresh ? undefined : bds?.state === \"stopped\" ? \"\u670D\u52A1\u5668\u672A\u8FD0\u884C\" : \"\u7B49\u5F85\u6E38\u620F\u5B9E\u65F6\u72B6\u6001\u540C\u6B65\",\n });\n return true;\n };\n}\n\nexport { createStatusRoutes, FRESH_MS };\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,2BAAsD;AAC/D,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB,gBAAgB,iBAAiB,kBAAkB,oBAAwC;AAC3H,SAAS,+BAA+B;AAExC,OAAO,QAAQ;AACf,OAAO,gBAAgB;AACvB,SAAS,gBAAgB;AACzB,SAAS,MAAM,YAA+B;AAE9C,MAAM,WAAW;AAcjB,SAAS,mBAAmB,EAAE,eAAe,aAAa,MAAM,GAAmC;AACjG,QAAM,OAAO,eAAe;AAC5B,QAAM,UAAU,iBAAiB;AACjC,MAAI,OAA4B;AAChC,MAAI,UAAgC;AACpC,QAAM,UAAU,QAAQ,IAAI,eAAe,KAAK,IAAI;AACpD,QAAM,YAAY,QAAQ,IAAI,gBAAgB,KAAK,IAAI;AACvD,MAAI,cAAc;AAClB,QAAM,mBAAmB,OAAO,WAAwC;AACtE,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI,WAAW;AACf,QAAI;AAAE,iBAAW,OAAO,GAAG,aAAa,WAAW,KAAK,SAAS,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,KAAK,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAsB;AACnI,UAAM,QAAQ,OAAO,cAAc,QAAQ,KAAK,WAAW,KAAK,OAAO,IAAI,QAAQ;AACnF,UAAM,YAAY;AAAA,MAChB,IAAI,MAAM,wBAAwB,OAAO,GAAG,KAAK,OAAO,GAAG,OAAO;AAAA,MAClE,KAAK,QAAQ,MAAM,wBAAwB,OAAO,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI;AAAA,IACnF;AACA,eAAW,OAAO;AAAA,MAChB,YAAY,KAAK,IAAI;AAAA,MACrB,YAAY,OAAO,KAAK,OAAO;AAAA,MAC/B,MAAM,UAAU,GAAG;AAAA,MACnB,OAAO,UAAU,KAAK,YAAY;AAAA,
|
|
4
|
+
"sourcesContent": ["/** GET /api/sfmc/status \u4E0E BDS \u5B9E\u65F6\u5FEB\u7167\u5165\u53E3\u3002 */\n\nimport { collectSystemStatus, type SystemStatusSnapshot } from \"../domain/system-status.js\";\nimport { PROJECT_ROOT } from \"../project-root.js\";\nimport { METRICS_RAW_WINDOW_MS, MetricsHistory, ResourceHistory, clampMetricsSpan, parseMetrics, type MetricsSample } from \"../domain/metrics.js\";\nimport { collectProcessResources } from \"../domain/process-resources.js\";\nimport { collectTrackedProcesses } from \"../domain/tracked-processes.js\";\nimport type { QueryFn } from \"../lib/sqlite.js\";\nimport fs from \"node:fs\";\nimport pathModule from \"node:path\";\nimport { stateDir } from \"@sfmc-bds/sdk/node/config\";\nimport { body, json, type RouteFactory } from \"./_shared.js\";\n\nconst FRESH_MS = 60_000;\n\ninterface LiveSnapshot {\n online: Array<{ name: string }>;\n world: { day: number; difficulty: string };\n updatedAt: number;\n}\n\ninterface Deps {\n collectSystem?: (projectRoot: string) => Promise<SystemStatusSnapshot>;\n projectRoot?: string;\n query?: QueryFn;\n}\n\nfunction createStatusRoutes({ collectSystem, projectRoot, query }: Deps): ReturnType<RouteFactory> {\n const root = projectRoot ?? PROJECT_ROOT;\n const collect = collectSystem ?? collectSystemStatus;\n let live: LiveSnapshot | null = null;\n let metrics: MetricsSample | null = null;\n const history = query ? new MetricsHistory(query) : undefined;\n const resources = query ? new ResourceHistory(query) : undefined;\n let lastCapture = 0;\n const captureResources = async (system: SystemStatusSnapshot | null) => {\n if (!system) return null;\n let ownedPid = 0;\n try { ownedPid = Number(fs.readFileSync(pathModule.join(stateDir(root), \"bds.pid\"), \"utf8\").trim()); } catch { /* \u672A\u6258\u7BA1\u5B9E\u4F8B\u4E0D\u731C\u6D4B\u8FDB\u7A0B\u5F52\u5C5E\u3002 */ }\n const owned = Number.isSafeInteger(ownedPid) && ownedPid > 0 && system.bds.pid === ownedPid;\n const processes = {\n db: await collectProcessResources(system.db.pid, system.db.running),\n bds: owned ? await collectProcessResources(system.bds.pid, system.bds.running) : null,\n };\n const skip = new Set<number>();\n if (processes.db.pid > 0) skip.add(processes.db.pid);\n if (processes.bds && processes.bds.pid > 0) skip.add(processes.bds.pid);\n const parts = await collectTrackedProcesses(root, skip);\n const partsMb: Record<string, number> = {};\n for (const part of parts) partsMb[part.key] = part.memoryMb;\n resources?.append({\n recordedAt: Date.now(),\n hostUsedMb: system.host.memory.usedMb,\n dbMb: processes.db.memoryMb,\n bdsMb: processes.bds?.memoryMb ?? null,\n ...(Object.keys(partsMb).length ? { partsMb } : {}),\n });\n lastCapture = Date.now();\n return { ...processes, ...(parts.length ? { parts } : {}) };\n };\n let systemCache: { data: SystemStatusSnapshot; at: number } | undefined;\n let collecting: Promise<SystemStatusSnapshot> | undefined;\n const getSystem = async () => {\n if (systemCache && Date.now() - systemCache.at < 5000) return systemCache.data;\n collecting ??= collect(root).then(data => { systemCache = { data, at: Date.now() }; return data; }).finally(() => { collecting = undefined; });\n return collecting;\n };\n if (resources) {\n const timer = setInterval(() => {\n if (Date.now() - lastCapture < 12_000) return;\n void getSystem().then(system => captureResources(system)).catch(() => undefined);\n }, 15_000);\n timer.unref();\n }\n\n return async function handle({ path, method, params, req, res }): Promise<boolean> {\n if (path === \"/api/sfmc/status/live\" || path === \"/api/sfmc/metrics/live\") {\n if (method !== \"POST\") {\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n const data = await body(req);\n const raw = data.players;\n const day = data.day;\n const difficulty = data.difficulty;\n if (\n !Array.isArray(raw) || raw.length > 1000 ||\n !raw.every((name) => typeof name === \"string\" && name.trim().length > 0 && name.length <= 64) ||\n typeof day !== \"number\" || !Number.isSafeInteger(day) || day < 0 ||\n typeof difficulty !== \"string\" || difficulty.length > 32\n ) {\n json(res, { success: false, error: \"invalid_live_status\" }, 400);\n return true;\n }\n if (path === \"/api/sfmc/metrics/live\") {\n const sample = parseMetrics(data, Date.now());\n if (!sample) { json(res, { success: false, error: \"invalid_metrics\" }, 400); return true; }\n history?.append(sample);\n metrics = sample;\n }\n live = {\n online: raw.map((name: string) => ({ name: name.trim() })),\n world: { day, difficulty },\n updatedAt: Date.now(),\n };\n json(res, { success: true });\n return true;\n }\n\n if (path !== \"/api/sfmc/status\" && path !== \"/api/sfmc/metrics\") return false;\n if (method !== \"GET\") {\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n }\n\n let system: SystemStatusSnapshot | null = null;\n try {\n system = await getSystem();\n } catch {\n system = null;\n }\n\n const now = Date.now();\n const bds = system?.bds;\n const bdsAgeMs = typeof bds?.uptimeSec === \"number\" ? bds.uptimeSec * 1000 : null;\n const snapshot = live;\n const fresh = snapshot !== null &&\n bds?.state === \"running\" &&\n now - snapshot.updatedAt <= FRESH_MS &&\n (bdsAgeMs === null || now - snapshot.updatedAt <= bdsAgeMs + 2_000);\n const current = fresh ? snapshot : null;\n\n if (path === \"/api/sfmc/metrics\") {\n // \u8D44\u6E90\u6307\u6807\u53EA\u8BA4\u5F53\u524D\u5B9E\u4F8B\u7684 PID\uFF0C\u4E0D\u80FD\u4F7F\u7528\u5168\u673A\u626B\u63CF\u627E\u5230\u7684\u53E6\u4E00\u5957 BDS\u3002\n let ownedPid = 0;\n try { ownedPid = Number(fs.readFileSync(pathModule.join(stateDir(root), \"bds.pid\"), \"utf8\").trim()); } catch { /* \u672A\u6258\u7BA1\u5B9E\u4F8B\u4E0D\u731C\u6D4B\u8FDB\u7A0B\u5F52\u5C5E\u3002 */ }\n const owned = Number.isSafeInteger(ownedPid) && ownedPid > 0 && bds?.pid === ownedPid;\n const metricFresh = owned && metrics !== null && bds?.state === \"running\" && now - metrics.recordedAt <= 60_000 &&\n (bdsAgeMs === null || now - metrics.recordedAt <= bdsAgeMs + 2000);\n const processes = await captureResources(system);\n let span = METRICS_RAW_WINDOW_MS;\n const rawSpan = params.get(\"spanMs\");\n if (rawSpan) {\n try { span = clampMetricsSpan(Number(rawSpan)); } catch {\n json(res, { success: false, error: \"invalid_span\" }, 400);\n return true;\n }\n }\n json(res, { fresh: metricFresh, current: metricFresh ? metrics : null, updatedAt: metrics?.recordedAt ?? null,\n history: history?.read(now, span) ?? [], host: system?.host ?? null, processes, resourcesUpdatedAt: system ? Date.now() : null,\n resourceHistory: resources?.read(now, span) ?? [],\n note: metricFresh ? undefined : bds?.state === \"stopped\" ? \"\u670D\u52A1\u5668\u672A\u8FD0\u884C\" : \"\u7B49\u5F85\u5E73\u53F0\u6307\u6807\u540C\u6B65\" });\n return true;\n }\n\n json(res, {\n online: current?.online ?? [],\n world: current?.world ?? null,\n updatedAt: current?.updatedAt ?? null,\n host: system?.host ?? null,\n processes: system ? { db: system.db, bds: system.bds } : null,\n source: \"bds_script_live\",\n note: fresh ? undefined : bds?.state === \"stopped\" ? \"\u670D\u52A1\u5668\u672A\u8FD0\u884C\" : \"\u7B49\u5F85\u6E38\u620F\u5B9E\u65F6\u72B6\u6001\u540C\u6B65\",\n });\n return true;\n };\n}\n\nexport { createStatusRoutes, FRESH_MS };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routes/wechat-bind.ts — 微信↔MC 身份绑定(平台 HTTP,仅本机)
|
|
3
|
+
*
|
|
4
|
+
* POST /api/sfmc/wechat/bind/request — mp-gateway 代小程序玩家申请短码 { openid }
|
|
5
|
+
* POST /api/sfmc/wechat/bind/unbind — 解绑 { openid }
|
|
6
|
+
* GET /api/sfmc/wechat/bind/me — 查询 ?openid=:绑定、账号资料与 SFMC 有效等级
|
|
7
|
+
*
|
|
8
|
+
* 游戏侧确认走统一入口 POST /api/sfmc/bind/confirm(routes/bind-confirm.ts)。
|
|
9
|
+
* openid 由 mp-gateway 通过微信 code2session 取得,db-server 只信任本机调用方(与 QQ 绑定路由同一信任边界)。
|
|
10
|
+
*/
|
|
11
|
+
import type http from "node:http";
|
|
12
|
+
import type { QueryFn } from "../lib/sqlite.js";
|
|
13
|
+
interface Deps {
|
|
14
|
+
query: QueryFn;
|
|
15
|
+
body: (req: http.IncomingMessage) => Promise<Record<string, unknown>>;
|
|
16
|
+
json: (res: http.ServerResponse, data: Record<string, unknown>, status?: number) => void;
|
|
17
|
+
/** 跨渠道短码查重(QQ + 微信) */
|
|
18
|
+
isCodeTaken: (code: string) => boolean;
|
|
19
|
+
/** 按 xuid / 玩家名计算 SFMC 有效等级(DIP:文件位置由入口决定) */
|
|
20
|
+
resolveLevel: (player: {
|
|
21
|
+
xuid: string;
|
|
22
|
+
name: string;
|
|
23
|
+
}) => number;
|
|
24
|
+
}
|
|
25
|
+
/** 路由上下文(与其他平台路由一致) */
|
|
26
|
+
interface Ctx {
|
|
27
|
+
path: string;
|
|
28
|
+
method: string;
|
|
29
|
+
params: URLSearchParams;
|
|
30
|
+
req: http.IncomingMessage;
|
|
31
|
+
res: http.ServerResponse;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 创建微信绑定路由。
|
|
35
|
+
* 使用场景:index.ts 装配到平台路由链。
|
|
36
|
+
*/
|
|
37
|
+
declare function createWechatBindRoutes({ query, body, json, isCodeTaken, resolveLevel }: Deps): ({ path, method, params, req, res }: Ctx) => Promise<boolean>;
|
|
38
|
+
export { createWechatBindRoutes };
|
|
39
|
+
//# sourceMappingURL=wechat-bind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-bind.d.ts","sourceRoot":"","sources":["../../src/routes/wechat-bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,UAAU,IAAI;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtE,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,uBAAuB;IACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,8CAA8C;IAC9C,YAAY,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CAClE;AAED,uBAAuB;AACvB,UAAU,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC;IAC1B,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC;CAC1B;AAID;;;GAGG;AACH,iBAAS,sBAAsB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,IAAI,wCACnB,GAAG,KAAG,OAAO,CAAC,OAAO,CAAC,CAmDxF;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { loadQqAccountProfile } from "../domain/qq-account-profile.js";
|
|
2
|
+
import { currentPlayerName, findWechatBindingByOpenid, requestWechatBindCode, unbindWechat } from "../domain/wechat-bind.js";
|
|
3
|
+
const PREFIX = "/api/sfmc/wechat/bind";
|
|
4
|
+
function createWechatBindRoutes({ query, body, json, isCodeTaken, resolveLevel }) {
|
|
5
|
+
return async function handle({ path, method, params, req, res }) {
|
|
6
|
+
if (!path.startsWith(PREFIX)) return false;
|
|
7
|
+
if (path === `${PREFIX}/me` && method === "GET") {
|
|
8
|
+
const openid = String(params.get("openid") ?? "").trim();
|
|
9
|
+
if (!openid) {
|
|
10
|
+
json(res, { success: false, error: "openid_required" }, 400);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
const binding = findWechatBindingByOpenid(query, openid);
|
|
14
|
+
if (!binding) {
|
|
15
|
+
json(res, { success: true, bound: false, binding: null });
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const name = currentPlayerName(query, binding.player_xuid, binding.player_name);
|
|
19
|
+
json(res, {
|
|
20
|
+
success: true,
|
|
21
|
+
bound: true,
|
|
22
|
+
binding: { ...binding, player_name: name },
|
|
23
|
+
level: resolveLevel({ xuid: binding.player_xuid, name }),
|
|
24
|
+
profile: loadQqAccountProfile(query, binding.player_xuid, name)
|
|
25
|
+
});
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (path === `${PREFIX}/request` && method === "POST") {
|
|
29
|
+
const openid = String((await body(req)).openid ?? "").trim();
|
|
30
|
+
if (!openid) {
|
|
31
|
+
json(res, { success: false, error: "openid_required" }, 400);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
const result = requestWechatBindCode(query, openid, isCodeTaken);
|
|
35
|
+
if (result.ok) json(res, { success: true, code: result.code, expires_at: result.expires_at, ttl_ms: result.ttl_ms });
|
|
36
|
+
else json(res, { success: false, error: result.error, ...result.player_name ? { player_name: result.player_name } : {} }, result.status);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (path === `${PREFIX}/unbind` && method === "POST") {
|
|
40
|
+
const openid = String((await body(req)).openid ?? "").trim();
|
|
41
|
+
if (!openid) {
|
|
42
|
+
json(res, { success: false, error: "openid_required" }, 400);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
const removed = unbindWechat(query, openid);
|
|
46
|
+
json(res, { success: true, unbound: removed > 0, removed });
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
json(res, { success: false, error: "not_found" }, 404);
|
|
50
|
+
return true;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
createWechatBindRoutes
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=wechat-bind.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/routes/wechat-bind.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * routes/wechat-bind.ts \u2014 \u5FAE\u4FE1\u2194MC \u8EAB\u4EFD\u7ED1\u5B9A\uFF08\u5E73\u53F0 HTTP\uFF0C\u4EC5\u672C\u673A\uFF09\n *\n * POST /api/sfmc/wechat/bind/request \u2014 mp-gateway \u4EE3\u5C0F\u7A0B\u5E8F\u73A9\u5BB6\u7533\u8BF7\u77ED\u7801 { openid }\n * POST /api/sfmc/wechat/bind/unbind \u2014 \u89E3\u7ED1 { openid }\n * GET /api/sfmc/wechat/bind/me \u2014 \u67E5\u8BE2 ?openid=\uFF1A\u7ED1\u5B9A\u3001\u8D26\u53F7\u8D44\u6599\u4E0E SFMC \u6709\u6548\u7B49\u7EA7\n *\n * \u6E38\u620F\u4FA7\u786E\u8BA4\u8D70\u7EDF\u4E00\u5165\u53E3 POST /api/sfmc/bind/confirm\uFF08routes/bind-confirm.ts\uFF09\u3002\n * openid \u7531 mp-gateway \u901A\u8FC7\u5FAE\u4FE1 code2session \u53D6\u5F97\uFF0Cdb-server \u53EA\u4FE1\u4EFB\u672C\u673A\u8C03\u7528\u65B9\uFF08\u4E0E QQ \u7ED1\u5B9A\u8DEF\u7531\u540C\u4E00\u4FE1\u4EFB\u8FB9\u754C\uFF09\u3002\n */\n\nimport type http from \"node:http\";\nimport { loadQqAccountProfile } from \"../domain/qq-account-profile.js\";\nimport { currentPlayerName, findWechatBindingByOpenid, requestWechatBindCode, unbindWechat } from \"../domain/wechat-bind.js\";\nimport type { QueryFn } from \"../lib/sqlite.js\";\n\ninterface Deps {\n query: QueryFn;\n body: (req: http.IncomingMessage) => Promise<Record<string, unknown>>;\n json: (res: http.ServerResponse, data: Record<string, unknown>, status?: number) => void;\n /** \u8DE8\u6E20\u9053\u77ED\u7801\u67E5\u91CD\uFF08QQ + \u5FAE\u4FE1\uFF09 */\n isCodeTaken: (code: string) => boolean;\n /** \u6309 xuid / \u73A9\u5BB6\u540D\u8BA1\u7B97 SFMC \u6709\u6548\u7B49\u7EA7\uFF08DIP\uFF1A\u6587\u4EF6\u4F4D\u7F6E\u7531\u5165\u53E3\u51B3\u5B9A\uFF09 */\n resolveLevel: (player: { xuid: string; name: string }) => number;\n}\n\n/** \u8DEF\u7531\u4E0A\u4E0B\u6587\uFF08\u4E0E\u5176\u4ED6\u5E73\u53F0\u8DEF\u7531\u4E00\u81F4\uFF09 */\ninterface Ctx {\n path: string;\n method: string;\n params: URLSearchParams;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n}\n\nconst PREFIX = \"/api/sfmc/wechat/bind\";\n\n/**\n * \u521B\u5EFA\u5FAE\u4FE1\u7ED1\u5B9A\u8DEF\u7531\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1Aindex.ts \u88C5\u914D\u5230\u5E73\u53F0\u8DEF\u7531\u94FE\u3002\n */\nfunction createWechatBindRoutes({ query, body, json, isCodeTaken, resolveLevel }: Deps) {\n return async function handle({ path, method, params, req, res }: Ctx): Promise<boolean> {\n if (!path.startsWith(PREFIX)) return false;\n\n if (path === `${PREFIX}/me` && method === \"GET\") {\n const openid = String(params.get(\"openid\") ?? \"\").trim();\n if (!openid) {\n json(res, { success: false, error: \"openid_required\" }, 400);\n return true;\n }\n const binding = findWechatBindingByOpenid(query, openid);\n if (!binding) {\n json(res, { success: true, bound: false, binding: null });\n return true;\n }\n const name = currentPlayerName(query, binding.player_xuid, binding.player_name);\n json(res, {\n success: true,\n bound: true,\n binding: { ...binding, player_name: name },\n level: resolveLevel({ xuid: binding.player_xuid, name }),\n profile: loadQqAccountProfile(query, binding.player_xuid, name),\n });\n return true;\n }\n\n if (path === `${PREFIX}/request` && method === \"POST\") {\n const openid = String((await body(req)).openid ?? \"\").trim();\n if (!openid) {\n json(res, { success: false, error: \"openid_required\" }, 400);\n return true;\n }\n const result = requestWechatBindCode(query, openid, isCodeTaken);\n if (result.ok) json(res, { success: true, code: result.code, expires_at: result.expires_at, ttl_ms: result.ttl_ms });\n else json(res, { success: false, error: result.error, ...(result.player_name ? { player_name: result.player_name } : {}) }, result.status);\n return true;\n }\n\n if (path === `${PREFIX}/unbind` && method === \"POST\") {\n const openid = String((await body(req)).openid ?? \"\").trim();\n if (!openid) {\n json(res, { success: false, error: \"openid_required\" }, 400);\n return true;\n }\n const removed = unbindWechat(query, openid);\n json(res, { success: true, unbound: removed > 0, removed });\n return true;\n }\n\n json(res, { success: false, error: \"not_found\" }, 404);\n return true;\n };\n}\n\nexport { createWechatBindRoutes };\n"],
|
|
5
|
+
"mappings": "AAYA,SAAS,4BAA4B;AACrC,SAAS,mBAAmB,2BAA2B,uBAAuB,oBAAoB;AAsBlG,MAAM,SAAS;AAMf,SAAS,uBAAuB,EAAE,OAAO,MAAM,MAAM,aAAa,aAAa,GAAS;AACtF,SAAO,eAAe,OAAO,EAAE,MAAM,QAAQ,QAAQ,KAAK,IAAI,GAA0B;AACtF,QAAI,CAAC,KAAK,WAAW,MAAM,EAAG,QAAO;AAErC,QAAI,SAAS,GAAG,MAAM,SAAS,WAAW,OAAO;AAC/C,YAAM,SAAS,OAAO,OAAO,IAAI,QAAQ,KAAK,EAAE,EAAE,KAAK;AACvD,UAAI,CAAC,QAAQ;AACX,aAAK,KAAK,EAAE,SAAS,OAAO,OAAO,kBAAkB,GAAG,GAAG;AAC3D,eAAO;AAAA,MACT;AACA,YAAM,UAAU,0BAA0B,OAAO,MAAM;AACvD,UAAI,CAAC,SAAS;AACZ,aAAK,KAAK,EAAE,SAAS,MAAM,OAAO,OAAO,SAAS,KAAK,CAAC;AACxD,eAAO;AAAA,MACT;AACA,YAAM,OAAO,kBAAkB,OAAO,QAAQ,aAAa,QAAQ,WAAW;AAC9E,WAAK,KAAK;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS,EAAE,GAAG,SAAS,aAAa,KAAK;AAAA,QACzC,OAAO,aAAa,EAAE,MAAM,QAAQ,aAAa,KAAK,CAAC;AAAA,QACvD,SAAS,qBAAqB,OAAO,QAAQ,aAAa,IAAI;AAAA,MAChE,CAAC;AACD,aAAO;AAAA,IACT;AAEA,QAAI,SAAS,GAAG,MAAM,cAAc,WAAW,QAAQ;AACrD,YAAM,SAAS,QAAQ,MAAM,KAAK,GAAG,GAAG,UAAU,EAAE,EAAE,KAAK;AAC3D,UAAI,CAAC,QAAQ;AACX,aAAK,KAAK,EAAE,SAAS,OAAO,OAAO,kBAAkB,GAAG,GAAG;AAC3D,eAAO;AAAA,MACT;AACA,YAAM,SAAS,sBAAsB,OAAO,QAAQ,WAAW;AAC/D,UAAI,OAAO,GAAI,MAAK,KAAK,EAAE,SAAS,MAAM,MAAM,OAAO,MAAM,YAAY,OAAO,YAAY,QAAQ,OAAO,OAAO,CAAC;AAAA,UAC9G,MAAK,KAAK,EAAE,SAAS,OAAO,OAAO,OAAO,OAAO,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC,EAAG,GAAG,OAAO,MAAM;AACzI,aAAO;AAAA,IACT;AAEA,QAAI,SAAS,GAAG,MAAM,aAAa,WAAW,QAAQ;AACpD,YAAM,SAAS,QAAQ,MAAM,KAAK,GAAG,GAAG,UAAU,EAAE,EAAE,KAAK;AAC3D,UAAI,CAAC,QAAQ;AACX,aAAK,KAAK,EAAE,SAAS,OAAO,OAAO,kBAAkB,GAAG,GAAG;AAC3D,eAAO;AAAA,MACT;AACA,YAAM,UAAU,aAAa,OAAO,MAAM;AAC1C,WAAK,KAAK,EAAE,SAAS,MAAM,SAAS,UAAU,GAAG,QAAQ,CAAC;AAC1D,aAAO;AAAA,IACT;AAEA,SAAK,KAAK,EAAE,SAAS,OAAO,OAAO,YAAY,GAAG,GAAG;AACrD,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfmc-bds/db-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "SFMC SQLite HTTP REST backend — configs, modules, gameplay data",
|
|
5
5
|
"author": "Shiroha7z",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"sql-template-strings": "^2.2.2",
|
|
53
|
-
"@sfmc-bds/
|
|
54
|
-
"@sfmc-bds/
|
|
53
|
+
"@sfmc-bds/bds-tools": "0.3.0",
|
|
54
|
+
"@sfmc-bds/sdk": "0.6.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@sfmc-bds/tools": "0.2.
|
|
57
|
+
"@sfmc-bds/tools": "0.2.11"
|
|
58
58
|
},
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"dev": "tsx src/index.ts",
|
|
67
67
|
"format": "prettier --write \"src/**/*.{ts,tsx,js,json}\"",
|
|
68
68
|
"start": "node dist/index.js",
|
|
69
|
+
"test": "node --test --import tsx/esm test/*.test.ts",
|
|
69
70
|
"typecheck": "tsc7 --noEmit"
|
|
70
71
|
}
|
|
71
72
|
}
|