@sfmc-bds/db-server 0.1.0 → 0.2.0-beta.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 (112) hide show
  1. package/README.md +1 -1
  2. package/dist/db-tables.js +16 -17
  3. package/dist/db-tables.js.map +7 -1
  4. package/dist/domain/bridge.js +54 -77
  5. package/dist/domain/bridge.js.map +7 -1
  6. package/dist/domain/economy.d.ts +83 -2
  7. package/dist/domain/economy.d.ts.map +1 -1
  8. package/dist/domain/economy.js +292 -281
  9. package/dist/domain/economy.js.map +7 -1
  10. package/dist/domain/schema.js +480 -426
  11. package/dist/domain/schema.js.map +7 -1
  12. package/dist/domain/transaction.js +32 -80
  13. package/dist/domain/transaction.js.map +7 -1
  14. package/dist/env.d.ts.map +1 -1
  15. package/dist/env.js +85 -84
  16. package/dist/env.js.map +7 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +218 -240
  20. package/dist/index.js.map +7 -1
  21. package/dist/lib/http.js +30 -39
  22. package/dist/lib/http.js.map +7 -1
  23. package/dist/lib/idempotency-store.js +34 -47
  24. package/dist/lib/idempotency-store.js.map +7 -1
  25. package/dist/lib/idempotency.js +8 -13
  26. package/dist/lib/idempotency.js.map +7 -1
  27. package/dist/lib/identifiers.js +18 -14
  28. package/dist/lib/identifiers.js.map +7 -1
  29. package/dist/lib/log.d.ts +3 -6
  30. package/dist/lib/log.d.ts.map +1 -1
  31. package/dist/lib/log.js +13 -14
  32. package/dist/lib/log.js.map +7 -1
  33. package/dist/lib/module-state.d.ts.map +1 -1
  34. package/dist/lib/module-state.js +32 -21
  35. package/dist/lib/module-state.js.map +7 -1
  36. package/dist/lib/order-by.d.ts +17 -0
  37. package/dist/lib/order-by.d.ts.map +1 -0
  38. package/dist/lib/order-by.js +24 -0
  39. package/dist/lib/order-by.js.map +7 -0
  40. package/dist/lib/runtime.js +16 -31
  41. package/dist/lib/runtime.js.map +7 -1
  42. package/dist/lib/sql-helpers.js +9 -27
  43. package/dist/lib/sql-helpers.js.map +7 -1
  44. package/dist/lib/sqlite.js +40 -52
  45. package/dist/lib/sqlite.js.map +7 -1
  46. package/dist/manifest-loader.d.ts.map +1 -1
  47. package/dist/manifest-loader.js +154 -195
  48. package/dist/manifest-loader.js.map +7 -1
  49. package/dist/manifest.d.ts +3 -7
  50. package/dist/manifest.d.ts.map +1 -1
  51. package/dist/manifest.js +76 -115
  52. package/dist/manifest.js.map +7 -1
  53. package/dist/module-auth.d.ts +17 -6
  54. package/dist/module-auth.d.ts.map +1 -1
  55. package/dist/module-auth.js +93 -107
  56. package/dist/module-auth.js.map +7 -1
  57. package/dist/module-runtime-sync.d.ts +37 -0
  58. package/dist/module-runtime-sync.d.ts.map +1 -0
  59. package/dist/module-runtime-sync.js +54 -0
  60. package/dist/module-runtime-sync.js.map +7 -0
  61. package/dist/permission-gate.d.ts.map +1 -1
  62. package/dist/permission-gate.js +55 -86
  63. package/dist/permission-gate.js.map +7 -1
  64. package/dist/routes/_shared.d.ts +7 -2
  65. package/dist/routes/_shared.d.ts.map +1 -1
  66. package/dist/routes/_shared.js +16 -25
  67. package/dist/routes/_shared.js.map +7 -1
  68. package/dist/routes/config.d.ts +11 -1
  69. package/dist/routes/config.d.ts.map +1 -1
  70. package/dist/routes/config.js +167 -213
  71. package/dist/routes/config.js.map +7 -1
  72. package/dist/routes/db-routes.d.ts +6 -10
  73. package/dist/routes/db-routes.d.ts.map +1 -1
  74. package/dist/routes/db-routes.js +198 -172
  75. package/dist/routes/db-routes.js.map +7 -1
  76. package/dist/routes/health.js +15 -20
  77. package/dist/routes/health.js.map +7 -1
  78. package/dist/routes/messages.d.ts.map +1 -1
  79. package/dist/routes/messages.js +56 -63
  80. package/dist/routes/messages.js.map +7 -1
  81. package/dist/routes/module-config-routes.d.ts.map +1 -1
  82. package/dist/routes/module-config-routes.js +92 -111
  83. package/dist/routes/module-config-routes.js.map +7 -1
  84. package/dist/routes/modules.d.ts.map +1 -1
  85. package/dist/routes/modules.js +82 -88
  86. package/dist/routes/modules.js.map +7 -1
  87. package/dist/routes/service-routes.d.ts.map +1 -1
  88. package/dist/routes/service-routes.js +54 -61
  89. package/dist/routes/service-routes.js.map +7 -1
  90. package/dist/runtime.test.js +248 -49
  91. package/dist/runtime.test.js.map +7 -1
  92. package/dist/schema-registry.d.ts.map +1 -1
  93. package/dist/schema-registry.js +119 -160
  94. package/dist/schema-registry.js.map +7 -1
  95. package/dist/server.js +69 -72
  96. package/dist/server.js.map +7 -1
  97. package/dist/service-registry.d.ts.map +1 -1
  98. package/dist/service-registry.js +60 -67
  99. package/dist/service-registry.js.map +7 -1
  100. package/dist/services/builtin-handlers.d.ts +4 -0
  101. package/dist/services/builtin-handlers.d.ts.map +1 -1
  102. package/dist/services/builtin-handlers.js +34 -20
  103. package/dist/services/builtin-handlers.js.map +7 -1
  104. package/dist/services/economy-handlers.js +143 -132
  105. package/dist/services/economy-handlers.js.map +7 -1
  106. package/dist/tx-runner.d.ts +35 -11
  107. package/dist/tx-runner.d.ts.map +1 -1
  108. package/dist/tx-runner.js +293 -250
  109. package/dist/tx-runner.js.map +7 -1
  110. package/dist/where.js +71 -94
  111. package/dist/where.js.map +7 -1
  112. package/package.json +4 -4
