@sfmc-bds/db-server 0.2.0-beta.9 → 0.2.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/README.md +1 -1
- 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/player-session.d.ts +8 -0
- package/dist/domain/player-session.d.ts.map +1 -0
- package/dist/domain/player-session.js +16 -0
- package/dist/domain/player-session.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 +48 -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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -52
- 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/dist/tx-runner.d.ts +11 -2
- package/dist/tx-runner.d.ts.map +1 -1
- package/dist/tx-runner.js +42 -7
- package/dist/tx-runner.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/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 -402
- package/dist/runtime.test.js.map +0 -7
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { DatabaseSync } from "node:sqlite";
|
|
4
|
-
import { SQL } from "sql-template-strings";
|
|
5
|
-
import { initSchema } from "./schema.js";
|
|
6
|
-
import { createQuery } from "../lib/sqlite.js";
|
|
7
|
-
import { createStatusRoutes, FRESH_MS } from "../routes/status.js";
|
|
8
|
-
import { createQqBindRoutes } from "../routes/qq-bind.js";
|
|
9
|
-
function memDb() {
|
|
10
|
-
const db = new DatabaseSync(":memory:");
|
|
11
|
-
initSchema(db);
|
|
12
|
-
return { db, query: createQuery(db) };
|
|
13
|
-
}
|
|
14
|
-
function mockRes() {
|
|
15
|
-
let status = 200;
|
|
16
|
-
let body = {};
|
|
17
|
-
return {
|
|
18
|
-
res: {
|
|
19
|
-
writeHead(code) {
|
|
20
|
-
status = code;
|
|
21
|
-
},
|
|
22
|
-
end(s) {
|
|
23
|
-
body = JSON.parse(s);
|
|
24
|
-
},
|
|
25
|
-
setHeader() {
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
get status() {
|
|
29
|
-
return status;
|
|
30
|
-
},
|
|
31
|
-
get body() {
|
|
32
|
-
return body;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
test("initSchema \u542B qq bind \u8868", () => {
|
|
37
|
-
const { db } = memDb();
|
|
38
|
-
const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'sfmc_qq_%' ORDER BY name").all();
|
|
39
|
-
const names = tables.map((t) => t.name);
|
|
40
|
-
assert.ok(names.includes("sfmc_qq_bind_pending"));
|
|
41
|
-
assert.ok(names.includes("sfmc_qq_bindings"));
|
|
42
|
-
assert.ok(names.includes("sfmc_qq_join_requests"));
|
|
43
|
-
assert.ok(names.includes("sfmc_qq_admin_actions"));
|
|
44
|
-
assert.ok(FRESH_MS > 0);
|
|
45
|
-
});
|
|
46
|
-
test("GET /api/sfmc/status \u7A7A\u8868\u4E0D\u629B\u9519", async () => {
|
|
47
|
-
const { query } = memDb();
|
|
48
|
-
const handle = createStatusRoutes({
|
|
49
|
-
query,
|
|
50
|
-
collectSystem: async () => ({
|
|
51
|
-
host: {
|
|
52
|
-
hostname: "test-host",
|
|
53
|
-
platform: "win32",
|
|
54
|
-
arch: "x64",
|
|
55
|
-
release: "10.0",
|
|
56
|
-
uptimeSec: 3600,
|
|
57
|
-
uptimeText: "1\u65F60\u5206",
|
|
58
|
-
cpu: { model: "Test CPU", cores: 4 },
|
|
59
|
-
memory: { totalMb: 8192, freeMb: 4096, usedMb: 4096, usedPercent: 50 },
|
|
60
|
-
loadavg: [0, 0, 0]
|
|
61
|
-
},
|
|
62
|
-
db: { pid: 1, running: true, uptimeSec: 10, uptimeText: "10\u79D2" },
|
|
63
|
-
bds: { state: "stopped", running: false, pid: 0, uptimeSec: null, uptimeText: "\u672A\u8FD0\u884C" }
|
|
64
|
-
})
|
|
65
|
-
});
|
|
66
|
-
const m = mockRes();
|
|
67
|
-
const ok = await handle({
|
|
68
|
-
path: "/api/sfmc/status",
|
|
69
|
-
method: "GET",
|
|
70
|
-
params: new URLSearchParams(),
|
|
71
|
-
req: {},
|
|
72
|
-
res: m.res
|
|
73
|
-
});
|
|
74
|
-
assert.equal(ok, true);
|
|
75
|
-
assert.equal(m.status, 200);
|
|
76
|
-
assert.ok(Array.isArray(m.body.online));
|
|
77
|
-
assert.equal(m.body.online.length, 0);
|
|
78
|
-
assert.equal(m.body.host.hostname, "test-host");
|
|
79
|
-
assert.equal(m.body.processes.bds.state, "stopped");
|
|
80
|
-
});
|
|
81
|
-
test("bind request \u2192 confirm \u2192 me \u2192 unbind + \u51B2\u7A81", async () => {
|
|
82
|
-
const { query } = memDb();
|
|
83
|
-
let bodyData = {};
|
|
84
|
-
const handle = createQqBindRoutes({
|
|
85
|
-
query,
|
|
86
|
-
body: async () => bodyData,
|
|
87
|
-
json: (res, data, status = 200) => {
|
|
88
|
-
res.writeHead(status);
|
|
89
|
-
res.end(JSON.stringify(data));
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
bodyData = { openid: "oa", qq_backend: "official" };
|
|
93
|
-
let m = mockRes();
|
|
94
|
-
await handle({
|
|
95
|
-
path: "/api/sfmc/qq/bind/request",
|
|
96
|
-
method: "POST",
|
|
97
|
-
params: new URLSearchParams(),
|
|
98
|
-
req: {},
|
|
99
|
-
res: m.res
|
|
100
|
-
});
|
|
101
|
-
assert.equal(m.body.success, true);
|
|
102
|
-
const code = String(m.body.code);
|
|
103
|
-
assert.match(code, /^\d{6}$/);
|
|
104
|
-
bodyData = { code, xuid: "x1", name: "Steve" };
|
|
105
|
-
m = mockRes();
|
|
106
|
-
await handle({
|
|
107
|
-
path: "/api/sfmc/qq/bind/confirm",
|
|
108
|
-
method: "POST",
|
|
109
|
-
params: new URLSearchParams(),
|
|
110
|
-
req: {},
|
|
111
|
-
res: m.res
|
|
112
|
-
});
|
|
113
|
-
assert.equal(m.body.success, true);
|
|
114
|
-
m = mockRes();
|
|
115
|
-
await handle({
|
|
116
|
-
path: "/api/sfmc/qq/bind/me",
|
|
117
|
-
method: "GET",
|
|
118
|
-
params: new URLSearchParams("openid=oa"),
|
|
119
|
-
req: {},
|
|
120
|
-
res: m.res
|
|
121
|
-
});
|
|
122
|
-
assert.equal(m.body.bound, true);
|
|
123
|
-
assert.equal(m.body.binding.player_name, "Steve");
|
|
124
|
-
bodyData = { openid: "ob", qq_backend: "official" };
|
|
125
|
-
m = mockRes();
|
|
126
|
-
await handle({
|
|
127
|
-
path: "/api/sfmc/qq/bind/request",
|
|
128
|
-
method: "POST",
|
|
129
|
-
params: new URLSearchParams(),
|
|
130
|
-
req: {},
|
|
131
|
-
res: m.res
|
|
132
|
-
});
|
|
133
|
-
const code2 = String(m.body.code);
|
|
134
|
-
bodyData = { code: code2, xuid: "x1", name: "Alex" };
|
|
135
|
-
m = mockRes();
|
|
136
|
-
await handle({
|
|
137
|
-
path: "/api/sfmc/qq/bind/confirm",
|
|
138
|
-
method: "POST",
|
|
139
|
-
params: new URLSearchParams(),
|
|
140
|
-
req: {},
|
|
141
|
-
res: m.res
|
|
142
|
-
});
|
|
143
|
-
assert.equal(m.body.success, false);
|
|
144
|
-
assert.equal(m.body.error, "player_already_bound");
|
|
145
|
-
bodyData = { openid: "oa" };
|
|
146
|
-
m = mockRes();
|
|
147
|
-
await handle({
|
|
148
|
-
path: "/api/sfmc/qq/bind/unbind",
|
|
149
|
-
method: "POST",
|
|
150
|
-
params: new URLSearchParams(),
|
|
151
|
-
req: {},
|
|
152
|
-
res: m.res
|
|
153
|
-
});
|
|
154
|
-
assert.equal(m.body.unbound, true);
|
|
155
|
-
bodyData = { openid: "oa", qq_backend: "official" };
|
|
156
|
-
m = mockRes();
|
|
157
|
-
await handle({
|
|
158
|
-
path: "/api/sfmc/qq/bind/request",
|
|
159
|
-
method: "POST",
|
|
160
|
-
params: new URLSearchParams(),
|
|
161
|
-
req: {},
|
|
162
|
-
res: m.res
|
|
163
|
-
});
|
|
164
|
-
assert.equal(m.body.success, true);
|
|
165
|
-
});
|
|
166
|
-
test("status \u65B0\u9C9C\u73A9\u5BB6\u8BA1\u5165 online", async () => {
|
|
167
|
-
const { query } = memDb();
|
|
168
|
-
const now = Date.now();
|
|
169
|
-
query(
|
|
170
|
-
SQL`INSERT INTO sfmc_players (id, name, updated_at) VALUES ('p1', 'Steve', ${now})`
|
|
171
|
-
);
|
|
172
|
-
query(
|
|
173
|
-
SQL`INSERT INTO sfmc_world (day, difficulty, updated_at) VALUES (3, 'normal', ${String(now)})`
|
|
174
|
-
);
|
|
175
|
-
const handle = createStatusRoutes({
|
|
176
|
-
query,
|
|
177
|
-
collectSystem: async () => ({
|
|
178
|
-
host: {
|
|
179
|
-
hostname: "h",
|
|
180
|
-
platform: "linux",
|
|
181
|
-
arch: "x64",
|
|
182
|
-
release: "6",
|
|
183
|
-
uptimeSec: 1,
|
|
184
|
-
uptimeText: "1\u79D2",
|
|
185
|
-
cpu: { model: "c", cores: 2 },
|
|
186
|
-
memory: { totalMb: 1, freeMb: 1, usedMb: 0, usedPercent: 0 },
|
|
187
|
-
loadavg: [0, 0, 0]
|
|
188
|
-
},
|
|
189
|
-
db: { pid: 1, running: true, uptimeSec: 1, uptimeText: "1\u79D2" },
|
|
190
|
-
bds: {
|
|
191
|
-
state: "running",
|
|
192
|
-
running: true,
|
|
193
|
-
pid: 99,
|
|
194
|
-
uptimeSec: 120,
|
|
195
|
-
uptimeText: "2\u52060\u79D2"
|
|
196
|
-
}
|
|
197
|
-
})
|
|
198
|
-
});
|
|
199
|
-
const m = mockRes();
|
|
200
|
-
await handle({
|
|
201
|
-
path: "/api/sfmc/status",
|
|
202
|
-
method: "GET",
|
|
203
|
-
params: new URLSearchParams(),
|
|
204
|
-
req: {},
|
|
205
|
-
res: m.res
|
|
206
|
-
});
|
|
207
|
-
assert.equal(m.body.online.length, 1);
|
|
208
|
-
assert.equal(m.body.world.day, 3);
|
|
209
|
-
assert.equal(m.body.processes.bds.pid, 99);
|
|
210
|
-
});
|
|
211
|
-
//# sourceMappingURL=qq-bind-status.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/domain/qq-bind-status.test.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * domain/qq-bind-status.test.ts \u2014 bind \u8868 + status \u67E5\u8BE2\u5F62\u72B6\n */\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport { SQL } from \"sql-template-strings\";\nimport { initSchema } from \"./schema.js\";\nimport { createQuery } from \"../lib/sqlite.js\";\nimport { createStatusRoutes, FRESH_MS } from \"../routes/status.js\";\nimport { createQqBindRoutes } from \"../routes/qq-bind.js\";\n\nfunction memDb() {\n const db = new DatabaseSync(\":memory:\");\n initSchema(db);\n return { db, query: createQuery(db) };\n}\n\nfunction mockRes() {\n let status = 200;\n let body: Record<string, unknown> = {};\n return {\n res: {\n writeHead(code: number) {\n status = code;\n },\n end(s: string) {\n body = JSON.parse(s) as Record<string, unknown>;\n },\n setHeader() {},\n } as unknown as import(\"http\").ServerResponse,\n get status() {\n return status;\n },\n get body() {\n return body;\n },\n };\n}\n\ntest(\"initSchema \u542B qq bind \u8868\", () => {\n const { db } = memDb();\n const tables = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'sfmc_qq_%' ORDER BY name\")\n .all() as Array<{ name: string }>;\n const names = tables.map((t) => t.name);\n assert.ok(names.includes(\"sfmc_qq_bind_pending\"));\n assert.ok(names.includes(\"sfmc_qq_bindings\"));\n assert.ok(names.includes(\"sfmc_qq_join_requests\"));\n assert.ok(names.includes(\"sfmc_qq_admin_actions\"));\n assert.ok(FRESH_MS > 0);\n});\n\ntest(\"GET /api/sfmc/status \u7A7A\u8868\u4E0D\u629B\u9519\", async () => {\n const { query } = memDb();\n const handle = createStatusRoutes({\n query,\n collectSystem: async () => ({\n host: {\n hostname: \"test-host\",\n platform: \"win32\",\n arch: \"x64\",\n release: \"10.0\",\n uptimeSec: 3600,\n uptimeText: \"1\u65F60\u5206\",\n cpu: { model: \"Test CPU\", cores: 4 },\n memory: { totalMb: 8192, freeMb: 4096, usedMb: 4096, usedPercent: 50 },\n loadavg: [0, 0, 0],\n },\n db: { pid: 1, running: true, uptimeSec: 10, uptimeText: \"10\u79D2\" },\n bds: { state: \"stopped\", running: false, pid: 0, uptimeSec: null, uptimeText: \"\u672A\u8FD0\u884C\" },\n }),\n });\n const m = mockRes();\n const ok = await handle({\n path: \"/api/sfmc/status\",\n method: \"GET\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(ok, true);\n assert.equal(m.status, 200);\n assert.ok(Array.isArray(m.body.online));\n assert.equal((m.body.online as unknown[]).length, 0);\n assert.equal((m.body.host as { hostname: string }).hostname, \"test-host\");\n assert.equal((m.body.processes as { bds: { state: string } }).bds.state, \"stopped\");\n});\n\ntest(\"bind request \u2192 confirm \u2192 me \u2192 unbind + \u51B2\u7A81\", async () => {\n const { query } = memDb();\n let bodyData: Record<string, unknown> = {};\n const handle = createQqBindRoutes({\n query,\n body: async () => bodyData,\n json: (res, data, status = 200) => {\n (res as unknown as { writeHead: (c: number) => void }).writeHead(status);\n (res as unknown as { end: (s: string) => void }).end(JSON.stringify(data));\n },\n });\n\n bodyData = { openid: \"oa\", qq_backend: \"official\" };\n let m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/request\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(m.body.success, true);\n const code = String(m.body.code);\n assert.match(code, /^\\d{6}$/);\n\n bodyData = { code, xuid: \"x1\", name: \"Steve\" };\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/confirm\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(m.body.success, true);\n\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/me\",\n method: \"GET\",\n params: new URLSearchParams(\"openid=oa\"),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(m.body.bound, true);\n assert.equal((m.body.binding as { player_name: string }).player_name, \"Steve\");\n\n // \u51B2\u7A81\uFF1A\u53E6\u4E00 QQ \u7ED1\u540C\u4E00 xuid\n bodyData = { openid: \"ob\", qq_backend: \"official\" };\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/request\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n const code2 = String(m.body.code);\n bodyData = { code: code2, xuid: \"x1\", name: \"Alex\" };\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/confirm\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(m.body.success, false);\n assert.equal(m.body.error, \"player_already_bound\");\n\n bodyData = { openid: \"oa\" };\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/unbind\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal(m.body.unbound, true);\n\n // \u5DF2\u7ED1\u5B9A\u518D request\n bodyData = { openid: \"oa\", qq_backend: \"official\" };\n m = mockRes();\n await handle({\n path: \"/api/sfmc/qq/bind/request\",\n method: \"POST\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n // \u89E3\u7ED1\u540E\u5E94\u80FD\u518D\u7533\u8BF7\n assert.equal(m.body.success, true);\n});\n\ntest(\"status \u65B0\u9C9C\u73A9\u5BB6\u8BA1\u5165 online\", async () => {\n const { query } = memDb();\n const now = Date.now();\n query(\n SQL`INSERT INTO sfmc_players (id, name, updated_at) VALUES ('p1', 'Steve', ${now})`\n );\n query(\n SQL`INSERT INTO sfmc_world (day, difficulty, updated_at) VALUES (3, 'normal', ${String(now)})`\n );\n const handle = createStatusRoutes({\n query,\n collectSystem: async () => ({\n host: {\n hostname: \"h\",\n platform: \"linux\",\n arch: \"x64\",\n release: \"6\",\n uptimeSec: 1,\n uptimeText: \"1\u79D2\",\n cpu: { model: \"c\", cores: 2 },\n memory: { totalMb: 1, freeMb: 1, usedMb: 0, usedPercent: 0 },\n loadavg: [0, 0, 0],\n },\n db: { pid: 1, running: true, uptimeSec: 1, uptimeText: \"1\u79D2\" },\n bds: {\n state: \"running\",\n running: true,\n pid: 99,\n uptimeSec: 120,\n uptimeText: \"2\u52060\u79D2\",\n },\n }),\n });\n const m = mockRes();\n await handle({\n path: \"/api/sfmc/status\",\n method: \"GET\",\n params: new URLSearchParams(),\n req: {} as import(\"http\").IncomingMessage,\n res: m.res,\n });\n assert.equal((m.body.online as unknown[]).length, 1);\n assert.equal((m.body.world as { day: number }).day, 3);\n assert.equal((m.body.processes as { bds: { pid: number } }).bds.pid, 99);\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qq-events.test.d.ts","sourceRoot":"","sources":["../../src/domain/qq-events.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import {
|
|
4
|
-
createQqEventsAggregator,
|
|
5
|
-
formatImmediateBody,
|
|
6
|
-
formatWindowBody,
|
|
7
|
-
localizeCause,
|
|
8
|
-
MAX_WINDOW_EVENTS,
|
|
9
|
-
normalizeEventPayload,
|
|
10
|
-
resolveQqEventsConfig
|
|
11
|
-
} from "./qq-events.js";
|
|
12
|
-
const ALL_ON = {
|
|
13
|
-
enabled: true,
|
|
14
|
-
window_sec: 60,
|
|
15
|
-
join: true,
|
|
16
|
-
leave: true,
|
|
17
|
-
death: true,
|
|
18
|
-
crash: true,
|
|
19
|
-
start: true
|
|
20
|
-
};
|
|
21
|
-
const fakeOutbound = {
|
|
22
|
-
backend: "official",
|
|
23
|
-
creds: { appId: "a", appSecret: "s" },
|
|
24
|
-
groupOpenid: "G",
|
|
25
|
-
prefix: "[MC]"
|
|
26
|
-
};
|
|
27
|
-
test("resolveQqEventsConfig \u7F3A\u7701\u4E0E\u603B\u5F00\u5173", () => {
|
|
28
|
-
const d = resolveQqEventsConfig(void 0);
|
|
29
|
-
assert.equal(d.enabled, true);
|
|
30
|
-
assert.equal(d.window_sec, 60);
|
|
31
|
-
assert.equal(d.join, true);
|
|
32
|
-
const off = resolveQqEventsConfig({ enabled: false, join: false });
|
|
33
|
-
assert.equal(off.enabled, false);
|
|
34
|
-
assert.equal(off.join, false);
|
|
35
|
-
assert.equal(off.death, true);
|
|
36
|
-
});
|
|
37
|
-
test("localizeCause \u6620\u5C04\u4E0E\u539F\u6587\u56DE\u9000", () => {
|
|
38
|
-
assert.equal(localizeCause("fall"), "\u5760\u843D");
|
|
39
|
-
assert.equal(localizeCause("drowning"), "\u6EBA\u6C34");
|
|
40
|
-
assert.equal(localizeCause("custom_xyz"), "custom_xyz");
|
|
41
|
-
assert.equal(localizeCause(""), "");
|
|
42
|
-
});
|
|
43
|
-
test("normalizeEventPayload \u8FC7\u6EE4\u975E\u6CD5 type", () => {
|
|
44
|
-
assert.equal(normalizeEventPayload({ type: "chat" }), null);
|
|
45
|
-
assert.deepEqual(normalizeEventPayload({ type: "join", player: "Steve" }), {
|
|
46
|
-
type: "join",
|
|
47
|
-
player: "Steve"
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
test("formatWindowBody \u805A\u5408\u6587\u6848", () => {
|
|
51
|
-
const text = formatWindowBody([
|
|
52
|
-
{ type: "join", player: "Steve" },
|
|
53
|
-
{ type: "join", player: "Alex" },
|
|
54
|
-
{ type: "leave", player: "Bob" },
|
|
55
|
-
{ type: "death", player: "Steve", cause: "fall" }
|
|
56
|
-
]);
|
|
57
|
-
assert.match(text, /^\[MC事件\]/);
|
|
58
|
-
assert.match(text, /上线:Steve、Alex/);
|
|
59
|
-
assert.match(text, /下线:Bob/);
|
|
60
|
-
assert.match(text, /死亡:Steve(坠落)/);
|
|
61
|
-
});
|
|
62
|
-
test("formatImmediateBody crash/start", () => {
|
|
63
|
-
assert.equal(formatImmediateBody({ type: "crash", detail: "code=1" }), "[MC\u4E8B\u4EF6] BDS \u610F\u5916\u9000\u51FA (code=1)");
|
|
64
|
-
assert.equal(formatImmediateBody({ type: "start", detail: "pid=9" }), "[MC\u4E8B\u4EF6] BDS \u5DF2\u542F\u52A8 (pid=9)");
|
|
65
|
-
});
|
|
66
|
-
test("\u7A97\u53E3\u5185 join+death \u5230\u671F flush \u6210\u4E00\u6761", () => {
|
|
67
|
-
const sent = [];
|
|
68
|
-
const timers = [];
|
|
69
|
-
const agg = createQqEventsAggregator({
|
|
70
|
-
getConfig: () => ({ ...ALL_ON, window_sec: 60 }),
|
|
71
|
-
getOutbound: () => fakeOutbound,
|
|
72
|
-
send: (t) => sent.push(t),
|
|
73
|
-
setTimeoutFn: (fn, ms) => {
|
|
74
|
-
timers.push({ fn, ms });
|
|
75
|
-
return timers.length;
|
|
76
|
-
},
|
|
77
|
-
clearTimeoutFn: () => {
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
agg.ingestOne({ type: "join", player: "A" });
|
|
81
|
-
agg.ingestOne({ type: "join", player: "B" });
|
|
82
|
-
agg.ingestOne({ type: "death", player: "A", cause: "fall" });
|
|
83
|
-
assert.equal(sent.length, 0);
|
|
84
|
-
assert.equal(agg.pendingCount(), 3);
|
|
85
|
-
assert.equal(timers.length, 1);
|
|
86
|
-
assert.equal(timers[0].ms, 6e4);
|
|
87
|
-
timers[0].fn();
|
|
88
|
-
assert.equal(sent.length, 1);
|
|
89
|
-
assert.match(sent[0], /上线:A、B/);
|
|
90
|
-
assert.match(sent[0], /死亡:A(坠落)/);
|
|
91
|
-
assert.equal(agg.pendingCount(), 0);
|
|
92
|
-
agg.dispose();
|
|
93
|
-
});
|
|
94
|
-
test("crash \u7ACB\u5373\u63A8\u4E14\u5148\u51B2\u5237\u7A97\u53E3", () => {
|
|
95
|
-
const sent = [];
|
|
96
|
-
const timers = [];
|
|
97
|
-
const agg = createQqEventsAggregator({
|
|
98
|
-
getConfig: () => ALL_ON,
|
|
99
|
-
getOutbound: () => fakeOutbound,
|
|
100
|
-
send: (t) => sent.push(t),
|
|
101
|
-
setTimeoutFn: (fn) => {
|
|
102
|
-
timers.push({ fn });
|
|
103
|
-
return 1;
|
|
104
|
-
},
|
|
105
|
-
clearTimeoutFn: () => {
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
agg.ingestOne({ type: "join", player: "Steve" });
|
|
109
|
-
agg.ingestOne({ type: "crash", detail: "code=1" });
|
|
110
|
-
assert.equal(sent.length, 2);
|
|
111
|
-
assert.match(sent[0], /上线:Steve/);
|
|
112
|
-
assert.match(sent[1], /BDS 意外退出 \(code=1\)/);
|
|
113
|
-
assert.equal(agg.pendingCount(), 0);
|
|
114
|
-
agg.dispose();
|
|
115
|
-
});
|
|
116
|
-
test("enabled:false \u5168\u4E22", () => {
|
|
117
|
-
const sent = [];
|
|
118
|
-
const agg = createQqEventsAggregator({
|
|
119
|
-
getConfig: () => ({ ...ALL_ON, enabled: false }),
|
|
120
|
-
getOutbound: () => fakeOutbound,
|
|
121
|
-
send: (t) => sent.push(t)
|
|
122
|
-
});
|
|
123
|
-
const r = agg.ingestMany([
|
|
124
|
-
{ type: "join", player: "A" },
|
|
125
|
-
{ type: "crash", detail: "x" }
|
|
126
|
-
]);
|
|
127
|
-
assert.equal(r.accepted, 0);
|
|
128
|
-
assert.equal(r.rejected, 2);
|
|
129
|
-
assert.equal(sent.length, 0);
|
|
130
|
-
agg.dispose();
|
|
131
|
-
});
|
|
132
|
-
test("\u5355\u7C7B\u5173\u95ED\uFF1Adeath \u5173\u5219\u4E22\u5F03", () => {
|
|
133
|
-
const sent = [];
|
|
134
|
-
const timers = [];
|
|
135
|
-
const agg = createQqEventsAggregator({
|
|
136
|
-
getConfig: () => ({ ...ALL_ON, death: false }),
|
|
137
|
-
getOutbound: () => fakeOutbound,
|
|
138
|
-
send: (t) => sent.push(t),
|
|
139
|
-
setTimeoutFn: (fn) => {
|
|
140
|
-
timers.push({ fn });
|
|
141
|
-
return 1;
|
|
142
|
-
},
|
|
143
|
-
clearTimeoutFn: () => {
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
assert.equal(agg.ingestOne({ type: "death", player: "A", cause: "fall" }).accepted, false);
|
|
147
|
-
assert.equal(agg.ingestOne({ type: "join", player: "A" }).accepted, true);
|
|
148
|
-
timers[0].fn();
|
|
149
|
-
assert.equal(sent.length, 1);
|
|
150
|
-
assert.doesNotMatch(sent[0], /死亡/);
|
|
151
|
-
agg.dispose();
|
|
152
|
-
});
|
|
153
|
-
test("\u7A97\u53E3\u6EE1 MAX_WINDOW_EVENTS \u63D0\u524D flush", () => {
|
|
154
|
-
const sent = [];
|
|
155
|
-
const agg = createQqEventsAggregator({
|
|
156
|
-
getConfig: () => ({ ...ALL_ON, window_sec: 600 }),
|
|
157
|
-
getOutbound: () => fakeOutbound,
|
|
158
|
-
send: (t) => sent.push(t),
|
|
159
|
-
setTimeoutFn: () => 1,
|
|
160
|
-
clearTimeoutFn: () => {
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
for (let i = 0; i < MAX_WINDOW_EVENTS; i++) {
|
|
164
|
-
agg.ingestOne({ type: "join", player: `P${i}` });
|
|
165
|
-
}
|
|
166
|
-
assert.equal(sent.length, 1);
|
|
167
|
-
assert.equal(agg.pendingCount(), 0);
|
|
168
|
-
agg.dispose();
|
|
169
|
-
});
|
|
170
|
-
//# sourceMappingURL=qq-events.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/domain/qq-events.test.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * qq-events \u805A\u5408\u5668\u5355\u6D4B\n */\n\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport {\n createQqEventsAggregator,\n formatImmediateBody,\n formatWindowBody,\n localizeCause,\n MAX_WINDOW_EVENTS,\n normalizeEventPayload,\n resolveQqEventsConfig,\n type ResolvedQqEventsConfig,\n} from \"./qq-events.js\";\nimport type { OutboundConfig } from \"./bridge.js\";\n\nconst ALL_ON: ResolvedQqEventsConfig = {\n enabled: true,\n window_sec: 60,\n join: true,\n leave: true,\n death: true,\n crash: true,\n start: true,\n};\n\nconst fakeOutbound: OutboundConfig = {\n backend: \"official\",\n creds: { appId: \"a\", appSecret: \"s\" },\n groupOpenid: \"G\",\n prefix: \"[MC]\",\n};\n\ntest(\"resolveQqEventsConfig \u7F3A\u7701\u4E0E\u603B\u5F00\u5173\", () => {\n const d = resolveQqEventsConfig(undefined);\n assert.equal(d.enabled, true);\n assert.equal(d.window_sec, 60);\n assert.equal(d.join, true);\n\n const off = resolveQqEventsConfig({ enabled: false, join: false });\n assert.equal(off.enabled, false);\n assert.equal(off.join, false);\n assert.equal(off.death, true);\n});\n\ntest(\"localizeCause \u6620\u5C04\u4E0E\u539F\u6587\u56DE\u9000\", () => {\n assert.equal(localizeCause(\"fall\"), \"\u5760\u843D\");\n assert.equal(localizeCause(\"drowning\"), \"\u6EBA\u6C34\");\n assert.equal(localizeCause(\"custom_xyz\"), \"custom_xyz\");\n assert.equal(localizeCause(\"\"), \"\");\n});\n\ntest(\"normalizeEventPayload \u8FC7\u6EE4\u975E\u6CD5 type\", () => {\n assert.equal(normalizeEventPayload({ type: \"chat\" }), null);\n assert.deepEqual(normalizeEventPayload({ type: \"join\", player: \"Steve\" }), {\n type: \"join\",\n player: \"Steve\",\n });\n});\n\ntest(\"formatWindowBody \u805A\u5408\u6587\u6848\", () => {\n const text = formatWindowBody([\n { type: \"join\", player: \"Steve\" },\n { type: \"join\", player: \"Alex\" },\n { type: \"leave\", player: \"Bob\" },\n { type: \"death\", player: \"Steve\", cause: \"fall\" },\n ]);\n assert.match(text, /^\\[MC\u4E8B\u4EF6\\]/);\n assert.match(text, /\u4E0A\u7EBF\uFF1ASteve\u3001Alex/);\n assert.match(text, /\u4E0B\u7EBF\uFF1ABob/);\n assert.match(text, /\u6B7B\u4EA1\uFF1ASteve\uFF08\u5760\u843D\uFF09/);\n});\n\ntest(\"formatImmediateBody crash/start\", () => {\n assert.equal(formatImmediateBody({ type: \"crash\", detail: \"code=1\" }), \"[MC\u4E8B\u4EF6] BDS \u610F\u5916\u9000\u51FA (code=1)\");\n assert.equal(formatImmediateBody({ type: \"start\", detail: \"pid=9\" }), \"[MC\u4E8B\u4EF6] BDS \u5DF2\u542F\u52A8 (pid=9)\");\n});\n\ntest(\"\u7A97\u53E3\u5185 join+death \u5230\u671F flush \u6210\u4E00\u6761\", () => {\n const sent: string[] = [];\n const timers: Array<{ fn: () => void; ms: number }> = [];\n const agg = createQqEventsAggregator({\n getConfig: () => ({ ...ALL_ON, window_sec: 60 }),\n getOutbound: () => fakeOutbound,\n send: (t) => sent.push(t),\n setTimeoutFn: (fn, ms) => {\n timers.push({ fn, ms });\n return timers.length as unknown as ReturnType<typeof setTimeout>;\n },\n clearTimeoutFn: () => {},\n });\n\n agg.ingestOne({ type: \"join\", player: \"A\" });\n agg.ingestOne({ type: \"join\", player: \"B\" });\n agg.ingestOne({ type: \"death\", player: \"A\", cause: \"fall\" });\n assert.equal(sent.length, 0);\n assert.equal(agg.pendingCount(), 3);\n assert.equal(timers.length, 1);\n assert.equal(timers[0]!.ms, 60_000);\n\n timers[0]!.fn();\n assert.equal(sent.length, 1);\n assert.match(sent[0]!, /\u4E0A\u7EBF\uFF1AA\u3001B/);\n assert.match(sent[0]!, /\u6B7B\u4EA1\uFF1AA\uFF08\u5760\u843D\uFF09/);\n assert.equal(agg.pendingCount(), 0);\n agg.dispose();\n});\n\ntest(\"crash \u7ACB\u5373\u63A8\u4E14\u5148\u51B2\u5237\u7A97\u53E3\", () => {\n const sent: string[] = [];\n const timers: Array<{ fn: () => void }> = [];\n const agg = createQqEventsAggregator({\n getConfig: () => ALL_ON,\n getOutbound: () => fakeOutbound,\n send: (t) => sent.push(t),\n setTimeoutFn: (fn) => {\n timers.push({ fn });\n return 1 as unknown as ReturnType<typeof setTimeout>;\n },\n clearTimeoutFn: () => {},\n });\n\n agg.ingestOne({ type: \"join\", player: \"Steve\" });\n agg.ingestOne({ type: \"crash\", detail: \"code=1\" });\n assert.equal(sent.length, 2);\n assert.match(sent[0]!, /\u4E0A\u7EBF\uFF1ASteve/);\n assert.match(sent[1]!, /BDS \u610F\u5916\u9000\u51FA \\(code=1\\)/);\n assert.equal(agg.pendingCount(), 0);\n agg.dispose();\n});\n\ntest(\"enabled:false \u5168\u4E22\", () => {\n const sent: string[] = [];\n const agg = createQqEventsAggregator({\n getConfig: () => ({ ...ALL_ON, enabled: false }),\n getOutbound: () => fakeOutbound,\n send: (t) => sent.push(t),\n });\n const r = agg.ingestMany([\n { type: \"join\", player: \"A\" },\n { type: \"crash\", detail: \"x\" },\n ]);\n assert.equal(r.accepted, 0);\n assert.equal(r.rejected, 2);\n assert.equal(sent.length, 0);\n agg.dispose();\n});\n\ntest(\"\u5355\u7C7B\u5173\u95ED\uFF1Adeath \u5173\u5219\u4E22\u5F03\", () => {\n const sent: string[] = [];\n const timers: Array<{ fn: () => void }> = [];\n const agg = createQqEventsAggregator({\n getConfig: () => ({ ...ALL_ON, death: false }),\n getOutbound: () => fakeOutbound,\n send: (t) => sent.push(t),\n setTimeoutFn: (fn) => {\n timers.push({ fn });\n return 1 as unknown as ReturnType<typeof setTimeout>;\n },\n clearTimeoutFn: () => {},\n });\n assert.equal(agg.ingestOne({ type: \"death\", player: \"A\", cause: \"fall\" }).accepted, false);\n assert.equal(agg.ingestOne({ type: \"join\", player: \"A\" }).accepted, true);\n timers[0]!.fn();\n assert.equal(sent.length, 1);\n assert.doesNotMatch(sent[0]!, /\u6B7B\u4EA1/);\n agg.dispose();\n});\n\ntest(\"\u7A97\u53E3\u6EE1 MAX_WINDOW_EVENTS \u63D0\u524D flush\", () => {\n const sent: string[] = [];\n const agg = createQqEventsAggregator({\n getConfig: () => ({ ...ALL_ON, window_sec: 600 }),\n getOutbound: () => fakeOutbound,\n send: (t) => sent.push(t),\n setTimeoutFn: () => 1 as unknown as ReturnType<typeof setTimeout>,\n clearTimeoutFn: () => {},\n });\n for (let i = 0; i < MAX_WINDOW_EVENTS; i++) {\n agg.ingestOne({ type: \"join\", player: `P${i}` });\n }\n assert.equal(sent.length, 1);\n assert.equal(agg.pendingCount(), 0);\n agg.dispose();\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qq-join.test.d.ts","sourceRoot":"","sources":["../../src/domain/qq-join.test.ts"],"names":[],"mappings":""}
|