befly 3.14.2 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/befly.config.js +1 -1
- package/dist/befly.js +618 -209
- package/dist/befly.min.js +13 -13
- package/dist/checks/checkApi.d.ts +1 -1
- package/dist/checks/checkApi.js +64 -24
- package/dist/checks/checkHook.js +20 -14
- package/dist/checks/checkPlugin.js +20 -14
- package/dist/checks/checkTable.js +6 -3
- package/dist/hooks/permission.js +1 -1
- package/dist/lib/cipher.js +3 -4
- package/dist/lib/connect.js +2 -1
- package/dist/lib/dbDialect.d.ts +4 -4
- package/dist/lib/dbDialect.js +3 -12
- package/dist/lib/dbHelper.d.ts +8 -3
- package/dist/lib/dbHelper.js +85 -35
- package/dist/lib/dbUtils.js +2 -2
- package/dist/lib/logger.d.ts +6 -11
- package/dist/lib/logger.js +15 -10
- package/dist/lib/sqlBuilder.js +10 -2
- package/dist/lib/validator.d.ts +3 -3
- package/dist/lib/validator.js +59 -7
- package/dist/loader/loadApis.js +38 -6
- package/dist/loader/loadHooks.js +12 -5
- package/dist/loader/loadPlugins.js +13 -6
- package/dist/plugins/tool.d.ts +11 -9
- package/dist/plugins/tool.js +1 -1
- package/dist/sync/syncApi.d.ts +2 -2
- package/dist/sync/syncApi.js +23 -11
- package/dist/sync/syncDev.js +2 -2
- package/dist/sync/syncMenu.js +3 -2
- package/dist/sync/syncTable.d.ts +22 -26
- package/dist/sync/syncTable.js +114 -25
- package/dist/types/api.d.ts +11 -10
- package/dist/types/befly.d.ts +17 -11
- package/dist/types/common.d.ts +23 -6
- package/dist/types/context.d.ts +7 -3
- package/dist/types/database.d.ts +50 -15
- package/dist/types/jwt.d.ts +3 -2
- package/dist/types/logger.d.ts +24 -7
- package/dist/types/sync.d.ts +7 -7
- package/dist/types/validate.d.ts +12 -4
- package/dist/utils/convertBigIntFields.d.ts +2 -1
- package/dist/utils/convertBigIntFields.js +3 -12
- package/dist/utils/isDirentDirectory.d.ts +2 -1
- package/dist/utils/loadMenuConfigs.d.ts +1 -1
- package/dist/utils/loadMenuConfigs.js +11 -3
- package/dist/utils/mergeAndConcat.d.ts +1 -1
- package/dist/utils/mergeAndConcat.js +22 -17
- package/dist/utils/normalizeFieldDefinition.d.ts +2 -1
- package/dist/utils/scanCoreBuiltins.js +9 -5
- package/dist/utils/scanFiles.d.ts +2 -2
- package/dist/utils/scanFiles.js +1 -1
- package/dist/utils/sortModules.js +8 -1
- package/dist/utils/sqlParams.d.ts +10 -0
- package/dist/utils/sqlParams.js +78 -0
- package/dist/utils/sqlResult.d.ts +5 -0
- package/dist/utils/sqlResult.js +7 -0
- package/dist/utils/util.d.ts +7 -6
- package/dist/utils/util.js +8 -5
- package/package.json +2 -2
package/dist/befly.js
CHANGED
|
@@ -90,8 +90,9 @@ function forOwn(obj, iteratee) {
|
|
|
90
90
|
if (!isPlainObject(obj)) {
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
const record = obj;
|
|
94
|
+
for (const key of Object.keys(record)) {
|
|
95
|
+
iteratee(record[key], key);
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
function toWordParts(input) {
|
|
@@ -559,7 +560,12 @@ class LogFileSink {
|
|
|
559
560
|
const ok = this.stream.write(chunk);
|
|
560
561
|
if (!ok) {
|
|
561
562
|
await new Promise((resolve) => {
|
|
562
|
-
this.stream
|
|
563
|
+
const stream = this.stream;
|
|
564
|
+
if (!stream) {
|
|
565
|
+
resolve();
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
stream.once("drain", () => resolve());
|
|
563
569
|
});
|
|
564
570
|
}
|
|
565
571
|
this.streamSizeBytes = this.streamSizeBytes + chunkBytes;
|
|
@@ -829,7 +835,8 @@ function createSinkLogger(options) {
|
|
|
829
835
|
const write = (level, record) => {
|
|
830
836
|
if (level === "debug" && config.debug !== 1)
|
|
831
837
|
return;
|
|
832
|
-
const
|
|
838
|
+
const input = isPlainObject(record) ? record : { value: record };
|
|
839
|
+
const sanitizedRecord = sanitizeLogObject(input, sanitizeOptions);
|
|
833
840
|
const line = buildLogLine(level, sanitizedRecord);
|
|
834
841
|
fileSink.enqueue(line);
|
|
835
842
|
if (consoleSink)
|
|
@@ -871,8 +878,8 @@ function metaToObject() {
|
|
|
871
878
|
}
|
|
872
879
|
function mergeMetaIntoObject(input, meta) {
|
|
873
880
|
const merged = {};
|
|
874
|
-
for (const
|
|
875
|
-
merged[key] =
|
|
881
|
+
for (const key of Object.keys(input)) {
|
|
882
|
+
merged[key] = input[key];
|
|
876
883
|
}
|
|
877
884
|
const keys = ["requestId", "method", "route", "ip", "now", "durationSinceNowMs", "userId", "roleCode", "nickname", "roleType"];
|
|
878
885
|
for (const key of keys) {
|
|
@@ -919,28 +926,27 @@ class LoggerFacade {
|
|
|
919
926
|
info(input) {
|
|
920
927
|
const record0 = withRequestMetaRecord(toRecord(input));
|
|
921
928
|
const record = this.maybeSanitizeForMock(record0);
|
|
922
|
-
|
|
929
|
+
getSink("app").info(record);
|
|
923
930
|
}
|
|
924
931
|
warn(input) {
|
|
925
932
|
const record0 = withRequestMetaRecord(toRecord(input));
|
|
926
933
|
const record = this.maybeSanitizeForMock(record0);
|
|
927
|
-
|
|
934
|
+
getSink("app").warn(record);
|
|
928
935
|
}
|
|
929
936
|
error(input) {
|
|
930
937
|
const record0 = withRequestMetaRecord(toRecord(input));
|
|
931
938
|
const record = this.maybeSanitizeForMock(record0);
|
|
932
|
-
|
|
939
|
+
getSink("app").error(record);
|
|
933
940
|
if (mockInstance)
|
|
934
|
-
return
|
|
941
|
+
return;
|
|
935
942
|
getSink("error").error(record);
|
|
936
|
-
return ret;
|
|
937
943
|
}
|
|
938
944
|
debug(input) {
|
|
939
945
|
if (config.debug !== 1)
|
|
940
946
|
return;
|
|
941
947
|
const record0 = withRequestMetaRecord(toRecord(input));
|
|
942
948
|
const record = this.maybeSanitizeForMock(record0);
|
|
943
|
-
|
|
949
|
+
getSink("app").debug(record);
|
|
944
950
|
}
|
|
945
951
|
async flush() {
|
|
946
952
|
await flush();
|
|
@@ -1255,12 +1261,20 @@ function normalizeViewDirMeta(input) {
|
|
|
1255
1261
|
if (!input || typeof input !== "object") {
|
|
1256
1262
|
return null;
|
|
1257
1263
|
}
|
|
1258
|
-
|
|
1264
|
+
const record = input;
|
|
1265
|
+
const title = record["title"];
|
|
1266
|
+
if (typeof title !== "string" || !title) {
|
|
1259
1267
|
return null;
|
|
1260
1268
|
}
|
|
1261
|
-
const
|
|
1269
|
+
const orderRaw = record["order"];
|
|
1270
|
+
const order = typeof orderRaw === "number" && Number.isFinite(orderRaw) && Number.isInteger(orderRaw) && orderRaw >= 0 ? orderRaw : undefined;
|
|
1271
|
+
if (order === undefined) {
|
|
1272
|
+
return {
|
|
1273
|
+
title
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1262
1276
|
return {
|
|
1263
|
-
title
|
|
1277
|
+
title,
|
|
1264
1278
|
order
|
|
1265
1279
|
};
|
|
1266
1280
|
}
|
|
@@ -7446,8 +7460,9 @@ function cloneDeepLoose(value) {
|
|
|
7446
7460
|
}
|
|
7447
7461
|
if (isPlainObject(value)) {
|
|
7448
7462
|
const out = {};
|
|
7449
|
-
|
|
7450
|
-
|
|
7463
|
+
const record = value;
|
|
7464
|
+
for (const key of Object.keys(record)) {
|
|
7465
|
+
out[key] = cloneDeepLoose(record[key]);
|
|
7451
7466
|
}
|
|
7452
7467
|
return out;
|
|
7453
7468
|
}
|
|
@@ -7458,18 +7473,28 @@ function mergeInto(target, source) {
|
|
|
7458
7473
|
return target;
|
|
7459
7474
|
}
|
|
7460
7475
|
if (Array.isArray(target) && Array.isArray(source)) {
|
|
7476
|
+
const nextArr = [];
|
|
7477
|
+
for (const item of target) {
|
|
7478
|
+
nextArr.push(cloneDeepLoose(item));
|
|
7479
|
+
}
|
|
7461
7480
|
for (const item of source) {
|
|
7462
|
-
|
|
7481
|
+
nextArr.push(cloneDeepLoose(item));
|
|
7463
7482
|
}
|
|
7464
|
-
return
|
|
7483
|
+
return nextArr;
|
|
7465
7484
|
}
|
|
7466
7485
|
if (isPlainObject(target) && isPlainObject(source)) {
|
|
7467
|
-
|
|
7468
|
-
|
|
7486
|
+
const targetRecord = target;
|
|
7487
|
+
const sourceRecord = source;
|
|
7488
|
+
const out = {};
|
|
7489
|
+
for (const key of Object.keys(targetRecord)) {
|
|
7490
|
+
out[key] = cloneDeepLoose(targetRecord[key]);
|
|
7491
|
+
}
|
|
7492
|
+
for (const key of Object.keys(sourceRecord)) {
|
|
7493
|
+
const srcVal = sourceRecord[key];
|
|
7469
7494
|
if (srcVal === undefined) {
|
|
7470
7495
|
continue;
|
|
7471
7496
|
}
|
|
7472
|
-
const curVal =
|
|
7497
|
+
const curVal = out[key];
|
|
7473
7498
|
if (Array.isArray(curVal) && Array.isArray(srcVal)) {
|
|
7474
7499
|
const nextArr = [];
|
|
7475
7500
|
for (const item of curVal) {
|
|
@@ -7478,16 +7503,16 @@ function mergeInto(target, source) {
|
|
|
7478
7503
|
for (const item of srcVal) {
|
|
7479
7504
|
nextArr.push(cloneDeepLoose(item));
|
|
7480
7505
|
}
|
|
7481
|
-
|
|
7506
|
+
out[key] = nextArr;
|
|
7482
7507
|
continue;
|
|
7483
7508
|
}
|
|
7484
7509
|
if (isPlainObject(curVal) && isPlainObject(srcVal)) {
|
|
7485
|
-
|
|
7510
|
+
out[key] = mergeInto(cloneDeepLoose(curVal), srcVal);
|
|
7486
7511
|
continue;
|
|
7487
7512
|
}
|
|
7488
|
-
|
|
7513
|
+
out[key] = cloneDeepLoose(srcVal);
|
|
7489
7514
|
}
|
|
7490
|
-
return
|
|
7515
|
+
return out;
|
|
7491
7516
|
}
|
|
7492
7517
|
return cloneDeepLoose(source);
|
|
7493
7518
|
}
|
|
@@ -7571,7 +7596,7 @@ async function loadBeflyConfig(nodeEnv) {
|
|
|
7571
7596
|
const envConfig = await importDefault(join(configsDir, `befly.${nodeEnv}.json`), {});
|
|
7572
7597
|
const config2 = mergeAndConcat(defaultOptions, commonConfig, envConfig);
|
|
7573
7598
|
config2.nodeEnv = nodeEnv;
|
|
7574
|
-
const redisPrefix = config2
|
|
7599
|
+
const redisPrefix = config2.redis?.prefix;
|
|
7575
7600
|
if (typeof redisPrefix === "string") {
|
|
7576
7601
|
const trimmedPrefix = redisPrefix.trim();
|
|
7577
7602
|
if (trimmedPrefix.includes(":")) {
|
|
@@ -7586,63 +7611,100 @@ init_logger();
|
|
|
7586
7611
|
init_util();
|
|
7587
7612
|
async function checkApi(apis) {
|
|
7588
7613
|
let hasError = false;
|
|
7614
|
+
const seenPaths = new Set;
|
|
7589
7615
|
for (const api of apis) {
|
|
7590
7616
|
try {
|
|
7591
|
-
if (
|
|
7592
|
-
Logger.warn(
|
|
7617
|
+
if (!isPlainObject(api)) {
|
|
7618
|
+
Logger.warn({ item: api, msg: "\u63A5\u53E3\u5FC5\u987B\u662F\u5BF9\u8C61" });
|
|
7619
|
+
hasError = true;
|
|
7620
|
+
continue;
|
|
7621
|
+
}
|
|
7622
|
+
const record = api;
|
|
7623
|
+
const name = record["name"];
|
|
7624
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
7625
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 name \u5C5E\u6027\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32" }));
|
|
7593
7626
|
hasError = true;
|
|
7594
7627
|
continue;
|
|
7595
7628
|
}
|
|
7596
|
-
|
|
7597
|
-
|
|
7629
|
+
const handler = record["handler"];
|
|
7630
|
+
if (typeof handler !== "function") {
|
|
7631
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 handler \u5C5E\u6027\u5FC5\u987B\u662F\u51FD\u6570" }));
|
|
7598
7632
|
hasError = true;
|
|
7599
7633
|
continue;
|
|
7600
7634
|
}
|
|
7601
|
-
|
|
7602
|
-
|
|
7635
|
+
const rawPath = record["path"];
|
|
7636
|
+
if (typeof rawPath !== "string" || rawPath.trim() === "") {
|
|
7637
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u5C5E\u6027\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF09" }));
|
|
7603
7638
|
hasError = true;
|
|
7604
7639
|
} else {
|
|
7605
|
-
const path =
|
|
7640
|
+
const path = rawPath.trim();
|
|
7641
|
+
if (seenPaths.has(path)) {
|
|
7642
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u91CD\u590D\uFF08\u4E25\u683C\u6A21\u5F0F\u7981\u6B62\u91CD\u590D path\uFF09" }));
|
|
7643
|
+
hasError = true;
|
|
7644
|
+
} else {
|
|
7645
|
+
seenPaths.add(path);
|
|
7646
|
+
}
|
|
7606
7647
|
if (/^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b/i.test(path)) {
|
|
7607
|
-
Logger.warn(Object.assign({}, omit(
|
|
7648
|
+
Logger.warn(Object.assign({}, omit(record, ["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" }));
|
|
7608
7649
|
hasError = true;
|
|
7609
7650
|
}
|
|
7610
7651
|
if (!path.startsWith("/api/")) {
|
|
7611
|
-
Logger.warn(Object.assign({}, omit(
|
|
7652
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u5FC5\u987B\u4EE5 /api/ \u5F00\u5934" }));
|
|
7612
7653
|
hasError = true;
|
|
7613
7654
|
}
|
|
7614
7655
|
if (path.includes(" ")) {
|
|
7615
|
-
Logger.warn(Object.assign({}, omit(
|
|
7656
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u4E0D\u5141\u8BB8\u5305\u542B\u7A7A\u683C" }));
|
|
7616
7657
|
hasError = true;
|
|
7617
7658
|
}
|
|
7618
7659
|
if (path.includes("/api//")) {
|
|
7619
|
-
Logger.warn(Object.assign({}, omit(
|
|
7660
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 path \u4E0D\u5141\u8BB8\u51FA\u73B0 /api//\uFF08\u91CD\u590D\u659C\u6760\uFF09" }));
|
|
7620
7661
|
hasError = true;
|
|
7621
7662
|
}
|
|
7622
7663
|
}
|
|
7623
|
-
|
|
7624
|
-
|
|
7664
|
+
const routePrefix = record["routePrefix"];
|
|
7665
|
+
const routePrefixTrimmed = typeof routePrefix === "string" ? routePrefix.trim() : "";
|
|
7666
|
+
if (routePrefixTrimmed === "") {
|
|
7667
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 routePrefix \u5C5E\u6027\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF09" }));
|
|
7625
7668
|
hasError = true;
|
|
7669
|
+
} else {
|
|
7670
|
+
if (!(routePrefixTrimmed === "/app" || routePrefixTrimmed.startsWith("/addon/"))) {
|
|
7671
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 routePrefix \u5FC5\u987B\u662F /app \u6216 /addon/<name>\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF09" }));
|
|
7672
|
+
hasError = true;
|
|
7673
|
+
}
|
|
7674
|
+
if (typeof rawPath === "string" && rawPath.trim() !== "") {
|
|
7675
|
+
const path = rawPath.trim();
|
|
7676
|
+
const expectedPrefix = `/api${routePrefixTrimmed}/`;
|
|
7677
|
+
if (!path.startsWith(expectedPrefix)) {
|
|
7678
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { expectedPrefix, msg: "\u63A5\u53E3\u7684 path \u4E0E routePrefix \u4E0D\u4E00\u81F4\uFF1A\u5E94\u4EE5 /api${routePrefix}/ \u5F00\u5934\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF09" }));
|
|
7679
|
+
hasError = true;
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7626
7682
|
}
|
|
7627
|
-
|
|
7628
|
-
|
|
7683
|
+
const method = record["method"];
|
|
7684
|
+
if (method !== undefined && !["GET", "POST", "GET,POST"].includes(String(method).toUpperCase())) {
|
|
7685
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 method \u5C5E\u6027\u5FC5\u987B\u662F\u6709\u6548\u7684 HTTP \u65B9\u6CD5 (GET, POST, GET,POST)" }));
|
|
7629
7686
|
hasError = true;
|
|
7630
7687
|
}
|
|
7631
|
-
|
|
7632
|
-
|
|
7688
|
+
const auth = record["auth"];
|
|
7689
|
+
if (auth !== undefined && typeof auth !== "boolean") {
|
|
7690
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 auth \u5C5E\u6027\u5FC5\u987B\u662F\u5E03\u5C14\u503C (true=\u9700\u767B\u5F55, false=\u516C\u5F00)" }));
|
|
7633
7691
|
hasError = true;
|
|
7634
7692
|
}
|
|
7635
|
-
|
|
7636
|
-
|
|
7693
|
+
const fields = record["fields"];
|
|
7694
|
+
if (fields !== undefined && fields !== null && !isPlainObject(fields)) {
|
|
7695
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 fields \u5C5E\u6027\u5FC5\u987B\u662F\u5BF9\u8C61" }));
|
|
7637
7696
|
hasError = true;
|
|
7638
7697
|
}
|
|
7639
|
-
|
|
7640
|
-
|
|
7698
|
+
const required = record["required"];
|
|
7699
|
+
if (required !== undefined && !Array.isArray(required)) {
|
|
7700
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 required \u5C5E\u6027\u5FC5\u987B\u662F\u6570\u7EC4" }));
|
|
7641
7701
|
hasError = true;
|
|
7642
7702
|
}
|
|
7643
|
-
if (
|
|
7644
|
-
|
|
7645
|
-
|
|
7703
|
+
if (Array.isArray(required)) {
|
|
7704
|
+
if (required.some((reqItem) => typeof reqItem !== "string")) {
|
|
7705
|
+
Logger.warn(Object.assign({}, omit(record, ["handler"]), { msg: "\u63A5\u53E3\u7684 required \u5C5E\u6027\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4" }));
|
|
7706
|
+
hasError = true;
|
|
7707
|
+
}
|
|
7646
7708
|
}
|
|
7647
7709
|
} catch (error) {
|
|
7648
7710
|
Logger.error({ err: error, item: api, msg: "\u63A5\u53E3\u89E3\u6790\u5931\u8D25" });
|
|
@@ -7668,12 +7730,14 @@ async function checkHook(hooks) {
|
|
|
7668
7730
|
hasError = true;
|
|
7669
7731
|
continue;
|
|
7670
7732
|
}
|
|
7671
|
-
|
|
7733
|
+
const record = hook;
|
|
7734
|
+
const moduleName = record["moduleName"];
|
|
7735
|
+
if (typeof moduleName !== "string" || moduleName.trim() === "") {
|
|
7672
7736
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u7684 moduleName \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF0C\u7528\u4E8E deps \u4E0E\u8FD0\u884C\u65F6\u6302\u8F7D\uFF09" }));
|
|
7673
7737
|
hasError = true;
|
|
7674
7738
|
continue;
|
|
7675
7739
|
}
|
|
7676
|
-
const customKeys =
|
|
7740
|
+
const customKeys = record["customKeys"];
|
|
7677
7741
|
if (!Array.isArray(customKeys)) {
|
|
7678
7742
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u626B\u63CF\u7ED3\u679C\u7F3A\u5C11 customKeys\uFF08\u65E0\u6CD5\u5224\u65AD\u7528\u6237\u5BFC\u51FA\u7684\u5B57\u6BB5\u662F\u5426\u5408\u6CD5\uFF09" }));
|
|
7679
7743
|
hasError = true;
|
|
@@ -7693,16 +7757,17 @@ async function checkHook(hooks) {
|
|
|
7693
7757
|
const hasCustomEnable = customKeys.includes("enable");
|
|
7694
7758
|
const hasCustomDeps = customKeys.includes("deps");
|
|
7695
7759
|
if (hasCustomEnable) {
|
|
7696
|
-
|
|
7760
|
+
const enable = record["enable"];
|
|
7761
|
+
if (typeof enable !== "boolean") {
|
|
7697
7762
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u7684 enable \u5C5E\u6027\u5FC5\u987B\u662F boolean\uFF08true/false\uFF09\uFF0C\u4E0D\u5141\u8BB8 0/1 \u7B49\u5176\u4ED6\u7C7B\u578B" }));
|
|
7698
7763
|
hasError = true;
|
|
7699
7764
|
continue;
|
|
7700
7765
|
}
|
|
7701
7766
|
} else {
|
|
7702
|
-
|
|
7767
|
+
record["enable"] = true;
|
|
7703
7768
|
}
|
|
7704
|
-
if (
|
|
7705
|
-
const name = typeof
|
|
7769
|
+
if (record["source"] === "core") {
|
|
7770
|
+
const name = typeof record["name"] === "string" ? record["name"] : "";
|
|
7706
7771
|
if (name === "") {
|
|
7707
7772
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "core \u5185\u7F6E\u94A9\u5B50\u5FC5\u987B\u663E\u5F0F\u8BBE\u7F6E name\uFF08string\uFF09\uFF0C\u7528\u4E8E\u786E\u5B9A\u94A9\u5B50\u540D\u79F0" }));
|
|
7708
7773
|
hasError = true;
|
|
@@ -7713,39 +7778,42 @@ async function checkHook(hooks) {
|
|
|
7713
7778
|
hasError = true;
|
|
7714
7779
|
continue;
|
|
7715
7780
|
}
|
|
7716
|
-
if (!coreBuiltinNameRegexp.test(
|
|
7781
|
+
if (!coreBuiltinNameRegexp.test(String(record["moduleName"]))) {
|
|
7717
7782
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "core \u5185\u7F6E\u94A9\u5B50\u7684 moduleName \u5FC5\u987B\u6EE1\u8DB3\u5C0F\u5199\u5B57\u6BCD+\u4E0B\u5212\u7EBF\u683C\u5F0F\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF0C\u4E14\u5FC5\u987B\u4E0E name \u4E00\u81F4\uFF09" }));
|
|
7718
7783
|
hasError = true;
|
|
7719
7784
|
continue;
|
|
7720
7785
|
}
|
|
7721
|
-
if (name !==
|
|
7786
|
+
if (name !== String(record["moduleName"])) {
|
|
7722
7787
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "core \u5185\u7F6E\u94A9\u5B50\u7684 name \u5FC5\u987B\u4E0E moduleName \u5B8C\u5168\u4E00\u81F4" }));
|
|
7723
7788
|
hasError = true;
|
|
7724
7789
|
continue;
|
|
7725
7790
|
}
|
|
7726
|
-
|
|
7791
|
+
const filePath = record["filePath"];
|
|
7792
|
+
if (typeof filePath !== "string" || !filePath.startsWith(`core:hook:${name}`)) {
|
|
7727
7793
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "core \u5185\u7F6E\u94A9\u5B50\u5FC5\u987B\u6765\u81EA\u9759\u6001\u6CE8\u518C\uFF08filePath \u5FC5\u987B\u4EE5 core:hook:<name> \u5F00\u5934\uFF09\uFF0C\u4E0D\u5141\u8BB8\u901A\u8FC7\u626B\u63CF\u76EE\u5F55\u52A0\u8F7D" }));
|
|
7728
7794
|
hasError = true;
|
|
7729
7795
|
continue;
|
|
7730
7796
|
}
|
|
7731
7797
|
}
|
|
7732
7798
|
if (hasCustomDeps) {
|
|
7733
|
-
|
|
7799
|
+
const deps = record["deps"];
|
|
7800
|
+
if (!Array.isArray(deps)) {
|
|
7734
7801
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u7684 deps \u5C5E\u6027\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4" }));
|
|
7735
7802
|
hasError = true;
|
|
7736
7803
|
continue;
|
|
7737
7804
|
}
|
|
7738
|
-
if (
|
|
7805
|
+
if (deps.some((depItem) => typeof depItem !== "string")) {
|
|
7739
7806
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u7684 deps \u5C5E\u6027\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4" }));
|
|
7740
7807
|
hasError = true;
|
|
7741
7808
|
continue;
|
|
7742
7809
|
}
|
|
7743
7810
|
} else {
|
|
7744
|
-
|
|
7745
|
-
|
|
7811
|
+
const deps = record["deps"];
|
|
7812
|
+
if (!Array.isArray(deps)) {
|
|
7813
|
+
record["deps"] = [];
|
|
7746
7814
|
}
|
|
7747
7815
|
}
|
|
7748
|
-
if (typeof
|
|
7816
|
+
if (typeof record["handler"] !== "function") {
|
|
7749
7817
|
Logger.warn(Object.assign({}, omit(hook, ["handler"]), { msg: "\u94A9\u5B50\u7684 handler \u5C5E\u6027\u5FC5\u987B\u662F\u51FD\u6570" }));
|
|
7750
7818
|
hasError = true;
|
|
7751
7819
|
continue;
|
|
@@ -7880,12 +7948,14 @@ async function checkPlugin(plugins) {
|
|
|
7880
7948
|
hasError = true;
|
|
7881
7949
|
continue;
|
|
7882
7950
|
}
|
|
7883
|
-
|
|
7951
|
+
const record = plugin;
|
|
7952
|
+
const moduleName = record["moduleName"];
|
|
7953
|
+
if (typeof moduleName !== "string" || moduleName.trim() === "") {
|
|
7884
7954
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u7684 moduleName \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF0C\u7528\u4E8E deps \u4E0E\u8FD0\u884C\u65F6\u6302\u8F7D\uFF09" }));
|
|
7885
7955
|
hasError = true;
|
|
7886
7956
|
continue;
|
|
7887
7957
|
}
|
|
7888
|
-
const customKeys =
|
|
7958
|
+
const customKeys = record["customKeys"];
|
|
7889
7959
|
if (!Array.isArray(customKeys)) {
|
|
7890
7960
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u626B\u63CF\u7ED3\u679C\u7F3A\u5C11 customKeys\uFF08\u65E0\u6CD5\u5224\u65AD\u7528\u6237\u5BFC\u51FA\u7684\u5B57\u6BB5\u662F\u5426\u5408\u6CD5\uFF09" }));
|
|
7891
7961
|
hasError = true;
|
|
@@ -7905,16 +7975,17 @@ async function checkPlugin(plugins) {
|
|
|
7905
7975
|
const hasCustomEnable = customKeys.includes("enable");
|
|
7906
7976
|
const hasCustomDeps = customKeys.includes("deps");
|
|
7907
7977
|
if (hasCustomEnable) {
|
|
7908
|
-
|
|
7978
|
+
const enable = record["enable"];
|
|
7979
|
+
if (typeof enable !== "boolean") {
|
|
7909
7980
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u7684 enable \u5C5E\u6027\u5FC5\u987B\u662F boolean\uFF08true/false\uFF09\uFF0C\u4E0D\u5141\u8BB8 0/1 \u7B49\u5176\u4ED6\u7C7B\u578B" }));
|
|
7910
7981
|
hasError = true;
|
|
7911
7982
|
continue;
|
|
7912
7983
|
}
|
|
7913
7984
|
} else {
|
|
7914
|
-
|
|
7985
|
+
record["enable"] = true;
|
|
7915
7986
|
}
|
|
7916
|
-
if (
|
|
7917
|
-
const name = typeof
|
|
7987
|
+
if (record["source"] === "core") {
|
|
7988
|
+
const name = typeof record["name"] === "string" ? record["name"] : "";
|
|
7918
7989
|
if (name === "") {
|
|
7919
7990
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "core \u5185\u7F6E\u63D2\u4EF6\u5FC5\u987B\u663E\u5F0F\u8BBE\u7F6E name\uFF08string\uFF09\uFF0C\u7528\u4E8E\u786E\u5B9A\u63D2\u4EF6\u540D\u79F0" }));
|
|
7920
7991
|
hasError = true;
|
|
@@ -7925,39 +7996,42 @@ async function checkPlugin(plugins) {
|
|
|
7925
7996
|
hasError = true;
|
|
7926
7997
|
continue;
|
|
7927
7998
|
}
|
|
7928
|
-
if (!coreBuiltinNameRegexp.test(
|
|
7999
|
+
if (!coreBuiltinNameRegexp.test(String(record["moduleName"]))) {
|
|
7929
8000
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "core \u5185\u7F6E\u63D2\u4EF6\u7684 moduleName \u5FC5\u987B\u6EE1\u8DB3\u5C0F\u5199\u5B57\u6BCD+\u4E0B\u5212\u7EBF\u683C\u5F0F\uFF08\u7531\u7CFB\u7EDF\u751F\u6210\uFF0C\u4E14\u5FC5\u987B\u4E0E name \u4E00\u81F4\uFF09" }));
|
|
7930
8001
|
hasError = true;
|
|
7931
8002
|
continue;
|
|
7932
8003
|
}
|
|
7933
|
-
if (name !==
|
|
8004
|
+
if (name !== String(record["moduleName"])) {
|
|
7934
8005
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "core \u5185\u7F6E\u63D2\u4EF6\u7684 name \u5FC5\u987B\u4E0E moduleName \u5B8C\u5168\u4E00\u81F4" }));
|
|
7935
8006
|
hasError = true;
|
|
7936
8007
|
continue;
|
|
7937
8008
|
}
|
|
7938
|
-
|
|
8009
|
+
const filePath = record["filePath"];
|
|
8010
|
+
if (typeof filePath !== "string" || !filePath.startsWith(`core:plugin:${name}`)) {
|
|
7939
8011
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "core \u5185\u7F6E\u63D2\u4EF6\u5FC5\u987B\u6765\u81EA\u9759\u6001\u6CE8\u518C\uFF08filePath \u5FC5\u987B\u4EE5 core:plugin:<name> \u5F00\u5934\uFF09\uFF0C\u4E0D\u5141\u8BB8\u901A\u8FC7\u626B\u63CF\u76EE\u5F55\u52A0\u8F7D" }));
|
|
7940
8012
|
hasError = true;
|
|
7941
8013
|
continue;
|
|
7942
8014
|
}
|
|
7943
8015
|
}
|
|
7944
8016
|
if (hasCustomDeps) {
|
|
7945
|
-
|
|
8017
|
+
const deps = record["deps"];
|
|
8018
|
+
if (!Array.isArray(deps)) {
|
|
7946
8019
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u7684 deps \u5C5E\u6027\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4" }));
|
|
7947
8020
|
hasError = true;
|
|
7948
8021
|
continue;
|
|
7949
8022
|
}
|
|
7950
|
-
if (
|
|
8023
|
+
if (deps.some((depItem) => typeof depItem !== "string")) {
|
|
7951
8024
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u7684 deps \u5C5E\u6027\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4" }));
|
|
7952
8025
|
hasError = true;
|
|
7953
8026
|
continue;
|
|
7954
8027
|
}
|
|
7955
8028
|
} else {
|
|
7956
|
-
|
|
7957
|
-
|
|
8029
|
+
const deps = record["deps"];
|
|
8030
|
+
if (!Array.isArray(deps)) {
|
|
8031
|
+
record["deps"] = [];
|
|
7958
8032
|
}
|
|
7959
8033
|
}
|
|
7960
|
-
if (typeof
|
|
8034
|
+
if (typeof record["handler"] !== "function") {
|
|
7961
8035
|
Logger.warn(Object.assign({}, omit(plugin, ["handler"]), { msg: "\u63D2\u4EF6\u7684 handler \u5C5E\u6027\u5FC5\u987B\u662F\u51FD\u6570" }));
|
|
7962
8036
|
hasError = true;
|
|
7963
8037
|
continue;
|
|
@@ -7975,8 +8049,11 @@ async function checkPlugin(plugins) {
|
|
|
7975
8049
|
// checks/checkTable.ts
|
|
7976
8050
|
init_logger();
|
|
7977
8051
|
var RESERVED_FIELDS = ["id", "created_at", "updated_at", "deleted_at", "state"];
|
|
8052
|
+
var RESERVED_FIELD_SET = new Set(RESERVED_FIELDS);
|
|
7978
8053
|
var FIELD_TYPES = ["string", "number", "text", "array_string", "array_text", "array_number_string", "array_number_text"];
|
|
8054
|
+
var FIELD_TYPE_SET = new Set(FIELD_TYPES);
|
|
7979
8055
|
var ALLOWED_FIELD_PROPERTIES = ["name", "type", "min", "max", "default", "detail", "index", "unique", "nullable", "unsigned", "regexp"];
|
|
8056
|
+
var ALLOWED_FIELD_PROPERTY_SET = new Set(ALLOWED_FIELD_PROPERTIES);
|
|
7980
8057
|
var LOWER_CAMEL_CASE_REGEX = /^_?[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/;
|
|
7981
8058
|
var FIELD_NAME_REGEX = /^[\u4e00-\u9fa5a-zA-Z0-9 _-]+$/;
|
|
7982
8059
|
var MAX_VARCHAR_LENGTH = 65535;
|
|
@@ -8002,13 +8079,13 @@ async function checkTable(tables) {
|
|
|
8002
8079
|
hasError = true;
|
|
8003
8080
|
continue;
|
|
8004
8081
|
}
|
|
8005
|
-
if (
|
|
8082
|
+
if (RESERVED_FIELD_SET.has(colKey)) {
|
|
8006
8083
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6\u5305\u542B\u4FDD\u7559\u5B57\u6BB5 ${colKey}\uFF0C` + `\u4E0D\u80FD\u5728\u8868\u5B9A\u4E49\u4E2D\u4F7F\u7528\u4EE5\u4E0B\u5B57\u6BB5: ${RESERVED_FIELDS.join(", ")}`);
|
|
8007
8084
|
hasError = true;
|
|
8008
8085
|
}
|
|
8009
8086
|
const field = fieldDef;
|
|
8010
8087
|
const fieldKeys = Object.keys(field);
|
|
8011
|
-
const illegalProps = fieldKeys.filter((key) => !
|
|
8088
|
+
const illegalProps = fieldKeys.filter((key) => !ALLOWED_FIELD_PROPERTY_SET.has(key));
|
|
8012
8089
|
if (illegalProps.length > 0) {
|
|
8013
8090
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5305\u542B\u975E\u6CD5\u5C5E\u6027: ${illegalProps.join(", ")}\uFF0C` + `\u5141\u8BB8\u7684\u5C5E\u6027\u4E3A: ${ALLOWED_FIELD_PROPERTIES.join(", ")}`);
|
|
8014
8091
|
hasError = true;
|
|
@@ -8060,7 +8137,7 @@ async function checkTable(tables) {
|
|
|
8060
8137
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5\u540D\u79F0 "${fieldName}" \u683C\u5F0F\u9519\u8BEF\uFF0C` + `\u5FC5\u987B\u4E3A\u4E2D\u6587\u3001\u6570\u5B57\u3001\u5B57\u6BCD\u3001\u4E0B\u5212\u7EBF\u3001\u77ED\u6A2A\u7EBF\u3001\u7A7A\u683C`);
|
|
8061
8138
|
hasError = true;
|
|
8062
8139
|
}
|
|
8063
|
-
if (!
|
|
8140
|
+
if (!FIELD_TYPE_SET.has(fieldType)) {
|
|
8064
8141
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5\u7C7B\u578B "${fieldType}" \u683C\u5F0F\u9519\u8BEF\uFF0C` + `\u5FC5\u987B\u4E3A${FIELD_TYPES.join("\u3001")}\u4E4B\u4E00`);
|
|
8065
8142
|
hasError = true;
|
|
8066
8143
|
}
|
|
@@ -8266,7 +8343,8 @@ class Connect {
|
|
|
8266
8343
|
await this.connectSql(config2.db || {});
|
|
8267
8344
|
await this.connectRedis(config2.redis || {});
|
|
8268
8345
|
} catch (error) {
|
|
8269
|
-
|
|
8346
|
+
const env = typeof process?.env?.NODE_ENV === "string" ? "development" : "";
|
|
8347
|
+
Logger.error({ env, err: error, msg: "\u6570\u636E\u5E93\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25" });
|
|
8270
8348
|
await this.disconnect();
|
|
8271
8349
|
throw error;
|
|
8272
8350
|
}
|
|
@@ -8320,11 +8398,42 @@ init_logger();
|
|
|
8320
8398
|
async function loadApis(apis) {
|
|
8321
8399
|
const apisMap = new Map;
|
|
8322
8400
|
for (const api of apis) {
|
|
8323
|
-
if (Object.hasOwn(api, "type") && api.type !== "api") {
|
|
8324
|
-
continue;
|
|
8325
|
-
}
|
|
8326
8401
|
try {
|
|
8327
|
-
|
|
8402
|
+
if (Object.hasOwn(api, "type") && api.type !== "api") {
|
|
8403
|
+
continue;
|
|
8404
|
+
}
|
|
8405
|
+
const record = api;
|
|
8406
|
+
const path = record["path"];
|
|
8407
|
+
const route = {
|
|
8408
|
+
name: record["name"],
|
|
8409
|
+
handler: record["handler"],
|
|
8410
|
+
route: path
|
|
8411
|
+
};
|
|
8412
|
+
const method = record["method"];
|
|
8413
|
+
if (typeof method === "string") {
|
|
8414
|
+
const upperMethod = method.toUpperCase();
|
|
8415
|
+
const normalized = upperMethod === "POST,GET" ? "GET,POST" : upperMethod;
|
|
8416
|
+
route.method = ["GET", "POST", "GET,POST"].includes(normalized) ? normalized : "POST";
|
|
8417
|
+
} else {
|
|
8418
|
+
route.method = "POST";
|
|
8419
|
+
}
|
|
8420
|
+
const auth = record["auth"];
|
|
8421
|
+
if (auth !== undefined) {
|
|
8422
|
+
route.auth = auth;
|
|
8423
|
+
}
|
|
8424
|
+
const fields = record["fields"];
|
|
8425
|
+
if (fields !== undefined) {
|
|
8426
|
+
route.fields = fields;
|
|
8427
|
+
}
|
|
8428
|
+
const required = record["required"];
|
|
8429
|
+
if (required !== undefined) {
|
|
8430
|
+
route.required = required;
|
|
8431
|
+
}
|
|
8432
|
+
const rawBody = record["rawBody"];
|
|
8433
|
+
if (rawBody !== undefined) {
|
|
8434
|
+
route.rawBody = rawBody;
|
|
8435
|
+
}
|
|
8436
|
+
apisMap.set(path, route);
|
|
8328
8437
|
} catch (error) {
|
|
8329
8438
|
Logger.error({ err: error, api: api.relativePath, file: api.filePath, msg: "\u63A5\u53E3\u52A0\u8F7D\u5931\u8D25" });
|
|
8330
8439
|
throw error;
|
|
@@ -8345,7 +8454,13 @@ function sortModules(items, options = {}) {
|
|
|
8345
8454
|
}
|
|
8346
8455
|
return camelCase(item.fileName);
|
|
8347
8456
|
});
|
|
8348
|
-
const getDeps = options.getDeps || ((item) =>
|
|
8457
|
+
const getDeps = options.getDeps || ((item) => {
|
|
8458
|
+
const deps = item.deps;
|
|
8459
|
+
if (!Array.isArray(deps)) {
|
|
8460
|
+
return [];
|
|
8461
|
+
}
|
|
8462
|
+
return deps.filter((x) => typeof x === "string");
|
|
8463
|
+
});
|
|
8349
8464
|
const result = [];
|
|
8350
8465
|
const visited = new Set;
|
|
8351
8466
|
const visiting = new Set;
|
|
@@ -8425,11 +8540,12 @@ function sortModules(items, options = {}) {
|
|
|
8425
8540
|
async function loadHooks(hooks) {
|
|
8426
8541
|
const hooksMap = [];
|
|
8427
8542
|
const enabledHooks = hooks.filter((item) => {
|
|
8428
|
-
const moduleName = item
|
|
8543
|
+
const moduleName = item.moduleName;
|
|
8429
8544
|
if (typeof moduleName !== "string" || moduleName.trim() === "") {
|
|
8430
8545
|
return false;
|
|
8431
8546
|
}
|
|
8432
|
-
|
|
8547
|
+
const enable = Object.hasOwn(item, "enable") ? item.enable : undefined;
|
|
8548
|
+
if (enable === false) {
|
|
8433
8549
|
return false;
|
|
8434
8550
|
}
|
|
8435
8551
|
return true;
|
|
@@ -8440,12 +8556,18 @@ async function loadHooks(hooks) {
|
|
|
8440
8556
|
}
|
|
8441
8557
|
for (const item of sortedHooks) {
|
|
8442
8558
|
const hookName = item.moduleName;
|
|
8443
|
-
const
|
|
8559
|
+
const depsRaw = Object.hasOwn(item, "deps") ? item.deps : undefined;
|
|
8560
|
+
const deps = Array.isArray(depsRaw) ? depsRaw.filter((x) => typeof x === "string") : [];
|
|
8561
|
+
const handlerRaw = Object.hasOwn(item, "handler") ? item.handler : undefined;
|
|
8562
|
+
if (typeof handlerRaw !== "function") {
|
|
8563
|
+
throw new Error(`Hook '${hookName}' handler \u5FC5\u987B\u662F\u51FD\u6570`);
|
|
8564
|
+
}
|
|
8565
|
+
const handler = handlerRaw;
|
|
8444
8566
|
hooksMap.push({
|
|
8445
8567
|
name: hookName,
|
|
8446
8568
|
enable: true,
|
|
8447
|
-
deps
|
|
8448
|
-
handler
|
|
8569
|
+
deps,
|
|
8570
|
+
handler
|
|
8449
8571
|
});
|
|
8450
8572
|
}
|
|
8451
8573
|
return hooksMap;
|
|
@@ -8456,11 +8578,12 @@ init_logger();
|
|
|
8456
8578
|
async function loadPlugins(plugins, context) {
|
|
8457
8579
|
const pluginsMap = [];
|
|
8458
8580
|
const enabledPlugins = plugins.filter((item) => {
|
|
8459
|
-
const moduleName = item
|
|
8581
|
+
const moduleName = item.moduleName;
|
|
8460
8582
|
if (typeof moduleName !== "string" || moduleName.trim() === "") {
|
|
8461
8583
|
return false;
|
|
8462
8584
|
}
|
|
8463
|
-
|
|
8585
|
+
const enable = Object.hasOwn(item, "enable") ? item.enable : undefined;
|
|
8586
|
+
if (enable === false) {
|
|
8464
8587
|
return false;
|
|
8465
8588
|
}
|
|
8466
8589
|
return true;
|
|
@@ -8471,15 +8594,21 @@ async function loadPlugins(plugins, context) {
|
|
|
8471
8594
|
}
|
|
8472
8595
|
for (const item of sortedPlugins) {
|
|
8473
8596
|
const pluginName = item.moduleName;
|
|
8474
|
-
const
|
|
8597
|
+
const depsRaw = Object.hasOwn(item, "deps") ? item.deps : undefined;
|
|
8598
|
+
const deps = Array.isArray(depsRaw) ? depsRaw.filter((x) => typeof x === "string") : [];
|
|
8599
|
+
const handlerRaw = Object.hasOwn(item, "handler") ? item.handler : undefined;
|
|
8600
|
+
if (typeof handlerRaw !== "function") {
|
|
8601
|
+
throw new Error(`\u63D2\u4EF6 '${pluginName}' handler \u5FC5\u987B\u662F\u51FD\u6570`);
|
|
8602
|
+
}
|
|
8603
|
+
const handler = handlerRaw;
|
|
8475
8604
|
try {
|
|
8476
|
-
const pluginInstance =
|
|
8605
|
+
const pluginInstance = await handler(context);
|
|
8477
8606
|
context[pluginName] = pluginInstance;
|
|
8478
8607
|
pluginsMap.push({
|
|
8479
8608
|
name: pluginName,
|
|
8480
8609
|
enable: true,
|
|
8481
|
-
deps
|
|
8482
|
-
handler
|
|
8610
|
+
deps,
|
|
8611
|
+
handler
|
|
8483
8612
|
});
|
|
8484
8613
|
} catch (error) {
|
|
8485
8614
|
Logger.error({ err: error, plugin: pluginName, msg: "\u63D2\u4EF6\u521D\u59CB\u5316\u5931\u8D25" });
|
|
@@ -8795,28 +8924,40 @@ async function syncApi(ctx, apis) {
|
|
|
8795
8924
|
if (api.type !== "api") {
|
|
8796
8925
|
continue;
|
|
8797
8926
|
}
|
|
8798
|
-
const
|
|
8799
|
-
const
|
|
8800
|
-
|
|
8801
|
-
const
|
|
8927
|
+
const record = api;
|
|
8928
|
+
const path = record["path"];
|
|
8929
|
+
const name = record["name"];
|
|
8930
|
+
const addonNameRaw = record["addonName"];
|
|
8931
|
+
if (typeof path !== "string" || path.trim() === "") {
|
|
8932
|
+
continue;
|
|
8933
|
+
}
|
|
8934
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
8935
|
+
continue;
|
|
8936
|
+
}
|
|
8937
|
+
const addonName = typeof addonNameRaw === "string" ? addonNameRaw : "";
|
|
8938
|
+
const authRaw = record["auth"];
|
|
8939
|
+
const auth = authRaw === false || authRaw === 0 ? 0 : 1;
|
|
8940
|
+
const parentPath = getApiParentPath(path);
|
|
8941
|
+
apiRouteKeys.add(path);
|
|
8942
|
+
const item = allDbApiMap[path];
|
|
8802
8943
|
if (item) {
|
|
8803
|
-
const shouldUpdate =
|
|
8944
|
+
const shouldUpdate = name !== item.name || path !== item.path || addonName !== item.addonName || parentPath !== item.parentPath || auth !== item.auth;
|
|
8804
8945
|
if (shouldUpdate) {
|
|
8805
8946
|
updData.push({
|
|
8806
8947
|
id: item.id,
|
|
8807
|
-
name
|
|
8808
|
-
path
|
|
8948
|
+
name,
|
|
8949
|
+
path,
|
|
8809
8950
|
parentPath,
|
|
8810
|
-
addonName
|
|
8951
|
+
addonName,
|
|
8811
8952
|
auth
|
|
8812
8953
|
});
|
|
8813
8954
|
}
|
|
8814
8955
|
} else {
|
|
8815
8956
|
insData.push({
|
|
8816
|
-
name
|
|
8817
|
-
path
|
|
8957
|
+
name,
|
|
8958
|
+
path,
|
|
8818
8959
|
parentPath,
|
|
8819
|
-
addonName
|
|
8960
|
+
addonName,
|
|
8820
8961
|
auth
|
|
8821
8962
|
});
|
|
8822
8963
|
}
|
|
@@ -8956,10 +9097,7 @@ class Cipher {
|
|
|
8956
9097
|
}
|
|
8957
9098
|
}
|
|
8958
9099
|
static async hashPassword(password, options = {}) {
|
|
8959
|
-
const finalOptions = {
|
|
8960
|
-
algorithm: "bcrypt",
|
|
8961
|
-
...options
|
|
8962
|
-
};
|
|
9100
|
+
const finalOptions = Object.assign({}, options, { algorithm: "bcrypt" });
|
|
8963
9101
|
return await Bun.password.hash(password, finalOptions);
|
|
8964
9102
|
}
|
|
8965
9103
|
static async verifyPassword(password, hash) {
|
|
@@ -9034,8 +9172,8 @@ async function syncDev(ctx, config2 = {}) {
|
|
|
9034
9172
|
code: "dev",
|
|
9035
9173
|
name: "\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9036
9174
|
description: "\u62E5\u6709\u6240\u6709\u83DC\u5355\u548C\u63A5\u53E3\u6743\u9650\u7684\u5F00\u53D1\u8005\u89D2\u8272",
|
|
9037
|
-
menus: allMenus.data.lists.map((item) => item.path).filter((v) => v),
|
|
9038
|
-
apis: allApis.data.lists.map((item) => item.path).filter((v) => v),
|
|
9175
|
+
menus: allMenus.data.lists.map((item) => item.path).filter((v) => typeof v === "string" && v.length > 0),
|
|
9176
|
+
apis: allApis.data.lists.map((item) => item.path).filter((v) => typeof v === "string" && v.length > 0),
|
|
9039
9177
|
sort: 0
|
|
9040
9178
|
};
|
|
9041
9179
|
if (typeof devRole.data.id === "number") {
|
|
@@ -9173,12 +9311,13 @@ function createDisableMenuMatcher(ctx) {
|
|
|
9173
9311
|
candidates.push(`/${trimmed}`);
|
|
9174
9312
|
}
|
|
9175
9313
|
for (const glob of globs) {
|
|
9176
|
-
const match = glob.match;
|
|
9314
|
+
const match = typeof glob === "object" && glob !== null && "match" in glob ? glob.match : undefined;
|
|
9177
9315
|
if (typeof match !== "function") {
|
|
9178
9316
|
throw new Error("syncMenu: \u5F53\u524D Bun \u7248\u672C\u4E0D\u652F\u6301 Bun.Glob.match\uFF0C\u65E0\u6CD5\u6309 disableMenus \u505A glob \u5339\u914D");
|
|
9179
9317
|
}
|
|
9318
|
+
const matchFn = match;
|
|
9180
9319
|
for (const candidate of candidates) {
|
|
9181
|
-
if (
|
|
9320
|
+
if (matchFn.call(glob, candidate)) {
|
|
9182
9321
|
return true;
|
|
9183
9322
|
}
|
|
9184
9323
|
}
|
|
@@ -9511,12 +9650,9 @@ class MySqlDialect {
|
|
|
9511
9650
|
return { sql: `SHOW COLUMNS FROM ${quotedTable}`, params: [] };
|
|
9512
9651
|
}
|
|
9513
9652
|
getTableColumnsFromResult(result) {
|
|
9514
|
-
if (!Array.isArray(result)) {
|
|
9515
|
-
return [];
|
|
9516
|
-
}
|
|
9517
9653
|
const columnNames = [];
|
|
9518
9654
|
for (const row of result) {
|
|
9519
|
-
const name = row
|
|
9655
|
+
const name = row["Field"];
|
|
9520
9656
|
if (typeof name === "string" && name.length > 0) {
|
|
9521
9657
|
columnNames.push(name);
|
|
9522
9658
|
}
|
|
@@ -9557,12 +9693,9 @@ class PostgresDialect {
|
|
|
9557
9693
|
return { sql: "SELECT column_name FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = ? ORDER BY ordinal_position", params: [table] };
|
|
9558
9694
|
}
|
|
9559
9695
|
getTableColumnsFromResult(result) {
|
|
9560
|
-
if (!Array.isArray(result)) {
|
|
9561
|
-
return [];
|
|
9562
|
-
}
|
|
9563
9696
|
const columnNames = [];
|
|
9564
9697
|
for (const row of result) {
|
|
9565
|
-
const name = row
|
|
9698
|
+
const name = row["column_name"];
|
|
9566
9699
|
if (typeof name === "string" && name.length > 0) {
|
|
9567
9700
|
columnNames.push(name);
|
|
9568
9701
|
}
|
|
@@ -9598,12 +9731,9 @@ class SqliteDialect {
|
|
|
9598
9731
|
return { sql: `PRAGMA table_info(${quotedTable})`, params: [] };
|
|
9599
9732
|
}
|
|
9600
9733
|
getTableColumnsFromResult(result) {
|
|
9601
|
-
if (!Array.isArray(result)) {
|
|
9602
|
-
return [];
|
|
9603
|
-
}
|
|
9604
9734
|
const columnNames = [];
|
|
9605
9735
|
for (const row of result) {
|
|
9606
|
-
const name = row
|
|
9736
|
+
const name = row["name"];
|
|
9607
9737
|
if (typeof name === "string" && name.length > 0) {
|
|
9608
9738
|
columnNames.push(name);
|
|
9609
9739
|
}
|
|
@@ -9696,10 +9826,11 @@ var syncTable = async (ctx, items) => {
|
|
|
9696
9826
|
applyFieldDefaults(fieldDef);
|
|
9697
9827
|
}
|
|
9698
9828
|
const existsTable = await tableExistsRuntime(runtime, tableName);
|
|
9829
|
+
const tableFields = tableDefinition;
|
|
9699
9830
|
if (existsTable) {
|
|
9700
|
-
await modifyTableRuntime(runtime, tableName,
|
|
9831
|
+
await modifyTableRuntime(runtime, tableName, tableFields);
|
|
9701
9832
|
} else {
|
|
9702
|
-
await createTable(runtime, tableName,
|
|
9833
|
+
await createTable(runtime, tableName, tableFields);
|
|
9703
9834
|
}
|
|
9704
9835
|
processedTables.push(tableName);
|
|
9705
9836
|
}
|
|
@@ -9832,19 +9963,99 @@ function quoteIdentifier(dbDialect, identifier) {
|
|
|
9832
9963
|
function escapeComment(str) {
|
|
9833
9964
|
return String(str).replace(/"/g, "\\\"");
|
|
9834
9965
|
}
|
|
9966
|
+
function normalizeColumnDefaultValue(value) {
|
|
9967
|
+
if (value === null)
|
|
9968
|
+
return null;
|
|
9969
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
9970
|
+
return value;
|
|
9971
|
+
if (Array.isArray(value)) {
|
|
9972
|
+
const items = [];
|
|
9973
|
+
for (const v of value) {
|
|
9974
|
+
items.push(normalizeColumnDefaultValue(v));
|
|
9975
|
+
}
|
|
9976
|
+
return items;
|
|
9977
|
+
}
|
|
9978
|
+
return String(value);
|
|
9979
|
+
}
|
|
9980
|
+
function isJsonValue(value) {
|
|
9981
|
+
if (value === null)
|
|
9982
|
+
return true;
|
|
9983
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
9984
|
+
return true;
|
|
9985
|
+
if (Array.isArray(value)) {
|
|
9986
|
+
return value.every((v) => isJsonValue(v));
|
|
9987
|
+
}
|
|
9988
|
+
if (typeof value === "object") {
|
|
9989
|
+
for (const v of Object.values(value)) {
|
|
9990
|
+
if (v === undefined)
|
|
9991
|
+
continue;
|
|
9992
|
+
if (!isJsonValue(v))
|
|
9993
|
+
return false;
|
|
9994
|
+
}
|
|
9995
|
+
return true;
|
|
9996
|
+
}
|
|
9997
|
+
return false;
|
|
9998
|
+
}
|
|
9835
9999
|
function applyFieldDefaults(fieldDef) {
|
|
9836
10000
|
if (!fieldDef || typeof fieldDef !== "object")
|
|
9837
10001
|
return;
|
|
9838
|
-
const
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
10002
|
+
const record = fieldDef;
|
|
10003
|
+
const name = record["name"];
|
|
10004
|
+
const type = record["type"];
|
|
10005
|
+
if (typeof name !== "string" || typeof type !== "string")
|
|
10006
|
+
return;
|
|
10007
|
+
const minRaw = record["min"];
|
|
10008
|
+
const maxRaw = record["max"];
|
|
10009
|
+
const defaultRaw = record["default"];
|
|
10010
|
+
const detailRaw = record["detail"];
|
|
10011
|
+
const indexRaw = record["index"];
|
|
10012
|
+
const uniqueRaw = record["unique"];
|
|
10013
|
+
const nullableRaw = record["nullable"];
|
|
10014
|
+
const unsignedRaw = record["unsigned"];
|
|
10015
|
+
const regexpRaw = record["regexp"];
|
|
10016
|
+
const input = {
|
|
10017
|
+
name,
|
|
10018
|
+
type
|
|
10019
|
+
};
|
|
10020
|
+
if (typeof detailRaw === "string") {
|
|
10021
|
+
input.detail = detailRaw;
|
|
10022
|
+
}
|
|
10023
|
+
if (typeof minRaw === "number" || minRaw === null) {
|
|
10024
|
+
input.min = minRaw;
|
|
10025
|
+
}
|
|
10026
|
+
if (typeof maxRaw === "number" || maxRaw === null) {
|
|
10027
|
+
input.max = maxRaw;
|
|
10028
|
+
}
|
|
10029
|
+
if (defaultRaw === null) {
|
|
10030
|
+
input.default = null;
|
|
10031
|
+
} else if (isJsonValue(defaultRaw)) {
|
|
10032
|
+
input.default = defaultRaw;
|
|
10033
|
+
}
|
|
10034
|
+
if (typeof indexRaw === "boolean") {
|
|
10035
|
+
input.index = indexRaw;
|
|
10036
|
+
}
|
|
10037
|
+
if (typeof uniqueRaw === "boolean") {
|
|
10038
|
+
input.unique = uniqueRaw;
|
|
10039
|
+
}
|
|
10040
|
+
if (typeof nullableRaw === "boolean") {
|
|
10041
|
+
input.nullable = nullableRaw;
|
|
10042
|
+
}
|
|
10043
|
+
if (typeof unsignedRaw === "boolean") {
|
|
10044
|
+
input.unsigned = unsignedRaw;
|
|
10045
|
+
}
|
|
10046
|
+
if (typeof regexpRaw === "string" || regexpRaw === null) {
|
|
10047
|
+
input.regexp = regexpRaw;
|
|
10048
|
+
}
|
|
10049
|
+
const normalized = normalizeFieldDefinition(input);
|
|
10050
|
+
record["detail"] = normalized.detail;
|
|
10051
|
+
record["min"] = normalized.min;
|
|
10052
|
+
record["max"] = normalized.max;
|
|
10053
|
+
record["default"] = normalized.default;
|
|
10054
|
+
record["index"] = normalized.index;
|
|
10055
|
+
record["unique"] = normalized.unique;
|
|
10056
|
+
record["nullable"] = normalized.nullable;
|
|
10057
|
+
record["unsigned"] = normalized.unsigned;
|
|
10058
|
+
record["regexp"] = normalized.regexp;
|
|
9848
10059
|
}
|
|
9849
10060
|
function isStringOrArrayType(fieldType) {
|
|
9850
10061
|
return fieldType === "string" || fieldType === "array_string" || fieldType === "array_number_string";
|
|
@@ -10022,7 +10233,8 @@ function isCompatibleTypeChange(currentType, newType) {
|
|
|
10022
10233
|
return false;
|
|
10023
10234
|
}
|
|
10024
10235
|
async function tableExistsRuntime(runtime, tableName) {
|
|
10025
|
-
|
|
10236
|
+
const db = runtime.db;
|
|
10237
|
+
if (!db)
|
|
10026
10238
|
throw new Error("SQL \u6267\u884C\u5668\u672A\u521D\u59CB\u5316");
|
|
10027
10239
|
try {
|
|
10028
10240
|
let schema = undefined;
|
|
@@ -10032,7 +10244,7 @@ async function tableExistsRuntime(runtime, tableName) {
|
|
|
10032
10244
|
schema = "public";
|
|
10033
10245
|
}
|
|
10034
10246
|
const q = getDialectByName(runtime.dbDialect).tableExistsQuery(tableName, schema);
|
|
10035
|
-
const res = await
|
|
10247
|
+
const res = await db.unsafe(q.sql, q.params);
|
|
10036
10248
|
return (res.data?.[0]?.count || 0) > 0;
|
|
10037
10249
|
} catch (error) {
|
|
10038
10250
|
const errMsg = String(error?.message || error);
|
|
@@ -10044,12 +10256,15 @@ async function tableExistsRuntime(runtime, tableName) {
|
|
|
10044
10256
|
}
|
|
10045
10257
|
async function getTableColumnsRuntime(runtime, tableName) {
|
|
10046
10258
|
const columns = {};
|
|
10259
|
+
const db = runtime.db;
|
|
10260
|
+
if (!db)
|
|
10261
|
+
throw new Error("SQL \u6267\u884C\u5668\u672A\u521D\u59CB\u5316");
|
|
10047
10262
|
try {
|
|
10048
10263
|
if (runtime.dbDialect === "mysql") {
|
|
10049
10264
|
const q = getSyncTableColumnsInfoQuery({ dialect: "mysql", table: tableName, dbName: runtime.dbName });
|
|
10050
|
-
const result = await
|
|
10265
|
+
const result = await db.unsafe(q.columns.sql, q.columns.params);
|
|
10051
10266
|
for (const row of result.data) {
|
|
10052
|
-
const defaultValue = row.COLUMN_DEFAULT;
|
|
10267
|
+
const defaultValue = normalizeColumnDefaultValue(row.COLUMN_DEFAULT);
|
|
10053
10268
|
columns[row.COLUMN_NAME] = {
|
|
10054
10269
|
type: row.DATA_TYPE,
|
|
10055
10270
|
columnType: row.COLUMN_TYPE,
|
|
@@ -10062,8 +10277,8 @@ async function getTableColumnsRuntime(runtime, tableName) {
|
|
|
10062
10277
|
}
|
|
10063
10278
|
} else if (runtime.dbDialect === "postgresql") {
|
|
10064
10279
|
const q = getSyncTableColumnsInfoQuery({ dialect: "postgresql", table: tableName, dbName: runtime.dbName });
|
|
10065
|
-
const result = await
|
|
10066
|
-
const comments = q.comments ? (await
|
|
10280
|
+
const result = await db.unsafe(q.columns.sql, q.columns.params);
|
|
10281
|
+
const comments = q.comments ? (await db.unsafe(q.comments.sql, q.comments.params)).data : [];
|
|
10067
10282
|
const commentMap = {};
|
|
10068
10283
|
for (const r of comments)
|
|
10069
10284
|
commentMap[r.column_name] = r.column_comment;
|
|
@@ -10074,13 +10289,13 @@ async function getTableColumnsRuntime(runtime, tableName) {
|
|
|
10074
10289
|
length: row.character_maximum_length,
|
|
10075
10290
|
max: row.character_maximum_length,
|
|
10076
10291
|
nullable: String(row.is_nullable).toUpperCase() === "YES",
|
|
10077
|
-
defaultValue: row.column_default,
|
|
10292
|
+
defaultValue: normalizeColumnDefaultValue(row.column_default),
|
|
10078
10293
|
comment: commentMap[row.column_name] ?? null
|
|
10079
10294
|
};
|
|
10080
10295
|
}
|
|
10081
10296
|
} else if (runtime.dbDialect === "sqlite") {
|
|
10082
10297
|
const q = getSyncTableColumnsInfoQuery({ dialect: "sqlite", table: tableName, dbName: runtime.dbName });
|
|
10083
|
-
const result = await
|
|
10298
|
+
const result = await db.unsafe(q.columns.sql, q.columns.params);
|
|
10084
10299
|
for (const row of result.data) {
|
|
10085
10300
|
let baseType = String(row.type || "").toUpperCase();
|
|
10086
10301
|
let max = null;
|
|
@@ -10101,7 +10316,7 @@ async function getTableColumnsRuntime(runtime, tableName) {
|
|
|
10101
10316
|
length: max,
|
|
10102
10317
|
max,
|
|
10103
10318
|
nullable: row.notnull === 0,
|
|
10104
|
-
defaultValue: row.dflt_value,
|
|
10319
|
+
defaultValue: normalizeColumnDefaultValue(row.dflt_value),
|
|
10105
10320
|
comment: null
|
|
10106
10321
|
};
|
|
10107
10322
|
}
|
|
@@ -10117,10 +10332,13 @@ async function getTableColumnsRuntime(runtime, tableName) {
|
|
|
10117
10332
|
}
|
|
10118
10333
|
async function getTableIndexesRuntime(runtime, tableName) {
|
|
10119
10334
|
const indexes = {};
|
|
10335
|
+
const db = runtime.db;
|
|
10336
|
+
if (!db)
|
|
10337
|
+
throw new Error("SQL \u6267\u884C\u5668\u672A\u521D\u59CB\u5316");
|
|
10120
10338
|
try {
|
|
10121
10339
|
if (runtime.dbDialect === "mysql") {
|
|
10122
10340
|
const q = getSyncTableIndexesQuery({ dialect: "mysql", table: tableName, dbName: runtime.dbName });
|
|
10123
|
-
const result = await
|
|
10341
|
+
const result = await db.unsafe(q.sql, q.params);
|
|
10124
10342
|
for (const row of result.data) {
|
|
10125
10343
|
const indexName = row.INDEX_NAME;
|
|
10126
10344
|
const current = indexes[indexName];
|
|
@@ -10132,7 +10350,7 @@ async function getTableIndexesRuntime(runtime, tableName) {
|
|
|
10132
10350
|
}
|
|
10133
10351
|
} else if (runtime.dbDialect === "postgresql") {
|
|
10134
10352
|
const q = getSyncTableIndexesQuery({ dialect: "postgresql", table: tableName, dbName: runtime.dbName });
|
|
10135
|
-
const result = await
|
|
10353
|
+
const result = await db.unsafe(q.sql, q.params);
|
|
10136
10354
|
for (const row of result.data) {
|
|
10137
10355
|
const m = /\(([^)]+)\)/.exec(row.indexdef);
|
|
10138
10356
|
if (m) {
|
|
@@ -10143,10 +10361,10 @@ async function getTableIndexesRuntime(runtime, tableName) {
|
|
|
10143
10361
|
}
|
|
10144
10362
|
} else if (runtime.dbDialect === "sqlite") {
|
|
10145
10363
|
const quotedTable = quoteIdentifier("sqlite", tableName);
|
|
10146
|
-
const list = await
|
|
10364
|
+
const list = await db.unsafe(`PRAGMA index_list(${quotedTable})`);
|
|
10147
10365
|
for (const idx of list.data) {
|
|
10148
10366
|
const quotedIndex = quoteIdentifier("sqlite", idx.name);
|
|
10149
|
-
const info = await
|
|
10367
|
+
const info = await db.unsafe(`PRAGMA index_info(${quotedIndex})`);
|
|
10150
10368
|
const cols = info.data.map((r) => r.name);
|
|
10151
10369
|
if (cols.length === 1)
|
|
10152
10370
|
indexes[idx.name] = cols;
|
|
@@ -12173,7 +12391,7 @@ var permissionHook = {
|
|
|
12173
12391
|
if (ctx.api.auth === false) {
|
|
12174
12392
|
return;
|
|
12175
12393
|
}
|
|
12176
|
-
if (
|
|
12394
|
+
if (typeof ctx.user.id !== "number") {
|
|
12177
12395
|
ctx.response = ErrorResponse(ctx, "\u672A\u767B\u5F55", 1, null, null, "auth");
|
|
12178
12396
|
return;
|
|
12179
12397
|
}
|
|
@@ -12285,28 +12503,75 @@ function getCompiledRegex(pattern, flags) {
|
|
|
12285
12503
|
}
|
|
12286
12504
|
|
|
12287
12505
|
// lib/validator.ts
|
|
12506
|
+
init_util();
|
|
12507
|
+
|
|
12288
12508
|
class Validator {
|
|
12289
12509
|
static validate(data, rules, required = []) {
|
|
12290
12510
|
const fieldErrors = {};
|
|
12291
|
-
if (!
|
|
12511
|
+
if (!isPlainObject(data)) {
|
|
12292
12512
|
return this.buildResult({ _error: "\u6570\u636E\u5FC5\u987B\u662F\u5BF9\u8C61\u683C\u5F0F" });
|
|
12293
12513
|
}
|
|
12294
|
-
if (!rules
|
|
12514
|
+
if (!isPlainObject(rules)) {
|
|
12295
12515
|
return this.buildResult({ _error: "\u9A8C\u8BC1\u89C4\u5219\u5FC5\u987B\u662F\u5BF9\u8C61\u683C\u5F0F" });
|
|
12296
12516
|
}
|
|
12517
|
+
const dataRecord = data;
|
|
12518
|
+
const rulesRecord = rules;
|
|
12297
12519
|
for (const field of required) {
|
|
12298
|
-
const value =
|
|
12520
|
+
const value = dataRecord[field];
|
|
12299
12521
|
if (value === undefined || value === null) {
|
|
12300
|
-
const
|
|
12522
|
+
const rawRule = rulesRecord[field];
|
|
12523
|
+
const label = isPlainObject(rawRule) && typeof rawRule["name"] === "string" ? rawRule["name"] : field;
|
|
12301
12524
|
fieldErrors[field] = `${label}\u4E3A\u5FC5\u586B\u9879`;
|
|
12302
12525
|
}
|
|
12303
12526
|
}
|
|
12304
|
-
for (const [field,
|
|
12527
|
+
for (const [field, rawRule] of Object.entries(rulesRecord)) {
|
|
12305
12528
|
if (fieldErrors[field])
|
|
12306
12529
|
continue;
|
|
12307
|
-
if (
|
|
12530
|
+
if (dataRecord[field] === undefined && !required.includes(field))
|
|
12531
|
+
continue;
|
|
12532
|
+
if (!isPlainObject(rawRule)) {
|
|
12533
|
+
fieldErrors[field] = `${field}\u9A8C\u8BC1\u89C4\u5219\u5FC5\u987B\u662F\u5BF9\u8C61\u683C\u5F0F`;
|
|
12534
|
+
continue;
|
|
12535
|
+
}
|
|
12536
|
+
const ruleName = rawRule["name"];
|
|
12537
|
+
const ruleType = rawRule["type"];
|
|
12538
|
+
if (typeof ruleName !== "string" || typeof ruleType !== "string") {
|
|
12539
|
+
fieldErrors[field] = `${field}\u9A8C\u8BC1\u89C4\u5219\u65E0\u6548`;
|
|
12308
12540
|
continue;
|
|
12309
|
-
|
|
12541
|
+
}
|
|
12542
|
+
const rule = {
|
|
12543
|
+
name: ruleName,
|
|
12544
|
+
type: ruleType
|
|
12545
|
+
};
|
|
12546
|
+
const min = rawRule["min"];
|
|
12547
|
+
if (typeof min === "number" || min === null)
|
|
12548
|
+
rule.min = min;
|
|
12549
|
+
const max = rawRule["max"];
|
|
12550
|
+
if (typeof max === "number" || max === null)
|
|
12551
|
+
rule.max = max;
|
|
12552
|
+
const def = rawRule["default"];
|
|
12553
|
+
if (def === null || typeof def === "string" || typeof def === "number" || typeof def === "boolean" || Array.isArray(def) || isPlainObject(def)) {
|
|
12554
|
+
rule.default = def;
|
|
12555
|
+
}
|
|
12556
|
+
const detail = rawRule["detail"];
|
|
12557
|
+
if (typeof detail === "string")
|
|
12558
|
+
rule.detail = detail;
|
|
12559
|
+
const index = rawRule["index"];
|
|
12560
|
+
if (typeof index === "boolean")
|
|
12561
|
+
rule.index = index;
|
|
12562
|
+
const unique = rawRule["unique"];
|
|
12563
|
+
if (typeof unique === "boolean")
|
|
12564
|
+
rule.unique = unique;
|
|
12565
|
+
const nullable = rawRule["nullable"];
|
|
12566
|
+
if (typeof nullable === "boolean")
|
|
12567
|
+
rule.nullable = nullable;
|
|
12568
|
+
const unsigned = rawRule["unsigned"];
|
|
12569
|
+
if (typeof unsigned === "boolean")
|
|
12570
|
+
rule.unsigned = unsigned;
|
|
12571
|
+
const regexp = rawRule["regexp"];
|
|
12572
|
+
if (typeof regexp === "string" || regexp === null)
|
|
12573
|
+
rule.regexp = regexp;
|
|
12574
|
+
const error = this.checkField(dataRecord[field], rule, field);
|
|
12310
12575
|
if (error)
|
|
12311
12576
|
fieldErrors[field] = error;
|
|
12312
12577
|
}
|
|
@@ -12392,6 +12657,8 @@ class Validator {
|
|
|
12392
12657
|
const regex = this.resolveRegex(regexp);
|
|
12393
12658
|
switch (type.toLowerCase()) {
|
|
12394
12659
|
case "number":
|
|
12660
|
+
if (typeof value !== "number")
|
|
12661
|
+
return "\u5FC5\u987B\u662F\u6570\u5B57";
|
|
12395
12662
|
if (min !== null && value < min)
|
|
12396
12663
|
return `\u4E0D\u80FD\u5C0F\u4E8E${min}`;
|
|
12397
12664
|
if (max !== null && max > 0 && value > max)
|
|
@@ -12401,6 +12668,8 @@ class Validator {
|
|
|
12401
12668
|
break;
|
|
12402
12669
|
case "string":
|
|
12403
12670
|
case "text":
|
|
12671
|
+
if (typeof value !== "string")
|
|
12672
|
+
return "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32";
|
|
12404
12673
|
if (min !== null && value.length < min)
|
|
12405
12674
|
return `\u957F\u5EA6\u4E0D\u80FD\u5C11\u4E8E${min}\u4E2A\u5B57\u7B26`;
|
|
12406
12675
|
if (max !== null && max > 0 && value.length > max)
|
|
@@ -12412,6 +12681,8 @@ class Validator {
|
|
|
12412
12681
|
case "array_text":
|
|
12413
12682
|
case "array_number_string":
|
|
12414
12683
|
case "array_number_text":
|
|
12684
|
+
if (!Array.isArray(value))
|
|
12685
|
+
return "\u5FC5\u987B\u662F\u6570\u7EC4";
|
|
12415
12686
|
if (min !== null && value.length < min)
|
|
12416
12687
|
return `\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5143\u7D20`;
|
|
12417
12688
|
if (max !== null && max > 0 && value.length > max)
|
|
@@ -12769,8 +13040,9 @@ function convertBigIntFields(arr, fields = ["id", "pid", "sort"]) {
|
|
|
12769
13040
|
return arr;
|
|
12770
13041
|
}
|
|
12771
13042
|
return arr.map((item) => {
|
|
13043
|
+
const source = item;
|
|
12772
13044
|
const converted = {};
|
|
12773
|
-
for (const [key, value] of Object.entries(
|
|
13045
|
+
for (const [key, value] of Object.entries(source)) {
|
|
12774
13046
|
converted[key] = value;
|
|
12775
13047
|
}
|
|
12776
13048
|
for (const [key, value] of Object.entries(converted)) {
|
|
@@ -12780,7 +13052,7 @@ function convertBigIntFields(arr, fields = ["id", "pid", "sort"]) {
|
|
|
12780
13052
|
const shouldConvert = fields.includes(key) || key.endsWith("Id") || key.endsWith("_id") || key.endsWith("At") || key.endsWith("_at");
|
|
12781
13053
|
if (shouldConvert && typeof value === "string") {
|
|
12782
13054
|
const num = Number(value);
|
|
12783
|
-
if (!isNaN(num)) {
|
|
13055
|
+
if (!Number.isNaN(num)) {
|
|
12784
13056
|
converted[key] = num;
|
|
12785
13057
|
}
|
|
12786
13058
|
}
|
|
@@ -12839,6 +13111,82 @@ function fieldClear(data, options = {}) {
|
|
|
12839
13111
|
return data;
|
|
12840
13112
|
}
|
|
12841
13113
|
|
|
13114
|
+
// utils/sqlParams.ts
|
|
13115
|
+
function isJsonPrimitive(value) {
|
|
13116
|
+
if (value === null)
|
|
13117
|
+
return true;
|
|
13118
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
13119
|
+
}
|
|
13120
|
+
function isJsonObject(value) {
|
|
13121
|
+
if (!value || typeof value !== "object")
|
|
13122
|
+
return false;
|
|
13123
|
+
if (value instanceof Date)
|
|
13124
|
+
return false;
|
|
13125
|
+
if (Array.isArray(value))
|
|
13126
|
+
return false;
|
|
13127
|
+
return true;
|
|
13128
|
+
}
|
|
13129
|
+
function isJsonValue2(value) {
|
|
13130
|
+
if (isJsonPrimitive(value))
|
|
13131
|
+
return true;
|
|
13132
|
+
if (Array.isArray(value)) {
|
|
13133
|
+
for (const item of value) {
|
|
13134
|
+
if (!isJsonValue2(item))
|
|
13135
|
+
return false;
|
|
13136
|
+
}
|
|
13137
|
+
return true;
|
|
13138
|
+
}
|
|
13139
|
+
if (isJsonObject(value)) {
|
|
13140
|
+
for (const v of Object.values(value)) {
|
|
13141
|
+
if (v === undefined)
|
|
13142
|
+
continue;
|
|
13143
|
+
if (!isJsonValue2(v))
|
|
13144
|
+
return false;
|
|
13145
|
+
}
|
|
13146
|
+
return true;
|
|
13147
|
+
}
|
|
13148
|
+
return false;
|
|
13149
|
+
}
|
|
13150
|
+
function toSqlParams(params) {
|
|
13151
|
+
if (!Array.isArray(params)) {
|
|
13152
|
+
return [];
|
|
13153
|
+
}
|
|
13154
|
+
const out = [];
|
|
13155
|
+
for (const value of params) {
|
|
13156
|
+
if (value === null) {
|
|
13157
|
+
out.push(null);
|
|
13158
|
+
continue;
|
|
13159
|
+
}
|
|
13160
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
13161
|
+
out.push(value);
|
|
13162
|
+
continue;
|
|
13163
|
+
}
|
|
13164
|
+
if (typeof value === "bigint") {
|
|
13165
|
+
out.push(String(value));
|
|
13166
|
+
continue;
|
|
13167
|
+
}
|
|
13168
|
+
if (value instanceof Date) {
|
|
13169
|
+
out.push(value);
|
|
13170
|
+
continue;
|
|
13171
|
+
}
|
|
13172
|
+
if (isJsonValue2(value)) {
|
|
13173
|
+
out.push(value);
|
|
13174
|
+
continue;
|
|
13175
|
+
}
|
|
13176
|
+
out.push(String(value));
|
|
13177
|
+
}
|
|
13178
|
+
return out;
|
|
13179
|
+
}
|
|
13180
|
+
|
|
13181
|
+
// utils/sqlResult.ts
|
|
13182
|
+
function toNumberFromSql(value) {
|
|
13183
|
+
if (typeof value === "number")
|
|
13184
|
+
return value;
|
|
13185
|
+
if (typeof value === "bigint")
|
|
13186
|
+
return Number(value);
|
|
13187
|
+
return 0;
|
|
13188
|
+
}
|
|
13189
|
+
|
|
12842
13190
|
// lib/dbHelper.ts
|
|
12843
13191
|
init_util();
|
|
12844
13192
|
|
|
@@ -13065,7 +13413,7 @@ class DbUtils {
|
|
|
13065
13413
|
for (const [key, value] of Object.entries(where)) {
|
|
13066
13414
|
const newKey = DbUtils.processJoinWhereKey(key);
|
|
13067
13415
|
if (key === "$or" || key === "$and") {
|
|
13068
|
-
result[newKey] = value.map((item) => DbUtils.processJoinWhere(item));
|
|
13416
|
+
result[newKey] = Array.isArray(value) ? value.map((item) => DbUtils.processJoinWhere(item)) : [];
|
|
13069
13417
|
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
13070
13418
|
result[newKey] = DbUtils.processJoinWhere(value);
|
|
13071
13419
|
} else {
|
|
@@ -13124,7 +13472,7 @@ class DbUtils {
|
|
|
13124
13472
|
const result = {};
|
|
13125
13473
|
for (const [key, value] of Object.entries(where)) {
|
|
13126
13474
|
if (key === "$or" || key === "$and") {
|
|
13127
|
-
result[key] = value.map((item) => DbUtils.whereKeysToSnake(item));
|
|
13475
|
+
result[key] = Array.isArray(value) ? value.map((item) => DbUtils.whereKeysToSnake(item)) : [];
|
|
13128
13476
|
continue;
|
|
13129
13477
|
}
|
|
13130
13478
|
if (key.includes("$")) {
|
|
@@ -13661,13 +14009,20 @@ class SqlBuilder {
|
|
|
13661
14009
|
}
|
|
13662
14010
|
if (key === "$and") {
|
|
13663
14011
|
if (Array.isArray(value)) {
|
|
13664
|
-
value.forEach((condition) =>
|
|
14012
|
+
value.forEach((condition) => {
|
|
14013
|
+
if (condition && typeof condition === "object" && !Array.isArray(condition)) {
|
|
14014
|
+
this._processWhereConditions(condition);
|
|
14015
|
+
}
|
|
14016
|
+
});
|
|
13665
14017
|
}
|
|
13666
14018
|
} else if (key === "$or") {
|
|
13667
14019
|
if (Array.isArray(value)) {
|
|
13668
14020
|
const orConditions = [];
|
|
13669
14021
|
const tempParams = [];
|
|
13670
14022
|
value.forEach((condition) => {
|
|
14023
|
+
if (!condition || typeof condition !== "object" || Array.isArray(condition)) {
|
|
14024
|
+
return;
|
|
14025
|
+
}
|
|
13671
14026
|
const tempBuilder = new SqlBuilder({ quoteIdent: this._quoteIdent });
|
|
13672
14027
|
tempBuilder._processWhereConditions(condition);
|
|
13673
14028
|
if (tempBuilder._where.length > 0) {
|
|
@@ -13912,7 +14267,8 @@ class SqlBuilder {
|
|
|
13912
14267
|
throw new Error(SqlBuilderError.INSERT_NEED_AT_LEAST_ONE_FIELD(table));
|
|
13913
14268
|
}
|
|
13914
14269
|
for (const field of fields) {
|
|
13915
|
-
|
|
14270
|
+
const record = data;
|
|
14271
|
+
this._validateParam(record[field]);
|
|
13916
14272
|
}
|
|
13917
14273
|
const escapedFields = fields.map((field) => this._escapeField(field));
|
|
13918
14274
|
const placeholders = fields.map(() => "?").join(", ");
|
|
@@ -14049,6 +14405,23 @@ class SqlBuilder {
|
|
|
14049
14405
|
|
|
14050
14406
|
// lib/dbHelper.ts
|
|
14051
14407
|
var TABLE_COLUMNS_CACHE_TTL_SECONDS = 3600;
|
|
14408
|
+
function hasBegin(sql) {
|
|
14409
|
+
return typeof sql.begin === "function";
|
|
14410
|
+
}
|
|
14411
|
+
|
|
14412
|
+
class DbSqlError extends Error {
|
|
14413
|
+
originalError;
|
|
14414
|
+
params;
|
|
14415
|
+
duration;
|
|
14416
|
+
sqlInfo;
|
|
14417
|
+
constructor(message, options) {
|
|
14418
|
+
super(message);
|
|
14419
|
+
this.originalError = options.originalError;
|
|
14420
|
+
this.params = options.params;
|
|
14421
|
+
this.duration = options.duration;
|
|
14422
|
+
this.sqlInfo = options.sqlInfo;
|
|
14423
|
+
}
|
|
14424
|
+
}
|
|
14052
14425
|
|
|
14053
14426
|
class DbHelper {
|
|
14054
14427
|
redis;
|
|
@@ -14071,7 +14444,7 @@ class DbHelper {
|
|
|
14071
14444
|
return columns;
|
|
14072
14445
|
}
|
|
14073
14446
|
const query = this.dialect.getTableColumnsQuery(table);
|
|
14074
|
-
const execRes = await this.
|
|
14447
|
+
const execRes = await this.executeSelect(query.sql, query.params);
|
|
14075
14448
|
const result = execRes.data;
|
|
14076
14449
|
if (!result || result.length === 0) {
|
|
14077
14450
|
throw new Error(`\u8868 ${table} \u4E0D\u5B58\u5728\u6216\u6CA1\u6709\u5B57\u6BB5`);
|
|
@@ -14133,6 +14506,12 @@ class DbHelper {
|
|
|
14133
14506
|
}
|
|
14134
14507
|
}
|
|
14135
14508
|
}
|
|
14509
|
+
async executeSelect(sqlStr, params) {
|
|
14510
|
+
return await this.executeWithConn(sqlStr, params);
|
|
14511
|
+
}
|
|
14512
|
+
async executeRun(sqlStr, params) {
|
|
14513
|
+
return await this.executeWithConn(sqlStr, params);
|
|
14514
|
+
}
|
|
14136
14515
|
async executeWithConn(sqlStr, params) {
|
|
14137
14516
|
if (!this.sql) {
|
|
14138
14517
|
throw new Error("\u6570\u636E\u5E93\u8FDE\u63A5\u672A\u521D\u59CB\u5316");
|
|
@@ -14141,7 +14520,7 @@ class DbHelper {
|
|
|
14141
14520
|
throw new Error(`executeWithConn \u53EA\u63A5\u53D7\u5B57\u7B26\u4E32\u7C7B\u578B\u7684 SQL\uFF0C\u6536\u5230\u7C7B\u578B: ${typeof sqlStr}\uFF0C\u503C: ${JSON.stringify(sqlStr)}`);
|
|
14142
14521
|
}
|
|
14143
14522
|
const startTime = Date.now();
|
|
14144
|
-
const safeParams =
|
|
14523
|
+
const safeParams = toSqlParams(params);
|
|
14145
14524
|
try {
|
|
14146
14525
|
let result;
|
|
14147
14526
|
if (safeParams.length > 0) {
|
|
@@ -14161,16 +14540,17 @@ class DbHelper {
|
|
|
14161
14540
|
};
|
|
14162
14541
|
} catch (error) {
|
|
14163
14542
|
const duration = Date.now() - startTime;
|
|
14164
|
-
const
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
enhancedError.duration = duration;
|
|
14168
|
-
enhancedError.sqlInfo = {
|
|
14169
|
-
sql: sqlStr,
|
|
14543
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
14544
|
+
throw new DbSqlError(`SQL\u6267\u884C\u5931\u8D25: ${msg}`, {
|
|
14545
|
+
originalError: error,
|
|
14170
14546
|
params: safeParams,
|
|
14171
|
-
duration
|
|
14172
|
-
|
|
14173
|
-
|
|
14547
|
+
duration,
|
|
14548
|
+
sqlInfo: {
|
|
14549
|
+
sql: sqlStr,
|
|
14550
|
+
params: safeParams,
|
|
14551
|
+
duration
|
|
14552
|
+
}
|
|
14553
|
+
});
|
|
14174
14554
|
}
|
|
14175
14555
|
}
|
|
14176
14556
|
async unsafe(sqlStr, params) {
|
|
@@ -14179,7 +14559,7 @@ class DbHelper {
|
|
|
14179
14559
|
async tableExists(tableName) {
|
|
14180
14560
|
const snakeTableName = snakeCase(tableName);
|
|
14181
14561
|
const query = this.dialect.tableExistsQuery(snakeTableName);
|
|
14182
|
-
const execRes = await this.
|
|
14562
|
+
const execRes = await this.executeSelect(query.sql, query.params);
|
|
14183
14563
|
const exists = (execRes.data?.[0]?.count || 0) > 0;
|
|
14184
14564
|
return {
|
|
14185
14565
|
data: exists,
|
|
@@ -14192,7 +14572,7 @@ class DbHelper {
|
|
|
14192
14572
|
const builder = this.createSqlBuilder().selectRaw("COUNT(*) as count").from(table).where(DbUtils.addDefaultStateFilter(where, tableQualifier, hasJoins));
|
|
14193
14573
|
this.applyJoins(builder, joins);
|
|
14194
14574
|
const { sql, params } = builder.toSelectSql();
|
|
14195
|
-
const execRes = await this.
|
|
14575
|
+
const execRes = await this.executeSelect(sql, params);
|
|
14196
14576
|
const count = execRes.data?.[0]?.count || 0;
|
|
14197
14577
|
return {
|
|
14198
14578
|
data: count,
|
|
@@ -14205,7 +14585,7 @@ class DbHelper {
|
|
|
14205
14585
|
const builder = this.createSqlBuilder().select(fields).from(table).where(DbUtils.addDefaultStateFilter(where, tableQualifier, hasJoins));
|
|
14206
14586
|
this.applyJoins(builder, joins);
|
|
14207
14587
|
const { sql, params } = builder.toSelectSql();
|
|
14208
|
-
const execRes = await this.
|
|
14588
|
+
const execRes = await this.executeSelect(sql, params);
|
|
14209
14589
|
const result = execRes.data;
|
|
14210
14590
|
const row = result?.[0] || null;
|
|
14211
14591
|
if (!row) {
|
|
@@ -14244,7 +14624,7 @@ class DbHelper {
|
|
|
14244
14624
|
const countBuilder = this.createSqlBuilder().selectRaw("COUNT(*) as total").from(prepared.table).where(whereFiltered);
|
|
14245
14625
|
this.applyJoins(countBuilder, prepared.joins);
|
|
14246
14626
|
const { sql: countSql, params: countParams } = countBuilder.toSelectSql();
|
|
14247
|
-
const countExecRes = await this.
|
|
14627
|
+
const countExecRes = await this.executeSelect(countSql, countParams);
|
|
14248
14628
|
const total = countExecRes.data?.[0]?.total || 0;
|
|
14249
14629
|
if (total === 0) {
|
|
14250
14630
|
return {
|
|
@@ -14267,7 +14647,7 @@ class DbHelper {
|
|
|
14267
14647
|
dataBuilder.orderBy(prepared.orderBy);
|
|
14268
14648
|
}
|
|
14269
14649
|
const { sql: dataSql, params: dataParams } = dataBuilder.toSelectSql();
|
|
14270
|
-
const dataExecRes = await this.
|
|
14650
|
+
const dataExecRes = await this.executeSelect(dataSql, dataParams);
|
|
14271
14651
|
const list = dataExecRes.data || [];
|
|
14272
14652
|
const camelList = arrayKeysToCamel(list);
|
|
14273
14653
|
const deserializedList = camelList.map((item) => DbUtils.deserializeArrayFields(item)).filter((item) => item !== null);
|
|
@@ -14306,7 +14686,7 @@ class DbHelper {
|
|
|
14306
14686
|
const countBuilder = this.createSqlBuilder().selectRaw("COUNT(*) as total").from(prepared.table).where(whereFiltered);
|
|
14307
14687
|
this.applyJoins(countBuilder, prepared.joins);
|
|
14308
14688
|
const { sql: countSql, params: countParams } = countBuilder.toSelectSql();
|
|
14309
|
-
const countExecRes = await this.
|
|
14689
|
+
const countExecRes = await this.executeSelect(countSql, countParams);
|
|
14310
14690
|
const total = countExecRes.data?.[0]?.total || 0;
|
|
14311
14691
|
if (total === 0) {
|
|
14312
14692
|
return {
|
|
@@ -14325,7 +14705,7 @@ class DbHelper {
|
|
|
14325
14705
|
dataBuilder.orderBy(prepared.orderBy);
|
|
14326
14706
|
}
|
|
14327
14707
|
const { sql: dataSql, params: dataParams } = dataBuilder.toSelectSql();
|
|
14328
|
-
const dataExecRes = await this.
|
|
14708
|
+
const dataExecRes = await this.executeSelect(dataSql, dataParams);
|
|
14329
14709
|
const result = dataExecRes.data || [];
|
|
14330
14710
|
if (result.length >= WARNING_LIMIT) {
|
|
14331
14711
|
Logger.warn({ table: options.table, count: result.length, total, msg: "getAll \u8FD4\u56DE\u6570\u636E\u8FC7\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528 getList \u5206\u9875\u67E5\u8BE2" });
|
|
@@ -14361,8 +14741,11 @@ class DbHelper {
|
|
|
14361
14741
|
SqlCheck.assertNoUndefinedInRecord(processed, `insData \u63D2\u5165\u6570\u636E (table: ${snakeTable})`);
|
|
14362
14742
|
const builder = this.createSqlBuilder();
|
|
14363
14743
|
const { sql, params } = builder.toInsertSql(snakeTable, processed);
|
|
14364
|
-
const execRes = await this.
|
|
14365
|
-
const
|
|
14744
|
+
const execRes = await this.executeRun(sql, params);
|
|
14745
|
+
const processedId = processed["id"];
|
|
14746
|
+
const processedIdNum = typeof processedId === "number" ? processedId : 0;
|
|
14747
|
+
const lastInsertRowidNum = toNumberFromSql(execRes.data?.lastInsertRowid);
|
|
14748
|
+
const insertedId = processedIdNum || lastInsertRowidNum || 0;
|
|
14366
14749
|
return {
|
|
14367
14750
|
data: insertedId,
|
|
14368
14751
|
sql: execRes.sql
|
|
@@ -14397,7 +14780,7 @@ class DbHelper {
|
|
|
14397
14780
|
const builder = this.createSqlBuilder();
|
|
14398
14781
|
const { sql, params } = builder.toInsertSql(snakeTable, processedList);
|
|
14399
14782
|
try {
|
|
14400
|
-
const execRes = await this.
|
|
14783
|
+
const execRes = await this.executeRun(sql, params);
|
|
14401
14784
|
return {
|
|
14402
14785
|
data: ids,
|
|
14403
14786
|
sql: execRes.sql
|
|
@@ -14429,8 +14812,8 @@ class DbHelper {
|
|
|
14429
14812
|
ids,
|
|
14430
14813
|
quoteIdent: this.dialect.quoteIdent.bind(this.dialect)
|
|
14431
14814
|
});
|
|
14432
|
-
const execRes = await this.
|
|
14433
|
-
const changes = execRes.data?.changes
|
|
14815
|
+
const execRes = await this.executeRun(query.sql, query.params);
|
|
14816
|
+
const changes = toNumberFromSql(execRes.data?.changes);
|
|
14434
14817
|
return {
|
|
14435
14818
|
data: changes,
|
|
14436
14819
|
sql: execRes.sql
|
|
@@ -14474,8 +14857,8 @@ class DbHelper {
|
|
|
14474
14857
|
stateField: "state",
|
|
14475
14858
|
stateGtZero: true
|
|
14476
14859
|
});
|
|
14477
|
-
const execRes = await this.
|
|
14478
|
-
const changes = execRes.data?.changes
|
|
14860
|
+
const execRes = await this.executeRun(query.sql, query.params);
|
|
14861
|
+
const changes = toNumberFromSql(execRes.data?.changes);
|
|
14479
14862
|
return {
|
|
14480
14863
|
data: changes,
|
|
14481
14864
|
sql: execRes.sql
|
|
@@ -14490,8 +14873,8 @@ class DbHelper {
|
|
|
14490
14873
|
const whereFiltered = DbUtils.addDefaultStateFilter(snakeWhere, snakeTable, false);
|
|
14491
14874
|
const builder = this.createSqlBuilder().where(whereFiltered);
|
|
14492
14875
|
const { sql, params } = builder.toUpdateSql(snakeTable, processed);
|
|
14493
|
-
const execRes = await this.
|
|
14494
|
-
const changes = execRes.data?.changes
|
|
14876
|
+
const execRes = await this.executeRun(sql, params);
|
|
14877
|
+
const changes = toNumberFromSql(execRes.data?.changes);
|
|
14495
14878
|
return {
|
|
14496
14879
|
data: changes,
|
|
14497
14880
|
sql: execRes.sql
|
|
@@ -14512,8 +14895,8 @@ class DbHelper {
|
|
|
14512
14895
|
const snakeWhere = DbUtils.whereKeysToSnake(cleanWhere);
|
|
14513
14896
|
const builder = this.createSqlBuilder().where(snakeWhere);
|
|
14514
14897
|
const { sql, params } = builder.toDeleteSql(snakeTable);
|
|
14515
|
-
const execRes = await this.
|
|
14516
|
-
const changes = execRes.data?.changes
|
|
14898
|
+
const execRes = await this.executeRun(sql, params);
|
|
14899
|
+
const changes = toNumberFromSql(execRes.data?.changes);
|
|
14517
14900
|
return {
|
|
14518
14901
|
data: changes,
|
|
14519
14902
|
sql: execRes.sql
|
|
@@ -14543,7 +14926,14 @@ class DbHelper {
|
|
|
14543
14926
|
if (this.isTransaction) {
|
|
14544
14927
|
return await callback(this);
|
|
14545
14928
|
}
|
|
14546
|
-
|
|
14929
|
+
const sql = this.sql;
|
|
14930
|
+
if (!sql) {
|
|
14931
|
+
throw new Error("\u6570\u636E\u5E93\u8FDE\u63A5\u672A\u521D\u59CB\u5316");
|
|
14932
|
+
}
|
|
14933
|
+
if (!hasBegin(sql)) {
|
|
14934
|
+
throw new Error("\u5F53\u524D SQL \u5BA2\u6237\u7AEF\u4E0D\u652F\u6301\u4E8B\u52A1 begin() \u65B9\u6CD5");
|
|
14935
|
+
}
|
|
14936
|
+
return await sql.begin(async (tx) => {
|
|
14547
14937
|
const trans = new DbHelper({ redis: this.redis, sql: tx, dialect: this.dialect });
|
|
14548
14938
|
return await callback(trans);
|
|
14549
14939
|
});
|
|
@@ -14552,10 +14942,19 @@ class DbHelper {
|
|
|
14552
14942
|
return await this.executeWithConn(sql, params);
|
|
14553
14943
|
}
|
|
14554
14944
|
async exists(options) {
|
|
14555
|
-
const
|
|
14945
|
+
const prepareOptions = {
|
|
14946
|
+
table: options.table,
|
|
14947
|
+
page: 1,
|
|
14948
|
+
limit: 1
|
|
14949
|
+
};
|
|
14950
|
+
if (options.where !== undefined)
|
|
14951
|
+
prepareOptions.where = options.where;
|
|
14952
|
+
if (options.joins !== undefined)
|
|
14953
|
+
prepareOptions.joins = options.joins;
|
|
14954
|
+
const { table, where, tableQualifier } = await this.prepareQueryOptions(prepareOptions);
|
|
14556
14955
|
const builder = this.createSqlBuilder().selectRaw("COUNT(1) as cnt").from(table).where(DbUtils.addDefaultStateFilter(where, tableQualifier, false)).limit(1);
|
|
14557
14956
|
const { sql, params } = builder.toSelectSql();
|
|
14558
|
-
const execRes = await this.
|
|
14957
|
+
const execRes = await this.executeSelect(sql, params);
|
|
14559
14958
|
const exists = (execRes.data?.[0]?.cnt || 0) > 0;
|
|
14560
14959
|
return {
|
|
14561
14960
|
data: exists,
|
|
@@ -14583,6 +14982,12 @@ class DbHelper {
|
|
|
14583
14982
|
oneOptions.fields = [field];
|
|
14584
14983
|
const oneRes = await this.getOne(oneOptions);
|
|
14585
14984
|
const result = oneRes.data;
|
|
14985
|
+
if (!isPlainObject(result)) {
|
|
14986
|
+
return {
|
|
14987
|
+
data: null,
|
|
14988
|
+
sql: oneRes.sql
|
|
14989
|
+
};
|
|
14990
|
+
}
|
|
14586
14991
|
if (Object.hasOwn(result, field)) {
|
|
14587
14992
|
return {
|
|
14588
14993
|
data: result[field],
|
|
@@ -14628,8 +15033,8 @@ class DbHelper {
|
|
|
14628
15033
|
const quotedTable = this.dialect.quoteIdent(snakeTable);
|
|
14629
15034
|
const quotedField = this.dialect.quoteIdent(snakeField);
|
|
14630
15035
|
const sql = whereClause ? `UPDATE ${quotedTable} SET ${quotedField} = ${quotedField} + ? WHERE ${whereClause}` : `UPDATE ${quotedTable} SET ${quotedField} = ${quotedField} + ?`;
|
|
14631
|
-
const execRes = await this.
|
|
14632
|
-
const changes = execRes.data?.changes
|
|
15036
|
+
const execRes = await this.executeRun(sql, [value, ...whereParams]);
|
|
15037
|
+
const changes = toNumberFromSql(execRes.data?.changes);
|
|
14633
15038
|
return {
|
|
14634
15039
|
data: changes,
|
|
14635
15040
|
sql: execRes.sql
|
|
@@ -15211,9 +15616,12 @@ var tool_default = toolPlugin;
|
|
|
15211
15616
|
// utils/scanCoreBuiltins.ts
|
|
15212
15617
|
init_util();
|
|
15213
15618
|
function toCoreBuiltinScanFileResult(type, item) {
|
|
15214
|
-
const
|
|
15619
|
+
const record = isPlainObject(item) ? item : {};
|
|
15620
|
+
const name = typeof record["name"] === "string" ? String(record["name"]) : "";
|
|
15215
15621
|
const customKeys = isPlainObject(item) ? Object.keys(item) : [];
|
|
15216
|
-
|
|
15622
|
+
const depsRaw = record["deps"];
|
|
15623
|
+
const deps = Array.isArray(depsRaw) ? depsRaw.filter((x) => typeof x === "string") : [];
|
|
15624
|
+
const out = {
|
|
15217
15625
|
source: "core",
|
|
15218
15626
|
type,
|
|
15219
15627
|
sourceName: "\u6838\u5FC3",
|
|
@@ -15225,11 +15633,12 @@ function toCoreBuiltinScanFileResult(type, item) {
|
|
|
15225
15633
|
fileBaseName: name,
|
|
15226
15634
|
fileDir: "(builtin)",
|
|
15227
15635
|
name,
|
|
15228
|
-
enable:
|
|
15229
|
-
deps
|
|
15230
|
-
handler:
|
|
15636
|
+
enable: record["enable"],
|
|
15637
|
+
deps,
|
|
15638
|
+
handler: record["handler"] ?? null,
|
|
15231
15639
|
customKeys
|
|
15232
15640
|
};
|
|
15641
|
+
return out;
|
|
15233
15642
|
}
|
|
15234
15643
|
function scanCoreBuiltinPlugins() {
|
|
15235
15644
|
const plugins = [];
|
|
@@ -15344,7 +15753,7 @@ async function scanFiles(dir, source, type, pattern) {
|
|
|
15344
15753
|
customKeys: isPlainObject(content) ? Object.keys(content) : []
|
|
15345
15754
|
};
|
|
15346
15755
|
if (type === "table") {
|
|
15347
|
-
base["content"] = content;
|
|
15756
|
+
base["content"] = isPlainObject(content) ? content : {};
|
|
15348
15757
|
results.push(base);
|
|
15349
15758
|
continue;
|
|
15350
15759
|
}
|