@sfmc-bds/db-server 0.2.0-beta.0 → 0.2.0-beta.10
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/LICENSE +663 -0
- package/dist/domain/bridge.d.ts +57 -23
- package/dist/domain/bridge.d.ts.map +1 -1
- package/dist/domain/bridge.js +77 -6
- package/dist/domain/bridge.js.map +2 -2
- package/dist/domain/bridge.test.d.ts +2 -0
- package/dist/domain/bridge.test.d.ts.map +1 -0
- package/dist/domain/bridge.test.js +87 -0
- package/dist/domain/bridge.test.js.map +7 -0
- package/dist/domain/economy.d.ts +38 -7
- package/dist/domain/economy.d.ts.map +1 -1
- package/dist/domain/economy.js.map +2 -2
- package/dist/domain/messages-bridge-filter.test.d.ts +5 -0
- package/dist/domain/messages-bridge-filter.test.d.ts.map +1 -0
- package/dist/domain/messages-bridge-filter.test.js +20 -0
- package/dist/domain/messages-bridge-filter.test.js.map +7 -0
- package/dist/domain/qq-bind-status.test.d.ts +2 -0
- package/dist/domain/qq-bind-status.test.d.ts.map +1 -0
- package/dist/domain/qq-bind-status.test.js +211 -0
- package/dist/domain/qq-bind-status.test.js.map +7 -0
- package/dist/domain/qq-events.d.ts +84 -0
- package/dist/domain/qq-events.d.ts.map +1 -0
- package/dist/domain/qq-events.js +193 -0
- package/dist/domain/qq-events.js.map +7 -0
- package/dist/domain/qq-events.test.d.ts +5 -0
- package/dist/domain/qq-events.test.d.ts.map +1 -0
- package/dist/domain/qq-events.test.js +170 -0
- package/dist/domain/qq-events.test.js.map +7 -0
- package/dist/domain/qq-join.test.d.ts +2 -0
- package/dist/domain/qq-join.test.d.ts.map +1 -0
- package/dist/domain/qq-join.test.js +353 -0
- package/dist/domain/qq-join.test.js.map +7 -0
- package/dist/domain/schema.d.ts +15 -18
- package/dist/domain/schema.d.ts.map +1 -1
- package/dist/domain/schema.js +67 -451
- package/dist/domain/schema.js.map +2 -2
- package/dist/domain/system-status.d.ts +75 -0
- package/dist/domain/system-status.d.ts.map +1 -0
- package/dist/domain/system-status.js +181 -0
- package/dist/domain/system-status.js.map +7 -0
- package/dist/domain/system-status.test.d.ts +5 -0
- package/dist/domain/system-status.test.d.ts.map +1 -0
- package/dist/domain/system-status.test.js +19 -0
- package/dist/domain/system-status.test.js.map +7 -0
- package/dist/domain/transaction.d.ts +5 -4
- package/dist/domain/transaction.d.ts.map +1 -1
- package/dist/domain/transaction.js.map +2 -2
- package/dist/env.d.ts +7 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +57 -9
- package/dist/env.js.map +2 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -19
- package/dist/index.js.map +2 -2
- package/dist/lib/idempotency-store.d.ts +17 -11
- package/dist/lib/idempotency-store.d.ts.map +1 -1
- package/dist/lib/idempotency-store.js.map +2 -2
- package/dist/lib/idempotency.d.ts +3 -4
- package/dist/lib/idempotency.d.ts.map +1 -1
- package/dist/lib/idempotency.js.map +2 -2
- package/dist/lib/log.d.ts.map +1 -1
- package/dist/lib/log.js +3 -6
- package/dist/lib/log.js.map +2 -2
- package/dist/lib/module-state.d.ts +38 -8
- package/dist/lib/module-state.d.ts.map +1 -1
- package/dist/lib/module-state.js.map +2 -2
- package/dist/lib/order-by.d.ts +8 -6
- package/dist/lib/order-by.d.ts.map +1 -1
- package/dist/lib/order-by.js.map +2 -2
- package/dist/lib/sql-helpers.d.ts +25 -13
- package/dist/lib/sql-helpers.d.ts.map +1 -1
- package/dist/lib/sql-helpers.js.map +2 -2
- package/dist/lib/sqlite.d.ts +14 -5
- package/dist/lib/sqlite.d.ts.map +1 -1
- package/dist/lib/sqlite.js.map +2 -2
- package/dist/manifest-loader.d.ts +5 -2
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +16 -6
- package/dist/manifest-loader.js.map +2 -2
- package/dist/manifest.d.ts +1 -2
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +13 -8
- package/dist/manifest.js.map +2 -2
- package/dist/module-auth.d.ts.map +1 -1
- package/dist/module-auth.js +3 -7
- package/dist/module-auth.js.map +2 -2
- package/dist/permission-gate.d.ts.map +1 -1
- package/dist/permission-gate.js +8 -2
- package/dist/permission-gate.js.map +2 -2
- package/dist/project-root.d.ts +6 -0
- package/dist/project-root.d.ts.map +1 -0
- package/dist/project-root.js +9 -0
- package/dist/project-root.js.map +7 -0
- package/dist/routes/_shared.d.ts +14 -5
- package/dist/routes/_shared.d.ts.map +1 -1
- package/dist/routes/_shared.js.map +2 -2
- package/dist/routes/config.d.ts +8 -11
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +17 -23
- package/dist/routes/config.js.map +2 -2
- package/dist/routes/db-routes.d.ts +8 -2
- package/dist/routes/db-routes.d.ts.map +1 -1
- package/dist/routes/db-routes.js +5 -12
- package/dist/routes/db-routes.js.map +2 -2
- package/dist/routes/messages.d.ts +6 -2
- package/dist/routes/messages.d.ts.map +1 -1
- package/dist/routes/messages.js +17 -3
- package/dist/routes/messages.js.map +2 -2
- package/dist/routes/module-config-routes.d.ts +13 -9
- package/dist/routes/module-config-routes.d.ts.map +1 -1
- package/dist/routes/module-config-routes.js.map +2 -2
- package/dist/routes/modules.d.ts +6 -0
- package/dist/routes/modules.d.ts.map +1 -1
- package/dist/routes/modules.js.map +2 -2
- package/dist/routes/qq-bind.d.ts +24 -0
- package/dist/routes/qq-bind.d.ts.map +1 -0
- package/dist/routes/qq-bind.js +179 -0
- package/dist/routes/qq-bind.js.map +7 -0
- package/dist/routes/qq-events.d.ts +20 -0
- package/dist/routes/qq-events.d.ts.map +1 -0
- package/dist/routes/qq-events.js +39 -0
- package/dist/routes/qq-events.js.map +7 -0
- package/dist/routes/qq-join.d.ts +46 -0
- package/dist/routes/qq-join.d.ts.map +1 -0
- package/dist/routes/qq-join.js +277 -0
- package/dist/routes/qq-join.js.map +7 -0
- package/dist/routes/service-routes.d.ts +6 -0
- package/dist/routes/service-routes.d.ts.map +1 -1
- package/dist/routes/service-routes.js.map +2 -2
- package/dist/routes/status.d.ts +19 -0
- package/dist/routes/status.d.ts.map +1 -0
- package/dist/routes/status.js +74 -0
- package/dist/routes/status.js.map +7 -0
- package/dist/runtime.test.js +216 -4
- package/dist/runtime.test.js.map +2 -2
- package/dist/schema-registry.d.ts +17 -16
- package/dist/schema-registry.d.ts.map +1 -1
- package/dist/schema-registry.js +76 -6
- package/dist/schema-registry.js.map +2 -2
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js.map +2 -2
- package/dist/service-registry.d.ts +39 -9
- package/dist/service-registry.d.ts.map +1 -1
- package/dist/service-registry.js +30 -2
- package/dist/service-registry.js.map +2 -2
- package/dist/services/builtin-handlers.d.ts +27 -7
- package/dist/services/builtin-handlers.d.ts.map +1 -1
- package/dist/services/builtin-handlers.js.map +2 -2
- package/dist/tx-runner.d.ts +48 -9
- package/dist/tx-runner.d.ts.map +1 -1
- package/dist/tx-runner.js +99 -27
- package/dist/tx-runner.js.map +2 -2
- package/package.json +26 -24
package/dist/server.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ interface CheckResult {
|
|
|
9
9
|
port: number;
|
|
10
10
|
error?: string;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* 检测指定端口是否冲突可用。
|
|
14
|
+
*
|
|
15
|
+
* @param port 待检测的端口号。
|
|
16
|
+
* @returns 包含端口可用性状态的检测结果对象。
|
|
17
|
+
*/
|
|
12
18
|
export declare function checkPortConflict(port: number): Promise<CheckResult>;
|
|
13
19
|
export type ServerEnv = {
|
|
14
20
|
PORT: number;
|
|
@@ -21,7 +27,20 @@ export interface ServerOptions {
|
|
|
21
27
|
handle: Handler;
|
|
22
28
|
onListening?: (server: http.Server) => void;
|
|
23
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* 创建并配置 db-server 的原生 HTTP 服务实例(集成请求耗时监控与状态码日志)。
|
|
32
|
+
*
|
|
33
|
+
* @param options 服务端启动配置选项。
|
|
34
|
+
* @returns 原生 http.Server 实例。
|
|
35
|
+
*/
|
|
24
36
|
export declare function createServer({ handle, env, onListening }: ServerOptions): http.Server;
|
|
37
|
+
/**
|
|
38
|
+
* 启动交互式控制台 REPL 界面,支持在终端输入 `help`、`status`、`stop` 运维管理指令。
|
|
39
|
+
*
|
|
40
|
+
* @param server HTTP 服务实例。
|
|
41
|
+
* @param db 数据库连接实例。
|
|
42
|
+
* @returns 控制台 Readline 接口对象。
|
|
43
|
+
*/
|
|
25
44
|
export declare function startConsole(server: http.Server, db: DatabaseSync | null): readline.Interface;
|
|
26
45
|
export {};
|
|
27
46
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,UAAU,WAAW;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBpE;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpG,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM,CA2BrF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,IAAI,GAAG,QAAQ,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,UAAU,WAAW;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBpE;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpG,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM,CA2BrF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,IAAI,GAAG,QAAQ,CAAC,SAAS,CA0B7F"}
|
package/dist/server.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/server.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * server.ts \u2014 HTTP \u670D\u52A1 + \u63A7\u5236\u53F0\n */\n\nimport http from \"node:http\";\nimport net from \"node:net\";\nimport readline from \"node:readline\";\nimport type { DatabaseSync } from \"node:sqlite\";\n\nimport { log } from \"./lib/log.js\";\n\ninterface CheckResult {\n ok: boolean;\n port: number;\n error?: string;\n}\n\nexport function checkPortConflict(port: number): Promise<CheckResult> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n const result: { ok: false; port: number; error?: string } = { ok: false, port };\n if (err.code) {\n result.error = err.code;\n }\n resolve(result);\n });\n server.once(\"listening\", () => {\n server.close();\n resolve({ ok: true, port });\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport type ServerEnv = {\n PORT: number;\n HOST: string;\n AUTH_TOKEN?: string;\n};\n\nexport type Handler = (req: http.IncomingMessage, res: http.ServerResponse) => void | Promise<void>;\n\nexport interface ServerOptions {\n env: ServerEnv;\n handle: Handler;\n onListening?: (server: http.Server) => void;\n}\n\nexport function createServer({ handle, env, onListening }: ServerOptions): http.Server {\n const server = http.createServer((req, res) => {\n const startedAt = Date.now();\n let bodyStr = \"\";\n const chunks: Buffer[] = [];\n req.on(\"data\", (c: Buffer) => chunks.push(c));\n req.on(\"end\", () => {\n bodyStr = Buffer.concat(chunks).toString(\"utf-8\").slice(0, 300);\n (req as http.IncomingMessage & { bodyBuffer: string }).bodyBuffer = bodyStr;\n });\n res.once(\"finish\", () => {\n const quietPoll = (req.url ?? \"\").startsWith(\"/api/sfmc/messages?\") && res.statusCode < 400;\n const bodySnippet = req.method === \"GET\" ? \"\" : ` ${bodyStr.slice(0, 200)}`;\n if (!quietPoll)\n log.info(`[HTTP] ${req.method} ${req.url} ${res.statusCode} ${Date.now() - startedAt}ms${bodySnippet}`);\n });\n void handle(req, res);\n });\n\n server.listen(env.PORT, env.HOST, () => {\n log.success(`HTTP \u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u7AEF\u53E3 ${env.PORT} (loopback only)`);\n log.info(`API \u5065\u5EB7\u68C0\u67E5: http://${env.HOST}:${env.PORT}/api/health`);\n log.info(`\u9274\u6743: ${env.AUTH_TOKEN ? \"\u5DF2\u542F\u7528 token\" : \"\u672A\u542F\u7528\"}`);\n if (onListening) onListening(server);\n });\n\n return server;\n}\n\nexport function startConsole(server: http.Server, db: DatabaseSync | null): readline.Interface {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n rl.on(\"line\", (line: string) => {\n const cmd = line.trim().toLowerCase();\n if (cmd === \"help\") {\n console.log(\"DB Server \u53EF\u7528\u547D\u4EE4:\");\n console.log(\" help \u2014 \u663E\u793A\u5E2E\u52A9\");\n console.log(\" status \u2014 \u663E\u793A\u670D\u52A1\u72B6\u6001\");\n console.log(\" stop \u2014 \u505C\u6B62\u670D\u52A1\");\n } else if (cmd === \"status\") {\n console.log(`\u72B6\u6001: \u8FD0\u884C\u4E2D`);\n console.log(` HTTP \u7AEF\u53E3: ${(server.address() as { port: number }).port}`);\n console.log(` \u6570\u636E\u5E93: ${db ? \"(\u5DF2\u8FDE\u63A5)\" : \"(\u672A\u8FDE\u63A5)\"}`);\n } else if (cmd === \"stop\") {\n log.info(\"\u6B63\u5728\u505C\u6B62\u670D\u52A1...\");\n rl.close();\n server.close();\n if (db) db.close();\n process.exit(0);\n } else {\n log.warn(`\u672A\u77E5\u547D\u4EE4: ${cmd}\uFF0C\u8F93\u5165 help \u67E5\u770B\u5E2E\u52A9`);\n }\n });\n rl.on(\"SIGINT\", () => process.exit());\n return rl;\n}\n\n"],
|
|
5
|
-
"mappings": "AAIA,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,cAAc;AAGrB,SAAS,WAAW;
|
|
4
|
+
"sourcesContent": ["/**\n * server.ts \u2014 HTTP \u670D\u52A1 + \u63A7\u5236\u53F0\n */\n\nimport http from \"node:http\";\nimport net from \"node:net\";\nimport readline from \"node:readline\";\nimport type { DatabaseSync } from \"node:sqlite\";\n\nimport { log } from \"./lib/log.js\";\n\ninterface CheckResult {\n ok: boolean;\n port: number;\n error?: string;\n}\n\n/**\n * \u68C0\u6D4B\u6307\u5B9A\u7AEF\u53E3\u662F\u5426\u51B2\u7A81\u53EF\u7528\u3002\n *\n * @param port \u5F85\u68C0\u6D4B\u7684\u7AEF\u53E3\u53F7\u3002\n * @returns \u5305\u542B\u7AEF\u53E3\u53EF\u7528\u6027\u72B6\u6001\u7684\u68C0\u6D4B\u7ED3\u679C\u5BF9\u8C61\u3002\n */\nexport function checkPortConflict(port: number): Promise<CheckResult> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n const result: { ok: false; port: number; error?: string } = { ok: false, port };\n if (err.code) {\n result.error = err.code;\n }\n resolve(result);\n });\n server.once(\"listening\", () => {\n server.close();\n resolve({ ok: true, port });\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport type ServerEnv = {\n PORT: number;\n HOST: string;\n AUTH_TOKEN?: string;\n};\n\nexport type Handler = (req: http.IncomingMessage, res: http.ServerResponse) => void | Promise<void>;\n\nexport interface ServerOptions {\n env: ServerEnv;\n handle: Handler;\n onListening?: (server: http.Server) => void;\n}\n\n/**\n * \u521B\u5EFA\u5E76\u914D\u7F6E db-server \u7684\u539F\u751F HTTP \u670D\u52A1\u5B9E\u4F8B\uFF08\u96C6\u6210\u8BF7\u6C42\u8017\u65F6\u76D1\u63A7\u4E0E\u72B6\u6001\u7801\u65E5\u5FD7\uFF09\u3002\n *\n * @param options \u670D\u52A1\u7AEF\u542F\u52A8\u914D\u7F6E\u9009\u9879\u3002\n * @returns \u539F\u751F http.Server \u5B9E\u4F8B\u3002\n */\nexport function createServer({ handle, env, onListening }: ServerOptions): http.Server {\n const server = http.createServer((req, res) => {\n const startedAt = Date.now();\n let bodyStr = \"\";\n const chunks: Buffer[] = [];\n req.on(\"data\", (c: Buffer) => chunks.push(c));\n req.on(\"end\", () => {\n bodyStr = Buffer.concat(chunks).toString(\"utf-8\").slice(0, 300);\n (req as http.IncomingMessage & { bodyBuffer: string }).bodyBuffer = bodyStr;\n });\n res.once(\"finish\", () => {\n const quietPoll = (req.url ?? \"\").startsWith(\"/api/sfmc/messages?\") && res.statusCode < 400;\n const bodySnippet = req.method === \"GET\" ? \"\" : ` ${bodyStr.slice(0, 200)}`;\n if (!quietPoll)\n log.info(`[HTTP] ${req.method} ${req.url} ${res.statusCode} ${Date.now() - startedAt}ms${bodySnippet}`);\n });\n void handle(req, res);\n });\n\n server.listen(env.PORT, env.HOST, () => {\n log.success(`HTTP \u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u7AEF\u53E3 ${env.PORT} (loopback only)`);\n log.info(`API \u5065\u5EB7\u68C0\u67E5: http://${env.HOST}:${env.PORT}/api/health`);\n log.info(`\u9274\u6743: ${env.AUTH_TOKEN ? \"\u5DF2\u542F\u7528 token\" : \"\u672A\u542F\u7528\"}`);\n if (onListening) onListening(server);\n });\n\n return server;\n}\n\n/**\n * \u542F\u52A8\u4EA4\u4E92\u5F0F\u63A7\u5236\u53F0 REPL \u754C\u9762\uFF0C\u652F\u6301\u5728\u7EC8\u7AEF\u8F93\u5165 `help`\u3001`status`\u3001`stop` \u8FD0\u7EF4\u7BA1\u7406\u6307\u4EE4\u3002\n *\n * @param server HTTP \u670D\u52A1\u5B9E\u4F8B\u3002\n * @param db \u6570\u636E\u5E93\u8FDE\u63A5\u5B9E\u4F8B\u3002\n * @returns \u63A7\u5236\u53F0 Readline \u63A5\u53E3\u5BF9\u8C61\u3002\n */\nexport function startConsole(server: http.Server, db: DatabaseSync | null): readline.Interface {\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n rl.on(\"line\", (line: string) => {\n const cmd = line.trim().toLowerCase();\n if (cmd === \"help\") {\n console.log(\"DB Server \u53EF\u7528\u547D\u4EE4:\");\n console.log(\" help \u2014 \u663E\u793A\u5E2E\u52A9\");\n console.log(\" status \u2014 \u663E\u793A\u670D\u52A1\u72B6\u6001\");\n console.log(\" stop \u2014 \u505C\u6B62\u670D\u52A1\");\n } else if (cmd === \"status\") {\n console.log(`\u72B6\u6001: \u8FD0\u884C\u4E2D`);\n console.log(` HTTP \u7AEF\u53E3: ${(server.address() as { port: number }).port}`);\n console.log(` \u6570\u636E\u5E93: ${db ? \"(\u5DF2\u8FDE\u63A5)\" : \"(\u672A\u8FDE\u63A5)\"}`);\n } else if (cmd === \"stop\") {\n log.info(\"\u6B63\u5728\u505C\u6B62\u670D\u52A1...\");\n rl.close();\n server.close();\n if (db) db.close();\n process.exit(0);\n } else {\n log.warn(`\u672A\u77E5\u547D\u4EE4: ${cmd}\uFF0C\u8F93\u5165 help \u67E5\u770B\u5E2E\u52A9`);\n }\n });\n rl.on(\"SIGINT\", () => process.exit());\n return rl;\n}\n\n"],
|
|
5
|
+
"mappings": "AAIA,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,cAAc;AAGrB,SAAS,WAAW;AAcb,SAAS,kBAAkB,MAAoC;AACpE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAS,IAAI,aAAa;AAChC,WAAO,KAAK,SAAS,CAAC,QAA+B;AACnD,YAAM,SAAsD,EAAE,IAAI,OAAO,KAAK;AAC9E,UAAI,IAAI,MAAM;AACZ,eAAO,QAAQ,IAAI;AAAA,MACrB;AACA,cAAQ,MAAM;AAAA,IAChB,CAAC;AACD,WAAO,KAAK,aAAa,MAAM;AAC7B,aAAO,MAAM;AACb,cAAQ,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IAC5B,CAAC;AACD,WAAO,OAAO,MAAM,WAAW;AAAA,EACjC,CAAC;AACH;AAsBO,SAAS,aAAa,EAAE,QAAQ,KAAK,YAAY,GAA+B;AACrF,QAAM,SAAS,KAAK,aAAa,CAAC,KAAK,QAAQ;AAC7C,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,UAAU;AACd,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AAC5C,QAAI,GAAG,OAAO,MAAM;AAClB,gBAAU,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,EAAE,MAAM,GAAG,GAAG;AAC9D,MAAC,IAAsD,aAAa;AAAA,IACtE,CAAC;AACD,QAAI,KAAK,UAAU,MAAM;AACvB,YAAM,aAAa,IAAI,OAAO,IAAI,WAAW,qBAAqB,KAAK,IAAI,aAAa;AACxF,YAAM,cAAc,IAAI,WAAW,QAAQ,KAAK,IAAI,QAAQ,MAAM,GAAG,GAAG,CAAC;AACzE,UAAI,CAAC;AACH,YAAI,KAAK,UAAU,IAAI,MAAM,IAAI,IAAI,GAAG,IAAI,IAAI,UAAU,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,WAAW,EAAE;AAAA,IAC1G,CAAC;AACD,SAAK,OAAO,KAAK,GAAG;AAAA,EACtB,CAAC;AAED,SAAO,OAAO,IAAI,MAAM,IAAI,MAAM,MAAM;AACtC,QAAI,QAAQ,yDAAiB,IAAI,IAAI,kBAAkB;AACvD,QAAI,KAAK,wCAAoB,IAAI,IAAI,IAAI,IAAI,IAAI,aAAa;AAC9D,QAAI,KAAK,iBAAO,IAAI,aAAa,6BAAc,oBAAK,EAAE;AACtD,QAAI,YAAa,aAAY,MAAM;AAAA,EACrC,CAAC;AAED,SAAO;AACT;AASO,SAAS,aAAa,QAAqB,IAA6C;AAE7F,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,KAAG,GAAG,QAAQ,CAAC,SAAiB;AAC9B,UAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,QAAI,QAAQ,QAAQ;AAClB,cAAQ,IAAI,qCAAiB;AAC7B,cAAQ,IAAI,2CAAkB;AAC9B,cAAQ,IAAI,uDAAoB;AAChC,cAAQ,IAAI,2CAAkB;AAAA,IAChC,WAAW,QAAQ,UAAU;AAC3B,cAAQ,IAAI,kCAAS;AACrB,cAAQ,IAAI,wBAAe,OAAO,QAAQ,EAAuB,IAAI,EAAE;AACvE,cAAQ,IAAI,yBAAU,KAAK,yBAAU,sBAAO,EAAE;AAAA,IAChD,WAAW,QAAQ,QAAQ;AACzB,UAAI,KAAK,yCAAW;AACpB,SAAG,MAAM;AACT,aAAO,MAAM;AACb,UAAI,GAAI,IAAG,MAAM;AACjB,cAAQ,KAAK,CAAC;AAAA,IAChB,OAAO;AACL,UAAI,KAAK,6BAAS,GAAG,kDAAe;AAAA,IACtC;AAAA,EACF,CAAC;AACD,KAAG,GAAG,UAAU,MAAM,QAAQ,KAAK,CAAC;AACpC,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* service-registry.ts —
|
|
2
|
+
* service-registry.ts — 跨模块服务注册表与调度中心(Service Registry)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* 协议规范:
|
|
5
|
+
* - HTTP GET `/api/sfmc/services/<name>?input=<urlencoded-json>`
|
|
6
|
+
* - 鉴权机制:Bearer module_token + 查询参数 `?moduleId=<callerId>`
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* 调度与事务边界:
|
|
9
|
+
* 服务处理器注册在 db-server 进程内存中。
|
|
10
|
+
* 在外层 `db.tx` 事务会话内调用 `tx.call` 时,会通过 `ctx.tx = { query, db }` 注入现有事务上下文,
|
|
11
|
+
* 处理器复用当前事务连接,严禁重复开启嵌套事务。
|
|
11
12
|
*/
|
|
12
13
|
import type { DatabaseSync } from "node:sqlite";
|
|
13
14
|
import type { ModuleManifestV2 } from "./manifest-loader.js";
|
|
@@ -23,19 +24,48 @@ export interface ServiceTxContext {
|
|
|
23
24
|
export interface ServiceDispatchContext {
|
|
24
25
|
callerModuleId: string;
|
|
25
26
|
payload: unknown;
|
|
26
|
-
/** 外层 db.tx
|
|
27
|
+
/** 外层 db.tx 已打开时注入;处理器复用此连接,禁止开启嵌套 BEGIN。 */
|
|
27
28
|
tx?: ServiceTxContext;
|
|
28
29
|
}
|
|
29
30
|
export type ServiceHandler = (ctx: ServiceDispatchContext) => Promise<unknown>;
|
|
31
|
+
/** 跨模块服务注册表管理器。 */
|
|
30
32
|
export declare class ServiceRegistry {
|
|
31
33
|
private readonly handlers;
|
|
32
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* 注册指定模块提供的跨模块服务处理器。
|
|
36
|
+
*
|
|
37
|
+
* @param moduleId 服务提供方模块 ID。
|
|
38
|
+
* @param name 服务完整名称。
|
|
39
|
+
* @param handle 业务处理函数。
|
|
40
|
+
*/
|
|
33
41
|
registerHandler(moduleId: string, name: string, handle: ServiceHandler): void;
|
|
42
|
+
/**
|
|
43
|
+
* 注销指定名称的服务处理器。
|
|
44
|
+
*
|
|
45
|
+
* @param name 待注销的服务名称。
|
|
46
|
+
*/
|
|
34
47
|
unregisterHandler(name: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* 获取当前已注册的全部跨模块服务列表。
|
|
50
|
+
*
|
|
51
|
+
* @returns 包含服务名与所属模块 ID 的列表。
|
|
52
|
+
*/
|
|
35
53
|
list(): Array<{
|
|
36
54
|
name: string;
|
|
37
55
|
moduleId: string;
|
|
38
56
|
}>;
|
|
57
|
+
/**
|
|
58
|
+
* 调度并执行指定的跨模块服务。
|
|
59
|
+
* 包含调用方与提供方启停状态校验、声明式契约(`services.requires`)匹配及异常分流。
|
|
60
|
+
*
|
|
61
|
+
* @param enabled 当前所有已启用的模块清单字典。
|
|
62
|
+
* @param callerModuleId 发起调用的模块唯一标识符。
|
|
63
|
+
* @param name 目标服务完整名称。
|
|
64
|
+
* @param payload 传入调用的参数数据。
|
|
65
|
+
* @param tx 可选的当前事务上下文。
|
|
66
|
+
* @returns 服务执行返回结果。
|
|
67
|
+
* @throws {DispatchError} 服务未找到、未声明依赖或鉴权失败时抛出。
|
|
68
|
+
*/
|
|
39
69
|
dispatch(enabled: Map<string, ModuleManifestV2>, callerModuleId: string, name: string, payload: unknown, tx?: ServiceTxContext): Promise<ServiceCallResult>;
|
|
40
70
|
}
|
|
41
71
|
export declare class DispatchError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-registry.d.ts","sourceRoot":"","sources":["../src/service-registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"service-registry.d.ts","sourceRoot":"","sources":["../src/service-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,YAAY,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,EAAE,CAAC,EAAE,gBAAgB,CAAC;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAO/E,mBAAmB;AACnB,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IAEjE;;;;;;OAMG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAK5E;IAED;;;;OAIG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpC;IAED;;;;OAIG;IACH,IAAI,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAEhD;IAED;;;;;;;;;;;OAWG;IACG,QAAQ,CAEZ,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,EAAE,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAqC5B;CAEF;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,YACE,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,EACvF,MAAM,EAAE,MAAM,EAKf;CACF"}
|
package/dist/service-registry.js
CHANGED
|
@@ -1,18 +1,46 @@
|
|
|
1
1
|
class ServiceRegistry {
|
|
2
2
|
handlers = /* @__PURE__ */ new Map();
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* 注册指定模块提供的跨模块服务处理器。
|
|
5
|
+
*
|
|
6
|
+
* @param moduleId 服务提供方模块 ID。
|
|
7
|
+
* @param name 服务完整名称。
|
|
8
|
+
* @param handle 业务处理函数。
|
|
9
|
+
*/
|
|
4
10
|
registerHandler(moduleId, name, handle) {
|
|
5
11
|
if (this.handlers.has(name)) {
|
|
6
|
-
throw new Error(`[service] "${name}" \u5DF2\u88AB ${this.handlers.get(name)?.moduleId} \u6CE8\u518C
|
|
12
|
+
throw new Error(`[service] "${name}" \u5DF2\u88AB ${this.handlers.get(name)?.moduleId} \u6CE8\u518C, ${moduleId} \u62A2\u6CE8`);
|
|
7
13
|
}
|
|
8
14
|
this.handlers.set(name, { moduleId, handle });
|
|
9
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* 注销指定名称的服务处理器。
|
|
18
|
+
*
|
|
19
|
+
* @param name 待注销的服务名称。
|
|
20
|
+
*/
|
|
10
21
|
unregisterHandler(name) {
|
|
11
22
|
this.handlers.delete(name);
|
|
12
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* 获取当前已注册的全部跨模块服务列表。
|
|
26
|
+
*
|
|
27
|
+
* @returns 包含服务名与所属模块 ID 的列表。
|
|
28
|
+
*/
|
|
13
29
|
list() {
|
|
14
30
|
return [...this.handlers.entries()].map(([name, h]) => ({ name, moduleId: h.moduleId }));
|
|
15
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 调度并执行指定的跨模块服务。
|
|
34
|
+
* 包含调用方与提供方启停状态校验、声明式契约(`services.requires`)匹配及异常分流。
|
|
35
|
+
*
|
|
36
|
+
* @param enabled 当前所有已启用的模块清单字典。
|
|
37
|
+
* @param callerModuleId 发起调用的模块唯一标识符。
|
|
38
|
+
* @param name 目标服务完整名称。
|
|
39
|
+
* @param payload 传入调用的参数数据。
|
|
40
|
+
* @param tx 可选的当前事务上下文。
|
|
41
|
+
* @returns 服务执行返回结果。
|
|
42
|
+
* @throws {DispatchError} 服务未找到、未声明依赖或鉴权失败时抛出。
|
|
43
|
+
*/
|
|
16
44
|
async dispatch(enabled, callerModuleId, name, payload, tx) {
|
|
17
45
|
const handler = this.handlers.get(name);
|
|
18
46
|
if (!handler) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/service-registry.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * service-registry.ts \u2014 \u8DE8\u6A21\u5757
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * service-registry.ts \u2014 \u8DE8\u6A21\u5757\u670D\u52A1\u6CE8\u518C\u8868\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\uFF08Service Registry\uFF09\n *\n * \u534F\u8BAE\u89C4\u8303\uFF1A\n * - HTTP GET `/api/sfmc/services/<name>?input=<urlencoded-json>`\n * - \u9274\u6743\u673A\u5236\uFF1ABearer module_token + \u67E5\u8BE2\u53C2\u6570 `?moduleId=<callerId>`\n *\n * \u8C03\u5EA6\u4E0E\u4E8B\u52A1\u8FB9\u754C\uFF1A\n * \u670D\u52A1\u5904\u7406\u5668\u6CE8\u518C\u5728 db-server \u8FDB\u7A0B\u5185\u5B58\u4E2D\u3002\n * \u5728\u5916\u5C42 `db.tx` \u4E8B\u52A1\u4F1A\u8BDD\u5185\u8C03\u7528 `tx.call` \u65F6\uFF0C\u4F1A\u901A\u8FC7 `ctx.tx = { query, db }` \u6CE8\u5165\u73B0\u6709\u4E8B\u52A1\u4E0A\u4E0B\u6587\uFF0C\n * \u5904\u7406\u5668\u590D\u7528\u5F53\u524D\u4E8B\u52A1\u8FDE\u63A5\uFF0C\u4E25\u7981\u91CD\u590D\u5F00\u542F\u5D4C\u5957\u4E8B\u52A1\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\uFF1B\u5904\u7406\u5668\u590D\u7528\u6B64\u8FDE\u63A5\uFF0C\u7981\u6B62\u5F00\u542F\u5D4C\u5957 BEGIN\u3002 */\n tx?: ServiceTxContext;\n}\n\nexport type ServiceHandler = (ctx: ServiceDispatchContext) => Promise<unknown>;\n\ninterface RegisteredHandler {\n moduleId: string;\n handle: ServiceHandler;\n}\n\n/** \u8DE8\u6A21\u5757\u670D\u52A1\u6CE8\u518C\u8868\u7BA1\u7406\u5668\u3002 */\nexport class ServiceRegistry {\n private readonly handlers = new Map<string, RegisteredHandler>();\n\n /**\n * \u6CE8\u518C\u6307\u5B9A\u6A21\u5757\u63D0\u4F9B\u7684\u8DE8\u6A21\u5757\u670D\u52A1\u5904\u7406\u5668\u3002\n *\n * @param moduleId \u670D\u52A1\u63D0\u4F9B\u65B9\u6A21\u5757 ID\u3002\n * @param name \u670D\u52A1\u5B8C\u6574\u540D\u79F0\u3002\n * @param handle \u4E1A\u52A1\u5904\u7406\u51FD\u6570\u3002\n */\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 /**\n * \u6CE8\u9500\u6307\u5B9A\u540D\u79F0\u7684\u670D\u52A1\u5904\u7406\u5668\u3002\n *\n * @param name \u5F85\u6CE8\u9500\u7684\u670D\u52A1\u540D\u79F0\u3002\n */\n unregisterHandler(name: string): void {\n this.handlers.delete(name);\n }\n\n /**\n * \u83B7\u53D6\u5F53\u524D\u5DF2\u6CE8\u518C\u7684\u5168\u90E8\u8DE8\u6A21\u5757\u670D\u52A1\u5217\u8868\u3002\n *\n * @returns \u5305\u542B\u670D\u52A1\u540D\u4E0E\u6240\u5C5E\u6A21\u5757 ID \u7684\u5217\u8868\u3002\n */\n list(): Array<{ name: string; moduleId: string }> {\n return [...this.handlers.entries()].map(([name, h]) => ({ name, moduleId: h.moduleId }));\n }\n\n /**\n * \u8C03\u5EA6\u5E76\u6267\u884C\u6307\u5B9A\u7684\u8DE8\u6A21\u5757\u670D\u52A1\u3002\n * \u5305\u542B\u8C03\u7528\u65B9\u4E0E\u63D0\u4F9B\u65B9\u542F\u505C\u72B6\u6001\u6821\u9A8C\u3001\u58F0\u660E\u5F0F\u5951\u7EA6\uFF08`services.requires`\uFF09\u5339\u914D\u53CA\u5F02\u5E38\u5206\u6D41\u3002\n *\n * @param enabled \u5F53\u524D\u6240\u6709\u5DF2\u542F\u7528\u7684\u6A21\u5757\u6E05\u5355\u5B57\u5178\u3002\n * @param callerModuleId \u53D1\u8D77\u8C03\u7528\u7684\u6A21\u5757\u552F\u4E00\u6807\u8BC6\u7B26\u3002\n * @param name \u76EE\u6807\u670D\u52A1\u5B8C\u6574\u540D\u79F0\u3002\n * @param payload \u4F20\u5165\u8C03\u7528\u7684\u53C2\u6570\u6570\u636E\u3002\n * @param tx \u53EF\u9009\u7684\u5F53\u524D\u4E8B\u52A1\u4E0A\u4E0B\u6587\u3002\n * @returns \u670D\u52A1\u6267\u884C\u8FD4\u56DE\u7ED3\u679C\u3002\n * @throws {DispatchError} \u670D\u52A1\u672A\u627E\u5230\u3001\u672A\u58F0\u660E\u4F9D\u8D56\u6216\u9274\u6743\u5931\u8D25\u65F6\u629B\u51FA\u3002\n */\n async dispatch(\n\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": "AA0CO,MAAM,gBAAgB;AAAA,EACV,WAAW,oBAAI,IAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/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,kBAAQ,QAAQ,eAAK;AAAA,IAClG;AACA,SAAK,SAAS,IAAI,MAAM,EAAE,UAAU,OAAO,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,MAAoB;AACpC,SAAK,SAAS,OAAO,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,SAEJ,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
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* services/builtin-handlers.ts —
|
|
2
|
+
* services/builtin-handlers.ts — 进程内置跨模块服务插件注册表
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 遵循开闭原则(OCP):新增内置服务仅需向 `BUILTIN_SERVICE_PLUGINS` 追加配置,
|
|
5
|
+
* 避免在主入口硬编码 `if (enabledSet.has(...)) registerXxx` 注册链。
|
|
6
6
|
*/
|
|
7
7
|
import type { DatabaseSync } from "node:sqlite";
|
|
8
8
|
import type { QueryFn } from "../lib/sqlite.js";
|
|
@@ -15,12 +15,32 @@ export type BuiltinServicePlugin = {
|
|
|
15
15
|
moduleId: string;
|
|
16
16
|
register: (registry: ServiceRegistry, deps: BuiltinServiceDeps) => void;
|
|
17
17
|
};
|
|
18
|
-
/** 内置 service 插件清单 —
|
|
18
|
+
/** 内置 service 插件清单 — 扩展注册列表。 */
|
|
19
19
|
export declare const BUILTIN_SERVICE_PLUGINS: BuiltinServicePlugin[];
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* 根据已启用模块集合批量注册内置服务插件。
|
|
22
|
+
*
|
|
23
|
+
* @param registry 服务注册表实例。
|
|
24
|
+
* @param deps 数据库查询与连接依赖。
|
|
25
|
+
* @param enabledSet 当前处于启用状态的模块 ID 集合。
|
|
26
|
+
* @returns 成功注册的插件数量。
|
|
27
|
+
*/
|
|
21
28
|
export declare function registerEnabledBuiltinServices(registry: ServiceRegistry, deps: BuiltinServiceDeps, enabledSet: Set<string>): number;
|
|
22
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* 热启用指定模块的内置服务插件(若尚未注册)。
|
|
31
|
+
*
|
|
32
|
+
* @param registry 服务注册表实例。
|
|
33
|
+
* @param deps 数据库依赖。
|
|
34
|
+
* @param moduleId 目标模块唯一标识符。
|
|
35
|
+
* @returns 若成功注册返回 `true`,若插件不存在或已注册则返回 `false`。
|
|
36
|
+
*/
|
|
23
37
|
export declare function registerBuiltinPluginForModule(registry: ServiceRegistry, deps: BuiltinServiceDeps, moduleId: string): boolean;
|
|
24
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* 热禁用指定模块的全部服务处理器。
|
|
40
|
+
*
|
|
41
|
+
* @param registry 服务注册表实例。
|
|
42
|
+
* @param moduleId 待卸载服务的模块 ID。
|
|
43
|
+
* @returns 成功卸载的服务数量。
|
|
44
|
+
*/
|
|
25
45
|
export declare function unregisterBuiltinPluginForModule(registry: ServiceRegistry, moduleId: string): number;
|
|
26
46
|
//# 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,
|
|
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,gCAAgC;AAChC,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAEzD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,kBAAkB,EACxB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,CAQR;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASpG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/builtin-handlers.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * services/builtin-handlers.ts \u2014 \u8FDB\u7A0B\u5185\u7F6E
|
|
5
|
-
"mappings": "AAUA,SAAS,+BAA+B;AAUjC,MAAM,0BAAkD;AAAA,EAC7D,EAAE,UAAU,mBAAmB,UAAU,wBAAwB;AACnE;
|
|
4
|
+
"sourcesContent": ["/**\n * services/builtin-handlers.ts \u2014 \u8FDB\u7A0B\u5185\u7F6E\u8DE8\u6A21\u5757\u670D\u52A1\u63D2\u4EF6\u6CE8\u518C\u8868\n *\n * \u9075\u5FAA\u5F00\u95ED\u539F\u5219\uFF08OCP\uFF09\uFF1A\u65B0\u589E\u5185\u7F6E\u670D\u52A1\u4EC5\u9700\u5411 `BUILTIN_SERVICE_PLUGINS` \u8FFD\u52A0\u914D\u7F6E\uFF0C\n * \u907F\u514D\u5728\u4E3B\u5165\u53E3\u786C\u7F16\u7801 `if (enabledSet.has(...)) registerXxx` \u6CE8\u518C\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 \u6269\u5C55\u6CE8\u518C\u5217\u8868\u3002 */\nexport const BUILTIN_SERVICE_PLUGINS: BuiltinServicePlugin[] = [\n { moduleId: \"feature-economy\", register: registerEconomyHandlers },\n];\n\n/**\n * \u6839\u636E\u5DF2\u542F\u7528\u6A21\u5757\u96C6\u5408\u6279\u91CF\u6CE8\u518C\u5185\u7F6E\u670D\u52A1\u63D2\u4EF6\u3002\n *\n * @param registry \u670D\u52A1\u6CE8\u518C\u8868\u5B9E\u4F8B\u3002\n * @param deps \u6570\u636E\u5E93\u67E5\u8BE2\u4E0E\u8FDE\u63A5\u4F9D\u8D56\u3002\n * @param enabledSet \u5F53\u524D\u5904\u4E8E\u542F\u7528\u72B6\u6001\u7684\u6A21\u5757 ID \u96C6\u5408\u3002\n * @returns \u6210\u529F\u6CE8\u518C\u7684\u63D2\u4EF6\u6570\u91CF\u3002\n */\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/**\n * \u70ED\u542F\u7528\u6307\u5B9A\u6A21\u5757\u7684\u5185\u7F6E\u670D\u52A1\u63D2\u4EF6\uFF08\u82E5\u5C1A\u672A\u6CE8\u518C\uFF09\u3002\n *\n * @param registry \u670D\u52A1\u6CE8\u518C\u8868\u5B9E\u4F8B\u3002\n * @param deps \u6570\u636E\u5E93\u4F9D\u8D56\u3002\n * @param moduleId \u76EE\u6807\u6A21\u5757\u552F\u4E00\u6807\u8BC6\u7B26\u3002\n * @returns \u82E5\u6210\u529F\u6CE8\u518C\u8FD4\u56DE `true`\uFF0C\u82E5\u63D2\u4EF6\u4E0D\u5B58\u5728\u6216\u5DF2\u6CE8\u518C\u5219\u8FD4\u56DE `false`\u3002\n */\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/**\n * \u70ED\u7981\u7528\u6307\u5B9A\u6A21\u5757\u7684\u5168\u90E8\u670D\u52A1\u5904\u7406\u5668\u3002\n *\n * @param registry \u670D\u52A1\u6CE8\u518C\u8868\u5B9E\u4F8B\u3002\n * @param moduleId \u5F85\u5378\u8F7D\u670D\u52A1\u7684\u6A21\u5757 ID\u3002\n * @returns \u6210\u529F\u5378\u8F7D\u7684\u670D\u52A1\u6570\u91CF\u3002\n */\nexport function unregisterBuiltinPluginForModule(registry: ServiceRegistry, moduleId: string): number {\n\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;AAUO,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;AAUO,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;AASO,SAAS,iCAAiC,UAA2B,UAA0B;AAEpG,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
6
|
"names": []
|
|
7
7
|
}
|
package/dist/tx-runner.d.ts
CHANGED
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
* 实现:handler 返回 result 写回 step 输出;若 handler 还要写 db,应走其它接口在事务外做。
|
|
25
25
|
*/
|
|
26
26
|
import type { DatabaseSync } from "node:sqlite";
|
|
27
|
+
import type { ModuleManifestV2 } from "./manifest-loader.js";
|
|
27
28
|
import type { SchemaRegistry } from "./schema-registry.js";
|
|
28
|
-
import type { WhereExpr } from "./where.js";
|
|
29
29
|
import { type ServiceRegistry } from "./service-registry.js";
|
|
30
|
-
import type {
|
|
30
|
+
import type { WhereExpr } from "./where.js";
|
|
31
31
|
export interface TxStepQuery {
|
|
32
32
|
op: "query";
|
|
33
33
|
table: string;
|
|
@@ -112,12 +112,18 @@ export type TxError = {
|
|
|
112
112
|
ok: false;
|
|
113
113
|
step: number;
|
|
114
114
|
error: string;
|
|
115
|
-
code: "permission_denied" | "forbidden" | "no_such_service" | "not_in_requires" | "domain_error" | "internal" | "no_such_table";
|
|
115
|
+
code: "permission_denied" | "forbidden" | "no_such_service" | "not_in_requires" | "domain_error" | "transaction_busy" | "internal" | "no_such_table";
|
|
116
116
|
};
|
|
117
117
|
export interface TxRequest {
|
|
118
118
|
moduleId: string;
|
|
119
119
|
steps: TxStep[];
|
|
120
120
|
}
|
|
121
|
+
export interface TxRunnerOptions {
|
|
122
|
+
/** 等待全局 SQLite 事务槽的最长时间。 */
|
|
123
|
+
slotWaitTimeoutMs?: number;
|
|
124
|
+
/** 交互式事务两次请求之间允许空闲的最长时间。 */
|
|
125
|
+
sessionIdleTimeoutMs?: number;
|
|
126
|
+
}
|
|
121
127
|
export interface TxRunnerDeps {
|
|
122
128
|
db: DatabaseSync;
|
|
123
129
|
query: import("./lib/sqlite.js").QueryFn;
|
|
@@ -128,26 +134,59 @@ export interface TxRunnerDeps {
|
|
|
128
134
|
export declare class TxRunner {
|
|
129
135
|
private readonly deps;
|
|
130
136
|
private readonly sessions;
|
|
131
|
-
|
|
137
|
+
private transactionBusy;
|
|
138
|
+
private readonly transactionWaiters;
|
|
139
|
+
private readonly slotWaitTimeoutMs;
|
|
140
|
+
private readonly sessionIdleTimeoutMs;
|
|
141
|
+
constructor(deps: TxRunnerDeps, options?: TxRunnerOptions);
|
|
132
142
|
run(req: TxRequest): Promise<TxResponse | TxError>;
|
|
133
143
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
144
|
+
* 开启交互式事务会话(协议流程:begin → step* → commit | rollback)。
|
|
145
|
+
* 供客户端 `db.tx` 在回调内部异步执行并实时读回 query / get / call 的服务端执行结果。
|
|
146
|
+
* 单连接互斥保护:与批量 run() 共用事务队列,并在提交/回滚时唤醒下一个等待者。
|
|
147
|
+
*
|
|
148
|
+
* @param moduleId 请求模块唯一标识符。
|
|
149
|
+
* @returns 成功返回分配的会话 txId,失败返回错误响应。
|
|
137
150
|
*/
|
|
138
|
-
beginSession(moduleId: string): {
|
|
151
|
+
beginSession(moduleId: string): Promise<{
|
|
139
152
|
ok: true;
|
|
140
153
|
txId: string;
|
|
141
|
-
} | TxError
|
|
154
|
+
} | TxError>;
|
|
155
|
+
/**
|
|
156
|
+
* 在当前交互式事务会话中顺序执行单个步骤。
|
|
157
|
+
*
|
|
158
|
+
* @param txId 会话唯一标识符。
|
|
159
|
+
* @param moduleId 调用模块标识。
|
|
160
|
+
* @param step 待执行的操作步骤对象。
|
|
161
|
+
* @returns 步骤执行结果或错误响应。
|
|
162
|
+
*/
|
|
142
163
|
stepSession(txId: string, moduleId: string, step: TxStep): Promise<{
|
|
143
164
|
ok: true;
|
|
144
165
|
result: TxStepResult;
|
|
145
166
|
} | TxError>;
|
|
167
|
+
/**
|
|
168
|
+
* 提交当前交互式事务会话,将所有步骤的修改持久化并释放连接。
|
|
169
|
+
*
|
|
170
|
+
* @param txId 会话唯一标识符。
|
|
171
|
+
* @param moduleId 调用模块标识。
|
|
172
|
+
* @returns 提交结果响应。
|
|
173
|
+
*/
|
|
146
174
|
commitSession(txId: string, moduleId: string): TxResponse | TxError;
|
|
175
|
+
/**
|
|
176
|
+
* 回滚当前交互式事务会话,撤销所有未提交的数据库变更。
|
|
177
|
+
* 具有幂等性:会话已结束或已回滚时同样返回成功。
|
|
178
|
+
*
|
|
179
|
+
* @param txId 会话唯一标识符。
|
|
180
|
+
* @param moduleId 调用模块标识。
|
|
181
|
+
* @returns 回滚确认结果。
|
|
182
|
+
*/
|
|
147
183
|
rollbackSession(txId: string, moduleId: string): {
|
|
148
184
|
ok: true;
|
|
149
185
|
} | TxError;
|
|
150
186
|
private abortSession;
|
|
187
|
+
private acquireTransactionSlot;
|
|
188
|
+
private releaseTransactionSlot;
|
|
189
|
+
private createSessionIdleTimer;
|
|
151
190
|
private mapErrorCode;
|
|
152
191
|
private rollback;
|
|
153
192
|
/** 单 step 由对应权限检查 + SQL 路径执行 */
|
package/dist/tx-runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx-runner.d.ts","sourceRoot":"","sources":["../src/tx-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tx-runner.d.ts","sourceRoot":"","sources":["../src/tx-runner.ts"],"names":[],"mappings":"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"}
|