@sfmc-bds/db-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/db-tables.d.ts +13 -0
- package/dist/db-tables.d.ts.map +1 -0
- package/dist/db-tables.js +35 -0
- package/dist/db-tables.js.map +1 -0
- package/dist/domain/bridge.d.ts +48 -0
- package/dist/domain/bridge.d.ts.map +1 -0
- package/dist/domain/bridge.js +82 -0
- package/dist/domain/bridge.js.map +1 -0
- package/dist/domain/economy.d.ts +120 -0
- package/dist/domain/economy.d.ts.map +1 -0
- package/dist/domain/economy.js +321 -0
- package/dist/domain/economy.js.map +1 -0
- package/dist/domain/schema.d.ts +26 -0
- package/dist/domain/schema.d.ts.map +1 -0
- package/dist/domain/schema.js +462 -0
- package/dist/domain/schema.js.map +1 -0
- package/dist/domain/transaction.d.ts +67 -0
- package/dist/domain/transaction.d.ts.map +1 -0
- package/dist/domain/transaction.js +85 -0
- package/dist/domain/transaction.js.map +1 -0
- package/dist/env.d.ts +22 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +94 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +313 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/http.d.ts +18 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +43 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/idempotency-store.d.ts +28 -0
- package/dist/lib/idempotency-store.d.ts.map +1 -0
- package/dist/lib/idempotency-store.js +49 -0
- package/dist/lib/idempotency-store.js.map +1 -0
- package/dist/lib/idempotency.d.ts +9 -0
- package/dist/lib/idempotency.d.ts.map +1 -0
- package/dist/lib/idempotency.js +14 -0
- package/dist/lib/idempotency.js.map +1 -0
- package/dist/lib/identifiers.d.ts +3 -0
- package/dist/lib/identifiers.d.ts.map +1 -0
- package/dist/lib/identifiers.js +18 -0
- package/dist/lib/identifiers.js.map +1 -0
- package/dist/lib/log.d.ts +11 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +15 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/lib/module-state.d.ts +15 -0
- package/dist/lib/module-state.d.ts.map +1 -0
- package/dist/lib/module-state.js +27 -0
- package/dist/lib/module-state.js.map +1 -0
- package/dist/lib/runtime.d.ts +21 -0
- package/dist/lib/runtime.d.ts.map +1 -0
- package/dist/lib/runtime.js +34 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/sql-helpers.d.ts +31 -0
- package/dist/lib/sql-helpers.d.ts.map +1 -0
- package/dist/lib/sql-helpers.js +30 -0
- package/dist/lib/sql-helpers.js.map +1 -0
- package/dist/lib/sqlite.d.ts +20 -0
- package/dist/lib/sqlite.d.ts.map +1 -0
- package/dist/lib/sqlite.js +59 -0
- package/dist/lib/sqlite.js.map +1 -0
- package/dist/manifest-loader.d.ts +69 -0
- package/dist/manifest-loader.d.ts.map +1 -0
- package/dist/manifest-loader.js +212 -0
- package/dist/manifest-loader.js.map +1 -0
- package/dist/manifest.d.ts +76 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +128 -0
- package/dist/manifest.js.map +1 -0
- package/dist/module-auth.d.ts +58 -0
- package/dist/module-auth.d.ts.map +1 -0
- package/dist/module-auth.js +118 -0
- package/dist/module-auth.js.map +1 -0
- package/dist/permission-gate.d.ts +53 -0
- package/dist/permission-gate.d.ts.map +1 -0
- package/dist/permission-gate.js +94 -0
- package/dist/permission-gate.js.map +1 -0
- package/dist/routes/_shared.d.ts +68 -0
- package/dist/routes/_shared.d.ts.map +1 -0
- package/dist/routes/_shared.js +27 -0
- package/dist/routes/_shared.js.map +1 -0
- package/dist/routes/config.d.ts +27 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +236 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/db-routes.d.ts +38 -0
- package/dist/routes/db-routes.d.ts.map +1 -0
- package/dist/routes/db-routes.js +186 -0
- package/dist/routes/db-routes.js.map +1 -0
- package/dist/routes/health.d.ts +10 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +23 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/messages.d.ts +23 -0
- package/dist/routes/messages.d.ts.map +1 -0
- package/dist/routes/messages.js +72 -0
- package/dist/routes/messages.js.map +1 -0
- package/dist/routes/module-config-routes.d.ts +31 -0
- package/dist/routes/module-config-routes.d.ts.map +1 -0
- package/dist/routes/module-config-routes.js +128 -0
- package/dist/routes/module-config-routes.js.map +1 -0
- package/dist/routes/modules.d.ts +34 -0
- package/dist/routes/modules.d.ts.map +1 -0
- package/dist/routes/modules.js +92 -0
- package/dist/routes/modules.js.map +1 -0
- package/dist/routes/service-routes.d.ts +26 -0
- package/dist/routes/service-routes.d.ts.map +1 -0
- package/dist/routes/service-routes.js +68 -0
- package/dist/routes/service-routes.js.map +1 -0
- package/dist/runtime.test.d.ts +2 -0
- package/dist/runtime.test.d.ts.map +1 -0
- package/dist/runtime.test.js +66 -0
- package/dist/runtime.test.js.map +1 -0
- package/dist/schema-registry.d.ts +63 -0
- package/dist/schema-registry.d.ts.map +1 -0
- package/dist/schema-registry.js +178 -0
- package/dist/schema-registry.js.map +1 -0
- package/dist/server.d.ts +27 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +82 -0
- package/dist/server.js.map +1 -0
- package/dist/service-registry.d.ts +46 -0
- package/dist/service-registry.d.ts.map +1 -0
- package/dist/service-registry.js +73 -0
- package/dist/service-registry.js.map +1 -0
- package/dist/services/builtin-handlers.d.ts +22 -0
- package/dist/services/builtin-handlers.d.ts.map +1 -0
- package/dist/services/builtin-handlers.js +23 -0
- package/dist/services/builtin-handlers.js.map +1 -0
- package/dist/services/economy-handlers.d.ts +14 -0
- package/dist/services/economy-handlers.d.ts.map +1 -0
- package/dist/services/economy-handlers.js +144 -0
- package/dist/services/economy-handlers.js.map +1 -0
- package/dist/tx-runner.d.ts +144 -0
- package/dist/tx-runner.d.ts.map +1 -0
- package/dist/tx-runner.js +273 -0
- package/dist/tx-runner.js.map +1 -0
- package/dist/where.d.ts +48 -0
- package/dist/where.d.ts.map +1 -0
- package/dist/where.js +107 -0
- package/dist/where.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* domain/transaction.ts — SQLite 事务执行器 + 共享业务结果类型
|
|
3
|
+
*
|
|
4
|
+
* 事务描述:
|
|
5
|
+
* - withTransaction(db, fn) IMMEDIATE 事务包裹器
|
|
6
|
+
* 自动 BEGIN IMMEDIATE / COMMIT / ROLLBACK,
|
|
7
|
+
* 异常时 ROLLBACK 并重新抛错;支持同步 + async 回调
|
|
8
|
+
* - withResult(db, fn) withTransaction 的语义别名(供"业务失败但不抛错"
|
|
9
|
+
* 的场景,函数返回 TxResult 自己判 ok)
|
|
10
|
+
*
|
|
11
|
+
* 共享类型:
|
|
12
|
+
* - Transactional 事务执行器所需的最小接口(Pick<DatabaseSync, "exec">),
|
|
13
|
+
* 让领域函数能接受 node:sqlite DatabaseSync 或 routes 注入的
|
|
14
|
+
* 窄化包装
|
|
15
|
+
* - TxResult<T> 领域事务统一结果类型:{ ok:true, data } | { ok:false, error, status, extra? }
|
|
16
|
+
* 所有领域模块(land / coop / economy / redpacket)都从此处引用,
|
|
17
|
+
* 避免跨域循环依赖
|
|
18
|
+
*
|
|
19
|
+
* 用法:
|
|
20
|
+
* const result = withTransaction(db, () => {
|
|
21
|
+
* const rows = query(SQL`SELECT 1`);
|
|
22
|
+
* return rows[0];
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* 行为约定:
|
|
26
|
+
* - return value → COMMIT 后透传给调用方
|
|
27
|
+
* - throw → ROLLBACK 后重新抛错
|
|
28
|
+
* - return Promise → await 后再 COMMIT / ROLLBACK
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* 在 IMMEDIATE 事务包裹下运行回调。回调内任何抛出都会触发 ROLLBACK 并重新抛错。
|
|
32
|
+
*
|
|
33
|
+
* 行为约定:
|
|
34
|
+
* - return value → COMMIT 后透传给调用方
|
|
35
|
+
* - throw → ROLLBACK 后重新抛错
|
|
36
|
+
* - return Promise → await 后再 COMMIT / ROLLBACK
|
|
37
|
+
*/
|
|
38
|
+
export function withTransaction(db, fn) {
|
|
39
|
+
db.exec("BEGIN IMMEDIATE");
|
|
40
|
+
try {
|
|
41
|
+
const out = fn();
|
|
42
|
+
if (out instanceof Promise) {
|
|
43
|
+
// 同步/异步混合:等待 Promise 后决定提交
|
|
44
|
+
return Promise.resolve(out).then((v) => {
|
|
45
|
+
db.exec("COMMIT");
|
|
46
|
+
return v;
|
|
47
|
+
}, (err) => {
|
|
48
|
+
try {
|
|
49
|
+
db.exec("ROLLBACK");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* ignore secondary failures */
|
|
53
|
+
}
|
|
54
|
+
throw err;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
db.exec("COMMIT");
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
try {
|
|
62
|
+
db.exec("ROLLBACK");
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
/* ignore rollback failures */
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* withTransaction 的结果封装版 —— 适合领域函数想表达“业务失败但不抛错”的场景。
|
|
72
|
+
*
|
|
73
|
+
* 用法:
|
|
74
|
+
* const r = withResult(db, () => {
|
|
75
|
+
* if (bad) return { ok: false, error: "x" };
|
|
76
|
+
* return { ok: true, ... };
|
|
77
|
+
* });
|
|
78
|
+
* if (!r.ok) ...
|
|
79
|
+
*
|
|
80
|
+
* - 注意:仍由回调决定成功/失败;只在抛错时回滚。
|
|
81
|
+
*/
|
|
82
|
+
export function withResult(db, fn) {
|
|
83
|
+
return withTransaction(db, fn);
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/domain/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAcH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAiB,EACjB,EAAwB;IAExB,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,EAAE,CAAC;QACjB,IAAI,GAAG,YAAY,OAAO,EAAE,CAAC;YAC3B,2BAA2B;YAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE;gBACJ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClB,OAAO,CAAC,CAAC;YACX,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;gBACN,IAAI,CAAC;oBACH,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACtB,CAAC;gBAAC,MAAM,CAAC;oBACP,+BAA+B;gBACjC,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC,CACG,CAAC;QACT,CAAC;QACD,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CACxB,EAAiB,EACjB,EAAwB;IAExB,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* env.ts — 环境配置加载
|
|
3
|
+
*/
|
|
4
|
+
export interface EnvConfig {
|
|
5
|
+
PROJECT_ROOT: string;
|
|
6
|
+
PORT: number;
|
|
7
|
+
HOST: string;
|
|
8
|
+
DB_PATH: string;
|
|
9
|
+
AUTH_TOKEN: string;
|
|
10
|
+
LLBOT_HOST: string;
|
|
11
|
+
LLBOT_PORT: number;
|
|
12
|
+
LLBOT_TOKEN: string;
|
|
13
|
+
QQ_GROUP_ID: string;
|
|
14
|
+
QQ_BRIDGE_CHANNEL_ID: string;
|
|
15
|
+
MODULES_DIR: string;
|
|
16
|
+
MODULE_CATALOG_PATH: string;
|
|
17
|
+
MODULE_LOCK_PATH: string;
|
|
18
|
+
dbconfig: Record<string, unknown>;
|
|
19
|
+
qqconfig: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export declare function loadEnv(): EnvConfig;
|
|
22
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,OAAO,IAAI,SAAS,CA2FnC"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* env.ts — 环境配置加载
|
|
3
|
+
*/
|
|
4
|
+
import { ensureJsonConfig, modulePath, resolveRuntimeRoot } from "@sfmc-bds/sdk/node/config";
|
|
5
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { log } from "./lib/log.js";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
const DEFAULT_DB_CONFIG = {
|
|
12
|
+
db_port: 3001,
|
|
13
|
+
dbDir: "data/sfmc_data.db",
|
|
14
|
+
modulesDir: "modules",
|
|
15
|
+
};
|
|
16
|
+
const DEFAULT_QQ_CONFIG = {
|
|
17
|
+
llbot_host: "127.0.0.1",
|
|
18
|
+
llbot_port: 3004,
|
|
19
|
+
llbot_token: "",
|
|
20
|
+
};
|
|
21
|
+
export function loadEnv() {
|
|
22
|
+
const PROJECT_ROOT = resolveRuntimeRoot(resolve(__dirname, "..", ".."));
|
|
23
|
+
/* 启动时确认 db/qq config 存在;不存在就写带默认值的骨架。
|
|
24
|
+
* 不依赖 wizard:wizard 只填字段,骨架由服务自己 ensure。 */
|
|
25
|
+
const dbconfig = ensureJsonConfig(PROJECT_ROOT, "db_config.json", DEFAULT_DB_CONFIG);
|
|
26
|
+
const qqconfig = ensureJsonConfig(PROJECT_ROOT, "qq_config.json", DEFAULT_QQ_CONFIG);
|
|
27
|
+
// ── 优先级:JSON > 系统环境变量 > 默认值 ───────────────────────
|
|
28
|
+
const envBaseline = { ...process.env };
|
|
29
|
+
// 元数据前缀:`_` 开头视为注释/说明(如 _comment / _comment_group),不写 env、不打日志
|
|
30
|
+
const isMeta = (k) => String(k).startsWith("_");
|
|
31
|
+
for (const [k, v] of Object.entries(dbconfig)) {
|
|
32
|
+
if (isMeta(k))
|
|
33
|
+
continue;
|
|
34
|
+
const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
35
|
+
process.env[envKey] = String(v);
|
|
36
|
+
log.info(`db_config::${k} -> process.env.${envKey} = ${String(v)}`);
|
|
37
|
+
}
|
|
38
|
+
for (const [k, v] of Object.entries(qqconfig)) {
|
|
39
|
+
if (isMeta(k))
|
|
40
|
+
continue;
|
|
41
|
+
const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
42
|
+
if (process.env[envKey] === undefined) {
|
|
43
|
+
process.env[envKey] = String(v);
|
|
44
|
+
log.info(`qq_config::${k} -> process.env.${envKey} = ${String(v)}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// 工具:JSON > envBaseline(原 process.env) > default
|
|
48
|
+
// 语义:JSON 里有这个键(非 undefined / null)就用 JSON;空串、0、false 都算"显式配置"
|
|
49
|
+
// 只有 JSON 完全没这个键(或者显式 null)才 fall through 到 env
|
|
50
|
+
function pick(jsonVal, envKey, fallback, source) {
|
|
51
|
+
if (jsonVal !== undefined && jsonVal !== null) {
|
|
52
|
+
return jsonVal;
|
|
53
|
+
}
|
|
54
|
+
const fromEnv = envBaseline[envKey];
|
|
55
|
+
if (fromEnv !== undefined && fromEnv !== "") {
|
|
56
|
+
log.info(`${source} 未在 JSON 中配置,使用系统环境变量 ${envKey} = ${fromEnv}`);
|
|
57
|
+
return fromEnv;
|
|
58
|
+
}
|
|
59
|
+
return fallback;
|
|
60
|
+
}
|
|
61
|
+
const PORT = parseInt(String(pick(dbconfig["db_port"], "DB_PORT", 3001, "db_port")), 10);
|
|
62
|
+
const HOST = "127.0.0.1";
|
|
63
|
+
const DB_PATH_RAW = String(pick(dbconfig["dbDir"], "DB_DIR", "data/sfmc_data.db", "dbDir"));
|
|
64
|
+
const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);
|
|
65
|
+
const LLBOT_HOST = String(pick(qqconfig["llbot_host"], "LLBOT_HOST", "127.0.0.1", "llbot_host"));
|
|
66
|
+
const LLBOT_PORT = parseInt(String(pick(qqconfig["llbot_port"], "LLBOT_PORT", 3004, "llbot_port")), 10);
|
|
67
|
+
const LLBOT_TOKEN = String(pick(qqconfig["llbot_token"], "LLBOT_TOKEN", "", "llbot_token"));
|
|
68
|
+
const QQ_GROUP_ID = String(pick(qqconfig["qq_group_id"], "QQ_GROUP_ID", "", "qq_group_id"));
|
|
69
|
+
const QQ_BRIDGE_CHANNEL_ID = String(pick(qqconfig["bridge_channel_id"], "BRIDGE_CHANNEL_ID", "", "bridge_channel_id"));
|
|
70
|
+
const AUTH_TOKEN = String(pick(dbconfig["http_auth"], "HTTP_AUTH", "", "http_auth"));
|
|
71
|
+
const MODULES_DIR = dbconfig["modulesDir"]
|
|
72
|
+
? resolve(PROJECT_ROOT, String(dbconfig["modulesDir"]))
|
|
73
|
+
: join(PROJECT_ROOT, "modules");
|
|
74
|
+
const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, "catalog.json");
|
|
75
|
+
const MODULE_LOCK_PATH = modulePath(MODULES_DIR, "module-lock.json");
|
|
76
|
+
return {
|
|
77
|
+
PROJECT_ROOT,
|
|
78
|
+
PORT,
|
|
79
|
+
HOST,
|
|
80
|
+
DB_PATH,
|
|
81
|
+
AUTH_TOKEN,
|
|
82
|
+
LLBOT_HOST,
|
|
83
|
+
LLBOT_PORT,
|
|
84
|
+
LLBOT_TOKEN,
|
|
85
|
+
QQ_GROUP_ID,
|
|
86
|
+
QQ_BRIDGE_CHANNEL_ID,
|
|
87
|
+
MODULES_DIR,
|
|
88
|
+
MODULE_CATALOG_PATH,
|
|
89
|
+
MODULE_LOCK_PATH,
|
|
90
|
+
dbconfig,
|
|
91
|
+
qqconfig,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.ts — 入口(v2 启动顺序)
|
|
3
|
+
*
|
|
4
|
+
* 工作流:
|
|
5
|
+
* 1. 加载 env
|
|
6
|
+
* 2. 校验 Node 版本
|
|
7
|
+
* 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)
|
|
8
|
+
* 4. loadManifestV2() — 失败 = 启动失败
|
|
9
|
+
* 5. filterEnabled(loaded, lockFileEnabled)
|
|
10
|
+
* 6. buildModuleAuth({auth_token, enabled_modules}) ← data/module-tokens.json
|
|
11
|
+
* 7. 实例化:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner
|
|
12
|
+
* 8. 装配 v2 路由 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)
|
|
13
|
+
* 另保留 messages(qq-bridge) + config/modules/health 平台路由
|
|
14
|
+
* 9. createServer + listen
|
|
15
|
+
*
|
|
16
|
+
* 鉴权(handle 层):
|
|
17
|
+
* - /api/sfmc/db/*, /api/sfmc/services*, /api/sfmc/configs/:key(/set|notify)*
|
|
18
|
+
* → module token (Authorization: Bearer ...) + ?moduleId=...
|
|
19
|
+
* - 其他:env.AUTH_TOKEN 旧 auth(NEEDS_AUTH)
|
|
20
|
+
*/
|
|
21
|
+
import { SchemaRegistry } from "./schema-registry.js";
|
|
22
|
+
import { ServiceRegistry } from "./service-registry.js";
|
|
23
|
+
import { TxRunner } from "./tx-runner.js";
|
|
24
|
+
declare const env: import("./env.js").EnvConfig;
|
|
25
|
+
declare const db: import("node:sqlite").DatabaseSync;
|
|
26
|
+
declare const query: import("./lib/sqlite.js").QueryFn;
|
|
27
|
+
declare const enabledManifests: Map<string, import("./manifest-loader.js").ModuleManifestV2>;
|
|
28
|
+
declare const moduleAuth: import("./module-auth.js").ModuleAuthMap;
|
|
29
|
+
declare const schemaRegistry: SchemaRegistry;
|
|
30
|
+
declare const serviceRegistry: ServiceRegistry;
|
|
31
|
+
declare const txRunner: TxRunner;
|
|
32
|
+
export { db, env, query, schemaRegistry, serviceRegistry, txRunner, enabledManifests, moduleAuth };
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAuB1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AA4B9B,QAAA,MAAM,gBAAgB,8DAAwE,CAAC;AAU/F,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AAyOH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.ts — 入口(v2 启动顺序)
|
|
3
|
+
*
|
|
4
|
+
* 工作流:
|
|
5
|
+
* 1. 加载 env
|
|
6
|
+
* 2. 校验 Node 版本
|
|
7
|
+
* 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)
|
|
8
|
+
* 4. loadManifestV2() — 失败 = 启动失败
|
|
9
|
+
* 5. filterEnabled(loaded, lockFileEnabled)
|
|
10
|
+
* 6. buildModuleAuth({auth_token, enabled_modules}) ← data/module-tokens.json
|
|
11
|
+
* 7. 实例化:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner
|
|
12
|
+
* 8. 装配 v2 路由 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)
|
|
13
|
+
* 另保留 messages(qq-bridge) + config/modules/health 平台路由
|
|
14
|
+
* 9. createServer + listen
|
|
15
|
+
*
|
|
16
|
+
* 鉴权(handle 层):
|
|
17
|
+
* - /api/sfmc/db/*, /api/sfmc/services*, /api/sfmc/configs/:key(/set|notify)*
|
|
18
|
+
* → module token (Authorization: Bearer ...) + ?moduleId=...
|
|
19
|
+
* - 其他:env.AUTH_TOKEN 旧 auth(NEEDS_AUTH)
|
|
20
|
+
*/
|
|
21
|
+
import http from "node:http";
|
|
22
|
+
import { createIdempotencyStore } from "./lib/idempotency-store.js";
|
|
23
|
+
import { loadEnv } from "./env.js";
|
|
24
|
+
import { buildModuleAuth, verifyModuleAuth } from "./module-auth.js";
|
|
25
|
+
import { loadManifestV2 } from "./manifest-loader.js";
|
|
26
|
+
import { log } from "./lib/log.js";
|
|
27
|
+
import { assertNodeVersion } from "./lib/runtime.js";
|
|
28
|
+
import { createQuery, openDatabase } from "./lib/sqlite.js";
|
|
29
|
+
import { createServer, startConsole } from "./server.js";
|
|
30
|
+
import { createPlatformTables } from "./db-tables.js";
|
|
31
|
+
import { initSchema } from "./domain/schema.js";
|
|
32
|
+
import { SchemaRegistry } from "./schema-registry.js";
|
|
33
|
+
import { ServiceRegistry } from "./service-registry.js";
|
|
34
|
+
import { TxRunner } from "./tx-runner.js";
|
|
35
|
+
import { registerEnabledBuiltinServices } from "./services/builtin-handlers.js";
|
|
36
|
+
import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
|
|
37
|
+
import { createModuleConfigRoutes } from "./routes/module-config-routes.js";
|
|
38
|
+
import { createDbRoutes } from "./routes/db-routes.js";
|
|
39
|
+
import { createServiceRoutes } from "./routes/service-routes.js";
|
|
40
|
+
import { jsonV2Fail } from "./routes/_shared.js";
|
|
41
|
+
import { createConfigRoutes } from "./routes/config.js";
|
|
42
|
+
import { createHealthRoutes } from "./routes/health.js";
|
|
43
|
+
import { createMessagesRoutes } from "./routes/messages.js";
|
|
44
|
+
import { createModuleRoutes } from "./routes/modules.js";
|
|
45
|
+
import { forwardToQQBridge, makeLLBotConfig } from "./domain/bridge.js";
|
|
46
|
+
import { isEnabled, loadModuleLock, updateModuleState } from "./lib/module-state.js";
|
|
47
|
+
import { body as sharedBody, json as sharedJson } from "./lib/http.js";
|
|
48
|
+
if (!assertNodeVersion(22, 13)) {
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
51
|
+
const env = loadEnv();
|
|
52
|
+
const db = openDatabase(env.DB_PATH);
|
|
53
|
+
createPlatformTables(db); // sfmc__audit / sfmc__idempotent
|
|
54
|
+
initSchema(db); // 平台业务 bootstrap 表(players/world/chat/...)——qq-bridge 在 SAPI defineTable 之前就需要
|
|
55
|
+
const query = createQuery(db);
|
|
56
|
+
// ── v2 manifest 加载(失败 = 启动失败)─────────────────────────
|
|
57
|
+
const loadedManifest = loadManifestV2(); // throws on violation
|
|
58
|
+
log.success(`[manifest v2] loaded ${Object.keys(loadedManifest.modules).length} modules; provides ${loadedManifest.providesMap.size} services`);
|
|
59
|
+
// ── enabled 集合(从 lock file)─────────────────────────────
|
|
60
|
+
const lockFile = loadModuleLock(env.MODULE_LOCK_PATH);
|
|
61
|
+
const moduleCatalog = readJson(env.MODULE_CATALOG_PATH) ?? { modules: [] };
|
|
62
|
+
const catalogIds = new Set(Array.isArray(moduleCatalog.modules)
|
|
63
|
+
? moduleCatalog.modules
|
|
64
|
+
.map((m) => String(m.id || ""))
|
|
65
|
+
.filter((id) => id.length > 0)
|
|
66
|
+
: []);
|
|
67
|
+
const enabledSet = new Set();
|
|
68
|
+
for (const id of Object.keys(loadedManifest.modules)) {
|
|
69
|
+
if (!catalogIds.has(id))
|
|
70
|
+
continue;
|
|
71
|
+
const catalogEntry = moduleCatalog.modules.find((m) => String(m.id) === id);
|
|
72
|
+
if (!catalogEntry)
|
|
73
|
+
continue;
|
|
74
|
+
const defaultEnabled = catalogEntry.enabledByDefault !== false;
|
|
75
|
+
if (isEnabled(lockFile, id, defaultEnabled))
|
|
76
|
+
enabledSet.add(id);
|
|
77
|
+
}
|
|
78
|
+
const enabledManifests = new Map();
|
|
79
|
+
for (const id of enabledSet) {
|
|
80
|
+
const m = loadedManifest.modules[id];
|
|
81
|
+
if (m)
|
|
82
|
+
enabledManifests.set(id, m);
|
|
83
|
+
}
|
|
84
|
+
log.info(`[manifest v2] enabled: ${[...enabledSet].sort().join(", ") || "(none)"}`);
|
|
85
|
+
// ── 模块 HMAC token map(写到 data/module-tokens.json)────────
|
|
86
|
+
const moduleAuth = buildModuleAuth({
|
|
87
|
+
projectRoot: env.PROJECT_ROOT,
|
|
88
|
+
envAuthToken: env.AUTH_TOKEN,
|
|
89
|
+
enabledModuleIds: [...enabledSet],
|
|
90
|
+
});
|
|
91
|
+
// ── 三件套 + 路由工厂 ─────────────────────────────────────
|
|
92
|
+
const schemaRegistry = new SchemaRegistry(db);
|
|
93
|
+
const serviceRegistry = new ServiceRegistry();
|
|
94
|
+
const idempotent = createIdempotencyStore(db);
|
|
95
|
+
const txRunner = new TxRunner({
|
|
96
|
+
db,
|
|
97
|
+
query,
|
|
98
|
+
schema: schemaRegistry,
|
|
99
|
+
serviceRegistry,
|
|
100
|
+
enabled: enabledManifests,
|
|
101
|
+
});
|
|
102
|
+
// ── 进程内置 service handler(扩展点:BUILTIN_SERVICE_PLUGINS) ──
|
|
103
|
+
{
|
|
104
|
+
const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);
|
|
105
|
+
if (plugins > 0) {
|
|
106
|
+
log.success(`[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const json = sharedJson;
|
|
110
|
+
const body = sharedBody;
|
|
111
|
+
// ── 工具函数 ──────────────────────────────────────────────
|
|
112
|
+
function loadModuleCatalog() {
|
|
113
|
+
return Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules : [];
|
|
114
|
+
}
|
|
115
|
+
function buildModuleList() {
|
|
116
|
+
const catalog = loadModuleCatalog();
|
|
117
|
+
return catalog
|
|
118
|
+
.map((raw) => {
|
|
119
|
+
const entry = raw.entry && typeof raw.entry === "object"
|
|
120
|
+
? raw.entry
|
|
121
|
+
: {};
|
|
122
|
+
const id = String(raw.id || "").trim();
|
|
123
|
+
const configKey = String(raw.configKey || raw.config_key || "").trim();
|
|
124
|
+
if (!id || !configKey)
|
|
125
|
+
return null;
|
|
126
|
+
const state = lockFile.modules[id];
|
|
127
|
+
const enabled = isEnabled(lockFile, id, raw.enabledByDefault !== false);
|
|
128
|
+
return {
|
|
129
|
+
id,
|
|
130
|
+
module_id: id,
|
|
131
|
+
name: configKey,
|
|
132
|
+
config_key: configKey,
|
|
133
|
+
display_name: String(raw.name || configKey),
|
|
134
|
+
type: String(raw.type || "feature"),
|
|
135
|
+
description: String(raw.description || ""),
|
|
136
|
+
default_enabled: raw.enabledByDefault !== false,
|
|
137
|
+
can_disable: raw.canDisable !== false,
|
|
138
|
+
requires: Array.isArray(raw.requires)
|
|
139
|
+
? raw.requires.filter(Boolean).map(String)
|
|
140
|
+
: [],
|
|
141
|
+
optional: Array.isArray(raw.optional)
|
|
142
|
+
? raw.optional.filter(Boolean).map(String)
|
|
143
|
+
: [],
|
|
144
|
+
commands: Array.isArray(raw.commands)
|
|
145
|
+
? raw.commands.filter(Boolean).map(String)
|
|
146
|
+
: [],
|
|
147
|
+
entry: {
|
|
148
|
+
kind: String(entry.kind || ""),
|
|
149
|
+
path: String(entry.path || ""),
|
|
150
|
+
init: String(entry.init || ""),
|
|
151
|
+
},
|
|
152
|
+
updated_at: state?.updatedAt ?? null,
|
|
153
|
+
enabled: !!enabled,
|
|
154
|
+
};
|
|
155
|
+
})
|
|
156
|
+
.filter(Boolean);
|
|
157
|
+
}
|
|
158
|
+
function resolveModuleByKey(key) {
|
|
159
|
+
const k = String(key || "").trim();
|
|
160
|
+
const catalog = loadModuleCatalog();
|
|
161
|
+
return catalog.find((m) => String(m.id || "") === k ||
|
|
162
|
+
String(m.configKey || m.config_key || "") === k);
|
|
163
|
+
}
|
|
164
|
+
function setModuleEnabled(mod, enabled) {
|
|
165
|
+
// 直接更新启动时缓存的 lockFile(而非另读一份新副本),
|
|
166
|
+
// 否则 buildModuleList() 读的仍是旧缓存,导致启停后 enabled 状态不翻转。
|
|
167
|
+
updateModuleState(lockFile, mod.id, { enabled: !!enabled });
|
|
168
|
+
writeJson(env.MODULE_LOCK_PATH, lockFile);
|
|
169
|
+
}
|
|
170
|
+
// ── 平台路由(非模块业务) ───────────────────────────────────
|
|
171
|
+
const healthRoutes = createHealthRoutes();
|
|
172
|
+
const messagesRoutes = createMessagesRoutes({
|
|
173
|
+
query,
|
|
174
|
+
body,
|
|
175
|
+
json,
|
|
176
|
+
forwardToQQBridge: (channelId, fromName, content, fromId) => forwardToQQBridge(makeLLBotConfig({
|
|
177
|
+
LLBOT_HOST: env.LLBOT_HOST,
|
|
178
|
+
LLBOT_PORT: env.LLBOT_PORT,
|
|
179
|
+
LLBOT_TOKEN: env.LLBOT_TOKEN,
|
|
180
|
+
QQ_GROUP_ID: env.QQ_GROUP_ID,
|
|
181
|
+
}), channelId, fromName, content, fromId),
|
|
182
|
+
});
|
|
183
|
+
const configRoutes = createConfigRoutes({ json, projectRoot: env.PROJECT_ROOT });
|
|
184
|
+
const moduleRoutesInstance = createModuleRoutes({
|
|
185
|
+
loadModuleCatalog,
|
|
186
|
+
buildModuleList: buildModuleList,
|
|
187
|
+
resolveModuleByKey,
|
|
188
|
+
setModuleEnabled,
|
|
189
|
+
body,
|
|
190
|
+
json,
|
|
191
|
+
});
|
|
192
|
+
// ── v2 路由工厂 ───────────────────────────────────────────────
|
|
193
|
+
// 类型断言成 unknown 函数 — v2 routes 的 ctx 类型与 RouteCtx 不兼容,
|
|
194
|
+
// 但调用契约({path, method, params, req, res, body?})是稳定的。
|
|
195
|
+
const dbRoutes = createDbRoutes({ schemaRegistry, txRunner, idempotent, json });
|
|
196
|
+
const serviceRoutes = createServiceRoutes({
|
|
197
|
+
serviceRegistry,
|
|
198
|
+
enabled: enabledManifests,
|
|
199
|
+
json,
|
|
200
|
+
});
|
|
201
|
+
const moduleConfigRoutes = createModuleConfigRoutes({
|
|
202
|
+
projectRoot: env.PROJECT_ROOT,
|
|
203
|
+
enabled: enabledManifests,
|
|
204
|
+
json,
|
|
205
|
+
});
|
|
206
|
+
// ── 主请求处理器 ────────────────────────────────────────────
|
|
207
|
+
async function handle(req, res) {
|
|
208
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
209
|
+
const path = url.pathname;
|
|
210
|
+
const method = req.method || "GET";
|
|
211
|
+
const params = url.searchParams;
|
|
212
|
+
// loopback 绑定
|
|
213
|
+
const remote = req.socket.remoteAddress || "";
|
|
214
|
+
if (remote && !remote.startsWith("127.") && remote !== "::1" && remote !== "::ffff:127.") {
|
|
215
|
+
json(res, { success: false, error: "forbidden" }, 403);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// ── 预读 body(所有路由共享) ───────────────────────────────
|
|
219
|
+
await body(req);
|
|
220
|
+
// ── v2 模块身份校验 → 写入路由 ctx.moduleAuth(LoD:不挂 req 私有字段) ──
|
|
221
|
+
// 注意:`/api/sfmc/configs/all` 是旧的一次性配置快照端点(SAPI ConfigManager.init
|
|
222
|
+
// 启动必用),不属于 v2 模块配置命名空间(configs/<模块 configKey>),必须豁免,
|
|
223
|
+
// 否则会被模块鉴权网关拦成 401,导致插件端起不来。
|
|
224
|
+
const isLegacyConfigAll = path === "/api/sfmc/configs/all";
|
|
225
|
+
const needsModuleAuth = path.startsWith("/api/sfmc/db/") ||
|
|
226
|
+
path.startsWith("/api/sfmc/services") ||
|
|
227
|
+
(/^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+(?:\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll);
|
|
228
|
+
let moduleAuthCtx = null;
|
|
229
|
+
if (needsModuleAuth) {
|
|
230
|
+
const id = verifyModuleAuth({
|
|
231
|
+
headers: req.headers,
|
|
232
|
+
params,
|
|
233
|
+
auth: moduleAuth,
|
|
234
|
+
enabledModuleIds: enabledSet,
|
|
235
|
+
});
|
|
236
|
+
if (!id) {
|
|
237
|
+
// LSP: v2 模块门与 service-routes 同用 ok 方言
|
|
238
|
+
jsonV2Fail(res, "unauthorized: module identity invalid", 401, "unauthorized");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const manifest = enabledManifests.get(id);
|
|
242
|
+
moduleAuthCtx = {
|
|
243
|
+
id,
|
|
244
|
+
permissions: manifest?.permissions ?? [],
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// ── 旧 env token 鉴权(只对 POST/PUT 生效) ─────────────
|
|
249
|
+
const PUBLIC_GET = path === "/api/health" ||
|
|
250
|
+
(method === "GET" &&
|
|
251
|
+
(path === "/api/sfmc/modules" || path === "/api/sfmc/modules/catalog" || path.startsWith("/api/sfmc/modules/")));
|
|
252
|
+
const NEEDS_AUTH = !PUBLIC_GET && method !== "GET";
|
|
253
|
+
if (env.AUTH_TOKEN && NEEDS_AUTH) {
|
|
254
|
+
const auth = req.headers["authorization"] || "";
|
|
255
|
+
const provided = auth.startsWith("Bearer ") ? auth.slice(7) : req.headers["x-db-token"] || "";
|
|
256
|
+
if (provided !== env.AUTH_TOKEN) {
|
|
257
|
+
json(res, { success: false, error: "unauthorized" }, 401);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
// ── v2 路由(优先匹配) ─────────────────────────────
|
|
264
|
+
if (moduleAuthCtx && (path.startsWith("/api/sfmc/db/") || path.startsWith("/api/sfmc/services") || (/^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll))) {
|
|
265
|
+
const ctx = {
|
|
266
|
+
path,
|
|
267
|
+
method,
|
|
268
|
+
params,
|
|
269
|
+
req,
|
|
270
|
+
res,
|
|
271
|
+
moduleAuth: moduleAuthCtx,
|
|
272
|
+
};
|
|
273
|
+
// body 已在上面 `await body(req)` 预读并缓存到 req._bodyPromise;
|
|
274
|
+
// 这里复用缓存(原实现读的 req._body 从未被赋值,导致所有 v2 路由 body 恒为空)。
|
|
275
|
+
ctx["body"] = await body(req);
|
|
276
|
+
if (path.startsWith("/api/sfmc/db/")) {
|
|
277
|
+
if (await dbRoutes(ctx))
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
else if (path.startsWith("/api/sfmc/services")) {
|
|
281
|
+
if (await serviceRoutes(ctx))
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
if (await moduleConfigRoutes(ctx))
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// ── 平台路由 ────────────────────────────────────
|
|
290
|
+
const ctxBase = { path, method, params, req, res };
|
|
291
|
+
if (await moduleRoutesInstance(ctxBase))
|
|
292
|
+
return;
|
|
293
|
+
if (await healthRoutes(ctxBase))
|
|
294
|
+
return;
|
|
295
|
+
if (await messagesRoutes(ctxBase))
|
|
296
|
+
return;
|
|
297
|
+
if (await configRoutes(ctxBase))
|
|
298
|
+
return;
|
|
299
|
+
json(res, { success: false, error: "not_found" }, 404);
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
log.err(err, "DogeDB");
|
|
303
|
+
json(res, { success: false, error: err.message }, 500);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// ── 启动 ────────────────────────────────────────────────────
|
|
307
|
+
const server = createServer({
|
|
308
|
+
env: { PORT: env.PORT, HOST: env.HOST, AUTH_TOKEN: env.AUTH_TOKEN },
|
|
309
|
+
handle,
|
|
310
|
+
});
|
|
311
|
+
startConsole(server, db);
|
|
312
|
+
export { db, env, query, schemaRegistry, serviceRegistry, txRunner, enabledManifests, moduleAuth };
|
|
313
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
8
|
+
export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
9
|
+
/** 写 JSON 响应并结束。 */
|
|
10
|
+
export declare function json(res: ServerResponse, data: Record<string, unknown>, status?: number): void;
|
|
11
|
+
/** 解析请求 body 字符串为对象(解析失败返回空对象)。 */
|
|
12
|
+
export declare function parseBody(raw: string): Record<string, unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* 异步读取请求 body,结果会缓存到 req._bodyPromise 上以避免重复读取。
|
|
15
|
+
* Buffer 累积 + 异步拼接,正确处理 binary 字节流。
|
|
16
|
+
*/
|
|
17
|
+
export declare function body(req: IncomingMessage): Promise<Record<string, unknown>>;
|
|
18
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjE,oBAAoB;AACpB,wBAAgB,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAE,MAAY,GAAG,IAAI,CAGnG;AAED,mCAAmC;AACnC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM9D;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgB3E"}
|