befly 3.13.10 → 3.14.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/dist/befly.js +443 -255
- package/dist/befly.min.js +11 -11
- package/dist/checks/checkApi.js +12 -12
- package/dist/index.js +14 -5
- package/dist/lib/asyncContext.js +4 -4
- package/dist/lib/cacheHelper.d.ts +2 -2
- package/dist/lib/dbHelper.d.ts +21 -13
- package/dist/lib/dbHelper.js +37 -9
- package/dist/lib/dbUtils.js +95 -20
- package/dist/lib/jwt.js +31 -19
- package/dist/lib/logger.js +7 -7
- package/dist/lib/sqlBuilder.js +53 -13
- package/dist/lib/validator.js +1 -1
- package/dist/loader/loadApis.js +3 -4
- package/dist/loader/loadHooks.js +1 -1
- package/dist/loader/loadPlugins.js +1 -1
- package/dist/router/api.js +8 -7
- package/dist/sync/syncApi.js +54 -31
- package/dist/sync/syncDev.js +88 -97
- package/dist/sync/syncTable.d.ts +1 -1
- package/dist/sync/syncTable.js +31 -10
- package/dist/types/common.d.ts +9 -9
- package/dist/types/database.d.ts +25 -22
- package/dist/types/sync.d.ts +2 -1
- package/dist/utils/loadMenuConfigs.js +1 -1
- package/dist/utils/loggerUtils.js +7 -3
- package/dist/utils/processAtSymbol.d.ts +1 -1
- package/dist/utils/processAtSymbol.js +2 -2
- package/dist/utils/processInfo.js +2 -2
- package/dist/utils/scanFiles.js +16 -12
- package/dist/utils/util.js +10 -3
- package/package.json +2 -2
package/dist/befly.js
CHANGED
|
@@ -105,16 +105,20 @@ function upperFirst(s) {
|
|
|
105
105
|
if (s.length === 0) {
|
|
106
106
|
return s;
|
|
107
107
|
}
|
|
108
|
-
return s
|
|
108
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
109
109
|
}
|
|
110
110
|
function camelCase(input) {
|
|
111
111
|
const parts = toWordParts(input);
|
|
112
112
|
if (parts.length === 0) {
|
|
113
113
|
return "";
|
|
114
114
|
}
|
|
115
|
-
const
|
|
115
|
+
const firstPart = parts[0];
|
|
116
|
+
if (!firstPart) {
|
|
117
|
+
return "";
|
|
118
|
+
}
|
|
119
|
+
const first = firstPart.toLowerCase();
|
|
116
120
|
const rest = parts.slice(1).map((p) => upperFirst(p.toLowerCase()));
|
|
117
|
-
return [first
|
|
121
|
+
return [first].concat(rest).join("");
|
|
118
122
|
}
|
|
119
123
|
function normalizeToWords(input) {
|
|
120
124
|
return String(input).replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim();
|
|
@@ -235,7 +239,7 @@ function sanitizeErrorValue(err, options) {
|
|
|
235
239
|
message: truncateString(err.message || "", options.maxStringLen)
|
|
236
240
|
};
|
|
237
241
|
if (typeof err.stack === "string") {
|
|
238
|
-
out
|
|
242
|
+
out["stack"] = truncateString(err.stack, options.maxStringLen);
|
|
239
243
|
}
|
|
240
244
|
return out;
|
|
241
245
|
}
|
|
@@ -323,8 +327,12 @@ function sanitizeAny(value, options, state, depth, visited) {
|
|
|
323
327
|
const entries = Object.entries(obj);
|
|
324
328
|
const limit = entries.length > options.sanitizeObjectKeys ? options.sanitizeObjectKeys : entries.length;
|
|
325
329
|
for (let i = 0;i < limit; i++) {
|
|
326
|
-
const
|
|
327
|
-
|
|
330
|
+
const entry = entries[i];
|
|
331
|
+
if (!entry) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const key = entry[0];
|
|
335
|
+
const child = entry[1];
|
|
328
336
|
if (isSensitiveKey(key, options.sensitiveKeyMatcher)) {
|
|
329
337
|
out[key] = "[MASKED]";
|
|
330
338
|
continue;
|
|
@@ -365,10 +373,10 @@ function setCtxUser(userId, roleCode, nickname, roleType) {
|
|
|
365
373
|
const store = storage.getStore();
|
|
366
374
|
if (!store)
|
|
367
375
|
return;
|
|
368
|
-
store.userId = userId;
|
|
369
|
-
store.roleCode = roleCode;
|
|
370
|
-
store.nickname = nickname;
|
|
371
|
-
store.roleType = roleType;
|
|
376
|
+
store.userId = userId === undefined ? null : userId;
|
|
377
|
+
store.roleCode = roleCode === undefined ? null : roleCode;
|
|
378
|
+
store.nickname = nickname === undefined ? null : nickname;
|
|
379
|
+
store.roleType = roleType === undefined ? null : roleType;
|
|
372
380
|
}
|
|
373
381
|
var storage;
|
|
374
382
|
var init_asyncContext = __esm(() => {
|
|
@@ -798,8 +806,8 @@ function buildLogLine(level, record) {
|
|
|
798
806
|
return `${safeJsonStringify(out)}
|
|
799
807
|
`;
|
|
800
808
|
}
|
|
801
|
-
if (base
|
|
802
|
-
base
|
|
809
|
+
if (base["msg"] === undefined) {
|
|
810
|
+
base["msg"] = "";
|
|
803
811
|
}
|
|
804
812
|
return `${safeJsonStringify(base)}
|
|
805
813
|
`;
|
|
@@ -809,7 +817,7 @@ function safeJsonStringify(obj) {
|
|
|
809
817
|
return JSON.stringify(obj);
|
|
810
818
|
} catch {
|
|
811
819
|
try {
|
|
812
|
-
return JSON.stringify({ level: obj
|
|
820
|
+
return JSON.stringify({ level: obj["level"], time: obj["time"], pid: obj["pid"], hostname: obj["hostname"], msg: "[Unserializable log record]" });
|
|
813
821
|
} catch {
|
|
814
822
|
return '{"msg":"[Unserializable log record]"}';
|
|
815
823
|
}
|
|
@@ -855,10 +863,10 @@ function metaToObject() {
|
|
|
855
863
|
now: meta.now,
|
|
856
864
|
durationSinceNowMs
|
|
857
865
|
};
|
|
858
|
-
obj
|
|
859
|
-
obj
|
|
860
|
-
obj
|
|
861
|
-
obj
|
|
866
|
+
obj["userId"] = meta.userId;
|
|
867
|
+
obj["roleCode"] = meta.roleCode;
|
|
868
|
+
obj["nickname"] = meta.nickname;
|
|
869
|
+
obj["roleType"] = meta.roleType;
|
|
862
870
|
return obj;
|
|
863
871
|
}
|
|
864
872
|
function mergeMetaIntoObject(input, meta) {
|
|
@@ -1309,7 +1317,7 @@ async function scanViewsDirToMenuConfigs(viewsDir, prefix, parentPath = "") {
|
|
|
1309
1317
|
return menus;
|
|
1310
1318
|
}
|
|
1311
1319
|
function getParentPath(path) {
|
|
1312
|
-
const parts = path.split("/").filter((p) =>
|
|
1320
|
+
const parts = path.split("/").filter((p) => Boolean(p));
|
|
1313
1321
|
if (parts.length <= 1) {
|
|
1314
1322
|
return "";
|
|
1315
1323
|
}
|
|
@@ -7590,25 +7598,25 @@ async function checkApi(apis) {
|
|
|
7590
7598
|
hasError = true;
|
|
7591
7599
|
continue;
|
|
7592
7600
|
}
|
|
7593
|
-
if (typeof api?.
|
|
7594
|
-
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684
|
|
7601
|
+
if (typeof api?.path !== "string" || api.path.trim() === "") {
|
|
7602
|
+
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u5C5E\u6027\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF09" }));
|
|
7595
7603
|
hasError = true;
|
|
7596
7604
|
} else {
|
|
7597
|
-
const
|
|
7598
|
-
if (/^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b/i.test(
|
|
7599
|
-
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684
|
|
7605
|
+
const path = api.path.trim();
|
|
7606
|
+
if (/^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b/i.test(path)) {
|
|
7607
|
+
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u4E0D\u5141\u8BB8\u5305\u542B method \u524D\u7F00\uFF0C\u5E94\u4E3A url.pathname\uFF08\u4F8B\u5982 /api/app/xxx\uFF09" }));
|
|
7600
7608
|
hasError = true;
|
|
7601
7609
|
}
|
|
7602
|
-
if (!
|
|
7603
|
-
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684
|
|
7610
|
+
if (!path.startsWith("/api/")) {
|
|
7611
|
+
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u5FC5\u987B\u4EE5 /api/ \u5F00\u5934" }));
|
|
7604
7612
|
hasError = true;
|
|
7605
7613
|
}
|
|
7606
|
-
if (
|
|
7607
|
-
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684
|
|
7614
|
+
if (path.includes(" ")) {
|
|
7615
|
+
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u4E0D\u5141\u8BB8\u5305\u542B\u7A7A\u683C" }));
|
|
7608
7616
|
hasError = true;
|
|
7609
7617
|
}
|
|
7610
|
-
if (
|
|
7611
|
-
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684
|
|
7618
|
+
if (path.includes("/api//")) {
|
|
7619
|
+
Logger.warn(Object.assign({}, omit(api, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u4E0D\u5141\u8BB8\u51FA\u73B0 /api//\uFF08\u91CD\u590D\u659C\u6760\uFF09" }));
|
|
7612
7620
|
hasError = true;
|
|
7613
7621
|
}
|
|
7614
7622
|
}
|
|
@@ -8320,7 +8328,7 @@ var presetFields = {
|
|
|
8320
8328
|
};
|
|
8321
8329
|
|
|
8322
8330
|
// utils/processAtSymbol.ts
|
|
8323
|
-
function processAtSymbol(fields, apiName,
|
|
8331
|
+
function processAtSymbol(fields, apiName, path) {
|
|
8324
8332
|
if (!fields || typeof fields !== "object")
|
|
8325
8333
|
return fields;
|
|
8326
8334
|
const processed = {};
|
|
@@ -8331,7 +8339,7 @@ function processAtSymbol(fields, apiName, routePath) {
|
|
|
8331
8339
|
continue;
|
|
8332
8340
|
}
|
|
8333
8341
|
const validKeys = Object.keys(presetFields).join(", ");
|
|
8334
|
-
throw new Error(`API [${apiName}] (${
|
|
8342
|
+
throw new Error(`API [${apiName}] (${path}) \u5B57\u6BB5 [${key}] \u5F15\u7528\u4E86\u672A\u5B9A\u4E49\u7684\u9884\u8BBE\u5B57\u6BB5 "${value}"\u3002\u53EF\u7528\u7684\u9884\u8BBE\u5B57\u6BB5\u6709: ${validKeys}`);
|
|
8335
8343
|
}
|
|
8336
8344
|
processed[key] = value;
|
|
8337
8345
|
}
|
|
@@ -8342,14 +8350,13 @@ function processAtSymbol(fields, apiName, routePath) {
|
|
|
8342
8350
|
async function loadApis(apis) {
|
|
8343
8351
|
const apisMap = new Map;
|
|
8344
8352
|
for (const api of apis) {
|
|
8345
|
-
|
|
8346
|
-
if (apiType && apiType !== "api") {
|
|
8353
|
+
if (api.type !== "api") {
|
|
8347
8354
|
continue;
|
|
8348
8355
|
}
|
|
8349
8356
|
try {
|
|
8350
8357
|
const apiRoute = api;
|
|
8351
|
-
apiRoute.fields = processAtSymbol(apiRoute.fields || {}, apiRoute.name, apiRoute.
|
|
8352
|
-
apisMap.set(apiRoute.
|
|
8358
|
+
apiRoute.fields = processAtSymbol(apiRoute.fields || {}, apiRoute.name, apiRoute.path);
|
|
8359
|
+
apisMap.set(apiRoute.path, apiRoute);
|
|
8353
8360
|
} catch (error) {
|
|
8354
8361
|
Logger.error({ err: error, api: api.relativePath, file: api.filePath, msg: "\u63A5\u53E3\u52A0\u8F7D\u5931\u8D25" });
|
|
8355
8362
|
throw error;
|
|
@@ -8469,7 +8476,7 @@ async function loadHooks(hooks) {
|
|
|
8469
8476
|
hooksMap.push({
|
|
8470
8477
|
name: hookName,
|
|
8471
8478
|
enable: true,
|
|
8472
|
-
deps: hook.deps,
|
|
8479
|
+
deps: Array.isArray(hook.deps) ? hook.deps : [],
|
|
8473
8480
|
handler: hook.handler
|
|
8474
8481
|
});
|
|
8475
8482
|
}
|
|
@@ -8503,7 +8510,7 @@ async function loadPlugins(plugins, context) {
|
|
|
8503
8510
|
pluginsMap.push({
|
|
8504
8511
|
name: pluginName,
|
|
8505
8512
|
enable: true,
|
|
8506
|
-
deps: plugin.deps,
|
|
8513
|
+
deps: Array.isArray(plugin.deps) ? plugin.deps : [],
|
|
8507
8514
|
handler: plugin.handler
|
|
8508
8515
|
});
|
|
8509
8516
|
} catch (error) {
|
|
@@ -8642,11 +8649,12 @@ function apiHandler(apis, hooks, context) {
|
|
|
8642
8649
|
requestId,
|
|
8643
8650
|
corsHeaders: {
|
|
8644
8651
|
"X-Request-ID": requestId
|
|
8645
|
-
}
|
|
8646
|
-
api: apis.get(apiPath),
|
|
8647
|
-
response: undefined,
|
|
8648
|
-
result: undefined
|
|
8652
|
+
}
|
|
8649
8653
|
};
|
|
8654
|
+
const api = apis.get(apiPath);
|
|
8655
|
+
if (api) {
|
|
8656
|
+
ctx.api = api;
|
|
8657
|
+
}
|
|
8650
8658
|
return withCtx({
|
|
8651
8659
|
requestId,
|
|
8652
8660
|
method: req.method,
|
|
@@ -8667,9 +8675,9 @@ function apiHandler(apis, hooks, context) {
|
|
|
8667
8675
|
apiName: ctx.api.name
|
|
8668
8676
|
};
|
|
8669
8677
|
if (ctx.body && Object.keys(ctx.body).length > 0) {
|
|
8670
|
-
logData
|
|
8678
|
+
logData["body"] = ctx.body;
|
|
8671
8679
|
}
|
|
8672
|
-
logData
|
|
8680
|
+
logData["msg"] = "request";
|
|
8673
8681
|
Logger.info(logData);
|
|
8674
8682
|
}
|
|
8675
8683
|
if (!ctx.api) {
|
|
@@ -8783,6 +8791,15 @@ function staticHandler(corsConfig = undefined) {
|
|
|
8783
8791
|
// sync/syncApi.ts
|
|
8784
8792
|
init_logger();
|
|
8785
8793
|
init_util();
|
|
8794
|
+
var getApiParentPath = (apiPath) => {
|
|
8795
|
+
const segments = apiPath.split("/").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
8796
|
+
const seg2 = segments[1] || "";
|
|
8797
|
+
const take = seg2 === "addon" ? 4 : 3;
|
|
8798
|
+
const parentSegments = segments.slice(0, Math.min(take, segments.length));
|
|
8799
|
+
if (parentSegments.length === 0)
|
|
8800
|
+
return "";
|
|
8801
|
+
return `/${parentSegments.join("/")}`;
|
|
8802
|
+
};
|
|
8786
8803
|
async function syncApi(ctx, apis) {
|
|
8787
8804
|
const tableName = "addon_admin_api";
|
|
8788
8805
|
if (!ctx.db) {
|
|
@@ -8797,55 +8814,61 @@ async function syncApi(ctx, apis) {
|
|
|
8797
8814
|
}
|
|
8798
8815
|
const allDbApis = await ctx.db.getAll({
|
|
8799
8816
|
table: tableName,
|
|
8800
|
-
fields: ["id", "
|
|
8817
|
+
fields: ["id", "path", "parentPath", "name", "addonName", "auth", "state"],
|
|
8801
8818
|
where: { state$gte: 0 }
|
|
8802
8819
|
});
|
|
8803
8820
|
const dbLists = allDbApis.data.lists || [];
|
|
8804
|
-
const allDbApiMap = keyBy(dbLists, (item) => item.
|
|
8821
|
+
const allDbApiMap = keyBy(dbLists, (item) => item.path);
|
|
8805
8822
|
const insData = [];
|
|
8806
8823
|
const updData = [];
|
|
8807
8824
|
const delData = [];
|
|
8808
8825
|
const apiRouteKeys = new Set;
|
|
8809
8826
|
for (const api of apis) {
|
|
8810
|
-
|
|
8811
|
-
if (apiType && apiType !== "api") {
|
|
8827
|
+
if (api.type !== "api") {
|
|
8812
8828
|
continue;
|
|
8813
8829
|
}
|
|
8814
|
-
const
|
|
8815
|
-
const
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
addonName: api.addonName,
|
|
8819
|
-
auth: normalizedAuth
|
|
8820
|
-
};
|
|
8821
|
-
const routePath = normalizedApi.routePath;
|
|
8822
|
-
apiRouteKeys.add(routePath);
|
|
8823
|
-
const item = allDbApiMap[routePath];
|
|
8830
|
+
const auth = api.auth === false || api.auth === 0 ? 0 : 1;
|
|
8831
|
+
const parentPath = getApiParentPath(api.path);
|
|
8832
|
+
apiRouteKeys.add(api.path);
|
|
8833
|
+
const item = allDbApiMap[api.path];
|
|
8824
8834
|
if (item) {
|
|
8825
|
-
const
|
|
8826
|
-
const shouldUpdate = normalizedApi.name !== item.name || normalizedApi.routePath !== item.routePath || normalizedApi.addonName !== item.addonName || normalizedAuth !== dbAuth;
|
|
8835
|
+
const shouldUpdate = api.name !== item.name || api.path !== item.path || api.addonName !== item.addonName || parentPath !== item.parentPath || auth !== item.auth;
|
|
8827
8836
|
if (shouldUpdate) {
|
|
8828
|
-
updData.push({
|
|
8837
|
+
updData.push({
|
|
8838
|
+
id: item.id,
|
|
8839
|
+
name: api.name,
|
|
8840
|
+
path: api.path,
|
|
8841
|
+
parentPath,
|
|
8842
|
+
addonName: api.addonName,
|
|
8843
|
+
auth
|
|
8844
|
+
});
|
|
8829
8845
|
}
|
|
8830
8846
|
} else {
|
|
8831
|
-
insData.push(
|
|
8847
|
+
insData.push({
|
|
8848
|
+
name: api.name,
|
|
8849
|
+
path: api.path,
|
|
8850
|
+
parentPath,
|
|
8851
|
+
addonName: api.addonName,
|
|
8852
|
+
auth
|
|
8853
|
+
});
|
|
8832
8854
|
}
|
|
8833
8855
|
}
|
|
8834
8856
|
for (const record of dbLists) {
|
|
8835
|
-
if (!apiRouteKeys.has(record.
|
|
8857
|
+
if (!apiRouteKeys.has(record.path)) {
|
|
8836
8858
|
delData.push(record.id);
|
|
8837
8859
|
}
|
|
8838
8860
|
}
|
|
8839
8861
|
if (updData.length > 0) {
|
|
8840
8862
|
try {
|
|
8841
|
-
await ctx.db.updBatch(tableName, updData.map((
|
|
8863
|
+
await ctx.db.updBatch(tableName, updData.map((api) => {
|
|
8842
8864
|
return {
|
|
8843
|
-
id:
|
|
8865
|
+
id: api.id,
|
|
8844
8866
|
data: {
|
|
8845
|
-
name:
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8867
|
+
name: api.name,
|
|
8868
|
+
path: api.path,
|
|
8869
|
+
parentPath: api.parentPath,
|
|
8870
|
+
addonName: api.addonName,
|
|
8871
|
+
auth: api.auth
|
|
8849
8872
|
}
|
|
8850
8873
|
};
|
|
8851
8874
|
}));
|
|
@@ -8858,9 +8881,10 @@ async function syncApi(ctx, apis) {
|
|
|
8858
8881
|
await ctx.db.insBatch(tableName, insData.map((api) => {
|
|
8859
8882
|
return {
|
|
8860
8883
|
name: api.name,
|
|
8861
|
-
|
|
8884
|
+
path: api.path,
|
|
8885
|
+
parentPath: api.parentPath,
|
|
8862
8886
|
addonName: api.addonName,
|
|
8863
|
-
auth: api.auth
|
|
8887
|
+
auth: api.auth
|
|
8864
8888
|
};
|
|
8865
8889
|
}));
|
|
8866
8890
|
} catch (error) {
|
|
@@ -9000,7 +9024,6 @@ async function syncDev(ctx, config2 = {}) {
|
|
|
9000
9024
|
if (!config2.devPassword) {
|
|
9001
9025
|
return;
|
|
9002
9026
|
}
|
|
9003
|
-
const devEmail = typeof config2.devEmail === "string" && config2.devEmail.length > 0 ? config2.devEmail : "dev@qq.com";
|
|
9004
9027
|
if (!ctx.db) {
|
|
9005
9028
|
throw new Error("syncDev: ctx.db \u672A\u521D\u59CB\u5316\uFF08Db \u63D2\u4EF6\u672A\u52A0\u8F7D\u6216\u6CE8\u5165\u5931\u8D25\uFF09");
|
|
9006
9029
|
}
|
|
@@ -9019,140 +9042,130 @@ async function syncDev(ctx, config2 = {}) {
|
|
|
9019
9042
|
Logger.debug(`addon_admin_menu \u8868\u4E0D\u5B58\u5728`);
|
|
9020
9043
|
return;
|
|
9021
9044
|
}
|
|
9045
|
+
if (!(await ctx.db.tableExists("addon_admin_api")).data) {
|
|
9046
|
+
Logger.debug(`addon_admin_api \u8868\u4E0D\u5B58\u5728`);
|
|
9047
|
+
return;
|
|
9048
|
+
}
|
|
9022
9049
|
const allMenus = await ctx.db.getAll({
|
|
9023
9050
|
table: "addon_admin_menu",
|
|
9024
9051
|
fields: ["path"],
|
|
9025
9052
|
where: { state$gte: 0 },
|
|
9026
9053
|
orderBy: ["id#ASC"]
|
|
9027
9054
|
});
|
|
9028
|
-
const
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9055
|
+
const allApis = await ctx.db.getAll({
|
|
9056
|
+
table: "addon_admin_api",
|
|
9057
|
+
fields: ["path"],
|
|
9058
|
+
where: { state$gte: 0 },
|
|
9059
|
+
orderBy: ["id#ASC"]
|
|
9060
|
+
});
|
|
9061
|
+
const devRole = await ctx.db.getOne({
|
|
9062
|
+
table: "addon_admin_role",
|
|
9063
|
+
where: { code: "dev" }
|
|
9064
|
+
});
|
|
9065
|
+
const devRoleData = {
|
|
9066
|
+
code: "dev",
|
|
9067
|
+
name: "\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9068
|
+
description: "\u62E5\u6709\u6240\u6709\u83DC\u5355\u548C\u63A5\u53E3\u6743\u9650\u7684\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9069
|
+
menus: allMenus.data.lists.map((item) => item.path).filter((v) => v),
|
|
9070
|
+
apis: allApis.data.lists.map((item) => item.path).filter((v) => v),
|
|
9071
|
+
sort: 0
|
|
9072
|
+
};
|
|
9073
|
+
if (devRole.data) {
|
|
9074
|
+
await ctx.db.updData({
|
|
9075
|
+
table: "addon_admin_role",
|
|
9076
|
+
where: { code: "dev" },
|
|
9077
|
+
data: {
|
|
9078
|
+
name: devRoleData.name,
|
|
9079
|
+
description: devRoleData.description,
|
|
9080
|
+
menus: devRoleData.menus,
|
|
9081
|
+
apis: devRoleData.apis,
|
|
9082
|
+
sort: devRoleData.sort
|
|
9045
9083
|
}
|
|
9046
|
-
|
|
9047
|
-
|
|
9084
|
+
});
|
|
9085
|
+
} else {
|
|
9086
|
+
await ctx.db.insData({
|
|
9087
|
+
table: "addon_admin_role",
|
|
9088
|
+
data: devRoleData
|
|
9089
|
+
});
|
|
9090
|
+
}
|
|
9091
|
+
const devAdminData = {
|
|
9092
|
+
nickname: "\u5F00\u53D1\u8005",
|
|
9093
|
+
email: config2.devEmail || "dev@qq.com",
|
|
9094
|
+
username: "dev",
|
|
9095
|
+
password: await Cipher.hashPassword(Cipher.sha256(config2.devPassword + "befly")),
|
|
9096
|
+
roleCode: "dev",
|
|
9097
|
+
roleType: "admin"
|
|
9098
|
+
};
|
|
9099
|
+
const devAdmin = await ctx.db.getOne({
|
|
9100
|
+
table: "addon_admin_admin",
|
|
9101
|
+
where: { username: "dev" }
|
|
9102
|
+
});
|
|
9103
|
+
if (devAdmin.data) {
|
|
9104
|
+
await ctx.db.updData({
|
|
9105
|
+
table: "addon_admin_admin",
|
|
9106
|
+
where: { username: "dev" },
|
|
9107
|
+
data: {
|
|
9108
|
+
nickname: devAdminData.nickname,
|
|
9109
|
+
email: devAdminData.email,
|
|
9110
|
+
username: devAdminData.username,
|
|
9111
|
+
password: devAdminData.password,
|
|
9112
|
+
roleCode: devAdminData.roleCode,
|
|
9113
|
+
roleType: devAdminData.roleType
|
|
9048
9114
|
}
|
|
9049
|
-
|
|
9050
|
-
|
|
9115
|
+
});
|
|
9116
|
+
} else {
|
|
9117
|
+
await ctx.db.insData({
|
|
9118
|
+
table: "addon_admin_admin",
|
|
9119
|
+
data: devAdminData
|
|
9120
|
+
});
|
|
9051
9121
|
}
|
|
9052
9122
|
const roles = [
|
|
9053
|
-
{
|
|
9054
|
-
code: "dev",
|
|
9055
|
-
name: "\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9056
|
-
description: "\u62E5\u6709\u6240\u6709\u83DC\u5355\u548C\u63A5\u53E3\u6743\u9650\u7684\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9057
|
-
menus: menuPaths,
|
|
9058
|
-
apis: apiPaths,
|
|
9059
|
-
sort: 0
|
|
9060
|
-
},
|
|
9061
9123
|
{
|
|
9062
9124
|
code: "user",
|
|
9063
9125
|
name: "\u7528\u6237\u89D2\u8272",
|
|
9064
9126
|
description: "\u666E\u901A\u7528\u6237\u89D2\u8272",
|
|
9065
|
-
menus: [],
|
|
9066
|
-
apis: [],
|
|
9067
9127
|
sort: 1
|
|
9068
9128
|
},
|
|
9069
9129
|
{
|
|
9070
9130
|
code: "admin",
|
|
9071
9131
|
name: "\u7BA1\u7406\u5458\u89D2\u8272",
|
|
9072
9132
|
description: "\u7BA1\u7406\u5458\u89D2\u8272",
|
|
9073
|
-
menus: [],
|
|
9074
|
-
apis: [],
|
|
9075
9133
|
sort: 2
|
|
9076
9134
|
},
|
|
9077
9135
|
{
|
|
9078
9136
|
code: "guest",
|
|
9079
9137
|
name: "\u8BBF\u5BA2\u89D2\u8272",
|
|
9080
9138
|
description: "\u8BBF\u5BA2\u89D2\u8272",
|
|
9081
|
-
menus: [],
|
|
9082
|
-
apis: [],
|
|
9083
9139
|
sort: 3
|
|
9084
9140
|
}
|
|
9085
9141
|
];
|
|
9086
|
-
let devRole = null;
|
|
9087
9142
|
for (const roleConfig of roles) {
|
|
9088
9143
|
const existingRole = await ctx.db.getOne({
|
|
9089
9144
|
table: "addon_admin_role",
|
|
9090
9145
|
where: { code: roleConfig.code }
|
|
9091
9146
|
});
|
|
9092
|
-
if (existingRole.data) {
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
table: "addon_admin_role",
|
|
9103
|
-
where: { code: roleConfig.code },
|
|
9104
|
-
data: {
|
|
9105
|
-
name: roleConfig.name,
|
|
9106
|
-
description: roleConfig.description,
|
|
9107
|
-
menus: roleConfig.menus,
|
|
9108
|
-
apis: roleConfig.apis,
|
|
9109
|
-
sort: roleConfig.sort
|
|
9110
|
-
}
|
|
9111
|
-
});
|
|
9112
|
-
}
|
|
9113
|
-
if (roleConfig.code === "dev") {
|
|
9114
|
-
devRole = existingRole.data;
|
|
9115
|
-
}
|
|
9147
|
+
if (existingRole.data?.id) {
|
|
9148
|
+
await ctx.db.updData({
|
|
9149
|
+
table: "addon_admin_role",
|
|
9150
|
+
where: { code: roleConfig.code },
|
|
9151
|
+
data: {
|
|
9152
|
+
name: roleConfig.name,
|
|
9153
|
+
description: roleConfig.description,
|
|
9154
|
+
sort: roleConfig.sort
|
|
9155
|
+
}
|
|
9156
|
+
});
|
|
9116
9157
|
} else {
|
|
9117
|
-
|
|
9158
|
+
await ctx.db.insData({
|
|
9118
9159
|
table: "addon_admin_role",
|
|
9119
|
-
data:
|
|
9160
|
+
data: {
|
|
9161
|
+
code: roleConfig.code,
|
|
9162
|
+
name: roleConfig.name,
|
|
9163
|
+
description: roleConfig.description,
|
|
9164
|
+
sort: roleConfig.sort
|
|
9165
|
+
}
|
|
9120
9166
|
});
|
|
9121
|
-
if (roleConfig.code === "dev") {
|
|
9122
|
-
devRole = { id: roleId.data };
|
|
9123
|
-
}
|
|
9124
9167
|
}
|
|
9125
9168
|
}
|
|
9126
|
-
if (!devRole) {
|
|
9127
|
-
Logger.error("dev \u89D2\u8272\u4E0D\u5B58\u5728\uFF0C\u65E0\u6CD5\u521B\u5EFA\u5F00\u53D1\u8005\u8D26\u53F7");
|
|
9128
|
-
return;
|
|
9129
|
-
}
|
|
9130
|
-
const sha256Hashed = Cipher.sha256(config2.devPassword + "befly");
|
|
9131
|
-
const hashed = await Cipher.hashPassword(sha256Hashed);
|
|
9132
|
-
const devData = {
|
|
9133
|
-
nickname: "\u5F00\u53D1\u8005",
|
|
9134
|
-
email: devEmail,
|
|
9135
|
-
username: "dev",
|
|
9136
|
-
password: hashed,
|
|
9137
|
-
roleCode: "dev",
|
|
9138
|
-
roleType: "admin"
|
|
9139
|
-
};
|
|
9140
|
-
const existing = await ctx.db.getOne({
|
|
9141
|
-
table: "addon_admin_admin",
|
|
9142
|
-
where: { email: devEmail }
|
|
9143
|
-
});
|
|
9144
|
-
if (existing.data) {
|
|
9145
|
-
await ctx.db.updData({
|
|
9146
|
-
table: "addon_admin_admin",
|
|
9147
|
-
where: { email: devEmail },
|
|
9148
|
-
data: devData
|
|
9149
|
-
});
|
|
9150
|
-
} else {
|
|
9151
|
-
await ctx.db.insData({
|
|
9152
|
-
table: "addon_admin_admin",
|
|
9153
|
-
data: devData
|
|
9154
|
-
});
|
|
9155
|
-
}
|
|
9156
9169
|
}
|
|
9157
9170
|
|
|
9158
9171
|
// sync/syncMenu.ts
|
|
@@ -10081,8 +10094,14 @@ async function getTableColumnsRuntime(runtime, tableName) {
|
|
|
10081
10094
|
let max = null;
|
|
10082
10095
|
const m = /^(\w+)\s*\((\d+)\)/.exec(baseType);
|
|
10083
10096
|
if (m) {
|
|
10084
|
-
|
|
10085
|
-
|
|
10097
|
+
const base = m[1];
|
|
10098
|
+
const maxText = m[2];
|
|
10099
|
+
if (typeof base === "string") {
|
|
10100
|
+
baseType = base;
|
|
10101
|
+
}
|
|
10102
|
+
if (typeof maxText === "string") {
|
|
10103
|
+
max = Number(maxText);
|
|
10104
|
+
}
|
|
10086
10105
|
}
|
|
10087
10106
|
columns[row.name] = {
|
|
10088
10107
|
type: baseType.toLowerCase(),
|
|
@@ -10111,9 +10130,13 @@ async function getTableIndexesRuntime(runtime, tableName) {
|
|
|
10111
10130
|
const q = getSyncTableIndexesQuery({ dialect: "mysql", table: tableName, dbName: runtime.dbName });
|
|
10112
10131
|
const result = await runtime.db.unsafe(q.sql, q.params);
|
|
10113
10132
|
for (const row of result.data) {
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10133
|
+
const indexName = row.INDEX_NAME;
|
|
10134
|
+
const current = indexes[indexName];
|
|
10135
|
+
if (Array.isArray(current)) {
|
|
10136
|
+
current.push(row.COLUMN_NAME);
|
|
10137
|
+
} else {
|
|
10138
|
+
indexes[indexName] = [row.COLUMN_NAME];
|
|
10139
|
+
}
|
|
10117
10140
|
}
|
|
10118
10141
|
} else if (runtime.dbDialect === "postgresql") {
|
|
10119
10142
|
const q = getSyncTableIndexesQuery({ dialect: "postgresql", table: tableName, dbName: runtime.dbName });
|
|
@@ -10121,7 +10144,8 @@ async function getTableIndexesRuntime(runtime, tableName) {
|
|
|
10121
10144
|
for (const row of result.data) {
|
|
10122
10145
|
const m = /\(([^)]+)\)/.exec(row.indexdef);
|
|
10123
10146
|
if (m) {
|
|
10124
|
-
const
|
|
10147
|
+
const colPart = m[1];
|
|
10148
|
+
const col = typeof colPart === "string" ? colPart.replace(/"/g, "").trim() : "";
|
|
10125
10149
|
indexes[row.indexname] = [col];
|
|
10126
10150
|
}
|
|
10127
10151
|
}
|
|
@@ -10154,7 +10178,8 @@ async function ensureDbVersion(dbDialect, db) {
|
|
|
10154
10178
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6 MySQL \u7248\u672C\u4FE1\u606F");
|
|
10155
10179
|
}
|
|
10156
10180
|
const version = r.data[0].version;
|
|
10157
|
-
const
|
|
10181
|
+
const majorPart = String(version).split(".")[0] || "0";
|
|
10182
|
+
const majorVersion = parseInt(majorPart, 10);
|
|
10158
10183
|
if (!Number.isFinite(majorVersion) || majorVersion < DB_VERSION_REQUIREMENTS.MYSQL_MIN_MAJOR) {
|
|
10159
10184
|
throw new Error(`\u6B64\u811A\u672C\u4EC5\u652F\u6301 MySQL ${DB_VERSION_REQUIREMENTS.MYSQL_MIN_MAJOR}.0+\uFF0C\u5F53\u524D\u7248\u672C: ${version}`);
|
|
10160
10185
|
}
|
|
@@ -10167,7 +10192,8 @@ async function ensureDbVersion(dbDialect, db) {
|
|
|
10167
10192
|
}
|
|
10168
10193
|
const versionText = r.data[0].version;
|
|
10169
10194
|
const m = /PostgreSQL\s+(\d+)/i.exec(versionText);
|
|
10170
|
-
const
|
|
10195
|
+
const majorText = m ? m[1] : undefined;
|
|
10196
|
+
const major = typeof majorText === "string" ? parseInt(majorText, 10) : NaN;
|
|
10171
10197
|
if (!Number.isFinite(major) || major < DB_VERSION_REQUIREMENTS.POSTGRES_MIN_MAJOR) {
|
|
10172
10198
|
throw new Error(`\u6B64\u811A\u672C\u8981\u6C42 PostgreSQL >= ${DB_VERSION_REQUIREMENTS.POSTGRES_MIN_MAJOR}\uFF0C\u5F53\u524D: ${versionText}`);
|
|
10173
10199
|
}
|
|
@@ -10179,7 +10205,10 @@ async function ensureDbVersion(dbDialect, db) {
|
|
|
10179
10205
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6 SQLite \u7248\u672C\u4FE1\u606F");
|
|
10180
10206
|
}
|
|
10181
10207
|
const version = r.data[0].version;
|
|
10182
|
-
const
|
|
10208
|
+
const parts = String(version).split(".").map((v) => parseInt(v, 10) || 0);
|
|
10209
|
+
const maj = parts[0] ?? 0;
|
|
10210
|
+
const min = parts[1] ?? 0;
|
|
10211
|
+
const patch = parts[2] ?? 0;
|
|
10183
10212
|
const vnum = maj * 1e4 + min * 100 + patch;
|
|
10184
10213
|
if (!Number.isFinite(vnum) || vnum < DB_VERSION_REQUIREMENTS.SQLITE_MIN_VERSION_NUM) {
|
|
10185
10214
|
throw new Error(`\u6B64\u811A\u672C\u8981\u6C42 SQLite >= ${DB_VERSION_REQUIREMENTS.SQLITE_MIN_VERSION}\uFF0C\u5F53\u524D: ${version}`);
|
|
@@ -10209,7 +10238,11 @@ function compareFieldDefinition(dbDialect, existingColumn, fieldDef) {
|
|
|
10209
10238
|
}
|
|
10210
10239
|
}
|
|
10211
10240
|
const typeMapping = getTypeMapping(dbDialect);
|
|
10212
|
-
const
|
|
10241
|
+
const mapped = typeMapping[fieldDef.type];
|
|
10242
|
+
if (typeof mapped !== "string") {
|
|
10243
|
+
throw new Error(`\u672A\u77E5\u5B57\u6BB5\u7C7B\u578B\u6620\u5C04\uFF1Adialect=${dbDialect} type=${String(fieldDef.type)}`);
|
|
10244
|
+
}
|
|
10245
|
+
const expectedType = mapped.toLowerCase();
|
|
10213
10246
|
const currentType = existingColumn.type.toLowerCase();
|
|
10214
10247
|
if (currentType !== expectedType) {
|
|
10215
10248
|
changes.push({
|
|
@@ -10519,8 +10552,8 @@ var calcPerfTime = (startTime, endTime = Bun.nanoseconds()) => {
|
|
|
10519
10552
|
// utils/processInfo.ts
|
|
10520
10553
|
function getProcessRole(env) {
|
|
10521
10554
|
const runtimeEnv = env || {};
|
|
10522
|
-
const bunWorkerId = runtimeEnv
|
|
10523
|
-
const pm2InstanceId = runtimeEnv
|
|
10555
|
+
const bunWorkerId = runtimeEnv["BUN_WORKER_ID"];
|
|
10556
|
+
const pm2InstanceId = runtimeEnv["PM2_INSTANCE_ID"];
|
|
10524
10557
|
if (bunWorkerId !== undefined) {
|
|
10525
10558
|
return {
|
|
10526
10559
|
role: bunWorkerId === "" ? "primary" : "worker",
|
|
@@ -12307,7 +12340,7 @@ class Validator {
|
|
|
12307
12340
|
return {
|
|
12308
12341
|
code: failed ? 1 : 0,
|
|
12309
12342
|
failed,
|
|
12310
|
-
firstError: failed ? errors[0] : null,
|
|
12343
|
+
firstError: failed ? errors[0] ?? null : null,
|
|
12311
12344
|
errors,
|
|
12312
12345
|
errorFields,
|
|
12313
12346
|
fieldErrors
|
|
@@ -12821,18 +12854,44 @@ class DbUtils {
|
|
|
12821
12854
|
throw new Error("tableRef \u4E0D\u80FD\u4E3A\u7A7A");
|
|
12822
12855
|
}
|
|
12823
12856
|
const parts = trimmed.split(/\s+/).filter((p) => p.length > 0);
|
|
12857
|
+
if (parts.length === 0) {
|
|
12858
|
+
throw new Error("tableRef \u4E0D\u80FD\u4E3A\u7A7A");
|
|
12859
|
+
}
|
|
12824
12860
|
if (parts.length > 2) {
|
|
12825
12861
|
throw new Error(`\u4E0D\u652F\u6301\u7684\u8868\u5F15\u7528\u683C\u5F0F\uFF08\u5305\u542B\u8FC7\u591A\u7247\u6BB5\uFF09\u3002\u8BF7\u4F7F\u7528\u6700\u7B80\u5F62\u5F0F\uFF1Atable \u6216 table alias \u6216 schema.table \u6216 schema.table alias (tableRef: ${trimmed})`);
|
|
12826
12862
|
}
|
|
12827
12863
|
const namePart = parts[0];
|
|
12828
|
-
|
|
12864
|
+
if (typeof namePart !== "string" || namePart.trim() === "") {
|
|
12865
|
+
throw new Error(`tableRef \u89E3\u6790\u5931\u8D25\uFF1A\u7F3A\u5C11\u8868\u540D (tableRef: ${trimmed})`);
|
|
12866
|
+
}
|
|
12867
|
+
let aliasPart = null;
|
|
12868
|
+
if (parts.length === 2) {
|
|
12869
|
+
const alias = parts[1];
|
|
12870
|
+
if (typeof alias !== "string" || alias.trim() === "") {
|
|
12871
|
+
throw new Error(`tableRef \u89E3\u6790\u5931\u8D25\uFF1A\u7F3A\u5C11 alias (tableRef: ${trimmed})`);
|
|
12872
|
+
}
|
|
12873
|
+
aliasPart = alias;
|
|
12874
|
+
}
|
|
12829
12875
|
const nameSegments = namePart.split(".");
|
|
12830
12876
|
if (nameSegments.length > 2) {
|
|
12831
12877
|
throw new Error(`\u4E0D\u652F\u6301\u7684\u8868\u5F15\u7528\u683C\u5F0F\uFF08schema \u5C42\u7EA7\u8FC7\u6DF1\uFF09 (tableRef: ${trimmed})`);
|
|
12832
12878
|
}
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12879
|
+
if (nameSegments.length === 2) {
|
|
12880
|
+
const schema = nameSegments[0];
|
|
12881
|
+
const table2 = nameSegments[1];
|
|
12882
|
+
if (typeof schema !== "string" || schema.trim() === "") {
|
|
12883
|
+
throw new Error(`tableRef \u89E3\u6790\u5931\u8D25\uFF1Aschema \u4E3A\u7A7A (tableRef: ${trimmed})`);
|
|
12884
|
+
}
|
|
12885
|
+
if (typeof table2 !== "string" || table2.trim() === "") {
|
|
12886
|
+
throw new Error(`tableRef \u89E3\u6790\u5931\u8D25\uFF1Atable \u4E3A\u7A7A (tableRef: ${trimmed})`);
|
|
12887
|
+
}
|
|
12888
|
+
return { schema, table: table2, alias: aliasPart };
|
|
12889
|
+
}
|
|
12890
|
+
const table = nameSegments[0];
|
|
12891
|
+
if (typeof table !== "string" || table.trim() === "") {
|
|
12892
|
+
throw new Error(`tableRef \u89E3\u6790\u5931\u8D25\uFF1Atable \u4E3A\u7A7A (tableRef: ${trimmed})`);
|
|
12893
|
+
}
|
|
12894
|
+
return { schema: null, table, alias: aliasPart };
|
|
12836
12895
|
}
|
|
12837
12896
|
static normalizeTableRef(tableRef) {
|
|
12838
12897
|
const parsed = DbUtils.parseTableRef(tableRef);
|
|
@@ -12910,7 +12969,15 @@ class DbUtils {
|
|
|
12910
12969
|
if (typeof item !== "string" || !item.includes("#")) {
|
|
12911
12970
|
return item;
|
|
12912
12971
|
}
|
|
12913
|
-
const
|
|
12972
|
+
const parts = item.split("#");
|
|
12973
|
+
if (parts.length !== 2) {
|
|
12974
|
+
return item;
|
|
12975
|
+
}
|
|
12976
|
+
const field = parts[0];
|
|
12977
|
+
const direction = parts[1];
|
|
12978
|
+
if (typeof field !== "string" || typeof direction !== "string") {
|
|
12979
|
+
return item;
|
|
12980
|
+
}
|
|
12914
12981
|
return `${snakeCase(field.trim())}#${direction.trim()}`;
|
|
12915
12982
|
});
|
|
12916
12983
|
}
|
|
@@ -12920,14 +12987,26 @@ class DbUtils {
|
|
|
12920
12987
|
}
|
|
12921
12988
|
if (field.toUpperCase().includes(" AS ")) {
|
|
12922
12989
|
const parts = field.split(/\s+AS\s+/i);
|
|
12923
|
-
const fieldPart = parts[0]
|
|
12924
|
-
const aliasPart = parts[1]
|
|
12925
|
-
|
|
12990
|
+
const fieldPart = parts[0];
|
|
12991
|
+
const aliasPart = parts[1];
|
|
12992
|
+
if (typeof fieldPart !== "string" || typeof aliasPart !== "string") {
|
|
12993
|
+
return field;
|
|
12994
|
+
}
|
|
12995
|
+
return `${DbUtils.processJoinField(fieldPart.trim())} AS ${aliasPart.trim()}`;
|
|
12926
12996
|
}
|
|
12927
12997
|
if (field.includes(".")) {
|
|
12928
12998
|
const parts = field.split(".");
|
|
12929
|
-
|
|
12930
|
-
|
|
12999
|
+
if (parts.length < 2) {
|
|
13000
|
+
return snakeCase(field);
|
|
13001
|
+
}
|
|
13002
|
+
if (parts.some((p) => p.trim() === "")) {
|
|
13003
|
+
return field;
|
|
13004
|
+
}
|
|
13005
|
+
const fieldName = parts[parts.length - 1];
|
|
13006
|
+
const tableName = parts.slice(0, parts.length - 1).join(".");
|
|
13007
|
+
if (typeof fieldName !== "string" || typeof tableName !== "string") {
|
|
13008
|
+
return snakeCase(field);
|
|
13009
|
+
}
|
|
12931
13010
|
return `${tableName.trim()}.${snakeCase(fieldName)}`;
|
|
12932
13011
|
}
|
|
12933
13012
|
return snakeCase(field);
|
|
@@ -12942,16 +13021,34 @@ class DbUtils {
|
|
|
12942
13021
|
const operator = key.substring(lastDollarIndex);
|
|
12943
13022
|
if (fieldPart.includes(".")) {
|
|
12944
13023
|
const parts = fieldPart.split(".");
|
|
12945
|
-
|
|
12946
|
-
|
|
13024
|
+
if (parts.length < 2) {
|
|
13025
|
+
return `${snakeCase(fieldPart)}${operator}`;
|
|
13026
|
+
}
|
|
13027
|
+
if (parts.some((p) => p.trim() === "")) {
|
|
13028
|
+
return `${snakeCase(fieldPart)}${operator}`;
|
|
13029
|
+
}
|
|
13030
|
+
const fieldName = parts[parts.length - 1];
|
|
13031
|
+
const tableName = parts.slice(0, parts.length - 1).join(".");
|
|
13032
|
+
if (typeof fieldName !== "string" || typeof tableName !== "string") {
|
|
13033
|
+
return `${snakeCase(fieldPart)}${operator}`;
|
|
13034
|
+
}
|
|
12947
13035
|
return `${tableName.trim()}.${snakeCase(fieldName)}${operator}`;
|
|
12948
13036
|
}
|
|
12949
13037
|
return `${snakeCase(fieldPart)}${operator}`;
|
|
12950
13038
|
}
|
|
12951
13039
|
if (key.includes(".")) {
|
|
12952
13040
|
const parts = key.split(".");
|
|
12953
|
-
|
|
12954
|
-
|
|
13041
|
+
if (parts.length < 2) {
|
|
13042
|
+
return snakeCase(key);
|
|
13043
|
+
}
|
|
13044
|
+
if (parts.some((p) => p.trim() === "")) {
|
|
13045
|
+
return snakeCase(key);
|
|
13046
|
+
}
|
|
13047
|
+
const fieldName = parts[parts.length - 1];
|
|
13048
|
+
const tableName = parts.slice(0, parts.length - 1).join(".");
|
|
13049
|
+
if (typeof fieldName !== "string" || typeof tableName !== "string") {
|
|
13050
|
+
return snakeCase(key);
|
|
13051
|
+
}
|
|
12955
13052
|
return `${tableName.trim()}.${snakeCase(fieldName)}`;
|
|
12956
13053
|
}
|
|
12957
13054
|
return snakeCase(key);
|
|
@@ -12984,7 +13081,15 @@ class DbUtils {
|
|
|
12984
13081
|
if (typeof item !== "string" || !item.includes("#")) {
|
|
12985
13082
|
return item;
|
|
12986
13083
|
}
|
|
12987
|
-
const
|
|
13084
|
+
const parts = item.split("#");
|
|
13085
|
+
if (parts.length !== 2) {
|
|
13086
|
+
return item;
|
|
13087
|
+
}
|
|
13088
|
+
const field = parts[0];
|
|
13089
|
+
const direction = parts[1];
|
|
13090
|
+
if (typeof field !== "string" || typeof direction !== "string") {
|
|
13091
|
+
return item;
|
|
13092
|
+
}
|
|
12988
13093
|
return `${DbUtils.processJoinField(field.trim())}#${direction.trim()}`;
|
|
12989
13094
|
});
|
|
12990
13095
|
}
|
|
@@ -13105,10 +13210,10 @@ class DbUtils {
|
|
|
13105
13210
|
for (const [key, value] of Object.entries(userData)) {
|
|
13106
13211
|
result[key] = value;
|
|
13107
13212
|
}
|
|
13108
|
-
result
|
|
13109
|
-
result
|
|
13110
|
-
result
|
|
13111
|
-
result
|
|
13213
|
+
result["id"] = options.id;
|
|
13214
|
+
result["created_at"] = options.now;
|
|
13215
|
+
result["updated_at"] = options.now;
|
|
13216
|
+
result["state"] = 1;
|
|
13112
13217
|
return result;
|
|
13113
13218
|
}
|
|
13114
13219
|
static buildUpdateRow(options) {
|
|
@@ -13118,7 +13223,7 @@ class DbUtils {
|
|
|
13118
13223
|
for (const [key, value] of Object.entries(userData)) {
|
|
13119
13224
|
result[key] = value;
|
|
13120
13225
|
}
|
|
13121
|
-
result
|
|
13226
|
+
result["updated_at"] = options.now;
|
|
13122
13227
|
return result;
|
|
13123
13228
|
}
|
|
13124
13229
|
static buildPartialUpdateData(options) {
|
|
@@ -13242,6 +13347,7 @@ var SqlBuilderError = {
|
|
|
13242
13347
|
QUOTE_IDENT_NEED_STRING: (identifier) => `quoteIdent \u9700\u8981\u5B57\u7B26\u4E32\u7C7B\u578B\u6807\u8BC6\u7B26 (identifier: ${String(identifier)})`,
|
|
13243
13348
|
IDENT_EMPTY: "SQL \u6807\u8BC6\u7B26\u4E0D\u80FD\u4E3A\u7A7A",
|
|
13244
13349
|
FIELD_EXPR_NOT_ALLOWED: (field) => `\u5B57\u6BB5\u5305\u542B\u51FD\u6570/\u8868\u8FBE\u5F0F\uFF0C\u8BF7\u4F7F\u7528 selectRaw/whereRaw (field: ${field})`,
|
|
13350
|
+
FIELD_INVALID: (field) => `\u5B57\u6BB5\u683C\u5F0F\u975E\u6CD5\uFF0C\u8BF7\u4F7F\u7528\u7B80\u5355\u5B57\u6BB5\u540D\u6216\u5B89\u5168\u5F15\u7528\uFF0C\u590D\u6742\u8868\u8FBE\u5F0F\u8BF7\u4F7F\u7528 selectRaw/whereRaw (field: ${field})`,
|
|
13245
13351
|
FROM_EMPTY: "FROM \u8868\u540D\u4E0D\u80FD\u4E3A\u7A7A",
|
|
13246
13352
|
FROM_NEED_NON_EMPTY: (table) => `FROM \u8868\u540D\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32 (table: ${String(table)})`,
|
|
13247
13353
|
FROM_REQUIRED: "FROM \u8868\u540D\u662F\u5FC5\u9700\u7684",
|
|
@@ -13345,10 +13451,18 @@ class SqlBuilder {
|
|
|
13345
13451
|
}
|
|
13346
13452
|
if (field.toUpperCase().includes(" AS ")) {
|
|
13347
13453
|
const parts = field.split(/\s+AS\s+/i);
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13454
|
+
if (parts.length !== 2) {
|
|
13455
|
+
throw new Error(SqlBuilderError.FIELD_INVALID(field));
|
|
13456
|
+
}
|
|
13457
|
+
const fieldPart = parts[0];
|
|
13458
|
+
const aliasPart = parts[1];
|
|
13459
|
+
if (typeof fieldPart !== "string" || typeof aliasPart !== "string") {
|
|
13460
|
+
throw new Error(SqlBuilderError.FIELD_INVALID(field));
|
|
13461
|
+
}
|
|
13462
|
+
const cleanFieldPart = fieldPart.trim();
|
|
13463
|
+
const cleanAliasPart = aliasPart.trim();
|
|
13464
|
+
SqlCheck.assertSafeAlias(cleanAliasPart);
|
|
13465
|
+
return `${this._escapeField(cleanFieldPart)} AS ${cleanAliasPart}`;
|
|
13352
13466
|
}
|
|
13353
13467
|
if (field.includes(".")) {
|
|
13354
13468
|
const parts = field.split(".");
|
|
@@ -13382,16 +13496,26 @@ class SqlBuilder {
|
|
|
13382
13496
|
if (parts.length > 2) {
|
|
13383
13497
|
throw new Error(SqlBuilderError.TABLE_REF_TOO_MANY_PARTS(table));
|
|
13384
13498
|
}
|
|
13385
|
-
const
|
|
13386
|
-
|
|
13499
|
+
const namePartRaw = parts[0];
|
|
13500
|
+
if (typeof namePartRaw !== "string" || namePartRaw.trim() === "") {
|
|
13501
|
+
throw new Error(SqlBuilderError.FROM_EMPTY);
|
|
13502
|
+
}
|
|
13503
|
+
const namePart = namePartRaw.trim();
|
|
13504
|
+
const aliasPartRaw = parts.length === 2 ? parts[1] : null;
|
|
13505
|
+
const aliasPart = typeof aliasPartRaw === "string" ? aliasPartRaw.trim() : null;
|
|
13387
13506
|
const nameSegments = namePart.split(".");
|
|
13388
13507
|
if (nameSegments.length > 2) {
|
|
13389
13508
|
throw new Error(SqlBuilderError.TABLE_REF_SCHEMA_TOO_DEEP(table));
|
|
13390
13509
|
}
|
|
13391
13510
|
let escapedName = "";
|
|
13392
13511
|
if (nameSegments.length === 2) {
|
|
13393
|
-
const
|
|
13394
|
-
const
|
|
13512
|
+
const schemaRaw = nameSegments[0];
|
|
13513
|
+
const tableNameRaw = nameSegments[1];
|
|
13514
|
+
if (typeof schemaRaw !== "string" || typeof tableNameRaw !== "string") {
|
|
13515
|
+
throw new Error(SqlBuilderError.TABLE_REF_SCHEMA_TOO_DEEP(table));
|
|
13516
|
+
}
|
|
13517
|
+
const schema = schemaRaw.trim();
|
|
13518
|
+
const tableName = tableNameRaw.trim();
|
|
13395
13519
|
const escapedSchema = this._isQuotedIdent(schema) ? schema : (() => {
|
|
13396
13520
|
if (this._startsWithQuote(schema) && !this._isQuotedIdent(schema)) {
|
|
13397
13521
|
throw new Error(SqlBuilderError.SCHEMA_QUOTE_NOT_PAIRED(schema));
|
|
@@ -13408,7 +13532,11 @@ class SqlBuilder {
|
|
|
13408
13532
|
})();
|
|
13409
13533
|
escapedName = `${escapedSchema}.${escapedTableName}`;
|
|
13410
13534
|
} else {
|
|
13411
|
-
const
|
|
13535
|
+
const tableNameRaw = nameSegments[0];
|
|
13536
|
+
if (typeof tableNameRaw !== "string") {
|
|
13537
|
+
throw new Error(SqlBuilderError.FROM_EMPTY);
|
|
13538
|
+
}
|
|
13539
|
+
const tableName = tableNameRaw.trim();
|
|
13412
13540
|
if (this._isQuotedIdent(tableName)) {
|
|
13413
13541
|
escapedName = tableName;
|
|
13414
13542
|
} else {
|
|
@@ -13666,7 +13794,15 @@ class SqlBuilder {
|
|
|
13666
13794
|
if (typeof item !== "string" || !item.includes("#")) {
|
|
13667
13795
|
throw new Error(SqlBuilderError.ORDER_BY_ITEM_NEED_HASH(item));
|
|
13668
13796
|
}
|
|
13669
|
-
const
|
|
13797
|
+
const parts = item.split("#");
|
|
13798
|
+
if (parts.length !== 2) {
|
|
13799
|
+
throw new Error(SqlBuilderError.ORDER_BY_ITEM_NEED_HASH(item));
|
|
13800
|
+
}
|
|
13801
|
+
const fieldName = parts[0];
|
|
13802
|
+
const direction = parts[1];
|
|
13803
|
+
if (typeof fieldName !== "string" || typeof direction !== "string") {
|
|
13804
|
+
throw new Error(SqlBuilderError.ORDER_BY_ITEM_NEED_HASH(item));
|
|
13805
|
+
}
|
|
13670
13806
|
const cleanField = fieldName.trim();
|
|
13671
13807
|
const cleanDir = direction.trim().toUpperCase();
|
|
13672
13808
|
if (!cleanField) {
|
|
@@ -13763,7 +13899,9 @@ class SqlBuilder {
|
|
|
13763
13899
|
for (let i = 0;i < data.length; i++) {
|
|
13764
13900
|
const row = data[i];
|
|
13765
13901
|
for (const field of fields) {
|
|
13766
|
-
|
|
13902
|
+
const value = row[field];
|
|
13903
|
+
this._validateParam(value);
|
|
13904
|
+
params.push(value);
|
|
13767
13905
|
}
|
|
13768
13906
|
}
|
|
13769
13907
|
return { sql, params };
|
|
@@ -13778,7 +13916,12 @@ class SqlBuilder {
|
|
|
13778
13916
|
const escapedFields = fields.map((field) => this._escapeField(field));
|
|
13779
13917
|
const placeholders = fields.map(() => "?").join(", ");
|
|
13780
13918
|
const sql = `INSERT INTO ${escapedTable} (${escapedFields.join(", ")}) VALUES (${placeholders})`;
|
|
13781
|
-
const params =
|
|
13919
|
+
const params = [];
|
|
13920
|
+
for (const field of fields) {
|
|
13921
|
+
const value = data[field];
|
|
13922
|
+
this._validateParam(value);
|
|
13923
|
+
params.push(value);
|
|
13924
|
+
}
|
|
13782
13925
|
return { sql, params };
|
|
13783
13926
|
}
|
|
13784
13927
|
}
|
|
@@ -13880,7 +14023,9 @@ class SqlBuilder {
|
|
|
13880
14023
|
}
|
|
13881
14024
|
whenList.push("WHEN ? THEN ?");
|
|
13882
14025
|
args.push(row.id);
|
|
13883
|
-
|
|
14026
|
+
const value = row.data[field];
|
|
14027
|
+
SqlCheck.assertNoUndefinedParam(value, "SQL \u53C2\u6570\u503C");
|
|
14028
|
+
args.push(value);
|
|
13884
14029
|
}
|
|
13885
14030
|
if (whenList.length === 0) {
|
|
13886
14031
|
continue;
|
|
@@ -13912,7 +14057,7 @@ class DbHelper {
|
|
|
13912
14057
|
constructor(options) {
|
|
13913
14058
|
this.redis = options.redis;
|
|
13914
14059
|
this.sql = options.sql || null;
|
|
13915
|
-
this.isTransaction =
|
|
14060
|
+
this.isTransaction = Boolean(options.sql);
|
|
13916
14061
|
this.dialect = options.dialect ? options.dialect : new MySqlDialect;
|
|
13917
14062
|
}
|
|
13918
14063
|
createSqlBuilder() {
|
|
@@ -14042,7 +14187,8 @@ class DbHelper {
|
|
|
14042
14187
|
}
|
|
14043
14188
|
async getCount(options) {
|
|
14044
14189
|
const { table, where, joins, tableQualifier } = await this.prepareQueryOptions(options);
|
|
14045
|
-
const
|
|
14190
|
+
const hasJoins = Array.isArray(joins) && joins.length > 0;
|
|
14191
|
+
const builder = this.createSqlBuilder().selectRaw("COUNT(*) as count").from(table).where(DbUtils.addDefaultStateFilter(where, tableQualifier, hasJoins));
|
|
14046
14192
|
this.applyJoins(builder, joins);
|
|
14047
14193
|
const { sql, params } = builder.toSelectSql();
|
|
14048
14194
|
const execRes = await this.executeWithConn(sql, params);
|
|
@@ -14054,7 +14200,8 @@ class DbHelper {
|
|
|
14054
14200
|
}
|
|
14055
14201
|
async getOne(options) {
|
|
14056
14202
|
const { table, fields, where, joins, tableQualifier } = await this.prepareQueryOptions(options);
|
|
14057
|
-
const
|
|
14203
|
+
const hasJoins = Array.isArray(joins) && joins.length > 0;
|
|
14204
|
+
const builder = this.createSqlBuilder().select(fields).from(table).where(DbUtils.addDefaultStateFilter(where, tableQualifier, hasJoins));
|
|
14058
14205
|
this.applyJoins(builder, joins);
|
|
14059
14206
|
const { sql, params } = builder.toSelectSql();
|
|
14060
14207
|
const execRes = await this.executeWithConn(sql, params);
|
|
@@ -14074,12 +14221,16 @@ class DbHelper {
|
|
|
14074
14221
|
sql: execRes.sql
|
|
14075
14222
|
};
|
|
14076
14223
|
}
|
|
14077
|
-
const
|
|
14224
|
+
const convertedList = convertBigIntFields([deserialized]);
|
|
14225
|
+
const data = convertedList[0] ?? deserialized;
|
|
14078
14226
|
return {
|
|
14079
14227
|
data,
|
|
14080
14228
|
sql: execRes.sql
|
|
14081
14229
|
};
|
|
14082
14230
|
}
|
|
14231
|
+
async getDetail(options) {
|
|
14232
|
+
return await this.getOne(options);
|
|
14233
|
+
}
|
|
14083
14234
|
async getList(options) {
|
|
14084
14235
|
const prepared = await this.prepareQueryOptions(options);
|
|
14085
14236
|
if (prepared.page < 1 || prepared.page > 1e4) {
|
|
@@ -14088,7 +14239,7 @@ class DbHelper {
|
|
|
14088
14239
|
if (prepared.limit < 1 || prepared.limit > 1000) {
|
|
14089
14240
|
throw new Error(`\u6BCF\u9875\u6570\u91CF\u5FC5\u987B\u5728 1 \u5230 1000 \u4E4B\u95F4 (table: ${options.table}, page: ${prepared.page}, limit: ${prepared.limit})`);
|
|
14090
14241
|
}
|
|
14091
|
-
const whereFiltered = DbUtils.addDefaultStateFilter(prepared.where, prepared.tableQualifier,
|
|
14242
|
+
const whereFiltered = DbUtils.addDefaultStateFilter(prepared.where, prepared.tableQualifier, Array.isArray(prepared.joins) && prepared.joins.length > 0);
|
|
14092
14243
|
const countBuilder = this.createSqlBuilder().selectRaw("COUNT(*) as total").from(prepared.table).where(whereFiltered);
|
|
14093
14244
|
this.applyJoins(countBuilder, prepared.joins);
|
|
14094
14245
|
const { sql: countSql, params: countParams } = countBuilder.toSelectSql();
|
|
@@ -14136,8 +14287,21 @@ class DbHelper {
|
|
|
14136
14287
|
async getAll(options) {
|
|
14137
14288
|
const MAX_LIMIT = 1e4;
|
|
14138
14289
|
const WARNING_LIMIT = 1000;
|
|
14139
|
-
const
|
|
14140
|
-
|
|
14290
|
+
const prepareOptions = {
|
|
14291
|
+
table: options.table,
|
|
14292
|
+
page: 1,
|
|
14293
|
+
limit: 10
|
|
14294
|
+
};
|
|
14295
|
+
if (options.fields !== undefined)
|
|
14296
|
+
prepareOptions.fields = options.fields;
|
|
14297
|
+
if (options.where !== undefined)
|
|
14298
|
+
prepareOptions.where = options.where;
|
|
14299
|
+
if (options.joins !== undefined)
|
|
14300
|
+
prepareOptions.joins = options.joins;
|
|
14301
|
+
if (options.orderBy !== undefined)
|
|
14302
|
+
prepareOptions.orderBy = options.orderBy;
|
|
14303
|
+
const prepared = await this.prepareQueryOptions(prepareOptions);
|
|
14304
|
+
const whereFiltered = DbUtils.addDefaultStateFilter(prepared.where, prepared.tableQualifier, Array.isArray(prepared.joins) && prepared.joins.length > 0);
|
|
14141
14305
|
const countBuilder = this.createSqlBuilder().selectRaw("COUNT(*) as total").from(prepared.table).where(whereFiltered);
|
|
14142
14306
|
this.applyJoins(countBuilder, prepared.joins);
|
|
14143
14307
|
const { sql: countSql, params: countParams } = countBuilder.toSelectSql();
|
|
@@ -14197,7 +14361,7 @@ class DbHelper {
|
|
|
14197
14361
|
const builder = this.createSqlBuilder();
|
|
14198
14362
|
const { sql, params } = builder.toInsertSql(snakeTable, processed);
|
|
14199
14363
|
const execRes = await this.executeWithConn(sql, params);
|
|
14200
|
-
const insertedId = processed
|
|
14364
|
+
const insertedId = processed["id"] || execRes.data?.lastInsertRowid || 0;
|
|
14201
14365
|
return {
|
|
14202
14366
|
data: insertedId,
|
|
14203
14367
|
sql: execRes.sql
|
|
@@ -14222,7 +14386,11 @@ class DbHelper {
|
|
|
14222
14386
|
}
|
|
14223
14387
|
const now = Date.now();
|
|
14224
14388
|
const processedList = dataList.map((data, index) => {
|
|
14225
|
-
|
|
14389
|
+
const id = ids[index];
|
|
14390
|
+
if (typeof id !== "number") {
|
|
14391
|
+
throw new Error(`\u6279\u91CF\u63D2\u5165\u751F\u6210 ID \u5931\u8D25\uFF1Aids[${index}] \u4E0D\u662F number (table: ${snakeTable})`);
|
|
14392
|
+
}
|
|
14393
|
+
return DbUtils.buildInsertRow({ data, id, now });
|
|
14226
14394
|
});
|
|
14227
14395
|
const insertFields = SqlCheck.assertBatchInsertRowsConsistent(processedList, { table: snakeTable });
|
|
14228
14396
|
const builder = this.createSqlBuilder();
|
|
@@ -14505,38 +14673,50 @@ class Jwt {
|
|
|
14505
14673
|
};
|
|
14506
14674
|
}
|
|
14507
14675
|
sign(payload, options = {}) {
|
|
14508
|
-
const key = options.secret || this.config.secret
|
|
14676
|
+
const key = options.secret || this.config.secret;
|
|
14509
14677
|
const algorithm = options.algorithm || this.config.algorithm || "HS256";
|
|
14510
|
-
const
|
|
14678
|
+
const signerOptions = {
|
|
14511
14679
|
key,
|
|
14512
14680
|
algorithm,
|
|
14513
|
-
expiresIn: options.expiresIn
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
|
|
14681
|
+
expiresIn: options.expiresIn ?? this.config.expiresIn
|
|
14682
|
+
};
|
|
14683
|
+
if (options.issuer !== undefined)
|
|
14684
|
+
signerOptions.iss = options.issuer;
|
|
14685
|
+
if (options.audience !== undefined)
|
|
14686
|
+
signerOptions.aud = options.audience;
|
|
14687
|
+
if (options.subject !== undefined)
|
|
14688
|
+
signerOptions.sub = options.subject;
|
|
14689
|
+
if (options.jwtId !== undefined)
|
|
14690
|
+
signerOptions.jti = options.jwtId;
|
|
14691
|
+
if (typeof options.notBefore === "number")
|
|
14692
|
+
signerOptions.notBefore = options.notBefore;
|
|
14693
|
+
const signer = import_fast_jwt.createSigner(signerOptions);
|
|
14520
14694
|
return signer(payload);
|
|
14521
14695
|
}
|
|
14522
14696
|
verify(token, options = {}) {
|
|
14523
14697
|
if (!token || typeof token !== "string") {
|
|
14524
14698
|
throw new Error("Token\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
14525
14699
|
}
|
|
14526
|
-
const key = options.secret || this.config.secret
|
|
14700
|
+
const key = options.secret || this.config.secret;
|
|
14527
14701
|
const algorithm = this.config.algorithm || "HS256";
|
|
14528
14702
|
const algorithms = options.algorithms ? options.algorithms : [algorithm];
|
|
14529
|
-
const
|
|
14703
|
+
const verifierOptions = {
|
|
14530
14704
|
key,
|
|
14531
14705
|
algorithms,
|
|
14532
|
-
allowedIss: options.issuer,
|
|
14533
|
-
allowedAud: options.audience,
|
|
14534
|
-
allowedSub: options.subject,
|
|
14535
|
-
ignoreExpiration: options.ignoreExpiration,
|
|
14536
|
-
ignoreNotBefore: options.ignoreNotBefore,
|
|
14537
14706
|
cache: true,
|
|
14538
14707
|
cacheTTL: 600000
|
|
14539
|
-
}
|
|
14708
|
+
};
|
|
14709
|
+
if (options.issuer !== undefined)
|
|
14710
|
+
verifierOptions.allowedIss = options.issuer;
|
|
14711
|
+
if (options.audience !== undefined)
|
|
14712
|
+
verifierOptions.allowedAud = options.audience;
|
|
14713
|
+
if (options.subject !== undefined)
|
|
14714
|
+
verifierOptions.allowedSub = options.subject;
|
|
14715
|
+
if (typeof options.ignoreExpiration === "boolean")
|
|
14716
|
+
verifierOptions.ignoreExpiration = options.ignoreExpiration;
|
|
14717
|
+
if (typeof options.ignoreNotBefore === "boolean")
|
|
14718
|
+
verifierOptions.ignoreNotBefore = options.ignoreNotBefore;
|
|
14719
|
+
const verifier = import_fast_jwt.createVerifier(verifierOptions);
|
|
14540
14720
|
return verifier(token);
|
|
14541
14721
|
}
|
|
14542
14722
|
decode(token, complete = false) {
|
|
@@ -15147,7 +15327,7 @@ async function scanFiles(dir, source, type, pattern) {
|
|
|
15147
15327
|
const base = {
|
|
15148
15328
|
source,
|
|
15149
15329
|
type,
|
|
15150
|
-
sourceName:
|
|
15330
|
+
sourceName: source === "core" ? "\u6838\u5FC3" : source === "addon" ? "\u7EC4\u4EF6" : "\u9879\u76EE",
|
|
15151
15331
|
filePath: normalizedFile,
|
|
15152
15332
|
relativePath,
|
|
15153
15333
|
fileName,
|
|
@@ -15158,28 +15338,28 @@ async function scanFiles(dir, source, type, pattern) {
|
|
|
15158
15338
|
customKeys: isPlainObject(content) ? Object.keys(content) : []
|
|
15159
15339
|
};
|
|
15160
15340
|
if (type === "table") {
|
|
15161
|
-
base
|
|
15341
|
+
base["content"] = content;
|
|
15162
15342
|
results.push(base);
|
|
15163
15343
|
continue;
|
|
15164
15344
|
}
|
|
15165
15345
|
if (type === "api") {
|
|
15166
|
-
base
|
|
15167
|
-
base
|
|
15168
|
-
base
|
|
15169
|
-
base
|
|
15170
|
-
base
|
|
15346
|
+
base["auth"] = true;
|
|
15347
|
+
base["rawBody"] = false;
|
|
15348
|
+
base["method"] = "POST";
|
|
15349
|
+
base["fields"] = {};
|
|
15350
|
+
base["required"] = [];
|
|
15171
15351
|
}
|
|
15172
15352
|
if (type === "plugin" || type === "hook") {
|
|
15173
|
-
base
|
|
15174
|
-
base
|
|
15175
|
-
base
|
|
15353
|
+
base["deps"] = [];
|
|
15354
|
+
base["name"] = "";
|
|
15355
|
+
base["handler"] = null;
|
|
15176
15356
|
}
|
|
15177
15357
|
forOwn(content, (value, key) => {
|
|
15178
15358
|
base[key] = value;
|
|
15179
15359
|
});
|
|
15180
15360
|
if (type === "api") {
|
|
15181
|
-
base
|
|
15182
|
-
base
|
|
15361
|
+
base["routePrefix"] = source === "app" ? "/app" : `/addon/${addonName}`;
|
|
15362
|
+
base["path"] = `/api${base["routePrefix"]}/${relativePath}`;
|
|
15183
15363
|
}
|
|
15184
15364
|
results.push(base);
|
|
15185
15365
|
}
|
|
@@ -15235,11 +15415,11 @@ class Befly {
|
|
|
15235
15415
|
async start(env = {}) {
|
|
15236
15416
|
try {
|
|
15237
15417
|
const serverStartTime = Bun.nanoseconds();
|
|
15238
|
-
this.config = await loadBeflyConfig(env
|
|
15418
|
+
this.config = await loadBeflyConfig(env["NODE_ENV"] || "development");
|
|
15239
15419
|
this.context.config = this.config;
|
|
15240
15420
|
this.context.env = env;
|
|
15241
15421
|
const { apis, tables, plugins, hooks, addons } = await scanSources();
|
|
15242
|
-
this.context
|
|
15422
|
+
this.context["addons"] = addons;
|
|
15243
15423
|
await checkApi(apis);
|
|
15244
15424
|
await checkTable(tables);
|
|
15245
15425
|
await checkPlugin(plugins);
|
|
@@ -15262,15 +15442,23 @@ class Befly {
|
|
|
15262
15442
|
await syncTable(this.context, tables);
|
|
15263
15443
|
await syncApi(this.context, apis);
|
|
15264
15444
|
await syncMenu(this.context, checkedMenus);
|
|
15265
|
-
|
|
15445
|
+
const devEmail = this.config.devEmail;
|
|
15446
|
+
const devPassword = this.config.devPassword;
|
|
15447
|
+
if (typeof devEmail === "string" && devEmail.length > 0 && typeof devPassword === "string" && devPassword.length > 0) {
|
|
15448
|
+
await syncDev(this.context, { devEmail, devPassword });
|
|
15449
|
+
} else {
|
|
15450
|
+
Logger.debug("\u8DF3\u8FC7 syncDev\uFF1A\u672A\u914D\u7F6E devEmail/devPassword");
|
|
15451
|
+
}
|
|
15266
15452
|
await syncCache(this.context);
|
|
15267
15453
|
this.hooks = await loadHooks(hooks);
|
|
15268
15454
|
this.apis = await loadApis(apis);
|
|
15269
15455
|
const apiFetch = apiHandler(this.apis, this.hooks, this.context);
|
|
15270
15456
|
const staticFetch = staticHandler(this.config.cors);
|
|
15457
|
+
const port = typeof this.config.appPort === "number" ? this.config.appPort : 3000;
|
|
15458
|
+
const hostname = typeof this.config.appHost === "string" && this.config.appHost.length > 0 ? this.config.appHost : "0.0.0.0";
|
|
15271
15459
|
const server = Bun.serve({
|
|
15272
|
-
port
|
|
15273
|
-
hostname
|
|
15460
|
+
port,
|
|
15461
|
+
hostname,
|
|
15274
15462
|
development: this.config.nodeEnv === "development",
|
|
15275
15463
|
idleTimeout: 30,
|
|
15276
15464
|
fetch: async (req, bunServer) => {
|