befly 3.15.17 → 3.15.18
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 +293 -145
- package/dist/befly.min.js +13 -13
- package/dist/checks/checkTable.js +67 -81
- package/dist/configs/presetRegexp.js +19 -3
- package/dist/lib/validator.js +21 -47
- package/dist/sync/syncTable.d.ts +2 -1
- package/dist/sync/syncTable.js +95 -16
- package/dist/types/validate.d.ts +11 -1
- package/dist/utils/normalizeFieldDefinition.d.ts +2 -0
- package/dist/utils/normalizeFieldDefinition.js +4 -0
- package/dist/utils/util.d.ts +77 -0
- package/dist/utils/util.js +181 -0
- package/package.json +2 -2
package/dist/befly.js
CHANGED
|
@@ -49,6 +49,84 @@ function isPlainObject(value) {
|
|
|
49
49
|
const proto = Object.getPrototypeOf(value);
|
|
50
50
|
return proto === Object.prototype || proto === null;
|
|
51
51
|
}
|
|
52
|
+
function isJsonPrimitive(value) {
|
|
53
|
+
if (value === null) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
57
|
+
}
|
|
58
|
+
function isJsonObject(value) {
|
|
59
|
+
if (!value || typeof value !== "object") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (value instanceof Date) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
function isJsonStructure(value) {
|
|
71
|
+
return Array.isArray(value) || isJsonObject(value);
|
|
72
|
+
}
|
|
73
|
+
function isJsonValue(value) {
|
|
74
|
+
if (isJsonPrimitive(value)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
for (const item of value) {
|
|
79
|
+
if (!isJsonValue(item)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (isJsonObject(value)) {
|
|
86
|
+
for (const v of Object.values(value)) {
|
|
87
|
+
if (v === undefined) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (!isJsonValue(v)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
function isFiniteNumber(value) {
|
|
99
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
100
|
+
}
|
|
101
|
+
function isIntegerNumber(value) {
|
|
102
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value);
|
|
103
|
+
}
|
|
104
|
+
function formatValuePreview(value) {
|
|
105
|
+
if (value === null) {
|
|
106
|
+
return "null";
|
|
107
|
+
}
|
|
108
|
+
if (value === undefined) {
|
|
109
|
+
return "undefined";
|
|
110
|
+
}
|
|
111
|
+
if (typeof value === "string") {
|
|
112
|
+
const s2 = value.length > 80 ? `${value.slice(0, 80)}...` : value;
|
|
113
|
+
return JSON.stringify(s2);
|
|
114
|
+
}
|
|
115
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
116
|
+
return String(value);
|
|
117
|
+
}
|
|
118
|
+
if (typeof value === "function") {
|
|
119
|
+
return "[Function]";
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const s2 = JSON.stringify(value);
|
|
123
|
+
if (typeof s2 === "string") {
|
|
124
|
+
return s2.length > 120 ? `${s2.slice(0, 120)}...` : s2;
|
|
125
|
+
}
|
|
126
|
+
} catch {}
|
|
127
|
+
const s = String(value);
|
|
128
|
+
return s.length > 120 ? `${s.slice(0, 120)}...` : s;
|
|
129
|
+
}
|
|
52
130
|
function getTypeTag(value) {
|
|
53
131
|
if (value === null)
|
|
54
132
|
return "null";
|
|
@@ -71,6 +149,38 @@ function getTypeTag(value) {
|
|
|
71
149
|
return "function";
|
|
72
150
|
return "object";
|
|
73
151
|
}
|
|
152
|
+
function isRegexLiteral(input) {
|
|
153
|
+
const trimmed = String(input || "").trim();
|
|
154
|
+
if (trimmed.length < 2) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (!trimmed.startsWith("/")) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
const lastSlash = trimmed.lastIndexOf("/");
|
|
161
|
+
if (lastSlash <= 0) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const flags = trimmed.slice(lastSlash + 1);
|
|
165
|
+
if (flags !== "" && !/^[gimsuy]+$/.test(flags)) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
function isRegexInput(input) {
|
|
171
|
+
const trimmed = String(input || "").trim();
|
|
172
|
+
return isRegexLiteral(trimmed) || trimmed.startsWith("@");
|
|
173
|
+
}
|
|
174
|
+
function isEnumInput(input) {
|
|
175
|
+
const trimmed = String(input || "").trim();
|
|
176
|
+
if (trimmed.length === 0) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
return !trimmed.startsWith("/") && trimmed.includes("|");
|
|
180
|
+
}
|
|
181
|
+
function isAliasInput(input) {
|
|
182
|
+
return String(input || "").trim().startsWith("@");
|
|
183
|
+
}
|
|
74
184
|
function normalizePositiveInt(value, fallback, min, max) {
|
|
75
185
|
if (typeof value !== "number")
|
|
76
186
|
return fallback;
|
|
@@ -8181,79 +8291,13 @@ async function checkPlugin(plugins) {
|
|
|
8181
8291
|
|
|
8182
8292
|
// checks/checkTable.ts
|
|
8183
8293
|
init_logger();
|
|
8184
|
-
|
|
8185
|
-
if (value === null)
|
|
8186
|
-
return true;
|
|
8187
|
-
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
8188
|
-
}
|
|
8189
|
-
function isJsonObject(value) {
|
|
8190
|
-
if (!value || typeof value !== "object")
|
|
8191
|
-
return false;
|
|
8192
|
-
if (value instanceof Date)
|
|
8193
|
-
return false;
|
|
8194
|
-
if (Array.isArray(value))
|
|
8195
|
-
return false;
|
|
8196
|
-
return true;
|
|
8197
|
-
}
|
|
8198
|
-
function isJsonValue(value) {
|
|
8199
|
-
if (isJsonPrimitive(value))
|
|
8200
|
-
return true;
|
|
8201
|
-
if (Array.isArray(value)) {
|
|
8202
|
-
for (const item of value) {
|
|
8203
|
-
if (!isJsonValue(item))
|
|
8204
|
-
return false;
|
|
8205
|
-
}
|
|
8206
|
-
return true;
|
|
8207
|
-
}
|
|
8208
|
-
if (isJsonObject(value)) {
|
|
8209
|
-
for (const v of Object.values(value)) {
|
|
8210
|
-
if (v === undefined)
|
|
8211
|
-
continue;
|
|
8212
|
-
if (!isJsonValue(v))
|
|
8213
|
-
return false;
|
|
8214
|
-
}
|
|
8215
|
-
return true;
|
|
8216
|
-
}
|
|
8217
|
-
return false;
|
|
8218
|
-
}
|
|
8219
|
-
function formatValuePreview(value) {
|
|
8220
|
-
if (value === null)
|
|
8221
|
-
return "null";
|
|
8222
|
-
if (value === undefined)
|
|
8223
|
-
return "undefined";
|
|
8224
|
-
if (typeof value === "string") {
|
|
8225
|
-
const s2 = value.length > 80 ? `${value.slice(0, 80)}...` : value;
|
|
8226
|
-
return JSON.stringify(s2);
|
|
8227
|
-
}
|
|
8228
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
8229
|
-
return String(value);
|
|
8230
|
-
}
|
|
8231
|
-
if (typeof value === "function") {
|
|
8232
|
-
return "[Function]";
|
|
8233
|
-
}
|
|
8234
|
-
try {
|
|
8235
|
-
const s2 = JSON.stringify(value);
|
|
8236
|
-
if (typeof s2 === "string") {
|
|
8237
|
-
return s2.length > 120 ? `${s2.slice(0, 120)}...` : s2;
|
|
8238
|
-
}
|
|
8239
|
-
} catch {}
|
|
8240
|
-
const s = String(value);
|
|
8241
|
-
return s.length > 120 ? `${s.slice(0, 120)}...` : s;
|
|
8242
|
-
}
|
|
8294
|
+
init_util();
|
|
8243
8295
|
var RESERVED_FIELDS = ["id", "created_at", "updated_at", "deleted_at", "state"];
|
|
8244
8296
|
var RESERVED_FIELD_SET = new Set(RESERVED_FIELDS);
|
|
8245
|
-
var FIELD_TYPES = ["tinyint", "smallint", "mediumint", "int", "bigint", "char", "varchar", "tinytext", "text", "mediumtext", "longtext", "datetime", "json"];
|
|
8297
|
+
var FIELD_TYPES = ["tinyint", "smallint", "mediumint", "int", "bigint", "decimal", "char", "varchar", "tinytext", "text", "mediumtext", "longtext", "datetime", "json"];
|
|
8246
8298
|
var FIELD_TYPE_SET = new Set(FIELD_TYPES);
|
|
8247
8299
|
var INPUT_TYPES = ["number", "integer", "string", "char", "array", "array_number", "array_integer", "json", "json_number", "json_integer"];
|
|
8248
8300
|
var INPUT_TYPE_SET = new Set(INPUT_TYPES);
|
|
8249
|
-
function isRegexInput(input) {
|
|
8250
|
-
if (input.startsWith("@"))
|
|
8251
|
-
return true;
|
|
8252
|
-
return /[\\^$.*+?()[\]{}]/.test(input);
|
|
8253
|
-
}
|
|
8254
|
-
function isEnumInput(input) {
|
|
8255
|
-
return input.includes("|") && !isRegexInput(input);
|
|
8256
|
-
}
|
|
8257
8301
|
function inferInputByType(dbType) {
|
|
8258
8302
|
switch (dbType.toLowerCase()) {
|
|
8259
8303
|
case "tinyint":
|
|
@@ -8262,6 +8306,8 @@ function inferInputByType(dbType) {
|
|
|
8262
8306
|
case "int":
|
|
8263
8307
|
case "bigint":
|
|
8264
8308
|
return "integer";
|
|
8309
|
+
case "decimal":
|
|
8310
|
+
return "number";
|
|
8265
8311
|
case "char":
|
|
8266
8312
|
case "varchar":
|
|
8267
8313
|
case "tinytext":
|
|
@@ -8285,7 +8331,7 @@ function normalizeTypeAndInput(type, input) {
|
|
|
8285
8331
|
input: rawInput || inferInputByType(rawType)
|
|
8286
8332
|
};
|
|
8287
8333
|
}
|
|
8288
|
-
var ALLOWED_FIELD_PROPERTIES = ["name", "type", "input", "min", "max", "default", "detail", "index", "unique", "nullable", "unsigned"];
|
|
8334
|
+
var ALLOWED_FIELD_PROPERTIES = ["name", "type", "input", "min", "max", "default", "detail", "precision", "scale", "index", "unique", "nullable", "unsigned"];
|
|
8289
8335
|
var ALLOWED_FIELD_PROPERTY_SET = new Set(ALLOWED_FIELD_PROPERTIES);
|
|
8290
8336
|
var LOWER_CAMEL_CASE_REGEX = /^_?[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/;
|
|
8291
8337
|
var FIELD_NAME_REGEX = /^[\u4e00-\u9fa5a-zA-Z0-9 _-]+$/;
|
|
@@ -8324,8 +8370,9 @@ async function checkTable(tables, config2) {
|
|
|
8324
8370
|
hasError = true;
|
|
8325
8371
|
continue;
|
|
8326
8372
|
}
|
|
8327
|
-
|
|
8328
|
-
|
|
8373
|
+
const dbFieldName = snakeCase(colKey);
|
|
8374
|
+
if (RESERVED_FIELD_SET.has(colKey) || RESERVED_FIELD_SET.has(dbFieldName)) {
|
|
8375
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6\u5305\u542B\u4FDD\u7559\u5B57\u6BB5 ${colKey}\uFF08\u6620\u5C04\u5217\u540D: ${dbFieldName}\uFF09\uFF0C` + `\u4E0D\u80FD\u5728\u8868\u5B9A\u4E49\u4E2D\u4F7F\u7528\u4EE5\u4E0B\u5B57\u6BB5: ${RESERVED_FIELDS.join(", ")}`);
|
|
8329
8376
|
hasError = true;
|
|
8330
8377
|
}
|
|
8331
8378
|
const field = fieldDef;
|
|
@@ -8361,6 +8408,14 @@ async function checkTable(tables, config2) {
|
|
|
8361
8408
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 detail \u7C7B\u578B\u9519\u8BEF\uFF0C\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32`);
|
|
8362
8409
|
hasError = true;
|
|
8363
8410
|
}
|
|
8411
|
+
if (field.precision !== undefined && !(field.precision === null || typeof field.precision === "number")) {
|
|
8412
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 precision \u7C7B\u578B\u9519\u8BEF\uFF0C\u5FC5\u987B\u4E3A null \u6216\u6570\u5B57`);
|
|
8413
|
+
hasError = true;
|
|
8414
|
+
}
|
|
8415
|
+
if (field.scale !== undefined && !(field.scale === null || typeof field.scale === "number")) {
|
|
8416
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 scale \u7C7B\u578B\u9519\u8BEF\uFF0C\u5FC5\u987B\u4E3A null \u6216\u6570\u5B57`);
|
|
8417
|
+
hasError = true;
|
|
8418
|
+
}
|
|
8364
8419
|
if (field.index !== undefined && typeof field.index !== "boolean") {
|
|
8365
8420
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 index \u7C7B\u578B\u9519\u8BEF\uFF0C\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C`);
|
|
8366
8421
|
hasError = true;
|
|
@@ -8398,25 +8453,31 @@ async function checkTable(tables, config2) {
|
|
|
8398
8453
|
if (normalizedInput === "") {
|
|
8399
8454
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input \u65E0\u6CD5\u63A8\u5BFC`);
|
|
8400
8455
|
hasError = true;
|
|
8401
|
-
} else if (!INPUT_TYPE_SET.has(normalizedInput) && !isRegexInput(normalizedInput) && !isEnumInput(normalizedInput)) {
|
|
8402
|
-
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input "${normalizedInput}" \u4E0D\u5408\u6CD5\uFF0C` + `\u5FC5\u987B\u4E3A${INPUT_TYPES.join("\u3001")}\u4E4B\u4E00\uFF0C\u6216\u6B63\u5219/\u679A\u4E3E`);
|
|
8456
|
+
} else if (!INPUT_TYPE_SET.has(normalizedInput) && !isRegexInput(normalizedInput) && !isEnumInput(normalizedInput) && !isAliasInput(normalizedInput)) {
|
|
8457
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input "${normalizedInput}" \u4E0D\u5408\u6CD5\uFF0C` + `\u5FC5\u987B\u4E3A${INPUT_TYPES.join("\u3001")}\u4E4B\u4E00\uFF0C\u6216\u6B63\u5219/\u679A\u4E3E/\u6B63\u5219\u522B\u540D`);
|
|
8403
8458
|
hasError = true;
|
|
8404
8459
|
}
|
|
8405
8460
|
const isStringDbType = ["char", "varchar", "tinytext", "text", "mediumtext", "longtext"].includes(effectiveType);
|
|
8406
8461
|
const isTextDbType = ["tinytext", "text", "mediumtext", "longtext"].includes(effectiveType);
|
|
8407
8462
|
const isIntDbType = ["tinyint", "smallint", "mediumint", "int", "bigint"].includes(effectiveType);
|
|
8463
|
+
const isDecimalDbType = effectiveType === "decimal";
|
|
8408
8464
|
const isJsonDbType = effectiveType === "json";
|
|
8409
|
-
|
|
8465
|
+
const isNumericDbType = isIntDbType || isDecimalDbType;
|
|
8466
|
+
if (isRegexInput(normalizedInput) || isEnumInput(normalizedInput) || isAliasInput(normalizedInput)) {
|
|
8410
8467
|
if (!isStringDbType) {
|
|
8411
|
-
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input \u4F7F\u7528\u6B63\u5219/\u679A\u4E3E\uFF0C\u4EC5\u5141\u8BB8\u5B57\u7B26\u4E32\u7C7B\u5B57\u6BB5\uFF08char/varchar/text\uFF09`);
|
|
8468
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input \u4F7F\u7528\u6B63\u5219/\u679A\u4E3E/\u6B63\u5219\u522B\u540D\uFF0C\u4EC5\u5141\u8BB8\u5B57\u7B26\u4E32\u7C7B\u5B57\u6BB5\uFF08char/varchar/text\uFF09`);
|
|
8412
8469
|
hasError = true;
|
|
8413
8470
|
}
|
|
8414
8471
|
}
|
|
8415
8472
|
if (normalizedInput === "number" || normalizedInput === "integer") {
|
|
8416
|
-
if (!isIntDbType) {
|
|
8473
|
+
if (normalizedInput === "integer" && !isIntDbType) {
|
|
8417
8474
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input=${normalizedInput} \u4EC5\u5141\u8BB8\u6574\u6570\u7C7B\u5B57\u6BB5\uFF08tinyint/smallint/mediumint/int/bigint\uFF09`);
|
|
8418
8475
|
hasError = true;
|
|
8419
8476
|
}
|
|
8477
|
+
if (normalizedInput === "number" && !isNumericDbType) {
|
|
8478
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5 input=${normalizedInput} \u4EC5\u5141\u8BB8\u6570\u503C\u7C7B\u5B57\u6BB5\uFF08tinyint/smallint/mediumint/int/bigint/decimal\uFF09`);
|
|
8479
|
+
hasError = true;
|
|
8480
|
+
}
|
|
8420
8481
|
}
|
|
8421
8482
|
if (normalizedInput === "array" || normalizedInput === "array_number" || normalizedInput === "array_integer") {
|
|
8422
8483
|
if (!isStringDbType) {
|
|
@@ -8430,8 +8491,8 @@ async function checkTable(tables, config2) {
|
|
|
8430
8491
|
hasError = true;
|
|
8431
8492
|
}
|
|
8432
8493
|
}
|
|
8433
|
-
if (!
|
|
8434
|
-
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5\u7C7B\u578B\u4E3A ${effectiveType}\uFF0C\u4E0D\u5141\u8BB8\u8BBE\u7F6E unsigned\uFF08\u4EC5\
|
|
8494
|
+
if (!isNumericDbType && field.unsigned !== undefined) {
|
|
8495
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u5B57\u6BB5\u7C7B\u578B\u4E3A ${effectiveType}\uFF0C\u4E0D\u5141\u8BB8\u8BBE\u7F6E unsigned\uFF08\u4EC5\u6570\u503C\u7C7B\u578B\u6709\u6548\uFF09`);
|
|
8435
8496
|
hasError = true;
|
|
8436
8497
|
}
|
|
8437
8498
|
if (field.unique === true && field.index === true) {
|
|
@@ -8482,6 +8543,31 @@ async function checkTable(tables, config2) {
|
|
|
8482
8543
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A datetime \u7C7B\u578B\uFF0C\u4E0D\u5141\u8BB8\u8BBE\u7F6E unsigned`);
|
|
8483
8544
|
hasError = true;
|
|
8484
8545
|
}
|
|
8546
|
+
} else if (isDecimalDbType) {
|
|
8547
|
+
const precision = field.precision;
|
|
8548
|
+
const scale = field.scale;
|
|
8549
|
+
if (typeof precision !== "number") {
|
|
8550
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0C\u5FC5\u987B\u8BBE\u7F6E precision\uFF08\u603B\u4F4D\u6570\uFF09`);
|
|
8551
|
+
hasError = true;
|
|
8552
|
+
} else if (precision < 1 || precision > 65) {
|
|
8553
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0Cprecision \u5FC5\u987B\u5728 1..65 \u8303\u56F4\u5185\uFF0C\u5F53\u524D\u4E3A ${precision}`);
|
|
8554
|
+
hasError = true;
|
|
8555
|
+
}
|
|
8556
|
+
if (typeof scale !== "number") {
|
|
8557
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0C\u5FC5\u987B\u8BBE\u7F6E scale\uFF08\u5C0F\u6570\u4F4D\u6570\uFF09`);
|
|
8558
|
+
hasError = true;
|
|
8559
|
+
} else if (scale < 0 || scale > 30) {
|
|
8560
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0Cscale \u5FC5\u987B\u5728 0..30 \u8303\u56F4\u5185\uFF0C\u5F53\u524D\u4E3A ${scale}`);
|
|
8561
|
+
hasError = true;
|
|
8562
|
+
}
|
|
8563
|
+
if (typeof precision === "number" && typeof scale === "number" && scale > precision) {
|
|
8564
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0Cscale \u4E0D\u80FD\u5927\u4E8E precision\uFF08precision=${precision}, scale=${scale}\uFF09`);
|
|
8565
|
+
hasError = true;
|
|
8566
|
+
}
|
|
8567
|
+
if (field.default !== undefined && field.default !== null && typeof field.default !== "number") {
|
|
8568
|
+
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A decimal \u7C7B\u578B\uFF0C\u9ED8\u8BA4\u503C\u5FC5\u987B\u4E3A\u6570\u5B57\u6216 null` + `\uFF08typeof=${typeof field.default}\uFF0Cvalue=${formatValuePreview(field.default)}\uFF09`);
|
|
8569
|
+
hasError = true;
|
|
8570
|
+
}
|
|
8485
8571
|
} else if (effectiveType === "char" || effectiveType === "varchar") {
|
|
8486
8572
|
if (field.max === undefined || field.max === null || typeof field.max !== "number") {
|
|
8487
8573
|
Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A ${effectiveType} \u7C7B\u578B\uFF0C` + `\u5FC5\u987B\u8BBE\u7F6E max \u4E14\u7C7B\u578B\u4E3A\u6570\u5B57\uFF0C\u5F53\u524D\u4E3A "${field.max}"`);
|
|
@@ -9900,6 +9986,8 @@ function inferInputByType2(dbType) {
|
|
|
9900
9986
|
case "int":
|
|
9901
9987
|
case "bigint":
|
|
9902
9988
|
return "integer";
|
|
9989
|
+
case "decimal":
|
|
9990
|
+
return "number";
|
|
9903
9991
|
case "char":
|
|
9904
9992
|
case "varchar":
|
|
9905
9993
|
case "tinytext":
|
|
@@ -9936,6 +10024,8 @@ function normalizeFieldDefinition(fieldDef) {
|
|
|
9936
10024
|
detail: fieldDef.detail ?? "",
|
|
9937
10025
|
min: fieldDef.min ?? null,
|
|
9938
10026
|
max: fieldDef.max ?? null,
|
|
10027
|
+
precision: fieldDef.precision ?? null,
|
|
10028
|
+
scale: fieldDef.scale ?? null,
|
|
9939
10029
|
default: normalizedDefault,
|
|
9940
10030
|
index: fieldDef.index ?? false,
|
|
9941
10031
|
unique: fieldDef.unique ?? false,
|
|
@@ -10093,6 +10183,7 @@ class SyncTable {
|
|
|
10093
10183
|
mediumint: "MEDIUMINT",
|
|
10094
10184
|
int: "INT",
|
|
10095
10185
|
bigint: "BIGINT",
|
|
10186
|
+
decimal: "DECIMAL",
|
|
10096
10187
|
char: "CHAR",
|
|
10097
10188
|
varchar: "VARCHAR",
|
|
10098
10189
|
datetime: "DATETIME",
|
|
@@ -10104,6 +10195,7 @@ class SyncTable {
|
|
|
10104
10195
|
};
|
|
10105
10196
|
static TEXT_FAMILY = new Set(["tinytext", "text", "mediumtext", "longtext"]);
|
|
10106
10197
|
static INT_TYPES = new Set(["tinyint", "smallint", "mediumint", "int", "bigint"]);
|
|
10198
|
+
static DECIMAL_TYPES = new Set(["decimal"]);
|
|
10107
10199
|
db;
|
|
10108
10200
|
dbName;
|
|
10109
10201
|
constructor(ctx) {
|
|
@@ -10187,6 +10279,8 @@ class SyncTable {
|
|
|
10187
10279
|
fieldDef.detail = normalized.detail;
|
|
10188
10280
|
fieldDef.min = normalized.min;
|
|
10189
10281
|
fieldDef.max = normalized.max;
|
|
10282
|
+
fieldDef.precision = normalized.precision;
|
|
10283
|
+
fieldDef.scale = normalized.scale;
|
|
10190
10284
|
fieldDef.default = normalized.default;
|
|
10191
10285
|
fieldDef.index = normalized.index;
|
|
10192
10286
|
fieldDef.unique = normalized.unique;
|
|
@@ -10207,7 +10301,7 @@ class SyncTable {
|
|
|
10207
10301
|
}
|
|
10208
10302
|
return `\`${trimmed}\``;
|
|
10209
10303
|
}
|
|
10210
|
-
static getSqlType(fieldType, fieldMax, unsigned = false) {
|
|
10304
|
+
static getSqlType(fieldType, fieldMax, unsigned = false, precision = null, scale = null) {
|
|
10211
10305
|
const normalizedType = String(fieldType || "").toLowerCase();
|
|
10212
10306
|
const typeMapping = SyncTable.TYPE_MAPPING;
|
|
10213
10307
|
if (SyncTable.isStringOrArrayType(normalizedType)) {
|
|
@@ -10216,6 +10310,13 @@ class SyncTable {
|
|
|
10216
10310
|
}
|
|
10217
10311
|
return `${typeMapping[normalizedType]}(${fieldMax})`;
|
|
10218
10312
|
}
|
|
10313
|
+
if (SyncTable.DECIMAL_TYPES.has(normalizedType)) {
|
|
10314
|
+
if (typeof precision !== "number" || typeof scale !== "number") {
|
|
10315
|
+
throw new Error(`\u540C\u6B65\u8868\uFF1A\u5185\u90E8\u9519\u8BEF\uFF1Adecimal \u7C7B\u578B\u7F3A\u5931 precision/scale\uFF08\u5E94\u7531 checkTable \u963B\u65AD\uFF09`);
|
|
10316
|
+
}
|
|
10317
|
+
const base = `${typeMapping[normalizedType]}(${precision},${scale})`;
|
|
10318
|
+
return unsigned ? `${base} UNSIGNED` : base;
|
|
10319
|
+
}
|
|
10219
10320
|
const baseType = typeMapping[normalizedType] || "TEXT";
|
|
10220
10321
|
if (SyncTable.INT_TYPES.has(normalizedType) && unsigned) {
|
|
10221
10322
|
return `${baseType} UNSIGNED`;
|
|
@@ -10233,6 +10334,7 @@ class SyncTable {
|
|
|
10233
10334
|
case "mediumint":
|
|
10234
10335
|
case "int":
|
|
10235
10336
|
case "bigint":
|
|
10337
|
+
case "decimal":
|
|
10236
10338
|
return 0;
|
|
10237
10339
|
case "char":
|
|
10238
10340
|
case "varchar":
|
|
@@ -10254,7 +10356,7 @@ class SyncTable {
|
|
|
10254
10356
|
if (SyncTable.TEXT_FAMILY.has(normalizedType) || normalizedType === "json" || actualDefault === "null") {
|
|
10255
10357
|
return "";
|
|
10256
10358
|
}
|
|
10257
|
-
if (SyncTable.INT_TYPES.has(normalizedType) || SyncTable.isStringOrArrayType(normalizedType)) {
|
|
10359
|
+
if (SyncTable.INT_TYPES.has(normalizedType) || SyncTable.DECIMAL_TYPES.has(normalizedType) || SyncTable.isStringOrArrayType(normalizedType)) {
|
|
10258
10360
|
if (typeof actualDefault === "number" && !Number.isNaN(actualDefault)) {
|
|
10259
10361
|
return ` DEFAULT ${actualDefault}`;
|
|
10260
10362
|
} else {
|
|
@@ -10276,10 +10378,31 @@ class SyncTable {
|
|
|
10276
10378
|
}
|
|
10277
10379
|
return "";
|
|
10278
10380
|
}
|
|
10279
|
-
static normalizeDefaultForCompare(value) {
|
|
10381
|
+
static normalizeDefaultForCompare(value, fieldType) {
|
|
10280
10382
|
if (value === null || value === undefined)
|
|
10281
10383
|
return "null";
|
|
10282
|
-
|
|
10384
|
+
const normalizedType = String(fieldType || "").toLowerCase();
|
|
10385
|
+
const raw = String(value).trim();
|
|
10386
|
+
if (SyncTable.INT_TYPES.has(normalizedType) || SyncTable.DECIMAL_TYPES.has(normalizedType)) {
|
|
10387
|
+
if (/^[+-]?\d+(?:\.\d+)?$/.test(raw)) {
|
|
10388
|
+
let sign = "";
|
|
10389
|
+
let body = raw;
|
|
10390
|
+
if (body.startsWith("+") || body.startsWith("-")) {
|
|
10391
|
+
sign = body.startsWith("-") ? "-" : "";
|
|
10392
|
+
body = body.slice(1);
|
|
10393
|
+
}
|
|
10394
|
+
const parts = body.split(".");
|
|
10395
|
+
const intPart = parts[0] || "0";
|
|
10396
|
+
const fracPart = parts[1] || "";
|
|
10397
|
+
const normalizedInt = intPart.replace(/^0+(\d)/, "$1");
|
|
10398
|
+
const normalizedFrac = fracPart.replace(/0+$/g, "");
|
|
10399
|
+
const mergedInt = normalizedInt === "" ? "0" : normalizedInt;
|
|
10400
|
+
const merged = normalizedFrac.length > 0 ? `${mergedInt}.${normalizedFrac}` : mergedInt;
|
|
10401
|
+
const normalized = sign === "-" && merged !== "0" ? `-${merged}` : merged;
|
|
10402
|
+
return normalized;
|
|
10403
|
+
}
|
|
10404
|
+
}
|
|
10405
|
+
return raw;
|
|
10283
10406
|
}
|
|
10284
10407
|
static buildIndexClause(indexName, fieldName, action) {
|
|
10285
10408
|
const indexQuoted = SyncTable.quoteIdentifier(indexName);
|
|
@@ -10337,7 +10460,7 @@ class SyncTable {
|
|
|
10337
10460
|
const normalized = normalizeFieldDefinition(fieldDef);
|
|
10338
10461
|
const dbFieldName = snakeCase(fieldKey);
|
|
10339
10462
|
const colQuoted = SyncTable.quoteIdentifier(dbFieldName);
|
|
10340
|
-
const sqlType = SyncTable.getSqlType(normalized.type, normalized.max, normalized.unsigned);
|
|
10463
|
+
const sqlType = SyncTable.getSqlType(normalized.type, normalized.max, normalized.unsigned, normalized.precision, normalized.scale);
|
|
10341
10464
|
const actualDefault = SyncTable.resolveDefaultValue(normalized.default, normalized.type);
|
|
10342
10465
|
const defaultSql = SyncTable.generateDefaultSql(actualDefault, normalized.type);
|
|
10343
10466
|
const uniqueSql = normalized.unique ? " UNIQUE" : "";
|
|
@@ -10381,6 +10504,10 @@ class SyncTable {
|
|
|
10381
10504
|
addedSystem,
|
|
10382
10505
|
modified,
|
|
10383
10506
|
indexChanges: indexActions.length
|
|
10507
|
+
},
|
|
10508
|
+
details: {
|
|
10509
|
+
fieldChanges: fieldPlan.changeDetails,
|
|
10510
|
+
indexChanges: indexPlan.indexActions
|
|
10384
10511
|
}
|
|
10385
10512
|
};
|
|
10386
10513
|
}
|
|
@@ -10388,12 +10515,14 @@ class SyncTable {
|
|
|
10388
10515
|
const alterClauses = [];
|
|
10389
10516
|
let addedBusiness = 0;
|
|
10390
10517
|
let modified = 0;
|
|
10518
|
+
const changeDetails = [];
|
|
10391
10519
|
for (const [fieldKey, fieldDef] of Object.entries(options.fields)) {
|
|
10392
10520
|
const dbFieldName = snakeCase(fieldKey);
|
|
10393
10521
|
if (options.existingColumns[dbFieldName]) {
|
|
10394
10522
|
const comparison = SyncTable.compareFieldDefinition(options.existingColumns[dbFieldName], fieldDef);
|
|
10395
10523
|
if (comparison.length > 0) {
|
|
10396
10524
|
modified = modified + 1;
|
|
10525
|
+
changeDetails.push({ fieldKey, dbFieldName, changes: comparison });
|
|
10397
10526
|
SyncTable.assertCompatibleTypeChange(options.tableName, dbFieldName, comparison, fieldDef);
|
|
10398
10527
|
alterClauses.push(SyncTable.generateDDLClause(fieldKey, fieldDef, false));
|
|
10399
10528
|
}
|
|
@@ -10402,7 +10531,7 @@ class SyncTable {
|
|
|
10402
10531
|
alterClauses.push(SyncTable.generateDDLClause(fieldKey, fieldDef, true));
|
|
10403
10532
|
}
|
|
10404
10533
|
}
|
|
10405
|
-
return { alterClauses, addedBusiness, modified };
|
|
10534
|
+
return { alterClauses, addedBusiness, modified, changeDetails };
|
|
10406
10535
|
}
|
|
10407
10536
|
static buildSystemFieldPlan(options) {
|
|
10408
10537
|
const alterClauses = [];
|
|
@@ -10443,7 +10572,7 @@ class SyncTable {
|
|
|
10443
10572
|
if (!typeChange)
|
|
10444
10573
|
return;
|
|
10445
10574
|
const currentType = String(typeChange.current || "").toLowerCase();
|
|
10446
|
-
const expectedType = SyncTable.getSqlType(fieldDef.type, fieldDef.max ?? null, fieldDef.unsigned ?? false).toLowerCase();
|
|
10575
|
+
const expectedType = SyncTable.getSqlType(fieldDef.type, fieldDef.max ?? null, fieldDef.unsigned ?? false, fieldDef.precision ?? null, fieldDef.scale ?? null).toLowerCase();
|
|
10447
10576
|
const currentBase = currentType.replace(/\s*unsigned/gi, "").replace(/\([^)]*\)/g, "").trim();
|
|
10448
10577
|
const expectedBase = expectedType.replace(/\s*unsigned/gi, "").replace(/\([^)]*\)/g, "").trim();
|
|
10449
10578
|
if (currentBase !== expectedBase && !SyncTable.isCompatibleTypeChange(currentType, expectedType))
|
|
@@ -10567,12 +10696,14 @@ SQL: ${sqlLine}
|
|
|
10567
10696
|
static compareFieldDefinition(existingColumn, fieldDef) {
|
|
10568
10697
|
const changes = [];
|
|
10569
10698
|
const normalized = normalizeFieldDefinition(fieldDef);
|
|
10570
|
-
const expectedType = SyncTable.getSqlType(normalized.type, normalized.max, normalized.unsigned).toLowerCase().replace(/\s+/g, " ").trim();
|
|
10699
|
+
const expectedType = SyncTable.getSqlType(normalized.type, normalized.max, normalized.unsigned, normalized.precision, normalized.scale).toLowerCase().replace(/\s+/g, " ").trim();
|
|
10571
10700
|
const currentType = (typeof existingColumn.columnType === "string" && existingColumn.columnType.trim() !== "" ? existingColumn.columnType : typeof existingColumn.type === "string" && existingColumn.type.trim() !== "" ? SyncTable.isStringOrArrayType(normalized.type) && typeof existingColumn.max === "number" ? `${existingColumn.type.trim()}(${existingColumn.max})` : existingColumn.type.trim() : String(existingColumn.type ?? "")).toLowerCase().replace(/\s+/g, " ").trim();
|
|
10572
|
-
|
|
10701
|
+
const currentBase = currentType.replace(/\s*unsigned/gi, "").replace(/\([^)]*\)/g, "").trim();
|
|
10702
|
+
const normalizedCurrentType = SyncTable.INT_TYPES.has(currentBase) ? currentType.replace(/\([^)]*\)/g, "").replace(/\s+/g, " ").trim() : currentType;
|
|
10703
|
+
if (normalizedCurrentType !== expectedType) {
|
|
10573
10704
|
changes.push({
|
|
10574
10705
|
type: "datatype",
|
|
10575
|
-
current:
|
|
10706
|
+
current: normalizedCurrentType,
|
|
10576
10707
|
expected: expectedType
|
|
10577
10708
|
});
|
|
10578
10709
|
}
|
|
@@ -10584,12 +10715,26 @@ SQL: ${sqlLine}
|
|
|
10584
10715
|
expected: expectedNullable
|
|
10585
10716
|
});
|
|
10586
10717
|
}
|
|
10587
|
-
const
|
|
10588
|
-
if (SyncTable.
|
|
10718
|
+
const normalizedType = String(normalized.type || "").toLowerCase();
|
|
10719
|
+
if (!SyncTable.TEXT_FAMILY.has(normalizedType) && normalizedType !== "json") {
|
|
10720
|
+
const expectedDefault = SyncTable.resolveDefaultValue(normalized.default, normalized.type);
|
|
10721
|
+
const currentDefaultNormalized = SyncTable.normalizeDefaultForCompare(existingColumn.defaultValue, normalized.type);
|
|
10722
|
+
const expectedDefaultNormalized = SyncTable.normalizeDefaultForCompare(expectedDefault, normalized.type);
|
|
10723
|
+
if (currentDefaultNormalized !== expectedDefaultNormalized) {
|
|
10724
|
+
changes.push({
|
|
10725
|
+
type: "default",
|
|
10726
|
+
current: existingColumn.defaultValue,
|
|
10727
|
+
expected: expectedDefault
|
|
10728
|
+
});
|
|
10729
|
+
}
|
|
10730
|
+
}
|
|
10731
|
+
const currentComment = String(existingColumn.comment ?? "");
|
|
10732
|
+
const expectedComment = String(normalized.name ?? "");
|
|
10733
|
+
if (currentComment !== expectedComment) {
|
|
10589
10734
|
changes.push({
|
|
10590
|
-
type: "
|
|
10591
|
-
current:
|
|
10592
|
-
expected:
|
|
10735
|
+
type: "comment",
|
|
10736
|
+
current: currentComment,
|
|
10737
|
+
expected: expectedComment
|
|
10593
10738
|
});
|
|
10594
10739
|
}
|
|
10595
10740
|
return changes;
|
|
@@ -10703,7 +10848,7 @@ SQL: ${sqlLine}
|
|
|
10703
10848
|
static async modifyTable(db, dbName, tableName, fields) {
|
|
10704
10849
|
const existingColumns = await SyncTable.getTableColumns(db, dbName, tableName);
|
|
10705
10850
|
const existingIndexes = await SyncTable.getTableIndexes(db, dbName, tableName);
|
|
10706
|
-
const { plan, summary } = SyncTable.buildTablePlan({
|
|
10851
|
+
const { plan, summary, details } = SyncTable.buildTablePlan({
|
|
10707
10852
|
tableName,
|
|
10708
10853
|
fields,
|
|
10709
10854
|
existingColumns,
|
|
@@ -10711,7 +10856,23 @@ SQL: ${sqlLine}
|
|
|
10711
10856
|
});
|
|
10712
10857
|
if (plan.changed) {
|
|
10713
10858
|
const msg = `[\u8868 ${tableName}] \u53D8\u66F4\u6C47\u603B\uFF0C\u65B0\u589E\u5B57\u6BB5=${summary.addedBusiness}\uFF0C\u65B0\u589E\u7CFB\u7EDF\u5B57\u6BB5=${summary.addedSystem}\uFF0C\u4FEE\u6539\u5B57\u6BB5=${summary.modified}\uFF0C\u7D22\u5F15\u53D8\u66F4=${summary.indexChanges}`;
|
|
10859
|
+
const detailLines = details.fieldChanges.flatMap((item) => item.changes.map((change) => {
|
|
10860
|
+
const current = String(change.current ?? "");
|
|
10861
|
+
const expected = String(change.expected ?? "");
|
|
10862
|
+
return `- ${item.dbFieldName}.${change.type}: ${current} -> ${expected}`;
|
|
10863
|
+
}));
|
|
10864
|
+
const indexLines = details.indexChanges.map((change) => {
|
|
10865
|
+
const indexLabel = `idx_${change.fieldName}` === change.indexName ? change.indexName : change.indexName;
|
|
10866
|
+
if (change.action === "create") {
|
|
10867
|
+
return `- index.${indexLabel}: \u65E0 -> ${change.indexName}(${change.fieldName})`;
|
|
10868
|
+
}
|
|
10869
|
+
return `- index.${indexLabel}: ${change.indexName}(${change.fieldName}) -> \u65E0`;
|
|
10870
|
+
});
|
|
10871
|
+
const allLines = [...detailLines, ...indexLines];
|
|
10714
10872
|
Logger.debug(msg);
|
|
10873
|
+
for (const line of allLines) {
|
|
10874
|
+
Logger.debug(`[\u8868 ${tableName}] \u53D8\u66F4\u660E\u7EC6 ${line}`);
|
|
10875
|
+
}
|
|
10715
10876
|
await SyncTable.applyTablePlan(db, tableName, plan);
|
|
10716
10877
|
}
|
|
10717
10878
|
return plan;
|
|
@@ -12473,12 +12634,28 @@ function getRegex(name) {
|
|
|
12473
12634
|
}
|
|
12474
12635
|
return name;
|
|
12475
12636
|
}
|
|
12637
|
+
function parseRegexLiteral(pattern) {
|
|
12638
|
+
const trimmed = String(pattern || "").trim();
|
|
12639
|
+
if (trimmed.length < 2)
|
|
12640
|
+
return null;
|
|
12641
|
+
if (!trimmed.startsWith("/"))
|
|
12642
|
+
return null;
|
|
12643
|
+
const lastSlash = trimmed.lastIndexOf("/");
|
|
12644
|
+
if (lastSlash <= 0)
|
|
12645
|
+
return null;
|
|
12646
|
+
const flags = trimmed.slice(lastSlash + 1);
|
|
12647
|
+
if (flags !== "" && !/^[gimsuy]+$/.test(flags))
|
|
12648
|
+
return null;
|
|
12649
|
+
return { source: trimmed.slice(1, lastSlash), flags };
|
|
12650
|
+
}
|
|
12476
12651
|
function getCompiledRegex(pattern, flags) {
|
|
12477
|
-
const
|
|
12478
|
-
const
|
|
12652
|
+
const literal = parseRegexLiteral(pattern);
|
|
12653
|
+
const regexStr = literal ? literal.source : getRegex(pattern);
|
|
12654
|
+
const useFlags = literal && literal.flags !== "" ? literal.flags : flags || "";
|
|
12655
|
+
const cacheKey = `${regexStr}:${useFlags}`;
|
|
12479
12656
|
let cached = regexCache.get(cacheKey);
|
|
12480
12657
|
if (!cached) {
|
|
12481
|
-
cached = new RegExp(regexStr,
|
|
12658
|
+
cached = new RegExp(regexStr, useFlags);
|
|
12482
12659
|
regexCache.set(cacheKey, cached);
|
|
12483
12660
|
}
|
|
12484
12661
|
return cached;
|
|
@@ -12487,39 +12664,8 @@ function getCompiledRegex(pattern, flags) {
|
|
|
12487
12664
|
// lib/validator.ts
|
|
12488
12665
|
init_util();
|
|
12489
12666
|
var INPUT_TYPE_SET2 = new Set(["number", "integer", "string", "char", "array", "array_number", "array_integer", "json", "json_number", "json_integer"]);
|
|
12490
|
-
function isRegexInput2(input) {
|
|
12491
|
-
if (input.startsWith("@"))
|
|
12492
|
-
return true;
|
|
12493
|
-
return /[\\^$.*+?()[\]{}]/.test(input);
|
|
12494
|
-
}
|
|
12495
|
-
function isEnumInput2(input) {
|
|
12496
|
-
return input.includes("|") && !isRegexInput2(input);
|
|
12497
|
-
}
|
|
12498
|
-
function isJsonPrimitive3(value) {
|
|
12499
|
-
if (value === null)
|
|
12500
|
-
return true;
|
|
12501
|
-
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
12502
|
-
}
|
|
12503
|
-
function isJsonObject3(value) {
|
|
12504
|
-
if (!value || typeof value !== "object")
|
|
12505
|
-
return false;
|
|
12506
|
-
if (value instanceof Date)
|
|
12507
|
-
return false;
|
|
12508
|
-
if (Array.isArray(value))
|
|
12509
|
-
return false;
|
|
12510
|
-
return true;
|
|
12511
|
-
}
|
|
12512
|
-
function isJsonStructure(value) {
|
|
12513
|
-
return Array.isArray(value) || isJsonObject3(value);
|
|
12514
|
-
}
|
|
12515
|
-
function isFiniteNumber(value) {
|
|
12516
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
12517
|
-
}
|
|
12518
|
-
function isIntegerNumber(value) {
|
|
12519
|
-
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value);
|
|
12520
|
-
}
|
|
12521
12667
|
function checkJsonLeaves(value, rule) {
|
|
12522
|
-
if (
|
|
12668
|
+
if (isJsonPrimitive(value)) {
|
|
12523
12669
|
if (rule === "number")
|
|
12524
12670
|
return isFiniteNumber(value);
|
|
12525
12671
|
return isIntegerNumber(value);
|
|
@@ -12531,7 +12677,7 @@ function checkJsonLeaves(value, rule) {
|
|
|
12531
12677
|
}
|
|
12532
12678
|
return true;
|
|
12533
12679
|
}
|
|
12534
|
-
if (
|
|
12680
|
+
if (isJsonObject(value)) {
|
|
12535
12681
|
for (const v of Object.values(value)) {
|
|
12536
12682
|
if (v === undefined)
|
|
12537
12683
|
continue;
|
|
@@ -12657,14 +12803,15 @@ class Validator {
|
|
|
12657
12803
|
return error ? `${label}${error}` : null;
|
|
12658
12804
|
}
|
|
12659
12805
|
static convert(value, input, dbType) {
|
|
12660
|
-
const
|
|
12661
|
-
|
|
12806
|
+
const inputRaw = String(input || "").trim();
|
|
12807
|
+
const inputKey = inputRaw.toLowerCase();
|
|
12808
|
+
if (!INPUT_TYPE_SET2.has(inputKey) && isRegexInput(inputRaw)) {
|
|
12662
12809
|
return typeof value === "string" ? { value, error: null } : { value: null, error: "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32" };
|
|
12663
12810
|
}
|
|
12664
|
-
if (!INPUT_TYPE_SET2.has(
|
|
12811
|
+
if (!INPUT_TYPE_SET2.has(inputKey) && isEnumInput(inputRaw)) {
|
|
12665
12812
|
return typeof value === "string" ? { value, error: null } : { value: null, error: "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32" };
|
|
12666
12813
|
}
|
|
12667
|
-
switch (
|
|
12814
|
+
switch (inputKey) {
|
|
12668
12815
|
case "number": {
|
|
12669
12816
|
if (isFiniteNumber(value))
|
|
12670
12817
|
return { value, error: null };
|
|
@@ -12749,43 +12896,44 @@ class Validator {
|
|
|
12749
12896
|
const input = normalized.input;
|
|
12750
12897
|
const min = normalized.min;
|
|
12751
12898
|
const max = normalized.max;
|
|
12752
|
-
const
|
|
12753
|
-
const
|
|
12754
|
-
const
|
|
12755
|
-
|
|
12899
|
+
const inputRaw = String(input || "").trim();
|
|
12900
|
+
const inputKey = inputRaw.toLowerCase();
|
|
12901
|
+
const isRegex = !INPUT_TYPE_SET2.has(inputKey) && isRegexInput(inputRaw);
|
|
12902
|
+
const isEnum = !INPUT_TYPE_SET2.has(inputKey) && isEnumInput(inputRaw);
|
|
12903
|
+
if (inputKey === "number" || inputKey === "integer") {
|
|
12756
12904
|
if (typeof value !== "number")
|
|
12757
|
-
return
|
|
12905
|
+
return inputKey === "integer" ? "\u5FC5\u987B\u662F\u6574\u6570" : "\u5FC5\u987B\u662F\u6570\u5B57";
|
|
12758
12906
|
if (min !== null && value < min)
|
|
12759
12907
|
return `\u4E0D\u80FD\u5C0F\u4E8E${min}`;
|
|
12760
12908
|
if (max !== null && max > 0 && value > max)
|
|
12761
12909
|
return `\u4E0D\u80FD\u5927\u4E8E${max}`;
|
|
12762
|
-
} else if (
|
|
12910
|
+
} else if (inputKey === "string" || inputKey === "char" || isRegex || isEnum) {
|
|
12763
12911
|
if (typeof value !== "string")
|
|
12764
12912
|
return "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32";
|
|
12765
|
-
if (
|
|
12913
|
+
if (inputKey === "char" && value.length !== 1)
|
|
12766
12914
|
return "\u5FC5\u987B\u662F\u5355\u5B57\u7B26";
|
|
12767
12915
|
if (min !== null && value.length < min)
|
|
12768
12916
|
return `\u957F\u5EA6\u4E0D\u80FD\u5C11\u4E8E${min}\u4E2A\u5B57\u7B26`;
|
|
12769
12917
|
if (max !== null && max > 0 && value.length > max)
|
|
12770
12918
|
return `\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7${max}\u4E2A\u5B57\u7B26`;
|
|
12771
12919
|
if (isRegex) {
|
|
12772
|
-
const regex = this.resolveRegex(
|
|
12920
|
+
const regex = this.resolveRegex(inputRaw);
|
|
12773
12921
|
if (!this.testRegex(regex, value))
|
|
12774
12922
|
return "\u683C\u5F0F\u4E0D\u6B63\u786E";
|
|
12775
12923
|
}
|
|
12776
12924
|
if (isEnum) {
|
|
12777
|
-
const enums =
|
|
12925
|
+
const enums = inputRaw.split("|").map((item) => item.trim()).filter((item) => item !== "");
|
|
12778
12926
|
if (!enums.includes(value))
|
|
12779
12927
|
return "\u503C\u4E0D\u5728\u679A\u4E3E\u8303\u56F4\u5185";
|
|
12780
12928
|
}
|
|
12781
|
-
} else if (
|
|
12929
|
+
} else if (inputKey === "array" || inputKey === "array_number" || inputKey === "array_integer") {
|
|
12782
12930
|
if (!Array.isArray(value))
|
|
12783
12931
|
return "\u5FC5\u987B\u662F\u6570\u7EC4";
|
|
12784
12932
|
if (min !== null && value.length < min)
|
|
12785
12933
|
return `\u81F3\u5C11\u9700\u8981${min}\u4E2A\u5143\u7D20`;
|
|
12786
12934
|
if (max !== null && max > 0 && value.length > max)
|
|
12787
12935
|
return `\u6700\u591A\u53EA\u80FD\u6709${max}\u4E2A\u5143\u7D20`;
|
|
12788
|
-
} else if (
|
|
12936
|
+
} else if (inputKey === "json" || inputKey === "json_number" || inputKey === "json_integer") {
|
|
12789
12937
|
if (!isJsonStructure(value))
|
|
12790
12938
|
return "\u5FC5\u987B\u662FJSON\u5BF9\u8C61\u6216\u6570\u7EC4";
|
|
12791
12939
|
}
|