@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.
Files changed (94) hide show
  1. package/README.md +1 -1
  2. package/dist/domain/bridge.d.ts +1 -5
  3. package/dist/domain/bridge.d.ts.map +1 -1
  4. package/dist/domain/bridge.js +15 -14
  5. package/dist/domain/bridge.js.map +2 -2
  6. package/dist/domain/installed-content.d.ts +84 -0
  7. package/dist/domain/installed-content.d.ts.map +1 -0
  8. package/dist/domain/installed-content.js +149 -0
  9. package/dist/domain/installed-content.js.map +7 -0
  10. package/dist/domain/player-session.d.ts +8 -0
  11. package/dist/domain/player-session.d.ts.map +1 -0
  12. package/dist/domain/player-session.js +16 -0
  13. package/dist/domain/player-session.js.map +7 -0
  14. package/dist/domain/qq-account-profile.d.ts +51 -0
  15. package/dist/domain/qq-account-profile.d.ts.map +1 -0
  16. package/dist/domain/qq-account-profile.js +129 -0
  17. package/dist/domain/qq-account-profile.js.map +7 -0
  18. package/dist/domain/qq-events.d.ts +2 -2
  19. package/dist/domain/qq-events.d.ts.map +1 -1
  20. package/dist/domain/qq-events.js +6 -3
  21. package/dist/domain/qq-events.js.map +2 -2
  22. package/dist/domain/schema.d.ts.map +1 -1
  23. package/dist/domain/schema.js +48 -0
  24. package/dist/domain/schema.js.map +2 -2
  25. package/dist/domain/system-status.d.ts +3 -0
  26. package/dist/domain/system-status.d.ts.map +1 -1
  27. package/dist/domain/system-status.js +27 -12
  28. package/dist/domain/system-status.js.map +2 -2
  29. package/dist/env.d.ts +0 -2
  30. package/dist/env.d.ts.map +1 -1
  31. package/dist/env.js +12 -24
  32. package/dist/env.js.map +2 -2
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +108 -52
  36. package/dist/index.js.map +3 -3
  37. package/dist/routes/config.d.ts +1 -1
  38. package/dist/routes/config.d.ts.map +1 -1
  39. package/dist/routes/config.js +0 -4
  40. package/dist/routes/config.js.map +2 -2
  41. package/dist/routes/content.d.ts +23 -0
  42. package/dist/routes/content.d.ts.map +1 -0
  43. package/dist/routes/content.js +19 -0
  44. package/dist/routes/content.js.map +7 -0
  45. package/dist/routes/messages.d.ts +14 -6
  46. package/dist/routes/messages.d.ts.map +1 -1
  47. package/dist/routes/messages.js +22 -8
  48. package/dist/routes/messages.js.map +2 -2
  49. package/dist/routes/qq-bind.d.ts.map +1 -1
  50. package/dist/routes/qq-bind.js +29 -1
  51. package/dist/routes/qq-bind.js.map +2 -2
  52. package/dist/routes/qq-events.d.ts +6 -2
  53. package/dist/routes/qq-events.d.ts.map +1 -1
  54. package/dist/routes/qq-events.js +35 -1
  55. package/dist/routes/qq-events.js.map +3 -3
  56. package/dist/routes/qq-join.js +1 -1
  57. package/dist/routes/qq-join.js.map +2 -2
  58. package/dist/routes/status.d.ts +3 -11
  59. package/dist/routes/status.d.ts.map +1 -1
  60. package/dist/routes/status.js +39 -49
  61. package/dist/routes/status.js.map +2 -2
  62. package/dist/tx-runner.d.ts +11 -2
  63. package/dist/tx-runner.d.ts.map +1 -1
  64. package/dist/tx-runner.js +42 -7
  65. package/dist/tx-runner.js.map +2 -2
  66. package/package.json +4 -5
  67. package/dist/domain/bridge.test.d.ts +0 -2
  68. package/dist/domain/bridge.test.d.ts.map +0 -1
  69. package/dist/domain/bridge.test.js +0 -87
  70. package/dist/domain/bridge.test.js.map +0 -7
  71. package/dist/domain/messages-bridge-filter.test.d.ts +0 -5
  72. package/dist/domain/messages-bridge-filter.test.d.ts.map +0 -1
  73. package/dist/domain/messages-bridge-filter.test.js +0 -20
  74. package/dist/domain/messages-bridge-filter.test.js.map +0 -7
  75. package/dist/domain/qq-bind-status.test.d.ts +0 -2
  76. package/dist/domain/qq-bind-status.test.d.ts.map +0 -1
  77. package/dist/domain/qq-bind-status.test.js +0 -211
  78. package/dist/domain/qq-bind-status.test.js.map +0 -7
  79. package/dist/domain/qq-events.test.d.ts +0 -5
  80. package/dist/domain/qq-events.test.d.ts.map +0 -1
  81. package/dist/domain/qq-events.test.js +0 -170
  82. package/dist/domain/qq-events.test.js.map +0 -7
  83. package/dist/domain/qq-join.test.d.ts +0 -2
  84. package/dist/domain/qq-join.test.d.ts.map +0 -1
  85. package/dist/domain/qq-join.test.js +0 -353
  86. package/dist/domain/qq-join.test.js.map +0 -7
  87. package/dist/domain/system-status.test.d.ts +0 -5
  88. package/dist/domain/system-status.test.d.ts.map +0 -1
  89. package/dist/domain/system-status.test.js +0 -19
  90. package/dist/domain/system-status.test.js.map +0 -7
  91. package/dist/runtime.test.d.ts +0 -2
  92. package/dist/runtime.test.d.ts.map +0 -1
  93. package/dist/runtime.test.js +0 -402
  94. package/dist/runtime.test.js.map +0 -7
