@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/index.js
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
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
1
|
import http from "node:http";
|
|
22
2
|
import { createIdempotencyStore } from "./lib/idempotency-store.js";
|
|
23
3
|
import { loadEnv } from "./env.js";
|
|
@@ -33,7 +13,8 @@ import { SchemaRegistry } from "./schema-registry.js";
|
|
|
33
13
|
import { ServiceRegistry } from "./service-registry.js";
|
|
34
14
|
import { TxRunner } from "./tx-runner.js";
|
|
35
15
|
import { registerEnabledBuiltinServices } from "./services/builtin-handlers.js";
|
|
36
|
-
import {
|
|
16
|
+
import { syncModuleRuntimeState } from "./module-runtime-sync.js";
|
|
17
|
+
import { readJson } from "@sfmc-bds/sdk/node/config";
|
|
37
18
|
import { createModuleConfigRoutes } from "./routes/module-config-routes.js";
|
|
38
19
|
import { createDbRoutes } from "./routes/db-routes.js";
|
|
39
20
|
import { createServiceRoutes } from "./routes/service-routes.js";
|
|
@@ -43,271 +24,268 @@ import { createHealthRoutes } from "./routes/health.js";
|
|
|
43
24
|
import { createMessagesRoutes } from "./routes/messages.js";
|
|
44
25
|
import { createModuleRoutes } from "./routes/modules.js";
|
|
45
26
|
import { forwardToQQBridge, makeLLBotConfig } from "./domain/bridge.js";
|
|
46
|
-
import { isEnabled, loadModuleLock, updateModuleState } from "./lib/module-state.js";
|
|
27
|
+
import { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from "./lib/module-state.js";
|
|
47
28
|
import { body as sharedBody, json as sharedJson } from "./lib/http.js";
|
|
48
29
|
if (!assertNodeVersion(22, 13)) {
|
|
49
|
-
|
|
30
|
+
process.exit(2);
|
|
50
31
|
}
|
|
51
32
|
const env = loadEnv();
|
|
52
33
|
const db = openDatabase(env.DB_PATH);
|
|
53
|
-
createPlatformTables(db);
|
|
54
|
-
initSchema(db);
|
|
34
|
+
createPlatformTables(db);
|
|
35
|
+
initSchema(db);
|
|
55
36
|
const query = createQuery(db);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
const loadedManifest = loadManifestV2();
|
|
38
|
+
log.success(
|
|
39
|
+
`[manifest v2] loaded ${Object.keys(loadedManifest.modules).length} modules; provides ${loadedManifest.providesMap.size} services`
|
|
40
|
+
);
|
|
60
41
|
const lockFile = loadModuleLock(env.MODULE_LOCK_PATH);
|
|
61
42
|
const moduleCatalog = readJson(env.MODULE_CATALOG_PATH) ?? { modules: [] };
|
|
62
|
-
const catalogIds = new Set(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: []);
|
|
67
|
-
const enabledSet = new Set();
|
|
43
|
+
const catalogIds = new Set(
|
|
44
|
+
Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules.map((m) => String(m.id || "")).filter((id) => id.length > 0) : []
|
|
45
|
+
);
|
|
46
|
+
const enabledSet = /* @__PURE__ */ new Set();
|
|
68
47
|
for (const id of Object.keys(loadedManifest.modules)) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
enabledSet.add(id);
|
|
48
|
+
if (!catalogIds.has(id)) continue;
|
|
49
|
+
const catalogEntry = moduleCatalog.modules.find(
|
|
50
|
+
(m) => String(m.id) === id
|
|
51
|
+
);
|
|
52
|
+
if (!catalogEntry) continue;
|
|
53
|
+
const defaultEnabled = catalogEntry.enabledByDefault !== false;
|
|
54
|
+
if (isEnabled(lockFile, id, defaultEnabled)) enabledSet.add(id);
|
|
77
55
|
}
|
|
78
|
-
const enabledManifests = new Map();
|
|
56
|
+
const enabledManifests = /* @__PURE__ */ new Map();
|
|
79
57
|
for (const id of enabledSet) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
enabledManifests.set(id, m);
|
|
58
|
+
const m = loadedManifest.modules[id];
|
|
59
|
+
if (m) enabledManifests.set(id, m);
|
|
83
60
|
}
|
|
84
|
-
log.info(
|
|
85
|
-
|
|
61
|
+
log.info(
|
|
62
|
+
`[manifest v2] enabled: ${[...enabledSet].sort().join(", ") || "(none)"}`
|
|
63
|
+
);
|
|
86
64
|
const moduleAuth = buildModuleAuth({
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
65
|
+
dbPath: env.DB_PATH,
|
|
66
|
+
envAuthToken: env.AUTH_TOKEN,
|
|
67
|
+
enabledModuleIds: [...enabledSet]
|
|
90
68
|
});
|
|
91
|
-
// ── 三件套 + 路由工厂 ─────────────────────────────────────
|
|
92
69
|
const schemaRegistry = new SchemaRegistry(db);
|
|
93
70
|
const serviceRegistry = new ServiceRegistry();
|
|
94
71
|
const idempotent = createIdempotencyStore(db);
|
|
95
72
|
const txRunner = new TxRunner({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
73
|
+
db,
|
|
74
|
+
query,
|
|
75
|
+
schema: schemaRegistry,
|
|
76
|
+
serviceRegistry,
|
|
77
|
+
enabled: enabledManifests
|
|
101
78
|
});
|
|
102
|
-
// ── 进程内置 service handler(扩展点:BUILTIN_SERVICE_PLUGINS) ──
|
|
103
79
|
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
80
|
+
const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);
|
|
81
|
+
if (plugins > 0) {
|
|
82
|
+
log.success(
|
|
83
|
+
`[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
108
86
|
}
|
|
109
87
|
const json = sharedJson;
|
|
110
88
|
const body = sharedBody;
|
|
111
|
-
// ── 工具函数 ──────────────────────────────────────────────
|
|
112
89
|
function loadModuleCatalog() {
|
|
113
|
-
|
|
90
|
+
return Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules : [];
|
|
114
91
|
}
|
|
115
92
|
function buildModuleList() {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
};
|
|
155
|
-
})
|
|
156
|
-
.filter(Boolean);
|
|
93
|
+
const catalog = loadModuleCatalog();
|
|
94
|
+
return catalog.map((raw) => {
|
|
95
|
+
const entry = raw.entry && typeof raw.entry === "object" ? raw.entry : {};
|
|
96
|
+
const id = String(raw.id || "").trim();
|
|
97
|
+
const configKey = String(
|
|
98
|
+
raw.configKey || raw.config_key || ""
|
|
99
|
+
).trim();
|
|
100
|
+
if (!id || !configKey) return null;
|
|
101
|
+
const state = lockFile.modules[id];
|
|
102
|
+
const enabled = isEnabled(lockFile, id, raw.enabledByDefault !== false);
|
|
103
|
+
return {
|
|
104
|
+
id,
|
|
105
|
+
module_id: id,
|
|
106
|
+
name: configKey,
|
|
107
|
+
configKey,
|
|
108
|
+
config_key: configKey,
|
|
109
|
+
display_name: String(raw.name || configKey),
|
|
110
|
+
type: String(raw.type || "feature"),
|
|
111
|
+
description: String(raw.description || ""),
|
|
112
|
+
default_enabled: raw.enabledByDefault !== false,
|
|
113
|
+
can_disable: moduleCanDisable(raw),
|
|
114
|
+
// ConfigManager 认 installed!==false;已装包默认 true
|
|
115
|
+
installed: true,
|
|
116
|
+
requires: Array.isArray(raw.requires) ? raw.requires.filter(Boolean).map(String) : [],
|
|
117
|
+
optional: Array.isArray(raw.optional) ? raw.optional.filter(Boolean).map(String) : [],
|
|
118
|
+
commands: Array.isArray(raw.commands) ? raw.commands.filter(Boolean).map(String) : [],
|
|
119
|
+
entry: {
|
|
120
|
+
kind: String(entry.kind || ""),
|
|
121
|
+
path: String(entry.path || ""),
|
|
122
|
+
init: String(entry.init || "")
|
|
123
|
+
},
|
|
124
|
+
updated_at: state?.updatedAt ?? null,
|
|
125
|
+
enabled: !!enabled
|
|
126
|
+
};
|
|
127
|
+
}).filter(Boolean);
|
|
128
|
+
}
|
|
129
|
+
function moduleCanDisable(raw) {
|
|
130
|
+
return raw.canDisable !== false;
|
|
157
131
|
}
|
|
158
132
|
function resolveModuleByKey(key) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
133
|
+
const k = String(key || "").trim();
|
|
134
|
+
const catalog = loadModuleCatalog();
|
|
135
|
+
const raw = catalog.find(
|
|
136
|
+
(m) => String(m.id || "") === k || String(m.configKey || m.config_key || "") === k
|
|
137
|
+
);
|
|
138
|
+
if (!raw) return null;
|
|
139
|
+
const id = String(raw.id || "").trim();
|
|
140
|
+
const configKey = String(raw.configKey || raw.config_key || "").trim();
|
|
141
|
+
if (!id || !configKey) return null;
|
|
142
|
+
return { id, configKey, canDisable: moduleCanDisable(raw) };
|
|
163
143
|
}
|
|
164
144
|
function setModuleEnabled(mod, enabled) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
145
|
+
updateModuleState(lockFile, mod.id, { enabled: !!enabled });
|
|
146
|
+
saveModuleLock(env.MODULE_LOCK_PATH, lockFile);
|
|
147
|
+
syncModuleRuntimeState({
|
|
148
|
+
moduleId: mod.id,
|
|
149
|
+
enabled: !!enabled,
|
|
150
|
+
dbPath: env.DB_PATH,
|
|
151
|
+
envAuthToken: env.AUTH_TOKEN,
|
|
152
|
+
enabledSet,
|
|
153
|
+
enabledManifests,
|
|
154
|
+
loadedManifest,
|
|
155
|
+
moduleAuth,
|
|
156
|
+
serviceRegistry,
|
|
157
|
+
builtinDeps: { query, db }
|
|
158
|
+
});
|
|
169
159
|
}
|
|
170
|
-
// ── 平台路由(非模块业务) ───────────────────────────────────
|
|
171
160
|
const healthRoutes = createHealthRoutes();
|
|
172
161
|
const messagesRoutes = createMessagesRoutes({
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
162
|
+
query,
|
|
163
|
+
body,
|
|
164
|
+
json,
|
|
165
|
+
forwardToQQBridge: (channelId, fromName, content, fromId) => forwardToQQBridge(
|
|
166
|
+
makeLLBotConfig({
|
|
167
|
+
LLBOT_HOST: env.LLBOT_HOST,
|
|
168
|
+
LLBOT_PORT: env.LLBOT_PORT,
|
|
169
|
+
LLBOT_TOKEN: env.LLBOT_TOKEN,
|
|
170
|
+
QQ_GROUP_ID: env.QQ_GROUP_ID
|
|
171
|
+
}),
|
|
172
|
+
channelId,
|
|
173
|
+
fromName,
|
|
174
|
+
content,
|
|
175
|
+
fromId
|
|
176
|
+
)
|
|
177
|
+
});
|
|
178
|
+
const configRoutes = createConfigRoutes({
|
|
179
|
+
json,
|
|
180
|
+
projectRoot: env.PROJECT_ROOT,
|
|
181
|
+
// DIP:路由不读 lock/catalog/token 文件,由入口注入与 /modules 同源数据
|
|
182
|
+
listModules: () => buildModuleList(),
|
|
183
|
+
getModuleTokens: () => ({ ...moduleAuth.tokens })
|
|
182
184
|
});
|
|
183
|
-
const configRoutes = createConfigRoutes({ json, projectRoot: env.PROJECT_ROOT });
|
|
184
185
|
const moduleRoutesInstance = createModuleRoutes({
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
loadModuleCatalog,
|
|
187
|
+
buildModuleList,
|
|
188
|
+
resolveModuleByKey,
|
|
189
|
+
setModuleEnabled,
|
|
190
|
+
body,
|
|
191
|
+
json
|
|
191
192
|
});
|
|
192
|
-
// ── v2 路由工厂 ───────────────────────────────────────────────
|
|
193
|
-
// 类型断言成 unknown 函数 — v2 routes 的 ctx 类型与 RouteCtx 不兼容,
|
|
194
|
-
// 但调用契约({path, method, params, req, res, body?})是稳定的。
|
|
195
193
|
const dbRoutes = createDbRoutes({ schemaRegistry, txRunner, idempotent, json });
|
|
196
194
|
const serviceRoutes = createServiceRoutes({
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
195
|
+
serviceRegistry,
|
|
196
|
+
enabled: enabledManifests,
|
|
197
|
+
json
|
|
200
198
|
});
|
|
201
199
|
const moduleConfigRoutes = createModuleConfigRoutes({
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
projectRoot: env.PROJECT_ROOT,
|
|
201
|
+
enabled: enabledManifests,
|
|
202
|
+
json
|
|
205
203
|
});
|
|
206
|
-
// ── 主请求处理器 ────────────────────────────────────────────
|
|
207
204
|
async function handle(req, res) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
205
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
206
|
+
const path = url.pathname;
|
|
207
|
+
const method = req.method || "GET";
|
|
208
|
+
const params = url.searchParams;
|
|
209
|
+
const remote = req.socket.remoteAddress || "";
|
|
210
|
+
if (remote && !remote.startsWith("127.") && remote !== "::1" && remote !== "::ffff:127.") {
|
|
211
|
+
json(res, { success: false, error: "forbidden" }, 403);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
await body(req);
|
|
215
|
+
const isLegacyConfigAll = path === "/api/sfmc/configs/all";
|
|
216
|
+
const needsModuleAuth = path.startsWith("/api/sfmc/db/") || path.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+(?:\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll;
|
|
217
|
+
let moduleAuthCtx = null;
|
|
218
|
+
if (needsModuleAuth) {
|
|
219
|
+
const id = verifyModuleAuth({
|
|
220
|
+
headers: req.headers,
|
|
221
|
+
params,
|
|
222
|
+
auth: moduleAuth,
|
|
223
|
+
enabledModuleIds: enabledSet
|
|
224
|
+
});
|
|
225
|
+
if (!id) {
|
|
226
|
+
jsonV2Fail(res, "unauthorized: module identity invalid", 401, "unauthorized");
|
|
227
|
+
return;
|
|
217
228
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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);
|
|
229
|
+
const manifest = enabledManifests.get(id);
|
|
230
|
+
moduleAuthCtx = {
|
|
231
|
+
id,
|
|
232
|
+
permissions: manifest?.permissions ?? []
|
|
233
|
+
};
|
|
234
|
+
} else {
|
|
235
|
+
const PUBLIC_GET = path === "/api/health" || method === "GET" && (path === "/api/sfmc/modules" || path === "/api/sfmc/modules/catalog" || path.startsWith("/api/sfmc/modules/"));
|
|
236
|
+
const NEEDS_AUTH = !PUBLIC_GET && method !== "GET";
|
|
237
|
+
if (env.AUTH_TOKEN && NEEDS_AUTH) {
|
|
238
|
+
const auth = req.headers["authorization"] || "";
|
|
239
|
+
const provided = auth.startsWith("Bearer ") ? auth.slice(7) : req.headers["x-db-token"] || "";
|
|
240
|
+
if (provided !== env.AUTH_TOKEN) {
|
|
241
|
+
json(res, { success: false, error: "unauthorized" }, 401);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
300
244
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
if (moduleAuthCtx && (path.startsWith("/api/sfmc/db/") || path.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll)) {
|
|
248
|
+
const ctx = {
|
|
249
|
+
path,
|
|
250
|
+
method,
|
|
251
|
+
params,
|
|
252
|
+
req,
|
|
253
|
+
res,
|
|
254
|
+
moduleAuth: moduleAuthCtx
|
|
255
|
+
};
|
|
256
|
+
ctx["body"] = await body(req);
|
|
257
|
+
if (path.startsWith("/api/sfmc/db/")) {
|
|
258
|
+
if (await dbRoutes(ctx)) return;
|
|
259
|
+
} else if (path.startsWith("/api/sfmc/services")) {
|
|
260
|
+
if (await serviceRoutes(ctx)) return;
|
|
261
|
+
} else {
|
|
262
|
+
if (await moduleConfigRoutes(ctx)) return;
|
|
263
|
+
}
|
|
304
264
|
}
|
|
265
|
+
const ctxBase = { path, method, params, req, res };
|
|
266
|
+
if (await moduleRoutesInstance(ctxBase)) return;
|
|
267
|
+
if (await healthRoutes(ctxBase)) return;
|
|
268
|
+
if (await messagesRoutes(ctxBase)) return;
|
|
269
|
+
if (await configRoutes(ctxBase)) return;
|
|
270
|
+
json(res, { success: false, error: "not_found" }, 404);
|
|
271
|
+
} catch (err) {
|
|
272
|
+
log.err(err, "DogeDB");
|
|
273
|
+
json(res, { success: false, error: err.message }, 500);
|
|
274
|
+
}
|
|
305
275
|
}
|
|
306
|
-
// ── 启动 ────────────────────────────────────────────────────
|
|
307
276
|
const server = createServer({
|
|
308
|
-
|
|
309
|
-
|
|
277
|
+
env: { PORT: env.PORT, HOST: env.HOST, AUTH_TOKEN: env.AUTH_TOKEN },
|
|
278
|
+
handle
|
|
310
279
|
});
|
|
311
280
|
startConsole(server, db);
|
|
312
|
-
export {
|
|
313
|
-
|
|
281
|
+
export {
|
|
282
|
+
db,
|
|
283
|
+
enabledManifests,
|
|
284
|
+
env,
|
|
285
|
+
moduleAuth,
|
|
286
|
+
query,
|
|
287
|
+
schemaRegistry,
|
|
288
|
+
serviceRegistry,
|
|
289
|
+
txRunner
|
|
290
|
+
};
|
|
291
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * index.ts \u2014 \u5165\u53E3(v2 \u542F\u52A8\u987A\u5E8F)\n *\n * \u5DE5\u4F5C\u6D41:\n * 1. \u52A0\u8F7D env\n * 2. \u6821\u9A8C Node \u7248\u672C\n * 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)\n * 4. loadManifestV2() \u2014 \u5931\u8D25 = \u542F\u52A8\u5931\u8D25\n * 5. filterEnabled(loaded, lockFileEnabled)\n * 6. buildModuleAuth({auth_token, enabled_modules}) \u2190 \u4E0E DB \u540C\u76EE\u5F55 module-tokens.json\n * 7. \u5B9E\u4F8B\u5316:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner\n * 8. \u88C5\u914D v2 \u8DEF\u7531 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)\n * \u53E6\u4FDD\u7559 messages(qq-bridge) + config/modules/health \u5E73\u53F0\u8DEF\u7531\n * 9. createServer + listen\n *\n * \u9274\u6743(handle \u5C42):\n * - /api/sfmc/db/*, /api/sfmc/services*, /api/sfmc/configs/:key(/set|notify)*\n * \u2192 module token (Authorization: Bearer ...) + ?moduleId=...\n * - \u5176\u4ED6:env.AUTH_TOKEN \u65E7 auth(NEEDS_AUTH)\n */\n\nimport http from \"node:http\";\n\nimport { createIdempotencyStore } from \"./lib/idempotency-store.js\";\nimport { loadEnv } from \"./env.js\";\nimport { buildModuleAuth, verifyModuleAuth } from \"./module-auth.js\";\nimport { loadManifestV2 } from \"./manifest-loader.js\";\nimport { log } from \"./lib/log.js\";\nimport { assertNodeVersion } from \"./lib/runtime.js\";\nimport { createQuery, openDatabase } from \"./lib/sqlite.js\";\nimport { createServer, startConsole } from \"./server.js\";\nimport { createPlatformTables } from \"./db-tables.js\";\nimport { initSchema } from \"./domain/schema.js\";\nimport { SchemaRegistry } from \"./schema-registry.js\";\nimport { ServiceRegistry } from \"./service-registry.js\";\nimport { TxRunner } from \"./tx-runner.js\";\nimport { registerEnabledBuiltinServices } from \"./services/builtin-handlers.js\";\nimport { syncModuleRuntimeState } from \"./module-runtime-sync.js\";\n\nimport { readJson } from \"@sfmc-bds/sdk/node/config\";\n\nimport { createModuleConfigRoutes } from \"./routes/module-config-routes.js\";\nimport { createDbRoutes } from \"./routes/db-routes.js\";\nimport { createServiceRoutes } from \"./routes/service-routes.js\";\nimport { jsonV2Fail } from \"./routes/_shared.js\";\n\nimport { createConfigRoutes } from \"./routes/config.js\";\nimport { createHealthRoutes } from \"./routes/health.js\";\nimport { createMessagesRoutes } from \"./routes/messages.js\";\nimport { createModuleRoutes } from \"./routes/modules.js\";\n\nimport { forwardToQQBridge, makeLLBotConfig } from \"./domain/bridge.js\";\nimport { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from \"./lib/module-state.js\";\nimport { body as sharedBody, json as sharedJson } from \"./lib/http.js\";\n\nif (!assertNodeVersion(22, 13)) {\n process.exit(2);\n}\n\nconst env = loadEnv();\nconst db = openDatabase(env.DB_PATH);\ncreatePlatformTables(db); // sfmc__audit / sfmc__idempotent\ninitSchema(db); // \u5E73\u53F0\u4E1A\u52A1 bootstrap \u8868(players/world/chat/...)\u2014\u2014qq-bridge \u5728 SAPI defineTable \u4E4B\u524D\u5C31\u9700\u8981\nconst query = createQuery(db);\n\n// \u2500\u2500 v2 manifest \u52A0\u8F7D(\u5931\u8D25 = \u542F\u52A8\u5931\u8D25)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst loadedManifest = loadManifestV2(); // throws on violation\nlog.success(\n `[manifest v2] loaded ${Object.keys(loadedManifest.modules).length} modules; provides ${loadedManifest.providesMap.size} services`\n);\n\n// \u2500\u2500 enabled \u96C6\u5408(\u4ECE lock file)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst lockFile = loadModuleLock(env.MODULE_LOCK_PATH);\nconst moduleCatalog = readJson<{ modules?: unknown[] }>(env.MODULE_CATALOG_PATH) ?? { modules: [] };\nconst catalogIds = new Set(\n Array.isArray(moduleCatalog.modules)\n ? (moduleCatalog.modules as Array<{ id?: string }>)\n .map((m) => String(m.id || \"\"))\n .filter((id) => id.length > 0)\n : []\n);\nconst enabledSet = new Set<string>();\nfor (const id of Object.keys(loadedManifest.modules)) {\n if (!catalogIds.has(id)) continue;\n const catalogEntry = (moduleCatalog.modules as Array<Record<string, unknown>>).find(\n (m) => String(m.id) === id\n );\n if (!catalogEntry) continue;\n const defaultEnabled = catalogEntry.enabledByDefault !== false;\n if (isEnabled(lockFile, id, defaultEnabled)) enabledSet.add(id);\n}\nconst enabledManifests = new Map<string, NonNullable<typeof loadedManifest.modules[string]>>();\nfor (const id of enabledSet) {\n const m = loadedManifest.modules[id];\n if (m) enabledManifests.set(id, m);\n}\nlog.info(\n `[manifest v2] enabled: ${[...enabledSet].sort().join(\", \") || \"(none)\"}`\n);\n\n// \u2500\u2500 \u6A21\u5757 HMAC token map(\u4E0E DB \u540C\u76EE\u5F55 module-tokens.json)\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst moduleAuth = buildModuleAuth({\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledModuleIds: [...enabledSet],\n});\n\n// \u2500\u2500 \u4E09\u4EF6\u5957 + \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst schemaRegistry = new SchemaRegistry(db);\nconst serviceRegistry = new ServiceRegistry();\nconst idempotent = createIdempotencyStore(db);\nconst txRunner = new TxRunner({\n db,\n query,\n schema: schemaRegistry,\n serviceRegistry,\n enabled: enabledManifests,\n});\n\n// \u2500\u2500 \u8FDB\u7A0B\u5185\u7F6E service handler(\u6269\u5C55\u70B9:BUILTIN_SERVICE_PLUGINS) \u2500\u2500\n{\n const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);\n if (plugins > 0) {\n log.success(\n `[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`\n );\n }\n}\n\nconst json = sharedJson;\nconst body = sharedBody;\n\n// \u2500\u2500 \u5DE5\u5177\u51FD\u6570 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction loadModuleCatalog() {\n return Array.isArray(moduleCatalog.modules) ? moduleCatalog.modules : [];\n}\n\nfunction buildModuleList() {\n const catalog = loadModuleCatalog();\n return catalog\n .map((raw) => {\n const entry =\n (raw as Record<string, unknown>).entry && typeof (raw as Record<string, unknown>).entry === \"object\"\n ? ((raw as Record<string, unknown>).entry as Record<string, unknown>)\n : {};\n const id = String((raw as Record<string, unknown>).id || \"\").trim();\n const configKey = String(\n (raw as Record<string, unknown>).configKey || (raw as Record<string, unknown>).config_key || \"\"\n ).trim();\n if (!id || !configKey) return null;\n const state = lockFile.modules[id];\n const enabled = isEnabled(lockFile, id, (raw as Record<string, unknown>).enabledByDefault !== false);\n return {\n id,\n module_id: id,\n name: configKey,\n configKey,\n config_key: configKey,\n display_name: String((raw as Record<string, unknown>).name || configKey),\n type: String((raw as Record<string, unknown>).type || \"feature\"),\n description: String((raw as Record<string, unknown>).description || \"\"),\n default_enabled: (raw as Record<string, unknown>).enabledByDefault !== false,\n can_disable: moduleCanDisable(raw as Record<string, unknown>),\n // ConfigManager \u8BA4 installed!==false;\u5DF2\u88C5\u5305\u9ED8\u8BA4 true\n installed: true,\n requires: Array.isArray((raw as Record<string, unknown>).requires)\n ? ((raw as Record<string, unknown>).requires as unknown[]).filter(Boolean).map(String)\n : [],\n optional: Array.isArray((raw as Record<string, unknown>).optional)\n ? ((raw as Record<string, unknown>).optional as unknown[]).filter(Boolean).map(String)\n : [],\n commands: Array.isArray((raw as Record<string, unknown>).commands)\n ? ((raw as Record<string, unknown>).commands as unknown[]).filter(Boolean).map(String)\n : [],\n entry: {\n kind: String(entry.kind || \"\"),\n path: String(entry.path || \"\"),\n init: String(entry.init || \"\"),\n },\n updated_at: state?.updatedAt ?? null,\n enabled: !!enabled,\n };\n })\n .filter(Boolean);\n}\n\n/** catalog \u7701\u7565 canDisable \u65F6\u9ED8\u8BA4\u5141\u8BB8\u7981\u7528(\u4E0E buildModuleList.can_disable \u540C\u6E90)\u3002 */\nfunction moduleCanDisable(raw: Record<string, unknown>): boolean {\n return raw.canDisable !== false;\n}\n\nfunction resolveModuleByKey(key: string) {\n const k = String(key || \"\").trim();\n const catalog = loadModuleCatalog();\n const raw = catalog.find(\n (m) =>\n String((m as Record<string, unknown>).id || \"\") === k ||\n String((m as Record<string, unknown>).configKey || (m as Record<string, unknown>).config_key || \"\") === k\n ) as Record<string, unknown> | undefined;\n if (!raw) return null;\n const id = String(raw.id || \"\").trim();\n const configKey = String(raw.configKey || raw.config_key || \"\").trim();\n if (!id || !configKey) return null;\n /* LSP:\u4E0E buildModuleList.can_disable \u540C\u6E90 \u2014 \u7701\u7565\u5B57\u6BB5\u89C6\u4E3A\u53EF\u7981\u7528 */\n return { id, configKey, canDisable: moduleCanDisable(raw) };\n}\n\nfunction setModuleEnabled(mod: { id: string; canDisable: boolean }, enabled: boolean) {\n // \u76F4\u63A5\u66F4\u65B0\u542F\u52A8\u65F6\u7F13\u5B58\u7684 lockFile(\u800C\u975E\u53E6\u8BFB\u4E00\u4EFD\u65B0\u526F\u672C),\n // \u5426\u5219 buildModuleList() \u8BFB\u7684\u4ECD\u662F\u65E7\u7F13\u5B58,\u5BFC\u81F4\u542F\u505C\u540E enabled \u72B6\u6001\u4E0D\u7FFB\u8F6C\u3002\n updateModuleState(lockFile, mod.id, { enabled: !!enabled });\n // DRY:\u4E0E loadModuleLock \u5BF9\u79F0\u8D70 saveModuleLock,\u52FF\u6563\u843D writeJson\n saveModuleLock(env.MODULE_LOCK_PATH, lockFile);\n\n // DIP:\u70ED\u540C\u6B65 enabledSet / tokens / manifests / builtin handlers(\u4E0D\u91CD\u542F db-server)\n syncModuleRuntimeState({\n moduleId: mod.id,\n enabled: !!enabled,\n dbPath: env.DB_PATH,\n envAuthToken: env.AUTH_TOKEN,\n enabledSet,\n enabledManifests,\n loadedManifest,\n moduleAuth,\n serviceRegistry,\n builtinDeps: { query, db },\n });\n}\n\n// \u2500\u2500 \u5E73\u53F0\u8DEF\u7531(\u975E\u6A21\u5757\u4E1A\u52A1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst healthRoutes = createHealthRoutes();\nconst messagesRoutes = createMessagesRoutes({\n query,\n body,\n json,\n forwardToQQBridge: (channelId: string, fromName: string, content: string, fromId: string) =>\n forwardToQQBridge(\n makeLLBotConfig({\n LLBOT_HOST: env.LLBOT_HOST,\n LLBOT_PORT: env.LLBOT_PORT,\n LLBOT_TOKEN: env.LLBOT_TOKEN,\n QQ_GROUP_ID: env.QQ_GROUP_ID,\n }),\n channelId,\n fromName,\n content,\n fromId\n ),\n});\nconst configRoutes = createConfigRoutes({\n json,\n projectRoot: env.PROJECT_ROOT,\n // DIP:\u8DEF\u7531\u4E0D\u8BFB lock/catalog/token \u6587\u4EF6,\u7531\u5165\u53E3\u6CE8\u5165\u4E0E /modules \u540C\u6E90\u6570\u636E\n listModules: () => buildModuleList() as Array<Record<string, unknown>>,\n getModuleTokens: () => ({ ...moduleAuth.tokens }),\n});\nconst moduleRoutesInstance = createModuleRoutes({\n loadModuleCatalog,\n buildModuleList: buildModuleList as unknown as () => Array<Record<string, unknown>>,\n resolveModuleByKey,\n setModuleEnabled,\n body,\n json,\n});\n\n// \u2500\u2500 v2 \u8DEF\u7531\u5DE5\u5382 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// \u7C7B\u578B\u65AD\u8A00\u6210 unknown \u51FD\u6570 \u2014 v2 routes \u7684 ctx \u7C7B\u578B\u4E0E RouteCtx \u4E0D\u517C\u5BB9,\n// \u4F46\u8C03\u7528\u5951\u7EA6({path, method, params, req, res, body?})\u662F\u7A33\u5B9A\u7684\u3002\nconst dbRoutes = createDbRoutes({ schemaRegistry, txRunner, idempotent, json }) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\nconst serviceRoutes = createServiceRoutes({\n serviceRegistry,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\nconst moduleConfigRoutes = createModuleConfigRoutes({\n projectRoot: env.PROJECT_ROOT,\n enabled: enabledManifests,\n json,\n}) as unknown as (ctx: Record<string, unknown>) => Promise<boolean>;\n\n// \u2500\u2500 \u4E3B\u8BF7\u6C42\u5904\u7406\u5668 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nasync function handle(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n const url = new URL(req.url || \"/\", `http://${req.headers.host || \"localhost\"}`);\n const path = url.pathname;\n const method = req.method || \"GET\";\n const params = url.searchParams;\n\n // loopback \u7ED1\u5B9A\n const remote = req.socket.remoteAddress || \"\";\n if (remote && !remote.startsWith(\"127.\") && remote !== \"::1\" && remote !== \"::ffff:127.\") {\n json(res, { success: false, error: \"forbidden\" }, 403);\n return;\n }\n\n // \u2500\u2500 \u9884\u8BFB body(\u6240\u6709\u8DEF\u7531\u5171\u4EAB) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n await body(req);\n\n // \u2500\u2500 v2 \u6A21\u5757\u8EAB\u4EFD\u6821\u9A8C \u2192 \u5199\u5165\u8DEF\u7531 ctx.moduleAuth(LoD:\u4E0D\u6302 req \u79C1\u6709\u5B57\u6BB5) \u2500\u2500\n // \u6CE8\u610F:`/api/sfmc/configs/all` \u662F\u65E7\u7684\u4E00\u6B21\u6027\u914D\u7F6E\u5FEB\u7167\u7AEF\u70B9(SAPI ConfigManager.init\n // \u542F\u52A8\u5FC5\u7528),\u4E0D\u5C5E\u4E8E v2 \u6A21\u5757\u914D\u7F6E\u547D\u540D\u7A7A\u95F4(configs/<\u6A21\u5757 configKey>),\u5FC5\u987B\u8C41\u514D,\n // \u5426\u5219\u4F1A\u88AB\u6A21\u5757\u9274\u6743\u7F51\u5173\u62E6\u6210 401,\u5BFC\u81F4\u63D2\u4EF6\u7AEF\u8D77\u4E0D\u6765\u3002\n const isLegacyConfigAll = path === \"/api/sfmc/configs/all\";\n const needsModuleAuth =\n path.startsWith(\"/api/sfmc/db/\") ||\n path.startsWith(\"/api/sfmc/services\") ||\n (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+(?:\\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll);\n let moduleAuthCtx: { id: string; permissions: string[] } | null = null;\n if (needsModuleAuth) {\n const id = verifyModuleAuth({\n headers: req.headers,\n params,\n auth: moduleAuth,\n enabledModuleIds: enabledSet,\n });\n if (!id) {\n // LSP: v2 \u6A21\u5757\u95E8\u4E0E service-routes \u540C\u7528 ok \u65B9\u8A00\n jsonV2Fail(res, \"unauthorized: module identity invalid\", 401, \"unauthorized\");\n return;\n }\n const manifest = enabledManifests.get(id);\n moduleAuthCtx = {\n id,\n permissions: manifest?.permissions ?? [],\n };\n } else {\n // \u2500\u2500 \u65E7 env token \u9274\u6743(\u53EA\u5BF9 POST/PUT \u751F\u6548) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const PUBLIC_GET =\n path === \"/api/health\" ||\n (method === \"GET\" &&\n (path === \"/api/sfmc/modules\" || path === \"/api/sfmc/modules/catalog\" || path.startsWith(\"/api/sfmc/modules/\")));\n const NEEDS_AUTH = !PUBLIC_GET && method !== \"GET\";\n if (env.AUTH_TOKEN && NEEDS_AUTH) {\n const auth = req.headers[\"authorization\"] || \"\";\n const provided = auth.startsWith(\"Bearer \") ? auth.slice(7) : (req.headers[\"x-db-token\"] as string) || \"\";\n if (provided !== env.AUTH_TOKEN) {\n json(res, { success: false, error: \"unauthorized\" }, 401);\n return;\n }\n }\n }\n\n try {\n // \u2500\u2500 v2 \u8DEF\u7531(\u4F18\u5148\u5339\u914D) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (moduleAuthCtx && (path.startsWith(\"/api/sfmc/db/\") || path.startsWith(\"/api/sfmc/services\") || (/^\\/api\\/sfmc\\/configs\\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll))) {\n const ctx: Record<string, unknown> = {\n path,\n method,\n params,\n req,\n res,\n moduleAuth: moduleAuthCtx,\n };\n // body \u5DF2\u5728\u4E0A\u9762 `await body(req)` \u9884\u8BFB\u5E76\u7F13\u5B58\u5230 req._bodyPromise;\n // \u8FD9\u91CC\u590D\u7528\u7F13\u5B58(\u539F\u5B9E\u73B0\u8BFB\u7684 req._body \u4ECE\u672A\u88AB\u8D4B\u503C,\u5BFC\u81F4\u6240\u6709 v2 \u8DEF\u7531 body \u6052\u4E3A\u7A7A)\u3002\n ctx[\"body\"] = await body(req);\n if (path.startsWith(\"/api/sfmc/db/\")) {\n if (await dbRoutes(ctx)) return;\n } else if (path.startsWith(\"/api/sfmc/services\")) {\n if (await serviceRoutes(ctx)) return;\n } else {\n if (await moduleConfigRoutes(ctx)) return;\n }\n }\n\n // \u2500\u2500 \u5E73\u53F0\u8DEF\u7531 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctxBase = { path, method, params, req, res } as { path: string; method: string; params: URLSearchParams; req: http.IncomingMessage; res: http.ServerResponse };\n if (await moduleRoutesInstance(ctxBase)) return;\n if (await healthRoutes(ctxBase)) return;\n if (await messagesRoutes(ctxBase)) return;\n if (await configRoutes(ctxBase)) return;\n\n json(res, { success: false, error: \"not_found\" }, 404);\n } catch (err) {\n log.err(err, \"DogeDB\");\n json(res, { success: false, error: (err as Error).message }, 500);\n }\n}\n\n// \u2500\u2500 \u542F\u52A8 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst server = createServer({\n env: { PORT: env.PORT, HOST: env.HOST, AUTH_TOKEN: env.AUTH_TOKEN },\n handle,\n});\nstartConsole(server, db);\n\nexport { db, env, query, schemaRegistry, serviceRegistry, txRunner, enabledManifests, moduleAuth };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|