@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.
- package/README.md +1 -1
- package/dist/db-tables.js +16 -17
- package/dist/db-tables.js.map +7 -1
- package/dist/domain/bridge.js +54 -77
- package/dist/domain/bridge.js.map +7 -1
- package/dist/domain/economy.d.ts +83 -2
- package/dist/domain/economy.d.ts.map +1 -1
- package/dist/domain/economy.js +292 -281
- package/dist/domain/economy.js.map +7 -1
- package/dist/domain/schema.js +480 -426
- package/dist/domain/schema.js.map +7 -1
- package/dist/domain/transaction.js +32 -80
- package/dist/domain/transaction.js.map +7 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +85 -84
- package/dist/env.js.map +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +218 -240
- package/dist/index.js.map +7 -1
- package/dist/lib/http.js +30 -39
- package/dist/lib/http.js.map +7 -1
- package/dist/lib/idempotency-store.js +34 -47
- package/dist/lib/idempotency-store.js.map +7 -1
- package/dist/lib/idempotency.js +8 -13
- package/dist/lib/idempotency.js.map +7 -1
- package/dist/lib/identifiers.js +18 -14
- package/dist/lib/identifiers.js.map +7 -1
- package/dist/lib/log.d.ts +3 -6
- package/dist/lib/log.d.ts.map +1 -1
- package/dist/lib/log.js +13 -14
- package/dist/lib/log.js.map +7 -1
- package/dist/lib/module-state.d.ts.map +1 -1
- package/dist/lib/module-state.js +32 -21
- package/dist/lib/module-state.js.map +7 -1
- package/dist/lib/order-by.d.ts +17 -0
- package/dist/lib/order-by.d.ts.map +1 -0
- package/dist/lib/order-by.js +24 -0
- package/dist/lib/order-by.js.map +7 -0
- package/dist/lib/runtime.js +16 -31
- package/dist/lib/runtime.js.map +7 -1
- package/dist/lib/sql-helpers.js +9 -27
- package/dist/lib/sql-helpers.js.map +7 -1
- package/dist/lib/sqlite.js +40 -52
- package/dist/lib/sqlite.js.map +7 -1
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +154 -195
- package/dist/manifest-loader.js.map +7 -1
- package/dist/manifest.d.ts +3 -7
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +76 -115
- package/dist/manifest.js.map +7 -1
- package/dist/module-auth.d.ts +17 -6
- package/dist/module-auth.d.ts.map +1 -1
- package/dist/module-auth.js +93 -107
- package/dist/module-auth.js.map +7 -1
- package/dist/module-runtime-sync.d.ts +37 -0
- package/dist/module-runtime-sync.d.ts.map +1 -0
- package/dist/module-runtime-sync.js +54 -0
- package/dist/module-runtime-sync.js.map +7 -0
- package/dist/permission-gate.d.ts.map +1 -1
- package/dist/permission-gate.js +55 -86
- package/dist/permission-gate.js.map +7 -1
- package/dist/routes/_shared.d.ts +7 -2
- package/dist/routes/_shared.d.ts.map +1 -1
- package/dist/routes/_shared.js +16 -25
- package/dist/routes/_shared.js.map +7 -1
- package/dist/routes/config.d.ts +11 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +167 -213
- package/dist/routes/config.js.map +7 -1
- package/dist/routes/db-routes.d.ts +6 -10
- package/dist/routes/db-routes.d.ts.map +1 -1
- package/dist/routes/db-routes.js +198 -172
- package/dist/routes/db-routes.js.map +7 -1
- package/dist/routes/health.js +15 -20
- package/dist/routes/health.js.map +7 -1
- package/dist/routes/messages.d.ts.map +1 -1
- package/dist/routes/messages.js +56 -63
- package/dist/routes/messages.js.map +7 -1
- package/dist/routes/module-config-routes.d.ts.map +1 -1
- package/dist/routes/module-config-routes.js +92 -111
- package/dist/routes/module-config-routes.js.map +7 -1
- package/dist/routes/modules.d.ts.map +1 -1
- package/dist/routes/modules.js +82 -88
- package/dist/routes/modules.js.map +7 -1
- package/dist/routes/service-routes.d.ts.map +1 -1
- package/dist/routes/service-routes.js +54 -61
- package/dist/routes/service-routes.js.map +7 -1
- package/dist/runtime.test.js +248 -49
- package/dist/runtime.test.js.map +7 -1
- package/dist/schema-registry.d.ts.map +1 -1
- package/dist/schema-registry.js +119 -160
- package/dist/schema-registry.js.map +7 -1
- package/dist/server.js +69 -72
- package/dist/server.js.map +7 -1
- package/dist/service-registry.d.ts.map +1 -1
- package/dist/service-registry.js +60 -67
- package/dist/service-registry.js.map +7 -1
- package/dist/services/builtin-handlers.d.ts +4 -0
- package/dist/services/builtin-handlers.d.ts.map +1 -1
- package/dist/services/builtin-handlers.js +34 -20
- package/dist/services/builtin-handlers.js.map +7 -1
- package/dist/services/economy-handlers.js +143 -132
- package/dist/services/economy-handlers.js.map +7 -1
- package/dist/tx-runner.d.ts +35 -11
- package/dist/tx-runner.d.ts.map +1 -1
- package/dist/tx-runner.js +293 -250
- package/dist/tx-runner.js.map +7 -1
- package/dist/where.js +71 -94
- package/dist/where.js.map +7 -1
- package/package.json +4 -4
package/dist/lib/http.js
CHANGED
|
@@ -1,43 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {};
|
|
19
|
-
}
|
|
5
|
+
function parseBody(raw) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(raw || "{}");
|
|
8
|
+
} catch {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
20
11
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
41
|
-
|
|
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
|
-
|
|
29
|
+
export {
|
|
30
|
+
body,
|
|
31
|
+
json,
|
|
32
|
+
parseBody
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=http.js.map
|
package/dist/lib/http.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
33
|
+
export {
|
|
34
|
+
createIdempotencyStore
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=idempotency-store.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
+
}
|
package/dist/lib/idempotency.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
6
|
+
export {
|
|
7
|
+
isValidIdempotencyKey
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=idempotency.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
+
}
|
package/dist/lib/identifiers.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
class IdentifierError extends Error {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
code;
|
|
3
|
+
constructor(message, code) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
Object.setPrototypeOf(this, IdentifierError.prototype);
|
|
7
|
+
}
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
-
|
|
15
|
+
function quoteIdentifier(value, label) {
|
|
16
|
+
return `"${assertIdentifier(value, label)}"`;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
export {
|
|
19
|
+
assertIdentifier,
|
|
20
|
+
quoteIdentifier
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=identifiers.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
-
*
|
|
5
|
-
* sfmc
|
|
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").
|
|
7
|
+
export declare const log: import("@sfmc-bds/sdk/logs").NodeServiceLogger;
|
|
11
8
|
//# sourceMappingURL=log.d.ts.map
|
package/dist/lib/log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
10
|
+
process.on("exit", () => log.close());
|
|
11
|
+
export {
|
|
12
|
+
log
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=log.js.map
|
package/dist/lib/log.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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,
|
|
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"}
|
package/dist/lib/module-state.js
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
11
|
+
function saveModuleLock(filePath, lock) {
|
|
12
|
+
writeJson(filePath, lock);
|
|
9
13
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
function getModuleState(lock, id, defaults = {}) {
|
|
15
|
+
const state = lock.modules[id];
|
|
16
|
+
return state && typeof state === "object" ? state : defaults;
|
|
13
17
|
}
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
function isEnabled(lock, id, defaultValue = false) {
|
|
19
|
+
return getModuleState(lock, id).enabled ?? defaultValue;
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
31
|
+
export {
|
|
32
|
+
getModuleState,
|
|
33
|
+
isEnabled,
|
|
34
|
+
loadModuleLock,
|
|
35
|
+
saveModuleLock,
|
|
36
|
+
updateModuleState
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=module-state.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
+
}
|
package/dist/lib/runtime.js
CHANGED
|
@@ -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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
15
|
+
export {
|
|
16
|
+
assertNodeVersion,
|
|
17
|
+
parseNodeVersion
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=runtime.js.map
|
package/dist/lib/runtime.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
+
}
|
package/dist/lib/sql-helpers.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
8
|
+
export {
|
|
9
|
+
raw,
|
|
10
|
+
sql
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=sql-helpers.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
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
|
+
}
|