@@ -1,73 +1,66 @@
1
- /**
2
- * service-registry.ts 跨模块 service.get 后端
3
- *
4
- * 协议:
5
- * HTTP GET /api/sfmc/services/<name>?input=<urlencoded-json>
6
- * 鉴权:Bearer module_token + ?moduleId=<callerId>
7
- *
8
- * 派发:
9
- * handler 注册在 db-server 进程内存。外层 db.tx 内的 tx.call 会注入
10
- * ctx.tx = { query, db },handler 不得再 BEGIN(方案 A)。
11
- */
12
- export class ServiceRegistry {
13
- handlers = new Map();
14
- /** 提供方在 db-server 启动期注册 handler */
15
- registerHandler(moduleId, name, handle) {
16
- if (this.handlers.has(name)) {
17
- throw new Error(`[service] "${name}" 已被 ${this.handlers.get(name)?.moduleId} 注册,${moduleId} 抢注`);
18
- }
19
- this.handlers.set(name, { moduleId, handle });
1
+ class ServiceRegistry {
2
+ handlers = /* @__PURE__ */ new Map();
3
+ /** 提供方在 db-server 启动期注册 handler */
4
+ registerHandler(moduleId, name, handle) {
5
+ if (this.handlers.has(name)) {
6
+ throw new Error(`[service] "${name}" \u5DF2\u88AB ${this.handlers.get(name)?.moduleId} \u6CE8\u518C,${moduleId} \u62A2\u6CE8`);
20
7
  }
21
- unregisterHandler(name) {
22
- this.handlers.delete(name);
8
+ this.handlers.set(name, { moduleId, handle });
9
+ }
10
+ unregisterHandler(name) {
11
+ this.handlers.delete(name);
12
+ }
13
+ list() {
14
+ return [...this.handlers.entries()].map(([name, h]) => ({ name, moduleId: h.moduleId }));
15
+ }
16
+ async dispatch(enabled, callerModuleId, name, payload, tx) {
17
+ const handler = this.handlers.get(name);
18
+ if (!handler) {
19
+ throw new DispatchError(`service "${name}" \u672A\u6CE8\u518C`, "no_such_service", 404);
23
20
  }
24
- list() {
25
- return [...this.handlers.entries()].map(([name, h]) => ({ name, moduleId: h.moduleId }));
21
+ if (!enabled.has(handler.moduleId)) {
22
+ throw new DispatchError(`service "${name}" \u63D0\u4F9B\u65B9 ${handler.moduleId} \u672A enabled`, "forbidden", 403);
26
23
  }
27
- async dispatch(enabled, callerModuleId, name, payload, tx) {
28
- const handler = this.handlers.get(name);
29
- if (!handler) {
30
- throw new DispatchError(`service "${name}" 未注册`, "no_such_service", 404);
31
- }
32
- if (!enabled.has(handler.moduleId)) {
33
- throw new DispatchError(`service "${name}" 提供方 ${handler.moduleId} 未 enabled`, "forbidden", 403);
34
- }
35
- const caller = enabled.get(callerModuleId);
36
- if (!caller) {
37
- throw new DispatchError(`调用方 ${callerModuleId} 未 enabled`, "forbidden", 403);
38
- }
39
- const declared = caller.services.requires.find((r) => r.name === name);
40
- // 提供方调自己的 service 免 requires(例如 economy 白皮书调 stats.monthly)
41
- if (!declared && callerModuleId !== handler.moduleId) {
42
- throw new DispatchError(`${callerModuleId} 的 manifest.services.requires 未声明 "${name}"`, "not_in_requires", 403);
43
- }
44
- try {
45
- const result = await handler.handle({
46
- callerModuleId,
47
- payload,
48
- ...(tx ? { tx } : {}),
49
- });
50
- return { ok: true, result };
51
- }
52
- catch (e) {
53
- // 保留 handler 抛出的领域/鉴权错误契约,勿压成 500 internal(LSP)
54
- if (e instanceof DispatchError)
55
- throw e;
56
- const err = e;
57
- if (typeof err.status === "number" && err.code) {
58
- throw new DispatchError(err.message, err.code, err.status);
59
- }
60
- throw new DispatchError(`handler 抛错: ${err.message}`, "internal", 500);
61
- }
24
+ const caller = enabled.get(callerModuleId);
25
+ if (!caller) {
26
+ throw new DispatchError(`\u8C03\u7528\u65B9 ${callerModuleId} \u672A enabled`, "forbidden", 403);
62
27
  }
63
- }
64
- export class DispatchError extends Error {
65
- code;
66
- status;
67
- constructor(message, code, status) {
68
- super(message);
69
- this.code = code;
70
- this.status = status;
28
+ const declared = caller.services.requires.find((r) => r.name === name);
29
+ if (!declared && callerModuleId !== handler.moduleId) {
30
+ throw new DispatchError(
31
+ `${callerModuleId} \u7684 manifest.services.requires \u672A\u58F0\u660E "${name}"`,
32
+ "not_in_requires",
33
+ 403
34
+ );
35
+ }
36
+ try {
37
+ const result = await handler.handle({
38
+ callerModuleId,
39
+ payload,
40
+ ...tx ? { tx } : {}
41
+ });
42
+ return { ok: true, result };
43
+ } catch (e) {
44
+ if (e instanceof DispatchError) throw e;
45
+ const err = e;
46
+ if (typeof err.status === "number" && err.code) {
47
+ throw new DispatchError(err.message, err.code, err.status);
48
+ }
49
+ throw new DispatchError(`handler \u629B\u9519: ${err.message}`, "internal", 500);
71
50
  }
51
+ }
52
+ }
53
+ class DispatchError extends Error {
54
+ code;
55
+ status;
56
+ constructor(message, code, status) {
57
+ super(message);
58
+ this.code = code;
59
+ this.status = status;
60
+ }
72
61
  }
73
- //# sourceMappingURL=service-registry.js.map
62
+ export {
63
+ DispatchError,
64
+ ServiceRegistry
65
+ };
66
+ //# sourceMappingURL=service-registry.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"service-registry.js","sourceRoot":"","sources":["../src/service-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA8BH,MAAM,OAAO,eAAe;IACT,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEjE,mCAAmC;IACnC,eAAe,CAAC,QAAgB,EAAE,IAAY,EAAE,MAAsB;QACpE,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,OAAO,QAAQ,KAAK,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,iBAAiB,CAAC,IAAY;QAC5B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,OAAsC,EACtC,cAAsB,EACtB,IAAY,EACZ,OAAgB,EAChB,EAAqB;QAErB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CAAC,YAAY,IAAI,OAAO,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CAAC,YAAY,IAAI,SAAS,OAAO,CAAC,QAAQ,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,aAAa,CAAC,OAAO,cAAc,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACvE,4DAA4D;QAC5D,IAAI,CAAC,QAAQ,IAAI,cAAc,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,aAAa,CACrB,GAAG,cAAc,sCAAsC,IAAI,GAAG,EAC9D,iBAAiB,EACjB,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;gBAClC,cAAc;gBACd,OAAO;gBACP,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtB,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,gDAAgD;YAChD,IAAI,CAAC,YAAY,aAAa;gBAAE,MAAM,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,CAA+C,CAAC;YAC5D,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC/C,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAA6B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YACtF,CAAC;YACD,MAAM,IAAI,aAAa,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;CAEF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,IAAI,CAAoF;IACxF,MAAM,CAAS;IACf,YACE,OAAe,EACf,IAAuF,EACvF,MAAc;QAEd,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/service-registry.ts"],
4
+ "sourcesContent": ["/**\n * service-registry.ts \u2014 \u8DE8\u6A21\u5757 service.get \u540E\u7AEF\n *\n * \u534F\u8BAE:\n * HTTP GET /api/sfmc/services/<name>?input=<urlencoded-json>\n * \u9274\u6743:Bearer module_token + ?moduleId=<callerId>\n *\n * \u6D3E\u53D1:\n * handler \u6CE8\u518C\u5728 db-server \u8FDB\u7A0B\u5185\u5B58\u3002\u5916\u5C42 db.tx \u5185\u7684 tx.call \u4F1A\u6CE8\u5165\n * ctx.tx = { query, db },handler \u4E0D\u5F97\u518D BEGIN(\u65B9\u6848 A)\u3002\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { ModuleManifestV2 } from \"./manifest-loader.js\";\nimport type { QueryFn } from \"./lib/sqlite.js\";\n\nexport interface ServiceCallResult {\n ok: true;\n result: unknown;\n}\n\nexport interface ServiceTxContext {\n query: QueryFn;\n db: DatabaseSync;\n}\n\nexport interface ServiceDispatchContext {\n callerModuleId: string;\n payload: unknown;\n /** \u5916\u5C42 db.tx \u5DF2\u6253\u5F00\u65F6\u6CE8\u5165;handler \u590D\u7528\u8FDE\u63A5,\u7981\u6B62\u5D4C\u5957 BEGIN */\n tx?: ServiceTxContext;\n}\n\nexport type ServiceHandler = (ctx: ServiceDispatchContext) => Promise<unknown>;\n\ninterface RegisteredHandler {\n moduleId: string;\n handle: ServiceHandler;\n}\n\nexport class ServiceRegistry {\n private readonly handlers = new Map<string, RegisteredHandler>();\n\n /** \u63D0\u4F9B\u65B9\u5728 db-server \u542F\u52A8\u671F\u6CE8\u518C handler */\n registerHandler(moduleId: string, name: string, handle: ServiceHandler): void {\n if (this.handlers.has(name)) {\n throw new Error(`[service] \"${name}\" \u5DF2\u88AB ${this.handlers.get(name)?.moduleId} \u6CE8\u518C,${moduleId} \u62A2\u6CE8`);\n }\n this.handlers.set(name, { moduleId, handle });\n }\n\n unregisterHandler(name: string): void {\n this.handlers.delete(name);\n }\n\n list(): Array<{ name: string; moduleId: string }> {\n return [...this.handlers.entries()].map(([name, h]) => ({ name, moduleId: h.moduleId }));\n }\n\n async dispatch(\n enabled: Map<string, ModuleManifestV2>,\n callerModuleId: string,\n name: string,\n payload: unknown,\n tx?: ServiceTxContext\n ): Promise<ServiceCallResult> {\n const handler = this.handlers.get(name);\n if (!handler) {\n throw new DispatchError(`service \"${name}\" \u672A\u6CE8\u518C`, \"no_such_service\", 404);\n }\n if (!enabled.has(handler.moduleId)) {\n throw new DispatchError(`service \"${name}\" \u63D0\u4F9B\u65B9 ${handler.moduleId} \u672A enabled`, \"forbidden\", 403);\n }\n const caller = enabled.get(callerModuleId);\n if (!caller) {\n throw new DispatchError(`\u8C03\u7528\u65B9 ${callerModuleId} \u672A enabled`, \"forbidden\", 403);\n }\n const declared = caller.services.requires.find((r) => r.name === name);\n // \u63D0\u4F9B\u65B9\u8C03\u81EA\u5DF1\u7684 service \u514D requires(\u4F8B\u5982 economy \u767D\u76AE\u4E66\u8C03 stats.monthly)\n if (!declared && callerModuleId !== handler.moduleId) {\n throw new DispatchError(\n `${callerModuleId} \u7684 manifest.services.requires \u672A\u58F0\u660E \"${name}\"`,\n \"not_in_requires\",\n 403\n );\n }\n try {\n const result = await handler.handle({\n callerModuleId,\n payload,\n ...(tx ? { tx } : {}),\n });\n return { ok: true, result };\n } catch (e) {\n // \u4FDD\u7559 handler \u629B\u51FA\u7684\u9886\u57DF/\u9274\u6743\u9519\u8BEF\u5951\u7EA6,\u52FF\u538B\u6210 500 internal(LSP)\n if (e instanceof DispatchError) throw e;\n const err = e as Error & { code?: string; status?: number };\n if (typeof err.status === \"number\" && err.code) {\n throw new DispatchError(err.message, err.code as DispatchError[\"code\"], err.status);\n }\n throw new DispatchError(`handler \u629B\u9519: ${err.message}`, \"internal\", 500);\n }\n }\n\n}\n\nexport class DispatchError extends Error {\n code: \"no_such_service\" | \"not_in_requires\" | \"forbidden\" | \"internal\" | \"domain_error\";\n status: number;\n constructor(\n message: string,\n code: \"no_such_service\" | \"not_in_requires\" | \"forbidden\" | \"internal\" | \"domain_error\",\n status: number\n ) {\n super(message);\n this.code = code;\n this.status = status;\n }\n}\n"],
5
+ "mappings": "AAwCO,MAAM,gBAAgB;AAAA,EACV,WAAW,oBAAI,IAA+B;AAAA;AAAA,EAG/D,gBAAgB,UAAkB,MAAc,QAA8B;AAC5E,QAAI,KAAK,SAAS,IAAI,IAAI,GAAG;AAC3B,YAAM,IAAI,MAAM,cAAc,IAAI,kBAAQ,KAAK,SAAS,IAAI,IAAI,GAAG,QAAQ,iBAAO,QAAQ,eAAK;AAAA,IACjG;AACA,SAAK,SAAS,IAAI,MAAM,EAAE,UAAU,OAAO,CAAC;AAAA,EAC9C;AAAA,EAEA,kBAAkB,MAAoB;AACpC,SAAK,SAAS,OAAO,IAAI;AAAA,EAC3B;AAAA,EAEA,OAAkD;AAChD,WAAO,CAAC,GAAG,KAAK,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,UAAU,EAAE,SAAS,EAAE;AAAA,EACzF;AAAA,EAEA,MAAM,SACJ,SACA,gBACA,MACA,SACA,IAC4B;AAC5B,UAAM,UAAU,KAAK,SAAS,IAAI,IAAI;AACtC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,cAAc,YAAY,IAAI,wBAAS,mBAAmB,GAAG;AAAA,IACzE;AACA,QAAI,CAAC,QAAQ,IAAI,QAAQ,QAAQ,GAAG;AAClC,YAAM,IAAI,cAAc,YAAY,IAAI,wBAAS,QAAQ,QAAQ,mBAAc,aAAa,GAAG;AAAA,IACjG;AACA,UAAM,SAAS,QAAQ,IAAI,cAAc;AACzC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,cAAc,sBAAO,cAAc,mBAAc,aAAa,GAAG;AAAA,IAC7E;AACA,UAAM,WAAW,OAAO,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAErE,QAAI,CAAC,YAAY,mBAAmB,QAAQ,UAAU;AACpD,YAAM,IAAI;AAAA,QACR,GAAG,cAAc,0DAAsC,IAAI;AAAA,QAC3D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,OAAO;AAAA,QAClC;AAAA,QACA;AAAA,QACA,GAAI,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,MACrB,CAAC;AACD,aAAO,EAAE,IAAI,MAAM,OAAO;AAAA,IAC5B,SAAS,GAAG;AAEV,UAAI,aAAa,cAAe,OAAM;AACtC,YAAM,MAAM;AACZ,UAAI,OAAO,IAAI,WAAW,YAAY,IAAI,MAAM;AAC9C,cAAM,IAAI,cAAc,IAAI,SAAS,IAAI,MAA+B,IAAI,MAAM;AAAA,MACpF;AACA,YAAM,IAAI,cAAc,yBAAe,IAAI,OAAO,IAAI,YAAY,GAAG;AAAA,IACvE;AAAA,EACF;AAEF;AAEO,MAAM,sBAAsB,MAAM;AAAA,EACvC;AAAA,EACA;AAAA,EACA,YACE,SACA,MACA,QACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;",
6
+ "names": []
7
+ }
@@ -19,4 +19,8 @@ export type BuiltinServicePlugin = {
19
19
  export declare const BUILTIN_SERVICE_PLUGINS: BuiltinServicePlugin[];
20
20
  /** 按 enabledSet 注册内置插件,返回已注册插件数 */
21
21
  export declare function registerEnabledBuiltinServices(registry: ServiceRegistry, deps: BuiltinServiceDeps, enabledSet: Set<string>): number;
22
+ /** 热启用:只注册单个内置插件(若尚未注册) — 以 registry.moduleId 为权威,勿硬编码 service 名(DRY) */
23
+ export declare function registerBuiltinPluginForModule(registry: ServiceRegistry, deps: BuiltinServiceDeps, moduleId: string): boolean;
24
+ /** 热禁用:按 moduleId 卸掉该模块全部 handler(勿维护 serviceNames 副本 — DRY/OCP) */
25
+ export declare function unregisterBuiltinPluginForModule(registry: ServiceRegistry, moduleId: string): number;
22
26
  //# sourceMappingURL=builtin-handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builtin-handlers.d.ts","sourceRoot":"","sources":["../../src/services/builtin-handlers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,MAAM,kBAAkB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,8BAA8B;AAC9B,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAEzD,CAAC;AAEF,mCAAmC;AACnC,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,kBAAkB,EACxB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,CAQR"}
1
+ {"version":3,"file":"builtin-handlers.d.ts","sourceRoot":"","sources":["../../src/services/builtin-handlers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,MAAM,kBAAkB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,8BAA8B;AAC9B,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAEzD,CAAC;AAEF,mCAAmC;AACnC,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,kBAAkB,EACxB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,CAQR;AAED,yEAAyE;AACzE,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAOT;AAED,oEAAoE;AACpE,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQpG"}
@@ -1,23 +1,37 @@
1
- /**
2
- * services/builtin-handlers.ts — 进程内置 service 插件注册表
3
- *
4
- * 新增内置 handler 只追加 BUILTIN_SERVICE_PLUGINS(OCP),
5
- * 勿在 index.ts 再写 if (enabledSet.has(...)) registerXxx 链。
6
- */
7
1
  import { registerEconomyHandlers } from "./economy-handlers.js";
8
- /** 内置 service 插件清单 — 唯一扩展点 */
9
- export const BUILTIN_SERVICE_PLUGINS = [
10
- { moduleId: "feature-economy", register: registerEconomyHandlers },
2
+ const BUILTIN_SERVICE_PLUGINS = [
3
+ { moduleId: "feature-economy", register: registerEconomyHandlers }
11
4
  ];
12
- /** enabledSet 注册内置插件,返回已注册插件数 */
13
- export function registerEnabledBuiltinServices(registry, deps, enabledSet) {
14
- let n = 0;
15
- for (const plugin of BUILTIN_SERVICE_PLUGINS) {
16
- if (!enabledSet.has(plugin.moduleId))
17
- continue;
18
- plugin.register(registry, deps);
19
- n += 1;
20
- }
21
- return n;
5
+ function registerEnabledBuiltinServices(registry, deps, enabledSet) {
6
+ let n = 0;
7
+ for (const plugin of BUILTIN_SERVICE_PLUGINS) {
8
+ if (!enabledSet.has(plugin.moduleId)) continue;
9
+ plugin.register(registry, deps);
10
+ n += 1;
11
+ }
12
+ return n;
22
13
  }
23
- //# sourceMappingURL=builtin-handlers.js.map
14
+ function registerBuiltinPluginForModule(registry, deps, moduleId) {
15
+ const plugin = BUILTIN_SERVICE_PLUGINS.find((p) => p.moduleId === moduleId);
16
+ if (!plugin) return false;
17
+ const already = registry.list().some((h) => h.moduleId === moduleId);
18
+ if (already) return false;
19
+ plugin.register(registry, deps);
20
+ return true;
21
+ }
22
+ function unregisterBuiltinPluginForModule(registry, moduleId) {
23
+ let n = 0;
24
+ for (const h of registry.list()) {
25
+ if (h.moduleId !== moduleId) continue;
26
+ registry.unregisterHandler(h.name);
27
+ n += 1;
28
+ }
29
+ return n;
30
+ }
31
+ export {
32
+ BUILTIN_SERVICE_PLUGINS,
33
+ registerBuiltinPluginForModule,
34
+ registerEnabledBuiltinServices,
35
+ unregisterBuiltinPluginForModule
36
+ };
37
+ //# sourceMappingURL=builtin-handlers.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"builtin-handlers.js","sourceRoot":"","sources":["../../src/services/builtin-handlers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAShE,8BAA8B;AAC9B,MAAM,CAAC,MAAM,uBAAuB,GAA2B;IAC7D,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,uBAAuB,EAAE;CACnE,CAAC;AAEF,mCAAmC;AACnC,MAAM,UAAU,8BAA8B,CAC5C,QAAyB,EACzB,IAAwB,EACxB,UAAuB;IAEvB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,MAAM,IAAI,uBAAuB,EAAE,CAAC;QAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,SAAS;QAC/C,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/services/builtin-handlers.ts"],
4
+ "sourcesContent": ["/**\n * services/builtin-handlers.ts \u2014 \u8FDB\u7A0B\u5185\u7F6E service \u63D2\u4EF6\u6CE8\u518C\u8868\n *\n * \u65B0\u589E\u5185\u7F6E handler \u53EA\u8FFD\u52A0 BUILTIN_SERVICE_PLUGINS(OCP),\n * \u52FF\u5728 index.ts \u518D\u5199 if (enabledSet.has(...)) registerXxx \u94FE\u3002\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { QueryFn } from \"../lib/sqlite.js\";\nimport type { ServiceRegistry } from \"../service-registry.js\";\nimport { registerEconomyHandlers } from \"./economy-handlers.js\";\n\nexport type BuiltinServiceDeps = { query: QueryFn; db: DatabaseSync };\n\nexport type BuiltinServicePlugin = {\n moduleId: string;\n register: (registry: ServiceRegistry, deps: BuiltinServiceDeps) => void;\n};\n\n/** \u5185\u7F6E service \u63D2\u4EF6\u6E05\u5355 \u2014 \u552F\u4E00\u6269\u5C55\u70B9 */\nexport const BUILTIN_SERVICE_PLUGINS: BuiltinServicePlugin[] = [\n { moduleId: \"feature-economy\", register: registerEconomyHandlers },\n];\n\n/** \u6309 enabledSet \u6CE8\u518C\u5185\u7F6E\u63D2\u4EF6,\u8FD4\u56DE\u5DF2\u6CE8\u518C\u63D2\u4EF6\u6570 */\nexport function registerEnabledBuiltinServices(\n registry: ServiceRegistry,\n deps: BuiltinServiceDeps,\n enabledSet: Set<string>\n): number {\n let n = 0;\n for (const plugin of BUILTIN_SERVICE_PLUGINS) {\n if (!enabledSet.has(plugin.moduleId)) continue;\n plugin.register(registry, deps);\n n += 1;\n }\n return n;\n}\n\n/** \u70ED\u542F\u7528:\u53EA\u6CE8\u518C\u5355\u4E2A\u5185\u7F6E\u63D2\u4EF6(\u82E5\u5C1A\u672A\u6CE8\u518C) \u2014 \u4EE5 registry.moduleId \u4E3A\u6743\u5A01,\u52FF\u786C\u7F16\u7801 service \u540D(DRY) */\nexport function registerBuiltinPluginForModule(\n registry: ServiceRegistry,\n deps: BuiltinServiceDeps,\n moduleId: string\n): boolean {\n const plugin = BUILTIN_SERVICE_PLUGINS.find((p) => p.moduleId === moduleId);\n if (!plugin) return false;\n const already = registry.list().some((h) => h.moduleId === moduleId);\n if (already) return false;\n plugin.register(registry, deps);\n return true;\n}\n\n/** \u70ED\u7981\u7528:\u6309 moduleId \u5378\u6389\u8BE5\u6A21\u5757\u5168\u90E8 handler(\u52FF\u7EF4\u62A4 serviceNames \u526F\u672C \u2014 DRY/OCP) */\nexport function unregisterBuiltinPluginForModule(registry: ServiceRegistry, moduleId: string): number {\n let n = 0;\n for (const h of registry.list()) {\n if (h.moduleId !== moduleId) continue;\n registry.unregisterHandler(h.name);\n n += 1;\n }\n return n;\n}\n"],
5
+ "mappings": "AAUA,SAAS,+BAA+B;AAUjC,MAAM,0BAAkD;AAAA,EAC7D,EAAE,UAAU,mBAAmB,UAAU,wBAAwB;AACnE;AAGO,SAAS,+BACd,UACA,MACA,YACQ;AACR,MAAI,IAAI;AACR,aAAW,UAAU,yBAAyB;AAC5C,QAAI,CAAC,WAAW,IAAI,OAAO,QAAQ,EAAG;AACtC,WAAO,SAAS,UAAU,IAAI;AAC9B,SAAK;AAAA,EACP;AACA,SAAO;AACT;AAGO,SAAS,+BACd,UACA,MACA,UACS;AACT,QAAM,SAAS,wBAAwB,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAC1E,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,UAAU,SAAS,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AACnE,MAAI,QAAS,QAAO;AACpB,SAAO,SAAS,UAAU,IAAI;AAC9B,SAAO;AACT;AAGO,SAAS,iCAAiC,UAA2B,UAA0B;AACpG,MAAI,IAAI;AACR,aAAW,KAAK,SAAS,KAAK,GAAG;AAC/B,QAAI,EAAE,aAAa,SAAU;AAC7B,aAAS,kBAAkB,EAAE,IAAI;AACjC,SAAK;AAAA,EACP;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,144 +1,155 @@
1
- /**
2
- * services/economy-handlers.ts — feature-economy 的 7 个 service handler
3
- *
4
- * 全部跑在 db-server 进程内,复用 domain/economy.ts。
5
- * ctx.tx 存在时 alreadyInTx=true,与外层 db.tx 共享同一 SQLite 事务。
6
- */
7
1
  import { DispatchError } from "../service-registry.js";
8
- import { applyEconomyTransaction, getEconomyAccount, listDailyTasks, monthlyEconomyStats, submitDailyTaskTx, } from "../domain/economy.js";
2
+ import {
3
+ applyEconomyTransaction,
4
+ getEconomyAccount,
5
+ listDailyTasks,
6
+ monthlyEconomyStats,
7
+ submitDailyTaskTx
8
+ } from "../domain/economy.js";
9
9
  const MODULE_ID = "feature-economy";
10
10
  function asObj(payload) {
11
- return payload && typeof payload === "object" ? payload : {};
11
+ return payload && typeof payload === "object" ? payload : {};
12
12
  }
13
13
  function str(v, fallback = "") {
14
- return v === undefined || v === null ? fallback : String(v);
14
+ return v === void 0 || v === null ? fallback : String(v);
15
15
  }
16
16
  function num(v) {
17
- return Number(v);
17
+ return Number(v);
18
18
  }
19
- /** 领域失败保留 status/code,避免被 registry 压成 500 internal(LSP) */
20
19
  function unwrapOk(result) {
21
- if (!result.ok) {
22
- throw new DispatchError(result.error, "domain_error", result.status);
23
- }
20
+ if (!result.ok) {
21
+ throw new DispatchError(result.error, "domain_error", result.status);
22
+ }
23
+ return {
24
+ transactionId: result.transactionId,
25
+ replayed: result.replayed ?? false,
26
+ source: result.source,
27
+ target: result.target,
28
+ // 方便调用方读单边余额
29
+ balance: result.target?.balanceAfter ?? result.source?.balanceAfter,
30
+ version: result.target?.version ?? result.source?.version
31
+ };
32
+ }
33
+ function registerEconomyHandlers(registry, deps) {
34
+ const standaloneQuery = deps.query;
35
+ registry.registerHandler(MODULE_ID, "economy.account.get", async (ctx) => {
36
+ const p = asObj(ctx.payload);
37
+ const playerId = str(p.playerId ?? p.player_id);
38
+ if (!playerId) throw new DispatchError("missing_playerId", "domain_error", 400);
39
+ const q = ctx.tx?.query ?? standaloneQuery;
40
+ return getEconomyAccount(q, playerId, str(p.playerName ?? p.player_name));
41
+ });
42
+ registry.registerHandler(MODULE_ID, "economy.account.debit", async (ctx) => {
43
+ const p = asObj(ctx.payload);
44
+ const playerId = str(p.playerId ?? p.player_id ?? p.actorId);
45
+ const amount = num(p.amount);
46
+ if (!playerId) throw new DispatchError("missing_playerId", "domain_error", 400);
47
+ const q = ctx.tx?.query ?? standaloneQuery;
48
+ const db = ctx.tx?.db ?? deps.db;
49
+ const idem = str(p.idempotencyKey ?? p.idempotency_key);
50
+ const result = applyEconomyTransaction(
51
+ q,
52
+ db,
53
+ {
54
+ actorId: playerId,
55
+ sourcePlayerId: playerId,
56
+ sourcePlayerName: str(p.playerName ?? p.player_name),
57
+ amount,
58
+ type: "debit",
59
+ reason: str(p.reason),
60
+ referenceType: str(p.referenceType ?? p.meta?.type),
61
+ referenceId: str(p.referenceId ?? p.meta?.redpacketId),
62
+ ...idem ? { idempotencyKey: idem } : {}
63
+ },
64
+ { alreadyInTx: !!ctx.tx }
65
+ );
66
+ return unwrapOk(result);
67
+ });
68
+ registry.registerHandler(MODULE_ID, "economy.account.credit", async (ctx) => {
69
+ const p = asObj(ctx.payload);
70
+ const playerId = str(p.playerId ?? p.player_id ?? p.actorId);
71
+ const amount = num(p.amount);
72
+ if (!playerId) throw new DispatchError("missing_playerId", "domain_error", 400);
73
+ const q = ctx.tx?.query ?? standaloneQuery;
74
+ const db = ctx.tx?.db ?? deps.db;
75
+ const idem = str(p.idempotencyKey ?? p.idempotency_key);
76
+ const result = applyEconomyTransaction(
77
+ q,
78
+ db,
79
+ {
80
+ actorId: playerId,
81
+ targetPlayerId: playerId,
82
+ targetPlayerName: str(p.playerName ?? p.player_name),
83
+ amount,
84
+ type: "credit",
85
+ reason: str(p.reason),
86
+ referenceType: str(p.referenceType ?? p.meta?.type),
87
+ referenceId: str(p.referenceId ?? p.meta?.redpacketId),
88
+ ...idem ? { idempotencyKey: idem } : {}
89
+ },
90
+ { alreadyInTx: !!ctx.tx }
91
+ );
92
+ return unwrapOk(result);
93
+ });
94
+ registry.registerHandler(MODULE_ID, "economy.account.transfer", async (ctx) => {
95
+ const p = asObj(ctx.payload);
96
+ const from = str(p.fromPlayerId ?? p.sourcePlayerId ?? p.source_player_id ?? p.actorId ?? p.actor_id) || "";
97
+ const to = str(p.toPlayerId ?? p.targetPlayerId ?? p.target_player_id) || "";
98
+ const amount = num(p.amount);
99
+ if (!from || !to) throw new DispatchError("missing_from_or_to", "domain_error", 400);
100
+ const q = ctx.tx?.query ?? standaloneQuery;
101
+ const db = ctx.tx?.db ?? deps.db;
102
+ const idem = str(p.idempotencyKey ?? p.idempotency_key);
103
+ const result = applyEconomyTransaction(
104
+ q,
105
+ db,
106
+ {
107
+ actorId: from,
108
+ sourcePlayerId: from,
109
+ sourcePlayerName: str(p.fromPlayerName ?? p.sourcePlayerName),
110
+ targetPlayerId: to,
111
+ targetPlayerName: str(p.toPlayerName ?? p.targetPlayerName),
112
+ amount,
113
+ type: "transfer",
114
+ reason: str(p.reason),
115
+ ...idem ? { idempotencyKey: idem } : {}
116
+ },
117
+ { alreadyInTx: !!ctx.tx }
118
+ );
119
+ return unwrapOk(result);
120
+ });
121
+ registry.registerHandler(MODULE_ID, "economy.dailyTasks.list", async (ctx) => {
122
+ const p = asObj(ctx.payload);
123
+ const q = ctx.tx?.query ?? standaloneQuery;
24
124
  return {
25
- transactionId: result.transactionId,
26
- replayed: result.replayed ?? false,
27
- source: result.source,
28
- target: result.target,
29
- // 方便调用方读单边余额
30
- balance: result.target?.balanceAfter ?? result.source?.balanceAfter,
31
- version: result.target?.version ?? result.source?.version,
125
+ tasks: listDailyTasks(q, {
126
+ status: str(p.status) || "active",
127
+ includeExpired: Boolean(p.includeExpired)
128
+ })
32
129
  };
130
+ });
131
+ registry.registerHandler(MODULE_ID, "economy.dailyTasks.submit", async (ctx) => {
132
+ const p = asObj(ctx.payload);
133
+ const actorId = str(p.actorId ?? p.playerId ?? p.player_id);
134
+ const taskId = str(p.taskId ?? p.task_id);
135
+ const quantity = num(p.quantity ?? 1);
136
+ if (!actorId || !taskId) {
137
+ return { ok: false, error: "missing_actor_or_task", status: 400 };
138
+ }
139
+ const q = ctx.tx?.query ?? standaloneQuery;
140
+ const db = ctx.tx?.db ?? deps.db;
141
+ const result = submitDailyTaskTx(q, db, { actorId, taskId, quantity }, { alreadyInTx: !!ctx.tx });
142
+ if (!result.ok) {
143
+ return { ok: false, error: result.error, status: result.status };
144
+ }
145
+ return { ok: true, ...result.data };
146
+ });
147
+ registry.registerHandler(MODULE_ID, "economy.stats.monthly", async (ctx) => {
148
+ const q = ctx.tx?.query ?? standaloneQuery;
149
+ return monthlyEconomyStats(q);
150
+ });
33
151
  }
34
- export function registerEconomyHandlers(registry, deps) {
35
- const standaloneQuery = deps.query;
36
- registry.registerHandler(MODULE_ID, "economy.account.get", async (ctx) => {
37
- const p = asObj(ctx.payload);
38
- const playerId = str(p.playerId ?? p.player_id);
39
- if (!playerId)
40
- throw new DispatchError("missing_playerId", "domain_error", 400);
41
- const q = ctx.tx?.query ?? standaloneQuery;
42
- return getEconomyAccount(q, playerId, str(p.playerName ?? p.player_name));
43
- });
44
- registry.registerHandler(MODULE_ID, "economy.account.debit", async (ctx) => {
45
- const p = asObj(ctx.payload);
46
- const playerId = str(p.playerId ?? p.player_id ?? p.actorId);
47
- const amount = num(p.amount);
48
- if (!playerId)
49
- throw new DispatchError("missing_playerId", "domain_error", 400);
50
- const q = ctx.tx?.query ?? standaloneQuery;
51
- const db = ctx.tx?.db ?? deps.db;
52
- const idem = str(p.idempotencyKey ?? p.idempotency_key);
53
- const result = applyEconomyTransaction(q, db, {
54
- actorId: playerId,
55
- sourcePlayerId: playerId,
56
- sourcePlayerName: str(p.playerName ?? p.player_name),
57
- amount,
58
- type: "debit",
59
- reason: str(p.reason),
60
- referenceType: str(p.referenceType ?? p.meta?.type),
61
- referenceId: str(p.referenceId ?? p.meta?.redpacketId),
62
- ...(idem ? { idempotencyKey: idem } : {}),
63
- }, { alreadyInTx: !!ctx.tx });
64
- return unwrapOk(result);
65
- });
66
- registry.registerHandler(MODULE_ID, "economy.account.credit", async (ctx) => {
67
- const p = asObj(ctx.payload);
68
- const playerId = str(p.playerId ?? p.player_id ?? p.actorId);
69
- const amount = num(p.amount);
70
- if (!playerId)
71
- throw new DispatchError("missing_playerId", "domain_error", 400);
72
- const q = ctx.tx?.query ?? standaloneQuery;
73
- const db = ctx.tx?.db ?? deps.db;
74
- const idem = str(p.idempotencyKey ?? p.idempotency_key);
75
- const result = applyEconomyTransaction(q, db, {
76
- actorId: playerId,
77
- targetPlayerId: playerId,
78
- targetPlayerName: str(p.playerName ?? p.player_name),
79
- amount,
80
- type: "credit",
81
- reason: str(p.reason),
82
- referenceType: str(p.referenceType ?? p.meta?.type),
83
- referenceId: str(p.referenceId ?? p.meta?.redpacketId),
84
- ...(idem ? { idempotencyKey: idem } : {}),
85
- }, { alreadyInTx: !!ctx.tx });
86
- return unwrapOk(result);
87
- });
88
- registry.registerHandler(MODULE_ID, "economy.account.transfer", async (ctx) => {
89
- const p = asObj(ctx.payload);
90
- const from = str(p.fromPlayerId ?? p.sourcePlayerId ?? p.source_player_id ?? p.actorId ?? p.actor_id) || "";
91
- const to = str(p.toPlayerId ?? p.targetPlayerId ?? p.target_player_id) || "";
92
- const amount = num(p.amount);
93
- if (!from || !to)
94
- throw new DispatchError("missing_from_or_to", "domain_error", 400);
95
- const q = ctx.tx?.query ?? standaloneQuery;
96
- const db = ctx.tx?.db ?? deps.db;
97
- const idem = str(p.idempotencyKey ?? p.idempotency_key);
98
- const result = applyEconomyTransaction(q, db, {
99
- actorId: from,
100
- sourcePlayerId: from,
101
- sourcePlayerName: str(p.fromPlayerName ?? p.sourcePlayerName),
102
- targetPlayerId: to,
103
- targetPlayerName: str(p.toPlayerName ?? p.targetPlayerName),
104
- amount,
105
- type: "transfer",
106
- reason: str(p.reason),
107
- ...(idem ? { idempotencyKey: idem } : {}),
108
- }, { alreadyInTx: !!ctx.tx });
109
- return unwrapOk(result);
110
- });
111
- // 信封与 daily-task 消费方对齐:{ tasks: [...] }
112
- registry.registerHandler(MODULE_ID, "economy.dailyTasks.list", async (ctx) => {
113
- const p = asObj(ctx.payload);
114
- const q = ctx.tx?.query ?? standaloneQuery;
115
- return {
116
- tasks: listDailyTasks(q, {
117
- status: str(p.status) || "active",
118
- includeExpired: Boolean(p.includeExpired),
119
- }),
120
- };
121
- });
122
- // 信封与 daily-task 消费方对齐:成功/失败都带 ok,业务失败不抛(避免物品已扣却无法走 !ok 退还分支)
123
- registry.registerHandler(MODULE_ID, "economy.dailyTasks.submit", async (ctx) => {
124
- const p = asObj(ctx.payload);
125
- const actorId = str(p.actorId ?? p.playerId ?? p.player_id);
126
- const taskId = str(p.taskId ?? p.task_id);
127
- const quantity = num(p.quantity ?? 1);
128
- if (!actorId || !taskId) {
129
- return { ok: false, error: "missing_actor_or_task", status: 400 };
130
- }
131
- const q = ctx.tx?.query ?? standaloneQuery;
132
- const db = ctx.tx?.db ?? deps.db;
133
- const result = submitDailyTaskTx(q, db, { actorId, taskId, quantity }, { alreadyInTx: !!ctx.tx });
134
- if (!result.ok) {
135
- return { ok: false, error: result.error, status: result.status };
136
- }
137
- return { ok: true, ...result.data };
138
- });
139
- registry.registerHandler(MODULE_ID, "economy.stats.monthly", async (ctx) => {
140
- const q = ctx.tx?.query ?? standaloneQuery;
141
- return monthlyEconomyStats(q);
142
- });
143
- }
144
- //# sourceMappingURL=economy-handlers.js.map
152
+ export {
153
+ registerEconomyHandlers
154
+ };
155
+ //# sourceMappingURL=economy-handlers.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"economy-handlers.js","sourceRoot":"","sources":["../../src/services/economy-handlers.ts"],"names":[],"mappings":"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"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/services/economy-handlers.ts"],
4
+ "sourcesContent": ["/**\n * services/economy-handlers.ts \u2014 feature-economy \u7684 7 \u4E2A service handler\n *\n * \u5168\u90E8\u8DD1\u5728 db-server \u8FDB\u7A0B\u5185,\u590D\u7528 domain/economy.ts\u3002\n * ctx.tx \u5B58\u5728\u65F6 alreadyInTx=true,\u4E0E\u5916\u5C42 db.tx \u5171\u4EAB\u540C\u4E00 SQLite \u4E8B\u52A1\u3002\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { QueryFn } from \"../lib/sqlite.js\";\nimport { DispatchError, type ServiceRegistry } from \"../service-registry.js\";\nimport {\n applyEconomyTransaction,\n getEconomyAccount,\n listDailyTasks,\n monthlyEconomyStats,\n submitDailyTaskTx,\n type AnyQuery,\n type ApplyEconomyResult,\n} from \"../domain/economy.js\";\n\nconst MODULE_ID = \"feature-economy\";\n\nfunction asObj(payload: unknown): Record<string, unknown> {\n return payload && typeof payload === \"object\" ? (payload as Record<string, unknown>) : {};\n}\n\nfunction str(v: unknown, fallback = \"\"): string {\n return v === undefined || v === null ? fallback : String(v);\n}\n\nfunction num(v: unknown): number {\n return Number(v);\n}\n\n/** \u9886\u57DF\u5931\u8D25\u4FDD\u7559 status/code,\u907F\u514D\u88AB registry \u538B\u6210 500 internal(LSP) */\nfunction unwrapOk(result: ApplyEconomyResult): unknown {\n if (!result.ok) {\n throw new DispatchError(result.error, \"domain_error\", result.status);\n }\n return {\n transactionId: result.transactionId,\n replayed: result.replayed ?? false,\n source: result.source,\n target: result.target,\n // \u65B9\u4FBF\u8C03\u7528\u65B9\u8BFB\u5355\u8FB9\u4F59\u989D\n balance: result.target?.balanceAfter ?? result.source?.balanceAfter,\n version: result.target?.version ?? result.source?.version,\n };\n}\n\nexport function registerEconomyHandlers(\n registry: ServiceRegistry,\n deps: { query: QueryFn; db: DatabaseSync }\n): void {\n const standaloneQuery = deps.query as unknown as AnyQuery;\n\n registry.registerHandler(MODULE_ID, \"economy.account.get\", async (ctx) => {\n const p = asObj(ctx.payload);\n const playerId = str(p.playerId ?? p.player_id);\n if (!playerId) throw new DispatchError(\"missing_playerId\", \"domain_error\", 400);\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n return getEconomyAccount(q, playerId, str(p.playerName ?? p.player_name));\n });\n\n registry.registerHandler(MODULE_ID, \"economy.account.debit\", async (ctx) => {\n const p = asObj(ctx.payload);\n const playerId = str(p.playerId ?? p.player_id ?? p.actorId);\n const amount = num(p.amount);\n if (!playerId) throw new DispatchError(\"missing_playerId\", \"domain_error\", 400);\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n const db = ctx.tx?.db ?? deps.db;\n const idem = str(p.idempotencyKey ?? p.idempotency_key);\n const result = applyEconomyTransaction(\n q,\n db,\n {\n actorId: playerId,\n sourcePlayerId: playerId,\n sourcePlayerName: str(p.playerName ?? p.player_name),\n amount,\n type: \"debit\",\n reason: str(p.reason),\n referenceType: str(p.referenceType ?? (p.meta as Record<string, unknown> | undefined)?.type),\n referenceId: str(p.referenceId ?? (p.meta as Record<string, unknown> | undefined)?.redpacketId),\n ...(idem ? { idempotencyKey: idem } : {}),\n },\n { alreadyInTx: !!ctx.tx }\n );\n return unwrapOk(result);\n });\n\n registry.registerHandler(MODULE_ID, \"economy.account.credit\", async (ctx) => {\n const p = asObj(ctx.payload);\n const playerId = str(p.playerId ?? p.player_id ?? p.actorId);\n const amount = num(p.amount);\n if (!playerId) throw new DispatchError(\"missing_playerId\", \"domain_error\", 400);\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n const db = ctx.tx?.db ?? deps.db;\n const idem = str(p.idempotencyKey ?? p.idempotency_key);\n const result = applyEconomyTransaction(\n q,\n db,\n {\n actorId: playerId,\n targetPlayerId: playerId,\n targetPlayerName: str(p.playerName ?? p.player_name),\n amount,\n type: \"credit\",\n reason: str(p.reason),\n referenceType: str(p.referenceType ?? (p.meta as Record<string, unknown> | undefined)?.type),\n referenceId: str(p.referenceId ?? (p.meta as Record<string, unknown> | undefined)?.redpacketId),\n ...(idem ? { idempotencyKey: idem } : {}),\n },\n { alreadyInTx: !!ctx.tx }\n );\n return unwrapOk(result);\n });\n\n registry.registerHandler(MODULE_ID, \"economy.account.transfer\", async (ctx) => {\n const p = asObj(ctx.payload);\n const from =\n str(p.fromPlayerId ?? p.sourcePlayerId ?? p.source_player_id ?? p.actorId ?? p.actor_id) || \"\";\n const to = str(p.toPlayerId ?? p.targetPlayerId ?? p.target_player_id) || \"\";\n const amount = num(p.amount);\n if (!from || !to) throw new DispatchError(\"missing_from_or_to\", \"domain_error\", 400);\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n const db = ctx.tx?.db ?? deps.db;\n const idem = str(p.idempotencyKey ?? p.idempotency_key);\n const result = applyEconomyTransaction(\n q,\n db,\n {\n actorId: from,\n sourcePlayerId: from,\n sourcePlayerName: str(p.fromPlayerName ?? p.sourcePlayerName),\n targetPlayerId: to,\n targetPlayerName: str(p.toPlayerName ?? p.targetPlayerName),\n amount,\n type: \"transfer\",\n reason: str(p.reason),\n ...(idem ? { idempotencyKey: idem } : {}),\n },\n { alreadyInTx: !!ctx.tx }\n );\n return unwrapOk(result);\n });\n\n // \u4FE1\u5C01\u4E0E daily-task \u6D88\u8D39\u65B9\u5BF9\u9F50:{ tasks: [...] }\n registry.registerHandler(MODULE_ID, \"economy.dailyTasks.list\", async (ctx) => {\n const p = asObj(ctx.payload);\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n return {\n tasks: listDailyTasks(q, {\n status: str(p.status) || \"active\",\n includeExpired: Boolean(p.includeExpired),\n }),\n };\n });\n\n // \u4FE1\u5C01\u4E0E daily-task \u6D88\u8D39\u65B9\u5BF9\u9F50:\u6210\u529F/\u5931\u8D25\u90FD\u5E26 ok,\u4E1A\u52A1\u5931\u8D25\u4E0D\u629B(\u907F\u514D\u7269\u54C1\u5DF2\u6263\u5374\u65E0\u6CD5\u8D70 !ok \u9000\u8FD8\u5206\u652F)\n registry.registerHandler(MODULE_ID, \"economy.dailyTasks.submit\", async (ctx) => {\n const p = asObj(ctx.payload);\n const actorId = str(p.actorId ?? p.playerId ?? p.player_id);\n const taskId = str(p.taskId ?? p.task_id);\n const quantity = num(p.quantity ?? 1);\n if (!actorId || !taskId) {\n return { ok: false, error: \"missing_actor_or_task\", status: 400 };\n }\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n const db = ctx.tx?.db ?? deps.db;\n const result = submitDailyTaskTx(q, db, { actorId, taskId, quantity }, { alreadyInTx: !!ctx.tx });\n if (!result.ok) {\n return { ok: false, error: result.error, status: result.status };\n }\n return { ok: true, ...result.data };\n });\n\n registry.registerHandler(MODULE_ID, \"economy.stats.monthly\", async (ctx) => {\n const q = (ctx.tx?.query as unknown as AnyQuery) ?? standaloneQuery;\n return monthlyEconomyStats(q);\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }