befly 3.15.8 → 3.15.9

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 CHANGED
@@ -8246,7 +8246,7 @@ function formatValuePreview(value) {
8246
8246
  }
8247
8247
  var RESERVED_FIELDS = ["id", "created_at", "updated_at", "deleted_at", "state"];
8248
8248
  var RESERVED_FIELD_SET = new Set(RESERVED_FIELDS);
8249
- var FIELD_TYPES = ["string", "number", "text", "array_string", "array_text", "array_number_string", "array_number_text"];
8249
+ var FIELD_TYPES = ["string", "number", "text", "datetime", "array_string", "array_text", "array_number_string", "array_number_text"];
8250
8250
  var FIELD_TYPE_SET = new Set(FIELD_TYPES);
8251
8251
  var ALLOWED_FIELD_PROPERTIES = ["name", "type", "min", "max", "default", "detail", "index", "unique", "nullable", "unsigned", "regexp"];
8252
8252
  var ALLOWED_FIELD_PROPERTY_SET = new Set(ALLOWED_FIELD_PROPERTIES);
@@ -8389,6 +8389,23 @@ async function checkTable(tables, config2) {
8389
8389
  Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A ${field.type} \u7C7B\u578B\uFF0C\u4E0D\u652F\u6301\u552F\u4E00\u7EA6\u675F\uFF08unique=true \u65E0\u6548\uFF09`);
8390
8390
  hasError = true;
8391
8391
  }
8392
+ } else if (field.type === "datetime") {
8393
+ if (field.min !== undefined && field.min !== null) {
8394
+ Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A datetime \u7C7B\u578B\uFF0Cmin \u5FC5\u987B\u4E3A null\uFF0C\u5F53\u524D\u4E3A "${field.min}"`);
8395
+ hasError = true;
8396
+ }
8397
+ if (field.max !== undefined && field.max !== null) {
8398
+ Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A datetime \u7C7B\u578B\uFF0Cmax \u5FC5\u987B\u4E3A null\uFF0C\u5F53\u524D\u4E3A "${field.max}"`);
8399
+ hasError = true;
8400
+ }
8401
+ if (field.default !== undefined && field.default !== null) {
8402
+ Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A datetime \u7C7B\u578B\uFF0C\u9ED8\u8BA4\u503C\u5FC5\u987B\u4E3A null\uFF08\u5982\u9700\u5F53\u524D\u65F6\u95F4\uFF0C\u8BF7\u5728\u4E1A\u52A1\u5199\u5165\u65F6\u8D4B\u503C\uFF09\u3002\u5F53\u524D\u4E3A ${formatValuePreview(field.default)}`);
8403
+ hasError = true;
8404
+ }
8405
+ if (field.unsigned !== undefined) {
8406
+ Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A datetime \u7C7B\u578B\uFF0C\u4E0D\u5141\u8BB8\u8BBE\u7F6E unsigned`);
8407
+ hasError = true;
8408
+ }
8392
8409
  } else if (field.type === "string" || field.type === "array_string" || field.type === "array_number_string") {
8393
8410
  if (field.max === undefined || field.max === null || typeof field.max !== "number") {
8394
8411
  Logger.warn(`${tablePrefix}${fileName} \u6587\u4EF6 ${colKey} \u4E3A ${field.type} \u7C7B\u578B\uFF0C` + `\u5FC5\u987B\u8BBE\u7F6E max \u4E14\u7C7B\u578B\u4E3A\u6570\u5B57\uFF1B\u5176\u4E2D array_*_string \u7684 max \u8868\u793A\u5355\u4E2A\u5143\u7D20\u957F\u5EA6\uFF0C\u5F53\u524D\u4E3A "${field.max}"`);
@@ -10025,6 +10042,7 @@ class SyncTable {
10025
10042
  return {
10026
10043
  number: "BIGINT",
10027
10044
  string: "VARCHAR",
10045
+ datetime: "DATETIME",
10028
10046
  text: "MEDIUMTEXT",
10029
10047
  array_string: "VARCHAR",
10030
10048
  array_text: "MEDIUMTEXT",
@@ -10080,6 +10098,8 @@ class SyncTable {
10080
10098
  return 0;
10081
10099
  case "string":
10082
10100
  return "";
10101
+ case "datetime":
10102
+ return "null";
10083
10103
  case "array_string":
10084
10104
  case "array_number_string":
10085
10105
  return "[]";
@@ -10103,6 +10123,18 @@ class SyncTable {
10103
10123
  return ` DEFAULT '${escaped}'`;
10104
10124
  }
10105
10125
  }
10126
+ if (fieldType === "datetime") {
10127
+ if (typeof actualDefault === "string") {
10128
+ const trimmed = actualDefault.trim();
10129
+ if (/^current_timestamp(\(\s*\d+\s*\)|\(\s*\))?$/i.test(trimmed)) {
10130
+ const normalized = trimmed.toUpperCase().replace(/\(\s*\)/g, "");
10131
+ return ` DEFAULT ${normalized}`;
10132
+ }
10133
+ const escaped = trimmed.replace(/'/g, "''");
10134
+ return ` DEFAULT '${escaped}'`;
10135
+ }
10136
+ return "";
10137
+ }
10106
10138
  return "";
10107
10139
  }
10108
10140
  static buildIndexClause(indexName, fieldName, action) {
@@ -10235,6 +10267,9 @@ class SyncTable {
10235
10267
  if (cBase === "char" && nBase === "varchar" || cBase === "varchar" && nBase === "char") {
10236
10268
  return true;
10237
10269
  }
10270
+ if (cBase === "datetime" && nBase === "bigint" || cBase === "bigint" && nBase === "datetime") {
10271
+ return false;
10272
+ }
10238
10273
  return false;
10239
10274
  }
10240
10275
  static compareFieldDefinition(existingColumn, fieldDef) {
@@ -10461,7 +10496,12 @@ class SyncTable {
10461
10496
  const typeMapping = SyncTable.getTypeMapping();
10462
10497
  const expectedType = typeMapping[fieldDef.type]?.toLowerCase() || "";
10463
10498
  if (!SyncTable.isCompatibleTypeChange(currentType, expectedType)) {
10464
- const errorMsg = [`\u7981\u6B62\u5B57\u6BB5\u7C7B\u578B\u53D8\u66F4: ${tableName}.${dbFieldName}`, `\u5F53\u524D\u7C7B\u578B: ${typeChange?.current}`, `\u76EE\u6807\u7C7B\u578B: ${typeChange?.expected}`, "\u8BF4\u660E: \u4EC5\u5141\u8BB8\u5BBD\u5316\u578B\u53D8\u66F4\uFF08\u5982 INT->BIGINT, VARCHAR->TEXT\uFF09\uFF0C\u4EE5\u53CA CHAR/VARCHAR \u4E92\u8F6C\uFF1B\u5176\u4ED6\u7C7B\u578B\u53D8\u66F4\u9700\u8981\u624B\u52A8\u5904\u7406"].join(`
10499
+ const errorMsg = [
10500
+ `\u7981\u6B62\u5B57\u6BB5\u7C7B\u578B\u53D8\u66F4: ${tableName}.${dbFieldName}`,
10501
+ `\u5F53\u524D\u7C7B\u578B: ${typeChange?.current}`,
10502
+ `\u76EE\u6807\u7C7B\u578B: ${typeChange?.expected}`,
10503
+ "\u8BF4\u660E: \u4EC5\u5141\u8BB8\u5BBD\u5316\u578B\u53D8\u66F4\uFF08\u5982 INT->BIGINT, VARCHAR->TEXT\uFF09\uFF0C\u4EE5\u53CA CHAR/VARCHAR \u4E92\u8F6C\uFF1BDATETIME \u4E0E BIGINT \u4E0D\u5141\u8BB8\u4E92\u8F6C\uFF08\u9700\u8981\u624B\u52A8\u8FC1\u79FB\u6570\u636E\uFF09"
10504
+ ].join(`
10465
10505
  `);
10466
10506
  throw new Error(errorMsg);
10467
10507
  }
@@ -12485,6 +12525,15 @@ class Validator {
12485
12525
  case "string":
12486
12526
  case "text":
12487
12527
  return typeof value === "string" ? { value, error: null } : { value: null, error: "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32" };
12528
+ case "datetime":
12529
+ if (typeof value !== "string") {
12530
+ return { value: null, error: "\u5FC5\u987B\u662F\u65F6\u95F4\u5B57\u7B26\u4E32" };
12531
+ }
12532
+ const trimmed = value.trim();
12533
+ if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
12534
+ return { value: `${trimmed} 00:00:00`, error: null };
12535
+ }
12536
+ return { value: trimmed, error: null };
12488
12537
  case "array_string":
12489
12538
  case "array_text":
12490
12539
  return Array.isArray(value) ? { value, error: null } : { value: null, error: "\u5FC5\u987B\u662F\u6570\u7EC4" };
@@ -12532,6 +12581,43 @@ class Validator {
12532
12581
  if (regex && !this.testRegex(regex, value))
12533
12582
  return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12534
12583
  break;
12584
+ case "datetime": {
12585
+ if (typeof value !== "string")
12586
+ return "\u5FC5\u987B\u662F\u65F6\u95F4\u5B57\u7B26\u4E32";
12587
+ if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(value))
12588
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12589
+ const [datePart, timePart] = value.split(" ");
12590
+ if (typeof datePart !== "string" || typeof timePart !== "string")
12591
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12592
+ const [yStr, mStr, dStr] = datePart.split("-");
12593
+ const [hhStr, mmStr, ssStr] = timePart.split(":");
12594
+ const year = Number(yStr);
12595
+ const month = Number(mStr);
12596
+ const day = Number(dStr);
12597
+ const hh = Number(hhStr);
12598
+ const mm = Number(mmStr);
12599
+ const ss = Number(ssStr);
12600
+ if (!Number.isInteger(year) || year < 1000 || year > 9999)
12601
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12602
+ if (!Number.isInteger(month) || month < 1 || month > 12)
12603
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12604
+ if (!Number.isInteger(day) || day < 1)
12605
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12606
+ if (!Number.isInteger(hh) || hh < 0 || hh > 23)
12607
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12608
+ if (!Number.isInteger(mm) || mm < 0 || mm > 59)
12609
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12610
+ if (!Number.isInteger(ss) || ss < 0 || ss > 59)
12611
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12612
+ const isLeap = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
12613
+ const daysInMonth = [31, isLeap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
12614
+ const maxDay = daysInMonth[month - 1] ?? 0;
12615
+ if (day > maxDay)
12616
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12617
+ if (regex && !this.testRegex(regex, value))
12618
+ return "\u683C\u5F0F\u4E0D\u6B63\u786E";
12619
+ break;
12620
+ }
12535
12621
  case "array_string":
12536
12622
  case "array_text":
12537
12623
  case "array_number_string":
@@ -12589,6 +12675,8 @@ class Validator {
12589
12675
  switch (type.toLowerCase()) {
12590
12676
  case "number":
12591
12677
  return 0;
12678
+ case "datetime":
12679
+ return null;
12592
12680
  case "array_string":
12593
12681
  case "array_text":
12594
12682
  case "array_number_string":