@@ -1,402 +0,0 @@
1
- import { deepEqual, equal, rejects, throws } from "node:assert/strict";
2
- import test from "node:test";
3
- import { SQL } from "sql-template-strings";
4
- import { assertIdentifier, quoteIdentifier } from "./lib/identifiers.js";
5
- import { parseNodeVersion } from "./lib/runtime.js";
6
- import { raw, sql } from "./lib/sql-helpers.js";
7
- import { DispatchError, ServiceRegistry } from "./service-registry.js";
8
- test("parses Node versions", () => {
9
- deepEqual(parseNodeVersion("22.5.1"), { major: 22, minor: 5, patch: 1 });
10
- deepEqual(parseNodeVersion("v22.5.1"), { major: 22, minor: 5, patch: 1 });
11
- });
12
- test("accepts only safe SQL identifiers", () => {
13
- equal(quoteIdentifier("sfmc_players", "table"), '"sfmc_players"');
14
- throws(() => assertIdentifier("users; DROP TABLE x"), /Invalid SQL/);
15
- });
16
- test("sql() embeds trusted identifiers and binds values", () => {
17
- const TABLE = "sfmc_economy_accounts";
18
- const q = sql(`SELECT * FROM ${TABLE} WHERE player_id = ?`, ["p1"]);
19
- equal(q.sql, "SELECT * FROM sfmc_economy_accounts WHERE player_id = ?");
20
- deepEqual(q.values, ["p1"]);
21
- });
22
- test("raw() only works via append \u2014 template interpolation still becomes ?", () => {
23
- const TABLE = "sfmc_economy_accounts";
24
- const broken = SQL`SELECT * FROM ${raw(TABLE)} WHERE id = ${"p1"}`;
25
- equal(broken.sql, "SELECT * FROM ? WHERE id = ?");
26
- const ok = SQL`SELECT * FROM `.append(raw(TABLE)).append(SQL` WHERE id = ${"p1"}`);
27
- equal(ok.sql, "SELECT * FROM sfmc_economy_accounts WHERE id = ?");
28
- deepEqual(ok.values, ["p1"]);
29
- });
30
- test("ServiceRegistry: provider self-call skips requires (LSP with tx.call path)", async () => {
31
- const reg = new ServiceRegistry();
32
- reg.registerHandler("feature-economy", "economy.stats.monthly", async () => ({ ok: true }));
33
- const enabled = /* @__PURE__ */ new Map([
34
- [
35
- "feature-economy",
36
- {
37
- id: "feature-economy",
38
- version: "1.0.0",
39
- permissions: [],
40
- services: { provides: [{ name: "economy.stats.monthly" }], requires: [] },
41
- db: { tables: [] },
42
- config: { key: "economy" }
43
- }
44
- ]
45
- ]);
46
- const out = await reg.dispatch(enabled, "feature-economy", "economy.stats.monthly", {});
47
- deepEqual(out, { ok: true, result: { ok: true } });
48
- });
49
- test("ServiceRegistry: missing service \u2192 no_such_service (not not_in_requires)", async () => {
50
- const reg = new ServiceRegistry();
51
- const enabled = /* @__PURE__ */ new Map([
52
- [
53
- "feature-chat",
54
- {
55
- id: "feature-chat",
56
- version: "1.0.0",
57
- permissions: [],
58
- services: { provides: [], requires: [] },
59
- db: { tables: [] },
60
- config: { key: "chat" }
61
- }
62
- ]
63
- ]);
64
- await rejects(
65
- () => reg.dispatch(enabled, "feature-chat", "economy.account.get", {}),
66
- (e) => e instanceof DispatchError && e.code === "no_such_service"
67
- );
68
- });
69
- test("jsonV2Fail: ok \u65B9\u8A00 + extra(step) \u5408\u5E76(LSP/DRY)", async () => {
70
- const { jsonV2Fail } = await import("./routes/_shared.js");
71
- const chunks = [];
72
- let statusCode = 0;
73
- const res = {
74
- writeHead(code) {
75
- statusCode = code;
76
- },
77
- end(body) {
78
- if (body) chunks.push(Buffer.from(body));
79
- },
80
- setHeader() {
81
- }
82
- };
83
- jsonV2Fail(res, "boom", 400, "bad_step", { step: 2 });
84
- const payload = JSON.parse(Buffer.concat(chunks).toString("utf8"));
85
- equal(statusCode, 400);
86
- deepEqual(payload, { ok: false, error: "boom", code: "bad_step", step: 2 });
87
- });
88
- test("jsonV2Ok: \u4E0E Fail \u5BF9\u79F0 ok \u65B9\u8A00(LSP/DRY)", async () => {
89
- const { jsonV2Ok } = await import("./routes/_shared.js");
90
- const chunks = [];
91
- let statusCode = 0;
92
- const res = {
93
- writeHead(code) {
94
- statusCode = code;
95
- },
96
- end(body) {
97
- if (body) chunks.push(Buffer.from(body));
98
- },
99
- setHeader() {
100
- }
101
- };
102
- jsonV2Ok(res, { rows: [1] });
103
- const payload = JSON.parse(Buffer.concat(chunks).toString("utf8"));
104
- equal(statusCode, 200);
105
- deepEqual(payload, { ok: true, rows: [1] });
106
- });
107
- test("normalizeOrderBy: SDK field \u4E0E\u9057\u7559 col / \u6570\u7EC4\u4E92\u901A(LSP)", async () => {
108
- const { normalizeOrderBy } = await import("./lib/order-by.js");
109
- deepEqual(normalizeOrderBy(void 0), []);
110
- deepEqual(normalizeOrderBy({ field: "created_at", dir: "desc" }), [{ col: "created_at", dir: "desc" }]);
111
- deepEqual(normalizeOrderBy({ col: "id" }), [{ col: "id", dir: "asc" }]);
112
- deepEqual(normalizeOrderBy([{ field: "a" }, { col: "b", dir: "desc" }]), [
113
- { col: "a", dir: "asc" },
114
- { col: "b", dir: "desc" }
115
- ]);
116
- throws(() => normalizeOrderBy({ dir: "asc" }), /field\/col/);
117
- });
118
- test("syncModuleRuntimeState: enable/disable \u70ED\u66F4\u65B0 token+enabledSet(DIP)", async () => {
119
- const { mkdtempSync, rmSync, readFileSync } = await import("node:fs");
120
- const { join } = await import("node:path");
121
- const { tmpdir } = await import("node:os");
122
- const { syncModuleRuntimeState } = await import("./module-runtime-sync.js");
123
- const { deriveToken } = await import("./module-auth.js");
124
- const { unregisterBuiltinPluginForModule } = await import("./services/builtin-handlers.js");
125
- const root = mkdtempSync(join(tmpdir(), "sfmc-runtime-sync-"));
126
- const dbPath = join(root, "data", "sfmc_data.db");
127
- try {
128
- const enabledSet = /* @__PURE__ */ new Set(["feature-a"]);
129
- const enabledManifests = /* @__PURE__ */ new Map();
130
- const moduleAuth = { tokens: { "feature-a": "old" }, secret: "test-secret" };
131
- const registry = new ServiceRegistry();
132
- const fakeManifest = {
133
- id: "feature-b",
134
- version: "1.0.0",
135
- permissions: [],
136
- services: { provides: [], requires: [] },
137
- db: { tables: [] },
138
- config: { key: "b" }
139
- };
140
- syncModuleRuntimeState({
141
- moduleId: "feature-b",
142
- enabled: true,
143
- dbPath,
144
- envAuthToken: "fixed-auth",
145
- enabledSet,
146
- enabledManifests,
147
- loadedManifest: { modules: { "feature-b": fakeManifest } },
148
- moduleAuth,
149
- serviceRegistry: registry,
150
- builtinDeps: { query: (() => []), db: {} }
151
- });
152
- equal(enabledSet.has("feature-b"), true);
153
- equal(enabledManifests.has("feature-b"), true);
154
- equal(moduleAuth.tokens["feature-b"], deriveToken("feature-b", "test-secret"));
155
- const store = JSON.parse(readFileSync(join(root, "data", "module-tokens.json"), "utf8"));
156
- equal(store.tokens["feature-b"], moduleAuth.tokens["feature-b"]);
157
- syncModuleRuntimeState({
158
- moduleId: "feature-b",
159
- enabled: false,
160
- dbPath,
161
- envAuthToken: "fixed-auth",
162
- enabledSet,
163
- enabledManifests,
164
- loadedManifest: { modules: { "feature-b": fakeManifest } },
165
- moduleAuth,
166
- serviceRegistry: registry,
167
- builtinDeps: { query: (() => []), db: {} }
168
- });
169
- equal(enabledSet.has("feature-b"), false);
170
- equal(enabledManifests.has("feature-b"), false);
171
- equal(moduleAuth.tokens["feature-b"], void 0);
172
- equal(unregisterBuiltinPluginForModule(registry, "feature-b"), 0);
173
- } finally {
174
- rmSync(root, { recursive: true, force: true });
175
- }
176
- });
177
- test("module-auth: ensureModuleToken / revoke \u590D\u7528 secret(DRY)", async () => {
178
- const { deriveToken, ensureModuleToken, revokeModuleToken } = await import("./module-auth.js");
179
- const secret = "test-secret";
180
- const auth = { secret, tokens: {} };
181
- equal(ensureModuleToken(auth, "feature-afk"), true);
182
- equal(auth.tokens["feature-afk"], deriveToken("feature-afk", secret));
183
- equal(ensureModuleToken(auth, "feature-afk"), false);
184
- equal(revokeModuleToken(auth, "feature-afk"), true);
185
- equal(auth.tokens["feature-afk"], void 0);
186
- equal(revokeModuleToken(auth, "feature-afk"), false);
187
- });
188
- test("builtin-handlers: \u70ED\u7981\u7528\u6309 moduleId \u5378\u8F7D(DRY/OCP)", async () => {
189
- const { unregisterBuiltinPluginForModule, registerBuiltinPluginForModule } = await import("./services/builtin-handlers.js");
190
- const reg = new ServiceRegistry();
191
- reg.registerHandler("feature-economy", "economy.account.get", async () => ({}));
192
- reg.registerHandler("feature-economy", "economy.account.debit", async () => ({}));
193
- reg.registerHandler("other-mod", "other.ping", async () => ({}));
194
- equal(unregisterBuiltinPluginForModule(reg, "feature-economy"), 2);
195
- equal(reg.list().length, 1);
196
- equal(reg.list()[0]?.moduleId, "other-mod");
197
- equal(unregisterBuiltinPluginForModule(reg, "feature-unknown"), 0);
198
- equal(registerBuiltinPluginForModule(reg, { query: (() => []), db: {} }, "feature-economy"), true);
199
- equal(registerBuiltinPluginForModule(reg, { query: (() => []), db: {} }, "feature-economy"), false);
200
- });
201
- test("TxRunner \u4EA4\u4E92\u4F1A\u8BDD: step \u4E2D\u9014\u8BFB\u56DE insert/get(PR #31 leftover)", async () => {
202
- const { DatabaseSync } = await import("node:sqlite");
203
- const { createQuery } = await import("./lib/sqlite.js");
204
- const { SchemaRegistry } = await import("./schema-registry.js");
205
- const { TxRunner } = await import("./tx-runner.js");
206
- const db = new DatabaseSync(":memory:");
207
- const query = createQuery(db);
208
- const schema = new SchemaRegistry(db);
209
- schema.define("feature-demo", {
210
- name: "demo_items",
211
- columns: {
212
- id: { type: "text", primary: true },
213
- name: { type: "text", notNull: true }
214
- },
215
- softDelete: false
216
- });
217
- const enabled = /* @__PURE__ */ new Map([
218
- [
219
- "feature-demo",
220
- {
221
- id: "feature-demo",
222
- version: "1.0.0",
223
- permissions: ["db:read:demo_items", "db:write:demo_items"],
224
- services: { provides: [], requires: [] },
225
- db: { tables: [] },
226
- config: { key: "demo" }
227
- }
228
- ]
229
- ]);
230
- const runner = new TxRunner({
231
- db,
232
- query,
233
- schema,
234
- serviceRegistry: new ServiceRegistry(),
235
- enabled
236
- });
237
- const begin = await runner.beginSession("feature-demo");
238
- equal(begin.ok, true);
239
- if (!begin.ok) return;
240
- const { txId } = begin;
241
- const ins = await runner.stepSession(txId, "feature-demo", {
242
- op: "insert",
243
- table: "demo_items",
244
- row: { id: "a1", name: "alpha" }
245
- });
246
- equal(ins.ok, true);
247
- if (!ins.ok) return;
248
- equal(ins.result.row.id, "a1");
249
- const got = await runner.stepSession(txId, "feature-demo", {
250
- op: "get",
251
- table: "demo_items",
252
- id: "a1"
253
- });
254
- equal(got.ok, true);
255
- if (!got.ok) return;
256
- equal(got.result.row?.name, "alpha");
257
- const committed = runner.commitSession(txId, "feature-demo");
258
- equal(committed.ok, true);
259
- const rows = db.prepare("SELECT name FROM demo_items WHERE id = ?").all("a1");
260
- equal(rows[0]?.name, "alpha");
261
- db.close();
262
- });
263
- test("TxRunner \u4EA4\u4E92\u4F1A\u8BDD: \u5E76\u53D1 beginSession \u81EA\u52A8\u6392\u961F\u4E92\u65A5\u6267\u884C", async () => {
264
- const { DatabaseSync } = await import("node:sqlite");
265
- const { createQuery } = await import("./lib/sqlite.js");
266
- const { SchemaRegistry } = await import("./schema-registry.js");
267
- const { TxRunner } = await import("./tx-runner.js");
268
- const db = new DatabaseSync(":memory:");
269
- const query = createQuery(db);
270
- const schema = new SchemaRegistry(db);
271
- schema.define("feature-demo", {
272
- name: "queue_items",
273
- columns: {
274
- id: { type: "text", primary: true },
275
- val: { type: "text", notNull: true }
276
- },
277
- softDelete: false
278
- });
279
- const enabled = /* @__PURE__ */ new Map([
280
- [
281
- "feature-demo",
282
- {
283
- id: "feature-demo",
284
- version: "1.0.0",
285
- permissions: ["db:read:queue_items", "db:write:queue_items"],
286
- services: { provides: [], requires: [] },
287
- db: { tables: [] },
288
- config: { key: "demo" }
289
- }
290
- ]
291
- ]);
292
- const runner = new TxRunner({
293
- db,
294
- query,
295
- schema,
296
- serviceRegistry: new ServiceRegistry(),
297
- enabled
298
- });
299
- const s1 = await runner.beginSession("feature-demo");
300
- equal(s1.ok, true);
301
- if (!s1.ok) return;
302
- let s2Started = false;
303
- const s2Promise = runner.beginSession("feature-demo").then((res) => {
304
- s2Started = true;
305
- return res;
306
- });
307
- equal(s2Started, false);
308
- const s1Step = await runner.stepSession(s1.txId, "feature-demo", {
309
- op: "insert",
310
- table: "queue_items",
311
- row: { id: "1", val: "one" }
312
- });
313
- equal(s1Step.ok, true);
314
- const s1Commit = runner.commitSession(s1.txId, "feature-demo");
315
- equal(s1Commit.ok, true);
316
- const s2 = await s2Promise;
317
- equal(s2.ok, true);
318
- equal(s2Started, true);
319
- if (!s2.ok) return;
320
- const s2Step = await runner.stepSession(s2.txId, "feature-demo", {
321
- op: "insert",
322
- table: "queue_items",
323
- row: { id: "2", val: "two" }
324
- });
325
- equal(s2Step.ok, true);
326
- const s2Commit = runner.commitSession(s2.txId, "feature-demo");
327
- equal(s2Commit.ok, true);
328
- const rows = db.prepare("SELECT val FROM queue_items ORDER BY id ASC").all();
329
- equal(rows.length, 2);
330
- equal(rows[0]?.val, "one");
331
- equal(rows[1]?.val, "two");
332
- db.close();
333
- });
334
- test("TxRunner \u5355\u8FDE\u63A5: run \u4E0E\u4EA4\u4E92\u4F1A\u8BDD\u5171\u7528\u4E8B\u52A1\u961F\u5217", async () => {
335
- const { DatabaseSync } = await import("node:sqlite");
336
- const { createQuery } = await import("./lib/sqlite.js");
337
- const { SchemaRegistry } = await import("./schema-registry.js");
338
- const { TxRunner } = await import("./tx-runner.js");
339
- const db = new DatabaseSync(":memory:");
340
- const query = createQuery(db);
341
- const schema = new SchemaRegistry(db);
342
- schema.define("feature-demo", {
343
- name: "queue_items",
344
- columns: {
345
- id: { type: "text", primary: true },
346
- val: { type: "text", notNull: true }
347
- },
348
- softDelete: false
349
- });
350
- const enabled = /* @__PURE__ */ new Map([
351
- [
352
- "feature-demo",
353
- {
354
- id: "feature-demo",
355
- version: "1.0.0",
356
- permissions: ["db:read:queue_items", "db:write:queue_items"],
357
- services: { provides: [], requires: [] },
358
- db: { tables: [] },
359
- config: { key: "demo" }
360
- }
361
- ]
362
- ]);
363
- const runner = new TxRunner({
364
- db,
365
- query,
366
- schema,
367
- serviceRegistry: new ServiceRegistry(),
368
- enabled
369
- });
370
- const session = await runner.beginSession("feature-demo");
371
- equal(session.ok, true);
372
- if (!session.ok) return;
373
- let runFinished = false;
374
- const queuedRun = runner.run({
375
- moduleId: "feature-demo",
376
- steps: [{ op: "query", table: "queue_items" }]
377
- }).then((result) => {
378
- runFinished = true;
379
- return result;
380
- });
381
- equal(runFinished, false);
382
- equal(runner.commitSession(session.txId, "feature-demo").ok, true);
383
- equal((await queuedRun).ok, true);
384
- equal(runFinished, true);
385
- const running = runner.run({
386
- moduleId: "feature-demo",
387
- steps: [{ op: "query", table: "queue_items" }]
388
- });
389
- let sessionStarted = false;
390
- const queuedSession = runner.beginSession("feature-demo").then((result) => {
391
- sessionStarted = true;
392
- return result;
393
- });
394
- equal(sessionStarted, false);
395
- equal((await running).ok, true);
396
- const nextSession = await queuedSession;
397
- equal(nextSession.ok, true);
398
- equal(sessionStarted, true);
399
- if (nextSession.ok) equal(runner.rollbackSession(nextSession.txId, "feature-demo").ok, true);
400
- db.close();
401
- });
402
- //# sourceMappingURL=runtime.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/runtime.test.ts"],
4
- "sourcesContent": ["import { deepEqual, equal, rejects, throws } from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { SQL } from \"sql-template-strings\";\nimport { assertIdentifier, quoteIdentifier } from \"./lib/identifiers.js\";\nimport { parseNodeVersion } from \"./lib/runtime.js\";\nimport { raw, sql } from \"./lib/sql-helpers.js\";\nimport { DispatchError, ServiceRegistry } from \"./service-registry.js\";\n\ntest(\"parses Node versions\", () => {\n deepEqual(parseNodeVersion(\"22.5.1\"), { major: 22, minor: 5, patch: 1 });\n deepEqual(parseNodeVersion(\"v22.5.1\"), { major: 22, minor: 5, patch: 1 });\n});\n\ntest(\"accepts only safe SQL identifiers\", () => {\n equal(quoteIdentifier(\"sfmc_players\", \"table\"), '\"sfmc_players\"');\n throws(() => assertIdentifier(\"users; DROP TABLE x\"), /Invalid SQL/);\n});\n\ntest(\"sql() embeds trusted identifiers and binds values\", () => {\n const TABLE = \"sfmc_economy_accounts\";\n const q = sql(`SELECT * FROM ${TABLE} WHERE player_id = ?`, [\"p1\"]);\n equal(q.sql, \"SELECT * FROM sfmc_economy_accounts WHERE player_id = ?\");\n deepEqual(q.values, [\"p1\"]);\n});\n\ntest(\"raw() only works via append \u2014 template interpolation still becomes ?\", () => {\n const TABLE = \"sfmc_economy_accounts\";\n const broken = SQL`SELECT * FROM ${raw(TABLE)} WHERE id = ${\"p1\"}`;\n equal(broken.sql, \"SELECT * FROM ? WHERE id = ?\");\n\n const ok = SQL`SELECT * FROM `.append(raw(TABLE)).append(SQL` WHERE id = ${\"p1\"}`);\n equal(ok.sql, \"SELECT * FROM sfmc_economy_accounts WHERE id = ?\");\n deepEqual(ok.values, [\"p1\"]);\n});\n\ntest(\"ServiceRegistry: provider self-call skips requires (LSP with tx.call path)\", async () => {\n const reg = new ServiceRegistry();\n reg.registerHandler(\"feature-economy\", \"economy.stats.monthly\", async () => ({ ok: true }));\n\n const enabled = new Map([\n [\n \"feature-economy\",\n {\n id: \"feature-economy\",\n version: \"1.0.0\",\n permissions: [] as string[],\n services: { provides: [{ name: \"economy.stats.monthly\" }], requires: [] as Array<{ name: string }> },\n db: { tables: [] as unknown[] },\n config: { key: \"economy\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2,\n ],\n ]);\n\n const out = await reg.dispatch(enabled, \"feature-economy\", \"economy.stats.monthly\", {});\n deepEqual(out, { ok: true, result: { ok: true } });\n});\n\ntest(\"ServiceRegistry: missing service \u2192 no_such_service (not not_in_requires)\", async () => {\n const reg = new ServiceRegistry();\n const enabled = new Map([\n [\n \"feature-chat\",\n {\n id: \"feature-chat\",\n version: \"1.0.0\",\n permissions: [] as string[],\n services: { provides: [], requires: [] },\n db: { tables: [] },\n config: { key: \"chat\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2,\n ],\n ]);\n\n await rejects(\n () => reg.dispatch(enabled, \"feature-chat\", \"economy.account.get\", {}),\n (e: unknown) => e instanceof DispatchError && e.code === \"no_such_service\"\n );\n});\n\ntest(\"jsonV2Fail: ok \u65B9\u8A00 + extra(step) \u5408\u5E76(LSP/DRY)\", async () => {\n const { jsonV2Fail } = await import(\"./routes/_shared.js\");\n const chunks: Buffer[] = [];\n let statusCode = 0;\n const res = {\n writeHead(code: number) {\n statusCode = code;\n },\n end(body?: string) {\n if (body) chunks.push(Buffer.from(body));\n },\n setHeader() {},\n } as unknown as import(\"node:http\").ServerResponse;\n\n jsonV2Fail(res, \"boom\", 400, \"bad_step\", { step: 2 });\n const payload = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n equal(statusCode, 400);\n deepEqual(payload, { ok: false, error: \"boom\", code: \"bad_step\", step: 2 });\n});\n\ntest(\"jsonV2Ok: \u4E0E Fail \u5BF9\u79F0 ok \u65B9\u8A00(LSP/DRY)\", async () => {\n const { jsonV2Ok } = await import(\"./routes/_shared.js\");\n const chunks: Buffer[] = [];\n let statusCode = 0;\n const res = {\n writeHead(code: number) {\n statusCode = code;\n },\n end(body?: string) {\n if (body) chunks.push(Buffer.from(body));\n },\n setHeader() {},\n } as unknown as import(\"node:http\").ServerResponse;\n\n jsonV2Ok(res, { rows: [1] });\n const payload = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n equal(statusCode, 200);\n deepEqual(payload, { ok: true, rows: [1] });\n});\n\ntest(\"normalizeOrderBy: SDK field \u4E0E\u9057\u7559 col / \u6570\u7EC4\u4E92\u901A(LSP)\", async () => {\n const { normalizeOrderBy } = await import(\"./lib/order-by.js\");\n deepEqual(normalizeOrderBy(undefined), []);\n deepEqual(normalizeOrderBy({ field: \"created_at\", dir: \"desc\" }), [{ col: \"created_at\", dir: \"desc\" }]);\n deepEqual(normalizeOrderBy({ col: \"id\" }), [{ col: \"id\", dir: \"asc\" }]);\n deepEqual(normalizeOrderBy([{ field: \"a\" }, { col: \"b\", dir: \"desc\" }]), [\n { col: \"a\", dir: \"asc\" },\n { col: \"b\", dir: \"desc\" },\n ]);\n throws(() => normalizeOrderBy({ dir: \"asc\" }), /field\\/col/);\n});\n\ntest(\"syncModuleRuntimeState: enable/disable \u70ED\u66F4\u65B0 token+enabledSet(DIP)\", async () => {\n const { mkdtempSync, rmSync, readFileSync } = await import(\"node:fs\");\n const { join } = await import(\"node:path\");\n const { tmpdir } = await import(\"node:os\");\n const { syncModuleRuntimeState } = await import(\"./module-runtime-sync.js\");\n const { deriveToken } = await import(\"./module-auth.js\");\n const { unregisterBuiltinPluginForModule } = await import(\"./services/builtin-handlers.js\");\n\n const root = mkdtempSync(join(tmpdir(), \"sfmc-runtime-sync-\"));\n const dbPath = join(root, \"data\", \"sfmc_data.db\");\n try {\n const enabledSet = new Set<string>([\"feature-a\"]);\n const enabledManifests = new Map();\n const moduleAuth = { tokens: { \"feature-a\": \"old\" } as Record<string, string>, secret: \"test-secret\" };\n const registry = new ServiceRegistry();\n const fakeManifest = {\n id: \"feature-b\",\n version: \"1.0.0\",\n permissions: [] as string[],\n services: { provides: [], requires: [] },\n db: { tables: [] },\n config: { key: \"b\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2;\n\n syncModuleRuntimeState({\n moduleId: \"feature-b\",\n enabled: true,\n dbPath,\n envAuthToken: \"fixed-auth\",\n enabledSet,\n enabledManifests,\n loadedManifest: { modules: { \"feature-b\": fakeManifest } },\n moduleAuth,\n serviceRegistry: registry,\n builtinDeps: { query: (() => []) as never, db: {} as never },\n });\n\n equal(enabledSet.has(\"feature-b\"), true);\n equal(enabledManifests.has(\"feature-b\"), true);\n equal(moduleAuth.tokens[\"feature-b\"], deriveToken(\"feature-b\", \"test-secret\"));\n const store = JSON.parse(readFileSync(join(root, \"data\", \"module-tokens.json\"), \"utf8\"));\n equal(store.tokens[\"feature-b\"], moduleAuth.tokens[\"feature-b\"]);\n\n syncModuleRuntimeState({\n moduleId: \"feature-b\",\n enabled: false,\n dbPath,\n envAuthToken: \"fixed-auth\",\n enabledSet,\n enabledManifests,\n loadedManifest: { modules: { \"feature-b\": fakeManifest } },\n moduleAuth,\n serviceRegistry: registry,\n builtinDeps: { query: (() => []) as never, db: {} as never },\n });\n\n equal(enabledSet.has(\"feature-b\"), false);\n equal(enabledManifests.has(\"feature-b\"), false);\n equal(moduleAuth.tokens[\"feature-b\"], undefined);\n equal(unregisterBuiltinPluginForModule(registry, \"feature-b\"), 0);\n } finally {\n rmSync(root, { recursive: true, force: true });\n }\n});\n\ntest(\"module-auth: ensureModuleToken / revoke \u590D\u7528 secret(DRY)\", async () => {\n const { deriveToken, ensureModuleToken, revokeModuleToken } = await import(\"./module-auth.js\");\n const secret = \"test-secret\";\n const auth = { secret, tokens: {} as Record<string, string> };\n equal(ensureModuleToken(auth, \"feature-afk\"), true);\n equal(auth.tokens[\"feature-afk\"], deriveToken(\"feature-afk\", secret));\n equal(ensureModuleToken(auth, \"feature-afk\"), false);\n equal(revokeModuleToken(auth, \"feature-afk\"), true);\n equal(auth.tokens[\"feature-afk\"], undefined);\n equal(revokeModuleToken(auth, \"feature-afk\"), false);\n});\n\ntest(\"builtin-handlers: \u70ED\u7981\u7528\u6309 moduleId \u5378\u8F7D(DRY/OCP)\", async () => {\n const { unregisterBuiltinPluginForModule, registerBuiltinPluginForModule } =\n await import(\"./services/builtin-handlers.js\");\n\n const reg = new ServiceRegistry();\n reg.registerHandler(\"feature-economy\", \"economy.account.get\", async () => ({}));\n reg.registerHandler(\"feature-economy\", \"economy.account.debit\", async () => ({}));\n reg.registerHandler(\"other-mod\", \"other.ping\", async () => ({}));\n equal(unregisterBuiltinPluginForModule(reg, \"feature-economy\"), 2);\n equal(reg.list().length, 1);\n equal(reg.list()[0]?.moduleId, \"other-mod\");\n equal(unregisterBuiltinPluginForModule(reg, \"feature-unknown\"), 0);\n\n // \u5DF2\u6709\u540C moduleId handler \u65F6\u70ED\u542F\u7528\u8DF3\u8FC7\n equal(registerBuiltinPluginForModule(reg, { query: (() => []) as never, db: {} as never }, \"feature-economy\"), true);\n equal(registerBuiltinPluginForModule(reg, { query: (() => []) as never, db: {} as never }, \"feature-economy\"), false);\n});\n\ntest(\"TxRunner \u4EA4\u4E92\u4F1A\u8BDD: step \u4E2D\u9014\u8BFB\u56DE insert/get(PR #31 leftover)\", async () => {\n const { DatabaseSync } = await import(\"node:sqlite\");\n const { createQuery } = await import(\"./lib/sqlite.js\");\n const { SchemaRegistry } = await import(\"./schema-registry.js\");\n const { TxRunner } = await import(\"./tx-runner.js\");\n\n const db = new DatabaseSync(\":memory:\");\n const query = createQuery(db);\n const schema = new SchemaRegistry(db);\n schema.define(\"feature-demo\", {\n name: \"demo_items\",\n columns: {\n id: { type: \"text\", primary: true },\n name: { type: \"text\", notNull: true },\n },\n softDelete: false,\n });\n\n const enabled = new Map([\n [\n \"feature-demo\",\n {\n id: \"feature-demo\",\n version: \"1.0.0\",\n permissions: [\"db:read:demo_items\", \"db:write:demo_items\"],\n services: { provides: [], requires: [] },\n db: { tables: [] },\n config: { key: \"demo\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2,\n ],\n ]);\n\n const runner = new TxRunner({\n db,\n query,\n schema,\n serviceRegistry: new ServiceRegistry(),\n enabled,\n });\n\n const begin = await runner.beginSession(\"feature-demo\");\n equal(begin.ok, true);\n if (!begin.ok) return;\n const { txId } = begin;\n\n const ins = await runner.stepSession(txId, \"feature-demo\", {\n op: \"insert\",\n table: \"demo_items\",\n row: { id: \"a1\", name: \"alpha\" },\n });\n equal(ins.ok, true);\n if (!ins.ok) return;\n equal((ins.result as { op: string; row: { id: string } }).row.id, \"a1\");\n\n const got = await runner.stepSession(txId, \"feature-demo\", {\n op: \"get\",\n table: \"demo_items\",\n id: \"a1\",\n });\n equal(got.ok, true);\n if (!got.ok) return;\n equal((got.result as { row: { name: string } | null }).row?.name, \"alpha\");\n\n const committed = runner.commitSession(txId, \"feature-demo\");\n equal(committed.ok, true);\n\n const rows = db.prepare(\"SELECT name FROM demo_items WHERE id = ?\").all(\"a1\") as Array<{ name: string }>;\n equal(rows[0]?.name, \"alpha\");\n db.close();\n});\n\ntest(\"TxRunner \u4EA4\u4E92\u4F1A\u8BDD: \u5E76\u53D1 beginSession \u81EA\u52A8\u6392\u961F\u4E92\u65A5\u6267\u884C\", async () => {\n const { DatabaseSync } = await import(\"node:sqlite\");\n const { createQuery } = await import(\"./lib/sqlite.js\");\n const { SchemaRegistry } = await import(\"./schema-registry.js\");\n const { TxRunner } = await import(\"./tx-runner.js\");\n\n const db = new DatabaseSync(\":memory:\");\n const query = createQuery(db);\n const schema = new SchemaRegistry(db);\n schema.define(\"feature-demo\", {\n name: \"queue_items\",\n columns: {\n id: { type: \"text\", primary: true },\n val: { type: \"text\", notNull: true },\n },\n softDelete: false,\n });\n\n const enabled = new Map([\n [\n \"feature-demo\",\n {\n id: \"feature-demo\",\n version: \"1.0.0\",\n permissions: [\"db:read:queue_items\", \"db:write:queue_items\"],\n services: { provides: [], requires: [] },\n db: { tables: [] },\n config: { key: \"demo\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2,\n ],\n ]);\n\n const runner = new TxRunner({\n db,\n query,\n schema,\n serviceRegistry: new ServiceRegistry(),\n enabled,\n });\n\n // Session 1 \u542F\u52A8\n const s1 = await runner.beginSession(\"feature-demo\");\n equal(s1.ok, true);\n if (!s1.ok) return;\n\n // Session 2 \u5E76\u53D1\u542F\u52A8\uFF08\u4F1A\u5F02\u6B65\u6392\u961F\u7B49\u5F85 Session 1 \u5B8C\u6210\uFF09\n let s2Started = false;\n const s2Promise = runner.beginSession(\"feature-demo\").then((res) => {\n s2Started = true;\n return res;\n });\n\n // \u6B64\u65F6 Session 2 \u5E94\u5904\u4E8E\u7B49\u5F85\u4E2D\uFF0C\u672A\u8FDB\u5165\n equal(s2Started, false);\n\n // Session 1 \u63D2\u5165\u6B65\u9AA4\n const s1Step = await runner.stepSession(s1.txId, \"feature-demo\", {\n op: \"insert\",\n table: \"queue_items\",\n row: { id: \"1\", val: \"one\" },\n });\n equal(s1Step.ok, true);\n\n // Session 1 \u63D0\u4EA4\n const s1Commit = runner.commitSession(s1.txId, \"feature-demo\");\n equal(s1Commit.ok, true);\n\n // Session 1 \u63D0\u4EA4\u540E\uFF0CSession 2 \u5E94\u8BE5\u88AB\u5524\u9192\u5E76\u6210\u529F\u83B7\u5F97\u4E8B\u52A1\n const s2 = await s2Promise;\n equal(s2.ok, true);\n equal(s2Started, true);\n if (!s2.ok) return;\n\n // Session 2 \u63D2\u5165\u6B65\u9AA4\u5E76\u63D0\u4EA4\n const s2Step = await runner.stepSession(s2.txId, \"feature-demo\", {\n op: \"insert\",\n table: \"queue_items\",\n row: { id: \"2\", val: \"two\" },\n });\n equal(s2Step.ok, true);\n\n const s2Commit = runner.commitSession(s2.txId, \"feature-demo\");\n equal(s2Commit.ok, true);\n\n const rows = db.prepare(\"SELECT val FROM queue_items ORDER BY id ASC\").all() as Array<{ val: string }>;\n equal(rows.length, 2);\n equal(rows[0]?.val, \"one\");\n equal(rows[1]?.val, \"two\");\n db.close();\n});\n\ntest(\"TxRunner \u5355\u8FDE\u63A5: run \u4E0E\u4EA4\u4E92\u4F1A\u8BDD\u5171\u7528\u4E8B\u52A1\u961F\u5217\", async () => {\n const { DatabaseSync } = await import(\"node:sqlite\");\n const { createQuery } = await import(\"./lib/sqlite.js\");\n const { SchemaRegistry } = await import(\"./schema-registry.js\");\n const { TxRunner } = await import(\"./tx-runner.js\");\n\n const db = new DatabaseSync(\":memory:\");\n const query = createQuery(db);\n const schema = new SchemaRegistry(db);\n schema.define(\"feature-demo\", {\n name: \"queue_items\",\n columns: {\n id: { type: \"text\", primary: true },\n val: { type: \"text\", notNull: true },\n },\n softDelete: false,\n });\n\n const enabled = new Map([\n [\n \"feature-demo\",\n {\n id: \"feature-demo\",\n version: \"1.0.0\",\n permissions: [\"db:read:queue_items\", \"db:write:queue_items\"],\n services: { provides: [], requires: [] },\n db: { tables: [] },\n config: { key: \"demo\" },\n } as unknown as import(\"./manifest-loader.js\").ModuleManifestV2,\n ],\n ]);\n\n const runner = new TxRunner({\n db,\n query,\n schema,\n serviceRegistry: new ServiceRegistry(),\n enabled,\n });\n\n const session = await runner.beginSession(\"feature-demo\");\n equal(session.ok, true);\n if (!session.ok) return;\n\n let runFinished = false;\n const queuedRun = runner\n .run({\n moduleId: \"feature-demo\",\n steps: [{ op: \"query\", table: \"queue_items\" }],\n })\n .then((result) => {\n runFinished = true;\n return result;\n });\n equal(runFinished, false);\n\n equal(runner.commitSession(session.txId, \"feature-demo\").ok, true);\n equal((await queuedRun).ok, true);\n equal(runFinished, true);\n\n const running = runner.run({\n moduleId: \"feature-demo\",\n steps: [{ op: \"query\", table: \"queue_items\" }],\n });\n let sessionStarted = false;\n const queuedSession = runner.beginSession(\"feature-demo\").then((result) => {\n sessionStarted = true;\n return result;\n });\n equal(sessionStarted, false);\n equal((await running).ok, true);\n\n const nextSession = await queuedSession;\n equal(nextSession.ok, true);\n equal(sessionStarted, true);\n if (nextSession.ok) equal(runner.rollbackSession(nextSession.txId, \"feature-demo\").ok, true);\n\n db.close();\n});\n"],
5
- "mappings": "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",
6
- "names": []
7
- }