@sfmc-bds/db-server 0.1.0 → 0.2.0-beta.1

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
package/dist/lib/http.js CHANGED
@@ -1,43 +1,34 @@
1
- /**
2
- * lib/http.ts HTTP 工具(JSON 响应 + body 解析)
3
- *
4
- * 所有 db-server 路由统一走这里的 json / body / parseBody。
5
- * 路由上下文 ({ path, method, params, req, res }) 在 routes/_shared.ts 定义。
6
- */
7
- /** 写 JSON 响应并结束。 */
8
- export function json(res, data, status = 200) {
9
- res.writeHead(status, { "Content-Type": "application/json" });
10
- res.end(JSON.stringify(data));
1
+ function json(res, data, status = 200) {
2
+ res.writeHead(status, { "Content-Type": "application/json" });
3
+ res.end(JSON.stringify(data));
11
4
  }
12
- /** 解析请求 body 字符串为对象(解析失败返回空对象)。 */
13
- export function parseBody(raw) {
14
- try {
15
- return JSON.parse(raw || "{}");
16
- }
17
- catch {
18
- return {};
19
- }
5
+ function parseBody(raw) {
6
+ try {
7
+ return JSON.parse(raw || "{}");
8
+ } catch {
9
+ return {};
10
+ }
20
11
  }
21
- /**
22
- * 异步读取请求 body,结果会缓存到 req._bodyPromise 上以避免重复读取。
23
- * Buffer 累积 + 异步拼接,正确处理 binary 字节流。
24
- */
25
- export function body(req) {
26
- const cached = req._bodyPromise;
27
- if (cached)
28
- return cached;
29
- const promise = new Promise((resolve) => {
30
- const chunks = [];
31
- req.on("data", (chunk) => {
32
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
33
- });
34
- req.on("end", () => {
35
- const raw = Buffer.concat(chunks).toString("utf-8");
36
- resolve(parseBody(raw));
37
- });
38
- req.on("error", () => resolve({}));
12
+ function body(req) {
13
+ const cached = req._bodyPromise;
14
+ if (cached) return cached;
15
+ const promise = new Promise((resolve) => {
16
+ const chunks = [];
17
+ req.on("data", (chunk) => {
18
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
39
19
  });
40
- req._bodyPromise = promise;
41
- return promise;
20
+ req.on("end", () => {
21
+ const raw = Buffer.concat(chunks).toString("utf-8");
22
+ resolve(parseBody(raw));
23
+ });
24
+ req.on("error", () => resolve({}));
25
+ });
26
+ req._bodyPromise = promise;
27
+ return promise;
42
28
  }
43
- //# sourceMappingURL=http.js.map
29
+ export {
30
+ body,
31
+ json,
32
+ parseBody
33
+ };
34
+ //# sourceMappingURL=http.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,oBAAoB;AACpB,MAAM,UAAU,IAAI,CAAC,GAAmB,EAAE,IAA6B,EAAE,SAAiB,GAAG;IAC3F,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAA4B,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,GAAoB;IACvC,MAAM,MAAM,GAAI,GAA6E,CAAC,YAAY,CAAC;IAC3G,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,CAA0B,CAAC,OAAO,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YACxC,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACpD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IACF,GAA6E,CAAC,YAAY,GAAG,OAAO,CAAC;IACtG,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/http.ts"],
4
+ "sourcesContent": ["/**\n * lib/http.ts \u2014 HTTP \u5DE5\u5177\uFF08JSON \u54CD\u5E94 + body \u89E3\u6790\uFF09\n *\n * \u6240\u6709 db-server \u8DEF\u7531\u7EDF\u4E00\u8D70\u8FD9\u91CC\u7684 json / body / parseBody\u3002\n * \u8DEF\u7531\u4E0A\u4E0B\u6587 ({ path, method, params, req, res }) \u5728 routes/_shared.ts \u5B9A\u4E49\u3002\n */\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport type Method = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n\n/** \u5199 JSON \u54CD\u5E94\u5E76\u7ED3\u675F\u3002 */\nexport function json(res: ServerResponse, data: Record<string, unknown>, status: number = 200): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n}\n\n/** \u89E3\u6790\u8BF7\u6C42 body \u5B57\u7B26\u4E32\u4E3A\u5BF9\u8C61\uFF08\u89E3\u6790\u5931\u8D25\u8FD4\u56DE\u7A7A\u5BF9\u8C61\uFF09\u3002 */\nexport function parseBody(raw: string): Record<string, unknown> {\n try {\n return JSON.parse(raw || \"{}\") as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * \u5F02\u6B65\u8BFB\u53D6\u8BF7\u6C42 body\uFF0C\u7ED3\u679C\u4F1A\u7F13\u5B58\u5230 req._bodyPromise \u4E0A\u4EE5\u907F\u514D\u91CD\u590D\u8BFB\u53D6\u3002\n * Buffer \u7D2F\u79EF + \u5F02\u6B65\u62FC\u63A5\uFF0C\u6B63\u786E\u5904\u7406 binary \u5B57\u8282\u6D41\u3002\n */\nexport function body(req: IncomingMessage): Promise<Record<string, unknown>> {\n const cached = (req as IncomingMessage & { _bodyPromise?: Promise<Record<string, unknown>> })._bodyPromise;\n if (cached) return cached;\n const promise = new Promise<Record<string, unknown>>((resolve) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer | string) => {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n req.on(\"end\", () => {\n const raw = Buffer.concat(chunks).toString(\"utf-8\");\n resolve(parseBody(raw));\n });\n req.on(\"error\", () => resolve({}));\n });\n (req as IncomingMessage & { _bodyPromise?: Promise<Record<string, unknown>> })._bodyPromise = promise;\n return promise;\n}\n"],
5
+ "mappings": "AAYO,SAAS,KAAK,KAAqB,MAA+B,SAAiB,KAAW;AACnG,MAAI,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC5D,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAGO,SAAS,UAAU,KAAsC;AAC9D,MAAI;AACF,WAAO,KAAK,MAAM,OAAO,IAAI;AAAA,EAC/B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAMO,SAAS,KAAK,KAAwD;AAC3E,QAAM,SAAU,IAA8E;AAC9F,MAAI,OAAQ,QAAO;AACnB,QAAM,UAAU,IAAI,QAAiC,CAAC,YAAY;AAChE,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAA2B;AACzC,aAAO,KAAK,OAAO,UAAU,WAAW,OAAO,KAAK,KAAK,IAAI,KAAK;AAAA,IACpE,CAAC;AACD,QAAI,GAAG,OAAO,MAAM;AAClB,YAAM,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAClD,cAAQ,UAAU,GAAG,CAAC;AAAA,IACxB,CAAC;AACD,QAAI,GAAG,SAAS,MAAM,QAAQ,CAAC,CAAC,CAAC;AAAA,EACnC,CAAC;AACD,EAAC,IAA8E,eAAe;AAC9F,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,49 +1,36 @@
1
- /**
2
- * lib/idempotency.ts — db.idempotent() 后端
3
- *
4
- * 表:sfmc__idempotent (db-tables.ts 创建)
5
- * key: (module_id, action, key) → cached value?
6
- *
7
- * probe(module_id, action, key):
8
- * - 命中 → {replayed:true, cached}
9
- * - 不命中 → {replayed:false}
10
- *
11
- * commit(module_id, action, key, value?):
12
- * - INSERT … (replace) — 即使没 probe 也允许直接 commit
13
- *
14
- * 事务内调用一律走 tx-runner 不行(commit 必须在事务外完成,跨事务持久化);
15
- * 这里单独端点 POST /api/sfmc/db/idempotent/{probe,commit},不走 tx。
16
- */
17
1
  import { isValidIdempotencyKey } from "./idempotency.js";
18
- export function createIdempotencyStore(db) {
19
- const probeStmt = db.prepare("SELECT value FROM sfmc__idempotent WHERE module_id=? AND action=? AND key=?");
20
- const insertStmt = db.prepare(`INSERT OR REPLACE INTO sfmc__idempotent (module_id, action, key, value, created_at)
21
- VALUES (?, ?, ?, ?, ?)`);
22
- return {
23
- async probe(moduleId, action, key) {
24
- if (!isValidIdempotencyKey(key))
25
- throw new Error("invalid idempotency key");
26
- const row = probeStmt.get(moduleId, action, key);
27
- if (!row)
28
- return { replayed: false };
29
- let cached = null;
30
- if (row.value) {
31
- try {
32
- cached = JSON.parse(row.value);
33
- }
34
- catch {
35
- cached = row.value;
36
- }
37
- }
38
- return { replayed: true, cached };
39
- },
40
- async commit(moduleId, action, key, value) {
41
- if (!isValidIdempotencyKey(key))
42
- throw new Error("invalid idempotency key");
43
- const json = value === undefined ? null : JSON.stringify(value);
44
- insertStmt.run(moduleId, action, key, json, new Date().toISOString());
45
- return { ok: true };
46
- },
47
- };
2
+ function createIdempotencyStore(db) {
3
+ const probeStmt = db.prepare(
4
+ "SELECT value FROM sfmc__idempotent WHERE module_id=? AND action=? AND key=?"
5
+ );
6
+ const insertStmt = db.prepare(
7
+ `INSERT OR REPLACE INTO sfmc__idempotent (module_id, action, key, value, created_at)
8
+ VALUES (?, ?, ?, ?, ?)`
9
+ );
10
+ return {
11
+ async probe(moduleId, action, key) {
12
+ if (!isValidIdempotencyKey(key)) throw new Error("invalid idempotency key");
13
+ const row = probeStmt.get(moduleId, action, key);
14
+ if (!row) return { replayed: false };
15
+ let cached = null;
16
+ if (row.value) {
17
+ try {
18
+ cached = JSON.parse(row.value);
19
+ } catch {
20
+ cached = row.value;
21
+ }
22
+ }
23
+ return { replayed: true, cached };
24
+ },
25
+ async commit(moduleId, action, key, value) {
26
+ if (!isValidIdempotencyKey(key)) throw new Error("invalid idempotency key");
27
+ const json = value === void 0 ? null : JSON.stringify(value);
28
+ insertStmt.run(moduleId, action, key, json, (/* @__PURE__ */ new Date()).toISOString());
29
+ return { ok: true };
30
+ }
31
+ };
48
32
  }
49
- //# sourceMappingURL=idempotency-store.js.map
33
+ export {
34
+ createIdempotencyStore
35
+ };
36
+ //# sourceMappingURL=idempotency-store.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"idempotency-store.js","sourceRoot":"","sources":["../../src/lib/idempotency-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAOzD,MAAM,UAAU,sBAAsB,CAAC,EAAgB;IACrD,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,6EAA6E,CAC9E,CAAC;IACF,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAC3B;4BACwB,CACzB,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG;YAC/B,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC5E,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAyC,CAAC;YACzF,IAAI,CAAC,GAAG;gBAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YACrC,IAAI,MAAM,GAAY,IAAI,CAAC;YAC3B,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACjC,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACpC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,KAAM;YACxC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC5E,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAChE,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YACtE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/idempotency-store.ts"],
4
+ "sourcesContent": ["/**\n * lib/idempotency.ts \u2014 db.idempotent() \u540E\u7AEF\n *\n * \u8868:sfmc__idempotent (db-tables.ts \u521B\u5EFA)\n * key: (module_id, action, key) \u2192 cached value?\n *\n * probe(module_id, action, key):\n * - \u547D\u4E2D \u2192 {replayed:true, cached}\n * - \u4E0D\u547D\u4E2D \u2192 {replayed:false}\n *\n * commit(module_id, action, key, value?):\n * - INSERT \u2026 (replace) \u2014 \u5373\u4F7F\u6CA1 probe \u4E5F\u5141\u8BB8\u76F4\u63A5 commit\n *\n * \u4E8B\u52A1\u5185\u8C03\u7528\u4E00\u5F8B\u8D70 tx-runner \u4E0D\u884C(commit \u5FC5\u987B\u5728\u4E8B\u52A1\u5916\u5B8C\u6210,\u8DE8\u4E8B\u52A1\u6301\u4E45\u5316);\n * \u8FD9\u91CC\u5355\u72EC\u7AEF\u70B9 POST /api/sfmc/db/idempotent/{probe,commit},\u4E0D\u8D70 tx\u3002\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport { isValidIdempotencyKey } from \"./idempotency.js\";\n\nexport interface IdempotencyStore {\n probe(moduleId: string, action: string, key: string): Promise<{ replayed: boolean; cached?: unknown }>;\n commit(moduleId: string, action: string, key: string, value?: unknown): Promise<{ ok: boolean }>;\n}\n\nexport function createIdempotencyStore(db: DatabaseSync): IdempotencyStore {\n const probeStmt = db.prepare(\n \"SELECT value FROM sfmc__idempotent WHERE module_id=? AND action=? AND key=?\"\n );\n const insertStmt = db.prepare(\n `INSERT OR REPLACE INTO sfmc__idempotent (module_id, action, key, value, created_at)\n VALUES (?, ?, ?, ?, ?)`\n );\n\n return {\n async probe(moduleId, action, key) {\n if (!isValidIdempotencyKey(key)) throw new Error(\"invalid idempotency key\");\n const row = probeStmt.get(moduleId, action, key) as { value: string | null } | undefined;\n if (!row) return { replayed: false };\n let cached: unknown = null;\n if (row.value) {\n try {\n cached = JSON.parse(row.value);\n } catch {\n cached = row.value;\n }\n }\n return { replayed: true, cached };\n },\n\n async commit(moduleId, action, key, value?) {\n if (!isValidIdempotencyKey(key)) throw new Error(\"invalid idempotency key\");\n const json = value === undefined ? null : JSON.stringify(value);\n insertStmt.run(moduleId, action, key, json, new Date().toISOString());\n return { ok: true };\n },\n };\n}\n"],
5
+ "mappings": "AAkBA,SAAS,6BAA6B;AAO/B,SAAS,uBAAuB,IAAoC;AACzE,QAAM,YAAY,GAAG;AAAA,IACnB;AAAA,EACF;AACA,QAAM,aAAa,GAAG;AAAA,IACpB;AAAA;AAAA,EAEF;AAEA,SAAO;AAAA,IACL,MAAM,MAAM,UAAU,QAAQ,KAAK;AACjC,UAAI,CAAC,sBAAsB,GAAG,EAAG,OAAM,IAAI,MAAM,yBAAyB;AAC1E,YAAM,MAAM,UAAU,IAAI,UAAU,QAAQ,GAAG;AAC/C,UAAI,CAAC,IAAK,QAAO,EAAE,UAAU,MAAM;AACnC,UAAI,SAAkB;AACtB,UAAI,IAAI,OAAO;AACb,YAAI;AACF,mBAAS,KAAK,MAAM,IAAI,KAAK;AAAA,QAC/B,QAAQ;AACN,mBAAS,IAAI;AAAA,QACf;AAAA,MACF;AACA,aAAO,EAAE,UAAU,MAAM,OAAO;AAAA,IAClC;AAAA,IAEA,MAAM,OAAO,UAAU,QAAQ,KAAK,OAAQ;AAC1C,UAAI,CAAC,sBAAsB,GAAG,EAAG,OAAM,IAAI,MAAM,yBAAyB;AAC1E,YAAM,OAAO,UAAU,SAAY,OAAO,KAAK,UAAU,KAAK;AAC9D,iBAAW,IAAI,UAAU,QAAQ,KAAK,OAAM,oBAAI,KAAK,GAAE,YAAY,CAAC;AACpE,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -1,14 +1,9 @@
1
- /**
2
- * 验证幂等键格式
3
- *
4
- * @export
5
- * @param {string} key
6
- * @return {*} {(boolean | string)}
7
- */
8
- export function isValidIdempotencyKey(key) {
9
- if (!key || typeof key !== "string")
10
- return false;
11
- const trimmed = key.trim();
12
- return trimmed.length > 0 && /^[A-Za-z0-9_.:-]{1,128}$/.test(trimmed);
1
+ function isValidIdempotencyKey(key) {
2
+ if (!key || typeof key !== "string") return false;
3
+ const trimmed = key.trim();
4
+ return trimmed.length > 0 && /^[A-Za-z0-9_.:-]{1,128}$/.test(trimmed);
13
5
  }
14
- //# sourceMappingURL=idempotency.js.map
6
+ export {
7
+ isValidIdempotencyKey
8
+ };
9
+ //# sourceMappingURL=idempotency.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/lib/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxE,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/idempotency.ts"],
4
+ "sourcesContent": ["/**\n * \u9A8C\u8BC1\u5E42\u7B49\u952E\u683C\u5F0F\n *\n * @export\n * @param {string} key\n * @return {*} {(boolean | string)}\n */\nexport function isValidIdempotencyKey(key: string): boolean {\n if (!key || typeof key !== \"string\") return false;\n const trimmed = key.trim();\n return trimmed.length > 0 && /^[A-Za-z0-9_.:-]{1,128}$/.test(trimmed);\n}\n"],
5
+ "mappings": "AAOO,SAAS,sBAAsB,KAAsB;AAC1D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,UAAU,IAAI,KAAK;AACzB,SAAO,QAAQ,SAAS,KAAK,2BAA2B,KAAK,OAAO;AACtE;",
6
+ "names": []
7
+ }
@@ -1,18 +1,22 @@
1
1
  class IdentifierError extends Error {
2
- code;
3
- constructor(message, code) {
4
- super(message);
5
- this.code = code;
6
- Object.setPrototypeOf(this, IdentifierError.prototype);
7
- }
2
+ code;
3
+ constructor(message, code) {
4
+ super(message);
5
+ this.code = code;
6
+ Object.setPrototypeOf(this, IdentifierError.prototype);
7
+ }
8
8
  }
9
- export function assertIdentifier(value, label = "identifier") {
10
- if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
11
- throw new IdentifierError(`Invalid SQL ${label}`, "INVALID_IDENTIFIER");
12
- }
13
- return value;
9
+ function assertIdentifier(value, label = "identifier") {
10
+ if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
11
+ throw new IdentifierError(`Invalid SQL ${label}`, "INVALID_IDENTIFIER");
12
+ }
13
+ return value;
14
14
  }
15
- export function quoteIdentifier(value, label) {
16
- return `"${assertIdentifier(value, label)}"`;
15
+ function quoteIdentifier(value, label) {
16
+ return `"${assertIdentifier(value, label)}"`;
17
17
  }
18
- //# sourceMappingURL=identifiers.js.map
18
+ export {
19
+ assertIdentifier,
20
+ quoteIdentifier
21
+ };
22
+ //# sourceMappingURL=identifiers.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"identifiers.js","sourceRoot":"","sources":["../../src/lib/identifiers.ts"],"names":[],"mappings":"AAAA,MAAM,eAAgB,SAAQ,KAAK;IACjC,IAAI,CAAS;IACb,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,QAAgB,YAAY;IAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,eAAe,CAAC,eAAe,KAAK,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa;IAC1D,OAAO,IAAI,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;AAC/C,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/identifiers.ts"],
4
+ "sourcesContent": ["class IdentifierError extends Error {\n code: string;\n constructor(message: string, code: string) {\n super(message);\n this.code = code;\n Object.setPrototypeOf(this, IdentifierError.prototype);\n }\n}\n\nexport function assertIdentifier(value: unknown, label: string = \"identifier\"): string {\n if (typeof value !== \"string\" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {\n throw new IdentifierError(`Invalid SQL ${label}`, \"INVALID_IDENTIFIER\");\n }\n return value;\n}\n\nexport function quoteIdentifier(value: string, label: string): string {\n return `\"${assertIdentifier(value, label)}\"`;\n}\n"],
5
+ "mappings": "AAAA,MAAM,wBAAwB,MAAM;AAAA,EAClC;AAAA,EACA,YAAY,SAAiB,MAAc;AACzC,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,WAAO,eAAe,MAAM,gBAAgB,SAAS;AAAA,EACvD;AACF;AAEO,SAAS,iBAAiB,OAAgB,QAAgB,cAAsB;AACrF,MAAI,OAAO,UAAU,YAAY,CAAC,2BAA2B,KAAK,KAAK,GAAG;AACxE,UAAM,IAAI,gBAAgB,eAAe,KAAK,IAAI,oBAAoB;AAAA,EACxE;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAe,OAAuB;AACpE,SAAO,IAAI,iBAAiB,OAAO,KAAK,CAAC;AAC3C;",
6
+ "names": []
7
+ }
package/dist/lib/log.d.ts CHANGED
@@ -1,11 +1,8 @@
1
1
  /**
2
2
  * log.ts — db-server 统一日志实例
3
3
  *
4
- * 通过 @sfmc-bds/logs 共享包接入,source = "db"。
5
- * sfmc 主进程通过捕获本进程 stdout 汇聚展示。
6
- *
7
- * bare 模式: stdout 只输出纯 text,不加时间戳/source/level 前缀
8
- * (由 sfmc 的 formatLog 统一添加,避免重复)。error 走 stderr。
4
+ * stdout bare + 落盘 `<SFMC_ROOT>/.sfmc/logs/db.log`。
5
+ * bare: 只输出纯 text,由 sfmc 捕获后统一加前缀;error stderr。
9
6
  */
10
- export declare const log: import("@sfmc-bds/sdk/logs").Logger;
7
+ export declare const log: import("@sfmc-bds/sdk/logs").NodeServiceLogger;
11
8
  //# sourceMappingURL=log.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,eAAO,MAAM,GAAG,qCAGd,CAAC"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,eAAO,MAAM,GAAG,gDAGd,CAAC"}
package/dist/lib/log.js CHANGED
@@ -1,15 +1,14 @@
1
- /**
2
- * log.ts db-server 统一日志实例
3
- *
4
- * 通过 @sfmc-bds/logs 共享包接入,source = "db"
5
- * sfmc 主进程通过捕获本进程 stdout 汇聚展示。
6
- *
7
- * bare 模式: stdout 只输出纯 text,不加时间戳/source/level 前缀
8
- * ( sfmc 的 formatLog 统一添加,避免重复)。error 走 stderr。
9
- */
10
- import { createLogger, createStdoutSink } from "@sfmc-bds/sdk/logs";
11
- export const log = createLogger({
12
- source: "db",
13
- sinks: [createStdoutSink({ bare: true })],
1
+ import { createNodeServiceLogger } from "@sfmc-bds/sdk/logs";
2
+ import { logFile, resolveRuntimeRoot } from "@sfmc-bds/sdk/node/config";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const ROOT = resolveRuntimeRoot(resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", ".."));
6
+ const log = createNodeServiceLogger({
7
+ source: "db",
8
+ logPath: logFile(ROOT, "db")
14
9
  });
15
- //# sourceMappingURL=log.js.map
10
+ process.on("exit", () => log.close());
11
+ export {
12
+ log
13
+ };
14
+ //# sourceMappingURL=log.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,MAAM,CAAC,MAAM,GAAG,GAAG,YAAY,CAAC;IAC9B,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;CAC1C,CAAC,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/log.ts"],
4
+ "sourcesContent": ["/**\n * log.ts \u2014 db-server \u7EDF\u4E00\u65E5\u5FD7\u5B9E\u4F8B\n *\n * stdout bare + \u843D\u76D8 `<SFMC_ROOT>/.sfmc/logs/db.log`\u3002\n * bare: \u53EA\u8F93\u51FA\u7EAF text,\u7531 sfmc \u6355\u83B7\u540E\u7EDF\u4E00\u52A0\u524D\u7F00;error \u8D70 stderr\u3002\n */\n\nimport { createNodeServiceLogger } from \"@sfmc-bds/sdk/logs\";\nimport { logFile, resolveRuntimeRoot } from \"@sfmc-bds/sdk/node/config\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/** src/lib \u2192 \u4ED3\u6839(\u4E0E env.ts \u7684 src \u4E0A\u6EAF\u5DEE\u4E00\u5C42) */\nconst ROOT = resolveRuntimeRoot(resolve(dirname(fileURLToPath(import.meta.url)), \"..\", \"..\", \"..\"));\n\nexport const log = createNodeServiceLogger({\n source: \"db\",\n logPath: logFile(ROOT, \"db\"),\n});\n\nprocess.on(\"exit\", () => log.close());\n"],
5
+ "mappings": "AAOA,SAAS,+BAA+B;AACxC,SAAS,SAAS,0BAA0B;AAC5C,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAG9B,MAAM,OAAO,mBAAmB,QAAQ,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,MAAM,IAAI,CAAC;AAE3F,MAAM,MAAM,wBAAwB;AAAA,EACzC,QAAQ;AAAA,EACR,SAAS,QAAQ,MAAM,IAAI;AAC7B,CAAC;AAED,QAAQ,GAAG,QAAQ,MAAM,IAAI,MAAM,CAAC;",
6
+ "names": []
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"module-state.d.ts","sourceRoot":"","sources":["../../src/lib/module-state.ts"],"names":[],"mappings":"AAEA,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAI3D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAEvE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAgB,GAAG,WAAW,CAGpG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAE9F;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,GAC7C,WAAW,CASb"}
1
+ {"version":3,"file":"module-state.d.ts","sourceRoot":"","sources":["../../src/lib/module-state.ts"],"names":[],"mappings":"AAEA,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAS3D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAEvE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAgB,GAAG,WAAW,CAGpG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAE9F;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,GAC7C,WAAW,CASb"}
@@ -1,27 +1,38 @@
1
1
  import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
2
- export function loadModuleLock(filePath) {
3
- const data = readJson(filePath);
4
- const modules = data?.modules && typeof data.modules === "object" ? data.modules : {};
5
- return { version: 1, modules };
2
+ function loadModuleLock(filePath) {
3
+ const data = readJson(filePath);
4
+ const modules = data?.modules && typeof data.modules === "object" ? data.modules : {};
5
+ const lock = { version: 1, modules };
6
+ if (!data) {
7
+ saveModuleLock(filePath, lock);
8
+ }
9
+ return lock;
6
10
  }
7
- export function saveModuleLock(filePath, lock) {
8
- writeJson(filePath, lock);
11
+ function saveModuleLock(filePath, lock) {
12
+ writeJson(filePath, lock);
9
13
  }
10
- export function getModuleState(lock, id, defaults = {}) {
11
- const state = lock.modules[id];
12
- return state && typeof state === "object" ? state : defaults;
14
+ function getModuleState(lock, id, defaults = {}) {
15
+ const state = lock.modules[id];
16
+ return state && typeof state === "object" ? state : defaults;
13
17
  }
14
- export function isEnabled(lock, id, defaultValue = false) {
15
- return getModuleState(lock, id).enabled ?? defaultValue;
18
+ function isEnabled(lock, id, defaultValue = false) {
19
+ return getModuleState(lock, id).enabled ?? defaultValue;
16
20
  }
17
- export function updateModuleState(lock, id, patch) {
18
- const now = Date.now();
19
- const previous = getModuleState(lock, id);
20
- lock.modules[id] = {
21
- ...previous,
22
- ...patch,
23
- updatedAt: now,
24
- };
25
- return lock.modules[id];
21
+ function updateModuleState(lock, id, patch) {
22
+ const now = Date.now();
23
+ const previous = getModuleState(lock, id);
24
+ lock.modules[id] = {
25
+ ...previous,
26
+ ...patch,
27
+ updatedAt: now
28
+ };
29
+ return lock.modules[id];
26
30
  }
27
- //# sourceMappingURL=module-state.js.map
31
+ export {
32
+ getModuleState,
33
+ isEnabled,
34
+ loadModuleLock,
35
+ saveModuleLock,
36
+ updateModuleState
37
+ };
38
+ //# sourceMappingURL=module-state.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"module-state.js","sourceRoot":"","sources":["../../src/lib/module-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAShE,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAa,QAAQ,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAgB;IAC/D,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAgB,EAAE,EAAU,EAAE,WAAwB,EAAE;IACrF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/B,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAgB,EAAE,EAAU,EAAE,eAAwB,KAAK;IACnF,OAAO,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,YAAY,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAgB,EAChB,EAAU,EACV,KAA8C;IAE9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG;QACjB,GAAG,QAAQ;QACX,GAAG,KAAK;QACR,SAAS,EAAE,GAAG;KACf,CAAC;IACF,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/module-state.ts"],
4
+ "sourcesContent": ["import { readJson, writeJson } from \"@sfmc-bds/sdk/node/config\";\n\ninterface ModuleLock {\n version: number;\n modules: Record<string, { enabled?: boolean; updatedAt?: number }>;\n}\n\ntype ModuleState = ModuleLock[\"modules\"][string];\n\nexport function loadModuleLock(filePath: string): ModuleLock {\n const data = readJson<ModuleLock>(filePath);\n const modules = data?.modules && typeof data.modules === \"object\" ? data.modules : {};\n const lock: ModuleLock = { version: 1, modules };\n // \u7F3A\u6587\u4EF6\u65F6\u843D\u76D8\u7A7A\u9AA8\u67B6\uFF0C\u4FBF\u4E8E\u540E\u7EED enable/disable\uFF08\u4E0E configs \u540C\u5C5E\u672C\u5730\u72B6\u6001\uFF09\n if (!data) {\n saveModuleLock(filePath, lock);\n }\n return lock;\n}\n\nexport function saveModuleLock(filePath: string, lock: ModuleLock): void {\n writeJson(filePath, lock);\n}\n\nexport function getModuleState(lock: ModuleLock, id: string, defaults: ModuleState = {}): ModuleState {\n const state = lock.modules[id];\n return state && typeof state === \"object\" ? state : defaults;\n}\n\nexport function isEnabled(lock: ModuleLock, id: string, defaultValue: boolean = false): boolean {\n return getModuleState(lock, id).enabled ?? defaultValue;\n}\n\nexport function updateModuleState(\n lock: ModuleLock,\n id: string,\n patch: Partial<Omit<ModuleState, \"updatedAt\">>\n): ModuleState {\n const now = Date.now();\n const previous = getModuleState(lock, id);\n lock.modules[id] = {\n ...previous,\n ...patch,\n updatedAt: now,\n };\n return lock.modules[id];\n}"],
5
+ "mappings": "AAAA,SAAS,UAAU,iBAAiB;AAS7B,SAAS,eAAe,UAA8B;AAC3D,QAAM,OAAO,SAAqB,QAAQ;AAC1C,QAAM,UAAU,MAAM,WAAW,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,CAAC;AACpF,QAAM,OAAmB,EAAE,SAAS,GAAG,QAAQ;AAE/C,MAAI,CAAC,MAAM;AACT,mBAAe,UAAU,IAAI;AAAA,EAC/B;AACA,SAAO;AACT;AAEO,SAAS,eAAe,UAAkB,MAAwB;AACvE,YAAU,UAAU,IAAI;AAC1B;AAEO,SAAS,eAAe,MAAkB,IAAY,WAAwB,CAAC,GAAgB;AACpG,QAAM,QAAQ,KAAK,QAAQ,EAAE;AAC7B,SAAO,SAAS,OAAO,UAAU,WAAW,QAAQ;AACtD;AAEO,SAAS,UAAU,MAAkB,IAAY,eAAwB,OAAgB;AAC9F,SAAO,eAAe,MAAM,EAAE,EAAE,WAAW;AAC7C;AAEO,SAAS,kBACd,MACA,IACA,OACa;AACb,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,WAAW,eAAe,MAAM,EAAE;AACxC,OAAK,QAAQ,EAAE,IAAI;AAAA,IACjB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,WAAW;AAAA,EACb;AACA,SAAO,KAAK,QAAQ,EAAE;AACxB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * order-by.ts — 规范化 QueryOptions.orderBy(DRY + LSP)
3
+ *
4
+ * SDK 权威形态是 `{ field, dir? }`(见 @sfmc-bds/sdk/db OrderBy);
5
+ * tx-runner 早期用过 `{ col, dir? }`。两端必须互通,否则
6
+ * `ORDER BY "undefined"` / `orderBy bad column` 静默炸。
7
+ */
8
+ export type NormalizedOrder = {
9
+ col: string;
10
+ dir: "asc" | "desc";
11
+ };
12
+ /**
13
+ * 把 SDK `field` / 遗留 `col`、单值 / 数组 统一成 `{col,dir}[]`。
14
+ * @throws 缺列名或类型非法时
15
+ */
16
+ export declare function normalizeOrderBy(orderBy: unknown): NormalizedOrder[];
17
+ //# sourceMappingURL=order-by.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order-by.d.ts","sourceRoot":"","sources":["../../src/lib/order-by.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,EAAE,CAmBpE"}
@@ -0,0 +1,24 @@
1
+ function normalizeOrderBy(orderBy) {
2
+ if (orderBy == null) return [];
3
+ const list = Array.isArray(orderBy) ? orderBy : [orderBy];
4
+ const out = [];
5
+ for (const item of list) {
6
+ if (item == null || typeof item !== "object") {
7
+ throw new Error("[tx] orderBy \u9879\u5FC5\u987B\u662F\u5BF9\u8C61");
8
+ }
9
+ const rec = item;
10
+ const col = rec.col ?? rec.field;
11
+ if (typeof col !== "string" || !col) {
12
+ throw new Error("[tx] orderBy \u7F3A\u5C11 field/col");
13
+ }
14
+ out.push({
15
+ col,
16
+ dir: rec.dir === "desc" ? "desc" : "asc"
17
+ });
18
+ }
19
+ return out;
20
+ }
21
+ export {
22
+ normalizeOrderBy
23
+ };
24
+ //# sourceMappingURL=order-by.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/order-by.ts"],
4
+ "sourcesContent": ["/**\n * order-by.ts \u2014 \u89C4\u8303\u5316 QueryOptions.orderBy(DRY + LSP)\n *\n * SDK \u6743\u5A01\u5F62\u6001\u662F `{ field, dir? }`(\u89C1 @sfmc-bds/sdk/db OrderBy);\n * tx-runner \u65E9\u671F\u7528\u8FC7 `{ col, dir? }`\u3002\u4E24\u7AEF\u5FC5\u987B\u4E92\u901A,\u5426\u5219\n * `ORDER BY \"undefined\"` / `orderBy bad column` \u9759\u9ED8\u70B8\u3002\n */\n\nexport type NormalizedOrder = { col: string; dir: \"asc\" | \"desc\" };\n\n/**\n * \u628A SDK `field` / \u9057\u7559 `col`\u3001\u5355\u503C / \u6570\u7EC4 \u7EDF\u4E00\u6210 `{col,dir}[]`\u3002\n * @throws \u7F3A\u5217\u540D\u6216\u7C7B\u578B\u975E\u6CD5\u65F6\n */\nexport function normalizeOrderBy(orderBy: unknown): NormalizedOrder[] {\n if (orderBy == null) return [];\n const list = Array.isArray(orderBy) ? orderBy : [orderBy];\n const out: NormalizedOrder[] = [];\n for (const item of list) {\n if (item == null || typeof item !== \"object\") {\n throw new Error(\"[tx] orderBy \u9879\u5FC5\u987B\u662F\u5BF9\u8C61\");\n }\n const rec = item as Record<string, unknown>;\n const col = rec.col ?? rec.field;\n if (typeof col !== \"string\" || !col) {\n throw new Error(\"[tx] orderBy \u7F3A\u5C11 field/col\");\n }\n out.push({\n col,\n dir: rec.dir === \"desc\" ? \"desc\" : \"asc\",\n });\n }\n return out;\n}\n"],
5
+ "mappings": "AAcO,SAAS,iBAAiB,SAAqC;AACpE,MAAI,WAAW,KAAM,QAAO,CAAC;AAC7B,QAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACxD,QAAM,MAAyB,CAAC;AAChC,aAAW,QAAQ,MAAM;AACvB,QAAI,QAAQ,QAAQ,OAAO,SAAS,UAAU;AAC5C,YAAM,IAAI,MAAM,mDAAqB;AAAA,IACvC;AACA,UAAM,MAAM;AACZ,UAAM,MAAM,IAAI,OAAO,IAAI;AAC3B,QAAI,OAAO,QAAQ,YAAY,CAAC,KAAK;AACnC,YAAM,IAAI,MAAM,qCAA2B;AAAA,IAC7C;AACA,QAAI,KAAK;AAAA,MACP;AAAA,MACA,KAAK,IAAI,QAAQ,SAAS,SAAS;AAAA,IACrC,CAAC;AAAA,EACH;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,34 +1,19 @@
1
- /**
2
- * 解析 Node.js 版本字符串,提取主版本号、次版本号和补丁号。
3
- * @param version - 版本字符串(可选),例如 "v14.17.0" 或 "14.17.0"。默认为 process.versions.node。
4
- * @returns 包含 major, minor, patch 的对象,若格式无效则返回 null。
5
- */
6
1
  import { log } from "./log.js";
7
- export function parseNodeVersion(version = process.versions.node) {
8
- const match = String(version).match(/^v?(\d+)\.(\d+)\.(\d+)/);
9
- return match ? { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) } : null;
2
+ function parseNodeVersion(version = process.versions.node) {
3
+ const match = String(version).match(/^v?(\d+)\.(\d+)\.(\d+)/);
4
+ return match ? { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) } : null;
10
5
  }
11
- /**
12
- * 校验当前 Node.js 版本是否满足最低要求。
13
- *
14
- * 默认下限 22.13 —— `node:sqlite`(db-server 的核心依赖)在 22.5.0–22.12.x
15
- * 仍需 `--experimental-sqlite` CLI 参数才能加载,未带参数时会在 import 阶段
16
- * 直接抛出 `ERR_UNKNOWN_BUILTIN_MODULE`;该模块从 22.13.0 起默认可用(仍标记为
17
- * experimental)。注意:由于 ESM 静态 import 会在本文件被调用之前完成解析,
18
- * 这里的检查无法拦截 `./lib/sqlite.ts` 自身的 import 崩溃,只能作为其余场景
19
- * 的兜底防线与版本要求的单一事实来源。
20
- *
21
- * @param {number} [minMajor=22]
22
- * @param {number} [minMinor=13]
23
- * @return {*} {boolean}
24
- */
25
- export function assertNodeVersion(minMajor = 22, minMinor = 13) {
26
- const actual = parseNodeVersion();
27
- if (!actual || actual.major < minMajor || (actual.major === minMajor && actual.minor < minMinor)) {
28
- log.error(`[Runtime] Node.js ${minMajor}.${minMinor}+ is required; found ${process.versions.node}`);
29
- process.exitCode = 2;
30
- return false;
31
- }
32
- return true;
6
+ function assertNodeVersion(minMajor = 22, minMinor = 13) {
7
+ const actual = parseNodeVersion();
8
+ if (!actual || actual.major < minMajor || actual.major === minMajor && actual.minor < minMinor) {
9
+ log.error(`[Runtime] Node.js ${minMajor}.${minMinor}+ is required; found ${process.versions.node}`);
10
+ process.exitCode = 2;
11
+ return false;
12
+ }
13
+ return true;
33
14
  }
34
- //# sourceMappingURL=runtime.js.map
15
+ export {
16
+ assertNodeVersion,
17
+ parseNodeVersion
18
+ };
19
+ //# sourceMappingURL=runtime.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/lib/runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,UAAU,gBAAgB,CAAC,UAAkB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAKtE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC9D,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtG,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB,EAAE,EAAE,WAAmB,EAAE;IAC5E,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,GAAG,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC;QACjG,GAAG,CAAC,KAAK,CAAC,qBAAqB,QAAQ,IAAI,QAAQ,wBAAwB,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACpG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/runtime.ts"],
4
+ "sourcesContent": ["/**\n * \u89E3\u6790 Node.js \u7248\u672C\u5B57\u7B26\u4E32\uFF0C\u63D0\u53D6\u4E3B\u7248\u672C\u53F7\u3001\u6B21\u7248\u672C\u53F7\u548C\u8865\u4E01\u53F7\u3002\n * @param version - \u7248\u672C\u5B57\u7B26\u4E32\uFF08\u53EF\u9009\uFF09\uFF0C\u4F8B\u5982 \"v14.17.0\" \u6216 \"14.17.0\"\u3002\u9ED8\u8BA4\u4E3A process.versions.node\u3002\n * @returns \u5305\u542B major, minor, patch \u7684\u5BF9\u8C61\uFF0C\u82E5\u683C\u5F0F\u65E0\u6548\u5219\u8FD4\u56DE null\u3002\n */\nimport { log } from \"./log.js\";\n\nexport function parseNodeVersion(version: string = process.versions.node): {\n major: number;\n minor: number;\n patch: number;\n} | null {\n const match = String(version).match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)/);\n return match ? { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) } : null;\n}\n\n/**\n * \u6821\u9A8C\u5F53\u524D Node.js \u7248\u672C\u662F\u5426\u6EE1\u8DB3\u6700\u4F4E\u8981\u6C42\u3002\n *\n * \u9ED8\u8BA4\u4E0B\u9650 22.13 \u2014\u2014 `node:sqlite`\uFF08db-server \u7684\u6838\u5FC3\u4F9D\u8D56\uFF09\u5728 22.5.0\u201322.12.x\n * \u4ECD\u9700 `--experimental-sqlite` CLI \u53C2\u6570\u624D\u80FD\u52A0\u8F7D\uFF0C\u672A\u5E26\u53C2\u6570\u65F6\u4F1A\u5728 import \u9636\u6BB5\n * \u76F4\u63A5\u629B\u51FA `ERR_UNKNOWN_BUILTIN_MODULE`\uFF1B\u8BE5\u6A21\u5757\u4ECE 22.13.0 \u8D77\u9ED8\u8BA4\u53EF\u7528\uFF08\u4ECD\u6807\u8BB0\u4E3A\n * experimental\uFF09\u3002\u6CE8\u610F\uFF1A\u7531\u4E8E ESM \u9759\u6001 import \u4F1A\u5728\u672C\u6587\u4EF6\u88AB\u8C03\u7528\u4E4B\u524D\u5B8C\u6210\u89E3\u6790\uFF0C\n * \u8FD9\u91CC\u7684\u68C0\u67E5\u65E0\u6CD5\u62E6\u622A `./lib/sqlite.ts` \u81EA\u8EAB\u7684 import \u5D29\u6E83\uFF0C\u53EA\u80FD\u4F5C\u4E3A\u5176\u4F59\u573A\u666F\n * \u7684\u515C\u5E95\u9632\u7EBF\u4E0E\u7248\u672C\u8981\u6C42\u7684\u5355\u4E00\u4E8B\u5B9E\u6765\u6E90\u3002\n *\n * @param {number} [minMajor=22]\n * @param {number} [minMinor=13]\n * @return {*} {boolean}\n */\nexport function assertNodeVersion(minMajor: number = 22, minMinor: number = 13): boolean {\n const actual = parseNodeVersion();\n if (!actual || actual.major < minMajor || (actual.major === minMajor && actual.minor < minMinor)) {\n log.error(`[Runtime] Node.js ${minMajor}.${minMinor}+ is required; found ${process.versions.node}`);\n process.exitCode = 2;\n return false;\n }\n return true;\n}\n"],
5
+ "mappings": "AAKA,SAAS,WAAW;AAEb,SAAS,iBAAiB,UAAkB,QAAQ,SAAS,MAI3D;AACP,QAAM,QAAQ,OAAO,OAAO,EAAE,MAAM,wBAAwB;AAC5D,SAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE,IAAI;AACjG;AAgBO,SAAS,kBAAkB,WAAmB,IAAI,WAAmB,IAAa;AACvF,QAAM,SAAS,iBAAiB;AAChC,MAAI,CAAC,UAAU,OAAO,QAAQ,YAAa,OAAO,UAAU,YAAY,OAAO,QAAQ,UAAW;AAChG,QAAI,MAAM,qBAAqB,QAAQ,IAAI,QAAQ,wBAAwB,QAAQ,SAAS,IAAI,EAAE;AAClG,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,30 +1,12 @@
1
- /**
2
- * lib/sql-helpers.ts — SQL 构造辅助
3
- *
4
- * sql-template-strings 会把每一次 ${} 插值都变成 `?` 绑定值。
5
- * 表名/列名等信任标识符必须嵌入 SQL 文本,不能走绑定 —— 否则会出现
6
- * `FROM ?` → `near "?": syntax error`(见 economy 域修复)。
7
- */
8
1
  import { SQL } from "sql-template-strings";
9
- /**
10
- * 构造「标识符已嵌入、值走 ?」的查询。
11
- * 表名等信任常量用模板字符串嵌入;用户输入只放进 values。
12
- *
13
- * @example
14
- * sql(`SELECT * FROM ${TABLE} WHERE id = ?`, [id])
15
- */
16
- export function sql(text, values = []) {
17
- return { sql: text, values };
2
+ function sql(text, values = []) {
3
+ return { sql: text, values };
18
4
  }
19
- /**
20
- * 把一段静态 SQL 文本包装成 SQLStatement,仅可与 `.append(...)` 合用。
21
- *
22
- * 警告(LSP):切勿写成 `SQL\`... FROM ${raw(table)} ...\`` —— 模板插值仍会变成 `?`,
23
- * 与直接插值表名同病。正确用法:
24
- * SQL`SELECT * FROM `.append(raw(TABLE)).append(SQL` WHERE id = ${id}`)
25
- * 纯字符串 `.append(TABLE)` 效果相同;优先用 {@link sql}。
26
- */
27
- export function raw(text) {
28
- return SQL([text]);
5
+ function raw(text) {
6
+ return SQL([text]);
29
7
  }
30
- //# sourceMappingURL=sql-helpers.js.map
8
+ export {
9
+ raw,
10
+ sql
11
+ };
12
+ //# sourceMappingURL=sql-helpers.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"sql-helpers.js","sourceRoot":"","sources":["../../src/lib/sql-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,GAAG,EAAqB,MAAM,sBAAsB,CAAC;AAK9D;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,SAAoB,EAAE;IACtD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAiB,CAAC;AACrC,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/sql-helpers.ts"],
4
+ "sourcesContent": ["/**\n * lib/sql-helpers.ts \u2014 SQL \u6784\u9020\u8F85\u52A9\n *\n * sql-template-strings \u4F1A\u628A\u6BCF\u4E00\u6B21 ${} \u63D2\u503C\u90FD\u53D8\u6210 `?` \u7ED1\u5B9A\u503C\u3002\n * \u8868\u540D/\u5217\u540D\u7B49\u4FE1\u4EFB\u6807\u8BC6\u7B26\u5FC5\u987B\u5D4C\u5165 SQL \u6587\u672C,\u4E0D\u80FD\u8D70\u7ED1\u5B9A \u2014\u2014 \u5426\u5219\u4F1A\u51FA\u73B0\n * `FROM ?` \u2192 `near \"?\": syntax error`(\u89C1 economy \u57DF\u4FEE\u590D)\u3002\n */\n\nimport { SQL, type SQLStatement } from \"sql-template-strings\";\n\n/** \u53C2\u6570\u5316\u67E5\u8BE2\u4FE1\u5C01,\u4E0E createQuery / AnyQuery \u7684\u683C\u5F0F 2 \u5BF9\u9F50 */\nexport type BoundSql = { sql: string; values: unknown[] };\n\n/**\n * \u6784\u9020\u300C\u6807\u8BC6\u7B26\u5DF2\u5D4C\u5165\u3001\u503C\u8D70 ?\u300D\u7684\u67E5\u8BE2\u3002\n * \u8868\u540D\u7B49\u4FE1\u4EFB\u5E38\u91CF\u7528\u6A21\u677F\u5B57\u7B26\u4E32\u5D4C\u5165;\u7528\u6237\u8F93\u5165\u53EA\u653E\u8FDB values\u3002\n *\n * @example\n * sql(`SELECT * FROM ${TABLE} WHERE id = ?`, [id])\n */\nexport function sql(text: string, values: unknown[] = []): BoundSql {\n return { sql: text, values };\n}\n\n/**\n * \u628A\u4E00\u6BB5\u9759\u6001 SQL \u6587\u672C\u5305\u88C5\u6210 SQLStatement,\u4EC5\u53EF\u4E0E `.append(...)` \u5408\u7528\u3002\n *\n * \u8B66\u544A(LSP):\u5207\u52FF\u5199\u6210 `SQL\\`... FROM ${raw(table)} ...\\`` \u2014\u2014 \u6A21\u677F\u63D2\u503C\u4ECD\u4F1A\u53D8\u6210 `?`,\n * \u4E0E\u76F4\u63A5\u63D2\u503C\u8868\u540D\u540C\u75C5\u3002\u6B63\u786E\u7528\u6CD5:\n * SQL`SELECT * FROM `.append(raw(TABLE)).append(SQL` WHERE id = ${id}`)\n * \u7EAF\u5B57\u7B26\u4E32 `.append(TABLE)` \u6548\u679C\u76F8\u540C;\u4F18\u5148\u7528 {@link sql}\u3002\n */\nexport function raw(text: string): SQLStatement {\n return SQL([text]) as SQLStatement;\n}\n"],
5
+ "mappings": "AAQA,SAAS,WAA8B;AAYhC,SAAS,IAAI,MAAc,SAAoB,CAAC,GAAa;AAClE,SAAO,EAAE,KAAK,MAAM,OAAO;AAC7B;AAUO,SAAS,IAAI,MAA4B;AAC9C,SAAO,IAAI,CAAC,IAAI,CAAC;AACnB;",
6
+ "names": []
7
+ }